git: 4c36e9454374 - stable/12 - pf: syncookie ioctl interface
Kristof Provost
kp at FreeBSD.org
Tue Jul 27 11:46:47 UTC 2021
The branch stable/12 has been updated by kp:
URL: https://cgit.FreeBSD.org/src/commit/?id=4c36e9454374fa200572ce4be5fb2570892c5634
commit 4c36e9454374fa200572ce4be5fb2570892c5634
Author: Kristof Provost <kp at FreeBSD.org>
AuthorDate: 2021-05-26 08:18:19 +0000
Commit: Kristof Provost <kp at FreeBSD.org>
CommitDate: 2021-07-27 11:24:24 +0000
pf: syncookie ioctl interface
Kernel side implementation to allow switching between on and off modes,
and allow this configuration to be retrieved.
MFC after: 1 week
Sponsored by: Modirum MDPay
Differential Revision: https://reviews.freebsd.org/D31139
(cherry picked from commit 231e83d3422ff58fe94de8375a9532a1726056ed)
---
sys/net/pfvar.h | 2 +-
sys/netpfil/pf/pf_ioctl.c | 18 +++++++++
sys/netpfil/pf/pf_syncookies.c | 84 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 103 insertions(+), 1 deletion(-)
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
index 3a74709fecf5..d072eedd3621 100644
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1573,6 +1573,7 @@ struct pf_idhash {
struct mtx lock;
};
+extern u_long pf_ioctl_maxcount;
extern u_long pf_hashmask;
extern u_long pf_srchashmask;
#define PF_HASHSIZ (131072)
@@ -1841,7 +1842,6 @@ void pf_send_tcp(const struct pf_krule *, sa_family_t,
u_int16_t);
void pf_syncookies_init(void);
-int pf_syncookies_setmode(u_int8_t);
int pf_get_syncookies(struct pfioc_nv *);
int pf_set_syncookies(struct pfioc_nv *);
int pf_synflood_check(struct pf_pdesc *);
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
index 70cc4ff83d7b..dde2aecc8ef5 100644
--- a/sys/netpfil/pf/pf_ioctl.c
+++ b/sys/netpfil/pf/pf_ioctl.c
@@ -276,6 +276,14 @@ pflog_packet_t *pflog_packet_ptr = NULL;
extern u_long pf_ioctl_maxcount;
+#define ERROUT_FUNCTION(target, x) \
+ do { \
+ error = (x); \
+ SDT_PROBE3(pf, ioctl, function, error, __func__, error, \
+ __LINE__); \
+ goto target; \
+ } while (0)
+
static void
pfattach_vnet(void)
{
@@ -2138,6 +2146,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCOSFPGET:
case DIOCGETSRCNODES:
case DIOCCLRSRCNODES:
+ case DIOCGETSYNCOOKIES:
case DIOCIGETIFACES:
case DIOCGIFSPEEDV0:
case DIOCGIFSPEEDV1:
@@ -2185,6 +2194,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
case DIOCRTSTADDRS:
case DIOCOSFPGET:
case DIOCGETSRCNODES:
+ case DIOCGETSYNCOOKIES:
case DIOCIGETIFACES:
case DIOCGIFSPEEDV1:
case DIOCGIFSPEEDV0:
@@ -4602,6 +4612,14 @@ DIOCCHANGEADDR_error:
error = pf_keepcounters((struct pfioc_nv *)addr);
break;
+ case DIOCGETSYNCOOKIES:
+ error = pf_get_syncookies((struct pfioc_nv *)addr);
+ break;
+
+ case DIOCSETSYNCOOKIES:
+ error = pf_set_syncookies((struct pfioc_nv *)addr);
+ break;
+
case DIOCSETHOSTID: {
u_int32_t *hostid = (u_int32_t *)addr;
diff --git a/sys/netpfil/pf/pf_syncookies.c b/sys/netpfil/pf/pf_syncookies.c
index ee936b6662fa..c05aed605e06 100644
--- a/sys/netpfil/pf/pf_syncookies.c
+++ b/sys/netpfil/pf/pf_syncookies.c
@@ -110,6 +110,7 @@ struct pf_syncookie_status {
VNET_DEFINE_STATIC(struct pf_syncookie_status, pf_syncookie_status);
#define V_pf_syncookie_status VNET(pf_syncookie_status)
+static int pf_syncookies_setmode(u_int8_t);
void pf_syncookie_rotate(void *);
void pf_syncookie_newkey(void);
uint32_t pf_syncookie_mac(struct pf_pdesc *, union pf_syncookie,
@@ -127,6 +128,89 @@ pf_syncookies_init(void)
}
int
+pf_get_syncookies(struct pfioc_nv *nv)
+{
+ nvlist_t *nvl = NULL;
+ void *nvlpacked = NULL;
+
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ return (ENOMEM);
+
+ nvlist_add_bool(nvl, "enabled",
+ V_pf_status.syncookies_mode != PF_SYNCOOKIES_NEVER);
+ nvlist_add_bool(nvl, "adaptive", false);
+
+ nvlpacked = nvlist_pack(nvl, &nv->len);
+ if (nvlpacked == NULL) {
+ nvlist_destroy(nvl);
+ return (ENOMEM);
+ }
+ if (nv->size == 0) {
+ nvlist_destroy(nvl);
+ free(nvlpacked, M_TEMP);
+ return (0);
+ } else if (nv->size < nv->len) {
+ nvlist_destroy(nvl);
+ free(nvlpacked, M_TEMP);
+ return (ENOSPC);
+ }
+
+ return (copyout(nvlpacked, nv->data, nv->len));
+}
+
+int
+pf_set_syncookies(struct pfioc_nv *nv)
+{
+ nvlist_t *nvl = NULL;
+ void *nvlpacked = NULL;
+ int error;
+ bool enabled, adaptive;
+
+ if (nv->len > pf_ioctl_maxcount)
+ return (ENOMEM);
+
+ nvlpacked = malloc(nv->len, M_TEMP, M_WAITOK);
+ if (nvlpacked == NULL)
+ return (ENOMEM);
+
+ error = copyin(nv->data, nvlpacked, nv->len);
+ if (error) {
+ free(nvlpacked, M_TEMP);
+ return (error);
+ }
+
+ nvl = nvlist_unpack(nvlpacked, nv->len, 0);
+ if (nvl == NULL) {
+ free(nvlpacked, M_TEMP);
+ return (EBADMSG);
+ }
+
+ if (! nvlist_exists_bool(nvl, "enabled")
+ || ! nvlist_exists_bool(nvl, "adaptive")) {
+ nvlist_destroy(nvl);
+ free(nvlpacked, M_TEMP);
+ return (EBADMSG);
+ }
+
+ enabled = nvlist_get_bool(nvl, "enabled");
+ adaptive = nvlist_get_bool(nvl, "adaptive");
+
+ if (adaptive) {
+ nvlist_destroy(nvl);
+ free(nvlpacked, M_TEMP);
+ return (ENOTSUP);
+ }
+
+ PF_RULES_WLOCK();
+ error = pf_syncookies_setmode(enabled ?
+ PF_SYNCOOKIES_ALWAYS : PF_SYNCOOKIES_NEVER);
+ PF_RULES_WUNLOCK();
+
+ return (error);
+}
+
+static int
pf_syncookies_setmode(u_int8_t mode)
{
if (mode > PF_SYNCOOKIES_MODE_MAX)
More information about the dev-commits-src-all
mailing list