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 Lcppkt
35 {
36 uchar code;
37 uchar id;
38 uchar len[2];
39 uchar data[1];
40 };
42 typedef struct Lcpopt Lcpopt;
43 struct Lcpopt
44 {
45 uchar type;
46 uchar len;
47 uchar data[1];
48 };
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 */
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= 132
94 };
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[] =
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 enum
134 OOproto
135 };
137 static void
138 p_compile(Filter *f)
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;
150 sysfatal("unknown ppp field or protocol: %s", f->s);
153 static int
154 p_filter(Filter *f, Msg *m)
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;
179 static int
180 p_seprint(Msg *m)
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;
202 static int
203 p_seprintchap(Msg *m)
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);
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;
248 m->p = seprint(p, e, " len=%d", len);
249 return 0;
252 static char*
253 seprintlcpopt(char *p, char *e, void *a, int len)
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;
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;
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;
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;
316 return p;
320 static int
321 p_seprintlcp(Msg *m)
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;
363 m->p = seprint(p, e, " len=%d", len);
364 return 0;
367 static char*
368 seprintipcpopt(char *p, char *e, void *a, int len)
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;
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;
410 return p;
413 static int
414 p_seprintipcp(Msg *m)
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;
451 m->p = seprint(p, e, " len=%d", len);
452 return 0;
455 static char*
456 seprintccpopt(char *p, char *e, void *a, int len)
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;
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;
487 return p;
490 static int
491 p_seprintccp(Msg *m)
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;
530 m->p = seprint(p, e, " len=%d", len);
532 return 0;
535 static int
536 p_seprintcomp(Msg *m)
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;
565 Proto ppp =
567 "ppp",
568 p_compile,
569 p_filter,
570 p_seprint,
571 p_mux,
572 "%#.4lux",
573 nil,
574 defaultframer
575 };
577 Proto ppp_ipcp =
579 "ppp_ipcp",
580 p_compile,
581 p_filter,
582 p_seprintipcp,
583 nil,
584 nil,
585 nil,
586 defaultframer
587 };
589 Proto ppp_lcp =
591 "ppp_lcp",
592 p_compile,
593 p_filter,
594 p_seprintlcp,
595 nil,
596 nil,
597 nil,
598 defaultframer
599 };
601 Proto ppp_ccp =
603 "ppp_ccp",
604 p_compile,
605 p_filter,
606 p_seprintccp,
607 nil,
608 nil,
609 nil,
610 defaultframer
611 };
613 Proto ppp_chap =
615 "ppp_chap",
616 p_compile,
617 p_filter,
618 p_seprintchap,
619 nil,
620 nil,
621 nil,
622 defaultframer
623 };
625 Proto ppp_comp =
627 "ppp_comp",
628 p_compile,
629 p_filter,
630 p_seprintcomp,
631 nil,
632 nil,
633 nil,
634 defaultframer
635 };