*/
#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.49 2007-06-13 22:51:07 gianluca Exp $ (LBL)";
+ "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.221.2.54 2007-10-26 00:47:36 guy Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
#include "ppp.h"
#include "sll.h"
#include "arcnet.h"
-#include "pf.h"
+#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
static jmp_buf top_ctx;
static pcap_t *bpf_pcap;
+#ifdef WIN32
/* Hack for updating VLAN, MPLS, and PPPoE offsets. */
+static u_int orig_linktype = (u_int)-1, orig_nl = (u_int)-1, label_stack_depth = (u_int)-1;
+#else
static u_int orig_linktype = -1U, orig_nl = -1U, label_stack_depth = -1U;
+#endif
/* XXX */
#ifdef PCAP_FDDIPAD
static void init_linktype(pcap_t *);
+static void init_regs(void);
static int alloc_reg(void);
static void free_reg(int);
static struct block *gen_mac_multicast(int);
static struct block *gen_len(int, int);
+static struct block *gen_ppi_dlt_check(void);
static struct block *gen_msg_abbrev(int type);
static void *
n_errors = 0;
root = NULL;
bpf_pcap = p;
+ init_regs();
if (setjmp(top_ctx)) {
lex_cleanup();
freechunks();
*p = b1;
}
+
void
finish_parse(p)
struct block *p;
{
+ struct block *ppi_dlt_check;
+
+ ppi_dlt_check = gen_ppi_dlt_check();
+
+ if (ppi_dlt_check != NULL)
+ {
+ gen_and(ppi_dlt_check, p);
+ }
+
backpatch(p, gen_retblk(snaplen));
p->sense = !p->sense;
backpatch(p, gen_retblk(0));
* require the length of that header, doing more for that
* header length isn't really worth the effort.
*/
+
insert_load_llprefixlen(root);
}
/*
- * TODO GV
- *
* At the moment we treat PPI as normal Radiotap encoded
* packets. The difference is in the function that generates
* the code at the beginning to compute the header length.
* Since this code generator of PPI supports bare 802.11
* encapsulation only (i.e. the encapsulated DLT should be
- * DLT_IEEE802_11) we should generate code to check for this.
- * Unfortunately given the current structure of the code generator,
- * generating the proper JMP(x) code to be prepended is problematic.
- * We just ignore the DLT in the PPI header.
- *
+ * DLT_IEEE802_11) we generate code to check for this too.
*/
case DLT_PPI:
case DLT_IEEE802_11_RADIO:
off_nl_nosnap = 44; /* XXX - what does it do with 802.3 packets? */
return;
+#ifdef HAVE_NET_PFVAR_H
case DLT_PFLOG:
off_linktype = 0;
- /* XXX read this from pf.h? */
off_nl = PFLOG_HDRLEN;
off_nl_nosnap = PFLOG_HDRLEN; /* no 802.2 LLC */
return;
+#endif
case DLT_JUNIPER_MFR:
case DLT_JUNIPER_MLFR:
off_nl_nosnap = -1;
return;
+ case DLT_MTP2_WITH_PHDR:
+ off_li = 6;
+ off_sio = 7;
+ off_opc = 8;
+ off_dpc = 8;
+ off_sls = 11;
+ off_linktype = -1;
+ off_nl = -1;
+ off_nl_nosnap = -1;
+ return;
+
#ifdef DLT_PFSYNC
case DLT_PFSYNC:
off_linktype = -1;
}
/*
- * TODO GV
- *
* At the moment we treat PPI as normal Radiotap encoded
* packets. The difference is in the function that generates
* the code at the beginning to compute the header length.
* Since this code generator of PPI supports bare 802.11
* encapsulation only (i.e. the encapsulated DLT should be
- * DLT_IEEE802_11) we should generate code to check for this.
- * Unfortunately given the current structure of the code generator,
- * generating the proper JMP(x) code to be prepended is problematic.
- * We just ignore the DLT in the PPI header.
- *
+ * DLT_IEEE802_11) we generate code to check for this too.
*/
static void
insert_ppi_load_llprefixlen(b)
struct block *b;
{
struct slist *s1, *s2;
-
+
/*
* Prepend to the statements in this block code to load the
* length of the radiotap header into the register assigned
* to hold that length, if one has been assigned.
*/
if (reg_ll_size != -1) {
- /*
+ /*
* The 2 bytes at offsets of 2 and 3 from the beginning
* of the radiotap header are the length of the radiotap
* header; unfortunately, it's little-endian, so we have
*/
sappend(s1, b->stmts);
b->stmts = s1;
+
+ }
+}
+
+static struct block *
+gen_ppi_dlt_check(void)
+{
+ struct slist *s_load_dlt;
+ struct block *b;
+
+ if (linktype == DLT_PPI)
+ {
+ /* Create the statements that check for the DLT
+ */
+ s_load_dlt = new_stmt(BPF_LD|BPF_W|BPF_ABS);
+ s_load_dlt->s.k = 4;
+
+ b = new_block(JMP(BPF_JEQ));
+
+ b->stmts = s_load_dlt;
+ b->s.k = SWAPLONG(DLT_IEEE802_11);
}
+ else
+ {
+ b = NULL;
+ }
+
+ return b;
}
static void
switch (linktype) {
/*
- * TODO GV
- *
* At the moment we treat PPI as normal Radiotap encoded
* packets. The difference is in the function that generates
* the code at the beginning to compute the header length.
* Since this code generator of PPI supports bare 802.11
* encapsulation only (i.e. the encapsulated DLT should be
- * DLT_IEEE802_11) we should generate code to check for this.
- * Unfortunately given the current structure of the code generator,
- * generating the proper JMP(x) code to be prepended is problematic.
- * We just ignore the DLT in the PPI header.
- *
+ * DLT_IEEE802_11) we generate code to check for this too.
*/
case DLT_PPI:
insert_ppi_load_llprefixlen(b);
}
/*
- * TODO GV
- *
* At the moment we treat PPI as normal Radiotap encoded
* packets. The difference is in the function that generates
* the code at the beginning to compute the header length.
* Since this code generator of PPI supports bare 802.11
* encapsulation only (i.e. the encapsulated DLT should be
- * DLT_IEEE802_11) we should generate code to check for this.
- * Unfortunately given the current structure of the code generator,
- * generating the proper JMP(x) code to be prepended is problematic.
- * We just ignore the DLT in the PPI header.
- *
+ * DLT_IEEE802_11) we generate code to check for this too.
*/
static struct slist *
gen_ppi_llprefixlen(void)
}
return (gen_cmp(OR_LINK, 0, BPF_W, (bpf_int32)proto));
+#ifdef HAVE_NET_PFVAR_H
case DLT_PFLOG:
/*
* af field is host byte order in contrast to the rest of
return gen_false();
/*NOTREACHED*/
break;
+#endif /* HAVE_NET_PFVAR_H */
case DLT_ARCNET:
case DLT_ARCNET_LINUX:
tmp = gen_mcmp(OR_NET, 2, BPF_H,
(bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
b1 = gen_cmp(OR_NET, 2 + 1 + offset_lh,
- BPF_H, (bpf_int32)ntohs(addr));
+ BPF_H, (bpf_int32)ntohs((u_short)addr));
gen_and(tmp, b1);
/* Check for pad = 0, long header case */
tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
- b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32)ntohs(addr));
+ b2 = gen_cmp(OR_NET, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr));
gen_and(tmp, b2);
gen_or(b2, b1);
/* Check for pad = 1, short header case */
tmp = gen_mcmp(OR_NET, 2, BPF_H,
(bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
- b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs(addr));
+ b2 = gen_cmp(OR_NET, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
gen_and(tmp, b2);
gen_or(b2, b1);
/* Check for pad = 0, short header case */
tmp = gen_mcmp(OR_NET, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
- b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32)ntohs(addr));
+ b2 = gen_cmp(OR_NET, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
gen_and(tmp, b2);
gen_or(b2, b1);
static int regused[BPF_MEMWORDS];
static int curreg;
+/*
+ * Initialize the table of used registers and the current register.
+ */
+static void
+init_regs()
+{
+ curreg = 0;
+ memset(regused, 0, sizeof regused);
+}
+
/*
* Return the next free register.
*/
}
break;
+#ifdef HAVE_NET_PFVAR_H
case DLT_PFLOG:
b0 = gen_cmp(OR_LINK, offsetof(struct pfloghdr, dir), BPF_B,
(bpf_int32)((dir == 0) ? PF_IN : PF_OUT));
break;
+#endif
case DLT_PPP_PPPD:
if (dir) {
return (b0);
}
+#ifdef HAVE_NET_PFVAR_H
/* PF firewall log matched interface */
struct block *
gen_pf_ifname(const char *ifname)
return (b0);
}
+#else /* !HAVE_NET_PFVAR_H */
+struct block *
+gen_pf_ifname(const char *ifname)
+{
+ bpf_error("libpcap was compiled without pf support");
+ /* NOTREACHED */
+ return (NULL);
+}
+
+struct block *
+gen_pf_ruleset(char *ruleset)
+{
+ bpf_error("libpcap was compiled on a machine without pf support");
+ /* NOTREACHED */
+ return (NULL);
+}
+
+struct block *
+gen_pf_rnr(int rnr)
+{
+ bpf_error("libpcap was compiled on a machine without pf support");
+ /* NOTREACHED */
+ return (NULL);
+}
+
+struct block *
+gen_pf_srnr(int srnr)
+{
+ bpf_error("libpcap was compiled on a machine without pf support");
+ /* NOTREACHED */
+ return (NULL);
+}
+
+struct block *
+gen_pf_reason(int reason)
+{
+ bpf_error("libpcap was compiled on a machine without pf support");
+ /* NOTREACHED */
+ return (NULL);
+}
+
+struct block *
+gen_pf_action(int action)
+{
+ bpf_error("libpcap was compiled on a machine without pf support");
+ /* NOTREACHED */
+ return (NULL);
+}
+#endif /* HAVE_NET_PFVAR_H */
struct block *
gen_acode(eaddr, q)
switch (type) {
case M_FISU:
- if (linktype != DLT_MTP2)
+ if ( (linktype != DLT_MTP2) &&
+ (linktype != DLT_MTP2_WITH_PHDR) )
bpf_error("'fisu' supported only on MTP2");
/* gen_ncmp(offrel, offset, size, mask, jtype, reverse, value) */
b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0);
break;
case M_LSSU:
- if (linktype != DLT_MTP2)
+ if ( (linktype != DLT_MTP2) &&
+ (linktype != DLT_MTP2_WITH_PHDR) )
bpf_error("'lssu' supported only on MTP2");
b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 1, 2);
b1 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 0);
break;
case M_MSU:
- if (linktype != DLT_MTP2)
+ if ( (linktype != DLT_MTP2) &&
+ (linktype != DLT_MTP2_WITH_PHDR) )
bpf_error("'msu' supported only on MTP2");
b0 = gen_ncmp(OR_PACKET, off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
break;