From nobody Tue Oct 10 09:50:36 2023 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4S4WNs31Gmz4wVDk; Tue, 10 Oct 2023 09:50:37 +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 4S4WNs1SFMz3P6p; Tue, 10 Oct 2023 09:50:37 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1696931437; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Q/rMh8N/Py/DiyhE1QX3OfM/Vvafg6NX6mm1ywjuMUo=; b=ZaRelOU2OXDjx2Hze/WemUIE1XJ3vw+q6sdo/S7bheLPLoEOMa0Z62CmTqRfG6wzc62uv1 +yC/Y+ordPSupMLqUXtdHH8AvcTk4JYor1vTyQddFByo8BpAOStU8+3NLgBb/MRxb712re 9zqNysUH/ewE0SjYegdJFxouiNDlBbn5WqqXAe5IthsOVL2cF05jjE5RZfWPA8gYKBGtJ2 NVXGod5MO4XOE1yX7oubhBnNrn3YCRfPZ0aTcM5gJEqkQpw/zO/Omr+O6LQn4oRaULSHUp RA4dFmnK1fcAQ/zHPjIqhW9IVJhOtJV2P6wSoo4b44Y7+b+Zp7IoMwsdqhXPMA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1696931437; a=rsa-sha256; cv=none; b=obndlgT6HnY6LdUvWWufX4e7D7zxzg0ACiDSC6BAQgG96gukAxr1FVvMORmN7Z4P0/jdHS ji1URuuFY0W+/5MAph6UIMj/tHO9QsF9vT6U0pnNQI0UezhYwcjuQxBw1P3LcSpOGOXWbp utnS3CO+qjrsUj3g/9pNAMHOan4H9kSO3oQJ27gbQqgEGzjmrn2KUZsP2E5QwAO71hR+s6 bkQKM0yohV9WwjmqSxVxqujfXSztFDzIpJWTcVHT/EoysdTns6G/QqZ2r4DDUsTTVRbXgf S2HsILvhgVb60agTa310f0fO2AdcuUGA26Ap4aMpqLX2yO3ugdXDvncN6ZbFaA== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1696931437; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Q/rMh8N/Py/DiyhE1QX3OfM/Vvafg6NX6mm1ywjuMUo=; b=m48NpU/jLacP+Sl2peh5wSNUOPKDm707Pd/3o0aJTAnr0kyxxdL1erglDMMxrFiQhsNhNH PIVWt1ycPY+/vJaymKEaFKQIzkRPp3S3gS+Jl8rMP2IzqoVitpTsJ6pzHLWrH1w4/oTva/ aA/aACeQUPfqrfbSPiR18XHbRaM/PHUcFUl+LSQEvJDCssIG0HSNMDkdMuCT3T9clU+AAc mCTTHUNy3hDTloFmBFmjVRBNNM+PQGBySXJrzw4efgSHE18xzWQRss4DmSb8KO1SaF1fHs i1ScE6z9EHtt09ajg9WDzvmc6fPYZHzIw9Lzmx4OYlCvIibqFx/xthswgK/XWQ== 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 4S4WNr6lMJzYh7; Tue, 10 Oct 2023 09:50:36 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 39A9oa9F030092; Tue, 10 Oct 2023 09:50:36 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 39A9oaL0030089; Tue, 10 Oct 2023 09:50:36 GMT (envelope-from git) Date: Tue, 10 Oct 2023 09:50:36 GMT Message-Id: <202310100950.39A9oaL0030089@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kristof Provost Subject: git: a7191e5d7b62 - main - pf: add a way to list creator ids List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org 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/main X-Git-Reftype: branch X-Git-Commit: a7191e5d7b625c35434f99f51ccbf577228b2afc Auto-Submitted: auto-generated The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=a7191e5d7b625c35434f99f51ccbf577228b2afc commit a7191e5d7b625c35434f99f51ccbf577228b2afc Author: Kristof Provost AuthorDate: 2023-10-04 10:27:54 +0000 Commit: Kristof Provost CommitDate: 2023-10-10 09:48:21 +0000 pf: add a way to list creator ids Allow userspace to retrieve a list of distinct creator ids for the current states. This is used by pfSense, and used to require dumping all states to userspace. It's rather inefficient to export a (potentially extremely large) state table to obtain a handful (typically 2) of 32-bit integers. Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D42092 --- lib/libpfctl/libpfctl.c | 68 ++++++++++++++++++++++++++++++++++- lib/libpfctl/libpfctl.h | 1 + sbin/pfctl/pfctl.c | 21 ++++++++++- sbin/pfctl/pfctl.h | 1 + sys/netpfil/pf/pf_nl.c | 80 ++++++++++++++++++++++++++++++++++++++++++ sys/netpfil/pf/pf_nl.h | 1 + tests/sys/netpfil/pf/pfsync.sh | 8 +++++ 7 files changed, 178 insertions(+), 2 deletions(-) diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index 03f80baa2178..ca29645f9c34 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -1106,6 +1106,71 @@ pfctl_set_keepcounters(int dev, bool keep) return (ret); } +struct pfctl_creator { + uint32_t id; +}; +#define _IN(_field) offsetof(struct genlmsghdr, _field) +#define _OUT(_field) offsetof(struct pfctl_creator, _field) +static struct snl_attr_parser ap_creators[] = { + { .type = PF_ST_CREATORID, .off = _OUT(id), .cb = snl_attr_get_uint32 }, +}; +static struct snl_field_parser fp_creators[] = { +}; +#undef _IN +#undef _OUT +SNL_DECLARE_PARSER(creator_parser, struct genlmsghdr, fp_creators, ap_creators); + +static int +pfctl_get_creators_nl(struct snl_state *ss, uint32_t *creators, size_t *len) +{ + + int family_id = snl_get_genl_family(ss, PFNL_FAMILY_NAME); + size_t i = 0; + + struct nlmsghdr *hdr; + struct snl_writer nw; + + snl_init_writer(ss, &nw); + hdr = snl_create_genl_msg_request(&nw, family_id, PFNL_CMD_GETCREATORS); + hdr->nlmsg_flags |= NLM_F_DUMP; + snl_finalize_msg(&nw); + uint32_t seq_id = hdr->nlmsg_seq; + + snl_send_message(ss, hdr); + + struct snl_errmsg_data e = {}; + while ((hdr = snl_read_reply_multi(ss, seq_id, &e)) != NULL) { + struct pfctl_creator c; + bzero(&c, sizeof(c)); + + if (!snl_parse_nlmsg(ss, hdr, &creator_parser, &c)) + continue; + + creators[i] = c.id; + i++; + if (i > *len) + return (E2BIG); + } + + *len = i; + + return (0); +} + +int +pfctl_get_creatorids(uint32_t *creators, size_t *len) +{ + struct snl_state ss = {}; + int error; + + snl_init(&ss, NETLINK_GENERIC); + error = pfctl_get_creators_nl(&ss, creators, len); + snl_free(&ss); + + return (error); + +} + static void pfctl_nv_add_state_cmp(nvlist_t *nvl, const char *name, const struct pfctl_state_cmp *cmp) @@ -1199,7 +1264,8 @@ static struct snl_field_parser fp_state[] = { SNL_DECLARE_PARSER(state_parser, struct genlmsghdr, fp_state, ap_state); static const struct snl_hdr_parser *all_parsers[] = { - &state_parser, &skey_parser, &speer_parser + &state_parser, &skey_parser, &speer_parser, + &creator_parser, }; static int diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h index 4906ec3ccfce..e75f93d8775e 100644 --- a/lib/libpfctl/libpfctl.h +++ b/lib/libpfctl/libpfctl.h @@ -413,6 +413,7 @@ int pfctl_add_rule(int dev, const struct pfctl_rule *r, const char *anchor, const char *anchor_call, uint32_t ticket, uint32_t pool_ticket); int pfctl_set_keepcounters(int dev, bool keep); +int pfctl_get_creatorids(uint32_t *creators, size_t *len); typedef int (*pfctl_get_state_fn)(struct pfctl_state *, void *); int pfctl_get_states_iter(pfctl_get_state_fn f, void *arg); int pfctl_get_states(int dev, struct pfctl_states *states); diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 9a75eb7d00b5..759b36d9cebe 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -233,7 +233,7 @@ static const char * const clearopt_list[] = { static const char * const showopt_list[] = { "ether", "nat", "queue", "rules", "Anchors", "Sources", "states", "info", "Interfaces", "labels", "timeouts", "memory", "Tables", - "osfp", "Running", "all", NULL + "osfp", "Running", "all", "creatorids", NULL }; static const char * const tblcmdopt_list[] = { @@ -1639,6 +1639,22 @@ pfctl_show_limits(int dev, int opts) return (0); } +void +pfctl_show_creators(int opts) +{ + int ret; + uint32_t creators[16]; + size_t count = nitems(creators); + + ret = pfctl_get_creatorids(creators, &count); + if (ret != 0) + errx(ret, "Failed to retrieve creators"); + + printf("Creator IDs:\n"); + for (size_t i = 0; i < count; i++) + printf("%08x\n", creators[i]); +} + /* callbacks for rule/nat/rdr/addr */ int pfctl_add_pool(struct pfctl *pf, struct pfctl_pool *p, sa_family_t af) @@ -3121,6 +3137,9 @@ main(int argc, char *argv[]) case 'I': pfctl_show_ifaces(ifaceopt, opts); break; + case 'c': + pfctl_show_creators(opts); + break; } } diff --git a/sbin/pfctl/pfctl.h b/sbin/pfctl/pfctl.h index b9da5e96a90e..cf198d557299 100644 --- a/sbin/pfctl/pfctl.h +++ b/sbin/pfctl/pfctl.h @@ -88,6 +88,7 @@ int pfctl_command_tables(int, char *[], char *, const char *, char *, int pfctl_show_altq(int, const char *, int, int); void warn_namespace_collision(const char *); int pfctl_show_ifaces(const char *, int); +void pfctl_show_creators(int); FILE *pfctl_fopen(const char *, const char *); #ifdef __FreeBSD__ diff --git a/sys/netpfil/pf/pf_nl.c b/sys/netpfil/pf/pf_nl.c index cbea76e7386f..bb50b3b2b321 100644 --- a/sys/netpfil/pf/pf_nl.c +++ b/sys/netpfil/pf/pf_nl.c @@ -246,6 +246,30 @@ handle_getstate(struct nlpcb *nlp, struct nl_parsed_state *attrs, return (dump_state(nlp, hdr, s, npt)); } +static int +dump_creatorid(struct nlpcb *nlp, const struct nlmsghdr *hdr, uint32_t creator, + struct nl_pstate *npt) +{ + struct nl_writer *nw = npt->nw; + + if (!nlmsg_reply(nw, hdr, sizeof(struct genlmsghdr))) + goto enomem; + + struct genlmsghdr *ghdr_new = nlmsg_reserve_object(nw, struct genlmsghdr); + ghdr_new->cmd = PFNL_CMD_GETCREATORS; + ghdr_new->version = 0; + ghdr_new->reserved = 0; + + nlattr_add_u32(nw, PF_ST_CREATORID, htonl(creator)); + + if (nlmsg_end(nw)) + return (0); + +enomem: + nlmsg_abort(nw); + return (ENOMEM); +} + static int pf_handle_getstates(struct nlmsghdr *hdr, struct nl_pstate *npt) { @@ -264,6 +288,56 @@ pf_handle_getstates(struct nlmsghdr *hdr, struct nl_pstate *npt) return (error); } +static int +pf_handle_getcreators(struct nlmsghdr *hdr, struct nl_pstate *npt) +{ + uint32_t creators[16]; + int error = 0; + + bzero(creators, sizeof(creators)); + + for (int i = 0; i < pf_hashmask; i++) { + struct pf_idhash *ih = &V_pf_idhash[i]; + struct pf_kstate *s; + + if (LIST_EMPTY(&ih->states)) + continue; + + PF_HASHROW_LOCK(ih); + LIST_FOREACH(s, &ih->states, entry) { + int j; + if (s->timeout == PFTM_UNLINKED) + continue; + + for (j = 0; j < nitems(creators); j++) { + if (creators[j] == s->creatorid) + break; + if (creators[j] == 0) { + creators[j] = s->creatorid; + break; + } + } + if (j == nitems(creators)) + printf("Warning: too many creators!\n"); + } + PF_HASHROW_UNLOCK(ih); + } + + hdr->nlmsg_flags |= NLM_F_MULTI; + for (int i = 0; i < nitems(creators); i++) { + if (creators[i] == 0) + break; + error = dump_creatorid(npt->nlp, hdr, creators[i], npt); + } + + if (!nlmsg_end_dump(npt->nw, error, hdr)) { + NL_LOG(LOG_DEBUG, "Unable to finalize the dump"); + return (ENOMEM); + } + + return (error); +} + static const struct nlhdr_parser *all_parsers[] = { &state_parser }; static int family_id; @@ -275,6 +349,12 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_getstates, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, }, + { + .cmd_num = PFNL_CMD_GETCREATORS, + .cmd_name = "GETCREATORS", + .cmd_cb = pf_handle_getcreators, + .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, + }, }; void diff --git a/sys/netpfil/pf/pf_nl.h b/sys/netpfil/pf/pf_nl.h index 5ef757eead21..98525641b43d 100644 --- a/sys/netpfil/pf/pf_nl.h +++ b/sys/netpfil/pf/pf_nl.h @@ -37,6 +37,7 @@ enum { PFNL_CMD_UNSPEC = 0, PFNL_CMD_GETSTATES = 1, + PFNL_CMD_GETCREATORS = 2, __PFNL_CMD_MAX, }; #define PFNL_CMD_MAX (__PFNL_CMD_MAX -1) diff --git a/tests/sys/netpfil/pf/pfsync.sh b/tests/sys/netpfil/pf/pfsync.sh index 5d30f5b44888..87dfcf748d3c 100644 --- a/tests/sys/netpfil/pf/pfsync.sh +++ b/tests/sys/netpfil/pf/pfsync.sh @@ -78,6 +78,8 @@ common_body() "set skip on ${epair_sync}b" \ "pass out keep state" + hostid_one=$(jexec one pfctl -si -v | awk '/Hostid:/ { gsub(/0x/, "", $2); printf($2); }') + ifconfig ${epair_one}b 198.51.100.254/24 up ping -c 1 -S 198.51.100.254 198.51.100.1 @@ -89,6 +91,12 @@ common_body() grep 198.51.100.254 ; then atf_fail "state not found on synced host" fi + + if ! jexec two pfctl -sc | grep ""${hostid_one}""; + then + jexec two pfctl -sc + atf_fail "HostID for host one not found on two" + fi } basic_cleanup()