libnl 1.1
|
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-2006 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(handle); 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(nl_handle, neigh, NLM_F_REPLACE); 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(handle, 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_change(handle, neigh, 0); 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 goto errout; 00191 00192 if (src->n_dst) 00193 if (!(dst->n_dst = nl_addr_clone(src->n_dst))) 00194 goto errout; 00195 00196 return 0; 00197 errout: 00198 return nl_get_errno(); 00199 } 00200 00201 static int neigh_compare(struct nl_object *_a, struct nl_object *_b, 00202 uint32_t attrs, int flags) 00203 { 00204 struct rtnl_neigh *a = (struct rtnl_neigh *) _a; 00205 struct rtnl_neigh *b = (struct rtnl_neigh *) _b; 00206 int diff = 0; 00207 00208 #define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR) 00209 00210 diff |= NEIGH_DIFF(IFINDEX, a->n_ifindex != b->n_ifindex); 00211 diff |= NEIGH_DIFF(FAMILY, a->n_family != b->n_family); 00212 diff |= NEIGH_DIFF(TYPE, a->n_type != b->n_type); 00213 diff |= NEIGH_DIFF(LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr)); 00214 diff |= NEIGH_DIFF(DST, nl_addr_cmp(a->n_dst, b->n_dst)); 00215 00216 if (flags & LOOSE_FLAG_COMPARISON) { 00217 diff |= NEIGH_DIFF(STATE, 00218 (a->n_state ^ b->n_state) & b->n_state_mask); 00219 diff |= NEIGH_DIFF(FLAGS, 00220 (a->n_flags ^ b->n_flags) & b->n_flag_mask); 00221 } else { 00222 diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state); 00223 diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags); 00224 } 00225 00226 #undef NEIGH_DIFF 00227 00228 return diff; 00229 } 00230 00231 static struct trans_tbl neigh_attrs[] = { 00232 __ADD(NEIGH_ATTR_FLAGS, flags) 00233 __ADD(NEIGH_ATTR_STATE, state) 00234 __ADD(NEIGH_ATTR_LLADDR, lladdr) 00235 __ADD(NEIGH_ATTR_DST, dst) 00236 __ADD(NEIGH_ATTR_CACHEINFO, cacheinfo) 00237 __ADD(NEIGH_ATTR_IFINDEX, ifindex) 00238 __ADD(NEIGH_ATTR_FAMILY, family) 00239 __ADD(NEIGH_ATTR_TYPE, type) 00240 __ADD(NEIGH_ATTR_PROBES, probes) 00241 }; 00242 00243 static char *neigh_attrs2str(int attrs, char *buf, size_t len) 00244 { 00245 return __flags2str(attrs, buf, len, neigh_attrs, 00246 ARRAY_SIZE(neigh_attrs)); 00247 } 00248 00249 static struct nla_policy neigh_policy[NDA_MAX+1] = { 00250 [NDA_CACHEINFO] = { .minlen = sizeof(struct nda_cacheinfo) }, 00251 [NDA_PROBES] = { .type = NLA_U32 }, 00252 }; 00253 00254 static int neigh_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 00255 struct nlmsghdr *n, struct nl_parser_param *pp) 00256 { 00257 struct rtnl_neigh *neigh; 00258 struct nlattr *tb[NDA_MAX + 1]; 00259 struct ndmsg *nm; 00260 int err; 00261 00262 neigh = rtnl_neigh_alloc(); 00263 if (!neigh) { 00264 err = nl_errno(ENOMEM); 00265 goto errout; 00266 } 00267 00268 neigh->ce_msgtype = n->nlmsg_type; 00269 nm = nlmsg_data(n); 00270 00271 err = nlmsg_parse(n, sizeof(*nm), tb, NDA_MAX, neigh_policy); 00272 if (err < 0) 00273 goto errout; 00274 00275 neigh->n_family = nm->ndm_family; 00276 neigh->n_ifindex = nm->ndm_ifindex; 00277 neigh->n_state = nm->ndm_state; 00278 neigh->n_flags = nm->ndm_flags; 00279 neigh->n_type = nm->ndm_type; 00280 00281 neigh->ce_mask |= (NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX | 00282 NEIGH_ATTR_STATE | NEIGH_ATTR_FLAGS | 00283 NEIGH_ATTR_TYPE); 00284 00285 if (tb[NDA_LLADDR]) { 00286 neigh->n_lladdr = nla_get_addr(tb[NDA_LLADDR], AF_UNSPEC); 00287 if (!neigh->n_lladdr) 00288 goto errout; 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 = nla_get_addr(tb[NDA_DST], neigh->n_family); 00296 if (!neigh->n_dst) 00297 goto errout; 00298 neigh->ce_mask |= NEIGH_ATTR_DST; 00299 } 00300 00301 if (tb[NDA_CACHEINFO]) { 00302 struct nda_cacheinfo *ci = nla_data(tb[NDA_CACHEINFO]); 00303 00304 neigh->n_cacheinfo.nci_confirmed = ci->ndm_confirmed; 00305 neigh->n_cacheinfo.nci_used = ci->ndm_used; 00306 neigh->n_cacheinfo.nci_updated = ci->ndm_updated; 00307 neigh->n_cacheinfo.nci_refcnt = ci->ndm_refcnt; 00308 00309 neigh->ce_mask |= NEIGH_ATTR_CACHEINFO; 00310 } 00311 00312 if (tb[NDA_PROBES]) { 00313 neigh->n_probes = nla_get_u32(tb[NDA_PROBES]); 00314 neigh->ce_mask |= NEIGH_ATTR_PROBES; 00315 } 00316 00317 err = pp->pp_cb((struct nl_object *) neigh, pp); 00318 if (err < 0) 00319 goto errout; 00320 00321 err = P_ACCEPT; 00322 00323 errout: 00324 rtnl_neigh_put(neigh); 00325 return err; 00326 } 00327 00328 static int neigh_request_update(struct nl_cache *c, struct nl_handle *h) 00329 { 00330 return nl_rtgen_request(h, RTM_GETNEIGH, AF_UNSPEC, NLM_F_DUMP); 00331 } 00332 00333 00334 static int neigh_dump_brief(struct nl_object *a, struct nl_dump_params *p) 00335 { 00336 char dst[INET6_ADDRSTRLEN+5], lladdr[INET6_ADDRSTRLEN+5]; 00337 struct rtnl_neigh *n = (struct rtnl_neigh *) a; 00338 struct nl_cache *link_cache; 00339 char state[128], flags[64]; 00340 00341 link_cache = nl_cache_mngt_require("route/link"); 00342 00343 dp_dump(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst))); 00344 00345 if (link_cache) 00346 dp_dump(p, "dev %s ", 00347 rtnl_link_i2name(link_cache, n->n_ifindex, 00348 state, sizeof(state))); 00349 else 00350 dp_dump(p, "dev %d ", n->n_ifindex); 00351 00352 if (n->ce_mask & NEIGH_ATTR_LLADDR) 00353 dp_dump(p, "lladdr %s ", 00354 nl_addr2str(n->n_lladdr, lladdr, sizeof(lladdr))); 00355 00356 rtnl_neigh_state2str(n->n_state, state, sizeof(state)); 00357 rtnl_neigh_flags2str(n->n_flags, flags, sizeof(flags)); 00358 00359 if (state[0]) 00360 dp_dump(p, "<%s", state); 00361 if (flags[0]) 00362 dp_dump(p, "%s%s", state[0] ? "," : "<", flags); 00363 if (state[0] || flags[0]) 00364 dp_dump(p, ">"); 00365 dp_dump(p, "\n"); 00366 00367 return 1; 00368 } 00369 00370 static int neigh_dump_full(struct nl_object *a, struct nl_dump_params *p) 00371 { 00372 char rtn_type[32]; 00373 struct rtnl_neigh *n = (struct rtnl_neigh *) a; 00374 int hz = nl_get_hz(); 00375 00376 int line = neigh_dump_brief(a, p); 00377 00378 dp_dump_line(p, line++, " refcnt %u type %s confirmed %u used " 00379 "%u updated %u\n", 00380 n->n_cacheinfo.nci_refcnt, 00381 nl_rtntype2str(n->n_type, rtn_type, sizeof(rtn_type)), 00382 n->n_cacheinfo.nci_confirmed/hz, 00383 n->n_cacheinfo.nci_used/hz, n->n_cacheinfo.nci_updated/hz); 00384 00385 return line; 00386 } 00387 00388 static int neigh_dump_stats(struct nl_object *a, struct nl_dump_params *p) 00389 { 00390 return neigh_dump_full(a, p); 00391 } 00392 00393 static int neigh_dump_xml(struct nl_object *obj, struct nl_dump_params *p) 00394 { 00395 struct rtnl_neigh *neigh = (struct rtnl_neigh *) obj; 00396 char buf[128]; 00397 int line = 0; 00398 00399 dp_dump_line(p, line++, "<neighbour>\n"); 00400 dp_dump_line(p, line++, " <family>%s</family>\n", 00401 nl_af2str(neigh->n_family, buf, sizeof(buf))); 00402 00403 if (neigh->ce_mask & NEIGH_ATTR_LLADDR) 00404 dp_dump_line(p, line++, " <lladdr>%s</lladdr>\n", 00405 nl_addr2str(neigh->n_lladdr, buf, sizeof(buf))); 00406 00407 if (neigh->ce_mask & NEIGH_ATTR_DST) 00408 dp_dump_line(p, line++, " <dst>%s</dst>\n", 00409 nl_addr2str(neigh->n_dst, buf, sizeof(buf))); 00410 00411 if (neigh->ce_mask & NEIGH_ATTR_IFINDEX) { 00412 struct nl_cache *link_cache; 00413 00414 link_cache = nl_cache_mngt_require("route/link"); 00415 00416 if (link_cache) 00417 dp_dump_line(p, line++, " <device>%s</device>\n", 00418 rtnl_link_i2name(link_cache, 00419 neigh->n_ifindex, 00420 buf, sizeof(buf))); 00421 else 00422 dp_dump_line(p, line++, " <device>%u</device>\n", 00423 neigh->n_ifindex); 00424 } 00425 00426 if (neigh->ce_mask & NEIGH_ATTR_PROBES) 00427 dp_dump_line(p, line++, " <probes>%u</probes>\n", 00428 neigh->n_probes); 00429 00430 if (neigh->ce_mask & NEIGH_ATTR_TYPE) 00431 dp_dump_line(p, line++, " <type>%s</type>\n", 00432 nl_rtntype2str(neigh->n_type, buf, sizeof(buf))); 00433 00434 rtnl_neigh_flags2str(neigh->n_flags, buf, sizeof(buf)); 00435 if (buf[0]) 00436 dp_dump_line(p, line++, " <flags>%s</flags>\n", buf); 00437 00438 rtnl_neigh_state2str(neigh->n_state, buf, sizeof(buf)); 00439 if (buf[0]) 00440 dp_dump_line(p, line++, " <state>%s</state>\n", buf); 00441 00442 dp_dump_line(p, line++, "</neighbour>\n"); 00443 00444 #if 0 00445 struct rtnl_ncacheinfo n_cacheinfo; 00446 #endif 00447 00448 return line; 00449 } 00450 00451 static int neigh_dump_env(struct nl_object *obj, struct nl_dump_params *p) 00452 { 00453 struct rtnl_neigh *neigh = (struct rtnl_neigh *) obj; 00454 char buf[128]; 00455 int line = 0; 00456 00457 dp_dump_line(p, line++, "NEIGH_FAMILY=%s\n", 00458 nl_af2str(neigh->n_family, buf, sizeof(buf))); 00459 00460 if (neigh->ce_mask & NEIGH_ATTR_LLADDR) 00461 dp_dump_line(p, line++, "NEIGHT_LLADDR=%s\n", 00462 nl_addr2str(neigh->n_lladdr, buf, sizeof(buf))); 00463 00464 if (neigh->ce_mask & NEIGH_ATTR_DST) 00465 dp_dump_line(p, line++, "NEIGH_DST=%s\n", 00466 nl_addr2str(neigh->n_dst, buf, sizeof(buf))); 00467 00468 if (neigh->ce_mask & NEIGH_ATTR_IFINDEX) { 00469 struct nl_cache *link_cache; 00470 00471 dp_dump_line(p, line++, "NEIGH_IFINDEX=%u\n", 00472 neigh->n_ifindex); 00473 00474 link_cache = nl_cache_mngt_require("route/link"); 00475 if (link_cache) 00476 dp_dump_line(p, line++, "NEIGH_IFNAME=%s\n", 00477 rtnl_link_i2name(link_cache, 00478 neigh->n_ifindex, 00479 buf, sizeof(buf))); 00480 } 00481 00482 if (neigh->ce_mask & NEIGH_ATTR_PROBES) 00483 dp_dump_line(p, line++, "NEIGH_PROBES=%u\n", 00484 neigh->n_probes); 00485 00486 if (neigh->ce_mask & NEIGH_ATTR_TYPE) 00487 dp_dump_line(p, line++, "NEIGH_TYPE=%s\n", 00488 nl_rtntype2str(neigh->n_type, buf, sizeof(buf))); 00489 00490 rtnl_neigh_flags2str(neigh->n_flags, buf, sizeof(buf)); 00491 if (buf[0]) 00492 dp_dump_line(p, line++, "NEIGH_FLAGS=%s\n", buf); 00493 00494 rtnl_neigh_state2str(neigh->n_state, buf, sizeof(buf)); 00495 if (buf[0]) 00496 dp_dump_line(p, line++, "NEIGH_STATE=%s\n", buf); 00497 00498 return line; 00499 } 00500 00501 /** 00502 * @name Neighbour Object Allocation/Freeage 00503 * @{ 00504 */ 00505 00506 struct rtnl_neigh *rtnl_neigh_alloc(void) 00507 { 00508 return (struct rtnl_neigh *) nl_object_alloc(&neigh_obj_ops); 00509 } 00510 00511 void rtnl_neigh_put(struct rtnl_neigh *neigh) 00512 { 00513 nl_object_put((struct nl_object *) neigh); 00514 } 00515 00516 /** @} */ 00517 00518 /** 00519 * @name Neighbour Cache Managament 00520 * @{ 00521 */ 00522 00523 /** 00524 * Build a neighbour cache including all neighbours currently configured in the kernel. 00525 * @arg handle netlink handle 00526 * 00527 * Allocates a new neighbour cache, initializes it properly and updates it 00528 * to include all neighbours currently configured in the kernel. 00529 * 00530 * @note The caller is responsible for destroying and freeing the 00531 * cache after using it. 00532 * @return The new cache or NULL if an error occured. 00533 */ 00534 struct nl_cache *rtnl_neigh_alloc_cache(struct nl_handle *handle) 00535 { 00536 struct nl_cache *cache; 00537 00538 cache = nl_cache_alloc(&rtnl_neigh_ops); 00539 if (cache == NULL) 00540 return NULL; 00541 00542 if (handle && nl_cache_refill(handle, cache) < 0) { 00543 nl_cache_free(cache); 00544 return NULL; 00545 } 00546 00547 NL_DBG(2, "Returning new cache %p\n", cache); 00548 00549 return cache; 00550 } 00551 00552 /** 00553 * Look up a neighbour by interface index and destination address 00554 * @arg cache neighbour cache 00555 * @arg ifindex interface index the neighbour is on 00556 * @arg dst destination address of the neighbour 00557 * @return neighbour handle or NULL if no match was found. 00558 */ 00559 struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex, 00560 struct nl_addr *dst) 00561 { 00562 struct rtnl_neigh *neigh; 00563 00564 nl_list_for_each_entry(neigh, &cache->c_items, ce_list) { 00565 if (neigh->n_ifindex == ifindex && 00566 !nl_addr_cmp(neigh->n_dst, dst)) { 00567 nl_object_get((struct nl_object *) neigh); 00568 return neigh; 00569 } 00570 } 00571 00572 return NULL; 00573 } 00574 00575 /** @} */ 00576 00577 /** 00578 * @name Neighbour Addition 00579 * @{ 00580 */ 00581 00582 static struct nl_msg * build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, 00583 int flags) 00584 { 00585 struct nl_msg *msg; 00586 struct ndmsg nhdr = { 00587 .ndm_ifindex = tmpl->n_ifindex, 00588 .ndm_family = nl_addr_get_family(tmpl->n_dst), 00589 .ndm_state = NUD_PERMANENT, 00590 }; 00591 00592 if (tmpl->ce_mask & NEIGH_ATTR_STATE) 00593 nhdr.ndm_state = tmpl->n_state; 00594 00595 msg = nlmsg_alloc_simple(cmd, flags); 00596 if (!msg) 00597 return NULL; 00598 00599 if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0) 00600 goto nla_put_failure; 00601 00602 NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst); 00603 00604 if (tmpl->ce_mask & NEIGH_ATTR_LLADDR) 00605 NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr); 00606 00607 return msg; 00608 00609 nla_put_failure: 00610 nlmsg_free(msg); 00611 return NULL; 00612 } 00613 00614 /** 00615 * Build netlink request message to add a new neighbour 00616 * @arg tmpl template with data of new neighbour 00617 * @arg flags additional netlink message flags 00618 * 00619 * Builds a new netlink message requesting a addition of a new 00620 * neighbour. The netlink message header isn't fully equipped with 00621 * all relevant fields and must thus be sent out via nl_send_auto_complete() 00622 * or supplemented as needed. \a tmpl must contain the attributes of the new 00623 * neighbour set via \c rtnl_neigh_set_* functions. 00624 * 00625 * The following attributes must be set in the template: 00626 * - Interface index (rtnl_neigh_set_ifindex()) 00627 * - State (rtnl_neigh_set_state()) 00628 * - Destination address (rtnl_neigh_set_dst()) 00629 * - Link layer address (rtnl_neigh_set_lladdr()) 00630 * 00631 * @return The netlink message 00632 */ 00633 struct nl_msg * rtnl_neigh_build_add_request(struct rtnl_neigh *tmpl, int flags) 00634 { 00635 return build_neigh_msg(tmpl, RTM_NEWNEIGH, NLM_F_CREATE | flags); 00636 } 00637 00638 /** 00639 * Add a new neighbour 00640 * @arg handle netlink handle 00641 * @arg tmpl template with requested changes 00642 * @arg flags additional netlink message flags 00643 * 00644 * Builds a netlink message by calling rtnl_neigh_build_add_request(), 00645 * sends the request to the kernel and waits for the next ACK to be 00646 * received and thus blocks until the request has been fullfilled. 00647 * 00648 * The following attributes must be set in the template: 00649 * - Interface index (rtnl_neigh_set_ifindex()) 00650 * - State (rtnl_neigh_set_state()) 00651 * - Destination address (rtnl_neigh_set_dst()) 00652 * - Link layer address (rtnl_neigh_set_lladdr()) 00653 * 00654 * @return 0 on sucess or a negative error if an error occured. 00655 */ 00656 int rtnl_neigh_add(struct nl_handle *handle, struct rtnl_neigh *tmpl, int flags) 00657 { 00658 int err; 00659 struct nl_msg *msg; 00660 00661 msg = rtnl_neigh_build_add_request(tmpl, flags); 00662 if (!msg) 00663 return nl_errno(ENOMEM); 00664 00665 err = nl_send_auto_complete(handle, msg); 00666 if (err < 0) 00667 return err; 00668 00669 nlmsg_free(msg); 00670 return nl_wait_for_ack(handle); 00671 } 00672 00673 /** @} */ 00674 00675 /** 00676 * @name Neighbour Deletion 00677 * @{ 00678 */ 00679 00680 /** 00681 * Build a netlink request message to delete a neighbour 00682 * @arg neigh neighbour to delete 00683 * @arg flags additional netlink message flags 00684 * 00685 * Builds a new netlink message requesting a deletion of a neighbour. 00686 * The netlink message header isn't fully equipped with all relevant 00687 * fields and must thus be sent out via nl_send_auto_complete() 00688 * or supplemented as needed. \a neigh must point to an existing 00689 * neighbour. 00690 * 00691 * @return The netlink message 00692 */ 00693 struct nl_msg *rtnl_neigh_build_delete_request(struct rtnl_neigh *neigh, 00694 int flags) 00695 { 00696 return build_neigh_msg(neigh, RTM_DELNEIGH, flags); 00697 } 00698 00699 /** 00700 * Delete a neighbour 00701 * @arg handle netlink handle 00702 * @arg neigh neighbour to delete 00703 * @arg flags additional netlink message flags 00704 * 00705 * Builds a netlink message by calling rtnl_neigh_build_delete_request(), 00706 * sends the request to the kernel and waits for the next ACK to be 00707 * received and thus blocks until the request has been fullfilled. 00708 * 00709 * @return 0 on sucess or a negative error if an error occured. 00710 */ 00711 int rtnl_neigh_delete(struct nl_handle *handle, struct rtnl_neigh *neigh, 00712 int flags) 00713 { 00714 int err; 00715 struct nl_msg *msg; 00716 00717 msg = rtnl_neigh_build_delete_request(neigh, flags); 00718 if (!msg) 00719 return nl_errno(ENOMEM); 00720 00721 err = nl_send_auto_complete(handle, msg); 00722 if (err < 0) 00723 return err; 00724 00725 nlmsg_free(msg); 00726 return nl_wait_for_ack(handle); 00727 } 00728 00729 /** @} */ 00730 00731 /** 00732 * @name Neighbour Modification 00733 * @{ 00734 */ 00735 00736 /** 00737 * Build a netlink request message to change neighbour attributes 00738 * @arg neigh the neighbour to change 00739 * @arg flags additional netlink message flags 00740 * 00741 * Builds a new netlink message requesting a change of a neigh 00742 * attributes. The netlink message header isn't fully equipped with 00743 * all relevant fields and must thus be sent out via nl_send_auto_complete() 00744 * or supplemented as needed. 00745 * 00746 * @return The netlink message 00747 * @note Not all attributes can be changed, see 00748 * \ref neigh_changeable "Changeable Attributes" for a list. 00749 */ 00750 struct nl_msg *rtnl_neigh_build_change_request(struct rtnl_neigh *neigh, 00751 int flags) 00752 { 00753 return build_neigh_msg(neigh, RTM_NEWNEIGH, NLM_F_REPLACE | flags); 00754 } 00755 00756 /** 00757 * Change neighbour attributes 00758 * @arg handle netlink handle 00759 * @arg neigh neighbour to be changed 00760 * @arg flags additional netlink message flags 00761 * 00762 * Builds a netlink message by calling rtnl_neigh_build_change_request(), 00763 * sends the request to the kernel and waits for the next ACK to be 00764 * received and thus blocks until the request has been fullfilled. 00765 * 00766 * @return 0 on sucess or a negative error if an error occured. 00767 * @note Not all attributes can be changed, see 00768 * \ref neigh_changeable "Changeable Attributes" for a list. 00769 */ 00770 int rtnl_neigh_change(struct nl_handle *handle, struct rtnl_neigh *neigh, 00771 int flags) 00772 { 00773 int err; 00774 struct nl_msg *msg; 00775 00776 msg = rtnl_neigh_build_change_request(neigh, flags); 00777 if (!msg) 00778 return nl_errno(ENOMEM); 00779 00780 err = nl_send_auto_complete(handle, msg); 00781 if (err < 0) 00782 return err; 00783 00784 nlmsg_free(msg); 00785 return nl_wait_for_ack(handle); 00786 } 00787 00788 /** @} */ 00789 00790 /** 00791 * @name Neighbour States Translations 00792 * @{ 00793 */ 00794 00795 static struct trans_tbl neigh_states[] = { 00796 __ADD(NUD_INCOMPLETE, incomplete) 00797 __ADD(NUD_REACHABLE, reachable) 00798 __ADD(NUD_STALE, stale) 00799 __ADD(NUD_DELAY, delay) 00800 __ADD(NUD_PROBE, probe) 00801 __ADD(NUD_FAILED, failed) 00802 __ADD(NUD_NOARP, norarp) 00803 __ADD(NUD_PERMANENT, permanent) 00804 }; 00805 00806 char * rtnl_neigh_state2str(int state, char *buf, size_t len) 00807 { 00808 return __flags2str(state, buf, len, neigh_states, 00809 ARRAY_SIZE(neigh_states)); 00810 } 00811 00812 int rtnl_neigh_str2state(const char *name) 00813 { 00814 return __str2type(name, neigh_states, ARRAY_SIZE(neigh_states)); 00815 } 00816 00817 /** @} */ 00818 00819 /** 00820 * @name Neighbour Flags Translations 00821 * @{ 00822 */ 00823 00824 static struct trans_tbl neigh_flags[] = { 00825 __ADD(NTF_PROXY, proxy) 00826 __ADD(NTF_ROUTER, router) 00827 }; 00828 00829 char * rtnl_neigh_flags2str(int flags, char *buf, size_t len) 00830 { 00831 return __flags2str(flags, buf, len, neigh_flags, 00832 ARRAY_SIZE(neigh_flags)); 00833 } 00834 00835 int rtnl_neigh_str2flag(const char *name) 00836 { 00837 return __str2type(name, neigh_flags, ARRAY_SIZE(neigh_flags)); 00838 } 00839 00840 /** @} */ 00841 00842 /** 00843 * @name Attributes 00844 * @{ 00845 */ 00846 00847 void rtnl_neigh_set_state(struct rtnl_neigh *neigh, int state) 00848 { 00849 neigh->n_state_mask |= state; 00850 neigh->n_state |= state; 00851 neigh->ce_mask |= NEIGH_ATTR_STATE; 00852 } 00853 00854 int rtnl_neigh_get_state(struct rtnl_neigh *neigh) 00855 { 00856 if (neigh->ce_mask & NEIGH_ATTR_STATE) 00857 return neigh->n_state; 00858 else 00859 return -1; 00860 } 00861 00862 void rtnl_neigh_unset_state(struct rtnl_neigh *neigh, int state) 00863 { 00864 neigh->n_state_mask |= state; 00865 neigh->n_state &= ~state; 00866 neigh->ce_mask |= NEIGH_ATTR_STATE; 00867 } 00868 00869 void rtnl_neigh_set_flags(struct rtnl_neigh *neigh, unsigned int flags) 00870 { 00871 neigh->n_flag_mask |= flags; 00872 neigh->n_flags |= flags; 00873 neigh->ce_mask |= NEIGH_ATTR_FLAGS; 00874 } 00875 00876 unsigned int rtnl_neigh_get_flags(struct rtnl_neigh *neigh) 00877 { 00878 return neigh->n_flags; 00879 } 00880 00881 void rtnl_neigh_unset_flags(struct rtnl_neigh *neigh, unsigned int flags) 00882 { 00883 neigh->n_flag_mask |= flags; 00884 neigh->n_flags &= ~flags; 00885 neigh->ce_mask |= NEIGH_ATTR_FLAGS; 00886 } 00887 00888 void rtnl_neigh_set_ifindex(struct rtnl_neigh *neigh, int ifindex) 00889 { 00890 neigh->n_ifindex = ifindex; 00891 neigh->ce_mask |= NEIGH_ATTR_IFINDEX; 00892 } 00893 00894 int rtnl_neigh_get_ifindex(struct rtnl_neigh *neigh) 00895 { 00896 if (neigh->ce_mask & NEIGH_ATTR_IFINDEX) 00897 return neigh->n_ifindex; 00898 else 00899 return RTNL_LINK_NOT_FOUND; 00900 } 00901 00902 static inline int __assign_addr(struct rtnl_neigh *neigh, struct nl_addr **pos, 00903 struct nl_addr *new, int flag, int nocheck) 00904 { 00905 if (!nocheck) { 00906 if (neigh->ce_mask & NEIGH_ATTR_FAMILY) { 00907 if (new->a_family != neigh->n_family) 00908 return nl_error(EINVAL, 00909 "Address family mismatch"); 00910 } else { 00911 neigh->n_family = new->a_family; 00912 neigh->ce_mask |= NEIGH_ATTR_FAMILY; 00913 } 00914 } 00915 00916 if (*pos) 00917 nl_addr_put(*pos); 00918 00919 nl_addr_get(new); 00920 *pos = new; 00921 00922 neigh->ce_mask |= flag; 00923 00924 return 0; 00925 } 00926 00927 void rtnl_neigh_set_lladdr(struct rtnl_neigh *neigh, struct nl_addr *addr) 00928 { 00929 __assign_addr(neigh, &neigh->n_lladdr, addr, NEIGH_ATTR_LLADDR, 1); 00930 } 00931 00932 struct nl_addr *rtnl_neigh_get_lladdr(struct rtnl_neigh *neigh) 00933 { 00934 if (neigh->ce_mask & NEIGH_ATTR_LLADDR) 00935 return neigh->n_lladdr; 00936 else 00937 return NULL; 00938 } 00939 00940 int rtnl_neigh_set_dst(struct rtnl_neigh *neigh, struct nl_addr *addr) 00941 { 00942 return __assign_addr(neigh, &neigh->n_dst, addr, 00943 NEIGH_ATTR_DST, 0); 00944 } 00945 00946 struct nl_addr *rtnl_neigh_get_dst(struct rtnl_neigh *neigh) 00947 { 00948 if (neigh->ce_mask & NEIGH_ATTR_DST) 00949 return neigh->n_dst; 00950 else 00951 return NULL; 00952 } 00953 00954 void rtnl_neigh_set_family(struct rtnl_neigh *neigh, int family) 00955 { 00956 neigh->n_family = family; 00957 neigh->ce_mask |= NEIGH_ATTR_FAMILY; 00958 } 00959 00960 void rtnl_neigh_set_type(struct rtnl_neigh *neigh, int type) 00961 { 00962 neigh->n_type = type; 00963 neigh->ce_mask = NEIGH_ATTR_TYPE; 00964 } 00965 00966 int rtnl_neigh_get_type(struct rtnl_neigh *neigh) 00967 { 00968 if (neigh->ce_mask & NEIGH_ATTR_TYPE) 00969 return neigh->n_type; 00970 else 00971 return -1; 00972 } 00973 00974 /** @} */ 00975 00976 static struct nl_object_ops neigh_obj_ops = { 00977 .oo_name = "route/neigh", 00978 .oo_size = sizeof(struct rtnl_neigh), 00979 .oo_free_data = neigh_free_data, 00980 .oo_clone = neigh_clone, 00981 .oo_dump[NL_DUMP_BRIEF] = neigh_dump_brief, 00982 .oo_dump[NL_DUMP_FULL] = neigh_dump_full, 00983 .oo_dump[NL_DUMP_STATS] = neigh_dump_stats, 00984 .oo_dump[NL_DUMP_XML] = neigh_dump_xml, 00985 .oo_dump[NL_DUMP_ENV] = neigh_dump_env, 00986 .oo_compare = neigh_compare, 00987 .oo_attrs2str = neigh_attrs2str, 00988 .oo_id_attrs = (NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY), 00989 }; 00990 00991 static struct nl_af_group neigh_groups[] = { 00992 { AF_UNSPEC, RTNLGRP_NEIGH }, 00993 { END_OF_GROUP_LIST }, 00994 }; 00995 00996 static struct nl_cache_ops rtnl_neigh_ops = { 00997 .co_name = "route/neigh", 00998 .co_hdrsize = sizeof(struct ndmsg), 00999 .co_msgtypes = { 01000 { RTM_NEWNEIGH, NL_ACT_NEW, "new" }, 01001 { RTM_DELNEIGH, NL_ACT_DEL, "del" }, 01002 { RTM_GETNEIGH, NL_ACT_GET, "get" }, 01003 END_OF_MSGTYPES_LIST, 01004 }, 01005 .co_protocol = NETLINK_ROUTE, 01006 .co_groups = neigh_groups, 01007 .co_request_update = neigh_request_update, 01008 .co_msg_parser = neigh_msg_parser, 01009 .co_obj_ops = &neigh_obj_ops, 01010 }; 01011 01012 static void __init neigh_init(void) 01013 { 01014 nl_cache_mngt_register(&rtnl_neigh_ops); 01015 } 01016 01017 static void __exit neigh_exit(void) 01018 { 01019 nl_cache_mngt_unregister(&rtnl_neigh_ops); 01020 } 01021 01022 /** @} */