diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-05 21:44:59 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-05 21:44:59 -0500 |
commit | 15b0669072127f282896b3bef2e9df4ec5d7264f (patch) | |
tree | 8480e09bbc7c26cd5c9ef048b734664cb6fe76be /net/ipv6 | |
parent | c155b914651753f843445d2f860bc00137df5d52 (diff) | |
parent | 3537d54c0c39de5738bba8d19f128478b0b96a71 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (44 commits)
qlge: Fix sparse warnings for tx ring indexes.
qlge: Fix sparse warning regarding rx buffer queues.
qlge: Fix sparse endian warning in ql_hw_csum_setup().
qlge: Fix sparse endian warning for inbound packet control block flags.
qlge: Fix sparse warnings for byte swapping in qlge_ethool.c
myri10ge: print MAC and serial number on probe failure
pkt_sched: cls_u32: Fix locking in u32_change()
iucv: fix cpu hotplug
af_iucv: Free iucv path/socket in path_pending callback
af_iucv: avoid left over IUCV connections from failing connects
af_iucv: New error return codes for connect()
net/ehea: bitops work on unsigned longs
Revert "net: Fix for initial link state in 2.6.28"
tcp: Kill extraneous SPLICE_F_NONBLOCK checks.
tcp: don't mask EOF and socket errors on nonblocking splice receive
dccp: Integrate the TFRC library with DCCP
dccp: Clean up ccid.c after integration of CCID plugins
dccp: Lockless integration of CCID congestion-control plugins
qeth: get rid of extra argument after printk to dev_* conversion
qeth: No large send using EDDP for HiperSockets.
...
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/ipv6_sockglue.c | 2 | ||||
-rw-r--r-- | net/ipv6/route.c | 52 |
2 files changed, 48 insertions, 6 deletions
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index eeeaad2e8b5c..40f324655e24 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -404,7 +404,7 @@ sticky_done: | |||
404 | else if (optlen < sizeof(struct in6_pktinfo) || optval == NULL) | 404 | else if (optlen < sizeof(struct in6_pktinfo) || optval == NULL) |
405 | goto e_inval; | 405 | goto e_inval; |
406 | 406 | ||
407 | if (copy_from_user(&pkt, optval, optlen)) { | 407 | if (copy_from_user(&pkt, optval, sizeof(struct in6_pktinfo))) { |
408 | retv = -EFAULT; | 408 | retv = -EFAULT; |
409 | break; | 409 | break; |
410 | } | 410 | } |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 18c486cf4987..76f06b94ab9f 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -627,6 +627,9 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad | |||
627 | rt = ip6_rt_copy(ort); | 627 | rt = ip6_rt_copy(ort); |
628 | 628 | ||
629 | if (rt) { | 629 | if (rt) { |
630 | struct neighbour *neigh; | ||
631 | int attempts = !in_softirq(); | ||
632 | |||
630 | if (!(rt->rt6i_flags&RTF_GATEWAY)) { | 633 | if (!(rt->rt6i_flags&RTF_GATEWAY)) { |
631 | if (rt->rt6i_dst.plen != 128 && | 634 | if (rt->rt6i_dst.plen != 128 && |
632 | ipv6_addr_equal(&rt->rt6i_dst.addr, daddr)) | 635 | ipv6_addr_equal(&rt->rt6i_dst.addr, daddr)) |
@@ -646,7 +649,35 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad | |||
646 | } | 649 | } |
647 | #endif | 650 | #endif |
648 | 651 | ||
649 | rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); | 652 | retry: |
653 | neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); | ||
654 | if (IS_ERR(neigh)) { | ||
655 | struct net *net = dev_net(rt->rt6i_dev); | ||
656 | int saved_rt_min_interval = | ||
657 | net->ipv6.sysctl.ip6_rt_gc_min_interval; | ||
658 | int saved_rt_elasticity = | ||
659 | net->ipv6.sysctl.ip6_rt_gc_elasticity; | ||
660 | |||
661 | if (attempts-- > 0) { | ||
662 | net->ipv6.sysctl.ip6_rt_gc_elasticity = 1; | ||
663 | net->ipv6.sysctl.ip6_rt_gc_min_interval = 0; | ||
664 | |||
665 | ip6_dst_gc(net->ipv6.ip6_dst_ops); | ||
666 | |||
667 | net->ipv6.sysctl.ip6_rt_gc_elasticity = | ||
668 | saved_rt_elasticity; | ||
669 | net->ipv6.sysctl.ip6_rt_gc_min_interval = | ||
670 | saved_rt_min_interval; | ||
671 | goto retry; | ||
672 | } | ||
673 | |||
674 | if (net_ratelimit()) | ||
675 | printk(KERN_WARNING | ||
676 | "Neighbour table overflow.\n"); | ||
677 | dst_free(&rt->u.dst); | ||
678 | return NULL; | ||
679 | } | ||
680 | rt->rt6i_nexthop = neigh; | ||
650 | 681 | ||
651 | } | 682 | } |
652 | 683 | ||
@@ -945,8 +976,11 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
945 | dev_hold(dev); | 976 | dev_hold(dev); |
946 | if (neigh) | 977 | if (neigh) |
947 | neigh_hold(neigh); | 978 | neigh_hold(neigh); |
948 | else | 979 | else { |
949 | neigh = ndisc_get_neigh(dev, addr); | 980 | neigh = ndisc_get_neigh(dev, addr); |
981 | if (IS_ERR(neigh)) | ||
982 | neigh = NULL; | ||
983 | } | ||
950 | 984 | ||
951 | rt->rt6i_dev = dev; | 985 | rt->rt6i_dev = dev; |
952 | rt->rt6i_idev = idev; | 986 | rt->rt6i_idev = idev; |
@@ -1887,6 +1921,7 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1887 | { | 1921 | { |
1888 | struct net *net = dev_net(idev->dev); | 1922 | struct net *net = dev_net(idev->dev); |
1889 | struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); | 1923 | struct rt6_info *rt = ip6_dst_alloc(net->ipv6.ip6_dst_ops); |
1924 | struct neighbour *neigh; | ||
1890 | 1925 | ||
1891 | if (rt == NULL) | 1926 | if (rt == NULL) |
1892 | return ERR_PTR(-ENOMEM); | 1927 | return ERR_PTR(-ENOMEM); |
@@ -1909,11 +1944,18 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1909 | rt->rt6i_flags |= RTF_ANYCAST; | 1944 | rt->rt6i_flags |= RTF_ANYCAST; |
1910 | else | 1945 | else |
1911 | rt->rt6i_flags |= RTF_LOCAL; | 1946 | rt->rt6i_flags |= RTF_LOCAL; |
1912 | rt->rt6i_nexthop = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); | 1947 | neigh = ndisc_get_neigh(rt->rt6i_dev, &rt->rt6i_gateway); |
1913 | if (rt->rt6i_nexthop == NULL) { | 1948 | if (IS_ERR(neigh)) { |
1914 | dst_free(&rt->u.dst); | 1949 | dst_free(&rt->u.dst); |
1915 | return ERR_PTR(-ENOMEM); | 1950 | |
1951 | /* We are casting this because that is the return | ||
1952 | * value type. But an errno encoded pointer is the | ||
1953 | * same regardless of the underlying pointer type, | ||
1954 | * and that's what we are returning. So this is OK. | ||
1955 | */ | ||
1956 | return (struct rt6_info *) neigh; | ||
1916 | } | 1957 | } |
1958 | rt->rt6i_nexthop = neigh; | ||
1917 | 1959 | ||
1918 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | 1960 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); |
1919 | rt->rt6i_dst.plen = 128; | 1961 | rt->rt6i_dst.plen = 128; |