aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
authorNicolas Dichtel <nicolas.dichtel@6wind.com>2012-10-25 18:28:51 -0400
committerDavid S. Miller <davem@davemloft.net>2012-10-28 19:05:00 -0400
commit76f8f6cb76b110aaace90b6208b1ceb46bd78b7f (patch)
tree0b70420e29479970155518d8ac3f147bf652328e /net/ipv6/addrconf.c
parentf3a1bfb11ccbc72d44f0b58c92115a40128979c3 (diff)
rtnl/ipv6: add support of RTM_GETNETCONF
This message allows to get the devconf for an interface. Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c75
1 files changed, 73 insertions, 2 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 0c57a8f67715..8f0b12a67131 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -466,7 +466,8 @@ static int inet6_netconf_msgsize_devconf(int type)
466 int size = NLMSG_ALIGN(sizeof(struct netconfmsg)) 466 int size = NLMSG_ALIGN(sizeof(struct netconfmsg))
467 + nla_total_size(4); /* NETCONFA_IFINDEX */ 467 + nla_total_size(4); /* NETCONFA_IFINDEX */
468 468
469 if (type == NETCONFA_FORWARDING) 469 /* type -1 is used for ALL */
470 if (type == -1 || type == NETCONFA_FORWARDING)
470 size += nla_total_size(4); 471 size += nla_total_size(4);
471 472
472 return size; 473 return size;
@@ -491,7 +492,8 @@ static int inet6_netconf_fill_devconf(struct sk_buff *skb, int ifindex,
491 if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0) 492 if (nla_put_s32(skb, NETCONFA_IFINDEX, ifindex) < 0)
492 goto nla_put_failure; 493 goto nla_put_failure;
493 494
494 if (type == NETCONFA_FORWARDING && 495 /* type -1 is used for ALL */
496 if ((type == -1 || type == NETCONFA_FORWARDING) &&
495 nla_put_s32(skb, NETCONFA_FORWARDING, devconf->forwarding) < 0) 497 nla_put_s32(skb, NETCONFA_FORWARDING, devconf->forwarding) < 0)
496 goto nla_put_failure; 498 goto nla_put_failure;
497 499
@@ -527,6 +529,73 @@ errout:
527 rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err); 529 rtnl_set_sk_err(net, RTNLGRP_IPV6_NETCONF, err);
528} 530}
529 531
532static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = {
533 [NETCONFA_IFINDEX] = { .len = sizeof(int) },
534 [NETCONFA_FORWARDING] = { .len = sizeof(int) },
535};
536
537static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
538 struct nlmsghdr *nlh,
539 void *arg)
540{
541 struct net *net = sock_net(in_skb->sk);
542 struct nlattr *tb[NETCONFA_MAX+1];
543 struct netconfmsg *ncm;
544 struct sk_buff *skb;
545 struct ipv6_devconf *devconf;
546 struct inet6_dev *in6_dev;
547 struct net_device *dev;
548 int ifindex;
549 int err;
550
551 err = nlmsg_parse(nlh, sizeof(*ncm), tb, NETCONFA_MAX,
552 devconf_ipv6_policy);
553 if (err < 0)
554 goto errout;
555
556 err = EINVAL;
557 if (!tb[NETCONFA_IFINDEX])
558 goto errout;
559
560 ifindex = nla_get_s32(tb[NETCONFA_IFINDEX]);
561 switch (ifindex) {
562 case NETCONFA_IFINDEX_ALL:
563 devconf = net->ipv6.devconf_all;
564 break;
565 case NETCONFA_IFINDEX_DEFAULT:
566 devconf = net->ipv6.devconf_dflt;
567 break;
568 default:
569 dev = __dev_get_by_index(net, ifindex);
570 if (dev == NULL)
571 goto errout;
572 in6_dev = __in6_dev_get(dev);
573 if (in6_dev == NULL)
574 goto errout;
575 devconf = &in6_dev->cnf;
576 break;
577 }
578
579 err = -ENOBUFS;
580 skb = nlmsg_new(inet6_netconf_msgsize_devconf(-1), GFP_ATOMIC);
581 if (skb == NULL)
582 goto errout;
583
584 err = inet6_netconf_fill_devconf(skb, ifindex, devconf,
585 NETLINK_CB(in_skb).portid,
586 nlh->nlmsg_seq, RTM_NEWNETCONF, 0,
587 -1);
588 if (err < 0) {
589 /* -EMSGSIZE implies BUG in inet6_netconf_msgsize_devconf() */
590 WARN_ON(err == -EMSGSIZE);
591 kfree_skb(skb);
592 goto errout;
593 }
594 err = rtnl_unicast(skb, net, NETLINK_CB(in_skb).portid);
595errout:
596 return err;
597}
598
530#ifdef CONFIG_SYSCTL 599#ifdef CONFIG_SYSCTL
531static void dev_forward_change(struct inet6_dev *idev) 600static void dev_forward_change(struct inet6_dev *idev)
532{ 601{
@@ -4861,6 +4930,8 @@ int __init addrconf_init(void)
4861 inet6_dump_ifmcaddr, NULL); 4930 inet6_dump_ifmcaddr, NULL);
4862 __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, 4931 __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL,
4863 inet6_dump_ifacaddr, NULL); 4932 inet6_dump_ifacaddr, NULL);
4933 __rtnl_register(PF_INET6, RTM_GETNETCONF, inet6_netconf_get_devconf,
4934 NULL, NULL);
4864 4935
4865 ipv6_addr_label_rtnl_register(); 4936 ipv6_addr_label_rtnl_register();
4866 4937