neigh.c revision 5d82806b48959e4726ae3913ae0b3ce279c4c04a
1/* 2 * lib/route/neigh.c Neighbours 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2003-2008 Thomas Graf <tgraf@suug.ch> 10 */ 11 12/** 13 * @ingroup rtnl 14 * @defgroup neigh Neighbours 15 * @brief 16 * 17 * The neighbour table establishes bindings between protocol addresses and 18 * link layer addresses for hosts sharing the same physical link. This 19 * module allows you to access and manipulate the content of these tables. 20 * 21 * @par Neighbour States 22 * @code 23 * NUD_INCOMPLETE 24 * NUD_REACHABLE 25 * NUD_STALE 26 * NUD_DELAY 27 * NUD_PROBE 28 * NUD_FAILED 29 * NUD_NOARP 30 * NUD_PERMANENT 31 * @endcode 32 * 33 * @par Neighbour Flags 34 * @code 35 * NTF_PROXY 36 * NTF_ROUTER 37 * @endcode 38 * 39 * @par Neighbour Identification 40 * A neighbour is uniquely identified by the attributes listed below, whenever 41 * you refer to an existing neighbour all of the attributes must be set. 42 * Neighbours from caches automatically have all required attributes set. 43 * - interface index (rtnl_neigh_set_ifindex()) 44 * - destination address (rtnl_neigh_set_dst()) 45 * 46 * @par Changeable Attributes 47 * \anchor neigh_changeable 48 * - state (rtnl_neigh_set_state()) 49 * - link layer address (rtnl_neigh_set_lladdr()) 50 * 51 * @par Required Caches for Dumping 52 * In order to dump neighbour attributes you must provide the following 53 * caches via nl_cache_provide() 54 * - link cache holding all links 55 * 56 * @par TODO 57 * - Document proxy settings 58 * - Document states and their influence 59 * 60 * @par 1) Retrieving information about configured neighbours 61 * @code 62 * // The first step is to retrieve a list of all available neighbour within 63 * // the kernel and put them into a cache. 64 * struct nl_cache *cache = rtnl_neigh_alloc_cache(sk); 65 * 66 * // Neighbours can then be looked up by the interface and destination 67 * // address: 68 * struct rtnl_neigh *neigh = rtnl_neigh_get(cache, ifindex, dst_addr); 69 * 70 * // After successful usage, the object must be given back to the cache 71 * rtnl_neigh_put(neigh); 72 * @endcode 73 * 74 * @par 2) Adding new neighbours 75 * @code 76 * // Allocate an empty neighbour handle to be filled out with the attributes 77 * // of the new neighbour. 78 * struct rtnl_neigh *neigh = rtnl_neigh_alloc(); 79 * 80 * // Fill out the attributes of the new neighbour 81 * rtnl_neigh_set_ifindex(neigh, ifindex); 82 * rtnl_neigh_set_dst(neigh, dst_addr); 83 * rtnl_neigh_set_state(neigh, rtnl_neigh_str2state("permanent")); 84 * 85 * // Build the netlink message and send it to the kernel, the operation will 86 * // block until the operation has been completed. Alternatively the required 87 * // netlink message can be built using rtnl_neigh_build_add_request() 88 * // to be sent out using nl_send_auto_complete(). 89 * rtnl_neigh_add(sk, neigh, NLM_F_REPLACE); 90 * 91 * // Free the memory 92 * rtnl_neigh_put(neigh); 93 * @endcode 94 * 95 * @par 3) Deleting an existing neighbour 96 * @code 97 * // Allocate an empty neighbour object to be filled out with the attributes 98 * // matching the neighbour to be deleted. Alternatively a fully equipped 99 * // neighbour object out of a cache can be used instead. 100 * struct rtnl_neigh *neigh = rtnl_neigh_alloc(); 101 * 102 * // Neighbours are uniquely identified by their interface index and 103 * // destination address, you may fill out other attributes but they 104 * // will have no influence. 105 * rtnl_neigh_set_ifindex(neigh, ifindex); 106 * rtnl_neigh_set_dst(neigh, dst_addr); 107 * 108 * // Build the netlink message and send it to the kernel, the operation will 109 * // block until the operation has been completed. Alternatively the required 110 * // netlink message can be built using rtnl_neigh_build_delete_request() 111 * // to be sent out using nl_send_auto_complete(). 112 * rtnl_neigh_delete(sk, neigh, 0); 113 * 114 * // Free the memory 115 * rtnl_neigh_put(neigh); 116 * @endcode 117 * 118 * @par 4) Changing neighbour attributes 119 * @code 120 * // Allocate an empty neighbour object to be filled out with the attributes 121 * // matching the neighbour to be changed and the new parameters. Alternatively 122 * // a fully equipped modified neighbour object out of a cache can be used. 123 * struct rtnl_neigh *neigh = rtnl_neigh_alloc(); 124 * 125 * // Identify the neighbour to be changed by its interface index and 126 * // destination address 127 * rtnl_neigh_set_ifindex(neigh, ifindex); 128 * rtnl_neigh_set_dst(neigh, dst_addr); 129 * 130 * // The link layer address may be modified, if so it is wise to change 131 * // its state to "permanent" in order to avoid having it overwritten. 132 * rtnl_neigh_set_lladdr(neigh, lladdr); 133 * 134 * // Secondly the state can be modified allowing normal neighbours to be 135 * // converted into permanent entries or to manually confirm a neighbour. 136 * rtnl_neigh_set_state(neigh, state); 137 * 138 * // Build the netlink message and send it to the kernel, the operation will 139 * // block until the operation has been completed. Alternatively the required 140 * // netlink message can be built using rtnl_neigh_build_change_request() 141 * // to be sent out using nl_send_auto_complete(). 142 * rtnl_neigh_change(sk, neigh, 0); 143 * 144 * // Free the memory 145 * rtnl_neigh_put(neigh); 146 * @endcode 147 * @{ 148 */ 149 150#include <netlink-local.h> 151#include <netlink/netlink.h> 152#include <netlink/utils.h> 153#include <netlink/route/rtnl.h> 154#include <netlink/route/neighbour.h> 155#include <netlink/route/link.h> 156 157/** @cond SKIP */ 158#define NEIGH_ATTR_FLAGS 0x01 159#define NEIGH_ATTR_STATE 0x02 160#define NEIGH_ATTR_LLADDR 0x04 161#define NEIGH_ATTR_DST 0x08 162#define NEIGH_ATTR_CACHEINFO 0x10 163#define NEIGH_ATTR_IFINDEX 0x20 164#define NEIGH_ATTR_FAMILY 0x40 165#define NEIGH_ATTR_TYPE 0x80 166#define NEIGH_ATTR_PROBES 0x100 167 168static struct nl_cache_ops rtnl_neigh_ops; 169static struct nl_object_ops neigh_obj_ops; 170/** @endcond */ 171 172static void neigh_free_data(struct nl_object *c) 173{ 174 struct rtnl_neigh *neigh = nl_object_priv(c); 175 176 if (!neigh) 177 return; 178 179 nl_addr_put(neigh->n_lladdr); 180 nl_addr_put(neigh->n_dst); 181} 182 183static int neigh_clone(struct nl_object *_dst, struct nl_object *_src) 184{ 185 struct rtnl_neigh *dst = nl_object_priv(_dst); 186 struct rtnl_neigh *src = nl_object_priv(_src); 187 188 if (src->n_lladdr) 189 if (!(dst->n_lladdr = nl_addr_clone(src->n_lladdr))) 190 return -NLE_NOMEM; 191 192 if (src->n_dst) 193 if (!(dst->n_dst = nl_addr_clone(src->n_dst))) 194 return -NLE_NOMEM; 195 196 return 0; 197} 198 199static int neigh_compare(struct nl_object *_a, struct nl_object *_b, 200 uint32_t attrs, int flags) 201{ 202 struct rtnl_neigh *a = (struct rtnl_neigh *) _a; 203 struct rtnl_neigh *b = (struct rtnl_neigh *) _b; 204 int diff = 0; 205 206#define NEIGH_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, NEIGH_ATTR_##ATTR, a, b, EXPR) 207 208 diff |= NEIGH_DIFF(IFINDEX, a->n_ifindex != b->n_ifindex); 209 diff |= NEIGH_DIFF(FAMILY, a->n_family != b->n_family); 210 diff |= NEIGH_DIFF(TYPE, a->n_type != b->n_type); 211 diff |= NEIGH_DIFF(LLADDR, nl_addr_cmp(a->n_lladdr, b->n_lladdr)); 212 diff |= NEIGH_DIFF(DST, nl_addr_cmp(a->n_dst, b->n_dst)); 213 214 if (flags & LOOSE_COMPARISON) { 215 diff |= NEIGH_DIFF(STATE, 216 (a->n_state ^ b->n_state) & b->n_state_mask); 217 diff |= NEIGH_DIFF(FLAGS, 218 (a->n_flags ^ b->n_flags) & b->n_flag_mask); 219 } else { 220 diff |= NEIGH_DIFF(STATE, a->n_state != b->n_state); 221 diff |= NEIGH_DIFF(FLAGS, a->n_flags != b->n_flags); 222 } 223 224#undef NEIGH_DIFF 225 226 return diff; 227} 228 229static struct trans_tbl neigh_attrs[] = { 230 __ADD(NEIGH_ATTR_FLAGS, flags) 231 __ADD(NEIGH_ATTR_STATE, state) 232 __ADD(NEIGH_ATTR_LLADDR, lladdr) 233 __ADD(NEIGH_ATTR_DST, dst) 234 __ADD(NEIGH_ATTR_CACHEINFO, cacheinfo) 235 __ADD(NEIGH_ATTR_IFINDEX, ifindex) 236 __ADD(NEIGH_ATTR_FAMILY, family) 237 __ADD(NEIGH_ATTR_TYPE, type) 238 __ADD(NEIGH_ATTR_PROBES, probes) 239}; 240 241static char *neigh_attrs2str(int attrs, char *buf, size_t len) 242{ 243 return __flags2str(attrs, buf, len, neigh_attrs, 244 ARRAY_SIZE(neigh_attrs)); 245} 246 247static struct nla_policy neigh_policy[NDA_MAX+1] = { 248 [NDA_CACHEINFO] = { .minlen = sizeof(struct nda_cacheinfo) }, 249 [NDA_PROBES] = { .type = NLA_U32 }, 250}; 251 252static int neigh_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 253 struct nlmsghdr *n, struct nl_parser_param *pp) 254{ 255 struct rtnl_neigh *neigh; 256 struct nlattr *tb[NDA_MAX + 1]; 257 struct ndmsg *nm; 258 int err; 259 260 neigh = rtnl_neigh_alloc(); 261 if (!neigh) { 262 err = -NLE_NOMEM; 263 goto errout; 264 } 265 266 neigh->ce_msgtype = n->nlmsg_type; 267 nm = nlmsg_data(n); 268 269 err = nlmsg_parse(n, sizeof(*nm), tb, NDA_MAX, neigh_policy); 270 if (err < 0) 271 goto errout; 272 273 neigh->n_family = nm->ndm_family; 274 neigh->n_ifindex = nm->ndm_ifindex; 275 neigh->n_state = nm->ndm_state; 276 neigh->n_flags = nm->ndm_flags; 277 neigh->n_type = nm->ndm_type; 278 279 neigh->ce_mask |= (NEIGH_ATTR_FAMILY | NEIGH_ATTR_IFINDEX | 280 NEIGH_ATTR_STATE | NEIGH_ATTR_FLAGS | 281 NEIGH_ATTR_TYPE); 282 283 if (tb[NDA_LLADDR]) { 284 neigh->n_lladdr = nl_addr_alloc_attr(tb[NDA_LLADDR], AF_UNSPEC); 285 if (!neigh->n_lladdr) { 286 err = -NLE_NOMEM; 287 goto errout; 288 } 289 nl_addr_set_family(neigh->n_lladdr, 290 nl_addr_guess_family(neigh->n_lladdr)); 291 neigh->ce_mask |= NEIGH_ATTR_LLADDR; 292 } 293 294 if (tb[NDA_DST]) { 295 neigh->n_dst = nl_addr_alloc_attr(tb[NDA_DST], neigh->n_family); 296 if (!neigh->n_dst) { 297 err = -NLE_NOMEM; 298 goto errout; 299 } 300 neigh->ce_mask |= NEIGH_ATTR_DST; 301 } 302 303 if (tb[NDA_CACHEINFO]) { 304 struct nda_cacheinfo *ci = nla_data(tb[NDA_CACHEINFO]); 305 306 neigh->n_cacheinfo.nci_confirmed = ci->ndm_confirmed; 307 neigh->n_cacheinfo.nci_used = ci->ndm_used; 308 neigh->n_cacheinfo.nci_updated = ci->ndm_updated; 309 neigh->n_cacheinfo.nci_refcnt = ci->ndm_refcnt; 310 311 neigh->ce_mask |= NEIGH_ATTR_CACHEINFO; 312 } 313 314 if (tb[NDA_PROBES]) { 315 neigh->n_probes = nla_get_u32(tb[NDA_PROBES]); 316 neigh->ce_mask |= NEIGH_ATTR_PROBES; 317 } 318 319 err = pp->pp_cb((struct nl_object *) neigh, pp); 320errout: 321 rtnl_neigh_put(neigh); 322 return err; 323} 324 325static int neigh_request_update(struct nl_cache *c, struct nl_sock *h) 326{ 327 return nl_rtgen_request(h, RTM_GETNEIGH, AF_UNSPEC, NLM_F_DUMP); 328} 329 330 331static int neigh_dump_brief(struct nl_object *a, struct nl_dump_params *p) 332{ 333 char dst[INET6_ADDRSTRLEN+5], lladdr[INET6_ADDRSTRLEN+5]; 334 struct rtnl_neigh *n = (struct rtnl_neigh *) a; 335 struct nl_cache *link_cache; 336 char state[128], flags[64]; 337 338 link_cache = nl_cache_mngt_require("route/link"); 339 340 dp_dump(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst))); 341 342 if (link_cache) 343 dp_dump(p, "dev %s ", 344 rtnl_link_i2name(link_cache, n->n_ifindex, 345 state, sizeof(state))); 346 else 347 dp_dump(p, "dev %d ", n->n_ifindex); 348 349 if (n->ce_mask & NEIGH_ATTR_LLADDR) 350 dp_dump(p, "lladdr %s ", 351 nl_addr2str(n->n_lladdr, lladdr, sizeof(lladdr))); 352 353 rtnl_neigh_state2str(n->n_state, state, sizeof(state)); 354 rtnl_neigh_flags2str(n->n_flags, flags, sizeof(flags)); 355 356 if (state[0]) 357 dp_dump(p, "<%s", state); 358 if (flags[0]) 359 dp_dump(p, "%s%s", state[0] ? "," : "<", flags); 360 if (state[0] || flags[0]) 361 dp_dump(p, ">"); 362 dp_dump(p, "\n"); 363 364 return 1; 365} 366 367static int neigh_dump_full(struct nl_object *a, struct nl_dump_params *p) 368{ 369 char rtn_type[32]; 370 struct rtnl_neigh *n = (struct rtnl_neigh *) a; 371 int hz = nl_get_hz(); 372 373 int line = neigh_dump_brief(a, p); 374 375 dp_dump_line(p, line++, " refcnt %u type %s confirmed %u used " 376 "%u updated %u\n", 377 n->n_cacheinfo.nci_refcnt, 378 nl_rtntype2str(n->n_type, rtn_type, sizeof(rtn_type)), 379 n->n_cacheinfo.nci_confirmed/hz, 380 n->n_cacheinfo.nci_used/hz, n->n_cacheinfo.nci_updated/hz); 381 382 return line; 383} 384 385static int neigh_dump_stats(struct nl_object *a, struct nl_dump_params *p) 386{ 387 return neigh_dump_full(a, p); 388} 389 390static int neigh_dump_xml(struct nl_object *obj, struct nl_dump_params *p) 391{ 392 struct rtnl_neigh *neigh = (struct rtnl_neigh *) obj; 393 char buf[128]; 394 int line = 0; 395 396 dp_dump_line(p, line++, "<neighbour>\n"); 397 dp_dump_line(p, line++, " <family>%s</family>\n", 398 nl_af2str(neigh->n_family, buf, sizeof(buf))); 399 400 if (neigh->ce_mask & NEIGH_ATTR_LLADDR) 401 dp_dump_line(p, line++, " <lladdr>%s</lladdr>\n", 402 nl_addr2str(neigh->n_lladdr, buf, sizeof(buf))); 403 404 if (neigh->ce_mask & NEIGH_ATTR_DST) 405 dp_dump_line(p, line++, " <dst>%s</dst>\n", 406 nl_addr2str(neigh->n_dst, buf, sizeof(buf))); 407 408 if (neigh->ce_mask & NEIGH_ATTR_IFINDEX) { 409 struct nl_cache *link_cache; 410 411 link_cache = nl_cache_mngt_require("route/link"); 412 413 if (link_cache) 414 dp_dump_line(p, line++, " <device>%s</device>\n", 415 rtnl_link_i2name(link_cache, 416 neigh->n_ifindex, 417 buf, sizeof(buf))); 418 else 419 dp_dump_line(p, line++, " <device>%u</device>\n", 420 neigh->n_ifindex); 421 } 422 423 if (neigh->ce_mask & NEIGH_ATTR_PROBES) 424 dp_dump_line(p, line++, " <probes>%u</probes>\n", 425 neigh->n_probes); 426 427 if (neigh->ce_mask & NEIGH_ATTR_TYPE) 428 dp_dump_line(p, line++, " <type>%s</type>\n", 429 nl_rtntype2str(neigh->n_type, buf, sizeof(buf))); 430 431 rtnl_neigh_flags2str(neigh->n_flags, buf, sizeof(buf)); 432 if (buf[0]) 433 dp_dump_line(p, line++, " <flags>%s</flags>\n", buf); 434 435 rtnl_neigh_state2str(neigh->n_state, buf, sizeof(buf)); 436 if (buf[0]) 437 dp_dump_line(p, line++, " <state>%s</state>\n", buf); 438 439 dp_dump_line(p, line++, "</neighbour>\n"); 440 441#if 0 442 struct rtnl_ncacheinfo n_cacheinfo; 443#endif 444 445 return line; 446} 447 448static int neigh_dump_env(struct nl_object *obj, struct nl_dump_params *p) 449{ 450 struct rtnl_neigh *neigh = (struct rtnl_neigh *) obj; 451 char buf[128]; 452 int line = 0; 453 454 dp_dump_line(p, line++, "NEIGH_FAMILY=%s\n", 455 nl_af2str(neigh->n_family, buf, sizeof(buf))); 456 457 if (neigh->ce_mask & NEIGH_ATTR_LLADDR) 458 dp_dump_line(p, line++, "NEIGHT_LLADDR=%s\n", 459 nl_addr2str(neigh->n_lladdr, buf, sizeof(buf))); 460 461 if (neigh->ce_mask & NEIGH_ATTR_DST) 462 dp_dump_line(p, line++, "NEIGH_DST=%s\n", 463 nl_addr2str(neigh->n_dst, buf, sizeof(buf))); 464 465 if (neigh->ce_mask & NEIGH_ATTR_IFINDEX) { 466 struct nl_cache *link_cache; 467 468 dp_dump_line(p, line++, "NEIGH_IFINDEX=%u\n", 469 neigh->n_ifindex); 470 471 link_cache = nl_cache_mngt_require("route/link"); 472 if (link_cache) 473 dp_dump_line(p, line++, "NEIGH_IFNAME=%s\n", 474 rtnl_link_i2name(link_cache, 475 neigh->n_ifindex, 476 buf, sizeof(buf))); 477 } 478 479 if (neigh->ce_mask & NEIGH_ATTR_PROBES) 480 dp_dump_line(p, line++, "NEIGH_PROBES=%u\n", 481 neigh->n_probes); 482 483 if (neigh->ce_mask & NEIGH_ATTR_TYPE) 484 dp_dump_line(p, line++, "NEIGH_TYPE=%s\n", 485 nl_rtntype2str(neigh->n_type, buf, sizeof(buf))); 486 487 rtnl_neigh_flags2str(neigh->n_flags, buf, sizeof(buf)); 488 if (buf[0]) 489 dp_dump_line(p, line++, "NEIGH_FLAGS=%s\n", buf); 490 491 rtnl_neigh_state2str(neigh->n_state, buf, sizeof(buf)); 492 if (buf[0]) 493 dp_dump_line(p, line++, "NEIGH_STATE=%s\n", buf); 494 495 return line; 496} 497 498/** 499 * @name Neighbour Object Allocation/Freeage 500 * @{ 501 */ 502 503struct rtnl_neigh *rtnl_neigh_alloc(void) 504{ 505 return (struct rtnl_neigh *) nl_object_alloc(&neigh_obj_ops); 506} 507 508void rtnl_neigh_put(struct rtnl_neigh *neigh) 509{ 510 nl_object_put((struct nl_object *) neigh); 511} 512 513/** @} */ 514 515/** 516 * @name Neighbour Cache Managament 517 * @{ 518 */ 519 520/** 521 * Build a neighbour cache including all neighbours currently configured in the kernel. 522 * @arg sk Netlink socket. 523 * @arg result Pointer to store resulting cache. 524 * 525 * Allocates a new neighbour cache, initializes it properly and updates it 526 * to include all neighbours currently configured in the kernel. 527 * 528 * @return 0 on success or a negative error code. 529 */ 530int rtnl_neigh_alloc_cache(struct nl_sock *sock, struct nl_cache **result) 531{ 532 return nl_cache_alloc_and_fill(&rtnl_neigh_ops, sock, result); 533} 534 535/** 536 * Look up a neighbour by interface index and destination address 537 * @arg cache neighbour cache 538 * @arg ifindex interface index the neighbour is on 539 * @arg dst destination address of the neighbour 540 * @return neighbour handle or NULL if no match was found. 541 */ 542struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex, 543 struct nl_addr *dst) 544{ 545 struct rtnl_neigh *neigh; 546 547 nl_list_for_each_entry(neigh, &cache->c_items, ce_list) { 548 if (neigh->n_ifindex == ifindex && 549 !nl_addr_cmp(neigh->n_dst, dst)) { 550 nl_object_get((struct nl_object *) neigh); 551 return neigh; 552 } 553 } 554 555 return NULL; 556} 557 558/** @} */ 559 560/** 561 * @name Neighbour Addition 562 * @{ 563 */ 564 565static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags, 566 struct nl_msg **result) 567{ 568 struct nl_msg *msg; 569 struct ndmsg nhdr = { 570 .ndm_ifindex = tmpl->n_ifindex, 571 .ndm_family = nl_addr_get_family(tmpl->n_dst), 572 .ndm_state = NUD_PERMANENT, 573 }; 574 575 if (tmpl->ce_mask & NEIGH_ATTR_STATE) 576 nhdr.ndm_state = tmpl->n_state; 577 578 msg = nlmsg_alloc_simple(cmd, flags); 579 if (!msg) 580 return -NLE_NOMEM; 581 582 if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0) 583 goto nla_put_failure; 584 585 NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst); 586 587 if (tmpl->ce_mask & NEIGH_ATTR_LLADDR) 588 NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr); 589 590 *result = msg; 591 return 0; 592 593nla_put_failure: 594 nlmsg_free(msg); 595 return -NLE_MSGSIZE; 596} 597 598/** 599 * Build netlink request message to add a new neighbour 600 * @arg tmpl template with data of new neighbour 601 * @arg flags additional netlink message flags 602 * @arg result Pointer to store resulting message. 603 * 604 * Builds a new netlink message requesting a addition of a new 605 * neighbour. The netlink message header isn't fully equipped with 606 * all relevant fields and must thus be sent out via nl_send_auto_complete() 607 * or supplemented as needed. \a tmpl must contain the attributes of the new 608 * neighbour set via \c rtnl_neigh_set_* functions. 609 * 610 * The following attributes must be set in the template: 611 * - Interface index (rtnl_neigh_set_ifindex()) 612 * - State (rtnl_neigh_set_state()) 613 * - Destination address (rtnl_neigh_set_dst()) 614 * - Link layer address (rtnl_neigh_set_lladdr()) 615 * 616 * @return 0 on success or a negative error code. 617 */ 618int rtnl_neigh_build_add_request(struct rtnl_neigh *tmpl, int flags, 619 struct nl_msg **result) 620{ 621 return build_neigh_msg(tmpl, RTM_NEWNEIGH, NLM_F_CREATE | flags, 622 result); 623} 624 625/** 626 * Add a new neighbour 627 * @arg sk Netlink socket. 628 * @arg tmpl template with requested changes 629 * @arg flags additional netlink message flags 630 * 631 * Builds a netlink message by calling rtnl_neigh_build_add_request(), 632 * sends the request to the kernel and waits for the next ACK to be 633 * received and thus blocks until the request has been fullfilled. 634 * 635 * The following attributes must be set in the template: 636 * - Interface index (rtnl_neigh_set_ifindex()) 637 * - State (rtnl_neigh_set_state()) 638 * - Destination address (rtnl_neigh_set_dst()) 639 * - Link layer address (rtnl_neigh_set_lladdr()) 640 * 641 * @return 0 on sucess or a negative error if an error occured. 642 */ 643int rtnl_neigh_add(struct nl_sock *sk, struct rtnl_neigh *tmpl, int flags) 644{ 645 int err; 646 struct nl_msg *msg; 647 648 if ((err = rtnl_neigh_build_add_request(tmpl, flags, &msg)) < 0) 649 return err; 650 651 err = nl_send_auto_complete(sk, msg); 652 nlmsg_free(msg); 653 if (err < 0) 654 return err; 655 656 return nl_wait_for_ack(sk); 657} 658 659/** @} */ 660 661/** 662 * @name Neighbour Deletion 663 * @{ 664 */ 665 666/** 667 * Build a netlink request message to delete a neighbour 668 * @arg neigh neighbour to delete 669 * @arg flags additional netlink message flags 670 * @arg result Pointer to store resulting message. 671 * 672 * Builds a new netlink message requesting a deletion of a neighbour. 673 * The netlink message header isn't fully equipped with all relevant 674 * fields and must thus be sent out via nl_send_auto_complete() 675 * or supplemented as needed. \a neigh must point to an existing 676 * neighbour. 677 * 678 * @return 0 on success or a negative error code. 679 */ 680int rtnl_neigh_build_delete_request(struct rtnl_neigh *neigh, int flags, 681 struct nl_msg **result) 682{ 683 return build_neigh_msg(neigh, RTM_DELNEIGH, flags, result); 684} 685 686/** 687 * Delete a neighbour 688 * @arg sk Netlink socket. 689 * @arg neigh neighbour to delete 690 * @arg flags additional netlink message flags 691 * 692 * Builds a netlink message by calling rtnl_neigh_build_delete_request(), 693 * sends the request to the kernel and waits for the next ACK to be 694 * received and thus blocks until the request has been fullfilled. 695 * 696 * @return 0 on sucess or a negative error if an error occured. 697 */ 698int rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh, 699 int flags) 700{ 701 struct nl_msg *msg; 702 int err; 703 704 if ((err = rtnl_neigh_build_delete_request(neigh, flags, &msg)) < 0) 705 return err; 706 707 err = nl_send_auto_complete(sk, msg); 708 nlmsg_free(msg); 709 if (err < 0) 710 return err; 711 712 return nl_wait_for_ack(sk); 713} 714 715/** @} */ 716 717/** 718 * @name Neighbour Modification 719 * @{ 720 */ 721 722/** 723 * Build a netlink request message to change neighbour attributes 724 * @arg neigh the neighbour to change 725 * @arg flags additional netlink message flags 726 * @arg result Pointer to store resulting message. 727 * 728 * Builds a new netlink message requesting a change of a neigh 729 * attributes. The netlink message header isn't fully equipped with 730 * all relevant fields and must thus be sent out via nl_send_auto_complete() 731 * or supplemented as needed. 732 * 733 * @note Not all attributes can be changed, see 734 * \ref neigh_changeable "Changeable Attributes" for a list. 735 * 736 * @return 0 on success or a negative error code. 737 */ 738int rtnl_neigh_build_change_request(struct rtnl_neigh *neigh, int flags, 739 struct nl_msg **result) 740{ 741 return build_neigh_msg(neigh, RTM_NEWNEIGH, NLM_F_REPLACE | flags, 742 result); 743} 744 745/** 746 * Change neighbour attributes 747 * @arg sk Netlink socket. 748 * @arg neigh neighbour to be changed 749 * @arg flags additional netlink message flags 750 * 751 * Builds a netlink message by calling rtnl_neigh_build_change_request(), 752 * sends the request to the kernel and waits for the next ACK to be 753 * received and thus blocks until the request has been fullfilled. 754 * 755 * @return 0 on sucess or a negative error if an error occured. 756 * @note Not all attributes can be changed, see 757 * \ref neigh_changeable "Changeable Attributes" for a list. 758 */ 759int rtnl_neigh_change(struct nl_sock *sk, struct rtnl_neigh *neigh, int flags) 760{ 761 struct nl_msg *msg; 762 int err; 763 764 if ((err = rtnl_neigh_build_change_request(neigh, flags, &msg)) < 0) 765 return err; 766 767 err = nl_send_auto_complete(sk, msg); 768 nlmsg_free(msg); 769 if (err < 0) 770 return err; 771 772 return nl_wait_for_ack(sk); 773} 774 775/** @} */ 776 777/** 778 * @name Neighbour States Translations 779 * @{ 780 */ 781 782static struct trans_tbl neigh_states[] = { 783 __ADD(NUD_INCOMPLETE, incomplete) 784 __ADD(NUD_REACHABLE, reachable) 785 __ADD(NUD_STALE, stale) 786 __ADD(NUD_DELAY, delay) 787 __ADD(NUD_PROBE, probe) 788 __ADD(NUD_FAILED, failed) 789 __ADD(NUD_NOARP, norarp) 790 __ADD(NUD_PERMANENT, permanent) 791}; 792 793char * rtnl_neigh_state2str(int state, char *buf, size_t len) 794{ 795 return __flags2str(state, buf, len, neigh_states, 796 ARRAY_SIZE(neigh_states)); 797} 798 799int rtnl_neigh_str2state(const char *name) 800{ 801 return __str2type(name, neigh_states, ARRAY_SIZE(neigh_states)); 802} 803 804/** @} */ 805 806/** 807 * @name Neighbour Flags Translations 808 * @{ 809 */ 810 811static struct trans_tbl neigh_flags[] = { 812 __ADD(NTF_PROXY, proxy) 813 __ADD(NTF_ROUTER, router) 814}; 815 816char * rtnl_neigh_flags2str(int flags, char *buf, size_t len) 817{ 818 return __flags2str(flags, buf, len, neigh_flags, 819 ARRAY_SIZE(neigh_flags)); 820} 821 822int rtnl_neigh_str2flag(const char *name) 823{ 824 return __str2type(name, neigh_flags, ARRAY_SIZE(neigh_flags)); 825} 826 827/** @} */ 828 829/** 830 * @name Attributes 831 * @{ 832 */ 833 834void rtnl_neigh_set_state(struct rtnl_neigh *neigh, int state) 835{ 836 neigh->n_state_mask |= state; 837 neigh->n_state |= state; 838 neigh->ce_mask |= NEIGH_ATTR_STATE; 839} 840 841int rtnl_neigh_get_state(struct rtnl_neigh *neigh) 842{ 843 if (neigh->ce_mask & NEIGH_ATTR_STATE) 844 return neigh->n_state; 845 else 846 return -1; 847} 848 849void rtnl_neigh_unset_state(struct rtnl_neigh *neigh, int state) 850{ 851 neigh->n_state_mask |= state; 852 neigh->n_state &= ~state; 853 neigh->ce_mask |= NEIGH_ATTR_STATE; 854} 855 856void rtnl_neigh_set_flags(struct rtnl_neigh *neigh, unsigned int flags) 857{ 858 neigh->n_flag_mask |= flags; 859 neigh->n_flags |= flags; 860 neigh->ce_mask |= NEIGH_ATTR_FLAGS; 861} 862 863unsigned int rtnl_neigh_get_flags(struct rtnl_neigh *neigh) 864{ 865 return neigh->n_flags; 866} 867 868void rtnl_neigh_unset_flags(struct rtnl_neigh *neigh, unsigned int flags) 869{ 870 neigh->n_flag_mask |= flags; 871 neigh->n_flags &= ~flags; 872 neigh->ce_mask |= NEIGH_ATTR_FLAGS; 873} 874 875void rtnl_neigh_set_ifindex(struct rtnl_neigh *neigh, int ifindex) 876{ 877 neigh->n_ifindex = ifindex; 878 neigh->ce_mask |= NEIGH_ATTR_IFINDEX; 879} 880 881int rtnl_neigh_get_ifindex(struct rtnl_neigh *neigh) 882{ 883 return neigh->n_ifindex; 884} 885 886static inline int __assign_addr(struct rtnl_neigh *neigh, struct nl_addr **pos, 887 struct nl_addr *new, int flag, int nocheck) 888{ 889 if (!nocheck) { 890 if (neigh->ce_mask & NEIGH_ATTR_FAMILY) { 891 if (new->a_family != neigh->n_family) 892 return -NLE_AF_MISMATCH; 893 } else { 894 neigh->n_family = new->a_family; 895 neigh->ce_mask |= NEIGH_ATTR_FAMILY; 896 } 897 } 898 899 if (*pos) 900 nl_addr_put(*pos); 901 902 nl_addr_get(new); 903 *pos = new; 904 905 neigh->ce_mask |= flag; 906 907 return 0; 908} 909 910void rtnl_neigh_set_lladdr(struct rtnl_neigh *neigh, struct nl_addr *addr) 911{ 912 __assign_addr(neigh, &neigh->n_lladdr, addr, NEIGH_ATTR_LLADDR, 1); 913} 914 915struct nl_addr *rtnl_neigh_get_lladdr(struct rtnl_neigh *neigh) 916{ 917 if (neigh->ce_mask & NEIGH_ATTR_LLADDR) 918 return neigh->n_lladdr; 919 else 920 return NULL; 921} 922 923int rtnl_neigh_set_dst(struct rtnl_neigh *neigh, struct nl_addr *addr) 924{ 925 return __assign_addr(neigh, &neigh->n_dst, addr, 926 NEIGH_ATTR_DST, 0); 927} 928 929struct nl_addr *rtnl_neigh_get_dst(struct rtnl_neigh *neigh) 930{ 931 if (neigh->ce_mask & NEIGH_ATTR_DST) 932 return neigh->n_dst; 933 else 934 return NULL; 935} 936 937void rtnl_neigh_set_family(struct rtnl_neigh *neigh, int family) 938{ 939 neigh->n_family = family; 940 neigh->ce_mask |= NEIGH_ATTR_FAMILY; 941} 942 943int rtnl_neigh_get_family(struct rtnl_neigh *neigh) 944{ 945 return neigh->n_family; 946} 947 948void rtnl_neigh_set_type(struct rtnl_neigh *neigh, int type) 949{ 950 neigh->n_type = type; 951 neigh->ce_mask = NEIGH_ATTR_TYPE; 952} 953 954int rtnl_neigh_get_type(struct rtnl_neigh *neigh) 955{ 956 if (neigh->ce_mask & NEIGH_ATTR_TYPE) 957 return neigh->n_type; 958 else 959 return -1; 960} 961 962/** @} */ 963 964static struct nl_object_ops neigh_obj_ops = { 965 .oo_name = "route/neigh", 966 .oo_size = sizeof(struct rtnl_neigh), 967 .oo_free_data = neigh_free_data, 968 .oo_clone = neigh_clone, 969 .oo_dump[NL_DUMP_BRIEF] = neigh_dump_brief, 970 .oo_dump[NL_DUMP_FULL] = neigh_dump_full, 971 .oo_dump[NL_DUMP_STATS] = neigh_dump_stats, 972 .oo_dump[NL_DUMP_XML] = neigh_dump_xml, 973 .oo_dump[NL_DUMP_ENV] = neigh_dump_env, 974 .oo_compare = neigh_compare, 975 .oo_attrs2str = neigh_attrs2str, 976 .oo_id_attrs = (NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY), 977}; 978 979static struct nl_af_group neigh_groups[] = { 980 { AF_UNSPEC, RTNLGRP_NEIGH }, 981 { END_OF_GROUP_LIST }, 982}; 983 984static struct nl_cache_ops rtnl_neigh_ops = { 985 .co_name = "route/neigh", 986 .co_hdrsize = sizeof(struct ndmsg), 987 .co_msgtypes = { 988 { RTM_NEWNEIGH, NL_ACT_NEW, "new" }, 989 { RTM_DELNEIGH, NL_ACT_DEL, "del" }, 990 { RTM_GETNEIGH, NL_ACT_GET, "get" }, 991 END_OF_MSGTYPES_LIST, 992 }, 993 .co_protocol = NETLINK_ROUTE, 994 .co_groups = neigh_groups, 995 .co_request_update = neigh_request_update, 996 .co_msg_parser = neigh_msg_parser, 997 .co_obj_ops = &neigh_obj_ops, 998}; 999 1000static void __init neigh_init(void) 1001{ 1002 nl_cache_mngt_register(&rtnl_neigh_ops); 1003} 1004 1005static void __exit neigh_exit(void) 1006{ 1007 nl_cache_mngt_unregister(&rtnl_neigh_ops); 1008} 1009 1010/** @} */ 1011