On 13/05/11 12:52 AM, Darren Reed wrote:
On 12/05/11 04:27 AM, Guy Harris wrote:
On May 10, 2011, at 1:40 PM, Darren Reed wrote:
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)
What about packets for which there is no appropriate Ethernet
protocol number value, such as:
various link control protocols for PPP;
management and control frames for 802.11 (and similar frames for
older LAN technologies such as FDDI and Token Ring);
LAN frames with 802.2 headers with DSAPs for which there's no
Ethernet protocol number;
LAN frames with 802.2+SNAP headers with an OUI other than 0x000000;
etc.?
An alternative would be like this:
bits field values
----- ------------
00-07 version (1)
08-15 control field for bits 64-95
16-31 pre-mac payload length
32-63 dlt (DLT_*)
64-95 mac payload type
So, if bits 08-15 are 0, 64-79 are 0 and 80-95 are the ethernet
protocol number.
...
I've adopted the comments directly above into the frame format being used.
The attached diffs represent the changes required to have libpcap
properly work with this header. As yet I haven't seen a DLT assigned, so
I've chosen one a fair distance off - 16384. At present the code
generator assumes that bits 8-15 are 0 because thus far there is no
other type of packet being generated.
Darren
diff -ur libpcap-clone/bpf_image.c libpcap/bpf_image.c
--- libpcap-clone/bpf_image.c Fri Jun 3 20:41:14 2011
+++ libpcap/bpf_image.c Wed May 11 23:42:42 2011
@@ -130,6 +130,11 @@
fmt = "4*([%d]&0xf)";
break;
+ case BPF_LDX|BPF_MSHM|BPF_B:
+ op = "ldxbi";
+ fmt = "4*([[%d]]&0xf)";
+ break;
+
case BPF_LD|BPF_MEM:
op = "ld";
fmt = "M[%d]";
diff -ur libpcap-clone/gencode.c libpcap/gencode.c
--- libpcap-clone/gencode.c Fri Jun 3 20:41:14 2011
+++ libpcap/gencode.c Fri Jun 3 19:47:06 2011
@@ -1608,6 +1608,14 @@
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 */
@@ -1776,7 +1784,10 @@
{
struct slist *s, *s2;
- s = gen_off_macpl();
+ if (linktype != DLT_LINK)
+ s = gen_off_macpl();
+ else
+ s = NULL;
if (s != NULL) {
/*
* There's a variable-length prefix preceding the
@@ -1818,8 +1829,13 @@
* of off_mac_pl + off_nl from the beginning of the
* raw packet data.
*/
- s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
- s->s.k = off_macpl + off_nl;
+ if (linktype == DLT_LINK) {
+ s = new_stmt(BPF_LDX|BPF_MSHM|BPF_B);
+ s->s.k = 2;
+ } else {
+ s = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
+ s->s.k = off_macpl + off_nl;
+ }
}
return s;
}
@@ -2437,6 +2453,39 @@
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
@@ -2775,6 +2824,11 @@
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;
+
}
/*
@@ -5685,8 +5739,13 @@
s[i]->s.k = off_macpl + off_nl + 9;
i++;
/* X = ip->ip_hl << 2 */
- s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
- s[i]->s.k = off_macpl + off_nl;
+ if (linktype == DLT_LINK) {
+ s[i] = new_stmt(BPF_LDX|BPF_MSHM|BPF_B);
+ s[i]->s.k = 2;
+ } else {
+ s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B);
+ s[i]->s.k = off_macpl + off_nl;
+ }
i++;
break;
#ifdef INET6
diff -ur libpcap-clone/optimize.c libpcap/optimize.c
--- libpcap-clone/optimize.c Fri Jun 3 20:41:15 2011
+++ libpcap/optimize.c Wed May 11 23:36:55 2011
@@ -785,7 +785,8 @@
* following it (with 0 or more nops between the
* ldxms and addx).
*/
- if (next->s.code != (BPF_LDX|BPF_MSH|BPF_B))
+ if (next->s.code != (BPF_LDX|BPF_MSH|BPF_B) &&
+ next->s.code != (BPF_LDX|BPF_MSHM|BPF_B))
add = next;
else
add = this_op(next->next);
@@ -1028,6 +1029,11 @@
case BPF_LDX|BPF_MSH|BPF_B:
v = F(s->code, s->k, 0L);
vstore(s, &val[X_ATOM], v, alter);
+ break;
+
+ case BPF_LDX|BPF_MSHM|BPF_B:
+ v = F(s->code, s->k, 0L);
+ vstore(s, &val[X_ATOM], v, alter);
break;
case BPF_ALU|BPF_NEG:
diff -ur libpcap-clone/bpf/net/bpf_filter.c libpcap/bpf/net/bpf_filter.c
--- libpcap-clone/bpf/net/bpf_filter.c Fri Jun 3 20:41:14 2011
+++ libpcap/bpf/net/bpf_filter.c Fri Jun 3 19:47:06 2011
@@ -363,8 +363,26 @@
A = p[k];
continue;
+ case BPF_LDX|BPF_MSHM|BPF_B:
+ k = pc->k;
+ if (k >= buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+ if (m == NULL)
+ return 0;
+ n = m;
+ MINDEX(len, n, k);
+ k = mtod(n, u_char *)[k];
+#else
+ return 0;
+#endif
+ } else {
+ k = p[k];
+ }
+ goto bpf_do_msh;
+
case BPF_LDX|BPF_MSH|BPF_B:
k = pc->k;
+bpf_do_msh:
if (k >= buflen) {
#if defined(KERNEL) || defined(_KERNEL)
if (m == NULL)
@@ -371,13 +389,13 @@
return 0;
n = m;
MINDEX(len, n, k);
- X = (mtod(n, char *)[k] & 0xf) << 2;
+ X = (mtod(n, u_char *)[k] & 0xf) << 2;
continue;
#else
return 0;
#endif
}
- X = (p[pc->k] & 0xf) << 2;
+ X = (p[k] & 0xf) << 2;
continue;
case BPF_LD|BPF_IMM:
@@ -575,6 +593,7 @@
case BPF_ABS:
case BPF_IND:
case BPF_MSH:
+ case BPF_MSHM:
/*
* There's no maximum packet data size
* in userland. The runtime packet length
diff -ur libpcap-clone/net/bpf_filter.c libpcap/net/bpf_filter.c
--- libpcap-clone/net/bpf_filter.c Fri Jun 3 20:41:14 2011
+++ libpcap/net/bpf_filter.c Fri Jun 3 19:47:06 2011
@@ -363,8 +363,26 @@
A = p[k];
continue;
+ case BPF_LDX|BPF_MSHM|BPF_B:
+ k = pc->k;
+ if (k >= buflen) {
+#if defined(KERNEL) || defined(_KERNEL)
+ if (m == NULL)
+ return 0;
+ n = m;
+ MINDEX(len, n, k);
+ k = mtod(n, u_char *)[k];
+#else
+ return 0;
+#endif
+ } else {
+ k = p[k];
+ }
+ goto bpf_do_msh;
+
case BPF_LDX|BPF_MSH|BPF_B:
k = pc->k;
+bpf_do_msh:
if (k >= buflen) {
#if defined(KERNEL) || defined(_KERNEL)
if (m == NULL)
@@ -371,13 +389,13 @@
return 0;
n = m;
MINDEX(len, n, k);
- X = (mtod(n, char *)[k] & 0xf) << 2;
+ X = (mtod(n, u_char *)[k] & 0xf) << 2;
continue;
#else
return 0;
#endif
}
- X = (p[pc->k] & 0xf) << 2;
+ X = (p[k] & 0xf) << 2;
continue;
case BPF_LD|BPF_IMM:
@@ -575,6 +593,7 @@
case BPF_ABS:
case BPF_IND:
case BPF_MSH:
+ case BPF_MSHM:
/*
* There's no maximum packet data size
* in userland. The runtime packet length
diff -ur libpcap-clone/pcap/bpf.h libpcap/pcap/bpf.h
--- libpcap-clone/pcap/bpf.h Fri Jun 3 20:41:15 2011
+++ libpcap/pcap/bpf.h Fri Jun 3 19:47:07 2011
@@ -993,6 +993,8 @@
*/
#define DLT_DBUS 231
+#define DLT_LINK 16384
+
/*
* Juniper-private data link type, as per request from
* Hannes Gredler <han...@juniper.net>.
@@ -1078,6 +1080,7 @@
#define BPF_MEM 0x60
#define BPF_LEN 0x80
#define BPF_MSH 0xa0
+#define BPF_MSHM 0xe0
/* alu/jmp fields */
#define BPF_OP(code) ((code) & 0xf0)
-
This is the tcpdump-workers list.
Visit https://cod.sandelman.ca/ to unsubscribe.