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;