diff options
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r-- | net/ipv6/addrconf.c | 114 |
1 files changed, 82 insertions, 32 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 848b35591042..99d1888af363 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -3838,6 +3838,15 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | |||
3838 | array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao; | 3838 | array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao; |
3839 | } | 3839 | } |
3840 | 3840 | ||
3841 | static inline size_t inet6_ifla6_size(void) | ||
3842 | { | ||
3843 | return nla_total_size(4) /* IFLA_INET6_FLAGS */ | ||
3844 | + nla_total_size(sizeof(struct ifla_cacheinfo)) | ||
3845 | + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */ | ||
3846 | + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */ | ||
3847 | + nla_total_size(ICMP6_MIB_MAX * 8); /* IFLA_INET6_ICMP6STATS */ | ||
3848 | } | ||
3849 | |||
3841 | static inline size_t inet6_if_nlmsg_size(void) | 3850 | static inline size_t inet6_if_nlmsg_size(void) |
3842 | { | 3851 | { |
3843 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) | 3852 | return NLMSG_ALIGN(sizeof(struct ifinfomsg)) |
@@ -3845,13 +3854,7 @@ static inline size_t inet6_if_nlmsg_size(void) | |||
3845 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ | 3854 | + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ |
3846 | + nla_total_size(4) /* IFLA_MTU */ | 3855 | + nla_total_size(4) /* IFLA_MTU */ |
3847 | + nla_total_size(4) /* IFLA_LINK */ | 3856 | + nla_total_size(4) /* IFLA_LINK */ |
3848 | + nla_total_size( /* IFLA_PROTINFO */ | 3857 | + nla_total_size(inet6_ifla6_size()); /* IFLA_PROTINFO */ |
3849 | nla_total_size(4) /* IFLA_INET6_FLAGS */ | ||
3850 | + nla_total_size(sizeof(struct ifla_cacheinfo)) | ||
3851 | + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */ | ||
3852 | + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */ | ||
3853 | + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */ | ||
3854 | ); | ||
3855 | } | 3858 | } |
3856 | 3859 | ||
3857 | static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, | 3860 | static inline void __snmp6_fill_stats(u64 *stats, void __percpu **mib, |
@@ -3898,15 +3901,70 @@ static void snmp6_fill_stats(u64 *stats, struct inet6_dev *idev, int attrtype, | |||
3898 | } | 3901 | } |
3899 | } | 3902 | } |
3900 | 3903 | ||
3904 | static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev) | ||
3905 | { | ||
3906 | struct nlattr *nla; | ||
3907 | struct ifla_cacheinfo ci; | ||
3908 | |||
3909 | NLA_PUT_U32(skb, IFLA_INET6_FLAGS, idev->if_flags); | ||
3910 | |||
3911 | ci.max_reasm_len = IPV6_MAXPLEN; | ||
3912 | ci.tstamp = cstamp_delta(idev->tstamp); | ||
3913 | ci.reachable_time = jiffies_to_msecs(idev->nd_parms->reachable_time); | ||
3914 | ci.retrans_time = jiffies_to_msecs(idev->nd_parms->retrans_time); | ||
3915 | NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci); | ||
3916 | |||
3917 | nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32)); | ||
3918 | if (nla == NULL) | ||
3919 | goto nla_put_failure; | ||
3920 | ipv6_store_devconf(&idev->cnf, nla_data(nla), nla_len(nla)); | ||
3921 | |||
3922 | /* XXX - MC not implemented */ | ||
3923 | |||
3924 | nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64)); | ||
3925 | if (nla == NULL) | ||
3926 | goto nla_put_failure; | ||
3927 | snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla)); | ||
3928 | |||
3929 | nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64)); | ||
3930 | if (nla == NULL) | ||
3931 | goto nla_put_failure; | ||
3932 | snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla)); | ||
3933 | |||
3934 | return 0; | ||
3935 | |||
3936 | nla_put_failure: | ||
3937 | return -EMSGSIZE; | ||
3938 | } | ||
3939 | |||
3940 | static size_t inet6_get_link_af_size(const struct net_device *dev) | ||
3941 | { | ||
3942 | if (!__in6_dev_get(dev)) | ||
3943 | return 0; | ||
3944 | |||
3945 | return inet6_ifla6_size(); | ||
3946 | } | ||
3947 | |||
3948 | static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev) | ||
3949 | { | ||
3950 | struct inet6_dev *idev = __in6_dev_get(dev); | ||
3951 | |||
3952 | if (!idev) | ||
3953 | return -ENODATA; | ||
3954 | |||
3955 | if (inet6_fill_ifla6_attrs(skb, idev) < 0) | ||
3956 | return -EMSGSIZE; | ||
3957 | |||
3958 | return 0; | ||
3959 | } | ||
3960 | |||
3901 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, | 3961 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, |
3902 | u32 pid, u32 seq, int event, unsigned int flags) | 3962 | u32 pid, u32 seq, int event, unsigned int flags) |
3903 | { | 3963 | { |
3904 | struct net_device *dev = idev->dev; | 3964 | struct net_device *dev = idev->dev; |
3905 | struct nlattr *nla; | ||
3906 | struct ifinfomsg *hdr; | 3965 | struct ifinfomsg *hdr; |
3907 | struct nlmsghdr *nlh; | 3966 | struct nlmsghdr *nlh; |
3908 | void *protoinfo; | 3967 | void *protoinfo; |
3909 | struct ifla_cacheinfo ci; | ||
3910 | 3968 | ||
3911 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); | 3969 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); |
3912 | if (nlh == NULL) | 3970 | if (nlh == NULL) |
@@ -3933,30 +3991,8 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, | |||
3933 | if (protoinfo == NULL) | 3991 | if (protoinfo == NULL) |
3934 | goto nla_put_failure; | 3992 | goto nla_put_failure; |
3935 | 3993 | ||
3936 | NLA_PUT_U32(skb, IFLA_INET6_FLAGS, idev->if_flags); | 3994 | if (inet6_fill_ifla6_attrs(skb, idev) < 0) |
3937 | |||
3938 | ci.max_reasm_len = IPV6_MAXPLEN; | ||
3939 | ci.tstamp = cstamp_delta(idev->tstamp); | ||
3940 | ci.reachable_time = jiffies_to_msecs(idev->nd_parms->reachable_time); | ||
3941 | ci.retrans_time = jiffies_to_msecs(idev->nd_parms->retrans_time); | ||
3942 | NLA_PUT(skb, IFLA_INET6_CACHEINFO, sizeof(ci), &ci); | ||
3943 | |||
3944 | nla = nla_reserve(skb, IFLA_INET6_CONF, DEVCONF_MAX * sizeof(s32)); | ||
3945 | if (nla == NULL) | ||
3946 | goto nla_put_failure; | ||
3947 | ipv6_store_devconf(&idev->cnf, nla_data(nla), nla_len(nla)); | ||
3948 | |||
3949 | /* XXX - MC not implemented */ | ||
3950 | |||
3951 | nla = nla_reserve(skb, IFLA_INET6_STATS, IPSTATS_MIB_MAX * sizeof(u64)); | ||
3952 | if (nla == NULL) | ||
3953 | goto nla_put_failure; | ||
3954 | snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_STATS, nla_len(nla)); | ||
3955 | |||
3956 | nla = nla_reserve(skb, IFLA_INET6_ICMP6STATS, ICMP6_MIB_MAX * sizeof(u64)); | ||
3957 | if (nla == NULL) | ||
3958 | goto nla_put_failure; | 3995 | goto nla_put_failure; |
3959 | snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla)); | ||
3960 | 3996 | ||
3961 | nla_nest_end(skb, protoinfo); | 3997 | nla_nest_end(skb, protoinfo); |
3962 | return nlmsg_end(skb, nlh); | 3998 | return nlmsg_end(skb, nlh); |
@@ -4627,6 +4663,12 @@ int unregister_inet6addr_notifier(struct notifier_block *nb) | |||
4627 | } | 4663 | } |
4628 | EXPORT_SYMBOL(unregister_inet6addr_notifier); | 4664 | EXPORT_SYMBOL(unregister_inet6addr_notifier); |
4629 | 4665 | ||
4666 | static struct rtnl_af_ops inet6_ops = { | ||
4667 | .family = AF_INET6, | ||
4668 | .fill_link_af = inet6_fill_link_af, | ||
4669 | .get_link_af_size = inet6_get_link_af_size, | ||
4670 | }; | ||
4671 | |||
4630 | /* | 4672 | /* |
4631 | * Init / cleanup code | 4673 | * Init / cleanup code |
4632 | */ | 4674 | */ |
@@ -4678,6 +4720,10 @@ int __init addrconf_init(void) | |||
4678 | 4720 | ||
4679 | addrconf_verify(0); | 4721 | addrconf_verify(0); |
4680 | 4722 | ||
4723 | err = rtnl_af_register(&inet6_ops); | ||
4724 | if (err < 0) | ||
4725 | goto errout_af; | ||
4726 | |||
4681 | err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo); | 4727 | err = __rtnl_register(PF_INET6, RTM_GETLINK, NULL, inet6_dump_ifinfo); |
4682 | if (err < 0) | 4728 | if (err < 0) |
4683 | goto errout; | 4729 | goto errout; |
@@ -4693,6 +4739,8 @@ int __init addrconf_init(void) | |||
4693 | 4739 | ||
4694 | return 0; | 4740 | return 0; |
4695 | errout: | 4741 | errout: |
4742 | rtnl_af_unregister(&inet6_ops); | ||
4743 | errout_af: | ||
4696 | unregister_netdevice_notifier(&ipv6_dev_notf); | 4744 | unregister_netdevice_notifier(&ipv6_dev_notf); |
4697 | errlo: | 4745 | errlo: |
4698 | unregister_pernet_subsys(&addrconf_ops); | 4746 | unregister_pernet_subsys(&addrconf_ops); |
@@ -4713,6 +4761,8 @@ void addrconf_cleanup(void) | |||
4713 | 4761 | ||
4714 | rtnl_lock(); | 4762 | rtnl_lock(); |
4715 | 4763 | ||
4764 | __rtnl_af_unregister(&inet6_ops); | ||
4765 | |||
4716 | /* clean dev list */ | 4766 | /* clean dev list */ |
4717 | for_each_netdev(&init_net, dev) { | 4767 | for_each_netdev(&init_net, dev) { |
4718 | if (__in6_dev_get(dev) == NULL) | 4768 | if (__in6_dev_get(dev) == NULL) |