]> The Tcpdump Group git mirrors - libpcap/commitdiff
Improve handling of DLT_PFLOG when generating filter code.
authorGuy Harris <[email protected]>
Sun, 30 Jan 2022 05:11:34 +0000 (21:11 -0800)
committerGuy Harris <[email protected]>
Sun, 30 Jan 2022 05:11:34 +0000 (21:11 -0800)
Don't rely on the OS's pflog include files to give the pflog header
length; instead, fetch it from the length field of the header, and round
up to a multiple of 4.  That way, it'll handle headers for OSes other
than the one for which we're compiling code, and will handle different
header lengths for any given OS if, for example, a new version of the OS
adds more fields to the end.

Don't rely on the OS's pflog include files to define direction types,
reason types, action types, or the layout of the header; instead, define
them ourselves in a header of our own, with #ifs to select the ones that
are only on some platforms.  That way, it'll handle some fields and
field values (the ones common to all OSes with pflog) on all OSes, even
ones without pflog.

This should also clean up the FreeBSD build issues reported in #1074, as
we no longer include <net/if_pflog.h>.

CMakeLists.txt
Makefile.in
config.h.in
configure
configure.ac
gencode.c
grammar.y.in

index fdd91800f428a46bfcc5ec3bcc4ff1e74de48ff3..e83177480002fe8a36c4aeee7a9b4d55ed446862 100644 (file)
@@ -382,25 +382,6 @@ if(NOT WIN32)
     check_include_file(sys/select.h HAVE_SYS_SELECT_H)
 
     check_include_file(netpacket/packet.h HAVE_NETPACKET_PACKET_H)
-    check_include_files("sys/types.h;sys/socket.h;net/if.h;net/pfvar.h" HAVE_NET_PFVAR_H)
-    if(HAVE_NET_PFVAR_H)
-        #
-        # Check for various PF actions.
-        #
-        check_c_source_compiles(
-"#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <net/pfvar.h>
-
-int
-main(void)
-{
-    return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;
-}
-"
-            HAVE_PF_NAT_THROUGH_PF_NORDR)
-    endif(HAVE_NET_PFVAR_H)
     check_include_file(netinet/if_ether.h HAVE_NETINET_IF_ETHER_H)
 endif(NOT WIN32)
 
index be7b9865697c87531ebd8ecbd66d766340deeff5..a0e4b9fadf81329ee6a5bf6fc0c4b4f5655f29f5 100644 (file)
@@ -149,6 +149,7 @@ HDR = $(PUBHDR) \
        pcap-int.h \
        pcap-rpcap.h \
        pcap-types.h \
+       pflog.h \
        portability.h \
        ppp.h \
        rpcap-protocol.h \
index a1e371a93e414b7b1aeeca5154197363720fb93a..3eb90a8b23d8f278fbfcdfea5f7f7986baad3fc7 100644 (file)
 /* Define to 1 if you have the <net/pfilt.h> header file. */
 #undef HAVE_NET_PFILT_H
 
-/* Define to 1 if you have the <net/pfvar.h> header file. */
-#undef HAVE_NET_PFVAR_H
-
 /* Define to 1 if you have the <net/raw.h> header file. */
 #undef HAVE_NET_RAW_H
 
 /* if there's an os_proto.h for this platform, to use additional prototypes */
 #undef HAVE_OS_PROTO_H
 
-/* define if net/pfvar.h defines PF_NAT through PF_NORDR */
-#undef HAVE_PF_NAT_THROUGH_PF_NORDR
-
 /* Define to 1 if you have a POSIX-style `strerror_r' function. */
 #undef HAVE_POSIX_STRERROR_R
 
index e66c6474c38535577ffbb215764aa346fbd321d0..b8da398afe1f50c984995435ba4a2b745607e44d 100755 (executable)
--- a/configure
+++ b/configure
@@ -5285,55 +5285,6 @@ fi
 
 done
 
