Hi, this adds a -N option to pfctl that turns of dns resolution for all the things where a dns entry is a possible thing, i.e. in rules ("pass in from www.openbsd.org") or table entries.
Its usefull to make sure the configuration will load when DNS is not available. ok? diff --git regress/sbin/pfctl/Makefile regress/sbin/pfctl/Makefile index ff9c38e28a8..80364b8ba14 100644 --- regress/sbin/pfctl/Makefile +++ regress/sbin/pfctl/Makefile @@ -29,6 +29,7 @@ PFOPT=1 2 6 PFIF2IP=1 2 3 PFCHKSUM=1 2 3 PFCMD=1 +PFCMDFAIL=1 MAKEOBJDIRPREFIX= @@ -252,6 +253,32 @@ REGRESS_TARGETS+=pfcmd REGRESS_ROOT_TARGETS+=pfcmd UPDATE_TARGETS+=pfcmd-update +.for n in ${PFCMDFAIL} +PFCMDFAIL_TARGETS+=pfcmdfail${n} +PFCMDFAIL_UPDATES+=pfcmdfail${n}-update + +pfcmdfail${n}: + ${SUDO} pfctl `cat ${.CURDIR}/pfcmdfail${n}.opts` \ + -f - < ${.CURDIR}/pfcmdfail${n}.in 2>&1 | \ + diff -u ${.CURDIR}/pfcmdfail${n}.ok /dev/stdin + +pfcmdfail${n}-update: + if ${SUDO} pfctl `cat ${.CURDIR}/pfcmdfail${n}.opts` \ + -f - < ${.CURDIR}/pfcmdfail${n}.in > \ + ${.CURDIR}/pfcmdfail${n}.ok 2>&1; then \ + true; \ + fi; + +.endfor + +pfcmdfail: ${PFCMDFAIL_TARGETS} +pfcmdfail-update: ${PFCMDFAIL_UPDATES} +NODEFAULT_TARGETS+=pfcmdfail +REGRESS_TARGETS+=pfcmdfail + +REGRESS_ROOT_TARGETS+=pfcmd +UPDATE_TARGETS+=pfcmd-update + .for n in ${PFSETUP} PFSETUP_TARGETS+=pfsetup${n} PFSETUP_UPDATES+=pfsetup${n}-update diff --git regress/sbin/pfctl/pfcmd2.out regress/sbin/pfctl/pfcmd2.out new file mode 100644 index 00000000000..e991e53a580 --- /dev/null +++ regress/sbin/pfctl/pfcmd2.out @@ -0,0 +1,2 @@ +no IP address found for localhost +pfcmd2.in:1: could not parse host specification diff --git regress/sbin/pfctl/pfcmdfail1.in regress/sbin/pfctl/pfcmdfail1.in new file mode 100644 index 00000000000..68d5b071164 --- /dev/null +++ regress/sbin/pfctl/pfcmdfail1.in @@ -0,0 +1 @@ +pass in from localhost diff --git regress/sbin/pfctl/pfcmdfail1.ok regress/sbin/pfctl/pfcmdfail1.ok new file mode 100644 index 00000000000..011baa3283d --- /dev/null +++ regress/sbin/pfctl/pfcmdfail1.ok @@ -0,0 +1,2 @@ +no IP address found for localhost +stdin:1: could not parse host specification diff --git regress/sbin/pfctl/pfcmdfail1.opts regress/sbin/pfctl/pfcmdfail1.opts new file mode 100644 index 00000000000..b641baefa31 --- /dev/null +++ regress/sbin/pfctl/pfcmdfail1.opts @@ -0,0 +1 @@ +-nN diff --git sbin/pfctl/parse.y sbin/pfctl/parse.y index 5ae134e04a2..0cbb2d651be 100644 --- sbin/pfctl/parse.y +++ sbin/pfctl/parse.y @@ -342,7 +342,7 @@ int disallow_table(struct node_host *, const char *); int disallow_urpf_failed(struct node_host *, const char *); int disallow_alias(struct node_host *, const char *); int rule_consistent(struct pf_rule *, int); -int process_tabledef(char *, struct table_opts *); +int process_tabledef(char *, struct table_opts *, int); void expand_label_str(char *, size_t, const char *, const char *); void expand_label_if(const char *, char *, size_t, const char *); void expand_label_addr(const char *, char *, size_t, u_int8_t, @@ -1176,7 +1176,7 @@ tabledef : TABLE '<' STRING '>' table_opts { free($3); YYERROR; } - if (process_tabledef($3, &$5)) { + if (process_tabledef($3, &$5, pf->opts)) { free($3); YYERROR; } @@ -2035,7 +2035,7 @@ filter_opt : USER uids { filter_opts.rtableid = $2; } | DIVERTTO STRING PORT portplain { - if ((filter_opts.divert.addr = host($2)) == NULL) { + if ((filter_opts.divert.addr = host($2, pf->opts)) == NULL) { yyerror("could not parse divert address: %s", $2); free($2); @@ -2670,7 +2670,7 @@ optweight : WEIGHT NUMBER { ; host : STRING { - if (($$ = host($1)) == NULL) { + if (($$ = host($1, pf->opts)) == NULL) { /* error. "any" is handled elsewhere */ free($1); yyerror("could not parse host specification"); @@ -2682,7 +2682,8 @@ host : STRING { | STRING '-' STRING { struct node_host *b, *e; - if ((b = host($1)) == NULL || (e = host($3)) == NULL) { + if ((b = host($1, pf->opts)) == NULL || + (e = host($3, pf->opts)) == NULL) { free($1); free($3); yyerror("could not parse host specification"); @@ -2718,7 +2719,7 @@ host : STRING { if (asprintf(&buf, "%s/%lld", $1, $3) == -1) err(1, "host: asprintf"); free($1); - if (($$ = host(buf)) == NULL) { + if (($$ = host(buf, pf->opts)) == NULL) { /* error. "any" is handled elsewhere */ free(buf); yyerror("could not parse host specification"); @@ -2732,7 +2733,7 @@ host : STRING { /* ie. for 10/8 parsing */ if (asprintf(&buf, "%lld/%lld", $1, $3) == -1) err(1, "host: asprintf"); - if (($$ = host(buf)) == NULL) { + if (($$ = host(buf, pf->opts)) == NULL) { /* error. "any" is handled elsewhere */ free(buf); yyerror("could not parse host specification"); @@ -3722,7 +3723,7 @@ pool_opt : BITMASK { route_host : STRING { /* try to find @if0 address specs */ if (strrchr($1, '@') != NULL) { - if (($$ = host($1)) == NULL) { + if (($$ = host($1, pf->opts)) == NULL) { yyerror("invalid host for route spec"); YYERROR; } @@ -3744,7 +3745,7 @@ route_host : STRING { if (asprintf(&buf, "%s/%s", $1, $3) == -1) err(1, "host: asprintf"); free($1); - if (($$ = host(buf)) == NULL) { + if (($$ = host(buf, pf->opts)) == NULL) { /* error. "any" is handled elsewhere */ free(buf); yyerror("could not parse host specification"); @@ -4080,7 +4081,7 @@ rule_consistent(struct pf_rule *r, int anchor_call) } int -process_tabledef(char *name, struct table_opts *opts) +process_tabledef(char *name, struct table_opts *opts, int popts) { struct pfr_buffer ab; struct node_tinit *ti; @@ -4089,7 +4090,7 @@ process_tabledef(char *name, struct table_opts *opts) ab.pfrb_type = PFRB_ADDRS; SIMPLEQ_FOREACH(ti, &opts->init_nodes, entries) { if (ti->file) - if (pfr_buf_load(&ab, ti->file, 0)) { + if (pfr_buf_load(&ab, ti->file, 0, popts)) { if (errno) yyerror("cannot load \"%s\": %s", ti->file, strerror(errno)); diff --git sbin/pfctl/pfctl.8 sbin/pfctl/pfctl.8 index bd9afd75eaa..7ce6521f13e 100644 --- sbin/pfctl/pfctl.8 +++ sbin/pfctl/pfctl.8 @@ -33,7 +33,7 @@ .Sh SYNOPSIS .Nm pfctl .Bk -words -.Op Fl deghnPqrvz +.Op Fl deghNnPqrvz .Op Fl a Ar anchor .Op Fl D Ar macro Ns = Ns Ar value .Op Fl F Ar modifier @@ -282,6 +282,9 @@ firewall with hostid 00000002 use: .It Fl L Ar statefile Load pf states from the file specified by .Ar statefile . +.It Fl N +No name resolution will be performed. +If a name cannot be resolved without DNS, an error will be reported. .It Fl n Do not actually load rules, just parse them. .It Fl o Ar level diff --git sbin/pfctl/pfctl.c sbin/pfctl/pfctl.c index 281cd939c6e..122797633bd 100644 --- sbin/pfctl/pfctl.c +++ sbin/pfctl/pfctl.c @@ -2238,7 +2238,7 @@ main(int argc, char *argv[]) usage(); while ((ch = getopt(argc, argv, - "a:dD:eqf:F:ghi:k:K:L:no:Pp:R:rS:s:t:T:vV:x:z")) != -1) { + "a:dD:eqf:F:ghi:k:K:L:Nno:Pp:R:rS:s:t:T:vV:x:z")) != -1) { switch (ch) { case 'a': anchoropt = optarg; @@ -2288,6 +2288,9 @@ main(int argc, char *argv[]) src_node_kill[src_node_killers++] = optarg; mode = O_RDWR; break; + case 'N': + opts |= PF_OPT_NODNS; + break; case 'n': opts |= PF_OPT_NOACTION; break; diff --git sbin/pfctl/pfctl.h sbin/pfctl/pfctl.h index 4a276998eb7..1955a7d0f5d 100644 --- sbin/pfctl/pfctl.h +++ sbin/pfctl/pfctl.h @@ -69,7 +69,7 @@ void pfr_buf_clear(struct pfr_buffer *); int pfr_buf_add(struct pfr_buffer *, const void *); void *pfr_buf_next(struct pfr_buffer *, const void *); int pfr_buf_grow(struct pfr_buffer *, int); -int pfr_buf_load(struct pfr_buffer *, char *, int); +int pfr_buf_load(struct pfr_buffer *, char *, int, int); char *pfr_strerror(int); int pfi_get_ifaces(const char *, struct pfi_kif *, int *); int pfi_clr_istats(const char *, int *, int); diff --git sbin/pfctl/pfctl_parser.c sbin/pfctl/pfctl_parser.c index 6844c29c9fe..33b56f8d785 100644 --- sbin/pfctl/pfctl_parser.c +++ sbin/pfctl/pfctl_parser.c @@ -76,7 +76,7 @@ struct node_host *ifa_grouplookup(const char *, int); struct node_host *host_if(const char *, int); struct node_host *host_v4(const char *, int); struct node_host *host_v6(const char *, int); -struct node_host *host_dns(const char *, int, int); +struct node_host *host_dns(const char *, int, int, int); const char *tcpflags = "FSRPAUEW"; @@ -1609,7 +1609,7 @@ ifa_skip_if(const char *filter, struct node_host *p) } struct node_host * -host(const char *s) +host(const char *s, int opts) { struct node_host *h = NULL, *n; int mask = -1, v4mask = 32, v6mask = 128, cont = 1; @@ -1653,7 +1653,8 @@ host(const char *s) cont = 0; /* dns lookup */ - if (cont && (h = host_dns(ps, v4mask, v6mask)) != NULL) + if (cont && (h = host_dns(ps, v4mask, v6mask, + (opts & PF_OPT_NODNS))) != NULL) cont = 0; if (if_name && if_name[0]) @@ -1779,7 +1780,7 @@ host_v6(const char *s, int mask) } struct node_host * -host_dns(const char *s, int v4mask, int v6mask) +host_dns(const char *s, int v4mask, int v6mask, int numeric) { struct addrinfo hints, *res0, *res; struct node_host *n, *h = NULL; @@ -1796,6 +1797,8 @@ host_dns(const char *s, int v4mask, int v6mask) memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; /* DUMMY */ + if (numeric) + hints.ai_flags = AI_NUMERICHOST; error = getaddrinfo(ps, NULL, &hints, &res0); if (error) { free(ps); @@ -1859,7 +1862,7 @@ host_dns(const char *s, int v4mask, int v6mask) * if set to 1, only simple addresses are accepted (no netblock, no "!"). */ int -append_addr(struct pfr_buffer *b, char *s, int test) +append_addr(struct pfr_buffer *b, char *s, int test, int opts) { static int previous = 0; static int expect = 0; @@ -1899,7 +1902,7 @@ append_addr(struct pfr_buffer *b, char *s, int test) for (r = s; *r == '!'; r++) not = !not; - if ((n = host(r)) == NULL) { + if ((n = host(r, opts)) == NULL) { errno = 0; return (-1); } diff --git sbin/pfctl/pfctl_parser.h sbin/pfctl/pfctl_parser.h index 89d9fc4d2d4..803794d5c82 100644 --- sbin/pfctl/pfctl_parser.h +++ sbin/pfctl/pfctl_parser.h @@ -48,6 +48,7 @@ #define PF_OPT_DEBUG 0x0200 #define PF_OPT_SHOWALL 0x0400 #define PF_OPT_OPTIMIZE 0x0800 +#define PF_OPT_NODNS 0x1000 #define PF_OPT_RECURSE 0x4000 #define PF_OPT_PORTNAMES 0x8000 @@ -280,9 +281,9 @@ unsigned int ifa_nametoindex(const char *); char *ifa_indextoname(unsigned int, char *); struct node_host *ifa_exists(const char *); struct node_host *ifa_lookup(const char *, int); -struct node_host *host(const char *); +struct node_host *host(const char *, int); -int append_addr(struct pfr_buffer *, char *, int); +int append_addr(struct pfr_buffer *, char *, int, int); int append_addr_host(struct pfr_buffer *, struct node_host *, int, int); diff --git sbin/pfctl/pfctl_radix.c sbin/pfctl/pfctl_radix.c index a43c469e40f..a07f01bcf78 100644 --- sbin/pfctl/pfctl_radix.c +++ sbin/pfctl/pfctl_radix.c @@ -496,7 +496,7 @@ pfr_buf_clear(struct pfr_buffer *b) } int -pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork) +pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork, int opts) { FILE *fp; char buf[BUF_SIZE]; @@ -513,7 +513,7 @@ pfr_buf_load(struct pfr_buffer *b, char *file, int nonetwork) return (-1); } while ((rv = pfr_next_token(buf, fp)) == 1) - if ((ev = append_addr(b, buf, nonetwork)) == -1) { + if ((ev = append_addr(b, buf, nonetwork, opts)) == -1) { rv = -1; break; } diff --git sbin/pfctl/pfctl_table.c sbin/pfctl/pfctl_table.c index 0e2f81d888e..9308bbcea9b 100644 --- sbin/pfctl/pfctl_table.c +++ sbin/pfctl/pfctl_table.c @@ -58,7 +58,7 @@ static int pfctl_table(int, char *[], char *, const char *, char *, const char *, int); static void print_table(struct pfr_table *, int, int); static void print_tstats(struct pfr_tstats *, int); -static int load_addr(struct pfr_buffer *, int, char *[], char *, int); +static int load_addr(struct pfr_buffer *, int, char *[], char *, int, int); static void print_addrx(struct pfr_addr *, struct pfr_addr *, int); static void print_astats(struct pfr_astats *, int); static void radix_perror(void); @@ -199,7 +199,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command, xprintf(opts, "%d addresses deleted", ndel); } else if (!strcmp(command, "add")) { b.pfrb_type = PFRB_ADDRS; - if (load_addr(&b, argc, argv, file, 0)) + if (load_addr(&b, argc, argv, file, 0, opts)) goto _error; CREATE_TABLE; if (opts & PF_OPT_VERBOSE) @@ -214,7 +214,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command, opts & PF_OPT_USEDNS); } else if (!strcmp(command, "delete")) { b.pfrb_type = PFRB_ADDRS; - if (load_addr(&b, argc, argv, file, 0)) + if (load_addr(&b, argc, argv, file, 0, opts)) goto _error; if (opts & PF_OPT_VERBOSE) flags |= PFR_FLAG_FEEDBACK; @@ -228,7 +228,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command, opts & PF_OPT_USEDNS); } else if (!strcmp(command, "replace")) { b.pfrb_type = PFRB_ADDRS; - if (load_addr(&b, argc, argv, file, 0)) + if (load_addr(&b, argc, argv, file, 0, opts)) goto _error; CREATE_TABLE; if (opts & PF_OPT_VERBOSE) @@ -321,7 +321,7 @@ pfctl_table(int argc, char *argv[], char *tname, const char *command, b.pfrb_type = PFRB_ADDRS; b2.pfrb_type = PFRB_ADDRS; - if (load_addr(&b, argc, argv, file, 1)) + if (load_addr(&b, argc, argv, file, 1, opts)) goto _error; if (opts & PF_OPT_VERBOSE2) { flags |= PFR_FLAG_REPLACE; @@ -413,11 +413,11 @@ print_tstats(struct pfr_tstats *ts, int debug) int load_addr(struct pfr_buffer *b, int argc, char *argv[], char *file, - int nonetwork) + int nonetwork, int opts) { int ev = 0; while (argc--) - if ((ev = append_addr(b, *argv++, nonetwork)) == -1) { + if ((ev = append_addr(b, *argv++, nonetwork, opts)) == -1) { if (errno) warn("cannot decode %s", argv[-1]); return (-1); @@ -426,7 +426,7 @@ load_addr(struct pfr_buffer *b, int argc, char *argv[], char *file, warnx("failed to decode %s", argv[-1]); return (-1); } - if (pfr_buf_load(b, file, nonetwork)) { + if (pfr_buf_load(b, file, nonetwork, opts)) { warn("cannot load %s", file); return (-1); }