diff options
-rw-r--r-- | include/net/xfrm.h | 16 | ||||
-rw-r--r-- | net/ipv4/xfrm4_state.c | 53 | ||||
-rw-r--r-- | net/ipv6/xfrm6_state.c | 56 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 110 |
4 files changed, 100 insertions, 135 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index c75b3287d8f8..cc83443f301e 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -243,7 +243,6 @@ 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_bydst; | ||
247 | struct list_head *state_bysrc; | 246 | struct list_head *state_bysrc; |
248 | struct list_head *state_byspi; | 247 | struct list_head *state_byspi; |
249 | int (*init_flags)(struct xfrm_state *x); | 248 | int (*init_flags)(struct xfrm_state *x); |
@@ -252,9 +251,6 @@ struct xfrm_state_afinfo { | |||
252 | xfrm_address_t *daddr, xfrm_address_t *saddr); | 251 | xfrm_address_t *daddr, xfrm_address_t *saddr); |
253 | struct xfrm_state *(*state_lookup)(xfrm_address_t *daddr, u32 spi, u8 proto); | 252 | struct xfrm_state *(*state_lookup)(xfrm_address_t *daddr, u32 spi, u8 proto); |
254 | struct xfrm_state *(*state_lookup_byaddr)(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto); | 253 | struct xfrm_state *(*state_lookup_byaddr)(xfrm_address_t *daddr, xfrm_address_t *saddr, u8 proto); |
255 | struct xfrm_state *(*find_acq)(u8 mode, u32 reqid, u8 proto, | ||
256 | xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
257 | int create); | ||
258 | int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n); | 254 | int (*tmpl_sort)(struct xfrm_tmpl **dst, struct xfrm_tmpl **src, int n); |
259 | int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n); | 255 | int (*state_sort)(struct xfrm_state **dst, struct xfrm_state **src, int n); |
260 | }; | 256 | }; |
@@ -456,18 +452,6 @@ unsigned __xfrm6_dst_hash(xfrm_address_t *addr) | |||
456 | } | 452 | } |
457 | 453 | ||
458 | static __inline__ | 454 | static __inline__ |
459 | unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) | ||
460 | { | ||
461 | switch (family) { | ||
462 | case AF_INET: | ||
463 | return __xfrm4_dst_hash(addr); | ||
464 | case AF_INET6: | ||
465 | return __xfrm6_dst_hash(addr); | ||
466 | } | ||
467 | return 0; | ||
468 | } | ||
469 | |||
470 | static __inline__ | ||
471 | unsigned __xfrm4_src_hash(xfrm_address_t *addr) | 455 | unsigned __xfrm4_src_hash(xfrm_address_t *addr) |
472 | { | 456 | { |
473 | return __xfrm4_dst_hash(addr); | 457 | return __xfrm4_dst_hash(addr); |
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 616be131b4e3..9dc1afc17b6d 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
@@ -88,65 +88,12 @@ __xfrm4_state_lookup_byaddr(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
88 | return NULL; | 88 | return NULL; |
89 | } | 89 | } |
90 | 90 | ||
91 | static struct xfrm_state * | ||
92 | __xfrm4_find_acq(u8 mode, u32 reqid, u8 proto, | ||
93 | xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
94 | int create) | ||
95 | { | ||
96 | struct xfrm_state *x, *x0; | ||
97 | unsigned h = __xfrm4_dst_hash(daddr); | ||
98 | |||
99 | x0 = NULL; | ||
100 | |||
101 | list_for_each_entry(x, xfrm4_state_afinfo.state_bydst+h, bydst) { | ||
102 | if (x->props.family == AF_INET && | ||
103 | daddr->a4 == x->id.daddr.a4 && | ||
104 | mode == x->props.mode && | ||
105 | proto == x->id.proto && | ||
106 | saddr->a4 == x->props.saddr.a4 && | ||
107 | reqid == x->props.reqid && | ||
108 | x->km.state == XFRM_STATE_ACQ && | ||
109 | !x->id.spi) { | ||
110 | x0 = x; | ||
111 | break; | ||
112 | } | ||
113 | } | ||
114 | if (!x0 && create && (x0 = xfrm_state_alloc()) != NULL) { | ||
115 | x0->sel.daddr.a4 = daddr->a4; | ||
116 | x0->sel.saddr.a4 = saddr->a4; | ||
117 | x0->sel.prefixlen_d = 32; | ||
118 | x0->sel.prefixlen_s = 32; | ||
119 | x0->props.saddr.a4 = saddr->a4; | ||
120 | x0->km.state = XFRM_STATE_ACQ; | ||
121 | x0->id.daddr.a4 = daddr->a4; | ||
122 | x0->id.proto = proto; | ||
123 | x0->props.family = AF_INET; | ||
124 | x0->props.mode = mode; | ||
125 | x0->props.reqid = reqid; | ||
126 | x0->props.family = AF_INET; | ||
127 | x0->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES; | ||
128 | xfrm_state_hold(x0); | ||
129 | x0->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; | ||
130 | add_timer(&x0->timer); | ||
131 | xfrm_state_hold(x0); | ||
132 | list_add_tail(&x0->bydst, xfrm4_state_afinfo.state_bydst+h); | ||
133 | h = __xfrm4_src_hash(saddr); | ||
134 | xfrm_state_hold(x0); | ||
135 | list_add_tail(&x0->bysrc, xfrm4_state_afinfo.state_bysrc+h); | ||
136 | wake_up(&km_waitq); | ||
137 | } | ||
138 | if (x0) | ||
139 | xfrm_state_hold(x0); | ||
140 | return x0; | ||
141 | } | ||
142 | |||
143 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { | 91 | static struct xfrm_state_afinfo xfrm4_state_afinfo = { |
144 | .family = AF_INET, | 92 | .family = AF_INET, |
145 | .init_flags = xfrm4_init_flags, | 93 | .init_flags = xfrm4_init_flags, |
146 | .init_tempsel = __xfrm4_init_tempsel, | 94 | .init_tempsel = __xfrm4_init_tempsel, |
147 | .state_lookup = __xfrm4_state_lookup, | 95 | .state_lookup = __xfrm4_state_lookup, |
148 | .state_lookup_byaddr = __xfrm4_state_lookup_byaddr, | 96 | .state_lookup_byaddr = __xfrm4_state_lookup_byaddr, |
149 | .find_acq = __xfrm4_find_acq, | ||
150 | }; | 97 | }; |
151 | 98 | ||
152 | void __init xfrm4_state_init(void) | 99 | void __init xfrm4_state_init(void) |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index 6269584e610e..40fcaab7e028 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -101,61 +101,6 @@ __xfrm6_state_lookup(xfrm_address_t *daddr, u32 spi, u8 proto) | |||
101 | return NULL; | 101 | return NULL; |
102 | } | 102 | } |
103 | 103 | ||
104 | static struct xfrm_state * | ||
105 | __xfrm6_find_acq(u8 mode, u32 reqid, u8 proto, | ||
106 | xfrm_address_t *daddr, xfrm_address_t *saddr, | ||
107 | int create) | ||
108 | { | ||
109 | struct xfrm_state *x, *x0; | ||
110 | unsigned h = __xfrm6_dst_hash(daddr); | ||
111 | |||
112 | x0 = NULL; | ||
113 | |||
114 | list_for_each_entry(x, xfrm6_state_afinfo.state_bydst+h, bydst) { | ||
115 | if (x->props.family == AF_INET6 && | ||
116 | ipv6_addr_equal((struct in6_addr *)daddr, (struct in6_addr *)x->id.daddr.a6) && | ||
117 | mode == x->props.mode && | ||
118 | proto == x->id.proto && | ||
119 | ipv6_addr_equal((struct in6_addr *)saddr, (struct in6_addr *)x->props.saddr.a6) && | ||
120 | reqid == x->props.reqid && | ||
121 | x->km.state == XFRM_STATE_ACQ && | ||
122 | !x->id.spi) { | ||
123 | x0 = x; | ||
124 | break; | ||
125 | } | ||
126 | } | ||
127 | if (!x0 && create && (x0 = xfrm_state_alloc()) != NULL) { | ||
128 | ipv6_addr_copy((struct in6_addr *)x0->sel.daddr.a6, | ||
129 | (struct in6_addr *)daddr); | ||
130 | ipv6_addr_copy((struct in6_addr *)x0->sel.saddr.a6, | ||
131 | (struct in6_addr *)saddr); | ||
132 | x0->sel.prefixlen_d = 128; | ||
133 | x0->sel.prefixlen_s = 128; | ||
134 | ipv6_addr_copy((struct in6_addr *)x0->props.saddr.a6, | ||
135 | (struct in6_addr *)saddr); | ||
136 | x0->km.state = XFRM_STATE_ACQ; | ||
137 | ipv6_addr_copy((struct in6_addr *)x0->id.daddr.a6, | ||
138 | (struct in6_addr *)daddr); | ||
139 | x0->id.proto = proto; | ||
140 | x0->props.family = AF_INET6; | ||
141 | x0->props.mode = mode; | ||
142 | x0->props.reqid = reqid; | ||
143 | x0->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES; | ||
144 | xfrm_state_hold(x0); | ||
145 | x0->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; | ||
146 | add_timer(&x0->timer); | ||
147 | xfrm_state_hold(x0); | ||
148 | list_add_tail(&x0->bydst, xfrm6_state_afinfo.state_bydst+h); | ||
149 | h = __xfrm6_src_hash(saddr); | ||
150 | xfrm_state_hold(x0); | ||
151 | list_add_tail(&x0->bysrc, xfrm6_state_afinfo.state_bysrc+h); | ||
152 | wake_up(&km_waitq); | ||
153 | } | ||
154 | if (x0) | ||
155 | xfrm_state_hold(x0); | ||
156 | return x0; | ||
157 | } | ||
158 | |||
159 | static int | 104 | static int |
160 | __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) | 105 | __xfrm6_state_sort(struct xfrm_state **dst, struct xfrm_state **src, int n) |
161 | { | 106 | { |
@@ -280,7 +225,6 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = { | |||
280 | .init_tempsel = __xfrm6_init_tempsel, | 225 | .init_tempsel = __xfrm6_init_tempsel, |
281 | .state_lookup = __xfrm6_state_lookup, | 226 | .state_lookup = __xfrm6_state_lookup, |
282 | .state_lookup_byaddr = __xfrm6_state_lookup_byaddr, | 227 | .state_lookup_byaddr = __xfrm6_state_lookup_byaddr, |
283 | .find_acq = __xfrm6_find_acq, | ||
284 | .tmpl_sort = __xfrm6_tmpl_sort, | 228 | .tmpl_sort = __xfrm6_tmpl_sort, |
285 | .state_sort = __xfrm6_state_sort, | 229 | .state_sort = __xfrm6_state_sort, |
286 | }; | 230 | }; |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 622e92a08d0b..80f5f9dc2b9e 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -48,6 +48,18 @@ static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE]; | |||
48 | static struct list_head xfrm_state_bysrc[XFRM_DST_HSIZE]; | 48 | static struct list_head xfrm_state_bysrc[XFRM_DST_HSIZE]; |
49 | static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; | 49 | static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; |
50 | 50 | ||
51 | static __inline__ | ||
52 | unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) | ||
53 | { | ||
54 | switch (family) { | ||
55 | case AF_INET: | ||
56 | return __xfrm4_dst_hash(addr); | ||
57 | case AF_INET6: | ||
58 | return __xfrm6_dst_hash(addr); | ||
59 | } | ||
60 | return 0; | ||
61 | } | ||
62 | |||
51 | DECLARE_WAIT_QUEUE_HEAD(km_waitq); | 63 | DECLARE_WAIT_QUEUE_HEAD(km_waitq); |
52 | EXPORT_SYMBOL(km_waitq); | 64 | EXPORT_SYMBOL(km_waitq); |
53 | 65 | ||
@@ -489,6 +501,89 @@ void xfrm_state_insert(struct xfrm_state *x) | |||
489 | } | 501 | } |
490 | EXPORT_SYMBOL(xfrm_state_insert); | 502 | EXPORT_SYMBOL(xfrm_state_insert); |
491 | 503 | ||
504 | /* xfrm_state_lock is held */ | ||
505 | static struct xfrm_state *__find_acq_core(unsigned short family, u8 mode, u32 reqid, u8 proto, xfrm_address_t *daddr, xfrm_address_t *saddr, int create) | ||
506 | { | ||
507 | unsigned int h = xfrm_dst_hash(daddr, family); | ||
508 | struct xfrm_state *x; | ||
509 | |||
510 | list_for_each_entry(x, xfrm_state_bydst+h, bydst) { | ||
511 | if (x->props.reqid != reqid || | ||
512 | x->props.mode != mode || | ||
513 | x->props.family != family || | ||
514 | x->km.state != XFRM_STATE_ACQ || | ||
515 | x->id.spi != 0) | ||
516 | continue; | ||
517 | |||
518 | switch (family) { | ||
519 | case AF_INET: | ||
520 | if (x->id.daddr.a4 != daddr->a4 || | ||
521 | x->props.saddr.a4 != saddr->a4) | ||
522 | continue; | ||
523 | break; | ||
524 | case AF_INET6: | ||
525 | if (!ipv6_addr_equal((struct in6_addr *)x->id.daddr.a6, | ||
526 | (struct in6_addr *)daddr) || | ||
527 | !ipv6_addr_equal((struct in6_addr *) | ||
528 | x->props.saddr.a6, | ||
529 | (struct in6_addr *)saddr)) | ||
530 | continue; | ||
531 | break; | ||
532 | }; | ||
533 | |||
534 | xfrm_state_hold(x); | ||
535 | return x; | ||
536 | } | ||
537 | |||
538 | if (!create) | ||
539 | return NULL; | ||
540 | |||
541 | x = xfrm_state_alloc(); | ||
542 | if (likely(x)) { | ||
543 | switch (family) { | ||
544 | case AF_INET: | ||
545 | x->sel.daddr.a4 = daddr->a4; | ||
546 | x->sel.saddr.a4 = saddr->a4; | ||
547 | x->sel.prefixlen_d = 32; | ||
548 | x->sel.prefixlen_s = 32; | ||
549 | x->props.saddr.a4 = saddr->a4; | ||
550 | x->id.daddr.a4 = daddr->a4; | ||
551 | break; | ||
552 | |||
553 | case AF_INET6: | ||
554 | ipv6_addr_copy((struct in6_addr *)x->sel.daddr.a6, | ||
555 | (struct in6_addr *)daddr); | ||
556 | ipv6_addr_copy((struct in6_addr *)x->sel.saddr.a6, | ||
557 | (struct in6_addr *)saddr); | ||
558 | x->sel.prefixlen_d = 128; | ||
559 | x->sel.prefixlen_s = 128; | ||
560 | ipv6_addr_copy((struct in6_addr *)x->props.saddr.a6, | ||
561 | (struct in6_addr *)saddr); | ||
562 | ipv6_addr_copy((struct in6_addr *)x->id.daddr.a6, | ||
563 | (struct in6_addr *)daddr); | ||
564 | break; | ||
565 | }; | ||
566 | |||
567 | x->km.state = XFRM_STATE_ACQ; | ||
568 | x->id.proto = proto; | ||
569 | x->props.family = family; | ||
570 | x->props.mode = mode; | ||
571 | x->props.reqid = reqid; | ||
572 | x->lft.hard_add_expires_seconds = XFRM_ACQ_EXPIRES; | ||
573 | xfrm_state_hold(x); | ||
574 | x->timer.expires = jiffies + XFRM_ACQ_EXPIRES*HZ; | ||
575 | add_timer(&x->timer); | ||
576 | xfrm_state_hold(x); | ||
577 | list_add_tail(&x->bydst, xfrm_state_bydst+h); | ||
578 | h = xfrm_src_hash(saddr, family); | ||
579 | xfrm_state_hold(x); | ||
580 | list_add_tail(&x->bysrc, xfrm_state_bysrc+h); | ||
581 | wake_up(&km_waitq); | ||
582 | } | ||
583 | |||
584 | return x; | ||
585 | } | ||
586 | |||
492 | static inline struct xfrm_state * | 587 | static inline struct xfrm_state * |
493 | __xfrm_state_locate(struct xfrm_state_afinfo *afinfo, struct xfrm_state *x, | 588 | __xfrm_state_locate(struct xfrm_state_afinfo *afinfo, struct xfrm_state *x, |
494 | int use_spi) | 589 | int use_spi) |
@@ -533,9 +628,9 @@ int xfrm_state_add(struct xfrm_state *x) | |||
533 | } | 628 | } |
534 | 629 | ||
535 | if (use_spi && !x1) | 630 | if (use_spi && !x1) |
536 | x1 = afinfo->find_acq( | 631 | x1 = __find_acq_core(family, x->props.mode, x->props.reqid, |
537 | x->props.mode, x->props.reqid, x->id.proto, | 632 | x->id.proto, |
538 | &x->id.daddr, &x->props.saddr, 0); | 633 | &x->id.daddr, &x->props.saddr, 0); |
539 | 634 | ||
540 | __xfrm_state_insert(x); | 635 | __xfrm_state_insert(x); |
541 | err = 0; | 636 | err = 0; |
@@ -716,14 +811,11 @@ xfrm_find_acq(u8 mode, u32 reqid, u8 proto, | |||
716 | int create, unsigned short family) | 811 | int create, unsigned short family) |
717 | { | 812 | { |
718 | struct xfrm_state *x; | 813 | struct xfrm_state *x; |
719 | struct xfrm_state_afinfo *afinfo = xfrm_state_get_afinfo(family); | ||
720 | if (!afinfo) | ||
721 | return NULL; | ||
722 | 814 | ||
723 | spin_lock_bh(&xfrm_state_lock); | 815 | spin_lock_bh(&xfrm_state_lock); |
724 | x = afinfo->find_acq(mode, reqid, proto, daddr, saddr, create); | 816 | x = __find_acq_core(family, mode, reqid, proto, daddr, saddr, create); |
725 | spin_unlock_bh(&xfrm_state_lock); | 817 | spin_unlock_bh(&xfrm_state_lock); |
726 | xfrm_state_put_afinfo(afinfo); | 818 | |
727 | return x; | 819 | return x; |
728 | } | 820 | } |
729 | EXPORT_SYMBOL(xfrm_find_acq); | 821 | EXPORT_SYMBOL(xfrm_find_acq); |
@@ -1181,7 +1273,6 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo) | |||
1181 | if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) | 1273 | if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) |
1182 | err = -ENOBUFS; | 1274 | err = -ENOBUFS; |
1183 | else { | 1275 | else { |
1184 | afinfo->state_bydst = xfrm_state_bydst; | ||
1185 | afinfo->state_bysrc = xfrm_state_bysrc; | 1276 | afinfo->state_bysrc = xfrm_state_bysrc; |
1186 | afinfo->state_byspi = xfrm_state_byspi; | 1277 | afinfo->state_byspi = xfrm_state_byspi; |
1187 | xfrm_state_afinfo[afinfo->family] = afinfo; | 1278 | xfrm_state_afinfo[afinfo->family] = afinfo; |
@@ -1206,7 +1297,6 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) | |||
1206 | xfrm_state_afinfo[afinfo->family] = NULL; | 1297 | xfrm_state_afinfo[afinfo->family] = NULL; |
1207 | afinfo->state_byspi = NULL; | 1298 | afinfo->state_byspi = NULL; |
1208 | afinfo->state_bysrc = NULL; | 1299 | afinfo->state_bysrc = NULL; |
1209 | afinfo->state_bydst = NULL; | ||
1210 | } | 1300 | } |
1211 | } | 1301 | } |
1212 | write_unlock_bh(&xfrm_state_afinfo_lock); | 1302 | write_unlock_bh(&xfrm_state_afinfo_lock); |