aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/ip/snoopy/llc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/ip/snoopy/llc.c')
-rw-r--r--src/cmd/ip/snoopy/llc.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/src/cmd/ip/snoopy/llc.c b/src/cmd/ip/snoopy/llc.c
new file mode 100644
index 00000000..bbc21986
--- /dev/null
+++ b/src/cmd/ip/snoopy/llc.c
@@ -0,0 +1,173 @@
+/*
+ * LLC. Only enough to dispatch to SNAP and IP.
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <ip.h>
+#include "dat.h"
+#include "protos.h"
+
+enum
+{
+ UFmt = 3,
+ Gsap = 1,
+ IG = 1,
+ SFmt = 1,
+ UPoll = 0x10,
+ IsPoll = 0x100,
+ XidFi = 0x81,
+
+ SapNull = 0,
+ SapGlobal = 0xff,
+ Sap8021BI = 0x02,
+ Sap8021BG = 0x03,
+ SapSNA = 0x04,
+ SapIP = 0x06,
+ SapProwayNM = 0x0e,
+ Sap8021D = 0x42,
+ SapRS511 = 0x4e,
+ SapISO8208 = 0x7e,
+ SapProway = 0x8e,
+ SapSnap = 0xaa,
+ SapIpx = 0xe0,
+ SapNetbeui = 0xf0,
+ SapIsons = 0xfe,
+};
+
+static Mux p_mux[] =
+{
+// Linux gives llc -> snap not llc -> ip.
+// If we don't tell snoopy about llc -> ip, then the default patterns
+// like snoopy -h radiotap -f dns work better.
+// { "ip", SapIP },
+ { "snap", SapSnap },
+ { 0 }
+};
+
+typedef struct Hdr Hdr;
+struct Hdr
+{
+ uchar dsap;
+ uchar ssap;
+ uchar dsapf;
+ uchar ssapf;
+ ushort ctl;
+ uchar isu;
+ int hdrlen;
+};
+
+static int
+unpackhdr(uchar *p, uchar *ep, Hdr *h)
+{
+ if(p+3 > ep)
+ return -1;
+ h->dsapf = p[0];
+ h->dsap = h->dsapf & ~IG;
+ h->ssapf = p[1];
+ h->ssap = h->ssapf & ~Gsap;
+ h->ctl = p[2];
+ h->hdrlen = 3;
+ if((h->ctl&UFmt) == UFmt)
+ h->isu = 1;
+ else{
+ if(p+4 > ep)
+ return -1;
+ h->hdrlen = 4;
+ h->ctl = LittleS(p+2);
+ }
+ return 0;
+}
+
+enum
+{
+ Ossap,
+ Odsap,
+ Ot,
+};
+
+static Field p_fields[] =
+{
+ { "ssap", Fnum, Ossap, "ssap" },
+ { "dsap", Fnum, Odsap, "dsap" },
+ { 0 }
+};
+
+static void
+p_compile(Filter *f)
+{
+ Mux *m;
+
+ if(f->op == '='){
+ compile_cmp(llc.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 llc 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.hdrlen;
+
+ switch(f->subop){
+ case Ossap:
+ return f->ulv == h.ssap;
+ case Odsap:
+ return f->ulv == h.dsap;
+ case Ot:
+ return f->ulv == h.ssap && f->ulv == h.dsap;
+ }
+ 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->pr = &dump;
+ m->p = seprint(m->p, m->e, "ssap=%02x dsap=%02x ctl=%04x", h.ssap, h.dsap, h.ctl);
+ m->ps += h.hdrlen;
+ m->pr = &dump;
+ if(h.ssap == h.dsap){
+ switch(h.ssap){
+ case SapIP:
+ m->pr = &ip;
+ break;
+ case SapSnap:
+ m->pr = &snap;
+ break;
+ }
+ }
+ return 0;
+}
+
+Proto llc =
+{
+ "llc",
+ p_compile,
+ p_filter,
+ p_seprint,
+ p_mux,
+ nil,
+ nil,
+ defaultframer
+};