1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * IPv6 Address Label subsystem 4 * for the IPv6 "Default" Source Address Selection 5 * 6 * Copyright (C)2007 USAGI/WIDE Project 7 */ 8 /* 9 * Author: 10 * YOSHIFUJI Hideaki @ USAGI/WIDE Project <yoshfuji@linux-ipv6.org> 11 */ 12 13 #include <linux/kernel.h> 14 #include <linux/list.h> 15 #include <linux/rcupdate.h> 16 #include <linux/in6.h> 17 #include <linux/slab.h> 18 #include <net/addrconf.h> 19 #include <linux/if_addrlabel.h> 20 #include <linux/netlink.h> 21 #include <linux/rtnetlink.h> 22 23 #if 0 24 #define ADDRLABEL(x...) printk(x) 25 #else 26 #define ADDRLABEL(x...) do { ; } while (0) 27 #endif 28 29 /* 30 * Policy Table 31 */ 32 struct ip6addrlbl_entry { 33 struct in6_addr prefix; 34 int prefixlen; 35 int ifindex; 36 int addrtype; 37 u32 label; 38 struct hlist_node list; 39 struct rcu_head rcu; 40 }; 41 42 /* 43 * Default policy table (RFC6724 + extensions) 44 * 45 * prefix addr_type label 46 * ------------------------------------------------------------------------- 47 * ::1/128 LOOPBACK 0 48 * ::/0 N/A 1 49 * 2002::/16 N/A 2 50 * ::/96 COMPATv4 3 51 * ::ffff:0:0/96 V4MAPPED 4 52 * fc00::/7 N/A 5 ULA (RFC 4193) 53 * 2001::/32 N/A 6 Teredo (RFC 4380) 54 * 2001:10::/28 N/A 7 ORCHID (RFC 4843) 55 * fec0::/10 N/A 11 Site-local 56 * (deprecated by RFC3879) 57 * 3ffe::/16 N/A 12 6bone 58 * 59 * Note: 0xffffffff is used if we do not have any policies. 60 * Note: Labels for ULA and 6to4 are different from labels listed in RFC6724. 61 */ 62 63 #define IPV6_ADDR_LABEL_DEFAULT 0xffffffffUL 64 65 static const __net_initconst struct ip6addrlbl_init_table 66 { 67 const struct in6_addr *prefix; 68 int prefixlen; 69 u32 label; 70 } ip6addrlbl_init_table[] = { 71 { /* ::/0 */ 72 .prefix = &in6addr_any, 73 .label = 1, 74 }, { /* fc00::/7 */ 75 .prefix = &(struct in6_addr){ { { 0xfc } } } , 76 .prefixlen = 7, 77 .label = 5, 78 }, { /* fec0::/10 */ 79 .prefix = &(struct in6_addr){ { { 0xfe, 0xc0 } } }, 80 .prefixlen = 10, 81 .label = 11, 82 }, { /* 2002::/16 */ 83 .prefix = &(struct in6_addr){ { { 0x20, 0x02 } } }, 84 .prefixlen = 16, 85 .label = 2, 86 }, { /* 3ffe::/16 */ 87 .prefix = &(struct in6_addr){ { { 0x3f, 0xfe } } }, 88 .prefixlen = 16, 89 .label = 12, 90 }, { /* 2001::/32 */ 91 .prefix = &(struct in6_addr){ { { 0x20, 0x01 } } }, 92 .prefixlen = 32, 93 .label = 6, 94 }, { /* 2001:10::/28 */ 95 .prefix = &(struct in6_addr){ { { 0x20, 0x01, 0x00, 0x10 } } }, 96 .prefixlen = 28, 97 .label = 7, 98 }, { /* ::ffff:0:0 */ 99 .prefix = &(struct in6_addr){ { { [10] = 0xff, [11] = 0xff } } }, 100 .prefixlen = 96, 101 .label = 4, 102 }, { /* ::/96 */ 103 .prefix = &in6addr_any, 104 .prefixlen = 96, 105 .label = 3, 106 }, { /* ::1/128 */ 107 .prefix = &in6addr_loopback, 108 .prefixlen = 128, 109 .label = 0, 110 } 111 }; 112 113 /* Find label */ 114 static bool __ip6addrlbl_match(const struct ip6addrlbl_entry *p, 115 const struct in6_addr *addr, 116 int addrtype, int ifindex) 117 { 118 if (p->ifindex && p->ifindex != ifindex) 119 return false; 120 if (p->addrtype && p->addrtype != addrtype) 121 return false; 122 if (!ipv6_prefix_equal(addr, &p->prefix, p->prefixlen)) 123 return false; 124 return true; 125 } 126 127 static struct ip6addrlbl_entry *__ipv6_addr_label(struct net *net, 128 const struct in6_addr *addr, 129 int type, int ifindex) 130 { 131 struct ip6addrlbl_entry *p; 132 133 hlist_for_each_entry_rcu(p, &net->ipv6.ip6addrlbl_table.head, list) { 134 if (__ip6addrlbl_match(p, addr, type, ifindex)) 135 return p; 136 } 137 return NULL; 138 } 139 140 u32 ipv6_addr_label(struct net *net, 141 const struct in6_addr *addr, int type, int ifindex) 142 { 143 u32 label; 144 struct ip6addrlbl_entry *p; 145 146 type &= IPV6_ADDR_MAPPED | IPV6_ADDR_COMPATv4 | IPV6_ADDR_LOOPBACK; 147 148 rcu_read_lock(); 149 p = __ipv6_addr_label(net, addr, type, ifindex); 150 label = p ? p->label : IPV6_ADDR_LABEL_DEFAULT; 151 rcu_read_unlock(); 152 153 ADDRLABEL(KERN_DEBUG "%s(addr=%pI6, type=%d, ifindex=%d) => %08x\n", 154 __func__, addr, type, ifindex, label); 155 156 return label; 157 } 158 159 /* allocate one entry */ 160 static struct ip6addrlbl_entry *ip6addrlbl_alloc(const struct in6_addr *prefix, 161 int prefixlen, int ifindex, 162 u32 label) 163 { 164 struct ip6addrlbl_entry *newp; 165 int addrtype; 166 167 ADDRLABEL(KERN_DEBUG "%s(prefix=%pI6, prefixlen=%d, ifindex=%d, label=%u)\n", 168 __func__, prefix, prefixlen, ifindex, (unsigned int)label); 169 170 addrtype = ipv6_addr_type(prefix) & (IPV6_ADDR_MAPPED | IPV6_ADDR_COMPATv4 | IPV6_ADDR_LOOPBACK); 171 172 switch (addrtype) { 173 case IPV6_ADDR_MAPPED: 174 if (prefixlen > 96) 175 return ERR_PTR(-EINVAL); 176 if (prefixlen < 96) 177 addrtype = 0; 178 break; 179 case IPV6_ADDR_COMPATv4: 180 if (prefixlen != 96) 181 addrtype = 0; 182 break; 183 case IPV6_ADDR_LOOPBACK: 184 if (prefixlen != 128) 185 addrtype = 0; 186 break; 187 } 188 189 newp = kmalloc(sizeof(*newp), GFP_KERNEL); 190 if (!newp) 191 return ERR_PTR(-ENOMEM); 192 193 ipv6_addr_prefix(&newp->prefix, prefix, prefixlen); 194 newp->prefixlen = prefixlen; 195 newp->ifindex = ifindex; 196 newp->addrtype = addrtype; 197 newp->label = label; 198 INIT_HLIST_NODE(&newp->list); 199 return newp; 200 } 201 202 /* add a label */ 203 static int __ip6addrlbl_add(struct net *net, struct ip6addrlbl_entry *newp, 204 int replace) 205 { 206 struct ip6addrlbl_entry *last = NULL, *p = NULL; 207 struct hlist_node *n; 208 int ret = 0; 209 210 ADDRLABEL(KERN_DEBUG "%s(newp=%p, replace=%d)\n", __func__, newp, 211 replace); 212 213 hlist_for_each_entry_safe(p, n, &net->ipv6.ip6addrlbl_table.head, list) { 214 if (p->prefixlen == newp->prefixlen && 215 p->ifindex == newp->ifindex && 216 ipv6_addr_equal(&p->prefix, &newp->prefix)) { 217 if (!replace) { 218 ret = -EEXIST; 219 goto out; 220 } 221 hlist_replace_rcu(&p->list, &newp->list); 222 kfree_rcu(p, rcu); 223 goto out; 224 } else if ((p->prefixlen == newp->prefixlen && !p->ifindex) || 225 (p->prefixlen < newp->prefixlen)) { 226 hlist_add_before_rcu(&newp->list, &p->list); 227 goto out; 228 } 229 last = p; 230 } 231 if (last) 232 hlist_add_behind_rcu(&newp->list, &last->list); 233 else 234 hlist_add_head_rcu(&newp->list, &net->ipv6.ip6addrlbl_table.head); 235 out: 236 if (!ret) 237 WRITE_ONCE(net->ipv6.ip6addrlbl_table.seq, 238 net->ipv6.ip6addrlbl_table.seq + 1); 239 return ret; 240 } 241 242 /* add a label */ 243 static int ip6addrlbl_add(struct net *net, 244 const struct in6_addr *prefix, int prefixlen, 245 int ifindex, u32 label, int replace) 246 { 247 struct ip6addrlbl_entry *newp; 248 int ret = 0; 249 250 ADDRLABEL(KERN_DEBUG "%s(prefix=%pI6, prefixlen=%d, ifindex=%d, label=%u, replace=%d)\n", 251 __func__, prefix, prefixlen, ifindex, (unsigned int)label, 252 replace); 253 254 newp = ip6addrlbl_alloc(prefix, prefixlen, ifindex, label); 255 if (IS_ERR(newp)) 256 return PTR_ERR(newp); 257 spin_lock(&net->ipv6.ip6addrlbl_table.lock); 258 ret = __ip6addrlbl_add(net, newp, replace); 259 spin_unlock(&net->ipv6.ip6addrlbl_table.lock); 260 if (ret) 261 kfree(newp); 262 return ret; 263 } 264 265 /* remove a label */ 266 static int __ip6addrlbl_del(struct net *net, 267 const struct in6_addr *prefix, int prefixlen, 268 int ifindex) 269 { 270 struct ip6addrlbl_entry *p = NULL; 271 struct hlist_node *n; 272 int ret = -ESRCH; 273 274 ADDRLABEL(KERN_DEBUG "%s(prefix=%pI6, prefixlen=%d, ifindex=%d)\n", 275 __func__, prefix, prefixlen, ifindex); 276 277 hlist_for_each_entry_safe(p, n, &net->ipv6.ip6addrlbl_table.head, list) { 278 if (p->prefixlen == prefixlen && 279 p->ifindex == ifindex && 280 ipv6_addr_equal(&p->prefix, prefix)) { 281 hlist_del_rcu(&p->list); 282 kfree_rcu(p, rcu); 283 ret = 0; 284 break; 285 } 286 } 287 return ret; 288 } 289 290 static int ip6addrlbl_del(struct net *net, 291 const struct in6_addr *prefix, int prefixlen, 292 int ifindex) 293 { 294 struct in6_addr prefix_buf; 295 int ret; 296 297 ADDRLABEL(KERN_DEBUG "%s(prefix=%pI6, prefixlen=%d, ifindex=%d)\n", 298 __func__, prefix, prefixlen, ifindex); 299 300 ipv6_addr_prefix(&prefix_buf, prefix, prefixlen); 301 spin_lock(&net->ipv6.ip6addrlbl_table.lock); 302 ret = __ip6addrlbl_del(net, &prefix_buf, prefixlen, ifindex); 303 spin_unlock(&net->ipv6.ip6addrlbl_table.lock); 304 return ret; 305 } 306 307 /* add default label */ 308 static int __net_init ip6addrlbl_net_init(struct net *net) 309 { 310 struct ip6addrlbl_entry *p = NULL; 311 struct hlist_node *n; 312 int err; 313 int i; 314 315 ADDRLABEL(KERN_DEBUG "%s\n", __func__); 316 317 spin_lock_init(&net->ipv6.ip6addrlbl_table.lock); 318 INIT_HLIST_HEAD(&net->ipv6.ip6addrlbl_table.head); 319 320 for (i = 0; i < ARRAY_SIZE(ip6addrlbl_init_table); i++) { 321 err = ip6addrlbl_add(net, 322 ip6addrlbl_init_table[i].prefix, 323 ip6addrlbl_init_table[i].prefixlen, 324 0, 325 ip6addrlbl_init_table[i].label, 0); 326 if (err) 327 goto err_ip6addrlbl_add; 328 } 329 return 0; 330 331 err_ip6addrlbl_add: 332 hlist_for_each_entry_safe(p, n, &net->ipv6.ip6addrlbl_table.head, list) { 333 hlist_del_rcu(&p->list); 334 kfree_rcu(p, rcu); 335 } 336 return err; 337 } 338 339 static void __net_exit ip6addrlbl_net_exit(struct net *net) 340 { 341 struct ip6addrlbl_entry *p = NULL; 342 struct hlist_node *n; 343 344 /* Remove all labels belonging to the exiting net */ 345 spin_lock(&net->ipv6.ip6addrlbl_table.lock); 346 hlist_for_each_entry_safe(p, n, &net->ipv6.ip6addrlbl_table.head, list) { 347 hlist_del_rcu(&p->list); 348 kfree_rcu(p, rcu); 349 } 350 spin_unlock(&net->ipv6.ip6addrlbl_table.lock); 351 } 352 353 static struct pernet_operations ipv6_addr_label_ops = { 354 .init = ip6addrlbl_net_init, 355 .exit = ip6addrlbl_net_exit, 356 }; 357 358 int __init ipv6_addr_label_init(void) 359 { 360 return register_pernet_subsys(&ipv6_addr_label_ops); 361 } 362 363 void ipv6_addr_label_cleanup(void) 364 { 365 unregister_pernet_subsys(&ipv6_addr_label_ops); 366 } 367 368 static const struct nla_policy ifal_policy[IFAL_MAX+1] = { 369 [IFAL_ADDRESS] = { .len = sizeof(struct in6_addr), }, 370 [IFAL_LABEL] = { .len = sizeof(u32), }, 371 }; 372 373 static bool addrlbl_ifindex_exists(struct net *net, int ifindex) 374 { 375 376 struct net_device *dev; 377 378 rcu_read_lock(); 379 dev = dev_get_by_index_rcu(net, ifindex); 380 rcu_read_unlock(); 381 382 return dev != NULL; 383 } 384 385 static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh, 386 struct netlink_ext_ack *extack) 387 { 388 struct net *net = sock_net(skb->sk); 389 struct ifaddrlblmsg *ifal; 390 struct nlattr *tb[IFAL_MAX+1]; 391 struct in6_addr *pfx; 392 u32 label; 393 int err = 0; 394 395 err = nlmsg_parse_deprecated(nlh, sizeof(*ifal), tb, IFAL_MAX, 396 ifal_policy, extack); 397 if (err < 0) 398 return err; 399 400 ifal = nlmsg_data(nlh); 401 402 if (ifal->ifal_family != AF_INET6 || 403 ifal->ifal_prefixlen > 128) 404 return -EINVAL; 405 406 if (!tb[IFAL_ADDRESS]) 407 return -EINVAL; 408 pfx = nla_data(tb[IFAL_ADDRESS]); 409 410 if (!tb[IFAL_LABEL]) 411 return -EINVAL; 412 label = nla_get_u32(tb[IFAL_LABEL]); 413 if (label == IPV6_ADDR_LABEL_DEFAULT) 414 return -EINVAL; 415 416 switch (nlh->nlmsg_type) { 417 case RTM_NEWADDRLABEL: 418 if (ifal->ifal_index && 419 !addrlbl_ifindex_exists(net, ifal->ifal_index)) 420 return -EINVAL; 421 422 err = ip6addrlbl_add(net, pfx, ifal->ifal_prefixlen, 423 ifal->ifal_index, label, 424 nlh->nlmsg_flags & NLM_F_REPLACE); 425 break; 426 case RTM_DELADDRLABEL: 427 err = ip6addrlbl_del(net, pfx, ifal->ifal_prefixlen, 428 ifal->ifal_index); 429 break; 430 default: 431 err = -EOPNOTSUPP; 432 } 433 return err; 434 } 435 436 static void ip6addrlbl_putmsg(struct nlmsghdr *nlh, 437 int prefixlen, int ifindex, u32 lseq) 438 { 439 struct ifaddrlblmsg *ifal = nlmsg_data(nlh); 440 ifal->ifal_family = AF_INET6; 441 ifal->__ifal_reserved = 0; 442 ifal->ifal_prefixlen = prefixlen; 443 ifal->ifal_flags = 0; 444 ifal->ifal_index = ifindex; 445 ifal->ifal_seq = lseq; 446 }; 447 448 static int ip6addrlbl_fill(struct sk_buff *skb, 449 const struct ip6addrlbl_entry *p, 450 u32 lseq, 451 u32 portid, u32 seq, int event, 452 unsigned int flags) 453 { 454 struct nlmsghdr *nlh = nlmsg_put(skb, portid, seq, event, 455 sizeof(struct ifaddrlblmsg), flags); 456 if (!nlh) 457 return -EMSGSIZE; 458 459 ip6addrlbl_putmsg(nlh, p->prefixlen, p->ifindex, lseq); 460 461 if (nla_put_in6_addr(skb, IFAL_ADDRESS, &p->prefix) < 0 || 462 nla_put_u32(skb, IFAL_LABEL, p->label) < 0) { 463 nlmsg_cancel(skb, nlh); 464 return -EMSGSIZE; 465 } 466 467 nlmsg_end(skb, nlh); 468 return 0; 469 } 470 471 static int ip6addrlbl_valid_dump_req(const struct nlmsghdr *nlh, 472 struct netlink_ext_ack *extack) 473 { 474 struct ifaddrlblmsg *ifal; 475 476 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifal))) { 477 NL_SET_ERR_MSG_MOD(extack, "Invalid header for address label dump request"); 478 return -EINVAL; 479 } 480 481 ifal = nlmsg_data(nlh); 482 if (ifal->__ifal_reserved || ifal->ifal_prefixlen || 483 ifal->ifal_flags || ifal->ifal_index || ifal->ifal_seq) { 484 NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for address label dump request"); 485 return -EINVAL; 486 } 487 488 if (nlmsg_attrlen(nlh, sizeof(*ifal))) { 489 NL_SET_ERR_MSG_MOD(extack, "Invalid data after header for address label dump request"); 490 return -EINVAL; 491 } 492 493 return 0; 494 } 495 496 static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb) 497 { 498 const struct nlmsghdr *nlh = cb->nlh; 499 struct net *net = sock_net(skb->sk); 500 struct ip6addrlbl_entry *p; 501 int idx = 0, s_idx = cb->args[0]; 502 int err = 0; 503 u32 lseq; 504 505 if (cb->strict_check) { 506 err = ip6addrlbl_valid_dump_req(nlh, cb->extack); 507 if (err < 0) 508 return err; 509 } 510 511 rcu_read_lock(); 512 lseq = READ_ONCE(net->ipv6.ip6addrlbl_table.seq); 513 hlist_for_each_entry_rcu(p, &net->ipv6.ip6addrlbl_table.head, list) { 514 if (idx >= s_idx) { 515 err = ip6addrlbl_fill(skb, p, 516 lseq, 517 NETLINK_CB(cb->skb).portid, 518 nlh->nlmsg_seq, 519 RTM_NEWADDRLABEL, 520 NLM_F_MULTI); 521 if (err < 0) 522 break; 523 } 524 idx++; 525 } 526 rcu_read_unlock(); 527 cb->args[0] = idx; 528 return err; 529 } 530 531 static inline int ip6addrlbl_msgsize(void) 532 { 533 return NLMSG_ALIGN(sizeof(struct ifaddrlblmsg)) 534 + nla_total_size(16) /* IFAL_ADDRESS */ 535 + nla_total_size(4); /* IFAL_LABEL */ 536 } 537 538 static int ip6addrlbl_valid_get_req(struct sk_buff *skb, 539 const struct nlmsghdr *nlh, 540 struct nlattr **tb, 541 struct netlink_ext_ack *extack) 542 { 543 struct ifaddrlblmsg *ifal; 544 int i, err; 545 546 if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*ifal))) { 547 NL_SET_ERR_MSG_MOD(extack, "Invalid header for addrlabel get request"); 548 return -EINVAL; 549 } 550 551 if (!netlink_strict_get_check(skb)) 552 return nlmsg_parse_deprecated(nlh, sizeof(*ifal), tb, 553 IFAL_MAX, ifal_policy, extack); 554 555 ifal = nlmsg_data(nlh); 556 if (ifal->__ifal_reserved || ifal->ifal_flags || ifal->ifal_seq) { 557 NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for addrlabel get request"); 558 return -EINVAL; 559 } 560 561 err = nlmsg_parse_deprecated_strict(nlh, sizeof(*ifal), tb, IFAL_MAX, 562 ifal_policy, extack); 563 if (err) 564 return err; 565 566 for (i = 0; i <= IFAL_MAX; i++) { 567 if (!tb[i]) 568 continue; 569 570 switch (i) { 571 case IFAL_ADDRESS: 572 break; 573 default: 574 NL_SET_ERR_MSG_MOD(extack, "Unsupported attribute in addrlabel get request"); 575 return -EINVAL; 576 } 577 } 578 579 return 0; 580 } 581 582 static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr *nlh, 583 struct netlink_ext_ack *extack) 584 { 585 struct net *net = sock_net(in_skb->sk); 586 struct ifaddrlblmsg *ifal; 587 struct nlattr *tb[IFAL_MAX+1]; 588 struct in6_addr *addr; 589 u32 lseq; 590 int err = 0; 591 struct ip6addrlbl_entry *p; 592 struct sk_buff *skb; 593 594 err = ip6addrlbl_valid_get_req(in_skb, nlh, tb, extack); 595 if (err < 0) 596 return err; 597 598 ifal = nlmsg_data(nlh); 599 600 if (ifal->ifal_family != AF_INET6 || 601 ifal->ifal_prefixlen != 128) 602 return -EINVAL; 603 604 if (ifal->ifal_index && 605 !addrlbl_ifindex_exists(net, ifal->ifal_index)) 606 return -EINVAL; 607 608 if (!tb[IFAL_ADDRESS]) 609 return -EINVAL; 610 addr = nla_data(tb[IFAL_ADDRESS]); 611 612 skb = nlmsg_new(ip6addrlbl_msgsize(), GFP_KERNEL); 613 if (!skb) 614 return -ENOBUFS; 615 616 err = -ESRCH; 617 618 rcu_read_lock(); 619 p = __ipv6_addr_label(net, addr, ipv6_addr_type(addr), ifal->ifal_index); 620 lseq = READ_ONCE(net->ipv6.ip6addrlbl_table.seq); 621 if (p) 622 err = ip6addrlbl_fill(skb, p, lseq, 623 NETLINK_CB(in_skb).portid, 624 nlh->nlmsg_seq, 625 RTM_NEWADDRLABEL, 0); 626 rcu_read_unlock(); 627 628 if (err < 0) { 629 WARN_ON(err == -EMSGSIZE); 630 kfree_skb(skb); 631 } else { 632 err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid); 633 } 634 return err; 635 } 636 637 static const struct rtnl_msg_handler ipv6_adddr_label_rtnl_msg_handlers[] __initconst_or_module = { 638 {.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_NEWADDRLABEL, 639 .doit = ip6addrlbl_newdel, .flags = RTNL_FLAG_DOIT_UNLOCKED}, 640 {.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_DELADDRLABEL, 641 .doit = ip6addrlbl_newdel, .flags = RTNL_FLAG_DOIT_UNLOCKED}, 642 {.owner = THIS_MODULE, .protocol = PF_INET6, .msgtype = RTM_GETADDRLABEL, 643 .doit = ip6addrlbl_get, .dumpit = ip6addrlbl_dump, 644 .flags = RTNL_FLAG_DOIT_UNLOCKED | RTNL_FLAG_DUMP_UNLOCKED}, 645 }; 646 647 int __init ipv6_addr_label_rtnl_register(void) 648 { 649 return rtnl_register_many(ipv6_adddr_label_rtnl_msg_handlers); 650 } 651