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_CREATE); 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_add(sk, neigh, NLM_F_REPLACE); 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 void neigh_dump_line(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 nl_dump_line(p, "%s ", nl_addr2str(n->n_dst, dst, sizeof(dst))); 341 342 if (link_cache) 343 nl_dump(p, "dev %s ", 344 rtnl_link_i2name(link_cache, n->n_ifindex, 345 state, sizeof(state))); 346 else 347 nl_dump(p, "dev %d ", n->n_ifindex); 348 349 if (n->ce_mask & NEIGH_ATTR_LLADDR) 350 nl_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 nl_dump(p, "<%s", state); 358 if (flags[0]) 359 nl_dump(p, "%s%s", state[0] ? "," : "<", flags); 360 if (state[0] || flags[0]) 361 nl_dump(p, ">"); 362 nl_dump(p, "\n"); 363} 364 365static void neigh_dump_details(struct nl_object *a, struct nl_dump_params *p) 366{ 367 char rtn_type[32]; 368 struct rtnl_neigh *n = (struct rtnl_neigh *) a; 369 int hz = nl_get_hz(); 370 371 neigh_dump_line(a, p); 372 373 nl_dump_line(p, " refcnt %u type %s confirmed %u used " 374 "%u updated %u\n", 375 n->n_cacheinfo.nci_refcnt, 376 nl_rtntype2str(n->n_type, rtn_type, sizeof(rtn_type)), 377 n->n_cacheinfo.nci_confirmed/hz, 378 n->n_cacheinfo.nci_used/hz, n->n_cacheinfo.nci_updated/hz); 379} 380 381static void neigh_dump_stats(struct nl_object *a, struct nl_dump_params *p) 382{ 383 neigh_dump_details(a, p); 384} 385 386static void neigh_dump_env(struct nl_object *obj, struct nl_dump_params *p) 387{ 388 struct rtnl_neigh *neigh = (struct rtnl_neigh *) obj; 389 char buf[128]; 390 391 nl_dump_line(p, "NEIGH_FAMILY=%s\n", 392 nl_af2str(neigh->n_family, buf, sizeof(buf))); 393 394 if (neigh->ce_mask & NEIGH_ATTR_LLADDR) 395 nl_dump_line(p, "NEIGHT_LLADDR=%s\n", 396 nl_addr2str(neigh->n_lladdr, buf, sizeof(buf))); 397 398 if (neigh->ce_mask & NEIGH_ATTR_DST) 399 nl_dump_line(p, "NEIGH_DST=%s\n", 400 nl_addr2str(neigh->n_dst, buf, sizeof(buf))); 401 402 if (neigh->ce_mask & NEIGH_ATTR_IFINDEX) { 403 struct nl_cache *link_cache; 404 405 nl_dump_line(p, "NEIGH_IFINDEX=%u\n", neigh->n_ifindex); 406 407 link_cache = nl_cache_mngt_require("route/link"); 408 if (link_cache) 409 nl_dump_line(p, "NEIGH_IFNAME=%s\n", 410 rtnl_link_i2name(link_cache, 411 neigh->n_ifindex, 412 buf, sizeof(buf))); 413 } 414 415 if (neigh->ce_mask & NEIGH_ATTR_PROBES) 416 nl_dump_line(p, "NEIGH_PROBES=%u\n", neigh->n_probes); 417 418 if (neigh->ce_mask & NEIGH_ATTR_TYPE) 419 nl_dump_line(p, "NEIGH_TYPE=%s\n", 420 nl_rtntype2str(neigh->n_type, buf, sizeof(buf))); 421 422 rtnl_neigh_flags2str(neigh->n_flags, buf, sizeof(buf)); 423 if (buf[0]) 424 nl_dump_line(p, "NEIGH_FLAGS=%s\n", buf); 425 426 rtnl_neigh_state2str(neigh->n_state, buf, sizeof(buf)); 427 if (buf[0]) 428 nl_dump_line(p, "NEIGH_STATE=%s\n", buf); 429} 430 431/** 432 * @name Neighbour Object Allocation/Freeage 433 * @{ 434 */ 435 436struct rtnl_neigh *rtnl_neigh_alloc(void) 437{ 438 return (struct rtnl_neigh *) nl_object_alloc(&neigh_obj_ops); 439} 440 441void rtnl_neigh_put(struct rtnl_neigh *neigh) 442{ 443 nl_object_put((struct nl_object *) neigh); 444} 445 446/** @} */ 447 448/** 449 * @name Neighbour Cache Managament 450 * @{ 451 */ 452 453/** 454 * Build a neighbour cache including all neighbours currently configured in the kernel. 455 * @arg sk Netlink socket. 456 * @arg result Pointer to store resulting cache. 457 * 458 * Allocates a new neighbour cache, initializes it properly and updates it 459 * to include all neighbours currently configured in the kernel. 460 * 461 * @return 0 on success or a negative error code. 462 */ 463int rtnl_neigh_alloc_cache(struct nl_sock *sock, struct nl_cache **result) 464{ 465 return nl_cache_alloc_and_fill(&rtnl_neigh_ops, sock, result); 466} 467 468/** 469 * Look up a neighbour by interface index and destination address 470 * @arg cache neighbour cache 471 * @arg ifindex interface index the neighbour is on 472 * @arg dst destination address of the neighbour 473 * @return neighbour handle or NULL if no match was found. 474 */ 475struct rtnl_neigh * rtnl_neigh_get(struct nl_cache *cache, int ifindex, 476 struct nl_addr *dst) 477{ 478 struct rtnl_neigh *neigh; 479 480 nl_list_for_each_entry(neigh, &cache->c_items, ce_list) { 481 if (neigh->n_ifindex == ifindex && 482 !nl_addr_cmp(neigh->n_dst, dst)) { 483 nl_object_get((struct nl_object *) neigh); 484 return neigh; 485 } 486 } 487 488 return NULL; 489} 490 491/** @} */ 492 493/** 494 * @name Neighbour Addition 495 * @{ 496 */ 497 498static int build_neigh_msg(struct rtnl_neigh *tmpl, int cmd, int flags, 499 struct nl_msg **result) 500{ 501 struct nl_msg *msg; 502 struct ndmsg nhdr = { 503 .ndm_ifindex = tmpl->n_ifindex, 504 .ndm_state = NUD_PERMANENT, 505 }; 506 507 if (!(tmpl->ce_mask & NEIGH_ATTR_DST)) 508 return -NLE_MISSING_ATTR; 509 510 nhdr.ndm_family = nl_addr_get_family(tmpl->n_dst); 511 512 if (tmpl->ce_mask & NEIGH_ATTR_STATE) 513 nhdr.ndm_state = tmpl->n_state; 514 515 msg = nlmsg_alloc_simple(cmd, flags); 516 if (!msg) 517 return -NLE_NOMEM; 518 519 if (nlmsg_append(msg, &nhdr, sizeof(nhdr), NLMSG_ALIGNTO) < 0) 520 goto nla_put_failure; 521 522 NLA_PUT_ADDR(msg, NDA_DST, tmpl->n_dst); 523 524 if (tmpl->ce_mask & NEIGH_ATTR_LLADDR) 525 NLA_PUT_ADDR(msg, NDA_LLADDR, tmpl->n_lladdr); 526 527 *result = msg; 528 return 0; 529 530nla_put_failure: 531 nlmsg_free(msg); 532 return -NLE_MSGSIZE; 533} 534 535/** 536 * Build netlink request message to add a new neighbour 537 * @arg tmpl template with data of new neighbour 538 * @arg flags additional netlink message flags 539 * @arg result Pointer to store resulting message. 540 * 541 * Builds a new netlink message requesting a addition of a new 542 * neighbour. The netlink message header isn't fully equipped with 543 * all relevant fields and must thus be sent out via nl_send_auto_complete() 544 * or supplemented as needed. \a tmpl must contain the attributes of the new 545 * neighbour set via \c rtnl_neigh_set_* functions. 546 * 547 * The following attributes must be set in the template: 548 * - Interface index (rtnl_neigh_set_ifindex()) 549 * - State (rtnl_neigh_set_state()) 550 * - Destination address (rtnl_neigh_set_dst()) 551 * - Link layer address (rtnl_neigh_set_lladdr()) 552 * 553 * @return 0 on success or a negative error code. 554 */ 555int rtnl_neigh_build_add_request(struct rtnl_neigh *tmpl, int flags, 556 struct nl_msg **result) 557{ 558 return build_neigh_msg(tmpl, RTM_NEWNEIGH, flags, result); 559} 560 561/** 562 * Add a new neighbour 563 * @arg sk Netlink socket. 564 * @arg tmpl template with requested changes 565 * @arg flags additional netlink message flags 566 * 567 * Builds a netlink message by calling rtnl_neigh_build_add_request(), 568 * sends the request to the kernel and waits for the next ACK to be 569 * received and thus blocks until the request has been fullfilled. 570 * 571 * The following attributes must be set in the template: 572 * - Interface index (rtnl_neigh_set_ifindex()) 573 * - State (rtnl_neigh_set_state()) 574 * - Destination address (rtnl_neigh_set_dst()) 575 * - Link layer address (rtnl_neigh_set_lladdr()) 576 * 577 * @return 0 on sucess or a negative error if an error occured. 578 */ 579int rtnl_neigh_add(struct nl_sock *sk, struct rtnl_neigh *tmpl, int flags) 580{ 581 int err; 582 struct nl_msg *msg; 583 584 if ((err = rtnl_neigh_build_add_request(tmpl, flags, &msg)) < 0) 585 return err; 586 587 err = nl_send_auto_complete(sk, msg); 588 nlmsg_free(msg); 589 if (err < 0) 590 return err; 591 592 return wait_for_ack(sk); 593} 594 595/** @} */ 596 597/** 598 * @name Neighbour Deletion 599 * @{ 600 */ 601 602/** 603 * Build a netlink request message to delete a neighbour 604 * @arg neigh neighbour to delete 605 * @arg flags additional netlink message flags 606 * @arg result Pointer to store resulting message. 607 * 608 * Builds a new netlink message requesting a deletion of a neighbour. 609 * The netlink message header isn't fully equipped with all relevant 610 * fields and must thus be sent out via nl_send_auto_complete() 611 * or supplemented as needed. \a neigh must point to an existing 612 * neighbour. 613 * 614 * @return 0 on success or a negative error code. 615 */ 616int rtnl_neigh_build_delete_request(struct rtnl_neigh *neigh, int flags, 617 struct nl_msg **result) 618{ 619 return build_neigh_msg(neigh, RTM_DELNEIGH, flags, result); 620} 621 622/** 623 * Delete a neighbour 624 * @arg sk Netlink socket. 625 * @arg neigh neighbour to delete 626 * @arg flags additional netlink message flags 627 * 628 * Builds a netlink message by calling rtnl_neigh_build_delete_request(), 629 * sends the request to the kernel and waits for the next ACK to be 630 * received and thus blocks until the request has been fullfilled. 631 * 632 * @return 0 on sucess or a negative error if an error occured. 633 */ 634int rtnl_neigh_delete(struct nl_sock *sk, struct rtnl_neigh *neigh, 635 int flags) 636{ 637 struct nl_msg *msg; 638 int err; 639 640 if ((err = rtnl_neigh_build_delete_request(neigh, flags, &msg)) < 0) 641 return err; 642 643 err = nl_send_auto_complete(sk, msg); 644 nlmsg_free(msg); 645 if (err < 0) 646 return err; 647 648 return wait_for_ack(sk); 649} 650 651/** @} */ 652 653/** 654 * @name Neighbour States Translations 655 * @{ 656 */ 657 658static struct trans_tbl neigh_states[] = { 659 __ADD(NUD_INCOMPLETE, incomplete) 660 __ADD(NUD_REACHABLE, reachable) 661 __ADD(NUD_STALE, stale) 662 __ADD(NUD_DELAY, delay) 663 __ADD(NUD_PROBE, probe) 664 __ADD(NUD_FAILED, failed) 665 __ADD(NUD_NOARP, norarp) 666 __ADD(NUD_PERMANENT, permanent) 667}; 668 669char * rtnl_neigh_state2str(int state, char *buf, size_t len) 670{ 671 return __flags2str(state, buf, len, neigh_states, 672 ARRAY_SIZE(neigh_states)); 673} 674 675int rtnl_neigh_str2state(const char *name) 676{ 677 return __str2type(name, neigh_states, ARRAY_SIZE(neigh_states)); 678} 679 680/** @} */ 681 682/** 683 * @name Neighbour Flags Translations 684 * @{ 685 */ 686 687static struct trans_tbl neigh_flags[] = { 688 __ADD(NTF_PROXY, proxy) 689 __ADD(NTF_ROUTER, router) 690}; 691 692char * rtnl_neigh_flags2str(int flags, char *buf, size_t len) 693{ 694 return __flags2str(flags, buf, len, neigh_flags, 695 ARRAY_SIZE(neigh_flags)); 696} 697 698int rtnl_neigh_str2flag(const char *name) 699{ 700 return __str2type(name, neigh_flags, ARRAY_SIZE(neigh_flags)); 701} 702 703/** @} */ 704 705/** 706 * @name Attributes 707 * @{ 708 */ 709 710void rtnl_neigh_set_state(struct rtnl_neigh *neigh, int state) 711{ 712 neigh->n_state_mask |= state; 713 neigh->n_state |= state; 714 neigh->ce_mask |= NEIGH_ATTR_STATE; 715} 716 717int rtnl_neigh_get_state(struct rtnl_neigh *neigh) 718{ 719 if (neigh->ce_mask & NEIGH_ATTR_STATE) 720 return neigh->n_state; 721 else 722 return -1; 723} 724 725void rtnl_neigh_unset_state(struct rtnl_neigh *neigh, int state) 726{ 727 neigh->n_state_mask |= state; 728 neigh->n_state &= ~state; 729 neigh->ce_mask |= NEIGH_ATTR_STATE; 730} 731 732void rtnl_neigh_set_flags(struct rtnl_neigh *neigh, unsigned int flags) 733{ 734 neigh->n_flag_mask |= flags; 735 neigh->n_flags |= flags; 736 neigh->ce_mask |= NEIGH_ATTR_FLAGS; 737} 738 739unsigned int rtnl_neigh_get_flags(struct rtnl_neigh *neigh) 740{ 741 return neigh->n_flags; 742} 743 744void rtnl_neigh_unset_flags(struct rtnl_neigh *neigh, unsigned int flags) 745{ 746 neigh->n_flag_mask |= flags; 747 neigh->n_flags &= ~flags; 748 neigh->ce_mask |= NEIGH_ATTR_FLAGS; 749} 750 751void rtnl_neigh_set_ifindex(struct rtnl_neigh *neigh, int ifindex) 752{ 753 neigh->n_ifindex = ifindex; 754 neigh->ce_mask |= NEIGH_ATTR_IFINDEX; 755} 756 757int rtnl_neigh_get_ifindex(struct rtnl_neigh *neigh) 758{ 759 return neigh->n_ifindex; 760} 761 762static inline int __assign_addr(struct rtnl_neigh *neigh, struct nl_addr **pos, 763 struct nl_addr *new, int flag, int nocheck) 764{ 765 if (!nocheck) { 766 if (neigh->ce_mask & NEIGH_ATTR_FAMILY) { 767 if (new->a_family != neigh->n_family) 768 return -NLE_AF_MISMATCH; 769 } else { 770 neigh->n_family = new->a_family; 771 neigh->ce_mask |= NEIGH_ATTR_FAMILY; 772 } 773 } 774 775 if (*pos) 776 nl_addr_put(*pos); 777 778 nl_addr_get(new); 779 *pos = new; 780 781 neigh->ce_mask |= flag; 782 783 return 0; 784} 785 786void rtnl_neigh_set_lladdr(struct rtnl_neigh *neigh, struct nl_addr *addr) 787{ 788 __assign_addr(neigh, &neigh->n_lladdr, addr, NEIGH_ATTR_LLADDR, 1); 789} 790 791struct nl_addr *rtnl_neigh_get_lladdr(struct rtnl_neigh *neigh) 792{ 793 if (neigh->ce_mask & NEIGH_ATTR_LLADDR) 794 return neigh->n_lladdr; 795 else 796 return NULL; 797} 798 799int rtnl_neigh_set_dst(struct rtnl_neigh *neigh, struct nl_addr *addr) 800{ 801 return __assign_addr(neigh, &neigh->n_dst, addr, 802 NEIGH_ATTR_DST, 0); 803} 804 805struct nl_addr *rtnl_neigh_get_dst(struct rtnl_neigh *neigh) 806{ 807 if (neigh->ce_mask & NEIGH_ATTR_DST) 808 return neigh->n_dst; 809 else 810 return NULL; 811} 812 813void rtnl_neigh_set_family(struct rtnl_neigh *neigh, int family) 814{ 815 neigh->n_family = family; 816 neigh->ce_mask |= NEIGH_ATTR_FAMILY; 817} 818 819int rtnl_neigh_get_family(struct rtnl_neigh *neigh) 820{ 821 return neigh->n_family; 822} 823 824void rtnl_neigh_set_type(struct rtnl_neigh *neigh, int type) 825{ 826 neigh->n_type = type; 827 neigh->ce_mask = NEIGH_ATTR_TYPE; 828} 829 830int rtnl_neigh_get_type(struct rtnl_neigh *neigh) 831{ 832 if (neigh->ce_mask & NEIGH_ATTR_TYPE) 833 return neigh->n_type; 834 else 835 return -1; 836} 837 838/** @} */ 839 840static struct nl_object_ops neigh_obj_ops = { 841 .oo_name = "route/neigh", 842 .oo_size = sizeof(struct rtnl_neigh), 843 .oo_free_data = neigh_free_data, 844 .oo_clone = neigh_clone, 845 .oo_dump = { 846 [NL_DUMP_LINE] = neigh_dump_line, 847 [NL_DUMP_DETAILS] = neigh_dump_details, 848 [NL_DUMP_STATS] = neigh_dump_stats, 849 [NL_DUMP_ENV] = neigh_dump_env, 850 }, 851 .oo_compare = neigh_compare, 852 .oo_attrs2str = neigh_attrs2str, 853 .oo_id_attrs = (NEIGH_ATTR_IFINDEX | NEIGH_ATTR_DST | NEIGH_ATTR_FAMILY), 854}; 855 856static struct nl_af_group neigh_groups[] = { 857 { AF_UNSPEC, RTNLGRP_NEIGH }, 858 { END_OF_GROUP_LIST }, 859}; 860 861static struct nl_cache_ops rtnl_neigh_ops = { 862 .co_name = "route/neigh", 863 .co_hdrsize = sizeof(struct ndmsg), 864 .co_msgtypes = { 865 { RTM_NEWNEIGH, NL_ACT_NEW, "new" }, 866 { RTM_DELNEIGH, NL_ACT_DEL, "del" }, 867 { RTM_GETNEIGH, NL_ACT_GET, "get" }, 868 END_OF_MSGTYPES_LIST, 869 }, 870 .co_protocol = NETLINK_ROUTE, 871 .co_groups = neigh_groups, 872 .co_request_update = neigh_request_update, 873 .co_msg_parser = neigh_msg_parser, 874 .co_obj_ops = &neigh_obj_ops, 875}; 876 877static void __init neigh_init(void) 878{ 879 nl_cache_mngt_register(&rtnl_neigh_ops); 880} 881 882static void __exit neigh_exit(void) 883{ 884 nl_cache_mngt_unregister(&rtnl_neigh_ops); 885} 886 887/** @} */ 888