summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/netkey/key.c90
-rw-r--r--sys/netkey/key_var.h6
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
OpenPOWER on IntegriCloud