| #include <u.h> |
| #include <libc.h> |
| #include <ip.h> |
| #include "dat.h" |
| #include "protos.h" |
| |
| typedef struct Hdr Hdr; |
| struct Hdr { |
| uchar verstype; |
| uchar code; |
| uchar sessid[2]; |
| uchar length[2]; /* of payload */ |
| }; |
| enum |
| { |
| HDRSIZE = 1+1+2+2 |
| }; |
| |
| static Mux p_mux[] = |
| { |
| {"ppp", 0, } , |
| {0} |
| }; |
| |
| enum |
| { |
| Overs, |
| Otype, |
| Ocode, |
| Osess |
| }; |
| |
| static Field p_fields[] = |
| { |
| {"v", Fnum, Overs, "version", } , |
| {"t", Fnum, Otype, "type", } , |
| {"c", Fnum, Ocode, "code" } , |
| {"s", Fnum, Osess, "sessid" } , |
| {0} |
| }; |
| |
| static void |
| p_compilesess(Filter *f) |
| { |
| /* Mux *m; */ |
| |
| if(f->op == '='){ |
| compile_cmp(pppoe_sess.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 pppoe field or protocol: %s", f->s); |
| } |
| static void |
| p_compiledisc(Filter *f) |
| { |
| /* Mux *m; */ |
| |
| if(f->op == '='){ |
| compile_cmp(pppoe_disc.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 pppoe field or protocol: %s", f->s); |
| } |
| |
| static int |
| p_filter(Filter *f, Msg *m) |
| { |
| Hdr *h; |
| |
| if(m->pe - m->ps < HDRSIZE) |
| return 0; |
| |
| h = (Hdr*)m->ps; |
| m->ps += HDRSIZE; |
| |
| switch(f->subop){ |
| case Overs: |
| return (h->verstype>>4) == f->ulv; |
| case Otype: |
| return (h->verstype&0xF) == f->ulv; |
| case Ocode: |
| return h->code == f->ulv; |
| case Osess: |
| return NetS(h->sessid) == f->ulv; |
| } |
| return 0; |
| } |
| |
| /* BUG: print all the discovery types */ |
| static int |
| p_seprintdisc(Msg *m) |
| { |
| Hdr *h; |
| int len; |
| |
| len = m->pe - m->ps; |
| if(len < HDRSIZE) |
| return -1; |
| |
| h = (Hdr*)m->ps; |
| m->ps += HDRSIZE; |
| |
| m->pr = nil; |
| |
| m->p = seprint(m->p, m->e, "v=%d t=%d c=0x%x s=0x%ux, len=%d", |
| h->verstype>>4, h->verstype&0xF, h->code, NetS(h->sessid), NetS(h->length)); |
| |
| return 0; |
| } |
| |
| static int |
| p_seprintsess(Msg *m) |
| { |
| Hdr *h; |
| int len; |
| |
| len = m->pe - m->ps; |
| if(len < HDRSIZE) |
| return -1; |
| |
| h = (Hdr*)m->ps; |
| m->ps += HDRSIZE; |
| |
| /* this will call ppp for me */ |
| demux(p_mux, 0, 0, m, &dump); |
| |
| m->p = seprint(m->p, m->e, "v=%d t=%d c=0x%x s=0x%ux, len=%d", |
| h->verstype>>4, h->verstype&0xF, h->code, NetS(h->sessid), NetS(h->length)); |
| |
| return 0; |
| } |
| |
| Proto pppoe_disc = |
| { |
| "pppoe_disc", |
| p_compiledisc, |
| p_filter, |
| p_seprintdisc, |
| p_mux, |
| "%lud", |
| p_fields, |
| defaultframer |
| }; |
| |
| Proto pppoe_sess = |
| { |
| "pppoe_sess", |
| p_compilesess, |
| p_filter, |
| p_seprintsess, |
| p_mux, |
| "%lud", |
| p_fields, |
| defaultframer |
| }; |
| |