13b3a8eb9SGleb Smirnoff /* $OpenBSD: parse.y,v 1.554 2008/10/17 12:59:53 henning Exp $ */
23b3a8eb9SGleb Smirnoff
31de7b4b8SPedro F. Giffuni /*-
41de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause
51de7b4b8SPedro F. Giffuni *
63b3a8eb9SGleb Smirnoff * Copyright (c) 2001 Markus Friedl. All rights reserved.
73b3a8eb9SGleb Smirnoff * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
83b3a8eb9SGleb Smirnoff * Copyright (c) 2001 Theo de Raadt. All rights reserved.
93b3a8eb9SGleb Smirnoff * Copyright (c) 2002,2003 Henning Brauer. All rights reserved.
103b3a8eb9SGleb Smirnoff *
113b3a8eb9SGleb Smirnoff * Redistribution and use in source and binary forms, with or without
123b3a8eb9SGleb Smirnoff * modification, are permitted provided that the following conditions
133b3a8eb9SGleb Smirnoff * are met:
143b3a8eb9SGleb Smirnoff * 1. Redistributions of source code must retain the above copyright
153b3a8eb9SGleb Smirnoff * notice, this list of conditions and the following disclaimer.
163b3a8eb9SGleb Smirnoff * 2. Redistributions in binary form must reproduce the above copyright
173b3a8eb9SGleb Smirnoff * notice, this list of conditions and the following disclaimer in the
183b3a8eb9SGleb Smirnoff * documentation and/or other materials provided with the distribution.
193b3a8eb9SGleb Smirnoff *
203b3a8eb9SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
213b3a8eb9SGleb Smirnoff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
223b3a8eb9SGleb Smirnoff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
233b3a8eb9SGleb Smirnoff * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
243b3a8eb9SGleb Smirnoff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
253b3a8eb9SGleb Smirnoff * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
263b3a8eb9SGleb Smirnoff * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
273b3a8eb9SGleb Smirnoff * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
283b3a8eb9SGleb Smirnoff * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
293b3a8eb9SGleb Smirnoff * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
303b3a8eb9SGleb Smirnoff */
313b3a8eb9SGleb Smirnoff %{
323b3a8eb9SGleb Smirnoff #include <sys/cdefs.h>
33249cc75fSPatrick Kelsey #define PFIOC_USE_LATEST
34249cc75fSPatrick Kelsey
353b3a8eb9SGleb Smirnoff #include <sys/types.h>
363b3a8eb9SGleb Smirnoff #include <sys/socket.h>
373b3a8eb9SGleb Smirnoff #include <sys/stat.h>
383b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__
393b3a8eb9SGleb Smirnoff #include <sys/sysctl.h>
403b3a8eb9SGleb Smirnoff #endif
413b3a8eb9SGleb Smirnoff #include <net/if.h>
423b3a8eb9SGleb Smirnoff #include <netinet/in.h>
433b3a8eb9SGleb Smirnoff #include <netinet/in_systm.h>
443b3a8eb9SGleb Smirnoff #include <netinet/ip.h>
453b3a8eb9SGleb Smirnoff #include <netinet/ip_icmp.h>
463b3a8eb9SGleb Smirnoff #include <netinet/icmp6.h>
473b3a8eb9SGleb Smirnoff #include <net/pfvar.h>
483b3a8eb9SGleb Smirnoff #include <arpa/inet.h>
49772e66a6SGleb Smirnoff #include <net/altq/altq.h>
50772e66a6SGleb Smirnoff #include <net/altq/altq_cbq.h>
510a70aaf8SLuiz Otavio O Souza #include <net/altq/altq_codel.h>
52772e66a6SGleb Smirnoff #include <net/altq/altq_priq.h>
53772e66a6SGleb Smirnoff #include <net/altq/altq_hfsc.h>
54a5b789f6SErmal Luçi #include <net/altq/altq_fairq.h>
553b3a8eb9SGleb Smirnoff
566fcc8e04SKristof Provost #include <assert.h>
573b3a8eb9SGleb Smirnoff #include <stdio.h>
583b3a8eb9SGleb Smirnoff #include <unistd.h>
593b3a8eb9SGleb Smirnoff #include <stdlib.h>
603b3a8eb9SGleb Smirnoff #include <netdb.h>
613b3a8eb9SGleb Smirnoff #include <stdarg.h>
623b3a8eb9SGleb Smirnoff #include <errno.h>
633b3a8eb9SGleb Smirnoff #include <string.h>
643b3a8eb9SGleb Smirnoff #include <ctype.h>
653b3a8eb9SGleb Smirnoff #include <math.h>
663b3a8eb9SGleb Smirnoff #include <err.h>
673b3a8eb9SGleb Smirnoff #include <limits.h>
683b3a8eb9SGleb Smirnoff #include <pwd.h>
693b3a8eb9SGleb Smirnoff #include <grp.h>
703b3a8eb9SGleb Smirnoff #include <md5.h>
713b3a8eb9SGleb Smirnoff
723b3a8eb9SGleb Smirnoff #include "pfctl_parser.h"
733b3a8eb9SGleb Smirnoff #include "pfctl.h"
743b3a8eb9SGleb Smirnoff
753b3a8eb9SGleb Smirnoff static struct pfctl *pf = NULL;
763b3a8eb9SGleb Smirnoff static int debug = 0;
773b3a8eb9SGleb Smirnoff static int rulestate = 0;
783b3a8eb9SGleb Smirnoff static u_int16_t returnicmpdefault =
793b3a8eb9SGleb Smirnoff (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
803b3a8eb9SGleb Smirnoff static u_int16_t returnicmp6default =
813b3a8eb9SGleb Smirnoff (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
823b3a8eb9SGleb Smirnoff static int blockpolicy = PFRULE_DROP;
83150182e3SKristof Provost static int failpolicy = PFRULE_DROP;
843b3a8eb9SGleb Smirnoff static int require_order = 1;
853b3a8eb9SGleb Smirnoff static int default_statelock;
863b3a8eb9SGleb Smirnoff
8713cfafabSKristof Provost static TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
883b3a8eb9SGleb Smirnoff static struct file {
893b3a8eb9SGleb Smirnoff TAILQ_ENTRY(file) entry;
903b3a8eb9SGleb Smirnoff FILE *stream;
913b3a8eb9SGleb Smirnoff char *name;
923b3a8eb9SGleb Smirnoff int lineno;
933b3a8eb9SGleb Smirnoff int errors;
943b3a8eb9SGleb Smirnoff } *file;
953b3a8eb9SGleb Smirnoff struct file *pushfile(const char *, int);
963b3a8eb9SGleb Smirnoff int popfile(void);
973b3a8eb9SGleb Smirnoff int check_file_secrecy(int, const char *);
983b3a8eb9SGleb Smirnoff int yyparse(void);
993b3a8eb9SGleb Smirnoff int yylex(void);
1003b3a8eb9SGleb Smirnoff int yyerror(const char *, ...);
1013b3a8eb9SGleb Smirnoff int kw_cmp(const void *, const void *);
1023b3a8eb9SGleb Smirnoff int lookup(char *);
1033b3a8eb9SGleb Smirnoff int lgetc(int);
1043b3a8eb9SGleb Smirnoff int lungetc(int);
1053b3a8eb9SGleb Smirnoff int findeol(void);
1063b3a8eb9SGleb Smirnoff
10713cfafabSKristof Provost static TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
1083b3a8eb9SGleb Smirnoff struct sym {
1093b3a8eb9SGleb Smirnoff TAILQ_ENTRY(sym) entry;
1103b3a8eb9SGleb Smirnoff int used;
1113b3a8eb9SGleb Smirnoff int persist;
1123b3a8eb9SGleb Smirnoff char *nam;
1133b3a8eb9SGleb Smirnoff char *val;
1143b3a8eb9SGleb Smirnoff };
1153b3a8eb9SGleb Smirnoff int symset(const char *, const char *, int);
1163b3a8eb9SGleb Smirnoff char *symget(const char *);
1173b3a8eb9SGleb Smirnoff
1183b3a8eb9SGleb Smirnoff int atoul(char *, u_long *);
1193b3a8eb9SGleb Smirnoff
1203b3a8eb9SGleb Smirnoff enum {
1213b3a8eb9SGleb Smirnoff PFCTL_STATE_NONE,
1223b3a8eb9SGleb Smirnoff PFCTL_STATE_OPTION,
1232b29ceb8SKristof Provost PFCTL_STATE_ETHER,
1243b3a8eb9SGleb Smirnoff PFCTL_STATE_SCRUB,
1253b3a8eb9SGleb Smirnoff PFCTL_STATE_QUEUE,
1263b3a8eb9SGleb Smirnoff PFCTL_STATE_NAT,
1273b3a8eb9SGleb Smirnoff PFCTL_STATE_FILTER
1283b3a8eb9SGleb Smirnoff };
1293b3a8eb9SGleb Smirnoff
1302b29ceb8SKristof Provost struct node_etherproto {
1312b29ceb8SKristof Provost u_int16_t proto;
1322b29ceb8SKristof Provost struct node_etherproto *next;
1332b29ceb8SKristof Provost struct node_etherproto *tail;
1342b29ceb8SKristof Provost };
1352b29ceb8SKristof Provost
1363b3a8eb9SGleb Smirnoff struct node_proto {
1373b3a8eb9SGleb Smirnoff u_int8_t proto;
1383b3a8eb9SGleb Smirnoff struct node_proto *next;
1393b3a8eb9SGleb Smirnoff struct node_proto *tail;
1403b3a8eb9SGleb Smirnoff };
1413b3a8eb9SGleb Smirnoff
1423b3a8eb9SGleb Smirnoff struct node_port {
1433b3a8eb9SGleb Smirnoff u_int16_t port[2];
1443b3a8eb9SGleb Smirnoff u_int8_t op;
1453b3a8eb9SGleb Smirnoff struct node_port *next;
1463b3a8eb9SGleb Smirnoff struct node_port *tail;
1473b3a8eb9SGleb Smirnoff };
1483b3a8eb9SGleb Smirnoff
1493b3a8eb9SGleb Smirnoff struct node_uid {
1503b3a8eb9SGleb Smirnoff uid_t uid[2];
1513b3a8eb9SGleb Smirnoff u_int8_t op;
1523b3a8eb9SGleb Smirnoff struct node_uid *next;
1533b3a8eb9SGleb Smirnoff struct node_uid *tail;
1543b3a8eb9SGleb Smirnoff };
1553b3a8eb9SGleb Smirnoff
1563b3a8eb9SGleb Smirnoff struct node_gid {
1573b3a8eb9SGleb Smirnoff gid_t gid[2];
1583b3a8eb9SGleb Smirnoff u_int8_t op;
1593b3a8eb9SGleb Smirnoff struct node_gid *next;
1603b3a8eb9SGleb Smirnoff struct node_gid *tail;
1613b3a8eb9SGleb Smirnoff };
1623b3a8eb9SGleb Smirnoff
1633b3a8eb9SGleb Smirnoff struct node_icmp {
1643b3a8eb9SGleb Smirnoff u_int8_t code;
1653b3a8eb9SGleb Smirnoff u_int8_t type;
1663b3a8eb9SGleb Smirnoff u_int8_t proto;
1673b3a8eb9SGleb Smirnoff struct node_icmp *next;
1683b3a8eb9SGleb Smirnoff struct node_icmp *tail;
1693b3a8eb9SGleb Smirnoff };
1703b3a8eb9SGleb Smirnoff
1713b3a8eb9SGleb Smirnoff enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK,
1723b3a8eb9SGleb Smirnoff PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN,
1733b3a8eb9SGleb Smirnoff PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES,
1743b3a8eb9SGleb Smirnoff PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK,
175baf9b6d0SKristof Provost PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY,
176e4f2733dSKristof Provost PF_STATE_OPT_PFLOW, PF_STATE_OPT_ALLOW_RELATED };
1773b3a8eb9SGleb Smirnoff
1783b3a8eb9SGleb Smirnoff enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE };
1793b3a8eb9SGleb Smirnoff
1803b3a8eb9SGleb Smirnoff struct node_state_opt {
1813b3a8eb9SGleb Smirnoff int type;
1823b3a8eb9SGleb Smirnoff union {
1833b3a8eb9SGleb Smirnoff u_int32_t max_states;
1843b3a8eb9SGleb Smirnoff u_int32_t max_src_states;
1853b3a8eb9SGleb Smirnoff u_int32_t max_src_conn;
1863b3a8eb9SGleb Smirnoff struct {
1873b3a8eb9SGleb Smirnoff u_int32_t limit;
1883b3a8eb9SGleb Smirnoff u_int32_t seconds;
1893b3a8eb9SGleb Smirnoff } max_src_conn_rate;
1903b3a8eb9SGleb Smirnoff struct {
1913b3a8eb9SGleb Smirnoff u_int8_t flush;
1923b3a8eb9SGleb Smirnoff char tblname[PF_TABLE_NAME_SIZE];
1933b3a8eb9SGleb Smirnoff } overload;
1943b3a8eb9SGleb Smirnoff u_int32_t max_src_nodes;
1953b3a8eb9SGleb Smirnoff u_int8_t src_track;
1963b3a8eb9SGleb Smirnoff u_int32_t statelock;
1973b3a8eb9SGleb Smirnoff struct {
1983b3a8eb9SGleb Smirnoff int number;
1993b3a8eb9SGleb Smirnoff u_int32_t seconds;
2003b3a8eb9SGleb Smirnoff } timeout;
2013b3a8eb9SGleb Smirnoff } data;
2023b3a8eb9SGleb Smirnoff struct node_state_opt *next;
2033b3a8eb9SGleb Smirnoff struct node_state_opt *tail;
2043b3a8eb9SGleb Smirnoff };
2053b3a8eb9SGleb Smirnoff
2063b3a8eb9SGleb Smirnoff struct peer {
2073b3a8eb9SGleb Smirnoff struct node_host *host;
2083b3a8eb9SGleb Smirnoff struct node_port *port;
2093b3a8eb9SGleb Smirnoff };
2103b3a8eb9SGleb Smirnoff
21113cfafabSKristof Provost static struct node_queue {
2123b3a8eb9SGleb Smirnoff char queue[PF_QNAME_SIZE];
2133b3a8eb9SGleb Smirnoff char parent[PF_QNAME_SIZE];
2143b3a8eb9SGleb Smirnoff char ifname[IFNAMSIZ];
2153b3a8eb9SGleb Smirnoff int scheduler;
2163b3a8eb9SGleb Smirnoff struct node_queue *next;
2173b3a8eb9SGleb Smirnoff struct node_queue *tail;
2183b3a8eb9SGleb Smirnoff } *queues = NULL;
2193b3a8eb9SGleb Smirnoff
2203b3a8eb9SGleb Smirnoff struct node_qassign {
2213b3a8eb9SGleb Smirnoff char *qname;
2223b3a8eb9SGleb Smirnoff char *pqname;
2233b3a8eb9SGleb Smirnoff };
2243b3a8eb9SGleb Smirnoff
225aa69fdf1SKristof Provost struct range {
226aa69fdf1SKristof Provost int a;
227aa69fdf1SKristof Provost int b;
228aa69fdf1SKristof Provost int t;
229aa69fdf1SKristof Provost };
230aa69fdf1SKristof Provost
231aa69fdf1SKristof Provost static struct pool_opts {
232aa69fdf1SKristof Provost int marker;
233aa69fdf1SKristof Provost #define POM_TYPE 0x01
234aa69fdf1SKristof Provost #define POM_STICKYADDRESS 0x02
235aa69fdf1SKristof Provost #define POM_ENDPI 0x04
236aa69fdf1SKristof Provost u_int8_t opts;
237aa69fdf1SKristof Provost int type;
238aa69fdf1SKristof Provost int staticport;
239aa69fdf1SKristof Provost struct pf_poolhashkey *key;
240aa69fdf1SKristof Provost struct pf_mape_portset mape;
241aa69fdf1SKristof Provost } pool_opts;
242aa69fdf1SKristof Provost
243aa69fdf1SKristof Provost struct redirspec {
244*aeddee83SKajetan Staszkiewicz struct node_host *host;
245*aeddee83SKajetan Staszkiewicz struct range rport;
246aa69fdf1SKristof Provost struct pool_opts pool_opts;
247aa69fdf1SKristof Provost int af;
248aa69fdf1SKristof Provost };
249aa69fdf1SKristof Provost
25013cfafabSKristof Provost static struct filter_opts {
2513b3a8eb9SGleb Smirnoff int marker;
25239282ef3SKajetan Staszkiewicz #define FOM_FLAGS 0x0001
25339282ef3SKajetan Staszkiewicz #define FOM_ICMP 0x0002
25439282ef3SKajetan Staszkiewicz #define FOM_TOS 0x0004
25539282ef3SKajetan Staszkiewicz #define FOM_KEEP 0x0008
25639282ef3SKajetan Staszkiewicz #define FOM_SRCTRACK 0x0010
25739282ef3SKajetan Staszkiewicz #define FOM_MINTTL 0x0020
25839282ef3SKajetan Staszkiewicz #define FOM_MAXMSS 0x0040
259aa69fdf1SKristof Provost #define FOM_AFTO 0x0080
26039282ef3SKajetan Staszkiewicz #define FOM_SETTOS 0x0100
26139282ef3SKajetan Staszkiewicz #define FOM_SCRUB_TCP 0x0200
2623e248e0fSKristof Provost #define FOM_SETPRIO 0x0400
26339282ef3SKajetan Staszkiewicz #define FOM_ONCE 0x1000 /* not yet implemmented */
2643e248e0fSKristof Provost #define FOM_PRIO 0x2000
26539282ef3SKajetan Staszkiewicz #define FOM_SETDELAY 0x4000
26639282ef3SKajetan Staszkiewicz #define FOM_FRAGCACHE 0x8000 /* does not exist in OpenBSD */
2673b3a8eb9SGleb Smirnoff struct node_uid *uid;
2683b3a8eb9SGleb Smirnoff struct node_gid *gid;
2692339ead6SKristof Provost struct node_if *rcv;
2703b3a8eb9SGleb Smirnoff struct {
2713b3a8eb9SGleb Smirnoff u_int8_t b1;
2723b3a8eb9SGleb Smirnoff u_int8_t b2;
2733b3a8eb9SGleb Smirnoff u_int16_t w;
2743b3a8eb9SGleb Smirnoff u_int16_t w2;
2753b3a8eb9SGleb Smirnoff } flags;
2763b3a8eb9SGleb Smirnoff struct node_icmp *icmpspec;
2773b3a8eb9SGleb Smirnoff u_int32_t tos;
2783b3a8eb9SGleb Smirnoff u_int32_t prob;
27976c5eeccSKristof Provost u_int32_t ridentifier;
2803b3a8eb9SGleb Smirnoff struct {
2813b3a8eb9SGleb Smirnoff int action;
2823b3a8eb9SGleb Smirnoff struct node_state_opt *options;
2833b3a8eb9SGleb Smirnoff } keep;
2843b3a8eb9SGleb Smirnoff int fragment;
2853b3a8eb9SGleb Smirnoff int allowopts;
2866fcc8e04SKristof Provost char *label[PF_RULE_MAX_LABEL_COUNT];
2876fcc8e04SKristof Provost int labelcount;
2883b3a8eb9SGleb Smirnoff struct node_qassign queues;
2893b3a8eb9SGleb Smirnoff char *tag;
2903b3a8eb9SGleb Smirnoff char *match_tag;
2913b3a8eb9SGleb Smirnoff u_int8_t match_tag_not;
29263b3c1c7SKristof Provost u_int16_t dnpipe;
29363b3c1c7SKristof Provost u_int16_t dnrpipe;
29463b3c1c7SKristof Provost u_int32_t free_flags;
2953b3a8eb9SGleb Smirnoff u_int rtableid;
2963e248e0fSKristof Provost u_int8_t prio;
2973e248e0fSKristof Provost u_int8_t set_prio[2];
2983b3a8eb9SGleb Smirnoff struct {
2993b3a8eb9SGleb Smirnoff struct node_host *addr;
3003b3a8eb9SGleb Smirnoff u_int16_t port;
3013b3a8eb9SGleb Smirnoff } divert;
302*aeddee83SKajetan Staszkiewicz struct redirspec *nat;
303*aeddee83SKajetan Staszkiewicz struct redirspec *rdr;
30439282ef3SKajetan Staszkiewicz /* new-style scrub opts */
30539282ef3SKajetan Staszkiewicz int nodf;
30639282ef3SKajetan Staszkiewicz int minttl;
30739282ef3SKajetan Staszkiewicz int settos;
30839282ef3SKajetan Staszkiewicz int randomid;
30939282ef3SKajetan Staszkiewicz int max_mss;
3103b3a8eb9SGleb Smirnoff } filter_opts;
3113b3a8eb9SGleb Smirnoff
31213cfafabSKristof Provost static struct antispoof_opts {
3136fcc8e04SKristof Provost char *label[PF_RULE_MAX_LABEL_COUNT];
3146fcc8e04SKristof Provost int labelcount;
31576c5eeccSKristof Provost u_int32_t ridentifier;
3163b3a8eb9SGleb Smirnoff u_int rtableid;
3173b3a8eb9SGleb Smirnoff } antispoof_opts;
3183b3a8eb9SGleb Smirnoff
31913cfafabSKristof Provost static struct scrub_opts {
3203b3a8eb9SGleb Smirnoff int marker;
3213b3a8eb9SGleb Smirnoff int nodf;
3223b3a8eb9SGleb Smirnoff int minttl;
3233b3a8eb9SGleb Smirnoff int maxmss;
3243b3a8eb9SGleb Smirnoff int settos;
3253b3a8eb9SGleb Smirnoff int fragcache;
3263b3a8eb9SGleb Smirnoff int randomid;
3273b3a8eb9SGleb Smirnoff int reassemble_tcp;
3283b3a8eb9SGleb Smirnoff char *match_tag;
3293b3a8eb9SGleb Smirnoff u_int8_t match_tag_not;
3303b3a8eb9SGleb Smirnoff u_int rtableid;
3313b3a8eb9SGleb Smirnoff } scrub_opts;
3323b3a8eb9SGleb Smirnoff
33313cfafabSKristof Provost static struct queue_opts {
3343b3a8eb9SGleb Smirnoff int marker;
3353b3a8eb9SGleb Smirnoff #define QOM_BWSPEC 0x01
3363b3a8eb9SGleb Smirnoff #define QOM_SCHEDULER 0x02
3373b3a8eb9SGleb Smirnoff #define QOM_PRIORITY 0x04
3383b3a8eb9SGleb Smirnoff #define QOM_TBRSIZE 0x08
3393b3a8eb9SGleb Smirnoff #define QOM_QLIMIT 0x10
3403b3a8eb9SGleb Smirnoff struct node_queue_bw queue_bwspec;
3413b3a8eb9SGleb Smirnoff struct node_queue_opt scheduler;
3423b3a8eb9SGleb Smirnoff int priority;
343249cc75fSPatrick Kelsey unsigned int tbrsize;
3443b3a8eb9SGleb Smirnoff int qlimit;
3453b3a8eb9SGleb Smirnoff } queue_opts;
3463b3a8eb9SGleb Smirnoff
34713cfafabSKristof Provost static struct table_opts {
3483b3a8eb9SGleb Smirnoff int flags;
3493b3a8eb9SGleb Smirnoff int init_addr;
3503b3a8eb9SGleb Smirnoff struct node_tinithead init_nodes;
3513b3a8eb9SGleb Smirnoff } table_opts;
3523b3a8eb9SGleb Smirnoff
35313cfafabSKristof Provost static struct codel_opts codel_opts;
35413cfafabSKristof Provost static struct node_hfsc_opts hfsc_opts;
35513cfafabSKristof Provost static struct node_fairq_opts fairq_opts;
35613cfafabSKristof Provost static struct node_state_opt *keep_state_defaults = NULL;
3575062afffSKristof Provost static struct pfctl_watermarks syncookie_opts;
3583b3a8eb9SGleb Smirnoff
3593b3a8eb9SGleb Smirnoff int disallow_table(struct node_host *, const char *);
3603b3a8eb9SGleb Smirnoff int disallow_urpf_failed(struct node_host *, const char *);
3613b3a8eb9SGleb Smirnoff int disallow_alias(struct node_host *, const char *);
362e9eb0941SKristof Provost int rule_consistent(struct pfctl_rule *, int);
363e9eb0941SKristof Provost int filter_consistent(struct pfctl_rule *, int);
364e9eb0941SKristof Provost int nat_consistent(struct pfctl_rule *);
365e9eb0941SKristof Provost int rdr_consistent(struct pfctl_rule *);
3663b3a8eb9SGleb Smirnoff int process_tabledef(char *, struct table_opts *);
3673b3a8eb9SGleb Smirnoff void expand_label_str(char *, size_t, const char *, const char *);
3683b3a8eb9SGleb Smirnoff void expand_label_if(const char *, char *, size_t, const char *);
3699ec48bc3SKristof Provost void expand_label_addr(const char *, char *, size_t, sa_family_t,
37009c7f238SKristof Provost struct pf_rule_addr *);
3713b3a8eb9SGleb Smirnoff void expand_label_port(const char *, char *, size_t,
37209c7f238SKristof Provost struct pf_rule_addr *);
3733b3a8eb9SGleb Smirnoff void expand_label_proto(const char *, char *, size_t, u_int8_t);
37409c7f238SKristof Provost void expand_label_nr(const char *, char *, size_t,
37509c7f238SKristof Provost struct pfctl_rule *);
3762b29ceb8SKristof Provost void expand_eth_rule(struct pfctl_eth_rule *,
37787a89d6eSKristof Provost struct node_if *, struct node_etherproto *,
3788a42005dSKristof Provost struct node_mac *, struct node_mac *,
3798a8af942SKristof Provost struct node_host *, struct node_host *, const char *,
3808a8af942SKristof Provost const char *);
381*aeddee83SKajetan Staszkiewicz int apply_rdr_ports(struct pfctl_rule *r, struct pfctl_pool *, struct redirspec *);
382*aeddee83SKajetan Staszkiewicz int apply_nat_ports(struct pfctl_pool *, struct redirspec *);
383*aeddee83SKajetan Staszkiewicz int apply_redirspec(struct pfctl_pool *, struct redirspec *);
384e9eb0941SKristof Provost void expand_rule(struct pfctl_rule *, struct node_if *,
3850972294eSKristof Provost struct redirspec *, struct redirspec *, struct redirspec *,
3860972294eSKristof Provost struct node_proto *, struct node_os *, struct node_host *,
3870972294eSKristof Provost struct node_port *, struct node_host *, struct node_port *,
3880972294eSKristof Provost struct node_uid *, struct node_gid *, struct node_if *,
3890972294eSKristof Provost struct node_icmp *, const char *);
3903b3a8eb9SGleb Smirnoff int expand_altq(struct pf_altq *, struct node_if *,
3913b3a8eb9SGleb Smirnoff struct node_queue *, struct node_queue_bw bwspec,
3923b3a8eb9SGleb Smirnoff struct node_queue_opt *);
3933b3a8eb9SGleb Smirnoff int expand_queue(struct pf_altq *, struct node_if *,
3943b3a8eb9SGleb Smirnoff struct node_queue *, struct node_queue_bw,
3953b3a8eb9SGleb Smirnoff struct node_queue_opt *);
3963b3a8eb9SGleb Smirnoff int expand_skip_interface(struct node_if *);
3973b3a8eb9SGleb Smirnoff
3983b3a8eb9SGleb Smirnoff int check_rulestate(int);
3993b3a8eb9SGleb Smirnoff int getservice(char *);
4006fcc8e04SKristof Provost int rule_label(struct pfctl_rule *, char *s[PF_RULE_MAX_LABEL_COUNT]);
401ef661d4aSChristian McDonald int eth_rule_label(struct pfctl_eth_rule *, char *s[PF_RULE_MAX_LABEL_COUNT]);
4023b3a8eb9SGleb Smirnoff int rt_tableid_max(void);
4033b3a8eb9SGleb Smirnoff
404e9eb0941SKristof Provost void mv_rules(struct pfctl_ruleset *, struct pfctl_ruleset *);
405c5131afeSKristof Provost void mv_eth_rules(struct pfctl_eth_ruleset *, struct pfctl_eth_ruleset *);
4063b3a8eb9SGleb Smirnoff void decide_address_family(struct node_host *, sa_family_t *);
4073b3a8eb9SGleb Smirnoff void remove_invalid_hosts(struct node_host **, sa_family_t *);
4083b3a8eb9SGleb Smirnoff int invalid_redirect(struct node_host *, sa_family_t);
4093b3a8eb9SGleb Smirnoff u_int16_t parseicmpspec(char *, sa_family_t);
4101f495578SKristof Provost int kw_casecmp(const void *, const void *);
4111f495578SKristof Provost int map_tos(char *string, int *);
412b590f17aSKristof Provost struct node_mac* node_mac_from_string(const char *);
413b590f17aSKristof Provost struct node_mac* node_mac_from_string_masklen(const char *, int);
414b590f17aSKristof Provost struct node_mac* node_mac_from_string_mask(const char *, const char *);
4153b3a8eb9SGleb Smirnoff
41613cfafabSKristof Provost static TAILQ_HEAD(loadanchorshead, loadanchors)
4173b3a8eb9SGleb Smirnoff loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead);
4183b3a8eb9SGleb Smirnoff
4193b3a8eb9SGleb Smirnoff struct loadanchors {
4203b3a8eb9SGleb Smirnoff TAILQ_ENTRY(loadanchors) entries;
4213b3a8eb9SGleb Smirnoff char *anchorname;
4223b3a8eb9SGleb Smirnoff char *filename;
4233b3a8eb9SGleb Smirnoff };
4243b3a8eb9SGleb Smirnoff
4253b3a8eb9SGleb Smirnoff typedef struct {
4263b3a8eb9SGleb Smirnoff union {
4273b3a8eb9SGleb Smirnoff int64_t number;
4283b3a8eb9SGleb Smirnoff double probability;
4293b3a8eb9SGleb Smirnoff int i;
4303b3a8eb9SGleb Smirnoff char *string;
4313b3a8eb9SGleb Smirnoff u_int rtableid;
4323b3a8eb9SGleb Smirnoff struct {
4333b3a8eb9SGleb Smirnoff u_int8_t b1;
4343b3a8eb9SGleb Smirnoff u_int8_t b2;
4353b3a8eb9SGleb Smirnoff u_int16_t w;
4363b3a8eb9SGleb Smirnoff u_int16_t w2;
4373b3a8eb9SGleb Smirnoff } b;
438aa69fdf1SKristof Provost struct range range;
4393b3a8eb9SGleb Smirnoff struct node_if *interface;
4403b3a8eb9SGleb Smirnoff struct node_proto *proto;
4412b29ceb8SKristof Provost struct node_etherproto *etherproto;
4423b3a8eb9SGleb Smirnoff struct node_icmp *icmp;
4433b3a8eb9SGleb Smirnoff struct node_host *host;
4443b3a8eb9SGleb Smirnoff struct node_os *os;
4453b3a8eb9SGleb Smirnoff struct node_port *port;
4463b3a8eb9SGleb Smirnoff struct node_uid *uid;
4473b3a8eb9SGleb Smirnoff struct node_gid *gid;
4483b3a8eb9SGleb Smirnoff struct node_state_opt *state_opt;
4493b3a8eb9SGleb Smirnoff struct peer peer;
4503b3a8eb9SGleb Smirnoff struct {
4513b3a8eb9SGleb Smirnoff struct peer src, dst;
4523b3a8eb9SGleb Smirnoff struct node_os *src_os;
4533b3a8eb9SGleb Smirnoff } fromto;
4543b3a8eb9SGleb Smirnoff struct {
45587a89d6eSKristof Provost struct node_mac *src;
45687a89d6eSKristof Provost struct node_mac *dst;
4572b29ceb8SKristof Provost } etherfromto;
45887a89d6eSKristof Provost struct node_mac *mac;
4592b29ceb8SKristof Provost struct {
46087a89d6eSKristof Provost struct node_mac *mac;
4612b29ceb8SKristof Provost } etheraddr;
4628a8af942SKristof Provost char *bridge_to;
4632b29ceb8SKristof Provost struct {
464*aeddee83SKajetan Staszkiewicz struct redirspec *redirspec;
4653b3a8eb9SGleb Smirnoff u_int8_t rt;
4663b3a8eb9SGleb Smirnoff } route;
467*aeddee83SKajetan Staszkiewicz struct redirspec *redirspec;
4683b3a8eb9SGleb Smirnoff struct {
4693b3a8eb9SGleb Smirnoff int action;
4703b3a8eb9SGleb Smirnoff struct node_state_opt *options;
4713b3a8eb9SGleb Smirnoff } keep_state;
4723b3a8eb9SGleb Smirnoff struct {
4733b3a8eb9SGleb Smirnoff u_int8_t log;
4743b3a8eb9SGleb Smirnoff u_int8_t logif;
4753b3a8eb9SGleb Smirnoff u_int8_t quick;
4763b3a8eb9SGleb Smirnoff } logquick;
4773b3a8eb9SGleb Smirnoff struct {
4783b3a8eb9SGleb Smirnoff int neg;
4793b3a8eb9SGleb Smirnoff char *name;
4803b3a8eb9SGleb Smirnoff } tagged;
4813b3a8eb9SGleb Smirnoff struct pf_poolhashkey *hashkey;
4823b3a8eb9SGleb Smirnoff struct node_queue *queue;
4833b3a8eb9SGleb Smirnoff struct node_queue_opt queue_options;
4843b3a8eb9SGleb Smirnoff struct node_queue_bw queue_bwspec;
4853b3a8eb9SGleb Smirnoff struct node_qassign qassign;
4863b3a8eb9SGleb Smirnoff struct filter_opts filter_opts;
4873b3a8eb9SGleb Smirnoff struct antispoof_opts antispoof_opts;
4883b3a8eb9SGleb Smirnoff struct queue_opts queue_opts;
4893b3a8eb9SGleb Smirnoff struct scrub_opts scrub_opts;
4903b3a8eb9SGleb Smirnoff struct table_opts table_opts;
4913b3a8eb9SGleb Smirnoff struct pool_opts pool_opts;
4923b3a8eb9SGleb Smirnoff struct node_hfsc_opts hfsc_opts;
493a5b789f6SErmal Luçi struct node_fairq_opts fairq_opts;
4940a70aaf8SLuiz Otavio O Souza struct codel_opts codel_opts;
4955062afffSKristof Provost struct pfctl_watermarks *watermarks;
4963b3a8eb9SGleb Smirnoff } v;
4973b3a8eb9SGleb Smirnoff int lineno;
4983b3a8eb9SGleb Smirnoff } YYSTYPE;
4993b3a8eb9SGleb Smirnoff
5003b3a8eb9SGleb Smirnoff #define PPORT_RANGE 1
5013b3a8eb9SGleb Smirnoff #define PPORT_STAR 2
5023b3a8eb9SGleb Smirnoff int parseport(char *, struct range *r, int);
5033b3a8eb9SGleb Smirnoff
5043b3a8eb9SGleb Smirnoff #define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \
5053b3a8eb9SGleb Smirnoff (!((addr).iflags & PFI_AFLAG_NOALIAS) || \
5063b3a8eb9SGleb Smirnoff !isdigit((addr).v.ifname[strlen((addr).v.ifname)-1])))
5073b3a8eb9SGleb Smirnoff
5083b3a8eb9SGleb Smirnoff %}
5093b3a8eb9SGleb Smirnoff
510ef950daaSKristof Provost %token PASS BLOCK MATCH SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS
5113b3a8eb9SGleb Smirnoff %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE
5123b3a8eb9SGleb Smirnoff %token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF
5133b3a8eb9SGleb Smirnoff %token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL
5143b3a8eb9SGleb Smirnoff %token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE
51588e858e5SKristof Provost %token REASSEMBLE ANCHOR NATANCHOR RDRANCHOR BINATANCHOR
516150182e3SKristof Provost %token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY FAILPOLICY
517150182e3SKristof Provost %token RANDOMID REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID
518f3ab00c2SKristof Provost %token ANTISPOOF FOR INCLUDE KEEPCOUNTERS SYNCOOKIES L3 MATCHES
5192b29ceb8SKristof Provost %token ETHER
5202aa21096SKurosawa Takahiro %token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY MAPEPORTSET
5210a70aaf8SLuiz Otavio O Souza %token ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME
5220a70aaf8SLuiz Otavio O Souza %token UPPERLIMIT QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE TARGET INTERVAL
52376c5eeccSKristof Provost %token DNPIPE DNQUEUE RIDENTIFIER
5243e248e0fSKristof Provost %token LOAD RULESET_OPTIMIZATION PRIO
525390dc369STom Jones %token STICKYADDRESS ENDPI MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE
526e4f2733dSKristof Provost %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY PFLOW ALLOW_RELATED
5273b3a8eb9SGleb Smirnoff %token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS
528aa69fdf1SKristof Provost %token DIVERTTO DIVERTREPLY BRIDGE_TO RECEIVEDON NE LE GE AFTO
5293b3a8eb9SGleb Smirnoff %token <v.string> STRING
5303b3a8eb9SGleb Smirnoff %token <v.number> NUMBER
5313b3a8eb9SGleb Smirnoff %token <v.i> PORTBINARY
5323b3a8eb9SGleb Smirnoff %type <v.interface> interface if_list if_item_not if_item
5333b3a8eb9SGleb Smirnoff %type <v.number> number icmptype icmp6type uid gid
53439282ef3SKajetan Staszkiewicz %type <v.number> tos not yesno optnodf
5353b3a8eb9SGleb Smirnoff %type <v.probability> probability
536c69121c4SKristof Provost %type <v.i> no dir af fragcache optimizer syncookie_val
5373b3a8eb9SGleb Smirnoff %type <v.i> sourcetrack flush unaryop statelock
5382b29ceb8SKristof Provost %type <v.i> etherprotoval
5393b3a8eb9SGleb Smirnoff %type <v.b> action nataction natpasslog scrubaction
5403e248e0fSKristof Provost %type <v.b> flags flag blockspec prio
5413b3a8eb9SGleb Smirnoff %type <v.range> portplain portstar portrange
5423b3a8eb9SGleb Smirnoff %type <v.hashkey> hashkey
5433b3a8eb9SGleb Smirnoff %type <v.proto> proto proto_list proto_item
5443b3a8eb9SGleb Smirnoff %type <v.number> protoval
5453b3a8eb9SGleb Smirnoff %type <v.icmp> icmpspec
5463b3a8eb9SGleb Smirnoff %type <v.icmp> icmp_list icmp_item
5473b3a8eb9SGleb Smirnoff %type <v.icmp> icmp6_list icmp6_item
5483b3a8eb9SGleb Smirnoff %type <v.number> reticmpspec reticmp6spec
5498a42005dSKristof Provost %type <v.fromto> fromto l3fromto
5503b3a8eb9SGleb Smirnoff %type <v.peer> ipportspec from to
5513b3a8eb9SGleb Smirnoff %type <v.host> ipspec toipspec xhost host dynaddr host_list
552*aeddee83SKajetan Staszkiewicz %type <v.host> redir_host redir_host_list routespec
553*aeddee83SKajetan Staszkiewicz %type <v.host> route_host route_host_list
5543b3a8eb9SGleb Smirnoff %type <v.os> os xos os_list
5553b3a8eb9SGleb Smirnoff %type <v.port> portspec port_list port_item
5563b3a8eb9SGleb Smirnoff %type <v.uid> uids uid_list uid_item
5573b3a8eb9SGleb Smirnoff %type <v.gid> gids gid_list gid_item
5583b3a8eb9SGleb Smirnoff %type <v.route> route
559*aeddee83SKajetan Staszkiewicz %type <v.redirspec> no_port_redirspec port_redirspec route_redirspec
560*aeddee83SKajetan Staszkiewicz %type <v.redirspec> binat_redirspec nat_redirspec
5613b3a8eb9SGleb Smirnoff %type <v.string> label stringall tag anchorname
5623b3a8eb9SGleb Smirnoff %type <v.string> string varstring numberstring
5633b3a8eb9SGleb Smirnoff %type <v.keep_state> keep
5643b3a8eb9SGleb Smirnoff %type <v.state_opt> state_opt_spec state_opt_list state_opt_item
5653b3a8eb9SGleb Smirnoff %type <v.logquick> logquick quick log logopts logopt
5663b3a8eb9SGleb Smirnoff %type <v.interface> antispoof_ifspc antispoof_iflst antispoof_if
5672b29ceb8SKristof Provost %type <v.qassign> qname etherqname
5683b3a8eb9SGleb Smirnoff %type <v.queue> qassign qassign_list qassign_item
5693b3a8eb9SGleb Smirnoff %type <v.queue_options> scheduler
5703b3a8eb9SGleb Smirnoff %type <v.number> cbqflags_list cbqflags_item
5713b3a8eb9SGleb Smirnoff %type <v.number> priqflags_list priqflags_item
5723b3a8eb9SGleb Smirnoff %type <v.hfsc_opts> hfscopts_list hfscopts_item hfsc_opts
573a5b789f6SErmal Luçi %type <v.fairq_opts> fairqopts_list fairqopts_item fairq_opts
5740a70aaf8SLuiz Otavio O Souza %type <v.codel_opts> codelopts_list codelopts_item codel_opts
5753b3a8eb9SGleb Smirnoff %type <v.queue_bwspec> bandwidth
5762b29ceb8SKristof Provost %type <v.filter_opts> filter_opts filter_opt filter_opts_l etherfilter_opts etherfilter_opt etherfilter_opts_l
5773e248e0fSKristof Provost %type <v.filter_opts> filter_sets filter_set filter_sets_l
5783b3a8eb9SGleb Smirnoff %type <v.antispoof_opts> antispoof_opts antispoof_opt antispoof_opts_l
5793b3a8eb9SGleb Smirnoff %type <v.queue_opts> queue_opts queue_opt queue_opts_l
5803b3a8eb9SGleb Smirnoff %type <v.scrub_opts> scrub_opts scrub_opt scrub_opts_l
5813b3a8eb9SGleb Smirnoff %type <v.table_opts> table_opts table_opt table_opts_l
5823b3a8eb9SGleb Smirnoff %type <v.pool_opts> pool_opts pool_opt pool_opts_l
5833b3a8eb9SGleb Smirnoff %type <v.tagged> tagged
5843b3a8eb9SGleb Smirnoff %type <v.rtableid> rtable
5855062afffSKristof Provost %type <v.watermarks> syncookie_opts
5862b29ceb8SKristof Provost %type <v.etherproto> etherproto etherproto_list etherproto_item
5872b29ceb8SKristof Provost %type <v.etherfromto> etherfromto
5882b29ceb8SKristof Provost %type <v.etheraddr> etherfrom etherto
5898a8af942SKristof Provost %type <v.bridge_to> bridge
59087a89d6eSKristof Provost %type <v.mac> xmac mac mac_list macspec
5913b3a8eb9SGleb Smirnoff %%
5923b3a8eb9SGleb Smirnoff
5933b3a8eb9SGleb Smirnoff ruleset : /* empty */
5943b3a8eb9SGleb Smirnoff | ruleset include '\n'
5953b3a8eb9SGleb Smirnoff | ruleset '\n'
5963b3a8eb9SGleb Smirnoff | ruleset option '\n'
5972b29ceb8SKristof Provost | ruleset etherrule '\n'
598c5131afeSKristof Provost | ruleset etheranchorrule '\n'
5993b3a8eb9SGleb Smirnoff | ruleset scrubrule '\n'
6003b3a8eb9SGleb Smirnoff | ruleset natrule '\n'
6013b3a8eb9SGleb Smirnoff | ruleset binatrule '\n'
6023b3a8eb9SGleb Smirnoff | ruleset pfrule '\n'
6033b3a8eb9SGleb Smirnoff | ruleset anchorrule '\n'
6043b3a8eb9SGleb Smirnoff | ruleset loadrule '\n'
6053b3a8eb9SGleb Smirnoff | ruleset altqif '\n'
6063b3a8eb9SGleb Smirnoff | ruleset queuespec '\n'
6073b3a8eb9SGleb Smirnoff | ruleset varset '\n'
6083b3a8eb9SGleb Smirnoff | ruleset antispoof '\n'
6093b3a8eb9SGleb Smirnoff | ruleset tabledef '\n'
6103b3a8eb9SGleb Smirnoff | '{' fakeanchor '}' '\n';
6113b3a8eb9SGleb Smirnoff | ruleset error '\n' { file->errors++; }
6123b3a8eb9SGleb Smirnoff ;
6133b3a8eb9SGleb Smirnoff
6143b3a8eb9SGleb Smirnoff include : INCLUDE STRING {
6153b3a8eb9SGleb Smirnoff struct file *nfile;
6163b3a8eb9SGleb Smirnoff
6173b3a8eb9SGleb Smirnoff if ((nfile = pushfile($2, 0)) == NULL) {
6183b3a8eb9SGleb Smirnoff yyerror("failed to include file %s", $2);
6193b3a8eb9SGleb Smirnoff free($2);
6203b3a8eb9SGleb Smirnoff YYERROR;
6213b3a8eb9SGleb Smirnoff }
6223b3a8eb9SGleb Smirnoff free($2);
6233b3a8eb9SGleb Smirnoff
6243b3a8eb9SGleb Smirnoff file = nfile;
6253b3a8eb9SGleb Smirnoff lungetc('\n');
6263b3a8eb9SGleb Smirnoff }
6273b3a8eb9SGleb Smirnoff ;
6283b3a8eb9SGleb Smirnoff
6293b3a8eb9SGleb Smirnoff /*
6303b3a8eb9SGleb Smirnoff * apply to previouslys specified rule: must be careful to note
6313b3a8eb9SGleb Smirnoff * what that is: pf or nat or binat or rdr
6323b3a8eb9SGleb Smirnoff */
6333b3a8eb9SGleb Smirnoff fakeanchor : fakeanchor '\n'
6343b3a8eb9SGleb Smirnoff | fakeanchor anchorrule '\n'
6353b3a8eb9SGleb Smirnoff | fakeanchor binatrule '\n'
6363b3a8eb9SGleb Smirnoff | fakeanchor natrule '\n'
6373b3a8eb9SGleb Smirnoff | fakeanchor pfrule '\n'
6383b3a8eb9SGleb Smirnoff | fakeanchor error '\n'
6393b3a8eb9SGleb Smirnoff ;
6403b3a8eb9SGleb Smirnoff
6413b3a8eb9SGleb Smirnoff optimizer : string {
6423b3a8eb9SGleb Smirnoff if (!strcmp($1, "none"))
6433b3a8eb9SGleb Smirnoff $$ = 0;
6443b3a8eb9SGleb Smirnoff else if (!strcmp($1, "basic"))
6453b3a8eb9SGleb Smirnoff $$ = PF_OPTIMIZE_BASIC;
6463b3a8eb9SGleb Smirnoff else if (!strcmp($1, "profile"))
6473b3a8eb9SGleb Smirnoff $$ = PF_OPTIMIZE_BASIC | PF_OPTIMIZE_PROFILE;
6483b3a8eb9SGleb Smirnoff else {
6493b3a8eb9SGleb Smirnoff yyerror("unknown ruleset-optimization %s", $1);
6503b3a8eb9SGleb Smirnoff YYERROR;
6513b3a8eb9SGleb Smirnoff }
6523b3a8eb9SGleb Smirnoff }
6533b3a8eb9SGleb Smirnoff ;
6543b3a8eb9SGleb Smirnoff
65539282ef3SKajetan Staszkiewicz optnodf : /* empty */ { $$ = 0; }
65639282ef3SKajetan Staszkiewicz | NODF { $$ = 1; }
65739282ef3SKajetan Staszkiewicz ;
65839282ef3SKajetan Staszkiewicz
65939282ef3SKajetan Staszkiewicz option : SET REASSEMBLE yesno optnodf {
66039282ef3SKajetan Staszkiewicz if (check_rulestate(PFCTL_STATE_OPTION))
66139282ef3SKajetan Staszkiewicz YYERROR;
66239282ef3SKajetan Staszkiewicz pfctl_set_reassembly(pf, $3, $4);
66339282ef3SKajetan Staszkiewicz }
66439282ef3SKajetan Staszkiewicz | SET OPTIMIZATION STRING {
6653b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION)) {
6663b3a8eb9SGleb Smirnoff free($3);
6673b3a8eb9SGleb Smirnoff YYERROR;
6683b3a8eb9SGleb Smirnoff }
6693b3a8eb9SGleb Smirnoff if (pfctl_set_optimization(pf, $3) != 0) {
6703b3a8eb9SGleb Smirnoff yyerror("unknown optimization %s", $3);
6713b3a8eb9SGleb Smirnoff free($3);
6723b3a8eb9SGleb Smirnoff YYERROR;
6733b3a8eb9SGleb Smirnoff }
6743b3a8eb9SGleb Smirnoff free($3);
6753b3a8eb9SGleb Smirnoff }
6763b3a8eb9SGleb Smirnoff | SET RULESET_OPTIMIZATION optimizer {
6773b3a8eb9SGleb Smirnoff if (!(pf->opts & PF_OPT_OPTIMIZE)) {
6783b3a8eb9SGleb Smirnoff pf->opts |= PF_OPT_OPTIMIZE;
6793b3a8eb9SGleb Smirnoff pf->optimize = $3;
6803b3a8eb9SGleb Smirnoff }
6813b3a8eb9SGleb Smirnoff }
6823b3a8eb9SGleb Smirnoff | SET TIMEOUT timeout_spec
6833b3a8eb9SGleb Smirnoff | SET TIMEOUT '{' optnl timeout_list '}'
6843b3a8eb9SGleb Smirnoff | SET LIMIT limit_spec
6853b3a8eb9SGleb Smirnoff | SET LIMIT '{' optnl limit_list '}'
6863b3a8eb9SGleb Smirnoff | SET LOGINTERFACE stringall {
6873b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION)) {
6883b3a8eb9SGleb Smirnoff free($3);
6893b3a8eb9SGleb Smirnoff YYERROR;
6903b3a8eb9SGleb Smirnoff }
6913b3a8eb9SGleb Smirnoff if (pfctl_set_logif(pf, $3) != 0) {
6923b3a8eb9SGleb Smirnoff yyerror("error setting loginterface %s", $3);
6933b3a8eb9SGleb Smirnoff free($3);
6943b3a8eb9SGleb Smirnoff YYERROR;
6953b3a8eb9SGleb Smirnoff }
6963b3a8eb9SGleb Smirnoff free($3);
6973b3a8eb9SGleb Smirnoff }
6983b3a8eb9SGleb Smirnoff | SET HOSTID number {
6993b3a8eb9SGleb Smirnoff if ($3 == 0 || $3 > UINT_MAX) {
7003b3a8eb9SGleb Smirnoff yyerror("hostid must be non-zero");
7013b3a8eb9SGleb Smirnoff YYERROR;
7023b3a8eb9SGleb Smirnoff }
7034aafc73dSKristof Provost pfctl_set_hostid(pf, $3);
7043b3a8eb9SGleb Smirnoff }
7053b3a8eb9SGleb Smirnoff | SET BLOCKPOLICY DROP {
7063b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE)
7073b3a8eb9SGleb Smirnoff printf("set block-policy drop\n");
7083b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION))
7093b3a8eb9SGleb Smirnoff YYERROR;
7103b3a8eb9SGleb Smirnoff blockpolicy = PFRULE_DROP;
7113b3a8eb9SGleb Smirnoff }
7123b3a8eb9SGleb Smirnoff | SET BLOCKPOLICY RETURN {
7133b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE)
7143b3a8eb9SGleb Smirnoff printf("set block-policy return\n");
7153b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION))
7163b3a8eb9SGleb Smirnoff YYERROR;
7173b3a8eb9SGleb Smirnoff blockpolicy = PFRULE_RETURN;
7183b3a8eb9SGleb Smirnoff }
719150182e3SKristof Provost | SET FAILPOLICY DROP {
720150182e3SKristof Provost if (pf->opts & PF_OPT_VERBOSE)
721150182e3SKristof Provost printf("set fail-policy drop\n");
722150182e3SKristof Provost if (check_rulestate(PFCTL_STATE_OPTION))
723150182e3SKristof Provost YYERROR;
724150182e3SKristof Provost failpolicy = PFRULE_DROP;
725150182e3SKristof Provost }
726150182e3SKristof Provost | SET FAILPOLICY RETURN {
727150182e3SKristof Provost if (pf->opts & PF_OPT_VERBOSE)
728150182e3SKristof Provost printf("set fail-policy return\n");
729150182e3SKristof Provost if (check_rulestate(PFCTL_STATE_OPTION))
730150182e3SKristof Provost YYERROR;
731150182e3SKristof Provost failpolicy = PFRULE_RETURN;
732150182e3SKristof Provost }
7333b3a8eb9SGleb Smirnoff | SET REQUIREORDER yesno {
7343b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE)
7353b3a8eb9SGleb Smirnoff printf("set require-order %s\n",
7363b3a8eb9SGleb Smirnoff $3 == 1 ? "yes" : "no");
7373b3a8eb9SGleb Smirnoff require_order = $3;
7383b3a8eb9SGleb Smirnoff }
7393b3a8eb9SGleb Smirnoff | SET FINGERPRINTS STRING {
7403b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE)
7413b3a8eb9SGleb Smirnoff printf("set fingerprints \"%s\"\n", $3);
7423b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION)) {
7433b3a8eb9SGleb Smirnoff free($3);
7443b3a8eb9SGleb Smirnoff YYERROR;
7453b3a8eb9SGleb Smirnoff }
7463b3a8eb9SGleb Smirnoff if (!pf->anchor->name[0]) {
7473b3a8eb9SGleb Smirnoff if (pfctl_file_fingerprints(pf->dev,
7483b3a8eb9SGleb Smirnoff pf->opts, $3)) {
7493b3a8eb9SGleb Smirnoff yyerror("error loading "
7503b3a8eb9SGleb Smirnoff "fingerprints %s", $3);
7513b3a8eb9SGleb Smirnoff free($3);
7523b3a8eb9SGleb Smirnoff YYERROR;
7533b3a8eb9SGleb Smirnoff }
7543b3a8eb9SGleb Smirnoff }
7553b3a8eb9SGleb Smirnoff free($3);
7563b3a8eb9SGleb Smirnoff }
7573b3a8eb9SGleb Smirnoff | SET STATEPOLICY statelock {
7583b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE)
7593b3a8eb9SGleb Smirnoff switch ($3) {
7603b3a8eb9SGleb Smirnoff case 0:
7613b3a8eb9SGleb Smirnoff printf("set state-policy floating\n");
7623b3a8eb9SGleb Smirnoff break;
7633b3a8eb9SGleb Smirnoff case PFRULE_IFBOUND:
7643b3a8eb9SGleb Smirnoff printf("set state-policy if-bound\n");
7653b3a8eb9SGleb Smirnoff break;
7663b3a8eb9SGleb Smirnoff }
7673b3a8eb9SGleb Smirnoff default_statelock = $3;
7683b3a8eb9SGleb Smirnoff }
7693b3a8eb9SGleb Smirnoff | SET DEBUG STRING {
7703b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION)) {
7713b3a8eb9SGleb Smirnoff free($3);
7723b3a8eb9SGleb Smirnoff YYERROR;
7733b3a8eb9SGleb Smirnoff }
774c36c90a2SKristof Provost if (pfctl_do_set_debug(pf, $3) != 0) {
7753b3a8eb9SGleb Smirnoff yyerror("error setting debuglevel %s", $3);
7763b3a8eb9SGleb Smirnoff free($3);
7773b3a8eb9SGleb Smirnoff YYERROR;
7783b3a8eb9SGleb Smirnoff }
7793b3a8eb9SGleb Smirnoff free($3);
7803b3a8eb9SGleb Smirnoff }
7813b3a8eb9SGleb Smirnoff | SET SKIP interface {
7823b3a8eb9SGleb Smirnoff if (expand_skip_interface($3) != 0) {
7833b3a8eb9SGleb Smirnoff yyerror("error setting skip interface(s)");
7843b3a8eb9SGleb Smirnoff YYERROR;
7853b3a8eb9SGleb Smirnoff }
7863b3a8eb9SGleb Smirnoff }
7873b3a8eb9SGleb Smirnoff | SET STATEDEFAULTS state_opt_list {
7883b3a8eb9SGleb Smirnoff if (keep_state_defaults != NULL) {
7893b3a8eb9SGleb Smirnoff yyerror("cannot redefine state-defaults");
7903b3a8eb9SGleb Smirnoff YYERROR;
7913b3a8eb9SGleb Smirnoff }
7923b3a8eb9SGleb Smirnoff keep_state_defaults = $3;
7933b3a8eb9SGleb Smirnoff }
79442ec75f8SKristof Provost | SET KEEPCOUNTERS {
79542ec75f8SKristof Provost pf->keep_counters = true;
79642ec75f8SKristof Provost }
7975062afffSKristof Provost | SET SYNCOOKIES syncookie_val syncookie_opts {
7985062afffSKristof Provost if (pfctl_cfg_syncookies(pf, $3, $4)) {
7995062afffSKristof Provost yyerror("error setting syncookies");
8005062afffSKristof Provost YYERROR;
8015062afffSKristof Provost }
802c69121c4SKristof Provost }
803c69121c4SKristof Provost ;
804c69121c4SKristof Provost
805c69121c4SKristof Provost syncookie_val : STRING {
806c69121c4SKristof Provost if (!strcmp($1, "never"))
807c69121c4SKristof Provost $$ = PFCTL_SYNCOOKIES_NEVER;
8085062afffSKristof Provost else if (!strcmp($1, "adaptive"))
8095062afffSKristof Provost $$ = PFCTL_SYNCOOKIES_ADAPTIVE;
810c69121c4SKristof Provost else if (!strcmp($1, "always"))
811c69121c4SKristof Provost $$ = PFCTL_SYNCOOKIES_ALWAYS;
812c69121c4SKristof Provost else {
813c69121c4SKristof Provost yyerror("illegal value for syncookies");
814c69121c4SKristof Provost YYERROR;
815c69121c4SKristof Provost }
816c69121c4SKristof Provost }
8173b3a8eb9SGleb Smirnoff ;
8185062afffSKristof Provost syncookie_opts : /* empty */ { $$ = NULL; }
8195062afffSKristof Provost | {
8205062afffSKristof Provost memset(&syncookie_opts, 0, sizeof(syncookie_opts));
8215062afffSKristof Provost } '(' syncookie_opt_l ')' { $$ = &syncookie_opts; }
8225062afffSKristof Provost ;
8235062afffSKristof Provost
8245062afffSKristof Provost syncookie_opt_l : syncookie_opt_l comma syncookie_opt
8255062afffSKristof Provost | syncookie_opt
8265062afffSKristof Provost ;
8275062afffSKristof Provost
8285062afffSKristof Provost syncookie_opt : STRING STRING {
8295062afffSKristof Provost double val;
8305062afffSKristof Provost char *cp;
8315062afffSKristof Provost
8325062afffSKristof Provost val = strtod($2, &cp);
8335062afffSKristof Provost if (cp == NULL || strcmp(cp, "%"))
8345062afffSKristof Provost YYERROR;
8355062afffSKristof Provost if (val <= 0 || val > 100) {
8365062afffSKristof Provost yyerror("illegal percentage value");
8375062afffSKristof Provost YYERROR;
8385062afffSKristof Provost }
8395062afffSKristof Provost if (!strcmp($1, "start")) {
8405062afffSKristof Provost syncookie_opts.hi = val;
8415062afffSKristof Provost } else if (!strcmp($1, "end")) {
8425062afffSKristof Provost syncookie_opts.lo = val;
8435062afffSKristof Provost } else {
8445062afffSKristof Provost yyerror("illegal syncookie option");
8455062afffSKristof Provost YYERROR;
8465062afffSKristof Provost }
8475062afffSKristof Provost }
8485062afffSKristof Provost ;
8493b3a8eb9SGleb Smirnoff
8503b3a8eb9SGleb Smirnoff stringall : STRING { $$ = $1; }
8513b3a8eb9SGleb Smirnoff | ALL {
8523b3a8eb9SGleb Smirnoff if (($$ = strdup("all")) == NULL) {
8533b3a8eb9SGleb Smirnoff err(1, "stringall: strdup");
8543b3a8eb9SGleb Smirnoff }
8553b3a8eb9SGleb Smirnoff }
8563b3a8eb9SGleb Smirnoff ;
8573b3a8eb9SGleb Smirnoff
8583b3a8eb9SGleb Smirnoff string : STRING string {
8593b3a8eb9SGleb Smirnoff if (asprintf(&$$, "%s %s", $1, $2) == -1)
8603b3a8eb9SGleb Smirnoff err(1, "string: asprintf");
8613b3a8eb9SGleb Smirnoff free($1);
8623b3a8eb9SGleb Smirnoff free($2);
8633b3a8eb9SGleb Smirnoff }
8643b3a8eb9SGleb Smirnoff | STRING
8653b3a8eb9SGleb Smirnoff ;
8663b3a8eb9SGleb Smirnoff
8673b3a8eb9SGleb Smirnoff varstring : numberstring varstring {
8683b3a8eb9SGleb Smirnoff if (asprintf(&$$, "%s %s", $1, $2) == -1)
8693b3a8eb9SGleb Smirnoff err(1, "string: asprintf");
8703b3a8eb9SGleb Smirnoff free($1);
8713b3a8eb9SGleb Smirnoff free($2);
8723b3a8eb9SGleb Smirnoff }
8733b3a8eb9SGleb Smirnoff | numberstring
8743b3a8eb9SGleb Smirnoff ;
8753b3a8eb9SGleb Smirnoff
8763b3a8eb9SGleb Smirnoff numberstring : NUMBER {
8773b3a8eb9SGleb Smirnoff char *s;
8783b3a8eb9SGleb Smirnoff if (asprintf(&s, "%lld", (long long)$1) == -1) {
8793b3a8eb9SGleb Smirnoff yyerror("string: asprintf");
8803b3a8eb9SGleb Smirnoff YYERROR;
8813b3a8eb9SGleb Smirnoff }
8823b3a8eb9SGleb Smirnoff $$ = s;
8833b3a8eb9SGleb Smirnoff }
8843b3a8eb9SGleb Smirnoff | STRING
8853b3a8eb9SGleb Smirnoff ;
8863b3a8eb9SGleb Smirnoff
8873b3a8eb9SGleb Smirnoff varset : STRING '=' varstring {
888d3f65324SKristof Provost char *s = $1;
8893b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE)
8903b3a8eb9SGleb Smirnoff printf("%s = \"%s\"\n", $1, $3);
891d3f65324SKristof Provost while (*s++) {
892d3f65324SKristof Provost if (isspace((unsigned char)*s)) {
893d3f65324SKristof Provost yyerror("macro name cannot contain "
894d3f65324SKristof Provost "whitespace");
895d3f65324SKristof Provost YYERROR;
896d3f65324SKristof Provost }
897d3f65324SKristof Provost }
8983b3a8eb9SGleb Smirnoff if (symset($1, $3, 0) == -1)
8993b3a8eb9SGleb Smirnoff err(1, "cannot store variable %s", $1);
9003b3a8eb9SGleb Smirnoff free($1);
9013b3a8eb9SGleb Smirnoff free($3);
9023b3a8eb9SGleb Smirnoff }
9033b3a8eb9SGleb Smirnoff ;
9043b3a8eb9SGleb Smirnoff
9053b3a8eb9SGleb Smirnoff anchorname : STRING { $$ = $1; }
9063b3a8eb9SGleb Smirnoff | /* empty */ { $$ = NULL; }
9073b3a8eb9SGleb Smirnoff ;
9083b3a8eb9SGleb Smirnoff
9093b3a8eb9SGleb Smirnoff pfa_anchorlist : /* empty */
9103b3a8eb9SGleb Smirnoff | pfa_anchorlist '\n'
9113b3a8eb9SGleb Smirnoff | pfa_anchorlist pfrule '\n'
9123b3a8eb9SGleb Smirnoff | pfa_anchorlist anchorrule '\n'
9133b3a8eb9SGleb Smirnoff ;
9143b3a8eb9SGleb Smirnoff
9153b3a8eb9SGleb Smirnoff pfa_anchor : '{'
9163b3a8eb9SGleb Smirnoff {
9173b3a8eb9SGleb Smirnoff char ta[PF_ANCHOR_NAME_SIZE];
918e9eb0941SKristof Provost struct pfctl_ruleset *rs;
9193b3a8eb9SGleb Smirnoff
9202fa6223aSGordon Bergling /* stepping into a brace anchor */
9213b3a8eb9SGleb Smirnoff pf->asd++;
9223b3a8eb9SGleb Smirnoff pf->bn++;
9233b3a8eb9SGleb Smirnoff
924585a5ed0SKristof Provost /*
925585a5ed0SKristof Provost * Anchor contents are parsed before the anchor rule
926585a5ed0SKristof Provost * production completes, so we don't know the real
927585a5ed0SKristof Provost * location yet. Create a holding ruleset in the root;
928585a5ed0SKristof Provost * contents will be moved afterwards.
929585a5ed0SKristof Provost */
9303b3a8eb9SGleb Smirnoff snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn);
9313b3a8eb9SGleb Smirnoff rs = pf_find_or_create_ruleset(ta);
9323b3a8eb9SGleb Smirnoff if (rs == NULL)
9333b3a8eb9SGleb Smirnoff err(1, "pfa_anchor: pf_find_or_create_ruleset");
9343b3a8eb9SGleb Smirnoff pf->astack[pf->asd] = rs->anchor;
9353b3a8eb9SGleb Smirnoff pf->anchor = rs->anchor;
9363b3a8eb9SGleb Smirnoff } '\n' pfa_anchorlist '}'
9373b3a8eb9SGleb Smirnoff {
9383b3a8eb9SGleb Smirnoff pf->alast = pf->anchor;
9393b3a8eb9SGleb Smirnoff pf->asd--;
9403b3a8eb9SGleb Smirnoff pf->anchor = pf->astack[pf->asd];
9413b3a8eb9SGleb Smirnoff }
9423b3a8eb9SGleb Smirnoff | /* empty */
9433b3a8eb9SGleb Smirnoff ;
9443b3a8eb9SGleb Smirnoff
9453b3a8eb9SGleb Smirnoff anchorrule : ANCHOR anchorname dir quick interface af proto fromto
9463b3a8eb9SGleb Smirnoff filter_opts pfa_anchor
9473b3a8eb9SGleb Smirnoff {
948e9eb0941SKristof Provost struct pfctl_rule r;
9493b3a8eb9SGleb Smirnoff struct node_proto *proto;
9503b3a8eb9SGleb Smirnoff
9513b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_FILTER)) {
9523b3a8eb9SGleb Smirnoff if ($2)
9533b3a8eb9SGleb Smirnoff free($2);
9543b3a8eb9SGleb Smirnoff YYERROR;
9553b3a8eb9SGleb Smirnoff }
9563b3a8eb9SGleb Smirnoff
9573b3a8eb9SGleb Smirnoff if ($2 && ($2[0] == '_' || strstr($2, "/_") != NULL)) {
9583b3a8eb9SGleb Smirnoff free($2);
9593b3a8eb9SGleb Smirnoff yyerror("anchor names beginning with '_' "
9603b3a8eb9SGleb Smirnoff "are reserved for internal use");
9613b3a8eb9SGleb Smirnoff YYERROR;
9623b3a8eb9SGleb Smirnoff }
9633b3a8eb9SGleb Smirnoff
964*aeddee83SKajetan Staszkiewicz pfctl_init_rule(&r);
965*aeddee83SKajetan Staszkiewicz
9663b3a8eb9SGleb Smirnoff if (pf->astack[pf->asd + 1]) {
967585a5ed0SKristof Provost if ($2 && strchr($2, '/') != NULL) {
968585a5ed0SKristof Provost free($2);
969585a5ed0SKristof Provost yyerror("anchor paths containing '/' "
970585a5ed0SKristof Provost "cannot be used for inline anchors.");
971585a5ed0SKristof Provost YYERROR;
972585a5ed0SKristof Provost }
973585a5ed0SKristof Provost
974585a5ed0SKristof Provost /* Move inline rules into relative location. */
975e9eb0941SKristof Provost pfctl_anchor_setup(&r,
9763b3a8eb9SGleb Smirnoff &pf->astack[pf->asd]->ruleset,
9773b3a8eb9SGleb Smirnoff $2 ? $2 : pf->alast->name);
9783b3a8eb9SGleb Smirnoff
9793b3a8eb9SGleb Smirnoff if (r.anchor == NULL)
9803b3a8eb9SGleb Smirnoff err(1, "anchorrule: unable to "
9813b3a8eb9SGleb Smirnoff "create ruleset");
9823b3a8eb9SGleb Smirnoff
9833b3a8eb9SGleb Smirnoff if (pf->alast != r.anchor) {
9843b3a8eb9SGleb Smirnoff if (r.anchor->match) {
9853b3a8eb9SGleb Smirnoff yyerror("inline anchor '%s' "
9863b3a8eb9SGleb Smirnoff "already exists",
9873b3a8eb9SGleb Smirnoff r.anchor->name);
9883b3a8eb9SGleb Smirnoff YYERROR;
9893b3a8eb9SGleb Smirnoff }
9903b3a8eb9SGleb Smirnoff mv_rules(&pf->alast->ruleset,
9913b3a8eb9SGleb Smirnoff &r.anchor->ruleset);
9923b3a8eb9SGleb Smirnoff }
9933b3a8eb9SGleb Smirnoff pf_remove_if_empty_ruleset(&pf->alast->ruleset);
9943b3a8eb9SGleb Smirnoff pf->alast = r.anchor;
9953b3a8eb9SGleb Smirnoff } else {
9963b3a8eb9SGleb Smirnoff if (!$2) {
9973b3a8eb9SGleb Smirnoff yyerror("anchors without explicit "
9983b3a8eb9SGleb Smirnoff "rules must specify a name");
9993b3a8eb9SGleb Smirnoff YYERROR;
10003b3a8eb9SGleb Smirnoff }
10013b3a8eb9SGleb Smirnoff }
10023b3a8eb9SGleb Smirnoff r.direction = $3;
10033b3a8eb9SGleb Smirnoff r.quick = $4.quick;
10043b3a8eb9SGleb Smirnoff r.af = $6;
10053b3a8eb9SGleb Smirnoff r.prob = $9.prob;
10063b3a8eb9SGleb Smirnoff r.rtableid = $9.rtableid;
100776c5eeccSKristof Provost r.ridentifier = $9.ridentifier;
10083b3a8eb9SGleb Smirnoff
10093b3a8eb9SGleb Smirnoff if ($9.tag)
10103b3a8eb9SGleb Smirnoff if (strlcpy(r.tagname, $9.tag,
10113b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
10123b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars",
10133b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1);
10143b3a8eb9SGleb Smirnoff YYERROR;
10153b3a8eb9SGleb Smirnoff }
10163b3a8eb9SGleb Smirnoff if ($9.match_tag)
10173b3a8eb9SGleb Smirnoff if (strlcpy(r.match_tagname, $9.match_tag,
10183b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
10193b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars",
10203b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1);
10213b3a8eb9SGleb Smirnoff YYERROR;
10223b3a8eb9SGleb Smirnoff }
10233b3a8eb9SGleb Smirnoff r.match_tag_not = $9.match_tag_not;
10243b3a8eb9SGleb Smirnoff if (rule_label(&r, $9.label))
10253b3a8eb9SGleb Smirnoff YYERROR;
10266fcc8e04SKristof Provost for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
10276fcc8e04SKristof Provost free($9.label[i]);
10283b3a8eb9SGleb Smirnoff r.flags = $9.flags.b1;
10293b3a8eb9SGleb Smirnoff r.flagset = $9.flags.b2;
10303b3a8eb9SGleb Smirnoff if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) {
10313b3a8eb9SGleb Smirnoff yyerror("flags always false");
10323b3a8eb9SGleb Smirnoff YYERROR;
10333b3a8eb9SGleb Smirnoff }
10343b3a8eb9SGleb Smirnoff if ($9.flags.b1 || $9.flags.b2 || $8.src_os) {
10353b3a8eb9SGleb Smirnoff for (proto = $7; proto != NULL &&
10363b3a8eb9SGleb Smirnoff proto->proto != IPPROTO_TCP;
10373b3a8eb9SGleb Smirnoff proto = proto->next)
10383b3a8eb9SGleb Smirnoff ; /* nothing */
10393b3a8eb9SGleb Smirnoff if (proto == NULL && $7 != NULL) {
10403b3a8eb9SGleb Smirnoff if ($9.flags.b1 || $9.flags.b2)
10413b3a8eb9SGleb Smirnoff yyerror(
10423b3a8eb9SGleb Smirnoff "flags only apply to tcp");
10433b3a8eb9SGleb Smirnoff if ($8.src_os)
10443b3a8eb9SGleb Smirnoff yyerror(
10453b3a8eb9SGleb Smirnoff "OS fingerprinting only "
10463b3a8eb9SGleb Smirnoff "applies to tcp");
10473b3a8eb9SGleb Smirnoff YYERROR;
10483b3a8eb9SGleb Smirnoff }
10493b3a8eb9SGleb Smirnoff }
10503b3a8eb9SGleb Smirnoff
10513b3a8eb9SGleb Smirnoff r.tos = $9.tos;
10523b3a8eb9SGleb Smirnoff
10533b3a8eb9SGleb Smirnoff if ($9.keep.action) {
10543b3a8eb9SGleb Smirnoff yyerror("cannot specify state handling "
10553b3a8eb9SGleb Smirnoff "on anchors");
10563b3a8eb9SGleb Smirnoff YYERROR;
10573b3a8eb9SGleb Smirnoff }
10583b3a8eb9SGleb Smirnoff
10593b3a8eb9SGleb Smirnoff if ($9.match_tag)
10603b3a8eb9SGleb Smirnoff if (strlcpy(r.match_tagname, $9.match_tag,
10613b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
10623b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars",
10633b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1);
10643b3a8eb9SGleb Smirnoff YYERROR;
10653b3a8eb9SGleb Smirnoff }
10663b3a8eb9SGleb Smirnoff r.match_tag_not = $9.match_tag_not;
10673e248e0fSKristof Provost if ($9.marker & FOM_PRIO) {
10683e248e0fSKristof Provost if ($9.prio == 0)
10693e248e0fSKristof Provost r.prio = PF_PRIO_ZERO;
10703e248e0fSKristof Provost else
10713e248e0fSKristof Provost r.prio = $9.prio;
10723e248e0fSKristof Provost }
10733e248e0fSKristof Provost if ($9.marker & FOM_SETPRIO) {
10743e248e0fSKristof Provost r.set_prio[0] = $9.set_prio[0];
10753e248e0fSKristof Provost r.set_prio[1] = $9.set_prio[1];
10763e248e0fSKristof Provost r.scrub_flags |= PFSTATE_SETPRIO;
10773e248e0fSKristof Provost }
10783b3a8eb9SGleb Smirnoff
10793b3a8eb9SGleb Smirnoff decide_address_family($8.src.host, &r.af);
10803b3a8eb9SGleb Smirnoff decide_address_family($8.dst.host, &r.af);
10813b3a8eb9SGleb Smirnoff
1082*aeddee83SKajetan Staszkiewicz expand_rule(&r, $5, NULL, NULL, NULL,
10830972294eSKristof Provost $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host,
10840972294eSKristof Provost $8.dst.port, $9.uid, $9.gid, $9.rcv, $9.icmpspec,
10853b3a8eb9SGleb Smirnoff pf->astack[pf->asd + 1] ? pf->alast->name : $2);
10863b3a8eb9SGleb Smirnoff free($2);
10873b3a8eb9SGleb Smirnoff pf->astack[pf->asd + 1] = NULL;
10883b3a8eb9SGleb Smirnoff }
10893b3a8eb9SGleb Smirnoff | NATANCHOR string interface af proto fromto rtable {
1090e9eb0941SKristof Provost struct pfctl_rule r;
10913b3a8eb9SGleb Smirnoff
10923b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_NAT)) {
10933b3a8eb9SGleb Smirnoff free($2);
10943b3a8eb9SGleb Smirnoff YYERROR;
10953b3a8eb9SGleb Smirnoff }
10963b3a8eb9SGleb Smirnoff
1097*aeddee83SKajetan Staszkiewicz pfctl_init_rule(&r);
1098*aeddee83SKajetan Staszkiewicz
10993b3a8eb9SGleb Smirnoff r.action = PF_NAT;
11003b3a8eb9SGleb Smirnoff r.af = $4;
11013b3a8eb9SGleb Smirnoff r.rtableid = $7;
11023b3a8eb9SGleb Smirnoff
11033b3a8eb9SGleb Smirnoff decide_address_family($6.src.host, &r.af);
11043b3a8eb9SGleb Smirnoff decide_address_family($6.dst.host, &r.af);
11053b3a8eb9SGleb Smirnoff
1106*aeddee83SKajetan Staszkiewicz expand_rule(&r, $3, NULL, NULL, NULL,
11070972294eSKristof Provost $5, $6.src_os, $6.src.host, $6.src.port, $6.dst.host,
11080972294eSKristof Provost $6.dst.port, 0, 0, 0, 0, $2);
11093b3a8eb9SGleb Smirnoff free($2);
11103b3a8eb9SGleb Smirnoff }
11113b3a8eb9SGleb Smirnoff | RDRANCHOR string interface af proto fromto rtable {
1112e9eb0941SKristof Provost struct pfctl_rule r;
11133b3a8eb9SGleb Smirnoff
11143b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_NAT)) {
11153b3a8eb9SGleb Smirnoff free($2);
11163b3a8eb9SGleb Smirnoff YYERROR;
11173b3a8eb9SGleb Smirnoff }
11183b3a8eb9SGleb Smirnoff
1119*aeddee83SKajetan Staszkiewicz pfctl_init_rule(&r);
1120*aeddee83SKajetan Staszkiewicz
11213b3a8eb9SGleb Smirnoff r.action = PF_RDR;
11223b3a8eb9SGleb Smirnoff r.af = $4;
11233b3a8eb9SGleb Smirnoff r.rtableid = $7;
11243b3a8eb9SGleb Smirnoff
11253b3a8eb9SGleb Smirnoff decide_address_family($6.src.host, &r.af);
11263b3a8eb9SGleb Smirnoff decide_address_family($6.dst.host, &r.af);
11273b3a8eb9SGleb Smirnoff
11283b3a8eb9SGleb Smirnoff if ($6.src.port != NULL) {
11293b3a8eb9SGleb Smirnoff yyerror("source port parameter not supported"
11303b3a8eb9SGleb Smirnoff " in rdr-anchor");
11313b3a8eb9SGleb Smirnoff YYERROR;
11323b3a8eb9SGleb Smirnoff }
11333b3a8eb9SGleb Smirnoff if ($6.dst.port != NULL) {
11343b3a8eb9SGleb Smirnoff if ($6.dst.port->next != NULL) {
11353b3a8eb9SGleb Smirnoff yyerror("destination port list "
11363b3a8eb9SGleb Smirnoff "expansion not supported in "
11373b3a8eb9SGleb Smirnoff "rdr-anchor");
11383b3a8eb9SGleb Smirnoff YYERROR;
11393b3a8eb9SGleb Smirnoff } else if ($6.dst.port->op != PF_OP_EQ) {
11403b3a8eb9SGleb Smirnoff yyerror("destination port operators"
11413b3a8eb9SGleb Smirnoff " not supported in rdr-anchor");
11423b3a8eb9SGleb Smirnoff YYERROR;
11433b3a8eb9SGleb Smirnoff }
11443b3a8eb9SGleb Smirnoff r.dst.port[0] = $6.dst.port->port[0];
11453b3a8eb9SGleb Smirnoff r.dst.port[1] = $6.dst.port->port[1];
11463b3a8eb9SGleb Smirnoff r.dst.port_op = $6.dst.port->op;
11473b3a8eb9SGleb Smirnoff }
11483b3a8eb9SGleb Smirnoff
1149*aeddee83SKajetan Staszkiewicz expand_rule(&r, $3, NULL, NULL, NULL,
11500972294eSKristof Provost $5, $6.src_os, $6.src.host, $6.src.port, $6.dst.host,
11510972294eSKristof Provost $6.dst.port, 0, 0, 0, 0, $2);
11523b3a8eb9SGleb Smirnoff free($2);
11533b3a8eb9SGleb Smirnoff }
11543b3a8eb9SGleb Smirnoff | BINATANCHOR string interface af proto fromto rtable {
1155e9eb0941SKristof Provost struct pfctl_rule r;
11563b3a8eb9SGleb Smirnoff
11573b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_NAT)) {
11583b3a8eb9SGleb Smirnoff free($2);
11593b3a8eb9SGleb Smirnoff YYERROR;
11603b3a8eb9SGleb Smirnoff }
11613b3a8eb9SGleb Smirnoff
1162*aeddee83SKajetan Staszkiewicz pfctl_init_rule(&r);
1163*aeddee83SKajetan Staszkiewicz
11643b3a8eb9SGleb Smirnoff r.action = PF_BINAT;
11653b3a8eb9SGleb Smirnoff r.af = $4;
11663b3a8eb9SGleb Smirnoff r.rtableid = $7;
11673b3a8eb9SGleb Smirnoff if ($5 != NULL) {
11683b3a8eb9SGleb Smirnoff if ($5->next != NULL) {
11693b3a8eb9SGleb Smirnoff yyerror("proto list expansion"
11703b3a8eb9SGleb Smirnoff " not supported in binat-anchor");
11713b3a8eb9SGleb Smirnoff YYERROR;
11723b3a8eb9SGleb Smirnoff }
11733b3a8eb9SGleb Smirnoff r.proto = $5->proto;
11743b3a8eb9SGleb Smirnoff free($5);
11753b3a8eb9SGleb Smirnoff }
11763b3a8eb9SGleb Smirnoff
11773b3a8eb9SGleb Smirnoff if ($6.src.host != NULL || $6.src.port != NULL ||
11783b3a8eb9SGleb Smirnoff $6.dst.host != NULL || $6.dst.port != NULL) {
11793b3a8eb9SGleb Smirnoff yyerror("fromto parameter not supported"
11803b3a8eb9SGleb Smirnoff " in binat-anchor");
11813b3a8eb9SGleb Smirnoff YYERROR;
11823b3a8eb9SGleb Smirnoff }
11833b3a8eb9SGleb Smirnoff
11843b3a8eb9SGleb Smirnoff decide_address_family($6.src.host, &r.af);
11853b3a8eb9SGleb Smirnoff decide_address_family($6.dst.host, &r.af);
11863b3a8eb9SGleb Smirnoff
11870d71f9f3SKristof Provost pfctl_append_rule(pf, &r, $2);
11883b3a8eb9SGleb Smirnoff free($2);
11893b3a8eb9SGleb Smirnoff }
11903b3a8eb9SGleb Smirnoff ;
11913b3a8eb9SGleb Smirnoff
11923b3a8eb9SGleb Smirnoff loadrule : LOAD ANCHOR string FROM string {
11933b3a8eb9SGleb Smirnoff struct loadanchors *loadanchor;
11943b3a8eb9SGleb Smirnoff
11953b3a8eb9SGleb Smirnoff if (strlen(pf->anchor->name) + 1 +
11963b3a8eb9SGleb Smirnoff strlen($3) >= MAXPATHLEN) {
11973b3a8eb9SGleb Smirnoff yyerror("anchorname %s too long, max %u\n",
11983b3a8eb9SGleb Smirnoff $3, MAXPATHLEN - 1);
11993b3a8eb9SGleb Smirnoff free($3);
12003b3a8eb9SGleb Smirnoff YYERROR;
12013b3a8eb9SGleb Smirnoff }
12023b3a8eb9SGleb Smirnoff loadanchor = calloc(1, sizeof(struct loadanchors));
12033b3a8eb9SGleb Smirnoff if (loadanchor == NULL)
12043b3a8eb9SGleb Smirnoff err(1, "loadrule: calloc");
12053b3a8eb9SGleb Smirnoff if ((loadanchor->anchorname = malloc(MAXPATHLEN)) ==
12063b3a8eb9SGleb Smirnoff NULL)
12073b3a8eb9SGleb Smirnoff err(1, "loadrule: malloc");
12083b3a8eb9SGleb Smirnoff if (pf->anchor->name[0])
12093b3a8eb9SGleb Smirnoff snprintf(loadanchor->anchorname, MAXPATHLEN,
12103b3a8eb9SGleb Smirnoff "%s/%s", pf->anchor->name, $3);
12113b3a8eb9SGleb Smirnoff else
12123b3a8eb9SGleb Smirnoff strlcpy(loadanchor->anchorname, $3, MAXPATHLEN);
12133b3a8eb9SGleb Smirnoff if ((loadanchor->filename = strdup($5)) == NULL)
12143b3a8eb9SGleb Smirnoff err(1, "loadrule: strdup");
12153b3a8eb9SGleb Smirnoff
12163b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor,
12173b3a8eb9SGleb Smirnoff entries);
12183b3a8eb9SGleb Smirnoff
12193b3a8eb9SGleb Smirnoff free($3);
12203b3a8eb9SGleb Smirnoff free($5);
12213b3a8eb9SGleb Smirnoff };
12223b3a8eb9SGleb Smirnoff
12233b3a8eb9SGleb Smirnoff scrubaction : no SCRUB {
12243b3a8eb9SGleb Smirnoff $$.b2 = $$.w = 0;
12253b3a8eb9SGleb Smirnoff if ($1)
12263b3a8eb9SGleb Smirnoff $$.b1 = PF_NOSCRUB;
12273b3a8eb9SGleb Smirnoff else
12283b3a8eb9SGleb Smirnoff $$.b1 = PF_SCRUB;
12293b3a8eb9SGleb Smirnoff }
12303b3a8eb9SGleb Smirnoff ;
12313b3a8eb9SGleb Smirnoff
12328a8af942SKristof Provost etherrule : ETHER action dir quick interface bridge etherproto etherfromto l3fromto etherfilter_opts
12332b29ceb8SKristof Provost {
12342b29ceb8SKristof Provost struct pfctl_eth_rule r;
12352b29ceb8SKristof Provost
12362b29ceb8SKristof Provost bzero(&r, sizeof(r));
12372b29ceb8SKristof Provost
12382b29ceb8SKristof Provost if (check_rulestate(PFCTL_STATE_ETHER))
12392b29ceb8SKristof Provost YYERROR;
12402b29ceb8SKristof Provost
12412b29ceb8SKristof Provost r.action = $2.b1;
12422b29ceb8SKristof Provost r.direction = $3;
12432b29ceb8SKristof Provost r.quick = $4.quick;
12448a8af942SKristof Provost if ($10.tag != NULL)
1245dc3ee89cSKristof Provost strlcpy(r.tagname, $10.tag, sizeof(r.tagname));
12468a8af942SKristof Provost if ($10.match_tag)
12478a8af942SKristof Provost if (strlcpy(r.match_tagname, $10.match_tag,
12481f61367fSKristof Provost PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
12491f61367fSKristof Provost yyerror("tag too long, max %u chars",
12501f61367fSKristof Provost PF_TAG_NAME_SIZE - 1);
12511f61367fSKristof Provost YYERROR;
12521f61367fSKristof Provost }
12538a8af942SKristof Provost r.match_tag_not = $10.match_tag_not;
12548a8af942SKristof Provost if ($10.queues.qname != NULL)
1255dc3ee89cSKristof Provost strlcpy(r.qname, $10.queues.qname, sizeof(r.qname));
12568a8af942SKristof Provost r.dnpipe = $10.dnpipe;
12578a8af942SKristof Provost r.dnflags = $10.free_flags;
1258ef661d4aSChristian McDonald if (eth_rule_label(&r, $10.label))
1259ef661d4aSChristian McDonald YYERROR;
1260ef661d4aSChristian McDonald for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
1261ef661d4aSChristian McDonald free($10.label[i]);
1262ef661d4aSChristian McDonald r.ridentifier = $10.ridentifier;
12632b29ceb8SKristof Provost
12648a8af942SKristof Provost expand_eth_rule(&r, $5, $7, $8.src, $8.dst,
12658a8af942SKristof Provost $9.src.host, $9.dst.host, $6, "");
1266c5131afeSKristof Provost }
1267c5131afeSKristof Provost ;
1268c5131afeSKristof Provost
1269c5131afeSKristof Provost etherpfa_anchorlist : /* empty */
1270c5131afeSKristof Provost | etherpfa_anchorlist '\n'
1271c5131afeSKristof Provost | etherpfa_anchorlist etherrule '\n'
1272c5131afeSKristof Provost | etherpfa_anchorlist etheranchorrule '\n'
1273c5131afeSKristof Provost ;
1274c5131afeSKristof Provost
1275c5131afeSKristof Provost etherpfa_anchor : '{'
1276c5131afeSKristof Provost {
1277c5131afeSKristof Provost char ta[PF_ANCHOR_NAME_SIZE];
1278c5131afeSKristof Provost struct pfctl_eth_ruleset *rs;
1279c5131afeSKristof Provost
1280c5131afeSKristof Provost /* steping into a brace anchor */
1281c5131afeSKristof Provost pf->asd++;
1282c5131afeSKristof Provost pf->bn++;
1283c5131afeSKristof Provost
1284c5131afeSKristof Provost /* create a holding ruleset in the root */
1285c5131afeSKristof Provost snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn);
1286c5131afeSKristof Provost rs = pf_find_or_create_eth_ruleset(ta);
1287c5131afeSKristof Provost if (rs == NULL)
1288c5131afeSKristof Provost err(1, "etherpfa_anchor: pf_find_or_create_eth_ruleset");
1289c5131afeSKristof Provost pf->eastack[pf->asd] = rs->anchor;
1290c5131afeSKristof Provost pf->eanchor = rs->anchor;
1291c5131afeSKristof Provost } '\n' etherpfa_anchorlist '}'
1292c5131afeSKristof Provost {
1293c5131afeSKristof Provost pf->ealast = pf->eanchor;
1294c5131afeSKristof Provost pf->asd--;
1295c5131afeSKristof Provost pf->eanchor = pf->eastack[pf->asd];
1296c5131afeSKristof Provost }
1297c5131afeSKristof Provost | /* empty */
1298c5131afeSKristof Provost ;
1299c5131afeSKristof Provost
13008a42005dSKristof Provost etheranchorrule : ETHER ANCHOR anchorname dir quick interface etherproto etherfromto l3fromto etherpfa_anchor
1301c5131afeSKristof Provost {
1302c5131afeSKristof Provost struct pfctl_eth_rule r;
1303c5131afeSKristof Provost
1304c5131afeSKristof Provost if (check_rulestate(PFCTL_STATE_ETHER)) {
1305c5131afeSKristof Provost free($3);
1306c5131afeSKristof Provost YYERROR;
1307c5131afeSKristof Provost }
1308c5131afeSKristof Provost
1309c5131afeSKristof Provost if ($3 && ($3[0] == '_' || strstr($3, "/_") != NULL)) {
1310c5131afeSKristof Provost free($3);
1311c5131afeSKristof Provost yyerror("anchor names beginning with '_' "
1312c5131afeSKristof Provost "are reserved for internal use");
1313c5131afeSKristof Provost YYERROR;
1314c5131afeSKristof Provost }
1315c5131afeSKristof Provost
1316c5131afeSKristof Provost memset(&r, 0, sizeof(r));
1317c5131afeSKristof Provost if (pf->eastack[pf->asd + 1]) {
1318cfa1a130SKristof Provost if ($3 && strchr($3, '/') != NULL) {
1319cfa1a130SKristof Provost free($3);
1320cfa1a130SKristof Provost yyerror("anchor paths containing '/' "
1321cfa1a130SKristof Provost "cannot be used for inline anchors.");
1322cfa1a130SKristof Provost YYERROR;
1323cfa1a130SKristof Provost }
1324cfa1a130SKristof Provost
1325cfa1a130SKristof Provost /* Move inline rules into relative location. */
1326c5131afeSKristof Provost pfctl_eth_anchor_setup(pf, &r,
1327c5131afeSKristof Provost &pf->eastack[pf->asd]->ruleset,
1328c5131afeSKristof Provost $3 ? $3 : pf->ealast->name);
1329c5131afeSKristof Provost if (r.anchor == NULL)
1330c5131afeSKristof Provost err(1, "etheranchorrule: unable to "
1331c5131afeSKristof Provost "create ruleset");
1332c5131afeSKristof Provost
1333c5131afeSKristof Provost if (pf->ealast != r.anchor) {
1334c5131afeSKristof Provost if (r.anchor->match) {
1335c5131afeSKristof Provost yyerror("inline anchor '%s' "
1336c5131afeSKristof Provost "already exists",
1337c5131afeSKristof Provost r.anchor->name);
1338c5131afeSKristof Provost YYERROR;
1339c5131afeSKristof Provost }
1340c5131afeSKristof Provost mv_eth_rules(&pf->ealast->ruleset,
1341c5131afeSKristof Provost &r.anchor->ruleset);
1342c5131afeSKristof Provost }
1343c5131afeSKristof Provost pf_remove_if_empty_eth_ruleset(&pf->ealast->ruleset);
1344c5131afeSKristof Provost pf->ealast = r.anchor;
1345c5131afeSKristof Provost } else {
1346c5131afeSKristof Provost if (!$3) {
1347c5131afeSKristof Provost yyerror("anchors without explicit "
1348c5131afeSKristof Provost "rules must specify a name");
1349c5131afeSKristof Provost YYERROR;
1350c5131afeSKristof Provost }
1351c5131afeSKristof Provost }
1352c5131afeSKristof Provost
1353c5131afeSKristof Provost r.direction = $4;
1354c5131afeSKristof Provost r.quick = $5.quick;
1355c5131afeSKristof Provost
1356c5131afeSKristof Provost expand_eth_rule(&r, $6, $7, $8.src, $8.dst,
13578a8af942SKristof Provost $9.src.host, $9.dst.host, NULL,
1358c5131afeSKristof Provost pf->eastack[pf->asd + 1] ? pf->ealast->name : $3);
1359c5131afeSKristof Provost
1360c5131afeSKristof Provost free($3);
1361c5131afeSKristof Provost pf->eastack[pf->asd + 1] = NULL;
13622b29ceb8SKristof Provost }
13632b29ceb8SKristof Provost ;
13642b29ceb8SKristof Provost
13652b29ceb8SKristof Provost etherfilter_opts : {
13662b29ceb8SKristof Provost bzero(&filter_opts, sizeof filter_opts);
13672b29ceb8SKristof Provost }
13682b29ceb8SKristof Provost etherfilter_opts_l
13692b29ceb8SKristof Provost { $$ = filter_opts; }
13702b29ceb8SKristof Provost | /* empty */ {
13712b29ceb8SKristof Provost bzero(&filter_opts, sizeof filter_opts);
13722b29ceb8SKristof Provost $$ = filter_opts;
13732b29ceb8SKristof Provost }
13742b29ceb8SKristof Provost ;
13752b29ceb8SKristof Provost
13762b29ceb8SKristof Provost etherfilter_opts_l : etherfilter_opts_l etherfilter_opt
13772b29ceb8SKristof Provost | etherfilter_opt
13782b29ceb8SKristof Provost
13792b29ceb8SKristof Provost etherfilter_opt : etherqname {
13802b29ceb8SKristof Provost if (filter_opts.queues.qname) {
13812b29ceb8SKristof Provost yyerror("queue cannot be redefined");
13822b29ceb8SKristof Provost YYERROR;
13832b29ceb8SKristof Provost }
13842b29ceb8SKristof Provost filter_opts.queues = $1;
13852b29ceb8SKristof Provost }
1386ef661d4aSChristian McDonald | RIDENTIFIER number {
1387ef661d4aSChristian McDonald filter_opts.ridentifier = $2;
1388ef661d4aSChristian McDonald }
1389ef661d4aSChristian McDonald | label {
1390ef661d4aSChristian McDonald if (filter_opts.labelcount >= PF_RULE_MAX_LABEL_COUNT) {
1391ef661d4aSChristian McDonald yyerror("label can only be used %d times", PF_RULE_MAX_LABEL_COUNT);
1392ef661d4aSChristian McDonald YYERROR;
1393ef661d4aSChristian McDonald }
1394ef661d4aSChristian McDonald filter_opts.label[filter_opts.labelcount++] = $1;
1395ef661d4aSChristian McDonald }
13962b29ceb8SKristof Provost | TAG string {
13972b29ceb8SKristof Provost filter_opts.tag = $2;
13982b29ceb8SKristof Provost }
13991f61367fSKristof Provost | not TAGGED string {
14001f61367fSKristof Provost filter_opts.match_tag = $3;
14011f61367fSKristof Provost filter_opts.match_tag_not = $1;
14021f61367fSKristof Provost }
1403fb330f39SKristof Provost | DNPIPE number {
1404fb330f39SKristof Provost filter_opts.dnpipe = $2;
1405fb330f39SKristof Provost filter_opts.free_flags |= PFRULE_DN_IS_PIPE;
1406fb330f39SKristof Provost }
1407fb330f39SKristof Provost | DNQUEUE number {
1408fb330f39SKristof Provost filter_opts.dnpipe = $2;
1409fb330f39SKristof Provost filter_opts.free_flags |= PFRULE_DN_IS_QUEUE;
1410fb330f39SKristof Provost }
14112b29ceb8SKristof Provost ;
14122b29ceb8SKristof Provost
14138a8af942SKristof Provost bridge : /* empty */ {
14148a8af942SKristof Provost $$ = NULL;
14158a8af942SKristof Provost }
14168a8af942SKristof Provost | BRIDGE_TO STRING {
14178a8af942SKristof Provost $$ = strdup($2);
14188a8af942SKristof Provost }
14198a8af942SKristof Provost ;
14208a8af942SKristof Provost
14213b3a8eb9SGleb Smirnoff scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts
14223b3a8eb9SGleb Smirnoff {
1423e9eb0941SKristof Provost struct pfctl_rule r;
14243b3a8eb9SGleb Smirnoff
14253b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_SCRUB))
14263b3a8eb9SGleb Smirnoff YYERROR;
14273b3a8eb9SGleb Smirnoff
1428*aeddee83SKajetan Staszkiewicz pfctl_init_rule(&r);
14293b3a8eb9SGleb Smirnoff
14303b3a8eb9SGleb Smirnoff r.action = $1.b1;
14313b3a8eb9SGleb Smirnoff r.direction = $2;
14323b3a8eb9SGleb Smirnoff
14333b3a8eb9SGleb Smirnoff r.log = $3.log;
14343b3a8eb9SGleb Smirnoff r.logif = $3.logif;
14353b3a8eb9SGleb Smirnoff if ($3.quick) {
14363b3a8eb9SGleb Smirnoff yyerror("scrub rules do not support 'quick'");
14373b3a8eb9SGleb Smirnoff YYERROR;
14383b3a8eb9SGleb Smirnoff }
14393b3a8eb9SGleb Smirnoff
14403b3a8eb9SGleb Smirnoff r.af = $5;
14413b3a8eb9SGleb Smirnoff if ($8.nodf)
14423b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_NODF;
14433b3a8eb9SGleb Smirnoff if ($8.randomid)
14443b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_RANDOMID;
14453b3a8eb9SGleb Smirnoff if ($8.reassemble_tcp) {
14463b3a8eb9SGleb Smirnoff if (r.direction != PF_INOUT) {
14473b3a8eb9SGleb Smirnoff yyerror("reassemble tcp rules can not "
14483b3a8eb9SGleb Smirnoff "specify direction");
14493b3a8eb9SGleb Smirnoff YYERROR;
14503b3a8eb9SGleb Smirnoff }
14513b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_REASSEMBLE_TCP;
14523b3a8eb9SGleb Smirnoff }
14533b3a8eb9SGleb Smirnoff if ($8.minttl)
14543b3a8eb9SGleb Smirnoff r.min_ttl = $8.minttl;
14553b3a8eb9SGleb Smirnoff if ($8.maxmss)
14563b3a8eb9SGleb Smirnoff r.max_mss = $8.maxmss;
145739282ef3SKajetan Staszkiewicz if ($8.marker & FOM_SETTOS) {
14583b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_SET_TOS;
14593b3a8eb9SGleb Smirnoff r.set_tos = $8.settos;
14603b3a8eb9SGleb Smirnoff }
14613b3a8eb9SGleb Smirnoff if ($8.fragcache)
14623b3a8eb9SGleb Smirnoff r.rule_flag |= $8.fragcache;
14633b3a8eb9SGleb Smirnoff if ($8.match_tag)
14643b3a8eb9SGleb Smirnoff if (strlcpy(r.match_tagname, $8.match_tag,
14653b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
14663b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars",
14673b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1);
14683b3a8eb9SGleb Smirnoff YYERROR;
14693b3a8eb9SGleb Smirnoff }
14703b3a8eb9SGleb Smirnoff r.match_tag_not = $8.match_tag_not;
14713b3a8eb9SGleb Smirnoff r.rtableid = $8.rtableid;
14723b3a8eb9SGleb Smirnoff
1473*aeddee83SKajetan Staszkiewicz expand_rule(&r, $4, NULL, NULL, NULL,
14740972294eSKristof Provost $6, $7.src_os, $7.src.host, $7.src.port, $7.dst.host,
14750972294eSKristof Provost $7.dst.port, NULL, NULL, NULL, NULL, "");
14763b3a8eb9SGleb Smirnoff }
14773b3a8eb9SGleb Smirnoff ;
14783b3a8eb9SGleb Smirnoff
14793b3a8eb9SGleb Smirnoff scrub_opts : {
14803b3a8eb9SGleb Smirnoff bzero(&scrub_opts, sizeof scrub_opts);
14813b3a8eb9SGleb Smirnoff scrub_opts.rtableid = -1;
14823b3a8eb9SGleb Smirnoff }
14833b3a8eb9SGleb Smirnoff scrub_opts_l
14843b3a8eb9SGleb Smirnoff { $$ = scrub_opts; }
14853b3a8eb9SGleb Smirnoff | /* empty */ {
14863b3a8eb9SGleb Smirnoff bzero(&scrub_opts, sizeof scrub_opts);
14873b3a8eb9SGleb Smirnoff scrub_opts.rtableid = -1;
14883b3a8eb9SGleb Smirnoff $$ = scrub_opts;
14893b3a8eb9SGleb Smirnoff }
14903b3a8eb9SGleb Smirnoff ;
14913b3a8eb9SGleb Smirnoff
149239282ef3SKajetan Staszkiewicz scrub_opts_l : scrub_opts_l comma scrub_opt
14933b3a8eb9SGleb Smirnoff | scrub_opt
14943b3a8eb9SGleb Smirnoff ;
14953b3a8eb9SGleb Smirnoff
14963b3a8eb9SGleb Smirnoff scrub_opt : NODF {
14973b3a8eb9SGleb Smirnoff if (scrub_opts.nodf) {
14983b3a8eb9SGleb Smirnoff yyerror("no-df cannot be respecified");
14993b3a8eb9SGleb Smirnoff YYERROR;
15003b3a8eb9SGleb Smirnoff }
15013b3a8eb9SGleb Smirnoff scrub_opts.nodf = 1;
15023b3a8eb9SGleb Smirnoff }
15033b3a8eb9SGleb Smirnoff | MINTTL NUMBER {
150439282ef3SKajetan Staszkiewicz if (scrub_opts.marker & FOM_MINTTL) {
15053b3a8eb9SGleb Smirnoff yyerror("min-ttl cannot be respecified");
15063b3a8eb9SGleb Smirnoff YYERROR;
15073b3a8eb9SGleb Smirnoff }
15083b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > 255) {
15093b3a8eb9SGleb Smirnoff yyerror("illegal min-ttl value %d", $2);
15103b3a8eb9SGleb Smirnoff YYERROR;
15113b3a8eb9SGleb Smirnoff }
151239282ef3SKajetan Staszkiewicz scrub_opts.marker |= FOM_MINTTL;
15133b3a8eb9SGleb Smirnoff scrub_opts.minttl = $2;
15143b3a8eb9SGleb Smirnoff }
15153b3a8eb9SGleb Smirnoff | MAXMSS NUMBER {
151639282ef3SKajetan Staszkiewicz if (scrub_opts.marker & FOM_MAXMSS) {
15173b3a8eb9SGleb Smirnoff yyerror("max-mss cannot be respecified");
15183b3a8eb9SGleb Smirnoff YYERROR;
15193b3a8eb9SGleb Smirnoff }
15203b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > 65535) {
15213b3a8eb9SGleb Smirnoff yyerror("illegal max-mss value %d", $2);
15223b3a8eb9SGleb Smirnoff YYERROR;
15233b3a8eb9SGleb Smirnoff }
152439282ef3SKajetan Staszkiewicz scrub_opts.marker |= FOM_MAXMSS;
15253b3a8eb9SGleb Smirnoff scrub_opts.maxmss = $2;
15263b3a8eb9SGleb Smirnoff }
15273b3a8eb9SGleb Smirnoff | SETTOS tos {
152839282ef3SKajetan Staszkiewicz if (scrub_opts.marker & FOM_SETTOS) {
15293b3a8eb9SGleb Smirnoff yyerror("set-tos cannot be respecified");
15303b3a8eb9SGleb Smirnoff YYERROR;
15313b3a8eb9SGleb Smirnoff }
153239282ef3SKajetan Staszkiewicz scrub_opts.marker |= FOM_SETTOS;
15333b3a8eb9SGleb Smirnoff scrub_opts.settos = $2;
15343b3a8eb9SGleb Smirnoff }
15353b3a8eb9SGleb Smirnoff | fragcache {
153639282ef3SKajetan Staszkiewicz if (scrub_opts.marker & FOM_FRAGCACHE) {
15373b3a8eb9SGleb Smirnoff yyerror("fragcache cannot be respecified");
15383b3a8eb9SGleb Smirnoff YYERROR;
15393b3a8eb9SGleb Smirnoff }
154039282ef3SKajetan Staszkiewicz scrub_opts.marker |= FOM_FRAGCACHE;
15413b3a8eb9SGleb Smirnoff scrub_opts.fragcache = $1;
15423b3a8eb9SGleb Smirnoff }
15433b3a8eb9SGleb Smirnoff | REASSEMBLE STRING {
15443b3a8eb9SGleb Smirnoff if (strcasecmp($2, "tcp") != 0) {
15453b3a8eb9SGleb Smirnoff yyerror("scrub reassemble supports only tcp, "
15463b3a8eb9SGleb Smirnoff "not '%s'", $2);
15473b3a8eb9SGleb Smirnoff free($2);
15483b3a8eb9SGleb Smirnoff YYERROR;
15493b3a8eb9SGleb Smirnoff }
15503b3a8eb9SGleb Smirnoff free($2);
15513b3a8eb9SGleb Smirnoff if (scrub_opts.reassemble_tcp) {
15523b3a8eb9SGleb Smirnoff yyerror("reassemble tcp cannot be respecified");
15533b3a8eb9SGleb Smirnoff YYERROR;
15543b3a8eb9SGleb Smirnoff }
15553b3a8eb9SGleb Smirnoff scrub_opts.reassemble_tcp = 1;
15563b3a8eb9SGleb Smirnoff }
15573b3a8eb9SGleb Smirnoff | RANDOMID {
15583b3a8eb9SGleb Smirnoff if (scrub_opts.randomid) {
15593b3a8eb9SGleb Smirnoff yyerror("random-id cannot be respecified");
15603b3a8eb9SGleb Smirnoff YYERROR;
15613b3a8eb9SGleb Smirnoff }
15623b3a8eb9SGleb Smirnoff scrub_opts.randomid = 1;
15633b3a8eb9SGleb Smirnoff }
15643b3a8eb9SGleb Smirnoff | RTABLE NUMBER {
15653b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > rt_tableid_max()) {
15663b3a8eb9SGleb Smirnoff yyerror("invalid rtable id");
15673b3a8eb9SGleb Smirnoff YYERROR;
15683b3a8eb9SGleb Smirnoff }
15693b3a8eb9SGleb Smirnoff scrub_opts.rtableid = $2;
15703b3a8eb9SGleb Smirnoff }
15713b3a8eb9SGleb Smirnoff | not TAGGED string {
15723b3a8eb9SGleb Smirnoff scrub_opts.match_tag = $3;
15733b3a8eb9SGleb Smirnoff scrub_opts.match_tag_not = $1;
15743b3a8eb9SGleb Smirnoff }
15753b3a8eb9SGleb Smirnoff ;
15763b3a8eb9SGleb Smirnoff
15773b3a8eb9SGleb Smirnoff fragcache : FRAGMENT REASSEMBLE { $$ = 0; /* default */ }
157857e047e5SKristof Provost | FRAGMENT NO REASSEMBLE { $$ = PFRULE_FRAGMENT_NOREASS; }
15793b3a8eb9SGleb Smirnoff ;
15803b3a8eb9SGleb Smirnoff
15813b3a8eb9SGleb Smirnoff antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts {
1582e9eb0941SKristof Provost struct pfctl_rule r;
15833b3a8eb9SGleb Smirnoff struct node_host *h = NULL, *hh;
15843b3a8eb9SGleb Smirnoff struct node_if *i, *j;
15853b3a8eb9SGleb Smirnoff
15863b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_FILTER))
15873b3a8eb9SGleb Smirnoff YYERROR;
15883b3a8eb9SGleb Smirnoff
15893b3a8eb9SGleb Smirnoff for (i = $3; i; i = i->next) {
1590*aeddee83SKajetan Staszkiewicz pfctl_init_rule(&r);
15913b3a8eb9SGleb Smirnoff
15923b3a8eb9SGleb Smirnoff r.action = PF_DROP;
15933b3a8eb9SGleb Smirnoff r.direction = PF_IN;
15943b3a8eb9SGleb Smirnoff r.log = $2.log;
15953b3a8eb9SGleb Smirnoff r.logif = $2.logif;
15963b3a8eb9SGleb Smirnoff r.quick = $2.quick;
15973b3a8eb9SGleb Smirnoff r.af = $4;
159876c5eeccSKristof Provost r.ridentifier = $5.ridentifier;
15993b3a8eb9SGleb Smirnoff if (rule_label(&r, $5.label))
16003b3a8eb9SGleb Smirnoff YYERROR;
16013b3a8eb9SGleb Smirnoff r.rtableid = $5.rtableid;
16023b3a8eb9SGleb Smirnoff j = calloc(1, sizeof(struct node_if));
16033b3a8eb9SGleb Smirnoff if (j == NULL)
16043b3a8eb9SGleb Smirnoff err(1, "antispoof: calloc");
16053b3a8eb9SGleb Smirnoff if (strlcpy(j->ifname, i->ifname,
16063b3a8eb9SGleb Smirnoff sizeof(j->ifname)) >= sizeof(j->ifname)) {
16073b3a8eb9SGleb Smirnoff free(j);
16083b3a8eb9SGleb Smirnoff yyerror("interface name too long");
16093b3a8eb9SGleb Smirnoff YYERROR;
16103b3a8eb9SGleb Smirnoff }
16113b3a8eb9SGleb Smirnoff j->not = 1;
16123b3a8eb9SGleb Smirnoff if (i->dynamic) {
16133b3a8eb9SGleb Smirnoff h = calloc(1, sizeof(*h));
16143b3a8eb9SGleb Smirnoff if (h == NULL)
16153b3a8eb9SGleb Smirnoff err(1, "address: calloc");
16163b3a8eb9SGleb Smirnoff h->addr.type = PF_ADDR_DYNIFTL;
16173b3a8eb9SGleb Smirnoff set_ipmask(h, 128);
16183b3a8eb9SGleb Smirnoff if (strlcpy(h->addr.v.ifname, i->ifname,
16193b3a8eb9SGleb Smirnoff sizeof(h->addr.v.ifname)) >=
16203b3a8eb9SGleb Smirnoff sizeof(h->addr.v.ifname)) {
16213b3a8eb9SGleb Smirnoff free(h);
16223b3a8eb9SGleb Smirnoff yyerror(
16233b3a8eb9SGleb Smirnoff "interface name too long");
16243b3a8eb9SGleb Smirnoff YYERROR;
16253b3a8eb9SGleb Smirnoff }
16263b3a8eb9SGleb Smirnoff hh = malloc(sizeof(*hh));
16273b3a8eb9SGleb Smirnoff if (hh == NULL)
16283b3a8eb9SGleb Smirnoff err(1, "address: malloc");
16293b3a8eb9SGleb Smirnoff bcopy(h, hh, sizeof(*hh));
16303b3a8eb9SGleb Smirnoff h->addr.iflags = PFI_AFLAG_NETWORK;
16313b3a8eb9SGleb Smirnoff } else {
16323b3a8eb9SGleb Smirnoff h = ifa_lookup(j->ifname,
16333b3a8eb9SGleb Smirnoff PFI_AFLAG_NETWORK);
16343b3a8eb9SGleb Smirnoff hh = NULL;
16353b3a8eb9SGleb Smirnoff }
16363b3a8eb9SGleb Smirnoff
16373b3a8eb9SGleb Smirnoff if (h != NULL)
1638*aeddee83SKajetan Staszkiewicz expand_rule(&r, j, NULL, NULL, NULL,
1639*aeddee83SKajetan Staszkiewicz NULL, NULL, h, NULL, NULL, NULL,
1640*aeddee83SKajetan Staszkiewicz NULL, NULL, NULL, NULL, "");
16413b3a8eb9SGleb Smirnoff
16423b3a8eb9SGleb Smirnoff if ((i->ifa_flags & IFF_LOOPBACK) == 0) {
16433b3a8eb9SGleb Smirnoff bzero(&r, sizeof(r));
16443b3a8eb9SGleb Smirnoff
16453b3a8eb9SGleb Smirnoff r.action = PF_DROP;
16463b3a8eb9SGleb Smirnoff r.direction = PF_IN;
16473b3a8eb9SGleb Smirnoff r.log = $2.log;
16483b3a8eb9SGleb Smirnoff r.logif = $2.logif;
16493b3a8eb9SGleb Smirnoff r.quick = $2.quick;
16503b3a8eb9SGleb Smirnoff r.af = $4;
165176c5eeccSKristof Provost r.ridentifier = $5.ridentifier;
16523b3a8eb9SGleb Smirnoff if (rule_label(&r, $5.label))
16533b3a8eb9SGleb Smirnoff YYERROR;
16543b3a8eb9SGleb Smirnoff r.rtableid = $5.rtableid;
16553b3a8eb9SGleb Smirnoff if (hh != NULL)
16563b3a8eb9SGleb Smirnoff h = hh;
16573b3a8eb9SGleb Smirnoff else
16583b3a8eb9SGleb Smirnoff h = ifa_lookup(i->ifname, 0);
16593b3a8eb9SGleb Smirnoff if (h != NULL)
1660*aeddee83SKajetan Staszkiewicz expand_rule(&r, NULL, NULL,
1661*aeddee83SKajetan Staszkiewicz NULL, NULL, NULL, NULL, h,
1662*aeddee83SKajetan Staszkiewicz NULL, NULL, NULL, NULL,
1663*aeddee83SKajetan Staszkiewicz NULL, NULL, NULL, "");
16643b3a8eb9SGleb Smirnoff } else
16653b3a8eb9SGleb Smirnoff free(hh);
16663b3a8eb9SGleb Smirnoff }
16676fcc8e04SKristof Provost for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
16686fcc8e04SKristof Provost free($5.label[i]);
16693b3a8eb9SGleb Smirnoff }
16703b3a8eb9SGleb Smirnoff ;
16713b3a8eb9SGleb Smirnoff
16723b3a8eb9SGleb Smirnoff antispoof_ifspc : FOR antispoof_if { $$ = $2; }
16733b3a8eb9SGleb Smirnoff | FOR '{' optnl antispoof_iflst '}' { $$ = $4; }
16743b3a8eb9SGleb Smirnoff ;
16753b3a8eb9SGleb Smirnoff
16763b3a8eb9SGleb Smirnoff antispoof_iflst : antispoof_if optnl { $$ = $1; }
16773b3a8eb9SGleb Smirnoff | antispoof_iflst comma antispoof_if optnl {
16783b3a8eb9SGleb Smirnoff $1->tail->next = $3;
16793b3a8eb9SGleb Smirnoff $1->tail = $3;
16803b3a8eb9SGleb Smirnoff $$ = $1;
16813b3a8eb9SGleb Smirnoff }
16823b3a8eb9SGleb Smirnoff ;
16833b3a8eb9SGleb Smirnoff
16843b3a8eb9SGleb Smirnoff antispoof_if : if_item { $$ = $1; }
16853b3a8eb9SGleb Smirnoff | '(' if_item ')' {
16863b3a8eb9SGleb Smirnoff $2->dynamic = 1;
16873b3a8eb9SGleb Smirnoff $$ = $2;
16883b3a8eb9SGleb Smirnoff }
16893b3a8eb9SGleb Smirnoff ;
16903b3a8eb9SGleb Smirnoff
16913b3a8eb9SGleb Smirnoff antispoof_opts : {
16923b3a8eb9SGleb Smirnoff bzero(&antispoof_opts, sizeof antispoof_opts);
16933b3a8eb9SGleb Smirnoff antispoof_opts.rtableid = -1;
16943b3a8eb9SGleb Smirnoff }
16953b3a8eb9SGleb Smirnoff antispoof_opts_l
16963b3a8eb9SGleb Smirnoff { $$ = antispoof_opts; }
16973b3a8eb9SGleb Smirnoff | /* empty */ {
16983b3a8eb9SGleb Smirnoff bzero(&antispoof_opts, sizeof antispoof_opts);
16993b3a8eb9SGleb Smirnoff antispoof_opts.rtableid = -1;
17003b3a8eb9SGleb Smirnoff $$ = antispoof_opts;
17013b3a8eb9SGleb Smirnoff }
17023b3a8eb9SGleb Smirnoff ;
17033b3a8eb9SGleb Smirnoff
17043b3a8eb9SGleb Smirnoff antispoof_opts_l : antispoof_opts_l antispoof_opt
17053b3a8eb9SGleb Smirnoff | antispoof_opt
17063b3a8eb9SGleb Smirnoff ;
17073b3a8eb9SGleb Smirnoff
17083b3a8eb9SGleb Smirnoff antispoof_opt : label {
17096fcc8e04SKristof Provost if (antispoof_opts.labelcount >= PF_RULE_MAX_LABEL_COUNT) {
17106fcc8e04SKristof Provost yyerror("label can only be used %d times", PF_RULE_MAX_LABEL_COUNT);
17113b3a8eb9SGleb Smirnoff YYERROR;
17123b3a8eb9SGleb Smirnoff }
17136fcc8e04SKristof Provost antispoof_opts.label[antispoof_opts.labelcount++] = $1;
17143b3a8eb9SGleb Smirnoff }
171576c5eeccSKristof Provost | RIDENTIFIER number {
171676c5eeccSKristof Provost antispoof_opts.ridentifier = $2;
171776c5eeccSKristof Provost }
17183b3a8eb9SGleb Smirnoff | RTABLE NUMBER {
17193b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > rt_tableid_max()) {
17203b3a8eb9SGleb Smirnoff yyerror("invalid rtable id");
17213b3a8eb9SGleb Smirnoff YYERROR;
17223b3a8eb9SGleb Smirnoff }
17233b3a8eb9SGleb Smirnoff antispoof_opts.rtableid = $2;
17243b3a8eb9SGleb Smirnoff }
17253b3a8eb9SGleb Smirnoff ;
17263b3a8eb9SGleb Smirnoff
17273b3a8eb9SGleb Smirnoff not : '!' { $$ = 1; }
17283b3a8eb9SGleb Smirnoff | /* empty */ { $$ = 0; }
17293b3a8eb9SGleb Smirnoff ;
17303b3a8eb9SGleb Smirnoff
17313b3a8eb9SGleb Smirnoff tabledef : TABLE '<' STRING '>' table_opts {
17323b3a8eb9SGleb Smirnoff struct node_host *h, *nh;
17333b3a8eb9SGleb Smirnoff struct node_tinit *ti, *nti;
17343b3a8eb9SGleb Smirnoff
17353b3a8eb9SGleb Smirnoff if (strlen($3) >= PF_TABLE_NAME_SIZE) {
17363b3a8eb9SGleb Smirnoff yyerror("table name too long, max %d chars",
17373b3a8eb9SGleb Smirnoff PF_TABLE_NAME_SIZE - 1);
17383b3a8eb9SGleb Smirnoff free($3);
17393b3a8eb9SGleb Smirnoff YYERROR;
17403b3a8eb9SGleb Smirnoff }
17413b3a8eb9SGleb Smirnoff if (pf->loadopt & PFCTL_FLAG_TABLE)
17423b3a8eb9SGleb Smirnoff if (process_tabledef($3, &$5)) {
17433b3a8eb9SGleb Smirnoff free($3);
17443b3a8eb9SGleb Smirnoff YYERROR;
17453b3a8eb9SGleb Smirnoff }
17463b3a8eb9SGleb Smirnoff free($3);
17473b3a8eb9SGleb Smirnoff for (ti = SIMPLEQ_FIRST(&$5.init_nodes);
17483b3a8eb9SGleb Smirnoff ti != SIMPLEQ_END(&$5.init_nodes); ti = nti) {
17493b3a8eb9SGleb Smirnoff if (ti->file)
17503b3a8eb9SGleb Smirnoff free(ti->file);
17513b3a8eb9SGleb Smirnoff for (h = ti->host; h != NULL; h = nh) {
17523b3a8eb9SGleb Smirnoff nh = h->next;
17533b3a8eb9SGleb Smirnoff free(h);
17543b3a8eb9SGleb Smirnoff }
17553b3a8eb9SGleb Smirnoff nti = SIMPLEQ_NEXT(ti, entries);
17563b3a8eb9SGleb Smirnoff free(ti);
17573b3a8eb9SGleb Smirnoff }
17583b3a8eb9SGleb Smirnoff }
17593b3a8eb9SGleb Smirnoff ;
17603b3a8eb9SGleb Smirnoff
17613b3a8eb9SGleb Smirnoff table_opts : {
17623b3a8eb9SGleb Smirnoff bzero(&table_opts, sizeof table_opts);
17633b3a8eb9SGleb Smirnoff SIMPLEQ_INIT(&table_opts.init_nodes);
17643b3a8eb9SGleb Smirnoff }
17653b3a8eb9SGleb Smirnoff table_opts_l
17663b3a8eb9SGleb Smirnoff { $$ = table_opts; }
17673b3a8eb9SGleb Smirnoff | /* empty */
17683b3a8eb9SGleb Smirnoff {
17693b3a8eb9SGleb Smirnoff bzero(&table_opts, sizeof table_opts);
17703b3a8eb9SGleb Smirnoff SIMPLEQ_INIT(&table_opts.init_nodes);
17713b3a8eb9SGleb Smirnoff $$ = table_opts;
17723b3a8eb9SGleb Smirnoff }
17733b3a8eb9SGleb Smirnoff ;
17743b3a8eb9SGleb Smirnoff
17753b3a8eb9SGleb Smirnoff table_opts_l : table_opts_l table_opt
17763b3a8eb9SGleb Smirnoff | table_opt
17773b3a8eb9SGleb Smirnoff ;
17783b3a8eb9SGleb Smirnoff
17793b3a8eb9SGleb Smirnoff table_opt : STRING {
17803b3a8eb9SGleb Smirnoff if (!strcmp($1, "const"))
17813b3a8eb9SGleb Smirnoff table_opts.flags |= PFR_TFLAG_CONST;
17823b3a8eb9SGleb Smirnoff else if (!strcmp($1, "persist"))
17833b3a8eb9SGleb Smirnoff table_opts.flags |= PFR_TFLAG_PERSIST;
17843b3a8eb9SGleb Smirnoff else if (!strcmp($1, "counters"))
17853b3a8eb9SGleb Smirnoff table_opts.flags |= PFR_TFLAG_COUNTERS;
17863b3a8eb9SGleb Smirnoff else {
17873b3a8eb9SGleb Smirnoff yyerror("invalid table option '%s'", $1);
17883b3a8eb9SGleb Smirnoff free($1);
17893b3a8eb9SGleb Smirnoff YYERROR;
17903b3a8eb9SGleb Smirnoff }
17913b3a8eb9SGleb Smirnoff free($1);
17923b3a8eb9SGleb Smirnoff }
17933b3a8eb9SGleb Smirnoff | '{' optnl '}' { table_opts.init_addr = 1; }
17943b3a8eb9SGleb Smirnoff | '{' optnl host_list '}' {
17953b3a8eb9SGleb Smirnoff struct node_host *n;
17963b3a8eb9SGleb Smirnoff struct node_tinit *ti;
17973b3a8eb9SGleb Smirnoff
17983b3a8eb9SGleb Smirnoff for (n = $3; n != NULL; n = n->next) {
17993b3a8eb9SGleb Smirnoff switch (n->addr.type) {
18003b3a8eb9SGleb Smirnoff case PF_ADDR_ADDRMASK:
18013b3a8eb9SGleb Smirnoff continue; /* ok */
18023b3a8eb9SGleb Smirnoff case PF_ADDR_RANGE:
18033b3a8eb9SGleb Smirnoff yyerror("address ranges are not "
18043b3a8eb9SGleb Smirnoff "permitted inside tables");
18053b3a8eb9SGleb Smirnoff break;
18063b3a8eb9SGleb Smirnoff case PF_ADDR_DYNIFTL:
18073b3a8eb9SGleb Smirnoff yyerror("dynamic addresses are not "
18083b3a8eb9SGleb Smirnoff "permitted inside tables");
18093b3a8eb9SGleb Smirnoff break;
18103b3a8eb9SGleb Smirnoff case PF_ADDR_TABLE:
18113b3a8eb9SGleb Smirnoff yyerror("tables cannot contain tables");
18123b3a8eb9SGleb Smirnoff break;
18133b3a8eb9SGleb Smirnoff case PF_ADDR_NOROUTE:
18143b3a8eb9SGleb Smirnoff yyerror("\"no-route\" is not permitted "
18153b3a8eb9SGleb Smirnoff "inside tables");
18163b3a8eb9SGleb Smirnoff break;
18173b3a8eb9SGleb Smirnoff case PF_ADDR_URPFFAILED:
18183b3a8eb9SGleb Smirnoff yyerror("\"urpf-failed\" is not "
18193b3a8eb9SGleb Smirnoff "permitted inside tables");
18203b3a8eb9SGleb Smirnoff break;
18213b3a8eb9SGleb Smirnoff default:
18223b3a8eb9SGleb Smirnoff yyerror("unknown address type %d",
18233b3a8eb9SGleb Smirnoff n->addr.type);
18243b3a8eb9SGleb Smirnoff }
18253b3a8eb9SGleb Smirnoff YYERROR;
18263b3a8eb9SGleb Smirnoff }
18273b3a8eb9SGleb Smirnoff if (!(ti = calloc(1, sizeof(*ti))))
18283b3a8eb9SGleb Smirnoff err(1, "table_opt: calloc");
18293b3a8eb9SGleb Smirnoff ti->host = $3;
18303b3a8eb9SGleb Smirnoff SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
18313b3a8eb9SGleb Smirnoff entries);
18323b3a8eb9SGleb Smirnoff table_opts.init_addr = 1;
18333b3a8eb9SGleb Smirnoff }
18343b3a8eb9SGleb Smirnoff | FILENAME STRING {
18353b3a8eb9SGleb Smirnoff struct node_tinit *ti;
18363b3a8eb9SGleb Smirnoff
18373b3a8eb9SGleb Smirnoff if (!(ti = calloc(1, sizeof(*ti))))
18383b3a8eb9SGleb Smirnoff err(1, "table_opt: calloc");
18393b3a8eb9SGleb Smirnoff ti->file = $2;
18403b3a8eb9SGleb Smirnoff SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti,
18413b3a8eb9SGleb Smirnoff entries);
18423b3a8eb9SGleb Smirnoff table_opts.init_addr = 1;
18433b3a8eb9SGleb Smirnoff }
18443b3a8eb9SGleb Smirnoff ;
18453b3a8eb9SGleb Smirnoff
18463b3a8eb9SGleb Smirnoff altqif : ALTQ interface queue_opts QUEUE qassign {
18473b3a8eb9SGleb Smirnoff struct pf_altq a;
18483b3a8eb9SGleb Smirnoff
18493b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_QUEUE))
18503b3a8eb9SGleb Smirnoff YYERROR;
18513b3a8eb9SGleb Smirnoff
18523b3a8eb9SGleb Smirnoff memset(&a, 0, sizeof(a));
18533b3a8eb9SGleb Smirnoff if ($3.scheduler.qtype == ALTQT_NONE) {
18543b3a8eb9SGleb Smirnoff yyerror("no scheduler specified!");
18553b3a8eb9SGleb Smirnoff YYERROR;
18563b3a8eb9SGleb Smirnoff }
18573b3a8eb9SGleb Smirnoff a.scheduler = $3.scheduler.qtype;
18583b3a8eb9SGleb Smirnoff a.qlimit = $3.qlimit;
18593b3a8eb9SGleb Smirnoff a.tbrsize = $3.tbrsize;
18600a70aaf8SLuiz Otavio O Souza if ($5 == NULL && $3.scheduler.qtype != ALTQT_CODEL) {
18613b3a8eb9SGleb Smirnoff yyerror("no child queues specified");
18623b3a8eb9SGleb Smirnoff YYERROR;
18633b3a8eb9SGleb Smirnoff }
18643b3a8eb9SGleb Smirnoff if (expand_altq(&a, $2, $5, $3.queue_bwspec,
18653b3a8eb9SGleb Smirnoff &$3.scheduler))
18663b3a8eb9SGleb Smirnoff YYERROR;
18673b3a8eb9SGleb Smirnoff }
18683b3a8eb9SGleb Smirnoff ;
18693b3a8eb9SGleb Smirnoff
18703b3a8eb9SGleb Smirnoff queuespec : QUEUE STRING interface queue_opts qassign {
18713b3a8eb9SGleb Smirnoff struct pf_altq a;
18723b3a8eb9SGleb Smirnoff
18733b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_QUEUE)) {
18743b3a8eb9SGleb Smirnoff free($2);
18753b3a8eb9SGleb Smirnoff YYERROR;
18763b3a8eb9SGleb Smirnoff }
18773b3a8eb9SGleb Smirnoff
18783b3a8eb9SGleb Smirnoff memset(&a, 0, sizeof(a));
18793b3a8eb9SGleb Smirnoff
18803b3a8eb9SGleb Smirnoff if (strlcpy(a.qname, $2, sizeof(a.qname)) >=
18813b3a8eb9SGleb Smirnoff sizeof(a.qname)) {
18823b3a8eb9SGleb Smirnoff yyerror("queue name too long (max "
18833b3a8eb9SGleb Smirnoff "%d chars)", PF_QNAME_SIZE-1);
18843b3a8eb9SGleb Smirnoff free($2);
18853b3a8eb9SGleb Smirnoff YYERROR;
18863b3a8eb9SGleb Smirnoff }
18873b3a8eb9SGleb Smirnoff free($2);
18883b3a8eb9SGleb Smirnoff if ($4.tbrsize) {
18893b3a8eb9SGleb Smirnoff yyerror("cannot specify tbrsize for queue");
18903b3a8eb9SGleb Smirnoff YYERROR;
18913b3a8eb9SGleb Smirnoff }
18923b3a8eb9SGleb Smirnoff if ($4.priority > 255) {
18933b3a8eb9SGleb Smirnoff yyerror("priority out of range: max 255");
18943b3a8eb9SGleb Smirnoff YYERROR;
18953b3a8eb9SGleb Smirnoff }
18963b3a8eb9SGleb Smirnoff a.priority = $4.priority;
18973b3a8eb9SGleb Smirnoff a.qlimit = $4.qlimit;
18983b3a8eb9SGleb Smirnoff a.scheduler = $4.scheduler.qtype;
18993b3a8eb9SGleb Smirnoff if (expand_queue(&a, $3, $5, $4.queue_bwspec,
19003b3a8eb9SGleb Smirnoff &$4.scheduler)) {
19013b3a8eb9SGleb Smirnoff yyerror("errors in queue definition");
19023b3a8eb9SGleb Smirnoff YYERROR;
19033b3a8eb9SGleb Smirnoff }
19043b3a8eb9SGleb Smirnoff }
19053b3a8eb9SGleb Smirnoff ;
19063b3a8eb9SGleb Smirnoff
19073b3a8eb9SGleb Smirnoff queue_opts : {
19083b3a8eb9SGleb Smirnoff bzero(&queue_opts, sizeof queue_opts);
19093b3a8eb9SGleb Smirnoff queue_opts.priority = DEFAULT_PRIORITY;
19103b3a8eb9SGleb Smirnoff queue_opts.qlimit = DEFAULT_QLIMIT;
19113b3a8eb9SGleb Smirnoff queue_opts.scheduler.qtype = ALTQT_NONE;
19123b3a8eb9SGleb Smirnoff queue_opts.queue_bwspec.bw_percent = 100;
19133b3a8eb9SGleb Smirnoff }
19143b3a8eb9SGleb Smirnoff queue_opts_l
19153b3a8eb9SGleb Smirnoff { $$ = queue_opts; }
19163b3a8eb9SGleb Smirnoff | /* empty */ {
19173b3a8eb9SGleb Smirnoff bzero(&queue_opts, sizeof queue_opts);
19183b3a8eb9SGleb Smirnoff queue_opts.priority = DEFAULT_PRIORITY;
19193b3a8eb9SGleb Smirnoff queue_opts.qlimit = DEFAULT_QLIMIT;
19203b3a8eb9SGleb Smirnoff queue_opts.scheduler.qtype = ALTQT_NONE;
19213b3a8eb9SGleb Smirnoff queue_opts.queue_bwspec.bw_percent = 100;
19223b3a8eb9SGleb Smirnoff $$ = queue_opts;
19233b3a8eb9SGleb Smirnoff }
19243b3a8eb9SGleb Smirnoff ;
19253b3a8eb9SGleb Smirnoff
19263b3a8eb9SGleb Smirnoff queue_opts_l : queue_opts_l queue_opt
19273b3a8eb9SGleb Smirnoff | queue_opt
19283b3a8eb9SGleb Smirnoff ;
19293b3a8eb9SGleb Smirnoff
19303b3a8eb9SGleb Smirnoff queue_opt : BANDWIDTH bandwidth {
19313b3a8eb9SGleb Smirnoff if (queue_opts.marker & QOM_BWSPEC) {
19323b3a8eb9SGleb Smirnoff yyerror("bandwidth cannot be respecified");
19333b3a8eb9SGleb Smirnoff YYERROR;
19343b3a8eb9SGleb Smirnoff }
19353b3a8eb9SGleb Smirnoff queue_opts.marker |= QOM_BWSPEC;
19363b3a8eb9SGleb Smirnoff queue_opts.queue_bwspec = $2;
19373b3a8eb9SGleb Smirnoff }
19383b3a8eb9SGleb Smirnoff | PRIORITY NUMBER {
19393b3a8eb9SGleb Smirnoff if (queue_opts.marker & QOM_PRIORITY) {
19403b3a8eb9SGleb Smirnoff yyerror("priority cannot be respecified");
19413b3a8eb9SGleb Smirnoff YYERROR;
19423b3a8eb9SGleb Smirnoff }
19433b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > 255) {
19443b3a8eb9SGleb Smirnoff yyerror("priority out of range: max 255");
19453b3a8eb9SGleb Smirnoff YYERROR;
19463b3a8eb9SGleb Smirnoff }
19473b3a8eb9SGleb Smirnoff queue_opts.marker |= QOM_PRIORITY;
19483b3a8eb9SGleb Smirnoff queue_opts.priority = $2;
19493b3a8eb9SGleb Smirnoff }
19503b3a8eb9SGleb Smirnoff | QLIMIT NUMBER {
19513b3a8eb9SGleb Smirnoff if (queue_opts.marker & QOM_QLIMIT) {
19523b3a8eb9SGleb Smirnoff yyerror("qlimit cannot be respecified");
19533b3a8eb9SGleb Smirnoff YYERROR;
19543b3a8eb9SGleb Smirnoff }
19553b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > 65535) {
19563b3a8eb9SGleb Smirnoff yyerror("qlimit out of range: max 65535");
19573b3a8eb9SGleb Smirnoff YYERROR;
19583b3a8eb9SGleb Smirnoff }
19593b3a8eb9SGleb Smirnoff queue_opts.marker |= QOM_QLIMIT;
19603b3a8eb9SGleb Smirnoff queue_opts.qlimit = $2;
19613b3a8eb9SGleb Smirnoff }
19623b3a8eb9SGleb Smirnoff | scheduler {
19633b3a8eb9SGleb Smirnoff if (queue_opts.marker & QOM_SCHEDULER) {
19643b3a8eb9SGleb Smirnoff yyerror("scheduler cannot be respecified");
19653b3a8eb9SGleb Smirnoff YYERROR;
19663b3a8eb9SGleb Smirnoff }
19673b3a8eb9SGleb Smirnoff queue_opts.marker |= QOM_SCHEDULER;
19683b3a8eb9SGleb Smirnoff queue_opts.scheduler = $1;
19693b3a8eb9SGleb Smirnoff }
19703b3a8eb9SGleb Smirnoff | TBRSIZE NUMBER {
19713b3a8eb9SGleb Smirnoff if (queue_opts.marker & QOM_TBRSIZE) {
19723b3a8eb9SGleb Smirnoff yyerror("tbrsize cannot be respecified");
19733b3a8eb9SGleb Smirnoff YYERROR;
19743b3a8eb9SGleb Smirnoff }
1975249cc75fSPatrick Kelsey if ($2 < 0 || $2 > UINT_MAX) {
1976249cc75fSPatrick Kelsey yyerror("tbrsize too big: max %u", UINT_MAX);
19773b3a8eb9SGleb Smirnoff YYERROR;
19783b3a8eb9SGleb Smirnoff }
19793b3a8eb9SGleb Smirnoff queue_opts.marker |= QOM_TBRSIZE;
19803b3a8eb9SGleb Smirnoff queue_opts.tbrsize = $2;
19813b3a8eb9SGleb Smirnoff }
19823b3a8eb9SGleb Smirnoff ;
19833b3a8eb9SGleb Smirnoff
19843b3a8eb9SGleb Smirnoff bandwidth : STRING {
19853b3a8eb9SGleb Smirnoff double bps;
19863b3a8eb9SGleb Smirnoff char *cp;
19873b3a8eb9SGleb Smirnoff
19883b3a8eb9SGleb Smirnoff $$.bw_percent = 0;
19893b3a8eb9SGleb Smirnoff
19903b3a8eb9SGleb Smirnoff bps = strtod($1, &cp);
19913b3a8eb9SGleb Smirnoff if (cp != NULL) {
1992db1bbde6SLuiz Otavio O Souza if (strlen(cp) > 1) {
1993db1bbde6SLuiz Otavio O Souza char *cu = cp + 1;
1994db1bbde6SLuiz Otavio O Souza if (!strcmp(cu, "Bit") ||
1995db1bbde6SLuiz Otavio O Souza !strcmp(cu, "B") ||
1996db1bbde6SLuiz Otavio O Souza !strcmp(cu, "bit") ||
1997db1bbde6SLuiz Otavio O Souza !strcmp(cu, "b")) {
1998db1bbde6SLuiz Otavio O Souza *cu = 0;
1999db1bbde6SLuiz Otavio O Souza }
2000db1bbde6SLuiz Otavio O Souza }
20013b3a8eb9SGleb Smirnoff if (!strcmp(cp, "b"))
20023b3a8eb9SGleb Smirnoff ; /* nothing */
2003db1bbde6SLuiz Otavio O Souza else if (!strcmp(cp, "K"))
20043b3a8eb9SGleb Smirnoff bps *= 1000;
2005db1bbde6SLuiz Otavio O Souza else if (!strcmp(cp, "M"))
20063b3a8eb9SGleb Smirnoff bps *= 1000 * 1000;
2007db1bbde6SLuiz Otavio O Souza else if (!strcmp(cp, "G"))
20083b3a8eb9SGleb Smirnoff bps *= 1000 * 1000 * 1000;
20093b3a8eb9SGleb Smirnoff else if (!strcmp(cp, "%")) {
20103b3a8eb9SGleb Smirnoff if (bps < 0 || bps > 100) {
20113b3a8eb9SGleb Smirnoff yyerror("bandwidth spec "
20123b3a8eb9SGleb Smirnoff "out of range");
20133b3a8eb9SGleb Smirnoff free($1);
20143b3a8eb9SGleb Smirnoff YYERROR;
20153b3a8eb9SGleb Smirnoff }
20163b3a8eb9SGleb Smirnoff $$.bw_percent = bps;
20173b3a8eb9SGleb Smirnoff bps = 0;
20183b3a8eb9SGleb Smirnoff } else {
20193b3a8eb9SGleb Smirnoff yyerror("unknown unit %s", cp);
20203b3a8eb9SGleb Smirnoff free($1);
20213b3a8eb9SGleb Smirnoff YYERROR;
20223b3a8eb9SGleb Smirnoff }
20233b3a8eb9SGleb Smirnoff }
20243b3a8eb9SGleb Smirnoff free($1);
2025249cc75fSPatrick Kelsey $$.bw_absolute = (u_int64_t)bps;
20263b3a8eb9SGleb Smirnoff }
20273b3a8eb9SGleb Smirnoff | NUMBER {
2028249cc75fSPatrick Kelsey if ($1 < 0 || $1 >= LLONG_MAX) {
20293b3a8eb9SGleb Smirnoff yyerror("bandwidth number too big");
20303b3a8eb9SGleb Smirnoff YYERROR;
20313b3a8eb9SGleb Smirnoff }
20323b3a8eb9SGleb Smirnoff $$.bw_percent = 0;
20333b3a8eb9SGleb Smirnoff $$.bw_absolute = $1;
20343b3a8eb9SGleb Smirnoff }
20353b3a8eb9SGleb Smirnoff ;
20363b3a8eb9SGleb Smirnoff
20373b3a8eb9SGleb Smirnoff scheduler : CBQ {
20383b3a8eb9SGleb Smirnoff $$.qtype = ALTQT_CBQ;
20393b3a8eb9SGleb Smirnoff $$.data.cbq_opts.flags = 0;
20403b3a8eb9SGleb Smirnoff }
20413b3a8eb9SGleb Smirnoff | CBQ '(' cbqflags_list ')' {
20423b3a8eb9SGleb Smirnoff $$.qtype = ALTQT_CBQ;
20433b3a8eb9SGleb Smirnoff $$.data.cbq_opts.flags = $3;
20443b3a8eb9SGleb Smirnoff }
20453b3a8eb9SGleb Smirnoff | PRIQ {
20463b3a8eb9SGleb Smirnoff $$.qtype = ALTQT_PRIQ;
20473b3a8eb9SGleb Smirnoff $$.data.priq_opts.flags = 0;
20483b3a8eb9SGleb Smirnoff }
20493b3a8eb9SGleb Smirnoff | PRIQ '(' priqflags_list ')' {
20503b3a8eb9SGleb Smirnoff $$.qtype = ALTQT_PRIQ;
20513b3a8eb9SGleb Smirnoff $$.data.priq_opts.flags = $3;
20523b3a8eb9SGleb Smirnoff }
20533b3a8eb9SGleb Smirnoff | HFSC {
20543b3a8eb9SGleb Smirnoff $$.qtype = ALTQT_HFSC;
20553b3a8eb9SGleb Smirnoff bzero(&$$.data.hfsc_opts,
20563b3a8eb9SGleb Smirnoff sizeof(struct node_hfsc_opts));
20573b3a8eb9SGleb Smirnoff }
20583b3a8eb9SGleb Smirnoff | HFSC '(' hfsc_opts ')' {
20593b3a8eb9SGleb Smirnoff $$.qtype = ALTQT_HFSC;
20603b3a8eb9SGleb Smirnoff $$.data.hfsc_opts = $3;
20613b3a8eb9SGleb Smirnoff }
2062a5b789f6SErmal Luçi | FAIRQ {
2063a5b789f6SErmal Luçi $$.qtype = ALTQT_FAIRQ;
2064a5b789f6SErmal Luçi bzero(&$$.data.fairq_opts,
2065a5b789f6SErmal Luçi sizeof(struct node_fairq_opts));
2066a5b789f6SErmal Luçi }
2067a5b789f6SErmal Luçi | FAIRQ '(' fairq_opts ')' {
2068a5b789f6SErmal Luçi $$.qtype = ALTQT_FAIRQ;
2069a5b789f6SErmal Luçi $$.data.fairq_opts = $3;
2070a5b789f6SErmal Luçi }
20710a70aaf8SLuiz Otavio O Souza | CODEL {
20720a70aaf8SLuiz Otavio O Souza $$.qtype = ALTQT_CODEL;
20730a70aaf8SLuiz Otavio O Souza bzero(&$$.data.codel_opts,
20740a70aaf8SLuiz Otavio O Souza sizeof(struct codel_opts));
20750a70aaf8SLuiz Otavio O Souza }
20760a70aaf8SLuiz Otavio O Souza | CODEL '(' codel_opts ')' {
20770a70aaf8SLuiz Otavio O Souza $$.qtype = ALTQT_CODEL;
20780a70aaf8SLuiz Otavio O Souza $$.data.codel_opts = $3;
20790a70aaf8SLuiz Otavio O Souza }
20803b3a8eb9SGleb Smirnoff ;
20813b3a8eb9SGleb Smirnoff
20823b3a8eb9SGleb Smirnoff cbqflags_list : cbqflags_item { $$ |= $1; }
20833b3a8eb9SGleb Smirnoff | cbqflags_list comma cbqflags_item { $$ |= $3; }
20843b3a8eb9SGleb Smirnoff ;
20853b3a8eb9SGleb Smirnoff
20863b3a8eb9SGleb Smirnoff cbqflags_item : STRING {
20873b3a8eb9SGleb Smirnoff if (!strcmp($1, "default"))
20883b3a8eb9SGleb Smirnoff $$ = CBQCLF_DEFCLASS;
20893b3a8eb9SGleb Smirnoff else if (!strcmp($1, "borrow"))
20903b3a8eb9SGleb Smirnoff $$ = CBQCLF_BORROW;
20913b3a8eb9SGleb Smirnoff else if (!strcmp($1, "red"))
20923b3a8eb9SGleb Smirnoff $$ = CBQCLF_RED;
20933b3a8eb9SGleb Smirnoff else if (!strcmp($1, "ecn"))
20943b3a8eb9SGleb Smirnoff $$ = CBQCLF_RED|CBQCLF_ECN;
20953b3a8eb9SGleb Smirnoff else if (!strcmp($1, "rio"))
20963b3a8eb9SGleb Smirnoff $$ = CBQCLF_RIO;
20970a70aaf8SLuiz Otavio O Souza else if (!strcmp($1, "codel"))
20980a70aaf8SLuiz Otavio O Souza $$ = CBQCLF_CODEL;
20993b3a8eb9SGleb Smirnoff else {
21003b3a8eb9SGleb Smirnoff yyerror("unknown cbq flag \"%s\"", $1);
21013b3a8eb9SGleb Smirnoff free($1);
21023b3a8eb9SGleb Smirnoff YYERROR;
21033b3a8eb9SGleb Smirnoff }
21043b3a8eb9SGleb Smirnoff free($1);
21053b3a8eb9SGleb Smirnoff }
21063b3a8eb9SGleb Smirnoff ;
21073b3a8eb9SGleb Smirnoff
21083b3a8eb9SGleb Smirnoff priqflags_list : priqflags_item { $$ |= $1; }
21093b3a8eb9SGleb Smirnoff | priqflags_list comma priqflags_item { $$ |= $3; }
21103b3a8eb9SGleb Smirnoff ;
21113b3a8eb9SGleb Smirnoff
21123b3a8eb9SGleb Smirnoff priqflags_item : STRING {
21133b3a8eb9SGleb Smirnoff if (!strcmp($1, "default"))
21143b3a8eb9SGleb Smirnoff $$ = PRCF_DEFAULTCLASS;
21153b3a8eb9SGleb Smirnoff else if (!strcmp($1, "red"))
21163b3a8eb9SGleb Smirnoff $$ = PRCF_RED;
21173b3a8eb9SGleb Smirnoff else if (!strcmp($1, "ecn"))
21183b3a8eb9SGleb Smirnoff $$ = PRCF_RED|PRCF_ECN;
21193b3a8eb9SGleb Smirnoff else if (!strcmp($1, "rio"))
21203b3a8eb9SGleb Smirnoff $$ = PRCF_RIO;
21210a70aaf8SLuiz Otavio O Souza else if (!strcmp($1, "codel"))
21220a70aaf8SLuiz Otavio O Souza $$ = PRCF_CODEL;
21233b3a8eb9SGleb Smirnoff else {
21243b3a8eb9SGleb Smirnoff yyerror("unknown priq flag \"%s\"", $1);
21253b3a8eb9SGleb Smirnoff free($1);
21263b3a8eb9SGleb Smirnoff YYERROR;
21273b3a8eb9SGleb Smirnoff }
21283b3a8eb9SGleb Smirnoff free($1);
21293b3a8eb9SGleb Smirnoff }
21303b3a8eb9SGleb Smirnoff ;
21313b3a8eb9SGleb Smirnoff
21323b3a8eb9SGleb Smirnoff hfsc_opts : {
21333b3a8eb9SGleb Smirnoff bzero(&hfsc_opts,
21343b3a8eb9SGleb Smirnoff sizeof(struct node_hfsc_opts));
21353b3a8eb9SGleb Smirnoff }
21363b3a8eb9SGleb Smirnoff hfscopts_list {
21373b3a8eb9SGleb Smirnoff $$ = hfsc_opts;
21383b3a8eb9SGleb Smirnoff }
21393b3a8eb9SGleb Smirnoff ;
21403b3a8eb9SGleb Smirnoff
21413b3a8eb9SGleb Smirnoff hfscopts_list : hfscopts_item
21423b3a8eb9SGleb Smirnoff | hfscopts_list comma hfscopts_item
21433b3a8eb9SGleb Smirnoff ;
21443b3a8eb9SGleb Smirnoff
21453b3a8eb9SGleb Smirnoff hfscopts_item : LINKSHARE bandwidth {
21463b3a8eb9SGleb Smirnoff if (hfsc_opts.linkshare.used) {
21473b3a8eb9SGleb Smirnoff yyerror("linkshare already specified");
21483b3a8eb9SGleb Smirnoff YYERROR;
21493b3a8eb9SGleb Smirnoff }
21503b3a8eb9SGleb Smirnoff hfsc_opts.linkshare.m2 = $2;
21513b3a8eb9SGleb Smirnoff hfsc_opts.linkshare.used = 1;
21523b3a8eb9SGleb Smirnoff }
21533b3a8eb9SGleb Smirnoff | LINKSHARE '(' bandwidth comma NUMBER comma bandwidth ')'
21543b3a8eb9SGleb Smirnoff {
21553b3a8eb9SGleb Smirnoff if ($5 < 0 || $5 > INT_MAX) {
21563b3a8eb9SGleb Smirnoff yyerror("timing in curve out of range");
21573b3a8eb9SGleb Smirnoff YYERROR;
21583b3a8eb9SGleb Smirnoff }
21593b3a8eb9SGleb Smirnoff if (hfsc_opts.linkshare.used) {
21603b3a8eb9SGleb Smirnoff yyerror("linkshare already specified");
21613b3a8eb9SGleb Smirnoff YYERROR;
21623b3a8eb9SGleb Smirnoff }
21633b3a8eb9SGleb Smirnoff hfsc_opts.linkshare.m1 = $3;
21643b3a8eb9SGleb Smirnoff hfsc_opts.linkshare.d = $5;
21653b3a8eb9SGleb Smirnoff hfsc_opts.linkshare.m2 = $7;
21663b3a8eb9SGleb Smirnoff hfsc_opts.linkshare.used = 1;
21673b3a8eb9SGleb Smirnoff }
21683b3a8eb9SGleb Smirnoff | REALTIME bandwidth {
21693b3a8eb9SGleb Smirnoff if (hfsc_opts.realtime.used) {
21703b3a8eb9SGleb Smirnoff yyerror("realtime already specified");
21713b3a8eb9SGleb Smirnoff YYERROR;
21723b3a8eb9SGleb Smirnoff }
21733b3a8eb9SGleb Smirnoff hfsc_opts.realtime.m2 = $2;
21743b3a8eb9SGleb Smirnoff hfsc_opts.realtime.used = 1;
21753b3a8eb9SGleb Smirnoff }
21763b3a8eb9SGleb Smirnoff | REALTIME '(' bandwidth comma NUMBER comma bandwidth ')'
21773b3a8eb9SGleb Smirnoff {
21783b3a8eb9SGleb Smirnoff if ($5 < 0 || $5 > INT_MAX) {
21793b3a8eb9SGleb Smirnoff yyerror("timing in curve out of range");
21803b3a8eb9SGleb Smirnoff YYERROR;
21813b3a8eb9SGleb Smirnoff }
21823b3a8eb9SGleb Smirnoff if (hfsc_opts.realtime.used) {
21833b3a8eb9SGleb Smirnoff yyerror("realtime already specified");
21843b3a8eb9SGleb Smirnoff YYERROR;
21853b3a8eb9SGleb Smirnoff }
21863b3a8eb9SGleb Smirnoff hfsc_opts.realtime.m1 = $3;
21873b3a8eb9SGleb Smirnoff hfsc_opts.realtime.d = $5;
21883b3a8eb9SGleb Smirnoff hfsc_opts.realtime.m2 = $7;
21893b3a8eb9SGleb Smirnoff hfsc_opts.realtime.used = 1;
21903b3a8eb9SGleb Smirnoff }
21913b3a8eb9SGleb Smirnoff | UPPERLIMIT bandwidth {
21923b3a8eb9SGleb Smirnoff if (hfsc_opts.upperlimit.used) {
21933b3a8eb9SGleb Smirnoff yyerror("upperlimit already specified");
21943b3a8eb9SGleb Smirnoff YYERROR;
21953b3a8eb9SGleb Smirnoff }
21963b3a8eb9SGleb Smirnoff hfsc_opts.upperlimit.m2 = $2;
21973b3a8eb9SGleb Smirnoff hfsc_opts.upperlimit.used = 1;
21983b3a8eb9SGleb Smirnoff }
21993b3a8eb9SGleb Smirnoff | UPPERLIMIT '(' bandwidth comma NUMBER comma bandwidth ')'
22003b3a8eb9SGleb Smirnoff {
22013b3a8eb9SGleb Smirnoff if ($5 < 0 || $5 > INT_MAX) {
22023b3a8eb9SGleb Smirnoff yyerror("timing in curve out of range");
22033b3a8eb9SGleb Smirnoff YYERROR;
22043b3a8eb9SGleb Smirnoff }
22053b3a8eb9SGleb Smirnoff if (hfsc_opts.upperlimit.used) {
22063b3a8eb9SGleb Smirnoff yyerror("upperlimit already specified");
22073b3a8eb9SGleb Smirnoff YYERROR;
22083b3a8eb9SGleb Smirnoff }
22093b3a8eb9SGleb Smirnoff hfsc_opts.upperlimit.m1 = $3;
22103b3a8eb9SGleb Smirnoff hfsc_opts.upperlimit.d = $5;
22113b3a8eb9SGleb Smirnoff hfsc_opts.upperlimit.m2 = $7;
22123b3a8eb9SGleb Smirnoff hfsc_opts.upperlimit.used = 1;
22133b3a8eb9SGleb Smirnoff }
22143b3a8eb9SGleb Smirnoff | STRING {
22153b3a8eb9SGleb Smirnoff if (!strcmp($1, "default"))
22163b3a8eb9SGleb Smirnoff hfsc_opts.flags |= HFCF_DEFAULTCLASS;
22173b3a8eb9SGleb Smirnoff else if (!strcmp($1, "red"))
22183b3a8eb9SGleb Smirnoff hfsc_opts.flags |= HFCF_RED;
22193b3a8eb9SGleb Smirnoff else if (!strcmp($1, "ecn"))
22203b3a8eb9SGleb Smirnoff hfsc_opts.flags |= HFCF_RED|HFCF_ECN;
22213b3a8eb9SGleb Smirnoff else if (!strcmp($1, "rio"))
22223b3a8eb9SGleb Smirnoff hfsc_opts.flags |= HFCF_RIO;
22230a70aaf8SLuiz Otavio O Souza else if (!strcmp($1, "codel"))
22240a70aaf8SLuiz Otavio O Souza hfsc_opts.flags |= HFCF_CODEL;
22253b3a8eb9SGleb Smirnoff else {
22263b3a8eb9SGleb Smirnoff yyerror("unknown hfsc flag \"%s\"", $1);
22273b3a8eb9SGleb Smirnoff free($1);
22283b3a8eb9SGleb Smirnoff YYERROR;
22293b3a8eb9SGleb Smirnoff }
22303b3a8eb9SGleb Smirnoff free($1);
22313b3a8eb9SGleb Smirnoff }
22323b3a8eb9SGleb Smirnoff ;
22333b3a8eb9SGleb Smirnoff
2234a5b789f6SErmal Luçi fairq_opts : {
2235a5b789f6SErmal Luçi bzero(&fairq_opts,
2236a5b789f6SErmal Luçi sizeof(struct node_fairq_opts));
2237a5b789f6SErmal Luçi }
2238a5b789f6SErmal Luçi fairqopts_list {
2239a5b789f6SErmal Luçi $$ = fairq_opts;
2240a5b789f6SErmal Luçi }
2241a5b789f6SErmal Luçi ;
2242a5b789f6SErmal Luçi
2243a5b789f6SErmal Luçi fairqopts_list : fairqopts_item
2244a5b789f6SErmal Luçi | fairqopts_list comma fairqopts_item
2245a5b789f6SErmal Luçi ;
2246a5b789f6SErmal Luçi
2247a5b789f6SErmal Luçi fairqopts_item : LINKSHARE bandwidth {
2248a5b789f6SErmal Luçi if (fairq_opts.linkshare.used) {
2249a5b789f6SErmal Luçi yyerror("linkshare already specified");
2250a5b789f6SErmal Luçi YYERROR;
2251a5b789f6SErmal Luçi }
2252a5b789f6SErmal Luçi fairq_opts.linkshare.m2 = $2;
2253a5b789f6SErmal Luçi fairq_opts.linkshare.used = 1;
2254a5b789f6SErmal Luçi }
2255a5b789f6SErmal Luçi | LINKSHARE '(' bandwidth number bandwidth ')' {
2256a5b789f6SErmal Luçi if (fairq_opts.linkshare.used) {
2257a5b789f6SErmal Luçi yyerror("linkshare already specified");
2258a5b789f6SErmal Luçi YYERROR;
2259a5b789f6SErmal Luçi }
2260a5b789f6SErmal Luçi fairq_opts.linkshare.m1 = $3;
2261a5b789f6SErmal Luçi fairq_opts.linkshare.d = $4;
2262a5b789f6SErmal Luçi fairq_opts.linkshare.m2 = $5;
2263a5b789f6SErmal Luçi fairq_opts.linkshare.used = 1;
2264a5b789f6SErmal Luçi }
2265a5b789f6SErmal Luçi | HOGS bandwidth {
2266a5b789f6SErmal Luçi fairq_opts.hogs_bw = $2;
2267a5b789f6SErmal Luçi }
2268a5b789f6SErmal Luçi | BUCKETS number {
2269a5b789f6SErmal Luçi fairq_opts.nbuckets = $2;
2270a5b789f6SErmal Luçi }
2271a5b789f6SErmal Luçi | STRING {
2272a5b789f6SErmal Luçi if (!strcmp($1, "default"))
2273a5b789f6SErmal Luçi fairq_opts.flags |= FARF_DEFAULTCLASS;
2274a5b789f6SErmal Luçi else if (!strcmp($1, "red"))
2275a5b789f6SErmal Luçi fairq_opts.flags |= FARF_RED;
2276a5b789f6SErmal Luçi else if (!strcmp($1, "ecn"))
2277a5b789f6SErmal Luçi fairq_opts.flags |= FARF_RED|FARF_ECN;
2278a5b789f6SErmal Luçi else if (!strcmp($1, "rio"))
2279a5b789f6SErmal Luçi fairq_opts.flags |= FARF_RIO;
22800a70aaf8SLuiz Otavio O Souza else if (!strcmp($1, "codel"))
22810a70aaf8SLuiz Otavio O Souza fairq_opts.flags |= FARF_CODEL;
2282a5b789f6SErmal Luçi else {
2283a5b789f6SErmal Luçi yyerror("unknown fairq flag \"%s\"", $1);
2284a5b789f6SErmal Luçi free($1);
2285a5b789f6SErmal Luçi YYERROR;
2286a5b789f6SErmal Luçi }
2287a5b789f6SErmal Luçi free($1);
2288a5b789f6SErmal Luçi }
2289a5b789f6SErmal Luçi ;
2290a5b789f6SErmal Luçi
22910a70aaf8SLuiz Otavio O Souza codel_opts : {
22920a70aaf8SLuiz Otavio O Souza bzero(&codel_opts,
22930a70aaf8SLuiz Otavio O Souza sizeof(struct codel_opts));
22940a70aaf8SLuiz Otavio O Souza }
22950a70aaf8SLuiz Otavio O Souza codelopts_list {
22960a70aaf8SLuiz Otavio O Souza $$ = codel_opts;
22970a70aaf8SLuiz Otavio O Souza }
22980a70aaf8SLuiz Otavio O Souza ;
22990a70aaf8SLuiz Otavio O Souza
23000a70aaf8SLuiz Otavio O Souza codelopts_list : codelopts_item
23010a70aaf8SLuiz Otavio O Souza | codelopts_list comma codelopts_item
23020a70aaf8SLuiz Otavio O Souza ;
23030a70aaf8SLuiz Otavio O Souza
23040a70aaf8SLuiz Otavio O Souza codelopts_item : INTERVAL number {
23050a70aaf8SLuiz Otavio O Souza if (codel_opts.interval) {
23060a70aaf8SLuiz Otavio O Souza yyerror("interval already specified");
23070a70aaf8SLuiz Otavio O Souza YYERROR;
23080a70aaf8SLuiz Otavio O Souza }
23090a70aaf8SLuiz Otavio O Souza codel_opts.interval = $2;
23100a70aaf8SLuiz Otavio O Souza }
23110a70aaf8SLuiz Otavio O Souza | TARGET number {
23120a70aaf8SLuiz Otavio O Souza if (codel_opts.target) {
23130a70aaf8SLuiz Otavio O Souza yyerror("target already specified");
23140a70aaf8SLuiz Otavio O Souza YYERROR;
23150a70aaf8SLuiz Otavio O Souza }
23160a70aaf8SLuiz Otavio O Souza codel_opts.target = $2;
23170a70aaf8SLuiz Otavio O Souza }
23180a70aaf8SLuiz Otavio O Souza | STRING {
23190a70aaf8SLuiz Otavio O Souza if (!strcmp($1, "ecn"))
23200a70aaf8SLuiz Otavio O Souza codel_opts.ecn = 1;
23210a70aaf8SLuiz Otavio O Souza else {
23220a70aaf8SLuiz Otavio O Souza yyerror("unknown codel option \"%s\"", $1);
23230a70aaf8SLuiz Otavio O Souza free($1);
23240a70aaf8SLuiz Otavio O Souza YYERROR;
23250a70aaf8SLuiz Otavio O Souza }
23260a70aaf8SLuiz Otavio O Souza free($1);
23270a70aaf8SLuiz Otavio O Souza }
23280a70aaf8SLuiz Otavio O Souza ;
23290a70aaf8SLuiz Otavio O Souza
23303b3a8eb9SGleb Smirnoff qassign : /* empty */ { $$ = NULL; }
23313b3a8eb9SGleb Smirnoff | qassign_item { $$ = $1; }
23323b3a8eb9SGleb Smirnoff | '{' optnl qassign_list '}' { $$ = $3; }
23333b3a8eb9SGleb Smirnoff ;
23343b3a8eb9SGleb Smirnoff
23353b3a8eb9SGleb Smirnoff qassign_list : qassign_item optnl { $$ = $1; }
23363b3a8eb9SGleb Smirnoff | qassign_list comma qassign_item optnl {
23373b3a8eb9SGleb Smirnoff $1->tail->next = $3;
23383b3a8eb9SGleb Smirnoff $1->tail = $3;
23393b3a8eb9SGleb Smirnoff $$ = $1;
23403b3a8eb9SGleb Smirnoff }
23413b3a8eb9SGleb Smirnoff ;
23423b3a8eb9SGleb Smirnoff
23433b3a8eb9SGleb Smirnoff qassign_item : STRING {
23443b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_queue));
23453b3a8eb9SGleb Smirnoff if ($$ == NULL)
23463b3a8eb9SGleb Smirnoff err(1, "qassign_item: calloc");
23473b3a8eb9SGleb Smirnoff if (strlcpy($$->queue, $1, sizeof($$->queue)) >=
23483b3a8eb9SGleb Smirnoff sizeof($$->queue)) {
23493b3a8eb9SGleb Smirnoff yyerror("queue name '%s' too long (max "
23503b3a8eb9SGleb Smirnoff "%d chars)", $1, sizeof($$->queue)-1);
23513b3a8eb9SGleb Smirnoff free($1);
23523b3a8eb9SGleb Smirnoff free($$);
23533b3a8eb9SGleb Smirnoff YYERROR;
23543b3a8eb9SGleb Smirnoff }
23553b3a8eb9SGleb Smirnoff free($1);
23563b3a8eb9SGleb Smirnoff $$->next = NULL;
23573b3a8eb9SGleb Smirnoff $$->tail = $$;
23583b3a8eb9SGleb Smirnoff }
23593b3a8eb9SGleb Smirnoff ;
23603b3a8eb9SGleb Smirnoff
23613b3a8eb9SGleb Smirnoff pfrule : action dir logquick interface route af proto fromto
23623b3a8eb9SGleb Smirnoff filter_opts
23633b3a8eb9SGleb Smirnoff {
2364e9eb0941SKristof Provost struct pfctl_rule r;
23653b3a8eb9SGleb Smirnoff struct node_state_opt *o;
23663b3a8eb9SGleb Smirnoff struct node_proto *proto;
23673b3a8eb9SGleb Smirnoff int srctrack = 0;
23683b3a8eb9SGleb Smirnoff int statelock = 0;
23693b3a8eb9SGleb Smirnoff int adaptive = 0;
23703b3a8eb9SGleb Smirnoff int defaults = 0;
23713b3a8eb9SGleb Smirnoff
23723b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_FILTER))
23733b3a8eb9SGleb Smirnoff YYERROR;
23743b3a8eb9SGleb Smirnoff
2375*aeddee83SKajetan Staszkiewicz pfctl_init_rule(&r);
23763b3a8eb9SGleb Smirnoff
23773b3a8eb9SGleb Smirnoff r.action = $1.b1;
23783b3a8eb9SGleb Smirnoff switch ($1.b2) {
23793b3a8eb9SGleb Smirnoff case PFRULE_RETURNRST:
23803b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_RETURNRST;
23813b3a8eb9SGleb Smirnoff r.return_ttl = $1.w;
23823b3a8eb9SGleb Smirnoff break;
23833b3a8eb9SGleb Smirnoff case PFRULE_RETURNICMP:
23843b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_RETURNICMP;
23853b3a8eb9SGleb Smirnoff r.return_icmp = $1.w;
23863b3a8eb9SGleb Smirnoff r.return_icmp6 = $1.w2;
23873b3a8eb9SGleb Smirnoff break;
23883b3a8eb9SGleb Smirnoff case PFRULE_RETURN:
23893b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_RETURN;
23903b3a8eb9SGleb Smirnoff r.return_icmp = $1.w;
23913b3a8eb9SGleb Smirnoff r.return_icmp6 = $1.w2;
23923b3a8eb9SGleb Smirnoff break;
23933b3a8eb9SGleb Smirnoff }
23943b3a8eb9SGleb Smirnoff r.direction = $2;
23953b3a8eb9SGleb Smirnoff r.log = $3.log;
23963b3a8eb9SGleb Smirnoff r.logif = $3.logif;
23973b3a8eb9SGleb Smirnoff r.quick = $3.quick;
23983b3a8eb9SGleb Smirnoff r.prob = $9.prob;
23993b3a8eb9SGleb Smirnoff r.rtableid = $9.rtableid;
24003b3a8eb9SGleb Smirnoff
240139282ef3SKajetan Staszkiewicz if ($9.nodf)
240239282ef3SKajetan Staszkiewicz r.scrub_flags |= PFSTATE_NODF;
240339282ef3SKajetan Staszkiewicz if ($9.randomid)
240439282ef3SKajetan Staszkiewicz r.scrub_flags |= PFSTATE_RANDOMID;
240539282ef3SKajetan Staszkiewicz if ($9.minttl)
240639282ef3SKajetan Staszkiewicz r.min_ttl = $9.minttl;
240739282ef3SKajetan Staszkiewicz if ($9.max_mss)
240839282ef3SKajetan Staszkiewicz r.max_mss = $9.max_mss;
240939282ef3SKajetan Staszkiewicz if ($9.marker & FOM_SETTOS) {
241039282ef3SKajetan Staszkiewicz r.scrub_flags |= PFSTATE_SETTOS;
241139282ef3SKajetan Staszkiewicz r.set_tos = $9.settos;
241239282ef3SKajetan Staszkiewicz }
241339282ef3SKajetan Staszkiewicz if ($9.marker & FOM_SCRUB_TCP)
241439282ef3SKajetan Staszkiewicz r.scrub_flags |= PFSTATE_SCRUB_TCP;
241539282ef3SKajetan Staszkiewicz
24163e248e0fSKristof Provost if ($9.marker & FOM_PRIO) {
24173e248e0fSKristof Provost if ($9.prio == 0)
24183e248e0fSKristof Provost r.prio = PF_PRIO_ZERO;
24193e248e0fSKristof Provost else
24203e248e0fSKristof Provost r.prio = $9.prio;
24213e248e0fSKristof Provost }
24223e248e0fSKristof Provost if ($9.marker & FOM_SETPRIO) {
24233e248e0fSKristof Provost r.set_prio[0] = $9.set_prio[0];
24243e248e0fSKristof Provost r.set_prio[1] = $9.set_prio[1];
24253e248e0fSKristof Provost r.scrub_flags |= PFSTATE_SETPRIO;
24263e248e0fSKristof Provost }
24273e248e0fSKristof Provost
2428899e7976SKristof Provost if ($9.marker & FOM_AFTO)
2429f88019e8SKristof Provost r.rule_flag |= PFRULE_AFTO;
2430aa69fdf1SKristof Provost
24313b3a8eb9SGleb Smirnoff r.af = $6;
24323b3a8eb9SGleb Smirnoff if ($9.tag)
24333b3a8eb9SGleb Smirnoff if (strlcpy(r.tagname, $9.tag,
24343b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
24353b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars",
24363b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1);
24373b3a8eb9SGleb Smirnoff YYERROR;
24383b3a8eb9SGleb Smirnoff }
24393b3a8eb9SGleb Smirnoff if ($9.match_tag)
24403b3a8eb9SGleb Smirnoff if (strlcpy(r.match_tagname, $9.match_tag,
24413b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
24423b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars",
24433b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1);
24443b3a8eb9SGleb Smirnoff YYERROR;
24453b3a8eb9SGleb Smirnoff }
24463b3a8eb9SGleb Smirnoff r.match_tag_not = $9.match_tag_not;
24473b3a8eb9SGleb Smirnoff if (rule_label(&r, $9.label))
24483b3a8eb9SGleb Smirnoff YYERROR;
24496fcc8e04SKristof Provost for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++)
24506fcc8e04SKristof Provost free($9.label[i]);
245176c5eeccSKristof Provost r.ridentifier = $9.ridentifier;
24523b3a8eb9SGleb Smirnoff r.flags = $9.flags.b1;
24533b3a8eb9SGleb Smirnoff r.flagset = $9.flags.b2;
24543b3a8eb9SGleb Smirnoff if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) {
24553b3a8eb9SGleb Smirnoff yyerror("flags always false");
24563b3a8eb9SGleb Smirnoff YYERROR;
24573b3a8eb9SGleb Smirnoff }
24583b3a8eb9SGleb Smirnoff if ($9.flags.b1 || $9.flags.b2 || $8.src_os) {
24593b3a8eb9SGleb Smirnoff for (proto = $7; proto != NULL &&
24603b3a8eb9SGleb Smirnoff proto->proto != IPPROTO_TCP;
24613b3a8eb9SGleb Smirnoff proto = proto->next)
24623b3a8eb9SGleb Smirnoff ; /* nothing */
24633b3a8eb9SGleb Smirnoff if (proto == NULL && $7 != NULL) {
24643b3a8eb9SGleb Smirnoff if ($9.flags.b1 || $9.flags.b2)
24653b3a8eb9SGleb Smirnoff yyerror(
24663b3a8eb9SGleb Smirnoff "flags only apply to tcp");
24673b3a8eb9SGleb Smirnoff if ($8.src_os)
24683b3a8eb9SGleb Smirnoff yyerror(
24693b3a8eb9SGleb Smirnoff "OS fingerprinting only "
24703b3a8eb9SGleb Smirnoff "apply to tcp");
24713b3a8eb9SGleb Smirnoff YYERROR;
24723b3a8eb9SGleb Smirnoff }
24733b3a8eb9SGleb Smirnoff #if 0
24743b3a8eb9SGleb Smirnoff if (($9.flags.b1 & parse_flags("S")) == 0 &&
24753b3a8eb9SGleb Smirnoff $8.src_os) {
24763b3a8eb9SGleb Smirnoff yyerror("OS fingerprinting requires "
24773b3a8eb9SGleb Smirnoff "the SYN TCP flag (flags S/SA)");
24783b3a8eb9SGleb Smirnoff YYERROR;
24793b3a8eb9SGleb Smirnoff }
24803b3a8eb9SGleb Smirnoff #endif
24813b3a8eb9SGleb Smirnoff }
24823b3a8eb9SGleb Smirnoff
24833b3a8eb9SGleb Smirnoff r.tos = $9.tos;
24843b3a8eb9SGleb Smirnoff r.keep_state = $9.keep.action;
24853b3a8eb9SGleb Smirnoff o = $9.keep.options;
24863b3a8eb9SGleb Smirnoff
24873b3a8eb9SGleb Smirnoff /* 'keep state' by default on pass rules. */
24883b3a8eb9SGleb Smirnoff if (!r.keep_state && !r.action &&
24893b3a8eb9SGleb Smirnoff !($9.marker & FOM_KEEP)) {
24903b3a8eb9SGleb Smirnoff r.keep_state = PF_STATE_NORMAL;
24913b3a8eb9SGleb Smirnoff o = keep_state_defaults;
24923b3a8eb9SGleb Smirnoff defaults = 1;
24933b3a8eb9SGleb Smirnoff }
24943b3a8eb9SGleb Smirnoff
24953b3a8eb9SGleb Smirnoff while (o) {
24963b3a8eb9SGleb Smirnoff struct node_state_opt *p = o;
24973b3a8eb9SGleb Smirnoff
24983b3a8eb9SGleb Smirnoff switch (o->type) {
24993b3a8eb9SGleb Smirnoff case PF_STATE_OPT_MAX:
25003b3a8eb9SGleb Smirnoff if (r.max_states) {
25013b3a8eb9SGleb Smirnoff yyerror("state option 'max' "
25023b3a8eb9SGleb Smirnoff "multiple definitions");
25033b3a8eb9SGleb Smirnoff YYERROR;
25043b3a8eb9SGleb Smirnoff }
25053b3a8eb9SGleb Smirnoff r.max_states = o->data.max_states;
25063b3a8eb9SGleb Smirnoff break;
25073b3a8eb9SGleb Smirnoff case PF_STATE_OPT_NOSYNC:
25083b3a8eb9SGleb Smirnoff if (r.rule_flag & PFRULE_NOSYNC) {
25093b3a8eb9SGleb Smirnoff yyerror("state option 'sync' "
25103b3a8eb9SGleb Smirnoff "multiple definitions");
25113b3a8eb9SGleb Smirnoff YYERROR;
25123b3a8eb9SGleb Smirnoff }
25133b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_NOSYNC;
25143b3a8eb9SGleb Smirnoff break;
25153b3a8eb9SGleb Smirnoff case PF_STATE_OPT_SRCTRACK:
25163b3a8eb9SGleb Smirnoff if (srctrack) {
25173b3a8eb9SGleb Smirnoff yyerror("state option "
25183b3a8eb9SGleb Smirnoff "'source-track' "
25193b3a8eb9SGleb Smirnoff "multiple definitions");
25203b3a8eb9SGleb Smirnoff YYERROR;
25213b3a8eb9SGleb Smirnoff }
25223b3a8eb9SGleb Smirnoff srctrack = o->data.src_track;
25233b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_SRCTRACK;
25243b3a8eb9SGleb Smirnoff break;
25253b3a8eb9SGleb Smirnoff case PF_STATE_OPT_MAX_SRC_STATES:
25263b3a8eb9SGleb Smirnoff if (r.max_src_states) {
25273b3a8eb9SGleb Smirnoff yyerror("state option "
25283b3a8eb9SGleb Smirnoff "'max-src-states' "
25293b3a8eb9SGleb Smirnoff "multiple definitions");
25303b3a8eb9SGleb Smirnoff YYERROR;
25313b3a8eb9SGleb Smirnoff }
25323b3a8eb9SGleb Smirnoff if (o->data.max_src_states == 0) {
25333b3a8eb9SGleb Smirnoff yyerror("'max-src-states' must "
25343b3a8eb9SGleb Smirnoff "be > 0");
25353b3a8eb9SGleb Smirnoff YYERROR;
25363b3a8eb9SGleb Smirnoff }
25373b3a8eb9SGleb Smirnoff r.max_src_states =
25383b3a8eb9SGleb Smirnoff o->data.max_src_states;
25393b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_SRCTRACK;
25403b3a8eb9SGleb Smirnoff break;
25413b3a8eb9SGleb Smirnoff case PF_STATE_OPT_OVERLOAD:
25423b3a8eb9SGleb Smirnoff if (r.overload_tblname[0]) {
25433b3a8eb9SGleb Smirnoff yyerror("multiple 'overload' "
25443b3a8eb9SGleb Smirnoff "table definitions");
25453b3a8eb9SGleb Smirnoff YYERROR;
25463b3a8eb9SGleb Smirnoff }
25473b3a8eb9SGleb Smirnoff if (strlcpy(r.overload_tblname,
25483b3a8eb9SGleb Smirnoff o->data.overload.tblname,
25493b3a8eb9SGleb Smirnoff PF_TABLE_NAME_SIZE) >=
25503b3a8eb9SGleb Smirnoff PF_TABLE_NAME_SIZE) {
25513b3a8eb9SGleb Smirnoff yyerror("state option: "
25523b3a8eb9SGleb Smirnoff "strlcpy");
25533b3a8eb9SGleb Smirnoff YYERROR;
25543b3a8eb9SGleb Smirnoff }
25553b3a8eb9SGleb Smirnoff r.flush = o->data.overload.flush;
25563b3a8eb9SGleb Smirnoff break;
25573b3a8eb9SGleb Smirnoff case PF_STATE_OPT_MAX_SRC_CONN:
25583b3a8eb9SGleb Smirnoff if (r.max_src_conn) {
25593b3a8eb9SGleb Smirnoff yyerror("state option "
25603b3a8eb9SGleb Smirnoff "'max-src-conn' "
25613b3a8eb9SGleb Smirnoff "multiple definitions");
25623b3a8eb9SGleb Smirnoff YYERROR;
25633b3a8eb9SGleb Smirnoff }
25643b3a8eb9SGleb Smirnoff if (o->data.max_src_conn == 0) {
25653b3a8eb9SGleb Smirnoff yyerror("'max-src-conn' "
25663b3a8eb9SGleb Smirnoff "must be > 0");
25673b3a8eb9SGleb Smirnoff YYERROR;
25683b3a8eb9SGleb Smirnoff }
25693b3a8eb9SGleb Smirnoff r.max_src_conn =
25703b3a8eb9SGleb Smirnoff o->data.max_src_conn;
25713b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_SRCTRACK |
25723b3a8eb9SGleb Smirnoff PFRULE_RULESRCTRACK;
25733b3a8eb9SGleb Smirnoff break;
25743b3a8eb9SGleb Smirnoff case PF_STATE_OPT_MAX_SRC_CONN_RATE:
25753b3a8eb9SGleb Smirnoff if (r.max_src_conn_rate.limit) {
25763b3a8eb9SGleb Smirnoff yyerror("state option "
25773b3a8eb9SGleb Smirnoff "'max-src-conn-rate' "
25783b3a8eb9SGleb Smirnoff "multiple definitions");
25793b3a8eb9SGleb Smirnoff YYERROR;
25803b3a8eb9SGleb Smirnoff }
25813b3a8eb9SGleb Smirnoff if (!o->data.max_src_conn_rate.limit ||
25823b3a8eb9SGleb Smirnoff !o->data.max_src_conn_rate.seconds) {
25833b3a8eb9SGleb Smirnoff yyerror("'max-src-conn-rate' "
25843b3a8eb9SGleb Smirnoff "values must be > 0");
25853b3a8eb9SGleb Smirnoff YYERROR;
25863b3a8eb9SGleb Smirnoff }
25873b3a8eb9SGleb Smirnoff if (o->data.max_src_conn_rate.limit >
25883b3a8eb9SGleb Smirnoff PF_THRESHOLD_MAX) {
25893b3a8eb9SGleb Smirnoff yyerror("'max-src-conn-rate' "
25903b3a8eb9SGleb Smirnoff "maximum rate must be < %u",
25913b3a8eb9SGleb Smirnoff PF_THRESHOLD_MAX);
25923b3a8eb9SGleb Smirnoff YYERROR;
25933b3a8eb9SGleb Smirnoff }
25943b3a8eb9SGleb Smirnoff r.max_src_conn_rate.limit =
25953b3a8eb9SGleb Smirnoff o->data.max_src_conn_rate.limit;
25963b3a8eb9SGleb Smirnoff r.max_src_conn_rate.seconds =
25973b3a8eb9SGleb Smirnoff o->data.max_src_conn_rate.seconds;
25983b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_SRCTRACK |
25993b3a8eb9SGleb Smirnoff PFRULE_RULESRCTRACK;
26003b3a8eb9SGleb Smirnoff break;
26013b3a8eb9SGleb Smirnoff case PF_STATE_OPT_MAX_SRC_NODES:
26023b3a8eb9SGleb Smirnoff if (r.max_src_nodes) {
26033b3a8eb9SGleb Smirnoff yyerror("state option "
26043b3a8eb9SGleb Smirnoff "'max-src-nodes' "
26053b3a8eb9SGleb Smirnoff "multiple definitions");
26063b3a8eb9SGleb Smirnoff YYERROR;
26073b3a8eb9SGleb Smirnoff }
26083b3a8eb9SGleb Smirnoff if (o->data.max_src_nodes == 0) {
26093b3a8eb9SGleb Smirnoff yyerror("'max-src-nodes' must "
26103b3a8eb9SGleb Smirnoff "be > 0");
26113b3a8eb9SGleb Smirnoff YYERROR;
26123b3a8eb9SGleb Smirnoff }
26133b3a8eb9SGleb Smirnoff r.max_src_nodes =
26143b3a8eb9SGleb Smirnoff o->data.max_src_nodes;
26153b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_SRCTRACK |
26163b3a8eb9SGleb Smirnoff PFRULE_RULESRCTRACK;
26173b3a8eb9SGleb Smirnoff break;
26183b3a8eb9SGleb Smirnoff case PF_STATE_OPT_STATELOCK:
26193b3a8eb9SGleb Smirnoff if (statelock) {
26203b3a8eb9SGleb Smirnoff yyerror("state locking option: "
26213b3a8eb9SGleb Smirnoff "multiple definitions");
26223b3a8eb9SGleb Smirnoff YYERROR;
26233b3a8eb9SGleb Smirnoff }
26243b3a8eb9SGleb Smirnoff statelock = 1;
26253b3a8eb9SGleb Smirnoff r.rule_flag |= o->data.statelock;
26263b3a8eb9SGleb Smirnoff break;
26273b3a8eb9SGleb Smirnoff case PF_STATE_OPT_SLOPPY:
26283b3a8eb9SGleb Smirnoff if (r.rule_flag & PFRULE_STATESLOPPY) {
26293b3a8eb9SGleb Smirnoff yyerror("state sloppy option: "
26303b3a8eb9SGleb Smirnoff "multiple definitions");
26313b3a8eb9SGleb Smirnoff YYERROR;
26323b3a8eb9SGleb Smirnoff }
26333b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_STATESLOPPY;
26343b3a8eb9SGleb Smirnoff break;
2635baf9b6d0SKristof Provost case PF_STATE_OPT_PFLOW:
2636baf9b6d0SKristof Provost if (r.rule_flag & PFRULE_PFLOW) {
2637baf9b6d0SKristof Provost yyerror("state pflow option: "
2638baf9b6d0SKristof Provost "multiple definitions");
2639baf9b6d0SKristof Provost YYERROR;
2640baf9b6d0SKristof Provost }
2641baf9b6d0SKristof Provost r.rule_flag |= PFRULE_PFLOW;
2642baf9b6d0SKristof Provost break;
2643e4f2733dSKristof Provost case PF_STATE_OPT_ALLOW_RELATED:
2644e4f2733dSKristof Provost if (r.rule_flag & PFRULE_ALLOW_RELATED) {
2645e4f2733dSKristof Provost yyerror("state allow-related option: "
2646e4f2733dSKristof Provost "multiple definitions");
2647e4f2733dSKristof Provost YYERROR;
2648e4f2733dSKristof Provost }
2649e4f2733dSKristof Provost r.rule_flag |= PFRULE_ALLOW_RELATED;
2650e4f2733dSKristof Provost break;
26513b3a8eb9SGleb Smirnoff case PF_STATE_OPT_TIMEOUT:
26523b3a8eb9SGleb Smirnoff if (o->data.timeout.number ==
26533b3a8eb9SGleb Smirnoff PFTM_ADAPTIVE_START ||
26543b3a8eb9SGleb Smirnoff o->data.timeout.number ==
26553b3a8eb9SGleb Smirnoff PFTM_ADAPTIVE_END)
26563b3a8eb9SGleb Smirnoff adaptive = 1;
26573b3a8eb9SGleb Smirnoff if (r.timeout[o->data.timeout.number]) {
26583b3a8eb9SGleb Smirnoff yyerror("state timeout %s "
26593b3a8eb9SGleb Smirnoff "multiple definitions",
26603b3a8eb9SGleb Smirnoff pf_timeouts[o->data.
26613b3a8eb9SGleb Smirnoff timeout.number].name);
26623b3a8eb9SGleb Smirnoff YYERROR;
26633b3a8eb9SGleb Smirnoff }
26643b3a8eb9SGleb Smirnoff r.timeout[o->data.timeout.number] =
26653b3a8eb9SGleb Smirnoff o->data.timeout.seconds;
26663b3a8eb9SGleb Smirnoff }
26673b3a8eb9SGleb Smirnoff o = o->next;
26683b3a8eb9SGleb Smirnoff if (!defaults)
26693b3a8eb9SGleb Smirnoff free(p);
26703b3a8eb9SGleb Smirnoff }
26713b3a8eb9SGleb Smirnoff
26723b3a8eb9SGleb Smirnoff /* 'flags S/SA' by default on stateful rules */
26733b3a8eb9SGleb Smirnoff if (!r.action && !r.flags && !r.flagset &&
26743b3a8eb9SGleb Smirnoff !$9.fragment && !($9.marker & FOM_FLAGS) &&
26753b3a8eb9SGleb Smirnoff r.keep_state) {
26763b3a8eb9SGleb Smirnoff r.flags = parse_flags("S");
26773b3a8eb9SGleb Smirnoff r.flagset = parse_flags("SA");
26783b3a8eb9SGleb Smirnoff }
26793b3a8eb9SGleb Smirnoff if (!adaptive && r.max_states) {
26803b3a8eb9SGleb Smirnoff r.timeout[PFTM_ADAPTIVE_START] =
26813b3a8eb9SGleb Smirnoff (r.max_states / 10) * 6;
26823b3a8eb9SGleb Smirnoff r.timeout[PFTM_ADAPTIVE_END] =
26833b3a8eb9SGleb Smirnoff (r.max_states / 10) * 12;
26843b3a8eb9SGleb Smirnoff }
26853b3a8eb9SGleb Smirnoff if (r.rule_flag & PFRULE_SRCTRACK) {
26863b3a8eb9SGleb Smirnoff if (srctrack == PF_SRCTRACK_GLOBAL &&
26873b3a8eb9SGleb Smirnoff r.max_src_nodes) {
26883b3a8eb9SGleb Smirnoff yyerror("'max-src-nodes' is "
26893b3a8eb9SGleb Smirnoff "incompatible with "
26903b3a8eb9SGleb Smirnoff "'source-track global'");
26913b3a8eb9SGleb Smirnoff YYERROR;
26923b3a8eb9SGleb Smirnoff }
26933b3a8eb9SGleb Smirnoff if (srctrack == PF_SRCTRACK_GLOBAL &&
26943b3a8eb9SGleb Smirnoff r.max_src_conn) {
26953b3a8eb9SGleb Smirnoff yyerror("'max-src-conn' is "
26963b3a8eb9SGleb Smirnoff "incompatible with "
26973b3a8eb9SGleb Smirnoff "'source-track global'");
26983b3a8eb9SGleb Smirnoff YYERROR;
26993b3a8eb9SGleb Smirnoff }
27003b3a8eb9SGleb Smirnoff if (srctrack == PF_SRCTRACK_GLOBAL &&
27013b3a8eb9SGleb Smirnoff r.max_src_conn_rate.seconds) {
27023b3a8eb9SGleb Smirnoff yyerror("'max-src-conn-rate' is "
27033b3a8eb9SGleb Smirnoff "incompatible with "
27043b3a8eb9SGleb Smirnoff "'source-track global'");
27053b3a8eb9SGleb Smirnoff YYERROR;
27063b3a8eb9SGleb Smirnoff }
27073b3a8eb9SGleb Smirnoff if (r.timeout[PFTM_SRC_NODE] <
27083b3a8eb9SGleb Smirnoff r.max_src_conn_rate.seconds)
27093b3a8eb9SGleb Smirnoff r.timeout[PFTM_SRC_NODE] =
27103b3a8eb9SGleb Smirnoff r.max_src_conn_rate.seconds;
27113b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_SRCTRACK;
27123b3a8eb9SGleb Smirnoff if (srctrack == PF_SRCTRACK_RULE)
27133b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_RULESRCTRACK;
27143b3a8eb9SGleb Smirnoff }
27153b3a8eb9SGleb Smirnoff if (r.keep_state && !statelock)
27163b3a8eb9SGleb Smirnoff r.rule_flag |= default_statelock;
27173b3a8eb9SGleb Smirnoff
27183b3a8eb9SGleb Smirnoff if ($9.fragment)
27193b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_FRAGMENT;
27203b3a8eb9SGleb Smirnoff r.allow_opts = $9.allowopts;
27213b3a8eb9SGleb Smirnoff
27223b3a8eb9SGleb Smirnoff decide_address_family($8.src.host, &r.af);
27233b3a8eb9SGleb Smirnoff decide_address_family($8.dst.host, &r.af);
27243b3a8eb9SGleb Smirnoff
27253b3a8eb9SGleb Smirnoff if ($5.rt) {
27263b3a8eb9SGleb Smirnoff if (!r.direction) {
27273b3a8eb9SGleb Smirnoff yyerror("direction must be explicit "
27283b3a8eb9SGleb Smirnoff "with rules that specify routing");
27293b3a8eb9SGleb Smirnoff YYERROR;
27303b3a8eb9SGleb Smirnoff }
27313b3a8eb9SGleb Smirnoff r.rt = $5.rt;
2732*aeddee83SKajetan Staszkiewicz decide_address_family($5.redirspec->host, &r.af);
2733ca0e6934SKristof Provost if (!(r.rule_flag & PFRULE_AFTO))
2734*aeddee83SKajetan Staszkiewicz remove_invalid_hosts(&($5.redirspec->host), &r.af);
2735*aeddee83SKajetan Staszkiewicz if ($5.redirspec->host == NULL) {
27363b3a8eb9SGleb Smirnoff yyerror("no routing address with "
27373b3a8eb9SGleb Smirnoff "matching address family found.");
27383b3a8eb9SGleb Smirnoff YYERROR;
27393b3a8eb9SGleb Smirnoff }
27403b3a8eb9SGleb Smirnoff }
27413b3a8eb9SGleb Smirnoff if ($9.queues.qname != NULL) {
27423b3a8eb9SGleb Smirnoff if (strlcpy(r.qname, $9.queues.qname,
27433b3a8eb9SGleb Smirnoff sizeof(r.qname)) >= sizeof(r.qname)) {
27443b3a8eb9SGleb Smirnoff yyerror("rule qname too long (max "
27453b3a8eb9SGleb Smirnoff "%d chars)", sizeof(r.qname)-1);
27463b3a8eb9SGleb Smirnoff YYERROR;
27473b3a8eb9SGleb Smirnoff }
27483b3a8eb9SGleb Smirnoff free($9.queues.qname);
27493b3a8eb9SGleb Smirnoff }
27503b3a8eb9SGleb Smirnoff if ($9.queues.pqname != NULL) {
27513b3a8eb9SGleb Smirnoff if (strlcpy(r.pqname, $9.queues.pqname,
27523b3a8eb9SGleb Smirnoff sizeof(r.pqname)) >= sizeof(r.pqname)) {
27533b3a8eb9SGleb Smirnoff yyerror("rule pqname too long (max "
27543b3a8eb9SGleb Smirnoff "%d chars)", sizeof(r.pqname)-1);
27553b3a8eb9SGleb Smirnoff YYERROR;
27563b3a8eb9SGleb Smirnoff }
27573b3a8eb9SGleb Smirnoff free($9.queues.pqname);
27583b3a8eb9SGleb Smirnoff }
27593b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__
27603b3a8eb9SGleb Smirnoff r.divert.port = $9.divert.port;
27613b3a8eb9SGleb Smirnoff #else
27623b3a8eb9SGleb Smirnoff if ((r.divert.port = $9.divert.port)) {
27633b3a8eb9SGleb Smirnoff if (r.direction == PF_OUT) {
27643b3a8eb9SGleb Smirnoff if ($9.divert.addr) {
27653b3a8eb9SGleb Smirnoff yyerror("address specified "
27663b3a8eb9SGleb Smirnoff "for outgoing divert");
27673b3a8eb9SGleb Smirnoff YYERROR;
27683b3a8eb9SGleb Smirnoff }
27693b3a8eb9SGleb Smirnoff bzero(&r.divert.addr,
27703b3a8eb9SGleb Smirnoff sizeof(r.divert.addr));
27713b3a8eb9SGleb Smirnoff } else {
27723b3a8eb9SGleb Smirnoff if (!$9.divert.addr) {
27733b3a8eb9SGleb Smirnoff yyerror("no address specified "
27743b3a8eb9SGleb Smirnoff "for incoming divert");
27753b3a8eb9SGleb Smirnoff YYERROR;
27763b3a8eb9SGleb Smirnoff }
27773b3a8eb9SGleb Smirnoff if ($9.divert.addr->af != r.af) {
27783b3a8eb9SGleb Smirnoff yyerror("address family "
27793b3a8eb9SGleb Smirnoff "mismatch for divert");
27803b3a8eb9SGleb Smirnoff YYERROR;
27813b3a8eb9SGleb Smirnoff }
27823b3a8eb9SGleb Smirnoff r.divert.addr =
27833b3a8eb9SGleb Smirnoff $9.divert.addr->addr.v.a.addr;
27843b3a8eb9SGleb Smirnoff }
27853b3a8eb9SGleb Smirnoff }
27863b3a8eb9SGleb Smirnoff #endif
27873b3a8eb9SGleb Smirnoff
278863b3c1c7SKristof Provost if ($9.dnpipe || $9.dnrpipe) {
278963b3c1c7SKristof Provost r.dnpipe = $9.dnpipe;
279063b3c1c7SKristof Provost r.dnrpipe = $9.dnrpipe;
279163b3c1c7SKristof Provost if ($9.free_flags & PFRULE_DN_IS_PIPE)
279263b3c1c7SKristof Provost r.free_flags |= PFRULE_DN_IS_PIPE;
279363b3c1c7SKristof Provost else
279463b3c1c7SKristof Provost r.free_flags |= PFRULE_DN_IS_QUEUE;
279563b3c1c7SKristof Provost }
279663b3c1c7SKristof Provost
2797e0dcc51dSKristof Provost if ($9.marker & FOM_AFTO) {
2798*aeddee83SKajetan Staszkiewicz r.naf = $9.nat->af;
2799e0dcc51dSKristof Provost }
2800e0dcc51dSKristof Provost
2801*aeddee83SKajetan Staszkiewicz expand_rule(&r, $4, $9.nat, $9.rdr, $5.redirspec,
2802aa69fdf1SKristof Provost $7, $8.src_os, $8.src.host, $8.src.port, $8.dst.host,
2803aa69fdf1SKristof Provost $8.dst.port, $9.uid, $9.gid, $9.rcv, $9.icmpspec, "");
28043b3a8eb9SGleb Smirnoff }
28053b3a8eb9SGleb Smirnoff ;
28063b3a8eb9SGleb Smirnoff
28073b3a8eb9SGleb Smirnoff filter_opts : {
28083b3a8eb9SGleb Smirnoff bzero(&filter_opts, sizeof filter_opts);
28093b3a8eb9SGleb Smirnoff filter_opts.rtableid = -1;
28103b3a8eb9SGleb Smirnoff }
28113b3a8eb9SGleb Smirnoff filter_opts_l
28123b3a8eb9SGleb Smirnoff { $$ = filter_opts; }
28133b3a8eb9SGleb Smirnoff | /* empty */ {
28143b3a8eb9SGleb Smirnoff bzero(&filter_opts, sizeof filter_opts);
28153b3a8eb9SGleb Smirnoff filter_opts.rtableid = -1;
28163b3a8eb9SGleb Smirnoff $$ = filter_opts;
28173b3a8eb9SGleb Smirnoff }
28183b3a8eb9SGleb Smirnoff ;
28193b3a8eb9SGleb Smirnoff
28203b3a8eb9SGleb Smirnoff filter_opts_l : filter_opts_l filter_opt
28213b3a8eb9SGleb Smirnoff | filter_opt
28223b3a8eb9SGleb Smirnoff ;
28233b3a8eb9SGleb Smirnoff
28243b3a8eb9SGleb Smirnoff filter_opt : USER uids {
28253b3a8eb9SGleb Smirnoff if (filter_opts.uid)
28263b3a8eb9SGleb Smirnoff $2->tail->next = filter_opts.uid;
28273b3a8eb9SGleb Smirnoff filter_opts.uid = $2;
28283b3a8eb9SGleb Smirnoff }
28293b3a8eb9SGleb Smirnoff | GROUP gids {
28303b3a8eb9SGleb Smirnoff if (filter_opts.gid)
28313b3a8eb9SGleb Smirnoff $2->tail->next = filter_opts.gid;
28323b3a8eb9SGleb Smirnoff filter_opts.gid = $2;
28333b3a8eb9SGleb Smirnoff }
28343b3a8eb9SGleb Smirnoff | flags {
28353b3a8eb9SGleb Smirnoff if (filter_opts.marker & FOM_FLAGS) {
28363b3a8eb9SGleb Smirnoff yyerror("flags cannot be redefined");
28373b3a8eb9SGleb Smirnoff YYERROR;
28383b3a8eb9SGleb Smirnoff }
28393b3a8eb9SGleb Smirnoff filter_opts.marker |= FOM_FLAGS;
28403b3a8eb9SGleb Smirnoff filter_opts.flags.b1 |= $1.b1;
28413b3a8eb9SGleb Smirnoff filter_opts.flags.b2 |= $1.b2;
28423b3a8eb9SGleb Smirnoff filter_opts.flags.w |= $1.w;
28433b3a8eb9SGleb Smirnoff filter_opts.flags.w2 |= $1.w2;
28443b3a8eb9SGleb Smirnoff }
28453b3a8eb9SGleb Smirnoff | icmpspec {
28463b3a8eb9SGleb Smirnoff if (filter_opts.marker & FOM_ICMP) {
28473b3a8eb9SGleb Smirnoff yyerror("icmp-type cannot be redefined");
28483b3a8eb9SGleb Smirnoff YYERROR;
28493b3a8eb9SGleb Smirnoff }
28503b3a8eb9SGleb Smirnoff filter_opts.marker |= FOM_ICMP;
28513b3a8eb9SGleb Smirnoff filter_opts.icmpspec = $1;
28523b3a8eb9SGleb Smirnoff }
28533e248e0fSKristof Provost | PRIO NUMBER {
28543e248e0fSKristof Provost if (filter_opts.marker & FOM_PRIO) {
28553e248e0fSKristof Provost yyerror("prio cannot be redefined");
28563e248e0fSKristof Provost YYERROR;
28573e248e0fSKristof Provost }
28583e248e0fSKristof Provost if ($2 < 0 || $2 > PF_PRIO_MAX) {
28593e248e0fSKristof Provost yyerror("prio must be 0 - %u", PF_PRIO_MAX);
28603e248e0fSKristof Provost YYERROR;
28613e248e0fSKristof Provost }
28623e248e0fSKristof Provost filter_opts.marker |= FOM_PRIO;
28633e248e0fSKristof Provost filter_opts.prio = $2;
28643e248e0fSKristof Provost }
28653b3a8eb9SGleb Smirnoff | TOS tos {
28663b3a8eb9SGleb Smirnoff if (filter_opts.marker & FOM_TOS) {
28673b3a8eb9SGleb Smirnoff yyerror("tos cannot be redefined");
28683b3a8eb9SGleb Smirnoff YYERROR;
28693b3a8eb9SGleb Smirnoff }
28703b3a8eb9SGleb Smirnoff filter_opts.marker |= FOM_TOS;
28713b3a8eb9SGleb Smirnoff filter_opts.tos = $2;
28723b3a8eb9SGleb Smirnoff }
28733b3a8eb9SGleb Smirnoff | keep {
28743b3a8eb9SGleb Smirnoff if (filter_opts.marker & FOM_KEEP) {
28753b3a8eb9SGleb Smirnoff yyerror("modulate or keep cannot be redefined");
28763b3a8eb9SGleb Smirnoff YYERROR;
28773b3a8eb9SGleb Smirnoff }
28783b3a8eb9SGleb Smirnoff filter_opts.marker |= FOM_KEEP;
28793b3a8eb9SGleb Smirnoff filter_opts.keep.action = $1.action;
28803b3a8eb9SGleb Smirnoff filter_opts.keep.options = $1.options;
28813b3a8eb9SGleb Smirnoff }
288276c5eeccSKristof Provost | RIDENTIFIER number {
288376c5eeccSKristof Provost filter_opts.ridentifier = $2;
288476c5eeccSKristof Provost }
28853b3a8eb9SGleb Smirnoff | FRAGMENT {
28863b3a8eb9SGleb Smirnoff filter_opts.fragment = 1;
28873b3a8eb9SGleb Smirnoff }
28883b3a8eb9SGleb Smirnoff | ALLOWOPTS {
28893b3a8eb9SGleb Smirnoff filter_opts.allowopts = 1;
28903b3a8eb9SGleb Smirnoff }
28913b3a8eb9SGleb Smirnoff | label {
28926fcc8e04SKristof Provost if (filter_opts.labelcount >= PF_RULE_MAX_LABEL_COUNT) {
28936fcc8e04SKristof Provost yyerror("label can only be used %d times", PF_RULE_MAX_LABEL_COUNT);
28943b3a8eb9SGleb Smirnoff YYERROR;
28953b3a8eb9SGleb Smirnoff }
28966fcc8e04SKristof Provost filter_opts.label[filter_opts.labelcount++] = $1;
28973b3a8eb9SGleb Smirnoff }
28983b3a8eb9SGleb Smirnoff | qname {
28993b3a8eb9SGleb Smirnoff if (filter_opts.queues.qname) {
29003b3a8eb9SGleb Smirnoff yyerror("queue cannot be redefined");
29013b3a8eb9SGleb Smirnoff YYERROR;
29023b3a8eb9SGleb Smirnoff }
29033b3a8eb9SGleb Smirnoff filter_opts.queues = $1;
29043b3a8eb9SGleb Smirnoff }
290563b3c1c7SKristof Provost | DNPIPE number {
290663b3c1c7SKristof Provost filter_opts.dnpipe = $2;
290763b3c1c7SKristof Provost filter_opts.free_flags |= PFRULE_DN_IS_PIPE;
290863b3c1c7SKristof Provost }
290963b3c1c7SKristof Provost | DNPIPE '(' number ')' {
291063b3c1c7SKristof Provost filter_opts.dnpipe = $3;
291163b3c1c7SKristof Provost filter_opts.free_flags |= PFRULE_DN_IS_PIPE;
291263b3c1c7SKristof Provost }
291363b3c1c7SKristof Provost | DNPIPE '(' number comma number ')' {
291463b3c1c7SKristof Provost filter_opts.dnrpipe = $5;
291563b3c1c7SKristof Provost filter_opts.dnpipe = $3;
291663b3c1c7SKristof Provost filter_opts.free_flags |= PFRULE_DN_IS_PIPE;
291763b3c1c7SKristof Provost }
291863b3c1c7SKristof Provost | DNQUEUE number {
291963b3c1c7SKristof Provost filter_opts.dnpipe = $2;
292063b3c1c7SKristof Provost filter_opts.free_flags |= PFRULE_DN_IS_QUEUE;
292163b3c1c7SKristof Provost }
292263b3c1c7SKristof Provost | DNQUEUE '(' number comma number ')' {
292363b3c1c7SKristof Provost filter_opts.dnrpipe = $5;
292463b3c1c7SKristof Provost filter_opts.dnpipe = $3;
292563b3c1c7SKristof Provost filter_opts.free_flags |= PFRULE_DN_IS_QUEUE;
292663b3c1c7SKristof Provost }
292763b3c1c7SKristof Provost | DNQUEUE '(' number ')' {
292863b3c1c7SKristof Provost filter_opts.dnpipe = $3;
292963b3c1c7SKristof Provost filter_opts.free_flags |= PFRULE_DN_IS_QUEUE;
293063b3c1c7SKristof Provost }
29313b3a8eb9SGleb Smirnoff | TAG string {
29323b3a8eb9SGleb Smirnoff filter_opts.tag = $2;
29333b3a8eb9SGleb Smirnoff }
29343b3a8eb9SGleb Smirnoff | not TAGGED string {
29353b3a8eb9SGleb Smirnoff filter_opts.match_tag = $3;
29363b3a8eb9SGleb Smirnoff filter_opts.match_tag_not = $1;
29373b3a8eb9SGleb Smirnoff }
293871594e32SKristof Provost | not RECEIVEDON if_item {
29392339ead6SKristof Provost if (filter_opts.rcv) {
29402339ead6SKristof Provost yyerror("cannot respecify received-on");
29412339ead6SKristof Provost YYERROR;
29422339ead6SKristof Provost }
294371594e32SKristof Provost filter_opts.rcv = $3;
294471594e32SKristof Provost filter_opts.rcv->not = $1;
29452339ead6SKristof Provost }
29463b3a8eb9SGleb Smirnoff | PROBABILITY probability {
29473b3a8eb9SGleb Smirnoff double p;
29483b3a8eb9SGleb Smirnoff
29493b3a8eb9SGleb Smirnoff p = floor($2 * UINT_MAX + 0.5);
29503b3a8eb9SGleb Smirnoff if (p < 0.0 || p > UINT_MAX) {
29513b3a8eb9SGleb Smirnoff yyerror("invalid probability: %lf", p);
29523b3a8eb9SGleb Smirnoff YYERROR;
29533b3a8eb9SGleb Smirnoff }
29543b3a8eb9SGleb Smirnoff filter_opts.prob = (u_int32_t)p;
29553b3a8eb9SGleb Smirnoff if (filter_opts.prob == 0)
29563b3a8eb9SGleb Smirnoff filter_opts.prob = 1;
29573b3a8eb9SGleb Smirnoff }
29583b3a8eb9SGleb Smirnoff | RTABLE NUMBER {
29593b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > rt_tableid_max()) {
29603b3a8eb9SGleb Smirnoff yyerror("invalid rtable id");
29613b3a8eb9SGleb Smirnoff YYERROR;
29623b3a8eb9SGleb Smirnoff }
29633b3a8eb9SGleb Smirnoff filter_opts.rtableid = $2;
29643b3a8eb9SGleb Smirnoff }
29653b3a8eb9SGleb Smirnoff | DIVERTTO portplain {
29663b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__
29673b3a8eb9SGleb Smirnoff filter_opts.divert.port = $2.a;
29683b3a8eb9SGleb Smirnoff if (!filter_opts.divert.port) {
29693b3a8eb9SGleb Smirnoff yyerror("invalid divert port: %u", ntohs($2.a));
29703b3a8eb9SGleb Smirnoff YYERROR;
29713b3a8eb9SGleb Smirnoff }
29723b3a8eb9SGleb Smirnoff #endif
29733b3a8eb9SGleb Smirnoff }
29743b3a8eb9SGleb Smirnoff | DIVERTTO STRING PORT portplain {
29753b3a8eb9SGleb Smirnoff #ifndef __FreeBSD__
29763b3a8eb9SGleb Smirnoff if ((filter_opts.divert.addr = host($2)) == NULL) {
29773b3a8eb9SGleb Smirnoff yyerror("could not parse divert address: %s",
29783b3a8eb9SGleb Smirnoff $2);
29793b3a8eb9SGleb Smirnoff free($2);
29803b3a8eb9SGleb Smirnoff YYERROR;
29813b3a8eb9SGleb Smirnoff }
29823b3a8eb9SGleb Smirnoff #else
29833b3a8eb9SGleb Smirnoff if ($2)
29843b3a8eb9SGleb Smirnoff #endif
29853b3a8eb9SGleb Smirnoff free($2);
29863b3a8eb9SGleb Smirnoff filter_opts.divert.port = $4.a;
29873b3a8eb9SGleb Smirnoff if (!filter_opts.divert.port) {
29883b3a8eb9SGleb Smirnoff yyerror("invalid divert port: %u", ntohs($4.a));
29893b3a8eb9SGleb Smirnoff YYERROR;
29903b3a8eb9SGleb Smirnoff }
29913b3a8eb9SGleb Smirnoff }
29923b3a8eb9SGleb Smirnoff | DIVERTREPLY {
29933b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__
29943b3a8eb9SGleb Smirnoff yyerror("divert-reply has no meaning in FreeBSD pf(4)");
29953b3a8eb9SGleb Smirnoff YYERROR;
29963b3a8eb9SGleb Smirnoff #else
29973b3a8eb9SGleb Smirnoff filter_opts.divert.port = 1; /* some random value */
29983b3a8eb9SGleb Smirnoff #endif
29993b3a8eb9SGleb Smirnoff }
300039282ef3SKajetan Staszkiewicz | SCRUB '(' scrub_opts ')' {
300139282ef3SKajetan Staszkiewicz filter_opts.nodf = $3.nodf;
300239282ef3SKajetan Staszkiewicz filter_opts.minttl = $3.minttl;
300339282ef3SKajetan Staszkiewicz if ($3.marker & FOM_SETTOS) {
300439282ef3SKajetan Staszkiewicz /* Old style rules are "scrub set-tos 0x42"
300539282ef3SKajetan Staszkiewicz * New style are "set tos 0x42 scrub (...)"
300639282ef3SKajetan Staszkiewicz * What is in "scrub(...)"" is unfortunately the
300739282ef3SKajetan Staszkiewicz * original scrub syntax so it would overwrite
300839282ef3SKajetan Staszkiewicz * "set tos" of a pass/match rule.
300939282ef3SKajetan Staszkiewicz */
301039282ef3SKajetan Staszkiewicz filter_opts.settos = $3.settos;
301139282ef3SKajetan Staszkiewicz }
301239282ef3SKajetan Staszkiewicz filter_opts.randomid = $3.randomid;
301339282ef3SKajetan Staszkiewicz filter_opts.max_mss = $3.maxmss;
301439282ef3SKajetan Staszkiewicz if ($3.reassemble_tcp)
301539282ef3SKajetan Staszkiewicz filter_opts.marker |= FOM_SCRUB_TCP;
301639282ef3SKajetan Staszkiewicz filter_opts.marker |= $3.marker;
301739282ef3SKajetan Staszkiewicz }
3018*aeddee83SKajetan Staszkiewicz | AFTO af FROM port_redirspec {
3019*aeddee83SKajetan Staszkiewicz if (filter_opts.nat) {
3020aa69fdf1SKristof Provost yyerror("cannot respecify af-to");
3021aa69fdf1SKristof Provost YYERROR;
3022aa69fdf1SKristof Provost }
3023aa69fdf1SKristof Provost if ($2 == 0) {
3024aa69fdf1SKristof Provost yyerror("no address family specified");
3025aa69fdf1SKristof Provost YYERROR;
3026aa69fdf1SKristof Provost }
3027*aeddee83SKajetan Staszkiewicz
3028*aeddee83SKajetan Staszkiewicz filter_opts.nat = $4;
3029*aeddee83SKajetan Staszkiewicz filter_opts.nat->af = $2;
3030aa69fdf1SKristof Provost if ($4->af && $4->af != $2) {
3031aa69fdf1SKristof Provost yyerror("af-to addresses must be in the "
3032aa69fdf1SKristof Provost "target address family");
3033aa69fdf1SKristof Provost YYERROR;
3034aa69fdf1SKristof Provost }
3035aa69fdf1SKristof Provost filter_opts.marker |= FOM_AFTO;
3036aa69fdf1SKristof Provost }
3037*aeddee83SKajetan Staszkiewicz | AFTO af FROM port_redirspec TO port_redirspec {
3038*aeddee83SKajetan Staszkiewicz if (filter_opts.nat) {
3039aa69fdf1SKristof Provost yyerror("cannot respecify af-to");
3040aa69fdf1SKristof Provost YYERROR;
3041aa69fdf1SKristof Provost }
3042aa69fdf1SKristof Provost if ($2 == 0) {
3043aa69fdf1SKristof Provost yyerror("no address family specified");
3044aa69fdf1SKristof Provost YYERROR;
3045aa69fdf1SKristof Provost }
3046*aeddee83SKajetan Staszkiewicz filter_opts.nat = $4;
3047*aeddee83SKajetan Staszkiewicz filter_opts.nat->af = $2;
3048*aeddee83SKajetan Staszkiewicz filter_opts.rdr = $6;
3049*aeddee83SKajetan Staszkiewicz filter_opts.rdr->af = $2;
3050*aeddee83SKajetan Staszkiewicz if (($4->af && $4->host->af != $2) ||
3051*aeddee83SKajetan Staszkiewicz ($6->af && $6->host->af != $2)) {
3052aa69fdf1SKristof Provost yyerror("af-to addresses must be in the "
3053aa69fdf1SKristof Provost "target address family");
3054aa69fdf1SKristof Provost YYERROR;
3055aa69fdf1SKristof Provost }
3056aa69fdf1SKristof Provost filter_opts.marker |= FOM_AFTO;
3057aa69fdf1SKristof Provost }
30583e248e0fSKristof Provost | filter_sets
30593e248e0fSKristof Provost ;
30603e248e0fSKristof Provost
30613e248e0fSKristof Provost filter_sets : SET '(' filter_sets_l ')' { $$ = filter_opts; }
30623e248e0fSKristof Provost | SET filter_set { $$ = filter_opts; }
30633e248e0fSKristof Provost ;
30643e248e0fSKristof Provost
30653e248e0fSKristof Provost filter_sets_l : filter_sets_l comma filter_set
30663e248e0fSKristof Provost | filter_set
30673e248e0fSKristof Provost ;
30683e248e0fSKristof Provost
30693e248e0fSKristof Provost filter_set : prio {
30703e248e0fSKristof Provost if (filter_opts.marker & FOM_SETPRIO) {
30713e248e0fSKristof Provost yyerror("prio cannot be redefined");
30723e248e0fSKristof Provost YYERROR;
30733e248e0fSKristof Provost }
30743e248e0fSKristof Provost filter_opts.marker |= FOM_SETPRIO;
30753e248e0fSKristof Provost filter_opts.set_prio[0] = $1.b1;
30763e248e0fSKristof Provost filter_opts.set_prio[1] = $1.b2;
30773e248e0fSKristof Provost }
307839282ef3SKajetan Staszkiewicz | TOS tos {
307939282ef3SKajetan Staszkiewicz if (filter_opts.marker & FOM_SETTOS) {
308039282ef3SKajetan Staszkiewicz yyerror("tos cannot be respecified");
308139282ef3SKajetan Staszkiewicz YYERROR;
308239282ef3SKajetan Staszkiewicz }
308339282ef3SKajetan Staszkiewicz filter_opts.marker |= FOM_SETTOS;
308439282ef3SKajetan Staszkiewicz filter_opts.settos = $2;
308539282ef3SKajetan Staszkiewicz }
30863e248e0fSKristof Provost prio : PRIO NUMBER {
30873e248e0fSKristof Provost if ($2 < 0 || $2 > PF_PRIO_MAX) {
30883e248e0fSKristof Provost yyerror("prio must be 0 - %u", PF_PRIO_MAX);
30893e248e0fSKristof Provost YYERROR;
30903e248e0fSKristof Provost }
30913e248e0fSKristof Provost $$.b1 = $$.b2 = $2;
30923e248e0fSKristof Provost }
30933e248e0fSKristof Provost | PRIO '(' NUMBER comma NUMBER ')' {
30943e248e0fSKristof Provost if ($3 < 0 || $3 > PF_PRIO_MAX ||
30953e248e0fSKristof Provost $5 < 0 || $5 > PF_PRIO_MAX) {
30963e248e0fSKristof Provost yyerror("prio must be 0 - %u", PF_PRIO_MAX);
30973e248e0fSKristof Provost YYERROR;
30983e248e0fSKristof Provost }
30993e248e0fSKristof Provost $$.b1 = $3;
31003e248e0fSKristof Provost $$.b2 = $5;
31013e248e0fSKristof Provost }
31023b3a8eb9SGleb Smirnoff ;
31033b3a8eb9SGleb Smirnoff
31043b3a8eb9SGleb Smirnoff probability : STRING {
31053b3a8eb9SGleb Smirnoff char *e;
31063b3a8eb9SGleb Smirnoff double p = strtod($1, &e);
31073b3a8eb9SGleb Smirnoff
31083b3a8eb9SGleb Smirnoff if (*e == '%') {
31093b3a8eb9SGleb Smirnoff p *= 0.01;
31103b3a8eb9SGleb Smirnoff e++;
31113b3a8eb9SGleb Smirnoff }
31123b3a8eb9SGleb Smirnoff if (*e) {
31133b3a8eb9SGleb Smirnoff yyerror("invalid probability: %s", $1);
31143b3a8eb9SGleb Smirnoff free($1);
31153b3a8eb9SGleb Smirnoff YYERROR;
31163b3a8eb9SGleb Smirnoff }
31173b3a8eb9SGleb Smirnoff free($1);
31183b3a8eb9SGleb Smirnoff $$ = p;
31193b3a8eb9SGleb Smirnoff }
31203b3a8eb9SGleb Smirnoff | NUMBER {
31213b3a8eb9SGleb Smirnoff $$ = (double)$1;
31223b3a8eb9SGleb Smirnoff }
31233b3a8eb9SGleb Smirnoff ;
31243b3a8eb9SGleb Smirnoff
31253b3a8eb9SGleb Smirnoff
3126150182e3SKristof Provost action : PASS {
3127150182e3SKristof Provost $$.b1 = PF_PASS;
3128150182e3SKristof Provost $$.b2 = failpolicy;
3129150182e3SKristof Provost $$.w = returnicmpdefault;
3130150182e3SKristof Provost $$.w2 = returnicmp6default;
3131150182e3SKristof Provost }
3132ef950daaSKristof Provost | MATCH { $$.b1 = PF_MATCH; $$.b2 = $$.w = 0; }
31333b3a8eb9SGleb Smirnoff | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; }
31343b3a8eb9SGleb Smirnoff ;
31353b3a8eb9SGleb Smirnoff
31363b3a8eb9SGleb Smirnoff blockspec : /* empty */ {
31373b3a8eb9SGleb Smirnoff $$.b2 = blockpolicy;
31383b3a8eb9SGleb Smirnoff $$.w = returnicmpdefault;
31393b3a8eb9SGleb Smirnoff $$.w2 = returnicmp6default;
31403b3a8eb9SGleb Smirnoff }
31413b3a8eb9SGleb Smirnoff | DROP {
31423b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_DROP;
31433b3a8eb9SGleb Smirnoff $$.w = 0;
31443b3a8eb9SGleb Smirnoff $$.w2 = 0;
31453b3a8eb9SGleb Smirnoff }
31463b3a8eb9SGleb Smirnoff | RETURNRST {
31473b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURNRST;
31483b3a8eb9SGleb Smirnoff $$.w = 0;
31493b3a8eb9SGleb Smirnoff $$.w2 = 0;
31503b3a8eb9SGleb Smirnoff }
31513b3a8eb9SGleb Smirnoff | RETURNRST '(' TTL NUMBER ')' {
31523b3a8eb9SGleb Smirnoff if ($4 < 0 || $4 > 255) {
31533b3a8eb9SGleb Smirnoff yyerror("illegal ttl value %d", $4);
31543b3a8eb9SGleb Smirnoff YYERROR;
31553b3a8eb9SGleb Smirnoff }
31563b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURNRST;
31573b3a8eb9SGleb Smirnoff $$.w = $4;
31583b3a8eb9SGleb Smirnoff $$.w2 = 0;
31593b3a8eb9SGleb Smirnoff }
31603b3a8eb9SGleb Smirnoff | RETURNICMP {
31613b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURNICMP;
31623b3a8eb9SGleb Smirnoff $$.w = returnicmpdefault;
31633b3a8eb9SGleb Smirnoff $$.w2 = returnicmp6default;
31643b3a8eb9SGleb Smirnoff }
31653b3a8eb9SGleb Smirnoff | RETURNICMP6 {
31663b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURNICMP;
31673b3a8eb9SGleb Smirnoff $$.w = returnicmpdefault;
31683b3a8eb9SGleb Smirnoff $$.w2 = returnicmp6default;
31693b3a8eb9SGleb Smirnoff }
31703b3a8eb9SGleb Smirnoff | RETURNICMP '(' reticmpspec ')' {
31713b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURNICMP;
31723b3a8eb9SGleb Smirnoff $$.w = $3;
31733b3a8eb9SGleb Smirnoff $$.w2 = returnicmpdefault;
31743b3a8eb9SGleb Smirnoff }
31753b3a8eb9SGleb Smirnoff | RETURNICMP6 '(' reticmp6spec ')' {
31763b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURNICMP;
31773b3a8eb9SGleb Smirnoff $$.w = returnicmpdefault;
31783b3a8eb9SGleb Smirnoff $$.w2 = $3;
31793b3a8eb9SGleb Smirnoff }
31803b3a8eb9SGleb Smirnoff | RETURNICMP '(' reticmpspec comma reticmp6spec ')' {
31813b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURNICMP;
31823b3a8eb9SGleb Smirnoff $$.w = $3;
31833b3a8eb9SGleb Smirnoff $$.w2 = $5;
31843b3a8eb9SGleb Smirnoff }
31853b3a8eb9SGleb Smirnoff | RETURN {
31863b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURN;
31873b3a8eb9SGleb Smirnoff $$.w = returnicmpdefault;
31883b3a8eb9SGleb Smirnoff $$.w2 = returnicmp6default;
31893b3a8eb9SGleb Smirnoff }
31903b3a8eb9SGleb Smirnoff ;
31913b3a8eb9SGleb Smirnoff
31923b3a8eb9SGleb Smirnoff reticmpspec : STRING {
31933b3a8eb9SGleb Smirnoff if (!($$ = parseicmpspec($1, AF_INET))) {
31943b3a8eb9SGleb Smirnoff free($1);
31953b3a8eb9SGleb Smirnoff YYERROR;
31963b3a8eb9SGleb Smirnoff }
31973b3a8eb9SGleb Smirnoff free($1);
31983b3a8eb9SGleb Smirnoff }
31993b3a8eb9SGleb Smirnoff | NUMBER {
32003b3a8eb9SGleb Smirnoff u_int8_t icmptype;
32013b3a8eb9SGleb Smirnoff
32023b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 > 255) {
32033b3a8eb9SGleb Smirnoff yyerror("invalid icmp code %lu", $1);
32043b3a8eb9SGleb Smirnoff YYERROR;
32053b3a8eb9SGleb Smirnoff }
32063b3a8eb9SGleb Smirnoff icmptype = returnicmpdefault >> 8;
32073b3a8eb9SGleb Smirnoff $$ = (icmptype << 8 | $1);
32083b3a8eb9SGleb Smirnoff }
32093b3a8eb9SGleb Smirnoff ;
32103b3a8eb9SGleb Smirnoff
32113b3a8eb9SGleb Smirnoff reticmp6spec : STRING {
32123b3a8eb9SGleb Smirnoff if (!($$ = parseicmpspec($1, AF_INET6))) {
32133b3a8eb9SGleb Smirnoff free($1);
32143b3a8eb9SGleb Smirnoff YYERROR;
32153b3a8eb9SGleb Smirnoff }
32163b3a8eb9SGleb Smirnoff free($1);
32173b3a8eb9SGleb Smirnoff }
32183b3a8eb9SGleb Smirnoff | NUMBER {
32193b3a8eb9SGleb Smirnoff u_int8_t icmptype;
32203b3a8eb9SGleb Smirnoff
32213b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 > 255) {
32223b3a8eb9SGleb Smirnoff yyerror("invalid icmp code %lu", $1);
32233b3a8eb9SGleb Smirnoff YYERROR;
32243b3a8eb9SGleb Smirnoff }
32253b3a8eb9SGleb Smirnoff icmptype = returnicmp6default >> 8;
32263b3a8eb9SGleb Smirnoff $$ = (icmptype << 8 | $1);
32273b3a8eb9SGleb Smirnoff }
32283b3a8eb9SGleb Smirnoff ;
32293b3a8eb9SGleb Smirnoff
32303b3a8eb9SGleb Smirnoff dir : /* empty */ { $$ = PF_INOUT; }
32313b3a8eb9SGleb Smirnoff | IN { $$ = PF_IN; }
32323b3a8eb9SGleb Smirnoff | OUT { $$ = PF_OUT; }
32333b3a8eb9SGleb Smirnoff ;
32343b3a8eb9SGleb Smirnoff
32353b3a8eb9SGleb Smirnoff quick : /* empty */ { $$.quick = 0; }
32363b3a8eb9SGleb Smirnoff | QUICK { $$.quick = 1; }
32373b3a8eb9SGleb Smirnoff ;
32383b3a8eb9SGleb Smirnoff
32393b3a8eb9SGleb Smirnoff logquick : /* empty */ { $$.log = 0; $$.quick = 0; $$.logif = 0; }
32403b3a8eb9SGleb Smirnoff | log { $$ = $1; $$.quick = 0; }
32413b3a8eb9SGleb Smirnoff | QUICK { $$.quick = 1; $$.log = 0; $$.logif = 0; }
32423b3a8eb9SGleb Smirnoff | log QUICK { $$ = $1; $$.quick = 1; }
32433b3a8eb9SGleb Smirnoff | QUICK log { $$ = $2; $$.quick = 1; }
32443b3a8eb9SGleb Smirnoff ;
32453b3a8eb9SGleb Smirnoff
32463b3a8eb9SGleb Smirnoff log : LOG { $$.log = PF_LOG; $$.logif = 0; }
32473b3a8eb9SGleb Smirnoff | LOG '(' logopts ')' {
32483b3a8eb9SGleb Smirnoff $$.log = PF_LOG | $3.log;
32493b3a8eb9SGleb Smirnoff $$.logif = $3.logif;
32503b3a8eb9SGleb Smirnoff }
32513b3a8eb9SGleb Smirnoff ;
32523b3a8eb9SGleb Smirnoff
32533b3a8eb9SGleb Smirnoff logopts : logopt { $$ = $1; }
32543b3a8eb9SGleb Smirnoff | logopts comma logopt {
32553b3a8eb9SGleb Smirnoff $$.log = $1.log | $3.log;
32563b3a8eb9SGleb Smirnoff $$.logif = $3.logif;
32573b3a8eb9SGleb Smirnoff if ($$.logif == 0)
32583b3a8eb9SGleb Smirnoff $$.logif = $1.logif;
32593b3a8eb9SGleb Smirnoff }
32603b3a8eb9SGleb Smirnoff ;
32613b3a8eb9SGleb Smirnoff
32623b3a8eb9SGleb Smirnoff logopt : ALL { $$.log = PF_LOG_ALL; $$.logif = 0; }
3263f3ab00c2SKristof Provost | MATCHES { $$.log = PF_LOG_MATCHES; $$.logif = 0; }
32643b3a8eb9SGleb Smirnoff | USER { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; }
32653b3a8eb9SGleb Smirnoff | GROUP { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; }
32663b3a8eb9SGleb Smirnoff | TO string {
32673b3a8eb9SGleb Smirnoff const char *errstr;
32683b3a8eb9SGleb Smirnoff u_int i;
32693b3a8eb9SGleb Smirnoff
32703b3a8eb9SGleb Smirnoff $$.log = 0;
32713b3a8eb9SGleb Smirnoff if (strncmp($2, "pflog", 5)) {
32723b3a8eb9SGleb Smirnoff yyerror("%s: should be a pflog interface", $2);
32733b3a8eb9SGleb Smirnoff free($2);
32743b3a8eb9SGleb Smirnoff YYERROR;
32753b3a8eb9SGleb Smirnoff }
32763b3a8eb9SGleb Smirnoff i = strtonum($2 + 5, 0, 255, &errstr);
32773b3a8eb9SGleb Smirnoff if (errstr) {
32783b3a8eb9SGleb Smirnoff yyerror("%s: %s", $2, errstr);
32793b3a8eb9SGleb Smirnoff free($2);
32803b3a8eb9SGleb Smirnoff YYERROR;
32813b3a8eb9SGleb Smirnoff }
32823b3a8eb9SGleb Smirnoff free($2);
32833b3a8eb9SGleb Smirnoff $$.logif = i;
32843b3a8eb9SGleb Smirnoff }
32853b3a8eb9SGleb Smirnoff ;
32863b3a8eb9SGleb Smirnoff
32873b3a8eb9SGleb Smirnoff interface : /* empty */ { $$ = NULL; }
32883b3a8eb9SGleb Smirnoff | ON if_item_not { $$ = $2; }
32893b3a8eb9SGleb Smirnoff | ON '{' optnl if_list '}' { $$ = $4; }
32903b3a8eb9SGleb Smirnoff ;
32913b3a8eb9SGleb Smirnoff
32923b3a8eb9SGleb Smirnoff if_list : if_item_not optnl { $$ = $1; }
32933b3a8eb9SGleb Smirnoff | if_list comma if_item_not optnl {
32943b3a8eb9SGleb Smirnoff $1->tail->next = $3;
32953b3a8eb9SGleb Smirnoff $1->tail = $3;
32963b3a8eb9SGleb Smirnoff $$ = $1;
32973b3a8eb9SGleb Smirnoff }
32983b3a8eb9SGleb Smirnoff ;
32993b3a8eb9SGleb Smirnoff
33003b3a8eb9SGleb Smirnoff if_item_not : not if_item { $$ = $2; $$->not = $1; }
33013b3a8eb9SGleb Smirnoff ;
33023b3a8eb9SGleb Smirnoff
33033b3a8eb9SGleb Smirnoff if_item : STRING {
33043b3a8eb9SGleb Smirnoff struct node_host *n;
33053b3a8eb9SGleb Smirnoff
33063b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_if));
33073b3a8eb9SGleb Smirnoff if ($$ == NULL)
33083b3a8eb9SGleb Smirnoff err(1, "if_item: calloc");
33093b3a8eb9SGleb Smirnoff if (strlcpy($$->ifname, $1, sizeof($$->ifname)) >=
33103b3a8eb9SGleb Smirnoff sizeof($$->ifname)) {
33113b3a8eb9SGleb Smirnoff free($1);
33123b3a8eb9SGleb Smirnoff free($$);
33133b3a8eb9SGleb Smirnoff yyerror("interface name too long");
33143b3a8eb9SGleb Smirnoff YYERROR;
33153b3a8eb9SGleb Smirnoff }
33163b3a8eb9SGleb Smirnoff
33173b3a8eb9SGleb Smirnoff if ((n = ifa_exists($1)) != NULL)
33183b3a8eb9SGleb Smirnoff $$->ifa_flags = n->ifa_flags;
33193b3a8eb9SGleb Smirnoff
33203b3a8eb9SGleb Smirnoff free($1);
33213b3a8eb9SGleb Smirnoff $$->not = 0;
33223b3a8eb9SGleb Smirnoff $$->next = NULL;
33233b3a8eb9SGleb Smirnoff $$->tail = $$;
33243b3a8eb9SGleb Smirnoff }
3325a2614574SKristof Provost | ANY {
3326a2614574SKristof Provost $$ = calloc(1, sizeof(struct node_if));
3327a2614574SKristof Provost if ($$ == NULL)
3328a2614574SKristof Provost err(1, "if_item: calloc");
3329a2614574SKristof Provost strlcpy($$->ifname, "any", sizeof($$->ifname));
3330a2614574SKristof Provost $$->not = 0;
3331a2614574SKristof Provost $$->next = NULL;
3332a2614574SKristof Provost $$->tail = $$;
3333a2614574SKristof Provost }
33343b3a8eb9SGleb Smirnoff ;
33353b3a8eb9SGleb Smirnoff
33363b3a8eb9SGleb Smirnoff af : /* empty */ { $$ = 0; }
33373b3a8eb9SGleb Smirnoff | INET { $$ = AF_INET; }
33383b3a8eb9SGleb Smirnoff | INET6 { $$ = AF_INET6; }
33393b3a8eb9SGleb Smirnoff ;
33403b3a8eb9SGleb Smirnoff
33412b29ceb8SKristof Provost etherproto : /* empty */ { $$ = NULL; }
33422b29ceb8SKristof Provost | PROTO etherproto_item { $$ = $2; }
33432b29ceb8SKristof Provost | PROTO '{' optnl etherproto_list '}' { $$ = $4; }
33442b29ceb8SKristof Provost ;
33452b29ceb8SKristof Provost
33462b29ceb8SKristof Provost etherproto_list : etherproto_item optnl { $$ = $1; }
33472b29ceb8SKristof Provost | etherproto_list comma etherproto_item optnl {
33482b29ceb8SKristof Provost $1->tail->next = $3;
33492b29ceb8SKristof Provost $1->tail = $3;
33502b29ceb8SKristof Provost $$ = $1;
33512b29ceb8SKristof Provost }
33522b29ceb8SKristof Provost ;
33532b29ceb8SKristof Provost
33542b29ceb8SKristof Provost etherproto_item : etherprotoval {
33552b29ceb8SKristof Provost u_int16_t pr;
33562b29ceb8SKristof Provost
33572b29ceb8SKristof Provost pr = (u_int16_t)$1;
33582b29ceb8SKristof Provost if (pr == 0) {
33592b29ceb8SKristof Provost yyerror("proto 0 cannot be used");
33602b29ceb8SKristof Provost YYERROR;
33612b29ceb8SKristof Provost }
33622b29ceb8SKristof Provost $$ = calloc(1, sizeof(struct node_proto));
33632b29ceb8SKristof Provost if ($$ == NULL)
33642b29ceb8SKristof Provost err(1, "proto_item: calloc");
33652b29ceb8SKristof Provost $$->proto = pr;
33662b29ceb8SKristof Provost $$->next = NULL;
33672b29ceb8SKristof Provost $$->tail = $$;
33682b29ceb8SKristof Provost }
33692b29ceb8SKristof Provost ;
33702b29ceb8SKristof Provost
33712b29ceb8SKristof Provost etherprotoval : NUMBER {
33722b29ceb8SKristof Provost if ($1 < 0 || $1 > 65565) {
33732b29ceb8SKristof Provost yyerror("protocol outside range");
33742b29ceb8SKristof Provost YYERROR;
33752b29ceb8SKristof Provost }
33762b29ceb8SKristof Provost }
33772b29ceb8SKristof Provost | STRING
33782b29ceb8SKristof Provost {
33792b29ceb8SKristof Provost if (!strncmp($1, "0x", 2)) {
33802b29ceb8SKristof Provost if (sscanf($1, "0x%4x", &$$) != 1) {
33812b29ceb8SKristof Provost free($1);
33822b29ceb8SKristof Provost yyerror("invalid EtherType hex");
33832b29ceb8SKristof Provost YYERROR;
33842b29ceb8SKristof Provost }
33852b29ceb8SKristof Provost } else {
33862b29ceb8SKristof Provost yyerror("Symbolic EtherType not yet supported");
33872b29ceb8SKristof Provost }
33882b29ceb8SKristof Provost }
33892b29ceb8SKristof Provost ;
33902b29ceb8SKristof Provost
33913b3a8eb9SGleb Smirnoff proto : /* empty */ { $$ = NULL; }
33923b3a8eb9SGleb Smirnoff | PROTO proto_item { $$ = $2; }
33933b3a8eb9SGleb Smirnoff | PROTO '{' optnl proto_list '}' { $$ = $4; }
33943b3a8eb9SGleb Smirnoff ;
33953b3a8eb9SGleb Smirnoff
33963b3a8eb9SGleb Smirnoff proto_list : proto_item optnl { $$ = $1; }
33973b3a8eb9SGleb Smirnoff | proto_list comma proto_item optnl {
33983b3a8eb9SGleb Smirnoff $1->tail->next = $3;
33993b3a8eb9SGleb Smirnoff $1->tail = $3;
34003b3a8eb9SGleb Smirnoff $$ = $1;
34013b3a8eb9SGleb Smirnoff }
34023b3a8eb9SGleb Smirnoff ;
34033b3a8eb9SGleb Smirnoff
34043b3a8eb9SGleb Smirnoff proto_item : protoval {
34053b3a8eb9SGleb Smirnoff u_int8_t pr;
34063b3a8eb9SGleb Smirnoff
34073b3a8eb9SGleb Smirnoff pr = (u_int8_t)$1;
34083b3a8eb9SGleb Smirnoff if (pr == 0) {
34093b3a8eb9SGleb Smirnoff yyerror("proto 0 cannot be used");
34103b3a8eb9SGleb Smirnoff YYERROR;
34113b3a8eb9SGleb Smirnoff }
34123b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_proto));
34133b3a8eb9SGleb Smirnoff if ($$ == NULL)
34143b3a8eb9SGleb Smirnoff err(1, "proto_item: calloc");
34153b3a8eb9SGleb Smirnoff $$->proto = pr;
34163b3a8eb9SGleb Smirnoff $$->next = NULL;
34173b3a8eb9SGleb Smirnoff $$->tail = $$;
34183b3a8eb9SGleb Smirnoff }
34193b3a8eb9SGleb Smirnoff ;
34203b3a8eb9SGleb Smirnoff
34213b3a8eb9SGleb Smirnoff protoval : STRING {
34223b3a8eb9SGleb Smirnoff struct protoent *p;
34233b3a8eb9SGleb Smirnoff
34243b3a8eb9SGleb Smirnoff p = getprotobyname($1);
34253b3a8eb9SGleb Smirnoff if (p == NULL) {
34263b3a8eb9SGleb Smirnoff yyerror("unknown protocol %s", $1);
34273b3a8eb9SGleb Smirnoff free($1);
34283b3a8eb9SGleb Smirnoff YYERROR;
34293b3a8eb9SGleb Smirnoff }
34303b3a8eb9SGleb Smirnoff $$ = p->p_proto;
34313b3a8eb9SGleb Smirnoff free($1);
34323b3a8eb9SGleb Smirnoff }
34333b3a8eb9SGleb Smirnoff | NUMBER {
34343b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 > 255) {
34353b3a8eb9SGleb Smirnoff yyerror("protocol outside range");
34363b3a8eb9SGleb Smirnoff YYERROR;
34373b3a8eb9SGleb Smirnoff }
34383b3a8eb9SGleb Smirnoff }
34393b3a8eb9SGleb Smirnoff ;
34403b3a8eb9SGleb Smirnoff
34418a42005dSKristof Provost l3fromto : /* empty */ {
34428a42005dSKristof Provost bzero(&$$, sizeof($$));
34438a42005dSKristof Provost }
34448a42005dSKristof Provost | L3 fromto {
34453468cd95SKristof Provost if ($2.src.host != NULL &&
3446812839e5SKristof Provost $2.src.host->addr.type != PF_ADDR_ADDRMASK &&
3447812839e5SKristof Provost $2.src.host->addr.type != PF_ADDR_TABLE) {
3448812839e5SKristof Provost yyerror("from must be an address or table");
34493468cd95SKristof Provost YYERROR;
34503468cd95SKristof Provost }
34513468cd95SKristof Provost if ($2.dst.host != NULL &&
3452812839e5SKristof Provost $2.dst.host->addr.type != PF_ADDR_ADDRMASK &&
3453812839e5SKristof Provost $2.dst.host->addr.type != PF_ADDR_TABLE) {
3454812839e5SKristof Provost yyerror("to must be an address or table");
34553468cd95SKristof Provost YYERROR;
34563468cd95SKristof Provost }
34578a42005dSKristof Provost $$ = $2;
34588a42005dSKristof Provost }
34598a42005dSKristof Provost ;
34602b29ceb8SKristof Provost etherfromto : ALL {
346187a89d6eSKristof Provost $$.src = NULL;
346287a89d6eSKristof Provost $$.dst = NULL;
34632b29ceb8SKristof Provost }
34642b29ceb8SKristof Provost | etherfrom etherto {
346587a89d6eSKristof Provost $$.src = $1.mac;
346687a89d6eSKristof Provost $$.dst = $2.mac;
34672b29ceb8SKristof Provost }
34682b29ceb8SKristof Provost ;
34692b29ceb8SKristof Provost
34702b29ceb8SKristof Provost etherfrom : /* emtpy */ {
34712b29ceb8SKristof Provost bzero(&$$, sizeof($$));
34722b29ceb8SKristof Provost }
347387a89d6eSKristof Provost | FROM macspec {
347487a89d6eSKristof Provost $$.mac = $2;
34752b29ceb8SKristof Provost }
34762b29ceb8SKristof Provost ;
34772b29ceb8SKristof Provost
34782b29ceb8SKristof Provost etherto : /* empty */ {
34792b29ceb8SKristof Provost bzero(&$$, sizeof($$));
34802b29ceb8SKristof Provost }
348187a89d6eSKristof Provost | TO macspec {
348287a89d6eSKristof Provost $$.mac = $2;
34832b29ceb8SKristof Provost }
34842b29ceb8SKristof Provost ;
34852b29ceb8SKristof Provost
3486b590f17aSKristof Provost mac : string '/' NUMBER {
3487b590f17aSKristof Provost $$ = node_mac_from_string_masklen($1, $3);
34882b29ceb8SKristof Provost free($1);
3489b590f17aSKristof Provost if ($$ == NULL)
34902b29ceb8SKristof Provost YYERROR;
34912b29ceb8SKristof Provost }
3492b590f17aSKristof Provost | string {
3493b590f17aSKristof Provost if (strchr($1, '&')) {
3494b590f17aSKristof Provost /* mac&mask */
3495b590f17aSKristof Provost char *mac = strtok($1, "&");
3496b590f17aSKristof Provost char *mask = strtok(NULL, "&");
3497b590f17aSKristof Provost $$ = node_mac_from_string_mask(mac, mask);
3498b590f17aSKristof Provost } else {
3499b590f17aSKristof Provost $$ = node_mac_from_string($1);
3500b590f17aSKristof Provost }
350187a89d6eSKristof Provost free($1);
3502b590f17aSKristof Provost if ($$ == NULL)
3503b590f17aSKristof Provost YYERROR;
3504b590f17aSKristof Provost
350587a89d6eSKristof Provost }
350687a89d6eSKristof Provost xmac : not mac {
350787a89d6eSKristof Provost struct node_mac *n;
350887a89d6eSKristof Provost
350987a89d6eSKristof Provost for (n = $2; n != NULL; n = n->next)
351087a89d6eSKristof Provost n->neg = $1;
351187a89d6eSKristof Provost $$ = $2;
35122b29ceb8SKristof Provost }
35132b29ceb8SKristof Provost ;
351487a89d6eSKristof Provost macspec : xmac {
351587a89d6eSKristof Provost $$ = $1;
351687a89d6eSKristof Provost }
351787a89d6eSKristof Provost | '{' optnl mac_list '}'
351887a89d6eSKristof Provost {
351987a89d6eSKristof Provost $$ = $3;
352087a89d6eSKristof Provost }
352187a89d6eSKristof Provost ;
352287a89d6eSKristof Provost mac_list : xmac optnl {
352387a89d6eSKristof Provost $$ = $1;
352487a89d6eSKristof Provost }
352587a89d6eSKristof Provost | mac_list comma xmac {
352687a89d6eSKristof Provost if ($3 == NULL)
352787a89d6eSKristof Provost $$ = $1;
352887a89d6eSKristof Provost else if ($1 == NULL)
352987a89d6eSKristof Provost $$ = $3;
353087a89d6eSKristof Provost else {
353187a89d6eSKristof Provost $1->tail->next = $3;
353287a89d6eSKristof Provost $1->tail = $3->tail;
353387a89d6eSKristof Provost $$ = $1;
353487a89d6eSKristof Provost }
353587a89d6eSKristof Provost }
35362b29ceb8SKristof Provost
35373b3a8eb9SGleb Smirnoff fromto : ALL {
35383b3a8eb9SGleb Smirnoff $$.src.host = NULL;
35393b3a8eb9SGleb Smirnoff $$.src.port = NULL;
35403b3a8eb9SGleb Smirnoff $$.dst.host = NULL;
35413b3a8eb9SGleb Smirnoff $$.dst.port = NULL;
35423b3a8eb9SGleb Smirnoff $$.src_os = NULL;
35433b3a8eb9SGleb Smirnoff }
35443b3a8eb9SGleb Smirnoff | from os to {
35453b3a8eb9SGleb Smirnoff $$.src = $1;
35463b3a8eb9SGleb Smirnoff $$.src_os = $2;
35473b3a8eb9SGleb Smirnoff $$.dst = $3;
35483b3a8eb9SGleb Smirnoff }
35493b3a8eb9SGleb Smirnoff ;
35503b3a8eb9SGleb Smirnoff
35513b3a8eb9SGleb Smirnoff os : /* empty */ { $$ = NULL; }
35523b3a8eb9SGleb Smirnoff | OS xos { $$ = $2; }
35533b3a8eb9SGleb Smirnoff | OS '{' optnl os_list '}' { $$ = $4; }
35543b3a8eb9SGleb Smirnoff ;
35553b3a8eb9SGleb Smirnoff
35563b3a8eb9SGleb Smirnoff xos : STRING {
35573b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_os));
35583b3a8eb9SGleb Smirnoff if ($$ == NULL)
35593b3a8eb9SGleb Smirnoff err(1, "os: calloc");
35603b3a8eb9SGleb Smirnoff $$->os = $1;
35613b3a8eb9SGleb Smirnoff $$->tail = $$;
35623b3a8eb9SGleb Smirnoff }
35633b3a8eb9SGleb Smirnoff ;
35643b3a8eb9SGleb Smirnoff
35653b3a8eb9SGleb Smirnoff os_list : xos optnl { $$ = $1; }
35663b3a8eb9SGleb Smirnoff | os_list comma xos optnl {
35673b3a8eb9SGleb Smirnoff $1->tail->next = $3;
35683b3a8eb9SGleb Smirnoff $1->tail = $3;
35693b3a8eb9SGleb Smirnoff $$ = $1;
35703b3a8eb9SGleb Smirnoff }
35713b3a8eb9SGleb Smirnoff ;
35723b3a8eb9SGleb Smirnoff
35733b3a8eb9SGleb Smirnoff from : /* empty */ {
35743b3a8eb9SGleb Smirnoff $$.host = NULL;
35753b3a8eb9SGleb Smirnoff $$.port = NULL;
35763b3a8eb9SGleb Smirnoff }
35773b3a8eb9SGleb Smirnoff | FROM ipportspec {
35783b3a8eb9SGleb Smirnoff $$ = $2;
35793b3a8eb9SGleb Smirnoff }
35803b3a8eb9SGleb Smirnoff ;
35813b3a8eb9SGleb Smirnoff
35823b3a8eb9SGleb Smirnoff to : /* empty */ {
35833b3a8eb9SGleb Smirnoff $$.host = NULL;
35843b3a8eb9SGleb Smirnoff $$.port = NULL;
35853b3a8eb9SGleb Smirnoff }
35863b3a8eb9SGleb Smirnoff | TO ipportspec {
35873b3a8eb9SGleb Smirnoff if (disallow_urpf_failed($2.host, "\"urpf-failed\" is "
35883b3a8eb9SGleb Smirnoff "not permitted in a destination address"))
35893b3a8eb9SGleb Smirnoff YYERROR;
35903b3a8eb9SGleb Smirnoff $$ = $2;
35913b3a8eb9SGleb Smirnoff }
35923b3a8eb9SGleb Smirnoff ;
35933b3a8eb9SGleb Smirnoff
35943b3a8eb9SGleb Smirnoff ipportspec : ipspec {
35953b3a8eb9SGleb Smirnoff $$.host = $1;
35963b3a8eb9SGleb Smirnoff $$.port = NULL;
35973b3a8eb9SGleb Smirnoff }
35983b3a8eb9SGleb Smirnoff | ipspec PORT portspec {
35993b3a8eb9SGleb Smirnoff $$.host = $1;
36003b3a8eb9SGleb Smirnoff $$.port = $3;
36013b3a8eb9SGleb Smirnoff }
36023b3a8eb9SGleb Smirnoff | PORT portspec {
36033b3a8eb9SGleb Smirnoff $$.host = NULL;
36043b3a8eb9SGleb Smirnoff $$.port = $2;
36053b3a8eb9SGleb Smirnoff }
36063b3a8eb9SGleb Smirnoff ;
36073b3a8eb9SGleb Smirnoff
36083b3a8eb9SGleb Smirnoff optnl : '\n' optnl
36093b3a8eb9SGleb Smirnoff |
36103b3a8eb9SGleb Smirnoff ;
36113b3a8eb9SGleb Smirnoff
36123b3a8eb9SGleb Smirnoff ipspec : ANY { $$ = NULL; }
36133b3a8eb9SGleb Smirnoff | xhost { $$ = $1; }
36143b3a8eb9SGleb Smirnoff | '{' optnl host_list '}' { $$ = $3; }
36153b3a8eb9SGleb Smirnoff ;
36163b3a8eb9SGleb Smirnoff
36173b3a8eb9SGleb Smirnoff toipspec : TO ipspec { $$ = $2; }
36183b3a8eb9SGleb Smirnoff | /* empty */ { $$ = NULL; }
36193b3a8eb9SGleb Smirnoff ;
36203b3a8eb9SGleb Smirnoff
36213b3a8eb9SGleb Smirnoff host_list : ipspec optnl { $$ = $1; }
36223b3a8eb9SGleb Smirnoff | host_list comma ipspec optnl {
3623637d81c5SKristof Provost if ($1 == NULL) {
3624637d81c5SKristof Provost freehostlist($3);
36253b3a8eb9SGleb Smirnoff $$ = $1;
3626637d81c5SKristof Provost } else if ($3 == NULL) {
3627637d81c5SKristof Provost freehostlist($1);
36283b3a8eb9SGleb Smirnoff $$ = $3;
3629637d81c5SKristof Provost } else {
36303b3a8eb9SGleb Smirnoff $1->tail->next = $3;
36313b3a8eb9SGleb Smirnoff $1->tail = $3->tail;
36323b3a8eb9SGleb Smirnoff $$ = $1;
36333b3a8eb9SGleb Smirnoff }
36343b3a8eb9SGleb Smirnoff }
36353b3a8eb9SGleb Smirnoff ;
36363b3a8eb9SGleb Smirnoff
36373b3a8eb9SGleb Smirnoff xhost : not host {
36383b3a8eb9SGleb Smirnoff struct node_host *n;
36393b3a8eb9SGleb Smirnoff
36403b3a8eb9SGleb Smirnoff for (n = $2; n != NULL; n = n->next)
36413b3a8eb9SGleb Smirnoff n->not = $1;
36423b3a8eb9SGleb Smirnoff $$ = $2;
36433b3a8eb9SGleb Smirnoff }
36443b3a8eb9SGleb Smirnoff | not NOROUTE {
36453b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_host));
36463b3a8eb9SGleb Smirnoff if ($$ == NULL)
36473b3a8eb9SGleb Smirnoff err(1, "xhost: calloc");
36483b3a8eb9SGleb Smirnoff $$->addr.type = PF_ADDR_NOROUTE;
36493b3a8eb9SGleb Smirnoff $$->next = NULL;
36503b3a8eb9SGleb Smirnoff $$->not = $1;
36513b3a8eb9SGleb Smirnoff $$->tail = $$;
36523b3a8eb9SGleb Smirnoff }
36533b3a8eb9SGleb Smirnoff | not URPFFAILED {
36543b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_host));
36553b3a8eb9SGleb Smirnoff if ($$ == NULL)
36563b3a8eb9SGleb Smirnoff err(1, "xhost: calloc");
36573b3a8eb9SGleb Smirnoff $$->addr.type = PF_ADDR_URPFFAILED;
36583b3a8eb9SGleb Smirnoff $$->next = NULL;
36593b3a8eb9SGleb Smirnoff $$->not = $1;
36603b3a8eb9SGleb Smirnoff $$->tail = $$;
36613b3a8eb9SGleb Smirnoff }
36623b3a8eb9SGleb Smirnoff ;
36633b3a8eb9SGleb Smirnoff
36643b3a8eb9SGleb Smirnoff host : STRING {
36653b3a8eb9SGleb Smirnoff if (($$ = host($1)) == NULL) {
36663b3a8eb9SGleb Smirnoff /* error. "any" is handled elsewhere */
36673b3a8eb9SGleb Smirnoff free($1);
36683b3a8eb9SGleb Smirnoff yyerror("could not parse host specification");
36693b3a8eb9SGleb Smirnoff YYERROR;
36703b3a8eb9SGleb Smirnoff }
36713b3a8eb9SGleb Smirnoff free($1);
36723b3a8eb9SGleb Smirnoff
36733b3a8eb9SGleb Smirnoff }
36743b3a8eb9SGleb Smirnoff | STRING '-' STRING {
36753b3a8eb9SGleb Smirnoff struct node_host *b, *e;
36763b3a8eb9SGleb Smirnoff
36773b3a8eb9SGleb Smirnoff if ((b = host($1)) == NULL || (e = host($3)) == NULL) {
36783b3a8eb9SGleb Smirnoff free($1);
36793b3a8eb9SGleb Smirnoff free($3);
36803b3a8eb9SGleb Smirnoff yyerror("could not parse host specification");
36813b3a8eb9SGleb Smirnoff YYERROR;
36823b3a8eb9SGleb Smirnoff }
36833b3a8eb9SGleb Smirnoff if (b->af != e->af ||
36843b3a8eb9SGleb Smirnoff b->addr.type != PF_ADDR_ADDRMASK ||
36853b3a8eb9SGleb Smirnoff e->addr.type != PF_ADDR_ADDRMASK ||
36863b3a8eb9SGleb Smirnoff unmask(&b->addr.v.a.mask, b->af) !=
36873b3a8eb9SGleb Smirnoff (b->af == AF_INET ? 32 : 128) ||
36883b3a8eb9SGleb Smirnoff unmask(&e->addr.v.a.mask, e->af) !=
36893b3a8eb9SGleb Smirnoff (e->af == AF_INET ? 32 : 128) ||
36903b3a8eb9SGleb Smirnoff b->next != NULL || b->not ||
36913b3a8eb9SGleb Smirnoff e->next != NULL || e->not) {
36923b3a8eb9SGleb Smirnoff free(b);
36933b3a8eb9SGleb Smirnoff free(e);
36943b3a8eb9SGleb Smirnoff free($1);
36953b3a8eb9SGleb Smirnoff free($3);
36963b3a8eb9SGleb Smirnoff yyerror("invalid address range");
36973b3a8eb9SGleb Smirnoff YYERROR;
36983b3a8eb9SGleb Smirnoff }
36993b3a8eb9SGleb Smirnoff memcpy(&b->addr.v.a.mask, &e->addr.v.a.addr,
37003b3a8eb9SGleb Smirnoff sizeof(b->addr.v.a.mask));
37013b3a8eb9SGleb Smirnoff b->addr.type = PF_ADDR_RANGE;
37023b3a8eb9SGleb Smirnoff $$ = b;
37033b3a8eb9SGleb Smirnoff free(e);
37043b3a8eb9SGleb Smirnoff free($1);
37053b3a8eb9SGleb Smirnoff free($3);
37063b3a8eb9SGleb Smirnoff }
37073b3a8eb9SGleb Smirnoff | STRING '/' NUMBER {
37083b3a8eb9SGleb Smirnoff char *buf;
37093b3a8eb9SGleb Smirnoff
37103b3a8eb9SGleb Smirnoff if (asprintf(&buf, "%s/%lld", $1, (long long)$3) == -1)
37113b3a8eb9SGleb Smirnoff err(1, "host: asprintf");
37123b3a8eb9SGleb Smirnoff free($1);
37133b3a8eb9SGleb Smirnoff if (($$ = host(buf)) == NULL) {
37143b3a8eb9SGleb Smirnoff /* error. "any" is handled elsewhere */
37153b3a8eb9SGleb Smirnoff free(buf);
37163b3a8eb9SGleb Smirnoff yyerror("could not parse host specification");
37173b3a8eb9SGleb Smirnoff YYERROR;
37183b3a8eb9SGleb Smirnoff }
37193b3a8eb9SGleb Smirnoff free(buf);
37203b3a8eb9SGleb Smirnoff }
37213b3a8eb9SGleb Smirnoff | NUMBER '/' NUMBER {
37223b3a8eb9SGleb Smirnoff char *buf;
37233b3a8eb9SGleb Smirnoff
37243b3a8eb9SGleb Smirnoff /* ie. for 10/8 parsing */
37253b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__
37263b3a8eb9SGleb Smirnoff if (asprintf(&buf, "%lld/%lld", (long long)$1, (long long)$3) == -1)
37273b3a8eb9SGleb Smirnoff #else
37283b3a8eb9SGleb Smirnoff if (asprintf(&buf, "%lld/%lld", $1, $3) == -1)
37293b3a8eb9SGleb Smirnoff #endif
37303b3a8eb9SGleb Smirnoff err(1, "host: asprintf");
37313b3a8eb9SGleb Smirnoff if (($$ = host(buf)) == NULL) {
37323b3a8eb9SGleb Smirnoff /* error. "any" is handled elsewhere */
37333b3a8eb9SGleb Smirnoff free(buf);
37343b3a8eb9SGleb Smirnoff yyerror("could not parse host specification");
37353b3a8eb9SGleb Smirnoff YYERROR;
37363b3a8eb9SGleb Smirnoff }
37373b3a8eb9SGleb Smirnoff free(buf);
37383b3a8eb9SGleb Smirnoff }
37393b3a8eb9SGleb Smirnoff | dynaddr
37403b3a8eb9SGleb Smirnoff | dynaddr '/' NUMBER {
37413b3a8eb9SGleb Smirnoff struct node_host *n;
37423b3a8eb9SGleb Smirnoff
37433b3a8eb9SGleb Smirnoff if ($3 < 0 || $3 > 128) {
37443b3a8eb9SGleb Smirnoff yyerror("bit number too big");
37453b3a8eb9SGleb Smirnoff YYERROR;
37463b3a8eb9SGleb Smirnoff }
37473b3a8eb9SGleb Smirnoff $$ = $1;
37483b3a8eb9SGleb Smirnoff for (n = $1; n != NULL; n = n->next)
37493b3a8eb9SGleb Smirnoff set_ipmask(n, $3);
37503b3a8eb9SGleb Smirnoff }
37513b3a8eb9SGleb Smirnoff | '<' STRING '>' {
37523b3a8eb9SGleb Smirnoff if (strlen($2) >= PF_TABLE_NAME_SIZE) {
37533b3a8eb9SGleb Smirnoff yyerror("table name '%s' too long", $2);
37543b3a8eb9SGleb Smirnoff free($2);
37553b3a8eb9SGleb Smirnoff YYERROR;
37563b3a8eb9SGleb Smirnoff }
37573b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_host));
37583b3a8eb9SGleb Smirnoff if ($$ == NULL)
37593b3a8eb9SGleb Smirnoff err(1, "host: calloc");
37603b3a8eb9SGleb Smirnoff $$->addr.type = PF_ADDR_TABLE;
37613b3a8eb9SGleb Smirnoff if (strlcpy($$->addr.v.tblname, $2,
37623b3a8eb9SGleb Smirnoff sizeof($$->addr.v.tblname)) >=
37633b3a8eb9SGleb Smirnoff sizeof($$->addr.v.tblname))
37643b3a8eb9SGleb Smirnoff errx(1, "host: strlcpy");
37653b3a8eb9SGleb Smirnoff free($2);
37663b3a8eb9SGleb Smirnoff $$->next = NULL;
37673b3a8eb9SGleb Smirnoff $$->tail = $$;
37683b3a8eb9SGleb Smirnoff }
37693b3a8eb9SGleb Smirnoff ;
37703b3a8eb9SGleb Smirnoff
37713b3a8eb9SGleb Smirnoff number : NUMBER
37723b3a8eb9SGleb Smirnoff | STRING {
37733b3a8eb9SGleb Smirnoff u_long ulval;
37743b3a8eb9SGleb Smirnoff
37753b3a8eb9SGleb Smirnoff if (atoul($1, &ulval) == -1) {
37763b3a8eb9SGleb Smirnoff yyerror("%s is not a number", $1);
37773b3a8eb9SGleb Smirnoff free($1);
37783b3a8eb9SGleb Smirnoff YYERROR;
37793b3a8eb9SGleb Smirnoff } else
37803b3a8eb9SGleb Smirnoff $$ = ulval;
37813b3a8eb9SGleb Smirnoff free($1);
37823b3a8eb9SGleb Smirnoff }
37833b3a8eb9SGleb Smirnoff ;
37843b3a8eb9SGleb Smirnoff
37853b3a8eb9SGleb Smirnoff dynaddr : '(' STRING ')' {
37863b3a8eb9SGleb Smirnoff int flags = 0;
37873b3a8eb9SGleb Smirnoff char *p, *op;
37883b3a8eb9SGleb Smirnoff
37893b3a8eb9SGleb Smirnoff op = $2;
37903b3a8eb9SGleb Smirnoff if (!isalpha(op[0])) {
37913b3a8eb9SGleb Smirnoff yyerror("invalid interface name '%s'", op);
37923b3a8eb9SGleb Smirnoff free(op);
37933b3a8eb9SGleb Smirnoff YYERROR;
37943b3a8eb9SGleb Smirnoff }
37953b3a8eb9SGleb Smirnoff while ((p = strrchr($2, ':')) != NULL) {
37963b3a8eb9SGleb Smirnoff if (!strcmp(p+1, "network"))
37973b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_NETWORK;
37983b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "broadcast"))
37993b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_BROADCAST;
38003b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "peer"))
38013b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_PEER;
38023b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "0"))
38033b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_NOALIAS;
38043b3a8eb9SGleb Smirnoff else {
38053b3a8eb9SGleb Smirnoff yyerror("interface %s has bad modifier",
38063b3a8eb9SGleb Smirnoff $2);
38073b3a8eb9SGleb Smirnoff free(op);
38083b3a8eb9SGleb Smirnoff YYERROR;
38093b3a8eb9SGleb Smirnoff }
38103b3a8eb9SGleb Smirnoff *p = '\0';
38113b3a8eb9SGleb Smirnoff }
38123b3a8eb9SGleb Smirnoff if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) {
38133b3a8eb9SGleb Smirnoff free(op);
38143b3a8eb9SGleb Smirnoff yyerror("illegal combination of "
38153b3a8eb9SGleb Smirnoff "interface modifiers");
38163b3a8eb9SGleb Smirnoff YYERROR;
38173b3a8eb9SGleb Smirnoff }
38183b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_host));
38193b3a8eb9SGleb Smirnoff if ($$ == NULL)
38203b3a8eb9SGleb Smirnoff err(1, "address: calloc");
38213b3a8eb9SGleb Smirnoff $$->af = 0;
38223b3a8eb9SGleb Smirnoff set_ipmask($$, 128);
38233b3a8eb9SGleb Smirnoff $$->addr.type = PF_ADDR_DYNIFTL;
38243b3a8eb9SGleb Smirnoff $$->addr.iflags = flags;
38253b3a8eb9SGleb Smirnoff if (strlcpy($$->addr.v.ifname, $2,
38263b3a8eb9SGleb Smirnoff sizeof($$->addr.v.ifname)) >=
38273b3a8eb9SGleb Smirnoff sizeof($$->addr.v.ifname)) {
38283b3a8eb9SGleb Smirnoff free(op);
38293b3a8eb9SGleb Smirnoff free($$);
38303b3a8eb9SGleb Smirnoff yyerror("interface name too long");
38313b3a8eb9SGleb Smirnoff YYERROR;
38323b3a8eb9SGleb Smirnoff }
38333b3a8eb9SGleb Smirnoff free(op);
38343b3a8eb9SGleb Smirnoff $$->next = NULL;
38353b3a8eb9SGleb Smirnoff $$->tail = $$;
38363b3a8eb9SGleb Smirnoff }
38373b3a8eb9SGleb Smirnoff ;
38383b3a8eb9SGleb Smirnoff
38393b3a8eb9SGleb Smirnoff portspec : port_item { $$ = $1; }
38403b3a8eb9SGleb Smirnoff | '{' optnl port_list '}' { $$ = $3; }
38413b3a8eb9SGleb Smirnoff ;
38423b3a8eb9SGleb Smirnoff
38433b3a8eb9SGleb Smirnoff port_list : port_item optnl { $$ = $1; }
38443b3a8eb9SGleb Smirnoff | port_list comma port_item optnl {
38453b3a8eb9SGleb Smirnoff $1->tail->next = $3;
38463b3a8eb9SGleb Smirnoff $1->tail = $3;
38473b3a8eb9SGleb Smirnoff $$ = $1;
38483b3a8eb9SGleb Smirnoff }
38493b3a8eb9SGleb Smirnoff ;
38503b3a8eb9SGleb Smirnoff
38513b3a8eb9SGleb Smirnoff port_item : portrange {
38523b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_port));
38533b3a8eb9SGleb Smirnoff if ($$ == NULL)
38543b3a8eb9SGleb Smirnoff err(1, "port_item: calloc");
38553b3a8eb9SGleb Smirnoff $$->port[0] = $1.a;
38563b3a8eb9SGleb Smirnoff $$->port[1] = $1.b;
38573b3a8eb9SGleb Smirnoff if ($1.t)
38583b3a8eb9SGleb Smirnoff $$->op = PF_OP_RRG;
38593b3a8eb9SGleb Smirnoff else
38603b3a8eb9SGleb Smirnoff $$->op = PF_OP_EQ;
38613b3a8eb9SGleb Smirnoff $$->next = NULL;
38623b3a8eb9SGleb Smirnoff $$->tail = $$;
38633b3a8eb9SGleb Smirnoff }
38643b3a8eb9SGleb Smirnoff | unaryop portrange {
38653b3a8eb9SGleb Smirnoff if ($2.t) {
38663b3a8eb9SGleb Smirnoff yyerror("':' cannot be used with an other "
38673b3a8eb9SGleb Smirnoff "port operator");
38683b3a8eb9SGleb Smirnoff YYERROR;
38693b3a8eb9SGleb Smirnoff }
38703b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_port));
38713b3a8eb9SGleb Smirnoff if ($$ == NULL)
38723b3a8eb9SGleb Smirnoff err(1, "port_item: calloc");
38733b3a8eb9SGleb Smirnoff $$->port[0] = $2.a;
38743b3a8eb9SGleb Smirnoff $$->port[1] = $2.b;
38753b3a8eb9SGleb Smirnoff $$->op = $1;
38763b3a8eb9SGleb Smirnoff $$->next = NULL;
38773b3a8eb9SGleb Smirnoff $$->tail = $$;
38783b3a8eb9SGleb Smirnoff }
38793b3a8eb9SGleb Smirnoff | portrange PORTBINARY portrange {
38803b3a8eb9SGleb Smirnoff if ($1.t || $3.t) {
38813b3a8eb9SGleb Smirnoff yyerror("':' cannot be used with an other "
38823b3a8eb9SGleb Smirnoff "port operator");
38833b3a8eb9SGleb Smirnoff YYERROR;
38843b3a8eb9SGleb Smirnoff }
38853b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_port));
38863b3a8eb9SGleb Smirnoff if ($$ == NULL)
38873b3a8eb9SGleb Smirnoff err(1, "port_item: calloc");
38883b3a8eb9SGleb Smirnoff $$->port[0] = $1.a;
38893b3a8eb9SGleb Smirnoff $$->port[1] = $3.a;
38903b3a8eb9SGleb Smirnoff $$->op = $2;
38913b3a8eb9SGleb Smirnoff $$->next = NULL;
38923b3a8eb9SGleb Smirnoff $$->tail = $$;
38933b3a8eb9SGleb Smirnoff }
38943b3a8eb9SGleb Smirnoff ;
38953b3a8eb9SGleb Smirnoff
38963b3a8eb9SGleb Smirnoff portplain : numberstring {
38973b3a8eb9SGleb Smirnoff if (parseport($1, &$$, 0) == -1) {
38983b3a8eb9SGleb Smirnoff free($1);
38993b3a8eb9SGleb Smirnoff YYERROR;
39003b3a8eb9SGleb Smirnoff }
39013b3a8eb9SGleb Smirnoff free($1);
39023b3a8eb9SGleb Smirnoff }
39033b3a8eb9SGleb Smirnoff ;
39043b3a8eb9SGleb Smirnoff
39053b3a8eb9SGleb Smirnoff portrange : numberstring {
39063b3a8eb9SGleb Smirnoff if (parseport($1, &$$, PPORT_RANGE) == -1) {
39073b3a8eb9SGleb Smirnoff free($1);
39083b3a8eb9SGleb Smirnoff YYERROR;
39093b3a8eb9SGleb Smirnoff }
39103b3a8eb9SGleb Smirnoff free($1);
39113b3a8eb9SGleb Smirnoff }
39123b3a8eb9SGleb Smirnoff ;
39133b3a8eb9SGleb Smirnoff
39143b3a8eb9SGleb Smirnoff uids : uid_item { $$ = $1; }
39153b3a8eb9SGleb Smirnoff | '{' optnl uid_list '}' { $$ = $3; }
39163b3a8eb9SGleb Smirnoff ;
39173b3a8eb9SGleb Smirnoff
39183b3a8eb9SGleb Smirnoff uid_list : uid_item optnl { $$ = $1; }
39193b3a8eb9SGleb Smirnoff | uid_list comma uid_item optnl {
39203b3a8eb9SGleb Smirnoff $1->tail->next = $3;
39213b3a8eb9SGleb Smirnoff $1->tail = $3;
39223b3a8eb9SGleb Smirnoff $$ = $1;
39233b3a8eb9SGleb Smirnoff }
39243b3a8eb9SGleb Smirnoff ;
39253b3a8eb9SGleb Smirnoff
39263b3a8eb9SGleb Smirnoff uid_item : uid {
39273b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_uid));
39283b3a8eb9SGleb Smirnoff if ($$ == NULL)
39293b3a8eb9SGleb Smirnoff err(1, "uid_item: calloc");
39303b3a8eb9SGleb Smirnoff $$->uid[0] = $1;
39313b3a8eb9SGleb Smirnoff $$->uid[1] = $1;
39323b3a8eb9SGleb Smirnoff $$->op = PF_OP_EQ;
39333b3a8eb9SGleb Smirnoff $$->next = NULL;
39343b3a8eb9SGleb Smirnoff $$->tail = $$;
39353b3a8eb9SGleb Smirnoff }
39363b3a8eb9SGleb Smirnoff | unaryop uid {
39373b3a8eb9SGleb Smirnoff if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
39383b3a8eb9SGleb Smirnoff yyerror("user unknown requires operator = or "
39393b3a8eb9SGleb Smirnoff "!=");
39403b3a8eb9SGleb Smirnoff YYERROR;
39413b3a8eb9SGleb Smirnoff }
39423b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_uid));
39433b3a8eb9SGleb Smirnoff if ($$ == NULL)
39443b3a8eb9SGleb Smirnoff err(1, "uid_item: calloc");
39453b3a8eb9SGleb Smirnoff $$->uid[0] = $2;
39463b3a8eb9SGleb Smirnoff $$->uid[1] = $2;
39473b3a8eb9SGleb Smirnoff $$->op = $1;
39483b3a8eb9SGleb Smirnoff $$->next = NULL;
39493b3a8eb9SGleb Smirnoff $$->tail = $$;
39503b3a8eb9SGleb Smirnoff }
39513b3a8eb9SGleb Smirnoff | uid PORTBINARY uid {
39523b3a8eb9SGleb Smirnoff if ($1 == UID_MAX || $3 == UID_MAX) {
39533b3a8eb9SGleb Smirnoff yyerror("user unknown requires operator = or "
39543b3a8eb9SGleb Smirnoff "!=");
39553b3a8eb9SGleb Smirnoff YYERROR;
39563b3a8eb9SGleb Smirnoff }
39573b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_uid));
39583b3a8eb9SGleb Smirnoff if ($$ == NULL)
39593b3a8eb9SGleb Smirnoff err(1, "uid_item: calloc");
39603b3a8eb9SGleb Smirnoff $$->uid[0] = $1;
39613b3a8eb9SGleb Smirnoff $$->uid[1] = $3;
39623b3a8eb9SGleb Smirnoff $$->op = $2;
39633b3a8eb9SGleb Smirnoff $$->next = NULL;
39643b3a8eb9SGleb Smirnoff $$->tail = $$;
39653b3a8eb9SGleb Smirnoff }
39663b3a8eb9SGleb Smirnoff ;
39673b3a8eb9SGleb Smirnoff
39683b3a8eb9SGleb Smirnoff uid : STRING {
39693b3a8eb9SGleb Smirnoff if (!strcmp($1, "unknown"))
39703b3a8eb9SGleb Smirnoff $$ = UID_MAX;
39713b3a8eb9SGleb Smirnoff else {
39723b3a8eb9SGleb Smirnoff struct passwd *pw;
39733b3a8eb9SGleb Smirnoff
39743b3a8eb9SGleb Smirnoff if ((pw = getpwnam($1)) == NULL) {
39753b3a8eb9SGleb Smirnoff yyerror("unknown user %s", $1);
39763b3a8eb9SGleb Smirnoff free($1);
39773b3a8eb9SGleb Smirnoff YYERROR;
39783b3a8eb9SGleb Smirnoff }
39793b3a8eb9SGleb Smirnoff $$ = pw->pw_uid;
39803b3a8eb9SGleb Smirnoff }
39813b3a8eb9SGleb Smirnoff free($1);
39823b3a8eb9SGleb Smirnoff }
39833b3a8eb9SGleb Smirnoff | NUMBER {
39843b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 >= UID_MAX) {
39853b3a8eb9SGleb Smirnoff yyerror("illegal uid value %lu", $1);
39863b3a8eb9SGleb Smirnoff YYERROR;
39873b3a8eb9SGleb Smirnoff }
39883b3a8eb9SGleb Smirnoff $$ = $1;
39893b3a8eb9SGleb Smirnoff }
39903b3a8eb9SGleb Smirnoff ;
39913b3a8eb9SGleb Smirnoff
39923b3a8eb9SGleb Smirnoff gids : gid_item { $$ = $1; }
39933b3a8eb9SGleb Smirnoff | '{' optnl gid_list '}' { $$ = $3; }
39943b3a8eb9SGleb Smirnoff ;
39953b3a8eb9SGleb Smirnoff
39963b3a8eb9SGleb Smirnoff gid_list : gid_item optnl { $$ = $1; }
39973b3a8eb9SGleb Smirnoff | gid_list comma gid_item optnl {
39983b3a8eb9SGleb Smirnoff $1->tail->next = $3;
39993b3a8eb9SGleb Smirnoff $1->tail = $3;
40003b3a8eb9SGleb Smirnoff $$ = $1;
40013b3a8eb9SGleb Smirnoff }
40023b3a8eb9SGleb Smirnoff ;
40033b3a8eb9SGleb Smirnoff
40043b3a8eb9SGleb Smirnoff gid_item : gid {
40053b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_gid));
40063b3a8eb9SGleb Smirnoff if ($$ == NULL)
40073b3a8eb9SGleb Smirnoff err(1, "gid_item: calloc");
40083b3a8eb9SGleb Smirnoff $$->gid[0] = $1;
40093b3a8eb9SGleb Smirnoff $$->gid[1] = $1;
40103b3a8eb9SGleb Smirnoff $$->op = PF_OP_EQ;
40113b3a8eb9SGleb Smirnoff $$->next = NULL;
40123b3a8eb9SGleb Smirnoff $$->tail = $$;
40133b3a8eb9SGleb Smirnoff }
40143b3a8eb9SGleb Smirnoff | unaryop gid {
40153b3a8eb9SGleb Smirnoff if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) {
40163b3a8eb9SGleb Smirnoff yyerror("group unknown requires operator = or "
40173b3a8eb9SGleb Smirnoff "!=");
40183b3a8eb9SGleb Smirnoff YYERROR;
40193b3a8eb9SGleb Smirnoff }
40203b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_gid));
40213b3a8eb9SGleb Smirnoff if ($$ == NULL)
40223b3a8eb9SGleb Smirnoff err(1, "gid_item: calloc");
40233b3a8eb9SGleb Smirnoff $$->gid[0] = $2;
40243b3a8eb9SGleb Smirnoff $$->gid[1] = $2;
40253b3a8eb9SGleb Smirnoff $$->op = $1;
40263b3a8eb9SGleb Smirnoff $$->next = NULL;
40273b3a8eb9SGleb Smirnoff $$->tail = $$;
40283b3a8eb9SGleb Smirnoff }
40293b3a8eb9SGleb Smirnoff | gid PORTBINARY gid {
40303b3a8eb9SGleb Smirnoff if ($1 == GID_MAX || $3 == GID_MAX) {
40313b3a8eb9SGleb Smirnoff yyerror("group unknown requires operator = or "
40323b3a8eb9SGleb Smirnoff "!=");
40333b3a8eb9SGleb Smirnoff YYERROR;
40343b3a8eb9SGleb Smirnoff }
40353b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_gid));
40363b3a8eb9SGleb Smirnoff if ($$ == NULL)
40373b3a8eb9SGleb Smirnoff err(1, "gid_item: calloc");
40383b3a8eb9SGleb Smirnoff $$->gid[0] = $1;
40393b3a8eb9SGleb Smirnoff $$->gid[1] = $3;
40403b3a8eb9SGleb Smirnoff $$->op = $2;
40413b3a8eb9SGleb Smirnoff $$->next = NULL;
40423b3a8eb9SGleb Smirnoff $$->tail = $$;
40433b3a8eb9SGleb Smirnoff }
40443b3a8eb9SGleb Smirnoff ;
40453b3a8eb9SGleb Smirnoff
40463b3a8eb9SGleb Smirnoff gid : STRING {
40473b3a8eb9SGleb Smirnoff if (!strcmp($1, "unknown"))
40483b3a8eb9SGleb Smirnoff $$ = GID_MAX;
40493b3a8eb9SGleb Smirnoff else {
40503b3a8eb9SGleb Smirnoff struct group *grp;
40513b3a8eb9SGleb Smirnoff
40523b3a8eb9SGleb Smirnoff if ((grp = getgrnam($1)) == NULL) {
40533b3a8eb9SGleb Smirnoff yyerror("unknown group %s", $1);
40543b3a8eb9SGleb Smirnoff free($1);
40553b3a8eb9SGleb Smirnoff YYERROR;
40563b3a8eb9SGleb Smirnoff }
40573b3a8eb9SGleb Smirnoff $$ = grp->gr_gid;
40583b3a8eb9SGleb Smirnoff }
40593b3a8eb9SGleb Smirnoff free($1);
40603b3a8eb9SGleb Smirnoff }
40613b3a8eb9SGleb Smirnoff | NUMBER {
40623b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 >= GID_MAX) {
40633b3a8eb9SGleb Smirnoff yyerror("illegal gid value %lu", $1);
40643b3a8eb9SGleb Smirnoff YYERROR;
40653b3a8eb9SGleb Smirnoff }
40663b3a8eb9SGleb Smirnoff $$ = $1;
40673b3a8eb9SGleb Smirnoff }
40683b3a8eb9SGleb Smirnoff ;
40693b3a8eb9SGleb Smirnoff
40703b3a8eb9SGleb Smirnoff flag : STRING {
40713b3a8eb9SGleb Smirnoff int f;
40723b3a8eb9SGleb Smirnoff
40733b3a8eb9SGleb Smirnoff if ((f = parse_flags($1)) < 0) {
40743b3a8eb9SGleb Smirnoff yyerror("bad flags %s", $1);
40753b3a8eb9SGleb Smirnoff free($1);
40763b3a8eb9SGleb Smirnoff YYERROR;
40773b3a8eb9SGleb Smirnoff }
40783b3a8eb9SGleb Smirnoff free($1);
40793b3a8eb9SGleb Smirnoff $$.b1 = f;
40803b3a8eb9SGleb Smirnoff }
40813b3a8eb9SGleb Smirnoff ;
40823b3a8eb9SGleb Smirnoff
40833b3a8eb9SGleb Smirnoff flags : FLAGS flag '/' flag { $$.b1 = $2.b1; $$.b2 = $4.b1; }
40843b3a8eb9SGleb Smirnoff | FLAGS '/' flag { $$.b1 = 0; $$.b2 = $3.b1; }
40853b3a8eb9SGleb Smirnoff | FLAGS ANY { $$.b1 = 0; $$.b2 = 0; }
40863b3a8eb9SGleb Smirnoff ;
40873b3a8eb9SGleb Smirnoff
40883b3a8eb9SGleb Smirnoff icmpspec : ICMPTYPE icmp_item { $$ = $2; }
40893b3a8eb9SGleb Smirnoff | ICMPTYPE '{' optnl icmp_list '}' { $$ = $4; }
40903b3a8eb9SGleb Smirnoff | ICMP6TYPE icmp6_item { $$ = $2; }
40913b3a8eb9SGleb Smirnoff | ICMP6TYPE '{' optnl icmp6_list '}' { $$ = $4; }
40923b3a8eb9SGleb Smirnoff ;
40933b3a8eb9SGleb Smirnoff
40943b3a8eb9SGleb Smirnoff icmp_list : icmp_item optnl { $$ = $1; }
40953b3a8eb9SGleb Smirnoff | icmp_list comma icmp_item optnl {
40963b3a8eb9SGleb Smirnoff $1->tail->next = $3;
40973b3a8eb9SGleb Smirnoff $1->tail = $3;
40983b3a8eb9SGleb Smirnoff $$ = $1;
40993b3a8eb9SGleb Smirnoff }
41003b3a8eb9SGleb Smirnoff ;
41013b3a8eb9SGleb Smirnoff
41023b3a8eb9SGleb Smirnoff icmp6_list : icmp6_item optnl { $$ = $1; }
41033b3a8eb9SGleb Smirnoff | icmp6_list comma icmp6_item optnl {
41043b3a8eb9SGleb Smirnoff $1->tail->next = $3;
41053b3a8eb9SGleb Smirnoff $1->tail = $3;
41063b3a8eb9SGleb Smirnoff $$ = $1;
41073b3a8eb9SGleb Smirnoff }
41083b3a8eb9SGleb Smirnoff ;
41093b3a8eb9SGleb Smirnoff
41103b3a8eb9SGleb Smirnoff icmp_item : icmptype {
41113b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_icmp));
41123b3a8eb9SGleb Smirnoff if ($$ == NULL)
41133b3a8eb9SGleb Smirnoff err(1, "icmp_item: calloc");
41143b3a8eb9SGleb Smirnoff $$->type = $1;
41153b3a8eb9SGleb Smirnoff $$->code = 0;
41163b3a8eb9SGleb Smirnoff $$->proto = IPPROTO_ICMP;
41173b3a8eb9SGleb Smirnoff $$->next = NULL;
41183b3a8eb9SGleb Smirnoff $$->tail = $$;
41193b3a8eb9SGleb Smirnoff }
41203b3a8eb9SGleb Smirnoff | icmptype CODE STRING {
41213b3a8eb9SGleb Smirnoff const struct icmpcodeent *p;
41223b3a8eb9SGleb Smirnoff
41233b3a8eb9SGleb Smirnoff if ((p = geticmpcodebyname($1-1, $3, AF_INET)) == NULL) {
41243b3a8eb9SGleb Smirnoff yyerror("unknown icmp-code %s", $3);
41253b3a8eb9SGleb Smirnoff free($3);
41263b3a8eb9SGleb Smirnoff YYERROR;
41273b3a8eb9SGleb Smirnoff }
41283b3a8eb9SGleb Smirnoff
41293b3a8eb9SGleb Smirnoff free($3);
41303b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_icmp));
41313b3a8eb9SGleb Smirnoff if ($$ == NULL)
41323b3a8eb9SGleb Smirnoff err(1, "icmp_item: calloc");
41333b3a8eb9SGleb Smirnoff $$->type = $1;
41343b3a8eb9SGleb Smirnoff $$->code = p->code + 1;
41353b3a8eb9SGleb Smirnoff $$->proto = IPPROTO_ICMP;
41363b3a8eb9SGleb Smirnoff $$->next = NULL;
41373b3a8eb9SGleb Smirnoff $$->tail = $$;
41383b3a8eb9SGleb Smirnoff }
41393b3a8eb9SGleb Smirnoff | icmptype CODE NUMBER {
41403b3a8eb9SGleb Smirnoff if ($3 < 0 || $3 > 255) {
41413b3a8eb9SGleb Smirnoff yyerror("illegal icmp-code %lu", $3);
41423b3a8eb9SGleb Smirnoff YYERROR;
41433b3a8eb9SGleb Smirnoff }
41443b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_icmp));
41453b3a8eb9SGleb Smirnoff if ($$ == NULL)
41463b3a8eb9SGleb Smirnoff err(1, "icmp_item: calloc");
41473b3a8eb9SGleb Smirnoff $$->type = $1;
41483b3a8eb9SGleb Smirnoff $$->code = $3 + 1;
41493b3a8eb9SGleb Smirnoff $$->proto = IPPROTO_ICMP;
41503b3a8eb9SGleb Smirnoff $$->next = NULL;
41513b3a8eb9SGleb Smirnoff $$->tail = $$;
41523b3a8eb9SGleb Smirnoff }
41533b3a8eb9SGleb Smirnoff ;
41543b3a8eb9SGleb Smirnoff
41553b3a8eb9SGleb Smirnoff icmp6_item : icmp6type {
41563b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_icmp));
41573b3a8eb9SGleb Smirnoff if ($$ == NULL)
41583b3a8eb9SGleb Smirnoff err(1, "icmp_item: calloc");
41593b3a8eb9SGleb Smirnoff $$->type = $1;
41603b3a8eb9SGleb Smirnoff $$->code = 0;
41613b3a8eb9SGleb Smirnoff $$->proto = IPPROTO_ICMPV6;
41623b3a8eb9SGleb Smirnoff $$->next = NULL;
41633b3a8eb9SGleb Smirnoff $$->tail = $$;
41643b3a8eb9SGleb Smirnoff }
41653b3a8eb9SGleb Smirnoff | icmp6type CODE STRING {
41663b3a8eb9SGleb Smirnoff const struct icmpcodeent *p;
41673b3a8eb9SGleb Smirnoff
41683b3a8eb9SGleb Smirnoff if ((p = geticmpcodebyname($1-1, $3, AF_INET6)) == NULL) {
41693b3a8eb9SGleb Smirnoff yyerror("unknown icmp6-code %s", $3);
41703b3a8eb9SGleb Smirnoff free($3);
41713b3a8eb9SGleb Smirnoff YYERROR;
41723b3a8eb9SGleb Smirnoff }
41733b3a8eb9SGleb Smirnoff free($3);
41743b3a8eb9SGleb Smirnoff
41753b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_icmp));
41763b3a8eb9SGleb Smirnoff if ($$ == NULL)
41773b3a8eb9SGleb Smirnoff err(1, "icmp_item: calloc");
41783b3a8eb9SGleb Smirnoff $$->type = $1;
41793b3a8eb9SGleb Smirnoff $$->code = p->code + 1;
41803b3a8eb9SGleb Smirnoff $$->proto = IPPROTO_ICMPV6;
41813b3a8eb9SGleb Smirnoff $$->next = NULL;
41823b3a8eb9SGleb Smirnoff $$->tail = $$;
41833b3a8eb9SGleb Smirnoff }
41843b3a8eb9SGleb Smirnoff | icmp6type CODE NUMBER {
41853b3a8eb9SGleb Smirnoff if ($3 < 0 || $3 > 255) {
41863b3a8eb9SGleb Smirnoff yyerror("illegal icmp-code %lu", $3);
41873b3a8eb9SGleb Smirnoff YYERROR;
41883b3a8eb9SGleb Smirnoff }
41893b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_icmp));
41903b3a8eb9SGleb Smirnoff if ($$ == NULL)
41913b3a8eb9SGleb Smirnoff err(1, "icmp_item: calloc");
41923b3a8eb9SGleb Smirnoff $$->type = $1;
41933b3a8eb9SGleb Smirnoff $$->code = $3 + 1;
41943b3a8eb9SGleb Smirnoff $$->proto = IPPROTO_ICMPV6;
41953b3a8eb9SGleb Smirnoff $$->next = NULL;
41963b3a8eb9SGleb Smirnoff $$->tail = $$;
41973b3a8eb9SGleb Smirnoff }
41983b3a8eb9SGleb Smirnoff ;
41993b3a8eb9SGleb Smirnoff
42003b3a8eb9SGleb Smirnoff icmptype : STRING {
42013b3a8eb9SGleb Smirnoff const struct icmptypeent *p;
42023b3a8eb9SGleb Smirnoff
42033b3a8eb9SGleb Smirnoff if ((p = geticmptypebyname($1, AF_INET)) == NULL) {
42043b3a8eb9SGleb Smirnoff yyerror("unknown icmp-type %s", $1);
42053b3a8eb9SGleb Smirnoff free($1);
42063b3a8eb9SGleb Smirnoff YYERROR;
42073b3a8eb9SGleb Smirnoff }
42083b3a8eb9SGleb Smirnoff $$ = p->type + 1;
42093b3a8eb9SGleb Smirnoff free($1);
42103b3a8eb9SGleb Smirnoff }
42113b3a8eb9SGleb Smirnoff | NUMBER {
42123b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 > 255) {
42133b3a8eb9SGleb Smirnoff yyerror("illegal icmp-type %lu", $1);
42143b3a8eb9SGleb Smirnoff YYERROR;
42153b3a8eb9SGleb Smirnoff }
42163b3a8eb9SGleb Smirnoff $$ = $1 + 1;
42173b3a8eb9SGleb Smirnoff }
42183b3a8eb9SGleb Smirnoff ;
42193b3a8eb9SGleb Smirnoff
42203b3a8eb9SGleb Smirnoff icmp6type : STRING {
42213b3a8eb9SGleb Smirnoff const struct icmptypeent *p;
42223b3a8eb9SGleb Smirnoff
42233b3a8eb9SGleb Smirnoff if ((p = geticmptypebyname($1, AF_INET6)) ==
42243b3a8eb9SGleb Smirnoff NULL) {
42253b3a8eb9SGleb Smirnoff yyerror("unknown icmp6-type %s", $1);
42263b3a8eb9SGleb Smirnoff free($1);
42273b3a8eb9SGleb Smirnoff YYERROR;
42283b3a8eb9SGleb Smirnoff }
42293b3a8eb9SGleb Smirnoff $$ = p->type + 1;
42303b3a8eb9SGleb Smirnoff free($1);
42313b3a8eb9SGleb Smirnoff }
42323b3a8eb9SGleb Smirnoff | NUMBER {
42333b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 > 255) {
42343b3a8eb9SGleb Smirnoff yyerror("illegal icmp6-type %lu", $1);
42353b3a8eb9SGleb Smirnoff YYERROR;
42363b3a8eb9SGleb Smirnoff }
42373b3a8eb9SGleb Smirnoff $$ = $1 + 1;
42383b3a8eb9SGleb Smirnoff }
42393b3a8eb9SGleb Smirnoff ;
42403b3a8eb9SGleb Smirnoff
42413b3a8eb9SGleb Smirnoff tos : STRING {
42421f495578SKristof Provost int val;
42431f495578SKristof Provost char *end;
42441f495578SKristof Provost
42451f495578SKristof Provost if (map_tos($1, &val))
42461f495578SKristof Provost $$ = val;
42471f495578SKristof Provost else if ($1[0] == '0' && $1[1] == 'x') {
42481f495578SKristof Provost errno = 0;
42491f495578SKristof Provost $$ = strtoul($1, &end, 16);
42501f495578SKristof Provost if (errno || *end != '\0')
42511f495578SKristof Provost $$ = 256;
42521f495578SKristof Provost } else
42530cd7a91aSKristof Provost $$ = 256; /* flag bad argument */
42540cd7a91aSKristof Provost if ($$ < 0 || $$ > 255) {
42553b3a8eb9SGleb Smirnoff yyerror("illegal tos value %s", $1);
42563b3a8eb9SGleb Smirnoff free($1);
42573b3a8eb9SGleb Smirnoff YYERROR;
42583b3a8eb9SGleb Smirnoff }
42593b3a8eb9SGleb Smirnoff free($1);
42603b3a8eb9SGleb Smirnoff }
42613b3a8eb9SGleb Smirnoff | NUMBER {
42623b3a8eb9SGleb Smirnoff $$ = $1;
42630cd7a91aSKristof Provost if ($$ < 0 || $$ > 255) {
42646562157dSKristof Provost yyerror("illegal tos value %lu", $1);
42653b3a8eb9SGleb Smirnoff YYERROR;
42663b3a8eb9SGleb Smirnoff }
42673b3a8eb9SGleb Smirnoff }
42683b3a8eb9SGleb Smirnoff ;
42693b3a8eb9SGleb Smirnoff
42703b3a8eb9SGleb Smirnoff sourcetrack : SOURCETRACK { $$ = PF_SRCTRACK; }
42713b3a8eb9SGleb Smirnoff | SOURCETRACK GLOBAL { $$ = PF_SRCTRACK_GLOBAL; }
42723b3a8eb9SGleb Smirnoff | SOURCETRACK RULE { $$ = PF_SRCTRACK_RULE; }
42733b3a8eb9SGleb Smirnoff ;
42743b3a8eb9SGleb Smirnoff
42753b3a8eb9SGleb Smirnoff statelock : IFBOUND {
42763b3a8eb9SGleb Smirnoff $$ = PFRULE_IFBOUND;
42773b3a8eb9SGleb Smirnoff }
42783b3a8eb9SGleb Smirnoff | FLOATING {
42793b3a8eb9SGleb Smirnoff $$ = 0;
42803b3a8eb9SGleb Smirnoff }
42813b3a8eb9SGleb Smirnoff ;
42823b3a8eb9SGleb Smirnoff
42833b3a8eb9SGleb Smirnoff keep : NO STATE {
42843b3a8eb9SGleb Smirnoff $$.action = 0;
42853b3a8eb9SGleb Smirnoff $$.options = NULL;
42863b3a8eb9SGleb Smirnoff }
42873b3a8eb9SGleb Smirnoff | KEEP STATE state_opt_spec {
42883b3a8eb9SGleb Smirnoff $$.action = PF_STATE_NORMAL;
42893b3a8eb9SGleb Smirnoff $$.options = $3;
42903b3a8eb9SGleb Smirnoff }
42913b3a8eb9SGleb Smirnoff | MODULATE STATE state_opt_spec {
42923b3a8eb9SGleb Smirnoff $$.action = PF_STATE_MODULATE;
42933b3a8eb9SGleb Smirnoff $$.options = $3;
42943b3a8eb9SGleb Smirnoff }
42953b3a8eb9SGleb Smirnoff | SYNPROXY STATE state_opt_spec {
42963b3a8eb9SGleb Smirnoff $$.action = PF_STATE_SYNPROXY;
42973b3a8eb9SGleb Smirnoff $$.options = $3;
42983b3a8eb9SGleb Smirnoff }
42993b3a8eb9SGleb Smirnoff ;
43003b3a8eb9SGleb Smirnoff
43013b3a8eb9SGleb Smirnoff flush : /* empty */ { $$ = 0; }
43023b3a8eb9SGleb Smirnoff | FLUSH { $$ = PF_FLUSH; }
43033b3a8eb9SGleb Smirnoff | FLUSH GLOBAL {
43043b3a8eb9SGleb Smirnoff $$ = PF_FLUSH | PF_FLUSH_GLOBAL;
43053b3a8eb9SGleb Smirnoff }
43063b3a8eb9SGleb Smirnoff ;
43073b3a8eb9SGleb Smirnoff
43083b3a8eb9SGleb Smirnoff state_opt_spec : '(' state_opt_list ')' { $$ = $2; }
43093b3a8eb9SGleb Smirnoff | /* empty */ { $$ = NULL; }
43103b3a8eb9SGleb Smirnoff ;
43113b3a8eb9SGleb Smirnoff
43123b3a8eb9SGleb Smirnoff state_opt_list : state_opt_item { $$ = $1; }
43133b3a8eb9SGleb Smirnoff | state_opt_list comma state_opt_item {
43143b3a8eb9SGleb Smirnoff $1->tail->next = $3;
43153b3a8eb9SGleb Smirnoff $1->tail = $3;
43163b3a8eb9SGleb Smirnoff $$ = $1;
43173b3a8eb9SGleb Smirnoff }
43183b3a8eb9SGleb Smirnoff ;
43193b3a8eb9SGleb Smirnoff
43203b3a8eb9SGleb Smirnoff state_opt_item : MAXIMUM NUMBER {
43213b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX) {
43223b3a8eb9SGleb Smirnoff yyerror("only positive values permitted");
43233b3a8eb9SGleb Smirnoff YYERROR;
43243b3a8eb9SGleb Smirnoff }
43253b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt));
43263b3a8eb9SGleb Smirnoff if ($$ == NULL)
43273b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc");
43283b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_MAX;
43293b3a8eb9SGleb Smirnoff $$->data.max_states = $2;
43303b3a8eb9SGleb Smirnoff $$->next = NULL;
43313b3a8eb9SGleb Smirnoff $$->tail = $$;
43323b3a8eb9SGleb Smirnoff }
43333b3a8eb9SGleb Smirnoff | NOSYNC {
43343b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt));
43353b3a8eb9SGleb Smirnoff if ($$ == NULL)
43363b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc");
43373b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_NOSYNC;
43383b3a8eb9SGleb Smirnoff $$->next = NULL;
43393b3a8eb9SGleb Smirnoff $$->tail = $$;
43403b3a8eb9SGleb Smirnoff }
43413b3a8eb9SGleb Smirnoff | MAXSRCSTATES NUMBER {
43423b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX) {
43433b3a8eb9SGleb Smirnoff yyerror("only positive values permitted");
43443b3a8eb9SGleb Smirnoff YYERROR;
43453b3a8eb9SGleb Smirnoff }
43463b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt));
43473b3a8eb9SGleb Smirnoff if ($$ == NULL)
43483b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc");
43493b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_MAX_SRC_STATES;
43503b3a8eb9SGleb Smirnoff $$->data.max_src_states = $2;
43513b3a8eb9SGleb Smirnoff $$->next = NULL;
43523b3a8eb9SGleb Smirnoff $$->tail = $$;
43533b3a8eb9SGleb Smirnoff }
43543b3a8eb9SGleb Smirnoff | MAXSRCCONN NUMBER {
43553b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX) {
43563b3a8eb9SGleb Smirnoff yyerror("only positive values permitted");
43573b3a8eb9SGleb Smirnoff YYERROR;
43583b3a8eb9SGleb Smirnoff }
43593b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt));
43603b3a8eb9SGleb Smirnoff if ($$ == NULL)
43613b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc");
43623b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_MAX_SRC_CONN;
43633b3a8eb9SGleb Smirnoff $$->data.max_src_conn = $2;
43643b3a8eb9SGleb Smirnoff $$->next = NULL;
43653b3a8eb9SGleb Smirnoff $$->tail = $$;
43663b3a8eb9SGleb Smirnoff }
43673b3a8eb9SGleb Smirnoff | MAXSRCCONNRATE NUMBER '/' NUMBER {
43683b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX ||
43693b3a8eb9SGleb Smirnoff $4 < 0 || $4 > UINT_MAX) {
43703b3a8eb9SGleb Smirnoff yyerror("only positive values permitted");
43713b3a8eb9SGleb Smirnoff YYERROR;
43723b3a8eb9SGleb Smirnoff }
43733b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt));
43743b3a8eb9SGleb Smirnoff if ($$ == NULL)
43753b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc");
43763b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_MAX_SRC_CONN_RATE;
43773b3a8eb9SGleb Smirnoff $$->data.max_src_conn_rate.limit = $2;
43783b3a8eb9SGleb Smirnoff $$->data.max_src_conn_rate.seconds = $4;
43793b3a8eb9SGleb Smirnoff $$->next = NULL;
43803b3a8eb9SGleb Smirnoff $$->tail = $$;
43813b3a8eb9SGleb Smirnoff }
43823b3a8eb9SGleb Smirnoff | OVERLOAD '<' STRING '>' flush {
43833b3a8eb9SGleb Smirnoff if (strlen($3) >= PF_TABLE_NAME_SIZE) {
43843b3a8eb9SGleb Smirnoff yyerror("table name '%s' too long", $3);
43853b3a8eb9SGleb Smirnoff free($3);
43863b3a8eb9SGleb Smirnoff YYERROR;
43873b3a8eb9SGleb Smirnoff }
43883b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt));
43893b3a8eb9SGleb Smirnoff if ($$ == NULL)
43903b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc");
43913b3a8eb9SGleb Smirnoff if (strlcpy($$->data.overload.tblname, $3,
43923b3a8eb9SGleb Smirnoff PF_TABLE_NAME_SIZE) >= PF_TABLE_NAME_SIZE)
43933b3a8eb9SGleb Smirnoff errx(1, "state_opt_item: strlcpy");
43943b3a8eb9SGleb Smirnoff free($3);
43953b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_OVERLOAD;
43963b3a8eb9SGleb Smirnoff $$->data.overload.flush = $5;
43973b3a8eb9SGleb Smirnoff $$->next = NULL;
43983b3a8eb9SGleb Smirnoff $$->tail = $$;
43993b3a8eb9SGleb Smirnoff }
44003b3a8eb9SGleb Smirnoff | MAXSRCNODES NUMBER {
44013b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX) {
44023b3a8eb9SGleb Smirnoff yyerror("only positive values permitted");
44033b3a8eb9SGleb Smirnoff YYERROR;
44043b3a8eb9SGleb Smirnoff }
44053b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt));
44063b3a8eb9SGleb Smirnoff if ($$ == NULL)
44073b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc");
44083b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_MAX_SRC_NODES;
44093b3a8eb9SGleb Smirnoff $$->data.max_src_nodes = $2;
44103b3a8eb9SGleb Smirnoff $$->next = NULL;
44113b3a8eb9SGleb Smirnoff $$->tail = $$;
44123b3a8eb9SGleb Smirnoff }
44133b3a8eb9SGleb Smirnoff | sourcetrack {
44143b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt));
44153b3a8eb9SGleb Smirnoff if ($$ == NULL)
44163b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc");
44173b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_SRCTRACK;
44183b3a8eb9SGleb Smirnoff $$->data.src_track = $1;
44193b3a8eb9SGleb Smirnoff $$->next = NULL;
44203b3a8eb9SGleb Smirnoff $$->tail = $$;
44213b3a8eb9SGleb Smirnoff }
44223b3a8eb9SGleb Smirnoff | statelock {
44233b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt));
44243b3a8eb9SGleb Smirnoff if ($$ == NULL)
44253b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc");
44263b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_STATELOCK;
44273b3a8eb9SGleb Smirnoff $$->data.statelock = $1;
44283b3a8eb9SGleb Smirnoff $$->next = NULL;
44293b3a8eb9SGleb Smirnoff $$->tail = $$;
44303b3a8eb9SGleb Smirnoff }
44313b3a8eb9SGleb Smirnoff | SLOPPY {
44323b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt));
44333b3a8eb9SGleb Smirnoff if ($$ == NULL)
44343b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc");
44353b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_SLOPPY;
44363b3a8eb9SGleb Smirnoff $$->next = NULL;
44373b3a8eb9SGleb Smirnoff $$->tail = $$;
44383b3a8eb9SGleb Smirnoff }
4439baf9b6d0SKristof Provost | PFLOW {
4440baf9b6d0SKristof Provost $$ = calloc(1, sizeof(struct node_state_opt));
4441baf9b6d0SKristof Provost if ($$ == NULL)
4442baf9b6d0SKristof Provost err(1, "state_opt_item: calloc");
4443baf9b6d0SKristof Provost $$->type = PF_STATE_OPT_PFLOW;
4444baf9b6d0SKristof Provost $$->next = NULL;
4445baf9b6d0SKristof Provost $$->tail = $$;
4446baf9b6d0SKristof Provost }
4447e4f2733dSKristof Provost | ALLOW_RELATED {
4448e4f2733dSKristof Provost $$ = calloc(1, sizeof(struct node_state_opt));
4449e4f2733dSKristof Provost if ($$ == NULL)
4450e4f2733dSKristof Provost err(1, "state_opt_item: calloc");
4451e4f2733dSKristof Provost $$->type = PF_STATE_OPT_ALLOW_RELATED;
4452e4f2733dSKristof Provost $$->next = NULL;
4453e4f2733dSKristof Provost $$->tail = $$;
4454e4f2733dSKristof Provost }
44553b3a8eb9SGleb Smirnoff | STRING NUMBER {
44563b3a8eb9SGleb Smirnoff int i;
44573b3a8eb9SGleb Smirnoff
44583b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX) {
44593b3a8eb9SGleb Smirnoff yyerror("only positive values permitted");
44603b3a8eb9SGleb Smirnoff YYERROR;
44613b3a8eb9SGleb Smirnoff }
44623b3a8eb9SGleb Smirnoff for (i = 0; pf_timeouts[i].name &&
44633b3a8eb9SGleb Smirnoff strcmp(pf_timeouts[i].name, $1); ++i)
44643b3a8eb9SGleb Smirnoff ; /* nothing */
44653b3a8eb9SGleb Smirnoff if (!pf_timeouts[i].name) {
44663b3a8eb9SGleb Smirnoff yyerror("illegal timeout name %s", $1);
44673b3a8eb9SGleb Smirnoff free($1);
44683b3a8eb9SGleb Smirnoff YYERROR;
44693b3a8eb9SGleb Smirnoff }
44703b3a8eb9SGleb Smirnoff if (strchr(pf_timeouts[i].name, '.') == NULL) {
44713b3a8eb9SGleb Smirnoff yyerror("illegal state timeout %s", $1);
44723b3a8eb9SGleb Smirnoff free($1);
44733b3a8eb9SGleb Smirnoff YYERROR;
44743b3a8eb9SGleb Smirnoff }
44753b3a8eb9SGleb Smirnoff free($1);
44763b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt));
44773b3a8eb9SGleb Smirnoff if ($$ == NULL)
44783b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc");
44793b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_TIMEOUT;
44803b3a8eb9SGleb Smirnoff $$->data.timeout.number = pf_timeouts[i].timeout;
44813b3a8eb9SGleb Smirnoff $$->data.timeout.seconds = $2;
44823b3a8eb9SGleb Smirnoff $$->next = NULL;
44833b3a8eb9SGleb Smirnoff $$->tail = $$;
44843b3a8eb9SGleb Smirnoff }
44853b3a8eb9SGleb Smirnoff ;
44863b3a8eb9SGleb Smirnoff
44873b3a8eb9SGleb Smirnoff label : LABEL STRING {
44883b3a8eb9SGleb Smirnoff $$ = $2;
44893b3a8eb9SGleb Smirnoff }
44903b3a8eb9SGleb Smirnoff ;
44913b3a8eb9SGleb Smirnoff
44922b29ceb8SKristof Provost etherqname : QUEUE STRING {
44932b29ceb8SKristof Provost $$.qname = $2;
44942b29ceb8SKristof Provost }
44952b29ceb8SKristof Provost | QUEUE '(' STRING ')' {
44962b29ceb8SKristof Provost $$.qname = $3;
44972b29ceb8SKristof Provost }
44982b29ceb8SKristof Provost ;
44992b29ceb8SKristof Provost
45003b3a8eb9SGleb Smirnoff qname : QUEUE STRING {
45013b3a8eb9SGleb Smirnoff $$.qname = $2;
45023b3a8eb9SGleb Smirnoff $$.pqname = NULL;
45033b3a8eb9SGleb Smirnoff }
45043b3a8eb9SGleb Smirnoff | QUEUE '(' STRING ')' {
45053b3a8eb9SGleb Smirnoff $$.qname = $3;
45063b3a8eb9SGleb Smirnoff $$.pqname = NULL;
45073b3a8eb9SGleb Smirnoff }
45083b3a8eb9SGleb Smirnoff | QUEUE '(' STRING comma STRING ')' {
45093b3a8eb9SGleb Smirnoff $$.qname = $3;
45103b3a8eb9SGleb Smirnoff $$.pqname = $5;
45113b3a8eb9SGleb Smirnoff }
45123b3a8eb9SGleb Smirnoff ;
45133b3a8eb9SGleb Smirnoff
45143b3a8eb9SGleb Smirnoff no : /* empty */ { $$ = 0; }
45153b3a8eb9SGleb Smirnoff | NO { $$ = 1; }
45163b3a8eb9SGleb Smirnoff ;
45173b3a8eb9SGleb Smirnoff
45183b3a8eb9SGleb Smirnoff portstar : numberstring {
45193b3a8eb9SGleb Smirnoff if (parseport($1, &$$, PPORT_RANGE|PPORT_STAR) == -1) {
45203b3a8eb9SGleb Smirnoff free($1);
45213b3a8eb9SGleb Smirnoff YYERROR;
45223b3a8eb9SGleb Smirnoff }
45233b3a8eb9SGleb Smirnoff free($1);
45243b3a8eb9SGleb Smirnoff }
45253b3a8eb9SGleb Smirnoff ;
45263b3a8eb9SGleb Smirnoff
4527*aeddee83SKajetan Staszkiewicz redir_host : host { $$ = $1; }
45283b3a8eb9SGleb Smirnoff | '{' optnl redir_host_list '}' { $$ = $3; }
45293b3a8eb9SGleb Smirnoff ;
45303b3a8eb9SGleb Smirnoff
45313b3a8eb9SGleb Smirnoff redir_host_list : host optnl { $$ = $1; }
45323b3a8eb9SGleb Smirnoff | redir_host_list comma host optnl {
45333b3a8eb9SGleb Smirnoff $1->tail->next = $3;
45343b3a8eb9SGleb Smirnoff $1->tail = $3->tail;
45353b3a8eb9SGleb Smirnoff $$ = $1;
45363b3a8eb9SGleb Smirnoff }
45373b3a8eb9SGleb Smirnoff ;
45383b3a8eb9SGleb Smirnoff
4539*aeddee83SKajetan Staszkiewicz /* Redirection without port */
4540*aeddee83SKajetan Staszkiewicz no_port_redirspec: redir_host pool_opts {
4541*aeddee83SKajetan Staszkiewicz $$ = calloc(1, sizeof(struct redirspec));
45423b3a8eb9SGleb Smirnoff if ($$ == NULL)
4543*aeddee83SKajetan Staszkiewicz err(1, "redirspec: calloc");
4544*aeddee83SKajetan Staszkiewicz $$->host = $1;
4545*aeddee83SKajetan Staszkiewicz $$->pool_opts = $2;
45463b3a8eb9SGleb Smirnoff $$->rport.a = $$->rport.b = $$->rport.t = 0;
45473b3a8eb9SGleb Smirnoff }
4548*aeddee83SKajetan Staszkiewicz ;
4549*aeddee83SKajetan Staszkiewicz
4550*aeddee83SKajetan Staszkiewicz /* Redirection with optional port */
4551*aeddee83SKajetan Staszkiewicz port_redirspec : no_port_redirspec;
4552*aeddee83SKajetan Staszkiewicz | redir_host PORT portstar pool_opts {
4553*aeddee83SKajetan Staszkiewicz $$ = calloc(1, sizeof(struct redirspec));
45543b3a8eb9SGleb Smirnoff if ($$ == NULL)
4555*aeddee83SKajetan Staszkiewicz err(1, "redirspec: calloc");
4556*aeddee83SKajetan Staszkiewicz $$->host = $1;
4557*aeddee83SKajetan Staszkiewicz $$->rport = $3;
4558*aeddee83SKajetan Staszkiewicz $$->pool_opts = $4;
4559*aeddee83SKajetan Staszkiewicz }
4560*aeddee83SKajetan Staszkiewicz
4561*aeddee83SKajetan Staszkiewicz /* Redirection with an arrow and an optional port: FreeBSD NAT rules */
4562*aeddee83SKajetan Staszkiewicz nat_redirspec : ARROW port_redirspec {
4563*aeddee83SKajetan Staszkiewicz $$ = $2;
4564*aeddee83SKajetan Staszkiewicz }
4565*aeddee83SKajetan Staszkiewicz ;
4566*aeddee83SKajetan Staszkiewicz
4567*aeddee83SKajetan Staszkiewicz /* Redirection with interfaces and without ports: route-to rules */
4568*aeddee83SKajetan Staszkiewicz route_redirspec : routespec pool_opts {
4569*aeddee83SKajetan Staszkiewicz $$ = calloc(1, sizeof(struct redirspec));
4570*aeddee83SKajetan Staszkiewicz if ($$ == NULL)
4571*aeddee83SKajetan Staszkiewicz err(1, "redirspec: calloc");
4572*aeddee83SKajetan Staszkiewicz $$->host = $1;
4573*aeddee83SKajetan Staszkiewicz $$->pool_opts = $2;
45743b3a8eb9SGleb Smirnoff }
45753b3a8eb9SGleb Smirnoff ;
45763b3a8eb9SGleb Smirnoff
45773b3a8eb9SGleb Smirnoff hashkey : /* empty */
45783b3a8eb9SGleb Smirnoff {
45793b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct pf_poolhashkey));
45803b3a8eb9SGleb Smirnoff if ($$ == NULL)
45813b3a8eb9SGleb Smirnoff err(1, "hashkey: calloc");
45823b3a8eb9SGleb Smirnoff $$->key32[0] = arc4random();
45833b3a8eb9SGleb Smirnoff $$->key32[1] = arc4random();
45843b3a8eb9SGleb Smirnoff $$->key32[2] = arc4random();
45853b3a8eb9SGleb Smirnoff $$->key32[3] = arc4random();
45863b3a8eb9SGleb Smirnoff }
45873b3a8eb9SGleb Smirnoff | string
45883b3a8eb9SGleb Smirnoff {
45893b3a8eb9SGleb Smirnoff if (!strncmp($1, "0x", 2)) {
45903b3a8eb9SGleb Smirnoff if (strlen($1) != 34) {
45913b3a8eb9SGleb Smirnoff free($1);
45923b3a8eb9SGleb Smirnoff yyerror("hex key must be 128 bits "
45933b3a8eb9SGleb Smirnoff "(32 hex digits) long");
45943b3a8eb9SGleb Smirnoff YYERROR;
45953b3a8eb9SGleb Smirnoff }
45963b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct pf_poolhashkey));
45973b3a8eb9SGleb Smirnoff if ($$ == NULL)
45983b3a8eb9SGleb Smirnoff err(1, "hashkey: calloc");
45993b3a8eb9SGleb Smirnoff
46003b3a8eb9SGleb Smirnoff if (sscanf($1, "0x%8x%8x%8x%8x",
46013b3a8eb9SGleb Smirnoff &$$->key32[0], &$$->key32[1],
46023b3a8eb9SGleb Smirnoff &$$->key32[2], &$$->key32[3]) != 4) {
46033b3a8eb9SGleb Smirnoff free($$);
46043b3a8eb9SGleb Smirnoff free($1);
46053b3a8eb9SGleb Smirnoff yyerror("invalid hex key");
46063b3a8eb9SGleb Smirnoff YYERROR;
46073b3a8eb9SGleb Smirnoff }
46083b3a8eb9SGleb Smirnoff } else {
46093b3a8eb9SGleb Smirnoff MD5_CTX context;
46103b3a8eb9SGleb Smirnoff
46113b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct pf_poolhashkey));
46123b3a8eb9SGleb Smirnoff if ($$ == NULL)
46133b3a8eb9SGleb Smirnoff err(1, "hashkey: calloc");
46143b3a8eb9SGleb Smirnoff MD5Init(&context);
46153b3a8eb9SGleb Smirnoff MD5Update(&context, (unsigned char *)$1,
46163b3a8eb9SGleb Smirnoff strlen($1));
46173b3a8eb9SGleb Smirnoff MD5Final((unsigned char *)$$, &context);
46183b3a8eb9SGleb Smirnoff HTONL($$->key32[0]);
46193b3a8eb9SGleb Smirnoff HTONL($$->key32[1]);
46203b3a8eb9SGleb Smirnoff HTONL($$->key32[2]);
46213b3a8eb9SGleb Smirnoff HTONL($$->key32[3]);
46223b3a8eb9SGleb Smirnoff }
46233b3a8eb9SGleb Smirnoff free($1);
46243b3a8eb9SGleb Smirnoff }
46253b3a8eb9SGleb Smirnoff ;
46263b3a8eb9SGleb Smirnoff
46273b3a8eb9SGleb Smirnoff pool_opts : { bzero(&pool_opts, sizeof pool_opts); }
46283b3a8eb9SGleb Smirnoff pool_opts_l
46293b3a8eb9SGleb Smirnoff { $$ = pool_opts; }
46303b3a8eb9SGleb Smirnoff | /* empty */ {
46313b3a8eb9SGleb Smirnoff bzero(&pool_opts, sizeof pool_opts);
46323b3a8eb9SGleb Smirnoff $$ = pool_opts;
46333b3a8eb9SGleb Smirnoff }
46343b3a8eb9SGleb Smirnoff ;
46353b3a8eb9SGleb Smirnoff
46363b3a8eb9SGleb Smirnoff pool_opts_l : pool_opts_l pool_opt
46373b3a8eb9SGleb Smirnoff | pool_opt
46383b3a8eb9SGleb Smirnoff ;
46393b3a8eb9SGleb Smirnoff
46403b3a8eb9SGleb Smirnoff pool_opt : BITMASK {
46413b3a8eb9SGleb Smirnoff if (pool_opts.type) {
46423b3a8eb9SGleb Smirnoff yyerror("pool type cannot be redefined");
46433b3a8eb9SGleb Smirnoff YYERROR;
46443b3a8eb9SGleb Smirnoff }
46453b3a8eb9SGleb Smirnoff pool_opts.type = PF_POOL_BITMASK;
46463b3a8eb9SGleb Smirnoff }
46473b3a8eb9SGleb Smirnoff | RANDOM {
46483b3a8eb9SGleb Smirnoff if (pool_opts.type) {
46493b3a8eb9SGleb Smirnoff yyerror("pool type cannot be redefined");
46503b3a8eb9SGleb Smirnoff YYERROR;
46513b3a8eb9SGleb Smirnoff }
46523b3a8eb9SGleb Smirnoff pool_opts.type = PF_POOL_RANDOM;
46533b3a8eb9SGleb Smirnoff }
46543b3a8eb9SGleb Smirnoff | SOURCEHASH hashkey {
46553b3a8eb9SGleb Smirnoff if (pool_opts.type) {
46563b3a8eb9SGleb Smirnoff yyerror("pool type cannot be redefined");
46573b3a8eb9SGleb Smirnoff YYERROR;
46583b3a8eb9SGleb Smirnoff }
46593b3a8eb9SGleb Smirnoff pool_opts.type = PF_POOL_SRCHASH;
46603b3a8eb9SGleb Smirnoff pool_opts.key = $2;
46613b3a8eb9SGleb Smirnoff }
46623b3a8eb9SGleb Smirnoff | ROUNDROBIN {
46633b3a8eb9SGleb Smirnoff if (pool_opts.type) {
46643b3a8eb9SGleb Smirnoff yyerror("pool type cannot be redefined");
46653b3a8eb9SGleb Smirnoff YYERROR;
46663b3a8eb9SGleb Smirnoff }
46673b3a8eb9SGleb Smirnoff pool_opts.type = PF_POOL_ROUNDROBIN;
46683b3a8eb9SGleb Smirnoff }
46693b3a8eb9SGleb Smirnoff | STATICPORT {
46703b3a8eb9SGleb Smirnoff if (pool_opts.staticport) {
46713b3a8eb9SGleb Smirnoff yyerror("static-port cannot be redefined");
46723b3a8eb9SGleb Smirnoff YYERROR;
46733b3a8eb9SGleb Smirnoff }
46743b3a8eb9SGleb Smirnoff pool_opts.staticport = 1;
46753b3a8eb9SGleb Smirnoff }
46763b3a8eb9SGleb Smirnoff | STICKYADDRESS {
46771e73fbd8SFranco Fichtner if (pool_opts.marker & POM_STICKYADDRESS) {
46783b3a8eb9SGleb Smirnoff yyerror("sticky-address cannot be redefined");
46793b3a8eb9SGleb Smirnoff YYERROR;
46803b3a8eb9SGleb Smirnoff }
46813b3a8eb9SGleb Smirnoff pool_opts.marker |= POM_STICKYADDRESS;
46823b3a8eb9SGleb Smirnoff pool_opts.opts |= PF_POOL_STICKYADDR;
46833b3a8eb9SGleb Smirnoff }
4684390dc369STom Jones | ENDPI {
4685390dc369STom Jones if (pool_opts.marker & POM_ENDPI) {
4686390dc369STom Jones yyerror("endpoint-independent cannot be redefined");
4687390dc369STom Jones YYERROR;
4688390dc369STom Jones }
4689390dc369STom Jones pool_opts.marker |= POM_ENDPI;
4690390dc369STom Jones pool_opts.opts |= PF_POOL_ENDPI;
4691390dc369STom Jones }
46922aa21096SKurosawa Takahiro | MAPEPORTSET number '/' number '/' number {
46932aa21096SKurosawa Takahiro if (pool_opts.mape.offset) {
46942aa21096SKurosawa Takahiro yyerror("map-e-portset cannot be redefined");
46952aa21096SKurosawa Takahiro YYERROR;
46962aa21096SKurosawa Takahiro }
46972aa21096SKurosawa Takahiro if (pool_opts.type) {
46982aa21096SKurosawa Takahiro yyerror("map-e-portset cannot be used with "
46992aa21096SKurosawa Takahiro "address pools");
47002aa21096SKurosawa Takahiro YYERROR;
47012aa21096SKurosawa Takahiro }
47022aa21096SKurosawa Takahiro if ($2 <= 0 || $2 >= 16) {
47032aa21096SKurosawa Takahiro yyerror("MAP-E PSID offset must be 1-15");
47042aa21096SKurosawa Takahiro YYERROR;
47052aa21096SKurosawa Takahiro }
47062aa21096SKurosawa Takahiro if ($4 < 0 || $4 >= 16 || $2 + $4 > 16) {
47072aa21096SKurosawa Takahiro yyerror("Invalid MAP-E PSID length");
47082aa21096SKurosawa Takahiro YYERROR;
47092aa21096SKurosawa Takahiro } else if ($4 == 0) {
47102aa21096SKurosawa Takahiro yyerror("PSID Length = 0: this means"
47112aa21096SKurosawa Takahiro " you do not need MAP-E");
47122aa21096SKurosawa Takahiro YYERROR;
47132aa21096SKurosawa Takahiro }
47142aa21096SKurosawa Takahiro if ($6 < 0 || $6 > 65535) {
47152aa21096SKurosawa Takahiro yyerror("Invalid MAP-E PSID");
47162aa21096SKurosawa Takahiro YYERROR;
47172aa21096SKurosawa Takahiro }
47182aa21096SKurosawa Takahiro pool_opts.mape.offset = $2;
47192aa21096SKurosawa Takahiro pool_opts.mape.psidlen = $4;
47202aa21096SKurosawa Takahiro pool_opts.mape.psid = $6;
47212aa21096SKurosawa Takahiro }
47223b3a8eb9SGleb Smirnoff ;
47233b3a8eb9SGleb Smirnoff
4724*aeddee83SKajetan Staszkiewicz binat_redirspec : /* empty */ { $$ = NULL; }
47253b3a8eb9SGleb Smirnoff | ARROW host {
4726*aeddee83SKajetan Staszkiewicz $$ = calloc(1, sizeof(struct redirspec));
47273b3a8eb9SGleb Smirnoff if ($$ == NULL)
4728*aeddee83SKajetan Staszkiewicz err(1, "redirspec: calloc");
47293b3a8eb9SGleb Smirnoff $$->host = $2;
47303b3a8eb9SGleb Smirnoff $$->rport.a = $$->rport.b = $$->rport.t = 0;
47313b3a8eb9SGleb Smirnoff }
47323b3a8eb9SGleb Smirnoff | ARROW host PORT portstar {
4733*aeddee83SKajetan Staszkiewicz $$ = calloc(1, sizeof(struct redirspec));
47343b3a8eb9SGleb Smirnoff if ($$ == NULL)
4735*aeddee83SKajetan Staszkiewicz err(1, "redirspec: calloc");
47363b3a8eb9SGleb Smirnoff $$->host = $2;
47373b3a8eb9SGleb Smirnoff $$->rport = $4;
47383b3a8eb9SGleb Smirnoff }
47393b3a8eb9SGleb Smirnoff ;
47403b3a8eb9SGleb Smirnoff
47413b3a8eb9SGleb Smirnoff natpasslog : /* empty */ { $$.b1 = $$.b2 = 0; $$.w2 = 0; }
47423b3a8eb9SGleb Smirnoff | PASS { $$.b1 = 1; $$.b2 = 0; $$.w2 = 0; }
47433b3a8eb9SGleb Smirnoff | PASS log { $$.b1 = 1; $$.b2 = $2.log; $$.w2 = $2.logif; }
47443b3a8eb9SGleb Smirnoff | log { $$.b1 = 0; $$.b2 = $1.log; $$.w2 = $1.logif; }
47453b3a8eb9SGleb Smirnoff ;
47463b3a8eb9SGleb Smirnoff
47473b3a8eb9SGleb Smirnoff nataction : no NAT natpasslog {
47483b3a8eb9SGleb Smirnoff if ($1 && $3.b1) {
47493b3a8eb9SGleb Smirnoff yyerror("\"pass\" not valid with \"no\"");
47503b3a8eb9SGleb Smirnoff YYERROR;
47513b3a8eb9SGleb Smirnoff }
47523b3a8eb9SGleb Smirnoff if ($1)
47533b3a8eb9SGleb Smirnoff $$.b1 = PF_NONAT;
47543b3a8eb9SGleb Smirnoff else
47553b3a8eb9SGleb Smirnoff $$.b1 = PF_NAT;
47563b3a8eb9SGleb Smirnoff $$.b2 = $3.b1;
47573b3a8eb9SGleb Smirnoff $$.w = $3.b2;
47583b3a8eb9SGleb Smirnoff $$.w2 = $3.w2;
47593b3a8eb9SGleb Smirnoff }
47603b3a8eb9SGleb Smirnoff | no RDR natpasslog {
47613b3a8eb9SGleb Smirnoff if ($1 && $3.b1) {
47623b3a8eb9SGleb Smirnoff yyerror("\"pass\" not valid with \"no\"");
47633b3a8eb9SGleb Smirnoff YYERROR;
47643b3a8eb9SGleb Smirnoff }
47653b3a8eb9SGleb Smirnoff if ($1)
47663b3a8eb9SGleb Smirnoff $$.b1 = PF_NORDR;
47673b3a8eb9SGleb Smirnoff else
47683b3a8eb9SGleb Smirnoff $$.b1 = PF_RDR;
47693b3a8eb9SGleb Smirnoff $$.b2 = $3.b1;
47703b3a8eb9SGleb Smirnoff $$.w = $3.b2;
47713b3a8eb9SGleb Smirnoff $$.w2 = $3.w2;
47723b3a8eb9SGleb Smirnoff }
47733b3a8eb9SGleb Smirnoff ;
47743b3a8eb9SGleb Smirnoff
47753b3a8eb9SGleb Smirnoff natrule : nataction interface af proto fromto tag tagged rtable
4776*aeddee83SKajetan Staszkiewicz nat_redirspec
47773b3a8eb9SGleb Smirnoff {
4778e9eb0941SKristof Provost struct pfctl_rule r;
4779fc6e5069SKristof Provost struct node_state_opt *o;
47803b3a8eb9SGleb Smirnoff
47813b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_NAT))
47823b3a8eb9SGleb Smirnoff YYERROR;
47833b3a8eb9SGleb Smirnoff
4784*aeddee83SKajetan Staszkiewicz pfctl_init_rule(&r);
47853b3a8eb9SGleb Smirnoff
47863b3a8eb9SGleb Smirnoff r.action = $1.b1;
47873b3a8eb9SGleb Smirnoff r.natpass = $1.b2;
47883b3a8eb9SGleb Smirnoff r.log = $1.w;
47893b3a8eb9SGleb Smirnoff r.logif = $1.w2;
47903b3a8eb9SGleb Smirnoff r.af = $3;
47913b3a8eb9SGleb Smirnoff
47923b3a8eb9SGleb Smirnoff if (!r.af) {
47933b3a8eb9SGleb Smirnoff if ($5.src.host && $5.src.host->af &&
47943b3a8eb9SGleb Smirnoff !$5.src.host->ifindex)
47953b3a8eb9SGleb Smirnoff r.af = $5.src.host->af;
47963b3a8eb9SGleb Smirnoff else if ($5.dst.host && $5.dst.host->af &&
47973b3a8eb9SGleb Smirnoff !$5.dst.host->ifindex)
47983b3a8eb9SGleb Smirnoff r.af = $5.dst.host->af;
47993b3a8eb9SGleb Smirnoff }
48003b3a8eb9SGleb Smirnoff
48013b3a8eb9SGleb Smirnoff if ($6 != NULL)
48023b3a8eb9SGleb Smirnoff if (strlcpy(r.tagname, $6, PF_TAG_NAME_SIZE) >=
48033b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) {
48043b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars",
48053b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1);
48063b3a8eb9SGleb Smirnoff YYERROR;
48073b3a8eb9SGleb Smirnoff }
48083b3a8eb9SGleb Smirnoff
48093b3a8eb9SGleb Smirnoff if ($7.name)
48103b3a8eb9SGleb Smirnoff if (strlcpy(r.match_tagname, $7.name,
48113b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
48123b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars",
48133b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1);
48143b3a8eb9SGleb Smirnoff YYERROR;
48153b3a8eb9SGleb Smirnoff }
48163b3a8eb9SGleb Smirnoff r.match_tag_not = $7.neg;
48173b3a8eb9SGleb Smirnoff r.rtableid = $8;
48183b3a8eb9SGleb Smirnoff
48193b3a8eb9SGleb Smirnoff if (r.action == PF_NONAT || r.action == PF_NORDR) {
48203b3a8eb9SGleb Smirnoff if ($9 != NULL) {
48213b3a8eb9SGleb Smirnoff yyerror("translation rule with 'no' "
48223b3a8eb9SGleb Smirnoff "does not need '->'");
48233b3a8eb9SGleb Smirnoff YYERROR;
48243b3a8eb9SGleb Smirnoff }
48253b3a8eb9SGleb Smirnoff } else {
48263b3a8eb9SGleb Smirnoff if ($9 == NULL || $9->host == NULL) {
48273b3a8eb9SGleb Smirnoff yyerror("translation rule requires '-> "
48283b3a8eb9SGleb Smirnoff "address'");
48293b3a8eb9SGleb Smirnoff YYERROR;
48303b3a8eb9SGleb Smirnoff }
48313b3a8eb9SGleb Smirnoff if (!r.af && ! $9->host->ifindex)
48323b3a8eb9SGleb Smirnoff r.af = $9->host->af;
48333b3a8eb9SGleb Smirnoff
48343b3a8eb9SGleb Smirnoff remove_invalid_hosts(&$9->host, &r.af);
48353b3a8eb9SGleb Smirnoff if (invalid_redirect($9->host, r.af))
48363b3a8eb9SGleb Smirnoff YYERROR;
48377ce98cf2SKristof Provost if ($9->host->addr.type == PF_ADDR_DYNIFTL) {
48387ce98cf2SKristof Provost if (($9->host = gen_dynnode($9->host, r.af)) == NULL)
48397ce98cf2SKristof Provost err(1, "calloc");
48407ce98cf2SKristof Provost }
48413b3a8eb9SGleb Smirnoff if (check_netmask($9->host, r.af))
48423b3a8eb9SGleb Smirnoff YYERROR;
48432aa21096SKurosawa Takahiro }
48442aa21096SKurosawa Takahiro
4845fc6e5069SKristof Provost o = keep_state_defaults;
4846fc6e5069SKristof Provost while (o) {
4847fc6e5069SKristof Provost switch (o->type) {
4848fc6e5069SKristof Provost case PF_STATE_OPT_PFLOW:
4849fc6e5069SKristof Provost if (r.rule_flag & PFRULE_PFLOW) {
4850fc6e5069SKristof Provost yyerror("state pflow option: "
4851fc6e5069SKristof Provost "multiple definitions");
4852fc6e5069SKristof Provost YYERROR;
4853fc6e5069SKristof Provost }
4854fc6e5069SKristof Provost r.rule_flag |= PFRULE_PFLOW;
4855fc6e5069SKristof Provost break;
4856fc6e5069SKristof Provost }
4857fc6e5069SKristof Provost o = o->next;
4858fc6e5069SKristof Provost }
4859fc6e5069SKristof Provost
4860*aeddee83SKajetan Staszkiewicz expand_rule(&r, $2, NULL, $9, NULL, $4,
48610972294eSKristof Provost $5.src_os, $5.src.host, $5.src.port, $5.dst.host,
48622339ead6SKristof Provost $5.dst.port, 0, 0, 0, 0, "");
48633b3a8eb9SGleb Smirnoff }
48643b3a8eb9SGleb Smirnoff ;
48653b3a8eb9SGleb Smirnoff
48661e93588bSLuiz Otavio O Souza binatrule : no BINAT natpasslog interface af proto FROM ipspec toipspec tag
4867*aeddee83SKajetan Staszkiewicz tagged rtable binat_redirspec
48683b3a8eb9SGleb Smirnoff {
4869e9eb0941SKristof Provost struct pfctl_rule binat;
48703b3a8eb9SGleb Smirnoff struct pf_pooladdr *pa;
48713b3a8eb9SGleb Smirnoff
48723b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_NAT))
48733b3a8eb9SGleb Smirnoff YYERROR;
48743b3a8eb9SGleb Smirnoff if (disallow_urpf_failed($9, "\"urpf-failed\" is not "
48753b3a8eb9SGleb Smirnoff "permitted as a binat destination"))
48763b3a8eb9SGleb Smirnoff YYERROR;
48773b3a8eb9SGleb Smirnoff
4878*aeddee83SKajetan Staszkiewicz pfctl_init_rule(&binat);
48793b3a8eb9SGleb Smirnoff
48803b3a8eb9SGleb Smirnoff if ($1 && $3.b1) {
48813b3a8eb9SGleb Smirnoff yyerror("\"pass\" not valid with \"no\"");
48823b3a8eb9SGleb Smirnoff YYERROR;
48833b3a8eb9SGleb Smirnoff }
48843b3a8eb9SGleb Smirnoff if ($1)
48853b3a8eb9SGleb Smirnoff binat.action = PF_NOBINAT;
48863b3a8eb9SGleb Smirnoff else
48873b3a8eb9SGleb Smirnoff binat.action = PF_BINAT;
48883b3a8eb9SGleb Smirnoff binat.natpass = $3.b1;
48893b3a8eb9SGleb Smirnoff binat.log = $3.b2;
48903b3a8eb9SGleb Smirnoff binat.logif = $3.w2;
48913b3a8eb9SGleb Smirnoff binat.af = $5;
48923b3a8eb9SGleb Smirnoff if (!binat.af && $8 != NULL && $8->af)
48933b3a8eb9SGleb Smirnoff binat.af = $8->af;
48943b3a8eb9SGleb Smirnoff if (!binat.af && $9 != NULL && $9->af)
48953b3a8eb9SGleb Smirnoff binat.af = $9->af;
48963b3a8eb9SGleb Smirnoff
48973b3a8eb9SGleb Smirnoff if (!binat.af && $13 != NULL && $13->host)
48983b3a8eb9SGleb Smirnoff binat.af = $13->host->af;
48993b3a8eb9SGleb Smirnoff if (!binat.af) {
49003b3a8eb9SGleb Smirnoff yyerror("address family (inet/inet6) "
49013b3a8eb9SGleb Smirnoff "undefined");
49023b3a8eb9SGleb Smirnoff YYERROR;
49033b3a8eb9SGleb Smirnoff }
49043b3a8eb9SGleb Smirnoff
49053b3a8eb9SGleb Smirnoff if ($4 != NULL) {
49063b3a8eb9SGleb Smirnoff memcpy(binat.ifname, $4->ifname,
49073b3a8eb9SGleb Smirnoff sizeof(binat.ifname));
49083b3a8eb9SGleb Smirnoff binat.ifnot = $4->not;
49093b3a8eb9SGleb Smirnoff free($4);
49103b3a8eb9SGleb Smirnoff }
49113b3a8eb9SGleb Smirnoff
49123b3a8eb9SGleb Smirnoff if ($10 != NULL)
49133b3a8eb9SGleb Smirnoff if (strlcpy(binat.tagname, $10,
49143b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
49153b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars",
49163b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1);
49173b3a8eb9SGleb Smirnoff YYERROR;
49183b3a8eb9SGleb Smirnoff }
49193b3a8eb9SGleb Smirnoff if ($11.name)
49203b3a8eb9SGleb Smirnoff if (strlcpy(binat.match_tagname, $11.name,
49213b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) {
49223b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars",
49233b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1);
49243b3a8eb9SGleb Smirnoff YYERROR;
49253b3a8eb9SGleb Smirnoff }
49263b3a8eb9SGleb Smirnoff binat.match_tag_not = $11.neg;
49273b3a8eb9SGleb Smirnoff binat.rtableid = $12;
49283b3a8eb9SGleb Smirnoff
49293b3a8eb9SGleb Smirnoff if ($6 != NULL) {
49303b3a8eb9SGleb Smirnoff binat.proto = $6->proto;
49313b3a8eb9SGleb Smirnoff free($6);
49323b3a8eb9SGleb Smirnoff }
49333b3a8eb9SGleb Smirnoff
49343b3a8eb9SGleb Smirnoff if ($8 != NULL && disallow_table($8, "invalid use of "
49353b3a8eb9SGleb Smirnoff "table <%s> as the source address of a binat rule"))
49363b3a8eb9SGleb Smirnoff YYERROR;
49373b3a8eb9SGleb Smirnoff if ($8 != NULL && disallow_alias($8, "invalid use of "
49383b3a8eb9SGleb Smirnoff "interface (%s) as the source address of a binat "
49393b3a8eb9SGleb Smirnoff "rule"))
49403b3a8eb9SGleb Smirnoff YYERROR;
49413b3a8eb9SGleb Smirnoff if ($13 != NULL && $13->host != NULL && disallow_table(
49423b3a8eb9SGleb Smirnoff $13->host, "invalid use of table <%s> as the "
49433b3a8eb9SGleb Smirnoff "redirect address of a binat rule"))
49443b3a8eb9SGleb Smirnoff YYERROR;
49453b3a8eb9SGleb Smirnoff if ($13 != NULL && $13->host != NULL && disallow_alias(
49463b3a8eb9SGleb Smirnoff $13->host, "invalid use of interface (%s) as the "
49473b3a8eb9SGleb Smirnoff "redirect address of a binat rule"))
49483b3a8eb9SGleb Smirnoff YYERROR;
49493b3a8eb9SGleb Smirnoff
49503b3a8eb9SGleb Smirnoff if ($8 != NULL) {
49513b3a8eb9SGleb Smirnoff if ($8->next) {
49523b3a8eb9SGleb Smirnoff yyerror("multiple binat ip addresses");
49533b3a8eb9SGleb Smirnoff YYERROR;
49543b3a8eb9SGleb Smirnoff }
49553b3a8eb9SGleb Smirnoff if ($8->addr.type == PF_ADDR_DYNIFTL)
49563b3a8eb9SGleb Smirnoff $8->af = binat.af;
49573b3a8eb9SGleb Smirnoff if ($8->af != binat.af) {
49583b3a8eb9SGleb Smirnoff yyerror("binat ip versions must match");
49593b3a8eb9SGleb Smirnoff YYERROR;
49603b3a8eb9SGleb Smirnoff }
49617ce98cf2SKristof Provost if ($8->addr.type == PF_ADDR_DYNIFTL) {
49627ce98cf2SKristof Provost if (($8 = gen_dynnode($8, binat.af)) == NULL)
49637ce98cf2SKristof Provost err(1, "calloc");
49647ce98cf2SKristof Provost }
49653b3a8eb9SGleb Smirnoff if (check_netmask($8, binat.af))
49663b3a8eb9SGleb Smirnoff YYERROR;
49673b3a8eb9SGleb Smirnoff memcpy(&binat.src.addr, &$8->addr,
49683b3a8eb9SGleb Smirnoff sizeof(binat.src.addr));
49693b3a8eb9SGleb Smirnoff free($8);
49703b3a8eb9SGleb Smirnoff }
49713b3a8eb9SGleb Smirnoff if ($9 != NULL) {
49723b3a8eb9SGleb Smirnoff if ($9->next) {
49733b3a8eb9SGleb Smirnoff yyerror("multiple binat ip addresses");
49743b3a8eb9SGleb Smirnoff YYERROR;
49753b3a8eb9SGleb Smirnoff }
49763b3a8eb9SGleb Smirnoff if ($9->af != binat.af && $9->af) {
49773b3a8eb9SGleb Smirnoff yyerror("binat ip versions must match");
49783b3a8eb9SGleb Smirnoff YYERROR;
49793b3a8eb9SGleb Smirnoff }
49807ce98cf2SKristof Provost if ($9->addr.type == PF_ADDR_DYNIFTL) {
49817ce98cf2SKristof Provost if (($9 = gen_dynnode($9, binat.af)) == NULL)
49827ce98cf2SKristof Provost err(1, "calloc");
49837ce98cf2SKristof Provost }
49843b3a8eb9SGleb Smirnoff if (check_netmask($9, binat.af))
49853b3a8eb9SGleb Smirnoff YYERROR;
49863b3a8eb9SGleb Smirnoff memcpy(&binat.dst.addr, &$9->addr,
49873b3a8eb9SGleb Smirnoff sizeof(binat.dst.addr));
49883b3a8eb9SGleb Smirnoff binat.dst.neg = $9->not;
49893b3a8eb9SGleb Smirnoff free($9);
49903b3a8eb9SGleb Smirnoff }
49913b3a8eb9SGleb Smirnoff
49923b3a8eb9SGleb Smirnoff if (binat.action == PF_NOBINAT) {
49933b3a8eb9SGleb Smirnoff if ($13 != NULL) {
49943b3a8eb9SGleb Smirnoff yyerror("'no binat' rule does not need"
49953b3a8eb9SGleb Smirnoff " '->'");
49963b3a8eb9SGleb Smirnoff YYERROR;
49973b3a8eb9SGleb Smirnoff }
49983b3a8eb9SGleb Smirnoff } else {
49993b3a8eb9SGleb Smirnoff if ($13 == NULL || $13->host == NULL) {
50003b3a8eb9SGleb Smirnoff yyerror("'binat' rule requires"
50013b3a8eb9SGleb Smirnoff " '-> address'");
50023b3a8eb9SGleb Smirnoff YYERROR;
50033b3a8eb9SGleb Smirnoff }
50043b3a8eb9SGleb Smirnoff
50053b3a8eb9SGleb Smirnoff remove_invalid_hosts(&$13->host, &binat.af);
50063b3a8eb9SGleb Smirnoff if (invalid_redirect($13->host, binat.af))
50073b3a8eb9SGleb Smirnoff YYERROR;
50083b3a8eb9SGleb Smirnoff if ($13->host->next != NULL) {
50093b3a8eb9SGleb Smirnoff yyerror("binat rule must redirect to "
50103b3a8eb9SGleb Smirnoff "a single address");
50113b3a8eb9SGleb Smirnoff YYERROR;
50123b3a8eb9SGleb Smirnoff }
50137ce98cf2SKristof Provost if ($13->host->addr.type == PF_ADDR_DYNIFTL) {
50147ce98cf2SKristof Provost if (($13->host = gen_dynnode($13->host, binat.af)) == NULL)
50157ce98cf2SKristof Provost err(1, "calloc");
50167ce98cf2SKristof Provost }
50173b3a8eb9SGleb Smirnoff if (check_netmask($13->host, binat.af))
50183b3a8eb9SGleb Smirnoff YYERROR;
50193b3a8eb9SGleb Smirnoff
50203b3a8eb9SGleb Smirnoff if (!PF_AZERO(&binat.src.addr.v.a.mask,
50213b3a8eb9SGleb Smirnoff binat.af) &&
50223b3a8eb9SGleb Smirnoff !PF_AEQ(&binat.src.addr.v.a.mask,
50233b3a8eb9SGleb Smirnoff &$13->host->addr.v.a.mask, binat.af)) {
50243b3a8eb9SGleb Smirnoff yyerror("'binat' source mask and "
50253b3a8eb9SGleb Smirnoff "redirect mask must be the same");
50263b3a8eb9SGleb Smirnoff YYERROR;
50273b3a8eb9SGleb Smirnoff }
50283b3a8eb9SGleb Smirnoff
5029096efeb6SKristof Provost TAILQ_INIT(&binat.rdr.list);
50305cb08fddSKristof Provost TAILQ_INIT(&binat.nat.list);
50313b3a8eb9SGleb Smirnoff pa = calloc(1, sizeof(struct pf_pooladdr));
50323b3a8eb9SGleb Smirnoff if (pa == NULL)
50333b3a8eb9SGleb Smirnoff err(1, "binat: calloc");
50343b3a8eb9SGleb Smirnoff pa->addr = $13->host->addr;
50353b3a8eb9SGleb Smirnoff pa->ifname[0] = 0;
5036096efeb6SKristof Provost TAILQ_INSERT_TAIL(&binat.rdr.list,
50373b3a8eb9SGleb Smirnoff pa, entries);
50383b3a8eb9SGleb Smirnoff
50393b3a8eb9SGleb Smirnoff free($13);
50403b3a8eb9SGleb Smirnoff }
50413b3a8eb9SGleb Smirnoff
50420d71f9f3SKristof Provost pfctl_append_rule(pf, &binat, "");
50433b3a8eb9SGleb Smirnoff }
50443b3a8eb9SGleb Smirnoff ;
50453b3a8eb9SGleb Smirnoff
50463b3a8eb9SGleb Smirnoff tag : /* empty */ { $$ = NULL; }
50473b3a8eb9SGleb Smirnoff | TAG STRING { $$ = $2; }
50483b3a8eb9SGleb Smirnoff ;
50493b3a8eb9SGleb Smirnoff
50503b3a8eb9SGleb Smirnoff tagged : /* empty */ { $$.neg = 0; $$.name = NULL; }
50513b3a8eb9SGleb Smirnoff | not TAGGED string { $$.neg = $1; $$.name = $3; }
50523b3a8eb9SGleb Smirnoff ;
50533b3a8eb9SGleb Smirnoff
50543b3a8eb9SGleb Smirnoff rtable : /* empty */ { $$ = -1; }
50553b3a8eb9SGleb Smirnoff | RTABLE NUMBER {
50563b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > rt_tableid_max()) {
50573b3a8eb9SGleb Smirnoff yyerror("invalid rtable id");
50583b3a8eb9SGleb Smirnoff YYERROR;
50593b3a8eb9SGleb Smirnoff }
50603b3a8eb9SGleb Smirnoff $$ = $2;
50613b3a8eb9SGleb Smirnoff }
50623b3a8eb9SGleb Smirnoff ;
50633b3a8eb9SGleb Smirnoff
50643b3a8eb9SGleb Smirnoff route_host : STRING {
50653b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_host));
50663b3a8eb9SGleb Smirnoff if ($$ == NULL)
50673b3a8eb9SGleb Smirnoff err(1, "route_host: calloc");
5068e68de669SKristof Provost if (strlen($1) >= IFNAMSIZ) {
5069e68de669SKristof Provost yyerror("interface name too long");
5070e68de669SKristof Provost YYERROR;
5071e68de669SKristof Provost }
5072a2a90d6eSKristof Provost $$->ifname = strdup($1);
50733b3a8eb9SGleb Smirnoff set_ipmask($$, 128);
50743b3a8eb9SGleb Smirnoff $$->next = NULL;
50753b3a8eb9SGleb Smirnoff $$->tail = $$;
50763b3a8eb9SGleb Smirnoff }
50773b3a8eb9SGleb Smirnoff | '(' STRING host ')' {
507858c8430aSKristof Provost struct node_host *n;
507958c8430aSKristof Provost
50803b3a8eb9SGleb Smirnoff $$ = $3;
5081e68de669SKristof Provost for (n = $3; n != NULL; n = n->next) {
5082e68de669SKristof Provost if (strlen($2) >= IFNAMSIZ) {
5083e68de669SKristof Provost yyerror("interface name too long");
5084e68de669SKristof Provost YYERROR;
5085e68de669SKristof Provost }
5086a2a90d6eSKristof Provost n->ifname = strdup($2);
50873b3a8eb9SGleb Smirnoff }
5088e68de669SKristof Provost }
50893b3a8eb9SGleb Smirnoff ;
50903b3a8eb9SGleb Smirnoff
50913b3a8eb9SGleb Smirnoff route_host_list : route_host optnl { $$ = $1; }
50923b3a8eb9SGleb Smirnoff | route_host_list comma route_host optnl {
50933b3a8eb9SGleb Smirnoff if ($1->af == 0)
50943b3a8eb9SGleb Smirnoff $1->af = $3->af;
50953b3a8eb9SGleb Smirnoff if ($1->af != $3->af) {
50963b3a8eb9SGleb Smirnoff yyerror("all pool addresses must be in the "
50973b3a8eb9SGleb Smirnoff "same address family");
50983b3a8eb9SGleb Smirnoff YYERROR;
50993b3a8eb9SGleb Smirnoff }
51003b3a8eb9SGleb Smirnoff $1->tail->next = $3;
51013b3a8eb9SGleb Smirnoff $1->tail = $3->tail;
51023b3a8eb9SGleb Smirnoff $$ = $1;
51033b3a8eb9SGleb Smirnoff }
51043b3a8eb9SGleb Smirnoff ;
51053b3a8eb9SGleb Smirnoff
51063b3a8eb9SGleb Smirnoff routespec : route_host { $$ = $1; }
51073b3a8eb9SGleb Smirnoff | '{' optnl route_host_list '}' { $$ = $3; }
51083b3a8eb9SGleb Smirnoff ;
51093b3a8eb9SGleb Smirnoff
51103b3a8eb9SGleb Smirnoff route : /* empty */ {
5111*aeddee83SKajetan Staszkiewicz $$.rt = PF_NOPFROUTE;
51123b3a8eb9SGleb Smirnoff }
51133b3a8eb9SGleb Smirnoff | FASTROUTE {
5114813196a1SKristof Provost /* backwards-compat */
5115*aeddee83SKajetan Staszkiewicz $$.rt = PF_NOPFROUTE;
51163b3a8eb9SGleb Smirnoff }
5117*aeddee83SKajetan Staszkiewicz | ROUTETO route_redirspec {
51183b3a8eb9SGleb Smirnoff $$.rt = PF_ROUTETO;
5119*aeddee83SKajetan Staszkiewicz $$.redirspec = $2;
51203b3a8eb9SGleb Smirnoff }
5121*aeddee83SKajetan Staszkiewicz | REPLYTO route_redirspec {
51223b3a8eb9SGleb Smirnoff $$.rt = PF_REPLYTO;
5123*aeddee83SKajetan Staszkiewicz $$.redirspec = $2;
51243b3a8eb9SGleb Smirnoff }
5125*aeddee83SKajetan Staszkiewicz | DUPTO route_redirspec {
51263b3a8eb9SGleb Smirnoff $$.rt = PF_DUPTO;
5127*aeddee83SKajetan Staszkiewicz $$.redirspec = $2;
51283b3a8eb9SGleb Smirnoff }
51293b3a8eb9SGleb Smirnoff ;
51303b3a8eb9SGleb Smirnoff
51313b3a8eb9SGleb Smirnoff timeout_spec : STRING NUMBER
51323b3a8eb9SGleb Smirnoff {
51333b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION)) {
51343b3a8eb9SGleb Smirnoff free($1);
51353b3a8eb9SGleb Smirnoff YYERROR;
51363b3a8eb9SGleb Smirnoff }
51373b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX) {
51383b3a8eb9SGleb Smirnoff yyerror("only positive values permitted");
51393b3a8eb9SGleb Smirnoff YYERROR;
51403b3a8eb9SGleb Smirnoff }
514130bad751SKristof Provost if (pfctl_apply_timeout(pf, $1, $2, 0) != 0) {
51423b3a8eb9SGleb Smirnoff yyerror("unknown timeout %s", $1);
51433b3a8eb9SGleb Smirnoff free($1);
51443b3a8eb9SGleb Smirnoff YYERROR;
51453b3a8eb9SGleb Smirnoff }
51463b3a8eb9SGleb Smirnoff free($1);
51473b3a8eb9SGleb Smirnoff }
51487f8af000SLuiz Otavio O Souza | INTERVAL NUMBER {
51497f8af000SLuiz Otavio O Souza if (check_rulestate(PFCTL_STATE_OPTION))
51507f8af000SLuiz Otavio O Souza YYERROR;
51517f8af000SLuiz Otavio O Souza if ($2 < 0 || $2 > UINT_MAX) {
51527f8af000SLuiz Otavio O Souza yyerror("only positive values permitted");
51537f8af000SLuiz Otavio O Souza YYERROR;
51547f8af000SLuiz Otavio O Souza }
515530bad751SKristof Provost if (pfctl_apply_timeout(pf, "interval", $2, 0) != 0)
51567f8af000SLuiz Otavio O Souza YYERROR;
51577f8af000SLuiz Otavio O Souza }
51583b3a8eb9SGleb Smirnoff ;
51593b3a8eb9SGleb Smirnoff
51603b3a8eb9SGleb Smirnoff timeout_list : timeout_list comma timeout_spec optnl
51613b3a8eb9SGleb Smirnoff | timeout_spec optnl
51623b3a8eb9SGleb Smirnoff ;
51633b3a8eb9SGleb Smirnoff
51643b3a8eb9SGleb Smirnoff limit_spec : STRING NUMBER
51653b3a8eb9SGleb Smirnoff {
51663b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION)) {
51673b3a8eb9SGleb Smirnoff free($1);
51683b3a8eb9SGleb Smirnoff YYERROR;
51693b3a8eb9SGleb Smirnoff }
51703b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX) {
51713b3a8eb9SGleb Smirnoff yyerror("only positive values permitted");
51723b3a8eb9SGleb Smirnoff YYERROR;
51733b3a8eb9SGleb Smirnoff }
5174d9ab8999SKristof Provost if (pfctl_apply_limit(pf, $1, $2) != 0) {
51753b3a8eb9SGleb Smirnoff yyerror("unable to set limit %s %u", $1, $2);
51763b3a8eb9SGleb Smirnoff free($1);
51773b3a8eb9SGleb Smirnoff YYERROR;
51783b3a8eb9SGleb Smirnoff }
51793b3a8eb9SGleb Smirnoff free($1);
51803b3a8eb9SGleb Smirnoff }
51813b3a8eb9SGleb Smirnoff ;
51823b3a8eb9SGleb Smirnoff
51833b3a8eb9SGleb Smirnoff limit_list : limit_list comma limit_spec optnl
51843b3a8eb9SGleb Smirnoff | limit_spec optnl
51853b3a8eb9SGleb Smirnoff ;
51863b3a8eb9SGleb Smirnoff
51873b3a8eb9SGleb Smirnoff comma : ','
51883b3a8eb9SGleb Smirnoff | /* empty */
51893b3a8eb9SGleb Smirnoff ;
51903b3a8eb9SGleb Smirnoff
51913b3a8eb9SGleb Smirnoff yesno : NO { $$ = 0; }
51923b3a8eb9SGleb Smirnoff | STRING {
51933b3a8eb9SGleb Smirnoff if (!strcmp($1, "yes"))
51943b3a8eb9SGleb Smirnoff $$ = 1;
51953b3a8eb9SGleb Smirnoff else {
51963b3a8eb9SGleb Smirnoff yyerror("invalid value '%s', expected 'yes' "
51973b3a8eb9SGleb Smirnoff "or 'no'", $1);
51983b3a8eb9SGleb Smirnoff free($1);
51993b3a8eb9SGleb Smirnoff YYERROR;
52003b3a8eb9SGleb Smirnoff }
52013b3a8eb9SGleb Smirnoff free($1);
52023b3a8eb9SGleb Smirnoff }
52033b3a8eb9SGleb Smirnoff ;
52043b3a8eb9SGleb Smirnoff
52053b3a8eb9SGleb Smirnoff unaryop : '=' { $$ = PF_OP_EQ; }
520680eb861dSKristof Provost | NE { $$ = PF_OP_NE; }
520780eb861dSKristof Provost | LE { $$ = PF_OP_LE; }
52083b3a8eb9SGleb Smirnoff | '<' { $$ = PF_OP_LT; }
520980eb861dSKristof Provost | GE { $$ = PF_OP_GE; }
52103b3a8eb9SGleb Smirnoff | '>' { $$ = PF_OP_GT; }
52113b3a8eb9SGleb Smirnoff ;
52123b3a8eb9SGleb Smirnoff
52133b3a8eb9SGleb Smirnoff %%
52143b3a8eb9SGleb Smirnoff
52153b3a8eb9SGleb Smirnoff int
52163b3a8eb9SGleb Smirnoff yyerror(const char *fmt, ...)
52173b3a8eb9SGleb Smirnoff {
52183b3a8eb9SGleb Smirnoff va_list ap;
52193b3a8eb9SGleb Smirnoff
52203b3a8eb9SGleb Smirnoff file->errors++;
52213b3a8eb9SGleb Smirnoff va_start(ap, fmt);
52223b3a8eb9SGleb Smirnoff fprintf(stderr, "%s:%d: ", file->name, yylval.lineno);
52233b3a8eb9SGleb Smirnoff vfprintf(stderr, fmt, ap);
52243b3a8eb9SGleb Smirnoff fprintf(stderr, "\n");
52253b3a8eb9SGleb Smirnoff va_end(ap);
52263b3a8eb9SGleb Smirnoff return (0);
52273b3a8eb9SGleb Smirnoff }
52283b3a8eb9SGleb Smirnoff
52293b3a8eb9SGleb Smirnoff int
disallow_table(struct node_host * h,const char * fmt)52303b3a8eb9SGleb Smirnoff disallow_table(struct node_host *h, const char *fmt)
52313b3a8eb9SGleb Smirnoff {
52323b3a8eb9SGleb Smirnoff for (; h != NULL; h = h->next)
52333b3a8eb9SGleb Smirnoff if (h->addr.type == PF_ADDR_TABLE) {
52343b3a8eb9SGleb Smirnoff yyerror(fmt, h->addr.v.tblname);
52353b3a8eb9SGleb Smirnoff return (1);
52363b3a8eb9SGleb Smirnoff }
52373b3a8eb9SGleb Smirnoff return (0);
52383b3a8eb9SGleb Smirnoff }
52393b3a8eb9SGleb Smirnoff
52403b3a8eb9SGleb Smirnoff int
disallow_urpf_failed(struct node_host * h,const char * fmt)52413b3a8eb9SGleb Smirnoff disallow_urpf_failed(struct node_host *h, const char *fmt)
52423b3a8eb9SGleb Smirnoff {
52433b3a8eb9SGleb Smirnoff for (; h != NULL; h = h->next)
52443b3a8eb9SGleb Smirnoff if (h->addr.type == PF_ADDR_URPFFAILED) {
52453b3a8eb9SGleb Smirnoff yyerror(fmt);
52463b3a8eb9SGleb Smirnoff return (1);
52473b3a8eb9SGleb Smirnoff }
52483b3a8eb9SGleb Smirnoff return (0);
52493b3a8eb9SGleb Smirnoff }
52503b3a8eb9SGleb Smirnoff
52513b3a8eb9SGleb Smirnoff int
disallow_alias(struct node_host * h,const char * fmt)52523b3a8eb9SGleb Smirnoff disallow_alias(struct node_host *h, const char *fmt)
52533b3a8eb9SGleb Smirnoff {
52543b3a8eb9SGleb Smirnoff for (; h != NULL; h = h->next)
52553b3a8eb9SGleb Smirnoff if (DYNIF_MULTIADDR(h->addr)) {
52563b3a8eb9SGleb Smirnoff yyerror(fmt, h->addr.v.tblname);
52573b3a8eb9SGleb Smirnoff return (1);
52583b3a8eb9SGleb Smirnoff }
52593b3a8eb9SGleb Smirnoff return (0);
52603b3a8eb9SGleb Smirnoff }
52613b3a8eb9SGleb Smirnoff
52623b3a8eb9SGleb Smirnoff int
rule_consistent(struct pfctl_rule * r,int anchor_call)5263e9eb0941SKristof Provost rule_consistent(struct pfctl_rule *r, int anchor_call)
52643b3a8eb9SGleb Smirnoff {
52653b3a8eb9SGleb Smirnoff int problems = 0;
52663b3a8eb9SGleb Smirnoff
52673b3a8eb9SGleb Smirnoff switch (r->action) {
52683b3a8eb9SGleb Smirnoff case PF_PASS:
526939282ef3SKajetan Staszkiewicz case PF_MATCH:
52703b3a8eb9SGleb Smirnoff case PF_DROP:
52713b3a8eb9SGleb Smirnoff case PF_SCRUB:
52723b3a8eb9SGleb Smirnoff case PF_NOSCRUB:
52733b3a8eb9SGleb Smirnoff problems = filter_consistent(r, anchor_call);
52743b3a8eb9SGleb Smirnoff break;
52753b3a8eb9SGleb Smirnoff case PF_NAT:
52763b3a8eb9SGleb Smirnoff case PF_NONAT:
52773b3a8eb9SGleb Smirnoff problems = nat_consistent(r);
52783b3a8eb9SGleb Smirnoff break;
52793b3a8eb9SGleb Smirnoff case PF_RDR:
52803b3a8eb9SGleb Smirnoff case PF_NORDR:
52813b3a8eb9SGleb Smirnoff problems = rdr_consistent(r);
52823b3a8eb9SGleb Smirnoff break;
52833b3a8eb9SGleb Smirnoff case PF_BINAT:
52843b3a8eb9SGleb Smirnoff case PF_NOBINAT:
52853b3a8eb9SGleb Smirnoff default:
52863b3a8eb9SGleb Smirnoff break;
52873b3a8eb9SGleb Smirnoff }
52883b3a8eb9SGleb Smirnoff return (problems);
52893b3a8eb9SGleb Smirnoff }
52903b3a8eb9SGleb Smirnoff
52913b3a8eb9SGleb Smirnoff int
filter_consistent(struct pfctl_rule * r,int anchor_call)5292e9eb0941SKristof Provost filter_consistent(struct pfctl_rule *r, int anchor_call)
52933b3a8eb9SGleb Smirnoff {
52943b3a8eb9SGleb Smirnoff int problems = 0;
52953b3a8eb9SGleb Smirnoff
52963b3a8eb9SGleb Smirnoff if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
52970bd4a683SKristof Provost r->proto != IPPROTO_SCTP &&
52983b3a8eb9SGleb Smirnoff (r->src.port_op || r->dst.port_op)) {
52990bd4a683SKristof Provost yyerror("port only applies to tcp/udp/sctp");
53003b3a8eb9SGleb Smirnoff problems++;
53013b3a8eb9SGleb Smirnoff }
53023b3a8eb9SGleb Smirnoff if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 &&
53033b3a8eb9SGleb Smirnoff (r->type || r->code)) {
53043b3a8eb9SGleb Smirnoff yyerror("icmp-type/code only applies to icmp");
53053b3a8eb9SGleb Smirnoff problems++;
53063b3a8eb9SGleb Smirnoff }
53073b3a8eb9SGleb Smirnoff if (!r->af && (r->type || r->code)) {
53083b3a8eb9SGleb Smirnoff yyerror("must indicate address family with icmp-type/code");
53093b3a8eb9SGleb Smirnoff problems++;
53103b3a8eb9SGleb Smirnoff }
5311899e7976SKristof Provost if (r->rule_flag & PFRULE_AFTO && r->af == r->naf) {
5312899e7976SKristof Provost yyerror("must indicate different address family with af-to");
5313899e7976SKristof Provost problems++;
5314899e7976SKristof Provost }
53153b3a8eb9SGleb Smirnoff if (r->overload_tblname[0] &&
53163b3a8eb9SGleb Smirnoff r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) {
53173b3a8eb9SGleb Smirnoff yyerror("'overload' requires 'max-src-conn' "
53183b3a8eb9SGleb Smirnoff "or 'max-src-conn-rate'");
53193b3a8eb9SGleb Smirnoff problems++;
53203b3a8eb9SGleb Smirnoff }
53213b3a8eb9SGleb Smirnoff if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) ||
53223b3a8eb9SGleb Smirnoff (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) {
53233b3a8eb9SGleb Smirnoff yyerror("proto %s doesn't match address family %s",
53243b3a8eb9SGleb Smirnoff r->proto == IPPROTO_ICMP ? "icmp" : "icmp6",
53253b3a8eb9SGleb Smirnoff r->af == AF_INET ? "inet" : "inet6");
53263b3a8eb9SGleb Smirnoff problems++;
53273b3a8eb9SGleb Smirnoff }
53283b3a8eb9SGleb Smirnoff if (r->allow_opts && r->action != PF_PASS) {
53293b3a8eb9SGleb Smirnoff yyerror("allow-opts can only be specified for pass rules");
53303b3a8eb9SGleb Smirnoff problems++;
53313b3a8eb9SGleb Smirnoff }
53323b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op ||
53333b3a8eb9SGleb Smirnoff r->dst.port_op || r->flagset || r->type || r->code)) {
53343b3a8eb9SGleb Smirnoff yyerror("fragments can be filtered only on IP header fields");
53353b3a8eb9SGleb Smirnoff problems++;
53363b3a8eb9SGleb Smirnoff }
53373b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) {
53383b3a8eb9SGleb Smirnoff yyerror("return-rst can only be applied to TCP rules");
53393b3a8eb9SGleb Smirnoff problems++;
53403b3a8eb9SGleb Smirnoff }
53413b3a8eb9SGleb Smirnoff if (r->max_src_nodes && !(r->rule_flag & PFRULE_RULESRCTRACK)) {
53423b3a8eb9SGleb Smirnoff yyerror("max-src-nodes requires 'source-track rule'");
53433b3a8eb9SGleb Smirnoff problems++;
53443b3a8eb9SGleb Smirnoff }
534539282ef3SKajetan Staszkiewicz if (r->action != PF_PASS && r->keep_state) {
534639282ef3SKajetan Staszkiewicz yyerror("keep state is great, but only for pass rules");
53473b3a8eb9SGleb Smirnoff problems++;
53483b3a8eb9SGleb Smirnoff }
53493b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_STATESLOPPY &&
53503b3a8eb9SGleb Smirnoff (r->keep_state == PF_STATE_MODULATE ||
53513b3a8eb9SGleb Smirnoff r->keep_state == PF_STATE_SYNPROXY)) {
53523b3a8eb9SGleb Smirnoff yyerror("sloppy state matching cannot be used with "
53533b3a8eb9SGleb Smirnoff "synproxy state or modulate state");
53543b3a8eb9SGleb Smirnoff problems++;
53553b3a8eb9SGleb Smirnoff }
5356ca0e6934SKristof Provost if (r->rule_flag & PFRULE_AFTO && r->rt) {
53577a372bdeSKristof Provost if (r->rt != PF_ROUTETO && r->rt != PF_REPLYTO) {
53587a372bdeSKristof Provost yyerror("dup-to "
5359ca0e6934SKristof Provost "must not be used on af-to rules");
5360ca0e6934SKristof Provost problems++;
5361ca0e6934SKristof Provost }
5362ca0e6934SKristof Provost }
536339282ef3SKajetan Staszkiewicz /* match rules rules */
536439282ef3SKajetan Staszkiewicz if (r->action == PF_MATCH) {
536539282ef3SKajetan Staszkiewicz if (r->divert.port) {
536639282ef3SKajetan Staszkiewicz yyerror("divert is not supported on match rules");
536739282ef3SKajetan Staszkiewicz problems++;
536839282ef3SKajetan Staszkiewicz }
536939282ef3SKajetan Staszkiewicz if (r->rt) {
537039282ef3SKajetan Staszkiewicz yyerror("route-to, reply-to, dup-to and fastroute "
537139282ef3SKajetan Staszkiewicz "must not be used on match rules");
537239282ef3SKajetan Staszkiewicz problems++;
537339282ef3SKajetan Staszkiewicz }
5374f88019e8SKristof Provost if (r->rule_flag & PFRULE_AFTO) {
5375aa69fdf1SKristof Provost yyerror("af-to is not supported on match rules");
5376aa69fdf1SKristof Provost problems++;
5377aa69fdf1SKristof Provost }
537839282ef3SKajetan Staszkiewicz }
5379096efeb6SKristof Provost if (r->rdr.opts & PF_POOL_STICKYADDR && !r->keep_state) {
5380788f194fSKajetan Staszkiewicz yyerror("'sticky-address' requires 'keep state'");
5381788f194fSKajetan Staszkiewicz problems++;
5382788f194fSKajetan Staszkiewicz }
53833b3a8eb9SGleb Smirnoff return (-problems);
53843b3a8eb9SGleb Smirnoff }
53853b3a8eb9SGleb Smirnoff
53863b3a8eb9SGleb Smirnoff int
nat_consistent(struct pfctl_rule * r)5387e9eb0941SKristof Provost nat_consistent(struct pfctl_rule *r)
53883b3a8eb9SGleb Smirnoff {
53893b3a8eb9SGleb Smirnoff return (0); /* yeah! */
53903b3a8eb9SGleb Smirnoff }
53913b3a8eb9SGleb Smirnoff
53923b3a8eb9SGleb Smirnoff int
rdr_consistent(struct pfctl_rule * r)5393e9eb0941SKristof Provost rdr_consistent(struct pfctl_rule *r)
53943b3a8eb9SGleb Smirnoff {
53953b3a8eb9SGleb Smirnoff int problems = 0;
53963b3a8eb9SGleb Smirnoff
53970bd4a683SKristof Provost if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP &&
53980bd4a683SKristof Provost r->proto != IPPROTO_SCTP) {
53993b3a8eb9SGleb Smirnoff if (r->src.port_op) {
54000bd4a683SKristof Provost yyerror("src port only applies to tcp/udp/sctp");
54013b3a8eb9SGleb Smirnoff problems++;
54023b3a8eb9SGleb Smirnoff }
54033b3a8eb9SGleb Smirnoff if (r->dst.port_op) {
54040bd4a683SKristof Provost yyerror("dst port only applies to tcp/udp/sctp");
54053b3a8eb9SGleb Smirnoff problems++;
54063b3a8eb9SGleb Smirnoff }
5407096efeb6SKristof Provost if (r->rdr.proxy_port[0]) {
5408096efeb6SKristof Provost yyerror("rdr port only applies to tcp/udp/sctp");
54093b3a8eb9SGleb Smirnoff problems++;
54103b3a8eb9SGleb Smirnoff }
54113b3a8eb9SGleb Smirnoff }
54123b3a8eb9SGleb Smirnoff if (r->dst.port_op &&
54133b3a8eb9SGleb Smirnoff r->dst.port_op != PF_OP_EQ && r->dst.port_op != PF_OP_RRG) {
54143b3a8eb9SGleb Smirnoff yyerror("invalid port operator for rdr destination port");
54153b3a8eb9SGleb Smirnoff problems++;
54163b3a8eb9SGleb Smirnoff }
54173b3a8eb9SGleb Smirnoff return (-problems);
54183b3a8eb9SGleb Smirnoff }
54193b3a8eb9SGleb Smirnoff
54203b3a8eb9SGleb Smirnoff int
process_tabledef(char * name,struct table_opts * opts)54213b3a8eb9SGleb Smirnoff process_tabledef(char *name, struct table_opts *opts)
54223b3a8eb9SGleb Smirnoff {
54233b3a8eb9SGleb Smirnoff struct pfr_buffer ab;
54243b3a8eb9SGleb Smirnoff struct node_tinit *ti;
5425542feeffSKristof Provost unsigned long maxcount;
5426542feeffSKristof Provost size_t s = sizeof(maxcount);
54273b3a8eb9SGleb Smirnoff
54283b3a8eb9SGleb Smirnoff bzero(&ab, sizeof(ab));
54293b3a8eb9SGleb Smirnoff ab.pfrb_type = PFRB_ADDRS;
54303b3a8eb9SGleb Smirnoff SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) {
54313b3a8eb9SGleb Smirnoff if (ti->file)
54323b3a8eb9SGleb Smirnoff if (pfr_buf_load(&ab, ti->file, 0, append_addr)) {
54333b3a8eb9SGleb Smirnoff if (errno)
54343b3a8eb9SGleb Smirnoff yyerror("cannot load \"%s\": %s",
54353b3a8eb9SGleb Smirnoff ti->file, strerror(errno));
54363b3a8eb9SGleb Smirnoff else
54373b3a8eb9SGleb Smirnoff yyerror("file \"%s\" contains bad data",
54383b3a8eb9SGleb Smirnoff ti->file);
54393b3a8eb9SGleb Smirnoff goto _error;
54403b3a8eb9SGleb Smirnoff }
54413b3a8eb9SGleb Smirnoff if (ti->host)
54423b3a8eb9SGleb Smirnoff if (append_addr_host(&ab, ti->host, 0, 0)) {
54433b3a8eb9SGleb Smirnoff yyerror("cannot create address buffer: %s",
54443b3a8eb9SGleb Smirnoff strerror(errno));
54453b3a8eb9SGleb Smirnoff goto _error;
54463b3a8eb9SGleb Smirnoff }
54473b3a8eb9SGleb Smirnoff }
54483b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE)
54493b3a8eb9SGleb Smirnoff print_tabledef(name, opts->flags, opts->init_addr,
54503b3a8eb9SGleb Smirnoff &opts->init_nodes);
54513b3a8eb9SGleb Smirnoff if (!(pf->opts & PF_OPT_NOACTION) &&
54523b3a8eb9SGleb Smirnoff pfctl_define_table(name, opts->flags, opts->init_addr,
54533b3a8eb9SGleb Smirnoff pf->anchor->name, &ab, pf->anchor->ruleset.tticket)) {
5454542feeffSKristof Provost
5455542feeffSKristof Provost if (sysctlbyname("net.pf.request_maxcount", &maxcount, &s,
5456542feeffSKristof Provost NULL, 0) == -1)
5457542feeffSKristof Provost maxcount = 65535;
5458542feeffSKristof Provost
5459542feeffSKristof Provost if (ab.pfrb_size > maxcount)
5460542feeffSKristof Provost yyerror("cannot define table %s: too many elements.\n"
5461542feeffSKristof Provost "Consider increasing net.pf.request_maxcount.",
5462542feeffSKristof Provost name);
5463542feeffSKristof Provost else
54643b3a8eb9SGleb Smirnoff yyerror("cannot define table %s: %s", name,
54653b3a8eb9SGleb Smirnoff pfr_strerror(errno));
5466542feeffSKristof Provost
54673b3a8eb9SGleb Smirnoff goto _error;
54683b3a8eb9SGleb Smirnoff }
54693b3a8eb9SGleb Smirnoff pf->tdirty = 1;
54703b3a8eb9SGleb Smirnoff pfr_buf_clear(&ab);
54713b3a8eb9SGleb Smirnoff return (0);
54723b3a8eb9SGleb Smirnoff _error:
54733b3a8eb9SGleb Smirnoff pfr_buf_clear(&ab);
54743b3a8eb9SGleb Smirnoff return (-1);
54753b3a8eb9SGleb Smirnoff }
54763b3a8eb9SGleb Smirnoff
54773b3a8eb9SGleb Smirnoff struct keywords {
54783b3a8eb9SGleb Smirnoff const char *k_name;
54793b3a8eb9SGleb Smirnoff int k_val;
54803b3a8eb9SGleb Smirnoff };
54813b3a8eb9SGleb Smirnoff
54823b3a8eb9SGleb Smirnoff /* macro gore, but you should've seen the prior indentation nightmare... */
54833b3a8eb9SGleb Smirnoff
54843b3a8eb9SGleb Smirnoff #define FREE_LIST(T,r) \
54853b3a8eb9SGleb Smirnoff do { \
54863b3a8eb9SGleb Smirnoff T *p, *node = r; \
54873b3a8eb9SGleb Smirnoff while (node != NULL) { \
54883b3a8eb9SGleb Smirnoff p = node; \
54893b3a8eb9SGleb Smirnoff node = node->next; \
54903b3a8eb9SGleb Smirnoff free(p); \
54913b3a8eb9SGleb Smirnoff } \
54923b3a8eb9SGleb Smirnoff } while (0)
54933b3a8eb9SGleb Smirnoff
54943b3a8eb9SGleb Smirnoff #define LOOP_THROUGH(T,n,r,C) \
54953b3a8eb9SGleb Smirnoff do { \
54963b3a8eb9SGleb Smirnoff T *n; \
54973b3a8eb9SGleb Smirnoff if (r == NULL) { \
54983b3a8eb9SGleb Smirnoff r = calloc(1, sizeof(T)); \
54993b3a8eb9SGleb Smirnoff if (r == NULL) \
55003b3a8eb9SGleb Smirnoff err(1, "LOOP: calloc"); \
55013b3a8eb9SGleb Smirnoff r->next = NULL; \
55023b3a8eb9SGleb Smirnoff } \
55033b3a8eb9SGleb Smirnoff n = r; \
55043b3a8eb9SGleb Smirnoff while (n != NULL) { \
55053b3a8eb9SGleb Smirnoff do { \
55063b3a8eb9SGleb Smirnoff C; \
55073b3a8eb9SGleb Smirnoff } while (0); \
55083b3a8eb9SGleb Smirnoff n = n->next; \
55093b3a8eb9SGleb Smirnoff } \
55103b3a8eb9SGleb Smirnoff } while (0)
55113b3a8eb9SGleb Smirnoff
55123b3a8eb9SGleb Smirnoff void
expand_label_str(char * label,size_t len,const char * srch,const char * repl)55133b3a8eb9SGleb Smirnoff expand_label_str(char *label, size_t len, const char *srch, const char *repl)
55143b3a8eb9SGleb Smirnoff {
55153b3a8eb9SGleb Smirnoff char *tmp;
55163b3a8eb9SGleb Smirnoff char *p, *q;
55173b3a8eb9SGleb Smirnoff
55183b3a8eb9SGleb Smirnoff if ((tmp = calloc(1, len)) == NULL)
55193b3a8eb9SGleb Smirnoff err(1, "expand_label_str: calloc");
55203b3a8eb9SGleb Smirnoff p = q = label;
55213b3a8eb9SGleb Smirnoff while ((q = strstr(p, srch)) != NULL) {
55223b3a8eb9SGleb Smirnoff *q = '\0';
55233b3a8eb9SGleb Smirnoff if ((strlcat(tmp, p, len) >= len) ||
55243b3a8eb9SGleb Smirnoff (strlcat(tmp, repl, len) >= len))
55253b3a8eb9SGleb Smirnoff errx(1, "expand_label: label too long");
55263b3a8eb9SGleb Smirnoff q += strlen(srch);
55273b3a8eb9SGleb Smirnoff p = q;
55283b3a8eb9SGleb Smirnoff }
55293b3a8eb9SGleb Smirnoff if (strlcat(tmp, p, len) >= len)
55303b3a8eb9SGleb Smirnoff errx(1, "expand_label: label too long");
55313b3a8eb9SGleb Smirnoff strlcpy(label, tmp, len); /* always fits */
55323b3a8eb9SGleb Smirnoff free(tmp);
55333b3a8eb9SGleb Smirnoff }
55343b3a8eb9SGleb Smirnoff
55353b3a8eb9SGleb Smirnoff void
expand_label_if(const char * name,char * label,size_t len,const char * ifname)55363b3a8eb9SGleb Smirnoff expand_label_if(const char *name, char *label, size_t len, const char *ifname)
55373b3a8eb9SGleb Smirnoff {
55383b3a8eb9SGleb Smirnoff if (strstr(label, name) != NULL) {
55393b3a8eb9SGleb Smirnoff if (!*ifname)
55403b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, "any");
55413b3a8eb9SGleb Smirnoff else
55423b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, ifname);
55433b3a8eb9SGleb Smirnoff }
55443b3a8eb9SGleb Smirnoff }
55453b3a8eb9SGleb Smirnoff
55463b3a8eb9SGleb Smirnoff void
expand_label_addr(const char * name,char * label,size_t len,sa_family_t af,struct pf_rule_addr * addr)55473b3a8eb9SGleb Smirnoff expand_label_addr(const char *name, char *label, size_t len, sa_family_t af,
554809c7f238SKristof Provost struct pf_rule_addr *addr)
55493b3a8eb9SGleb Smirnoff {
55503b3a8eb9SGleb Smirnoff char tmp[64], tmp_not[66];
55513b3a8eb9SGleb Smirnoff
55523b3a8eb9SGleb Smirnoff if (strstr(label, name) != NULL) {
555309c7f238SKristof Provost switch (addr->addr.type) {
55543b3a8eb9SGleb Smirnoff case PF_ADDR_DYNIFTL:
555509c7f238SKristof Provost snprintf(tmp, sizeof(tmp), "(%s)", addr->addr.v.ifname);
55563b3a8eb9SGleb Smirnoff break;
55573b3a8eb9SGleb Smirnoff case PF_ADDR_TABLE:
555809c7f238SKristof Provost snprintf(tmp, sizeof(tmp), "<%s>", addr->addr.v.tblname);
55593b3a8eb9SGleb Smirnoff break;
55603b3a8eb9SGleb Smirnoff case PF_ADDR_NOROUTE:
55613b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp), "no-route");
55623b3a8eb9SGleb Smirnoff break;
55633b3a8eb9SGleb Smirnoff case PF_ADDR_URPFFAILED:
55643b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp), "urpf-failed");
55653b3a8eb9SGleb Smirnoff break;
55663b3a8eb9SGleb Smirnoff case PF_ADDR_ADDRMASK:
556709c7f238SKristof Provost if (!af || (PF_AZERO(&addr->addr.v.a.addr, af) &&
556809c7f238SKristof Provost PF_AZERO(&addr->addr.v.a.mask, af)))
55693b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp), "any");
55703b3a8eb9SGleb Smirnoff else {
55713b3a8eb9SGleb Smirnoff char a[48];
55723b3a8eb9SGleb Smirnoff int bits;
55733b3a8eb9SGleb Smirnoff
557409c7f238SKristof Provost if (inet_ntop(af, &addr->addr.v.a.addr, a,
55753b3a8eb9SGleb Smirnoff sizeof(a)) == NULL)
55763b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp), "?");
55773b3a8eb9SGleb Smirnoff else {
557809c7f238SKristof Provost bits = unmask(&addr->addr.v.a.mask, af);
55793b3a8eb9SGleb Smirnoff if ((af == AF_INET && bits < 32) ||
55803b3a8eb9SGleb Smirnoff (af == AF_INET6 && bits < 128))
55813b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp),
55823b3a8eb9SGleb Smirnoff "%s/%d", a, bits);
55833b3a8eb9SGleb Smirnoff else
55843b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp),
55853b3a8eb9SGleb Smirnoff "%s", a);
55863b3a8eb9SGleb Smirnoff }
55873b3a8eb9SGleb Smirnoff }
55883b3a8eb9SGleb Smirnoff break;
55893b3a8eb9SGleb Smirnoff default:
55903b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp), "?");
55913b3a8eb9SGleb Smirnoff break;
55923b3a8eb9SGleb Smirnoff }
55933b3a8eb9SGleb Smirnoff
559409c7f238SKristof Provost if (addr->neg) {
55953b3a8eb9SGleb Smirnoff snprintf(tmp_not, sizeof(tmp_not), "! %s", tmp);
55963b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, tmp_not);
55973b3a8eb9SGleb Smirnoff } else
55983b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, tmp);
55993b3a8eb9SGleb Smirnoff }
56003b3a8eb9SGleb Smirnoff }
56013b3a8eb9SGleb Smirnoff
56023b3a8eb9SGleb Smirnoff void
expand_label_port(const char * name,char * label,size_t len,struct pf_rule_addr * addr)56033b3a8eb9SGleb Smirnoff expand_label_port(const char *name, char *label, size_t len,
560409c7f238SKristof Provost struct pf_rule_addr *addr)
56053b3a8eb9SGleb Smirnoff {
56063b3a8eb9SGleb Smirnoff char a1[6], a2[6], op[13] = "";
56073b3a8eb9SGleb Smirnoff
56083b3a8eb9SGleb Smirnoff if (strstr(label, name) != NULL) {
560909c7f238SKristof Provost snprintf(a1, sizeof(a1), "%u", ntohs(addr->port[0]));
561009c7f238SKristof Provost snprintf(a2, sizeof(a2), "%u", ntohs(addr->port[1]));
561109c7f238SKristof Provost if (!addr->port_op)
56123b3a8eb9SGleb Smirnoff ;
561309c7f238SKristof Provost else if (addr->port_op == PF_OP_IRG)
56143b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), "%s><%s", a1, a2);
561509c7f238SKristof Provost else if (addr->port_op == PF_OP_XRG)
56163b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), "%s<>%s", a1, a2);
561709c7f238SKristof Provost else if (addr->port_op == PF_OP_EQ)
56183b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), "%s", a1);
561909c7f238SKristof Provost else if (addr->port_op == PF_OP_NE)
56203b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), "!=%s", a1);
562109c7f238SKristof Provost else if (addr->port_op == PF_OP_LT)
56223b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), "<%s", a1);
562309c7f238SKristof Provost else if (addr->port_op == PF_OP_LE)
56243b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), "<=%s", a1);
562509c7f238SKristof Provost else if (addr->port_op == PF_OP_GT)
56263b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), ">%s", a1);
562709c7f238SKristof Provost else if (addr->port_op == PF_OP_GE)
56283b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), ">=%s", a1);
56293b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, op);
56303b3a8eb9SGleb Smirnoff }
56313b3a8eb9SGleb Smirnoff }
56323b3a8eb9SGleb Smirnoff
56333b3a8eb9SGleb Smirnoff void
expand_label_proto(const char * name,char * label,size_t len,u_int8_t proto)56343b3a8eb9SGleb Smirnoff expand_label_proto(const char *name, char *label, size_t len, u_int8_t proto)
56353b3a8eb9SGleb Smirnoff {
5636858937beSMateusz Guzik const char *protoname;
56373b3a8eb9SGleb Smirnoff char n[4];
56383b3a8eb9SGleb Smirnoff
56393b3a8eb9SGleb Smirnoff if (strstr(label, name) != NULL) {
5640858937beSMateusz Guzik protoname = pfctl_proto2name(proto);
5641858937beSMateusz Guzik if (protoname != NULL)
5642858937beSMateusz Guzik expand_label_str(label, len, name, protoname);
56433b3a8eb9SGleb Smirnoff else {
56443b3a8eb9SGleb Smirnoff snprintf(n, sizeof(n), "%u", proto);
56453b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, n);
56463b3a8eb9SGleb Smirnoff }
56473b3a8eb9SGleb Smirnoff }
56483b3a8eb9SGleb Smirnoff }
56493b3a8eb9SGleb Smirnoff
56503b3a8eb9SGleb Smirnoff void
expand_label_nr(const char * name,char * label,size_t len,struct pfctl_rule * r)565109c7f238SKristof Provost expand_label_nr(const char *name, char *label, size_t len,
565209c7f238SKristof Provost struct pfctl_rule *r)
56533b3a8eb9SGleb Smirnoff {
56543b3a8eb9SGleb Smirnoff char n[11];
56553b3a8eb9SGleb Smirnoff
56563b3a8eb9SGleb Smirnoff if (strstr(label, name) != NULL) {
565709c7f238SKristof Provost snprintf(n, sizeof(n), "%u", r->nr);
56583b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, n);
56593b3a8eb9SGleb Smirnoff }
56603b3a8eb9SGleb Smirnoff }
56613b3a8eb9SGleb Smirnoff
56623b3a8eb9SGleb Smirnoff void
expand_label(char * label,size_t len,struct pfctl_rule * r)566309c7f238SKristof Provost expand_label(char *label, size_t len, struct pfctl_rule *r)
56643b3a8eb9SGleb Smirnoff {
566509c7f238SKristof Provost expand_label_if("$if", label, len, r->ifname);
566609c7f238SKristof Provost expand_label_addr("$srcaddr", label, len, r->af, &r->src);
566709c7f238SKristof Provost expand_label_addr("$dstaddr", label, len, r->af, &r->dst);
566809c7f238SKristof Provost expand_label_port("$srcport", label, len, &r->src);
566909c7f238SKristof Provost expand_label_port("$dstport", label, len, &r->dst);
567009c7f238SKristof Provost expand_label_proto("$proto", label, len, r->proto);
567109c7f238SKristof Provost expand_label_nr("$nr", label, len, r);
56723b3a8eb9SGleb Smirnoff }
56733b3a8eb9SGleb Smirnoff
56743b3a8eb9SGleb Smirnoff int
expand_altq(struct pf_altq * a,struct node_if * interfaces,struct node_queue * nqueues,struct node_queue_bw bwspec,struct node_queue_opt * opts)56753b3a8eb9SGleb Smirnoff expand_altq(struct pf_altq *a, struct node_if *interfaces,
56763b3a8eb9SGleb Smirnoff struct node_queue *nqueues, struct node_queue_bw bwspec,
56773b3a8eb9SGleb Smirnoff struct node_queue_opt *opts)
56783b3a8eb9SGleb Smirnoff {
56793b3a8eb9SGleb Smirnoff struct pf_altq pa, pb;
56803b3a8eb9SGleb Smirnoff char qname[PF_QNAME_SIZE];
56813b3a8eb9SGleb Smirnoff struct node_queue *n;
56823b3a8eb9SGleb Smirnoff struct node_queue_bw bw;
56833b3a8eb9SGleb Smirnoff int errs = 0;
56843b3a8eb9SGleb Smirnoff
56853b3a8eb9SGleb Smirnoff if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) {
56863b3a8eb9SGleb Smirnoff FREE_LIST(struct node_if, interfaces);
56870a70aaf8SLuiz Otavio O Souza if (nqueues)
56883b3a8eb9SGleb Smirnoff FREE_LIST(struct node_queue, nqueues);
56893b3a8eb9SGleb Smirnoff return (0);
56903b3a8eb9SGleb Smirnoff }
56913b3a8eb9SGleb Smirnoff
56923b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_if, interface, interfaces,
56933b3a8eb9SGleb Smirnoff memcpy(&pa, a, sizeof(struct pf_altq));
56943b3a8eb9SGleb Smirnoff if (strlcpy(pa.ifname, interface->ifname,
56953b3a8eb9SGleb Smirnoff sizeof(pa.ifname)) >= sizeof(pa.ifname))
56963b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcpy");
56973b3a8eb9SGleb Smirnoff
56983b3a8eb9SGleb Smirnoff if (interface->not) {
56993b3a8eb9SGleb Smirnoff yyerror("altq on ! <interface> is not supported");
57003b3a8eb9SGleb Smirnoff errs++;
57013b3a8eb9SGleb Smirnoff } else {
57023b3a8eb9SGleb Smirnoff if (eval_pfaltq(pf, &pa, &bwspec, opts))
57033b3a8eb9SGleb Smirnoff errs++;
57043b3a8eb9SGleb Smirnoff else
57053b3a8eb9SGleb Smirnoff if (pfctl_add_altq(pf, &pa))
57063b3a8eb9SGleb Smirnoff errs++;
57073b3a8eb9SGleb Smirnoff
57083b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) {
57093b3a8eb9SGleb Smirnoff print_altq(&pf->paltq->altq, 0,
57103b3a8eb9SGleb Smirnoff &bwspec, opts);
57113b3a8eb9SGleb Smirnoff if (nqueues && nqueues->tail) {
57123b3a8eb9SGleb Smirnoff printf("queue { ");
57133b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_queue, queue,
57143b3a8eb9SGleb Smirnoff nqueues,
57153b3a8eb9SGleb Smirnoff printf("%s ",
57163b3a8eb9SGleb Smirnoff queue->queue);
57173b3a8eb9SGleb Smirnoff );
57183b3a8eb9SGleb Smirnoff printf("}");
57193b3a8eb9SGleb Smirnoff }
57203b3a8eb9SGleb Smirnoff printf("\n");
57213b3a8eb9SGleb Smirnoff }
57223b3a8eb9SGleb Smirnoff
57233b3a8eb9SGleb Smirnoff if (pa.scheduler == ALTQT_CBQ ||
5724dc784287SKristof Provost pa.scheduler == ALTQT_HFSC ||
5725dc784287SKristof Provost pa.scheduler == ALTQT_FAIRQ) {
57263b3a8eb9SGleb Smirnoff /* now create a root queue */
57273b3a8eb9SGleb Smirnoff memset(&pb, 0, sizeof(struct pf_altq));
57283b3a8eb9SGleb Smirnoff if (strlcpy(qname, "root_", sizeof(qname)) >=
57293b3a8eb9SGleb Smirnoff sizeof(qname))
57303b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcpy");
57313b3a8eb9SGleb Smirnoff if (strlcat(qname, interface->ifname,
57323b3a8eb9SGleb Smirnoff sizeof(qname)) >= sizeof(qname))
57333b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcat");
57343b3a8eb9SGleb Smirnoff if (strlcpy(pb.qname, qname,
57353b3a8eb9SGleb Smirnoff sizeof(pb.qname)) >= sizeof(pb.qname))
57363b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcpy");
57373b3a8eb9SGleb Smirnoff if (strlcpy(pb.ifname, interface->ifname,
57383b3a8eb9SGleb Smirnoff sizeof(pb.ifname)) >= sizeof(pb.ifname))
57393b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcpy");
57403b3a8eb9SGleb Smirnoff pb.qlimit = pa.qlimit;
57413b3a8eb9SGleb Smirnoff pb.scheduler = pa.scheduler;
57423b3a8eb9SGleb Smirnoff bw.bw_absolute = pa.ifbandwidth;
57433b3a8eb9SGleb Smirnoff bw.bw_percent = 0;
57443b3a8eb9SGleb Smirnoff if (eval_pfqueue(pf, &pb, &bw, opts))
57453b3a8eb9SGleb Smirnoff errs++;
57463b3a8eb9SGleb Smirnoff else
57473b3a8eb9SGleb Smirnoff if (pfctl_add_altq(pf, &pb))
57483b3a8eb9SGleb Smirnoff errs++;
57493b3a8eb9SGleb Smirnoff }
57503b3a8eb9SGleb Smirnoff
57513b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_queue, queue, nqueues,
57523b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_queue));
57533b3a8eb9SGleb Smirnoff if (n == NULL)
57543b3a8eb9SGleb Smirnoff err(1, "expand_altq: calloc");
57553b3a8eb9SGleb Smirnoff if (pa.scheduler == ALTQT_CBQ ||
5756dc784287SKristof Provost pa.scheduler == ALTQT_HFSC ||
5757dc784287SKristof Provost pa.scheduler == ALTQT_FAIRQ)
57583b3a8eb9SGleb Smirnoff if (strlcpy(n->parent, qname,
57593b3a8eb9SGleb Smirnoff sizeof(n->parent)) >=
57603b3a8eb9SGleb Smirnoff sizeof(n->parent))
57613b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcpy");
57623b3a8eb9SGleb Smirnoff if (strlcpy(n->queue, queue->queue,
57633b3a8eb9SGleb Smirnoff sizeof(n->queue)) >= sizeof(n->queue))
57643b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcpy");
57653b3a8eb9SGleb Smirnoff if (strlcpy(n->ifname, interface->ifname,
57663b3a8eb9SGleb Smirnoff sizeof(n->ifname)) >= sizeof(n->ifname))
57673b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcpy");
57683b3a8eb9SGleb Smirnoff n->scheduler = pa.scheduler;
57693b3a8eb9SGleb Smirnoff n->next = NULL;
57703b3a8eb9SGleb Smirnoff n->tail = n;
57713b3a8eb9SGleb Smirnoff if (queues == NULL)
57723b3a8eb9SGleb Smirnoff queues = n;
57733b3a8eb9SGleb Smirnoff else {
57743b3a8eb9SGleb Smirnoff queues->tail->next = n;
57753b3a8eb9SGleb Smirnoff queues->tail = n;
57763b3a8eb9SGleb Smirnoff }
57773b3a8eb9SGleb Smirnoff );
57783b3a8eb9SGleb Smirnoff }
57793b3a8eb9SGleb Smirnoff );
57803b3a8eb9SGleb Smirnoff FREE_LIST(struct node_if, interfaces);
57810a70aaf8SLuiz Otavio O Souza if (nqueues)
57823b3a8eb9SGleb Smirnoff FREE_LIST(struct node_queue, nqueues);
57833b3a8eb9SGleb Smirnoff
57843b3a8eb9SGleb Smirnoff return (errs);
57853b3a8eb9SGleb Smirnoff }
57863b3a8eb9SGleb Smirnoff
57873b3a8eb9SGleb Smirnoff int
expand_queue(struct pf_altq * a,struct node_if * interfaces,struct node_queue * nqueues,struct node_queue_bw bwspec,struct node_queue_opt * opts)57883b3a8eb9SGleb Smirnoff expand_queue(struct pf_altq *a, struct node_if *interfaces,
57893b3a8eb9SGleb Smirnoff struct node_queue *nqueues, struct node_queue_bw bwspec,
57903b3a8eb9SGleb Smirnoff struct node_queue_opt *opts)
57913b3a8eb9SGleb Smirnoff {
57923b3a8eb9SGleb Smirnoff struct node_queue *n, *nq;
57933b3a8eb9SGleb Smirnoff struct pf_altq pa;
57943b3a8eb9SGleb Smirnoff u_int8_t found = 0;
57953b3a8eb9SGleb Smirnoff u_int8_t errs = 0;
57963b3a8eb9SGleb Smirnoff
57973b3a8eb9SGleb Smirnoff if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) {
57983b3a8eb9SGleb Smirnoff FREE_LIST(struct node_queue, nqueues);
57993b3a8eb9SGleb Smirnoff return (0);
58003b3a8eb9SGleb Smirnoff }
58013b3a8eb9SGleb Smirnoff
58023b3a8eb9SGleb Smirnoff if (queues == NULL) {
58033b3a8eb9SGleb Smirnoff yyerror("queue %s has no parent", a->qname);
58043b3a8eb9SGleb Smirnoff FREE_LIST(struct node_queue, nqueues);
58053b3a8eb9SGleb Smirnoff return (1);
58063b3a8eb9SGleb Smirnoff }
58073b3a8eb9SGleb Smirnoff
58083b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_if, interface, interfaces,
58093b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_queue, tqueue, queues,
58103b3a8eb9SGleb Smirnoff if (!strncmp(a->qname, tqueue->queue, PF_QNAME_SIZE) &&
58113b3a8eb9SGleb Smirnoff (interface->ifname[0] == 0 ||
58123b3a8eb9SGleb Smirnoff (!interface->not && !strncmp(interface->ifname,
58133b3a8eb9SGleb Smirnoff tqueue->ifname, IFNAMSIZ)) ||
58143b3a8eb9SGleb Smirnoff (interface->not && strncmp(interface->ifname,
58153b3a8eb9SGleb Smirnoff tqueue->ifname, IFNAMSIZ)))) {
58163b3a8eb9SGleb Smirnoff /* found ourself in queues */
58173b3a8eb9SGleb Smirnoff found++;
58183b3a8eb9SGleb Smirnoff
58193b3a8eb9SGleb Smirnoff memcpy(&pa, a, sizeof(struct pf_altq));
58203b3a8eb9SGleb Smirnoff
58213b3a8eb9SGleb Smirnoff if (pa.scheduler != ALTQT_NONE &&
58223b3a8eb9SGleb Smirnoff pa.scheduler != tqueue->scheduler) {
58233b3a8eb9SGleb Smirnoff yyerror("exactly one scheduler type "
58243b3a8eb9SGleb Smirnoff "per interface allowed");
58253b3a8eb9SGleb Smirnoff return (1);
58263b3a8eb9SGleb Smirnoff }
58273b3a8eb9SGleb Smirnoff pa.scheduler = tqueue->scheduler;
58283b3a8eb9SGleb Smirnoff
58293b3a8eb9SGleb Smirnoff /* scheduler dependent error checking */
58303b3a8eb9SGleb Smirnoff switch (pa.scheduler) {
58313b3a8eb9SGleb Smirnoff case ALTQT_PRIQ:
58323b3a8eb9SGleb Smirnoff if (nqueues != NULL) {
58333b3a8eb9SGleb Smirnoff yyerror("priq queues cannot "
58343b3a8eb9SGleb Smirnoff "have child queues");
58353b3a8eb9SGleb Smirnoff return (1);
58363b3a8eb9SGleb Smirnoff }
58373b3a8eb9SGleb Smirnoff if (bwspec.bw_absolute > 0 ||
58383b3a8eb9SGleb Smirnoff bwspec.bw_percent < 100) {
58393b3a8eb9SGleb Smirnoff yyerror("priq doesn't take "
58403b3a8eb9SGleb Smirnoff "bandwidth");
58413b3a8eb9SGleb Smirnoff return (1);
58423b3a8eb9SGleb Smirnoff }
58433b3a8eb9SGleb Smirnoff break;
58443b3a8eb9SGleb Smirnoff default:
58453b3a8eb9SGleb Smirnoff break;
58463b3a8eb9SGleb Smirnoff }
58473b3a8eb9SGleb Smirnoff
58483b3a8eb9SGleb Smirnoff if (strlcpy(pa.ifname, tqueue->ifname,
58493b3a8eb9SGleb Smirnoff sizeof(pa.ifname)) >= sizeof(pa.ifname))
58503b3a8eb9SGleb Smirnoff errx(1, "expand_queue: strlcpy");
58513b3a8eb9SGleb Smirnoff if (strlcpy(pa.parent, tqueue->parent,
58523b3a8eb9SGleb Smirnoff sizeof(pa.parent)) >= sizeof(pa.parent))
58533b3a8eb9SGleb Smirnoff errx(1, "expand_queue: strlcpy");
58543b3a8eb9SGleb Smirnoff
58553b3a8eb9SGleb Smirnoff if (eval_pfqueue(pf, &pa, &bwspec, opts))
58563b3a8eb9SGleb Smirnoff errs++;
58573b3a8eb9SGleb Smirnoff else
58583b3a8eb9SGleb Smirnoff if (pfctl_add_altq(pf, &pa))
58593b3a8eb9SGleb Smirnoff errs++;
58603b3a8eb9SGleb Smirnoff
58613b3a8eb9SGleb Smirnoff for (nq = nqueues; nq != NULL; nq = nq->next) {
58623b3a8eb9SGleb Smirnoff if (!strcmp(a->qname, nq->queue)) {
58633b3a8eb9SGleb Smirnoff yyerror("queue cannot have "
58643b3a8eb9SGleb Smirnoff "itself as child");
58653b3a8eb9SGleb Smirnoff errs++;
58663b3a8eb9SGleb Smirnoff continue;
58673b3a8eb9SGleb Smirnoff }
58683b3a8eb9SGleb Smirnoff n = calloc(1,
58693b3a8eb9SGleb Smirnoff sizeof(struct node_queue));
58703b3a8eb9SGleb Smirnoff if (n == NULL)
58713b3a8eb9SGleb Smirnoff err(1, "expand_queue: calloc");
58723b3a8eb9SGleb Smirnoff if (strlcpy(n->parent, a->qname,
58733b3a8eb9SGleb Smirnoff sizeof(n->parent)) >=
58743b3a8eb9SGleb Smirnoff sizeof(n->parent))
58753b3a8eb9SGleb Smirnoff errx(1, "expand_queue strlcpy");
58763b3a8eb9SGleb Smirnoff if (strlcpy(n->queue, nq->queue,
58773b3a8eb9SGleb Smirnoff sizeof(n->queue)) >=
58783b3a8eb9SGleb Smirnoff sizeof(n->queue))
58793b3a8eb9SGleb Smirnoff errx(1, "expand_queue strlcpy");
58803b3a8eb9SGleb Smirnoff if (strlcpy(n->ifname, tqueue->ifname,
58813b3a8eb9SGleb Smirnoff sizeof(n->ifname)) >=
58823b3a8eb9SGleb Smirnoff sizeof(n->ifname))
58833b3a8eb9SGleb Smirnoff errx(1, "expand_queue strlcpy");
58843b3a8eb9SGleb Smirnoff n->scheduler = tqueue->scheduler;
58853b3a8eb9SGleb Smirnoff n->next = NULL;
58863b3a8eb9SGleb Smirnoff n->tail = n;
58873b3a8eb9SGleb Smirnoff if (queues == NULL)
58883b3a8eb9SGleb Smirnoff queues = n;
58893b3a8eb9SGleb Smirnoff else {
58903b3a8eb9SGleb Smirnoff queues->tail->next = n;
58913b3a8eb9SGleb Smirnoff queues->tail = n;
58923b3a8eb9SGleb Smirnoff }
58933b3a8eb9SGleb Smirnoff }
58943b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_VERBOSE) && (
58953b3a8eb9SGleb Smirnoff (found == 1 && interface->ifname[0] == 0) ||
58963b3a8eb9SGleb Smirnoff (found > 0 && interface->ifname[0] != 0))) {
58973b3a8eb9SGleb Smirnoff print_queue(&pf->paltq->altq, 0,
58983b3a8eb9SGleb Smirnoff &bwspec, interface->ifname[0] != 0,
58993b3a8eb9SGleb Smirnoff opts);
59003b3a8eb9SGleb Smirnoff if (nqueues && nqueues->tail) {
59013b3a8eb9SGleb Smirnoff printf("{ ");
59023b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_queue,
59033b3a8eb9SGleb Smirnoff queue, nqueues,
59043b3a8eb9SGleb Smirnoff printf("%s ",
59053b3a8eb9SGleb Smirnoff queue->queue);
59063b3a8eb9SGleb Smirnoff );
59073b3a8eb9SGleb Smirnoff printf("}");
59083b3a8eb9SGleb Smirnoff }
59093b3a8eb9SGleb Smirnoff printf("\n");
59103b3a8eb9SGleb Smirnoff }
59113b3a8eb9SGleb Smirnoff }
59123b3a8eb9SGleb Smirnoff );
59133b3a8eb9SGleb Smirnoff );
59143b3a8eb9SGleb Smirnoff
59153b3a8eb9SGleb Smirnoff FREE_LIST(struct node_queue, nqueues);
59163b3a8eb9SGleb Smirnoff FREE_LIST(struct node_if, interfaces);
59173b3a8eb9SGleb Smirnoff
59183b3a8eb9SGleb Smirnoff if (!found) {
59193b3a8eb9SGleb Smirnoff yyerror("queue %s has no parent", a->qname);
59203b3a8eb9SGleb Smirnoff errs++;
59213b3a8eb9SGleb Smirnoff }
59223b3a8eb9SGleb Smirnoff
59233b3a8eb9SGleb Smirnoff if (errs)
59243b3a8eb9SGleb Smirnoff return (1);
59253b3a8eb9SGleb Smirnoff else
59263b3a8eb9SGleb Smirnoff return (0);
59273b3a8eb9SGleb Smirnoff }
59283b3a8eb9SGleb Smirnoff
59298a42005dSKristof Provost static int
pf_af_to_proto(sa_family_t af)59308a42005dSKristof Provost pf_af_to_proto(sa_family_t af)
59318a42005dSKristof Provost {
59328a42005dSKristof Provost if (af == AF_INET)
59338a42005dSKristof Provost return (ETHERTYPE_IP);
59348a42005dSKristof Provost if (af == AF_INET6)
59358a42005dSKristof Provost return (ETHERTYPE_IPV6);
59368a42005dSKristof Provost
59378a42005dSKristof Provost return (0);
59388a42005dSKristof Provost }
59398a42005dSKristof Provost
59403b3a8eb9SGleb Smirnoff void
expand_eth_rule(struct pfctl_eth_rule * r,struct node_if * interfaces,struct node_etherproto * protos,struct node_mac * srcs,struct node_mac * dsts,struct node_host * ipsrcs,struct node_host * ipdsts,const char * bridge_to,const char * anchor_call)59412b29ceb8SKristof Provost expand_eth_rule(struct pfctl_eth_rule *r,
594287a89d6eSKristof Provost struct node_if *interfaces, struct node_etherproto *protos,
59438a42005dSKristof Provost struct node_mac *srcs, struct node_mac *dsts,
59448a8af942SKristof Provost struct node_host *ipsrcs, struct node_host *ipdsts,
59458a8af942SKristof Provost const char *bridge_to, const char *anchor_call)
59462b29ceb8SKristof Provost {
59471f61367fSKristof Provost char tagname[PF_TAG_NAME_SIZE];
59481f61367fSKristof Provost char match_tagname[PF_TAG_NAME_SIZE];
59491f61367fSKristof Provost char qname[PF_QNAME_SIZE];
59501f61367fSKristof Provost
59511f61367fSKristof Provost if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname))
59521f61367fSKristof Provost errx(1, "expand_eth_rule: tagname");
59531f61367fSKristof Provost if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >=
59541f61367fSKristof Provost sizeof(match_tagname))
59551f61367fSKristof Provost errx(1, "expand_eth_rule: match_tagname");
59561f61367fSKristof Provost if (strlcpy(qname, r->qname, sizeof(qname)) >= sizeof(qname))
59571f61367fSKristof Provost errx(1, "expand_eth_rule: qname");
59581f61367fSKristof Provost
59592b29ceb8SKristof Provost LOOP_THROUGH(struct node_if, interface, interfaces,
59602b29ceb8SKristof Provost LOOP_THROUGH(struct node_etherproto, proto, protos,
596187a89d6eSKristof Provost LOOP_THROUGH(struct node_mac, src, srcs,
596287a89d6eSKristof Provost LOOP_THROUGH(struct node_mac, dst, dsts,
59638a42005dSKristof Provost LOOP_THROUGH(struct node_host, ipsrc, ipsrcs,
59648a42005dSKristof Provost LOOP_THROUGH(struct node_host, ipdst, ipdsts,
59652b29ceb8SKristof Provost strlcpy(r->ifname, interface->ifname,
59662b29ceb8SKristof Provost sizeof(r->ifname));
59672b29ceb8SKristof Provost r->ifnot = interface->not;
59682b29ceb8SKristof Provost r->proto = proto->proto;
59698a42005dSKristof Provost if (!r->proto && ipsrc->af)
59708a42005dSKristof Provost r->proto = pf_af_to_proto(ipsrc->af);
59718a42005dSKristof Provost else if (!r->proto && ipdst->af)
59728a42005dSKristof Provost r->proto = pf_af_to_proto(ipdst->af);
597387a89d6eSKristof Provost bcopy(src->mac, r->src.addr, ETHER_ADDR_LEN);
5974b590f17aSKristof Provost bcopy(src->mask, r->src.mask, ETHER_ADDR_LEN);
597587a89d6eSKristof Provost r->src.neg = src->neg;
5976c32cd180SKristof Provost r->src.isset = src->isset;
59778a42005dSKristof Provost r->ipsrc.addr = ipsrc->addr;
59788a42005dSKristof Provost r->ipsrc.neg = ipsrc->not;
59798a42005dSKristof Provost r->ipdst.addr = ipdst->addr;
59808a42005dSKristof Provost r->ipdst.neg = ipdst->not;
598187a89d6eSKristof Provost bcopy(dst->mac, r->dst.addr, ETHER_ADDR_LEN);
5982b590f17aSKristof Provost bcopy(dst->mask, r->dst.mask, ETHER_ADDR_LEN);
598387a89d6eSKristof Provost r->dst.neg = dst->neg;
5984c32cd180SKristof Provost r->dst.isset = dst->isset;
5985c5131afeSKristof Provost r->nr = pf->eastack[pf->asd]->match++;
59862b29ceb8SKristof Provost
59871f61367fSKristof Provost if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >=
59881f61367fSKristof Provost sizeof(r->tagname))
59891f61367fSKristof Provost errx(1, "expand_eth_rule: r->tagname");
59901f61367fSKristof Provost if (strlcpy(r->match_tagname, match_tagname,
59911f61367fSKristof Provost sizeof(r->match_tagname)) >= sizeof(r->match_tagname))
59921f61367fSKristof Provost errx(1, "expand_eth_rule: r->match_tagname");
59931f61367fSKristof Provost if (strlcpy(r->qname, qname, sizeof(r->qname)) >= sizeof(r->qname))
59941f61367fSKristof Provost errx(1, "expand_eth_rule: r->qname");
59951f61367fSKristof Provost
59968a8af942SKristof Provost if (bridge_to)
59978a8af942SKristof Provost strlcpy(r->bridge_to, bridge_to, sizeof(r->bridge_to));
59988a8af942SKristof Provost
5999c5131afeSKristof Provost pfctl_append_eth_rule(pf, r, anchor_call);
60008a42005dSKristof Provost ))))));
60012b29ceb8SKristof Provost
60022b29ceb8SKristof Provost FREE_LIST(struct node_if, interfaces);
60032b29ceb8SKristof Provost FREE_LIST(struct node_etherproto, protos);
600487a89d6eSKristof Provost FREE_LIST(struct node_mac, srcs);
600587a89d6eSKristof Provost FREE_LIST(struct node_mac, dsts);
60068a42005dSKristof Provost FREE_LIST(struct node_host, ipsrcs);
60078a42005dSKristof Provost FREE_LIST(struct node_host, ipdsts);
60082b29ceb8SKristof Provost }
60092b29ceb8SKristof Provost
6010*aeddee83SKajetan Staszkiewicz int
apply_rdr_ports(struct pfctl_rule * r,struct pfctl_pool * rpool,struct redirspec * rs)6011*aeddee83SKajetan Staszkiewicz apply_rdr_ports(struct pfctl_rule *r, struct pfctl_pool *rpool, struct redirspec *rs)
6012*aeddee83SKajetan Staszkiewicz {
6013*aeddee83SKajetan Staszkiewicz if (rs == NULL)
6014*aeddee83SKajetan Staszkiewicz return 0;
6015*aeddee83SKajetan Staszkiewicz
6016*aeddee83SKajetan Staszkiewicz rpool->proxy_port[0] = ntohs(rs->rport.a);
6017*aeddee83SKajetan Staszkiewicz
6018*aeddee83SKajetan Staszkiewicz if (!rs->rport.b && rs->rport.t && r->dst.port != NULL) {
6019*aeddee83SKajetan Staszkiewicz rpool->proxy_port[1] = ntohs(rs->rport.a) +
6020*aeddee83SKajetan Staszkiewicz (ntohs(r->dst.port[1]) - ntohs(r->dst.port[0]));
6021*aeddee83SKajetan Staszkiewicz } else
6022*aeddee83SKajetan Staszkiewicz r->rdr.proxy_port[1] = ntohs(rs->rport.b);
6023*aeddee83SKajetan Staszkiewicz
6024*aeddee83SKajetan Staszkiewicz if (rs->pool_opts.staticport) {
6025*aeddee83SKajetan Staszkiewicz yyerror("the 'static-port' option is only valid with nat rules");
6026*aeddee83SKajetan Staszkiewicz return 1;
6027*aeddee83SKajetan Staszkiewicz }
6028*aeddee83SKajetan Staszkiewicz
6029*aeddee83SKajetan Staszkiewicz if (rs->pool_opts.mape.offset) {
6030*aeddee83SKajetan Staszkiewicz yyerror("the 'map-e-portset' option is only valid with nat rules");
6031*aeddee83SKajetan Staszkiewicz return 1;
6032*aeddee83SKajetan Staszkiewicz }
6033*aeddee83SKajetan Staszkiewicz
6034*aeddee83SKajetan Staszkiewicz return 0;
6035*aeddee83SKajetan Staszkiewicz }
6036*aeddee83SKajetan Staszkiewicz
6037*aeddee83SKajetan Staszkiewicz int
apply_nat_ports(struct pfctl_pool * rpool,struct redirspec * rs)6038*aeddee83SKajetan Staszkiewicz apply_nat_ports(struct pfctl_pool *rpool, struct redirspec *rs)
6039*aeddee83SKajetan Staszkiewicz {
6040*aeddee83SKajetan Staszkiewicz if (rs == NULL)
6041*aeddee83SKajetan Staszkiewicz return 0;
6042*aeddee83SKajetan Staszkiewicz
6043*aeddee83SKajetan Staszkiewicz rpool->proxy_port[0] = ntohs(rs->rport.a);
6044*aeddee83SKajetan Staszkiewicz rpool->proxy_port[1] = ntohs(rs->rport.b);
6045*aeddee83SKajetan Staszkiewicz if (!rpool->proxy_port[0] && !rpool->proxy_port[1]) {
6046*aeddee83SKajetan Staszkiewicz rpool->proxy_port[0] = PF_NAT_PROXY_PORT_LOW;
6047*aeddee83SKajetan Staszkiewicz rpool->proxy_port[1] = PF_NAT_PROXY_PORT_HIGH;
6048*aeddee83SKajetan Staszkiewicz } else if (!rpool->proxy_port[1])
6049*aeddee83SKajetan Staszkiewicz rpool->proxy_port[1] = rpool->proxy_port[0];
6050*aeddee83SKajetan Staszkiewicz
6051*aeddee83SKajetan Staszkiewicz if (rs->pool_opts.staticport) {
6052*aeddee83SKajetan Staszkiewicz if (rpool->proxy_port[0] != PF_NAT_PROXY_PORT_LOW &&
6053*aeddee83SKajetan Staszkiewicz rpool->proxy_port[1] != PF_NAT_PROXY_PORT_HIGH) {
6054*aeddee83SKajetan Staszkiewicz yyerror("the 'static-port' option can't"
6055*aeddee83SKajetan Staszkiewicz " be used when specifying a port"
6056*aeddee83SKajetan Staszkiewicz " range");
6057*aeddee83SKajetan Staszkiewicz return 1;
6058*aeddee83SKajetan Staszkiewicz }
6059*aeddee83SKajetan Staszkiewicz rpool->proxy_port[0] = 0;
6060*aeddee83SKajetan Staszkiewicz rpool->proxy_port[1] = 0;
6061*aeddee83SKajetan Staszkiewicz }
6062*aeddee83SKajetan Staszkiewicz
6063*aeddee83SKajetan Staszkiewicz if (rs->pool_opts.mape.offset) {
6064*aeddee83SKajetan Staszkiewicz if (rs->pool_opts.staticport) {
6065*aeddee83SKajetan Staszkiewicz yyerror("the 'map-e-portset' option"
6066*aeddee83SKajetan Staszkiewicz " can't be used 'static-port'");
6067*aeddee83SKajetan Staszkiewicz return 1;
6068*aeddee83SKajetan Staszkiewicz }
6069*aeddee83SKajetan Staszkiewicz if (rpool->proxy_port[0] != PF_NAT_PROXY_PORT_LOW &&
6070*aeddee83SKajetan Staszkiewicz rpool->proxy_port[1] != PF_NAT_PROXY_PORT_HIGH) {
6071*aeddee83SKajetan Staszkiewicz yyerror("the 'map-e-portset' option"
6072*aeddee83SKajetan Staszkiewicz " can't be used when specifying"
6073*aeddee83SKajetan Staszkiewicz " a port range");
6074*aeddee83SKajetan Staszkiewicz return 1;
6075*aeddee83SKajetan Staszkiewicz }
6076*aeddee83SKajetan Staszkiewicz rpool->mape = rs->pool_opts.mape;
6077*aeddee83SKajetan Staszkiewicz }
6078*aeddee83SKajetan Staszkiewicz
6079*aeddee83SKajetan Staszkiewicz return 0;
6080*aeddee83SKajetan Staszkiewicz }
6081*aeddee83SKajetan Staszkiewicz
6082*aeddee83SKajetan Staszkiewicz int
apply_redirspec(struct pfctl_pool * rpool,struct redirspec * rs)6083*aeddee83SKajetan Staszkiewicz apply_redirspec(struct pfctl_pool *rpool, struct redirspec *rs)
6084*aeddee83SKajetan Staszkiewicz {
6085*aeddee83SKajetan Staszkiewicz struct node_host *h;
6086*aeddee83SKajetan Staszkiewicz struct pf_pooladdr *pa;
6087*aeddee83SKajetan Staszkiewicz
6088*aeddee83SKajetan Staszkiewicz if (rs == NULL)
6089*aeddee83SKajetan Staszkiewicz return 0;
6090*aeddee83SKajetan Staszkiewicz
6091*aeddee83SKajetan Staszkiewicz rpool->opts = rs->pool_opts.type;
6092*aeddee83SKajetan Staszkiewicz
6093*aeddee83SKajetan Staszkiewicz if ((rpool->opts & PF_POOL_TYPEMASK) == PF_POOL_NONE &&
6094*aeddee83SKajetan Staszkiewicz (rs->host->next != NULL ||
6095*aeddee83SKajetan Staszkiewicz rs->host->addr.type == PF_ADDR_TABLE ||
6096*aeddee83SKajetan Staszkiewicz DYNIF_MULTIADDR(rs->host->addr)))
6097*aeddee83SKajetan Staszkiewicz rpool->opts = PF_POOL_ROUNDROBIN;
6098*aeddee83SKajetan Staszkiewicz
6099*aeddee83SKajetan Staszkiewicz if (!PF_POOL_DYNTYPE(rpool->opts) &&
6100*aeddee83SKajetan Staszkiewicz (disallow_table(rs->host, "tables are not supported by pool type") ||
6101*aeddee83SKajetan Staszkiewicz disallow_alias(rs->host, "interface (%s) is not supported by pool type")))
6102*aeddee83SKajetan Staszkiewicz return 1;
6103*aeddee83SKajetan Staszkiewicz
6104*aeddee83SKajetan Staszkiewicz if (rs->host->next != NULL &&
6105*aeddee83SKajetan Staszkiewicz ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN)) {
6106*aeddee83SKajetan Staszkiewicz yyerror("r.route.opts must be PF_POOL_ROUNDROBIN");
6107*aeddee83SKajetan Staszkiewicz return 1;
6108*aeddee83SKajetan Staszkiewicz }
6109*aeddee83SKajetan Staszkiewicz
6110*aeddee83SKajetan Staszkiewicz if (rs->host->next != NULL) {
6111*aeddee83SKajetan Staszkiewicz if ((rpool->opts & PF_POOL_TYPEMASK) !=
6112*aeddee83SKajetan Staszkiewicz PF_POOL_ROUNDROBIN) {
6113*aeddee83SKajetan Staszkiewicz yyerror("only round-robin valid for multiple "
6114*aeddee83SKajetan Staszkiewicz "redirection addresses");
6115*aeddee83SKajetan Staszkiewicz return 1;
6116*aeddee83SKajetan Staszkiewicz }
6117*aeddee83SKajetan Staszkiewicz }
6118*aeddee83SKajetan Staszkiewicz
6119*aeddee83SKajetan Staszkiewicz rpool->opts |= rs->pool_opts.opts;
6120*aeddee83SKajetan Staszkiewicz
6121*aeddee83SKajetan Staszkiewicz if (rs->pool_opts.key != NULL)
6122*aeddee83SKajetan Staszkiewicz memcpy(&(rpool->key), rs->pool_opts.key,
6123*aeddee83SKajetan Staszkiewicz sizeof(struct pf_poolhashkey));
6124*aeddee83SKajetan Staszkiewicz
6125*aeddee83SKajetan Staszkiewicz TAILQ_INIT(&(rpool->list));
6126*aeddee83SKajetan Staszkiewicz for (h = rs->host; h != NULL; h = h->next) {
6127*aeddee83SKajetan Staszkiewicz pa = calloc(1, sizeof(struct pf_pooladdr));
6128*aeddee83SKajetan Staszkiewicz if (pa == NULL)
6129*aeddee83SKajetan Staszkiewicz err(1, "expand_rule: calloc");
6130*aeddee83SKajetan Staszkiewicz pa->addr = h->addr;
6131*aeddee83SKajetan Staszkiewicz if (h->ifname != NULL) {
6132*aeddee83SKajetan Staszkiewicz if (strlcpy(pa->ifname, h->ifname,
6133*aeddee83SKajetan Staszkiewicz sizeof(pa->ifname)) >= sizeof(pa->ifname))
6134*aeddee83SKajetan Staszkiewicz errx(1, "expand_rule: strlcpy");
6135*aeddee83SKajetan Staszkiewicz } else
6136*aeddee83SKajetan Staszkiewicz pa->ifname[0] = 0;
6137*aeddee83SKajetan Staszkiewicz TAILQ_INSERT_TAIL(&(rpool->list), pa, entries);
6138*aeddee83SKajetan Staszkiewicz }
6139*aeddee83SKajetan Staszkiewicz
6140*aeddee83SKajetan Staszkiewicz return 0;
6141*aeddee83SKajetan Staszkiewicz }
6142*aeddee83SKajetan Staszkiewicz
61432b29ceb8SKristof Provost void
expand_rule(struct pfctl_rule * r,struct node_if * interfaces,struct redirspec * nat,struct redirspec * rdr,struct redirspec * route,struct node_proto * protos,struct node_os * src_oses,struct node_host * src_hosts,struct node_port * src_ports,struct node_host * dst_hosts,struct node_port * dst_ports,struct node_uid * uids,struct node_gid * gids,struct node_if * rcv,struct node_icmp * icmp_types,const char * anchor_call)6144e9eb0941SKristof Provost expand_rule(struct pfctl_rule *r,
6145f88019e8SKristof Provost struct node_if *interfaces, struct redirspec *nat,
61460972294eSKristof Provost struct redirspec *rdr, struct redirspec *route,
6147*aeddee83SKajetan Staszkiewicz struct node_proto *protos,
61480972294eSKristof Provost struct node_os *src_oses, struct node_host *src_hosts,
61490972294eSKristof Provost struct node_port *src_ports, struct node_host *dst_hosts,
61500972294eSKristof Provost struct node_port *dst_ports, struct node_uid *uids, struct node_gid *gids,
61510972294eSKristof Provost struct node_if *rcv, struct node_icmp *icmp_types, const char *anchor_call)
61523b3a8eb9SGleb Smirnoff {
61533b3a8eb9SGleb Smirnoff sa_family_t af = r->af;
61543b3a8eb9SGleb Smirnoff int added = 0, error = 0;
61553b3a8eb9SGleb Smirnoff char ifname[IF_NAMESIZE];
61566fcc8e04SKristof Provost char label[PF_RULE_MAX_LABEL_COUNT][PF_RULE_LABEL_SIZE];
61573b3a8eb9SGleb Smirnoff char tagname[PF_TAG_NAME_SIZE];
61583b3a8eb9SGleb Smirnoff char match_tagname[PF_TAG_NAME_SIZE];
6159*aeddee83SKajetan Staszkiewicz struct node_host *osrch, *odsth;
61603b3a8eb9SGleb Smirnoff u_int8_t flags, flagset, keep_state;
61613b3a8eb9SGleb Smirnoff
61626fcc8e04SKristof Provost memcpy(label, r->label, sizeof(r->label));
61636fcc8e04SKristof Provost assert(sizeof(r->label) == sizeof(label));
61643b3a8eb9SGleb Smirnoff if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname))
61653b3a8eb9SGleb Smirnoff errx(1, "expand_rule: strlcpy");
61663b3a8eb9SGleb Smirnoff if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >=
61673b3a8eb9SGleb Smirnoff sizeof(match_tagname))
61683b3a8eb9SGleb Smirnoff errx(1, "expand_rule: strlcpy");
61693b3a8eb9SGleb Smirnoff flags = r->flags;
61703b3a8eb9SGleb Smirnoff flagset = r->flagset;
61713b3a8eb9SGleb Smirnoff keep_state = r->keep_state;
61723b3a8eb9SGleb Smirnoff
61733b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_if, interface, interfaces,
61743b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_proto, proto, protos,
61753b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types,
61763b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_host, src_host, src_hosts,
61773b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_host, dst_host, dst_hosts,
6178288bec2bSKristof Provost LOOP_THROUGH(struct node_port, src_port, src_ports,
61793b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_port, dst_port, dst_ports,
6180288bec2bSKristof Provost LOOP_THROUGH(struct node_os, src_os, src_oses,
61813b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_uid, uid, uids,
61823b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_gid, gid, gids,
61833b3a8eb9SGleb Smirnoff
61840d68985bSKristof Provost r->af = af;
6185f88019e8SKristof Provost
6186f88019e8SKristof Provost if (r->rule_flag & PFRULE_AFTO) {
6187f88019e8SKristof Provost assert(nat != NULL);
6188f88019e8SKristof Provost r->naf = nat->af;
6189f88019e8SKristof Provost }
6190f88019e8SKristof Provost
61913b3a8eb9SGleb Smirnoff /* for link-local IPv6 address, interface must match up */
61923b3a8eb9SGleb Smirnoff if ((r->af && src_host->af && r->af != src_host->af) ||
61933b3a8eb9SGleb Smirnoff (r->af && dst_host->af && r->af != dst_host->af) ||
61943b3a8eb9SGleb Smirnoff (src_host->af && dst_host->af &&
61953b3a8eb9SGleb Smirnoff src_host->af != dst_host->af) ||
61963b3a8eb9SGleb Smirnoff (src_host->ifindex && dst_host->ifindex &&
61973b3a8eb9SGleb Smirnoff src_host->ifindex != dst_host->ifindex) ||
61983b3a8eb9SGleb Smirnoff (src_host->ifindex && *interface->ifname &&
61997cef9d19SKristof Provost src_host->ifindex != ifa_nametoindex(interface->ifname)) ||
62003b3a8eb9SGleb Smirnoff (dst_host->ifindex && *interface->ifname &&
62017cef9d19SKristof Provost dst_host->ifindex != ifa_nametoindex(interface->ifname)))
62023b3a8eb9SGleb Smirnoff continue;
62033b3a8eb9SGleb Smirnoff if (!r->af && src_host->af)
62043b3a8eb9SGleb Smirnoff r->af = src_host->af;
62053b3a8eb9SGleb Smirnoff else if (!r->af && dst_host->af)
62063b3a8eb9SGleb Smirnoff r->af = dst_host->af;
62073b3a8eb9SGleb Smirnoff
62083b3a8eb9SGleb Smirnoff if (*interface->ifname)
62093b3a8eb9SGleb Smirnoff strlcpy(r->ifname, interface->ifname,
62103b3a8eb9SGleb Smirnoff sizeof(r->ifname));
62117cef9d19SKristof Provost else if (ifa_indextoname(src_host->ifindex, ifname))
62123b3a8eb9SGleb Smirnoff strlcpy(r->ifname, ifname, sizeof(r->ifname));
62137cef9d19SKristof Provost else if (ifa_indextoname(dst_host->ifindex, ifname))
62143b3a8eb9SGleb Smirnoff strlcpy(r->ifname, ifname, sizeof(r->ifname));
62153b3a8eb9SGleb Smirnoff else
62163b3a8eb9SGleb Smirnoff memset(r->ifname, '\0', sizeof(r->ifname));
62173b3a8eb9SGleb Smirnoff
62186fcc8e04SKristof Provost memcpy(r->label, label, sizeof(r->label));
62193b3a8eb9SGleb Smirnoff if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >=
62203b3a8eb9SGleb Smirnoff sizeof(r->tagname))
62213b3a8eb9SGleb Smirnoff errx(1, "expand_rule: strlcpy");
62223b3a8eb9SGleb Smirnoff if (strlcpy(r->match_tagname, match_tagname,
62233b3a8eb9SGleb Smirnoff sizeof(r->match_tagname)) >= sizeof(r->match_tagname))
62243b3a8eb9SGleb Smirnoff errx(1, "expand_rule: strlcpy");
62253b3a8eb9SGleb Smirnoff
62267ce98cf2SKristof Provost osrch = odsth = NULL;
62277ce98cf2SKristof Provost if (src_host->addr.type == PF_ADDR_DYNIFTL) {
62287ce98cf2SKristof Provost osrch = src_host;
62297ce98cf2SKristof Provost if ((src_host = gen_dynnode(src_host, r->af)) == NULL)
62307ce98cf2SKristof Provost err(1, "expand_rule: calloc");
62317ce98cf2SKristof Provost }
62327ce98cf2SKristof Provost if (dst_host->addr.type == PF_ADDR_DYNIFTL) {
62337ce98cf2SKristof Provost odsth = dst_host;
62347ce98cf2SKristof Provost if ((dst_host = gen_dynnode(dst_host, r->af)) == NULL)
62357ce98cf2SKristof Provost err(1, "expand_rule: calloc");
62367ce98cf2SKristof Provost }
62377ce98cf2SKristof Provost
62383b3a8eb9SGleb Smirnoff error += check_netmask(src_host, r->af);
62393b3a8eb9SGleb Smirnoff error += check_netmask(dst_host, r->af);
62403b3a8eb9SGleb Smirnoff
62413b3a8eb9SGleb Smirnoff r->ifnot = interface->not;
62423b3a8eb9SGleb Smirnoff r->proto = proto->proto;
62433b3a8eb9SGleb Smirnoff r->src.addr = src_host->addr;
62443b3a8eb9SGleb Smirnoff r->src.neg = src_host->not;
62453b3a8eb9SGleb Smirnoff r->src.port[0] = src_port->port[0];
62463b3a8eb9SGleb Smirnoff r->src.port[1] = src_port->port[1];
62473b3a8eb9SGleb Smirnoff r->src.port_op = src_port->op;
62483b3a8eb9SGleb Smirnoff r->dst.addr = dst_host->addr;
62493b3a8eb9SGleb Smirnoff r->dst.neg = dst_host->not;
62503b3a8eb9SGleb Smirnoff r->dst.port[0] = dst_port->port[0];
62513b3a8eb9SGleb Smirnoff r->dst.port[1] = dst_port->port[1];
62523b3a8eb9SGleb Smirnoff r->dst.port_op = dst_port->op;
62533b3a8eb9SGleb Smirnoff r->uid.op = uid->op;
62543b3a8eb9SGleb Smirnoff r->uid.uid[0] = uid->uid[0];
62553b3a8eb9SGleb Smirnoff r->uid.uid[1] = uid->uid[1];
62563b3a8eb9SGleb Smirnoff r->gid.op = gid->op;
62573b3a8eb9SGleb Smirnoff r->gid.gid[0] = gid->gid[0];
62583b3a8eb9SGleb Smirnoff r->gid.gid[1] = gid->gid[1];
62592339ead6SKristof Provost if (rcv) {
62602339ead6SKristof Provost strlcpy(r->rcv_ifname, rcv->ifname,
62612339ead6SKristof Provost sizeof(r->rcv_ifname));
626271594e32SKristof Provost r->rcvifnot = rcv->not;
62632339ead6SKristof Provost }
62643b3a8eb9SGleb Smirnoff r->type = icmp_type->type;
62653b3a8eb9SGleb Smirnoff r->code = icmp_type->code;
62663b3a8eb9SGleb Smirnoff
62673b3a8eb9SGleb Smirnoff if ((keep_state == PF_STATE_MODULATE ||
62683b3a8eb9SGleb Smirnoff keep_state == PF_STATE_SYNPROXY) &&
62693b3a8eb9SGleb Smirnoff r->proto && r->proto != IPPROTO_TCP)
62703b3a8eb9SGleb Smirnoff r->keep_state = PF_STATE_NORMAL;
62713b3a8eb9SGleb Smirnoff else
62723b3a8eb9SGleb Smirnoff r->keep_state = keep_state;
62733b3a8eb9SGleb Smirnoff
62743b3a8eb9SGleb Smirnoff if (r->proto && r->proto != IPPROTO_TCP) {
62753b3a8eb9SGleb Smirnoff r->flags = 0;
62763b3a8eb9SGleb Smirnoff r->flagset = 0;
62773b3a8eb9SGleb Smirnoff } else {
62783b3a8eb9SGleb Smirnoff r->flags = flags;
62793b3a8eb9SGleb Smirnoff r->flagset = flagset;
62803b3a8eb9SGleb Smirnoff }
62813b3a8eb9SGleb Smirnoff if (icmp_type->proto && r->proto != icmp_type->proto) {
62823b3a8eb9SGleb Smirnoff yyerror("icmp-type mismatch");
62833b3a8eb9SGleb Smirnoff error++;
62843b3a8eb9SGleb Smirnoff }
62853b3a8eb9SGleb Smirnoff
62863b3a8eb9SGleb Smirnoff if (src_os && src_os->os) {
62873b3a8eb9SGleb Smirnoff r->os_fingerprint = pfctl_get_fingerprint(src_os->os);
62883b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_VERBOSE2) &&
62893b3a8eb9SGleb Smirnoff r->os_fingerprint == PF_OSFP_NOMATCH)
62903b3a8eb9SGleb Smirnoff fprintf(stderr,
62913b3a8eb9SGleb Smirnoff "warning: unknown '%s' OS fingerprint\n",
62923b3a8eb9SGleb Smirnoff src_os->os);
62933b3a8eb9SGleb Smirnoff } else {
62943b3a8eb9SGleb Smirnoff r->os_fingerprint = PF_OSFP_ANY;
62953b3a8eb9SGleb Smirnoff }
62963b3a8eb9SGleb Smirnoff
6297*aeddee83SKajetan Staszkiewicz if (r->action == PF_RDR) {
6298*aeddee83SKajetan Staszkiewicz error += apply_rdr_ports(r, &(r->rdr), rdr);
6299*aeddee83SKajetan Staszkiewicz } else if (r->action == PF_NAT) {
6300*aeddee83SKajetan Staszkiewicz error += apply_nat_ports(&(r->rdr), rdr);
63013b3a8eb9SGleb Smirnoff }
6302*aeddee83SKajetan Staszkiewicz
6303*aeddee83SKajetan Staszkiewicz error += apply_redirspec(&(r->nat), nat);
6304*aeddee83SKajetan Staszkiewicz error += apply_redirspec(&(r->rdr), rdr);
6305*aeddee83SKajetan Staszkiewicz error += apply_redirspec(&(r->route), route);
6306aa69fdf1SKristof Provost
6307aa69fdf1SKristof Provost r->nat.proxy_port[0] = PF_NAT_PROXY_PORT_LOW;
6308aa69fdf1SKristof Provost r->nat.proxy_port[1] = PF_NAT_PROXY_PORT_HIGH;
63093b3a8eb9SGleb Smirnoff
63103b3a8eb9SGleb Smirnoff if (rule_consistent(r, anchor_call[0]) < 0 || error)
63113b3a8eb9SGleb Smirnoff yyerror("skipping rule due to errors");
63123b3a8eb9SGleb Smirnoff else {
63133b3a8eb9SGleb Smirnoff r->nr = pf->astack[pf->asd]->match++;
63140d71f9f3SKristof Provost pfctl_append_rule(pf, r, anchor_call);
63153b3a8eb9SGleb Smirnoff added++;
63163b3a8eb9SGleb Smirnoff }
63173b3a8eb9SGleb Smirnoff
63187ce98cf2SKristof Provost if (osrch && src_host->addr.type == PF_ADDR_DYNIFTL) {
63197ce98cf2SKristof Provost free(src_host);
63207ce98cf2SKristof Provost src_host = osrch;
63217ce98cf2SKristof Provost }
63227ce98cf2SKristof Provost if (odsth && dst_host->addr.type == PF_ADDR_DYNIFTL) {
63237ce98cf2SKristof Provost free(dst_host);
63247ce98cf2SKristof Provost dst_host = odsth;
63257ce98cf2SKristof Provost }
63267ce98cf2SKristof Provost
63273b3a8eb9SGleb Smirnoff ))))))))));
63283b3a8eb9SGleb Smirnoff
63293b3a8eb9SGleb Smirnoff FREE_LIST(struct node_if, interfaces);
63303b3a8eb9SGleb Smirnoff FREE_LIST(struct node_proto, protos);
63313b3a8eb9SGleb Smirnoff FREE_LIST(struct node_host, src_hosts);
63323b3a8eb9SGleb Smirnoff FREE_LIST(struct node_port, src_ports);
63333b3a8eb9SGleb Smirnoff FREE_LIST(struct node_os, src_oses);
63343b3a8eb9SGleb Smirnoff FREE_LIST(struct node_host, dst_hosts);
63353b3a8eb9SGleb Smirnoff FREE_LIST(struct node_port, dst_ports);
63363b3a8eb9SGleb Smirnoff FREE_LIST(struct node_uid, uids);
63373b3a8eb9SGleb Smirnoff FREE_LIST(struct node_gid, gids);
63383b3a8eb9SGleb Smirnoff FREE_LIST(struct node_icmp, icmp_types);
6339*aeddee83SKajetan Staszkiewicz if (nat) {
6340*aeddee83SKajetan Staszkiewicz FREE_LIST(struct node_host, nat->host);
6341*aeddee83SKajetan Staszkiewicz free(nat);
6342*aeddee83SKajetan Staszkiewicz }
6343*aeddee83SKajetan Staszkiewicz if (rdr) {
6344*aeddee83SKajetan Staszkiewicz FREE_LIST(struct node_host, rdr->host);
6345*aeddee83SKajetan Staszkiewicz free(rdr);
6346*aeddee83SKajetan Staszkiewicz }
6347*aeddee83SKajetan Staszkiewicz if (route) {
6348*aeddee83SKajetan Staszkiewicz FREE_LIST(struct node_host, route->host);
6349*aeddee83SKajetan Staszkiewicz free(route);
6350*aeddee83SKajetan Staszkiewicz }
63513b3a8eb9SGleb Smirnoff
63523b3a8eb9SGleb Smirnoff if (!added)
63533b3a8eb9SGleb Smirnoff yyerror("rule expands to no valid combination");
63543b3a8eb9SGleb Smirnoff }
63553b3a8eb9SGleb Smirnoff
63563b3a8eb9SGleb Smirnoff int
expand_skip_interface(struct node_if * interfaces)63573b3a8eb9SGleb Smirnoff expand_skip_interface(struct node_if *interfaces)
63583b3a8eb9SGleb Smirnoff {
63593b3a8eb9SGleb Smirnoff int errs = 0;
63603b3a8eb9SGleb Smirnoff
63613b3a8eb9SGleb Smirnoff if (!interfaces || (!interfaces->next && !interfaces->not &&
63623b3a8eb9SGleb Smirnoff !strcmp(interfaces->ifname, "none"))) {
63633b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE)
63643b3a8eb9SGleb Smirnoff printf("set skip on none\n");
63653b3a8eb9SGleb Smirnoff errs = pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0);
63663b3a8eb9SGleb Smirnoff return (errs);
63673b3a8eb9SGleb Smirnoff }
63683b3a8eb9SGleb Smirnoff
63693b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE)
63703b3a8eb9SGleb Smirnoff printf("set skip on {");
63713b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_if, interface, interfaces,
63723b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE)
63733b3a8eb9SGleb Smirnoff printf(" %s", interface->ifname);
63743b3a8eb9SGleb Smirnoff if (interface->not) {
63753b3a8eb9SGleb Smirnoff yyerror("skip on ! <interface> is not supported");
63763b3a8eb9SGleb Smirnoff errs++;
63773b3a8eb9SGleb Smirnoff } else
63783b3a8eb9SGleb Smirnoff errs += pfctl_set_interface_flags(pf,
63793b3a8eb9SGleb Smirnoff interface->ifname, PFI_IFLAG_SKIP, 1);
63803b3a8eb9SGleb Smirnoff );
63813b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE)
63823b3a8eb9SGleb Smirnoff printf(" }\n");
63833b3a8eb9SGleb Smirnoff
63843b3a8eb9SGleb Smirnoff FREE_LIST(struct node_if, interfaces);
63853b3a8eb9SGleb Smirnoff
63863b3a8eb9SGleb Smirnoff if (errs)
63873b3a8eb9SGleb Smirnoff return (1);
63883b3a8eb9SGleb Smirnoff else
63893b3a8eb9SGleb Smirnoff return (0);
63903b3a8eb9SGleb Smirnoff }
63913b3a8eb9SGleb Smirnoff
6392637d81c5SKristof Provost void
freehostlist(struct node_host * h)6393637d81c5SKristof Provost freehostlist(struct node_host *h)
6394637d81c5SKristof Provost {
6395637d81c5SKristof Provost FREE_LIST(struct node_host, h);
6396637d81c5SKristof Provost }
6397637d81c5SKristof Provost
63983b3a8eb9SGleb Smirnoff #undef FREE_LIST
63993b3a8eb9SGleb Smirnoff #undef LOOP_THROUGH
64003b3a8eb9SGleb Smirnoff
64013b3a8eb9SGleb Smirnoff int
check_rulestate(int desired_state)64023b3a8eb9SGleb Smirnoff check_rulestate(int desired_state)
64033b3a8eb9SGleb Smirnoff {
64043b3a8eb9SGleb Smirnoff if (require_order && (rulestate > desired_state)) {
64052b29ceb8SKristof Provost yyerror("Rules must be in order: options, ethernet, "
64062b29ceb8SKristof Provost "normalization, queueing, translation, filtering");
64073b3a8eb9SGleb Smirnoff return (1);
64083b3a8eb9SGleb Smirnoff }
64093b3a8eb9SGleb Smirnoff rulestate = desired_state;
64103b3a8eb9SGleb Smirnoff return (0);
64113b3a8eb9SGleb Smirnoff }
64123b3a8eb9SGleb Smirnoff
64133b3a8eb9SGleb Smirnoff int
kw_cmp(const void * k,const void * e)64143b3a8eb9SGleb Smirnoff kw_cmp(const void *k, const void *e)
64153b3a8eb9SGleb Smirnoff {
64163b3a8eb9SGleb Smirnoff return (strcmp(k, ((const struct keywords *)e)->k_name));
64173b3a8eb9SGleb Smirnoff }
64183b3a8eb9SGleb Smirnoff
64193b3a8eb9SGleb Smirnoff int
lookup(char * s)64203b3a8eb9SGleb Smirnoff lookup(char *s)
64213b3a8eb9SGleb Smirnoff {
64223b3a8eb9SGleb Smirnoff /* this has to be sorted always */
64233b3a8eb9SGleb Smirnoff static const struct keywords keywords[] = {
6424aa69fdf1SKristof Provost { "af-to", AFTO},
64253b3a8eb9SGleb Smirnoff { "all", ALL},
64263b3a8eb9SGleb Smirnoff { "allow-opts", ALLOWOPTS},
6427e4f2733dSKristof Provost { "allow-related", ALLOW_RELATED},
64283b3a8eb9SGleb Smirnoff { "altq", ALTQ},
64293b3a8eb9SGleb Smirnoff { "anchor", ANCHOR},
64303b3a8eb9SGleb Smirnoff { "antispoof", ANTISPOOF},
64313b3a8eb9SGleb Smirnoff { "any", ANY},
64323b3a8eb9SGleb Smirnoff { "bandwidth", BANDWIDTH},
64333b3a8eb9SGleb Smirnoff { "binat", BINAT},
64343b3a8eb9SGleb Smirnoff { "binat-anchor", BINATANCHOR},
64353b3a8eb9SGleb Smirnoff { "bitmask", BITMASK},
64363b3a8eb9SGleb Smirnoff { "block", BLOCK},
64373b3a8eb9SGleb Smirnoff { "block-policy", BLOCKPOLICY},
64388a8af942SKristof Provost { "bridge-to", BRIDGE_TO},
6439a5b789f6SErmal Luçi { "buckets", BUCKETS},
64403b3a8eb9SGleb Smirnoff { "cbq", CBQ},
64413b3a8eb9SGleb Smirnoff { "code", CODE},
64420a70aaf8SLuiz Otavio O Souza { "codelq", CODEL},
64433b3a8eb9SGleb Smirnoff { "debug", DEBUG},
64443b3a8eb9SGleb Smirnoff { "divert-reply", DIVERTREPLY},
64453b3a8eb9SGleb Smirnoff { "divert-to", DIVERTTO},
644663b3c1c7SKristof Provost { "dnpipe", DNPIPE},
644763b3c1c7SKristof Provost { "dnqueue", DNQUEUE},
64483b3a8eb9SGleb Smirnoff { "drop", DROP},
64493b3a8eb9SGleb Smirnoff { "dup-to", DUPTO},
6450390dc369STom Jones { "endpoint-independent", ENDPI},
64512b29ceb8SKristof Provost { "ether", ETHER},
6452150182e3SKristof Provost { "fail-policy", FAILPOLICY},
6453a5b789f6SErmal Luçi { "fairq", FAIRQ},
64543b3a8eb9SGleb Smirnoff { "fastroute", FASTROUTE},
64553b3a8eb9SGleb Smirnoff { "file", FILENAME},
64563b3a8eb9SGleb Smirnoff { "fingerprints", FINGERPRINTS},
64573b3a8eb9SGleb Smirnoff { "flags", FLAGS},
64583b3a8eb9SGleb Smirnoff { "floating", FLOATING},
64593b3a8eb9SGleb Smirnoff { "flush", FLUSH},
64603b3a8eb9SGleb Smirnoff { "for", FOR},
64613b3a8eb9SGleb Smirnoff { "fragment", FRAGMENT},
64623b3a8eb9SGleb Smirnoff { "from", FROM},
64633b3a8eb9SGleb Smirnoff { "global", GLOBAL},
64643b3a8eb9SGleb Smirnoff { "group", GROUP},
64653b3a8eb9SGleb Smirnoff { "hfsc", HFSC},
6466a5b789f6SErmal Luçi { "hogs", HOGS},
64673b3a8eb9SGleb Smirnoff { "hostid", HOSTID},
64683b3a8eb9SGleb Smirnoff { "icmp-type", ICMPTYPE},
64693b3a8eb9SGleb Smirnoff { "icmp6-type", ICMP6TYPE},
64703b3a8eb9SGleb Smirnoff { "if-bound", IFBOUND},
64713b3a8eb9SGleb Smirnoff { "in", IN},
64723b3a8eb9SGleb Smirnoff { "include", INCLUDE},
64733b3a8eb9SGleb Smirnoff { "inet", INET},
64743b3a8eb9SGleb Smirnoff { "inet6", INET6},
64750a70aaf8SLuiz Otavio O Souza { "interval", INTERVAL},
64763b3a8eb9SGleb Smirnoff { "keep", KEEP},
647742ec75f8SKristof Provost { "keepcounters", KEEPCOUNTERS},
64788a42005dSKristof Provost { "l3", L3},
64793b3a8eb9SGleb Smirnoff { "label", LABEL},
64803b3a8eb9SGleb Smirnoff { "limit", LIMIT},
64813b3a8eb9SGleb Smirnoff { "linkshare", LINKSHARE},
64823b3a8eb9SGleb Smirnoff { "load", LOAD},
64833b3a8eb9SGleb Smirnoff { "log", LOG},
64843b3a8eb9SGleb Smirnoff { "loginterface", LOGINTERFACE},
64852aa21096SKurosawa Takahiro { "map-e-portset", MAPEPORTSET},
6486ef950daaSKristof Provost { "match", MATCH},
6487f3ab00c2SKristof Provost { "matches", MATCHES},
64883b3a8eb9SGleb Smirnoff { "max", MAXIMUM},
64893b3a8eb9SGleb Smirnoff { "max-mss", MAXMSS},
64903b3a8eb9SGleb Smirnoff { "max-src-conn", MAXSRCCONN},
64913b3a8eb9SGleb Smirnoff { "max-src-conn-rate", MAXSRCCONNRATE},
64923b3a8eb9SGleb Smirnoff { "max-src-nodes", MAXSRCNODES},
64933b3a8eb9SGleb Smirnoff { "max-src-states", MAXSRCSTATES},
64943b3a8eb9SGleb Smirnoff { "min-ttl", MINTTL},
64953b3a8eb9SGleb Smirnoff { "modulate", MODULATE},
64963b3a8eb9SGleb Smirnoff { "nat", NAT},
64973b3a8eb9SGleb Smirnoff { "nat-anchor", NATANCHOR},
64983b3a8eb9SGleb Smirnoff { "no", NO},
64993b3a8eb9SGleb Smirnoff { "no-df", NODF},
65003b3a8eb9SGleb Smirnoff { "no-route", NOROUTE},
65013b3a8eb9SGleb Smirnoff { "no-sync", NOSYNC},
65023b3a8eb9SGleb Smirnoff { "on", ON},
65033b3a8eb9SGleb Smirnoff { "optimization", OPTIMIZATION},
65043b3a8eb9SGleb Smirnoff { "os", OS},
65053b3a8eb9SGleb Smirnoff { "out", OUT},
65063b3a8eb9SGleb Smirnoff { "overload", OVERLOAD},
65073b3a8eb9SGleb Smirnoff { "pass", PASS},
6508baf9b6d0SKristof Provost { "pflow", PFLOW},
65093b3a8eb9SGleb Smirnoff { "port", PORT},
65103e248e0fSKristof Provost { "prio", PRIO},
65113b3a8eb9SGleb Smirnoff { "priority", PRIORITY},
65123b3a8eb9SGleb Smirnoff { "priq", PRIQ},
65133b3a8eb9SGleb Smirnoff { "probability", PROBABILITY},
65143b3a8eb9SGleb Smirnoff { "proto", PROTO},
65153b3a8eb9SGleb Smirnoff { "qlimit", QLIMIT},
65163b3a8eb9SGleb Smirnoff { "queue", QUEUE},
65173b3a8eb9SGleb Smirnoff { "quick", QUICK},
65183b3a8eb9SGleb Smirnoff { "random", RANDOM},
65193b3a8eb9SGleb Smirnoff { "random-id", RANDOMID},
65203b3a8eb9SGleb Smirnoff { "rdr", RDR},
65213b3a8eb9SGleb Smirnoff { "rdr-anchor", RDRANCHOR},
65223b3a8eb9SGleb Smirnoff { "realtime", REALTIME},
65233b3a8eb9SGleb Smirnoff { "reassemble", REASSEMBLE},
65242339ead6SKristof Provost { "received-on", RECEIVEDON},
65253b3a8eb9SGleb Smirnoff { "reply-to", REPLYTO},
65263b3a8eb9SGleb Smirnoff { "require-order", REQUIREORDER},
65273b3a8eb9SGleb Smirnoff { "return", RETURN},
65283b3a8eb9SGleb Smirnoff { "return-icmp", RETURNICMP},
65293b3a8eb9SGleb Smirnoff { "return-icmp6", RETURNICMP6},
65303b3a8eb9SGleb Smirnoff { "return-rst", RETURNRST},
653176c5eeccSKristof Provost { "ridentifier", RIDENTIFIER},
65323b3a8eb9SGleb Smirnoff { "round-robin", ROUNDROBIN},
65333b3a8eb9SGleb Smirnoff { "route", ROUTE},
65343b3a8eb9SGleb Smirnoff { "route-to", ROUTETO},
65353b3a8eb9SGleb Smirnoff { "rtable", RTABLE},
65363b3a8eb9SGleb Smirnoff { "rule", RULE},
65373b3a8eb9SGleb Smirnoff { "ruleset-optimization", RULESET_OPTIMIZATION},
65383b3a8eb9SGleb Smirnoff { "scrub", SCRUB},
65393b3a8eb9SGleb Smirnoff { "set", SET},
65403b3a8eb9SGleb Smirnoff { "set-tos", SETTOS},
65413b3a8eb9SGleb Smirnoff { "skip", SKIP},
65423b3a8eb9SGleb Smirnoff { "sloppy", SLOPPY},
65433b3a8eb9SGleb Smirnoff { "source-hash", SOURCEHASH},
65443b3a8eb9SGleb Smirnoff { "source-track", SOURCETRACK},
65453b3a8eb9SGleb Smirnoff { "state", STATE},
65463b3a8eb9SGleb Smirnoff { "state-defaults", STATEDEFAULTS},
65473b3a8eb9SGleb Smirnoff { "state-policy", STATEPOLICY},
65483b3a8eb9SGleb Smirnoff { "static-port", STATICPORT},
65493b3a8eb9SGleb Smirnoff { "sticky-address", STICKYADDRESS},
6550c69121c4SKristof Provost { "syncookies", SYNCOOKIES},
65513b3a8eb9SGleb Smirnoff { "synproxy", SYNPROXY},
65523b3a8eb9SGleb Smirnoff { "table", TABLE},
65533b3a8eb9SGleb Smirnoff { "tag", TAG},
65543b3a8eb9SGleb Smirnoff { "tagged", TAGGED},
65550a70aaf8SLuiz Otavio O Souza { "target", TARGET},
65563b3a8eb9SGleb Smirnoff { "tbrsize", TBRSIZE},
65573b3a8eb9SGleb Smirnoff { "timeout", TIMEOUT},
65583b3a8eb9SGleb Smirnoff { "to", TO},
65593b3a8eb9SGleb Smirnoff { "tos", TOS},
65603b3a8eb9SGleb Smirnoff { "ttl", TTL},
65613b3a8eb9SGleb Smirnoff { "upperlimit", UPPERLIMIT},
65623b3a8eb9SGleb Smirnoff { "urpf-failed", URPFFAILED},
65633b3a8eb9SGleb Smirnoff { "user", USER},
65643b3a8eb9SGleb Smirnoff };
65653b3a8eb9SGleb Smirnoff const struct keywords *p;
65663b3a8eb9SGleb Smirnoff
65673b3a8eb9SGleb Smirnoff p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
65683b3a8eb9SGleb Smirnoff sizeof(keywords[0]), kw_cmp);
65693b3a8eb9SGleb Smirnoff
65703b3a8eb9SGleb Smirnoff if (p) {
65713b3a8eb9SGleb Smirnoff if (debug > 1)
65723b3a8eb9SGleb Smirnoff fprintf(stderr, "%s: %d\n", s, p->k_val);
65733b3a8eb9SGleb Smirnoff return (p->k_val);
65743b3a8eb9SGleb Smirnoff } else {
65753b3a8eb9SGleb Smirnoff if (debug > 1)
65763b3a8eb9SGleb Smirnoff fprintf(stderr, "string: %s\n", s);
65773b3a8eb9SGleb Smirnoff return (STRING);
65783b3a8eb9SGleb Smirnoff }
65793b3a8eb9SGleb Smirnoff }
65803b3a8eb9SGleb Smirnoff
65813b3a8eb9SGleb Smirnoff #define MAXPUSHBACK 128
65823b3a8eb9SGleb Smirnoff
658313cfafabSKristof Provost static char *parsebuf;
658413cfafabSKristof Provost static int parseindex;
658513cfafabSKristof Provost static char pushback_buffer[MAXPUSHBACK];
658613cfafabSKristof Provost static int pushback_index = 0;
65873b3a8eb9SGleb Smirnoff
65883b3a8eb9SGleb Smirnoff int
lgetc(int quotec)65893b3a8eb9SGleb Smirnoff lgetc(int quotec)
65903b3a8eb9SGleb Smirnoff {
65913b3a8eb9SGleb Smirnoff int c, next;
65923b3a8eb9SGleb Smirnoff
65933b3a8eb9SGleb Smirnoff if (parsebuf) {
65943b3a8eb9SGleb Smirnoff /* Read character from the parsebuffer instead of input. */
65953b3a8eb9SGleb Smirnoff if (parseindex >= 0) {
65963b3a8eb9SGleb Smirnoff c = parsebuf[parseindex++];
65973b3a8eb9SGleb Smirnoff if (c != '\0')
65983b3a8eb9SGleb Smirnoff return (c);
65993b3a8eb9SGleb Smirnoff parsebuf = NULL;
66003b3a8eb9SGleb Smirnoff } else
66013b3a8eb9SGleb Smirnoff parseindex++;
66023b3a8eb9SGleb Smirnoff }
66033b3a8eb9SGleb Smirnoff
66043b3a8eb9SGleb Smirnoff if (pushback_index)
66053b3a8eb9SGleb Smirnoff return (pushback_buffer[--pushback_index]);
66063b3a8eb9SGleb Smirnoff
66073b3a8eb9SGleb Smirnoff if (quotec) {
66083b3a8eb9SGleb Smirnoff if ((c = getc(file->stream)) == EOF) {
66093b3a8eb9SGleb Smirnoff yyerror("reached end of file while parsing quoted string");
66103b3a8eb9SGleb Smirnoff if (popfile() == EOF)
66113b3a8eb9SGleb Smirnoff return (EOF);
66123b3a8eb9SGleb Smirnoff return (quotec);
66133b3a8eb9SGleb Smirnoff }
66143b3a8eb9SGleb Smirnoff return (c);
66153b3a8eb9SGleb Smirnoff }
66163b3a8eb9SGleb Smirnoff
66173b3a8eb9SGleb Smirnoff while ((c = getc(file->stream)) == '\\') {
66183b3a8eb9SGleb Smirnoff next = getc(file->stream);
66193b3a8eb9SGleb Smirnoff if (next != '\n') {
66203b3a8eb9SGleb Smirnoff c = next;
66213b3a8eb9SGleb Smirnoff break;
66223b3a8eb9SGleb Smirnoff }
66233b3a8eb9SGleb Smirnoff yylval.lineno = file->lineno;
66243b3a8eb9SGleb Smirnoff file->lineno++;
66253b3a8eb9SGleb Smirnoff }
66263b3a8eb9SGleb Smirnoff
66273b3a8eb9SGleb Smirnoff while (c == EOF) {
66283b3a8eb9SGleb Smirnoff if (popfile() == EOF)
66293b3a8eb9SGleb Smirnoff return (EOF);
66303b3a8eb9SGleb Smirnoff c = getc(file->stream);
66313b3a8eb9SGleb Smirnoff }
66323b3a8eb9SGleb Smirnoff return (c);
66333b3a8eb9SGleb Smirnoff }
66343b3a8eb9SGleb Smirnoff
66353b3a8eb9SGleb Smirnoff int
lungetc(int c)66363b3a8eb9SGleb Smirnoff lungetc(int c)
66373b3a8eb9SGleb Smirnoff {
66383b3a8eb9SGleb Smirnoff if (c == EOF)
66393b3a8eb9SGleb Smirnoff return (EOF);
66403b3a8eb9SGleb Smirnoff if (parsebuf) {
66413b3a8eb9SGleb Smirnoff parseindex--;
66423b3a8eb9SGleb Smirnoff if (parseindex >= 0)
66433b3a8eb9SGleb Smirnoff return (c);
66443b3a8eb9SGleb Smirnoff }
66453b3a8eb9SGleb Smirnoff if (pushback_index < MAXPUSHBACK-1)
66463b3a8eb9SGleb Smirnoff return (pushback_buffer[pushback_index++] = c);
66473b3a8eb9SGleb Smirnoff else
66483b3a8eb9SGleb Smirnoff return (EOF);
66493b3a8eb9SGleb Smirnoff }
66503b3a8eb9SGleb Smirnoff
66513b3a8eb9SGleb Smirnoff int
findeol(void)66523b3a8eb9SGleb Smirnoff findeol(void)
66533b3a8eb9SGleb Smirnoff {
66543b3a8eb9SGleb Smirnoff int c;
66553b3a8eb9SGleb Smirnoff
66563b3a8eb9SGleb Smirnoff parsebuf = NULL;
66573b3a8eb9SGleb Smirnoff
66583b3a8eb9SGleb Smirnoff /* skip to either EOF or the first real EOL */
66593b3a8eb9SGleb Smirnoff while (1) {
66603b3a8eb9SGleb Smirnoff if (pushback_index)
66613b3a8eb9SGleb Smirnoff c = pushback_buffer[--pushback_index];
66623b3a8eb9SGleb Smirnoff else
66633b3a8eb9SGleb Smirnoff c = lgetc(0);
66643b3a8eb9SGleb Smirnoff if (c == '\n') {
66653b3a8eb9SGleb Smirnoff file->lineno++;
66663b3a8eb9SGleb Smirnoff break;
66673b3a8eb9SGleb Smirnoff }
66683b3a8eb9SGleb Smirnoff if (c == EOF)
66693b3a8eb9SGleb Smirnoff break;
66703b3a8eb9SGleb Smirnoff }
66713b3a8eb9SGleb Smirnoff return (ERROR);
66723b3a8eb9SGleb Smirnoff }
66733b3a8eb9SGleb Smirnoff
66743b3a8eb9SGleb Smirnoff int
yylex(void)66753b3a8eb9SGleb Smirnoff yylex(void)
66763b3a8eb9SGleb Smirnoff {
66773b3a8eb9SGleb Smirnoff char buf[8096];
66783b3a8eb9SGleb Smirnoff char *p, *val;
66793b3a8eb9SGleb Smirnoff int quotec, next, c;
66803b3a8eb9SGleb Smirnoff int token;
66813b3a8eb9SGleb Smirnoff
66823b3a8eb9SGleb Smirnoff top:
66833b3a8eb9SGleb Smirnoff p = buf;
66843b3a8eb9SGleb Smirnoff while ((c = lgetc(0)) == ' ' || c == '\t')
66853b3a8eb9SGleb Smirnoff ; /* nothing */
66863b3a8eb9SGleb Smirnoff
66873b3a8eb9SGleb Smirnoff yylval.lineno = file->lineno;
66883b3a8eb9SGleb Smirnoff if (c == '#')
66893b3a8eb9SGleb Smirnoff while ((c = lgetc(0)) != '\n' && c != EOF)
66903b3a8eb9SGleb Smirnoff ; /* nothing */
66913b3a8eb9SGleb Smirnoff if (c == '$' && parsebuf == NULL) {
66923b3a8eb9SGleb Smirnoff while (1) {
66933b3a8eb9SGleb Smirnoff if ((c = lgetc(0)) == EOF)
66943b3a8eb9SGleb Smirnoff return (0);
66953b3a8eb9SGleb Smirnoff
66963b3a8eb9SGleb Smirnoff if (p + 1 >= buf + sizeof(buf) - 1) {
66973b3a8eb9SGleb Smirnoff yyerror("string too long");
66983b3a8eb9SGleb Smirnoff return (findeol());
66993b3a8eb9SGleb Smirnoff }
67003b3a8eb9SGleb Smirnoff if (isalnum(c) || c == '_') {
67013b3a8eb9SGleb Smirnoff *p++ = (char)c;
67023b3a8eb9SGleb Smirnoff continue;
67033b3a8eb9SGleb Smirnoff }
67043b3a8eb9SGleb Smirnoff *p = '\0';
67053b3a8eb9SGleb Smirnoff lungetc(c);
67063b3a8eb9SGleb Smirnoff break;
67073b3a8eb9SGleb Smirnoff }
67083b3a8eb9SGleb Smirnoff val = symget(buf);
67093b3a8eb9SGleb Smirnoff if (val == NULL) {
67103b3a8eb9SGleb Smirnoff yyerror("macro '%s' not defined", buf);
67113b3a8eb9SGleb Smirnoff return (findeol());
67123b3a8eb9SGleb Smirnoff }
67133b3a8eb9SGleb Smirnoff parsebuf = val;
67143b3a8eb9SGleb Smirnoff parseindex = 0;
67153b3a8eb9SGleb Smirnoff goto top;
67163b3a8eb9SGleb Smirnoff }
67173b3a8eb9SGleb Smirnoff
67183b3a8eb9SGleb Smirnoff switch (c) {
67193b3a8eb9SGleb Smirnoff case '\'':
67203b3a8eb9SGleb Smirnoff case '"':
67213b3a8eb9SGleb Smirnoff quotec = c;
67223b3a8eb9SGleb Smirnoff while (1) {
67233b3a8eb9SGleb Smirnoff if ((c = lgetc(quotec)) == EOF)
67243b3a8eb9SGleb Smirnoff return (0);
67253b3a8eb9SGleb Smirnoff if (c == '\n') {
67263b3a8eb9SGleb Smirnoff file->lineno++;
67273b3a8eb9SGleb Smirnoff continue;
67283b3a8eb9SGleb Smirnoff } else if (c == '\\') {
67293b3a8eb9SGleb Smirnoff if ((next = lgetc(quotec)) == EOF)
67303b3a8eb9SGleb Smirnoff return (0);
67313b3a8eb9SGleb Smirnoff if (next == quotec || c == ' ' || c == '\t')
67323b3a8eb9SGleb Smirnoff c = next;
67334a8e4793SKristof Provost else if (next == '\n') {
67344a8e4793SKristof Provost file->lineno++;
67353b3a8eb9SGleb Smirnoff continue;
67364a8e4793SKristof Provost }
67373b3a8eb9SGleb Smirnoff else
67383b3a8eb9SGleb Smirnoff lungetc(next);
67393b3a8eb9SGleb Smirnoff } else if (c == quotec) {
67403b3a8eb9SGleb Smirnoff *p = '\0';
67413b3a8eb9SGleb Smirnoff break;
67422514ac81SKristof Provost } else if (c == '\0') {
67432514ac81SKristof Provost yyerror("syntax error");
67442514ac81SKristof Provost return (findeol());
67453b3a8eb9SGleb Smirnoff }
67463b3a8eb9SGleb Smirnoff if (p + 1 >= buf + sizeof(buf) - 1) {
67473b3a8eb9SGleb Smirnoff yyerror("string too long");
67483b3a8eb9SGleb Smirnoff return (findeol());
67493b3a8eb9SGleb Smirnoff }
67503b3a8eb9SGleb Smirnoff *p++ = (char)c;
67513b3a8eb9SGleb Smirnoff }
67523b3a8eb9SGleb Smirnoff yylval.v.string = strdup(buf);
67533b3a8eb9SGleb Smirnoff if (yylval.v.string == NULL)
67543b3a8eb9SGleb Smirnoff err(1, "yylex: strdup");
67553b3a8eb9SGleb Smirnoff return (STRING);
675680eb861dSKristof Provost case '!':
675780eb861dSKristof Provost next = lgetc(0);
675880eb861dSKristof Provost if (next == '=')
675980eb861dSKristof Provost return (NE);
676080eb861dSKristof Provost lungetc(next);
676180eb861dSKristof Provost break;
67623b3a8eb9SGleb Smirnoff case '<':
67633b3a8eb9SGleb Smirnoff next = lgetc(0);
67643b3a8eb9SGleb Smirnoff if (next == '>') {
67653b3a8eb9SGleb Smirnoff yylval.v.i = PF_OP_XRG;
67663b3a8eb9SGleb Smirnoff return (PORTBINARY);
676780eb861dSKristof Provost } else if (next == '=')
676880eb861dSKristof Provost return (LE);
67693b3a8eb9SGleb Smirnoff lungetc(next);
67703b3a8eb9SGleb Smirnoff break;
67713b3a8eb9SGleb Smirnoff case '>':
67723b3a8eb9SGleb Smirnoff next = lgetc(0);
67733b3a8eb9SGleb Smirnoff if (next == '<') {
67743b3a8eb9SGleb Smirnoff yylval.v.i = PF_OP_IRG;
67753b3a8eb9SGleb Smirnoff return (PORTBINARY);
677680eb861dSKristof Provost } else if (next == '=')
677780eb861dSKristof Provost return (GE);
67783b3a8eb9SGleb Smirnoff lungetc(next);
67793b3a8eb9SGleb Smirnoff break;
67803b3a8eb9SGleb Smirnoff case '-':
67813b3a8eb9SGleb Smirnoff next = lgetc(0);
67823b3a8eb9SGleb Smirnoff if (next == '>')
67833b3a8eb9SGleb Smirnoff return (ARROW);
67843b3a8eb9SGleb Smirnoff lungetc(next);
67853b3a8eb9SGleb Smirnoff break;
67863b3a8eb9SGleb Smirnoff }
67873b3a8eb9SGleb Smirnoff
67883b3a8eb9SGleb Smirnoff #define allowed_to_end_number(x) \
67893b3a8eb9SGleb Smirnoff (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
67903b3a8eb9SGleb Smirnoff
67913b3a8eb9SGleb Smirnoff if (c == '-' || isdigit(c)) {
67923b3a8eb9SGleb Smirnoff do {
67933b3a8eb9SGleb Smirnoff *p++ = c;
67943b3a8eb9SGleb Smirnoff if ((unsigned)(p-buf) >= sizeof(buf)) {
67953b3a8eb9SGleb Smirnoff yyerror("string too long");
67963b3a8eb9SGleb Smirnoff return (findeol());
67973b3a8eb9SGleb Smirnoff }
67983b3a8eb9SGleb Smirnoff } while ((c = lgetc(0)) != EOF && isdigit(c));
67993b3a8eb9SGleb Smirnoff lungetc(c);
68003b3a8eb9SGleb Smirnoff if (p == buf + 1 && buf[0] == '-')
68013b3a8eb9SGleb Smirnoff goto nodigits;
68023b3a8eb9SGleb Smirnoff if (c == EOF || allowed_to_end_number(c)) {
68033b3a8eb9SGleb Smirnoff const char *errstr = NULL;
68043b3a8eb9SGleb Smirnoff
68053b3a8eb9SGleb Smirnoff *p = '\0';
68063b3a8eb9SGleb Smirnoff yylval.v.number = strtonum(buf, LLONG_MIN,
68073b3a8eb9SGleb Smirnoff LLONG_MAX, &errstr);
68083b3a8eb9SGleb Smirnoff if (errstr) {
68093b3a8eb9SGleb Smirnoff yyerror("\"%s\" invalid number: %s",
68103b3a8eb9SGleb Smirnoff buf, errstr);
68113b3a8eb9SGleb Smirnoff return (findeol());
68123b3a8eb9SGleb Smirnoff }
68133b3a8eb9SGleb Smirnoff return (NUMBER);
68143b3a8eb9SGleb Smirnoff } else {
68153b3a8eb9SGleb Smirnoff nodigits:
68163b3a8eb9SGleb Smirnoff while (p > buf + 1)
68173b3a8eb9SGleb Smirnoff lungetc(*--p);
68183b3a8eb9SGleb Smirnoff c = *--p;
68193b3a8eb9SGleb Smirnoff if (c == '-')
68203b3a8eb9SGleb Smirnoff return (c);
68213b3a8eb9SGleb Smirnoff }
68223b3a8eb9SGleb Smirnoff }
68233b3a8eb9SGleb Smirnoff
68243b3a8eb9SGleb Smirnoff #define allowed_in_string(x) \
68253b3a8eb9SGleb Smirnoff (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
68263b3a8eb9SGleb Smirnoff x != '{' && x != '}' && x != '<' && x != '>' && \
68273b3a8eb9SGleb Smirnoff x != '!' && x != '=' && x != '/' && x != '#' && \
68283b3a8eb9SGleb Smirnoff x != ','))
68293b3a8eb9SGleb Smirnoff
68303b3a8eb9SGleb Smirnoff if (isalnum(c) || c == ':' || c == '_') {
68313b3a8eb9SGleb Smirnoff do {
68323b3a8eb9SGleb Smirnoff *p++ = c;
68333b3a8eb9SGleb Smirnoff if ((unsigned)(p-buf) >= sizeof(buf)) {
68343b3a8eb9SGleb Smirnoff yyerror("string too long");
68353b3a8eb9SGleb Smirnoff return (findeol());
68363b3a8eb9SGleb Smirnoff }
68373b3a8eb9SGleb Smirnoff } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
68383b3a8eb9SGleb Smirnoff lungetc(c);
68393b3a8eb9SGleb Smirnoff *p = '\0';
68403b3a8eb9SGleb Smirnoff if ((token = lookup(buf)) == STRING)
68413b3a8eb9SGleb Smirnoff if ((yylval.v.string = strdup(buf)) == NULL)
68423b3a8eb9SGleb Smirnoff err(1, "yylex: strdup");
68433b3a8eb9SGleb Smirnoff return (token);
68443b3a8eb9SGleb Smirnoff }
68453b3a8eb9SGleb Smirnoff if (c == '\n') {
68463b3a8eb9SGleb Smirnoff yylval.lineno = file->lineno;
68473b3a8eb9SGleb Smirnoff file->lineno++;
68483b3a8eb9SGleb Smirnoff }
68493b3a8eb9SGleb Smirnoff if (c == EOF)
68503b3a8eb9SGleb Smirnoff return (0);
68513b3a8eb9SGleb Smirnoff return (c);
68523b3a8eb9SGleb Smirnoff }
68533b3a8eb9SGleb Smirnoff
68543b3a8eb9SGleb Smirnoff int
check_file_secrecy(int fd,const char * fname)68553b3a8eb9SGleb Smirnoff check_file_secrecy(int fd, const char *fname)
68563b3a8eb9SGleb Smirnoff {
68573b3a8eb9SGleb Smirnoff struct stat st;
68583b3a8eb9SGleb Smirnoff
68593b3a8eb9SGleb Smirnoff if (fstat(fd, &st)) {
68603b3a8eb9SGleb Smirnoff warn("cannot stat %s", fname);
68613b3a8eb9SGleb Smirnoff return (-1);
68623b3a8eb9SGleb Smirnoff }
68633b3a8eb9SGleb Smirnoff if (st.st_uid != 0 && st.st_uid != getuid()) {
68643b3a8eb9SGleb Smirnoff warnx("%s: owner not root or current user", fname);
68653b3a8eb9SGleb Smirnoff return (-1);
68663b3a8eb9SGleb Smirnoff }
6867cba525e5SKristof Provost if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
6868cba525e5SKristof Provost warnx("%s: group writable or world read/writable", fname);
68693b3a8eb9SGleb Smirnoff return (-1);
68703b3a8eb9SGleb Smirnoff }
68713b3a8eb9SGleb Smirnoff return (0);
68723b3a8eb9SGleb Smirnoff }
68733b3a8eb9SGleb Smirnoff
68743b3a8eb9SGleb Smirnoff struct file *
pushfile(const char * name,int secret)68753b3a8eb9SGleb Smirnoff pushfile(const char *name, int secret)
68763b3a8eb9SGleb Smirnoff {
68773b3a8eb9SGleb Smirnoff struct file *nfile;
68783b3a8eb9SGleb Smirnoff
68793b3a8eb9SGleb Smirnoff if ((nfile = calloc(1, sizeof(struct file))) == NULL ||
68803b3a8eb9SGleb Smirnoff (nfile->name = strdup(name)) == NULL) {
68813b3a8eb9SGleb Smirnoff warn("malloc");
68823b3a8eb9SGleb Smirnoff return (NULL);
68833b3a8eb9SGleb Smirnoff }
68843b3a8eb9SGleb Smirnoff if (TAILQ_FIRST(&files) == NULL && strcmp(nfile->name, "-") == 0) {
68853b3a8eb9SGleb Smirnoff nfile->stream = stdin;
68863b3a8eb9SGleb Smirnoff free(nfile->name);
68873b3a8eb9SGleb Smirnoff if ((nfile->name = strdup("stdin")) == NULL) {
68883b3a8eb9SGleb Smirnoff warn("strdup");
68893b3a8eb9SGleb Smirnoff free(nfile);
68903b3a8eb9SGleb Smirnoff return (NULL);
68913b3a8eb9SGleb Smirnoff }
68923b3a8eb9SGleb Smirnoff } else if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
68933b3a8eb9SGleb Smirnoff warn("%s", nfile->name);
68943b3a8eb9SGleb Smirnoff free(nfile->name);
68953b3a8eb9SGleb Smirnoff free(nfile);
68963b3a8eb9SGleb Smirnoff return (NULL);
68973b3a8eb9SGleb Smirnoff } else if (secret &&
68983b3a8eb9SGleb Smirnoff check_file_secrecy(fileno(nfile->stream), nfile->name)) {
68993b3a8eb9SGleb Smirnoff fclose(nfile->stream);
69003b3a8eb9SGleb Smirnoff free(nfile->name);
69013b3a8eb9SGleb Smirnoff free(nfile);
69023b3a8eb9SGleb Smirnoff return (NULL);
69033b3a8eb9SGleb Smirnoff }
69043b3a8eb9SGleb Smirnoff nfile->lineno = 1;
69053b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(&files, nfile, entry);
69063b3a8eb9SGleb Smirnoff return (nfile);
69073b3a8eb9SGleb Smirnoff }
69083b3a8eb9SGleb Smirnoff
69093b3a8eb9SGleb Smirnoff int
popfile(void)69103b3a8eb9SGleb Smirnoff popfile(void)
69113b3a8eb9SGleb Smirnoff {
69123b3a8eb9SGleb Smirnoff struct file *prev;
69133b3a8eb9SGleb Smirnoff
69143b3a8eb9SGleb Smirnoff if ((prev = TAILQ_PREV(file, files, entry)) != NULL) {
69153b3a8eb9SGleb Smirnoff prev->errors += file->errors;
69163b3a8eb9SGleb Smirnoff TAILQ_REMOVE(&files, file, entry);
69173b3a8eb9SGleb Smirnoff fclose(file->stream);
69183b3a8eb9SGleb Smirnoff free(file->name);
69193b3a8eb9SGleb Smirnoff free(file);
69203b3a8eb9SGleb Smirnoff file = prev;
69213b3a8eb9SGleb Smirnoff return (0);
69223b3a8eb9SGleb Smirnoff }
69233b3a8eb9SGleb Smirnoff return (EOF);
69243b3a8eb9SGleb Smirnoff }
69253b3a8eb9SGleb Smirnoff
69263b3a8eb9SGleb Smirnoff int
parse_config(char * filename,struct pfctl * xpf)69273b3a8eb9SGleb Smirnoff parse_config(char *filename, struct pfctl *xpf)
69283b3a8eb9SGleb Smirnoff {
69293b3a8eb9SGleb Smirnoff int errors = 0;
69303b3a8eb9SGleb Smirnoff struct sym *sym;
69313b3a8eb9SGleb Smirnoff
69323b3a8eb9SGleb Smirnoff pf = xpf;
69333b3a8eb9SGleb Smirnoff errors = 0;
69343b3a8eb9SGleb Smirnoff rulestate = PFCTL_STATE_NONE;
69353b3a8eb9SGleb Smirnoff returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT;
69363b3a8eb9SGleb Smirnoff returnicmp6default =
69373b3a8eb9SGleb Smirnoff (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT;
69383b3a8eb9SGleb Smirnoff blockpolicy = PFRULE_DROP;
6939150182e3SKristof Provost failpolicy = PFRULE_DROP;
69403b3a8eb9SGleb Smirnoff require_order = 1;
69413b3a8eb9SGleb Smirnoff
69423b3a8eb9SGleb Smirnoff if ((file = pushfile(filename, 0)) == NULL) {
69433b3a8eb9SGleb Smirnoff warn("cannot open the main config file!");
69443b3a8eb9SGleb Smirnoff return (-1);
69453b3a8eb9SGleb Smirnoff }
69463b3a8eb9SGleb Smirnoff
69473b3a8eb9SGleb Smirnoff yyparse();
69483b3a8eb9SGleb Smirnoff errors = file->errors;
69493b3a8eb9SGleb Smirnoff popfile();
69503b3a8eb9SGleb Smirnoff
69513b3a8eb9SGleb Smirnoff /* Free macros and check which have not been used. */
69523b3a8eb9SGleb Smirnoff while ((sym = TAILQ_FIRST(&symhead))) {
69533b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used)
69543b3a8eb9SGleb Smirnoff fprintf(stderr, "warning: macro '%s' not "
69553b3a8eb9SGleb Smirnoff "used\n", sym->nam);
69563b3a8eb9SGleb Smirnoff free(sym->nam);
69573b3a8eb9SGleb Smirnoff free(sym->val);
69583b3a8eb9SGleb Smirnoff TAILQ_REMOVE(&symhead, sym, entry);
69593b3a8eb9SGleb Smirnoff free(sym);
69603b3a8eb9SGleb Smirnoff }
69613b3a8eb9SGleb Smirnoff
69623b3a8eb9SGleb Smirnoff return (errors ? -1 : 0);
69633b3a8eb9SGleb Smirnoff }
69643b3a8eb9SGleb Smirnoff
69653b3a8eb9SGleb Smirnoff int
symset(const char * nam,const char * val,int persist)69663b3a8eb9SGleb Smirnoff symset(const char *nam, const char *val, int persist)
69673b3a8eb9SGleb Smirnoff {
69683b3a8eb9SGleb Smirnoff struct sym *sym;
69693b3a8eb9SGleb Smirnoff
69703b3a8eb9SGleb Smirnoff for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
69713b3a8eb9SGleb Smirnoff sym = TAILQ_NEXT(sym, entry))
69723b3a8eb9SGleb Smirnoff ; /* nothing */
69733b3a8eb9SGleb Smirnoff
69743b3a8eb9SGleb Smirnoff if (sym != NULL) {
69753b3a8eb9SGleb Smirnoff if (sym->persist == 1)
69763b3a8eb9SGleb Smirnoff return (0);
69773b3a8eb9SGleb Smirnoff else {
69783b3a8eb9SGleb Smirnoff free(sym->nam);
69793b3a8eb9SGleb Smirnoff free(sym->val);
69803b3a8eb9SGleb Smirnoff TAILQ_REMOVE(&symhead, sym, entry);
69813b3a8eb9SGleb Smirnoff free(sym);
69823b3a8eb9SGleb Smirnoff }
69833b3a8eb9SGleb Smirnoff }
69843b3a8eb9SGleb Smirnoff if ((sym = calloc(1, sizeof(*sym))) == NULL)
69853b3a8eb9SGleb Smirnoff return (-1);
69863b3a8eb9SGleb Smirnoff
69873b3a8eb9SGleb Smirnoff sym->nam = strdup(nam);
69883b3a8eb9SGleb Smirnoff if (sym->nam == NULL) {
69893b3a8eb9SGleb Smirnoff free(sym);
69903b3a8eb9SGleb Smirnoff return (-1);
69913b3a8eb9SGleb Smirnoff }
69923b3a8eb9SGleb Smirnoff sym->val = strdup(val);
69933b3a8eb9SGleb Smirnoff if (sym->val == NULL) {
69943b3a8eb9SGleb Smirnoff free(sym->nam);
69953b3a8eb9SGleb Smirnoff free(sym);
69963b3a8eb9SGleb Smirnoff return (-1);
69973b3a8eb9SGleb Smirnoff }
69983b3a8eb9SGleb Smirnoff sym->used = 0;
69993b3a8eb9SGleb Smirnoff sym->persist = persist;
70003b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(&symhead, sym, entry);
70013b3a8eb9SGleb Smirnoff return (0);
70023b3a8eb9SGleb Smirnoff }
70033b3a8eb9SGleb Smirnoff
70043b3a8eb9SGleb Smirnoff int
pfctl_cmdline_symset(char * s)70053b3a8eb9SGleb Smirnoff pfctl_cmdline_symset(char *s)
70063b3a8eb9SGleb Smirnoff {
70073b3a8eb9SGleb Smirnoff char *sym, *val;
70083b3a8eb9SGleb Smirnoff int ret;
70093b3a8eb9SGleb Smirnoff
70103b3a8eb9SGleb Smirnoff if ((val = strrchr(s, '=')) == NULL)
70113b3a8eb9SGleb Smirnoff return (-1);
70123b3a8eb9SGleb Smirnoff
70133b3a8eb9SGleb Smirnoff if ((sym = malloc(strlen(s) - strlen(val) + 1)) == NULL)
70143b3a8eb9SGleb Smirnoff err(1, "pfctl_cmdline_symset: malloc");
70153b3a8eb9SGleb Smirnoff
70163b3a8eb9SGleb Smirnoff strlcpy(sym, s, strlen(s) - strlen(val) + 1);
70173b3a8eb9SGleb Smirnoff
70183b3a8eb9SGleb Smirnoff ret = symset(sym, val + 1, 1);
70193b3a8eb9SGleb Smirnoff free(sym);
70203b3a8eb9SGleb Smirnoff
70213b3a8eb9SGleb Smirnoff return (ret);
70223b3a8eb9SGleb Smirnoff }
70233b3a8eb9SGleb Smirnoff
70243b3a8eb9SGleb Smirnoff char *
symget(const char * nam)70253b3a8eb9SGleb Smirnoff symget(const char *nam)
70263b3a8eb9SGleb Smirnoff {
70273b3a8eb9SGleb Smirnoff struct sym *sym;
70283b3a8eb9SGleb Smirnoff
70293b3a8eb9SGleb Smirnoff TAILQ_FOREACH(sym, &symhead, entry)
70303b3a8eb9SGleb Smirnoff if (strcmp(nam, sym->nam) == 0) {
70313b3a8eb9SGleb Smirnoff sym->used = 1;
70323b3a8eb9SGleb Smirnoff return (sym->val);
70333b3a8eb9SGleb Smirnoff }
70343b3a8eb9SGleb Smirnoff return (NULL);
70353b3a8eb9SGleb Smirnoff }
70363b3a8eb9SGleb Smirnoff
70373b3a8eb9SGleb Smirnoff void
mv_rules(struct pfctl_ruleset * src,struct pfctl_ruleset * dst)7038e9eb0941SKristof Provost mv_rules(struct pfctl_ruleset *src, struct pfctl_ruleset *dst)
70393b3a8eb9SGleb Smirnoff {
70403b3a8eb9SGleb Smirnoff int i;
7041e9eb0941SKristof Provost struct pfctl_rule *r;
70423b3a8eb9SGleb Smirnoff
70433b3a8eb9SGleb Smirnoff for (i = 0; i < PF_RULESET_MAX; ++i) {
70443b3a8eb9SGleb Smirnoff while ((r = TAILQ_FIRST(src->rules[i].active.ptr))
70453b3a8eb9SGleb Smirnoff != NULL) {
70463b3a8eb9SGleb Smirnoff TAILQ_REMOVE(src->rules[i].active.ptr, r, entries);
70473b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(dst->rules[i].active.ptr, r, entries);
70483b3a8eb9SGleb Smirnoff dst->anchor->match++;
70493b3a8eb9SGleb Smirnoff }
70503b3a8eb9SGleb Smirnoff src->anchor->match = 0;
70513b3a8eb9SGleb Smirnoff while ((r = TAILQ_FIRST(src->rules[i].inactive.ptr))
70523b3a8eb9SGleb Smirnoff != NULL) {
70533b3a8eb9SGleb Smirnoff TAILQ_REMOVE(src->rules[i].inactive.ptr, r, entries);
70543b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(dst->rules[i].inactive.ptr,
70553b3a8eb9SGleb Smirnoff r, entries);
70563b3a8eb9SGleb Smirnoff }
70573b3a8eb9SGleb Smirnoff }
70583b3a8eb9SGleb Smirnoff }
70593b3a8eb9SGleb Smirnoff
70603b3a8eb9SGleb Smirnoff void
mv_eth_rules(struct pfctl_eth_ruleset * src,struct pfctl_eth_ruleset * dst)7061c5131afeSKristof Provost mv_eth_rules(struct pfctl_eth_ruleset *src, struct pfctl_eth_ruleset *dst)
7062c5131afeSKristof Provost {
7063c5131afeSKristof Provost struct pfctl_eth_rule *r;
7064c5131afeSKristof Provost
7065c5131afeSKristof Provost while ((r = TAILQ_FIRST(&src->rules)) != NULL) {
7066c5131afeSKristof Provost TAILQ_REMOVE(&src->rules, r, entries);
7067c5131afeSKristof Provost TAILQ_INSERT_TAIL(&dst->rules, r, entries);
7068c5131afeSKristof Provost dst->anchor->match++;
7069c5131afeSKristof Provost }
7070c5131afeSKristof Provost src->anchor->match = 0;
7071c5131afeSKristof Provost }
7072c5131afeSKristof Provost
7073c5131afeSKristof Provost void
decide_address_family(struct node_host * n,sa_family_t * af)70743b3a8eb9SGleb Smirnoff decide_address_family(struct node_host *n, sa_family_t *af)
70753b3a8eb9SGleb Smirnoff {
70763b3a8eb9SGleb Smirnoff if (*af != 0 || n == NULL)
70773b3a8eb9SGleb Smirnoff return;
70783b3a8eb9SGleb Smirnoff *af = n->af;
70793b3a8eb9SGleb Smirnoff while ((n = n->next) != NULL) {
70803b3a8eb9SGleb Smirnoff if (n->af != *af) {
70813b3a8eb9SGleb Smirnoff *af = 0;
70823b3a8eb9SGleb Smirnoff return;
70833b3a8eb9SGleb Smirnoff }
70843b3a8eb9SGleb Smirnoff }
70853b3a8eb9SGleb Smirnoff }
70863b3a8eb9SGleb Smirnoff
70873b3a8eb9SGleb Smirnoff void
remove_invalid_hosts(struct node_host ** nh,sa_family_t * af)70883b3a8eb9SGleb Smirnoff remove_invalid_hosts(struct node_host **nh, sa_family_t *af)
70893b3a8eb9SGleb Smirnoff {
70903b3a8eb9SGleb Smirnoff struct node_host *n = *nh, *prev = NULL;
70913b3a8eb9SGleb Smirnoff
70923b3a8eb9SGleb Smirnoff while (n != NULL) {
70933b3a8eb9SGleb Smirnoff if (*af && n->af && n->af != *af) {
70943b3a8eb9SGleb Smirnoff /* unlink and free n */
70953b3a8eb9SGleb Smirnoff struct node_host *next = n->next;
70963b3a8eb9SGleb Smirnoff
70973b3a8eb9SGleb Smirnoff /* adjust tail pointer */
70983b3a8eb9SGleb Smirnoff if (n == (*nh)->tail)
70993b3a8eb9SGleb Smirnoff (*nh)->tail = prev;
71003b3a8eb9SGleb Smirnoff /* adjust previous node's next pointer */
71013b3a8eb9SGleb Smirnoff if (prev == NULL)
71023b3a8eb9SGleb Smirnoff *nh = next;
71033b3a8eb9SGleb Smirnoff else
71043b3a8eb9SGleb Smirnoff prev->next = next;
71053b3a8eb9SGleb Smirnoff /* free node */
71063b3a8eb9SGleb Smirnoff if (n->ifname != NULL)
71073b3a8eb9SGleb Smirnoff free(n->ifname);
71083b3a8eb9SGleb Smirnoff free(n);
71093b3a8eb9SGleb Smirnoff n = next;
71103b3a8eb9SGleb Smirnoff } else {
71113b3a8eb9SGleb Smirnoff if (n->af && !*af)
71123b3a8eb9SGleb Smirnoff *af = n->af;
71133b3a8eb9SGleb Smirnoff prev = n;
71143b3a8eb9SGleb Smirnoff n = n->next;
71153b3a8eb9SGleb Smirnoff }
71163b3a8eb9SGleb Smirnoff }
71173b3a8eb9SGleb Smirnoff }
71183b3a8eb9SGleb Smirnoff
71193b3a8eb9SGleb Smirnoff int
invalid_redirect(struct node_host * nh,sa_family_t af)71203b3a8eb9SGleb Smirnoff invalid_redirect(struct node_host *nh, sa_family_t af)
71213b3a8eb9SGleb Smirnoff {
71223b3a8eb9SGleb Smirnoff if (!af) {
71233b3a8eb9SGleb Smirnoff struct node_host *n;
71243b3a8eb9SGleb Smirnoff
71253b3a8eb9SGleb Smirnoff /* tables and dyniftl are ok without an address family */
71263b3a8eb9SGleb Smirnoff for (n = nh; n != NULL; n = n->next) {
71273b3a8eb9SGleb Smirnoff if (n->addr.type != PF_ADDR_TABLE &&
71283b3a8eb9SGleb Smirnoff n->addr.type != PF_ADDR_DYNIFTL) {
71293b3a8eb9SGleb Smirnoff yyerror("address family not given and "
71303b3a8eb9SGleb Smirnoff "translation address expands to multiple "
71313b3a8eb9SGleb Smirnoff "address families");
71323b3a8eb9SGleb Smirnoff return (1);
71333b3a8eb9SGleb Smirnoff }
71343b3a8eb9SGleb Smirnoff }
71353b3a8eb9SGleb Smirnoff }
71363b3a8eb9SGleb Smirnoff if (nh == NULL) {
71373b3a8eb9SGleb Smirnoff yyerror("no translation address with matching address family "
71383b3a8eb9SGleb Smirnoff "found.");
71393b3a8eb9SGleb Smirnoff return (1);
71403b3a8eb9SGleb Smirnoff }
71413b3a8eb9SGleb Smirnoff return (0);
71423b3a8eb9SGleb Smirnoff }
71433b3a8eb9SGleb Smirnoff
71443b3a8eb9SGleb Smirnoff int
atoul(char * s,u_long * ulvalp)71453b3a8eb9SGleb Smirnoff atoul(char *s, u_long *ulvalp)
71463b3a8eb9SGleb Smirnoff {
71473b3a8eb9SGleb Smirnoff u_long ulval;
71483b3a8eb9SGleb Smirnoff char *ep;
71493b3a8eb9SGleb Smirnoff
71503b3a8eb9SGleb Smirnoff errno = 0;
71513b3a8eb9SGleb Smirnoff ulval = strtoul(s, &ep, 0);
71523b3a8eb9SGleb Smirnoff if (s[0] == '\0' || *ep != '\0')
71533b3a8eb9SGleb Smirnoff return (-1);
71543b3a8eb9SGleb Smirnoff if (errno == ERANGE && ulval == ULONG_MAX)
71553b3a8eb9SGleb Smirnoff return (-1);
71563b3a8eb9SGleb Smirnoff *ulvalp = ulval;
71573b3a8eb9SGleb Smirnoff return (0);
71583b3a8eb9SGleb Smirnoff }
71593b3a8eb9SGleb Smirnoff
71603b3a8eb9SGleb Smirnoff int
getservice(char * n)71613b3a8eb9SGleb Smirnoff getservice(char *n)
71623b3a8eb9SGleb Smirnoff {
71633b3a8eb9SGleb Smirnoff struct servent *s;
71643b3a8eb9SGleb Smirnoff u_long ulval;
71653b3a8eb9SGleb Smirnoff
71663b3a8eb9SGleb Smirnoff if (atoul(n, &ulval) == 0) {
71673b3a8eb9SGleb Smirnoff if (ulval > 65535) {
71683b3a8eb9SGleb Smirnoff yyerror("illegal port value %lu", ulval);
71693b3a8eb9SGleb Smirnoff return (-1);
71703b3a8eb9SGleb Smirnoff }
71713b3a8eb9SGleb Smirnoff return (htons(ulval));
71723b3a8eb9SGleb Smirnoff } else {
71733b3a8eb9SGleb Smirnoff s = getservbyname(n, "tcp");
71743b3a8eb9SGleb Smirnoff if (s == NULL)
71753b3a8eb9SGleb Smirnoff s = getservbyname(n, "udp");
71760bd4a683SKristof Provost if (s == NULL)
71770bd4a683SKristof Provost s = getservbyname(n, "sctp");
71783b3a8eb9SGleb Smirnoff if (s == NULL) {
71793b3a8eb9SGleb Smirnoff yyerror("unknown port %s", n);
71803b3a8eb9SGleb Smirnoff return (-1);
71813b3a8eb9SGleb Smirnoff }
71823b3a8eb9SGleb Smirnoff return (s->s_port);
71833b3a8eb9SGleb Smirnoff }
71843b3a8eb9SGleb Smirnoff }
71853b3a8eb9SGleb Smirnoff
71863b3a8eb9SGleb Smirnoff int
rule_label(struct pfctl_rule * r,char * s[PF_RULE_MAX_LABEL_COUNT])71876fcc8e04SKristof Provost rule_label(struct pfctl_rule *r, char *s[PF_RULE_MAX_LABEL_COUNT])
71883b3a8eb9SGleb Smirnoff {
71896fcc8e04SKristof Provost for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
71906fcc8e04SKristof Provost if (s[i] == NULL)
71916fcc8e04SKristof Provost return (0);
71926fcc8e04SKristof Provost
71936fcc8e04SKristof Provost if (strlcpy(r->label[i], s[i], sizeof(r->label[0])) >=
71946fcc8e04SKristof Provost sizeof(r->label[0])) {
71953b3a8eb9SGleb Smirnoff yyerror("rule label too long (max %d chars)",
71966fcc8e04SKristof Provost sizeof(r->label[0])-1);
71973b3a8eb9SGleb Smirnoff return (-1);
71983b3a8eb9SGleb Smirnoff }
71993b3a8eb9SGleb Smirnoff }
72003b3a8eb9SGleb Smirnoff return (0);
72013b3a8eb9SGleb Smirnoff }
72023b3a8eb9SGleb Smirnoff
7203ef661d4aSChristian McDonald int
eth_rule_label(struct pfctl_eth_rule * r,char * s[PF_RULE_MAX_LABEL_COUNT])7204ef661d4aSChristian McDonald eth_rule_label(struct pfctl_eth_rule *r, char *s[PF_RULE_MAX_LABEL_COUNT])
7205ef661d4aSChristian McDonald {
7206ef661d4aSChristian McDonald for (int i = 0; i < PF_RULE_MAX_LABEL_COUNT; i++) {
7207ef661d4aSChristian McDonald if (s[i] == NULL)
7208ef661d4aSChristian McDonald return (0);
7209ef661d4aSChristian McDonald
7210ef661d4aSChristian McDonald if (strlcpy(r->label[i], s[i], sizeof(r->label[0])) >=
7211ef661d4aSChristian McDonald sizeof(r->label[0])) {
7212ef661d4aSChristian McDonald yyerror("rule label too long (max %d chars)",
7213ef661d4aSChristian McDonald sizeof(r->label[0])-1);
7214ef661d4aSChristian McDonald return (-1);
7215ef661d4aSChristian McDonald }
7216ef661d4aSChristian McDonald }
7217ef661d4aSChristian McDonald return (0);
7218ef661d4aSChristian McDonald }
7219ef661d4aSChristian McDonald
72203b3a8eb9SGleb Smirnoff u_int16_t
parseicmpspec(char * w,sa_family_t af)72213b3a8eb9SGleb Smirnoff parseicmpspec(char *w, sa_family_t af)
72223b3a8eb9SGleb Smirnoff {
72233b3a8eb9SGleb Smirnoff const struct icmpcodeent *p;
72243b3a8eb9SGleb Smirnoff u_long ulval;
72253b3a8eb9SGleb Smirnoff u_int8_t icmptype;
72263b3a8eb9SGleb Smirnoff
72273b3a8eb9SGleb Smirnoff if (af == AF_INET)
72283b3a8eb9SGleb Smirnoff icmptype = returnicmpdefault >> 8;
72293b3a8eb9SGleb Smirnoff else
72303b3a8eb9SGleb Smirnoff icmptype = returnicmp6default >> 8;
72313b3a8eb9SGleb Smirnoff
72323b3a8eb9SGleb Smirnoff if (atoul(w, &ulval) == -1) {
72333b3a8eb9SGleb Smirnoff if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) {
72343b3a8eb9SGleb Smirnoff yyerror("unknown icmp code %s", w);
72353b3a8eb9SGleb Smirnoff return (0);
72363b3a8eb9SGleb Smirnoff }
72373b3a8eb9SGleb Smirnoff ulval = p->code;
72383b3a8eb9SGleb Smirnoff }
72393b3a8eb9SGleb Smirnoff if (ulval > 255) {
72403b3a8eb9SGleb Smirnoff yyerror("invalid icmp code %lu", ulval);
72413b3a8eb9SGleb Smirnoff return (0);
72423b3a8eb9SGleb Smirnoff }
72433b3a8eb9SGleb Smirnoff return (icmptype << 8 | ulval);
72443b3a8eb9SGleb Smirnoff }
72453b3a8eb9SGleb Smirnoff
72463b3a8eb9SGleb Smirnoff int
parseport(char * port,struct range * r,int extensions)72473b3a8eb9SGleb Smirnoff parseport(char *port, struct range *r, int extensions)
72483b3a8eb9SGleb Smirnoff {
72493b3a8eb9SGleb Smirnoff char *p = strchr(port, ':');
72503b3a8eb9SGleb Smirnoff
72513b3a8eb9SGleb Smirnoff if (p == NULL) {
72523b3a8eb9SGleb Smirnoff if ((r->a = getservice(port)) == -1)
72533b3a8eb9SGleb Smirnoff return (-1);
72543b3a8eb9SGleb Smirnoff r->b = 0;
72553b3a8eb9SGleb Smirnoff r->t = PF_OP_NONE;
72563b3a8eb9SGleb Smirnoff return (0);
72573b3a8eb9SGleb Smirnoff }
72583b3a8eb9SGleb Smirnoff if ((extensions & PPORT_STAR) && !strcmp(p+1, "*")) {
72593b3a8eb9SGleb Smirnoff *p = 0;
72603b3a8eb9SGleb Smirnoff if ((r->a = getservice(port)) == -1)
72613b3a8eb9SGleb Smirnoff return (-1);
72623b3a8eb9SGleb Smirnoff r->b = 0;
72633b3a8eb9SGleb Smirnoff r->t = PF_OP_IRG;
72643b3a8eb9SGleb Smirnoff return (0);
72653b3a8eb9SGleb Smirnoff }
72663b3a8eb9SGleb Smirnoff if ((extensions & PPORT_RANGE)) {
72673b3a8eb9SGleb Smirnoff *p++ = 0;
72683b3a8eb9SGleb Smirnoff if ((r->a = getservice(port)) == -1 ||
72693b3a8eb9SGleb Smirnoff (r->b = getservice(p)) == -1)
72703b3a8eb9SGleb Smirnoff return (-1);
72713b3a8eb9SGleb Smirnoff if (r->a == r->b) {
72723b3a8eb9SGleb Smirnoff r->b = 0;
72733b3a8eb9SGleb Smirnoff r->t = PF_OP_NONE;
72743b3a8eb9SGleb Smirnoff } else
72753b3a8eb9SGleb Smirnoff r->t = PF_OP_RRG;
72763b3a8eb9SGleb Smirnoff return (0);
72773b3a8eb9SGleb Smirnoff }
72783b3a8eb9SGleb Smirnoff return (-1);
72793b3a8eb9SGleb Smirnoff }
72803b3a8eb9SGleb Smirnoff
72813b3a8eb9SGleb Smirnoff int
pfctl_load_anchors(int dev,struct pfctl * pf,struct pfr_buffer * trans)72823b3a8eb9SGleb Smirnoff pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans)
72833b3a8eb9SGleb Smirnoff {
72843b3a8eb9SGleb Smirnoff struct loadanchors *la;
72853b3a8eb9SGleb Smirnoff
72863b3a8eb9SGleb Smirnoff TAILQ_FOREACH(la, &loadanchorshead, entries) {
72873b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE)
72883b3a8eb9SGleb Smirnoff fprintf(stderr, "\nLoading anchor %s from %s\n",
72893b3a8eb9SGleb Smirnoff la->anchorname, la->filename);
72903b3a8eb9SGleb Smirnoff if (pfctl_rules(dev, la->filename, pf->opts, pf->optimize,
72913b3a8eb9SGleb Smirnoff la->anchorname, trans) == -1)
72923b3a8eb9SGleb Smirnoff return (-1);
72933b3a8eb9SGleb Smirnoff }
72943b3a8eb9SGleb Smirnoff
72953b3a8eb9SGleb Smirnoff return (0);
72963b3a8eb9SGleb Smirnoff }
72973b3a8eb9SGleb Smirnoff
72983b3a8eb9SGleb Smirnoff int
kw_casecmp(const void * k,const void * e)72991f495578SKristof Provost kw_casecmp(const void *k, const void *e)
73001f495578SKristof Provost {
73011f495578SKristof Provost return (strcasecmp(k, ((const struct keywords *)e)->k_name));
73021f495578SKristof Provost }
73031f495578SKristof Provost
73041f495578SKristof Provost int
map_tos(char * s,int * val)73051f495578SKristof Provost map_tos(char *s, int *val)
73061f495578SKristof Provost {
73071f495578SKristof Provost /* DiffServ Codepoints and other TOS mappings */
73081f495578SKristof Provost const struct keywords toswords[] = {
73091f495578SKristof Provost { "af11", IPTOS_DSCP_AF11 },
73101f495578SKristof Provost { "af12", IPTOS_DSCP_AF12 },
73111f495578SKristof Provost { "af13", IPTOS_DSCP_AF13 },
73121f495578SKristof Provost { "af21", IPTOS_DSCP_AF21 },
73131f495578SKristof Provost { "af22", IPTOS_DSCP_AF22 },
73141f495578SKristof Provost { "af23", IPTOS_DSCP_AF23 },
73151f495578SKristof Provost { "af31", IPTOS_DSCP_AF31 },
73161f495578SKristof Provost { "af32", IPTOS_DSCP_AF32 },
73171f495578SKristof Provost { "af33", IPTOS_DSCP_AF33 },
73181f495578SKristof Provost { "af41", IPTOS_DSCP_AF41 },
73191f495578SKristof Provost { "af42", IPTOS_DSCP_AF42 },
73201f495578SKristof Provost { "af43", IPTOS_DSCP_AF43 },
73211f495578SKristof Provost { "critical", IPTOS_PREC_CRITIC_ECP },
73221f495578SKristof Provost { "cs0", IPTOS_DSCP_CS0 },
73231f495578SKristof Provost { "cs1", IPTOS_DSCP_CS1 },
73241f495578SKristof Provost { "cs2", IPTOS_DSCP_CS2 },
73251f495578SKristof Provost { "cs3", IPTOS_DSCP_CS3 },
73261f495578SKristof Provost { "cs4", IPTOS_DSCP_CS4 },
73271f495578SKristof Provost { "cs5", IPTOS_DSCP_CS5 },
73281f495578SKristof Provost { "cs6", IPTOS_DSCP_CS6 },
73291f495578SKristof Provost { "cs7", IPTOS_DSCP_CS7 },
73301f495578SKristof Provost { "ef", IPTOS_DSCP_EF },
73311f495578SKristof Provost { "inetcontrol", IPTOS_PREC_INTERNETCONTROL },
73321f495578SKristof Provost { "lowdelay", IPTOS_LOWDELAY },
73331f495578SKristof Provost { "netcontrol", IPTOS_PREC_NETCONTROL },
73341f495578SKristof Provost { "reliability", IPTOS_RELIABILITY },
7335b4e3f3c2SKristof Provost { "throughput", IPTOS_THROUGHPUT },
7336b4e3f3c2SKristof Provost { "va", IPTOS_DSCP_VA }
73371f495578SKristof Provost };
73381f495578SKristof Provost const struct keywords *p;
73391f495578SKristof Provost
73401f495578SKristof Provost p = bsearch(s, toswords, sizeof(toswords)/sizeof(toswords[0]),
73411f495578SKristof Provost sizeof(toswords[0]), kw_casecmp);
73421f495578SKristof Provost
73431f495578SKristof Provost if (p) {
73441f495578SKristof Provost *val = p->k_val;
73451f495578SKristof Provost return (1);
73461f495578SKristof Provost }
73471f495578SKristof Provost return (0);
73481f495578SKristof Provost }
73491f495578SKristof Provost
73501f495578SKristof Provost int
rt_tableid_max(void)73513b3a8eb9SGleb Smirnoff rt_tableid_max(void)
73523b3a8eb9SGleb Smirnoff {
73533b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__
73543b3a8eb9SGleb Smirnoff int fibs;
73553b3a8eb9SGleb Smirnoff size_t l = sizeof(fibs);
73563b3a8eb9SGleb Smirnoff
73573b3a8eb9SGleb Smirnoff if (sysctlbyname("net.fibs", &fibs, &l, NULL, 0) == -1)
73583b3a8eb9SGleb Smirnoff fibs = 16; /* XXX RT_MAXFIBS, at least limit it some. */
73593b3a8eb9SGleb Smirnoff /*
73603b3a8eb9SGleb Smirnoff * As the OpenBSD code only compares > and not >= we need to adjust
73613b3a8eb9SGleb Smirnoff * here given we only accept values of 0..n and want to avoid #ifdefs
7362b68ac800SPedro F. Giffuni * in the grammar.
73633b3a8eb9SGleb Smirnoff */
73643b3a8eb9SGleb Smirnoff return (fibs - 1);
73653b3a8eb9SGleb Smirnoff #else
73663b3a8eb9SGleb Smirnoff return (RT_TABLEID_MAX);
73673b3a8eb9SGleb Smirnoff #endif
73683b3a8eb9SGleb Smirnoff }
7369b590f17aSKristof Provost
7370b590f17aSKristof Provost struct node_mac*
node_mac_from_string(const char * str)7371b590f17aSKristof Provost node_mac_from_string(const char *str)
7372b590f17aSKristof Provost {
7373b590f17aSKristof Provost struct node_mac *m;
7374b590f17aSKristof Provost
7375b590f17aSKristof Provost m = calloc(1, sizeof(struct node_mac));
7376b590f17aSKristof Provost if (m == NULL)
7377b590f17aSKristof Provost err(1, "mac: calloc");
7378b590f17aSKristof Provost
7379b590f17aSKristof Provost if (sscanf(str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
7380b590f17aSKristof Provost &m->mac[0], &m->mac[1], &m->mac[2], &m->mac[3], &m->mac[4],
7381b590f17aSKristof Provost &m->mac[5]) != 6) {
7382b590f17aSKristof Provost free(m);
7383b590f17aSKristof Provost yyerror("invalid MAC address");
7384b590f17aSKristof Provost return (NULL);
7385b590f17aSKristof Provost }
7386b590f17aSKristof Provost
7387b590f17aSKristof Provost memset(m->mask, 0xff, ETHER_ADDR_LEN);
7388c32cd180SKristof Provost m->isset = true;
7389b590f17aSKristof Provost m->next = NULL;
7390b590f17aSKristof Provost m->tail = m;
7391b590f17aSKristof Provost
7392b590f17aSKristof Provost return (m);
7393b590f17aSKristof Provost }
7394b590f17aSKristof Provost
7395b590f17aSKristof Provost struct node_mac*
node_mac_from_string_masklen(const char * str,int masklen)7396b590f17aSKristof Provost node_mac_from_string_masklen(const char *str, int masklen)
7397b590f17aSKristof Provost {
7398b590f17aSKristof Provost struct node_mac *m;
7399b590f17aSKristof Provost
7400b590f17aSKristof Provost if (masklen < 0 || masklen > (ETHER_ADDR_LEN * 8)) {
7401b590f17aSKristof Provost yyerror("invalid MAC mask length");
7402b590f17aSKristof Provost return (NULL);
7403b590f17aSKristof Provost }
7404b590f17aSKristof Provost
7405b590f17aSKristof Provost m = node_mac_from_string(str);
7406b590f17aSKristof Provost if (m == NULL)
7407b590f17aSKristof Provost return (NULL);
7408b590f17aSKristof Provost
7409b590f17aSKristof Provost memset(m->mask, 0, ETHER_ADDR_LEN);
7410b590f17aSKristof Provost for (int i = 0; i < masklen; i++)
7411b590f17aSKristof Provost m->mask[i / 8] |= 1 << (i % 8);
7412b590f17aSKristof Provost
7413b590f17aSKristof Provost return (m);
7414b590f17aSKristof Provost }
7415b590f17aSKristof Provost
7416b590f17aSKristof Provost struct node_mac*
node_mac_from_string_mask(const char * str,const char * mask)7417b590f17aSKristof Provost node_mac_from_string_mask(const char *str, const char *mask)
7418b590f17aSKristof Provost {
7419b590f17aSKristof Provost struct node_mac *m;
7420b590f17aSKristof Provost
7421b590f17aSKristof Provost m = node_mac_from_string(str);
7422b590f17aSKristof Provost if (m == NULL)
7423b590f17aSKristof Provost return (NULL);
7424b590f17aSKristof Provost
7425b590f17aSKristof Provost if (sscanf(mask, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
7426b590f17aSKristof Provost &m->mask[0], &m->mask[1], &m->mask[2], &m->mask[3], &m->mask[4],
7427b590f17aSKristof Provost &m->mask[5]) != 6) {
7428b590f17aSKristof Provost free(m);
7429b590f17aSKristof Provost yyerror("invalid MAC mask");
7430b590f17aSKristof Provost return (NULL);
7431b590f17aSKristof Provost }
7432b590f17aSKristof Provost
7433b590f17aSKristof Provost return (m);
7434b590f17aSKristof Provost }
7435