diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2007-12-16 18:55:02 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-01-28 17:53:51 -0500 |
commit | 668dc8af3150f837f7f0461001bbbc0ce25d7bdf (patch) | |
tree | 9ba3534a190bb69b3aebf24aaa4340685fe16539 | |
parent | b2aa5e9d43a38dcdfa0878ed750cf32f98460278 (diff) |
[IPSEC]: Move integrity stat collection into xfrm_input
Similar to the moving out of the replay processing on the output, this
patch moves the integrity stat collectin from x->type->input into
xfrm_input.
This would eventually allow transforms such as AH/ESP to be lockless.
The error value EBADMSG (currently unused in the crypto layer) is used
to indicate a failed integrity check. In future this error can be
directly returned by the crypto layer once we switch to aead
algorithms.
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/ipv4/ah4.c | 3 | ||||
-rw-r--r-- | net/ipv4/esp4.c | 13 | ||||
-rw-r--r-- | net/ipv6/ah6.c | 3 | ||||
-rw-r--r-- | net/ipv6/esp6.c | 3 | ||||
-rw-r--r-- | net/xfrm/xfrm_input.c | 5 |
5 files changed, 15 insertions, 12 deletions
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 5fc346d8b566..a989d29b44ea 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c | |||
@@ -177,9 +177,8 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) | |||
177 | err = ah_mac_digest(ahp, skb, ah->auth_data); | 177 | err = ah_mac_digest(ahp, skb, ah->auth_data); |
178 | if (err) | 178 | if (err) |
179 | goto out; | 179 | goto out; |
180 | err = -EINVAL; | ||
181 | if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) { | 180 | if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) { |
182 | x->stats.integrity_failed++; | 181 | err = -EBADMSG; |
183 | goto out; | 182 | goto out; |
184 | } | 183 | } |
185 | } | 184 | } |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 1738113268bc..3350a7d50669 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
@@ -163,7 +163,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
163 | u8 nexthdr[2]; | 163 | u8 nexthdr[2]; |
164 | struct scatterlist *sg; | 164 | struct scatterlist *sg; |
165 | int padlen; | 165 | int padlen; |
166 | int err; | 166 | int err = -EINVAL; |
167 | 167 | ||
168 | if (!pskb_may_pull(skb, sizeof(*esph))) | 168 | if (!pskb_may_pull(skb, sizeof(*esph))) |
169 | goto out; | 169 | goto out; |
@@ -183,13 +183,14 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
183 | BUG(); | 183 | BUG(); |
184 | 184 | ||
185 | if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) { | 185 | if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) { |
186 | x->stats.integrity_failed++; | 186 | err = -EBADMSG; |
187 | goto out; | 187 | goto out; |
188 | } | 188 | } |
189 | } | 189 | } |
190 | 190 | ||
191 | if ((nfrags = skb_cow_data(skb, 0, &trailer)) < 0) | 191 | if ((err = skb_cow_data(skb, 0, &trailer)) < 0) |
192 | goto out; | 192 | goto out; |
193 | nfrags = err; | ||
193 | 194 | ||
194 | skb->ip_summed = CHECKSUM_NONE; | 195 | skb->ip_summed = CHECKSUM_NONE; |
195 | 196 | ||
@@ -202,6 +203,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
202 | sg = &esp->sgbuf[0]; | 203 | sg = &esp->sgbuf[0]; |
203 | 204 | ||
204 | if (unlikely(nfrags > ESP_NUM_FAST_SG)) { | 205 | if (unlikely(nfrags > ESP_NUM_FAST_SG)) { |
206 | err = -ENOMEM; | ||
205 | sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); | 207 | sg = kmalloc(sizeof(struct scatterlist)*nfrags, GFP_ATOMIC); |
206 | if (!sg) | 208 | if (!sg) |
207 | goto out; | 209 | goto out; |
@@ -214,11 +216,12 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
214 | if (unlikely(sg != &esp->sgbuf[0])) | 216 | if (unlikely(sg != &esp->sgbuf[0])) |
215 | kfree(sg); | 217 | kfree(sg); |
216 | if (unlikely(err)) | 218 | if (unlikely(err)) |
217 | return err; | 219 | goto out; |
218 | 220 | ||
219 | if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) | 221 | if (skb_copy_bits(skb, skb->len-alen-2, nexthdr, 2)) |
220 | BUG(); | 222 | BUG(); |
221 | 223 | ||
224 | err = -EINVAL; | ||
222 | padlen = nexthdr[0]; | 225 | padlen = nexthdr[0]; |
223 | if (padlen+2 >= elen) | 226 | if (padlen+2 >= elen) |
224 | goto out; | 227 | goto out; |
@@ -276,7 +279,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) | |||
276 | return nexthdr[1]; | 279 | return nexthdr[1]; |
277 | 280 | ||
278 | out: | 281 | out: |
279 | return -EINVAL; | 282 | return err; |
280 | } | 283 | } |
281 | 284 | ||
282 | static u32 esp4_get_mtu(struct xfrm_state *x, int mtu) | 285 | static u32 esp4_get_mtu(struct xfrm_state *x, int mtu) |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 4eaf55072b1b..d4b59ecb0b57 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
@@ -379,10 +379,9 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
379 | err = ah_mac_digest(ahp, skb, ah->auth_data); | 379 | err = ah_mac_digest(ahp, skb, ah->auth_data); |
380 | if (err) | 380 | if (err) |
381 | goto free_out; | 381 | goto free_out; |
382 | err = -EINVAL; | ||
383 | if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) { | 382 | if (memcmp(ahp->work_icv, auth_data, ahp->icv_trunc_len)) { |
384 | LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n"); | 383 | LIMIT_NETDEBUG(KERN_WARNING "ipsec ah authentication error\n"); |
385 | x->stats.integrity_failed++; | 384 | err = -EBADMSG; |
386 | goto free_out; | 385 | goto free_out; |
387 | } | 386 | } |
388 | } | 387 | } |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 444053254676..096974ba6420 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -177,8 +177,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
177 | BUG(); | 177 | BUG(); |
178 | 178 | ||
179 | if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) { | 179 | if (unlikely(memcmp(esp->auth.work_icv, sum, alen))) { |
180 | x->stats.integrity_failed++; | 180 | ret = -EBADMSG; |
181 | ret = -EINVAL; | ||
182 | goto out; | 181 | goto out; |
183 | } | 182 | } |
184 | } | 183 | } |
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 587f3474ed3d..b7d68eb9434c 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
@@ -147,8 +147,11 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
147 | goto drop_unlock; | 147 | goto drop_unlock; |
148 | 148 | ||
149 | nexthdr = x->type->input(x, skb); | 149 | nexthdr = x->type->input(x, skb); |
150 | if (nexthdr <= 0) | 150 | if (nexthdr <= 0) { |
151 | if (nexthdr == -EBADMSG) | ||
152 | x->stats.integrity_failed++; | ||
151 | goto drop_unlock; | 153 | goto drop_unlock; |
154 | } | ||
152 | 155 | ||
153 | skb_network_header(skb)[nhoff] = nexthdr; | 156 | skb_network_header(skb)[nhoff] = nexthdr; |
154 | 157 | ||