aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/xfrm4_mode_beet.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-11-14 00:41:28 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:53:46 -0500
commit227620e295090629fcb2c46ad3828222ab65438d (patch)
tree534162a74628fdfa7a8201cb776a45ca07510e5b /net/ipv4/xfrm4_mode_beet.c
parent36cf9acf93e8561d9faec24849e57688a81eb9c5 (diff)
[IPSEC]: Separate inner/outer mode processing on input
With inter-family transforms the inner mode differs from the outer mode. Attempting to handle both sides from the same function means that it needs to handle both IPv4 and IPv6 which creates duplication and confusion. This patch separates the two parts on the input path so that each function deals with one family only. In particular, the functions xfrm4_extract_inut/xfrm6_extract_inut moves the pertinent fields from the IPv4/IPv6 IP headers into a neutral format stored in skb->cb. This is then used by the inner mode input functions to modify the inner IP header. In this way the input function no longer has to know about the outer address family. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/xfrm4_mode_beet.c')
-rw-r--r--net/ipv4/xfrm4_mode_beet.c67
1 files changed, 39 insertions, 28 deletions
diff --git a/net/ipv4/xfrm4_mode_beet.c b/net/ipv4/xfrm4_mode_beet.c
index 94842adce144..e093a7b59e18 100644
--- a/net/ipv4/xfrm4_mode_beet.c
+++ b/net/ipv4/xfrm4_mode_beet.c
@@ -17,6 +17,21 @@
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
20/* Add encapsulation header. 35/* Add encapsulation header.
21 * 36 *
22 * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt. 37 * The top IP header will be constructed per draft-nikander-esp-beet-mode-06.txt.
@@ -40,20 +55,12 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
40 offsetof(struct iphdr, protocol); 55 offsetof(struct iphdr, protocol);
41 skb->transport_header = skb->network_header + sizeof(*iph); 56 skb->transport_header = skb->network_header + sizeof(*iph);
42 57
58 xfrm4_beet_make_header(skb);
59
43 ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen); 60 ph = (struct ip_beet_phdr *)__skb_pull(skb, sizeof(*iph) - hdrlen);
44 61
45 top_iph = ip_hdr(skb); 62 top_iph = ip_hdr(skb);
46 63
47 top_iph->ihl = 5;
48 top_iph->version = 4;
49
50 top_iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol;
51 top_iph->tos = XFRM_MODE_SKB_CB(skb)->tos;
52
53 top_iph->id = XFRM_MODE_SKB_CB(skb)->id;
54 top_iph->frag_off = XFRM_MODE_SKB_CB(skb)->frag_off;
55 top_iph->ttl = XFRM_MODE_SKB_CB(skb)->ttl;
56
57 if (unlikely(optlen)) { 64 if (unlikely(optlen)) {
58 BUG_ON(optlen < 0); 65 BUG_ON(optlen < 0);
59 66
@@ -75,43 +82,46 @@ static int xfrm4_beet_output(struct xfrm_state *x, struct sk_buff *skb)
75 82
76static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb) 83static int xfrm4_beet_input(struct xfrm_state *x, struct sk_buff *skb)
77{ 84{
78 struct iphdr *iph = ip_hdr(skb); 85 struct iphdr *iph;
79 int phlen = 0;
80 int optlen = 0; 86 int optlen = 0;
81 u8 ph_nexthdr = 0;
82 int err = -EINVAL; 87 int err = -EINVAL;
83 88
84 if (unlikely(iph->protocol == IPPROTO_BEETPH)) { 89 if (unlikely(XFRM_MODE_SKB_CB(skb)->protocol == IPPROTO_BEETPH)) {
85 struct ip_beet_phdr *ph; 90 struct ip_beet_phdr *ph;
91 int phlen;
86 92
87 if (!pskb_may_pull(skb, sizeof(*ph))) 93 if (!pskb_may_pull(skb, sizeof(*ph)))
88 goto out; 94 goto out;
89 ph = (struct ip_beet_phdr *)(ipip_hdr(skb) + 1); 95
96 ph = (struct ip_beet_phdr *)skb->data;
90 97
91 phlen = sizeof(*ph) + ph->padlen; 98 phlen = sizeof(*ph) + ph->padlen;
92 optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen); 99 optlen = ph->hdrlen * 8 + (IPV4_BEET_PHMAXLEN - phlen);
93 if (optlen < 0 || optlen & 3 || optlen > 250) 100 if (optlen < 0 || optlen & 3 || optlen > 250)
94 goto out; 101 goto out;
95 102
96 if (!pskb_may_pull(skb, phlen + optlen)) 103 XFRM_MODE_SKB_CB(skb)->protocol = ph->nexthdr;
97 goto out;
98 skb->len -= phlen + optlen;
99 104
100 ph_nexthdr = ph->nexthdr; 105 if (!pskb_may_pull(skb, phlen));
106 goto out;
107 __skb_pull(skb, phlen);
101 } 108 }
102 109
103 skb_set_network_header(skb, phlen - sizeof(*iph)); 110 skb_push(skb, sizeof(*iph));
104 memmove(skb_network_header(skb), iph, sizeof(*iph)); 111 skb_reset_network_header(skb);
105 skb_set_transport_header(skb, phlen + optlen); 112
106 skb->data = skb_transport_header(skb); 113 memmove(skb->data - skb->mac_len, skb_mac_header(skb),
114 skb->mac_len);
115 skb_set_mac_header(skb, -skb->mac_len);
116
117 xfrm4_beet_make_header(skb);
107 118
108 iph = ip_hdr(skb); 119 iph = ip_hdr(skb);
109 iph->ihl = (sizeof(*iph) + optlen) / 4; 120
110 iph->tot_len = htons(skb->len + iph->ihl * 4); 121 iph->ihl += optlen / 4;
122 iph->tot_len = htons(skb->len);
111 iph->daddr = x->sel.daddr.a4; 123 iph->daddr = x->sel.daddr.a4;
112 iph->saddr = x->sel.saddr.a4; 124 iph->saddr = x->sel.saddr.a4;
113 if (ph_nexthdr)
114 iph->protocol = ph_nexthdr;
115 iph->check = 0; 125 iph->check = 0;
116 iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl); 126 iph->check = ip_fast_csum(skb_network_header(skb), iph->ihl);
117 err = 0; 127 err = 0;
@@ -120,7 +130,8 @@ out:
120} 130}
121 131
122static struct xfrm_mode xfrm4_beet_mode = { 132static struct xfrm_mode xfrm4_beet_mode = {
123 .input = xfrm4_beet_input, 133 .input2 = xfrm4_beet_input,
134 .input = xfrm_prepare_input,
124 .output2 = xfrm4_beet_output, 135 .output2 = xfrm4_beet_output,
125 .output = xfrm4_prepare_output, 136 .output = xfrm4_prepare_output,
126 .owner = THIS_MODULE, 137 .owner = THIS_MODULE,