diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-01-09 02:38:23 -0500 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2012-01-09 02:38:23 -0500 |
| commit | da733563be5a9da26fe81d9f007262d00b846e22 (patch) | |
| tree | db28291df94a2043af2123911984c5c173da4e6f /net/ipv6 | |
| parent | 6ccbcf2cb41131f8d56ef0723bf3f7c1f8486076 (diff) | |
| parent | dab78d7924598ea4031663dd10db814e2e324928 (diff) | |
Merge branch 'next' into for-linus
Diffstat (limited to 'net/ipv6')
34 files changed, 428 insertions, 267 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f012ebd87b43..cf88df82e2c2 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
| @@ -87,6 +87,7 @@ | |||
| 87 | 87 | ||
| 88 | #include <linux/proc_fs.h> | 88 | #include <linux/proc_fs.h> |
| 89 | #include <linux/seq_file.h> | 89 | #include <linux/seq_file.h> |
| 90 | #include <linux/export.h> | ||
| 90 | 91 | ||
| 91 | /* Set to 3 to get tracing... */ | 92 | /* Set to 3 to get tracing... */ |
| 92 | #define ACONF_DEBUG 2 | 93 | #define ACONF_DEBUG 2 |
| @@ -374,8 +375,8 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
| 374 | "%s(): cannot allocate memory for statistics; dev=%s.\n", | 375 | "%s(): cannot allocate memory for statistics; dev=%s.\n", |
| 375 | __func__, dev->name)); | 376 | __func__, dev->name)); |
| 376 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | 377 | neigh_parms_release(&nd_tbl, ndev->nd_parms); |
| 377 | ndev->dead = 1; | 378 | dev_put(dev); |
| 378 | in6_dev_finish_destroy(ndev); | 379 | kfree(ndev); |
| 379 | return NULL; | 380 | return NULL; |
| 380 | } | 381 | } |
| 381 | 382 | ||
| @@ -428,7 +429,7 @@ static struct inet6_dev * ipv6_add_dev(struct net_device *dev) | |||
| 428 | ndev->tstamp = jiffies; | 429 | ndev->tstamp = jiffies; |
| 429 | addrconf_sysctl_register(ndev); | 430 | addrconf_sysctl_register(ndev); |
| 430 | /* protected by rtnl_lock */ | 431 | /* protected by rtnl_lock */ |
| 431 | rcu_assign_pointer(dev->ip6_ptr, ndev); | 432 | RCU_INIT_POINTER(dev->ip6_ptr, ndev); |
| 432 | 433 | ||
| 433 | /* Join all-node multicast group */ | 434 | /* Join all-node multicast group */ |
| 434 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes); | 435 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allnodes); |
| @@ -824,12 +825,13 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, struct inet6_ifaddr *i | |||
| 824 | { | 825 | { |
| 825 | struct inet6_dev *idev = ifp->idev; | 826 | struct inet6_dev *idev = ifp->idev; |
| 826 | struct in6_addr addr, *tmpaddr; | 827 | struct in6_addr addr, *tmpaddr; |
| 827 | unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_cstamp, tmp_tstamp, age; | 828 | unsigned long tmp_prefered_lft, tmp_valid_lft, tmp_tstamp, age; |
| 828 | unsigned long regen_advance; | 829 | unsigned long regen_advance; |
| 829 | int tmp_plen; | 830 | int tmp_plen; |
| 830 | int ret = 0; | 831 | int ret = 0; |
| 831 | int max_addresses; | 832 | int max_addresses; |
| 832 | u32 addr_flags; | 833 | u32 addr_flags; |
| 834 | unsigned long now = jiffies; | ||
| 833 | 835 | ||
| 834 | write_lock(&idev->lock); | 836 | write_lock(&idev->lock); |
| 835 | if (ift) { | 837 | if (ift) { |
| @@ -874,7 +876,7 @@ retry: | |||
| 874 | goto out; | 876 | goto out; |
| 875 | } | 877 | } |
| 876 | memcpy(&addr.s6_addr[8], idev->rndid, 8); | 878 | memcpy(&addr.s6_addr[8], idev->rndid, 8); |
| 877 | age = (jiffies - ifp->tstamp) / HZ; | 879 | age = (now - ifp->tstamp) / HZ; |
| 878 | tmp_valid_lft = min_t(__u32, | 880 | tmp_valid_lft = min_t(__u32, |
| 879 | ifp->valid_lft, | 881 | ifp->valid_lft, |
| 880 | idev->cnf.temp_valid_lft + age); | 882 | idev->cnf.temp_valid_lft + age); |
| @@ -884,7 +886,6 @@ retry: | |||
| 884 | idev->cnf.max_desync_factor); | 886 | idev->cnf.max_desync_factor); |
| 885 | tmp_plen = ifp->prefix_len; | 887 | tmp_plen = ifp->prefix_len; |
| 886 | max_addresses = idev->cnf.max_addresses; | 888 | max_addresses = idev->cnf.max_addresses; |
| 887 | tmp_cstamp = ifp->cstamp; | ||
| 888 | tmp_tstamp = ifp->tstamp; | 889 | tmp_tstamp = ifp->tstamp; |
| 889 | spin_unlock_bh(&ifp->lock); | 890 | spin_unlock_bh(&ifp->lock); |
| 890 | 891 | ||
| @@ -929,7 +930,7 @@ retry: | |||
| 929 | ift->ifpub = ifp; | 930 | ift->ifpub = ifp; |
| 930 | ift->valid_lft = tmp_valid_lft; | 931 | ift->valid_lft = tmp_valid_lft; |
| 931 | ift->prefered_lft = tmp_prefered_lft; | 932 | ift->prefered_lft = tmp_prefered_lft; |
| 932 | ift->cstamp = tmp_cstamp; | 933 | ift->cstamp = now; |
| 933 | ift->tstamp = tmp_tstamp; | 934 | ift->tstamp = tmp_tstamp; |
| 934 | spin_unlock_bh(&ift->lock); | 935 | spin_unlock_bh(&ift->lock); |
| 935 | 936 | ||
| @@ -1713,6 +1714,40 @@ addrconf_prefix_route(struct in6_addr *pfx, int plen, struct net_device *dev, | |||
| 1713 | ip6_route_add(&cfg); | 1714 | ip6_route_add(&cfg); |
| 1714 | } | 1715 | } |
| 1715 | 1716 | ||
| 1717 | |||
| 1718 | static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx, | ||
| 1719 | int plen, | ||
| 1720 | const struct net_device *dev, | ||
| 1721 | u32 flags, u32 noflags) | ||
| 1722 | { | ||
| 1723 | struct fib6_node *fn; | ||
| 1724 | struct rt6_info *rt = NULL; | ||
| 1725 | struct fib6_table *table; | ||
| 1726 | |||
| 1727 | table = fib6_get_table(dev_net(dev), RT6_TABLE_PREFIX); | ||
| 1728 | if (table == NULL) | ||
| 1729 | return NULL; | ||
| 1730 | |||
| 1731 | write_lock_bh(&table->tb6_lock); | ||
| 1732 | fn = fib6_locate(&table->tb6_root, pfx, plen, NULL, 0); | ||
| 1733 | if (!fn) | ||
| 1734 | goto out; | ||
| 1735 | for (rt = fn->leaf; rt; rt = rt->dst.rt6_next) { | ||
| 1736 | if (rt->rt6i_dev->ifindex != dev->ifindex) | ||
| 1737 | continue; | ||
| 1738 | if ((rt->rt6i_flags & flags) != flags) | ||
| 1739 | continue; | ||
| 1740 | if ((noflags != 0) && ((rt->rt6i_flags & flags) != 0)) | ||
| 1741 | continue; | ||
| 1742 | dst_hold(&rt->dst); | ||
| 1743 | break; | ||
| 1744 | } | ||
| 1745 | out: | ||
| 1746 | write_unlock_bh(&table->tb6_lock); | ||
| 1747 | return rt; | ||
| 1748 | } | ||
| 1749 | |||
| 1750 | |||
| 1716 | /* Create "default" multicast route to the interface */ | 1751 | /* Create "default" multicast route to the interface */ |
| 1717 | 1752 | ||
| 1718 | static void addrconf_add_mroute(struct net_device *dev) | 1753 | static void addrconf_add_mroute(struct net_device *dev) |
| @@ -1842,10 +1877,13 @@ void addrconf_prefix_rcv(struct net_device *dev, u8 *opt, int len) | |||
| 1842 | if (addrconf_finite_timeout(rt_expires)) | 1877 | if (addrconf_finite_timeout(rt_expires)) |
| 1843 | rt_expires *= HZ; | 1878 | rt_expires *= HZ; |
| 1844 | 1879 | ||
| 1845 | rt = rt6_lookup(net, &pinfo->prefix, NULL, | 1880 | rt = addrconf_get_prefix_route(&pinfo->prefix, |
| 1846 | dev->ifindex, 1); | 1881 | pinfo->prefix_len, |
| 1882 | dev, | ||
| 1883 | RTF_ADDRCONF | RTF_PREFIX_RT, | ||
| 1884 | RTF_GATEWAY | RTF_DEFAULT); | ||
| 1847 | 1885 | ||
| 1848 | if (rt && addrconf_is_prefix_route(rt)) { | 1886 | if (rt) { |
| 1849 | /* Autoconf prefix route */ | 1887 | /* Autoconf prefix route */ |
| 1850 | if (valid_lft == 0) { | 1888 | if (valid_lft == 0) { |
| 1851 | ip6_del_rt(rt); | 1889 | ip6_del_rt(rt); |
| @@ -1999,25 +2037,50 @@ ok: | |||
| 1999 | #ifdef CONFIG_IPV6_PRIVACY | 2037 | #ifdef CONFIG_IPV6_PRIVACY |
| 2000 | read_lock_bh(&in6_dev->lock); | 2038 | read_lock_bh(&in6_dev->lock); |
| 2001 | /* update all temporary addresses in the list */ | 2039 | /* update all temporary addresses in the list */ |
| 2002 | list_for_each_entry(ift, &in6_dev->tempaddr_list, tmp_list) { | 2040 | list_for_each_entry(ift, &in6_dev->tempaddr_list, |
| 2003 | /* | 2041 | tmp_list) { |
| 2004 | * When adjusting the lifetimes of an existing | 2042 | int age, max_valid, max_prefered; |
| 2005 | * temporary address, only lower the lifetimes. | 2043 | |
| 2006 | * Implementations must not increase the | ||
| 2007 | * lifetimes of an existing temporary address | ||
| 2008 | * when processing a Prefix Information Option. | ||
| 2009 | */ | ||
| 2010 | if (ifp != ift->ifpub) | 2044 | if (ifp != ift->ifpub) |
| 2011 | continue; | 2045 | continue; |
| 2012 | 2046 | ||
| 2047 | /* | ||
| 2048 | * RFC 4941 section 3.3: | ||
| 2049 | * If a received option will extend the lifetime | ||
| 2050 | * of a public address, the lifetimes of | ||
| 2051 | * temporary addresses should be extended, | ||
| 2052 | * subject to the overall constraint that no | ||
| 2053 | * temporary addresses should ever remain | ||
| 2054 | * "valid" or "preferred" for a time longer than | ||
| 2055 | * (TEMP_VALID_LIFETIME) or | ||
| 2056 | * (TEMP_PREFERRED_LIFETIME - DESYNC_FACTOR), | ||
| 2057 | * respectively. | ||
| 2058 | */ | ||
| 2059 | age = (now - ift->cstamp) / HZ; | ||
| 2060 | max_valid = in6_dev->cnf.temp_valid_lft - age; | ||
| 2061 | if (max_valid < 0) | ||
| 2062 | max_valid = 0; | ||
| 2063 | |||
| 2064 | max_prefered = in6_dev->cnf.temp_prefered_lft - | ||
| 2065 | in6_dev->cnf.max_desync_factor - | ||
| 2066 | age; | ||
| 2067 | if (max_prefered < 0) | ||
| 2068 | max_prefered = 0; | ||
| 2069 | |||
| 2070 | if (valid_lft > max_valid) | ||
| 2071 | valid_lft = max_valid; | ||
| 2072 | |||
| 2073 | if (prefered_lft > max_prefered) | ||
| 2074 | prefered_lft = max_prefered; | ||
| 2075 | |||
| 2013 | spin_lock(&ift->lock); | 2076 | spin_lock(&ift->lock); |
| 2014 | flags = ift->flags; | 2077 | flags = ift->flags; |
| 2015 | if (ift->valid_lft > valid_lft && | 2078 | ift->valid_lft = valid_lft; |
| 2016 | ift->valid_lft - valid_lft > (jiffies - ift->tstamp) / HZ) | 2079 | ift->prefered_lft = prefered_lft; |
| 2017 | ift->valid_lft = valid_lft + (jiffies - ift->tstamp) / HZ; | 2080 | ift->tstamp = now; |
| 2018 | if (ift->prefered_lft > prefered_lft && | 2081 | if (prefered_lft > 0) |
| 2019 | ift->prefered_lft - prefered_lft > (jiffies - ift->tstamp) / HZ) | 2082 | ift->flags &= ~IFA_F_DEPRECATED; |
| 2020 | ift->prefered_lft = prefered_lft + (jiffies - ift->tstamp) / HZ; | 2083 | |
| 2021 | spin_unlock(&ift->lock); | 2084 | spin_unlock(&ift->lock); |
| 2022 | if (!(flags&IFA_F_TENTATIVE)) | 2085 | if (!(flags&IFA_F_TENTATIVE)) |
| 2023 | ipv6_ifa_notify(0, ift); | 2086 | ipv6_ifa_notify(0, ift); |
| @@ -2025,9 +2088,11 @@ ok: | |||
| 2025 | 2088 | ||
| 2026 | if ((create || list_empty(&in6_dev->tempaddr_list)) && in6_dev->cnf.use_tempaddr > 0) { | 2089 | if ((create || list_empty(&in6_dev->tempaddr_list)) && in6_dev->cnf.use_tempaddr > 0) { |
| 2027 | /* | 2090 | /* |
| 2028 | * When a new public address is created as described in [ADDRCONF], | 2091 | * When a new public address is created as |
| 2029 | * also create a new temporary address. Also create a temporary | 2092 | * described in [ADDRCONF], also create a new |
| 2030 | * address if it's enabled but no temporary address currently exists. | 2093 | * temporary address. Also create a temporary |
| 2094 | * address if it's enabled but no temporary | ||
| 2095 | * address currently exists. | ||
| 2031 | */ | 2096 | */ |
| 2032 | read_unlock_bh(&in6_dev->lock); | 2097 | read_unlock_bh(&in6_dev->lock); |
| 2033 | ipv6_create_tempaddr(ifp, NULL); | 2098 | ipv6_create_tempaddr(ifp, NULL); |
| @@ -2706,7 +2771,7 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
| 2706 | idev->dead = 1; | 2771 | idev->dead = 1; |
| 2707 | 2772 | ||
| 2708 | /* protected by rtnl_lock */ | 2773 | /* protected by rtnl_lock */ |
| 2709 | rcu_assign_pointer(dev->ip6_ptr, NULL); | 2774 | RCU_INIT_POINTER(dev->ip6_ptr, NULL); |
| 2710 | 2775 | ||
| 2711 | /* Step 1.5: remove snmp6 entry */ | 2776 | /* Step 1.5: remove snmp6 entry */ |
| 2712 | snmp6_unregister_dev(idev); | 2777 | snmp6_unregister_dev(idev); |
| @@ -2969,12 +3034,12 @@ static void addrconf_dad_completed(struct inet6_ifaddr *ifp) | |||
| 2969 | 3034 | ||
| 2970 | ipv6_ifa_notify(RTM_NEWADDR, ifp); | 3035 | ipv6_ifa_notify(RTM_NEWADDR, ifp); |
| 2971 | 3036 | ||
| 2972 | /* If added prefix is link local and forwarding is off, | 3037 | /* If added prefix is link local and we are prepared to process |
| 2973 | start sending router solicitations. | 3038 | router advertisements, start sending router solicitations. |
| 2974 | */ | 3039 | */ |
| 2975 | 3040 | ||
| 2976 | if ((ifp->idev->cnf.forwarding == 0 || | 3041 | if (((ifp->idev->cnf.accept_ra == 1 && !ifp->idev->cnf.forwarding) || |
| 2977 | ifp->idev->cnf.forwarding == 2) && | 3042 | ifp->idev->cnf.accept_ra == 2) && |
| 2978 | ifp->idev->cnf.rtr_solicits > 0 && | 3043 | ifp->idev->cnf.rtr_solicits > 0 && |
| 2979 | (dev->flags&IFF_LOOPBACK) == 0 && | 3044 | (dev->flags&IFF_LOOPBACK) == 0 && |
| 2980 | (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) { | 3045 | (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)) { |
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index 6b03826552e1..399287e595d7 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * not configured or static. | 3 | * not configured or static. |
| 4 | */ | 4 | */ |
| 5 | 5 | ||
| 6 | #include <linux/export.h> | ||
| 6 | #include <net/ipv6.h> | 7 | #include <net/ipv6.h> |
| 7 | 8 | ||
| 8 | #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) | 9 | #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 3b5669a2582d..d27c797f9f05 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
| @@ -875,6 +875,7 @@ static struct sk_buff **ipv6_gro_receive(struct sk_buff **head, | |||
| 875 | skb_reset_transport_header(skb); | 875 | skb_reset_transport_header(skb); |
| 876 | __skb_push(skb, skb_gro_offset(skb)); | 876 | __skb_push(skb, skb_gro_offset(skb)); |
| 877 | 877 | ||
| 878 | ops = rcu_dereference(inet6_protos[proto]); | ||
| 878 | if (!ops || !ops->gro_receive) | 879 | if (!ops || !ops->gro_receive) |
| 879 | goto out_unlock; | 880 | goto out_unlock; |
| 880 | 881 | ||
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 2195ae651923..4c0f894d0843 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
| @@ -324,8 +324,6 @@ static void ah6_output_done(struct crypto_async_request *base, int err) | |||
| 324 | #endif | 324 | #endif |
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | err = ah->nexthdr; | ||
| 328 | |||
| 329 | kfree(AH_SKB_CB(skb)->tmp); | 327 | kfree(AH_SKB_CB(skb)->tmp); |
| 330 | xfrm_output_resume(skb, err); | 328 | xfrm_output_resume(skb, err); |
| 331 | } | 329 | } |
| @@ -466,12 +464,12 @@ static void ah6_input_done(struct crypto_async_request *base, int err) | |||
| 466 | if (err) | 464 | if (err) |
| 467 | goto out; | 465 | goto out; |
| 468 | 466 | ||
| 467 | err = ah->nexthdr; | ||
| 468 | |||
| 469 | skb->network_header += ah_hlen; | 469 | skb->network_header += ah_hlen; |
| 470 | memcpy(skb_network_header(skb), work_iph, hdr_len); | 470 | memcpy(skb_network_header(skb), work_iph, hdr_len); |
| 471 | __skb_pull(skb, ah_hlen + hdr_len); | 471 | __skb_pull(skb, ah_hlen + hdr_len); |
| 472 | skb_set_transport_header(skb, -hdr_len); | 472 | skb_set_transport_header(skb, -hdr_len); |
| 473 | |||
| 474 | err = ah->nexthdr; | ||
| 475 | out: | 473 | out: |
| 476 | kfree(AH_SKB_CB(skb)->tmp); | 474 | kfree(AH_SKB_CB(skb)->tmp); |
| 477 | xfrm_input_resume(skb, err); | 475 | xfrm_input_resume(skb, err); |
| @@ -583,8 +581,6 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
| 583 | if (err == -EINPROGRESS) | 581 | if (err == -EINPROGRESS) |
| 584 | goto out; | 582 | goto out; |
| 585 | 583 | ||
| 586 | if (err == -EBUSY) | ||
| 587 | err = NET_XMIT_DROP; | ||
| 588 | goto out_free; | 584 | goto out_free; |
| 589 | } | 585 | } |
| 590 | 586 | ||
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 9ef1831746ef..e2480691c220 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
| @@ -297,10 +297,6 @@ void ipv6_local_rxpmtu(struct sock *sk, struct flowi6 *fl6, u32 mtu) | |||
| 297 | ipv6_addr_copy(&iph->daddr, &fl6->daddr); | 297 | ipv6_addr_copy(&iph->daddr, &fl6->daddr); |
| 298 | 298 | ||
| 299 | mtu_info = IP6CBMTU(skb); | 299 | mtu_info = IP6CBMTU(skb); |
| 300 | if (!mtu_info) { | ||
| 301 | kfree_skb(skb); | ||
| 302 | return; | ||
| 303 | } | ||
| 304 | 300 | ||
| 305 | mtu_info->ip6m_mtu = mtu; | 301 | mtu_info->ip6m_mtu = mtu; |
| 306 | mtu_info->ip6m_addr.sin6_family = AF_INET6; | 302 | mtu_info->ip6m_addr.sin6_family = AF_INET6; |
| @@ -599,7 +595,7 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
| 599 | return 0; | 595 | return 0; |
| 600 | } | 596 | } |
| 601 | 597 | ||
| 602 | int datagram_send_ctl(struct net *net, | 598 | int datagram_send_ctl(struct net *net, struct sock *sk, |
| 603 | struct msghdr *msg, struct flowi6 *fl6, | 599 | struct msghdr *msg, struct flowi6 *fl6, |
| 604 | struct ipv6_txoptions *opt, | 600 | struct ipv6_txoptions *opt, |
| 605 | int *hlimit, int *tclass, int *dontfrag) | 601 | int *hlimit, int *tclass, int *dontfrag) |
| @@ -658,7 +654,8 @@ int datagram_send_ctl(struct net *net, | |||
| 658 | 654 | ||
| 659 | if (addr_type != IPV6_ADDR_ANY) { | 655 | if (addr_type != IPV6_ADDR_ANY) { |
| 660 | int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL; | 656 | int strict = __ipv6_addr_src_scope(addr_type) <= IPV6_ADDR_SCOPE_LINKLOCAL; |
| 661 | if (!ipv6_chk_addr(net, &src_info->ipi6_addr, | 657 | if (!inet_sk(sk)->transparent && |
| 658 | !ipv6_chk_addr(net, &src_info->ipi6_addr, | ||
| 662 | strict ? dev : NULL, 0)) | 659 | strict ? dev : NULL, 0)) |
| 663 | err = -EINVAL; | 660 | err = -EINVAL; |
| 664 | else | 661 | else |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 79a485e8a700..bf22a225f422 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/in6.h> | 30 | #include <linux/in6.h> |
| 31 | #include <linux/icmpv6.h> | 31 | #include <linux/icmpv6.h> |
| 32 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
| 33 | #include <linux/export.h> | ||
| 33 | 34 | ||
| 34 | #include <net/dst.h> | 35 | #include <net/dst.h> |
| 35 | #include <net/sock.h> | 36 | #include <net/sock.h> |
| @@ -273,12 +274,12 @@ static int ipv6_destopt_rcv(struct sk_buff *skb) | |||
| 273 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 274 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
| 274 | __u16 dstbuf; | 275 | __u16 dstbuf; |
| 275 | #endif | 276 | #endif |
| 276 | struct dst_entry *dst; | 277 | struct dst_entry *dst = skb_dst(skb); |
| 277 | 278 | ||
| 278 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || | 279 | if (!pskb_may_pull(skb, skb_transport_offset(skb) + 8) || |
| 279 | !pskb_may_pull(skb, (skb_transport_offset(skb) + | 280 | !pskb_may_pull(skb, (skb_transport_offset(skb) + |
| 280 | ((skb_transport_header(skb)[1] + 1) << 3)))) { | 281 | ((skb_transport_header(skb)[1] + 1) << 3)))) { |
| 281 | IP6_INC_STATS_BH(dev_net(skb_dst(skb)->dev), ip6_dst_idev(skb_dst(skb)), | 282 | IP6_INC_STATS_BH(dev_net(dst->dev), ip6_dst_idev(dst), |
| 282 | IPSTATS_MIB_INHDRERRORS); | 283 | IPSTATS_MIB_INHDRERRORS); |
| 283 | kfree_skb(skb); | 284 | kfree_skb(skb); |
| 284 | return -1; | 285 | return -1; |
| @@ -289,9 +290,7 @@ static int ipv6_destopt_rcv(struct sk_buff *skb) | |||
| 289 | dstbuf = opt->dst1; | 290 | dstbuf = opt->dst1; |
| 290 | #endif | 291 | #endif |
| 291 | 292 | ||
| 292 | dst = dst_clone(skb_dst(skb)); | ||
| 293 | if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { | 293 | if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { |
| 294 | dst_release(dst); | ||
| 295 | skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; | 294 | skb->transport_header += (skb_transport_header(skb)[1] + 1) << 3; |
| 296 | opt = IP6CB(skb); | 295 | opt = IP6CB(skb); |
| 297 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 296 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
| @@ -304,7 +303,6 @@ static int ipv6_destopt_rcv(struct sk_buff *skb) | |||
| 304 | 303 | ||
| 305 | IP6_INC_STATS_BH(dev_net(dst->dev), | 304 | IP6_INC_STATS_BH(dev_net(dst->dev), |
| 306 | ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); | 305 | ip6_dst_idev(dst), IPSTATS_MIB_INHDRERRORS); |
| 307 | dst_release(dst); | ||
| 308 | return -1; | 306 | return -1; |
| 309 | } | 307 | } |
| 310 | 308 | ||
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c index 14ed0a955b56..37f548b7f6dc 100644 --- a/net/ipv6/exthdrs_core.c +++ b/net/ipv6/exthdrs_core.c | |||
| @@ -2,6 +2,7 @@ | |||
| 2 | * IPv6 library code, needed by static components when full IPv6 support is | 2 | * IPv6 library code, needed by static components when full IPv6 support is |
| 3 | * not configured or static. | 3 | * not configured or static. |
| 4 | */ | 4 | */ |
| 5 | #include <linux/export.h> | ||
| 5 | #include <net/ipv6.h> | 6 | #include <net/ipv6.h> |
| 6 | 7 | ||
| 7 | /* | 8 | /* |
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c index 34d244df907d..295571576f83 100644 --- a/net/ipv6/fib6_rules.c +++ b/net/ipv6/fib6_rules.c | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | */ | 14 | */ |
| 15 | 15 | ||
| 16 | #include <linux/netdevice.h> | 16 | #include <linux/netdevice.h> |
| 17 | #include <linux/export.h> | ||
| 17 | 18 | ||
| 18 | #include <net/fib_rules.h> | 19 | #include <net/fib_rules.h> |
| 19 | #include <net/ipv6.h> | 20 | #include <net/ipv6.h> |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 11900417b1cc..90868fb42757 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
| @@ -490,7 +490,8 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
| 490 | goto out_dst_release; | 490 | goto out_dst_release; |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | idev = in6_dev_get(skb->dev); | 493 | rcu_read_lock(); |
| 494 | idev = __in6_dev_get(skb->dev); | ||
| 494 | 495 | ||
| 495 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, | 496 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, |
| 496 | len + sizeof(struct icmp6hdr), | 497 | len + sizeof(struct icmp6hdr), |
| @@ -500,19 +501,16 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
| 500 | if (err) { | 501 | if (err) { |
| 501 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); | 502 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); |
| 502 | ip6_flush_pending_frames(sk); | 503 | ip6_flush_pending_frames(sk); |
| 503 | goto out_put; | 504 | } else { |
| 505 | err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, | ||
| 506 | len + sizeof(struct icmp6hdr)); | ||
| 504 | } | 507 | } |
| 505 | err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, len + sizeof(struct icmp6hdr)); | 508 | rcu_read_unlock(); |
| 506 | |||
| 507 | out_put: | ||
| 508 | if (likely(idev != NULL)) | ||
| 509 | in6_dev_put(idev); | ||
| 510 | out_dst_release: | 509 | out_dst_release: |
| 511 | dst_release(dst); | 510 | dst_release(dst); |
| 512 | out: | 511 | out: |
| 513 | icmpv6_xmit_unlock(sk); | 512 | icmpv6_xmit_unlock(sk); |
| 514 | } | 513 | } |
| 515 | |||
| 516 | EXPORT_SYMBOL(icmpv6_send); | 514 | EXPORT_SYMBOL(icmpv6_send); |
| 517 | 515 | ||
| 518 | static void icmpv6_echo_reply(struct sk_buff *skb) | 516 | static void icmpv6_echo_reply(struct sk_buff *skb) |
| @@ -569,7 +567,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
| 569 | if (hlimit < 0) | 567 | if (hlimit < 0) |
| 570 | hlimit = ip6_dst_hoplimit(dst); | 568 | hlimit = ip6_dst_hoplimit(dst); |
| 571 | 569 | ||
| 572 | idev = in6_dev_get(skb->dev); | 570 | idev = __in6_dev_get(skb->dev); |
| 573 | 571 | ||
| 574 | msg.skb = skb; | 572 | msg.skb = skb; |
| 575 | msg.offset = 0; | 573 | msg.offset = 0; |
| @@ -583,13 +581,10 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
| 583 | if (err) { | 581 | if (err) { |
| 584 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); | 582 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); |
| 585 | ip6_flush_pending_frames(sk); | 583 | ip6_flush_pending_frames(sk); |
| 586 | goto out_put; | 584 | } else { |
| 585 | err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, | ||
| 586 | skb->len + sizeof(struct icmp6hdr)); | ||
| 587 | } | 587 | } |
| 588 | err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, skb->len + sizeof(struct icmp6hdr)); | ||
| 589 | |||
| 590 | out_put: | ||
| 591 | if (likely(idev != NULL)) | ||
| 592 | in6_dev_put(idev); | ||
| 593 | dst_release(dst); | 588 | dst_release(dst); |
| 594 | out: | 589 | out: |
| 595 | icmpv6_xmit_unlock(sk); | 590 | icmpv6_xmit_unlock(sk); |
| @@ -840,8 +835,7 @@ static int __net_init icmpv6_sk_init(struct net *net) | |||
| 840 | /* Enough space for 2 64K ICMP packets, including | 835 | /* Enough space for 2 64K ICMP packets, including |
| 841 | * sk_buff struct overhead. | 836 | * sk_buff struct overhead. |
| 842 | */ | 837 | */ |
| 843 | sk->sk_sndbuf = | 838 | sk->sk_sndbuf = 2 * SKB_TRUESIZE(64 * 1024); |
| 844 | (2 * ((64 * 1024) + sizeof(struct sk_buff))); | ||
| 845 | } | 839 | } |
| 846 | return 0; | 840 | return 0; |
| 847 | 841 | ||
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 8a58e8cf6646..fee46d5a2f12 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
| @@ -211,6 +211,7 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) | |||
| 211 | struct flowi6 fl6; | 211 | struct flowi6 fl6; |
| 212 | struct dst_entry *dst; | 212 | struct dst_entry *dst; |
| 213 | struct in6_addr *final_p, final; | 213 | struct in6_addr *final_p, final; |
| 214 | int res; | ||
| 214 | 215 | ||
| 215 | memset(&fl6, 0, sizeof(fl6)); | 216 | memset(&fl6, 0, sizeof(fl6)); |
| 216 | fl6.flowi6_proto = sk->sk_protocol; | 217 | fl6.flowi6_proto = sk->sk_protocol; |
| @@ -241,12 +242,14 @@ int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) | |||
| 241 | __inet6_csk_dst_store(sk, dst, NULL, NULL); | 242 | __inet6_csk_dst_store(sk, dst, NULL, NULL); |
| 242 | } | 243 | } |
| 243 | 244 | ||
| 244 | skb_dst_set(skb, dst_clone(dst)); | 245 | rcu_read_lock(); |
| 246 | skb_dst_set_noref(skb, dst); | ||
| 245 | 247 | ||
| 246 | /* Restore final destination back after routing done */ | 248 | /* Restore final destination back after routing done */ |
| 247 | ipv6_addr_copy(&fl6.daddr, &np->daddr); | 249 | ipv6_addr_copy(&fl6.daddr, &np->daddr); |
| 248 | 250 | ||
| 249 | return ip6_xmit(sk, skb, &fl6, np->opt); | 251 | res = ip6_xmit(sk, skb, &fl6, np->opt, np->tclass); |
| 252 | rcu_read_unlock(); | ||
| 253 | return res; | ||
| 250 | } | 254 | } |
| 251 | |||
| 252 | EXPORT_SYMBOL_GPL(inet6_csk_xmit); | 255 | EXPORT_SYMBOL_GPL(inet6_csk_xmit); |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 320d91d20ad7..93718f3db79b 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
| @@ -28,10 +28,6 @@ | |||
| 28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
| 29 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
| 30 | 30 | ||
| 31 | #ifdef CONFIG_PROC_FS | ||
| 32 | #include <linux/proc_fs.h> | ||
| 33 | #endif | ||
| 34 | |||
| 35 | #include <net/ipv6.h> | 31 | #include <net/ipv6.h> |
| 36 | #include <net/ndisc.h> | 32 | #include <net/ndisc.h> |
| 37 | #include <net/addrconf.h> | 33 | #include <net/addrconf.h> |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index f3caf1b8d572..4566dbd916d3 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/proc_fs.h> | 21 | #include <linux/proc_fs.h> |
| 22 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
| 23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 24 | #include <linux/export.h> | ||
| 24 | 25 | ||
| 25 | #include <net/net_namespace.h> | 26 | #include <net/net_namespace.h> |
| 26 | #include <net/sock.h> | 27 | #include <net/sock.h> |
| @@ -322,8 +323,8 @@ static int fl6_renew(struct ip6_flowlabel *fl, unsigned long linger, unsigned lo | |||
| 322 | } | 323 | } |
| 323 | 324 | ||
| 324 | static struct ip6_flowlabel * | 325 | static struct ip6_flowlabel * |
| 325 | fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, | 326 | fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq, |
| 326 | int optlen, int *err_p) | 327 | char __user *optval, int optlen, int *err_p) |
| 327 | { | 328 | { |
| 328 | struct ip6_flowlabel *fl = NULL; | 329 | struct ip6_flowlabel *fl = NULL; |
| 329 | int olen; | 330 | int olen; |
| @@ -360,7 +361,7 @@ fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, | |||
| 360 | msg.msg_control = (void*)(fl->opt+1); | 361 | msg.msg_control = (void*)(fl->opt+1); |
| 361 | memset(&flowi6, 0, sizeof(flowi6)); | 362 | memset(&flowi6, 0, sizeof(flowi6)); |
| 362 | 363 | ||
| 363 | err = datagram_send_ctl(net, &msg, &flowi6, fl->opt, &junk, | 364 | err = datagram_send_ctl(net, sk, &msg, &flowi6, fl->opt, &junk, |
| 364 | &junk, &junk); | 365 | &junk, &junk); |
| 365 | if (err) | 366 | if (err) |
| 366 | goto done; | 367 | goto done; |
| @@ -528,7 +529,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen) | |||
| 528 | if (freq.flr_label & ~IPV6_FLOWLABEL_MASK) | 529 | if (freq.flr_label & ~IPV6_FLOWLABEL_MASK) |
| 529 | return -EINVAL; | 530 | return -EINVAL; |
| 530 | 531 | ||
| 531 | fl = fl_create(net, &freq, optval, optlen, &err); | 532 | fl = fl_create(net, sk, &freq, optval, optlen, &err); |
| 532 | if (fl == NULL) | 533 | if (fl == NULL) |
| 533 | return err; | 534 | return err; |
| 534 | sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL); | 535 | sfl1 = kmalloc(sizeof(*sfl1), GFP_KERNEL); |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 027c7ff6f1e5..a46c64eb0a66 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
| @@ -111,6 +111,14 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt | |||
| 111 | ipv6_addr_loopback(&hdr->daddr)) | 111 | ipv6_addr_loopback(&hdr->daddr)) |
| 112 | goto err; | 112 | goto err; |
| 113 | 113 | ||
| 114 | /* | ||
| 115 | * RFC4291 2.7 | ||
| 116 | * Multicast addresses must not be used as source addresses in IPv6 | ||
| 117 | * packets or appear in any Routing header. | ||
| 118 | */ | ||
| 119 | if (ipv6_addr_is_multicast(&hdr->saddr)) | ||
| 120 | goto err; | ||
| 121 | |||
| 114 | skb->transport_header = skb->network_header + sizeof(*hdr); | 122 | skb->transport_header = skb->network_header + sizeof(*hdr); |
| 115 | IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); | 123 | IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); |
| 116 | 124 | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4c882cf4e8a1..84d0bd5cac93 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -180,7 +180,7 @@ int ip6_output(struct sk_buff *skb) | |||
| 180 | */ | 180 | */ |
| 181 | 181 | ||
| 182 | int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, | 182 | int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, |
| 183 | struct ipv6_txoptions *opt) | 183 | struct ipv6_txoptions *opt, int tclass) |
| 184 | { | 184 | { |
| 185 | struct net *net = sock_net(sk); | 185 | struct net *net = sock_net(sk); |
| 186 | struct ipv6_pinfo *np = inet6_sk(sk); | 186 | struct ipv6_pinfo *np = inet6_sk(sk); |
| @@ -190,7 +190,6 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, | |||
| 190 | u8 proto = fl6->flowi6_proto; | 190 | u8 proto = fl6->flowi6_proto; |
| 191 | int seg_len = skb->len; | 191 | int seg_len = skb->len; |
| 192 | int hlimit = -1; | 192 | int hlimit = -1; |
| 193 | int tclass = 0; | ||
| 194 | u32 mtu; | 193 | u32 mtu; |
| 195 | 194 | ||
| 196 | if (opt) { | 195 | if (opt) { |
| @@ -228,10 +227,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, | |||
| 228 | /* | 227 | /* |
| 229 | * Fill in the IPv6 header | 228 | * Fill in the IPv6 header |
| 230 | */ | 229 | */ |
| 231 | if (np) { | 230 | if (np) |
| 232 | tclass = np->tclass; | ||
| 233 | hlimit = np->hop_limit; | 231 | hlimit = np->hop_limit; |
| 234 | } | ||
| 235 | if (hlimit < 0) | 232 | if (hlimit < 0) |
| 236 | hlimit = ip6_dst_hoplimit(dst); | 233 | hlimit = ip6_dst_hoplimit(dst); |
| 237 | 234 | ||
| @@ -1126,7 +1123,7 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
| 1126 | hh_len + fragheaderlen + transhdrlen + 20, | 1123 | hh_len + fragheaderlen + transhdrlen + 20, |
| 1127 | (flags & MSG_DONTWAIT), &err); | 1124 | (flags & MSG_DONTWAIT), &err); |
| 1128 | if (skb == NULL) | 1125 | if (skb == NULL) |
| 1129 | return -ENOMEM; | 1126 | return err; |
| 1130 | 1127 | ||
| 1131 | /* reserve space for Hardware header */ | 1128 | /* reserve space for Hardware header */ |
| 1132 | skb_reserve(skb, hh_len); | 1129 | skb_reserve(skb, hh_len); |
| @@ -1193,6 +1190,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1193 | struct sk_buff *skb; | 1190 | struct sk_buff *skb; |
| 1194 | unsigned int maxfraglen, fragheaderlen; | 1191 | unsigned int maxfraglen, fragheaderlen; |
| 1195 | int exthdrlen; | 1192 | int exthdrlen; |
| 1193 | int dst_exthdrlen; | ||
| 1196 | int hh_len; | 1194 | int hh_len; |
| 1197 | int mtu; | 1195 | int mtu; |
| 1198 | int copy; | 1196 | int copy; |
| @@ -1248,7 +1246,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1248 | np->cork.hop_limit = hlimit; | 1246 | np->cork.hop_limit = hlimit; |
| 1249 | np->cork.tclass = tclass; | 1247 | np->cork.tclass = tclass; |
| 1250 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? | 1248 | mtu = np->pmtudisc == IPV6_PMTUDISC_PROBE ? |
| 1251 | rt->dst.dev->mtu : dst_mtu(rt->dst.path); | 1249 | rt->dst.dev->mtu : dst_mtu(&rt->dst); |
| 1252 | if (np->frag_size < mtu) { | 1250 | if (np->frag_size < mtu) { |
| 1253 | if (np->frag_size) | 1251 | if (np->frag_size) |
| 1254 | mtu = np->frag_size; | 1252 | mtu = np->frag_size; |
| @@ -1259,16 +1257,17 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1259 | cork->length = 0; | 1257 | cork->length = 0; |
| 1260 | sk->sk_sndmsg_page = NULL; | 1258 | sk->sk_sndmsg_page = NULL; |
| 1261 | sk->sk_sndmsg_off = 0; | 1259 | sk->sk_sndmsg_off = 0; |
| 1262 | exthdrlen = rt->dst.header_len + (opt ? opt->opt_flen : 0) - | 1260 | exthdrlen = (opt ? opt->opt_flen : 0) - rt->rt6i_nfheader_len; |
| 1263 | rt->rt6i_nfheader_len; | ||
| 1264 | length += exthdrlen; | 1261 | length += exthdrlen; |
| 1265 | transhdrlen += exthdrlen; | 1262 | transhdrlen += exthdrlen; |
| 1263 | dst_exthdrlen = rt->dst.header_len; | ||
| 1266 | } else { | 1264 | } else { |
| 1267 | rt = (struct rt6_info *)cork->dst; | 1265 | rt = (struct rt6_info *)cork->dst; |
| 1268 | fl6 = &inet->cork.fl.u.ip6; | 1266 | fl6 = &inet->cork.fl.u.ip6; |
| 1269 | opt = np->cork.opt; | 1267 | opt = np->cork.opt; |
| 1270 | transhdrlen = 0; | 1268 | transhdrlen = 0; |
| 1271 | exthdrlen = 0; | 1269 | exthdrlen = 0; |
| 1270 | dst_exthdrlen = 0; | ||
| 1272 | mtu = cork->fragsize; | 1271 | mtu = cork->fragsize; |
| 1273 | } | 1272 | } |
| 1274 | 1273 | ||
| @@ -1368,6 +1367,8 @@ alloc_new_skb: | |||
| 1368 | else | 1367 | else |
| 1369 | alloclen = datalen + fragheaderlen; | 1368 | alloclen = datalen + fragheaderlen; |
| 1370 | 1369 | ||
| 1370 | alloclen += dst_exthdrlen; | ||
| 1371 | |||
| 1371 | /* | 1372 | /* |
| 1372 | * The last fragment gets additional space at tail. | 1373 | * The last fragment gets additional space at tail. |
| 1373 | * Note: we overallocate on fragments with MSG_MODE | 1374 | * Note: we overallocate on fragments with MSG_MODE |
| @@ -1419,9 +1420,9 @@ alloc_new_skb: | |||
| 1419 | /* | 1420 | /* |
| 1420 | * Find where to start putting bytes | 1421 | * Find where to start putting bytes |
| 1421 | */ | 1422 | */ |
| 1422 | data = skb_put(skb, fraglen); | 1423 | data = skb_put(skb, fraglen + dst_exthdrlen); |
| 1423 | skb_set_network_header(skb, exthdrlen); | 1424 | skb_set_network_header(skb, exthdrlen + dst_exthdrlen); |
| 1424 | data += fragheaderlen; | 1425 | data += fragheaderlen + dst_exthdrlen; |
| 1425 | skb->transport_header = (skb->network_header + | 1426 | skb->transport_header = (skb->network_header + |
| 1426 | fragheaderlen); | 1427 | fragheaderlen); |
| 1427 | if (fraggap) { | 1428 | if (fraggap) { |
| @@ -1434,6 +1435,7 @@ alloc_new_skb: | |||
| 1434 | pskb_trim_unique(skb_prev, maxfraglen); | 1435 | pskb_trim_unique(skb_prev, maxfraglen); |
| 1435 | } | 1436 | } |
| 1436 | copy = datalen - transhdrlen - fraggap; | 1437 | copy = datalen - transhdrlen - fraggap; |
| 1438 | |||
| 1437 | if (copy < 0) { | 1439 | if (copy < 0) { |
| 1438 | err = -EINVAL; | 1440 | err = -EINVAL; |
| 1439 | kfree_skb(skb); | 1441 | kfree_skb(skb); |
| @@ -1448,6 +1450,7 @@ alloc_new_skb: | |||
| 1448 | length -= datalen - fraggap; | 1450 | length -= datalen - fraggap; |
| 1449 | transhdrlen = 0; | 1451 | transhdrlen = 0; |
| 1450 | exthdrlen = 0; | 1452 | exthdrlen = 0; |
| 1453 | dst_exthdrlen = 0; | ||
| 1451 | csummode = CHECKSUM_NONE; | 1454 | csummode = CHECKSUM_NONE; |
| 1452 | 1455 | ||
| 1453 | /* | 1456 | /* |
| @@ -1480,13 +1483,13 @@ alloc_new_skb: | |||
| 1480 | if (page && (left = PAGE_SIZE - off) > 0) { | 1483 | if (page && (left = PAGE_SIZE - off) > 0) { |
| 1481 | if (copy >= left) | 1484 | if (copy >= left) |
| 1482 | copy = left; | 1485 | copy = left; |
| 1483 | if (page != frag->page) { | 1486 | if (page != skb_frag_page(frag)) { |
| 1484 | if (i == MAX_SKB_FRAGS) { | 1487 | if (i == MAX_SKB_FRAGS) { |
| 1485 | err = -EMSGSIZE; | 1488 | err = -EMSGSIZE; |
| 1486 | goto error; | 1489 | goto error; |
| 1487 | } | 1490 | } |
| 1488 | get_page(page); | ||
| 1489 | skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0); | 1491 | skb_fill_page_desc(skb, i, page, sk->sk_sndmsg_off, 0); |
| 1492 | skb_frag_ref(skb, i); | ||
| 1490 | frag = &skb_shinfo(skb)->frags[i]; | 1493 | frag = &skb_shinfo(skb)->frags[i]; |
| 1491 | } | 1494 | } |
| 1492 | } else if(i < MAX_SKB_FRAGS) { | 1495 | } else if(i < MAX_SKB_FRAGS) { |
| @@ -1506,12 +1509,14 @@ alloc_new_skb: | |||
| 1506 | err = -EMSGSIZE; | 1509 | err = -EMSGSIZE; |
| 1507 | goto error; | 1510 | goto error; |
| 1508 | } | 1511 | } |
| 1509 | if (getfrag(from, page_address(frag->page)+frag->page_offset+frag->size, offset, copy, skb->len, skb) < 0) { | 1512 | if (getfrag(from, |
| 1513 | skb_frag_address(frag) + skb_frag_size(frag), | ||
| 1514 | offset, copy, skb->len, skb) < 0) { | ||
| 1510 | err = -EFAULT; | 1515 | err = -EFAULT; |
| 1511 | goto error; | 1516 | goto error; |
| 1512 | } | 1517 | } |
| 1513 | sk->sk_sndmsg_off += copy; | 1518 | sk->sk_sndmsg_off += copy; |
| 1514 | frag->size += copy; | 1519 | skb_frag_size_add(frag, copy); |
| 1515 | skb->len += copy; | 1520 | skb->len += copy; |
| 1516 | skb->data_len += copy; | 1521 | skb->data_len += copy; |
| 1517 | skb->truesize += copy; | 1522 | skb->truesize += copy; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 0bc98886c383..4e2e9ff67ef2 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
| @@ -218,8 +218,8 @@ ip6_tnl_link(struct ip6_tnl_net *ip6n, struct ip6_tnl *t) | |||
| 218 | { | 218 | { |
| 219 | struct ip6_tnl __rcu **tp = ip6_tnl_bucket(ip6n, &t->parms); | 219 | struct ip6_tnl __rcu **tp = ip6_tnl_bucket(ip6n, &t->parms); |
| 220 | 220 | ||
| 221 | rcu_assign_pointer(t->next , rtnl_dereference(*tp)); | 221 | RCU_INIT_POINTER(t->next , rtnl_dereference(*tp)); |
| 222 | rcu_assign_pointer(*tp, t); | 222 | RCU_INIT_POINTER(*tp, t); |
| 223 | } | 223 | } |
| 224 | 224 | ||
| 225 | /** | 225 | /** |
| @@ -237,7 +237,7 @@ ip6_tnl_unlink(struct ip6_tnl_net *ip6n, struct ip6_tnl *t) | |||
| 237 | (iter = rtnl_dereference(*tp)) != NULL; | 237 | (iter = rtnl_dereference(*tp)) != NULL; |
| 238 | tp = &iter->next) { | 238 | tp = &iter->next) { |
| 239 | if (t == iter) { | 239 | if (t == iter) { |
| 240 | rcu_assign_pointer(*tp, t->next); | 240 | RCU_INIT_POINTER(*tp, t->next); |
| 241 | break; | 241 | break; |
| 242 | } | 242 | } |
| 243 | } | 243 | } |
| @@ -289,6 +289,8 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p) | |||
| 289 | if ((err = register_netdevice(dev)) < 0) | 289 | if ((err = register_netdevice(dev)) < 0) |
| 290 | goto failed_free; | 290 | goto failed_free; |
| 291 | 291 | ||
| 292 | strcpy(t->parms.name, dev->name); | ||
| 293 | |||
| 292 | dev_hold(dev); | 294 | dev_hold(dev); |
| 293 | ip6_tnl_link(ip6n, t); | 295 | ip6_tnl_link(ip6n, t); |
| 294 | return t; | 296 | return t; |
| @@ -350,7 +352,7 @@ ip6_tnl_dev_uninit(struct net_device *dev) | |||
| 350 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | 352 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); |
| 351 | 353 | ||
| 352 | if (dev == ip6n->fb_tnl_dev) | 354 | if (dev == ip6n->fb_tnl_dev) |
| 353 | rcu_assign_pointer(ip6n->tnls_wc[0], NULL); | 355 | RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL); |
| 354 | else | 356 | else |
| 355 | ip6_tnl_unlink(ip6n, t); | 357 | ip6_tnl_unlink(ip6n, t); |
| 356 | ip6_tnl_dst_reset(t); | 358 | ip6_tnl_dst_reset(t); |
| @@ -889,7 +891,7 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
| 889 | struct net_device_stats *stats = &t->dev->stats; | 891 | struct net_device_stats *stats = &t->dev->stats; |
| 890 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 892 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
| 891 | struct ipv6_tel_txoption opt; | 893 | struct ipv6_tel_txoption opt; |
| 892 | struct dst_entry *dst; | 894 | struct dst_entry *dst = NULL, *ndst = NULL; |
| 893 | struct net_device *tdev; | 895 | struct net_device *tdev; |
| 894 | int mtu; | 896 | int mtu; |
| 895 | unsigned int max_headroom = sizeof(struct ipv6hdr); | 897 | unsigned int max_headroom = sizeof(struct ipv6hdr); |
| @@ -897,19 +899,20 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
| 897 | int err = -1; | 899 | int err = -1; |
| 898 | int pkt_len; | 900 | int pkt_len; |
| 899 | 901 | ||
| 900 | if ((dst = ip6_tnl_dst_check(t)) != NULL) | 902 | if (!fl6->flowi6_mark) |
| 901 | dst_hold(dst); | 903 | dst = ip6_tnl_dst_check(t); |
| 902 | else { | 904 | if (!dst) { |
| 903 | dst = ip6_route_output(net, NULL, fl6); | 905 | ndst = ip6_route_output(net, NULL, fl6); |
| 904 | 906 | ||
| 905 | if (dst->error) | 907 | if (ndst->error) |
| 906 | goto tx_err_link_failure; | 908 | goto tx_err_link_failure; |
| 907 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), NULL, 0); | 909 | ndst = xfrm_lookup(net, ndst, flowi6_to_flowi(fl6), NULL, 0); |
| 908 | if (IS_ERR(dst)) { | 910 | if (IS_ERR(ndst)) { |
| 909 | err = PTR_ERR(dst); | 911 | err = PTR_ERR(ndst); |
| 910 | dst = NULL; | 912 | ndst = NULL; |
| 911 | goto tx_err_link_failure; | 913 | goto tx_err_link_failure; |
| 912 | } | 914 | } |
| 915 | dst = ndst; | ||
| 913 | } | 916 | } |
| 914 | 917 | ||
| 915 | tdev = dst->dev; | 918 | tdev = dst->dev; |
| @@ -955,8 +958,12 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
| 955 | skb = new_skb; | 958 | skb = new_skb; |
| 956 | } | 959 | } |
| 957 | skb_dst_drop(skb); | 960 | skb_dst_drop(skb); |
| 958 | skb_dst_set(skb, dst_clone(dst)); | 961 | if (fl6->flowi6_mark) { |
| 959 | 962 | skb_dst_set(skb, dst); | |
| 963 | ndst = NULL; | ||
| 964 | } else { | ||
| 965 | skb_dst_set_noref(skb, dst); | ||
| 966 | } | ||
| 960 | skb->transport_header = skb->network_header; | 967 | skb->transport_header = skb->network_header; |
| 961 | 968 | ||
| 962 | proto = fl6->flowi6_proto; | 969 | proto = fl6->flowi6_proto; |
| @@ -987,13 +994,14 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
| 987 | stats->tx_errors++; | 994 | stats->tx_errors++; |
| 988 | stats->tx_aborted_errors++; | 995 | stats->tx_aborted_errors++; |
| 989 | } | 996 | } |
| 990 | ip6_tnl_dst_store(t, dst); | 997 | if (ndst) |
| 998 | ip6_tnl_dst_store(t, ndst); | ||
| 991 | return 0; | 999 | return 0; |
| 992 | tx_err_link_failure: | 1000 | tx_err_link_failure: |
| 993 | stats->tx_carrier_errors++; | 1001 | stats->tx_carrier_errors++; |
| 994 | dst_link_failure(skb); | 1002 | dst_link_failure(skb); |
| 995 | tx_err_dst_release: | 1003 | tx_err_dst_release: |
| 996 | dst_release(dst); | 1004 | dst_release(ndst); |
| 997 | return err; | 1005 | return err; |
| 998 | } | 1006 | } |
| 999 | 1007 | ||
| @@ -1020,9 +1028,11 @@ ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1020 | 1028 | ||
| 1021 | dsfield = ipv4_get_dsfield(iph); | 1029 | dsfield = ipv4_get_dsfield(iph); |
| 1022 | 1030 | ||
| 1023 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) | 1031 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) |
| 1024 | fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT) | 1032 | fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT) |
| 1025 | & IPV6_TCLASS_MASK; | 1033 | & IPV6_TCLASS_MASK; |
| 1034 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) | ||
| 1035 | fl6.flowi6_mark = skb->mark; | ||
| 1026 | 1036 | ||
| 1027 | err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); | 1037 | err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); |
| 1028 | if (err != 0) { | 1038 | if (err != 0) { |
| @@ -1069,10 +1079,12 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1069 | fl6.flowi6_proto = IPPROTO_IPV6; | 1079 | fl6.flowi6_proto = IPPROTO_IPV6; |
| 1070 | 1080 | ||
| 1071 | dsfield = ipv6_get_dsfield(ipv6h); | 1081 | dsfield = ipv6_get_dsfield(ipv6h); |
| 1072 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS)) | 1082 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) |
| 1073 | fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK); | 1083 | fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK); |
| 1074 | if ((t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL)) | 1084 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) |
| 1075 | fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK); | 1085 | fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK); |
| 1086 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) | ||
| 1087 | fl6.flowi6_mark = skb->mark; | ||
| 1076 | 1088 | ||
| 1077 | err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); | 1089 | err = ip6_tnl_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); |
| 1078 | if (err != 0) { | 1090 | if (err != 0) { |
| @@ -1397,7 +1409,6 @@ ip6_tnl_dev_init_gen(struct net_device *dev) | |||
| 1397 | struct ip6_tnl *t = netdev_priv(dev); | 1409 | struct ip6_tnl *t = netdev_priv(dev); |
| 1398 | 1410 | ||
| 1399 | t->dev = dev; | 1411 | t->dev = dev; |
| 1400 | strcpy(t->parms.name, dev->name); | ||
| 1401 | dev->tstats = alloc_percpu(struct pcpu_tstats); | 1412 | dev->tstats = alloc_percpu(struct pcpu_tstats); |
| 1402 | if (!dev->tstats) | 1413 | if (!dev->tstats) |
| 1403 | return -ENOMEM; | 1414 | return -ENOMEM; |
| @@ -1439,7 +1450,7 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev) | |||
| 1439 | 1450 | ||
| 1440 | t->parms.proto = IPPROTO_IPV6; | 1451 | t->parms.proto = IPPROTO_IPV6; |
| 1441 | dev_hold(dev); | 1452 | dev_hold(dev); |
| 1442 | rcu_assign_pointer(ip6n->tnls_wc[0], t); | 1453 | RCU_INIT_POINTER(ip6n->tnls_wc[0], t); |
| 1443 | return 0; | 1454 | return 0; |
| 1444 | } | 1455 | } |
| 1445 | 1456 | ||
| @@ -1477,6 +1488,7 @@ static void __net_exit ip6_tnl_destroy_tunnels(struct ip6_tnl_net *ip6n) | |||
| 1477 | static int __net_init ip6_tnl_init_net(struct net *net) | 1488 | static int __net_init ip6_tnl_init_net(struct net *net) |
| 1478 | { | 1489 | { |
| 1479 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | 1490 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); |
| 1491 | struct ip6_tnl *t = NULL; | ||
| 1480 | int err; | 1492 | int err; |
| 1481 | 1493 | ||
| 1482 | ip6n->tnls[0] = ip6n->tnls_wc; | 1494 | ip6n->tnls[0] = ip6n->tnls_wc; |
| @@ -1497,6 +1509,10 @@ static int __net_init ip6_tnl_init_net(struct net *net) | |||
| 1497 | err = register_netdev(ip6n->fb_tnl_dev); | 1509 | err = register_netdev(ip6n->fb_tnl_dev); |
| 1498 | if (err < 0) | 1510 | if (err < 0) |
| 1499 | goto err_register; | 1511 | goto err_register; |
| 1512 | |||
| 1513 | t = netdev_priv(ip6n->fb_tnl_dev); | ||
| 1514 | |||
| 1515 | strcpy(t->parms.name, ip6n->fb_tnl_dev->name); | ||
| 1500 | return 0; | 1516 | return 0; |
| 1501 | 1517 | ||
| 1502 | err_register: | 1518 | err_register: |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 705c82886281..449a9185b8f2 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
| @@ -51,6 +51,7 @@ | |||
| 51 | #include <linux/pim.h> | 51 | #include <linux/pim.h> |
| 52 | #include <net/addrconf.h> | 52 | #include <net/addrconf.h> |
| 53 | #include <linux/netfilter_ipv6.h> | 53 | #include <linux/netfilter_ipv6.h> |
| 54 | #include <linux/export.h> | ||
| 54 | #include <net/ip6_checksum.h> | 55 | #include <net/ip6_checksum.h> |
| 55 | 56 | ||
| 56 | struct mr6_table { | 57 | struct mr6_table { |
| @@ -696,8 +697,10 @@ static netdev_tx_t reg_vif_xmit(struct sk_buff *skb, | |||
| 696 | int err; | 697 | int err; |
| 697 | 698 | ||
| 698 | err = ip6mr_fib_lookup(net, &fl6, &mrt); | 699 | err = ip6mr_fib_lookup(net, &fl6, &mrt); |
| 699 | if (err < 0) | 700 | if (err < 0) { |
| 701 | kfree_skb(skb); | ||
| 700 | return err; | 702 | return err; |
| 703 | } | ||
| 701 | 704 | ||
| 702 | read_lock(&mrt_lock); | 705 | read_lock(&mrt_lock); |
| 703 | dev->stats.tx_bytes += skb->len; | 706 | dev->stats.tx_bytes += skb->len; |
| @@ -2052,8 +2055,10 @@ int ip6_mr_input(struct sk_buff *skb) | |||
| 2052 | int err; | 2055 | int err; |
| 2053 | 2056 | ||
| 2054 | err = ip6mr_fib_lookup(net, &fl6, &mrt); | 2057 | err = ip6mr_fib_lookup(net, &fl6, &mrt); |
| 2055 | if (err < 0) | 2058 | if (err < 0) { |
| 2059 | kfree_skb(skb); | ||
| 2056 | return err; | 2060 | return err; |
| 2061 | } | ||
| 2057 | 2062 | ||
| 2058 | read_lock(&mrt_lock); | 2063 | read_lock(&mrt_lock); |
| 2059 | cache = ip6mr_cache_find(mrt, | 2064 | cache = ip6mr_cache_find(mrt, |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 147ede38ab48..c99e3ee9781f 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
| @@ -343,7 +343,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
| 343 | break; | 343 | break; |
| 344 | 344 | ||
| 345 | case IPV6_TRANSPARENT: | 345 | case IPV6_TRANSPARENT: |
| 346 | if (!capable(CAP_NET_ADMIN)) { | 346 | if (valbool && !capable(CAP_NET_ADMIN) && !capable(CAP_NET_RAW)) { |
| 347 | retv = -EPERM; | 347 | retv = -EPERM; |
| 348 | break; | 348 | break; |
| 349 | } | 349 | } |
| @@ -475,7 +475,7 @@ sticky_done: | |||
| 475 | msg.msg_controllen = optlen; | 475 | msg.msg_controllen = optlen; |
| 476 | msg.msg_control = (void*)(opt+1); | 476 | msg.msg_control = (void*)(opt+1); |
| 477 | 477 | ||
| 478 | retv = datagram_send_ctl(net, &msg, &fl6, opt, &junk, &junk, | 478 | retv = datagram_send_ctl(net, sk, &msg, &fl6, opt, &junk, &junk, |
| 479 | &junk); | 479 | &junk); |
| 480 | if (retv) | 480 | if (retv) |
| 481 | goto done; | 481 | goto done; |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 3e6ebcdb4779..ee7839f4d6e3 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
| @@ -1059,7 +1059,7 @@ static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs, | |||
| 1059 | break; | 1059 | break; |
| 1060 | for (i=0; i<nsrcs; i++) { | 1060 | for (i=0; i<nsrcs; i++) { |
| 1061 | /* skip inactive filters */ | 1061 | /* skip inactive filters */ |
| 1062 | if (pmc->mca_sfcount[MCAST_INCLUDE] || | 1062 | if (psf->sf_count[MCAST_INCLUDE] || |
| 1063 | pmc->mca_sfcount[MCAST_EXCLUDE] != | 1063 | pmc->mca_sfcount[MCAST_EXCLUDE] != |
| 1064 | psf->sf_count[MCAST_EXCLUDE]) | 1064 | psf->sf_count[MCAST_EXCLUDE]) |
| 1065 | continue; | 1065 | continue; |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 9da6e02eaaeb..44e5b7f2a6c1 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
| @@ -370,17 +370,14 @@ static int ndisc_constructor(struct neighbour *neigh) | |||
| 370 | struct neigh_parms *parms; | 370 | struct neigh_parms *parms; |
| 371 | int is_multicast = ipv6_addr_is_multicast(addr); | 371 | int is_multicast = ipv6_addr_is_multicast(addr); |
| 372 | 372 | ||
| 373 | rcu_read_lock(); | ||
| 374 | in6_dev = in6_dev_get(dev); | 373 | in6_dev = in6_dev_get(dev); |
| 375 | if (in6_dev == NULL) { | 374 | if (in6_dev == NULL) { |
| 376 | rcu_read_unlock(); | ||
| 377 | return -EINVAL; | 375 | return -EINVAL; |
| 378 | } | 376 | } |
| 379 | 377 | ||
| 380 | parms = in6_dev->nd_parms; | 378 | parms = in6_dev->nd_parms; |
| 381 | __neigh_parms_put(neigh->parms); | 379 | __neigh_parms_put(neigh->parms); |
| 382 | neigh->parms = neigh_parms_clone(parms); | 380 | neigh->parms = neigh_parms_clone(parms); |
| 383 | rcu_read_unlock(); | ||
| 384 | 381 | ||
| 385 | neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST; | 382 | neigh->type = is_multicast ? RTN_MULTICAST : RTN_UNICAST; |
| 386 | if (!dev->header_ops) { | 383 | if (!dev->header_ops) { |
| @@ -533,7 +530,8 @@ void ndisc_send_skb(struct sk_buff *skb, | |||
| 533 | 530 | ||
| 534 | skb_dst_set(skb, dst); | 531 | skb_dst_set(skb, dst); |
| 535 | 532 | ||
| 536 | idev = in6_dev_get(dst->dev); | 533 | rcu_read_lock(); |
| 534 | idev = __in6_dev_get(dst->dev); | ||
| 537 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); | 535 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); |
| 538 | 536 | ||
| 539 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, | 537 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, skb, NULL, dst->dev, |
| @@ -543,8 +541,7 @@ void ndisc_send_skb(struct sk_buff *skb, | |||
| 543 | ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); | 541 | ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); |
| 544 | } | 542 | } |
| 545 | 543 | ||
| 546 | if (likely(idev != NULL)) | 544 | rcu_read_unlock(); |
| 547 | in6_dev_put(idev); | ||
| 548 | } | 545 | } |
| 549 | 546 | ||
| 550 | EXPORT_SYMBOL(ndisc_send_skb); | 547 | EXPORT_SYMBOL(ndisc_send_skb); |
| @@ -1039,7 +1036,7 @@ static void ndisc_recv_rs(struct sk_buff *skb) | |||
| 1039 | if (skb->len < sizeof(*rs_msg)) | 1036 | if (skb->len < sizeof(*rs_msg)) |
| 1040 | return; | 1037 | return; |
| 1041 | 1038 | ||
| 1042 | idev = in6_dev_get(skb->dev); | 1039 | idev = __in6_dev_get(skb->dev); |
| 1043 | if (!idev) { | 1040 | if (!idev) { |
| 1044 | if (net_ratelimit()) | 1041 | if (net_ratelimit()) |
| 1045 | ND_PRINTK1("ICMP6 RS: can't find in6 device\n"); | 1042 | ND_PRINTK1("ICMP6 RS: can't find in6 device\n"); |
| @@ -1080,7 +1077,7 @@ static void ndisc_recv_rs(struct sk_buff *skb) | |||
| 1080 | neigh_release(neigh); | 1077 | neigh_release(neigh); |
| 1081 | } | 1078 | } |
| 1082 | out: | 1079 | out: |
| 1083 | in6_dev_put(idev); | 1080 | return; |
| 1084 | } | 1081 | } |
| 1085 | 1082 | ||
| 1086 | static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) | 1083 | static void ndisc_ra_useropt(struct sk_buff *ra, struct nd_opt_hdr *opt) |
| @@ -1179,7 +1176,7 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
| 1179 | * set the RA_RECV flag in the interface | 1176 | * set the RA_RECV flag in the interface |
| 1180 | */ | 1177 | */ |
| 1181 | 1178 | ||
| 1182 | in6_dev = in6_dev_get(skb->dev); | 1179 | in6_dev = __in6_dev_get(skb->dev); |
| 1183 | if (in6_dev == NULL) { | 1180 | if (in6_dev == NULL) { |
| 1184 | ND_PRINTK0(KERN_ERR | 1181 | ND_PRINTK0(KERN_ERR |
| 1185 | "ICMPv6 RA: can't find inet6 device for %s.\n", | 1182 | "ICMPv6 RA: can't find inet6 device for %s.\n", |
| @@ -1188,7 +1185,6 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
| 1188 | } | 1185 | } |
| 1189 | 1186 | ||
| 1190 | if (!ndisc_parse_options(opt, optlen, &ndopts)) { | 1187 | if (!ndisc_parse_options(opt, optlen, &ndopts)) { |
| 1191 | in6_dev_put(in6_dev); | ||
| 1192 | ND_PRINTK2(KERN_WARNING | 1188 | ND_PRINTK2(KERN_WARNING |
| 1193 | "ICMP6 RA: invalid ND options\n"); | 1189 | "ICMP6 RA: invalid ND options\n"); |
| 1194 | return; | 1190 | return; |
| @@ -1225,6 +1221,9 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
| 1225 | if (!in6_dev->cnf.accept_ra_defrtr) | 1221 | if (!in6_dev->cnf.accept_ra_defrtr) |
| 1226 | goto skip_defrtr; | 1222 | goto skip_defrtr; |
| 1227 | 1223 | ||
| 1224 | if (ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, NULL, 0)) | ||
| 1225 | goto skip_defrtr; | ||
| 1226 | |||
| 1228 | lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); | 1227 | lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); |
| 1229 | 1228 | ||
| 1230 | #ifdef CONFIG_IPV6_ROUTER_PREF | 1229 | #ifdef CONFIG_IPV6_ROUTER_PREF |
| @@ -1255,7 +1254,6 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
| 1255 | ND_PRINTK0(KERN_ERR | 1254 | ND_PRINTK0(KERN_ERR |
| 1256 | "ICMPv6 RA: %s() failed to add default route.\n", | 1255 | "ICMPv6 RA: %s() failed to add default route.\n", |
| 1257 | __func__); | 1256 | __func__); |
| 1258 | in6_dev_put(in6_dev); | ||
| 1259 | return; | 1257 | return; |
| 1260 | } | 1258 | } |
| 1261 | 1259 | ||
| @@ -1265,7 +1263,6 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
| 1265 | "ICMPv6 RA: %s() got default router without neighbour.\n", | 1263 | "ICMPv6 RA: %s() got default router without neighbour.\n", |
| 1266 | __func__); | 1264 | __func__); |
| 1267 | dst_release(&rt->dst); | 1265 | dst_release(&rt->dst); |
| 1268 | in6_dev_put(in6_dev); | ||
| 1269 | return; | 1266 | return; |
| 1270 | } | 1267 | } |
| 1271 | neigh->flags |= NTF_ROUTER; | 1268 | neigh->flags |= NTF_ROUTER; |
| @@ -1349,6 +1346,9 @@ skip_linkparms: | |||
| 1349 | goto out; | 1346 | goto out; |
| 1350 | 1347 | ||
| 1351 | #ifdef CONFIG_IPV6_ROUTE_INFO | 1348 | #ifdef CONFIG_IPV6_ROUTE_INFO |
| 1349 | if (ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, NULL, 0)) | ||
| 1350 | goto skip_routeinfo; | ||
| 1351 | |||
| 1352 | if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) { | 1352 | if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) { |
| 1353 | struct nd_opt_hdr *p; | 1353 | struct nd_opt_hdr *p; |
| 1354 | for (p = ndopts.nd_opts_ri; | 1354 | for (p = ndopts.nd_opts_ri; |
| @@ -1366,6 +1366,8 @@ skip_linkparms: | |||
| 1366 | &ipv6_hdr(skb)->saddr); | 1366 | &ipv6_hdr(skb)->saddr); |
| 1367 | } | 1367 | } |
| 1368 | } | 1368 | } |
| 1369 | |||
| 1370 | skip_routeinfo: | ||
| 1369 | #endif | 1371 | #endif |
| 1370 | 1372 | ||
| 1371 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | 1373 | #ifdef CONFIG_IPV6_NDISC_NODETYPE |
| @@ -1422,7 +1424,6 @@ out: | |||
| 1422 | dst_release(&rt->dst); | 1424 | dst_release(&rt->dst); |
| 1423 | else if (neigh) | 1425 | else if (neigh) |
| 1424 | neigh_release(neigh); | 1426 | neigh_release(neigh); |
| 1425 | in6_dev_put(in6_dev); | ||
| 1426 | } | 1427 | } |
| 1427 | 1428 | ||
| 1428 | static void ndisc_redirect_rcv(struct sk_buff *skb) | 1429 | static void ndisc_redirect_rcv(struct sk_buff *skb) |
| @@ -1481,13 +1482,11 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
| 1481 | return; | 1482 | return; |
| 1482 | } | 1483 | } |
| 1483 | 1484 | ||
| 1484 | in6_dev = in6_dev_get(skb->dev); | 1485 | in6_dev = __in6_dev_get(skb->dev); |
| 1485 | if (!in6_dev) | 1486 | if (!in6_dev) |
| 1486 | return; | 1487 | return; |
| 1487 | if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects) { | 1488 | if (in6_dev->cnf.forwarding || !in6_dev->cnf.accept_redirects) |
| 1488 | in6_dev_put(in6_dev); | ||
| 1489 | return; | 1489 | return; |
| 1490 | } | ||
| 1491 | 1490 | ||
| 1492 | /* RFC2461 8.1: | 1491 | /* RFC2461 8.1: |
| 1493 | * The IP source address of the Redirect MUST be the same as the current | 1492 | * The IP source address of the Redirect MUST be the same as the current |
| @@ -1497,7 +1496,6 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
| 1497 | if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) { | 1496 | if (!ndisc_parse_options((u8*)(dest + 1), optlen, &ndopts)) { |
| 1498 | ND_PRINTK2(KERN_WARNING | 1497 | ND_PRINTK2(KERN_WARNING |
| 1499 | "ICMPv6 Redirect: invalid ND options\n"); | 1498 | "ICMPv6 Redirect: invalid ND options\n"); |
| 1500 | in6_dev_put(in6_dev); | ||
| 1501 | return; | 1499 | return; |
| 1502 | } | 1500 | } |
| 1503 | if (ndopts.nd_opts_tgt_lladdr) { | 1501 | if (ndopts.nd_opts_tgt_lladdr) { |
| @@ -1506,7 +1504,6 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
| 1506 | if (!lladdr) { | 1504 | if (!lladdr) { |
| 1507 | ND_PRINTK2(KERN_WARNING | 1505 | ND_PRINTK2(KERN_WARNING |
| 1508 | "ICMPv6 Redirect: invalid link-layer address length\n"); | 1506 | "ICMPv6 Redirect: invalid link-layer address length\n"); |
| 1509 | in6_dev_put(in6_dev); | ||
| 1510 | return; | 1507 | return; |
| 1511 | } | 1508 | } |
| 1512 | } | 1509 | } |
| @@ -1518,7 +1515,6 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
| 1518 | on_link); | 1515 | on_link); |
| 1519 | neigh_release(neigh); | 1516 | neigh_release(neigh); |
| 1520 | } | 1517 | } |
| 1521 | in6_dev_put(in6_dev); | ||
| 1522 | } | 1518 | } |
| 1523 | 1519 | ||
| 1524 | void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | 1520 | void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, |
| @@ -1651,7 +1647,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
| 1651 | csum_partial(icmph, len, 0)); | 1647 | csum_partial(icmph, len, 0)); |
| 1652 | 1648 | ||
| 1653 | skb_dst_set(buff, dst); | 1649 | skb_dst_set(buff, dst); |
| 1654 | idev = in6_dev_get(dst->dev); | 1650 | rcu_read_lock(); |
| 1651 | idev = __in6_dev_get(dst->dev); | ||
| 1655 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); | 1652 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len); |
| 1656 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev, | 1653 | err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, buff, NULL, dst->dev, |
| 1657 | dst_output); | 1654 | dst_output); |
| @@ -1660,8 +1657,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
| 1660 | ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); | 1657 | ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); |
| 1661 | } | 1658 | } |
| 1662 | 1659 | ||
| 1663 | if (likely(idev != NULL)) | 1660 | rcu_read_unlock(); |
| 1664 | in6_dev_put(idev); | ||
| 1665 | return; | 1661 | return; |
| 1666 | 1662 | ||
| 1667 | release: | 1663 | release: |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 30fcee465448..db31561cc8df 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | #include <linux/ipv6.h> | 3 | #include <linux/ipv6.h> |
| 4 | #include <linux/netfilter.h> | 4 | #include <linux/netfilter.h> |
| 5 | #include <linux/netfilter_ipv6.h> | 5 | #include <linux/netfilter_ipv6.h> |
| 6 | #include <linux/export.h> | ||
| 6 | #include <net/dst.h> | 7 | #include <net/dst.h> |
| 7 | #include <net/ipv6.h> | 8 | #include <net/ipv6.h> |
| 8 | #include <net/ip6_route.h> | 9 | #include <net/ip6_route.h> |
| @@ -100,9 +101,16 @@ static int nf_ip6_route(struct net *net, struct dst_entry **dst, | |||
| 100 | .pinet6 = (struct ipv6_pinfo *) &fake_pinfo, | 101 | .pinet6 = (struct ipv6_pinfo *) &fake_pinfo, |
| 101 | }; | 102 | }; |
| 102 | const void *sk = strict ? &fake_sk : NULL; | 103 | const void *sk = strict ? &fake_sk : NULL; |
| 103 | 104 | struct dst_entry *result; | |
| 104 | *dst = ip6_route_output(net, sk, &fl->u.ip6); | 105 | int err; |
| 105 | return (*dst)->error; | 106 | |
| 107 | result = ip6_route_output(net, sk, &fl->u.ip6); | ||
| 108 | err = result->error; | ||
| 109 | if (err) | ||
| 110 | dst_release(result); | ||
| 111 | else | ||
| 112 | *dst = result; | ||
| 113 | return err; | ||
| 106 | } | 114 | } |
| 107 | 115 | ||
| 108 | __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, | 116 | __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, |
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c index 249394863284..e63c3972a739 100644 --- a/net/ipv6/netfilter/ip6_queue.c +++ b/net/ipv6/netfilter/ip6_queue.c | |||
| @@ -218,6 +218,7 @@ ipq_build_packet_message(struct nf_queue_entry *entry, int *errp) | |||
| 218 | return skb; | 218 | return skb; |
| 219 | 219 | ||
| 220 | nlmsg_failure: | 220 | nlmsg_failure: |
| 221 | kfree_skb(skb); | ||
| 221 | *errp = -EINVAL; | 222 | *errp = -EINVAL; |
| 222 | printk(KERN_ERR "ip6_queue: error creating packet message\n"); | 223 | printk(KERN_ERR "ip6_queue: error creating packet message\n"); |
| 223 | return NULL; | 224 | return NULL; |
| @@ -313,7 +314,7 @@ ipq_set_verdict(struct ipq_verdict_msg *vmsg, unsigned int len) | |||
| 313 | { | 314 | { |
| 314 | struct nf_queue_entry *entry; | 315 | struct nf_queue_entry *entry; |
| 315 | 316 | ||
| 316 | if (vmsg->value > NF_MAX_VERDICT) | 317 | if (vmsg->value > NF_MAX_VERDICT || vmsg->value == NF_STOLEN) |
| 317 | return -EINVAL; | 318 | return -EINVAL; |
| 318 | 319 | ||
| 319 | entry = ipq_find_dequeue_entry(vmsg->id); | 320 | entry = ipq_find_dequeue_entry(vmsg->id); |
| @@ -358,12 +359,9 @@ ipq_receive_peer(struct ipq_peer_msg *pmsg, | |||
| 358 | break; | 359 | break; |
| 359 | 360 | ||
| 360 | case IPQM_VERDICT: | 361 | case IPQM_VERDICT: |
| 361 | if (pmsg->msg.verdict.value > NF_MAX_VERDICT) | 362 | status = ipq_set_verdict(&pmsg->msg.verdict, |
| 362 | status = -EINVAL; | 363 | len - sizeof(*pmsg)); |
| 363 | else | 364 | break; |
| 364 | status = ipq_set_verdict(&pmsg->msg.verdict, | ||
| 365 | len - sizeof(*pmsg)); | ||
| 366 | break; | ||
| 367 | default: | 365 | default: |
| 368 | status = -EINVAL; | 366 | status = -EINVAL; |
| 369 | } | 367 | } |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 085727263812..38f00b0298d3 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
| @@ -182,7 +182,6 @@ fq_find(__be32 id, u32 user, struct in6_addr *src, struct in6_addr *dst) | |||
| 182 | return container_of(q, struct nf_ct_frag6_queue, q); | 182 | return container_of(q, struct nf_ct_frag6_queue, q); |
| 183 | 183 | ||
| 184 | oom: | 184 | oom: |
| 185 | pr_debug("Can't alloc new queue\n"); | ||
| 186 | return NULL; | 185 | return NULL; |
| 187 | } | 186 | } |
| 188 | 187 | ||
| @@ -370,16 +369,16 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
| 370 | struct sk_buff *clone; | 369 | struct sk_buff *clone; |
| 371 | int i, plen = 0; | 370 | int i, plen = 0; |
| 372 | 371 | ||
| 373 | if ((clone = alloc_skb(0, GFP_ATOMIC)) == NULL) { | 372 | clone = alloc_skb(0, GFP_ATOMIC); |
| 374 | pr_debug("Can't alloc skb\n"); | 373 | if (clone == NULL) |
| 375 | goto out_oom; | 374 | goto out_oom; |
| 376 | } | 375 | |
| 377 | clone->next = head->next; | 376 | clone->next = head->next; |
| 378 | head->next = clone; | 377 | head->next = clone; |
| 379 | skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list; | 378 | skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list; |
| 380 | skb_frag_list_init(head); | 379 | skb_frag_list_init(head); |
| 381 | for (i=0; i<skb_shinfo(head)->nr_frags; i++) | 380 | for (i = 0; i < skb_shinfo(head)->nr_frags; i++) |
| 382 | plen += skb_shinfo(head)->frags[i].size; | 381 | plen += skb_frag_size(&skb_shinfo(head)->frags[i]); |
| 383 | clone->len = clone->data_len = head->data_len - plen; | 382 | clone->len = clone->data_len = head->data_len - plen; |
| 384 | head->data_len -= clone->len; | 383 | head->data_len -= clone->len; |
| 385 | head->len -= clone->len; | 384 | head->len -= clone->len; |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 18ff5df7ec02..1008ce94bc33 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/proc_fs.h> | 21 | #include <linux/proc_fs.h> |
| 22 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
| 23 | #include <linux/stddef.h> | 23 | #include <linux/stddef.h> |
| 24 | #include <linux/export.h> | ||
| 24 | #include <net/net_namespace.h> | 25 | #include <net/net_namespace.h> |
| 25 | #include <net/ip.h> | 26 | #include <net/ip.h> |
| 26 | #include <net/sock.h> | 27 | #include <net/sock.h> |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 6a79f3081bdb..331af3b882ac 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
| @@ -61,6 +61,7 @@ | |||
| 61 | 61 | ||
| 62 | #include <linux/proc_fs.h> | 62 | #include <linux/proc_fs.h> |
| 63 | #include <linux/seq_file.h> | 63 | #include <linux/seq_file.h> |
| 64 | #include <linux/export.h> | ||
| 64 | 65 | ||
| 65 | static struct raw_hashinfo raw_v6_hashinfo = { | 66 | static struct raw_hashinfo raw_v6_hashinfo = { |
| 66 | .lock = __RW_LOCK_UNLOCKED(raw_v6_hashinfo.lock), | 67 | .lock = __RW_LOCK_UNLOCKED(raw_v6_hashinfo.lock), |
| @@ -130,14 +131,14 @@ static mh_filter_t __rcu *mh_filter __read_mostly; | |||
| 130 | 131 | ||
| 131 | int rawv6_mh_filter_register(mh_filter_t filter) | 132 | int rawv6_mh_filter_register(mh_filter_t filter) |
| 132 | { | 133 | { |
| 133 | rcu_assign_pointer(mh_filter, filter); | 134 | RCU_INIT_POINTER(mh_filter, filter); |
| 134 | return 0; | 135 | return 0; |
| 135 | } | 136 | } |
| 136 | EXPORT_SYMBOL(rawv6_mh_filter_register); | 137 | EXPORT_SYMBOL(rawv6_mh_filter_register); |
| 137 | 138 | ||
| 138 | int rawv6_mh_filter_unregister(mh_filter_t filter) | 139 | int rawv6_mh_filter_unregister(mh_filter_t filter) |
| 139 | { | 140 | { |
| 140 | rcu_assign_pointer(mh_filter, NULL); | 141 | RCU_INIT_POINTER(mh_filter, NULL); |
| 141 | synchronize_rcu(); | 142 | synchronize_rcu(); |
| 142 | return 0; | 143 | return 0; |
| 143 | } | 144 | } |
| @@ -372,9 +373,9 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, | |||
| 372 | read_unlock(&raw_v6_hashinfo.lock); | 373 | read_unlock(&raw_v6_hashinfo.lock); |
| 373 | } | 374 | } |
| 374 | 375 | ||
| 375 | static inline int rawv6_rcv_skb(struct sock * sk, struct sk_buff * skb) | 376 | static inline int rawv6_rcv_skb(struct sock *sk, struct sk_buff *skb) |
| 376 | { | 377 | { |
| 377 | if ((raw6_sk(sk)->checksum || rcu_dereference_raw(sk->sk_filter)) && | 378 | if ((raw6_sk(sk)->checksum || rcu_access_pointer(sk->sk_filter)) && |
| 378 | skb_checksum_complete(skb)) { | 379 | skb_checksum_complete(skb)) { |
| 379 | atomic_inc(&sk->sk_drops); | 380 | atomic_inc(&sk->sk_drops); |
| 380 | kfree_skb(skb); | 381 | kfree_skb(skb); |
| @@ -542,8 +543,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, | |||
| 542 | goto out; | 543 | goto out; |
| 543 | 544 | ||
| 544 | offset = rp->offset; | 545 | offset = rp->offset; |
| 545 | total_len = inet_sk(sk)->cork.base.length - (skb_network_header(skb) - | 546 | total_len = inet_sk(sk)->cork.base.length; |
| 546 | skb->data); | ||
| 547 | if (offset >= total_len - 1) { | 547 | if (offset >= total_len - 1) { |
| 548 | err = -EINVAL; | 548 | err = -EINVAL; |
| 549 | ip6_flush_pending_frames(sk); | 549 | ip6_flush_pending_frames(sk); |
| @@ -817,8 +817,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 817 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 817 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
| 818 | opt->tot_len = sizeof(struct ipv6_txoptions); | 818 | opt->tot_len = sizeof(struct ipv6_txoptions); |
| 819 | 819 | ||
| 820 | err = datagram_send_ctl(sock_net(sk), msg, &fl6, opt, &hlimit, | 820 | err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, |
| 821 | &tclass, &dontfrag); | 821 | &hlimit, &tclass, &dontfrag); |
| 822 | if (err < 0) { | 822 | if (err < 0) { |
| 823 | fl6_sock_release(flowlabel); | 823 | fl6_sock_release(flowlabel); |
| 824 | return err; | 824 | return err; |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 7b954e2539d0..dfb164e9051a 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | #include <linux/jhash.h> | 42 | #include <linux/jhash.h> |
| 43 | #include <linux/skbuff.h> | 43 | #include <linux/skbuff.h> |
| 44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
| 45 | #include <linux/export.h> | ||
| 45 | 46 | ||
| 46 | #include <net/sock.h> | 47 | #include <net/sock.h> |
| 47 | #include <net/snmp.h> | 48 | #include <net/snmp.h> |
| @@ -464,8 +465,8 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
| 464 | head->next = clone; | 465 | head->next = clone; |
| 465 | skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list; | 466 | skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list; |
| 466 | skb_frag_list_init(head); | 467 | skb_frag_list_init(head); |
| 467 | for (i=0; i<skb_shinfo(head)->nr_frags; i++) | 468 | for (i = 0; i < skb_shinfo(head)->nr_frags; i++) |
| 468 | plen += skb_shinfo(head)->frags[i].size; | 469 | plen += skb_frag_size(&skb_shinfo(head)->frags[i]); |
| 469 | clone->len = clone->data_len = head->data_len - plen; | 470 | clone->len = clone->data_len = head->data_len - plen; |
| 470 | head->data_len -= clone->len; | 471 | head->data_len -= clone->len; |
| 471 | head->len -= clone->len; | 472 | head->len -= clone->len; |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9e69eb0ec6dd..8473016bba4a 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -26,6 +26,7 @@ | |||
| 26 | 26 | ||
| 27 | #include <linux/capability.h> | 27 | #include <linux/capability.h> |
| 28 | #include <linux/errno.h> | 28 | #include <linux/errno.h> |
| 29 | #include <linux/export.h> | ||
| 29 | #include <linux/types.h> | 30 | #include <linux/types.h> |
| 30 | #include <linux/times.h> | 31 | #include <linux/times.h> |
| 31 | #include <linux/socket.h> | 32 | #include <linux/socket.h> |
| @@ -104,6 +105,9 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
| 104 | struct inet_peer *peer; | 105 | struct inet_peer *peer; |
| 105 | u32 *p = NULL; | 106 | u32 *p = NULL; |
| 106 | 107 | ||
| 108 | if (!(rt->dst.flags & DST_HOST)) | ||
| 109 | return NULL; | ||
| 110 | |||
| 107 | if (!rt->rt6i_peer) | 111 | if (!rt->rt6i_peer) |
| 108 | rt6_bind_peer(rt, 1); | 112 | rt6_bind_peer(rt, 1); |
| 109 | 113 | ||
| @@ -241,7 +245,9 @@ static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops, | |||
| 241 | { | 245 | { |
| 242 | struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); | 246 | struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, flags); |
| 243 | 247 | ||
| 244 | memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); | 248 | if (rt != NULL) |
| 249 | memset(&rt->rt6i_table, 0, | ||
| 250 | sizeof(*rt) - sizeof(struct dst_entry)); | ||
| 245 | 251 | ||
| 246 | return rt; | 252 | return rt; |
| 247 | } | 253 | } |
| @@ -252,6 +258,9 @@ static void ip6_dst_destroy(struct dst_entry *dst) | |||
| 252 | struct inet6_dev *idev = rt->rt6i_idev; | 258 | struct inet6_dev *idev = rt->rt6i_idev; |
| 253 | struct inet_peer *peer = rt->rt6i_peer; | 259 | struct inet_peer *peer = rt->rt6i_peer; |
| 254 | 260 | ||
| 261 | if (!(rt->dst.flags & DST_HOST)) | ||
| 262 | dst_destroy_metrics_generic(dst); | ||
| 263 | |||
| 255 | if (idev != NULL) { | 264 | if (idev != NULL) { |
| 256 | rt->rt6i_idev = NULL; | 265 | rt->rt6i_idev = NULL; |
| 257 | in6_dev_put(idev); | 266 | in6_dev_put(idev); |
| @@ -723,9 +732,7 @@ static struct rt6_info *rt6_alloc_cow(const struct rt6_info *ort, | |||
| 723 | ipv6_addr_copy(&rt->rt6i_gateway, daddr); | 732 | ipv6_addr_copy(&rt->rt6i_gateway, daddr); |
| 724 | } | 733 | } |
| 725 | 734 | ||
| 726 | rt->rt6i_dst.plen = 128; | ||
| 727 | rt->rt6i_flags |= RTF_CACHE; | 735 | rt->rt6i_flags |= RTF_CACHE; |
| 728 | rt->dst.flags |= DST_HOST; | ||
| 729 | 736 | ||
| 730 | #ifdef CONFIG_IPV6_SUBTREES | 737 | #ifdef CONFIG_IPV6_SUBTREES |
| 731 | if (rt->rt6i_src.plen && saddr) { | 738 | if (rt->rt6i_src.plen && saddr) { |
| @@ -775,9 +782,7 @@ static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, | |||
| 775 | struct rt6_info *rt = ip6_rt_copy(ort, daddr); | 782 | struct rt6_info *rt = ip6_rt_copy(ort, daddr); |
| 776 | 783 | ||
| 777 | if (rt) { | 784 | if (rt) { |
| 778 | rt->rt6i_dst.plen = 128; | ||
| 779 | rt->rt6i_flags |= RTF_CACHE; | 785 | rt->rt6i_flags |= RTF_CACHE; |
| 780 | rt->dst.flags |= DST_HOST; | ||
| 781 | dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst))); | 786 | dst_set_neighbour(&rt->dst, neigh_clone(dst_get_neighbour_raw(&ort->dst))); |
| 782 | } | 787 | } |
| 783 | return rt; | 788 | return rt; |
| @@ -1078,12 +1083,14 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
| 1078 | neigh = NULL; | 1083 | neigh = NULL; |
| 1079 | } | 1084 | } |
| 1080 | 1085 | ||
| 1081 | rt->rt6i_idev = idev; | 1086 | rt->dst.flags |= DST_HOST; |
| 1087 | rt->dst.output = ip6_output; | ||
| 1082 | dst_set_neighbour(&rt->dst, neigh); | 1088 | dst_set_neighbour(&rt->dst, neigh); |
| 1083 | atomic_set(&rt->dst.__refcnt, 1); | 1089 | atomic_set(&rt->dst.__refcnt, 1); |
| 1084 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); | 1090 | ipv6_addr_copy(&rt->rt6i_dst.addr, addr); |
| 1091 | rt->rt6i_dst.plen = 128; | ||
| 1092 | rt->rt6i_idev = idev; | ||
| 1085 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); | 1093 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); |
| 1086 | rt->dst.output = ip6_output; | ||
| 1087 | 1094 | ||
| 1088 | spin_lock_bh(&icmp6_dst_lock); | 1095 | spin_lock_bh(&icmp6_dst_lock); |
| 1089 | rt->dst.next = icmp6_dst_gc_list; | 1096 | rt->dst.next = icmp6_dst_gc_list; |
| @@ -1261,6 +1268,14 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1261 | if (rt->rt6i_dst.plen == 128) | 1268 | if (rt->rt6i_dst.plen == 128) |
| 1262 | rt->dst.flags |= DST_HOST; | 1269 | rt->dst.flags |= DST_HOST; |
| 1263 | 1270 | ||
| 1271 | if (!(rt->dst.flags & DST_HOST) && cfg->fc_mx) { | ||
| 1272 | u32 *metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); | ||
| 1273 | if (!metrics) { | ||
| 1274 | err = -ENOMEM; | ||
| 1275 | goto out; | ||
| 1276 | } | ||
| 1277 | dst_init_metrics(&rt->dst, metrics, 0); | ||
| 1278 | } | ||
| 1264 | #ifdef CONFIG_IPV6_SUBTREES | 1279 | #ifdef CONFIG_IPV6_SUBTREES |
| 1265 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); | 1280 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); |
| 1266 | rt->rt6i_src.plen = cfg->fc_src_len; | 1281 | rt->rt6i_src.plen = cfg->fc_src_len; |
| @@ -1607,9 +1622,6 @@ void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, | |||
| 1607 | if (on_link) | 1622 | if (on_link) |
| 1608 | nrt->rt6i_flags &= ~RTF_GATEWAY; | 1623 | nrt->rt6i_flags &= ~RTF_GATEWAY; |
| 1609 | 1624 | ||
| 1610 | nrt->rt6i_dst.plen = 128; | ||
| 1611 | nrt->dst.flags |= DST_HOST; | ||
| 1612 | |||
| 1613 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); | 1625 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); |
| 1614 | dst_set_neighbour(&nrt->dst, neigh_clone(neigh)); | 1626 | dst_set_neighbour(&nrt->dst, neigh_clone(neigh)); |
| 1615 | 1627 | ||
| @@ -1754,9 +1766,10 @@ static struct rt6_info *ip6_rt_copy(const struct rt6_info *ort, | |||
| 1754 | if (rt) { | 1766 | if (rt) { |
| 1755 | rt->dst.input = ort->dst.input; | 1767 | rt->dst.input = ort->dst.input; |
| 1756 | rt->dst.output = ort->dst.output; | 1768 | rt->dst.output = ort->dst.output; |
| 1769 | rt->dst.flags |= DST_HOST; | ||
| 1757 | 1770 | ||
| 1758 | ipv6_addr_copy(&rt->rt6i_dst.addr, dest); | 1771 | ipv6_addr_copy(&rt->rt6i_dst.addr, dest); |
| 1759 | rt->rt6i_dst.plen = ort->rt6i_dst.plen; | 1772 | rt->rt6i_dst.plen = 128; |
| 1760 | dst_copy_metrics(&rt->dst, &ort->dst); | 1773 | dst_copy_metrics(&rt->dst, &ort->dst); |
| 1761 | rt->dst.error = ort->dst.error; | 1774 | rt->dst.error = ort->dst.error; |
| 1762 | rt->rt6i_idev = ort->rt6i_idev; | 1775 | rt->rt6i_idev = ort->rt6i_idev; |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 00b15ac7a702..a7a18602a046 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
| @@ -182,7 +182,7 @@ static void ipip6_tunnel_unlink(struct sit_net *sitn, struct ip_tunnel *t) | |||
| 182 | (iter = rtnl_dereference(*tp)) != NULL; | 182 | (iter = rtnl_dereference(*tp)) != NULL; |
| 183 | tp = &iter->next) { | 183 | tp = &iter->next) { |
| 184 | if (t == iter) { | 184 | if (t == iter) { |
| 185 | rcu_assign_pointer(*tp, t->next); | 185 | RCU_INIT_POINTER(*tp, t->next); |
| 186 | break; | 186 | break; |
| 187 | } | 187 | } |
| 188 | } | 188 | } |
| @@ -192,8 +192,8 @@ static void ipip6_tunnel_link(struct sit_net *sitn, struct ip_tunnel *t) | |||
| 192 | { | 192 | { |
| 193 | struct ip_tunnel __rcu **tp = ipip6_bucket(sitn, t); | 193 | struct ip_tunnel __rcu **tp = ipip6_bucket(sitn, t); |
| 194 | 194 | ||
| 195 | rcu_assign_pointer(t->next, rtnl_dereference(*tp)); | 195 | RCU_INIT_POINTER(t->next, rtnl_dereference(*tp)); |
| 196 | rcu_assign_pointer(*tp, t); | 196 | RCU_INIT_POINTER(*tp, t); |
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn) | 199 | static void ipip6_tunnel_clone_6rd(struct net_device *dev, struct sit_net *sitn) |
| @@ -391,7 +391,7 @@ ipip6_tunnel_add_prl(struct ip_tunnel *t, struct ip_tunnel_prl *a, int chg) | |||
| 391 | p->addr = a->addr; | 391 | p->addr = a->addr; |
| 392 | p->flags = a->flags; | 392 | p->flags = a->flags; |
| 393 | t->prl_count++; | 393 | t->prl_count++; |
| 394 | rcu_assign_pointer(t->prl, p); | 394 | RCU_INIT_POINTER(t->prl, p); |
| 395 | out: | 395 | out: |
| 396 | return err; | 396 | return err; |
| 397 | } | 397 | } |
| @@ -474,7 +474,7 @@ static void ipip6_tunnel_uninit(struct net_device *dev) | |||
| 474 | struct sit_net *sitn = net_generic(net, sit_net_id); | 474 | struct sit_net *sitn = net_generic(net, sit_net_id); |
| 475 | 475 | ||
| 476 | if (dev == sitn->fb_tunnel_dev) { | 476 | if (dev == sitn->fb_tunnel_dev) { |
| 477 | rcu_assign_pointer(sitn->tunnels_wc[0], NULL); | 477 | RCU_INIT_POINTER(sitn->tunnels_wc[0], NULL); |
| 478 | } else { | 478 | } else { |
| 479 | ipip6_tunnel_unlink(sitn, netdev_priv(dev)); | 479 | ipip6_tunnel_unlink(sitn, netdev_priv(dev)); |
| 480 | ipip6_tunnel_del_prl(netdev_priv(dev), NULL); | 480 | ipip6_tunnel_del_prl(netdev_priv(dev), NULL); |
| @@ -1176,7 +1176,7 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
| 1176 | if (!dev->tstats) | 1176 | if (!dev->tstats) |
| 1177 | return -ENOMEM; | 1177 | return -ENOMEM; |
| 1178 | dev_hold(dev); | 1178 | dev_hold(dev); |
| 1179 | rcu_assign_pointer(sitn->tunnels_wc[0], tunnel); | 1179 | RCU_INIT_POINTER(sitn->tunnels_wc[0], tunnel); |
| 1180 | return 0; | 1180 | return 0; |
| 1181 | } | 1181 | } |
| 1182 | 1182 | ||
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index ac838965ff34..5a0d6648bbbc 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
| @@ -115,7 +115,7 @@ static __u32 check_tcp_syn_cookie(__u32 cookie, const struct in6_addr *saddr, | |||
| 115 | & COOKIEMASK; | 115 | & COOKIEMASK; |
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) | 118 | __u32 cookie_v6_init_sequence(struct sock *sk, const struct sk_buff *skb, __u16 *mssp) |
| 119 | { | 119 | { |
| 120 | const struct ipv6hdr *iph = ipv6_hdr(skb); | 120 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
| 121 | const struct tcphdr *th = tcp_hdr(skb); | 121 | const struct tcphdr *th = tcp_hdr(skb); |
| @@ -137,7 +137,7 @@ __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) | |||
| 137 | jiffies / (HZ * 60), mssind); | 137 | jiffies / (HZ * 60), mssind); |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | static inline int cookie_check(struct sk_buff *skb, __u32 cookie) | 140 | static inline int cookie_check(const struct sk_buff *skb, __u32 cookie) |
| 141 | { | 141 | { |
| 142 | const struct ipv6hdr *iph = ipv6_hdr(skb); | 142 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
| 143 | const struct tcphdr *th = tcp_hdr(skb); | 143 | const struct tcphdr *th = tcp_hdr(skb); |
| @@ -152,7 +152,7 @@ static inline int cookie_check(struct sk_buff *skb, __u32 cookie) | |||
| 152 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | 152 | struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) |
| 153 | { | 153 | { |
| 154 | struct tcp_options_received tcp_opt; | 154 | struct tcp_options_received tcp_opt; |
| 155 | u8 *hash_location; | 155 | const u8 *hash_location; |
| 156 | struct inet_request_sock *ireq; | 156 | struct inet_request_sock *ireq; |
| 157 | struct inet6_request_sock *ireq6; | 157 | struct inet6_request_sock *ireq6; |
| 158 | struct tcp_request_sock *treq; | 158 | struct tcp_request_sock *treq; |
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index 6dcf5e7d661b..166a57c47d39 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/in6.h> | 10 | #include <linux/in6.h> |
| 11 | #include <linux/ipv6.h> | 11 | #include <linux/ipv6.h> |
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/export.h> | ||
| 13 | #include <net/ndisc.h> | 14 | #include <net/ndisc.h> |
| 14 | #include <net/ipv6.h> | 15 | #include <net/ipv6.h> |
| 15 | #include <net/addrconf.h> | 16 | #include <net/addrconf.h> |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index d1fb63f4aeb7..36131d122a6f 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -114,7 +114,7 @@ static __inline__ __sum16 tcp_v6_check(int len, | |||
| 114 | return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); | 114 | return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | static __u32 tcp_v6_init_sequence(struct sk_buff *skb) | 117 | static __u32 tcp_v6_init_sequence(const struct sk_buff *skb) |
| 118 | { | 118 | { |
| 119 | return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32, | 119 | return secure_tcpv6_sequence_number(ipv6_hdr(skb)->daddr.s6_addr32, |
| 120 | ipv6_hdr(skb)->saddr.s6_addr32, | 120 | ipv6_hdr(skb)->saddr.s6_addr32, |
| @@ -513,7 +513,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
| 513 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); | 513 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); |
| 514 | 514 | ||
| 515 | ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr); | 515 | ipv6_addr_copy(&fl6.daddr, &treq->rmt_addr); |
| 516 | err = ip6_xmit(sk, skb, &fl6, opt); | 516 | err = ip6_xmit(sk, skb, &fl6, opt, np->tclass); |
| 517 | err = net_xmit_eval(err); | 517 | err = net_xmit_eval(err); |
| 518 | } | 518 | } |
| 519 | 519 | ||
| @@ -531,20 +531,6 @@ static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req, | |||
| 531 | return tcp_v6_send_synack(sk, req, rvp); | 531 | return tcp_v6_send_synack(sk, req, rvp); |
| 532 | } | 532 | } |
| 533 | 533 | ||
| 534 | static inline void syn_flood_warning(struct sk_buff *skb) | ||
| 535 | { | ||
| 536 | #ifdef CONFIG_SYN_COOKIES | ||
| 537 | if (sysctl_tcp_syncookies) | ||
| 538 | printk(KERN_INFO | ||
| 539 | "TCPv6: Possible SYN flooding on port %d. " | ||
| 540 | "Sending cookies.\n", ntohs(tcp_hdr(skb)->dest)); | ||
| 541 | else | ||
| 542 | #endif | ||
| 543 | printk(KERN_INFO | ||
| 544 | "TCPv6: Possible SYN flooding on port %d. " | ||
| 545 | "Dropping request.\n", ntohs(tcp_hdr(skb)->dest)); | ||
| 546 | } | ||
| 547 | |||
| 548 | static void tcp_v6_reqsk_destructor(struct request_sock *req) | 534 | static void tcp_v6_reqsk_destructor(struct request_sock *req) |
| 549 | { | 535 | { |
| 550 | kfree_skb(inet6_rsk(req)->pktopts); | 536 | kfree_skb(inet6_rsk(req)->pktopts); |
| @@ -605,7 +591,8 @@ static int tcp_v6_md5_do_add(struct sock *sk, const struct in6_addr *peer, | |||
| 605 | } | 591 | } |
| 606 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); | 592 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); |
| 607 | } | 593 | } |
| 608 | if (tcp_alloc_md5sig_pool(sk) == NULL) { | 594 | if (tp->md5sig_info->entries6 == 0 && |
| 595 | tcp_alloc_md5sig_pool(sk) == NULL) { | ||
| 609 | kfree(newkey); | 596 | kfree(newkey); |
| 610 | return -ENOMEM; | 597 | return -ENOMEM; |
| 611 | } | 598 | } |
| @@ -614,8 +601,9 @@ static int tcp_v6_md5_do_add(struct sock *sk, const struct in6_addr *peer, | |||
| 614 | (tp->md5sig_info->entries6 + 1)), GFP_ATOMIC); | 601 | (tp->md5sig_info->entries6 + 1)), GFP_ATOMIC); |
| 615 | 602 | ||
| 616 | if (!keys) { | 603 | if (!keys) { |
| 617 | tcp_free_md5sig_pool(); | ||
| 618 | kfree(newkey); | 604 | kfree(newkey); |
| 605 | if (tp->md5sig_info->entries6 == 0) | ||
| 606 | tcp_free_md5sig_pool(); | ||
| 619 | return -ENOMEM; | 607 | return -ENOMEM; |
| 620 | } | 608 | } |
| 621 | 609 | ||
| @@ -661,6 +649,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, const struct in6_addr *peer) | |||
| 661 | kfree(tp->md5sig_info->keys6); | 649 | kfree(tp->md5sig_info->keys6); |
| 662 | tp->md5sig_info->keys6 = NULL; | 650 | tp->md5sig_info->keys6 = NULL; |
| 663 | tp->md5sig_info->alloced6 = 0; | 651 | tp->md5sig_info->alloced6 = 0; |
| 652 | tcp_free_md5sig_pool(); | ||
| 664 | } else { | 653 | } else { |
| 665 | /* shrink the database */ | 654 | /* shrink the database */ |
| 666 | if (tp->md5sig_info->entries6 != i) | 655 | if (tp->md5sig_info->entries6 != i) |
| @@ -669,7 +658,6 @@ static int tcp_v6_md5_do_del(struct sock *sk, const struct in6_addr *peer) | |||
| 669 | (tp->md5sig_info->entries6 - i) | 658 | (tp->md5sig_info->entries6 - i) |
| 670 | * sizeof (tp->md5sig_info->keys6[0])); | 659 | * sizeof (tp->md5sig_info->keys6[0])); |
| 671 | } | 660 | } |
| 672 | tcp_free_md5sig_pool(); | ||
| 673 | return 0; | 661 | return 0; |
| 674 | } | 662 | } |
| 675 | } | 663 | } |
| @@ -773,7 +761,7 @@ static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, | |||
| 773 | 761 | ||
| 774 | static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, | 762 | static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, |
| 775 | const struct in6_addr *daddr, struct in6_addr *saddr, | 763 | const struct in6_addr *daddr, struct in6_addr *saddr, |
| 776 | struct tcphdr *th) | 764 | const struct tcphdr *th) |
| 777 | { | 765 | { |
| 778 | struct tcp_md5sig_pool *hp; | 766 | struct tcp_md5sig_pool *hp; |
| 779 | struct hash_desc *desc; | 767 | struct hash_desc *desc; |
| @@ -805,13 +793,14 @@ clear_hash_noput: | |||
| 805 | } | 793 | } |
| 806 | 794 | ||
| 807 | static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key, | 795 | static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key, |
| 808 | struct sock *sk, struct request_sock *req, | 796 | const struct sock *sk, |
| 809 | struct sk_buff *skb) | 797 | const struct request_sock *req, |
| 798 | const struct sk_buff *skb) | ||
| 810 | { | 799 | { |
| 811 | const struct in6_addr *saddr, *daddr; | 800 | const struct in6_addr *saddr, *daddr; |
| 812 | struct tcp_md5sig_pool *hp; | 801 | struct tcp_md5sig_pool *hp; |
| 813 | struct hash_desc *desc; | 802 | struct hash_desc *desc; |
| 814 | struct tcphdr *th = tcp_hdr(skb); | 803 | const struct tcphdr *th = tcp_hdr(skb); |
| 815 | 804 | ||
| 816 | if (sk) { | 805 | if (sk) { |
| 817 | saddr = &inet6_sk(sk)->saddr; | 806 | saddr = &inet6_sk(sk)->saddr; |
| @@ -854,12 +843,12 @@ clear_hash_noput: | |||
| 854 | return 1; | 843 | return 1; |
| 855 | } | 844 | } |
| 856 | 845 | ||
| 857 | static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | 846 | static int tcp_v6_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) |
| 858 | { | 847 | { |
| 859 | __u8 *hash_location = NULL; | 848 | const __u8 *hash_location = NULL; |
| 860 | struct tcp_md5sig_key *hash_expected; | 849 | struct tcp_md5sig_key *hash_expected; |
| 861 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); | 850 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
| 862 | struct tcphdr *th = tcp_hdr(skb); | 851 | const struct tcphdr *th = tcp_hdr(skb); |
| 863 | int genhash; | 852 | int genhash; |
| 864 | u8 newhash[16]; | 853 | u8 newhash[16]; |
| 865 | 854 | ||
| @@ -990,9 +979,10 @@ static int tcp6_gro_complete(struct sk_buff *skb) | |||
| 990 | } | 979 | } |
| 991 | 980 | ||
| 992 | static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | 981 | static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, |
| 993 | u32 ts, struct tcp_md5sig_key *key, int rst) | 982 | u32 ts, struct tcp_md5sig_key *key, int rst, u8 tclass) |
| 994 | { | 983 | { |
| 995 | struct tcphdr *th = tcp_hdr(skb), *t1; | 984 | const struct tcphdr *th = tcp_hdr(skb); |
| 985 | struct tcphdr *t1; | ||
| 996 | struct sk_buff *buff; | 986 | struct sk_buff *buff; |
| 997 | struct flowi6 fl6; | 987 | struct flowi6 fl6; |
| 998 | struct net *net = dev_net(skb_dst(skb)->dev); | 988 | struct net *net = dev_net(skb_dst(skb)->dev); |
| @@ -1070,7 +1060,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
| 1070 | dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false); | 1060 | dst = ip6_dst_lookup_flow(ctl_sk, &fl6, NULL, false); |
| 1071 | if (!IS_ERR(dst)) { | 1061 | if (!IS_ERR(dst)) { |
| 1072 | skb_dst_set(buff, dst); | 1062 | skb_dst_set(buff, dst); |
| 1073 | ip6_xmit(ctl_sk, buff, &fl6, NULL); | 1063 | ip6_xmit(ctl_sk, buff, &fl6, NULL, tclass); |
| 1074 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); | 1064 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); |
| 1075 | if (rst) | 1065 | if (rst) |
| 1076 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); | 1066 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); |
| @@ -1082,7 +1072,7 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
| 1082 | 1072 | ||
| 1083 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | 1073 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) |
| 1084 | { | 1074 | { |
| 1085 | struct tcphdr *th = tcp_hdr(skb); | 1075 | const struct tcphdr *th = tcp_hdr(skb); |
| 1086 | u32 seq = 0, ack_seq = 0; | 1076 | u32 seq = 0, ack_seq = 0; |
| 1087 | struct tcp_md5sig_key *key = NULL; | 1077 | struct tcp_md5sig_key *key = NULL; |
| 1088 | 1078 | ||
| @@ -1103,13 +1093,13 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
| 1103 | ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len - | 1093 | ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len - |
| 1104 | (th->doff << 2); | 1094 | (th->doff << 2); |
| 1105 | 1095 | ||
| 1106 | tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1); | 1096 | tcp_v6_send_response(skb, seq, ack_seq, 0, 0, key, 1, 0); |
| 1107 | } | 1097 | } |
| 1108 | 1098 | ||
| 1109 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, | 1099 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, |
| 1110 | struct tcp_md5sig_key *key) | 1100 | struct tcp_md5sig_key *key, u8 tclass) |
| 1111 | { | 1101 | { |
| 1112 | tcp_v6_send_response(skb, seq, ack, win, ts, key, 0); | 1102 | tcp_v6_send_response(skb, seq, ack, win, ts, key, 0, tclass); |
| 1113 | } | 1103 | } |
| 1114 | 1104 | ||
| 1115 | static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | 1105 | static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) |
| @@ -1119,7 +1109,8 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
| 1119 | 1109 | ||
| 1120 | tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 1110 | tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, |
| 1121 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 1111 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
| 1122 | tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw)); | 1112 | tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw), |
| 1113 | tw->tw_tclass); | ||
| 1123 | 1114 | ||
| 1124 | inet_twsk_put(tw); | 1115 | inet_twsk_put(tw); |
| 1125 | } | 1116 | } |
| @@ -1128,7 +1119,7 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
| 1128 | struct request_sock *req) | 1119 | struct request_sock *req) |
| 1129 | { | 1120 | { |
| 1130 | tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent, | 1121 | tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent, |
| 1131 | tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr)); | 1122 | tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), 0); |
| 1132 | } | 1123 | } |
| 1133 | 1124 | ||
| 1134 | 1125 | ||
| @@ -1172,18 +1163,14 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
| 1172 | { | 1163 | { |
| 1173 | struct tcp_extend_values tmp_ext; | 1164 | struct tcp_extend_values tmp_ext; |
| 1174 | struct tcp_options_received tmp_opt; | 1165 | struct tcp_options_received tmp_opt; |
| 1175 | u8 *hash_location; | 1166 | const u8 *hash_location; |
| 1176 | struct request_sock *req; | 1167 | struct request_sock *req; |
| 1177 | struct inet6_request_sock *treq; | 1168 | struct inet6_request_sock *treq; |
| 1178 | struct ipv6_pinfo *np = inet6_sk(sk); | 1169 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 1179 | struct tcp_sock *tp = tcp_sk(sk); | 1170 | struct tcp_sock *tp = tcp_sk(sk); |
| 1180 | __u32 isn = TCP_SKB_CB(skb)->when; | 1171 | __u32 isn = TCP_SKB_CB(skb)->when; |
| 1181 | struct dst_entry *dst = NULL; | 1172 | struct dst_entry *dst = NULL; |
| 1182 | #ifdef CONFIG_SYN_COOKIES | ||
| 1183 | int want_cookie = 0; | 1173 | int want_cookie = 0; |
| 1184 | #else | ||
| 1185 | #define want_cookie 0 | ||
| 1186 | #endif | ||
| 1187 | 1174 | ||
| 1188 | if (skb->protocol == htons(ETH_P_IP)) | 1175 | if (skb->protocol == htons(ETH_P_IP)) |
| 1189 | return tcp_v4_conn_request(sk, skb); | 1176 | return tcp_v4_conn_request(sk, skb); |
| @@ -1192,14 +1179,9 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
| 1192 | goto drop; | 1179 | goto drop; |
| 1193 | 1180 | ||
| 1194 | if (inet_csk_reqsk_queue_is_full(sk) && !isn) { | 1181 | if (inet_csk_reqsk_queue_is_full(sk) && !isn) { |
| 1195 | if (net_ratelimit()) | 1182 | want_cookie = tcp_syn_flood_action(sk, skb, "TCPv6"); |
| 1196 | syn_flood_warning(skb); | 1183 | if (!want_cookie) |
| 1197 | #ifdef CONFIG_SYN_COOKIES | 1184 | goto drop; |
| 1198 | if (sysctl_tcp_syncookies) | ||
| 1199 | want_cookie = 1; | ||
| 1200 | else | ||
| 1201 | #endif | ||
| 1202 | goto drop; | ||
| 1203 | } | 1185 | } |
| 1204 | 1186 | ||
| 1205 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) | 1187 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) |
| @@ -1249,9 +1231,7 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
| 1249 | while (l-- > 0) | 1231 | while (l-- > 0) |
| 1250 | *c++ ^= *hash_location++; | 1232 | *c++ ^= *hash_location++; |
| 1251 | 1233 | ||
| 1252 | #ifdef CONFIG_SYN_COOKIES | ||
| 1253 | want_cookie = 0; /* not our kind of cookie */ | 1234 | want_cookie = 0; /* not our kind of cookie */ |
| 1254 | #endif | ||
| 1255 | tmp_ext.cookie_out_never = 0; /* false */ | 1235 | tmp_ext.cookie_out_never = 0; /* false */ |
| 1256 | tmp_ext.cookie_plus = tmp_opt.cookie_plus; | 1236 | tmp_ext.cookie_plus = tmp_opt.cookie_plus; |
| 1257 | } else if (!tp->rx_opt.cookie_in_always) { | 1237 | } else if (!tp->rx_opt.cookie_in_always) { |
| @@ -1408,6 +1388,8 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
| 1408 | newtp->af_specific = &tcp_sock_ipv6_mapped_specific; | 1388 | newtp->af_specific = &tcp_sock_ipv6_mapped_specific; |
| 1409 | #endif | 1389 | #endif |
| 1410 | 1390 | ||
| 1391 | newnp->ipv6_ac_list = NULL; | ||
| 1392 | newnp->ipv6_fl_list = NULL; | ||
| 1411 | newnp->pktoptions = NULL; | 1393 | newnp->pktoptions = NULL; |
| 1412 | newnp->opt = NULL; | 1394 | newnp->opt = NULL; |
| 1413 | newnp->mcast_oif = inet6_iif(skb); | 1395 | newnp->mcast_oif = inet6_iif(skb); |
| @@ -1472,6 +1454,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
| 1472 | First: no IPv4 options. | 1454 | First: no IPv4 options. |
| 1473 | */ | 1455 | */ |
| 1474 | newinet->inet_opt = NULL; | 1456 | newinet->inet_opt = NULL; |
| 1457 | newnp->ipv6_ac_list = NULL; | ||
| 1475 | newnp->ipv6_fl_list = NULL; | 1458 | newnp->ipv6_fl_list = NULL; |
| 1476 | 1459 | ||
| 1477 | /* Clone RX bits */ | 1460 | /* Clone RX bits */ |
| @@ -1628,7 +1611,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
| 1628 | opt_skb = skb_clone(skb, GFP_ATOMIC); | 1611 | opt_skb = skb_clone(skb, GFP_ATOMIC); |
| 1629 | 1612 | ||
| 1630 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ | 1613 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ |
| 1631 | sock_rps_save_rxhash(sk, skb->rxhash); | 1614 | sock_rps_save_rxhash(sk, skb); |
| 1632 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) | 1615 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) |
| 1633 | goto reset; | 1616 | goto reset; |
| 1634 | if (opt_skb) | 1617 | if (opt_skb) |
| @@ -1650,7 +1633,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
| 1650 | * the new socket.. | 1633 | * the new socket.. |
| 1651 | */ | 1634 | */ |
| 1652 | if(nsk != sk) { | 1635 | if(nsk != sk) { |
| 1653 | sock_rps_save_rxhash(nsk, skb->rxhash); | 1636 | sock_rps_save_rxhash(nsk, skb); |
| 1654 | if (tcp_child_process(sk, nsk, skb)) | 1637 | if (tcp_child_process(sk, nsk, skb)) |
| 1655 | goto reset; | 1638 | goto reset; |
| 1656 | if (opt_skb) | 1639 | if (opt_skb) |
| @@ -1658,7 +1641,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
| 1658 | return 0; | 1641 | return 0; |
| 1659 | } | 1642 | } |
| 1660 | } else | 1643 | } else |
| 1661 | sock_rps_save_rxhash(sk, skb->rxhash); | 1644 | sock_rps_save_rxhash(sk, skb); |
| 1662 | 1645 | ||
| 1663 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) | 1646 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) |
| 1664 | goto reset; | 1647 | goto reset; |
| @@ -1708,7 +1691,7 @@ ipv6_pktoptions: | |||
| 1708 | 1691 | ||
| 1709 | static int tcp_v6_rcv(struct sk_buff *skb) | 1692 | static int tcp_v6_rcv(struct sk_buff *skb) |
| 1710 | { | 1693 | { |
| 1711 | struct tcphdr *th; | 1694 | const struct tcphdr *th; |
| 1712 | const struct ipv6hdr *hdr; | 1695 | const struct ipv6hdr *hdr; |
| 1713 | struct sock *sk; | 1696 | struct sock *sk; |
| 1714 | int ret; | 1697 | int ret; |
| @@ -1742,7 +1725,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
| 1742 | skb->len - th->doff*4); | 1725 | skb->len - th->doff*4); |
| 1743 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); | 1726 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); |
| 1744 | TCP_SKB_CB(skb)->when = 0; | 1727 | TCP_SKB_CB(skb)->when = 0; |
| 1745 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(hdr); | 1728 | TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr); |
| 1746 | TCP_SKB_CB(skb)->sacked = 0; | 1729 | TCP_SKB_CB(skb)->sacked = 0; |
| 1747 | 1730 | ||
| 1748 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); | 1731 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest); |
| @@ -1876,8 +1859,8 @@ static struct inet_peer *tcp_v6_get_peer(struct sock *sk, bool *release_it) | |||
| 1876 | 1859 | ||
| 1877 | static void *tcp_v6_tw_get_peer(struct sock *sk) | 1860 | static void *tcp_v6_tw_get_peer(struct sock *sk) |
| 1878 | { | 1861 | { |
| 1879 | struct inet6_timewait_sock *tw6 = inet6_twsk(sk); | 1862 | const struct inet6_timewait_sock *tw6 = inet6_twsk(sk); |
| 1880 | struct inet_timewait_sock *tw = inet_twsk(sk); | 1863 | const struct inet_timewait_sock *tw = inet_twsk(sk); |
| 1881 | 1864 | ||
| 1882 | if (tw->tw_family == AF_INET) | 1865 | if (tw->tw_family == AF_INET) |
| 1883 | return tcp_v4_tw_get_peer(sk); | 1866 | return tcp_v4_tw_get_peer(sk); |
| @@ -2032,7 +2015,7 @@ static void tcp_v6_destroy_sock(struct sock *sk) | |||
| 2032 | #ifdef CONFIG_PROC_FS | 2015 | #ifdef CONFIG_PROC_FS |
| 2033 | /* Proc filesystem TCPv6 sock list dumping. */ | 2016 | /* Proc filesystem TCPv6 sock list dumping. */ |
| 2034 | static void get_openreq6(struct seq_file *seq, | 2017 | static void get_openreq6(struct seq_file *seq, |
| 2035 | struct sock *sk, struct request_sock *req, int i, int uid) | 2018 | const struct sock *sk, struct request_sock *req, int i, int uid) |
| 2036 | { | 2019 | { |
| 2037 | int ttd = req->expires - jiffies; | 2020 | int ttd = req->expires - jiffies; |
| 2038 | const struct in6_addr *src = &inet6_rsk(req)->loc_addr; | 2021 | const struct in6_addr *src = &inet6_rsk(req)->loc_addr; |
| @@ -2068,10 +2051,10 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | |||
| 2068 | __u16 destp, srcp; | 2051 | __u16 destp, srcp; |
| 2069 | int timer_active; | 2052 | int timer_active; |
| 2070 | unsigned long timer_expires; | 2053 | unsigned long timer_expires; |
| 2071 | struct inet_sock *inet = inet_sk(sp); | 2054 | const struct inet_sock *inet = inet_sk(sp); |
| 2072 | struct tcp_sock *tp = tcp_sk(sp); | 2055 | const struct tcp_sock *tp = tcp_sk(sp); |
| 2073 | const struct inet_connection_sock *icsk = inet_csk(sp); | 2056 | const struct inet_connection_sock *icsk = inet_csk(sp); |
| 2074 | struct ipv6_pinfo *np = inet6_sk(sp); | 2057 | const struct ipv6_pinfo *np = inet6_sk(sp); |
| 2075 | 2058 | ||
| 2076 | dest = &np->daddr; | 2059 | dest = &np->daddr; |
| 2077 | src = &np->rcv_saddr; | 2060 | src = &np->rcv_saddr; |
| @@ -2123,7 +2106,7 @@ static void get_timewait6_sock(struct seq_file *seq, | |||
| 2123 | { | 2106 | { |
| 2124 | const struct in6_addr *dest, *src; | 2107 | const struct in6_addr *dest, *src; |
| 2125 | __u16 destp, srcp; | 2108 | __u16 destp, srcp; |
| 2126 | struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); | 2109 | const struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); |
| 2127 | int ttd = tw->tw_ttd - jiffies; | 2110 | int ttd = tw->tw_ttd - jiffies; |
| 2128 | 2111 | ||
| 2129 | if (ttd < 0) | 2112 | if (ttd < 0) |
| @@ -2178,12 +2161,18 @@ out: | |||
| 2178 | return 0; | 2161 | return 0; |
| 2179 | } | 2162 | } |
| 2180 | 2163 | ||
| 2164 | static const struct file_operations tcp6_afinfo_seq_fops = { | ||
| 2165 | .owner = THIS_MODULE, | ||
| 2166 | .open = tcp_seq_open, | ||
| 2167 | .read = seq_read, | ||
| 2168 | .llseek = seq_lseek, | ||
| 2169 | .release = seq_release_net | ||
| 2170 | }; | ||
| 2171 | |||
| 2181 | static struct tcp_seq_afinfo tcp6_seq_afinfo = { | 2172 | static struct tcp_seq_afinfo tcp6_seq_afinfo = { |
| 2182 | .name = "tcp6", | 2173 | .name = "tcp6", |
| 2183 | .family = AF_INET6, | 2174 | .family = AF_INET6, |
| 2184 | .seq_fops = { | 2175 | .seq_fops = &tcp6_afinfo_seq_fops, |
| 2185 | .owner = THIS_MODULE, | ||
| 2186 | }, | ||
| 2187 | .seq_ops = { | 2176 | .seq_ops = { |
| 2188 | .show = tcp6_seq_show, | 2177 | .show = tcp6_seq_show, |
| 2189 | }, | 2178 | }, |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 29213b51c499..846f4757eb8d 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
| @@ -509,7 +509,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
| 509 | int is_udplite = IS_UDPLITE(sk); | 509 | int is_udplite = IS_UDPLITE(sk); |
| 510 | 510 | ||
| 511 | if (!ipv6_addr_any(&inet6_sk(sk)->daddr)) | 511 | if (!ipv6_addr_any(&inet6_sk(sk)->daddr)) |
| 512 | sock_rps_save_rxhash(sk, skb->rxhash); | 512 | sock_rps_save_rxhash(sk, skb); |
| 513 | 513 | ||
| 514 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 514 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
| 515 | goto drop; | 515 | goto drop; |
| @@ -533,7 +533,7 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
| 533 | } | 533 | } |
| 534 | } | 534 | } |
| 535 | 535 | ||
| 536 | if (rcu_dereference_raw(sk->sk_filter)) { | 536 | if (rcu_access_pointer(sk->sk_filter)) { |
| 537 | if (udp_lib_checksum_complete(skb)) | 537 | if (udp_lib_checksum_complete(skb)) |
| 538 | goto drop; | 538 | goto drop; |
| 539 | } | 539 | } |
| @@ -1090,8 +1090,8 @@ do_udp_sendmsg: | |||
| 1090 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 1090 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
| 1091 | opt->tot_len = sizeof(*opt); | 1091 | opt->tot_len = sizeof(*opt); |
| 1092 | 1092 | ||
| 1093 | err = datagram_send_ctl(sock_net(sk), msg, &fl6, opt, &hlimit, | 1093 | err = datagram_send_ctl(sock_net(sk), sk, msg, &fl6, opt, |
| 1094 | &tclass, &dontfrag); | 1094 | &hlimit, &tclass, &dontfrag); |
| 1095 | if (err < 0) { | 1095 | if (err < 0) { |
| 1096 | fl6_sock_release(flowlabel); | 1096 | fl6_sock_release(flowlabel); |
| 1097 | return err; | 1097 | return err; |
| @@ -1424,13 +1424,19 @@ int udp6_seq_show(struct seq_file *seq, void *v) | |||
| 1424 | return 0; | 1424 | return 0; |
| 1425 | } | 1425 | } |
| 1426 | 1426 | ||
| 1427 | static const struct file_operations udp6_afinfo_seq_fops = { | ||
| 1428 | .owner = THIS_MODULE, | ||
| 1429 | .open = udp_seq_open, | ||
| 1430 | .read = seq_read, | ||
| 1431 | .llseek = seq_lseek, | ||
| 1432 | .release = seq_release_net | ||
| 1433 | }; | ||
| 1434 | |||
| 1427 | static struct udp_seq_afinfo udp6_seq_afinfo = { | 1435 | static struct udp_seq_afinfo udp6_seq_afinfo = { |
| 1428 | .name = "udp6", | 1436 | .name = "udp6", |
| 1429 | .family = AF_INET6, | 1437 | .family = AF_INET6, |
| 1430 | .udp_table = &udp_table, | 1438 | .udp_table = &udp_table, |
| 1431 | .seq_fops = { | 1439 | .seq_fops = &udp6_afinfo_seq_fops, |
| 1432 | .owner = THIS_MODULE, | ||
| 1433 | }, | ||
| 1434 | .seq_ops = { | 1440 | .seq_ops = { |
| 1435 | .show = udp6_seq_show, | 1441 | .show = udp6_seq_show, |
| 1436 | }, | 1442 | }, |
diff --git a/net/ipv6/udplite.c b/net/ipv6/udplite.c index 986c4de5292e..1d08e21d9f69 100644 --- a/net/ipv6/udplite.c +++ b/net/ipv6/udplite.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | * as published by the Free Software Foundation; either version | 11 | * as published by the Free Software Foundation; either version |
| 12 | * 2 of the License, or (at your option) any later version. | 12 | * 2 of the License, or (at your option) any later version. |
| 13 | */ | 13 | */ |
| 14 | #include <linux/export.h> | ||
| 14 | #include "udp_impl.h" | 15 | #include "udp_impl.h" |
| 15 | 16 | ||
| 16 | static int udplitev6_rcv(struct sk_buff *skb) | 17 | static int udplitev6_rcv(struct sk_buff *skb) |
| @@ -93,13 +94,20 @@ void udplitev6_exit(void) | |||
| 93 | } | 94 | } |
| 94 | 95 | ||
| 95 | #ifdef CONFIG_PROC_FS | 96 | #ifdef CONFIG_PROC_FS |
| 97 | |||
| 98 | static const struct file_operations udplite6_afinfo_seq_fops = { | ||
| 99 | .owner = THIS_MODULE, | ||
| 100 | .open = udp_seq_open, | ||
| 101 | .read = seq_read, | ||
| 102 | .llseek = seq_lseek, | ||
| 103 | .release = seq_release_net | ||
| 104 | }; | ||
| 105 | |||
| 96 | static struct udp_seq_afinfo udplite6_seq_afinfo = { | 106 | static struct udp_seq_afinfo udplite6_seq_afinfo = { |
| 97 | .name = "udplite6", | 107 | .name = "udplite6", |
| 98 | .family = AF_INET6, | 108 | .family = AF_INET6, |
| 99 | .udp_table = &udplite_table, | 109 | .udp_table = &udplite_table, |
| 100 | .seq_fops = { | 110 | .seq_fops = &udplite6_afinfo_seq_fops, |
| 101 | .owner = THIS_MODULE, | ||
| 102 | }, | ||
| 103 | .seq_ops = { | 111 | .seq_ops = { |
| 104 | .show = udp6_seq_show, | 112 | .show = udp6_seq_show, |
| 105 | }, | 113 | }, |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 49a91c5f5623..faae41737fca 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
| @@ -28,6 +28,43 @@ int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, | |||
| 28 | 28 | ||
| 29 | EXPORT_SYMBOL(xfrm6_find_1stfragopt); | 29 | EXPORT_SYMBOL(xfrm6_find_1stfragopt); |
| 30 | 30 | ||
| 31 | static int xfrm6_local_dontfrag(struct sk_buff *skb) | ||
| 32 | { | ||
| 33 | int proto; | ||
| 34 | struct sock *sk = skb->sk; | ||
| 35 | |||
| 36 | if (sk) { | ||
| 37 | proto = sk->sk_protocol; | ||
| 38 | |||
| 39 | if (proto == IPPROTO_UDP || proto == IPPROTO_RAW) | ||
| 40 | return inet6_sk(sk)->dontfrag; | ||
| 41 | } | ||
| 42 | |||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 46 | static void xfrm6_local_rxpmtu(struct sk_buff *skb, u32 mtu) | ||
| 47 | { | ||
| 48 | struct flowi6 fl6; | ||
| 49 | struct sock *sk = skb->sk; | ||
| 50 | |||
| 51 | fl6.flowi6_oif = sk->sk_bound_dev_if; | ||
| 52 | ipv6_addr_copy(&fl6.daddr, &ipv6_hdr(skb)->daddr); | ||
| 53 | |||
| 54 | ipv6_local_rxpmtu(sk, &fl6, mtu); | ||
| 55 | } | ||
| 56 | |||
| 57 | static void xfrm6_local_error(struct sk_buff *skb, u32 mtu) | ||
| 58 | { | ||
| 59 | struct flowi6 fl6; | ||
| 60 | struct sock *sk = skb->sk; | ||
| 61 | |||
| 62 | fl6.fl6_dport = inet_sk(sk)->inet_dport; | ||
| 63 | ipv6_addr_copy(&fl6.daddr, &ipv6_hdr(skb)->daddr); | ||
| 64 | |||
| 65 | ipv6_local_error(sk, EMSGSIZE, &fl6, mtu); | ||
| 66 | } | ||
| 67 | |||
| 31 | static int xfrm6_tunnel_check_size(struct sk_buff *skb) | 68 | static int xfrm6_tunnel_check_size(struct sk_buff *skb) |
| 32 | { | 69 | { |
| 33 | int mtu, ret = 0; | 70 | int mtu, ret = 0; |
| @@ -39,7 +76,13 @@ static int xfrm6_tunnel_check_size(struct sk_buff *skb) | |||
| 39 | 76 | ||
| 40 | if (!skb->local_df && skb->len > mtu) { | 77 | if (!skb->local_df && skb->len > mtu) { |
| 41 | skb->dev = dst->dev; | 78 | skb->dev = dst->dev; |
| 42 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | 79 | |
| 80 | if (xfrm6_local_dontfrag(skb)) | ||
| 81 | xfrm6_local_rxpmtu(skb, mtu); | ||
| 82 | else if (skb->sk) | ||
| 83 | xfrm6_local_error(skb, mtu); | ||
| 84 | else | ||
| 85 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | ||
| 43 | ret = -EMSGSIZE; | 86 | ret = -EMSGSIZE; |
| 44 | } | 87 | } |
| 45 | 88 | ||
| @@ -93,9 +136,18 @@ static int __xfrm6_output(struct sk_buff *skb) | |||
| 93 | { | 136 | { |
| 94 | struct dst_entry *dst = skb_dst(skb); | 137 | struct dst_entry *dst = skb_dst(skb); |
| 95 | struct xfrm_state *x = dst->xfrm; | 138 | struct xfrm_state *x = dst->xfrm; |
| 139 | int mtu = ip6_skb_dst_mtu(skb); | ||
| 140 | |||
| 141 | if (skb->len > mtu && xfrm6_local_dontfrag(skb)) { | ||
| 142 | xfrm6_local_rxpmtu(skb, mtu); | ||
| 143 | return -EMSGSIZE; | ||
| 144 | } else if (!skb->local_df && skb->len > mtu && skb->sk) { | ||
| 145 | xfrm6_local_error(skb, mtu); | ||
| 146 | return -EMSGSIZE; | ||
| 147 | } | ||
| 96 | 148 | ||
| 97 | if ((x && x->props.mode == XFRM_MODE_TUNNEL) && | 149 | if ((x && x->props.mode == XFRM_MODE_TUNNEL) && |
| 98 | ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || | 150 | ((skb->len > mtu && !skb_is_gso(skb)) || |
| 99 | dst_allfrag(skb_dst(skb)))) { | 151 | dst_allfrag(skb_dst(skb)))) { |
| 100 | return ip6_fragment(skb, x->outer_mode->afinfo->output_finish); | 152 | return ip6_fragment(skb, x->outer_mode->afinfo->output_finish); |
| 101 | } | 153 | } |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index 248f0b2a7ee9..f2d72b8a3faa 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <linux/pfkeyv2.h> | 15 | #include <linux/pfkeyv2.h> |
| 16 | #include <linux/ipsec.h> | 16 | #include <linux/ipsec.h> |
| 17 | #include <linux/netfilter_ipv6.h> | 17 | #include <linux/netfilter_ipv6.h> |
| 18 | #include <linux/export.h> | ||
| 18 | #include <net/dsfield.h> | 19 | #include <net/dsfield.h> |
| 19 | #include <net/ipv6.h> | 20 | #include <net/ipv6.h> |
| 20 | #include <net/addrconf.h> | 21 | #include <net/addrconf.h> |
