To pursue this a little further, experimenting has
determined that the best layout thus far would be
something similar to this:
bits field
00-07 version (1)
08-15 pad (0)
16-31 pre-mac payload length
32-63 dlt (DLT_*)
64-79 ethernet protocol number
80-95 pad (0)
The pads are to ensure that fields start on byte boundaries
that align with their sizes. Similarly, the final pad is to
ensure that this header has minimal impact on any alignment
requirements of data that follows it. The pre-mac payload
length is the length of all data (i.e in most cases this
will be the combined length of the above header and the mac
header) that preceeds the mac payload (where the IP header
starts.)
The design of the above is to facilitate being able to
generate a simple BPF instruction set that allows filter
expressions on network protocols.
With a few tweaks to gencode.c (see attachment),
it seems to work:
# ./tcpdump -d -vi net0 ip and tcp port 80
(000) ldh [2]
(001) st M[0]
(002) ldh [8]
(003) jeq #0x800 jt 4 jf 25
(004) ldx M[0]
(005) ldb [x + 9]
(006) jeq #0x6 jt 7 jf 25
(007) ldh [x + 6]
(008) jset #0x1fff jt 25 jf 9
(009) ldb [x + 0]
(010) and #0xf
(011) lsh #2
(012) add x
(013) tax
(014) ldh [x + 0]
(015) jeq #0x50 jt 24 jf 16
(016) ldx M[0]
(017) ldb [x + 0]
(018) and #0xf
(019) lsh #2
(020) add x
(021) tax
(022) ldh [x + 2]
(023) jeq #0x50 jt 24 jf 25
(024) ret #65535
(025) ret #0
The premise of the above is that no matter what the
payload is after the mac header, that it will have
a corresponding ethernet protocol number.
Thus even though a "packet" for DLT_NULL on NetBSD
might have AF_INET in the DLT_NULL header, the value
for "proto" in the above header would be ETHERTYPE_IP
(0x0800). It is the responsibility of the code that
is constructing the header to make this translation.
The presence of the dlt field in the header allows the
entire packet to be printed out by tcpdump, etc, as it
unravels the packet headers.
The attached diff uses DLT_LINK and unless anyone has
an objection, I'd like to request that this name be
assigned a DLT number that's associated with the header
described above.
Thoughts? Comments?
Darren
diff --git a/gencode.c b/gencode.c
index b94ea72..8aa5727 100644
--- a/gencode.c
+++ b/gencode.c
@@ -1598,6 +1598,14 @@ init_linktype(p)
off_nl = -1;
off_nl_nosnap = -1;
return;
+
+ case DLT_LINK:
+ off_linktype = 8;
+ off_macpl = 0;
+ off_macpl_is_variable = 1;
+ off_nl = 0;
+ off_nl_nosnap = 0;
+ return;
}
bpf_error("unknown data link type %d", linktype);
/* NOTREACHED */
@@ -2427,6 +2435,39 @@ gen_load_radiotap_llprefixlen()
return (NULL);
}
+static struct slist *
+gen_load_link_ll_header_len()
+{
+ struct slist *s1, *s2;
+
+ if (reg_off_macpl == -1)
+ reg_off_macpl = alloc_reg();
+
+ /*
+ * Generate code to load the length of the link header into
+ * the register assigned to hold that length, if one has been
+ * assigned. (If one hasn't been assigned, no code we've
+ * generated uses that prefix, so we don't need to generate any
+ * code to load it.)
+ */
+ if (reg_off_macpl != -1) {
+ s1 = new_stmt(BPF_LD|BPF_H|BPF_ABS);
+ s1->s.k = 2;
+ s2 = new_stmt(BPF_ST);
+ s2->s.k = reg_off_macpl;
+ sappend(s1, s2);
+
+ /*
+ * Now move it into the X register.
+ */
+ s2 = new_stmt(BPF_MISC|BPF_TAX);
+ sappend(s1, s2);
+
+ return (s1);
+ } else
+ return (NULL);
+}
+
/*
* At the moment we treat PPI as normal Radiotap encoded
* packets. The difference is in the function that generates
@@ -2765,6 +2806,11 @@ insert_compute_vloffsets(b)
case DLT_PPI:
s = gen_load_802_11_header_len(s, b->stmts);
break;
+
+ case DLT_LINK:
+ s = gen_load_link_ll_header_len();
+ break;
+
}
/*
-
This is the tcpdump-workers list.
Visit https://cod.sandelman.ca/ to unsubscribe.