13b3a8eb9SGleb Smirnoff /* $OpenBSD: parse.y,v 1.554 2008/10/17 12:59:53 henning Exp $ */ 23b3a8eb9SGleb Smirnoff 33b3a8eb9SGleb Smirnoff /* 43b3a8eb9SGleb Smirnoff * Copyright (c) 2001 Markus Friedl. All rights reserved. 53b3a8eb9SGleb Smirnoff * Copyright (c) 2001 Daniel Hartmeier. All rights reserved. 63b3a8eb9SGleb Smirnoff * Copyright (c) 2001 Theo de Raadt. All rights reserved. 73b3a8eb9SGleb Smirnoff * Copyright (c) 2002,2003 Henning Brauer. All rights reserved. 83b3a8eb9SGleb Smirnoff * 93b3a8eb9SGleb Smirnoff * Redistribution and use in source and binary forms, with or without 103b3a8eb9SGleb Smirnoff * modification, are permitted provided that the following conditions 113b3a8eb9SGleb Smirnoff * are met: 123b3a8eb9SGleb Smirnoff * 1. Redistributions of source code must retain the above copyright 133b3a8eb9SGleb Smirnoff * notice, this list of conditions and the following disclaimer. 143b3a8eb9SGleb Smirnoff * 2. Redistributions in binary form must reproduce the above copyright 153b3a8eb9SGleb Smirnoff * notice, this list of conditions and the following disclaimer in the 163b3a8eb9SGleb Smirnoff * documentation and/or other materials provided with the distribution. 173b3a8eb9SGleb Smirnoff * 183b3a8eb9SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 193b3a8eb9SGleb Smirnoff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 203b3a8eb9SGleb Smirnoff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 213b3a8eb9SGleb Smirnoff * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 223b3a8eb9SGleb Smirnoff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 233b3a8eb9SGleb Smirnoff * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 243b3a8eb9SGleb Smirnoff * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 253b3a8eb9SGleb Smirnoff * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 263b3a8eb9SGleb Smirnoff * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 273b3a8eb9SGleb Smirnoff * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 283b3a8eb9SGleb Smirnoff */ 293b3a8eb9SGleb Smirnoff %{ 303b3a8eb9SGleb Smirnoff #include <sys/cdefs.h> 313b3a8eb9SGleb Smirnoff __FBSDID("$FreeBSD$"); 323b3a8eb9SGleb Smirnoff 333b3a8eb9SGleb Smirnoff #include <sys/types.h> 343b3a8eb9SGleb Smirnoff #include <sys/socket.h> 353b3a8eb9SGleb Smirnoff #include <sys/stat.h> 363b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 373b3a8eb9SGleb Smirnoff #include <sys/sysctl.h> 383b3a8eb9SGleb Smirnoff #endif 393b3a8eb9SGleb Smirnoff #include <net/if.h> 403b3a8eb9SGleb Smirnoff #include <netinet/in.h> 413b3a8eb9SGleb Smirnoff #include <netinet/in_systm.h> 423b3a8eb9SGleb Smirnoff #include <netinet/ip.h> 433b3a8eb9SGleb Smirnoff #include <netinet/ip_icmp.h> 443b3a8eb9SGleb Smirnoff #include <netinet/icmp6.h> 453b3a8eb9SGleb Smirnoff #include <net/pfvar.h> 463b3a8eb9SGleb Smirnoff #include <arpa/inet.h> 47772e66a6SGleb Smirnoff #include <net/altq/altq.h> 48772e66a6SGleb Smirnoff #include <net/altq/altq_cbq.h> 490a70aaf8SLuiz Otavio O Souza #include <net/altq/altq_codel.h> 50772e66a6SGleb Smirnoff #include <net/altq/altq_priq.h> 51772e66a6SGleb Smirnoff #include <net/altq/altq_hfsc.h> 52a5b789f6SErmal Luçi #include <net/altq/altq_fairq.h> 533b3a8eb9SGleb Smirnoff 543b3a8eb9SGleb Smirnoff #include <stdio.h> 553b3a8eb9SGleb Smirnoff #include <unistd.h> 563b3a8eb9SGleb Smirnoff #include <stdlib.h> 573b3a8eb9SGleb Smirnoff #include <netdb.h> 583b3a8eb9SGleb Smirnoff #include <stdarg.h> 593b3a8eb9SGleb Smirnoff #include <errno.h> 603b3a8eb9SGleb Smirnoff #include <string.h> 613b3a8eb9SGleb Smirnoff #include <ctype.h> 623b3a8eb9SGleb Smirnoff #include <math.h> 633b3a8eb9SGleb Smirnoff #include <err.h> 643b3a8eb9SGleb Smirnoff #include <limits.h> 653b3a8eb9SGleb Smirnoff #include <pwd.h> 663b3a8eb9SGleb Smirnoff #include <grp.h> 673b3a8eb9SGleb Smirnoff #include <md5.h> 683b3a8eb9SGleb Smirnoff 693b3a8eb9SGleb Smirnoff #include "pfctl_parser.h" 703b3a8eb9SGleb Smirnoff #include "pfctl.h" 713b3a8eb9SGleb Smirnoff 723b3a8eb9SGleb Smirnoff static struct pfctl *pf = NULL; 733b3a8eb9SGleb Smirnoff static int debug = 0; 743b3a8eb9SGleb Smirnoff static int rulestate = 0; 753b3a8eb9SGleb Smirnoff static u_int16_t returnicmpdefault = 763b3a8eb9SGleb Smirnoff (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT; 773b3a8eb9SGleb Smirnoff static u_int16_t returnicmp6default = 783b3a8eb9SGleb Smirnoff (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT; 793b3a8eb9SGleb Smirnoff static int blockpolicy = PFRULE_DROP; 803b3a8eb9SGleb Smirnoff static int require_order = 1; 813b3a8eb9SGleb Smirnoff static int default_statelock; 823b3a8eb9SGleb Smirnoff 8313cfafabSKristof Provost static TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); 843b3a8eb9SGleb Smirnoff static struct file { 853b3a8eb9SGleb Smirnoff TAILQ_ENTRY(file) entry; 863b3a8eb9SGleb Smirnoff FILE *stream; 873b3a8eb9SGleb Smirnoff char *name; 883b3a8eb9SGleb Smirnoff int lineno; 893b3a8eb9SGleb Smirnoff int errors; 903b3a8eb9SGleb Smirnoff } *file; 913b3a8eb9SGleb Smirnoff struct file *pushfile(const char *, int); 923b3a8eb9SGleb Smirnoff int popfile(void); 933b3a8eb9SGleb Smirnoff int check_file_secrecy(int, const char *); 943b3a8eb9SGleb Smirnoff int yyparse(void); 953b3a8eb9SGleb Smirnoff int yylex(void); 963b3a8eb9SGleb Smirnoff int yyerror(const char *, ...); 973b3a8eb9SGleb Smirnoff int kw_cmp(const void *, const void *); 983b3a8eb9SGleb Smirnoff int lookup(char *); 993b3a8eb9SGleb Smirnoff int lgetc(int); 1003b3a8eb9SGleb Smirnoff int lungetc(int); 1013b3a8eb9SGleb Smirnoff int findeol(void); 1023b3a8eb9SGleb Smirnoff 10313cfafabSKristof Provost static TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); 1043b3a8eb9SGleb Smirnoff struct sym { 1053b3a8eb9SGleb Smirnoff TAILQ_ENTRY(sym) entry; 1063b3a8eb9SGleb Smirnoff int used; 1073b3a8eb9SGleb Smirnoff int persist; 1083b3a8eb9SGleb Smirnoff char *nam; 1093b3a8eb9SGleb Smirnoff char *val; 1103b3a8eb9SGleb Smirnoff }; 1113b3a8eb9SGleb Smirnoff int symset(const char *, const char *, int); 1123b3a8eb9SGleb Smirnoff char *symget(const char *); 1133b3a8eb9SGleb Smirnoff 1143b3a8eb9SGleb Smirnoff int atoul(char *, u_long *); 1153b3a8eb9SGleb Smirnoff 1163b3a8eb9SGleb Smirnoff enum { 1173b3a8eb9SGleb Smirnoff PFCTL_STATE_NONE, 1183b3a8eb9SGleb Smirnoff PFCTL_STATE_OPTION, 1193b3a8eb9SGleb Smirnoff PFCTL_STATE_SCRUB, 1203b3a8eb9SGleb Smirnoff PFCTL_STATE_QUEUE, 1213b3a8eb9SGleb Smirnoff PFCTL_STATE_NAT, 1223b3a8eb9SGleb Smirnoff PFCTL_STATE_FILTER 1233b3a8eb9SGleb Smirnoff }; 1243b3a8eb9SGleb Smirnoff 1253b3a8eb9SGleb Smirnoff struct node_proto { 1263b3a8eb9SGleb Smirnoff u_int8_t proto; 1273b3a8eb9SGleb Smirnoff struct node_proto *next; 1283b3a8eb9SGleb Smirnoff struct node_proto *tail; 1293b3a8eb9SGleb Smirnoff }; 1303b3a8eb9SGleb Smirnoff 1313b3a8eb9SGleb Smirnoff struct node_port { 1323b3a8eb9SGleb Smirnoff u_int16_t port[2]; 1333b3a8eb9SGleb Smirnoff u_int8_t op; 1343b3a8eb9SGleb Smirnoff struct node_port *next; 1353b3a8eb9SGleb Smirnoff struct node_port *tail; 1363b3a8eb9SGleb Smirnoff }; 1373b3a8eb9SGleb Smirnoff 1383b3a8eb9SGleb Smirnoff struct node_uid { 1393b3a8eb9SGleb Smirnoff uid_t uid[2]; 1403b3a8eb9SGleb Smirnoff u_int8_t op; 1413b3a8eb9SGleb Smirnoff struct node_uid *next; 1423b3a8eb9SGleb Smirnoff struct node_uid *tail; 1433b3a8eb9SGleb Smirnoff }; 1443b3a8eb9SGleb Smirnoff 1453b3a8eb9SGleb Smirnoff struct node_gid { 1463b3a8eb9SGleb Smirnoff gid_t gid[2]; 1473b3a8eb9SGleb Smirnoff u_int8_t op; 1483b3a8eb9SGleb Smirnoff struct node_gid *next; 1493b3a8eb9SGleb Smirnoff struct node_gid *tail; 1503b3a8eb9SGleb Smirnoff }; 1513b3a8eb9SGleb Smirnoff 1523b3a8eb9SGleb Smirnoff struct node_icmp { 1533b3a8eb9SGleb Smirnoff u_int8_t code; 1543b3a8eb9SGleb Smirnoff u_int8_t type; 1553b3a8eb9SGleb Smirnoff u_int8_t proto; 1563b3a8eb9SGleb Smirnoff struct node_icmp *next; 1573b3a8eb9SGleb Smirnoff struct node_icmp *tail; 1583b3a8eb9SGleb Smirnoff }; 1593b3a8eb9SGleb Smirnoff 1603b3a8eb9SGleb Smirnoff enum { PF_STATE_OPT_MAX, PF_STATE_OPT_NOSYNC, PF_STATE_OPT_SRCTRACK, 1613b3a8eb9SGleb Smirnoff PF_STATE_OPT_MAX_SRC_STATES, PF_STATE_OPT_MAX_SRC_CONN, 1623b3a8eb9SGleb Smirnoff PF_STATE_OPT_MAX_SRC_CONN_RATE, PF_STATE_OPT_MAX_SRC_NODES, 1633b3a8eb9SGleb Smirnoff PF_STATE_OPT_OVERLOAD, PF_STATE_OPT_STATELOCK, 1643b3a8eb9SGleb Smirnoff PF_STATE_OPT_TIMEOUT, PF_STATE_OPT_SLOPPY, }; 1653b3a8eb9SGleb Smirnoff 1663b3a8eb9SGleb Smirnoff enum { PF_SRCTRACK_NONE, PF_SRCTRACK, PF_SRCTRACK_GLOBAL, PF_SRCTRACK_RULE }; 1673b3a8eb9SGleb Smirnoff 1683b3a8eb9SGleb Smirnoff struct node_state_opt { 1693b3a8eb9SGleb Smirnoff int type; 1703b3a8eb9SGleb Smirnoff union { 1713b3a8eb9SGleb Smirnoff u_int32_t max_states; 1723b3a8eb9SGleb Smirnoff u_int32_t max_src_states; 1733b3a8eb9SGleb Smirnoff u_int32_t max_src_conn; 1743b3a8eb9SGleb Smirnoff struct { 1753b3a8eb9SGleb Smirnoff u_int32_t limit; 1763b3a8eb9SGleb Smirnoff u_int32_t seconds; 1773b3a8eb9SGleb Smirnoff } max_src_conn_rate; 1783b3a8eb9SGleb Smirnoff struct { 1793b3a8eb9SGleb Smirnoff u_int8_t flush; 1803b3a8eb9SGleb Smirnoff char tblname[PF_TABLE_NAME_SIZE]; 1813b3a8eb9SGleb Smirnoff } overload; 1823b3a8eb9SGleb Smirnoff u_int32_t max_src_nodes; 1833b3a8eb9SGleb Smirnoff u_int8_t src_track; 1843b3a8eb9SGleb Smirnoff u_int32_t statelock; 1853b3a8eb9SGleb Smirnoff struct { 1863b3a8eb9SGleb Smirnoff int number; 1873b3a8eb9SGleb Smirnoff u_int32_t seconds; 1883b3a8eb9SGleb Smirnoff } timeout; 1893b3a8eb9SGleb Smirnoff } data; 1903b3a8eb9SGleb Smirnoff struct node_state_opt *next; 1913b3a8eb9SGleb Smirnoff struct node_state_opt *tail; 1923b3a8eb9SGleb Smirnoff }; 1933b3a8eb9SGleb Smirnoff 1943b3a8eb9SGleb Smirnoff struct peer { 1953b3a8eb9SGleb Smirnoff struct node_host *host; 1963b3a8eb9SGleb Smirnoff struct node_port *port; 1973b3a8eb9SGleb Smirnoff }; 1983b3a8eb9SGleb Smirnoff 19913cfafabSKristof Provost static struct node_queue { 2003b3a8eb9SGleb Smirnoff char queue[PF_QNAME_SIZE]; 2013b3a8eb9SGleb Smirnoff char parent[PF_QNAME_SIZE]; 2023b3a8eb9SGleb Smirnoff char ifname[IFNAMSIZ]; 2033b3a8eb9SGleb Smirnoff int scheduler; 2043b3a8eb9SGleb Smirnoff struct node_queue *next; 2053b3a8eb9SGleb Smirnoff struct node_queue *tail; 2063b3a8eb9SGleb Smirnoff } *queues = NULL; 2073b3a8eb9SGleb Smirnoff 2083b3a8eb9SGleb Smirnoff struct node_qassign { 2093b3a8eb9SGleb Smirnoff char *qname; 2103b3a8eb9SGleb Smirnoff char *pqname; 2113b3a8eb9SGleb Smirnoff }; 2123b3a8eb9SGleb Smirnoff 21313cfafabSKristof Provost static struct filter_opts { 2143b3a8eb9SGleb Smirnoff int marker; 2153b3a8eb9SGleb Smirnoff #define FOM_FLAGS 0x01 2163b3a8eb9SGleb Smirnoff #define FOM_ICMP 0x02 2173b3a8eb9SGleb Smirnoff #define FOM_TOS 0x04 2183b3a8eb9SGleb Smirnoff #define FOM_KEEP 0x08 2193b3a8eb9SGleb Smirnoff #define FOM_SRCTRACK 0x10 2203e248e0fSKristof Provost #define FOM_SETPRIO 0x0400 2213e248e0fSKristof Provost #define FOM_PRIO 0x2000 2223b3a8eb9SGleb Smirnoff struct node_uid *uid; 2233b3a8eb9SGleb Smirnoff struct node_gid *gid; 2243b3a8eb9SGleb Smirnoff struct { 2253b3a8eb9SGleb Smirnoff u_int8_t b1; 2263b3a8eb9SGleb Smirnoff u_int8_t b2; 2273b3a8eb9SGleb Smirnoff u_int16_t w; 2283b3a8eb9SGleb Smirnoff u_int16_t w2; 2293b3a8eb9SGleb Smirnoff } flags; 2303b3a8eb9SGleb Smirnoff struct node_icmp *icmpspec; 2313b3a8eb9SGleb Smirnoff u_int32_t tos; 2323b3a8eb9SGleb Smirnoff u_int32_t prob; 2333b3a8eb9SGleb Smirnoff struct { 2343b3a8eb9SGleb Smirnoff int action; 2353b3a8eb9SGleb Smirnoff struct node_state_opt *options; 2363b3a8eb9SGleb Smirnoff } keep; 2373b3a8eb9SGleb Smirnoff int fragment; 2383b3a8eb9SGleb Smirnoff int allowopts; 2393b3a8eb9SGleb Smirnoff char *label; 2403b3a8eb9SGleb Smirnoff struct node_qassign queues; 2413b3a8eb9SGleb Smirnoff char *tag; 2423b3a8eb9SGleb Smirnoff char *match_tag; 2433b3a8eb9SGleb Smirnoff u_int8_t match_tag_not; 2443b3a8eb9SGleb Smirnoff u_int rtableid; 2453e248e0fSKristof Provost u_int8_t prio; 2463e248e0fSKristof Provost u_int8_t set_prio[2]; 2473b3a8eb9SGleb Smirnoff struct { 2483b3a8eb9SGleb Smirnoff struct node_host *addr; 2493b3a8eb9SGleb Smirnoff u_int16_t port; 2503b3a8eb9SGleb Smirnoff } divert; 2513b3a8eb9SGleb Smirnoff } filter_opts; 2523b3a8eb9SGleb Smirnoff 25313cfafabSKristof Provost static struct antispoof_opts { 2543b3a8eb9SGleb Smirnoff char *label; 2553b3a8eb9SGleb Smirnoff u_int rtableid; 2563b3a8eb9SGleb Smirnoff } antispoof_opts; 2573b3a8eb9SGleb Smirnoff 25813cfafabSKristof Provost static struct scrub_opts { 2593b3a8eb9SGleb Smirnoff int marker; 2603b3a8eb9SGleb Smirnoff #define SOM_MINTTL 0x01 2613b3a8eb9SGleb Smirnoff #define SOM_MAXMSS 0x02 2623b3a8eb9SGleb Smirnoff #define SOM_FRAGCACHE 0x04 2633b3a8eb9SGleb Smirnoff #define SOM_SETTOS 0x08 2643b3a8eb9SGleb Smirnoff int nodf; 2653b3a8eb9SGleb Smirnoff int minttl; 2663b3a8eb9SGleb Smirnoff int maxmss; 2673b3a8eb9SGleb Smirnoff int settos; 2683b3a8eb9SGleb Smirnoff int fragcache; 2693b3a8eb9SGleb Smirnoff int randomid; 2703b3a8eb9SGleb Smirnoff int reassemble_tcp; 2713b3a8eb9SGleb Smirnoff char *match_tag; 2723b3a8eb9SGleb Smirnoff u_int8_t match_tag_not; 2733b3a8eb9SGleb Smirnoff u_int rtableid; 2743b3a8eb9SGleb Smirnoff } scrub_opts; 2753b3a8eb9SGleb Smirnoff 27613cfafabSKristof Provost static struct queue_opts { 2773b3a8eb9SGleb Smirnoff int marker; 2783b3a8eb9SGleb Smirnoff #define QOM_BWSPEC 0x01 2793b3a8eb9SGleb Smirnoff #define QOM_SCHEDULER 0x02 2803b3a8eb9SGleb Smirnoff #define QOM_PRIORITY 0x04 2813b3a8eb9SGleb Smirnoff #define QOM_TBRSIZE 0x08 2823b3a8eb9SGleb Smirnoff #define QOM_QLIMIT 0x10 2833b3a8eb9SGleb Smirnoff struct node_queue_bw queue_bwspec; 2843b3a8eb9SGleb Smirnoff struct node_queue_opt scheduler; 2853b3a8eb9SGleb Smirnoff int priority; 2863b3a8eb9SGleb Smirnoff int tbrsize; 2873b3a8eb9SGleb Smirnoff int qlimit; 2883b3a8eb9SGleb Smirnoff } queue_opts; 2893b3a8eb9SGleb Smirnoff 29013cfafabSKristof Provost static struct table_opts { 2913b3a8eb9SGleb Smirnoff int flags; 2923b3a8eb9SGleb Smirnoff int init_addr; 2933b3a8eb9SGleb Smirnoff struct node_tinithead init_nodes; 2943b3a8eb9SGleb Smirnoff } table_opts; 2953b3a8eb9SGleb Smirnoff 29613cfafabSKristof Provost static struct pool_opts { 2973b3a8eb9SGleb Smirnoff int marker; 2983b3a8eb9SGleb Smirnoff #define POM_TYPE 0x01 2993b3a8eb9SGleb Smirnoff #define POM_STICKYADDRESS 0x02 3003b3a8eb9SGleb Smirnoff u_int8_t opts; 3013b3a8eb9SGleb Smirnoff int type; 3023b3a8eb9SGleb Smirnoff int staticport; 3033b3a8eb9SGleb Smirnoff struct pf_poolhashkey *key; 3043b3a8eb9SGleb Smirnoff 3053b3a8eb9SGleb Smirnoff } pool_opts; 3063b3a8eb9SGleb Smirnoff 30713cfafabSKristof Provost static struct codel_opts codel_opts; 30813cfafabSKristof Provost static struct node_hfsc_opts hfsc_opts; 30913cfafabSKristof Provost static struct node_fairq_opts fairq_opts; 31013cfafabSKristof Provost static struct node_state_opt *keep_state_defaults = NULL; 3113b3a8eb9SGleb Smirnoff 3123b3a8eb9SGleb Smirnoff int disallow_table(struct node_host *, const char *); 3133b3a8eb9SGleb Smirnoff int disallow_urpf_failed(struct node_host *, const char *); 3143b3a8eb9SGleb Smirnoff int disallow_alias(struct node_host *, const char *); 3153b3a8eb9SGleb Smirnoff int rule_consistent(struct pf_rule *, int); 3163b3a8eb9SGleb Smirnoff int filter_consistent(struct pf_rule *, int); 3173b3a8eb9SGleb Smirnoff int nat_consistent(struct pf_rule *); 3183b3a8eb9SGleb Smirnoff int rdr_consistent(struct pf_rule *); 3193b3a8eb9SGleb Smirnoff int process_tabledef(char *, struct table_opts *); 3203b3a8eb9SGleb Smirnoff void expand_label_str(char *, size_t, const char *, const char *); 3213b3a8eb9SGleb Smirnoff void expand_label_if(const char *, char *, size_t, const char *); 3223b3a8eb9SGleb Smirnoff void expand_label_addr(const char *, char *, size_t, u_int8_t, 3233b3a8eb9SGleb Smirnoff struct node_host *); 3243b3a8eb9SGleb Smirnoff void expand_label_port(const char *, char *, size_t, 3253b3a8eb9SGleb Smirnoff struct node_port *); 3263b3a8eb9SGleb Smirnoff void expand_label_proto(const char *, char *, size_t, u_int8_t); 3273b3a8eb9SGleb Smirnoff void expand_label_nr(const char *, char *, size_t); 3283b3a8eb9SGleb Smirnoff void expand_label(char *, size_t, const char *, u_int8_t, 3293b3a8eb9SGleb Smirnoff struct node_host *, struct node_port *, struct node_host *, 3303b3a8eb9SGleb Smirnoff struct node_port *, u_int8_t); 3313b3a8eb9SGleb Smirnoff void expand_rule(struct pf_rule *, struct node_if *, 3323b3a8eb9SGleb Smirnoff struct node_host *, struct node_proto *, struct node_os *, 3333b3a8eb9SGleb Smirnoff struct node_host *, struct node_port *, struct node_host *, 3343b3a8eb9SGleb Smirnoff struct node_port *, struct node_uid *, struct node_gid *, 3353b3a8eb9SGleb Smirnoff struct node_icmp *, const char *); 3363b3a8eb9SGleb Smirnoff int expand_altq(struct pf_altq *, struct node_if *, 3373b3a8eb9SGleb Smirnoff struct node_queue *, struct node_queue_bw bwspec, 3383b3a8eb9SGleb Smirnoff struct node_queue_opt *); 3393b3a8eb9SGleb Smirnoff int expand_queue(struct pf_altq *, struct node_if *, 3403b3a8eb9SGleb Smirnoff struct node_queue *, struct node_queue_bw, 3413b3a8eb9SGleb Smirnoff struct node_queue_opt *); 3423b3a8eb9SGleb Smirnoff int expand_skip_interface(struct node_if *); 3433b3a8eb9SGleb Smirnoff 3443b3a8eb9SGleb Smirnoff int check_rulestate(int); 3453b3a8eb9SGleb Smirnoff int getservice(char *); 3463b3a8eb9SGleb Smirnoff int rule_label(struct pf_rule *, char *); 3473b3a8eb9SGleb Smirnoff int rt_tableid_max(void); 3483b3a8eb9SGleb Smirnoff 3493b3a8eb9SGleb Smirnoff void mv_rules(struct pf_ruleset *, struct pf_ruleset *); 3503b3a8eb9SGleb Smirnoff void decide_address_family(struct node_host *, sa_family_t *); 3513b3a8eb9SGleb Smirnoff void remove_invalid_hosts(struct node_host **, sa_family_t *); 3523b3a8eb9SGleb Smirnoff int invalid_redirect(struct node_host *, sa_family_t); 3533b3a8eb9SGleb Smirnoff u_int16_t parseicmpspec(char *, sa_family_t); 3543b3a8eb9SGleb Smirnoff 35513cfafabSKristof Provost static TAILQ_HEAD(loadanchorshead, loadanchors) 3563b3a8eb9SGleb Smirnoff loadanchorshead = TAILQ_HEAD_INITIALIZER(loadanchorshead); 3573b3a8eb9SGleb Smirnoff 3583b3a8eb9SGleb Smirnoff struct loadanchors { 3593b3a8eb9SGleb Smirnoff TAILQ_ENTRY(loadanchors) entries; 3603b3a8eb9SGleb Smirnoff char *anchorname; 3613b3a8eb9SGleb Smirnoff char *filename; 3623b3a8eb9SGleb Smirnoff }; 3633b3a8eb9SGleb Smirnoff 3643b3a8eb9SGleb Smirnoff typedef struct { 3653b3a8eb9SGleb Smirnoff union { 3663b3a8eb9SGleb Smirnoff int64_t number; 3673b3a8eb9SGleb Smirnoff double probability; 3683b3a8eb9SGleb Smirnoff int i; 3693b3a8eb9SGleb Smirnoff char *string; 3703b3a8eb9SGleb Smirnoff u_int rtableid; 3713b3a8eb9SGleb Smirnoff struct { 3723b3a8eb9SGleb Smirnoff u_int8_t b1; 3733b3a8eb9SGleb Smirnoff u_int8_t b2; 3743b3a8eb9SGleb Smirnoff u_int16_t w; 3753b3a8eb9SGleb Smirnoff u_int16_t w2; 3763b3a8eb9SGleb Smirnoff } b; 3773b3a8eb9SGleb Smirnoff struct range { 3783b3a8eb9SGleb Smirnoff int a; 3793b3a8eb9SGleb Smirnoff int b; 3803b3a8eb9SGleb Smirnoff int t; 3813b3a8eb9SGleb Smirnoff } range; 3823b3a8eb9SGleb Smirnoff struct node_if *interface; 3833b3a8eb9SGleb Smirnoff struct node_proto *proto; 3843b3a8eb9SGleb Smirnoff struct node_icmp *icmp; 3853b3a8eb9SGleb Smirnoff struct node_host *host; 3863b3a8eb9SGleb Smirnoff struct node_os *os; 3873b3a8eb9SGleb Smirnoff struct node_port *port; 3883b3a8eb9SGleb Smirnoff struct node_uid *uid; 3893b3a8eb9SGleb Smirnoff struct node_gid *gid; 3903b3a8eb9SGleb Smirnoff struct node_state_opt *state_opt; 3913b3a8eb9SGleb Smirnoff struct peer peer; 3923b3a8eb9SGleb Smirnoff struct { 3933b3a8eb9SGleb Smirnoff struct peer src, dst; 3943b3a8eb9SGleb Smirnoff struct node_os *src_os; 3953b3a8eb9SGleb Smirnoff } fromto; 3963b3a8eb9SGleb Smirnoff struct { 3973b3a8eb9SGleb Smirnoff struct node_host *host; 3983b3a8eb9SGleb Smirnoff u_int8_t rt; 3993b3a8eb9SGleb Smirnoff u_int8_t pool_opts; 4003b3a8eb9SGleb Smirnoff sa_family_t af; 4013b3a8eb9SGleb Smirnoff struct pf_poolhashkey *key; 4023b3a8eb9SGleb Smirnoff } route; 4033b3a8eb9SGleb Smirnoff struct redirection { 4043b3a8eb9SGleb Smirnoff struct node_host *host; 4053b3a8eb9SGleb Smirnoff struct range rport; 4063b3a8eb9SGleb Smirnoff } *redirection; 4073b3a8eb9SGleb Smirnoff struct { 4083b3a8eb9SGleb Smirnoff int action; 4093b3a8eb9SGleb Smirnoff struct node_state_opt *options; 4103b3a8eb9SGleb Smirnoff } keep_state; 4113b3a8eb9SGleb Smirnoff struct { 4123b3a8eb9SGleb Smirnoff u_int8_t log; 4133b3a8eb9SGleb Smirnoff u_int8_t logif; 4143b3a8eb9SGleb Smirnoff u_int8_t quick; 4153b3a8eb9SGleb Smirnoff } logquick; 4163b3a8eb9SGleb Smirnoff struct { 4173b3a8eb9SGleb Smirnoff int neg; 4183b3a8eb9SGleb Smirnoff char *name; 4193b3a8eb9SGleb Smirnoff } tagged; 4203b3a8eb9SGleb Smirnoff struct pf_poolhashkey *hashkey; 4213b3a8eb9SGleb Smirnoff struct node_queue *queue; 4223b3a8eb9SGleb Smirnoff struct node_queue_opt queue_options; 4233b3a8eb9SGleb Smirnoff struct node_queue_bw queue_bwspec; 4243b3a8eb9SGleb Smirnoff struct node_qassign qassign; 4253b3a8eb9SGleb Smirnoff struct filter_opts filter_opts; 4263b3a8eb9SGleb Smirnoff struct antispoof_opts antispoof_opts; 4273b3a8eb9SGleb Smirnoff struct queue_opts queue_opts; 4283b3a8eb9SGleb Smirnoff struct scrub_opts scrub_opts; 4293b3a8eb9SGleb Smirnoff struct table_opts table_opts; 4303b3a8eb9SGleb Smirnoff struct pool_opts pool_opts; 4313b3a8eb9SGleb Smirnoff struct node_hfsc_opts hfsc_opts; 432a5b789f6SErmal Luçi struct node_fairq_opts fairq_opts; 4330a70aaf8SLuiz Otavio O Souza struct codel_opts codel_opts; 4343b3a8eb9SGleb Smirnoff } v; 4353b3a8eb9SGleb Smirnoff int lineno; 4363b3a8eb9SGleb Smirnoff } YYSTYPE; 4373b3a8eb9SGleb Smirnoff 4383b3a8eb9SGleb Smirnoff #define PPORT_RANGE 1 4393b3a8eb9SGleb Smirnoff #define PPORT_STAR 2 4403b3a8eb9SGleb Smirnoff int parseport(char *, struct range *r, int); 4413b3a8eb9SGleb Smirnoff 4423b3a8eb9SGleb Smirnoff #define DYNIF_MULTIADDR(addr) ((addr).type == PF_ADDR_DYNIFTL && \ 4433b3a8eb9SGleb Smirnoff (!((addr).iflags & PFI_AFLAG_NOALIAS) || \ 4443b3a8eb9SGleb Smirnoff !isdigit((addr).v.ifname[strlen((addr).v.ifname)-1]))) 4453b3a8eb9SGleb Smirnoff 4463b3a8eb9SGleb Smirnoff %} 4473b3a8eb9SGleb Smirnoff 4483b3a8eb9SGleb Smirnoff %token PASS BLOCK SCRUB RETURN IN OS OUT LOG QUICK ON FROM TO FLAGS 4493b3a8eb9SGleb Smirnoff %token RETURNRST RETURNICMP RETURNICMP6 PROTO INET INET6 ALL ANY ICMPTYPE 4503b3a8eb9SGleb Smirnoff %token ICMP6TYPE CODE KEEP MODULATE STATE PORT RDR NAT BINAT ARROW NODF 4513b3a8eb9SGleb Smirnoff %token MINTTL ERROR ALLOWOPTS FASTROUTE FILENAME ROUTETO DUPTO REPLYTO NO LABEL 4523b3a8eb9SGleb Smirnoff %token NOROUTE URPFFAILED FRAGMENT USER GROUP MAXMSS MAXIMUM TTL TOS DROP TABLE 4533b3a8eb9SGleb Smirnoff %token REASSEMBLE FRAGDROP FRAGCROP ANCHOR NATANCHOR RDRANCHOR BINATANCHOR 4543b3a8eb9SGleb Smirnoff %token SET OPTIMIZATION TIMEOUT LIMIT LOGINTERFACE BLOCKPOLICY RANDOMID 4553b3a8eb9SGleb Smirnoff %token REQUIREORDER SYNPROXY FINGERPRINTS NOSYNC DEBUG SKIP HOSTID 4563b3a8eb9SGleb Smirnoff %token ANTISPOOF FOR INCLUDE 4573b3a8eb9SGleb Smirnoff %token BITMASK RANDOM SOURCEHASH ROUNDROBIN STATICPORT PROBABILITY 4580a70aaf8SLuiz Otavio O Souza %token ALTQ CBQ CODEL PRIQ HFSC FAIRQ BANDWIDTH TBRSIZE LINKSHARE REALTIME 4590a70aaf8SLuiz Otavio O Souza %token UPPERLIMIT QUEUE PRIORITY QLIMIT HOGS BUCKETS RTABLE TARGET INTERVAL 4603e248e0fSKristof Provost %token LOAD RULESET_OPTIMIZATION PRIO 4613b3a8eb9SGleb Smirnoff %token STICKYADDRESS MAXSRCSTATES MAXSRCNODES SOURCETRACK GLOBAL RULE 4623b3a8eb9SGleb Smirnoff %token MAXSRCCONN MAXSRCCONNRATE OVERLOAD FLUSH SLOPPY 4633b3a8eb9SGleb Smirnoff %token TAGGED TAG IFBOUND FLOATING STATEPOLICY STATEDEFAULTS ROUTE SETTOS 4643b3a8eb9SGleb Smirnoff %token DIVERTTO DIVERTREPLY 4653b3a8eb9SGleb Smirnoff %token <v.string> STRING 4663b3a8eb9SGleb Smirnoff %token <v.number> NUMBER 4673b3a8eb9SGleb Smirnoff %token <v.i> PORTBINARY 4683b3a8eb9SGleb Smirnoff %type <v.interface> interface if_list if_item_not if_item 4693b3a8eb9SGleb Smirnoff %type <v.number> number icmptype icmp6type uid gid 4703b3a8eb9SGleb Smirnoff %type <v.number> tos not yesno 4713b3a8eb9SGleb Smirnoff %type <v.probability> probability 4723b3a8eb9SGleb Smirnoff %type <v.i> no dir af fragcache optimizer 4733b3a8eb9SGleb Smirnoff %type <v.i> sourcetrack flush unaryop statelock 4743b3a8eb9SGleb Smirnoff %type <v.b> action nataction natpasslog scrubaction 4753e248e0fSKristof Provost %type <v.b> flags flag blockspec prio 4763b3a8eb9SGleb Smirnoff %type <v.range> portplain portstar portrange 4773b3a8eb9SGleb Smirnoff %type <v.hashkey> hashkey 4783b3a8eb9SGleb Smirnoff %type <v.proto> proto proto_list proto_item 4793b3a8eb9SGleb Smirnoff %type <v.number> protoval 4803b3a8eb9SGleb Smirnoff %type <v.icmp> icmpspec 4813b3a8eb9SGleb Smirnoff %type <v.icmp> icmp_list icmp_item 4823b3a8eb9SGleb Smirnoff %type <v.icmp> icmp6_list icmp6_item 4833b3a8eb9SGleb Smirnoff %type <v.number> reticmpspec reticmp6spec 4843b3a8eb9SGleb Smirnoff %type <v.fromto> fromto 4853b3a8eb9SGleb Smirnoff %type <v.peer> ipportspec from to 4863b3a8eb9SGleb Smirnoff %type <v.host> ipspec toipspec xhost host dynaddr host_list 4873b3a8eb9SGleb Smirnoff %type <v.host> redir_host_list redirspec 4883b3a8eb9SGleb Smirnoff %type <v.host> route_host route_host_list routespec 4893b3a8eb9SGleb Smirnoff %type <v.os> os xos os_list 4903b3a8eb9SGleb Smirnoff %type <v.port> portspec port_list port_item 4913b3a8eb9SGleb Smirnoff %type <v.uid> uids uid_list uid_item 4923b3a8eb9SGleb Smirnoff %type <v.gid> gids gid_list gid_item 4933b3a8eb9SGleb Smirnoff %type <v.route> route 4943b3a8eb9SGleb Smirnoff %type <v.redirection> redirection redirpool 4953b3a8eb9SGleb Smirnoff %type <v.string> label stringall tag anchorname 4963b3a8eb9SGleb Smirnoff %type <v.string> string varstring numberstring 4973b3a8eb9SGleb Smirnoff %type <v.keep_state> keep 4983b3a8eb9SGleb Smirnoff %type <v.state_opt> state_opt_spec state_opt_list state_opt_item 4993b3a8eb9SGleb Smirnoff %type <v.logquick> logquick quick log logopts logopt 5003b3a8eb9SGleb Smirnoff %type <v.interface> antispoof_ifspc antispoof_iflst antispoof_if 5013b3a8eb9SGleb Smirnoff %type <v.qassign> qname 5023b3a8eb9SGleb Smirnoff %type <v.queue> qassign qassign_list qassign_item 5033b3a8eb9SGleb Smirnoff %type <v.queue_options> scheduler 5043b3a8eb9SGleb Smirnoff %type <v.number> cbqflags_list cbqflags_item 5053b3a8eb9SGleb Smirnoff %type <v.number> priqflags_list priqflags_item 5063b3a8eb9SGleb Smirnoff %type <v.hfsc_opts> hfscopts_list hfscopts_item hfsc_opts 507a5b789f6SErmal Luçi %type <v.fairq_opts> fairqopts_list fairqopts_item fairq_opts 5080a70aaf8SLuiz Otavio O Souza %type <v.codel_opts> codelopts_list codelopts_item codel_opts 5093b3a8eb9SGleb Smirnoff %type <v.queue_bwspec> bandwidth 5103b3a8eb9SGleb Smirnoff %type <v.filter_opts> filter_opts filter_opt filter_opts_l 5113e248e0fSKristof Provost %type <v.filter_opts> filter_sets filter_set filter_sets_l 5123b3a8eb9SGleb Smirnoff %type <v.antispoof_opts> antispoof_opts antispoof_opt antispoof_opts_l 5133b3a8eb9SGleb Smirnoff %type <v.queue_opts> queue_opts queue_opt queue_opts_l 5143b3a8eb9SGleb Smirnoff %type <v.scrub_opts> scrub_opts scrub_opt scrub_opts_l 5153b3a8eb9SGleb Smirnoff %type <v.table_opts> table_opts table_opt table_opts_l 5163b3a8eb9SGleb Smirnoff %type <v.pool_opts> pool_opts pool_opt pool_opts_l 5173b3a8eb9SGleb Smirnoff %type <v.tagged> tagged 5183b3a8eb9SGleb Smirnoff %type <v.rtableid> rtable 5193b3a8eb9SGleb Smirnoff %% 5203b3a8eb9SGleb Smirnoff 5213b3a8eb9SGleb Smirnoff ruleset : /* empty */ 5223b3a8eb9SGleb Smirnoff | ruleset include '\n' 5233b3a8eb9SGleb Smirnoff | ruleset '\n' 5243b3a8eb9SGleb Smirnoff | ruleset option '\n' 5253b3a8eb9SGleb Smirnoff | ruleset scrubrule '\n' 5263b3a8eb9SGleb Smirnoff | ruleset natrule '\n' 5273b3a8eb9SGleb Smirnoff | ruleset binatrule '\n' 5283b3a8eb9SGleb Smirnoff | ruleset pfrule '\n' 5293b3a8eb9SGleb Smirnoff | ruleset anchorrule '\n' 5303b3a8eb9SGleb Smirnoff | ruleset loadrule '\n' 5313b3a8eb9SGleb Smirnoff | ruleset altqif '\n' 5323b3a8eb9SGleb Smirnoff | ruleset queuespec '\n' 5333b3a8eb9SGleb Smirnoff | ruleset varset '\n' 5343b3a8eb9SGleb Smirnoff | ruleset antispoof '\n' 5353b3a8eb9SGleb Smirnoff | ruleset tabledef '\n' 5363b3a8eb9SGleb Smirnoff | '{' fakeanchor '}' '\n'; 5373b3a8eb9SGleb Smirnoff | ruleset error '\n' { file->errors++; } 5383b3a8eb9SGleb Smirnoff ; 5393b3a8eb9SGleb Smirnoff 5403b3a8eb9SGleb Smirnoff include : INCLUDE STRING { 5413b3a8eb9SGleb Smirnoff struct file *nfile; 5423b3a8eb9SGleb Smirnoff 5433b3a8eb9SGleb Smirnoff if ((nfile = pushfile($2, 0)) == NULL) { 5443b3a8eb9SGleb Smirnoff yyerror("failed to include file %s", $2); 5453b3a8eb9SGleb Smirnoff free($2); 5463b3a8eb9SGleb Smirnoff YYERROR; 5473b3a8eb9SGleb Smirnoff } 5483b3a8eb9SGleb Smirnoff free($2); 5493b3a8eb9SGleb Smirnoff 5503b3a8eb9SGleb Smirnoff file = nfile; 5513b3a8eb9SGleb Smirnoff lungetc('\n'); 5523b3a8eb9SGleb Smirnoff } 5533b3a8eb9SGleb Smirnoff ; 5543b3a8eb9SGleb Smirnoff 5553b3a8eb9SGleb Smirnoff /* 5563b3a8eb9SGleb Smirnoff * apply to previouslys specified rule: must be careful to note 5573b3a8eb9SGleb Smirnoff * what that is: pf or nat or binat or rdr 5583b3a8eb9SGleb Smirnoff */ 5593b3a8eb9SGleb Smirnoff fakeanchor : fakeanchor '\n' 5603b3a8eb9SGleb Smirnoff | fakeanchor anchorrule '\n' 5613b3a8eb9SGleb Smirnoff | fakeanchor binatrule '\n' 5623b3a8eb9SGleb Smirnoff | fakeanchor natrule '\n' 5633b3a8eb9SGleb Smirnoff | fakeanchor pfrule '\n' 5643b3a8eb9SGleb Smirnoff | fakeanchor error '\n' 5653b3a8eb9SGleb Smirnoff ; 5663b3a8eb9SGleb Smirnoff 5673b3a8eb9SGleb Smirnoff optimizer : string { 5683b3a8eb9SGleb Smirnoff if (!strcmp($1, "none")) 5693b3a8eb9SGleb Smirnoff $$ = 0; 5703b3a8eb9SGleb Smirnoff else if (!strcmp($1, "basic")) 5713b3a8eb9SGleb Smirnoff $$ = PF_OPTIMIZE_BASIC; 5723b3a8eb9SGleb Smirnoff else if (!strcmp($1, "profile")) 5733b3a8eb9SGleb Smirnoff $$ = PF_OPTIMIZE_BASIC | PF_OPTIMIZE_PROFILE; 5743b3a8eb9SGleb Smirnoff else { 5753b3a8eb9SGleb Smirnoff yyerror("unknown ruleset-optimization %s", $1); 5763b3a8eb9SGleb Smirnoff YYERROR; 5773b3a8eb9SGleb Smirnoff } 5783b3a8eb9SGleb Smirnoff } 5793b3a8eb9SGleb Smirnoff ; 5803b3a8eb9SGleb Smirnoff 5813b3a8eb9SGleb Smirnoff option : SET OPTIMIZATION STRING { 5823b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION)) { 5833b3a8eb9SGleb Smirnoff free($3); 5843b3a8eb9SGleb Smirnoff YYERROR; 5853b3a8eb9SGleb Smirnoff } 5863b3a8eb9SGleb Smirnoff if (pfctl_set_optimization(pf, $3) != 0) { 5873b3a8eb9SGleb Smirnoff yyerror("unknown optimization %s", $3); 5883b3a8eb9SGleb Smirnoff free($3); 5893b3a8eb9SGleb Smirnoff YYERROR; 5903b3a8eb9SGleb Smirnoff } 5913b3a8eb9SGleb Smirnoff free($3); 5923b3a8eb9SGleb Smirnoff } 5933b3a8eb9SGleb Smirnoff | SET RULESET_OPTIMIZATION optimizer { 5943b3a8eb9SGleb Smirnoff if (!(pf->opts & PF_OPT_OPTIMIZE)) { 5953b3a8eb9SGleb Smirnoff pf->opts |= PF_OPT_OPTIMIZE; 5963b3a8eb9SGleb Smirnoff pf->optimize = $3; 5973b3a8eb9SGleb Smirnoff } 5983b3a8eb9SGleb Smirnoff } 5993b3a8eb9SGleb Smirnoff | SET TIMEOUT timeout_spec 6003b3a8eb9SGleb Smirnoff | SET TIMEOUT '{' optnl timeout_list '}' 6013b3a8eb9SGleb Smirnoff | SET LIMIT limit_spec 6023b3a8eb9SGleb Smirnoff | SET LIMIT '{' optnl limit_list '}' 6033b3a8eb9SGleb Smirnoff | SET LOGINTERFACE stringall { 6043b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION)) { 6053b3a8eb9SGleb Smirnoff free($3); 6063b3a8eb9SGleb Smirnoff YYERROR; 6073b3a8eb9SGleb Smirnoff } 6083b3a8eb9SGleb Smirnoff if (pfctl_set_logif(pf, $3) != 0) { 6093b3a8eb9SGleb Smirnoff yyerror("error setting loginterface %s", $3); 6103b3a8eb9SGleb Smirnoff free($3); 6113b3a8eb9SGleb Smirnoff YYERROR; 6123b3a8eb9SGleb Smirnoff } 6133b3a8eb9SGleb Smirnoff free($3); 6143b3a8eb9SGleb Smirnoff } 6153b3a8eb9SGleb Smirnoff | SET HOSTID number { 6163b3a8eb9SGleb Smirnoff if ($3 == 0 || $3 > UINT_MAX) { 6173b3a8eb9SGleb Smirnoff yyerror("hostid must be non-zero"); 6183b3a8eb9SGleb Smirnoff YYERROR; 6193b3a8eb9SGleb Smirnoff } 6203b3a8eb9SGleb Smirnoff if (pfctl_set_hostid(pf, $3) != 0) { 6213b3a8eb9SGleb Smirnoff yyerror("error setting hostid %08x", $3); 6223b3a8eb9SGleb Smirnoff YYERROR; 6233b3a8eb9SGleb Smirnoff } 6243b3a8eb9SGleb Smirnoff } 6253b3a8eb9SGleb Smirnoff | SET BLOCKPOLICY DROP { 6263b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 6273b3a8eb9SGleb Smirnoff printf("set block-policy drop\n"); 6283b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION)) 6293b3a8eb9SGleb Smirnoff YYERROR; 6303b3a8eb9SGleb Smirnoff blockpolicy = PFRULE_DROP; 6313b3a8eb9SGleb Smirnoff } 6323b3a8eb9SGleb Smirnoff | SET BLOCKPOLICY RETURN { 6333b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 6343b3a8eb9SGleb Smirnoff printf("set block-policy return\n"); 6353b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION)) 6363b3a8eb9SGleb Smirnoff YYERROR; 6373b3a8eb9SGleb Smirnoff blockpolicy = PFRULE_RETURN; 6383b3a8eb9SGleb Smirnoff } 6393b3a8eb9SGleb Smirnoff | SET REQUIREORDER yesno { 6403b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 6413b3a8eb9SGleb Smirnoff printf("set require-order %s\n", 6423b3a8eb9SGleb Smirnoff $3 == 1 ? "yes" : "no"); 6433b3a8eb9SGleb Smirnoff require_order = $3; 6443b3a8eb9SGleb Smirnoff } 6453b3a8eb9SGleb Smirnoff | SET FINGERPRINTS STRING { 6463b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 6473b3a8eb9SGleb Smirnoff printf("set fingerprints \"%s\"\n", $3); 6483b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION)) { 6493b3a8eb9SGleb Smirnoff free($3); 6503b3a8eb9SGleb Smirnoff YYERROR; 6513b3a8eb9SGleb Smirnoff } 6523b3a8eb9SGleb Smirnoff if (!pf->anchor->name[0]) { 6533b3a8eb9SGleb Smirnoff if (pfctl_file_fingerprints(pf->dev, 6543b3a8eb9SGleb Smirnoff pf->opts, $3)) { 6553b3a8eb9SGleb Smirnoff yyerror("error loading " 6563b3a8eb9SGleb Smirnoff "fingerprints %s", $3); 6573b3a8eb9SGleb Smirnoff free($3); 6583b3a8eb9SGleb Smirnoff YYERROR; 6593b3a8eb9SGleb Smirnoff } 6603b3a8eb9SGleb Smirnoff } 6613b3a8eb9SGleb Smirnoff free($3); 6623b3a8eb9SGleb Smirnoff } 6633b3a8eb9SGleb Smirnoff | SET STATEPOLICY statelock { 6643b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 6653b3a8eb9SGleb Smirnoff switch ($3) { 6663b3a8eb9SGleb Smirnoff case 0: 6673b3a8eb9SGleb Smirnoff printf("set state-policy floating\n"); 6683b3a8eb9SGleb Smirnoff break; 6693b3a8eb9SGleb Smirnoff case PFRULE_IFBOUND: 6703b3a8eb9SGleb Smirnoff printf("set state-policy if-bound\n"); 6713b3a8eb9SGleb Smirnoff break; 6723b3a8eb9SGleb Smirnoff } 6733b3a8eb9SGleb Smirnoff default_statelock = $3; 6743b3a8eb9SGleb Smirnoff } 6753b3a8eb9SGleb Smirnoff | SET DEBUG STRING { 6763b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION)) { 6773b3a8eb9SGleb Smirnoff free($3); 6783b3a8eb9SGleb Smirnoff YYERROR; 6793b3a8eb9SGleb Smirnoff } 6803b3a8eb9SGleb Smirnoff if (pfctl_set_debug(pf, $3) != 0) { 6813b3a8eb9SGleb Smirnoff yyerror("error setting debuglevel %s", $3); 6823b3a8eb9SGleb Smirnoff free($3); 6833b3a8eb9SGleb Smirnoff YYERROR; 6843b3a8eb9SGleb Smirnoff } 6853b3a8eb9SGleb Smirnoff free($3); 6863b3a8eb9SGleb Smirnoff } 6873b3a8eb9SGleb Smirnoff | SET SKIP interface { 6883b3a8eb9SGleb Smirnoff if (expand_skip_interface($3) != 0) { 6893b3a8eb9SGleb Smirnoff yyerror("error setting skip interface(s)"); 6903b3a8eb9SGleb Smirnoff YYERROR; 6913b3a8eb9SGleb Smirnoff } 6923b3a8eb9SGleb Smirnoff } 6933b3a8eb9SGleb Smirnoff | SET STATEDEFAULTS state_opt_list { 6943b3a8eb9SGleb Smirnoff if (keep_state_defaults != NULL) { 6953b3a8eb9SGleb Smirnoff yyerror("cannot redefine state-defaults"); 6963b3a8eb9SGleb Smirnoff YYERROR; 6973b3a8eb9SGleb Smirnoff } 6983b3a8eb9SGleb Smirnoff keep_state_defaults = $3; 6993b3a8eb9SGleb Smirnoff } 7003b3a8eb9SGleb Smirnoff ; 7013b3a8eb9SGleb Smirnoff 7023b3a8eb9SGleb Smirnoff stringall : STRING { $$ = $1; } 7033b3a8eb9SGleb Smirnoff | ALL { 7043b3a8eb9SGleb Smirnoff if (($$ = strdup("all")) == NULL) { 7053b3a8eb9SGleb Smirnoff err(1, "stringall: strdup"); 7063b3a8eb9SGleb Smirnoff } 7073b3a8eb9SGleb Smirnoff } 7083b3a8eb9SGleb Smirnoff ; 7093b3a8eb9SGleb Smirnoff 7103b3a8eb9SGleb Smirnoff string : STRING string { 7113b3a8eb9SGleb Smirnoff if (asprintf(&$$, "%s %s", $1, $2) == -1) 7123b3a8eb9SGleb Smirnoff err(1, "string: asprintf"); 7133b3a8eb9SGleb Smirnoff free($1); 7143b3a8eb9SGleb Smirnoff free($2); 7153b3a8eb9SGleb Smirnoff } 7163b3a8eb9SGleb Smirnoff | STRING 7173b3a8eb9SGleb Smirnoff ; 7183b3a8eb9SGleb Smirnoff 7193b3a8eb9SGleb Smirnoff varstring : numberstring varstring { 7203b3a8eb9SGleb Smirnoff if (asprintf(&$$, "%s %s", $1, $2) == -1) 7213b3a8eb9SGleb Smirnoff err(1, "string: asprintf"); 7223b3a8eb9SGleb Smirnoff free($1); 7233b3a8eb9SGleb Smirnoff free($2); 7243b3a8eb9SGleb Smirnoff } 7253b3a8eb9SGleb Smirnoff | numberstring 7263b3a8eb9SGleb Smirnoff ; 7273b3a8eb9SGleb Smirnoff 7283b3a8eb9SGleb Smirnoff numberstring : NUMBER { 7293b3a8eb9SGleb Smirnoff char *s; 7303b3a8eb9SGleb Smirnoff if (asprintf(&s, "%lld", (long long)$1) == -1) { 7313b3a8eb9SGleb Smirnoff yyerror("string: asprintf"); 7323b3a8eb9SGleb Smirnoff YYERROR; 7333b3a8eb9SGleb Smirnoff } 7343b3a8eb9SGleb Smirnoff $$ = s; 7353b3a8eb9SGleb Smirnoff } 7363b3a8eb9SGleb Smirnoff | STRING 7373b3a8eb9SGleb Smirnoff ; 7383b3a8eb9SGleb Smirnoff 7393b3a8eb9SGleb Smirnoff varset : STRING '=' varstring { 7403b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 7413b3a8eb9SGleb Smirnoff printf("%s = \"%s\"\n", $1, $3); 7423b3a8eb9SGleb Smirnoff if (symset($1, $3, 0) == -1) 7433b3a8eb9SGleb Smirnoff err(1, "cannot store variable %s", $1); 7443b3a8eb9SGleb Smirnoff free($1); 7453b3a8eb9SGleb Smirnoff free($3); 7463b3a8eb9SGleb Smirnoff } 7473b3a8eb9SGleb Smirnoff ; 7483b3a8eb9SGleb Smirnoff 7493b3a8eb9SGleb Smirnoff anchorname : STRING { $$ = $1; } 7503b3a8eb9SGleb Smirnoff | /* empty */ { $$ = NULL; } 7513b3a8eb9SGleb Smirnoff ; 7523b3a8eb9SGleb Smirnoff 7533b3a8eb9SGleb Smirnoff pfa_anchorlist : /* empty */ 7543b3a8eb9SGleb Smirnoff | pfa_anchorlist '\n' 7553b3a8eb9SGleb Smirnoff | pfa_anchorlist pfrule '\n' 7563b3a8eb9SGleb Smirnoff | pfa_anchorlist anchorrule '\n' 7573b3a8eb9SGleb Smirnoff ; 7583b3a8eb9SGleb Smirnoff 7593b3a8eb9SGleb Smirnoff pfa_anchor : '{' 7603b3a8eb9SGleb Smirnoff { 7613b3a8eb9SGleb Smirnoff char ta[PF_ANCHOR_NAME_SIZE]; 7623b3a8eb9SGleb Smirnoff struct pf_ruleset *rs; 7633b3a8eb9SGleb Smirnoff 7643b3a8eb9SGleb Smirnoff /* steping into a brace anchor */ 7653b3a8eb9SGleb Smirnoff pf->asd++; 7663b3a8eb9SGleb Smirnoff pf->bn++; 7673b3a8eb9SGleb Smirnoff pf->brace = 1; 7683b3a8eb9SGleb Smirnoff 7693b3a8eb9SGleb Smirnoff /* create a holding ruleset in the root */ 7703b3a8eb9SGleb Smirnoff snprintf(ta, PF_ANCHOR_NAME_SIZE, "_%d", pf->bn); 7713b3a8eb9SGleb Smirnoff rs = pf_find_or_create_ruleset(ta); 7723b3a8eb9SGleb Smirnoff if (rs == NULL) 7733b3a8eb9SGleb Smirnoff err(1, "pfa_anchor: pf_find_or_create_ruleset"); 7743b3a8eb9SGleb Smirnoff pf->astack[pf->asd] = rs->anchor; 7753b3a8eb9SGleb Smirnoff pf->anchor = rs->anchor; 7763b3a8eb9SGleb Smirnoff } '\n' pfa_anchorlist '}' 7773b3a8eb9SGleb Smirnoff { 7783b3a8eb9SGleb Smirnoff pf->alast = pf->anchor; 7793b3a8eb9SGleb Smirnoff pf->asd--; 7803b3a8eb9SGleb Smirnoff pf->anchor = pf->astack[pf->asd]; 7813b3a8eb9SGleb Smirnoff } 7823b3a8eb9SGleb Smirnoff | /* empty */ 7833b3a8eb9SGleb Smirnoff ; 7843b3a8eb9SGleb Smirnoff 7853b3a8eb9SGleb Smirnoff anchorrule : ANCHOR anchorname dir quick interface af proto fromto 7863b3a8eb9SGleb Smirnoff filter_opts pfa_anchor 7873b3a8eb9SGleb Smirnoff { 7883b3a8eb9SGleb Smirnoff struct pf_rule r; 7893b3a8eb9SGleb Smirnoff struct node_proto *proto; 7903b3a8eb9SGleb Smirnoff 7913b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_FILTER)) { 7923b3a8eb9SGleb Smirnoff if ($2) 7933b3a8eb9SGleb Smirnoff free($2); 7943b3a8eb9SGleb Smirnoff YYERROR; 7953b3a8eb9SGleb Smirnoff } 7963b3a8eb9SGleb Smirnoff 7973b3a8eb9SGleb Smirnoff if ($2 && ($2[0] == '_' || strstr($2, "/_") != NULL)) { 7983b3a8eb9SGleb Smirnoff free($2); 7993b3a8eb9SGleb Smirnoff yyerror("anchor names beginning with '_' " 8003b3a8eb9SGleb Smirnoff "are reserved for internal use"); 8013b3a8eb9SGleb Smirnoff YYERROR; 8023b3a8eb9SGleb Smirnoff } 8033b3a8eb9SGleb Smirnoff 8043b3a8eb9SGleb Smirnoff memset(&r, 0, sizeof(r)); 8053b3a8eb9SGleb Smirnoff if (pf->astack[pf->asd + 1]) { 8063b3a8eb9SGleb Smirnoff /* move inline rules into relative location */ 8073b3a8eb9SGleb Smirnoff pf_anchor_setup(&r, 8083b3a8eb9SGleb Smirnoff &pf->astack[pf->asd]->ruleset, 8093b3a8eb9SGleb Smirnoff $2 ? $2 : pf->alast->name); 8103b3a8eb9SGleb Smirnoff 8113b3a8eb9SGleb Smirnoff if (r.anchor == NULL) 8123b3a8eb9SGleb Smirnoff err(1, "anchorrule: unable to " 8133b3a8eb9SGleb Smirnoff "create ruleset"); 8143b3a8eb9SGleb Smirnoff 8153b3a8eb9SGleb Smirnoff if (pf->alast != r.anchor) { 8163b3a8eb9SGleb Smirnoff if (r.anchor->match) { 8173b3a8eb9SGleb Smirnoff yyerror("inline anchor '%s' " 8183b3a8eb9SGleb Smirnoff "already exists", 8193b3a8eb9SGleb Smirnoff r.anchor->name); 8203b3a8eb9SGleb Smirnoff YYERROR; 8213b3a8eb9SGleb Smirnoff } 8223b3a8eb9SGleb Smirnoff mv_rules(&pf->alast->ruleset, 8233b3a8eb9SGleb Smirnoff &r.anchor->ruleset); 8243b3a8eb9SGleb Smirnoff } 8253b3a8eb9SGleb Smirnoff pf_remove_if_empty_ruleset(&pf->alast->ruleset); 8263b3a8eb9SGleb Smirnoff pf->alast = r.anchor; 8273b3a8eb9SGleb Smirnoff } else { 8283b3a8eb9SGleb Smirnoff if (!$2) { 8293b3a8eb9SGleb Smirnoff yyerror("anchors without explicit " 8303b3a8eb9SGleb Smirnoff "rules must specify a name"); 8313b3a8eb9SGleb Smirnoff YYERROR; 8323b3a8eb9SGleb Smirnoff } 8333b3a8eb9SGleb Smirnoff } 8343b3a8eb9SGleb Smirnoff r.direction = $3; 8353b3a8eb9SGleb Smirnoff r.quick = $4.quick; 8363b3a8eb9SGleb Smirnoff r.af = $6; 8373b3a8eb9SGleb Smirnoff r.prob = $9.prob; 8383b3a8eb9SGleb Smirnoff r.rtableid = $9.rtableid; 8393b3a8eb9SGleb Smirnoff 8403b3a8eb9SGleb Smirnoff if ($9.tag) 8413b3a8eb9SGleb Smirnoff if (strlcpy(r.tagname, $9.tag, 8423b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 8433b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars", 8443b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1); 8453b3a8eb9SGleb Smirnoff YYERROR; 8463b3a8eb9SGleb Smirnoff } 8473b3a8eb9SGleb Smirnoff if ($9.match_tag) 8483b3a8eb9SGleb Smirnoff if (strlcpy(r.match_tagname, $9.match_tag, 8493b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 8503b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars", 8513b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1); 8523b3a8eb9SGleb Smirnoff YYERROR; 8533b3a8eb9SGleb Smirnoff } 8543b3a8eb9SGleb Smirnoff r.match_tag_not = $9.match_tag_not; 8553b3a8eb9SGleb Smirnoff if (rule_label(&r, $9.label)) 8563b3a8eb9SGleb Smirnoff YYERROR; 8573b3a8eb9SGleb Smirnoff free($9.label); 8583b3a8eb9SGleb Smirnoff r.flags = $9.flags.b1; 8593b3a8eb9SGleb Smirnoff r.flagset = $9.flags.b2; 8603b3a8eb9SGleb Smirnoff if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) { 8613b3a8eb9SGleb Smirnoff yyerror("flags always false"); 8623b3a8eb9SGleb Smirnoff YYERROR; 8633b3a8eb9SGleb Smirnoff } 8643b3a8eb9SGleb Smirnoff if ($9.flags.b1 || $9.flags.b2 || $8.src_os) { 8653b3a8eb9SGleb Smirnoff for (proto = $7; proto != NULL && 8663b3a8eb9SGleb Smirnoff proto->proto != IPPROTO_TCP; 8673b3a8eb9SGleb Smirnoff proto = proto->next) 8683b3a8eb9SGleb Smirnoff ; /* nothing */ 8693b3a8eb9SGleb Smirnoff if (proto == NULL && $7 != NULL) { 8703b3a8eb9SGleb Smirnoff if ($9.flags.b1 || $9.flags.b2) 8713b3a8eb9SGleb Smirnoff yyerror( 8723b3a8eb9SGleb Smirnoff "flags only apply to tcp"); 8733b3a8eb9SGleb Smirnoff if ($8.src_os) 8743b3a8eb9SGleb Smirnoff yyerror( 8753b3a8eb9SGleb Smirnoff "OS fingerprinting only " 8763b3a8eb9SGleb Smirnoff "applies to tcp"); 8773b3a8eb9SGleb Smirnoff YYERROR; 8783b3a8eb9SGleb Smirnoff } 8793b3a8eb9SGleb Smirnoff } 8803b3a8eb9SGleb Smirnoff 8813b3a8eb9SGleb Smirnoff r.tos = $9.tos; 8823b3a8eb9SGleb Smirnoff 8833b3a8eb9SGleb Smirnoff if ($9.keep.action) { 8843b3a8eb9SGleb Smirnoff yyerror("cannot specify state handling " 8853b3a8eb9SGleb Smirnoff "on anchors"); 8863b3a8eb9SGleb Smirnoff YYERROR; 8873b3a8eb9SGleb Smirnoff } 8883b3a8eb9SGleb Smirnoff 8893b3a8eb9SGleb Smirnoff if ($9.match_tag) 8903b3a8eb9SGleb Smirnoff if (strlcpy(r.match_tagname, $9.match_tag, 8913b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 8923b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars", 8933b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1); 8943b3a8eb9SGleb Smirnoff YYERROR; 8953b3a8eb9SGleb Smirnoff } 8963b3a8eb9SGleb Smirnoff r.match_tag_not = $9.match_tag_not; 8973e248e0fSKristof Provost if ($9.marker & FOM_PRIO) { 8983e248e0fSKristof Provost if ($9.prio == 0) 8993e248e0fSKristof Provost r.prio = PF_PRIO_ZERO; 9003e248e0fSKristof Provost else 9013e248e0fSKristof Provost r.prio = $9.prio; 9023e248e0fSKristof Provost } 9033e248e0fSKristof Provost if ($9.marker & FOM_SETPRIO) { 9043e248e0fSKristof Provost r.set_prio[0] = $9.set_prio[0]; 9053e248e0fSKristof Provost r.set_prio[1] = $9.set_prio[1]; 9063e248e0fSKristof Provost r.scrub_flags |= PFSTATE_SETPRIO; 9073e248e0fSKristof Provost } 9083b3a8eb9SGleb Smirnoff 9093b3a8eb9SGleb Smirnoff decide_address_family($8.src.host, &r.af); 9103b3a8eb9SGleb Smirnoff decide_address_family($8.dst.host, &r.af); 9113b3a8eb9SGleb Smirnoff 9123b3a8eb9SGleb Smirnoff expand_rule(&r, $5, NULL, $7, $8.src_os, 9133b3a8eb9SGleb Smirnoff $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, 9143b3a8eb9SGleb Smirnoff $9.uid, $9.gid, $9.icmpspec, 9153b3a8eb9SGleb Smirnoff pf->astack[pf->asd + 1] ? pf->alast->name : $2); 9163b3a8eb9SGleb Smirnoff free($2); 9173b3a8eb9SGleb Smirnoff pf->astack[pf->asd + 1] = NULL; 9183b3a8eb9SGleb Smirnoff } 9193b3a8eb9SGleb Smirnoff | NATANCHOR string interface af proto fromto rtable { 9203b3a8eb9SGleb Smirnoff struct pf_rule r; 9213b3a8eb9SGleb Smirnoff 9223b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_NAT)) { 9233b3a8eb9SGleb Smirnoff free($2); 9243b3a8eb9SGleb Smirnoff YYERROR; 9253b3a8eb9SGleb Smirnoff } 9263b3a8eb9SGleb Smirnoff 9273b3a8eb9SGleb Smirnoff memset(&r, 0, sizeof(r)); 9283b3a8eb9SGleb Smirnoff r.action = PF_NAT; 9293b3a8eb9SGleb Smirnoff r.af = $4; 9303b3a8eb9SGleb Smirnoff r.rtableid = $7; 9313b3a8eb9SGleb Smirnoff 9323b3a8eb9SGleb Smirnoff decide_address_family($6.src.host, &r.af); 9333b3a8eb9SGleb Smirnoff decide_address_family($6.dst.host, &r.af); 9343b3a8eb9SGleb Smirnoff 9353b3a8eb9SGleb Smirnoff expand_rule(&r, $3, NULL, $5, $6.src_os, 9363b3a8eb9SGleb Smirnoff $6.src.host, $6.src.port, $6.dst.host, $6.dst.port, 9373b3a8eb9SGleb Smirnoff 0, 0, 0, $2); 9383b3a8eb9SGleb Smirnoff free($2); 9393b3a8eb9SGleb Smirnoff } 9403b3a8eb9SGleb Smirnoff | RDRANCHOR string interface af proto fromto rtable { 9413b3a8eb9SGleb Smirnoff struct pf_rule r; 9423b3a8eb9SGleb Smirnoff 9433b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_NAT)) { 9443b3a8eb9SGleb Smirnoff free($2); 9453b3a8eb9SGleb Smirnoff YYERROR; 9463b3a8eb9SGleb Smirnoff } 9473b3a8eb9SGleb Smirnoff 9483b3a8eb9SGleb Smirnoff memset(&r, 0, sizeof(r)); 9493b3a8eb9SGleb Smirnoff r.action = PF_RDR; 9503b3a8eb9SGleb Smirnoff r.af = $4; 9513b3a8eb9SGleb Smirnoff r.rtableid = $7; 9523b3a8eb9SGleb Smirnoff 9533b3a8eb9SGleb Smirnoff decide_address_family($6.src.host, &r.af); 9543b3a8eb9SGleb Smirnoff decide_address_family($6.dst.host, &r.af); 9553b3a8eb9SGleb Smirnoff 9563b3a8eb9SGleb Smirnoff if ($6.src.port != NULL) { 9573b3a8eb9SGleb Smirnoff yyerror("source port parameter not supported" 9583b3a8eb9SGleb Smirnoff " in rdr-anchor"); 9593b3a8eb9SGleb Smirnoff YYERROR; 9603b3a8eb9SGleb Smirnoff } 9613b3a8eb9SGleb Smirnoff if ($6.dst.port != NULL) { 9623b3a8eb9SGleb Smirnoff if ($6.dst.port->next != NULL) { 9633b3a8eb9SGleb Smirnoff yyerror("destination port list " 9643b3a8eb9SGleb Smirnoff "expansion not supported in " 9653b3a8eb9SGleb Smirnoff "rdr-anchor"); 9663b3a8eb9SGleb Smirnoff YYERROR; 9673b3a8eb9SGleb Smirnoff } else if ($6.dst.port->op != PF_OP_EQ) { 9683b3a8eb9SGleb Smirnoff yyerror("destination port operators" 9693b3a8eb9SGleb Smirnoff " not supported in rdr-anchor"); 9703b3a8eb9SGleb Smirnoff YYERROR; 9713b3a8eb9SGleb Smirnoff } 9723b3a8eb9SGleb Smirnoff r.dst.port[0] = $6.dst.port->port[0]; 9733b3a8eb9SGleb Smirnoff r.dst.port[1] = $6.dst.port->port[1]; 9743b3a8eb9SGleb Smirnoff r.dst.port_op = $6.dst.port->op; 9753b3a8eb9SGleb Smirnoff } 9763b3a8eb9SGleb Smirnoff 9773b3a8eb9SGleb Smirnoff expand_rule(&r, $3, NULL, $5, $6.src_os, 9783b3a8eb9SGleb Smirnoff $6.src.host, $6.src.port, $6.dst.host, $6.dst.port, 9793b3a8eb9SGleb Smirnoff 0, 0, 0, $2); 9803b3a8eb9SGleb Smirnoff free($2); 9813b3a8eb9SGleb Smirnoff } 9823b3a8eb9SGleb Smirnoff | BINATANCHOR string interface af proto fromto rtable { 9833b3a8eb9SGleb Smirnoff struct pf_rule r; 9843b3a8eb9SGleb Smirnoff 9853b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_NAT)) { 9863b3a8eb9SGleb Smirnoff free($2); 9873b3a8eb9SGleb Smirnoff YYERROR; 9883b3a8eb9SGleb Smirnoff } 9893b3a8eb9SGleb Smirnoff 9903b3a8eb9SGleb Smirnoff memset(&r, 0, sizeof(r)); 9913b3a8eb9SGleb Smirnoff r.action = PF_BINAT; 9923b3a8eb9SGleb Smirnoff r.af = $4; 9933b3a8eb9SGleb Smirnoff r.rtableid = $7; 9943b3a8eb9SGleb Smirnoff if ($5 != NULL) { 9953b3a8eb9SGleb Smirnoff if ($5->next != NULL) { 9963b3a8eb9SGleb Smirnoff yyerror("proto list expansion" 9973b3a8eb9SGleb Smirnoff " not supported in binat-anchor"); 9983b3a8eb9SGleb Smirnoff YYERROR; 9993b3a8eb9SGleb Smirnoff } 10003b3a8eb9SGleb Smirnoff r.proto = $5->proto; 10013b3a8eb9SGleb Smirnoff free($5); 10023b3a8eb9SGleb Smirnoff } 10033b3a8eb9SGleb Smirnoff 10043b3a8eb9SGleb Smirnoff if ($6.src.host != NULL || $6.src.port != NULL || 10053b3a8eb9SGleb Smirnoff $6.dst.host != NULL || $6.dst.port != NULL) { 10063b3a8eb9SGleb Smirnoff yyerror("fromto parameter not supported" 10073b3a8eb9SGleb Smirnoff " in binat-anchor"); 10083b3a8eb9SGleb Smirnoff YYERROR; 10093b3a8eb9SGleb Smirnoff } 10103b3a8eb9SGleb Smirnoff 10113b3a8eb9SGleb Smirnoff decide_address_family($6.src.host, &r.af); 10123b3a8eb9SGleb Smirnoff decide_address_family($6.dst.host, &r.af); 10133b3a8eb9SGleb Smirnoff 10143b3a8eb9SGleb Smirnoff pfctl_add_rule(pf, &r, $2); 10153b3a8eb9SGleb Smirnoff free($2); 10163b3a8eb9SGleb Smirnoff } 10173b3a8eb9SGleb Smirnoff ; 10183b3a8eb9SGleb Smirnoff 10193b3a8eb9SGleb Smirnoff loadrule : LOAD ANCHOR string FROM string { 10203b3a8eb9SGleb Smirnoff struct loadanchors *loadanchor; 10213b3a8eb9SGleb Smirnoff 10223b3a8eb9SGleb Smirnoff if (strlen(pf->anchor->name) + 1 + 10233b3a8eb9SGleb Smirnoff strlen($3) >= MAXPATHLEN) { 10243b3a8eb9SGleb Smirnoff yyerror("anchorname %s too long, max %u\n", 10253b3a8eb9SGleb Smirnoff $3, MAXPATHLEN - 1); 10263b3a8eb9SGleb Smirnoff free($3); 10273b3a8eb9SGleb Smirnoff YYERROR; 10283b3a8eb9SGleb Smirnoff } 10293b3a8eb9SGleb Smirnoff loadanchor = calloc(1, sizeof(struct loadanchors)); 10303b3a8eb9SGleb Smirnoff if (loadanchor == NULL) 10313b3a8eb9SGleb Smirnoff err(1, "loadrule: calloc"); 10323b3a8eb9SGleb Smirnoff if ((loadanchor->anchorname = malloc(MAXPATHLEN)) == 10333b3a8eb9SGleb Smirnoff NULL) 10343b3a8eb9SGleb Smirnoff err(1, "loadrule: malloc"); 10353b3a8eb9SGleb Smirnoff if (pf->anchor->name[0]) 10363b3a8eb9SGleb Smirnoff snprintf(loadanchor->anchorname, MAXPATHLEN, 10373b3a8eb9SGleb Smirnoff "%s/%s", pf->anchor->name, $3); 10383b3a8eb9SGleb Smirnoff else 10393b3a8eb9SGleb Smirnoff strlcpy(loadanchor->anchorname, $3, MAXPATHLEN); 10403b3a8eb9SGleb Smirnoff if ((loadanchor->filename = strdup($5)) == NULL) 10413b3a8eb9SGleb Smirnoff err(1, "loadrule: strdup"); 10423b3a8eb9SGleb Smirnoff 10433b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(&loadanchorshead, loadanchor, 10443b3a8eb9SGleb Smirnoff entries); 10453b3a8eb9SGleb Smirnoff 10463b3a8eb9SGleb Smirnoff free($3); 10473b3a8eb9SGleb Smirnoff free($5); 10483b3a8eb9SGleb Smirnoff }; 10493b3a8eb9SGleb Smirnoff 10503b3a8eb9SGleb Smirnoff scrubaction : no SCRUB { 10513b3a8eb9SGleb Smirnoff $$.b2 = $$.w = 0; 10523b3a8eb9SGleb Smirnoff if ($1) 10533b3a8eb9SGleb Smirnoff $$.b1 = PF_NOSCRUB; 10543b3a8eb9SGleb Smirnoff else 10553b3a8eb9SGleb Smirnoff $$.b1 = PF_SCRUB; 10563b3a8eb9SGleb Smirnoff } 10573b3a8eb9SGleb Smirnoff ; 10583b3a8eb9SGleb Smirnoff 10593b3a8eb9SGleb Smirnoff scrubrule : scrubaction dir logquick interface af proto fromto scrub_opts 10603b3a8eb9SGleb Smirnoff { 10613b3a8eb9SGleb Smirnoff struct pf_rule r; 10623b3a8eb9SGleb Smirnoff 10633b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_SCRUB)) 10643b3a8eb9SGleb Smirnoff YYERROR; 10653b3a8eb9SGleb Smirnoff 10663b3a8eb9SGleb Smirnoff memset(&r, 0, sizeof(r)); 10673b3a8eb9SGleb Smirnoff 10683b3a8eb9SGleb Smirnoff r.action = $1.b1; 10693b3a8eb9SGleb Smirnoff r.direction = $2; 10703b3a8eb9SGleb Smirnoff 10713b3a8eb9SGleb Smirnoff r.log = $3.log; 10723b3a8eb9SGleb Smirnoff r.logif = $3.logif; 10733b3a8eb9SGleb Smirnoff if ($3.quick) { 10743b3a8eb9SGleb Smirnoff yyerror("scrub rules do not support 'quick'"); 10753b3a8eb9SGleb Smirnoff YYERROR; 10763b3a8eb9SGleb Smirnoff } 10773b3a8eb9SGleb Smirnoff 10783b3a8eb9SGleb Smirnoff r.af = $5; 10793b3a8eb9SGleb Smirnoff if ($8.nodf) 10803b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_NODF; 10813b3a8eb9SGleb Smirnoff if ($8.randomid) 10823b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_RANDOMID; 10833b3a8eb9SGleb Smirnoff if ($8.reassemble_tcp) { 10843b3a8eb9SGleb Smirnoff if (r.direction != PF_INOUT) { 10853b3a8eb9SGleb Smirnoff yyerror("reassemble tcp rules can not " 10863b3a8eb9SGleb Smirnoff "specify direction"); 10873b3a8eb9SGleb Smirnoff YYERROR; 10883b3a8eb9SGleb Smirnoff } 10893b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_REASSEMBLE_TCP; 10903b3a8eb9SGleb Smirnoff } 10913b3a8eb9SGleb Smirnoff if ($8.minttl) 10923b3a8eb9SGleb Smirnoff r.min_ttl = $8.minttl; 10933b3a8eb9SGleb Smirnoff if ($8.maxmss) 10943b3a8eb9SGleb Smirnoff r.max_mss = $8.maxmss; 10953b3a8eb9SGleb Smirnoff if ($8.marker & SOM_SETTOS) { 10963b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_SET_TOS; 10973b3a8eb9SGleb Smirnoff r.set_tos = $8.settos; 10983b3a8eb9SGleb Smirnoff } 10993b3a8eb9SGleb Smirnoff if ($8.fragcache) 11003b3a8eb9SGleb Smirnoff r.rule_flag |= $8.fragcache; 11013b3a8eb9SGleb Smirnoff if ($8.match_tag) 11023b3a8eb9SGleb Smirnoff if (strlcpy(r.match_tagname, $8.match_tag, 11033b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 11043b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars", 11053b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1); 11063b3a8eb9SGleb Smirnoff YYERROR; 11073b3a8eb9SGleb Smirnoff } 11083b3a8eb9SGleb Smirnoff r.match_tag_not = $8.match_tag_not; 11093b3a8eb9SGleb Smirnoff r.rtableid = $8.rtableid; 11103b3a8eb9SGleb Smirnoff 11113b3a8eb9SGleb Smirnoff expand_rule(&r, $4, NULL, $6, $7.src_os, 11123b3a8eb9SGleb Smirnoff $7.src.host, $7.src.port, $7.dst.host, $7.dst.port, 11133b3a8eb9SGleb Smirnoff NULL, NULL, NULL, ""); 11143b3a8eb9SGleb Smirnoff } 11153b3a8eb9SGleb Smirnoff ; 11163b3a8eb9SGleb Smirnoff 11173b3a8eb9SGleb Smirnoff scrub_opts : { 11183b3a8eb9SGleb Smirnoff bzero(&scrub_opts, sizeof scrub_opts); 11193b3a8eb9SGleb Smirnoff scrub_opts.rtableid = -1; 11203b3a8eb9SGleb Smirnoff } 11213b3a8eb9SGleb Smirnoff scrub_opts_l 11223b3a8eb9SGleb Smirnoff { $$ = scrub_opts; } 11233b3a8eb9SGleb Smirnoff | /* empty */ { 11243b3a8eb9SGleb Smirnoff bzero(&scrub_opts, sizeof scrub_opts); 11253b3a8eb9SGleb Smirnoff scrub_opts.rtableid = -1; 11263b3a8eb9SGleb Smirnoff $$ = scrub_opts; 11273b3a8eb9SGleb Smirnoff } 11283b3a8eb9SGleb Smirnoff ; 11293b3a8eb9SGleb Smirnoff 11303b3a8eb9SGleb Smirnoff scrub_opts_l : scrub_opts_l scrub_opt 11313b3a8eb9SGleb Smirnoff | scrub_opt 11323b3a8eb9SGleb Smirnoff ; 11333b3a8eb9SGleb Smirnoff 11343b3a8eb9SGleb Smirnoff scrub_opt : NODF { 11353b3a8eb9SGleb Smirnoff if (scrub_opts.nodf) { 11363b3a8eb9SGleb Smirnoff yyerror("no-df cannot be respecified"); 11373b3a8eb9SGleb Smirnoff YYERROR; 11383b3a8eb9SGleb Smirnoff } 11393b3a8eb9SGleb Smirnoff scrub_opts.nodf = 1; 11403b3a8eb9SGleb Smirnoff } 11413b3a8eb9SGleb Smirnoff | MINTTL NUMBER { 11423b3a8eb9SGleb Smirnoff if (scrub_opts.marker & SOM_MINTTL) { 11433b3a8eb9SGleb Smirnoff yyerror("min-ttl cannot be respecified"); 11443b3a8eb9SGleb Smirnoff YYERROR; 11453b3a8eb9SGleb Smirnoff } 11463b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > 255) { 11473b3a8eb9SGleb Smirnoff yyerror("illegal min-ttl value %d", $2); 11483b3a8eb9SGleb Smirnoff YYERROR; 11493b3a8eb9SGleb Smirnoff } 11503b3a8eb9SGleb Smirnoff scrub_opts.marker |= SOM_MINTTL; 11513b3a8eb9SGleb Smirnoff scrub_opts.minttl = $2; 11523b3a8eb9SGleb Smirnoff } 11533b3a8eb9SGleb Smirnoff | MAXMSS NUMBER { 11543b3a8eb9SGleb Smirnoff if (scrub_opts.marker & SOM_MAXMSS) { 11553b3a8eb9SGleb Smirnoff yyerror("max-mss cannot be respecified"); 11563b3a8eb9SGleb Smirnoff YYERROR; 11573b3a8eb9SGleb Smirnoff } 11583b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > 65535) { 11593b3a8eb9SGleb Smirnoff yyerror("illegal max-mss value %d", $2); 11603b3a8eb9SGleb Smirnoff YYERROR; 11613b3a8eb9SGleb Smirnoff } 11623b3a8eb9SGleb Smirnoff scrub_opts.marker |= SOM_MAXMSS; 11633b3a8eb9SGleb Smirnoff scrub_opts.maxmss = $2; 11643b3a8eb9SGleb Smirnoff } 11653b3a8eb9SGleb Smirnoff | SETTOS tos { 11663b3a8eb9SGleb Smirnoff if (scrub_opts.marker & SOM_SETTOS) { 11673b3a8eb9SGleb Smirnoff yyerror("set-tos cannot be respecified"); 11683b3a8eb9SGleb Smirnoff YYERROR; 11693b3a8eb9SGleb Smirnoff } 11703b3a8eb9SGleb Smirnoff scrub_opts.marker |= SOM_SETTOS; 11713b3a8eb9SGleb Smirnoff scrub_opts.settos = $2; 11723b3a8eb9SGleb Smirnoff } 11733b3a8eb9SGleb Smirnoff | fragcache { 11743b3a8eb9SGleb Smirnoff if (scrub_opts.marker & SOM_FRAGCACHE) { 11753b3a8eb9SGleb Smirnoff yyerror("fragcache cannot be respecified"); 11763b3a8eb9SGleb Smirnoff YYERROR; 11773b3a8eb9SGleb Smirnoff } 11783b3a8eb9SGleb Smirnoff scrub_opts.marker |= SOM_FRAGCACHE; 11793b3a8eb9SGleb Smirnoff scrub_opts.fragcache = $1; 11803b3a8eb9SGleb Smirnoff } 11813b3a8eb9SGleb Smirnoff | REASSEMBLE STRING { 11823b3a8eb9SGleb Smirnoff if (strcasecmp($2, "tcp") != 0) { 11833b3a8eb9SGleb Smirnoff yyerror("scrub reassemble supports only tcp, " 11843b3a8eb9SGleb Smirnoff "not '%s'", $2); 11853b3a8eb9SGleb Smirnoff free($2); 11863b3a8eb9SGleb Smirnoff YYERROR; 11873b3a8eb9SGleb Smirnoff } 11883b3a8eb9SGleb Smirnoff free($2); 11893b3a8eb9SGleb Smirnoff if (scrub_opts.reassemble_tcp) { 11903b3a8eb9SGleb Smirnoff yyerror("reassemble tcp cannot be respecified"); 11913b3a8eb9SGleb Smirnoff YYERROR; 11923b3a8eb9SGleb Smirnoff } 11933b3a8eb9SGleb Smirnoff scrub_opts.reassemble_tcp = 1; 11943b3a8eb9SGleb Smirnoff } 11953b3a8eb9SGleb Smirnoff | RANDOMID { 11963b3a8eb9SGleb Smirnoff if (scrub_opts.randomid) { 11973b3a8eb9SGleb Smirnoff yyerror("random-id cannot be respecified"); 11983b3a8eb9SGleb Smirnoff YYERROR; 11993b3a8eb9SGleb Smirnoff } 12003b3a8eb9SGleb Smirnoff scrub_opts.randomid = 1; 12013b3a8eb9SGleb Smirnoff } 12023b3a8eb9SGleb Smirnoff | RTABLE NUMBER { 12033b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > rt_tableid_max()) { 12043b3a8eb9SGleb Smirnoff yyerror("invalid rtable id"); 12053b3a8eb9SGleb Smirnoff YYERROR; 12063b3a8eb9SGleb Smirnoff } 12073b3a8eb9SGleb Smirnoff scrub_opts.rtableid = $2; 12083b3a8eb9SGleb Smirnoff } 12093b3a8eb9SGleb Smirnoff | not TAGGED string { 12103b3a8eb9SGleb Smirnoff scrub_opts.match_tag = $3; 12113b3a8eb9SGleb Smirnoff scrub_opts.match_tag_not = $1; 12123b3a8eb9SGleb Smirnoff } 12133b3a8eb9SGleb Smirnoff ; 12143b3a8eb9SGleb Smirnoff 12153b3a8eb9SGleb Smirnoff fragcache : FRAGMENT REASSEMBLE { $$ = 0; /* default */ } 121664b3b4d6SKristof Provost | FRAGMENT FRAGCROP { $$ = 0; } 121764b3b4d6SKristof Provost | FRAGMENT FRAGDROP { $$ = 0; } 12183b3a8eb9SGleb Smirnoff ; 12193b3a8eb9SGleb Smirnoff 12203b3a8eb9SGleb Smirnoff antispoof : ANTISPOOF logquick antispoof_ifspc af antispoof_opts { 12213b3a8eb9SGleb Smirnoff struct pf_rule r; 12223b3a8eb9SGleb Smirnoff struct node_host *h = NULL, *hh; 12233b3a8eb9SGleb Smirnoff struct node_if *i, *j; 12243b3a8eb9SGleb Smirnoff 12253b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_FILTER)) 12263b3a8eb9SGleb Smirnoff YYERROR; 12273b3a8eb9SGleb Smirnoff 12283b3a8eb9SGleb Smirnoff for (i = $3; i; i = i->next) { 12293b3a8eb9SGleb Smirnoff bzero(&r, sizeof(r)); 12303b3a8eb9SGleb Smirnoff 12313b3a8eb9SGleb Smirnoff r.action = PF_DROP; 12323b3a8eb9SGleb Smirnoff r.direction = PF_IN; 12333b3a8eb9SGleb Smirnoff r.log = $2.log; 12343b3a8eb9SGleb Smirnoff r.logif = $2.logif; 12353b3a8eb9SGleb Smirnoff r.quick = $2.quick; 12363b3a8eb9SGleb Smirnoff r.af = $4; 12373b3a8eb9SGleb Smirnoff if (rule_label(&r, $5.label)) 12383b3a8eb9SGleb Smirnoff YYERROR; 12393b3a8eb9SGleb Smirnoff r.rtableid = $5.rtableid; 12403b3a8eb9SGleb Smirnoff j = calloc(1, sizeof(struct node_if)); 12413b3a8eb9SGleb Smirnoff if (j == NULL) 12423b3a8eb9SGleb Smirnoff err(1, "antispoof: calloc"); 12433b3a8eb9SGleb Smirnoff if (strlcpy(j->ifname, i->ifname, 12443b3a8eb9SGleb Smirnoff sizeof(j->ifname)) >= sizeof(j->ifname)) { 12453b3a8eb9SGleb Smirnoff free(j); 12463b3a8eb9SGleb Smirnoff yyerror("interface name too long"); 12473b3a8eb9SGleb Smirnoff YYERROR; 12483b3a8eb9SGleb Smirnoff } 12493b3a8eb9SGleb Smirnoff j->not = 1; 12503b3a8eb9SGleb Smirnoff if (i->dynamic) { 12513b3a8eb9SGleb Smirnoff h = calloc(1, sizeof(*h)); 12523b3a8eb9SGleb Smirnoff if (h == NULL) 12533b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 12543b3a8eb9SGleb Smirnoff h->addr.type = PF_ADDR_DYNIFTL; 12553b3a8eb9SGleb Smirnoff set_ipmask(h, 128); 12563b3a8eb9SGleb Smirnoff if (strlcpy(h->addr.v.ifname, i->ifname, 12573b3a8eb9SGleb Smirnoff sizeof(h->addr.v.ifname)) >= 12583b3a8eb9SGleb Smirnoff sizeof(h->addr.v.ifname)) { 12593b3a8eb9SGleb Smirnoff free(h); 12603b3a8eb9SGleb Smirnoff yyerror( 12613b3a8eb9SGleb Smirnoff "interface name too long"); 12623b3a8eb9SGleb Smirnoff YYERROR; 12633b3a8eb9SGleb Smirnoff } 12643b3a8eb9SGleb Smirnoff hh = malloc(sizeof(*hh)); 12653b3a8eb9SGleb Smirnoff if (hh == NULL) 12663b3a8eb9SGleb Smirnoff err(1, "address: malloc"); 12673b3a8eb9SGleb Smirnoff bcopy(h, hh, sizeof(*hh)); 12683b3a8eb9SGleb Smirnoff h->addr.iflags = PFI_AFLAG_NETWORK; 12693b3a8eb9SGleb Smirnoff } else { 12703b3a8eb9SGleb Smirnoff h = ifa_lookup(j->ifname, 12713b3a8eb9SGleb Smirnoff PFI_AFLAG_NETWORK); 12723b3a8eb9SGleb Smirnoff hh = NULL; 12733b3a8eb9SGleb Smirnoff } 12743b3a8eb9SGleb Smirnoff 12753b3a8eb9SGleb Smirnoff if (h != NULL) 12763b3a8eb9SGleb Smirnoff expand_rule(&r, j, NULL, NULL, NULL, h, 12773b3a8eb9SGleb Smirnoff NULL, NULL, NULL, NULL, NULL, 12783b3a8eb9SGleb Smirnoff NULL, ""); 12793b3a8eb9SGleb Smirnoff 12803b3a8eb9SGleb Smirnoff if ((i->ifa_flags & IFF_LOOPBACK) == 0) { 12813b3a8eb9SGleb Smirnoff bzero(&r, sizeof(r)); 12823b3a8eb9SGleb Smirnoff 12833b3a8eb9SGleb Smirnoff r.action = PF_DROP; 12843b3a8eb9SGleb Smirnoff r.direction = PF_IN; 12853b3a8eb9SGleb Smirnoff r.log = $2.log; 12863b3a8eb9SGleb Smirnoff r.logif = $2.logif; 12873b3a8eb9SGleb Smirnoff r.quick = $2.quick; 12883b3a8eb9SGleb Smirnoff r.af = $4; 12893b3a8eb9SGleb Smirnoff if (rule_label(&r, $5.label)) 12903b3a8eb9SGleb Smirnoff YYERROR; 12913b3a8eb9SGleb Smirnoff r.rtableid = $5.rtableid; 12923b3a8eb9SGleb Smirnoff if (hh != NULL) 12933b3a8eb9SGleb Smirnoff h = hh; 12943b3a8eb9SGleb Smirnoff else 12953b3a8eb9SGleb Smirnoff h = ifa_lookup(i->ifname, 0); 12963b3a8eb9SGleb Smirnoff if (h != NULL) 12973b3a8eb9SGleb Smirnoff expand_rule(&r, NULL, NULL, 12983b3a8eb9SGleb Smirnoff NULL, NULL, h, NULL, NULL, 12993b3a8eb9SGleb Smirnoff NULL, NULL, NULL, NULL, ""); 13003b3a8eb9SGleb Smirnoff } else 13013b3a8eb9SGleb Smirnoff free(hh); 13023b3a8eb9SGleb Smirnoff } 13033b3a8eb9SGleb Smirnoff free($5.label); 13043b3a8eb9SGleb Smirnoff } 13053b3a8eb9SGleb Smirnoff ; 13063b3a8eb9SGleb Smirnoff 13073b3a8eb9SGleb Smirnoff antispoof_ifspc : FOR antispoof_if { $$ = $2; } 13083b3a8eb9SGleb Smirnoff | FOR '{' optnl antispoof_iflst '}' { $$ = $4; } 13093b3a8eb9SGleb Smirnoff ; 13103b3a8eb9SGleb Smirnoff 13113b3a8eb9SGleb Smirnoff antispoof_iflst : antispoof_if optnl { $$ = $1; } 13123b3a8eb9SGleb Smirnoff | antispoof_iflst comma antispoof_if optnl { 13133b3a8eb9SGleb Smirnoff $1->tail->next = $3; 13143b3a8eb9SGleb Smirnoff $1->tail = $3; 13153b3a8eb9SGleb Smirnoff $$ = $1; 13163b3a8eb9SGleb Smirnoff } 13173b3a8eb9SGleb Smirnoff ; 13183b3a8eb9SGleb Smirnoff 13193b3a8eb9SGleb Smirnoff antispoof_if : if_item { $$ = $1; } 13203b3a8eb9SGleb Smirnoff | '(' if_item ')' { 13213b3a8eb9SGleb Smirnoff $2->dynamic = 1; 13223b3a8eb9SGleb Smirnoff $$ = $2; 13233b3a8eb9SGleb Smirnoff } 13243b3a8eb9SGleb Smirnoff ; 13253b3a8eb9SGleb Smirnoff 13263b3a8eb9SGleb Smirnoff antispoof_opts : { 13273b3a8eb9SGleb Smirnoff bzero(&antispoof_opts, sizeof antispoof_opts); 13283b3a8eb9SGleb Smirnoff antispoof_opts.rtableid = -1; 13293b3a8eb9SGleb Smirnoff } 13303b3a8eb9SGleb Smirnoff antispoof_opts_l 13313b3a8eb9SGleb Smirnoff { $$ = antispoof_opts; } 13323b3a8eb9SGleb Smirnoff | /* empty */ { 13333b3a8eb9SGleb Smirnoff bzero(&antispoof_opts, sizeof antispoof_opts); 13343b3a8eb9SGleb Smirnoff antispoof_opts.rtableid = -1; 13353b3a8eb9SGleb Smirnoff $$ = antispoof_opts; 13363b3a8eb9SGleb Smirnoff } 13373b3a8eb9SGleb Smirnoff ; 13383b3a8eb9SGleb Smirnoff 13393b3a8eb9SGleb Smirnoff antispoof_opts_l : antispoof_opts_l antispoof_opt 13403b3a8eb9SGleb Smirnoff | antispoof_opt 13413b3a8eb9SGleb Smirnoff ; 13423b3a8eb9SGleb Smirnoff 13433b3a8eb9SGleb Smirnoff antispoof_opt : label { 13443b3a8eb9SGleb Smirnoff if (antispoof_opts.label) { 13453b3a8eb9SGleb Smirnoff yyerror("label cannot be redefined"); 13463b3a8eb9SGleb Smirnoff YYERROR; 13473b3a8eb9SGleb Smirnoff } 13483b3a8eb9SGleb Smirnoff antispoof_opts.label = $1; 13493b3a8eb9SGleb Smirnoff } 13503b3a8eb9SGleb Smirnoff | RTABLE NUMBER { 13513b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > rt_tableid_max()) { 13523b3a8eb9SGleb Smirnoff yyerror("invalid rtable id"); 13533b3a8eb9SGleb Smirnoff YYERROR; 13543b3a8eb9SGleb Smirnoff } 13553b3a8eb9SGleb Smirnoff antispoof_opts.rtableid = $2; 13563b3a8eb9SGleb Smirnoff } 13573b3a8eb9SGleb Smirnoff ; 13583b3a8eb9SGleb Smirnoff 13593b3a8eb9SGleb Smirnoff not : '!' { $$ = 1; } 13603b3a8eb9SGleb Smirnoff | /* empty */ { $$ = 0; } 13613b3a8eb9SGleb Smirnoff ; 13623b3a8eb9SGleb Smirnoff 13633b3a8eb9SGleb Smirnoff tabledef : TABLE '<' STRING '>' table_opts { 13643b3a8eb9SGleb Smirnoff struct node_host *h, *nh; 13653b3a8eb9SGleb Smirnoff struct node_tinit *ti, *nti; 13663b3a8eb9SGleb Smirnoff 13673b3a8eb9SGleb Smirnoff if (strlen($3) >= PF_TABLE_NAME_SIZE) { 13683b3a8eb9SGleb Smirnoff yyerror("table name too long, max %d chars", 13693b3a8eb9SGleb Smirnoff PF_TABLE_NAME_SIZE - 1); 13703b3a8eb9SGleb Smirnoff free($3); 13713b3a8eb9SGleb Smirnoff YYERROR; 13723b3a8eb9SGleb Smirnoff } 13733b3a8eb9SGleb Smirnoff if (pf->loadopt & PFCTL_FLAG_TABLE) 13743b3a8eb9SGleb Smirnoff if (process_tabledef($3, &$5)) { 13753b3a8eb9SGleb Smirnoff free($3); 13763b3a8eb9SGleb Smirnoff YYERROR; 13773b3a8eb9SGleb Smirnoff } 13783b3a8eb9SGleb Smirnoff free($3); 13793b3a8eb9SGleb Smirnoff for (ti = SIMPLEQ_FIRST(&$5.init_nodes); 13803b3a8eb9SGleb Smirnoff ti != SIMPLEQ_END(&$5.init_nodes); ti = nti) { 13813b3a8eb9SGleb Smirnoff if (ti->file) 13823b3a8eb9SGleb Smirnoff free(ti->file); 13833b3a8eb9SGleb Smirnoff for (h = ti->host; h != NULL; h = nh) { 13843b3a8eb9SGleb Smirnoff nh = h->next; 13853b3a8eb9SGleb Smirnoff free(h); 13863b3a8eb9SGleb Smirnoff } 13873b3a8eb9SGleb Smirnoff nti = SIMPLEQ_NEXT(ti, entries); 13883b3a8eb9SGleb Smirnoff free(ti); 13893b3a8eb9SGleb Smirnoff } 13903b3a8eb9SGleb Smirnoff } 13913b3a8eb9SGleb Smirnoff ; 13923b3a8eb9SGleb Smirnoff 13933b3a8eb9SGleb Smirnoff table_opts : { 13943b3a8eb9SGleb Smirnoff bzero(&table_opts, sizeof table_opts); 13953b3a8eb9SGleb Smirnoff SIMPLEQ_INIT(&table_opts.init_nodes); 13963b3a8eb9SGleb Smirnoff } 13973b3a8eb9SGleb Smirnoff table_opts_l 13983b3a8eb9SGleb Smirnoff { $$ = table_opts; } 13993b3a8eb9SGleb Smirnoff | /* empty */ 14003b3a8eb9SGleb Smirnoff { 14013b3a8eb9SGleb Smirnoff bzero(&table_opts, sizeof table_opts); 14023b3a8eb9SGleb Smirnoff SIMPLEQ_INIT(&table_opts.init_nodes); 14033b3a8eb9SGleb Smirnoff $$ = table_opts; 14043b3a8eb9SGleb Smirnoff } 14053b3a8eb9SGleb Smirnoff ; 14063b3a8eb9SGleb Smirnoff 14073b3a8eb9SGleb Smirnoff table_opts_l : table_opts_l table_opt 14083b3a8eb9SGleb Smirnoff | table_opt 14093b3a8eb9SGleb Smirnoff ; 14103b3a8eb9SGleb Smirnoff 14113b3a8eb9SGleb Smirnoff table_opt : STRING { 14123b3a8eb9SGleb Smirnoff if (!strcmp($1, "const")) 14133b3a8eb9SGleb Smirnoff table_opts.flags |= PFR_TFLAG_CONST; 14143b3a8eb9SGleb Smirnoff else if (!strcmp($1, "persist")) 14153b3a8eb9SGleb Smirnoff table_opts.flags |= PFR_TFLAG_PERSIST; 14163b3a8eb9SGleb Smirnoff else if (!strcmp($1, "counters")) 14173b3a8eb9SGleb Smirnoff table_opts.flags |= PFR_TFLAG_COUNTERS; 14183b3a8eb9SGleb Smirnoff else { 14193b3a8eb9SGleb Smirnoff yyerror("invalid table option '%s'", $1); 14203b3a8eb9SGleb Smirnoff free($1); 14213b3a8eb9SGleb Smirnoff YYERROR; 14223b3a8eb9SGleb Smirnoff } 14233b3a8eb9SGleb Smirnoff free($1); 14243b3a8eb9SGleb Smirnoff } 14253b3a8eb9SGleb Smirnoff | '{' optnl '}' { table_opts.init_addr = 1; } 14263b3a8eb9SGleb Smirnoff | '{' optnl host_list '}' { 14273b3a8eb9SGleb Smirnoff struct node_host *n; 14283b3a8eb9SGleb Smirnoff struct node_tinit *ti; 14293b3a8eb9SGleb Smirnoff 14303b3a8eb9SGleb Smirnoff for (n = $3; n != NULL; n = n->next) { 14313b3a8eb9SGleb Smirnoff switch (n->addr.type) { 14323b3a8eb9SGleb Smirnoff case PF_ADDR_ADDRMASK: 14333b3a8eb9SGleb Smirnoff continue; /* ok */ 14343b3a8eb9SGleb Smirnoff case PF_ADDR_RANGE: 14353b3a8eb9SGleb Smirnoff yyerror("address ranges are not " 14363b3a8eb9SGleb Smirnoff "permitted inside tables"); 14373b3a8eb9SGleb Smirnoff break; 14383b3a8eb9SGleb Smirnoff case PF_ADDR_DYNIFTL: 14393b3a8eb9SGleb Smirnoff yyerror("dynamic addresses are not " 14403b3a8eb9SGleb Smirnoff "permitted inside tables"); 14413b3a8eb9SGleb Smirnoff break; 14423b3a8eb9SGleb Smirnoff case PF_ADDR_TABLE: 14433b3a8eb9SGleb Smirnoff yyerror("tables cannot contain tables"); 14443b3a8eb9SGleb Smirnoff break; 14453b3a8eb9SGleb Smirnoff case PF_ADDR_NOROUTE: 14463b3a8eb9SGleb Smirnoff yyerror("\"no-route\" is not permitted " 14473b3a8eb9SGleb Smirnoff "inside tables"); 14483b3a8eb9SGleb Smirnoff break; 14493b3a8eb9SGleb Smirnoff case PF_ADDR_URPFFAILED: 14503b3a8eb9SGleb Smirnoff yyerror("\"urpf-failed\" is not " 14513b3a8eb9SGleb Smirnoff "permitted inside tables"); 14523b3a8eb9SGleb Smirnoff break; 14533b3a8eb9SGleb Smirnoff default: 14543b3a8eb9SGleb Smirnoff yyerror("unknown address type %d", 14553b3a8eb9SGleb Smirnoff n->addr.type); 14563b3a8eb9SGleb Smirnoff } 14573b3a8eb9SGleb Smirnoff YYERROR; 14583b3a8eb9SGleb Smirnoff } 14593b3a8eb9SGleb Smirnoff if (!(ti = calloc(1, sizeof(*ti)))) 14603b3a8eb9SGleb Smirnoff err(1, "table_opt: calloc"); 14613b3a8eb9SGleb Smirnoff ti->host = $3; 14623b3a8eb9SGleb Smirnoff SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti, 14633b3a8eb9SGleb Smirnoff entries); 14643b3a8eb9SGleb Smirnoff table_opts.init_addr = 1; 14653b3a8eb9SGleb Smirnoff } 14663b3a8eb9SGleb Smirnoff | FILENAME STRING { 14673b3a8eb9SGleb Smirnoff struct node_tinit *ti; 14683b3a8eb9SGleb Smirnoff 14693b3a8eb9SGleb Smirnoff if (!(ti = calloc(1, sizeof(*ti)))) 14703b3a8eb9SGleb Smirnoff err(1, "table_opt: calloc"); 14713b3a8eb9SGleb Smirnoff ti->file = $2; 14723b3a8eb9SGleb Smirnoff SIMPLEQ_INSERT_TAIL(&table_opts.init_nodes, ti, 14733b3a8eb9SGleb Smirnoff entries); 14743b3a8eb9SGleb Smirnoff table_opts.init_addr = 1; 14753b3a8eb9SGleb Smirnoff } 14763b3a8eb9SGleb Smirnoff ; 14773b3a8eb9SGleb Smirnoff 14783b3a8eb9SGleb Smirnoff altqif : ALTQ interface queue_opts QUEUE qassign { 14793b3a8eb9SGleb Smirnoff struct pf_altq a; 14803b3a8eb9SGleb Smirnoff 14813b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_QUEUE)) 14823b3a8eb9SGleb Smirnoff YYERROR; 14833b3a8eb9SGleb Smirnoff 14843b3a8eb9SGleb Smirnoff memset(&a, 0, sizeof(a)); 14853b3a8eb9SGleb Smirnoff if ($3.scheduler.qtype == ALTQT_NONE) { 14863b3a8eb9SGleb Smirnoff yyerror("no scheduler specified!"); 14873b3a8eb9SGleb Smirnoff YYERROR; 14883b3a8eb9SGleb Smirnoff } 14893b3a8eb9SGleb Smirnoff a.scheduler = $3.scheduler.qtype; 14903b3a8eb9SGleb Smirnoff a.qlimit = $3.qlimit; 14913b3a8eb9SGleb Smirnoff a.tbrsize = $3.tbrsize; 14920a70aaf8SLuiz Otavio O Souza if ($5 == NULL && $3.scheduler.qtype != ALTQT_CODEL) { 14933b3a8eb9SGleb Smirnoff yyerror("no child queues specified"); 14943b3a8eb9SGleb Smirnoff YYERROR; 14953b3a8eb9SGleb Smirnoff } 14963b3a8eb9SGleb Smirnoff if (expand_altq(&a, $2, $5, $3.queue_bwspec, 14973b3a8eb9SGleb Smirnoff &$3.scheduler)) 14983b3a8eb9SGleb Smirnoff YYERROR; 14993b3a8eb9SGleb Smirnoff } 15003b3a8eb9SGleb Smirnoff ; 15013b3a8eb9SGleb Smirnoff 15023b3a8eb9SGleb Smirnoff queuespec : QUEUE STRING interface queue_opts qassign { 15033b3a8eb9SGleb Smirnoff struct pf_altq a; 15043b3a8eb9SGleb Smirnoff 15053b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_QUEUE)) { 15063b3a8eb9SGleb Smirnoff free($2); 15073b3a8eb9SGleb Smirnoff YYERROR; 15083b3a8eb9SGleb Smirnoff } 15093b3a8eb9SGleb Smirnoff 15103b3a8eb9SGleb Smirnoff memset(&a, 0, sizeof(a)); 15113b3a8eb9SGleb Smirnoff 15123b3a8eb9SGleb Smirnoff if (strlcpy(a.qname, $2, sizeof(a.qname)) >= 15133b3a8eb9SGleb Smirnoff sizeof(a.qname)) { 15143b3a8eb9SGleb Smirnoff yyerror("queue name too long (max " 15153b3a8eb9SGleb Smirnoff "%d chars)", PF_QNAME_SIZE-1); 15163b3a8eb9SGleb Smirnoff free($2); 15173b3a8eb9SGleb Smirnoff YYERROR; 15183b3a8eb9SGleb Smirnoff } 15193b3a8eb9SGleb Smirnoff free($2); 15203b3a8eb9SGleb Smirnoff if ($4.tbrsize) { 15213b3a8eb9SGleb Smirnoff yyerror("cannot specify tbrsize for queue"); 15223b3a8eb9SGleb Smirnoff YYERROR; 15233b3a8eb9SGleb Smirnoff } 15243b3a8eb9SGleb Smirnoff if ($4.priority > 255) { 15253b3a8eb9SGleb Smirnoff yyerror("priority out of range: max 255"); 15263b3a8eb9SGleb Smirnoff YYERROR; 15273b3a8eb9SGleb Smirnoff } 15283b3a8eb9SGleb Smirnoff a.priority = $4.priority; 15293b3a8eb9SGleb Smirnoff a.qlimit = $4.qlimit; 15303b3a8eb9SGleb Smirnoff a.scheduler = $4.scheduler.qtype; 15313b3a8eb9SGleb Smirnoff if (expand_queue(&a, $3, $5, $4.queue_bwspec, 15323b3a8eb9SGleb Smirnoff &$4.scheduler)) { 15333b3a8eb9SGleb Smirnoff yyerror("errors in queue definition"); 15343b3a8eb9SGleb Smirnoff YYERROR; 15353b3a8eb9SGleb Smirnoff } 15363b3a8eb9SGleb Smirnoff } 15373b3a8eb9SGleb Smirnoff ; 15383b3a8eb9SGleb Smirnoff 15393b3a8eb9SGleb Smirnoff queue_opts : { 15403b3a8eb9SGleb Smirnoff bzero(&queue_opts, sizeof queue_opts); 15413b3a8eb9SGleb Smirnoff queue_opts.priority = DEFAULT_PRIORITY; 15423b3a8eb9SGleb Smirnoff queue_opts.qlimit = DEFAULT_QLIMIT; 15433b3a8eb9SGleb Smirnoff queue_opts.scheduler.qtype = ALTQT_NONE; 15443b3a8eb9SGleb Smirnoff queue_opts.queue_bwspec.bw_percent = 100; 15453b3a8eb9SGleb Smirnoff } 15463b3a8eb9SGleb Smirnoff queue_opts_l 15473b3a8eb9SGleb Smirnoff { $$ = queue_opts; } 15483b3a8eb9SGleb Smirnoff | /* empty */ { 15493b3a8eb9SGleb Smirnoff bzero(&queue_opts, sizeof queue_opts); 15503b3a8eb9SGleb Smirnoff queue_opts.priority = DEFAULT_PRIORITY; 15513b3a8eb9SGleb Smirnoff queue_opts.qlimit = DEFAULT_QLIMIT; 15523b3a8eb9SGleb Smirnoff queue_opts.scheduler.qtype = ALTQT_NONE; 15533b3a8eb9SGleb Smirnoff queue_opts.queue_bwspec.bw_percent = 100; 15543b3a8eb9SGleb Smirnoff $$ = queue_opts; 15553b3a8eb9SGleb Smirnoff } 15563b3a8eb9SGleb Smirnoff ; 15573b3a8eb9SGleb Smirnoff 15583b3a8eb9SGleb Smirnoff queue_opts_l : queue_opts_l queue_opt 15593b3a8eb9SGleb Smirnoff | queue_opt 15603b3a8eb9SGleb Smirnoff ; 15613b3a8eb9SGleb Smirnoff 15623b3a8eb9SGleb Smirnoff queue_opt : BANDWIDTH bandwidth { 15633b3a8eb9SGleb Smirnoff if (queue_opts.marker & QOM_BWSPEC) { 15643b3a8eb9SGleb Smirnoff yyerror("bandwidth cannot be respecified"); 15653b3a8eb9SGleb Smirnoff YYERROR; 15663b3a8eb9SGleb Smirnoff } 15673b3a8eb9SGleb Smirnoff queue_opts.marker |= QOM_BWSPEC; 15683b3a8eb9SGleb Smirnoff queue_opts.queue_bwspec = $2; 15693b3a8eb9SGleb Smirnoff } 15703b3a8eb9SGleb Smirnoff | PRIORITY NUMBER { 15713b3a8eb9SGleb Smirnoff if (queue_opts.marker & QOM_PRIORITY) { 15723b3a8eb9SGleb Smirnoff yyerror("priority cannot be respecified"); 15733b3a8eb9SGleb Smirnoff YYERROR; 15743b3a8eb9SGleb Smirnoff } 15753b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > 255) { 15763b3a8eb9SGleb Smirnoff yyerror("priority out of range: max 255"); 15773b3a8eb9SGleb Smirnoff YYERROR; 15783b3a8eb9SGleb Smirnoff } 15793b3a8eb9SGleb Smirnoff queue_opts.marker |= QOM_PRIORITY; 15803b3a8eb9SGleb Smirnoff queue_opts.priority = $2; 15813b3a8eb9SGleb Smirnoff } 15823b3a8eb9SGleb Smirnoff | QLIMIT NUMBER { 15833b3a8eb9SGleb Smirnoff if (queue_opts.marker & QOM_QLIMIT) { 15843b3a8eb9SGleb Smirnoff yyerror("qlimit cannot be respecified"); 15853b3a8eb9SGleb Smirnoff YYERROR; 15863b3a8eb9SGleb Smirnoff } 15873b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > 65535) { 15883b3a8eb9SGleb Smirnoff yyerror("qlimit out of range: max 65535"); 15893b3a8eb9SGleb Smirnoff YYERROR; 15903b3a8eb9SGleb Smirnoff } 15913b3a8eb9SGleb Smirnoff queue_opts.marker |= QOM_QLIMIT; 15923b3a8eb9SGleb Smirnoff queue_opts.qlimit = $2; 15933b3a8eb9SGleb Smirnoff } 15943b3a8eb9SGleb Smirnoff | scheduler { 15953b3a8eb9SGleb Smirnoff if (queue_opts.marker & QOM_SCHEDULER) { 15963b3a8eb9SGleb Smirnoff yyerror("scheduler cannot be respecified"); 15973b3a8eb9SGleb Smirnoff YYERROR; 15983b3a8eb9SGleb Smirnoff } 15993b3a8eb9SGleb Smirnoff queue_opts.marker |= QOM_SCHEDULER; 16003b3a8eb9SGleb Smirnoff queue_opts.scheduler = $1; 16013b3a8eb9SGleb Smirnoff } 16023b3a8eb9SGleb Smirnoff | TBRSIZE NUMBER { 16033b3a8eb9SGleb Smirnoff if (queue_opts.marker & QOM_TBRSIZE) { 16043b3a8eb9SGleb Smirnoff yyerror("tbrsize cannot be respecified"); 16053b3a8eb9SGleb Smirnoff YYERROR; 16063b3a8eb9SGleb Smirnoff } 16073b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > 65535) { 16083b3a8eb9SGleb Smirnoff yyerror("tbrsize too big: max 65535"); 16093b3a8eb9SGleb Smirnoff YYERROR; 16103b3a8eb9SGleb Smirnoff } 16113b3a8eb9SGleb Smirnoff queue_opts.marker |= QOM_TBRSIZE; 16123b3a8eb9SGleb Smirnoff queue_opts.tbrsize = $2; 16133b3a8eb9SGleb Smirnoff } 16143b3a8eb9SGleb Smirnoff ; 16153b3a8eb9SGleb Smirnoff 16163b3a8eb9SGleb Smirnoff bandwidth : STRING { 16173b3a8eb9SGleb Smirnoff double bps; 16183b3a8eb9SGleb Smirnoff char *cp; 16193b3a8eb9SGleb Smirnoff 16203b3a8eb9SGleb Smirnoff $$.bw_percent = 0; 16213b3a8eb9SGleb Smirnoff 16223b3a8eb9SGleb Smirnoff bps = strtod($1, &cp); 16233b3a8eb9SGleb Smirnoff if (cp != NULL) { 1624db1bbde6SLuiz Otavio O Souza if (strlen(cp) > 1) { 1625db1bbde6SLuiz Otavio O Souza char *cu = cp + 1; 1626db1bbde6SLuiz Otavio O Souza if (!strcmp(cu, "Bit") || 1627db1bbde6SLuiz Otavio O Souza !strcmp(cu, "B") || 1628db1bbde6SLuiz Otavio O Souza !strcmp(cu, "bit") || 1629db1bbde6SLuiz Otavio O Souza !strcmp(cu, "b")) { 1630db1bbde6SLuiz Otavio O Souza *cu = 0; 1631db1bbde6SLuiz Otavio O Souza } 1632db1bbde6SLuiz Otavio O Souza } 16333b3a8eb9SGleb Smirnoff if (!strcmp(cp, "b")) 16343b3a8eb9SGleb Smirnoff ; /* nothing */ 1635db1bbde6SLuiz Otavio O Souza else if (!strcmp(cp, "K")) 16363b3a8eb9SGleb Smirnoff bps *= 1000; 1637db1bbde6SLuiz Otavio O Souza else if (!strcmp(cp, "M")) 16383b3a8eb9SGleb Smirnoff bps *= 1000 * 1000; 1639db1bbde6SLuiz Otavio O Souza else if (!strcmp(cp, "G")) 16403b3a8eb9SGleb Smirnoff bps *= 1000 * 1000 * 1000; 16413b3a8eb9SGleb Smirnoff else if (!strcmp(cp, "%")) { 16423b3a8eb9SGleb Smirnoff if (bps < 0 || bps > 100) { 16433b3a8eb9SGleb Smirnoff yyerror("bandwidth spec " 16443b3a8eb9SGleb Smirnoff "out of range"); 16453b3a8eb9SGleb Smirnoff free($1); 16463b3a8eb9SGleb Smirnoff YYERROR; 16473b3a8eb9SGleb Smirnoff } 16483b3a8eb9SGleb Smirnoff $$.bw_percent = bps; 16493b3a8eb9SGleb Smirnoff bps = 0; 16503b3a8eb9SGleb Smirnoff } else { 16513b3a8eb9SGleb Smirnoff yyerror("unknown unit %s", cp); 16523b3a8eb9SGleb Smirnoff free($1); 16533b3a8eb9SGleb Smirnoff YYERROR; 16543b3a8eb9SGleb Smirnoff } 16553b3a8eb9SGleb Smirnoff } 16563b3a8eb9SGleb Smirnoff free($1); 16573b3a8eb9SGleb Smirnoff $$.bw_absolute = (u_int32_t)bps; 16583b3a8eb9SGleb Smirnoff } 16593b3a8eb9SGleb Smirnoff | NUMBER { 16603b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 > UINT_MAX) { 16613b3a8eb9SGleb Smirnoff yyerror("bandwidth number too big"); 16623b3a8eb9SGleb Smirnoff YYERROR; 16633b3a8eb9SGleb Smirnoff } 16643b3a8eb9SGleb Smirnoff $$.bw_percent = 0; 16653b3a8eb9SGleb Smirnoff $$.bw_absolute = $1; 16663b3a8eb9SGleb Smirnoff } 16673b3a8eb9SGleb Smirnoff ; 16683b3a8eb9SGleb Smirnoff 16693b3a8eb9SGleb Smirnoff scheduler : CBQ { 16703b3a8eb9SGleb Smirnoff $$.qtype = ALTQT_CBQ; 16713b3a8eb9SGleb Smirnoff $$.data.cbq_opts.flags = 0; 16723b3a8eb9SGleb Smirnoff } 16733b3a8eb9SGleb Smirnoff | CBQ '(' cbqflags_list ')' { 16743b3a8eb9SGleb Smirnoff $$.qtype = ALTQT_CBQ; 16753b3a8eb9SGleb Smirnoff $$.data.cbq_opts.flags = $3; 16763b3a8eb9SGleb Smirnoff } 16773b3a8eb9SGleb Smirnoff | PRIQ { 16783b3a8eb9SGleb Smirnoff $$.qtype = ALTQT_PRIQ; 16793b3a8eb9SGleb Smirnoff $$.data.priq_opts.flags = 0; 16803b3a8eb9SGleb Smirnoff } 16813b3a8eb9SGleb Smirnoff | PRIQ '(' priqflags_list ')' { 16823b3a8eb9SGleb Smirnoff $$.qtype = ALTQT_PRIQ; 16833b3a8eb9SGleb Smirnoff $$.data.priq_opts.flags = $3; 16843b3a8eb9SGleb Smirnoff } 16853b3a8eb9SGleb Smirnoff | HFSC { 16863b3a8eb9SGleb Smirnoff $$.qtype = ALTQT_HFSC; 16873b3a8eb9SGleb Smirnoff bzero(&$$.data.hfsc_opts, 16883b3a8eb9SGleb Smirnoff sizeof(struct node_hfsc_opts)); 16893b3a8eb9SGleb Smirnoff } 16903b3a8eb9SGleb Smirnoff | HFSC '(' hfsc_opts ')' { 16913b3a8eb9SGleb Smirnoff $$.qtype = ALTQT_HFSC; 16923b3a8eb9SGleb Smirnoff $$.data.hfsc_opts = $3; 16933b3a8eb9SGleb Smirnoff } 1694a5b789f6SErmal Luçi | FAIRQ { 1695a5b789f6SErmal Luçi $$.qtype = ALTQT_FAIRQ; 1696a5b789f6SErmal Luçi bzero(&$$.data.fairq_opts, 1697a5b789f6SErmal Luçi sizeof(struct node_fairq_opts)); 1698a5b789f6SErmal Luçi } 1699a5b789f6SErmal Luçi | FAIRQ '(' fairq_opts ')' { 1700a5b789f6SErmal Luçi $$.qtype = ALTQT_FAIRQ; 1701a5b789f6SErmal Luçi $$.data.fairq_opts = $3; 1702a5b789f6SErmal Luçi } 17030a70aaf8SLuiz Otavio O Souza | CODEL { 17040a70aaf8SLuiz Otavio O Souza $$.qtype = ALTQT_CODEL; 17050a70aaf8SLuiz Otavio O Souza bzero(&$$.data.codel_opts, 17060a70aaf8SLuiz Otavio O Souza sizeof(struct codel_opts)); 17070a70aaf8SLuiz Otavio O Souza } 17080a70aaf8SLuiz Otavio O Souza | CODEL '(' codel_opts ')' { 17090a70aaf8SLuiz Otavio O Souza $$.qtype = ALTQT_CODEL; 17100a70aaf8SLuiz Otavio O Souza $$.data.codel_opts = $3; 17110a70aaf8SLuiz Otavio O Souza } 17123b3a8eb9SGleb Smirnoff ; 17133b3a8eb9SGleb Smirnoff 17143b3a8eb9SGleb Smirnoff cbqflags_list : cbqflags_item { $$ |= $1; } 17153b3a8eb9SGleb Smirnoff | cbqflags_list comma cbqflags_item { $$ |= $3; } 17163b3a8eb9SGleb Smirnoff ; 17173b3a8eb9SGleb Smirnoff 17183b3a8eb9SGleb Smirnoff cbqflags_item : STRING { 17193b3a8eb9SGleb Smirnoff if (!strcmp($1, "default")) 17203b3a8eb9SGleb Smirnoff $$ = CBQCLF_DEFCLASS; 17213b3a8eb9SGleb Smirnoff else if (!strcmp($1, "borrow")) 17223b3a8eb9SGleb Smirnoff $$ = CBQCLF_BORROW; 17233b3a8eb9SGleb Smirnoff else if (!strcmp($1, "red")) 17243b3a8eb9SGleb Smirnoff $$ = CBQCLF_RED; 17253b3a8eb9SGleb Smirnoff else if (!strcmp($1, "ecn")) 17263b3a8eb9SGleb Smirnoff $$ = CBQCLF_RED|CBQCLF_ECN; 17273b3a8eb9SGleb Smirnoff else if (!strcmp($1, "rio")) 17283b3a8eb9SGleb Smirnoff $$ = CBQCLF_RIO; 17290a70aaf8SLuiz Otavio O Souza else if (!strcmp($1, "codel")) 17300a70aaf8SLuiz Otavio O Souza $$ = CBQCLF_CODEL; 17313b3a8eb9SGleb Smirnoff else { 17323b3a8eb9SGleb Smirnoff yyerror("unknown cbq flag \"%s\"", $1); 17333b3a8eb9SGleb Smirnoff free($1); 17343b3a8eb9SGleb Smirnoff YYERROR; 17353b3a8eb9SGleb Smirnoff } 17363b3a8eb9SGleb Smirnoff free($1); 17373b3a8eb9SGleb Smirnoff } 17383b3a8eb9SGleb Smirnoff ; 17393b3a8eb9SGleb Smirnoff 17403b3a8eb9SGleb Smirnoff priqflags_list : priqflags_item { $$ |= $1; } 17413b3a8eb9SGleb Smirnoff | priqflags_list comma priqflags_item { $$ |= $3; } 17423b3a8eb9SGleb Smirnoff ; 17433b3a8eb9SGleb Smirnoff 17443b3a8eb9SGleb Smirnoff priqflags_item : STRING { 17453b3a8eb9SGleb Smirnoff if (!strcmp($1, "default")) 17463b3a8eb9SGleb Smirnoff $$ = PRCF_DEFAULTCLASS; 17473b3a8eb9SGleb Smirnoff else if (!strcmp($1, "red")) 17483b3a8eb9SGleb Smirnoff $$ = PRCF_RED; 17493b3a8eb9SGleb Smirnoff else if (!strcmp($1, "ecn")) 17503b3a8eb9SGleb Smirnoff $$ = PRCF_RED|PRCF_ECN; 17513b3a8eb9SGleb Smirnoff else if (!strcmp($1, "rio")) 17523b3a8eb9SGleb Smirnoff $$ = PRCF_RIO; 17530a70aaf8SLuiz Otavio O Souza else if (!strcmp($1, "codel")) 17540a70aaf8SLuiz Otavio O Souza $$ = PRCF_CODEL; 17553b3a8eb9SGleb Smirnoff else { 17563b3a8eb9SGleb Smirnoff yyerror("unknown priq flag \"%s\"", $1); 17573b3a8eb9SGleb Smirnoff free($1); 17583b3a8eb9SGleb Smirnoff YYERROR; 17593b3a8eb9SGleb Smirnoff } 17603b3a8eb9SGleb Smirnoff free($1); 17613b3a8eb9SGleb Smirnoff } 17623b3a8eb9SGleb Smirnoff ; 17633b3a8eb9SGleb Smirnoff 17643b3a8eb9SGleb Smirnoff hfsc_opts : { 17653b3a8eb9SGleb Smirnoff bzero(&hfsc_opts, 17663b3a8eb9SGleb Smirnoff sizeof(struct node_hfsc_opts)); 17673b3a8eb9SGleb Smirnoff } 17683b3a8eb9SGleb Smirnoff hfscopts_list { 17693b3a8eb9SGleb Smirnoff $$ = hfsc_opts; 17703b3a8eb9SGleb Smirnoff } 17713b3a8eb9SGleb Smirnoff ; 17723b3a8eb9SGleb Smirnoff 17733b3a8eb9SGleb Smirnoff hfscopts_list : hfscopts_item 17743b3a8eb9SGleb Smirnoff | hfscopts_list comma hfscopts_item 17753b3a8eb9SGleb Smirnoff ; 17763b3a8eb9SGleb Smirnoff 17773b3a8eb9SGleb Smirnoff hfscopts_item : LINKSHARE bandwidth { 17783b3a8eb9SGleb Smirnoff if (hfsc_opts.linkshare.used) { 17793b3a8eb9SGleb Smirnoff yyerror("linkshare already specified"); 17803b3a8eb9SGleb Smirnoff YYERROR; 17813b3a8eb9SGleb Smirnoff } 17823b3a8eb9SGleb Smirnoff hfsc_opts.linkshare.m2 = $2; 17833b3a8eb9SGleb Smirnoff hfsc_opts.linkshare.used = 1; 17843b3a8eb9SGleb Smirnoff } 17853b3a8eb9SGleb Smirnoff | LINKSHARE '(' bandwidth comma NUMBER comma bandwidth ')' 17863b3a8eb9SGleb Smirnoff { 17873b3a8eb9SGleb Smirnoff if ($5 < 0 || $5 > INT_MAX) { 17883b3a8eb9SGleb Smirnoff yyerror("timing in curve out of range"); 17893b3a8eb9SGleb Smirnoff YYERROR; 17903b3a8eb9SGleb Smirnoff } 17913b3a8eb9SGleb Smirnoff if (hfsc_opts.linkshare.used) { 17923b3a8eb9SGleb Smirnoff yyerror("linkshare already specified"); 17933b3a8eb9SGleb Smirnoff YYERROR; 17943b3a8eb9SGleb Smirnoff } 17953b3a8eb9SGleb Smirnoff hfsc_opts.linkshare.m1 = $3; 17963b3a8eb9SGleb Smirnoff hfsc_opts.linkshare.d = $5; 17973b3a8eb9SGleb Smirnoff hfsc_opts.linkshare.m2 = $7; 17983b3a8eb9SGleb Smirnoff hfsc_opts.linkshare.used = 1; 17993b3a8eb9SGleb Smirnoff } 18003b3a8eb9SGleb Smirnoff | REALTIME bandwidth { 18013b3a8eb9SGleb Smirnoff if (hfsc_opts.realtime.used) { 18023b3a8eb9SGleb Smirnoff yyerror("realtime already specified"); 18033b3a8eb9SGleb Smirnoff YYERROR; 18043b3a8eb9SGleb Smirnoff } 18053b3a8eb9SGleb Smirnoff hfsc_opts.realtime.m2 = $2; 18063b3a8eb9SGleb Smirnoff hfsc_opts.realtime.used = 1; 18073b3a8eb9SGleb Smirnoff } 18083b3a8eb9SGleb Smirnoff | REALTIME '(' bandwidth comma NUMBER comma bandwidth ')' 18093b3a8eb9SGleb Smirnoff { 18103b3a8eb9SGleb Smirnoff if ($5 < 0 || $5 > INT_MAX) { 18113b3a8eb9SGleb Smirnoff yyerror("timing in curve out of range"); 18123b3a8eb9SGleb Smirnoff YYERROR; 18133b3a8eb9SGleb Smirnoff } 18143b3a8eb9SGleb Smirnoff if (hfsc_opts.realtime.used) { 18153b3a8eb9SGleb Smirnoff yyerror("realtime already specified"); 18163b3a8eb9SGleb Smirnoff YYERROR; 18173b3a8eb9SGleb Smirnoff } 18183b3a8eb9SGleb Smirnoff hfsc_opts.realtime.m1 = $3; 18193b3a8eb9SGleb Smirnoff hfsc_opts.realtime.d = $5; 18203b3a8eb9SGleb Smirnoff hfsc_opts.realtime.m2 = $7; 18213b3a8eb9SGleb Smirnoff hfsc_opts.realtime.used = 1; 18223b3a8eb9SGleb Smirnoff } 18233b3a8eb9SGleb Smirnoff | UPPERLIMIT bandwidth { 18243b3a8eb9SGleb Smirnoff if (hfsc_opts.upperlimit.used) { 18253b3a8eb9SGleb Smirnoff yyerror("upperlimit already specified"); 18263b3a8eb9SGleb Smirnoff YYERROR; 18273b3a8eb9SGleb Smirnoff } 18283b3a8eb9SGleb Smirnoff hfsc_opts.upperlimit.m2 = $2; 18293b3a8eb9SGleb Smirnoff hfsc_opts.upperlimit.used = 1; 18303b3a8eb9SGleb Smirnoff } 18313b3a8eb9SGleb Smirnoff | UPPERLIMIT '(' bandwidth comma NUMBER comma bandwidth ')' 18323b3a8eb9SGleb Smirnoff { 18333b3a8eb9SGleb Smirnoff if ($5 < 0 || $5 > INT_MAX) { 18343b3a8eb9SGleb Smirnoff yyerror("timing in curve out of range"); 18353b3a8eb9SGleb Smirnoff YYERROR; 18363b3a8eb9SGleb Smirnoff } 18373b3a8eb9SGleb Smirnoff if (hfsc_opts.upperlimit.used) { 18383b3a8eb9SGleb Smirnoff yyerror("upperlimit already specified"); 18393b3a8eb9SGleb Smirnoff YYERROR; 18403b3a8eb9SGleb Smirnoff } 18413b3a8eb9SGleb Smirnoff hfsc_opts.upperlimit.m1 = $3; 18423b3a8eb9SGleb Smirnoff hfsc_opts.upperlimit.d = $5; 18433b3a8eb9SGleb Smirnoff hfsc_opts.upperlimit.m2 = $7; 18443b3a8eb9SGleb Smirnoff hfsc_opts.upperlimit.used = 1; 18453b3a8eb9SGleb Smirnoff } 18463b3a8eb9SGleb Smirnoff | STRING { 18473b3a8eb9SGleb Smirnoff if (!strcmp($1, "default")) 18483b3a8eb9SGleb Smirnoff hfsc_opts.flags |= HFCF_DEFAULTCLASS; 18493b3a8eb9SGleb Smirnoff else if (!strcmp($1, "red")) 18503b3a8eb9SGleb Smirnoff hfsc_opts.flags |= HFCF_RED; 18513b3a8eb9SGleb Smirnoff else if (!strcmp($1, "ecn")) 18523b3a8eb9SGleb Smirnoff hfsc_opts.flags |= HFCF_RED|HFCF_ECN; 18533b3a8eb9SGleb Smirnoff else if (!strcmp($1, "rio")) 18543b3a8eb9SGleb Smirnoff hfsc_opts.flags |= HFCF_RIO; 18550a70aaf8SLuiz Otavio O Souza else if (!strcmp($1, "codel")) 18560a70aaf8SLuiz Otavio O Souza hfsc_opts.flags |= HFCF_CODEL; 18573b3a8eb9SGleb Smirnoff else { 18583b3a8eb9SGleb Smirnoff yyerror("unknown hfsc flag \"%s\"", $1); 18593b3a8eb9SGleb Smirnoff free($1); 18603b3a8eb9SGleb Smirnoff YYERROR; 18613b3a8eb9SGleb Smirnoff } 18623b3a8eb9SGleb Smirnoff free($1); 18633b3a8eb9SGleb Smirnoff } 18643b3a8eb9SGleb Smirnoff ; 18653b3a8eb9SGleb Smirnoff 1866a5b789f6SErmal Luçi fairq_opts : { 1867a5b789f6SErmal Luçi bzero(&fairq_opts, 1868a5b789f6SErmal Luçi sizeof(struct node_fairq_opts)); 1869a5b789f6SErmal Luçi } 1870a5b789f6SErmal Luçi fairqopts_list { 1871a5b789f6SErmal Luçi $$ = fairq_opts; 1872a5b789f6SErmal Luçi } 1873a5b789f6SErmal Luçi ; 1874a5b789f6SErmal Luçi 1875a5b789f6SErmal Luçi fairqopts_list : fairqopts_item 1876a5b789f6SErmal Luçi | fairqopts_list comma fairqopts_item 1877a5b789f6SErmal Luçi ; 1878a5b789f6SErmal Luçi 1879a5b789f6SErmal Luçi fairqopts_item : LINKSHARE bandwidth { 1880a5b789f6SErmal Luçi if (fairq_opts.linkshare.used) { 1881a5b789f6SErmal Luçi yyerror("linkshare already specified"); 1882a5b789f6SErmal Luçi YYERROR; 1883a5b789f6SErmal Luçi } 1884a5b789f6SErmal Luçi fairq_opts.linkshare.m2 = $2; 1885a5b789f6SErmal Luçi fairq_opts.linkshare.used = 1; 1886a5b789f6SErmal Luçi } 1887a5b789f6SErmal Luçi | LINKSHARE '(' bandwidth number bandwidth ')' { 1888a5b789f6SErmal Luçi if (fairq_opts.linkshare.used) { 1889a5b789f6SErmal Luçi yyerror("linkshare already specified"); 1890a5b789f6SErmal Luçi YYERROR; 1891a5b789f6SErmal Luçi } 1892a5b789f6SErmal Luçi fairq_opts.linkshare.m1 = $3; 1893a5b789f6SErmal Luçi fairq_opts.linkshare.d = $4; 1894a5b789f6SErmal Luçi fairq_opts.linkshare.m2 = $5; 1895a5b789f6SErmal Luçi fairq_opts.linkshare.used = 1; 1896a5b789f6SErmal Luçi } 1897a5b789f6SErmal Luçi | HOGS bandwidth { 1898a5b789f6SErmal Luçi fairq_opts.hogs_bw = $2; 1899a5b789f6SErmal Luçi } 1900a5b789f6SErmal Luçi | BUCKETS number { 1901a5b789f6SErmal Luçi fairq_opts.nbuckets = $2; 1902a5b789f6SErmal Luçi } 1903a5b789f6SErmal Luçi | STRING { 1904a5b789f6SErmal Luçi if (!strcmp($1, "default")) 1905a5b789f6SErmal Luçi fairq_opts.flags |= FARF_DEFAULTCLASS; 1906a5b789f6SErmal Luçi else if (!strcmp($1, "red")) 1907a5b789f6SErmal Luçi fairq_opts.flags |= FARF_RED; 1908a5b789f6SErmal Luçi else if (!strcmp($1, "ecn")) 1909a5b789f6SErmal Luçi fairq_opts.flags |= FARF_RED|FARF_ECN; 1910a5b789f6SErmal Luçi else if (!strcmp($1, "rio")) 1911a5b789f6SErmal Luçi fairq_opts.flags |= FARF_RIO; 19120a70aaf8SLuiz Otavio O Souza else if (!strcmp($1, "codel")) 19130a70aaf8SLuiz Otavio O Souza fairq_opts.flags |= FARF_CODEL; 1914a5b789f6SErmal Luçi else { 1915a5b789f6SErmal Luçi yyerror("unknown fairq flag \"%s\"", $1); 1916a5b789f6SErmal Luçi free($1); 1917a5b789f6SErmal Luçi YYERROR; 1918a5b789f6SErmal Luçi } 1919a5b789f6SErmal Luçi free($1); 1920a5b789f6SErmal Luçi } 1921a5b789f6SErmal Luçi ; 1922a5b789f6SErmal Luçi 19230a70aaf8SLuiz Otavio O Souza codel_opts : { 19240a70aaf8SLuiz Otavio O Souza bzero(&codel_opts, 19250a70aaf8SLuiz Otavio O Souza sizeof(struct codel_opts)); 19260a70aaf8SLuiz Otavio O Souza } 19270a70aaf8SLuiz Otavio O Souza codelopts_list { 19280a70aaf8SLuiz Otavio O Souza $$ = codel_opts; 19290a70aaf8SLuiz Otavio O Souza } 19300a70aaf8SLuiz Otavio O Souza ; 19310a70aaf8SLuiz Otavio O Souza 19320a70aaf8SLuiz Otavio O Souza codelopts_list : codelopts_item 19330a70aaf8SLuiz Otavio O Souza | codelopts_list comma codelopts_item 19340a70aaf8SLuiz Otavio O Souza ; 19350a70aaf8SLuiz Otavio O Souza 19360a70aaf8SLuiz Otavio O Souza codelopts_item : INTERVAL number { 19370a70aaf8SLuiz Otavio O Souza if (codel_opts.interval) { 19380a70aaf8SLuiz Otavio O Souza yyerror("interval already specified"); 19390a70aaf8SLuiz Otavio O Souza YYERROR; 19400a70aaf8SLuiz Otavio O Souza } 19410a70aaf8SLuiz Otavio O Souza codel_opts.interval = $2; 19420a70aaf8SLuiz Otavio O Souza } 19430a70aaf8SLuiz Otavio O Souza | TARGET number { 19440a70aaf8SLuiz Otavio O Souza if (codel_opts.target) { 19450a70aaf8SLuiz Otavio O Souza yyerror("target already specified"); 19460a70aaf8SLuiz Otavio O Souza YYERROR; 19470a70aaf8SLuiz Otavio O Souza } 19480a70aaf8SLuiz Otavio O Souza codel_opts.target = $2; 19490a70aaf8SLuiz Otavio O Souza } 19500a70aaf8SLuiz Otavio O Souza | STRING { 19510a70aaf8SLuiz Otavio O Souza if (!strcmp($1, "ecn")) 19520a70aaf8SLuiz Otavio O Souza codel_opts.ecn = 1; 19530a70aaf8SLuiz Otavio O Souza else { 19540a70aaf8SLuiz Otavio O Souza yyerror("unknown codel option \"%s\"", $1); 19550a70aaf8SLuiz Otavio O Souza free($1); 19560a70aaf8SLuiz Otavio O Souza YYERROR; 19570a70aaf8SLuiz Otavio O Souza } 19580a70aaf8SLuiz Otavio O Souza free($1); 19590a70aaf8SLuiz Otavio O Souza } 19600a70aaf8SLuiz Otavio O Souza ; 19610a70aaf8SLuiz Otavio O Souza 19623b3a8eb9SGleb Smirnoff qassign : /* empty */ { $$ = NULL; } 19633b3a8eb9SGleb Smirnoff | qassign_item { $$ = $1; } 19643b3a8eb9SGleb Smirnoff | '{' optnl qassign_list '}' { $$ = $3; } 19653b3a8eb9SGleb Smirnoff ; 19663b3a8eb9SGleb Smirnoff 19673b3a8eb9SGleb Smirnoff qassign_list : qassign_item optnl { $$ = $1; } 19683b3a8eb9SGleb Smirnoff | qassign_list comma qassign_item optnl { 19693b3a8eb9SGleb Smirnoff $1->tail->next = $3; 19703b3a8eb9SGleb Smirnoff $1->tail = $3; 19713b3a8eb9SGleb Smirnoff $$ = $1; 19723b3a8eb9SGleb Smirnoff } 19733b3a8eb9SGleb Smirnoff ; 19743b3a8eb9SGleb Smirnoff 19753b3a8eb9SGleb Smirnoff qassign_item : STRING { 19763b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_queue)); 19773b3a8eb9SGleb Smirnoff if ($$ == NULL) 19783b3a8eb9SGleb Smirnoff err(1, "qassign_item: calloc"); 19793b3a8eb9SGleb Smirnoff if (strlcpy($$->queue, $1, sizeof($$->queue)) >= 19803b3a8eb9SGleb Smirnoff sizeof($$->queue)) { 19813b3a8eb9SGleb Smirnoff yyerror("queue name '%s' too long (max " 19823b3a8eb9SGleb Smirnoff "%d chars)", $1, sizeof($$->queue)-1); 19833b3a8eb9SGleb Smirnoff free($1); 19843b3a8eb9SGleb Smirnoff free($$); 19853b3a8eb9SGleb Smirnoff YYERROR; 19863b3a8eb9SGleb Smirnoff } 19873b3a8eb9SGleb Smirnoff free($1); 19883b3a8eb9SGleb Smirnoff $$->next = NULL; 19893b3a8eb9SGleb Smirnoff $$->tail = $$; 19903b3a8eb9SGleb Smirnoff } 19913b3a8eb9SGleb Smirnoff ; 19923b3a8eb9SGleb Smirnoff 19933b3a8eb9SGleb Smirnoff pfrule : action dir logquick interface route af proto fromto 19943b3a8eb9SGleb Smirnoff filter_opts 19953b3a8eb9SGleb Smirnoff { 19963b3a8eb9SGleb Smirnoff struct pf_rule r; 19973b3a8eb9SGleb Smirnoff struct node_state_opt *o; 19983b3a8eb9SGleb Smirnoff struct node_proto *proto; 19993b3a8eb9SGleb Smirnoff int srctrack = 0; 20003b3a8eb9SGleb Smirnoff int statelock = 0; 20013b3a8eb9SGleb Smirnoff int adaptive = 0; 20023b3a8eb9SGleb Smirnoff int defaults = 0; 20033b3a8eb9SGleb Smirnoff 20043b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_FILTER)) 20053b3a8eb9SGleb Smirnoff YYERROR; 20063b3a8eb9SGleb Smirnoff 20073b3a8eb9SGleb Smirnoff memset(&r, 0, sizeof(r)); 20083b3a8eb9SGleb Smirnoff 20093b3a8eb9SGleb Smirnoff r.action = $1.b1; 20103b3a8eb9SGleb Smirnoff switch ($1.b2) { 20113b3a8eb9SGleb Smirnoff case PFRULE_RETURNRST: 20123b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_RETURNRST; 20133b3a8eb9SGleb Smirnoff r.return_ttl = $1.w; 20143b3a8eb9SGleb Smirnoff break; 20153b3a8eb9SGleb Smirnoff case PFRULE_RETURNICMP: 20163b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_RETURNICMP; 20173b3a8eb9SGleb Smirnoff r.return_icmp = $1.w; 20183b3a8eb9SGleb Smirnoff r.return_icmp6 = $1.w2; 20193b3a8eb9SGleb Smirnoff break; 20203b3a8eb9SGleb Smirnoff case PFRULE_RETURN: 20213b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_RETURN; 20223b3a8eb9SGleb Smirnoff r.return_icmp = $1.w; 20233b3a8eb9SGleb Smirnoff r.return_icmp6 = $1.w2; 20243b3a8eb9SGleb Smirnoff break; 20253b3a8eb9SGleb Smirnoff } 20263b3a8eb9SGleb Smirnoff r.direction = $2; 20273b3a8eb9SGleb Smirnoff r.log = $3.log; 20283b3a8eb9SGleb Smirnoff r.logif = $3.logif; 20293b3a8eb9SGleb Smirnoff r.quick = $3.quick; 20303b3a8eb9SGleb Smirnoff r.prob = $9.prob; 20313b3a8eb9SGleb Smirnoff r.rtableid = $9.rtableid; 20323b3a8eb9SGleb Smirnoff 20333e248e0fSKristof Provost if ($9.marker & FOM_PRIO) { 20343e248e0fSKristof Provost if ($9.prio == 0) 20353e248e0fSKristof Provost r.prio = PF_PRIO_ZERO; 20363e248e0fSKristof Provost else 20373e248e0fSKristof Provost r.prio = $9.prio; 20383e248e0fSKristof Provost } 20393e248e0fSKristof Provost if ($9.marker & FOM_SETPRIO) { 20403e248e0fSKristof Provost r.set_prio[0] = $9.set_prio[0]; 20413e248e0fSKristof Provost r.set_prio[1] = $9.set_prio[1]; 20423e248e0fSKristof Provost r.scrub_flags |= PFSTATE_SETPRIO; 20433e248e0fSKristof Provost } 20443e248e0fSKristof Provost 20453b3a8eb9SGleb Smirnoff r.af = $6; 20463b3a8eb9SGleb Smirnoff if ($9.tag) 20473b3a8eb9SGleb Smirnoff if (strlcpy(r.tagname, $9.tag, 20483b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 20493b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars", 20503b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1); 20513b3a8eb9SGleb Smirnoff YYERROR; 20523b3a8eb9SGleb Smirnoff } 20533b3a8eb9SGleb Smirnoff if ($9.match_tag) 20543b3a8eb9SGleb Smirnoff if (strlcpy(r.match_tagname, $9.match_tag, 20553b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 20563b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars", 20573b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1); 20583b3a8eb9SGleb Smirnoff YYERROR; 20593b3a8eb9SGleb Smirnoff } 20603b3a8eb9SGleb Smirnoff r.match_tag_not = $9.match_tag_not; 20613b3a8eb9SGleb Smirnoff if (rule_label(&r, $9.label)) 20623b3a8eb9SGleb Smirnoff YYERROR; 20633b3a8eb9SGleb Smirnoff free($9.label); 20643b3a8eb9SGleb Smirnoff r.flags = $9.flags.b1; 20653b3a8eb9SGleb Smirnoff r.flagset = $9.flags.b2; 20663b3a8eb9SGleb Smirnoff if (($9.flags.b1 & $9.flags.b2) != $9.flags.b1) { 20673b3a8eb9SGleb Smirnoff yyerror("flags always false"); 20683b3a8eb9SGleb Smirnoff YYERROR; 20693b3a8eb9SGleb Smirnoff } 20703b3a8eb9SGleb Smirnoff if ($9.flags.b1 || $9.flags.b2 || $8.src_os) { 20713b3a8eb9SGleb Smirnoff for (proto = $7; proto != NULL && 20723b3a8eb9SGleb Smirnoff proto->proto != IPPROTO_TCP; 20733b3a8eb9SGleb Smirnoff proto = proto->next) 20743b3a8eb9SGleb Smirnoff ; /* nothing */ 20753b3a8eb9SGleb Smirnoff if (proto == NULL && $7 != NULL) { 20763b3a8eb9SGleb Smirnoff if ($9.flags.b1 || $9.flags.b2) 20773b3a8eb9SGleb Smirnoff yyerror( 20783b3a8eb9SGleb Smirnoff "flags only apply to tcp"); 20793b3a8eb9SGleb Smirnoff if ($8.src_os) 20803b3a8eb9SGleb Smirnoff yyerror( 20813b3a8eb9SGleb Smirnoff "OS fingerprinting only " 20823b3a8eb9SGleb Smirnoff "apply to tcp"); 20833b3a8eb9SGleb Smirnoff YYERROR; 20843b3a8eb9SGleb Smirnoff } 20853b3a8eb9SGleb Smirnoff #if 0 20863b3a8eb9SGleb Smirnoff if (($9.flags.b1 & parse_flags("S")) == 0 && 20873b3a8eb9SGleb Smirnoff $8.src_os) { 20883b3a8eb9SGleb Smirnoff yyerror("OS fingerprinting requires " 20893b3a8eb9SGleb Smirnoff "the SYN TCP flag (flags S/SA)"); 20903b3a8eb9SGleb Smirnoff YYERROR; 20913b3a8eb9SGleb Smirnoff } 20923b3a8eb9SGleb Smirnoff #endif 20933b3a8eb9SGleb Smirnoff } 20943b3a8eb9SGleb Smirnoff 20953b3a8eb9SGleb Smirnoff r.tos = $9.tos; 20963b3a8eb9SGleb Smirnoff r.keep_state = $9.keep.action; 20973b3a8eb9SGleb Smirnoff o = $9.keep.options; 20983b3a8eb9SGleb Smirnoff 20993b3a8eb9SGleb Smirnoff /* 'keep state' by default on pass rules. */ 21003b3a8eb9SGleb Smirnoff if (!r.keep_state && !r.action && 21013b3a8eb9SGleb Smirnoff !($9.marker & FOM_KEEP)) { 21023b3a8eb9SGleb Smirnoff r.keep_state = PF_STATE_NORMAL; 21033b3a8eb9SGleb Smirnoff o = keep_state_defaults; 21043b3a8eb9SGleb Smirnoff defaults = 1; 21053b3a8eb9SGleb Smirnoff } 21063b3a8eb9SGleb Smirnoff 21073b3a8eb9SGleb Smirnoff while (o) { 21083b3a8eb9SGleb Smirnoff struct node_state_opt *p = o; 21093b3a8eb9SGleb Smirnoff 21103b3a8eb9SGleb Smirnoff switch (o->type) { 21113b3a8eb9SGleb Smirnoff case PF_STATE_OPT_MAX: 21123b3a8eb9SGleb Smirnoff if (r.max_states) { 21133b3a8eb9SGleb Smirnoff yyerror("state option 'max' " 21143b3a8eb9SGleb Smirnoff "multiple definitions"); 21153b3a8eb9SGleb Smirnoff YYERROR; 21163b3a8eb9SGleb Smirnoff } 21173b3a8eb9SGleb Smirnoff r.max_states = o->data.max_states; 21183b3a8eb9SGleb Smirnoff break; 21193b3a8eb9SGleb Smirnoff case PF_STATE_OPT_NOSYNC: 21203b3a8eb9SGleb Smirnoff if (r.rule_flag & PFRULE_NOSYNC) { 21213b3a8eb9SGleb Smirnoff yyerror("state option 'sync' " 21223b3a8eb9SGleb Smirnoff "multiple definitions"); 21233b3a8eb9SGleb Smirnoff YYERROR; 21243b3a8eb9SGleb Smirnoff } 21253b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_NOSYNC; 21263b3a8eb9SGleb Smirnoff break; 21273b3a8eb9SGleb Smirnoff case PF_STATE_OPT_SRCTRACK: 21283b3a8eb9SGleb Smirnoff if (srctrack) { 21293b3a8eb9SGleb Smirnoff yyerror("state option " 21303b3a8eb9SGleb Smirnoff "'source-track' " 21313b3a8eb9SGleb Smirnoff "multiple definitions"); 21323b3a8eb9SGleb Smirnoff YYERROR; 21333b3a8eb9SGleb Smirnoff } 21343b3a8eb9SGleb Smirnoff srctrack = o->data.src_track; 21353b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_SRCTRACK; 21363b3a8eb9SGleb Smirnoff break; 21373b3a8eb9SGleb Smirnoff case PF_STATE_OPT_MAX_SRC_STATES: 21383b3a8eb9SGleb Smirnoff if (r.max_src_states) { 21393b3a8eb9SGleb Smirnoff yyerror("state option " 21403b3a8eb9SGleb Smirnoff "'max-src-states' " 21413b3a8eb9SGleb Smirnoff "multiple definitions"); 21423b3a8eb9SGleb Smirnoff YYERROR; 21433b3a8eb9SGleb Smirnoff } 21443b3a8eb9SGleb Smirnoff if (o->data.max_src_states == 0) { 21453b3a8eb9SGleb Smirnoff yyerror("'max-src-states' must " 21463b3a8eb9SGleb Smirnoff "be > 0"); 21473b3a8eb9SGleb Smirnoff YYERROR; 21483b3a8eb9SGleb Smirnoff } 21493b3a8eb9SGleb Smirnoff r.max_src_states = 21503b3a8eb9SGleb Smirnoff o->data.max_src_states; 21513b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_SRCTRACK; 21523b3a8eb9SGleb Smirnoff break; 21533b3a8eb9SGleb Smirnoff case PF_STATE_OPT_OVERLOAD: 21543b3a8eb9SGleb Smirnoff if (r.overload_tblname[0]) { 21553b3a8eb9SGleb Smirnoff yyerror("multiple 'overload' " 21563b3a8eb9SGleb Smirnoff "table definitions"); 21573b3a8eb9SGleb Smirnoff YYERROR; 21583b3a8eb9SGleb Smirnoff } 21593b3a8eb9SGleb Smirnoff if (strlcpy(r.overload_tblname, 21603b3a8eb9SGleb Smirnoff o->data.overload.tblname, 21613b3a8eb9SGleb Smirnoff PF_TABLE_NAME_SIZE) >= 21623b3a8eb9SGleb Smirnoff PF_TABLE_NAME_SIZE) { 21633b3a8eb9SGleb Smirnoff yyerror("state option: " 21643b3a8eb9SGleb Smirnoff "strlcpy"); 21653b3a8eb9SGleb Smirnoff YYERROR; 21663b3a8eb9SGleb Smirnoff } 21673b3a8eb9SGleb Smirnoff r.flush = o->data.overload.flush; 21683b3a8eb9SGleb Smirnoff break; 21693b3a8eb9SGleb Smirnoff case PF_STATE_OPT_MAX_SRC_CONN: 21703b3a8eb9SGleb Smirnoff if (r.max_src_conn) { 21713b3a8eb9SGleb Smirnoff yyerror("state option " 21723b3a8eb9SGleb Smirnoff "'max-src-conn' " 21733b3a8eb9SGleb Smirnoff "multiple definitions"); 21743b3a8eb9SGleb Smirnoff YYERROR; 21753b3a8eb9SGleb Smirnoff } 21763b3a8eb9SGleb Smirnoff if (o->data.max_src_conn == 0) { 21773b3a8eb9SGleb Smirnoff yyerror("'max-src-conn' " 21783b3a8eb9SGleb Smirnoff "must be > 0"); 21793b3a8eb9SGleb Smirnoff YYERROR; 21803b3a8eb9SGleb Smirnoff } 21813b3a8eb9SGleb Smirnoff r.max_src_conn = 21823b3a8eb9SGleb Smirnoff o->data.max_src_conn; 21833b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_SRCTRACK | 21843b3a8eb9SGleb Smirnoff PFRULE_RULESRCTRACK; 21853b3a8eb9SGleb Smirnoff break; 21863b3a8eb9SGleb Smirnoff case PF_STATE_OPT_MAX_SRC_CONN_RATE: 21873b3a8eb9SGleb Smirnoff if (r.max_src_conn_rate.limit) { 21883b3a8eb9SGleb Smirnoff yyerror("state option " 21893b3a8eb9SGleb Smirnoff "'max-src-conn-rate' " 21903b3a8eb9SGleb Smirnoff "multiple definitions"); 21913b3a8eb9SGleb Smirnoff YYERROR; 21923b3a8eb9SGleb Smirnoff } 21933b3a8eb9SGleb Smirnoff if (!o->data.max_src_conn_rate.limit || 21943b3a8eb9SGleb Smirnoff !o->data.max_src_conn_rate.seconds) { 21953b3a8eb9SGleb Smirnoff yyerror("'max-src-conn-rate' " 21963b3a8eb9SGleb Smirnoff "values must be > 0"); 21973b3a8eb9SGleb Smirnoff YYERROR; 21983b3a8eb9SGleb Smirnoff } 21993b3a8eb9SGleb Smirnoff if (o->data.max_src_conn_rate.limit > 22003b3a8eb9SGleb Smirnoff PF_THRESHOLD_MAX) { 22013b3a8eb9SGleb Smirnoff yyerror("'max-src-conn-rate' " 22023b3a8eb9SGleb Smirnoff "maximum rate must be < %u", 22033b3a8eb9SGleb Smirnoff PF_THRESHOLD_MAX); 22043b3a8eb9SGleb Smirnoff YYERROR; 22053b3a8eb9SGleb Smirnoff } 22063b3a8eb9SGleb Smirnoff r.max_src_conn_rate.limit = 22073b3a8eb9SGleb Smirnoff o->data.max_src_conn_rate.limit; 22083b3a8eb9SGleb Smirnoff r.max_src_conn_rate.seconds = 22093b3a8eb9SGleb Smirnoff o->data.max_src_conn_rate.seconds; 22103b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_SRCTRACK | 22113b3a8eb9SGleb Smirnoff PFRULE_RULESRCTRACK; 22123b3a8eb9SGleb Smirnoff break; 22133b3a8eb9SGleb Smirnoff case PF_STATE_OPT_MAX_SRC_NODES: 22143b3a8eb9SGleb Smirnoff if (r.max_src_nodes) { 22153b3a8eb9SGleb Smirnoff yyerror("state option " 22163b3a8eb9SGleb Smirnoff "'max-src-nodes' " 22173b3a8eb9SGleb Smirnoff "multiple definitions"); 22183b3a8eb9SGleb Smirnoff YYERROR; 22193b3a8eb9SGleb Smirnoff } 22203b3a8eb9SGleb Smirnoff if (o->data.max_src_nodes == 0) { 22213b3a8eb9SGleb Smirnoff yyerror("'max-src-nodes' must " 22223b3a8eb9SGleb Smirnoff "be > 0"); 22233b3a8eb9SGleb Smirnoff YYERROR; 22243b3a8eb9SGleb Smirnoff } 22253b3a8eb9SGleb Smirnoff r.max_src_nodes = 22263b3a8eb9SGleb Smirnoff o->data.max_src_nodes; 22273b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_SRCTRACK | 22283b3a8eb9SGleb Smirnoff PFRULE_RULESRCTRACK; 22293b3a8eb9SGleb Smirnoff break; 22303b3a8eb9SGleb Smirnoff case PF_STATE_OPT_STATELOCK: 22313b3a8eb9SGleb Smirnoff if (statelock) { 22323b3a8eb9SGleb Smirnoff yyerror("state locking option: " 22333b3a8eb9SGleb Smirnoff "multiple definitions"); 22343b3a8eb9SGleb Smirnoff YYERROR; 22353b3a8eb9SGleb Smirnoff } 22363b3a8eb9SGleb Smirnoff statelock = 1; 22373b3a8eb9SGleb Smirnoff r.rule_flag |= o->data.statelock; 22383b3a8eb9SGleb Smirnoff break; 22393b3a8eb9SGleb Smirnoff case PF_STATE_OPT_SLOPPY: 22403b3a8eb9SGleb Smirnoff if (r.rule_flag & PFRULE_STATESLOPPY) { 22413b3a8eb9SGleb Smirnoff yyerror("state sloppy option: " 22423b3a8eb9SGleb Smirnoff "multiple definitions"); 22433b3a8eb9SGleb Smirnoff YYERROR; 22443b3a8eb9SGleb Smirnoff } 22453b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_STATESLOPPY; 22463b3a8eb9SGleb Smirnoff break; 22473b3a8eb9SGleb Smirnoff case PF_STATE_OPT_TIMEOUT: 22483b3a8eb9SGleb Smirnoff if (o->data.timeout.number == 22493b3a8eb9SGleb Smirnoff PFTM_ADAPTIVE_START || 22503b3a8eb9SGleb Smirnoff o->data.timeout.number == 22513b3a8eb9SGleb Smirnoff PFTM_ADAPTIVE_END) 22523b3a8eb9SGleb Smirnoff adaptive = 1; 22533b3a8eb9SGleb Smirnoff if (r.timeout[o->data.timeout.number]) { 22543b3a8eb9SGleb Smirnoff yyerror("state timeout %s " 22553b3a8eb9SGleb Smirnoff "multiple definitions", 22563b3a8eb9SGleb Smirnoff pf_timeouts[o->data. 22573b3a8eb9SGleb Smirnoff timeout.number].name); 22583b3a8eb9SGleb Smirnoff YYERROR; 22593b3a8eb9SGleb Smirnoff } 22603b3a8eb9SGleb Smirnoff r.timeout[o->data.timeout.number] = 22613b3a8eb9SGleb Smirnoff o->data.timeout.seconds; 22623b3a8eb9SGleb Smirnoff } 22633b3a8eb9SGleb Smirnoff o = o->next; 22643b3a8eb9SGleb Smirnoff if (!defaults) 22653b3a8eb9SGleb Smirnoff free(p); 22663b3a8eb9SGleb Smirnoff } 22673b3a8eb9SGleb Smirnoff 22683b3a8eb9SGleb Smirnoff /* 'flags S/SA' by default on stateful rules */ 22693b3a8eb9SGleb Smirnoff if (!r.action && !r.flags && !r.flagset && 22703b3a8eb9SGleb Smirnoff !$9.fragment && !($9.marker & FOM_FLAGS) && 22713b3a8eb9SGleb Smirnoff r.keep_state) { 22723b3a8eb9SGleb Smirnoff r.flags = parse_flags("S"); 22733b3a8eb9SGleb Smirnoff r.flagset = parse_flags("SA"); 22743b3a8eb9SGleb Smirnoff } 22753b3a8eb9SGleb Smirnoff if (!adaptive && r.max_states) { 22763b3a8eb9SGleb Smirnoff r.timeout[PFTM_ADAPTIVE_START] = 22773b3a8eb9SGleb Smirnoff (r.max_states / 10) * 6; 22783b3a8eb9SGleb Smirnoff r.timeout[PFTM_ADAPTIVE_END] = 22793b3a8eb9SGleb Smirnoff (r.max_states / 10) * 12; 22803b3a8eb9SGleb Smirnoff } 22813b3a8eb9SGleb Smirnoff if (r.rule_flag & PFRULE_SRCTRACK) { 22823b3a8eb9SGleb Smirnoff if (srctrack == PF_SRCTRACK_GLOBAL && 22833b3a8eb9SGleb Smirnoff r.max_src_nodes) { 22843b3a8eb9SGleb Smirnoff yyerror("'max-src-nodes' is " 22853b3a8eb9SGleb Smirnoff "incompatible with " 22863b3a8eb9SGleb Smirnoff "'source-track global'"); 22873b3a8eb9SGleb Smirnoff YYERROR; 22883b3a8eb9SGleb Smirnoff } 22893b3a8eb9SGleb Smirnoff if (srctrack == PF_SRCTRACK_GLOBAL && 22903b3a8eb9SGleb Smirnoff r.max_src_conn) { 22913b3a8eb9SGleb Smirnoff yyerror("'max-src-conn' is " 22923b3a8eb9SGleb Smirnoff "incompatible with " 22933b3a8eb9SGleb Smirnoff "'source-track global'"); 22943b3a8eb9SGleb Smirnoff YYERROR; 22953b3a8eb9SGleb Smirnoff } 22963b3a8eb9SGleb Smirnoff if (srctrack == PF_SRCTRACK_GLOBAL && 22973b3a8eb9SGleb Smirnoff r.max_src_conn_rate.seconds) { 22983b3a8eb9SGleb Smirnoff yyerror("'max-src-conn-rate' is " 22993b3a8eb9SGleb Smirnoff "incompatible with " 23003b3a8eb9SGleb Smirnoff "'source-track global'"); 23013b3a8eb9SGleb Smirnoff YYERROR; 23023b3a8eb9SGleb Smirnoff } 23033b3a8eb9SGleb Smirnoff if (r.timeout[PFTM_SRC_NODE] < 23043b3a8eb9SGleb Smirnoff r.max_src_conn_rate.seconds) 23053b3a8eb9SGleb Smirnoff r.timeout[PFTM_SRC_NODE] = 23063b3a8eb9SGleb Smirnoff r.max_src_conn_rate.seconds; 23073b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_SRCTRACK; 23083b3a8eb9SGleb Smirnoff if (srctrack == PF_SRCTRACK_RULE) 23093b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_RULESRCTRACK; 23103b3a8eb9SGleb Smirnoff } 23113b3a8eb9SGleb Smirnoff if (r.keep_state && !statelock) 23123b3a8eb9SGleb Smirnoff r.rule_flag |= default_statelock; 23133b3a8eb9SGleb Smirnoff 23143b3a8eb9SGleb Smirnoff if ($9.fragment) 23153b3a8eb9SGleb Smirnoff r.rule_flag |= PFRULE_FRAGMENT; 23163b3a8eb9SGleb Smirnoff r.allow_opts = $9.allowopts; 23173b3a8eb9SGleb Smirnoff 23183b3a8eb9SGleb Smirnoff decide_address_family($8.src.host, &r.af); 23193b3a8eb9SGleb Smirnoff decide_address_family($8.dst.host, &r.af); 23203b3a8eb9SGleb Smirnoff 23213b3a8eb9SGleb Smirnoff if ($5.rt) { 23223b3a8eb9SGleb Smirnoff if (!r.direction) { 23233b3a8eb9SGleb Smirnoff yyerror("direction must be explicit " 23243b3a8eb9SGleb Smirnoff "with rules that specify routing"); 23253b3a8eb9SGleb Smirnoff YYERROR; 23263b3a8eb9SGleb Smirnoff } 23273b3a8eb9SGleb Smirnoff r.rt = $5.rt; 23283b3a8eb9SGleb Smirnoff r.rpool.opts = $5.pool_opts; 23293b3a8eb9SGleb Smirnoff if ($5.key != NULL) 23303b3a8eb9SGleb Smirnoff memcpy(&r.rpool.key, $5.key, 23313b3a8eb9SGleb Smirnoff sizeof(struct pf_poolhashkey)); 23323b3a8eb9SGleb Smirnoff } 2333*813196a1SKristof Provost if (r.rt) { 23343b3a8eb9SGleb Smirnoff decide_address_family($5.host, &r.af); 23353b3a8eb9SGleb Smirnoff remove_invalid_hosts(&$5.host, &r.af); 23363b3a8eb9SGleb Smirnoff if ($5.host == NULL) { 23373b3a8eb9SGleb Smirnoff yyerror("no routing address with " 23383b3a8eb9SGleb Smirnoff "matching address family found."); 23393b3a8eb9SGleb Smirnoff YYERROR; 23403b3a8eb9SGleb Smirnoff } 23413b3a8eb9SGleb Smirnoff if ((r.rpool.opts & PF_POOL_TYPEMASK) == 23423b3a8eb9SGleb Smirnoff PF_POOL_NONE && ($5.host->next != NULL || 23433b3a8eb9SGleb Smirnoff $5.host->addr.type == PF_ADDR_TABLE || 23443b3a8eb9SGleb Smirnoff DYNIF_MULTIADDR($5.host->addr))) 23453b3a8eb9SGleb Smirnoff r.rpool.opts |= PF_POOL_ROUNDROBIN; 23463b3a8eb9SGleb Smirnoff if ((r.rpool.opts & PF_POOL_TYPEMASK) != 23473b3a8eb9SGleb Smirnoff PF_POOL_ROUNDROBIN && 23483b3a8eb9SGleb Smirnoff disallow_table($5.host, "tables are only " 23493b3a8eb9SGleb Smirnoff "supported in round-robin routing pools")) 23503b3a8eb9SGleb Smirnoff YYERROR; 23513b3a8eb9SGleb Smirnoff if ((r.rpool.opts & PF_POOL_TYPEMASK) != 23523b3a8eb9SGleb Smirnoff PF_POOL_ROUNDROBIN && 23533b3a8eb9SGleb Smirnoff disallow_alias($5.host, "interface (%s) " 23543b3a8eb9SGleb Smirnoff "is only supported in round-robin " 23553b3a8eb9SGleb Smirnoff "routing pools")) 23563b3a8eb9SGleb Smirnoff YYERROR; 23573b3a8eb9SGleb Smirnoff if ($5.host->next != NULL) { 23583b3a8eb9SGleb Smirnoff if ((r.rpool.opts & PF_POOL_TYPEMASK) != 23593b3a8eb9SGleb Smirnoff PF_POOL_ROUNDROBIN) { 23603b3a8eb9SGleb Smirnoff yyerror("r.rpool.opts must " 23613b3a8eb9SGleb Smirnoff "be PF_POOL_ROUNDROBIN"); 23623b3a8eb9SGleb Smirnoff YYERROR; 23633b3a8eb9SGleb Smirnoff } 23643b3a8eb9SGleb Smirnoff } 23653b3a8eb9SGleb Smirnoff } 23663b3a8eb9SGleb Smirnoff if ($9.queues.qname != NULL) { 23673b3a8eb9SGleb Smirnoff if (strlcpy(r.qname, $9.queues.qname, 23683b3a8eb9SGleb Smirnoff sizeof(r.qname)) >= sizeof(r.qname)) { 23693b3a8eb9SGleb Smirnoff yyerror("rule qname too long (max " 23703b3a8eb9SGleb Smirnoff "%d chars)", sizeof(r.qname)-1); 23713b3a8eb9SGleb Smirnoff YYERROR; 23723b3a8eb9SGleb Smirnoff } 23733b3a8eb9SGleb Smirnoff free($9.queues.qname); 23743b3a8eb9SGleb Smirnoff } 23753b3a8eb9SGleb Smirnoff if ($9.queues.pqname != NULL) { 23763b3a8eb9SGleb Smirnoff if (strlcpy(r.pqname, $9.queues.pqname, 23773b3a8eb9SGleb Smirnoff sizeof(r.pqname)) >= sizeof(r.pqname)) { 23783b3a8eb9SGleb Smirnoff yyerror("rule pqname too long (max " 23793b3a8eb9SGleb Smirnoff "%d chars)", sizeof(r.pqname)-1); 23803b3a8eb9SGleb Smirnoff YYERROR; 23813b3a8eb9SGleb Smirnoff } 23823b3a8eb9SGleb Smirnoff free($9.queues.pqname); 23833b3a8eb9SGleb Smirnoff } 23843b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 23853b3a8eb9SGleb Smirnoff r.divert.port = $9.divert.port; 23863b3a8eb9SGleb Smirnoff #else 23873b3a8eb9SGleb Smirnoff if ((r.divert.port = $9.divert.port)) { 23883b3a8eb9SGleb Smirnoff if (r.direction == PF_OUT) { 23893b3a8eb9SGleb Smirnoff if ($9.divert.addr) { 23903b3a8eb9SGleb Smirnoff yyerror("address specified " 23913b3a8eb9SGleb Smirnoff "for outgoing divert"); 23923b3a8eb9SGleb Smirnoff YYERROR; 23933b3a8eb9SGleb Smirnoff } 23943b3a8eb9SGleb Smirnoff bzero(&r.divert.addr, 23953b3a8eb9SGleb Smirnoff sizeof(r.divert.addr)); 23963b3a8eb9SGleb Smirnoff } else { 23973b3a8eb9SGleb Smirnoff if (!$9.divert.addr) { 23983b3a8eb9SGleb Smirnoff yyerror("no address specified " 23993b3a8eb9SGleb Smirnoff "for incoming divert"); 24003b3a8eb9SGleb Smirnoff YYERROR; 24013b3a8eb9SGleb Smirnoff } 24023b3a8eb9SGleb Smirnoff if ($9.divert.addr->af != r.af) { 24033b3a8eb9SGleb Smirnoff yyerror("address family " 24043b3a8eb9SGleb Smirnoff "mismatch for divert"); 24053b3a8eb9SGleb Smirnoff YYERROR; 24063b3a8eb9SGleb Smirnoff } 24073b3a8eb9SGleb Smirnoff r.divert.addr = 24083b3a8eb9SGleb Smirnoff $9.divert.addr->addr.v.a.addr; 24093b3a8eb9SGleb Smirnoff } 24103b3a8eb9SGleb Smirnoff } 24113b3a8eb9SGleb Smirnoff #endif 24123b3a8eb9SGleb Smirnoff 24133b3a8eb9SGleb Smirnoff expand_rule(&r, $4, $5.host, $7, $8.src_os, 24143b3a8eb9SGleb Smirnoff $8.src.host, $8.src.port, $8.dst.host, $8.dst.port, 24153b3a8eb9SGleb Smirnoff $9.uid, $9.gid, $9.icmpspec, ""); 24163b3a8eb9SGleb Smirnoff } 24173b3a8eb9SGleb Smirnoff ; 24183b3a8eb9SGleb Smirnoff 24193b3a8eb9SGleb Smirnoff filter_opts : { 24203b3a8eb9SGleb Smirnoff bzero(&filter_opts, sizeof filter_opts); 24213b3a8eb9SGleb Smirnoff filter_opts.rtableid = -1; 24223b3a8eb9SGleb Smirnoff } 24233b3a8eb9SGleb Smirnoff filter_opts_l 24243b3a8eb9SGleb Smirnoff { $$ = filter_opts; } 24253b3a8eb9SGleb Smirnoff | /* empty */ { 24263b3a8eb9SGleb Smirnoff bzero(&filter_opts, sizeof filter_opts); 24273b3a8eb9SGleb Smirnoff filter_opts.rtableid = -1; 24283b3a8eb9SGleb Smirnoff $$ = filter_opts; 24293b3a8eb9SGleb Smirnoff } 24303b3a8eb9SGleb Smirnoff ; 24313b3a8eb9SGleb Smirnoff 24323b3a8eb9SGleb Smirnoff filter_opts_l : filter_opts_l filter_opt 24333b3a8eb9SGleb Smirnoff | filter_opt 24343b3a8eb9SGleb Smirnoff ; 24353b3a8eb9SGleb Smirnoff 24363b3a8eb9SGleb Smirnoff filter_opt : USER uids { 24373b3a8eb9SGleb Smirnoff if (filter_opts.uid) 24383b3a8eb9SGleb Smirnoff $2->tail->next = filter_opts.uid; 24393b3a8eb9SGleb Smirnoff filter_opts.uid = $2; 24403b3a8eb9SGleb Smirnoff } 24413b3a8eb9SGleb Smirnoff | GROUP gids { 24423b3a8eb9SGleb Smirnoff if (filter_opts.gid) 24433b3a8eb9SGleb Smirnoff $2->tail->next = filter_opts.gid; 24443b3a8eb9SGleb Smirnoff filter_opts.gid = $2; 24453b3a8eb9SGleb Smirnoff } 24463b3a8eb9SGleb Smirnoff | flags { 24473b3a8eb9SGleb Smirnoff if (filter_opts.marker & FOM_FLAGS) { 24483b3a8eb9SGleb Smirnoff yyerror("flags cannot be redefined"); 24493b3a8eb9SGleb Smirnoff YYERROR; 24503b3a8eb9SGleb Smirnoff } 24513b3a8eb9SGleb Smirnoff filter_opts.marker |= FOM_FLAGS; 24523b3a8eb9SGleb Smirnoff filter_opts.flags.b1 |= $1.b1; 24533b3a8eb9SGleb Smirnoff filter_opts.flags.b2 |= $1.b2; 24543b3a8eb9SGleb Smirnoff filter_opts.flags.w |= $1.w; 24553b3a8eb9SGleb Smirnoff filter_opts.flags.w2 |= $1.w2; 24563b3a8eb9SGleb Smirnoff } 24573b3a8eb9SGleb Smirnoff | icmpspec { 24583b3a8eb9SGleb Smirnoff if (filter_opts.marker & FOM_ICMP) { 24593b3a8eb9SGleb Smirnoff yyerror("icmp-type cannot be redefined"); 24603b3a8eb9SGleb Smirnoff YYERROR; 24613b3a8eb9SGleb Smirnoff } 24623b3a8eb9SGleb Smirnoff filter_opts.marker |= FOM_ICMP; 24633b3a8eb9SGleb Smirnoff filter_opts.icmpspec = $1; 24643b3a8eb9SGleb Smirnoff } 24653e248e0fSKristof Provost | PRIO NUMBER { 24663e248e0fSKristof Provost if (filter_opts.marker & FOM_PRIO) { 24673e248e0fSKristof Provost yyerror("prio cannot be redefined"); 24683e248e0fSKristof Provost YYERROR; 24693e248e0fSKristof Provost } 24703e248e0fSKristof Provost if ($2 < 0 || $2 > PF_PRIO_MAX) { 24713e248e0fSKristof Provost yyerror("prio must be 0 - %u", PF_PRIO_MAX); 24723e248e0fSKristof Provost YYERROR; 24733e248e0fSKristof Provost } 24743e248e0fSKristof Provost filter_opts.marker |= FOM_PRIO; 24753e248e0fSKristof Provost filter_opts.prio = $2; 24763e248e0fSKristof Provost } 24773b3a8eb9SGleb Smirnoff | TOS tos { 24783b3a8eb9SGleb Smirnoff if (filter_opts.marker & FOM_TOS) { 24793b3a8eb9SGleb Smirnoff yyerror("tos cannot be redefined"); 24803b3a8eb9SGleb Smirnoff YYERROR; 24813b3a8eb9SGleb Smirnoff } 24823b3a8eb9SGleb Smirnoff filter_opts.marker |= FOM_TOS; 24833b3a8eb9SGleb Smirnoff filter_opts.tos = $2; 24843b3a8eb9SGleb Smirnoff } 24853b3a8eb9SGleb Smirnoff | keep { 24863b3a8eb9SGleb Smirnoff if (filter_opts.marker & FOM_KEEP) { 24873b3a8eb9SGleb Smirnoff yyerror("modulate or keep cannot be redefined"); 24883b3a8eb9SGleb Smirnoff YYERROR; 24893b3a8eb9SGleb Smirnoff } 24903b3a8eb9SGleb Smirnoff filter_opts.marker |= FOM_KEEP; 24913b3a8eb9SGleb Smirnoff filter_opts.keep.action = $1.action; 24923b3a8eb9SGleb Smirnoff filter_opts.keep.options = $1.options; 24933b3a8eb9SGleb Smirnoff } 24943b3a8eb9SGleb Smirnoff | FRAGMENT { 24953b3a8eb9SGleb Smirnoff filter_opts.fragment = 1; 24963b3a8eb9SGleb Smirnoff } 24973b3a8eb9SGleb Smirnoff | ALLOWOPTS { 24983b3a8eb9SGleb Smirnoff filter_opts.allowopts = 1; 24993b3a8eb9SGleb Smirnoff } 25003b3a8eb9SGleb Smirnoff | label { 25013b3a8eb9SGleb Smirnoff if (filter_opts.label) { 25023b3a8eb9SGleb Smirnoff yyerror("label cannot be redefined"); 25033b3a8eb9SGleb Smirnoff YYERROR; 25043b3a8eb9SGleb Smirnoff } 25053b3a8eb9SGleb Smirnoff filter_opts.label = $1; 25063b3a8eb9SGleb Smirnoff } 25073b3a8eb9SGleb Smirnoff | qname { 25083b3a8eb9SGleb Smirnoff if (filter_opts.queues.qname) { 25093b3a8eb9SGleb Smirnoff yyerror("queue cannot be redefined"); 25103b3a8eb9SGleb Smirnoff YYERROR; 25113b3a8eb9SGleb Smirnoff } 25123b3a8eb9SGleb Smirnoff filter_opts.queues = $1; 25133b3a8eb9SGleb Smirnoff } 25143b3a8eb9SGleb Smirnoff | TAG string { 25153b3a8eb9SGleb Smirnoff filter_opts.tag = $2; 25163b3a8eb9SGleb Smirnoff } 25173b3a8eb9SGleb Smirnoff | not TAGGED string { 25183b3a8eb9SGleb Smirnoff filter_opts.match_tag = $3; 25193b3a8eb9SGleb Smirnoff filter_opts.match_tag_not = $1; 25203b3a8eb9SGleb Smirnoff } 25213b3a8eb9SGleb Smirnoff | PROBABILITY probability { 25223b3a8eb9SGleb Smirnoff double p; 25233b3a8eb9SGleb Smirnoff 25243b3a8eb9SGleb Smirnoff p = floor($2 * UINT_MAX + 0.5); 25253b3a8eb9SGleb Smirnoff if (p < 0.0 || p > UINT_MAX) { 25263b3a8eb9SGleb Smirnoff yyerror("invalid probability: %lf", p); 25273b3a8eb9SGleb Smirnoff YYERROR; 25283b3a8eb9SGleb Smirnoff } 25293b3a8eb9SGleb Smirnoff filter_opts.prob = (u_int32_t)p; 25303b3a8eb9SGleb Smirnoff if (filter_opts.prob == 0) 25313b3a8eb9SGleb Smirnoff filter_opts.prob = 1; 25323b3a8eb9SGleb Smirnoff } 25333b3a8eb9SGleb Smirnoff | RTABLE NUMBER { 25343b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > rt_tableid_max()) { 25353b3a8eb9SGleb Smirnoff yyerror("invalid rtable id"); 25363b3a8eb9SGleb Smirnoff YYERROR; 25373b3a8eb9SGleb Smirnoff } 25383b3a8eb9SGleb Smirnoff filter_opts.rtableid = $2; 25393b3a8eb9SGleb Smirnoff } 25403b3a8eb9SGleb Smirnoff | DIVERTTO portplain { 25413b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 25423b3a8eb9SGleb Smirnoff filter_opts.divert.port = $2.a; 25433b3a8eb9SGleb Smirnoff if (!filter_opts.divert.port) { 25443b3a8eb9SGleb Smirnoff yyerror("invalid divert port: %u", ntohs($2.a)); 25453b3a8eb9SGleb Smirnoff YYERROR; 25463b3a8eb9SGleb Smirnoff } 25473b3a8eb9SGleb Smirnoff #endif 25483b3a8eb9SGleb Smirnoff } 25493b3a8eb9SGleb Smirnoff | DIVERTTO STRING PORT portplain { 25503b3a8eb9SGleb Smirnoff #ifndef __FreeBSD__ 25513b3a8eb9SGleb Smirnoff if ((filter_opts.divert.addr = host($2)) == NULL) { 25523b3a8eb9SGleb Smirnoff yyerror("could not parse divert address: %s", 25533b3a8eb9SGleb Smirnoff $2); 25543b3a8eb9SGleb Smirnoff free($2); 25553b3a8eb9SGleb Smirnoff YYERROR; 25563b3a8eb9SGleb Smirnoff } 25573b3a8eb9SGleb Smirnoff #else 25583b3a8eb9SGleb Smirnoff if ($2) 25593b3a8eb9SGleb Smirnoff #endif 25603b3a8eb9SGleb Smirnoff free($2); 25613b3a8eb9SGleb Smirnoff filter_opts.divert.port = $4.a; 25623b3a8eb9SGleb Smirnoff if (!filter_opts.divert.port) { 25633b3a8eb9SGleb Smirnoff yyerror("invalid divert port: %u", ntohs($4.a)); 25643b3a8eb9SGleb Smirnoff YYERROR; 25653b3a8eb9SGleb Smirnoff } 25663b3a8eb9SGleb Smirnoff } 25673b3a8eb9SGleb Smirnoff | DIVERTREPLY { 25683b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 25693b3a8eb9SGleb Smirnoff yyerror("divert-reply has no meaning in FreeBSD pf(4)"); 25703b3a8eb9SGleb Smirnoff YYERROR; 25713b3a8eb9SGleb Smirnoff #else 25723b3a8eb9SGleb Smirnoff filter_opts.divert.port = 1; /* some random value */ 25733b3a8eb9SGleb Smirnoff #endif 25743b3a8eb9SGleb Smirnoff } 25753e248e0fSKristof Provost | filter_sets 25763e248e0fSKristof Provost ; 25773e248e0fSKristof Provost 25783e248e0fSKristof Provost filter_sets : SET '(' filter_sets_l ')' { $$ = filter_opts; } 25793e248e0fSKristof Provost | SET filter_set { $$ = filter_opts; } 25803e248e0fSKristof Provost ; 25813e248e0fSKristof Provost 25823e248e0fSKristof Provost filter_sets_l : filter_sets_l comma filter_set 25833e248e0fSKristof Provost | filter_set 25843e248e0fSKristof Provost ; 25853e248e0fSKristof Provost 25863e248e0fSKristof Provost filter_set : prio { 25873e248e0fSKristof Provost if (filter_opts.marker & FOM_SETPRIO) { 25883e248e0fSKristof Provost yyerror("prio cannot be redefined"); 25893e248e0fSKristof Provost YYERROR; 25903e248e0fSKristof Provost } 25913e248e0fSKristof Provost filter_opts.marker |= FOM_SETPRIO; 25923e248e0fSKristof Provost filter_opts.set_prio[0] = $1.b1; 25933e248e0fSKristof Provost filter_opts.set_prio[1] = $1.b2; 25943e248e0fSKristof Provost } 25953e248e0fSKristof Provost prio : PRIO NUMBER { 25963e248e0fSKristof Provost if ($2 < 0 || $2 > PF_PRIO_MAX) { 25973e248e0fSKristof Provost yyerror("prio must be 0 - %u", PF_PRIO_MAX); 25983e248e0fSKristof Provost YYERROR; 25993e248e0fSKristof Provost } 26003e248e0fSKristof Provost $$.b1 = $$.b2 = $2; 26013e248e0fSKristof Provost } 26023e248e0fSKristof Provost | PRIO '(' NUMBER comma NUMBER ')' { 26033e248e0fSKristof Provost if ($3 < 0 || $3 > PF_PRIO_MAX || 26043e248e0fSKristof Provost $5 < 0 || $5 > PF_PRIO_MAX) { 26053e248e0fSKristof Provost yyerror("prio must be 0 - %u", PF_PRIO_MAX); 26063e248e0fSKristof Provost YYERROR; 26073e248e0fSKristof Provost } 26083e248e0fSKristof Provost $$.b1 = $3; 26093e248e0fSKristof Provost $$.b2 = $5; 26103e248e0fSKristof Provost } 26113b3a8eb9SGleb Smirnoff ; 26123b3a8eb9SGleb Smirnoff 26133b3a8eb9SGleb Smirnoff probability : STRING { 26143b3a8eb9SGleb Smirnoff char *e; 26153b3a8eb9SGleb Smirnoff double p = strtod($1, &e); 26163b3a8eb9SGleb Smirnoff 26173b3a8eb9SGleb Smirnoff if (*e == '%') { 26183b3a8eb9SGleb Smirnoff p *= 0.01; 26193b3a8eb9SGleb Smirnoff e++; 26203b3a8eb9SGleb Smirnoff } 26213b3a8eb9SGleb Smirnoff if (*e) { 26223b3a8eb9SGleb Smirnoff yyerror("invalid probability: %s", $1); 26233b3a8eb9SGleb Smirnoff free($1); 26243b3a8eb9SGleb Smirnoff YYERROR; 26253b3a8eb9SGleb Smirnoff } 26263b3a8eb9SGleb Smirnoff free($1); 26273b3a8eb9SGleb Smirnoff $$ = p; 26283b3a8eb9SGleb Smirnoff } 26293b3a8eb9SGleb Smirnoff | NUMBER { 26303b3a8eb9SGleb Smirnoff $$ = (double)$1; 26313b3a8eb9SGleb Smirnoff } 26323b3a8eb9SGleb Smirnoff ; 26333b3a8eb9SGleb Smirnoff 26343b3a8eb9SGleb Smirnoff 26353b3a8eb9SGleb Smirnoff action : PASS { $$.b1 = PF_PASS; $$.b2 = $$.w = 0; } 26363b3a8eb9SGleb Smirnoff | BLOCK blockspec { $$ = $2; $$.b1 = PF_DROP; } 26373b3a8eb9SGleb Smirnoff ; 26383b3a8eb9SGleb Smirnoff 26393b3a8eb9SGleb Smirnoff blockspec : /* empty */ { 26403b3a8eb9SGleb Smirnoff $$.b2 = blockpolicy; 26413b3a8eb9SGleb Smirnoff $$.w = returnicmpdefault; 26423b3a8eb9SGleb Smirnoff $$.w2 = returnicmp6default; 26433b3a8eb9SGleb Smirnoff } 26443b3a8eb9SGleb Smirnoff | DROP { 26453b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_DROP; 26463b3a8eb9SGleb Smirnoff $$.w = 0; 26473b3a8eb9SGleb Smirnoff $$.w2 = 0; 26483b3a8eb9SGleb Smirnoff } 26493b3a8eb9SGleb Smirnoff | RETURNRST { 26503b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURNRST; 26513b3a8eb9SGleb Smirnoff $$.w = 0; 26523b3a8eb9SGleb Smirnoff $$.w2 = 0; 26533b3a8eb9SGleb Smirnoff } 26543b3a8eb9SGleb Smirnoff | RETURNRST '(' TTL NUMBER ')' { 26553b3a8eb9SGleb Smirnoff if ($4 < 0 || $4 > 255) { 26563b3a8eb9SGleb Smirnoff yyerror("illegal ttl value %d", $4); 26573b3a8eb9SGleb Smirnoff YYERROR; 26583b3a8eb9SGleb Smirnoff } 26593b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURNRST; 26603b3a8eb9SGleb Smirnoff $$.w = $4; 26613b3a8eb9SGleb Smirnoff $$.w2 = 0; 26623b3a8eb9SGleb Smirnoff } 26633b3a8eb9SGleb Smirnoff | RETURNICMP { 26643b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURNICMP; 26653b3a8eb9SGleb Smirnoff $$.w = returnicmpdefault; 26663b3a8eb9SGleb Smirnoff $$.w2 = returnicmp6default; 26673b3a8eb9SGleb Smirnoff } 26683b3a8eb9SGleb Smirnoff | RETURNICMP6 { 26693b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURNICMP; 26703b3a8eb9SGleb Smirnoff $$.w = returnicmpdefault; 26713b3a8eb9SGleb Smirnoff $$.w2 = returnicmp6default; 26723b3a8eb9SGleb Smirnoff } 26733b3a8eb9SGleb Smirnoff | RETURNICMP '(' reticmpspec ')' { 26743b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURNICMP; 26753b3a8eb9SGleb Smirnoff $$.w = $3; 26763b3a8eb9SGleb Smirnoff $$.w2 = returnicmpdefault; 26773b3a8eb9SGleb Smirnoff } 26783b3a8eb9SGleb Smirnoff | RETURNICMP6 '(' reticmp6spec ')' { 26793b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURNICMP; 26803b3a8eb9SGleb Smirnoff $$.w = returnicmpdefault; 26813b3a8eb9SGleb Smirnoff $$.w2 = $3; 26823b3a8eb9SGleb Smirnoff } 26833b3a8eb9SGleb Smirnoff | RETURNICMP '(' reticmpspec comma reticmp6spec ')' { 26843b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURNICMP; 26853b3a8eb9SGleb Smirnoff $$.w = $3; 26863b3a8eb9SGleb Smirnoff $$.w2 = $5; 26873b3a8eb9SGleb Smirnoff } 26883b3a8eb9SGleb Smirnoff | RETURN { 26893b3a8eb9SGleb Smirnoff $$.b2 = PFRULE_RETURN; 26903b3a8eb9SGleb Smirnoff $$.w = returnicmpdefault; 26913b3a8eb9SGleb Smirnoff $$.w2 = returnicmp6default; 26923b3a8eb9SGleb Smirnoff } 26933b3a8eb9SGleb Smirnoff ; 26943b3a8eb9SGleb Smirnoff 26953b3a8eb9SGleb Smirnoff reticmpspec : STRING { 26963b3a8eb9SGleb Smirnoff if (!($$ = parseicmpspec($1, AF_INET))) { 26973b3a8eb9SGleb Smirnoff free($1); 26983b3a8eb9SGleb Smirnoff YYERROR; 26993b3a8eb9SGleb Smirnoff } 27003b3a8eb9SGleb Smirnoff free($1); 27013b3a8eb9SGleb Smirnoff } 27023b3a8eb9SGleb Smirnoff | NUMBER { 27033b3a8eb9SGleb Smirnoff u_int8_t icmptype; 27043b3a8eb9SGleb Smirnoff 27053b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 > 255) { 27063b3a8eb9SGleb Smirnoff yyerror("invalid icmp code %lu", $1); 27073b3a8eb9SGleb Smirnoff YYERROR; 27083b3a8eb9SGleb Smirnoff } 27093b3a8eb9SGleb Smirnoff icmptype = returnicmpdefault >> 8; 27103b3a8eb9SGleb Smirnoff $$ = (icmptype << 8 | $1); 27113b3a8eb9SGleb Smirnoff } 27123b3a8eb9SGleb Smirnoff ; 27133b3a8eb9SGleb Smirnoff 27143b3a8eb9SGleb Smirnoff reticmp6spec : STRING { 27153b3a8eb9SGleb Smirnoff if (!($$ = parseicmpspec($1, AF_INET6))) { 27163b3a8eb9SGleb Smirnoff free($1); 27173b3a8eb9SGleb Smirnoff YYERROR; 27183b3a8eb9SGleb Smirnoff } 27193b3a8eb9SGleb Smirnoff free($1); 27203b3a8eb9SGleb Smirnoff } 27213b3a8eb9SGleb Smirnoff | NUMBER { 27223b3a8eb9SGleb Smirnoff u_int8_t icmptype; 27233b3a8eb9SGleb Smirnoff 27243b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 > 255) { 27253b3a8eb9SGleb Smirnoff yyerror("invalid icmp code %lu", $1); 27263b3a8eb9SGleb Smirnoff YYERROR; 27273b3a8eb9SGleb Smirnoff } 27283b3a8eb9SGleb Smirnoff icmptype = returnicmp6default >> 8; 27293b3a8eb9SGleb Smirnoff $$ = (icmptype << 8 | $1); 27303b3a8eb9SGleb Smirnoff } 27313b3a8eb9SGleb Smirnoff ; 27323b3a8eb9SGleb Smirnoff 27333b3a8eb9SGleb Smirnoff dir : /* empty */ { $$ = PF_INOUT; } 27343b3a8eb9SGleb Smirnoff | IN { $$ = PF_IN; } 27353b3a8eb9SGleb Smirnoff | OUT { $$ = PF_OUT; } 27363b3a8eb9SGleb Smirnoff ; 27373b3a8eb9SGleb Smirnoff 27383b3a8eb9SGleb Smirnoff quick : /* empty */ { $$.quick = 0; } 27393b3a8eb9SGleb Smirnoff | QUICK { $$.quick = 1; } 27403b3a8eb9SGleb Smirnoff ; 27413b3a8eb9SGleb Smirnoff 27423b3a8eb9SGleb Smirnoff logquick : /* empty */ { $$.log = 0; $$.quick = 0; $$.logif = 0; } 27433b3a8eb9SGleb Smirnoff | log { $$ = $1; $$.quick = 0; } 27443b3a8eb9SGleb Smirnoff | QUICK { $$.quick = 1; $$.log = 0; $$.logif = 0; } 27453b3a8eb9SGleb Smirnoff | log QUICK { $$ = $1; $$.quick = 1; } 27463b3a8eb9SGleb Smirnoff | QUICK log { $$ = $2; $$.quick = 1; } 27473b3a8eb9SGleb Smirnoff ; 27483b3a8eb9SGleb Smirnoff 27493b3a8eb9SGleb Smirnoff log : LOG { $$.log = PF_LOG; $$.logif = 0; } 27503b3a8eb9SGleb Smirnoff | LOG '(' logopts ')' { 27513b3a8eb9SGleb Smirnoff $$.log = PF_LOG | $3.log; 27523b3a8eb9SGleb Smirnoff $$.logif = $3.logif; 27533b3a8eb9SGleb Smirnoff } 27543b3a8eb9SGleb Smirnoff ; 27553b3a8eb9SGleb Smirnoff 27563b3a8eb9SGleb Smirnoff logopts : logopt { $$ = $1; } 27573b3a8eb9SGleb Smirnoff | logopts comma logopt { 27583b3a8eb9SGleb Smirnoff $$.log = $1.log | $3.log; 27593b3a8eb9SGleb Smirnoff $$.logif = $3.logif; 27603b3a8eb9SGleb Smirnoff if ($$.logif == 0) 27613b3a8eb9SGleb Smirnoff $$.logif = $1.logif; 27623b3a8eb9SGleb Smirnoff } 27633b3a8eb9SGleb Smirnoff ; 27643b3a8eb9SGleb Smirnoff 27653b3a8eb9SGleb Smirnoff logopt : ALL { $$.log = PF_LOG_ALL; $$.logif = 0; } 27663b3a8eb9SGleb Smirnoff | USER { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; } 27673b3a8eb9SGleb Smirnoff | GROUP { $$.log = PF_LOG_SOCKET_LOOKUP; $$.logif = 0; } 27683b3a8eb9SGleb Smirnoff | TO string { 27693b3a8eb9SGleb Smirnoff const char *errstr; 27703b3a8eb9SGleb Smirnoff u_int i; 27713b3a8eb9SGleb Smirnoff 27723b3a8eb9SGleb Smirnoff $$.log = 0; 27733b3a8eb9SGleb Smirnoff if (strncmp($2, "pflog", 5)) { 27743b3a8eb9SGleb Smirnoff yyerror("%s: should be a pflog interface", $2); 27753b3a8eb9SGleb Smirnoff free($2); 27763b3a8eb9SGleb Smirnoff YYERROR; 27773b3a8eb9SGleb Smirnoff } 27783b3a8eb9SGleb Smirnoff i = strtonum($2 + 5, 0, 255, &errstr); 27793b3a8eb9SGleb Smirnoff if (errstr) { 27803b3a8eb9SGleb Smirnoff yyerror("%s: %s", $2, errstr); 27813b3a8eb9SGleb Smirnoff free($2); 27823b3a8eb9SGleb Smirnoff YYERROR; 27833b3a8eb9SGleb Smirnoff } 27843b3a8eb9SGleb Smirnoff free($2); 27853b3a8eb9SGleb Smirnoff $$.logif = i; 27863b3a8eb9SGleb Smirnoff } 27873b3a8eb9SGleb Smirnoff ; 27883b3a8eb9SGleb Smirnoff 27893b3a8eb9SGleb Smirnoff interface : /* empty */ { $$ = NULL; } 27903b3a8eb9SGleb Smirnoff | ON if_item_not { $$ = $2; } 27913b3a8eb9SGleb Smirnoff | ON '{' optnl if_list '}' { $$ = $4; } 27923b3a8eb9SGleb Smirnoff ; 27933b3a8eb9SGleb Smirnoff 27943b3a8eb9SGleb Smirnoff if_list : if_item_not optnl { $$ = $1; } 27953b3a8eb9SGleb Smirnoff | if_list comma if_item_not optnl { 27963b3a8eb9SGleb Smirnoff $1->tail->next = $3; 27973b3a8eb9SGleb Smirnoff $1->tail = $3; 27983b3a8eb9SGleb Smirnoff $$ = $1; 27993b3a8eb9SGleb Smirnoff } 28003b3a8eb9SGleb Smirnoff ; 28013b3a8eb9SGleb Smirnoff 28023b3a8eb9SGleb Smirnoff if_item_not : not if_item { $$ = $2; $$->not = $1; } 28033b3a8eb9SGleb Smirnoff ; 28043b3a8eb9SGleb Smirnoff 28053b3a8eb9SGleb Smirnoff if_item : STRING { 28063b3a8eb9SGleb Smirnoff struct node_host *n; 28073b3a8eb9SGleb Smirnoff 28083b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_if)); 28093b3a8eb9SGleb Smirnoff if ($$ == NULL) 28103b3a8eb9SGleb Smirnoff err(1, "if_item: calloc"); 28113b3a8eb9SGleb Smirnoff if (strlcpy($$->ifname, $1, sizeof($$->ifname)) >= 28123b3a8eb9SGleb Smirnoff sizeof($$->ifname)) { 28133b3a8eb9SGleb Smirnoff free($1); 28143b3a8eb9SGleb Smirnoff free($$); 28153b3a8eb9SGleb Smirnoff yyerror("interface name too long"); 28163b3a8eb9SGleb Smirnoff YYERROR; 28173b3a8eb9SGleb Smirnoff } 28183b3a8eb9SGleb Smirnoff 28193b3a8eb9SGleb Smirnoff if ((n = ifa_exists($1)) != NULL) 28203b3a8eb9SGleb Smirnoff $$->ifa_flags = n->ifa_flags; 28213b3a8eb9SGleb Smirnoff 28223b3a8eb9SGleb Smirnoff free($1); 28233b3a8eb9SGleb Smirnoff $$->not = 0; 28243b3a8eb9SGleb Smirnoff $$->next = NULL; 28253b3a8eb9SGleb Smirnoff $$->tail = $$; 28263b3a8eb9SGleb Smirnoff } 28273b3a8eb9SGleb Smirnoff ; 28283b3a8eb9SGleb Smirnoff 28293b3a8eb9SGleb Smirnoff af : /* empty */ { $$ = 0; } 28303b3a8eb9SGleb Smirnoff | INET { $$ = AF_INET; } 28313b3a8eb9SGleb Smirnoff | INET6 { $$ = AF_INET6; } 28323b3a8eb9SGleb Smirnoff ; 28333b3a8eb9SGleb Smirnoff 28343b3a8eb9SGleb Smirnoff proto : /* empty */ { $$ = NULL; } 28353b3a8eb9SGleb Smirnoff | PROTO proto_item { $$ = $2; } 28363b3a8eb9SGleb Smirnoff | PROTO '{' optnl proto_list '}' { $$ = $4; } 28373b3a8eb9SGleb Smirnoff ; 28383b3a8eb9SGleb Smirnoff 28393b3a8eb9SGleb Smirnoff proto_list : proto_item optnl { $$ = $1; } 28403b3a8eb9SGleb Smirnoff | proto_list comma proto_item optnl { 28413b3a8eb9SGleb Smirnoff $1->tail->next = $3; 28423b3a8eb9SGleb Smirnoff $1->tail = $3; 28433b3a8eb9SGleb Smirnoff $$ = $1; 28443b3a8eb9SGleb Smirnoff } 28453b3a8eb9SGleb Smirnoff ; 28463b3a8eb9SGleb Smirnoff 28473b3a8eb9SGleb Smirnoff proto_item : protoval { 28483b3a8eb9SGleb Smirnoff u_int8_t pr; 28493b3a8eb9SGleb Smirnoff 28503b3a8eb9SGleb Smirnoff pr = (u_int8_t)$1; 28513b3a8eb9SGleb Smirnoff if (pr == 0) { 28523b3a8eb9SGleb Smirnoff yyerror("proto 0 cannot be used"); 28533b3a8eb9SGleb Smirnoff YYERROR; 28543b3a8eb9SGleb Smirnoff } 28553b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_proto)); 28563b3a8eb9SGleb Smirnoff if ($$ == NULL) 28573b3a8eb9SGleb Smirnoff err(1, "proto_item: calloc"); 28583b3a8eb9SGleb Smirnoff $$->proto = pr; 28593b3a8eb9SGleb Smirnoff $$->next = NULL; 28603b3a8eb9SGleb Smirnoff $$->tail = $$; 28613b3a8eb9SGleb Smirnoff } 28623b3a8eb9SGleb Smirnoff ; 28633b3a8eb9SGleb Smirnoff 28643b3a8eb9SGleb Smirnoff protoval : STRING { 28653b3a8eb9SGleb Smirnoff struct protoent *p; 28663b3a8eb9SGleb Smirnoff 28673b3a8eb9SGleb Smirnoff p = getprotobyname($1); 28683b3a8eb9SGleb Smirnoff if (p == NULL) { 28693b3a8eb9SGleb Smirnoff yyerror("unknown protocol %s", $1); 28703b3a8eb9SGleb Smirnoff free($1); 28713b3a8eb9SGleb Smirnoff YYERROR; 28723b3a8eb9SGleb Smirnoff } 28733b3a8eb9SGleb Smirnoff $$ = p->p_proto; 28743b3a8eb9SGleb Smirnoff free($1); 28753b3a8eb9SGleb Smirnoff } 28763b3a8eb9SGleb Smirnoff | NUMBER { 28773b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 > 255) { 28783b3a8eb9SGleb Smirnoff yyerror("protocol outside range"); 28793b3a8eb9SGleb Smirnoff YYERROR; 28803b3a8eb9SGleb Smirnoff } 28813b3a8eb9SGleb Smirnoff } 28823b3a8eb9SGleb Smirnoff ; 28833b3a8eb9SGleb Smirnoff 28843b3a8eb9SGleb Smirnoff fromto : ALL { 28853b3a8eb9SGleb Smirnoff $$.src.host = NULL; 28863b3a8eb9SGleb Smirnoff $$.src.port = NULL; 28873b3a8eb9SGleb Smirnoff $$.dst.host = NULL; 28883b3a8eb9SGleb Smirnoff $$.dst.port = NULL; 28893b3a8eb9SGleb Smirnoff $$.src_os = NULL; 28903b3a8eb9SGleb Smirnoff } 28913b3a8eb9SGleb Smirnoff | from os to { 28923b3a8eb9SGleb Smirnoff $$.src = $1; 28933b3a8eb9SGleb Smirnoff $$.src_os = $2; 28943b3a8eb9SGleb Smirnoff $$.dst = $3; 28953b3a8eb9SGleb Smirnoff } 28963b3a8eb9SGleb Smirnoff ; 28973b3a8eb9SGleb Smirnoff 28983b3a8eb9SGleb Smirnoff os : /* empty */ { $$ = NULL; } 28993b3a8eb9SGleb Smirnoff | OS xos { $$ = $2; } 29003b3a8eb9SGleb Smirnoff | OS '{' optnl os_list '}' { $$ = $4; } 29013b3a8eb9SGleb Smirnoff ; 29023b3a8eb9SGleb Smirnoff 29033b3a8eb9SGleb Smirnoff xos : STRING { 29043b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_os)); 29053b3a8eb9SGleb Smirnoff if ($$ == NULL) 29063b3a8eb9SGleb Smirnoff err(1, "os: calloc"); 29073b3a8eb9SGleb Smirnoff $$->os = $1; 29083b3a8eb9SGleb Smirnoff $$->tail = $$; 29093b3a8eb9SGleb Smirnoff } 29103b3a8eb9SGleb Smirnoff ; 29113b3a8eb9SGleb Smirnoff 29123b3a8eb9SGleb Smirnoff os_list : xos optnl { $$ = $1; } 29133b3a8eb9SGleb Smirnoff | os_list comma xos optnl { 29143b3a8eb9SGleb Smirnoff $1->tail->next = $3; 29153b3a8eb9SGleb Smirnoff $1->tail = $3; 29163b3a8eb9SGleb Smirnoff $$ = $1; 29173b3a8eb9SGleb Smirnoff } 29183b3a8eb9SGleb Smirnoff ; 29193b3a8eb9SGleb Smirnoff 29203b3a8eb9SGleb Smirnoff from : /* empty */ { 29213b3a8eb9SGleb Smirnoff $$.host = NULL; 29223b3a8eb9SGleb Smirnoff $$.port = NULL; 29233b3a8eb9SGleb Smirnoff } 29243b3a8eb9SGleb Smirnoff | FROM ipportspec { 29253b3a8eb9SGleb Smirnoff $$ = $2; 29263b3a8eb9SGleb Smirnoff } 29273b3a8eb9SGleb Smirnoff ; 29283b3a8eb9SGleb Smirnoff 29293b3a8eb9SGleb Smirnoff to : /* empty */ { 29303b3a8eb9SGleb Smirnoff $$.host = NULL; 29313b3a8eb9SGleb Smirnoff $$.port = NULL; 29323b3a8eb9SGleb Smirnoff } 29333b3a8eb9SGleb Smirnoff | TO ipportspec { 29343b3a8eb9SGleb Smirnoff if (disallow_urpf_failed($2.host, "\"urpf-failed\" is " 29353b3a8eb9SGleb Smirnoff "not permitted in a destination address")) 29363b3a8eb9SGleb Smirnoff YYERROR; 29373b3a8eb9SGleb Smirnoff $$ = $2; 29383b3a8eb9SGleb Smirnoff } 29393b3a8eb9SGleb Smirnoff ; 29403b3a8eb9SGleb Smirnoff 29413b3a8eb9SGleb Smirnoff ipportspec : ipspec { 29423b3a8eb9SGleb Smirnoff $$.host = $1; 29433b3a8eb9SGleb Smirnoff $$.port = NULL; 29443b3a8eb9SGleb Smirnoff } 29453b3a8eb9SGleb Smirnoff | ipspec PORT portspec { 29463b3a8eb9SGleb Smirnoff $$.host = $1; 29473b3a8eb9SGleb Smirnoff $$.port = $3; 29483b3a8eb9SGleb Smirnoff } 29493b3a8eb9SGleb Smirnoff | PORT portspec { 29503b3a8eb9SGleb Smirnoff $$.host = NULL; 29513b3a8eb9SGleb Smirnoff $$.port = $2; 29523b3a8eb9SGleb Smirnoff } 29533b3a8eb9SGleb Smirnoff ; 29543b3a8eb9SGleb Smirnoff 29553b3a8eb9SGleb Smirnoff optnl : '\n' optnl 29563b3a8eb9SGleb Smirnoff | 29573b3a8eb9SGleb Smirnoff ; 29583b3a8eb9SGleb Smirnoff 29593b3a8eb9SGleb Smirnoff ipspec : ANY { $$ = NULL; } 29603b3a8eb9SGleb Smirnoff | xhost { $$ = $1; } 29613b3a8eb9SGleb Smirnoff | '{' optnl host_list '}' { $$ = $3; } 29623b3a8eb9SGleb Smirnoff ; 29633b3a8eb9SGleb Smirnoff 29643b3a8eb9SGleb Smirnoff toipspec : TO ipspec { $$ = $2; } 29653b3a8eb9SGleb Smirnoff | /* empty */ { $$ = NULL; } 29663b3a8eb9SGleb Smirnoff ; 29673b3a8eb9SGleb Smirnoff 29683b3a8eb9SGleb Smirnoff host_list : ipspec optnl { $$ = $1; } 29693b3a8eb9SGleb Smirnoff | host_list comma ipspec optnl { 29703b3a8eb9SGleb Smirnoff if ($3 == NULL) 29713b3a8eb9SGleb Smirnoff $$ = $1; 29723b3a8eb9SGleb Smirnoff else if ($1 == NULL) 29733b3a8eb9SGleb Smirnoff $$ = $3; 29743b3a8eb9SGleb Smirnoff else { 29753b3a8eb9SGleb Smirnoff $1->tail->next = $3; 29763b3a8eb9SGleb Smirnoff $1->tail = $3->tail; 29773b3a8eb9SGleb Smirnoff $$ = $1; 29783b3a8eb9SGleb Smirnoff } 29793b3a8eb9SGleb Smirnoff } 29803b3a8eb9SGleb Smirnoff ; 29813b3a8eb9SGleb Smirnoff 29823b3a8eb9SGleb Smirnoff xhost : not host { 29833b3a8eb9SGleb Smirnoff struct node_host *n; 29843b3a8eb9SGleb Smirnoff 29853b3a8eb9SGleb Smirnoff for (n = $2; n != NULL; n = n->next) 29863b3a8eb9SGleb Smirnoff n->not = $1; 29873b3a8eb9SGleb Smirnoff $$ = $2; 29883b3a8eb9SGleb Smirnoff } 29893b3a8eb9SGleb Smirnoff | not NOROUTE { 29903b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_host)); 29913b3a8eb9SGleb Smirnoff if ($$ == NULL) 29923b3a8eb9SGleb Smirnoff err(1, "xhost: calloc"); 29933b3a8eb9SGleb Smirnoff $$->addr.type = PF_ADDR_NOROUTE; 29943b3a8eb9SGleb Smirnoff $$->next = NULL; 29953b3a8eb9SGleb Smirnoff $$->not = $1; 29963b3a8eb9SGleb Smirnoff $$->tail = $$; 29973b3a8eb9SGleb Smirnoff } 29983b3a8eb9SGleb Smirnoff | not URPFFAILED { 29993b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_host)); 30003b3a8eb9SGleb Smirnoff if ($$ == NULL) 30013b3a8eb9SGleb Smirnoff err(1, "xhost: calloc"); 30023b3a8eb9SGleb Smirnoff $$->addr.type = PF_ADDR_URPFFAILED; 30033b3a8eb9SGleb Smirnoff $$->next = NULL; 30043b3a8eb9SGleb Smirnoff $$->not = $1; 30053b3a8eb9SGleb Smirnoff $$->tail = $$; 30063b3a8eb9SGleb Smirnoff } 30073b3a8eb9SGleb Smirnoff ; 30083b3a8eb9SGleb Smirnoff 30093b3a8eb9SGleb Smirnoff host : STRING { 30103b3a8eb9SGleb Smirnoff if (($$ = host($1)) == NULL) { 30113b3a8eb9SGleb Smirnoff /* error. "any" is handled elsewhere */ 30123b3a8eb9SGleb Smirnoff free($1); 30133b3a8eb9SGleb Smirnoff yyerror("could not parse host specification"); 30143b3a8eb9SGleb Smirnoff YYERROR; 30153b3a8eb9SGleb Smirnoff } 30163b3a8eb9SGleb Smirnoff free($1); 30173b3a8eb9SGleb Smirnoff 30183b3a8eb9SGleb Smirnoff } 30193b3a8eb9SGleb Smirnoff | STRING '-' STRING { 30203b3a8eb9SGleb Smirnoff struct node_host *b, *e; 30213b3a8eb9SGleb Smirnoff 30223b3a8eb9SGleb Smirnoff if ((b = host($1)) == NULL || (e = host($3)) == NULL) { 30233b3a8eb9SGleb Smirnoff free($1); 30243b3a8eb9SGleb Smirnoff free($3); 30253b3a8eb9SGleb Smirnoff yyerror("could not parse host specification"); 30263b3a8eb9SGleb Smirnoff YYERROR; 30273b3a8eb9SGleb Smirnoff } 30283b3a8eb9SGleb Smirnoff if (b->af != e->af || 30293b3a8eb9SGleb Smirnoff b->addr.type != PF_ADDR_ADDRMASK || 30303b3a8eb9SGleb Smirnoff e->addr.type != PF_ADDR_ADDRMASK || 30313b3a8eb9SGleb Smirnoff unmask(&b->addr.v.a.mask, b->af) != 30323b3a8eb9SGleb Smirnoff (b->af == AF_INET ? 32 : 128) || 30333b3a8eb9SGleb Smirnoff unmask(&e->addr.v.a.mask, e->af) != 30343b3a8eb9SGleb Smirnoff (e->af == AF_INET ? 32 : 128) || 30353b3a8eb9SGleb Smirnoff b->next != NULL || b->not || 30363b3a8eb9SGleb Smirnoff e->next != NULL || e->not) { 30373b3a8eb9SGleb Smirnoff free(b); 30383b3a8eb9SGleb Smirnoff free(e); 30393b3a8eb9SGleb Smirnoff free($1); 30403b3a8eb9SGleb Smirnoff free($3); 30413b3a8eb9SGleb Smirnoff yyerror("invalid address range"); 30423b3a8eb9SGleb Smirnoff YYERROR; 30433b3a8eb9SGleb Smirnoff } 30443b3a8eb9SGleb Smirnoff memcpy(&b->addr.v.a.mask, &e->addr.v.a.addr, 30453b3a8eb9SGleb Smirnoff sizeof(b->addr.v.a.mask)); 30463b3a8eb9SGleb Smirnoff b->addr.type = PF_ADDR_RANGE; 30473b3a8eb9SGleb Smirnoff $$ = b; 30483b3a8eb9SGleb Smirnoff free(e); 30493b3a8eb9SGleb Smirnoff free($1); 30503b3a8eb9SGleb Smirnoff free($3); 30513b3a8eb9SGleb Smirnoff } 30523b3a8eb9SGleb Smirnoff | STRING '/' NUMBER { 30533b3a8eb9SGleb Smirnoff char *buf; 30543b3a8eb9SGleb Smirnoff 30553b3a8eb9SGleb Smirnoff if (asprintf(&buf, "%s/%lld", $1, (long long)$3) == -1) 30563b3a8eb9SGleb Smirnoff err(1, "host: asprintf"); 30573b3a8eb9SGleb Smirnoff free($1); 30583b3a8eb9SGleb Smirnoff if (($$ = host(buf)) == NULL) { 30593b3a8eb9SGleb Smirnoff /* error. "any" is handled elsewhere */ 30603b3a8eb9SGleb Smirnoff free(buf); 30613b3a8eb9SGleb Smirnoff yyerror("could not parse host specification"); 30623b3a8eb9SGleb Smirnoff YYERROR; 30633b3a8eb9SGleb Smirnoff } 30643b3a8eb9SGleb Smirnoff free(buf); 30653b3a8eb9SGleb Smirnoff } 30663b3a8eb9SGleb Smirnoff | NUMBER '/' NUMBER { 30673b3a8eb9SGleb Smirnoff char *buf; 30683b3a8eb9SGleb Smirnoff 30693b3a8eb9SGleb Smirnoff /* ie. for 10/8 parsing */ 30703b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 30713b3a8eb9SGleb Smirnoff if (asprintf(&buf, "%lld/%lld", (long long)$1, (long long)$3) == -1) 30723b3a8eb9SGleb Smirnoff #else 30733b3a8eb9SGleb Smirnoff if (asprintf(&buf, "%lld/%lld", $1, $3) == -1) 30743b3a8eb9SGleb Smirnoff #endif 30753b3a8eb9SGleb Smirnoff err(1, "host: asprintf"); 30763b3a8eb9SGleb Smirnoff if (($$ = host(buf)) == NULL) { 30773b3a8eb9SGleb Smirnoff /* error. "any" is handled elsewhere */ 30783b3a8eb9SGleb Smirnoff free(buf); 30793b3a8eb9SGleb Smirnoff yyerror("could not parse host specification"); 30803b3a8eb9SGleb Smirnoff YYERROR; 30813b3a8eb9SGleb Smirnoff } 30823b3a8eb9SGleb Smirnoff free(buf); 30833b3a8eb9SGleb Smirnoff } 30843b3a8eb9SGleb Smirnoff | dynaddr 30853b3a8eb9SGleb Smirnoff | dynaddr '/' NUMBER { 30863b3a8eb9SGleb Smirnoff struct node_host *n; 30873b3a8eb9SGleb Smirnoff 30883b3a8eb9SGleb Smirnoff if ($3 < 0 || $3 > 128) { 30893b3a8eb9SGleb Smirnoff yyerror("bit number too big"); 30903b3a8eb9SGleb Smirnoff YYERROR; 30913b3a8eb9SGleb Smirnoff } 30923b3a8eb9SGleb Smirnoff $$ = $1; 30933b3a8eb9SGleb Smirnoff for (n = $1; n != NULL; n = n->next) 30943b3a8eb9SGleb Smirnoff set_ipmask(n, $3); 30953b3a8eb9SGleb Smirnoff } 30963b3a8eb9SGleb Smirnoff | '<' STRING '>' { 30973b3a8eb9SGleb Smirnoff if (strlen($2) >= PF_TABLE_NAME_SIZE) { 30983b3a8eb9SGleb Smirnoff yyerror("table name '%s' too long", $2); 30993b3a8eb9SGleb Smirnoff free($2); 31003b3a8eb9SGleb Smirnoff YYERROR; 31013b3a8eb9SGleb Smirnoff } 31023b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_host)); 31033b3a8eb9SGleb Smirnoff if ($$ == NULL) 31043b3a8eb9SGleb Smirnoff err(1, "host: calloc"); 31053b3a8eb9SGleb Smirnoff $$->addr.type = PF_ADDR_TABLE; 31063b3a8eb9SGleb Smirnoff if (strlcpy($$->addr.v.tblname, $2, 31073b3a8eb9SGleb Smirnoff sizeof($$->addr.v.tblname)) >= 31083b3a8eb9SGleb Smirnoff sizeof($$->addr.v.tblname)) 31093b3a8eb9SGleb Smirnoff errx(1, "host: strlcpy"); 31103b3a8eb9SGleb Smirnoff free($2); 31113b3a8eb9SGleb Smirnoff $$->next = NULL; 31123b3a8eb9SGleb Smirnoff $$->tail = $$; 31133b3a8eb9SGleb Smirnoff } 31143b3a8eb9SGleb Smirnoff ; 31153b3a8eb9SGleb Smirnoff 31163b3a8eb9SGleb Smirnoff number : NUMBER 31173b3a8eb9SGleb Smirnoff | STRING { 31183b3a8eb9SGleb Smirnoff u_long ulval; 31193b3a8eb9SGleb Smirnoff 31203b3a8eb9SGleb Smirnoff if (atoul($1, &ulval) == -1) { 31213b3a8eb9SGleb Smirnoff yyerror("%s is not a number", $1); 31223b3a8eb9SGleb Smirnoff free($1); 31233b3a8eb9SGleb Smirnoff YYERROR; 31243b3a8eb9SGleb Smirnoff } else 31253b3a8eb9SGleb Smirnoff $$ = ulval; 31263b3a8eb9SGleb Smirnoff free($1); 31273b3a8eb9SGleb Smirnoff } 31283b3a8eb9SGleb Smirnoff ; 31293b3a8eb9SGleb Smirnoff 31303b3a8eb9SGleb Smirnoff dynaddr : '(' STRING ')' { 31313b3a8eb9SGleb Smirnoff int flags = 0; 31323b3a8eb9SGleb Smirnoff char *p, *op; 31333b3a8eb9SGleb Smirnoff 31343b3a8eb9SGleb Smirnoff op = $2; 31353b3a8eb9SGleb Smirnoff if (!isalpha(op[0])) { 31363b3a8eb9SGleb Smirnoff yyerror("invalid interface name '%s'", op); 31373b3a8eb9SGleb Smirnoff free(op); 31383b3a8eb9SGleb Smirnoff YYERROR; 31393b3a8eb9SGleb Smirnoff } 31403b3a8eb9SGleb Smirnoff while ((p = strrchr($2, ':')) != NULL) { 31413b3a8eb9SGleb Smirnoff if (!strcmp(p+1, "network")) 31423b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_NETWORK; 31433b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "broadcast")) 31443b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_BROADCAST; 31453b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "peer")) 31463b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_PEER; 31473b3a8eb9SGleb Smirnoff else if (!strcmp(p+1, "0")) 31483b3a8eb9SGleb Smirnoff flags |= PFI_AFLAG_NOALIAS; 31493b3a8eb9SGleb Smirnoff else { 31503b3a8eb9SGleb Smirnoff yyerror("interface %s has bad modifier", 31513b3a8eb9SGleb Smirnoff $2); 31523b3a8eb9SGleb Smirnoff free(op); 31533b3a8eb9SGleb Smirnoff YYERROR; 31543b3a8eb9SGleb Smirnoff } 31553b3a8eb9SGleb Smirnoff *p = '\0'; 31563b3a8eb9SGleb Smirnoff } 31573b3a8eb9SGleb Smirnoff if (flags & (flags - 1) & PFI_AFLAG_MODEMASK) { 31583b3a8eb9SGleb Smirnoff free(op); 31593b3a8eb9SGleb Smirnoff yyerror("illegal combination of " 31603b3a8eb9SGleb Smirnoff "interface modifiers"); 31613b3a8eb9SGleb Smirnoff YYERROR; 31623b3a8eb9SGleb Smirnoff } 31633b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_host)); 31643b3a8eb9SGleb Smirnoff if ($$ == NULL) 31653b3a8eb9SGleb Smirnoff err(1, "address: calloc"); 31663b3a8eb9SGleb Smirnoff $$->af = 0; 31673b3a8eb9SGleb Smirnoff set_ipmask($$, 128); 31683b3a8eb9SGleb Smirnoff $$->addr.type = PF_ADDR_DYNIFTL; 31693b3a8eb9SGleb Smirnoff $$->addr.iflags = flags; 31703b3a8eb9SGleb Smirnoff if (strlcpy($$->addr.v.ifname, $2, 31713b3a8eb9SGleb Smirnoff sizeof($$->addr.v.ifname)) >= 31723b3a8eb9SGleb Smirnoff sizeof($$->addr.v.ifname)) { 31733b3a8eb9SGleb Smirnoff free(op); 31743b3a8eb9SGleb Smirnoff free($$); 31753b3a8eb9SGleb Smirnoff yyerror("interface name too long"); 31763b3a8eb9SGleb Smirnoff YYERROR; 31773b3a8eb9SGleb Smirnoff } 31783b3a8eb9SGleb Smirnoff free(op); 31793b3a8eb9SGleb Smirnoff $$->next = NULL; 31803b3a8eb9SGleb Smirnoff $$->tail = $$; 31813b3a8eb9SGleb Smirnoff } 31823b3a8eb9SGleb Smirnoff ; 31833b3a8eb9SGleb Smirnoff 31843b3a8eb9SGleb Smirnoff portspec : port_item { $$ = $1; } 31853b3a8eb9SGleb Smirnoff | '{' optnl port_list '}' { $$ = $3; } 31863b3a8eb9SGleb Smirnoff ; 31873b3a8eb9SGleb Smirnoff 31883b3a8eb9SGleb Smirnoff port_list : port_item optnl { $$ = $1; } 31893b3a8eb9SGleb Smirnoff | port_list comma port_item optnl { 31903b3a8eb9SGleb Smirnoff $1->tail->next = $3; 31913b3a8eb9SGleb Smirnoff $1->tail = $3; 31923b3a8eb9SGleb Smirnoff $$ = $1; 31933b3a8eb9SGleb Smirnoff } 31943b3a8eb9SGleb Smirnoff ; 31953b3a8eb9SGleb Smirnoff 31963b3a8eb9SGleb Smirnoff port_item : portrange { 31973b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_port)); 31983b3a8eb9SGleb Smirnoff if ($$ == NULL) 31993b3a8eb9SGleb Smirnoff err(1, "port_item: calloc"); 32003b3a8eb9SGleb Smirnoff $$->port[0] = $1.a; 32013b3a8eb9SGleb Smirnoff $$->port[1] = $1.b; 32023b3a8eb9SGleb Smirnoff if ($1.t) 32033b3a8eb9SGleb Smirnoff $$->op = PF_OP_RRG; 32043b3a8eb9SGleb Smirnoff else 32053b3a8eb9SGleb Smirnoff $$->op = PF_OP_EQ; 32063b3a8eb9SGleb Smirnoff $$->next = NULL; 32073b3a8eb9SGleb Smirnoff $$->tail = $$; 32083b3a8eb9SGleb Smirnoff } 32093b3a8eb9SGleb Smirnoff | unaryop portrange { 32103b3a8eb9SGleb Smirnoff if ($2.t) { 32113b3a8eb9SGleb Smirnoff yyerror("':' cannot be used with an other " 32123b3a8eb9SGleb Smirnoff "port operator"); 32133b3a8eb9SGleb Smirnoff YYERROR; 32143b3a8eb9SGleb Smirnoff } 32153b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_port)); 32163b3a8eb9SGleb Smirnoff if ($$ == NULL) 32173b3a8eb9SGleb Smirnoff err(1, "port_item: calloc"); 32183b3a8eb9SGleb Smirnoff $$->port[0] = $2.a; 32193b3a8eb9SGleb Smirnoff $$->port[1] = $2.b; 32203b3a8eb9SGleb Smirnoff $$->op = $1; 32213b3a8eb9SGleb Smirnoff $$->next = NULL; 32223b3a8eb9SGleb Smirnoff $$->tail = $$; 32233b3a8eb9SGleb Smirnoff } 32243b3a8eb9SGleb Smirnoff | portrange PORTBINARY portrange { 32253b3a8eb9SGleb Smirnoff if ($1.t || $3.t) { 32263b3a8eb9SGleb Smirnoff yyerror("':' cannot be used with an other " 32273b3a8eb9SGleb Smirnoff "port operator"); 32283b3a8eb9SGleb Smirnoff YYERROR; 32293b3a8eb9SGleb Smirnoff } 32303b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_port)); 32313b3a8eb9SGleb Smirnoff if ($$ == NULL) 32323b3a8eb9SGleb Smirnoff err(1, "port_item: calloc"); 32333b3a8eb9SGleb Smirnoff $$->port[0] = $1.a; 32343b3a8eb9SGleb Smirnoff $$->port[1] = $3.a; 32353b3a8eb9SGleb Smirnoff $$->op = $2; 32363b3a8eb9SGleb Smirnoff $$->next = NULL; 32373b3a8eb9SGleb Smirnoff $$->tail = $$; 32383b3a8eb9SGleb Smirnoff } 32393b3a8eb9SGleb Smirnoff ; 32403b3a8eb9SGleb Smirnoff 32413b3a8eb9SGleb Smirnoff portplain : numberstring { 32423b3a8eb9SGleb Smirnoff if (parseport($1, &$$, 0) == -1) { 32433b3a8eb9SGleb Smirnoff free($1); 32443b3a8eb9SGleb Smirnoff YYERROR; 32453b3a8eb9SGleb Smirnoff } 32463b3a8eb9SGleb Smirnoff free($1); 32473b3a8eb9SGleb Smirnoff } 32483b3a8eb9SGleb Smirnoff ; 32493b3a8eb9SGleb Smirnoff 32503b3a8eb9SGleb Smirnoff portrange : numberstring { 32513b3a8eb9SGleb Smirnoff if (parseport($1, &$$, PPORT_RANGE) == -1) { 32523b3a8eb9SGleb Smirnoff free($1); 32533b3a8eb9SGleb Smirnoff YYERROR; 32543b3a8eb9SGleb Smirnoff } 32553b3a8eb9SGleb Smirnoff free($1); 32563b3a8eb9SGleb Smirnoff } 32573b3a8eb9SGleb Smirnoff ; 32583b3a8eb9SGleb Smirnoff 32593b3a8eb9SGleb Smirnoff uids : uid_item { $$ = $1; } 32603b3a8eb9SGleb Smirnoff | '{' optnl uid_list '}' { $$ = $3; } 32613b3a8eb9SGleb Smirnoff ; 32623b3a8eb9SGleb Smirnoff 32633b3a8eb9SGleb Smirnoff uid_list : uid_item optnl { $$ = $1; } 32643b3a8eb9SGleb Smirnoff | uid_list comma uid_item optnl { 32653b3a8eb9SGleb Smirnoff $1->tail->next = $3; 32663b3a8eb9SGleb Smirnoff $1->tail = $3; 32673b3a8eb9SGleb Smirnoff $$ = $1; 32683b3a8eb9SGleb Smirnoff } 32693b3a8eb9SGleb Smirnoff ; 32703b3a8eb9SGleb Smirnoff 32713b3a8eb9SGleb Smirnoff uid_item : uid { 32723b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_uid)); 32733b3a8eb9SGleb Smirnoff if ($$ == NULL) 32743b3a8eb9SGleb Smirnoff err(1, "uid_item: calloc"); 32753b3a8eb9SGleb Smirnoff $$->uid[0] = $1; 32763b3a8eb9SGleb Smirnoff $$->uid[1] = $1; 32773b3a8eb9SGleb Smirnoff $$->op = PF_OP_EQ; 32783b3a8eb9SGleb Smirnoff $$->next = NULL; 32793b3a8eb9SGleb Smirnoff $$->tail = $$; 32803b3a8eb9SGleb Smirnoff } 32813b3a8eb9SGleb Smirnoff | unaryop uid { 32823b3a8eb9SGleb Smirnoff if ($2 == UID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 32833b3a8eb9SGleb Smirnoff yyerror("user unknown requires operator = or " 32843b3a8eb9SGleb Smirnoff "!="); 32853b3a8eb9SGleb Smirnoff YYERROR; 32863b3a8eb9SGleb Smirnoff } 32873b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_uid)); 32883b3a8eb9SGleb Smirnoff if ($$ == NULL) 32893b3a8eb9SGleb Smirnoff err(1, "uid_item: calloc"); 32903b3a8eb9SGleb Smirnoff $$->uid[0] = $2; 32913b3a8eb9SGleb Smirnoff $$->uid[1] = $2; 32923b3a8eb9SGleb Smirnoff $$->op = $1; 32933b3a8eb9SGleb Smirnoff $$->next = NULL; 32943b3a8eb9SGleb Smirnoff $$->tail = $$; 32953b3a8eb9SGleb Smirnoff } 32963b3a8eb9SGleb Smirnoff | uid PORTBINARY uid { 32973b3a8eb9SGleb Smirnoff if ($1 == UID_MAX || $3 == UID_MAX) { 32983b3a8eb9SGleb Smirnoff yyerror("user unknown requires operator = or " 32993b3a8eb9SGleb Smirnoff "!="); 33003b3a8eb9SGleb Smirnoff YYERROR; 33013b3a8eb9SGleb Smirnoff } 33023b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_uid)); 33033b3a8eb9SGleb Smirnoff if ($$ == NULL) 33043b3a8eb9SGleb Smirnoff err(1, "uid_item: calloc"); 33053b3a8eb9SGleb Smirnoff $$->uid[0] = $1; 33063b3a8eb9SGleb Smirnoff $$->uid[1] = $3; 33073b3a8eb9SGleb Smirnoff $$->op = $2; 33083b3a8eb9SGleb Smirnoff $$->next = NULL; 33093b3a8eb9SGleb Smirnoff $$->tail = $$; 33103b3a8eb9SGleb Smirnoff } 33113b3a8eb9SGleb Smirnoff ; 33123b3a8eb9SGleb Smirnoff 33133b3a8eb9SGleb Smirnoff uid : STRING { 33143b3a8eb9SGleb Smirnoff if (!strcmp($1, "unknown")) 33153b3a8eb9SGleb Smirnoff $$ = UID_MAX; 33163b3a8eb9SGleb Smirnoff else { 33173b3a8eb9SGleb Smirnoff struct passwd *pw; 33183b3a8eb9SGleb Smirnoff 33193b3a8eb9SGleb Smirnoff if ((pw = getpwnam($1)) == NULL) { 33203b3a8eb9SGleb Smirnoff yyerror("unknown user %s", $1); 33213b3a8eb9SGleb Smirnoff free($1); 33223b3a8eb9SGleb Smirnoff YYERROR; 33233b3a8eb9SGleb Smirnoff } 33243b3a8eb9SGleb Smirnoff $$ = pw->pw_uid; 33253b3a8eb9SGleb Smirnoff } 33263b3a8eb9SGleb Smirnoff free($1); 33273b3a8eb9SGleb Smirnoff } 33283b3a8eb9SGleb Smirnoff | NUMBER { 33293b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 >= UID_MAX) { 33303b3a8eb9SGleb Smirnoff yyerror("illegal uid value %lu", $1); 33313b3a8eb9SGleb Smirnoff YYERROR; 33323b3a8eb9SGleb Smirnoff } 33333b3a8eb9SGleb Smirnoff $$ = $1; 33343b3a8eb9SGleb Smirnoff } 33353b3a8eb9SGleb Smirnoff ; 33363b3a8eb9SGleb Smirnoff 33373b3a8eb9SGleb Smirnoff gids : gid_item { $$ = $1; } 33383b3a8eb9SGleb Smirnoff | '{' optnl gid_list '}' { $$ = $3; } 33393b3a8eb9SGleb Smirnoff ; 33403b3a8eb9SGleb Smirnoff 33413b3a8eb9SGleb Smirnoff gid_list : gid_item optnl { $$ = $1; } 33423b3a8eb9SGleb Smirnoff | gid_list comma gid_item optnl { 33433b3a8eb9SGleb Smirnoff $1->tail->next = $3; 33443b3a8eb9SGleb Smirnoff $1->tail = $3; 33453b3a8eb9SGleb Smirnoff $$ = $1; 33463b3a8eb9SGleb Smirnoff } 33473b3a8eb9SGleb Smirnoff ; 33483b3a8eb9SGleb Smirnoff 33493b3a8eb9SGleb Smirnoff gid_item : gid { 33503b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_gid)); 33513b3a8eb9SGleb Smirnoff if ($$ == NULL) 33523b3a8eb9SGleb Smirnoff err(1, "gid_item: calloc"); 33533b3a8eb9SGleb Smirnoff $$->gid[0] = $1; 33543b3a8eb9SGleb Smirnoff $$->gid[1] = $1; 33553b3a8eb9SGleb Smirnoff $$->op = PF_OP_EQ; 33563b3a8eb9SGleb Smirnoff $$->next = NULL; 33573b3a8eb9SGleb Smirnoff $$->tail = $$; 33583b3a8eb9SGleb Smirnoff } 33593b3a8eb9SGleb Smirnoff | unaryop gid { 33603b3a8eb9SGleb Smirnoff if ($2 == GID_MAX && $1 != PF_OP_EQ && $1 != PF_OP_NE) { 33613b3a8eb9SGleb Smirnoff yyerror("group unknown requires operator = or " 33623b3a8eb9SGleb Smirnoff "!="); 33633b3a8eb9SGleb Smirnoff YYERROR; 33643b3a8eb9SGleb Smirnoff } 33653b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_gid)); 33663b3a8eb9SGleb Smirnoff if ($$ == NULL) 33673b3a8eb9SGleb Smirnoff err(1, "gid_item: calloc"); 33683b3a8eb9SGleb Smirnoff $$->gid[0] = $2; 33693b3a8eb9SGleb Smirnoff $$->gid[1] = $2; 33703b3a8eb9SGleb Smirnoff $$->op = $1; 33713b3a8eb9SGleb Smirnoff $$->next = NULL; 33723b3a8eb9SGleb Smirnoff $$->tail = $$; 33733b3a8eb9SGleb Smirnoff } 33743b3a8eb9SGleb Smirnoff | gid PORTBINARY gid { 33753b3a8eb9SGleb Smirnoff if ($1 == GID_MAX || $3 == GID_MAX) { 33763b3a8eb9SGleb Smirnoff yyerror("group unknown requires operator = or " 33773b3a8eb9SGleb Smirnoff "!="); 33783b3a8eb9SGleb Smirnoff YYERROR; 33793b3a8eb9SGleb Smirnoff } 33803b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_gid)); 33813b3a8eb9SGleb Smirnoff if ($$ == NULL) 33823b3a8eb9SGleb Smirnoff err(1, "gid_item: calloc"); 33833b3a8eb9SGleb Smirnoff $$->gid[0] = $1; 33843b3a8eb9SGleb Smirnoff $$->gid[1] = $3; 33853b3a8eb9SGleb Smirnoff $$->op = $2; 33863b3a8eb9SGleb Smirnoff $$->next = NULL; 33873b3a8eb9SGleb Smirnoff $$->tail = $$; 33883b3a8eb9SGleb Smirnoff } 33893b3a8eb9SGleb Smirnoff ; 33903b3a8eb9SGleb Smirnoff 33913b3a8eb9SGleb Smirnoff gid : STRING { 33923b3a8eb9SGleb Smirnoff if (!strcmp($1, "unknown")) 33933b3a8eb9SGleb Smirnoff $$ = GID_MAX; 33943b3a8eb9SGleb Smirnoff else { 33953b3a8eb9SGleb Smirnoff struct group *grp; 33963b3a8eb9SGleb Smirnoff 33973b3a8eb9SGleb Smirnoff if ((grp = getgrnam($1)) == NULL) { 33983b3a8eb9SGleb Smirnoff yyerror("unknown group %s", $1); 33993b3a8eb9SGleb Smirnoff free($1); 34003b3a8eb9SGleb Smirnoff YYERROR; 34013b3a8eb9SGleb Smirnoff } 34023b3a8eb9SGleb Smirnoff $$ = grp->gr_gid; 34033b3a8eb9SGleb Smirnoff } 34043b3a8eb9SGleb Smirnoff free($1); 34053b3a8eb9SGleb Smirnoff } 34063b3a8eb9SGleb Smirnoff | NUMBER { 34073b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 >= GID_MAX) { 34083b3a8eb9SGleb Smirnoff yyerror("illegal gid value %lu", $1); 34093b3a8eb9SGleb Smirnoff YYERROR; 34103b3a8eb9SGleb Smirnoff } 34113b3a8eb9SGleb Smirnoff $$ = $1; 34123b3a8eb9SGleb Smirnoff } 34133b3a8eb9SGleb Smirnoff ; 34143b3a8eb9SGleb Smirnoff 34153b3a8eb9SGleb Smirnoff flag : STRING { 34163b3a8eb9SGleb Smirnoff int f; 34173b3a8eb9SGleb Smirnoff 34183b3a8eb9SGleb Smirnoff if ((f = parse_flags($1)) < 0) { 34193b3a8eb9SGleb Smirnoff yyerror("bad flags %s", $1); 34203b3a8eb9SGleb Smirnoff free($1); 34213b3a8eb9SGleb Smirnoff YYERROR; 34223b3a8eb9SGleb Smirnoff } 34233b3a8eb9SGleb Smirnoff free($1); 34243b3a8eb9SGleb Smirnoff $$.b1 = f; 34253b3a8eb9SGleb Smirnoff } 34263b3a8eb9SGleb Smirnoff ; 34273b3a8eb9SGleb Smirnoff 34283b3a8eb9SGleb Smirnoff flags : FLAGS flag '/' flag { $$.b1 = $2.b1; $$.b2 = $4.b1; } 34293b3a8eb9SGleb Smirnoff | FLAGS '/' flag { $$.b1 = 0; $$.b2 = $3.b1; } 34303b3a8eb9SGleb Smirnoff | FLAGS ANY { $$.b1 = 0; $$.b2 = 0; } 34313b3a8eb9SGleb Smirnoff ; 34323b3a8eb9SGleb Smirnoff 34333b3a8eb9SGleb Smirnoff icmpspec : ICMPTYPE icmp_item { $$ = $2; } 34343b3a8eb9SGleb Smirnoff | ICMPTYPE '{' optnl icmp_list '}' { $$ = $4; } 34353b3a8eb9SGleb Smirnoff | ICMP6TYPE icmp6_item { $$ = $2; } 34363b3a8eb9SGleb Smirnoff | ICMP6TYPE '{' optnl icmp6_list '}' { $$ = $4; } 34373b3a8eb9SGleb Smirnoff ; 34383b3a8eb9SGleb Smirnoff 34393b3a8eb9SGleb Smirnoff icmp_list : icmp_item optnl { $$ = $1; } 34403b3a8eb9SGleb Smirnoff | icmp_list comma icmp_item optnl { 34413b3a8eb9SGleb Smirnoff $1->tail->next = $3; 34423b3a8eb9SGleb Smirnoff $1->tail = $3; 34433b3a8eb9SGleb Smirnoff $$ = $1; 34443b3a8eb9SGleb Smirnoff } 34453b3a8eb9SGleb Smirnoff ; 34463b3a8eb9SGleb Smirnoff 34473b3a8eb9SGleb Smirnoff icmp6_list : icmp6_item optnl { $$ = $1; } 34483b3a8eb9SGleb Smirnoff | icmp6_list comma icmp6_item optnl { 34493b3a8eb9SGleb Smirnoff $1->tail->next = $3; 34503b3a8eb9SGleb Smirnoff $1->tail = $3; 34513b3a8eb9SGleb Smirnoff $$ = $1; 34523b3a8eb9SGleb Smirnoff } 34533b3a8eb9SGleb Smirnoff ; 34543b3a8eb9SGleb Smirnoff 34553b3a8eb9SGleb Smirnoff icmp_item : icmptype { 34563b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_icmp)); 34573b3a8eb9SGleb Smirnoff if ($$ == NULL) 34583b3a8eb9SGleb Smirnoff err(1, "icmp_item: calloc"); 34593b3a8eb9SGleb Smirnoff $$->type = $1; 34603b3a8eb9SGleb Smirnoff $$->code = 0; 34613b3a8eb9SGleb Smirnoff $$->proto = IPPROTO_ICMP; 34623b3a8eb9SGleb Smirnoff $$->next = NULL; 34633b3a8eb9SGleb Smirnoff $$->tail = $$; 34643b3a8eb9SGleb Smirnoff } 34653b3a8eb9SGleb Smirnoff | icmptype CODE STRING { 34663b3a8eb9SGleb Smirnoff const struct icmpcodeent *p; 34673b3a8eb9SGleb Smirnoff 34683b3a8eb9SGleb Smirnoff if ((p = geticmpcodebyname($1-1, $3, AF_INET)) == NULL) { 34693b3a8eb9SGleb Smirnoff yyerror("unknown icmp-code %s", $3); 34703b3a8eb9SGleb Smirnoff free($3); 34713b3a8eb9SGleb Smirnoff YYERROR; 34723b3a8eb9SGleb Smirnoff } 34733b3a8eb9SGleb Smirnoff 34743b3a8eb9SGleb Smirnoff free($3); 34753b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_icmp)); 34763b3a8eb9SGleb Smirnoff if ($$ == NULL) 34773b3a8eb9SGleb Smirnoff err(1, "icmp_item: calloc"); 34783b3a8eb9SGleb Smirnoff $$->type = $1; 34793b3a8eb9SGleb Smirnoff $$->code = p->code + 1; 34803b3a8eb9SGleb Smirnoff $$->proto = IPPROTO_ICMP; 34813b3a8eb9SGleb Smirnoff $$->next = NULL; 34823b3a8eb9SGleb Smirnoff $$->tail = $$; 34833b3a8eb9SGleb Smirnoff } 34843b3a8eb9SGleb Smirnoff | icmptype CODE NUMBER { 34853b3a8eb9SGleb Smirnoff if ($3 < 0 || $3 > 255) { 34863b3a8eb9SGleb Smirnoff yyerror("illegal icmp-code %lu", $3); 34873b3a8eb9SGleb Smirnoff YYERROR; 34883b3a8eb9SGleb Smirnoff } 34893b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_icmp)); 34903b3a8eb9SGleb Smirnoff if ($$ == NULL) 34913b3a8eb9SGleb Smirnoff err(1, "icmp_item: calloc"); 34923b3a8eb9SGleb Smirnoff $$->type = $1; 34933b3a8eb9SGleb Smirnoff $$->code = $3 + 1; 34943b3a8eb9SGleb Smirnoff $$->proto = IPPROTO_ICMP; 34953b3a8eb9SGleb Smirnoff $$->next = NULL; 34963b3a8eb9SGleb Smirnoff $$->tail = $$; 34973b3a8eb9SGleb Smirnoff } 34983b3a8eb9SGleb Smirnoff ; 34993b3a8eb9SGleb Smirnoff 35003b3a8eb9SGleb Smirnoff icmp6_item : icmp6type { 35013b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_icmp)); 35023b3a8eb9SGleb Smirnoff if ($$ == NULL) 35033b3a8eb9SGleb Smirnoff err(1, "icmp_item: calloc"); 35043b3a8eb9SGleb Smirnoff $$->type = $1; 35053b3a8eb9SGleb Smirnoff $$->code = 0; 35063b3a8eb9SGleb Smirnoff $$->proto = IPPROTO_ICMPV6; 35073b3a8eb9SGleb Smirnoff $$->next = NULL; 35083b3a8eb9SGleb Smirnoff $$->tail = $$; 35093b3a8eb9SGleb Smirnoff } 35103b3a8eb9SGleb Smirnoff | icmp6type CODE STRING { 35113b3a8eb9SGleb Smirnoff const struct icmpcodeent *p; 35123b3a8eb9SGleb Smirnoff 35133b3a8eb9SGleb Smirnoff if ((p = geticmpcodebyname($1-1, $3, AF_INET6)) == NULL) { 35143b3a8eb9SGleb Smirnoff yyerror("unknown icmp6-code %s", $3); 35153b3a8eb9SGleb Smirnoff free($3); 35163b3a8eb9SGleb Smirnoff YYERROR; 35173b3a8eb9SGleb Smirnoff } 35183b3a8eb9SGleb Smirnoff free($3); 35193b3a8eb9SGleb Smirnoff 35203b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_icmp)); 35213b3a8eb9SGleb Smirnoff if ($$ == NULL) 35223b3a8eb9SGleb Smirnoff err(1, "icmp_item: calloc"); 35233b3a8eb9SGleb Smirnoff $$->type = $1; 35243b3a8eb9SGleb Smirnoff $$->code = p->code + 1; 35253b3a8eb9SGleb Smirnoff $$->proto = IPPROTO_ICMPV6; 35263b3a8eb9SGleb Smirnoff $$->next = NULL; 35273b3a8eb9SGleb Smirnoff $$->tail = $$; 35283b3a8eb9SGleb Smirnoff } 35293b3a8eb9SGleb Smirnoff | icmp6type CODE NUMBER { 35303b3a8eb9SGleb Smirnoff if ($3 < 0 || $3 > 255) { 35313b3a8eb9SGleb Smirnoff yyerror("illegal icmp-code %lu", $3); 35323b3a8eb9SGleb Smirnoff YYERROR; 35333b3a8eb9SGleb Smirnoff } 35343b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_icmp)); 35353b3a8eb9SGleb Smirnoff if ($$ == NULL) 35363b3a8eb9SGleb Smirnoff err(1, "icmp_item: calloc"); 35373b3a8eb9SGleb Smirnoff $$->type = $1; 35383b3a8eb9SGleb Smirnoff $$->code = $3 + 1; 35393b3a8eb9SGleb Smirnoff $$->proto = IPPROTO_ICMPV6; 35403b3a8eb9SGleb Smirnoff $$->next = NULL; 35413b3a8eb9SGleb Smirnoff $$->tail = $$; 35423b3a8eb9SGleb Smirnoff } 35433b3a8eb9SGleb Smirnoff ; 35443b3a8eb9SGleb Smirnoff 35453b3a8eb9SGleb Smirnoff icmptype : STRING { 35463b3a8eb9SGleb Smirnoff const struct icmptypeent *p; 35473b3a8eb9SGleb Smirnoff 35483b3a8eb9SGleb Smirnoff if ((p = geticmptypebyname($1, AF_INET)) == NULL) { 35493b3a8eb9SGleb Smirnoff yyerror("unknown icmp-type %s", $1); 35503b3a8eb9SGleb Smirnoff free($1); 35513b3a8eb9SGleb Smirnoff YYERROR; 35523b3a8eb9SGleb Smirnoff } 35533b3a8eb9SGleb Smirnoff $$ = p->type + 1; 35543b3a8eb9SGleb Smirnoff free($1); 35553b3a8eb9SGleb Smirnoff } 35563b3a8eb9SGleb Smirnoff | NUMBER { 35573b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 > 255) { 35583b3a8eb9SGleb Smirnoff yyerror("illegal icmp-type %lu", $1); 35593b3a8eb9SGleb Smirnoff YYERROR; 35603b3a8eb9SGleb Smirnoff } 35613b3a8eb9SGleb Smirnoff $$ = $1 + 1; 35623b3a8eb9SGleb Smirnoff } 35633b3a8eb9SGleb Smirnoff ; 35643b3a8eb9SGleb Smirnoff 35653b3a8eb9SGleb Smirnoff icmp6type : STRING { 35663b3a8eb9SGleb Smirnoff const struct icmptypeent *p; 35673b3a8eb9SGleb Smirnoff 35683b3a8eb9SGleb Smirnoff if ((p = geticmptypebyname($1, AF_INET6)) == 35693b3a8eb9SGleb Smirnoff NULL) { 35703b3a8eb9SGleb Smirnoff yyerror("unknown icmp6-type %s", $1); 35713b3a8eb9SGleb Smirnoff free($1); 35723b3a8eb9SGleb Smirnoff YYERROR; 35733b3a8eb9SGleb Smirnoff } 35743b3a8eb9SGleb Smirnoff $$ = p->type + 1; 35753b3a8eb9SGleb Smirnoff free($1); 35763b3a8eb9SGleb Smirnoff } 35773b3a8eb9SGleb Smirnoff | NUMBER { 35783b3a8eb9SGleb Smirnoff if ($1 < 0 || $1 > 255) { 35793b3a8eb9SGleb Smirnoff yyerror("illegal icmp6-type %lu", $1); 35803b3a8eb9SGleb Smirnoff YYERROR; 35813b3a8eb9SGleb Smirnoff } 35823b3a8eb9SGleb Smirnoff $$ = $1 + 1; 35833b3a8eb9SGleb Smirnoff } 35843b3a8eb9SGleb Smirnoff ; 35853b3a8eb9SGleb Smirnoff 35863b3a8eb9SGleb Smirnoff tos : STRING { 35873b3a8eb9SGleb Smirnoff if (!strcmp($1, "lowdelay")) 35883b3a8eb9SGleb Smirnoff $$ = IPTOS_LOWDELAY; 35893b3a8eb9SGleb Smirnoff else if (!strcmp($1, "throughput")) 35903b3a8eb9SGleb Smirnoff $$ = IPTOS_THROUGHPUT; 35913b3a8eb9SGleb Smirnoff else if (!strcmp($1, "reliability")) 35923b3a8eb9SGleb Smirnoff $$ = IPTOS_RELIABILITY; 35933b3a8eb9SGleb Smirnoff else if ($1[0] == '0' && $1[1] == 'x') 35943b3a8eb9SGleb Smirnoff $$ = strtoul($1, NULL, 16); 35953b3a8eb9SGleb Smirnoff else 35960cd7a91aSKristof Provost $$ = 256; /* flag bad argument */ 35970cd7a91aSKristof Provost if ($$ < 0 || $$ > 255) { 35983b3a8eb9SGleb Smirnoff yyerror("illegal tos value %s", $1); 35993b3a8eb9SGleb Smirnoff free($1); 36003b3a8eb9SGleb Smirnoff YYERROR; 36013b3a8eb9SGleb Smirnoff } 36023b3a8eb9SGleb Smirnoff free($1); 36033b3a8eb9SGleb Smirnoff } 36043b3a8eb9SGleb Smirnoff | NUMBER { 36053b3a8eb9SGleb Smirnoff $$ = $1; 36060cd7a91aSKristof Provost if ($$ < 0 || $$ > 255) { 36073b3a8eb9SGleb Smirnoff yyerror("illegal tos value %s", $1); 36083b3a8eb9SGleb Smirnoff YYERROR; 36093b3a8eb9SGleb Smirnoff } 36103b3a8eb9SGleb Smirnoff } 36113b3a8eb9SGleb Smirnoff ; 36123b3a8eb9SGleb Smirnoff 36133b3a8eb9SGleb Smirnoff sourcetrack : SOURCETRACK { $$ = PF_SRCTRACK; } 36143b3a8eb9SGleb Smirnoff | SOURCETRACK GLOBAL { $$ = PF_SRCTRACK_GLOBAL; } 36153b3a8eb9SGleb Smirnoff | SOURCETRACK RULE { $$ = PF_SRCTRACK_RULE; } 36163b3a8eb9SGleb Smirnoff ; 36173b3a8eb9SGleb Smirnoff 36183b3a8eb9SGleb Smirnoff statelock : IFBOUND { 36193b3a8eb9SGleb Smirnoff $$ = PFRULE_IFBOUND; 36203b3a8eb9SGleb Smirnoff } 36213b3a8eb9SGleb Smirnoff | FLOATING { 36223b3a8eb9SGleb Smirnoff $$ = 0; 36233b3a8eb9SGleb Smirnoff } 36243b3a8eb9SGleb Smirnoff ; 36253b3a8eb9SGleb Smirnoff 36263b3a8eb9SGleb Smirnoff keep : NO STATE { 36273b3a8eb9SGleb Smirnoff $$.action = 0; 36283b3a8eb9SGleb Smirnoff $$.options = NULL; 36293b3a8eb9SGleb Smirnoff } 36303b3a8eb9SGleb Smirnoff | KEEP STATE state_opt_spec { 36313b3a8eb9SGleb Smirnoff $$.action = PF_STATE_NORMAL; 36323b3a8eb9SGleb Smirnoff $$.options = $3; 36333b3a8eb9SGleb Smirnoff } 36343b3a8eb9SGleb Smirnoff | MODULATE STATE state_opt_spec { 36353b3a8eb9SGleb Smirnoff $$.action = PF_STATE_MODULATE; 36363b3a8eb9SGleb Smirnoff $$.options = $3; 36373b3a8eb9SGleb Smirnoff } 36383b3a8eb9SGleb Smirnoff | SYNPROXY STATE state_opt_spec { 36393b3a8eb9SGleb Smirnoff $$.action = PF_STATE_SYNPROXY; 36403b3a8eb9SGleb Smirnoff $$.options = $3; 36413b3a8eb9SGleb Smirnoff } 36423b3a8eb9SGleb Smirnoff ; 36433b3a8eb9SGleb Smirnoff 36443b3a8eb9SGleb Smirnoff flush : /* empty */ { $$ = 0; } 36453b3a8eb9SGleb Smirnoff | FLUSH { $$ = PF_FLUSH; } 36463b3a8eb9SGleb Smirnoff | FLUSH GLOBAL { 36473b3a8eb9SGleb Smirnoff $$ = PF_FLUSH | PF_FLUSH_GLOBAL; 36483b3a8eb9SGleb Smirnoff } 36493b3a8eb9SGleb Smirnoff ; 36503b3a8eb9SGleb Smirnoff 36513b3a8eb9SGleb Smirnoff state_opt_spec : '(' state_opt_list ')' { $$ = $2; } 36523b3a8eb9SGleb Smirnoff | /* empty */ { $$ = NULL; } 36533b3a8eb9SGleb Smirnoff ; 36543b3a8eb9SGleb Smirnoff 36553b3a8eb9SGleb Smirnoff state_opt_list : state_opt_item { $$ = $1; } 36563b3a8eb9SGleb Smirnoff | state_opt_list comma state_opt_item { 36573b3a8eb9SGleb Smirnoff $1->tail->next = $3; 36583b3a8eb9SGleb Smirnoff $1->tail = $3; 36593b3a8eb9SGleb Smirnoff $$ = $1; 36603b3a8eb9SGleb Smirnoff } 36613b3a8eb9SGleb Smirnoff ; 36623b3a8eb9SGleb Smirnoff 36633b3a8eb9SGleb Smirnoff state_opt_item : MAXIMUM NUMBER { 36643b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX) { 36653b3a8eb9SGleb Smirnoff yyerror("only positive values permitted"); 36663b3a8eb9SGleb Smirnoff YYERROR; 36673b3a8eb9SGleb Smirnoff } 36683b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt)); 36693b3a8eb9SGleb Smirnoff if ($$ == NULL) 36703b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc"); 36713b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_MAX; 36723b3a8eb9SGleb Smirnoff $$->data.max_states = $2; 36733b3a8eb9SGleb Smirnoff $$->next = NULL; 36743b3a8eb9SGleb Smirnoff $$->tail = $$; 36753b3a8eb9SGleb Smirnoff } 36763b3a8eb9SGleb Smirnoff | NOSYNC { 36773b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt)); 36783b3a8eb9SGleb Smirnoff if ($$ == NULL) 36793b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc"); 36803b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_NOSYNC; 36813b3a8eb9SGleb Smirnoff $$->next = NULL; 36823b3a8eb9SGleb Smirnoff $$->tail = $$; 36833b3a8eb9SGleb Smirnoff } 36843b3a8eb9SGleb Smirnoff | MAXSRCSTATES NUMBER { 36853b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX) { 36863b3a8eb9SGleb Smirnoff yyerror("only positive values permitted"); 36873b3a8eb9SGleb Smirnoff YYERROR; 36883b3a8eb9SGleb Smirnoff } 36893b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt)); 36903b3a8eb9SGleb Smirnoff if ($$ == NULL) 36913b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc"); 36923b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_MAX_SRC_STATES; 36933b3a8eb9SGleb Smirnoff $$->data.max_src_states = $2; 36943b3a8eb9SGleb Smirnoff $$->next = NULL; 36953b3a8eb9SGleb Smirnoff $$->tail = $$; 36963b3a8eb9SGleb Smirnoff } 36973b3a8eb9SGleb Smirnoff | MAXSRCCONN NUMBER { 36983b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX) { 36993b3a8eb9SGleb Smirnoff yyerror("only positive values permitted"); 37003b3a8eb9SGleb Smirnoff YYERROR; 37013b3a8eb9SGleb Smirnoff } 37023b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt)); 37033b3a8eb9SGleb Smirnoff if ($$ == NULL) 37043b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc"); 37053b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_MAX_SRC_CONN; 37063b3a8eb9SGleb Smirnoff $$->data.max_src_conn = $2; 37073b3a8eb9SGleb Smirnoff $$->next = NULL; 37083b3a8eb9SGleb Smirnoff $$->tail = $$; 37093b3a8eb9SGleb Smirnoff } 37103b3a8eb9SGleb Smirnoff | MAXSRCCONNRATE NUMBER '/' NUMBER { 37113b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX || 37123b3a8eb9SGleb Smirnoff $4 < 0 || $4 > UINT_MAX) { 37133b3a8eb9SGleb Smirnoff yyerror("only positive values permitted"); 37143b3a8eb9SGleb Smirnoff YYERROR; 37153b3a8eb9SGleb Smirnoff } 37163b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt)); 37173b3a8eb9SGleb Smirnoff if ($$ == NULL) 37183b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc"); 37193b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_MAX_SRC_CONN_RATE; 37203b3a8eb9SGleb Smirnoff $$->data.max_src_conn_rate.limit = $2; 37213b3a8eb9SGleb Smirnoff $$->data.max_src_conn_rate.seconds = $4; 37223b3a8eb9SGleb Smirnoff $$->next = NULL; 37233b3a8eb9SGleb Smirnoff $$->tail = $$; 37243b3a8eb9SGleb Smirnoff } 37253b3a8eb9SGleb Smirnoff | OVERLOAD '<' STRING '>' flush { 37263b3a8eb9SGleb Smirnoff if (strlen($3) >= PF_TABLE_NAME_SIZE) { 37273b3a8eb9SGleb Smirnoff yyerror("table name '%s' too long", $3); 37283b3a8eb9SGleb Smirnoff free($3); 37293b3a8eb9SGleb Smirnoff YYERROR; 37303b3a8eb9SGleb Smirnoff } 37313b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt)); 37323b3a8eb9SGleb Smirnoff if ($$ == NULL) 37333b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc"); 37343b3a8eb9SGleb Smirnoff if (strlcpy($$->data.overload.tblname, $3, 37353b3a8eb9SGleb Smirnoff PF_TABLE_NAME_SIZE) >= PF_TABLE_NAME_SIZE) 37363b3a8eb9SGleb Smirnoff errx(1, "state_opt_item: strlcpy"); 37373b3a8eb9SGleb Smirnoff free($3); 37383b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_OVERLOAD; 37393b3a8eb9SGleb Smirnoff $$->data.overload.flush = $5; 37403b3a8eb9SGleb Smirnoff $$->next = NULL; 37413b3a8eb9SGleb Smirnoff $$->tail = $$; 37423b3a8eb9SGleb Smirnoff } 37433b3a8eb9SGleb Smirnoff | MAXSRCNODES NUMBER { 37443b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX) { 37453b3a8eb9SGleb Smirnoff yyerror("only positive values permitted"); 37463b3a8eb9SGleb Smirnoff YYERROR; 37473b3a8eb9SGleb Smirnoff } 37483b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt)); 37493b3a8eb9SGleb Smirnoff if ($$ == NULL) 37503b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc"); 37513b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_MAX_SRC_NODES; 37523b3a8eb9SGleb Smirnoff $$->data.max_src_nodes = $2; 37533b3a8eb9SGleb Smirnoff $$->next = NULL; 37543b3a8eb9SGleb Smirnoff $$->tail = $$; 37553b3a8eb9SGleb Smirnoff } 37563b3a8eb9SGleb Smirnoff | sourcetrack { 37573b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt)); 37583b3a8eb9SGleb Smirnoff if ($$ == NULL) 37593b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc"); 37603b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_SRCTRACK; 37613b3a8eb9SGleb Smirnoff $$->data.src_track = $1; 37623b3a8eb9SGleb Smirnoff $$->next = NULL; 37633b3a8eb9SGleb Smirnoff $$->tail = $$; 37643b3a8eb9SGleb Smirnoff } 37653b3a8eb9SGleb Smirnoff | statelock { 37663b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt)); 37673b3a8eb9SGleb Smirnoff if ($$ == NULL) 37683b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc"); 37693b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_STATELOCK; 37703b3a8eb9SGleb Smirnoff $$->data.statelock = $1; 37713b3a8eb9SGleb Smirnoff $$->next = NULL; 37723b3a8eb9SGleb Smirnoff $$->tail = $$; 37733b3a8eb9SGleb Smirnoff } 37743b3a8eb9SGleb Smirnoff | SLOPPY { 37753b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt)); 37763b3a8eb9SGleb Smirnoff if ($$ == NULL) 37773b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc"); 37783b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_SLOPPY; 37793b3a8eb9SGleb Smirnoff $$->next = NULL; 37803b3a8eb9SGleb Smirnoff $$->tail = $$; 37813b3a8eb9SGleb Smirnoff } 37823b3a8eb9SGleb Smirnoff | STRING NUMBER { 37833b3a8eb9SGleb Smirnoff int i; 37843b3a8eb9SGleb Smirnoff 37853b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX) { 37863b3a8eb9SGleb Smirnoff yyerror("only positive values permitted"); 37873b3a8eb9SGleb Smirnoff YYERROR; 37883b3a8eb9SGleb Smirnoff } 37893b3a8eb9SGleb Smirnoff for (i = 0; pf_timeouts[i].name && 37903b3a8eb9SGleb Smirnoff strcmp(pf_timeouts[i].name, $1); ++i) 37913b3a8eb9SGleb Smirnoff ; /* nothing */ 37923b3a8eb9SGleb Smirnoff if (!pf_timeouts[i].name) { 37933b3a8eb9SGleb Smirnoff yyerror("illegal timeout name %s", $1); 37943b3a8eb9SGleb Smirnoff free($1); 37953b3a8eb9SGleb Smirnoff YYERROR; 37963b3a8eb9SGleb Smirnoff } 37973b3a8eb9SGleb Smirnoff if (strchr(pf_timeouts[i].name, '.') == NULL) { 37983b3a8eb9SGleb Smirnoff yyerror("illegal state timeout %s", $1); 37993b3a8eb9SGleb Smirnoff free($1); 38003b3a8eb9SGleb Smirnoff YYERROR; 38013b3a8eb9SGleb Smirnoff } 38023b3a8eb9SGleb Smirnoff free($1); 38033b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_state_opt)); 38043b3a8eb9SGleb Smirnoff if ($$ == NULL) 38053b3a8eb9SGleb Smirnoff err(1, "state_opt_item: calloc"); 38063b3a8eb9SGleb Smirnoff $$->type = PF_STATE_OPT_TIMEOUT; 38073b3a8eb9SGleb Smirnoff $$->data.timeout.number = pf_timeouts[i].timeout; 38083b3a8eb9SGleb Smirnoff $$->data.timeout.seconds = $2; 38093b3a8eb9SGleb Smirnoff $$->next = NULL; 38103b3a8eb9SGleb Smirnoff $$->tail = $$; 38113b3a8eb9SGleb Smirnoff } 38123b3a8eb9SGleb Smirnoff ; 38133b3a8eb9SGleb Smirnoff 38143b3a8eb9SGleb Smirnoff label : LABEL STRING { 38153b3a8eb9SGleb Smirnoff $$ = $2; 38163b3a8eb9SGleb Smirnoff } 38173b3a8eb9SGleb Smirnoff ; 38183b3a8eb9SGleb Smirnoff 38193b3a8eb9SGleb Smirnoff qname : QUEUE STRING { 38203b3a8eb9SGleb Smirnoff $$.qname = $2; 38213b3a8eb9SGleb Smirnoff $$.pqname = NULL; 38223b3a8eb9SGleb Smirnoff } 38233b3a8eb9SGleb Smirnoff | QUEUE '(' STRING ')' { 38243b3a8eb9SGleb Smirnoff $$.qname = $3; 38253b3a8eb9SGleb Smirnoff $$.pqname = NULL; 38263b3a8eb9SGleb Smirnoff } 38273b3a8eb9SGleb Smirnoff | QUEUE '(' STRING comma STRING ')' { 38283b3a8eb9SGleb Smirnoff $$.qname = $3; 38293b3a8eb9SGleb Smirnoff $$.pqname = $5; 38303b3a8eb9SGleb Smirnoff } 38313b3a8eb9SGleb Smirnoff ; 38323b3a8eb9SGleb Smirnoff 38333b3a8eb9SGleb Smirnoff no : /* empty */ { $$ = 0; } 38343b3a8eb9SGleb Smirnoff | NO { $$ = 1; } 38353b3a8eb9SGleb Smirnoff ; 38363b3a8eb9SGleb Smirnoff 38373b3a8eb9SGleb Smirnoff portstar : numberstring { 38383b3a8eb9SGleb Smirnoff if (parseport($1, &$$, PPORT_RANGE|PPORT_STAR) == -1) { 38393b3a8eb9SGleb Smirnoff free($1); 38403b3a8eb9SGleb Smirnoff YYERROR; 38413b3a8eb9SGleb Smirnoff } 38423b3a8eb9SGleb Smirnoff free($1); 38433b3a8eb9SGleb Smirnoff } 38443b3a8eb9SGleb Smirnoff ; 38453b3a8eb9SGleb Smirnoff 38463b3a8eb9SGleb Smirnoff redirspec : host { $$ = $1; } 38473b3a8eb9SGleb Smirnoff | '{' optnl redir_host_list '}' { $$ = $3; } 38483b3a8eb9SGleb Smirnoff ; 38493b3a8eb9SGleb Smirnoff 38503b3a8eb9SGleb Smirnoff redir_host_list : host optnl { $$ = $1; } 38513b3a8eb9SGleb Smirnoff | redir_host_list comma host optnl { 38523b3a8eb9SGleb Smirnoff $1->tail->next = $3; 38533b3a8eb9SGleb Smirnoff $1->tail = $3->tail; 38543b3a8eb9SGleb Smirnoff $$ = $1; 38553b3a8eb9SGleb Smirnoff } 38563b3a8eb9SGleb Smirnoff ; 38573b3a8eb9SGleb Smirnoff 38583b3a8eb9SGleb Smirnoff redirpool : /* empty */ { $$ = NULL; } 38593b3a8eb9SGleb Smirnoff | ARROW redirspec { 38603b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct redirection)); 38613b3a8eb9SGleb Smirnoff if ($$ == NULL) 38623b3a8eb9SGleb Smirnoff err(1, "redirection: calloc"); 38633b3a8eb9SGleb Smirnoff $$->host = $2; 38643b3a8eb9SGleb Smirnoff $$->rport.a = $$->rport.b = $$->rport.t = 0; 38653b3a8eb9SGleb Smirnoff } 38663b3a8eb9SGleb Smirnoff | ARROW redirspec PORT portstar { 38673b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct redirection)); 38683b3a8eb9SGleb Smirnoff if ($$ == NULL) 38693b3a8eb9SGleb Smirnoff err(1, "redirection: calloc"); 38703b3a8eb9SGleb Smirnoff $$->host = $2; 38713b3a8eb9SGleb Smirnoff $$->rport = $4; 38723b3a8eb9SGleb Smirnoff } 38733b3a8eb9SGleb Smirnoff ; 38743b3a8eb9SGleb Smirnoff 38753b3a8eb9SGleb Smirnoff hashkey : /* empty */ 38763b3a8eb9SGleb Smirnoff { 38773b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct pf_poolhashkey)); 38783b3a8eb9SGleb Smirnoff if ($$ == NULL) 38793b3a8eb9SGleb Smirnoff err(1, "hashkey: calloc"); 38803b3a8eb9SGleb Smirnoff $$->key32[0] = arc4random(); 38813b3a8eb9SGleb Smirnoff $$->key32[1] = arc4random(); 38823b3a8eb9SGleb Smirnoff $$->key32[2] = arc4random(); 38833b3a8eb9SGleb Smirnoff $$->key32[3] = arc4random(); 38843b3a8eb9SGleb Smirnoff } 38853b3a8eb9SGleb Smirnoff | string 38863b3a8eb9SGleb Smirnoff { 38873b3a8eb9SGleb Smirnoff if (!strncmp($1, "0x", 2)) { 38883b3a8eb9SGleb Smirnoff if (strlen($1) != 34) { 38893b3a8eb9SGleb Smirnoff free($1); 38903b3a8eb9SGleb Smirnoff yyerror("hex key must be 128 bits " 38913b3a8eb9SGleb Smirnoff "(32 hex digits) long"); 38923b3a8eb9SGleb Smirnoff YYERROR; 38933b3a8eb9SGleb Smirnoff } 38943b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct pf_poolhashkey)); 38953b3a8eb9SGleb Smirnoff if ($$ == NULL) 38963b3a8eb9SGleb Smirnoff err(1, "hashkey: calloc"); 38973b3a8eb9SGleb Smirnoff 38983b3a8eb9SGleb Smirnoff if (sscanf($1, "0x%8x%8x%8x%8x", 38993b3a8eb9SGleb Smirnoff &$$->key32[0], &$$->key32[1], 39003b3a8eb9SGleb Smirnoff &$$->key32[2], &$$->key32[3]) != 4) { 39013b3a8eb9SGleb Smirnoff free($$); 39023b3a8eb9SGleb Smirnoff free($1); 39033b3a8eb9SGleb Smirnoff yyerror("invalid hex key"); 39043b3a8eb9SGleb Smirnoff YYERROR; 39053b3a8eb9SGleb Smirnoff } 39063b3a8eb9SGleb Smirnoff } else { 39073b3a8eb9SGleb Smirnoff MD5_CTX context; 39083b3a8eb9SGleb Smirnoff 39093b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct pf_poolhashkey)); 39103b3a8eb9SGleb Smirnoff if ($$ == NULL) 39113b3a8eb9SGleb Smirnoff err(1, "hashkey: calloc"); 39123b3a8eb9SGleb Smirnoff MD5Init(&context); 39133b3a8eb9SGleb Smirnoff MD5Update(&context, (unsigned char *)$1, 39143b3a8eb9SGleb Smirnoff strlen($1)); 39153b3a8eb9SGleb Smirnoff MD5Final((unsigned char *)$$, &context); 39163b3a8eb9SGleb Smirnoff HTONL($$->key32[0]); 39173b3a8eb9SGleb Smirnoff HTONL($$->key32[1]); 39183b3a8eb9SGleb Smirnoff HTONL($$->key32[2]); 39193b3a8eb9SGleb Smirnoff HTONL($$->key32[3]); 39203b3a8eb9SGleb Smirnoff } 39213b3a8eb9SGleb Smirnoff free($1); 39223b3a8eb9SGleb Smirnoff } 39233b3a8eb9SGleb Smirnoff ; 39243b3a8eb9SGleb Smirnoff 39253b3a8eb9SGleb Smirnoff pool_opts : { bzero(&pool_opts, sizeof pool_opts); } 39263b3a8eb9SGleb Smirnoff pool_opts_l 39273b3a8eb9SGleb Smirnoff { $$ = pool_opts; } 39283b3a8eb9SGleb Smirnoff | /* empty */ { 39293b3a8eb9SGleb Smirnoff bzero(&pool_opts, sizeof pool_opts); 39303b3a8eb9SGleb Smirnoff $$ = pool_opts; 39313b3a8eb9SGleb Smirnoff } 39323b3a8eb9SGleb Smirnoff ; 39333b3a8eb9SGleb Smirnoff 39343b3a8eb9SGleb Smirnoff pool_opts_l : pool_opts_l pool_opt 39353b3a8eb9SGleb Smirnoff | pool_opt 39363b3a8eb9SGleb Smirnoff ; 39373b3a8eb9SGleb Smirnoff 39383b3a8eb9SGleb Smirnoff pool_opt : BITMASK { 39393b3a8eb9SGleb Smirnoff if (pool_opts.type) { 39403b3a8eb9SGleb Smirnoff yyerror("pool type cannot be redefined"); 39413b3a8eb9SGleb Smirnoff YYERROR; 39423b3a8eb9SGleb Smirnoff } 39433b3a8eb9SGleb Smirnoff pool_opts.type = PF_POOL_BITMASK; 39443b3a8eb9SGleb Smirnoff } 39453b3a8eb9SGleb Smirnoff | RANDOM { 39463b3a8eb9SGleb Smirnoff if (pool_opts.type) { 39473b3a8eb9SGleb Smirnoff yyerror("pool type cannot be redefined"); 39483b3a8eb9SGleb Smirnoff YYERROR; 39493b3a8eb9SGleb Smirnoff } 39503b3a8eb9SGleb Smirnoff pool_opts.type = PF_POOL_RANDOM; 39513b3a8eb9SGleb Smirnoff } 39523b3a8eb9SGleb Smirnoff | SOURCEHASH hashkey { 39533b3a8eb9SGleb Smirnoff if (pool_opts.type) { 39543b3a8eb9SGleb Smirnoff yyerror("pool type cannot be redefined"); 39553b3a8eb9SGleb Smirnoff YYERROR; 39563b3a8eb9SGleb Smirnoff } 39573b3a8eb9SGleb Smirnoff pool_opts.type = PF_POOL_SRCHASH; 39583b3a8eb9SGleb Smirnoff pool_opts.key = $2; 39593b3a8eb9SGleb Smirnoff } 39603b3a8eb9SGleb Smirnoff | ROUNDROBIN { 39613b3a8eb9SGleb Smirnoff if (pool_opts.type) { 39623b3a8eb9SGleb Smirnoff yyerror("pool type cannot be redefined"); 39633b3a8eb9SGleb Smirnoff YYERROR; 39643b3a8eb9SGleb Smirnoff } 39653b3a8eb9SGleb Smirnoff pool_opts.type = PF_POOL_ROUNDROBIN; 39663b3a8eb9SGleb Smirnoff } 39673b3a8eb9SGleb Smirnoff | STATICPORT { 39683b3a8eb9SGleb Smirnoff if (pool_opts.staticport) { 39693b3a8eb9SGleb Smirnoff yyerror("static-port cannot be redefined"); 39703b3a8eb9SGleb Smirnoff YYERROR; 39713b3a8eb9SGleb Smirnoff } 39723b3a8eb9SGleb Smirnoff pool_opts.staticport = 1; 39733b3a8eb9SGleb Smirnoff } 39743b3a8eb9SGleb Smirnoff | STICKYADDRESS { 39753b3a8eb9SGleb Smirnoff if (filter_opts.marker & POM_STICKYADDRESS) { 39763b3a8eb9SGleb Smirnoff yyerror("sticky-address cannot be redefined"); 39773b3a8eb9SGleb Smirnoff YYERROR; 39783b3a8eb9SGleb Smirnoff } 39793b3a8eb9SGleb Smirnoff pool_opts.marker |= POM_STICKYADDRESS; 39803b3a8eb9SGleb Smirnoff pool_opts.opts |= PF_POOL_STICKYADDR; 39813b3a8eb9SGleb Smirnoff } 39823b3a8eb9SGleb Smirnoff ; 39833b3a8eb9SGleb Smirnoff 39843b3a8eb9SGleb Smirnoff redirection : /* empty */ { $$ = NULL; } 39853b3a8eb9SGleb Smirnoff | ARROW host { 39863b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct redirection)); 39873b3a8eb9SGleb Smirnoff if ($$ == NULL) 39883b3a8eb9SGleb Smirnoff err(1, "redirection: calloc"); 39893b3a8eb9SGleb Smirnoff $$->host = $2; 39903b3a8eb9SGleb Smirnoff $$->rport.a = $$->rport.b = $$->rport.t = 0; 39913b3a8eb9SGleb Smirnoff } 39923b3a8eb9SGleb Smirnoff | ARROW host PORT portstar { 39933b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct redirection)); 39943b3a8eb9SGleb Smirnoff if ($$ == NULL) 39953b3a8eb9SGleb Smirnoff err(1, "redirection: calloc"); 39963b3a8eb9SGleb Smirnoff $$->host = $2; 39973b3a8eb9SGleb Smirnoff $$->rport = $4; 39983b3a8eb9SGleb Smirnoff } 39993b3a8eb9SGleb Smirnoff ; 40003b3a8eb9SGleb Smirnoff 40013b3a8eb9SGleb Smirnoff natpasslog : /* empty */ { $$.b1 = $$.b2 = 0; $$.w2 = 0; } 40023b3a8eb9SGleb Smirnoff | PASS { $$.b1 = 1; $$.b2 = 0; $$.w2 = 0; } 40033b3a8eb9SGleb Smirnoff | PASS log { $$.b1 = 1; $$.b2 = $2.log; $$.w2 = $2.logif; } 40043b3a8eb9SGleb Smirnoff | log { $$.b1 = 0; $$.b2 = $1.log; $$.w2 = $1.logif; } 40053b3a8eb9SGleb Smirnoff ; 40063b3a8eb9SGleb Smirnoff 40073b3a8eb9SGleb Smirnoff nataction : no NAT natpasslog { 40083b3a8eb9SGleb Smirnoff if ($1 && $3.b1) { 40093b3a8eb9SGleb Smirnoff yyerror("\"pass\" not valid with \"no\""); 40103b3a8eb9SGleb Smirnoff YYERROR; 40113b3a8eb9SGleb Smirnoff } 40123b3a8eb9SGleb Smirnoff if ($1) 40133b3a8eb9SGleb Smirnoff $$.b1 = PF_NONAT; 40143b3a8eb9SGleb Smirnoff else 40153b3a8eb9SGleb Smirnoff $$.b1 = PF_NAT; 40163b3a8eb9SGleb Smirnoff $$.b2 = $3.b1; 40173b3a8eb9SGleb Smirnoff $$.w = $3.b2; 40183b3a8eb9SGleb Smirnoff $$.w2 = $3.w2; 40193b3a8eb9SGleb Smirnoff } 40203b3a8eb9SGleb Smirnoff | no RDR natpasslog { 40213b3a8eb9SGleb Smirnoff if ($1 && $3.b1) { 40223b3a8eb9SGleb Smirnoff yyerror("\"pass\" not valid with \"no\""); 40233b3a8eb9SGleb Smirnoff YYERROR; 40243b3a8eb9SGleb Smirnoff } 40253b3a8eb9SGleb Smirnoff if ($1) 40263b3a8eb9SGleb Smirnoff $$.b1 = PF_NORDR; 40273b3a8eb9SGleb Smirnoff else 40283b3a8eb9SGleb Smirnoff $$.b1 = PF_RDR; 40293b3a8eb9SGleb Smirnoff $$.b2 = $3.b1; 40303b3a8eb9SGleb Smirnoff $$.w = $3.b2; 40313b3a8eb9SGleb Smirnoff $$.w2 = $3.w2; 40323b3a8eb9SGleb Smirnoff } 40333b3a8eb9SGleb Smirnoff ; 40343b3a8eb9SGleb Smirnoff 40353b3a8eb9SGleb Smirnoff natrule : nataction interface af proto fromto tag tagged rtable 40363b3a8eb9SGleb Smirnoff redirpool pool_opts 40373b3a8eb9SGleb Smirnoff { 40383b3a8eb9SGleb Smirnoff struct pf_rule r; 40393b3a8eb9SGleb Smirnoff 40403b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_NAT)) 40413b3a8eb9SGleb Smirnoff YYERROR; 40423b3a8eb9SGleb Smirnoff 40433b3a8eb9SGleb Smirnoff memset(&r, 0, sizeof(r)); 40443b3a8eb9SGleb Smirnoff 40453b3a8eb9SGleb Smirnoff r.action = $1.b1; 40463b3a8eb9SGleb Smirnoff r.natpass = $1.b2; 40473b3a8eb9SGleb Smirnoff r.log = $1.w; 40483b3a8eb9SGleb Smirnoff r.logif = $1.w2; 40493b3a8eb9SGleb Smirnoff r.af = $3; 40503b3a8eb9SGleb Smirnoff 40513b3a8eb9SGleb Smirnoff if (!r.af) { 40523b3a8eb9SGleb Smirnoff if ($5.src.host && $5.src.host->af && 40533b3a8eb9SGleb Smirnoff !$5.src.host->ifindex) 40543b3a8eb9SGleb Smirnoff r.af = $5.src.host->af; 40553b3a8eb9SGleb Smirnoff else if ($5.dst.host && $5.dst.host->af && 40563b3a8eb9SGleb Smirnoff !$5.dst.host->ifindex) 40573b3a8eb9SGleb Smirnoff r.af = $5.dst.host->af; 40583b3a8eb9SGleb Smirnoff } 40593b3a8eb9SGleb Smirnoff 40603b3a8eb9SGleb Smirnoff if ($6 != NULL) 40613b3a8eb9SGleb Smirnoff if (strlcpy(r.tagname, $6, PF_TAG_NAME_SIZE) >= 40623b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) { 40633b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars", 40643b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1); 40653b3a8eb9SGleb Smirnoff YYERROR; 40663b3a8eb9SGleb Smirnoff } 40673b3a8eb9SGleb Smirnoff 40683b3a8eb9SGleb Smirnoff if ($7.name) 40693b3a8eb9SGleb Smirnoff if (strlcpy(r.match_tagname, $7.name, 40703b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 40713b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars", 40723b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1); 40733b3a8eb9SGleb Smirnoff YYERROR; 40743b3a8eb9SGleb Smirnoff } 40753b3a8eb9SGleb Smirnoff r.match_tag_not = $7.neg; 40763b3a8eb9SGleb Smirnoff r.rtableid = $8; 40773b3a8eb9SGleb Smirnoff 40783b3a8eb9SGleb Smirnoff if (r.action == PF_NONAT || r.action == PF_NORDR) { 40793b3a8eb9SGleb Smirnoff if ($9 != NULL) { 40803b3a8eb9SGleb Smirnoff yyerror("translation rule with 'no' " 40813b3a8eb9SGleb Smirnoff "does not need '->'"); 40823b3a8eb9SGleb Smirnoff YYERROR; 40833b3a8eb9SGleb Smirnoff } 40843b3a8eb9SGleb Smirnoff } else { 40853b3a8eb9SGleb Smirnoff if ($9 == NULL || $9->host == NULL) { 40863b3a8eb9SGleb Smirnoff yyerror("translation rule requires '-> " 40873b3a8eb9SGleb Smirnoff "address'"); 40883b3a8eb9SGleb Smirnoff YYERROR; 40893b3a8eb9SGleb Smirnoff } 40903b3a8eb9SGleb Smirnoff if (!r.af && ! $9->host->ifindex) 40913b3a8eb9SGleb Smirnoff r.af = $9->host->af; 40923b3a8eb9SGleb Smirnoff 40933b3a8eb9SGleb Smirnoff remove_invalid_hosts(&$9->host, &r.af); 40943b3a8eb9SGleb Smirnoff if (invalid_redirect($9->host, r.af)) 40953b3a8eb9SGleb Smirnoff YYERROR; 40963b3a8eb9SGleb Smirnoff if (check_netmask($9->host, r.af)) 40973b3a8eb9SGleb Smirnoff YYERROR; 40983b3a8eb9SGleb Smirnoff 40993b3a8eb9SGleb Smirnoff r.rpool.proxy_port[0] = ntohs($9->rport.a); 41003b3a8eb9SGleb Smirnoff 41013b3a8eb9SGleb Smirnoff switch (r.action) { 41023b3a8eb9SGleb Smirnoff case PF_RDR: 41033b3a8eb9SGleb Smirnoff if (!$9->rport.b && $9->rport.t && 41043b3a8eb9SGleb Smirnoff $5.dst.port != NULL) { 41053b3a8eb9SGleb Smirnoff r.rpool.proxy_port[1] = 41063b3a8eb9SGleb Smirnoff ntohs($9->rport.a) + 41073b3a8eb9SGleb Smirnoff (ntohs( 41083b3a8eb9SGleb Smirnoff $5.dst.port->port[1]) - 41093b3a8eb9SGleb Smirnoff ntohs( 41103b3a8eb9SGleb Smirnoff $5.dst.port->port[0])); 41113b3a8eb9SGleb Smirnoff } else 41123b3a8eb9SGleb Smirnoff r.rpool.proxy_port[1] = 41133b3a8eb9SGleb Smirnoff ntohs($9->rport.b); 41143b3a8eb9SGleb Smirnoff break; 41153b3a8eb9SGleb Smirnoff case PF_NAT: 41163b3a8eb9SGleb Smirnoff r.rpool.proxy_port[1] = 41173b3a8eb9SGleb Smirnoff ntohs($9->rport.b); 41183b3a8eb9SGleb Smirnoff if (!r.rpool.proxy_port[0] && 41193b3a8eb9SGleb Smirnoff !r.rpool.proxy_port[1]) { 41203b3a8eb9SGleb Smirnoff r.rpool.proxy_port[0] = 41213b3a8eb9SGleb Smirnoff PF_NAT_PROXY_PORT_LOW; 41223b3a8eb9SGleb Smirnoff r.rpool.proxy_port[1] = 41233b3a8eb9SGleb Smirnoff PF_NAT_PROXY_PORT_HIGH; 41243b3a8eb9SGleb Smirnoff } else if (!r.rpool.proxy_port[1]) 41253b3a8eb9SGleb Smirnoff r.rpool.proxy_port[1] = 41263b3a8eb9SGleb Smirnoff r.rpool.proxy_port[0]; 41273b3a8eb9SGleb Smirnoff break; 41283b3a8eb9SGleb Smirnoff default: 41293b3a8eb9SGleb Smirnoff break; 41303b3a8eb9SGleb Smirnoff } 41313b3a8eb9SGleb Smirnoff 41323b3a8eb9SGleb Smirnoff r.rpool.opts = $10.type; 41333b3a8eb9SGleb Smirnoff if ((r.rpool.opts & PF_POOL_TYPEMASK) == 41343b3a8eb9SGleb Smirnoff PF_POOL_NONE && ($9->host->next != NULL || 41353b3a8eb9SGleb Smirnoff $9->host->addr.type == PF_ADDR_TABLE || 41363b3a8eb9SGleb Smirnoff DYNIF_MULTIADDR($9->host->addr))) 41373b3a8eb9SGleb Smirnoff r.rpool.opts = PF_POOL_ROUNDROBIN; 41383b3a8eb9SGleb Smirnoff if ((r.rpool.opts & PF_POOL_TYPEMASK) != 41393b3a8eb9SGleb Smirnoff PF_POOL_ROUNDROBIN && 41403b3a8eb9SGleb Smirnoff disallow_table($9->host, "tables are only " 41413b3a8eb9SGleb Smirnoff "supported in round-robin redirection " 41423b3a8eb9SGleb Smirnoff "pools")) 41433b3a8eb9SGleb Smirnoff YYERROR; 41443b3a8eb9SGleb Smirnoff if ((r.rpool.opts & PF_POOL_TYPEMASK) != 41453b3a8eb9SGleb Smirnoff PF_POOL_ROUNDROBIN && 41463b3a8eb9SGleb Smirnoff disallow_alias($9->host, "interface (%s) " 41473b3a8eb9SGleb Smirnoff "is only supported in round-robin " 41483b3a8eb9SGleb Smirnoff "redirection pools")) 41493b3a8eb9SGleb Smirnoff YYERROR; 41503b3a8eb9SGleb Smirnoff if ($9->host->next != NULL) { 41513b3a8eb9SGleb Smirnoff if ((r.rpool.opts & PF_POOL_TYPEMASK) != 41523b3a8eb9SGleb Smirnoff PF_POOL_ROUNDROBIN) { 41533b3a8eb9SGleb Smirnoff yyerror("only round-robin " 41543b3a8eb9SGleb Smirnoff "valid for multiple " 41553b3a8eb9SGleb Smirnoff "redirection addresses"); 41563b3a8eb9SGleb Smirnoff YYERROR; 41573b3a8eb9SGleb Smirnoff } 41583b3a8eb9SGleb Smirnoff } 41593b3a8eb9SGleb Smirnoff } 41603b3a8eb9SGleb Smirnoff 41613b3a8eb9SGleb Smirnoff if ($10.key != NULL) 41623b3a8eb9SGleb Smirnoff memcpy(&r.rpool.key, $10.key, 41633b3a8eb9SGleb Smirnoff sizeof(struct pf_poolhashkey)); 41643b3a8eb9SGleb Smirnoff 41653b3a8eb9SGleb Smirnoff if ($10.opts) 41663b3a8eb9SGleb Smirnoff r.rpool.opts |= $10.opts; 41673b3a8eb9SGleb Smirnoff 41683b3a8eb9SGleb Smirnoff if ($10.staticport) { 41693b3a8eb9SGleb Smirnoff if (r.action != PF_NAT) { 41703b3a8eb9SGleb Smirnoff yyerror("the 'static-port' option is " 41713b3a8eb9SGleb Smirnoff "only valid with nat rules"); 41723b3a8eb9SGleb Smirnoff YYERROR; 41733b3a8eb9SGleb Smirnoff } 41743b3a8eb9SGleb Smirnoff if (r.rpool.proxy_port[0] != 41753b3a8eb9SGleb Smirnoff PF_NAT_PROXY_PORT_LOW && 41763b3a8eb9SGleb Smirnoff r.rpool.proxy_port[1] != 41773b3a8eb9SGleb Smirnoff PF_NAT_PROXY_PORT_HIGH) { 41783b3a8eb9SGleb Smirnoff yyerror("the 'static-port' option can't" 41793b3a8eb9SGleb Smirnoff " be used when specifying a port" 41803b3a8eb9SGleb Smirnoff " range"); 41813b3a8eb9SGleb Smirnoff YYERROR; 41823b3a8eb9SGleb Smirnoff } 41833b3a8eb9SGleb Smirnoff r.rpool.proxy_port[0] = 0; 41843b3a8eb9SGleb Smirnoff r.rpool.proxy_port[1] = 0; 41853b3a8eb9SGleb Smirnoff } 41863b3a8eb9SGleb Smirnoff 41873b3a8eb9SGleb Smirnoff expand_rule(&r, $2, $9 == NULL ? NULL : $9->host, $4, 41883b3a8eb9SGleb Smirnoff $5.src_os, $5.src.host, $5.src.port, $5.dst.host, 41893b3a8eb9SGleb Smirnoff $5.dst.port, 0, 0, 0, ""); 41903b3a8eb9SGleb Smirnoff free($9); 41913b3a8eb9SGleb Smirnoff } 41923b3a8eb9SGleb Smirnoff ; 41933b3a8eb9SGleb Smirnoff 41943b3a8eb9SGleb Smirnoff binatrule : no BINAT natpasslog interface af proto FROM host toipspec tag 41953b3a8eb9SGleb Smirnoff tagged rtable redirection 41963b3a8eb9SGleb Smirnoff { 41973b3a8eb9SGleb Smirnoff struct pf_rule binat; 41983b3a8eb9SGleb Smirnoff struct pf_pooladdr *pa; 41993b3a8eb9SGleb Smirnoff 42003b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_NAT)) 42013b3a8eb9SGleb Smirnoff YYERROR; 42023b3a8eb9SGleb Smirnoff if (disallow_urpf_failed($9, "\"urpf-failed\" is not " 42033b3a8eb9SGleb Smirnoff "permitted as a binat destination")) 42043b3a8eb9SGleb Smirnoff YYERROR; 42053b3a8eb9SGleb Smirnoff 42063b3a8eb9SGleb Smirnoff memset(&binat, 0, sizeof(binat)); 42073b3a8eb9SGleb Smirnoff 42083b3a8eb9SGleb Smirnoff if ($1 && $3.b1) { 42093b3a8eb9SGleb Smirnoff yyerror("\"pass\" not valid with \"no\""); 42103b3a8eb9SGleb Smirnoff YYERROR; 42113b3a8eb9SGleb Smirnoff } 42123b3a8eb9SGleb Smirnoff if ($1) 42133b3a8eb9SGleb Smirnoff binat.action = PF_NOBINAT; 42143b3a8eb9SGleb Smirnoff else 42153b3a8eb9SGleb Smirnoff binat.action = PF_BINAT; 42163b3a8eb9SGleb Smirnoff binat.natpass = $3.b1; 42173b3a8eb9SGleb Smirnoff binat.log = $3.b2; 42183b3a8eb9SGleb Smirnoff binat.logif = $3.w2; 42193b3a8eb9SGleb Smirnoff binat.af = $5; 42203b3a8eb9SGleb Smirnoff if (!binat.af && $8 != NULL && $8->af) 42213b3a8eb9SGleb Smirnoff binat.af = $8->af; 42223b3a8eb9SGleb Smirnoff if (!binat.af && $9 != NULL && $9->af) 42233b3a8eb9SGleb Smirnoff binat.af = $9->af; 42243b3a8eb9SGleb Smirnoff 42253b3a8eb9SGleb Smirnoff if (!binat.af && $13 != NULL && $13->host) 42263b3a8eb9SGleb Smirnoff binat.af = $13->host->af; 42273b3a8eb9SGleb Smirnoff if (!binat.af) { 42283b3a8eb9SGleb Smirnoff yyerror("address family (inet/inet6) " 42293b3a8eb9SGleb Smirnoff "undefined"); 42303b3a8eb9SGleb Smirnoff YYERROR; 42313b3a8eb9SGleb Smirnoff } 42323b3a8eb9SGleb Smirnoff 42333b3a8eb9SGleb Smirnoff if ($4 != NULL) { 42343b3a8eb9SGleb Smirnoff memcpy(binat.ifname, $4->ifname, 42353b3a8eb9SGleb Smirnoff sizeof(binat.ifname)); 42363b3a8eb9SGleb Smirnoff binat.ifnot = $4->not; 42373b3a8eb9SGleb Smirnoff free($4); 42383b3a8eb9SGleb Smirnoff } 42393b3a8eb9SGleb Smirnoff 42403b3a8eb9SGleb Smirnoff if ($10 != NULL) 42413b3a8eb9SGleb Smirnoff if (strlcpy(binat.tagname, $10, 42423b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 42433b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars", 42443b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1); 42453b3a8eb9SGleb Smirnoff YYERROR; 42463b3a8eb9SGleb Smirnoff } 42473b3a8eb9SGleb Smirnoff if ($11.name) 42483b3a8eb9SGleb Smirnoff if (strlcpy(binat.match_tagname, $11.name, 42493b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE) >= PF_TAG_NAME_SIZE) { 42503b3a8eb9SGleb Smirnoff yyerror("tag too long, max %u chars", 42513b3a8eb9SGleb Smirnoff PF_TAG_NAME_SIZE - 1); 42523b3a8eb9SGleb Smirnoff YYERROR; 42533b3a8eb9SGleb Smirnoff } 42543b3a8eb9SGleb Smirnoff binat.match_tag_not = $11.neg; 42553b3a8eb9SGleb Smirnoff binat.rtableid = $12; 42563b3a8eb9SGleb Smirnoff 42573b3a8eb9SGleb Smirnoff if ($6 != NULL) { 42583b3a8eb9SGleb Smirnoff binat.proto = $6->proto; 42593b3a8eb9SGleb Smirnoff free($6); 42603b3a8eb9SGleb Smirnoff } 42613b3a8eb9SGleb Smirnoff 42623b3a8eb9SGleb Smirnoff if ($8 != NULL && disallow_table($8, "invalid use of " 42633b3a8eb9SGleb Smirnoff "table <%s> as the source address of a binat rule")) 42643b3a8eb9SGleb Smirnoff YYERROR; 42653b3a8eb9SGleb Smirnoff if ($8 != NULL && disallow_alias($8, "invalid use of " 42663b3a8eb9SGleb Smirnoff "interface (%s) as the source address of a binat " 42673b3a8eb9SGleb Smirnoff "rule")) 42683b3a8eb9SGleb Smirnoff YYERROR; 42693b3a8eb9SGleb Smirnoff if ($13 != NULL && $13->host != NULL && disallow_table( 42703b3a8eb9SGleb Smirnoff $13->host, "invalid use of table <%s> as the " 42713b3a8eb9SGleb Smirnoff "redirect address of a binat rule")) 42723b3a8eb9SGleb Smirnoff YYERROR; 42733b3a8eb9SGleb Smirnoff if ($13 != NULL && $13->host != NULL && disallow_alias( 42743b3a8eb9SGleb Smirnoff $13->host, "invalid use of interface (%s) as the " 42753b3a8eb9SGleb Smirnoff "redirect address of a binat rule")) 42763b3a8eb9SGleb Smirnoff YYERROR; 42773b3a8eb9SGleb Smirnoff 42783b3a8eb9SGleb Smirnoff if ($8 != NULL) { 42793b3a8eb9SGleb Smirnoff if ($8->next) { 42803b3a8eb9SGleb Smirnoff yyerror("multiple binat ip addresses"); 42813b3a8eb9SGleb Smirnoff YYERROR; 42823b3a8eb9SGleb Smirnoff } 42833b3a8eb9SGleb Smirnoff if ($8->addr.type == PF_ADDR_DYNIFTL) 42843b3a8eb9SGleb Smirnoff $8->af = binat.af; 42853b3a8eb9SGleb Smirnoff if ($8->af != binat.af) { 42863b3a8eb9SGleb Smirnoff yyerror("binat ip versions must match"); 42873b3a8eb9SGleb Smirnoff YYERROR; 42883b3a8eb9SGleb Smirnoff } 42893b3a8eb9SGleb Smirnoff if (check_netmask($8, binat.af)) 42903b3a8eb9SGleb Smirnoff YYERROR; 42913b3a8eb9SGleb Smirnoff memcpy(&binat.src.addr, &$8->addr, 42923b3a8eb9SGleb Smirnoff sizeof(binat.src.addr)); 42933b3a8eb9SGleb Smirnoff free($8); 42943b3a8eb9SGleb Smirnoff } 42953b3a8eb9SGleb Smirnoff if ($9 != NULL) { 42963b3a8eb9SGleb Smirnoff if ($9->next) { 42973b3a8eb9SGleb Smirnoff yyerror("multiple binat ip addresses"); 42983b3a8eb9SGleb Smirnoff YYERROR; 42993b3a8eb9SGleb Smirnoff } 43003b3a8eb9SGleb Smirnoff if ($9->af != binat.af && $9->af) { 43013b3a8eb9SGleb Smirnoff yyerror("binat ip versions must match"); 43023b3a8eb9SGleb Smirnoff YYERROR; 43033b3a8eb9SGleb Smirnoff } 43043b3a8eb9SGleb Smirnoff if (check_netmask($9, binat.af)) 43053b3a8eb9SGleb Smirnoff YYERROR; 43063b3a8eb9SGleb Smirnoff memcpy(&binat.dst.addr, &$9->addr, 43073b3a8eb9SGleb Smirnoff sizeof(binat.dst.addr)); 43083b3a8eb9SGleb Smirnoff binat.dst.neg = $9->not; 43093b3a8eb9SGleb Smirnoff free($9); 43103b3a8eb9SGleb Smirnoff } 43113b3a8eb9SGleb Smirnoff 43123b3a8eb9SGleb Smirnoff if (binat.action == PF_NOBINAT) { 43133b3a8eb9SGleb Smirnoff if ($13 != NULL) { 43143b3a8eb9SGleb Smirnoff yyerror("'no binat' rule does not need" 43153b3a8eb9SGleb Smirnoff " '->'"); 43163b3a8eb9SGleb Smirnoff YYERROR; 43173b3a8eb9SGleb Smirnoff } 43183b3a8eb9SGleb Smirnoff } else { 43193b3a8eb9SGleb Smirnoff if ($13 == NULL || $13->host == NULL) { 43203b3a8eb9SGleb Smirnoff yyerror("'binat' rule requires" 43213b3a8eb9SGleb Smirnoff " '-> address'"); 43223b3a8eb9SGleb Smirnoff YYERROR; 43233b3a8eb9SGleb Smirnoff } 43243b3a8eb9SGleb Smirnoff 43253b3a8eb9SGleb Smirnoff remove_invalid_hosts(&$13->host, &binat.af); 43263b3a8eb9SGleb Smirnoff if (invalid_redirect($13->host, binat.af)) 43273b3a8eb9SGleb Smirnoff YYERROR; 43283b3a8eb9SGleb Smirnoff if ($13->host->next != NULL) { 43293b3a8eb9SGleb Smirnoff yyerror("binat rule must redirect to " 43303b3a8eb9SGleb Smirnoff "a single address"); 43313b3a8eb9SGleb Smirnoff YYERROR; 43323b3a8eb9SGleb Smirnoff } 43333b3a8eb9SGleb Smirnoff if (check_netmask($13->host, binat.af)) 43343b3a8eb9SGleb Smirnoff YYERROR; 43353b3a8eb9SGleb Smirnoff 43363b3a8eb9SGleb Smirnoff if (!PF_AZERO(&binat.src.addr.v.a.mask, 43373b3a8eb9SGleb Smirnoff binat.af) && 43383b3a8eb9SGleb Smirnoff !PF_AEQ(&binat.src.addr.v.a.mask, 43393b3a8eb9SGleb Smirnoff &$13->host->addr.v.a.mask, binat.af)) { 43403b3a8eb9SGleb Smirnoff yyerror("'binat' source mask and " 43413b3a8eb9SGleb Smirnoff "redirect mask must be the same"); 43423b3a8eb9SGleb Smirnoff YYERROR; 43433b3a8eb9SGleb Smirnoff } 43443b3a8eb9SGleb Smirnoff 43453b3a8eb9SGleb Smirnoff TAILQ_INIT(&binat.rpool.list); 43463b3a8eb9SGleb Smirnoff pa = calloc(1, sizeof(struct pf_pooladdr)); 43473b3a8eb9SGleb Smirnoff if (pa == NULL) 43483b3a8eb9SGleb Smirnoff err(1, "binat: calloc"); 43493b3a8eb9SGleb Smirnoff pa->addr = $13->host->addr; 43503b3a8eb9SGleb Smirnoff pa->ifname[0] = 0; 43513b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(&binat.rpool.list, 43523b3a8eb9SGleb Smirnoff pa, entries); 43533b3a8eb9SGleb Smirnoff 43543b3a8eb9SGleb Smirnoff free($13); 43553b3a8eb9SGleb Smirnoff } 43563b3a8eb9SGleb Smirnoff 43573b3a8eb9SGleb Smirnoff pfctl_add_rule(pf, &binat, ""); 43583b3a8eb9SGleb Smirnoff } 43593b3a8eb9SGleb Smirnoff ; 43603b3a8eb9SGleb Smirnoff 43613b3a8eb9SGleb Smirnoff tag : /* empty */ { $$ = NULL; } 43623b3a8eb9SGleb Smirnoff | TAG STRING { $$ = $2; } 43633b3a8eb9SGleb Smirnoff ; 43643b3a8eb9SGleb Smirnoff 43653b3a8eb9SGleb Smirnoff tagged : /* empty */ { $$.neg = 0; $$.name = NULL; } 43663b3a8eb9SGleb Smirnoff | not TAGGED string { $$.neg = $1; $$.name = $3; } 43673b3a8eb9SGleb Smirnoff ; 43683b3a8eb9SGleb Smirnoff 43693b3a8eb9SGleb Smirnoff rtable : /* empty */ { $$ = -1; } 43703b3a8eb9SGleb Smirnoff | RTABLE NUMBER { 43713b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > rt_tableid_max()) { 43723b3a8eb9SGleb Smirnoff yyerror("invalid rtable id"); 43733b3a8eb9SGleb Smirnoff YYERROR; 43743b3a8eb9SGleb Smirnoff } 43753b3a8eb9SGleb Smirnoff $$ = $2; 43763b3a8eb9SGleb Smirnoff } 43773b3a8eb9SGleb Smirnoff ; 43783b3a8eb9SGleb Smirnoff 43793b3a8eb9SGleb Smirnoff route_host : STRING { 43803b3a8eb9SGleb Smirnoff $$ = calloc(1, sizeof(struct node_host)); 43813b3a8eb9SGleb Smirnoff if ($$ == NULL) 43823b3a8eb9SGleb Smirnoff err(1, "route_host: calloc"); 43833b3a8eb9SGleb Smirnoff $$->ifname = $1; 43843b3a8eb9SGleb Smirnoff set_ipmask($$, 128); 43853b3a8eb9SGleb Smirnoff $$->next = NULL; 43863b3a8eb9SGleb Smirnoff $$->tail = $$; 43873b3a8eb9SGleb Smirnoff } 43883b3a8eb9SGleb Smirnoff | '(' STRING host ')' { 43893b3a8eb9SGleb Smirnoff $$ = $3; 43903b3a8eb9SGleb Smirnoff $$->ifname = $2; 43913b3a8eb9SGleb Smirnoff } 43923b3a8eb9SGleb Smirnoff ; 43933b3a8eb9SGleb Smirnoff 43943b3a8eb9SGleb Smirnoff route_host_list : route_host optnl { $$ = $1; } 43953b3a8eb9SGleb Smirnoff | route_host_list comma route_host optnl { 43963b3a8eb9SGleb Smirnoff if ($1->af == 0) 43973b3a8eb9SGleb Smirnoff $1->af = $3->af; 43983b3a8eb9SGleb Smirnoff if ($1->af != $3->af) { 43993b3a8eb9SGleb Smirnoff yyerror("all pool addresses must be in the " 44003b3a8eb9SGleb Smirnoff "same address family"); 44013b3a8eb9SGleb Smirnoff YYERROR; 44023b3a8eb9SGleb Smirnoff } 44033b3a8eb9SGleb Smirnoff $1->tail->next = $3; 44043b3a8eb9SGleb Smirnoff $1->tail = $3->tail; 44053b3a8eb9SGleb Smirnoff $$ = $1; 44063b3a8eb9SGleb Smirnoff } 44073b3a8eb9SGleb Smirnoff ; 44083b3a8eb9SGleb Smirnoff 44093b3a8eb9SGleb Smirnoff routespec : route_host { $$ = $1; } 44103b3a8eb9SGleb Smirnoff | '{' optnl route_host_list '}' { $$ = $3; } 44113b3a8eb9SGleb Smirnoff ; 44123b3a8eb9SGleb Smirnoff 44133b3a8eb9SGleb Smirnoff route : /* empty */ { 44143b3a8eb9SGleb Smirnoff $$.host = NULL; 44153b3a8eb9SGleb Smirnoff $$.rt = 0; 44163b3a8eb9SGleb Smirnoff $$.pool_opts = 0; 44173b3a8eb9SGleb Smirnoff } 44183b3a8eb9SGleb Smirnoff | FASTROUTE { 4419*813196a1SKristof Provost /* backwards-compat */ 44203b3a8eb9SGleb Smirnoff $$.host = NULL; 4421*813196a1SKristof Provost $$.rt = 0; 44223b3a8eb9SGleb Smirnoff $$.pool_opts = 0; 44233b3a8eb9SGleb Smirnoff } 44243b3a8eb9SGleb Smirnoff | ROUTETO routespec pool_opts { 44253b3a8eb9SGleb Smirnoff $$.host = $2; 44263b3a8eb9SGleb Smirnoff $$.rt = PF_ROUTETO; 44273b3a8eb9SGleb Smirnoff $$.pool_opts = $3.type | $3.opts; 44283b3a8eb9SGleb Smirnoff if ($3.key != NULL) 44293b3a8eb9SGleb Smirnoff $$.key = $3.key; 44303b3a8eb9SGleb Smirnoff } 44313b3a8eb9SGleb Smirnoff | REPLYTO routespec pool_opts { 44323b3a8eb9SGleb Smirnoff $$.host = $2; 44333b3a8eb9SGleb Smirnoff $$.rt = PF_REPLYTO; 44343b3a8eb9SGleb Smirnoff $$.pool_opts = $3.type | $3.opts; 44353b3a8eb9SGleb Smirnoff if ($3.key != NULL) 44363b3a8eb9SGleb Smirnoff $$.key = $3.key; 44373b3a8eb9SGleb Smirnoff } 44383b3a8eb9SGleb Smirnoff | DUPTO routespec pool_opts { 44393b3a8eb9SGleb Smirnoff $$.host = $2; 44403b3a8eb9SGleb Smirnoff $$.rt = PF_DUPTO; 44413b3a8eb9SGleb Smirnoff $$.pool_opts = $3.type | $3.opts; 44423b3a8eb9SGleb Smirnoff if ($3.key != NULL) 44433b3a8eb9SGleb Smirnoff $$.key = $3.key; 44443b3a8eb9SGleb Smirnoff } 44453b3a8eb9SGleb Smirnoff ; 44463b3a8eb9SGleb Smirnoff 44473b3a8eb9SGleb Smirnoff timeout_spec : STRING NUMBER 44483b3a8eb9SGleb Smirnoff { 44493b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION)) { 44503b3a8eb9SGleb Smirnoff free($1); 44513b3a8eb9SGleb Smirnoff YYERROR; 44523b3a8eb9SGleb Smirnoff } 44533b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX) { 44543b3a8eb9SGleb Smirnoff yyerror("only positive values permitted"); 44553b3a8eb9SGleb Smirnoff YYERROR; 44563b3a8eb9SGleb Smirnoff } 44573b3a8eb9SGleb Smirnoff if (pfctl_set_timeout(pf, $1, $2, 0) != 0) { 44583b3a8eb9SGleb Smirnoff yyerror("unknown timeout %s", $1); 44593b3a8eb9SGleb Smirnoff free($1); 44603b3a8eb9SGleb Smirnoff YYERROR; 44613b3a8eb9SGleb Smirnoff } 44623b3a8eb9SGleb Smirnoff free($1); 44633b3a8eb9SGleb Smirnoff } 44647f8af000SLuiz Otavio O Souza | INTERVAL NUMBER { 44657f8af000SLuiz Otavio O Souza if (check_rulestate(PFCTL_STATE_OPTION)) 44667f8af000SLuiz Otavio O Souza YYERROR; 44677f8af000SLuiz Otavio O Souza if ($2 < 0 || $2 > UINT_MAX) { 44687f8af000SLuiz Otavio O Souza yyerror("only positive values permitted"); 44697f8af000SLuiz Otavio O Souza YYERROR; 44707f8af000SLuiz Otavio O Souza } 44717f8af000SLuiz Otavio O Souza if (pfctl_set_timeout(pf, "interval", $2, 0) != 0) 44727f8af000SLuiz Otavio O Souza YYERROR; 44737f8af000SLuiz Otavio O Souza } 44743b3a8eb9SGleb Smirnoff ; 44753b3a8eb9SGleb Smirnoff 44763b3a8eb9SGleb Smirnoff timeout_list : timeout_list comma timeout_spec optnl 44773b3a8eb9SGleb Smirnoff | timeout_spec optnl 44783b3a8eb9SGleb Smirnoff ; 44793b3a8eb9SGleb Smirnoff 44803b3a8eb9SGleb Smirnoff limit_spec : STRING NUMBER 44813b3a8eb9SGleb Smirnoff { 44823b3a8eb9SGleb Smirnoff if (check_rulestate(PFCTL_STATE_OPTION)) { 44833b3a8eb9SGleb Smirnoff free($1); 44843b3a8eb9SGleb Smirnoff YYERROR; 44853b3a8eb9SGleb Smirnoff } 44863b3a8eb9SGleb Smirnoff if ($2 < 0 || $2 > UINT_MAX) { 44873b3a8eb9SGleb Smirnoff yyerror("only positive values permitted"); 44883b3a8eb9SGleb Smirnoff YYERROR; 44893b3a8eb9SGleb Smirnoff } 44903b3a8eb9SGleb Smirnoff if (pfctl_set_limit(pf, $1, $2) != 0) { 44913b3a8eb9SGleb Smirnoff yyerror("unable to set limit %s %u", $1, $2); 44923b3a8eb9SGleb Smirnoff free($1); 44933b3a8eb9SGleb Smirnoff YYERROR; 44943b3a8eb9SGleb Smirnoff } 44953b3a8eb9SGleb Smirnoff free($1); 44963b3a8eb9SGleb Smirnoff } 44973b3a8eb9SGleb Smirnoff ; 44983b3a8eb9SGleb Smirnoff 44993b3a8eb9SGleb Smirnoff limit_list : limit_list comma limit_spec optnl 45003b3a8eb9SGleb Smirnoff | limit_spec optnl 45013b3a8eb9SGleb Smirnoff ; 45023b3a8eb9SGleb Smirnoff 45033b3a8eb9SGleb Smirnoff comma : ',' 45043b3a8eb9SGleb Smirnoff | /* empty */ 45053b3a8eb9SGleb Smirnoff ; 45063b3a8eb9SGleb Smirnoff 45073b3a8eb9SGleb Smirnoff yesno : NO { $$ = 0; } 45083b3a8eb9SGleb Smirnoff | STRING { 45093b3a8eb9SGleb Smirnoff if (!strcmp($1, "yes")) 45103b3a8eb9SGleb Smirnoff $$ = 1; 45113b3a8eb9SGleb Smirnoff else { 45123b3a8eb9SGleb Smirnoff yyerror("invalid value '%s', expected 'yes' " 45133b3a8eb9SGleb Smirnoff "or 'no'", $1); 45143b3a8eb9SGleb Smirnoff free($1); 45153b3a8eb9SGleb Smirnoff YYERROR; 45163b3a8eb9SGleb Smirnoff } 45173b3a8eb9SGleb Smirnoff free($1); 45183b3a8eb9SGleb Smirnoff } 45193b3a8eb9SGleb Smirnoff ; 45203b3a8eb9SGleb Smirnoff 45213b3a8eb9SGleb Smirnoff unaryop : '=' { $$ = PF_OP_EQ; } 45223b3a8eb9SGleb Smirnoff | '!' '=' { $$ = PF_OP_NE; } 45233b3a8eb9SGleb Smirnoff | '<' '=' { $$ = PF_OP_LE; } 45243b3a8eb9SGleb Smirnoff | '<' { $$ = PF_OP_LT; } 45253b3a8eb9SGleb Smirnoff | '>' '=' { $$ = PF_OP_GE; } 45263b3a8eb9SGleb Smirnoff | '>' { $$ = PF_OP_GT; } 45273b3a8eb9SGleb Smirnoff ; 45283b3a8eb9SGleb Smirnoff 45293b3a8eb9SGleb Smirnoff %% 45303b3a8eb9SGleb Smirnoff 45313b3a8eb9SGleb Smirnoff int 45323b3a8eb9SGleb Smirnoff yyerror(const char *fmt, ...) 45333b3a8eb9SGleb Smirnoff { 45343b3a8eb9SGleb Smirnoff va_list ap; 45353b3a8eb9SGleb Smirnoff 45363b3a8eb9SGleb Smirnoff file->errors++; 45373b3a8eb9SGleb Smirnoff va_start(ap, fmt); 45383b3a8eb9SGleb Smirnoff fprintf(stderr, "%s:%d: ", file->name, yylval.lineno); 45393b3a8eb9SGleb Smirnoff vfprintf(stderr, fmt, ap); 45403b3a8eb9SGleb Smirnoff fprintf(stderr, "\n"); 45413b3a8eb9SGleb Smirnoff va_end(ap); 45423b3a8eb9SGleb Smirnoff return (0); 45433b3a8eb9SGleb Smirnoff } 45443b3a8eb9SGleb Smirnoff 45453b3a8eb9SGleb Smirnoff int 45463b3a8eb9SGleb Smirnoff disallow_table(struct node_host *h, const char *fmt) 45473b3a8eb9SGleb Smirnoff { 45483b3a8eb9SGleb Smirnoff for (; h != NULL; h = h->next) 45493b3a8eb9SGleb Smirnoff if (h->addr.type == PF_ADDR_TABLE) { 45503b3a8eb9SGleb Smirnoff yyerror(fmt, h->addr.v.tblname); 45513b3a8eb9SGleb Smirnoff return (1); 45523b3a8eb9SGleb Smirnoff } 45533b3a8eb9SGleb Smirnoff return (0); 45543b3a8eb9SGleb Smirnoff } 45553b3a8eb9SGleb Smirnoff 45563b3a8eb9SGleb Smirnoff int 45573b3a8eb9SGleb Smirnoff disallow_urpf_failed(struct node_host *h, const char *fmt) 45583b3a8eb9SGleb Smirnoff { 45593b3a8eb9SGleb Smirnoff for (; h != NULL; h = h->next) 45603b3a8eb9SGleb Smirnoff if (h->addr.type == PF_ADDR_URPFFAILED) { 45613b3a8eb9SGleb Smirnoff yyerror(fmt); 45623b3a8eb9SGleb Smirnoff return (1); 45633b3a8eb9SGleb Smirnoff } 45643b3a8eb9SGleb Smirnoff return (0); 45653b3a8eb9SGleb Smirnoff } 45663b3a8eb9SGleb Smirnoff 45673b3a8eb9SGleb Smirnoff int 45683b3a8eb9SGleb Smirnoff disallow_alias(struct node_host *h, const char *fmt) 45693b3a8eb9SGleb Smirnoff { 45703b3a8eb9SGleb Smirnoff for (; h != NULL; h = h->next) 45713b3a8eb9SGleb Smirnoff if (DYNIF_MULTIADDR(h->addr)) { 45723b3a8eb9SGleb Smirnoff yyerror(fmt, h->addr.v.tblname); 45733b3a8eb9SGleb Smirnoff return (1); 45743b3a8eb9SGleb Smirnoff } 45753b3a8eb9SGleb Smirnoff return (0); 45763b3a8eb9SGleb Smirnoff } 45773b3a8eb9SGleb Smirnoff 45783b3a8eb9SGleb Smirnoff int 45793b3a8eb9SGleb Smirnoff rule_consistent(struct pf_rule *r, int anchor_call) 45803b3a8eb9SGleb Smirnoff { 45813b3a8eb9SGleb Smirnoff int problems = 0; 45823b3a8eb9SGleb Smirnoff 45833b3a8eb9SGleb Smirnoff switch (r->action) { 45843b3a8eb9SGleb Smirnoff case PF_PASS: 45853b3a8eb9SGleb Smirnoff case PF_DROP: 45863b3a8eb9SGleb Smirnoff case PF_SCRUB: 45873b3a8eb9SGleb Smirnoff case PF_NOSCRUB: 45883b3a8eb9SGleb Smirnoff problems = filter_consistent(r, anchor_call); 45893b3a8eb9SGleb Smirnoff break; 45903b3a8eb9SGleb Smirnoff case PF_NAT: 45913b3a8eb9SGleb Smirnoff case PF_NONAT: 45923b3a8eb9SGleb Smirnoff problems = nat_consistent(r); 45933b3a8eb9SGleb Smirnoff break; 45943b3a8eb9SGleb Smirnoff case PF_RDR: 45953b3a8eb9SGleb Smirnoff case PF_NORDR: 45963b3a8eb9SGleb Smirnoff problems = rdr_consistent(r); 45973b3a8eb9SGleb Smirnoff break; 45983b3a8eb9SGleb Smirnoff case PF_BINAT: 45993b3a8eb9SGleb Smirnoff case PF_NOBINAT: 46003b3a8eb9SGleb Smirnoff default: 46013b3a8eb9SGleb Smirnoff break; 46023b3a8eb9SGleb Smirnoff } 46033b3a8eb9SGleb Smirnoff return (problems); 46043b3a8eb9SGleb Smirnoff } 46053b3a8eb9SGleb Smirnoff 46063b3a8eb9SGleb Smirnoff int 46073b3a8eb9SGleb Smirnoff filter_consistent(struct pf_rule *r, int anchor_call) 46083b3a8eb9SGleb Smirnoff { 46093b3a8eb9SGleb Smirnoff int problems = 0; 46103b3a8eb9SGleb Smirnoff 46113b3a8eb9SGleb Smirnoff if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP && 46123b3a8eb9SGleb Smirnoff (r->src.port_op || r->dst.port_op)) { 46133b3a8eb9SGleb Smirnoff yyerror("port only applies to tcp/udp"); 46143b3a8eb9SGleb Smirnoff problems++; 46153b3a8eb9SGleb Smirnoff } 46163b3a8eb9SGleb Smirnoff if (r->proto != IPPROTO_ICMP && r->proto != IPPROTO_ICMPV6 && 46173b3a8eb9SGleb Smirnoff (r->type || r->code)) { 46183b3a8eb9SGleb Smirnoff yyerror("icmp-type/code only applies to icmp"); 46193b3a8eb9SGleb Smirnoff problems++; 46203b3a8eb9SGleb Smirnoff } 46213b3a8eb9SGleb Smirnoff if (!r->af && (r->type || r->code)) { 46223b3a8eb9SGleb Smirnoff yyerror("must indicate address family with icmp-type/code"); 46233b3a8eb9SGleb Smirnoff problems++; 46243b3a8eb9SGleb Smirnoff } 46253b3a8eb9SGleb Smirnoff if (r->overload_tblname[0] && 46263b3a8eb9SGleb Smirnoff r->max_src_conn == 0 && r->max_src_conn_rate.seconds == 0) { 46273b3a8eb9SGleb Smirnoff yyerror("'overload' requires 'max-src-conn' " 46283b3a8eb9SGleb Smirnoff "or 'max-src-conn-rate'"); 46293b3a8eb9SGleb Smirnoff problems++; 46303b3a8eb9SGleb Smirnoff } 46313b3a8eb9SGleb Smirnoff if ((r->proto == IPPROTO_ICMP && r->af == AF_INET6) || 46323b3a8eb9SGleb Smirnoff (r->proto == IPPROTO_ICMPV6 && r->af == AF_INET)) { 46333b3a8eb9SGleb Smirnoff yyerror("proto %s doesn't match address family %s", 46343b3a8eb9SGleb Smirnoff r->proto == IPPROTO_ICMP ? "icmp" : "icmp6", 46353b3a8eb9SGleb Smirnoff r->af == AF_INET ? "inet" : "inet6"); 46363b3a8eb9SGleb Smirnoff problems++; 46373b3a8eb9SGleb Smirnoff } 46383b3a8eb9SGleb Smirnoff if (r->allow_opts && r->action != PF_PASS) { 46393b3a8eb9SGleb Smirnoff yyerror("allow-opts can only be specified for pass rules"); 46403b3a8eb9SGleb Smirnoff problems++; 46413b3a8eb9SGleb Smirnoff } 46423b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_FRAGMENT && (r->src.port_op || 46433b3a8eb9SGleb Smirnoff r->dst.port_op || r->flagset || r->type || r->code)) { 46443b3a8eb9SGleb Smirnoff yyerror("fragments can be filtered only on IP header fields"); 46453b3a8eb9SGleb Smirnoff problems++; 46463b3a8eb9SGleb Smirnoff } 46473b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_RETURNRST && r->proto != IPPROTO_TCP) { 46483b3a8eb9SGleb Smirnoff yyerror("return-rst can only be applied to TCP rules"); 46493b3a8eb9SGleb Smirnoff problems++; 46503b3a8eb9SGleb Smirnoff } 46513b3a8eb9SGleb Smirnoff if (r->max_src_nodes && !(r->rule_flag & PFRULE_RULESRCTRACK)) { 46523b3a8eb9SGleb Smirnoff yyerror("max-src-nodes requires 'source-track rule'"); 46533b3a8eb9SGleb Smirnoff problems++; 46543b3a8eb9SGleb Smirnoff } 46553b3a8eb9SGleb Smirnoff if (r->action == PF_DROP && r->keep_state) { 46563b3a8eb9SGleb Smirnoff yyerror("keep state on block rules doesn't make sense"); 46573b3a8eb9SGleb Smirnoff problems++; 46583b3a8eb9SGleb Smirnoff } 46593b3a8eb9SGleb Smirnoff if (r->rule_flag & PFRULE_STATESLOPPY && 46603b3a8eb9SGleb Smirnoff (r->keep_state == PF_STATE_MODULATE || 46613b3a8eb9SGleb Smirnoff r->keep_state == PF_STATE_SYNPROXY)) { 46623b3a8eb9SGleb Smirnoff yyerror("sloppy state matching cannot be used with " 46633b3a8eb9SGleb Smirnoff "synproxy state or modulate state"); 46643b3a8eb9SGleb Smirnoff problems++; 46653b3a8eb9SGleb Smirnoff } 46663b3a8eb9SGleb Smirnoff return (-problems); 46673b3a8eb9SGleb Smirnoff } 46683b3a8eb9SGleb Smirnoff 46693b3a8eb9SGleb Smirnoff int 46703b3a8eb9SGleb Smirnoff nat_consistent(struct pf_rule *r) 46713b3a8eb9SGleb Smirnoff { 46723b3a8eb9SGleb Smirnoff return (0); /* yeah! */ 46733b3a8eb9SGleb Smirnoff } 46743b3a8eb9SGleb Smirnoff 46753b3a8eb9SGleb Smirnoff int 46763b3a8eb9SGleb Smirnoff rdr_consistent(struct pf_rule *r) 46773b3a8eb9SGleb Smirnoff { 46783b3a8eb9SGleb Smirnoff int problems = 0; 46793b3a8eb9SGleb Smirnoff 46803b3a8eb9SGleb Smirnoff if (r->proto != IPPROTO_TCP && r->proto != IPPROTO_UDP) { 46813b3a8eb9SGleb Smirnoff if (r->src.port_op) { 46823b3a8eb9SGleb Smirnoff yyerror("src port only applies to tcp/udp"); 46833b3a8eb9SGleb Smirnoff problems++; 46843b3a8eb9SGleb Smirnoff } 46853b3a8eb9SGleb Smirnoff if (r->dst.port_op) { 46863b3a8eb9SGleb Smirnoff yyerror("dst port only applies to tcp/udp"); 46873b3a8eb9SGleb Smirnoff problems++; 46883b3a8eb9SGleb Smirnoff } 46893b3a8eb9SGleb Smirnoff if (r->rpool.proxy_port[0]) { 46903b3a8eb9SGleb Smirnoff yyerror("rpool port only applies to tcp/udp"); 46913b3a8eb9SGleb Smirnoff problems++; 46923b3a8eb9SGleb Smirnoff } 46933b3a8eb9SGleb Smirnoff } 46943b3a8eb9SGleb Smirnoff if (r->dst.port_op && 46953b3a8eb9SGleb Smirnoff r->dst.port_op != PF_OP_EQ && r->dst.port_op != PF_OP_RRG) { 46963b3a8eb9SGleb Smirnoff yyerror("invalid port operator for rdr destination port"); 46973b3a8eb9SGleb Smirnoff problems++; 46983b3a8eb9SGleb Smirnoff } 46993b3a8eb9SGleb Smirnoff return (-problems); 47003b3a8eb9SGleb Smirnoff } 47013b3a8eb9SGleb Smirnoff 47023b3a8eb9SGleb Smirnoff int 47033b3a8eb9SGleb Smirnoff process_tabledef(char *name, struct table_opts *opts) 47043b3a8eb9SGleb Smirnoff { 47053b3a8eb9SGleb Smirnoff struct pfr_buffer ab; 47063b3a8eb9SGleb Smirnoff struct node_tinit *ti; 47073b3a8eb9SGleb Smirnoff 47083b3a8eb9SGleb Smirnoff bzero(&ab, sizeof(ab)); 47093b3a8eb9SGleb Smirnoff ab.pfrb_type = PFRB_ADDRS; 47103b3a8eb9SGleb Smirnoff SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) { 47113b3a8eb9SGleb Smirnoff if (ti->file) 47123b3a8eb9SGleb Smirnoff if (pfr_buf_load(&ab, ti->file, 0, append_addr)) { 47133b3a8eb9SGleb Smirnoff if (errno) 47143b3a8eb9SGleb Smirnoff yyerror("cannot load \"%s\": %s", 47153b3a8eb9SGleb Smirnoff ti->file, strerror(errno)); 47163b3a8eb9SGleb Smirnoff else 47173b3a8eb9SGleb Smirnoff yyerror("file \"%s\" contains bad data", 47183b3a8eb9SGleb Smirnoff ti->file); 47193b3a8eb9SGleb Smirnoff goto _error; 47203b3a8eb9SGleb Smirnoff } 47213b3a8eb9SGleb Smirnoff if (ti->host) 47223b3a8eb9SGleb Smirnoff if (append_addr_host(&ab, ti->host, 0, 0)) { 47233b3a8eb9SGleb Smirnoff yyerror("cannot create address buffer: %s", 47243b3a8eb9SGleb Smirnoff strerror(errno)); 47253b3a8eb9SGleb Smirnoff goto _error; 47263b3a8eb9SGleb Smirnoff } 47273b3a8eb9SGleb Smirnoff } 47283b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 47293b3a8eb9SGleb Smirnoff print_tabledef(name, opts->flags, opts->init_addr, 47303b3a8eb9SGleb Smirnoff &opts->init_nodes); 47313b3a8eb9SGleb Smirnoff if (!(pf->opts & PF_OPT_NOACTION) && 47323b3a8eb9SGleb Smirnoff pfctl_define_table(name, opts->flags, opts->init_addr, 47333b3a8eb9SGleb Smirnoff pf->anchor->name, &ab, pf->anchor->ruleset.tticket)) { 47343b3a8eb9SGleb Smirnoff yyerror("cannot define table %s: %s", name, 47353b3a8eb9SGleb Smirnoff pfr_strerror(errno)); 47363b3a8eb9SGleb Smirnoff goto _error; 47373b3a8eb9SGleb Smirnoff } 47383b3a8eb9SGleb Smirnoff pf->tdirty = 1; 47393b3a8eb9SGleb Smirnoff pfr_buf_clear(&ab); 47403b3a8eb9SGleb Smirnoff return (0); 47413b3a8eb9SGleb Smirnoff _error: 47423b3a8eb9SGleb Smirnoff pfr_buf_clear(&ab); 47433b3a8eb9SGleb Smirnoff return (-1); 47443b3a8eb9SGleb Smirnoff } 47453b3a8eb9SGleb Smirnoff 47463b3a8eb9SGleb Smirnoff struct keywords { 47473b3a8eb9SGleb Smirnoff const char *k_name; 47483b3a8eb9SGleb Smirnoff int k_val; 47493b3a8eb9SGleb Smirnoff }; 47503b3a8eb9SGleb Smirnoff 47513b3a8eb9SGleb Smirnoff /* macro gore, but you should've seen the prior indentation nightmare... */ 47523b3a8eb9SGleb Smirnoff 47533b3a8eb9SGleb Smirnoff #define FREE_LIST(T,r) \ 47543b3a8eb9SGleb Smirnoff do { \ 47553b3a8eb9SGleb Smirnoff T *p, *node = r; \ 47563b3a8eb9SGleb Smirnoff while (node != NULL) { \ 47573b3a8eb9SGleb Smirnoff p = node; \ 47583b3a8eb9SGleb Smirnoff node = node->next; \ 47593b3a8eb9SGleb Smirnoff free(p); \ 47603b3a8eb9SGleb Smirnoff } \ 47613b3a8eb9SGleb Smirnoff } while (0) 47623b3a8eb9SGleb Smirnoff 47633b3a8eb9SGleb Smirnoff #define LOOP_THROUGH(T,n,r,C) \ 47643b3a8eb9SGleb Smirnoff do { \ 47653b3a8eb9SGleb Smirnoff T *n; \ 47663b3a8eb9SGleb Smirnoff if (r == NULL) { \ 47673b3a8eb9SGleb Smirnoff r = calloc(1, sizeof(T)); \ 47683b3a8eb9SGleb Smirnoff if (r == NULL) \ 47693b3a8eb9SGleb Smirnoff err(1, "LOOP: calloc"); \ 47703b3a8eb9SGleb Smirnoff r->next = NULL; \ 47713b3a8eb9SGleb Smirnoff } \ 47723b3a8eb9SGleb Smirnoff n = r; \ 47733b3a8eb9SGleb Smirnoff while (n != NULL) { \ 47743b3a8eb9SGleb Smirnoff do { \ 47753b3a8eb9SGleb Smirnoff C; \ 47763b3a8eb9SGleb Smirnoff } while (0); \ 47773b3a8eb9SGleb Smirnoff n = n->next; \ 47783b3a8eb9SGleb Smirnoff } \ 47793b3a8eb9SGleb Smirnoff } while (0) 47803b3a8eb9SGleb Smirnoff 47813b3a8eb9SGleb Smirnoff void 47823b3a8eb9SGleb Smirnoff expand_label_str(char *label, size_t len, const char *srch, const char *repl) 47833b3a8eb9SGleb Smirnoff { 47843b3a8eb9SGleb Smirnoff char *tmp; 47853b3a8eb9SGleb Smirnoff char *p, *q; 47863b3a8eb9SGleb Smirnoff 47873b3a8eb9SGleb Smirnoff if ((tmp = calloc(1, len)) == NULL) 47883b3a8eb9SGleb Smirnoff err(1, "expand_label_str: calloc"); 47893b3a8eb9SGleb Smirnoff p = q = label; 47903b3a8eb9SGleb Smirnoff while ((q = strstr(p, srch)) != NULL) { 47913b3a8eb9SGleb Smirnoff *q = '\0'; 47923b3a8eb9SGleb Smirnoff if ((strlcat(tmp, p, len) >= len) || 47933b3a8eb9SGleb Smirnoff (strlcat(tmp, repl, len) >= len)) 47943b3a8eb9SGleb Smirnoff errx(1, "expand_label: label too long"); 47953b3a8eb9SGleb Smirnoff q += strlen(srch); 47963b3a8eb9SGleb Smirnoff p = q; 47973b3a8eb9SGleb Smirnoff } 47983b3a8eb9SGleb Smirnoff if (strlcat(tmp, p, len) >= len) 47993b3a8eb9SGleb Smirnoff errx(1, "expand_label: label too long"); 48003b3a8eb9SGleb Smirnoff strlcpy(label, tmp, len); /* always fits */ 48013b3a8eb9SGleb Smirnoff free(tmp); 48023b3a8eb9SGleb Smirnoff } 48033b3a8eb9SGleb Smirnoff 48043b3a8eb9SGleb Smirnoff void 48053b3a8eb9SGleb Smirnoff expand_label_if(const char *name, char *label, size_t len, const char *ifname) 48063b3a8eb9SGleb Smirnoff { 48073b3a8eb9SGleb Smirnoff if (strstr(label, name) != NULL) { 48083b3a8eb9SGleb Smirnoff if (!*ifname) 48093b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, "any"); 48103b3a8eb9SGleb Smirnoff else 48113b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, ifname); 48123b3a8eb9SGleb Smirnoff } 48133b3a8eb9SGleb Smirnoff } 48143b3a8eb9SGleb Smirnoff 48153b3a8eb9SGleb Smirnoff void 48163b3a8eb9SGleb Smirnoff expand_label_addr(const char *name, char *label, size_t len, sa_family_t af, 48173b3a8eb9SGleb Smirnoff struct node_host *h) 48183b3a8eb9SGleb Smirnoff { 48193b3a8eb9SGleb Smirnoff char tmp[64], tmp_not[66]; 48203b3a8eb9SGleb Smirnoff 48213b3a8eb9SGleb Smirnoff if (strstr(label, name) != NULL) { 48223b3a8eb9SGleb Smirnoff switch (h->addr.type) { 48233b3a8eb9SGleb Smirnoff case PF_ADDR_DYNIFTL: 48243b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp), "(%s)", h->addr.v.ifname); 48253b3a8eb9SGleb Smirnoff break; 48263b3a8eb9SGleb Smirnoff case PF_ADDR_TABLE: 48273b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp), "<%s>", h->addr.v.tblname); 48283b3a8eb9SGleb Smirnoff break; 48293b3a8eb9SGleb Smirnoff case PF_ADDR_NOROUTE: 48303b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp), "no-route"); 48313b3a8eb9SGleb Smirnoff break; 48323b3a8eb9SGleb Smirnoff case PF_ADDR_URPFFAILED: 48333b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp), "urpf-failed"); 48343b3a8eb9SGleb Smirnoff break; 48353b3a8eb9SGleb Smirnoff case PF_ADDR_ADDRMASK: 48363b3a8eb9SGleb Smirnoff if (!af || (PF_AZERO(&h->addr.v.a.addr, af) && 48373b3a8eb9SGleb Smirnoff PF_AZERO(&h->addr.v.a.mask, af))) 48383b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp), "any"); 48393b3a8eb9SGleb Smirnoff else { 48403b3a8eb9SGleb Smirnoff char a[48]; 48413b3a8eb9SGleb Smirnoff int bits; 48423b3a8eb9SGleb Smirnoff 48433b3a8eb9SGleb Smirnoff if (inet_ntop(af, &h->addr.v.a.addr, a, 48443b3a8eb9SGleb Smirnoff sizeof(a)) == NULL) 48453b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp), "?"); 48463b3a8eb9SGleb Smirnoff else { 48473b3a8eb9SGleb Smirnoff bits = unmask(&h->addr.v.a.mask, af); 48483b3a8eb9SGleb Smirnoff if ((af == AF_INET && bits < 32) || 48493b3a8eb9SGleb Smirnoff (af == AF_INET6 && bits < 128)) 48503b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp), 48513b3a8eb9SGleb Smirnoff "%s/%d", a, bits); 48523b3a8eb9SGleb Smirnoff else 48533b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp), 48543b3a8eb9SGleb Smirnoff "%s", a); 48553b3a8eb9SGleb Smirnoff } 48563b3a8eb9SGleb Smirnoff } 48573b3a8eb9SGleb Smirnoff break; 48583b3a8eb9SGleb Smirnoff default: 48593b3a8eb9SGleb Smirnoff snprintf(tmp, sizeof(tmp), "?"); 48603b3a8eb9SGleb Smirnoff break; 48613b3a8eb9SGleb Smirnoff } 48623b3a8eb9SGleb Smirnoff 48633b3a8eb9SGleb Smirnoff if (h->not) { 48643b3a8eb9SGleb Smirnoff snprintf(tmp_not, sizeof(tmp_not), "! %s", tmp); 48653b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, tmp_not); 48663b3a8eb9SGleb Smirnoff } else 48673b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, tmp); 48683b3a8eb9SGleb Smirnoff } 48693b3a8eb9SGleb Smirnoff } 48703b3a8eb9SGleb Smirnoff 48713b3a8eb9SGleb Smirnoff void 48723b3a8eb9SGleb Smirnoff expand_label_port(const char *name, char *label, size_t len, 48733b3a8eb9SGleb Smirnoff struct node_port *port) 48743b3a8eb9SGleb Smirnoff { 48753b3a8eb9SGleb Smirnoff char a1[6], a2[6], op[13] = ""; 48763b3a8eb9SGleb Smirnoff 48773b3a8eb9SGleb Smirnoff if (strstr(label, name) != NULL) { 48783b3a8eb9SGleb Smirnoff snprintf(a1, sizeof(a1), "%u", ntohs(port->port[0])); 48793b3a8eb9SGleb Smirnoff snprintf(a2, sizeof(a2), "%u", ntohs(port->port[1])); 48803b3a8eb9SGleb Smirnoff if (!port->op) 48813b3a8eb9SGleb Smirnoff ; 48823b3a8eb9SGleb Smirnoff else if (port->op == PF_OP_IRG) 48833b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), "%s><%s", a1, a2); 48843b3a8eb9SGleb Smirnoff else if (port->op == PF_OP_XRG) 48853b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), "%s<>%s", a1, a2); 48863b3a8eb9SGleb Smirnoff else if (port->op == PF_OP_EQ) 48873b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), "%s", a1); 48883b3a8eb9SGleb Smirnoff else if (port->op == PF_OP_NE) 48893b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), "!=%s", a1); 48903b3a8eb9SGleb Smirnoff else if (port->op == PF_OP_LT) 48913b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), "<%s", a1); 48923b3a8eb9SGleb Smirnoff else if (port->op == PF_OP_LE) 48933b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), "<=%s", a1); 48943b3a8eb9SGleb Smirnoff else if (port->op == PF_OP_GT) 48953b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), ">%s", a1); 48963b3a8eb9SGleb Smirnoff else if (port->op == PF_OP_GE) 48973b3a8eb9SGleb Smirnoff snprintf(op, sizeof(op), ">=%s", a1); 48983b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, op); 48993b3a8eb9SGleb Smirnoff } 49003b3a8eb9SGleb Smirnoff } 49013b3a8eb9SGleb Smirnoff 49023b3a8eb9SGleb Smirnoff void 49033b3a8eb9SGleb Smirnoff expand_label_proto(const char *name, char *label, size_t len, u_int8_t proto) 49043b3a8eb9SGleb Smirnoff { 49053b3a8eb9SGleb Smirnoff struct protoent *pe; 49063b3a8eb9SGleb Smirnoff char n[4]; 49073b3a8eb9SGleb Smirnoff 49083b3a8eb9SGleb Smirnoff if (strstr(label, name) != NULL) { 49093b3a8eb9SGleb Smirnoff pe = getprotobynumber(proto); 49103b3a8eb9SGleb Smirnoff if (pe != NULL) 49113b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, pe->p_name); 49123b3a8eb9SGleb Smirnoff else { 49133b3a8eb9SGleb Smirnoff snprintf(n, sizeof(n), "%u", proto); 49143b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, n); 49153b3a8eb9SGleb Smirnoff } 49163b3a8eb9SGleb Smirnoff } 49173b3a8eb9SGleb Smirnoff } 49183b3a8eb9SGleb Smirnoff 49193b3a8eb9SGleb Smirnoff void 49203b3a8eb9SGleb Smirnoff expand_label_nr(const char *name, char *label, size_t len) 49213b3a8eb9SGleb Smirnoff { 49223b3a8eb9SGleb Smirnoff char n[11]; 49233b3a8eb9SGleb Smirnoff 49243b3a8eb9SGleb Smirnoff if (strstr(label, name) != NULL) { 49253b3a8eb9SGleb Smirnoff snprintf(n, sizeof(n), "%u", pf->anchor->match); 49263b3a8eb9SGleb Smirnoff expand_label_str(label, len, name, n); 49273b3a8eb9SGleb Smirnoff } 49283b3a8eb9SGleb Smirnoff } 49293b3a8eb9SGleb Smirnoff 49303b3a8eb9SGleb Smirnoff void 49313b3a8eb9SGleb Smirnoff expand_label(char *label, size_t len, const char *ifname, sa_family_t af, 49323b3a8eb9SGleb Smirnoff struct node_host *src_host, struct node_port *src_port, 49333b3a8eb9SGleb Smirnoff struct node_host *dst_host, struct node_port *dst_port, 49343b3a8eb9SGleb Smirnoff u_int8_t proto) 49353b3a8eb9SGleb Smirnoff { 49363b3a8eb9SGleb Smirnoff expand_label_if("$if", label, len, ifname); 49373b3a8eb9SGleb Smirnoff expand_label_addr("$srcaddr", label, len, af, src_host); 49383b3a8eb9SGleb Smirnoff expand_label_addr("$dstaddr", label, len, af, dst_host); 49393b3a8eb9SGleb Smirnoff expand_label_port("$srcport", label, len, src_port); 49403b3a8eb9SGleb Smirnoff expand_label_port("$dstport", label, len, dst_port); 49413b3a8eb9SGleb Smirnoff expand_label_proto("$proto", label, len, proto); 49423b3a8eb9SGleb Smirnoff expand_label_nr("$nr", label, len); 49433b3a8eb9SGleb Smirnoff } 49443b3a8eb9SGleb Smirnoff 49453b3a8eb9SGleb Smirnoff int 49463b3a8eb9SGleb Smirnoff expand_altq(struct pf_altq *a, struct node_if *interfaces, 49473b3a8eb9SGleb Smirnoff struct node_queue *nqueues, struct node_queue_bw bwspec, 49483b3a8eb9SGleb Smirnoff struct node_queue_opt *opts) 49493b3a8eb9SGleb Smirnoff { 49503b3a8eb9SGleb Smirnoff struct pf_altq pa, pb; 49513b3a8eb9SGleb Smirnoff char qname[PF_QNAME_SIZE]; 49523b3a8eb9SGleb Smirnoff struct node_queue *n; 49533b3a8eb9SGleb Smirnoff struct node_queue_bw bw; 49543b3a8eb9SGleb Smirnoff int errs = 0; 49553b3a8eb9SGleb Smirnoff 49563b3a8eb9SGleb Smirnoff if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) { 49573b3a8eb9SGleb Smirnoff FREE_LIST(struct node_if, interfaces); 49580a70aaf8SLuiz Otavio O Souza if (nqueues) 49593b3a8eb9SGleb Smirnoff FREE_LIST(struct node_queue, nqueues); 49603b3a8eb9SGleb Smirnoff return (0); 49613b3a8eb9SGleb Smirnoff } 49623b3a8eb9SGleb Smirnoff 49633b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_if, interface, interfaces, 49643b3a8eb9SGleb Smirnoff memcpy(&pa, a, sizeof(struct pf_altq)); 49653b3a8eb9SGleb Smirnoff if (strlcpy(pa.ifname, interface->ifname, 49663b3a8eb9SGleb Smirnoff sizeof(pa.ifname)) >= sizeof(pa.ifname)) 49673b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcpy"); 49683b3a8eb9SGleb Smirnoff 49693b3a8eb9SGleb Smirnoff if (interface->not) { 49703b3a8eb9SGleb Smirnoff yyerror("altq on ! <interface> is not supported"); 49713b3a8eb9SGleb Smirnoff errs++; 49723b3a8eb9SGleb Smirnoff } else { 49733b3a8eb9SGleb Smirnoff if (eval_pfaltq(pf, &pa, &bwspec, opts)) 49743b3a8eb9SGleb Smirnoff errs++; 49753b3a8eb9SGleb Smirnoff else 49763b3a8eb9SGleb Smirnoff if (pfctl_add_altq(pf, &pa)) 49773b3a8eb9SGleb Smirnoff errs++; 49783b3a8eb9SGleb Smirnoff 49793b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) { 49803b3a8eb9SGleb Smirnoff print_altq(&pf->paltq->altq, 0, 49813b3a8eb9SGleb Smirnoff &bwspec, opts); 49823b3a8eb9SGleb Smirnoff if (nqueues && nqueues->tail) { 49833b3a8eb9SGleb Smirnoff printf("queue { "); 49843b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_queue, queue, 49853b3a8eb9SGleb Smirnoff nqueues, 49863b3a8eb9SGleb Smirnoff printf("%s ", 49873b3a8eb9SGleb Smirnoff queue->queue); 49883b3a8eb9SGleb Smirnoff ); 49893b3a8eb9SGleb Smirnoff printf("}"); 49903b3a8eb9SGleb Smirnoff } 49913b3a8eb9SGleb Smirnoff printf("\n"); 49923b3a8eb9SGleb Smirnoff } 49933b3a8eb9SGleb Smirnoff 49943b3a8eb9SGleb Smirnoff if (pa.scheduler == ALTQT_CBQ || 49953b3a8eb9SGleb Smirnoff pa.scheduler == ALTQT_HFSC) { 49963b3a8eb9SGleb Smirnoff /* now create a root queue */ 49973b3a8eb9SGleb Smirnoff memset(&pb, 0, sizeof(struct pf_altq)); 49983b3a8eb9SGleb Smirnoff if (strlcpy(qname, "root_", sizeof(qname)) >= 49993b3a8eb9SGleb Smirnoff sizeof(qname)) 50003b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcpy"); 50013b3a8eb9SGleb Smirnoff if (strlcat(qname, interface->ifname, 50023b3a8eb9SGleb Smirnoff sizeof(qname)) >= sizeof(qname)) 50033b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcat"); 50043b3a8eb9SGleb Smirnoff if (strlcpy(pb.qname, qname, 50053b3a8eb9SGleb Smirnoff sizeof(pb.qname)) >= sizeof(pb.qname)) 50063b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcpy"); 50073b3a8eb9SGleb Smirnoff if (strlcpy(pb.ifname, interface->ifname, 50083b3a8eb9SGleb Smirnoff sizeof(pb.ifname)) >= sizeof(pb.ifname)) 50093b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcpy"); 50103b3a8eb9SGleb Smirnoff pb.qlimit = pa.qlimit; 50113b3a8eb9SGleb Smirnoff pb.scheduler = pa.scheduler; 50123b3a8eb9SGleb Smirnoff bw.bw_absolute = pa.ifbandwidth; 50133b3a8eb9SGleb Smirnoff bw.bw_percent = 0; 50143b3a8eb9SGleb Smirnoff if (eval_pfqueue(pf, &pb, &bw, opts)) 50153b3a8eb9SGleb Smirnoff errs++; 50163b3a8eb9SGleb Smirnoff else 50173b3a8eb9SGleb Smirnoff if (pfctl_add_altq(pf, &pb)) 50183b3a8eb9SGleb Smirnoff errs++; 50193b3a8eb9SGleb Smirnoff } 50203b3a8eb9SGleb Smirnoff 50213b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_queue, queue, nqueues, 50223b3a8eb9SGleb Smirnoff n = calloc(1, sizeof(struct node_queue)); 50233b3a8eb9SGleb Smirnoff if (n == NULL) 50243b3a8eb9SGleb Smirnoff err(1, "expand_altq: calloc"); 50253b3a8eb9SGleb Smirnoff if (pa.scheduler == ALTQT_CBQ || 50263b3a8eb9SGleb Smirnoff pa.scheduler == ALTQT_HFSC) 50273b3a8eb9SGleb Smirnoff if (strlcpy(n->parent, qname, 50283b3a8eb9SGleb Smirnoff sizeof(n->parent)) >= 50293b3a8eb9SGleb Smirnoff sizeof(n->parent)) 50303b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcpy"); 50313b3a8eb9SGleb Smirnoff if (strlcpy(n->queue, queue->queue, 50323b3a8eb9SGleb Smirnoff sizeof(n->queue)) >= sizeof(n->queue)) 50333b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcpy"); 50343b3a8eb9SGleb Smirnoff if (strlcpy(n->ifname, interface->ifname, 50353b3a8eb9SGleb Smirnoff sizeof(n->ifname)) >= sizeof(n->ifname)) 50363b3a8eb9SGleb Smirnoff errx(1, "expand_altq: strlcpy"); 50373b3a8eb9SGleb Smirnoff n->scheduler = pa.scheduler; 50383b3a8eb9SGleb Smirnoff n->next = NULL; 50393b3a8eb9SGleb Smirnoff n->tail = n; 50403b3a8eb9SGleb Smirnoff if (queues == NULL) 50413b3a8eb9SGleb Smirnoff queues = n; 50423b3a8eb9SGleb Smirnoff else { 50433b3a8eb9SGleb Smirnoff queues->tail->next = n; 50443b3a8eb9SGleb Smirnoff queues->tail = n; 50453b3a8eb9SGleb Smirnoff } 50463b3a8eb9SGleb Smirnoff ); 50473b3a8eb9SGleb Smirnoff } 50483b3a8eb9SGleb Smirnoff ); 50493b3a8eb9SGleb Smirnoff FREE_LIST(struct node_if, interfaces); 50500a70aaf8SLuiz Otavio O Souza if (nqueues) 50513b3a8eb9SGleb Smirnoff FREE_LIST(struct node_queue, nqueues); 50523b3a8eb9SGleb Smirnoff 50533b3a8eb9SGleb Smirnoff return (errs); 50543b3a8eb9SGleb Smirnoff } 50553b3a8eb9SGleb Smirnoff 50563b3a8eb9SGleb Smirnoff int 50573b3a8eb9SGleb Smirnoff expand_queue(struct pf_altq *a, struct node_if *interfaces, 50583b3a8eb9SGleb Smirnoff struct node_queue *nqueues, struct node_queue_bw bwspec, 50593b3a8eb9SGleb Smirnoff struct node_queue_opt *opts) 50603b3a8eb9SGleb Smirnoff { 50613b3a8eb9SGleb Smirnoff struct node_queue *n, *nq; 50623b3a8eb9SGleb Smirnoff struct pf_altq pa; 50633b3a8eb9SGleb Smirnoff u_int8_t found = 0; 50643b3a8eb9SGleb Smirnoff u_int8_t errs = 0; 50653b3a8eb9SGleb Smirnoff 50663b3a8eb9SGleb Smirnoff if ((pf->loadopt & PFCTL_FLAG_ALTQ) == 0) { 50673b3a8eb9SGleb Smirnoff FREE_LIST(struct node_queue, nqueues); 50683b3a8eb9SGleb Smirnoff return (0); 50693b3a8eb9SGleb Smirnoff } 50703b3a8eb9SGleb Smirnoff 50713b3a8eb9SGleb Smirnoff if (queues == NULL) { 50723b3a8eb9SGleb Smirnoff yyerror("queue %s has no parent", a->qname); 50733b3a8eb9SGleb Smirnoff FREE_LIST(struct node_queue, nqueues); 50743b3a8eb9SGleb Smirnoff return (1); 50753b3a8eb9SGleb Smirnoff } 50763b3a8eb9SGleb Smirnoff 50773b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_if, interface, interfaces, 50783b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_queue, tqueue, queues, 50793b3a8eb9SGleb Smirnoff if (!strncmp(a->qname, tqueue->queue, PF_QNAME_SIZE) && 50803b3a8eb9SGleb Smirnoff (interface->ifname[0] == 0 || 50813b3a8eb9SGleb Smirnoff (!interface->not && !strncmp(interface->ifname, 50823b3a8eb9SGleb Smirnoff tqueue->ifname, IFNAMSIZ)) || 50833b3a8eb9SGleb Smirnoff (interface->not && strncmp(interface->ifname, 50843b3a8eb9SGleb Smirnoff tqueue->ifname, IFNAMSIZ)))) { 50853b3a8eb9SGleb Smirnoff /* found ourself in queues */ 50863b3a8eb9SGleb Smirnoff found++; 50873b3a8eb9SGleb Smirnoff 50883b3a8eb9SGleb Smirnoff memcpy(&pa, a, sizeof(struct pf_altq)); 50893b3a8eb9SGleb Smirnoff 50903b3a8eb9SGleb Smirnoff if (pa.scheduler != ALTQT_NONE && 50913b3a8eb9SGleb Smirnoff pa.scheduler != tqueue->scheduler) { 50923b3a8eb9SGleb Smirnoff yyerror("exactly one scheduler type " 50933b3a8eb9SGleb Smirnoff "per interface allowed"); 50943b3a8eb9SGleb Smirnoff return (1); 50953b3a8eb9SGleb Smirnoff } 50963b3a8eb9SGleb Smirnoff pa.scheduler = tqueue->scheduler; 50973b3a8eb9SGleb Smirnoff 50983b3a8eb9SGleb Smirnoff /* scheduler dependent error checking */ 50993b3a8eb9SGleb Smirnoff switch (pa.scheduler) { 51003b3a8eb9SGleb Smirnoff case ALTQT_PRIQ: 51013b3a8eb9SGleb Smirnoff if (nqueues != NULL) { 51023b3a8eb9SGleb Smirnoff yyerror("priq queues cannot " 51033b3a8eb9SGleb Smirnoff "have child queues"); 51043b3a8eb9SGleb Smirnoff return (1); 51053b3a8eb9SGleb Smirnoff } 51063b3a8eb9SGleb Smirnoff if (bwspec.bw_absolute > 0 || 51073b3a8eb9SGleb Smirnoff bwspec.bw_percent < 100) { 51083b3a8eb9SGleb Smirnoff yyerror("priq doesn't take " 51093b3a8eb9SGleb Smirnoff "bandwidth"); 51103b3a8eb9SGleb Smirnoff return (1); 51113b3a8eb9SGleb Smirnoff } 51123b3a8eb9SGleb Smirnoff break; 51133b3a8eb9SGleb Smirnoff default: 51143b3a8eb9SGleb Smirnoff break; 51153b3a8eb9SGleb Smirnoff } 51163b3a8eb9SGleb Smirnoff 51173b3a8eb9SGleb Smirnoff if (strlcpy(pa.ifname, tqueue->ifname, 51183b3a8eb9SGleb Smirnoff sizeof(pa.ifname)) >= sizeof(pa.ifname)) 51193b3a8eb9SGleb Smirnoff errx(1, "expand_queue: strlcpy"); 51203b3a8eb9SGleb Smirnoff if (strlcpy(pa.parent, tqueue->parent, 51213b3a8eb9SGleb Smirnoff sizeof(pa.parent)) >= sizeof(pa.parent)) 51223b3a8eb9SGleb Smirnoff errx(1, "expand_queue: strlcpy"); 51233b3a8eb9SGleb Smirnoff 51243b3a8eb9SGleb Smirnoff if (eval_pfqueue(pf, &pa, &bwspec, opts)) 51253b3a8eb9SGleb Smirnoff errs++; 51263b3a8eb9SGleb Smirnoff else 51273b3a8eb9SGleb Smirnoff if (pfctl_add_altq(pf, &pa)) 51283b3a8eb9SGleb Smirnoff errs++; 51293b3a8eb9SGleb Smirnoff 51303b3a8eb9SGleb Smirnoff for (nq = nqueues; nq != NULL; nq = nq->next) { 51313b3a8eb9SGleb Smirnoff if (!strcmp(a->qname, nq->queue)) { 51323b3a8eb9SGleb Smirnoff yyerror("queue cannot have " 51333b3a8eb9SGleb Smirnoff "itself as child"); 51343b3a8eb9SGleb Smirnoff errs++; 51353b3a8eb9SGleb Smirnoff continue; 51363b3a8eb9SGleb Smirnoff } 51373b3a8eb9SGleb Smirnoff n = calloc(1, 51383b3a8eb9SGleb Smirnoff sizeof(struct node_queue)); 51393b3a8eb9SGleb Smirnoff if (n == NULL) 51403b3a8eb9SGleb Smirnoff err(1, "expand_queue: calloc"); 51413b3a8eb9SGleb Smirnoff if (strlcpy(n->parent, a->qname, 51423b3a8eb9SGleb Smirnoff sizeof(n->parent)) >= 51433b3a8eb9SGleb Smirnoff sizeof(n->parent)) 51443b3a8eb9SGleb Smirnoff errx(1, "expand_queue strlcpy"); 51453b3a8eb9SGleb Smirnoff if (strlcpy(n->queue, nq->queue, 51463b3a8eb9SGleb Smirnoff sizeof(n->queue)) >= 51473b3a8eb9SGleb Smirnoff sizeof(n->queue)) 51483b3a8eb9SGleb Smirnoff errx(1, "expand_queue strlcpy"); 51493b3a8eb9SGleb Smirnoff if (strlcpy(n->ifname, tqueue->ifname, 51503b3a8eb9SGleb Smirnoff sizeof(n->ifname)) >= 51513b3a8eb9SGleb Smirnoff sizeof(n->ifname)) 51523b3a8eb9SGleb Smirnoff errx(1, "expand_queue strlcpy"); 51533b3a8eb9SGleb Smirnoff n->scheduler = tqueue->scheduler; 51543b3a8eb9SGleb Smirnoff n->next = NULL; 51553b3a8eb9SGleb Smirnoff n->tail = n; 51563b3a8eb9SGleb Smirnoff if (queues == NULL) 51573b3a8eb9SGleb Smirnoff queues = n; 51583b3a8eb9SGleb Smirnoff else { 51593b3a8eb9SGleb Smirnoff queues->tail->next = n; 51603b3a8eb9SGleb Smirnoff queues->tail = n; 51613b3a8eb9SGleb Smirnoff } 51623b3a8eb9SGleb Smirnoff } 51633b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_VERBOSE) && ( 51643b3a8eb9SGleb Smirnoff (found == 1 && interface->ifname[0] == 0) || 51653b3a8eb9SGleb Smirnoff (found > 0 && interface->ifname[0] != 0))) { 51663b3a8eb9SGleb Smirnoff print_queue(&pf->paltq->altq, 0, 51673b3a8eb9SGleb Smirnoff &bwspec, interface->ifname[0] != 0, 51683b3a8eb9SGleb Smirnoff opts); 51693b3a8eb9SGleb Smirnoff if (nqueues && nqueues->tail) { 51703b3a8eb9SGleb Smirnoff printf("{ "); 51713b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_queue, 51723b3a8eb9SGleb Smirnoff queue, nqueues, 51733b3a8eb9SGleb Smirnoff printf("%s ", 51743b3a8eb9SGleb Smirnoff queue->queue); 51753b3a8eb9SGleb Smirnoff ); 51763b3a8eb9SGleb Smirnoff printf("}"); 51773b3a8eb9SGleb Smirnoff } 51783b3a8eb9SGleb Smirnoff printf("\n"); 51793b3a8eb9SGleb Smirnoff } 51803b3a8eb9SGleb Smirnoff } 51813b3a8eb9SGleb Smirnoff ); 51823b3a8eb9SGleb Smirnoff ); 51833b3a8eb9SGleb Smirnoff 51843b3a8eb9SGleb Smirnoff FREE_LIST(struct node_queue, nqueues); 51853b3a8eb9SGleb Smirnoff FREE_LIST(struct node_if, interfaces); 51863b3a8eb9SGleb Smirnoff 51873b3a8eb9SGleb Smirnoff if (!found) { 51883b3a8eb9SGleb Smirnoff yyerror("queue %s has no parent", a->qname); 51893b3a8eb9SGleb Smirnoff errs++; 51903b3a8eb9SGleb Smirnoff } 51913b3a8eb9SGleb Smirnoff 51923b3a8eb9SGleb Smirnoff if (errs) 51933b3a8eb9SGleb Smirnoff return (1); 51943b3a8eb9SGleb Smirnoff else 51953b3a8eb9SGleb Smirnoff return (0); 51963b3a8eb9SGleb Smirnoff } 51973b3a8eb9SGleb Smirnoff 51983b3a8eb9SGleb Smirnoff void 51993b3a8eb9SGleb Smirnoff expand_rule(struct pf_rule *r, 52003b3a8eb9SGleb Smirnoff struct node_if *interfaces, struct node_host *rpool_hosts, 52013b3a8eb9SGleb Smirnoff struct node_proto *protos, struct node_os *src_oses, 52023b3a8eb9SGleb Smirnoff struct node_host *src_hosts, struct node_port *src_ports, 52033b3a8eb9SGleb Smirnoff struct node_host *dst_hosts, struct node_port *dst_ports, 52043b3a8eb9SGleb Smirnoff struct node_uid *uids, struct node_gid *gids, struct node_icmp *icmp_types, 52053b3a8eb9SGleb Smirnoff const char *anchor_call) 52063b3a8eb9SGleb Smirnoff { 52073b3a8eb9SGleb Smirnoff sa_family_t af = r->af; 52083b3a8eb9SGleb Smirnoff int added = 0, error = 0; 52093b3a8eb9SGleb Smirnoff char ifname[IF_NAMESIZE]; 52103b3a8eb9SGleb Smirnoff char label[PF_RULE_LABEL_SIZE]; 52113b3a8eb9SGleb Smirnoff char tagname[PF_TAG_NAME_SIZE]; 52123b3a8eb9SGleb Smirnoff char match_tagname[PF_TAG_NAME_SIZE]; 52133b3a8eb9SGleb Smirnoff struct pf_pooladdr *pa; 52143b3a8eb9SGleb Smirnoff struct node_host *h; 52153b3a8eb9SGleb Smirnoff u_int8_t flags, flagset, keep_state; 52163b3a8eb9SGleb Smirnoff 52173b3a8eb9SGleb Smirnoff if (strlcpy(label, r->label, sizeof(label)) >= sizeof(label)) 52183b3a8eb9SGleb Smirnoff errx(1, "expand_rule: strlcpy"); 52193b3a8eb9SGleb Smirnoff if (strlcpy(tagname, r->tagname, sizeof(tagname)) >= sizeof(tagname)) 52203b3a8eb9SGleb Smirnoff errx(1, "expand_rule: strlcpy"); 52213b3a8eb9SGleb Smirnoff if (strlcpy(match_tagname, r->match_tagname, sizeof(match_tagname)) >= 52223b3a8eb9SGleb Smirnoff sizeof(match_tagname)) 52233b3a8eb9SGleb Smirnoff errx(1, "expand_rule: strlcpy"); 52243b3a8eb9SGleb Smirnoff flags = r->flags; 52253b3a8eb9SGleb Smirnoff flagset = r->flagset; 52263b3a8eb9SGleb Smirnoff keep_state = r->keep_state; 52273b3a8eb9SGleb Smirnoff 52283b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_if, interface, interfaces, 52293b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_proto, proto, protos, 52303b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_icmp, icmp_type, icmp_types, 52313b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_host, src_host, src_hosts, 52323b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_port, src_port, src_ports, 52333b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_os, src_os, src_oses, 52343b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_host, dst_host, dst_hosts, 52353b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_port, dst_port, dst_ports, 52363b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_uid, uid, uids, 52373b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_gid, gid, gids, 52383b3a8eb9SGleb Smirnoff 52393b3a8eb9SGleb Smirnoff r->af = af; 52403b3a8eb9SGleb Smirnoff /* for link-local IPv6 address, interface must match up */ 52413b3a8eb9SGleb Smirnoff if ((r->af && src_host->af && r->af != src_host->af) || 52423b3a8eb9SGleb Smirnoff (r->af && dst_host->af && r->af != dst_host->af) || 52433b3a8eb9SGleb Smirnoff (src_host->af && dst_host->af && 52443b3a8eb9SGleb Smirnoff src_host->af != dst_host->af) || 52453b3a8eb9SGleb Smirnoff (src_host->ifindex && dst_host->ifindex && 52463b3a8eb9SGleb Smirnoff src_host->ifindex != dst_host->ifindex) || 52473b3a8eb9SGleb Smirnoff (src_host->ifindex && *interface->ifname && 52483b3a8eb9SGleb Smirnoff src_host->ifindex != if_nametoindex(interface->ifname)) || 52493b3a8eb9SGleb Smirnoff (dst_host->ifindex && *interface->ifname && 52503b3a8eb9SGleb Smirnoff dst_host->ifindex != if_nametoindex(interface->ifname))) 52513b3a8eb9SGleb Smirnoff continue; 52523b3a8eb9SGleb Smirnoff if (!r->af && src_host->af) 52533b3a8eb9SGleb Smirnoff r->af = src_host->af; 52543b3a8eb9SGleb Smirnoff else if (!r->af && dst_host->af) 52553b3a8eb9SGleb Smirnoff r->af = dst_host->af; 52563b3a8eb9SGleb Smirnoff 52573b3a8eb9SGleb Smirnoff if (*interface->ifname) 52583b3a8eb9SGleb Smirnoff strlcpy(r->ifname, interface->ifname, 52593b3a8eb9SGleb Smirnoff sizeof(r->ifname)); 52603b3a8eb9SGleb Smirnoff else if (if_indextoname(src_host->ifindex, ifname)) 52613b3a8eb9SGleb Smirnoff strlcpy(r->ifname, ifname, sizeof(r->ifname)); 52623b3a8eb9SGleb Smirnoff else if (if_indextoname(dst_host->ifindex, ifname)) 52633b3a8eb9SGleb Smirnoff strlcpy(r->ifname, ifname, sizeof(r->ifname)); 52643b3a8eb9SGleb Smirnoff else 52653b3a8eb9SGleb Smirnoff memset(r->ifname, '\0', sizeof(r->ifname)); 52663b3a8eb9SGleb Smirnoff 52673b3a8eb9SGleb Smirnoff if (strlcpy(r->label, label, sizeof(r->label)) >= 52683b3a8eb9SGleb Smirnoff sizeof(r->label)) 52693b3a8eb9SGleb Smirnoff errx(1, "expand_rule: strlcpy"); 52703b3a8eb9SGleb Smirnoff if (strlcpy(r->tagname, tagname, sizeof(r->tagname)) >= 52713b3a8eb9SGleb Smirnoff sizeof(r->tagname)) 52723b3a8eb9SGleb Smirnoff errx(1, "expand_rule: strlcpy"); 52733b3a8eb9SGleb Smirnoff if (strlcpy(r->match_tagname, match_tagname, 52743b3a8eb9SGleb Smirnoff sizeof(r->match_tagname)) >= sizeof(r->match_tagname)) 52753b3a8eb9SGleb Smirnoff errx(1, "expand_rule: strlcpy"); 52763b3a8eb9SGleb Smirnoff expand_label(r->label, PF_RULE_LABEL_SIZE, r->ifname, r->af, 52773b3a8eb9SGleb Smirnoff src_host, src_port, dst_host, dst_port, proto->proto); 52783b3a8eb9SGleb Smirnoff expand_label(r->tagname, PF_TAG_NAME_SIZE, r->ifname, r->af, 52793b3a8eb9SGleb Smirnoff src_host, src_port, dst_host, dst_port, proto->proto); 52803b3a8eb9SGleb Smirnoff expand_label(r->match_tagname, PF_TAG_NAME_SIZE, r->ifname, 52813b3a8eb9SGleb Smirnoff r->af, src_host, src_port, dst_host, dst_port, 52823b3a8eb9SGleb Smirnoff proto->proto); 52833b3a8eb9SGleb Smirnoff 52843b3a8eb9SGleb Smirnoff error += check_netmask(src_host, r->af); 52853b3a8eb9SGleb Smirnoff error += check_netmask(dst_host, r->af); 52863b3a8eb9SGleb Smirnoff 52873b3a8eb9SGleb Smirnoff r->ifnot = interface->not; 52883b3a8eb9SGleb Smirnoff r->proto = proto->proto; 52893b3a8eb9SGleb Smirnoff r->src.addr = src_host->addr; 52903b3a8eb9SGleb Smirnoff r->src.neg = src_host->not; 52913b3a8eb9SGleb Smirnoff r->src.port[0] = src_port->port[0]; 52923b3a8eb9SGleb Smirnoff r->src.port[1] = src_port->port[1]; 52933b3a8eb9SGleb Smirnoff r->src.port_op = src_port->op; 52943b3a8eb9SGleb Smirnoff r->dst.addr = dst_host->addr; 52953b3a8eb9SGleb Smirnoff r->dst.neg = dst_host->not; 52963b3a8eb9SGleb Smirnoff r->dst.port[0] = dst_port->port[0]; 52973b3a8eb9SGleb Smirnoff r->dst.port[1] = dst_port->port[1]; 52983b3a8eb9SGleb Smirnoff r->dst.port_op = dst_port->op; 52993b3a8eb9SGleb Smirnoff r->uid.op = uid->op; 53003b3a8eb9SGleb Smirnoff r->uid.uid[0] = uid->uid[0]; 53013b3a8eb9SGleb Smirnoff r->uid.uid[1] = uid->uid[1]; 53023b3a8eb9SGleb Smirnoff r->gid.op = gid->op; 53033b3a8eb9SGleb Smirnoff r->gid.gid[0] = gid->gid[0]; 53043b3a8eb9SGleb Smirnoff r->gid.gid[1] = gid->gid[1]; 53053b3a8eb9SGleb Smirnoff r->type = icmp_type->type; 53063b3a8eb9SGleb Smirnoff r->code = icmp_type->code; 53073b3a8eb9SGleb Smirnoff 53083b3a8eb9SGleb Smirnoff if ((keep_state == PF_STATE_MODULATE || 53093b3a8eb9SGleb Smirnoff keep_state == PF_STATE_SYNPROXY) && 53103b3a8eb9SGleb Smirnoff r->proto && r->proto != IPPROTO_TCP) 53113b3a8eb9SGleb Smirnoff r->keep_state = PF_STATE_NORMAL; 53123b3a8eb9SGleb Smirnoff else 53133b3a8eb9SGleb Smirnoff r->keep_state = keep_state; 53143b3a8eb9SGleb Smirnoff 53153b3a8eb9SGleb Smirnoff if (r->proto && r->proto != IPPROTO_TCP) { 53163b3a8eb9SGleb Smirnoff r->flags = 0; 53173b3a8eb9SGleb Smirnoff r->flagset = 0; 53183b3a8eb9SGleb Smirnoff } else { 53193b3a8eb9SGleb Smirnoff r->flags = flags; 53203b3a8eb9SGleb Smirnoff r->flagset = flagset; 53213b3a8eb9SGleb Smirnoff } 53223b3a8eb9SGleb Smirnoff if (icmp_type->proto && r->proto != icmp_type->proto) { 53233b3a8eb9SGleb Smirnoff yyerror("icmp-type mismatch"); 53243b3a8eb9SGleb Smirnoff error++; 53253b3a8eb9SGleb Smirnoff } 53263b3a8eb9SGleb Smirnoff 53273b3a8eb9SGleb Smirnoff if (src_os && src_os->os) { 53283b3a8eb9SGleb Smirnoff r->os_fingerprint = pfctl_get_fingerprint(src_os->os); 53293b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_VERBOSE2) && 53303b3a8eb9SGleb Smirnoff r->os_fingerprint == PF_OSFP_NOMATCH) 53313b3a8eb9SGleb Smirnoff fprintf(stderr, 53323b3a8eb9SGleb Smirnoff "warning: unknown '%s' OS fingerprint\n", 53333b3a8eb9SGleb Smirnoff src_os->os); 53343b3a8eb9SGleb Smirnoff } else { 53353b3a8eb9SGleb Smirnoff r->os_fingerprint = PF_OSFP_ANY; 53363b3a8eb9SGleb Smirnoff } 53373b3a8eb9SGleb Smirnoff 53383b3a8eb9SGleb Smirnoff TAILQ_INIT(&r->rpool.list); 53393b3a8eb9SGleb Smirnoff for (h = rpool_hosts; h != NULL; h = h->next) { 53403b3a8eb9SGleb Smirnoff pa = calloc(1, sizeof(struct pf_pooladdr)); 53413b3a8eb9SGleb Smirnoff if (pa == NULL) 53423b3a8eb9SGleb Smirnoff err(1, "expand_rule: calloc"); 53433b3a8eb9SGleb Smirnoff pa->addr = h->addr; 53443b3a8eb9SGleb Smirnoff if (h->ifname != NULL) { 53453b3a8eb9SGleb Smirnoff if (strlcpy(pa->ifname, h->ifname, 53463b3a8eb9SGleb Smirnoff sizeof(pa->ifname)) >= 53473b3a8eb9SGleb Smirnoff sizeof(pa->ifname)) 53483b3a8eb9SGleb Smirnoff errx(1, "expand_rule: strlcpy"); 53493b3a8eb9SGleb Smirnoff } else 53503b3a8eb9SGleb Smirnoff pa->ifname[0] = 0; 53513b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(&r->rpool.list, pa, entries); 53523b3a8eb9SGleb Smirnoff } 53533b3a8eb9SGleb Smirnoff 53543b3a8eb9SGleb Smirnoff if (rule_consistent(r, anchor_call[0]) < 0 || error) 53553b3a8eb9SGleb Smirnoff yyerror("skipping rule due to errors"); 53563b3a8eb9SGleb Smirnoff else { 53573b3a8eb9SGleb Smirnoff r->nr = pf->astack[pf->asd]->match++; 53583b3a8eb9SGleb Smirnoff pfctl_add_rule(pf, r, anchor_call); 53593b3a8eb9SGleb Smirnoff added++; 53603b3a8eb9SGleb Smirnoff } 53613b3a8eb9SGleb Smirnoff 53623b3a8eb9SGleb Smirnoff )))))))))); 53633b3a8eb9SGleb Smirnoff 53643b3a8eb9SGleb Smirnoff FREE_LIST(struct node_if, interfaces); 53653b3a8eb9SGleb Smirnoff FREE_LIST(struct node_proto, protos); 53663b3a8eb9SGleb Smirnoff FREE_LIST(struct node_host, src_hosts); 53673b3a8eb9SGleb Smirnoff FREE_LIST(struct node_port, src_ports); 53683b3a8eb9SGleb Smirnoff FREE_LIST(struct node_os, src_oses); 53693b3a8eb9SGleb Smirnoff FREE_LIST(struct node_host, dst_hosts); 53703b3a8eb9SGleb Smirnoff FREE_LIST(struct node_port, dst_ports); 53713b3a8eb9SGleb Smirnoff FREE_LIST(struct node_uid, uids); 53723b3a8eb9SGleb Smirnoff FREE_LIST(struct node_gid, gids); 53733b3a8eb9SGleb Smirnoff FREE_LIST(struct node_icmp, icmp_types); 53743b3a8eb9SGleb Smirnoff FREE_LIST(struct node_host, rpool_hosts); 53753b3a8eb9SGleb Smirnoff 53763b3a8eb9SGleb Smirnoff if (!added) 53773b3a8eb9SGleb Smirnoff yyerror("rule expands to no valid combination"); 53783b3a8eb9SGleb Smirnoff } 53793b3a8eb9SGleb Smirnoff 53803b3a8eb9SGleb Smirnoff int 53813b3a8eb9SGleb Smirnoff expand_skip_interface(struct node_if *interfaces) 53823b3a8eb9SGleb Smirnoff { 53833b3a8eb9SGleb Smirnoff int errs = 0; 53843b3a8eb9SGleb Smirnoff 53853b3a8eb9SGleb Smirnoff if (!interfaces || (!interfaces->next && !interfaces->not && 53863b3a8eb9SGleb Smirnoff !strcmp(interfaces->ifname, "none"))) { 53873b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 53883b3a8eb9SGleb Smirnoff printf("set skip on none\n"); 53893b3a8eb9SGleb Smirnoff errs = pfctl_set_interface_flags(pf, "", PFI_IFLAG_SKIP, 0); 53903b3a8eb9SGleb Smirnoff return (errs); 53913b3a8eb9SGleb Smirnoff } 53923b3a8eb9SGleb Smirnoff 53933b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 53943b3a8eb9SGleb Smirnoff printf("set skip on {"); 53953b3a8eb9SGleb Smirnoff LOOP_THROUGH(struct node_if, interface, interfaces, 53963b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 53973b3a8eb9SGleb Smirnoff printf(" %s", interface->ifname); 53983b3a8eb9SGleb Smirnoff if (interface->not) { 53993b3a8eb9SGleb Smirnoff yyerror("skip on ! <interface> is not supported"); 54003b3a8eb9SGleb Smirnoff errs++; 54013b3a8eb9SGleb Smirnoff } else 54023b3a8eb9SGleb Smirnoff errs += pfctl_set_interface_flags(pf, 54033b3a8eb9SGleb Smirnoff interface->ifname, PFI_IFLAG_SKIP, 1); 54043b3a8eb9SGleb Smirnoff ); 54053b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 54063b3a8eb9SGleb Smirnoff printf(" }\n"); 54073b3a8eb9SGleb Smirnoff 54083b3a8eb9SGleb Smirnoff FREE_LIST(struct node_if, interfaces); 54093b3a8eb9SGleb Smirnoff 54103b3a8eb9SGleb Smirnoff if (errs) 54113b3a8eb9SGleb Smirnoff return (1); 54123b3a8eb9SGleb Smirnoff else 54133b3a8eb9SGleb Smirnoff return (0); 54143b3a8eb9SGleb Smirnoff } 54153b3a8eb9SGleb Smirnoff 54163b3a8eb9SGleb Smirnoff #undef FREE_LIST 54173b3a8eb9SGleb Smirnoff #undef LOOP_THROUGH 54183b3a8eb9SGleb Smirnoff 54193b3a8eb9SGleb Smirnoff int 54203b3a8eb9SGleb Smirnoff check_rulestate(int desired_state) 54213b3a8eb9SGleb Smirnoff { 54223b3a8eb9SGleb Smirnoff if (require_order && (rulestate > desired_state)) { 54233b3a8eb9SGleb Smirnoff yyerror("Rules must be in order: options, normalization, " 54243b3a8eb9SGleb Smirnoff "queueing, translation, filtering"); 54253b3a8eb9SGleb Smirnoff return (1); 54263b3a8eb9SGleb Smirnoff } 54273b3a8eb9SGleb Smirnoff rulestate = desired_state; 54283b3a8eb9SGleb Smirnoff return (0); 54293b3a8eb9SGleb Smirnoff } 54303b3a8eb9SGleb Smirnoff 54313b3a8eb9SGleb Smirnoff int 54323b3a8eb9SGleb Smirnoff kw_cmp(const void *k, const void *e) 54333b3a8eb9SGleb Smirnoff { 54343b3a8eb9SGleb Smirnoff return (strcmp(k, ((const struct keywords *)e)->k_name)); 54353b3a8eb9SGleb Smirnoff } 54363b3a8eb9SGleb Smirnoff 54373b3a8eb9SGleb Smirnoff int 54383b3a8eb9SGleb Smirnoff lookup(char *s) 54393b3a8eb9SGleb Smirnoff { 54403b3a8eb9SGleb Smirnoff /* this has to be sorted always */ 54413b3a8eb9SGleb Smirnoff static const struct keywords keywords[] = { 54423b3a8eb9SGleb Smirnoff { "all", ALL}, 54433b3a8eb9SGleb Smirnoff { "allow-opts", ALLOWOPTS}, 54443b3a8eb9SGleb Smirnoff { "altq", ALTQ}, 54453b3a8eb9SGleb Smirnoff { "anchor", ANCHOR}, 54463b3a8eb9SGleb Smirnoff { "antispoof", ANTISPOOF}, 54473b3a8eb9SGleb Smirnoff { "any", ANY}, 54483b3a8eb9SGleb Smirnoff { "bandwidth", BANDWIDTH}, 54493b3a8eb9SGleb Smirnoff { "binat", BINAT}, 54503b3a8eb9SGleb Smirnoff { "binat-anchor", BINATANCHOR}, 54513b3a8eb9SGleb Smirnoff { "bitmask", BITMASK}, 54523b3a8eb9SGleb Smirnoff { "block", BLOCK}, 54533b3a8eb9SGleb Smirnoff { "block-policy", BLOCKPOLICY}, 5454a5b789f6SErmal Luçi { "buckets", BUCKETS}, 54553b3a8eb9SGleb Smirnoff { "cbq", CBQ}, 54563b3a8eb9SGleb Smirnoff { "code", CODE}, 54570a70aaf8SLuiz Otavio O Souza { "codelq", CODEL}, 54583b3a8eb9SGleb Smirnoff { "crop", FRAGCROP}, 54593b3a8eb9SGleb Smirnoff { "debug", DEBUG}, 54603b3a8eb9SGleb Smirnoff { "divert-reply", DIVERTREPLY}, 54613b3a8eb9SGleb Smirnoff { "divert-to", DIVERTTO}, 54623b3a8eb9SGleb Smirnoff { "drop", DROP}, 54633b3a8eb9SGleb Smirnoff { "drop-ovl", FRAGDROP}, 54643b3a8eb9SGleb Smirnoff { "dup-to", DUPTO}, 5465a5b789f6SErmal Luçi { "fairq", FAIRQ}, 54663b3a8eb9SGleb Smirnoff { "fastroute", FASTROUTE}, 54673b3a8eb9SGleb Smirnoff { "file", FILENAME}, 54683b3a8eb9SGleb Smirnoff { "fingerprints", FINGERPRINTS}, 54693b3a8eb9SGleb Smirnoff { "flags", FLAGS}, 54703b3a8eb9SGleb Smirnoff { "floating", FLOATING}, 54713b3a8eb9SGleb Smirnoff { "flush", FLUSH}, 54723b3a8eb9SGleb Smirnoff { "for", FOR}, 54733b3a8eb9SGleb Smirnoff { "fragment", FRAGMENT}, 54743b3a8eb9SGleb Smirnoff { "from", FROM}, 54753b3a8eb9SGleb Smirnoff { "global", GLOBAL}, 54763b3a8eb9SGleb Smirnoff { "group", GROUP}, 54773b3a8eb9SGleb Smirnoff { "hfsc", HFSC}, 5478a5b789f6SErmal Luçi { "hogs", HOGS}, 54793b3a8eb9SGleb Smirnoff { "hostid", HOSTID}, 54803b3a8eb9SGleb Smirnoff { "icmp-type", ICMPTYPE}, 54813b3a8eb9SGleb Smirnoff { "icmp6-type", ICMP6TYPE}, 54823b3a8eb9SGleb Smirnoff { "if-bound", IFBOUND}, 54833b3a8eb9SGleb Smirnoff { "in", IN}, 54843b3a8eb9SGleb Smirnoff { "include", INCLUDE}, 54853b3a8eb9SGleb Smirnoff { "inet", INET}, 54863b3a8eb9SGleb Smirnoff { "inet6", INET6}, 54870a70aaf8SLuiz Otavio O Souza { "interval", INTERVAL}, 54883b3a8eb9SGleb Smirnoff { "keep", KEEP}, 54893b3a8eb9SGleb Smirnoff { "label", LABEL}, 54903b3a8eb9SGleb Smirnoff { "limit", LIMIT}, 54913b3a8eb9SGleb Smirnoff { "linkshare", LINKSHARE}, 54923b3a8eb9SGleb Smirnoff { "load", LOAD}, 54933b3a8eb9SGleb Smirnoff { "log", LOG}, 54943b3a8eb9SGleb Smirnoff { "loginterface", LOGINTERFACE}, 54953b3a8eb9SGleb Smirnoff { "max", MAXIMUM}, 54963b3a8eb9SGleb Smirnoff { "max-mss", MAXMSS}, 54973b3a8eb9SGleb Smirnoff { "max-src-conn", MAXSRCCONN}, 54983b3a8eb9SGleb Smirnoff { "max-src-conn-rate", MAXSRCCONNRATE}, 54993b3a8eb9SGleb Smirnoff { "max-src-nodes", MAXSRCNODES}, 55003b3a8eb9SGleb Smirnoff { "max-src-states", MAXSRCSTATES}, 55013b3a8eb9SGleb Smirnoff { "min-ttl", MINTTL}, 55023b3a8eb9SGleb Smirnoff { "modulate", MODULATE}, 55033b3a8eb9SGleb Smirnoff { "nat", NAT}, 55043b3a8eb9SGleb Smirnoff { "nat-anchor", NATANCHOR}, 55053b3a8eb9SGleb Smirnoff { "no", NO}, 55063b3a8eb9SGleb Smirnoff { "no-df", NODF}, 55073b3a8eb9SGleb Smirnoff { "no-route", NOROUTE}, 55083b3a8eb9SGleb Smirnoff { "no-sync", NOSYNC}, 55093b3a8eb9SGleb Smirnoff { "on", ON}, 55103b3a8eb9SGleb Smirnoff { "optimization", OPTIMIZATION}, 55113b3a8eb9SGleb Smirnoff { "os", OS}, 55123b3a8eb9SGleb Smirnoff { "out", OUT}, 55133b3a8eb9SGleb Smirnoff { "overload", OVERLOAD}, 55143b3a8eb9SGleb Smirnoff { "pass", PASS}, 55153b3a8eb9SGleb Smirnoff { "port", PORT}, 55163e248e0fSKristof Provost { "prio", PRIO}, 55173b3a8eb9SGleb Smirnoff { "priority", PRIORITY}, 55183b3a8eb9SGleb Smirnoff { "priq", PRIQ}, 55193b3a8eb9SGleb Smirnoff { "probability", PROBABILITY}, 55203b3a8eb9SGleb Smirnoff { "proto", PROTO}, 55213b3a8eb9SGleb Smirnoff { "qlimit", QLIMIT}, 55223b3a8eb9SGleb Smirnoff { "queue", QUEUE}, 55233b3a8eb9SGleb Smirnoff { "quick", QUICK}, 55243b3a8eb9SGleb Smirnoff { "random", RANDOM}, 55253b3a8eb9SGleb Smirnoff { "random-id", RANDOMID}, 55263b3a8eb9SGleb Smirnoff { "rdr", RDR}, 55273b3a8eb9SGleb Smirnoff { "rdr-anchor", RDRANCHOR}, 55283b3a8eb9SGleb Smirnoff { "realtime", REALTIME}, 55293b3a8eb9SGleb Smirnoff { "reassemble", REASSEMBLE}, 55303b3a8eb9SGleb Smirnoff { "reply-to", REPLYTO}, 55313b3a8eb9SGleb Smirnoff { "require-order", REQUIREORDER}, 55323b3a8eb9SGleb Smirnoff { "return", RETURN}, 55333b3a8eb9SGleb Smirnoff { "return-icmp", RETURNICMP}, 55343b3a8eb9SGleb Smirnoff { "return-icmp6", RETURNICMP6}, 55353b3a8eb9SGleb Smirnoff { "return-rst", RETURNRST}, 55363b3a8eb9SGleb Smirnoff { "round-robin", ROUNDROBIN}, 55373b3a8eb9SGleb Smirnoff { "route", ROUTE}, 55383b3a8eb9SGleb Smirnoff { "route-to", ROUTETO}, 55393b3a8eb9SGleb Smirnoff { "rtable", RTABLE}, 55403b3a8eb9SGleb Smirnoff { "rule", RULE}, 55413b3a8eb9SGleb Smirnoff { "ruleset-optimization", RULESET_OPTIMIZATION}, 55423b3a8eb9SGleb Smirnoff { "scrub", SCRUB}, 55433b3a8eb9SGleb Smirnoff { "set", SET}, 55443b3a8eb9SGleb Smirnoff { "set-tos", SETTOS}, 55453b3a8eb9SGleb Smirnoff { "skip", SKIP}, 55463b3a8eb9SGleb Smirnoff { "sloppy", SLOPPY}, 55473b3a8eb9SGleb Smirnoff { "source-hash", SOURCEHASH}, 55483b3a8eb9SGleb Smirnoff { "source-track", SOURCETRACK}, 55493b3a8eb9SGleb Smirnoff { "state", STATE}, 55503b3a8eb9SGleb Smirnoff { "state-defaults", STATEDEFAULTS}, 55513b3a8eb9SGleb Smirnoff { "state-policy", STATEPOLICY}, 55523b3a8eb9SGleb Smirnoff { "static-port", STATICPORT}, 55533b3a8eb9SGleb Smirnoff { "sticky-address", STICKYADDRESS}, 55543b3a8eb9SGleb Smirnoff { "synproxy", SYNPROXY}, 55553b3a8eb9SGleb Smirnoff { "table", TABLE}, 55563b3a8eb9SGleb Smirnoff { "tag", TAG}, 55573b3a8eb9SGleb Smirnoff { "tagged", TAGGED}, 55580a70aaf8SLuiz Otavio O Souza { "target", TARGET}, 55593b3a8eb9SGleb Smirnoff { "tbrsize", TBRSIZE}, 55603b3a8eb9SGleb Smirnoff { "timeout", TIMEOUT}, 55613b3a8eb9SGleb Smirnoff { "to", TO}, 55623b3a8eb9SGleb Smirnoff { "tos", TOS}, 55633b3a8eb9SGleb Smirnoff { "ttl", TTL}, 55643b3a8eb9SGleb Smirnoff { "upperlimit", UPPERLIMIT}, 55653b3a8eb9SGleb Smirnoff { "urpf-failed", URPFFAILED}, 55663b3a8eb9SGleb Smirnoff { "user", USER}, 55673b3a8eb9SGleb Smirnoff }; 55683b3a8eb9SGleb Smirnoff const struct keywords *p; 55693b3a8eb9SGleb Smirnoff 55703b3a8eb9SGleb Smirnoff p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]), 55713b3a8eb9SGleb Smirnoff sizeof(keywords[0]), kw_cmp); 55723b3a8eb9SGleb Smirnoff 55733b3a8eb9SGleb Smirnoff if (p) { 55743b3a8eb9SGleb Smirnoff if (debug > 1) 55753b3a8eb9SGleb Smirnoff fprintf(stderr, "%s: %d\n", s, p->k_val); 55763b3a8eb9SGleb Smirnoff return (p->k_val); 55773b3a8eb9SGleb Smirnoff } else { 55783b3a8eb9SGleb Smirnoff if (debug > 1) 55793b3a8eb9SGleb Smirnoff fprintf(stderr, "string: %s\n", s); 55803b3a8eb9SGleb Smirnoff return (STRING); 55813b3a8eb9SGleb Smirnoff } 55823b3a8eb9SGleb Smirnoff } 55833b3a8eb9SGleb Smirnoff 55843b3a8eb9SGleb Smirnoff #define MAXPUSHBACK 128 55853b3a8eb9SGleb Smirnoff 558613cfafabSKristof Provost static char *parsebuf; 558713cfafabSKristof Provost static int parseindex; 558813cfafabSKristof Provost static char pushback_buffer[MAXPUSHBACK]; 558913cfafabSKristof Provost static int pushback_index = 0; 55903b3a8eb9SGleb Smirnoff 55913b3a8eb9SGleb Smirnoff int 55923b3a8eb9SGleb Smirnoff lgetc(int quotec) 55933b3a8eb9SGleb Smirnoff { 55943b3a8eb9SGleb Smirnoff int c, next; 55953b3a8eb9SGleb Smirnoff 55963b3a8eb9SGleb Smirnoff if (parsebuf) { 55973b3a8eb9SGleb Smirnoff /* Read character from the parsebuffer instead of input. */ 55983b3a8eb9SGleb Smirnoff if (parseindex >= 0) { 55993b3a8eb9SGleb Smirnoff c = parsebuf[parseindex++]; 56003b3a8eb9SGleb Smirnoff if (c != '\0') 56013b3a8eb9SGleb Smirnoff return (c); 56023b3a8eb9SGleb Smirnoff parsebuf = NULL; 56033b3a8eb9SGleb Smirnoff } else 56043b3a8eb9SGleb Smirnoff parseindex++; 56053b3a8eb9SGleb Smirnoff } 56063b3a8eb9SGleb Smirnoff 56073b3a8eb9SGleb Smirnoff if (pushback_index) 56083b3a8eb9SGleb Smirnoff return (pushback_buffer[--pushback_index]); 56093b3a8eb9SGleb Smirnoff 56103b3a8eb9SGleb Smirnoff if (quotec) { 56113b3a8eb9SGleb Smirnoff if ((c = getc(file->stream)) == EOF) { 56123b3a8eb9SGleb Smirnoff yyerror("reached end of file while parsing quoted string"); 56133b3a8eb9SGleb Smirnoff if (popfile() == EOF) 56143b3a8eb9SGleb Smirnoff return (EOF); 56153b3a8eb9SGleb Smirnoff return (quotec); 56163b3a8eb9SGleb Smirnoff } 56173b3a8eb9SGleb Smirnoff return (c); 56183b3a8eb9SGleb Smirnoff } 56193b3a8eb9SGleb Smirnoff 56203b3a8eb9SGleb Smirnoff while ((c = getc(file->stream)) == '\\') { 56213b3a8eb9SGleb Smirnoff next = getc(file->stream); 56223b3a8eb9SGleb Smirnoff if (next != '\n') { 56233b3a8eb9SGleb Smirnoff c = next; 56243b3a8eb9SGleb Smirnoff break; 56253b3a8eb9SGleb Smirnoff } 56263b3a8eb9SGleb Smirnoff yylval.lineno = file->lineno; 56273b3a8eb9SGleb Smirnoff file->lineno++; 56283b3a8eb9SGleb Smirnoff } 56293b3a8eb9SGleb Smirnoff 56303b3a8eb9SGleb Smirnoff while (c == EOF) { 56313b3a8eb9SGleb Smirnoff if (popfile() == EOF) 56323b3a8eb9SGleb Smirnoff return (EOF); 56333b3a8eb9SGleb Smirnoff c = getc(file->stream); 56343b3a8eb9SGleb Smirnoff } 56353b3a8eb9SGleb Smirnoff return (c); 56363b3a8eb9SGleb Smirnoff } 56373b3a8eb9SGleb Smirnoff 56383b3a8eb9SGleb Smirnoff int 56393b3a8eb9SGleb Smirnoff lungetc(int c) 56403b3a8eb9SGleb Smirnoff { 56413b3a8eb9SGleb Smirnoff if (c == EOF) 56423b3a8eb9SGleb Smirnoff return (EOF); 56433b3a8eb9SGleb Smirnoff if (parsebuf) { 56443b3a8eb9SGleb Smirnoff parseindex--; 56453b3a8eb9SGleb Smirnoff if (parseindex >= 0) 56463b3a8eb9SGleb Smirnoff return (c); 56473b3a8eb9SGleb Smirnoff } 56483b3a8eb9SGleb Smirnoff if (pushback_index < MAXPUSHBACK-1) 56493b3a8eb9SGleb Smirnoff return (pushback_buffer[pushback_index++] = c); 56503b3a8eb9SGleb Smirnoff else 56513b3a8eb9SGleb Smirnoff return (EOF); 56523b3a8eb9SGleb Smirnoff } 56533b3a8eb9SGleb Smirnoff 56543b3a8eb9SGleb Smirnoff int 56553b3a8eb9SGleb Smirnoff findeol(void) 56563b3a8eb9SGleb Smirnoff { 56573b3a8eb9SGleb Smirnoff int c; 56583b3a8eb9SGleb Smirnoff 56593b3a8eb9SGleb Smirnoff parsebuf = NULL; 56603b3a8eb9SGleb Smirnoff 56613b3a8eb9SGleb Smirnoff /* skip to either EOF or the first real EOL */ 56623b3a8eb9SGleb Smirnoff while (1) { 56633b3a8eb9SGleb Smirnoff if (pushback_index) 56643b3a8eb9SGleb Smirnoff c = pushback_buffer[--pushback_index]; 56653b3a8eb9SGleb Smirnoff else 56663b3a8eb9SGleb Smirnoff c = lgetc(0); 56673b3a8eb9SGleb Smirnoff if (c == '\n') { 56683b3a8eb9SGleb Smirnoff file->lineno++; 56693b3a8eb9SGleb Smirnoff break; 56703b3a8eb9SGleb Smirnoff } 56713b3a8eb9SGleb Smirnoff if (c == EOF) 56723b3a8eb9SGleb Smirnoff break; 56733b3a8eb9SGleb Smirnoff } 56743b3a8eb9SGleb Smirnoff return (ERROR); 56753b3a8eb9SGleb Smirnoff } 56763b3a8eb9SGleb Smirnoff 56773b3a8eb9SGleb Smirnoff int 56783b3a8eb9SGleb Smirnoff yylex(void) 56793b3a8eb9SGleb Smirnoff { 56803b3a8eb9SGleb Smirnoff char buf[8096]; 56813b3a8eb9SGleb Smirnoff char *p, *val; 56823b3a8eb9SGleb Smirnoff int quotec, next, c; 56833b3a8eb9SGleb Smirnoff int token; 56843b3a8eb9SGleb Smirnoff 56853b3a8eb9SGleb Smirnoff top: 56863b3a8eb9SGleb Smirnoff p = buf; 56873b3a8eb9SGleb Smirnoff while ((c = lgetc(0)) == ' ' || c == '\t') 56883b3a8eb9SGleb Smirnoff ; /* nothing */ 56893b3a8eb9SGleb Smirnoff 56903b3a8eb9SGleb Smirnoff yylval.lineno = file->lineno; 56913b3a8eb9SGleb Smirnoff if (c == '#') 56923b3a8eb9SGleb Smirnoff while ((c = lgetc(0)) != '\n' && c != EOF) 56933b3a8eb9SGleb Smirnoff ; /* nothing */ 56943b3a8eb9SGleb Smirnoff if (c == '$' && parsebuf == NULL) { 56953b3a8eb9SGleb Smirnoff while (1) { 56963b3a8eb9SGleb Smirnoff if ((c = lgetc(0)) == EOF) 56973b3a8eb9SGleb Smirnoff return (0); 56983b3a8eb9SGleb Smirnoff 56993b3a8eb9SGleb Smirnoff if (p + 1 >= buf + sizeof(buf) - 1) { 57003b3a8eb9SGleb Smirnoff yyerror("string too long"); 57013b3a8eb9SGleb Smirnoff return (findeol()); 57023b3a8eb9SGleb Smirnoff } 57033b3a8eb9SGleb Smirnoff if (isalnum(c) || c == '_') { 57043b3a8eb9SGleb Smirnoff *p++ = (char)c; 57053b3a8eb9SGleb Smirnoff continue; 57063b3a8eb9SGleb Smirnoff } 57073b3a8eb9SGleb Smirnoff *p = '\0'; 57083b3a8eb9SGleb Smirnoff lungetc(c); 57093b3a8eb9SGleb Smirnoff break; 57103b3a8eb9SGleb Smirnoff } 57113b3a8eb9SGleb Smirnoff val = symget(buf); 57123b3a8eb9SGleb Smirnoff if (val == NULL) { 57133b3a8eb9SGleb Smirnoff yyerror("macro '%s' not defined", buf); 57143b3a8eb9SGleb Smirnoff return (findeol()); 57153b3a8eb9SGleb Smirnoff } 57163b3a8eb9SGleb Smirnoff parsebuf = val; 57173b3a8eb9SGleb Smirnoff parseindex = 0; 57183b3a8eb9SGleb Smirnoff goto top; 57193b3a8eb9SGleb Smirnoff } 57203b3a8eb9SGleb Smirnoff 57213b3a8eb9SGleb Smirnoff switch (c) { 57223b3a8eb9SGleb Smirnoff case '\'': 57233b3a8eb9SGleb Smirnoff case '"': 57243b3a8eb9SGleb Smirnoff quotec = c; 57253b3a8eb9SGleb Smirnoff while (1) { 57263b3a8eb9SGleb Smirnoff if ((c = lgetc(quotec)) == EOF) 57273b3a8eb9SGleb Smirnoff return (0); 57283b3a8eb9SGleb Smirnoff if (c == '\n') { 57293b3a8eb9SGleb Smirnoff file->lineno++; 57303b3a8eb9SGleb Smirnoff continue; 57313b3a8eb9SGleb Smirnoff } else if (c == '\\') { 57323b3a8eb9SGleb Smirnoff if ((next = lgetc(quotec)) == EOF) 57333b3a8eb9SGleb Smirnoff return (0); 57343b3a8eb9SGleb Smirnoff if (next == quotec || c == ' ' || c == '\t') 57353b3a8eb9SGleb Smirnoff c = next; 57363b3a8eb9SGleb Smirnoff else if (next == '\n') 57373b3a8eb9SGleb Smirnoff continue; 57383b3a8eb9SGleb Smirnoff else 57393b3a8eb9SGleb Smirnoff lungetc(next); 57403b3a8eb9SGleb Smirnoff } else if (c == quotec) { 57413b3a8eb9SGleb Smirnoff *p = '\0'; 57423b3a8eb9SGleb Smirnoff break; 57433b3a8eb9SGleb Smirnoff } 57443b3a8eb9SGleb Smirnoff if (p + 1 >= buf + sizeof(buf) - 1) { 57453b3a8eb9SGleb Smirnoff yyerror("string too long"); 57463b3a8eb9SGleb Smirnoff return (findeol()); 57473b3a8eb9SGleb Smirnoff } 57483b3a8eb9SGleb Smirnoff *p++ = (char)c; 57493b3a8eb9SGleb Smirnoff } 57503b3a8eb9SGleb Smirnoff yylval.v.string = strdup(buf); 57513b3a8eb9SGleb Smirnoff if (yylval.v.string == NULL) 57523b3a8eb9SGleb Smirnoff err(1, "yylex: strdup"); 57533b3a8eb9SGleb Smirnoff return (STRING); 57543b3a8eb9SGleb Smirnoff case '<': 57553b3a8eb9SGleb Smirnoff next = lgetc(0); 57563b3a8eb9SGleb Smirnoff if (next == '>') { 57573b3a8eb9SGleb Smirnoff yylval.v.i = PF_OP_XRG; 57583b3a8eb9SGleb Smirnoff return (PORTBINARY); 57593b3a8eb9SGleb Smirnoff } 57603b3a8eb9SGleb Smirnoff lungetc(next); 57613b3a8eb9SGleb Smirnoff break; 57623b3a8eb9SGleb Smirnoff case '>': 57633b3a8eb9SGleb Smirnoff next = lgetc(0); 57643b3a8eb9SGleb Smirnoff if (next == '<') { 57653b3a8eb9SGleb Smirnoff yylval.v.i = PF_OP_IRG; 57663b3a8eb9SGleb Smirnoff return (PORTBINARY); 57673b3a8eb9SGleb Smirnoff } 57683b3a8eb9SGleb Smirnoff lungetc(next); 57693b3a8eb9SGleb Smirnoff break; 57703b3a8eb9SGleb Smirnoff case '-': 57713b3a8eb9SGleb Smirnoff next = lgetc(0); 57723b3a8eb9SGleb Smirnoff if (next == '>') 57733b3a8eb9SGleb Smirnoff return (ARROW); 57743b3a8eb9SGleb Smirnoff lungetc(next); 57753b3a8eb9SGleb Smirnoff break; 57763b3a8eb9SGleb Smirnoff } 57773b3a8eb9SGleb Smirnoff 57783b3a8eb9SGleb Smirnoff #define allowed_to_end_number(x) \ 57793b3a8eb9SGleb Smirnoff (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=') 57803b3a8eb9SGleb Smirnoff 57813b3a8eb9SGleb Smirnoff if (c == '-' || isdigit(c)) { 57823b3a8eb9SGleb Smirnoff do { 57833b3a8eb9SGleb Smirnoff *p++ = c; 57843b3a8eb9SGleb Smirnoff if ((unsigned)(p-buf) >= sizeof(buf)) { 57853b3a8eb9SGleb Smirnoff yyerror("string too long"); 57863b3a8eb9SGleb Smirnoff return (findeol()); 57873b3a8eb9SGleb Smirnoff } 57883b3a8eb9SGleb Smirnoff } while ((c = lgetc(0)) != EOF && isdigit(c)); 57893b3a8eb9SGleb Smirnoff lungetc(c); 57903b3a8eb9SGleb Smirnoff if (p == buf + 1 && buf[0] == '-') 57913b3a8eb9SGleb Smirnoff goto nodigits; 57923b3a8eb9SGleb Smirnoff if (c == EOF || allowed_to_end_number(c)) { 57933b3a8eb9SGleb Smirnoff const char *errstr = NULL; 57943b3a8eb9SGleb Smirnoff 57953b3a8eb9SGleb Smirnoff *p = '\0'; 57963b3a8eb9SGleb Smirnoff yylval.v.number = strtonum(buf, LLONG_MIN, 57973b3a8eb9SGleb Smirnoff LLONG_MAX, &errstr); 57983b3a8eb9SGleb Smirnoff if (errstr) { 57993b3a8eb9SGleb Smirnoff yyerror("\"%s\" invalid number: %s", 58003b3a8eb9SGleb Smirnoff buf, errstr); 58013b3a8eb9SGleb Smirnoff return (findeol()); 58023b3a8eb9SGleb Smirnoff } 58033b3a8eb9SGleb Smirnoff return (NUMBER); 58043b3a8eb9SGleb Smirnoff } else { 58053b3a8eb9SGleb Smirnoff nodigits: 58063b3a8eb9SGleb Smirnoff while (p > buf + 1) 58073b3a8eb9SGleb Smirnoff lungetc(*--p); 58083b3a8eb9SGleb Smirnoff c = *--p; 58093b3a8eb9SGleb Smirnoff if (c == '-') 58103b3a8eb9SGleb Smirnoff return (c); 58113b3a8eb9SGleb Smirnoff } 58123b3a8eb9SGleb Smirnoff } 58133b3a8eb9SGleb Smirnoff 58143b3a8eb9SGleb Smirnoff #define allowed_in_string(x) \ 58153b3a8eb9SGleb Smirnoff (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \ 58163b3a8eb9SGleb Smirnoff x != '{' && x != '}' && x != '<' && x != '>' && \ 58173b3a8eb9SGleb Smirnoff x != '!' && x != '=' && x != '/' && x != '#' && \ 58183b3a8eb9SGleb Smirnoff x != ',')) 58193b3a8eb9SGleb Smirnoff 58203b3a8eb9SGleb Smirnoff if (isalnum(c) || c == ':' || c == '_') { 58213b3a8eb9SGleb Smirnoff do { 58223b3a8eb9SGleb Smirnoff *p++ = c; 58233b3a8eb9SGleb Smirnoff if ((unsigned)(p-buf) >= sizeof(buf)) { 58243b3a8eb9SGleb Smirnoff yyerror("string too long"); 58253b3a8eb9SGleb Smirnoff return (findeol()); 58263b3a8eb9SGleb Smirnoff } 58273b3a8eb9SGleb Smirnoff } while ((c = lgetc(0)) != EOF && (allowed_in_string(c))); 58283b3a8eb9SGleb Smirnoff lungetc(c); 58293b3a8eb9SGleb Smirnoff *p = '\0'; 58303b3a8eb9SGleb Smirnoff if ((token = lookup(buf)) == STRING) 58313b3a8eb9SGleb Smirnoff if ((yylval.v.string = strdup(buf)) == NULL) 58323b3a8eb9SGleb Smirnoff err(1, "yylex: strdup"); 58333b3a8eb9SGleb Smirnoff return (token); 58343b3a8eb9SGleb Smirnoff } 58353b3a8eb9SGleb Smirnoff if (c == '\n') { 58363b3a8eb9SGleb Smirnoff yylval.lineno = file->lineno; 58373b3a8eb9SGleb Smirnoff file->lineno++; 58383b3a8eb9SGleb Smirnoff } 58393b3a8eb9SGleb Smirnoff if (c == EOF) 58403b3a8eb9SGleb Smirnoff return (0); 58413b3a8eb9SGleb Smirnoff return (c); 58423b3a8eb9SGleb Smirnoff } 58433b3a8eb9SGleb Smirnoff 58443b3a8eb9SGleb Smirnoff int 58453b3a8eb9SGleb Smirnoff check_file_secrecy(int fd, const char *fname) 58463b3a8eb9SGleb Smirnoff { 58473b3a8eb9SGleb Smirnoff struct stat st; 58483b3a8eb9SGleb Smirnoff 58493b3a8eb9SGleb Smirnoff if (fstat(fd, &st)) { 58503b3a8eb9SGleb Smirnoff warn("cannot stat %s", fname); 58513b3a8eb9SGleb Smirnoff return (-1); 58523b3a8eb9SGleb Smirnoff } 58533b3a8eb9SGleb Smirnoff if (st.st_uid != 0 && st.st_uid != getuid()) { 58543b3a8eb9SGleb Smirnoff warnx("%s: owner not root or current user", fname); 58553b3a8eb9SGleb Smirnoff return (-1); 58563b3a8eb9SGleb Smirnoff } 58573b3a8eb9SGleb Smirnoff if (st.st_mode & (S_IRWXG | S_IRWXO)) { 58583b3a8eb9SGleb Smirnoff warnx("%s: group/world readable/writeable", fname); 58593b3a8eb9SGleb Smirnoff return (-1); 58603b3a8eb9SGleb Smirnoff } 58613b3a8eb9SGleb Smirnoff return (0); 58623b3a8eb9SGleb Smirnoff } 58633b3a8eb9SGleb Smirnoff 58643b3a8eb9SGleb Smirnoff struct file * 58653b3a8eb9SGleb Smirnoff pushfile(const char *name, int secret) 58663b3a8eb9SGleb Smirnoff { 58673b3a8eb9SGleb Smirnoff struct file *nfile; 58683b3a8eb9SGleb Smirnoff 58693b3a8eb9SGleb Smirnoff if ((nfile = calloc(1, sizeof(struct file))) == NULL || 58703b3a8eb9SGleb Smirnoff (nfile->name = strdup(name)) == NULL) { 58713b3a8eb9SGleb Smirnoff warn("malloc"); 58723b3a8eb9SGleb Smirnoff return (NULL); 58733b3a8eb9SGleb Smirnoff } 58743b3a8eb9SGleb Smirnoff if (TAILQ_FIRST(&files) == NULL && strcmp(nfile->name, "-") == 0) { 58753b3a8eb9SGleb Smirnoff nfile->stream = stdin; 58763b3a8eb9SGleb Smirnoff free(nfile->name); 58773b3a8eb9SGleb Smirnoff if ((nfile->name = strdup("stdin")) == NULL) { 58783b3a8eb9SGleb Smirnoff warn("strdup"); 58793b3a8eb9SGleb Smirnoff free(nfile); 58803b3a8eb9SGleb Smirnoff return (NULL); 58813b3a8eb9SGleb Smirnoff } 58823b3a8eb9SGleb Smirnoff } else if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { 58833b3a8eb9SGleb Smirnoff warn("%s", nfile->name); 58843b3a8eb9SGleb Smirnoff free(nfile->name); 58853b3a8eb9SGleb Smirnoff free(nfile); 58863b3a8eb9SGleb Smirnoff return (NULL); 58873b3a8eb9SGleb Smirnoff } else if (secret && 58883b3a8eb9SGleb Smirnoff check_file_secrecy(fileno(nfile->stream), nfile->name)) { 58893b3a8eb9SGleb Smirnoff fclose(nfile->stream); 58903b3a8eb9SGleb Smirnoff free(nfile->name); 58913b3a8eb9SGleb Smirnoff free(nfile); 58923b3a8eb9SGleb Smirnoff return (NULL); 58933b3a8eb9SGleb Smirnoff } 58943b3a8eb9SGleb Smirnoff nfile->lineno = 1; 58953b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(&files, nfile, entry); 58963b3a8eb9SGleb Smirnoff return (nfile); 58973b3a8eb9SGleb Smirnoff } 58983b3a8eb9SGleb Smirnoff 58993b3a8eb9SGleb Smirnoff int 59003b3a8eb9SGleb Smirnoff popfile(void) 59013b3a8eb9SGleb Smirnoff { 59023b3a8eb9SGleb Smirnoff struct file *prev; 59033b3a8eb9SGleb Smirnoff 59043b3a8eb9SGleb Smirnoff if ((prev = TAILQ_PREV(file, files, entry)) != NULL) { 59053b3a8eb9SGleb Smirnoff prev->errors += file->errors; 59063b3a8eb9SGleb Smirnoff TAILQ_REMOVE(&files, file, entry); 59073b3a8eb9SGleb Smirnoff fclose(file->stream); 59083b3a8eb9SGleb Smirnoff free(file->name); 59093b3a8eb9SGleb Smirnoff free(file); 59103b3a8eb9SGleb Smirnoff file = prev; 59113b3a8eb9SGleb Smirnoff return (0); 59123b3a8eb9SGleb Smirnoff } 59133b3a8eb9SGleb Smirnoff return (EOF); 59143b3a8eb9SGleb Smirnoff } 59153b3a8eb9SGleb Smirnoff 59163b3a8eb9SGleb Smirnoff int 59173b3a8eb9SGleb Smirnoff parse_config(char *filename, struct pfctl *xpf) 59183b3a8eb9SGleb Smirnoff { 59193b3a8eb9SGleb Smirnoff int errors = 0; 59203b3a8eb9SGleb Smirnoff struct sym *sym; 59213b3a8eb9SGleb Smirnoff 59223b3a8eb9SGleb Smirnoff pf = xpf; 59233b3a8eb9SGleb Smirnoff errors = 0; 59243b3a8eb9SGleb Smirnoff rulestate = PFCTL_STATE_NONE; 59253b3a8eb9SGleb Smirnoff returnicmpdefault = (ICMP_UNREACH << 8) | ICMP_UNREACH_PORT; 59263b3a8eb9SGleb Smirnoff returnicmp6default = 59273b3a8eb9SGleb Smirnoff (ICMP6_DST_UNREACH << 8) | ICMP6_DST_UNREACH_NOPORT; 59283b3a8eb9SGleb Smirnoff blockpolicy = PFRULE_DROP; 59293b3a8eb9SGleb Smirnoff require_order = 1; 59303b3a8eb9SGleb Smirnoff 59313b3a8eb9SGleb Smirnoff if ((file = pushfile(filename, 0)) == NULL) { 59323b3a8eb9SGleb Smirnoff warn("cannot open the main config file!"); 59333b3a8eb9SGleb Smirnoff return (-1); 59343b3a8eb9SGleb Smirnoff } 59353b3a8eb9SGleb Smirnoff 59363b3a8eb9SGleb Smirnoff yyparse(); 59373b3a8eb9SGleb Smirnoff errors = file->errors; 59383b3a8eb9SGleb Smirnoff popfile(); 59393b3a8eb9SGleb Smirnoff 59403b3a8eb9SGleb Smirnoff /* Free macros and check which have not been used. */ 59413b3a8eb9SGleb Smirnoff while ((sym = TAILQ_FIRST(&symhead))) { 59423b3a8eb9SGleb Smirnoff if ((pf->opts & PF_OPT_VERBOSE2) && !sym->used) 59433b3a8eb9SGleb Smirnoff fprintf(stderr, "warning: macro '%s' not " 59443b3a8eb9SGleb Smirnoff "used\n", sym->nam); 59453b3a8eb9SGleb Smirnoff free(sym->nam); 59463b3a8eb9SGleb Smirnoff free(sym->val); 59473b3a8eb9SGleb Smirnoff TAILQ_REMOVE(&symhead, sym, entry); 59483b3a8eb9SGleb Smirnoff free(sym); 59493b3a8eb9SGleb Smirnoff } 59503b3a8eb9SGleb Smirnoff 59513b3a8eb9SGleb Smirnoff return (errors ? -1 : 0); 59523b3a8eb9SGleb Smirnoff } 59533b3a8eb9SGleb Smirnoff 59543b3a8eb9SGleb Smirnoff int 59553b3a8eb9SGleb Smirnoff symset(const char *nam, const char *val, int persist) 59563b3a8eb9SGleb Smirnoff { 59573b3a8eb9SGleb Smirnoff struct sym *sym; 59583b3a8eb9SGleb Smirnoff 59593b3a8eb9SGleb Smirnoff for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam); 59603b3a8eb9SGleb Smirnoff sym = TAILQ_NEXT(sym, entry)) 59613b3a8eb9SGleb Smirnoff ; /* nothing */ 59623b3a8eb9SGleb Smirnoff 59633b3a8eb9SGleb Smirnoff if (sym != NULL) { 59643b3a8eb9SGleb Smirnoff if (sym->persist == 1) 59653b3a8eb9SGleb Smirnoff return (0); 59663b3a8eb9SGleb Smirnoff else { 59673b3a8eb9SGleb Smirnoff free(sym->nam); 59683b3a8eb9SGleb Smirnoff free(sym->val); 59693b3a8eb9SGleb Smirnoff TAILQ_REMOVE(&symhead, sym, entry); 59703b3a8eb9SGleb Smirnoff free(sym); 59713b3a8eb9SGleb Smirnoff } 59723b3a8eb9SGleb Smirnoff } 59733b3a8eb9SGleb Smirnoff if ((sym = calloc(1, sizeof(*sym))) == NULL) 59743b3a8eb9SGleb Smirnoff return (-1); 59753b3a8eb9SGleb Smirnoff 59763b3a8eb9SGleb Smirnoff sym->nam = strdup(nam); 59773b3a8eb9SGleb Smirnoff if (sym->nam == NULL) { 59783b3a8eb9SGleb Smirnoff free(sym); 59793b3a8eb9SGleb Smirnoff return (-1); 59803b3a8eb9SGleb Smirnoff } 59813b3a8eb9SGleb Smirnoff sym->val = strdup(val); 59823b3a8eb9SGleb Smirnoff if (sym->val == NULL) { 59833b3a8eb9SGleb Smirnoff free(sym->nam); 59843b3a8eb9SGleb Smirnoff free(sym); 59853b3a8eb9SGleb Smirnoff return (-1); 59863b3a8eb9SGleb Smirnoff } 59873b3a8eb9SGleb Smirnoff sym->used = 0; 59883b3a8eb9SGleb Smirnoff sym->persist = persist; 59893b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(&symhead, sym, entry); 59903b3a8eb9SGleb Smirnoff return (0); 59913b3a8eb9SGleb Smirnoff } 59923b3a8eb9SGleb Smirnoff 59933b3a8eb9SGleb Smirnoff int 59943b3a8eb9SGleb Smirnoff pfctl_cmdline_symset(char *s) 59953b3a8eb9SGleb Smirnoff { 59963b3a8eb9SGleb Smirnoff char *sym, *val; 59973b3a8eb9SGleb Smirnoff int ret; 59983b3a8eb9SGleb Smirnoff 59993b3a8eb9SGleb Smirnoff if ((val = strrchr(s, '=')) == NULL) 60003b3a8eb9SGleb Smirnoff return (-1); 60013b3a8eb9SGleb Smirnoff 60023b3a8eb9SGleb Smirnoff if ((sym = malloc(strlen(s) - strlen(val) + 1)) == NULL) 60033b3a8eb9SGleb Smirnoff err(1, "pfctl_cmdline_symset: malloc"); 60043b3a8eb9SGleb Smirnoff 60053b3a8eb9SGleb Smirnoff strlcpy(sym, s, strlen(s) - strlen(val) + 1); 60063b3a8eb9SGleb Smirnoff 60073b3a8eb9SGleb Smirnoff ret = symset(sym, val + 1, 1); 60083b3a8eb9SGleb Smirnoff free(sym); 60093b3a8eb9SGleb Smirnoff 60103b3a8eb9SGleb Smirnoff return (ret); 60113b3a8eb9SGleb Smirnoff } 60123b3a8eb9SGleb Smirnoff 60133b3a8eb9SGleb Smirnoff char * 60143b3a8eb9SGleb Smirnoff symget(const char *nam) 60153b3a8eb9SGleb Smirnoff { 60163b3a8eb9SGleb Smirnoff struct sym *sym; 60173b3a8eb9SGleb Smirnoff 60183b3a8eb9SGleb Smirnoff TAILQ_FOREACH(sym, &symhead, entry) 60193b3a8eb9SGleb Smirnoff if (strcmp(nam, sym->nam) == 0) { 60203b3a8eb9SGleb Smirnoff sym->used = 1; 60213b3a8eb9SGleb Smirnoff return (sym->val); 60223b3a8eb9SGleb Smirnoff } 60233b3a8eb9SGleb Smirnoff return (NULL); 60243b3a8eb9SGleb Smirnoff } 60253b3a8eb9SGleb Smirnoff 60263b3a8eb9SGleb Smirnoff void 60273b3a8eb9SGleb Smirnoff mv_rules(struct pf_ruleset *src, struct pf_ruleset *dst) 60283b3a8eb9SGleb Smirnoff { 60293b3a8eb9SGleb Smirnoff int i; 60303b3a8eb9SGleb Smirnoff struct pf_rule *r; 60313b3a8eb9SGleb Smirnoff 60323b3a8eb9SGleb Smirnoff for (i = 0; i < PF_RULESET_MAX; ++i) { 60333b3a8eb9SGleb Smirnoff while ((r = TAILQ_FIRST(src->rules[i].active.ptr)) 60343b3a8eb9SGleb Smirnoff != NULL) { 60353b3a8eb9SGleb Smirnoff TAILQ_REMOVE(src->rules[i].active.ptr, r, entries); 60363b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(dst->rules[i].active.ptr, r, entries); 60373b3a8eb9SGleb Smirnoff dst->anchor->match++; 60383b3a8eb9SGleb Smirnoff } 60393b3a8eb9SGleb Smirnoff src->anchor->match = 0; 60403b3a8eb9SGleb Smirnoff while ((r = TAILQ_FIRST(src->rules[i].inactive.ptr)) 60413b3a8eb9SGleb Smirnoff != NULL) { 60423b3a8eb9SGleb Smirnoff TAILQ_REMOVE(src->rules[i].inactive.ptr, r, entries); 60433b3a8eb9SGleb Smirnoff TAILQ_INSERT_TAIL(dst->rules[i].inactive.ptr, 60443b3a8eb9SGleb Smirnoff r, entries); 60453b3a8eb9SGleb Smirnoff } 60463b3a8eb9SGleb Smirnoff } 60473b3a8eb9SGleb Smirnoff } 60483b3a8eb9SGleb Smirnoff 60493b3a8eb9SGleb Smirnoff void 60503b3a8eb9SGleb Smirnoff decide_address_family(struct node_host *n, sa_family_t *af) 60513b3a8eb9SGleb Smirnoff { 60523b3a8eb9SGleb Smirnoff if (*af != 0 || n == NULL) 60533b3a8eb9SGleb Smirnoff return; 60543b3a8eb9SGleb Smirnoff *af = n->af; 60553b3a8eb9SGleb Smirnoff while ((n = n->next) != NULL) { 60563b3a8eb9SGleb Smirnoff if (n->af != *af) { 60573b3a8eb9SGleb Smirnoff *af = 0; 60583b3a8eb9SGleb Smirnoff return; 60593b3a8eb9SGleb Smirnoff } 60603b3a8eb9SGleb Smirnoff } 60613b3a8eb9SGleb Smirnoff } 60623b3a8eb9SGleb Smirnoff 60633b3a8eb9SGleb Smirnoff void 60643b3a8eb9SGleb Smirnoff remove_invalid_hosts(struct node_host **nh, sa_family_t *af) 60653b3a8eb9SGleb Smirnoff { 60663b3a8eb9SGleb Smirnoff struct node_host *n = *nh, *prev = NULL; 60673b3a8eb9SGleb Smirnoff 60683b3a8eb9SGleb Smirnoff while (n != NULL) { 60693b3a8eb9SGleb Smirnoff if (*af && n->af && n->af != *af) { 60703b3a8eb9SGleb Smirnoff /* unlink and free n */ 60713b3a8eb9SGleb Smirnoff struct node_host *next = n->next; 60723b3a8eb9SGleb Smirnoff 60733b3a8eb9SGleb Smirnoff /* adjust tail pointer */ 60743b3a8eb9SGleb Smirnoff if (n == (*nh)->tail) 60753b3a8eb9SGleb Smirnoff (*nh)->tail = prev; 60763b3a8eb9SGleb Smirnoff /* adjust previous node's next pointer */ 60773b3a8eb9SGleb Smirnoff if (prev == NULL) 60783b3a8eb9SGleb Smirnoff *nh = next; 60793b3a8eb9SGleb Smirnoff else 60803b3a8eb9SGleb Smirnoff prev->next = next; 60813b3a8eb9SGleb Smirnoff /* free node */ 60823b3a8eb9SGleb Smirnoff if (n->ifname != NULL) 60833b3a8eb9SGleb Smirnoff free(n->ifname); 60843b3a8eb9SGleb Smirnoff free(n); 60853b3a8eb9SGleb Smirnoff n = next; 60863b3a8eb9SGleb Smirnoff } else { 60873b3a8eb9SGleb Smirnoff if (n->af && !*af) 60883b3a8eb9SGleb Smirnoff *af = n->af; 60893b3a8eb9SGleb Smirnoff prev = n; 60903b3a8eb9SGleb Smirnoff n = n->next; 60913b3a8eb9SGleb Smirnoff } 60923b3a8eb9SGleb Smirnoff } 60933b3a8eb9SGleb Smirnoff } 60943b3a8eb9SGleb Smirnoff 60953b3a8eb9SGleb Smirnoff int 60963b3a8eb9SGleb Smirnoff invalid_redirect(struct node_host *nh, sa_family_t af) 60973b3a8eb9SGleb Smirnoff { 60983b3a8eb9SGleb Smirnoff if (!af) { 60993b3a8eb9SGleb Smirnoff struct node_host *n; 61003b3a8eb9SGleb Smirnoff 61013b3a8eb9SGleb Smirnoff /* tables and dyniftl are ok without an address family */ 61023b3a8eb9SGleb Smirnoff for (n = nh; n != NULL; n = n->next) { 61033b3a8eb9SGleb Smirnoff if (n->addr.type != PF_ADDR_TABLE && 61043b3a8eb9SGleb Smirnoff n->addr.type != PF_ADDR_DYNIFTL) { 61053b3a8eb9SGleb Smirnoff yyerror("address family not given and " 61063b3a8eb9SGleb Smirnoff "translation address expands to multiple " 61073b3a8eb9SGleb Smirnoff "address families"); 61083b3a8eb9SGleb Smirnoff return (1); 61093b3a8eb9SGleb Smirnoff } 61103b3a8eb9SGleb Smirnoff } 61113b3a8eb9SGleb Smirnoff } 61123b3a8eb9SGleb Smirnoff if (nh == NULL) { 61133b3a8eb9SGleb Smirnoff yyerror("no translation address with matching address family " 61143b3a8eb9SGleb Smirnoff "found."); 61153b3a8eb9SGleb Smirnoff return (1); 61163b3a8eb9SGleb Smirnoff } 61173b3a8eb9SGleb Smirnoff return (0); 61183b3a8eb9SGleb Smirnoff } 61193b3a8eb9SGleb Smirnoff 61203b3a8eb9SGleb Smirnoff int 61213b3a8eb9SGleb Smirnoff atoul(char *s, u_long *ulvalp) 61223b3a8eb9SGleb Smirnoff { 61233b3a8eb9SGleb Smirnoff u_long ulval; 61243b3a8eb9SGleb Smirnoff char *ep; 61253b3a8eb9SGleb Smirnoff 61263b3a8eb9SGleb Smirnoff errno = 0; 61273b3a8eb9SGleb Smirnoff ulval = strtoul(s, &ep, 0); 61283b3a8eb9SGleb Smirnoff if (s[0] == '\0' || *ep != '\0') 61293b3a8eb9SGleb Smirnoff return (-1); 61303b3a8eb9SGleb Smirnoff if (errno == ERANGE && ulval == ULONG_MAX) 61313b3a8eb9SGleb Smirnoff return (-1); 61323b3a8eb9SGleb Smirnoff *ulvalp = ulval; 61333b3a8eb9SGleb Smirnoff return (0); 61343b3a8eb9SGleb Smirnoff } 61353b3a8eb9SGleb Smirnoff 61363b3a8eb9SGleb Smirnoff int 61373b3a8eb9SGleb Smirnoff getservice(char *n) 61383b3a8eb9SGleb Smirnoff { 61393b3a8eb9SGleb Smirnoff struct servent *s; 61403b3a8eb9SGleb Smirnoff u_long ulval; 61413b3a8eb9SGleb Smirnoff 61423b3a8eb9SGleb Smirnoff if (atoul(n, &ulval) == 0) { 61433b3a8eb9SGleb Smirnoff if (ulval > 65535) { 61443b3a8eb9SGleb Smirnoff yyerror("illegal port value %lu", ulval); 61453b3a8eb9SGleb Smirnoff return (-1); 61463b3a8eb9SGleb Smirnoff } 61473b3a8eb9SGleb Smirnoff return (htons(ulval)); 61483b3a8eb9SGleb Smirnoff } else { 61493b3a8eb9SGleb Smirnoff s = getservbyname(n, "tcp"); 61503b3a8eb9SGleb Smirnoff if (s == NULL) 61513b3a8eb9SGleb Smirnoff s = getservbyname(n, "udp"); 61523b3a8eb9SGleb Smirnoff if (s == NULL) { 61533b3a8eb9SGleb Smirnoff yyerror("unknown port %s", n); 61543b3a8eb9SGleb Smirnoff return (-1); 61553b3a8eb9SGleb Smirnoff } 61563b3a8eb9SGleb Smirnoff return (s->s_port); 61573b3a8eb9SGleb Smirnoff } 61583b3a8eb9SGleb Smirnoff } 61593b3a8eb9SGleb Smirnoff 61603b3a8eb9SGleb Smirnoff int 61613b3a8eb9SGleb Smirnoff rule_label(struct pf_rule *r, char *s) 61623b3a8eb9SGleb Smirnoff { 61633b3a8eb9SGleb Smirnoff if (s) { 61643b3a8eb9SGleb Smirnoff if (strlcpy(r->label, s, sizeof(r->label)) >= 61653b3a8eb9SGleb Smirnoff sizeof(r->label)) { 61663b3a8eb9SGleb Smirnoff yyerror("rule label too long (max %d chars)", 61673b3a8eb9SGleb Smirnoff sizeof(r->label)-1); 61683b3a8eb9SGleb Smirnoff return (-1); 61693b3a8eb9SGleb Smirnoff } 61703b3a8eb9SGleb Smirnoff } 61713b3a8eb9SGleb Smirnoff return (0); 61723b3a8eb9SGleb Smirnoff } 61733b3a8eb9SGleb Smirnoff 61743b3a8eb9SGleb Smirnoff u_int16_t 61753b3a8eb9SGleb Smirnoff parseicmpspec(char *w, sa_family_t af) 61763b3a8eb9SGleb Smirnoff { 61773b3a8eb9SGleb Smirnoff const struct icmpcodeent *p; 61783b3a8eb9SGleb Smirnoff u_long ulval; 61793b3a8eb9SGleb Smirnoff u_int8_t icmptype; 61803b3a8eb9SGleb Smirnoff 61813b3a8eb9SGleb Smirnoff if (af == AF_INET) 61823b3a8eb9SGleb Smirnoff icmptype = returnicmpdefault >> 8; 61833b3a8eb9SGleb Smirnoff else 61843b3a8eb9SGleb Smirnoff icmptype = returnicmp6default >> 8; 61853b3a8eb9SGleb Smirnoff 61863b3a8eb9SGleb Smirnoff if (atoul(w, &ulval) == -1) { 61873b3a8eb9SGleb Smirnoff if ((p = geticmpcodebyname(icmptype, w, af)) == NULL) { 61883b3a8eb9SGleb Smirnoff yyerror("unknown icmp code %s", w); 61893b3a8eb9SGleb Smirnoff return (0); 61903b3a8eb9SGleb Smirnoff } 61913b3a8eb9SGleb Smirnoff ulval = p->code; 61923b3a8eb9SGleb Smirnoff } 61933b3a8eb9SGleb Smirnoff if (ulval > 255) { 61943b3a8eb9SGleb Smirnoff yyerror("invalid icmp code %lu", ulval); 61953b3a8eb9SGleb Smirnoff return (0); 61963b3a8eb9SGleb Smirnoff } 61973b3a8eb9SGleb Smirnoff return (icmptype << 8 | ulval); 61983b3a8eb9SGleb Smirnoff } 61993b3a8eb9SGleb Smirnoff 62003b3a8eb9SGleb Smirnoff int 62013b3a8eb9SGleb Smirnoff parseport(char *port, struct range *r, int extensions) 62023b3a8eb9SGleb Smirnoff { 62033b3a8eb9SGleb Smirnoff char *p = strchr(port, ':'); 62043b3a8eb9SGleb Smirnoff 62053b3a8eb9SGleb Smirnoff if (p == NULL) { 62063b3a8eb9SGleb Smirnoff if ((r->a = getservice(port)) == -1) 62073b3a8eb9SGleb Smirnoff return (-1); 62083b3a8eb9SGleb Smirnoff r->b = 0; 62093b3a8eb9SGleb Smirnoff r->t = PF_OP_NONE; 62103b3a8eb9SGleb Smirnoff return (0); 62113b3a8eb9SGleb Smirnoff } 62123b3a8eb9SGleb Smirnoff if ((extensions & PPORT_STAR) && !strcmp(p+1, "*")) { 62133b3a8eb9SGleb Smirnoff *p = 0; 62143b3a8eb9SGleb Smirnoff if ((r->a = getservice(port)) == -1) 62153b3a8eb9SGleb Smirnoff return (-1); 62163b3a8eb9SGleb Smirnoff r->b = 0; 62173b3a8eb9SGleb Smirnoff r->t = PF_OP_IRG; 62183b3a8eb9SGleb Smirnoff return (0); 62193b3a8eb9SGleb Smirnoff } 62203b3a8eb9SGleb Smirnoff if ((extensions & PPORT_RANGE)) { 62213b3a8eb9SGleb Smirnoff *p++ = 0; 62223b3a8eb9SGleb Smirnoff if ((r->a = getservice(port)) == -1 || 62233b3a8eb9SGleb Smirnoff (r->b = getservice(p)) == -1) 62243b3a8eb9SGleb Smirnoff return (-1); 62253b3a8eb9SGleb Smirnoff if (r->a == r->b) { 62263b3a8eb9SGleb Smirnoff r->b = 0; 62273b3a8eb9SGleb Smirnoff r->t = PF_OP_NONE; 62283b3a8eb9SGleb Smirnoff } else 62293b3a8eb9SGleb Smirnoff r->t = PF_OP_RRG; 62303b3a8eb9SGleb Smirnoff return (0); 62313b3a8eb9SGleb Smirnoff } 62323b3a8eb9SGleb Smirnoff return (-1); 62333b3a8eb9SGleb Smirnoff } 62343b3a8eb9SGleb Smirnoff 62353b3a8eb9SGleb Smirnoff int 62363b3a8eb9SGleb Smirnoff pfctl_load_anchors(int dev, struct pfctl *pf, struct pfr_buffer *trans) 62373b3a8eb9SGleb Smirnoff { 62383b3a8eb9SGleb Smirnoff struct loadanchors *la; 62393b3a8eb9SGleb Smirnoff 62403b3a8eb9SGleb Smirnoff TAILQ_FOREACH(la, &loadanchorshead, entries) { 62413b3a8eb9SGleb Smirnoff if (pf->opts & PF_OPT_VERBOSE) 62423b3a8eb9SGleb Smirnoff fprintf(stderr, "\nLoading anchor %s from %s\n", 62433b3a8eb9SGleb Smirnoff la->anchorname, la->filename); 62443b3a8eb9SGleb Smirnoff if (pfctl_rules(dev, la->filename, pf->opts, pf->optimize, 62453b3a8eb9SGleb Smirnoff la->anchorname, trans) == -1) 62463b3a8eb9SGleb Smirnoff return (-1); 62473b3a8eb9SGleb Smirnoff } 62483b3a8eb9SGleb Smirnoff 62493b3a8eb9SGleb Smirnoff return (0); 62503b3a8eb9SGleb Smirnoff } 62513b3a8eb9SGleb Smirnoff 62523b3a8eb9SGleb Smirnoff int 62533b3a8eb9SGleb Smirnoff rt_tableid_max(void) 62543b3a8eb9SGleb Smirnoff { 62553b3a8eb9SGleb Smirnoff #ifdef __FreeBSD__ 62563b3a8eb9SGleb Smirnoff int fibs; 62573b3a8eb9SGleb Smirnoff size_t l = sizeof(fibs); 62583b3a8eb9SGleb Smirnoff 62593b3a8eb9SGleb Smirnoff if (sysctlbyname("net.fibs", &fibs, &l, NULL, 0) == -1) 62603b3a8eb9SGleb Smirnoff fibs = 16; /* XXX RT_MAXFIBS, at least limit it some. */ 62613b3a8eb9SGleb Smirnoff /* 62623b3a8eb9SGleb Smirnoff * As the OpenBSD code only compares > and not >= we need to adjust 62633b3a8eb9SGleb Smirnoff * here given we only accept values of 0..n and want to avoid #ifdefs 6264b68ac800SPedro F. Giffuni * in the grammar. 62653b3a8eb9SGleb Smirnoff */ 62663b3a8eb9SGleb Smirnoff return (fibs - 1); 62673b3a8eb9SGleb Smirnoff #else 62683b3a8eb9SGleb Smirnoff return (RT_TABLEID_MAX); 62693b3a8eb9SGleb Smirnoff #endif 62703b3a8eb9SGleb Smirnoff } 6271