1 /* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * Routing netlink socket interface: protocol independent part. 7 * 8 * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License 12 * as published by the Free Software Foundation; either version 13 * 2 of the License, or (at your option) any later version. 14 * 15 * Fixes: 16 * Vitaly E. Lavrov RTA_OK arithmetics was wrong. 17 */ 18 19 #include <linux/config.h> 20 #include <linux/errno.h> 21 #include <linux/module.h> 22 #include <linux/types.h> 23 #include <linux/socket.h> 24 #include <linux/kernel.h> 25 #include <linux/sched.h> 26 #include <linux/timer.h> 27 #include <linux/string.h> 28 #include <linux/sockios.h> 29 #include <linux/net.h> 30 #include <linux/fcntl.h> 31 #include <linux/mm.h> 32 #include <linux/slab.h> 33 #include <linux/interrupt.h> 34 #include <linux/capability.h> 35 #include <linux/skbuff.h> 36 #include <linux/init.h> 37 #include <linux/security.h> 38 39 #include <asm/uaccess.h> 40 #include <asm/system.h> 41 #include <asm/string.h> 42 43 #include <linux/inet.h> 44 #include <linux/netdevice.h> 45 #include <net/ip.h> 46 #include <net/protocol.h> 47 #include <net/arp.h> 48 #include <net/route.h> 49 #include <net/udp.h> 50 #include <net/sock.h> 51 #include <net/pkt_sched.h> 52 #include <net/netlink.h> 53 54 DECLARE_MUTEX(rtnl_sem); 55 56 void rtnl_lock(void) 57 { 58 rtnl_shlock(); 59 } 60 61 int rtnl_lock_interruptible(void) 62 { 63 return down_interruptible(&rtnl_sem); 64 } 65 66 void rtnl_unlock(void) 67 { 68 rtnl_shunlock(); 69 70 netdev_run_todo(); 71 } 72 73 int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len) 74 { 75 memset(tb, 0, sizeof(struct rtattr*)*maxattr); 76 77 while (RTA_OK(rta, len)) { 78 unsigned flavor = rta->rta_type; 79 if (flavor && flavor <= maxattr) 80 tb[flavor-1] = rta; 81 rta = RTA_NEXT(rta, len); 82 } 83 return 0; 84 } 85 86 struct sock *rtnl; 87 88 struct rtnetlink_link * rtnetlink_links[NPROTO]; 89 90 static const int rtm_min[RTM_NR_FAMILIES] = 91 { 92 [RTM_FAM(RTM_NEWLINK)] = NLMSG_LENGTH(sizeof(struct ifinfomsg)), 93 [RTM_FAM(RTM_NEWADDR)] = NLMSG_LENGTH(sizeof(struct ifaddrmsg)), 94 [RTM_FAM(RTM_NEWROUTE)] = NLMSG_LENGTH(sizeof(struct rtmsg)), 95 [RTM_FAM(RTM_NEWNEIGH)] = NLMSG_LENGTH(sizeof(struct ndmsg)), 96 [RTM_FAM(RTM_NEWRULE)] = NLMSG_LENGTH(sizeof(struct rtmsg)), 97 [RTM_FAM(RTM_NEWQDISC)] = NLMSG_LENGTH(sizeof(struct tcmsg)), 98 [RTM_FAM(RTM_NEWTCLASS)] = NLMSG_LENGTH(sizeof(struct tcmsg)), 99 [RTM_FAM(RTM_NEWTFILTER)] = NLMSG_LENGTH(sizeof(struct tcmsg)), 100 [RTM_FAM(RTM_NEWACTION)] = NLMSG_LENGTH(sizeof(struct tcamsg)), 101 [RTM_FAM(RTM_NEWPREFIX)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), 102 [RTM_FAM(RTM_GETMULTICAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), 103 [RTM_FAM(RTM_GETANYCAST)] = NLMSG_LENGTH(sizeof(struct rtgenmsg)), 104 [RTM_FAM(RTM_NEWNEIGHTBL)] = NLMSG_LENGTH(sizeof(struct ndtmsg)), 105 }; 106 107 static const int rta_max[RTM_NR_FAMILIES] = 108 { 109 [RTM_FAM(RTM_NEWLINK)] = IFLA_MAX, 110 [RTM_FAM(RTM_NEWADDR)] = IFA_MAX, 111 [RTM_FAM(RTM_NEWROUTE)] = RTA_MAX, 112 [RTM_FAM(RTM_NEWNEIGH)] = NDA_MAX, 113 [RTM_FAM(RTM_NEWRULE)] = RTA_MAX, 114 [RTM_FAM(RTM_NEWQDISC)] = TCA_MAX, 115 [RTM_FAM(RTM_NEWTCLASS)] = TCA_MAX, 116 [RTM_FAM(RTM_NEWTFILTER)] = TCA_MAX, 117 [RTM_FAM(RTM_NEWACTION)] = TCAA_MAX, 118 [RTM_FAM(RTM_NEWNEIGHTBL)] = NDTA_MAX, 119 }; 120 121 void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data) 122 { 123 struct rtattr *rta; 124 int size = RTA_LENGTH(attrlen); 125 126 rta = (struct rtattr*)skb_put(skb, RTA_ALIGN(size)); 127 rta->rta_type = attrtype; 128 rta->rta_len = size; 129 memcpy(RTA_DATA(rta), data, attrlen); 130 memset(RTA_DATA(rta) + attrlen, 0, RTA_ALIGN(size) - size); 131 } 132 133 size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size) 134 { 135 size_t ret = RTA_PAYLOAD(rta); 136 char *src = RTA_DATA(rta); 137 138 if (ret > 0 && src[ret - 1] == '\0') 139 ret--; 140 if (size > 0) { 141 size_t len = (ret >= size) ? size - 1 : ret; 142 memset(dest, 0, size); 143 memcpy(dest, src, len); 144 } 145 return ret; 146 } 147 148 int rtnetlink_send(struct sk_buff *skb, u32 pid, unsigned group, int echo) 149 { 150 int err = 0; 151 152 NETLINK_CB(skb).dst_group = group; 153 if (echo) 154 atomic_inc(&skb->users); 155 netlink_broadcast(rtnl, skb, pid, group, GFP_KERNEL); 156 if (echo) 157 err = netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT); 158 return err; 159 } 160 161 int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) 162 { 163 struct rtattr *mx = (struct rtattr*)skb->tail; 164 int i; 165 166 RTA_PUT(skb, RTA_METRICS, 0, NULL); 167 for (i=0; i<RTAX_MAX; i++) { 168 if (metrics[i]) 169 RTA_PUT(skb, i+1, sizeof(u32), metrics+i); 170 } 171 mx->rta_len = skb->tail - (u8*)mx; 172 if (mx->rta_len == RTA_LENGTH(0)) 173 skb_trim(skb, (u8*)mx - skb->data); 174 return 0; 175 176 rtattr_failure: 177 skb_trim(skb, (u8*)mx - skb->data); 178 return -1; 179 } 180 181 182 static int rtnetlink_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, 183 int type, u32 pid, u32 seq, u32 change, 184 unsigned int flags) 185 { 186 struct ifinfomsg *r; 187 struct nlmsghdr *nlh; 188 unsigned char *b = skb->tail; 189 190 nlh = NLMSG_NEW(skb, pid, seq, type, sizeof(*r), flags); 191 r = NLMSG_DATA(nlh); 192 r->ifi_family = AF_UNSPEC; 193 r->__ifi_pad = 0; 194 r->ifi_type = dev->type; 195 r->ifi_index = dev->ifindex; 196 r->ifi_flags = dev_get_flags(dev); 197 r->ifi_change = change; 198 199 RTA_PUT(skb, IFLA_IFNAME, strlen(dev->name)+1, dev->name); 200 201 if (1) { 202 u32 txqlen = dev->tx_queue_len; 203 RTA_PUT(skb, IFLA_TXQLEN, sizeof(txqlen), &txqlen); 204 } 205 206 if (1) { 207 u32 weight = dev->weight; 208 RTA_PUT(skb, IFLA_WEIGHT, sizeof(weight), &weight); 209 } 210 211 if (1) { 212 struct rtnl_link_ifmap map = { 213 .mem_start = dev->mem_start, 214 .mem_end = dev->mem_end, 215 .base_addr = dev->base_addr, 216 .irq = dev->irq, 217 .dma = dev->dma, 218 .port = dev->if_port, 219 }; 220 RTA_PUT(skb, IFLA_MAP, sizeof(map), &map); 221 } 222 223 if (dev->addr_len) { 224 RTA_PUT(skb, IFLA_ADDRESS, dev->addr_len, dev->dev_addr); 225 RTA_PUT(skb, IFLA_BROADCAST, dev->addr_len, dev->broadcast); 226 } 227 228 if (1) { 229 u32 mtu = dev->mtu; 230 RTA_PUT(skb, IFLA_MTU, sizeof(mtu), &mtu); 231 } 232 233 if (dev->ifindex != dev->iflink) { 234 u32 iflink = dev->iflink; 235 RTA_PUT(skb, IFLA_LINK, sizeof(iflink), &iflink); 236 } 237 238 if (dev->qdisc_sleeping) 239 RTA_PUT(skb, IFLA_QDISC, 240 strlen(dev->qdisc_sleeping->ops->id) + 1, 241 dev->qdisc_sleeping->ops->id); 242 243 if (dev->master) { 244 u32 master = dev->master->ifindex; 245 RTA_PUT(skb, IFLA_MASTER, sizeof(master), &master); 246 } 247 248 if (dev->get_stats) { 249 unsigned long *stats = (unsigned long*)dev->get_stats(dev); 250 if (stats) { 251 struct rtattr *a; 252 __u32 *s; 253 int i; 254 int n = sizeof(struct rtnl_link_stats)/4; 255 256 a = __RTA_PUT(skb, IFLA_STATS, n*4); 257 s = RTA_DATA(a); 258 for (i=0; i<n; i++) 259 s[i] = stats[i]; 260 } 261 } 262 nlh->nlmsg_len = skb->tail - b; 263 return skb->len; 264 265 nlmsg_failure: 266 rtattr_failure: 267 skb_trim(skb, b - skb->data); 268 return -1; 269 } 270 271 static int rtnetlink_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) 272 { 273 int idx; 274 int s_idx = cb->args[0]; 275 struct net_device *dev; 276 277 read_lock(&dev_base_lock); 278 for (dev=dev_base, idx=0; dev; dev = dev->next, idx++) { 279 if (idx < s_idx) 280 continue; 281 if (rtnetlink_fill_ifinfo(skb, dev, RTM_NEWLINK, 282 NETLINK_CB(cb->skb).pid, 283 cb->nlh->nlmsg_seq, 0, 284 NLM_F_MULTI) <= 0) 285 break; 286 } 287 read_unlock(&dev_base_lock); 288 cb->args[0] = idx; 289 290 return skb->len; 291 } 292 293 static int do_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 294 { 295 struct ifinfomsg *ifm = NLMSG_DATA(nlh); 296 struct rtattr **ida = arg; 297 struct net_device *dev; 298 int err, send_addr_notify = 0; 299 300 if (ifm->ifi_index >= 0) 301 dev = dev_get_by_index(ifm->ifi_index); 302 else if (ida[IFLA_IFNAME - 1]) { 303 char ifname[IFNAMSIZ]; 304 305 if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1], 306 IFNAMSIZ) >= IFNAMSIZ) 307 return -EINVAL; 308 dev = dev_get_by_name(ifname); 309 } else 310 return -EINVAL; 311 312 if (!dev) 313 return -ENODEV; 314 315 err = -EINVAL; 316 317 if (ifm->ifi_flags) 318 dev_change_flags(dev, ifm->ifi_flags); 319 320 if (ida[IFLA_MAP - 1]) { 321 struct rtnl_link_ifmap *u_map; 322 struct ifmap k_map; 323 324 if (!dev->set_config) { 325 err = -EOPNOTSUPP; 326 goto out; 327 } 328 329 if (!netif_device_present(dev)) { 330 err = -ENODEV; 331 goto out; 332 } 333 334 if (ida[IFLA_MAP - 1]->rta_len != RTA_LENGTH(sizeof(*u_map))) 335 goto out; 336 337 u_map = RTA_DATA(ida[IFLA_MAP - 1]); 338 339 k_map.mem_start = (unsigned long) u_map->mem_start; 340 k_map.mem_end = (unsigned long) u_map->mem_end; 341 k_map.base_addr = (unsigned short) u_map->base_addr; 342 k_map.irq = (unsigned char) u_map->irq; 343 k_map.dma = (unsigned char) u_map->dma; 344 k_map.port = (unsigned char) u_map->port; 345 346 err = dev->set_config(dev, &k_map); 347 348 if (err) 349 goto out; 350 } 351 352 if (ida[IFLA_ADDRESS - 1]) { 353 if (!dev->set_mac_address) { 354 err = -EOPNOTSUPP; 355 goto out; 356 } 357 if (!netif_device_present(dev)) { 358 err = -ENODEV; 359 goto out; 360 } 361 if (ida[IFLA_ADDRESS - 1]->rta_len != RTA_LENGTH(dev->addr_len)) 362 goto out; 363 364 err = dev->set_mac_address(dev, RTA_DATA(ida[IFLA_ADDRESS - 1])); 365 if (err) 366 goto out; 367 send_addr_notify = 1; 368 } 369 370 if (ida[IFLA_BROADCAST - 1]) { 371 if (ida[IFLA_BROADCAST - 1]->rta_len != RTA_LENGTH(dev->addr_len)) 372 goto out; 373 memcpy(dev->broadcast, RTA_DATA(ida[IFLA_BROADCAST - 1]), 374 dev->addr_len); 375 send_addr_notify = 1; 376 } 377 378 if (ida[IFLA_MTU - 1]) { 379 if (ida[IFLA_MTU - 1]->rta_len != RTA_LENGTH(sizeof(u32))) 380 goto out; 381 err = dev_set_mtu(dev, *((u32 *) RTA_DATA(ida[IFLA_MTU - 1]))); 382 383 if (err) 384 goto out; 385 386 } 387 388 if (ida[IFLA_TXQLEN - 1]) { 389 if (ida[IFLA_TXQLEN - 1]->rta_len != RTA_LENGTH(sizeof(u32))) 390 goto out; 391 392 dev->tx_queue_len = *((u32 *) RTA_DATA(ida[IFLA_TXQLEN - 1])); 393 } 394 395 if (ida[IFLA_WEIGHT - 1]) { 396 if (ida[IFLA_WEIGHT - 1]->rta_len != RTA_LENGTH(sizeof(u32))) 397 goto out; 398 399 dev->weight = *((u32 *) RTA_DATA(ida[IFLA_WEIGHT - 1])); 400 } 401 402 if (ifm->ifi_index >= 0 && ida[IFLA_IFNAME - 1]) { 403 char ifname[IFNAMSIZ]; 404 405 if (rtattr_strlcpy(ifname, ida[IFLA_IFNAME - 1], 406 IFNAMSIZ) >= IFNAMSIZ) 407 goto out; 408 err = dev_change_name(dev, ifname); 409 if (err) 410 goto out; 411 } 412 413 err = 0; 414 415 out: 416 if (send_addr_notify) 417 call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); 418 419 dev_put(dev); 420 return err; 421 } 422 423 static int rtnetlink_dump_all(struct sk_buff *skb, struct netlink_callback *cb) 424 { 425 int idx; 426 int s_idx = cb->family; 427 428 if (s_idx == 0) 429 s_idx = 1; 430 for (idx=1; idx<NPROTO; idx++) { 431 int type = cb->nlh->nlmsg_type-RTM_BASE; 432 if (idx < s_idx || idx == PF_PACKET) 433 continue; 434 if (rtnetlink_links[idx] == NULL || 435 rtnetlink_links[idx][type].dumpit == NULL) 436 continue; 437 if (idx > s_idx) 438 memset(&cb->args[0], 0, sizeof(cb->args)); 439 if (rtnetlink_links[idx][type].dumpit(skb, cb)) 440 break; 441 } 442 cb->family = idx; 443 444 return skb->len; 445 } 446 447 void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) 448 { 449 struct sk_buff *skb; 450 int size = NLMSG_SPACE(sizeof(struct ifinfomsg) + 451 sizeof(struct rtnl_link_ifmap) + 452 sizeof(struct rtnl_link_stats) + 128); 453 454 skb = alloc_skb(size, GFP_KERNEL); 455 if (!skb) 456 return; 457 458 if (rtnetlink_fill_ifinfo(skb, dev, type, current->pid, 0, change, 0) < 0) { 459 kfree_skb(skb); 460 return; 461 } 462 NETLINK_CB(skb).dst_group = RTNLGRP_LINK; 463 netlink_broadcast(rtnl, skb, 0, RTNLGRP_LINK, GFP_KERNEL); 464 } 465 466 /* Protected by RTNL sempahore. */ 467 static struct rtattr **rta_buf; 468 static int rtattr_max; 469 470 /* Process one rtnetlink message. */ 471 472 static __inline__ int 473 rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int *errp) 474 { 475 struct rtnetlink_link *link; 476 struct rtnetlink_link *link_tab; 477 int sz_idx, kind; 478 int min_len; 479 int family; 480 int type; 481 int err; 482 483 /* Only requests are handled by kernel now */ 484 if (!(nlh->nlmsg_flags&NLM_F_REQUEST)) 485 return 0; 486 487 type = nlh->nlmsg_type; 488 489 /* A control message: ignore them */ 490 if (type < RTM_BASE) 491 return 0; 492 493 /* Unknown message: reply with EINVAL */ 494 if (type > RTM_MAX) 495 goto err_inval; 496 497 type -= RTM_BASE; 498 499 /* All the messages must have at least 1 byte length */ 500 if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg))) 501 return 0; 502 503 family = ((struct rtgenmsg*)NLMSG_DATA(nlh))->rtgen_family; 504 if (family >= NPROTO) { 505 *errp = -EAFNOSUPPORT; 506 return -1; 507 } 508 509 link_tab = rtnetlink_links[family]; 510 if (link_tab == NULL) 511 link_tab = rtnetlink_links[PF_UNSPEC]; 512 link = &link_tab[type]; 513 514 sz_idx = type>>2; 515 kind = type&3; 516 517 if (kind != 2 && security_netlink_recv(skb)) { 518 *errp = -EPERM; 519 return -1; 520 } 521 522 if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) { 523 if (link->dumpit == NULL) 524 link = &(rtnetlink_links[PF_UNSPEC][type]); 525 526 if (link->dumpit == NULL) 527 goto err_inval; 528 529 if ((*errp = netlink_dump_start(rtnl, skb, nlh, 530 link->dumpit, NULL)) != 0) { 531 return -1; 532 } 533 534 netlink_queue_skip(nlh, skb); 535 return -1; 536 } 537 538 memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *))); 539 540 min_len = rtm_min[sz_idx]; 541 if (nlh->nlmsg_len < min_len) 542 goto err_inval; 543 544 if (nlh->nlmsg_len > min_len) { 545 int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); 546 struct rtattr *attr = (void*)nlh + NLMSG_ALIGN(min_len); 547 548 while (RTA_OK(attr, attrlen)) { 549 unsigned flavor = attr->rta_type; 550 if (flavor) { 551 if (flavor > rta_max[sz_idx]) 552 goto err_inval; 553 rta_buf[flavor-1] = attr; 554 } 555 attr = RTA_NEXT(attr, attrlen); 556 } 557 } 558 559 if (link->doit == NULL) 560 link = &(rtnetlink_links[PF_UNSPEC][type]); 561 if (link->doit == NULL) 562 goto err_inval; 563 err = link->doit(skb, nlh, (void *)&rta_buf[0]); 564 565 *errp = err; 566 return err; 567 568 err_inval: 569 *errp = -EINVAL; 570 return -1; 571 } 572 573 static void rtnetlink_rcv(struct sock *sk, int len) 574 { 575 unsigned int qlen = 0; 576 577 do { 578 rtnl_lock(); 579 netlink_run_queue(sk, &qlen, &rtnetlink_rcv_msg); 580 up(&rtnl_sem); 581 582 netdev_run_todo(); 583 } while (qlen); 584 } 585 586 static struct rtnetlink_link link_rtnetlink_table[RTM_NR_MSGTYPES] = 587 { 588 [RTM_GETLINK - RTM_BASE] = { .dumpit = rtnetlink_dump_ifinfo }, 589 [RTM_SETLINK - RTM_BASE] = { .doit = do_setlink }, 590 [RTM_GETADDR - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, 591 [RTM_GETROUTE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, 592 [RTM_NEWNEIGH - RTM_BASE] = { .doit = neigh_add }, 593 [RTM_DELNEIGH - RTM_BASE] = { .doit = neigh_delete }, 594 [RTM_GETNEIGH - RTM_BASE] = { .dumpit = neigh_dump_info }, 595 [RTM_GETRULE - RTM_BASE] = { .dumpit = rtnetlink_dump_all }, 596 [RTM_GETNEIGHTBL - RTM_BASE] = { .dumpit = neightbl_dump_info }, 597 [RTM_SETNEIGHTBL - RTM_BASE] = { .doit = neightbl_set }, 598 }; 599 600 static int rtnetlink_event(struct notifier_block *this, unsigned long event, void *ptr) 601 { 602 struct net_device *dev = ptr; 603 switch (event) { 604 case NETDEV_UNREGISTER: 605 rtmsg_ifinfo(RTM_DELLINK, dev, ~0U); 606 break; 607 case NETDEV_REGISTER: 608 rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); 609 break; 610 case NETDEV_UP: 611 case NETDEV_DOWN: 612 rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); 613 break; 614 case NETDEV_CHANGE: 615 case NETDEV_GOING_DOWN: 616 break; 617 default: 618 rtmsg_ifinfo(RTM_NEWLINK, dev, 0); 619 break; 620 } 621 return NOTIFY_DONE; 622 } 623 624 static struct notifier_block rtnetlink_dev_notifier = { 625 .notifier_call = rtnetlink_event, 626 }; 627 628 void __init rtnetlink_init(void) 629 { 630 int i; 631 632 rtattr_max = 0; 633 for (i = 0; i < ARRAY_SIZE(rta_max); i++) 634 if (rta_max[i] > rtattr_max) 635 rtattr_max = rta_max[i]; 636 rta_buf = kmalloc(rtattr_max * sizeof(struct rtattr *), GFP_KERNEL); 637 if (!rta_buf) 638 panic("rtnetlink_init: cannot allocate rta_buf\n"); 639 640 rtnl = netlink_kernel_create(NETLINK_ROUTE, RTNLGRP_MAX, rtnetlink_rcv, 641 THIS_MODULE); 642 if (rtnl == NULL) 643 panic("rtnetlink_init: cannot initialize rtnetlink\n"); 644 netlink_set_nonroot(NETLINK_ROUTE, NL_NONROOT_RECV); 645 register_netdevice_notifier(&rtnetlink_dev_notifier); 646 rtnetlink_links[PF_UNSPEC] = link_rtnetlink_table; 647 rtnetlink_links[PF_PACKET] = link_rtnetlink_table; 648 } 649 650 EXPORT_SYMBOL(__rta_fill); 651 EXPORT_SYMBOL(rtattr_strlcpy); 652 EXPORT_SYMBOL(rtattr_parse); 653 EXPORT_SYMBOL(rtnetlink_links); 654 EXPORT_SYMBOL(rtnetlink_put_metrics); 655 EXPORT_SYMBOL(rtnl); 656 EXPORT_SYMBOL(rtnl_lock); 657 EXPORT_SYMBOL(rtnl_lock_interruptible); 658 EXPORT_SYMBOL(rtnl_sem); 659 EXPORT_SYMBOL(rtnl_unlock); 660