Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111604256
D32136.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
8 KB
Referenced Files
None
Subscribers
None
D32136.id.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D32136: pfctl: userspace adaptive syncookies configration
Attached
Detach File
Event Timeline
Log In to Comment