From nobody Fri Oct 13 09:15:39 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 4S6LT763Hbz4wkpG; Fri, 13 Oct 2023 09:15:39 +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 4S6LT75Tb0z4R13; Fri, 13 Oct 2023 09:15:39 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1697188539; 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=CIfl6rPiF3bsZA3Uv7+jHrYDyfY4j3N58ApIOR3I71o=; b=WsRSC3azr9sHVa8PgOsHyEu0J6CwT35v67Jc9t9DwqeCIy00Cg/YtZYdy+W5py+3BN613J rCWqcqhyCpwlvX8bh3Z5BH6BfwJNjZzCsaaFN2m9CdEjl+XbXGgkQyHPUR26ESnQ5NoJlM lHUJLVjMIpnpC2xayGUxX5N1p7PAWRV/0iN3Ee4wO06nSpp0PoF01Gow3whfM4M7020V9z DPJlBwwdSKM4UyvoabcxKDJkgPkRWR+UHUSCQLtMu4yz2I9dZy9pxJLc0/4LKowrbKJmsB c7cSp+PKHFfA0qV3hiosDBMi2/aP4wvH+EA5khNsbSjiR6JSTnUC4+YDFfcv7w== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1697188539; a=rsa-sha256; cv=none; b=VP3F75nRtVzcLb53xa5gGDX1RZqg1QIXpk9vKJUd3ijDvF4qmY9Trn4xEdlmeDwKOe1CDj mdf6FiK9qXcdJHEcnble/cduRqwFzCwhZWXVUoV05nG8SPFYu67X56qi7aShvS0rWKpYKo bLT99SJPzAF+aboUL1ARzTmKLctGo2xxTMktRe3h4w2j/xa8p5OclaR/8RwyrI1w7nAEG0 +AE4yf33X8G09fNoTfqTQCaOeKlE4iJK/T77tmUR+UPcSqrK6OBJpZYYJgY0D+KDV3RQHU mDlJQWE+08PATG7ZCvjpHbc9PVMsmBtP7E9AoZR6c9FglFYxzPyjGabKAuUvfQ== 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=1697188539; 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=CIfl6rPiF3bsZA3Uv7+jHrYDyfY4j3N58ApIOR3I71o=; b=IUe8vphe6sWjrILOhquNJ/hm4eRrs9Ys+2XWWXG1Lrc0p+NhNfzXDV0B748AU9wLJhfq+x 3D8rnAV1UfMWTRHKWczvCxpSdhD8KZkS1anai0wAVTf9j/G69M7bsAoFeKqXour3LLEGMW zMwD8XtWlGLFVoutcpv9pC8ftUaPbhIjZAwLzH6ihevI4TOEV/d17Z8YUsrswCEgZZ+8kV hM1HKjR2gq54/tpvv5KkS9zj+LM/bqRzB0h+sU5bVYSqalB/loDrbw6fwnq6cJcGDcWFLJ QWOvpPizc2GszQrOXRvWMR8LpMINC1IsqBjMA+kB0RvQIDoo16KX6xzcDiqWRA== 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 4S6LT74YgwzhF4; Fri, 13 Oct 2023 09:15:39 +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 39D9Fd8G068388; Fri, 13 Oct 2023 09:15:39 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 39D9FdHt068385; Fri, 13 Oct 2023 09:15:39 GMT (envelope-from git) Date: Fri, 13 Oct 2023 09:15:39 GMT Message-Id: <202310130915.39D9FdHt068385@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: 81647eb60ee3 - main - pf: implement start/stop calls via netlink 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: 81647eb60ee387b0b33ac42deacd25edace2661e Auto-Submitted: auto-generated The branch main has been updated by kp: URL: https://cgit.FreeBSD.org/src/commit/?id=81647eb60ee387b0b33ac42deacd25edace2661e commit 81647eb60ee387b0b33ac42deacd25edace2661e Author: Kristof Provost AuthorDate: 2023-10-10 15:20:12 +0000 Commit: Kristof Provost CommitDate: 2023-10-13 07:53:22 +0000 pf: implement start/stop calls via netlink Implement equivalents to DIOCSTART and DIOCSTOP in netlink. Provide a libpfctl implementation and add a basic test case, mostly to verify that we still return the same errors as before the conversion Sponsored by: Rubicon Communications, LLC ("Netgate") Differential Revision: https://reviews.freebsd.org/D42145 --- lib/libpfctl/libpfctl.c | 28 +++++++++++++++ lib/libpfctl/libpfctl.h | 1 + sbin/pfctl/pfctl.c | 14 +++++--- sys/net/pfvar.h | 2 ++ sys/netpfil/pf/pf_ioctl.c | 72 +++++++++++++++++++++++++------------- sys/netpfil/pf/pf_nl.c | 24 +++++++++++++ sys/netpfil/pf/pf_nl.h | 2 ++ tests/sys/netpfil/pf/pass_block.sh | 38 ++++++++++++++++++++ 8 files changed, 151 insertions(+), 30 deletions(-) diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c index ca29645f9c34..51276d8bb343 100644 --- a/lib/libpfctl/libpfctl.c +++ b/lib/libpfctl/libpfctl.c @@ -177,6 +177,34 @@ pf_nvuint_64_array(const nvlist_t *nvl, const char *name, size_t maxelems, *nelems = elems; } +int +pfctl_startstop(int start) +{ + struct snl_state ss = {}; + struct snl_errmsg_data e = {}; + struct snl_writer nw; + struct nlmsghdr *hdr; + uint32_t seq_id; + int family_id; + + snl_init(&ss, NETLINK_GENERIC); + family_id = snl_get_genl_family(&ss, PFNL_FAMILY_NAME); + + snl_init_writer(&ss, &nw); + hdr = snl_create_genl_msg_request(&nw, family_id, + start ? PFNL_CMD_START : PFNL_CMD_STOP); + + snl_finalize_msg(&nw); + seq_id = hdr->nlmsg_seq; + + snl_send_message(&ss, hdr); + + while ((hdr = snl_read_reply_multi(&ss, seq_id, &e)) != NULL) { + } + + return (e.error); +} + static void _pfctl_get_status_counters(const nvlist_t *nvl, struct pfctl_status_counters *counters) diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h index e75f93d8775e..06cd25e82c08 100644 --- a/lib/libpfctl/libpfctl.h +++ b/lib/libpfctl/libpfctl.h @@ -384,6 +384,7 @@ struct pfctl_syncookies { uint8_t lowwater; /* Percent */ }; +int pfctl_startstop(int start); struct pfctl_status* pfctl_get_status(int dev); uint64_t pfctl_status_counter(struct pfctl_status *status, int id); uint64_t pfctl_status_fcounter(struct pfctl_status *status, int id); diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c index 759b36d9cebe..56b1d28c6fd6 100644 --- a/sbin/pfctl/pfctl.c +++ b/sbin/pfctl/pfctl.c @@ -310,10 +310,12 @@ pfctl_proto2name(int proto) int pfctl_enable(int dev, int opts) { - if (ioctl(dev, DIOCSTART)) { - if (errno == EEXIST) + int ret; + + if ((ret = pfctl_startstop(1)) != 0) { + if (ret == EEXIST) errx(1, "pf already enabled"); - else if (errno == ESRCH) + else if (ret == ESRCH) errx(1, "pfil registeration failed"); else err(1, "DIOCSTART"); @@ -331,8 +333,10 @@ pfctl_enable(int dev, int opts) int pfctl_disable(int dev, int opts) { - if (ioctl(dev, DIOCSTOP)) { - if (errno == ENOENT) + int ret; + + if ((ret = pfctl_startstop(0)) != 0) { + if (ret == ENOENT) errx(1, "pf not enabled"); else err(1, "DIOCSTOP"); diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index f5ea9bf71f0c..59579a0849d9 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -2166,6 +2166,8 @@ VNET_DECLARE(struct pf_krule *, pf_rulemarker); #define V_pf_rulemarker VNET(pf_rulemarker) #endif +int pf_start(void); +int pf_stop(void); void pf_initialize(void); void pf_mtag_initialize(void); void pf_mtag_cleanup(void); diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c index 5a441c9723e3..38c09303a543 100644 --- a/sys/netpfil/pf/pf_ioctl.c +++ b/sys/netpfil/pf/pf_ioctl.c @@ -2337,6 +2337,49 @@ relock_DIOCKILLSTATES: return (killed); } +int +pf_start(void) +{ + int error = 0; + + sx_xlock(&V_pf_ioctl_lock); + if (V_pf_status.running) + error = EEXIST; + else { + hook_pf(); + if (! TAILQ_EMPTY(V_pf_keth->active.rules)) + hook_pf_eth(); + V_pf_status.running = 1; + V_pf_status.since = time_second; + new_unrhdr64(&V_pf_stateid, time_second); + + DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n")); + } + sx_xunlock(&V_pf_ioctl_lock); + + return (error); +} + +int +pf_stop(void) +{ + int error = 0; + + sx_xlock(&V_pf_ioctl_lock); + if (!V_pf_status.running) + error = ENOENT; + else { + V_pf_status.running = 0; + dehook_pf(); + dehook_pf_eth(); + V_pf_status.since = time_second; + DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n")); + } + sx_xunlock(&V_pf_ioctl_lock); + + return (error); +} + static int pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td) { @@ -2479,34 +2522,15 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td CURVNET_SET(TD_TO_VNET(td)); switch (cmd) { +#ifdef COMPAT_FREEBSD14 case DIOCSTART: - sx_xlock(&V_pf_ioctl_lock); - if (V_pf_status.running) - error = EEXIST; - else { - hook_pf(); - if (! TAILQ_EMPTY(V_pf_keth->active.rules)) - hook_pf_eth(); - V_pf_status.running = 1; - V_pf_status.since = time_second; - new_unrhdr64(&V_pf_stateid, time_second); - - DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n")); - } + error = pf_start(); break; case DIOCSTOP: - sx_xlock(&V_pf_ioctl_lock); - if (!V_pf_status.running) - error = ENOENT; - else { - V_pf_status.running = 0; - dehook_pf(); - dehook_pf_eth(); - V_pf_status.since = time_second; - DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n")); - } + error = pf_stop(); break; +#endif case DIOCGETETHRULES: { struct pfioc_nv *nv = (struct pfioc_nv *)addr; @@ -5416,8 +5440,6 @@ DIOCCHANGEADDR_error: break; } fail: - if (sx_xlocked(&V_pf_ioctl_lock)) - sx_xunlock(&V_pf_ioctl_lock); CURVNET_RESTORE(); #undef ERROUT_IOCTL diff --git a/sys/netpfil/pf/pf_nl.c b/sys/netpfil/pf/pf_nl.c index 459a5dc6507e..e079edcc166d 100644 --- a/sys/netpfil/pf/pf_nl.c +++ b/sys/netpfil/pf/pf_nl.c @@ -336,6 +336,18 @@ pf_handle_getcreators(struct nlmsghdr *hdr, struct nl_pstate *npt) return (error); } +static int +pf_handle_start(struct nlmsghdr *hdr __unused, struct nl_pstate *npt __unused) +{ + return (pf_start()); +} + +static int +pf_handle_stop(struct nlmsghdr *hdr __unused, struct nl_pstate *npt __unused) +{ + return (pf_stop()); +} + static const struct nlhdr_parser *all_parsers[] = { &state_parser }; static int family_id; @@ -353,6 +365,18 @@ static const struct genl_cmd pf_cmds[] = { .cmd_cb = pf_handle_getcreators, .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_DUMP | GENL_CMD_CAP_HASPOL, }, + { + .cmd_num = PFNL_CMD_START, + .cmd_name = "START", + .cmd_cb = pf_handle_start, + .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, + }, + { + .cmd_num = PFNL_CMD_STOP, + .cmd_name = "STOP", + .cmd_cb = pf_handle_stop, + .cmd_flags = GENL_CMD_CAP_DO | GENL_CMD_CAP_HASPOL, + }, }; void diff --git a/sys/netpfil/pf/pf_nl.h b/sys/netpfil/pf/pf_nl.h index 98525641b43d..3c8c6d3b8ed4 100644 --- a/sys/netpfil/pf/pf_nl.h +++ b/sys/netpfil/pf/pf_nl.h @@ -38,6 +38,8 @@ enum { PFNL_CMD_UNSPEC = 0, PFNL_CMD_GETSTATES = 1, PFNL_CMD_GETCREATORS = 2, + PFNL_CMD_START = 3, + PFNL_CMD_STOP = 4, __PFNL_CMD_MAX, }; #define PFNL_CMD_MAX (__PFNL_CMD_MAX -1) diff --git a/tests/sys/netpfil/pf/pass_block.sh b/tests/sys/netpfil/pf/pass_block.sh index 792b73b4a0a5..faf5c2de4de2 100644 --- a/tests/sys/netpfil/pf/pass_block.sh +++ b/tests/sys/netpfil/pf/pass_block.sh @@ -28,6 +28,43 @@ common_dir=$(atf_get_srcdir)/../common +atf_test_case "enable_disable" "cleanup" +enable_disable_head() +{ + atf_set descr 'Test enable/disable' + atf_set require.user root +} + +enable_disable_body() +{ + pft_init + + j="pass_block:enable_disable" + + vnet_mkjail ${j} + + # Disable when disabled fails + atf_check -s exit:1 -e ignore \ + jexec ${j} pfctl -d + + # Enable succeeds + atf_check -s exit:0 -e ignore \ + jexec ${j} pfctl -e + + # Enable when enabled fails + atf_check -s exit:1 -e ignore \ + jexec ${j} pfctl -e + + # Disable succeeds + atf_check -s exit:0 -e ignore \ + jexec ${j} pfctl -d +} + +enable_disable_cleanup() +{ + pft_cleanup +} + atf_test_case "v4" "cleanup" v4_head() { @@ -257,6 +294,7 @@ urpf_cleanup() atf_init_test_cases() { + atf_add_test_case "enable_disable" atf_add_test_case "v4" atf_add_test_case "v6" atf_add_test_case "noalias"