diff options
author | James Bottomley <jejb@sparkweed.localdomain> | 2006-09-23 22:03:52 -0400 |
---|---|---|
committer | James Bottomley <jejb@sparkweed.localdomain> | 2006-09-23 22:03:52 -0400 |
commit | 1aedf2ccc60fade26c46fae12e28664d0da3f199 (patch) | |
tree | d91083e3079f1ddb942a382ac2b5a7525570ad59 /net/ipv6/xfrm6_input.c | |
parent | dfdc58ba354adb80d67c99f7be84f95a8e02e466 (diff) | |
parent | 1ab9dd0902df4f4ff56fbf672220549090ab28ba (diff) |
Merge mulgrave-w:git/linux-2.6
Conflicts:
include/linux/blkdev.h
Trivial merge to incorporate tag prototypes.
Diffstat (limited to 'net/ipv6/xfrm6_input.c')
-rw-r--r-- | net/ipv6/xfrm6_input.c | 110 |
1 files changed, 109 insertions, 1 deletions
diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 0405d74ff910..a40a05789013 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c | |||
@@ -72,7 +72,7 @@ int xfrm6_rcv_spi(struct sk_buff *skb, u32 spi) | |||
72 | if (x->mode->input(x, skb)) | 72 | if (x->mode->input(x, skb)) |
73 | goto drop; | 73 | goto drop; |
74 | 74 | ||
75 | if (x->props.mode) { /* XXX */ | 75 | if (x->props.mode == XFRM_MODE_TUNNEL) { /* XXX */ |
76 | decaps = 1; | 76 | decaps = 1; |
77 | break; | 77 | break; |
78 | } | 78 | } |
@@ -138,3 +138,111 @@ int xfrm6_rcv(struct sk_buff **pskb) | |||
138 | { | 138 | { |
139 | return xfrm6_rcv_spi(*pskb, 0); | 139 | return xfrm6_rcv_spi(*pskb, 0); |
140 | } | 140 | } |
141 | |||
142 | int xfrm6_input_addr(struct sk_buff *skb, xfrm_address_t *daddr, | ||
143 | xfrm_address_t *saddr, u8 proto) | ||
144 | { | ||
145 | struct xfrm_state *x = NULL; | ||
146 | int wildcard = 0; | ||
147 | struct in6_addr any; | ||
148 | xfrm_address_t *xany; | ||
149 | struct xfrm_state *xfrm_vec_one = NULL; | ||
150 | int nh = 0; | ||
151 | int i = 0; | ||
152 | |||
153 | ipv6_addr_set(&any, 0, 0, 0, 0); | ||
154 | xany = (xfrm_address_t *)&any; | ||
155 | |||
156 | for (i = 0; i < 3; i++) { | ||
157 | xfrm_address_t *dst, *src; | ||
158 | switch (i) { | ||
159 | case 0: | ||
160 | dst = daddr; | ||
161 | src = saddr; | ||
162 | break; | ||
163 | case 1: | ||
164 | /* lookup state with wild-card source address */ | ||
165 | wildcard = 1; | ||
166 | dst = daddr; | ||
167 | src = xany; | ||
168 | break; | ||
169 | case 2: | ||
170 | default: | ||
171 | /* lookup state with wild-card addresses */ | ||
172 | wildcard = 1; /* XXX */ | ||
173 | dst = xany; | ||
174 | src = xany; | ||
175 | break; | ||
176 | } | ||
177 | |||
178 | x = xfrm_state_lookup_byaddr(dst, src, proto, AF_INET6); | ||
179 | if (!x) | ||
180 | continue; | ||
181 | |||
182 | spin_lock(&x->lock); | ||
183 | |||
184 | if (wildcard) { | ||
185 | if ((x->props.flags & XFRM_STATE_WILDRECV) == 0) { | ||
186 | spin_unlock(&x->lock); | ||
187 | xfrm_state_put(x); | ||
188 | x = NULL; | ||
189 | continue; | ||
190 | } | ||
191 | } | ||
192 | |||
193 | if (unlikely(x->km.state != XFRM_STATE_VALID)) { | ||
194 | spin_unlock(&x->lock); | ||
195 | xfrm_state_put(x); | ||
196 | x = NULL; | ||
197 | continue; | ||
198 | } | ||
199 | if (xfrm_state_check_expire(x)) { | ||
200 | spin_unlock(&x->lock); | ||
201 | xfrm_state_put(x); | ||
202 | x = NULL; | ||
203 | continue; | ||
204 | } | ||
205 | |||
206 | nh = x->type->input(x, skb); | ||
207 | if (nh <= 0) { | ||
208 | spin_unlock(&x->lock); | ||
209 | xfrm_state_put(x); | ||
210 | x = NULL; | ||
211 | continue; | ||
212 | } | ||
213 | |||
214 | x->curlft.bytes += skb->len; | ||
215 | x->curlft.packets++; | ||
216 | |||
217 | spin_unlock(&x->lock); | ||
218 | |||
219 | xfrm_vec_one = x; | ||
220 | break; | ||
221 | } | ||
222 | |||
223 | if (!xfrm_vec_one) | ||
224 | goto drop; | ||
225 | |||
226 | /* Allocate new secpath or COW existing one. */ | ||
227 | if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { | ||
228 | struct sec_path *sp; | ||
229 | sp = secpath_dup(skb->sp); | ||
230 | if (!sp) | ||
231 | goto drop; | ||
232 | if (skb->sp) | ||
233 | secpath_put(skb->sp); | ||
234 | skb->sp = sp; | ||
235 | } | ||
236 | |||
237 | if (1 + skb->sp->len > XFRM_MAX_DEPTH) | ||
238 | goto drop; | ||
239 | |||
240 | skb->sp->xvec[skb->sp->len] = xfrm_vec_one; | ||
241 | skb->sp->len ++; | ||
242 | |||
243 | return 1; | ||
244 | drop: | ||
245 | if (xfrm_vec_one) | ||
246 | xfrm_state_put(xfrm_vec_one); | ||
247 | return -1; | ||
248 | } | ||