-for ac_header in net/pfvar.h
-do :
-  ac_fn_c_check_header_compile "$LINENO" "net/pfvar.h" "ac_cv_header_net_pfvar_h" "#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>
-"
-if test "x$ac_cv_header_net_pfvar_h" = xyes; then :
-  cat >>confdefs.h <<_ACEOF
-#define HAVE_NET_PFVAR_H 1
-_ACEOF
-
-fi
-
-done
-
-if test "$ac_cv_header_net_pfvar_h" = yes; then
-       #
-       # Check for various PF actions.
-       #
-       { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether net/pfvar.h defines PF_NAT through PF_NORDR" >&5
-$as_echo_n "checking whether net/pfvar.h defines PF_NAT through PF_NORDR... " >&6; }
-       cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <sys/types.h>
-           #include <sys/socket.h>
-           #include <net/if.h>
-           #include <net/pfvar.h>
-int
-main ()
-{
-return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-
-               { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-
-$as_echo "#define HAVE_PF_NAT_THROUGH_PF_NORDR 1" >>confdefs.h
-
-
-else
-  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
 
 case "$host_os" in
 haiku*)
index a4f63e6b970015dabfae270ba784c9cfd2f77aa2..954340cf86e5cb6d30a6f07fbd6d570972d698b8 100644 (file)
@@ -63,27 +63,6 @@ dnl "AC_LBL_FIXINCLUDES" wouldn't work on some platforms such as Solaris.
 dnl
 AC_CHECK_HEADERS(sys/ioccom.h sys/sockio.h)
 AC_CHECK_HEADERS(netpacket/packet.h)
-AC_CHECK_HEADERS(net/pfvar.h, , , [#include <sys/types.h>
-#include <sys/socket.h>
-#include <net/if.h>])
-if test "$ac_cv_header_net_pfvar_h" = yes; then
-       #
-       # Check for various PF actions.
-       #
-       AC_MSG_CHECKING(whether net/pfvar.h defines PF_NAT through PF_NORDR)
-       AC_TRY_COMPILE(
-           [#include <sys/types.h>
-           #include <sys/socket.h>
-           #include <net/if.h>
-           #include <net/pfvar.h>],
-           [return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;],
-           [
-               AC_MSG_RESULT(yes)
-               AC_DEFINE(HAVE_PF_NAT_THROUGH_PF_NORDR, 1,
-                   [define if net/pfvar.h defines PF_NAT through PF_NORDR])
-           ],
-           AC_MSG_RESULT(no))
-fi
 
 case "$host_os" in
 haiku*)
index 703bb20e2ca86171d6c6e69e2c07aa7454cde698..9b16a5c1cf845b17f057be02b4ab699f7c76877e 100644 (file)
--- a/gencode.c
+++ b/gencode.c
 #include "pcap-dos.h"
 #endif
 
-#ifdef HAVE_NET_PFVAR_H
-/*
- * In NetBSD <net/if.h> includes <net/dlt.h>, which is an older version of
- * "pcap/dlt.h" with a lower value of DLT_MATCHING_MAX. Include the headers
- * below before "pcap-int.h", which eventually includes "pcap/dlt.h", which
- * redefines DLT_MATCHING_MAX from what this version of NetBSD has to what
- * this version of libpcap has.
- */
-#include <sys/socket.h>
-#include <net/if.h>
-#include <net/pfvar.h>
-#include <net/if_pflog.h>
-#endif /* HAVE_NET_PFVAR_H */
-
 #include "pcap-int.h"
 
 #include "extract.h"
@@ -73,6 +59,7 @@
 #include "ieee80211.h"
 #include "atmuni31.h"
 #include "sunatmpos.h"
+#include "pflog.h"
 #include "ppp.h"
 #include "pcap/sll.h"
 #include "pcap/ipnet.h"
@@ -524,6 +511,7 @@ static inline struct block *gen_false(compiler_state_t *);
 static struct block *gen_ether_linktype(compiler_state_t *, bpf_u_int32);
 static struct block *gen_ipnet_linktype(compiler_state_t *, bpf_u_int32);
 static struct block *gen_linux_sll_linktype(compiler_state_t *, bpf_u_int32);
+static struct slist *gen_load_pflog_llprefixlen(compiler_state_t *);
 static struct slist *gen_load_prism_llprefixlen(compiler_state_t *);
 static struct slist *gen_load_avs_llprefixlen(compiler_state_t *);
 static struct slist *gen_load_radiotap_llprefixlen(compiler_state_t *);
@@ -1517,14 +1505,13 @@ init_linktype(compiler_state_t *cstate, pcap_t *p)
                cstate->off_nl_nosnap = 0;      /* XXX - what does it do with 802.3 packets? */
                break;
 
-#ifdef HAVE_NET_PFVAR_H
        case DLT_PFLOG:
                cstate->off_linktype.constant_part = 0;
-               cstate->off_linkpl.constant_part = PFLOG_HDRLEN;
+               cstate->off_linkpl.constant_part = 0;   /* link-layer header is variable-length */
+               cstate->off_linkpl.is_variable = 1;
                cstate->off_nl = 0;
                cstate->off_nl_nosnap = 0;      /* no 802.2 LLC */
                break;
-#endif
 
         case DLT_JUNIPER_MFR:
         case DLT_JUNIPER_MLFR:
@@ -2349,6 +2336,59 @@ gen_linux_sll_linktype(compiler_state_t *cstate, bpf_u_int32 ll_proto)
        }
 }
 
+/*
+ * Load a value relative to the beginning of the link-layer header after the
+ * pflog header.
+ */
+static struct slist *
+gen_load_pflog_llprefixlen(compiler_state_t *cstate)
+{
+       struct slist *s1, *s2;
+
+       /*
+        * Generate code to load the length of the pflog header into
+        * the register assigned to hold that length, if one has been
+        * assigned.  (If one hasn't been assigned, no code we've
+        * generated uses that prefix, so we don't need to generate any
+        * code to load it.)
+        */
+       if (cstate->off_linkpl.reg != -1) {
+               /*
+                * The length is in the first byte of the header.
+                */
+               s1 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
+               s1->s.k = 0;
+
+               /*
+                * Round it up to a multiple of 4.
+                * Add 3, and clear the lower 2 bits.
+                */
+               s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+               s2->s.k = 3;
+               sappend(s1, s2);
+               s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
+               s2->s.k = 0xfffffffe;
+               sappend(s1, s2);
+                
+               /*
+                * Now allocate a register to hold that value and store
+                * it.
+                */
+               s2 = new_stmt(cstate, BPF_ST);
+               s2->s.k = cstate->off_linkpl.reg;
+               sappend(s1, s2);
+
+               /*
+                * Now move it into the X register.
+                */
+               s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
+               sappend(s1, s2);
+
+               return (s1);
+       } else
+               return (NULL);
+}
+
 static struct slist *
 gen_load_prism_llprefixlen(compiler_state_t *cstate)
 {
@@ -2936,6 +2976,10 @@ insert_compute_vloffsets(compiler_state_t *cstate, struct block *b)
        case DLT_PPI:
                s = gen_load_802_11_header_len(cstate, s, b->stmts);
                break;
+
+       case DLT_PFLOG:
+               s = gen_load_pflog_llprefixlen(cstate);
+               break;
        }
 
        /*
@@ -3401,7 +3445,6 @@ gen_linktype(compiler_state_t *cstate, bpf_u_int32 ll_proto)
                        return gen_false(cstate);
                }
 
-#ifdef HAVE_NET_PFVAR_H
        case DLT_PFLOG:
                /*
                 * af field is host byte order in contrast to the rest of
@@ -3416,7 +3459,6 @@ gen_linktype(compiler_state_t *cstate, bpf_u_int32 ll_proto)
                else
                        return gen_false(cstate);
                /*NOTREACHED*/
-#endif /* HAVE_NET_PFVAR_H */
 
        case DLT_ARCNET:
        case DLT_ARCNET_LINUX:
@@ -8307,12 +8349,10 @@ gen_inbound(compiler_state_t *cstate, int dir)
                }
                break;
 
