diff options
-rw-r--r-- | include/net/xfrm.h | 78 | ||||
-rw-r--r-- | net/ipv4/xfrm4_state.c | 28 | ||||
-rw-r--r-- | net/ipv6/xfrm6_state.c | 40 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 210 |
4 files changed, 159 insertions, 197 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index cc83443f301e..dd3b84b9c04e 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -243,14 +243,10 @@ extern int __xfrm_state_delete(struct xfrm_state *x); | |||
243 | 243 | ||
244 | struct xfrm_state_afinfo { | 244 | struct xfrm_state_afinfo { |
245 | unsigned short family; | 245 | unsigned short family; |
246 | struct list_head *state_bysrc; | ||
247 | struct list_head *state_byspi; | ||
248 | int (*init_flags)(struct xfrm_state *x); | 246 | int (*init_flags)(struct xfrm_state *x); |
249 | void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, | 247 | void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, |
250 | struct xfrm_tmpl *tmpl, | 248 | struct xfrm_tmpl *tmpl, |
251 | xfrm_address_t *daddr, xfrm_address_t *saddr); | 249 | xfrm_address_t *daddr, xfrm_address_t *saddr); |
252 | struct xfrm_state *(*state_lookup)(xfrm_address_t *daddr, u32 spi, u8 proto); | ||
253 | struct xfrm_state *(*state_lookup_byaddr)(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto); | ||
254 | int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n); | 250 | int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n); |
255 | int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n); | 251 | int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n); |
256 | }; | 252 | }; |
@@ -431,80 +427,6 @@ static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols) | |||
431 | } | 427 | } |
432 | #endif | 428 | #endif |
433 | 429 | ||
434 | #define XFRM_DST_HSIZE 1024 | ||
435 | |||
436 | static __inline__ | ||
437 | unsigned __xfrm4_dst_hash(xfrm_address_t *addr) | ||
438 | { | ||
439 | unsigned h; | ||
440 | h = ntohl(addr->a4); | ||
441 | h = (h ^ (h>>16)) % XFRM_DST_HSIZE; | ||
442 | return h; | ||
443 | } | ||
444 | |||
445 | static __inline__ | ||
446 | unsigned __xfrm6_dst_hash(xfrm_address_t *addr) | ||
447 | { | ||
448 | unsigned h; | ||
449 | h = ntohl(addr->a6[2]^addr->a6[3]); | ||
450 | h = (h ^ (h>>16)) % XFRM_DST_HSIZE; | ||
451 | return h; | ||
452 | } | ||
453 | |||
454 | static __inline__ | ||
455 | unsigned __xfrm4_src_hash(xfrm_address_t *addr) | ||
456 | { | ||
457 | return __xfrm4_dst_hash(addr); | ||
458 | } | ||
459 | |||
460 | static __inline__ | ||
461 | unsigned __xfrm6_src_hash(xfrm_address_t *addr) | ||
462 | { | ||
463 | return __xfrm6_dst_hash(addr); | ||
464 | } | ||
465 | |||
466 | static __inline__ | ||
467 | unsigned xfrm_src_hash(xfrm_address_t *addr, unsigned short family) | ||
468 | { | ||
469 | switch (family) { | ||
470 | case AF_INET: | ||
471 | return __xfrm4_src_hash(addr); | ||
472 | case AF_INET6: | ||
473 | return __xfrm6_src_hash(addr); | ||
474 | } | ||
475 | return 0; | ||
476 | } | ||
477 | |||
478 | static __inline__ | ||
479 | unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) | ||
480 | { | ||
481 | unsigned h; | ||
482 | h = ntohl(addr->a4^spi^proto); | ||
483 | h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; | ||
484 | return h; | ||
485 | } | ||
486 | |||
487 | static __inline__ | ||
488 | unsigned __xfrm6_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) | ||
489 | { | ||
490 | unsigned h; | ||
491 | h = ntohl(addr->a6[2]^addr->a6[3]^spi^proto); | ||
492 | h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; | ||
493 | return h; | ||
494 | } | ||
495 | |||
496 | static __inline__ | ||
497 | unsigned xfrm_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto, unsigned short family) | ||
498 | { | ||
499 | switch (family) { | ||
500 | case AF_INET: | ||
501 | return __xfrm4_spi_hash(addr, spi, proto); | ||
502 | case AF_INET6: | ||
503 | return __xfrm6_spi_hash(addr, spi, proto); | ||
504 | } | ||
505 | return 0; /*XXX*/ | ||
506 | } | ||
507 | |||
508 | extern void __xfrm_state_destroy(struct xfrm_state *); | 430 | extern void __xfrm_state_destroy(struct xfrm_state *); |
509 | 431 | ||
510 | static inline void __xfrm_state_put(struct xfrm_state *x) | 432 | static inline void __xfrm_state_put(struct xfrm_state *x) |
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 9dc1afc17b6d..6a2a4ab42772 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
@@ -62,38 +62,10 @@ __xfrm4_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
62 | x->props.family = AF_INET; | 62 | x->props.family = AF_INET; |
63 | } | 63 | } |
64 | 64 | ||
65 | static struct xfrm_state * | ||
66 | __xfrm4_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto) | ||
67 | { | ||
68 | unsigned h = __xfrm4_spi_hash(daddr, spi, proto); | ||
69 | struct xfrm_state *x; | ||
70 | |||
71 | list_for_each_entry(x, xfrm4_state_afinfo.state_byspi+h, byspi) { | ||
72 | if (x->props.family == AF_INET && | ||
73 | spi == x->id.spi && | ||
74 | daddr->a4 == x->id.daddr.a4 && | ||
75 | proto == x->id.proto) { | ||
76 | xfrm_state_hold(x); | ||
77 | return x; | ||
78 | } | ||
79 | } | ||
80 | return NULL; | ||
81 | } | ||
82 | |||
83 | /* placeholder until ipv4's code is written */ | ||
84 | static struct xfrm_state * | ||
85 | __xfrm4_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
86 | u8 proto) | ||
87 | { | ||
88 | return NULL; | ||
89 | } | ||
90 | |||
91 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { | 65 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { |
92 | .family = AF_INET, | 66 | .family = AF_INET, |
93 | .init_flags = xfrm4_init_flags, | 67 | .init_flags = xfrm4_init_flags, |
94 | .init_tempsel = __xfrm4_init_tempsel, | 68 | .init_tempsel = __xfrm4_init_tempsel, |
95 | .state_lookup = __xfrm4_state_lookup, | ||
96 | .state_lookup_byaddr = __xfrm4_state_lookup_byaddr, | ||
97 | }; | 69 | }; |
98 | 70 | ||
99 | void __init xfrm4_state_init(void) | 71 | void __init xfrm4_state_init(void) |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index 40fcaab7e028..d88cd92c864e 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -63,44 +63,6 @@ __xfrm6_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
63 | x->props.family = AF_INET6; | 63 | x->props.family = AF_INET6; |
64 | } | 64 | } |
65 | 65 | ||
66 | static struct xfrm_state * | ||
67 | __xfrm6_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
68 | u8 proto) | ||
69 | { | ||
70 | struct xfrm_state *x = NULL; | ||
71 | unsigned h; | ||
72 | |||
73 | h = __xfrm6_src_hash(saddr); | ||
74 | list_for_each_entry(x, xfrm6_state_afinfo.state_bysrc+h, bysrc) { | ||
75 | if (x->props.family == AF_INET6 && | ||
76 | ipv6_addr_equal((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) && | ||
77 | ipv6_addr_equal((struct in6_addr *)saddr, (struct in6_addr *)x->props.saddr.a6) && | ||
78 | proto == x->id.proto) { | ||
79 | xfrm_state_hold(x); | ||
80 | return x; | ||
81 | } | ||
82 | } | ||
83 | return NULL; | ||
84 | } | ||
85 | |||
86 | static struct xfrm_state * | ||
87 | __xfrm6_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto) | ||
88 | { | ||
89 | unsigned h = __xfrm6_spi_hash(daddr, spi, proto); | ||
90 | struct xfrm_state *x; | ||
91 | |||
92 | list_for_each_entry(x, xfrm6_state_afinfo.state_byspi+h, byspi) { | ||
93 | if (x->props.family == AF_INET6 && | ||
94 | spi == x->id.spi && | ||
95 | ipv6_addr_equal((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) && | ||
96 | proto == x->id.proto) { | ||
97 | xfrm_state_hold(x); | ||
98 | return x; | ||
99 | } | ||
100 | } | ||
101 | return NULL; | ||
102 | } | ||
103 | |||
104 | static int | 66 | static int |
105 | __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) | 67 | __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) |
106 | { | 68 | { |
@@ -223,8 +185,6 @@ __xfrm6_tmpl_sort(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n) | |||
223 | static struct xfrm_state_afinfo xfrm6_state_afinfo = { | 185 | static struct xfrm_state_afinfo xfrm6_state_afinfo = { |
224 | .family = AF_INET6, | 186 | .family = AF_INET6, |
225 | .init_tempsel = __xfrm6_init_tempsel, | 187 | .init_tempsel = __xfrm6_init_tempsel, |
226 | .state_lookup = __xfrm6_state_lookup, | ||
227 | .state_lookup_byaddr = __xfrm6_state_lookup_byaddr, | ||
228 | .tmpl_sort = __xfrm6_tmpl_sort, | 188 | .tmpl_sort = __xfrm6_tmpl_sort, |
229 | .state_sort = __xfrm6_state_sort, | 189 | .state_sort = __xfrm6_state_sort, |
230 | }; | 190 | }; |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 80f5f9dc2b9e..4a3832f81c37 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -38,6 +38,8 @@ EXPORT_SYMBOL(sysctl_xfrm_aevent_rseqth); | |||
38 | 38 | ||
39 | static DEFINE_SPINLOCK(xfrm_state_lock); | 39 | static DEFINE_SPINLOCK(xfrm_state_lock); |
40 | 40 | ||
41 | #define XFRM_DST_HSIZE 1024 | ||
42 | |||
41 | /* Hash table to find appropriate SA towards given target (endpoint | 43 | /* Hash table to find appropriate SA towards given target (endpoint |
42 | * of tunnel or destination of transport mode) allowed by selector. | 44 | * of tunnel or destination of transport mode) allowed by selector. |
43 | * | 45 | * |
@@ -49,6 +51,48 @@ static struct list_head xfrm_state_bysrc[XFRM_DST_HSIZE]; | |||
49 | static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; | 51 | static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; |
50 | 52 | ||
51 | static __inline__ | 53 | static __inline__ |
54 | unsigned __xfrm4_dst_hash(xfrm_address_t *addr) | ||
55 | { | ||
56 | unsigned h; | ||
57 | h = ntohl(addr->a4); | ||
58 | h = (h ^ (h>>16)) % XFRM_DST_HSIZE; | ||
59 | return h; | ||
60 | } | ||
61 | |||
62 | static __inline__ | ||
63 | unsigned __xfrm6_dst_hash(xfrm_address_t *addr) | ||
64 | { | ||
65 | unsigned h; | ||
66 | h = ntohl(addr->a6[2]^addr->a6[3]); | ||
67 | h = (h ^ (h>>16)) % XFRM_DST_HSIZE; | ||
68 | return h; | ||
69 | } | ||
70 | |||
71 | static __inline__ | ||
72 | unsigned __xfrm4_src_hash(xfrm_address_t *addr) | ||
73 | { | ||
74 | return __xfrm4_dst_hash(addr); | ||
75 | } | ||
76 | |||
77 | static __inline__ | ||
78 | unsigned __xfrm6_src_hash(xfrm_address_t *addr) | ||
79 | { | ||
80 | return __xfrm6_dst_hash(addr); | ||
81 | } | ||
82 | |||
83 | static __inline__ | ||
84 | unsigned xfrm_src_hash(xfrm_address_t *addr, unsigned short family) | ||
85 | { | ||
86 | switch (family) { | ||
87 | case AF_INET: | ||
88 | return __xfrm4_src_hash(addr); | ||
89 | case AF_INET6: | ||
90 | return __xfrm6_src_hash(addr); | ||
91 | } | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static __inline__ | ||
52 | unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) | 96 | unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) |
53 | { | 97 | { |
54 | switch (family) { | 98 | switch (family) { |
@@ -60,6 +104,36 @@ unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) | |||
60 | return 0; | 104 | return 0; |
61 | } | 105 | } |
62 | 106 | ||
107 | static __inline__ | ||
108 | unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) | ||
109 | { | ||
110 | unsigned h; | ||
111 | h = ntohl(addr->a4^spi^proto); | ||
112 | h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; | ||
113 | return h; | ||
114 | } | ||
115 | |||
116 | static __inline__ | ||
117 | unsigned __xfrm6_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) | ||
118 | { | ||
119 | unsigned h; | ||
120 | h = ntohl(addr->a6[2]^addr->a6[3]^spi^proto); | ||
121 | h = (h ^ (h>>10) ^ (h>>20)) % XFRM_DST_HSIZE; | ||
122 | return h; | ||
123 | } | ||
124 | |||
125 | static __inline__ | ||
126 | unsigned xfrm_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto, unsigned short family) | ||
127 | { | ||
128 | switch (family) { | ||
129 | case AF_INET: | ||
130 | return __xfrm4_spi_hash(addr, spi, proto); | ||
131 | case AF_INET6: | ||
132 | return __xfrm6_spi_hash(addr, spi, proto); | ||
133 | } | ||
134 | return 0; /*XXX*/ | ||
135 | } | ||
136 | |||
63 | DECLARE_WAIT_QUEUE_HEAD(km_waitq); | 137 | DECLARE_WAIT_QUEUE_HEAD(km_waitq); |
64 | EXPORT_SYMBOL(km_waitq); | 138 | EXPORT_SYMBOL(km_waitq); |
65 | 139 | ||
@@ -342,6 +416,83 @@ xfrm_init_tempsel(struct xfrm_state *x, struct flowi *fl, | |||
342 | return 0; | 416 | return 0; |
343 | } | 417 | } |
344 | 418 | ||
419 | static struct xfrm_state *__xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, unsigned short family) | ||
420 | { | ||
421 | unsigned int h = xfrm_spi_hash(daddr, spi, proto, family); | ||
422 | struct xfrm_state *x; | ||
423 | |||
424 | list_for_each_entry(x, xfrm_state_byspi+h, byspi) { | ||
425 | if (x->props.family != family || | ||
426 | x->id.spi != spi || | ||
427 | x->id.proto != proto) | ||
428 | continue; | ||
429 | |||
430 | switch (family) { | ||
431 | case AF_INET: | ||
432 | if (x->id.daddr.a4 != daddr->a4) | ||
433 | continue; | ||
434 | break; | ||
435 | case AF_INET6: | ||
436 | if (!ipv6_addr_equal((struct in6_addr *)daddr, | ||
437 | (struct in6_addr *) | ||
438 | x->id.daddr.a6)) | ||
439 | continue; | ||
440 | break; | ||
441 | }; | ||
442 | |||
443 | xfrm_state_hold(x); | ||
444 | return x; | ||
445 | } | ||
446 | |||
447 | return NULL; | ||
448 | } | ||
449 | |||
450 | static struct xfrm_state *__xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto, unsigned short family) | ||
451 | { | ||
452 | unsigned int h = xfrm_src_hash(saddr, family); | ||
453 | struct xfrm_state *x; | ||
454 | |||
455 | list_for_each_entry(x, xfrm_state_bysrc+h, bysrc) { | ||
456 | if (x->props.family != family || | ||
457 | x->id.proto != proto) | ||
458 | continue; | ||
459 | |||
460 | switch (family) { | ||
461 | case AF_INET: | ||
462 | if (x->id.daddr.a4 != daddr->a4 || | ||
463 | x->props.saddr.a4 != saddr->a4) | ||
464 | continue; | ||
465 | break; | ||
466 | case AF_INET6: | ||
467 | if (!ipv6_addr_equal((struct in6_addr *)daddr, | ||
468 | (struct in6_addr *) | ||
469 | x->id.daddr.a6) || | ||
470 | !ipv6_addr_equal((struct in6_addr *)saddr, | ||
471 | (struct in6_addr *) | ||
472 | x->props.saddr.a6)) | ||
473 | continue; | ||
474 | break; | ||
475 | }; | ||
476 | |||
477 | xfrm_state_hold(x); | ||
478 | return x; | ||
479 | } | ||
480 | |||
481 | return NULL; | ||
482 | } | ||
483 | |||
484 | static inline struct xfrm_state * | ||
485 | __xfrm_state_locate(struct xfrm_state *x, int use_spi, int family) | ||
486 | { | ||
487 | if (use_spi) | ||
488 | return __xfrm_state_lookup(&x->id.daddr, x->id.spi, | ||
489 | x->id.proto, family); | ||
490 | else | ||
491 | return __xfrm_state_lookup_byaddr(&x->id.daddr, | ||
492 | &x->props.saddr, | ||
493 | x->id.proto, family); | ||
494 | } | ||
495 | |||
345 | struct xfrm_state * | 496 | struct xfrm_state * |
346 | xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | 497 | xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, |
347 | struct flowi *fl, struct xfrm_tmpl *tmpl, | 498 | struct flowi *fl, struct xfrm_tmpl *tmpl, |
@@ -353,14 +504,7 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
353 | int acquire_in_progress = 0; | 504 | int acquire_in_progress = 0; |
354 | int error = 0; | 505 | int error = 0; |
355 | struct xfrm_state *best = NULL; | 506 | struct xfrm_state *best = NULL; |
356 | struct xfrm_state_afinfo *afinfo; | ||
357 | 507 | ||
358 | afinfo = xfrm_state_get_afinfo(family); | ||
359 | if (afinfo == NULL) { | ||
360 | *err = -EAFNOSUPPORT; | ||
361 | return NULL; | ||
362 | } | ||
363 | |||
364 | spin_lock_bh(&xfrm_state_lock); | 508 | spin_lock_bh(&xfrm_state_lock); |
365 | list_for_each_entry(x, xfrm_state_bydst+h, bydst) { | 509 | list_for_each_entry(x, xfrm_state_bydst+h, bydst) { |
366 | if (x->props.family == family && | 510 | if (x->props.family == family && |
@@ -406,8 +550,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
406 | x = best; | 550 | x = best; |
407 | if (!x && !error && !acquire_in_progress) { | 551 | if (!x && !error && !acquire_in_progress) { |
408 | if (tmpl->id.spi && | 552 | if (tmpl->id.spi && |
409 | (x0 = afinfo->state_lookup(daddr, tmpl->id.spi, | 553 | (x0 = __xfrm_state_lookup(daddr, tmpl->id.spi, |
410 | tmpl->id.proto)) != NULL) { | 554 | tmpl->id.proto, family)) != NULL) { |
411 | xfrm_state_put(x0); | 555 | xfrm_state_put(x0); |
412 | error = -EEXIST; | 556 | error = -EEXIST; |
413 | goto out; | 557 | goto out; |
@@ -457,7 +601,6 @@ out: | |||
457 | else | 601 | else |
458 | *err = acquire_in_progress ? -EAGAIN : error; | 602 | *err = acquire_in_progress ? -EAGAIN : error; |
459 | spin_unlock_bh(&xfrm_state_lock); | 603 | spin_unlock_bh(&xfrm_state_lock); |
460 | xfrm_state_put_afinfo(afinfo); | ||
461 | return x; | 604 | return x; |
462 | } | 605 | } |
463 | 606 | ||
@@ -584,34 +727,20 @@ static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 re | |||
584 | return x; | 727 | return x; |
585 | } | 728 | } |
586 | 729 | ||
587 | static inline struct xfrm_state * | ||
588 | __xfrm_state_locate(struct xfrm_state_afinfo *afinfo, struct xfrm_state *x, | ||
589 | int use_spi) | ||
590 | { | ||
591 | if (use_spi) | ||
592 | return afinfo->state_lookup(&x->id.daddr, x->id.spi, x->id.proto); | ||
593 | else | ||
594 | return afinfo->state_lookup_byaddr(&x->id.daddr, &x->props.saddr, x->id.proto); | ||
595 | } | ||
596 | |||
597 | static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); | 730 | static struct xfrm_state *__xfrm_find_acq_byseq(u32 seq); |
598 | 731 | ||
599 | int xfrm_state_add(struct xfrm_state *x) | 732 | int xfrm_state_add(struct xfrm_state *x) |
600 | { | 733 | { |
601 | struct xfrm_state_afinfo *afinfo; | ||
602 | struct xfrm_state *x1; | 734 | struct xfrm_state *x1; |
603 | int family; | 735 | int family; |
604 | int err; | 736 | int err; |
605 | int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); | 737 | int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); |
606 | 738 | ||
607 | family = x->props.family; | 739 | family = x->props.family; |
608 | afinfo = xfrm_state_get_afinfo(family); | ||
609 | if (unlikely(afinfo == NULL)) | ||
610 | return -EAFNOSUPPORT; | ||
611 | 740 | ||
612 | spin_lock_bh(&xfrm_state_lock); | 741 | spin_lock_bh(&xfrm_state_lock); |
613 | 742 | ||
614 | x1 = __xfrm_state_locate(afinfo, x, use_spi); | 743 | x1 = __xfrm_state_locate(x, use_spi, family); |
615 | if (x1) { | 744 | if (x1) { |
616 | xfrm_state_put(x1); | 745 | xfrm_state_put(x1); |
617 | x1 = NULL; | 746 | x1 = NULL; |
@@ -637,7 +766,6 @@ int xfrm_state_add(struct xfrm_state *x) | |||
637 | 766 | ||
638 | out: | 767 | out: |
639 | spin_unlock_bh(&xfrm_state_lock); | 768 | spin_unlock_bh(&xfrm_state_lock); |
640 | xfrm_state_put_afinfo(afinfo); | ||
641 | 769 | ||
642 | if (!err) | 770 | if (!err) |
643 | xfrm_flush_all_bundles(); | 771 | xfrm_flush_all_bundles(); |
@@ -653,17 +781,12 @@ EXPORT_SYMBOL(xfrm_state_add); | |||
653 | 781 | ||
654 | int xfrm_state_update(struct xfrm_state *x) | 782 | int xfrm_state_update(struct xfrm_state *x) |
655 | { | 783 | { |
656 | struct xfrm_state_afinfo *afinfo; | ||
657 | struct xfrm_state *x1; | 784 | struct xfrm_state *x1; |
658 | int err; | 785 | int err; |
659 | int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); | 786 | int use_spi = xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY); |
660 | 787 | ||
661 | afinfo = xfrm_state_get_afinfo(x->props.family); | ||
662 | if (unlikely(afinfo == NULL)) | ||
663 | return -EAFNOSUPPORT; | ||
664 | |||
665 | spin_lock_bh(&xfrm_state_lock); | 788 | spin_lock_bh(&xfrm_state_lock); |
666 | x1 = __xfrm_state_locate(afinfo, x, use_spi); | 789 | x1 = __xfrm_state_locate(x, use_spi, x->props.family); |
667 | 790 | ||
668 | err = -ESRCH; | 791 | err = -ESRCH; |
669 | if (!x1) | 792 | if (!x1) |
@@ -683,7 +806,6 @@ int xfrm_state_update(struct xfrm_state *x) | |||
683 | 806 | ||
684 | out: | 807 | out: |
685 | spin_unlock_bh(&xfrm_state_lock); | 808 | spin_unlock_bh(&xfrm_state_lock); |
686 | xfrm_state_put_afinfo(afinfo); | ||
687 | 809 | ||
688 | if (err) | 810 | if (err) |
689 | return err; | 811 | return err; |
@@ -776,14 +898,10 @@ xfrm_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto, | |||
776 | unsigned short family) | 898 | unsigned short family) |
777 | { | 899 | { |
778 | struct xfrm_state *x; | 900 | struct xfrm_state *x; |
779 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); | ||
780 | if (!afinfo) | ||
781 | return NULL; | ||
782 | 901 | ||
783 | spin_lock_bh(&xfrm_state_lock); | 902 | spin_lock_bh(&xfrm_state_lock); |
784 | x = afinfo->state_lookup(daddr, spi, proto); | 903 | x = __xfrm_state_lookup(daddr, spi, proto, family); |
785 | spin_unlock_bh(&xfrm_state_lock); | 904 | spin_unlock_bh(&xfrm_state_lock); |
786 | xfrm_state_put_afinfo(afinfo); | ||
787 | return x; | 905 | return x; |
788 | } | 906 | } |
789 | EXPORT_SYMBOL(xfrm_state_lookup); | 907 | EXPORT_SYMBOL(xfrm_state_lookup); |
@@ -793,14 +911,10 @@ xfrm_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
793 | u8 proto, unsigned short family) | 911 | u8 proto, unsigned short family) |
794 | { | 912 | { |
795 | struct xfrm_state *x; | 913 | struct xfrm_state *x; |
796 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); | ||
797 | if (!afinfo) | ||
798 | return NULL; | ||
799 | 914 | ||
800 | spin_lock_bh(&xfrm_state_lock); | 915 | spin_lock_bh(&xfrm_state_lock); |
801 | x = afinfo->state_lookup_byaddr(daddr, saddr, proto); | 916 | x = __xfrm_state_lookup_byaddr(daddr, saddr, proto, family); |
802 | spin_unlock_bh(&xfrm_state_lock); | 917 | spin_unlock_bh(&xfrm_state_lock); |
803 | xfrm_state_put_afinfo(afinfo); | ||
804 | return x; | 918 | return x; |
805 | } | 919 | } |
806 | EXPORT_SYMBOL(xfrm_state_lookup_byaddr); | 920 | EXPORT_SYMBOL(xfrm_state_lookup_byaddr); |
@@ -1272,11 +1386,8 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo) | |||
1272 | write_lock_bh(&xfrm_state_afinfo_lock); | 1386 | write_lock_bh(&xfrm_state_afinfo_lock); |
1273 | if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) | 1387 | if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) |
1274 | err = -ENOBUFS; | 1388 | err = -ENOBUFS; |
1275 | else { | 1389 | else |
1276 | afinfo->state_bysrc = xfrm_state_bysrc; | ||
1277 | afinfo->state_byspi = xfrm_state_byspi; | ||
1278 | xfrm_state_afinfo[afinfo->family] = afinfo; | 1390 | xfrm_state_afinfo[afinfo->family] = afinfo; |
1279 | } | ||
1280 | write_unlock_bh(&xfrm_state_afinfo_lock); | 1391 | write_unlock_bh(&xfrm_state_afinfo_lock); |
1281 | return err; | 1392 | return err; |
1282 | } | 1393 | } |
@@ -1293,11 +1404,8 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) | |||
1293 | if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) { | 1404 | if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) { |
1294 | if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo)) | 1405 | if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo)) |
1295 | err = -EINVAL; | 1406 | err = -EINVAL; |
1296 | else { | 1407 | else |
1297 | xfrm_state_afinfo[afinfo->family] = NULL; | 1408 | xfrm_state_afinfo[afinfo->family] = NULL; |
1298 | afinfo->state_byspi = NULL; | ||
1299 | afinfo->state_bysrc = NULL; | ||
1300 | } | ||
1301 | } | 1409 | } |
1302 | write_unlock_bh(&xfrm_state_afinfo_lock); | 1410 | write_unlock_bh(&xfrm_state_afinfo_lock); |
1303 | return err; | 1411 | return err; |