Folks...

I'm working on a packet classification package which uses the BPF VM
as the core.  One of the important features of the package is that
a classification point can be anywhere... with link-level headers or
without.

I'm using libpcap to compile the rules for the classification engine,
and found that a new DLT was needed in order to express all of the
possible filtering points.  Basically, I needed a generalization of
DLT_RAW (which means "raw IPv4").

What I came up with is called DLT_RAWAF(family).  So, DLT_RAW,
strictly interpreted[*], would be DLT_RAWAF(AF_INET).

[*] Unfortunately, DLT_RAW right now is hacked to match IPv4
and IPv6, so a corresponding hack in the DLT_RAWAF() support
is necessary to provide backwards-compatible behavior.

There are two parts here, only one of which is supplied as a diff (NetBSD
has split the DLT_* contents into a separate file, so they can be used
separately from BPF).

The first part is the new DLT_* stuff:

/*
 * Generic "raw" link type.  The upper 16-bits indicate that this is
 * the generic raw type, and the lower 16-bits are the address family
 * we're dealing with.
 */
#define DLT_RAWAF_MASK          0x02240000
#define DLT_RAWAF(af)           (DLT_RAWAF_MASK | (af))
#define DLT_RAWAF_AF(x)         ((x) & 0x0000ffff)
#define DLT_IS_RAWAF(x)         (((x) & 0xffff0000) == DLT_RAWAF_MASK)

And attached is the diff to gencode.c that I committed to the version of
libpcap in NetBSD to support the new DLT_RAWAF() (RCS ID change trimmed).

-- 
        -- Jason R. Thorpe <[EMAIL PROTECTED]>
Index: gencode.c
===================================================================
RCS file: /cvsroot/basesrc/lib/libpcap/gencode.c,v
retrieving revision 1.24
retrieving revision 1.25
diff -c -r1.24 -r1.25
*** gencode.c   2000/10/06 16:39:24     1.24
--- gencode.c   2000/12/28 22:04:22     1.25
***************
*** 533,543 ****
  /*
   * Various code constructs need to know the layout of the data link
   * layer.  These variables give the necessary offsets.  off_linktype
!  * is set to -1 for no encapsulation, in which case, IP is assumed.
   */
  static u_int off_linktype;
  static u_int off_nl;
  static int linktype;
  
  static void
  init_linktype(type)
--- 533,547 ----
  /*
   * Various code constructs need to know the layout of the data link
   * layer.  These variables give the necessary offsets.  off_linktype
!  * is set to -1 for no encapsulation, in which case the check is then
!  * deferred to linktype_af.  If that is AF_UNSPEC, AF_INET and AF_INET6
!  * are allowed, for backwards compatibility.  Otherwise, it is the
!  * family to expect.
   */
  static u_int off_linktype;
  static u_int off_nl;
  static int linktype;
+ static int linktype_af;
  
  static void
  init_linktype(type)
***************
*** 545,550 ****
--- 549,561 ----
  {
        linktype = type;
  
+       if (DLT_IS_RAWAF(type)) {
+               off_linktype = -1;
+               off_nl = 0;
+               linktype_af = DLT_RAWAF_AF(type);
+               return;
+       }
+ 
        switch (type) {
  
        case DLT_ARCNET:
***************
*** 564,569 ****
--- 575,581 ----
                 */
                off_linktype = -1;
                off_nl = 16;
+               linktype_af = AF_INET;
                return;
  
        case DLT_SLIP_BSDOS:
***************
*** 641,646 ****
--- 653,659 ----
        case DLT_RAW:
                off_linktype = -1;
                off_nl = 0;
+               linktype_af = AF_UNSPEC;
                return;
        }
        bpf_error("libpcap: unknown data link type 0x%x", linktype);
***************
*** 679,693 ****
        register int proto;
  {
        struct block *b0, *b1;
  
!       /* If we're not using encapsulation and checking for IP, we're done */
!       if (off_linktype == -1 && proto == ETHERTYPE_IP)
!               return gen_true();
! #ifdef INET6
!       /* this isn't the right thing to do, but sometimes necessary */
!       if (off_linktype == -1 && proto == ETHERTYPE_IPV6)
!               return gen_true();
  #endif
  
        switch (linktype) {
  
--- 692,735 ----
        register int proto;
  {
        struct block *b0, *b1;
+ 
+       /*
+        * If we're not using encapsulation, compare the proto against
+        * the one we're expecting.
+        *
+        * Note: this catches the RAWAF case.
+        */
+       if (off_linktype == -1) {
+               switch (linktype_af) {
+               case AF_UNSPEC:
+                       if (proto == ETHERTYPE_IP)
+                               return gen_true();
+ #ifdef INET6
+                       /*
+                        * This isn't the right thing to do, but sometimes
+                        * it is necessary.
+                        */
+                       if (proto == ETHERTYPE_IPV6)
+                               return gen_true();
+ #endif
+                       break;
  
!               case AF_INET:
!                       if (proto == ETHERTYPE_IP)
!                               return gen_true();
!                       else
!                               return gen_false();
!                       break;
! #ifdef INET6
!               case AF_INET6:
!                       if (proto == ETHERTYPE_IPV6)
!                               return gen_true();
!                       else
!                               return gen_false();
!                       break;
  #endif
+               }
+       }
  
        switch (linktype) {
  
***************
*** 737,751 ****
                break;
  
        case DLT_NULL:
!               /* XXX */
!               if (proto == ETHERTYPE_IP)
                        return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET)));
  #ifdef INET6
!               else if (proto == ETHERTYPE_IPV6)
                        return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET6)));
