plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 };