aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/addrconf.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/addrconf.c')
-rw-r--r--net/ipv6/addrconf.c208
1 files changed, 197 insertions, 11 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index dae802c0af7c..d1ab6ab29a55 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -70,6 +70,7 @@
70#include <net/snmp.h> 70#include <net/snmp.h>
71 71
72#include <net/af_ieee802154.h> 72#include <net/af_ieee802154.h>
73#include <net/firewire.h>
73#include <net/ipv6.h> 74#include <net/ipv6.h>
74#include <net/protocol.h> 75#include <net/protocol.h>
75#include <net/ndisc.h> 76#include <net/ndisc.h>
@@ -419,6 +420,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev)
419 ipv6_regen_rndid((unsigned long) ndev); 420 ipv6_regen_rndid((unsigned long) ndev);
420 } 421 }
421#endif 422#endif
423 ndev->token = in6addr_any;
422 424
423 if (netif_running(dev) && addrconf_qdisc_ok(dev)) 425 if (netif_running(dev) && addrconf_qdisc_ok(dev))
424 ndev->if_flags |= IF_READY; 426 ndev->if_flags |= IF_READY;
@@ -542,8 +544,7 @@ static const struct nla_policy devconf_ipv6_policy[NETCONFA_MAX+1] = {
542}; 544};
543 545
544static int inet6_netconf_get_devconf(struct sk_buff *in_skb, 546static int inet6_netconf_get_devconf(struct sk_buff *in_skb,
545 struct nlmsghdr *nlh, 547 struct nlmsghdr *nlh)
546 void *arg)
547{ 548{
548 struct net *net = sock_net(in_skb->sk); 549 struct net *net = sock_net(in_skb->sk);
549 struct nlattr *tb[NETCONFA_MAX+1]; 550 struct nlattr *tb[NETCONFA_MAX+1];
@@ -603,6 +604,77 @@ errout:
603 return err; 604 return err;
604} 605}
605 606
607static int inet6_netconf_dump_devconf(struct sk_buff *skb,
608 struct netlink_callback *cb)
609{
610 struct net *net = sock_net(skb->sk);
611 int h, s_h;
612 int idx, s_idx;
613 struct net_device *dev;
614 struct inet6_dev *idev;
615 struct hlist_head *head;
616
617 s_h = cb->args[0];
618 s_idx = idx = cb->args[1];
619
620 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
621 idx = 0;
622 head = &net->dev_index_head[h];
623 rcu_read_lock();
624 cb->seq = atomic_read(&net->ipv6.dev_addr_genid) ^
625 net->dev_base_seq;
626 hlist_for_each_entry_rcu(dev, head, index_hlist) {
627 if (idx < s_idx)
628 goto cont;
629 idev = __in6_dev_get(dev);
630 if (!idev)
631 goto cont;
632
633 if (inet6_netconf_fill_devconf(skb, dev->ifindex,
634 &idev->cnf,
635 NETLINK_CB(cb->skb).portid,
636 cb->nlh->nlmsg_seq,
637 RTM_NEWNETCONF,
638 NLM_F_MULTI,
639 -1) <= 0) {
640 rcu_read_unlock();
641 goto done;
642 }
643 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
644cont:
645 idx++;
646 }
647 rcu_read_unlock();
648 }
649 if (h == NETDEV_HASHENTRIES) {
650 if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_ALL,
651 net->ipv6.devconf_all,
652 NETLINK_CB(cb->skb).portid,
653 cb->nlh->nlmsg_seq,
654 RTM_NEWNETCONF, NLM_F_MULTI,
655 -1) <= 0)
656 goto done;
657 else
658 h++;
659 }
660 if (h == NETDEV_HASHENTRIES + 1) {
661 if (inet6_netconf_fill_devconf(skb, NETCONFA_IFINDEX_DEFAULT,
662 net->ipv6.devconf_dflt,
663 NETLINK_CB(cb->skb).portid,
664 cb->nlh->nlmsg_seq,
665 RTM_NEWNETCONF, NLM_F_MULTI,
666 -1) <= 0)
667 goto done;
668 else
669 h++;
670 }
671done:
672 cb->args[0] = h;
673 cb->args[1] = idx;
674
675 return skb->len;
676}
677
606#ifdef CONFIG_SYSCTL 678#ifdef CONFIG_SYSCTL
607static void dev_forward_change(struct inet6_dev *idev) 679static void dev_forward_change(struct inet6_dev *idev)
608{ 680{
@@ -804,6 +876,7 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen,
804 ifa->prefix_len = pfxlen; 876 ifa->prefix_len = pfxlen;
805 ifa->flags = flags | IFA_F_TENTATIVE; 877 ifa->flags = flags | IFA_F_TENTATIVE;
806 ifa->cstamp = ifa->tstamp = jiffies; 878 ifa->cstamp = ifa->tstamp = jiffies;
879 ifa->tokenized = false;
807 880
808 ifa->rt = rt; 881 ifa->rt = rt;
809 882
@@ -1666,6 +1739,20 @@ static int addrconf_ifid_eui64(u8 *eui, struct net_device *dev)
1666 return 0; 1739 return 0;
1667} 1740}
1668 1741
1742static int addrconf_ifid_ieee1394(u8 *eui, struct net_device *dev)
1743{
1744 union fwnet_hwaddr *ha;
1745
1746 if (dev->addr_len != FWNET_ALEN)
1747 return -1;
1748
1749 ha = (union fwnet_hwaddr *)dev->dev_addr;
1750
1751 memcpy(eui, &ha->uc.uniq_id, sizeof(ha->uc.uniq_id));
1752 eui[0] ^= 2;
1753 return 0;
1754}
1755
1669static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev) 1756static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev)
1670{ 1757{
1671 /* XXX: inherit EUI-64 from other interface -- yoshfuji */ 1758 /* XXX: inherit EUI-64 from other interface -- yoshfuji */
@@ -1730,6 +1817,8 @@ static int ipv6_generate_eui64(u8 *eui, struct net_device *dev)
1730 return addrconf_ifid_gre(eui, dev); 1817 return addrconf_ifid_gre(eui, dev);
1731 case ARPHRD_IEEE802154: 1818 case ARPHRD_IEEE802154:
1732 return addrconf_ifid_eui64(eui, dev); 1819 return addrconf_ifid_eui64(eui, dev);
1820 case ARPHRD_IEEE1394:
1821 return addrconf_ifid_ieee1394(eui, dev);
1733 } 1822 }
1734 return -1; 1823 return -1;
1735} 1824}
@@ -2044,11 +2133,19 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len, bool sllao)
2044 struct inet6_ifaddr *ifp; 2133 struct inet6_ifaddr *ifp;
2045 struct in6_addr addr; 2134 struct in6_addr addr;
2046 int create = 0, update_lft = 0; 2135 int create = 0, update_lft = 0;
2136 bool tokenized = false;
2047 2137
2048 if (pinfo->prefix_len == 64) { 2138 if (pinfo->prefix_len == 64) {
2049 memcpy(&addr, &pinfo->prefix, 8); 2139 memcpy(&addr, &pinfo->prefix, 8);
2050 if (ipv6_generate_eui64(addr.s6_addr + 8, dev) && 2140
2051 ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) { 2141 if (!ipv6_addr_any(&in6_dev->token)) {
2142 read_lock_bh(&in6_dev->lock);
2143 memcpy(addr.s6_addr + 8,
2144 in6_dev->token.s6_addr + 8, 8);
2145 read_unlock_bh(&in6_dev->lock);
2146 tokenized = true;
2147 } else if (ipv6_generate_eui64(addr.s6_addr + 8, dev) &&
2148 ipv6_inherit_eui64(addr.s6_addr + 8, in6_dev)) {
2052 in6_dev_put(in6_dev); 2149 in6_dev_put(in6_dev);
2053 return; 2150 return;
2054 } 2151 }
@@ -2089,6 +2186,7 @@ ok:
2089 2186
2090 update_lft = create = 1; 2187 update_lft = create = 1;
2091 ifp->cstamp = jiffies; 2188 ifp->cstamp = jiffies;
2189 ifp->tokenized = tokenized;
2092 addrconf_dad_start(ifp); 2190 addrconf_dad_start(ifp);
2093 } 2191 }
2094 2192
@@ -2598,7 +2696,8 @@ static void addrconf_dev_config(struct net_device *dev)
2598 (dev->type != ARPHRD_FDDI) && 2696 (dev->type != ARPHRD_FDDI) &&
2599 (dev->type != ARPHRD_ARCNET) && 2697 (dev->type != ARPHRD_ARCNET) &&
2600 (dev->type != ARPHRD_INFINIBAND) && 2698 (dev->type != ARPHRD_INFINIBAND) &&
2601 (dev->type != ARPHRD_IEEE802154)) { 2699 (dev->type != ARPHRD_IEEE802154) &&
2700 (dev->type != ARPHRD_IEEE1394)) {
2602 /* Alas, we support only Ethernet autoconfiguration. */ 2701 /* Alas, we support only Ethernet autoconfiguration. */
2603 return; 2702 return;
2604 } 2703 }
@@ -3535,7 +3634,7 @@ static const struct nla_policy ifa_ipv6_policy[IFA_MAX+1] = {
3535}; 3634};
3536 3635
3537static int 3636static int
3538inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 3637inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh)
3539{ 3638{
3540 struct net *net = sock_net(skb->sk); 3639 struct net *net = sock_net(skb->sk);
3541 struct ifaddrmsg *ifm; 3640 struct ifaddrmsg *ifm;
@@ -3601,7 +3700,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags,
3601} 3700}
3602 3701
3603static int 3702static int
3604inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) 3703inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh)
3605{ 3704{
3606 struct net *net = sock_net(skb->sk); 3705 struct net *net = sock_net(skb->sk);
3607 struct ifaddrmsg *ifm; 3706 struct ifaddrmsg *ifm;
@@ -3832,6 +3931,7 @@ static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb,
3832 NLM_F_MULTI); 3931 NLM_F_MULTI);
3833 if (err <= 0) 3932 if (err <= 0)
3834 break; 3933 break;
3934 nl_dump_check_consistent(cb, nlmsg_hdr(skb));
3835 } 3935 }
3836 break; 3936 break;
3837 } 3937 }
@@ -3889,6 +3989,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
3889 s_ip_idx = ip_idx = cb->args[2]; 3989 s_ip_idx = ip_idx = cb->args[2];
3890 3990
3891 rcu_read_lock(); 3991 rcu_read_lock();
3992 cb->seq = atomic_read(&net->ipv6.dev_addr_genid) ^ net->dev_base_seq;
3892 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { 3993 for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
3893 idx = 0; 3994 idx = 0;
3894 head = &net->dev_index_head[h]; 3995 head = &net->dev_index_head[h];
@@ -3940,8 +4041,7 @@ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb)
3940 return inet6_dump_addr(skb, cb, type); 4041 return inet6_dump_addr(skb, cb, type);
3941} 4042}
3942 4043
3943static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh, 4044static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh)
3944 void *arg)
3945{ 4045{
3946 struct net *net = sock_net(in_skb->sk); 4046 struct net *net = sock_net(in_skb->sk);
3947 struct ifaddrmsg *ifm; 4047 struct ifaddrmsg *ifm;
@@ -4074,7 +4174,8 @@ static inline size_t inet6_ifla6_size(void)
4074 + nla_total_size(sizeof(struct ifla_cacheinfo)) 4174 + nla_total_size(sizeof(struct ifla_cacheinfo))
4075 + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */ 4175 + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
4076 + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */ 4176 + nla_total_size(IPSTATS_MIB_MAX * 8) /* IFLA_INET6_STATS */
4077 + nla_total_size(ICMP6_MIB_MAX * 8); /* IFLA_INET6_ICMP6STATS */ 4177 + nla_total_size(ICMP6_MIB_MAX * 8) /* IFLA_INET6_ICMP6STATS */
4178 + nla_total_size(sizeof(struct in6_addr)); /* IFLA_INET6_TOKEN */
4078} 4179}
4079 4180
4080static inline size_t inet6_if_nlmsg_size(void) 4181static inline size_t inet6_if_nlmsg_size(void)
@@ -4161,6 +4262,13 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev)
4161 goto nla_put_failure; 4262 goto nla_put_failure;
4162 snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla)); 4263 snmp6_fill_stats(nla_data(nla), idev, IFLA_INET6_ICMP6STATS, nla_len(nla));
4163 4264
4265 nla = nla_reserve(skb, IFLA_INET6_TOKEN, sizeof(struct in6_addr));
4266 if (nla == NULL)
4267 goto nla_put_failure;
4268 read_lock_bh(&idev->lock);
4269 memcpy(nla_data(nla), idev->token.s6_addr, nla_len(nla));
4270 read_unlock_bh(&idev->lock);
4271
4164 return 0; 4272 return 0;
4165 4273
4166nla_put_failure: 4274nla_put_failure:
@@ -4188,6 +4296,80 @@ static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev)
4188 return 0; 4296 return 0;
4189} 4297}
4190 4298
4299static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token)
4300{
4301 struct inet6_ifaddr *ifp;
4302 struct net_device *dev = idev->dev;
4303 bool update_rs = false;
4304
4305 if (token == NULL)
4306 return -EINVAL;
4307 if (ipv6_addr_any(token))
4308 return -EINVAL;
4309 if (dev->flags & (IFF_LOOPBACK | IFF_NOARP))
4310 return -EINVAL;
4311 if (!ipv6_accept_ra(idev))
4312 return -EINVAL;
4313 if (idev->cnf.rtr_solicits <= 0)
4314 return -EINVAL;
4315
4316 write_lock_bh(&idev->lock);
4317
4318 BUILD_BUG_ON(sizeof(token->s6_addr) != 16);
4319 memcpy(idev->token.s6_addr + 8, token->s6_addr + 8, 8);
4320
4321 write_unlock_bh(&idev->lock);
4322
4323 if (!idev->dead && (idev->if_flags & IF_READY)) {
4324 struct in6_addr ll_addr;
4325
4326 ipv6_get_lladdr(dev, &ll_addr, IFA_F_TENTATIVE |
4327 IFA_F_OPTIMISTIC);
4328
4329 /* If we're not ready, then normal ifup will take care
4330 * of this. Otherwise, we need to request our rs here.
4331 */
4332 ndisc_send_rs(dev, &ll_addr, &in6addr_linklocal_allrouters);
4333 update_rs = true;
4334 }
4335
4336 write_lock_bh(&idev->lock);
4337
4338 if (update_rs)
4339 idev->if_flags |= IF_RS_SENT;
4340
4341 /* Well, that's kinda nasty ... */
4342 list_for_each_entry(ifp, &idev->addr_list, if_list) {
4343 spin_lock(&ifp->lock);
4344 if (ifp->tokenized) {
4345 ifp->valid_lft = 0;
4346 ifp->prefered_lft = 0;
4347 }
4348 spin_unlock(&ifp->lock);
4349 }
4350
4351 write_unlock_bh(&idev->lock);
4352 return 0;
4353}
4354
4355static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla)
4356{
4357 int err = -EINVAL;
4358 struct inet6_dev *idev = __in6_dev_get(dev);
4359 struct nlattr *tb[IFLA_INET6_MAX + 1];
4360
4361 if (!idev)
4362 return -EAFNOSUPPORT;
4363
4364 if (nla_parse_nested(tb, IFLA_INET6_MAX, nla, NULL) < 0)
4365 BUG();
4366
4367 if (tb[IFLA_INET6_TOKEN])
4368 err = inet6_set_iftoken(idev, nla_data(tb[IFLA_INET6_TOKEN]));
4369
4370 return err;
4371}
4372
4191static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, 4373static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
4192 u32 portid, u32 seq, int event, unsigned int flags) 4374 u32 portid, u32 seq, int event, unsigned int flags)
4193{ 4375{
@@ -4366,6 +4548,8 @@ errout:
4366 4548
4367static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) 4549static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
4368{ 4550{
4551 struct net *net = dev_net(ifp->idev->dev);
4552
4369 inet6_ifa_notify(event ? : RTM_NEWADDR, ifp); 4553 inet6_ifa_notify(event ? : RTM_NEWADDR, ifp);
4370 4554
4371 switch (event) { 4555 switch (event) {
@@ -4391,6 +4575,7 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
4391 dst_free(&ifp->rt->dst); 4575 dst_free(&ifp->rt->dst);
4392 break; 4576 break;
4393 } 4577 }
4578 atomic_inc(&net->ipv6.dev_addr_genid);
4394} 4579}
4395 4580
4396static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) 4581static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp)
@@ -4871,6 +5056,7 @@ static struct rtnl_af_ops inet6_ops = {
4871 .family = AF_INET6, 5056 .family = AF_INET6,
4872 .fill_link_af = inet6_fill_link_af, 5057 .fill_link_af = inet6_fill_link_af,
4873 .get_link_af_size = inet6_get_link_af_size, 5058 .get_link_af_size = inet6_get_link_af_size,
5059 .set_link_af = inet6_set_link_af,
4874}; 5060};
4875 5061
4876/* 5062/*
@@ -4943,7 +5129,7 @@ int __init addrconf_init(void)
4943 __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL, 5129 __rtnl_register(PF_INET6, RTM_GETANYCAST, NULL,
4944 inet6_dump_ifacaddr, NULL); 5130 inet6_dump_ifacaddr, NULL);
4945 __rtnl_register(PF_INET6, RTM_GETNETCONF, inet6_netconf_get_devconf, 5131 __rtnl_register(PF_INET6, RTM_GETNETCONF, inet6_netconf_get_devconf,
4946 NULL, NULL); 5132 inet6_netconf_dump_devconf, NULL);
4947 5133
4948 ipv6_addr_label_rtnl_register(); 5134 ipv6_addr_label_rtnl_register();
4949 5135