From 5f3992f56d52f92d0047bd6c794da10daa11cf3c Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 25 Oct 2012 22:28:51 +0000 Subject: [PATCH] --- yaml --- r: 340511 b: refs/heads/master c: 76f8f6cb76b110aaace90b6208b1ceb46bd78b7f h: refs/heads/master i: 340509: 03deb6dd5bcabf470fdde437e704887b4ee9dea9 340507: 1a0a82ae313a703e934fe1b45c5cbf624cd9615e 340503: ca20e36358e5aff9b04fc7dd5dad91d34bce82d2 340495: 3c5828870ad44c3576f125362f9bfd036d09449a 340479: 95482354bc39224f918430dc6275cf4b7bd3df58 v: v3 --- [refs] | 2 +- trunk/net/ipv6/addrconf.c | 75 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 74 insertions(+), 3 deletions(-) diff --git a/[refs] b/[refs] index 1410d44db3b3..23746a483840 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: f3a1bfb11ccbc72d44f0b58c92115a40128979c3 +refs/heads/master: 76f8f6cb76b110aaace90b6208b1ceb46bd78b7f diff --git a/trunk/net/ipv6/addrconf.c b/trunk/net/ipv6/addrconf.c index 0c57a8f67715..8f0b12a67131 100644 --- a/trunk/net/ipv6/addrconf.c +++ b/trunk/net/ipv6/addrconf.c @@ -466,7 +466,8 @@ static int inet6_netconf_msgsize_devconf(int type) int size = NLMSG_ALIGN(sizeof(struct netconfmsg)) + nla_total_size(4); /* NETCONFA_IFINDEX */ - if (type == NETCONFA_FORWARDING) + /* type -1 is used for ALL */ + if (type == -1 || type == NETCONFA_FORWARDING) size += nla_total_size(4); return size; @@ -491,7 +492,8 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex, if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0) goto nla_put_failure; - if (type == NETCONFA_FORWARDING && + /* type -1 is used for ALL */ + if ((type == -1 || type == NETCONFA_FORWARDING) && nla_put_s32(skb, NETCONFA_FORWARDING, devconf->forwarding) < 0) goto nla_put_failure; @@ -527,6 +529,73 @@ static void inet6_netconf_notify_devconf(struct net *net, int type, int ifindex, rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err); } +static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = { + [NETCONFA_IFINDEX] = { .len = sizeof(int) }, + [NETCONFA_FORWARDING] = { .len = sizeof(int) }, +}; + +static int inet6_netconf_get_devconf(struct sk_buff *in_skb, + struct nlmsghdr *nlh, + void *arg) +{ + struct net *net = sock_net(in_skb->sk); + struct nlattr *tb[NETCONFA_MAX+1]; + struct netconfmsg *ncm; + struct sk_buff *skb; + struct ipv6_devconf *devconf; + struct inet6_dev *in6_dev; + struct net_device *dev; + int ifindex; + int err; + + err = nlmsg_parse(nlh, sizeof(*ncm), tb, NETCONFA_MAX, + devconf_ipv6_policy); + if (err < 0) + goto errout; + + err = EINVAL; + if (!tb[NETCONFA_IFINDEX]) + goto errout; + + ifindex = nla_get_s32(tb[NETCONFA_IFINDEX]); + switch (ifindex) { + case NETCONFA_IFINDEX_ALL: + devconf = net->ipv6.devconf_all; + break; + case NETCONFA_IFINDEX_DEFAULT: + devconf = net->ipv6.devconf_dflt; + break; + default: + dev = __dev_get_by_index(net, ifindex); + if (dev == NULL) + goto errout; + in6_dev = __in6_dev_get(dev); + if (in6_dev == NULL) + goto errout; + devconf = &in6_dev->cnf; + break; + } + + err = -ENOBUFS; + skb = nlmsg_new(inet6_netconf_msgsize_devconf(-1), GFP_ATOMIC); + if (skb == NULL) + goto errout; + + err = inet6_netconf_fill_devconf(skb, ifindex, devconf, + NETLINK_CB(in_skb).portid, + nlh->nlmsg_seq, RTM_NEWNETCONF, 0, + -1); + if (err < 0) { + /* -EMSGSIZE implies BUG in inet6_netconf_msgsize_devconf() */ + WARN_ON(err == -EMSGSIZE); + kfree_skb(skb); + goto errout; + } + err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid); +errout: + return err; +} + #ifdef CONFIG_SYSCTL static void dev_forward_change(struct inet6_dev *idev) { @@ -4861,6 +4930,8 @@ int __init addrconf_init(void) inet6_dump_ifmcaddr, NULL); __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, inet6_dump_ifacaddr, NULL); + __rtnl_register(PF_INET6, RTM_GETNETCONF, inet6_netconf_get_devconf, + NULL, NULL); ipv6_addr_label_rtnl_register();