summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2004-05-03 03:29:21 +0000
committersam <sam@FreeBSD.org>2004-05-03 03:29:21 +0000
commit7f15aed8bdb45ef1c1d7835c4ac1e7c89a9f2570 (patch)
treef94d96f2b199e9ad548c18772d1bd8eb4a54710b
parentcc0587e38236cc0442cfc73c97cfd25ce763400d (diff)
downloadFreeBSD-src-7f15aed8bdb45ef1c1d7835c4ac1e7c89a9f2570.zip
FreeBSD-src-7f15aed8bdb45ef1c1d7835c4ac1e7c89a9f2570.tar.gz
add support to prefer old SA to new SA during allocation
(makes net.key.preferred_oldsa work as for KAME) Submitted by: gabor@sentex.net Reviewed by: Bjoern A. Zeeb MFC after: 1 day
-rw-r--r--sys/netipsec/key.c45
1 files changed, 27 insertions, 18 deletions
diff --git a/sys/netipsec/key.c b/sys/netipsec/key.c
index fa43445..bced4e1 100644
--- a/sys/netipsec/key.c
+++ b/sys/netipsec/key.c
@@ -173,12 +173,11 @@ static struct mtx spacq_lock;
#define SPACQ_LOCK_ASSERT() mtx_assert(&spacq_lock, MA_OWNED)
/* search order for SAs */
-static u_int saorder_state_valid[] = {
+static const u_int saorder_state_valid_prefer_old[] = {
SADB_SASTATE_DYING, SADB_SASTATE_MATURE,
- /*
- * This order is important because we must select the oldest SA
- * for outbound processing. For inbound, This is not important.
- */
+};
+static const u_int saorder_state_valid_prefer_new[] = {
+ SADB_SASTATE_MATURE, SADB_SASTATE_DYING,
};
static u_int saorder_state_alive[] = {
/* except DEAD */
@@ -821,15 +820,24 @@ key_checkrequest(struct ipsecrequest *isr, const struct secasindex *saidx)
static struct secasvar *
key_allocsa_policy(const struct secasindex *saidx)
{
+#define N(a) _ARRAYLEN(a)
struct secashead *sah;
struct secasvar *sav;
- u_int stateidx, state;
+ u_int stateidx, arraysize;
+ const u_int *state_valid;
SAHTREE_LOCK();
LIST_FOREACH(sah, &sahtree, chain) {
if (sah->state == SADB_SASTATE_DEAD)
continue;
if (key_cmpsaidx(&sah->saidx, saidx, CMP_MODE_REQID)) {
+ if (key_preferred_oldsa) {
+ state_valid = saorder_state_valid_prefer_old;
+ arraysize = N(saorder_state_valid_prefer_old);
+ } else {
+ state_valid = saorder_state_valid_prefer_new;
+ arraysize = N(saorder_state_valid_prefer_new);
+ }
SAHTREE_UNLOCK();
goto found;
}
@@ -839,20 +847,15 @@ key_allocsa_policy(const struct secasindex *saidx)
return NULL;
found:
-
/* search valid state */
- for (stateidx = 0;
- stateidx < _ARRAYLEN(saorder_state_valid);
- stateidx++) {
-
- state = saorder_state_valid[stateidx];
-
- sav = key_do_allocsa_policy(sah, state);
+ for (stateidx = 0; stateidx < arraysize; stateidx++) {
+ sav = key_do_allocsa_policy(sah, state_valid[stateidx]);
if (sav != NULL)
return sav;
}
return NULL;
+#undef N
}
/*
@@ -1012,7 +1015,8 @@ key_allocsa(
{
struct secashead *sah;
struct secasvar *sav;
- u_int stateidx, state;
+ u_int stateidx, arraysize, state;
+ const u_int *saorder_state_valid;
IPSEC_ASSERT(dst != NULL, ("null dst address"));
@@ -1026,11 +1030,16 @@ key_allocsa(
* encrypted so we can't check internal IP header.
*/
SAHTREE_LOCK();
+ if (key_preferred_oldsa) {
+ saorder_state_valid = saorder_state_valid_prefer_old;
+ arraysize = _ARRAYLEN(saorder_state_valid_prefer_old);
+ } else {
+ saorder_state_valid = saorder_state_valid_prefer_new;
+ arraysize = _ARRAYLEN(saorder_state_valid_prefer_new);
+ }
LIST_FOREACH(sah, &sahtree, chain) {
/* search valid state */
- for (stateidx = 0;
- stateidx < _ARRAYLEN(saorder_state_valid);
- stateidx++) {
+ for (stateidx = 0; stateidx < arraysize; stateidx++) {
state = saorder_state_valid[stateidx];
LIST_FOREACH(sav, &sah->savtree[state], chain) {
/* sanity check */
OpenPOWER on IntegriCloud