diff options
author | rsc <devnull@localhost> | 2005-12-26 04:48:52 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2005-12-26 04:48:52 +0000 |
commit | 87a52e0485d3281ebea6bf4b725aa8023690e96f (patch) | |
tree | 0abc2d2ddb875196177231639d3cb4519e814b9d /src/cmd/ip/snoopy/ppp.c | |
parent | 35d26aa32167e84326cdb745c0e906393b8de71d (diff) | |
download | plan9port-87a52e0485d3281ebea6bf4b725aa8023690e96f.tar.gz plan9port-87a52e0485d3281ebea6bf4b725aa8023690e96f.tar.bz2 plan9port-87a52e0485d3281ebea6bf4b725aa8023690e96f.zip |
new goodies
Diffstat (limited to 'src/cmd/ip/snoopy/ppp.c')
-rwxr-xr-x | src/cmd/ip/snoopy/ppp.c | 629 |
1 files changed, 629 insertions, 0 deletions
diff --git a/src/cmd/ip/snoopy/ppp.c b/src/cmd/ip/snoopy/ppp.c new file mode 100755 index 00000000..5c497a8c --- /dev/null +++ b/src/cmd/ip/snoopy/ppp.c @@ -0,0 +1,629 @@ +#include <u.h> +#include <libc.h> +#include <ip.h> +#include <libsec.h> +#include "dat.h" +#include "protos.h" + +/* PPP stuff */ +enum { + PPP_addr= 0xff, + PPP_ctl= 0x3, + PPP_period= 3*1000, /* period of retransmit process (in ms) */ +}; + +/* PPP protocols */ +enum { + PPP_ip= 0x21, /* internet */ + PPP_vjctcp= 0x2d, /* compressing van jacobson tcp */ + PPP_vjutcp= 0x2f, /* uncompressing van jacobson tcp */ + PPP_ml= 0x3d, /* multi link */ + PPP_comp= 0xfd, /* compressed packets */ + PPP_ipcp= 0x8021, /* ip control */ + PPP_ccp= 0x80fd, /* compression control */ + PPP_passwd= 0xc023, /* passwd authentication */ + PPP_lcp= 0xc021, /* link control */ + PPP_lqm= 0xc025, /* link quality monitoring */ + PPP_chap= 0xc223, /* challenge/response */ +}; + +/* LCP protocol (and IPCP) */ + + +typedef struct Lcppkt Lcppkt; +struct Lcppkt +{ + uchar code; + uchar id; + uchar len[2]; + uchar data[1]; +}; + +typedef struct Lcpopt Lcpopt; +struct Lcpopt +{ + uchar type; + uchar len; + uchar data[1]; +}; + +enum +{ + /* LCP codes */ + Lconfreq= 1, + Lconfack= 2, + Lconfnak= 3, + Lconfrej= 4, + Ltermreq= 5, + Ltermack= 6, + Lcoderej= 7, + Lprotorej= 8, + Lechoreq= 9, + Lechoack= 10, + Ldiscard= 11, + Lresetreq= 14, /* for ccp only */ + Lresetack= 15, /* for ccp only */ + + /* Lcp configure options */ + Omtu= 1, + Octlmap= 2, + Oauth= 3, + Oquality= 4, + Omagic= 5, + Opc= 7, + Oac= 8, + + /* authentication protocols */ + APmd5= 5, + APmschap= 128, + + /* Chap codes */ + Cchallenge= 1, + Cresponse= 2, + Csuccess= 3, + Cfailure= 4, + + /* ipcp configure options */ + Oipaddrs= 1, + Oipcompress= 2, + Oipaddr= 3, + Oipdns= 129, + Oipwins= 130, + Oipdns2= 131, + Oipwins2= 132, +}; + +char * +lcpcode[] = { + 0, + "confreq", + "confack", + "confnak", + "confrej", + "termreq", + "termack", + "coderej", + "protorej", + "echoreq", + "echoack", + "discard", + "id", + "timeremain", + "resetreq", + "resetack", +}; + +static Mux p_mux[] = +{ + {"ip", PPP_ip, }, + {"ppp_vjctcp", PPP_vjctcp, }, + {"ppp_vjutcp", PPP_vjutcp, }, + {"ppp_ml", PPP_ml, }, + {"ppp_comp", PPP_comp, }, + {"ppp_ipcp", PPP_ipcp, }, + {"ppp_ccp", PPP_ccp, }, + {"ppp_passwd", PPP_passwd, }, + {"ppp_lcp", PPP_lcp, }, + {"ppp_lqm", PPP_lqm, }, + {"ppp_chap", PPP_chap, }, + {0}, +}; + +enum +{ + OOproto, +}; + +static void +p_compile(Filter *f) +{ + Mux *m; + + 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 = OOproto; + return; + } + + sysfatal("unknown ppp field or protocol: %s", f->s); +} + +static int +p_filter(Filter *f, Msg *m) +{ + int proto; + int len; + + if(f->subop != OOproto) + return 0; + + len = m->pe - m->ps; + if(len < 3) + return -1; + + if(m->ps[0] == PPP_addr && m->ps[1] == PPP_ctl) + m->ps += 2; + + proto = *m->ps++; + if((proto&1) == 0) + proto = (proto<<8) | *m->ps++; + + if(proto == f->ulv) + return 1; + + return 0; +} + +static int +p_seprint(Msg *m) +{ + int proto; + int len; + + len = m->pe - m->ps; + if(len < 3) + return -1; + + if(m->ps[0] == PPP_addr && m->ps[1] == PPP_ctl) + m->ps += 2; + + proto = *m->ps++; + if((proto&1) == 0) + proto = (proto<<8) | *m->ps++; + + m->p = seprint(m->p, m->e, "pr=%ud len=%d", proto, len); + demux(p_mux, proto, proto, m, &dump); + + return 0; +} + +static int +p_seprintchap(Msg *m) +{ + Lcppkt *lcp; + char *p, *e; + int len; + + if(m->pe-m->ps < 4) + return -1; + + p = m->p; + e = m->e; + m->pr = nil; + + /* resize packet */ + lcp = (Lcppkt*)m->ps; + len = NetS(lcp->len); + if(m->ps+len < m->pe) + m->pe = m->ps+len; + else if(m->ps+len > m->pe) + return -1; + + p = seprint(p, e, "id=%d code=%d", lcp->id, lcp->code); + switch(lcp->code) { + default: + p = seprint(p, e, " data=%.*H", len>64?64:len, lcp->data); + break; + case 1: + case 2: + if(lcp->data[0] > len-4){ + p = seprint(p, e, "%.*H", len-4, lcp->data); + } else { + p = seprint(p, e, " %s=", lcp->code==1?"challenge ":"response "); + p = seprint(p, e, "%.*H", lcp->data[0], lcp->data+1); + p = seprint(p, e, " name="); + p = seprint(p, e, "%.*H", len-4-lcp->data[0]-1, lcp->data+lcp->data[0]+1); + } + break; + case 3: + case 4: + if(len > 64) + len = 64; + p = seprint(p, e, " %s=%.*H", lcp->code==3?"success ":"failure", + len>64?64:len, lcp->data); + break; + } + m->p = seprint(p, e, " len=%d", len); + return 0; +} + +static char* +seprintlcpopt(char *p, char *e, void *a, int len) +{ + Lcpopt *o; + int proto, x, period; + uchar *cp, *ecp; + + cp = a; + ecp = cp+len; + + for(; cp < ecp; cp += o->len){ + o = (Lcpopt*)cp; + if(cp + o->len > ecp || o->len == 0){ + p = seprint(p, e, " bad-opt-len=%d", o->len); + return p; + } + + switch(o->type){ + default: + p = seprint(p, e, " (type=%d len=%d)", o->type, o->len); + break; + case Omtu: + p = seprint(p, e, " mtu=%d", NetS(o->data)); + break; + case Octlmap: + p = seprint(p, e, " ctlmap=%ux", NetL(o->data)); + break; + case Oauth: + proto = NetS(o->data); + switch(proto) { + default: + p = seprint(p, e, " auth=%d", proto); + break; + case PPP_passwd: + p = seprint(p, e, " auth=passwd"); + break; + case PPP_chap: + p = seprint(p, e, " (auth=chap data=%2.2ux)", o->data[2]); + break; + } + break; + case Oquality: + proto = NetS(o->data); + switch(proto) { + default: + p = seprint(p, e, " qproto=%d", proto); + break; + case PPP_lqm: + x = NetL(o->data+2)*10; + period = (x+(PPP_period-1))/PPP_period; + p = seprint(p, e, " (qproto=lqm period=%d)", period); + break; + } + case Omagic: + p = seprint(p, e, " magic=%ux", NetL(o->data)); + break; + case Opc: + p = seprint(p, e, " protocol-compress"); + break; + case Oac: + p = seprint(p, e, " addr-compress"); + break; + } + } + return p; +} + + +static int +p_seprintlcp(Msg *m) +{ + Lcppkt *lcp; + char *p, *e; + int len; + + if(m->pe-m->ps < 4) + return -1; + + p = m->p; + e = m->e; + m->pr = nil; + + lcp = (Lcppkt*)m->ps; + len = NetS(lcp->len); + if(m->ps+len < m->pe) + m->pe = m->ps+len; + else if(m->ps+len > m->pe) + return -1; + + p = seprint(p, e, "id=%d code=%d", lcp->id, lcp->code); + switch(lcp->code) { + default: + p = seprint(p, e, " data=%.*H", len>64?64:len, lcp->data); + break; + case Lconfreq: + case Lconfack: + case Lconfnak: + case Lconfrej: + p = seprint(p, e, "=%s", lcpcode[lcp->code]); + p = seprintlcpopt(p, e, lcp->data, len-4); + break; + case Ltermreq: + case Ltermack: + case Lcoderej: + case Lprotorej: + case Lechoreq: + case Lechoack: + case Ldiscard: + p = seprint(p, e, "=%s", lcpcode[lcp->code]); + break; + } + m->p = seprint(p, e, " len=%d", len); + return 0; +} + +static char* +seprintipcpopt(char *p, char *e, void *a, int len) +{ + Lcpopt *o; + uchar *cp, *ecp; + + cp = a; + ecp = cp+len; + + for(; cp < ecp; cp += o->len){ + o = (Lcpopt*)cp; + if(cp + o->len > ecp){ + p = seprint(p, e, " bad opt len %ux", o->type); + return p; + } + + switch(o->type){ + default: + p = seprint(p, e, " (type=%d len=%d)", o->type, o->len); + break; + case Oipaddrs: + p = seprint(p, e, " ipaddrs(deprecated)"); + break; + case Oipcompress: + p = seprint(p, e, " ipcompress"); + break; + case Oipaddr: + p = seprint(p, e, " ipaddr=%V", o->data); + break; + case Oipdns: + p = seprint(p, e, " dnsaddr=%V", o->data); + break; + case Oipwins: + p = seprint(p, e, " winsaddr=%V", o->data); + break; + case Oipdns2: + p = seprint(p, e, " dns2addr=%V", o->data); + break; + case Oipwins2: + p = seprint(p, e, " wins2addr=%V", o->data); + break; + } + } + return p; +} + +static int +p_seprintipcp(Msg *m) +{ + Lcppkt *lcp; + char *p, *e; + int len; + + if(m->pe-m->ps < 4) + return -1; + + p = m->p; + e = m->e; + m->pr = nil; + + lcp = (Lcppkt*)m->ps; + len = NetS(lcp->len); + if(m->ps+len < m->pe) + m->pe = m->ps+len; + else if(m->ps+len > m->pe) + return -1; + + p = seprint(p, e, "id=%d code=%d", lcp->id, lcp->code); + switch(lcp->code) { + default: + p = seprint(p, e, " data=%.*H", len>64?64:len, lcp->data); + break; + case Lconfreq: + case Lconfack: + case Lconfnak: + case Lconfrej: + p = seprint(p, e, "=%s", lcpcode[lcp->code]); + p = seprintipcpopt(p, e, lcp->data, len-4); + break; + case Ltermreq: + case Ltermack: + p = seprint(p, e, "=%s", lcpcode[lcp->code]); + break; + } + m->p = seprint(p, e, " len=%d", len); + return 0; +} + +static char* +seprintccpopt(char *p, char *e, void *a, int len) +{ + Lcpopt *o; + uchar *cp, *ecp; + + cp = a; + ecp = cp+len; + + for(; cp < ecp; cp += o->len){ + o = (Lcpopt*)cp; + if(cp + o->len > ecp){ + p = seprint(p, e, " bad opt len %ux", o->type); + return p; + } + + switch(o->type){ + default: + p = seprint(p, e, " type=%d ", o->type); + break; + case 0: + p = seprint(p, e, " OUI=(%d %.2ux%.2ux%.2ux) ", o->type, + o->data[0], o->data[1], o->data[2]); + break; + case 17: + p = seprint(p, e, " Stac-LZS"); + break; + case 18: + p = seprint(p, e, " Microsoft-PPC=%ux", NetL(o->data)); + break; + } + } + return p; +} + +static int +p_seprintccp(Msg *m) +{ + Lcppkt *lcp; + char *p, *e; + int len; + + if(m->pe-m->ps < 4) + return -1; + + p = m->p; + e = m->e; + m->pr = nil; + + lcp = (Lcppkt*)m->ps; + len = NetS(lcp->len); + if(m->ps+len < m->pe) + m->pe = m->ps+len; + else if(m->ps+len > m->pe) + return -1; + + p = seprint(p, e, "id=%d code=%d", lcp->id, lcp->code); + switch(lcp->code) { + default: + p = seprint(p, e, " data=%.*H", len>64?64:len, lcp->data); + break; + case Lconfreq: + case Lconfack: + case Lconfnak: + case Lconfrej: + p = seprint(p, e, "=%s", lcpcode[lcp->code]); + p = seprintccpopt(p, e, lcp->data, len-4); + break; + case Ltermreq: + case Ltermack: + case Lresetreq: + case Lresetack: + p = seprint(p, e, "=%s", lcpcode[lcp->code]); + break; + } + m->p = seprint(p, e, " len=%d", len); + + return 0; +} + +static int +p_seprintcomp(Msg *m) +{ + char compflag[5]; + ushort x; + int i; + int len; + + len = m->pe-m->ps; + if(len < 2) + return -1; + + x = NetS(m->ps); + m->ps += 2; + i = 0; + if(x & (1<<15)) + compflag[i++] = 'r'; + if(x & (1<<14)) + compflag[i++] = 'f'; + if(x & (1<<13)) + compflag[i++] = 'c'; + if(x & (1<<12)) + compflag[i++] = 'e'; + compflag[i] = 0; + m->p = seprint(m->p, m->e, "flag=%s count=%.3ux", compflag, x&0xfff); + m->p = seprint(m->p, m->e, " data=%.*H", len>64?64:len, m->ps); + m->pr = nil; + return 0; +} + +Proto ppp = +{ + "ppp", + p_compile, + p_filter, + p_seprint, + p_mux, + nil, + defaultframer, +}; + +Proto ppp_ipcp = +{ + "ppp_ipcp", + p_compile, + p_filter, + p_seprintipcp, + nil, + nil, + defaultframer, +}; + +Proto ppp_lcp = +{ + "ppp_lcp", + p_compile, + p_filter, + p_seprintlcp, + nil, + nil, + defaultframer, +}; + +Proto ppp_ccp = +{ + "ppp_ccp", + p_compile, + p_filter, + p_seprintccp, + nil, + nil, + defaultframer, +}; + +Proto ppp_chap = +{ + "ppp_chap", + p_compile, + p_filter, + p_seprintchap, + nil, + nil, + defaultframer, +}; + +Proto ppp_comp = +{ + "ppp_comp", + p_compile, + p_filter, + p_seprintcomp, + nil, + nil, + defaultframer, +}; |