FAST_IPSEC doesn't seem to honor net.key.prefered_oldsa=0

Gabor gabor at vmunix.com
Thu Sep 11 11:32:07 PDT 2003


When using the FAST_IPSEC option in the kernel build, the sysctl
variable net.key.prefered_oldsa seems to make no difference.  The
kernel always chooses an old SA.  This problem can be easily
reproduced. Just wait till the soft limit of the SA is expired and do
a setkey -F on the remote and then ping through the tunnel.  Because
the old SA's are preferred and the remote no longer has the old SA's
the server and the remote cannot talk through the tunnel.  Looking
at the source code in netipsec/key.c and comparing it with
netkey/key.c I see the there is some differences that didn't make it
into netipsec/key.c.

Here is a context diff applied to 1.3.2.2 of the changes I made to fix
the problem.

*** /tmp/ipsec.key.c    Thu Sep 11 14:26:07 2003
--- /usr/src/sys/netipsec/key.c Thu Sep 11 14:27:42 2003
***************
*** 1,4 ****
! /*    $FreeBSD: /repoman/r/ncvs/src/sys/netipsec/key.c,v 1.3.2.2 2003/07/01 01:38:13 sam Exp $        */
  /*    $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $   */

  /*
--- 1,4 ----
! /*    $FreeBSD: src/sys/netipsec/key.c,v 1.3.2.2 2003/07/01 01:38:13 sam Exp $*/
  /*    $KAME: key.c,v 1.191 2001/06/27 10:46:49 sakane Exp $   */

  /*
***************
*** 133,138 ****
--- 133,139 ----
  #endif
  static LIST_HEAD(_spacqtree, secspacq) spacqtree;     /* SP acquiring list */

+ #if 0
  /* search order for SAs */
  static u_int saorder_state_valid[] = {
        SADB_SASTATE_DYING, SADB_SASTATE_MATURE,
***************
*** 141,146 ****
--- 142,155 ----
         * for outbound processing.  For inbound, This is not important.
         */
  };
+ #endif
+ static const u_int saorder_state_valid_prefer_old[] = {
+         SADB_SASTATE_DYING, SADB_SASTATE_MATURE,
+ };
+ static const u_int saorder_state_valid_prefer_new[] = {
+         SADB_SASTATE_MATURE, SADB_SASTATE_DYING,
+ };
+
  static u_int saorder_state_alive[] = {
        /* except DEAD */
        SADB_SASTATE_MATURE, SADB_SASTATE_DYING, SADB_SASTATE_LARVAL
***************
*** 816,821 ****
--- 825,832 ----
        struct secashead *sah;
        struct secasvar *sav;
        u_int stateidx, state;
+         const u_int *saorder_state_valid;
+         int arraysize;

        LIST_FOREACH(sah, &sahtree, chain) {
                if (sah->state == SADB_SASTATE_DEAD)
***************
*** 828,836 ****

      found:

        /* search valid state */
        for (stateidx = 0;
!            stateidx < _ARRAYLEN(saorder_state_valid);
             stateidx++) {

                state = saorder_state_valid[stateidx];
--- 839,859 ----

      found:

+         /*
+          * search a valid state list for outbound packet.
+          * This search order is important.
+          */
+         if (key_prefered_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);
+         }
+
        /* search valid state */
        for (stateidx = 0;
!            stateidx < arraysize;
             stateidx++) {

                state = saorder_state_valid[stateidx];
***************
*** 997,1008 ****
--- 1020,1045 ----
        struct secasvar *sav;
        u_int stateidx, state;
        int s;
+         const u_int *saorder_state_valid;
+         int arraysize;

        KASSERT(dst != NULL, ("key_allocsa: null dst address"));

        KEYDEBUG(KEYDEBUG_IPSEC_STAMP,
                printf("DP key_allocsa from %s:%u\n", where, tag));

+         /*
+          * when both systems employ similar strategy to use a SA.
+          * the search order is important even in the inbound case.
+          */
+         if (key_prefered_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);
+         }
+
        /*
         * searching SAD.
         * XXX: to be checked internal IP header somewhere.  Also when
***************
*** 1013,1019 ****
        LIST_FOREACH(sah, &sahtree, chain) {
                /* search valid state */
                for (stateidx = 0;
!                    stateidx < _ARRAYLEN(saorder_state_valid);
                     stateidx++) {
                        state = saorder_state_valid[stateidx];
                        LIST_FOREACH(sav, &sah->savtree[state], chain) {
--- 1050,1056 ----
        LIST_FOREACH(sah, &sahtree, chain) {
                /* search valid state */
                for (stateidx = 0;
!                    stateidx < arraysize;
                     stateidx++) {
                        state = saorder_state_valid[stateidx];
                        LIST_FOREACH(sav, &sah->savtree[state], chain) {



More information about the freebsd-stable mailing list