]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ip/snoopy/ppp.c
snoopy(8): avoid extra spaces in dhcp filter output
[plan9front.git] / sys / src / cmd / ip / snoopy / ppp.c
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 };