X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;ds=sidebyside;f=net%2Fipv6%2Faddrconf.c;h=1b616992d91637de002f87ab94843ce90301ba33;hb=d6e8823e7bf423c6850c68f716d2f5f693c97447;hp=569a37d698f7711fbf2c61aad8b271cce11550c5;hpb=60f29b1e1600d89aee5e529acb4b276a6650cb8b;p=powerpc.git diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 569a37d698..1b616992d9 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -211,74 +211,6 @@ const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT; #endif const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT; -#define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) - -static inline unsigned ipv6_addr_scope2type(unsigned scope) -{ - switch(scope) { - case IPV6_ADDR_SCOPE_NODELOCAL: - return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_NODELOCAL) | - IPV6_ADDR_LOOPBACK); - case IPV6_ADDR_SCOPE_LINKLOCAL: - return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL) | - IPV6_ADDR_LINKLOCAL); - case IPV6_ADDR_SCOPE_SITELOCAL: - return (IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL) | - IPV6_ADDR_SITELOCAL); - } - return IPV6_ADDR_SCOPE_TYPE(scope); -} - -int __ipv6_addr_type(const struct in6_addr *addr) -{ - __be32 st; - - st = addr->s6_addr32[0]; - - /* Consider all addresses with the first three bits different of - 000 and 111 as unicasts. - */ - if ((st & htonl(0xE0000000)) != htonl(0x00000000) && - (st & htonl(0xE0000000)) != htonl(0xE0000000)) - return (IPV6_ADDR_UNICAST | - IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); - - if ((st & htonl(0xFF000000)) == htonl(0xFF000000)) { - /* multicast */ - /* addr-select 3.1 */ - return (IPV6_ADDR_MULTICAST | - ipv6_addr_scope2type(IPV6_ADDR_MC_SCOPE(addr))); - } - - if ((st & htonl(0xFFC00000)) == htonl(0xFE800000)) - return (IPV6_ADDR_LINKLOCAL | IPV6_ADDR_UNICAST | - IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.1 */ - if ((st & htonl(0xFFC00000)) == htonl(0xFEC00000)) - return (IPV6_ADDR_SITELOCAL | IPV6_ADDR_UNICAST | - IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_SITELOCAL)); /* addr-select 3.1 */ - - if ((addr->s6_addr32[0] | addr->s6_addr32[1]) == 0) { - if (addr->s6_addr32[2] == 0) { - if (addr->s6_addr32[3] == 0) - return IPV6_ADDR_ANY; - - if (addr->s6_addr32[3] == htonl(0x00000001)) - return (IPV6_ADDR_LOOPBACK | IPV6_ADDR_UNICAST | - IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_LINKLOCAL)); /* addr-select 3.4 */ - - return (IPV6_ADDR_COMPATv4 | IPV6_ADDR_UNICAST | - IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ - } - - if (addr->s6_addr32[2] == htonl(0x0000ffff)) - return (IPV6_ADDR_MAPPED | - IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.3 */ - } - - return (IPV6_ADDR_RESERVED | - IPV6_ADDR_SCOPE_TYPE(IPV6_ADDR_SCOPE_GLOBAL)); /* addr-select 3.4 */ -} - static void addrconf_del_timer(struct inet6_ifaddr *ifp) { if (del_timer(&ifp->timer)) @@ -410,10 +342,6 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) } #endif - if (netif_carrier_ok(dev)) - ndev->if_flags |= IF_READY; - - ipv6_mc_init_dev(ndev); ndev->tstamp = jiffies; #ifdef CONFIG_SYSCTL @@ -468,6 +396,8 @@ static void dev_forward_change(struct inet6_dev *idev) ipv6_dev_mc_dec(dev, &addr); } for (ifa=idev->addr_list; ifa; ifa=ifa->if_next) { + if (ifa->flags&IFA_F_TENTATIVE) + continue; if (idev->cnf.forwarding) addrconf_join_anycast(ifa); else @@ -874,7 +804,7 @@ struct ipv6_saddr_score { #define IPV6_SADDR_SCORE_LABEL 0x0020 #define IPV6_SADDR_SCORE_PRIVACY 0x0040 -static int inline ipv6_saddr_preferred(int type) +static inline int ipv6_saddr_preferred(int type) { if (type & (IPV6_ADDR_MAPPED|IPV6_ADDR_COMPATv4| IPV6_ADDR_LOOPBACK|IPV6_ADDR_RESERVED)) @@ -883,7 +813,7 @@ static int inline ipv6_saddr_preferred(int type) } /* static matching label */ -static int inline ipv6_saddr_label(const struct in6_addr *addr, int type) +static inline int ipv6_saddr_label(const struct in6_addr *addr, int type) { /* * prefix (longest match) label @@ -1910,6 +1840,7 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, struct inet6_dev *idev; struct net_device *dev; int scope; + u32 flags = RTF_EXPIRES; ASSERT_RTNL(); @@ -1925,9 +1856,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) + if (valid_lft == INFINITY_LIFE_TIME) { ifa_flags |= IFA_F_PERMANENT; - else if (valid_lft >= 0x7FFFFFFF/HZ) + flags = 0; + } else if (valid_lft >= 0x7FFFFFFF/HZ) valid_lft = 0x7FFFFFFF/HZ; if (prefered_lft == 0) @@ -1945,6 +1877,8 @@ static int inet6_addr_add(int ifindex, struct in6_addr *pfx, int plen, ifp->tstamp = jiffies; spin_unlock_bh(&ifp->lock); + addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, + jiffies_to_clock_t(valid_lft * HZ), flags); addrconf_dad_start(ifp, 0); in6_ifa_put(ifp); addrconf_verify(0); @@ -2124,6 +2058,7 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr ifp = ipv6_add_addr(idev, addr, 64, IFA_LINK, IFA_F_PERMANENT); if (!IS_ERR(ifp)) { + addrconf_prefix_route(&ifp->addr, ifp->prefix_len, idev->dev, 0, 0); addrconf_dad_start(ifp, 0); in6_ifa_put(ifp); } @@ -2240,6 +2175,14 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, int run_pending = 0; switch(event) { + case NETDEV_REGISTER: + if (!idev) { + idev = ipv6_add_dev(dev); + if (!idev) + printk(KERN_WARNING "IPv6: add_dev failed for %s\n", + dev->name); + } + break; case NETDEV_UP: case NETDEV_CHANGE: if (event == NETDEV_UP) { @@ -2538,10 +2481,6 @@ static void addrconf_dad_start(struct inet6_ifaddr *ifp, u32 flags) addrconf_join_solict(dev, &ifp->addr); - if (ifp->prefix_len != 128 && (ifp->flags&IFA_F_PERMANENT)) - addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, 0, - flags); - net_srandom(ifp->addr.s6_addr32[3]); read_lock_bh(&idev->lock); @@ -2972,12 +2911,15 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, u32 prefered_lft, u32 valid_lft) { + u32 flags = RTF_EXPIRES; + if (!valid_lft || (prefered_lft > valid_lft)) return -EINVAL; - if (valid_lft == INFINITY_LIFE_TIME) + if (valid_lft == INFINITY_LIFE_TIME) { ifa_flags |= IFA_F_PERMANENT; - else if (valid_lft >= 0x7FFFFFFF/HZ) + flags = 0; + } else if (valid_lft >= 0x7FFFFFFF/HZ) valid_lft = 0x7FFFFFFF/HZ; if (prefered_lft == 0) @@ -2996,6 +2938,8 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, if (!(ifp->flags&IFA_F_TENTATIVE)) ipv6_ifa_notify(0, ifp); + addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev, + jiffies_to_clock_t(valid_lft * HZ), flags); addrconf_verify(0); return 0; @@ -3374,7 +3318,7 @@ errout: rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err); } -static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, +static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, __s32 *array, int bytes) { BUG_ON(bytes < (DEVCONF_MAX * 4));