]> The Tcpdump Group git mirrors - libpcap/blobdiff - gencode.c
Fix building without protochain support. (GH #852)
[libpcap] / gencode.c
index 13dbcb5e502812344559254794d5bbaf67cfcebd..ea272e17649aff9c1123b88d8f0c01ec76f55067 100644 (file)
--- a/gencode.c
+++ b/gencode.c
@@ -1,4 +1,3 @@
-/*#define CHASE_CHAIN*/
 /*
  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
  *     The Regents of the University of California.  All rights reserved.
 #include "ieee80211.h"
 #include "atmuni31.h"
 #include "sunatmpos.h"
+#include "pflog.h"
 #include "ppp.h"
 #include "pcap/sll.h"
 #include "pcap/ipnet.h"
 #include "arcnet.h"
+#include "diag-control.h"
 
-#include "grammar.h"
 #include "scanner.h"
 
 #if defined(linux)
 #include <linux/filter.h>
 #endif
 
-#ifdef HAVE_NET_PFVAR_H
-#include <sys/socket.h>
-#include <net/if.h>
-#include <net/pfvar.h>
-#include <net/if_pflog.h>
-#endif
-
 #ifndef offsetof
 #define offsetof(s, e) ((size_t)&((s *)0)->e)
 #endif
@@ -468,6 +461,9 @@ bpf_error(compiler_state_t *cstate, const char *fmt, ...)
        va_end(ap);
        longjmp(cstate->top_ctx, 1);
        /*NOTREACHED*/
+#ifdef _AIX
+       PCAP_UNREACHABLE
+#endif /* _AIX */
 }
 
 static int init_linktype(compiler_state_t *, pcap_t *);
@@ -514,6 +510,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 *);
@@ -567,7 +564,9 @@ static struct block *gen_portrangeop6(compiler_state_t *, u_int, u_int,
     bpf_u_int32, int);
 static struct block *gen_portrange6(compiler_state_t *, u_int, u_int, int, int);
 static int lookup_proto(compiler_state_t *, const char *, int);
+#if !defined(NO_PROTOCHAIN)
 static struct block *gen_protochain(compiler_state_t *, bpf_u_int32, int);
+#endif /* !defined(NO_PROTOCHAIN) */
 static struct block *gen_proto(compiler_state_t *, bpf_u_int32, int, int);
 static struct slist *xfer_to_x(compiler_state_t *, struct arth *);
 static struct slist *xfer_to_a(compiler_state_t *, struct arth *);
@@ -734,7 +733,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
        if (!p->activated) {
                snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
                    "not-yet-activated pcap_t passed to pcap_compile");
-               return (-1);
+               return (PCAP_ERROR);
        }
 
 #ifdef _WIN32
@@ -782,7 +781,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
        if (cstate.snaplen == 0) {
                snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
                         "snaplen of 0 rejects all packets");
-               rc = -1;
+               rc = PCAP_ERROR;
                goto quit;
        }
 
@@ -798,7 +797,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
        pcap_set_extra(&cstate, scanner);
 
        if (init_linktype(&cstate, p) == -1) {
-               rc = -1;
+               rc = PCAP_ERROR;
                goto quit;
        }
        if (pcap_parse(scanner, &cstate) != 0) {
@@ -808,7 +807,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
 #endif
                if (cstate.e != NULL)
                        free(cstate.e);
-               rc = -1;
+               rc = PCAP_ERROR;
                goto quit;
        }
 
@@ -817,7 +816,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
                 * Catch errors reported by gen_retblk().
                 */
                if (setjmp(cstate.top_ctx)) {
-                       rc = -1;
+                       rc = PCAP_ERROR;
                        goto quit;
                }
                cstate.ic.root = gen_retblk(&cstate, cstate.snaplen);
