Contrary to other rules accepting a single port, this one only works
with unquoted numerical values.

Fix this by simply using the proper grammar;  the impact is limited to
`divert-packet port $port' and easy to test:

        $ printf 'pass divert-packet port %s\n' 80 '"443"' ftp '"domain"' |
        > pfctl -vnf-
        stdin:3: ftp is not a number
        stdin:4: domain is not a number
        $ printf 'pass divert-packet port %s\n' 80 '"443"' ftp '"domain"' |
        > ./obj/pfctl -vnf-
        pass all flags S/SA scrub (reassemble tcp) divert-packet port 80
        pass all flags S/SA scrub (reassemble tcp) divert-packet port 443
        pass all flags S/SA scrub (reassemble tcp) divert-packet port 21
        pass all flags S/SA scrub (reassemble tcp) divert-packet port 53

Port ranges are not accepted, but an error message on a range without
start is missing in general, so add it while here:

        $ printf 'pass divert-to ::1 port :80\n' | pfctl -vnf-
        $ printf 'pass divert-to ::1 port :80\n' | ./obj/pfctl -vnf-
        stdin:1: port is invalid: :80

OK?

Index: parse.y
===================================================================
RCS file: /cvs/src/sbin/pfctl/parse.y,v
retrieving revision 1.689
diff -u -p -r1.689 parse.y
--- parse.y     11 Jan 2019 01:56:54 -0000      1.689
+++ parse.y     30 Jan 2019 21:20:32 -0000
@@ -1990,7 +1990,7 @@ filter_opt        : USER uids {
                        }
                        filter_opts.divert.type = PF_DIVERT_REPLY;
                }
-               | DIVERTPACKET PORT number {
+               | DIVERTPACKET PORT portplain {
                        if (filter_opts.divert.type != PF_DIVERT_NONE) {
                                yyerror("more than one divert option");
                                YYERROR;
@@ -2003,11 +2003,11 @@ filter_opt      : USER uids {
                        if (pf->reassemble & PF_REASS_ENABLED)
                                filter_opts.marker |= FOM_SCRUB_TCP;
 
-                       if ($3 < 1 || $3 > 65535) {
-                               yyerror("invalid divert port");
+                       filter_opts.divert.port = $3.a;
+                       if (!filter_opts.divert.port) {
+                               yyerror("invalid divert port: %u", ntohs($3.a));
                                YYERROR;
                        }
-                       filter_opts.divert.port = htons($3);
                }
                | SCRUB '(' scrub_opts ')' {
                        filter_opts.nodf = $3.nodf;
@@ -5755,6 +5755,7 @@ parseport(char *port, struct range *r, i
                        r->t = PF_OP_RRG;
                return (0);
        }
+       yyerror("port is invalid: %s", port);
        return (-1);
 }
 

Reply via email to