diff options
author | Masahide NAKAMURA <nakam@linux-ipv6.org> | 2006-08-23 20:53:57 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-09-22 18:06:34 -0400 |
commit | 6c44e6b7ab500d7e3e3f406c83325671be51a752 (patch) | |
tree | d68b6347f4e437cd4aac9444ed9ee323f73eb06c | |
parent | 622dc8281a80374873686514e46f852093d91106 (diff) |
[XFRM] STATE: Add source address list.
Support source address based searching.
Mobile IPv6 will use it.
Based on MIPL2 kernel patch.
Signed-off-by: Masahide NAKAMURA <nakam@linux-ipv6.org>
Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/xfrm.h | 26 | ||||
-rw-r--r-- | net/ipv4/xfrm4_state.c | 3 | ||||
-rw-r--r-- | net/ipv6/xfrm6_state.c | 3 | ||||
-rw-r--r-- | net/xfrm/xfrm_state.c | 21 |
4 files changed, 51 insertions, 2 deletions
diff --git a/include/net/xfrm.h b/include/net/xfrm.h index aa3be68041be..88145e3348d0 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h | |||
@@ -95,6 +95,7 @@ struct xfrm_state | |||
95 | { | 95 | { |
96 | /* Note: bydst is re-used during gc */ | 96 | /* Note: bydst is re-used during gc */ |
97 | struct list_head bydst; | 97 | struct list_head bydst; |
98 | struct list_head bysrc; | ||
98 | struct list_head byspi; | 99 | struct list_head byspi; |
99 | 100 | ||
100 | atomic_t refcnt; | 101 | atomic_t refcnt; |
@@ -236,6 +237,7 @@ extern int __xfrm_state_delete(struct xfrm_state *x); | |||
236 | struct xfrm_state_afinfo { | 237 | struct xfrm_state_afinfo { |
237 | unsigned short family; | 238 | unsigned short family; |
238 | struct list_head *state_bydst; | 239 | struct list_head *state_bydst; |
240 | struct list_head *state_bysrc; | ||
239 | struct list_head *state_byspi; | 241 | struct list_head *state_byspi; |
240 | int (*init_flags)(struct xfrm_state *x); | 242 | int (*init_flags)(struct xfrm_state *x); |
241 | void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, | 243 | void (*init_tempsel)(struct xfrm_state *x, struct flowi *fl, |
@@ -421,6 +423,30 @@ unsigned xfrm_dst_hash(xfrm_address_t *addr, unsigned short family) | |||
421 | } | 423 | } |
422 | 424 | ||
423 | static __inline__ | 425 | static __inline__ |
426 | unsigned __xfrm4_src_hash(xfrm_address_t *addr) | ||
427 | { | ||
428 | return __xfrm4_dst_hash(addr); | ||
429 | } | ||
430 | |||
431 | static __inline__ | ||
432 | unsigned __xfrm6_src_hash(xfrm_address_t *addr) | ||
433 | { | ||
434 | return __xfrm6_dst_hash(addr); | ||
435 | } | ||
436 | |||
437 | static __inline__ | ||
438 | unsigned xfrm_src_hash(xfrm_address_t *addr, unsigned short family) | ||
439 | { | ||
440 | switch (family) { | ||
441 | case AF_INET: | ||
442 | return __xfrm4_src_hash(addr); | ||
443 | case AF_INET6: | ||
444 | return __xfrm6_src_hash(addr); | ||
445 | } | ||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | static __inline__ | ||
424 | unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) | 450 | unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) |
425 | { | 451 | { |
426 | unsigned h; | 452 | unsigned h; |
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 97b0c7589711..c56b258fad73 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
@@ -122,6 +122,9 @@ __xfrm4_find_acq(u8 mode, u32 reqid, u8 proto, | |||
122 | add_timer(&x0->timer); | 122 | add_timer(&x0->timer); |
123 | xfrm_state_hold(x0); | 123 | xfrm_state_hold(x0); |
124 | list_add_tail(&x0->bydst, xfrm4_state_afinfo.state_bydst+h); | 124 | list_add_tail(&x0->bydst, xfrm4_state_afinfo.state_bydst+h); |
125 | h = __xfrm4_src_hash(saddr); | ||
126 | xfrm_state_hold(x0); | ||
127 | list_add_tail(&x0->bysrc, xfrm4_state_afinfo.state_bysrc+h); | ||
125 | wake_up(&km_waitq); | 128 | wake_up(&km_waitq); |
126 | } | 129 | } |
127 | if (x0) | 130 | if (x0) |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index a1a1f5476442..2fb07850449f 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -126,6 +126,9 @@ __xfrm6_find_acq(u8 mode, u32 reqid, u8 proto, | |||
126 | add_timer(&x0->timer); | 126 | add_timer(&x0->timer); |
127 | xfrm_state_hold(x0); | 127 | xfrm_state_hold(x0); |
128 | list_add_tail(&x0->bydst, xfrm6_state_afinfo.state_bydst+h); | 128 | list_add_tail(&x0->bydst, xfrm6_state_afinfo.state_bydst+h); |
129 | h = __xfrm6_src_hash(saddr); | ||
130 | xfrm_state_hold(x0); | ||
131 | list_add_tail(&x0->bysrc, xfrm6_state_afinfo.state_bysrc+h); | ||
129 | wake_up(&km_waitq); | 132 | wake_up(&km_waitq); |
130 | } | 133 | } |
131 | if (x0) | 134 | if (x0) |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 34c038cbdf46..2a9992894e69 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -45,6 +45,7 @@ static DEFINE_SPINLOCK(xfrm_state_lock); | |||
45 | * Also, it can be used by ah/esp icmp error handler to find offending SA. | 45 | * Also, it can be used by ah/esp icmp error handler to find offending SA. |
46 | */ | 46 | */ |
47 | static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE]; | 47 | 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_byspi[XFRM_DST_HSIZE]; | 49 | static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; |
49 | 50 | ||
50 | DECLARE_WAIT_QUEUE_HEAD(km_waitq); | 51 | DECLARE_WAIT_QUEUE_HEAD(km_waitq); |
@@ -200,6 +201,7 @@ struct xfrm_state *xfrm_state_alloc(void) | |||
200 | atomic_set(&x->refcnt, 1); | 201 | atomic_set(&x->refcnt, 1); |
201 | atomic_set(&x->tunnel_users, 0); | 202 | atomic_set(&x->tunnel_users, 0); |
202 | INIT_LIST_HEAD(&x->bydst); | 203 | INIT_LIST_HEAD(&x->bydst); |
204 | INIT_LIST_HEAD(&x->bysrc); | ||
203 | INIT_LIST_HEAD(&x->byspi); | 205 | INIT_LIST_HEAD(&x->byspi); |
204 | init_timer(&x->timer); | 206 | init_timer(&x->timer); |
205 | x->timer.function = xfrm_timer_handler; | 207 | x->timer.function = xfrm_timer_handler; |
@@ -240,6 +242,8 @@ int __xfrm_state_delete(struct xfrm_state *x) | |||
240 | spin_lock(&xfrm_state_lock); | 242 | spin_lock(&xfrm_state_lock); |
241 | list_del(&x->bydst); | 243 | list_del(&x->bydst); |
242 | __xfrm_state_put(x); | 244 | __xfrm_state_put(x); |
245 | list_del(&x->bysrc); | ||
246 | __xfrm_state_put(x); | ||
243 | if (x->id.spi) { | 247 | if (x->id.spi) { |
244 | list_del(&x->byspi); | 248 | list_del(&x->byspi); |
245 | __xfrm_state_put(x); | 249 | __xfrm_state_put(x); |
@@ -415,6 +419,8 @@ xfrm_state_find(xfrm_address_t *daddr, xfrm_address_t *saddr, | |||
415 | x->km.state = XFRM_STATE_ACQ; | 419 | x->km.state = XFRM_STATE_ACQ; |
416 | list_add_tail(&x->bydst, xfrm_state_bydst+h); | 420 | list_add_tail(&x->bydst, xfrm_state_bydst+h); |
417 | xfrm_state_hold(x); | 421 | xfrm_state_hold(x); |
422 | list_add_tail(&x->bysrc, xfrm_state_bysrc+h); | ||
423 | xfrm_state_hold(x); | ||
418 | if (x->id.spi) { | 424 | if (x->id.spi) { |
419 | h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); | 425 | h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, family); |
420 | list_add(&x->byspi, xfrm_state_byspi+h); | 426 | list_add(&x->byspi, xfrm_state_byspi+h); |
@@ -448,11 +454,19 @@ static void __xfrm_state_insert(struct xfrm_state *x) | |||
448 | list_add(&x->bydst, xfrm_state_bydst+h); | 454 | list_add(&x->bydst, xfrm_state_bydst+h); |
449 | xfrm_state_hold(x); | 455 | xfrm_state_hold(x); |
450 | 456 | ||
451 | h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, x->props.family); | 457 | h = xfrm_src_hash(&x->props.saddr, x->props.family); |
452 | 458 | ||
453 | list_add(&x->byspi, xfrm_state_byspi+h); | 459 | list_add(&x->bysrc, xfrm_state_bysrc+h); |
454 | xfrm_state_hold(x); | 460 | xfrm_state_hold(x); |
455 | 461 | ||
462 | if (xfrm_id_proto_match(x->id.proto, IPSEC_PROTO_ANY)) { | ||
463 | h = xfrm_spi_hash(&x->id.daddr, x->id.spi, x->id.proto, | ||
464 | x->props.family); | ||
465 | |||
466 | list_add(&x->byspi, xfrm_state_byspi+h); | ||
467 | xfrm_state_hold(x); | ||
468 | } | ||
469 | |||
456 | if (!mod_timer(&x->timer, jiffies + HZ)) | 470 | if (!mod_timer(&x->timer, jiffies + HZ)) |
457 | xfrm_state_hold(x); | 471 | xfrm_state_hold(x); |
458 | 472 | ||
@@ -1075,6 +1089,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo) | |||
1075 | err = -ENOBUFS; | 1089 | err = -ENOBUFS; |
1076 | else { | 1090 | else { |
1077 | afinfo->state_bydst = xfrm_state_bydst; | 1091 | afinfo->state_bydst = xfrm_state_bydst; |
1092 | afinfo->state_bysrc = xfrm_state_bysrc; | ||
1078 | afinfo->state_byspi = xfrm_state_byspi; | 1093 | afinfo->state_byspi = xfrm_state_byspi; |
1079 | xfrm_state_afinfo[afinfo->family] = afinfo; | 1094 | xfrm_state_afinfo[afinfo->family] = afinfo; |
1080 | } | 1095 | } |
@@ -1097,6 +1112,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) | |||
1097 | else { | 1112 | else { |
1098 | xfrm_state_afinfo[afinfo->family] = NULL; | 1113 | xfrm_state_afinfo[afinfo->family] = NULL; |
1099 | afinfo->state_byspi = NULL; | 1114 | afinfo->state_byspi = NULL; |
1115 | afinfo->state_bysrc = NULL; | ||
1100 | afinfo->state_bydst = NULL; | 1116 | afinfo->state_bydst = NULL; |
1101 | } | 1117 | } |
1102 | } | 1118 | } |
@@ -1218,6 +1234,7 @@ void __init xfrm_state_init(void) | |||
1218 | 1234 | ||
1219 | for (i=0; i<XFRM_DST_HSIZE; i++) { | 1235 | for (i=0; i<XFRM_DST_HSIZE; i++) { |
1220 | INIT_LIST_HEAD(&xfrm_state_bydst[i]); | 1236 | INIT_LIST_HEAD(&xfrm_state_bydst[i]); |
1237 | INIT_LIST_HEAD(&xfrm_state_bysrc[i]); | ||
1221 | INIT_LIST_HEAD(&xfrm_state_byspi[i]); | 1238 | INIT_LIST_HEAD(&xfrm_state_byspi[i]); |
1222 | } | 1239 | } |
1223 | INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL); | 1240 | INIT_WORK(&xfrm_state_gc_work, xfrm_state_gc_task, NULL); |