On Mon, Aug 07, 2023 at 05:36:27PM +0200, Tobias Heider wrote:
> 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.
this is working well in my testing. ok by me.
>
> 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;