aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ip/snoopy/snap.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ip/snoopy/snap.c')
-rw-r--r--src/cmd/ip/snoopy/snap.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/cmd/ip/snoopy/snap.c b/src/cmd/ip/snoopy/snap.c
new file mode 100644
index 00000000..1854d1d6
--- /dev/null
+++ b/src/cmd/ip/snoopy/snap.c
@@ -0,0 +1,112 @@
+/*
+ * SNAP.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include "dat.h"
+#include "protos.h"
+
+enum
+{
+ Oorg,
+ Oet,
+
+ OuiEther = 0,
+ OuiCisco = 0xc,
+ OuiCisco90 = 0xf8,
+ OuiRfc2684 = 0x80c2,
+ OuiAppletalk = 0x80007,
+};
+
+static Mux p_mux[] =
+{
+ {"ip", 0x0800, } ,
+ {"arp", 0x0806, } ,
+ {"rarp", 0x0806, } ,
+ {"ip6", 0x86dd, } ,
+ {"pppoe_disc", 0x8863, },
+ {"pppoe_sess", 0x8864, },
+ {"eapol", 0x888e, },
+ { 0 }
+};
+
+typedef struct Hdr Hdr;
+struct Hdr
+{
+ uchar org[3];
+ uchar et[2];
+};
+
+static Field p_fields[] =
+{
+ { "org", Fnum, Oorg, "org" },
+ { "et", Fnum, Oet, "et" },
+ { 0 }
+};
+
+static void
+p_compile(Filter *f)
+{
+ Mux *m;
+
+ if(f->op == '='){
+ compile_cmp(snap.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 = Oet;
+ return;
+ }
+ }
+ sysfatal("unknown snap field or protocol: %s", f->s);
+}
+
+static int
+p_filter(Filter *f, Msg *m)
+{
+ Hdr *h;
+
+ if(m->pe - m->ps < sizeof(Hdr))
+ return 0;
+ h = (Hdr*)m->ps;
+ m->ps += 5;
+ switch(f->subop){
+ case Oorg:
+ return f->ulv == Net3(h->org);
+ case Oet:
+ return f->ulv == NetS(h->et);
+ }
+ return 0;
+}
+
+static int
+p_seprint(Msg *m)
+{
+ Hdr *h;
+
+ if(m->pe - m->ps < sizeof(Hdr))
+ return 0;
+ h = (Hdr*)m->ps;
+ m->ps += 5;
+ demux(p_mux, NetS(h->et), NetS(h->et), m, &dump);
+
+ m->p = seprint(m->p, m->e, "org=%06x et=%04x", Net3(h->org), NetS(h->et));
+ return 0;
+}
+
+Proto snap =
+{
+ "snap",
+ p_compile,
+ p_filter,
+ p_seprint,
+ p_mux,
+ nil,
+ nil,
+ defaultframer
+};