Summary: This diff introduces a -P flag to pfctl for situations when
it is helpful to display all ports as numbers in "pfctl -sr" output.

Details:

When writing firewall rules or troubleshooting tricky network
issues, it is often helpful to confirm that the loaded PF ruleset
actually matches the original rules specified in pf.conf.

However, the current behavior of "pfctl -sr" of showing ports as
names (e.g. port 80 is printed as "port = www") makes it challenging
to do this confirmation, especially if the rules in pf.conf specify
ports as numbers.

For example, suppose we have loaded the following sample pf.conf
where all the ports are written as numbers:

# cat pf.conf
block in quick on em0 proto tcp to port 445
block in quick on em0 proto tcp to port 139
block in quick on em0 proto tcp to port 3031
pass in on em0 proto tcp from port 5680 to port 521
pass in on em0 proto tcp to port 4399
pass in on em0 proto tcp to port 80
pass in on em0 proto tcp to port 2817

"pfctl -sr" will show the ports according to their names in
/etc/services if available:

# pfctl -f pf.conf
# pfctl -sr
block drop in quick on em0 proto tcp from any to any port = microsoft-ds
block drop in quick on em0 proto tcp from any to any port = netbios-ssn
block drop in quick on em0 proto tcp from any to any port = eppc
pass in on em0 proto tcp from any port = canna to any port = efs flags S/SA 
keep state
pass in on em0 proto tcp from any to any port = 4399 flags S/SA keep state
pass in on em0 proto tcp from any to any port = www flags S/SA keep state
pass in on em0 proto tcp from any to any port = 2817 flags S/SA keep state

It is unclear from the above output whether the loaded ruleset
matches the original pf.conf, especially for less familiar ports
like ports 3031 and 5680, which are shown as "eppc" and "canna".

To resolve this, the attached diff introduces a -P flag to pfctl
that is useful in situations when it would be helpful to see the
ports as numbers:

# pfctl -P -sr
block drop in quick on em0 proto tcp from any to any port = 445
block drop in quick on em0 proto tcp from any to any port = 139
block drop in quick on em0 proto tcp from any to any port = 3031
pass in on em0 proto tcp from any port = 5680 to any port = 521 flags S/SA keep 
state
pass in on em0 proto tcp from any to any port = 4399 flags S/SA keep state
pass in on em0 proto tcp from any to any port = 80 flags S/SA keep state
pass in on em0 proto tcp from any to any port = 2817 flags S/SA keep state

A note on the diff: To implement this, I had to pass the opts
variable that represents various pfctl command-line options all the
way to print_port(). I wanted to preserve the convention of letting
this opts variable be the last argument in almost all functions in
pfctl.c. Since print_rule() also has a local variable named opts, I
chose to rename print_rule()'s local opts variable to rule_opts, so
that I can keep this convention.

Does anyone have thoughts or comments on this diff? I am open to
feedback and suggestions for improvement.

Thank you,
Lawrence


Index: pfctl.8
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl.8,v
retrieving revision 1.154
diff -u -p -r1.154 pfctl.8
--- pfctl.8     23 Apr 2011 10:14:59 -0000      1.154
+++ pfctl.8     24 May 2011 00:51:35 -0000
@@ -33,7 +33,7 @@
 .Sh SYNOPSIS
 .Nm pfctl
 .Bk -words
-.Op Fl deghnqrvz
+.Op Fl deghnPqrvz
 .Op Fl a Ar anchor
 .Op Fl D Ar macro Ns = Ns Ar value
 .Op Fl F Ar modifier
@@ -325,6 +325,9 @@ Enable basic ruleset optimizations with 
 .El
 For further information on the ruleset optimizer, see
 .Xr pf.conf 5 .
+.It Fl P
+Always print ports as numbers, even if names exist for them in
+.Pa /etc/services .
 .It Fl p Ar device
 Use the device file
 .Ar device