-#ifdef HAVE_NET_PFVAR_H
        case DLT_PFLOG:
                b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, dir), BPF_B,
                    ((dir == 0) ? PF_IN : PF_OUT));
                break;
-#endif
 
        case DLT_PPP_PPPD:
                if (dir) {
@@ -8403,7 +8443,6 @@ gen_inbound(compiler_state_t *cstate, int dir)
        return (b0);
 }
 
-#ifdef HAVE_NET_PFVAR_H
 /* PF firewall log matched interface */
 struct block *
 gen_pf_ifname(compiler_state_t *cstate, const char *ifname)
@@ -8554,91 +8593,6 @@ gen_pf_action(compiler_state_t *cstate, int action)
            (bpf_u_int32)action);
        return (b0);
 }
-#else /* !HAVE_NET_PFVAR_H */
-struct block *
-gen_pf_ifname(compiler_state_t *cstate, const char *ifname _U_)
-{
-       /*
-        * Catch errors reported by us and routines below us, and return NULL
-        * on an error.
-        */
-       if (setjmp(cstate->top_ctx))
-               return (NULL);
-
-       bpf_error(cstate, "libpcap was compiled without pf support");
-       /*NOTREACHED*/
-}
-
-struct block *
-gen_pf_ruleset(compiler_state_t *cstate, char *ruleset _U_)
-{
-       /*
-        * Catch errors reported by us and routines below us, and return NULL
-        * on an error.
-        */
-       if (setjmp(cstate->top_ctx))
-               return (NULL);
-
-       bpf_error(cstate, "libpcap was compiled on a machine without pf support");
-       /*NOTREACHED*/
-}
-
-struct block *
-gen_pf_rnr(compiler_state_t *cstate, int rnr _U_)
-{
-       /*
-        * Catch errors reported by us and routines below us, and return NULL
-        * on an error.
-        */
-       if (setjmp(cstate->top_ctx))
-               return (NULL);
-
-       bpf_error(cstate, "libpcap was compiled on a machine without pf support");
-       /*NOTREACHED*/
-}
-
-struct block *
-gen_pf_srnr(compiler_state_t *cstate, int srnr _U_)
-{
-       /*
-        * Catch errors reported by us and routines below us, and return NULL
-        * on an error.
-        */
-       if (setjmp(cstate->top_ctx))
-               return (NULL);
-
-       bpf_error(cstate, "libpcap was compiled on a machine without pf support");
-       /*NOTREACHED*/
-}
-
-struct block *
-gen_pf_reason(compiler_state_t *cstate, int reason _U_)
-{
-       /*
-        * Catch errors reported by us and routines below us, and return NULL
-        * on an error.
-        */
-       if (setjmp(cstate->top_ctx))
-               return (NULL);
-
-       bpf_error(cstate, "libpcap was compiled on a machine without pf support");
-       /*NOTREACHED*/
-}
-
-struct block *
-gen_pf_action(compiler_state_t *cstate, int action _U_)
-{
-       /*
-        * Catch errors reported by us and routines below us, and return NULL
-        * on an error.
-        */
-       if (setjmp(cstate->top_ctx))
-               return (NULL);
-
-       bpf_error(cstate, "libpcap was compiled on a machine without pf support");
-       /*NOTREACHED*/
-}
-#endif /* HAVE_NET_PFVAR_H */
 
 /* IEEE 802.11 wireless header */
 struct block *
