*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.199 2004-01-31 01:54:43 guy Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.216 2005-01-12 09:02:55 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
#else /* WIN32 */
#include <sys/types.h>
#include <sys/socket.h>
-#include <sys/time.h>
#endif /* WIN32 */
/*
#include <setjmp.h>
#include <stdarg.h>
+#ifdef MSDOS
+#include "pcap-dos.h"
+#endif
+
#include "pcap-int.h"
#include "ethertype.h"
#include "sll.h"
#include "arcnet.h"
#include "pf.h"
+#ifndef offsetof
+#define offsetof(s, e) ((size_t)&((s *)0)->e)
+#endif
#ifdef INET6
#ifndef WIN32
#include <netdb.h> /* for "struct addrinfo" */
static jmp_buf top_ctx;
static pcap_t *bpf_pcap;
-/* Hack for updating VLAN offsets. */
-static u_int orig_linktype = -1, orig_nl = -1, orig_nl_nosnap = -1;
+/* Hack for updating VLAN, MPLS offsets. */
+static u_int orig_linktype = -1U, orig_nl = -1U, orig_nl_nosnap = -1U;
/* XXX */
#ifdef PCAP_FDDIPAD
-int pcap_fddipad = PCAP_FDDIPAD;
-#else
-int pcap_fddipad;
+static int pcap_fddipad;
#endif
/* VARARGS */
/* NOTREACHED */
}
-static void init_linktype(int);
+static void init_linktype(pcap_t *);
static int alloc_reg(void);
static void free_reg(int);
/*
* We divy out chunks of memory rather than call malloc each time so
* we don't have to worry about leaking memory. It's probably
- * not a big deal if all this memory was wasted but it this ever
+ * not a big deal if all this memory was wasted but if this ever
* goes into a library that would probably not be a good idea.
+ *
+ * XXX - this *is* in a library....
*/
#define NCHUNKS 16
#define CHUNK0SIZE 1024
static inline struct block *gen_true(void);
static inline struct block *gen_false(void);
static struct block *gen_ether_linktype(int);
+static struct block *gen_linux_sll_linktype(int);
static struct block *gen_linktype(int);
static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int);
static struct block *gen_llc(int);
}
lex_init(buf ? buf : "");
- init_linktype(pcap_datalink(p));
+ init_linktype(p);
(void)pcap_parse();
if (n_errors)
{
struct slist *s;
struct block *b;
-
+
s = new_stmt(BPF_LD|datasize|BPF_ABS);
s->s.k = offset;
-
+
if (mask != 0xffffffff) {
s->next = new_stmt(BPF_ALU|BPF_AND|BPF_K);
s->next->s.k = mask;
}
-
+
b = new_block(JMP(jtype));
b->stmts = s;
b->s.k = jvalue;
static int linktype;
static void
-init_linktype(type)
- int type;
+init_linktype(p)
+ pcap_t *p;
{
- linktype = type;
+ linktype = pcap_datalink(p);
+#ifdef PCAP_FDDIPAD
+ pcap_fddipad = p->fddipad;
+#endif
/*
* Assume it's not raw ATM with a pseudo-header, for now.
orig_nl = -1;
orig_nl_nosnap = -1;
- switch (type) {
+ switch (linktype) {
case DLT_ARCNET:
off_linktype = 2;
off_nl_nosnap = 12; /* no 802.2 LLC */
return;
- case DLT_PFLOG:
- off_linktype = 0;
- off_nl = 28;
- off_nl_nosnap = 28; /* no 802.2 LLC */
- return;
-
case DLT_PPP:
+ case DLT_PPP_WITHDIRECTION:
case DLT_C_HDLC: /* BSD/OS Cisco HDLC */
case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */
off_linktype = 2;
off_vpi = SUNATM_VPI_POS;
off_vci = SUNATM_VCI_POS;
off_proto = PROTO_POS;
- off_mac = -1; /* LLC-encapsulated, so no MAC-layer header */
+ off_mac = -1; /* LLC-encapsulated, so no MAC-layer header */
off_payload = SUNATM_PKT_BEGIN_POS;
off_linktype = off_payload;
off_nl = off_payload+8; /* 802.2+SNAP */
off_nl_nosnap = 0; /* no 802.2 LLC */
return;
+ case DLT_APPLE_IP_OVER_IEEE1394:
+ off_linktype = 16;
+ off_nl = 18;
+ off_nl_nosnap = 0; /* no 802.2 LLC */
+ return;
+
case DLT_LINUX_IRDA:
/*
* Currently, only raw "link[N:M]" filtering is supported.
off_nl = -1;
off_nl_nosnap = -1;
return;
+
+ case DLT_SYMANTEC_FIREWALL:
+ off_linktype = 6;
+ off_nl = 44; /* Ethernet II */
+ off_nl_nosnap = 44; /* XXX - what does it do with 802.3 packets? */
+ return;
+
+ case DLT_PFLOG:
+ off_linktype = 0;
+ /* XXX read from header? */
+ off_nl = PFLOG_HDRLEN;
+ off_nl_nosnap = PFLOG_HDRLEN;
+ return;
+
+ case DLT_JUNIPER_MLPPP:
+ off_linktype = 4;
+ off_nl = 4;
+ off_nl_nosnap = -1;
+ break;
+
+ case DLT_JUNIPER_ATM1:
+ off_linktype = 4; /* in reality variable between 4-8 */
+ off_nl = 4;
+ off_nl_nosnap = 14;
+ return;
+
+ case DLT_JUNIPER_ATM2:
+ off_linktype = 8; /* in reality variable between 8-12 */
+ off_nl = 8;
+ off_nl_nosnap = 18;
+ return;
+
+#ifdef DLT_PFSYNC
+ case DLT_PFSYNC:
+ off_linktype = -1;
+ off_nl = 4;
+ off_nl_nosnap = 4;
+ return;
+#endif
}
bpf_error("unknown data link type %d", linktype);
/* NOTREACHED */
}
}
+static struct block *
+gen_linux_sll_linktype(proto)
+ register int proto;
+{
+ struct block *b0, *b1;
+
+ switch (proto) {
+
+ case LLCSAP_IP:
+ b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
+ b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
+ ((LLCSAP_IP << 8) | LLCSAP_IP));
+ gen_and(b0, b1);
+ return b1;
+
+ case LLCSAP_ISONS:
+ /*
+ * OSI protocols always use 802.2 encapsulation.
+ * XXX - should we check both the DSAP and the
+ * SSAP, like this, or should we check just the
+ * DSAP?
+ */
+ b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
+ b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
+ ((LLCSAP_ISONS << 8) | LLCSAP_ISONS));
+ gen_and(b0, b1);
+ return b1;
+
+ case LLCSAP_NETBEUI:
+ /*
+ * NetBEUI always uses 802.2 encapsulation.
+ * XXX - should we check both the DSAP and the
+ * LSAP, like this, or should we check just the
+ * DSAP?
+ */
+ b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
+ b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
+ ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI));
+ gen_and(b0, b1);
+ return b1;
+
+ case LLCSAP_IPX:
+ /*
+ * Ethernet_II frames, which are Ethernet
+ * frames with a frame type of ETHERTYPE_IPX;
+ *
+ * Ethernet_802.3 frames, which have a frame
+ * type of LINUX_SLL_P_802_3;
+ *
+ * Ethernet_802.2 frames, which are 802.3
+ * frames with an 802.2 LLC header (i.e, have
+ * a frame type of LINUX_SLL_P_802_2) and
+ * with the IPX LSAP as the DSAP in the LLC
+ * header;
+ *
+ * Ethernet_SNAP frames, which are 802.3
+ * frames with an LLC header and a SNAP
+ * header and with an OUI of 0x000000
+ * (encapsulated Ethernet) and a protocol
+ * ID of ETHERTYPE_IPX in the SNAP header.
+ *
+ * First, do the checks on LINUX_SLL_P_802_2
+ * frames; generate the check for either
+ * Ethernet_802.2 or Ethernet_SNAP frames, and
+ * then put a check for LINUX_SLL_P_802_2 frames
+ * before it.
+ */
+ b0 = gen_cmp(off_linktype + 2, BPF_B,
+ (bpf_int32)LLCSAP_IPX);
+ b1 = gen_snap(0x000000, ETHERTYPE_IPX,
+ off_linktype + 2);
+ gen_or(b0, b1);
+ b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
+ gen_and(b0, b1);
+
+ /*
+ * Now check for 802.3 frames and OR that with
+ * the previous test.
+ */
+ b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_3);
+ gen_or(b0, b1);
+
+ /*
+ * Now add the check for Ethernet_II frames, and
+ * do that before checking for the other frame
+ * types.
+ */
+ b0 = gen_cmp(off_linktype, BPF_H,
+ (bpf_int32)ETHERTYPE_IPX);
+ gen_or(b0, b1);
+ return b1;
+
+ case ETHERTYPE_ATALK:
+ case ETHERTYPE_AARP:
+ /*
+ * EtherTalk (AppleTalk protocols on Ethernet link
+ * layer) may use 802.2 encapsulation.
+ */
+
+ /*
+ * Check for 802.2 encapsulation (EtherTalk phase 2?);
+ * we check for the 802.2 protocol type in the
+ * "Ethernet type" field.
+ */
+ b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
+
+ /*
+ * 802.2-encapsulated ETHERTYPE_ATALK packets are
+ * SNAP packets with an organization code of
+ * 0x080007 (Apple, for Appletalk) and a protocol
+ * type of ETHERTYPE_ATALK (Appletalk).
+ *
+ * 802.2-encapsulated ETHERTYPE_AARP packets are
+ * SNAP packets with an organization code of
+ * 0x000000 (encapsulated Ethernet) and a protocol
+ * type of ETHERTYPE_AARP (Appletalk ARP).
+ */
+ if (proto == ETHERTYPE_ATALK)
+ b1 = gen_snap(0x080007, ETHERTYPE_ATALK,
+ off_linktype + 2);
+ else /* proto == ETHERTYPE_AARP */
+ b1 = gen_snap(0x000000, ETHERTYPE_AARP,
+ off_linktype + 2);
+ gen_and(b0, b1);
+
+ /*
+ * Check for Ethernet encapsulation (Ethertalk
+ * phase 1?); we just check for the Ethernet
+ * protocol type.
+ */
+ b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
+
+ gen_or(b0, b1);
+ return b1;
+
+ default:
+ if (proto <= ETHERMTU) {
+ /*
+ * This is an LLC SAP value, so the frames
+ * that match would be 802.2 frames.
+ * Check for the 802.2 protocol type
+ * in the "Ethernet type" field, and
+ * then check the DSAP.
+ */
+ b0 = gen_cmp(off_linktype, BPF_H,
+ LINUX_SLL_P_802_2);
+ b1 = gen_cmp(off_linktype + 2, BPF_B,
+ (bpf_int32)proto);
+ gen_and(b0, b1);
+ return b1;
+ } else {
+ /*
+ * This is an Ethernet type, so compare
+ * the length/type field with it (if
+ * the frame is an 802.2 frame, the length
+ * field will be <= ETHERMTU, and, as
+ * "proto" is > ETHERMTU, this test
+ * will fail and the frame won't match,
+ * which is what we want).
+ */
+ return gen_cmp(off_linktype, BPF_H,
+ (bpf_int32)proto);
+ }
+ }
+}
+
static struct block *
gen_linktype(proto)
register int proto;
case DLT_EN10MB:
return gen_ether_linktype(proto);
+ /*NOTREACHED*/
break;
case DLT_C_HDLC:
default:
return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
+ /*NOTREACHED*/
break;
}
break;
case DLT_ATM_CLIP:
case DLT_IP_OVER_FC:
return gen_llc(proto);
+ /*NOTREACHED*/
break;
case DLT_SUNATM:
}
case DLT_LINUX_SLL:
- switch (proto) {
-
- case LLCSAP_IP:
- b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
- b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
- ((LLCSAP_IP << 8) | LLCSAP_IP));
- gen_and(b0, b1);
- return b1;
-
- case LLCSAP_ISONS:
- /*
- * OSI protocols always use 802.2 encapsulation.
- * XXX - should we check both the DSAP and the
- * LSAP, like this, or should we check just the
- * DSAP?
- */
- b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
- b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
- ((LLCSAP_ISONS << 8) | LLCSAP_ISONS));
- gen_and(b0, b1);
- return b1;
-
- case LLCSAP_NETBEUI:
- /*
- * NetBEUI always uses 802.2 encapsulation.
- * XXX - should we check both the DSAP and the
- * LSAP, like this, or should we check just the
- * DSAP?
- */
- b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
- b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)
- ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI));
- gen_and(b0, b1);
- return b1;
-
- case LLCSAP_IPX:
- /*
- * Ethernet_II frames, which are Ethernet
- * frames with a frame type of ETHERTYPE_IPX;
- *
- * Ethernet_802.3 frames, which have a frame
- * type of LINUX_SLL_P_802_3;
- *
- * Ethernet_802.2 frames, which are 802.3
- * frames with an 802.2 LLC header (i.e, have
- * a frame type of LINUX_SLL_P_802_2) and
- * with the IPX LSAP as the DSAP in the LLC
- * header;
- *
- * Ethernet_SNAP frames, which are 802.3
- * frames with an LLC header and a SNAP
- * header and with an OUI of 0x000000
- * (encapsulated Ethernet) and a protocol
- * ID of ETHERTYPE_IPX in the SNAP header.
- *
- * First, do the checks on LINUX_SLL_P_802_2
- * frames; generate the check for either
- * Ethernet_802.2 or Ethernet_SNAP frames, and
- * then put a check for LINUX_SLL_P_802_2 frames
- * before it.
- */
- b0 = gen_cmp(off_linktype + 2, BPF_B,
- (bpf_int32)LLCSAP_IPX);
- b1 = gen_snap(0x000000, ETHERTYPE_IPX,
- off_linktype + 2);
- gen_or(b0, b1);
- b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
- gen_and(b0, b1);
-
- /*
- * Now check for 802.3 frames and OR that with
- * the previous test.
- */
- b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_3);
- gen_or(b0, b1);
-
- /*
- * Now add the check for Ethernet_II frames, and
- * do that before checking for the other frame
- * types.
- */
- b0 = gen_cmp(off_linktype, BPF_H,
- (bpf_int32)ETHERTYPE_IPX);
- gen_or(b0, b1);
- return b1;
-
- case ETHERTYPE_ATALK:
- case ETHERTYPE_AARP:
- /*
- * EtherTalk (AppleTalk protocols on Ethernet link
- * layer) may use 802.2 encapsulation.
- */
-
- /*
- * Check for 802.2 encapsulation (EtherTalk phase 2?);
- * we check for the 802.2 protocol type in the
- * "Ethernet type" field.
- */
- b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2);
-
- /*
- * 802.2-encapsulated ETHERTYPE_ATALK packets are
- * SNAP packets with an organization code of
- * 0x080007 (Apple, for Appletalk) and a protocol
- * type of ETHERTYPE_ATALK (Appletalk).
- *
- * 802.2-encapsulated ETHERTYPE_AARP packets are
- * SNAP packets with an organization code of
- * 0x000000 (encapsulated Ethernet) and a protocol
- * type of ETHERTYPE_AARP (Appletalk ARP).
- */
- if (proto == ETHERTYPE_ATALK)
- b1 = gen_snap(0x080007, ETHERTYPE_ATALK,
- off_linktype + 2);
- else /* proto == ETHERTYPE_AARP */
- b1 = gen_snap(0x000000, ETHERTYPE_AARP,
- off_linktype + 2);
- gen_and(b0, b1);
-
- /*
- * Check for Ethernet encapsulation (Ethertalk
- * phase 1?); we just check for the Ethernet
- * protocol type.
- */
- b0 = gen_cmp(off_linktype, BPF_H, (bpf_int32)proto);
-
- gen_or(b0, b1);
- return b1;
-
- default:
- if (proto <= ETHERMTU) {
- /*
- * This is an LLC SAP value, so the frames
- * that match would be 802.2 frames.
- * Check for the 802.2 protocol type
- * in the "Ethernet type" field, and
- * then check the DSAP.
- */
- b0 = gen_cmp(off_linktype, BPF_H,
- LINUX_SLL_P_802_2);
- b1 = gen_cmp(off_linktype + 2, BPF_B,
- (bpf_int32)proto);
- gen_and(b0, b1);
- return b1;
- } else {
- /*
- * This is an Ethernet type, so compare
- * the length/type field with it (if
- * the frame is an 802.2 frame, the length
- * field will be <= ETHERMTU, and, as
- * "proto" is > ETHERMTU, this test
- * will fail and the frame won't match,
- * which is what we want).
- */
- return gen_cmp(off_linktype, BPF_H,
- (bpf_int32)proto);
- }
- }
+ return gen_linux_sll_linktype(proto);
+ /*NOTREACHED*/
break;
case DLT_SLIP:
default:
return gen_false(); /* always false */
}
+ /*NOTREACHED*/
break;
case DLT_PPP:
+ case DLT_PPP_WITHDIRECTION:
case DLT_PPP_SERIAL:
case DLT_PPP_ETHER:
/*
case DLT_NULL:
case DLT_LOOP:
case DLT_ENC:
- case DLT_PFLOG:
/*
* For DLT_NULL, the link-layer header is a 32-bit
* word containing an AF_ value in *host* byte order,
* This means that, when reading a capture file, just
* checking for our AF_INET6 value won't work if the
* capture file came from another OS.
- *
- * XXX - what's the byte order for DLT_PFLOG?
*/
switch (proto) {
}
return (gen_cmp(0, BPF_W, (bpf_int32)proto));
+ case DLT_PFLOG:
+ /*
+ * af field is host byte order in contrast to the rest of
+ * the packet.
+ */
+ if (proto == ETHERTYPE_IP)
+ return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B,
+ (bpf_int32)AF_INET));
+#ifdef INET6
+ else if (proto == ETHERTYPE_IPV6)
+ return (gen_cmp(offsetof(struct pfloghdr, af), BPF_B,
+ (bpf_int32)AF_INET6));
+#endif /* INET6 */
+ else
+ return gen_false();
+ /*NOTREACHED*/
+ break;
+
case DLT_ARCNET:
case DLT_ARCNET_LINUX:
/*
#endif /* INET6 */
case ETHERTYPE_IP:
- b0 = gen_cmp(off_linktype, BPF_B,
+ b0 = gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_IP);
b1 = gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_IP_OLD);
case ETHERTYPE_ARP:
b0 = gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_ARP);
- b1 = gen_cmp(off_linktype, BPF_B,
+ b1 = gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_ARP_OLD);
gen_or(b0, b1);
return (b1);
return (gen_cmp(off_linktype, BPF_B,
(bpf_int32)ARCTYPE_ATALK));
}
+ /*NOTREACHED*/
break;
case DLT_LTALK:
default:
return gen_false();
}
+ /*NOTREACHED*/
break;
case DLT_FRELAY:
default:
return gen_false();
}
+ /*NOTREACHED*/
break;
+ case DLT_JUNIPER_MLPPP:
+ case DLT_JUNIPER_ATM1:
+ case DLT_JUNIPER_ATM2:
+ /* just lets verify the magic number for now -
+ * we may have up to 6 different encapsulations on the wire
+ * and need a lot of heuristics to figure out that the payload
+ * might be;
+ *
+ * FIXME encapsulation specific BPF_ filters
+ */
+ return gen_mcmp(0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
+
case DLT_LINUX_IRDA:
- bpf_error("IrDA link-layer type filtering not implemented");
+ bpf_error("IrDA link-layer type filtering not implemented");
case DLT_DOCSIS:
- bpf_error("DOCSIS link-layer type filtering not implemented");
+ bpf_error("DOCSIS link-layer type filtering not implemented");
}
/*
return b1;
case Q_ISO:
- bpf_error("ISO host filtering not implemented");
+ bpf_error("ISO host filtering not implemented");
default:
abort();
break;
case Q_ISO:
- b1 = gen_linktype(LLCSAP_ISONS);
+ b1 = gen_linktype(LLCSAP_ISONS);
break;
case Q_ESIS:
- b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT);
+ b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT);
break;
case Q_ISIS:
- b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
+ b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT);
break;
case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */
- b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
+ b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */
- b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
+ b0 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */
- b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
- case Q_ISIS_LSP:
- b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
+ case Q_ISIS_LSP:
+ b0 = gen_proto(ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_SNP:
- b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
- b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_CSNP:
- b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_ISIS_PSNP:
- b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
- b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+ b0 = gen_proto(ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
gen_or(b0, b1);
break;
case Q_CLNP:
- b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT);
+ b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT);
break;
case Q_STP:
- b1 = gen_linktype(LLCSAP_8021D);
+ b1 = gen_linktype(LLCSAP_8021D);
break;
case Q_IPX:
- b1 = gen_linktype(LLCSAP_IPX);
+ b1 = gen_linktype(LLCSAP_IPX);
break;
case Q_NETBEUI:
- b1 = gen_linktype(LLCSAP_NETBEUI);
+ b1 = gen_linktype(LLCSAP_NETBEUI);
break;
default:
* XXX - what about SNAP-encapsulated frames?
*/
return gen_cmp(2, BPF_H, (0x03<<8) | v);
+ /*NOTREACHED*/
break;
case DLT_C_HDLC:
bpf_error("Mask syntax for networks only");
/* NOTREACHED */
}
+ /* NOTREACHED */
}
struct block *
return b2;
}
bpf_error("only link-layer/IP broadcast filters supported");
+ /* NOTREACHED */
}
/*
#endif /* INET6 */
}
bpf_error("link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
+ /* NOTREACHED */
}
/*
break;
case DLT_PFLOG:
- b0 = gen_cmp(26, BPF_H,
+ b0 = gen_cmp(offsetof(struct pfloghdr, dir), BPF_B,
(bpf_int32)((dir == 0) ? PF_IN : PF_OUT));
break;
+ case DLT_PPP_WITHDIRECTION:
+ if (dir) {
+ /* match outgoing packets */
+ b0 = gen_cmp(0, BPF_B, PPP_WITHDIRECTION_OUT);
+ } else {
+ /* match incoming packets */
+ b0 = gen_cmp(0, BPF_B, PPP_WITHDIRECTION_IN);
+ }
+ break;
+
+ case DLT_JUNIPER_MLPPP:
+ case DLT_JUNIPER_ATM1:
+ case DLT_JUNIPER_ATM2:
+ /* juniper flags (including direction) are stored
+ * the byte after the 3-byte magic number */
+ if (dir) {
+ /* match outgoing packets */
+ b0 = gen_mcmp(3, BPF_B, 0, 0x01);
+ } else {
+ /* match incoming packets */
+ b0 = gen_mcmp(3, BPF_B, 1, 0x01);
+ }
+ break;
+
default:
bpf_error("inbound/outbound not supported on linktype %d",
linktype);
struct block *
gen_pf_ifname(const char *ifname)
{
- if (linktype != DLT_PFLOG) {
- bpf_error("ifname supported only for DLT_PFLOG");
+ struct block *b0;
+ u_int len, off;
+
+ if (linktype == DLT_PFLOG) {
+ len = sizeof(((struct pfloghdr *)0)->ifname);
+ off = offsetof(struct pfloghdr, ifname);
+ } else {
+ bpf_error("ifname not supported on linktype 0x%x", linktype);
/* NOTREACHED */
}
- if (strlen(ifname) >= 16) {
- bpf_error("ifname interface names can't be larger than 16 characters");
+ if (strlen(ifname) >= len) {
+ bpf_error("ifname interface names can only be %d characters",
+ len-1);
/* NOTREACHED */
}
- return (gen_bcmp(4, strlen(ifname), (const u_char *)ifname));
+ b0 = gen_bcmp(off, strlen(ifname), (const u_char *)ifname);
+ return (b0);
}
+/* PF firewall log matched interface */
+struct block *
+gen_pf_ruleset(char *ruleset)
+{
+ struct block *b0;
+
+ if (linktype != DLT_PFLOG) {
+ bpf_error("ruleset not supported on linktype 0x%x", linktype);
+ /* NOTREACHED */
+ }
+ if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) {
+ bpf_error("ruleset names can only be %ld characters",
+ (long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1));
+ /* NOTREACHED */
+ }
+ b0 = gen_bcmp(offsetof(struct pfloghdr, ruleset),
+ strlen(ruleset), (const u_char *)ruleset);
+ return (b0);
+}
/* PF firewall log rule number */
struct block *
gen_pf_rnr(int rnr)
{
+ struct block *b0;
+
+ if (linktype == DLT_PFLOG) {
+ b0 = gen_cmp(offsetof(struct pfloghdr, rulenr), BPF_W,
+ (bpf_int32)rnr);
+ } else {
+ bpf_error("rnr not supported on linktype 0x%x", linktype);
+ /* NOTREACHED */
+ }
+
+ return (b0);
+}
+
+/* PF firewall log sub-rule number */
+struct block *
+gen_pf_srnr(int srnr)
+{
+ struct block *b0;
+
if (linktype != DLT_PFLOG) {
- bpf_error("rnr supported only for DLT_PFLOG");
+ bpf_error("srnr not supported on linktype 0x%x", linktype);
/* NOTREACHED */
}
- return (gen_cmp(20, BPF_H, (bpf_int32)rnr));
+ b0 = gen_cmp(offsetof(struct pfloghdr, subrulenr), BPF_W,
+ (bpf_int32)srnr);
+ return (b0);
}
/* PF firewall log reason code */
struct block *
gen_pf_reason(int reason)
{
- if (linktype != DLT_PFLOG) {
- bpf_error("reason supported only for DLT_PFLOG");
+ struct block *b0;
+
+ if (linktype == DLT_PFLOG) {
+ b0 = gen_cmp(offsetof(struct pfloghdr, reason), BPF_B,
+ (bpf_int32)reason);
+ } else {
+ bpf_error("reason not supported on linktype 0x%x", linktype);
/* NOTREACHED */
}
- return (gen_cmp(22, BPF_H, (bpf_int32)reason));
+ return (b0);
}
/* PF firewall log action */
struct block *
gen_pf_action(int action)
{
- if (linktype != DLT_PFLOG) {
- bpf_error("action supported only for DLT_PFLOG");
+ struct block *b0;
+
+ if (linktype == DLT_PFLOG) {
+ b0 = gen_cmp(offsetof(struct pfloghdr, action), BPF_B,
+ (bpf_int32)action);
+ } else {
+ bpf_error("action not supported on linktype 0x%x", linktype);
/* NOTREACHED */
}
- return (gen_cmp(24, BPF_H, (bpf_int32)action));
+ return (b0);
}
struct block *
if (vlan_num >= 0) {
struct block *b1;
- b1 = gen_cmp(orig_nl, BPF_H, (bpf_int32)vlan_num);
+ b1 = gen_mcmp(orig_nl, BPF_H, (bpf_int32)vlan_num, 0x0fff);
+ gen_and(b0, b1);
+ b0 = b1;
+ }
+
+ return (b0);
+}
+
+/*
+ * support for MPLS
+ */
+struct block *
+gen_mpls(label_num)
+ int label_num;
+{
+ struct block *b0;
+
+ /*
+ * Change the offsets to point to the type and data fields within
+ * the MPLS packet. This is somewhat of a kludge.
+ */
+ if (orig_nl == (u_int)-1) {
+ orig_linktype = off_linktype; /* save original values */
+ orig_nl = off_nl;
+ orig_nl_nosnap = off_nl_nosnap;
+
+ switch (linktype) {
+
+ case DLT_EN10MB:
+ off_linktype = 16;
+ off_nl_nosnap = 18;
+ off_nl = 18;
+
+ b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_MPLS);
+ break;
+
+ case DLT_PPP:
+ off_linktype = 6;
+ off_nl_nosnap = 8;
+ off_nl = 8;
+
+ b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)PPP_MPLS_UCAST);
+ break;
+
+ case DLT_C_HDLC:
+ off_linktype = 6;
+ off_nl_nosnap = 8;
+ off_nl = 8;
+
+ b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_MPLS);
+ break;
+
+ /* FIXME add other DLT_s ...
+ * for Frame-Relay/and ATM this may get messy due to SNAP headers
+ * leave it for now */
+
+ default:
+ bpf_error("no MPLS support for data link type %d",
+ linktype);
+ /*NOTREACHED*/
+ }
+ } else {
+ bpf_error("'mpls' can't be combined with 'vlan' or another 'mpls'");
+ /*NOTREACHED*/
+ }
+
+ /* If a specific MPLS label is requested, check it */
+ if (label_num >= 0) {
+ struct block *b1;
+
+ label_num = label_num << 12; /* label is shifted 12 bits on the wire */
+ b1 = gen_mcmp(orig_nl, BPF_W, (bpf_int32)label_num, 0xfffff000); /* only compare the first 20 bits */
gen_and(b0, b1);
b0 = b1;
}
break;
case A_CALLPROCEED:
- b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
break;
case A_CONNECT:
b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0);
- break;
+ break;
case A_CONNECTACK:
- b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
break;
case A_RELEASE:
break;
case A_RELEASE_DONE:
- b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
+ b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
break;
default:
if (!is_atm)
bpf_error("'oamf4' supported only on raw ATM");
/* OAM F4 type */
- b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
+ b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0);
b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0);
- gen_or(b0, b1);
+ gen_or(b0, b1);
b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0);
gen_and(b0, b1);
break;