libnl
3.2.3
|
00001 /* 00002 * lib/route/neigh.c Neighbours 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation version 2.1 00007 * of the License. 00008 * 00009 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 00010 */ 00011 00012 /** 00013 * @ingroup rtnl 00014 * @defgroup neigh Neighbours 00015 * @brief 00016 * 00017 * The neighbour table establishes bindings between protocol addresses and 00018 * link layer addresses for hosts sharing the same physical link. This 00019 * module allows you to access and manipulate the content of these tables. 00020 * 00021 * @par Neighbour States 00022 * @code 00023 * NUD_INCOMPLETE 00024 * NUD_REACHABLE 00025 * NUD_STALE 00026 * NUD_DELAY 00027 * NUD_PROBE 00028 * NUD_FAILED 00029 * NUD_NOARP 00030 * NUD_PERMANENT 00031 * @endcode 00032 * 00033 * @par Neighbour Flags 00034 * @code 00035 * NTF_USE 00036 * NTF_PROXY 00037 * NTF_ROUTER 00038 * @endcode 00039 * 00040 * @par Neighbour Identification 00041 * A neighbour is uniquely identified by the attributes listed below, whenever 00042 * you refer to an existing neighbour all of the attributes must be set. 00043 * Neighbours from caches automatically have all required attributes set. 00044 * - interface index (rtnl_neigh_set_ifindex()) 00045 * - destination address (rtnl_neigh_set_dst()) 00046 * 00047 * @par Changeable Attributes 00048 * \anchor neigh_changeable 00049 * - state (rtnl_neigh_set_state()) 00050 * - link layer address (rtnl_neigh_set_lladdr()) 00051 * 00052 * @par Required Caches for Dumping 00053 * In order to dump neighbour attributes you must provide the following 00054 * caches via nl_cache_provide() 00055 * - link cache holding all links 00056 * 00057 * @par TODO 00058 * - Document proxy settings 00059 * - Document states and their influence 00060 * 00061 * @par 1) Retrieving information about configured neighbours 00062 * @code 00063 * // The first step is to retrieve a list of all available neighbour within 00064 * // the kernel and put them into a cache. 00065 * struct nl_cache *cache = rtnl_neigh_alloc_cache(sk); 00066 * 00067 * // Neighbours can then be looked up by the interface and destination 00068 * // address: 00069 * struct rtnl_neigh *neigh = rtnl_neigh_get(cache, ifindex, dst_addr); 00070 * 00071 * // After successful usage, the object must be given back to the cache 00072 * rtnl_neigh_put(neigh); 00073 * @endcode 00074 * 00075 * @par 2) Adding new neighbours 00076 * @code 00077 * // Allocate an empty neighbour handle to be filled out with the attributes 00078 * // of the new neighbour. 00079 * struct rtnl_neigh *neigh = rtnl_neigh_alloc(); 00080 * 00081 * // Fill out the attributes of the new neighbour 00082 * rtnl_neigh_set_ifindex(neigh, ifindex); 00083 * rtnl_neigh_set_dst(neigh, dst_addr); 00084 * rtnl_neigh_set_state(neigh, rtnl_neigh_str2state("permanent")); 00085 * 00086 * // Build the netlink message and send it to the kernel, the operation will 00087 * // block until the operation has been completed. Alternatively the required 00088 * // netlink message can be built using rtnl_neigh_build_add_request() 00089 * // to be sent out using nl_send_auto_complete(). 00090 * rtnl_neigh_add(sk, neigh, NLM_F_CREATE); 00091 * 00092 * // Free the memory 00093 * rtnl_neigh_put(neigh); 00094 * @endcode 00095 * 00096 * @par 3) Deleting an existing neighbour 00097 * @code 00098 * // Allocate an empty neighbour object to be filled out with the attributes 00099 * // matching the neighbour to be deleted. Alternatively a fully equipped 00100 * // neighbour object out of a cache can be used instead. 00101 * struct rtnl_neigh *neigh = rtnl_neigh_alloc(); 00102 * 00103 * // Neighbours are uniquely identified by their interface index and 00104 * // destination address, you may fill out other attributes but they 00105 * // will have no influence. 00106 * rtnl_neigh_set_ifindex(neigh, ifindex); 00107 * rtnl_neigh_set_dst(neigh, dst_addr); 00108 * 00109 * // Build the netlink message and send it to the kernel, the operation will 00110 * // block until the operation has been completed. Alternatively the required 00111 * // netlink message can be built using rtnl_neigh_build_delete_request() 00112 * // to be sent out using nl_send_auto_complete(). 00113 * rtnl_neigh_delete(sk, neigh, 0); 00114 * 00115 * // Free the memory 00116 * rtnl_neigh_put(neigh); 00117 * @endcode 00118 * 00119 * @par 4) Changing neighbour attributes 00120 * @code 00121 * // Allocate an empty neighbour object to be filled out with the attributes 00122 * // matching the neighbour to be changed and the new parameters. Alternatively 00123 * // a fully equipped modified neighbour object out of a cache can be used. 00124 * struct rtnl_neigh *neigh = rtnl_neigh_alloc(); 00125 * 00126 * // Identify the neighbour to be changed by its interface index and 00127 * // destination address 00128 * rtnl_neigh_set_ifindex(neigh, ifindex); 00129 * rtnl_neigh_set_dst(neigh, dst_addr); 00130 * 00131 * // The link layer address may be modified, if so it is wise to change 00132 * // its state to "permanent" in order to avoid having it overwritten. 00133 * rtnl_neigh_set_lladdr(neigh, lladdr); 00134 * 00135 * // Secondly the state can be modified allowing normal neighbours to be 00136 * // converted into permanent entries or to manually confirm a neighbour. 00137 * rtnl_neigh_set_state(neigh, state); 00138 * 00139 * // Build the netlink message and send it to the kernel, the operation will 00140 * // block until the operation has been completed. Alternatively the required 00141 * // netlink message can be built using rtnl_neigh_build_change_request() 00142 * // to be sent out using nl_send_auto_complete(). 00143 * rtnl_neigh_add(sk, neigh, NLM_F_REPLACE); 00144 * 00145 * // Free the memory 00146 * rtnl_neigh_put(neigh); 00147 * @endcode 00148 * @{ 00149 */ 00150 00151 #include <netlink-local.h> 00152 #include <netlink/netlink.h> 00153 #include <netlink/utils.h> 00154 #include <netlink/route/rtnl.h> 00155 #include <netlink/route/neighbour.h> 00156 #include <netlink/route/link.h> 00157 00158 /** @cond SKIP */ 00159 #define NEIGH_ATTR_FLAGS 0x01 00160 #define NEIGH_ATTR_STATE 0x02 00161 #define NEIGH_ATTR_LLADDR 0x04 00162 #define NEIGH_ATTR_DST 0x08 00163 #define NEIGH_ATTR_CACHEINFO 0x10 00164 #define NEIGH_ATTR_IFINDEX 0x20 00165 #define NEIGH_ATTR_FAMILY 0x40 00166 #define NEIGH_ATTR_TYPE 0x80 00167 #define NEIGH_ATTR_PROBES 0x100 00168 00169 static struct nl_cache_ops rtnl_neigh_ops; 00170 static struct nl_object_ops neigh_obj_ops; 00171 /** @endcond */ 00172 00173 static void neigh_free_data(struct nl_object *c) 00174 { 00175 struct rtnl_neigh *neigh = nl_object_priv(c); 00176 00177 if (!neigh) 00178 return; 00179 00180 nl_addr_put(neigh->n_lladdr); 00181 nl_addr_put(neigh->n_dst); 00182 } 00183 00184 static int neigh_clone(struct nl_object *_dst, struct nl_object *_src) 00185 { 00186 struct rtnl_neigh *dst = nl_object_priv(_dst); 00187 struct rtnl_neigh *src = nl_object_priv(_src); 00188 00189 if (src->n_lladdr) 00190 if (!(dst->n_lladdr = nl_addr_clone(src->n_lladdr))) 00191 return -NLE_NOMEM; 00192 00193 if (src->n_dst) 00194 if (!(dst->n_dst = nl_addr_clone(src->n_dst))) 00195 return -NLE_NOMEM; 00196 00197 return 0; 00198 } 00199 00200 static int neigh_compare(struct nl_object *_a, struct nl_object *_b, 00201 uint32_t attrs, int flags) 00202 { 00203 struct rtnl_neigh *a = (struct rtnl_neigh *) _a; 00204 struct rtnl_neigh *b = (struct rtnl_neigh *) _b; 00205 int diff = 0; 00206 00207 #define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR) 00208 00209 diff |= NEIGH_DIFF(IFINDEX, a->n_ifindex != b->n_ifindex); 00210 diff |= NEIGH_DIFF(FAMILY, a->n_family != b->n_family); 00211 diff |= NEIGH_DIFF(TYPE, a->n_type != b->n_type); 00212 diff |= NEIGH_DIFF(LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr)); 00213 diff |= NEIGH_DIFF(DST, nl_addr_cmp(a->n_dst, b->n_dst)); 00214 00215 if (flags & LOOSE_COMPARISON) { 00216 diff |= NEIGH_DIFF(STATE, 00217 (a->n_state ^ b->n_state) & b->n_state_mask); 00218 diff |= NEIGH_DIFF(FLAGS, 00219 (a->n_flags ^ b->n_flags) & b->n_flag_mask); 00220 } else { 00221 diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state); 00222 diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags); 00223 } 00224 00225 #undef NEIGH_DIFF 00226 00227 return diff; 00228 } 00229 00230 static const struct trans_tbl neigh_attrs[] = { 00231 __ADD(NEIGH_ATTR_FLAGS, flags) 00232 __ADD(NEIGH_ATTR_STATE, state) 00233 __ADD(NEIGH_ATTR_LLADDR, lladdr) 00234 __ADD(NEIGH_ATTR_DST, dst) 00235 __ADD(NEIGH_ATTR_CACHEINFO, cacheinfo) 00236 __ADD(NEIGH_ATTR_IFINDEX, ifindex) 00237 __ADD(NEIGH_ATTR_FAMILY, family) 00238 __ADD(NEIGH_ATTR_TYPE, type) 00239 __ADD(NEIGH_ATTR_PROBES, probes) 00240 }; 00241 00242 static char *neigh_attrs2str(int attrs, char *buf, size_t len) 00243 { 00244 return __flags2str(attrs, buf, len, neigh_attrs, 00245 ARRAY_SIZE(neigh_attrs)); 00246 } 00247 00248 static struct nla_policy neigh_policy[NDA_MAX+1] = { 00249 [NDA_CACHEINFO] = { .minlen = sizeof(struct nda_cacheinfo) }, 00250 [NDA_PROBES] = { .type = NLA_U32 }, 00251 }; 00252 00253 static int neigh_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 00254 struct nlmsghdr *n, struct nl_parser_param *pp) 00255 { 00256 struct rtnl_neigh *neigh; 00257 struct nlattr *tb[NDA_MAX + 1]; 00258 struct ndmsg *nm; 00259 int err; 00260 00261 neigh = rtnl_neigh_alloc(); 00262 if (!neigh) { 00263 err = -NLE_NOMEM; 00264 goto errout; 00265 } 00266 00267 neigh->ce_msgtype = n->nlmsg_type; 00268 nm = nlmsg_data(n); 00269 00270 err = nlmsg_parse(n, sizeof(*nm), tb, NDA_MAX, neigh_policy); 00271 if (err < 0) 00272 goto errout; 00273 00274 neigh->n_family = nm->ndm_family; 00275 neigh->n_ifindex = nm->ndm_ifindex; 00276 neigh->n_state = nm->ndm_state; 00277 neigh->n_flags = nm->ndm_flags; 00278 neigh->n_type = nm->ndm_type; 00279 00280 neigh->ce_mask |= (NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX | 00281 NEIGH_ATTR_STATE | NEIGH_ATTR_FLAGS | 00282 NEIGH_ATTR_TYPE); 00283 00284 if (tb[NDA_LLADDR]) { 00285 neigh->n_lladdr = nl_addr_alloc_attr(tb[NDA_LLADDR], AF_UNSPEC); 00286 if (!neigh->n_lladdr) { 00287 err = -NLE_NOMEM; 00288 goto errout; 00289 } 00290 nl_addr_set_family(neigh->n_lladdr, 00291 nl_addr_guess_family(neigh->n_lladdr)); 00292 neigh->ce_mask |= NEIGH_ATTR_LLADDR; 00293 } 00294 00295 if (tb[NDA_DST]) { 00296 neigh->n_dst = nl_addr_alloc_attr(tb[NDA_DST], neigh->n_family); 00297 if (!neigh->n_dst) { 00298 err = -NLE_NOMEM; 00299 goto errout; 00300 } 00301 neigh->ce_mask |= NEIGH_ATTR_DST; 00302 } 00303 00304 if (tb[NDA_CACHEINFO]) { 00305 struct nda_cacheinfo *ci = nla_data(tb[NDA_CACHEINFO]); 00306 00307 neigh->n_cacheinfo.nci_confirmed = ci->ndm_confirmed; 00308 neigh->n_cacheinfo.nci_used = ci->ndm_used; 00309 neigh->n_cacheinfo.nci_updated = ci->ndm_updated; 00310 neigh->n_cacheinfo.nci_refcnt = ci->ndm_refcnt; 00311 00312 neigh->ce_mask |= NEIGH_ATTR_CACHEINFO; 00313 } 00314 00315 if (tb[NDA_PROBES]) { 00316 neigh->n_probes = nla_get_u32(tb[NDA_PROBES]); 00317 neigh->ce_mask |= NEIGH_ATTR_PROBES; 00318 } 00319 00320 err = pp->pp_cb((struct nl_object *) neigh, pp); 00321 errout: 00322 rtnl_neigh_put(neigh); 00323 return err; 00324 } 00325 00326 static int neigh_request_update(struct nl_cache *c, struct nl_sock *h) 00327 { 00328 return nl_rtgen_request(h, RTM_GETNEIGH, AF_UNSPEC, NLM_F_DUMP); 00329 } 00330 00331 00332 static void neigh_dump_line(struct nl_object *a, struct nl_dump_params *p) 00333 { 00334 char dst[INET6_ADDRSTRLEN+5], lladdr[INET6_ADDRSTRLEN+5]; 00335 struct rtnl_neigh *n = (struct rtnl_neigh *) a; 00336 struct nl_cache *link_cache; 00337 char state[128], flags[64]; 00338 00339 link_cache = nl_cache_mngt_require("route/link"); 00340 00341 nl_dump_line(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst))); 00342 00343 if (link_cache) 00344 nl_dump(p, "dev %s ", 00345 rtnl_link_i2name(link_cache, n->n_ifindex, 00346 state, sizeof(state))); 00347 else 00348 nl_dump(p, "dev %d ", n->n_ifindex); 00349 00350 if (n->ce_mask & NEIGH_ATTR_LLADDR) 00351 nl_dump(p, "lladdr %s ", 00352 nl_addr2str(n->n_lladdr, lladdr, sizeof(lladdr))); 00353 00354 rtnl_neigh_state2str(n->n_state, state, sizeof(state)); 00355 rtnl_neigh_flags2str(n->n_flags, flags, sizeof(flags)); 00356 00357 if (state[0]) 00358 nl_dump(p, "<%s", state); 00359 if (flags[0]) 00360 nl_dump(p, "%s%s", state[0] ? "," : "<", flags); 00361 if (state[0] || flags[0]) 00362 nl_dump(p, ">"); 00363 nl_dump(p, "\n"); 00364 } 00365 00366 static void neigh_dump_details(struct nl_object *a, struct nl_dump_params *p) 00367 { 00368 char rtn_type[32]; 00369 struct rtnl_neigh *n = (struct rtnl_neigh *) a; 00370 int hz = nl_get_user_hz(); 00371 00372 neigh_dump_line(a, p); 00373 00374 nl_dump_line(p, " refcnt %u type %s confirmed %u used " 00375 "%u updated %u\n", 00376 n->n_cacheinfo.nci_refcnt, 00377 nl_rtntype2str(n->n_type, rtn_type, sizeof(rtn_type)), 00378 n->n_cacheinfo.nci_confirmed/hz, 00379 n->n_cacheinfo.nci_used/hz, n->n_cacheinfo.nci_updated/hz); 00380 } 00381 00382 static void neigh_dump_stats(struct nl_object *a, struct nl_dump_params *p) 00383 { 00384 neigh_dump_details(a, p); 00385 } 00386 00387 /** 00388 * @name Neighbour Object Allocation/Freeage 00389 * @{ 00390 */ 00391 00392 struct rtnl_neigh *rtnl_neigh_alloc(void) 00393 { 00394 return (struct rtnl_neigh *) nl_object_alloc(&neigh_obj_ops); 00395 } 00396 00397 void rtnl_neigh_put(struct rtnl_neigh *neigh) 00398 { 00399 nl_object_put((struct nl_object *) neigh); 00400 } 00401 00402 /** @} */ 00403 00404 /** 00405 * @name Neighbour Cache Managament 00406 * @{ 00407 */ 00408 00409 /** 00410 * Build a neighbour cache including all neighbours currently configured in the kernel. 00411 * @arg sock Netlink socket. 00412 * @arg result Pointer to store resulting cache. 00413 * 00414 * Allocates a new neighbour cache, initializes it properly and updates it 00415 * to include all neighbours currently configured in the kernel. 00416 * 00417 * @return 0 on success or a negative error code. 00418 */ 00419 int rtnl_neigh_alloc_cache(struct nl_sock *sock, struct nl_cache **result) 00420 { 00421 return nl_cache_alloc_and_fill(&rtnl_neigh_ops, sock, result); 00422 } 00423 00424 /** 00425 * Look up a neighbour by interface index and destination address 00426 * @arg cache neighbour cache 00427 * @arg ifindex interface index the neighbour is on 00428 * @arg dst destination address of the neighbour 00429 * @return neighbour handle or NULL if no match was found. 00430 */ 00431 struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex, 00432 struct nl_addr *dst) 00433 { 00434 struct rtnl_neigh *neigh; 00435 00436 nl_list_for_each_entry(neigh, &cache->c_items, ce_list) { 00437 if (neigh->n_ifindex == ifindex && 00438 !nl_addr_cmp(neigh->n_dst, dst)) { 00439 nl_object_get((struct nl_object *) neigh); 00440 return neigh; 00441 } 00442 } 00443 00444 return NULL; 00445 } 00446 00447 /** @} */ 00448 00449 /** 00450 * @name Neighbour Addition 00451 * @{ 00452 */ 00453 00454 static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags, 00455 struct nl_msg **result) 00456 { 00457 struct nl_msg *msg; 00458 struct ndmsg nhdr = { 00459 .ndm_ifindex = tmpl->n_ifindex, 00460 .ndm_state = NUD_PERMANENT, 00461 }; 00462 00463 if (!(tmpl->ce_mask & NEIGH_ATTR_DST)) 00464 return -NLE_MISSING_ATTR; 00465 00466 nhdr.ndm_family = nl_addr_get_family(tmpl->n_dst); 00467 00468 if (tmpl->ce_mask & NEIGH_ATTR_FLAGS) 00469 nhdr.ndm_flags = tmpl->n_flags; 00470 00471 if (tmpl->ce_mask & NEIGH_ATTR_STATE) 00472 nhdr.ndm_state = tmpl->n_state; 00473 00474 msg = nlmsg_alloc_simple(cmd, flags); 00475 if (!msg) 00476 return -NLE_NOMEM; 00477 00478 if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0) 00479 goto nla_put_failure; 00480 00481 NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst); 00482 00483 if (tmpl->ce_mask & NEIGH_ATTR_LLADDR) 00484 NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr); 00485 00486 *result = msg; 00487 return 0; 00488 00489 nla_put_failure: 00490 nlmsg_free(msg); 00491 return -NLE_MSGSIZE; 00492 } 00493 00494 /** 00495 * Build netlink request message to add a new neighbour 00496 * @arg tmpl template with data of new neighbour 00497 * @arg flags additional netlink message flags 00498 * @arg result Pointer to store resulting message. 00499 * 00500 * Builds a new netlink message requesting a addition of a new 00501 * neighbour. The netlink message header isn't fully equipped with 00502 * all relevant fields and must thus be sent out via nl_send_auto_complete() 00503 * or supplemented as needed. \a tmpl must contain the attributes of the new 00504 * neighbour set via \c rtnl_neigh_set_* functions. 00505 * 00506 * The following attributes must be set in the template: 00507 * - Interface index (rtnl_neigh_set_ifindex()) 00508 * - State (rtnl_neigh_set_state()) 00509 * - Destination address (rtnl_neigh_set_dst()) 00510 * - Link layer address (rtnl_neigh_set_lladdr()) 00511 * 00512 * @return 0 on success or a negative error code. 00513 */ 00514 int rtnl_neigh_build_add_request(struct rtnl_neigh *tmpl, int flags, 00515 struct nl_msg **result) 00516 { 00517 return build_neigh_msg(tmpl, RTM_NEWNEIGH, flags, result); 00518 } 00519 00520 /** 00521 * Add a new neighbour 00522 * @arg sk Netlink socket. 00523 * @arg tmpl template with requested changes 00524 * @arg flags additional netlink message flags 00525 * 00526 * Builds a netlink message by calling rtnl_neigh_build_add_request(), 00527 * sends the request to the kernel and waits for the next ACK to be 00528 * received and thus blocks until the request has been fullfilled. 00529 * 00530 * The following attributes must be set in the template: 00531 * - Interface index (rtnl_neigh_set_ifindex()) 00532 * - State (rtnl_neigh_set_state()) 00533 * - Destination address (rtnl_neigh_set_dst()) 00534 * - Link layer address (rtnl_neigh_set_lladdr()) 00535 * 00536 * @return 0 on sucess or a negative error if an error occured. 00537 */ 00538 int rtnl_neigh_add(struct nl_sock *sk, struct rtnl_neigh *tmpl, int flags) 00539 { 00540 int err; 00541 struct nl_msg *msg; 00542 00543 if ((err = rtnl_neigh_build_add_request(tmpl, flags, &msg)) < 0) 00544 return err; 00545 00546 err = nl_send_auto_complete(sk, msg); 00547 nlmsg_free(msg); 00548 if (err < 0) 00549 return err; 00550 00551 return wait_for_ack(sk); 00552 } 00553 00554 /** @} */ 00555 00556 /** 00557 * @name Neighbour Deletion 00558 * @{ 00559 */ 00560 00561 /** 00562 * Build a netlink request message to delete a neighbour 00563 * @arg neigh neighbour to delete 00564 * @arg flags additional netlink message flags 00565 * @arg result Pointer to store resulting message. 00566 * 00567 * Builds a new netlink message requesting a deletion of a neighbour. 00568 * The netlink message header isn't fully equipped with all relevant 00569 * fields and must thus be sent out via nl_send_auto_complete() 00570 * or supplemented as needed. \a neigh must point to an existing 00571 * neighbour. 00572 * 00573 * @return 0 on success or a negative error code. 00574 */ 00575 int rtnl_neigh_build_delete_request(struct rtnl_neigh *neigh, int flags, 00576 struct nl_msg **result) 00577 { 00578 return build_neigh_msg(neigh, RTM_DELNEIGH, flags, result); 00579 } 00580 00581 /** 00582 * Delete a neighbour 00583 * @arg sk Netlink socket. 00584 * @arg neigh neighbour to delete 00585 * @arg flags additional netlink message flags 00586 * 00587 * Builds a netlink message by calling rtnl_neigh_build_delete_request(), 00588 * sends the request to the kernel and waits for the next ACK to be 00589 * received and thus blocks until the request has been fullfilled. 00590 * 00591 * @return 0 on sucess or a negative error if an error occured. 00592 */ 00593 int rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh, 00594 int flags) 00595 { 00596 struct nl_msg *msg; 00597 int err; 00598 00599 if ((err = rtnl_neigh_build_delete_request(neigh, flags, &msg)) < 0) 00600 return err; 00601 00602 err = nl_send_auto_complete(sk, msg); 00603 nlmsg_free(msg); 00604 if (err < 0) 00605 return err; 00606 00607 return wait_for_ack(sk); 00608 } 00609 00610 /** @} */ 00611 00612 /** 00613 * @name Neighbour States Translations 00614 * @{ 00615 */ 00616 00617 static const struct trans_tbl neigh_states[] = { 00618 __ADD(NUD_INCOMPLETE, incomplete) 00619 __ADD(NUD_REACHABLE, reachable) 00620 __ADD(NUD_STALE, stale) 00621 __ADD(NUD_DELAY, delay) 00622 __ADD(NUD_PROBE, probe) 00623 __ADD(NUD_FAILED, failed) 00624 __ADD(NUD_NOARP, norarp) 00625 __ADD(NUD_PERMANENT, permanent) 00626 }; 00627 00628 char * rtnl_neigh_state2str(int state, char *buf, size_t len) 00629 { 00630 return __flags2str(state, buf, len, neigh_states, 00631 ARRAY_SIZE(neigh_states)); 00632 } 00633 00634 int rtnl_neigh_str2state(const char *name) 00635 { 00636 return __str2type(name, neigh_states, ARRAY_SIZE(neigh_states)); 00637 } 00638 00639 /** @} */ 00640 00641 /** 00642 * @name Neighbour Flags Translations 00643 * @{ 00644 */ 00645 00646 static const struct trans_tbl neigh_flags[] = { 00647 __ADD(NTF_USE, use) 00648 __ADD(NTF_PROXY, proxy) 00649 __ADD(NTF_ROUTER, router) 00650 }; 00651 00652 char * rtnl_neigh_flags2str(int flags, char *buf, size_t len) 00653 { 00654 return __flags2str(flags, buf, len, neigh_flags, 00655 ARRAY_SIZE(neigh_flags)); 00656 } 00657 00658 int rtnl_neigh_str2flag(const char *name) 00659 { 00660 return __str2type(name, neigh_flags, ARRAY_SIZE(neigh_flags)); 00661 } 00662 00663 /** @} */ 00664 00665 /** 00666 * @name Attributes 00667 * @{ 00668 */ 00669 00670 void rtnl_neigh_set_state(struct rtnl_neigh *neigh, int state) 00671 { 00672 neigh->n_state_mask |= state; 00673 neigh->n_state |= state; 00674 neigh->ce_mask |= NEIGH_ATTR_STATE; 00675 } 00676 00677 int rtnl_neigh_get_state(struct rtnl_neigh *neigh) 00678 { 00679 if (neigh->ce_mask & NEIGH_ATTR_STATE) 00680 return neigh->n_state; 00681 else 00682 return -1; 00683 } 00684 00685 void rtnl_neigh_unset_state(struct rtnl_neigh *neigh, int state) 00686 { 00687 neigh->n_state_mask |= state; 00688 neigh->n_state &= ~state; 00689 neigh->ce_mask |= NEIGH_ATTR_STATE; 00690 } 00691 00692 void rtnl_neigh_set_flags(struct rtnl_neigh *neigh, unsigned int flags) 00693 { 00694 neigh->n_flag_mask |= flags; 00695 neigh->n_flags |= flags; 00696 neigh->ce_mask |= NEIGH_ATTR_FLAGS; 00697 } 00698 00699 unsigned int rtnl_neigh_get_flags(struct rtnl_neigh *neigh) 00700 { 00701 return neigh->n_flags; 00702 } 00703 00704 void rtnl_neigh_unset_flags(struct rtnl_neigh *neigh, unsigned int flags) 00705 { 00706 neigh->n_flag_mask |= flags; 00707 neigh->n_flags &= ~flags; 00708 neigh->ce_mask |= NEIGH_ATTR_FLAGS; 00709 } 00710 00711 void rtnl_neigh_set_ifindex(struct rtnl_neigh *neigh, int ifindex) 00712 { 00713 neigh->n_ifindex = ifindex; 00714 neigh->ce_mask |= NEIGH_ATTR_IFINDEX; 00715 } 00716 00717 int rtnl_neigh_get_ifindex(struct rtnl_neigh *neigh) 00718 { 00719 return neigh->n_ifindex; 00720 } 00721 00722 static inline int __assign_addr(struct rtnl_neigh *neigh, struct nl_addr **pos, 00723 struct nl_addr *new, int flag, int nocheck) 00724 { 00725 if (!nocheck) { 00726 if (neigh->ce_mask & NEIGH_ATTR_FAMILY) { 00727 if (new->a_family != neigh->n_family) 00728 return -NLE_AF_MISMATCH; 00729 } else { 00730 neigh->n_family = new->a_family; 00731 neigh->ce_mask |= NEIGH_ATTR_FAMILY; 00732 } 00733 } 00734 00735 if (*pos) 00736 nl_addr_put(*pos); 00737 00738 nl_addr_get(new); 00739 *pos = new; 00740 00741 neigh->ce_mask |= flag; 00742 00743 return 0; 00744 } 00745 00746 void rtnl_neigh_set_lladdr(struct rtnl_neigh *neigh, struct nl_addr *addr) 00747 { 00748 __assign_addr(neigh, &neigh->n_lladdr, addr, NEIGH_ATTR_LLADDR, 1); 00749 } 00750 00751 struct nl_addr *rtnl_neigh_get_lladdr(struct rtnl_neigh *neigh) 00752 { 00753 if (neigh->ce_mask & NEIGH_ATTR_LLADDR) 00754 return neigh->n_lladdr; 00755 else 00756 return NULL; 00757 } 00758 00759 int rtnl_neigh_set_dst(struct rtnl_neigh *neigh, struct nl_addr *addr) 00760 { 00761 return __assign_addr(neigh, &neigh->n_dst, addr, 00762 NEIGH_ATTR_DST, 0); 00763 } 00764 00765 struct nl_addr *rtnl_neigh_get_dst(struct rtnl_neigh *neigh) 00766 { 00767 if (neigh->ce_mask & NEIGH_ATTR_DST) 00768 return neigh->n_dst; 00769 else 00770 return NULL; 00771 } 00772 00773 void rtnl_neigh_set_family(struct rtnl_neigh *neigh, int family) 00774 { 00775 neigh->n_family = family; 00776 neigh->ce_mask |= NEIGH_ATTR_FAMILY; 00777 } 00778 00779 int rtnl_neigh_get_family(struct rtnl_neigh *neigh) 00780 { 00781 return neigh->n_family; 00782 } 00783 00784 void rtnl_neigh_set_type(struct rtnl_neigh *neigh, int type) 00785 { 00786 neigh->n_type = type; 00787 neigh->ce_mask = NEIGH_ATTR_TYPE; 00788 } 00789 00790 int rtnl_neigh_get_type(struct rtnl_neigh *neigh) 00791 { 00792 if (neigh->ce_mask & NEIGH_ATTR_TYPE) 00793 return neigh->n_type; 00794 else 00795 return -1; 00796 } 00797 00798 /** @} */ 00799 00800 static struct nl_object_ops neigh_obj_ops = { 00801 .oo_name = "route/neigh", 00802 .oo_size = sizeof(struct rtnl_neigh), 00803 .oo_free_data = neigh_free_data, 00804 .oo_clone = neigh_clone, 00805 .oo_dump = { 00806 [NL_DUMP_LINE] = neigh_dump_line, 00807 [NL_DUMP_DETAILS] = neigh_dump_details, 00808 [NL_DUMP_STATS] = neigh_dump_stats, 00809 }, 00810 .oo_compare = neigh_compare, 00811 .oo_attrs2str = neigh_attrs2str, 00812 .oo_id_attrs = (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY), 00813 }; 00814 00815 static struct nl_af_group neigh_groups[] = { 00816 { AF_UNSPEC, RTNLGRP_NEIGH }, 00817 { END_OF_GROUP_LIST }, 00818 }; 00819 00820 static struct nl_cache_ops rtnl_neigh_ops = { 00821 .co_name = "route/neigh", 00822 .co_hdrsize = sizeof(struct ndmsg), 00823 .co_msgtypes = { 00824 { RTM_NEWNEIGH, NL_ACT_NEW, "new" }, 00825 { RTM_DELNEIGH, NL_ACT_DEL, "del" }, 00826 { RTM_GETNEIGH, NL_ACT_GET, "get" }, 00827 END_OF_MSGTYPES_LIST, 00828 }, 00829 .co_protocol = NETLINK_ROUTE, 00830 .co_groups = neigh_groups, 00831 .co_request_update = neigh_request_update, 00832 .co_msg_parser = neigh_msg_parser, 00833 .co_obj_ops = &neigh_obj_ops, 00834 }; 00835 00836 static void __init neigh_init(void) 00837 { 00838 nl_cache_mngt_register(&rtnl_neigh_ops); 00839 } 00840 00841 static void __exit neigh_exit(void) 00842 { 00843 nl_cache_mngt_unregister(&rtnl_neigh_ops); 00844 } 00845 00846 /** @} */