On Mon, Aug 07, 2023 at 02:22:23PM +1000, David Gwynne wrote:
> tobhe@ wrote the iked bits, so he'll commit them when he's ready.
> 
> your config looks pretty much the same as mine except you specify a lot
> more stuff around lifetimes and crypto than i do. maybe try without "tunnel
> esp"?
> 
> dlg

The config in the previous mail looks ok. You will need the "from any to any"
for now but I'm planning to adjust the default.

Below is the latest state of my iked diff. The previous version had a small
bug in pfkey preventing SAs from getting deleted properly. 

diff cfdc039572fed1d8c9081b6d9557ce9b85e89697 
a2b839af1fa9d47730731e392e3c8dd0e9f7dd1e
commit - cfdc039572fed1d8c9081b6d9557ce9b85e89697
commit + a2b839af1fa9d47730731e392e3c8dd0e9f7dd1e
blob - 2c7fbe14af3dad6fe38af607e9f870324e2be55c
blob + 6449f3cc2d423daee6294b71ca098247a296886a
--- sbin/iked/iked.h
+++ sbin/iked/iked.h
@@ -260,6 +260,7 @@ struct iked_policy {
 #define IKED_POLICY_SKIP                0x10
 #define IKED_POLICY_IPCOMP              0x20
 #define IKED_POLICY_TRANSPORT           0x40
+#define IKED_POLICY_ROUTING             0x80
 
        int                              pol_refcnt;
 
blob - bf6bf0fb0d43ef17ebe71368dfbc4bf28628a1f8
blob + 25e5098dd29b03426aa2d9a03c324f13dc8cdecf
--- sbin/iked/ikev2.c
+++ sbin/iked/ikev2.c
@@ -6532,63 +6532,65 @@ ikev2_childsa_enable(struct iked *env, struct iked_sa 
        peer_changed = (memcmp(&sa->sa_peer_loaded, &sa->sa_peer,
            sizeof(sa->sa_peer_loaded)) != 0);
 
-       TAILQ_FOREACH(flow, &sa->sa_flows, flow_entry) {
-               /* re-load the flow if the peer for the flow has changed */
-               reload = 0;
-               if (flow->flow_loaded) {
-                       if (!peer_changed) {
-                               log_debug("%s: flow already loaded %p",
-                                   __func__, flow);
-                               continue;
+       if (!(sa->sa_policy->pol_flags & IKED_POLICY_ROUTING)) {
+               TAILQ_FOREACH(flow, &sa->sa_flows, flow_entry) {
+                       /* re-load the flow if the peer for the flow has 
changed */
+                       reload = 0;
+                       if (flow->flow_loaded) {
+                               if (!peer_changed) {
+                                       log_debug("%s: flow already loaded %p",
+                                           __func__, flow);
+                                       continue;
+                               }
+                               RB_REMOVE(iked_flows, &env->sc_activeflows, 
flow);
+                               (void)pfkey_flow_delete(env, flow);
+                               flow->flow_loaded = 0; /* we did RB_REMOVE */
+                               reload = 1;
                        }
-                       RB_REMOVE(iked_flows, &env->sc_activeflows, flow);
-                       (void)pfkey_flow_delete(env, flow);
-                       flow->flow_loaded = 0; /* we did RB_REMOVE */
-                       reload = 1;
-               }
 
-               if (pfkey_flow_add(env, flow) != 0) {
-                       log_debug("%s: failed to load flow", __func__);
-                       goto done;
-               }
+                       if (pfkey_flow_add(env, flow) != 0) {
+                               log_debug("%s: failed to load flow", __func__);
+                               goto done;
+                       }
 
-               if ((oflow = RB_FIND(iked_flows, &env->sc_activeflows, flow))
-                   != NULL) {
-                       log_debug("%s: replaced old flow %p with %p",
-                           __func__, oflow, flow);
-                       oflow->flow_loaded = 0;
-                       RB_REMOVE(iked_flows, &env->sc_activeflows, oflow);
-               }
+                       if ((oflow = RB_FIND(iked_flows, &env->sc_activeflows, 
flow))
+                           != NULL) {
+                               log_debug("%s: replaced old flow %p with %p",
+                                   __func__, oflow, flow);
+                               oflow->flow_loaded = 0;
+                               RB_REMOVE(iked_flows, &env->sc_activeflows, 
oflow);
+                       }
 
-               RB_INSERT(iked_flows, &env->sc_activeflows, flow);
+                       RB_INSERT(iked_flows, &env->sc_activeflows, flow);
 
-               log_debug("%s: %sloaded flow %p", __func__,
-                   reload ? "re" : "", flow);
+                       log_debug("%s: %sloaded flow %p", __func__,
+                           reload ? "re" : "", flow);
 
-               /* append flow to log buffer */
-               if (flow->flow_dir == IPSP_DIRECTION_OUT &&
-                   flow->flow_prenat.addr_af != 0)
-                       snprintf(prenat_mask, sizeof(prenat_mask), "%d",
-                           flow->flow_prenat.addr_mask);
-               else
-                       prenat_mask[0] = '\0';
-               if (flow->flow_dir == IPSP_DIRECTION_OUT) {
-                       if (ftello(flowf) > 0)
-                               fputs(", ", flowf);
-                       fprintf(flowf, "%s-%s/%d%s%s%s%s%s=%s/%d(%u)%s",
-                           print_map(flow->flow_saproto, ikev2_saproto_map),
-                           print_addr(&flow->flow_src.addr),
-                           flow->flow_src.addr_mask,
-                           flow->flow_prenat.addr_af != 0 ? "[": "",
-                           flow->flow_prenat.addr_af != 0 ?
-                           print_addr(&flow->flow_prenat.addr) : "",
-                           flow->flow_prenat.addr_af != 0 ? "/" : "",
-                           flow->flow_prenat.addr_af != 0 ? prenat_mask : "",
-                           flow->flow_prenat.addr_af != 0 ? "]": "",
-                           print_addr(&flow->flow_dst.addr),
-                           flow->flow_dst.addr_mask,
-                           flow->flow_ipproto,
-                           reload ? "-R" : "");
+                       /* append flow to log buffer */
+                       if (flow->flow_dir == IPSP_DIRECTION_OUT &&
+                           flow->flow_prenat.addr_af != 0)
+                               snprintf(prenat_mask, sizeof(prenat_mask), "%d",
+                                   flow->flow_prenat.addr_mask);
+                       else
+                               prenat_mask[0] = '\0';
+                       if (flow->flow_dir == IPSP_DIRECTION_OUT) {
+                               if (ftello(flowf) > 0)
+                                       fputs(", ", flowf);
+                               fprintf(flowf, "%s-%s/%d%s%s%s%s%s=%s/%d(%u)%s",
+                                   print_map(flow->flow_saproto, 
ikev2_saproto_map),
+                                   print_addr(&flow->flow_src.addr),
+                                   flow->flow_src.addr_mask,
+                                   flow->flow_prenat.addr_af != 0 ? "[": "",
+                                   flow->flow_prenat.addr_af != 0 ?
+                                   print_addr(&flow->flow_prenat.addr) : "",
+                                   flow->flow_prenat.addr_af != 0 ? "/" : "",
+                                   flow->flow_prenat.addr_af != 0 ? 
prenat_mask : "",
+                                   flow->flow_prenat.addr_af != 0 ? "]": "",
+                                   print_addr(&flow->flow_dst.addr),
+                                   flow->flow_dst.addr_mask,
+                                   flow->flow_ipproto,
+                                   reload ? "-R" : "");
+                       }
                }
        }
 
blob - 075981db3201df3c982a72832f22c41bb64ae22a
blob + 48992694fbc40f75f046e39c423106a3348f4d38
--- sbin/iked/parse.y
+++ sbin/iked/parse.y
@@ -2519,6 +2519,10 @@ create_ike(char *name, int af, struct ipsec_addr_wrap 
        }
 
        if (iface != NULL) {
+               /* sec(4) */
+               if (strncmp("sec", iface, strlen("sec")) == 0)
+                       pol.pol_flags |= IKED_POLICY_ROUTING;
+
                pol.pol_iface = if_nametoindex(iface);
                if (pol.pol_iface == 0) {
                        yyerror("invalid iface");
blob - eaebe53a9904aec74ec5903e56a134a255e05c7d
blob + 4b9e4a4e12eaf87338b20f0ff114e84087b4461d
--- sbin/iked/pfkey.c
+++ sbin/iked/pfkey.c
@@ -25,6 +25,7 @@
 
 #include <netinet/in.h>
 #include <netinet/ip_ipsp.h>
+#include <net/if.h>
 #include <net/pfkeyv2.h>
 
 #include <err.h>
@@ -40,7 +41,7 @@
 #include "ikev2.h"
 
 #define ROUNDUP(x) (((x) + (PFKEYV2_CHUNK - 1)) & ~(PFKEYV2_CHUNK - 1))
-#define IOV_CNT 27
+#define IOV_CNT 28
 
 #define PFKEYV2_CHUNK sizeof(uint64_t)
 #define PFKEY_REPLY_TIMEOUT 1000
@@ -453,6 +454,7 @@ pfkey_sa(struct iked *env, uint8_t satype, uint8_t act
 int
 pfkey_sa(struct iked *env, uint8_t satype, uint8_t action, struct iked_childsa 
*sa)
 {
+       char                     iface[IF_NAMESIZE];
        struct sadb_msg          smsg;
        struct sadb_sa           sadb;
        struct sadb_address      sa_src, sa_dst, sa_pxy;
@@ -460,6 +462,7 @@ pfkey_sa(struct iked *env, uint8_t satype, uint8_t act
        struct sadb_lifetime     sa_ltime_hard, sa_ltime_soft;
        struct sadb_x_udpencap   udpencap;
        struct sadb_x_tag        sa_tag;
+       struct sadb_x_iface      sa_iface;
        char                    *tag = NULL;
        struct sadb_x_tap        sa_tap;
        struct sadb_x_rdomain    sa_rdomain;
@@ -469,6 +472,8 @@ pfkey_sa(struct iked *env, uint8_t satype, uint8_t act
        struct iked_policy      *pol;
        struct iked_addr        *dst;
        struct iovec             iov[IOV_CNT];
+       const char              *errstr = NULL;
+       uint32_t                 ifminor;
        uint32_t                 jitter;
        int                      iov_cnt;
        int                      ret, dotap = 0;
@@ -549,6 +554,7 @@ pfkey_sa(struct iked *env, uint8_t satype, uint8_t act
        bzero(&udpencap, sizeof udpencap);
        bzero(&sa_ltime_hard, sizeof(sa_ltime_hard));
        bzero(&sa_ltime_soft, sizeof(sa_ltime_soft));
+       bzero(&sa_iface, sizeof(sa_iface));
 
        if (pol->pol_rdomain >= 0) {
                bzero(&sa_rdomain, sizeof(sa_rdomain));
@@ -688,6 +694,24 @@ pfkey_sa(struct iked *env, uint8_t satype, uint8_t act
                sa_tap.sadb_x_tap_unit = pol->pol_tap;
        }
 
+       if (pol->pol_flags & IKED_POLICY_ROUTING) {
+               sa_iface.sadb_x_iface_exttype = SADB_X_EXT_IFACE;
+               sa_iface.sadb_x_iface_len = sizeof(sa_iface) / 8;
+               if (if_indextoname(pol->pol_iface, iface) == NULL) {
+                       log_warnx("%s: unsupported interface %s",
+                           __func__, iface);
+                       return (-1);
+               }
+               ifminor = strtonum(iface + strlen("sec"), 0, UINT_MAX, &errstr);
+               if (errstr != NULL) {
+                       log_warnx("%s: unsupported interface %s",
+                           __func__, iface);
+                       return (-1);
+               }
+               sa_iface.sadb_x_iface_unit = ifminor;
+               sa_iface.sadb_x_iface_direction = sa->csa_dir;
+       }
+
  send:
 
 #define PAD(len)                                       \
@@ -816,6 +840,13 @@ pfkey_sa(struct iked *env, uint8_t satype, uint8_t act
                PAD(strlen(tag) + 1);
        }
 
+       if (sa_iface.sadb_x_iface_len) {
+               iov[iov_cnt].iov_base = &sa_iface;
+               iov[iov_cnt].iov_len = sa_iface.sadb_x_iface_len * 8;
+               smsg.sadb_msg_len += sa_iface.sadb_x_iface_len;
+               iov_cnt++;
+       }
+
        if (dotap != 0) {
                /* enc(4) device tap unit */
                iov[iov_cnt].iov_base = &sa_tap;

Reply via email to