aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/core/pktgen.c2
-rw-r--r--net/ipv4/Kconfig29
-rw-r--r--net/ipv4/Makefile3
-rw-r--r--net/ipv4/esp4_offload.c50
-rw-r--r--net/ipv4/ip_vti.c66
-rw-r--r--net/ipv4/xfrm4_mode_beet.c155
-rw-r--r--net/ipv4/xfrm4_mode_transport.c114
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c152
-rw-r--r--net/ipv4/xfrm4_output.c27
-rw-r--r--net/ipv4/xfrm4_policy.c127
-rw-r--r--net/ipv4/xfrm4_protocol.c3
-rw-r--r--net/ipv6/Kconfig35
-rw-r--r--net/ipv6/Makefile4
-rw-r--r--net/ipv6/esp6_offload.c40
-rw-r--r--net/ipv6/ip6_vti.c6
-rw-r--r--net/ipv6/xfrm6_mode_beet.c131
-rw-r--r--net/ipv6/xfrm6_mode_ro.c85
-rw-r--r--net/ipv6/xfrm6_mode_transport.c121
-rw-r--r--net/ipv6/xfrm6_mode_tunnel.c151
-rw-r--r--net/ipv6/xfrm6_output.c36
-rw-r--r--net/ipv6/xfrm6_policy.c126
-rw-r--r--net/ipv6/xfrm6_protocol.c3
-rw-r--r--net/xfrm/Kconfig8
-rw-r--r--net/xfrm/xfrm_device.c61
-rw-r--r--net/xfrm/xfrm_inout.h38
-rw-r--r--net/xfrm/xfrm_input.c299
-rw-r--r--net/xfrm/xfrm_interface.c6
-rw-r--r--net/xfrm/xfrm_output.c381
-rw-r--r--net/xfrm/xfrm_policy.c280
-rw-r--r--net/xfrm/xfrm_state.c186
30 files changed, 1226 insertions, 1499 deletions
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index f3f5a78cd062..319ad5490fb3 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2521,7 +2521,7 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev)
2521 skb->_skb_refdst = (unsigned long)&pkt_dev->xdst.u.dst | SKB_DST_NOREF; 2521 skb->_skb_refdst = (unsigned long)&pkt_dev->xdst.u.dst | SKB_DST_NOREF;
2522 2522
2523 rcu_read_lock_bh(); 2523 rcu_read_lock_bh();
2524 err = x->outer_mode->output(x, skb); 2524 err = pktgen_xfrm_outer_mode_output(x, skb);
2525 rcu_read_unlock_bh(); 2525 rcu_read_unlock_bh();
2526 if (err) { 2526 if (err) {
2527 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR); 2527 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR);
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig
index 32cae39cdff6..8108e97d4285 100644
--- a/net/ipv4/Kconfig
+++ b/net/ipv4/Kconfig
@@ -304,7 +304,7 @@ config NET_IPVTI
304 tristate "Virtual (secure) IP: tunneling" 304 tristate "Virtual (secure) IP: tunneling"
305 select INET_TUNNEL 305 select INET_TUNNEL
306 select NET_IP_TUNNEL 306 select NET_IP_TUNNEL
307 depends on INET_XFRM_MODE_TUNNEL 307 select XFRM
308 ---help--- 308 ---help---
309 Tunneling means encapsulating data of one protocol type within 309 Tunneling means encapsulating data of one protocol type within
310 another protocol and sending it over a channel that understands the 310 another protocol and sending it over a channel that understands the
@@ -396,33 +396,6 @@ config INET_TUNNEL
396 tristate 396 tristate
397 default n 397 default n
398 398
399config INET_XFRM_MODE_TRANSPORT
400 tristate "IP: IPsec transport mode"
401 default y
402 select XFRM
403 ---help---
404 Support for IPsec transport mode.
405
406 If unsure, say Y.
407
408config INET_XFRM_MODE_TUNNEL
409 tristate "IP: IPsec tunnel mode"
410 default y
411 select XFRM
412 ---help---
413 Support for IPsec tunnel mode.
414
415 If unsure, say Y.
416
417config INET_XFRM_MODE_BEET
418 tristate "IP: IPsec BEET mode"
419 default y
420 select XFRM
421 ---help---
422 Support for IPsec BEET mode.
423
424 If unsure, say Y.
425
426config INET_DIAG 399config INET_DIAG
427 tristate "INET: socket monitoring interface" 400 tristate "INET: socket monitoring interface"
428 default y 401 default y
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index 58629314eae9..000a61994c8f 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -37,10 +37,7 @@ obj-$(CONFIG_INET_ESP) += esp4.o
37obj-$(CONFIG_INET_ESP_OFFLOAD) += esp4_offload.o 37obj-$(CONFIG_INET_ESP_OFFLOAD) += esp4_offload.o
38obj-$(CONFIG_INET_IPCOMP) += ipcomp.o 38obj-$(CONFIG_INET_IPCOMP) += ipcomp.o
39obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o 39obj-$(CONFIG_INET_XFRM_TUNNEL) += xfrm4_tunnel.o
40obj-$(CONFIG_INET_XFRM_MODE_BEET) += xfrm4_mode_beet.o
41obj-$(CONFIG_INET_TUNNEL) += tunnel4.o 40obj-$(CONFIG_INET_TUNNEL) += tunnel4.o
42obj-$(CONFIG_INET_XFRM_MODE_TRANSPORT) += xfrm4_mode_transport.o
43obj-$(CONFIG_INET_XFRM_MODE_TUNNEL) += xfrm4_mode_tunnel.o
44obj-$(CONFIG_IP_PNP) += ipconfig.o 41obj-$(CONFIG_IP_PNP) += ipconfig.o
45obj-$(CONFIG_NETFILTER) += netfilter.o netfilter/ 42obj-$(CONFIG_NETFILTER) += netfilter.o netfilter/
46obj-$(CONFIG_INET_DIAG) += inet_diag.o 43obj-$(CONFIG_INET_DIAG) += inet_diag.o
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index 8756e0e790d2..b61a8ff558f9 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -107,6 +107,44 @@ static void esp4_gso_encap(struct xfrm_state *x, struct sk_buff *skb)
107 xo->proto = proto; 107 xo->proto = proto;
108} 108}
109 109
110static struct sk_buff *xfrm4_tunnel_gso_segment(struct xfrm_state *x,
111 struct sk_buff *skb,
112 netdev_features_t features)
113{
114 __skb_push(skb, skb->mac_len);
115 return skb_mac_gso_segment(skb, features);
116}
117
118static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
119 struct sk_buff *skb,
120 netdev_features_t features)
121{
122 const struct net_offload *ops;
123 struct sk_buff *segs = ERR_PTR(-EINVAL);
124 struct xfrm_offload *xo = xfrm_offload(skb);
125
126 skb->transport_header += x->props.header_len;
127 ops = rcu_dereference(inet_offloads[xo->proto]);
128 if (likely(ops && ops->callbacks.gso_segment))
129 segs = ops->callbacks.gso_segment(skb, features);
130
131 return segs;
132}
133
134static struct sk_buff *xfrm4_outer_mode_gso_segment(struct xfrm_state *x,
135 struct sk_buff *skb,
136 netdev_features_t features)
137{
138 switch (x->outer_mode.encap) {
139 case XFRM_MODE_TUNNEL:
140 return xfrm4_tunnel_gso_segment(x, skb, features);
141 case XFRM_MODE_TRANSPORT:
142 return xfrm4_transport_gso_segment(x, skb, features);
143 }
144
145 return ERR_PTR(-EOPNOTSUPP);
146}
147
110static struct sk_buff *esp4_gso_segment(struct sk_buff *skb, 148static struct sk_buff *esp4_gso_segment(struct sk_buff *skb,
111 netdev_features_t features) 149 netdev_features_t features)
112{ 150{
@@ -138,14 +176,16 @@ static struct sk_buff *esp4_gso_segment(struct sk_buff *skb,
138 176
139 skb->encap_hdr_csum = 1; 177 skb->encap_hdr_csum = 1;
140 178
141 if (!(features & NETIF_F_HW_ESP) || x->xso.dev != skb->dev) 179 if ((!(skb->dev->gso_partial_features & NETIF_F_HW_ESP) &&
180 !(features & NETIF_F_HW_ESP)) || x->xso.dev != skb->dev)
142 esp_features = features & ~(NETIF_F_SG | NETIF_F_CSUM_MASK); 181 esp_features = features & ~(NETIF_F_SG | NETIF_F_CSUM_MASK);
143 else if (!(features & NETIF_F_HW_ESP_TX_CSUM)) 182 else if (!(features & NETIF_F_HW_ESP_TX_CSUM) &&
183 !(skb->dev->gso_partial_features & NETIF_F_HW_ESP_TX_CSUM))
144 esp_features = features & ~NETIF_F_CSUM_MASK; 184 esp_features = features & ~NETIF_F_CSUM_MASK;
145 185
146 xo->flags |= XFRM_GSO_SEGMENT; 186 xo->flags |= XFRM_GSO_SEGMENT;
147 187
148 return x->outer_mode->gso_segment(x, skb, esp_features); 188 return xfrm4_outer_mode_gso_segment(x, skb, esp_features);
149} 189}
150 190
151static int esp_input_tail(struct xfrm_state *x, struct sk_buff *skb) 191static int esp_input_tail(struct xfrm_state *x, struct sk_buff *skb)
@@ -181,7 +221,9 @@ static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features_
181 if (!xo) 221 if (!xo)
182 return -EINVAL; 222 return -EINVAL;
183 223
184 if (!(features & NETIF_F_HW_ESP) || x->xso.dev != skb->dev) { 224 if ((!(features & NETIF_F_HW_ESP) &&
225 !(skb->dev->gso_partial_features & NETIF_F_HW_ESP)) ||
226 x->xso.dev != skb->dev) {
185 xo->flags |= CRYPTO_FALLBACK; 227 xo->flags |= CRYPTO_FALLBACK;
186 hw_offload = false; 228 hw_offload = false;
187 } 229 }
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c
index 68a21bf75dd0..cc5d9c0a8a10 100644
--- a/net/ipv4/ip_vti.c
+++ b/net/ipv4/ip_vti.c
@@ -50,7 +50,7 @@ static unsigned int vti_net_id __read_mostly;
50static int vti_tunnel_init(struct net_device *dev); 50static int vti_tunnel_init(struct net_device *dev);
51 51
52static int vti_input(struct sk_buff *skb, int nexthdr, __be32 spi, 52static int vti_input(struct sk_buff *skb, int nexthdr, __be32 spi,
53 int encap_type) 53 int encap_type, bool update_skb_dev)
54{ 54{
55 struct ip_tunnel *tunnel; 55 struct ip_tunnel *tunnel;
56 const struct iphdr *iph = ip_hdr(skb); 56 const struct iphdr *iph = ip_hdr(skb);
@@ -65,6 +65,9 @@ static int vti_input(struct sk_buff *skb, int nexthdr, __be32 spi,
65 65
66 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel; 66 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel;
67 67
68 if (update_skb_dev)
69 skb->dev = tunnel->dev;
70
68 return xfrm_input(skb, nexthdr, spi, encap_type); 71 return xfrm_input(skb, nexthdr, spi, encap_type);
69 } 72 }
70 73
@@ -74,47 +77,28 @@ drop:
74 return 0; 77 return 0;
75} 78}
76 79
77static int vti_input_ipip(struct sk_buff *skb, int nexthdr, __be32 spi, 80static int vti_input_proto(struct sk_buff *skb, int nexthdr, __be32 spi,
78 int encap_type) 81 int encap_type)
79{ 82{
80 struct ip_tunnel *tunnel; 83 return vti_input(skb, nexthdr, spi, encap_type, false);
81 const struct iphdr *iph = ip_hdr(skb);
82 struct net *net = dev_net(skb->dev);
83 struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
84
85 tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
86 iph->saddr, iph->daddr, 0);
87 if (tunnel) {
88 if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
89 goto drop;
90
91 XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel;
92
93 skb->dev = tunnel->dev;
94
95 return xfrm_input(skb, nexthdr, spi, encap_type);
96 }
97
98 return -EINVAL;
99drop:
100 kfree_skb(skb);
101 return 0;
102} 84}
103 85
104static int vti_rcv(struct sk_buff *skb) 86static int vti_rcv(struct sk_buff *skb, __be32 spi, bool update_skb_dev)
105{ 87{
106 XFRM_SPI_SKB_CB(skb)->family = AF_INET; 88 XFRM_SPI_SKB_CB(skb)->family = AF_INET;
107 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); 89 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
108 90
109 return vti_input(skb, ip_hdr(skb)->protocol, 0, 0); 91 return vti_input(skb, ip_hdr(skb)->protocol, spi, 0, update_skb_dev);
110} 92}
111 93
112static int vti_rcv_ipip(struct sk_buff *skb) 94static int vti_rcv_proto(struct sk_buff *skb)
113{ 95{
114 XFRM_SPI_SKB_CB(skb)->family = AF_INET; 96 return vti_rcv(skb, 0, false);
115 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); 97}
116 98
117 return vti_input_ipip(skb, ip_hdr(skb)->protocol, ip_hdr(skb)->saddr, 0); 99static int vti_rcv_tunnel(struct sk_buff *skb)
100{
101 return vti_rcv(skb, ip_hdr(skb)->saddr, true);
118} 102}
119 103
120static int vti_rcv_cb(struct sk_buff *skb, int err) 104static int vti_rcv_cb(struct sk_buff *skb, int err)
@@ -123,7 +107,7 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
123 struct net_device *dev; 107 struct net_device *dev;
124 struct pcpu_sw_netstats *tstats; 108 struct pcpu_sw_netstats *tstats;
125 struct xfrm_state *x; 109 struct xfrm_state *x;
126 struct xfrm_mode *inner_mode; 110 const struct xfrm_mode *inner_mode;
127 struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4; 111 struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4;
128 u32 orig_mark = skb->mark; 112 u32 orig_mark = skb->mark;
129 int ret; 113 int ret;
@@ -142,7 +126,7 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
142 126
143 x = xfrm_input_state(skb); 127 x = xfrm_input_state(skb);
144 128
145 inner_mode = x->inner_mode; 129 inner_mode = &x->inner_mode;
146 130
147 if (x->sel.family == AF_UNSPEC) { 131 if (x->sel.family == AF_UNSPEC) {
148 inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); 132 inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
@@ -153,7 +137,7 @@ static int vti_rcv_cb(struct sk_buff *skb, int err)
153 } 137 }
154 } 138 }
155 139
156 family = inner_mode->afinfo->family; 140 family = inner_mode->family;
157 141
158 skb->mark = be32_to_cpu(tunnel->parms.i_key); 142 skb->mark = be32_to_cpu(tunnel->parms.i_key);
159 ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family); 143 ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);
@@ -447,31 +431,31 @@ static void __net_init vti_fb_tunnel_init(struct net_device *dev)
447} 431}
448 432
449static struct xfrm4_protocol vti_esp4_protocol __read_mostly = { 433static struct xfrm4_protocol vti_esp4_protocol __read_mostly = {
450 .handler = vti_rcv, 434 .handler = vti_rcv_proto,
451 .input_handler = vti_input, 435 .input_handler = vti_input_proto,
452 .cb_handler = vti_rcv_cb, 436 .cb_handler = vti_rcv_cb,
453 .err_handler = vti4_err, 437 .err_handler = vti4_err,
454 .priority = 100, 438 .priority = 100,
455}; 439};
456 440
457static struct xfrm4_protocol vti_ah4_protocol __read_mostly = { 441static struct xfrm4_protocol vti_ah4_protocol __read_mostly = {
458 .handler = vti_rcv, 442 .handler = vti_rcv_proto,
459 .input_handler = vti_input, 443 .input_handler = vti_input_proto,
460 .cb_handler = vti_rcv_cb, 444 .cb_handler = vti_rcv_cb,
461 .err_handler = vti4_err, 445 .err_handler = vti4_err,
462 .priority = 100, 446 .priority = 100,
463}; 447};
464 448
465static struct xfrm4_protocol vti_ipcomp4_protocol __read_mostly = { 449static struct xfrm4_protocol vti_ipcomp4_protocol __read_mostly = {
466 .handler = vti_rcv, 450 .handler = vti_rcv_proto,
467 .input_handler = vti_input, 451 .input_handler = vti_input_proto,
468 .cb_handler = vti_rcv_cb, 452 .cb_handler = vti_rcv_cb,
469 .err_handler = vti4_err, 453 .err_handler = vti4_err,
470 .priority = 100, 454 .priority = 100,
471}; 455};
472 456
473static struct xfrm_tunnel ipip_handler __read_mostly = { 457static struct xfrm_tunnel ipip_handler __read_mostly = {
474 .handler = vti_rcv_ipip, 458 .handler = vti_rcv_tunnel,
475 .err_handler = vti4_err, 459 .err_handler = vti4_err,
476 .priority = 0, 460 .priority = 0,
477}; 461};
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
deleted file mode 100644
index 856d2dfdb44b..000000000000
--- a/net/ipv4/xfrm4_mode_beet.c
+++ /dev/null
@@ -1,155 +0,0 @@
1/*
2 * xfrm4_mode_beet.c - BEET mode encapsulation for IPv4.
3 *
4 * Copyright (c) 2006 Diego Beltrami <diego.beltrami@gmail.com>
5 * Miika Komu <miika@iki.fi>
6 * Herbert Xu <herbert@gondor.apana.org.au>
7 * Abhinav Pathak <abhinav.pathak@hiit.fi>
8 * Jeff Ahrenholz <ahrenholz@gmail.com>
9 */
10
11#include <linux/init.h>
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/skbuff.h>
15#include <linux/stringify.h>
16#include <net/dst.h>
17#include <net/ip.h>
18#include <net/xfrm.h>
19
20static void xfrm4_beet_make_header(struct sk_buff *skb)
21{
22 struct iphdr *iph = ip_hdr(skb);
23
24 iph->ihl = 5;
25 iph->version = 4;
26
27 iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol;
28 iph->tos = XFRM_MODE_SKB_CB(skb)->tos;
29
30 iph->id = XFRM_MODE_SKB_CB(skb)->id;
31 iph->frag_off = XFRM_MODE_SKB_CB(skb)->frag_off;
32 iph->ttl = XFRM_MODE_SKB_CB(skb)->ttl;
33}
34
35/* Add encapsulation header.
36 *
37 * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
38 */
39static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
40{
41 struct ip_beet_phdr *ph;
42 struct iphdr *top_iph;
43 int hdrlen, optlen;
44
45 hdrlen = 0;
46 optlen = XFRM_MODE_SKB_CB(skb)->optlen;
47 if (unlikely(optlen))
48 hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);
49
50 skb_set_network_header(skb, -x->props.header_len -
51 hdrlen + (XFRM_MODE_SKB_CB(skb)->ihl - sizeof(*top_iph)));
52 if (x->sel.family != AF_INET6)
53 skb->network_header += IPV4_BEET_PHMAXLEN;
54 skb->mac_header = skb->network_header +
55 offsetof(struct iphdr, protocol);
56 skb->transport_header = skb->network_header + sizeof(*top_iph);
57
58 xfrm4_beet_make_header(skb);
59
60 ph = __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdrlen);
61
62 top_iph = ip_hdr(skb);
63
64 if (unlikely(optlen)) {
65 BUG_ON(optlen < 0);
66
67 ph->padlen = 4 - (optlen & 4);
68 ph->hdrlen = optlen / 8;
69 ph->nexthdr = top_iph->protocol;
70 if (ph->padlen)
71 memset(ph + 1, IPOPT_NOP, ph->padlen);
72
73 top_iph->protocol = IPPROTO_BEETPH;
74 top_iph->ihl = sizeof(struct iphdr) / 4;
75 }
76
77 top_iph->saddr = x->props.saddr.a4;
78 top_iph->daddr = x->id.daddr.a4;
79
80 return 0;
81}
82
83static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
84{
85 struct iphdr *iph;
86 int optlen = 0;
87 int err = -EINVAL;
88
89 if (unlikely(XFRM_MODE_SKB_CB(skb)->protocol == IPPROTO_BEETPH)) {
90 struct ip_beet_phdr *ph;
91 int phlen;
92
93 if (!pskb_may_pull(skb, sizeof(*ph)))
94 goto out;
95
96 ph = (struct ip_beet_phdr *)skb->data;
97
98 phlen = sizeof(*ph) + ph->padlen;
99 optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen);
100 if (optlen < 0 || optlen & 3 || optlen > 250)
101 goto out;
102
103 XFRM_MODE_SKB_CB(skb)->protocol = ph->nexthdr;
104
105 if (!pskb_may_pull(skb, phlen))
106 goto out;
107 __skb_pull(skb, phlen);
108 }
109
110 skb_push(skb, sizeof(*iph));
111 skb_reset_network_header(skb);
112 skb_mac_header_rebuild(skb);
113
114 xfrm4_beet_make_header(skb);
115
116 iph = ip_hdr(skb);
117
118 iph->ihl += optlen / 4;
119 iph->tot_len = htons(skb->len);
120 iph->daddr = x->sel.daddr.a4;
121 iph->saddr = x->sel.saddr.a4;
122 iph->check = 0;
123 iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl);
124 err = 0;
125out:
126 return err;
127}
128
129static struct xfrm_mode xfrm4_beet_mode = {
130 .input2 = xfrm4_beet_input,
131 .input = xfrm_prepare_input,
132 .output2 = xfrm4_beet_output,
133 .output = xfrm4_prepare_output,
134 .owner = THIS_MODULE,
135 .encap = XFRM_MODE_BEET,
136 .flags = XFRM_MODE_FLAG_TUNNEL,
137};
138
139static int __init xfrm4_beet_init(void)
140{
141 return xfrm_register_mode(&xfrm4_beet_mode, AF_INET);
142}
143
144static void __exit xfrm4_beet_exit(void)
145{
146 int err;
147
148 err = xfrm_unregister_mode(&xfrm4_beet_mode, AF_INET);
149 BUG_ON(err);
150}
151
152module_init(xfrm4_beet_init);
153module_exit(xfrm4_beet_exit);
154MODULE_LICENSE("GPL");
155MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_BEET);
diff --git a/net/ipv4/xfrm4_mode_transport.c b/net/ipv4/xfrm4_mode_transport.c
deleted file mode 100644
index 1ad2c2c4e250..000000000000
--- a/net/ipv4/xfrm4_mode_transport.c
+++ /dev/null
@@ -1,114 +0,0 @@
1/*
2 * xfrm4_mode_transport.c - Transport mode encapsulation for IPv4.
3 *
4 * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
5 */
6
7#include <linux/init.h>
8#include <linux/kernel.h>
9#include <linux/module.h>
10#include <linux/skbuff.h>
11#include <linux/stringify.h>
12#include <net/dst.h>
13#include <net/ip.h>
14#include <net/xfrm.h>
15#include <net/protocol.h>
16
17/* Add encapsulation header.
18 *
19 * The IP header will be moved forward to make space for the encapsulation
20 * header.
21 */
22static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
23{
24 struct iphdr *iph = ip_hdr(skb);
25 int ihl = iph->ihl * 4;
26
27 skb_set_inner_transport_header(skb, skb_transport_offset(skb));
28
29 skb_set_network_header(skb, -x->props.header_len);
30 skb->mac_header = skb->network_header +
31 offsetof(struct iphdr, protocol);
32 skb->transport_header = skb->network_header + ihl;
33 __skb_pull(skb, ihl);
34 memmove(skb_network_header(skb), iph, ihl);
35 return 0;
36}
37
38/* Remove encapsulation header.
39 *
40 * The IP header will be moved over the top of the encapsulation header.
41 *
42 * On entry, skb->h shall point to where the IP header should be and skb->nh
43 * shall be set to where the IP header currently is. skb->data shall point
44 * to the start of the payload.
45 */
46static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
47{
48 int ihl = skb->data - skb_transport_header(skb);
49
50 if (skb->transport_header != skb->network_header) {
51 memmove(skb_transport_header(skb),
52 skb_network_header(skb), ihl);
53 skb->network_header = skb->transport_header;
54 }
55 ip_hdr(skb)->tot_len = htons(skb->len + ihl);
56 skb_reset_transport_header(skb);
57 return 0;
58}
59
60static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
61 struct sk_buff *skb,
62 netdev_features_t features)
63{
64 const struct net_offload *ops;
65 struct sk_buff *segs = ERR_PTR(-EINVAL);
66 struct xfrm_offload *xo = xfrm_offload(skb);
67
68 skb->transport_header += x->props.header_len;
69 ops = rcu_dereference(inet_offloads[xo->proto]);
70 if (likely(ops && ops->callbacks.gso_segment))
71 segs = ops->callbacks.gso_segment(skb, features);
72
73 return segs;
74}
75
76static void xfrm4_transport_xmit(struct xfrm_state *x, struct sk_buff *skb)
77{
78 struct xfrm_offload *xo = xfrm_offload(skb);
79
80 skb_reset_mac_len(skb);
81 pskb_pull(skb, skb->mac_len + sizeof(struct iphdr) + x->props.header_len);
82
83 if (xo->flags & XFRM_GSO_SEGMENT) {
84 skb_reset_transport_header(skb);
85 skb->transport_header -= x->props.header_len;
86 }
87}
88
89static struct xfrm_mode xfrm4_transport_mode = {
90 .input = xfrm4_transport_input,
91 .output = xfrm4_transport_output,
92 .gso_segment = xfrm4_transport_gso_segment,
93 .xmit = xfrm4_transport_xmit,
94 .owner = THIS_MODULE,
95 .encap = XFRM_MODE_TRANSPORT,
96};
97
98static int __init xfrm4_transport_init(void)
99{
100 return xfrm_register_mode(&xfrm4_transport_mode, AF_INET);
101}
102
103static void __exit xfrm4_transport_exit(void)
104{
105 int err;
106
107 err = xfrm_unregister_mode(&xfrm4_transport_mode, AF_INET);
108 BUG_ON(err);
109}
110
111module_init(xfrm4_transport_init);
112module_exit(xfrm4_transport_exit);
113MODULE_LICENSE("GPL");
114MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TRANSPORT);
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
deleted file mode 100644
index 2a9764bd1719..000000000000
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ /dev/null
@@ -1,152 +0,0 @@
1/*
2 * xfrm4_mode_tunnel.c - Tunnel mode encapsulation for IPv4.
3 *
4 * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
5 */
6
7#include <linux/gfp.h>
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/skbuff.h>
12#include <linux/stringify.h>
13#include <net/dst.h>
14#include <net/inet_ecn.h>
15#include <net/ip.h>
16#include <net/xfrm.h>
17
18static inline void ipip_ecn_decapsulate(struct sk_buff *skb)
19{
20 struct iphdr *inner_iph = ipip_hdr(skb);
21
22 if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos))
23 IP_ECN_set_ce(inner_iph);
24}
25
26/* Add encapsulation header.
27 *
28 * The top IP header will be constructed per RFC 2401.
29 */
30static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
31{
32 struct dst_entry *dst = skb_dst(skb);
33 struct iphdr *top_iph;
34 int flags;
35
36 skb_set_inner_network_header(skb, skb_network_offset(skb));
37 skb_set_inner_transport_header(skb, skb_transport_offset(skb));
38
39 skb_set_network_header(skb, -x->props.header_len);
40 skb->mac_header = skb->network_header +
41 offsetof(struct iphdr, protocol);
42 skb->transport_header = skb->network_header + sizeof(*top_iph);
43 top_iph = ip_hdr(skb);
44
45 top_iph->ihl = 5;
46 top_iph->version = 4;
47
48 top_iph->protocol = xfrm_af2proto(skb_dst(skb)->ops->family);
49
50 /* DS disclosing depends on XFRM_SA_XFLAG_DONT_ENCAP_DSCP */
51 if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
52 top_iph->tos = 0;
53 else
54 top_iph->tos = XFRM_MODE_SKB_CB(skb)->tos;
55 top_iph->tos = INET_ECN_encapsulate(top_iph->tos,
56 XFRM_MODE_SKB_CB(skb)->tos);
57
58 flags = x->props.flags;
59 if (flags & XFRM_STATE_NOECN)
60 IP_ECN_clear(top_iph);
61
62 top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
63 0 : (XFRM_MODE_SKB_CB(skb)->frag_off & htons(IP_DF));
64
65 top_iph->ttl = ip4_dst_hoplimit(xfrm_dst_child(dst));
66
67 top_iph->saddr = x->props.saddr.a4;
68 top_iph->daddr = x->id.daddr.a4;
69 ip_select_ident(dev_net(dst->dev), skb, NULL);
70
71 return 0;
72}
73
74static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
75{
76 int err = -EINVAL;
77
78 if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP)
79 goto out;
80
81 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
82 goto out;
83
84 err = skb_unclone(skb, GFP_ATOMIC);
85 if (err)
86 goto out;
87
88 if (x->props.flags & XFRM_STATE_DECAP_DSCP)
89 ipv4_copy_dscp(XFRM_MODE_SKB_CB(skb)->tos, ipip_hdr(skb));
90 if (!(x->props.flags & XFRM_STATE_NOECN))
91 ipip_ecn_decapsulate(skb);
92
93 skb_reset_network_header(skb);
94 skb_mac_header_rebuild(skb);
95 if (skb->mac_len)
96 eth_hdr(skb)->h_proto = skb->protocol;
97
98 err = 0;
99
100out:
101 return err;
102}
103
104static struct sk_buff *xfrm4_mode_tunnel_gso_segment(struct xfrm_state *x,
105 struct sk_buff *skb,
106 netdev_features_t features)
107{
108 __skb_push(skb, skb->mac_len);
109 return skb_mac_gso_segment(skb, features);
110}
111
112static void xfrm4_mode_tunnel_xmit(struct xfrm_state *x, struct sk_buff *skb)
113{
114 struct xfrm_offload *xo = xfrm_offload(skb);
115
116 if (xo->flags & XFRM_GSO_SEGMENT)
117 skb->transport_header = skb->network_header +
118 sizeof(struct iphdr);
119
120 skb_reset_mac_len(skb);
121 pskb_pull(skb, skb->mac_len + x->props.header_len);
122}
123
124static struct xfrm_mode xfrm4_tunnel_mode = {
125 .input2 = xfrm4_mode_tunnel_input,
126 .input = xfrm_prepare_input,
127 .output2 = xfrm4_mode_tunnel_output,
128 .output = xfrm4_prepare_output,
129 .gso_segment = xfrm4_mode_tunnel_gso_segment,
130 .xmit = xfrm4_mode_tunnel_xmit,
131 .owner = THIS_MODULE,
132 .encap = XFRM_MODE_TUNNEL,
133 .flags = XFRM_MODE_FLAG_TUNNEL,
134};
135
136static int __init xfrm4_mode_tunnel_init(void)
137{
138 return xfrm_register_mode(&xfrm4_tunnel_mode, AF_INET);
139}
140
141static void __exit xfrm4_mode_tunnel_exit(void)
142{
143 int err;
144
145 err = xfrm_unregister_mode(&xfrm4_tunnel_mode, AF_INET);
146 BUG_ON(err);
147}
148
149module_init(xfrm4_mode_tunnel_init);
150module_exit(xfrm4_mode_tunnel_exit);
151MODULE_LICENSE("GPL");
152MODULE_ALIAS_XFRM_MODE(AF_INET, XFRM_MODE_TUNNEL);
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index be980c195fc5..9bb8905088c7 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -58,21 +58,6 @@ int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb)
58 return xfrm4_extract_header(skb); 58 return xfrm4_extract_header(skb);
59} 59}
60 60
61int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
62{
63 int err;
64
65 err = xfrm_inner_extract_output(x, skb);
66 if (err)
67 return err;
68
69 IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
70 skb->protocol = htons(ETH_P_IP);
71
72 return x->outer_mode->output2(x, skb);
73}
74EXPORT_SYMBOL(xfrm4_prepare_output);
75
76int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb) 61int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb)
77{ 62{
78 memset(IPCB(skb), 0, sizeof(*IPCB(skb))); 63 memset(IPCB(skb), 0, sizeof(*IPCB(skb)));
@@ -87,6 +72,8 @@ int xfrm4_output_finish(struct sock *sk, struct sk_buff *skb)
87static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) 72static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
88{ 73{
89 struct xfrm_state *x = skb_dst(skb)->xfrm; 74 struct xfrm_state *x = skb_dst(skb)->xfrm;
75 const struct xfrm_state_afinfo *afinfo;
76 int ret = -EAFNOSUPPORT;
90 77
91#ifdef CONFIG_NETFILTER 78#ifdef CONFIG_NETFILTER
92 if (!x) { 79 if (!x) {
@@ -95,7 +82,15 @@ static int __xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
95 } 82 }
96#endif 83#endif
97 84
98 return x->outer_mode->afinfo->output_finish(sk, skb); 85 rcu_read_lock();
86 afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family);
87 if (likely(afinfo))
88 ret = afinfo->output_finish(sk, skb);
89 else
90 kfree_skb(skb);
91 rcu_read_unlock();
92
93 return ret;
99} 94}
100 95
101int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb) 96int xfrm4_output(struct net *net, struct sock *sk, struct sk_buff *skb)
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
index 72d19b1838ed..cdef8f9a3b01 100644
--- a/net/ipv4/xfrm4_policy.c
+++ b/net/ipv4/xfrm4_policy.c
@@ -12,7 +12,6 @@
12#include <linux/err.h> 12#include <linux/err.h>
13#include <linux/kernel.h> 13#include <linux/kernel.h>
14#include <linux/inetdevice.h> 14#include <linux/inetdevice.h>
15#include <linux/if_tunnel.h>
16#include <net/dst.h> 15#include <net/dst.h>
17#include <net/xfrm.h> 16#include <net/xfrm.h>
18#include <net/ip.h> 17#include <net/ip.h>
@@ -69,17 +68,6 @@ static int xfrm4_get_saddr(struct net *net, int oif,
69 return 0; 68 return 0;
70} 69}
71 70
72static int xfrm4_get_tos(const struct flowi *fl)
73{
74 return IPTOS_RT_MASK & fl->u.ip4.flowi4_tos; /* Strip ECN bits */
75}
76
77static int xfrm4_init_path(struct xfrm_dst *path, struct dst_entry *dst,
78 int nfheader_len)
79{
80 return 0;
81}
82
83static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, 71static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
84 const struct flowi *fl) 72 const struct flowi *fl)
85{ 73{
@@ -110,118 +98,6 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
110 return 0; 98 return 0;
111} 99}
112 100
113static void
114_decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse)
115{
116 const struct iphdr *iph = ip_hdr(skb);
117 u8 *xprth = skb_network_header(skb) + iph->ihl * 4;
118 struct flowi4 *fl4 = &fl->u.ip4;
119 int oif = 0;
120
121 if (skb_dst(skb))
122 oif = skb_dst(skb)->dev->ifindex;
123
124 memset(fl4, 0, sizeof(struct flowi4));
125 fl4->flowi4_mark = skb->mark;
126 fl4->flowi4_oif = reverse ? skb->skb_iif : oif;
127
128 if (!ip_is_fragment(iph)) {
129 switch (iph->protocol) {
130 case IPPROTO_UDP:
131 case IPPROTO_UDPLITE:
132 case IPPROTO_TCP:
133 case IPPROTO_SCTP:
134 case IPPROTO_DCCP:
135 if (xprth + 4 < skb->data ||
136 pskb_may_pull(skb, xprth + 4 - skb->data)) {
137 __be16 *ports;
138
139 xprth = skb_network_header(skb) + iph->ihl * 4;
140 ports = (__be16 *)xprth;
141
142 fl4->fl4_sport = ports[!!reverse];
143 fl4->fl4_dport = ports[!reverse];
144 }
145 break;
146
147 case IPPROTO_ICMP:
148 if (xprth + 2 < skb->data ||
149 pskb_may_pull(skb, xprth + 2 - skb->data)) {
150 u8 *icmp;
151
152 xprth = skb_network_header(skb) + iph->ihl * 4;
153 icmp = xprth;
154
155 fl4->fl4_icmp_type = icmp[0];
156 fl4->fl4_icmp_code = icmp[1];
157 }
158 break;
159
160 case IPPROTO_ESP:
161 if (xprth + 4 < skb->data ||
162 pskb_may_pull(skb, xprth + 4 - skb->data)) {
163 __be32 *ehdr;
164
165 xprth = skb_network_header(skb) + iph->ihl * 4;
166 ehdr = (__be32 *)xprth;
167
168 fl4->fl4_ipsec_spi = ehdr[0];
169 }
170 break;
171
172 case IPPROTO_AH:
173 if (xprth + 8 < skb->data ||
174 pskb_may_pull(skb, xprth + 8 - skb->data)) {
175 __be32 *ah_hdr;
176
177 xprth = skb_network_header(skb) + iph->ihl * 4;
178 ah_hdr = (__be32 *)xprth;
179
180 fl4->fl4_ipsec_spi = ah_hdr[1];
181 }
182 break;
183
184 case IPPROTO_COMP:
185 if (xprth + 4 < skb->data ||
186 pskb_may_pull(skb, xprth + 4 - skb->data)) {
187 __be16 *ipcomp_hdr;
188
189 xprth = skb_network_header(skb) + iph->ihl * 4;
190 ipcomp_hdr = (__be16 *)xprth;
191
192 fl4->fl4_ipsec_spi = htonl(ntohs(ipcomp_hdr[1]));
193 }
194 break;
195
196 case IPPROTO_GRE:
197 if (xprth + 12 < skb->data ||
198 pskb_may_pull(skb, xprth + 12 - skb->data)) {
199 __be16 *greflags;
200 __be32 *gre_hdr;
201
202 xprth = skb_network_header(skb) + iph->ihl * 4;
203 greflags = (__be16 *)xprth;
204 gre_hdr = (__be32 *)xprth;
205
206 if (greflags[0] & GRE_KEY) {
207 if (greflags[0] & GRE_CSUM)
208 gre_hdr++;
209 fl4->fl4_gre_key = gre_hdr[1];
210 }
211 }
212 break;
213
214 default:
215 fl4->fl4_ipsec_spi = 0;
216 break;
217 }
218 }
219 fl4->flowi4_proto = iph->protocol;
220 fl4->daddr = reverse ? iph->saddr : iph->daddr;
221 fl4->saddr = reverse ? iph->daddr : iph->saddr;
222 fl4->flowi4_tos = iph->tos;
223}
224
225static void xfrm4_update_pmtu(struct dst_entry *dst, struct sock *sk, 101static void xfrm4_update_pmtu(struct dst_entry *dst, struct sock *sk,
226 struct sk_buff *skb, u32 mtu) 102 struct sk_buff *skb, u32 mtu)
227{ 103{
@@ -274,9 +150,6 @@ static const struct xfrm_policy_afinfo xfrm4_policy_afinfo = {
274 .dst_ops = &xfrm4_dst_ops_template, 150 .dst_ops = &xfrm4_dst_ops_template,
275 .dst_lookup = xfrm4_dst_lookup, 151 .dst_lookup = xfrm4_dst_lookup,
276 .get_saddr = xfrm4_get_saddr, 152 .get_saddr = xfrm4_get_saddr,
277 .decode_session = _decode_session4,
278 .get_tos = xfrm4_get_tos,
279 .init_path = xfrm4_init_path,
280 .fill_dst = xfrm4_fill_dst, 153 .fill_dst = xfrm4_fill_dst,
281 .blackhole_route = ipv4_blackhole_route, 154 .blackhole_route = ipv4_blackhole_route,
282}; 155};
diff --git a/net/ipv4/xfrm4_protocol.c b/net/ipv4/xfrm4_protocol.c
index 35c54865dc42..bcab48944c15 100644
--- a/net/ipv4/xfrm4_protocol.c
+++ b/net/ipv4/xfrm4_protocol.c
@@ -46,7 +46,7 @@ static inline struct xfrm4_protocol __rcu **proto_handlers(u8 protocol)
46 handler != NULL; \ 46 handler != NULL; \
47 handler = rcu_dereference(handler->next)) \ 47 handler = rcu_dereference(handler->next)) \
48 48
49int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err) 49static int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
50{ 50{
51 int ret; 51 int ret;
52 struct xfrm4_protocol *handler; 52 struct xfrm4_protocol *handler;
@@ -61,7 +61,6 @@ int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
61 61
62 return 0; 62 return 0;
63} 63}
64EXPORT_SYMBOL(xfrm4_rcv_cb);
65 64
66int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, 65int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
67 int encap_type) 66 int encap_type)
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 613282c65a10..cd915e332c98 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -135,44 +135,11 @@ config INET6_TUNNEL
135 tristate 135 tristate
136 default n 136 default n
137 137
138config INET6_XFRM_MODE_TRANSPORT
139 tristate "IPv6: IPsec transport mode"
140 default IPV6
141 select XFRM
142 ---help---
143 Support for IPsec transport mode.
144
145 If unsure, say Y.
146
147config INET6_XFRM_MODE_TUNNEL
148 tristate "IPv6: IPsec tunnel mode"
149 default IPV6
150 select XFRM
151 ---help---
152 Support for IPsec tunnel mode.
153
154 If unsure, say Y.
155
156config INET6_XFRM_MODE_BEET
157 tristate "IPv6: IPsec BEET mode"
158 default IPV6
159 select XFRM
160 ---help---
161 Support for IPsec BEET mode.
162
163 If unsure, say Y.
164
165config INET6_XFRM_MODE_ROUTEOPTIMIZATION
166 tristate "IPv6: MIPv6 route optimization mode"
167 select XFRM
168 ---help---
169 Support for MIPv6 route optimization mode.
170
171config IPV6_VTI 138config IPV6_VTI
172tristate "Virtual (secure) IPv6: tunneling" 139tristate "Virtual (secure) IPv6: tunneling"
173 select IPV6_TUNNEL 140 select IPV6_TUNNEL
174 select NET_IP_TUNNEL 141 select NET_IP_TUNNEL
175 depends on INET6_XFRM_MODE_TUNNEL 142 select XFRM
176 ---help--- 143 ---help---
177 Tunneling means encapsulating data of one protocol type within 144 Tunneling means encapsulating data of one protocol type within
178 another protocol and sending it over a channel that understands the 145 another protocol and sending it over a channel that understands the
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile
index e0026fa1261b..8ccf35514015 100644
--- a/net/ipv6/Makefile
+++ b/net/ipv6/Makefile
@@ -35,10 +35,6 @@ obj-$(CONFIG_INET6_ESP_OFFLOAD) += esp6_offload.o
35obj-$(CONFIG_INET6_IPCOMP) += ipcomp6.o 35obj-$(CONFIG_INET6_IPCOMP) += ipcomp6.o
36obj-$(CONFIG_INET6_XFRM_TUNNEL) += xfrm6_tunnel.o 36obj-$(CONFIG_INET6_XFRM_TUNNEL) += xfrm6_tunnel.o
37obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o 37obj-$(CONFIG_INET6_TUNNEL) += tunnel6.o
38obj-$(CONFIG_INET6_XFRM_MODE_TRANSPORT) += xfrm6_mode_transport.o
39obj-$(CONFIG_INET6_XFRM_MODE_TUNNEL) += xfrm6_mode_tunnel.o
40obj-$(CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION) += xfrm6_mode_ro.o
41obj-$(CONFIG_INET6_XFRM_MODE_BEET) += xfrm6_mode_beet.o
42obj-$(CONFIG_IPV6_MIP6) += mip6.o 38obj-$(CONFIG_IPV6_MIP6) += mip6.o
43obj-$(CONFIG_IPV6_ILA) += ila/ 39obj-$(CONFIG_IPV6_ILA) += ila/
44obj-$(CONFIG_NETFILTER) += netfilter/ 40obj-$(CONFIG_NETFILTER) += netfilter/
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index d46b4eb645c2..bff83279d76f 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -134,6 +134,44 @@ static void esp6_gso_encap(struct xfrm_state *x, struct sk_buff *skb)
134 xo->proto = proto; 134 xo->proto = proto;
135} 135}
136 136
137static struct sk_buff *xfrm6_tunnel_gso_segment(struct xfrm_state *x,
138 struct sk_buff *skb,
139 netdev_features_t features)
140{
141 __skb_push(skb, skb->mac_len);
142 return skb_mac_gso_segment(skb, features);
143}
144
145static struct sk_buff *xfrm6_transport_gso_segment(struct xfrm_state *x,
146 struct sk_buff *skb,
147 netdev_features_t features)
148{
149 const struct net_offload *ops;
150 struct sk_buff *segs = ERR_PTR(-EINVAL);
151 struct xfrm_offload *xo = xfrm_offload(skb);
152
153 skb->transport_header += x->props.header_len;
154 ops = rcu_dereference(inet6_offloads[xo->proto]);
155 if (likely(ops && ops->callbacks.gso_segment))
156 segs = ops->callbacks.gso_segment(skb, features);
157
158 return segs;
159}
160
161static struct sk_buff *xfrm6_outer_mode_gso_segment(struct xfrm_state *x,
162 struct sk_buff *skb,
163 netdev_features_t features)
164{
165 switch (x->outer_mode.encap) {
166 case XFRM_MODE_TUNNEL:
167 return xfrm6_tunnel_gso_segment(x, skb, features);
168 case XFRM_MODE_TRANSPORT:
169 return xfrm6_transport_gso_segment(x, skb, features);
170 }
171
172 return ERR_PTR(-EOPNOTSUPP);
173}
174
137static struct sk_buff *esp6_gso_segment(struct sk_buff *skb, 175static struct sk_buff *esp6_gso_segment(struct sk_buff *skb,
138 netdev_features_t features) 176 netdev_features_t features)
139{ 177{
@@ -172,7 +210,7 @@ static struct sk_buff *esp6_gso_segment(struct sk_buff *skb,
172 210
173 xo->flags |= XFRM_GSO_SEGMENT; 211 xo->flags |= XFRM_GSO_SEGMENT;
174 212
175 return x->outer_mode->gso_segment(x, skb, esp_features); 213 return xfrm6_outer_mode_gso_segment(x, skb, esp_features);
176} 214}
177 215
178static int esp6_input_tail(struct xfrm_state *x, struct sk_buff *skb) 216static int esp6_input_tail(struct xfrm_state *x, struct sk_buff *skb)
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c
index 8b6eefff2f7e..218a0dedc8f4 100644
--- a/net/ipv6/ip6_vti.c
+++ b/net/ipv6/ip6_vti.c
@@ -342,7 +342,7 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
342 struct net_device *dev; 342 struct net_device *dev;
343 struct pcpu_sw_netstats *tstats; 343 struct pcpu_sw_netstats *tstats;
344 struct xfrm_state *x; 344 struct xfrm_state *x;
345 struct xfrm_mode *inner_mode; 345 const struct xfrm_mode *inner_mode;
346 struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6; 346 struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6;
347 u32 orig_mark = skb->mark; 347 u32 orig_mark = skb->mark;
348 int ret; 348 int ret;
@@ -361,7 +361,7 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
361 361
362 x = xfrm_input_state(skb); 362 x = xfrm_input_state(skb);
363 363
364 inner_mode = x->inner_mode; 364 inner_mode = &x->inner_mode;
365 365
366 if (x->sel.family == AF_UNSPEC) { 366 if (x->sel.family == AF_UNSPEC) {
367 inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); 367 inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
@@ -372,7 +372,7 @@ static int vti6_rcv_cb(struct sk_buff *skb, int err)
372 } 372 }
373 } 373 }
374 374
375 family = inner_mode->afinfo->family; 375 family = inner_mode->family;
376 376
377 skb->mark = be32_to_cpu(t->parms.i_key); 377 skb->mark = be32_to_cpu(t->parms.i_key);
378 ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family); 378 ret = xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family);
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
deleted file mode 100644
index 57fd314ec2b8..000000000000
--- a/net/ipv6/xfrm6_mode_beet.c
+++ /dev/null
@@ -1,131 +0,0 @@
1/*
2 * xfrm6_mode_beet.c - BEET mode encapsulation for IPv6.
3 *
4 * Copyright (c) 2006 Diego Beltrami <diego.beltrami@gmail.com>
5 * Miika Komu <miika@iki.fi>
6 * Herbert Xu <herbert@gondor.apana.org.au>
7 * Abhinav Pathak <abhinav.pathak@hiit.fi>
8 * Jeff Ahrenholz <ahrenholz@gmail.com>
9 */
10
11#include <linux/init.h>
12#include <linux/kernel.h>
13#include <linux/module.h>
14#include <linux/skbuff.h>
15#include <linux/stringify.h>
16#include <net/dsfield.h>
17#include <net/dst.h>
18#include <net/inet_ecn.h>
19#include <net/ipv6.h>
20#include <net/xfrm.h>
21
22static void xfrm6_beet_make_header(struct sk_buff *skb)
23{
24 struct ipv6hdr *iph = ipv6_hdr(skb);
25
26 iph->version = 6;
27
28 memcpy(iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
29 sizeof(iph->flow_lbl));
30 iph->nexthdr = XFRM_MODE_SKB_CB(skb)->protocol;
31
32 ipv6_change_dsfield(iph, 0, XFRM_MODE_SKB_CB(skb)->tos);
33 iph->hop_limit = XFRM_MODE_SKB_CB(skb)->ttl;
34}
35
36/* Add encapsulation header.
37 *
38 * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
39 */
40static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb)
41{
42 struct ipv6hdr *top_iph;
43 struct ip_beet_phdr *ph;
44 int optlen, hdr_len;
45
46 hdr_len = 0;
47 optlen = XFRM_MODE_SKB_CB(skb)->optlen;
48 if (unlikely(optlen))
49 hdr_len += IPV4_BEET_PHMAXLEN - (optlen & 4);
50
51 skb_set_network_header(skb, -x->props.header_len - hdr_len);
52 if (x->sel.family != AF_INET6)
53 skb->network_header += IPV4_BEET_PHMAXLEN;
54 skb->mac_header = skb->network_header +
55 offsetof(struct ipv6hdr, nexthdr);
56 skb->transport_header = skb->network_header + sizeof(*top_iph);
57 ph = __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdr_len);
58
59 xfrm6_beet_make_header(skb);
60
61 top_iph = ipv6_hdr(skb);
62 if (unlikely(optlen)) {
63
64 BUG_ON(optlen < 0);
65
66 ph->padlen = 4 - (optlen & 4);
67 ph->hdrlen = optlen / 8;
68 ph->nexthdr = top_iph->nexthdr;
69 if (ph->padlen)
70 memset(ph + 1, IPOPT_NOP, ph->padlen);
71
72 top_iph->nexthdr = IPPROTO_BEETPH;
73 }
74
75 top_iph->saddr = *(struct in6_addr *)&x->props.saddr;
76 top_iph->daddr = *(struct in6_addr *)&x->id.daddr;
77 return 0;
78}
79
80static int xfrm6_beet_input(struct xfrm_state *x, struct sk_buff *skb)
81{
82 struct ipv6hdr *ip6h;
83 int size = sizeof(struct ipv6hdr);
84 int err;
85
86 err = skb_cow_head(skb, size + skb->mac_len);
87 if (err)
88 goto out;
89
90 __skb_push(skb, size);
91 skb_reset_network_header(skb);
92 skb_mac_header_rebuild(skb);
93
94 xfrm6_beet_make_header(skb);
95
96 ip6h = ipv6_hdr(skb);
97 ip6h->payload_len = htons(skb->len - size);
98 ip6h->daddr = x->sel.daddr.in6;
99 ip6h->saddr = x->sel.saddr.in6;
100 err = 0;
101out:
102 return err;
103}
104
105static struct xfrm_mode xfrm6_beet_mode = {
106 .input2 = xfrm6_beet_input,
107 .input = xfrm_prepare_input,
108 .output2 = xfrm6_beet_output,
109 .output = xfrm6_prepare_output,
110 .owner = THIS_MODULE,
111 .encap = XFRM_MODE_BEET,
112 .flags = XFRM_MODE_FLAG_TUNNEL,
113};
114
115static int __init xfrm6_beet_init(void)
116{
117 return xfrm_register_mode(&xfrm6_beet_mode, AF_INET6);
118}
119
120static void __exit xfrm6_beet_exit(void)
121{
122 int err;
123
124 err = xfrm_unregister_mode(&xfrm6_beet_mode, AF_INET6);
125 BUG_ON(err);
126}
127
128module_init(xfrm6_beet_init);
129module_exit(xfrm6_beet_exit);
130MODULE_LICENSE("GPL");
131MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_BEET);
diff --git a/net/ipv6/xfrm6_mode_ro.c b/net/ipv6/xfrm6_mode_ro.c
deleted file mode 100644
index da28e4407b8f..000000000000
--- a/net/ipv6/xfrm6_mode_ro.c
+++ /dev/null
@@ -1,85 +0,0 @@
1/*
2 * xfrm6_mode_ro.c - Route optimization mode for IPv6.
3 *
4 * Copyright (C)2003-2006 Helsinki University of Technology
5 * Copyright (C)2003-2006 USAGI/WIDE Project
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 */
20/*
21 * Authors:
22 * Noriaki TAKAMIYA @USAGI
23 * Masahide NAKAMURA @USAGI
24 */
25
26#include <linux/init.h>
27#include <linux/kernel.h>
28#include <linux/module.h>
29#include <linux/skbuff.h>
30#include <linux/spinlock.h>
31#include <linux/stringify.h>
32#include <linux/time.h>
33#include <net/ipv6.h>
34#include <net/xfrm.h>
35
36/* Add route optimization header space.
37 *
38 * The IP header and mutable extension headers will be moved forward to make
39 * space for the route optimization header.
40 */
41static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
42{
43 struct ipv6hdr *iph;
44 u8 *prevhdr;
45 int hdr_len;
46
47 iph = ipv6_hdr(skb);
48
49 hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
50 if (hdr_len < 0)
51 return hdr_len;
52 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
53 skb_set_network_header(skb, -x->props.header_len);
54 skb->transport_header = skb->network_header + hdr_len;
55 __skb_pull(skb, hdr_len);
56 memmove(ipv6_hdr(skb), iph, hdr_len);
57
58 x->lastused = ktime_get_real_seconds();
59
60 return 0;
61}
62
63static struct xfrm_mode xfrm6_ro_mode = {
64 .output = xfrm6_ro_output,
65 .owner = THIS_MODULE,
66 .encap = XFRM_MODE_ROUTEOPTIMIZATION,
67};
68
69static int __init xfrm6_ro_init(void)
70{
71 return xfrm_register_mode(&xfrm6_ro_mode, AF_INET6);
72}
73
74static void __exit xfrm6_ro_exit(void)
75{
76 int err;
77
78 err = xfrm_unregister_mode(&xfrm6_ro_mode, AF_INET6);
79 BUG_ON(err);
80}
81
82module_init(xfrm6_ro_init);
83module_exit(xfrm6_ro_exit);
84MODULE_LICENSE("GPL");
85MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_ROUTEOPTIMIZATION);
diff --git a/net/ipv6/xfrm6_mode_transport.c b/net/ipv6/xfrm6_mode_transport.c
deleted file mode 100644
index 3c29da5defe6..000000000000
--- a/net/ipv6/xfrm6_mode_transport.c
+++ /dev/null
@@ -1,121 +0,0 @@
1/*
2 * xfrm6_mode_transport.c - Transport mode encapsulation for IPv6.
3 *
4 * Copyright (C) 2002 USAGI/WIDE Project
5 * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
6 */
7
8#include <linux/init.h>
9#include <linux/kernel.h>
10#include <linux/module.h>
11#include <linux/skbuff.h>
12#include <linux/stringify.h>
13#include <net/dst.h>
14#include <net/ipv6.h>
15#include <net/xfrm.h>
16#include <net/protocol.h>
17
18/* Add encapsulation header.
19 *
20 * The IP header and mutable extension headers will be moved forward to make
21 * space for the encapsulation header.
22 */
23static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
24{
25 struct ipv6hdr *iph;
26 u8 *prevhdr;
27 int hdr_len;
28
29 iph = ipv6_hdr(skb);
30 skb_set_inner_transport_header(skb, skb_transport_offset(skb));
31
32 hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
33 if (hdr_len < 0)
34 return hdr_len;
35 skb_set_mac_header(skb, (prevhdr - x->props.header_len) - skb->data);
36 skb_set_network_header(skb, -x->props.header_len);
37 skb->transport_header = skb->network_header + hdr_len;
38 __skb_pull(skb, hdr_len);
39 memmove(ipv6_hdr(skb), iph, hdr_len);
40 return 0;
41}
42
43/* Remove encapsulation header.
44 *
45 * The IP header will be moved over the top of the encapsulation header.
46 *
47 * On entry, skb->h shall point to where the IP header should be and skb->nh
48 * shall be set to where the IP header currently is. skb->data shall point
49 * to the start of the payload.
50 */
51static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
52{
53 int ihl = skb->data - skb_transport_header(skb);
54
55 if (skb->transport_header != skb->network_header) {
56 memmove(skb_transport_header(skb),
57 skb_network_header(skb), ihl);
58 skb->network_header = skb->transport_header;
59 }
60 ipv6_hdr(skb)->payload_len = htons(skb->len + ihl -
61 sizeof(struct ipv6hdr));
62 skb_reset_transport_header(skb);
63 return 0;
64}
65
66static struct sk_buff *xfrm4_transport_gso_segment(struct xfrm_state *x,
67 struct sk_buff *skb,
68 netdev_features_t features)
69{
70 const struct net_offload *ops;
71 struct sk_buff *segs = ERR_PTR(-EINVAL);
72 struct xfrm_offload *xo = xfrm_offload(skb);
73
74 skb->transport_header += x->props.header_len;
75 ops = rcu_dereference(inet6_offloads[xo->proto]);
76 if (likely(ops && ops->callbacks.gso_segment))
77 segs = ops->callbacks.gso_segment(skb, features);
78
79 return segs;
80}
81
82static void xfrm6_transport_xmit(struct xfrm_state *x, struct sk_buff *skb)
83{
84 struct xfrm_offload *xo = xfrm_offload(skb);
85
86 skb_reset_mac_len(skb);
87 pskb_pull(skb, skb->mac_len + sizeof(struct ipv6hdr) + x->props.header_len);
88
89 if (xo->flags & XFRM_GSO_SEGMENT) {
90 skb_reset_transport_header(skb);
91 skb->transport_header -= x->props.header_len;
92 }
93}
94
95
96static struct xfrm_mode xfrm6_transport_mode = {
97 .input = xfrm6_transport_input,
98 .output = xfrm6_transport_output,
99 .gso_segment = xfrm4_transport_gso_segment,
100 .xmit = xfrm6_transport_xmit,
101 .owner = THIS_MODULE,
102 .encap = XFRM_MODE_TRANSPORT,
103};
104
105static int __init xfrm6_transport_init(void)
106{
107 return xfrm_register_mode(&xfrm6_transport_mode, AF_INET6);
108}
109
110static void __exit xfrm6_transport_exit(void)
111{
112 int err;
113
114 err = xfrm_unregister_mode(&xfrm6_transport_mode, AF_INET6);
115 BUG_ON(err);
116}
117
118module_init(xfrm6_transport_init);
119module_exit(xfrm6_transport_exit);
120MODULE_LICENSE("GPL");
121MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TRANSPORT);
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
deleted file mode 100644
index de1b0b8c53b0..000000000000
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ /dev/null
@@ -1,151 +0,0 @@
1/*
2 * xfrm6_mode_tunnel.c - Tunnel mode encapsulation for IPv6.
3 *
4 * Copyright (C) 2002 USAGI/WIDE Project
5 * Copyright (c) 2004-2006 Herbert Xu <herbert@gondor.apana.org.au>
6 */
7
8#include <linux/gfp.h>
9#include <linux/init.h>
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/skbuff.h>
13#include <linux/stringify.h>
14#include <net/dsfield.h>
15#include <net/dst.h>
16#include <net/inet_ecn.h>
17#include <net/ip6_route.h>
18#include <net/ipv6.h>
19#include <net/xfrm.h>
20
21static inline void ipip6_ecn_decapsulate(struct sk_buff *skb)
22{
23 struct ipv6hdr *inner_iph = ipipv6_hdr(skb);
24
25 if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos))
26 IP6_ECN_set_ce(skb, inner_iph);
27}
28
29/* Add encapsulation header.
30 *
31 * The top IP header will be constructed per RFC 2401.
32 */
33static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
34{
35 struct dst_entry *dst = skb_dst(skb);
36 struct ipv6hdr *top_iph;
37 int dsfield;
38
39 skb_set_inner_network_header(skb, skb_network_offset(skb));
40 skb_set_inner_transport_header(skb, skb_transport_offset(skb));
41
42 skb_set_network_header(skb, -x->props.header_len);
43 skb->mac_header = skb->network_header +
44 offsetof(struct ipv6hdr, nexthdr);
45 skb->transport_header = skb->network_header + sizeof(*top_iph);
46 top_iph = ipv6_hdr(skb);
47
48 top_iph->version = 6;
49
50 memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
51 sizeof(top_iph->flow_lbl));
52 top_iph->nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family);
53
54 if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
55 dsfield = 0;
56 else
57 dsfield = XFRM_MODE_SKB_CB(skb)->tos;
58 dsfield = INET_ECN_encapsulate(dsfield, XFRM_MODE_SKB_CB(skb)->tos);
59 if (x->props.flags & XFRM_STATE_NOECN)
60 dsfield &= ~INET_ECN_MASK;
61 ipv6_change_dsfield(top_iph, 0, dsfield);
62 top_iph->hop_limit = ip6_dst_hoplimit(xfrm_dst_child(dst));
63 top_iph->saddr = *(struct in6_addr *)&x->props.saddr;
64 top_iph->daddr = *(struct in6_addr *)&x->id.daddr;
65 return 0;
66}
67
68#define for_each_input_rcu(head, handler) \
69 for (handler = rcu_dereference(head); \
70 handler != NULL; \
71 handler = rcu_dereference(handler->next))
72
73
74static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb)
75{
76 int err = -EINVAL;
77
78 if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6)
79 goto out;
80 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
81 goto out;
82
83 err = skb_unclone(skb, GFP_ATOMIC);
84 if (err)
85 goto out;
86
87 if (x->props.flags & XFRM_STATE_DECAP_DSCP)
88 ipv6_copy_dscp(ipv6_get_dsfield(ipv6_hdr(skb)),
89 ipipv6_hdr(skb));
90 if (!(x->props.flags & XFRM_STATE_NOECN))
91 ipip6_ecn_decapsulate(skb);
92
93 skb_reset_network_header(skb);
94 skb_mac_header_rebuild(skb);
95 if (skb->mac_len)
96 eth_hdr(skb)->h_proto = skb->protocol;
97
98 err = 0;
99
100out:
101 return err;
102}
103
104static struct sk_buff *xfrm6_mode_tunnel_gso_segment(struct xfrm_state *x,
105 struct sk_buff *skb,
106 netdev_features_t features)
107{
108 __skb_push(skb, skb->mac_len);
109 return skb_mac_gso_segment(skb, features);
110}
111
112static void xfrm6_mode_tunnel_xmit(struct xfrm_state *x, struct sk_buff *skb)
113{
114 struct xfrm_offload *xo = xfrm_offload(skb);
115
116 if (xo->flags & XFRM_GSO_SEGMENT)
117 skb->transport_header = skb->network_header + sizeof(struct ipv6hdr);
118
119 skb_reset_mac_len(skb);
120 pskb_pull(skb, skb->mac_len + x->props.header_len);
121}
122
123static struct xfrm_mode xfrm6_tunnel_mode = {
124 .input2 = xfrm6_mode_tunnel_input,
125 .input = xfrm_prepare_input,
126 .output2 = xfrm6_mode_tunnel_output,
127 .output = xfrm6_prepare_output,
128 .gso_segment = xfrm6_mode_tunnel_gso_segment,
129 .xmit = xfrm6_mode_tunnel_xmit,
130 .owner = THIS_MODULE,
131 .encap = XFRM_MODE_TUNNEL,
132 .flags = XFRM_MODE_FLAG_TUNNEL,
133};
134
135static int __init xfrm6_mode_tunnel_init(void)
136{
137 return xfrm_register_mode(&xfrm6_tunnel_mode, AF_INET6);
138}
139
140static void __exit xfrm6_mode_tunnel_exit(void)
141{
142 int err;
143
144 err = xfrm_unregister_mode(&xfrm6_tunnel_mode, AF_INET6);
145 BUG_ON(err);
146}
147
148module_init(xfrm6_mode_tunnel_init);
149module_exit(xfrm6_mode_tunnel_exit);
150MODULE_LICENSE("GPL");
151MODULE_ALIAS_XFRM_MODE(AF_INET6, XFRM_MODE_TUNNEL);
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 6a74080005cf..8ad5e54eb8ca 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -111,21 +111,6 @@ int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb)
111 return xfrm6_extract_header(skb); 111 return xfrm6_extract_header(skb);
112} 112}
113 113
114int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
115{
116 int err;
117
118 err = xfrm_inner_extract_output(x, skb);
119 if (err)
120 return err;
121
122 skb->ignore_df = 1;
123 skb->protocol = htons(ETH_P_IPV6);
124
125 return x->outer_mode->output2(x, skb);
126}
127EXPORT_SYMBOL(xfrm6_prepare_output);
128
129int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb) 114int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb)
130{ 115{
131 memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); 116 memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
@@ -137,11 +122,28 @@ int xfrm6_output_finish(struct sock *sk, struct sk_buff *skb)
137 return xfrm_output(sk, skb); 122 return xfrm_output(sk, skb);
138} 123}
139 124
125static int __xfrm6_output_state_finish(struct xfrm_state *x, struct sock *sk,
126 struct sk_buff *skb)
127{
128 const struct xfrm_state_afinfo *afinfo;
129 int ret = -EAFNOSUPPORT;
130
131 rcu_read_lock();
132 afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family);
133 if (likely(afinfo))
134 ret = afinfo->output_finish(sk, skb);
135 else
136 kfree_skb(skb);
137 rcu_read_unlock();
138
139 return ret;
140}
141
140static int __xfrm6_output_finish(struct net *net, struct sock *sk, struct sk_buff *skb) 142static int __xfrm6_output_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
141{ 143{
142 struct xfrm_state *x = skb_dst(skb)->xfrm; 144 struct xfrm_state *x = skb_dst(skb)->xfrm;
143 145
144 return x->outer_mode->afinfo->output_finish(sk, skb); 146 return __xfrm6_output_state_finish(x, sk, skb);
145} 147}
146 148
147static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) 149static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
@@ -183,7 +185,7 @@ static int __xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
183 __xfrm6_output_finish); 185 __xfrm6_output_finish);
184 186
185skip_frag: 187skip_frag:
186 return x->outer_mode->afinfo->output_finish(sk, skb); 188 return __xfrm6_output_state_finish(x, sk, skb);
187} 189}
188 190
189int xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb) 191int xfrm6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
index 769f8f78d3b8..699e0730ce8e 100644
--- a/net/ipv6/xfrm6_policy.c
+++ b/net/ipv6/xfrm6_policy.c
@@ -22,9 +22,6 @@
22#include <net/ipv6.h> 22#include <net/ipv6.h>
23#include <net/ip6_route.h> 23#include <net/ip6_route.h>
24#include <net/l3mdev.h> 24#include <net/l3mdev.h>
25#if IS_ENABLED(CONFIG_IPV6_MIP6)
26#include <net/mip6.h>
27#endif
28 25
29static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif, 26static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
30 const xfrm_address_t *saddr, 27 const xfrm_address_t *saddr,
@@ -71,24 +68,6 @@ static int xfrm6_get_saddr(struct net *net, int oif,
71 return 0; 68 return 0;
72} 69}
73 70
74static int xfrm6_get_tos(const struct flowi *fl)
75{
76 return 0;
77}
78
79static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst,
80 int nfheader_len)
81{
82 if (dst->ops->family == AF_INET6) {
83 struct rt6_info *rt = (struct rt6_info *)dst;
84 path->path_cookie = rt6_get_cookie(rt);
85 }
86
87 path->u.rt6.rt6i_nfheader_len = nfheader_len;
88
89 return 0;
90}
91
92static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, 71static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
93 const struct flowi *fl) 72 const struct flowi *fl)
94{ 73{
@@ -118,108 +97,6 @@ static int xfrm6_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
118 return 0; 97 return 0;
119} 98}
120 99
121static inline void
122_decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse)
123{
124 struct flowi6 *fl6 = &fl->u.ip6;
125 int onlyproto = 0;
126 const struct ipv6hdr *hdr = ipv6_hdr(skb);
127 u32 offset = sizeof(*hdr);
128 struct ipv6_opt_hdr *exthdr;
129 const unsigned char *nh = skb_network_header(skb);
130 u16 nhoff = IP6CB(skb)->nhoff;
131 int oif = 0;
132 u8 nexthdr;
133
134 if (!nhoff)
135 nhoff = offsetof(struct ipv6hdr, nexthdr);
136
137 nexthdr = nh[nhoff];
138
139 if (skb_dst(skb))
140 oif = skb_dst(skb)->dev->ifindex;
141
142 memset(fl6, 0, sizeof(struct flowi6));
143 fl6->flowi6_mark = skb->mark;
144 fl6->flowi6_oif = reverse ? skb->skb_iif : oif;
145
146 fl6->daddr = reverse ? hdr->saddr : hdr->daddr;
147 fl6->saddr = reverse ? hdr->daddr : hdr->saddr;
148
149 while (nh + offset + sizeof(*exthdr) < skb->data ||
150 pskb_may_pull(skb, nh + offset + sizeof(*exthdr) - skb->data)) {
151 nh = skb_network_header(skb);
152 exthdr = (struct ipv6_opt_hdr *)(nh + offset);
153
154 switch (nexthdr) {
155 case NEXTHDR_FRAGMENT:
156 onlyproto = 1;
157 /* fall through */
158 case NEXTHDR_ROUTING:
159 case NEXTHDR_HOP:
160 case NEXTHDR_DEST:
161 offset += ipv6_optlen(exthdr);
162 nexthdr = exthdr->nexthdr;
163 exthdr = (struct ipv6_opt_hdr *)(nh + offset);
164 break;
165
166 case IPPROTO_UDP:
167 case IPPROTO_UDPLITE:
168 case IPPROTO_TCP:
169 case IPPROTO_SCTP:
170 case IPPROTO_DCCP:
171 if (!onlyproto && (nh + offset + 4 < skb->data ||
172 pskb_may_pull(skb, nh + offset + 4 - skb->data))) {
173 __be16 *ports;
174
175 nh = skb_network_header(skb);
176 ports = (__be16 *)(nh + offset);
177 fl6->fl6_sport = ports[!!reverse];
178 fl6->fl6_dport = ports[!reverse];
179 }
180 fl6->flowi6_proto = nexthdr;
181 return;
182
183 case IPPROTO_ICMPV6:
184 if (!onlyproto && (nh + offset + 2 < skb->data ||
185 pskb_may_pull(skb, nh + offset + 2 - skb->data))) {
186 u8 *icmp;
187
188 nh = skb_network_header(skb);
189 icmp = (u8 *)(nh + offset);
190 fl6->fl6_icmp_type = icmp[0];
191 fl6->fl6_icmp_code = icmp[1];
192 }
193 fl6->flowi6_proto = nexthdr;
194 return;
195
196#if IS_ENABLED(CONFIG_IPV6_MIP6)
197 case IPPROTO_MH:
198 offset += ipv6_optlen(exthdr);
199 if (!onlyproto && (nh + offset + 3 < skb->data ||
200 pskb_may_pull(skb, nh + offset + 3 - skb->data))) {
201 struct ip6_mh *mh;
202
203 nh = skb_network_header(skb);
204 mh = (struct ip6_mh *)(nh + offset);
205 fl6->fl6_mh_type = mh->ip6mh_type;
206 }
207 fl6->flowi6_proto = nexthdr;
208 return;
209#endif
210
211 /* XXX Why are there these headers? */
212 case IPPROTO_AH:
213 case IPPROTO_ESP:
214 case IPPROTO_COMP:
215 default:
216 fl6->fl6_ipsec_spi = 0;
217 fl6->flowi6_proto = nexthdr;
218 return;
219 }
220 }
221}
222
223static void xfrm6_update_pmtu(struct dst_entry *dst, struct sock *sk, 100static void xfrm6_update_pmtu(struct dst_entry *dst, struct sock *sk,
224 struct sk_buff *skb, u32 mtu) 101 struct sk_buff *skb, u32 mtu)
225{ 102{
@@ -291,9 +168,6 @@ static const struct xfrm_policy_afinfo xfrm6_policy_afinfo = {
291 .dst_ops = &xfrm6_dst_ops_template, 168 .dst_ops = &xfrm6_dst_ops_template,
292 .dst_lookup = xfrm6_dst_lookup, 169 .dst_lookup = xfrm6_dst_lookup,
293 .get_saddr = xfrm6_get_saddr, 170 .get_saddr = xfrm6_get_saddr,
294 .decode_session = _decode_session6,
295 .get_tos = xfrm6_get_tos,
296 .init_path = xfrm6_init_path,
297 .fill_dst = xfrm6_fill_dst, 171 .fill_dst = xfrm6_fill_dst,
298 .blackhole_route = ip6_blackhole_route, 172 .blackhole_route = ip6_blackhole_route,
299}; 173};
diff --git a/net/ipv6/xfrm6_protocol.c b/net/ipv6/xfrm6_protocol.c
index cc979b702c89..aaacac7fdbce 100644
--- a/net/ipv6/xfrm6_protocol.c
+++ b/net/ipv6/xfrm6_protocol.c
@@ -46,7 +46,7 @@ static inline struct xfrm6_protocol __rcu **proto_handlers(u8 protocol)
46 handler != NULL; \ 46 handler != NULL; \
47 handler = rcu_dereference(handler->next)) \ 47 handler = rcu_dereference(handler->next)) \
48 48
49int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err) 49static int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
50{ 50{
51 int ret; 51 int ret;
52 struct xfrm6_protocol *handler; 52 struct xfrm6_protocol *handler;
@@ -61,7 +61,6 @@ int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err)
61 61
62 return 0; 62 return 0;
63} 63}
64EXPORT_SYMBOL(xfrm6_rcv_cb);
65 64
66static int xfrm6_esp_rcv(struct sk_buff *skb) 65static int xfrm6_esp_rcv(struct sk_buff *skb)
67{ 66{
diff --git a/net/xfrm/Kconfig b/net/xfrm/Kconfig
index 5d43aaa17027..1ec8071226b2 100644
--- a/net/xfrm/Kconfig
+++ b/net/xfrm/Kconfig
@@ -3,7 +3,7 @@
3# 3#
4config XFRM 4config XFRM
5 bool 5 bool
6 depends on NET 6 depends on INET
7 select GRO_CELLS 7 select GRO_CELLS
8 select SKB_EXTENSIONS 8 select SKB_EXTENSIONS
9 9
@@ -15,9 +15,9 @@ config XFRM_ALGO
15 select XFRM 15 select XFRM
16 select CRYPTO 16 select CRYPTO
17 17
18if INET
18config XFRM_USER 19config XFRM_USER
19 tristate "Transformation user configuration interface" 20 tristate "Transformation user configuration interface"
20 depends on INET
21 select XFRM_ALGO 21 select XFRM_ALGO
22 ---help--- 22 ---help---
23 Support for Transformation(XFRM) user configuration interface 23 Support for Transformation(XFRM) user configuration interface
@@ -56,7 +56,7 @@ config XFRM_MIGRATE
56 56
57config XFRM_STATISTICS 57config XFRM_STATISTICS
58 bool "Transformation statistics" 58 bool "Transformation statistics"
59 depends on INET && XFRM && PROC_FS 59 depends on XFRM && PROC_FS
60 ---help--- 60 ---help---
61 This statistics is not a SNMP/MIB specification but shows 61 This statistics is not a SNMP/MIB specification but shows
62 statistics about transformation error (or almost error) factor 62 statistics about transformation error (or almost error) factor
@@ -95,3 +95,5 @@ config NET_KEY_MIGRATE
95 <draft-sugimoto-mip6-pfkey-migrate>. 95 <draft-sugimoto-mip6-pfkey-migrate>.
96 96
97 If unsure, say N. 97 If unsure, say N.
98
99endif # INET
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index 2db1626557c5..b24cd86a02c3 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -23,6 +23,60 @@
23#include <linux/notifier.h> 23#include <linux/notifier.h>
24 24
25#ifdef CONFIG_XFRM_OFFLOAD 25#ifdef CONFIG_XFRM_OFFLOAD
26static void __xfrm_transport_prep(struct xfrm_state *x, struct sk_buff *skb,
27 unsigned int hsize)
28{
29 struct xfrm_offload *xo = xfrm_offload(skb);
30
31 skb_reset_mac_len(skb);
32 pskb_pull(skb, skb->mac_len + hsize + x->props.header_len);
33
34 if (xo->flags & XFRM_GSO_SEGMENT) {
35 skb_reset_transport_header(skb);
36 skb->transport_header -= x->props.header_len;
37 }
38}
39
40static void __xfrm_mode_tunnel_prep(struct xfrm_state *x, struct sk_buff *skb,
41 unsigned int hsize)
42
43{
44 struct xfrm_offload *xo = xfrm_offload(skb);
45
46 if (xo->flags & XFRM_GSO_SEGMENT)
47 skb->transport_header = skb->network_header + hsize;
48
49 skb_reset_mac_len(skb);
50 pskb_pull(skb, skb->mac_len + x->props.header_len);
51}
52
53/* Adjust pointers into the packet when IPsec is done at layer2 */
54static void xfrm_outer_mode_prep(struct xfrm_state *x, struct sk_buff *skb)
55{
56 switch (x->outer_mode.encap) {
57 case XFRM_MODE_TUNNEL:
58 if (x->outer_mode.family == AF_INET)
59 return __xfrm_mode_tunnel_prep(x, skb,
60 sizeof(struct iphdr));
61 if (x->outer_mode.family == AF_INET6)
62 return __xfrm_mode_tunnel_prep(x, skb,
63 sizeof(struct ipv6hdr));
64 break;
65 case XFRM_MODE_TRANSPORT:
66 if (x->outer_mode.family == AF_INET)
67 return __xfrm_transport_prep(x, skb,
68 sizeof(struct iphdr));
69 if (x->outer_mode.family == AF_INET6)
70 return __xfrm_transport_prep(x, skb,
71 sizeof(struct ipv6hdr));
72 break;
73 case XFRM_MODE_ROUTEOPTIMIZATION:
74 case XFRM_MODE_IN_TRIGGER:
75 case XFRM_MODE_BEET:
76 break;
77 }
78}
79
26struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features, bool *again) 80struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features, bool *again)
27{ 81{
28 int err; 82 int err;
@@ -78,7 +132,8 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
78 } 132 }
79 133
80 if (!skb->next) { 134 if (!skb->next) {
81 x->outer_mode->xmit(x, skb); 135 esp_features |= skb->dev->gso_partial_features;
136 xfrm_outer_mode_prep(x, skb);
82 137
83 xo->flags |= XFRM_DEV_RESUME; 138 xo->flags |= XFRM_DEV_RESUME;
84 139
@@ -101,12 +156,14 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
101 156
102 do { 157 do {
103 struct sk_buff *nskb = skb2->next; 158 struct sk_buff *nskb = skb2->next;
159
160 esp_features |= skb->dev->gso_partial_features;
104 skb_mark_not_on_list(skb2); 161 skb_mark_not_on_list(skb2);
105 162
106 xo = xfrm_offload(skb2); 163 xo = xfrm_offload(skb2);
107 xo->flags |= XFRM_DEV_RESUME; 164 xo->flags |= XFRM_DEV_RESUME;
108 165
109 x->outer_mode->xmit(x, skb2); 166 xfrm_outer_mode_prep(x, skb2);
110 167
111 err = x->type_offload->xmit(x, skb2, esp_features); 168 err = x->type_offload->xmit(x, skb2, esp_features);
112 if (!err) { 169 if (!err) {
diff --git a/net/xfrm/xfrm_inout.h b/net/xfrm/xfrm_inout.h
new file mode 100644
index 000000000000..c7b0318938e2
--- /dev/null
+++ b/net/xfrm/xfrm_inout.h
@@ -0,0 +1,38 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#include <linux/ipv6.h>
3#include <net/dsfield.h>
4#include <net/xfrm.h>
5
6#ifndef XFRM_INOUT_H
7#define XFRM_INOUT_H 1
8
9static inline void xfrm6_beet_make_header(struct sk_buff *skb)
10{
11 struct ipv6hdr *iph = ipv6_hdr(skb);
12
13 iph->version = 6;
14
15 memcpy(iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
16 sizeof(iph->flow_lbl));
17 iph->nexthdr = XFRM_MODE_SKB_CB(skb)->protocol;
18
19 ipv6_change_dsfield(iph, 0, XFRM_MODE_SKB_CB(skb)->tos);
20 iph->hop_limit = XFRM_MODE_SKB_CB(skb)->ttl;
21}
22
23static inline void xfrm4_beet_make_header(struct sk_buff *skb)
24{
25 struct iphdr *iph = ip_hdr(skb);
26
27 iph->ihl = 5;
28 iph->version = 4;
29
30 iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol;
31 iph->tos = XFRM_MODE_SKB_CB(skb)->tos;
32
33 iph->id = XFRM_MODE_SKB_CB(skb)->id;
34 iph->frag_off = XFRM_MODE_SKB_CB(skb)->frag_off;
35 iph->ttl = XFRM_MODE_SKB_CB(skb)->ttl;
36}
37
38#endif
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index b3b613660d44..314973aaa414 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -21,6 +21,8 @@
21#include <net/ip_tunnels.h> 21#include <net/ip_tunnels.h>
22#include <net/ip6_tunnel.h> 22#include <net/ip6_tunnel.h>
23 23
24#include "xfrm_inout.h"
25
24struct xfrm_trans_tasklet { 26struct xfrm_trans_tasklet {
25 struct tasklet_struct tasklet; 27 struct tasklet_struct tasklet;
26 struct sk_buff_head queue; 28 struct sk_buff_head queue;
@@ -166,35 +168,299 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, __be32 *spi, __be32 *seq)
166} 168}
167EXPORT_SYMBOL(xfrm_parse_spi); 169EXPORT_SYMBOL(xfrm_parse_spi);
168 170
169int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb) 171static int xfrm4_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb)
172{
173 struct iphdr *iph;
174 int optlen = 0;
175 int err = -EINVAL;
176
177 if (unlikely(XFRM_MODE_SKB_CB(skb)->protocol == IPPROTO_BEETPH)) {
178 struct ip_beet_phdr *ph;
179 int phlen;
180
181 if (!pskb_may_pull(skb, sizeof(*ph)))
182 goto out;
183
184 ph = (struct ip_beet_phdr *)skb->data;
185
186 phlen = sizeof(*ph) + ph->padlen;
187 optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen);
188 if (optlen < 0 || optlen & 3 || optlen > 250)
189 goto out;
190
191 XFRM_MODE_SKB_CB(skb)->protocol = ph->nexthdr;
192
193 if (!pskb_may_pull(skb, phlen))
194 goto out;
195 __skb_pull(skb, phlen);
196 }
197
198 skb_push(skb, sizeof(*iph));
199 skb_reset_network_header(skb);
200 skb_mac_header_rebuild(skb);
201
202 xfrm4_beet_make_header(skb);
203
204 iph = ip_hdr(skb);
205
206 iph->ihl += optlen / 4;
207 iph->tot_len = htons(skb->len);
208 iph->daddr = x->sel.daddr.a4;
209 iph->saddr = x->sel.saddr.a4;
210 iph->check = 0;
211 iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl);
212 err = 0;
213out:
214 return err;
215}
216
217static void ipip_ecn_decapsulate(struct sk_buff *skb)
218{
219 struct iphdr *inner_iph = ipip_hdr(skb);
220
221 if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos))
222 IP_ECN_set_ce(inner_iph);
223}
224
225static int xfrm4_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb)
170{ 226{
171 struct xfrm_mode *inner_mode = x->inner_mode; 227 int err = -EINVAL;
228
229 if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP)
230 goto out;
231
232 if (!pskb_may_pull(skb, sizeof(struct iphdr)))
233 goto out;
234
235 err = skb_unclone(skb, GFP_ATOMIC);
236 if (err)
237 goto out;
238
239 if (x->props.flags & XFRM_STATE_DECAP_DSCP)
240 ipv4_copy_dscp(XFRM_MODE_SKB_CB(skb)->tos, ipip_hdr(skb));
241 if (!(x->props.flags & XFRM_STATE_NOECN))
242 ipip_ecn_decapsulate(skb);
243
244 skb_reset_network_header(skb);
245 skb_mac_header_rebuild(skb);
246 if (skb->mac_len)
247 eth_hdr(skb)->h_proto = skb->protocol;
248
249 err = 0;
250
251out:
252 return err;
253}
254
255static void ipip6_ecn_decapsulate(struct sk_buff *skb)
256{
257 struct ipv6hdr *inner_iph = ipipv6_hdr(skb);
258
259 if (INET_ECN_is_ce(XFRM_MODE_SKB_CB(skb)->tos))
260 IP6_ECN_set_ce(skb, inner_iph);
261}
262
263static int xfrm6_remove_tunnel_encap(struct xfrm_state *x, struct sk_buff *skb)
264{
265 int err = -EINVAL;
266
267 if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6)
268 goto out;
269 if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
270 goto out;
271
272 err = skb_unclone(skb, GFP_ATOMIC);
273 if (err)
274 goto out;
275
276 if (x->props.flags & XFRM_STATE_DECAP_DSCP)
277 ipv6_copy_dscp(ipv6_get_dsfield(ipv6_hdr(skb)),
278 ipipv6_hdr(skb));
279 if (!(x->props.flags & XFRM_STATE_NOECN))
280 ipip6_ecn_decapsulate(skb);
281
282 skb_reset_network_header(skb);
283 skb_mac_header_rebuild(skb);
284 if (skb->mac_len)
285 eth_hdr(skb)->h_proto = skb->protocol;
286
287 err = 0;
288
289out:
290 return err;
291}
292
293static int xfrm6_remove_beet_encap(struct xfrm_state *x, struct sk_buff *skb)
294{
295 struct ipv6hdr *ip6h;
296 int size = sizeof(struct ipv6hdr);
172 int err; 297 int err;
173 298
174 err = x->outer_mode->afinfo->extract_input(x, skb); 299 err = skb_cow_head(skb, size + skb->mac_len);
175 if (err) 300 if (err)
301 goto out;
302
303 __skb_push(skb, size);
304 skb_reset_network_header(skb);
305 skb_mac_header_rebuild(skb);
306
307 xfrm6_beet_make_header(skb);
308
309 ip6h = ipv6_hdr(skb);
310 ip6h->payload_len = htons(skb->len - size);
311 ip6h->daddr = x->sel.daddr.in6;
312 ip6h->saddr = x->sel.saddr.in6;
313 err = 0;
314out:
315 return err;
316}
317
318/* Remove encapsulation header.
319 *
320 * The IP header will be moved over the top of the encapsulation
321 * header.
322 *
323 * On entry, the transport header shall point to where the IP header
324 * should be and the network header shall be set to where the IP
325 * header currently is. skb->data shall point to the start of the
326 * payload.
327 */
328static int
329xfrm_inner_mode_encap_remove(struct xfrm_state *x,
330 const struct xfrm_mode *inner_mode,
331 struct sk_buff *skb)
332{
333 switch (inner_mode->encap) {
334 case XFRM_MODE_BEET:
335 if (inner_mode->family == AF_INET)
336 return xfrm4_remove_beet_encap(x, skb);
337 if (inner_mode->family == AF_INET6)
338 return xfrm6_remove_beet_encap(x, skb);
339 break;
340 case XFRM_MODE_TUNNEL:
341 if (inner_mode->family == AF_INET)
342 return xfrm4_remove_tunnel_encap(x, skb);
343 if (inner_mode->family == AF_INET6)
344 return xfrm6_remove_tunnel_encap(x, skb);
345 break;
346 }
347
348 WARN_ON_ONCE(1);
349 return -EOPNOTSUPP;
350}
351
352static int xfrm_prepare_input(struct xfrm_state *x, struct sk_buff *skb)
353{
354 const struct xfrm_mode *inner_mode = &x->inner_mode;
355 const struct xfrm_state_afinfo *afinfo;
356 int err = -EAFNOSUPPORT;
357
358 rcu_read_lock();
359 afinfo = xfrm_state_afinfo_get_rcu(x->outer_mode.family);
360 if (likely(afinfo))
361 err = afinfo->extract_input(x, skb);
362
363 if (err) {
364 rcu_read_unlock();
176 return err; 365 return err;
366 }
177 367
178 if (x->sel.family == AF_UNSPEC) { 368 if (x->sel.family == AF_UNSPEC) {
179 inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); 369 inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
180 if (inner_mode == NULL) 370 if (!inner_mode) {
371 rcu_read_unlock();
181 return -EAFNOSUPPORT; 372 return -EAFNOSUPPORT;
373 }
182 } 374 }
183 375
184 skb->protocol = inner_mode->afinfo->eth_proto; 376 afinfo = xfrm_state_afinfo_get_rcu(inner_mode->family);
185 return inner_mode->input2(x, skb); 377 if (unlikely(!afinfo)) {
378 rcu_read_unlock();
379 return -EAFNOSUPPORT;
380 }
381
382 skb->protocol = afinfo->eth_proto;
383 rcu_read_unlock();
384 return xfrm_inner_mode_encap_remove(x, inner_mode, skb);
385}
386
387/* Remove encapsulation header.
388 *
389 * The IP header will be moved over the top of the encapsulation header.
390 *
391 * On entry, skb_transport_header() shall point to where the IP header
392 * should be and skb_network_header() shall be set to where the IP header
393 * currently is. skb->data shall point to the start of the payload.
394 */
395static int xfrm4_transport_input(struct xfrm_state *x, struct sk_buff *skb)
396{
397 int ihl = skb->data - skb_transport_header(skb);
398
399 if (skb->transport_header != skb->network_header) {
400 memmove(skb_transport_header(skb),
401 skb_network_header(skb), ihl);
402 skb->network_header = skb->transport_header;
403 }
404 ip_hdr(skb)->tot_len = htons(skb->len + ihl);
405 skb_reset_transport_header(skb);
406 return 0;
407}
408
409static int xfrm6_transport_input(struct xfrm_state *x, struct sk_buff *skb)
410{
411#if IS_ENABLED(CONFIG_IPV6)
412 int ihl = skb->data - skb_transport_header(skb);
413
414 if (skb->transport_header != skb->network_header) {
415 memmove(skb_transport_header(skb),
416 skb_network_header(skb), ihl);
417 skb->network_header = skb->transport_header;
418 }
419 ipv6_hdr(skb)->payload_len = htons(skb->len + ihl -
420 sizeof(struct ipv6hdr));
421 skb_reset_transport_header(skb);
422 return 0;
423#else
424 WARN_ON_ONCE(1);
425 return -EAFNOSUPPORT;
426#endif
427}
428
429static int xfrm_inner_mode_input(struct xfrm_state *x,
430 const struct xfrm_mode *inner_mode,
431 struct sk_buff *skb)
432{
433 switch (inner_mode->encap) {
434 case XFRM_MODE_BEET:
435 case XFRM_MODE_TUNNEL:
436 return xfrm_prepare_input(x, skb);
437 case XFRM_MODE_TRANSPORT:
438 if (inner_mode->family == AF_INET)
439 return xfrm4_transport_input(x, skb);
440 if (inner_mode->family == AF_INET6)
441 return xfrm6_transport_input(x, skb);
442 break;
443 case XFRM_MODE_ROUTEOPTIMIZATION:
444 WARN_ON_ONCE(1);
445 break;
446 default:
447 WARN_ON_ONCE(1);
448 break;
449 }
450
451 return -EOPNOTSUPP;
186} 452}
187EXPORT_SYMBOL(xfrm_prepare_input);
188 453
189int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) 454int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
190{ 455{
456 const struct xfrm_state_afinfo *afinfo;
191 struct net *net = dev_net(skb->dev); 457 struct net *net = dev_net(skb->dev);
458 const struct xfrm_mode *inner_mode;
192 int err; 459 int err;
193 __be32 seq; 460 __be32 seq;
194 __be32 seq_hi; 461 __be32 seq_hi;
195 struct xfrm_state *x = NULL; 462 struct xfrm_state *x = NULL;
196 xfrm_address_t *daddr; 463 xfrm_address_t *daddr;
197 struct xfrm_mode *inner_mode;
198 u32 mark = skb->mark; 464 u32 mark = skb->mark;
199 unsigned int family = AF_UNSPEC; 465 unsigned int family = AF_UNSPEC;
200 int decaps = 0; 466 int decaps = 0;
@@ -216,7 +482,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
216 goto drop; 482 goto drop;
217 } 483 }
218 484
219 family = x->outer_mode->afinfo->family; 485 family = x->outer_mode.family;
220 486
221 /* An encap_type of -1 indicates async resumption. */ 487 /* An encap_type of -1 indicates async resumption. */
222 if (encap_type == -1) { 488 if (encap_type == -1) {
@@ -400,7 +666,7 @@ resume:
400 666
401 XFRM_MODE_SKB_CB(skb)->protocol = nexthdr; 667 XFRM_MODE_SKB_CB(skb)->protocol = nexthdr;
402 668
403 inner_mode = x->inner_mode; 669 inner_mode = &x->inner_mode;
404 670
405 if (x->sel.family == AF_UNSPEC) { 671 if (x->sel.family == AF_UNSPEC) {
406 inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); 672 inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
@@ -410,12 +676,12 @@ resume:
410 } 676 }
411 } 677 }
412 678
413 if (inner_mode->input(x, skb)) { 679 if (xfrm_inner_mode_input(x, inner_mode, skb)) {
414 XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR); 680 XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR);
415 goto drop; 681 goto drop;
416 } 682 }
417 683
418 if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) { 684 if (x->outer_mode.flags & XFRM_MODE_FLAG_TUNNEL) {
419 decaps = 1; 685 decaps = 1;
420 break; 686 break;
421 } 687 }
@@ -425,7 +691,7 @@ resume:
425 * transport mode so the outer address is identical. 691 * transport mode so the outer address is identical.
426 */ 692 */
427 daddr = &x->id.daddr; 693 daddr = &x->id.daddr;
428 family = x->outer_mode->afinfo->family; 694 family = x->outer_mode.family;
429 695
430 err = xfrm_parse_spi(skb, nexthdr, &spi, &seq); 696 err = xfrm_parse_spi(skb, nexthdr, &spi, &seq);
431 if (err < 0) { 697 if (err < 0) {
@@ -453,7 +719,12 @@ resume:
453 if (xo) 719 if (xo)
454 xfrm_gro = xo->flags & XFRM_GRO; 720 xfrm_gro = xo->flags & XFRM_GRO;
455 721
456 err = x->inner_mode->afinfo->transport_finish(skb, xfrm_gro || async); 722 err = -EAFNOSUPPORT;
723 rcu_read_lock();
724 afinfo = xfrm_state_afinfo_get_rcu(x->inner_mode.family);
725 if (likely(afinfo))
726 err = afinfo->transport_finish(skb, xfrm_gro || async);
727 rcu_read_unlock();
457 if (xfrm_gro) { 728 if (xfrm_gro) {
458 sp = skb_sec_path(skb); 729 sp = skb_sec_path(skb);
459 if (sp) 730 if (sp)
diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c
index dbb3c1945b5c..b9f118530db6 100644
--- a/net/xfrm/xfrm_interface.c
+++ b/net/xfrm/xfrm_interface.c
@@ -244,8 +244,8 @@ static void xfrmi_scrub_packet(struct sk_buff *skb, bool xnet)
244 244
245static int xfrmi_rcv_cb(struct sk_buff *skb, int err) 245static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
246{ 246{
247 const struct xfrm_mode *inner_mode;
247 struct pcpu_sw_netstats *tstats; 248 struct pcpu_sw_netstats *tstats;
248 struct xfrm_mode *inner_mode;
249 struct net_device *dev; 249 struct net_device *dev;
250 struct xfrm_state *x; 250 struct xfrm_state *x;
251 struct xfrm_if *xi; 251 struct xfrm_if *xi;
@@ -273,7 +273,7 @@ static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
273 xnet = !net_eq(xi->net, dev_net(skb->dev)); 273 xnet = !net_eq(xi->net, dev_net(skb->dev));
274 274
275 if (xnet) { 275 if (xnet) {
276 inner_mode = x->inner_mode; 276 inner_mode = &x->inner_mode;
277 277
278 if (x->sel.family == AF_UNSPEC) { 278 if (x->sel.family == AF_UNSPEC) {
279 inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); 279 inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol);
@@ -285,7 +285,7 @@ static int xfrmi_rcv_cb(struct sk_buff *skb, int err)
285 } 285 }
286 286
287 if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, 287 if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb,
288 inner_mode->afinfo->family)) 288 inner_mode->family))
289 return -EPERM; 289 return -EPERM;
290 } 290 }
291 291
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 9333153bafda..a55510f9ff35 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -17,9 +17,13 @@
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/spinlock.h> 18#include <linux/spinlock.h>
19#include <net/dst.h> 19#include <net/dst.h>
20#include <net/inet_ecn.h>
20#include <net/xfrm.h> 21#include <net/xfrm.h>
21 22
23#include "xfrm_inout.h"
24
22static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb); 25static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb);
26static int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
23 27
24static int xfrm_skb_check_space(struct sk_buff *skb) 28static int xfrm_skb_check_space(struct sk_buff *skb)
25{ 29{
@@ -50,6 +54,360 @@ static struct dst_entry *skb_dst_pop(struct sk_buff *skb)
50 return child; 54 return child;
51} 55}
52 56
57/* Add encapsulation header.
58 *
59 * The IP header will be moved forward to make space for the encapsulation
60 * header.
61 */
62static int xfrm4_transport_output(struct xfrm_state *x, struct sk_buff *skb)
63{
64 struct iphdr *iph = ip_hdr(skb);
65 int ihl = iph->ihl * 4;
66
67 skb_set_inner_transport_header(skb, skb_transport_offset(skb));
68
69 skb_set_network_header(skb, -x->props.header_len);
70 skb->mac_header = skb->network_header +
71 offsetof(struct iphdr, protocol);
72 skb->transport_header = skb->network_header + ihl;
73 __skb_pull(skb, ihl);
74 memmove(skb_network_header(skb), iph, ihl);
75 return 0;
76}
77
78/* Add encapsulation header.
79 *
80 * The IP header and mutable extension headers will be moved forward to make
81 * space for the encapsulation header.
82 */
83static int xfrm6_transport_output(struct xfrm_state *x, struct sk_buff *skb)
84{
85#if IS_ENABLED(CONFIG_IPV6)
86 struct ipv6hdr *iph;
87 u8 *prevhdr;
88 int hdr_len;
89
90 iph = ipv6_hdr(skb);
91 skb_set_inner_transport_header(skb, skb_transport_offset(skb));
92
93 hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
94 if (hdr_len < 0)
95 return hdr_len;
96 skb_set_mac_header(skb,
97 (prevhdr - x->props.header_len) - skb->data);
98 skb_set_network_header(skb, -x->props.header_len);
99 skb->transport_header = skb->network_header + hdr_len;
100 __skb_pull(skb, hdr_len);
101 memmove(ipv6_hdr(skb), iph, hdr_len);
102 return 0;
103#else
104 WARN_ON_ONCE(1);
105 return -EAFNOSUPPORT;
106#endif
107}
108
109/* Add route optimization header space.
110 *
111 * The IP header and mutable extension headers will be moved forward to make
112 * space for the route optimization header.
113 */
114static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
115{
116#if IS_ENABLED(CONFIG_IPV6)
117 struct ipv6hdr *iph;
118 u8 *prevhdr;
119 int hdr_len;
120
121 iph = ipv6_hdr(skb);
122
123 hdr_len = x->type->hdr_offset(x, skb, &prevhdr);
124 if (hdr_len < 0)
125 return hdr_len;
126 skb_set_mac_header(skb,
127 (prevhdr - x->props.header_len) - skb->data);
128 skb_set_network_header(skb, -x->props.header_len);
129 skb->transport_header = skb->network_header + hdr_len;
130 __skb_pull(skb, hdr_len);
131 memmove(ipv6_hdr(skb), iph, hdr_len);
132
133 x->lastused = ktime_get_real_seconds();
134
135 return 0;
136#else
137 WARN_ON_ONCE(1);
138 return -EAFNOSUPPORT;
139#endif
140}
141
142/* Add encapsulation header.
143 *
144 * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
145 */
146static int xfrm4_beet_encap_add(struct xfrm_state *x, struct sk_buff *skb)
147{
148 struct ip_beet_phdr *ph;
149 struct iphdr *top_iph;
150 int hdrlen, optlen;
151
152 hdrlen = 0;
153 optlen = XFRM_MODE_SKB_CB(skb)->optlen;
154 if (unlikely(optlen))
155 hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);
156
157 skb_set_network_header(skb, -x->props.header_len - hdrlen +
158 (XFRM_MODE_SKB_CB(skb)->ihl - sizeof(*top_iph)));
159 if (x->sel.family != AF_INET6)
160 skb->network_header += IPV4_BEET_PHMAXLEN;
161 skb->mac_header = skb->network_header +
162 offsetof(struct iphdr, protocol);
163 skb->transport_header = skb->network_header + sizeof(*top_iph);
164
165 xfrm4_beet_make_header(skb);
166
167 ph = __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdrlen);
168
169 top_iph = ip_hdr(skb);
170
171 if (unlikely(optlen)) {
172 if (WARN_ON(optlen < 0))
173 return -EINVAL;
174
175 ph->padlen = 4 - (optlen & 4);
176 ph->hdrlen = optlen / 8;
177 ph->nexthdr = top_iph->protocol;
178 if (ph->padlen)
179 memset(ph + 1, IPOPT_NOP, ph->padlen);
180
181 top_iph->protocol = IPPROTO_BEETPH;
182 top_iph->ihl = sizeof(struct iphdr) / 4;
183 }
184
185 top_iph->saddr = x->props.saddr.a4;
186 top_iph->daddr = x->id.daddr.a4;
187
188 return 0;
189}
190
191/* Add encapsulation header.
192 *
193 * The top IP header will be constructed per RFC 2401.
194 */
195static int xfrm4_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
196{
197 struct dst_entry *dst = skb_dst(skb);
198 struct iphdr *top_iph;
199 int flags;
200
201 skb_set_inner_network_header(skb, skb_network_offset(skb));
202 skb_set_inner_transport_header(skb, skb_transport_offset(skb));
203
204 skb_set_network_header(skb, -x->props.header_len);
205 skb->mac_header = skb->network_header +
206 offsetof(struct iphdr, protocol);
207 skb->transport_header = skb->network_header + sizeof(*top_iph);
208 top_iph = ip_hdr(skb);
209
210 top_iph->ihl = 5;
211 top_iph->version = 4;
212
213 top_iph->protocol = xfrm_af2proto(skb_dst(skb)->ops->family);
214
215 /* DS disclosing depends on XFRM_SA_XFLAG_DONT_ENCAP_DSCP */
216 if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
217 top_iph->tos = 0;
218 else
219 top_iph->tos = XFRM_MODE_SKB_CB(skb)->tos;
220 top_iph->tos = INET_ECN_encapsulate(top_iph->tos,
221 XFRM_MODE_SKB_CB(skb)->tos);
222
223 flags = x->props.flags;
224 if (flags & XFRM_STATE_NOECN)
225 IP_ECN_clear(top_iph);
226
227 top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
228 0 : (XFRM_MODE_SKB_CB(skb)->frag_off & htons(IP_DF));
229
230 top_iph->ttl = ip4_dst_hoplimit(xfrm_dst_child(dst));
231
232 top_iph->saddr = x->props.saddr.a4;
233 top_iph->daddr = x->id.daddr.a4;
234 ip_select_ident(dev_net(dst->dev), skb, NULL);
235
236 return 0;
237}
238
239#if IS_ENABLED(CONFIG_IPV6)
240static int xfrm6_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
241{
242 struct dst_entry *dst = skb_dst(skb);
243 struct ipv6hdr *top_iph;
244 int dsfield;
245
246 skb_set_inner_network_header(skb, skb_network_offset(skb));
247 skb_set_inner_transport_header(skb, skb_transport_offset(skb));
248
249 skb_set_network_header(skb, -x->props.header_len);
250 skb->mac_header = skb->network_header +
251 offsetof(struct ipv6hdr, nexthdr);
252 skb->transport_header = skb->network_header + sizeof(*top_iph);
253 top_iph = ipv6_hdr(skb);
254
255 top_iph->version = 6;
256
257 memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
258 sizeof(top_iph->flow_lbl));
259 top_iph->nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family);
260
261 if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
262 dsfield = 0;
263 else
264 dsfield = XFRM_MODE_SKB_CB(skb)->tos;
265 dsfield = INET_ECN_encapsulate(dsfield, XFRM_MODE_SKB_CB(skb)->tos);
266 if (x->props.flags & XFRM_STATE_NOECN)
267 dsfield &= ~INET_ECN_MASK;
268 ipv6_change_dsfield(top_iph, 0, dsfield);
269 top_iph->hop_limit = ip6_dst_hoplimit(xfrm_dst_child(dst));
270 top_iph->saddr = *(struct in6_addr *)&x->props.saddr;
271 top_iph->daddr = *(struct in6_addr *)&x->id.daddr;
272 return 0;
273}
274
275static int xfrm6_beet_encap_add(struct xfrm_state *x, struct sk_buff *skb)
276{
277 struct ipv6hdr *top_iph;
278 struct ip_beet_phdr *ph;
279 int optlen, hdr_len;
280
281 hdr_len = 0;
282 optlen = XFRM_MODE_SKB_CB(skb)->optlen;
283 if (unlikely(optlen))
284 hdr_len += IPV4_BEET_PHMAXLEN - (optlen & 4);
285
286 skb_set_network_header(skb, -x->props.header_len - hdr_len);
287 if (x->sel.family != AF_INET6)
288 skb->network_header += IPV4_BEET_PHMAXLEN;
289 skb->mac_header = skb->network_header +
290 offsetof(struct ipv6hdr, nexthdr);
291 skb->transport_header = skb->network_header + sizeof(*top_iph);
292 ph = __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdr_len);
293
294 xfrm6_beet_make_header(skb);
295
296 top_iph = ipv6_hdr(skb);
297 if (unlikely(optlen)) {
298 if (WARN_ON(optlen < 0))
299 return -EINVAL;
300
301 ph->padlen = 4 - (optlen & 4);
302 ph->hdrlen = optlen / 8;
303 ph->nexthdr = top_iph->nexthdr;
304 if (ph->padlen)
305 memset(ph + 1, IPOPT_NOP, ph->padlen);
306
307 top_iph->nexthdr = IPPROTO_BEETPH;
308 }
309
310 top_iph->saddr = *(struct in6_addr *)&x->props.saddr;
311 top_iph->daddr = *(struct in6_addr *)&x->id.daddr;
312 return 0;
313}
314#endif
315
316/* Add encapsulation header.
317 *
318 * On exit, the transport header will be set to the start of the
319 * encapsulation header to be filled in by x->type->output and the mac
320 * header will be set to the nextheader (protocol for IPv4) field of the
321 * extension header directly preceding the encapsulation header, or in
322 * its absence, that of the top IP header.
323 * The value of the network header will always point to the top IP header
324 * while skb->data will point to the payload.
325 */
326static int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
327{
328 int err;
329
330 err = xfrm_inner_extract_output(x, skb);
331 if (err)
332 return err;
333
334 IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
335 skb->protocol = htons(ETH_P_IP);
336
337 switch (x->outer_mode.encap) {
338 case XFRM_MODE_BEET:
339 return xfrm4_beet_encap_add(x, skb);
340 case XFRM_MODE_TUNNEL:
341 return xfrm4_tunnel_encap_add(x, skb);
342 }
343
344 WARN_ON_ONCE(1);
345 return -EOPNOTSUPP;
346}
347
348static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
349{
350#if IS_ENABLED(CONFIG_IPV6)
351 int err;
352
353 err = xfrm_inner_extract_output(x, skb);
354 if (err)
355 return err;
356
357 skb->ignore_df = 1;
358 skb->protocol = htons(ETH_P_IPV6);
359
360 switch (x->outer_mode.encap) {
361 case XFRM_MODE_BEET:
362 return xfrm6_beet_encap_add(x, skb);
363 case XFRM_MODE_TUNNEL:
364 return xfrm6_tunnel_encap_add(x, skb);
365 default:
366 WARN_ON_ONCE(1);
367 return -EOPNOTSUPP;
368 }
369#endif
370 WARN_ON_ONCE(1);
371 return -EAFNOSUPPORT;
372}
373
374static int xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
375{
376 switch (x->outer_mode.encap) {
377 case XFRM_MODE_BEET:
378 case XFRM_MODE_TUNNEL:
379 if (x->outer_mode.family == AF_INET)
380 return xfrm4_prepare_output(x, skb);
381 if (x->outer_mode.family == AF_INET6)
382 return xfrm6_prepare_output(x, skb);
383 break;
384 case XFRM_MODE_TRANSPORT:
385 if (x->outer_mode.family == AF_INET)
386 return xfrm4_transport_output(x, skb);
387 if (x->outer_mode.family == AF_INET6)
388 return xfrm6_transport_output(x, skb);
389 break;
390 case XFRM_MODE_ROUTEOPTIMIZATION:
391 if (x->outer_mode.family == AF_INET6)
392 return xfrm6_ro_output(x, skb);
393 WARN_ON_ONCE(1);
394 break;
395 default:
396 WARN_ON_ONCE(1);
397 break;
398 }
399
400 return -EOPNOTSUPP;
401}
402
403#if IS_ENABLED(CONFIG_NET_PKTGEN)
404int pktgen_xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)
405{
406 return xfrm_outer_mode_output(x, skb);
407}
408EXPORT_SYMBOL_GPL(pktgen_xfrm_outer_mode_output);
409#endif
410
53static int xfrm_output_one(struct sk_buff *skb, int err) 411static int xfrm_output_one(struct sk_buff *skb, int err)
54{ 412{
55 struct dst_entry *dst = skb_dst(skb); 413 struct dst_entry *dst = skb_dst(skb);
@@ -68,7 +426,7 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
68 426
69 skb->mark = xfrm_smark_get(skb->mark, x); 427 skb->mark = xfrm_smark_get(skb->mark, x);
70 428
71 err = x->outer_mode->output(x, skb); 429 err = xfrm_outer_mode_output(x, skb);
72 if (err) { 430 if (err) {
73 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR); 431 XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTSTATEMODEERROR);
74 goto error_nolock; 432 goto error_nolock;
@@ -131,7 +489,7 @@ resume:
131 } 489 }
132 skb_dst_set(skb, dst); 490 skb_dst_set(skb, dst);
133 x = dst->xfrm; 491 x = dst->xfrm;
134 } while (x && !(x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL)); 492 } while (x && !(x->outer_mode.flags & XFRM_MODE_FLAG_TUNNEL));
135 493
136 return 0; 494 return 0;
137 495
@@ -258,20 +616,29 @@ out:
258} 616}
259EXPORT_SYMBOL_GPL(xfrm_output); 617EXPORT_SYMBOL_GPL(xfrm_output);
260 618
261int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb) 619static int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb)
262{ 620{
263 struct xfrm_mode *inner_mode; 621 const struct xfrm_state_afinfo *afinfo;
622 const struct xfrm_mode *inner_mode;
623 int err = -EAFNOSUPPORT;
624
264 if (x->sel.family == AF_UNSPEC) 625 if (x->sel.family == AF_UNSPEC)
265 inner_mode = xfrm_ip2inner_mode(x, 626 inner_mode = xfrm_ip2inner_mode(x,
266 xfrm_af2proto(skb_dst(skb)->ops->family)); 627 xfrm_af2proto(skb_dst(skb)->ops->family));
267 else 628 else
268 inner_mode = x->inner_mode; 629 inner_mode = &x->inner_mode;
269 630
270 if (inner_mode == NULL) 631 if (inner_mode == NULL)
271 return -EAFNOSUPPORT; 632 return -EAFNOSUPPORT;
272 return inner_mode->afinfo->extract_output(x, skb); 633
634 rcu_read_lock();
635 afinfo = xfrm_state_afinfo_get_rcu(inner_mode->family);
636 if (likely(afinfo))
637 err = afinfo->extract_output(x, skb);
638 rcu_read_unlock();
639
640 return err;
273} 641}
274EXPORT_SYMBOL_GPL(xfrm_inner_extract_output);
275 642
276void xfrm_local_error(struct sk_buff *skb, int mtu) 643void xfrm_local_error(struct sk_buff *skb, int mtu)
277{ 644{
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 8d1a898d0ba5..03b6bf85d70b 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -27,10 +27,14 @@
27#include <linux/cpu.h> 27#include <linux/cpu.h>
28#include <linux/audit.h> 28#include <linux/audit.h>
29#include <linux/rhashtable.h> 29#include <linux/rhashtable.h>
30#include <linux/if_tunnel.h>
30#include <net/dst.h> 31#include <net/dst.h>
31#include <net/flow.h> 32#include <net/flow.h>
32#include <net/xfrm.h> 33#include <net/xfrm.h>
33#include <net/ip.h> 34#include <net/ip.h>
35#if IS_ENABLED(CONFIG_IPV6_MIP6)
36#include <net/mip6.h>
37#endif
34#ifdef CONFIG_XFRM_STATISTICS 38#ifdef CONFIG_XFRM_STATISTICS
35#include <net/snmp.h> 39#include <net/snmp.h>
36#endif 40#endif
@@ -2450,18 +2454,10 @@ xfrm_tmpl_resolve(struct xfrm_policy **pols, int npols, const struct flowi *fl,
2450 2454
2451static int xfrm_get_tos(const struct flowi *fl, int family) 2455static int xfrm_get_tos(const struct flowi *fl, int family)
2452{ 2456{
2453 const struct xfrm_policy_afinfo *afinfo; 2457 if (family == AF_INET)
2454 int tos; 2458 return IPTOS_RT_MASK & fl->u.ip4.flowi4_tos;
2455 2459
2456 afinfo = xfrm_policy_get_afinfo(family); 2460 return 0;
2457 if (!afinfo)
2458 return 0;
2459
2460 tos = afinfo->get_tos(fl);
2461
2462 rcu_read_unlock();
2463
2464 return tos;
2465} 2461}
2466 2462
2467static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) 2463static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family)
@@ -2499,21 +2495,14 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family)
2499 return xdst; 2495 return xdst;
2500} 2496}
2501 2497
2502static inline int xfrm_init_path(struct xfrm_dst *path, struct dst_entry *dst, 2498static void xfrm_init_path(struct xfrm_dst *path, struct dst_entry *dst,
2503 int nfheader_len) 2499 int nfheader_len)
2504{ 2500{
2505 const struct xfrm_policy_afinfo *afinfo = 2501 if (dst->ops->family == AF_INET6) {
2506 xfrm_policy_get_afinfo(dst->ops->family); 2502 struct rt6_info *rt = (struct rt6_info *)dst;
2507 int err; 2503 path->path_cookie = rt6_get_cookie(rt);
2508 2504 path->u.rt6.rt6i_nfheader_len = nfheader_len;
2509 if (!afinfo) 2505 }
2510 return -EINVAL;
2511
2512 err = afinfo->init_path(path, dst, nfheader_len);
2513
2514 rcu_read_unlock();
2515
2516 return err;
2517} 2506}
2518 2507
2519static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, 2508static inline int xfrm_fill_dst(struct xfrm_dst *xdst, struct net_device *dev,
@@ -2545,10 +2534,11 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
2545 const struct flowi *fl, 2534 const struct flowi *fl,
2546 struct dst_entry *dst) 2535 struct dst_entry *dst)
2547{ 2536{
2537 const struct xfrm_state_afinfo *afinfo;
2538 const struct xfrm_mode *inner_mode;
2548 struct net *net = xp_net(policy); 2539 struct net *net = xp_net(policy);
2549 unsigned long now = jiffies; 2540 unsigned long now = jiffies;
2550 struct net_device *dev; 2541 struct net_device *dev;
2551 struct xfrm_mode *inner_mode;
2552 struct xfrm_dst *xdst_prev = NULL; 2542 struct xfrm_dst *xdst_prev = NULL;
2553 struct xfrm_dst *xdst0 = NULL; 2543 struct xfrm_dst *xdst0 = NULL;
2554 int i = 0; 2544 int i = 0;
@@ -2594,7 +2584,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
2594 goto put_states; 2584 goto put_states;
2595 } 2585 }
2596 } else 2586 } else
2597 inner_mode = xfrm[i]->inner_mode; 2587 inner_mode = &xfrm[i]->inner_mode;
2598 2588
2599 xdst->route = dst; 2589 xdst->route = dst;
2600 dst_copy_metrics(dst1, dst); 2590 dst_copy_metrics(dst1, dst);
@@ -2622,7 +2612,14 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
2622 dst1->lastuse = now; 2612 dst1->lastuse = now;
2623 2613
2624 dst1->input = dst_discard; 2614 dst1->input = dst_discard;
2625 dst1->output = inner_mode->afinfo->output; 2615
2616 rcu_read_lock();
2617 afinfo = xfrm_state_afinfo_get_rcu(inner_mode->family);
2618 if (likely(afinfo))
2619 dst1->output = afinfo->output;
2620 else
2621 dst1->output = dst_discard_out;
2622 rcu_read_unlock();
2626 2623
2627 xdst_prev = xdst; 2624 xdst_prev = xdst;
2628 2625
@@ -3263,20 +3260,229 @@ xfrm_policy_ok(const struct xfrm_tmpl *tmpl, const struct sec_path *sp, int star
3263 return start; 3260 return start;
3264} 3261}
3265 3262
3263static void
3264decode_session4(struct sk_buff *skb, struct flowi *fl, bool reverse)
3265{
3266 const struct iphdr *iph = ip_hdr(skb);
3267 u8 *xprth = skb_network_header(skb) + iph->ihl * 4;
3268 struct flowi4 *fl4 = &fl->u.ip4;
3269 int oif = 0;
3270
3271 if (skb_dst(skb))
3272 oif = skb_dst(skb)->dev->ifindex;
3273
3274 memset(fl4, 0, sizeof(struct flowi4));
3275 fl4->flowi4_mark = skb->mark;
3276 fl4->flowi4_oif = reverse ? skb->skb_iif : oif;
3277
3278 if (!ip_is_fragment(iph)) {
3279 switch (iph->protocol) {
3280 case IPPROTO_UDP:
3281 case IPPROTO_UDPLITE:
3282 case IPPROTO_TCP:
3283 case IPPROTO_SCTP:
3284 case IPPROTO_DCCP:
3285 if (xprth + 4 < skb->data ||
3286 pskb_may_pull(skb, xprth + 4 - skb->data)) {
3287 __be16 *ports;
3288
3289 xprth = skb_network_header(skb) + iph->ihl * 4;
3290 ports = (__be16 *)xprth;
3291
3292 fl4->fl4_sport = ports[!!reverse];
3293 fl4->fl4_dport = ports[!reverse];
3294 }
3295 break;
3296 case IPPROTO_ICMP:
3297 if (xprth + 2 < skb->data ||
3298 pskb_may_pull(skb, xprth + 2 - skb->data)) {
3299 u8 *icmp;
3300
3301 xprth = skb_network_header(skb) + iph->ihl * 4;
3302 icmp = xprth;
3303
3304 fl4->fl4_icmp_type = icmp[0];
3305 fl4->fl4_icmp_code = icmp[1];
3306 }
3307 break;
3308 case IPPROTO_ESP:
3309 if (xprth + 4 < skb->data ||
3310 pskb_may_pull(skb, xprth + 4 - skb->data)) {
3311 __be32 *ehdr;
3312
3313 xprth = skb_network_header(skb) + iph->ihl * 4;
3314 ehdr = (__be32 *)xprth;
3315
3316 fl4->fl4_ipsec_spi = ehdr[0];
3317 }
3318 break;
3319 case IPPROTO_AH:
3320 if (xprth + 8 < skb->data ||
3321 pskb_may_pull(skb, xprth + 8 - skb->data)) {
3322 __be32 *ah_hdr;
3323
3324 xprth = skb_network_header(skb) + iph->ihl * 4;
3325 ah_hdr = (__be32 *)xprth;
3326
3327 fl4->fl4_ipsec_spi = ah_hdr[1];
3328 }
3329 break;
3330 case IPPROTO_COMP:
3331 if (xprth + 4 < skb->data ||
3332 pskb_may_pull(skb, xprth + 4 - skb->data)) {
3333 __be16 *ipcomp_hdr;
3334
3335 xprth = skb_network_header(skb) + iph->ihl * 4;
3336 ipcomp_hdr = (__be16 *)xprth;
3337
3338 fl4->fl4_ipsec_spi = htonl(ntohs(ipcomp_hdr[1]));
3339 }
3340 break;
3341 case IPPROTO_GRE:
3342 if (xprth + 12 < skb->data ||
3343 pskb_may_pull(skb, xprth + 12 - skb->data)) {
3344 __be16 *greflags;
3345 __be32 *gre_hdr;
3346
3347 xprth = skb_network_header(skb) + iph->ihl * 4;
3348 greflags = (__be16 *)xprth;
3349 gre_hdr = (__be32 *)xprth;
3350
3351 if (greflags[0] & GRE_KEY) {
3352 if (greflags[0] & GRE_CSUM)
3353 gre_hdr++;
3354 fl4->fl4_gre_key = gre_hdr[1];
3355 }
3356 }
3357 break;
3358 default:
3359 fl4->fl4_ipsec_spi = 0;
3360 break;
3361 }
3362 }
3363 fl4->flowi4_proto = iph->protocol;
3364 fl4->daddr = reverse ? iph->saddr : iph->daddr;
3365 fl4->saddr = reverse ? iph->daddr : iph->saddr;
3366 fl4->flowi4_tos = iph->tos;
3367}
3368
3369#if IS_ENABLED(CONFIG_IPV6)
3370static void
3371decode_session6(struct sk_buff *skb, struct flowi *fl, bool reverse)
3372{
3373 struct flowi6 *fl6 = &fl->u.ip6;
3374 int onlyproto = 0;
3375 const struct ipv6hdr *hdr = ipv6_hdr(skb);
3376 u32 offset = sizeof(*hdr);
3377 struct ipv6_opt_hdr *exthdr;
3378 const unsigned char *nh = skb_network_header(skb);
3379 u16 nhoff = IP6CB(skb)->nhoff;
3380 int oif = 0;
3381 u8 nexthdr;
3382
3383 if (!nhoff)
3384 nhoff = offsetof(struct ipv6hdr, nexthdr);
3385
3386 nexthdr = nh[nhoff];
3387
3388 if (skb_dst(skb))
3389 oif = skb_dst(skb)->dev->ifindex;
3390
3391 memset(fl6, 0, sizeof(struct flowi6));
3392 fl6->flowi6_mark = skb->mark;
3393 fl6->flowi6_oif = reverse ? skb->skb_iif : oif;
3394
3395 fl6->daddr = reverse ? hdr->saddr : hdr->daddr;
3396 fl6->saddr = reverse ? hdr->daddr : hdr->saddr;
3397
3398 while (nh + offset + sizeof(*exthdr) < skb->data ||
3399 pskb_may_pull(skb, nh + offset + sizeof(*exthdr) - skb->data)) {
3400 nh = skb_network_header(skb);
3401 exthdr = (struct ipv6_opt_hdr *)(nh + offset);
3402
3403 switch (nexthdr) {
3404 case NEXTHDR_FRAGMENT:
3405 onlyproto = 1;
3406 /* fall through */
3407 case NEXTHDR_ROUTING:
3408 case NEXTHDR_HOP:
3409 case NEXTHDR_DEST:
3410 offset += ipv6_optlen(exthdr);
3411 nexthdr = exthdr->nexthdr;
3412 exthdr = (struct ipv6_opt_hdr *)(nh + offset);
3413 break;
3414 case IPPROTO_UDP:
3415 case IPPROTO_UDPLITE:
3416 case IPPROTO_TCP:
3417 case IPPROTO_SCTP:
3418 case IPPROTO_DCCP:
3419 if (!onlyproto && (nh + offset + 4 < skb->data ||
3420 pskb_may_pull(skb, nh + offset + 4 - skb->data))) {
3421 __be16 *ports;
3422
3423 nh = skb_network_header(skb);
3424 ports = (__be16 *)(nh + offset);
3425 fl6->fl6_sport = ports[!!reverse];
3426 fl6->fl6_dport = ports[!reverse];
3427 }
3428 fl6->flowi6_proto = nexthdr;
3429 return;
3430 case IPPROTO_ICMPV6:
3431 if (!onlyproto && (nh + offset + 2 < skb->data ||
3432 pskb_may_pull(skb, nh + offset + 2 - skb->data))) {
3433 u8 *icmp;
3434
3435 nh = skb_network_header(skb);
3436 icmp = (u8 *)(nh + offset);
3437 fl6->fl6_icmp_type = icmp[0];
3438 fl6->fl6_icmp_code = icmp[1];
3439 }
3440 fl6->flowi6_proto = nexthdr;
3441 return;
3442#if IS_ENABLED(CONFIG_IPV6_MIP6)
3443 case IPPROTO_MH:
3444 offset += ipv6_optlen(exthdr);
3445 if (!onlyproto && (nh + offset + 3 < skb->data ||
3446 pskb_may_pull(skb, nh + offset + 3 - skb->data))) {
3447 struct ip6_mh *mh;
3448
3449 nh = skb_network_header(skb);
3450 mh = (struct ip6_mh *)(nh + offset);
3451 fl6->fl6_mh_type = mh->ip6mh_type;
3452 }
3453 fl6->flowi6_proto = nexthdr;
3454 return;
3455#endif
3456 /* XXX Why are there these headers? */
3457 case IPPROTO_AH:
3458 case IPPROTO_ESP:
3459 case IPPROTO_COMP:
3460 default:
3461 fl6->fl6_ipsec_spi = 0;
3462 fl6->flowi6_proto = nexthdr;
3463 return;
3464 }
3465 }
3466}
3467#endif
3468
3266int __xfrm_decode_session(struct sk_buff *skb, struct flowi *fl, 3469int __xfrm_decode_session(struct sk_buff *skb, struct flowi *fl,
3267 unsigned int family, int reverse) 3470 unsigned int family, int reverse)
3268{ 3471{
3269 const struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family); 3472 switch (family) {
3270 int err; 3473 case AF_INET:
3271 3474 decode_session4(skb, fl, reverse);
3272 if (unlikely(afinfo == NULL)) 3475 break;
3476#if IS_ENABLED(CONFIG_IPV6)
3477 case AF_INET6:
3478 decode_session6(skb, fl, reverse);
3479 break;
3480#endif
3481 default:
3273 return -EAFNOSUPPORT; 3482 return -EAFNOSUPPORT;
3483 }
3274 3484
3275 afinfo->decode_session(skb, fl, reverse); 3485 return security_xfrm_decode_session(skb, &fl->flowi_secid);
3276
3277 err = security_xfrm_decode_session(skb, &fl->flowi_secid);
3278 rcu_read_unlock();
3279 return err;
3280} 3486}
3281EXPORT_SYMBOL(__xfrm_decode_session); 3487EXPORT_SYMBOL(__xfrm_decode_session);
3282 3488
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 1bb971f46fc6..ed25eb81aabe 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -173,7 +173,7 @@ static DEFINE_SPINLOCK(xfrm_state_gc_lock);
173int __xfrm_state_delete(struct xfrm_state *x); 173int __xfrm_state_delete(struct xfrm_state *x);
174 174
175int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); 175int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol);
176bool km_is_alive(const struct km_event *c); 176static bool km_is_alive(const struct km_event *c);
177void km_state_expired(struct xfrm_state *x, int hard, u32 portid); 177void km_state_expired(struct xfrm_state *x, int hard, u32 portid);
178 178
179static DEFINE_SPINLOCK(xfrm_type_lock); 179static DEFINE_SPINLOCK(xfrm_type_lock);
@@ -330,100 +330,67 @@ static void xfrm_put_type_offload(const struct xfrm_type_offload *type)
330 module_put(type->owner); 330 module_put(type->owner);
331} 331}
332 332
333static DEFINE_SPINLOCK(xfrm_mode_lock); 333static const struct xfrm_mode xfrm4_mode_map[XFRM_MODE_MAX] = {
334int xfrm_register_mode(struct xfrm_mode *mode, int family) 334 [XFRM_MODE_BEET] = {
335{ 335 .encap = XFRM_MODE_BEET,
336 struct xfrm_state_afinfo *afinfo; 336 .flags = XFRM_MODE_FLAG_TUNNEL,
337 struct xfrm_mode **modemap; 337 .family = AF_INET,
338 int err; 338 },
339 339 [XFRM_MODE_TRANSPORT] = {
340 if (unlikely(mode->encap >= XFRM_MODE_MAX)) 340 .encap = XFRM_MODE_TRANSPORT,
341 return -EINVAL; 341 .family = AF_INET,
342 342 },
343 afinfo = xfrm_state_get_afinfo(family); 343 [XFRM_MODE_TUNNEL] = {
344 if (unlikely(afinfo == NULL)) 344 .encap = XFRM_MODE_TUNNEL,
345 return -EAFNOSUPPORT; 345 .flags = XFRM_MODE_FLAG_TUNNEL,
346 346 .family = AF_INET,
347 err = -EEXIST; 347 },
348 modemap = afinfo->mode_map; 348};
349 spin_lock_bh(&xfrm_mode_lock); 349
350 if (modemap[mode->encap]) 350static const struct xfrm_mode xfrm6_mode_map[XFRM_MODE_MAX] = {
351 goto out; 351 [XFRM_MODE_BEET] = {
352 352 .encap = XFRM_MODE_BEET,
353 err = -ENOENT; 353 .flags = XFRM_MODE_FLAG_TUNNEL,
354 if (!try_module_get(afinfo->owner)) 354 .family = AF_INET6,
355 goto out; 355 },
356 356 [XFRM_MODE_ROUTEOPTIMIZATION] = {
357 mode->afinfo = afinfo; 357 .encap = XFRM_MODE_ROUTEOPTIMIZATION,
358 modemap[mode->encap] = mode; 358 .family = AF_INET6,
359 err = 0; 359 },
360 360 [XFRM_MODE_TRANSPORT] = {
361out: 361 .encap = XFRM_MODE_TRANSPORT,
362 spin_unlock_bh(&xfrm_mode_lock); 362 .family = AF_INET6,
363 rcu_read_unlock(); 363 },
364 return err; 364 [XFRM_MODE_TUNNEL] = {
365} 365 .encap = XFRM_MODE_TUNNEL,
366EXPORT_SYMBOL(xfrm_register_mode); 366 .flags = XFRM_MODE_FLAG_TUNNEL,
367 367 .family = AF_INET6,
368int xfrm_unregister_mode(struct xfrm_mode *mode, int family) 368 },
369{ 369};
370 struct xfrm_state_afinfo *afinfo; 370
371 struct xfrm_mode **modemap; 371static const struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
372 int err; 372{
373 373 const struct xfrm_mode *mode;
374 if (unlikely(mode->encap >= XFRM_MODE_MAX))
375 return -EINVAL;
376
377 afinfo = xfrm_state_get_afinfo(family);
378 if (unlikely(afinfo == NULL))
379 return -EAFNOSUPPORT;
380
381 err = -ENOENT;
382 modemap = afinfo->mode_map;
383 spin_lock_bh(&xfrm_mode_lock);
384 if (likely(modemap[mode->encap] == mode)) {
385 modemap[mode->encap] = NULL;
386 module_put(mode->afinfo->owner);
387 err = 0;
388 }
389
390 spin_unlock_bh(&xfrm_mode_lock);
391 rcu_read_unlock();
392 return err;
393}
394EXPORT_SYMBOL(xfrm_unregister_mode);
395
396static struct xfrm_mode *xfrm_get_mode(unsigned int encap, int family)
397{
398 struct xfrm_state_afinfo *afinfo;
399 struct xfrm_mode *mode;
400 int modload_attempted = 0;
401 374
402 if (unlikely(encap >= XFRM_MODE_MAX)) 375 if (unlikely(encap >= XFRM_MODE_MAX))
403 return NULL; 376 return NULL;
404 377
405retry: 378 switch (family) {
406 afinfo = xfrm_state_get_afinfo(family); 379 case AF_INET:
407 if (unlikely(afinfo == NULL)) 380 mode = &xfrm4_mode_map[encap];
408 return NULL; 381 if (mode->family == family)
409 382 return mode;
410 mode = READ_ONCE(afinfo->mode_map[encap]); 383 break;
411 if (unlikely(mode && !try_module_get(mode->owner))) 384 case AF_INET6:
412 mode = NULL; 385 mode = &xfrm6_mode_map[encap];
413 386 if (mode->family == family)
414 rcu_read_unlock(); 387 return mode;
415 if (!mode && !modload_attempted) { 388 break;
416 request_module("xfrm-mode-%d-%d", family, encap); 389 default:
417 modload_attempted = 1; 390 break;
418 goto retry;
419 } 391 }
420 392
421 return mode; 393 return NULL;
422}
423
424static void xfrm_put_mode(struct xfrm_mode *mode)
425{
426 module_put(mode->owner);
427} 394}
428 395
429void xfrm_state_free(struct xfrm_state *x) 396void xfrm_state_free(struct xfrm_state *x)
@@ -444,12 +411,6 @@ static void ___xfrm_state_destroy(struct xfrm_state *x)
444 kfree(x->coaddr); 411 kfree(x->coaddr);
445 kfree(x->replay_esn); 412 kfree(x->replay_esn);
446 kfree(x->preplay_esn); 413 kfree(x->preplay_esn);
447 if (x->inner_mode)
448 xfrm_put_mode(x->inner_mode);
449 if (x->inner_mode_iaf)
450 xfrm_put_mode(x->inner_mode_iaf);
451 if (x->outer_mode)
452 xfrm_put_mode(x->outer_mode);
453 if (x->type_offload) 414 if (x->type_offload)
454 xfrm_put_type_offload(x->type_offload); 415 xfrm_put_type_offload(x->type_offload);
455 if (x->type) { 416 if (x->type) {
@@ -590,8 +551,6 @@ struct xfrm_state *xfrm_state_alloc(struct net *net)
590 x->lft.hard_packet_limit = XFRM_INF; 551 x->lft.hard_packet_limit = XFRM_INF;
591 x->replay_maxage = 0; 552 x->replay_maxage = 0;
592 x->replay_maxdiff = 0; 553 x->replay_maxdiff = 0;
593 x->inner_mode = NULL;
594 x->inner_mode_iaf = NULL;
595 spin_lock_init(&x->lock); 554 spin_lock_init(&x->lock);
596 } 555 }
597 return x; 556 return x;
@@ -2066,7 +2025,7 @@ int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address
2066} 2025}
2067EXPORT_SYMBOL(km_report); 2026EXPORT_SYMBOL(km_report);
2068 2027
2069bool km_is_alive(const struct km_event *c) 2028static bool km_is_alive(const struct km_event *c)
2070{ 2029{
2071 struct xfrm_mgr *km; 2030 struct xfrm_mgr *km;
2072 bool is_alive = false; 2031 bool is_alive = false;
@@ -2082,7 +2041,6 @@ bool km_is_alive(const struct km_event *c)
2082 2041
2083 return is_alive; 2042 return is_alive;
2084} 2043}
2085EXPORT_SYMBOL(km_is_alive);
2086 2044
2087int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen) 2045int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen)
2088{ 2046{
@@ -2195,6 +2153,7 @@ struct xfrm_state_afinfo *xfrm_state_afinfo_get_rcu(unsigned int family)
2195 2153
2196 return rcu_dereference(xfrm_state_afinfo[family]); 2154 return rcu_dereference(xfrm_state_afinfo[family]);
2197} 2155}
2156EXPORT_SYMBOL_GPL(xfrm_state_afinfo_get_rcu);
2198 2157
2199struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family) 2158struct xfrm_state_afinfo *xfrm_state_get_afinfo(unsigned int family)
2200{ 2159{
@@ -2242,8 +2201,9 @@ int xfrm_state_mtu(struct xfrm_state *x, int mtu)
2242 2201
2243int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload) 2202int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
2244{ 2203{
2245 struct xfrm_state_afinfo *afinfo; 2204 const struct xfrm_state_afinfo *afinfo;
2246 struct xfrm_mode *inner_mode; 2205 const struct xfrm_mode *inner_mode;
2206 const struct xfrm_mode *outer_mode;
2247 int family = x->props.family; 2207 int family = x->props.family;
2248 int err; 2208 int err;
2249 2209
@@ -2269,25 +2229,22 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
2269 goto error; 2229 goto error;
2270 2230
2271 if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) && 2231 if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL) &&
2272 family != x->sel.family) { 2232 family != x->sel.family)
2273 xfrm_put_mode(inner_mode);
2274 goto error; 2233 goto error;
2275 }
2276 2234
2277 x->inner_mode = inner_mode; 2235 x->inner_mode = *inner_mode;
2278 } else { 2236 } else {
2279 struct xfrm_mode *inner_mode_iaf; 2237 const struct xfrm_mode *inner_mode_iaf;
2280 int iafamily = AF_INET; 2238 int iafamily = AF_INET;
2281 2239
2282 inner_mode = xfrm_get_mode(x->props.mode, x->props.family); 2240 inner_mode = xfrm_get_mode(x->props.mode, x->props.family);
2283 if (inner_mode == NULL) 2241 if (inner_mode == NULL)
2284 goto error; 2242 goto error;
2285 2243
2286 if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL)) { 2244 if (!(inner_mode->flags & XFRM_MODE_FLAG_TUNNEL))
2287 xfrm_put_mode(inner_mode);
2288 goto error; 2245 goto error;
2289 } 2246
2290 x->inner_mode = inner_mode; 2247 x->inner_mode = *inner_mode;
2291 2248
2292 if (x->props.family == AF_INET) 2249 if (x->props.family == AF_INET)
2293 iafamily = AF_INET6; 2250 iafamily = AF_INET6;
@@ -2295,9 +2252,7 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
2295 inner_mode_iaf = xfrm_get_mode(x->props.mode, iafamily); 2252 inner_mode_iaf = xfrm_get_mode(x->props.mode, iafamily);
2296 if (inner_mode_iaf) { 2253 if (inner_mode_iaf) {
2297 if (inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL) 2254 if (inner_mode_iaf->flags & XFRM_MODE_FLAG_TUNNEL)
2298 x->inner_mode_iaf = inner_mode_iaf; 2255 x->inner_mode_iaf = *inner_mode_iaf;
2299 else
2300 xfrm_put_mode(inner_mode_iaf);
2301 } 2256 }
2302 } 2257 }
2303 2258
@@ -2311,12 +2266,13 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay, bool offload)
2311 if (err) 2266 if (err)
2312 goto error; 2267 goto error;
2313 2268
2314 x->outer_mode = xfrm_get_mode(x->props.mode, family); 2269 outer_mode = xfrm_get_mode(x->props.mode, family);
2315 if (x->outer_mode == NULL) { 2270 if (!outer_mode) {
2316 err = -EPROTONOSUPPORT; 2271 err = -EPROTONOSUPPORT;
2317 goto error; 2272 goto error;
2318 } 2273 }
2319 2274
2275 x->outer_mode = *outer_mode;
2320 if (init_replay) { 2276 if (init_replay) {
2321 err = xfrm_init_replay(x); 2277 err = xfrm_init_replay(x);
2322 if (err) 2278 if (err)