Index: sys/net/pfkeyv2.h =================================================================== --- sys/net/pfkeyv2.h +++ sys/net/pfkeyv2.h @@ -225,7 +225,7 @@ u_int8_t sadb_x_policy_dir; /* direction, see ipsec.h */ u_int8_t sadb_x_policy_reserved; u_int32_t sadb_x_policy_id; - u_int32_t sadb_x_policy_reserved2; + u_int32_t sadb_x_policy_priority; }; _Static_assert(sizeof(struct sadb_x_policy) == 16, "struct size mismatch"); Index: sys/netipsec/ipsec.h =================================================================== --- sys/netipsec/ipsec.h +++ sys/netipsec/ipsec.h @@ -92,6 +92,7 @@ u_int state; #define IPSEC_SPSTATE_DEAD 0 #define IPSEC_SPSTATE_ALIVE 1 + u_int32_t priority; /* priority of this policy */ u_int32_t id; /* It's unique number on the system. */ /* * lifetime handler. Index: sys/netipsec/key.c =================================================================== --- sys/netipsec/key.c +++ sys/netipsec/key.c @@ -1209,6 +1209,29 @@ } /* + * insert a secpolicy into the SP database. Lower priorities first + */ +static void +key_insertsp(struct secpolicy *newsp) +{ + struct secpolicy *sp; + + SPTREE_WLOCK(); + TAILQ_FOREACH(sp, &V_sptree[newsp->spidx.dir], chain) { + if (newsp->priority < sp->priority) { + TAILQ_INSERT_BEFORE(sp, newsp, chain); + goto done; + } + } + + TAILQ_INSERT_TAIL(&V_sptree[newsp->spidx.dir], newsp, chain); + +done: + newsp->state = IPSEC_SPSTATE_ALIVE; + SPTREE_WUNLOCK(); +} + +/* * Must be called after calling key_allocsp(). * For the packet with socket. */ @@ -1391,6 +1414,7 @@ newsp->spidx.dir = xpl0->sadb_x_policy_dir; newsp->policy = xpl0->sadb_x_policy_type; + newsp->priority = xpl0->sadb_x_policy_priority; /* check policy */ switch (xpl0->sadb_x_policy_type) { @@ -1627,6 +1651,7 @@ xpl->sadb_x_policy_type = sp->policy; xpl->sadb_x_policy_dir = sp->spidx.dir; xpl->sadb_x_policy_id = sp->id; + xpl->sadb_x_policy_priority = sp->priority; p = (caddr_t)xpl + sizeof(*xpl); /* if is the policy for ipsec ? */ @@ -1904,10 +1929,7 @@ newsp->lifetime = lft ? lft->sadb_lifetime_addtime : 0; newsp->validtime = lft ? lft->sadb_lifetime_usetime : 0; - SPTREE_WLOCK(); - TAILQ_INSERT_TAIL(&V_sptree[newsp->spidx.dir], newsp, chain); - newsp->state = IPSEC_SPSTATE_ALIVE; - SPTREE_WUNLOCK(); + key_insertsp(newsp); /* delete the entry in spacqtree */ if (mhp->msg->sadb_msg_type == SADB_X_SPDUPDATE) {