diff options
author | Nicolas Dichtel <nicolas.dichtel@6wind.com> | 2012-10-25 18:28:50 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2012-10-28 19:05:00 -0400 |
commit | f3a1bfb11ccbc72d44f0b58c92115a40128979c3 (patch) | |
tree | ad32461b8d2cc759260eec13d20f6a82729e69b4 /net/ipv6 | |
parent | d900082bd9060dc955b181dae2f2adf86e27d747 (diff) |
rtnl/ipv6: use netconf msg to advertise forwarding status
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 0424e4e27414..0c57a8f67715 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -81,6 +81,7 @@ | |||
81 | #include <net/pkt_sched.h> | 81 | #include <net/pkt_sched.h> |
82 | #include <linux/if_tunnel.h> | 82 | #include <linux/if_tunnel.h> |
83 | #include <linux/rtnetlink.h> | 83 | #include <linux/rtnetlink.h> |
84 | #include <linux/netconf.h> | ||
84 | 85 | ||
85 | #ifdef CONFIG_IPV6_PRIVACY | 86 | #ifdef CONFIG_IPV6_PRIVACY |
86 | #include <linux/random.h> | 87 | #include <linux/random.h> |
@@ -460,6 +461,72 @@ static struct inet6_dev *ipv6_find_idev(struct net_device *dev) | |||
460 | return idev; | 461 | return idev; |
461 | } | 462 | } |
462 | 463 | ||
464 | static int inet6_netconf_msgsize_devconf(int type) | ||
465 | { | ||
466 | int size = NLMSG_ALIGN(sizeof(struct netconfmsg)) | ||
467 | + nla_total_size(4); /* NETCONFA_IFINDEX */ | ||
468 | |||
469 | if (type == NETCONFA_FORWARDING) | ||
470 | size += nla_total_size(4); | ||
471 | |||
472 | return size; | ||
473 | } | ||
474 | |||
475 | static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex, | ||
476 | struct ipv6_devconf *devconf, u32 portid, | ||
477 | u32 seq, int event, unsigned int flags, | ||
478 | int type) | ||
479 | { | ||
480 | struct nlmsghdr *nlh; | ||
481 | struct netconfmsg *ncm; | ||
482 | |||
483 | nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct netconfmsg), | ||
484 | flags); | ||
485 | if (nlh == NULL) | ||
486 | return -EMSGSIZE; | ||
487 | |||
488 | ncm = nlmsg_data(nlh); | ||
489 | ncm->ncm_family = AF_INET6; | ||
490 | |||
491 | if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0) | ||
492 | goto nla_put_failure; | ||
493 | |||
494 | if (type == NETCONFA_FORWARDING && | ||
495 | nla_put_s32(skb, NETCONFA_FORWARDING, devconf->forwarding) < 0) | ||
496 | goto nla_put_failure; | ||
497 | |||
498 | return nlmsg_end(skb, nlh); | ||
499 | |||
500 | nla_put_failure: | ||
501 | nlmsg_cancel(skb, nlh); | ||
502 | return -EMSGSIZE; | ||
503 | } | ||
504 | |||
505 | static void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex, | ||
506 | struct ipv6_devconf *devconf) | ||
507 | { | ||
508 | struct sk_buff *skb; | ||
509 | int err = -ENOBUFS; | ||
510 | |||
511 | skb = nlmsg_new(inet6_netconf_msgsize_devconf(type), GFP_ATOMIC); | ||
512 | if (skb == NULL) | ||
513 | goto errout; | ||
514 | |||
515 | err = inet6_netconf_fill_devconf(skb, ifindex, devconf, 0, 0, | ||
516 | RTM_NEWNETCONF, 0, type); | ||
517 | if (err < 0) { | ||
518 | /* -EMSGSIZE implies BUG in inet6_netconf_msgsize_devconf() */ | ||
519 | WARN_ON(err == -EMSGSIZE); | ||
520 | kfree_skb(skb); | ||
521 | goto errout; | ||
522 | } | ||
523 | rtnl_notify(skb, net, 0, RTNLGRP_IPV6_NETCONF, NULL, GFP_ATOMIC); | ||
524 | return; | ||
525 | errout: | ||
526 | if (err < 0) | ||
527 | rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err); | ||
528 | } | ||
529 | |||
463 | #ifdef CONFIG_SYSCTL | 530 | #ifdef CONFIG_SYSCTL |
464 | static void dev_forward_change(struct inet6_dev *idev) | 531 | static void dev_forward_change(struct inet6_dev *idev) |
465 | { | 532 | { |
@@ -486,6 +553,8 @@ static void dev_forward_change(struct inet6_dev *idev) | |||
486 | else | 553 | else |
487 | addrconf_leave_anycast(ifa); | 554 | addrconf_leave_anycast(ifa); |
488 | } | 555 | } |
556 | inet6_netconf_notify_devconf(dev_net(dev), NETCONFA_FORWARDING, | ||
557 | dev->ifindex, &idev->cnf); | ||
489 | } | 558 | } |
490 | 559 | ||
491 | 560 | ||
@@ -518,6 +587,10 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf) | |||
518 | *p = newf; | 587 | *p = newf; |
519 | 588 | ||
520 | if (p == &net->ipv6.devconf_dflt->forwarding) { | 589 | if (p == &net->ipv6.devconf_dflt->forwarding) { |
590 | if ((!newf) ^ (!old)) | ||
591 | inet6_netconf_notify_devconf(net, NETCONFA_FORWARDING, | ||
592 | NETCONFA_IFINDEX_DEFAULT, | ||
593 | net->ipv6.devconf_dflt); | ||
521 | rtnl_unlock(); | 594 | rtnl_unlock(); |
522 | return 0; | 595 | return 0; |
523 | } | 596 | } |
@@ -525,6 +598,10 @@ static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf) | |||
525 | if (p == &net->ipv6.devconf_all->forwarding) { | 598 | if (p == &net->ipv6.devconf_all->forwarding) { |
526 | net->ipv6.devconf_dflt->forwarding = newf; | 599 | net->ipv6.devconf_dflt->forwarding = newf; |
527 | addrconf_forward_change(net, newf); | 600 | addrconf_forward_change(net, newf); |
601 | if ((!newf) ^ (!old)) | ||
602 | inet6_netconf_notify_devconf(net, NETCONFA_FORWARDING, | ||
603 | NETCONFA_IFINDEX_ALL, | ||
604 | net->ipv6.devconf_all); | ||
528 | } else if ((!newf) ^ (!old)) | 605 | } else if ((!newf) ^ (!old)) |
529 | dev_forward_change((struct inet6_dev *)table->extra1); | 606 | dev_forward_change((struct inet6_dev *)table->extra1); |
530 | rtnl_unlock(); | 607 | rtnl_unlock(); |