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);
        }

Reply via email to