Page MenuHomeFreeBSD

D32136.id.diff
No OneTemporary

D32136.id.diff

diff --git a/lib/libpfctl/libpfctl.h b/lib/libpfctl/libpfctl.h
--- a/lib/libpfctl/libpfctl.h
+++ b/lib/libpfctl/libpfctl.h
@@ -276,11 +276,15 @@
enum pfctl_syncookies_mode {
PFCTL_SYNCOOKIES_NEVER,
- PFCTL_SYNCOOKIES_ALWAYS
+ PFCTL_SYNCOOKIES_ALWAYS,
+ PFCTL_SYNCOOKIES_ADAPTIVE
};
+extern const char* PFCTL_SYNCOOKIES_MODE_NAMES[];
struct pfctl_syncookies {
enum pfctl_syncookies_mode mode;
+ uint8_t highwater; /* Percent */
+ uint8_t lowwater; /* Percent */
};
struct pfctl_status* pfctl_get_status(int dev);
diff --git a/lib/libpfctl/libpfctl.c b/lib/libpfctl/libpfctl.c
--- a/lib/libpfctl/libpfctl.c
+++ b/lib/libpfctl/libpfctl.c
@@ -50,6 +50,12 @@
#include "libpfctl.h"
+const char* PFCTL_SYNCOOKIES_MODE_NAMES[] = {
+ "never",
+ "always",
+ "adaptive"
+};
+
static int _pfctl_clear_states(int , const struct pfctl_kill *,
unsigned int *, uint64_t);
@@ -938,17 +944,40 @@
return (_pfctl_clear_states(dev, kill, killed, DIOCKILLSTATESNV));
}
+static int
+pfctl_get_limit(int dev, const int index, u_int *limit)
+{
+ struct pfioc_limit pl;
+
+ bzero(&pl, sizeof(pl));
+ pl.index = index;
+
+ if (ioctl(dev, DIOCGETLIMIT, &pl) == -1)
+ return (errno);
+
+ *limit = pl.limit;
+
+ return (0);
+}
+
int
pfctl_set_syncookies(int dev, const struct pfctl_syncookies *s)
{
struct pfioc_nv nv;
nvlist_t *nvl;
int ret;
+ u_int state_limit;
+
+ ret = pfctl_get_limit(dev, PF_LIMIT_STATES, &state_limit);
+ if (ret != 0)
+ return (ret);
nvl = nvlist_create(0);
nvlist_add_bool(nvl, "enabled", s->mode != PFCTL_SYNCOOKIES_NEVER);
- nvlist_add_bool(nvl, "adaptive", false); /* XXX TODO */
+ nvlist_add_bool(nvl, "adaptive", s->mode == PFCTL_SYNCOOKIES_ADAPTIVE);
+ nvlist_add_number(nvl, "highwater", state_limit * s->highwater / 100);
+ nvlist_add_number(nvl, "lowwater", state_limit * s->lowwater / 100);
nv.data = nvlist_pack(nvl, &nv.len);
nv.size = nv.len;
@@ -966,12 +995,18 @@
{
struct pfioc_nv nv;
nvlist_t *nvl;
- bool enabled, adaptive;
+ int ret;
+ u_int state_limit;
+ bool enabled, adaptive;
+
+ ret = pfctl_get_limit(dev, PF_LIMIT_STATES, &state_limit);
+ if (ret != 0)
+ return (ret);
bzero(s, sizeof(*s));
- nv.data = malloc(128);
- nv.len = nv.size = 128;
+ nv.data = malloc(256);
+ nv.len = nv.size = 256;
if (ioctl(dev, DIOCGETSYNCOOKIES, &nv)) {
free(nv.data);
@@ -987,7 +1022,17 @@
enabled = nvlist_get_bool(nvl, "enabled");
adaptive = nvlist_get_bool(nvl, "adaptive");
- s->mode = enabled ? PFCTL_SYNCOOKIES_ALWAYS : PFCTL_SYNCOOKIES_NEVER;
+ if (enabled) {
+ if (adaptive)
+ s->mode = PFCTL_SYNCOOKIES_ADAPTIVE;
+ else
+ s->mode = PFCTL_SYNCOOKIES_ALWAYS;
+ } else {
+ s->mode = PFCTL_SYNCOOKIES_NEVER;
+ }
+
+ s->highwater = nvlist_get_number(nvl, "highwater") * 100 / state_limit;
+ s->lowwater = nvlist_get_number(nvl, "lowwater") * 100 / state_limit;
nvlist_destroy(nvl);
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
--- a/sbin/pfctl/parse.y
+++ b/sbin/pfctl/parse.y
@@ -320,6 +320,7 @@
static struct node_hfsc_opts hfsc_opts;
static struct node_fairq_opts fairq_opts;
static struct node_state_opt *keep_state_defaults = NULL;
+static struct pfctl_watermarks syncookie_opts;
int disallow_table(struct node_host *, const char *);
int disallow_urpf_failed(struct node_host *, const char *);
@@ -445,6 +446,7 @@
struct node_hfsc_opts hfsc_opts;
struct node_fairq_opts fairq_opts;
struct codel_opts codel_opts;
+ struct pfctl_watermarks *watermarks;
} v;
int lineno;
} YYSTYPE;
@@ -531,6 +533,7 @@
%type <v.pool_opts> pool_opts pool_opt pool_opts_l
%type <v.tagged> tagged
%type <v.rtableid> rtable
+%type <v.watermarks> syncookie_opts
%%
ruleset : /* empty */
@@ -729,14 +732,19 @@
| SET KEEPCOUNTERS {
pf->keep_counters = true;
}
- | SET SYNCOOKIES syncookie_val {
- pf->syncookies = $3;
+ | SET SYNCOOKIES syncookie_val syncookie_opts {
+ if (pfctl_cfg_syncookies(pf, $3, $4)) {
+ yyerror("error setting syncookies");
+ YYERROR;
+ }
}
;
syncookie_val : STRING {
if (!strcmp($1, "never"))
$$ = PFCTL_SYNCOOKIES_NEVER;
+ else if (!strcmp($1, "adaptive"))
+ $$ = PFCTL_SYNCOOKIES_ADAPTIVE;
else if (!strcmp($1, "always"))
$$ = PFCTL_SYNCOOKIES_ALWAYS;
else {
@@ -745,6 +753,37 @@
}
}
;
+syncookie_opts : /* empty */ { $$ = NULL; }
+ | {
+ memset(&syncookie_opts, 0, sizeof(syncookie_opts));
+ } '(' syncookie_opt_l ')' { $$ = &syncookie_opts; }
+ ;
+
+syncookie_opt_l : syncookie_opt_l comma syncookie_opt
+ | syncookie_opt
+ ;
+
+syncookie_opt : STRING STRING {
+ double val;
+ char *cp;
+
+ val = strtod($2, &cp);
+ if (cp == NULL || strcmp(cp, "%"))
+ YYERROR;
+ if (val <= 0 || val > 100) {
+ yyerror("illegal percentage value");
+ YYERROR;
+ }
+ if (!strcmp($1, "start")) {
+ syncookie_opts.hi = val;
+ } else if (!strcmp($1, "end")) {
+ syncookie_opts.lo = val;
+ } else {
+ yyerror("illegal syncookie option");
+ YYERROR;
+ }
+ }
+ ;
stringall : STRING { $$ = $1; }
| ALL {
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
--- a/sbin/pfctl/pfctl.c
+++ b/sbin/pfctl/pfctl.c
@@ -1812,6 +1812,10 @@
pf->limit[PF_LIMIT_TABLE_ENTRIES] = PFR_KENTRY_HIWAT;
pf->debug = PF_DEBUG_URGENT;
+
+ pf->syncookies = false;
+ pf->syncookieswat[0] = PF_SYNCOOKIES_LOWATPCT;
+ pf->syncookieswat[1] = PF_SYNCOOKIES_HIWATPCT;
}
int
@@ -2069,7 +2073,9 @@
bzero(&cookies, sizeof(cookies));
- cookies.mode = val ? PFCTL_SYNCOOKIES_ALWAYS : PFCTL_SYNCOOKIES_NEVER;
+ cookies.mode = val;
+ cookies.lowwater = pf->syncookieswat[0];
+ cookies.highwater = pf->syncookieswat[1];
if (pfctl_set_syncookies(dev, &cookies)) {
warnx("DIOCSETSYNCOOKIES");
@@ -2078,6 +2084,49 @@
return (0);
}
+int
+pfctl_cfg_syncookies(struct pfctl *pf, uint8_t val, struct pfctl_watermarks *w)
+{
+ if (val != PF_SYNCOOKIES_ADAPTIVE && w != NULL) {
+ warnx("syncookies start/end only apply to adaptive");
+ return (1);
+ }
+ if (val == PF_SYNCOOKIES_ADAPTIVE && w != NULL) {
+ if (!w->hi)
+ w->hi = PF_SYNCOOKIES_HIWATPCT;
+ if (!w->lo)
+ w->lo = w->hi / 2;
+ if (w->lo >= w->hi) {
+ warnx("start must be higher than end");
+ return (1);
+ }
+ pf->syncookieswat[0] = w->lo;
+ pf->syncookieswat[1] = w->hi;
+ pf->syncookieswat_set = 1;
+ }
+
+ if (pf->opts & PF_OPT_VERBOSE) {
+ if (val == PF_SYNCOOKIES_NEVER)
+ printf("set syncookies never\n");
+ else if (val == PF_SYNCOOKIES_ALWAYS)
+ printf("set syncookies always\n");
+ else if (val == PF_SYNCOOKIES_ADAPTIVE) {
+ if (pf->syncookieswat_set)
+ printf("set syncookies adaptive (start %u%%, "
+ "end %u%%)\n", pf->syncookieswat[1],
+ pf->syncookieswat[0]);
+ else
+ printf("set syncookies adaptive\n");
+ } else { /* cannot happen */
+ warnx("king bula ate all syncookies");
+ return (1);
+ }
+ }
+
+ pf->syncookies = val;
+ return (0);
+}
+
int
pfctl_set_debug(struct pfctl *pf, char *d)
{
diff --git a/sbin/pfctl/pfctl_parser.h b/sbin/pfctl/pfctl_parser.h
--- a/sbin/pfctl/pfctl_parser.h
+++ b/sbin/pfctl/pfctl_parser.h
@@ -101,6 +101,8 @@
char *ifname;
bool keep_counters;
u_int8_t syncookies;
+ u_int8_t syncookieswat[2]; /* lowat, highwat, in % */
+ u_int8_t syncookieswat_set;
u_int8_t timeout_set[PFTM_MAX];
u_int8_t limit_set[PF_LIMIT_MAX];
@@ -200,6 +202,11 @@
} meta;
};
+struct pfctl_watermarks {
+ uint32_t hi;
+ uint32_t lo;
+};
+
#ifdef __FreeBSD__
/*
* XXX
@@ -270,6 +277,7 @@
int pfctl_set_hostid(struct pfctl *, u_int32_t);
int pfctl_set_debug(struct pfctl *, char *);
int pfctl_set_interface_flags(struct pfctl *, char *, int, int);
+int pfctl_cfg_syncookies(struct pfctl *, uint8_t, struct pfctl_watermarks *);
int parse_config(char *, struct pfctl *);
int parse_flags(char *);
diff --git a/sbin/pfctl/pfctl_parser.c b/sbin/pfctl/pfctl_parser.c
--- a/sbin/pfctl/pfctl_parser.c
+++ b/sbin/pfctl/pfctl_parser.c
@@ -50,6 +50,7 @@
#include <net/pfvar.h>
#include <arpa/inet.h>
+#include <assert.h>
#include <search.h>
#include <stdio.h>
#include <stdlib.h>
@@ -618,9 +619,9 @@
}
printf("Syncookies\n");
+ assert(cookies->mode <= PFCTL_SYNCOOKIES_ADAPTIVE);
printf(" %-25s %s\n", "mode",
- cookies->mode == PFCTL_SYNCOOKIES_NEVER ?
- "never" : "always");
+ PFCTL_SYNCOOKIES_MODE_NAMES[cookies->mode]);
}
}
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
--- a/sys/net/pfvar.h
+++ b/sys/net/pfvar.h
@@ -1386,6 +1386,9 @@
PF_SYNCOOKIES_MODE_MAX = PF_SYNCOOKIES_ADAPTIVE
};
+#define PF_SYNCOOKIES_HIWATPCT 25
+#define PF_SYNCOOKIES_LOWATPCT (PF_SYNCOOKIES_HIWATPCT / 2)
+
#ifdef _KERNEL
struct pf_kstatus {
counter_u64_t counters[PFRES_MAX]; /* reason for passing/dropping */

File Metadata

Mime Type
text/plain
Expires
Thu, Mar 6, 9:49 PM (13 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17020293
Default Alt Text
D32136.id.diff (8 KB)

Event Timeline