index 357dcbacb94393ef990ea357b5d8608fb9e55bdd..2360d3c7c3c2f8a5191157dfe78bb956c53a88a1 100644 (file)
@@ -101,13 +101,9 @@ struct rtentry;
 
 #include "scanner.h"
 
-#ifdef HAVE_NET_PFVAR_H
-#include <net/if.h>
-#include <net/pfvar.h>
-#include <net/if_pflog.h>
-#endif
 #include "llc.h"
 #include "ieee80211.h"
+#include "pflog.h"
 #include <pcap/namedb.h>
 
 #ifdef HAVE_OS_PROTO_H
@@ -261,60 +257,87 @@ yyerror(void *yyscanner _U_, compiler_state_t *cstate, const char *msg)
        bpf_set_error(cstate, "can't parse filter expression: %s", msg);
 }
 
-#ifdef HAVE_NET_PFVAR_H
+static const struct tok pflog_reasons[] = {
+       { PFRES_MATCH,          "match" },
+       { PFRES_BADOFF,         "bad-offset" },
+       { PFRES_FRAG,           "fragment" },
+       { PFRES_SHORT,          "short" },
+       { PFRES_NORM,           "normalize" },
+       { PFRES_MEMORY,         "memory" },
+       { PFRES_TS,             "bad-timestamp" },
+       { PFRES_CONGEST,        "congestion" },
+       { PFRES_IPOPTIONS,      "ip-option" },
+       { PFRES_PROTCKSUM,      "proto-cksum" },
+       { PFRES_BADSTATE,       "state-mismatch" },
+       { PFRES_STATEINS,       "state-insert" },
+       { PFRES_MAXSTATES,      "state-limit" },
+       { PFRES_SRCLIMIT,       "src-limit" },
+       { PFRES_SYNPROXY,       "synproxy" },
+#if defined(__FreeBSD__)
+       { PFRES_MAPFAILED,      "map-failed" },
+#elif defined(__NetBSD__)
+       { PFRES_STATELOCKED,    "state-locked" },
+#elif defined(__OpenBSD__)
+       { PFRES_TRANSLATE,      "translate" },
+       { PFRES_NOROUTE,        "no-route" },
+#elif defined(__APPLE__)
+       { PFRES_DUMMYNET,       "dummynet" },
+#endif
+       { 0, NULL }
+};
+
 static int
 pfreason_to_num(compiler_state_t *cstate, const char *reason)
 {
-       const char *reasons[] = PFRES_NAMES;
        int i;
 
-       for (i = 0; reasons[i]; i++) {
-               if (pcap_strcasecmp(reason, reasons[i]) == 0)
-                       return (i);
-       }
-       bpf_set_error(cstate, "unknown PF reason \"%s\"", reason);
-       return (-1);
+       i = str2tok(reason, pflog_reasons);
+       if (i == -1)
+               bpf_set_error(cstate, "unknown PF reason \"%s\"", reason);
+       return (i);
 }
 
