ppp.c (10519B)
1 #include <u.h> 2 #include <libc.h> 3 #include <ip.h> 4 #include <libsec.h> 5 #include "dat.h" 6 #include "protos.h" 7 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 }; 14 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 }; 29 30 /* LCP protocol (and IPCP) */ 31 32 33 typedef struct Lcppkt Lcppkt; 34 struct Lcppkt 35 { 36 uchar code; 37 uchar id; 38 uchar len[2]; 39 uchar data[1]; 40 }; 41 42 typedef struct Lcpopt Lcpopt; 43 struct Lcpopt 44 { 45 uchar type; 46 uchar len; 47 uchar data[1]; 48 }; 49 50 enum 51 { 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 */ 66 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, 75 76 /* authentication protocols */ 77 APmd5= 5, 78 APmschap= 128, 79 80 /* Chap codes */ 81 Cchallenge= 1, 82 Cresponse= 2, 83 Csuccess= 3, 84 Cfailure= 4, 85 86 /* ipcp configure options */ 87 Oipaddrs= 1, 88 Oipcompress= 2, 89 Oipaddr= 3, 90 Oipdns= 129, 91 Oipwins= 130, 92 Oipdns2= 131, 93 Oipwins2= 132 94 }; 95 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 }; 115 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 }; 131 132 enum 133 { 134 OOproto 135 }; 136 137 static void 138 p_compile(Filter *f) 139 { 140 Mux *m; 141 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 } 149 150 sysfatal("unknown ppp field or protocol: %s", f->s); 151 } 152 153 static int 154 p_filter(Filter *f, Msg *m) 155 { 156 int proto; 157 int len; 158 159 if(f->subop != OOproto) 160 return 0; 161 162 len = m->pe - m->ps; 163 if(len < 3) 164 return -1; 165 166 if(m->ps[0] == PPP_addr && m->ps[1] == PPP_ctl) 167 m->ps += 2; 168 169 proto = *m->ps++; 170 if((proto&1) == 0) 171 proto = (proto<<8) | *m->ps++; 172 173 if(proto == f->ulv) 174 return 1; 175 176 return 0; 177 } 178 179 static int 180 p_seprint(Msg *m) 181 { 182 int proto; 183 int len; 184 185 len = m->pe - m->ps; 186 if(len < 3) 187 return -1; 188 189 if(m->ps[0] == PPP_addr && m->ps[1] == PPP_ctl) 190 m->ps += 2; 191 192 proto = *m->ps++; 193 if((proto&1) == 0) 194 proto = (proto<<8) | *m->ps++; 195 196 m->p = seprint(m->p, m->e, "pr=%ud len=%d", proto, len); 197 demux(p_mux, proto, proto, m, &dump); 198 199 return 0; 200 } 201 202 static int 203 p_seprintchap(Msg *m) 204 { 205 Lcppkt *lcp; 206 char *p, *e; 207 int len; 208 209 if(m->pe-m->ps < 4) 210 return -1; 211 212 p = m->p; 213 e = m->e; 214 m->pr = nil; 215 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; 223 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 } 251 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; 258 259 cp = a; 260 ecp = cp+len; 261 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 } 268 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 } 318 319 320 static int 321 p_seprintlcp(Msg *m) 322 { 323 Lcppkt *lcp; 324 char *p, *e; 325 int len; 326 327 if(m->pe-m->ps < 4) 328 return -1; 329 330 p = m->p; 331 e = m->e; 332 m->pr = nil; 333 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; 340 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 } 366 367 static char* 368 seprintipcpopt(char *p, char *e, void *a, int len) 369 { 370 Lcpopt *o; 371 uchar *cp, *ecp; 372 373 cp = a; 374 ecp = cp+len; 375 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 } 382 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 } 412 413 static int 414 p_seprintipcp(Msg *m) 415 { 416 Lcppkt *lcp; 417 char *p, *e; 418 int len; 419 420 if(m->pe-m->ps < 4) 421 return -1; 422 423 p = m->p; 424 e = m->e; 425 m->pr = nil; 426 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; 433 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 } 454 455 static char* 456 seprintccpopt(char *p, char *e, void *a, int len) 457 { 458 Lcpopt *o; 459 uchar *cp, *ecp; 460 461 cp = a; 462 ecp = cp+len; 463 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 } 470 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 } 489 490 static int 491 p_seprintccp(Msg *m) 492 { 493 Lcppkt *lcp; 494 char *p, *e; 495 int len; 496 497 if(m->pe-m->ps < 4) 498 return -1; 499 500 p = m->p; 501 e = m->e; 502 m->pr = nil; 503 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; 510 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); 531 532 return 0; 533 } 534 535 static int 536 p_seprintcomp(Msg *m) 537 { 538 char compflag[5]; 539 ushort x; 540 int i; 541 int len; 542 543 len = m->pe-m->ps; 544 if(len < 2) 545 return -1; 546 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 } 564 565 Proto ppp = 566 { 567 "ppp", 568 p_compile, 569 p_filter, 570 p_seprint, 571 p_mux, 572 "%#.4lux", 573 nil, 574 defaultframer 575 }; 576 577 Proto ppp_ipcp = 578 { 579 "ppp_ipcp", 580 p_compile, 581 p_filter, 582 p_seprintipcp, 583 nil, 584 nil, 585 nil, 586 defaultframer 587 }; 588 589 Proto ppp_lcp = 590 { 591 "ppp_lcp", 592 p_compile, 593 p_filter, 594 p_seprintlcp, 595 nil, 596 nil, 597 nil, 598 defaultframer 599 }; 600 601 Proto ppp_ccp = 602 { 603 "ppp_ccp", 604 p_compile, 605 p_filter, 606 p_seprintccp, 607 nil, 608 nil, 609 nil, 610 defaultframer 611 }; 612 613 Proto ppp_chap = 614 { 615 "ppp_chap", 616 p_compile, 617 p_filter, 618 p_seprintchap, 619 nil, 620 nil, 621 nil, 622 defaultframer 623 }; 624 625 Proto ppp_comp = 626 { 627 "ppp_comp", 628 p_compile, 629 p_filter, 630 p_seprintcomp, 631 nil, 632 nil, 633 nil, 634 defaultframer 635 };