From owner-dev-commits-src-branches@freebsd.org Fri Jul 16 11:54:05 2021 Return-Path: Delivered-To: dev-commits-src-branches@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id A58C566040A; Fri, 16 Jul 2021 11:54:05 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4GR8lw0KB6z4qYh; Fri, 16 Jul 2021 11:54:03 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 092F31CAA8; Fri, 16 Jul 2021 11:54:03 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 16GBs2DJ016412; Fri, 16 Jul 2021 11:54:02 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 16GBs2Bf016411; Fri, 16 Jul 2021 11:54:02 GMT (envelope-from git) Date: Fri, 16 Jul 2021 11:54:02 GMT Message-Id: <202107161154.16GBs2Bf016411@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kristof Provost Subject: git: e8b98712d706 - stable/12 - pf: add DIOCGETSTATESV2 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kp X-Git-Repository: src X-Git-Refname: refs/heads/stable/12 X-Git-Reftype: branch X-Git-Commit: e8b98712d70675e48c84f31a4f108cba803c3a6c Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-branches@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commits to the stable branches of the FreeBSD src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 16 Jul 2021 11:54:05 -0000 The branch stable/12 has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=e8b98712d70675e48c84f31a4f108cba803c3a6c commit e8b98712d70675e48c84f31a4f108cba803c3a6c Author: Kristof Provost AuthorDate: 2021-07-06 10:12:12 +0000 Commit: Kristof Provost CommitDate: 2021-07-16 08:04:14 +0000 pf: add DIOCGETSTATESV2 Add a new version of the DIOCGETSTATES call, which extends the struct to include the original interface information. MFC after: 1 week Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D31097 (cherry picked from commit c6bf20a2a46dc36bf881ac594454f71379828a9a) --- sys/net/pfvar.h | 73 ++++++++++++++++++++++++++++ sys/netpfil/pf/pf_ioctl.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+) diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index b2c4231f29cc..dc9647f86c0b 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -517,6 +517,65 @@ struct pf_state_cmp { #define PFSTATE_SETPRIO 0x0200 #define PFSTATE_SETMASK (PFSTATE_SETPRIO) +struct pf_state_scrub_export { + uint16_t pfss_flags; + uint8_t pfss_ttl; /* stashed TTL */ +#define PF_SCRUB_FLAG_VALID 0x01 + uint8_t scrub_flag; + uint32_t pfss_ts_mod; /* timestamp modulation */ +}; + +struct pf_state_key_export { + struct pf_addr addr[2]; + uint16_t port[2]; +}; + +struct pf_state_peer_export { + struct pf_state_scrub_export scrub; /* state is scrubbed */ + uint32_t seqlo; /* Max sequence number sent */ + uint32_t seqhi; /* Max the other end ACKd + win */ + uint32_t seqdiff; /* Sequence number modulator */ + uint16_t max_win; /* largest window (pre scaling) */ + uint16_t mss; /* Maximum segment size option */ + uint8_t state; /* active state level */ + uint8_t wscale; /* window scaling factor */ + uint8_t dummy[6]; +}; +_Static_assert(sizeof(struct pf_state_peer_export) == 32, "size incorrect"); + +struct pf_state_export { + uint64_t version; +#define PF_STATE_VERSION 20210706 + uint64_t id; + char ifname[IFNAMSIZ]; + char orig_ifname[IFNAMSIZ]; + struct pf_state_key_export key[2]; + struct pf_state_peer_export src; + struct pf_state_peer_export dst; + struct pf_addr rt_addr; + uint32_t rule; + uint32_t anchor; + uint32_t nat_rule; + uint32_t creation; + uint32_t expire; + uint32_t spare0; + uint64_t packets[2]; + uint64_t bytes[2]; + uint32_t creatorid; + uint32_t spare1; + sa_family_t af; + uint8_t proto; + uint8_t direction; + uint8_t log; + uint8_t state_flags; + uint8_t timeout; + uint8_t sync_flags; + uint8_t updates; + + uint8_t spare[112]; +}; +_Static_assert(sizeof(struct pf_state_export) == 384, "size incorrect"); + #ifdef _KERNEL struct pf_kstate { u_int64_t id; @@ -643,6 +702,8 @@ extern pfsync_detach_ifnet_t *pfsync_detach_ifnet_ptr; void pfsync_state_export(struct pfsync_state *, struct pf_kstate *); +void pf_state_export(struct pf_state_export *, + struct pf_kstate *); /* pflog */ struct pf_kruleset; @@ -1184,6 +1245,17 @@ struct pfioc_states { #define ps_states ps_u.psu_states }; +struct pfioc_states_v2 { + int ps_len; + uint64_t ps_req_version; + union { + caddr_t psu_buf; + struct pf_state_export *psu_states; + } ps_u; +#define ps_buf ps_u.psu_buf +#define ps_states ps_u.psu_states +}; + struct pfioc_src_nodes { int psn_len; union { @@ -1400,6 +1472,7 @@ struct pfioc_iface { #define DIOCCLRIFFLAG _IOWR('D', 90, struct pfioc_iface) #define DIOCKILLSRCNODES _IOWR('D', 91, struct pfioc_src_node_kill) #define DIOCKEEPCOUNTERS _IOWR('D', 92, struct pfioc_nv) +#define DIOCGETSTATESV2 _IOWR('D', 93, struct pfioc_states_v2) struct pf_ifspeed_v0 { char ifname[IFNAMSIZ]; diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index 338880edf7e9..c8d7805b3fce 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -2110,6 +2110,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td case DIOCNATLOOK: case DIOCSETDEBUG: case DIOCGETSTATES: + case DIOCGETSTATESV2: case DIOCGETSTATESNV: case DIOCGETTIMEOUT: case DIOCCLRRULECTRS: @@ -2163,6 +2164,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td case DIOCGETSTATENV: case DIOCGETSTATUS: case DIOCGETSTATES: + case DIOCGETSTATESV2: case DIOCGETSTATESNV: case DIOCGETTIMEOUT: case DIOCGETLIMIT: @@ -2885,6 +2887,60 @@ DIOCGETSTATES_full: break; } + case DIOCGETSTATESV2: { + struct pfioc_states_v2 *ps = (struct pfioc_states_v2 *)addr; + struct pf_kstate *s; + struct pf_state_export *pstore, *p; + int i, nr; + + if (ps->ps_req_version > PF_STATE_VERSION) { + error = ENOTSUP; + break; + } + + if (ps->ps_len <= 0) { + nr = uma_zone_get_cur(V_pf_state_z); + ps->ps_len = sizeof(struct pf_state_export) * nr; + break; + } + + p = pstore = malloc(ps->ps_len, M_TEMP, M_WAITOK | M_ZERO); + nr = 0; + + for (i = 0; i <= pf_hashmask; i++) { + struct pf_idhash *ih = &V_pf_idhash[i]; + + if (LIST_EMPTY(&ih->states)) + continue; + + PF_HASHROW_LOCK(ih); + LIST_FOREACH(s, &ih->states, entry) { + if (s->timeout == PFTM_UNLINKED) + continue; + + if ((nr+1) * sizeof(*p) > ps->ps_len) { + PF_HASHROW_UNLOCK(ih); + goto DIOCGETSTATESV2_full; + } + pf_state_export(p, s); + p++; + nr++; + } + PF_HASHROW_UNLOCK(ih); + } +DIOCGETSTATESV2_full: + error = copyout(pstore, ps->ps_states, + sizeof(struct pf_state_export) * nr); + if (error) { + free(pstore, M_TEMP); + break; + } + ps->ps_len = sizeof(struct pf_state_export) * nr; + free(pstore, M_TEMP); + + break; + } + case DIOCGETSTATESNV: { error = pf_getstates((struct pfioc_nv *)addr); break; @@ -4662,7 +4718,70 @@ pfsync_state_export(struct pfsync_state *sp, struct pf_kstate *st) pf_state_counter_hton(st->packets[1], sp->packets[1]); pf_state_counter_hton(st->bytes[0], sp->bytes[0]); pf_state_counter_hton(st->bytes[1], sp->bytes[1]); +} + +void +pf_state_export(struct pf_state_export *sp, struct pf_kstate *st) +{ + bzero(sp, sizeof(*sp)); + + sp->version = PF_STATE_VERSION; + + /* copy from state key */ + sp->key[PF_SK_WIRE].addr[0] = st->key[PF_SK_WIRE]->addr[0]; + sp->key[PF_SK_WIRE].addr[1] = st->key[PF_SK_WIRE]->addr[1]; + sp->key[PF_SK_WIRE].port[0] = st->key[PF_SK_WIRE]->port[0]; + sp->key[PF_SK_WIRE].port[1] = st->key[PF_SK_WIRE]->port[1]; + sp->key[PF_SK_STACK].addr[0] = st->key[PF_SK_STACK]->addr[0]; + sp->key[PF_SK_STACK].addr[1] = st->key[PF_SK_STACK]->addr[1]; + sp->key[PF_SK_STACK].port[0] = st->key[PF_SK_STACK]->port[0]; + sp->key[PF_SK_STACK].port[1] = st->key[PF_SK_STACK]->port[1]; + sp->proto = st->key[PF_SK_WIRE]->proto; + sp->af = st->key[PF_SK_WIRE]->af; + + /* copy from state */ + strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname)); + strlcpy(sp->orig_ifname, st->orig_kif->pfik_name, + sizeof(sp->orig_ifname)); + bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr)); + sp->creation = htonl(time_uptime - st->creation); + sp->expire = pf_state_expires(st); + if (sp->expire <= time_uptime) + sp->expire = htonl(0); + else + sp->expire = htonl(sp->expire - time_uptime); + + sp->direction = st->direction; + sp->log = st->log; + sp->timeout = st->timeout; + sp->state_flags = st->state_flags; + if (st->src_node) + sp->sync_flags |= PFSYNC_FLAG_SRCNODE; + if (st->nat_src_node) + sp->sync_flags |= PFSYNC_FLAG_NATSRCNODE; + + sp->id = st->id; + sp->creatorid = st->creatorid; + pf_state_peer_hton(&st->src, &sp->src); + pf_state_peer_hton(&st->dst, &sp->dst); + + if (st->rule.ptr == NULL) + sp->rule = htonl(-1); + else + sp->rule = htonl(st->rule.ptr->nr); + if (st->anchor.ptr == NULL) + sp->anchor = htonl(-1); + else + sp->anchor = htonl(st->anchor.ptr->nr); + if (st->nat_rule.ptr == NULL) + sp->nat_rule = htonl(-1); + else + sp->nat_rule = htonl(st->nat_rule.ptr->nr); + sp->packets[0] = st->packets[0]; + sp->packets[1] = st->packets[1]; + sp->bytes[0] = st->bytes[0]; + sp->bytes[1] = st->bytes[1]; } static void