tppp.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
tppp.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 proces… | |
13 }; | |
14 | |
15 /* PPP protocols */ | |
16 enum { | |
17 PPP_ip= 0x21, /* internet */ | |
18 PPP_vjctcp= 0x2d, /* compressing van jacob… | |
19 PPP_vjutcp= 0x2f, /* uncompressing van jac… | |
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 authenticati… | |
25 PPP_lcp= 0xc021, /* link control */ | |
26 PPP_lqm= 0xc025, /* link quality monitorin… | |
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?"challeng… | |
235 p = seprint(p, e, "%.*H", lcp->data[0], lcp->dat… | |
236 p = seprint(p, e, " name="); | |
237 p = seprint(p, e, "%.*H", len-4-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 ":"f… | |
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, … | |
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.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=%… | |
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, … | |
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) ", … | |
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->… | |
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&0x… | |
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 }; |