-static int
-pfaction_to_num(compiler_state_t *cstate, const char *action)
-{
-       if (pcap_strcasecmp(action, "pass") == 0 ||
-           pcap_strcasecmp(action, "accept") == 0)
-               return (PF_PASS);
-       else if (pcap_strcasecmp(action, "drop") == 0 ||
-               pcap_strcasecmp(action, "block") == 0)
-               return (PF_DROP);
-#if HAVE_PF_NAT_THROUGH_PF_NORDR
-       else if (pcap_strcasecmp(action, "rdr") == 0)
-               return (PF_RDR);
-       else if (pcap_strcasecmp(action, "nat") == 0)
-               return (PF_NAT);
-       else if (pcap_strcasecmp(action, "binat") == 0)
-               return (PF_BINAT);
-       else if (pcap_strcasecmp(action, "nordr") == 0)
-               return (PF_NORDR);
+static const struct tok pflog_actions[] = {
+       { PF_PASS,              "pass" },
+       { PF_PASS,              "accept" },     /* alias for "pass" */
+       { PF_DROP,              "drop" },
+       { PF_DROP,              "block" },      /* alias for "drop" */
+       { PF_SCRUB,             "scrub" },
+       { PF_NOSCRUB,           "noscrub" },
+       { PF_NAT,               "nat" },
+       { PF_NONAT,             "nonat" },
+       { PF_BINAT,             "binat" },
+       { PF_NOBINAT,           "nobinat" },
+       { PF_RDR,               "rdr" },
+       { PF_NORDR,             "nordr" },
+       { PF_SYNPROXY_DROP,     "synproxy-drop" },
+#if defined(__FreeBSD__)
+       { PF_DEFER,             "defer" },
+#elif defined(__OpenBSD__)
+       { PF_DEFER,             "defer" },
+       { PF_MATCH,             "match" },
+       { PF_DIVERT,            "divert" },
+       { PF_RT,                "rt" },
+       { PF_AFRT,              "afrt" },
+#elif defined(__APPLE__)
+       { PF_DUMMYNET,          "dummynet" },
+       { PF_NODUMMYNET,        "nodummynet" },
+       { PF_NAT64,             "nat64" },
+       { PF_NONAT64,           "nonat64" },
 #endif
-       else {
-               bpf_set_error(cstate, "unknown PF action \"%s\"", action);
-               return (-1);
-       }
-}
-#else /* !HAVE_NET_PFVAR_H */
-static int
-pfreason_to_num(compiler_state_t *cstate, const char *reason _U_)
-{
-       bpf_set_error(cstate, "libpcap was compiled on a machine without pf support");
-       return (-1);
-}
+       { 0, NULL },
+};
 
 static int
-pfaction_to_num(compiler_state_t *cstate, const char *action _U_)
+pfaction_to_num(compiler_state_t *cstate, const char *action)
 {
-       bpf_set_error(cstate, "libpcap was compiled on a machine without pf support");
-       return (-1);
+       int i;
+
+       i = str2tok(action, pflog_actions);
+       if (i == -1)
+               bpf_set_error(cstate, "unknown PF action \"%s\"", action);
+       return (i);
 }
-#endif /* HAVE_NET_PFVAR_H */
 
 /*
  * For calls that might return an "an error occurred" value.