@@ -826,14 +825,14 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
        if (optimize && !cstate.no_optimize) {
                if (bpf_optimize(&cstate.ic, p->errbuf) == -1) {
                        /* Failure */
-                       rc = -1;
+                       rc = PCAP_ERROR;
                        goto quit;
                }
                if (cstate.ic.root == NULL ||
                    (cstate.ic.root->s.code == (BPF_RET|BPF_K) && cstate.ic.root->s.k == 0)) {
                        (void)snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
                            "expression rejects all packets");
-                       rc = -1;
+                       rc = PCAP_ERROR;
                        goto quit;
                }
        }
@@ -841,7 +840,7 @@ pcap_compile(pcap_t *p, struct bpf_program *program,
            cstate.ic.root, &len, p->errbuf);
        if (program->bf_insns == NULL) {
                /* Failure */
-               rc = -1;
+               rc = PCAP_ERROR;
                goto quit;
        }
        program->bf_len = len;
@@ -879,7 +878,7 @@ pcap_compile_nopcap(int snaplen_arg, int linktype_arg,
 
        p = pcap_open_dead(linktype_arg, snaplen_arg);
        if (p == NULL)
-               return (-1);
+               return (PCAP_ERROR);
        ret = pcap_compile(p, program, buf, optimize, mask);
        pcap_close(p);
        return (ret);
@@ -1258,6 +1257,7 @@ init_linktype(compiler_state_t *cstate, pcap_t *p)
        case DLT_PPP:
        case DLT_PPP_PPPD:
        case DLT_C_HDLC:                /* BSD/OS Cisco HDLC */
+       case DLT_HDLC:                  /* NetBSD (Cisco) HDLC */
        case DLT_PPP_SERIAL:            /* NetBSD sync/async serial PPP */
                cstate->off_linktype.constant_part = 2; /* skip HDLC-like framing */
                cstate->off_linkpl.constant_part = 4;   /* skip HDLC-like framing and protocol field */
@@ -1316,7 +1316,7 @@ init_linktype(compiler_state_t *cstate, pcap_t *p)
                 * information, i.e. is not source-routed, the correct
                 * values are 20 and 22, as they are in the vanilla code.
                 *
-                * A packet is source-routed if the uppermost bit
+                * A packet is source-routed iff the uppermost bit
                 * of the first byte of the source address, at an
                 * offset of 8, has the uppermost bit set.  If the
                 * packet is source-routed, the total number of bytes
@@ -1506,14 +1506,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:
@@ -1715,7 +1714,8 @@ init_linktype(compiler_state_t *cstate, pcap_t *p)
                        cstate->off_nl = OFFSET_NOT_SET;
                        cstate->off_nl_nosnap = OFFSET_NOT_SET;
                } else {
-                       bpf_set_error(cstate, "unknown data link type %d", cstate->linktype);
+                       bpf_set_error(cstate, "unknown data link type %d (min %d, max %d)",
+                           cstate->linktype, DLT_MATCHING_MIN, DLT_MATCHING_MAX);
                        return (-1);
                }
                break;
@@ -2337,6 +2337,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 = 0xfffffffc;
+               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)
 {
@@ -2924,6 +2977,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;
        }
 
        /*
@@ -3159,6 +3216,7 @@ gen_linktype(compiler_state_t *cstate, bpf_u_int32 ll_proto)
                /*NOTREACHED*/
 
        case DLT_C_HDLC:
