1
|
diff --git a/sbin/pfctl/parse.y b/sbin/pfctl/parse.y
|
2
|
index 3e52fb2..c99403d 100644
|
3
|
--- a/sbin/pfctl/parse.y
|
4
|
+++ b/sbin/pfctl/parse.y
|
5
|
@@ -235,6 +235,7 @@ struct filter_opts {
|
6
|
int fragment;
|
7
|
int allowopts;
|
8
|
char *label;
|
9
|
+ char *schedule;
|
10
|
struct node_qassign queues;
|
11
|
char *tag;
|
12
|
char *match_tag;
|
13
|
@@ -342,6 +343,7 @@ int expand_skip_interface(struct node_if *);
|
14
|
int check_rulestate(int);
|
15
|
int getservice(char *);
|
16
|
int rule_label(struct pf_rule *, char *);
|
17
|
+int rule_schedule(struct pf_rule *, char *);
|
18
|
int rt_tableid_max(void);
|
19
|
|
20
|
void mv_rules(struct pf_ruleset *, struct pf_ruleset *);
|
21
|
@@ -444,7 +446,7 @@ int parseport(char *, struct range *r, int);
|
22
|
%token PASS BLOCK SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
|
23
|
%token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
|
24
|
%token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
|
25
|
-%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
|
26
|
+%token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL SCHEDULE
|
27
|
%token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DSCP DROP TABLE
|
28
|
%token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
|
29
|
%token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
|
30
|
@@ -489,7 +491,7 @@ int parseport(char *, struct range *r, int);
|
31
|
%type <v.gid> gids gid_list gid_item
|
32
|
%type <v.route> route
|
33
|
%type <v.redirection> redirection redirpool
|
34
|
-%type <v.string> label stringall tag anchorname
|
35
|
+%type <v.string> label schedule stringall tag anchorname
|
36
|
%type <v.string> string varstring numberstring
|
37
|
%type <v.keep_state> keep
|
38
|
%type <v.state_opt> state_opt_spec state_opt_list state_opt_item
|
39
|
@@ -1911,6 +1913,9 @@ pfrule : action dir logquick interface route af proto fromto
|
40
|
if (rule_label(&r, $9.label))
|
41
|
YYERROR;
|
42
|
free($9.label);
|
43
|
+ if (rule_schedule(&r, $9.schedule))
|
44
|
+ YYERROR;
|
45
|
+ free($9.schedule);
|
46
|
r.flags = $9.flags.b1;
|
47
|
r.flagset = $9.flags.b2;
|
48
|
if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) {
|
49
|
@@ -2366,6 +2371,13 @@ filter_opt : USER uids {
|
50
|
}
|
51
|
filter_opts.label = $1;
|
52
|
}
|
53
|
+ | schedule {
|
54
|
+ if (filter_opts.schedule) {
|
55
|
+ yyerror("schedule label cannot be redefined");
|
56
|
+ YYERROR;
|
57
|
+ }
|
58
|
+ filter_opts.schedule = $1;
|
59
|
+ }
|
60
|
| qname {
|
61
|
if (filter_opts.queues.qname) {
|
62
|
yyerror("queue cannot be redefined");
|
63
|
@@ -3710,6 +3722,11 @@ label : LABEL STRING {
|
64
|
}
|
65
|
;
|
66
|
|
67
|
+schedule : SCHEDULE STRING {
|
68
|
+ $$ = $2;
|
69
|
+ }
|
70
|
+ ;
|
71
|
+
|
72
|
qname : QUEUE STRING {
|
73
|
$$.qname = $2;
|
74
|
$$.pqname = NULL;
|
75
|
@@ -5106,6 +5123,7 @@ expand_rule(struct pf_rule *r,
|
76
|
int added = 0, error = 0;
|
77
|
char ifname[IF_NAMESIZE];
|
78
|
char label[PF_RULE_LABEL_SIZE];
|
79
|
+ char schedule[PF_RULE_LABEL_SIZE];
|
80
|
char tagname[PF_TAG_NAME_SIZE];
|
81
|
char match_tagname[PF_TAG_NAME_SIZE];
|
82
|
struct pf_pooladdr *pa;
|
83
|
@@ -5114,6 +5132,8 @@ expand_rule(struct pf_rule *r,
|
84
|
|
85
|
if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label))
|
86
|
errx(1, "expand_rule: strlcpy");
|
87
|
+ if (strlcpy(schedule, r->schedule, sizeof(schedule)) > sizeof(schedule))
|
88
|
+ errx(1, "expand_rule: strlcpy");
|
89
|
if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname))
|
90
|
errx(1, "expand_rule: strlcpy");
|
91
|
if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >=
|
92
|
@@ -5165,6 +5185,9 @@ expand_rule(struct pf_rule *r,
|
93
|
if (strlcpy(r->label, label, sizeof(r->label)) >=
|
94
|
sizeof(r->label))
|
95
|
errx(1, "expand_rule: strlcpy");
|
96
|
+ if (strlcpy(r->schedule, schedule, sizeof(r->schedule)) >=
|
97
|
+ sizeof(r->schedule))
|
98
|
+ errx(1, "expand_rule: strlcpy");
|
99
|
if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >=
|
100
|
sizeof(r->tagname))
|
101
|
errx(1, "expand_rule: strlcpy");
|
102
|
@@ -5173,6 +5196,8 @@ expand_rule(struct pf_rule *r,
|
103
|
errx(1, "expand_rule: strlcpy");
|
104
|
expand_label(r->label, PF_RULE_LABEL_SIZE, r->ifname, r->af,
|
105
|
src_host, src_port, dst_host, dst_port, proto->proto);
|
106
|
+ expand_label(r->schedule, PF_RULE_LABEL_SIZE, r->ifname, r->af,
|
107
|
+ src_host, src_port, dst_host, dst_port, proto->proto);
|
108
|
expand_label(r->tagname, PF_TAG_NAME_SIZE, r->ifname, r->af,
|
109
|
src_host, src_port, dst_host, dst_port, proto->proto);
|
110
|
expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r->ifname,
|
111
|
@@ -5434,6 +5459,7 @@ lookup(char *s)
|
112
|
{ "rtable", RTABLE},
|
113
|
{ "rule", RULE},
|
114
|
{ "ruleset-optimization", RULESET_OPTIMIZATION},
|
115
|
+ { "schedule", SCHEDULE},
|
116
|
{ "scrub", SCRUB},
|
117
|
{ "set", SET},
|
118
|
{ "set-tos", SETTOS},
|
119
|
@@ -6065,6 +6091,20 @@ rule_label(struct pf_rule *r, char *s)
|
120
|
return (0);
|
121
|
}
|
122
|
|
123
|
+int
|
124
|
+rule_schedule(struct pf_rule *r, char *s)
|
125
|
+{
|
126
|
+ if (s) {
|
127
|
+ if (strlcpy(r->schedule, s, sizeof(r->label)) >=
|
128
|
+ sizeof(r->label)) {
|
129
|
+ yyerror("rule schedule label too long (max %d chars)",
|
130
|
+ sizeof(r->label)-1);
|
131
|
+ return (-1);
|
132
|
+ }
|
133
|
+ }
|
134
|
+ return (0);
|
135
|
+}
|
136
|
+
|
137
|
u_int16_t
|
138
|
parseicmpspec(char *w, sa_family_t af)
|
139
|
{
|
140
|
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
|
141
|
index 64b4a05..1e957f6 100644
|
142
|
--- a/sbin/pfctl/pfctl.c
|
143
|
+++ b/sbin/pfctl/pfctl.c
|
144
|
@@ -78,6 +78,7 @@ void pfctl_addrprefix(char *, struct pf_addr *);
|
145
|
int pfctl_kill_src_nodes(int, const char *, int);
|
146
|
int pfctl_net_kill_states(int, const char *, int);
|
147
|
int pfctl_label_kill_states(int, const char *, int);
|
148
|
+int pfctl_kill_schedule(int, const char *, int);
|
149
|
int pfctl_id_kill_states(int, const char *, int);
|
150
|
void pfctl_init_options(struct pfctl *);
|
151
|
int pfctl_load_options(struct pfctl *);
|
152
|
@@ -117,6 +118,7 @@ const char *optiopt = NULL;
|
153
|
char *pf_device = "/dev/pf";
|
154
|
char *ifaceopt;
|
155
|
char *tableopt;
|
156
|
+char *schedule = NULL;
|
157
|
const char *tblcmdopt;
|
158
|
int src_node_killers;
|
159
|
char *src_node_kill[2];
|
160
|
@@ -654,6 +656,25 @@ pfctl_net_kill_states(int dev, const char *iface, int opts)
|
161
|
}
|
162
|
|
163
|
int
|
164
|
+pfctl_kill_schedule(int dev, const char *sched, int opts)
|
165
|
+{
|
166
|
+ struct pfioc_schedule_kill psk;
|
167
|
+
|
168
|
+ memset(&psk, 0, sizeof(psk));
|
169
|
+ if (sched != NULL && strlcpy(psk.schedule, sched,
|
170
|
+ sizeof(psk.schedule)) >= sizeof(psk.schedule))
|
171
|
+ errx(1, "invalid schedule label: %s", sched);
|
172
|
+
|
173
|
+ if (ioctl(dev, DIOCKILLSCHEDULE, &psk))
|
174
|
+ err(1, "DIOCKILLSCHEDULE");
|
175
|
+
|
176
|
+ if ((opts & PF_OPT_QUIET) == 0)
|
177
|
+ fprintf(stderr, "killed %d states from %s schedule label\n",
|
178
|
+ psk.numberkilled, sched);
|
179
|
+ return (0);
|
180
|
+}
|
181
|
+
|
182
|
+int
|
183
|
pfctl_label_kill_states(int dev, const char *iface, int opts)
|
184
|
{
|
185
|
struct pfioc_state_kill psk;
|
186
|
@@ -2003,7 +2024,7 @@ main(int argc, char *argv[])
|
187
|
usage();
|
188
|
|
189
|
while ((ch = getopt(argc, argv,
|
190
|
- "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:z")) != -1) {
|
191
|
+ "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:y:z")) != -1) {
|
192
|
switch (ch) {
|
193
|
case 'a':
|
194
|
anchoropt = optarg;
|
195
|
@@ -2117,6 +2138,12 @@ main(int argc, char *argv[])
|
196
|
opts |= PF_OPT_VERBOSE2;
|
197
|
opts |= PF_OPT_VERBOSE;
|
198
|
break;
|
199
|
+ case 'y':
|
200
|
+ if (schedule != NULL && strlen(schedule) > 64)
|
201
|
+ errx(1, "Schedule label cannot be more than 64 characters\n");
|
202
|
+ schedule = optarg;
|
203
|
+ mode = O_RDWR;
|
204
|
+ break;
|
205
|
case 'x':
|
206
|
debugopt = pfctl_lookup_option(optarg, debugopt_list);
|
207
|
if (debugopt == NULL) {
|
208
|
@@ -2325,6 +2352,9 @@ main(int argc, char *argv[])
|
209
|
if (src_node_killers)
|
210
|
pfctl_kill_src_nodes(dev, ifaceopt, opts);
|
211
|
|
212
|
+ if (schedule)
|
213
|
+ pfctl_kill_schedule(dev, schedule, opts);
|
214
|
+
|
215
|
if (tblcmdopt != NULL) {
|
216
|
error = pfctl_command_tables(argc, argv, tableopt,
|
217
|
tblcmdopt, rulesopt, anchorname, opts);
|
218
|
diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h
|
219
|
index 0138557..5ff131c 100644
|
220
|
--- a/sys/net/pfvar.h
|
221
|
+++ b/sys/net/pfvar.h
|
222
|
@@ -489,6 +489,7 @@ struct pf_rule {
|
223
|
union pf_rule_ptr skip[PF_SKIP_COUNT];
|
224
|
#define PF_RULE_LABEL_SIZE 64
|
225
|
char label[PF_RULE_LABEL_SIZE];
|
226
|
+ char schedule[PF_RULE_LABEL_SIZE];
|
227
|
char ifname[IFNAMSIZ];
|
228
|
char qname[PF_QNAME_SIZE];
|
229
|
char pqname[PF_QNAME_SIZE];
|
230
|
@@ -1321,6 +1322,11 @@ struct pfioc_state_kill {
|
231
|
u_int psk_killed;
|
232
|
};
|
233
|
|
234
|
+struct pfioc_schedule_kill {
|
235
|
+ int numberkilled;
|
236
|
+ char schedule[PF_RULE_LABEL_SIZE];
|
237
|
+};
|
238
|
+
|
239
|
struct pfioc_states {
|
240
|
int ps_len;
|
241
|
union {
|
242
|
@@ -1401,6 +1407,7 @@ struct pfioc_trans {
|
243
|
#endif
|
244
|
#define DIOCGETNAMEDALTQ _IOWR('D', 94, struct pfioc_ruleset)
|
245
|
#define DIOCGETNAMEDTAG _IOR('D', 95, u_int32_t)
|
246
|
+#define DIOCKILLSCHEDULE _IOWR('D', 96, struct pfioc_schedule_kill)
|
247
|
|
248
|
struct pfioc_table {
|
249
|
struct pfr_table pfrio_table;
|
250
|
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
|
251
|
index 88c9076..e48400f 100644
|
252
|
--- a/sys/netpfil/pf/pf_ioctl.c
|
253
|
+++ b/sys/netpfil/pf/pf_ioctl.c
|
254
|
@@ -1702,6 +1702,30 @@ relock_DIOCKILLSTATES:
|
255
|
break;
|
256
|
}
|
257
|
|
258
|
+ case DIOCKILLSCHEDULE: {
|
259
|
+ struct pf_state *state;
|
260
|
+ struct pfioc_schedule_kill *psk = (struct pfioc_schedule_kill *)addr;
|
261
|
+ int killed = 0;
|
262
|
+ u_int i;
|
263
|
+
|
264
|
+ for (i = 0; i <= V_pf_hashmask; i++) {
|
265
|
+ struct pf_idhash *ih = &V_pf_idhash[i];
|
266
|
+
|
267
|
+relock_DIOCKILLSCHEDULE:
|
268
|
+ PF_HASHROW_LOCK(ih);
|
269
|
+ LIST_FOREACH(state, &ih->states, entry) {
|
270
|
+ if (!strcmp(psk->schedule, state->rule.ptr->schedule)) {
|
271
|
+ pf_unlink_state(state, PF_ENTER_LOCKED);
|
272
|
+ killed++;
|
273
|
+ goto relock_DIOCKILLSCHEDULE;
|
274
|
+ }
|
275
|
+ }
|
276
|
+ PF_HASHROW_UNLOCK(ih);
|
277
|
+ }
|
278
|
+ psk->numberkilled = killed;
|
279
|
+ break;
|
280
|
+ }
|
281
|
+
|
282
|
case DIOCADDSTATE: {
|
283
|
struct pfioc_state *ps = (struct pfioc_state *)addr;
|
284
|
struct pfsync_state *sp = &ps->state;
|