aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-11-14 00:44:23 -0500
committerDavid S. Miller <davem@davemloft.net>2008-01-28 17:53:50 -0500
commit716062fd4c2f88a33ab409f62a1e7397ad0a7e33 (patch)
tree73f2618fe99bca3870a0dbdc35acf6466ab3b976 /net/ipv6
parentc6581a457e661b7070e484ad723bbf555b17aca2 (diff)
[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 <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/xfrm6_input.c118
-rw-r--r--net/ipv6/xfrm6_state.c1
2 files changed, 14 insertions, 105 deletions
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c
index c458d0a2e684..3b9eedf5b24a 100644
--- a/net/ipv6/xfrm6_input.c
+++ b/net/ipv6/xfrm6_input.c
@@ -23,118 +23,26 @@ int xfrm6_extract_input(struct xfrm_state *x, struct sk_buff *skb)
23 23
24int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi) 24int xfrm6_rcv_spi(struct sk_buff *skb, int nexthdr, __be32 spi)
25{ 25{
26 int err; 26 XFRM_SPI_SKB_CB(skb)->nhoff = IP6CB(skb)->nhoff;
27 __be32 seq; 27 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct ipv6hdr, daddr);
28 struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; 28 return xfrm_input(skb, nexthdr, spi, 0);
29 struct xfrm_state *x; 29}
30 int xfrm_nr = 0; 30EXPORT_SYMBOL(xfrm6_rcv_spi);
31 int decaps = 0;
32 unsigned int nhoff;
33
34 nhoff = IP6CB(skb)->nhoff;
35
36 seq = 0;
37 if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
38 goto drop;
39
40 do {
41 struct ipv6hdr *iph = ipv6_hdr(skb);
42
43 if (xfrm_nr == XFRM_MAX_DEPTH)
44 goto drop;
45
46 x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
47 nexthdr, AF_INET6);
48 if (x == NULL)
49 goto drop;
50 spin_lock(&x->lock);
51 if (unlikely(x->km.state != XFRM_STATE_VALID))
52 goto drop_unlock;
53
54 if (x->props.replay_window && xfrm_replay_check(x, seq))
55 goto drop_unlock;
56
57 if (xfrm_state_check_expire(x))
58 goto drop_unlock;
59
60 nexthdr = x->type->input(x, skb);
61 if (nexthdr <= 0)
62 goto drop_unlock;
63
64 skb_network_header(skb)[nhoff] = nexthdr;
65
66 if (x->props.replay_window)
67 xfrm_replay_advance(x, seq);
68
69 x->curlft.bytes += skb->len;
70 x->curlft.packets++;
71
72 spin_unlock(&x->lock);
73
74 xfrm_vec[xfrm_nr++] = x;
75
76 if (x->inner_mode->input(x, skb))
77 goto drop;
78
79 if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
80 decaps = 1;
81 break;
82 }
83
84 if ((err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) < 0)
85 goto drop;
86 } while (!err);
87
88 /* Allocate new secpath or COW existing one. */
89 if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
90 struct sec_path *sp;
91 sp = secpath_dup(skb->sp);
92 if (!sp)
93 goto drop;
94 if (skb->sp)
95 secpath_put(skb->sp);
96 skb->sp = sp;
97 }
98
99 if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
100 goto drop;
101
102 memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
103 xfrm_nr * sizeof(xfrm_vec[0]));
104 skb->sp->len += xfrm_nr;
105
106 nf_reset(skb);
107 31
108 if (decaps) { 32int xfrm6_transport_finish(struct sk_buff *skb, int async)
109 dst_release(skb->dst); 33{
110 skb->dst = NULL;
111 netif_rx(skb);
112 return -1;
113 } else {
114#ifdef CONFIG_NETFILTER 34#ifdef CONFIG_NETFILTER
115 ipv6_hdr(skb)->payload_len = htons(skb->len); 35 ipv6_hdr(skb)->payload_len = htons(skb->len);
116 __skb_push(skb, skb->data - skb_network_header(skb)); 36 __skb_push(skb, skb->data - skb_network_header(skb));
117 37
118 NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL, 38 NF_HOOK(PF_INET6, NF_IP6_PRE_ROUTING, skb, skb->dev, NULL,
119 ip6_rcv_finish); 39 ip6_rcv_finish);
120 return -1; 40 return -1;
121#else 41#else
122 return 1; 42 return 1;
123#endif 43#endif
124 }
125
126drop_unlock:
127 spin_unlock(&x->lock);
128 xfrm_state_put(x);
129drop:
130 while (--xfrm_nr >= 0)
131 xfrm_state_put(xfrm_vec[xfrm_nr]);
132 kfree_skb(skb);
133 return -1;
134} 44}
135 45
136EXPORT_SYMBOL(xfrm6_rcv_spi);
137
138int xfrm6_rcv(struct sk_buff *skb) 46int xfrm6_rcv(struct sk_buff *skb)
139{ 47{
140 return xfrm6_rcv_spi(skb, skb_network_header(skb)[IP6CB(skb)->nhoff], 48 return xfrm6_rcv_spi(skb, skb_network_header(skb)[IP6CB(skb)->nhoff],
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c
index bb09e85a336d..00360b514e99 100644
--- a/net/ipv6/xfrm6_state.c
+++ b/net/ipv6/xfrm6_state.c
@@ -198,6 +198,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = {
198 .output = xfrm6_output, 198 .output = xfrm6_output,
199 .extract_input = xfrm6_extract_input, 199 .extract_input = xfrm6_extract_input,
200 .extract_output = xfrm6_extract_output, 200 .extract_output = xfrm6_extract_output,
201 .transport_finish = xfrm6_transport_finish,
201}; 202};
202 203
203void __init xfrm6_state_init(void) 204void __init xfrm6_state_init(void)