diff options
-rw-r--r-- | sys/netkey/key.c | 90 | ||||
-rw-r--r-- | sys/netkey/key_var.h | 6 |
2 files changed, 89 insertions, 7 deletions
diff --git a/sys/netkey/key.c b/sys/netkey/key.c index 22b437e..4236081 100644 --- a/sys/netkey/key.c +++ b/sys/netkey/key.c @@ -134,6 +134,7 @@ static u_int key_int_random = 60; /*interval to initialize randseed,1(m)*/ static u_int key_larval_lifetime = 30; /* interval to expire acquiring, 30(s)*/ static int key_blockacq_count = 10; /* counter for blocking SADB_ACQUIRE.*/ static int key_blockacq_lifetime = 20; /* lifetime for blocking SADB_ACQUIRE.*/ +static int key_prefered_oldsa = 1; /* prefered old sa rather than new sa.*/ static u_int32_t acq_seq = 0; static int key_tick_init_random = 0; @@ -262,6 +263,10 @@ SYSCTL_INT(_net_key, KEYCTL_ESP_KEYMIN, esp_keymin, CTLFLAG_RW, \ SYSCTL_INT(_net_key, KEYCTL_AH_KEYMIN, ah_keymin, CTLFLAG_RW, \ &ipsec_ah_keymin, 0, ""); +/* perfered old SA rather than new SA */ +SYSCTL_INT(_net_key, KEYCTL_PREFERED_OLDSA, prefered_oldsa, CTLFLAG_RW,\ + &key_prefered_oldsa, 0, ""); + #ifndef LIST_FOREACH #define LIST_FOREACH(elm, head, field) \ for (elm = LIST_FIRST(head); elm; elm = LIST_NEXT(elm, field)) @@ -769,12 +774,16 @@ key_do_allocsa_policy(sah, state) struct secashead *sah; u_int state; { - struct secasvar *sav, *candidate; + struct secasvar *sav, *nextsav, *candidate, *d; /* initilize */ candidate = NULL; - LIST_FOREACH(sav, &sah->savtree[state], chain) { + for (sav = LIST_FIRST(&sah->savtree[state]); + sav != NULL; + sav = nextsav) { + + nextsav = LIST_NEXT(sav, chain); /* sanity check */ KEY_CHKSASTATE(sav->state, state, "key_do_allocsa_policy"); @@ -792,11 +801,82 @@ key_do_allocsa_policy(sah, state) panic("key_do_allocsa_policy: " "lifetime_current is NULL.\n"); - /* XXX What the best method is to compare ? */ - if (candidate->lft_c->sadb_lifetime_addtime > + /* What the best method is to compare ? */ + if (key_prefered_oldsa) { + if (candidate->lft_c->sadb_lifetime_addtime > + sav->lft_c->sadb_lifetime_addtime) { + candidate = sav; + } + continue; + /*NOTREACHED*/ + } + + /* prefered new sa rather than old sa */ + if (candidate->lft_c->sadb_lifetime_addtime < sav->lft_c->sadb_lifetime_addtime) { + d = candidate; candidate = sav; - continue; + } else + d = sav; + + /* + * prepared to delete the SA when there is more + * suitable candidate and the lifetime of the SA is not + * permanent. + */ + if (d->lft_c->sadb_lifetime_addtime != 0) { + + struct mbuf *m, *result; + + key_sa_chgstate(d, SADB_SASTATE_DEAD); + key_freesav(d); + + m = key_setsadbmsg(SADB_DELETE, 0, + sav->sah->saidx.proto, 0, 0, d->refcnt); + if (!m) + return NULL; + result = m; + + /* set sadb_address for saidx's. */ + m = key_setsadbaddr(SADB_EXT_ADDRESS_SRC, + (struct sockaddr *)&d->sah->saidx.src, + d->sah->saidx.src.ss_len << 3, + IPSEC_ULPROTO_ANY); + if (!m) + return NULL; + m_cat(result, m); + + /* set sadb_address for saidx's. */ + m = key_setsadbaddr(SADB_EXT_ADDRESS_DST, + (struct sockaddr *)&d->sah->saidx.src, + d->sah->saidx.src.ss_len << 3, + IPSEC_ULPROTO_ANY); + if (!m) + return NULL; + m_cat(result, m); + + /* create SA extension */ + m = key_setsadbsa(d); + if (!m) + return NULL; + m_cat(result, m); + + if (result->m_len < sizeof(struct sadb_msg)) { + result = m_pullup(result, + sizeof(struct sadb_msg)); + if (result == NULL) + return NULL; + } + + result->m_pkthdr.len = 0; + for (m = result; m; m = m->m_next) + result->m_pkthdr.len += m->m_len; + mtod(result, struct sadb_msg *)->sadb_msg_len = + PFKEY_UNIT64(result->m_pkthdr.len); + + if (key_sendup_mbuf(NULL, result, + KEY_SENDUP_REGISTERED)) + return NULL; } } diff --git a/sys/netkey/key_var.h b/sys/netkey/key_var.h index 3bd65f9..910fda1 100644 --- a/sys/netkey/key_var.h +++ b/sys/netkey/key_var.h @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $KAME: key_var.h,v 1.10 2001/07/27 04:14:12 itojun Exp $ */ +/* $KAME: key_var.h,v 1.11 2001/09/12 23:05:07 sakane Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. @@ -45,7 +45,8 @@ #define KEYCTL_ESP_KEYMIN 9 #define KEYCTL_ESP_AUTH 10 #define KEYCTL_AH_KEYMIN 11 -#define KEYCTL_MAXID 12 +#define KEYCTL_PREFERED_OLDSA 12 +#define KEYCTL_MAXID 13 #define KEYCTL_NAMES { \ { 0, 0 }, \ @@ -60,6 +61,7 @@ { "esp_keymin", CTLTYPE_INT }, \ { "esp_auth", CTLTYPE_INT }, \ { "ah_keymin", CTLTYPE_INT }, \ + { "prefered_oldsa", CTLTYPE_INT }, \ } #ifdef _KERNEL |