diff options
Diffstat (limited to 'net/core/rtnetlink.c')
-rw-r--r-- | net/core/rtnetlink.c | 378 |
1 files changed, 281 insertions, 97 deletions
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index eb42873f2a3a..31e85d327aa2 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -35,10 +35,10 @@ | |||
35 | #include <linux/security.h> | 35 | #include <linux/security.h> |
36 | #include <linux/mutex.h> | 36 | #include <linux/mutex.h> |
37 | #include <linux/if_addr.h> | 37 | #include <linux/if_addr.h> |
38 | #include <linux/pci.h> | ||
38 | 39 | ||
39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
40 | #include <asm/system.h> | 41 | #include <asm/system.h> |
41 | #include <asm/string.h> | ||
42 | 42 | ||
43 | #include <linux/inet.h> | 43 | #include <linux/inet.h> |
44 | #include <linux/netdevice.h> | 44 | #include <linux/netdevice.h> |
@@ -53,8 +53,7 @@ | |||
53 | #include <net/rtnetlink.h> | 53 | #include <net/rtnetlink.h> |
54 | #include <net/net_namespace.h> | 54 | #include <net/net_namespace.h> |
55 | 55 | ||
56 | struct rtnl_link | 56 | struct rtnl_link { |
57 | { | ||
58 | rtnl_doit_func doit; | 57 | rtnl_doit_func doit; |
59 | rtnl_dumpit_func dumpit; | 58 | rtnl_dumpit_func dumpit; |
60 | }; | 59 | }; |
@@ -65,6 +64,7 @@ void rtnl_lock(void) | |||
65 | { | 64 | { |
66 | mutex_lock(&rtnl_mutex); | 65 | mutex_lock(&rtnl_mutex); |
67 | } | 66 | } |
67 | EXPORT_SYMBOL(rtnl_lock); | ||
68 | 68 | ||
69 | void __rtnl_unlock(void) | 69 | void __rtnl_unlock(void) |
70 | { | 70 | { |
@@ -76,16 +76,27 @@ void rtnl_unlock(void) | |||
76 | /* This fellow will unlock it for us. */ | 76 | /* This fellow will unlock it for us. */ |
77 | netdev_run_todo(); | 77 | netdev_run_todo(); |
78 | } | 78 | } |
79 | EXPORT_SYMBOL(rtnl_unlock); | ||
79 | 80 | ||
80 | int rtnl_trylock(void) | 81 | int rtnl_trylock(void) |
81 | { | 82 | { |
82 | return mutex_trylock(&rtnl_mutex); | 83 | return mutex_trylock(&rtnl_mutex); |
83 | } | 84 | } |
85 | EXPORT_SYMBOL(rtnl_trylock); | ||
84 | 86 | ||
85 | int rtnl_is_locked(void) | 87 | int rtnl_is_locked(void) |
86 | { | 88 | { |
87 | return mutex_is_locked(&rtnl_mutex); | 89 | return mutex_is_locked(&rtnl_mutex); |
88 | } | 90 | } |
91 | EXPORT_SYMBOL(rtnl_is_locked); | ||
92 | |||
93 | #ifdef CONFIG_PROVE_LOCKING | ||
94 | int lockdep_rtnl_is_held(void) | ||
95 | { | ||
96 | return lockdep_is_held(&rtnl_mutex); | ||
97 | } | ||
98 | EXPORT_SYMBOL(lockdep_rtnl_is_held); | ||
99 | #endif /* #ifdef CONFIG_PROVE_LOCKING */ | ||
89 | 100 | ||
90 | static struct rtnl_link *rtnl_msg_handlers[NPROTO]; | 101 | static struct rtnl_link *rtnl_msg_handlers[NPROTO]; |
91 | 102 | ||
@@ -168,7 +179,6 @@ int __rtnl_register(int protocol, int msgtype, | |||
168 | 179 | ||
169 | return 0; | 180 | return 0; |
170 | } | 181 | } |
171 | |||
172 | EXPORT_SYMBOL_GPL(__rtnl_register); | 182 | EXPORT_SYMBOL_GPL(__rtnl_register); |
173 | 183 | ||
174 | /** | 184 | /** |
@@ -188,7 +198,6 @@ void rtnl_register(int protocol, int msgtype, | |||
188 | "protocol = %d, message type = %d\n", | 198 | "protocol = %d, message type = %d\n", |
189 | protocol, msgtype); | 199 | protocol, msgtype); |
190 | } | 200 | } |
191 | |||
192 | EXPORT_SYMBOL_GPL(rtnl_register); | 201 | EXPORT_SYMBOL_GPL(rtnl_register); |
193 | 202 | ||
194 | /** | 203 | /** |
@@ -213,7 +222,6 @@ int rtnl_unregister(int protocol, int msgtype) | |||
213 | 222 | ||
214 | return 0; | 223 | return 0; |
215 | } | 224 | } |
216 | |||
217 | EXPORT_SYMBOL_GPL(rtnl_unregister); | 225 | EXPORT_SYMBOL_GPL(rtnl_unregister); |
218 | 226 | ||
219 | /** | 227 | /** |
@@ -230,7 +238,6 @@ void rtnl_unregister_all(int protocol) | |||
230 | kfree(rtnl_msg_handlers[protocol]); | 238 | kfree(rtnl_msg_handlers[protocol]); |
231 | rtnl_msg_handlers[protocol] = NULL; | 239 | rtnl_msg_handlers[protocol] = NULL; |
232 | } | 240 | } |
233 | |||
234 | EXPORT_SYMBOL_GPL(rtnl_unregister_all); | 241 | EXPORT_SYMBOL_GPL(rtnl_unregister_all); |
235 | 242 | ||
236 | static LIST_HEAD(link_ops); | 243 | static LIST_HEAD(link_ops); |
@@ -248,12 +255,11 @@ static LIST_HEAD(link_ops); | |||
248 | int __rtnl_link_register(struct rtnl_link_ops *ops) | 255 | int __rtnl_link_register(struct rtnl_link_ops *ops) |
249 | { | 256 | { |
250 | if (!ops->dellink) | 257 | if (!ops->dellink) |
251 | ops->dellink = unregister_netdevice; | 258 | ops->dellink = unregister_netdevice_queue; |
252 | 259 | ||
253 | list_add_tail(&ops->list, &link_ops); | 260 | list_add_tail(&ops->list, &link_ops); |
254 | return 0; | 261 | return 0; |
255 | } | 262 | } |
256 | |||
257 | EXPORT_SYMBOL_GPL(__rtnl_link_register); | 263 | EXPORT_SYMBOL_GPL(__rtnl_link_register); |
258 | 264 | ||
259 | /** | 265 | /** |
@@ -271,19 +277,18 @@ int rtnl_link_register(struct rtnl_link_ops *ops) | |||
271 | rtnl_unlock(); | 277 | rtnl_unlock(); |
272 | return err; | 278 | return err; |
273 | } | 279 | } |
274 | |||
275 | EXPORT_SYMBOL_GPL(rtnl_link_register); | 280 | EXPORT_SYMBOL_GPL(rtnl_link_register); |
276 | 281 | ||
277 | static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops) | 282 | static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops) |
278 | { | 283 | { |
279 | struct net_device *dev; | 284 | struct net_device *dev; |
280 | restart: | 285 | LIST_HEAD(list_kill); |
286 | |||
281 | for_each_netdev(net, dev) { | 287 | for_each_netdev(net, dev) { |
282 | if (dev->rtnl_link_ops == ops) { | 288 | if (dev->rtnl_link_ops == ops) |
283 | ops->dellink(dev); | 289 | ops->dellink(dev, &list_kill); |
284 | goto restart; | ||
285 | } | ||
286 | } | 290 | } |
291 | unregister_netdevice_many(&list_kill); | ||
287 | } | 292 | } |
288 | 293 | ||
289 | void rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops) | 294 | void rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops) |
@@ -309,7 +314,6 @@ void __rtnl_link_unregister(struct rtnl_link_ops *ops) | |||
309 | } | 314 | } |
310 | list_del(&ops->list); | 315 | list_del(&ops->list); |
311 | } | 316 | } |
312 | |||
313 | EXPORT_SYMBOL_GPL(__rtnl_link_unregister); | 317 | EXPORT_SYMBOL_GPL(__rtnl_link_unregister); |
314 | 318 | ||
315 | /** | 319 | /** |
@@ -322,7 +326,6 @@ void rtnl_link_unregister(struct rtnl_link_ops *ops) | |||
322 | __rtnl_link_unregister(ops); | 326 | __rtnl_link_unregister(ops); |
323 | rtnl_unlock(); | 327 | rtnl_unlock(); |
324 | } | 328 | } |
325 | |||
326 | EXPORT_SYMBOL_GPL(rtnl_link_unregister); | 329 | EXPORT_SYMBOL_GPL(rtnl_link_unregister); |
327 | 330 | ||
328 | static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) | 331 | static const struct rtnl_link_ops *rtnl_link_ops_get(const char *kind) |
@@ -427,12 +430,13 @@ void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data | |||
427 | struct rtattr *rta; | 430 | struct rtattr *rta; |
428 | int size = RTA_LENGTH(attrlen); | 431 | int size = RTA_LENGTH(attrlen); |
429 | 432 | ||
430 | rta = (struct rtattr*)skb_put(skb, RTA_ALIGN(size)); | 433 | rta = (struct rtattr *)skb_put(skb, RTA_ALIGN(size)); |
431 | rta->rta_type = attrtype; | 434 | rta->rta_type = attrtype; |
432 | rta->rta_len = size; | 435 | rta->rta_len = size; |
433 | memcpy(RTA_DATA(rta), data, attrlen); | 436 | memcpy(RTA_DATA(rta), data, attrlen); |
434 | memset(RTA_DATA(rta) + attrlen, 0, RTA_ALIGN(size) - size); | 437 | memset(RTA_DATA(rta) + attrlen, 0, RTA_ALIGN(size) - size); |
435 | } | 438 | } |
439 | EXPORT_SYMBOL(__rta_fill); | ||
436 | 440 | ||
437 | int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo) | 441 | int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned group, int echo) |
438 | { | 442 | { |
@@ -454,6 +458,7 @@ int rtnl_unicast(struct sk_buff *skb, struct net *net, u32 pid) | |||
454 | 458 | ||
455 | return nlmsg_unicast(rtnl, skb, pid); | 459 | return nlmsg_unicast(rtnl, skb, pid); |
456 | } | 460 | } |
461 | EXPORT_SYMBOL(rtnl_unicast); | ||
457 | 462 | ||
458 | void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, | 463 | void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, |
459 | struct nlmsghdr *nlh, gfp_t flags) | 464 | struct nlmsghdr *nlh, gfp_t flags) |
@@ -466,6 +471,7 @@ void rtnl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, | |||
466 | 471 | ||
467 | nlmsg_notify(rtnl, skb, pid, group, report, flags); | 472 | nlmsg_notify(rtnl, skb, pid, group, report, flags); |
468 | } | 473 | } |
474 | EXPORT_SYMBOL(rtnl_notify); | ||
469 | 475 | ||
470 | void rtnl_set_sk_err(struct net *net, u32 group, int error) | 476 | void rtnl_set_sk_err(struct net *net, u32 group, int error) |
471 | { | 477 | { |
@@ -473,6 +479,7 @@ void rtnl_set_sk_err(struct net *net, u32 group, int error) | |||
473 | 479 | ||
474 | netlink_set_err(rtnl, 0, group, error); | 480 | netlink_set_err(rtnl, 0, group, error); |
475 | } | 481 | } |
482 | EXPORT_SYMBOL(rtnl_set_sk_err); | ||
476 | 483 | ||
477 | int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) | 484 | int rtnetlink_put_metrics(struct sk_buff *skb, u32 *metrics) |
478 | { | 485 | { |
@@ -501,6 +508,7 @@ nla_put_failure: | |||
501 | nla_nest_cancel(skb, mx); | 508 | nla_nest_cancel(skb, mx); |
502 | return -EMSGSIZE; | 509 | return -EMSGSIZE; |
503 | } | 510 | } |
511 | EXPORT_SYMBOL(rtnetlink_put_metrics); | ||
504 | 512 | ||
505 | int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, | 513 | int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, |
506 | u32 ts, u32 tsage, long expires, u32 error) | 514 | u32 ts, u32 tsage, long expires, u32 error) |
@@ -520,14 +528,13 @@ int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, | |||
520 | 528 | ||
521 | return nla_put(skb, RTA_CACHEINFO, sizeof(ci), &ci); | 529 | return nla_put(skb, RTA_CACHEINFO, sizeof(ci), &ci); |
522 | } | 530 | } |
523 | |||
524 | EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo); | 531 | EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo); |
525 | 532 | ||
526 | static void set_operstate(struct net_device *dev, unsigned char transition) | 533 | static void set_operstate(struct net_device *dev, unsigned char transition) |
527 | { | 534 | { |
528 | unsigned char operstate = dev->operstate; | 535 | unsigned char operstate = dev->operstate; |
529 | 536 | ||
530 | switch(transition) { | 537 | switch (transition) { |
531 | case IF_OPER_UP: | 538 | case IF_OPER_UP: |
532 | if ((operstate == IF_OPER_DORMANT || | 539 | if ((operstate == IF_OPER_DORMANT || |
533 | operstate == IF_OPER_UNKNOWN) && | 540 | operstate == IF_OPER_UNKNOWN) && |
@@ -550,6 +557,19 @@ static void set_operstate(struct net_device *dev, unsigned char transition) | |||
550 | } | 557 | } |
551 | } | 558 | } |
552 | 559 | ||
560 | static unsigned int rtnl_dev_combine_flags(const struct net_device *dev, | ||
561 | const struct ifinfomsg *ifm) | ||
562 | { | ||
563 | unsigned int flags = ifm->ifi_flags; | ||
564 | |||
565 | /* bugwards compatibility: ifi_change == 0 is treated as ~0 */ | ||
566 | if (ifm->ifi_change) | ||
567 | flags = (flags & ifm->ifi_change) | | ||
568 | (dev->flags & ~ifm->ifi_change); | ||
569 | |||
570 | return flags; | ||
571 | } | ||
572 | |||
553 | static void copy_rtnl_link_stats(struct rtnl_link_stats *a, | 573 | static void copy_rtnl_link_stats(struct rtnl_link_stats *a, |
554 | const struct net_device_stats *b) | 574 | const struct net_device_stats *b) |
555 | { | 575 | { |
@@ -582,6 +602,22 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, | |||
582 | a->tx_compressed = b->tx_compressed; | 602 | a->tx_compressed = b->tx_compressed; |
583 | }; | 603 | }; |
584 | 604 | ||
605 | /* All VF info */ | ||
606 | static inline int rtnl_vfinfo_size(const struct net_device *dev) | ||
607 | { | ||
608 | if (dev->dev.parent && dev_is_pci(dev->dev.parent)) { | ||
609 | |||
610 | int num_vfs = dev_num_vf(dev->dev.parent); | ||
611 | size_t size = nlmsg_total_size(sizeof(struct nlattr)); | ||
612 | size += nlmsg_total_size(num_vfs * sizeof(struct nlattr)); | ||
613 | size += num_vfs * (sizeof(struct ifla_vf_mac) + | ||
614 | sizeof(struct ifla_vf_vlan) + | ||
615 | sizeof(struct ifla_vf_tx_rate)); | ||
616 | return size; | ||
617 | } else | ||
618 | return 0; | ||
619 | } | ||
620 | |||
585 | static inline size_t if_nlmsg_size(const struct net_device *dev) | 621 | static inline size_t if_nlmsg_size(const struct net_device *dev) |
586 | { | 622 | { |
587 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) | 623 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) |
@@ -599,6 +635,8 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) | |||
599 | + nla_total_size(4) /* IFLA_MASTER */ | 635 | + nla_total_size(4) /* IFLA_MASTER */ |
600 | + nla_total_size(1) /* IFLA_OPERSTATE */ | 636 | + nla_total_size(1) /* IFLA_OPERSTATE */ |
601 | + nla_total_size(1) /* IFLA_LINKMODE */ | 637 | + nla_total_size(1) /* IFLA_LINKMODE */ |
638 | + nla_total_size(4) /* IFLA_NUM_VF */ | ||
639 | + rtnl_vfinfo_size(dev) /* IFLA_VFINFO_LIST */ | ||
602 | + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ | 640 | + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ |
603 | } | 641 | } |
604 | 642 | ||
@@ -667,6 +705,40 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
667 | stats = dev_get_stats(dev); | 705 | stats = dev_get_stats(dev); |
668 | copy_rtnl_link_stats(nla_data(attr), stats); | 706 | copy_rtnl_link_stats(nla_data(attr), stats); |
669 | 707 | ||
708 | if (dev->netdev_ops->ndo_get_vf_config && dev->dev.parent) { | ||
709 | int i; | ||
710 | |||
711 | struct nlattr *vfinfo, *vf; | ||
712 | int num_vfs = dev_num_vf(dev->dev.parent); | ||
713 | |||
714 | NLA_PUT_U32(skb, IFLA_NUM_VF, num_vfs); | ||
715 | vfinfo = nla_nest_start(skb, IFLA_VFINFO_LIST); | ||
716 | if (!vfinfo) | ||
717 | goto nla_put_failure; | ||
718 | for (i = 0; i < num_vfs; i++) { | ||
719 | struct ifla_vf_info ivi; | ||
720 | struct ifla_vf_mac vf_mac; | ||
721 | struct ifla_vf_vlan vf_vlan; | ||
722 | struct ifla_vf_tx_rate vf_tx_rate; | ||
723 | if (dev->netdev_ops->ndo_get_vf_config(dev, i, &ivi)) | ||
724 | break; | ||
725 | vf_mac.vf = vf_vlan.vf = vf_tx_rate.vf = ivi.vf; | ||
726 | memcpy(vf_mac.mac, ivi.mac, sizeof(ivi.mac)); | ||
727 | vf_vlan.vlan = ivi.vlan; | ||
728 | vf_vlan.qos = ivi.qos; | ||
729 | vf_tx_rate.rate = ivi.tx_rate; | ||
730 | vf = nla_nest_start(skb, IFLA_VF_INFO); | ||
731 | if (!vf) { | ||
732 | nla_nest_cancel(skb, vfinfo); | ||
733 | goto nla_put_failure; | ||
734 | } | ||
735 | NLA_PUT(skb, IFLA_VF_MAC, sizeof(vf_mac), &vf_mac); | ||
736 | NLA_PUT(skb, IFLA_VF_VLAN, sizeof(vf_vlan), &vf_vlan); | ||
737 | NLA_PUT(skb, IFLA_VF_TX_RATE, sizeof(vf_tx_rate), &vf_tx_rate); | ||
738 | nla_nest_end(skb, vf); | ||
739 | } | ||
740 | nla_nest_end(skb, vfinfo); | ||
741 | } | ||
670 | if (dev->rtnl_link_ops) { | 742 | if (dev->rtnl_link_ops) { |
671 | if (rtnl_link_fill(skb, dev) < 0) | 743 | if (rtnl_link_fill(skb, dev) < 0) |
672 | goto nla_put_failure; | 744 | goto nla_put_failure; |
@@ -682,22 +754,33 @@ nla_put_failure: | |||
682 | static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | 754 | static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) |
683 | { | 755 | { |
684 | struct net *net = sock_net(skb->sk); | 756 | struct net *net = sock_net(skb->sk); |
685 | int idx; | 757 | int h, s_h; |
686 | int s_idx = cb->args[0]; | 758 | int idx = 0, s_idx; |
687 | struct net_device *dev; | 759 | struct net_device *dev; |
688 | 760 | struct hlist_head *head; | |
689 | idx = 0; | 761 | struct hlist_node *node; |
690 | for_each_netdev(net, dev) { | 762 | |
691 | if (idx < s_idx) | 763 | s_h = cb->args[0]; |
692 | goto cont; | 764 | s_idx = cb->args[1]; |
693 | if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, | 765 | |
694 | NETLINK_CB(cb->skb).pid, | 766 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { |
695 | cb->nlh->nlmsg_seq, 0, NLM_F_MULTI) <= 0) | 767 | idx = 0; |
696 | break; | 768 | head = &net->dev_index_head[h]; |
769 | hlist_for_each_entry(dev, node, head, index_hlist) { | ||
770 | if (idx < s_idx) | ||
771 | goto cont; | ||
772 | if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, | ||
773 | NETLINK_CB(cb->skb).pid, | ||
774 | cb->nlh->nlmsg_seq, 0, | ||
775 | NLM_F_MULTI) <= 0) | ||
776 | goto out; | ||
697 | cont: | 777 | cont: |
698 | idx++; | 778 | idx++; |
779 | } | ||
699 | } | 780 | } |
700 | cb->args[0] = idx; | 781 | out: |
782 | cb->args[1] = idx; | ||
783 | cb->args[0] = h; | ||
701 | 784 | ||
702 | return skb->len; | 785 | return skb->len; |
703 | } | 786 | } |
@@ -716,13 +799,42 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
716 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, | 799 | [IFLA_LINKINFO] = { .type = NLA_NESTED }, |
717 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, | 800 | [IFLA_NET_NS_PID] = { .type = NLA_U32 }, |
718 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, | 801 | [IFLA_IFALIAS] = { .type = NLA_STRING, .len = IFALIASZ-1 }, |
802 | [IFLA_VFINFO_LIST] = {. type = NLA_NESTED }, | ||
719 | }; | 803 | }; |
804 | EXPORT_SYMBOL(ifla_policy); | ||
720 | 805 | ||
721 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { | 806 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { |
722 | [IFLA_INFO_KIND] = { .type = NLA_STRING }, | 807 | [IFLA_INFO_KIND] = { .type = NLA_STRING }, |
723 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, | 808 | [IFLA_INFO_DATA] = { .type = NLA_NESTED }, |
724 | }; | 809 | }; |
725 | 810 | ||
811 | static const struct nla_policy ifla_vfinfo_policy[IFLA_VF_INFO_MAX+1] = { | ||
812 | [IFLA_VF_INFO] = { .type = NLA_NESTED }, | ||
813 | }; | ||
814 | |||
815 | static const struct nla_policy ifla_vf_policy[IFLA_VF_MAX+1] = { | ||
816 | [IFLA_VF_MAC] = { .type = NLA_BINARY, | ||
817 | .len = sizeof(struct ifla_vf_mac) }, | ||
818 | [IFLA_VF_VLAN] = { .type = NLA_BINARY, | ||
819 | .len = sizeof(struct ifla_vf_vlan) }, | ||
820 | [IFLA_VF_TX_RATE] = { .type = NLA_BINARY, | ||
821 | .len = sizeof(struct ifla_vf_tx_rate) }, | ||
822 | }; | ||
823 | |||
824 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) | ||
825 | { | ||
826 | struct net *net; | ||
827 | /* Examine the link attributes and figure out which | ||
828 | * network namespace we are talking about. | ||
829 | */ | ||
830 | if (tb[IFLA_NET_NS_PID]) | ||
831 | net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); | ||
832 | else | ||
833 | net = get_net(src_net); | ||
834 | return net; | ||
835 | } | ||
836 | EXPORT_SYMBOL(rtnl_link_get_net); | ||
837 | |||
726 | static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) | 838 | static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) |
727 | { | 839 | { |
728 | if (dev) { | 840 | if (dev) { |
@@ -738,6 +850,52 @@ static int validate_linkmsg(struct net_device *dev, struct nlattr *tb[]) | |||
738 | return 0; | 850 | return 0; |
739 | } | 851 | } |
740 | 852 | ||
853 | static int do_setvfinfo(struct net_device *dev, struct nlattr *attr) | ||
854 | { | ||
855 | int rem, err = -EINVAL; | ||
856 | struct nlattr *vf; | ||
857 | const struct net_device_ops *ops = dev->netdev_ops; | ||
858 | |||
859 | nla_for_each_nested(vf, attr, rem) { | ||
860 | switch (nla_type(vf)) { | ||
861 | case IFLA_VF_MAC: { | ||
862 | struct ifla_vf_mac *ivm; | ||
863 | ivm = nla_data(vf); | ||
864 | err = -EOPNOTSUPP; | ||
865 | if (ops->ndo_set_vf_mac) | ||
866 | err = ops->ndo_set_vf_mac(dev, ivm->vf, | ||
867 | ivm->mac); | ||
868 | break; | ||
869 | } | ||
870 | case IFLA_VF_VLAN: { | ||
871 | struct ifla_vf_vlan *ivv; | ||
872 | ivv = nla_data(vf); | ||
873 | err = -EOPNOTSUPP; | ||
874 | if (ops->ndo_set_vf_vlan) | ||
875 | err = ops->ndo_set_vf_vlan(dev, ivv->vf, | ||
876 | ivv->vlan, | ||
877 | ivv->qos); | ||
878 | break; | ||
879 | } | ||
880 | case IFLA_VF_TX_RATE: { | ||
881 | struct ifla_vf_tx_rate *ivt; | ||
882 | ivt = nla_data(vf); | ||
883 | err = -EOPNOTSUPP; | ||
884 | if (ops->ndo_set_vf_tx_rate) | ||
885 | err = ops->ndo_set_vf_tx_rate(dev, ivt->vf, | ||
886 | ivt->rate); | ||
887 | break; | ||
888 | } | ||
889 | default: | ||
890 | err = -EINVAL; | ||
891 | break; | ||
892 | } | ||
893 | if (err) | ||
894 | break; | ||
895 | } | ||
896 | return err; | ||
897 | } | ||
898 | |||
741 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | 899 | static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, |
742 | struct nlattr **tb, char *ifname, int modified) | 900 | struct nlattr **tb, char *ifname, int modified) |
743 | { | 901 | { |
@@ -746,8 +904,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
746 | int err; | 904 | int err; |
747 | 905 | ||
748 | if (tb[IFLA_NET_NS_PID]) { | 906 | if (tb[IFLA_NET_NS_PID]) { |
749 | struct net *net; | 907 | struct net *net = rtnl_link_get_net(dev_net(dev), tb); |
750 | net = get_net_ns_by_pid(nla_get_u32(tb[IFLA_NET_NS_PID])); | ||
751 | if (IS_ERR(net)) { | 908 | if (IS_ERR(net)) { |
752 | err = PTR_ERR(net); | 909 | err = PTR_ERR(net); |
753 | goto errout; | 910 | goto errout; |
@@ -852,13 +1009,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
852 | } | 1009 | } |
853 | 1010 | ||
854 | if (ifm->ifi_flags || ifm->ifi_change) { | 1011 | if (ifm->ifi_flags || ifm->ifi_change) { |
855 | unsigned int flags = ifm->ifi_flags; | 1012 | err = dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm)); |
856 | |||
857 | /* bugwards compatibility: ifi_change == 0 is treated as ~0 */ | ||
858 | if (ifm->ifi_change) | ||
859 | flags = (flags & ifm->ifi_change) | | ||
860 | (dev->flags & ~ifm->ifi_change); | ||
861 | err = dev_change_flags(dev, flags); | ||
862 | if (err < 0) | 1013 | if (err < 0) |
863 | goto errout; | 1014 | goto errout; |
864 | } | 1015 | } |
@@ -875,6 +1026,18 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
875 | write_unlock_bh(&dev_base_lock); | 1026 | write_unlock_bh(&dev_base_lock); |
876 | } | 1027 | } |
877 | 1028 | ||
1029 | if (tb[IFLA_VFINFO_LIST]) { | ||
1030 | struct nlattr *attr; | ||
1031 | int rem; | ||
1032 | nla_for_each_nested(attr, tb[IFLA_VFINFO_LIST], rem) { | ||
1033 | if (nla_type(attr) != IFLA_VF_INFO) | ||
1034 | goto errout; | ||
1035 | err = do_setvfinfo(dev, attr); | ||
1036 | if (err < 0) | ||
1037 | goto errout; | ||
1038 | modified = 1; | ||
1039 | } | ||
1040 | } | ||
878 | err = 0; | 1041 | err = 0; |
879 | 1042 | ||
880 | errout: | 1043 | errout: |
@@ -910,9 +1073,9 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
910 | err = -EINVAL; | 1073 | err = -EINVAL; |
911 | ifm = nlmsg_data(nlh); | 1074 | ifm = nlmsg_data(nlh); |
912 | if (ifm->ifi_index > 0) | 1075 | if (ifm->ifi_index > 0) |
913 | dev = dev_get_by_index(net, ifm->ifi_index); | 1076 | dev = __dev_get_by_index(net, ifm->ifi_index); |
914 | else if (tb[IFLA_IFNAME]) | 1077 | else if (tb[IFLA_IFNAME]) |
915 | dev = dev_get_by_name(net, ifname); | 1078 | dev = __dev_get_by_name(net, ifname); |
916 | else | 1079 | else |
917 | goto errout; | 1080 | goto errout; |
918 | 1081 | ||
@@ -921,12 +1084,11 @@ static int rtnl_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
921 | goto errout; | 1084 | goto errout; |
922 | } | 1085 | } |
923 | 1086 | ||
924 | if ((err = validate_linkmsg(dev, tb)) < 0) | 1087 | err = validate_linkmsg(dev, tb); |
925 | goto errout_dev; | 1088 | if (err < 0) |
1089 | goto errout; | ||
926 | 1090 | ||
927 | err = do_setlink(dev, ifm, tb, ifname, 0); | 1091 | err = do_setlink(dev, ifm, tb, ifname, 0); |
928 | errout_dev: | ||
929 | dev_put(dev); | ||
930 | errout: | 1092 | errout: |
931 | return err; | 1093 | return err; |
932 | } | 1094 | } |
@@ -963,12 +1125,32 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
963 | if (!ops) | 1125 | if (!ops) |
964 | return -EOPNOTSUPP; | 1126 | return -EOPNOTSUPP; |
965 | 1127 | ||
966 | ops->dellink(dev); | 1128 | ops->dellink(dev, NULL); |
967 | return 0; | 1129 | return 0; |
968 | } | 1130 | } |
969 | 1131 | ||
970 | struct net_device *rtnl_create_link(struct net *net, char *ifname, | 1132 | int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm) |
971 | const struct rtnl_link_ops *ops, struct nlattr *tb[]) | 1133 | { |
1134 | unsigned int old_flags; | ||
1135 | int err; | ||
1136 | |||
1137 | old_flags = dev->flags; | ||
1138 | if (ifm && (ifm->ifi_flags || ifm->ifi_change)) { | ||
1139 | err = __dev_change_flags(dev, rtnl_dev_combine_flags(dev, ifm)); | ||
1140 | if (err < 0) | ||
1141 | return err; | ||
1142 | } | ||
1143 | |||
1144 | dev->rtnl_link_state = RTNL_LINK_INITIALIZED; | ||
1145 | rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); | ||
1146 | |||
1147 | __dev_notify_flags(dev, old_flags); | ||
1148 | return 0; | ||
1149 | } | ||
1150 | EXPORT_SYMBOL(rtnl_configure_link); | ||
1151 | |||
1152 | struct net_device *rtnl_create_link(struct net *src_net, struct net *net, | ||
1153 | char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]) | ||
972 | { | 1154 | { |
973 | int err; | 1155 | int err; |
974 | struct net_device *dev; | 1156 | struct net_device *dev; |
@@ -976,7 +1158,8 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname, | |||
976 | unsigned int real_num_queues = 1; | 1158 | unsigned int real_num_queues = 1; |
977 | 1159 | ||
978 | if (ops->get_tx_queues) { | 1160 | if (ops->get_tx_queues) { |
979 | err = ops->get_tx_queues(net, tb, &num_queues, &real_num_queues); | 1161 | err = ops->get_tx_queues(src_net, tb, &num_queues, |
1162 | &real_num_queues); | ||
980 | if (err) | 1163 | if (err) |
981 | goto err; | 1164 | goto err; |
982 | } | 1165 | } |
@@ -985,16 +1168,17 @@ struct net_device *rtnl_create_link(struct net *net, char *ifname, | |||
985 | if (!dev) | 1168 | if (!dev) |
986 | goto err; | 1169 | goto err; |
987 | 1170 | ||
1171 | dev_net_set(dev, net); | ||
1172 | dev->rtnl_link_ops = ops; | ||
1173 | dev->rtnl_link_state = RTNL_LINK_INITIALIZING; | ||
988 | dev->real_num_tx_queues = real_num_queues; | 1174 | dev->real_num_tx_queues = real_num_queues; |
1175 | |||
989 | if (strchr(dev->name, '%')) { | 1176 | if (strchr(dev->name, '%')) { |
990 | err = dev_alloc_name(dev, dev->name); | 1177 | err = dev_alloc_name(dev, dev->name); |
991 | if (err < 0) | 1178 | if (err < 0) |
992 | goto err_free; | 1179 | goto err_free; |
993 | } | 1180 | } |
994 | 1181 | ||
995 | dev_net_set(dev, net); | ||
996 | dev->rtnl_link_ops = ops; | ||
997 | |||
998 | if (tb[IFLA_MTU]) | 1182 | if (tb[IFLA_MTU]) |
999 | dev->mtu = nla_get_u32(tb[IFLA_MTU]); | 1183 | dev->mtu = nla_get_u32(tb[IFLA_MTU]); |
1000 | if (tb[IFLA_ADDRESS]) | 1184 | if (tb[IFLA_ADDRESS]) |
@@ -1017,6 +1201,7 @@ err_free: | |||
1017 | err: | 1201 | err: |
1018 | return ERR_PTR(err); | 1202 | return ERR_PTR(err); |
1019 | } | 1203 | } |
1204 | EXPORT_SYMBOL(rtnl_create_link); | ||
1020 | 1205 | ||
1021 | static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | 1206 | static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) |
1022 | { | 1207 | { |
@@ -1050,7 +1235,8 @@ replay: | |||
1050 | else | 1235 | else |
1051 | dev = NULL; | 1236 | dev = NULL; |
1052 | 1237 | ||
1053 | if ((err = validate_linkmsg(dev, tb)) < 0) | 1238 | err = validate_linkmsg(dev, tb); |
1239 | if (err < 0) | ||
1054 | return err; | 1240 | return err; |
1055 | 1241 | ||
1056 | if (tb[IFLA_LINKINFO]) { | 1242 | if (tb[IFLA_LINKINFO]) { |
@@ -1071,6 +1257,7 @@ replay: | |||
1071 | 1257 | ||
1072 | if (1) { | 1258 | if (1) { |
1073 | struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL; | 1259 | struct nlattr *attr[ops ? ops->maxtype + 1 : 0], **data = NULL; |
1260 | struct net *dest_net; | ||
1074 | 1261 | ||
1075 | if (ops) { | 1262 | if (ops) { |
1076 | if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { | 1263 | if (ops->maxtype && linkinfo[IFLA_INFO_DATA]) { |
@@ -1113,7 +1300,7 @@ replay: | |||
1113 | if (!(nlh->nlmsg_flags & NLM_F_CREATE)) | 1300 | if (!(nlh->nlmsg_flags & NLM_F_CREATE)) |
1114 | return -ENODEV; | 1301 | return -ENODEV; |
1115 | 1302 | ||
1116 | if (ifm->ifi_index || ifm->ifi_flags || ifm->ifi_change) | 1303 | if (ifm->ifi_index) |
1117 | return -EOPNOTSUPP; | 1304 | return -EOPNOTSUPP; |
1118 | if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO]) | 1305 | if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO]) |
1119 | return -EOPNOTSUPP; | 1306 | return -EOPNOTSUPP; |
@@ -1135,17 +1322,26 @@ replay: | |||
1135 | if (!ifname[0]) | 1322 | if (!ifname[0]) |
1136 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); | 1323 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); |
1137 | 1324 | ||
1138 | dev = rtnl_create_link(net, ifname, ops, tb); | 1325 | dest_net = rtnl_link_get_net(net, tb); |
1326 | dev = rtnl_create_link(net, dest_net, ifname, ops, tb); | ||
1139 | 1327 | ||
1140 | if (IS_ERR(dev)) | 1328 | if (IS_ERR(dev)) |
1141 | err = PTR_ERR(dev); | 1329 | err = PTR_ERR(dev); |
1142 | else if (ops->newlink) | 1330 | else if (ops->newlink) |
1143 | err = ops->newlink(dev, tb, data); | 1331 | err = ops->newlink(net, dev, tb, data); |
1144 | else | 1332 | else |
1145 | err = register_netdevice(dev); | 1333 | err = register_netdevice(dev); |
1146 | 1334 | ||
1147 | if (err < 0 && !IS_ERR(dev)) | 1335 | if (err < 0 && !IS_ERR(dev)) |
1148 | free_netdev(dev); | 1336 | free_netdev(dev); |
1337 | if (err < 0) | ||
1338 | goto out; | ||
1339 | |||
1340 | err = rtnl_configure_link(dev, ifm); | ||
1341 | if (err < 0) | ||
1342 | unregister_netdevice(dev); | ||
1343 | out: | ||
1344 | put_net(dest_net); | ||
1149 | return err; | 1345 | return err; |
1150 | } | 1346 | } |
1151 | } | 1347 | } |
@@ -1154,6 +1350,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
1154 | { | 1350 | { |
1155 | struct net *net = sock_net(skb->sk); | 1351 | struct net *net = sock_net(skb->sk); |
1156 | struct ifinfomsg *ifm; | 1352 | struct ifinfomsg *ifm; |
1353 | char ifname[IFNAMSIZ]; | ||
1157 | struct nlattr *tb[IFLA_MAX+1]; | 1354 | struct nlattr *tb[IFLA_MAX+1]; |
1158 | struct net_device *dev = NULL; | 1355 | struct net_device *dev = NULL; |
1159 | struct sk_buff *nskb; | 1356 | struct sk_buff *nskb; |
@@ -1163,19 +1360,23 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
1163 | if (err < 0) | 1360 | if (err < 0) |
1164 | return err; | 1361 | return err; |
1165 | 1362 | ||
1363 | if (tb[IFLA_IFNAME]) | ||
1364 | nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); | ||
1365 | |||
1166 | ifm = nlmsg_data(nlh); | 1366 | ifm = nlmsg_data(nlh); |
1167 | if (ifm->ifi_index > 0) { | 1367 | if (ifm->ifi_index > 0) |
1168 | dev = dev_get_by_index(net, ifm->ifi_index); | 1368 | dev = __dev_get_by_index(net, ifm->ifi_index); |
1169 | if (dev == NULL) | 1369 | else if (tb[IFLA_IFNAME]) |
1170 | return -ENODEV; | 1370 | dev = __dev_get_by_name(net, ifname); |
1171 | } else | 1371 | else |
1172 | return -EINVAL; | 1372 | return -EINVAL; |
1173 | 1373 | ||
1374 | if (dev == NULL) | ||
1375 | return -ENODEV; | ||
1376 | |||
1174 | nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); | 1377 | nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); |
1175 | if (nskb == NULL) { | 1378 | if (nskb == NULL) |
1176 | err = -ENOBUFS; | 1379 | return -ENOBUFS; |
1177 | goto errout; | ||
1178 | } | ||
1179 | 1380 | ||
1180 | err = rtnl_fill_ifinfo(nskb, dev, RTM_NEWLINK, NETLINK_CB(skb).pid, | 1381 | err = rtnl_fill_ifinfo(nskb, dev, RTM_NEWLINK, NETLINK_CB(skb).pid, |
1181 | nlh->nlmsg_seq, 0, 0); | 1382 | nlh->nlmsg_seq, 0, 0); |
@@ -1183,11 +1384,8 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
1183 | /* -EMSGSIZE implies BUG in if_nlmsg_size */ | 1384 | /* -EMSGSIZE implies BUG in if_nlmsg_size */ |
1184 | WARN_ON(err == -EMSGSIZE); | 1385 | WARN_ON(err == -EMSGSIZE); |
1185 | kfree_skb(nskb); | 1386 | kfree_skb(nskb); |
1186 | goto errout; | 1387 | } else |
1187 | } | 1388 | err = rtnl_unicast(nskb, net, NETLINK_CB(skb).pid); |
1188 | err = rtnl_unicast(nskb, net, NETLINK_CB(skb).pid); | ||
1189 | errout: | ||
1190 | dev_put(dev); | ||
1191 | 1389 | ||
1192 | return err; | 1390 | return err; |
1193 | } | 1391 | } |
@@ -1199,7 +1397,7 @@ static int rtnl_dump_all(struct sk_buff *skb, struct netlink_callback *cb) | |||
1199 | 1397 | ||
1200 | if (s_idx == 0) | 1398 | if (s_idx == 0) |
1201 | s_idx = 1; | 1399 | s_idx = 1; |
1202 | for (idx=1; idx<NPROTO; idx++) { | 1400 | for (idx = 1; idx < NPROTO; idx++) { |
1203 | int type = cb->nlh->nlmsg_type-RTM_BASE; | 1401 | int type = cb->nlh->nlmsg_type-RTM_BASE; |
1204 | if (idx < s_idx || idx == PF_PACKET) | 1402 | if (idx < s_idx || idx == PF_PACKET) |
1205 | continue; | 1403 | continue; |
@@ -1266,7 +1464,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1266 | if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg))) | 1464 | if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct rtgenmsg))) |
1267 | return 0; | 1465 | return 0; |
1268 | 1466 | ||
1269 | family = ((struct rtgenmsg*)NLMSG_DATA(nlh))->rtgen_family; | 1467 | family = ((struct rtgenmsg *)NLMSG_DATA(nlh))->rtgen_family; |
1270 | if (family >= NPROTO) | 1468 | if (family >= NPROTO) |
1271 | return -EAFNOSUPPORT; | 1469 | return -EAFNOSUPPORT; |
1272 | 1470 | ||
@@ -1299,7 +1497,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1299 | 1497 | ||
1300 | if (nlh->nlmsg_len > min_len) { | 1498 | if (nlh->nlmsg_len > min_len) { |
1301 | int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); | 1499 | int attrlen = nlh->nlmsg_len - NLMSG_ALIGN(min_len); |
1302 | struct rtattr *attr = (void*)nlh + NLMSG_ALIGN(min_len); | 1500 | struct rtattr *attr = (void *)nlh + NLMSG_ALIGN(min_len); |
1303 | 1501 | ||
1304 | while (RTA_OK(attr, attrlen)) { | 1502 | while (RTA_OK(attr, attrlen)) { |
1305 | unsigned flavor = attr->rta_type; | 1503 | unsigned flavor = attr->rta_type; |
@@ -1331,18 +1529,15 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi | |||
1331 | struct net_device *dev = ptr; | 1529 | struct net_device *dev = ptr; |
1332 | 1530 | ||
1333 | switch (event) { | 1531 | switch (event) { |
1334 | case NETDEV_UNREGISTER: | ||
1335 | rtmsg_ifinfo(RTM_DELLINK, dev, ~0U); | ||
1336 | break; | ||
1337 | case NETDEV_REGISTER: | ||
1338 | rtmsg_ifinfo(RTM_NEWLINK, dev, ~0U); | ||
1339 | break; | ||
1340 | case NETDEV_UP: | 1532 | case NETDEV_UP: |
1341 | case NETDEV_DOWN: | 1533 | case NETDEV_DOWN: |
1342 | rtmsg_ifinfo(RTM_NEWLINK, dev, IFF_UP|IFF_RUNNING); | 1534 | case NETDEV_PRE_UP: |
1343 | break; | 1535 | case NETDEV_POST_INIT: |
1536 | case NETDEV_REGISTER: | ||
1344 | case NETDEV_CHANGE: | 1537 | case NETDEV_CHANGE: |
1345 | case NETDEV_GOING_DOWN: | 1538 | case NETDEV_GOING_DOWN: |
1539 | case NETDEV_UNREGISTER: | ||
1540 | case NETDEV_UNREGISTER_BATCH: | ||
1346 | break; | 1541 | break; |
1347 | default: | 1542 | default: |
1348 | rtmsg_ifinfo(RTM_NEWLINK, dev, 0); | 1543 | rtmsg_ifinfo(RTM_NEWLINK, dev, 0); |
@@ -1356,7 +1551,7 @@ static struct notifier_block rtnetlink_dev_notifier = { | |||
1356 | }; | 1551 | }; |
1357 | 1552 | ||
1358 | 1553 | ||
1359 | static int rtnetlink_net_init(struct net *net) | 1554 | static int __net_init rtnetlink_net_init(struct net *net) |
1360 | { | 1555 | { |
1361 | struct sock *sk; | 1556 | struct sock *sk; |
1362 | sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX, | 1557 | sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX, |
@@ -1367,7 +1562,7 @@ static int rtnetlink_net_init(struct net *net) | |||
1367 | return 0; | 1562 | return 0; |
1368 | } | 1563 | } |
1369 | 1564 | ||
1370 | static void rtnetlink_net_exit(struct net *net) | 1565 | static void __net_exit rtnetlink_net_exit(struct net *net) |
1371 | { | 1566 | { |
1372 | netlink_kernel_release(net->rtnl); | 1567 | netlink_kernel_release(net->rtnl); |
1373 | net->rtnl = NULL; | 1568 | net->rtnl = NULL; |
@@ -1405,14 +1600,3 @@ void __init rtnetlink_init(void) | |||
1405 | rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all); | 1600 | rtnl_register(PF_UNSPEC, RTM_GETROUTE, NULL, rtnl_dump_all); |
1406 | } | 1601 | } |
1407 | 1602 | ||
1408 | EXPORT_SYMBOL(__rta_fill); | ||
1409 | EXPORT_SYMBOL(rtnetlink_put_metrics); | ||
1410 | EXPORT_SYMBOL(rtnl_lock); | ||
1411 | EXPORT_SYMBOL(rtnl_trylock); | ||
1412 | EXPORT_SYMBOL(rtnl_unlock); | ||
1413 | EXPORT_SYMBOL(rtnl_is_locked); | ||
1414 | EXPORT_SYMBOL(rtnl_unicast); | ||
1415 | EXPORT_SYMBOL(rtnl_notify); | ||
1416 | EXPORT_SYMBOL(rtnl_set_sk_err); | ||
1417 | EXPORT_SYMBOL(rtnl_create_link); | ||
1418 | EXPORT_SYMBOL(ifla_policy); | ||