nice catch. you should be able to commit this now, ok by me. cheers, dlg
On Sun, 9 Jul 2023 at 04:52, GODA Kazuya <g...@gokzy.com> wrote: > Hi, > > I tested it between OpenBSD and a router that is based on NetBSD. > It seems to work well (I only tested using static routing). > > I found a minor issue that outgoing traffic doesn't appear in tcpdump. > It's because it's missing bpf_mtap so this patch can fix it. > > > diff --git a/sys/net/if_sec.c b/sys/net/if_sec.c > index eccbde9e152..4f01d136214 100644 > --- a/sys/net/if_sec.c > +++ b/sys/net/if_sec.c > @@ -353,7 +353,11 @@ sec_send(void *arg) > #if NPF > 0 > pf_pkt_addr_changed(m); > #endif > - > +#if NBPFILTER > 0 > + if (ifp->if_bpf) > + bpf_mtap_af(ifp->if_bpf, m->m_pkthdr.ph_family, m, > + BPF_DIRECTION_OUT); > +#endif > error = ipsp_process_packet(m, tdb, > m->m_pkthdr.ph_family, /* already tunnelled? */ 0); > if (error != 0) > > On Tue, 4 Jul 2023 at 14:33, David Gwynne <da...@gwynne.id.au> wrote: > > > > tl;dr: this adds sec(4) p2p ip interfaces. Traffic in and out of these > > interfaces is protected by IPsec security associations (SAs), but > > there's no flows (security policy database (SPD) entries) associated > > with these SAs. The policy for using the sec(4) interfaces and their > > SAs is route-based instead. > > > > Longer version: > > > > I was going to use "make ipsec great again^W" as the subject line, > > but thought better of it. The reason I started on this was to better > > interoperate with "site-to-site" vpns, in particular AWS Site-to-Site > > VPNs, and the Auto-Discovery VPN (ADVPN) stuff on fortinet fortigate > > appliances. Both of these negotiate IPsec tunnels that can carry any > > traffic at the IPsec level, but use BGP and routes to direct traffic > > into those tunnels. > > > > sec(4) is equivalent to a gif(4) interface with its encapsulated > > packets protected by ESP in transport mode. You route packets into the > > interface (sec or gif), and it gets encrypted and sent to the peer, > > which decaspulates the traffic. The main difference is in how the > > SAs for these connections are negotiated. > > > > Neither of these things want to negotiate esp transport mode to protect > > gif(4) packets, they want to negotiate esp tunnel mode for 0.0.0.0/0 to > > 0.0.0.0/0. The fact that IPsec in tunnel mode and gif both use the same > > ip protocol number also causes a lot of confusion in the kernel in the > > SPD. > > > > After trying a bunch of different configurations out, and then trying to > > hack up ipsecctl and isakmpd, and then talking to markus@, tobhe@, and > > sthen@, we came up with sec(4). The idea isn't unique to us though. It > > has been mooted in RFC3884 section 4.1.1, Cisco has VTI, Juniper has > > st0, Linux has vti and xfrm interfaces, FreeBSD has ipsec_if, NetBSD has > > ipsecif... > > > > The kernel has been modified so ike daemons can inject a SA with > > an iface extention message attached which specifies which sec(4) > > the SA is for, and which direction it should be processing traffic > > for. If a SA has this iface config on it, the ipsp code skips the > > SPD side of things and instead makes these SAs available to sec(4) > > for it to use. > > > > I've tweaked isakmpd and ipsecctl so they support new config options > > that let you configure SAs for sec(4). Most of the changes in isakmpd > > are so it can continue to negotiate the right stuff with the peer, > > but then short circuits the kernel config so only the SAs with the > > iface extension are injected, none of the flows get inserted. > > > > tobhe@ has done the same for iked, but he's reused the "iface" > > config and special cased the handling of sec interfaces. > > > > For ipsecctl and isakmpd, config looks like this in ipsec.conf: > > > > h_self="130.102.96.46" > > h_s2s1="52.65.9.248" > > h_s2s1_key="one" > > h_s2s2="54.153.175.223" > > h_s2s2_key="two" > > > > ike interface sec0 local $h_self peer $h_s2s1 \ > > main auth hmac-sha2-256 enc aes-256 group modp3072 lifetime > 28800 \ > > quick auth hmac-sha2-256 enc aes-256 group modp3072 lifetime > 3600 \ > > psk $h_s2s1_key > > > > ike interface sec1 local $h_self peer $h_s2s2 \ > > main auth hmac-sha2-256 enc aes-256 group modp3072 lifetime > 28800 \ > > quick auth hmac-sha2-256 enc aes-256 group modp3072 lifetime > 3600 \ > > psk $h_s2s2_key > > > > sec interface config: > > > > dlg@ix ~$ sudo cat /etc/hostname.sec0 > > inet 169.254.64.94 255.255.255.252 169.254.64.93 > > up > > dlg@ix ~$ sudo cat /etc/hostname.sec1 > > inet 169.254.105.134 255.255.255.252 169.254.105.133 > > up > > > > aws s2s says we can then talk bgp: > > > > dlg@ix ~$ sudo cat /etc/bgpd.conf > > AS 65001 > > router-id 130.102.96.46 > > > > group aws { > > remote-as 64512 > > neighbor 169.254.64.93 > > neighbor 169.254.105.133 > > } > > > > with isakmpd running and ipsecctl having injected its config into > > it, it then sets up SAs: > > > > dlg@ix ~$ sudo ipsecctl -sa > > FLOWS: > > No flows > > > > SAD: > > esp tunnel from 54.153.175.223 to 130.102.96.46 spi 0x13ca145b auth > hmac-sha2-256 enc aes-256 > > esp tunnel from 52.65.9.248 to 130.102.96.46 spi 0x8e5fec4b auth > hmac-sha2-256 enc aes-256 > > esp tunnel from 130.102.96.46 to 54.153.175.223 spi 0xc9d2adc1 auth > hmac-sha2-256 enc aes-256 > > esp tunnel from 130.102.96.46 to 52.65.9.248 spi 0xca1adc30 auth > hmac-sha2-256 enc aes-256 > > dlg@ix ~$ sudo ipsecctl -sa -v > > FLOWS: > > No flows > > > > SAD: > > esp tunnel from 54.153.175.223 to 130.102.96.46 spi 0x13ca145b auth > hmac-sha2-256 enc aes-256 > > sa: spi 0x13ca145b auth hmac-sha2-256 enc aes > > state mature replay 16 flags 0x204<tunnel,udpencap> > > lifetime_cur: alloc 0 bytes 752 add 1684451878 first 1684451880 > > lifetime_hard: alloc 0 bytes 0 add 3600 first 0 > > lifetime_soft: alloc 0 bytes 0 add 3240 first 0 > > address_src: 54.153.175.223 > > address_dst: 130.102.96.46 > > identity_src: type prefix id 0: 54.153.175.223/32 > > identity_dst: type prefix id 0: 130.102.96.46/32 > > src_mask: 0.0.0.0 > > dst_mask: 0.0.0.0 > > protocol: proto 0 flags 0 > > flow_type: type use direction in > > src_flow: 0.0.0.0 > > dst_flow: 0.0.0.0 > > udpencap: udpencap port 4500 > > lifetime_lastuse: alloc 0 bytes 0 add 0 first 1684451888 > > counter: > > 9 input packets > > 2044 input bytes > > 853 input bytes, decompressed > > 9 packets dropped on input > > > > replay: rpl 9 > > interface: sec1 direction in > > esp tunnel from 52.65.9.248 to 130.102.96.46 spi 0x8e5fec4b auth > hmac-sha2-256 enc aes-256 > > sa: spi 0x8e5fec4b auth hmac-sha2-256 enc aes > > state mature replay 16 flags 0x204<tunnel,udpencap> > > lifetime_cur: alloc 0 bytes 528 add 1684451878 first 1684451882 > > lifetime_hard: alloc 0 bytes 0 add 3600 first 0 > > lifetime_soft: alloc 0 bytes 0 add 3240 first 0 > > address_src: 52.65.9.248 > > address_dst: 130.102.96.46 > > identity_src: type prefix id 0: 52.65.9.248/32 > > identity_dst: type prefix id 0: 130.102.96.46/32 > > src_mask: 0.0.0.0 > > dst_mask: 0.0.0.0 > > protocol: proto 0 flags 0 > > flow_type: type use direction in > > src_flow: 0.0.0.0 > > dst_flow: 0.0.0.0 > > udpencap: udpencap port 4500 > > lifetime_lastuse: alloc 0 bytes 0 add 0 first 1684451887 > > counter: > > 6 input packets > > 1416 input bytes > > 597 input bytes, decompressed > > 6 packets dropped on input > > > > replay: rpl 6 > > interface: sec0 direction in > > esp tunnel from 130.102.96.46 to 54.153.175.223 spi 0xc9d2adc1 auth > hmac-sha2-256 enc aes-256 > > sa: spi 0xc9d2adc1 auth hmac-sha2-256 enc aes > > state mature replay 16 flags 0x204<tunnel,udpencap> > > lifetime_cur: alloc 0 bytes 511 add 1684451878 first 1684451880 > > lifetime_hard: alloc 0 bytes 0 add 3600 first 0 > > lifetime_soft: alloc 0 bytes 0 add 3240 first 0 > > address_src: 130.102.96.46 > > address_dst: 54.153.175.223 > > identity_src: type prefix id 0: 130.102.96.46/32 > > identity_dst: type prefix id 0: 54.153.175.223/32 > > src_mask: 0.0.0.0 > > dst_mask: 0.0.0.0 > > protocol: proto 0 flags 0 > > flow_type: type use direction out > > src_flow: 0.0.0.0 > > dst_flow: 0.0.0.0 > > udpencap: udpencap port 4500 > > lifetime_lastuse: alloc 0 bytes 0 add 0 first 1684451888 > > counter: > > 8 output packets > > 1136 output bytes > > 671 output bytes, uncompressed > > > > replay: rpl 9 > > interface: sec1 direction out > > esp tunnel from 130.102.96.46 to 52.65.9.248 spi 0xca1adc30 auth > hmac-sha2-256 enc aes-256 > > sa: spi 0xca1adc30 auth hmac-sha2-256 enc aes > > state mature replay 16 flags 0x204<tunnel,udpencap> > > lifetime_cur: alloc 0 bytes 452 add 1684451878 first 1684451882 > > lifetime_hard: alloc 0 bytes 0 add 3600 first 0 > > lifetime_soft: alloc 0 bytes 0 add 3240 first 0 > > address_src: 130.102.96.46 > > address_dst: 52.65.9.248 > > identity_src: type prefix id 0: 130.102.96.46/32 > > identity_dst: type prefix id 0: 52.65.9.248/32 > > src_mask: 0.0.0.0 > > dst_mask: 0.0.0.0 > > protocol: proto 0 flags 0 > > flow_type: type use direction out > > src_flow: 0.0.0.0 > > dst_flow: 0.0.0.0 > > udpencap: udpencap port 4500 > > lifetime_lastuse: alloc 0 bytes 0 add 0 first 1684451887 > > counter: > > 7 output packets > > 1004 output bytes > > 592 output bytes, uncompressed > > > > replay: rpl 8 > > interface: sec0 direction out > > > > dlg@ix ~$ ifconfig sec > > sec0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1280 > > index 14 priority 0 llprio 3 > > groups: sec > > inet 169.254.64.94 --> 169.254.64.93 netmask 0xfffffffc > > sec1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1280 > > index 15 priority 0 llprio 3 > > groups: sec > > inet 169.254.105.134 --> 169.254.105.133 netmask 0xfffffffc > > dlg@ix ~$ ping -qc4 169.254.64.93 > > PING 169.254.64.93 (169.254.64.93): 56 data bytes > > > > --- 169.254.64.93 ping statistics --- > > 4 packets transmitted, 4 packets received, 0.0% packet loss > > round-trip min/avg/max/std-dev = 16.878/17.062/17.230/0.131 ms > > dlg@ix ~$ ping -qc4 169.254.105.133 > > PING 169.254.105.133 (169.254.105.133): 56 data bytes > > > > --- 169.254.105.133 ping statistics --- > > 4 packets transmitted, 4 packets received, 0.0% packet loss > > round-trip min/avg/max/std-dev = 15.110/15.690/16.538/0.524 ms > > > > and bgp comes up: > > > > dlg@ix ~$ sudo bgpctl sh > > Neighbor AS MsgRcvd MsgSent OutQ Up/Down > State/PrfRcvd > > 169.254.64.93 64512 2534 2505 0 00:01:43 1 > > 169.254.105.133 64512 4140 4137 0 00:01:38 1 > > dlg@ix ~$ sudo bgpctl sh rib in > > flags: * = Valid, > = Selected, I = via IBGP, A = Announced, > > S = Stale, E = Error > > origin validation state: N = not-found, V = valid, ! = invalid > > aspa validation state: ? = unknown, V = valid, ! = invalid > > origin: i = IGP, e = EGP, ? = Incomplete > > > > flags vs destination gateway lpref med aspath origin > > N-? 100.64.64.0/22 169.254.105.133 100 100 64512 i > > N-? 100.64.64.0/22 169.254.64.93 100 200 64512 i > > > > ive got equivalent config with iked working, but tobhe@ wrote that > > so i don't think it's fair for me to steal his thunder. > > > > thoughts? is it worth continuing with? > > > > Index: sbin/iked/iked.h > > =================================================================== > > RCS file: /cvs/src/sbin/iked/iked.h,v > > retrieving revision 1.220 > > diff -u -p -r1.220 iked.h > > --- sbin/iked/iked.h 28 Jun 2023 14:10:24 -0000 1.220 > > +++ sbin/iked/iked.h 29 Jun 2023 03:09:45 -0000 > > @@ -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; > > > > Index: sbin/iked/ikev2.c > > =================================================================== > > RCS file: /cvs/src/sbin/iked/ikev2.c,v > > retrieving revision 1.372 > > diff -u -p -r1.372 ikev2.c > > --- sbin/iked/ikev2.c 28 Jun 2023 14:10:24 -0000 1.372 > > +++ sbin/iked/ikev2.c 29 Jun 2023 03:09:45 -0000 > > @@ -1782,7 +1782,8 @@ ikev2_init_done(struct iked *env, struct > > ikev2_enable_timer(env, sa); > > ikev2_log_established(sa); > > ikev2_record_dstid(env, sa); > > - sa_configure_iface(env, sa, 1); > > + if (!(sa->sa_policy->pol_flags & IKED_POLICY_ROUTING)) > > + sa_configure_iface(env, sa, 1); > > } > > > > if (ret) > > Index: sbin/iked/parse.y > > =================================================================== > > RCS file: /cvs/src/sbin/iked/parse.y,v > > retrieving revision 1.143 > > diff -u -p -r1.143 parse.y > > --- sbin/iked/parse.y 14 Jun 2023 14:09:29 -0000 1.143 > > +++ sbin/iked/parse.y 29 Jun 2023 03:09:45 -0000 > > @@ -2519,6 +2519,10 @@ create_ike(char *name, int af, struct ip > > } > > > > 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"); > > Index: sbin/iked/pfkey.c > > =================================================================== > > RCS file: /cvs/src/sbin/iked/pfkey.c,v > > retrieving revision 1.82 > > diff -u -p -r1.82 pfkey.c > > --- sbin/iked/pfkey.c 13 Jun 2023 12:34:12 -0000 1.82 > > +++ sbin/iked/pfkey.c 29 Jun 2023 03:09:45 -0000 > > @@ -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 sat > > 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 satyp > > 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 satyp > > 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; > > @@ -688,6 +693,25 @@ pfkey_sa(struct iked *env, uint8_t satyp > > sa_tap.sadb_x_tap_unit = pol->pol_tap; > > } > > > > + if (pol->pol_flags & IKED_POLICY_ROUTING) { > > + bzero(&sa_iface, sizeof(sa_iface)); > > + 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) \ > > @@ -814,6 +838,13 @@ pfkey_sa(struct iked *env, uint8_t satyp > > smsg.sadb_msg_len += sa_tag.sadb_x_tag_len; > > iov_cnt++; > > 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) { > > Index: sbin/ipsecctl/ike.c > > =================================================================== > > RCS file: /cvs/src/sbin/ipsecctl/ike.c,v > > retrieving revision 1.83 > > diff -u -p -r1.83 ike.c > > --- sbin/ipsecctl/ike.c 25 Jun 2022 20:33:40 -0000 1.83 > > +++ sbin/ipsecctl/ike.c 29 Jun 2023 03:09:45 -0000 > > @@ -148,6 +148,10 @@ ike_section_ipsec(struct ipsec_rule *r, > > > > if (r->tag) > > fprintf(fd, SET "[%s]:PF-Tag=%s force\n", r->p2name, > r->tag); > > + if (r->flags & IPSEC_RULE_F_IFACE) { > > + fprintf(fd, SET "[%s]:Interface=%u force\n", r->p2name, > > + r->iface); > > + } > > } > > > > static int > > @@ -842,21 +846,30 @@ ike_setup_ids(struct ipsec_rule *r) > > err(1, "ike_setup_ids"); > > > > /* Phase 2 name is from and to network, protocol, port*/ > > - sproto[0] = ssport[0] = sdport[0] = 0; > > - if (r->proto) > > - snprintf(sproto, sizeof sproto, "=%u", r->proto); > > - if (r->sport) > > - snprintf(ssport, sizeof ssport, ":%u", ntohs(r->sport)); > > - if (r->dport) > > - snprintf(sdport, sizeof sdport, ":%u", ntohs(r->dport)); > > - /* from-network/masklen=proto:port */ > > - if (asprintf(&r->p2lid, "from-%s%s%s", r->src->name, sproto, > ssport) > > - == -1) > > - err(1, "ike_setup_ids"); > > - /* to-network/masklen=proto:port */ > > - if (asprintf(&r->p2rid, "to-%s%s%s", r->dst->name, sproto, > sdport) > > - == -1) > > - err(1, "ike_setup_ids"); > > + if (r->flags & IPSEC_RULE_F_IFACE) { > > + if (asprintf(&r->p2lid, "from-sec%u", r->iface) == -1) > > + err(1, "ike_setup_ids"); > > + if (asprintf(&r->p2rid, "to-sec%u", r->iface) == -1) > > + err(1, "ike_setup_ids"); > > + } else { > > + sproto[0] = ssport[0] = sdport[0] = 0; > > + if (r->proto) > > + snprintf(sproto, sizeof sproto, "=%u", r->proto); > > + if (r->sport) > > + snprintf(ssport, sizeof ssport, ":%u", > ntohs(r->sport)); > > + if (r->dport) > > + snprintf(sdport, sizeof sdport, ":%u", > ntohs(r->dport)); > > + > > + /* from-network/masklen=proto:port */ > > + if (asprintf(&r->p2lid, "from-%s%s%s", r->src->name, > > + sproto, ssport) == -1) > > + err(1, "ike_setup_ids"); > > + /* to-network/masklen=proto:port */ > > + if (asprintf(&r->p2rid, "to-%s%s%s", r->dst->name, > > + sproto, sdport) == -1) > > + err(1, "ike_setup_ids"); > > + } > > + > > /* from-network/masklen=proto:port-to-network/masklen=proto:port > */ > > if (asprintf(&r->p2name, "%s-%s", r->p2lid , r->p2rid) == -1) > > err(1, "ike_setup_ids"); > > Index: sbin/ipsecctl/ipsecctl.h > > =================================================================== > > RCS file: /cvs/src/sbin/ipsecctl/ipsecctl.h,v > > retrieving revision 1.75 > > diff -u -p -r1.75 ipsecctl.h > > --- sbin/ipsecctl/ipsecctl.h 22 Oct 2021 12:30:54 -0000 1.75 > > +++ sbin/ipsecctl/ipsecctl.h 29 Jun 2023 03:09:45 -0000 > > @@ -178,6 +178,9 @@ TAILQ_HEAD(dst_bundle_queue, ipsec_rule) > > struct ipsec_rule { > > u_int8_t type; > > > > + unsigned int flags; > > +#define IPSEC_RULE_F_IFACE (1 << 0) /* iface is valid */ > > + > > struct ipsec_addr_wrap *src; > > struct ipsec_addr_wrap *dst; > > struct ipsec_addr_wrap *dst2; > > @@ -215,6 +218,7 @@ struct ipsec_rule { > > u_int32_t spi; > > u_int32_t spi2; > > u_int32_t nr; > > + unsigned int iface; > > > > TAILQ_ENTRY(ipsec_rule) rule_entry; > > TAILQ_ENTRY(ipsec_rule) bundle_entry; > > Index: sbin/ipsecctl/parse.y > > =================================================================== > > RCS file: /cvs/src/sbin/ipsecctl/parse.y,v > > retrieving revision 1.181 > > diff -u -p -r1.181 parse.y > > --- sbin/ipsecctl/parse.y 22 Oct 2021 12:30:54 -0000 1.181 > > +++ sbin/ipsecctl/parse.y 29 Jun 2023 03:09:45 -0000 > > @@ -233,6 +233,7 @@ struct ipsec_transforms *ipsec_transform > > typedef struct { > > union { > > int64_t number; > > + uint32_t unit; > > u_int8_t ikemode; > > u_int8_t dir; > > u_int8_t satype; /* encapsulating > prococol */ > > @@ -285,9 +286,10 @@ typedef struct { > > %token AUTHKEY ENCKEY FILENAME AUTHXF ENCXF ERROR IKE MAIN QUICK > AGGRESSIVE > > %token PASSIVE ACTIVE ANY IPIP IPCOMP COMPXF TUNNEL TRANSPORT DYNAMIC > LIFETIME > > %token TYPE DENY BYPASS LOCAL PROTO USE ACQUIRE REQUIRE DONTACQ GROUP > PORT TAG > > -%token INCLUDE BUNDLE UDPENCAP > > +%token INCLUDE BUNDLE UDPENCAP INTERFACE > > %token <v.string> STRING > > %token <v.number> NUMBER > > +%type <v.unit> iface > > %type <v.string> string > > %type <v.dir> dir > > %type <v.satype> satype > > @@ -402,6 +404,41 @@ ikerule : IKE ikemode satype tmode prot > > if (expand_rule(r, &$7, 0, 0, NULL, NULL, NULL)) > > errx(1, "ikerule: expand_rule"); > > } > > + > > + /* ike interface sec0 local $h_self peer $h_s2s1 ... */ > > + | IKE ikemode iface peers > > + phase1mode phase2mode ids ikeauth { > > + uint8_t proto = 0; // > IPPROTO_IPIP; > > + struct ipsec_hosts hosts; > > + struct ike_mode *phase1mode = $5; > > + struct ike_mode *phase2mode = $6; > > + uint8_t satype = IPSEC_ESP; > > + uint8_t tmode = IPSEC_TUNNEL; > > + uint8_t mode = $2; > > + struct ike_auth *authtype = &$8; > > + char *tag = NULL; > > + > > + struct ipsec_rule *r; > > + > > + hosts.src = host_v4("0.0.0.0/0", 1); > > + hosts.sport = htons(0); > > + hosts.dst = host_v4("0.0.0.0/0", 1); > > + hosts.dport = htons(0); > > + > > + r = create_ike(proto, &hosts, phase1mode, > phase2mode, > > + satype, tmode, mode, $7.srcid, $7.dstid, > > + authtype, tag); > > + if (r == NULL) { > > + YYERROR; > > + } > > + > > + r->flags |= IPSEC_RULE_F_IFACE; > > + r->iface = $3; > > + > > + if (expand_rule(r, &$4, 0, 0, NULL, NULL, NULL)) > > + errx(1, "ikerule: expand interface > rule"); > > + > > + } > > ; > > > > satype : /* empty */ { $$ = IPSEC_ESP; } > > @@ -910,6 +947,30 @@ tag : /* empty */ > > } > > ; > > > > +iface : INTERFACE STRING { > > + static const char prefix[] = "sec"; > > + const char *errstr = NULL; > > + size_t len, plen; > > + > > + plen = strlen(prefix); > > + len = strlen($2); > > + > > + if (len <= plen || memcmp($2, prefix, plen) != > 0) { > > + yyerror("invalid %s interface name", > prefix); > > + free($2); > > + YYERROR; > > + } > > + > > + $$ = strtonum($2 + plen, 0, UINT_MAX, &errstr); > > + free($2); > > + if (errstr != NULL) { > > + yyerror("invalid %s interface unit: %s", > > + prefix, errstr); > > + YYERROR; > > + } > > + } > > + ; > > + > > string : string STRING > > { > > if (asprintf(&$$, "%s %s", $1, $2) == -1) > > @@ -1010,6 +1071,7 @@ lookup(char *s) > > { "ike", IKE }, > > { "in", IN }, > > { "include", INCLUDE }, > > + { "interface", INTERFACE }, > > { "ipcomp", IPCOMP }, > > { "ipip", IPIP }, > > { "lifetime", LIFETIME }, > > @@ -2217,6 +2279,7 @@ copyrule(struct ipsec_rule *rule) > > r->enckey = copykey(rule->enckey); > > r->tag = copytag(rule->tag); > > > > + r->flags = rule->flags; > > r->p1ie = rule->p1ie; > > r->p2ie = rule->p2ie; > > r->type = rule->type; > > @@ -2232,6 +2295,7 @@ copyrule(struct ipsec_rule *rule) > > r->udpencap = rule->udpencap; > > r->udpdport = rule->udpdport; > > r->nr = rule->nr; > > + r->iface = rule->iface; > > > > return (r); > > } > > Index: sbin/ipsecctl/pfkdump.c > > =================================================================== > > RCS file: /cvs/src/sbin/ipsecctl/pfkdump.c,v > > retrieving revision 1.55 > > diff -u -p -r1.55 pfkdump.c > > --- sbin/ipsecctl/pfkdump.c 22 Oct 2021 12:30:54 -0000 1.55 > > +++ sbin/ipsecctl/pfkdump.c 29 Jun 2023 03:09:45 -0000 > > @@ -62,6 +62,7 @@ static void print_mtu(struct sadb_ext *, > > static void print_tap(struct sadb_ext *, struct sadb_msg *, int); > > static void print_satype(struct sadb_ext *, struct sadb_msg *, int); > > static void print_counter(struct sadb_ext *, struct sadb_msg *, int); > > +static void print_iface(struct sadb_ext *, struct sadb_msg *, int); > > > > static struct idname *lookup(struct idname *, u_int32_t); > > static char *lookup_name(struct idname *, u_int32_t); > > @@ -115,6 +116,7 @@ struct idname ext_types[] = { > > { SADB_X_EXT_TAP, "tap", > print_tap }, > > { SADB_X_EXT_SATYPE2, "satype2", > print_satype }, > > { SADB_X_EXT_COUNTER, "counter", > print_counter }, > > + { SADB_X_EXT_IFACE, "interface", > print_iface }, > > { 0, NULL, NULL } > > }; > > > > @@ -465,6 +467,24 @@ print_counter(struct sadb_ext *ext, stru > > p(sadb_x_counter_odrops, "\t\t%llu packet%s dropped on > output\n"); > > #undef p > > #undef plural > > +} > > + > > +static void > > +print_iface(struct sadb_ext *ext, struct sadb_msg *msg, int opts) > > +{ > > + struct sadb_x_iface *siface = (struct sadb_x_iface *)ext; > > + const char *dir = "unknown"; > > + > > + switch (siface->sadb_x_iface_direction) { > > + case IPSP_DIRECTION_IN: > > + dir = "in"; > > + break; > > + case IPSP_DIRECTION_OUT: > > + dir = "out"; > > + break; > > + } > > + > > + printf("sec%u direction %s", siface->sadb_x_iface_unit, dir); > > } > > > > static char * > > Index: sbin/isakmpd/ipsec.c > > =================================================================== > > RCS file: /cvs/src/sbin/isakmpd/ipsec.c,v > > retrieving revision 1.152 > > diff -u -p -r1.152 ipsec.c > > --- sbin/isakmpd/ipsec.c 16 Jan 2022 14:30:11 -0000 1.152 > > +++ sbin/isakmpd/ipsec.c 29 Jun 2023 03:09:45 -0000 > > @@ -38,6 +38,7 @@ > > #include <arpa/inet.h> > > #include <stdlib.h> > > #include <string.h> > > +#include <limits.h> > > > > #include <net/if.h> > > #include <net/pfvar.h> > > @@ -131,6 +132,7 @@ static int ipsec_validate_transform > > static int ipsec_sa_check_flow(struct sa *, void *); > > static int ipsec_sa_check_flow_any(struct sa *, void *); > > static int ipsec_sa_tag(struct exchange *, struct sa *, struct sa > *); > > +static int ipsec_sa_iface(struct exchange *, struct sa *, struct > sa *); > > > > static struct doi ipsec_doi = { > > {0}, IPSEC_DOI_IPSEC, > > @@ -272,6 +274,12 @@ ipsec_sa_check_flow_any(struct sa *sa, v > > isa->dport != isa2->dport) > > return 0; > > > > + if ((sa->flags & SA_FLAG_IFACE) != (sa2->flags & SA_FLAG_IFACE)) > > + return 0; > > + > > + if (sa->flags & SA_FLAG_IFACE) > > + return sa->iface == sa2->iface; > > + > > /* > > * If at least one of the IPsec SAs is incomplete, we're done. > > */ > > @@ -379,6 +387,30 @@ ipsec_sa_tag(struct exchange *exchange, > > return (error); > > } > > > > +static int > > +ipsec_sa_iface(struct exchange *exchange, struct sa *sa, struct sa > *isakmp_sa) > > +{ > > + char *section, *value; > > + const char *errstr = NULL; > > + > > + sa->tag = NULL; > > + > > + if (exchange->name == NULL || > > + (section = exchange->name) == NULL || > > + (value = conf_get_str(section, "Interface")) == NULL) > > + return (0); /* ignore if not present */ > > + > > + sa->iface = strtonum(value, 0, UINT_MAX, &errstr); > > + if (errstr != NULL) { > > + log_error("[%s]:Interface %s", section, errstr); > > + return (-1); > > + } > > + > > + sa->flags |= SA_FLAG_IFACE; > > + > > + return (0); > > +} > > + > > /* > > * Do IPsec DOI specific finalizations task for the exchange where MSG > was > > * the final message. > > @@ -463,6 +495,9 @@ ipsec_finalize_exchange(struct message * > > if (ipsec_sa_tag(exchange, sa, > isakmp_sa) == -1) > > return; > > > > + if (ipsec_sa_iface(exchange, sa, > isakmp_sa) == -1) > > + return; > > + > > for (proto = TAILQ_FIRST(&sa->protos), > > last_proto = 0; proto; > > proto = TAILQ_NEXT(proto, link)) { > > @@ -514,6 +549,7 @@ ipsec_finalize_exchange(struct message * > > * (a.k.a. flow) set up. > > */ > > if (!(sa->flags & SA_FLAG_ONDEMAND || > > + sa->flags & SA_FLAG_IFACE || > > conf_get_str("General", > "Acquire-Only") || > > acquire_only) && > > pf_key_v2_enable_sa(sa, isakmp_sa)) > > @@ -1596,7 +1632,8 @@ ipsec_delete_spi(struct sa *sa, struct p > > * We ignore any errors from the disabling of the flow. > > */ > > if (sa->flags & SA_FLAG_READY && !(sa->flags & SA_FLAG_ONDEMAND > || > > - sa->flags & SA_FLAG_REPLACED || acquire_only || > > + sa->flags & SA_FLAG_REPLACED || sa->flags & SA_FLAG_IFACE || > > + acquire_only || > > conf_get_str("General", "Acquire-Only"))) > > pf_key_v2_disable_sa(sa, incoming); > > > > Index: sbin/isakmpd/pf_key_v2.c > > =================================================================== > > RCS file: /cvs/src/sbin/isakmpd/pf_key_v2.c,v > > retrieving revision 1.204 > > diff -u -p -r1.204 pf_key_v2.c > > --- sbin/isakmpd/pf_key_v2.c 31 Jan 2022 23:51:15 -0000 1.204 > > +++ sbin/isakmpd/pf_key_v2.c 29 Jun 2023 03:09:45 -0000 > > @@ -890,6 +890,7 @@ pf_key_v2_set_spi(struct sa *sa, struct > > struct sadb_protocol flowtype, tprotocol; > > struct sadb_x_udpencap udpencap; > > char *addr_str, *s; > > + char iface_str[32]; > > > > msg.sadb_msg_type = incoming ? SADB_UPDATE : SADB_ADD; > > switch (proto->proto) { > > @@ -1378,16 +1379,37 @@ nodid: > > goto cleanup; > > } > > > > + if (sa->flags & SA_FLAG_IFACE) { > > + struct sadb_x_iface *siface; > > + > > + len = sizeof(*siface); > > + siface = calloc(1, len); > > + if (siface == NULL) > > + goto cleanup; > > + > > + siface->sadb_x_iface_len = len / PF_KEY_V2_CHUNK; > > + siface->sadb_x_iface_exttype = SADB_X_EXT_IFACE; > > + siface->sadb_x_iface_unit = sa->iface; > > + siface->sadb_x_iface_direction = incoming ? > > + IPSP_DIRECTION_IN : IPSP_DIRECTION_OUT; > > + > > + if (pf_key_v2_msg_add(update, (struct sadb_ext *)siface, > > + PF_KEY_V2_NODE_MALLOCED) == -1) > > + goto cleanup; > > + > > + snprintf(iface_str, sizeof(iface_str), "iface %u", > sa->iface); > > + } > > + > > /* XXX Here can sensitivity extensions be setup. */ > > > > if (sockaddr2text(dst, &addr_str, 0)) > > addr_str = 0; > > > > LOG_DBG((LOG_SYSDEP, 10, "pf_key_v2_set_spi: " > > - "satype %d dst %s SPI 0x%x%s%s", msg.sadb_msg_satype, > > + "satype %d dst %s SPI 0x%x%s%s%s", msg.sadb_msg_satype, > > addr_str ? addr_str : "unknown", > > ntohl(ssa.sadb_sa_spi), sa->tag ? " tag " : "", > > - sa->tag ? sa->tag : "")); > > + sa->tag ? sa->tag : "", iface_str)); > > > > free(addr_str); > > > > Index: sbin/isakmpd/sa.h > > =================================================================== > > RCS file: /cvs/src/sbin/isakmpd/sa.h,v > > retrieving revision 1.54 > > diff -u -p -r1.54 sa.h > > --- sbin/isakmpd/sa.h 15 Jan 2018 09:54:48 -0000 1.54 > > +++ sbin/isakmpd/sa.h 29 Jun 2023 03:09:45 -0000 > > @@ -211,6 +211,9 @@ struct sa { > > > > /* The add a pf tag to packets matching the established SA. */ > > char *tag; > > + > > + /* IPsec with Interface SAs, enabled with SA_FLAG_IFACE */ > > + unsigned int iface; > > }; > > > > /* This SA is alive. */ > > @@ -243,6 +246,9 @@ struct sa { > > /* NAT-T encapsulation state. Kept in isakmp_sa for the new p2 > exchange. */ > > #define SA_FLAG_NAT_T_ENABLE 0x100 > > #define SA_FLAG_NAT_T_KEEPALIVE 0x200 > > + > > +/* Policy is handled by routing/filtering on the specified iface */ > > +#define SA_FLAG_IFACE 0x400 > > > > extern void proto_free(struct proto * proto); > > extern int sa_add_transform(struct sa *, struct payload *, int, > > Index: sys/conf/GENERIC > > =================================================================== > > RCS file: /cvs/src/sys/conf/GENERIC,v > > retrieving revision 1.288 > > diff -u -p -r1.288 GENERIC > > --- sys/conf/GENERIC 27 Mar 2023 09:39:21 -0000 1.288 > > +++ sys/conf/GENERIC 29 Jun 2023 03:09:45 -0000 > > @@ -90,6 +90,7 @@ pseudo-device veb # virtual Ethernet br > > pseudo-device carp # CARP protocol support > > pseudo-device etherip # EtherIP (RFC 3378) > > pseudo-device gif # IPv[46] over IPv[46] tunnel (RFC1933) > > +pseudo-device sec # route based IPsec VPN interface > > pseudo-device gre # GRE encapsulation interface > > pseudo-device loop # network loopback > > pseudo-device mpe # MPLS PE interface > > Index: sys/conf/files > > =================================================================== > > RCS file: /cvs/src/sys/conf/files,v > > retrieving revision 1.724 > > diff -u -p -r1.724 files > > --- sys/conf/files 23 Apr 2023 00:20:26 -0000 1.724 > > +++ sys/conf/files 29 Jun 2023 03:09:45 -0000 > > @@ -572,6 +572,7 @@ pseudo-device vlan: ifnet, ether > > pseudo-device carp: ifnet, ether > > pseudo-device sppp: ifnet > > pseudo-device gif: ifnet > > +pseudo-device sec: ifnet > > pseudo-device gre: ifnet, ether, etherbridge > > pseudo-device crypto: ifnet > > pseudo-device trunk: ifnet, ether, ifmedia > > @@ -1006,6 +1007,7 @@ file uvm/uvm_vnode.c > > > > # IPv6 > > file net/if_gif.c gif > needs-count > > +file net/if_sec.c sec > needs-count > > file netinet/ip_ecn.c > > file netinet6/in6_pcb.c inet6 > > file netinet6/in6.c inet6 > > Index: sys/net/if_sec.c > > =================================================================== > > RCS file: sys/net/if_sec.c > > diff -N sys/net/if_sec.c > > --- /dev/null 1 Jan 1970 00:00:00 -0000 > > +++ sys/net/if_sec.c 29 Jun 2023 03:09:45 -0000 > > @@ -0,0 +1,578 @@ > > +/* $OpenBSD$ */ > > + > > +/* > > + * Copyright (c) 2022 The University of Queensland > > + * > > + * Permission to use, copy, modify, and distribute this software for any > > + * purpose with or without fee is hereby granted, provided that the > above > > + * copyright notice and this permission notice appear in all copies. > > + * > > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL > WARRANTIES > > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE > FOR > > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY > DAMAGES > > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT > OF > > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > > + */ > > + > > +/* > > + * This code was written by David Gwynne <d...@uq.edu.au> as part > > + * of the Information Technology Infrastructure Group (ITIG) in the > > + * Faculty of Engineering, Architecture and Information Technology > > + * (EAIT). > > + */ > > + > > +#ifndef IPSEC > > +#error sec enabled without IPSEC defined > > +#endif > > + > > +#include "bpfilter.h" > > +#include "pf.h" > > + > > +#include <sys/param.h> > > +#include <sys/mbuf.h> > > +#include <sys/socket.h> > > +#include <sys/sockio.h> > > +#include <sys/kernel.h> > > +#include <sys/systm.h> > > +#include <sys/errno.h> > > +#include <sys/timeout.h> > > +#include <sys/queue.h> > > +#include <sys/tree.h> > > +#include <sys/pool.h> > > +#include <sys/smr.h> > > +#include <sys/refcnt.h> > > + > > +#include <net/if.h> > > +#include <net/if_var.h> > > +#include <net/if_types.h> > > +#include <net/if_media.h> > > +#include <net/route.h> > > +#include <net/toeplitz.h> > > + > > +#include <netinet/in.h> > > +#include <netinet/in_var.h> > > +#include <netinet/if_ether.h> > > +#include <netinet/ip.h> > > +#include <netinet/ip_var.h> > > +#include <netinet/ip_ecn.h> > > +#include <netinet/ip_ipsp.h> > > + > > +#ifdef INET6 > > +#include <netinet/ip6.h> > > +#include <netinet6/ip6_var.h> > > +#include <netinet6/in6_var.h> > > +#endif > > + > > +#ifdef MPLS > > +#include <netmpls/mpls.h> > > +#endif /* MPLS */ > > + > > +#if NBPFILTER > 0 > > +#include <net/bpf.h> > > +#endif > > + > > +#if NPF > 0 > > +#include <net/pfvar.h> > > +#endif > > + > > +#define SEC_MTU 1280 > > +#define SEC_MTU_MIN 1280 > > +#define SEC_MTU_MAX 32768 /* could get closer to 64k... */ > > + > > +struct sec_softc { > > + struct ifnet sc_if; > > + > > + struct task sc_send; > > + > > + unsigned int sc_unit; > > + SMR_SLIST_ENTRY(sec_softc) sc_entry; > > + struct refcnt sc_refs; > > +}; > > + > > +SMR_SLIST_HEAD(sec_bucket, sec_softc); > > + > > +static int sec_output(struct ifnet *, struct mbuf *, struct > sockaddr *, > > + struct rtentry *); > > +static int sec_enqueue(struct ifnet *, struct mbuf *); > > +static void sec_send(void *); > > +static void sec_start(struct ifnet *); > > + > > +static int sec_ioctl(struct ifnet *, u_long, caddr_t); > > +static int sec_up(struct sec_softc *); > > +static int sec_down(struct sec_softc *); > > + > > +static int sec_clone_create(struct if_clone *, int); > > +static int sec_clone_destroy(struct ifnet *); > > + > > +static struct tdb * > > + sec_tdb_get(unsigned int); > > +static void sec_tdb_gc(void *); > > + > > +static struct if_clone sec_cloner = > > + IF_CLONE_INITIALIZER("sec", sec_clone_create, sec_clone_destroy); > > + > > +static struct sec_bucket sec_map[256] __aligned(CACHELINESIZE); > > +static struct tdb *sec_tdbh[256] __aligned(CACHELINESIZE); > > + > > +static struct tdb *sec_tdb_gc_list; > > +static struct task sec_tdb_gc_task = > > + TASK_INITIALIZER(sec_tdb_gc, NULL); > > +static struct mutex sec_tdb_gc_mtx = > > + MUTEX_INITIALIZER(IPL_MPFLOOR); > > + > > +void > > +secattach(int n) > > +{ > > + if_clone_attach(&sec_cloner); > > +} > > + > > +static int > > +sec_clone_create(struct if_clone *ifc, int unit) > > +{ > > + struct sec_softc *sc; > > + struct ifnet *ifp; > > + > > + sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO); > > + > > + sc->sc_unit = unit; > > + > > + task_set(&sc->sc_send, sec_send, sc); > > + > > + snprintf(sc->sc_if.if_xname, sizeof sc->sc_if.if_xname, "%s%d", > > + ifc->ifc_name, unit); > > + > > + ifp = &sc->sc_if; > > + ifp->if_softc = sc; > > + ifp->if_type = IFT_TUNNEL; > > + ifp->if_mtu = SEC_MTU; > > + ifp->if_flags = IFF_POINTOPOINT|IFF_MULTICAST; > > + ifp->if_xflags = IFXF_CLONED; > > + ifp->if_bpf_mtap = p2p_bpf_mtap; > > + ifp->if_input = p2p_input; > > + ifp->if_output = sec_output; > > + ifp->if_enqueue = sec_enqueue; > > + ifp->if_start = sec_start; > > + ifp->if_ioctl = sec_ioctl; > > + ifp->if_rtrequest = p2p_rtrequest; > > + > > + if_counters_alloc(ifp); > > + if_attach(ifp); > > + if_alloc_sadl(ifp); > > + > > +#if NBPFILTER > 0 > > + bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t)); > > +#endif > > + > > + return (0); > > +} > > + > > +static int > > +sec_clone_destroy(struct ifnet *ifp) > > +{ > > + struct sec_softc *sc = ifp->if_softc; > > + > > + NET_LOCK(); > > + if (ISSET(ifp->if_flags, IFF_RUNNING)) > > + sec_down(sc); > > + NET_UNLOCK(); > > + > > + if_detach(ifp); > > + > > + free(sc, M_DEVBUF, sizeof(*sc)); > > + > > + return (0); > > +} > > + > > +static int > > +sec_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) > > +{ > > + struct sec_softc *sc = ifp->if_softc; > > + struct ifreq *ifr = (struct ifreq *)data; > > + int error = 0; > > + > > + switch (cmd) { > > + case SIOCSIFADDR: > > + break; > > + > > + case SIOCSIFFLAGS: > > + if (ISSET(ifp->if_flags, IFF_UP)) { > > + if (!ISSET(ifp->if_flags, IFF_RUNNING)) > > + error = sec_up(sc); > > + else > > + error = 0; > > + } else { > > + if (ISSET(ifp->if_flags, IFF_RUNNING)) > > + error = sec_down(sc); > > + } > > + break; > > + > > + case SIOCADDMULTI: > > + case SIOCDELMULTI: > > + break; > > + > > + case SIOCSIFMTU: > > + if (ifr->ifr_mtu < SEC_MTU_MIN || > > + ifr->ifr_mtu > SEC_MTU_MAX) { > > + error = EINVAL; > > + break; > > + } > > + > > + ifp->if_mtu = ifr->ifr_mtu; > > + break; > > + > > + default: > > + error = ENOTTY; > > + break; > > + } > > + > > + return (error); > > +} > > + > > +static int > > +sec_up(struct sec_softc *sc) > > +{ > > + struct ifnet *ifp = &sc->sc_if; > > + unsigned int idx = stoeplitz_h32(sc->sc_unit) % nitems(sec_map); > > + > > + NET_ASSERT_LOCKED(); > > + > > + SET(ifp->if_flags, IFF_RUNNING); > > + refcnt_init(&sc->sc_refs); > > + > > + SMR_SLIST_INSERT_HEAD_LOCKED(&sec_map[idx], sc, sc_entry); > > + > > + return (0); > > +} > > + > > +static int > > +sec_down(struct sec_softc *sc) > > +{ > > + struct ifnet *ifp = &sc->sc_if; > > + unsigned int idx = stoeplitz_h32(sc->sc_unit) % nitems(sec_map); > > + > > + NET_ASSERT_LOCKED(); > > + > > + CLR(ifp->if_flags, IFF_RUNNING); > > + > > + SMR_SLIST_REMOVE_LOCKED(&sec_map[idx], sc, sec_softc, sc_entry); > > + > > + smr_barrier(); > > + taskq_del_barrier(systq, &sc->sc_send); > > + > > + refcnt_finalize(&sc->sc_refs, "secdown"); > > + > > + return (0); > > +} > > + > > +static int > > +sec_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, > > + struct rtentry *rt) > > +{ > > + struct m_tag *mtag; > > + int error = 0; > > + > > + if (!ISSET(ifp->if_flags, IFF_RUNNING)) { > > + error = ENETDOWN; > > + goto drop; > > + } > > + > > + switch (dst->sa_family) { > > + case AF_INET: > > +#ifdef INET6 > > + case AF_INET6: > > +#endif > > +#ifdef MPLS > > + case AF_MPLS: > > +#endif > > + break; > > + default: > > + error = EAFNOSUPPORT; > > + goto drop; > > + } > > + > > + mtag = NULL; > > + while ((mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) != NULL) { > > + if (ifp->if_index == *(int *)(mtag + 1)) { > > + error = EIO; > > + goto drop; > > + } > > + } > > + > > + m->m_pkthdr.ph_family = dst->sa_family; > > + > > + error = if_enqueue(ifp, m); > > + if (error != 0) > > + counters_inc(ifp->if_counters, ifc_oerrors); > > + > > + return (error); > > + > > +drop: > > + m_freem(m); > > + return (error); > > +} > > + > > +static int > > +sec_enqueue(struct ifnet *ifp, struct mbuf *m) > > +{ > > + struct sec_softc *sc = ifp->if_softc; > > + struct ifqueue *ifq = &ifp->if_snd; > > + int error; > > + > > + error = ifq_enqueue(ifq, m); > > + if (error) > > + return (error); > > + > > + task_add(systq, &sc->sc_send); > > + > > + return (0); > > +} > > + > > +static void > > +sec_send(void *arg) > > +{ > > + struct sec_softc *sc = arg; > > + struct ifnet *ifp = &sc->sc_if; > > + struct ifqueue *ifq = &ifp->if_snd; > > + struct tdb *tdb; > > + struct mbuf *m; > > + int error; > > + > > + if (!ISSET(ifp->if_flags, IFF_RUNNING)) > > + return; > > + > > + tdb = sec_tdb_get(sc->sc_unit); > > + if (tdb == NULL) > > + goto purge; > > + > > + NET_LOCK(); > > + while ((m = ifq_dequeue(ifq)) != NULL) { > > + CLR(m->m_flags, M_BCAST|M_MCAST); > > + > > +#if NPF > 0 > > + pf_pkt_addr_changed(m); > > +#endif > > + > > + error = ipsp_process_packet(m, tdb, > > + m->m_pkthdr.ph_family, /* already tunnelled? */ 0); > > + if (error != 0) > > + counters_inc(ifp->if_counters, ifc_oerrors); > > + } > > + NET_UNLOCK(); > > + > > + tdb_unref(tdb); > > + return; > > + > > +purge: > > + counters_add(ifp->if_counters, ifc_oerrors, ifq_purge(ifq)); > > +} > > + > > +static void > > +sec_start(struct ifnet *ifp) > > +{ > > + counters_add(ifp->if_counters, ifc_oerrors, > ifq_purge(&ifp->if_snd)); > > +} > > + > > +/* > > + * ipsec_input handling > > + */ > > + > > +struct sec_softc * > > +sec_get(unsigned int unit) > > +{ > > + unsigned int idx = stoeplitz_h32(unit) % nitems(sec_map); > > + struct sec_bucket *sb = &sec_map[idx]; > > + struct sec_softc *sc; > > + > > + smr_read_enter(); > > + SMR_SLIST_FOREACH(sc, sb, sc_entry) { > > + if (sc->sc_unit == unit) { > > + refcnt_take(&sc->sc_refs); > > + break; > > + } > > + } > > + smr_read_leave(); > > + > > + return (sc); > > +} > > + > > +void > > +sec_input(struct sec_softc *sc, int af, int proto, struct mbuf *m) > > +{ > > + struct ip *iph; > > + int hlen; > > + > > + switch (af) { > > + case AF_INET: > > + iph = mtod(m, struct ip *); > > + hlen = iph->ip_hl << 2; > > + break; > > +#ifdef INET6 > > + case AF_INET6: > > + hlen = sizeof(struct ip6_hdr); > > + break; > > +#endif > > + default: > > + unhandled_af(af); > > + } > > + > > + m_adj(m, hlen); > > + > > + switch (proto) { > > + case IPPROTO_IPV4: > > + af = AF_INET; > > + break; > > + case IPPROTO_IPV6: > > + af = AF_INET6; > > + break; > > + case IPPROTO_MPLS: > > + af = AF_MPLS; > > + break; > > + default: > > + af = AF_UNSPEC; > > + break; > > + } > > + > > + m->m_pkthdr.ph_family = af; > > + > > + if_vinput(&sc->sc_if, m); > > +} > > + > > +void > > +sec_put(struct sec_softc *sc) > > +{ > > + refcnt_rele_wake(&sc->sc_refs); > > +} > > + > > +/* > > + * tdb handling > > + */ > > + > > +static int > > +sec_tdb_valid(struct tdb *tdb) > > +{ > > + KASSERT(ISSET(tdb->tdb_flags, TDBF_IFACE)); > > + > > + if (!ISSET(tdb->tdb_flags, TDBF_TUNNELING)) > > + return (0); > > + if (ISSET(tdb->tdb_flags, TDBF_INVALID)) > > + return (0); > > + > > + if (tdb->tdb_iface_dir != IPSP_DIRECTION_OUT) > > + return (0); > > + > > + return (1); > > +} > > + > > +/* > > + * these are called from netinet/ip_ipsp.c with tdb_sadb_mtx held, > > + * which we rely on to serialise modifications to the sec_tdbh. > > + */ > > + > > +void > > +sec_tdb_insert(struct tdb *tdb) > > +{ > > + unsigned int idx; > > + struct tdb **tdbp; > > + struct tdb *ltdb; > > + > > + if (!sec_tdb_valid(tdb)) > > + return; > > + > > + idx = stoeplitz_h32(tdb->tdb_iface) % nitems(sec_tdbh); > > + tdbp = &sec_tdbh[idx]; > > + > > + tdb_ref(tdb); /* take a ref for the SMR pointer */ > > + > > + /* wire the tdb into the head of the list */ > > + ltdb = SMR_PTR_GET_LOCKED(tdbp); > > + SMR_PTR_SET_LOCKED(&tdb->tdb_dnext, ltdb); > > + SMR_PTR_SET_LOCKED(tdbp, tdb); > > +} > > + > > +void > > +sec_tdb_remove(struct tdb *tdb) > > +{ > > + struct tdb **tdbp; > > + struct tdb *ltdb; > > + unsigned int idx; > > + > > + if (!sec_tdb_valid(tdb)) > > + return; > > + > > + idx = stoeplitz_h32(tdb->tdb_iface) % nitems(sec_tdbh); > > + tdbp = &sec_tdbh[idx]; > > + > > + while ((ltdb = SMR_PTR_GET_LOCKED(tdbp)) != NULL) { > > + if (ltdb == tdb) { > > + /* take the tdb out of the list */ > > + ltdb = SMR_PTR_GET_LOCKED(&tdb->tdb_dnext); > > + SMR_PTR_SET_LOCKED(tdbp, ltdb); > > + > > + /* move the ref to the gc */ > > + > > + mtx_enter(&sec_tdb_gc_mtx); > > + tdb->tdb_dnext = sec_tdb_gc_list; > > + sec_tdb_gc_list = tdb; > > + mtx_leave(&sec_tdb_gc_mtx); > > + task_add(systq, &sec_tdb_gc_task); > > + > > + return; > > + } > > + > > + tdbp = <db->tdb_dnext; > > + } > > + > > + panic("%s: unable to find tdb %p", __func__, tdb); > > +} > > + > > +static void > > +sec_tdb_gc(void *null) > > +{ > > + struct tdb *tdb, *ntdb; > > + > > + mtx_enter(&sec_tdb_gc_mtx); > > + tdb = sec_tdb_gc_list; > > + sec_tdb_gc_list = NULL; > > + mtx_leave(&sec_tdb_gc_mtx); > > + > > + if (tdb == NULL) > > + return; > > + > > + smr_barrier(); > > + > > + NET_LOCK(); > > + do { > > + ntdb = tdb->tdb_dnext; > > + tdb_unref(tdb); > > + tdb = ntdb; > > + } while (tdb != NULL); > > + NET_UNLOCK(); > > +} > > + > > +struct tdb * > > +sec_tdb_get(unsigned int unit) > > +{ > > + unsigned int idx; > > + struct tdb **tdbp; > > + struct tdb *tdb; > > + > > + idx = stoeplitz_h32(unit) % nitems(sec_map); > > + tdbp = &sec_tdbh[idx]; > > + > > + smr_read_enter(); > > + while ((tdb = SMR_PTR_GET(tdbp)) != NULL) { > > + KASSERT(ISSET(tdb->tdb_flags, TDBF_IFACE)); > > + if (!ISSET(tdb->tdb_flags, TDBF_DELETED) && > > + tdb->tdb_iface == unit) { > > + tdb_ref(tdb); > > + break; > > + } > > + > > + tdbp = &tdb->tdb_dnext; > > + } > > + smr_read_leave(); > > + > > + return (tdb); > > +} > > Index: sys/net/if_sec.h > > =================================================================== > > RCS file: sys/net/if_sec.h > > diff -N sys/net/if_sec.h > > --- /dev/null 1 Jan 1970 00:00:00 -0000 > > +++ sys/net/if_sec.h 29 Jun 2023 03:09:45 -0000 > > @@ -0,0 +1,44 @@ > > +/* $OpenBSD$ */ > > + > > +/* > > + * Copyright (c) 2023 David Gwynne <d...@openbsd.org> > > + * > > + * Permission to use, copy, modify, and distribute this software for any > > + * purpose with or without fee is hereby granted, provided that the > above > > + * copyright notice and this permission notice appear in all copies. > > + * > > + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL > WARRANTIES > > + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > > + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE > FOR > > + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY > DAMAGES > > + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > > + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT > OF > > + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > > + */ > > + > > +#ifndef _NET_IF_SEC_H > > +#define _NET_IF_SEC_H > > + > > +#ifdef _KERNEL > > +struct sec_softc; > > +struct tdb; > > + > > +/* > > + * let the IPsec stack hand packets to sec(4) for input > > + */ > > + > > +struct sec_softc *sec_get(unsigned int); > > +void sec_input(struct sec_softc * , int, int, > > + struct mbuf *); > > +void sec_put(struct sec_softc *); > > + > > +/* > > + * let the IPsec stack give tdbs to sec(4) for output > > + */ > > + > > +void sec_tdb_insert(struct tdb *); > > +void sec_tdb_remove(struct tdb *); > > + > > +#endif /* _KERNEL */ > > + > > +#endif /* _NET_IF_SEC_H */ > > Index: sys/net/pfkeyv2.c > > =================================================================== > > RCS file: /cvs/src/sys/net/pfkeyv2.c,v > > retrieving revision 1.256 > > diff -u -p -r1.256 pfkeyv2.c > > --- sys/net/pfkeyv2.c 22 Apr 2023 20:51:56 -0000 1.256 > > +++ sys/net/pfkeyv2.c 29 Jun 2023 03:09:45 -0000 > > @@ -868,6 +868,9 @@ pfkeyv2_get(struct tdb *tdb, void **head > > i += sizeof(struct sadb_x_tap); > > #endif > > > > + if (ISSET(tdb->tdb_flags, TDBF_IFACE)) > > + i += sizeof(struct sadb_x_iface); > > + > > if (lenp) > > *lenp = i; > > > > @@ -979,6 +982,12 @@ pfkeyv2_get(struct tdb *tdb, void **head > > } > > #endif > > > > + /* Export sec(4) interface information, if present */ > > + if (ISSET(tdb->tdb_flags, TDBF_IFACE)) { > > + headers[SADB_X_EXT_IFACE] = p; > > + export_iface(&p, tdb); > > + } > > + > > headers[SADB_X_EXT_COUNTER] = p; > > export_counter(&p, tdb); > > > > @@ -1360,6 +1369,7 @@ pfkeyv2_dosend(struct socket *so, void * > > import_tag(newsa, headers[SADB_X_EXT_TAG]); > > import_tap(newsa, headers[SADB_X_EXT_TAP]); > > #endif > > + import_iface(newsa, headers[SADB_X_EXT_IFACE]); > > > > /* Exclude sensitive data from reply message. */ > > headers[SADB_EXT_KEY_AUTH] = NULL; > > @@ -1411,6 +1421,8 @@ pfkeyv2_dosend(struct socket *so, void * > > import_tag(sa2, headers[SADB_X_EXT_TAG]); > > import_tap(sa2, headers[SADB_X_EXT_TAP]); > > #endif > > + import_iface(sa2, headers[SADB_X_EXT_IFACE]); > > + > > if (headers[SADB_EXT_ADDRESS_SRC] || > > headers[SADB_EXT_ADDRESS_PROXY]) { > > mtx_enter(&tdb_sadb_mtx); > > @@ -1535,6 +1547,7 @@ pfkeyv2_dosend(struct socket *so, void * > > import_tag(newsa, headers[SADB_X_EXT_TAG]); > > import_tap(newsa, headers[SADB_X_EXT_TAP]); > > #endif > > + import_iface(newsa, headers[SADB_X_EXT_IFACE]); > > > > /* Exclude sensitive data from reply message. */ > > headers[SADB_EXT_KEY_AUTH] = NULL; > > Index: sys/net/pfkeyv2.h > > =================================================================== > > RCS file: /cvs/src/sys/net/pfkeyv2.h,v > > retrieving revision 1.93 > > diff -u -p -r1.93 pfkeyv2.h > > --- sys/net/pfkeyv2.h 27 Aug 2022 20:28:01 -0000 1.93 > > +++ sys/net/pfkeyv2.h 29 Jun 2023 03:09:45 -0000 > > @@ -252,6 +252,14 @@ struct sadb_x_mtu { > > uint32_t sadb_x_mtu_mtu; > > }; > > > > +struct sadb_x_iface { > > + uint16_t sadb_x_iface_len; > > + uint16_t sadb_x_iface_exttype; > > + uint32_t sadb_x_iface_unit; > > + uint8_t sadb_x_iface_direction; > > + uint8_t sadb_x_iface_reserved[7]; > > +}; > > + > > #ifdef _KERNEL > > #define SADB_X_GETSPROTO(x) \ > > ( (x) == SADB_SATYPE_AH ? IPPROTO_AH :\ > > @@ -300,7 +308,8 @@ struct sadb_x_mtu { > > #define SADB_X_EXT_RDOMAIN 37 > > #define SADB_X_EXT_MTU 38 > > #define SADB_X_EXT_REPLAY 39 > > -#define SADB_EXT_MAX 39 > > +#define SADB_X_EXT_IFACE 40 > > +#define SADB_EXT_MAX 40 > > > > /* Fix pfkeyv2.c struct pfkeyv2_socket if SATYPE_MAX > 31 */ > > #define SADB_SATYPE_UNSPEC 0 > > @@ -438,6 +447,7 @@ void export_mtu(void **, struct tdb *); > > void export_tap(void **, struct tdb *); > > void export_satype(void **, struct tdb *); > > void export_counter(void **, struct tdb *); > > +void export_iface(void **, struct tdb *); > > > > void import_address(struct sockaddr *, struct sadb_address *); > > void import_identities(struct ipsec_ids **, int, struct sadb_ident *, > > @@ -452,6 +462,7 @@ void import_udpencap(struct tdb *, struc > > void import_tag(struct tdb *, struct sadb_x_tag *); > > void import_rdomain(struct tdb *, struct sadb_x_rdomain *); > > void import_tap(struct tdb *, struct sadb_x_tap *); > > +void import_iface(struct tdb *, struct sadb_x_iface *); > > > > extern const uint64_t sadb_exts_allowed_out[SADB_MAX+1]; > > extern const uint64_t sadb_exts_required_out[SADB_MAX+1]; > > Index: sys/net/pfkeyv2_convert.c > > =================================================================== > > RCS file: /cvs/src/sys/net/pfkeyv2_convert.c,v > > retrieving revision 1.79 > > diff -u -p -r1.79 pfkeyv2_convert.c > > --- sys/net/pfkeyv2_convert.c 20 Jan 2022 17:13:12 -0000 1.79 > > +++ sys/net/pfkeyv2_convert.c 29 Jun 2023 03:09:45 -0000 > > @@ -951,6 +951,30 @@ export_tap(void **p, struct tdb *tdb) > > } > > #endif > > > > +/* Import interface information for SA */ > > +void > > +import_iface(struct tdb *tdb, struct sadb_x_iface *siface) > > +{ > > + if (siface != NULL) { > > + SET(tdb->tdb_flags, TDBF_IFACE); > > + tdb->tdb_iface = siface->sadb_x_iface_unit; > > + tdb->tdb_iface_dir = siface->sadb_x_iface_direction; > > + } > > +} > > + > > +/* Export interface information for SA */ > > +void > > +export_iface(void **p, struct tdb *tdb) > > +{ > > + struct sadb_x_iface *siface = (struct sadb_x_iface *)*p; > > + > > + siface->sadb_x_iface_len = sizeof(*siface) / sizeof(uint64_t); > > + siface->sadb_x_iface_unit = tdb->tdb_iface; > > + siface->sadb_x_iface_direction = tdb->tdb_iface_dir; > > + > > + *p += sizeof(*siface); > > +} > > + > > void > > export_satype(void **p, struct tdb *tdb) > > { > > Index: sys/net/pfkeyv2_parsemessage.c > > =================================================================== > > RCS file: /cvs/src/sys/net/pfkeyv2_parsemessage.c,v > > retrieving revision 1.60 > > diff -u -p -r1.60 pfkeyv2_parsemessage.c > > --- sys/net/pfkeyv2_parsemessage.c 14 Jul 2021 22:39:26 -0000 > 1.60 > > +++ sys/net/pfkeyv2_parsemessage.c 29 Jun 2023 03:09:45 -0000 > > @@ -135,6 +135,7 @@ > > #define BITMAP_X_COUNTER (1LL << SADB_X_EXT_COUNTER) > > #define BITMAP_X_MTU (1LL << SADB_X_EXT_MTU) > > #define BITMAP_X_REPLAY (1LL << SADB_X_EXT_REPLAY) > > +#define BITMAP_X_IFACE (1LL << SADB_X_EXT_IFACE) > > > > uint64_t sadb_exts_allowed_in[SADB_MAX+1] = > > { > > @@ -143,9 +144,9 @@ uint64_t sadb_exts_allowed_in[SADB_MAX+1 > > /* GETSPI */ > > BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_SPIRANGE, > > /* UPDATE */ > > - BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | > BITMAP_ADDRESS_PROXY | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_FLOW | > BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN, > > + BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | > BITMAP_ADDRESS_PROXY | BITMAP_KEY | BITMAP_IDENTITY | BITMAP_X_FLOW | > BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN | > BITMAP_X_IFACE, > > /* ADD */ > > - BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | > BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | > BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN, > > + BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | > BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP | > BITMAP_X_LIFETIME_LASTUSE | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN > | BITMAP_X_IFACE, > > /* DELETE */ > > BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | > BITMAP_X_RDOMAIN, > > /* GET */ > > @@ -215,13 +216,13 @@ const uint64_t sadb_exts_allowed_out[SAD > > /* GETSPI */ > > BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST, > > /* UPDATE */ > > - BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | > BITMAP_ADDRESS_PROXY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP > | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN, > > + BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | > BITMAP_ADDRESS_PROXY | BITMAP_IDENTITY | BITMAP_X_FLOW | BITMAP_X_UDPENCAP > | BITMAP_X_TAG | BITMAP_X_TAP | BITMAP_X_RDOMAIN | BITMAP_X_IFACE, > > /* ADD */ > > - BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | > BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | > BITMAP_X_RDOMAIN, > > + BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_IDENTITY | > BITMAP_X_FLOW | BITMAP_X_UDPENCAP | BITMAP_X_TAG | BITMAP_X_TAP | > BITMAP_X_RDOMAIN | BITMAP_X_IFACE, > > /* DELETE */ > > BITMAP_SA | BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | > BITMAP_X_RDOMAIN, > > /* GET */ > > - BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | > BITMAP_IDENTITY | BITMAP_X_UDPENCAP | BITMAP_X_LIFETIME_LASTUSE | > BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | > BITMAP_X_FLOW_TYPE | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_TAG | > BITMAP_X_TAP | BITMAP_X_COUNTER | BITMAP_X_RDOMAIN | BITMAP_X_MTU | > BITMAP_X_REPLAY, > > + BITMAP_SA | BITMAP_LIFETIME | BITMAP_ADDRESS | BITMAP_KEY | > BITMAP_IDENTITY | BITMAP_X_UDPENCAP | BITMAP_X_LIFETIME_LASTUSE | > BITMAP_X_SRC_MASK | BITMAP_X_DST_MASK | BITMAP_X_PROTOCOL | > BITMAP_X_FLOW_TYPE | BITMAP_X_SRC_FLOW | BITMAP_X_DST_FLOW | BITMAP_X_TAG | > BITMAP_X_TAP | BITMAP_X_COUNTER | BITMAP_X_RDOMAIN | BITMAP_X_MTU | > BITMAP_X_REPLAY | BITMAP_X_IFACE, > > /* ACQUIRE */ > > BITMAP_ADDRESS_SRC | BITMAP_ADDRESS_DST | BITMAP_IDENTITY | > BITMAP_PROPOSAL, > > /* REGISTER */ > > @@ -881,6 +882,12 @@ pfkeyv2_parsemessage(void *p, int len, v > > } > > break; > > #endif > > + case SADB_X_EXT_IFACE: > > + if (i != sizeof(struct sadb_x_iface)) { > > + DPRINTF("bad IFACE header length"); > > + return (EINVAL); > > + } > > + break; > > default: > > DPRINTF("unknown extension header type %d", > > sadb_ext->sadb_ext_type); > > Index: sys/netinet/ip_ipsp.c > > =================================================================== > > RCS file: /cvs/src/sys/netinet/ip_ipsp.c,v > > retrieving revision 1.275 > > diff -u -p -r1.275 ip_ipsp.c > > --- sys/netinet/ip_ipsp.c 11 Nov 2022 18:09:58 -0000 1.275 > > +++ sys/netinet/ip_ipsp.c 29 Jun 2023 03:09:45 -0000 > > @@ -39,6 +39,7 @@ > > > > #include "pf.h" > > #include "pfsync.h" > > +#include "sec.h" > > > > #include <sys/param.h> > > #include <sys/systm.h> > > @@ -67,6 +68,10 @@ > > #include <net/if_pfsync.h> > > #endif > > > > +#if NSEC > 0 > > +#include <net/if_sec.h> > > +#endif > > + > > #include <netinet/ip_ipsp.h> > > #include <net/pfkeyv2.h> > > > > @@ -852,14 +857,6 @@ puttdb_locked(struct tdb *tdbp) > > tdbp->tdb_hnext = tdbh[hashval]; > > tdbh[hashval] = tdbp; > > > > - hashval = tdb_hash(0, &tdbp->tdb_dst, tdbp->tdb_sproto); > > - tdbp->tdb_dnext = tdbdst[hashval]; > > - tdbdst[hashval] = tdbp; > > - > > - hashval = tdb_hash(0, &tdbp->tdb_src, tdbp->tdb_sproto); > > - tdbp->tdb_snext = tdbsrc[hashval]; > > - tdbsrc[hashval] = tdbp; > > - > > tdb_count++; > > #ifdef IPSEC > > if ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_TUNNELING)) == > TDBF_TUNNELING) > > @@ -867,6 +864,21 @@ puttdb_locked(struct tdb *tdbp) > > #endif /* IPSEC */ > > > > ipsec_last_added = getuptime(); > > + > > + if (ISSET(tdbp->tdb_flags, TDBF_IFACE)) { > > +#if NSEC > 0 > > + sec_tdb_insert(tdbp); > > +#endif > > + return; > > + } > > + > > + hashval = tdb_hash(0, &tdbp->tdb_dst, tdbp->tdb_sproto); > > + tdbp->tdb_dnext = tdbdst[hashval]; > > + tdbdst[hashval] = tdbp; > > + > > + hashval = tdb_hash(0, &tdbp->tdb_src, tdbp->tdb_sproto); > > + tdbp->tdb_snext = tdbsrc[hashval]; > > + tdbsrc[hashval] = tdbp; > > } > > > > void > > @@ -901,6 +913,22 @@ tdb_unlink_locked(struct tdb *tdbp) > > > > tdbp->tdb_hnext = NULL; > > > > + tdb_count--; > > +#ifdef IPSEC > > + if ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_TUNNELING)) == > > + TDBF_TUNNELING) { > > + ipsecstat_dec(ipsec_tunnels); > > + ipsecstat_inc(ipsec_prevtunnels); > > + } > > +#endif /* IPSEC */ > > + > > + if (ISSET(tdbp->tdb_flags, TDBF_IFACE)) { > > +#if NSEC > 0 > > + sec_tdb_remove(tdbp); > > +#endif > > + return; > > + } > > + > > hashval = tdb_hash(0, &tdbp->tdb_dst, tdbp->tdb_sproto); > > > > if (tdbdst[hashval] == tdbp) { > > @@ -932,14 +960,6 @@ tdb_unlink_locked(struct tdb *tdbp) > > } > > > > tdbp->tdb_snext = NULL; > > - tdb_count--; > > -#ifdef IPSEC > > - if ((tdbp->tdb_flags & (TDBF_INVALID|TDBF_TUNNELING)) == > > - TDBF_TUNNELING) { > > - ipsecstat_dec(ipsec_tunnels); > > - ipsecstat_inc(ipsec_prevtunnels); > > - } > > -#endif /* IPSEC */ > > } > > > > void > > Index: sys/netinet/ip_ipsp.h > > =================================================================== > > RCS file: /cvs/src/sys/netinet/ip_ipsp.h,v > > retrieving revision 1.240 > > diff -u -p -r1.240 ip_ipsp.h > > --- sys/netinet/ip_ipsp.h 14 Jul 2022 13:52:10 -0000 1.240 > > +++ sys/netinet/ip_ipsp.h 29 Jun 2023 03:09:45 -0000 > > @@ -356,6 +356,7 @@ struct tdb { /* > tunnel descriptor blo > > #define TDBF_PFSYNC_RPL 0x80000 /* Replay counter should > be bumped */ > > #define TDBF_ESN 0x100000 /* 64-bit sequence > numbers (ESN) */ > > #define TDBF_PFSYNC_SNAPPED 0x200000 /* entry is being > dispatched to peer */ > > +#define TDBF_IFACE 0x400000 /* entry policy is via > sec(4) */ > > > > #define TDBF_BITS ("\20" \ > > "\1UNIQUE\2TIMER\3BYTES\4ALLOCATIONS" \ > > @@ -363,7 +364,7 @@ struct tdb { /* > tunnel descriptor blo > > "\11SOFT_BYTES\12SOFT_ALLOCATIONS\13SOFT_FIRSTUSE\14PFS" \ > > "\15TUNNELING" \ > > "\21USEDTUNNEL\22UDPENCAP\23PFSYNC\24PFSYNC_RPL" \ > > - "\25ESN") > > + "\25ESN" "\26IFACE") > > > > u_int32_t tdb_flags; /* [m] Flags related to this TDB > */ > > > > @@ -406,6 +407,7 @@ struct tdb { /* > tunnel descriptor blo > > u_int8_t tdb_wnd; /* Replay window */ > > u_int8_t tdb_satype; /* SA type (RFC2367, PF_KEY) */ > > u_int8_t tdb_updates; /* pfsync update counter */ > > + u_int8_t tdb_iface_dir; /* [I] sec(4) iface direction */ > > > > union sockaddr_union tdb_dst; /* [N] Destination > address */ > > union sockaddr_union tdb_src; /* [N] Source address */ > > @@ -431,6 +433,7 @@ struct tdb { /* > tunnel descriptor blo > > > > u_int16_t tdb_tag; /* Packet filter tag */ > > u_int32_t tdb_tap; /* Alternate enc(4) > interface */ > > + unsigned int tdb_iface; /* [I] sec(4) iface */ > > > > u_int tdb_rdomain; /* [I] Routing domain */ > > u_int tdb_rdomain_post; /* [I] Change domain */ > > Index: sys/netinet/ipsec_input.c > > =================================================================== > > RCS file: /cvs/src/sys/netinet/ipsec_input.c,v > > retrieving revision 1.204 > > diff -u -p -r1.204 ipsec_input.c > > --- sys/netinet/ipsec_input.c 13 May 2023 13:35:17 -0000 1.204 > > +++ sys/netinet/ipsec_input.c 29 Jun 2023 03:09:45 -0000 > > @@ -36,6 +36,7 @@ > > */ > > > > #include "pf.h" > > +#include "sec.h" > > > > #include <sys/param.h> > > #include <sys/systm.h> > > @@ -63,6 +64,10 @@ > > #include <net/pfvar.h> > > #endif > > > > +#if NSEC > 0 > > +#include <net/if_sec.h> > > +#endif > > + > > #ifdef INET6 > > #include <netinet6/in6_var.h> > > #include <netinet/ip6.h> > > @@ -544,6 +549,22 @@ ipsec_common_input_cb(struct mbuf **mp, > > } > > } > > #endif > > + > > + if (ISSET(tdbp->tdb_flags, TDBF_IFACE)) { > > +#if NSEC > 0 > > + if (ISSET(tdbp->tdb_flags, TDBF_TUNNELING) && > > + tdbp->tdb_iface_dir == IPSP_DIRECTION_IN) { > > + struct sec_softc *sc = sec_get(tdbp->tdb_iface); > > + if (sc == NULL) > > + goto baddone; > > + > > + sec_input(sc, af, prot, m); > > + sec_put(sc); > > + return IPPROTO_DONE; > > + } > > +#endif /* NSEC > 0 */ > > + goto baddone; > > + } > > > > #if NPF > 0 > > /* > > >