aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
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/ipv4
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/ipv4')
-rw-r--r--net/ipv4/xfrm4_input.c126
-rw-r--r--net/ipv4/xfrm4_state.c1
2 files changed, 15 insertions, 112 deletions
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:
41int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, 41int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi,
42 int encap_type) 42 int encap_type)
43{ 43{
44 int err; 44 XFRM_SPI_SKB_CB(skb)->nhoff = offsetof(struct iphdr, protocol);
45 __be32 seq; 45 XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
46 struct xfrm_state *xfrm_vec[XFRM_MAX_DEPTH]; 46 return xfrm_input(skb, nexthdr, spi, encap_type);
47 struct xfrm_state *x; 47}
48 int xfrm_nr = 0; 48EXPORT_SYMBOL(xfrm4_rcv_encap);
49 int decaps = 0;
50 unsigned int nhoff = offsetof(struct iphdr, protocol);
51
52 seq = 0;
53 if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0)
54 goto drop;
55
56 do {
57 const struct iphdr *iph = ip_hdr(skb);
58
59 if (xfrm_nr == XFRM_MAX_DEPTH)
60 goto drop;
61
62 x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi,
63 nexthdr, AF_INET);
64 if (x == NULL)
65 goto drop;
66
67 spin_lock(&x->lock);
68 if (unlikely(x->km.state != XFRM_STATE_VALID))
69 goto drop_unlock;
70
71 if ((x->encap ? x->encap->encap_type : 0) != encap_type)
72 goto drop_unlock;
73
74 if (x->props.replay_window && xfrm_replay_check(x, seq))
75 goto drop_unlock;
76
77 if (xfrm_state_check_expire(x))
78 goto drop_unlock;
79
80 nexthdr = x->type->input(x, skb);
81 if (nexthdr <= 0)
82 goto drop_unlock;
83
84 skb_network_header(skb)[nhoff] = nexthdr;
85
86 /* only the first xfrm gets the encap type */
87 encap_type = 0;
88
89 if (x->props.replay_window)
90 xfrm_replay_advance(x, seq);
91
92 x->curlft.bytes += skb->len;
93 x->curlft.packets++;
94
95 spin_unlock(&x->lock);
96
97 xfrm_vec[xfrm_nr++] = x;
98
99 if (x->inner_mode->input(x, skb))
100 goto drop;
101
102 if (x->outer_mode->flags & XFRM_MODE_FLAG_TUNNEL) {
103 decaps = 1;
104 break;
105 }
106
107 err = xfrm_parse_spi(skb, nexthdr, &spi, &seq);
108 if (err < 0)
109 goto drop;
110 } while (!err);
111
112 /* Allocate new secpath or COW existing one. */
113
114 if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
115 struct sec_path *sp;
116 sp = secpath_dup(skb->sp);
117 if (!sp)
118 goto drop;
119 if (skb->sp)
120 secpath_put(skb->sp);
121 skb->sp = sp;
122 }
123 if (xfrm_nr + skb->sp->len > XFRM_MAX_DEPTH)
124 goto drop;
125
126 memcpy(skb->sp->xvec + skb->sp->len, xfrm_vec,
127 xfrm_nr * sizeof(xfrm_vec[0]));
128 skb->sp->len += xfrm_nr;
129
130 nf_reset(skb);
131 49
132 if (decaps) { 50int xfrm4_transport_finish(struct sk_buff *skb, int async)
133 dst_release(skb->dst); 51{
134 skb->dst = NULL;
135 netif_rx(skb);
136 return 0;
137 } else {
138#ifdef CONFIG_NETFILTER 52#ifdef CONFIG_NETFILTER
139 __skb_push(skb, skb->data - skb_network_header(skb)); 53 __skb_push(skb, skb->data - skb_network_header(skb));
140 ip_hdr(skb)->tot_len = htons(skb->len); 54 ip_hdr(skb)->tot_len = htons(skb->len);
141 ip_send_check(ip_hdr(skb)); 55 ip_send_check(ip_hdr(skb));
142 56
143 NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL, 57 NF_HOOK(PF_INET, NF_IP_PRE_ROUTING, skb, skb->dev, NULL,
144 xfrm4_rcv_encap_finish); 58 xfrm4_rcv_encap_finish);
145 return 0; 59 return 0;
146#else 60#else
147 return -ip_hdr(skb)->protocol; 61 return -ip_hdr(skb)->protocol;
148#endif 62#endif
149 }
150
151drop_unlock:
152 spin_unlock(&x->lock);
153 xfrm_state_put(x);
154drop:
155 while (--xfrm_nr >= 0)
156 xfrm_state_put(xfrm_vec[xfrm_nr]);
157
158 kfree_skb(skb);
159 return 0;
160} 63}
161EXPORT_SYMBOL(xfrm4_rcv_encap);
162 64
163/* If it's a keepalive packet, then just eat it. 65/* If it's a keepalive packet, then just eat it.
164 * If it's an encapsulated packet, then pass it to the 66 * If it's an encapsulated packet, then pass it to the
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c
index 80292fbf221a..3b067e8b7bfe 100644
--- a/net/ipv4/xfrm4_state.c
+++ b/net/ipv4/xfrm4_state.c
@@ -74,6 +74,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = {
74 .output = xfrm4_output, 74 .output = xfrm4_output,
75 .extract_input = xfrm4_extract_input, 75 .extract_input = xfrm4_extract_input,
76 .extract_output = xfrm4_extract_output, 76 .extract_output = xfrm4_extract_output,
77 .transport_finish = xfrm4_transport_finish,
77}; 78};
78 79
79void __init xfrm4_state_init(void) 80void __init xfrm4_state_init(void)