netconf: advertise mc_forwarding status
authorNicolas Dichtel <nicolas.dichtel@6wind.com>
Tue, 4 Dec 2012 01:13:35 +0000 (01:13 +0000)
committerDavid S. Miller <davem@davemloft.net>
Tue, 4 Dec 2012 18:08:10 +0000 (13:08 -0500)
This patch advertise the MC_FORWARDING status for IPv4 and IPv6.
This field is readonly, only multicast engine in the kernel updates it.

Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/inetdevice.h
include/net/addrconf.h
include/uapi/linux/netconf.h
net/ipv4/devinet.c
net/ipv4/ipmr.c
net/ipv6/addrconf.c
net/ipv6/ip6mr.c

index d032780d0ce50849c5441aae24025b2cc2f80cc3..a9d828976a77a56b400ffd3f4e7a56915f3762a5 100644 (file)
@@ -171,6 +171,9 @@ struct in_ifaddr {
 extern int register_inetaddr_notifier(struct notifier_block *nb);
 extern int unregister_inetaddr_notifier(struct notifier_block *nb);
 
+extern void inet_netconf_notify_devconf(struct net *net, int type, int ifindex,
+                                       struct ipv4_devconf *devconf);
+
 extern struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref);
 static inline struct net_device *ip_dev_find(struct net *net, __be32 addr)
 {
index 9e63e76b20e7e0ce4b60aa5daf0e113b6985ae16..df4ef945338425d7fc6d64a858dd706d2628ea28 100644 (file)
@@ -172,6 +172,9 @@ extern bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev,
 extern int register_inet6addr_notifier(struct notifier_block *nb);
 extern int unregister_inet6addr_notifier(struct notifier_block *nb);
 
+extern void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
+                                        struct ipv6_devconf *devconf);
+
 /**
  * __in6_dev_get - get inet6_dev pointer from netdevice
  * @dev: network device
index 75dcbc587fb5db5a64103ca5e65f1d93a4914289..64804a798b0c826aeb912c517e9f2ecd4c6cc5da 100644 (file)
@@ -13,6 +13,7 @@ enum {
        NETCONFA_IFINDEX,
        NETCONFA_FORWARDING,
        NETCONFA_RP_FILTER,
+       NETCONFA_MC_FORWARDING,
        __NETCONFA_MAX
 };
 #define NETCONFA_MAX   (__NETCONFA_MAX - 1)
index e13183abd7f643c512cc83afdf600ce4ec1c1b77..cc06a47f12163ad8b93cae060a8c211bb13fcc73 100644 (file)
@@ -1453,6 +1453,8 @@ static int inet_netconf_msgsize_devconf(int type)
                size += nla_total_size(4);
        if (type == -1 || type == NETCONFA_RP_FILTER)
                size += nla_total_size(4);
+       if (type == -1 || type == NETCONFA_MC_FORWARDING)
+               size += nla_total_size(4);
 
        return size;
 }
@@ -1485,6 +1487,10 @@ static int inet_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
            nla_put_s32(skb, NETCONFA_RP_FILTER,
                        IPV4_DEVCONF(*devconf, RP_FILTER)) < 0)
                goto nla_put_failure;
+       if ((type == -1 || type == NETCONFA_MC_FORWARDING) &&
+           nla_put_s32(skb, NETCONFA_MC_FORWARDING,
+                       IPV4_DEVCONF(*devconf, MC_FORWARDING)) < 0)
+               goto nla_put_failure;
 
        return nlmsg_end(skb, nlh);
 
@@ -1493,8 +1499,8 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
-static void inet_netconf_notify_devconf(struct net *net, int type, int ifindex,
-                                       struct ipv4_devconf *devconf)
+void inet_netconf_notify_devconf(struct net *net, int type, int ifindex,
+                                struct ipv4_devconf *devconf)
 {
        struct sk_buff *skb;
        int err = -ENOBUFS;
index 58e4160fdceeb7a7bea36feeb0b7ad0b63602205..0c452e3fdc1b80404fe47a141098a45940490d50 100644 (file)
@@ -65,6 +65,7 @@
 #include <net/checksum.h>
 #include <net/netlink.h>
 #include <net/fib_rules.h>
+#include <linux/netconf.h>
 
 #if defined(CONFIG_IP_PIMSM_V1) || defined(CONFIG_IP_PIMSM_V2)
 #define CONFIG_IP_PIMSM        1
@@ -582,6 +583,9 @@ static int vif_delete(struct mr_table *mrt, int vifi, int notify,
        in_dev = __in_dev_get_rtnl(dev);
        if (in_dev) {
                IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)--;
+               inet_netconf_notify_devconf(dev_net(dev),
+                                           NETCONFA_MC_FORWARDING,
+                                           dev->ifindex, &in_dev->cnf);
                ip_rt_multicast_event(in_dev);
        }
 
@@ -772,6 +776,8 @@ static int vif_add(struct net *net, struct mr_table *mrt,
                return -EADDRNOTAVAIL;
        }
        IPV4_DEVCONF(in_dev->cnf, MC_FORWARDING)++;
+       inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING, dev->ifindex,
+                                   &in_dev->cnf);
        ip_rt_multicast_event(in_dev);
 
        /* Fill in the VIF structures */
