Blob
1 #include <u.h>2 #include <libc.h>3 #include <ip.h>4 #include <libsec.h>5 #include "dat.h"6 #include "protos.h"8 /* PPP stuff */9 enum {10 PPP_addr= 0xff,11 PPP_ctl= 0x3,12 PPP_period= 3*1000, /* period of retransmit process (in ms) */13 };15 /* PPP protocols */16 enum {17 PPP_ip= 0x21, /* internet */18 PPP_vjctcp= 0x2d, /* compressing van jacobson tcp */19 PPP_vjutcp= 0x2f, /* uncompressing van jacobson tcp */20 PPP_ml= 0x3d, /* multi link */21 PPP_comp= 0xfd, /* compressed packets */22 PPP_ipcp= 0x8021, /* ip control */23 PPP_ccp= 0x80fd, /* compression control */24 PPP_passwd= 0xc023, /* passwd authentication */25 PPP_lcp= 0xc021, /* link control */26 PPP_lqm= 0xc025, /* link quality monitoring */27 PPP_chap= 0xc223, /* challenge/response */28 };30 /* LCP protocol (and IPCP) */33 typedef struct Lcppkt Lcppkt;34 struct Lcppkt35 {36 uchar code;37 uchar id;38 uchar len[2];39 uchar data[1];40 };42 typedef struct Lcpopt Lcpopt;43 struct Lcpopt44 {45 uchar type;46 uchar len;47 uchar data[1];48 };50 enum51 {52 /* LCP codes */53 Lconfreq= 1,54 Lconfack= 2,55 Lconfnak= 3,56 Lconfrej= 4,57 Ltermreq= 5,58 Ltermack= 6,59 Lcoderej= 7,60 Lprotorej= 8,61 Lechoreq= 9,62 Lechoack= 10,63 Ldiscard= 11,64 Lresetreq= 14, /* for ccp only */65 Lresetack= 15, /* for ccp only */67 /* Lcp configure options */68 Omtu= 1,69 Octlmap= 2,70 Oauth= 3,71 Oquality= 4,72 Omagic= 5,73 Opc= 7,74 Oac= 8,76 /* authentication protocols */77 APmd5= 5,78 APmschap= 128,80 /* Chap codes */81 Cchallenge= 1,82 Cresponse= 2,83 Csuccess= 3,84 Cfailure= 4,86 /* ipcp configure options */87 Oipaddrs= 1,88 Oipcompress= 2,89 Oipaddr= 3,90 Oipdns= 129,91 Oipwins= 130,92 Oipdns2= 131,93 Oipwins2= 13294 };96 char *97 lcpcode[] = {98 0,99 "confreq",100 "confack",101 "confnak",102 "confrej",103 "termreq",104 "termack",105 "coderej",106 "protorej",107 "echoreq",108 "echoack",109 "discard",110 "id",111 "timeremain",112 "resetreq",113 "resetack"114 };116 static Mux p_mux[] =117 {118 {"ip", PPP_ip, },119 {"ppp_vjctcp", PPP_vjctcp, },120 {"ppp_vjutcp", PPP_vjutcp, },121 {"ppp_ml", PPP_ml, },122 {"ppp_comp", PPP_comp, },123 {"ppp_ipcp", PPP_ipcp, },124 {"ppp_ccp", PPP_ccp, },125 {"ppp_passwd", PPP_passwd, },126 {"ppp_lcp", PPP_lcp, },127 {"ppp_lqm", PPP_lqm, },128 {"ppp_chap", PPP_chap, },129 {0}130 };132 enum133 {134 OOproto135 };137 static void138 p_compile(Filter *f)139 {140 Mux *m;142 for(m = p_mux; m->name != nil; m++)143 if(strcmp(f->s, m->name) == 0){144 f->pr = m->pr;145 f->ulv = m->val;146 f->subop = OOproto;147 return;148 }150 sysfatal("unknown ppp field or protocol: %s", f->s);151 }153 static int154 p_filter(Filter *f, Msg *m)155 {156 int proto;157 int len;159 if(f->subop != OOproto)160 return 0;162 len = m->pe - m->ps;163 if(len < 3)164 return -1;166 if(m->ps[0] == PPP_addr && m->ps[1] == PPP_ctl)167 m->ps += 2;169 proto = *m->ps++;170 if((proto&1) == 0)171 proto = (proto<<8) | *m->ps++;173 if(proto == f->ulv)174 return 1;176 return 0;177 }179 static int180 p_seprint(Msg *m)181 {182 int proto;183 int len;185 len = m->pe - m->ps;186 if(len < 3)187 return -1;189 if(m->ps[0] == PPP_addr && m->ps[1] == PPP_ctl)190 m->ps += 2;192 proto = *m->ps++;193 if((proto&1) == 0)194 proto = (proto<<8) | *m->ps++;196 m->p = seprint(m->p, m->e, "pr=%ud len=%d", proto, len);197 demux(p_mux, proto, proto, m, &dump);199 return 0;200 }202 static int203 p_seprintchap(Msg *m)204 {205 Lcppkt *lcp;206 char *p, *e;207 int len;209 if(m->pe-m->ps < 4)210 return -1;212 p = m->p;213 e = m->e;214 m->pr = nil;216 /* resize packet */217 lcp = (Lcppkt*)m->ps;218 len = NetS(lcp->len);219 if(m->ps+len < m->pe)220 m->pe = m->ps+len;221 else if(m->ps+len > m->pe)222 return -1;224 p = seprint(p, e, "id=%d code=%d", lcp->id, lcp->code);225 switch(lcp->code) {226 default:227 p = seprint(p, e, " data=%.*H", len>64?64:len, lcp->data);228 break;229 case 1:230 case 2:231 if(lcp->data[0] > len-4){232 p = seprint(p, e, "%.*H", len-4, lcp->data);233 } else {234 p = seprint(p, e, " %s=", lcp->code==1?"challenge ":"response ");235 p = seprint(p, e, "%.*H", lcp->data[0], lcp->data+1);236 p = seprint(p, e, " name=");237 p = seprint(p, e, "%.*H", len-4-lcp->data[0]-1, lcp->data+lcp->data[0]+1);238 }239 break;240 case 3:241 case 4:242 if(len > 64)243 len = 64;244 p = seprint(p, e, " %s=%.*H", lcp->code==3?"success ":"failure",245 len>64?64:len, lcp->data);246 break;247 }248 m->p = seprint(p, e, " len=%d", len);249 return 0;250 }252 static char*253 seprintlcpopt(char *p, char *e, void *a, int len)254 {255 Lcpopt *o;256 int proto, x, period;257 uchar *cp, *ecp;259 cp = a;260 ecp = cp+len;262 for(; cp < ecp; cp += o->len){263 o = (Lcpopt*)cp;264 if(cp + o->len > ecp || o->len == 0){265 p = seprint(p, e, " bad-opt-len=%d", o->len);266 return p;267 }269 switch(o->type){270 default:271 p = seprint(p, e, " (type=%d len=%d)", o->type, o->len);272 break;273 case Omtu:274 p = seprint(p, e, " mtu=%d", NetS(o->data));275 break;276 case Octlmap:277 p = seprint(p, e, " ctlmap=%ux", NetL(o->data));278 break;279 case Oauth:280 proto = NetS(o->data);281 switch(proto) {282 default:283 p = seprint(p, e, " auth=%d", proto);284 break;285 case PPP_passwd:286 p = seprint(p, e, " auth=passwd");287 break;288 case PPP_chap:289 p = seprint(p, e, " (auth=chap data=%2.2ux)", o->data[2]);290 break;291 }292 break;293 case Oquality:294 proto = NetS(o->data);295 switch(proto) {296 default:297 p = seprint(p, e, " qproto=%d", proto);298 break;299 case PPP_lqm:300 x = NetL(o->data+2)*10;301 period = (x+(PPP_period-1))/PPP_period;302 p = seprint(p, e, " (qproto=lqm period=%d)", period);303 break;304 }305 case Omagic:306 p = seprint(p, e, " magic=%ux", NetL(o->data));307 break;308 case Opc:309 p = seprint(p, e, " protocol-compress");310 break;311 case Oac:312 p = seprint(p, e, " addr-compress");313 break;314 }315 }316 return p;317 }320 static int321 p_seprintlcp(Msg *m)322 {323 Lcppkt *lcp;324 char *p, *e;325 int len;327 if(m->pe-m->ps < 4)328 return -1;330 p = m->p;331 e = m->e;332 m->pr = nil;334 lcp = (Lcppkt*)m->ps;335 len = NetS(lcp->len);336 if(m->ps+len < m->pe)337 m->pe = m->ps+len;338 else if(m->ps+len > m->pe)339 return -1;341 p = seprint(p, e, "id=%d code=%d", lcp->id, lcp->code);342 switch(lcp->code) {343 default:344 p = seprint(p, e, " data=%.*H", len>64?64:len, lcp->data);345 break;346 case Lconfreq:347 case Lconfack:348 case Lconfnak:349 case Lconfrej:350 p = seprint(p, e, "=%s", lcpcode[lcp->code]);351 p = seprintlcpopt(p, e, lcp->data, len-4);352 break;353 case Ltermreq:354 case Ltermack:355 case Lcoderej:356 case Lprotorej:357 case Lechoreq:358 case Lechoack:359 case Ldiscard:360 p = seprint(p, e, "=%s", lcpcode[lcp->code]);361 break;362 }363 m->p = seprint(p, e, " len=%d", len);364 return 0;365 }367 static char*368 seprintipcpopt(char *p, char *e, void *a, int len)369 {370 Lcpopt *o;371 uchar *cp, *ecp;373 cp = a;374 ecp = cp+len;376 for(; cp < ecp; cp += o->len){377 o = (Lcpopt*)cp;378 if(cp + o->len > ecp){379 p = seprint(p, e, " bad opt len %ux", o->type);380 return p;381 }383 switch(o->type){384 default:385 p = seprint(p, e, " (type=%d len=%d)", o->type, o->len);386 break;387 case Oipaddrs:388 p = seprint(p, e, " ipaddrs(deprecated)");389 break;390 case Oipcompress:391 p = seprint(p, e, " ipcompress");392 break;393 case Oipaddr:394 p = seprint(p, e, " ipaddr=%V", o->data);395 break;396 case Oipdns:397 p = seprint(p, e, " dnsaddr=%V", o->data);398 break;399 case Oipwins:400 p = seprint(p, e, " winsaddr=%V", o->data);401 break;402 case Oipdns2:403 p = seprint(p, e, " dns2addr=%V", o->data);404 break;405 case Oipwins2:406 p = seprint(p, e, " wins2addr=%V", o->data);407 break;408 }409 }410 return p;411 }413 static int414 p_seprintipcp(Msg *m)415 {416 Lcppkt *lcp;417 char *p, *e;418 int len;420 if(m->pe-m->ps < 4)421 return -1;423 p = m->p;424 e = m->e;425 m->pr = nil;427 lcp = (Lcppkt*)m->ps;428 len = NetS(lcp->len);429 if(m->ps+len < m->pe)430 m->pe = m->ps+len;431 else if(m->ps+len > m->pe)432 return -1;434 p = seprint(p, e, "id=%d code=%d", lcp->id, lcp->code);435 switch(lcp->code) {436 default:437 p = seprint(p, e, " data=%.*H", len>64?64:len, lcp->data);438 break;439 case Lconfreq:440 case Lconfack:441 case Lconfnak:442 case Lconfrej:443 p = seprint(p, e, "=%s", lcpcode[lcp->code]);444 p = seprintipcpopt(p, e, lcp->data, len-4);445 break;446 case Ltermreq:447 case Ltermack:448 p = seprint(p, e, "=%s", lcpcode[lcp->code]);449 break;450 }451 m->p = seprint(p, e, " len=%d", len);452 return 0;453 }455 static char*456 seprintccpopt(char *p, char *e, void *a, int len)457 {458 Lcpopt *o;459 uchar *cp, *ecp;461 cp = a;462 ecp = cp+len;464 for(; cp < ecp; cp += o->len){465 o = (Lcpopt*)cp;466 if(cp + o->len > ecp){467 p = seprint(p, e, " bad opt len %ux", o->type);468 return p;469 }471 switch(o->type){472 default:473 p = seprint(p, e, " type=%d ", o->type);474 break;475 case 0:476 p = seprint(p, e, " OUI=(%d %.2ux%.2ux%.2ux) ", o->type,477 o->data[0], o->data[1], o->data[2]);478 break;479 case 17:480 p = seprint(p, e, " Stac-LZS");481 break;482 case 18:483 p = seprint(p, e, " Microsoft-PPC=%ux", NetL(o->data));484 break;485 }486 }487 return p;488 }490 static int491 p_seprintccp(Msg *m)492 {493 Lcppkt *lcp;494 char *p, *e;495 int len;497 if(m->pe-m->ps < 4)498 return -1;500 p = m->p;501 e = m->e;502 m->pr = nil;504 lcp = (Lcppkt*)m->ps;505 len = NetS(lcp->len);506 if(m->ps+len < m->pe)507 m->pe = m->ps+len;508 else if(m->ps+len > m->pe)509 return -1;511 p = seprint(p, e, "id=%d code=%d", lcp->id, lcp->code);512 switch(lcp->code) {513 default:514 p = seprint(p, e, " data=%.*H", len>64?64:len, lcp->data);515 break;516 case Lconfreq:517 case Lconfack:518 case Lconfnak:519 case Lconfrej:520 p = seprint(p, e, "=%s", lcpcode[lcp->code]);521 p = seprintccpopt(p, e, lcp->data, len-4);522 break;523 case Ltermreq:524 case Ltermack:525 case Lresetreq:526 case Lresetack:527 p = seprint(p, e, "=%s", lcpcode[lcp->code]);528 break;529 }530 m->p = seprint(p, e, " len=%d", len);532 return 0;533 }535 static int536 p_seprintcomp(Msg *m)537 {538 char compflag[5];539 ushort x;540 int i;541 int len;543 len = m->pe-m->ps;544 if(len < 2)545 return -1;547 x = NetS(m->ps);548 m->ps += 2;549 i = 0;550 if(x & (1<<15))551 compflag[i++] = 'r';552 if(x & (1<<14))553 compflag[i++] = 'f';554 if(x & (1<<13))555 compflag[i++] = 'c';556 if(x & (1<<12))557 compflag[i++] = 'e';558 compflag[i] = 0;559 m->p = seprint(m->p, m->e, "flag=%s count=%.3ux", compflag, x&0xfff);560 m->p = seprint(m->p, m->e, " data=%.*H", len>64?64:len, m->ps);561 m->pr = nil;562 return 0;563 }565 Proto ppp =566 {567 "ppp",568 p_compile,569 p_filter,570 p_seprint,571 p_mux,572 "%#.4lux",573 nil,574 defaultframer575 };577 Proto ppp_ipcp =578 {579 "ppp_ipcp",580 p_compile,581 p_filter,582 p_seprintipcp,583 nil,584 nil,585 nil,586 defaultframer587 };589 Proto ppp_lcp =590 {591 "ppp_lcp",592 p_compile,593 p_filter,594 p_seprintlcp,595 nil,596 nil,597 nil,598 defaultframer599 };601 Proto ppp_ccp =602 {603 "ppp_ccp",604 p_compile,605 p_filter,606 p_seprintccp,607 nil,608 nil,609 nil,610 defaultframer611 };613 Proto ppp_chap =614 {615 "ppp_chap",616 p_compile,617 p_filter,618 p_seprintchap,619 nil,620 nil,621 nil,622 defaultframer623 };625 Proto ppp_comp =626 {627 "ppp_comp",628 p_compile,629 p_filter,630 p_seprintcomp,631 nil,632 nil,633 nil,634 defaultframer635 };