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
p_compile(Filter * f)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
p_filter(Filter * f,Msg * m)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
p_seprint(Msg * m)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
p_seprintchap(Msg * m)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*
seprintlcpopt(char * p,char * e,void * a,int len)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
p_seprintlcp(Msg * m)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*
seprintipcpopt(char * p,char * e,void * a,int len)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
p_seprintipcp(Msg * m)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*
seprintccpopt(char * p,char * e,void * a,int len)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
p_seprintccp(Msg * m)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
p_seprintcomp(Msg * m)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 };
636