aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/xfrm.h13
-rw-r--r--net/ipv4/xfrm4_mode_beet.c63
-rw-r--r--net/ipv4/xfrm4_mode_tunnel.c49
-rw-r--r--net/ipv6/xfrm6_mode_beet.c58
-rw-r--r--net/ipv6/xfrm6_mode_tunnel.c36
-rw-r--r--net/xfrm/xfrm_output.c212
6 files changed, 207 insertions, 224 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index bdda545cf740..4351444c10fc 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -423,19 +423,6 @@ int xfrm_register_type_offload(const struct xfrm_type_offload *type, unsigned sh
423int xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family); 423int xfrm_unregister_type_offload(const struct xfrm_type_offload *type, unsigned short family);
424 424
425struct xfrm_mode { 425struct xfrm_mode {
426 /*
427 * Add encapsulation header.
428 *
429 * On exit, the transport header will be set to the start of the
430 * encapsulation header to be filled in by x->type->output and
431 * the mac header will be set to the nextheader (protocol for
432 * IPv4) field of the extension header directly preceding the
433 * encapsulation header, or in its absence, that of the top IP
434 * header. The value of the network header will always point
435 * to the top IP header while skb->data will point to the payload.
436 */
437 int (*output2)(struct xfrm_state *x,struct sk_buff *skb);
438
439 struct xfrm_state_afinfo *afinfo; 426 struct xfrm_state_afinfo *afinfo;
440 struct module *owner; 427 struct module *owner;
441 u8 encap; 428 u8 encap;
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 500960172933..ba84b278e627 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -17,71 +17,8 @@
17#include <net/ip.h> 17#include <net/ip.h>
18#include <net/xfrm.h> 18#include <net/xfrm.h>
19 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 20
83static struct xfrm_mode xfrm4_beet_mode = { 21static struct xfrm_mode xfrm4_beet_mode = {
84 .output2 = xfrm4_beet_output,
85 .owner = THIS_MODULE, 22 .owner = THIS_MODULE,
86 .encap = XFRM_MODE_BEET, 23 .encap = XFRM_MODE_BEET,
87 .flags = XFRM_MODE_FLAG_TUNNEL, 24 .flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c
index 31645319aaeb..b2b132c800fc 100644
--- a/net/ipv4/xfrm4_mode_tunnel.c
+++ b/net/ipv4/xfrm4_mode_tunnel.c
@@ -15,56 +15,7 @@
15#include <net/ip.h> 15#include <net/ip.h>
16#include <net/xfrm.h> 16#include <net/xfrm.h>
17 17
18/* Add encapsulation header.
19 *
20 * The top IP header will be constructed per RFC 2401.
21 */
22static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
23{
24 struct dst_entry *dst = skb_dst(skb);
25 struct iphdr *top_iph;
26 int flags;
27
28 skb_set_inner_network_header(skb, skb_network_offset(skb));
29 skb_set_inner_transport_header(skb, skb_transport_offset(skb));
30
31 skb_set_network_header(skb, -x->props.header_len);
32 skb->mac_header = skb->network_header +
33 offsetof(struct iphdr, protocol);
34 skb->transport_header = skb->network_header + sizeof(*top_iph);
35 top_iph = ip_hdr(skb);
36
37 top_iph->ihl = 5;
38 top_iph->version = 4;
39
40 top_iph->protocol = xfrm_af2proto(skb_dst(skb)->ops->family);
41
42 /* DS disclosing depends on XFRM_SA_XFLAG_DONT_ENCAP_DSCP */
43 if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
44 top_iph->tos = 0;
45 else
46 top_iph->tos = XFRM_MODE_SKB_CB(skb)->tos;
47 top_iph->tos = INET_ECN_encapsulate(top_iph->tos,
48 XFRM_MODE_SKB_CB(skb)->tos);
49
50 flags = x->props.flags;
51 if (flags & XFRM_STATE_NOECN)
52 IP_ECN_clear(top_iph);
53
54 top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
55 0 : (XFRM_MODE_SKB_CB(skb)->frag_off & htons(IP_DF));
56
57 top_iph->ttl = ip4_dst_hoplimit(xfrm_dst_child(dst));
58
59 top_iph->saddr = x->props.saddr.a4;
60 top_iph->daddr = x->id.daddr.a4;
61 ip_select_ident(dev_net(dst->dev), skb, NULL);
62
63 return 0;
64}
65
66static struct xfrm_mode xfrm4_tunnel_mode = { 18static struct xfrm_mode xfrm4_tunnel_mode = {
67 .output2 = xfrm4_mode_tunnel_output,
68 .owner = THIS_MODULE, 19 .owner = THIS_MODULE,
69 .encap = XFRM_MODE_TUNNEL, 20 .encap = XFRM_MODE_TUNNEL,
70 .flags = XFRM_MODE_FLAG_TUNNEL, 21 .flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c
index a0537b4f62f8..1c4a76bdd889 100644
--- a/net/ipv6/xfrm6_mode_beet.c
+++ b/net/ipv6/xfrm6_mode_beet.c
@@ -19,65 +19,7 @@
19#include <net/ipv6.h> 19#include <net/ipv6.h>
20#include <net/xfrm.h> 20#include <net/xfrm.h>
21 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}
79static struct xfrm_mode xfrm6_beet_mode = { 22static struct xfrm_mode xfrm6_beet_mode = {
80 .output2 = xfrm6_beet_output,
81 .owner = THIS_MODULE, 23 .owner = THIS_MODULE,
82 .encap = XFRM_MODE_BEET, 24 .encap = XFRM_MODE_BEET,
83 .flags = XFRM_MODE_FLAG_TUNNEL, 25 .flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c
index 79c57decb472..e5c928dd70e3 100644
--- a/net/ipv6/xfrm6_mode_tunnel.c
+++ b/net/ipv6/xfrm6_mode_tunnel.c
@@ -22,43 +22,7 @@
22 * 22 *
23 * The top IP header will be constructed per RFC 2401. 23 * The top IP header will be constructed per RFC 2401.
24 */ 24 */
25static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb)
26{
27 struct dst_entry *dst = skb_dst(skb);
28 struct ipv6hdr *top_iph;
29 int dsfield;
30
31 skb_set_inner_network_header(skb, skb_network_offset(skb));
32 skb_set_inner_transport_header(skb, skb_transport_offset(skb));
33
34 skb_set_network_header(skb, -x->props.header_len);
35 skb->mac_header = skb->network_header +
36 offsetof(struct ipv6hdr, nexthdr);
37 skb->transport_header = skb->network_header + sizeof(*top_iph);
38 top_iph = ipv6_hdr(skb);
39
40 top_iph->version = 6;
41
42 memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
43 sizeof(top_iph->flow_lbl));
44 top_iph->nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family);
45
46 if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
47 dsfield = 0;
48 else
49 dsfield = XFRM_MODE_SKB_CB(skb)->tos;
50 dsfield = INET_ECN_encapsulate(dsfield, XFRM_MODE_SKB_CB(skb)->tos);
51 if (x->props.flags & XFRM_STATE_NOECN)
52 dsfield &= ~INET_ECN_MASK;
53 ipv6_change_dsfield(top_iph, 0, dsfield);
54 top_iph->hop_limit = ip6_dst_hoplimit(xfrm_dst_child(dst));
55 top_iph->saddr = *(struct in6_addr *)&x->props.saddr;
56 top_iph->daddr = *(struct in6_addr *)&x->id.daddr;
57 return 0;
58}
59
60static struct xfrm_mode xfrm6_tunnel_mode = { 25static struct xfrm_mode xfrm6_tunnel_mode = {
61 .output2 = xfrm6_mode_tunnel_output,
62 .owner = THIS_MODULE, 26 .owner = THIS_MODULE,
63 .encap = XFRM_MODE_TUNNEL, 27 .encap = XFRM_MODE_TUNNEL,
64 .flags = XFRM_MODE_FLAG_TUNNEL, 28 .flags = XFRM_MODE_FLAG_TUNNEL,
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 05926dcf5d17..9bdf16f13606 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -17,8 +17,11 @@
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);
23static int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb); 26static int xfrm_inner_extract_output(struct xfrm_state *x, struct sk_buff *skb);
24 27
@@ -141,6 +144,190 @@ static int xfrm6_ro_output(struct xfrm_state *x, struct sk_buff *skb)
141#endif 144#endif
142} 145}
143 146
147/* Add encapsulation header.
148 *
149 * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
150 */
151static int xfrm4_beet_encap_add(struct xfrm_state *x, struct sk_buff *skb)
152{
153 struct ip_beet_phdr *ph;
154 struct iphdr *top_iph;
155 int hdrlen, optlen;
156
157 hdrlen = 0;
158 optlen = XFRM_MODE_SKB_CB(skb)->optlen;
159 if (unlikely(optlen))
160 hdrlen += IPV4_BEET_PHMAXLEN - (optlen & 4);
161
162 skb_set_network_header(skb, -x->props.header_len - hdrlen +
163 (XFRM_MODE_SKB_CB(skb)->ihl - sizeof(*top_iph)));
164 if (x->sel.family != AF_INET6)
165 skb->network_header += IPV4_BEET_PHMAXLEN;
166 skb->mac_header = skb->network_header +
167 offsetof(struct iphdr, protocol);
168 skb->transport_header = skb->network_header + sizeof(*top_iph);
169
170 xfrm4_beet_make_header(skb);
171
172 ph = __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdrlen);
173
174 top_iph = ip_hdr(skb);
175
176 if (unlikely(optlen)) {
177 if (WARN_ON(optlen < 0))
178 return -EINVAL;
179
180 ph->padlen = 4 - (optlen & 4);
181 ph->hdrlen = optlen / 8;
182 ph->nexthdr = top_iph->protocol;
183 if (ph->padlen)
184 memset(ph + 1, IPOPT_NOP, ph->padlen);
185
186 top_iph->protocol = IPPROTO_BEETPH;
187 top_iph->ihl = sizeof(struct iphdr) / 4;
188 }
189
190 top_iph->saddr = x->props.saddr.a4;
191 top_iph->daddr = x->id.daddr.a4;
192
193 return 0;
194}
195
196/* Add encapsulation header.
197 *
198 * The top IP header will be constructed per RFC 2401.
199 */
200static int xfrm4_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
201{
202 struct dst_entry *dst = skb_dst(skb);
203 struct iphdr *top_iph;
204 int flags;
205
206 skb_set_inner_network_header(skb, skb_network_offset(skb));
207 skb_set_inner_transport_header(skb, skb_transport_offset(skb));
208
209 skb_set_network_header(skb, -x->props.header_len);
210 skb->mac_header = skb->network_header +
211 offsetof(struct iphdr, protocol);
212 skb->transport_header = skb->network_header + sizeof(*top_iph);
213 top_iph = ip_hdr(skb);
214
215 top_iph->ihl = 5;
216 top_iph->version = 4;
217
218 top_iph->protocol = xfrm_af2proto(skb_dst(skb)->ops->family);
219
220 /* DS disclosing depends on XFRM_SA_XFLAG_DONT_ENCAP_DSCP */
221 if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
222 top_iph->tos = 0;
223 else
224 top_iph->tos = XFRM_MODE_SKB_CB(skb)->tos;
225 top_iph->tos = INET_ECN_encapsulate(top_iph->tos,
226 XFRM_MODE_SKB_CB(skb)->tos);
227
228 flags = x->props.flags;
229 if (flags & XFRM_STATE_NOECN)
230 IP_ECN_clear(top_iph);
231
232 top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ?
233 0 : (XFRM_MODE_SKB_CB(skb)->frag_off & htons(IP_DF));
234
235 top_iph->ttl = ip4_dst_hoplimit(xfrm_dst_child(dst));
236
237 top_iph->saddr = x->props.saddr.a4;
238 top_iph->daddr = x->id.daddr.a4;
239 ip_select_ident(dev_net(dst->dev), skb, NULL);
240
241 return 0;
242}
243
244#if IS_ENABLED(CONFIG_IPV6)
245static int xfrm6_tunnel_encap_add(struct xfrm_state *x, struct sk_buff *skb)
246{
247 struct dst_entry *dst = skb_dst(skb);
248 struct ipv6hdr *top_iph;
249 int dsfield;
250
251 skb_set_inner_network_header(skb, skb_network_offset(skb));
252 skb_set_inner_transport_header(skb, skb_transport_offset(skb));
253
254 skb_set_network_header(skb, -x->props.header_len);
255 skb->mac_header = skb->network_header +
256 offsetof(struct ipv6hdr, nexthdr);
257 skb->transport_header = skb->network_header + sizeof(*top_iph);
258 top_iph = ipv6_hdr(skb);
259
260 top_iph->version = 6;
261
262 memcpy(top_iph->flow_lbl, XFRM_MODE_SKB_CB(skb)->flow_lbl,
263 sizeof(top_iph->flow_lbl));
264 top_iph->nexthdr = xfrm_af2proto(skb_dst(skb)->ops->family);
265
266 if (x->props.extra_flags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP)
267 dsfield = 0;
268 else
269 dsfield = XFRM_MODE_SKB_CB(skb)->tos;
270 dsfield = INET_ECN_encapsulate(dsfield, XFRM_MODE_SKB_CB(skb)->tos);
271 if (x->props.flags & XFRM_STATE_NOECN)
272 dsfield &= ~INET_ECN_MASK;
273 ipv6_change_dsfield(top_iph, 0, dsfield);
274 top_iph->hop_limit = ip6_dst_hoplimit(xfrm_dst_child(dst));
275 top_iph->saddr = *(struct in6_addr *)&x->props.saddr;
276 top_iph->daddr = *(struct in6_addr *)&x->id.daddr;
277 return 0;
278}
279
280static int xfrm6_beet_encap_add(struct xfrm_state *x, struct sk_buff *skb)
281{
282 struct ipv6hdr *top_iph;
283 struct ip_beet_phdr *ph;
284 int optlen, hdr_len;
285
286 hdr_len = 0;
287 optlen = XFRM_MODE_SKB_CB(skb)->optlen;
288 if (unlikely(optlen))
289 hdr_len += IPV4_BEET_PHMAXLEN - (optlen & 4);
290
291 skb_set_network_header(skb, -x->props.header_len - hdr_len);
292 if (x->sel.family != AF_INET6)
293 skb->network_header += IPV4_BEET_PHMAXLEN;
294 skb->mac_header = skb->network_header +
295 offsetof(struct ipv6hdr, nexthdr);
296 skb->transport_header = skb->network_header + sizeof(*top_iph);
297 ph = __skb_pull(skb, XFRM_MODE_SKB_CB(skb)->ihl - hdr_len);
298
299 xfrm6_beet_make_header(skb);
300
301 top_iph = ipv6_hdr(skb);
302 if (unlikely(optlen)) {
303 if (WARN_ON(optlen < 0))
304 return -EINVAL;
305
306 ph->padlen = 4 - (optlen & 4);
307 ph->hdrlen = optlen / 8;
308 ph->nexthdr = top_iph->nexthdr;
309 if (ph->padlen)
310 memset(ph + 1, IPOPT_NOP, ph->padlen);
311
312 top_iph->nexthdr = IPPROTO_BEETPH;
313 }
314
315 top_iph->saddr = *(struct in6_addr *)&x->props.saddr;
316 top_iph->daddr = *(struct in6_addr *)&x->id.daddr;
317 return 0;
318}
319#endif
320
321/* Add encapsulation header.
322 *
323 * On exit, the transport header will be set to the start of the
324 * encapsulation header to be filled in by x->type->output and the mac
325 * header will be set to the nextheader (protocol for IPv4) field of the
326 * extension header directly preceding the encapsulation header, or in
327 * its absence, that of the top IP header.
328 * The value of the network header will always point to the top IP header
329 * while skb->data will point to the payload.
330 */
144static int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb) 331static int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
145{ 332{
146 int err; 333 int err;
@@ -152,7 +339,15 @@ static int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
152 IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE; 339 IPCB(skb)->flags |= IPSKB_XFRM_TUNNEL_SIZE;
153 skb->protocol = htons(ETH_P_IP); 340 skb->protocol = htons(ETH_P_IP);
154 341
155 return x->outer_mode->output2(x, skb); 342 switch (x->outer_mode->encap) {
343 case XFRM_MODE_BEET:
344 return xfrm4_beet_encap_add(x, skb);
345 case XFRM_MODE_TUNNEL:
346 return xfrm4_tunnel_encap_add(x, skb);
347 }
348
349 WARN_ON_ONCE(1);
350 return -EOPNOTSUPP;
156} 351}
157 352
158static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb) 353static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
@@ -167,11 +362,18 @@ static int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
167 skb->ignore_df = 1; 362 skb->ignore_df = 1;
168 skb->protocol = htons(ETH_P_IPV6); 363 skb->protocol = htons(ETH_P_IPV6);
169 364
170 return x->outer_mode->output2(x, skb); 365 switch (x->outer_mode->encap) {
171#else 366 case XFRM_MODE_BEET:
172 WARN_ON_ONCE(1); 367 return xfrm6_beet_encap_add(x, skb);
173 return -EOPNOTSUPP; 368 case XFRM_MODE_TUNNEL:
369 return xfrm6_tunnel_encap_add(x, skb);
370 default:
371 WARN_ON_ONCE(1);
372 return -EOPNOTSUPP;
373 }
174#endif 374#endif
375 WARN_ON_ONCE(1);
376 return -EAFNOSUPPORT;
175} 377}
176 378
177static int xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb) 379static int xfrm_outer_mode_output(struct xfrm_state *x, struct sk_buff *skb)