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
This commit is contained in:
parent
8e1864ed07
commit
231e83d342
@ -1572,6 +1572,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)
|
||||
@ -1840,7 +1841,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 *);
|
||||
|
@ -275,6 +275,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)
|
||||
{
|
||||
@ -2136,6 +2144,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:
|
||||
@ -2183,6 +2192,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:
|
||||
@ -4538,6 +4548,14 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td
|
||||
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;
|
||||
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user