+       case DLT_HDLC:
                switch (ll_proto) {
 
                case LLCSAP_ISONS:
@@ -3388,7 +3446,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
@@ -3403,7 +3460,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:
@@ -5303,21 +5359,15 @@ gen_proto_abbrev_internal(compiler_state_t *cstate, int proto)
        switch (proto) {
 
        case Q_SCTP:
-               b1 = gen_proto(cstate, IPPROTO_SCTP, Q_IP, Q_DEFAULT);
-               b0 = gen_proto(cstate, IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
-               gen_or(b0, b1);
+               b1 = gen_proto(cstate, IPPROTO_SCTP, Q_DEFAULT, Q_DEFAULT);
                break;
 
        case Q_TCP:
-               b1 = gen_proto(cstate, IPPROTO_TCP, Q_IP, Q_DEFAULT);
-               b0 = gen_proto(cstate, IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
-               gen_or(b0, b1);
+               b1 = gen_proto(cstate, IPPROTO_TCP, Q_DEFAULT, Q_DEFAULT);
                break;
 
        case Q_UDP:
-               b1 = gen_proto(cstate, IPPROTO_UDP, Q_IP, Q_DEFAULT);
-               b0 = gen_proto(cstate, IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
-               gen_or(b0, b1);
+               b1 = gen_proto(cstate, IPPROTO_UDP, Q_DEFAULT, Q_DEFAULT);
                break;
 
        case Q_ICMP:
@@ -5344,9 +5394,7 @@ gen_proto_abbrev_internal(compiler_state_t *cstate, int proto)
 #endif
 
        case Q_PIM:
-               b1 = gen_proto(cstate, IPPROTO_PIM, Q_IP, Q_DEFAULT);
-               b0 = gen_proto(cstate, IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
-               gen_or(b0, b1);
+               b1 = gen_proto(cstate, IPPROTO_PIM, Q_DEFAULT, Q_DEFAULT);
                break;
 
 #ifndef IPPROTO_VRRP
@@ -5423,18 +5471,14 @@ gen_proto_abbrev_internal(compiler_state_t *cstate, int proto)
 #define IPPROTO_AH     51
 #endif
        case Q_AH:
-               b1 = gen_proto(cstate, IPPROTO_AH, Q_IP, Q_DEFAULT);
-               b0 = gen_proto(cstate, IPPROTO_AH, Q_IPV6, Q_DEFAULT);
-               gen_or(b0, b1);
+               b1 = gen_proto(cstate, IPPROTO_AH, Q_DEFAULT, Q_DEFAULT);
                break;
 
 #ifndef IPPROTO_ESP
 #define IPPROTO_ESP    50
 #endif
        case Q_ESP:
-               b1 = gen_proto(cstate, IPPROTO_ESP, Q_IP, Q_DEFAULT);
-               b0 = gen_proto(cstate, IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
-               gen_or(b0, b1);
+               b1 = gen_proto(cstate, IPPROTO_ESP, Q_DEFAULT, Q_DEFAULT);
                break;
 
        case Q_ISO:
@@ -6028,20 +6072,10 @@ lookup_proto(compiler_state_t *cstate, const char *name, int proto)
        return v;
 }
 
-#if 0
-struct stmt *
-gen_joinsp(struct stmt **s, int n)
-{
-       return NULL;
-}
-#endif
-
+#if !defined(NO_PROTOCHAIN)
 static struct block *
 gen_protochain(compiler_state_t *cstate, bpf_u_int32 v, int proto)
 {
-#ifdef NO_PROTOCHAIN
-       return gen_proto(cstate, v, proto);
-#else
        struct block *b0, *b;
        struct slist *s[100];
        int fix2, fix3, fix4, fix5;
@@ -6080,7 +6114,18 @@ gen_protochain(compiler_state_t *cstate, bpf_u_int32 v, int proto)
        if (cstate->off_linkpl.is_variable)
                bpf_error(cstate, "'protochain' not supported with variable length headers");
 
-       cstate->no_optimize = 1; /* this code is not compatible with optimizer yet */
+       /*
+        * To quote a comment in optimize.c:
+        *
+        * "These data structures are used in a Cocke and Shwarz style
+        * value numbering scheme.  Since the flowgraph is acyclic,
+        * exit values can be propagated from a node's predecessors
+        * provided it is uniquely defined."
+        *
+        * "Acyclic" means "no backward branches", which means "no
+        * loops", so we have to turn the optimizer off.
+        */
+       cstate->no_optimize = 1;
 
        /*
         * s[0] is a dummy entry to protect other BPF insn from damage
@@ -6324,8 +6369,8 @@ gen_protochain(compiler_state_t *cstate, bpf_u_int32 v, int proto)
 
        gen_and(b0, b);
        return b;
-#endif
 }
+#endif /* !defined(NO_PROTOCHAIN) */
 
 static struct block *
 gen_check_802_11_data_frame(compiler_state_t *cstate)
@@ -6366,9 +6411,7 @@ static struct block *
 gen_proto(compiler_state_t *cstate, bpf_u_int32 v, int proto, int dir)
 {
        struct block *b0, *b1;
-#ifndef CHASE_CHAIN
        struct block *b2;
-#endif
 
        if (dir != Q_DEFAULT)
                bpf_error(cstate, "direction applied to 'proto'");
@@ -6400,11 +6443,7 @@ gen_proto(compiler_state_t *cstate, bpf_u_int32 v, int proto, int dir)
                 * So we always check for ETHERTYPE_IP.
                 */
                b0 = gen_linktype(cstate, ETHERTYPE_IP);
-#ifndef CHASE_CHAIN
                b1 = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, v);
-#else
-               b1 = gen_protochain(cstate, v, Q_IP);
-#endif
                gen_and(b0, b1);
                return b1;
 
@@ -6466,7 +6505,6 @@ gen_proto(compiler_state_t *cstate, bpf_u_int32 v, int proto, int dir)
 
        case Q_IPV6:
                b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
-#ifndef CHASE_CHAIN
                /*
                 * Also check for a fragment header before the final
                 * header.
@@ -6476,9 +6514,6 @@ gen_proto(compiler_state_t *cstate, bpf_u_int32 v, int proto, int dir)
                gen_and(b2, b1);
                b2 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, v);
                gen_or(b2, b1);
-#else
-               b1 = gen_protochain(cstate, v, Q_IPV6);
-#endif
                gen_and(b0, b1);
                return b1;
 
@@ -6532,6 +6567,7 @@ gen_proto(compiler_state_t *cstate, bpf_u_int32 v, int proto, int dir)
                        /*NOTREACHED*/
 
                case DLT_C_HDLC:
+               case DLT_HDLC:
                        /*
                         * Cisco uses an Ethertype lookalike - for OSI,
                         * it's 0xfefe.
@@ -6917,12 +6953,14 @@ gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
                else
                        bpf_error(cstate, "unknown protocol: %s", name);
 
+#if !defined(NO_PROTOCHAIN)
        case Q_PROTOCHAIN:
                real_proto = lookup_proto(cstate, name, proto);
                if (real_proto >= 0)
                        return gen_protochain(cstate, real_proto, proto);
                else
                        bpf_error(cstate, "unknown protocol: %s", name);
+#endif /* !defined(NO_PROTOCHAIN) */
 
        case Q_UNDEF:
                syntax(cstate);
@@ -7095,8 +7133,10 @@ gen_ncode(compiler_state_t *cstate, const char *s, bpf_u_int32 v, struct qual q)
        case Q_PROTO:
                return gen_proto(cstate, v, proto, dir);
 
+#if !defined(NO_PROTOCHAIN)
        case Q_PROTOCHAIN:
                return gen_protochain(cstate, v, proto);
+#endif
 
        case Q_UNDEF:
                syntax(cstate);
@@ -8282,12 +8322,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) {
@@ -8378,7 +8416,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)
@@ -8529,91 +8566,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 *
@@ -9077,6 +9029,7 @@ gen_mpls(compiler_state_t *cstate, bpf_u_int32 label_num_arg,
             switch (cstate->linktype) {
 
             case DLT_C_HDLC: /* fall through */
+            case DLT_HDLC:
             case DLT_EN10MB:
             case DLT_NETANALYZER:
             case DLT_NETANALYZER_TRANSPARENT: