diff options
Diffstat (limited to 'sys/net/pfkeyv2.c')
-rw-r--r-- | sys/net/pfkeyv2.c | 52 |
1 files changed, 45 insertions, 7 deletions
diff --git a/sys/net/pfkeyv2.c b/sys/net/pfkeyv2.c index 0094555edba..7ce2f0da201 100644 --- a/sys/net/pfkeyv2.c +++ b/sys/net/pfkeyv2.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pfkeyv2.c,v 1.199 2020/03/18 11:56:40 mpi Exp $ */ +/* $OpenBSD: pfkeyv2.c,v 1.200 2020/04/23 19:38:08 tobhe Exp $ */ /* * @(#)COPYRIGHT 1.1 (NRL) 17 January 1995 @@ -855,6 +855,9 @@ pfkeyv2_get(struct tdb *tdb, void **headers, void **buffer, int *lenp) if (tdb->tdb_udpencap_port) i += sizeof(struct sadb_x_udpencap); + if (tdb->tdb_rdomain != tdb->tdb_rdomain_post) + i += sizeof(struct sadb_x_rdomain); + #if NPF > 0 if (tdb->tdb_tag) i += sizeof(struct sadb_x_tag) + PADUP(PF_TAG_NAME_SIZE); @@ -945,6 +948,12 @@ pfkeyv2_get(struct tdb *tdb, void **headers, void **buffer, int *lenp) export_udpencap(&p, tdb); } + /* Export rdomain switch, if present */ + if (tdb->tdb_rdomain != tdb->tdb_rdomain_post) { + headers[SADB_X_EXT_RDOMAIN] = p; + export_rdomain(&p, tdb); + } + #if NPF > 0 /* Export tag information, if present */ if (tdb->tdb_tag) { @@ -1109,7 +1118,8 @@ pfkeyv2_send(struct socket *so, void *message, int len) struct sadb_supported *ssup; struct sadb_ident *sid, *did; struct srp_ref sr; - u_int rdomain; + struct sadb_x_rdomain *srdomain; + u_int rdomain = 0; int promisc, s; mtx_enter(&pfkeyv2_mtx); @@ -1155,7 +1165,7 @@ pfkeyv2_send(struct socket *so, void *message, int len) /* Send to all promiscuous listeners */ SRPL_FOREACH(bkp, &sr, &pkptable.pkp_list, kcb_list) { - if (bkp->kcb_rdomain != rdomain) + if (bkp->kcb_rdomain != kp->kcb_rdomain) continue; s = keylock(bkp); @@ -1177,6 +1187,17 @@ pfkeyv2_send(struct socket *so, void *message, int len) if ((rval = pfkeyv2_parsemessage(message, len, headers)) != 0) goto ret; + /* use specified rdomain */ + srdomain = (struct sadb_x_rdomain *) headers[SADB_X_EXT_RDOMAIN]; + if (srdomain) { + if (!rtable_exists(srdomain->sadb_x_rdomain_dom1) || + !rtable_exists(srdomain->sadb_x_rdomain_dom2)) { + rval = EINVAL; + goto ret; + } + rdomain = srdomain->sadb_x_rdomain_dom1; + } + smsg = (struct sadb_msg *) headers[0]; switch (smsg->sadb_msg_type) { case SADB_GETSPI: /* Reserve an SPI */ @@ -1316,6 +1337,7 @@ pfkeyv2_send(struct socket *so, void *message, int len) headers[SADB_X_EXT_PROTOCOL], headers[SADB_X_EXT_FLOW_TYPE]); import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]); + import_rdomain(newsa, headers[SADB_X_EXT_RDOMAIN]); #if NPF > 0 import_tag(newsa, headers[SADB_X_EXT_TAG]); import_tap(newsa, headers[SADB_X_EXT_TAP]); @@ -1486,6 +1508,7 @@ pfkeyv2_send(struct socket *so, void *message, int len) headers[SADB_X_EXT_PROTOCOL], headers[SADB_X_EXT_FLOW_TYPE]); import_udpencap(newsa, headers[SADB_X_EXT_UDPENCAP]); + import_rdomain(newsa, headers[SADB_X_EXT_RDOMAIN]); #if NPF > 0 import_tag(newsa, headers[SADB_X_EXT_TAG]); import_tap(newsa, headers[SADB_X_EXT_TAP]); @@ -1720,7 +1743,9 @@ pfkeyv2_send(struct socket *so, void *message, int len) sizeof(struct sadb_address)); sa_proto = (struct sadb_protocol *) headers[SADB_X_EXT_SATYPE2]; - tdb2 = gettdb(rdomain, ssa->sadb_sa_spi, sunionp, + /* optionally fetch tdb2 from rdomain2 */ + tdb2 = gettdb(srdomain ? srdomain->sadb_x_rdomain_dom2 : rdomain, + ssa->sadb_sa_spi, sunionp, SADB_X_GETSPROTO(sa_proto->sadb_protocol_proto)); if (tdb2 == NULL) { rval = ESRCH; @@ -1983,7 +2008,7 @@ pfkeyv2_send(struct socket *so, void *message, int len) goto ret; SRPL_FOREACH(bkp, &sr, &pkptable.pkp_list, kcb_list) { - if (bkp == kp || bkp->kcb_rdomain != rdomain) + if (bkp == kp || bkp->kcb_rdomain != kp->kcb_rdomain) continue; if (!smsg->sadb_msg_seq || @@ -2061,7 +2086,7 @@ ret: } } - rval = pfkeyv2_sendmessage(headers, mode, so, 0, 0, rdomain); + rval = pfkeyv2_sendmessage(headers, mode, so, 0, 0, kp->kcb_rdomain); realret: @@ -2360,6 +2385,12 @@ pfkeyv2_expire(struct tdb *tdb, u_int16_t type) if ((rval = pfkeyv2_sendmessage(headers, PFKEYV2_SENDMESSAGE_BROADCAST, NULL, 0, 0, tdb->tdb_rdomain)) != 0) goto ret; + /* XXX */ + if (tdb->tdb_rdomain != tdb->tdb_rdomain_post) + if ((rval = pfkeyv2_sendmessage(headers, + PFKEYV2_SENDMESSAGE_BROADCAST, NULL, 0, 0, + tdb->tdb_rdomain_post)) != 0) + goto ret; rval = 0; @@ -2620,6 +2651,7 @@ pfkeyv2_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, struct pfkeyv2_sysctl_walk w; int error = EINVAL; u_int rdomain; + u_int tableid; if (new) return (EPERM); @@ -2630,7 +2662,13 @@ pfkeyv2_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, w.w_where = oldp; w.w_len = oldp ? *oldlenp : 0; - rdomain = rtable_l2(curproc->p_p->ps_rtableid); + if (namelen == 3) { + tableid = name[2]; + if (!rtable_exists(tableid)) + return (ENOENT); + } else + tableid = curproc->p_p->ps_rtableid; + rdomain = rtable_l2(tableid); switch(w.w_op) { case NET_KEY_SADB_DUMP: |