netconf: add support for IPv6 proxy_ndp
authorstephen hemminger <stephen@networkplumber.org>
Wed, 18 Dec 2013 06:37:14 +0000 (22:37 -0800)
committerDavid S. Miller <davem@davemloft.net>
Sun, 22 Dec 2013 23:02:43 +0000 (18:02 -0500)
Need to be able to see changes to proxy NDP status on a per
interface basis via netlink (analog to proxy_arp).

Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/addrconf.c

index 3c3425ee6a2b4d03a951a5630ca3aaba9c471cfe..cd2d7d0fb558be1d3c02f3419a2fb3cc9e6e9a09 100644 (file)
@@ -442,6 +442,8 @@ static int inet6_netconf_msgsize_devconf(int type)
        if (type == -1 || type == NETCONFA_MC_FORWARDING)
                size += nla_total_size(4);
 #endif
+       if (type == -1 || type == NETCONFA_PROXY_NEIGH)
+               size += nla_total_size(4);
 
        return size;
 }
@@ -475,6 +477,10 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
                        devconf->mc_forwarding) < 0)
                goto nla_put_failure;
 #endif
+       if ((type == -1 || type == NETCONFA_PROXY_NEIGH) &&
+           nla_put_s32(skb, NETCONFA_PROXY_NEIGH, devconf->proxy_ndp) < 0)
+               goto nla_put_failure;
+
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
@@ -509,6 +515,7 @@ errout:
 static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = {
        [NETCONFA_IFINDEX]      = { .len = sizeof(int) },
        [NETCONFA_FORWARDING]   = { .len = sizeof(int) },
+       [NETCONFA_PROXY_NEIGH]  = { .len = sizeof(int) },
 };
 
 static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
@@ -4728,6 +4735,46 @@ int addrconf_sysctl_disable(struct ctl_table *ctl, int write,
        return ret;
 }
 
+static
+int addrconf_sysctl_proxy_ndp(struct ctl_table *ctl, int write,
+                             void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       int *valp = ctl->data;
+       int ret;
+       int old, new;
+
+       old = *valp;
+       ret = proc_dointvec(ctl, write, buffer, lenp, ppos);
+       new = *valp;
+
+       if (write && old != new) {
+               struct net *net = ctl->extra2;
+
+               if (!rtnl_trylock())
+                       return restart_syscall();
+
+               if (valp == &net->ipv6.devconf_dflt->proxy_ndp)
+                       inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
+                                                    NETCONFA_IFINDEX_DEFAULT,
+                                                    net->ipv6.devconf_dflt);
+               else if (valp == &net->ipv6.devconf_all->proxy_ndp)
+                       inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
+                                                    NETCONFA_IFINDEX_ALL,
+                                                    net->ipv6.devconf_all);
+               else {
+                       struct inet6_dev *idev = ctl->extra1;
+
+                       inet6_netconf_notify_devconf(net, NETCONFA_PROXY_NEIGH,
+                                                    idev->dev->ifindex,
+                                                    &idev->cnf);
+               }
+               rtnl_unlock();
+       }
+
+       return ret;
+}
+
+
 static struct addrconf_sysctl_table
 {
        struct ctl_table_header *sysctl_header;
@@ -4914,7 +4961,7 @@ static struct addrconf_sysctl_table
                        .data           = &ipv6_devconf.proxy_ndp,
                        .maxlen         = sizeof(int),
                        .mode           = 0644,
-                       .proc_handler   = proc_dointvec,
+                       .proc_handler   = addrconf_sysctl_proxy_ndp,
                },
                {
                        .procname       = "accept_source_route",