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