parse.y revision 1.1.1.4 1 1.1.1.4 martti /* $NetBSD: parse.y,v 1.1.1.4 2009/12/01 07:03:06 martti Exp $ */
2 1.1.1.4 martti /* $OpenBSD: parse.y,v 1.519 2007/06/21 19:30:03 henning Exp $ */
3 1.1 itojun
4 1.1 itojun /*
5 1.1 itojun * Copyright (c) 2001 Markus Friedl. All rights reserved.
6 1.1 itojun * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
7 1.1 itojun * Copyright (c) 2001 Theo de Raadt. All rights reserved.
8 1.1 itojun * Copyright (c) 2002,2003 Henning Brauer. All rights reserved.
9 1.1 itojun *
10 1.1 itojun * Redistribution and use in source and binary forms, with or without
11 1.1 itojun * modification, are permitted provided that the following conditions
12 1.1 itojun * are met:
13 1.1 itojun * 1. Redistributions of source code must retain the above copyright
14 1.1 itojun * notice, this list of conditions and the following disclaimer.
15 1.1 itojun * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 itojun * notice, this list of conditions and the following disclaimer in the
17 1.1 itojun * documentation and/or other materials provided with the distribution.
18 1.1 itojun *
19 1.1 itojun * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20 1.1 itojun * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 1.1 itojun * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22 1.1 itojun * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23 1.1 itojun * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24 1.1 itojun * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 1.1 itojun * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 1.1 itojun * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 1.1 itojun * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 1.1 itojun * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 1.1 itojun */
30 1.1 itojun %{
31 1.1 itojun #include <sys/types.h>
32 1.1 itojun #include <sys/socket.h>
33 1.1 itojun #include <net/if.h>
34 1.1 itojun #include <netinet/in.h>
35 1.1 itojun #include <netinet/in_systm.h>
36 1.1 itojun #include <netinet/ip.h>
37 1.1 itojun #include <netinet/ip_icmp.h>
38 1.1 itojun #include <netinet/icmp6.h>
39 1.1 itojun #include <net/pfvar.h>
40 1.1 itojun #include <arpa/inet.h>
41 1.1 itojun #include <altq/altq.h>
42 1.1 itojun #include <altq/altq_cbq.h>
43 1.1 itojun #include <altq/altq_priq.h>
44 1.1 itojun #include <altq/altq_hfsc.h>
45 1.1 itojun
46 1.1 itojun #include <stdio.h>
47 1.1 itojun #include <stdlib.h>
48 1.1 itojun #include <netdb.h>
49 1.1 itojun #include <stdarg.h>
50 1.1 itojun #include <errno.h>
51 1.1 itojun #include <string.h>
52 1.1 itojun #include <ctype.h>
53 1.1.1.2 yamt #include <math.h>
54 1.1 itojun #include <err.h>
55 1.1 itojun #include <limits.h>
56 1.1 itojun #include <pwd.h>
57 1.1 itojun #include <grp.h>
58 1.1 itojun #include <md5.h>
59 1.1 itojun
60 1.1 itojun #include "pfctl_parser.h"
61 1.1 itojun #include "pfctl.h"
62 1.1 itojun
63 1.1 itojun static struct pfctl *pf = NULL;
64 1.1 itojun static FILE *fin = NULL;
65 1.1 itojun static int debug = 0;
66 1.1 itojun static int lineno = 1;
67 1.1 itojun static int errors = 0;
68 1.1 itojun static int rulestate = 0;
69 1.1 itojun static u_int16_t returnicmpdefault =
70 1.1 itojun (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
71 1.1 itojun static u_int16_t returnicmp6default =
72 1.1 itojun (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
73 1.1 itojun static int blockpolicy = PFRULE_DROP;
74 1.1 itojun static int require_order = 1;
75 1.1 itojun static int default_statelock;
76 1.1 itojun
77 1.1 itojun enum {
78 1.1 itojun PFCTL_STATE_NONE,
79 1.1 itojun PFCTL_STATE_OPTION,
80 1.1 itojun PFCTL_STATE_SCRUB,
81 1.1 itojun PFCTL_STATE_QUEUE,
82 1.1 itojun PFCTL_STATE_NAT,
83 1.1 itojun PFCTL_STATE_FILTER
84 1.1 itojun };
85 1.1 itojun
86 1.1 itojun struct node_proto {
87 1.1 itojun u_int8_t proto;
88 1.1 itojun struct node_proto *next;
89 1.1 itojun struct node_proto *tail;
90 1.1 itojun };
91 1.1 itojun
92 1.1 itojun struct node_port {
93 1.1 itojun u_int16_t port[2];
94 1.1 itojun u_int8_t op;
95 1.1 itojun struct node_port *next;
96 1.1 itojun struct node_port *tail;
97 1.1 itojun };
98 1.1 itojun
99 1.1 itojun struct node_uid {
100 1.1 itojun uid_t uid[2];
101 1.1 itojun u_int8_t op;
102 1.1 itojun struct node_uid *next;
103 1.1 itojun struct node_uid *tail;
104 1.1 itojun };
105 1.1 itojun
106 1.1 itojun struct node_gid {
107 1.1 itojun gid_t gid[2];
108 1.1 itojun u_int8_t op;
109 1.1 itojun struct node_gid *next;
110 1.1 itojun struct node_gid *tail;
111 1.1 itojun };
112 1.1 itojun
113 1.1 itojun struct node_icmp {
114 1.1 itojun u_int8_t code;
115 1.1 itojun u_int8_t type;
116 1.1 itojun u_int8_t proto;
117 1.1 itojun struct node_icmp *next;
118 1.1 itojun struct node_icmp *tail;
119 1.1 itojun };
120 1.1 itojun
121 1.1 itojun enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK,
122 1.1.1.3 peter PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN,
123 1.1.1.3 peter PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES,
124 1.1.1.3 peter PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK,
125 1.1.1.3 peter PF_STATE_OPT_TIMEOUT };
126 1.1 itojun
127 1.1 itojun enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE };
128 1.1 itojun
129 1.1 itojun struct node_state_opt {
130 1.1 itojun int type;
131 1.1 itojun union {
132 1.1 itojun u_int32_t max_states;
133 1.1 itojun u_int32_t max_src_states;
134 1.1.1.3 peter u_int32_t max_src_conn;
135 1.1.1.3 peter struct {
136 1.1.1.3 peter u_int32_t limit;
137 1.1.1.3 peter u_int32_t seconds;
138 1.1.1.3 peter } max_src_conn_rate;
139 1.1.1.3 peter struct {
140 1.1.1.3 peter u_int8_t flush;
141 1.1.1.3 peter char tblname[PF_TABLE_NAME_SIZE];
142 1.1.1.3 peter } overload;
143 1.1 itojun u_int32_t max_src_nodes;
144 1.1 itojun u_int8_t src_track;
145 1.1 itojun u_int32_t statelock;
146 1.1 itojun struct {
147 1.1 itojun int number;
148 1.1 itojun u_int32_t seconds;
149 1.1 itojun } timeout;
150 1.1 itojun } data;
151 1.1 itojun struct node_state_opt *next;
152 1.1 itojun struct node_state_opt *tail;
153 1.1 itojun };
154 1.1 itojun
155 1.1 itojun struct peer {
156 1.1 itojun struct node_host *host;
157 1.1 itojun struct node_port *port;
158 1.1 itojun };
159 1.1 itojun
160 1.1 itojun struct node_queue {
161 1.1 itojun char queue[PF_QNAME_SIZE];
162 1.1 itojun char parent[PF_QNAME_SIZE];
163 1.1 itojun char ifname[IFNAMSIZ];
164 1.1 itojun int scheduler;
165 1.1 itojun struct node_queue *next;
166 1.1 itojun struct node_queue *tail;
167 1.1 itojun } *queues = NULL;
168 1.1 itojun
169 1.1 itojun struct node_qassign {
170 1.1 itojun char *qname;
171 1.1 itojun char *pqname;
172 1.1 itojun };
173 1.1 itojun
174 1.1 itojun struct filter_opts {
175 1.1 itojun int marker;
176 1.1 itojun #define FOM_FLAGS 0x01
177 1.1 itojun #define FOM_ICMP 0x02
178 1.1 itojun #define FOM_TOS 0x04
179 1.1 itojun #define FOM_KEEP 0x08
180 1.1 itojun #define FOM_SRCTRACK 0x10
181 1.1 itojun struct node_uid *uid;
182 1.1 itojun struct node_gid *gid;
183 1.1 itojun struct {
184 1.1 itojun u_int8_t b1;
185 1.1 itojun u_int8_t b2;
186 1.1 itojun u_int16_t w;
187 1.1 itojun u_int16_t w2;
188 1.1 itojun } flags;
189 1.1 itojun struct node_icmp *icmpspec;
190 1.1 itojun u_int32_t tos;
191 1.1.1.2 yamt u_int32_t prob;
192 1.1 itojun struct {
193 1.1 itojun int action;
194 1.1 itojun struct node_state_opt *options;
195 1.1 itojun } keep;
196 1.1 itojun int fragment;
197 1.1 itojun int allowopts;
198 1.1 itojun char *label;
199 1.1 itojun struct node_qassign queues;
200 1.1 itojun char *tag;
201 1.1 itojun char *match_tag;
202 1.1 itojun u_int8_t match_tag_not;
203 1.1.1.4 martti int rtableid;
204 1.1 itojun } filter_opts;
205 1.1 itojun
206 1.1 itojun struct antispoof_opts {
207 1.1 itojun char *label;
208 1.1.1.4 martti int rtableid;
209 1.1 itojun } antispoof_opts;
210 1.1 itojun
211 1.1 itojun struct scrub_opts {
212 1.1 itojun int marker;
213 1.1 itojun #define SOM_MINTTL 0x01
214 1.1 itojun #define SOM_MAXMSS 0x02
215 1.1 itojun #define SOM_FRAGCACHE 0x04
216 1.1 itojun int nodf;
217 1.1 itojun int minttl;
218 1.1 itojun int maxmss;
219 1.1 itojun int fragcache;
220 1.1 itojun int randomid;
221 1.1 itojun int reassemble_tcp;
222 1.1.1.4 martti int rtableid;
223 1.1 itojun } scrub_opts;
224 1.1 itojun
225 1.1 itojun struct queue_opts {
226 1.1 itojun int marker;
227 1.1 itojun #define QOM_BWSPEC 0x01
228 1.1 itojun #define QOM_SCHEDULER 0x02
229 1.1 itojun #define QOM_PRIORITY 0x04
230 1.1 itojun #define QOM_TBRSIZE 0x08
231 1.1 itojun #define QOM_QLIMIT 0x10
232 1.1 itojun struct node_queue_bw queue_bwspec;
233 1.1 itojun struct node_queue_opt scheduler;
234 1.1 itojun int priority;
235 1.1 itojun int tbrsize;
236 1.1 itojun int qlimit;
237 1.1 itojun } queue_opts;
238 1.1 itojun
239 1.1 itojun struct table_opts {
240 1.1 itojun int flags;
241 1.1 itojun int init_addr;
242 1.1 itojun struct node_tinithead init_nodes;
243 1.1 itojun } table_opts;
244 1.1 itojun
245 1.1 itojun struct pool_opts {
246 1.1 itojun int marker;
247 1.1 itojun #define POM_TYPE 0x01
248 1.1 itojun #define POM_STICKYADDRESS 0x02
249 1.1 itojun u_int8_t opts;
250 1.1 itojun int type;
251 1.1 itojun int staticport;
252 1.1 itojun struct pf_poolhashkey *key;
253 1.1 itojun
254 1.1 itojun } pool_opts;
255 1.1 itojun
256 1.1 itojun
257 1.1 itojun struct node_hfsc_opts hfsc_opts;
258 1.1 itojun
259 1.1 itojun int yyerror(const char *, ...);
260 1.1 itojun int disallow_table(struct node_host *, const char *);
261 1.1.1.4 martti int disallow_urpf_failed(struct node_host *, const char *);
262 1.1 itojun int disallow_alias(struct node_host *, const char *);
263 1.1.1.4 martti int rule_consistent(struct pf_rule *, int);
264 1.1.1.4 martti int filter_consistent(struct pf_rule *, int);
265 1.1 itojun int nat_consistent(struct pf_rule *);
266 1.1 itojun int rdr_consistent(struct pf_rule *);
267 1.1 itojun int process_tabledef(char *, struct table_opts *);
268 1.1 itojun int yyparse(void);
269 1.1 itojun void expand_label_str(char *, size_t, const char *, const char *);
270 1.1 itojun void expand_label_if(const char *, char *, size_t, const char *);
271 1.1 itojun void expand_label_addr(const char *, char *, size_t, u_int8_t,
272 1.1 itojun struct node_host *);
273 1.1 itojun void expand_label_port(const char *, char *, size_t, struct node_port *);
274 1.1 itojun void expand_label_proto(const char *, char *, size_t, u_int8_t);
275 1.1 itojun void expand_label_nr(const char *, char *, size_t);
276 1.1 itojun void expand_label(char *, size_t, const char *, u_int8_t, struct node_host *,
277 1.1 itojun struct node_port *, struct node_host *, struct node_port *,
278 1.1 itojun u_int8_t);
279 1.1 itojun void expand_rule(struct pf_rule *, struct node_if *, struct node_host *,
280 1.1 itojun struct node_proto *, struct node_os*, struct node_host *,
281 1.1 itojun struct node_port *, struct node_host *, struct node_port *,
282 1.1.1.2 yamt struct node_uid *, struct node_gid *, struct node_icmp *,
283 1.1.1.2 yamt const char *);
284 1.1 itojun int expand_altq(struct pf_altq *, struct node_if *, struct node_queue *,
285 1.1 itojun struct node_queue_bw bwspec, struct node_queue_opt *);
286 1.1 itojun int expand_queue(struct pf_altq *, struct node_if *, struct node_queue *,
287 1.1 itojun struct node_queue_bw, struct node_queue_opt *);
288 1.1.1.3 peter int expand_skip_interface(struct node_if *);
289 1.1 itojun
290 1.1 itojun int check_rulestate(int);
291 1.1 itojun int kw_cmp(const void *, const void *);
292 1.1 itojun int lookup(char *);
293 1.1 itojun int lgetc(FILE *);
294 1.1 itojun int lungetc(int);
295 1.1 itojun int findeol(void);
296 1.1 itojun int yylex(void);
297 1.1 itojun int atoul(char *, u_long *);
298 1.1 itojun int getservice(char *);
299 1.1 itojun int rule_label(struct pf_rule *, char *);
300 1.1 itojun
301 1.1 itojun TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
302 1.1 itojun struct sym {
303 1.1 itojun TAILQ_ENTRY(sym) entries;
304 1.1 itojun int used;
305 1.1 itojun int persist;
306 1.1 itojun char *nam;
307 1.1 itojun char *val;
308 1.1 itojun };
309 1.1 itojun
310 1.1 itojun
311 1.1 itojun int symset(const char *, const char *, int);
312 1.1 itojun char *symget(const char *);
313 1.1 itojun
314 1.1.1.4 martti void mv_rules(struct pf_ruleset *, struct pf_ruleset *);
315 1.1 itojun void decide_address_family(struct node_host *, sa_family_t *);
316 1.1 itojun void remove_invalid_hosts(struct node_host **, sa_family_t *);
317 1.1 itojun int invalid_redirect(struct node_host *, sa_family_t);
318 1.1 itojun u_int16_t parseicmpspec(char *, sa_family_t);
319 1.1 itojun
320 1.1 itojun TAILQ_HEAD(loadanchorshead, loadanchors)
321 1.1 itojun loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead);
322 1.1 itojun
323 1.1 itojun struct loadanchors {
324 1.1 itojun TAILQ_ENTRY(loadanchors) entries;
325 1.1 itojun char *anchorname;
326 1.1 itojun char *filename;
327 1.1 itojun };
328 1.1 itojun
329 1.1 itojun typedef struct {
330 1.1 itojun union {
331 1.1 itojun u_int32_t number;
332 1.1 itojun int i;
333 1.1 itojun char *string;
334 1.1.1.4 martti int rtableid;
335 1.1 itojun struct {
336 1.1 itojun u_int8_t b1;
337 1.1 itojun u_int8_t b2;
338 1.1 itojun u_int16_t w;
339 1.1 itojun u_int16_t w2;
340 1.1 itojun } b;
341 1.1 itojun struct range {
342 1.1 itojun int a;
343 1.1 itojun int b;
344 1.1 itojun int t;
345 1.1 itojun } range;
346 1.1 itojun struct node_if *interface;
347 1.1 itojun struct node_proto *proto;
348 1.1 itojun struct node_icmp *icmp;
349 1.1 itojun struct node_host *host;
350 1.1 itojun struct node_os *os;
351 1.1 itojun struct node_port *port;
352 1.1 itojun struct node_uid *uid;
353 1.1 itojun struct node_gid *gid;
354 1.1 itojun struct node_state_opt *state_opt;
355 1.1 itojun struct peer peer;
356 1.1 itojun struct {
357 1.1 itojun struct peer src, dst;
358 1.1 itojun struct node_os *src_os;
359 1.1 itojun } fromto;
360 1.1 itojun struct {
361 1.1 itojun struct node_host *host;
362 1.1 itojun u_int8_t rt;
363 1.1 itojun u_int8_t pool_opts;
364 1.1 itojun sa_family_t af;
365 1.1 itojun struct pf_poolhashkey *key;
366 1.1 itojun } route;
367 1.1 itojun struct redirection {
368 1.1 itojun struct node_host *host;
369 1.1 itojun struct range rport;
370 1.1 itojun } *redirection;
371 1.1 itojun struct {
372 1.1 itojun int action;
373 1.1 itojun struct node_state_opt *options;
374 1.1 itojun } keep_state;
375 1.1 itojun struct {
376 1.1 itojun u_int8_t log;
377 1.1.1.4 martti u_int8_t logif;
378 1.1 itojun u_int8_t quick;
379 1.1 itojun } logquick;
380 1.1.1.3 peter struct {
381 1.1.1.3 peter int neg;
382 1.1.1.3 peter char *name;
383 1.1.1.3 peter } tagged;
384 1.1 itojun struct pf_poolhashkey *hashkey;
385 1.1 itojun struct node_queue *queue;
386 1.1 itojun struct node_queue_opt queue_options;
387 1.1 itojun struct node_queue_bw queue_bwspec;
388 1.1 itojun struct node_qassign qassign;
389 1.1 itojun struct filter_opts filter_opts;
390 1.1 itojun struct antispoof_opts antispoof_opts;
391 1.1 itojun struct queue_opts queue_opts;
392 1.1 itojun struct scrub_opts scrub_opts;
393 1.1 itojun struct table_opts table_opts;
394 1.1 itojun struct pool_opts pool_opts;
395 1.1 itojun struct node_hfsc_opts hfsc_opts;
396 1.1 itojun } v;
397 1.1 itojun int lineno;
398 1.1 itojun } YYSTYPE;
399 1.1 itojun
400 1.1 itojun #define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \
401 1.1 itojun (!((addr).iflags & PFI_AFLAG_NOALIAS) || \
402 1.1 itojun !isdigit((addr).v.ifname[strlen((addr).v.ifname)-1])))
403 1.1 itojun
404 1.1 itojun %}
405 1.1 itojun
406 1.1.1.4 martti %token PASS BLOCK SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
407 1.1 itojun %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
408 1.1 itojun %token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
409 1.1 itojun %token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
410 1.1.1.4 martti %token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
411 1.1 itojun %token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
412 1.1 itojun %token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID
413 1.1.1.3 peter %token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
414 1.1 itojun %token ANTISPOOF FOR
415 1.1.1.2 yamt %token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY
416 1.1 itojun %token ALTQ CBQ PRIQ HFSC BANDWIDTH TBRSIZE LINKSHARE REALTIME UPPERLIMIT
417 1.1.1.4 martti %token QUEUE PRIORITY QLIMIT RTABLE
418 1.1.1.4 martti %token LOAD RULESET_OPTIMIZATION
419 1.1 itojun %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
420 1.1.1.3 peter %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH
421 1.1.1.4 martti %token TAGGED TAG IFBOUND FLOATING STATEPOLICY ROUTE
422 1.1 itojun %token <v.string> STRING
423 1.1 itojun %token <v.i> PORTBINARY
424 1.1 itojun %type <v.interface> interface if_list if_item_not if_item
425 1.1 itojun %type <v.number> number icmptype icmp6type uid gid
426 1.1.1.4 martti %type <v.number> tos not yesno
427 1.1.1.4 martti %type <v.i> no dir af fragcache optimizer
428 1.1.1.4 martti %type <v.i> sourcetrack flush unaryop statelock
429 1.1.1.4 martti %type <v.b> action nataction natpasslog scrubaction
430 1.1.1.3 peter %type <v.b> flags flag blockspec
431 1.1 itojun %type <v.range> port rport
432 1.1 itojun %type <v.hashkey> hashkey
433 1.1 itojun %type <v.proto> proto proto_list proto_item
434 1.1 itojun %type <v.icmp> icmpspec
435 1.1 itojun %type <v.icmp> icmp_list icmp_item
436 1.1 itojun %type <v.icmp> icmp6_list icmp6_item
437 1.1 itojun %type <v.fromto> fromto
438 1.1 itojun %type <v.peer> ipportspec from to
439 1.1 itojun %type <v.host> ipspec xhost host dynaddr host_list
440 1.1 itojun %type <v.host> redir_host_list redirspec
441 1.1 itojun %type <v.host> route_host route_host_list routespec
442 1.1 itojun %type <v.os> os xos os_list
443 1.1 itojun %type <v.port> portspec port_list port_item
444 1.1 itojun %type <v.uid> uids uid_list uid_item
445 1.1 itojun %type <v.gid> gids gid_list gid_item
446 1.1 itojun %type <v.route> route
447 1.1 itojun %type <v.redirection> redirection redirpool
448 1.1.1.4 martti %type <v.string> label string tag anchorname
449 1.1 itojun %type <v.keep_state> keep
450 1.1 itojun %type <v.state_opt> state_opt_spec state_opt_list state_opt_item
451 1.1.1.4 martti %type <v.logquick> logquick quick log logopts logopt
452 1.1.1.2 yamt %type <v.interface> antispoof_ifspc antispoof_iflst antispoof_if
453 1.1 itojun %type <v.qassign> qname
454 1.1 itojun %type <v.queue> qassign qassign_list qassign_item
455 1.1 itojun %type <v.queue_options> scheduler
456 1.1 itojun %type <v.number> cbqflags_list cbqflags_item
457 1.1 itojun %type <v.number> priqflags_list priqflags_item
458 1.1 itojun %type <v.hfsc_opts> hfscopts_list hfscopts_item hfsc_opts
459 1.1 itojun %type <v.queue_bwspec> bandwidth
460 1.1 itojun %type <v.filter_opts> filter_opts filter_opt filter_opts_l
461 1.1 itojun %type <v.antispoof_opts> antispoof_opts antispoof_opt antispoof_opts_l
462 1.1 itojun %type <v.queue_opts> queue_opts queue_opt queue_opts_l
463 1.1 itojun %type <v.scrub_opts> scrub_opts scrub_opt scrub_opts_l
464 1.1 itojun %type <v.table_opts> table_opts table_opt table_opts_l
465 1.1 itojun %type <v.pool_opts> pool_opts pool_opt pool_opts_l
466 1.1.1.3 peter %type <v.tagged> tagged
467 1.1.1.4 martti %type <v.rtableid> rtable
468 1.1 itojun %%
469 1.1 itojun
470 1.1 itojun ruleset : /* empty */
471 1.1 itojun | ruleset '\n'
472 1.1 itojun | ruleset option '\n'
473 1.1 itojun | ruleset scrubrule '\n'
474 1.1 itojun | ruleset natrule '\n'
475 1.1 itojun | ruleset binatrule '\n'
476 1.1 itojun | ruleset pfrule '\n'
477 1.1 itojun | ruleset anchorrule '\n'
478 1.1 itojun | ruleset loadrule '\n'
479 1.1 itojun | ruleset altqif '\n'
480 1.1 itojun | ruleset queuespec '\n'
481 1.1 itojun | ruleset varset '\n'
482 1.1 itojun | ruleset antispoof '\n'
483 1.1 itojun | ruleset tabledef '\n'
484 1.1.1.4 martti | '{' fakeanchor '}' '\n';
485 1.1 itojun | ruleset error '\n' { errors++; }
486 1.1 itojun ;
487 1.1 itojun
488 1.1.1.4 martti /*
489 1.1.1.4 martti * apply to previouslys specified rule: must be careful to note
490 1.1.1.4 martti * what that is: pf or nat or binat or rdr
491 1.1.1.4 martti */
492 1.1.1.4 martti fakeanchor : fakeanchor '\n'
493 1.1.1.4 martti | fakeanchor anchorrule '\n'
494 1.1.1.4 martti | fakeanchor binatrule '\n'
495 1.1.1.4 martti | fakeanchor natrule '\n'
496 1.1.1.4 martti | fakeanchor pfrule '\n'
497 1.1.1.4 martti | fakeanchor error '\n'
498 1.1.1.4 martti ;
499 1.1.1.4 martti
500 1.1.1.4 martti optimizer : string {
501 1.1.1.4 martti if (!strcmp($1, "none"))
502 1.1.1.4 martti $$ = 0;
503 1.1.1.4 martti else if (!strcmp($1, "basic"))
504 1.1.1.4 martti $$ = PF_OPTIMIZE_BASIC;
505 1.1.1.4 martti else if (!strcmp($1, "profile"))
506 1.1.1.4 martti $$ = PF_OPTIMIZE_BASIC | PF_OPTIMIZE_PROFILE;
507 1.1.1.4 martti else {
508 1.1.1.4 martti yyerror("unknown ruleset-optimization %s", $$);
509 1.1.1.4 martti YYERROR;
510 1.1.1.4 martti }
511 1.1.1.4 martti }
512 1.1.1.4 martti ;
513 1.1.1.4 martti
514 1.1 itojun option : SET OPTIMIZATION STRING {
515 1.1 itojun if (check_rulestate(PFCTL_STATE_OPTION)) {
516 1.1 itojun free($3);
517 1.1 itojun YYERROR;
518 1.1 itojun }
519 1.1 itojun if (pfctl_set_optimization(pf, $3) != 0) {
520 1.1 itojun yyerror("unknown optimization %s", $3);
521 1.1 itojun free($3);
522 1.1 itojun YYERROR;
523 1.1 itojun }
524 1.1.1.4 martti free($3);
525 1.1.1.4 martti }
526 1.1.1.4 martti | SET RULESET_OPTIMIZATION optimizer {
527 1.1.1.4 martti if (!(pf->opts & PF_OPT_OPTIMIZE)) {
528 1.1.1.4 martti pf->opts |= PF_OPT_OPTIMIZE;
529 1.1.1.4 martti pf->optimize = $3;
530 1.1.1.4 martti }
531 1.1 itojun }
532 1.1 itojun | SET TIMEOUT timeout_spec
533 1.1 itojun | SET TIMEOUT '{' timeout_list '}'
534 1.1 itojun | SET LIMIT limit_spec
535 1.1 itojun | SET LIMIT '{' limit_list '}'
536 1.1 itojun | SET LOGINTERFACE STRING {
537 1.1 itojun if (check_rulestate(PFCTL_STATE_OPTION)) {
538 1.1 itojun free($3);
539 1.1 itojun YYERROR;
540 1.1 itojun }
541 1.1 itojun if (pfctl_set_logif(pf, $3) != 0) {
542 1.1 itojun yyerror("error setting loginterface %s", $3);
543 1.1 itojun free($3);
544 1.1 itojun YYERROR;
545 1.1 itojun }
546 1.1 itojun free($3);
547 1.1 itojun }
548 1.1 itojun | SET HOSTID number {
549 1.1 itojun if ($3 == 0) {
550 1.1 itojun yyerror("hostid must be non-zero");
551 1.1 itojun YYERROR;
552 1.1 itojun }
553 1.1 itojun if (pfctl_set_hostid(pf, $3) != 0) {
554 1.1.1.2 yamt yyerror("error setting hostid %08x", $3);
555 1.1 itojun YYERROR;
556 1.1 itojun }
557 1.1 itojun }
558 1.1 itojun | SET BLOCKPOLICY DROP {
559 1.1 itojun if (pf->opts & PF_OPT_VERBOSE)
560 1.1 itojun printf("set block-policy drop\n");
561 1.1 itojun if (check_rulestate(PFCTL_STATE_OPTION))
562 1.1 itojun YYERROR;
563 1.1 itojun blockpolicy = PFRULE_DROP;
564 1.1 itojun }
565 1.1 itojun | SET BLOCKPOLICY RETURN {
566 1.1 itojun if (pf->opts & PF_OPT_VERBOSE)
567 1.1 itojun printf("set block-policy return\n");
568 1.1 itojun if (check_rulestate(PFCTL_STATE_OPTION))
569 1.1 itojun YYERROR;
570 1.1 itojun blockpolicy = PFRULE_RETURN;
571 1.1 itojun }
572 1.1 itojun | SET REQUIREORDER yesno {
573 1.1 itojun if (pf->opts & PF_OPT_VERBOSE)
574 1.1 itojun printf("set require-order %s\n",
575 1.1 itojun $3 == 1 ? "yes" : "no");
576 1.1 itojun require_order = $3;
577 1.1 itojun }
578 1.1 itojun | SET FINGERPRINTS STRING {
579 1.1 itojun if (pf->opts & PF_OPT_VERBOSE)
580 1.1.1.4 martti printf("set fingerprints \"%s\"\n", $3);
581 1.1 itojun if (check_rulestate(PFCTL_STATE_OPTION)) {
582 1.1 itojun free($3);
583 1.1 itojun YYERROR;
584 1.1 itojun }
585 1.1.1.4 martti if (!pf->anchor->name[0]) {
586 1.1.1.3 peter if (pfctl_file_fingerprints(pf->dev,
587 1.1.1.3 peter pf->opts, $3)) {
588 1.1.1.3 peter yyerror("error loading "
589 1.1.1.3 peter "fingerprints %s", $3);
590 1.1.1.3 peter free($3);
591 1.1.1.3 peter YYERROR;
592 1.1.1.3 peter }
593 1.1 itojun }
594 1.1 itojun free($3);
595 1.1 itojun }
596 1.1 itojun | SET STATEPOLICY statelock {
597 1.1 itojun if (pf->opts & PF_OPT_VERBOSE)
598 1.1 itojun switch ($3) {
599 1.1 itojun case 0:
600 1.1 itojun printf("set state-policy floating\n");
601 1.1 itojun break;
602 1.1 itojun case PFRULE_IFBOUND:
603 1.1 itojun printf("set state-policy if-bound\n");
604 1.1 itojun break;
605 1.1 itojun }
606 1.1 itojun default_statelock = $3;
607 1.1 itojun }
608 1.1 itojun | SET DEBUG STRING {
609 1.1 itojun if (check_rulestate(PFCTL_STATE_OPTION)) {
610 1.1 itojun free($3);
611 1.1 itojun YYERROR;
612 1.1 itojun }
613 1.1 itojun if (pfctl_set_debug(pf, $3) != 0) {
614 1.1 itojun yyerror("error setting debuglevel %s", $3);
615 1.1 itojun free($3);
616 1.1 itojun YYERROR;
617 1.1 itojun }
618 1.1 itojun free($3);
619 1.1 itojun }
620 1.1.1.3 peter | SET SKIP interface {
621 1.1.1.3 peter if (expand_skip_interface($3) != 0) {
622 1.1.1.3 peter yyerror("error setting skip interface(s)");
623 1.1.1.3 peter YYERROR;
624 1.1.1.3 peter }
625 1.1.1.3 peter }
626 1.1 itojun ;
627 1.1 itojun
628 1.1 itojun string : string STRING {
629 1.1 itojun if (asprintf(&$$, "%s %s", $1, $2) == -1)
630 1.1 itojun err(1, "string: asprintf");
631 1.1 itojun free($1);
632 1.1 itojun free($2);
633 1.1 itojun }
634 1.1 itojun | STRING
635 1.1 itojun ;
636 1.1 itojun
637 1.1 itojun varset : STRING '=' string {
638 1.1 itojun if (pf->opts & PF_OPT_VERBOSE)
639 1.1 itojun printf("%s = \"%s\"\n", $1, $3);
640 1.1 itojun if (symset($1, $3, 0) == -1)
641 1.1 itojun err(1, "cannot store variable %s", $1);
642 1.1 itojun free($1);
643 1.1 itojun free($3);
644 1.1 itojun }
645 1.1 itojun ;
646 1.1 itojun
647 1.1.1.4 martti anchorname : STRING { $$ = $1; }
648 1.1.1.4 martti | /* empty */ { $$ = NULL; }
649 1.1.1.4 martti ;
650 1.1.1.4 martti
651 1.1.1.4 martti optnl : optnl '\n'
652 1.1.1.4 martti |
653 1.1.1.4 martti ;
654 1.1.1.4 martti
655 1.1.1.4 martti pfa_anchorlist : pfrule optnl
656 1.1.1.4 martti | anchorrule optnl
657 1.1.1.4 martti | pfa_anchorlist pfrule optnl
658 1.1.1.4 martti | pfa_anchorlist anchorrule optnl
659 1.1.1.4 martti ;
660 1.1.1.4 martti
661 1.1.1.4 martti pfa_anchor : '{'
662 1.1.1.4 martti {
663 1.1.1.4 martti char ta[PF_ANCHOR_NAME_SIZE];
664 1.1.1.4 martti struct pf_ruleset *rs;
665 1.1.1.4 martti
666 1.1.1.4 martti /* steping into a brace anchor */
667 1.1.1.4 martti pf->asd++;
668 1.1.1.4 martti pf->bn++;
669 1.1.1.4 martti pf->brace = 1;
670 1.1.1.4 martti
671 1.1.1.4 martti /* create a holding ruleset in the root */
672 1.1.1.4 martti snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn);
673 1.1.1.4 martti rs = pf_find_or_create_ruleset(ta);
674 1.1.1.4 martti if (rs == NULL)
675 1.1.1.4 martti err(1, "pfa_anchor: pf_find_or_create_ruleset");
676 1.1.1.4 martti pf->astack[pf->asd] = rs->anchor;
677 1.1.1.4 martti pf->anchor = rs->anchor;
678 1.1.1.4 martti } '\n' pfa_anchorlist '}'
679 1.1.1.4 martti {
680 1.1.1.4 martti pf->alast = pf->anchor;
681 1.1.1.4 martti pf->asd--;
682 1.1.1.4 martti pf->anchor = pf->astack[pf->asd];
683 1.1.1.4 martti }
684 1.1.1.4 martti | /* empty */
685 1.1.1.4 martti ;
686 1.1.1.4 martti
687 1.1.1.4 martti anchorrule : ANCHOR anchorname dir quick interface af proto fromto
688 1.1.1.4 martti filter_opts pfa_anchor
689 1.1.1.4 martti {
690 1.1 itojun struct pf_rule r;
691 1.1 itojun
692 1.1 itojun if (check_rulestate(PFCTL_STATE_FILTER)) {
693 1.1.1.4 martti if ($2)
694 1.1.1.4 martti free($2);
695 1.1.1.4 martti YYERROR;
696 1.1.1.4 martti }
697 1.1.1.4 martti
698 1.1.1.4 martti if ($2 && ($2[0] == '_' || strstr($2, "/_") != NULL)) {
699 1.1 itojun free($2);
700 1.1.1.4 martti yyerror("anchor names beginning with '_' "
701 1.1.1.4 martti "are reserved for internal use");
702 1.1 itojun YYERROR;
703 1.1 itojun }
704 1.1 itojun
705 1.1.1.2 yamt memset(&r, 0, sizeof(r));
706 1.1.1.4 martti if (pf->astack[pf->asd + 1]) {
707 1.1.1.4 martti /* move inline rules into relative location */
708 1.1.1.4 martti pf_anchor_setup(&r,
709 1.1.1.4 martti &pf->astack[pf->asd]->ruleset,
710 1.1.1.4 martti $2 ? $2 : pf->alast->name);
711 1.1.1.4 martti
712 1.1.1.4 martti if (r.anchor == NULL)
713 1.1.1.4 martti err(1, "anchorrule: unable to "
714 1.1.1.4 martti "create ruleset");
715 1.1.1.4 martti
716 1.1.1.4 martti if (pf->alast != r.anchor) {
717 1.1.1.4 martti if (r.anchor->match) {
718 1.1.1.4 martti yyerror("inline anchor '%s' "
719 1.1.1.4 martti "already exists",
720 1.1.1.4 martti r.anchor->name);
721 1.1.1.4 martti YYERROR;
722 1.1.1.4 martti }
723 1.1.1.4 martti mv_rules(&pf->alast->ruleset,
724 1.1.1.4 martti &r.anchor->ruleset);
725 1.1.1.4 martti }
726 1.1.1.4 martti pf_remove_if_empty_ruleset(&pf->alast->ruleset);
727 1.1.1.4 martti pf->alast = r.anchor;
728 1.1.1.4 martti } else {
729 1.1.1.4 martti if (!$2) {
730 1.1.1.4 martti yyerror("anchors without explicit "
731 1.1.1.4 martti "rules must specify a name");
732 1.1.1.4 martti YYERROR;
733 1.1.1.4 martti }
734 1.1.1.4 martti }
735 1.1 itojun r.direction = $3;
736 1.1.1.4 martti r.quick = $4.quick;
737 1.1.1.4 martti r.af = $6;
738 1.1.1.4 martti r.prob = $9.prob;
739 1.1.1.4 martti r.rtableid = $9.rtableid;
740 1.1 itojun
741 1.1.1.4 martti if ($9.match_tag)
742 1.1.1.4 martti if (strlcpy(r.match_tagname, $9.match_tag,
743 1.1 itojun PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
744 1.1 itojun yyerror("tag too long, max %u chars",
745 1.1 itojun PF_TAG_NAME_SIZE - 1);
746 1.1 itojun YYERROR;
747 1.1 itojun }
748 1.1.1.4 martti r.match_tag_not = $9.match_tag_not;
749 1.1 itojun
750 1.1.1.4 martti decide_address_family($8.src.host, &r.af);
751 1.1.1.4 martti decide_address_family($8.dst.host, &r.af);
752 1.1 itojun
753 1.1.1.4 martti expand_rule(&r, $5, NULL, $7, $8.src_os,
754 1.1.1.4 martti $8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
755 1.1.1.4 martti 0, 0, 0, pf->astack[pf->asd + 1] ?
756 1.1.1.4 martti pf->alast->name : $2);
757 1.1.1.2 yamt free($2);
758 1.1.1.4 martti pf->astack[pf->asd + 1] = NULL;
759 1.1 itojun }
760 1.1.1.4 martti | NATANCHOR string interface af proto fromto rtable {
761 1.1 itojun struct pf_rule r;
762 1.1 itojun
763 1.1 itojun if (check_rulestate(PFCTL_STATE_NAT)) {
764 1.1 itojun free($2);
765 1.1 itojun YYERROR;
766 1.1 itojun }
767 1.1 itojun
768 1.1.1.2 yamt memset(&r, 0, sizeof(r));
769 1.1 itojun r.action = PF_NAT;
770 1.1 itojun r.af = $4;
771 1.1.1.4 martti r.rtableid = $7;
772 1.1 itojun
773 1.1 itojun decide_address_family($6.src.host, &r.af);
774 1.1 itojun decide_address_family($6.dst.host, &r.af);
775 1.1 itojun
776 1.1 itojun expand_rule(&r, $3, NULL, $5, $6.src_os,
777 1.1 itojun $6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
778 1.1.1.2 yamt 0, 0, 0, $2);
779 1.1.1.2 yamt free($2);
780 1.1 itojun }
781 1.1.1.4 martti | RDRANCHOR string interface af proto fromto rtable {
782 1.1 itojun struct pf_rule r;
783 1.1 itojun
784 1.1 itojun if (check_rulestate(PFCTL_STATE_NAT)) {
785 1.1 itojun free($2);
786 1.1 itojun YYERROR;
787 1.1 itojun }
788 1.1 itojun
789 1.1.1.2 yamt memset(&r, 0, sizeof(r));
790 1.1 itojun r.action = PF_RDR;
791 1.1 itojun r.af = $4;
792 1.1.1.4 martti r.rtableid = $7;
793 1.1 itojun
794 1.1 itojun decide_address_family($6.src.host, &r.af);
795 1.1 itojun decide_address_family($6.dst.host, &r.af);
796 1.1 itojun
797 1.1 itojun if ($6.src.port != NULL) {
798 1.1 itojun yyerror("source port parameter not supported"
799 1.1 itojun " in rdr-anchor");
800 1.1 itojun YYERROR;
801 1.1 itojun }
802 1.1 itojun if ($6.dst.port != NULL) {
803 1.1 itojun if ($6.dst.port->next != NULL) {
804 1.1 itojun yyerror("destination port list "
805 1.1 itojun "expansion not supported in "
806 1.1 itojun "rdr-anchor");
807 1.1 itojun YYERROR;
808 1.1 itojun } else if ($6.dst.port->op != PF_OP_EQ) {
809 1.1 itojun yyerror("destination port operators"
810 1.1 itojun " not supported in rdr-anchor");
811 1.1 itojun YYERROR;
812 1.1 itojun }
813 1.1 itojun r.dst.port[0] = $6.dst.port->port[0];
814 1.1 itojun r.dst.port[1] = $6.dst.port->port[1];
815 1.1 itojun r.dst.port_op = $6.dst.port->op;
816 1.1 itojun }
817 1.1 itojun
818 1.1 itojun expand_rule(&r, $3, NULL, $5, $6.src_os,
819 1.1 itojun $6.src.host, $6.src.port, $6.dst.host, $6.dst.port,
820 1.1.1.2 yamt 0, 0, 0, $2);
821 1.1.1.2 yamt free($2);
822 1.1 itojun }
823 1.1.1.4 martti | BINATANCHOR string interface af proto fromto rtable {
824 1.1 itojun struct pf_rule r;
825 1.1 itojun
826 1.1 itojun if (check_rulestate(PFCTL_STATE_NAT)) {
827 1.1 itojun free($2);
828 1.1 itojun YYERROR;
829 1.1 itojun }
830 1.1 itojun
831 1.1.1.2 yamt memset(&r, 0, sizeof(r));
832 1.1 itojun r.action = PF_BINAT;
833 1.1 itojun r.af = $4;
834 1.1.1.4 martti r.rtableid = $7;
835 1.1 itojun if ($5 != NULL) {
836 1.1 itojun if ($5->next != NULL) {
837 1.1 itojun yyerror("proto list expansion"
838 1.1 itojun " not supported in binat-anchor");
839 1.1 itojun YYERROR;
840 1.1 itojun }
841 1.1 itojun r.proto = $5->proto;
842 1.1 itojun free($5);
843 1.1 itojun }
844 1.1 itojun
845 1.1 itojun if ($6.src.host != NULL || $6.src.port != NULL ||
846 1.1 itojun $6.dst.host != NULL || $6.dst.port != NULL) {
847 1.1 itojun yyerror("fromto parameter not supported"
848 1.1 itojun " in binat-anchor");
849 1.1 itojun YYERROR;
850 1.1 itojun }
851 1.1 itojun
852 1.1 itojun decide_address_family($6.src.host, &r.af);
853 1.1 itojun decide_address_family($6.dst.host, &r.af);
854 1.1 itojun
855 1.1.1.2 yamt pfctl_add_rule(pf, &r, $2);
856 1.1.1.2 yamt free($2);
857 1.1 itojun }
858 1.1 itojun ;
859 1.1 itojun
860 1.1 itojun loadrule : LOAD ANCHOR string FROM string {
861 1.1 itojun struct loadanchors *loadanchor;
862 1.1 itojun
863 1.1.1.4 martti if (strlen(pf->anchor->name) + 1 +
864 1.1.1.4 martti strlen($3) >= MAXPATHLEN) {
865 1.1 itojun yyerror("anchorname %s too long, max %u\n",
866 1.1.1.2 yamt $3, MAXPATHLEN - 1);
867 1.1.1.2 yamt free($3);
868 1.1 itojun YYERROR;
869 1.1 itojun }
870 1.1 itojun loadanchor = calloc(1, sizeof(struct loadanchors));
871 1.1 itojun if (loadanchor == NULL)
872 1.1 itojun err(1, "loadrule: calloc");
873 1.1.1.4 martti if ((loadanchor->anchorname = malloc(MAXPATHLEN)) ==
874 1.1.1.4 martti NULL)
875 1.1.1.4 martti err(1, "loadrule: malloc");
876 1.1.1.4 martti if (pf->anchor->name[0])
877 1.1.1.4 martti snprintf(loadanchor->anchorname, MAXPATHLEN,
878 1.1.1.4 martti "%s/%s", pf->anchor->name, $3);
879 1.1.1.4 martti else
880 1.1.1.4 martti strlcpy(loadanchor->anchorname, $3, MAXPATHLEN);
881 1.1 itojun if ((loadanchor->filename = strdup($5)) == NULL)
882 1.1 itojun err(1, "loadrule: strdup");
883 1.1 itojun
884 1.1 itojun TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor,
885 1.1 itojun entries);
886 1.1 itojun
887 1.1.1.2 yamt free($3);
888 1.1 itojun free($5);
889 1.1 itojun };
890 1.1 itojun
891 1.1.1.3 peter scrubaction : no SCRUB {
892 1.1.1.3 peter $$.b2 = $$.w = 0;
893 1.1.1.3 peter if ($1)
894 1.1.1.3 peter $$.b1 = PF_NOSCRUB;
895 1.1.1.3 peter else
896 1.1.1.3 peter $$.b1 = PF_SCRUB;
897 1.1.1.3 peter }
898 1.1.1.3 peter ;
899 1.1.1.3 peter
900 1.1.1.3 peter scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts
901 1.1 itojun {
902 1.1 itojun struct pf_rule r;
903 1.1 itojun
904 1.1 itojun if (check_rulestate(PFCTL_STATE_SCRUB))
905 1.1 itojun YYERROR;
906 1.1 itojun
907 1.1 itojun memset(&r, 0, sizeof(r));
908 1.1 itojun
909 1.1.1.3 peter r.action = $1.b1;
910 1.1 itojun r.direction = $2;
911 1.1 itojun
912 1.1 itojun r.log = $3.log;
913 1.1.1.4 martti r.logif = $3.logif;
914 1.1 itojun if ($3.quick) {
915 1.1 itojun yyerror("scrub rules do not support 'quick'");
916 1.1 itojun YYERROR;
917 1.1 itojun }
918 1.1 itojun
919 1.1 itojun r.af = $5;
920 1.1 itojun if ($8.nodf)
921 1.1 itojun r.rule_flag |= PFRULE_NODF;
922 1.1 itojun if ($8.randomid)
923 1.1 itojun r.rule_flag |= PFRULE_RANDOMID;
924 1.1 itojun if ($8.reassemble_tcp) {
925 1.1 itojun if (r.direction != PF_INOUT) {
926 1.1 itojun yyerror("reassemble tcp rules can not "
927 1.1 itojun "specify direction");
928 1.1 itojun YYERROR;
929 1.1 itojun }
930 1.1 itojun r.rule_flag |= PFRULE_REASSEMBLE_TCP;
931 1.1 itojun }
932 1.1 itojun if ($8.minttl)
933 1.1 itojun r.min_ttl = $8.minttl;
934 1.1 itojun if ($8.maxmss)
935 1.1 itojun r.max_mss = $8.maxmss;
936 1.1 itojun if ($8.fragcache)
937 1.1 itojun r.rule_flag |= $8.fragcache;
938 1.1.1.4 martti r.rtableid = $8.rtableid;
939 1.1 itojun
940 1.1 itojun expand_rule(&r, $4, NULL, $6, $7.src_os,
941 1.1 itojun $7.src.host, $7.src.port, $7.dst.host, $7.dst.port,
942 1.1.1.2 yamt NULL, NULL, NULL, "");
943 1.1 itojun }
944 1.1 itojun ;
945 1.1 itojun
946 1.1 itojun scrub_opts : {
947 1.1.1.4 martti bzero(&scrub_opts, sizeof scrub_opts);
948 1.1.1.4 martti scrub_opts.rtableid = -1;
949 1.1.1.4 martti }
950 1.1 itojun scrub_opts_l
951 1.1 itojun { $$ = scrub_opts; }
952 1.1 itojun | /* empty */ {
953 1.1 itojun bzero(&scrub_opts, sizeof scrub_opts);
954 1.1.1.4 martti scrub_opts.rtableid = -1;
955 1.1 itojun $$ = scrub_opts;
956 1.1 itojun }
957 1.1 itojun ;
958 1.1 itojun
959 1.1 itojun scrub_opts_l : scrub_opts_l scrub_opt
960 1.1 itojun | scrub_opt
961 1.1 itojun ;
962 1.1 itojun
963 1.1 itojun scrub_opt : NODF {
964 1.1 itojun if (scrub_opts.nodf) {
965 1.1 itojun yyerror("no-df cannot be respecified");
966 1.1 itojun YYERROR;
967 1.1 itojun }
968 1.1 itojun scrub_opts.nodf = 1;
969 1.1 itojun }
970 1.1 itojun | MINTTL number {
971 1.1 itojun if (scrub_opts.marker & SOM_MINTTL) {
972 1.1 itojun yyerror("min-ttl cannot be respecified");
973 1.1 itojun YYERROR;
974 1.1 itojun }
975 1.1 itojun if ($2 > 255) {
976 1.1 itojun yyerror("illegal min-ttl value %d", $2);
977 1.1 itojun YYERROR;
978 1.1 itojun }
979 1.1 itojun scrub_opts.marker |= SOM_MINTTL;
980 1.1 itojun scrub_opts.minttl = $2;
981 1.1 itojun }
982 1.1 itojun | MAXMSS number {
983 1.1 itojun if (scrub_opts.marker & SOM_MAXMSS) {
984 1.1 itojun yyerror("max-mss cannot be respecified");
985 1.1 itojun YYERROR;
986 1.1 itojun }
987 1.1 itojun if ($2 > 65535) {
988 1.1 itojun yyerror("illegal max-mss value %d", $2);
989 1.1 itojun YYERROR;
990 1.1 itojun }
991 1.1 itojun scrub_opts.marker |= SOM_MAXMSS;
992 1.1 itojun scrub_opts.maxmss = $2;
993 1.1 itojun }
994 1.1 itojun | fragcache {
995 1.1 itojun if (scrub_opts.marker & SOM_FRAGCACHE) {
996 1.1 itojun yyerror("fragcache cannot be respecified");
997 1.1 itojun YYERROR;
998 1.1 itojun }
999 1.1 itojun scrub_opts.marker |= SOM_FRAGCACHE;
1000 1.1 itojun scrub_opts.fragcache = $1;
1001 1.1 itojun }
1002 1.1 itojun | REASSEMBLE STRING {
1003 1.1 itojun if (strcasecmp($2, "tcp") != 0) {
1004 1.1.1.3 peter yyerror("scrub reassemble supports only tcp, "
1005 1.1.1.3 peter "not '%s'", $2);
1006 1.1 itojun free($2);
1007 1.1 itojun YYERROR;
1008 1.1 itojun }
1009 1.1 itojun free($2);
1010 1.1 itojun if (scrub_opts.reassemble_tcp) {
1011 1.1 itojun yyerror("reassemble tcp cannot be respecified");
1012 1.1 itojun YYERROR;
1013 1.1 itojun }
1014 1.1 itojun scrub_opts.reassemble_tcp = 1;
1015 1.1 itojun }
1016 1.1 itojun | RANDOMID {
1017 1.1 itojun if (scrub_opts.randomid) {
1018 1.1 itojun yyerror("random-id cannot be respecified");
1019 1.1 itojun YYERROR;
1020 1.1 itojun }
1021 1.1 itojun scrub_opts.randomid = 1;
1022 1.1 itojun }
1023 1.1.1.4 martti | RTABLE number {
1024 1.1.1.4 martti if ($2 > RT_TABLEID_MAX || $2 < 0) {
1025 1.1.1.4 martti yyerror("invalid rtable id");
1026 1.1.1.4 martti YYERROR;
1027 1.1.1.4 martti }
1028 1.1.1.4 martti scrub_opts.rtableid = $2;
1029 1.1.1.4 martti }
1030 1.1 itojun ;
1031 1.1 itojun
1032 1.1 itojun fragcache : FRAGMENT REASSEMBLE { $$ = 0; /* default */ }
1033 1.1 itojun | FRAGMENT FRAGCROP { $$ = PFRULE_FRAGCROP; }
1034 1.1 itojun | FRAGMENT FRAGDROP { $$ = PFRULE_FRAGDROP; }
1035 1.1 itojun ;
1036 1.1 itojun
1037 1.1 itojun antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
1038 1.1 itojun struct pf_rule r;
1039 1.1.1.2 yamt struct node_host *h = NULL, *hh;
1040 1.1 itojun struct node_if *i, *j;
1041 1.1 itojun
1042 1.1 itojun if (check_rulestate(PFCTL_STATE_FILTER))
1043 1.1 itojun YYERROR;
1044 1.1 itojun
1045 1.1 itojun for (i = $3; i; i = i->next) {
1046 1.1 itojun bzero(&r, sizeof(r));
1047 1.1 itojun
1048 1.1 itojun r.action = PF_DROP;
1049 1.1 itojun r.direction = PF_IN;
1050 1.1 itojun r.log = $2.log;
1051 1.1.1.4 martti r.logif = $2.logif;
1052 1.1 itojun r.quick = $2.quick;
1053 1.1 itojun r.af = $4;
1054 1.1 itojun if (rule_label(&r, $5.label))
1055 1.1 itojun YYERROR;
1056 1.1.1.4 martti r.rtableid = $5.rtableid;
1057 1.1 itojun j = calloc(1, sizeof(struct node_if));
1058 1.1 itojun if (j == NULL)
1059 1.1 itojun err(1, "antispoof: calloc");
1060 1.1 itojun if (strlcpy(j->ifname, i->ifname,
1061 1.1 itojun sizeof(j->ifname)) >= sizeof(j->ifname)) {
1062 1.1 itojun free(j);
1063 1.1 itojun yyerror("interface name too long");
1064 1.1 itojun YYERROR;
1065 1.1 itojun }
1066 1.1 itojun j->not = 1;
1067 1.1.1.2 yamt if (i->dynamic) {
1068 1.1.1.2 yamt h = calloc(1, sizeof(*h));
1069 1.1.1.2 yamt if (h == NULL)
1070 1.1.1.2 yamt err(1, "address: calloc");
1071 1.1.1.2 yamt h->addr.type = PF_ADDR_DYNIFTL;
1072 1.1.1.2 yamt set_ipmask(h, 128);
1073 1.1.1.2 yamt if (strlcpy(h->addr.v.ifname, i->ifname,
1074 1.1.1.2 yamt sizeof(h->addr.v.ifname)) >=
1075 1.1.1.2 yamt sizeof(h->addr.v.ifname)) {
1076 1.1.1.3 peter free(h);
1077 1.1.1.2 yamt yyerror(
1078 1.1.1.2 yamt "interface name too long");
1079 1.1.1.2 yamt YYERROR;
1080 1.1.1.2 yamt }
1081 1.1.1.2 yamt hh = malloc(sizeof(*hh));
1082 1.1.1.2 yamt if (hh == NULL)
1083 1.1.1.2 yamt err(1, "address: malloc");
1084 1.1.1.2 yamt bcopy(h, hh, sizeof(*hh));
1085 1.1.1.2 yamt h->addr.iflags = PFI_AFLAG_NETWORK;
1086 1.1.1.2 yamt } else {
1087 1.1.1.2 yamt h = ifa_lookup(j->ifname,
1088 1.1.1.2 yamt PFI_AFLAG_NETWORK);
1089 1.1.1.2 yamt hh = NULL;
1090 1.1.1.2 yamt }
1091 1.1 itojun
1092 1.1 itojun if (h != NULL)
1093 1.1 itojun expand_rule(&r, j, NULL, NULL, NULL, h,
1094 1.1.1.2 yamt NULL, NULL, NULL, NULL, NULL,
1095 1.1.1.2 yamt NULL, "");
1096 1.1 itojun
1097 1.1 itojun if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
1098 1.1 itojun bzero(&r, sizeof(r));
1099 1.1 itojun
1100 1.1 itojun r.action = PF_DROP;
1101 1.1 itojun r.direction = PF_IN;
1102 1.1 itojun r.log = $2.log;
1103 1.1 itojun r.quick = $2.quick;
1104 1.1 itojun r.af = $4;
1105 1.1 itojun if (rule_label(&r, $5.label))
1106 1.1 itojun YYERROR;
1107 1.1.1.4 martti r.rtableid = $5.rtableid;
1108 1.1.1.2 yamt if (hh != NULL)
1109 1.1.1.2 yamt h = hh;
1110 1.1.1.2 yamt else
1111 1.1.1.2 yamt h = ifa_lookup(i->ifname, 0);
1112 1.1 itojun if (h != NULL)
1113 1.1 itojun expand_rule(&r, NULL, NULL,
1114 1.1 itojun NULL, NULL, h, NULL, NULL,
1115 1.1.1.2 yamt NULL, NULL, NULL, NULL, "");
1116 1.1.1.2 yamt } else
1117 1.1.1.2 yamt free(hh);
1118 1.1 itojun }
1119 1.1 itojun free($5.label);
1120 1.1 itojun }
1121 1.1 itojun ;
1122 1.1 itojun
1123 1.1.1.2 yamt antispoof_ifspc : FOR antispoof_if { $$ = $2; }
1124 1.1 itojun | FOR '{' antispoof_iflst '}' { $$ = $3; }
1125 1.1 itojun ;
1126 1.1 itojun
1127 1.1.1.2 yamt antispoof_iflst : antispoof_if { $$ = $1; }
1128 1.1.1.2 yamt | antispoof_iflst comma antispoof_if {
1129 1.1 itojun $1->tail->next = $3;
1130 1.1 itojun $1->tail = $3;
1131 1.1 itojun $$ = $1;
1132 1.1 itojun }
1133 1.1 itojun ;
1134 1.1 itojun
1135 1.1.1.2 yamt antispoof_if : if_item { $$ = $1; }
1136 1.1.1.2 yamt | '(' if_item ')' {
1137 1.1.1.2 yamt $2->dynamic = 1;
1138 1.1.1.2 yamt $$ = $2;
1139 1.1.1.2 yamt }
1140 1.1.1.2 yamt ;
1141 1.1.1.2 yamt
1142 1.1.1.4 martti antispoof_opts : {
1143 1.1.1.4 martti bzero(&antispoof_opts, sizeof antispoof_opts);
1144 1.1.1.4 martti antispoof_opts.rtableid = -1;
1145 1.1.1.4 martti }
1146 1.1 itojun antispoof_opts_l
1147 1.1 itojun { $$ = antispoof_opts; }
1148 1.1 itojun | /* empty */ {
1149 1.1 itojun bzero(&antispoof_opts, sizeof antispoof_opts);
1150 1.1.1.4 martti antispoof_opts.rtableid = -1;
1151 1.1 itojun $$ = antispoof_opts;
1152 1.1 itojun }
1153 1.1 itojun ;
1154 1.1 itojun
1155 1.1 itojun antispoof_opts_l : antispoof_opts_l antispoof_opt
1156 1.1 itojun | antispoof_opt
1157 1.1 itojun ;
1158 1.1 itojun
1159 1.1 itojun antispoof_opt : label {
1160 1.1 itojun if (antispoof_opts.label) {
1161 1.1 itojun yyerror("label cannot be redefined");
1162 1.1 itojun YYERROR;
1163 1.1 itojun }
1164 1.1 itojun antispoof_opts.label = $1;
1165 1.1 itojun }
1166 1.1.1.4 martti | RTABLE number {
1167 1.1.1.4 martti if ($2 > RT_TABLEID_MAX || $2 < 0) {
1168 1.1.1.4 martti yyerror("invalid rtable id");
1169 1.1.1.4 martti YYERROR;
1170 1.1.1.4 martti }
1171 1.1.1.4 martti antispoof_opts.rtableid = $2;
1172 1.1.1.4 martti }
1173 1.1 itojun ;
1174 1.1 itojun
1175 1.1 itojun not : '!' { $$ = 1; }
1176 1.1 itojun | /* empty */ { $$ = 0; }
1177 1.1 itojun ;
1178 1.1 itojun
1179 1.1 itojun tabledef : TABLE '<' STRING '>' table_opts {
1180 1.1 itojun struct node_host *h, *nh;
1181 1.1 itojun struct node_tinit *ti, *nti;
1182 1.1 itojun
1183 1.1 itojun if (strlen($3) >= PF_TABLE_NAME_SIZE) {
1184 1.1 itojun yyerror("table name too long, max %d chars",
1185 1.1 itojun PF_TABLE_NAME_SIZE - 1);
1186 1.1 itojun free($3);
1187 1.1 itojun YYERROR;
1188 1.1 itojun }
1189 1.1 itojun if (pf->loadopt & PFCTL_FLAG_TABLE)
1190 1.1 itojun if (process_tabledef($3, &$5)) {
1191 1.1 itojun free($3);
1192 1.1 itojun YYERROR;
1193 1.1 itojun }
1194 1.1 itojun free($3);
1195 1.1 itojun for (ti = SIMPLEQ_FIRST(&$5.init_nodes);
1196 1.1 itojun ti != SIMPLEQ_END(&$5.init_nodes); ti = nti) {
1197 1.1 itojun if (ti->file)
1198 1.1 itojun free(ti->file);
1199 1.1 itojun for (h = ti->host; h != NULL; h = nh) {
1200 1.1 itojun nh = h->next;
1201 1.1 itojun free(h);
1202 1.1 itojun }
1203 1.1 itojun nti = SIMPLEQ_NEXT(ti, entries);
1204 1.1 itojun free(ti);
1205 1.1 itojun }
1206 1.1 itojun }
1207 1.1 itojun ;
1208 1.1 itojun
1209 1.1 itojun table_opts : {
1210 1.1 itojun bzero(&table_opts, sizeof table_opts);
1211 1.1 itojun SIMPLEQ_INIT(&table_opts.init_nodes);
1212 1.1 itojun }
1213 1.1 itojun table_opts_l
1214 1.1 itojun { $$ = table_opts; }
1215 1.1 itojun | /* empty */
1216 1.1 itojun {
1217 1.1 itojun bzero(&table_opts, sizeof table_opts);
1218 1.1 itojun SIMPLEQ_INIT(&table_opts.init_nodes);
1219 1.1 itojun $$ = table_opts;
1220 1.1 itojun }
1221 1.1 itojun ;
1222 1.1 itojun
1223 1.1 itojun table_opts_l : table_opts_l table_opt
1224 1.1 itojun | table_opt
1225 1.1 itojun ;
1226 1.1 itojun
1227 1.1 itojun table_opt : STRING {
1228 1.1 itojun if (!strcmp($1, "const"))
1229 1.1 itojun table_opts.flags |= PFR_TFLAG_CONST;
1230 1.1 itojun else if (!strcmp($1, "persist"))
1231 1.1 itojun table_opts.flags |= PFR_TFLAG_PERSIST;
1232 1.1 itojun else {
1233 1.1.1.3 peter yyerror("invalid table option '%s'", $1);
1234 1.1 itojun free($1);
1235 1.1 itojun YYERROR;
1236 1.1 itojun }
1237 1.1 itojun free($1);
1238 1.1 itojun }
1239 1.1 itojun | '{' '}' { table_opts.init_addr = 1; }
1240 1.1 itojun | '{' host_list '}' {
1241 1.1 itojun struct node_host *n;
1242 1.1 itojun struct node_tinit *ti;
1243 1.1 itojun
1244 1.1 itojun for (n = $2; n != NULL; n = n->next) {
1245 1.1 itojun switch (n->addr.type) {
1246 1.1 itojun case PF_ADDR_ADDRMASK:
1247 1.1 itojun continue; /* ok */
1248 1.1 itojun case PF_ADDR_DYNIFTL:
1249 1.1 itojun yyerror("dynamic addresses are not "
1250 1.1 itojun "permitted inside tables");
1251 1.1 itojun break;
1252 1.1 itojun case PF_ADDR_TABLE:
1253 1.1 itojun yyerror("tables cannot contain tables");
1254 1.1 itojun break;
1255 1.1 itojun case PF_ADDR_NOROUTE:
1256 1.1 itojun yyerror("\"no-route\" is not permitted "
1257 1.1 itojun "inside tables");
1258 1.1 itojun break;
1259 1.1.1.4 martti case PF_ADDR_URPFFAILED:
1260 1.1.1.4 martti yyerror("\"urpf-failed\" is not "
1261 1.1.1.4 martti "permitted inside tables");
1262 1.1.1.4 martti break;
1263 1.1 itojun default:
1264 1.1 itojun yyerror("unknown address type %d",
1265 1.1 itojun n->addr.type);
1266 1.1 itojun }
1267 1.1 itojun YYERROR;
1268 1.1 itojun }
1269 1.1 itojun if (!(ti = calloc(1, sizeof(*ti))))
1270 1.1 itojun err(1, "table_opt: calloc");
1271 1.1 itojun ti->host = $2;
1272 1.1 itojun SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
1273 1.1 itojun entries);
1274 1.1 itojun table_opts.init_addr = 1;
1275 1.1 itojun }
1276 1.1 itojun | FILENAME STRING {
1277 1.1 itojun struct node_tinit *ti;
1278 1.1 itojun
1279 1.1 itojun if (!(ti = calloc(1, sizeof(*ti))))
1280 1.1 itojun err(1, "table_opt: calloc");
1281 1.1 itojun ti->file = $2;
1282 1.1 itojun SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
1283 1.1 itojun entries);
1284 1.1 itojun table_opts.init_addr = 1;
1285 1.1 itojun }
1286 1.1 itojun ;
1287 1.1 itojun
1288 1.1 itojun altqif : ALTQ interface queue_opts QUEUE qassign {
1289 1.1 itojun struct pf_altq a;
1290 1.1 itojun
1291 1.1 itojun if (check_rulestate(PFCTL_STATE_QUEUE))
1292 1.1 itojun YYERROR;
1293 1.1 itojun
1294 1.1 itojun memset(&a, 0, sizeof(a));
1295 1.1 itojun if ($3.scheduler.qtype == ALTQT_NONE) {
1296 1.1 itojun yyerror("no scheduler specified!");
1297 1.1 itojun YYERROR;
1298 1.1 itojun }
1299 1.1 itojun a.scheduler = $3.scheduler.qtype;
1300 1.1 itojun a.qlimit = $3.qlimit;
1301 1.1 itojun a.tbrsize = $3.tbrsize;
1302 1.1 itojun if ($5 == NULL) {
1303 1.1 itojun yyerror("no child queues specified");
1304 1.1 itojun YYERROR;
1305 1.1 itojun }
1306 1.1 itojun if (expand_altq(&a, $2, $5, $3.queue_bwspec,
1307 1.1 itojun &$3.scheduler))
1308 1.1 itojun YYERROR;
1309 1.1 itojun }
1310 1.1 itojun ;
1311 1.1 itojun
1312 1.1 itojun queuespec : QUEUE STRING interface queue_opts qassign {
1313 1.1 itojun struct pf_altq a;
1314 1.1 itojun
1315 1.1 itojun if (check_rulestate(PFCTL_STATE_QUEUE)) {
1316 1.1 itojun free($2);
1317 1.1 itojun YYERROR;
1318 1.1 itojun }
1319 1.1 itojun
1320 1.1 itojun memset(&a, 0, sizeof(a));
1321 1.1 itojun
1322 1.1 itojun if (strlcpy(a.qname, $2, sizeof(a.qname)) >=
1323 1.1 itojun sizeof(a.qname)) {
1324 1.1 itojun yyerror("queue name too long (max "
1325 1.1 itojun "%d chars)", PF_QNAME_SIZE-1);
1326 1.1 itojun free($2);
1327 1.1 itojun YYERROR;
1328 1.1 itojun }
1329 1.1 itojun free($2);
1330 1.1 itojun if ($4.tbrsize) {
1331 1.1 itojun yyerror("cannot specify tbrsize for queue");
1332 1.1 itojun YYERROR;
1333 1.1 itojun }
1334 1.1 itojun if ($4.priority > 255) {
1335 1.1 itojun yyerror("priority out of range: max 255");
1336 1.1 itojun YYERROR;
1337 1.1 itojun }
1338 1.1 itojun a.priority = $4.priority;
1339 1.1 itojun a.qlimit = $4.qlimit;
1340 1.1 itojun a.scheduler = $4.scheduler.qtype;
1341 1.1 itojun if (expand_queue(&a, $3, $5, $4.queue_bwspec,
1342 1.1 itojun &$4.scheduler)) {
1343 1.1 itojun yyerror("errors in queue definition");
1344 1.1 itojun YYERROR;
1345 1.1 itojun }
1346 1.1 itojun }
1347 1.1 itojun ;
1348 1.1 itojun
1349 1.1 itojun queue_opts : {
1350 1.1 itojun bzero(&queue_opts, sizeof queue_opts);
1351 1.1 itojun queue_opts.priority = DEFAULT_PRIORITY;
1352 1.1 itojun queue_opts.qlimit = DEFAULT_QLIMIT;
1353 1.1 itojun queue_opts.scheduler.qtype = ALTQT_NONE;
1354 1.1 itojun queue_opts.queue_bwspec.bw_percent = 100;
1355 1.1 itojun }
1356 1.1 itojun queue_opts_l
1357 1.1 itojun { $$ = queue_opts; }
1358 1.1 itojun | /* empty */ {
1359 1.1 itojun bzero(&queue_opts, sizeof queue_opts);
1360 1.1 itojun queue_opts.priority = DEFAULT_PRIORITY;
1361 1.1 itojun queue_opts.qlimit = DEFAULT_QLIMIT;
1362 1.1 itojun queue_opts.scheduler.qtype = ALTQT_NONE;
1363 1.1 itojun queue_opts.queue_bwspec.bw_percent = 100;
1364 1.1 itojun $$ = queue_opts;
1365 1.1 itojun }
1366 1.1 itojun ;
1367 1.1 itojun
1368 1.1 itojun queue_opts_l : queue_opts_l queue_opt
1369 1.1 itojun | queue_opt
1370 1.1 itojun ;
1371 1.1 itojun
1372 1.1 itojun queue_opt : BANDWIDTH bandwidth {
1373 1.1 itojun if (queue_opts.marker & QOM_BWSPEC) {
1374 1.1 itojun yyerror("bandwidth cannot be respecified");
1375 1.1 itojun YYERROR;
1376 1.1 itojun }
1377 1.1 itojun queue_opts.marker |= QOM_BWSPEC;
1378 1.1 itojun queue_opts.queue_bwspec = $2;
1379 1.1 itojun }
1380 1.1 itojun | PRIORITY number {
1381 1.1 itojun if (queue_opts.marker & QOM_PRIORITY) {
1382 1.1 itojun yyerror("priority cannot be respecified");
1383 1.1 itojun YYERROR;
1384 1.1 itojun }
1385 1.1 itojun if ($2 > 255) {
1386 1.1 itojun yyerror("priority out of range: max 255");
1387 1.1 itojun YYERROR;
1388 1.1 itojun }
1389 1.1 itojun queue_opts.marker |= QOM_PRIORITY;
1390 1.1 itojun queue_opts.priority = $2;
1391 1.1 itojun }
1392 1.1 itojun | QLIMIT number {
1393 1.1 itojun if (queue_opts.marker & QOM_QLIMIT) {
1394 1.1 itojun yyerror("qlimit cannot be respecified");
1395 1.1 itojun YYERROR;
1396 1.1 itojun }
1397 1.1 itojun if ($2 > 65535) {
1398 1.1 itojun yyerror("qlimit out of range: max 65535");
1399 1.1 itojun YYERROR;
1400 1.1 itojun }
1401 1.1 itojun queue_opts.marker |= QOM_QLIMIT;
1402 1.1 itojun queue_opts.qlimit = $2;
1403 1.1 itojun }
1404 1.1 itojun | scheduler {
1405 1.1 itojun if (queue_opts.marker & QOM_SCHEDULER) {
1406 1.1 itojun yyerror("scheduler cannot be respecified");
1407 1.1 itojun YYERROR;
1408 1.1 itojun }
1409 1.1 itojun queue_opts.marker |= QOM_SCHEDULER;
1410 1.1 itojun queue_opts.scheduler = $1;
1411 1.1 itojun }
1412 1.1 itojun | TBRSIZE number {
1413 1.1 itojun if (queue_opts.marker & QOM_TBRSIZE) {
1414 1.1 itojun yyerror("tbrsize cannot be respecified");
1415 1.1 itojun YYERROR;
1416 1.1 itojun }
1417 1.1 itojun if ($2 > 65535) {
1418 1.1 itojun yyerror("tbrsize too big: max 65535");
1419 1.1 itojun YYERROR;
1420 1.1 itojun }
1421 1.1 itojun queue_opts.marker |= QOM_TBRSIZE;
1422 1.1 itojun queue_opts.tbrsize = $2;
1423 1.1 itojun }
1424 1.1 itojun ;
1425 1.1 itojun
1426 1.1 itojun bandwidth : STRING {
1427 1.1 itojun double bps;
1428 1.1 itojun char *cp;
1429 1.1 itojun
1430 1.1 itojun $$.bw_percent = 0;
1431 1.1 itojun
1432 1.1 itojun bps = strtod($1, &cp);
1433 1.1 itojun if (cp != NULL) {
1434 1.1 itojun if (!strcmp(cp, "b"))
1435 1.1 itojun ; /* nothing */
1436 1.1 itojun else if (!strcmp(cp, "Kb"))
1437 1.1 itojun bps *= 1000;
1438 1.1 itojun else if (!strcmp(cp, "Mb"))
1439 1.1 itojun bps *= 1000 * 1000;
1440 1.1 itojun else if (!strcmp(cp, "Gb"))
1441 1.1 itojun bps *= 1000 * 1000 * 1000;
1442 1.1 itojun else if (!strcmp(cp, "%")) {
1443 1.1 itojun if (bps < 0 || bps > 100) {
1444 1.1 itojun yyerror("bandwidth spec "
1445 1.1 itojun "out of range");
1446 1.1 itojun free($1);
1447 1.1 itojun YYERROR;
1448 1.1 itojun }
1449 1.1 itojun $$.bw_percent = bps;
1450 1.1 itojun bps = 0;
1451 1.1 itojun } else {
1452 1.1 itojun yyerror("unknown unit %s", cp);
1453 1.1 itojun free($1);
1454 1.1 itojun YYERROR;
1455 1.1 itojun }
1456 1.1 itojun }
1457 1.1 itojun free($1);
1458 1.1 itojun $$.bw_absolute = (u_int32_t)bps;
1459 1.1 itojun }
1460 1.1 itojun ;
1461 1.1 itojun
1462 1.1 itojun scheduler : CBQ {
1463 1.1 itojun $$.qtype = ALTQT_CBQ;
1464 1.1 itojun $$.data.cbq_opts.flags = 0;
1465 1.1 itojun }
1466 1.1 itojun | CBQ '(' cbqflags_list ')' {
1467 1.1 itojun $$.qtype = ALTQT_CBQ;
1468 1.1 itojun $$.data.cbq_opts.flags = $3;
1469 1.1 itojun }
1470 1.1 itojun | PRIQ {
1471 1.1 itojun $$.qtype = ALTQT_PRIQ;
1472 1.1 itojun $$.data.priq_opts.flags = 0;
1473 1.1 itojun }
1474 1.1 itojun | PRIQ '(' priqflags_list ')' {
1475 1.1 itojun $$.qtype = ALTQT_PRIQ;
1476 1.1 itojun $$.data.priq_opts.flags = $3;
1477 1.1 itojun }
1478 1.1 itojun | HFSC {
1479 1.1 itojun $$.qtype = ALTQT_HFSC;
1480 1.1 itojun bzero(&$$.data.hfsc_opts,
1481 1.1 itojun sizeof(struct node_hfsc_opts));
1482 1.1 itojun }
1483 1.1 itojun | HFSC '(' hfsc_opts ')' {
1484 1.1 itojun $$.qtype = ALTQT_HFSC;
1485 1.1 itojun $$.data.hfsc_opts = $3;
1486 1.1 itojun }
1487 1.1 itojun ;
1488 1.1 itojun
1489 1.1 itojun cbqflags_list : cbqflags_item { $$ |= $1; }
1490 1.1 itojun | cbqflags_list comma cbqflags_item { $$ |= $3; }
1491 1.1 itojun ;
1492 1.1 itojun
1493 1.1 itojun cbqflags_item : STRING {
1494 1.1 itojun if (!strcmp($1, "default"))
1495 1.1 itojun $$ = CBQCLF_DEFCLASS;
1496 1.1 itojun else if (!strcmp($1, "borrow"))
1497 1.1 itojun $$ = CBQCLF_BORROW;
1498 1.1 itojun else if (!strcmp($1, "red"))
1499 1.1 itojun $$ = CBQCLF_RED;
1500 1.1 itojun else if (!strcmp($1, "ecn"))
1501 1.1 itojun $$ = CBQCLF_RED|CBQCLF_ECN;
1502 1.1 itojun else if (!strcmp($1, "rio"))
1503 1.1 itojun $$ = CBQCLF_RIO;
1504 1.1 itojun else {
1505 1.1 itojun yyerror("unknown cbq flag \"%s\"", $1);
1506 1.1 itojun free($1);
1507 1.1 itojun YYERROR;
1508 1.1 itojun }
1509 1.1 itojun free($1);
1510 1.1 itojun }
1511 1.1 itojun ;
1512 1.1 itojun
1513 1.1 itojun priqflags_list : priqflags_item { $$ |= $1; }
1514 1.1 itojun | priqflags_list comma priqflags_item { $$ |= $3; }
1515 1.1 itojun ;
1516 1.1 itojun
1517 1.1 itojun priqflags_item : STRING {
1518 1.1 itojun if (!strcmp($1, "default"))
1519 1.1 itojun $$ = PRCF_DEFAULTCLASS;
1520 1.1 itojun else if (!strcmp($1, "red"))
1521 1.1 itojun $$ = PRCF_RED;
1522 1.1 itojun else if (!strcmp($1, "ecn"))
1523 1.1 itojun $$ = PRCF_RED|PRCF_ECN;
1524 1.1 itojun else if (!strcmp($1, "rio"))
1525 1.1 itojun $$ = PRCF_RIO;
1526 1.1 itojun else {
1527 1.1 itojun yyerror("unknown priq flag \"%s\"", $1);
1528 1.1 itojun free($1);
1529 1.1 itojun YYERROR;
1530 1.1 itojun }
1531 1.1 itojun free($1);
1532 1.1 itojun }
1533 1.1 itojun ;
1534 1.1 itojun
1535 1.1 itojun hfsc_opts : {
1536 1.1 itojun bzero(&hfsc_opts,
1537 1.1 itojun sizeof(struct node_hfsc_opts));
1538 1.1 itojun }
1539 1.1 itojun hfscopts_list {
1540 1.1 itojun $$ = hfsc_opts;
1541 1.1 itojun }
1542 1.1 itojun ;
1543 1.1 itojun
1544 1.1 itojun hfscopts_list : hfscopts_item
1545 1.1 itojun | hfscopts_list comma hfscopts_item
1546 1.1 itojun ;
1547 1.1 itojun
1548 1.1 itojun hfscopts_item : LINKSHARE bandwidth {
1549 1.1 itojun if (hfsc_opts.linkshare.used) {
1550 1.1 itojun yyerror("linkshare already specified");
1551 1.1 itojun YYERROR;
1552 1.1 itojun }
1553 1.1 itojun hfsc_opts.linkshare.m2 = $2;
1554 1.1 itojun hfsc_opts.linkshare.used = 1;
1555 1.1 itojun }
1556 1.1.1.3 peter | LINKSHARE '(' bandwidth comma number comma bandwidth ')'
1557 1.1.1.3 peter {
1558 1.1 itojun if (hfsc_opts.linkshare.used) {
1559 1.1 itojun yyerror("linkshare already specified");
1560 1.1 itojun YYERROR;
1561 1.1 itojun }
1562 1.1 itojun hfsc_opts.linkshare.m1 = $3;
1563 1.1.1.3 peter hfsc_opts.linkshare.d = $5;
1564 1.1.1.3 peter hfsc_opts.linkshare.m2 = $7;
1565 1.1 itojun hfsc_opts.linkshare.used = 1;
1566 1.1 itojun }
1567 1.1 itojun | REALTIME bandwidth {
1568 1.1 itojun if (hfsc_opts.realtime.used) {
1569 1.1 itojun yyerror("realtime already specified");
1570 1.1 itojun YYERROR;
1571 1.1 itojun }
1572 1.1 itojun hfsc_opts.realtime.m2 = $2;
1573 1.1 itojun hfsc_opts.realtime.used = 1;
1574 1.1 itojun }
1575 1.1.1.3 peter | REALTIME '(' bandwidth comma number comma bandwidth ')'
1576 1.1.1.3 peter {
1577 1.1 itojun if (hfsc_opts.realtime.used) {
1578 1.1 itojun yyerror("realtime already specified");
1579 1.1 itojun YYERROR;
1580 1.1 itojun }
1581 1.1 itojun hfsc_opts.realtime.m1 = $3;
1582 1.1.1.3 peter hfsc_opts.realtime.d = $5;
1583 1.1.1.3 peter hfsc_opts.realtime.m2 = $7;
1584 1.1 itojun hfsc_opts.realtime.used = 1;
1585 1.1 itojun }
1586 1.1 itojun | UPPERLIMIT bandwidth {
1587 1.1 itojun if (hfsc_opts.upperlimit.used) {
1588 1.1 itojun yyerror("upperlimit already specified");
1589 1.1 itojun YYERROR;
1590 1.1 itojun }
1591 1.1 itojun hfsc_opts.upperlimit.m2 = $2;
1592 1.1 itojun hfsc_opts.upperlimit.used = 1;
1593 1.1 itojun }
1594 1.1.1.3 peter | UPPERLIMIT '(' bandwidth comma number comma bandwidth ')'
1595 1.1.1.3 peter {
1596 1.1 itojun if (hfsc_opts.upperlimit.used) {
1597 1.1 itojun yyerror("upperlimit already specified");
1598 1.1 itojun YYERROR;
1599 1.1 itojun }
1600 1.1 itojun hfsc_opts.upperlimit.m1 = $3;
1601 1.1.1.3 peter hfsc_opts.upperlimit.d = $5;
1602 1.1.1.3 peter hfsc_opts.upperlimit.m2 = $7;
1603 1.1 itojun hfsc_opts.upperlimit.used = 1;
1604 1.1 itojun }
1605 1.1 itojun | STRING {
1606 1.1 itojun if (!strcmp($1, "default"))
1607 1.1 itojun hfsc_opts.flags |= HFCF_DEFAULTCLASS;
1608 1.1 itojun else if (!strcmp($1, "red"))
1609 1.1 itojun hfsc_opts.flags |= HFCF_RED;
1610 1.1 itojun else if (!strcmp($1, "ecn"))
1611 1.1 itojun hfsc_opts.flags |= HFCF_RED|HFCF_ECN;
1612 1.1 itojun else if (!strcmp($1, "rio"))
1613 1.1 itojun hfsc_opts.flags |= HFCF_RIO;
1614 1.1 itojun else {
1615 1.1 itojun yyerror("unknown hfsc flag \"%s\"", $1);
1616 1.1 itojun free($1);
1617 1.1 itojun YYERROR;
1618 1.1 itojun }
1619 1.1 itojun free($1);
1620 1.1 itojun }
1621 1.1 itojun ;
1622 1.1 itojun
1623 1.1 itojun qassign : /* empty */ { $$ = NULL; }
1624 1.1 itojun | qassign_item { $$ = $1; }
1625 1.1 itojun | '{' qassign_list '}' { $$ = $2; }
1626 1.1 itojun ;
1627 1.1 itojun
1628 1.1 itojun qassign_list : qassign_item { $$ = $1; }
1629 1.1 itojun | qassign_list comma qassign_item {
1630 1.1 itojun $1->tail->next = $3;
1631 1.1 itojun $1->tail = $3;
1632 1.1 itojun $$ = $1;
1633 1.1 itojun }
1634 1.1 itojun ;
1635 1.1 itojun
1636 1.1 itojun qassign_item : STRING {
1637 1.1 itojun $$ = calloc(1, sizeof(struct node_queue));
1638 1.1 itojun if ($$ == NULL)
1639 1.1 itojun err(1, "qassign_item: calloc");
1640 1.1 itojun if (strlcpy($$->queue, $1, sizeof($$->queue)) >=
1641 1.1 itojun sizeof($$->queue)) {
1642 1.1 itojun yyerror("queue name '%s' too long (max "
1643 1.1 itojun "%d chars)", $1, sizeof($$->queue)-1);
1644 1.1 itojun free($1);
1645 1.1 itojun free($$);
1646 1.1 itojun YYERROR;
1647 1.1 itojun }
1648 1.1 itojun free($1);
1649 1.1 itojun $$->next = NULL;
1650 1.1 itojun $$->tail = $$;
1651 1.1 itojun }
1652 1.1 itojun ;
1653 1.1 itojun
1654 1.1 itojun pfrule : action dir logquick interface route af proto fromto
1655 1.1 itojun filter_opts
1656 1.1 itojun {
1657 1.1 itojun struct pf_rule r;
1658 1.1 itojun struct node_state_opt *o;
1659 1.1 itojun struct node_proto *proto;
1660 1.1 itojun int srctrack = 0;
1661 1.1 itojun int statelock = 0;
1662 1.1.1.4 martti int adaptive = 0;
1663 1.1 itojun
1664 1.1 itojun if (check_rulestate(PFCTL_STATE_FILTER))
1665 1.1 itojun YYERROR;
1666 1.1 itojun
1667 1.1 itojun memset(&r, 0, sizeof(r));
1668 1.1 itojun
1669 1.1 itojun r.action = $1.b1;
1670 1.1 itojun switch ($1.b2) {
1671 1.1 itojun case PFRULE_RETURNRST:
1672 1.1 itojun r.rule_flag |= PFRULE_RETURNRST;
1673 1.1 itojun r.return_ttl = $1.w;
1674 1.1 itojun break;
1675 1.1 itojun case PFRULE_RETURNICMP:
1676 1.1 itojun r.rule_flag |= PFRULE_RETURNICMP;
1677 1.1 itojun r.return_icmp = $1.w;
1678 1.1 itojun r.return_icmp6 = $1.w2;
1679 1.1 itojun break;
1680 1.1 itojun case PFRULE_RETURN:
1681 1.1 itojun r.rule_flag |= PFRULE_RETURN;
1682 1.1 itojun r.return_icmp = $1.w;
1683 1.1 itojun r.return_icmp6 = $1.w2;
1684 1.1 itojun break;
1685 1.1 itojun }
1686 1.1 itojun r.direction = $2;
1687 1.1 itojun r.log = $3.log;
1688 1.1.1.4 martti r.logif = $3.logif;
1689 1.1 itojun r.quick = $3.quick;
1690 1.1.1.2 yamt r.prob = $9.prob;
1691 1.1.1.4 martti r.rtableid = $9.rtableid;
1692 1.1 itojun
1693 1.1 itojun r.af = $6;
1694 1.1 itojun if ($9.tag)
1695 1.1 itojun if (strlcpy(r.tagname, $9.tag,
1696 1.1 itojun PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
1697 1.1 itojun yyerror("tag too long, max %u chars",
1698 1.1 itojun PF_TAG_NAME_SIZE - 1);
1699 1.1 itojun YYERROR;
1700 1.1 itojun }
1701 1.1 itojun if ($9.match_tag)
1702 1.1 itojun if (strlcpy(r.match_tagname, $9.match_tag,
1703 1.1 itojun PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
1704 1.1 itojun yyerror("tag too long, max %u chars",
1705 1.1 itojun PF_TAG_NAME_SIZE - 1);
1706 1.1 itojun YYERROR;
1707 1.1 itojun }
1708 1.1 itojun r.match_tag_not = $9.match_tag_not;
1709 1.1 itojun if (rule_label(&r, $9.label))
1710 1.1 itojun YYERROR;
1711 1.1 itojun free($9.label);
1712 1.1.1.4 martti r.flags = $9.flags.b1;
1713 1.1.1.4 martti r.flagset = $9.flags.b2;
1714 1.1.1.4 martti if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) {
1715 1.1.1.4 martti yyerror("flags always false");
1716 1.1.1.4 martti YYERROR;
1717 1.1.1.4 martti }
1718 1.1 itojun if ($9.flags.b1 || $9.flags.b2 || $8.src_os) {
1719 1.1 itojun for (proto = $7; proto != NULL &&
1720 1.1 itojun proto->proto != IPPROTO_TCP;
1721 1.1 itojun proto = proto->next)
1722 1.1 itojun ; /* nothing */
1723 1.1 itojun if (proto == NULL && $7 != NULL) {
1724 1.1 itojun if ($9.flags.b1 || $9.flags.b2)
1725 1.1 itojun yyerror(
1726 1.1 itojun "flags only apply to tcp");
1727 1.1 itojun if ($8.src_os)
1728 1.1 itojun yyerror(
1729 1.1 itojun "OS fingerprinting only "
1730 1.1 itojun "apply to tcp");
1731 1.1 itojun YYERROR;
1732 1.1 itojun }
1733 1.1 itojun #if 0
1734 1.1 itojun if (($9.flags.b1 & parse_flags("S")) == 0 &&
1735 1.1 itojun $8.src_os) {
1736 1.1 itojun yyerror("OS fingerprinting requires "
1737 1.1 itojun "the SYN TCP flag (flags S/SA)");
1738 1.1 itojun YYERROR;
1739 1.1 itojun }
1740 1.1 itojun #endif
1741 1.1 itojun }
1742 1.1 itojun
1743 1.1 itojun r.tos = $9.tos;
1744 1.1 itojun r.keep_state = $9.keep.action;
1745 1.1.1.4 martti
1746 1.1.1.4 martti /* 'keep state' by default on pass rules. */
1747 1.1.1.4 martti if (!r.keep_state && !r.action &&
1748 1.1.1.4 martti !($9.marker & FOM_KEEP))
1749 1.1.1.4 martti r.keep_state = PF_STATE_NORMAL;
1750 1.1.1.4 martti
1751 1.1 itojun o = $9.keep.options;
1752 1.1 itojun while (o) {
1753 1.1 itojun struct node_state_opt *p = o;
1754 1.1 itojun
1755 1.1 itojun switch (o->type) {
1756 1.1 itojun case PF_STATE_OPT_MAX:
1757 1.1 itojun if (r.max_states) {
1758 1.1 itojun yyerror("state option 'max' "
1759 1.1 itojun "multiple definitions");
1760 1.1 itojun YYERROR;
1761 1.1 itojun }
1762 1.1 itojun r.max_states = o->data.max_states;
1763 1.1 itojun break;
1764 1.1 itojun case PF_STATE_OPT_NOSYNC:
1765 1.1 itojun if (r.rule_flag & PFRULE_NOSYNC) {
1766 1.1 itojun yyerror("state option 'sync' "
1767 1.1 itojun "multiple definitions");
1768 1.1 itojun YYERROR;
1769 1.1 itojun }
1770 1.1 itojun r.rule_flag |= PFRULE_NOSYNC;
1771 1.1 itojun break;
1772 1.1 itojun case PF_STATE_OPT_SRCTRACK:
1773 1.1 itojun if (srctrack) {
1774 1.1 itojun yyerror("state option "
1775 1.1 itojun "'source-track' "
1776 1.1 itojun "multiple definitions");
1777 1.1 itojun YYERROR;
1778 1.1 itojun }
1779 1.1 itojun srctrack = o->data.src_track;
1780 1.1.1.3 peter r.rule_flag |= PFRULE_SRCTRACK;
1781 1.1 itojun break;
1782 1.1 itojun case PF_STATE_OPT_MAX_SRC_STATES:
1783 1.1 itojun if (r.max_src_states) {
1784 1.1 itojun yyerror("state option "
1785 1.1 itojun "'max-src-states' "
1786 1.1 itojun "multiple definitions");
1787 1.1 itojun YYERROR;
1788 1.1 itojun }
1789 1.1.1.3 peter if (o->data.max_src_states == 0) {
1790 1.1 itojun yyerror("'max-src-states' must "
1791 1.1 itojun "be > 0");
1792 1.1 itojun YYERROR;
1793 1.1 itojun }
1794 1.1 itojun r.max_src_states =
1795 1.1 itojun o->data.max_src_states;
1796 1.1 itojun r.rule_flag |= PFRULE_SRCTRACK;
1797 1.1 itojun break;
1798 1.1.1.3 peter case PF_STATE_OPT_OVERLOAD:
1799 1.1.1.3 peter if (r.overload_tblname[0]) {
1800 1.1.1.3 peter yyerror("multiple 'overload' "
1801 1.1.1.3 peter "table definitions");
1802 1.1.1.3 peter YYERROR;
1803 1.1.1.3 peter }
1804 1.1.1.3 peter if (strlcpy(r.overload_tblname,
1805 1.1.1.3 peter o->data.overload.tblname,
1806 1.1.1.3 peter PF_TABLE_NAME_SIZE) >=
1807 1.1.1.3 peter PF_TABLE_NAME_SIZE) {
1808 1.1.1.3 peter yyerror("state option: "
1809 1.1.1.3 peter "strlcpy");
1810 1.1.1.3 peter YYERROR;
1811 1.1.1.3 peter }
1812 1.1.1.3 peter r.flush = o->data.overload.flush;
1813 1.1.1.3 peter break;
1814 1.1.1.3 peter case PF_STATE_OPT_MAX_SRC_CONN:
1815 1.1.1.3 peter if (r.max_src_conn) {
1816 1.1.1.3 peter yyerror("state option "
1817 1.1.1.3 peter "'max-src-conn' "
1818 1.1.1.3 peter "multiple definitions");
1819 1.1.1.3 peter YYERROR;
1820 1.1.1.3 peter }
1821 1.1.1.3 peter if (o->data.max_src_conn == 0) {
1822 1.1.1.3 peter yyerror("'max-src-conn' "
1823 1.1.1.3 peter "must be > 0");
1824 1.1.1.3 peter YYERROR;
1825 1.1.1.3 peter }
1826 1.1.1.3 peter r.max_src_conn =
1827 1.1.1.3 peter o->data.max_src_conn;
1828 1.1.1.3 peter r.rule_flag |= PFRULE_SRCTRACK |
1829 1.1.1.3 peter PFRULE_RULESRCTRACK;
1830 1.1.1.3 peter break;
1831 1.1.1.3 peter case PF_STATE_OPT_MAX_SRC_CONN_RATE:
1832 1.1.1.3 peter if (r.max_src_conn_rate.limit) {
1833 1.1.1.3 peter yyerror("state option "
1834 1.1.1.3 peter "'max-src-conn-rate' "
1835 1.1.1.3 peter "multiple definitions");
1836 1.1.1.3 peter YYERROR;
1837 1.1.1.3 peter }
1838 1.1.1.3 peter if (!o->data.max_src_conn_rate.limit ||
1839 1.1.1.3 peter !o->data.max_src_conn_rate.seconds) {
1840 1.1.1.3 peter yyerror("'max-src-conn-rate' "
1841 1.1.1.3 peter "values must be > 0");
1842 1.1.1.3 peter YYERROR;
1843 1.1.1.3 peter }
1844 1.1.1.3 peter if (o->data.max_src_conn_rate.limit >
1845 1.1.1.3 peter PF_THRESHOLD_MAX) {
1846 1.1.1.3 peter yyerror("'max-src-conn-rate' "
1847 1.1.1.4 martti "maximum rate must be < %u",
1848 1.1.1.4 martti PF_THRESHOLD_MAX);
1849 1.1.1.3 peter YYERROR;
1850 1.1.1.3 peter }
1851 1.1.1.3 peter r.max_src_conn_rate.limit =
1852 1.1.1.3 peter o->data.max_src_conn_rate.limit;
1853 1.1.1.3 peter r.max_src_conn_rate.seconds =
1854 1.1.1.3 peter o->data.max_src_conn_rate.seconds;
1855 1.1.1.3 peter r.rule_flag |= PFRULE_SRCTRACK |
1856 1.1.1.3 peter PFRULE_RULESRCTRACK;
1857 1.1.1.3 peter break;
1858 1.1 itojun case PF_STATE_OPT_MAX_SRC_NODES:
1859 1.1 itojun if (r.max_src_nodes) {
1860 1.1 itojun yyerror("state option "
1861 1.1 itojun "'max-src-nodes' "
1862 1.1 itojun "multiple definitions");
1863 1.1 itojun YYERROR;
1864 1.1 itojun }
1865 1.1 itojun if (o->data.max_src_nodes == 0) {
1866 1.1 itojun yyerror("'max-src-nodes' must "
1867 1.1 itojun "be > 0");
1868 1.1 itojun YYERROR;
1869 1.1 itojun }
1870 1.1 itojun r.max_src_nodes =
1871 1.1 itojun o->data.max_src_nodes;
1872 1.1 itojun r.rule_flag |= PFRULE_SRCTRACK |
1873 1.1 itojun PFRULE_RULESRCTRACK;
1874 1.1 itojun break;
1875 1.1 itojun case PF_STATE_OPT_STATELOCK:
1876 1.1 itojun if (statelock) {
1877 1.1 itojun yyerror("state locking option: "
1878 1.1 itojun "multiple definitions");
1879 1.1 itojun YYERROR;
1880 1.1 itojun }
1881 1.1 itojun statelock = 1;
1882 1.1 itojun r.rule_flag |= o->data.statelock;
1883 1.1 itojun break;
1884 1.1 itojun case PF_STATE_OPT_TIMEOUT:
1885 1.1.1.4 martti if (o->data.timeout.number ==
1886 1.1.1.4 martti PFTM_ADAPTIVE_START ||
1887 1.1.1.4 martti o->data.timeout.number ==
1888 1.1.1.4 martti PFTM_ADAPTIVE_END)
1889 1.1.1.4 martti adaptive = 1;
1890 1.1 itojun if (r.timeout[o->data.timeout.number]) {
1891 1.1 itojun yyerror("state timeout %s "
1892 1.1 itojun "multiple definitions",
1893 1.1 itojun pf_timeouts[o->data.
1894 1.1 itojun timeout.number].name);
1895 1.1 itojun YYERROR;
1896 1.1 itojun }
1897 1.1 itojun r.timeout[o->data.timeout.number] =
1898 1.1 itojun o->data.timeout.seconds;
1899 1.1 itojun }
1900 1.1 itojun o = o->next;
1901 1.1 itojun free(p);
1902 1.1 itojun }
1903 1.1.1.4 martti
1904 1.1.1.4 martti /* 'flags S/SA' by default on stateful rules */
1905 1.1.1.4 martti if (!r.action && !r.flags && !r.flagset &&
1906 1.1.1.4 martti !$9.fragment && !($9.marker & FOM_FLAGS) &&
1907 1.1.1.4 martti r.keep_state) {
1908 1.1.1.4 martti r.flags = parse_flags("S");
1909 1.1.1.4 martti r.flagset = parse_flags("SA");
1910 1.1.1.4 martti }
1911 1.1.1.4 martti if (!adaptive && r.max_states) {
1912 1.1.1.4 martti r.timeout[PFTM_ADAPTIVE_START] =
1913 1.1.1.4 martti (r.max_states / 10) * 6;
1914 1.1.1.4 martti r.timeout[PFTM_ADAPTIVE_END] =
1915 1.1.1.4 martti (r.max_states / 10) * 12;
1916 1.1.1.4 martti }
1917 1.1.1.3 peter if (r.rule_flag & PFRULE_SRCTRACK) {
1918 1.1 itojun if (srctrack == PF_SRCTRACK_GLOBAL &&
1919 1.1 itojun r.max_src_nodes) {
1920 1.1 itojun yyerror("'max-src-nodes' is "
1921 1.1 itojun "incompatible with "
1922 1.1 itojun "'source-track global'");
1923 1.1 itojun YYERROR;
1924 1.1 itojun }
1925 1.1.1.3 peter if (srctrack == PF_SRCTRACK_GLOBAL &&
1926 1.1.1.3 peter r.max_src_conn) {
1927 1.1.1.3 peter yyerror("'max-src-conn' is "
1928 1.1.1.3 peter "incompatible with "
1929 1.1.1.3 peter "'source-track global'");
1930 1.1.1.3 peter YYERROR;
1931 1.1.1.3 peter }
1932 1.1.1.3 peter if (srctrack == PF_SRCTRACK_GLOBAL &&
1933 1.1.1.3 peter r.max_src_conn_rate.seconds) {
1934 1.1.1.3 peter yyerror("'max-src-conn-rate' is "
1935 1.1.1.3 peter "incompatible with "
1936 1.1.1.3 peter "'source-track global'");
1937 1.1.1.3 peter YYERROR;
1938 1.1.1.3 peter }
1939 1.1.1.3 peter if (r.timeout[PFTM_SRC_NODE] <
1940 1.1.1.3 peter r.max_src_conn_rate.seconds)
1941 1.1.1.3 peter r.timeout[PFTM_SRC_NODE] =
1942 1.1.1.3 peter r.max_src_conn_rate.seconds;
1943 1.1 itojun r.rule_flag |= PFRULE_SRCTRACK;
1944 1.1 itojun if (srctrack == PF_SRCTRACK_RULE)
1945 1.1 itojun r.rule_flag |= PFRULE_RULESRCTRACK;
1946 1.1 itojun }
1947 1.1 itojun if (r.keep_state && !statelock)
1948 1.1 itojun r.rule_flag |= default_statelock;
1949 1.1 itojun
1950 1.1 itojun if ($9.fragment)
1951 1.1 itojun r.rule_flag |= PFRULE_FRAGMENT;
1952 1.1 itojun r.allow_opts = $9.allowopts;
1953 1.1 itojun
1954 1.1 itojun decide_address_family($8.src.host, &r.af);
1955 1.1 itojun decide_address_family($8.dst.host, &r.af);
1956 1.1 itojun
1957 1.1 itojun if ($5.rt) {
1958 1.1 itojun if (!r.direction) {
1959 1.1 itojun yyerror("direction must be explicit "
1960 1.1 itojun "with rules that specify routing");
1961 1.1 itojun YYERROR;
1962 1.1 itojun }
1963 1.1 itojun r.rt = $5.rt;
1964 1.1 itojun r.rpool.opts = $5.pool_opts;
1965 1.1 itojun if ($5.key != NULL)
1966 1.1 itojun memcpy(&r.rpool.key, $5.key,
1967 1.1 itojun sizeof(struct pf_poolhashkey));
1968 1.1 itojun }
1969 1.1 itojun if (r.rt && r.rt != PF_FASTROUTE) {
1970 1.1 itojun decide_address_family($5.host, &r.af);
1971 1.1 itojun remove_invalid_hosts(&$5.host, &r.af);
1972 1.1 itojun if ($5.host == NULL) {
1973 1.1 itojun yyerror("no routing address with "
1974 1.1 itojun "matching address family found.");
1975 1.1 itojun YYERROR;
1976 1.1 itojun }
1977 1.1 itojun if ((r.rpool.opts & PF_POOL_TYPEMASK) ==
1978 1.1 itojun PF_POOL_NONE && ($5.host->next != NULL ||
1979 1.1 itojun $5.host->addr.type == PF_ADDR_TABLE ||
1980 1.1 itojun DYNIF_MULTIADDR($5.host->addr)))
1981 1.1 itojun r.rpool.opts |= PF_POOL_ROUNDROBIN;
1982 1.1 itojun if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
1983 1.1 itojun PF_POOL_ROUNDROBIN &&
1984 1.1 itojun disallow_table($5.host, "tables are only "
1985 1.1 itojun "supported in round-robin routing pools"))
1986 1.1 itojun YYERROR;
1987 1.1 itojun if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
1988 1.1 itojun PF_POOL_ROUNDROBIN &&
1989 1.1 itojun disallow_alias($5.host, "interface (%s) "
1990 1.1 itojun "is only supported in round-robin "
1991 1.1 itojun "routing pools"))
1992 1.1 itojun YYERROR;
1993 1.1 itojun if ($5.host->next != NULL) {
1994 1.1 itojun if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
1995 1.1 itojun PF_POOL_ROUNDROBIN) {
1996 1.1 itojun yyerror("r.rpool.opts must "
1997 1.1 itojun "be PF_POOL_ROUNDROBIN");
1998 1.1 itojun YYERROR;
1999 1.1 itojun }
2000 1.1 itojun }
2001 1.1 itojun }
2002 1.1 itojun if ($9.queues.qname != NULL) {
2003 1.1 itojun if (strlcpy(r.qname, $9.queues.qname,
2004 1.1 itojun sizeof(r.qname)) >= sizeof(r.qname)) {
2005 1.1 itojun yyerror("rule qname too long (max "
2006 1.1 itojun "%d chars)", sizeof(r.qname)-1);
2007 1.1 itojun YYERROR;
2008 1.1 itojun }
2009 1.1 itojun free($9.queues.qname);
2010 1.1 itojun }
2011 1.1 itojun if ($9.queues.pqname != NULL) {
2012 1.1 itojun if (strlcpy(r.pqname, $9.queues.pqname,
2013 1.1 itojun sizeof(r.pqname)) >= sizeof(r.pqname)) {
2014 1.1 itojun yyerror("rule pqname too long (max "
2015 1.1 itojun "%d chars)", sizeof(r.pqname)-1);
2016 1.1 itojun YYERROR;
2017 1.1 itojun }
2018 1.1 itojun free($9.queues.pqname);
2019 1.1 itojun }
2020 1.1 itojun
2021 1.1 itojun expand_rule(&r, $4, $5.host, $7, $8.src_os,
2022 1.1 itojun $8.src.host, $8.src.port, $8.dst.host, $8.dst.port,
2023 1.1.1.2 yamt $9.uid, $9.gid, $9.icmpspec, "");
2024 1.1 itojun }
2025 1.1 itojun ;
2026 1.1 itojun
2027 1.1.1.4 martti filter_opts : {
2028 1.1.1.4 martti bzero(&filter_opts, sizeof filter_opts);
2029 1.1.1.4 martti filter_opts.rtableid = -1;
2030 1.1.1.4 martti }
2031 1.1 itojun filter_opts_l
2032 1.1 itojun { $$ = filter_opts; }
2033 1.1 itojun | /* empty */ {
2034 1.1 itojun bzero(&filter_opts, sizeof filter_opts);
2035 1.1.1.4 martti filter_opts.rtableid = -1;
2036 1.1 itojun $$ = filter_opts;
2037 1.1 itojun }
2038 1.1 itojun ;
2039 1.1 itojun
2040 1.1 itojun filter_opts_l : filter_opts_l filter_opt
2041 1.1 itojun | filter_opt
2042 1.1 itojun ;
2043 1.1 itojun
2044 1.1 itojun filter_opt : USER uids {
2045 1.1 itojun if (filter_opts.uid)
2046 1.1 itojun $2->tail->next = filter_opts.uid;
2047 1.1 itojun filter_opts.uid = $2;
2048 1.1 itojun }
2049 1.1 itojun | GROUP gids {
2050 1.1 itojun if (filter_opts.gid)
2051 1.1 itojun $2->tail->next = filter_opts.gid;
2052 1.1 itojun filter_opts.gid = $2;
2053 1.1 itojun }
2054 1.1 itojun | flags {
2055 1.1 itojun if (filter_opts.marker & FOM_FLAGS) {
2056 1.1 itojun yyerror("flags cannot be redefined");
2057 1.1 itojun YYERROR;
2058 1.1 itojun }
2059 1.1 itojun filter_opts.marker |= FOM_FLAGS;
2060 1.1 itojun filter_opts.flags.b1 |= $1.b1;
2061 1.1 itojun filter_opts.flags.b2 |= $1.b2;
2062 1.1 itojun filter_opts.flags.w |= $1.w;
2063 1.1 itojun filter_opts.flags.w2 |= $1.w2;
2064 1.1 itojun }
2065 1.1 itojun | icmpspec {
2066 1.1 itojun if (filter_opts.marker & FOM_ICMP) {
2067 1.1 itojun yyerror("icmp-type cannot be redefined");
2068 1.1 itojun YYERROR;
2069 1.1 itojun }
2070 1.1 itojun filter_opts.marker |= FOM_ICMP;
2071 1.1 itojun filter_opts.icmpspec = $1;
2072 1.1 itojun }
2073 1.1 itojun | tos {
2074 1.1 itojun if (filter_opts.marker & FOM_TOS) {
2075 1.1 itojun yyerror("tos cannot be redefined");
2076 1.1 itojun YYERROR;
2077 1.1 itojun }
2078 1.1 itojun filter_opts.marker |= FOM_TOS;
2079 1.1 itojun filter_opts.tos = $1;
2080 1.1 itojun }
2081 1.1 itojun | keep {
2082 1.1 itojun if (filter_opts.marker & FOM_KEEP) {
2083 1.1 itojun yyerror("modulate or keep cannot be redefined");
2084 1.1 itojun YYERROR;
2085 1.1 itojun }
2086 1.1 itojun filter_opts.marker |= FOM_KEEP;
2087 1.1 itojun filter_opts.keep.action = $1.action;
2088 1.1 itojun filter_opts.keep.options = $1.options;
2089 1.1 itojun }
2090 1.1 itojun | FRAGMENT {
2091 1.1 itojun filter_opts.fragment = 1;
2092 1.1 itojun }
2093 1.1 itojun | ALLOWOPTS {
2094 1.1 itojun filter_opts.allowopts = 1;
2095 1.1 itojun }
2096 1.1 itojun | label {
2097 1.1 itojun if (filter_opts.label) {
2098 1.1 itojun yyerror("label cannot be redefined");
2099 1.1 itojun YYERROR;
2100 1.1 itojun }
2101 1.1 itojun filter_opts.label = $1;
2102 1.1 itojun }
2103 1.1 itojun | qname {
2104 1.1 itojun if (filter_opts.queues.qname) {
2105 1.1 itojun yyerror("queue cannot be redefined");
2106 1.1 itojun YYERROR;
2107 1.1 itojun }
2108 1.1 itojun filter_opts.queues = $1;
2109 1.1 itojun }
2110 1.1 itojun | TAG string {
2111 1.1 itojun filter_opts.tag = $2;
2112 1.1 itojun }
2113 1.1 itojun | not TAGGED string {
2114 1.1 itojun filter_opts.match_tag = $3;
2115 1.1 itojun filter_opts.match_tag_not = $1;
2116 1.1 itojun }
2117 1.1.1.2 yamt | PROBABILITY STRING {
2118 1.1.1.2 yamt char *e;
2119 1.1.1.2 yamt double p = strtod($2, &e);
2120 1.1.1.2 yamt
2121 1.1.1.2 yamt if (*e == '%') {
2122 1.1.1.2 yamt p *= 0.01;
2123 1.1.1.2 yamt e++;
2124 1.1.1.2 yamt }
2125 1.1.1.2 yamt if (*e) {
2126 1.1.1.2 yamt yyerror("invalid probability: %s", $2);
2127 1.1.1.3 peter free($2);
2128 1.1.1.2 yamt YYERROR;
2129 1.1.1.2 yamt }
2130 1.1.1.2 yamt p = floor(p * (UINT_MAX+1.0) + 0.5);
2131 1.1.1.2 yamt if (p < 1.0 || p >= (UINT_MAX+1.0)) {
2132 1.1.1.2 yamt yyerror("invalid probability: %s", $2);
2133 1.1.1.3 peter free($2);
2134 1.1.1.2 yamt YYERROR;
2135 1.1.1.2 yamt }
2136 1.1.1.2 yamt filter_opts.prob = (u_int32_t)p;
2137 1.1.1.2 yamt free($2);
2138 1.1.1.2 yamt }
2139 1.1.1.4 martti | RTABLE number {
2140 1.1.1.4 martti if ($2 > RT_TABLEID_MAX || $2 < 0) {
2141 1.1.1.4 martti yyerror("invalid rtable id");
2142 1.1.1.4 martti YYERROR;
2143 1.1.1.4 martti }
2144 1.1.1.4 martti filter_opts.rtableid = $2;
2145 1.1.1.4 martti }
2146 1.1 itojun ;
2147 1.1 itojun
2148 1.1 itojun action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; }
2149 1.1 itojun | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; }
2150 1.1 itojun ;
2151 1.1 itojun
2152 1.1 itojun blockspec : /* empty */ {
2153 1.1 itojun $$.b2 = blockpolicy;
2154 1.1 itojun $$.w = returnicmpdefault;
2155 1.1 itojun $$.w2 = returnicmp6default;
2156 1.1 itojun }
2157 1.1 itojun | DROP {
2158 1.1 itojun $$.b2 = PFRULE_DROP;
2159 1.1 itojun $$.w = 0;
2160 1.1 itojun $$.w2 = 0;
2161 1.1 itojun }
2162 1.1 itojun | RETURNRST {
2163 1.1 itojun $$.b2 = PFRULE_RETURNRST;
2164 1.1 itojun $$.w = 0;
2165 1.1 itojun $$.w2 = 0;
2166 1.1 itojun }
2167 1.1 itojun | RETURNRST '(' TTL number ')' {
2168 1.1 itojun if ($4 > 255) {
2169 1.1 itojun yyerror("illegal ttl value %d", $4);
2170 1.1 itojun YYERROR;
2171 1.1 itojun }
2172 1.1 itojun $$.b2 = PFRULE_RETURNRST;
2173 1.1 itojun $$.w = $4;
2174 1.1 itojun $$.w2 = 0;
2175 1.1 itojun }
2176 1.1 itojun | RETURNICMP {
2177 1.1 itojun $$.b2 = PFRULE_RETURNICMP;
2178 1.1 itojun $$.w = returnicmpdefault;
2179 1.1 itojun $$.w2 = returnicmp6default;
2180 1.1 itojun }
2181 1.1 itojun | RETURNICMP6 {
2182 1.1 itojun $$.b2 = PFRULE_RETURNICMP;
2183 1.1 itojun $$.w = returnicmpdefault;
2184 1.1 itojun $$.w2 = returnicmp6default;
2185 1.1 itojun }
2186 1.1 itojun | RETURNICMP '(' STRING ')' {
2187 1.1 itojun $$.b2 = PFRULE_RETURNICMP;
2188 1.1 itojun if (!($$.w = parseicmpspec($3, AF_INET))) {
2189 1.1 itojun free($3);
2190 1.1 itojun YYERROR;
2191 1.1 itojun }
2192 1.1 itojun free($3);
2193 1.1 itojun $$.w2 = returnicmp6default;
2194 1.1 itojun }
2195 1.1 itojun | RETURNICMP6 '(' STRING ')' {
2196 1.1 itojun $$.b2 = PFRULE_RETURNICMP;
2197 1.1 itojun $$.w = returnicmpdefault;
2198 1.1 itojun if (!($$.w2 = parseicmpspec($3, AF_INET6))) {
2199 1.1 itojun free($3);
2200 1.1 itojun YYERROR;
2201 1.1 itojun }
2202 1.1 itojun free($3);
2203 1.1 itojun }
2204 1.1 itojun | RETURNICMP '(' STRING comma STRING ')' {
2205 1.1 itojun $$.b2 = PFRULE_RETURNICMP;
2206 1.1 itojun if (!($$.w = parseicmpspec($3, AF_INET)) ||
2207 1.1 itojun !($$.w2 = parseicmpspec($5, AF_INET6))) {
2208 1.1 itojun free($3);
2209 1.1 itojun free($5);
2210 1.1 itojun YYERROR;
2211 1.1 itojun }
2212 1.1 itojun free($3);
2213 1.1 itojun free($5);
2214 1.1 itojun }
2215 1.1 itojun | RETURN {
2216 1.1 itojun $$.b2 = PFRULE_RETURN;
2217 1.1 itojun $$.w = returnicmpdefault;
2218 1.1 itojun $$.w2 = returnicmp6default;
2219 1.1 itojun }
2220 1.1 itojun ;
2221 1.1 itojun
2222 1.1 itojun dir : /* empty */ { $$ = 0; }
2223 1.1 itojun | IN { $$ = PF_IN; }
2224 1.1 itojun | OUT { $$ = PF_OUT; }
2225 1.1 itojun ;
2226 1.1 itojun
2227 1.1.1.4 martti quick : /* empty */ { $$.quick = 0; }
2228 1.1.1.4 martti | QUICK { $$.quick = 1; }
2229 1.1 itojun ;
2230 1.1 itojun
2231 1.1.1.4 martti logquick : /* empty */ { $$.log = 0; $$.quick = 0; $$.logif = 0; }
2232 1.1.1.4 martti | log { $$ = $1; $$.quick = 0; }
2233 1.1.1.4 martti | QUICK { $$.quick = 1; $$.log = 0; $$.logif = 0; }
2234 1.1.1.4 martti | log QUICK { $$ = $1; $$.quick = 1; }
2235 1.1.1.4 martti | QUICK log { $$ = $2; $$.quick = 1; }
2236 1.1.1.4 martti ;
2237 1.1.1.4 martti
2238 1.1.1.4 martti log : LOG { $$.log = PF_LOG; $$.logif = 0; }
2239 1.1.1.4 martti | LOG '(' logopts ')' {
2240 1.1.1.4 martti $$.log = PF_LOG | $3.log;
2241 1.1.1.4 martti $$.logif = $3.logif;
2242 1.1.1.4 martti }
2243 1.1.1.4 martti ;
2244 1.1.1.4 martti
2245 1.1.1.4 martti logopts : logopt { $$ = $1; }
2246 1.1.1.4 martti | logopts comma logopt {
2247 1.1.1.4 martti $$.log = $1.log | $3.log;
2248 1.1.1.4 martti $$.logif = $3.logif;
2249 1.1.1.4 martti if ($$.logif == 0)
2250 1.1.1.4 martti $$.logif = $1.logif;
2251 1.1.1.4 martti }
2252 1.1.1.4 martti ;
2253 1.1.1.4 martti
2254 1.1.1.4 martti logopt : ALL { $$.log = PF_LOG_ALL; $$.logif = 0; }
2255 1.1.1.4 martti | USER { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; }
2256 1.1.1.4 martti | GROUP { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; }
2257 1.1.1.4 martti | TO string {
2258 1.1.1.4 martti const char *errstr;
2259 1.1.1.4 martti u_int i;
2260 1.1.1.4 martti
2261 1.1.1.4 martti $$.log = 0;
2262 1.1.1.4 martti if (strncmp($2, "pflog", 5)) {
2263 1.1.1.4 martti yyerror("%s: should be a pflog interface", $2);
2264 1.1.1.4 martti free($2);
2265 1.1.1.4 martti YYERROR;
2266 1.1.1.4 martti }
2267 1.1.1.4 martti i = strtonum($2 + 5, 0, 255, &errstr);
2268 1.1.1.4 martti if (errstr) {
2269 1.1.1.4 martti yyerror("%s: %s", $2, errstr);
2270 1.1.1.4 martti free($2);
2271 1.1.1.4 martti YYERROR;
2272 1.1.1.4 martti }
2273 1.1.1.4 martti free($2);
2274 1.1.1.4 martti $$.logif = i;
2275 1.1.1.4 martti }
2276 1.1 itojun ;
2277 1.1 itojun
2278 1.1 itojun interface : /* empty */ { $$ = NULL; }
2279 1.1 itojun | ON if_item_not { $$ = $2; }
2280 1.1 itojun | ON '{' if_list '}' { $$ = $3; }
2281 1.1 itojun ;
2282 1.1 itojun
2283 1.1 itojun if_list : if_item_not { $$ = $1; }
2284 1.1 itojun | if_list comma if_item_not {
2285 1.1 itojun $1->tail->next = $3;
2286 1.1 itojun $1->tail = $3;
2287 1.1 itojun $$ = $1;
2288 1.1 itojun }
2289 1.1 itojun ;
2290 1.1 itojun
2291 1.1 itojun if_item_not : not if_item { $$ = $2; $$->not = $1; }
2292 1.1 itojun ;
2293 1.1 itojun
2294 1.1 itojun if_item : STRING {
2295 1.1 itojun struct node_host *n;
2296 1.1 itojun
2297 1.1 itojun $$ = calloc(1, sizeof(struct node_if));
2298 1.1 itojun if ($$ == NULL)
2299 1.1 itojun err(1, "if_item: calloc");
2300 1.1 itojun if (strlcpy($$->ifname, $1, sizeof($$->ifname)) >=
2301 1.1 itojun sizeof($$->ifname)) {
2302 1.1 itojun free($1);
2303 1.1 itojun free($$);
2304 1.1 itojun yyerror("interface name too long");
2305 1.1 itojun YYERROR;
2306 1.1 itojun }
2307 1.1.1.2 yamt
2308 1.1.1.4 martti if ((n = ifa_exists($1)) != NULL)
2309 1.1.1.2 yamt $$->ifa_flags = n->ifa_flags;
2310 1.1.1.2 yamt
2311 1.1 itojun free($1);
2312 1.1 itojun $$->not = 0;
2313 1.1 itojun $$->next = NULL;
2314 1.1 itojun $$->tail = $$;
2315 1.1 itojun }
2316 1.1 itojun ;
2317 1.1 itojun
2318 1.1 itojun af : /* empty */ { $$ = 0; }
2319 1.1 itojun | INET { $$ = AF_INET; }
2320 1.1 itojun | INET6 { $$ = AF_INET6; }
2321 1.1 itojun ;
2322 1.1 itojun
2323 1.1 itojun proto : /* empty */ { $$ = NULL; }
2324 1.1 itojun | PROTO proto_item { $$ = $2; }
2325 1.1 itojun | PROTO '{' proto_list '}' { $$ = $3; }
2326 1.1 itojun ;
2327 1.1 itojun
2328 1.1 itojun proto_list : proto_item { $$ = $1; }
2329 1.1 itojun | proto_list comma proto_item {
2330 1.1 itojun $1->tail->next = $3;
2331 1.1 itojun $1->tail = $3;
2332 1.1 itojun $$ = $1;
2333 1.1 itojun }
2334 1.1 itojun ;
2335 1.1 itojun
2336 1.1 itojun proto_item : STRING {
2337 1.1 itojun u_int8_t pr;
2338 1.1 itojun u_long ulval;
2339 1.1 itojun
2340 1.1 itojun if (atoul($1, &ulval) == 0) {
2341 1.1 itojun if (ulval > 255) {
2342 1.1 itojun yyerror("protocol outside range");
2343 1.1 itojun free($1);
2344 1.1 itojun YYERROR;
2345 1.1 itojun }
2346 1.1 itojun pr = (u_int8_t)ulval;
2347 1.1 itojun } else {
2348 1.1 itojun struct protoent *p;
2349 1.1 itojun
2350 1.1 itojun p = getprotobyname($1);
2351 1.1 itojun if (p == NULL) {
2352 1.1 itojun yyerror("unknown protocol %s", $1);
2353 1.1 itojun free($1);
2354 1.1 itojun YYERROR;
2355 1.1 itojun }
2356 1.1 itojun pr = p->p_proto;
2357 1.1 itojun }
2358 1.1 itojun free($1);
2359 1.1 itojun if (pr == 0) {
2360 1.1 itojun yyerror("proto 0 cannot be used");
2361 1.1 itojun YYERROR;
2362 1.1 itojun }
2363 1.1 itojun $$ = calloc(1, sizeof(struct node_proto));
2364 1.1 itojun if ($$ == NULL)
2365 1.1 itojun err(1, "proto_item: calloc");
2366 1.1 itojun $$->proto = pr;
2367 1.1 itojun $$->next = NULL;
2368 1.1 itojun $$->tail = $$;
2369 1.1 itojun }
2370 1.1 itojun ;
2371 1.1 itojun
2372 1.1 itojun fromto : ALL {
2373 1.1 itojun $$.src.host = NULL;
2374 1.1 itojun $$.src.port = NULL;
2375 1.1 itojun $$.dst.host = NULL;
2376 1.1 itojun $$.dst.port = NULL;
2377 1.1 itojun $$.src_os = NULL;
2378 1.1 itojun }
2379 1.1 itojun | from os to {
2380 1.1 itojun $$.src = $1;
2381 1.1 itojun $$.src_os = $2;
2382 1.1 itojun $$.dst = $3;
2383 1.1 itojun }
2384 1.1 itojun ;
2385 1.1 itojun
2386 1.1 itojun os : /* empty */ { $$ = NULL; }
2387 1.1 itojun | OS xos { $$ = $2; }
2388 1.1 itojun | OS '{' os_list '}' { $$ = $3; }
2389 1.1 itojun ;
2390 1.1 itojun
2391 1.1 itojun xos : STRING {
2392 1.1 itojun $$ = calloc(1, sizeof(struct node_os));
2393 1.1 itojun if ($$ == NULL)
2394 1.1 itojun err(1, "os: calloc");
2395 1.1 itojun $$->os = $1;
2396 1.1 itojun $$->tail = $$;
2397 1.1 itojun }
2398 1.1 itojun ;
2399 1.1 itojun
2400 1.1 itojun os_list : xos { $$ = $1; }
2401 1.1 itojun | os_list comma xos {
2402 1.1 itojun $1->tail->next = $3;
2403 1.1 itojun $1->tail = $3;
2404 1.1 itojun $$ = $1;
2405 1.1 itojun }
2406 1.1 itojun ;
2407 1.1 itojun
2408 1.1 itojun from : /* empty */ {
2409 1.1 itojun $$.host = NULL;
2410 1.1 itojun $$.port = NULL;
2411 1.1 itojun }
2412 1.1 itojun | FROM ipportspec {
2413 1.1 itojun $$ = $2;
2414 1.1 itojun }
2415 1.1 itojun ;
2416 1.1 itojun
2417 1.1 itojun to : /* empty */ {
2418 1.1 itojun $$.host = NULL;
2419 1.1 itojun $$.port = NULL;
2420 1.1 itojun }
2421 1.1 itojun | TO ipportspec {
2422 1.1.1.4 martti if (disallow_urpf_failed($2.host, "\"urpf-failed\" is "
2423 1.1.1.4 martti "not permitted in a destination address"))
2424 1.1.1.4 martti YYERROR;
2425 1.1 itojun $$ = $2;
2426 1.1 itojun }
2427 1.1 itojun ;
2428 1.1 itojun
2429 1.1 itojun ipportspec : ipspec {
2430 1.1 itojun $$.host = $1;
2431 1.1 itojun $$.port = NULL;
2432 1.1 itojun }
2433 1.1 itojun | ipspec PORT portspec {
2434 1.1 itojun $$.host = $1;
2435 1.1 itojun $$.port = $3;
2436 1.1 itojun }
2437 1.1 itojun | PORT portspec {
2438 1.1 itojun $$.host = NULL;
2439 1.1 itojun $$.port = $2;
2440 1.1 itojun }
2441 1.1 itojun ;
2442 1.1 itojun
2443 1.1 itojun ipspec : ANY { $$ = NULL; }
2444 1.1 itojun | xhost { $$ = $1; }
2445 1.1 itojun | '{' host_list '}' { $$ = $2; }
2446 1.1 itojun ;
2447 1.1 itojun
2448 1.1.1.4 martti host_list : ipspec { $$ = $1; }
2449 1.1.1.4 martti | host_list comma ipspec {
2450 1.1 itojun if ($3 == NULL)
2451 1.1 itojun $$ = $1;
2452 1.1 itojun else if ($1 == NULL)
2453 1.1 itojun $$ = $3;
2454 1.1 itojun else {
2455 1.1 itojun $1->tail->next = $3;
2456 1.1 itojun $1->tail = $3->tail;
2457 1.1 itojun $$ = $1;
2458 1.1 itojun }
2459 1.1 itojun }
2460 1.1 itojun ;
2461 1.1 itojun
2462 1.1 itojun xhost : not host {
2463 1.1 itojun struct node_host *n;
2464 1.1 itojun
2465 1.1 itojun for (n = $2; n != NULL; n = n->next)
2466 1.1 itojun n->not = $1;
2467 1.1 itojun $$ = $2;
2468 1.1 itojun }
2469 1.1.1.4 martti | not NOROUTE {
2470 1.1 itojun $$ = calloc(1, sizeof(struct node_host));
2471 1.1 itojun if ($$ == NULL)
2472 1.1 itojun err(1, "xhost: calloc");
2473 1.1 itojun $$->addr.type = PF_ADDR_NOROUTE;
2474 1.1 itojun $$->next = NULL;
2475 1.1.1.4 martti $$->not = $1;
2476 1.1.1.4 martti $$->tail = $$;
2477 1.1.1.4 martti }
2478 1.1.1.4 martti | not URPFFAILED {
2479 1.1.1.4 martti $$ = calloc(1, sizeof(struct node_host));
2480 1.1.1.4 martti if ($$ == NULL)
2481 1.1.1.4 martti err(1, "xhost: calloc");
2482 1.1.1.4 martti $$->addr.type = PF_ADDR_URPFFAILED;
2483 1.1.1.4 martti $$->next = NULL;
2484 1.1.1.4 martti $$->not = $1;
2485 1.1 itojun $$->tail = $$;
2486 1.1 itojun }
2487 1.1 itojun ;
2488 1.1 itojun
2489 1.1 itojun host : STRING {
2490 1.1 itojun if (($$ = host($1)) == NULL) {
2491 1.1 itojun /* error. "any" is handled elsewhere */
2492 1.1 itojun free($1);
2493 1.1 itojun yyerror("could not parse host specification");
2494 1.1 itojun YYERROR;
2495 1.1 itojun }
2496 1.1 itojun free($1);
2497 1.1 itojun
2498 1.1 itojun }
2499 1.1 itojun | STRING '/' number {
2500 1.1 itojun char *buf;
2501 1.1 itojun
2502 1.1 itojun if (asprintf(&buf, "%s/%u", $1, $3) == -1)
2503 1.1 itojun err(1, "host: asprintf");
2504 1.1 itojun free($1);
2505 1.1 itojun if (($$ = host(buf)) == NULL) {
2506 1.1 itojun /* error. "any" is handled elsewhere */
2507 1.1 itojun free(buf);
2508 1.1 itojun yyerror("could not parse host specification");
2509 1.1 itojun YYERROR;
2510 1.1 itojun }
2511 1.1 itojun free(buf);
2512 1.1 itojun }
2513 1.1 itojun | dynaddr
2514 1.1 itojun | dynaddr '/' number {
2515 1.1 itojun struct node_host *n;
2516 1.1 itojun
2517 1.1 itojun $$ = $1;
2518 1.1 itojun for (n = $1; n != NULL; n = n->next)
2519 1.1 itojun set_ipmask(n, $3);
2520 1.1 itojun }
2521 1.1 itojun | '<' STRING '>' {
2522 1.1 itojun if (strlen($2) >= PF_TABLE_NAME_SIZE) {
2523 1.1 itojun yyerror("table name '%s' too long", $2);
2524 1.1 itojun free($2);
2525 1.1 itojun YYERROR;
2526 1.1 itojun }
2527 1.1 itojun $$ = calloc(1, sizeof(struct node_host));
2528 1.1 itojun if ($$ == NULL)
2529 1.1 itojun err(1, "host: calloc");
2530 1.1 itojun $$->addr.type = PF_ADDR_TABLE;
2531 1.1 itojun if (strlcpy($$->addr.v.tblname, $2,
2532 1.1 itojun sizeof($$->addr.v.tblname)) >=
2533 1.1 itojun sizeof($$->addr.v.tblname))
2534 1.1 itojun errx(1, "host: strlcpy");
2535 1.1 itojun free($2);
2536 1.1 itojun $$->next = NULL;
2537 1.1 itojun $$->tail = $$;
2538 1.1 itojun }
2539 1.1.1.3 peter | ROUTE STRING {
2540 1.1.1.3 peter $$ = calloc(1, sizeof(struct node_host));
2541 1.1.1.3 peter if ($$ == NULL) {
2542 1.1.1.3 peter free($2);
2543 1.1.1.3 peter err(1, "host: calloc");
2544 1.1.1.3 peter }
2545 1.1.1.3 peter $$->addr.type = PF_ADDR_RTLABEL;
2546 1.1.1.3 peter if (strlcpy($$->addr.v.rtlabelname, $2,
2547 1.1.1.3 peter sizeof($$->addr.v.rtlabelname)) >=
2548 1.1.1.3 peter sizeof($$->addr.v.rtlabelname)) {
2549 1.1.1.3 peter yyerror("route label too long, max %u chars",
2550 1.1.1.3 peter sizeof($$->addr.v.rtlabelname) - 1);
2551 1.1.1.3 peter free($2);
2552 1.1.1.3 peter free($$);
2553 1.1.1.3 peter YYERROR;
2554 1.1.1.3 peter }
2555 1.1.1.3 peter $$->next = NULL;
2556 1.1.1.3 peter $$->tail = $$;
2557 1.1.1.3 peter free($2);
2558 1.1.1.3 peter }
2559 1.1 itojun ;
2560 1.1 itojun
2561 1.1 itojun number : STRING {
2562 1.1 itojun u_long ulval;
2563 1.1 itojun
2564 1.1 itojun if (atoul($1, &ulval) == -1) {
2565 1.1 itojun yyerror("%s is not a number", $1);
2566 1.1 itojun free($1);
2567 1.1 itojun YYERROR;
2568 1.1 itojun } else
2569 1.1 itojun $$ = ulval;
2570 1.1 itojun free($1);
2571 1.1 itojun }
2572 1.1 itojun ;
2573 1.1 itojun
2574 1.1 itojun dynaddr : '(' STRING ')' {
2575 1.1 itojun int flags = 0;
2576 1.1 itojun char *p, *op;
2577 1.1 itojun
2578 1.1 itojun op = $2;
2579 1.1.1.3 peter if (!isalpha(op[0])) {
2580 1.1.1.3 peter yyerror("invalid interface name '%s'", op);
2581 1.1.1.3 peter free(op);
2582 1.1.1.3 peter YYERROR;
2583 1.1.1.3 peter }
2584 1.1 itojun while ((p = strrchr($2, ':')) != NULL) {
2585 1.1 itojun if (!strcmp(p+1, "network"))
2586 1.1 itojun flags |= PFI_AFLAG_NETWORK;
2587 1.1 itojun else if (!strcmp(p+1, "broadcast"))
2588 1.1 itojun flags |= PFI_AFLAG_BROADCAST;
2589 1.1 itojun else if (!strcmp(p+1, "peer"))
2590 1.1 itojun flags |= PFI_AFLAG_PEER;
2591 1.1 itojun else if (!strcmp(p+1, "0"))
2592 1.1 itojun flags |= PFI_AFLAG_NOALIAS;
2593 1.1 itojun else {
2594 1.1 itojun yyerror("interface %s has bad modifier",
2595 1.1 itojun $2);
2596 1.1 itojun free(op);
2597 1.1 itojun YYERROR;
2598 1.1 itojun }
2599 1.1 itojun *p = '\0';
2600 1.1 itojun }
2601 1.1 itojun if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) {
2602 1.1 itojun free(op);
2603 1.1 itojun yyerror("illegal combination of "
2604 1.1 itojun "interface modifiers");
2605 1.1 itojun YYERROR;
2606 1.1 itojun }
2607 1.1 itojun $$ = calloc(1, sizeof(struct node_host));
2608 1.1 itojun if ($$ == NULL)
2609 1.1 itojun err(1, "address: calloc");
2610 1.1 itojun $$->af = 0;
2611 1.1 itojun set_ipmask($$, 128);
2612 1.1 itojun $$->addr.type = PF_ADDR_DYNIFTL;
2613 1.1 itojun $$->addr.iflags = flags;
2614 1.1 itojun if (strlcpy($$->addr.v.ifname, $2,
2615 1.1 itojun sizeof($$->addr.v.ifname)) >=
2616 1.1 itojun sizeof($$->addr.v.ifname)) {
2617 1.1 itojun free(op);
2618 1.1 itojun free($$);
2619 1.1 itojun yyerror("interface name too long");
2620 1.1 itojun YYERROR;
2621 1.1 itojun }
2622 1.1 itojun free(op);
2623 1.1 itojun $$->next = NULL;
2624 1.1 itojun $$->tail = $$;
2625 1.1 itojun }
2626 1.1 itojun ;
2627 1.1 itojun
2628 1.1 itojun portspec : port_item { $$ = $1; }
2629 1.1 itojun | '{' port_list '}' { $$ = $2; }
2630 1.1 itojun ;
2631 1.1 itojun
2632 1.1 itojun port_list : port_item { $$ = $1; }
2633 1.1 itojun | port_list comma port_item {
2634 1.1 itojun $1->tail->next = $3;
2635 1.1 itojun $1->tail = $3;
2636 1.1 itojun $$ = $1;
2637 1.1 itojun }
2638 1.1 itojun ;
2639 1.1 itojun
2640 1.1 itojun port_item : port {
2641 1.1 itojun $$ = calloc(1, sizeof(struct node_port));
2642 1.1 itojun if ($$ == NULL)
2643 1.1 itojun err(1, "port_item: calloc");
2644 1.1 itojun $$->port[0] = $1.a;
2645 1.1 itojun $$->port[1] = $1.b;
2646 1.1 itojun if ($1.t)
2647 1.1 itojun $$->op = PF_OP_RRG;
2648 1.1 itojun else
2649 1.1 itojun $$->op = PF_OP_EQ;
2650 1.1 itojun $$->next = NULL;
2651 1.1 itojun $$->tail = $$;
2652 1.1 itojun }
2653 1.1 itojun | unaryop port {
2654 1.1 itojun if ($2.t) {
2655 1.1 itojun yyerror("':' cannot be used with an other "
2656 1.1 itojun "port operator");
2657 1.1 itojun YYERROR;
2658 1.1 itojun }
2659 1.1 itojun $$ = calloc(1, sizeof(struct node_port));
2660 1.1 itojun if ($$ == NULL)
2661 1.1 itojun err(1, "port_item: calloc");
2662 1.1 itojun $$->port[0] = $2.a;
2663 1.1 itojun $$->port[1] = $2.b;
2664 1.1 itojun $$->op = $1;
2665 1.1 itojun $$->next = NULL;
2666 1.1 itojun $$->tail = $$;
2667 1.1 itojun }
2668 1.1 itojun | port PORTBINARY port {
2669 1.1 itojun if ($1.t || $3.t) {
2670 1.1 itojun yyerror("':' cannot be used with an other "
2671 1.1 itojun "port operator");
2672 1.1 itojun YYERROR;
2673 1.1 itojun }
2674 1.1 itojun $$ = calloc(1, sizeof(struct node_port));
2675 1.1 itojun if ($$ == NULL)
2676 1.1 itojun err(1, "port_item: calloc");
2677 1.1 itojun $$->port[0] = $1.a;
2678 1.1 itojun $$->port[1] = $3.a;
2679 1.1 itojun $$->op = $2;
2680 1.1 itojun $$->next = NULL;
2681 1.1 itojun $$->tail = $$;
2682 1.1 itojun }
2683 1.1 itojun ;
2684 1.1 itojun
2685 1.1 itojun port : STRING {
2686 1.1 itojun char *p = strchr($1, ':');
2687 1.1 itojun
2688 1.1 itojun if (p == NULL) {
2689 1.1.1.4 martti if (($$.a = getservice($1)) == -1) {
2690 1.1.1.4 martti free($1);
2691 1.1.1.4 martti YYERROR;
2692 1.1 itojun }
2693 1.1.1.4 martti $$.b = $$.t = 0;
2694 1.1 itojun } else {
2695 1.1 itojun int port[2];
2696 1.1 itojun
2697 1.1 itojun *p++ = 0;
2698 1.1 itojun if ((port[0] = getservice($1)) == -1 ||
2699 1.1 itojun (port[1] = getservice(p)) == -1) {
2700 1.1 itojun free($1);
2701 1.1 itojun YYERROR;
2702 1.1 itojun }
2703 1.1 itojun $$.a = port[0];
2704 1.1 itojun $$.b = port[1];
2705 1.1 itojun $$.t = PF_OP_RRG;
2706 1.1 itojun }
2707 1.1 itojun free($1);
2708 1.1 itojun }
2709 1.1 itojun ;
2710 1.1 itojun
2711 1.1 itojun uids : uid_item { $$ = $1; }
2712 1.1 itojun | '{' uid_list '}' { $$ = $2; }
2713 1.1 itojun ;
2714 1.1 itojun
2715 1.1 itojun uid_list : uid_item { $$ = $1; }
2716 1.1 itojun | uid_list comma uid_item {
2717 1.1 itojun $1->tail->next = $3;
2718 1.1 itojun $1->tail = $3;
2719 1.1 itojun $$ = $1;
2720 1.1 itojun }
2721 1.1 itojun ;
2722 1.1 itojun
2723 1.1 itojun uid_item : uid {
2724 1.1 itojun $$ = calloc(1, sizeof(struct node_uid));
2725 1.1 itojun if ($$ == NULL)
2726 1.1 itojun err(1, "uid_item: calloc");
2727 1.1 itojun $$->uid[0] = $1;
2728 1.1 itojun $$->uid[1] = $1;
2729 1.1 itojun $$->op = PF_OP_EQ;
2730 1.1 itojun $$->next = NULL;
2731 1.1 itojun $$->tail = $$;
2732 1.1 itojun }
2733 1.1 itojun | unaryop uid {
2734 1.1 itojun if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
2735 1.1 itojun yyerror("user unknown requires operator = or "
2736 1.1 itojun "!=");
2737 1.1 itojun YYERROR;
2738 1.1 itojun }
2739 1.1 itojun $$ = calloc(1, sizeof(struct node_uid));
2740 1.1 itojun if ($$ == NULL)
2741 1.1 itojun err(1, "uid_item: calloc");
2742 1.1 itojun $$->uid[0] = $2;
2743 1.1 itojun $$->uid[1] = $2;
2744 1.1 itojun $$->op = $1;
2745 1.1 itojun $$->next = NULL;
2746 1.1 itojun $$->tail = $$;
2747 1.1 itojun }
2748 1.1 itojun | uid PORTBINARY uid {
2749 1.1 itojun if ($1 == UID_MAX || $3 == UID_MAX) {
2750 1.1 itojun yyerror("user unknown requires operator = or "
2751 1.1 itojun "!=");
2752 1.1 itojun YYERROR;
2753 1.1 itojun }
2754 1.1 itojun $$ = calloc(1, sizeof(struct node_uid));
2755 1.1 itojun if ($$ == NULL)
2756 1.1 itojun err(1, "uid_item: calloc");
2757 1.1 itojun $$->uid[0] = $1;
2758 1.1 itojun $$->uid[1] = $3;
2759 1.1 itojun $$->op = $2;
2760 1.1 itojun $$->next = NULL;
2761 1.1 itojun $$->tail = $$;
2762 1.1 itojun }
2763 1.1 itojun ;
2764 1.1 itojun
2765 1.1 itojun uid : STRING {
2766 1.1 itojun u_long ulval;
2767 1.1 itojun
2768 1.1 itojun if (atoul($1, &ulval) == -1) {
2769 1.1 itojun if (!strcmp($1, "unknown"))
2770 1.1 itojun $$ = UID_MAX;
2771 1.1 itojun else {
2772 1.1 itojun struct passwd *pw;
2773 1.1 itojun
2774 1.1 itojun if ((pw = getpwnam($1)) == NULL) {
2775 1.1 itojun yyerror("unknown user %s", $1);
2776 1.1 itojun free($1);
2777 1.1 itojun YYERROR;
2778 1.1 itojun }
2779 1.1 itojun $$ = pw->pw_uid;
2780 1.1 itojun }
2781 1.1 itojun } else {
2782 1.1 itojun if (ulval >= UID_MAX) {
2783 1.1 itojun free($1);
2784 1.1 itojun yyerror("illegal uid value %lu", ulval);
2785 1.1 itojun YYERROR;
2786 1.1 itojun }
2787 1.1 itojun $$ = ulval;
2788 1.1 itojun }
2789 1.1 itojun free($1);
2790 1.1 itojun }
2791 1.1 itojun ;
2792 1.1 itojun
2793 1.1 itojun gids : gid_item { $$ = $1; }
2794 1.1 itojun | '{' gid_list '}' { $$ = $2; }
2795 1.1 itojun ;
2796 1.1 itojun
2797 1.1 itojun gid_list : gid_item { $$ = $1; }
2798 1.1 itojun | gid_list comma gid_item {
2799 1.1 itojun $1->tail->next = $3;
2800 1.1 itojun $1->tail = $3;
2801 1.1 itojun $$ = $1;
2802 1.1 itojun }
2803 1.1 itojun ;
2804 1.1 itojun
2805 1.1 itojun gid_item : gid {
2806 1.1 itojun $$ = calloc(1, sizeof(struct node_gid));
2807 1.1 itojun if ($$ == NULL)
2808 1.1 itojun err(1, "gid_item: calloc");
2809 1.1 itojun $$->gid[0] = $1;
2810 1.1 itojun $$->gid[1] = $1;
2811 1.1 itojun $$->op = PF_OP_EQ;
2812 1.1 itojun $$->next = NULL;
2813 1.1 itojun $$->tail = $$;
2814 1.1 itojun }
2815 1.1 itojun | unaryop gid {
2816 1.1 itojun if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
2817 1.1 itojun yyerror("group unknown requires operator = or "
2818 1.1 itojun "!=");
2819 1.1 itojun YYERROR;
2820 1.1 itojun }
2821 1.1 itojun $$ = calloc(1, sizeof(struct node_gid));
2822 1.1 itojun if ($$ == NULL)
2823 1.1 itojun err(1, "gid_item: calloc");
2824 1.1 itojun $$->gid[0] = $2;
2825 1.1 itojun $$->gid[1] = $2;
2826 1.1 itojun $$->op = $1;
2827 1.1 itojun $$->next = NULL;
2828 1.1 itojun $$->tail = $$;
2829 1.1 itojun }
2830 1.1 itojun | gid PORTBINARY gid {
2831 1.1 itojun if ($1 == GID_MAX || $3 == GID_MAX) {
2832 1.1 itojun yyerror("group unknown requires operator = or "
2833 1.1 itojun "!=");
2834 1.1 itojun YYERROR;
2835 1.1 itojun }
2836 1.1 itojun $$ = calloc(1, sizeof(struct node_gid));
2837 1.1 itojun if ($$ == NULL)
2838 1.1 itojun err(1, "gid_item: calloc");
2839 1.1 itojun $$->gid[0] = $1;
2840 1.1 itojun $$->gid[1] = $3;
2841 1.1 itojun $$->op = $2;
2842 1.1 itojun $$->next = NULL;
2843 1.1 itojun $$->tail = $$;
2844 1.1 itojun }
2845 1.1 itojun ;
2846 1.1 itojun
2847 1.1 itojun gid : STRING {
2848 1.1 itojun u_long ulval;
2849 1.1 itojun
2850 1.1 itojun if (atoul($1, &ulval) == -1) {
2851 1.1 itojun if (!strcmp($1, "unknown"))
2852 1.1 itojun $$ = GID_MAX;
2853 1.1 itojun else {
2854 1.1 itojun struct group *grp;
2855 1.1 itojun
2856 1.1 itojun if ((grp = getgrnam($1)) == NULL) {
2857 1.1 itojun yyerror("unknown group %s", $1);
2858 1.1 itojun free($1);
2859 1.1 itojun YYERROR;
2860 1.1 itojun }
2861 1.1 itojun $$ = grp->gr_gid;
2862 1.1 itojun }
2863 1.1 itojun } else {
2864 1.1 itojun if (ulval >= GID_MAX) {
2865 1.1 itojun yyerror("illegal gid value %lu", ulval);
2866 1.1 itojun free($1);
2867 1.1 itojun YYERROR;
2868 1.1 itojun }
2869 1.1 itojun $$ = ulval;
2870 1.1 itojun }
2871 1.1 itojun free($1);
2872 1.1 itojun }
2873 1.1 itojun ;
2874 1.1 itojun
2875 1.1 itojun flag : STRING {
2876 1.1 itojun int f;
2877 1.1 itojun
2878 1.1 itojun if ((f = parse_flags($1)) < 0) {
2879 1.1 itojun yyerror("bad flags %s", $1);
2880 1.1 itojun free($1);
2881 1.1 itojun YYERROR;
2882 1.1 itojun }
2883 1.1 itojun free($1);
2884 1.1 itojun $$.b1 = f;
2885 1.1 itojun }
2886 1.1 itojun ;
2887 1.1 itojun
2888 1.1 itojun flags : FLAGS flag '/' flag { $$.b1 = $2.b1; $$.b2 = $4.b1; }
2889 1.1 itojun | FLAGS '/' flag { $$.b1 = 0; $$.b2 = $3.b1; }
2890 1.1.1.4 martti | FLAGS ANY { $$.b1 = 0; $$.b2 = 0; }
2891 1.1 itojun ;
2892 1.1 itojun
2893 1.1 itojun icmpspec : ICMPTYPE icmp_item { $$ = $2; }
2894 1.1 itojun | ICMPTYPE '{' icmp_list '}' { $$ = $3; }
2895 1.1 itojun | ICMP6TYPE icmp6_item { $$ = $2; }
2896 1.1 itojun | ICMP6TYPE '{' icmp6_list '}' { $$ = $3; }
2897 1.1 itojun ;
2898 1.1 itojun
2899 1.1 itojun icmp_list : icmp_item { $$ = $1; }
2900 1.1 itojun | icmp_list comma icmp_item {
2901 1.1 itojun $1->tail->next = $3;
2902 1.1 itojun $1->tail = $3;
2903 1.1 itojun $$ = $1;
2904 1.1 itojun }
2905 1.1 itojun ;
2906 1.1 itojun
2907 1.1 itojun icmp6_list : icmp6_item { $$ = $1; }
2908 1.1 itojun | icmp6_list comma icmp6_item {
2909 1.1 itojun $1->tail->next = $3;
2910 1.1 itojun $1->tail = $3;
2911 1.1 itojun $$ = $1;
2912 1.1 itojun }
2913 1.1 itojun ;
2914 1.1 itojun
2915 1.1 itojun icmp_item : icmptype {
2916 1.1 itojun $$ = calloc(1, sizeof(struct node_icmp));
2917 1.1 itojun if ($$ == NULL)
2918 1.1 itojun err(1, "icmp_item: calloc");
2919 1.1 itojun $$->type = $1;
2920 1.1 itojun $$->code = 0;
2921 1.1 itojun $$->proto = IPPROTO_ICMP;
2922 1.1 itojun $$->next = NULL;
2923 1.1 itojun $$->tail = $$;
2924 1.1 itojun }
2925 1.1 itojun | icmptype CODE STRING {
2926 1.1 itojun const struct icmpcodeent *p;
2927 1.1 itojun u_long ulval;
2928 1.1 itojun
2929 1.1 itojun if (atoul($3, &ulval) == 0) {
2930 1.1 itojun if (ulval > 255) {
2931 1.1 itojun free($3);
2932 1.1.1.3 peter yyerror("illegal icmp-code %lu", ulval);
2933 1.1 itojun YYERROR;
2934 1.1 itojun }
2935 1.1 itojun } else {
2936 1.1 itojun if ((p = geticmpcodebyname($1-1, $3,
2937 1.1 itojun AF_INET)) == NULL) {
2938 1.1 itojun yyerror("unknown icmp-code %s", $3);
2939 1.1 itojun free($3);
2940 1.1 itojun YYERROR;
2941 1.1 itojun }
2942 1.1 itojun ulval = p->code;
2943 1.1 itojun }
2944 1.1 itojun free($3);
2945 1.1 itojun $$ = calloc(1, sizeof(struct node_icmp));
2946 1.1 itojun if ($$ == NULL)
2947 1.1 itojun err(1, "icmp_item: calloc");
2948 1.1 itojun $$->type = $1;
2949 1.1 itojun $$->code = ulval + 1;
2950 1.1 itojun $$->proto = IPPROTO_ICMP;
2951 1.1 itojun $$->next = NULL;
2952 1.1 itojun $$->tail = $$;
2953 1.1 itojun }
2954 1.1 itojun ;
2955 1.1 itojun
2956 1.1 itojun icmp6_item : icmp6type {
2957 1.1 itojun $$ = calloc(1, sizeof(struct node_icmp));
2958 1.1 itojun if ($$ == NULL)
2959 1.1 itojun err(1, "icmp_item: calloc");
2960 1.1 itojun $$->type = $1;
2961 1.1 itojun $$->code = 0;
2962 1.1 itojun $$->proto = IPPROTO_ICMPV6;
2963 1.1 itojun $$->next = NULL;
2964 1.1 itojun $$->tail = $$;
2965 1.1 itojun }
2966 1.1 itojun | icmp6type CODE STRING {
2967 1.1 itojun const struct icmpcodeent *p;
2968 1.1 itojun u_long ulval;
2969 1.1 itojun
2970 1.1 itojun if (atoul($3, &ulval) == 0) {
2971 1.1 itojun if (ulval > 255) {
2972 1.1.1.3 peter yyerror("illegal icmp6-code %lu",
2973 1.1 itojun ulval);
2974 1.1 itojun free($3);
2975 1.1 itojun YYERROR;
2976 1.1 itojun }
2977 1.1 itojun } else {
2978 1.1 itojun if ((p = geticmpcodebyname($1-1, $3,
2979 1.1 itojun AF_INET6)) == NULL) {
2980 1.1 itojun yyerror("unknown icmp6-code %s", $3);
2981 1.1 itojun free($3);
2982 1.1 itojun YYERROR;
2983 1.1 itojun }
2984 1.1 itojun ulval = p->code;
2985 1.1 itojun }
2986 1.1 itojun free($3);
2987 1.1 itojun $$ = calloc(1, sizeof(struct node_icmp));
2988 1.1 itojun if ($$ == NULL)
2989 1.1 itojun err(1, "icmp_item: calloc");
2990 1.1 itojun $$->type = $1;
2991 1.1 itojun $$->code = ulval + 1;
2992 1.1 itojun $$->proto = IPPROTO_ICMPV6;
2993 1.1 itojun $$->next = NULL;
2994 1.1 itojun $$->tail = $$;
2995 1.1 itojun }
2996 1.1 itojun ;
2997 1.1 itojun
2998 1.1 itojun icmptype : STRING {
2999 1.1 itojun const struct icmptypeent *p;
3000 1.1 itojun u_long ulval;
3001 1.1 itojun
3002 1.1 itojun if (atoul($1, &ulval) == 0) {
3003 1.1 itojun if (ulval > 255) {
3004 1.1.1.3 peter yyerror("illegal icmp-type %lu", ulval);
3005 1.1 itojun free($1);
3006 1.1 itojun YYERROR;
3007 1.1 itojun }
3008 1.1 itojun $$ = ulval + 1;
3009 1.1 itojun } else {
3010 1.1 itojun if ((p = geticmptypebyname($1, AF_INET)) ==
3011 1.1 itojun NULL) {
3012 1.1 itojun yyerror("unknown icmp-type %s", $1);
3013 1.1 itojun free($1);
3014 1.1 itojun YYERROR;
3015 1.1 itojun }
3016 1.1 itojun $$ = p->type + 1;
3017 1.1 itojun }
3018 1.1 itojun free($1);
3019 1.1 itojun }
3020 1.1 itojun ;
3021 1.1 itojun
3022 1.1 itojun icmp6type : STRING {
3023 1.1 itojun const struct icmptypeent *p;
3024 1.1 itojun u_long ulval;
3025 1.1 itojun
3026 1.1 itojun if (atoul($1, &ulval) == 0) {
3027 1.1 itojun if (ulval > 255) {
3028 1.1.1.4 martti yyerror("illegal icmp6-type %lu",
3029 1.1.1.4 martti ulval);
3030 1.1 itojun free($1);
3031 1.1 itojun YYERROR;
3032 1.1 itojun }
3033 1.1 itojun $$ = ulval + 1;
3034 1.1 itojun } else {
3035 1.1 itojun if ((p = geticmptypebyname($1, AF_INET6)) ==
3036 1.1 itojun NULL) {
3037 1.1 itojun yyerror("unknown icmp6-type %s", $1);
3038 1.1 itojun free($1);
3039 1.1 itojun YYERROR;
3040 1.1 itojun }
3041 1.1 itojun $$ = p->type + 1;
3042 1.1 itojun }
3043 1.1 itojun free($1);
3044 1.1 itojun }
3045 1.1 itojun ;
3046 1.1 itojun
3047 1.1 itojun tos : TOS STRING {
3048 1.1 itojun if (!strcmp($2, "lowdelay"))
3049 1.1 itojun $$ = IPTOS_LOWDELAY;
3050 1.1 itojun else if (!strcmp($2, "throughput"))
3051 1.1 itojun $$ = IPTOS_THROUGHPUT;
3052 1.1 itojun else if (!strcmp($2, "reliability"))
3053 1.1 itojun $$ = IPTOS_RELIABILITY;
3054 1.1 itojun else if ($2[0] == '0' && $2[1] == 'x')
3055 1.1 itojun $$ = strtoul($2, NULL, 16);
3056 1.1 itojun else
3057 1.1 itojun $$ = strtoul($2, NULL, 10);
3058 1.1 itojun if (!$$ || $$ > 255) {
3059 1.1 itojun yyerror("illegal tos value %s", $2);
3060 1.1 itojun free($2);
3061 1.1 itojun YYERROR;
3062 1.1 itojun }
3063 1.1 itojun free($2);
3064 1.1 itojun }
3065 1.1 itojun ;
3066 1.1 itojun
3067 1.1 itojun sourcetrack : SOURCETRACK { $$ = PF_SRCTRACK; }
3068 1.1 itojun | SOURCETRACK GLOBAL { $$ = PF_SRCTRACK_GLOBAL; }
3069 1.1 itojun | SOURCETRACK RULE { $$ = PF_SRCTRACK_RULE; }
3070 1.1 itojun ;
3071 1.1 itojun
3072 1.1 itojun statelock : IFBOUND {
3073 1.1 itojun $$ = PFRULE_IFBOUND;
3074 1.1 itojun }
3075 1.1 itojun | FLOATING {
3076 1.1 itojun $$ = 0;
3077 1.1 itojun }
3078 1.1 itojun ;
3079 1.1 itojun
3080 1.1.1.4 martti keep : NO STATE {
3081 1.1.1.4 martti $$.action = 0;
3082 1.1.1.4 martti $$.options = NULL;
3083 1.1.1.4 martti }
3084 1.1.1.4 martti | KEEP STATE state_opt_spec {
3085 1.1 itojun $$.action = PF_STATE_NORMAL;
3086 1.1 itojun $$.options = $3;
3087 1.1 itojun }
3088 1.1 itojun | MODULATE STATE state_opt_spec {
3089 1.1 itojun $$.action = PF_STATE_MODULATE;
3090 1.1 itojun $$.options = $3;
3091 1.1 itojun }
3092 1.1 itojun | SYNPROXY STATE state_opt_spec {
3093 1.1 itojun $$.action = PF_STATE_SYNPROXY;
3094 1.1 itojun $$.options = $3;
3095 1.1 itojun }
3096 1.1 itojun ;
3097 1.1 itojun
3098 1.1.1.3 peter flush : /* empty */ { $$ = 0; }
3099 1.1.1.3 peter | FLUSH { $$ = PF_FLUSH; }
3100 1.1.1.3 peter | FLUSH GLOBAL {
3101 1.1.1.3 peter $$ = PF_FLUSH | PF_FLUSH_GLOBAL;
3102 1.1.1.3 peter }
3103 1.1.1.3 peter ;
3104 1.1.1.3 peter
3105 1.1 itojun state_opt_spec : '(' state_opt_list ')' { $$ = $2; }
3106 1.1 itojun | /* empty */ { $$ = NULL; }
3107 1.1 itojun ;
3108 1.1 itojun
3109 1.1 itojun state_opt_list : state_opt_item { $$ = $1; }
3110 1.1 itojun | state_opt_list comma state_opt_item {
3111 1.1 itojun $1->tail->next = $3;
3112 1.1 itojun $1->tail = $3;
3113 1.1 itojun $$ = $1;
3114 1.1 itojun }
3115 1.1 itojun ;
3116 1.1 itojun
3117 1.1 itojun state_opt_item : MAXIMUM number {
3118 1.1 itojun $$ = calloc(1, sizeof(struct node_state_opt));
3119 1.1 itojun if ($$ == NULL)
3120 1.1 itojun err(1, "state_opt_item: calloc");
3121 1.1 itojun $$->type = PF_STATE_OPT_MAX;
3122 1.1 itojun $$->data.max_states = $2;
3123 1.1 itojun $$->next = NULL;
3124 1.1 itojun $$->tail = $$;
3125 1.1 itojun }
3126 1.1 itojun | NOSYNC {
3127 1.1 itojun $$ = calloc(1, sizeof(struct node_state_opt));
3128 1.1 itojun if ($$ == NULL)
3129 1.1 itojun err(1, "state_opt_item: calloc");
3130 1.1 itojun $$->type = PF_STATE_OPT_NOSYNC;
3131 1.1 itojun $$->next = NULL;
3132 1.1 itojun $$->tail = $$;
3133 1.1 itojun }
3134 1.1 itojun | MAXSRCSTATES number {
3135 1.1 itojun $$ = calloc(1, sizeof(struct node_state_opt));
3136 1.1 itojun if ($$ == NULL)
3137 1.1 itojun err(1, "state_opt_item: calloc");
3138 1.1 itojun $$->type = PF_STATE_OPT_MAX_SRC_STATES;
3139 1.1 itojun $$->data.max_src_states = $2;
3140 1.1 itojun $$->next = NULL;
3141 1.1 itojun $$->tail = $$;
3142 1.1 itojun }
3143 1.1.1.3 peter | MAXSRCCONN number {
3144 1.1.1.3 peter $$ = calloc(1, sizeof(struct node_state_opt));
3145 1.1.1.3 peter if ($$ == NULL)
3146 1.1.1.3 peter err(1, "state_opt_item: calloc");
3147 1.1.1.3 peter $$->type = PF_STATE_OPT_MAX_SRC_CONN;
3148 1.1.1.3 peter $$->data.max_src_conn = $2;
3149 1.1.1.3 peter $$->next = NULL;
3150 1.1.1.3 peter $$->tail = $$;
3151 1.1.1.3 peter }
3152 1.1.1.3 peter | MAXSRCCONNRATE number '/' number {
3153 1.1.1.3 peter $$ = calloc(1, sizeof(struct node_state_opt));
3154 1.1.1.3 peter if ($$ == NULL)
3155 1.1.1.3 peter err(1, "state_opt_item: calloc");
3156 1.1.1.3 peter $$->type = PF_STATE_OPT_MAX_SRC_CONN_RATE;
3157 1.1.1.3 peter $$->data.max_src_conn_rate.limit = $2;
3158 1.1.1.3 peter $$->data.max_src_conn_rate.seconds = $4;
3159 1.1.1.3 peter $$->next = NULL;
3160 1.1.1.3 peter $$->tail = $$;
3161 1.1.1.3 peter }
3162 1.1.1.3 peter | OVERLOAD '<' STRING '>' flush {
3163 1.1.1.3 peter if (strlen($3) >= PF_TABLE_NAME_SIZE) {
3164 1.1.1.3 peter yyerror("table name '%s' too long", $3);
3165 1.1.1.3 peter free($3);
3166 1.1.1.3 peter YYERROR;
3167 1.1.1.3 peter }
3168 1.1.1.3 peter $$ = calloc(1, sizeof(struct node_state_opt));
3169 1.1.1.3 peter if ($$ == NULL)
3170 1.1.1.3 peter err(1, "state_opt_item: calloc");
3171 1.1.1.3 peter if (strlcpy($$->data.overload.tblname, $3,
3172 1.1.1.3 peter PF_TABLE_NAME_SIZE) >= PF_TABLE_NAME_SIZE)
3173 1.1.1.3 peter errx(1, "state_opt_item: strlcpy");
3174 1.1.1.3 peter free($3);
3175 1.1.1.3 peter $$->type = PF_STATE_OPT_OVERLOAD;
3176 1.1.1.3 peter $$->data.overload.flush = $5;
3177 1.1.1.3 peter $$->next = NULL;
3178 1.1.1.3 peter $$->tail = $$;
3179 1.1.1.3 peter }
3180 1.1 itojun | MAXSRCNODES number {
3181 1.1 itojun $$ = calloc(1, sizeof(struct node_state_opt));
3182 1.1 itojun if ($$ == NULL)
3183 1.1 itojun err(1, "state_opt_item: calloc");
3184 1.1 itojun $$->type = PF_STATE_OPT_MAX_SRC_NODES;
3185 1.1 itojun $$->data.max_src_nodes = $2;
3186 1.1 itojun $$->next = NULL;
3187 1.1 itojun $$->tail = $$;
3188 1.1 itojun }
3189 1.1 itojun | sourcetrack {
3190 1.1 itojun $$ = calloc(1, sizeof(struct node_state_opt));
3191 1.1 itojun if ($$ == NULL)
3192 1.1 itojun err(1, "state_opt_item: calloc");
3193 1.1 itojun $$->type = PF_STATE_OPT_SRCTRACK;
3194 1.1 itojun $$->data.src_track = $1;
3195 1.1 itojun $$->next = NULL;
3196 1.1 itojun $$->tail = $$;
3197 1.1 itojun }
3198 1.1 itojun | statelock {
3199 1.1 itojun $$ = calloc(1, sizeof(struct node_state_opt));
3200 1.1 itojun if ($$ == NULL)
3201 1.1 itojun err(1, "state_opt_item: calloc");
3202 1.1 itojun $$->type = PF_STATE_OPT_STATELOCK;
3203 1.1 itojun $$->data.statelock = $1;
3204 1.1 itojun $$->next = NULL;
3205 1.1 itojun $$->tail = $$;
3206 1.1 itojun }
3207 1.1 itojun | STRING number {
3208 1.1 itojun int i;
3209 1.1 itojun
3210 1.1 itojun for (i = 0; pf_timeouts[i].name &&
3211 1.1 itojun strcmp(pf_timeouts[i].name, $1); ++i)
3212 1.1 itojun ; /* nothing */
3213 1.1 itojun if (!pf_timeouts[i].name) {
3214 1.1 itojun yyerror("illegal timeout name %s", $1);
3215 1.1 itojun free($1);
3216 1.1 itojun YYERROR;
3217 1.1 itojun }
3218 1.1 itojun if (strchr(pf_timeouts[i].name, '.') == NULL) {
3219 1.1 itojun yyerror("illegal state timeout %s", $1);
3220 1.1 itojun free($1);
3221 1.1 itojun YYERROR;
3222 1.1 itojun }
3223 1.1 itojun free($1);
3224 1.1 itojun $$ = calloc(1, sizeof(struct node_state_opt));
3225 1.1 itojun if ($$ == NULL)
3226 1.1 itojun err(1, "state_opt_item: calloc");
3227 1.1 itojun $$->type = PF_STATE_OPT_TIMEOUT;
3228 1.1 itojun $$->data.timeout.number = pf_timeouts[i].timeout;
3229 1.1 itojun $$->data.timeout.seconds = $2;
3230 1.1 itojun $$->next = NULL;
3231 1.1 itojun $$->tail = $$;
3232 1.1 itojun }
3233 1.1 itojun ;
3234 1.1 itojun
3235 1.1 itojun label : LABEL STRING {
3236 1.1 itojun $$ = $2;
3237 1.1 itojun }
3238 1.1 itojun ;
3239 1.1 itojun
3240 1.1 itojun qname : QUEUE STRING {
3241 1.1 itojun $$.qname = $2;
3242 1.1 itojun }
3243 1.1 itojun | QUEUE '(' STRING ')' {
3244 1.1 itojun $$.qname = $3;
3245 1.1 itojun }
3246 1.1 itojun | QUEUE '(' STRING comma STRING ')' {
3247 1.1 itojun $$.qname = $3;
3248 1.1 itojun $$.pqname = $5;
3249 1.1 itojun }
3250 1.1 itojun ;
3251 1.1 itojun
3252 1.1 itojun no : /* empty */ { $$ = 0; }
3253 1.1 itojun | NO { $$ = 1; }
3254 1.1 itojun ;
3255 1.1 itojun
3256 1.1 itojun rport : STRING {
3257 1.1 itojun char *p = strchr($1, ':');
3258 1.1 itojun
3259 1.1 itojun if (p == NULL) {
3260 1.1 itojun if (($$.a = getservice($1)) == -1) {
3261 1.1 itojun free($1);
3262 1.1 itojun YYERROR;
3263 1.1 itojun }
3264 1.1 itojun $$.b = $$.t = 0;
3265 1.1 itojun } else if (!strcmp(p+1, "*")) {
3266 1.1 itojun *p = 0;
3267 1.1 itojun if (($$.a = getservice($1)) == -1) {
3268 1.1 itojun free($1);
3269 1.1 itojun YYERROR;
3270 1.1 itojun }
3271 1.1 itojun $$.b = 0;
3272 1.1 itojun $$.t = 1;
3273 1.1 itojun } else {
3274 1.1 itojun *p++ = 0;
3275 1.1 itojun if (($$.a = getservice($1)) == -1 ||
3276 1.1 itojun ($$.b = getservice(p)) == -1) {
3277 1.1 itojun free($1);
3278 1.1 itojun YYERROR;
3279 1.1 itojun }
3280 1.1 itojun if ($$.a == $$.b)
3281 1.1 itojun $$.b = 0;
3282 1.1 itojun $$.t = 0;
3283 1.1 itojun }
3284 1.1 itojun free($1);
3285 1.1 itojun }
3286 1.1 itojun ;
3287 1.1 itojun
3288 1.1 itojun redirspec : host { $$ = $1; }
3289 1.1 itojun | '{' redir_host_list '}' { $$ = $2; }
3290 1.1 itojun ;
3291 1.1 itojun
3292 1.1 itojun redir_host_list : host { $$ = $1; }
3293 1.1 itojun | redir_host_list comma host {
3294 1.1 itojun $1->tail->next = $3;
3295 1.1 itojun $1->tail = $3->tail;
3296 1.1 itojun $$ = $1;
3297 1.1 itojun }
3298 1.1 itojun ;
3299 1.1 itojun
3300 1.1 itojun redirpool : /* empty */ { $$ = NULL; }
3301 1.1 itojun | ARROW redirspec {
3302 1.1 itojun $$ = calloc(1, sizeof(struct redirection));
3303 1.1 itojun if ($$ == NULL)
3304 1.1 itojun err(1, "redirection: calloc");
3305 1.1 itojun $$->host = $2;
3306 1.1 itojun $$->rport.a = $$->rport.b = $$->rport.t = 0;
3307 1.1 itojun }
3308 1.1 itojun | ARROW redirspec PORT rport {
3309 1.1 itojun $$ = calloc(1, sizeof(struct redirection));
3310 1.1 itojun if ($$ == NULL)
3311 1.1 itojun err(1, "redirection: calloc");
3312 1.1 itojun $$->host = $2;
3313 1.1 itojun $$->rport = $4;
3314 1.1 itojun }
3315 1.1 itojun ;
3316 1.1 itojun
3317 1.1 itojun hashkey : /* empty */
3318 1.1 itojun {
3319 1.1 itojun $$ = calloc(1, sizeof(struct pf_poolhashkey));
3320 1.1 itojun if ($$ == NULL)
3321 1.1 itojun err(1, "hashkey: calloc");
3322 1.1 itojun $$->key32[0] = arc4random();
3323 1.1 itojun $$->key32[1] = arc4random();
3324 1.1 itojun $$->key32[2] = arc4random();
3325 1.1 itojun $$->key32[3] = arc4random();
3326 1.1 itojun }
3327 1.1 itojun | string
3328 1.1 itojun {
3329 1.1 itojun if (!strncmp($1, "0x", 2)) {
3330 1.1 itojun if (strlen($1) != 34) {
3331 1.1 itojun free($1);
3332 1.1 itojun yyerror("hex key must be 128 bits "
3333 1.1 itojun "(32 hex digits) long");
3334 1.1 itojun YYERROR;
3335 1.1 itojun }
3336 1.1 itojun $$ = calloc(1, sizeof(struct pf_poolhashkey));
3337 1.1 itojun if ($$ == NULL)
3338 1.1 itojun err(1, "hashkey: calloc");
3339 1.1 itojun
3340 1.1 itojun if (sscanf($1, "0x%8x%8x%8x%8x",
3341 1.1 itojun &$$->key32[0], &$$->key32[1],
3342 1.1 itojun &$$->key32[2], &$$->key32[3]) != 4) {
3343 1.1 itojun free($$);
3344 1.1 itojun free($1);
3345 1.1 itojun yyerror("invalid hex key");
3346 1.1 itojun YYERROR;
3347 1.1 itojun }
3348 1.1 itojun } else {
3349 1.1 itojun MD5_CTX context;
3350 1.1 itojun
3351 1.1 itojun $$ = calloc(1, sizeof(struct pf_poolhashkey));
3352 1.1 itojun if ($$ == NULL)
3353 1.1 itojun err(1, "hashkey: calloc");
3354 1.1 itojun MD5Init(&context);
3355 1.1 itojun MD5Update(&context, (unsigned char *)$1,
3356 1.1 itojun strlen($1));
3357 1.1 itojun MD5Final((unsigned char *)$$, &context);
3358 1.1 itojun HTONL($$->key32[0]);
3359 1.1 itojun HTONL($$->key32[1]);
3360 1.1 itojun HTONL($$->key32[2]);
3361 1.1 itojun HTONL($$->key32[3]);
3362 1.1 itojun }
3363 1.1 itojun free($1);
3364 1.1 itojun }
3365 1.1 itojun ;
3366 1.1 itojun
3367 1.1 itojun pool_opts : { bzero(&pool_opts, sizeof pool_opts); }
3368 1.1 itojun pool_opts_l
3369 1.1 itojun { $$ = pool_opts; }
3370 1.1 itojun | /* empty */ {
3371 1.1 itojun bzero(&pool_opts, sizeof pool_opts);
3372 1.1 itojun $$ = pool_opts;
3373 1.1 itojun }
3374 1.1 itojun ;
3375 1.1 itojun
3376 1.1 itojun pool_opts_l : pool_opts_l pool_opt
3377 1.1 itojun | pool_opt
3378 1.1 itojun ;
3379 1.1 itojun
3380 1.1 itojun pool_opt : BITMASK {
3381 1.1 itojun if (pool_opts.type) {
3382 1.1 itojun yyerror("pool type cannot be redefined");
3383 1.1 itojun YYERROR;
3384 1.1 itojun }
3385 1.1 itojun pool_opts.type = PF_POOL_BITMASK;
3386 1.1 itojun }
3387 1.1 itojun | RANDOM {
3388 1.1 itojun if (pool_opts.type) {
3389 1.1 itojun yyerror("pool type cannot be redefined");
3390 1.1 itojun YYERROR;
3391 1.1 itojun }
3392 1.1 itojun pool_opts.type = PF_POOL_RANDOM;
3393 1.1 itojun }
3394 1.1 itojun | SOURCEHASH hashkey {
3395 1.1 itojun if (pool_opts.type) {
3396 1.1 itojun yyerror("pool type cannot be redefined");
3397 1.1 itojun YYERROR;
3398 1.1 itojun }
3399 1.1 itojun pool_opts.type = PF_POOL_SRCHASH;
3400 1.1 itojun pool_opts.key = $2;
3401 1.1 itojun }
3402 1.1 itojun | ROUNDROBIN {
3403 1.1 itojun if (pool_opts.type) {
3404 1.1 itojun yyerror("pool type cannot be redefined");
3405 1.1 itojun YYERROR;
3406 1.1 itojun }
3407 1.1 itojun pool_opts.type = PF_POOL_ROUNDROBIN;
3408 1.1 itojun }
3409 1.1 itojun | STATICPORT {
3410 1.1 itojun if (pool_opts.staticport) {
3411 1.1 itojun yyerror("static-port cannot be redefined");
3412 1.1 itojun YYERROR;
3413 1.1 itojun }
3414 1.1 itojun pool_opts.staticport = 1;
3415 1.1 itojun }
3416 1.1 itojun | STICKYADDRESS {
3417 1.1 itojun if (filter_opts.marker & POM_STICKYADDRESS) {
3418 1.1 itojun yyerror("sticky-address cannot be redefined");
3419 1.1 itojun YYERROR;
3420 1.1 itojun }
3421 1.1 itojun pool_opts.marker |= POM_STICKYADDRESS;
3422 1.1 itojun pool_opts.opts |= PF_POOL_STICKYADDR;
3423 1.1 itojun }
3424 1.1 itojun ;
3425 1.1 itojun
3426 1.1 itojun redirection : /* empty */ { $$ = NULL; }
3427 1.1 itojun | ARROW host {
3428 1.1 itojun $$ = calloc(1, sizeof(struct redirection));
3429 1.1 itojun if ($$ == NULL)
3430 1.1 itojun err(1, "redirection: calloc");
3431 1.1 itojun $$->host = $2;
3432 1.1 itojun $$->rport.a = $$->rport.b = $$->rport.t = 0;
3433 1.1 itojun }
3434 1.1 itojun | ARROW host PORT rport {
3435 1.1 itojun $$ = calloc(1, sizeof(struct redirection));
3436 1.1 itojun if ($$ == NULL)
3437 1.1 itojun err(1, "redirection: calloc");
3438 1.1 itojun $$->host = $2;
3439 1.1 itojun $$->rport = $4;
3440 1.1 itojun }
3441 1.1 itojun ;
3442 1.1 itojun
3443 1.1.1.4 martti natpasslog : /* empty */ { $$.b1 = $$.b2 = 0; $$.w2 = 0; }
3444 1.1.1.4 martti | PASS { $$.b1 = 1; $$.b2 = 0; $$.w2 = 0; }
3445 1.1.1.4 martti | PASS log { $$.b1 = 1; $$.b2 = $2.log; $$.w2 = $2.logif; }
3446 1.1.1.4 martti | log { $$.b1 = 0; $$.b2 = $1.log; $$.w2 = $1.logif; }
3447 1.1 itojun ;
3448 1.1 itojun
3449 1.1.1.4 martti nataction : no NAT natpasslog {
3450 1.1.1.4 martti if ($1 && $3.b1) {
3451 1.1.1.4 martti yyerror("\"pass\" not valid with \"no\"");
3452 1.1.1.4 martti YYERROR;
3453 1.1.1.4 martti }
3454 1.1 itojun if ($1)
3455 1.1 itojun $$.b1 = PF_NONAT;
3456 1.1 itojun else
3457 1.1 itojun $$.b1 = PF_NAT;
3458 1.1.1.4 martti $$.b2 = $3.b1;
3459 1.1.1.4 martti $$.w = $3.b2;
3460 1.1.1.4 martti $$.w2 = $3.w2;
3461 1.1.1.4 martti }
3462 1.1.1.4 martti | no RDR natpasslog {
3463 1.1.1.4 martti if ($1 && $3.b1) {
3464 1.1.1.4 martti yyerror("\"pass\" not valid with \"no\"");
3465 1.1.1.4 martti YYERROR;
3466 1.1.1.4 martti }
3467 1.1 itojun if ($1)
3468 1.1 itojun $$.b1 = PF_NORDR;
3469 1.1 itojun else
3470 1.1 itojun $$.b1 = PF_RDR;
3471 1.1.1.4 martti $$.b2 = $3.b1;
3472 1.1.1.4 martti $$.w = $3.b2;
3473 1.1.1.4 martti $$.w2 = $3.w2;
3474 1.1 itojun }
3475 1.1 itojun ;
3476 1.1 itojun
3477 1.1.1.4 martti natrule : nataction interface af proto fromto tag tagged rtable
3478 1.1.1.4 martti redirpool pool_opts
3479 1.1 itojun {
3480 1.1 itojun struct pf_rule r;
3481 1.1 itojun
3482 1.1 itojun if (check_rulestate(PFCTL_STATE_NAT))
3483 1.1 itojun YYERROR;
3484 1.1 itojun
3485 1.1 itojun memset(&r, 0, sizeof(r));
3486 1.1 itojun
3487 1.1 itojun r.action = $1.b1;
3488 1.1 itojun r.natpass = $1.b2;
3489 1.1.1.4 martti r.log = $1.w;
3490 1.1.1.4 martti r.logif = $1.w2;
3491 1.1 itojun r.af = $3;
3492 1.1 itojun
3493 1.1 itojun if (!r.af) {
3494 1.1 itojun if ($5.src.host && $5.src.host->af &&
3495 1.1 itojun !$5.src.host->ifindex)
3496 1.1 itojun r.af = $5.src.host->af;
3497 1.1 itojun else if ($5.dst.host && $5.dst.host->af &&
3498 1.1 itojun !$5.dst.host->ifindex)
3499 1.1 itojun r.af = $5.dst.host->af;
3500 1.1 itojun }
3501 1.1 itojun
3502 1.1 itojun if ($6 != NULL)
3503 1.1 itojun if (strlcpy(r.tagname, $6, PF_TAG_NAME_SIZE) >=
3504 1.1 itojun PF_TAG_NAME_SIZE) {
3505 1.1 itojun yyerror("tag too long, max %u chars",
3506 1.1 itojun PF_TAG_NAME_SIZE - 1);
3507 1.1 itojun YYERROR;
3508 1.1 itojun }
3509 1.1 itojun
3510 1.1.1.3 peter if ($7.name)
3511 1.1.1.3 peter if (strlcpy(r.match_tagname, $7.name,
3512 1.1.1.3 peter PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
3513 1.1.1.3 peter yyerror("tag too long, max %u chars",
3514 1.1.1.3 peter PF_TAG_NAME_SIZE - 1);
3515 1.1.1.3 peter YYERROR;
3516 1.1.1.3 peter }
3517 1.1.1.3 peter r.match_tag_not = $7.neg;
3518 1.1.1.4 martti r.rtableid = $8;
3519 1.1.1.3 peter
3520 1.1 itojun if (r.action == PF_NONAT || r.action == PF_NORDR) {
3521 1.1.1.4 martti if ($9 != NULL) {
3522 1.1 itojun yyerror("translation rule with 'no' "
3523 1.1 itojun "does not need '->'");
3524 1.1 itojun YYERROR;
3525 1.1 itojun }
3526 1.1 itojun } else {
3527 1.1.1.4 martti if ($9 == NULL || $9->host == NULL) {
3528 1.1 itojun yyerror("translation rule requires '-> "
3529 1.1 itojun "address'");
3530 1.1 itojun YYERROR;
3531 1.1 itojun }
3532 1.1.1.4 martti if (!r.af && ! $9->host->ifindex)
3533 1.1.1.4 martti r.af = $9->host->af;
3534 1.1 itojun
3535 1.1.1.4 martti remove_invalid_hosts(&$9->host, &r.af);
3536 1.1.1.4 martti if (invalid_redirect($9->host, r.af))
3537 1.1 itojun YYERROR;
3538 1.1.1.4 martti if (check_netmask($9->host, r.af))
3539 1.1 itojun YYERROR;
3540 1.1 itojun
3541 1.1.1.4 martti r.rpool.proxy_port[0] = ntohs($9->rport.a);
3542 1.1 itojun
3543 1.1 itojun switch (r.action) {
3544 1.1 itojun case PF_RDR:
3545 1.1.1.4 martti if (!$9->rport.b && $9->rport.t &&
3546 1.1 itojun $5.dst.port != NULL) {
3547 1.1 itojun r.rpool.proxy_port[1] =
3548 1.1.1.4 martti ntohs($9->rport.a) +
3549 1.1 itojun (ntohs(
3550 1.1 itojun $5.dst.port->port[1]) -
3551 1.1 itojun ntohs(
3552 1.1 itojun $5.dst.port->port[0]));
3553 1.1 itojun } else
3554 1.1 itojun r.rpool.proxy_port[1] =
3555 1.1.1.4 martti ntohs($9->rport.b);
3556 1.1 itojun break;
3557 1.1 itojun case PF_NAT:
3558 1.1 itojun r.rpool.proxy_port[1] =
3559 1.1.1.4 martti ntohs($9->rport.b);
3560 1.1 itojun if (!r.rpool.proxy_port[0] &&
3561 1.1 itojun !r.rpool.proxy_port[1]) {
3562 1.1 itojun r.rpool.proxy_port[0] =
3563 1.1 itojun PF_NAT_PROXY_PORT_LOW;
3564 1.1 itojun r.rpool.proxy_port[1] =
3565 1.1 itojun PF_NAT_PROXY_PORT_HIGH;
3566 1.1 itojun } else if (!r.rpool.proxy_port[1])
3567 1.1 itojun r.rpool.proxy_port[1] =
3568 1.1 itojun r.rpool.proxy_port[0];
3569 1.1 itojun break;
3570 1.1 itojun default:
3571 1.1 itojun break;
3572 1.1 itojun }
3573 1.1 itojun
3574 1.1.1.4 martti r.rpool.opts = $10.type;
3575 1.1 itojun if ((r.rpool.opts & PF_POOL_TYPEMASK) ==
3576 1.1.1.4 martti PF_POOL_NONE && ($9->host->next != NULL ||
3577 1.1.1.4 martti $9->host->addr.type == PF_ADDR_TABLE ||
3578 1.1.1.4 martti DYNIF_MULTIADDR($9->host->addr)))
3579 1.1 itojun r.rpool.opts = PF_POOL_ROUNDROBIN;
3580 1.1 itojun if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
3581 1.1 itojun PF_POOL_ROUNDROBIN &&
3582 1.1.1.4 martti disallow_table($9->host, "tables are only "
3583 1.1 itojun "supported in round-robin redirection "
3584 1.1 itojun "pools"))
3585 1.1 itojun YYERROR;
3586 1.1 itojun if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
3587 1.1 itojun PF_POOL_ROUNDROBIN &&
3588 1.1.1.4 martti disallow_alias($9->host, "interface (%s) "
3589 1.1 itojun "is only supported in round-robin "
3590 1.1 itojun "redirection pools"))
3591 1.1 itojun YYERROR;
3592 1.1.1.4 martti if ($9->host->next != NULL) {
3593 1.1 itojun if ((r.rpool.opts & PF_POOL_TYPEMASK) !=
3594 1.1 itojun PF_POOL_ROUNDROBIN) {
3595 1.1 itojun yyerror("only round-robin "
3596 1.1 itojun "valid for multiple "
3597 1.1 itojun "redirection addresses");
3598 1.1 itojun YYERROR;
3599 1.1 itojun }
3600 1.1 itojun }
3601 1.1 itojun }
3602 1.1 itojun
3603 1.1.1.4 martti if ($10.key != NULL)
3604 1.1.1.4 martti memcpy(&r.rpool.key, $10.key,
3605 1.1 itojun sizeof(struct pf_poolhashkey));
3606 1.1 itojun
3607 1.1.1.4 martti if ($10.opts)
3608 1.1.1.4 martti r.rpool.opts |= $10.opts;
3609 1.1 itojun
3610 1.1.1.4 martti if ($10.staticport) {
3611 1.1 itojun if (r.action != PF_NAT) {
3612 1.1 itojun yyerror("the 'static-port' option is "
3613 1.1 itojun "only valid with nat rules");
3614 1.1 itojun YYERROR;
3615 1.1 itojun }
3616 1.1 itojun if (r.rpool.proxy_port[0] !=
3617 1.1 itojun PF_NAT_PROXY_PORT_LOW &&
3618 1.1 itojun r.rpool.proxy_port[1] !=
3619 1.1 itojun PF_NAT_PROXY_PORT_HIGH) {
3620 1.1 itojun yyerror("the 'static-port' option can't"
3621 1.1 itojun " be used when specifying a port"
3622 1.1 itojun " range");
3623 1.1 itojun YYERROR;
3624 1.1 itojun }
3625 1.1 itojun r.rpool.proxy_port[0] = 0;
3626 1.1 itojun r.rpool.proxy_port[1] = 0;
3627 1.1 itojun }
3628 1.1 itojun
3629 1.1.1.4 martti expand_rule(&r, $2, $9 == NULL ? NULL : $9->host, $4,
3630 1.1 itojun $5.src_os, $5.src.host, $5.src.port, $5.dst.host,
3631 1.1.1.2 yamt $5.dst.port, 0, 0, 0, "");
3632 1.1.1.4 martti free($9);
3633 1.1 itojun }
3634 1.1 itojun ;
3635 1.1 itojun
3636 1.1.1.4 martti binatrule : no BINAT natpasslog interface af proto FROM host TO ipspec tag
3637 1.1.1.4 martti tagged rtable redirection
3638 1.1 itojun {
3639 1.1 itojun struct pf_rule binat;
3640 1.1 itojun struct pf_pooladdr *pa;
3641 1.1 itojun
3642 1.1 itojun if (check_rulestate(PFCTL_STATE_NAT))
3643 1.1 itojun YYERROR;
3644 1.1.1.4 martti if (disallow_urpf_failed($10, "\"urpf-failed\" is not "
3645 1.1.1.4 martti "permitted as a binat destination"))
3646 1.1.1.4 martti YYERROR;
3647 1.1 itojun
3648 1.1 itojun memset(&binat, 0, sizeof(binat));
3649 1.1 itojun
3650 1.1.1.4 martti if ($1 && $3.b1) {
3651 1.1.1.4 martti yyerror("\"pass\" not valid with \"no\"");
3652 1.1.1.4 martti YYERROR;
3653 1.1.1.4 martti }
3654 1.1 itojun if ($1)
3655 1.1 itojun binat.action = PF_NOBINAT;
3656 1.1 itojun else
3657 1.1 itojun binat.action = PF_BINAT;
3658 1.1.1.4 martti binat.natpass = $3.b1;
3659 1.1.1.4 martti binat.log = $3.b2;
3660 1.1.1.4 martti binat.logif = $3.w2;
3661 1.1 itojun binat.af = $5;
3662 1.1 itojun if (!binat.af && $8 != NULL && $8->af)
3663 1.1 itojun binat.af = $8->af;
3664 1.1 itojun if (!binat.af && $10 != NULL && $10->af)
3665 1.1 itojun binat.af = $10->af;
3666 1.1.1.3 peter
3667 1.1.1.4 martti if (!binat.af && $14 != NULL && $14->host)
3668 1.1.1.4 martti binat.af = $14->host->af;
3669 1.1 itojun if (!binat.af) {
3670 1.1 itojun yyerror("address family (inet/inet6) "
3671 1.1 itojun "undefined");
3672 1.1 itojun YYERROR;
3673 1.1 itojun }
3674 1.1 itojun
3675 1.1 itojun if ($4 != NULL) {
3676 1.1 itojun memcpy(binat.ifname, $4->ifname,
3677 1.1 itojun sizeof(binat.ifname));
3678 1.1 itojun binat.ifnot = $4->not;
3679 1.1 itojun free($4);
3680 1.1 itojun }
3681 1.1.1.3 peter
3682 1.1 itojun if ($11 != NULL)
3683 1.1 itojun if (strlcpy(binat.tagname, $11,
3684 1.1 itojun PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
3685 1.1 itojun yyerror("tag too long, max %u chars",
3686 1.1 itojun PF_TAG_NAME_SIZE - 1);
3687 1.1 itojun YYERROR;
3688 1.1 itojun }
3689 1.1.1.3 peter if ($12.name)
3690 1.1.1.3 peter if (strlcpy(binat.match_tagname, $12.name,
3691 1.1.1.3 peter PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
3692 1.1.1.3 peter yyerror("tag too long, max %u chars",
3693 1.1.1.3 peter PF_TAG_NAME_SIZE - 1);
3694 1.1.1.3 peter YYERROR;
3695 1.1.1.3 peter }
3696 1.1.1.3 peter binat.match_tag_not = $12.neg;
3697 1.1.1.4 martti binat.rtableid = $13;
3698 1.1 itojun
3699 1.1 itojun if ($6 != NULL) {
3700 1.1 itojun binat.proto = $6->proto;
3701 1.1 itojun free($6);
3702 1.1 itojun }
3703 1.1 itojun
3704 1.1 itojun if ($8 != NULL && disallow_table($8, "invalid use of "
3705 1.1 itojun "table <%s> as the source address of a binat rule"))
3706 1.1 itojun YYERROR;
3707 1.1 itojun if ($8 != NULL && disallow_alias($8, "invalid use of "
3708 1.1 itojun "interface (%s) as the source address of a binat "
3709 1.1 itojun "rule"))
3710 1.1 itojun YYERROR;
3711 1.1.1.4 martti if ($14 != NULL && $14->host != NULL && disallow_table(
3712 1.1.1.4 martti $14->host, "invalid use of table <%s> as the "
3713 1.1 itojun "redirect address of a binat rule"))
3714 1.1 itojun YYERROR;
3715 1.1.1.4 martti if ($14 != NULL && $14->host != NULL && disallow_alias(
3716 1.1.1.4 martti $14->host, "invalid use of interface (%s) as the "
3717 1.1 itojun "redirect address of a binat rule"))
3718 1.1 itojun YYERROR;
3719 1.1 itojun
3720 1.1 itojun if ($8 != NULL) {
3721 1.1 itojun if ($8->next) {
3722 1.1 itojun yyerror("multiple binat ip addresses");
3723 1.1 itojun YYERROR;
3724 1.1 itojun }
3725 1.1 itojun if ($8->addr.type == PF_ADDR_DYNIFTL)
3726 1.1 itojun $8->af = binat.af;
3727 1.1 itojun if ($8->af != binat.af) {
3728 1.1 itojun yyerror("binat ip versions must match");
3729 1.1 itojun YYERROR;
3730 1.1 itojun }
3731 1.1 itojun if (check_netmask($8, binat.af))
3732 1.1 itojun YYERROR;
3733 1.1 itojun memcpy(&binat.src.addr, &$8->addr,
3734 1.1 itojun sizeof(binat.src.addr));
3735 1.1 itojun free($8);
3736 1.1 itojun }
3737 1.1 itojun if ($10 != NULL) {
3738 1.1 itojun if ($10->next) {
3739 1.1 itojun yyerror("multiple binat ip addresses");
3740 1.1 itojun YYERROR;
3741 1.1 itojun }
3742 1.1 itojun if ($10->af != binat.af && $10->af) {
3743 1.1 itojun yyerror("binat ip versions must match");
3744 1.1 itojun YYERROR;
3745 1.1 itojun }
3746 1.1 itojun if (check_netmask($10, binat.af))
3747 1.1 itojun YYERROR;
3748 1.1 itojun memcpy(&binat.dst.addr, &$10->addr,
3749 1.1 itojun sizeof(binat.dst.addr));
3750 1.1.1.2 yamt binat.dst.neg = $10->not;
3751 1.1 itojun free($10);
3752 1.1 itojun }
3753 1.1 itojun
3754 1.1 itojun if (binat.action == PF_NOBINAT) {
3755 1.1.1.4 martti if ($14 != NULL) {
3756 1.1 itojun yyerror("'no binat' rule does not need"
3757 1.1 itojun " '->'");
3758 1.1 itojun YYERROR;
3759 1.1 itojun }
3760 1.1 itojun } else {
3761 1.1.1.4 martti if ($14 == NULL || $14->host == NULL) {
3762 1.1 itojun yyerror("'binat' rule requires"
3763 1.1 itojun " '-> address'");
3764 1.1 itojun YYERROR;
3765 1.1 itojun }
3766 1.1 itojun
3767 1.1.1.4 martti remove_invalid_hosts(&$14->host, &binat.af);
3768 1.1.1.4 martti if (invalid_redirect($14->host, binat.af))
3769 1.1 itojun YYERROR;
3770 1.1.1.4 martti if ($14->host->next != NULL) {
3771 1.1 itojun yyerror("binat rule must redirect to "
3772 1.1 itojun "a single address");
3773 1.1 itojun YYERROR;
3774 1.1 itojun }
3775 1.1.1.4 martti if (check_netmask($14->host, binat.af))
3776 1.1 itojun YYERROR;
3777 1.1 itojun
3778 1.1 itojun if (!PF_AZERO(&binat.src.addr.v.a.mask,
3779 1.1 itojun binat.af) &&
3780 1.1 itojun !PF_AEQ(&binat.src.addr.v.a.mask,
3781 1.1.1.4 martti &$14->host->addr.v.a.mask, binat.af)) {
3782 1.1 itojun yyerror("'binat' source mask and "
3783 1.1 itojun "redirect mask must be the same");
3784 1.1 itojun YYERROR;
3785 1.1 itojun }
3786 1.1 itojun
3787 1.1 itojun TAILQ_INIT(&binat.rpool.list);
3788 1.1 itojun pa = calloc(1, sizeof(struct pf_pooladdr));
3789 1.1 itojun if (pa == NULL)
3790 1.1 itojun err(1, "binat: calloc");
3791 1.1.1.4 martti pa->addr = $14->host->addr;
3792 1.1 itojun pa->ifname[0] = 0;
3793 1.1 itojun TAILQ_INSERT_TAIL(&binat.rpool.list,
3794 1.1 itojun pa, entries);
3795 1.1 itojun
3796 1.1.1.4 martti free($14);
3797 1.1 itojun }
3798 1.1 itojun
3799 1.1.1.2 yamt pfctl_add_rule(pf, &binat, "");
3800 1.1 itojun }
3801 1.1 itojun ;
3802 1.1 itojun
3803 1.1 itojun tag : /* empty */ { $$ = NULL; }
3804 1.1 itojun | TAG STRING { $$ = $2; }
3805 1.1 itojun ;
3806 1.1 itojun
3807 1.1.1.3 peter tagged : /* empty */ { $$.neg = 0; $$.name = NULL; }
3808 1.1.1.3 peter | not TAGGED string { $$.neg = $1; $$.name = $3; }
3809 1.1.1.3 peter ;
3810 1.1.1.3 peter
3811 1.1.1.4 martti rtable : /* empty */ { $$ = -1; }
3812 1.1.1.4 martti | RTABLE number {
3813 1.1.1.4 martti if ($2 > RT_TABLEID_MAX || $2 < 0) {
3814 1.1.1.4 martti yyerror("invalid rtable id");
3815 1.1.1.4 martti YYERROR;
3816 1.1.1.4 martti }
3817 1.1.1.4 martti $$ = $2;
3818 1.1.1.4 martti }
3819 1.1.1.4 martti ;
3820 1.1.1.4 martti
3821 1.1 itojun route_host : STRING {
3822 1.1 itojun $$ = calloc(1, sizeof(struct node_host));
3823 1.1 itojun if ($$ == NULL)
3824 1.1 itojun err(1, "route_host: calloc");
3825 1.1 itojun $$->ifname = $1;
3826 1.1 itojun set_ipmask($$, 128);
3827 1.1 itojun $$->next = NULL;
3828 1.1 itojun $$->tail = $$;
3829 1.1 itojun }
3830 1.1 itojun | '(' STRING host ')' {
3831 1.1 itojun $$ = $3;
3832 1.1 itojun $$->ifname = $2;
3833 1.1 itojun }
3834 1.1 itojun ;
3835 1.1 itojun
3836 1.1 itojun route_host_list : route_host { $$ = $1; }
3837 1.1 itojun | route_host_list comma route_host {
3838 1.1 itojun if ($1->af == 0)
3839 1.1 itojun $1->af = $3->af;
3840 1.1 itojun if ($1->af != $3->af) {
3841 1.1 itojun yyerror("all pool addresses must be in the "
3842 1.1 itojun "same address family");
3843 1.1 itojun YYERROR;
3844 1.1 itojun }
3845 1.1 itojun $1->tail->next = $3;
3846 1.1 itojun $1->tail = $3->tail;
3847 1.1 itojun $$ = $1;
3848 1.1 itojun }
3849 1.1 itojun ;
3850 1.1 itojun
3851 1.1 itojun routespec : route_host { $$ = $1; }
3852 1.1 itojun | '{' route_host_list '}' { $$ = $2; }
3853 1.1 itojun ;
3854 1.1 itojun
3855 1.1 itojun route : /* empty */ {
3856 1.1 itojun $$.host = NULL;
3857 1.1 itojun $$.rt = 0;
3858 1.1 itojun $$.pool_opts = 0;
3859 1.1 itojun }
3860 1.1 itojun | FASTROUTE {
3861 1.1 itojun $$.host = NULL;
3862 1.1 itojun $$.rt = PF_FASTROUTE;
3863 1.1 itojun $$.pool_opts = 0;
3864 1.1 itojun }
3865 1.1 itojun | ROUTETO routespec pool_opts {
3866 1.1 itojun $$.host = $2;
3867 1.1 itojun $$.rt = PF_ROUTETO;
3868 1.1 itojun $$.pool_opts = $3.type | $3.opts;
3869 1.1 itojun if ($3.key != NULL)
3870 1.1 itojun $$.key = $3.key;
3871 1.1 itojun }
3872 1.1 itojun | REPLYTO routespec pool_opts {
3873 1.1 itojun $$.host = $2;
3874 1.1 itojun $$.rt = PF_REPLYTO;
3875 1.1 itojun $$.pool_opts = $3.type | $3.opts;
3876 1.1 itojun if ($3.key != NULL)
3877 1.1 itojun $$.key = $3.key;
3878 1.1 itojun }
3879 1.1 itojun | DUPTO routespec pool_opts {
3880 1.1 itojun $$.host = $2;
3881 1.1 itojun $$.rt = PF_DUPTO;
3882 1.1 itojun $$.pool_opts = $3.type | $3.opts;
3883 1.1 itojun if ($3.key != NULL)
3884 1.1 itojun $$.key = $3.key;
3885 1.1 itojun }
3886 1.1 itojun ;
3887 1.1 itojun
3888 1.1 itojun timeout_spec : STRING number
3889 1.1 itojun {
3890 1.1 itojun if (check_rulestate(PFCTL_STATE_OPTION)) {
3891 1.1 itojun free($1);
3892 1.1 itojun YYERROR;
3893 1.1 itojun }
3894 1.1 itojun if (pfctl_set_timeout(pf, $1, $2, 0) != 0) {
3895 1.1 itojun yyerror("unknown timeout %s", $1);
3896 1.1 itojun free($1);
3897 1.1 itojun YYERROR;
3898 1.1 itojun }
3899 1.1 itojun free($1);
3900 1.1 itojun }
3901 1.1 itojun ;
3902 1.1 itojun
3903 1.1 itojun timeout_list : timeout_list comma timeout_spec
3904 1.1 itojun | timeout_spec
3905 1.1 itojun ;
3906 1.1 itojun
3907 1.1 itojun limit_spec : STRING number
3908 1.1 itojun {
3909 1.1 itojun if (check_rulestate(PFCTL_STATE_OPTION)) {
3910 1.1 itojun free($1);
3911 1.1 itojun YYERROR;
3912 1.1 itojun }
3913 1.1 itojun if (pfctl_set_limit(pf, $1, $2) != 0) {
3914 1.1 itojun yyerror("unable to set limit %s %u", $1, $2);
3915 1.1 itojun free($1);
3916 1.1 itojun YYERROR;
3917 1.1 itojun }
3918 1.1 itojun free($1);
3919 1.1 itojun }
3920 1.1 itojun ;
3921 1.1 itojun
3922 1.1 itojun limit_list : limit_list comma limit_spec
3923 1.1 itojun | limit_spec
3924 1.1 itojun ;
3925 1.1 itojun
3926 1.1 itojun comma : ','
3927 1.1 itojun | /* empty */
3928 1.1 itojun ;
3929 1.1 itojun
3930 1.1 itojun yesno : NO { $$ = 0; }
3931 1.1 itojun | STRING {
3932 1.1 itojun if (!strcmp($1, "yes"))
3933 1.1 itojun $$ = 1;
3934 1.1 itojun else {
3935 1.1.1.3 peter yyerror("invalid value '%s', expected 'yes' "
3936 1.1.1.3 peter "or 'no'", $1);
3937 1.1 itojun free($1);
3938 1.1 itojun YYERROR;
3939 1.1 itojun }
3940 1.1 itojun free($1);
3941 1.1 itojun }
3942 1.1 itojun ;
3943 1.1 itojun
3944 1.1 itojun unaryop : '=' { $$ = PF_OP_EQ; }
3945 1.1 itojun | '!' '=' { $$ = PF_OP_NE; }
3946 1.1 itojun | '<' '=' { $$ = PF_OP_LE; }
3947 1.1 itojun | '<' { $$ = PF_OP_LT; }
3948 1.1 itojun | '>' '=' { $$ = PF_OP_GE; }
3949 1.1 itojun | '>' { $$ = PF_OP_GT; }
3950 1.1 itojun ;
3951 1.1 itojun
3952 1.1 itojun %%
3953 1.1 itojun
3954 1.1 itojun int
3955 1.1 itojun yyerror(const char *fmt, ...)
3956 1.1 itojun {
3957 1.1 itojun va_list ap;
3958 1.1 itojun extern char *infile;
3959 1.1 itojun
3960 1.1 itojun errors = 1;
3961 1.1 itojun va_start(ap, fmt);
3962 1.1 itojun fprintf(stderr, "%s:%d: ", infile, yylval.lineno);
3963 1.1 itojun vfprintf(stderr, fmt, ap);
3964 1.1 itojun fprintf(stderr, "\n");
3965 1.1 itojun va_end(ap);
3966 1.1 itojun return (0);
3967 1.1 itojun }
3968 1.1 itojun
3969 1.1 itojun int
3970 1.1 itojun disallow_table(struct node_host *h, const char *fmt)
3971 1.1 itojun {
3972 1.1 itojun for (; h != NULL; h = h->next)
3973 1.1 itojun if (h->addr.type == PF_ADDR_TABLE) {
3974 1.1 itojun yyerror(fmt, h->addr.v.tblname);
3975 1.1 itojun return (1);
3976 1.1 itojun }
3977 1.1 itojun return (0);
3978 1.1 itojun }
3979 1.1 itojun
3980 1.1 itojun int
3981 1.1.1.4 martti disallow_urpf_failed(struct node_host *h, const char *fmt)
3982 1.1.1.4 martti {
3983 1.1.1.4 martti for (; h != NULL; h = h->next)
3984 1.1.1.4 martti if (h->addr.type == PF_ADDR_URPFFAILED) {
3985 1.1.1.4 martti yyerror(fmt);
3986 1.1.1.4 martti return (1);
3987 1.1.1.4 martti }
3988 1.1.1.4 martti return (0);
3989 1.1.1.4 martti }
3990 1.1.1.4 martti
3991 1.1.1.4 martti int
3992 1.1 itojun disallow_alias(struct node_host *h, const char *fmt)
3993 1.1 itojun {
3994 1.1 itojun for (; h != NULL; h = h->next)
3995 1.1 itojun if (DYNIF_MULTIADDR(h->addr)) {
3996 1.1 itojun yyerror(fmt, h->addr.v.tblname);
3997 1.1 itojun return (1);
3998 1.1 itojun }
3999 1.1 itojun return (0);
4000 1.1 itojun }
4001 1.1 itojun
4002 1.1 itojun int
4003 1.1.1.4 martti rule_consistent(struct pf_rule *r, int anchor_call)
4004 1.1 itojun {
4005 1.1 itojun int problems = 0;
4006 1.1 itojun
4007 1.1 itojun switch (r->action) {
4008 1.1 itojun case PF_PASS:
4009 1.1 itojun case PF_DROP:
4010 1.1 itojun case PF_SCRUB:
4011 1.1.1.3 peter case PF_NOSCRUB:
4012 1.1.1.4 martti problems = filter_consistent(r, anchor_call);
4013 1.1 itojun break;
4014 1.1 itojun case PF_NAT:
4015 1.1 itojun case PF_NONAT:
4016 1.1 itojun problems = nat_consistent(r);
4017 1.1 itojun break;
4018 1.1 itojun case PF_RDR:
4019 1.1 itojun case PF_NORDR:
4020 1.1 itojun problems = rdr_consistent(r);
4021 1.1 itojun break;
4022 1.1 itojun case PF_BINAT:
4023 1.1 itojun case PF_NOBINAT:
4024 1.1 itojun default:
4025 1.1 itojun break;
4026 1.1 itojun }
4027 1.1 itojun return (problems);
4028 1.1 itojun }
4029 1.1 itojun
4030 1.1 itojun int
4031 1.1.1.4 martti filter_consistent(struct pf_rule *r, int anchor_call)
4032 1.1 itojun {
4033 1.1 itojun int problems = 0;
4034 1.1 itojun
4035 1.1 itojun if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
4036 1.1 itojun (r->src.port_op || r->dst.port_op)) {
4037 1.1 itojun yyerror("port only applies to tcp/udp");
4038 1.1 itojun problems++;
4039 1.1 itojun }
4040 1.1 itojun if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 &&
4041 1.1 itojun (r->type || r->code)) {
4042 1.1 itojun yyerror("icmp-type/code only applies to icmp");
4043 1.1 itojun problems++;
4044 1.1 itojun }
4045 1.1 itojun if (!r->af && (r->type || r->code)) {
4046 1.1 itojun yyerror("must indicate address family with icmp-type/code");
4047 1.1 itojun problems++;
4048 1.1 itojun }
4049 1.1.1.3 peter if (r->overload_tblname[0] &&
4050 1.1.1.3 peter r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) {
4051 1.1.1.3 peter yyerror("'overload' requires 'max-src-conn' "
4052 1.1.1.3 peter "or 'max-src-conn-rate'");
4053 1.1.1.3 peter problems++;
4054 1.1.1.3 peter }
4055 1.1 itojun if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) ||
4056 1.1 itojun (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) {
4057 1.1 itojun yyerror("proto %s doesn't match address family %s",
4058 1.1 itojun r->proto == IPPROTO_ICMP ? "icmp" : "icmp6",
4059 1.1 itojun r->af == AF_INET ? "inet" : "inet6");
4060 1.1 itojun problems++;
4061 1.1 itojun }
4062 1.1 itojun if (r->allow_opts && r->action != PF_PASS) {
4063 1.1 itojun yyerror("allow-opts can only be specified for pass rules");
4064 1.1 itojun problems++;
4065 1.1 itojun }
4066 1.1 itojun if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op ||
4067 1.1 itojun r->dst.port_op || r->flagset || r->type || r->code)) {
4068 1.1 itojun yyerror("fragments can be filtered only on IP header fields");
4069 1.1 itojun problems++;
4070 1.1 itojun }
4071 1.1 itojun if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) {
4072 1.1 itojun yyerror("return-rst can only be applied to TCP rules");
4073 1.1 itojun problems++;
4074 1.1 itojun }
4075 1.1 itojun if (r->max_src_nodes && !(r->rule_flag & PFRULE_RULESRCTRACK)) {
4076 1.1 itojun yyerror("max-src-nodes requires 'source-track rule'");
4077 1.1 itojun problems++;
4078 1.1 itojun }
4079 1.1 itojun if (r->action == PF_DROP && r->keep_state) {
4080 1.1 itojun yyerror("keep state on block rules doesn't make sense");
4081 1.1 itojun problems++;
4082 1.1 itojun }
4083 1.1 itojun return (-problems);
4084 1.1 itojun }
4085 1.1 itojun
4086 1.1 itojun int
4087 1.1 itojun nat_consistent(struct pf_rule *r)
4088 1.1 itojun {
4089 1.1 itojun return (0); /* yeah! */
4090 1.1 itojun }
4091 1.1 itojun
4092 1.1 itojun int
4093 1.1 itojun rdr_consistent(struct pf_rule *r)
4094 1.1 itojun {
4095 1.1 itojun int problems = 0;
4096 1.1 itojun
4097 1.1 itojun if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP) {
4098 1.1 itojun if (r->src.port_op) {
4099 1.1 itojun yyerror("src port only applies to tcp/udp");
4100 1.1 itojun problems++;
4101 1.1 itojun }
4102 1.1 itojun if (r->dst.port_op) {
4103 1.1 itojun yyerror("dst port only applies to tcp/udp");
4104 1.1 itojun problems++;
4105 1.1 itojun }
4106 1.1 itojun if (r->rpool.proxy_port[0]) {
4107 1.1 itojun yyerror("rpool port only applies to tcp/udp");
4108 1.1 itojun problems++;
4109 1.1 itojun }
4110 1.1 itojun }
4111 1.1 itojun if (r->dst.port_op &&
4112 1.1 itojun r->dst.port_op != PF_OP_EQ && r->dst.port_op != PF_OP_RRG) {
4113 1.1 itojun yyerror("invalid port operator for rdr destination port");
4114 1.1 itojun problems++;
4115 1.1 itojun }
4116 1.1 itojun return (-problems);
4117 1.1 itojun }
4118 1.1 itojun
4119 1.1 itojun int
4120 1.1 itojun process_tabledef(char *name, struct table_opts *opts)
4121 1.1 itojun {
4122 1.1 itojun struct pfr_buffer ab;
4123 1.1 itojun struct node_tinit *ti;
4124 1.1 itojun
4125 1.1 itojun bzero(&ab, sizeof(ab));
4126 1.1 itojun ab.pfrb_type = PFRB_ADDRS;
4127 1.1 itojun SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) {
4128 1.1 itojun if (ti->file)
4129 1.1 itojun if (pfr_buf_load(&ab, ti->file, 0, append_addr)) {
4130 1.1 itojun if (errno)
4131 1.1 itojun yyerror("cannot load \"%s\": %s",
4132 1.1 itojun ti->file, strerror(errno));
4133 1.1 itojun else
4134 1.1 itojun yyerror("file \"%s\" contains bad data",
4135 1.1 itojun ti->file);
4136 1.1 itojun goto _error;
4137 1.1 itojun }
4138 1.1 itojun if (ti->host)
4139 1.1 itojun if (append_addr_host(&ab, ti->host, 0, 0)) {
4140 1.1 itojun yyerror("cannot create address buffer: %s",
4141 1.1 itojun strerror(errno));
4142 1.1 itojun goto _error;
4143 1.1 itojun }
4144 1.1 itojun }
4145 1.1 itojun if (pf->opts & PF_OPT_VERBOSE)
4146 1.1 itojun print_tabledef(name, opts->flags, opts->init_addr,
4147 1.1 itojun &opts->init_nodes);
4148 1.1 itojun if (!(pf->opts & PF_OPT_NOACTION) &&
4149 1.1 itojun pfctl_define_table(name, opts->flags, opts->init_addr,
4150 1.1.1.4 martti pf->anchor->name, &ab, pf->anchor->ruleset.tticket)) {
4151 1.1 itojun yyerror("cannot define table %s: %s", name,
4152 1.1 itojun pfr_strerror(errno));
4153 1.1 itojun goto _error;
4154 1.1 itojun }
4155 1.1 itojun pf->tdirty = 1;
4156 1.1 itojun pfr_buf_clear(&ab);
4157 1.1 itojun return (0);
4158 1.1 itojun _error:
4159 1.1 itojun pfr_buf_clear(&ab);
4160 1.1 itojun return (-1);
4161 1.1 itojun }
4162 1.1 itojun
4163 1.1 itojun struct keywords {
4164 1.1 itojun const char *k_name;
4165 1.1 itojun int k_val;
4166 1.1 itojun };
4167 1.1 itojun
4168 1.1 itojun /* macro gore, but you should've seen the prior indentation nightmare... */
4169 1.1 itojun
4170 1.1 itojun #define FREE_LIST(T,r) \
4171 1.1 itojun do { \
4172 1.1 itojun T *p, *node = r; \
4173 1.1 itojun while (node != NULL) { \
4174 1.1 itojun p = node; \
4175 1.1 itojun node = node->next; \
4176 1.1 itojun free(p); \
4177 1.1 itojun } \
4178 1.1 itojun } while (0)
4179 1.1 itojun
4180 1.1 itojun #define LOOP_THROUGH(T,n,r,C) \
4181 1.1 itojun do { \
4182 1.1 itojun T *n; \
4183 1.1 itojun if (r == NULL) { \
4184 1.1 itojun r = calloc(1, sizeof(T)); \
4185 1.1 itojun if (r == NULL) \
4186 1.1 itojun err(1, "LOOP: calloc"); \
4187 1.1 itojun r->next = NULL; \
4188 1.1 itojun } \
4189 1.1 itojun n = r; \
4190 1.1 itojun while (n != NULL) { \
4191 1.1 itojun do { \
4192 1.1 itojun C; \
4193 1.1 itojun } while (0); \
4194 1.1 itojun n = n->next; \
4195 1.1 itojun } \
4196 1.1 itojun } while (0)
4197 1.1 itojun
4198 1.1 itojun void
4199 1.1 itojun expand_label_str(char *label, size_t len, const char *srch, const char *repl)
4200 1.1 itojun {
4201 1.1 itojun char *tmp;
4202 1.1 itojun char *p, *q;
4203 1.1 itojun
4204 1.1 itojun if ((tmp = calloc(1, len)) == NULL)
4205 1.1 itojun err(1, "expand_label_str: calloc");
4206 1.1 itojun p = q = label;
4207 1.1 itojun while ((q = strstr(p, srch)) != NULL) {
4208 1.1 itojun *q = '\0';
4209 1.1 itojun if ((strlcat(tmp, p, len) >= len) ||
4210 1.1 itojun (strlcat(tmp, repl, len) >= len))
4211 1.1 itojun errx(1, "expand_label: label too long");
4212 1.1 itojun q += strlen(srch);
4213 1.1 itojun p = q;
4214 1.1 itojun }
4215 1.1 itojun if (strlcat(tmp, p, len) >= len)
4216 1.1 itojun errx(1, "expand_label: label too long");
4217 1.1 itojun strlcpy(label, tmp, len); /* always fits */
4218 1.1 itojun free(tmp);
4219 1.1 itojun }
4220 1.1 itojun
4221 1.1 itojun void
4222 1.1 itojun expand_label_if(const char *name, char *label, size_t len, const char *ifname)
4223 1.1 itojun {
4224 1.1 itojun if (strstr(label, name) != NULL) {
4225 1.1 itojun if (!*ifname)
4226 1.1 itojun expand_label_str(label, len, name, "any");
4227 1.1 itojun else
4228 1.1 itojun expand_label_str(label, len, name, ifname);
4229 1.1 itojun }
4230 1.1 itojun }
4231 1.1 itojun
4232 1.1 itojun void
4233 1.1 itojun expand_label_addr(const char *name, char *label, size_t len, sa_family_t af,
4234 1.1 itojun struct node_host *h)
4235 1.1 itojun {
4236 1.1 itojun char tmp[64], tmp_not[66];
4237 1.1 itojun
4238 1.1 itojun if (strstr(label, name) != NULL) {
4239 1.1 itojun switch (h->addr.type) {
4240 1.1 itojun case PF_ADDR_DYNIFTL:
4241 1.1 itojun snprintf(tmp, sizeof(tmp), "(%s)", h->addr.v.ifname);
4242 1.1 itojun break;
4243 1.1 itojun case PF_ADDR_TABLE:
4244 1.1 itojun snprintf(tmp, sizeof(tmp), "<%s>", h->addr.v.tblname);
4245 1.1 itojun break;
4246 1.1 itojun case PF_ADDR_NOROUTE:
4247 1.1 itojun snprintf(tmp, sizeof(tmp), "no-route");
4248 1.1 itojun break;
4249 1.1.1.4 martti case PF_ADDR_URPFFAILED:
4250 1.1.1.4 martti snprintf(tmp, sizeof(tmp), "urpf-failed");
4251 1.1.1.4 martti break;
4252 1.1 itojun case PF_ADDR_ADDRMASK:
4253 1.1 itojun if (!af || (PF_AZERO(&h->addr.v.a.addr, af) &&
4254 1.1 itojun PF_AZERO(&h->addr.v.a.mask, af)))
4255 1.1 itojun snprintf(tmp, sizeof(tmp), "any");
4256 1.1 itojun else {
4257 1.1 itojun char a[48];
4258 1.1 itojun int bits;
4259 1.1 itojun
4260 1.1 itojun if (inet_ntop(af, &h->addr.v.a.addr, a,
4261 1.1 itojun sizeof(a)) == NULL)
4262 1.1 itojun snprintf(tmp, sizeof(tmp), "?");
4263 1.1 itojun else {
4264 1.1 itojun bits = unmask(&h->addr.v.a.mask, af);
4265 1.1 itojun if ((af == AF_INET && bits < 32) ||
4266 1.1 itojun (af == AF_INET6 && bits < 128))
4267 1.1 itojun snprintf(tmp, sizeof(tmp),
4268 1.1 itojun "%s/%d", a, bits);
4269 1.1 itojun else
4270 1.1 itojun snprintf(tmp, sizeof(tmp),
4271 1.1 itojun "%s", a);
4272 1.1 itojun }
4273 1.1 itojun }
4274 1.1 itojun break;
4275 1.1 itojun default:
4276 1.1 itojun snprintf(tmp, sizeof(tmp), "?");
4277 1.1 itojun break;
4278 1.1 itojun }
4279 1.1 itojun
4280 1.1 itojun if (h->not) {
4281 1.1 itojun snprintf(tmp_not, sizeof(tmp_not), "! %s", tmp);
4282 1.1 itojun expand_label_str(label, len, name, tmp_not);
4283 1.1 itojun } else
4284 1.1 itojun expand_label_str(label, len, name, tmp);
4285 1.1 itojun }
4286 1.1 itojun }
4287 1.1 itojun
4288 1.1 itojun void
4289 1.1 itojun expand_label_port(const char *name, char *label, size_t len,
4290 1.1 itojun struct node_port *port)
4291 1.1 itojun {
4292 1.1 itojun char a1[6], a2[6], op[13] = "";
4293 1.1 itojun
4294 1.1 itojun if (strstr(label, name) != NULL) {
4295 1.1 itojun snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0]));
4296 1.1 itojun snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1]));
4297 1.1 itojun if (!port->op)
4298 1.1 itojun ;
4299 1.1 itojun else if (port->op == PF_OP_IRG)
4300 1.1 itojun snprintf(op, sizeof(op), "%s><%s", a1, a2);
4301 1.1 itojun else if (port->op == PF_OP_XRG)
4302 1.1 itojun snprintf(op, sizeof(op), "%s<>%s", a1, a2);
4303 1.1 itojun else if (port->op == PF_OP_EQ)
4304 1.1 itojun snprintf(op, sizeof(op), "%s", a1);
4305 1.1 itojun else if (port->op == PF_OP_NE)
4306 1.1 itojun snprintf(op, sizeof(op), "!=%s", a1);
4307 1.1 itojun else if (port->op == PF_OP_LT)
4308 1.1 itojun snprintf(op, sizeof(op), "<%s", a1);
4309 1.1 itojun else if (port->op == PF_OP_LE)
4310 1.1 itojun snprintf(op, sizeof(op), "<=%s", a1);
4311 1.1 itojun else if (port->op == PF_OP_GT)
4312 1.1 itojun snprintf(op, sizeof(op), ">%s", a1);
4313 1.1 itojun else if (port->op == PF_OP_GE)
4314 1.1 itojun snprintf(op, sizeof(op), ">=%s", a1);
4315 1.1 itojun expand_label_str(label, len, name, op);
4316 1.1 itojun }
4317 1.1 itojun }
4318 1.1 itojun
4319 1.1 itojun void
4320 1.1 itojun expand_label_proto(const char *name, char *label, size_t len, u_int8_t proto)
4321 1.1 itojun {
4322 1.1 itojun struct protoent *pe;
4323 1.1 itojun char n[4];
4324 1.1 itojun
4325 1.1 itojun if (strstr(label, name) != NULL) {
4326 1.1 itojun pe = getprotobynumber(proto);
4327 1.1 itojun if (pe != NULL)
4328 1.1 itojun expand_label_str(label, len, name, pe->p_name);
4329 1.1 itojun else {
4330 1.1 itojun snprintf(n, sizeof(n), "%u", proto);
4331 1.1 itojun expand_label_str(label, len, name, n);
4332 1.1 itojun }
4333 1.1 itojun }
4334 1.1 itojun }
4335 1.1 itojun
4336 1.1 itojun void
4337 1.1 itojun expand_label_nr(const char *name, char *label, size_t len)
4338 1.1 itojun {
4339 1.1 itojun char n[11];
4340 1.1 itojun
4341 1.1 itojun if (strstr(label, name) != NULL) {
4342 1.1.1.4 martti snprintf(n, sizeof(n), "%u", pf->anchor->match);
4343 1.1 itojun expand_label_str(label, len, name, n);
4344 1.1 itojun }
4345 1.1 itojun }
4346 1.1 itojun
4347 1.1 itojun void
4348 1.1 itojun expand_label(char *label, size_t len, const char *ifname, sa_family_t af,
4349 1.1 itojun struct node_host *src_host, struct node_port *src_port,
4350 1.1 itojun struct node_host *dst_host, struct node_port *dst_port,
4351 1.1 itojun u_int8_t proto)
4352 1.1 itojun {
4353 1.1 itojun expand_label_if("$if", label, len, ifname);
4354 1.1 itojun expand_label_addr("$srcaddr", label, len, af, src_host);
4355 1.1 itojun expand_label_addr("$dstaddr", label, len, af, dst_host);
4356 1.1 itojun expand_label_port("$srcport", label, len, src_port);
4357 1.1 itojun expand_label_port("$dstport", label, len, dst_port);
4358 1.1 itojun expand_label_proto("$proto", label, len, proto);
4359 1.1 itojun expand_label_nr("$nr", label, len);
4360 1.1 itojun }
4361 1.1 itojun
4362 1.1 itojun int
4363 1.1 itojun expand_altq(struct pf_altq *a, struct node_if *interfaces,
4364 1.1 itojun struct node_queue *nqueues, struct node_queue_bw bwspec,
4365 1.1 itojun struct node_queue_opt *opts)
4366 1.1 itojun {
4367 1.1 itojun struct pf_altq pa, pb;
4368 1.1 itojun char qname[PF_QNAME_SIZE];
4369 1.1 itojun struct node_queue *n;
4370 1.1 itojun struct node_queue_bw bw;
4371 1.1 itojun int errs = 0;
4372 1.1 itojun
4373 1.1 itojun if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) {
4374 1.1 itojun FREE_LIST(struct node_if, interfaces);
4375 1.1 itojun FREE_LIST(struct node_queue, nqueues);
4376 1.1 itojun return (0);
4377 1.1 itojun }
4378 1.1 itojun
4379 1.1 itojun LOOP_THROUGH(struct node_if, interface, interfaces,
4380 1.1 itojun memcpy(&pa, a, sizeof(struct pf_altq));
4381 1.1 itojun if (strlcpy(pa.ifname, interface->ifname,
4382 1.1 itojun sizeof(pa.ifname)) >= sizeof(pa.ifname))
4383 1.1 itojun errx(1, "expand_altq: strlcpy");
4384 1.1 itojun
4385 1.1 itojun if (interface->not) {
4386 1.1 itojun yyerror("altq on ! <interface> is not supported");
4387 1.1 itojun errs++;
4388 1.1 itojun } else {
4389 1.1 itojun if (eval_pfaltq(pf, &pa, &bwspec, opts))
4390 1.1 itojun errs++;
4391 1.1 itojun else
4392 1.1 itojun if (pfctl_add_altq(pf, &pa))
4393 1.1 itojun errs++;
4394 1.1 itojun
4395 1.1 itojun if (pf->opts & PF_OPT_VERBOSE) {
4396 1.1 itojun print_altq(&pf->paltq->altq, 0,
4397 1.1 itojun &bwspec, opts);
4398 1.1 itojun if (nqueues && nqueues->tail) {
4399 1.1 itojun printf("queue { ");
4400 1.1 itojun LOOP_THROUGH(struct node_queue, queue,
4401 1.1 itojun nqueues,
4402 1.1 itojun printf("%s ",
4403 1.1 itojun queue->queue);
4404 1.1 itojun );
4405 1.1 itojun printf("}");
4406 1.1 itojun }
4407 1.1 itojun printf("\n");
4408 1.1 itojun }
4409 1.1 itojun
4410 1.1 itojun if (pa.scheduler == ALTQT_CBQ ||
4411 1.1 itojun pa.scheduler == ALTQT_HFSC) {
4412 1.1 itojun /* now create a root queue */
4413 1.1 itojun memset(&pb, 0, sizeof(struct pf_altq));
4414 1.1 itojun if (strlcpy(qname, "root_", sizeof(qname)) >=
4415 1.1 itojun sizeof(qname))
4416 1.1 itojun errx(1, "expand_altq: strlcpy");
4417 1.1 itojun if (strlcat(qname, interface->ifname,
4418 1.1 itojun sizeof(qname)) >= sizeof(qname))
4419 1.1 itojun errx(1, "expand_altq: strlcat");
4420 1.1 itojun if (strlcpy(pb.qname, qname,
4421 1.1 itojun sizeof(pb.qname)) >= sizeof(pb.qname))
4422 1.1 itojun errx(1, "expand_altq: strlcpy");
4423 1.1 itojun if (strlcpy(pb.ifname, interface->ifname,
4424 1.1 itojun sizeof(pb.ifname)) >= sizeof(pb.ifname))
4425 1.1 itojun errx(1, "expand_altq: strlcpy");
4426 1.1 itojun pb.qlimit = pa.qlimit;
4427 1.1 itojun pb.scheduler = pa.scheduler;
4428 1.1 itojun bw.bw_absolute = pa.ifbandwidth;
4429 1.1 itojun bw.bw_percent = 0;
4430 1.1 itojun if (eval_pfqueue(pf, &pb, &bw, opts))
4431 1.1 itojun errs++;
4432 1.1 itojun else
4433 1.1 itojun if (pfctl_add_altq(pf, &pb))
4434 1.1 itojun errs++;
4435 1.1 itojun }
4436 1.1 itojun
4437 1.1 itojun LOOP_THROUGH(struct node_queue, queue, nqueues,
4438 1.1 itojun n = calloc(1, sizeof(struct node_queue));
4439 1.1 itojun if (n == NULL)
4440 1.1 itojun err(1, "expand_altq: calloc");
4441 1.1 itojun if (pa.scheduler == ALTQT_CBQ ||
4442 1.1 itojun pa.scheduler == ALTQT_HFSC)
4443 1.1 itojun if (strlcpy(n->parent, qname,
4444 1.1 itojun sizeof(n->parent)) >=
4445 1.1 itojun sizeof(n->parent))
4446 1.1 itojun errx(1, "expand_altq: strlcpy");
4447 1.1 itojun if (strlcpy(n->queue, queue->queue,
4448 1.1 itojun sizeof(n->queue)) >= sizeof(n->queue))
4449 1.1 itojun errx(1, "expand_altq: strlcpy");
4450 1.1 itojun if (strlcpy(n->ifname, interface->ifname,
4451 1.1 itojun sizeof(n->ifname)) >= sizeof(n->ifname))
4452 1.1 itojun errx(1, "expand_altq: strlcpy");
4453 1.1 itojun n->scheduler = pa.scheduler;
4454 1.1 itojun n->next = NULL;
4455 1.1 itojun n->tail = n;
4456 1.1 itojun if (queues == NULL)
4457 1.1 itojun queues = n;
4458 1.1 itojun else {
4459 1.1 itojun queues->tail->next = n;
4460 1.1 itojun queues->tail = n;
4461 1.1 itojun }
4462 1.1 itojun );
4463 1.1 itojun }
4464 1.1 itojun );
4465 1.1 itojun FREE_LIST(struct node_if, interfaces);
4466 1.1 itojun FREE_LIST(struct node_queue, nqueues);
4467 1.1 itojun
4468 1.1 itojun return (errs);
4469 1.1 itojun }
4470 1.1 itojun
4471 1.1 itojun int
4472 1.1 itojun expand_queue(struct pf_altq *a, struct node_if *interfaces,
4473 1.1 itojun struct node_queue *nqueues, struct node_queue_bw bwspec,
4474 1.1 itojun struct node_queue_opt *opts)
4475 1.1 itojun {
4476 1.1 itojun struct node_queue *n, *nq;
4477 1.1 itojun struct pf_altq pa;
4478 1.1 itojun u_int8_t found = 0;
4479 1.1 itojun u_int8_t errs = 0;
4480 1.1 itojun
4481 1.1 itojun if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) {
4482 1.1 itojun FREE_LIST(struct node_queue, nqueues);
4483 1.1 itojun return (0);
4484 1.1 itojun }
4485 1.1 itojun
4486 1.1 itojun if (queues == NULL) {
4487 1.1 itojun yyerror("queue %s has no parent", a->qname);
4488 1.1 itojun FREE_LIST(struct node_queue, nqueues);
4489 1.1 itojun return (1);
4490 1.1 itojun }
4491 1.1 itojun
4492 1.1 itojun LOOP_THROUGH(struct node_if, interface, interfaces,
4493 1.1 itojun LOOP_THROUGH(struct node_queue, tqueue, queues,
4494 1.1 itojun if (!strncmp(a->qname, tqueue->queue, PF_QNAME_SIZE) &&
4495 1.1 itojun (interface->ifname[0] == 0 ||
4496 1.1 itojun (!interface->not && !strncmp(interface->ifname,
4497 1.1 itojun tqueue->ifname, IFNAMSIZ)) ||
4498 1.1 itojun (interface->not && strncmp(interface->ifname,
4499 1.1 itojun tqueue->ifname, IFNAMSIZ)))) {
4500 1.1 itojun /* found ourself in queues */
4501 1.1 itojun found++;
4502 1.1 itojun
4503 1.1 itojun memcpy(&pa, a, sizeof(struct pf_altq));
4504 1.1 itojun
4505 1.1 itojun if (pa.scheduler != ALTQT_NONE &&
4506 1.1 itojun pa.scheduler != tqueue->scheduler) {
4507 1.1 itojun yyerror("exactly one scheduler type "
4508 1.1 itojun "per interface allowed");
4509 1.1 itojun return (1);
4510 1.1 itojun }
4511 1.1 itojun pa.scheduler = tqueue->scheduler;
4512 1.1 itojun
4513 1.1 itojun /* scheduler dependent error checking */
4514 1.1 itojun switch (pa.scheduler) {
4515 1.1 itojun case ALTQT_PRIQ:
4516 1.1 itojun if (nqueues != NULL) {
4517 1.1 itojun yyerror("priq queues cannot "
4518 1.1 itojun "have child queues");
4519 1.1 itojun return (1);
4520 1.1 itojun }
4521 1.1 itojun if (bwspec.bw_absolute > 0 ||
4522 1.1 itojun bwspec.bw_percent < 100) {
4523 1.1 itojun yyerror("priq doesn't take "
4524 1.1 itojun "bandwidth");
4525 1.1 itojun return (1);
4526 1.1 itojun }
4527 1.1 itojun break;
4528 1.1 itojun default:
4529 1.1 itojun break;
4530 1.1 itojun }
4531 1.1 itojun
4532 1.1 itojun if (strlcpy(pa.ifname, tqueue->ifname,
4533 1.1 itojun sizeof(pa.ifname)) >= sizeof(pa.ifname))
4534 1.1 itojun errx(1, "expand_queue: strlcpy");
4535 1.1 itojun if (strlcpy(pa.parent, tqueue->parent,
4536 1.1 itojun sizeof(pa.parent)) >= sizeof(pa.parent))
4537 1.1 itojun errx(1, "expand_queue: strlcpy");
4538 1.1 itojun
4539 1.1 itojun if (eval_pfqueue(pf, &pa, &bwspec, opts))
4540 1.1 itojun errs++;
4541 1.1 itojun else
4542 1.1 itojun if (pfctl_add_altq(pf, &pa))
4543 1.1 itojun errs++;
4544 1.1 itojun
4545 1.1 itojun for (nq = nqueues; nq != NULL; nq = nq->next) {
4546 1.1 itojun if (!strcmp(a->qname, nq->queue)) {
4547 1.1 itojun yyerror("queue cannot have "
4548 1.1 itojun "itself as child");
4549 1.1 itojun errs++;
4550 1.1 itojun continue;
4551 1.1 itojun }
4552 1.1 itojun n = calloc(1,
4553 1.1 itojun sizeof(struct node_queue));
4554 1.1 itojun if (n == NULL)
4555 1.1 itojun err(1, "expand_queue: calloc");
4556 1.1 itojun if (strlcpy(n->parent, a->qname,
4557 1.1 itojun sizeof(n->parent)) >=
4558 1.1 itojun sizeof(n->parent))
4559 1.1 itojun errx(1, "expand_queue strlcpy");
4560 1.1 itojun if (strlcpy(n->queue, nq->queue,
4561 1.1 itojun sizeof(n->queue)) >=
4562 1.1 itojun sizeof(n->queue))
4563 1.1 itojun errx(1, "expand_queue strlcpy");
4564 1.1 itojun if (strlcpy(n->ifname, tqueue->ifname,
4565 1.1 itojun sizeof(n->ifname)) >=
4566 1.1 itojun sizeof(n->ifname))
4567 1.1 itojun errx(1, "expand_queue strlcpy");
4568 1.1 itojun n->scheduler = tqueue->scheduler;
4569 1.1 itojun n->next = NULL;
4570 1.1 itojun n->tail = n;
4571 1.1 itojun if (queues == NULL)
4572 1.1 itojun queues = n;
4573 1.1 itojun else {
4574 1.1 itojun queues->tail->next = n;
4575 1.1 itojun queues->tail = n;
4576 1.1 itojun }
4577 1.1 itojun }
4578 1.1 itojun if ((pf->opts & PF_OPT_VERBOSE) && (
4579 1.1 itojun (found == 1 && interface->ifname[0] == 0) ||
4580 1.1 itojun (found > 0 && interface->ifname[0] != 0))) {
4581 1.1 itojun print_queue(&pf->paltq->altq, 0,
4582 1.1 itojun &bwspec, interface->ifname[0] != 0,
4583 1.1 itojun opts);
4584 1.1 itojun if (nqueues && nqueues->tail) {
4585 1.1 itojun printf("{ ");
4586 1.1 itojun LOOP_THROUGH(struct node_queue,
4587 1.1 itojun queue, nqueues,
4588 1.1 itojun printf("%s ",
4589 1.1 itojun queue->queue);
4590 1.1 itojun );
4591 1.1 itojun printf("}");
4592 1.1 itojun }
4593 1.1 itojun printf("\n");
4594 1.1 itojun }
4595 1.1 itojun }
4596 1.1 itojun );
4597 1.1 itojun );
4598 1.1 itojun
4599 1.1 itojun FREE_LIST(struct node_queue, nqueues);
4600 1.1 itojun FREE_LIST(struct node_if, interfaces);
4601 1.1 itojun
4602 1.1 itojun if (!found) {
4603 1.1 itojun yyerror("queue %s has no parent", a->qname);
4604 1.1 itojun errs++;
4605 1.1 itojun }
4606 1.1 itojun
4607 1.1 itojun if (errs)
4608 1.1 itojun return (1);
4609 1.1 itojun else
4610 1.1 itojun return (0);
4611 1.1 itojun }
4612 1.1 itojun
4613 1.1 itojun void
4614 1.1 itojun expand_rule(struct pf_rule *r,
4615 1.1 itojun struct node_if *interfaces, struct node_host *rpool_hosts,
4616 1.1 itojun struct node_proto *protos, struct node_os *src_oses,
4617 1.1 itojun struct node_host *src_hosts, struct node_port *src_ports,
4618 1.1 itojun struct node_host *dst_hosts, struct node_port *dst_ports,
4619 1.1.1.2 yamt struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types,
4620 1.1.1.2 yamt const char *anchor_call)
4621 1.1 itojun {
4622 1.1 itojun sa_family_t af = r->af;
4623 1.1 itojun int added = 0, error = 0;
4624 1.1 itojun char ifname[IF_NAMESIZE];
4625 1.1 itojun char label[PF_RULE_LABEL_SIZE];
4626 1.1 itojun char tagname[PF_TAG_NAME_SIZE];
4627 1.1 itojun char match_tagname[PF_TAG_NAME_SIZE];
4628 1.1 itojun struct pf_pooladdr *pa;
4629 1.1 itojun struct node_host *h;
4630 1.1 itojun u_int8_t flags, flagset, keep_state;
4631 1.1 itojun
4632 1.1 itojun if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label))
4633 1.1 itojun errx(1, "expand_rule: strlcpy");
4634 1.1 itojun if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname))
4635 1.1 itojun errx(1, "expand_rule: strlcpy");
4636 1.1 itojun if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >=
4637 1.1 itojun sizeof(match_tagname))
4638 1.1 itojun errx(1, "expand_rule: strlcpy");
4639 1.1 itojun flags = r->flags;
4640 1.1 itojun flagset = r->flagset;
4641 1.1 itojun keep_state = r->keep_state;
4642 1.1 itojun
4643 1.1 itojun LOOP_THROUGH(struct node_if, interface, interfaces,
4644 1.1 itojun LOOP_THROUGH(struct node_proto, proto, protos,
4645 1.1 itojun LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types,
4646 1.1 itojun LOOP_THROUGH(struct node_host, src_host, src_hosts,
4647 1.1 itojun LOOP_THROUGH(struct node_port, src_port, src_ports,
4648 1.1 itojun LOOP_THROUGH(struct node_os, src_os, src_oses,
4649 1.1 itojun LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
4650 1.1 itojun LOOP_THROUGH(struct node_port, dst_port, dst_ports,
4651 1.1 itojun LOOP_THROUGH(struct node_uid, uid, uids,
4652 1.1 itojun LOOP_THROUGH(struct node_gid, gid, gids,
4653 1.1 itojun
4654 1.1 itojun r->af = af;
4655 1.1 itojun /* for link-local IPv6 address, interface must match up */
4656 1.1 itojun if ((r->af && src_host->af && r->af != src_host->af) ||
4657 1.1 itojun (r->af && dst_host->af && r->af != dst_host->af) ||
4658 1.1 itojun (src_host->af && dst_host->af &&
4659 1.1 itojun src_host->af != dst_host->af) ||
4660 1.1 itojun (src_host->ifindex && dst_host->ifindex &&
4661 1.1 itojun src_host->ifindex != dst_host->ifindex) ||
4662 1.1 itojun (src_host->ifindex && *interface->ifname &&
4663 1.1 itojun src_host->ifindex != if_nametoindex(interface->ifname)) ||
4664 1.1 itojun (dst_host->ifindex && *interface->ifname &&
4665 1.1 itojun dst_host->ifindex != if_nametoindex(interface->ifname)))
4666 1.1 itojun continue;
4667 1.1 itojun if (!r->af && src_host->af)
4668 1.1 itojun r->af = src_host->af;
4669 1.1 itojun else if (!r->af && dst_host->af)
4670 1.1 itojun r->af = dst_host->af;
4671 1.1 itojun
4672 1.1 itojun if (*interface->ifname)
4673 1.1.1.2 yamt strlcpy(r->ifname, interface->ifname,
4674 1.1.1.2 yamt sizeof(r->ifname));
4675 1.1 itojun else if (if_indextoname(src_host->ifindex, ifname))
4676 1.1.1.2 yamt strlcpy(r->ifname, ifname, sizeof(r->ifname));
4677 1.1 itojun else if (if_indextoname(dst_host->ifindex, ifname))
4678 1.1.1.2 yamt strlcpy(r->ifname, ifname, sizeof(r->ifname));
4679 1.1 itojun else
4680 1.1 itojun memset(r->ifname, '\0', sizeof(r->ifname));
4681 1.1 itojun
4682 1.1 itojun if (strlcpy(r->label, label, sizeof(r->label)) >=
4683 1.1 itojun sizeof(r->label))
4684 1.1 itojun errx(1, "expand_rule: strlcpy");
4685 1.1 itojun if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >=
4686 1.1 itojun sizeof(r->tagname))
4687 1.1 itojun errx(1, "expand_rule: strlcpy");
4688 1.1 itojun if (strlcpy(r->match_tagname, match_tagname,
4689 1.1 itojun sizeof(r->match_tagname)) >= sizeof(r->match_tagname))
4690 1.1 itojun errx(1, "expand_rule: strlcpy");
4691 1.1 itojun expand_label(r->label, PF_RULE_LABEL_SIZE, r->ifname, r->af,
4692 1.1 itojun src_host, src_port, dst_host, dst_port, proto->proto);
4693 1.1 itojun expand_label(r->tagname, PF_TAG_NAME_SIZE, r->ifname, r->af,
4694 1.1 itojun src_host, src_port, dst_host, dst_port, proto->proto);
4695 1.1 itojun expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r->ifname,
4696 1.1 itojun r->af, src_host, src_port, dst_host, dst_port,
4697 1.1 itojun proto->proto);
4698 1.1 itojun
4699 1.1 itojun error += check_netmask(src_host, r->af);
4700 1.1 itojun error += check_netmask(dst_host, r->af);
4701 1.1 itojun
4702 1.1 itojun r->ifnot = interface->not;
4703 1.1 itojun r->proto = proto->proto;
4704 1.1 itojun r->src.addr = src_host->addr;
4705 1.1.1.2 yamt r->src.neg = src_host->not;
4706 1.1 itojun r->src.port[0] = src_port->port[0];
4707 1.1 itojun r->src.port[1] = src_port->port[1];
4708 1.1 itojun r->src.port_op = src_port->op;
4709 1.1 itojun r->dst.addr = dst_host->addr;
4710 1.1.1.2 yamt r->dst.neg = dst_host->not;
4711 1.1 itojun r->dst.port[0] = dst_port->port[0];
4712 1.1 itojun r->dst.port[1] = dst_port->port[1];
4713 1.1 itojun r->dst.port_op = dst_port->op;
4714 1.1 itojun r->uid.op = uid->op;
4715 1.1 itojun r->uid.uid[0] = uid->uid[0];
4716 1.1 itojun r->uid.uid[1] = uid->uid[1];
4717 1.1 itojun r->gid.op = gid->op;
4718 1.1 itojun r->gid.gid[0] = gid->gid[0];
4719 1.1 itojun r->gid.gid[1] = gid->gid[1];
4720 1.1 itojun r->type = icmp_type->type;
4721 1.1 itojun r->code = icmp_type->code;
4722 1.1 itojun
4723 1.1 itojun if ((keep_state == PF_STATE_MODULATE ||
4724 1.1 itojun keep_state == PF_STATE_SYNPROXY) &&
4725 1.1 itojun r->proto && r->proto != IPPROTO_TCP)
4726 1.1 itojun r->keep_state = PF_STATE_NORMAL;
4727 1.1 itojun else
4728 1.1 itojun r->keep_state = keep_state;
4729 1.1 itojun
4730 1.1 itojun if (r->proto && r->proto != IPPROTO_TCP) {
4731 1.1 itojun r->flags = 0;
4732 1.1 itojun r->flagset = 0;
4733 1.1 itojun } else {
4734 1.1 itojun r->flags = flags;
4735 1.1 itojun r->flagset = flagset;
4736 1.1 itojun }
4737 1.1 itojun if (icmp_type->proto && r->proto != icmp_type->proto) {
4738 1.1 itojun yyerror("icmp-type mismatch");
4739 1.1 itojun error++;
4740 1.1 itojun }
4741 1.1 itojun
4742 1.1 itojun if (src_os && src_os->os) {
4743 1.1 itojun r->os_fingerprint = pfctl_get_fingerprint(src_os->os);
4744 1.1 itojun if ((pf->opts & PF_OPT_VERBOSE2) &&
4745 1.1 itojun r->os_fingerprint == PF_OSFP_NOMATCH)
4746 1.1 itojun fprintf(stderr,
4747 1.1 itojun "warning: unknown '%s' OS fingerprint\n",
4748 1.1 itojun src_os->os);
4749 1.1 itojun } else {
4750 1.1 itojun r->os_fingerprint = PF_OSFP_ANY;
4751 1.1 itojun }
4752 1.1 itojun
4753 1.1 itojun TAILQ_INIT(&r->rpool.list);
4754 1.1 itojun for (h = rpool_hosts; h != NULL; h = h->next) {
4755 1.1 itojun pa = calloc(1, sizeof(struct pf_pooladdr));
4756 1.1 itojun if (pa == NULL)
4757 1.1 itojun err(1, "expand_rule: calloc");
4758 1.1 itojun pa->addr = h->addr;
4759 1.1 itojun if (h->ifname != NULL) {
4760 1.1 itojun if (strlcpy(pa->ifname, h->ifname,
4761 1.1 itojun sizeof(pa->ifname)) >=
4762 1.1 itojun sizeof(pa->ifname))
4763 1.1 itojun errx(1, "expand_rule: strlcpy");
4764 1.1 itojun } else
4765 1.1 itojun pa->ifname[0] = 0;
4766 1.1 itojun TAILQ_INSERT_TAIL(&r->rpool.list, pa, entries);
4767 1.1 itojun }
4768 1.1 itojun
4769 1.1.1.4 martti if (rule_consistent(r, anchor_call[0]) < 0 || error)
4770 1.1 itojun yyerror("skipping rule due to errors");
4771 1.1 itojun else {
4772 1.1.1.4 martti r->nr = pf->astack[pf->asd]->match++;
4773 1.1.1.2 yamt pfctl_add_rule(pf, r, anchor_call);
4774 1.1 itojun added++;
4775 1.1 itojun }
4776 1.1 itojun
4777 1.1 itojun ))))))))));
4778 1.1 itojun
4779 1.1 itojun FREE_LIST(struct node_if, interfaces);
4780 1.1 itojun FREE_LIST(struct node_proto, protos);
4781 1.1 itojun FREE_LIST(struct node_host, src_hosts);
4782 1.1 itojun FREE_LIST(struct node_port, src_ports);
4783 1.1 itojun FREE_LIST(struct node_os, src_oses);
4784 1.1 itojun FREE_LIST(struct node_host, dst_hosts);
4785 1.1 itojun FREE_LIST(struct node_port, dst_ports);
4786 1.1 itojun FREE_LIST(struct node_uid, uids);
4787 1.1 itojun FREE_LIST(struct node_gid, gids);
4788 1.1 itojun FREE_LIST(struct node_icmp, icmp_types);
4789 1.1 itojun FREE_LIST(struct node_host, rpool_hosts);
4790 1.1 itojun
4791 1.1 itojun if (!added)
4792 1.1 itojun yyerror("rule expands to no valid combination");
4793 1.1 itojun }
4794 1.1 itojun
4795 1.1.1.3 peter int
4796 1.1.1.3 peter expand_skip_interface(struct node_if *interfaces)
4797 1.1.1.3 peter {
4798 1.1.1.3 peter int errs = 0;
4799 1.1.1.3 peter
4800 1.1.1.3 peter if (!interfaces || (!interfaces->next && !interfaces->not &&
4801 1.1.1.3 peter !strcmp(interfaces->ifname, "none"))) {
4802 1.1.1.3 peter if (pf->opts & PF_OPT_VERBOSE)
4803 1.1.1.3 peter printf("set skip on none\n");
4804 1.1.1.3 peter errs = pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0);
4805 1.1.1.3 peter return (errs);
4806 1.1.1.3 peter }
4807 1.1.1.3 peter
4808 1.1.1.3 peter if (pf->opts & PF_OPT_VERBOSE)
4809 1.1.1.3 peter printf("set skip on {");
4810 1.1.1.3 peter LOOP_THROUGH(struct node_if, interface, interfaces,
4811 1.1.1.3 peter if (pf->opts & PF_OPT_VERBOSE)
4812 1.1.1.3 peter printf(" %s", interface->ifname);
4813 1.1.1.3 peter if (interface->not) {
4814 1.1.1.3 peter yyerror("skip on ! <interface> is not supported");
4815 1.1.1.3 peter errs++;
4816 1.1.1.3 peter } else
4817 1.1.1.3 peter errs += pfctl_set_interface_flags(pf,
4818 1.1.1.3 peter interface->ifname, PFI_IFLAG_SKIP, 1);
4819 1.1.1.3 peter );
4820 1.1.1.3 peter if (pf->opts & PF_OPT_VERBOSE)
4821 1.1.1.3 peter printf(" }\n");
4822 1.1.1.3 peter
4823 1.1.1.3 peter FREE_LIST(struct node_if, interfaces);
4824 1.1.1.3 peter
4825 1.1.1.3 peter if (errs)
4826 1.1.1.3 peter return (1);
4827 1.1.1.3 peter else
4828 1.1.1.3 peter return (0);
4829 1.1.1.3 peter }
4830 1.1.1.3 peter
4831 1.1 itojun #undef FREE_LIST
4832 1.1 itojun #undef LOOP_THROUGH
4833 1.1 itojun
4834 1.1 itojun int
4835 1.1 itojun check_rulestate(int desired_state)
4836 1.1 itojun {
4837 1.1 itojun if (require_order && (rulestate > desired_state)) {
4838 1.1 itojun yyerror("Rules must be in order: options, normalization, "
4839 1.1 itojun "queueing, translation, filtering");
4840 1.1 itojun return (1);
4841 1.1 itojun }
4842 1.1 itojun rulestate = desired_state;
4843 1.1 itojun return (0);
4844 1.1 itojun }
4845 1.1 itojun
4846 1.1 itojun int
4847 1.1 itojun kw_cmp(const void *k, const void *e)
4848 1.1 itojun {
4849 1.1 itojun return (strcmp(k, ((const struct keywords *)e)->k_name));
4850 1.1 itojun }
4851 1.1 itojun
4852 1.1 itojun int
4853 1.1 itojun lookup(char *s)
4854 1.1 itojun {
4855 1.1 itojun /* this has to be sorted always */
4856 1.1 itojun static const struct keywords keywords[] = {
4857 1.1 itojun { "all", ALL},
4858 1.1 itojun { "allow-opts", ALLOWOPTS},
4859 1.1 itojun { "altq", ALTQ},
4860 1.1 itojun { "anchor", ANCHOR},
4861 1.1 itojun { "antispoof", ANTISPOOF},
4862 1.1 itojun { "any", ANY},
4863 1.1 itojun { "bandwidth", BANDWIDTH},
4864 1.1 itojun { "binat", BINAT},
4865 1.1 itojun { "binat-anchor", BINATANCHOR},
4866 1.1 itojun { "bitmask", BITMASK},
4867 1.1 itojun { "block", BLOCK},
4868 1.1 itojun { "block-policy", BLOCKPOLICY},
4869 1.1 itojun { "cbq", CBQ},
4870 1.1 itojun { "code", CODE},
4871 1.1 itojun { "crop", FRAGCROP},
4872 1.1 itojun { "debug", DEBUG},
4873 1.1 itojun { "drop", DROP},
4874 1.1 itojun { "drop-ovl", FRAGDROP},
4875 1.1 itojun { "dup-to", DUPTO},
4876 1.1 itojun { "fastroute", FASTROUTE},
4877 1.1 itojun { "file", FILENAME},
4878 1.1 itojun { "fingerprints", FINGERPRINTS},
4879 1.1 itojun { "flags", FLAGS},
4880 1.1 itojun { "floating", FLOATING},
4881 1.1.1.3 peter { "flush", FLUSH},
4882 1.1 itojun { "for", FOR},
4883 1.1 itojun { "fragment", FRAGMENT},
4884 1.1 itojun { "from", FROM},
4885 1.1 itojun { "global", GLOBAL},
4886 1.1 itojun { "group", GROUP},
4887 1.1 itojun { "hfsc", HFSC},
4888 1.1 itojun { "hostid", HOSTID},
4889 1.1 itojun { "icmp-type", ICMPTYPE},
4890 1.1 itojun { "icmp6-type", ICMP6TYPE},
4891 1.1 itojun { "if-bound", IFBOUND},
4892 1.1 itojun { "in", IN},
4893 1.1 itojun { "inet", INET},
4894 1.1 itojun { "inet6", INET6},
4895 1.1 itojun { "keep", KEEP},
4896 1.1 itojun { "label", LABEL},
4897 1.1 itojun { "limit", LIMIT},
4898 1.1 itojun { "linkshare", LINKSHARE},
4899 1.1 itojun { "load", LOAD},
4900 1.1 itojun { "log", LOG},
4901 1.1 itojun { "loginterface", LOGINTERFACE},
4902 1.1 itojun { "max", MAXIMUM},
4903 1.1 itojun { "max-mss", MAXMSS},
4904 1.1.1.3 peter { "max-src-conn", MAXSRCCONN},
4905 1.1.1.3 peter { "max-src-conn-rate", MAXSRCCONNRATE},
4906 1.1 itojun { "max-src-nodes", MAXSRCNODES},
4907 1.1 itojun { "max-src-states", MAXSRCSTATES},
4908 1.1 itojun { "min-ttl", MINTTL},
4909 1.1 itojun { "modulate", MODULATE},
4910 1.1 itojun { "nat", NAT},
4911 1.1 itojun { "nat-anchor", NATANCHOR},
4912 1.1 itojun { "no", NO},
4913 1.1 itojun { "no-df", NODF},
4914 1.1 itojun { "no-route", NOROUTE},
4915 1.1 itojun { "no-sync", NOSYNC},
4916 1.1 itojun { "on", ON},
4917 1.1 itojun { "optimization", OPTIMIZATION},
4918 1.1 itojun { "os", OS},
4919 1.1 itojun { "out", OUT},
4920 1.1.1.3 peter { "overload", OVERLOAD},
4921 1.1 itojun { "pass", PASS},
4922 1.1 itojun { "port", PORT},
4923 1.1 itojun { "priority", PRIORITY},
4924 1.1 itojun { "priq", PRIQ},
4925 1.1.1.2 yamt { "probability", PROBABILITY},
4926 1.1 itojun { "proto", PROTO},
4927 1.1 itojun { "qlimit", QLIMIT},
4928 1.1 itojun { "queue", QUEUE},
4929 1.1 itojun { "quick", QUICK},
4930 1.1 itojun { "random", RANDOM},
4931 1.1 itojun { "random-id", RANDOMID},
4932 1.1 itojun { "rdr", RDR},
4933 1.1 itojun { "rdr-anchor", RDRANCHOR},
4934 1.1 itojun { "realtime", REALTIME},
4935 1.1 itojun { "reassemble", REASSEMBLE},
4936 1.1 itojun { "reply-to", REPLYTO},
4937 1.1 itojun { "require-order", REQUIREORDER},
4938 1.1 itojun { "return", RETURN},
4939 1.1 itojun { "return-icmp", RETURNICMP},
4940 1.1 itojun { "return-icmp6", RETURNICMP6},
4941 1.1 itojun { "return-rst", RETURNRST},
4942 1.1 itojun { "round-robin", ROUNDROBIN},
4943 1.1.1.3 peter { "route", ROUTE},
4944 1.1 itojun { "route-to", ROUTETO},
4945 1.1.1.4 martti { "rtable", RTABLE},
4946 1.1 itojun { "rule", RULE},
4947 1.1.1.4 martti { "ruleset-optimization", RULESET_OPTIMIZATION},
4948 1.1 itojun { "scrub", SCRUB},
4949 1.1 itojun { "set", SET},
4950 1.1.1.3 peter { "skip", SKIP},
4951 1.1 itojun { "source-hash", SOURCEHASH},
4952 1.1 itojun { "source-track", SOURCETRACK},
4953 1.1 itojun { "state", STATE},
4954 1.1 itojun { "state-policy", STATEPOLICY},
4955 1.1 itojun { "static-port", STATICPORT},
4956 1.1 itojun { "sticky-address", STICKYADDRESS},
4957 1.1 itojun { "synproxy", SYNPROXY},
4958 1.1 itojun { "table", TABLE},
4959 1.1 itojun { "tag", TAG},
4960 1.1 itojun { "tagged", TAGGED},
4961 1.1 itojun { "tbrsize", TBRSIZE},
4962 1.1 itojun { "timeout", TIMEOUT},
4963 1.1 itojun { "to", TO},
4964 1.1 itojun { "tos", TOS},
4965 1.1 itojun { "ttl", TTL},
4966 1.1 itojun { "upperlimit", UPPERLIMIT},
4967 1.1.1.4 martti { "urpf-failed", URPFFAILED},
4968 1.1 itojun { "user", USER},
4969 1.1 itojun };
4970 1.1 itojun const struct keywords *p;
4971 1.1 itojun
4972 1.1 itojun p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
4973 1.1 itojun sizeof(keywords[0]), kw_cmp);
4974 1.1 itojun
4975 1.1 itojun if (p) {
4976 1.1 itojun if (debug > 1)
4977 1.1 itojun fprintf(stderr, "%s: %d\n", s, p->k_val);
4978 1.1 itojun return (p->k_val);
4979 1.1 itojun } else {
4980 1.1 itojun if (debug > 1)
4981 1.1 itojun fprintf(stderr, "string: %s\n", s);
4982 1.1 itojun return (STRING);
4983 1.1 itojun }
4984 1.1 itojun }
4985 1.1 itojun
4986 1.1 itojun #define MAXPUSHBACK 128
4987 1.1 itojun
4988 1.1 itojun char *parsebuf;
4989 1.1 itojun int parseindex;
4990 1.1 itojun char pushback_buffer[MAXPUSHBACK];
4991 1.1 itojun int pushback_index = 0;
4992 1.1 itojun
4993 1.1 itojun int
4994 1.1 itojun lgetc(FILE *f)
4995 1.1 itojun {
4996 1.1 itojun int c, next;
4997 1.1 itojun
4998 1.1 itojun if (parsebuf) {
4999 1.1 itojun /* Read character from the parsebuffer instead of input. */
5000 1.1 itojun if (parseindex >= 0) {
5001 1.1 itojun c = parsebuf[parseindex++];
5002 1.1 itojun if (c != '\0')
5003 1.1 itojun return (c);
5004 1.1 itojun parsebuf = NULL;
5005 1.1 itojun } else
5006 1.1 itojun parseindex++;
5007 1.1 itojun }
5008 1.1 itojun
5009 1.1 itojun if (pushback_index)
5010 1.1 itojun return (pushback_buffer[--pushback_index]);
5011 1.1 itojun
5012 1.1 itojun while ((c = getc(f)) == '\\') {
5013 1.1 itojun next = getc(f);
5014 1.1 itojun if (next != '\n') {
5015 1.1.1.4 martti c = next;
5016 1.1 itojun break;
5017 1.1 itojun }
5018 1.1 itojun yylval.lineno = lineno;
5019 1.1 itojun lineno++;
5020 1.1 itojun }
5021 1.1 itojun if (c == '\t' || c == ' ') {
5022 1.1 itojun /* Compress blanks to a single space. */
5023 1.1 itojun do {
5024 1.1 itojun c = getc(f);
5025 1.1 itojun } while (c == '\t' || c == ' ');
5026 1.1 itojun ungetc(c, f);
5027 1.1 itojun c = ' ';
5028 1.1 itojun }
5029 1.1 itojun
5030 1.1 itojun return (c);
5031 1.1 itojun }
5032 1.1 itojun
5033 1.1 itojun int
5034 1.1 itojun lungetc(int c)
5035 1.1 itojun {
5036 1.1 itojun if (c == EOF)
5037 1.1 itojun return (EOF);
5038 1.1 itojun if (parsebuf) {
5039 1.1 itojun parseindex--;
5040 1.1 itojun if (parseindex >= 0)
5041 1.1 itojun return (c);
5042 1.1 itojun }
5043 1.1 itojun if (pushback_index < MAXPUSHBACK-1)
5044 1.1 itojun return (pushback_buffer[pushback_index++] = c);
5045 1.1 itojun else
5046 1.1 itojun return (EOF);
5047 1.1 itojun }
5048 1.1 itojun
5049 1.1 itojun int
5050 1.1 itojun findeol(void)
5051 1.1 itojun {
5052 1.1 itojun int c;
5053 1.1 itojun
5054 1.1 itojun parsebuf = NULL;
5055 1.1 itojun pushback_index = 0;
5056 1.1 itojun
5057 1.1 itojun /* skip to either EOF or the first real EOL */
5058 1.1 itojun while (1) {
5059 1.1 itojun c = lgetc(fin);
5060 1.1 itojun if (c == '\n') {
5061 1.1 itojun lineno++;
5062 1.1 itojun break;
5063 1.1 itojun }
5064 1.1 itojun if (c == EOF)
5065 1.1 itojun break;
5066 1.1 itojun }
5067 1.1 itojun return (ERROR);
5068 1.1 itojun }
5069 1.1 itojun
5070 1.1 itojun int
5071 1.1 itojun yylex(void)
5072 1.1 itojun {
5073 1.1 itojun char buf[8096];
5074 1.1 itojun char *p, *val;
5075 1.1 itojun int endc, c, next;
5076 1.1 itojun int token;
5077 1.1 itojun
5078 1.1 itojun top:
5079 1.1 itojun p = buf;
5080 1.1 itojun while ((c = lgetc(fin)) == ' ')
5081 1.1 itojun ; /* nothing */
5082 1.1 itojun
5083 1.1 itojun yylval.lineno = lineno;
5084 1.1 itojun if (c == '#')
5085 1.1 itojun while ((c = lgetc(fin)) != '\n' && c != EOF)
5086 1.1 itojun ; /* nothing */
5087 1.1 itojun if (c == '$' && parsebuf == NULL) {
5088 1.1 itojun while (1) {
5089 1.1 itojun if ((c = lgetc(fin)) == EOF)
5090 1.1 itojun return (0);
5091 1.1 itojun
5092 1.1 itojun if (p + 1 >= buf + sizeof(buf) - 1) {
5093 1.1 itojun yyerror("string too long");
5094 1.1 itojun return (findeol());
5095 1.1 itojun }
5096 1.1 itojun if (isalnum(c) || c == '_') {
5097 1.1 itojun *p++ = (char)c;
5098 1.1 itojun continue;
5099 1.1 itojun }
5100 1.1 itojun *p = '\0';
5101 1.1 itojun lungetc(c);
5102 1.1 itojun break;
5103 1.1 itojun }
5104 1.1 itojun val = symget(buf);
5105 1.1 itojun if (val == NULL) {
5106 1.1 itojun yyerror("macro '%s' not defined", buf);
5107 1.1 itojun return (findeol());
5108 1.1 itojun }
5109 1.1 itojun parsebuf = val;
5110 1.1 itojun parseindex = 0;
5111 1.1 itojun goto top;
5112 1.1 itojun }
5113 1.1 itojun
5114 1.1 itojun switch (c) {
5115 1.1 itojun case '\'':
5116 1.1 itojun case '"':
5117 1.1 itojun endc = c;
5118 1.1 itojun while (1) {
5119 1.1 itojun if ((c = lgetc(fin)) == EOF)
5120 1.1 itojun return (0);
5121 1.1 itojun if (c == endc) {
5122 1.1 itojun *p = '\0';
5123 1.1 itojun break;
5124 1.1 itojun }
5125 1.1 itojun if (c == '\n') {
5126 1.1 itojun lineno++;
5127 1.1 itojun continue;
5128 1.1 itojun }
5129 1.1 itojun if (p + 1 >= buf + sizeof(buf) - 1) {
5130 1.1 itojun yyerror("string too long");
5131 1.1 itojun return (findeol());
5132 1.1 itojun }
5133 1.1 itojun *p++ = (char)c;
5134 1.1 itojun }
5135 1.1 itojun yylval.v.string = strdup(buf);
5136 1.1 itojun if (yylval.v.string == NULL)
5137 1.1 itojun err(1, "yylex: strdup");
5138 1.1 itojun return (STRING);
5139 1.1 itojun case '<':
5140 1.1 itojun next = lgetc(fin);
5141 1.1 itojun if (next == '>') {
5142 1.1 itojun yylval.v.i = PF_OP_XRG;
5143 1.1 itojun return (PORTBINARY);
5144 1.1 itojun }
5145 1.1 itojun lungetc(next);
5146 1.1 itojun break;
5147 1.1 itojun case '>':
5148 1.1 itojun next = lgetc(fin);
5149 1.1 itojun if (next == '<') {
5150 1.1 itojun yylval.v.i = PF_OP_IRG;
5151 1.1 itojun return (PORTBINARY);
5152 1.1 itojun }
5153 1.1 itojun lungetc(next);
5154 1.1 itojun break;
5155 1.1 itojun case '-':
5156 1.1 itojun next = lgetc(fin);
5157 1.1 itojun if (next == '>')
5158 1.1 itojun return (ARROW);
5159 1.1 itojun lungetc(next);
5160 1.1 itojun break;
5161 1.1 itojun }
5162 1.1 itojun
5163 1.1 itojun #define allowed_in_string(x) \
5164 1.1 itojun (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
5165 1.1 itojun x != '{' && x != '}' && x != '<' && x != '>' && \
5166 1.1 itojun x != '!' && x != '=' && x != '/' && x != '#' && \
5167 1.1 itojun x != ','))
5168 1.1 itojun
5169 1.1 itojun if (isalnum(c) || c == ':' || c == '_') {
5170 1.1 itojun do {
5171 1.1 itojun *p++ = c;
5172 1.1 itojun if ((unsigned)(p-buf) >= sizeof(buf)) {
5173 1.1 itojun yyerror("string too long");
5174 1.1 itojun return (findeol());
5175 1.1 itojun }
5176 1.1 itojun } while ((c = lgetc(fin)) != EOF && (allowed_in_string(c)));
5177 1.1 itojun lungetc(c);
5178 1.1 itojun *p = '\0';
5179 1.1 itojun if ((token = lookup(buf)) == STRING)
5180 1.1 itojun if ((yylval.v.string = strdup(buf)) == NULL)
5181 1.1 itojun err(1, "yylex: strdup");
5182 1.1 itojun return (token);
5183 1.1 itojun }
5184 1.1 itojun if (c == '\n') {
5185 1.1 itojun yylval.lineno = lineno;
5186 1.1 itojun lineno++;
5187 1.1 itojun }
5188 1.1 itojun if (c == EOF)
5189 1.1 itojun return (0);
5190 1.1 itojun return (c);
5191 1.1 itojun }
5192 1.1 itojun
5193 1.1 itojun int
5194 1.1 itojun parse_rules(FILE *input, struct pfctl *xpf)
5195 1.1 itojun {
5196 1.1 itojun struct sym *sym, *next;
5197 1.1 itojun
5198 1.1 itojun fin = input;
5199 1.1 itojun pf = xpf;
5200 1.1 itojun lineno = 1;
5201 1.1 itojun errors = 0;
5202 1.1 itojun rulestate = PFCTL_STATE_NONE;
5203 1.1 itojun returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
5204 1.1 itojun returnicmp6default =
5205 1.1 itojun (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
5206 1.1 itojun blockpolicy = PFRULE_DROP;
5207 1.1 itojun require_order = 1;
5208 1.1 itojun
5209 1.1 itojun yyparse();
5210 1.1 itojun
5211 1.1 itojun /* Free macros and check which have not been used. */
5212 1.1 itojun for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
5213 1.1 itojun next = TAILQ_NEXT(sym, entries);
5214 1.1 itojun if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used)
5215 1.1 itojun fprintf(stderr, "warning: macro '%s' not "
5216 1.1 itojun "used\n", sym->nam);
5217 1.1 itojun free(sym->nam);
5218 1.1 itojun free(sym->val);
5219 1.1 itojun TAILQ_REMOVE(&symhead, sym, entries);
5220 1.1 itojun free(sym);
5221 1.1 itojun }
5222 1.1 itojun
5223 1.1 itojun return (errors ? -1 : 0);
5224 1.1 itojun }
5225 1.1 itojun
5226 1.1 itojun /*
5227 1.1 itojun * Over-designed efficiency is a French and German concept, so how about
5228 1.1 itojun * we wait until they discover this ugliness and make it all fancy.
5229 1.1 itojun */
5230 1.1 itojun int
5231 1.1 itojun symset(const char *nam, const char *val, int persist)
5232 1.1 itojun {
5233 1.1 itojun struct sym *sym;
5234 1.1 itojun
5235 1.1 itojun for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
5236 1.1 itojun sym = TAILQ_NEXT(sym, entries))
5237 1.1 itojun ; /* nothing */
5238 1.1 itojun
5239 1.1 itojun if (sym != NULL) {
5240 1.1 itojun if (sym->persist == 1)
5241 1.1 itojun return (0);
5242 1.1 itojun else {
5243 1.1 itojun free(sym->nam);
5244 1.1 itojun free(sym->val);
5245 1.1 itojun TAILQ_REMOVE(&symhead, sym, entries);
5246 1.1 itojun free(sym);
5247 1.1 itojun }
5248 1.1 itojun }
5249 1.1 itojun if ((sym = calloc(1, sizeof(*sym))) == NULL)
5250 1.1 itojun return (-1);
5251 1.1 itojun
5252 1.1 itojun sym->nam = strdup(nam);
5253 1.1 itojun if (sym->nam == NULL) {
5254 1.1 itojun free(sym);
5255 1.1 itojun return (-1);
5256 1.1 itojun }
5257 1.1 itojun sym->val = strdup(val);
5258 1.1 itojun if (sym->val == NULL) {
5259 1.1 itojun free(sym->nam);
5260 1.1 itojun free(sym);
5261 1.1 itojun return (-1);
5262 1.1 itojun }
5263 1.1 itojun sym->used = 0;
5264 1.1 itojun sym->persist = persist;
5265 1.1 itojun TAILQ_INSERT_TAIL(&symhead, sym, entries);
5266 1.1 itojun return (0);
5267 1.1 itojun }
5268 1.1 itojun
5269 1.1 itojun int
5270 1.1 itojun pfctl_cmdline_symset(char *s)
5271 1.1 itojun {
5272 1.1 itojun char *sym, *val;
5273 1.1 itojun int ret;
5274 1.1 itojun
5275 1.1 itojun if ((val = strrchr(s, '=')) == NULL)
5276 1.1 itojun return (-1);
5277 1.1 itojun
5278 1.1 itojun if ((sym = malloc(strlen(s) - strlen(val) + 1)) == NULL)
5279 1.1 itojun err(1, "pfctl_cmdline_symset: malloc");
5280 1.1 itojun
5281 1.1 itojun strlcpy(sym, s, strlen(s) - strlen(val) + 1);
5282 1.1 itojun
5283 1.1 itojun ret = symset(sym, val + 1, 1);
5284 1.1 itojun free(sym);
5285 1.1 itojun
5286 1.1 itojun return (ret);
5287 1.1 itojun }
5288 1.1 itojun
5289 1.1 itojun char *
5290 1.1 itojun symget(const char *nam)
5291 1.1 itojun {
5292 1.1 itojun struct sym *sym;
5293 1.1 itojun
5294 1.1 itojun TAILQ_FOREACH(sym, &symhead, entries)
5295 1.1 itojun if (strcmp(nam, sym->nam) == 0) {
5296 1.1 itojun sym->used = 1;
5297 1.1 itojun return (sym->val);
5298 1.1 itojun }
5299 1.1 itojun return (NULL);
5300 1.1 itojun }
5301 1.1 itojun
5302 1.1 itojun void
5303 1.1.1.4 martti mv_rules(struct pf_ruleset *src, struct pf_ruleset *dst)
5304 1.1 itojun {
5305 1.1.1.4 martti int i;
5306 1.1.1.4 martti struct pf_rule *r;
5307 1.1 itojun
5308 1.1.1.4 martti for (i = 0; i < PF_RULESET_MAX; ++i) {
5309 1.1.1.4 martti while ((r = TAILQ_FIRST(src->rules[i].active.ptr))
5310 1.1.1.4 martti != NULL) {
5311 1.1.1.4 martti TAILQ_REMOVE(src->rules[i].active.ptr, r, entries);
5312 1.1.1.4 martti TAILQ_INSERT_TAIL(dst->rules[i].active.ptr, r, entries);
5313 1.1.1.4 martti dst->anchor->match++;
5314 1.1.1.4 martti }
5315 1.1.1.4 martti src->anchor->match = 0;
5316 1.1.1.4 martti while ((r = TAILQ_FIRST(src->rules[i].inactive.ptr))
5317 1.1.1.4 martti != NULL) {
5318 1.1.1.4 martti TAILQ_REMOVE(src->rules[i].inactive.ptr, r, entries);
5319 1.1.1.4 martti TAILQ_INSERT_TAIL(dst->rules[i].inactive.ptr,
5320 1.1.1.4 martti r, entries);
5321 1.1.1.4 martti }
5322 1.1.1.4 martti }
5323 1.1.1.4 martti }
5324 1.1.1.4 martti
5325 1.1.1.4 martti void
5326 1.1.1.4 martti decide_address_family(struct node_host *n, sa_family_t *af)
5327 1.1.1.4 martti {
5328 1.1.1.4 martti if (*af != 0 || n == NULL)
5329 1.1.1.4 martti return;
5330 1.1.1.4 martti *af = n->af;
5331 1.1.1.4 martti while ((n = n->next) != NULL) {
5332 1.1.1.4 martti if (n->af != *af) {
5333 1.1.1.4 martti *af = 0;
5334 1.1.1.4 martti return;
5335 1.1 itojun }
5336 1.1 itojun }
5337 1.1 itojun }
5338 1.1 itojun
5339 1.1 itojun void
5340 1.1 itojun remove_invalid_hosts(struct node_host **nh, sa_family_t *af)
5341 1.1 itojun {
5342 1.1 itojun struct node_host *n = *nh, *prev = NULL;
5343 1.1 itojun
5344 1.1 itojun while (n != NULL) {
5345 1.1 itojun if (*af && n->af && n->af != *af) {
5346 1.1 itojun /* unlink and free n */
5347 1.1 itojun struct node_host *next = n->next;
5348 1.1 itojun
5349 1.1 itojun /* adjust tail pointer */
5350 1.1 itojun if (n == (*nh)->tail)
5351 1.1 itojun (*nh)->tail = prev;
5352 1.1 itojun /* adjust previous node's next pointer */
5353 1.1 itojun if (prev == NULL)
5354 1.1 itojun *nh = next;
5355 1.1 itojun else
5356 1.1 itojun prev->next = next;
5357 1.1 itojun /* free node */
5358 1.1 itojun if (n->ifname != NULL)
5359 1.1 itojun free(n->ifname);
5360 1.1 itojun free(n);
5361 1.1 itojun n = next;
5362 1.1 itojun } else {
5363 1.1 itojun if (n->af && !*af)
5364 1.1 itojun *af = n->af;
5365 1.1 itojun prev = n;
5366 1.1 itojun n = n->next;
5367 1.1 itojun }
5368 1.1 itojun }
5369 1.1 itojun }
5370 1.1 itojun
5371 1.1 itojun int
5372 1.1 itojun invalid_redirect(struct node_host *nh, sa_family_t af)
5373 1.1 itojun {
5374 1.1 itojun if (!af) {
5375 1.1 itojun struct node_host *n;
5376 1.1 itojun
5377 1.1 itojun /* tables and dyniftl are ok without an address family */
5378 1.1 itojun for (n = nh; n != NULL; n = n->next) {
5379 1.1 itojun if (n->addr.type != PF_ADDR_TABLE &&
5380 1.1 itojun n->addr.type != PF_ADDR_DYNIFTL) {
5381 1.1 itojun yyerror("address family not given and "
5382 1.1 itojun "translation address expands to multiple "
5383 1.1 itojun "address families");
5384 1.1 itojun return (1);
5385 1.1 itojun }
5386 1.1 itojun }
5387 1.1 itojun }
5388 1.1 itojun if (nh == NULL) {
5389 1.1 itojun yyerror("no translation address with matching address family "
5390 1.1 itojun "found.");
5391 1.1 itojun return (1);
5392 1.1 itojun }
5393 1.1 itojun return (0);
5394 1.1 itojun }
5395 1.1 itojun
5396 1.1 itojun int
5397 1.1 itojun atoul(char *s, u_long *ulvalp)
5398 1.1 itojun {
5399 1.1 itojun u_long ulval;
5400 1.1 itojun char *ep;
5401 1.1 itojun
5402 1.1 itojun errno = 0;
5403 1.1 itojun ulval = strtoul(s, &ep, 0);
5404 1.1 itojun if (s[0] == '\0' || *ep != '\0')
5405 1.1 itojun return (-1);
5406 1.1 itojun if (errno == ERANGE && ulval == ULONG_MAX)
5407 1.1 itojun return (-1);
5408 1.1 itojun *ulvalp = ulval;
5409 1.1 itojun return (0);
5410 1.1 itojun }
5411 1.1 itojun
5412 1.1 itojun int
5413 1.1 itojun getservice(char *n)
5414 1.1 itojun {
5415 1.1 itojun struct servent *s;
5416 1.1 itojun u_long ulval;
5417 1.1 itojun
5418 1.1 itojun if (atoul(n, &ulval) == 0) {
5419 1.1 itojun if (ulval > 65535) {
5420 1.1.1.3 peter yyerror("illegal port value %lu", ulval);
5421 1.1 itojun return (-1);
5422 1.1 itojun }
5423 1.1 itojun return (htons(ulval));
5424 1.1 itojun } else {
5425 1.1 itojun s = getservbyname(n, "tcp");
5426 1.1 itojun if (s == NULL)
5427 1.1 itojun s = getservbyname(n, "udp");
5428 1.1 itojun if (s == NULL) {
5429 1.1 itojun yyerror("unknown port %s", n);
5430 1.1 itojun return (-1);
5431 1.1 itojun }
5432 1.1 itojun return (s->s_port);
5433 1.1 itojun }
5434 1.1 itojun }
5435 1.1 itojun
5436 1.1 itojun int
5437 1.1 itojun rule_label(struct pf_rule *r, char *s)
5438 1.1 itojun {
5439 1.1 itojun if (s) {
5440 1.1 itojun if (strlcpy(r->label, s, sizeof(r->label)) >=
5441 1.1 itojun sizeof(r->label)) {
5442 1.1 itojun yyerror("rule label too long (max %d chars)",
5443 1.1 itojun sizeof(r->label)-1);
5444 1.1 itojun return (-1);
5445 1.1 itojun }
5446 1.1 itojun }
5447 1.1 itojun return (0);
5448 1.1 itojun }
5449 1.1 itojun
5450 1.1 itojun u_int16_t
5451 1.1 itojun parseicmpspec(char *w, sa_family_t af)
5452 1.1 itojun {
5453 1.1 itojun const struct icmpcodeent *p;
5454 1.1 itojun u_long ulval;
5455 1.1 itojun u_int8_t icmptype;
5456 1.1 itojun
5457 1.1 itojun if (af == AF_INET)
5458 1.1 itojun icmptype = returnicmpdefault >> 8;
5459 1.1 itojun else
5460 1.1 itojun icmptype = returnicmp6default >> 8;
5461 1.1 itojun
5462 1.1 itojun if (atoul(w, &ulval) == -1) {
5463 1.1 itojun if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) {
5464 1.1 itojun yyerror("unknown icmp code %s", w);
5465 1.1 itojun return (0);
5466 1.1 itojun }
5467 1.1 itojun ulval = p->code;
5468 1.1 itojun }
5469 1.1 itojun if (ulval > 255) {
5470 1.1.1.3 peter yyerror("invalid icmp code %lu", ulval);
5471 1.1 itojun return (0);
5472 1.1 itojun }
5473 1.1 itojun return (icmptype << 8 | ulval);
5474 1.1 itojun }
5475 1.1 itojun
5476 1.1 itojun int
5477 1.1.1.4 martti pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans)
5478 1.1 itojun {
5479 1.1 itojun struct loadanchors *la;
5480 1.1.1.4 martti FILE *fin;
5481 1.1 itojun
5482 1.1 itojun TAILQ_FOREACH(la, &loadanchorshead, entries) {
5483 1.1.1.4 martti if (pf->opts & PF_OPT_VERBOSE)
5484 1.1.1.2 yamt fprintf(stderr, "\nLoading anchor %s from %s\n",
5485 1.1.1.2 yamt la->anchorname, la->filename);
5486 1.1.1.4 martti if ((fin = pfctl_fopen(la->filename, "r")) == NULL) {
5487 1.1.1.4 martti warn("%s", la->filename);
5488 1.1.1.4 martti continue;
5489 1.1.1.4 martti }
5490 1.1.1.4 martti if (pfctl_rules(dev, la->filename, fin, pf->opts, pf->optimize,
5491 1.1.1.4 martti la->anchorname, trans) == -1)
5492 1.1 itojun return (-1);
5493 1.1 itojun }
5494 1.1 itojun
5495 1.1 itojun return (0);
5496 1.1 itojun }
5497