Index: pfctl.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl.c,v
retrieving revision 1.303
diff -u -p -r1.303 pfctl.c
--- pfctl.c     1 Oct 2010 12:33:14 -0000       1.303
+++ pfctl.c     24 May 2011 00:51:35 -0000
@@ -232,7 +232,7 @@ usage(void)
 {
        extern char *__progname;
 
-       fprintf(stderr, "usage: %s [-deghnqrvz] ", __progname);
+       fprintf(stderr, "usage: %s [-deghnPqrvz] ", __progname);
        fprintf(stderr, "[-a anchor] [-D macro=value] [-F modifier]\n");
        fprintf(stderr, "\t[-f file] [-i interface] [-K host | network]\n");
        fprintf(stderr, "\t[-k host | network | label | id] ");
@@ -884,7 +884,7 @@ pfctl_show_rules(int dev, char *path, in
                        if (pr.rule.label[0] && (opts & PF_OPT_SHOWALL))
                                labels = 1;
                        INDENT(depth, !(opts & PF_OPT_VERBOSE));
-                       print_rule(&pr.rule, pr.anchor_call, rule_numbers);
+                       print_rule(&pr.rule, pr.anchor_call, rule_numbers, 
opts);
 
                        /*
                         * If this is a 'unnamed' brace notation
@@ -1232,7 +1232,7 @@ pfctl_load_rule(struct pfctl *pf, char *
 
        if (pf->opts & PF_OPT_VERBOSE) {
                INDENT(depth, !(pf->opts & PF_OPT_VERBOSE2));
-               print_rule(r, name, pf->opts & PF_OPT_VERBOSE2);
+               print_rule(r, name, pf->opts & PF_OPT_VERBOSE2, pf->opts);
        }
        path[len] = '\0';
        return (0);
@@ -1948,7 +1948,7 @@ main(int argc, char *argv[])
                usage();
 
        while ((ch = getopt(argc, argv,
-           "a:dD:eqf:F:ghi:k:K:L:no:p:R:rS:s:t:T:vx:z")) != -1) {
+           "a:dD:eqf:F:ghi:k:K:L:no:Pp:R:rS:s:t:T:vx:z")) != -1) {
                switch (ch) {
                case 'a':
                        anchoropt = optarg;
@@ -2026,6 +2026,9 @@ main(int argc, char *argv[])
                        }
                        opts |= PF_OPT_OPTIMIZE;
                        break;
+               case 'P':
+                       opts |= PF_OPT_NUMERICPORTS;
+                       break;
                case 'p':
                        pf_device = optarg;
                        break;
Index: pfctl_parser.c
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl_parser.c,v
retrieving revision 1.275
diff -u -p -r1.275 pfctl_parser.c
--- pfctl_parser.c      6 Apr 2011 13:19:55 -0000       1.275
+++ pfctl_parser.c      24 May 2011 00:51:36 -0000
@@ -63,11 +63,11 @@
 #include "pfctl.h"
 
 void            print_op (u_int8_t, const char *, const char *);
-void            print_port (u_int8_t, u_int16_t, u_int16_t, const char *);
+void            print_port (u_int8_t, u_int16_t, u_int16_t, const char *, int);
 void            print_ugid (u_int8_t, unsigned, unsigned, const char *, 
unsigned);
 void            print_flags (u_int8_t);
 void            print_fromto(struct pf_rule_addr *, pf_osfp_t,
-                   struct pf_rule_addr *, u_int8_t, u_int8_t, int);
+                   struct pf_rule_addr *, u_int8_t, u_int8_t, int, int);
 int             ifa_skip_if(const char *filter, struct node_host *p);
 
 struct node_host       *ifa_grouplookup(const char *, int);
@@ -360,12 +360,13 @@ print_op(u_int8_t op, const char *a1, co
 }
 
 void
-print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto)
+print_port(u_int8_t op, u_int16_t p1, u_int16_t p2, const char *proto, int 
opts)
 {
        char             a1[6], a2[6];
-       struct servent  *s;
+       struct servent  *s = NULL;
 
-       s = getservbyport(p1, proto);
+       if (!(opts & PF_OPT_NUMERICPORTS))
+               s = getservbyport(p1, proto);
        p1 = ntohs(p1);
        p2 = ntohs(p2);
        snprintf(a1, sizeof(a1), "%u", p1);
@@ -403,7 +404,7 @@ print_flags(u_int8_t f)
 
 void
 print_fromto(struct pf_rule_addr *src, pf_osfp_t osfp, struct pf_rule_addr 
*dst,
-    sa_family_t af, u_int8_t proto, int verbose)
+    sa_family_t af, u_int8_t proto, int verbose, int opts)
 {
        char buf[PF_OSFP_LEN*3];
        if (src->addr.type == PF_ADDR_ADDRMASK &&
@@ -424,7 +425,7 @@ print_fromto(struct pf_rule_addr *src, p
                if (src->port_op)
                        print_port(src->port_op, src->port[0],
                            src->port[1],
-                           proto == IPPROTO_TCP ? "tcp" : "udp");
+                           proto == IPPROTO_TCP ? "tcp" : "udp", opts);
                if (osfp != PF_OSFP_ANY)
                        printf(" os \"%s\"", pfctl_lookup_fingerprint(osfp, buf,
                            sizeof(buf)));
@@ -436,7 +437,7 @@ print_fromto(struct pf_rule_addr *src, p
                if (dst->port_op)
                        print_port(dst->port_op, dst->port[0],
                            dst->port[1],
-                           proto == IPPROTO_TCP ? "tcp" : "udp");
+                           proto == IPPROTO_TCP ? "tcp" : "udp", opts);
        }
 }
 
@@ -671,7 +672,7 @@ print_src_node(struct pf_src_node *sn, i
 }
 
 void
-print_rule(struct pf_rule *r, const char *anchor_call, int verbose)
+print_rule(struct pf_rule *r, const char *anchor_call, int verbose, int opts)
 {
        static const char *actiontypes[] = { "pass", "block", "scrub",
            "no scrub", "nat", "no nat", "binat", "no binat", "rdr", "no rdr",
@@ -679,7 +680,7 @@ print_rule(struct pf_rule *r, const char
        static const char *anchortypes[] = { "anchor", "anchor", "anchor",
            "anchor", "nat-anchor", "nat-anchor", "binat-anchor",
            "binat-anchor", "rdr-anchor", "rdr-anchor" };
-       int     i, opts;
+       int     i, rule_opts;
        char    *p;
 
        if (verbose)
@@ -792,7 +793,7 @@ print_rule(struct pf_rule *r, const char
                        printf(" proto %u", r->proto);
        }
        print_fromto(&r->src, r->os_fingerprint, &r->dst, r->af, r->proto,
-           verbose);
+           verbose, opts);
        if (r->rcv_ifname[0])
                printf(" received-on %s", r->rcv_ifname);
        if (r->uid.op)
@@ -858,72 +859,72 @@ print_rule(struct pf_rule *r, const char
                }
                printf(" probability %s%%", buf);
        }
-       opts = 0;
+       rule_opts = 0;
        if (r->max_states || r->max_src_nodes || r->max_src_states)
-               opts = 1;
+               rule_opts = 1;
        if (r->rule_flag & PFRULE_NOSYNC)
-               opts = 1;
+               rule_opts = 1;
        if (r->rule_flag & PFRULE_SRCTRACK)
-               opts = 1;
+               rule_opts = 1;
        if (r->rule_flag & PFRULE_IFBOUND)
-               opts = 1;
+               rule_opts = 1;
        if (r->rule_flag & PFRULE_STATESLOPPY)
-               opts = 1;
+               rule_opts = 1;
        if (r->rule_flag & PFRULE_PFLOW)
-               opts = 1;
-       for (i = 0; !opts && i < PFTM_MAX; ++i)
+               rule_opts = 1;
+       for (i = 0; !rule_opts && i < PFTM_MAX; ++i)
                if (r->timeout[i])
-                       opts = 1;
-       if (opts) {
+                       rule_opts = 1;
+       if (rule_opts) {
                printf(" (");
                if (r->max_states) {
                        printf("max %u", r->max_states);
-                       opts = 0;
+                       rule_opts = 0;
                }
                if (r->rule_flag & PFRULE_NOSYNC) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(", ");
                        printf("no-sync");
-                       opts = 0;
+                       rule_opts = 0;
                }
                if (r->rule_flag & PFRULE_SRCTRACK) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(", ");
                        printf("source-track");
                        if (r->rule_flag & PFRULE_RULESRCTRACK)
                                printf(" rule");
                        else
                                printf(" global");
-                       opts = 0;
+                       rule_opts = 0;
                }
                if (r->max_src_states) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(", ");
                        printf("max-src-states %u", r->max_src_states);
-                       opts = 0;
+                       rule_opts = 0;
                }
                if (r->max_src_conn) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(", ");
                        printf("max-src-conn %u", r->max_src_conn);
-                       opts = 0;
+                       rule_opts = 0;
                }
                if (r->max_src_conn_rate.limit) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(", ");
                        printf("max-src-conn-rate %u/%u",
                            r->max_src_conn_rate.limit,
                            r->max_src_conn_rate.seconds);
-                       opts = 0;
+                       rule_opts = 0;
                }
                if (r->max_src_nodes) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(", ");
                        printf("max-src-nodes %u", r->max_src_nodes);
-                       opts = 0;
+                       rule_opts = 0;
                }
                if (r->overload_tblname[0]) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(", ");
                        printf("overload <%s>", r->overload_tblname);
                        if (r->flush)
@@ -932,30 +933,30 @@ print_rule(struct pf_rule *r, const char
                                printf(" global");
                }
                if (r->rule_flag & PFRULE_IFBOUND) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(", ");
                        printf("if-bound");
-                       opts = 0;
+                       rule_opts = 0;
                }
                if (r->rule_flag & PFRULE_STATESLOPPY) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(", ");
                        printf("sloppy");
-                       opts = 0;
+                       rule_opts = 0;
                }
                if (r->rule_flag & PFRULE_PFLOW) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(", ");
                        printf("pflow");
-                       opts = 0;
+                       rule_opts = 0;
                }
                for (i = 0; i < PFTM_MAX; ++i)
                        if (r->timeout[i]) {
                                int j;
 
-                               if (!opts)
+                               if (!rule_opts)
                                        printf(", ");
-                               opts = 0;
+                               rule_opts = 0;
                                for (j = 0; pf_timeouts[j].name != NULL;
                                    ++j)
                                        if (pf_timeouts[j].timeout == i)
@@ -972,40 +973,40 @@ print_rule(struct pf_rule *r, const char
 
        if (r->scrub_flags >= PFSTATE_NODF || r->min_ttl || r->max_mss) {
                printf(" scrub (");
-               opts = 1;
+               rule_opts = 1;
                if (r->scrub_flags & PFSTATE_NODF) {
                        printf("no-df");
-                       opts = 0;
+                       rule_opts = 0;
                }
                if (r->scrub_flags & PFSTATE_RANDOMID) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(" ");
                        printf("random-id");
-                       opts = 0;
+                       rule_opts = 0;
                }
                if (r->min_ttl) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(" ");
                        printf("min-ttl %d", r->min_ttl);
-                       opts = 0;
+                       rule_opts = 0;
                }
                if (r->scrub_flags & PFSTATE_SETTOS) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(" ");
                        printf("set-tos 0x%2.2x", r->set_tos);
-                       opts = 0;
+                       rule_opts = 0;
                }
                if (r->scrub_flags & PFSTATE_SCRUB_TCP) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(" ");
                        printf("reassemble tcp");
-                       opts = 0;
+                       rule_opts = 0;
                }
                if (r->max_mss) {
-                       if (!opts)
+                       if (!rule_opts)
                                printf(" ");
                        printf("max-mss %d", r->max_mss);
-                       opts = 0;
+                       rule_opts = 0;
                }
                printf(")");
        }
Index: pfctl_parser.h
===================================================================
RCS file: /cvs/src/sbin/pfctl/pfctl_parser.h,v
retrieving revision 1.95
diff -u -p -r1.95 pfctl_parser.h
--- pfctl_parser.h      6 Apr 2011 13:19:55 -0000       1.95
+++ pfctl_parser.h      24 May 2011 00:51:36 -0000
@@ -48,6 +48,7 @@
 #define PF_OPT_SHOWALL         0x0400
 #define PF_OPT_OPTIMIZE                0x0800
 #define PF_OPT_RECURSE         0x4000
+#define PF_OPT_NUMERICPORTS    0x8000
 
 #define PF_TH_ALL              0xFF
 
@@ -216,7 +217,7 @@ int pfctl_load_anchors(int, struct pfctl
 
 void   print_pool(struct pf_pool *, u_int16_t, u_int16_t, sa_family_t, int, 
int);
 void   print_src_node(struct pf_src_node *, int);
-void   print_rule(struct pf_rule *, const char *, int);
+void   print_rule(struct pf_rule *, const char *, int, int);
 void   print_tabledef(const char *, int, int, struct node_tinithead *);
 void   print_status(struct pf_status *, int);

Reply via email to