Hi,

here is an update of the last diff rebased onto current with minor fixes. There
were some problems when multiple transport and non-transport policies were
configured, which should now be fixed.
I also have a test case for the new regression test which runs successfully.

ok?

diff --git a/sbin/iked/iked.conf.5 b/sbin/iked/iked.conf.5
index 671cb5c7955..5af0a2e6d63 100644
--- a/sbin/iked/iked.conf.5
+++ b/sbin/iked/iked.conf.5
@@ -271,6 +271,15 @@ The optional compression is applied before packets are 
encapsulated.
 IPcomp must be enabled in the kernel:
 .Pp
 .Dl # sysctl net.inet.ipcomp.enable=1
+.It Op Ar tmode
+.Ar tmode
+describes the encapsulation mode to be used.
+Possible modes are
+.Ar tunnel
+and
+.Ar transport ;
+the default is
+.Ar tunnel .
 .It Op Ar encap
 .Ar encap
 specifies the encapsulation protocol to be used.
@@ -280,15 +289,6 @@ and
 .Ar ah ;
 the default is
 .Ar esp .
-.\" .It Op Ar tmode
-.\" .Ar tmode
-.\" describes the encapsulation mode to be used.
-.\" Possible modes are
-.\" .Ar tunnel
-.\" and
-.\" .Ar transport ;
-.\" the default is
-.\" .Ar tunnel .
 .It Op Ar af
 This policy only applies to endpoints of the specified address family
 which can be either
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
index d99d52ff77c..7b4c2075810 100644
--- a/sbin/iked/iked.h
+++ b/sbin/iked/iked.h
@@ -254,6 +254,7 @@ struct iked_policy {
 #define IKED_POLICY_QUICK               0x08
 #define IKED_POLICY_SKIP                0x10
 #define IKED_POLICY_IPCOMP              0x20
+#define IKED_POLICY_TRANSPORT           0x40
 
        int                              pol_refcnt;
 
@@ -481,6 +482,9 @@ struct iked_sa {
        int                              sa_mobike;     /* MOBIKE */
        int                              sa_frag;       /* fragmentation */
 
+       int                              sa_use_transport_mode; /* peer 
requested */
+       int                              sa_used_transport_mode; /* we enabled 
*/
+
        struct iked_timer                sa_timer;      /* SA timeouts */
 #define IKED_IKE_SA_EXCHANGE_TIMEOUT    300            /* 5 minutes */
 #define IKED_IKE_SA_REKEY_TIMEOUT       120            /* 2 minutes */
diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c
index 842e8da110f..505cd31a204 100644
--- a/sbin/iked/ikev2.c
+++ b/sbin/iked/ikev2.c
@@ -142,15 +142,17 @@ int        ikev2_cp_setaddr(struct iked *, struct iked_sa 
*, sa_family_t);
 int     ikev2_cp_fixaddr(struct iked_sa *, struct iked_addr *,
            struct iked_addr *);
 
-ssize_t        ikev2_add_sighashnotify(struct ibuf *, struct ikev2_payload **,
+ssize_t         ikev2_add_sighashnotify(struct ibuf *, struct ikev2_payload **,
            ssize_t);
-ssize_t ikev2_add_nat_detection(struct iked *, struct ibuf *,
+ssize_t         ikev2_add_nat_detection(struct iked *, struct ibuf *,
            struct ikev2_payload **, struct iked_message *, ssize_t);
 ssize_t         ikev2_add_notify(struct ibuf *, struct ikev2_payload **, 
ssize_t,
-    uint16_t);
+           uint16_t);
 ssize_t         ikev2_add_mobike(struct ibuf *, struct ikev2_payload **, 
ssize_t);
-ssize_t ikev2_add_fragmentation(struct ibuf *, struct ikev2_payload **,
-    struct iked_message *, ssize_t);
+ssize_t         ikev2_add_fragmentation(struct ibuf *, struct ikev2_payload **,
+           struct iked_message *, ssize_t);
+ssize_t         ikev2_add_transport_mode(struct iked *, struct ibuf *,
+           struct ikev2_payload **, ssize_t, struct iked_sa *);
 int     ikev2_update_sa_addresses(struct iked *, struct iked_sa *);
 int     ikev2_resp_informational(struct iked *, struct iked_sa *,
            struct iked_message *);
@@ -1246,10 +1248,13 @@ ikev2_init_ike_auth(struct iked *env, struct iked_sa 
*sa)
                        goto done;
        }
 
-       /* compression */
+       /* compression, transport mode */
        if ((pol->pol_flags & IKED_POLICY_IPCOMP) &&
            (len = ikev2_add_ipcompnotify(env, e, &pld, len, sa, 1)) == -1)
                goto done;
+       if ((pol->pol_flags & IKED_POLICY_TRANSPORT) &&
+           (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1)
+               goto done;
 
        if (ikev2_next_payload(pld, len, IKEV2_PAYLOAD_SA) == -1)
                goto done;
@@ -1786,6 +1791,13 @@ ikev2_add_sighashnotify(struct ibuf *e, struct 
ikev2_payload **pld,
        return (len);
 }
 
+ssize_t
+ikev2_add_transport_mode(struct iked *env, struct ibuf *e,
+    struct ikev2_payload **pld, ssize_t len, struct iked_sa *sa)
+{
+       return ikev2_add_notify(e, pld, len, IKEV2_N_USE_TRANSPORT_MODE);
+}
+
 int
 ikev2_next_payload(struct ikev2_payload *pld, size_t length,
     uint8_t nextpayload)
@@ -2990,10 +3002,13 @@ ikev2_resp_ike_auth(struct iked *env, struct iked_sa 
*sa)
                        goto done;
        }
 
-       /* compression */
+       /* compression, transport mode */
        if (sa->sa_ipcompr.ic_transform &&
            (len = ikev2_add_ipcompnotify(env, e, &pld, len, sa, 0)) == -1)
                goto done;
+       if (sa->sa_used_transport_mode &&
+           (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1)
+               goto done;
 
        /* MOBIKE */
        if (sa->sa_mobike &&
@@ -3233,10 +3248,13 @@ ikev2_send_create_child_sa(struct iked *env, struct 
iked_sa *sa,
        if ((e = ibuf_static()) == NULL)
                goto done;
 
-       /* compression */
+       /* compression, transport mode */
        if ((pol->pol_flags & IKED_POLICY_IPCOMP) &&
            (len = ikev2_add_ipcompnotify(env, e, &pld, 0, sa, 1)) == -1)
                goto done;
+       if ((pol->pol_flags & IKED_POLICY_TRANSPORT) &&
+           (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1)
+               goto done;
 
        if (pld) {
                firstpayload = IKEV2_PAYLOAD_NOTIFY;
@@ -4055,10 +4073,13 @@ ikev2_resp_create_child_sa(struct iked *env, struct 
iked_message *msg)
        if ((e = ibuf_static()) == NULL)
                goto done;
 
-       /* compression (unless IKE rekeying) */
+       /* compression, transport mode (unless IKE rekeying) */
        if (!nsa && sa->sa_ipcompr.ic_transform &&
            (len = ikev2_add_ipcompnotify(env, e, &pld, 0, sa, 0)) == -1)
                goto done;
+       if (!nsa && sa->sa_used_transport_mode &&
+           (len = ikev2_add_transport_mode(env, e, &pld, len, sa)) == -1)
+               goto done;
 
        if (pld) {
                firstpayload = IKEV2_PAYLOAD_NOTIFY;
@@ -5320,6 +5341,9 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa 
*sa,
            (initiator && ic->ic_cpi_in == 0))
                ic = NULL;
 
+       /* reset state */
+       sa->sa_used_transport_mode = 0;
+
        /* We need to determine the key material length first */
        TAILQ_FOREACH(prop, proposals, prop_entry) {
                if (prop->prop_protoid == IKEV2_SAPROTO_IKE)
@@ -5460,6 +5484,8 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa 
*sa,
                csa->csa_spi.spi_protoid = prop->prop_protoid;
                csa->csa_esn = esn;
                csa->csa_acquired = acquired;
+               csa->csa_transport = sa->sa_use_transport_mode;
+               sa->sa_used_transport_mode = sa->sa_use_transport_mode;
 
                /* Set up responder's SPIs */
                if (initiator) {
@@ -5597,6 +5623,7 @@ ikev2_childsa_negotiate(struct iked *env, struct iked_sa 
*sa,
 
        ret = 0;
  done:
+       sa->sa_use_transport_mode = 0;          /* reset state after use */
        ibuf_release(dhsecret);
        ibuf_release(keymat);
        ibuf_release(seed);
diff --git a/sbin/iked/ikev2_pld.c b/sbin/iked/ikev2_pld.c
index 5cf0dee6615..c13a7e11158 100644
--- a/sbin/iked/ikev2_pld.c
+++ b/sbin/iked/ikev2_pld.c
@@ -1172,6 +1172,24 @@ ikev2_pld_notify(struct iked *env, struct ikev2_payload 
*pld,
                }
                msg->msg_parent->msg_flags |= IKED_MSG_FLAGS_MOBIKE;
                break;
+       case IKEV2_N_USE_TRANSPORT_MODE:
+               if (!msg->msg_e) {
+                       log_debug("%s: N_USE_TRANSPORT_MODE not encrypted",
+                           __func__);
+                       return (-1);
+               }
+               if (len != 0) {
+                       log_debug("%s: ignoring malformed transport mode"
+                           " notification: %zu", __func__, len);
+                       return (0);
+               }
+               if (!(msg->msg_policy->pol_flags & IKED_POLICY_TRANSPORT)) {
+                       log_debug("%s: ignoring transport mode"
+                           " notification (policy)", __func__);
+                       return (0);
+               }
+               msg->msg_sa->sa_use_transport_mode = 1;
+               break;
        case IKEV2_N_UPDATE_SA_ADDRESSES:
                if (!msg->msg_e) {
                        log_debug("%s: N_UPDATE_SA_ADDRESSES not encrypted",
diff --git a/sbin/iked/parse.y b/sbin/iked/parse.y
index fe052068922..3ca68e2fd7a 100644
--- a/sbin/iked/parse.y
+++ b/sbin/iked/parse.y
@@ -426,7 +426,7 @@ typedef struct {
 %type  <v.id>                  id
 %type  <v.transforms>          transforms
 %type  <v.filters>             filters
-%type  <v.ikemode>             ikeflags ikematch ikemode ipcomp
+%type  <v.ikemode>             ikeflags ikematch ikemode ipcomp tmode
 %type  <v.ikeauth>             ikeauth
 %type  <v.ikekey>              keyspec
 %type  <v.mode>                ike_sas child_sas
@@ -890,7 +890,7 @@ child_sa    : CHILDSA       {
                }
                ;
 
-ikeflags       : ikematch ikemode ipcomp       { $$ = $1 | $2 | $3; }
+ikeflags       : ikematch ikemode ipcomp tmode { $$ = $1 | $2 | $3 | $4; }
                ;
 
 ikematch       : /* empty */                   { $$ = 0; }
@@ -908,6 +908,11 @@ ipcomp             : /* empty */                   { $$ = 
0; }
                | IPCOMP                        { $$ = IKED_POLICY_IPCOMP; }
                ;
 
+tmode          : /* empty */                   { $$ = 0; }
+               | TUNNEL                        { $$ = 0; }
+               | TRANSPORT                     { $$ = IKED_POLICY_TRANSPORT; }
+               ;
+
 ikeauth                : /* empty */                   {
                        $$.auth_method = IKEV2_AUTH_SIG_ANY;    /* default */
                        $$.auth_eap = 0;
@@ -2465,6 +2470,9 @@ print_policy(struct iked_policy *pol)
        else
                print_verbose(" passive");
 
+       if (pol->pol_flags & IKED_POLICY_TRANSPORT)
+               print_verbose(" transport");
+
        print_verbose(" %s", print_xf(pol->pol_saproto, 0, saxfs));
 
        if (pol->pol_ipproto)

Reply via email to