aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ip/snoopy/radiotap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ip/snoopy/radiotap.c')
-rw-r--r--src/cmd/ip/snoopy/radiotap.c117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/cmd/ip/snoopy/radiotap.c b/src/cmd/ip/snoopy/radiotap.c
new file mode 100644
index 00000000..889dc8ab
--- /dev/null
+++ b/src/cmd/ip/snoopy/radiotap.c
@@ -0,0 +1,117 @@
+/*
+ * Radio tap as exported by BSD and Linux.
+ * The wireless ethernet devices return this format on Linux
+ * when running in monitor mode.
+ *
+ * TODO: Automatically determine whether the ethernet
+ * device is radio or ether, so that -h is not needed.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include "dat.h"
+#include "protos.h"
+
+static Mux p_mux[] =
+{
+ { "802.11", 0 },
+ { 0 }
+};
+
+typedef struct Hdr Hdr;
+struct Hdr
+{
+ uchar vers;
+ uchar pad;
+ ushort len;
+ ulong present;
+};
+
+static int
+unpackhdr(uchar *p, uchar *ep, Hdr *h)
+{
+ if(p+sizeof(Hdr) > ep)
+ return -1;
+ h->vers = p[0];
+ h->pad = p[1];
+ h->len = LittleS(p+2);
+ h->present = LittleL(p+4);
+ // can be more present fields if 0x80000000 is set in each along the chain.
+ if(p+h->len > ep)
+ return -1;
+ return 0;
+}
+
+enum
+{
+ Ot,
+};
+
+static Field p_fields[] =
+{
+ { 0 }
+};
+
+static void
+p_compile(Filter *f)
+{
+ Mux *m;
+
+ if(f->op == '='){
+ compile_cmp(radiotap.name, f, p_fields);
+ return;
+ }
+ for(m = p_mux; m->name != nil; m++){
+ if(strcmp(f->s, m->name) == 0){
+ f->pr = m->pr;
+ f->ulv = m->val;
+ f->subop = Ot;
+ return;
+ }
+ }
+ sysfatal("unknown radiotap field or protocol: %s", f->s);
+}
+
+static int
+p_filter(Filter *f, Msg *m)
+{
+ Hdr h;
+
+ memset(&h, 0, sizeof h);
+ if(unpackhdr(m->ps, m->pe, &h) < 0)
+ return 0;
+ m->ps += h.len;
+ switch(f->subop){
+ case Ot:
+ return 1;
+ }
+ return 0;
+}
+
+static int
+p_seprint(Msg *m)
+{
+ Hdr h;
+
+ memset(&h, 0, sizeof h);
+ if(unpackhdr(m->ps, m->pe, &h) < 0)
+ return -1;
+
+ m->p = seprint(m->p, m->e, "%.*H", h.len, m->ps);
+ m->ps += h.len;
+ m->pr = &p80211;
+ return 0;
+}
+
+Proto radiotap =
+{
+ "radiotap",
+ p_compile,
+ p_filter,
+ p_seprint,
+ p_mux,
+ nil,
+ nil,
+ defaultframer
+};