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

Reply via email to