addr.c revision 5702d4c1b97616f5212da31db01a2f3c79c15b7c
1/* 2 * lib/route/addr.c Addresses 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 * Copyright (c) 2003-2006 Baruch Even <baruch@ev-en.org>, 11 * Mediatrix Telecom, inc. <ericb@mediatrix.com> 12 */ 13 14/** 15 * @ingroup rtnl 16 * @defgroup rtaddr Addresses 17 * @brief 18 * 19 * @note The maximum size of an address label is IFNAMSIZ. 20 * 21 * @note The address may not contain a prefix length if the peer address 22 * has been specified already. 23 * 24 * @par 1) Address Addition 25 * @code 26 * // Allocate an empty address object to be filled out with the attributes 27 * // of the new address. 28 * struct rtnl_addr *addr = rtnl_addr_alloc(); 29 * 30 * // Fill out the mandatory attributes of the new address. Setting the 31 * // local address will automatically set the address family and the 32 * // prefix length to the correct values. 33 * rtnl_addr_set_ifindex(addr, ifindex); 34 * rtnl_addr_set_local(addr, local_addr); 35 * 36 * // The label of the address can be specified, currently only supported 37 * // by IPv4 and DECnet. 38 * rtnl_addr_set_label(addr, "mylabel"); 39 * 40 * // The peer address can be specified if necessary, in either case a peer 41 * // address will be sent to the kernel in order to fullfil the interface 42 * // requirements. If none is set, it will equal the local address. 43 * // Note: Real peer addresses are only supported by IPv4 for now. 44 * rtnl_addr_set_peer(addr, peer_addr); 45 * 46 * // In case you want to have the address have a scope other than global 47 * // it may be overwritten using rtnl_addr_set_scope(). The scope currently 48 * // cannot be set for IPv6 addresses. 49 * rtnl_addr_set_scope(addr, rtnl_str2scope("site")); 50 * 51 * // Broadcast address may be specified using the relevant 52 * // functions, the address family will be verified if one of the other 53 * // addresses has been set already. Currently only works for IPv4. 54 * rtnl_addr_set_broadcast(addr, broadcast_addr); 55 * 56 * // Build the netlink message and send it to the kernel, the operation will 57 * // block until the operation has been completed. Alternatively the required 58 * // netlink message can be built using rtnl_addr_build_add_request() to be 59 * // sent out using nl_send_auto_complete(). 60 * rtnl_addr_add(sk, addr, 0); 61 * 62 * // Free the memory 63 * rtnl_addr_put(addr); 64 * @endcode 65 * 66 * @par 2) Address Deletion 67 * @code 68 * // Allocate an empty address object to be filled out with the attributes 69 * // matching the address to be deleted. Alternatively a fully equipped 70 * // address object out of a cache can be used instead. 71 * struct rtnl_addr *addr = rtnl_addr_alloc(); 72 * 73 * // The only mandatory parameter besides the address family is the interface 74 * // index the address is on, i.e. leaving out all other parameters will 75 * // result in all addresses of the specified address family interface tuple 76 * // to be deleted. 77 * rtnl_addr_set_ifindex(addr, ifindex); 78 * 79 * // Specyfing the address family manually is only required if neither the 80 * // local nor peer address have been specified. 81 * rtnl_addr_set_family(addr, AF_INET); 82 * 83 * // Specyfing the local address is optional but the best choice to delete 84 * // specific addresses. 85 * rtnl_addr_set_local(addr, local_addr); 86 * 87 * // The label of the address can be specified, currently only supported 88 * // by IPv4 and DECnet. 89 * rtnl_addr_set_label(addr, "mylabel"); 90 * 91 * // The peer address can be specified if necessary, in either case a peer 92 * // address will be sent to the kernel in order to fullfil the interface 93 * // requirements. If none is set, it will equal the local address. 94 * // Note: Real peer addresses are only supported by IPv4 for now. 95 * rtnl_addr_set_peer(addr, peer_addr); 96 * 97 * // Build the netlink message and send it to the kernel, the operation will 98 * // block until the operation has been completed. Alternatively the required 99 * // netlink message can be built using rtnl_addr_build_delete_request() 100 * // to be sent out using nl_send_auto_complete(). 101 * rtnl_addr_delete(sk, addr, 0); 102 * 103 * // Free the memory 104 * rtnl_addr_put(addr); 105 * @endcode 106 * @{ 107 */ 108 109#include <netlink-local.h> 110#include <netlink/netlink.h> 111#include <netlink/route/rtnl.h> 112#include <netlink/route/addr.h> 113#include <netlink/route/route.h> 114#include <netlink/route/link.h> 115#include <netlink/utils.h> 116 117/** @cond SKIP */ 118#define ADDR_ATTR_FAMILY 0x0001 119#define ADDR_ATTR_PREFIXLEN 0x0002 120#define ADDR_ATTR_FLAGS 0x0004 121#define ADDR_ATTR_SCOPE 0x0008 122#define ADDR_ATTR_IFINDEX 0x0010 123#define ADDR_ATTR_LABEL 0x0020 124#define ADDR_ATTR_CACHEINFO 0x0040 125#define ADDR_ATTR_PEER 0x0080 126#define ADDR_ATTR_LOCAL 0x0100 127#define ADDR_ATTR_BROADCAST 0x0200 128#define ADDR_ATTR_MULTICAST 0x0400 129 130static struct nl_cache_ops rtnl_addr_ops; 131static struct nl_object_ops addr_obj_ops; 132/** @endcond */ 133 134static void addr_constructor(struct nl_object *obj) 135{ 136 struct rtnl_addr *addr = nl_object_priv(obj); 137 138 addr->a_scope = RT_SCOPE_NOWHERE; 139} 140 141static void addr_free_data(struct nl_object *obj) 142{ 143 struct rtnl_addr *addr = nl_object_priv(obj); 144 145 if (!addr) 146 return; 147 148 nl_addr_put(addr->a_peer); 149 nl_addr_put(addr->a_local); 150 nl_addr_put(addr->a_bcast); 151 nl_addr_put(addr->a_multicast); 152} 153 154static int addr_clone(struct nl_object *_dst, struct nl_object *_src) 155{ 156 struct rtnl_addr *dst = nl_object_priv(_dst); 157 struct rtnl_addr *src = nl_object_priv(_src); 158 159 if (src->a_peer) 160 if (!(dst->a_peer = nl_addr_clone(src->a_peer))) 161 return -NLE_NOMEM; 162 163 if (src->a_local) 164 if (!(dst->a_local = nl_addr_clone(src->a_local))) 165 return -NLE_NOMEM; 166 167 if (src->a_bcast) 168 if (!(dst->a_bcast = nl_addr_clone(src->a_bcast))) 169 return -NLE_NOMEM; 170 171 if (src->a_multicast) 172 if (!(dst->a_multicast = nl_addr_clone(src->a_multicast))) 173 return -NLE_NOMEM; 174 175 return 0; 176} 177 178static struct nla_policy addr_policy[IFA_MAX+1] = { 179 [IFA_LABEL] = { .type = NLA_STRING, 180 .maxlen = IFNAMSIZ }, 181 [IFA_CACHEINFO] = { .minlen = sizeof(struct ifa_cacheinfo) }, 182}; 183 184static int addr_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who, 185 struct nlmsghdr *nlh, struct nl_parser_param *pp) 186{ 187 struct rtnl_addr *addr; 188 struct ifaddrmsg *ifa; 189 struct nlattr *tb[IFA_MAX+1]; 190 int err, peer_prefix = 0, family; 191 192 addr = rtnl_addr_alloc(); 193 if (!addr) 194 return -NLE_NOMEM; 195 196 addr->ce_msgtype = nlh->nlmsg_type; 197 198 err = nlmsg_parse(nlh, sizeof(*ifa), tb, IFA_MAX, addr_policy); 199 if (err < 0) 200 goto errout; 201 202 ifa = nlmsg_data(nlh); 203 addr->a_family = family = ifa->ifa_family; 204 addr->a_prefixlen = ifa->ifa_prefixlen; 205 addr->a_flags = ifa->ifa_flags; 206 addr->a_scope = ifa->ifa_scope; 207 addr->a_ifindex = ifa->ifa_index; 208 209 addr->ce_mask = (ADDR_ATTR_FAMILY | ADDR_ATTR_PREFIXLEN | 210 ADDR_ATTR_FLAGS | ADDR_ATTR_SCOPE | ADDR_ATTR_IFINDEX); 211 212 if (tb[IFA_LABEL]) { 213 nla_strlcpy(addr->a_label, tb[IFA_LABEL], IFNAMSIZ); 214 addr->ce_mask |= ADDR_ATTR_LABEL; 215 } 216 217 if (tb[IFA_CACHEINFO]) { 218 struct ifa_cacheinfo *ca; 219 220 ca = nla_data(tb[IFA_CACHEINFO]); 221 addr->a_cacheinfo.aci_prefered = ca->ifa_prefered; 222 addr->a_cacheinfo.aci_valid = ca->ifa_valid; 223 addr->a_cacheinfo.aci_cstamp = ca->cstamp; 224 addr->a_cacheinfo.aci_tstamp = ca->tstamp; 225 addr->ce_mask |= ADDR_ATTR_CACHEINFO; 226 } 227 228 if (tb[IFA_LOCAL]) { 229 addr->a_local = nl_addr_alloc_attr(tb[IFA_LOCAL], family); 230 if (!addr->a_local) 231 goto errout_nomem; 232 addr->ce_mask |= ADDR_ATTR_LOCAL; 233 } 234 235 if (tb[IFA_ADDRESS]) { 236 struct nl_addr *a; 237 238 a = nl_addr_alloc_attr(tb[IFA_ADDRESS], family); 239 if (!a) 240 goto errout_nomem; 241 242 /* IPv6 sends the local address as IFA_ADDRESS with 243 * no IFA_LOCAL, IPv4 sends both IFA_LOCAL and IFA_ADDRESS 244 * with IFA_ADDRESS being the peer address if they differ */ 245 if (!tb[IFA_LOCAL] || !nl_addr_cmp(a, addr->a_local)) { 246 nl_addr_put(addr->a_local); 247 addr->a_local = a; 248 addr->ce_mask |= ADDR_ATTR_LOCAL; 249 } else { 250 addr->a_peer = a; 251 addr->ce_mask |= ADDR_ATTR_PEER; 252 peer_prefix = 1; 253 } 254 } 255 256 nl_addr_set_prefixlen(peer_prefix ? addr->a_peer : addr->a_local, 257 addr->a_prefixlen); 258 259 if (tb[IFA_BROADCAST]) { 260 addr->a_bcast = nl_addr_alloc_attr(tb[IFA_BROADCAST], family); 261 if (!addr->a_bcast) 262 goto errout_nomem; 263 264 addr->ce_mask |= ADDR_ATTR_BROADCAST; 265 } 266 267 if (tb[IFA_MULTICAST]) { 268 addr->a_multicast = nl_addr_alloc_attr(tb[IFA_MULTICAST], 269 family); 270 if (!addr->a_multicast) 271 goto errout_nomem; 272 273 addr->ce_mask |= ADDR_ATTR_MULTICAST; 274 } 275 276 err = pp->pp_cb((struct nl_object *) addr, pp); 277errout: 278 rtnl_addr_put(addr); 279 280 return err; 281 282errout_nomem: 283 err = -NLE_NOMEM; 284 goto errout; 285} 286 287static int addr_request_update(struct nl_cache *cache, struct nl_sock *sk) 288{ 289 return nl_rtgen_request(sk, RTM_GETADDR, AF_UNSPEC, NLM_F_DUMP); 290} 291 292static void addr_dump_line(struct nl_object *obj, struct nl_dump_params *p) 293{ 294 struct rtnl_addr *addr = (struct rtnl_addr *) obj; 295 struct nl_cache *link_cache; 296 char buf[128]; 297 298 link_cache = nl_cache_mngt_require("route/link"); 299 300 if (addr->ce_mask & ADDR_ATTR_LOCAL) 301 nl_dump_line(p, "%s", 302 nl_addr2str(addr->a_local, buf, sizeof(buf))); 303 else 304 nl_dump_line(p, "none"); 305 306 if (addr->ce_mask & ADDR_ATTR_PEER) 307 nl_dump(p, " peer %s", 308 nl_addr2str(addr->a_peer, buf, sizeof(buf))); 309 310 nl_dump(p, " %s ", nl_af2str(addr->a_family, buf, sizeof(buf))); 311 312 if (link_cache) 313 nl_dump(p, "dev %s ", 314 rtnl_link_i2name(link_cache, addr->a_ifindex, 315 buf, sizeof(buf))); 316 else 317 nl_dump(p, "dev %d ", addr->a_ifindex); 318 319 nl_dump(p, "scope %s", 320 rtnl_scope2str(addr->a_scope, buf, sizeof(buf))); 321 322 rtnl_addr_flags2str(addr->a_flags, buf, sizeof(buf)); 323 if (buf[0]) 324 nl_dump(p, " <%s>", buf); 325 326 nl_dump(p, "\n"); 327} 328 329static void addr_dump_details(struct nl_object *obj, struct nl_dump_params *p) 330{ 331 struct rtnl_addr *addr = (struct rtnl_addr *) obj; 332 char buf[128]; 333 334 addr_dump_line(obj, p); 335 336 if (addr->ce_mask & (ADDR_ATTR_LABEL | ADDR_ATTR_BROADCAST | 337 ADDR_ATTR_MULTICAST)) { 338 nl_dump_line(p, " "); 339 340 if (addr->ce_mask & ADDR_ATTR_LABEL) 341 nl_dump(p, " label %s", addr->a_label); 342 343 if (addr->ce_mask & ADDR_ATTR_BROADCAST) 344 nl_dump(p, " broadcast %s", 345 nl_addr2str(addr->a_bcast, buf, sizeof(buf))); 346 347 if (addr->ce_mask & ADDR_ATTR_MULTICAST) 348 nl_dump(p, " multicast %s", 349 nl_addr2str(addr->a_multicast, buf, 350 sizeof(buf))); 351 352 nl_dump(p, "\n"); 353 } 354 355 if (addr->ce_mask & ADDR_ATTR_CACHEINFO) { 356 struct rtnl_addr_cacheinfo *ci = &addr->a_cacheinfo; 357 358 nl_dump_line(p, " valid-lifetime %s", 359 ci->aci_valid == 0xFFFFFFFFU ? "forever" : 360 nl_msec2str(ci->aci_valid * 1000, 361 buf, sizeof(buf))); 362 363 nl_dump(p, " preferred-lifetime %s\n", 364 ci->aci_prefered == 0xFFFFFFFFU ? "forever" : 365 nl_msec2str(ci->aci_prefered * 1000, 366 buf, sizeof(buf))); 367 368 nl_dump_line(p, " created boot-time+%s ", 369 nl_msec2str(addr->a_cacheinfo.aci_cstamp * 10, 370 buf, sizeof(buf))); 371 372 nl_dump(p, "last-updated boot-time+%s\n", 373 nl_msec2str(addr->a_cacheinfo.aci_tstamp * 10, 374 buf, sizeof(buf))); 375 } 376} 377 378static void addr_dump_stats(struct nl_object *obj, struct nl_dump_params *p) 379{ 380 addr_dump_details(obj, p); 381} 382 383static int addr_compare(struct nl_object *_a, struct nl_object *_b, 384 uint32_t attrs, int flags) 385{ 386 struct rtnl_addr *a = (struct rtnl_addr *) _a; 387 struct rtnl_addr *b = (struct rtnl_addr *) _b; 388 int diff = 0; 389 390#define ADDR_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, ADDR_ATTR_##ATTR, a, b, EXPR) 391 392 diff |= ADDR_DIFF(IFINDEX, a->a_ifindex != b->a_ifindex); 393 diff |= ADDR_DIFF(FAMILY, a->a_family != b->a_family); 394 diff |= ADDR_DIFF(SCOPE, a->a_scope != b->a_scope); 395 diff |= ADDR_DIFF(LABEL, strcmp(a->a_label, b->a_label)); 396 diff |= ADDR_DIFF(PEER, nl_addr_cmp(a->a_peer, b->a_peer)); 397 diff |= ADDR_DIFF(LOCAL, nl_addr_cmp(a->a_local, b->a_local)); 398 diff |= ADDR_DIFF(MULTICAST, nl_addr_cmp(a->a_multicast, 399 b->a_multicast)); 400 diff |= ADDR_DIFF(BROADCAST, nl_addr_cmp(a->a_bcast, b->a_bcast)); 401 402 if (flags & LOOSE_COMPARISON) 403 diff |= ADDR_DIFF(FLAGS, 404 (a->a_flags ^ b->a_flags) & b->a_flag_mask); 405 else 406 diff |= ADDR_DIFF(FLAGS, a->a_flags != b->a_flags); 407 408#undef ADDR_DIFF 409 410 return diff; 411} 412 413static struct trans_tbl addr_attrs[] = { 414 __ADD(ADDR_ATTR_FAMILY, family) 415 __ADD(ADDR_ATTR_PREFIXLEN, prefixlen) 416 __ADD(ADDR_ATTR_FLAGS, flags) 417 __ADD(ADDR_ATTR_SCOPE, scope) 418 __ADD(ADDR_ATTR_IFINDEX, ifindex) 419 __ADD(ADDR_ATTR_LABEL, label) 420 __ADD(ADDR_ATTR_CACHEINFO, cacheinfo) 421 __ADD(ADDR_ATTR_PEER, peer) 422 __ADD(ADDR_ATTR_LOCAL, local) 423 __ADD(ADDR_ATTR_BROADCAST, broadcast) 424 __ADD(ADDR_ATTR_MULTICAST, multicast) 425}; 426 427static char *addr_attrs2str(int attrs, char *buf, size_t len) 428{ 429 return __flags2str(attrs, buf, len, addr_attrs, 430 ARRAY_SIZE(addr_attrs)); 431} 432 433/** 434 * @name Allocation/Freeing 435 * @{ 436 */ 437 438struct rtnl_addr *rtnl_addr_alloc(void) 439{ 440 return (struct rtnl_addr *) nl_object_alloc(&addr_obj_ops); 441} 442 443void rtnl_addr_put(struct rtnl_addr *addr) 444{ 445 nl_object_put((struct nl_object *) addr); 446} 447 448/** @} */ 449 450/** 451 * @name Cache Management 452 * @{ 453 */ 454 455int rtnl_addr_alloc_cache(struct nl_sock *sk, struct nl_cache **result) 456{ 457 return nl_cache_alloc_and_fill(&rtnl_addr_ops, sk, result); 458} 459 460/** @} */ 461 462static int build_addr_msg(struct rtnl_addr *tmpl, int cmd, int flags, 463 struct nl_msg **result) 464{ 465 struct nl_msg *msg; 466 struct ifaddrmsg am = { 467 .ifa_family = tmpl->a_family, 468 .ifa_index = tmpl->a_ifindex, 469 .ifa_prefixlen = tmpl->a_prefixlen, 470 }; 471 472 if (tmpl->ce_mask & ADDR_ATTR_SCOPE) 473 am.ifa_scope = tmpl->a_scope; 474 else { 475 /* compatibility hack */ 476 if (tmpl->a_family == AF_INET && 477 tmpl->ce_mask & ADDR_ATTR_LOCAL && 478 *((char *) nl_addr_get_binary_addr(tmpl->a_local)) == 127) 479 am.ifa_scope = RT_SCOPE_HOST; 480 else 481 am.ifa_scope = RT_SCOPE_UNIVERSE; 482 } 483 484 msg = nlmsg_alloc_simple(cmd, flags); 485 if (!msg) 486 return -NLE_NOMEM; 487 488 if (nlmsg_append(msg, &am, sizeof(am), NLMSG_ALIGNTO) < 0) 489 goto nla_put_failure; 490 491 if (tmpl->ce_mask & ADDR_ATTR_LOCAL) 492 NLA_PUT_ADDR(msg, IFA_LOCAL, tmpl->a_local); 493 494 if (tmpl->ce_mask & ADDR_ATTR_PEER) 495 NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_peer); 496 else if (tmpl->ce_mask & ADDR_ATTR_LOCAL) 497 NLA_PUT_ADDR(msg, IFA_ADDRESS, tmpl->a_local); 498 499 if (tmpl->ce_mask & ADDR_ATTR_LABEL) 500 NLA_PUT_STRING(msg, IFA_LABEL, tmpl->a_label); 501 502 if (tmpl->ce_mask & ADDR_ATTR_BROADCAST) 503 NLA_PUT_ADDR(msg, IFA_BROADCAST, tmpl->a_bcast); 504 505 if (tmpl->ce_mask & ADDR_ATTR_CACHEINFO) { 506 struct ifa_cacheinfo ca = { 507 .ifa_valid = tmpl->a_cacheinfo.aci_valid, 508 .ifa_prefered = tmpl->a_cacheinfo.aci_prefered, 509 }; 510 511 NLA_PUT(msg, IFA_CACHEINFO, sizeof(ca), &ca); 512 } 513 514 515 *result = msg; 516 return 0; 517 518nla_put_failure: 519 nlmsg_free(msg); 520 return -NLE_MSGSIZE; 521} 522 523/** 524 * @name Addition 525 * @{ 526 */ 527 528/** 529 * Build netlink request message to request addition of new address 530 * @arg addr Address object representing the new address. 531 * @arg flags Additional netlink message flags. 532 * @arg result Pointer to store resulting message. 533 * 534 * Builds a new netlink message requesting the addition of a new 535 * address. The netlink message header isn't fully equipped with 536 * all relevant fields and must thus be sent out via nl_send_auto_complete() 537 * or supplemented as needed. 538 * 539 * Minimal required attributes: 540 * - interface index (rtnl_addr_set_ifindex()) 541 * - local address (rtnl_addr_set_local()) 542 * 543 * The scope will default to universe except for loopback addresses in 544 * which case a host scope is used if not specified otherwise. 545 * 546 * @note Free the memory after usage using nlmsg_free(). 547 * 548 * @return 0 on success or a negative error code. 549 */ 550int rtnl_addr_build_add_request(struct rtnl_addr *addr, int flags, 551 struct nl_msg **result) 552{ 553 int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY | 554 ADDR_ATTR_PREFIXLEN | ADDR_ATTR_LOCAL; 555 556 if ((addr->ce_mask & required) != required) 557 return -NLE_MISSING_ATTR; 558 559 return build_addr_msg(addr, RTM_NEWADDR, NLM_F_CREATE | flags, result); 560} 561 562/** 563 * Request addition of new address 564 * @arg sk Netlink socket. 565 * @arg addr Address object representing the new address. 566 * @arg flags Additional netlink message flags. 567 * 568 * Builds a netlink message by calling rtnl_addr_build_add_request(), 569 * sends the request to the kernel and waits for the next ACK to be 570 * received and thus blocks until the request has been fullfilled. 571 * 572 * @see rtnl_addr_build_add_request() 573 * 574 * @return 0 on sucess or a negative error if an error occured. 575 */ 576int rtnl_addr_add(struct nl_sock *sk, struct rtnl_addr *addr, int flags) 577{ 578 struct nl_msg *msg; 579 int err; 580 581 if ((err = rtnl_addr_build_add_request(addr, flags, &msg)) < 0) 582 return err; 583 584 err = nl_send_auto_complete(sk, msg); 585 nlmsg_free(msg); 586 if (err < 0) 587 return err; 588 589 return nl_wait_for_ack(sk); 590} 591 592/** @} */ 593 594/** 595 * @name Deletion 596 * @{ 597 */ 598 599/** 600 * Build a netlink request message to request deletion of an address 601 * @arg addr Address object to be deleteted. 602 * @arg flags Additional netlink message flags. 603 * @arg result Pointer to store resulting message. 604 * 605 * Builds a new netlink message requesting a deletion of an address. 606 * The netlink message header isn't fully equipped with all relevant 607 * fields and must thus be sent out via nl_send_auto_complete() 608 * or supplemented as needed. 609 * 610 * Minimal required attributes: 611 * - interface index (rtnl_addr_set_ifindex()) 612 * - address family (rtnl_addr_set_family()) 613 * 614 * Optional attributes: 615 * - local address (rtnl_addr_set_local()) 616 * - label (rtnl_addr_set_label(), IPv4/DECnet only) 617 * - peer address (rtnl_addr_set_peer(), IPv4 only) 618 * 619 * @note Free the memory after usage using nlmsg_free(). 620 * 621 * @return 0 on success or a negative error code. 622 */ 623int rtnl_addr_build_delete_request(struct rtnl_addr *addr, int flags, 624 struct nl_msg **result) 625{ 626 int required = ADDR_ATTR_IFINDEX | ADDR_ATTR_FAMILY; 627 628 if ((addr->ce_mask & required) != required) 629 return -NLE_MISSING_ATTR; 630 631 return build_addr_msg(addr, RTM_DELADDR, flags, result); 632} 633 634/** 635 * Request deletion of an address 636 * @arg sk Netlink socket. 637 * @arg addr Address object to be deleted. 638 * @arg flags Additional netlink message flags. 639 * 640 * Builds a netlink message by calling rtnl_addr_build_delete_request(), 641 * sends the request to the kernel and waits for the next ACK to be 642 * received and thus blocks until the request has been fullfilled. 643 * 644 * @see rtnl_addr_build_delete_request(); 645 * 646 * @return 0 on sucess or a negative error if an error occured. 647 */ 648int rtnl_addr_delete(struct nl_sock *sk, struct rtnl_addr *addr, int flags) 649{ 650 struct nl_msg *msg; 651 int err; 652 653 if ((err = rtnl_addr_build_delete_request(addr, flags, &msg)) < 0) 654 return err; 655 656 err = nl_send_auto_complete(sk, msg); 657 nlmsg_free(msg); 658 if (err < 0) 659 return err; 660 661 return nl_wait_for_ack(sk); 662} 663 664/** @} */ 665 666/** 667 * @name Attributes 668 * @{ 669 */ 670 671int rtnl_addr_set_label(struct rtnl_addr *addr, const char *label) 672{ 673 if (strlen(label) > sizeof(addr->a_label) - 1) 674 return -NLE_RANGE; 675 676 strcpy(addr->a_label, label); 677 addr->ce_mask |= ADDR_ATTR_LABEL; 678 679 return 0; 680} 681 682char *rtnl_addr_get_label(struct rtnl_addr *addr) 683{ 684 if (addr->ce_mask & ADDR_ATTR_LABEL) 685 return addr->a_label; 686 else 687 return NULL; 688} 689 690void rtnl_addr_set_ifindex(struct rtnl_addr *addr, int ifindex) 691{ 692 addr->a_ifindex = ifindex; 693 addr->ce_mask |= ADDR_ATTR_IFINDEX; 694} 695 696int rtnl_addr_get_ifindex(struct rtnl_addr *addr) 697{ 698 return addr->a_ifindex; 699} 700 701void rtnl_addr_set_family(struct rtnl_addr *addr, int family) 702{ 703 addr->a_family = family; 704 addr->ce_mask |= ADDR_ATTR_FAMILY; 705} 706 707int rtnl_addr_get_family(struct rtnl_addr *addr) 708{ 709 return addr->a_family; 710} 711 712void rtnl_addr_set_prefixlen(struct rtnl_addr *addr, int prefix) 713{ 714 addr->a_prefixlen = prefix; 715 addr->ce_mask |= ADDR_ATTR_PREFIXLEN; 716} 717 718int rtnl_addr_get_prefixlen(struct rtnl_addr *addr) 719{ 720 return addr->a_prefixlen; 721} 722 723void rtnl_addr_set_scope(struct rtnl_addr *addr, int scope) 724{ 725 addr->a_scope = scope; 726 addr->ce_mask |= ADDR_ATTR_SCOPE; 727} 728 729int rtnl_addr_get_scope(struct rtnl_addr *addr) 730{ 731 return addr->a_scope; 732} 733 734void rtnl_addr_set_flags(struct rtnl_addr *addr, unsigned int flags) 735{ 736 addr->a_flag_mask |= flags; 737 addr->a_flags |= flags; 738 addr->ce_mask |= ADDR_ATTR_FLAGS; 739} 740 741void rtnl_addr_unset_flags(struct rtnl_addr *addr, unsigned int flags) 742{ 743 addr->a_flag_mask |= flags; 744 addr->a_flags &= ~flags; 745 addr->ce_mask |= ADDR_ATTR_FLAGS; 746} 747 748unsigned int rtnl_addr_get_flags(struct rtnl_addr *addr) 749{ 750 return addr->a_flags; 751} 752 753static inline int __assign_addr(struct rtnl_addr *addr, struct nl_addr **pos, 754 struct nl_addr *new, int flag) 755{ 756 if (addr->ce_mask & ADDR_ATTR_FAMILY) { 757 if (new->a_family != addr->a_family) 758 return -NLE_AF_MISMATCH; 759 } else 760 addr->a_family = new->a_family; 761 762 if (*pos) 763 nl_addr_put(*pos); 764 765 *pos = nl_addr_get(new); 766 addr->ce_mask |= (flag | ADDR_ATTR_FAMILY); 767 768 return 0; 769} 770 771int rtnl_addr_set_local(struct rtnl_addr *addr, struct nl_addr *local) 772{ 773 int err; 774 775 err = __assign_addr(addr, &addr->a_local, local, ADDR_ATTR_LOCAL); 776 if (err < 0) 777 return err; 778 779 if (!(addr->ce_mask & ADDR_ATTR_PEER)) { 780 addr->a_prefixlen = nl_addr_get_prefixlen(addr->a_local); 781 addr->ce_mask |= ADDR_ATTR_PREFIXLEN; 782 } 783 784 return 0; 785} 786 787struct nl_addr *rtnl_addr_get_local(struct rtnl_addr *addr) 788{ 789 return addr->a_local; 790} 791 792int rtnl_addr_set_peer(struct rtnl_addr *addr, struct nl_addr *peer) 793{ 794 return __assign_addr(addr, &addr->a_peer, peer, ADDR_ATTR_PEER); 795 796 addr->a_prefixlen = nl_addr_get_prefixlen(addr->a_peer); 797 addr->ce_mask |= ADDR_ATTR_PREFIXLEN; 798 799 return 0; 800} 801 802struct nl_addr *rtnl_addr_get_peer(struct rtnl_addr *addr) 803{ 804 return addr->a_peer; 805} 806 807int rtnl_addr_set_broadcast(struct rtnl_addr *addr, struct nl_addr *bcast) 808{ 809 return __assign_addr(addr, &addr->a_bcast, bcast, ADDR_ATTR_BROADCAST); 810} 811 812struct nl_addr *rtnl_addr_get_broadcast(struct rtnl_addr *addr) 813{ 814 return addr->a_bcast; 815} 816 817int rtnl_addr_set_multicast(struct rtnl_addr *addr, struct nl_addr *multicast) 818{ 819 return __assign_addr(addr, &addr->a_multicast, multicast, 820 ADDR_ATTR_MULTICAST); 821} 822 823struct nl_addr *rtnl_addr_get_multicast(struct rtnl_addr *addr) 824{ 825 return addr->a_multicast; 826} 827 828uint32_t rtnl_addr_get_valid_lifetime(struct rtnl_addr *addr) 829{ 830 if (addr->ce_mask & ADDR_ATTR_CACHEINFO) 831 return addr->a_cacheinfo.aci_valid; 832 else 833 return 0xFFFFFFFFU; 834} 835 836void rtnl_addr_set_valid_lifetime(struct rtnl_addr *addr, uint32_t lifetime) 837{ 838 addr->a_cacheinfo.aci_valid = lifetime; 839 addr->ce_mask |= ADDR_ATTR_CACHEINFO; 840} 841 842uint32_t rtnl_addr_get_preferred_lifetime(struct rtnl_addr *addr) 843{ 844 if (addr->ce_mask & ADDR_ATTR_CACHEINFO) 845 return addr->a_cacheinfo.aci_prefered; 846 else 847 return 0xFFFFFFFFU; 848} 849 850void rtnl_addr_set_preferred_lifetime(struct rtnl_addr *addr, uint32_t lifetime) 851{ 852 addr->a_cacheinfo.aci_prefered = lifetime; 853 addr->ce_mask |= ADDR_ATTR_CACHEINFO; 854} 855 856uint32_t rtnl_addr_get_create_time(struct rtnl_addr *addr) 857{ 858 return addr->a_cacheinfo.aci_cstamp; 859} 860 861uint32_t rtnl_addr_get_last_update_time(struct rtnl_addr *addr) 862{ 863 return addr->a_cacheinfo.aci_tstamp; 864} 865 866/** @} */ 867 868/** 869 * @name Flags Translations 870 * @{ 871 */ 872 873static struct trans_tbl addr_flags[] = { 874 __ADD(IFA_F_SECONDARY, secondary) 875 __ADD(IFA_F_NODAD, nodad) 876 __ADD(IFA_F_OPTIMISTIC, optimistic) 877 __ADD(IFA_F_HOMEADDRESS, homeaddress) 878 __ADD(IFA_F_DEPRECATED, deprecated) 879 __ADD(IFA_F_TENTATIVE, tentative) 880 __ADD(IFA_F_PERMANENT, permanent) 881}; 882 883char *rtnl_addr_flags2str(int flags, char *buf, size_t size) 884{ 885 return __flags2str(flags, buf, size, addr_flags, 886 ARRAY_SIZE(addr_flags)); 887} 888 889int rtnl_addr_str2flags(const char *name) 890{ 891 return __str2flags(name, addr_flags, ARRAY_SIZE(addr_flags)); 892} 893 894/** @} */ 895 896static struct nl_object_ops addr_obj_ops = { 897 .oo_name = "route/addr", 898 .oo_size = sizeof(struct rtnl_addr), 899 .oo_constructor = addr_constructor, 900 .oo_free_data = addr_free_data, 901 .oo_clone = addr_clone, 902 .oo_dump = { 903 [NL_DUMP_LINE] = addr_dump_line, 904 [NL_DUMP_DETAILS] = addr_dump_details, 905 [NL_DUMP_STATS] = addr_dump_stats, 906 }, 907 .oo_compare = addr_compare, 908 .oo_attrs2str = addr_attrs2str, 909 .oo_id_attrs = (ADDR_ATTR_FAMILY | ADDR_ATTR_IFINDEX | 910 ADDR_ATTR_LOCAL | ADDR_ATTR_PREFIXLEN | 911 ADDR_ATTR_PEER), 912}; 913 914static struct nl_af_group addr_groups[] = { 915 { AF_INET, RTNLGRP_IPV4_IFADDR }, 916 { AF_INET6, RTNLGRP_IPV6_IFADDR }, 917 { END_OF_GROUP_LIST }, 918}; 919 920static struct nl_cache_ops rtnl_addr_ops = { 921 .co_name = "route/addr", 922 .co_hdrsize = sizeof(struct ifaddrmsg), 923 .co_msgtypes = { 924 { RTM_NEWADDR, NL_ACT_NEW, "new" }, 925 { RTM_DELADDR, NL_ACT_DEL, "del" }, 926 { RTM_GETADDR, NL_ACT_GET, "get" }, 927 END_OF_MSGTYPES_LIST, 928 }, 929 .co_protocol = NETLINK_ROUTE, 930 .co_groups = addr_groups, 931 .co_request_update = addr_request_update, 932 .co_msg_parser = addr_msg_parser, 933 .co_obj_ops = &addr_obj_ops, 934}; 935 936static void __init addr_init(void) 937{ 938 nl_cache_mngt_register(&rtnl_addr_ops); 939} 940 941static void __exit addr_exit(void) 942{ 943 nl_cache_mngt_unregister(&rtnl_addr_ops); 944} 945 946/** @} */ 947