aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMasahide NAKAMURA <nakam@linux-ipv6.org>2006-08-23 20:53:57 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-09-22 18:06:34 -0400
commit6c44e6b7ab500d7e3e3f406c83325671be51a752 (patch)
treed68b6347f4e437cd4aac9444ed9ee323f73eb06c
parent622dc8281a80374873686514e46f852093d91106 (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.h26
-rw-r--r--net/ipv4/xfrm4_state.c3
-rw-r--r--net/ipv6/xfrm6_state.c3
-rw-r--r--net/xfrm/xfrm_state.c21
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);
236struct xfrm_state_afinfo { 237struct 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
423static __inline__ 425static __inline__
426unsigned __xfrm4_src_hash(xfrm_address_t *addr)
427{
428 return __xfrm4_dst_hash(addr);
429}
430
431static __inline__
432unsigned __xfrm6_src_hash(xfrm_address_t *addr)
433{
434 return __xfrm6_dst_hash(addr);
435}
436
437static __inline__
438unsigned 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
449static __inline__
424unsigned __xfrm4_spi_hash(xfrm_address_t *addr, u32 spi, u8 proto) 450unsigned __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 */
47static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE]; 47static struct list_head xfrm_state_bydst[XFRM_DST_HSIZE];
48static struct list_head xfrm_state_bysrc[XFRM_DST_HSIZE];
48static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE]; 49static struct list_head xfrm_state_byspi[XFRM_DST_HSIZE];
49 50
50DECLARE_WAIT_QUEUE_HEAD(km_waitq); 51DECLARE_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);