diff options
Diffstat (limited to 'sbin/iked')
-rw-r--r-- | sbin/iked/iked.h | 3 | ||||
-rw-r--r-- | sbin/iked/ikev2.c | 106 | ||||
-rw-r--r-- | sbin/iked/parse.y | 6 | ||||
-rw-r--r-- | sbin/iked/pfkey.c | 35 |
4 files changed, 94 insertions, 56 deletions
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h index 2c7fbe14af3..bdfac0ee74e 100644 --- a/sbin/iked/iked.h +++ b/sbin/iked/iked.h @@ -1,4 +1,4 @@ -/* $OpenBSD: iked.h,v 1.223 2023/07/28 11:23:03 claudio Exp $ */ +/* $OpenBSD: iked.h,v 1.224 2023/08/11 11:24:55 tobhe Exp $ */ /* * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de> @@ -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; diff --git a/sbin/iked/ikev2.c b/sbin/iked/ikev2.c index bf6bf0fb0d4..e243432a742 100644 --- a/sbin/iked/ikev2.c +++ b/sbin/iked/ikev2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ikev2.c,v 1.377 2023/08/04 19:06:25 claudio Exp $ */ +/* $OpenBSD: ikev2.c,v 1.378 2023/08/11 11:24:55 tobhe Exp $ */ /* * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de> @@ -6532,63 +6532,65 @@ ikev2_childsa_enable(struct iked *env, struct iked_sa *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" : ""); + } } } diff --git a/sbin/iked/parse.y b/sbin/iked/parse.y index 075981db320..5fadcd200e6 100644 --- a/sbin/iked/parse.y +++ b/sbin/iked/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.143 2023/06/14 14:09:29 claudio Exp $ */ +/* $OpenBSD: parse.y,v 1.144 2023/08/11 11:24:55 tobhe Exp $ */ /* * Copyright (c) 2019 Tobias Heider <tobias.heider@stusta.de> @@ -2519,6 +2519,10 @@ create_ike(char *name, int af, struct ipsec_addr_wrap *ipproto, } 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"); diff --git a/sbin/iked/pfkey.c b/sbin/iked/pfkey.c index eaebe53a990..80a931d5132 100644 --- a/sbin/iked/pfkey.c +++ b/sbin/iked/pfkey.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkey.c,v 1.82 2023/06/13 12:34:12 tb Exp $ */ +/* $OpenBSD: pfkey.c,v 1.83 2023/08/11 11:24:55 tobhe Exp $ */ /* * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org> @@ -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_flow(struct iked *env, uint8_t satype, uint8_t action, struct iked_flow *f 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 action, struct iked_childsa * 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 action, struct iked_childsa * 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 action, struct iked_childsa * 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 action, struct iked_childsa * 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 action, struct iked_childsa * 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; |