X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=net%2Fipv4%2Fah4.c;h=970fe58b48801beb1267fb7df294291264de5e2d;hb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;hp=d3395b048e86eeacd77293b2c11b91ef255b9a33;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index d3395b048..970fe58b4 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -67,52 +66,31 @@ static int ah_output(struct sk_buff *skb) char buf[60]; } tmp_iph; - if (skb->ip_summed == CHECKSUM_HW && skb_checksum_help(skb) == NULL) { - err = -EINVAL; - goto error_nolock; - } + top_iph = skb->nh.iph; + iph = &tmp_iph.iph; - spin_lock_bh(&x->lock); - err = xfrm_check_output(x, skb, AF_INET); - if (err) - goto error; + iph->tos = top_iph->tos; + iph->ttl = top_iph->ttl; + iph->frag_off = top_iph->frag_off; - iph = skb->nh.iph; - if (x->props.mode) { - top_iph = (struct iphdr*)skb_push(skb, x->props.header_len); - top_iph->ihl = 5; - top_iph->version = 4; - top_iph->tos = 0; - top_iph->tot_len = htons(skb->len); - top_iph->frag_off = 0; - if (!(iph->frag_off&htons(IP_DF))) - __ip_select_ident(top_iph, dst, 0); - top_iph->ttl = 0; - top_iph->protocol = IPPROTO_AH; - top_iph->check = 0; - top_iph->saddr = x->props.saddr.a4; - top_iph->daddr = x->id.daddr.a4; - ah = (struct ip_auth_hdr*)(top_iph+1); - ah->nexthdr = IPPROTO_IPIP; - } else { - memcpy(&tmp_iph, skb->data, iph->ihl*4); - top_iph = (struct iphdr*)skb_push(skb, x->props.header_len); - memcpy(top_iph, &tmp_iph, iph->ihl*4); - iph = &tmp_iph.iph; - top_iph->tos = 0; - top_iph->tot_len = htons(skb->len); - top_iph->frag_off = 0; - top_iph->ttl = 0; - top_iph->protocol = IPPROTO_AH; - top_iph->check = 0; - if (top_iph->ihl != 5) { - err = ip_clear_mutable_options(top_iph, &top_iph->daddr); - if (err) - goto error; - } - ah = (struct ip_auth_hdr*)((char*)top_iph+iph->ihl*4); - ah->nexthdr = iph->protocol; + if (top_iph->ihl != 5) { + iph->daddr = top_iph->daddr; + memcpy(iph+1, top_iph+1, top_iph->ihl*4 - sizeof(struct iphdr)); + err = ip_clear_mutable_options(top_iph, &top_iph->daddr); + if (err) + goto error; } + + ah = (struct ip_auth_hdr *)((char *)top_iph+top_iph->ihl*4); + ah->nexthdr = top_iph->protocol; + + top_iph->tos = 0; + top_iph->tot_len = htons(skb->len); + top_iph->frag_off = 0; + top_iph->ttl = 0; + top_iph->protocol = IPPROTO_AH; + top_iph->check = 0; + ahp = x->data; ah->hdrlen = (XFRM_ALIGN8(sizeof(struct ip_auth_hdr) + ahp->icv_trunc_len) >> 2) - 2; @@ -121,40 +99,24 @@ static int ah_output(struct sk_buff *skb) ah->spi = x->id.spi; ah->seq_no = htonl(++x->replay.oseq); ahp->icv(ahp, skb, ah->auth_data); + top_iph->tos = iph->tos; top_iph->ttl = iph->ttl; - if (x->props.mode) { - if (x->props.flags & XFRM_STATE_NOECN) - IP_ECN_clear(top_iph); - top_iph->frag_off = iph->frag_off&~htons(IP_MF|IP_OFFSET); - memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options)); - } else { - top_iph->frag_off = iph->frag_off; + top_iph->frag_off = iph->frag_off; + if (top_iph->ihl != 5) { top_iph->daddr = iph->daddr; - if (iph->ihl != 5) - memcpy(top_iph+1, iph+1, iph->ihl*4 - sizeof(struct iphdr)); + memcpy(top_iph+1, iph+1, top_iph->ihl*4 - sizeof(struct iphdr)); } - ip_send_check(top_iph); - skb->nh.raw = skb->data; + ip_send_check(top_iph); - x->curlft.bytes += skb->len; - x->curlft.packets++; - spin_unlock_bh(&x->lock); - if ((skb->dst = dst_pop(dst)) == NULL) { - err = -EHOSTUNREACH; - goto error_nolock; - } - return NET_XMIT_BYPASS; + err = 0; error: - spin_unlock_bh(&x->lock); -error_nolock: - kfree_skb(skb); return err; } -int ah_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) +static int ah_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb) { int ah_hlen; struct iphdr *iph; @@ -222,7 +184,7 @@ out: return -EINVAL; } -void ah4_err(struct sk_buff *skb, u32 info) +static void ah4_err(struct sk_buff *skb, u32 info) { struct iphdr *iph = (struct iphdr*)skb->data; struct ip_auth_hdr *ah = (struct ip_auth_hdr*)(skb->data+(iph->ihl<<2)); @@ -252,6 +214,9 @@ static int ah_init_state(struct xfrm_state *x, void *args) if (x->aalg->alg_key_len > 512) goto error; + if (x->encap) + goto error; + ahp = kmalloc(sizeof(*ahp), GFP_KERNEL); if (ahp == NULL) return -ENOMEM; @@ -339,7 +304,7 @@ static struct xfrm_type ah_type = .output = ah_output }; -static struct inet_protocol ah4_protocol = { +static struct net_protocol ah4_protocol = { .handler = xfrm4_rcv, .err_handler = ah4_err, .no_policy = 1,