diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2006-05-28 02:06:13 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-06-18 00:28:41 -0400 |
commit | 31a4ab93025719e62e7cf7ce899f71c34ecde5a0 (patch) | |
tree | 60404c5fd1124882753b38e334656a15f8de0804 /net/ipv4/ah4.c | |
parent | b59f45d0b2878ab76f8053b0973654e6621828ee (diff) |
[IPSEC] proto: Move transport mode input path into xfrm_mode_transport
Now that we have xfrm_mode objects we can move the transport mode specific
input decapsulation code into xfrm_mode_transport. This removes duplicate
code as well as unnecessary header movement in case of tunnel mode SAs
since we will discard the original IP header immediately.
This also fixes a minor bug for transport-mode ESP where the IP payload
length is set to the correct value minus the header length (with extension
headers for IPv6).
Of course the other neat thing is that we no longer have to allocate
temporary buffers to hold the IP headers for ESP and IPComp.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ah4.c')
-rw-r--r-- | net/ipv4/ah4.c | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index e2e4771fa4c6..c7782230080d 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c | |||
@@ -119,6 +119,7 @@ error: | |||
119 | static int ah_input(struct xfrm_state *x, struct sk_buff *skb) | 119 | static int ah_input(struct xfrm_state *x, struct sk_buff *skb) |
120 | { | 120 | { |
121 | int ah_hlen; | 121 | int ah_hlen; |
122 | int ihl; | ||
122 | struct iphdr *iph; | 123 | struct iphdr *iph; |
123 | struct ip_auth_hdr *ah; | 124 | struct ip_auth_hdr *ah; |
124 | struct ah_data *ahp; | 125 | struct ah_data *ahp; |
@@ -149,13 +150,14 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) | |||
149 | ah = (struct ip_auth_hdr*)skb->data; | 150 | ah = (struct ip_auth_hdr*)skb->data; |
150 | iph = skb->nh.iph; | 151 | iph = skb->nh.iph; |
151 | 152 | ||
152 | memcpy(work_buf, iph, iph->ihl*4); | 153 | ihl = skb->data - skb->nh.raw; |
154 | memcpy(work_buf, iph, ihl); | ||
153 | 155 | ||
154 | iph->ttl = 0; | 156 | iph->ttl = 0; |
155 | iph->tos = 0; | 157 | iph->tos = 0; |
156 | iph->frag_off = 0; | 158 | iph->frag_off = 0; |
157 | iph->check = 0; | 159 | iph->check = 0; |
158 | if (iph->ihl != 5) { | 160 | if (ihl > sizeof(*iph)) { |
159 | u32 dummy; | 161 | u32 dummy; |
160 | if (ip_clear_mutable_options(iph, &dummy)) | 162 | if (ip_clear_mutable_options(iph, &dummy)) |
161 | goto out; | 163 | goto out; |
@@ -164,7 +166,7 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) | |||
164 | u8 auth_data[MAX_AH_AUTH_LEN]; | 166 | u8 auth_data[MAX_AH_AUTH_LEN]; |
165 | 167 | ||
166 | memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); | 168 | memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); |
167 | skb_push(skb, skb->data - skb->nh.raw); | 169 | skb_push(skb, ihl); |
168 | ahp->icv(ahp, skb, ah->auth_data); | 170 | ahp->icv(ahp, skb, ah->auth_data); |
169 | if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { | 171 | if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) { |
170 | x->stats.integrity_failed++; | 172 | x->stats.integrity_failed++; |
@@ -172,11 +174,8 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) | |||
172 | } | 174 | } |
173 | } | 175 | } |
174 | ((struct iphdr*)work_buf)->protocol = ah->nexthdr; | 176 | ((struct iphdr*)work_buf)->protocol = ah->nexthdr; |
175 | skb->nh.raw = skb_pull(skb, ah_hlen); | 177 | skb->h.raw = memcpy(skb->nh.raw += ah_hlen, work_buf, ihl); |
176 | memcpy(skb->nh.raw, work_buf, iph->ihl*4); | 178 | __skb_pull(skb, ah_hlen + ihl); |
177 | skb->nh.iph->tot_len = htons(skb->len); | ||
178 | skb_pull(skb, skb->nh.iph->ihl*4); | ||
179 | skb->h.raw = skb->data; | ||
180 | 179 | ||
181 | return 0; | 180 | return 0; |
182 | 181 | ||