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