Page MenuHomeFreeBSD

D29669.diff
No OneTemporary

D29669.diff

Index: lib/libpfctl/libpfctl.h
===================================================================
--- lib/libpfctl/libpfctl.h
+++ lib/libpfctl/libpfctl.h
@@ -43,6 +43,7 @@
struct pf_rule_addr dst;
union pf_rule_ptr skip[PF_SKIP_COUNT];
char label[PF_RULE_LABEL_SIZE];
+ char schedule[PF_RULE_LABEL_SIZE];
char ifname[IFNAMSIZ];
char qname[PF_QNAME_SIZE];
char pqname[PF_QNAME_SIZE];
@@ -174,5 +175,6 @@
int libpfctl_add_rule(int dev, const struct pfctl_rule *r,
const char *anchor, const char *anchor_call, u_int32_t ticket,
u_int32_t pool_ticket);
+int libpfctl_kill_schedule(int dev, const char *sched, int *killed);
#endif
Index: lib/libpfctl/libpfctl.c
===================================================================
--- lib/libpfctl/libpfctl.c
+++ lib/libpfctl/libpfctl.c
@@ -291,6 +291,9 @@
rule->skip[i].nr = skip[i];
strlcpy(rule->label, nvlist_get_string(nvl, "label"), PF_RULE_LABEL_SIZE);
+ if (nvlist_exists_string(nvl, "schedule"))
+ strlcpy(rule->schedule, nvlist_get_string(nvl, "schedule"),
+ PF_RULE_LABEL_SIZE);
strlcpy(rule->ifname, nvlist_get_string(nvl, "ifname"), IFNAMSIZ);
strlcpy(rule->qname, nvlist_get_string(nvl, "qname"), PF_QNAME_SIZE);
strlcpy(rule->pqname, nvlist_get_string(nvl, "pqname"), PF_QNAME_SIZE);
@@ -395,6 +398,7 @@
pfctl_nv_add_rule_addr(nvlr, "dst", &r->dst);
nvlist_add_string(nvlr, "label", r->label);
+ nvlist_add_string(nvlr, "schedule", r->schedule);
nvlist_add_string(nvlr, "ifname", r->ifname);
nvlist_add_string(nvlr, "qname", r->qname);
nvlist_add_string(nvlr, "pqname", r->pqname);
@@ -534,3 +538,40 @@
return (0);
}
+
+int
+libpfctl_kill_schedule(int dev, const char *sched, int *killed)
+{
+ struct pfioc_nv nv;
+ nvlist_t *nvl;
+ int ret;
+
+ nvl = nvlist_create(0);
+
+ nvlist_add_string(nvl, "schedule", sched);
+
+ nv.data = nvlist_pack(nvl, &nv.len);
+ nv.size = nv.len; // Reply will be smaller than the request
+
+ nvlist_destroy(nvl);
+
+ ret = ioctl(dev, DIOCKILLSCHEDULE, &nv);
+ if (ret != 0) {
+ free(nv.data);
+ return (ret);
+ }
+
+ nvl = nvlist_unpack(nv.data, nv.len, 0);
+ if (nvl == NULL) {
+ free(nv.data);
+ return (EIO);
+ }
+
+ if (killed)
+ *killed = nvlist_get_number(nvl, "killed");
+
+ free(nv.data);
+ nvlist_destroy(nvl);
+
+ return (0);
+}
Index: sbin/pfctl/parse.y
===================================================================
--- sbin/pfctl/parse.y
+++ sbin/pfctl/parse.y
@@ -242,6 +242,7 @@
int fragment;
int allowopts;
char *label;
+ char *schedule;
struct node_qassign queues;
char *tag;
char *match_tag;
@@ -349,6 +350,7 @@
int check_rulestate(int);
int getservice(char *);
int rule_label(struct pfctl_rule *, char *);
+int rule_schedule(struct pfctl_rule *, char *);
int rt_tableid_max(void);
void mv_rules(struct pfctl_ruleset *, struct pfctl_ruleset *);
@@ -460,7 +462,7 @@
%token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY FAILPOLICY
%token RANDOMID REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
-%token ANTISPOOF FOR INCLUDE
+%token ANTISPOOF FOR INCLUDE SCHEDULE
%token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
%token ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME
%token UPPERLIMIT QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE TARGET INTERVAL
@@ -499,7 +501,7 @@
%type <v.gid> gids gid_list gid_item
%type <v.route> route
%type <v.redirection> redirection redirpool
-%type <v.string> label stringall tag anchorname
+%type <v.string> label schedule stringall tag anchorname
%type <v.string> string varstring numberstring
%type <v.keep_state> keep
%type <v.state_opt> state_opt_spec state_opt_list state_opt_item
@@ -2090,6 +2092,9 @@
if (rule_label(&r, $9.label))
YYERROR;
free($9.label);
+ if (rule_schedule(&r, $9.schedule))
+ YYERROR;
+ free($9.schedule);
r.flags = $9.flags.b1;
r.flagset = $9.flags.b2;
if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) {
@@ -2533,6 +2538,13 @@
}
filter_opts.label = $1;
}
+ | schedule {
+ if (filter_opts.schedule) {
+ yyerror("schedule cannot be redefined");
+ YYERROR;
+ }
+ filter_opts.schedule = $1;
+ }
| qname {
if (filter_opts.queues.qname) {
yyerror("queue cannot be redefined");
@@ -3852,6 +3864,11 @@
}
;
+schedule : SCHEDULE STRING {
+ $$ = $2;
+ }
+ ;
+
qname : QUEUE STRING {
$$.qname = $2;
$$.pqname = NULL;
@@ -5260,6 +5277,7 @@
int added = 0, error = 0;
char ifname[IF_NAMESIZE];
char label[PF_RULE_LABEL_SIZE];
+ char schedule[PF_RULE_LABEL_SIZE];
char tagname[PF_TAG_NAME_SIZE];
char match_tagname[PF_TAG_NAME_SIZE];
struct pf_pooladdr *pa;
@@ -5268,6 +5286,8 @@
if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label))
errx(1, "expand_rule: strlcpy");
+ if (strlcpy(schedule, r->schedule, sizeof(schedule)) >= sizeof(schedule))
+ errx(1, "expand_rule: strlcpy");
if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname))
errx(1, "expand_rule: strlcpy");
if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >=
@@ -5319,6 +5339,9 @@
if (strlcpy(r->label, label, sizeof(r->label)) >=
sizeof(r->label))
errx(1, "expand_rule: strlcpy");
+ if (strlcpy(r->schedule, schedule, sizeof(r->schedule)) >=
+ sizeof(r->schedule))
+ errx(1, "expand_rule: strlcpy");
if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >=
sizeof(r->tagname))
errx(1, "expand_rule: strlcpy");
@@ -5327,6 +5350,8 @@
errx(1, "expand_rule: strlcpy");
expand_label(r->label, PF_RULE_LABEL_SIZE, r->ifname, r->af,
src_host, src_port, dst_host, dst_port, proto->proto);
+ expand_label(r->schedule, PF_RULE_LABEL_SIZE, r->ifname, r->af,
+ src_host, src_port, dst_host, dst_port, proto->proto);
expand_label(r->tagname, PF_TAG_NAME_SIZE, r->ifname, r->af,
src_host, src_port, dst_host, dst_port, proto->proto);
expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r->ifname,
@@ -5592,6 +5617,7 @@
{ "rtable", RTABLE},
{ "rule", RULE},
{ "ruleset-optimization", RULESET_OPTIMIZATION},
+ { "schedule", SCHEDULE},
{ "scrub", SCRUB},
{ "set", SET},
{ "set-tos", SETTOS},
@@ -6227,6 +6253,20 @@
return (0);
}
+int
+rule_schedule(struct pfctl_rule *r, char *s)
+{
+ if (s) {
+ if (strlcpy(r->schedule, s, sizeof(r->schedule)) >=
+ sizeof(r->schedule)) {
+ yyerror("rule schedule too long (max %d chars)",
+ sizeof(r->schedule)-1);
+ return (-1);
+ }
+ }
+ return (0);
+}
+
u_int16_t
parseicmpspec(char *w, sa_family_t af)
{
Index: sbin/pfctl/pfctl.8
===================================================================
--- sbin/pfctl/pfctl.8
+++ sbin/pfctl/pfctl.8
@@ -26,7 +26,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd October 3, 2016
+.Dd April 9, 2021
.Dt PFCTL 8
.Os
.Sh NAME
@@ -56,6 +56,7 @@
.Op Ar address ...
.Oc Xc
.Op Fl x Ar level
+.Op Fl y Ar schedule
.Ek
.Sh DESCRIPTION
The
@@ -658,6 +659,9 @@
.It Fl x Cm loud
Generate debug messages for common conditions.
.El
+.It Fl y Ar schedule
+Kill all states marked with
+.Ar schedule .
.It Fl z
Clear per-rule statistics.
.El
Index: sbin/pfctl/pfctl.c
===================================================================
--- sbin/pfctl/pfctl.c
+++ sbin/pfctl/pfctl.c
@@ -125,6 +125,7 @@
static const char *pf_device = "/dev/pf";
static char *ifaceopt;
static char *tableopt;
+static char *schedule;
static const char *tblcmdopt;
static int src_node_killers;
static char *src_node_kill[2];
@@ -2122,7 +2123,7 @@
usage();
while ((ch = getopt(argc, argv,
- "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:z")) != -1) {
+ "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:y:z")) != -1) {
switch (ch) {
case 'a':
anchoropt = optarg;
@@ -2244,6 +2245,14 @@
}
mode = O_RDWR;
break;
+ case 'y':
+ if (schedule != NULL && strlen(schedule) >
+ PF_RULE_LABEL_SIZE)
+ errx(1, "Schedule label cannot be more than %d"
+ " characters\n", PF_RULE_LABEL_SIZE);
+ schedule = optarg;
+ mode = O_RDWR;
+ break;
case 'z':
opts |= PF_OPT_CLRRULECTRS;
mode = O_RDWR;
@@ -2447,6 +2456,17 @@
if (src_node_killers)
pfctl_kill_src_nodes(dev, ifaceopt, opts);
+ if (schedule) {
+ int killed;
+
+ if (libpfctl_kill_schedule(dev, schedule, &killed))
+ err(1, "DIOCKILLSCHEDULE");
+
+ if ((opts & PF_OPT_QUIET) == 0)
+ fprintf(stderr, "killed %d states from %s schedule label\n",
+ killed, schedule);
+ }
+
if (tblcmdopt != NULL) {
error = pfctl_command_tables(argc, argv, tableopt,
tblcmdopt, rulesopt, anchorname, opts);
Index: sbin/pfctl/pfctl_parser.c
===================================================================
--- sbin/pfctl/pfctl_parser.c
+++ sbin/pfctl/pfctl_parser.c
@@ -1018,6 +1018,8 @@
}
if (r->label[0])
printf(" label \"%s\"", r->label);
+ if (r->schedule[0])
+ printf(" schedule \"%s\"", r->schedule);
if (r->qname[0] && r->pqname[0])
printf(" queue(%s, %s)", r->qname, r->pqname);
else if (r->qname[0])
Index: share/man/man5/pf.conf.5
===================================================================
--- share/man/man5/pf.conf.5
+++ share/man/man5/pf.conf.5
@@ -28,7 +28,7 @@
.\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd December 7, 2019
+.Dd April 9, 2021
.Dt PF.CONF 5
.Os
.Sh NAME
@@ -1807,6 +1807,13 @@
The macro expansion for the
.Ar label
directive occurs only at configuration file parse time, not during runtime.
+.It Ar schedule Aq Ar string
+Adds a schedule label (name) to the rule, which can be used to identify and
+terminate states created by matching rules,
+using
+.Bd -literal -offset indent
+# pfctl -y string
+.Ed
.It Xo Ar queue Aq Ar queue
.No \*(Ba ( Aq Ar queue ,
.Aq Ar queue )
@@ -2885,9 +2892,10 @@
"max-mss" number | "random-id" | "reassemble tcp" |
fragmentation | "allow-opts" |
"label" string | "tag" string | [ ! ] "tagged" string |
- "set prio" ( number | "(" number [ [ "," ] number ] ")" ) |
- "queue" ( string | "(" string [ [ "," ] string ] ")" ) |
- "rtable" number | "probability" number"%" | "prio" number
+ "schedule" string | "set prio" ( number | "(" number [ [ "," ]
+ number ] ")" ) | "queue" ( string | "(" string [ [ "," ]
+ string ] ")" ) | "rtable" number | "probability" number"%" |
+ "prio" number
nat-rule = [ "no" ] "nat" [ "pass" [ "log" [ "(" logopts ")" ] ] ]
[ "on" ifspec ] [ af ]
Index: sys/net/pfvar.h
===================================================================
--- sys/net/pfvar.h
+++ sys/net/pfvar.h
@@ -324,6 +324,7 @@
struct pf_rule_addr dst;
union pf_krule_ptr skip[PF_SKIP_COUNT];
char label[PF_RULE_LABEL_SIZE];
+ char schedule[PF_RULE_LABEL_SIZE];
char ifname[IFNAMSIZ];
char qname[PF_QNAME_SIZE];
char pqname[PF_QNAME_SIZE];
@@ -1299,6 +1300,8 @@
#define DIOCSETIFFLAG _IOWR('D', 89, struct pfioc_iface)
#define DIOCCLRIFFLAG _IOWR('D', 90, struct pfioc_iface)
#define DIOCKILLSRCNODES _IOWR('D', 91, struct pfioc_src_node_kill)
+#define DIOCKILLSCHEDULE _IOWR('D', 92, struct pfioc_nv)
+
struct pf_ifspeed_v0 {
char ifname[IFNAMSIZ];
u_int32_t baudrate;
Index: sys/netpfil/pf/pf_ioctl.c
===================================================================
--- sys/netpfil/pf/pf_ioctl.c
+++ sys/netpfil/pf/pf_ioctl.c
@@ -197,6 +197,7 @@
static int pf_clear_tables(void);
static void pf_clear_srcnodes(struct pf_ksrc_node *);
static void pf_kill_srcnodes(struct pfioc_src_node_kill *);
+static int pf_kill_schedule(struct pfioc_nv *);
static void pf_tbladdr_copyout(struct pf_addr_wrap *);
/*
@@ -1764,6 +1765,9 @@
&rule->dst));
PFNV_CHK(pf_nvstring(nvl, "label", rule->label, sizeof(rule->label)));
+ if (nvlist_exists_string(nvl, "schedule"))
+ PFNV_CHK(pf_nvstring(nvl, "schedule", rule->schedule,
+ sizeof(rule->schedule)));
PFNV_CHK(pf_nvstring(nvl, "ifname", rule->ifname,
sizeof(rule->ifname)));
PFNV_CHK(pf_nvstring(nvl, "qname", rule->qname, sizeof(rule->qname)));
@@ -1938,6 +1942,7 @@
}
nvlist_add_string(nvl, "label", rule->label);
+ nvlist_add_string(nvl, "schedule", rule->schedule);
nvlist_add_string(nvl, "ifname", rule->ifname);
nvlist_add_string(nvl, "qname", rule->qname);
nvlist_add_string(nvl, "pqname", rule->pqname);
@@ -4372,6 +4377,10 @@
pf_kill_srcnodes((struct pfioc_src_node_kill *)addr);
break;
+ case DIOCKILLSCHEDULE:
+ error = pf_kill_schedule((struct pfioc_nv *)addr);
+ break;
+
case DIOCSETHOSTID: {
u_int32_t *hostid = (u_int32_t *)addr;
@@ -4651,6 +4660,74 @@
psnk->psnk_killed = pf_free_src_nodes(&kill);
}
+static int
+pf_kill_schedule(struct pfioc_nv *nv)
+{
+ nvlist_t *nvl = NULL;
+ void *nvlpacked = NULL;
+ const char *schedule;
+ struct pf_state *state;
+ int killed = 0;
+ int error = 0;
+
+#define ERROUT(x) do { error = (x); goto on_error; } while (0)
+
+ if (nv->len > pf_ioctl_maxcount)
+ ERROUT(ENOMEM);
+
+ nvlpacked = malloc(nv->len, M_TEMP, M_WAITOK);
+ if (nvlpacked == NULL)
+ ERROUT(ENOMEM);
+
+ error = copyin(nv->data, nvlpacked, nv->len);
+ if (error)
+ ERROUT(error);
+
+ nvl = nvlist_unpack(nvlpacked, nv->len, 0);
+ if (nvl == NULL)
+ ERROUT(EBADMSG);
+
+ if (! nvlist_exists_string(nvl, "schedule"))
+ ERROUT(EBADMSG);
+
+ schedule = nvlist_get_string(nvl, "schedule");
+
+ for (u_long i = 0; i <= pf_hashmask; i++) {
+ struct pf_idhash *ih = &V_pf_idhash[i];
+
+relock_DIOCKILLSCHEDULE:
+ PF_HASHROW_LOCK(ih);
+ LIST_FOREACH(state, &ih->states, entry) {
+ if (!strcmp(schedule, state->rule.ptr->schedule)) {
+ pf_unlink_state(state, PF_ENTER_LOCKED);
+ killed++;
+ goto relock_DIOCKILLSCHEDULE;
+ }
+ }
+ PF_HASHROW_UNLOCK(ih);
+ }
+
+ nvlist_destroy(nvl);
+ nvl = nvlist_create(0);
+ if (nvl == NULL)
+ ERROUT(ENOMEM);
+
+ nvlist_add_number(nvl, "killed", killed);
+ free(nvlpacked, M_TEMP);
+ nvlpacked = nvlist_pack(nvl, &nv->len);
+ if (nvlpacked == NULL)
+ ERROUT(ENOMEM);
+
+ error = copyout(nvlpacked, nv->data, nv->len);
+
+#undef ERROUT
+on_error:
+ free(nvlpacked, M_TEMP);
+ nvlist_destroy(nvl);
+
+ return (error);
+}
+
/*
* XXX - Check for version missmatch!!!
*/

File Metadata

Mime Type
text/plain
Expires
Sat, Dec 20, 6:37 AM (3 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
27093061
Default Alt Text
D29669.diff (14 KB)

Event Timeline