diff options
Diffstat (limited to 'net/xfrm/xfrm_state.c')
-rw-r--r-- | net/xfrm/xfrm_state.c | 21 |
1 files changed, 19 insertions, 2 deletions
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); |