From 716062fd4c2f88a33ab409f62a1e7397ad0a7e33 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Tue, 13 Nov 2007 21:44:23 -0800 Subject: [IPSEC]: Merge most of the input path As part of the work on asynchronous cryptographic operations, we need to be able to resume from the spot where they occur. As such, it helps if we isolate them to one spot. This patch moves most of the remaining family-specific processing into the common input code. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- net/ipv4/xfrm4_input.c | 126 ++++++------------------------------------------- 1 file changed, 14 insertions(+), 112 deletions(-) (limited to 'net/ipv4/xfrm4_input.c') diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index c0323d05ab69..e374903dacdf 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -41,124 +41,26 @@ drop: int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) { - int err; - __be32 seq; - struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; - struct xfrm_state *x; - int xfrm_nr = 0; - int decaps = 0; - unsigned int nhoff = offsetof(struct iphdr, protocol); - - seq = 0; - if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) - goto drop; - - do { - const struct iphdr *iph = ip_hdr(skb); - - if (xfrm_nr == XFRM_MAX_DEPTH) - goto drop; - - x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, - nexthdr, AF_INET); - if (x == NULL) - goto drop; - - spin_lock(&x->lock); - if (unlikely(x->km.state != XFRM_STATE_VALID)) - goto drop_unlock; - - if ((x->encap ? x->encap->encap_type : 0) != encap_type) - goto drop_unlock; - - if (x->props.replay_window && xfrm_replay_check(x, seq)) - goto drop_unlock; - - if (xfrm_state_check_expire(x)) - goto drop_unlock; - - nexthdr = x->type->input(x, skb); - if (nexthdr <= 0) - goto drop_unlock; - - skb_network_header(skb)[nhoff] = nexthdr; - - /* only the first xfrm gets the encap type */ - encap_type = 0; - - if (x->props.replay_window) - xfrm_replay_advance(x, seq); - - x->curlft.bytes += skb->len; - x->curlft.packets++; - - spin_unlock(&x->lock); - - xfrm_vec[xfrm_nr++] = x; - - if (x->inner_mode->input(x, skb)) - goto drop; - - if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) { - decaps = 1; - break; - } - - err = xfrm_parse_spi(skb, nexthdr, &spi, &seq); - if (err < 0) - goto drop; - } while (!err); - - /* Allocate new secpath or COW existing one. */ - - if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { - struct sec_path *sp; - sp = secpath_dup(skb->sp); - if (!sp) - goto drop; - if (skb->sp) - secpath_put(skb->sp); - skb->sp = sp; - } - if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH) - goto drop; - - memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec, - xfrm_nr * sizeof(xfrm_vec[0])); - skb->sp->len += xfrm_nr; - - nf_reset(skb); + XFRM_SPI_SKB_CB(skb)->nhoff = offsetof(struct iphdr, protocol); + XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); + return xfrm_input(skb, nexthdr, spi, encap_type); +} +EXPORT_SYMBOL(xfrm4_rcv_encap); - if (decaps) { - dst_release(skb->dst); - skb->dst = NULL; - netif_rx(skb); - return 0; - } else { +int xfrm4_transport_finish(struct sk_buff *skb, int async) +{ #ifdef CONFIG_NETFILTER - __skb_push(skb, skb->data - skb_network_header(skb)); - ip_hdr(skb)->tot_len = htons(skb->len); - ip_send_check(ip_hdr(skb)); + __skb_push(skb, skb->data - skb_network_header(skb)); + ip_hdr(skb)->tot_len = htons(skb->len); + ip_send_check(ip_hdr(skb)); - NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, - xfrm4_rcv_encap_finish); - return 0; + NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, + xfrm4_rcv_encap_finish); + return 0; #else - return -ip_hdr(skb)->protocol; + return -ip_hdr(skb)->protocol; #endif - } - -drop_unlock: - spin_unlock(&x->lock); - xfrm_state_put(x); -drop: - while (--xfrm_nr >= 0) - xfrm_state_put(xfrm_vec[xfrm_nr]); - - kfree_skb(skb); - return 0; } -EXPORT_SYMBOL(xfrm4_rcv_encap); /* If it's a keepalive packet, then just eat it. * If it's an encapsulated packet, then pass it to the -- cgit v1.2.3-59-g8ed1b