Hello,
I've been working on extending the way 802.1Q VLANs are supported by
libpcap. The current implementation simply shifts the offsets to the left
four bytes, thus pointing to the beginning of the data in tagged frames.
This however doesn't work for traffic on the native VLAN.
Traffic on the native VLAN is ignored, perhaps sometimes erroneously
reported. Since our offsets are off by 4 for these packets, other header
information at that location may match the requested pattern.
I started trying to implement the ability to distinguish between tagged and
untagged frames. I did this by adding BPF code that looks to see if the
ethertype is set to tagged, if so then the packet data begins at point x,
otherwise it beigns at point y.
However, when I run a tcpdump linked to my locally modified library I get
the following error:
rivendell# ./tcpdump port 110
tcpdump: no destination found for block-local relative jump: off=1
However, if I turn off the optimizer I get legitimate code. (Which I've
attached as well).
I think this is something that happens in the BPF optimizer that munges the
BPF that I generated.
I've included patches for what I've done to date. This doesn't include
linkage to the "vlan" command which is understood by the parser.
In case you're skimming: ** THESE PATCHES DON'T WORK YET **
Does anyone out there have any suggestions as to how to track down optimizer
problems? Also, I imagine there is a more elegant way to integrate my
changes -- I was simply going for a proof of concept here, any input on how
to improve this would be greatly appreciated.
Thanks,
Jon
--
Jon Dugan | Senior Network Engineer, NCSA Network Development
[EMAIL PROTECTED] | 269 CAB, 605 E Springfield, Champaign, IL 61820
217-244-7715 | http://www.ncsa.uiuc.edu/people/jdugan
Index: gencode.c
===================================================================
RCS file: /tcpdump/master/libpcap/gencode.c,v
retrieving revision 1.157
diff -c -r1.157 gencode.c
*** gencode.c 2001/07/03 19:15:47 1.157
--- gencode.c 2001/08/15 01:02:39
***************
*** 78,83 ****
--- 78,85 ----
static jmp_buf top_ctx;
static pcap_t *bpf_pcap;
+ static int vlan_reg = -1;
+
/* XXX */
#ifdef PCAP_FDDIPAD
int pcap_fddipad = PCAP_FDDIPAD;
***************
*** 452,460 ****
{
struct slist *s;
struct block *b;
! s = new_stmt(BPF_LD|BPF_ABS|size);
! s->s.k = offset;
b = new_block(JMP(BPF_JEQ));
b->stmts = s;
--- 454,465 ----
{
struct slist *s;
struct block *b;
+
+ s = new_stmt(BPF_LDX|BPF_MEM|BPF_W);
+ s->s.k = vlan_reg;
! s->next = new_stmt(BPF_LD|BPF_IND|size);
! s->next->s.k = offset;
b = new_block(JMP(BPF_JEQ));
b->stmts = s;
***************
*** 470,478 ****
{
struct slist *s;
struct block *b;
! s = new_stmt(BPF_LD|BPF_ABS|size);
! s->s.k = offset;
b = new_block(JMP(BPF_JGT));
b->stmts = s;
--- 475,486 ----
{
struct slist *s;
struct block *b;
+
+ s = new_stmt(BPF_LDX|BPF_MEM|BPF_W);
+ s->s.k = vlan_reg;
! s->next = new_stmt(BPF_LD|BPF_IND|size);
! s->next->s.k = offset;
b = new_block(JMP(BPF_JGT));
b->stmts = s;
***************
*** 495,500 ****
--- 503,509 ----
s->s.k = mask;
b->stmts->next = s;
}
+
return b;
}
***************
*** 748,758 ****
--- 757,829 ----
register int proto;
{
struct block *b0, *b1;
+ struct block ldx;
+ int i,fix1,fix2;
+ struct slist *s[32],*sn;
switch (linktype) {
case DLT_EN10MB:
+ i = 0;
+
+ if(vlan_reg == -1) {
+ vlan_reg = alloc_reg();
+
+ printf("i=%d\n",i);
+
+ /* A = ethertype */
+ s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_H);
+ s[i]->s.k = off_linktype;
+ i++;
+
+ /* if ethertype is 802.1Q then set register to skip tag */
+ s[i] = new_stmt(BPF_JMP|BPF_JEQ);
+ s[i]->s.k = ETHERTYPE_8021Q;
+ s[i]->s.jt = NULL;
+ s[i]->s.jf = NULL;
+ fix1 = i;
+ i++;
+
+
+ /* skip vlan tags */
+ s[i] = new_stmt(BPF_LD|BPF_IMM|BPF_W);
+ s[i]->s.k = 4;
+ s[fix1]->s.jt = s[i];
+ i++;
+ s[i] = new_stmt(BPF_ST);
+ s[i]->s.k = vlan_reg;
+ i++;
+ s[i] = new_stmt(BPF_JMP|BPF_JA);
+ fix2 = i;
+ i++;
+
+ /* no vlan tags to skip */
+ s[i] = new_stmt(BPF_LD|BPF_IMM|BPF_W);
+ s[i]->s.k = 0;
+ s[fix1]->s.jf = s[i];
+ i++;
+ s[i] = new_stmt(BPF_ST);
+ s[i]->s.k = vlan_reg;
+
+ s[fix2]->s.k = i-fix2;
+
+ /* thread it up */
+ fix1 = i;
+ while(--fix1 > -1) {
+ s[fix1]->next = s[fix1+1];
+ printf("i=%d\n",fix1);
+ }
+ }
+
switch (proto) {
+
+ case ETHERTYPE_IP:
+ b1 = gen_cmp(off_linktype, BPF_H, ETHERTYPE_IP);
+ if(i) {
+ s[i]->next = b1->stmts;
+ b1->stmts = s[0];
+ }
+ return b1;
case LLCSAP_ISONS:
/*
***************
*** 2201,2209 ****
struct slist *s;
struct block *b;
/* not ip frag */
! s = new_stmt(BPF_LD|BPF_H|BPF_ABS);
! s->s.k = off_nl + 6;
b = new_block(JMP(BPF_JSET));
b->s.k = 0x1fff;
b->stmts = s;
--- 2272,2283 ----
struct slist *s;
struct block *b;
+ s = new_stmt(BPF_LDX|BPF_MEM|BPF_W);
+ s->s.k = vlan_reg;
+
/* not ip frag */
! s->next = new_stmt(BPF_LD|BPF_H|BPF_IND);
! s->next->s.k = off_nl + 6;
b = new_block(JMP(BPF_JSET));
b->s.k = 0x1fff;
b->stmts = s;
***************
*** 2212,2231 ****
return b;
}
static struct block *
gen_portatom(off, v)
int off;
bpf_int32 v;
{
! struct slist *s;
struct block *b;
! s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
! s->s.k = off_nl;
! s->next = new_stmt(BPF_LD|BPF_IND|BPF_H);
! s->next->s.k = off_nl + off;
b = new_block(JMP(BPF_JEQ));
b->stmts = s;
b->s.k = v;
--- 2286,2355 ----
return b;
}
+ static struct slist *
+ gen_msh()
+ {
+ struct slist *s,*s0,*s1,*j;
+
+ s = s0 = new_stmt(BPF_LD|BPF_MEM|BPF_W);
+ s->s.k = vlan_reg;
+
+ s1 = new_stmt(BPF_JMP|BPF_JEQ);
+ s1->s.jt = NULL;
+ s1->s.jf = NULL;
+ j = s1;
+ s0->next = s1;
+ s0 = s1;
+
+ /* MSH for untagged frames */
+ s1 = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
+ s1->s.k = off_nl;
+ s0->next = s1;
+ j->s.jt = s1;
+ s0 = s1;
+
+ s1 = new_stmt(BPF_JMP|BPF_JA);
+ s1->s.k = 1;
+ s0->next = s1;
+ s0 = s1;
+
+ /* MSH for tagged frames */
+ s1 = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
+ s1->s.k = off_nl + 4;
+ s0->next = s1;
+ j->s.jf = s1;
+ s0 = s1;
+
+ return s;
+ }
+
static struct block *
gen_portatom(off, v)
int off;
bpf_int32 v;
{
! struct slist *s,*s0,*s1,*j;
struct block *b;
+
+ s = s0 = gen_msh();
! s1 = new_stmt(BPF_LD|BPF_MEM|BPF_W);
! s1->s.k = vlan_reg;
! s0->next = s1;
! s0 = s1;
! s1 = new_stmt(BPF_ALU|BPF_ADD|BPF_X);
! s0->next = s1;
! s0 = s1;
+ s1 = new_stmt(BPF_MISC|BPF_TAX);
+ s0->next = s1;
+ s0 = s1;
+
+ s1 = new_stmt(BPF_LD|BPF_IND|BPF_H);
+ s1->s.k = off_nl + off;
+ s0->next = s1;
+
b = new_block(JMP(BPF_JEQ));
b->stmts = s;
b->s.k = v;
***************
*** 2495,2504 ****
--- 2619,2630 ----
s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B);
s[i]->s.k = off_nl + 9;
i++;
+ #if 0
/* X = ip->ip_hl << 2 */
s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
s[i]->s.k = off_nl;
i++;
+ #endif
break;
#ifdef INET6
case Q_IPV6:
***************
*** 3417,3424 ****
case Q_IGRP:
case Q_PIM:
case Q_VRRP:
! s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
! s->s.k = off_nl;
sappend(s, xfer_to_a(index));
sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
sappend(s, new_stmt(BPF_MISC|BPF_TAX));
--- 3543,3549 ----
case Q_IGRP:
case Q_PIM:
case Q_VRRP:
! s = gen_msh();
sappend(s, xfer_to_a(index));
sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X));
sappend(s, new_stmt(BPF_MISC|BPF_TAX));
(000) ldh [12]
(001) jeq #0x8100 jt 2 jf 5
(002) ld #0x4
(003) st M[0]
(004) ja 7
(005) ld #0x0
(006) st M[0]
(007) ldx M[0]
(008) ldh [x + 12]
(009) jeq #0x800 jt 10 jf 65
(010) ldx M[0]
(011) ldb [x + 23]
(012) jeq #0x84 jt 13 jf 28
(013) ldx M[0]
(014) ldh [x + 20]
(015) jset #0x1fff jt 28 jf 16
(016) ld M[0]
(017) ld M[0]
(018) add x
(019) tax
(020) ldh [x + 14]
(021) jeq #0x6e jt 64 jf 22
(022) ld M[0]
(023) ld M[0]
(024) add x
(025) tax
(026) ldh [x + 16]
(027) jeq #0x6e jt 64 jf 28
(028) ldx M[0]
(029) ldb [x + 23]
(030) jeq #0x6 jt 31 jf 46
(031) ldx M[0]
(032) ldh [x + 20]
(033) jset #0x1fff jt 46 jf 34
(034) ld M[0]
(035) ld M[0]
(036) add x
(037) tax
(038) ldh [x + 14]
(039) jeq #0x6e jt 64 jf 40
(040) ld M[0]
(041) ld M[0]
(042) add x
(043) tax
(044) ldh [x + 16]
(045) jeq #0x6e jt 64 jf 46
(046) ldx M[0]
(047) ldb [x + 23]
(048) jeq #0x11 jt 49 jf 65
(049) ldx M[0]
(050) ldh [x + 20]
(051) jset #0x1fff jt 65 jf 52
(052) ld M[0]
(053) ld M[0]
(054) add x
(055) tax
(056) ldh [x + 14]
(057) jeq #0x6e jt 64 jf 58
(058) ld M[0]
(059) ld M[0]
(060) add x
(061) tax
(062) ldh [x + 16]
(063) jeq #0x6e jt 64 jf 65
(064) ret #96
(065) ret #0