X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv6%2Faddrconf.c;h=386ca5c41296d79738cd7b95ce123b4719ab5607;hb=9464c7cf61b9433057924c36e6e02f303a00e768;hp=5c1b33f40a5298f2a5252913804a0bc49cf6a79a;hpb=41689045f6a3cbe0550e1d34e9cc20d2e8c432ba;p=linux-2.6.git diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 5c1b33f40..386ca5c41 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -40,6 +40,7 @@ * status etc. */ +#include #include #include #include @@ -508,26 +509,6 @@ void inet6_ifa_finish_destroy(struct inet6_ifaddr *ifp) kfree(ifp); } -static void -ipv6_link_dev_addr(struct inet6_dev *idev, struct inet6_ifaddr *ifp) -{ - struct inet6_ifaddr *ifa, **ifap; - int ifp_scope = ipv6_addr_src_scope(&ifp->addr); - - /* - * Each device address list is sorted in order of scope - - * global before linklocal. - */ - for (ifap = &idev->addr_list; (ifa = *ifap) != NULL; - ifap = &ifa->if_next) { - if (ifp_scope >= ipv6_addr_src_scope(&ifa->addr)) - break; - } - - ifp->if_next = *ifap; - *ifap = ifp; -} - /* On success it returns ifp with increased reference count */ static struct inet6_ifaddr * @@ -578,8 +559,6 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, ifa->flags = flags | IFA_F_TENTATIVE; ifa->cstamp = ifa->tstamp = jiffies; - ifa->rt = rt; - ifa->idev = idev; in6_dev_hold(idev); /* For caller */ @@ -595,7 +574,8 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, write_lock(&idev->lock); /* Add to inet6_dev unicast addr list. */ - ipv6_link_dev_addr(idev, ifa); + ifa->if_next = idev->addr_list; + idev->addr_list = ifa; #ifdef CONFIG_IPV6_PRIVACY if (ifa->flags&IFA_F_TEMPORARY) { @@ -605,6 +585,8 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr, int pfxlen, } #endif + ifa->rt = rt; + in6_ifa_hold(ifa); write_unlock(&idev->lock); out2: @@ -1006,7 +988,7 @@ int ipv6_dev_get_saddr(struct net_device *daddr_dev, continue; } else if (score.scope < hiscore.scope) { if (score.scope < daddr_scope) - break; /* addresses sorted by scope */ + continue; else { score.rule = 2; goto record_it; @@ -1869,21 +1851,15 @@ err_exit: /* * Manual configuration of address on an interface */ -static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, - __u32 prefered_lft, __u32 valid_lft) +static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen) { struct inet6_ifaddr *ifp; struct inet6_dev *idev; struct net_device *dev; - __u8 ifa_flags = 0; int scope; ASSERT_RTNL(); - /* check the lifetime */ - if (!valid_lft || prefered_lft > valid_lft) - return -EINVAL; - if ((dev = __dev_get_by_index(ifindex)) == NULL) return -ENODEV; @@ -1895,29 +1871,10 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, scope = ipv6_addr_scope(pfx); - if (valid_lft == INFINITY_LIFE_TIME) - ifa_flags |= IFA_F_PERMANENT; - else if (valid_lft >= 0x7FFFFFFF/HZ) - valid_lft = 0x7FFFFFFF/HZ; - - if (prefered_lft == 0) - ifa_flags |= IFA_F_DEPRECATED; - else if ((prefered_lft >= 0x7FFFFFFF/HZ) && - (prefered_lft != INFINITY_LIFE_TIME)) - prefered_lft = 0x7FFFFFFF/HZ; - - ifp = ipv6_add_addr(idev, pfx, plen, scope, ifa_flags); - + ifp = ipv6_add_addr(idev, pfx, plen, scope, IFA_F_PERMANENT); if (!IS_ERR(ifp)) { - spin_lock_bh(&ifp->lock); - ifp->valid_lft = valid_lft; - ifp->prefered_lft = prefered_lft; - ifp->tstamp = jiffies; - spin_unlock_bh(&ifp->lock); - addrconf_dad_start(ifp, 0); in6_ifa_put(ifp); - addrconf_verify(0); return 0; } @@ -1970,8 +1927,7 @@ int addrconf_add_ifaddr(void __user *arg) return -EFAULT; rtnl_lock(); - err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen, - INFINITY_LIFE_TIME, INFINITY_LIFE_TIME); + err = inet6_addr_add(ireq.ifr6_ifindex, &ireq.ifr6_addr, ireq.ifr6_prefixlen); rtnl_unlock(); return err; } @@ -2802,16 +2758,12 @@ restart: ifp->idev->nd_parms->retrans_time / HZ; #endif - if (ifp->valid_lft != INFINITY_LIFE_TIME && - age >= ifp->valid_lft) { + if (age >= ifp->valid_lft) { spin_unlock(&ifp->lock); in6_ifa_hold(ifp); read_unlock(&addrconf_hash_lock); ipv6_del_addr(ifp); goto restart; - } else if (ifp->prefered_lft == INFINITY_LIFE_TIME) { - spin_unlock(&ifp->lock); - continue; } else if (age >= ifp->prefered_lft) { /* jiffies - ifp->tsamp > age >= ifp->prefered_lft */ int deprecate = 0; @@ -2888,8 +2840,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) pfx = RTA_DATA(rta[IFA_ADDRESS-1]); } if (rta[IFA_LOCAL-1]) { - if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) || - (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))) + if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))) return -EINVAL; pfx = RTA_DATA(rta[IFA_LOCAL-1]); } @@ -2899,62 +2850,12 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) return inet6_addr_del(ifm->ifa_index, pfx, ifm->ifa_prefixlen); } -static int -inet6_addr_modify(int ifindex, struct in6_addr *pfx, - __u32 prefered_lft, __u32 valid_lft) -{ - struct inet6_ifaddr *ifp = NULL; - struct net_device *dev; - int ifa_flags = 0; - - if ((dev = __dev_get_by_index(ifindex)) == NULL) - return -ENODEV; - - if (!(dev->flags&IFF_UP)) - return -ENETDOWN; - - if (!valid_lft || (prefered_lft > valid_lft)) - return -EINVAL; - - ifp = ipv6_get_ifaddr(pfx, dev, 1); - if (ifp == NULL) - return -ENOENT; - - if (valid_lft == INFINITY_LIFE_TIME) - ifa_flags = IFA_F_PERMANENT; - else if (valid_lft >= 0x7FFFFFFF/HZ) - valid_lft = 0x7FFFFFFF/HZ; - - if (prefered_lft == 0) - ifa_flags = IFA_F_DEPRECATED; - else if ((prefered_lft >= 0x7FFFFFFF/HZ) && - (prefered_lft != INFINITY_LIFE_TIME)) - prefered_lft = 0x7FFFFFFF/HZ; - - spin_lock_bh(&ifp->lock); - ifp->flags = (ifp->flags & ~(IFA_F_DEPRECATED|IFA_F_PERMANENT)) | ifa_flags; - - ifp->tstamp = jiffies; - ifp->valid_lft = valid_lft; - ifp->prefered_lft = prefered_lft; - - spin_unlock_bh(&ifp->lock); - if (!(ifp->flags&IFA_F_TENTATIVE)) - ipv6_ifa_notify(0, ifp); - in6_ifa_put(ifp); - - addrconf_verify(0); - - return 0; -} - static int inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) { struct rtattr **rta = arg; struct ifaddrmsg *ifm = NLMSG_DATA(nlh); struct in6_addr *pfx; - __u32 valid_lft = INFINITY_LIFE_TIME, prefered_lft = INFINITY_LIFE_TIME; pfx = NULL; if (rta[IFA_ADDRESS-1]) { @@ -2963,34 +2864,14 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) pfx = RTA_DATA(rta[IFA_ADDRESS-1]); } if (rta[IFA_LOCAL-1]) { - if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*pfx) || - (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx)))) + if (pfx && memcmp(pfx, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*pfx))) return -EINVAL; pfx = RTA_DATA(rta[IFA_LOCAL-1]); } if (pfx == NULL) return -EINVAL; - if (rta[IFA_CACHEINFO-1]) { - struct ifa_cacheinfo *ci; - if (RTA_PAYLOAD(rta[IFA_CACHEINFO-1]) < sizeof(*ci)) - return -EINVAL; - ci = RTA_DATA(rta[IFA_CACHEINFO-1]); - valid_lft = ci->ifa_valid; - prefered_lft = ci->ifa_prefered; - } - - if (nlh->nlmsg_flags & NLM_F_REPLACE) { - int ret; - ret = inet6_addr_modify(ifm->ifa_index, pfx, - prefered_lft, valid_lft); - if (ret == 0 || !(nlh->nlmsg_flags & NLM_F_CREATE)) - return ret; - } - - return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen, - prefered_lft, valid_lft); - + return inet6_addr_add(ifm->ifa_index, pfx, ifm->ifa_prefixlen); } /* Maximum length of ifa_cacheinfo attributes */ @@ -3231,62 +3112,6 @@ static int inet6_dump_ifacaddr(struct sk_buff *skb, struct netlink_callback *cb) return inet6_dump_addr(skb, cb, type); } -static int inet6_rtm_getaddr(struct sk_buff *in_skb, - struct nlmsghdr* nlh, void *arg) -{ - struct rtattr **rta = arg; - struct ifaddrmsg *ifm = NLMSG_DATA(nlh); - struct in6_addr *addr = NULL; - struct net_device *dev = NULL; - struct inet6_ifaddr *ifa; - struct sk_buff *skb; - int size = NLMSG_SPACE(sizeof(struct ifaddrmsg) + INET6_IFADDR_RTA_SPACE); - int err; - - if (rta[IFA_ADDRESS-1]) { - if (RTA_PAYLOAD(rta[IFA_ADDRESS-1]) < sizeof(*addr)) - return -EINVAL; - addr = RTA_DATA(rta[IFA_ADDRESS-1]); - } - if (rta[IFA_LOCAL-1]) { - if (RTA_PAYLOAD(rta[IFA_LOCAL-1]) < sizeof(*addr) || - (addr && memcmp(addr, RTA_DATA(rta[IFA_LOCAL-1]), sizeof(*addr)))) - return -EINVAL; - addr = RTA_DATA(rta[IFA_LOCAL-1]); - } - if (addr == NULL) - return -EINVAL; - - if (ifm->ifa_index) - dev = __dev_get_by_index(ifm->ifa_index); - - if ((ifa = ipv6_get_ifaddr(addr, dev, 1)) == NULL) - return -EADDRNOTAVAIL; - - if ((skb = alloc_skb(size, GFP_KERNEL)) == NULL) { - err = -ENOBUFS; - goto out; - } - - NETLINK_CB(skb).dst_pid = NETLINK_CB(in_skb).pid; - err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid, - nlh->nlmsg_seq, RTM_NEWADDR, 0); - if (err < 0) { - err = -EMSGSIZE; - goto out_free; - } - - err = netlink_unicast(rtnl, skb, NETLINK_CB(in_skb).pid, MSG_DONTWAIT); - if (err > 0) - err = 0; -out: - in6_ifa_put(ifa); - return err; -out_free: - kfree_skb(skb); - goto out; -} - static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) { struct sk_buff *skb; @@ -3533,8 +3358,7 @@ static struct rtnetlink_link inet6_rtnetlink_table[RTM_NR_MSGTYPES] = { [RTM_GETLINK - RTM_BASE] = { .dumpit = inet6_dump_ifinfo, }, [RTM_NEWADDR - RTM_BASE] = { .doit = inet6_rtm_newaddr, }, [RTM_DELADDR - RTM_BASE] = { .doit = inet6_rtm_deladdr, }, - [RTM_GETADDR - RTM_BASE] = { .doit = inet6_rtm_getaddr, - .dumpit = inet6_dump_ifaddr, }, + [RTM_GETADDR - RTM_BASE] = { .dumpit = inet6_dump_ifaddr, }, [RTM_GETMULTICAST - RTM_BASE] = { .dumpit = inet6_dump_ifmcaddr, }, [RTM_GETANYCAST - RTM_BASE] = { .dumpit = inet6_dump_ifacaddr, }, [RTM_NEWROUTE - RTM_BASE] = { .doit = inet6_rtm_newroute, },