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