diff options
author | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-04-16 18:20:36 -0400 |
commit | 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch) | |
tree | 0bba044c4ce775e45a88a51686b5d9f90697ea9d /include/net/xfrm.h |
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history,
even though we have it. We can create a separate "historical" git
archive of that later if we want to, and in the meantime it's about
3.2GB when imported into git - space that would just make the early
git days unnecessarily complicated, when we don't have a lot of good
infrastructure for it.
Let it rip!
Diffstat (limited to 'include/net/xfrm.h')
-rw-r--r-- | include/net/xfrm.h | 905 |
1 files changed, 905 insertions, 0 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h new file mode 100644 index 000000000000..73e9a8ca3d3b --- /dev/null +++ b/include/net/xfrm.h | |||
@@ -0,0 +1,905 @@ | |||
1 | #ifndef _NET_XFRM_H | ||
2 | #define _NET_XFRM_H | ||
3 | |||
4 | #include <linux/xfrm.h> | ||
5 | #include <linux/spinlock.h> | ||
6 | #include <linux/list.h> | ||
7 | #include <linux/skbuff.h> | ||
8 | #include <linux/netdevice.h> | ||
9 | #include <linux/crypto.h> | ||
10 | #include <linux/pfkeyv2.h> | ||
11 | #include <linux/in6.h> | ||
12 | |||
13 | #include <net/sock.h> | ||
14 | #include <net/dst.h> | ||
15 | #include <net/route.h> | ||
16 | #include <net/ipv6.h> | ||
17 | #include <net/ip6_fib.h> | ||
18 | |||
19 | #define XFRM_ALIGN8(len) (((len) + 7) & ~7) | ||
20 | |||
21 | extern struct semaphore xfrm_cfg_sem; | ||
22 | |||
23 | /* Organization of SPD aka "XFRM rules" | ||
24 | ------------------------------------ | ||
25 | |||
26 | Basic objects: | ||
27 | - policy rule, struct xfrm_policy (=SPD entry) | ||
28 | - bundle of transformations, struct dst_entry == struct xfrm_dst (=SA bundle) | ||
29 | - instance of a transformer, struct xfrm_state (=SA) | ||
30 | - template to clone xfrm_state, struct xfrm_tmpl | ||
31 | |||
32 | SPD is plain linear list of xfrm_policy rules, ordered by priority. | ||
33 | (To be compatible with existing pfkeyv2 implementations, | ||
34 | many rules with priority of 0x7fffffff are allowed to exist and | ||
35 | such rules are ordered in an unpredictable way, thanks to bsd folks.) | ||
36 | |||
37 | Lookup is plain linear search until the first match with selector. | ||
38 | |||
39 | If "action" is "block", then we prohibit the flow, otherwise: | ||
40 | if "xfrms_nr" is zero, the flow passes untransformed. Otherwise, | ||
41 | policy entry has list of up to XFRM_MAX_DEPTH transformations, | ||
42 | described by templates xfrm_tmpl. Each template is resolved | ||
43 | to a complete xfrm_state (see below) and we pack bundle of transformations | ||
44 | to a dst_entry returned to requestor. | ||
45 | |||
46 | dst -. xfrm .-> xfrm_state #1 | ||
47 | |---. child .-> dst -. xfrm .-> xfrm_state #2 | ||
48 | |---. child .-> dst -. xfrm .-> xfrm_state #3 | ||
49 | |---. child .-> NULL | ||
50 | |||
51 | Bundles are cached at xrfm_policy struct (field ->bundles). | ||
52 | |||
53 | |||
54 | Resolution of xrfm_tmpl | ||
55 | ----------------------- | ||
56 | Template contains: | ||
57 | 1. ->mode Mode: transport or tunnel | ||
58 | 2. ->id.proto Protocol: AH/ESP/IPCOMP | ||
59 | 3. ->id.daddr Remote tunnel endpoint, ignored for transport mode. | ||
60 | Q: allow to resolve security gateway? | ||
61 | 4. ->id.spi If not zero, static SPI. | ||
62 | 5. ->saddr Local tunnel endpoint, ignored for transport mode. | ||
63 | 6. ->algos List of allowed algos. Plain bitmask now. | ||
64 | Q: ealgos, aalgos, calgos. What a mess... | ||
65 | 7. ->share Sharing mode. | ||
66 | Q: how to implement private sharing mode? To add struct sock* to | ||
67 | flow id? | ||
68 | |||
69 | Having this template we search through SAD searching for entries | ||
70 | with appropriate mode/proto/algo, permitted by selector. | ||
71 | If no appropriate entry found, it is requested from key manager. | ||
72 | |||
73 | PROBLEMS: | ||
74 | Q: How to find all the bundles referring to a physical path for | ||
75 | PMTU discovery? Seems, dst should contain list of all parents... | ||
76 | and enter to infinite locking hierarchy disaster. | ||
77 | No! It is easier, we will not search for them, let them find us. | ||
78 | We add genid to each dst plus pointer to genid of raw IP route, | ||
79 | pmtu disc will update pmtu on raw IP route and increase its genid. | ||
80 | dst_check() will see this for top level and trigger resyncing | ||
81 | metrics. Plus, it will be made via sk->sk_dst_cache. Solved. | ||
82 | */ | ||
83 | |||
84 | /* Full description of state of transformer. */ | ||
85 | struct xfrm_state | ||
86 | { | ||
87 | /* Note: bydst is re-used during gc */ | ||
88 | struct list_head bydst; | ||
89 | struct list_head byspi; | ||
90 | |||
91 | atomic_t refcnt; | ||
92 | spinlock_t lock; | ||
93 | |||
94 | struct xfrm_id id; | ||
95 | struct xfrm_selector sel; | ||
96 | |||
97 | /* Key manger bits */ | ||
98 | struct { | ||
99 | u8 state; | ||
100 | u8 dying; | ||
101 | u32 seq; | ||
102 | } km; | ||
103 | |||
104 | /* Parameters of this state. */ | ||
105 | struct { | ||
106 | u32 reqid; | ||
107 | u8 mode; | ||
108 | u8 replay_window; | ||
109 | u8 aalgo, ealgo, calgo; | ||
110 | u8 flags; | ||
111 | u16 family; | ||
112 | xfrm_address_t saddr; | ||
113 | int header_len; | ||
114 | int trailer_len; | ||
115 | } props; | ||
116 | |||
117 | struct xfrm_lifetime_cfg lft; | ||
118 | |||
119 | /* Data for transformer */ | ||
120 | struct xfrm_algo *aalg; | ||
121 | struct xfrm_algo *ealg; | ||
122 | struct xfrm_algo *calg; | ||
123 | |||
124 | /* Data for encapsulator */ | ||
125 | struct xfrm_encap_tmpl *encap; | ||
126 | |||
127 | /* IPComp needs an IPIP tunnel for handling uncompressed packets */ | ||
128 | struct xfrm_state *tunnel; | ||
129 | |||
130 | /* If a tunnel, number of users + 1 */ | ||
131 | atomic_t tunnel_users; | ||
132 | |||
133 | /* State for replay detection */ | ||
134 | struct xfrm_replay_state replay; | ||
135 | |||
136 | /* Statistics */ | ||
137 | struct xfrm_stats stats; | ||
138 | |||
139 | struct xfrm_lifetime_cur curlft; | ||
140 | struct timer_list timer; | ||
141 | |||
142 | /* Reference to data common to all the instances of this | ||
143 | * transformer. */ | ||
144 | struct xfrm_type *type; | ||
145 | |||
146 | /* Private data of this transformer, format is opaque, | ||
147 | * interpreted by xfrm_type methods. */ | ||
148 | void *data; | ||
149 | }; | ||
150 | |||
151 | enum { | ||
152 | XFRM_STATE_VOID, | ||
153 | XFRM_STATE_ACQ, | ||
154 | XFRM_STATE_VALID, | ||
155 | XFRM_STATE_ERROR, | ||
156 | XFRM_STATE_EXPIRED, | ||
157 | XFRM_STATE_DEAD | ||
158 | }; | ||
159 | |||
160 | struct xfrm_type; | ||
161 | struct xfrm_dst; | ||
162 | struct xfrm_policy_afinfo { | ||
163 | unsigned short family; | ||
164 | rwlock_t lock; | ||
165 | struct xfrm_type_map *type_map; | ||
166 | struct dst_ops *dst_ops; | ||
167 | void (*garbage_collect)(void); | ||
168 | int (*dst_lookup)(struct xfrm_dst **dst, struct flowi *fl); | ||
169 | struct dst_entry *(*find_bundle)(struct flowi *fl, struct xfrm_policy *policy); | ||
170 | int (*bundle_create)(struct xfrm_policy *policy, | ||
171 | struct xfrm_state **xfrm, | ||
172 | int nx, | ||
173 | struct flowi *fl, | ||
174 | struct dst_entry **dst_p); | ||
175 | void (*decode_session)(struct sk_buff *skb, | ||
176 | struct flowi *fl); | ||
177 | }; | ||
178 | |||
179 | extern int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo); | ||
180 | extern int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo); | ||
181 | |||
182 | #define XFRM_ACQ_EXPIRES 30 | ||
183 | |||
184 | struct xfrm_tmpl; | ||
185 | struct xfrm_state_afinfo { | ||
186 | unsigned short family; | ||
187 | rwlock_t lock; | ||
188 | struct list_head *state_bydst; | ||
189 | struct list_head *state_byspi; | ||
190 | void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, | ||
191 | struct xfrm_tmpl *tmpl, | ||
192 | xfrm_address_t *daddr, xfrm_address_t *saddr); | ||
193 | struct xfrm_state *(*state_lookup)(xfrm_address_t *daddr, u32 spi, u8 proto); | ||
194 | struct xfrm_state *(*find_acq)(u8 mode, u32 reqid, u8 proto, | ||
195 | xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
196 | int create); | ||
197 | }; | ||
198 | |||
199 | extern int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo); | ||
200 | extern int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo); | ||
201 | |||
202 | extern void xfrm_state_delete_tunnel(struct xfrm_state *x); | ||
203 | |||
204 | struct xfrm_decap_state; | ||
205 | struct xfrm_type | ||
206 | { | ||
207 | char *description; | ||
208 | struct module *owner; | ||
209 | __u8 proto; | ||
210 | |||
211 | int (*init_state)(struct xfrm_state *x, void *args); | ||
212 | void (*destructor)(struct xfrm_state *); | ||
213 | int (*input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb); | ||
214 | int (*post_input)(struct xfrm_state *, struct xfrm_decap_state *, struct sk_buff *skb); | ||
215 | int (*output)(struct xfrm_state *, struct sk_buff *pskb); | ||
216 | /* Estimate maximal size of result of transformation of a dgram */ | ||
217 | u32 (*get_max_size)(struct xfrm_state *, int size); | ||
218 | }; | ||
219 | |||
220 | struct xfrm_type_map { | ||
221 | rwlock_t lock; | ||
222 | struct xfrm_type *map[256]; | ||
223 | }; | ||
224 | |||
225 | extern int xfrm_register_type(struct xfrm_type *type, unsigned short family); | ||
226 | extern int xfrm_unregister_type(struct xfrm_type *type, unsigned short family); | ||
227 | extern struct xfrm_type *xfrm_get_type(u8 proto, unsigned short family); | ||
228 | extern void xfrm_put_type(struct xfrm_type *type); | ||
229 | |||
230 | struct xfrm_tmpl | ||
231 | { | ||
232 | /* id in template is interpreted as: | ||
233 | * daddr - destination of tunnel, may be zero for transport mode. | ||
234 | * spi - zero to acquire spi. Not zero if spi is static, then | ||
235 | * daddr must be fixed too. | ||
236 | * proto - AH/ESP/IPCOMP | ||
237 | */ | ||
238 | struct xfrm_id id; | ||
239 | |||
240 | /* Source address of tunnel. Ignored, if it is not a tunnel. */ | ||
241 | xfrm_address_t saddr; | ||
242 | |||
243 | __u32 reqid; | ||
244 | |||
245 | /* Mode: transport/tunnel */ | ||
246 | __u8 mode; | ||
247 | |||
248 | /* Sharing mode: unique, this session only, this user only etc. */ | ||
249 | __u8 share; | ||
250 | |||
251 | /* May skip this transfomration if no SA is found */ | ||
252 | __u8 optional; | ||
253 | |||
254 | /* Bit mask of algos allowed for acquisition */ | ||
255 | __u32 aalgos; | ||
256 | __u32 ealgos; | ||
257 | __u32 calgos; | ||
258 | }; | ||
259 | |||
260 | #define XFRM_MAX_DEPTH 4 | ||
261 | |||
262 | struct xfrm_policy | ||
263 | { | ||
264 | struct xfrm_policy *next; | ||
265 | struct list_head list; | ||
266 | |||
267 | /* This lock only affects elements except for entry. */ | ||
268 | rwlock_t lock; | ||
269 | atomic_t refcnt; | ||
270 | struct timer_list timer; | ||
271 | |||
272 | u32 priority; | ||
273 | u32 index; | ||
274 | struct xfrm_selector selector; | ||
275 | struct xfrm_lifetime_cfg lft; | ||
276 | struct xfrm_lifetime_cur curlft; | ||
277 | struct dst_entry *bundles; | ||
278 | __u16 family; | ||
279 | __u8 action; | ||
280 | __u8 flags; | ||
281 | __u8 dead; | ||
282 | __u8 xfrm_nr; | ||
283 | struct xfrm_tmpl xfrm_vec[XFRM_MAX_DEPTH]; | ||
284 | }; | ||
285 | |||
286 | #define XFRM_KM_TIMEOUT 30 | ||
287 | |||
288 | struct xfrm_mgr | ||
289 | { | ||
290 | struct list_head list; | ||
291 | char *id; | ||
292 | int (*notify)(struct xfrm_state *x, int event); | ||
293 | int (*acquire)(struct xfrm_state *x, struct xfrm_tmpl *, struct xfrm_policy *xp, int dir); | ||
294 | struct xfrm_policy *(*compile_policy)(u16 family, int opt, u8 *data, int len, int *dir); | ||
295 | int (*new_mapping)(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); | ||
296 | int (*notify_policy)(struct xfrm_policy *x, int dir, int event); | ||
297 | }; | ||
298 | |||
299 | extern int xfrm_register_km(struct xfrm_mgr *km); | ||
300 | extern int xfrm_unregister_km(struct xfrm_mgr *km); | ||
301 | |||
302 | |||
303 | extern struct xfrm_policy *xfrm_policy_list[XFRM_POLICY_MAX*2]; | ||
304 | |||
305 | static inline void xfrm_pol_hold(struct xfrm_policy *policy) | ||
306 | { | ||
307 | if (likely(policy != NULL)) | ||
308 | atomic_inc(&policy->refcnt); | ||
309 | } | ||
310 | |||
311 | extern void __xfrm_policy_destroy(struct xfrm_policy *policy); | ||
312 | |||
313 | static inline void xfrm_pol_put(struct xfrm_policy *policy) | ||
314 | { | ||
315 | if (atomic_dec_and_test(&policy->refcnt)) | ||
316 | __xfrm_policy_destroy(policy); | ||
317 | } | ||
318 | |||
319 | #define XFRM_DST_HSIZE 1024 | ||
320 | |||
321 | static __inline__ | ||
322 | unsigned __xfrm4_dst_hash(xfrm_address_t *addr) | ||
323 | { | ||
324 | unsigned h; | ||
325 | h = ntohl(addr->a4); | ||
326 | h = (h ^ (h>>16)) % XFRM_DST_HSIZE; | ||
327 | return h; | ||
328 | } | ||
329 | |||
330 | static __inline__ | ||
331 | unsigned __xfrm6_dst_hash(xfrm_address_t *addr) | ||
332 | { | ||
333 | unsigned h; | ||
334 | h = ntohl(addr->a6[2]^addr->a6[3]); | ||
335 | h = (h ^ (h>>16)) % XFRM_DST_HSIZE; | ||
336 | return h; | ||
337 | } | ||
338 | |||
339 | static __inline__ | ||
340 | unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) | ||
341 | { | ||
342 | switch (family) { | ||
343 | case AF_INET: | ||
344 | return __xfrm4_dst_hash(addr); | ||
345 | case AF_INET6: | ||
346 | return __xfrm6_dst_hash(addr); | ||
347 | } | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static __inline__ | ||
352 | unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) | ||
353 | { | ||
354 | unsigned h; | ||
355 | h = ntohl(addr->a4^spi^proto); | ||
356 | h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; | ||
357 | return h; | ||
358 | } | ||
359 | |||
360 | static __inline__ | ||
361 | unsigned __xfrm6_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) | ||
362 | { | ||
363 | unsigned h; | ||
364 | h = ntohl(addr->a6[2]^addr->a6[3]^spi^proto); | ||
365 | h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; | ||
366 | return h; | ||
367 | } | ||
368 | |||
369 | static __inline__ | ||
370 | unsigned xfrm_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto, unsigned short family) | ||
371 | { | ||
372 | switch (family) { | ||
373 | case AF_INET: | ||
374 | return __xfrm4_spi_hash(addr, spi, proto); | ||
375 | case AF_INET6: | ||
376 | return __xfrm6_spi_hash(addr, spi, proto); | ||
377 | } | ||
378 | return 0; /*XXX*/ | ||
379 | } | ||
380 | |||
381 | extern void __xfrm_state_destroy(struct xfrm_state *); | ||
382 | |||
383 | static inline void xfrm_state_put(struct xfrm_state *x) | ||
384 | { | ||
385 | if (atomic_dec_and_test(&x->refcnt)) | ||
386 | __xfrm_state_destroy(x); | ||
387 | } | ||
388 | |||
389 | static inline void xfrm_state_hold(struct xfrm_state *x) | ||
390 | { | ||
391 | atomic_inc(&x->refcnt); | ||
392 | } | ||
393 | |||
394 | static __inline__ int addr_match(void *token1, void *token2, int prefixlen) | ||
395 | { | ||
396 | __u32 *a1 = token1; | ||
397 | __u32 *a2 = token2; | ||
398 | int pdw; | ||
399 | int pbi; | ||
400 | |||
401 | pdw = prefixlen >> 5; /* num of whole __u32 in prefix */ | ||
402 | pbi = prefixlen & 0x1f; /* num of bits in incomplete u32 in prefix */ | ||
403 | |||
404 | if (pdw) | ||
405 | if (memcmp(a1, a2, pdw << 2)) | ||
406 | return 0; | ||
407 | |||
408 | if (pbi) { | ||
409 | __u32 mask; | ||
410 | |||
411 | mask = htonl((0xffffffff) << (32 - pbi)); | ||
412 | |||
413 | if ((a1[pdw] ^ a2[pdw]) & mask) | ||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | return 1; | ||
418 | } | ||
419 | |||
420 | static __inline__ | ||
421 | u16 xfrm_flowi_sport(struct flowi *fl) | ||
422 | { | ||
423 | u16 port; | ||
424 | switch(fl->proto) { | ||
425 | case IPPROTO_TCP: | ||
426 | case IPPROTO_UDP: | ||
427 | case IPPROTO_SCTP: | ||
428 | port = fl->fl_ip_sport; | ||
429 | break; | ||
430 | case IPPROTO_ICMP: | ||
431 | case IPPROTO_ICMPV6: | ||
432 | port = htons(fl->fl_icmp_type); | ||
433 | break; | ||
434 | default: | ||
435 | port = 0; /*XXX*/ | ||
436 | } | ||
437 | return port; | ||
438 | } | ||
439 | |||
440 | static __inline__ | ||
441 | u16 xfrm_flowi_dport(struct flowi *fl) | ||
442 | { | ||
443 | u16 port; | ||
444 | switch(fl->proto) { | ||
445 | case IPPROTO_TCP: | ||
446 | case IPPROTO_UDP: | ||
447 | case IPPROTO_SCTP: | ||
448 | port = fl->fl_ip_dport; | ||
449 | break; | ||
450 | case IPPROTO_ICMP: | ||
451 | case IPPROTO_ICMPV6: | ||
452 | port = htons(fl->fl_icmp_code); | ||
453 | break; | ||
454 | default: | ||
455 | port = 0; /*XXX*/ | ||
456 | } | ||
457 | return port; | ||
458 | } | ||
459 | |||
460 | static inline int | ||
461 | __xfrm4_selector_match(struct xfrm_selector *sel, struct flowi *fl) | ||
462 | { | ||
463 | return addr_match(&fl->fl4_dst, &sel->daddr, sel->prefixlen_d) && | ||
464 | addr_match(&fl->fl4_src, &sel->saddr, sel->prefixlen_s) && | ||
465 | !((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) && | ||
466 | !((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) && | ||
467 | (fl->proto == sel->proto || !sel->proto) && | ||
468 | (fl->oif == sel->ifindex || !sel->ifindex); | ||
469 | } | ||
470 | |||
471 | static inline int | ||
472 | __xfrm6_selector_match(struct xfrm_selector *sel, struct flowi *fl) | ||
473 | { | ||
474 | return addr_match(&fl->fl6_dst, &sel->daddr, sel->prefixlen_d) && | ||
475 | addr_match(&fl->fl6_src, &sel->saddr, sel->prefixlen_s) && | ||
476 | !((xfrm_flowi_dport(fl) ^ sel->dport) & sel->dport_mask) && | ||
477 | !((xfrm_flowi_sport(fl) ^ sel->sport) & sel->sport_mask) && | ||
478 | (fl->proto == sel->proto || !sel->proto) && | ||
479 | (fl->oif == sel->ifindex || !sel->ifindex); | ||
480 | } | ||
481 | |||
482 | static inline int | ||
483 | xfrm_selector_match(struct xfrm_selector *sel, struct flowi *fl, | ||
484 | unsigned short family) | ||
485 | { | ||
486 | switch (family) { | ||
487 | case AF_INET: | ||
488 | return __xfrm4_selector_match(sel, fl); | ||
489 | case AF_INET6: | ||
490 | return __xfrm6_selector_match(sel, fl); | ||
491 | } | ||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | /* A struct encoding bundle of transformations to apply to some set of flow. | ||
496 | * | ||
497 | * dst->child points to the next element of bundle. | ||
498 | * dst->xfrm points to an instanse of transformer. | ||
499 | * | ||
500 | * Due to unfortunate limitations of current routing cache, which we | ||
501 | * have no time to fix, it mirrors struct rtable and bound to the same | ||
502 | * routing key, including saddr,daddr. However, we can have many of | ||
503 | * bundles differing by session id. All the bundles grow from a parent | ||
504 | * policy rule. | ||
505 | */ | ||
506 | struct xfrm_dst | ||
507 | { | ||
508 | union { | ||
509 | struct xfrm_dst *next; | ||
510 | struct dst_entry dst; | ||
511 | struct rtable rt; | ||
512 | struct rt6_info rt6; | ||
513 | } u; | ||
514 | struct dst_entry *route; | ||
515 | u32 route_mtu_cached; | ||
516 | u32 child_mtu_cached; | ||
517 | }; | ||
518 | |||
519 | /* Decapsulation state, used by the input to store data during | ||
520 | * decapsulation procedure, to be used later (during the policy | ||
521 | * check | ||
522 | */ | ||
523 | struct xfrm_decap_state { | ||
524 | char decap_data[20]; | ||
525 | __u16 decap_type; | ||
526 | }; | ||
527 | |||
528 | struct sec_decap_state { | ||
529 | struct xfrm_state *xvec; | ||
530 | struct xfrm_decap_state decap; | ||
531 | }; | ||
532 | |||
533 | struct sec_path | ||
534 | { | ||
535 | atomic_t refcnt; | ||
536 | int len; | ||
537 | struct sec_decap_state x[XFRM_MAX_DEPTH]; | ||
538 | }; | ||
539 | |||
540 | static inline struct sec_path * | ||
541 | secpath_get(struct sec_path *sp) | ||
542 | { | ||
543 | if (sp) | ||
544 | atomic_inc(&sp->refcnt); | ||
545 | return sp; | ||
546 | } | ||
547 | |||
548 | extern void __secpath_destroy(struct sec_path *sp); | ||
549 | |||
550 | static inline void | ||
551 | secpath_put(struct sec_path *sp) | ||
552 | { | ||
553 | if (sp && atomic_dec_and_test(&sp->refcnt)) | ||
554 | __secpath_destroy(sp); | ||
555 | } | ||
556 | |||
557 | extern struct sec_path *secpath_dup(struct sec_path *src); | ||
558 | |||
559 | static inline void | ||
560 | secpath_reset(struct sk_buff *skb) | ||
561 | { | ||
562 | #ifdef CONFIG_XFRM | ||
563 | secpath_put(skb->sp); | ||
564 | skb->sp = NULL; | ||
565 | #endif | ||
566 | } | ||
567 | |||
568 | static inline int | ||
569 | __xfrm4_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x) | ||
570 | { | ||
571 | return (tmpl->saddr.a4 && | ||
572 | tmpl->saddr.a4 != x->props.saddr.a4); | ||
573 | } | ||
574 | |||
575 | static inline int | ||
576 | __xfrm6_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x) | ||
577 | { | ||
578 | return (!ipv6_addr_any((struct in6_addr*)&tmpl->saddr) && | ||
579 | ipv6_addr_cmp((struct in6_addr *)&tmpl->saddr, (struct in6_addr*)&x->props.saddr)); | ||
580 | } | ||
581 | |||
582 | static inline int | ||
583 | xfrm_state_addr_cmp(struct xfrm_tmpl *tmpl, struct xfrm_state *x, unsigned short family) | ||
584 | { | ||
585 | switch (family) { | ||
586 | case AF_INET: | ||
587 | return __xfrm4_state_addr_cmp(tmpl, x); | ||
588 | case AF_INET6: | ||
589 | return __xfrm6_state_addr_cmp(tmpl, x); | ||
590 | } | ||
591 | return !0; | ||
592 | } | ||
593 | |||
594 | #ifdef CONFIG_XFRM | ||
595 | |||
596 | extern int __xfrm_policy_check(struct sock *, int dir, struct sk_buff *skb, unsigned short family); | ||
597 | |||
598 | static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family) | ||
599 | { | ||
600 | if (sk && sk->sk_policy[XFRM_POLICY_IN]) | ||
601 | return __xfrm_policy_check(sk, dir, skb, family); | ||
602 | |||
603 | return (!xfrm_policy_list[dir] && !skb->sp) || | ||
604 | (skb->dst->flags & DST_NOPOLICY) || | ||
605 | __xfrm_policy_check(sk, dir, skb, family); | ||
606 | } | ||
607 | |||
608 | static inline int xfrm4_policy_check(struct sock *sk, int dir, struct sk_buff *skb) | ||
609 | { | ||
610 | return xfrm_policy_check(sk, dir, skb, AF_INET); | ||
611 | } | ||
612 | |||
613 | static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb) | ||
614 | { | ||
615 | return xfrm_policy_check(sk, dir, skb, AF_INET6); | ||
616 | } | ||
617 | |||
618 | |||
619 | extern int __xfrm_route_forward(struct sk_buff *skb, unsigned short family); | ||
620 | |||
621 | static inline int xfrm_route_forward(struct sk_buff *skb, unsigned short family) | ||
622 | { | ||
623 | return !xfrm_policy_list[XFRM_POLICY_OUT] || | ||
624 | (skb->dst->flags & DST_NOXFRM) || | ||
625 | __xfrm_route_forward(skb, family); | ||
626 | } | ||
627 | |||
628 | static inline int xfrm4_route_forward(struct sk_buff *skb) | ||
629 | { | ||
630 | return xfrm_route_forward(skb, AF_INET); | ||
631 | } | ||
632 | |||
633 | static inline int xfrm6_route_forward(struct sk_buff *skb) | ||
634 | { | ||
635 | return xfrm_route_forward(skb, AF_INET6); | ||
636 | } | ||
637 | |||
638 | extern int __xfrm_sk_clone_policy(struct sock *sk); | ||
639 | |||
640 | static inline int xfrm_sk_clone_policy(struct sock *sk) | ||
641 | { | ||
642 | if (unlikely(sk->sk_policy[0] || sk->sk_policy[1])) | ||
643 | return __xfrm_sk_clone_policy(sk); | ||
644 | return 0; | ||
645 | } | ||
646 | |||
647 | extern void xfrm_policy_delete(struct xfrm_policy *pol, int dir); | ||
648 | |||
649 | static inline void xfrm_sk_free_policy(struct sock *sk) | ||
650 | { | ||
651 | if (unlikely(sk->sk_policy[0] != NULL)) { | ||
652 | xfrm_policy_delete(sk->sk_policy[0], XFRM_POLICY_MAX); | ||
653 | sk->sk_policy[0] = NULL; | ||
654 | } | ||
655 | if (unlikely(sk->sk_policy[1] != NULL)) { | ||
656 | xfrm_policy_delete(sk->sk_policy[1], XFRM_POLICY_MAX+1); | ||
657 | sk->sk_policy[1] = NULL; | ||
658 | } | ||
659 | } | ||
660 | |||
661 | #else | ||
662 | |||
663 | static inline void xfrm_sk_free_policy(struct sock *sk) {} | ||
664 | static inline int xfrm_sk_clone_policy(struct sock *sk) { return 0; } | ||
665 | static inline int xfrm6_route_forward(struct sk_buff *skb) { return 1; } | ||
666 | static inline int xfrm4_route_forward(struct sk_buff *skb) { return 1; } | ||
667 | static inline int xfrm6_policy_check(struct sock *sk, int dir, struct sk_buff *skb) | ||
668 | { | ||
669 | return 1; | ||
670 | } | ||
671 | static inline int xfrm4_policy_check(struct sock *sk, int dir, struct sk_buff *skb) | ||
672 | { | ||
673 | return 1; | ||
674 | } | ||
675 | static inline int xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, unsigned short family) | ||
676 | { | ||
677 | return 1; | ||
678 | } | ||
679 | #endif | ||
680 | |||
681 | static __inline__ | ||
682 | xfrm_address_t *xfrm_flowi_daddr(struct flowi *fl, unsigned short family) | ||
683 | { | ||
684 | switch (family){ | ||
685 | case AF_INET: | ||
686 | return (xfrm_address_t *)&fl->fl4_dst; | ||
687 | case AF_INET6: | ||
688 | return (xfrm_address_t *)&fl->fl6_dst; | ||
689 | } | ||
690 | return NULL; | ||
691 | } | ||
692 | |||
693 | static __inline__ | ||
694 | xfrm_address_t *xfrm_flowi_saddr(struct flowi *fl, unsigned short family) | ||
695 | { | ||
696 | switch (family){ | ||
697 | case AF_INET: | ||
698 | return (xfrm_address_t *)&fl->fl4_src; | ||
699 | case AF_INET6: | ||
700 | return (xfrm_address_t *)&fl->fl6_src; | ||
701 | } | ||
702 | return NULL; | ||
703 | } | ||
704 | |||
705 | static __inline__ int | ||
706 | __xfrm4_state_addr_check(struct xfrm_state *x, | ||
707 | xfrm_address_t *daddr, xfrm_address_t *saddr) | ||
708 | { | ||
709 | if (daddr->a4 == x->id.daddr.a4 && | ||
710 | (saddr->a4 == x->props.saddr.a4 || !saddr->a4 || !x->props.saddr.a4)) | ||
711 | return 1; | ||
712 | return 0; | ||
713 | } | ||
714 | |||
715 | static __inline__ int | ||
716 | __xfrm6_state_addr_check(struct xfrm_state *x, | ||
717 | xfrm_address_t *daddr, xfrm_address_t *saddr) | ||
718 | { | ||
719 | if (!ipv6_addr_cmp((struct in6_addr *)daddr, (struct in6_addr *)&x->id.daddr) && | ||
720 | (!ipv6_addr_cmp((struct in6_addr *)saddr, (struct in6_addr *)&x->props.saddr)|| | ||
721 | ipv6_addr_any((struct in6_addr *)saddr) || | ||
722 | ipv6_addr_any((struct in6_addr *)&x->props.saddr))) | ||
723 | return 1; | ||
724 | return 0; | ||
725 | } | ||
726 | |||
727 | static __inline__ int | ||
728 | xfrm_state_addr_check(struct xfrm_state *x, | ||
729 | xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
730 | unsigned short family) | ||
731 | { | ||
732 | switch (family) { | ||
733 | case AF_INET: | ||
734 | return __xfrm4_state_addr_check(x, daddr, saddr); | ||
735 | case AF_INET6: | ||
736 | return __xfrm6_state_addr_check(x, daddr, saddr); | ||
737 | } | ||
738 | return 0; | ||
739 | } | ||
740 | |||
741 | static inline int xfrm_state_kern(struct xfrm_state *x) | ||
742 | { | ||
743 | return atomic_read(&x->tunnel_users); | ||
744 | } | ||
745 | |||
746 | /* | ||
747 | * xfrm algorithm information | ||
748 | */ | ||
749 | struct xfrm_algo_auth_info { | ||
750 | u16 icv_truncbits; | ||
751 | u16 icv_fullbits; | ||
752 | }; | ||
753 | |||
754 | struct xfrm_algo_encr_info { | ||
755 | u16 blockbits; | ||
756 | u16 defkeybits; | ||
757 | }; | ||
758 | |||
759 | struct xfrm_algo_comp_info { | ||
760 | u16 threshold; | ||
761 | }; | ||
762 | |||
763 | struct xfrm_algo_desc { | ||
764 | char *name; | ||
765 | u8 available:1; | ||
766 | union { | ||
767 | struct xfrm_algo_auth_info auth; | ||
768 | struct xfrm_algo_encr_info encr; | ||
769 | struct xfrm_algo_comp_info comp; | ||
770 | } uinfo; | ||
771 | struct sadb_alg desc; | ||
772 | }; | ||
773 | |||
774 | /* XFRM tunnel handlers. */ | ||
775 | struct xfrm_tunnel { | ||
776 | int (*handler)(struct sk_buff *skb); | ||
777 | void (*err_handler)(struct sk_buff *skb, void *info); | ||
778 | }; | ||
779 | |||
780 | struct xfrm6_tunnel { | ||
781 | int (*handler)(struct sk_buff **pskb, unsigned int *nhoffp); | ||
782 | void (*err_handler)(struct sk_buff *skb, struct inet6_skb_parm *opt, | ||
783 | int type, int code, int offset, __u32 info); | ||
784 | }; | ||
785 | |||
786 | extern void xfrm_init(void); | ||
787 | extern void xfrm4_init(void); | ||
788 | extern void xfrm6_init(void); | ||
789 | extern void xfrm6_fini(void); | ||
790 | extern void xfrm_state_init(void); | ||
791 | extern void xfrm4_state_init(void); | ||
792 | extern void xfrm4_state_fini(void); | ||
793 | extern void xfrm6_state_init(void); | ||
794 | extern void xfrm6_state_fini(void); | ||
795 | |||
796 | extern int xfrm_state_walk(u8 proto, int (*func)(struct xfrm_state *, int, void*), void *); | ||
797 | extern struct xfrm_state *xfrm_state_alloc(void); | ||
798 | extern struct xfrm_state *xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
799 | struct flowi *fl, struct xfrm_tmpl *tmpl, | ||
800 | struct xfrm_policy *pol, int *err, | ||
801 | unsigned short family); | ||
802 | extern int xfrm_state_check_expire(struct xfrm_state *x); | ||
803 | extern void xfrm_state_insert(struct xfrm_state *x); | ||
804 | extern int xfrm_state_add(struct xfrm_state *x); | ||
805 | extern int xfrm_state_update(struct xfrm_state *x); | ||
806 | extern struct xfrm_state *xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family); | ||
807 | extern struct xfrm_state *xfrm_find_acq_byseq(u32 seq); | ||
808 | extern void xfrm_state_delete(struct xfrm_state *x); | ||
809 | extern void xfrm_state_flush(u8 proto); | ||
810 | extern int xfrm_replay_check(struct xfrm_state *x, u32 seq); | ||
811 | extern void xfrm_replay_advance(struct xfrm_state *x, u32 seq); | ||
812 | extern int xfrm_state_check(struct xfrm_state *x, struct sk_buff *skb); | ||
813 | extern int xfrm_state_mtu(struct xfrm_state *x, int mtu); | ||
814 | extern int xfrm4_rcv(struct sk_buff *skb); | ||
815 | extern int xfrm4_output(struct sk_buff *skb); | ||
816 | extern int xfrm4_tunnel_register(struct xfrm_tunnel *handler); | ||
817 | extern int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler); | ||
818 | extern int xfrm6_rcv_spi(struct sk_buff **pskb, unsigned int *nhoffp, u32 spi); | ||
819 | extern int xfrm6_rcv(struct sk_buff **pskb, unsigned int *nhoffp); | ||
820 | extern int xfrm6_tunnel_register(struct xfrm6_tunnel *handler); | ||
821 | extern int xfrm6_tunnel_deregister(struct xfrm6_tunnel *handler); | ||
822 | extern u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr); | ||
823 | extern void xfrm6_tunnel_free_spi(xfrm_address_t *saddr); | ||
824 | extern u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr); | ||
825 | extern int xfrm6_output(struct sk_buff *skb); | ||
826 | |||
827 | #ifdef CONFIG_XFRM | ||
828 | extern int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type); | ||
829 | extern int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen); | ||
830 | extern int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family); | ||
831 | #else | ||
832 | static inline int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen) | ||
833 | { | ||
834 | return -ENOPROTOOPT; | ||
835 | } | ||
836 | |||
837 | static inline int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type) | ||
838 | { | ||
839 | /* should not happen */ | ||
840 | kfree_skb(skb); | ||
841 | return 0; | ||
842 | } | ||
843 | static inline int xfrm_dst_lookup(struct xfrm_dst **dst, struct flowi *fl, unsigned short family) | ||
844 | { | ||
845 | return -EINVAL; | ||
846 | } | ||
847 | #endif | ||
848 | |||
849 | struct xfrm_policy *xfrm_policy_alloc(int gfp); | ||
850 | extern int xfrm_policy_walk(int (*func)(struct xfrm_policy *, int, int, void*), void *); | ||
851 | int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl); | ||
852 | struct xfrm_policy *xfrm_policy_bysel(int dir, struct xfrm_selector *sel, | ||
853 | int delete); | ||
854 | struct xfrm_policy *xfrm_policy_byid(int dir, u32 id, int delete); | ||
855 | void xfrm_policy_flush(void); | ||
856 | u32 xfrm_get_acqseq(void); | ||
857 | void xfrm_alloc_spi(struct xfrm_state *x, u32 minspi, u32 maxspi); | ||
858 | struct xfrm_state * xfrm_find_acq(u8 mode, u32 reqid, u8 proto, | ||
859 | xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
860 | int create, unsigned short family); | ||
861 | extern void xfrm_policy_flush(void); | ||
862 | extern int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol); | ||
863 | extern int xfrm_flush_bundles(void); | ||
864 | extern int xfrm_bundle_ok(struct xfrm_dst *xdst, struct flowi *fl, int family); | ||
865 | extern void xfrm_init_pmtu(struct dst_entry *dst); | ||
866 | |||
867 | extern wait_queue_head_t km_waitq; | ||
868 | extern int km_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, u16 sport); | ||
869 | extern void km_policy_expired(struct xfrm_policy *pol, int dir, int hard); | ||
870 | |||
871 | extern void xfrm_input_init(void); | ||
872 | extern int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq); | ||
873 | |||
874 | extern void xfrm_probe_algs(void); | ||
875 | extern int xfrm_count_auth_supported(void); | ||
876 | extern int xfrm_count_enc_supported(void); | ||
877 | extern struct xfrm_algo_desc *xfrm_aalg_get_byidx(unsigned int idx); | ||
878 | extern struct xfrm_algo_desc *xfrm_ealg_get_byidx(unsigned int idx); | ||
879 | extern struct xfrm_algo_desc *xfrm_aalg_get_byid(int alg_id); | ||
880 | extern struct xfrm_algo_desc *xfrm_ealg_get_byid(int alg_id); | ||
881 | extern struct xfrm_algo_desc *xfrm_calg_get_byid(int alg_id); | ||
882 | extern struct xfrm_algo_desc *xfrm_aalg_get_byname(char *name, int probe); | ||
883 | extern struct xfrm_algo_desc *xfrm_ealg_get_byname(char *name, int probe); | ||
884 | extern struct xfrm_algo_desc *xfrm_calg_get_byname(char *name, int probe); | ||
885 | |||
886 | struct crypto_tfm; | ||
887 | typedef void (icv_update_fn_t)(struct crypto_tfm *, struct scatterlist *, unsigned int); | ||
888 | |||
889 | extern void skb_icv_walk(const struct sk_buff *skb, struct crypto_tfm *tfm, | ||
890 | int offset, int len, icv_update_fn_t icv_update); | ||
891 | |||
892 | static inline int xfrm_addr_cmp(xfrm_address_t *a, xfrm_address_t *b, | ||
893 | int family) | ||
894 | { | ||
895 | switch (family) { | ||
896 | default: | ||
897 | case AF_INET: | ||
898 | return a->a4 - b->a4; | ||
899 | case AF_INET6: | ||
900 | return ipv6_addr_cmp((struct in6_addr *)a, | ||
901 | (struct in6_addr *)b); | ||
902 | } | ||
903 | } | ||
904 | |||
905 | #endif /* _NET_XFRM_H */ | ||