X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Fesp4.c;fp=net%2Fipv4%2Fesp4.c;h=09590f3560866758e0db00ff43580ca7b9ab798d;hb=64ba3f394c830ec48a1c31b53dcae312c56f1604;hp=fc2f8ce441def709bb1fdc88a4e8c651fc29ede2;hpb=be1e6109ac94a859551f8e1774eb9a8469fe055c;p=linux-2.6.git diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index fc2f8ce44..09590f356 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -89,7 +90,6 @@ static int esp_output(struct xfrm_state *x, struct sk_buff *skb) esph->spi = x->id.spi; esph->seq_no = htonl(++x->replay.oseq); - xfrm_aevent_doreplay(x); if (esp->conf.ivlen) crypto_cipher_set_iv(tfm, esp->conf.ivec, crypto_tfm_alg_ivsize(tfm)); @@ -132,7 +132,7 @@ error: * expensive, so we only support truncated data, which is the recommended * and common case. */ -static int esp_input(struct xfrm_state *x, struct sk_buff *skb) +static int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) { struct iphdr *iph; struct ip_esp_hdr *esph; @@ -142,9 +142,10 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) int alen = esp->auth.icv_trunc_len; int elen = skb->len - sizeof(struct ip_esp_hdr) - esp->conf.ivlen - alen; int nfrags; - int ihl; + int encap_len = 0; u8 nexthdr[2]; struct scatterlist *sg; + u8 workbuf[60]; int padlen; if (!pskb_may_pull(skb, sizeof(struct ip_esp_hdr))) @@ -175,6 +176,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) skb->ip_summed = CHECKSUM_NONE; esph = (struct ip_esp_hdr*)skb->data; + iph = skb->nh.iph; /* Get ivec. This can be wrong, check against another impls. */ if (esp->conf.ivlen) @@ -201,12 +203,15 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) /* ... check padding bits here. Silly. :-) */ - iph = skb->nh.iph; - ihl = iph->ihl * 4; - if (x->encap) { struct xfrm_encap_tmpl *encap = x->encap; - struct udphdr *uh = (void *)(skb->nh.raw + ihl); + struct udphdr *uh; + + if (encap->encap_type != decap->decap_type) + goto out; + + uh = (struct udphdr *)(iph + 1); + encap_len = (void*)esph - (void*)uh; /* * 1) if the NAT-T peer's IP or port changed then @@ -243,7 +248,11 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb) iph->protocol = nexthdr[1]; pskb_trim(skb, skb->len - alen - padlen - 2); - skb->h.raw = __skb_pull(skb, sizeof(*esph) + esp->conf.ivlen) - ihl; + memcpy(workbuf, skb->nh.raw, iph->ihl*4); + skb->h.raw = skb_pull(skb, sizeof(struct ip_esp_hdr) + esp->conf.ivlen); + skb->nh.raw += encap_len + sizeof(struct ip_esp_hdr) + esp->conf.ivlen; + memcpy(skb->nh.raw, workbuf, iph->ihl*4); + skb->nh.iph->tot_len = htons(skb->len); return 0; @@ -316,10 +325,12 @@ static int esp_init_state(struct xfrm_state *x) if (x->ealg == NULL) goto error; - esp = kzalloc(sizeof(*esp), GFP_KERNEL); + esp = kmalloc(sizeof(*esp), GFP_KERNEL); if (esp == NULL) return -ENOMEM; + memset(esp, 0, sizeof(*esp)); + if (x->aalg) { struct xfrm_algo_desc *aalg_desc;