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