diff options
author | David S. Miller <davem@davemloft.net> | 2008-05-26 02:26:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-05-26 02:26:10 -0400 |
commit | 43154d08d6bb5c69aa0d0e3448fb348b4cd84e91 (patch) | |
tree | 176edb26aad2d33e8be36530b66b19d0603c4b1d /net/ipv6 | |
parent | 03194379a77b02df3404ec4848a50c6784e9a8a5 (diff) | |
parent | 289c79a4bd350e8a25065102563ad1a183d1b402 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/cpmac.c
net/mac80211/mlme.c
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 75 | ||||
-rw-r--r-- | net/ipv6/ndisc.c | 8 | ||||
-rw-r--r-- | net/ipv6/route.c | 12 | ||||
-rw-r--r-- | net/ipv6/sit.c | 89 |
4 files changed, 63 insertions, 121 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e591e09e5e4..3a835578fd1 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1764,14 +1764,16 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1764 | * 2) Configure prefixes with the auto flag set | 1764 | * 2) Configure prefixes with the auto flag set |
1765 | */ | 1765 | */ |
1766 | 1766 | ||
1767 | /* Avoid arithmetic overflow. Really, we could | 1767 | if (valid_lft == INFINITY_LIFE_TIME) |
1768 | save rt_expires in seconds, likely valid_lft, | 1768 | rt_expires = ~0UL; |
1769 | but it would require division in fib gc, that it | 1769 | else if (valid_lft >= 0x7FFFFFFF/HZ) { |
1770 | not good. | 1770 | /* Avoid arithmetic overflow. Really, we could |
1771 | */ | 1771 | * save rt_expires in seconds, likely valid_lft, |
1772 | if (valid_lft >= 0x7FFFFFFF/HZ) | 1772 | * but it would require division in fib gc, that it |
1773 | * not good. | ||
1774 | */ | ||
1773 | rt_expires = 0x7FFFFFFF - (0x7FFFFFFF % HZ); | 1775 | rt_expires = 0x7FFFFFFF - (0x7FFFFFFF % HZ); |
1774 | else | 1776 | } else |
1775 | rt_expires = valid_lft * HZ; | 1777 | rt_expires = valid_lft * HZ; |
1776 | 1778 | ||
1777 | /* | 1779 | /* |
@@ -1779,7 +1781,7 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1779 | * Avoid arithmetic overflow there as well. | 1781 | * Avoid arithmetic overflow there as well. |
1780 | * Overflow can happen only if HZ < USER_HZ. | 1782 | * Overflow can happen only if HZ < USER_HZ. |
1781 | */ | 1783 | */ |
1782 | if (HZ < USER_HZ && rt_expires > 0x7FFFFFFF / USER_HZ) | 1784 | if (HZ < USER_HZ && ~rt_expires && rt_expires > 0x7FFFFFFF / USER_HZ) |
1783 | rt_expires = 0x7FFFFFFF / USER_HZ; | 1785 | rt_expires = 0x7FFFFFFF / USER_HZ; |
1784 | 1786 | ||
1785 | if (pinfo->onlink) { | 1787 | if (pinfo->onlink) { |
@@ -1788,17 +1790,28 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
1788 | dev->ifindex, 1); | 1790 | dev->ifindex, 1); |
1789 | 1791 | ||
1790 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { | 1792 | if (rt && ((rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0)) { |
1791 | if (rt->rt6i_flags&RTF_EXPIRES) { | 1793 | /* Autoconf prefix route */ |
1792 | if (valid_lft == 0) { | 1794 | if (valid_lft == 0) { |
1793 | ip6_del_rt(rt); | 1795 | ip6_del_rt(rt); |
1794 | rt = NULL; | 1796 | rt = NULL; |
1795 | } else { | 1797 | } else if (~rt_expires) { |
1796 | rt->rt6i_expires = jiffies + rt_expires; | 1798 | /* not infinity */ |
1797 | } | 1799 | rt->rt6i_expires = jiffies + rt_expires; |
1800 | rt->rt6i_flags |= RTF_EXPIRES; | ||
1801 | } else { | ||
1802 | rt->rt6i_flags &= ~RTF_EXPIRES; | ||
1803 | rt->rt6i_expires = 0; | ||
1798 | } | 1804 | } |
1799 | } else if (valid_lft) { | 1805 | } else if (valid_lft) { |
1806 | int flags = RTF_ADDRCONF | RTF_PREFIX_RT; | ||
1807 | clock_t expires = 0; | ||
1808 | if (~rt_expires) { | ||
1809 | /* not infinity */ | ||
1810 | flags |= RTF_EXPIRES; | ||
1811 | expires = jiffies_to_clock_t(rt_expires); | ||
1812 | } | ||
1800 | addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len, | 1813 | addrconf_prefix_route(&pinfo->prefix, pinfo->prefix_len, |
1801 | dev, jiffies_to_clock_t(rt_expires), RTF_ADDRCONF|RTF_EXPIRES|RTF_PREFIX_RT); | 1814 | dev, expires, flags); |
1802 | } | 1815 | } |
1803 | if (rt) | 1816 | if (rt) |
1804 | dst_release(&rt->u.dst); | 1817 | dst_release(&rt->u.dst); |
@@ -2021,7 +2034,8 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2021 | struct inet6_dev *idev; | 2034 | struct inet6_dev *idev; |
2022 | struct net_device *dev; | 2035 | struct net_device *dev; |
2023 | int scope; | 2036 | int scope; |
2024 | u32 flags = RTF_EXPIRES; | 2037 | u32 flags; |
2038 | clock_t expires; | ||
2025 | 2039 | ||
2026 | ASSERT_RTNL(); | 2040 | ASSERT_RTNL(); |
2027 | 2041 | ||
@@ -2041,8 +2055,13 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2041 | if (valid_lft == INFINITY_LIFE_TIME) { | 2055 | if (valid_lft == INFINITY_LIFE_TIME) { |
2042 | ifa_flags |= IFA_F_PERMANENT; | 2056 | ifa_flags |= IFA_F_PERMANENT; |
2043 | flags = 0; | 2057 | flags = 0; |
2044 | } else if (valid_lft >= 0x7FFFFFFF/HZ) | 2058 | expires = 0; |
2045 | valid_lft = 0x7FFFFFFF/HZ; | 2059 | } else { |
2060 | if (valid_lft >= 0x7FFFFFFF/HZ) | ||
2061 | valid_lft = 0x7FFFFFFF/HZ; | ||
2062 | flags = RTF_EXPIRES; | ||
2063 | expires = jiffies_to_clock_t(valid_lft * HZ); | ||
2064 | } | ||
2046 | 2065 | ||
2047 | if (prefered_lft == 0) | 2066 | if (prefered_lft == 0) |
2048 | ifa_flags |= IFA_F_DEPRECATED; | 2067 | ifa_flags |= IFA_F_DEPRECATED; |
@@ -2060,7 +2079,7 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2060 | spin_unlock_bh(&ifp->lock); | 2079 | spin_unlock_bh(&ifp->lock); |
2061 | 2080 | ||
2062 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, | 2081 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, dev, |
2063 | jiffies_to_clock_t(valid_lft * HZ), flags); | 2082 | expires, flags); |
2064 | /* | 2083 | /* |
2065 | * Note that section 3.1 of RFC 4429 indicates | 2084 | * Note that section 3.1 of RFC 4429 indicates |
2066 | * that the Optimistic flag should not be set for | 2085 | * that the Optimistic flag should not be set for |
@@ -3148,7 +3167,8 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
3148 | static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, | 3167 | static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, |
3149 | u32 prefered_lft, u32 valid_lft) | 3168 | u32 prefered_lft, u32 valid_lft) |
3150 | { | 3169 | { |
3151 | u32 flags = RTF_EXPIRES; | 3170 | u32 flags; |
3171 | clock_t expires; | ||
3152 | 3172 | ||
3153 | if (!valid_lft || (prefered_lft > valid_lft)) | 3173 | if (!valid_lft || (prefered_lft > valid_lft)) |
3154 | return -EINVAL; | 3174 | return -EINVAL; |
@@ -3156,8 +3176,13 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, | |||
3156 | if (valid_lft == INFINITY_LIFE_TIME) { | 3176 | if (valid_lft == INFINITY_LIFE_TIME) { |
3157 | ifa_flags |= IFA_F_PERMANENT; | 3177 | ifa_flags |= IFA_F_PERMANENT; |
3158 | flags = 0; | 3178 | flags = 0; |
3159 | } else if (valid_lft >= 0x7FFFFFFF/HZ) | 3179 | expires = 0; |
3160 | valid_lft = 0x7FFFFFFF/HZ; | 3180 | } else { |
3181 | if (valid_lft >= 0x7FFFFFFF/HZ) | ||
3182 | valid_lft = 0x7FFFFFFF/HZ; | ||
3183 | flags = RTF_EXPIRES; | ||
3184 | expires = jiffies_to_clock_t(valid_lft * HZ); | ||
3185 | } | ||
3161 | 3186 | ||
3162 | if (prefered_lft == 0) | 3187 | if (prefered_lft == 0) |
3163 | ifa_flags |= IFA_F_DEPRECATED; | 3188 | ifa_flags |= IFA_F_DEPRECATED; |
@@ -3176,7 +3201,7 @@ static int inet6_addr_modify(struct inet6_ifaddr *ifp, u8 ifa_flags, | |||
3176 | ipv6_ifa_notify(0, ifp); | 3201 | ipv6_ifa_notify(0, ifp); |
3177 | 3202 | ||
3178 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev, | 3203 | addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->idev->dev, |
3179 | jiffies_to_clock_t(valid_lft * HZ), flags); | 3204 | expires, flags); |
3180 | addrconf_verify(0); | 3205 | addrconf_verify(0); |
3181 | 3206 | ||
3182 | return 0; | 3207 | return 0; |
@@ -4242,7 +4267,7 @@ static void addrconf_sysctl_register(struct inet6_dev *idev) | |||
4242 | neigh_sysctl_register(idev->dev, idev->nd_parms, NET_IPV6, | 4267 | neigh_sysctl_register(idev->dev, idev->nd_parms, NET_IPV6, |
4243 | NET_IPV6_NEIGH, "ipv6", | 4268 | NET_IPV6_NEIGH, "ipv6", |
4244 | &ndisc_ifinfo_sysctl_change, | 4269 | &ndisc_ifinfo_sysctl_change, |
4245 | NULL); | 4270 | ndisc_ifinfo_sysctl_strategy); |
4246 | __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, | 4271 | __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, |
4247 | idev->dev->ifindex, idev, &idev->cnf); | 4272 | idev->dev->ifindex, idev, &idev->cnf); |
4248 | } | 4273 | } |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index a55fc05b812..282fdb31f8e 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1727,10 +1727,10 @@ int ndisc_ifinfo_sysctl_change(struct ctl_table *ctl, int write, struct file * f | |||
1727 | return ret; | 1727 | return ret; |
1728 | } | 1728 | } |
1729 | 1729 | ||
1730 | static int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name, | 1730 | int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl, int __user *name, |
1731 | int nlen, void __user *oldval, | 1731 | int nlen, void __user *oldval, |
1732 | size_t __user *oldlenp, | 1732 | size_t __user *oldlenp, |
1733 | void __user *newval, size_t newlen) | 1733 | void __user *newval, size_t newlen) |
1734 | { | 1734 | { |
1735 | struct net_device *dev = ctl->extra1; | 1735 | struct net_device *dev = ctl->extra1; |
1736 | struct inet6_dev *idev; | 1736 | struct inet6_dev *idev; |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 12bba088034..48534c6c073 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -109,7 +109,7 @@ static struct dst_ops ip6_dst_ops_template = { | |||
109 | .negative_advice = ip6_negative_advice, | 109 | .negative_advice = ip6_negative_advice, |
110 | .link_failure = ip6_link_failure, | 110 | .link_failure = ip6_link_failure, |
111 | .update_pmtu = ip6_rt_update_pmtu, | 111 | .update_pmtu = ip6_rt_update_pmtu, |
112 | .local_out = ip6_local_out, | 112 | .local_out = __ip6_local_out, |
113 | .entry_size = sizeof(struct rt6_info), | 113 | .entry_size = sizeof(struct rt6_info), |
114 | .entries = ATOMIC_INIT(0), | 114 | .entries = ATOMIC_INIT(0), |
115 | }; | 115 | }; |
@@ -475,7 +475,7 @@ int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | |||
475 | lifetime = ntohl(rinfo->lifetime); | 475 | lifetime = ntohl(rinfo->lifetime); |
476 | if (lifetime == 0xffffffff) { | 476 | if (lifetime == 0xffffffff) { |
477 | /* infinity */ | 477 | /* infinity */ |
478 | } else if (lifetime > 0x7fffffff/HZ) { | 478 | } else if (lifetime > 0x7fffffff/HZ - 1) { |
479 | /* Avoid arithmetic overflow */ | 479 | /* Avoid arithmetic overflow */ |
480 | lifetime = 0x7fffffff/HZ - 1; | 480 | lifetime = 0x7fffffff/HZ - 1; |
481 | } | 481 | } |
@@ -1106,7 +1106,9 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1106 | } | 1106 | } |
1107 | 1107 | ||
1108 | rt->u.dst.obsolete = -1; | 1108 | rt->u.dst.obsolete = -1; |
1109 | rt->rt6i_expires = jiffies + clock_t_to_jiffies(cfg->fc_expires); | 1109 | rt->rt6i_expires = (cfg->fc_flags & RTF_EXPIRES) ? |
1110 | jiffies + clock_t_to_jiffies(cfg->fc_expires) : | ||
1111 | 0; | ||
1110 | 1112 | ||
1111 | if (cfg->fc_protocol == RTPROT_UNSPEC) | 1113 | if (cfg->fc_protocol == RTPROT_UNSPEC) |
1112 | cfg->fc_protocol = RTPROT_BOOT; | 1114 | cfg->fc_protocol = RTPROT_BOOT; |
@@ -2200,7 +2202,9 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
2200 | 2202 | ||
2201 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); | 2203 | NLA_PUT_U32(skb, RTA_PRIORITY, rt->rt6i_metric); |
2202 | 2204 | ||
2203 | expires = rt->rt6i_expires ? rt->rt6i_expires - jiffies : 0; | 2205 | expires = (rt->rt6i_flags & RTF_EXPIRES) ? |
2206 | rt->rt6i_expires - jiffies : 0; | ||
2207 | |||
2204 | if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0, | 2208 | if (rtnl_put_cacheinfo(skb, &rt->u.dst, 0, 0, 0, |
2205 | expires, rt->u.dst.error) < 0) | 2209 | expires, rt->u.dst.error) < 0) |
2206 | goto nla_put_failure; | 2210 | goto nla_put_failure; |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index b0ee9618763..6b8f0583b63 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -403,9 +403,8 @@ static void ipip6_tunnel_uninit(struct net_device *dev) | |||
403 | 403 | ||
404 | static int ipip6_err(struct sk_buff *skb, u32 info) | 404 | static int ipip6_err(struct sk_buff *skb, u32 info) |
405 | { | 405 | { |
406 | #ifndef I_WISH_WORLD_WERE_PERFECT | ||
407 | 406 | ||
408 | /* It is not :-( All the routers (except for Linux) return only | 407 | /* All the routers (except for Linux) return only |
409 | 8 bytes of packet payload. It means, that precise relaying of | 408 | 8 bytes of packet payload. It means, that precise relaying of |
410 | ICMP in the real Internet is absolutely infeasible. | 409 | ICMP in the real Internet is absolutely infeasible. |
411 | */ | 410 | */ |
@@ -462,92 +461,6 @@ static int ipip6_err(struct sk_buff *skb, u32 info) | |||
462 | out: | 461 | out: |
463 | read_unlock(&ipip6_lock); | 462 | read_unlock(&ipip6_lock); |
464 | return err; | 463 | return err; |
465 | #else | ||
466 | struct iphdr *iph = (struct iphdr*)dp; | ||
467 | int hlen = iph->ihl<<2; | ||
468 | struct ipv6hdr *iph6; | ||
469 | const int type = icmp_hdr(skb)->type; | ||
470 | const int code = icmp_hdr(skb)->code; | ||
471 | int rel_type = 0; | ||
472 | int rel_code = 0; | ||
473 | int rel_info = 0; | ||
474 | struct sk_buff *skb2; | ||
475 | struct rt6_info *rt6i; | ||
476 | |||
477 | if (len < hlen + sizeof(struct ipv6hdr)) | ||
478 | return; | ||
479 | iph6 = (struct ipv6hdr*)(dp + hlen); | ||
480 | |||
481 | switch (type) { | ||
482 | default: | ||
483 | return; | ||
484 | case ICMP_PARAMETERPROB: | ||
485 | if (icmp_hdr(skb)->un.gateway < hlen) | ||
486 | return; | ||
487 | |||
488 | /* So... This guy found something strange INSIDE encapsulated | ||
489 | packet. Well, he is fool, but what can we do ? | ||
490 | */ | ||
491 | rel_type = ICMPV6_PARAMPROB; | ||
492 | rel_info = icmp_hdr(skb)->un.gateway - hlen; | ||
493 | break; | ||
494 | |||
495 | case ICMP_DEST_UNREACH: | ||
496 | switch (code) { | ||
497 | case ICMP_SR_FAILED: | ||
498 | case ICMP_PORT_UNREACH: | ||
499 | /* Impossible event. */ | ||
500 | return; | ||
501 | case ICMP_FRAG_NEEDED: | ||
502 | /* Too complicated case ... */ | ||
503 | return; | ||
504 | default: | ||
505 | /* All others are translated to HOST_UNREACH. | ||
506 | rfc2003 contains "deep thoughts" about NET_UNREACH, | ||
507 | I believe, it is just ether pollution. --ANK | ||
508 | */ | ||
509 | rel_type = ICMPV6_DEST_UNREACH; | ||
510 | rel_code = ICMPV6_ADDR_UNREACH; | ||
511 | break; | ||
512 | } | ||
513 | break; | ||
514 | case ICMP_TIME_EXCEEDED: | ||
515 | if (code != ICMP_EXC_TTL) | ||
516 | return; | ||
517 | rel_type = ICMPV6_TIME_EXCEED; | ||
518 | rel_code = ICMPV6_EXC_HOPLIMIT; | ||
519 | break; | ||
520 | } | ||
521 | |||
522 | /* Prepare fake skb to feed it to icmpv6_send */ | ||
523 | skb2 = skb_clone(skb, GFP_ATOMIC); | ||
524 | if (skb2 == NULL) | ||
525 | return 0; | ||
526 | dst_release(skb2->dst); | ||
527 | skb2->dst = NULL; | ||
528 | skb_pull(skb2, skb->data - (u8*)iph6); | ||
529 | skb_reset_network_header(skb2); | ||
530 | |||
531 | /* Try to guess incoming interface */ | ||
532 | rt6i = rt6_lookup(dev_net(skb->dev), &iph6->saddr, NULL, NULL, 0); | ||
533 | if (rt6i && rt6i->rt6i_dev) { | ||
534 | skb2->dev = rt6i->rt6i_dev; | ||
535 | |||
536 | rt6i = rt6_lookup(dev_net(skb->dev), | ||
537 | &iph6->daddr, &iph6->saddr, NULL, 0); | ||
538 | |||
539 | if (rt6i && rt6i->rt6i_dev && rt6i->rt6i_dev->type == ARPHRD_SIT) { | ||
540 | struct ip_tunnel *t = netdev_priv(rt6i->rt6i_dev); | ||
541 | if (rel_type == ICMPV6_TIME_EXCEED && t->parms.iph.ttl) { | ||
542 | rel_type = ICMPV6_DEST_UNREACH; | ||
543 | rel_code = ICMPV6_ADDR_UNREACH; | ||
544 | } | ||
545 | icmpv6_send(skb2, rel_type, rel_code, rel_info, skb2->dev); | ||
546 | } | ||
547 | } | ||
548 | kfree_skb(skb2); | ||
549 | return 0; | ||
550 | #endif | ||
551 | } | 464 | } |
552 | 465 | ||
553 | static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) | 466 | static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) |