aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/xfrm.h3
-rw-r--r--net/ipv4/xfrm4_output.c8
-rw-r--r--net/ipv4/xfrm4_state.c1
-rw-r--r--net/ipv6/xfrm6_output.c6
-rw-r--r--net/ipv6/xfrm6_state.c1
-rw-r--r--net/xfrm/xfrm_policy.c14
6 files changed, 27 insertions, 6 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 6ae4bc5ce8a7..20afeaa39395 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -324,6 +324,7 @@ struct xfrm_state_afinfo {
324 int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n); 324 int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n);
325 int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n); 325 int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n);
326 int (*output)(struct sk_buff *skb); 326 int (*output)(struct sk_buff *skb);
327 int (*output_finish)(struct sk_buff *skb);
327 int (*extract_input)(struct xfrm_state *x, 328 int (*extract_input)(struct xfrm_state *x,
328 struct sk_buff *skb); 329 struct sk_buff *skb);
329 int (*extract_output)(struct xfrm_state *x, 330 int (*extract_output)(struct xfrm_state *x,
@@ -1454,6 +1455,7 @@ static inline int xfrm4_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
1454extern int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb); 1455extern int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb);
1455extern int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb); 1456extern int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
1456extern int xfrm4_output(struct sk_buff *skb); 1457extern int xfrm4_output(struct sk_buff *skb);
1458extern int xfrm4_output_finish(struct sk_buff *skb);
1457extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family); 1459extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler, unsigned short family);
1458extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family); 1460extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler, unsigned short family);
1459extern int xfrm6_extract_header(struct sk_buff *skb); 1461extern int xfrm6_extract_header(struct sk_buff *skb);
@@ -1470,6 +1472,7 @@ extern __be32 xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr);
1470extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb); 1472extern int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb);
1471extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb); 1473extern int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb);
1472extern int xfrm6_output(struct sk_buff *skb); 1474extern int xfrm6_output(struct sk_buff *skb);
1475extern int xfrm6_output_finish(struct sk_buff *skb);
1473extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb, 1476extern int xfrm6_find_1stfragopt(struct xfrm_state *x, struct sk_buff *skb,
1474 u8 **prevhdr); 1477 u8 **prevhdr);
1475 1478
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c
index 571aa96a175c..2d51840e53a1 100644
--- a/net/ipv4/xfrm4_output.c
+++ b/net/ipv4/xfrm4_output.c
@@ -69,7 +69,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
69} 69}
70EXPORT_SYMBOL(xfrm4_prepare_output); 70EXPORT_SYMBOL(xfrm4_prepare_output);
71 71
72static int xfrm4_output_finish(struct sk_buff *skb) 72int xfrm4_output_finish(struct sk_buff *skb)
73{ 73{
74#ifdef CONFIG_NETFILTER 74#ifdef CONFIG_NETFILTER
75 if (!skb_dst(skb)->xfrm) { 75 if (!skb_dst(skb)->xfrm) {
@@ -86,7 +86,11 @@ static int xfrm4_output_finish(struct sk_buff *skb)
86 86
87int xfrm4_output(struct sk_buff *skb) 87int xfrm4_output(struct sk_buff *skb)
88{ 88{
89 struct dst_entry *dst = skb_dst(skb);
90 struct xfrm_state *x = dst->xfrm;
91
89 return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, 92 return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb,
90 NULL, skb_dst(skb)->dev, xfrm4_output_finish, 93 NULL, dst->dev,
94 x->outer_mode->afinfo->output_finish,
91 !(IPCB(skb)->flags & IPSKB_REROUTED)); 95 !(IPCB(skb)->flags & IPSKB_REROUTED));
92} 96}
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 1717c64628d1..805d63ef4340 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -78,6 +78,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = {
78 .init_tempsel = __xfrm4_init_tempsel, 78 .init_tempsel = __xfrm4_init_tempsel,
79 .init_temprop = xfrm4_init_temprop, 79 .init_temprop = xfrm4_init_temprop,
80 .output = xfrm4_output, 80 .output = xfrm4_output,
81 .output_finish = xfrm4_output_finish,
81 .extract_input = xfrm4_extract_input, 82 .extract_input = xfrm4_extract_input,
82 .extract_output = xfrm4_extract_output, 83 .extract_output = xfrm4_extract_output,
83 .transport_finish = xfrm4_transport_finish, 84 .transport_finish = xfrm4_transport_finish,
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c
index 8e688b3de9ab..49a91c5f5623 100644
--- a/net/ipv6/xfrm6_output.c
+++ b/net/ipv6/xfrm6_output.c
@@ -79,7 +79,7 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb)
79} 79}
80EXPORT_SYMBOL(xfrm6_prepare_output); 80EXPORT_SYMBOL(xfrm6_prepare_output);
81 81
82static int xfrm6_output_finish(struct sk_buff *skb) 82int xfrm6_output_finish(struct sk_buff *skb)
83{ 83{
84#ifdef CONFIG_NETFILTER 84#ifdef CONFIG_NETFILTER
85 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; 85 IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED;
@@ -97,9 +97,9 @@ static int __xfrm6_output(struct sk_buff *skb)
97 if ((x && x->props.mode == XFRM_MODE_TUNNEL) && 97 if ((x && x->props.mode == XFRM_MODE_TUNNEL) &&
98 ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || 98 ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) ||
99 dst_allfrag(skb_dst(skb)))) { 99 dst_allfrag(skb_dst(skb)))) {
100 return ip6_fragment(skb, xfrm6_output_finish); 100 return ip6_fragment(skb, x->outer_mode->afinfo->output_finish);
101 } 101 }
102 return xfrm6_output_finish(skb); 102 return x->outer_mode->afinfo->output_finish(skb);
103} 103}
104 104
105int xfrm6_output(struct sk_buff *skb) 105int xfrm6_output(struct sk_buff *skb)
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index afe941e9415c..248f0b2a7ee9 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -178,6 +178,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = {
178 .tmpl_sort = __xfrm6_tmpl_sort, 178 .tmpl_sort = __xfrm6_tmpl_sort,
179 .state_sort = __xfrm6_state_sort, 179 .state_sort = __xfrm6_state_sort,
180 .output = xfrm6_output, 180 .output = xfrm6_output,
181 .output_finish = xfrm6_output_finish,
181 .extract_input = xfrm6_extract_input, 182 .extract_input = xfrm6_extract_input,
182 .extract_output = xfrm6_extract_output, 183 .extract_output = xfrm6_extract_output,
183 .transport_finish = xfrm6_transport_finish, 184 .transport_finish = xfrm6_transport_finish,
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 15792d8b6272..b4d745ea8ee1 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -1406,6 +1406,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1406 struct net *net = xp_net(policy); 1406 struct net *net = xp_net(policy);
1407 unsigned long now = jiffies; 1407 unsigned long now = jiffies;
1408 struct net_device *dev; 1408 struct net_device *dev;
1409 struct xfrm_mode *inner_mode;
1409 struct dst_entry *dst_prev = NULL; 1410 struct dst_entry *dst_prev = NULL;
1410 struct dst_entry *dst0 = NULL; 1411 struct dst_entry *dst0 = NULL;
1411 int i = 0; 1412 int i = 0;
@@ -1436,6 +1437,17 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1436 goto put_states; 1437 goto put_states;
1437 } 1438 }
1438 1439
1440 if (xfrm[i]->sel.family == AF_UNSPEC) {
1441 inner_mode = xfrm_ip2inner_mode(xfrm[i],
1442 xfrm_af2proto(family));
1443 if (!inner_mode) {
1444 err = -EAFNOSUPPORT;
1445 dst_release(dst);
1446 goto put_states;
1447 }
1448 } else
1449 inner_mode = xfrm[i]->inner_mode;
1450
1439 if (!dst_prev) 1451 if (!dst_prev)
1440 dst0 = dst1; 1452 dst0 = dst1;
1441 else { 1453 else {
@@ -1464,7 +1476,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
1464 dst1->lastuse = now; 1476 dst1->lastuse = now;
1465 1477
1466 dst1->input = dst_discard; 1478 dst1->input = dst_discard;
1467 dst1->output = xfrm[i]->outer_mode->afinfo->output; 1479 dst1->output = inner_mode->afinfo->output;
1468 1480
1469 dst1->next = dst_prev; 1481 dst1->next = dst_prev;
1470 dst_prev = dst1; 1482 dst_prev = dst1;