@@ -1185,6 +1191,9 @@ static void mrtsock_destruct(struct sock *sk)
        ipmr_for_each_table(mrt, net) {
                if (sk == rtnl_dereference(mrt->mroute_sk)) {
                        IPV4_DEVCONF_ALL(net, MC_FORWARDING)--;
+                       inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING,
+                                                   NETCONFA_IFINDEX_ALL,
+                                                   net->ipv4.devconf_all);
                        RCU_INIT_POINTER(mrt->mroute_sk, NULL);
                        mroute_clean_tables(mrt);
                }
@@ -1236,6 +1245,9 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi
                if (ret == 0) {
                        rcu_assign_pointer(mrt->mroute_sk, sk);
                        IPV4_DEVCONF_ALL(net, MC_FORWARDING)++;
+                       inet_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING,
+                                                   NETCONFA_IFINDEX_ALL,
+                                                   net->ipv4.devconf_all);
                }
                rtnl_unlock();
                return ret;
index 22ae75d5401794b0ddca846eccb863f957538a50..28e0e627229c3fc28acc94a8f88998e5e49bdeb9 100644 (file)
@@ -469,6 +469,8 @@ static int inet6_netconf_msgsize_devconf(int type)
        /* type -1 is used for ALL */
        if (type == -1 || type == NETCONFA_FORWARDING)
                size += nla_total_size(4);
+       if (type == -1 || type == NETCONFA_MC_FORWARDING)
+               size += nla_total_size(4);
 
        return size;
 }
@@ -496,6 +498,10 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
        if ((type == -1 || type == NETCONFA_FORWARDING) &&
            nla_put_s32(skb, NETCONFA_FORWARDING, devconf->forwarding) < 0)
                goto nla_put_failure;
+       if ((type == -1 || type == NETCONFA_MC_FORWARDING) &&
+           nla_put_s32(skb, NETCONFA_MC_FORWARDING,
+                       devconf->mc_forwarding) < 0)
+               goto nla_put_failure;
 
        return nlmsg_end(skb, nlh);
 
@@ -504,8 +510,8 @@ nla_put_failure:
        return -EMSGSIZE;
 }
 
-static void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
-                                        struct ipv6_devconf *devconf)
+void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex,
+                                 struct ipv6_devconf *devconf)
 {
        struct sk_buff *skb;
        int err = -ENOBUFS;
index 926ea544f499e93c895b42e9677d316f7cff481d..1c05fe604d37049029b4c8ddfb4c5ef4aa0f4ab6 100644 (file)
@@ -52,6 +52,7 @@
 #include <linux/netfilter_ipv6.h>
 #include <linux/export.h>
 #include <net/ip6_checksum.h>
+#include <linux/netconf.h>
 
 struct mr6_table {
        struct list_head        list;
@@ -805,8 +806,12 @@ static int mif6_delete(struct mr6_table *mrt, int vifi, struct list_head *head)
        dev_set_allmulti(dev, -1);
 
        in6_dev = __in6_dev_get(dev);
-       if (in6_dev)
+       if (in6_dev) {
                in6_dev->cnf.mc_forwarding--;
+               inet6_netconf_notify_devconf(dev_net(dev),
+                                            NETCONFA_MC_FORWARDING,
+                                            dev->ifindex, &in6_dev->cnf);
+       }
 
        if (v->flags & MIFF_REGISTER)
                unregister_netdevice_queue(dev, head);
@@ -958,8 +963,12 @@ static int mif6_add(struct net *net, struct mr6_table *mrt,
        }
 
        in6_dev = __in6_dev_get(dev);
-       if (in6_dev)
+       if (in6_dev) {
                in6_dev->cnf.mc_forwarding++;
+               inet6_netconf_notify_devconf(dev_net(dev),
+                                            NETCONFA_MC_FORWARDING,
+                                            dev->ifindex, &in6_dev->cnf);
+       }
 
        /*
         *      Fill in the VIF structures
@@ -1513,6 +1522,9 @@ static int ip6mr_sk_init(struct mr6_table *mrt, struct sock *sk)
        if (likely(mrt->mroute6_sk == NULL)) {
                mrt->mroute6_sk = sk;
                net->ipv6.devconf_all->mc_forwarding++;
+               inet6_netconf_notify_devconf(net, NETCONFA_MC_FORWARDING,
+                                            NETCONFA_IFINDEX_ALL,
+                                            net->ipv6.devconf_all);
        }
        else
                err = -EADDRINUSE;
@@ -1535,6 +1547,10 @@ int ip6mr_sk_done(struct sock *sk)
                        write_lock_bh(&mrt_lock);
                        mrt->mroute6_sk = NULL;
                        net->ipv6.devconf_all->mc_forwarding--;
+                       inet6_netconf_notify_devconf(net,
+                                                    NETCONFA_MC_FORWARDING,
+                                                    NETCONFA_IFINDEX_ALL,
+                                                    net->ipv6.devconf_all);
                        write_unlock_bh(&mrt_lock);
 
                        mroute_clean_tables(mrt);