! #endif /* INET6 */
!               else
                        return gen_false();
                break;
        case DLT_ARCNET:
                /*
--- 779,796 ----
                break;
  
        case DLT_NULL:
!               switch (proto) {
!               case ETHERTYPE_IP:
                        return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET)));
+                       break;
  #ifdef INET6
!               case ETHERTYPE_IPV6:
                        return (gen_cmp(0, BPF_W, (bpf_int32)htonl(AF_INET6)));
!                       break;
! #endif
!               default:
                        return gen_false();
+               }
                break;
        case DLT_ARCNET:
                /*
***************
*** 2084,2090 ****
                        if (alist == NULL || *alist == NULL)
                                bpf_error("unknown host '%s'", name);
                        tproto = proto;
!                       if (off_linktype == -1 && tproto == Q_DEFAULT)
                                tproto = Q_IP;
                        b = gen_host(**alist++, 0xffffffff, tproto, dir);
                        while (*alist) {
--- 2129,2138 ----
                        if (alist == NULL || *alist == NULL)
                                bpf_error("unknown host '%s'", name);
                        tproto = proto;
!                       if (off_linktype == -1 &&
!                           (linktype_af == AF_UNSPEC ||
!                            linktype_af == AF_INET) &&
!                           tproto == Q_DEFAULT)
                                tproto = Q_IP;
                        b = gen_host(**alist++, 0xffffffff, tproto, dir);
                        while (*alist) {
***************
*** 2101,2107 ****
                                bpf_error("unknown host '%s'", name);
                        b = tmp = NULL;
                        tproto = tproto6 = proto;
!                       if (off_linktype == -1 && tproto == Q_DEFAULT) {
                                tproto = Q_IP;
                                tproto6 = Q_IPV6;
                        }
--- 2149,2159 ----
                                bpf_error("unknown host '%s'", name);
                        b = tmp = NULL;
                        tproto = tproto6 = proto;
!                       if (off_linktype == -1 &&
!                           (linktype_af == AF_UNSPEC ||
!                            linktype_af == AF_INET ||
!                            linktype_af == AF_INET6) &&
!                           tproto == Q_DEFAULT) {
                                tproto = Q_IP;
                                tproto6 = Q_IPV6;
                        }
***************
*** 2110,2115 ****
--- 2162,2171 ----
                                case AF_INET:
                                        if (tproto == Q_IPV6)
                                                continue;
+                                       if (off_linktype == -1 &&
+                                           (linktype_af != AF_INET &&
+                                            linktype_af != AF_UNSPEC))
+                                               continue;
  
                                        sin = (struct sockaddr_in *)
                                                res->ai_addr;
***************
*** 2118,2123 ****
--- 2174,2183 ----
                                        break;
                                case AF_INET6:
                                        if (tproto6 == Q_IP)
+                                               continue;
+                                       if (off_linktype == -1 &&
+                                           (linktype_af != AF_INET6 &&
+                                            linktype_af != AF_UNSPEC))
                                                continue;
  
                                        sin6 = (struct sockaddr_in6 *)

PGP signature

Reply via email to