diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2014-12-08 20:39:29 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2014-12-08 20:39:29 -0500 |
commit | ba00410b8131b23edfb0e09f8b6dd26c8eb621fb (patch) | |
tree | c08504e4d2fa51ac91cef544f336d0169806c49f /net/ipv6 | |
parent | 8ce74dd6057832618957fc2cbd38fa959c3a0a6c (diff) | |
parent | aa583096d9767892983332e7c1a984bd17e3cd39 (diff) |
Merge branch 'iov_iter' into for-next
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 1 | ||||
-rw-r--r-- | net/ipv6/ip6_gre.c | 5 | ||||
-rw-r--r-- | net/ipv6/ip6_offload.c | 2 | ||||
-rw-r--r-- | net/ipv6/ip6_tunnel.c | 10 | ||||
-rw-r--r-- | net/ipv6/ip6_vti.c | 11 | ||||
-rw-r--r-- | net/ipv6/ip6mr.c | 4 | ||||
-rw-r--r-- | net/ipv6/mcast.c | 9 | ||||
-rw-r--r-- | net/ipv6/netfilter/nf_reject_ipv6.c | 179 | ||||
-rw-r--r-- | net/ipv6/netfilter/nft_masq_ipv6.c | 2 | ||||
-rw-r--r-- | net/ipv6/output_core.c | 34 | ||||
-rw-r--r-- | net/ipv6/sit.c | 15 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 4 | ||||
-rw-r--r-- | net/ipv6/xfrm6_policy.c | 11 |
13 files changed, 181 insertions, 106 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 725c763270a0..0169ccf5aa4f 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -4531,6 +4531,7 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) | |||
4531 | } | 4531 | } |
4532 | 4532 | ||
4533 | write_unlock_bh(&idev->lock); | 4533 | write_unlock_bh(&idev->lock); |
4534 | inet6_ifinfo_notify(RTM_NEWLINK, idev); | ||
4534 | addrconf_verify_rtnl(); | 4535 | addrconf_verify_rtnl(); |
4535 | return 0; | 4536 | return 0; |
4536 | } | 4537 | } |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 12c3c8ef3849..4564e1fca3eb 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
@@ -961,8 +961,6 @@ static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu) | |||
961 | else | 961 | else |
962 | dev->flags &= ~IFF_POINTOPOINT; | 962 | dev->flags &= ~IFF_POINTOPOINT; |
963 | 963 | ||
964 | dev->iflink = p->link; | ||
965 | |||
966 | /* Precalculate GRE options length */ | 964 | /* Precalculate GRE options length */ |
967 | if (t->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) { | 965 | if (t->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) { |
968 | if (t->parms.o_flags&GRE_CSUM) | 966 | if (t->parms.o_flags&GRE_CSUM) |
@@ -1272,6 +1270,7 @@ static int ip6gre_tunnel_init(struct net_device *dev) | |||
1272 | u64_stats_init(&ip6gre_tunnel_stats->syncp); | 1270 | u64_stats_init(&ip6gre_tunnel_stats->syncp); |
1273 | } | 1271 | } |
1274 | 1272 | ||
1273 | dev->iflink = tunnel->parms.link; | ||
1275 | 1274 | ||
1276 | return 0; | 1275 | return 0; |
1277 | } | 1276 | } |
@@ -1481,6 +1480,8 @@ static int ip6gre_tap_init(struct net_device *dev) | |||
1481 | if (!dev->tstats) | 1480 | if (!dev->tstats) |
1482 | return -ENOMEM; | 1481 | return -ENOMEM; |
1483 | 1482 | ||
1483 | dev->iflink = tunnel->parms.link; | ||
1484 | |||
1484 | return 0; | 1485 | return 0; |
1485 | } | 1486 | } |
1486 | 1487 | ||
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c index 91014d32488d..a071563a7e6e 100644 --- a/net/ipv6/ip6_offload.c +++ b/net/ipv6/ip6_offload.c | |||
@@ -90,7 +90,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb, | |||
90 | 90 | ||
91 | encap = SKB_GSO_CB(skb)->encap_level > 0; | 91 | encap = SKB_GSO_CB(skb)->encap_level > 0; |
92 | if (encap) | 92 | if (encap) |
93 | features = skb->dev->hw_enc_features & netif_skb_features(skb); | 93 | features &= skb->dev->hw_enc_features; |
94 | SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h); | 94 | SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h); |
95 | 95 | ||
96 | ipv6h = ipv6_hdr(skb); | 96 | ipv6h = ipv6_hdr(skb); |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 9409887fb664..9cb94cfa0ae7 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -272,9 +272,6 @@ static int ip6_tnl_create2(struct net_device *dev) | |||
272 | int err; | 272 | int err; |
273 | 273 | ||
274 | t = netdev_priv(dev); | 274 | t = netdev_priv(dev); |
275 | err = ip6_tnl_dev_init(dev); | ||
276 | if (err < 0) | ||
277 | goto out; | ||
278 | 275 | ||
279 | err = register_netdevice(dev); | 276 | err = register_netdevice(dev); |
280 | if (err < 0) | 277 | if (err < 0) |
@@ -1462,6 +1459,7 @@ ip6_tnl_change_mtu(struct net_device *dev, int new_mtu) | |||
1462 | 1459 | ||
1463 | 1460 | ||
1464 | static const struct net_device_ops ip6_tnl_netdev_ops = { | 1461 | static const struct net_device_ops ip6_tnl_netdev_ops = { |
1462 | .ndo_init = ip6_tnl_dev_init, | ||
1465 | .ndo_uninit = ip6_tnl_dev_uninit, | 1463 | .ndo_uninit = ip6_tnl_dev_uninit, |
1466 | .ndo_start_xmit = ip6_tnl_xmit, | 1464 | .ndo_start_xmit = ip6_tnl_xmit, |
1467 | .ndo_do_ioctl = ip6_tnl_ioctl, | 1465 | .ndo_do_ioctl = ip6_tnl_ioctl, |
@@ -1546,16 +1544,10 @@ static int __net_init ip6_fb_tnl_dev_init(struct net_device *dev) | |||
1546 | struct ip6_tnl *t = netdev_priv(dev); | 1544 | struct ip6_tnl *t = netdev_priv(dev); |
1547 | struct net *net = dev_net(dev); | 1545 | struct net *net = dev_net(dev); |
1548 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | 1546 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); |
1549 | int err = ip6_tnl_dev_init_gen(dev); | ||
1550 | |||
1551 | if (err) | ||
1552 | return err; | ||
1553 | 1547 | ||
1554 | t->parms.proto = IPPROTO_IPV6; | 1548 | t->parms.proto = IPPROTO_IPV6; |
1555 | dev_hold(dev); | 1549 | dev_hold(dev); |
1556 | 1550 | ||
1557 | ip6_tnl_link_config(t); | ||
1558 | |||
1559 | rcu_assign_pointer(ip6n->tnls_wc[0], t); | 1551 | rcu_assign_pointer(ip6n->tnls_wc[0], t); |
1560 | return 0; | 1552 | return 0; |
1561 | } | 1553 | } |
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index d440bb585524..31089d153fd3 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c | |||
@@ -172,10 +172,6 @@ static int vti6_tnl_create2(struct net_device *dev) | |||
172 | struct vti6_net *ip6n = net_generic(net, vti6_net_id); | 172 | struct vti6_net *ip6n = net_generic(net, vti6_net_id); |
173 | int err; | 173 | int err; |
174 | 174 | ||
175 | err = vti6_dev_init(dev); | ||
176 | if (err < 0) | ||
177 | goto out; | ||
178 | |||
179 | err = register_netdevice(dev); | 175 | err = register_netdevice(dev); |
180 | if (err < 0) | 176 | if (err < 0) |
181 | goto out; | 177 | goto out; |
@@ -783,6 +779,7 @@ static int vti6_change_mtu(struct net_device *dev, int new_mtu) | |||
783 | } | 779 | } |
784 | 780 | ||
785 | static const struct net_device_ops vti6_netdev_ops = { | 781 | static const struct net_device_ops vti6_netdev_ops = { |
782 | .ndo_init = vti6_dev_init, | ||
786 | .ndo_uninit = vti6_dev_uninit, | 783 | .ndo_uninit = vti6_dev_uninit, |
787 | .ndo_start_xmit = vti6_tnl_xmit, | 784 | .ndo_start_xmit = vti6_tnl_xmit, |
788 | .ndo_do_ioctl = vti6_ioctl, | 785 | .ndo_do_ioctl = vti6_ioctl, |
@@ -852,16 +849,10 @@ static int __net_init vti6_fb_tnl_dev_init(struct net_device *dev) | |||
852 | struct ip6_tnl *t = netdev_priv(dev); | 849 | struct ip6_tnl *t = netdev_priv(dev); |
853 | struct net *net = dev_net(dev); | 850 | struct net *net = dev_net(dev); |
854 | struct vti6_net *ip6n = net_generic(net, vti6_net_id); | 851 | struct vti6_net *ip6n = net_generic(net, vti6_net_id); |
855 | int err = vti6_dev_init_gen(dev); | ||
856 | |||
857 | if (err) | ||
858 | return err; | ||
859 | 852 | ||
860 | t->parms.proto = IPPROTO_IPV6; | 853 | t->parms.proto = IPPROTO_IPV6; |
861 | dev_hold(dev); | 854 | dev_hold(dev); |
862 | 855 | ||
863 | vti6_link_config(t); | ||
864 | |||
865 | rcu_assign_pointer(ip6n->tnls_wc[0], t); | 856 | rcu_assign_pointer(ip6n->tnls_wc[0], t); |
866 | return 0; | 857 | return 0; |
867 | } | 858 | } |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 0171f08325c3..1a01d79b8698 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -1439,6 +1439,10 @@ reg_pernet_fail: | |||
1439 | 1439 | ||
1440 | void ip6_mr_cleanup(void) | 1440 | void ip6_mr_cleanup(void) |
1441 | { | 1441 | { |
1442 | rtnl_unregister(RTNL_FAMILY_IP6MR, RTM_GETROUTE); | ||
1443 | #ifdef CONFIG_IPV6_PIMSM_V2 | ||
1444 | inet6_del_protocol(&pim6_protocol, IPPROTO_PIM); | ||
1445 | #endif | ||
1442 | unregister_netdevice_notifier(&ip6_mr_notifier); | 1446 | unregister_netdevice_notifier(&ip6_mr_notifier); |
1443 | unregister_pernet_subsys(&ip6mr_net_ops); | 1447 | unregister_pernet_subsys(&ip6mr_net_ops); |
1444 | kmem_cache_destroy(mrt_cachep); | 1448 | kmem_cache_destroy(mrt_cachep); |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 9648de2b6745..ed2c4e400b46 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -1550,7 +1550,7 @@ static void ip6_mc_hdr(struct sock *sk, struct sk_buff *skb, | |||
1550 | hdr->daddr = *daddr; | 1550 | hdr->daddr = *daddr; |
1551 | } | 1551 | } |
1552 | 1552 | ||
1553 | static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size) | 1553 | static struct sk_buff *mld_newpack(struct inet6_dev *idev, unsigned int mtu) |
1554 | { | 1554 | { |
1555 | struct net_device *dev = idev->dev; | 1555 | struct net_device *dev = idev->dev; |
1556 | struct net *net = dev_net(dev); | 1556 | struct net *net = dev_net(dev); |
@@ -1561,13 +1561,13 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size) | |||
1561 | const struct in6_addr *saddr; | 1561 | const struct in6_addr *saddr; |
1562 | int hlen = LL_RESERVED_SPACE(dev); | 1562 | int hlen = LL_RESERVED_SPACE(dev); |
1563 | int tlen = dev->needed_tailroom; | 1563 | int tlen = dev->needed_tailroom; |
1564 | unsigned int size = mtu + hlen + tlen; | ||
1564 | int err; | 1565 | int err; |
1565 | u8 ra[8] = { IPPROTO_ICMPV6, 0, | 1566 | u8 ra[8] = { IPPROTO_ICMPV6, 0, |
1566 | IPV6_TLV_ROUTERALERT, 2, 0, 0, | 1567 | IPV6_TLV_ROUTERALERT, 2, 0, 0, |
1567 | IPV6_TLV_PADN, 0 }; | 1568 | IPV6_TLV_PADN, 0 }; |
1568 | 1569 | ||
1569 | /* we assume size > sizeof(ra) here */ | 1570 | /* we assume size > sizeof(ra) here */ |
1570 | size += hlen + tlen; | ||
1571 | /* limit our allocations to order-0 page */ | 1571 | /* limit our allocations to order-0 page */ |
1572 | size = min_t(int, size, SKB_MAX_ORDER(0, 0)); | 1572 | size = min_t(int, size, SKB_MAX_ORDER(0, 0)); |
1573 | skb = sock_alloc_send_skb(sk, size, 1, &err); | 1573 | skb = sock_alloc_send_skb(sk, size, 1, &err); |
@@ -1576,6 +1576,8 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size) | |||
1576 | return NULL; | 1576 | return NULL; |
1577 | 1577 | ||
1578 | skb->priority = TC_PRIO_CONTROL; | 1578 | skb->priority = TC_PRIO_CONTROL; |
1579 | skb->reserved_tailroom = skb_end_offset(skb) - | ||
1580 | min(mtu, skb_end_offset(skb)); | ||
1579 | skb_reserve(skb, hlen); | 1581 | skb_reserve(skb, hlen); |
1580 | 1582 | ||
1581 | if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) { | 1583 | if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) { |
@@ -1690,8 +1692,7 @@ static struct sk_buff *add_grhead(struct sk_buff *skb, struct ifmcaddr6 *pmc, | |||
1690 | return skb; | 1692 | return skb; |
1691 | } | 1693 | } |
1692 | 1694 | ||
1693 | #define AVAILABLE(skb) ((skb) ? ((skb)->dev ? (skb)->dev->mtu - (skb)->len : \ | 1695 | #define AVAILABLE(skb) ((skb) ? skb_availroom(skb) : 0) |
1694 | skb_tailroom(skb)) : 0) | ||
1695 | 1696 | ||
1696 | static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, | 1697 | static struct sk_buff *add_grec(struct sk_buff *skb, struct ifmcaddr6 *pmc, |
1697 | int type, int gdeleted, int sdeleted, int crsend) | 1698 | int type, int gdeleted, int sdeleted, int crsend) |
diff --git a/net/ipv6/netfilter/nf_reject_ipv6.c b/net/ipv6/netfilter/nf_reject_ipv6.c index 5f5f0438d74d..015eb8a80766 100644 --- a/net/ipv6/netfilter/nf_reject_ipv6.c +++ b/net/ipv6/netfilter/nf_reject_ipv6.c | |||
@@ -5,121 +5,109 @@ | |||
5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | |||
9 | #include <linux/module.h> | ||
8 | #include <net/ipv6.h> | 10 | #include <net/ipv6.h> |
9 | #include <net/ip6_route.h> | 11 | #include <net/ip6_route.h> |
10 | #include <net/ip6_fib.h> | 12 | #include <net/ip6_fib.h> |
11 | #include <net/ip6_checksum.h> | 13 | #include <net/ip6_checksum.h> |
12 | #include <linux/netfilter_ipv6.h> | 14 | #include <linux/netfilter_ipv6.h> |
15 | #include <net/netfilter/ipv6/nf_reject.h> | ||
13 | 16 | ||
14 | void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) | 17 | const struct tcphdr *nf_reject_ip6_tcphdr_get(struct sk_buff *oldskb, |
18 | struct tcphdr *otcph, | ||
19 | unsigned int *otcplen, int hook) | ||
15 | { | 20 | { |
16 | struct sk_buff *nskb; | ||
17 | struct tcphdr otcph, *tcph; | ||
18 | unsigned int otcplen, hh_len; | ||
19 | int tcphoff, needs_ack; | ||
20 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); | 21 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); |
21 | struct ipv6hdr *ip6h; | ||
22 | #define DEFAULT_TOS_VALUE 0x0U | ||
23 | const __u8 tclass = DEFAULT_TOS_VALUE; | ||
24 | struct dst_entry *dst = NULL; | ||
25 | u8 proto; | 22 | u8 proto; |
26 | __be16 frag_off; | 23 | __be16 frag_off; |
27 | struct flowi6 fl6; | 24 | int tcphoff; |
28 | |||
29 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || | ||
30 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { | ||
31 | pr_debug("addr is not unicast.\n"); | ||
32 | return; | ||
33 | } | ||
34 | 25 | ||
35 | proto = oip6h->nexthdr; | 26 | proto = oip6h->nexthdr; |
36 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), &proto, &frag_off); | 27 | tcphoff = ipv6_skip_exthdr(oldskb, ((u8*)(oip6h+1) - oldskb->data), |
28 | &proto, &frag_off); | ||
37 | 29 | ||
38 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { | 30 | if ((tcphoff < 0) || (tcphoff > oldskb->len)) { |
39 | pr_debug("Cannot get TCP header.\n"); | 31 | pr_debug("Cannot get TCP header.\n"); |
40 | return; | 32 | return NULL; |
41 | } | 33 | } |
42 | 34 | ||
43 | otcplen = oldskb->len - tcphoff; | 35 | *otcplen = oldskb->len - tcphoff; |
44 | 36 | ||
45 | /* IP header checks: fragment, too short. */ | 37 | /* IP header checks: fragment, too short. */ |
46 | if (proto != IPPROTO_TCP || otcplen < sizeof(struct tcphdr)) { | 38 | if (proto != IPPROTO_TCP || *otcplen < sizeof(struct tcphdr)) { |
47 | pr_debug("proto(%d) != IPPROTO_TCP, " | 39 | pr_debug("proto(%d) != IPPROTO_TCP or too short (len = %d)\n", |
48 | "or too short. otcplen = %d\n", | 40 | proto, *otcplen); |
49 | proto, otcplen); | 41 | return NULL; |
50 | return; | ||
51 | } | 42 | } |
52 | 43 | ||
53 | if (skb_copy_bits(oldskb, tcphoff, &otcph, sizeof(struct tcphdr))) | 44 | otcph = skb_header_pointer(oldskb, tcphoff, sizeof(struct tcphdr), |
54 | BUG(); | 45 | otcph); |
46 | if (otcph == NULL) | ||
47 | return NULL; | ||
55 | 48 | ||
56 | /* No RST for RST. */ | 49 | /* No RST for RST. */ |
57 | if (otcph.rst) { | 50 | if (otcph->rst) { |
58 | pr_debug("RST is set\n"); | 51 | pr_debug("RST is set\n"); |
59 | return; | 52 | return NULL; |
60 | } | 53 | } |
61 | 54 | ||
62 | /* Check checksum. */ | 55 | /* Check checksum. */ |
63 | if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) { | 56 | if (nf_ip6_checksum(oldskb, hook, tcphoff, IPPROTO_TCP)) { |
64 | pr_debug("TCP checksum is invalid\n"); | 57 | pr_debug("TCP checksum is invalid\n"); |
65 | return; | 58 | return NULL; |
66 | } | 59 | } |
67 | 60 | ||
68 | memset(&fl6, 0, sizeof(fl6)); | 61 | return otcph; |
69 | fl6.flowi6_proto = IPPROTO_TCP; | 62 | } |
70 | fl6.saddr = oip6h->daddr; | 63 | EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_get); |
71 | fl6.daddr = oip6h->saddr; | ||
72 | fl6.fl6_sport = otcph.dest; | ||
73 | fl6.fl6_dport = otcph.source; | ||
74 | security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); | ||
75 | dst = ip6_route_output(net, NULL, &fl6); | ||
76 | if (dst == NULL || dst->error) { | ||
77 | dst_release(dst); | ||
78 | return; | ||
79 | } | ||
80 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); | ||
81 | if (IS_ERR(dst)) | ||
82 | return; | ||
83 | |||
84 | hh_len = (dst->dev->hard_header_len + 15)&~15; | ||
85 | nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr) | ||
86 | + sizeof(struct tcphdr) + dst->trailer_len, | ||
87 | GFP_ATOMIC); | ||
88 | |||
89 | if (!nskb) { | ||
90 | net_dbg_ratelimited("cannot alloc skb\n"); | ||
91 | dst_release(dst); | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | skb_dst_set(nskb, dst); | ||
96 | 64 | ||
97 | skb_reserve(nskb, hh_len + dst->header_len); | 65 | struct ipv6hdr *nf_reject_ip6hdr_put(struct sk_buff *nskb, |
66 | const struct sk_buff *oldskb, | ||
67 | __be16 protocol, int hoplimit) | ||
68 | { | ||
69 | struct ipv6hdr *ip6h; | ||
70 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); | ||
71 | #define DEFAULT_TOS_VALUE 0x0U | ||
72 | const __u8 tclass = DEFAULT_TOS_VALUE; | ||
98 | 73 | ||
99 | skb_put(nskb, sizeof(struct ipv6hdr)); | 74 | skb_put(nskb, sizeof(struct ipv6hdr)); |
100 | skb_reset_network_header(nskb); | 75 | skb_reset_network_header(nskb); |
101 | ip6h = ipv6_hdr(nskb); | 76 | ip6h = ipv6_hdr(nskb); |
102 | ip6_flow_hdr(ip6h, tclass, 0); | 77 | ip6_flow_hdr(ip6h, tclass, 0); |
103 | ip6h->hop_limit = ip6_dst_hoplimit(dst); | 78 | ip6h->hop_limit = hoplimit; |
104 | ip6h->nexthdr = IPPROTO_TCP; | 79 | ip6h->nexthdr = protocol; |
105 | ip6h->saddr = oip6h->daddr; | 80 | ip6h->saddr = oip6h->daddr; |
106 | ip6h->daddr = oip6h->saddr; | 81 | ip6h->daddr = oip6h->saddr; |
107 | 82 | ||
83 | nskb->protocol = htons(ETH_P_IPV6); | ||
84 | |||
85 | return ip6h; | ||
86 | } | ||
87 | EXPORT_SYMBOL_GPL(nf_reject_ip6hdr_put); | ||
88 | |||
89 | void nf_reject_ip6_tcphdr_put(struct sk_buff *nskb, | ||
90 | const struct sk_buff *oldskb, | ||
91 | const struct tcphdr *oth, unsigned int otcplen) | ||
92 | { | ||
93 | struct tcphdr *tcph; | ||
94 | int needs_ack; | ||
95 | |||
108 | skb_reset_transport_header(nskb); | 96 | skb_reset_transport_header(nskb); |
109 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); | 97 | tcph = (struct tcphdr *)skb_put(nskb, sizeof(struct tcphdr)); |
110 | /* Truncate to length (no data) */ | 98 | /* Truncate to length (no data) */ |
111 | tcph->doff = sizeof(struct tcphdr)/4; | 99 | tcph->doff = sizeof(struct tcphdr)/4; |
112 | tcph->source = otcph.dest; | 100 | tcph->source = oth->dest; |
113 | tcph->dest = otcph.source; | 101 | tcph->dest = oth->source; |
114 | 102 | ||
115 | if (otcph.ack) { | 103 | if (oth->ack) { |
116 | needs_ack = 0; | 104 | needs_ack = 0; |
117 | tcph->seq = otcph.ack_seq; | 105 | tcph->seq = oth->ack_seq; |
118 | tcph->ack_seq = 0; | 106 | tcph->ack_seq = 0; |
119 | } else { | 107 | } else { |
120 | needs_ack = 1; | 108 | needs_ack = 1; |
121 | tcph->ack_seq = htonl(ntohl(otcph.seq) + otcph.syn + otcph.fin | 109 | tcph->ack_seq = htonl(ntohl(oth->seq) + oth->syn + oth->fin + |
122 | + otcplen - (otcph.doff<<2)); | 110 | otcplen - (oth->doff<<2)); |
123 | tcph->seq = 0; | 111 | tcph->seq = 0; |
124 | } | 112 | } |
125 | 113 | ||
@@ -137,6 +125,63 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) | |||
137 | sizeof(struct tcphdr), IPPROTO_TCP, | 125 | sizeof(struct tcphdr), IPPROTO_TCP, |
138 | csum_partial(tcph, | 126 | csum_partial(tcph, |
139 | sizeof(struct tcphdr), 0)); | 127 | sizeof(struct tcphdr), 0)); |
128 | } | ||
129 | EXPORT_SYMBOL_GPL(nf_reject_ip6_tcphdr_put); | ||
130 | |||
131 | void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) | ||
132 | { | ||
133 | struct sk_buff *nskb; | ||
134 | struct tcphdr _otcph; | ||
135 | const struct tcphdr *otcph; | ||
136 | unsigned int otcplen, hh_len; | ||
137 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); | ||
138 | struct ipv6hdr *ip6h; | ||
139 | struct dst_entry *dst = NULL; | ||
140 | struct flowi6 fl6; | ||
141 | |||
142 | if ((!(ipv6_addr_type(&oip6h->saddr) & IPV6_ADDR_UNICAST)) || | ||
143 | (!(ipv6_addr_type(&oip6h->daddr) & IPV6_ADDR_UNICAST))) { | ||
144 | pr_debug("addr is not unicast.\n"); | ||
145 | return; | ||
146 | } | ||
147 | |||
148 | otcph = nf_reject_ip6_tcphdr_get(oldskb, &_otcph, &otcplen, hook); | ||
149 | if (!otcph) | ||
150 | return; | ||
151 | |||
152 | memset(&fl6, 0, sizeof(fl6)); | ||
153 | fl6.flowi6_proto = IPPROTO_TCP; | ||
154 | fl6.saddr = oip6h->daddr; | ||
155 | fl6.daddr = oip6h->saddr; | ||
156 | fl6.fl6_sport = otcph->dest; | ||
157 | fl6.fl6_dport = otcph->source; | ||
158 | security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6)); | ||
159 | dst = ip6_route_output(net, NULL, &fl6); | ||
160 | if (dst == NULL || dst->error) { | ||
161 | dst_release(dst); | ||
162 | return; | ||
163 | } | ||
164 | dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), NULL, 0); | ||
165 | if (IS_ERR(dst)) | ||
166 | return; | ||
167 | |||
168 | hh_len = (dst->dev->hard_header_len + 15)&~15; | ||
169 | nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr) | ||
170 | + sizeof(struct tcphdr) + dst->trailer_len, | ||
171 | GFP_ATOMIC); | ||
172 | |||
173 | if (!nskb) { | ||
174 | net_dbg_ratelimited("cannot alloc skb\n"); | ||
175 | dst_release(dst); | ||
176 | return; | ||
177 | } | ||
178 | |||
179 | skb_dst_set(nskb, dst); | ||
180 | |||
181 | skb_reserve(nskb, hh_len + dst->header_len); | ||
182 | ip6h = nf_reject_ip6hdr_put(nskb, oldskb, IPPROTO_TCP, | ||
183 | ip6_dst_hoplimit(dst)); | ||
184 | nf_reject_ip6_tcphdr_put(nskb, oldskb, otcph, otcplen); | ||
140 | 185 | ||
141 | nf_ct_attach(nskb, oldskb); | 186 | nf_ct_attach(nskb, oldskb); |
142 | 187 | ||
@@ -161,3 +206,5 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook) | |||
161 | ip6_local_out(nskb); | 206 | ip6_local_out(nskb); |
162 | } | 207 | } |
163 | EXPORT_SYMBOL_GPL(nf_send_reset6); | 208 | EXPORT_SYMBOL_GPL(nf_send_reset6); |
209 | |||
210 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv6/netfilter/nft_masq_ipv6.c b/net/ipv6/netfilter/nft_masq_ipv6.c index 556262f40761..529c119cbb14 100644 --- a/net/ipv6/netfilter/nft_masq_ipv6.c +++ b/net/ipv6/netfilter/nft_masq_ipv6.c | |||
@@ -25,6 +25,7 @@ static void nft_masq_ipv6_eval(const struct nft_expr *expr, | |||
25 | struct nf_nat_range range; | 25 | struct nf_nat_range range; |
26 | unsigned int verdict; | 26 | unsigned int verdict; |
27 | 27 | ||
28 | memset(&range, 0, sizeof(range)); | ||
28 | range.flags = priv->flags; | 29 | range.flags = priv->flags; |
29 | 30 | ||
30 | verdict = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out); | 31 | verdict = nf_nat_masquerade_ipv6(pkt->skb, &range, pkt->out); |
@@ -39,6 +40,7 @@ static const struct nft_expr_ops nft_masq_ipv6_ops = { | |||
39 | .eval = nft_masq_ipv6_eval, | 40 | .eval = nft_masq_ipv6_eval, |
40 | .init = nft_masq_init, | 41 | .init = nft_masq_init, |
41 | .dump = nft_masq_dump, | 42 | .dump = nft_masq_dump, |
43 | .validate = nft_masq_validate, | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | static struct nft_expr_type nft_masq_ipv6_type __read_mostly = { | 46 | static struct nft_expr_type nft_masq_ipv6_type __read_mostly = { |
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index fc24c390af05..97f41a3e68d9 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c | |||
@@ -3,11 +3,45 @@ | |||
3 | * not configured or static. These functions are needed by GSO/GRO implementation. | 3 | * not configured or static. These functions are needed by GSO/GRO implementation. |
4 | */ | 4 | */ |
5 | #include <linux/export.h> | 5 | #include <linux/export.h> |
6 | #include <net/ip.h> | ||
6 | #include <net/ipv6.h> | 7 | #include <net/ipv6.h> |
7 | #include <net/ip6_fib.h> | 8 | #include <net/ip6_fib.h> |
8 | #include <net/addrconf.h> | 9 | #include <net/addrconf.h> |
9 | #include <net/secure_seq.h> | 10 | #include <net/secure_seq.h> |
10 | 11 | ||
12 | /* This function exists only for tap drivers that must support broken | ||
13 | * clients requesting UFO without specifying an IPv6 fragment ID. | ||
14 | * | ||
15 | * This is similar to ipv6_select_ident() but we use an independent hash | ||
16 | * seed to limit information leakage. | ||
17 | * | ||
18 | * The network header must be set before calling this. | ||
19 | */ | ||
20 | void ipv6_proxy_select_ident(struct sk_buff *skb) | ||
21 | { | ||
22 | static u32 ip6_proxy_idents_hashrnd __read_mostly; | ||
23 | struct in6_addr buf[2]; | ||
24 | struct in6_addr *addrs; | ||
25 | u32 hash, id; | ||
26 | |||
27 | addrs = skb_header_pointer(skb, | ||
28 | skb_network_offset(skb) + | ||
29 | offsetof(struct ipv6hdr, saddr), | ||
30 | sizeof(buf), buf); | ||
31 | if (!addrs) | ||
32 | return; | ||
33 | |||
34 | net_get_random_once(&ip6_proxy_idents_hashrnd, | ||
35 | sizeof(ip6_proxy_idents_hashrnd)); | ||
36 | |||
37 | hash = __ipv6_addr_jhash(&addrs[1], ip6_proxy_idents_hashrnd); | ||
38 | hash = __ipv6_addr_jhash(&addrs[0], hash); | ||
39 | |||
40 | id = ip_idents_reserve(hash, 1); | ||
41 | skb_shinfo(skb)->ip6_frag_id = htonl(id); | ||
42 | } | ||
43 | EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident); | ||
44 | |||
11 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) | 45 | int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr) |
12 | { | 46 | { |
13 | u16 offset = sizeof(struct ipv6hdr); | 47 | u16 offset = sizeof(struct ipv6hdr); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 58e5b4710127..a24557a1c1d8 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -195,10 +195,8 @@ static int ipip6_tunnel_create(struct net_device *dev) | |||
195 | struct sit_net *sitn = net_generic(net, sit_net_id); | 195 | struct sit_net *sitn = net_generic(net, sit_net_id); |
196 | int err; | 196 | int err; |
197 | 197 | ||
198 | err = ipip6_tunnel_init(dev); | 198 | memcpy(dev->dev_addr, &t->parms.iph.saddr, 4); |
199 | if (err < 0) | 199 | memcpy(dev->broadcast, &t->parms.iph.daddr, 4); |
200 | goto out; | ||
201 | ipip6_tunnel_clone_6rd(dev, sitn); | ||
202 | 200 | ||
203 | if ((__force u16)t->parms.i_flags & SIT_ISATAP) | 201 | if ((__force u16)t->parms.i_flags & SIT_ISATAP) |
204 | dev->priv_flags |= IFF_ISATAP; | 202 | dev->priv_flags |= IFF_ISATAP; |
@@ -207,7 +205,8 @@ static int ipip6_tunnel_create(struct net_device *dev) | |||
207 | if (err < 0) | 205 | if (err < 0) |
208 | goto out; | 206 | goto out; |
209 | 207 | ||
210 | strcpy(t->parms.name, dev->name); | 208 | ipip6_tunnel_clone_6rd(dev, sitn); |
209 | |||
211 | dev->rtnl_link_ops = &sit_link_ops; | 210 | dev->rtnl_link_ops = &sit_link_ops; |
212 | 211 | ||
213 | dev_hold(dev); | 212 | dev_hold(dev); |
@@ -1330,6 +1329,7 @@ static int ipip6_tunnel_change_mtu(struct net_device *dev, int new_mtu) | |||
1330 | } | 1329 | } |
1331 | 1330 | ||
1332 | static const struct net_device_ops ipip6_netdev_ops = { | 1331 | static const struct net_device_ops ipip6_netdev_ops = { |
1332 | .ndo_init = ipip6_tunnel_init, | ||
1333 | .ndo_uninit = ipip6_tunnel_uninit, | 1333 | .ndo_uninit = ipip6_tunnel_uninit, |
1334 | .ndo_start_xmit = sit_tunnel_xmit, | 1334 | .ndo_start_xmit = sit_tunnel_xmit, |
1335 | .ndo_do_ioctl = ipip6_tunnel_ioctl, | 1335 | .ndo_do_ioctl = ipip6_tunnel_ioctl, |
@@ -1378,9 +1378,7 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
1378 | 1378 | ||
1379 | tunnel->dev = dev; | 1379 | tunnel->dev = dev; |
1380 | tunnel->net = dev_net(dev); | 1380 | tunnel->net = dev_net(dev); |
1381 | 1381 | strcpy(tunnel->parms.name, dev->name); | |
1382 | memcpy(dev->dev_addr, &tunnel->parms.iph.saddr, 4); | ||
1383 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); | ||
1384 | 1382 | ||
1385 | ipip6_tunnel_bind_dev(dev); | 1383 | ipip6_tunnel_bind_dev(dev); |
1386 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); | 1384 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
@@ -1405,7 +1403,6 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
1405 | 1403 | ||
1406 | tunnel->dev = dev; | 1404 | tunnel->dev = dev; |
1407 | tunnel->net = dev_net(dev); | 1405 | tunnel->net = dev_net(dev); |
1408 | strcpy(tunnel->parms.name, dev->name); | ||
1409 | 1406 | ||
1410 | iph->version = 4; | 1407 | iph->version = 4; |
1411 | iph->protocol = IPPROTO_IPV6; | 1408 | iph->protocol = IPPROTO_IPV6; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 831495529b82..ace29b60813c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -200,8 +200,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
200 | sk->sk_v6_daddr = usin->sin6_addr; | 200 | sk->sk_v6_daddr = usin->sin6_addr; |
201 | np->flow_label = fl6.flowlabel; | 201 | np->flow_label = fl6.flowlabel; |
202 | 202 | ||
203 | ip6_set_txhash(sk); | ||
204 | |||
205 | /* | 203 | /* |
206 | * TCP over IPv4 | 204 | * TCP over IPv4 |
207 | */ | 205 | */ |
@@ -297,6 +295,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
297 | if (err) | 295 | if (err) |
298 | goto late_failure; | 296 | goto late_failure; |
299 | 297 | ||
298 | ip6_set_txhash(sk); | ||
299 | |||
300 | if (!tp->write_seq && likely(!tp->repair)) | 300 | if (!tp->write_seq && likely(!tp->repair)) |
301 | tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32, | 301 | tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32, |
302 | sk->sk_v6_daddr.s6_addr32, | 302 | sk->sk_v6_daddr.s6_addr32, |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index ac49f84fe2c3..5f983644373a 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -170,8 +170,10 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
170 | case IPPROTO_DCCP: | 170 | case IPPROTO_DCCP: |
171 | if (!onlyproto && (nh + offset + 4 < skb->data || | 171 | if (!onlyproto && (nh + offset + 4 < skb->data || |
172 | pskb_may_pull(skb, nh + offset + 4 - skb->data))) { | 172 | pskb_may_pull(skb, nh + offset + 4 - skb->data))) { |
173 | __be16 *ports = (__be16 *)exthdr; | 173 | __be16 *ports; |
174 | 174 | ||
175 | nh = skb_network_header(skb); | ||
176 | ports = (__be16 *)(nh + offset); | ||
175 | fl6->fl6_sport = ports[!!reverse]; | 177 | fl6->fl6_sport = ports[!!reverse]; |
176 | fl6->fl6_dport = ports[!reverse]; | 178 | fl6->fl6_dport = ports[!reverse]; |
177 | } | 179 | } |
@@ -180,8 +182,10 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
180 | 182 | ||
181 | case IPPROTO_ICMPV6: | 183 | case IPPROTO_ICMPV6: |
182 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) { | 184 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 2 - skb->data)) { |
183 | u8 *icmp = (u8 *)exthdr; | 185 | u8 *icmp; |
184 | 186 | ||
187 | nh = skb_network_header(skb); | ||
188 | icmp = (u8 *)(nh + offset); | ||
185 | fl6->fl6_icmp_type = icmp[0]; | 189 | fl6->fl6_icmp_type = icmp[0]; |
186 | fl6->fl6_icmp_code = icmp[1]; | 190 | fl6->fl6_icmp_code = icmp[1]; |
187 | } | 191 | } |
@@ -192,8 +196,9 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
192 | case IPPROTO_MH: | 196 | case IPPROTO_MH: |
193 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) { | 197 | if (!onlyproto && pskb_may_pull(skb, nh + offset + 3 - skb->data)) { |
194 | struct ip6_mh *mh; | 198 | struct ip6_mh *mh; |
195 | mh = (struct ip6_mh *)exthdr; | ||
196 | 199 | ||
200 | nh = skb_network_header(skb); | ||
201 | mh = (struct ip6_mh *)(nh + offset); | ||
197 | fl6->fl6_mh_type = mh->ip6mh_type; | 202 | fl6->fl6_mh_type = mh->ip6mh_type; |
198 | } | 203 | } |
199 | fl6->flowi6_proto = nexthdr; | 204 | fl6->flowi6_proto = nexthdr; |