blob: bbc21986ff98e74cfc5ff55a813d5ea53199b9cb [file] [log] [blame]
/*
* 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
};