1e99c15f18850851bf5bfb85aee04aa074387cc9
[dragonfly.git] / contrib / tcpdump-3.9 / print-ppp.c
1 /*
2  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * Extensively modified by Motonori Shindo (mshindo@mshindo.net) for more
22  * complete PPP support.
23  */
24
25 /*
26  * TODO:
27  * o resolve XXX as much as possible
28  * o MP support
29  * o BAP support
30  */
31
32 #ifndef lint
33 static const char rcsid[] _U_ =
34     "@(#) $Header: /tcpdump/master/tcpdump/print-ppp.c,v 1.108.2.6 2005/12/05 11:40:36 hannes Exp $ (LBL)";
35 #endif
36
37 #ifdef HAVE_CONFIG_H
38 #include "config.h"
39 #endif
40
41 #include <tcpdump-stdinc.h>
42
43 #ifdef __bsdi__
44 #include <net/slcompress.h>
45 #include <net/if_ppp.h>
46 #endif
47
48 #include <pcap.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51
52 #include "interface.h"
53 #include "extract.h"
54 #include "addrtoname.h"
55 #include "ppp.h"
56 #include "chdlc.h"
57 #include "ethertype.h"
58 #include "oui.h"
59
60 /*
61  * The following constatns are defined by IANA. Please refer to
62  *    http://www.isi.edu/in-notes/iana/assignments/ppp-numbers
63  * for the up-to-date information.
64  */
65
66 /* Protocol Codes defined in ppp.h */
67
68 struct tok ppptype2str[] = {
69         { PPP_IP,         "IP" },
70         { PPP_OSI,        "OSI" },
71         { PPP_NS,         "NS" },
72         { PPP_DECNET,     "DECNET" },
73         { PPP_APPLE,      "APPLE" },
74         { PPP_IPX,        "IPX" },
75         { PPP_VJC,        "VJC IP" },
76         { PPP_VJNC,       "VJNC IP" },
77         { PPP_BRPDU,      "BRPDU" },
78         { PPP_STII,       "STII" },
79         { PPP_VINES,      "VINES" },
80         { PPP_MPLS_UCAST, "MPLS" },
81         { PPP_MPLS_MCAST, "MPLS" },
82         { PPP_COMP,       "Compressed"},
83         { PPP_ML,         "MLPPP"},
84         { PPP_IPV6,       "IP6"},
85
86         { PPP_HELLO,      "HELLO" },
87         { PPP_LUXCOM,     "LUXCOM" },
88         { PPP_SNS,        "SNS" },
89         { PPP_IPCP,       "IPCP" },
90         { PPP_OSICP,      "OSICP" },
91         { PPP_NSCP,       "NSCP" },
92         { PPP_DECNETCP,   "DECNETCP" },
93         { PPP_APPLECP,    "APPLECP" },
94         { PPP_IPXCP,      "IPXCP" },
95         { PPP_STIICP,     "STIICP" },
96         { PPP_VINESCP,    "VINESCP" },
97         { PPP_IPV6CP,     "IP6CP" },
98         { PPP_MPLSCP,     "MPLSCP" },
99
100         { PPP_LCP,        "LCP" },
101         { PPP_PAP,        "PAP" },
102         { PPP_LQM,        "LQM" },
103         { PPP_CHAP,       "CHAP" },
104         { PPP_EAP,        "EAP" },
105         { PPP_SPAP,       "SPAP" },
106         { PPP_SPAP_OLD,   "Old-SPAP" },
107         { PPP_BACP,       "BACP" },
108         { PPP_BAP,        "BAP" },
109         { PPP_MPCP,       "MLPPP-CP" },
110         { 0,              NULL }
111 };
112
113 /* Control Protocols (LCP/IPCP/CCP etc.) Codes defined in RFC 1661 */
114
115 #define CPCODES_VEXT            0       /* Vendor-Specific (RFC2153) */
116 #define CPCODES_CONF_REQ        1       /* Configure-Request */
117 #define CPCODES_CONF_ACK        2       /* Configure-Ack */
118 #define CPCODES_CONF_NAK        3       /* Configure-Nak */
119 #define CPCODES_CONF_REJ        4       /* Configure-Reject */
120 #define CPCODES_TERM_REQ        5       /* Terminate-Request */
121 #define CPCODES_TERM_ACK        6       /* Terminate-Ack */
122 #define CPCODES_CODE_REJ        7       /* Code-Reject */
123 #define CPCODES_PROT_REJ        8       /* Protocol-Reject (LCP only) */
124 #define CPCODES_ECHO_REQ        9       /* Echo-Request (LCP only) */
125 #define CPCODES_ECHO_RPL        10      /* Echo-Reply (LCP only) */
126 #define CPCODES_DISC_REQ        11      /* Discard-Request (LCP only) */
127 #define CPCODES_ID              12      /* Identification (LCP only) RFC1570 */
128 #define CPCODES_TIME_REM        13      /* Time-Remaining (LCP only) RFC1570 */
129 #define CPCODES_RESET_REQ       14      /* Reset-Request (CCP only) RFC1962 */
130 #define CPCODES_RESET_REP       15      /* Reset-Reply (CCP only) */
131
132 struct tok cpcodes[] = {
133         {CPCODES_VEXT,      "Vendor-Extension"}, /* RFC2153 */
134         {CPCODES_CONF_REQ,  "Conf-Request"},
135         {CPCODES_CONF_ACK,  "Conf-Ack"},
136         {CPCODES_CONF_NAK,  "Conf-Nack"},
137         {CPCODES_CONF_REJ,  "Conf-Reject"},
138         {CPCODES_TERM_REQ,  "Term-Request"},
139         {CPCODES_TERM_ACK,  "Term-Ack"},
140         {CPCODES_CODE_REJ,  "Code-Reject"},
141         {CPCODES_PROT_REJ,  "Prot-Reject"},
142         {CPCODES_ECHO_REQ,  "Echo-Request"},
143         {CPCODES_ECHO_RPL,  "Echo-Reply"},
144         {CPCODES_DISC_REQ,  "Disc-Req"},
145         {CPCODES_ID,        "Ident"},            /* RFC1570 */
146         {CPCODES_TIME_REM,  "Time-Rem"},         /* RFC1570 */
147         {CPCODES_RESET_REQ, "Reset-Req"},        /* RFC1962 */
148         {CPCODES_RESET_REP, "Reset-Ack"},        /* RFC1962 */
149         {0,                 NULL}
150 };
151
152 /* LCP Config Options */
153
154 #define LCPOPT_VEXT     0
155 #define LCPOPT_MRU      1
156 #define LCPOPT_ACCM     2
157 #define LCPOPT_AP       3
158 #define LCPOPT_QP       4
159 #define LCPOPT_MN       5
160 #define LCPOPT_DEP6     6
161 #define LCPOPT_PFC      7
162 #define LCPOPT_ACFC     8
163 #define LCPOPT_FCSALT   9
164 #define LCPOPT_SDP      10
165 #define LCPOPT_NUMMODE  11
166 #define LCPOPT_DEP12    12
167 #define LCPOPT_CBACK    13
168 #define LCPOPT_DEP14    14
169 #define LCPOPT_DEP15    15
170 #define LCPOPT_DEP16    16
171 #define LCPOPT_MLMRRU   17
172 #define LCPOPT_MLSSNHF  18
173 #define LCPOPT_MLED     19
174 #define LCPOPT_PROP     20
175 #define LCPOPT_DCEID    21
176 #define LCPOPT_MPP      22
177 #define LCPOPT_LD       23
178 #define LCPOPT_LCPAOPT  24
179 #define LCPOPT_COBS     25
180 #define LCPOPT_PE       26
181 #define LCPOPT_MLHF     27
182 #define LCPOPT_I18N     28
183 #define LCPOPT_SDLOS    29
184 #define LCPOPT_PPPMUX   30
185
186 #define LCPOPT_MIN LCPOPT_VEXT
187 #define LCPOPT_MAX LCPOPT_PPPMUX
188
189 static const char *lcpconfopts[] = {
190         "Vend-Ext",             /* (0) */
191         "MRU",                  /* (1) */
192         "ACCM",                 /* (2) */
193         "Auth-Prot",            /* (3) */
194         "Qual-Prot",            /* (4) */
195         "Magic-Num",            /* (5) */
196         "deprecated(6)",        /* used to be a Quality Protocol */
197         "PFC",                  /* (7) */
198         "ACFC",                 /* (8) */
199         "FCS-Alt",              /* (9) */
200         "SDP",                  /* (10) */
201         "Num-Mode",             /* (11) */
202         "deprecated(12)",       /* used to be a Multi-Link-Procedure*/
203         "Call-Back",            /* (13) */
204         "deprecated(14)",       /* used to be a Connect-Time */
205         "deprecated(15)",       /* used to be a Compund-Frames */
206         "deprecated(16)",       /* used to be a Nominal-Data-Encap */
207         "MRRU",                 /* (17) */
208         "12-Bit seq #",         /* (18) */
209         "End-Disc",             /* (19) */
210         "Proprietary",          /* (20) */
211         "DCE-Id",               /* (21) */
212         "MP+",                  /* (22) */
213         "Link-Disc",            /* (23) */
214         "LCP-Auth-Opt",         /* (24) */
215         "COBS",                 /* (25) */
216         "Prefix-elision",       /* (26) */
217         "Multilink-header-Form",/* (27) */
218         "I18N",                 /* (28) */
219         "SDL-over-SONET/SDH",   /* (29) */
220         "PPP-Muxing",           /* (30) */
221 };
222
223 /* ECP - to be supported */
224
225 /* CCP Config Options */
226
227 #define CCPOPT_OUI      0       /* RFC1962 */
228 #define CCPOPT_PRED1    1       /* RFC1962 */
229 #define CCPOPT_PRED2    2       /* RFC1962 */
230 #define CCPOPT_PJUMP    3       /* RFC1962 */
231 /* 4-15 unassigned */
232 #define CCPOPT_HPPPC    16      /* RFC1962 */
233 #define CCPOPT_STACLZS  17      /* RFC1974 */
234 #define CCPOPT_MPPC     18      /* RFC2118 */
235 #define CCPOPT_GFZA     19      /* RFC1962 */
236 #define CCPOPT_V42BIS   20      /* RFC1962 */
237 #define CCPOPT_BSDCOMP  21      /* RFC1977 */
238 /* 22 unassigned */
239 #define CCPOPT_LZSDCP   23      /* RFC1967 */
240 #define CCPOPT_MVRCA    24      /* RFC1975 */
241 #define CCPOPT_DEC      25      /* RFC1976 */
242 #define CCPOPT_DEFLATE  26      /* RFC1979 */
243 /* 27-254 unassigned */
244 #define CCPOPT_RESV     255     /* RFC1962 */
245
246 const struct tok ccpconfopts_values[] = {
247         { CCPOPT_OUI, "OUI" },
248         { CCPOPT_PRED1, "Pred-1" },
249         { CCPOPT_PRED2, "Pred-2" },
250         { CCPOPT_PJUMP, "Puddle" },
251         { CCPOPT_HPPPC, "HP-PPC" },
252         { CCPOPT_STACLZS, "Stac-LZS" },
253         { CCPOPT_MPPC, "MPPC" },
254         { CCPOPT_GFZA, "Gand-FZA" },
255         { CCPOPT_V42BIS, "V.42bis" },
256         { CCPOPT_BSDCOMP, "BSD-Comp" },
257         { CCPOPT_LZSDCP, "LZS-DCP" },
258         { CCPOPT_MVRCA, "MVRCA" },
259         { CCPOPT_DEC, "DEC" },
260         { CCPOPT_DEFLATE, "Deflate" },
261         { CCPOPT_RESV, "Reserved"},
262         {0,                 NULL}
263 };
264
265 /* BACP Config Options */
266
267 #define BACPOPT_FPEER   1       /* RFC2125 */
268
269 const struct tok bacconfopts_values[] = {
270         { BACPOPT_FPEER, "Favored-Peer" },
271         {0,                 NULL}
272 };
273
274
275 /* SDCP - to be supported */
276
277 /* IPCP Config Options */
278 #define IPCPOPT_2ADDR   1       /* RFC1172, RFC1332 (deprecated) */
279 #define IPCPOPT_IPCOMP  2       /* RFC1332 */
280 #define IPCPOPT_ADDR    3       /* RFC1332 */
281 #define IPCPOPT_MOBILE4 4       /* RFC2290 */
282 #define IPCPOPT_PRIDNS  129     /* RFC1877 */
283 #define IPCPOPT_PRINBNS 130     /* RFC1877 */
284 #define IPCPOPT_SECDNS  131     /* RFC1877 */
285 #define IPCPOPT_SECNBNS 132     /* RFC1877 */
286
287 struct tok ipcpopt_values[] = {
288         { IPCPOPT_2ADDR, "IP-Addrs" },
289         { IPCPOPT_IPCOMP, "IP-Comp" },
290         { IPCPOPT_ADDR, "IP-Addr" },
291         { IPCPOPT_MOBILE4, "Home-Addr" },
292         { IPCPOPT_PRIDNS, "Pri-DNS" },
293         { IPCPOPT_PRINBNS, "Pri-NBNS" },
294         { IPCPOPT_SECDNS, "Sec-DNS" },
295         { IPCPOPT_SECNBNS, "Sec-NBNS" },
296         { 0,              NULL }
297 };
298
299 #define IPCPOPT_IPCOMP_HDRCOMP 0x61  /* rfc3544 */
300 #define IPCPOPT_IPCOMP_MINLEN    14
301
302 struct tok ipcpopt_compproto_values[] = {
303         { PPP_VJC, "VJ-Comp" },
304         { IPCPOPT_IPCOMP_HDRCOMP, "IP Header Compression" },
305         { 0,              NULL }
306 };
307
308 struct tok ipcpopt_compproto_subopt_values[] = {
309         { 1, "RTP-Compression" },
310         { 2, "Enhanced RTP-Compression" },
311         { 0,              NULL }
312 };
313
314 /* IP6CP Config Options */
315 #define IP6CP_IFID      1
316
317 struct tok ip6cpopt_values[] = {
318         { IP6CP_IFID, "Interface-ID" },
319         { 0,              NULL }
320 };
321
322 /* ATCP - to be supported */
323 /* OSINLCP - to be supported */
324 /* BVCP - to be supported */
325 /* BCP - to be supported */
326 /* IPXCP - to be supported */
327 /* MPLSCP - to be supported */
328
329 /* Auth Algorithms */
330
331 /* 0-4 Reserved (RFC1994) */
332 #define AUTHALG_CHAPMD5 5       /* RFC1994 */
333 #define AUTHALG_MSCHAP1 128     /* RFC2433 */
334 #define AUTHALG_MSCHAP2 129     /* RFC2795 */
335
336 struct tok authalg_values[] = {
337         { AUTHALG_CHAPMD5, "MD5" },
338         { AUTHALG_MSCHAP1, "MS-CHAPv1" },
339         { AUTHALG_MSCHAP2, "MS-CHAPv2" },
340         { 0,              NULL }
341 };
342
343 /* FCS Alternatives - to be supported */
344
345 /* Multilink Endpoint Discriminator (RFC1717) */
346 #define MEDCLASS_NULL   0       /* Null Class */
347 #define MEDCLASS_LOCAL  1       /* Locally Assigned */
348 #define MEDCLASS_IPV4   2       /* Internet Protocol (IPv4) */
349 #define MEDCLASS_MAC    3       /* IEEE 802.1 global MAC address */
350 #define MEDCLASS_MNB    4       /* PPP Magic Number Block */
351 #define MEDCLASS_PSNDN  5       /* Public Switched Network Director Number */
352
353 /* PPP LCP Callback */
354 #define CALLBACK_AUTH   0       /* Location determined by user auth */
355 #define CALLBACK_DSTR   1       /* Dialing string */
356 #define CALLBACK_LID    2       /* Location identifier */
357 #define CALLBACK_E164   3       /* E.164 number */
358 #define CALLBACK_X500   4       /* X.500 distinguished name */
359 #define CALLBACK_CBCP   6       /* Location is determined during CBCP nego */
360
361 struct tok ppp_callback_values[] = {
362         { CALLBACK_AUTH, "UserAuth" },
363         { CALLBACK_DSTR, "DialString" },
364         { CALLBACK_LID, "LocalID" },
365         { CALLBACK_E164, "E.164" },
366         { CALLBACK_X500, "X.500" },
367         { CALLBACK_CBCP, "CBCP" },
368         { 0,              NULL }
369 };
370
371 /* CHAP */
372
373 #define CHAP_CHAL       1
374 #define CHAP_RESP       2
375 #define CHAP_SUCC       3
376 #define CHAP_FAIL       4
377
378 struct tok chapcode_values[] = {
379         { CHAP_CHAL, "Challenge" },
380         { CHAP_RESP, "Response" },
381         { CHAP_SUCC, "Success" },
382         { CHAP_FAIL, "Fail" },
383         { 0, NULL}
384 };
385
386 /* PAP */
387
388 #define PAP_AREQ        1
389 #define PAP_AACK        2
390 #define PAP_ANAK        3
391
392 struct tok papcode_values[] = {
393         { PAP_AREQ, "Auth-Req" },
394         { PAP_AACK, "Auth-ACK" },
395         { PAP_ANAK, "Auth-NACK" },
396         { 0, NULL }
397 };
398
399 /* BAP */
400 #define BAP_CALLREQ     1
401 #define BAP_CALLRES     2
402 #define BAP_CBREQ       3
403 #define BAP_CBRES       4
404 #define BAP_LDQREQ      5
405 #define BAP_LDQRES      6
406 #define BAP_CSIND       7
407 #define BAP_CSRES       8
408
409 static void handle_ctrl_proto (u_int proto,const u_char *p, int length);
410 static void handle_chap (const u_char *p, int length);
411 static void handle_pap (const u_char *p, int length);
412 static void handle_bap (const u_char *p, int length);
413 static void handle_mlppp(const u_char *p, int length);
414 static int print_lcp_config_options (const u_char *p, int);
415 static int print_ipcp_config_options (const u_char *p, int);
416 static int print_ip6cp_config_options (const u_char *p, int);
417 static int print_ccp_config_options (const u_char *p, int);
418 static int print_bacp_config_options (const u_char *p, int);
419 static void handle_ppp (u_int proto, const u_char *p, int length);
420 static void ppp_hdlc(const u_char *p, int length);
421
422 /* generic Control Protocol (e.g. LCP, IPCP, CCP, etc.) handler */
423 static void
424 handle_ctrl_proto(u_int proto, const u_char *pptr, int length)
425 {
426         const char *typestr;
427         u_int code, len;
428         int (*pfunc)(const u_char *, int);
429         int x, j;
430         const u_char *tptr;
431
432         tptr=pptr;
433
434         typestr = tok2str(ppptype2str, "unknown ctrl-proto (0x%04x)", proto);
435         printf("%s, ",typestr);
436
437         if (length < 4) /* FIXME weak boundary checking */
438                 goto trunc;
439         TCHECK2(*tptr, 2);
440
441         code = *tptr++;
442         
443         printf("%s (0x%02x), id %u, length %u",
444                tok2str(cpcodes, "Unknown Opcode",code),
445                code,
446                *tptr++, /* ID */
447                length+2);
448
449         if (!vflag)
450                 return;
451
452         if (length <= 4)
453                 return;    /* there may be a NULL confreq etc. */
454
455         TCHECK2(*tptr, 2);
456         len = EXTRACT_16BITS(tptr);
457         tptr += 2;
458
459         printf("\n\tencoded length %u (=Option(s) length %u)",len,len-4);
460
461         if (vflag>1)
462             print_unknown_data(pptr-2,"\n\t",6);
463
464
465         switch (code) {
466         case CPCODES_VEXT:
467                 if (length < 11)
468                         break;
469                 TCHECK2(*tptr, 4);
470                 printf("\n\t  Magic-Num 0x%08x", EXTRACT_32BITS(tptr));
471                 tptr += 4;
472                 TCHECK2(*tptr, 3);
473                 printf(" Vendor: %s (%u)",
474                        tok2str(oui_values,"Unknown",EXTRACT_24BITS(tptr)),
475                        EXTRACT_24BITS(tptr));
476                 /* XXX: need to decode Kind and Value(s)? */
477                 break;
478         case CPCODES_CONF_REQ:
479         case CPCODES_CONF_ACK:
480         case CPCODES_CONF_NAK:
481         case CPCODES_CONF_REJ:
482                 x = len - 4;    /* Code(1), Identifier(1) and Length(2) */
483                 do {
484                         switch (proto) {
485                         case PPP_LCP:
486                                 pfunc = print_lcp_config_options;
487                                 break;
488                         case PPP_IPCP:
489                                 pfunc = print_ipcp_config_options;
490                                 break;
491                         case PPP_IPV6CP:
492                                 pfunc = print_ip6cp_config_options;
493                                 break;
494                         case PPP_CCP:
495                                 pfunc = print_ccp_config_options;
496                                 break;
497                         case PPP_BACP:
498                                 pfunc = print_bacp_config_options;
499                                 break;
500                         default:
501                                 /*
502                                  * No print routine for the options for
503                                  * this protocol.
504                                  */
505                                 pfunc = NULL;
506                                 break;
507                         }
508
509                         if (pfunc == NULL) /* catch the above null pointer if unknown CP */
510                                 break;
511  
512                         if ((j = (*pfunc)(tptr, len)) == 0)
513                                 break;
514                         x -= j;
515                         tptr += j;
516                 } while (x > 0);
517                 break;
518
519         case CPCODES_TERM_REQ:
520         case CPCODES_TERM_ACK:
521                 /* XXX: need to decode Data? */
522                 break;
523         case CPCODES_CODE_REJ:
524                 /* XXX: need to decode Rejected-Packet? */
525                 break;
526         case CPCODES_PROT_REJ:
527                 if (length < 6)
528                         break;
529                 TCHECK2(*tptr, 2);
530                 printf("\n\t  Rejected %s Protocol (0x%04x)",
531                        tok2str(ppptype2str,"unknown", EXTRACT_16BITS(tptr)),
532                        EXTRACT_16BITS(tptr));
533                 /* XXX: need to decode Rejected-Information? - hexdump for now */
534                 if (len > 6) {
535                         printf("\n\t  Rejected Packet");
536                         print_unknown_data(tptr+2,"\n\t    ",len-2);
537                 }
538                 break;
539         case CPCODES_ECHO_REQ:
540         case CPCODES_ECHO_RPL:
541         case CPCODES_DISC_REQ:
542                 if (length < 8)
543                         break;
544                 TCHECK2(*tptr, 4);
545                 printf("\n\t  Magic-Num 0x%08x", EXTRACT_32BITS(tptr));
546                 /* XXX: need to decode Data? - hexdump for now */
547                 if (len > 8) {
548                         printf("\n\t  -----trailing data-----");
549                         TCHECK2(tptr[4], len-8);
550                         print_unknown_data(tptr+4,"\n\t  ",len-8);
551                 }
552                 break;
553         case CPCODES_ID:
554                 if (length < 8)
555                         break;
556                 TCHECK2(*tptr, 4);
557                 printf("\n\t  Magic-Num 0x%08x", EXTRACT_32BITS(tptr));
558                 /* RFC 1661 says this is intended to be human readable */
559                 if (len > 8) {
560                         printf("\n\t  Message\n\t    ");
561                         fn_printn(tptr+4,len-4,snapend);
562                 }
563                 break;
564         case CPCODES_TIME_REM:
565                 if (length < 12)
566                         break;
567                 TCHECK2(*tptr, 4);
568                 printf("\n\t  Magic-Num 0x%08x", EXTRACT_32BITS(tptr));
569                 TCHECK2(*(tptr + 4), 4);
570                 printf(", Seconds-Remaining %us", EXTRACT_32BITS(tptr + 4));
571                 /* XXX: need to decode Message? */
572                 break;
573         default:
574             /* XXX this is dirty but we do not get the
575              * original pointer passed to the begin
576              * the PPP packet */
577                 if (vflag <= 1)
578                     print_unknown_data(pptr-2,"\n\t  ",length+2);
579                 break;
580         }
581         return;
582
583 trunc:
584         printf("[|%s]", typestr);
585 }
586
587 /* LCP config options */
588 static int
589 print_lcp_config_options(const u_char *p, int length)
590 {
591         int len, opt;
592
593         if (length < 2)
594                 return 0;
595         TCHECK2(*p, 2);
596         len = p[1];
597         opt = p[0];
598         if (length < len)
599                 return 0;
600         if (len < 2) {
601                 if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX))
602                         printf("\n\t  %s Option (0x%02x), length %u (bogus, should be >= 2)", lcpconfopts[opt],opt,len);
603                 else
604                         printf("\n\tunknown LCP option 0x%02x", opt);
605                 return 0;
606         }
607         if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX))
608                 printf("\n\t  %s Option (0x%02x), length %u: ", lcpconfopts[opt],opt,len);
609         else {
610                 printf("\n\tunknown LCP option 0x%02x", opt);
611                 return len;
612         }
613
614         switch (opt) {
615         case LCPOPT_VEXT:
616                 if (len >= 6) {
617                         TCHECK2(*(p + 2), 3);
618                         printf("Vendor: %s (%u)",
619                                tok2str(oui_values,"Unknown",EXTRACT_24BITS(p+2)),
620                                EXTRACT_24BITS(p+2));
621 #if 0
622                         TCHECK(p[5]);
623                         printf(", kind: 0x%02x", p[5]);
624                         printf(", Value: 0x")
625                         for (i = 0; i < len - 6; i++) {
626                                 TCHECK(p[6 + i]);
627                                 printf("%02x", p[6 + i]);
628                         }
629 #endif
630                 }
631                 break;
632         case LCPOPT_MRU:
633                 if (len == 4) {
634                         TCHECK2(*(p + 2), 2);
635                         printf("%u", EXTRACT_16BITS(p + 2));
636                 }
637                 break;
638         case LCPOPT_ACCM:
639                 if (len == 6) {
640                         TCHECK2(*(p + 2), 4);
641                         printf("0x%08x", EXTRACT_32BITS(p + 2));
642                 }
643                 break;
644         case LCPOPT_AP:
645                 if (len >= 4) {
646                     TCHECK2(*(p + 2), 2);
647                     printf("%s", tok2str(ppptype2str,"Unknown Auth Proto (0x04x)",EXTRACT_16BITS(p+2)));
648
649                     switch (EXTRACT_16BITS(p+2)) {
650                     case PPP_CHAP:
651                         TCHECK(p[4]);
652                         printf(", %s",tok2str(authalg_values,"Unknown Auth Alg %u",p[4]));
653                         break;
654                     case PPP_PAP: /* fall through */
655                     case PPP_EAP:
656                     case PPP_SPAP:
657                     case PPP_SPAP_OLD:
658                         break;
659                     default:
660                         print_unknown_data(p,"\n\t",len);
661                     }
662                 }
663                 break;
664         case LCPOPT_QP:
665                 if (len >= 4) {
666                         TCHECK2(*(p + 2), 2);
667                         if (EXTRACT_16BITS(p+2) == PPP_LQM)
668                                 printf(" LQR");
669                         else
670                                 printf(" unknown");
671                 }
672                 break;
673         case LCPOPT_MN:
674                 if (len == 6) {
675                         TCHECK2(*(p + 2), 4);
676                         printf("0x%08x", EXTRACT_32BITS(p + 2));
677                 }
678                 break;
679         case LCPOPT_PFC:
680                 break;
681         case LCPOPT_ACFC:
682                 break;
683         case LCPOPT_LD:
684                 if (len == 4) {
685                         TCHECK2(*(p + 2), 2);
686                         printf("0x%04x", EXTRACT_16BITS(p + 2));
687                 }
688                 break;
689         case LCPOPT_CBACK:
690                 if (len < 3)
691                         break;
692                 TCHECK(p[2]);
693                 printf("Callback Operation %s (%u)",
694                        tok2str(ppp_callback_values,"Unknown",p[2]),
695                        p[2]);
696                 break;
697         case LCPOPT_MLMRRU:
698                 if (len == 4) {
699                         TCHECK2(*(p + 2), 2);
700                         printf("%u", EXTRACT_16BITS(p + 2));
701                 }
702                 break;
703         case LCPOPT_MLED:
704                 if (len < 3)
705                         break;
706                 TCHECK(p[2]);
707                 switch (p[2]) {         /* class */
708                 case MEDCLASS_NULL:
709                         printf("Null");
710                         break;
711                 case MEDCLASS_LOCAL:
712                         printf("Local"); /* XXX */
713                         break;
714                 case MEDCLASS_IPV4:
715                         if (len != 7)
716                                 break;
717                         TCHECK2(*(p + 3), 4);
718                         printf("IPv4 %s", ipaddr_string(p + 3));
719                         break;
720                 case MEDCLASS_MAC:
721                         if (len != 9)
722                                 break;
723                         TCHECK(p[8]);
724                         printf("MAC %02x:%02x:%02x:%02x:%02x:%02x",
725                                p[3], p[4], p[5], p[6], p[7], p[8]);
726                         break;
727                 case MEDCLASS_MNB:
728                         printf("Magic-Num-Block"); /* XXX */
729                         break;
730                 case MEDCLASS_PSNDN:
731                         printf("PSNDN"); /* XXX */
732                         break;
733                 }
734                 break;
735
736 /* XXX: to be supported */
737 #if 0
738         case LCPOPT_DEP6:
739         case LCPOPT_FCSALT:
740         case LCPOPT_SDP:
741         case LCPOPT_NUMMODE:
742         case LCPOPT_DEP12:
743         case LCPOPT_DEP14:
744         case LCPOPT_DEP15:
745         case LCPOPT_DEP16:
746         case LCPOPT_MLSSNHF:
747         case LCPOPT_PROP:
748         case LCPOPT_DCEID:
749         case LCPOPT_MPP:
750         case LCPOPT_LCPAOPT:
751         case LCPOPT_COBS:
752         case LCPOPT_PE:
753         case LCPOPT_MLHF:
754         case LCPOPT_I18N:
755         case LCPOPT_SDLOS:
756         case LCPOPT_PPPMUX:
757                 break;
758 #endif
759         default:
760                 if(vflag<2)
761                         print_unknown_data(&p[2],"\n\t    ",len-2);
762                 break;
763         }
764          
765         if (vflag>1)
766                 print_unknown_data(&p[2],"\n\t    ",len-2); /* exclude TLV header */
767
768         return len;
769
770 trunc:
771         printf("[|lcp]");
772         return 0;
773 }
774
775 /* ML-PPP*/
776 struct tok ppp_ml_flag_values[] = {
777     { 0x80, "begin" },
778     { 0x40, "end" },
779     { 0, NULL }
780 };
781
782 static void
783 handle_mlppp(const u_char *p, int length) {
784
785     if (!eflag)
786         printf("MLPPP, ");
787
788     printf("seq 0x%03x, Flags [%s], length %u",
789            (EXTRACT_16BITS(p))&0x0fff, /* only support 12-Bit sequence space for now */
790            bittok2str(ppp_ml_flag_values, "none", *p & 0xc0),
791            length);
792
793     return;
794 }
795
796 /* CHAP */
797 static void
798 handle_chap(const u_char *p, int length)
799 {
800         u_int code, len;
801         int val_size, name_size, msg_size;
802         const u_char *p0;
803         int i;
804
805         p0 = p;
806         if (length < 1) {
807                 printf("[|chap]");
808                 return;
809         } else if (length < 4) {
810                 TCHECK(*p);
811                 printf("[|chap 0x%02x]", *p);
812                 return;
813         }
814
815         TCHECK(*p);
816         code = *p;
817         printf("CHAP, %s (0x%02x)",
818                tok2str(chapcode_values,"unknown",code),
819                code);
820         p++;
821
822         TCHECK(*p);
823         printf(", id %u", *p);          /* ID */
824         p++;
825
826         TCHECK2(*p, 2);
827         len = EXTRACT_16BITS(p);
828         p += 2;
829
830         /*
831          * Note that this is a generic CHAP decoding routine. Since we
832          * don't know which flavor of CHAP (i.e. CHAP-MD5, MS-CHAPv1,
833          * MS-CHAPv2) is used at this point, we can't decode packet
834          * specifically to each algorithms. Instead, we simply decode
835          * the GCD (Gratest Common Denominator) for all algorithms.
836          */
837         switch (code) {
838         case CHAP_CHAL:
839         case CHAP_RESP:
840                 if (length - (p - p0) < 1)
841                         return;
842                 TCHECK(*p);
843                 val_size = *p;          /* value size */
844                 p++;
845                 if (length - (p - p0) < val_size)
846                         return;
847                 printf(", Value ");
848                 for (i = 0; i < val_size; i++) {
849                         TCHECK(*p);
850                         printf("%02x", *p++);
851                 }
852                 name_size = len - (p - p0);
853                 printf(", Name ");
854                 for (i = 0; i < name_size; i++) {
855                         TCHECK(*p);
856                         safeputchar(*p++);
857                 }
858                 break;
859         case CHAP_SUCC:
860         case CHAP_FAIL:
861                 msg_size = len - (p - p0);
862                 printf(", Msg ");
863                 for (i = 0; i< msg_size; i++) {
864                         TCHECK(*p);
865                         safeputchar(*p++);
866                 }
867                 break;
868         }
869         return;
870
871 trunc:
872         printf("[|chap]");
873 }
874
875 /* PAP (see RFC 1334) */
876 static void
877 handle_pap(const u_char *p, int length)
878 {
879         u_int code, len;
880         int peerid_len, passwd_len, msg_len;
881         const u_char *p0;
882         int i;
883
884         p0 = p;
885         if (length < 1) {
886                 printf("[|pap]");
887                 return;
888         } else if (length < 4) {
889                 TCHECK(*p);
890                 printf("[|pap 0x%02x]", *p);
891                 return;
892         }
893
894         TCHECK(*p);
895         code = *p;
896         printf("PAP, %s (0x%02x)",
897                tok2str(papcode_values,"unknown",code),
898                code);
899         p++;
900
901         TCHECK(*p);
902         printf(", id %u", *p);          /* ID */
903         p++;
904
905         TCHECK2(*p, 2);
906         len = EXTRACT_16BITS(p);
907         p += 2;
908
909         if ((int)len > length) {
910                 printf(", length %u > packet size", len);
911                 return;
912         }
913         length = len;
914         if (length < (p - p0)) {
915                 printf(", length %u < PAP header length", length);
916                 return;
917         }
918
919         switch (code) {
920         case PAP_AREQ:
921                 if (length - (p - p0) < 1)
922                         return;
923                 TCHECK(*p);
924                 peerid_len = *p;        /* Peer-ID Length */
925                 p++;
926                 if (length - (p - p0) < peerid_len)
927                         return;
928                 printf(", Peer ");
929                 for (i = 0; i < peerid_len; i++) {
930                         TCHECK(*p);
931                         safeputchar(*p++);
932                 }
933
934                 if (length - (p - p0) < 1)
935                         return;
936                 TCHECK(*p);
937                 passwd_len = *p;        /* Password Length */
938                 p++;
939                 if (length - (p - p0) < passwd_len)
940                         return;
941                 printf(", Name ");
942                 for (i = 0; i < passwd_len; i++) {
943                         TCHECK(*p);
944                         safeputchar(*p++);
945                 }
946                 break;
947         case PAP_AACK:
948         case PAP_ANAK:
949                 if (length - (p - p0) < 1)
950                         return;
951                 TCHECK(*p);
952                 msg_len = *p;           /* Msg-Length */
953                 p++;
954                 if (length - (p - p0) < msg_len)
955                         return;
956                 printf(", Msg ");
957                 for (i = 0; i< msg_len; i++) {
958                         TCHECK(*p);
959                         safeputchar(*p++);
960                 }
961                 break;
962         }
963         return;
964
965 trunc:
966         printf("[|pap]");
967 }
968
969 /* BAP */
970 static void
971 handle_bap(const u_char *p _U_, int length _U_)
972 {
973         /* XXX: to be supported!! */
974 }
975
976
977 /* IPCP config options */
978 static int
979 print_ipcp_config_options(const u_char *p, int length)
980 {
981         int len, opt;
982         u_int compproto, ipcomp_subopttotallen, ipcomp_subopt, ipcomp_suboptlen;
983
984         if (length < 2)
985                 return 0;
986         TCHECK2(*p, 2);
987         len = p[1];
988         opt = p[0];
989         if (length < len)
990                 return 0;
991         if (len < 2) {
992                 printf("\n\t  %s Option (0x%02x), length %u (bogus, should be >= 2)",
993                        tok2str(ipcpopt_values,"unknown",opt),
994                        opt,
995                        len);
996                 return 0;
997         }
998
999         printf("\n\t  %s Option (0x%02x), length %u: ",
1000                tok2str(ipcpopt_values,"unknown",opt),
1001                opt,
1002                len);
1003
1004         switch (opt) {
1005         case IPCPOPT_2ADDR:             /* deprecated */
1006                 if (len != 10)
1007                         goto invlen;
1008                 TCHECK2(*(p + 6), 4);
1009                 printf("src %s, dst %s",
1010                        ipaddr_string(p + 2),
1011                        ipaddr_string(p + 6));
1012                 break;
1013         case IPCPOPT_IPCOMP:
1014                 if (len < 4)
1015                         goto invlen;
1016                 TCHECK2(*(p + 2), 2);
1017                 compproto = EXTRACT_16BITS(p+2);
1018
1019                 printf("%s (0x%02x):",
1020                        tok2str(ipcpopt_compproto_values,"Unknown",compproto),
1021                        compproto);
1022
1023                 switch (compproto) {
1024                 case PPP_VJC:
1025                         /* XXX: VJ-Comp parameters should be decoded */
1026                         break;
1027                 case IPCPOPT_IPCOMP_HDRCOMP:
1028                         if (len < IPCPOPT_IPCOMP_MINLEN)
1029                                 goto invlen;
1030
1031                         TCHECK2(*(p + 2), IPCPOPT_IPCOMP_MINLEN);
1032                         printf("\n\t    TCP Space %u, non-TCP Space %u" \
1033                                ", maxPeriod %u, maxTime %u, maxHdr %u",
1034                                EXTRACT_16BITS(p+4),
1035                                EXTRACT_16BITS(p+6),
1036                                EXTRACT_16BITS(p+8),
1037                                EXTRACT_16BITS(p+10),
1038                                EXTRACT_16BITS(p+12));
1039
1040                         /* suboptions present ? */
1041                         if (len > IPCPOPT_IPCOMP_MINLEN) {
1042                                 ipcomp_subopttotallen = len - IPCPOPT_IPCOMP_MINLEN;
1043                                 p += IPCPOPT_IPCOMP_MINLEN;
1044                                 
1045                                 printf("\n\t      Suboptions, length %u", ipcomp_subopttotallen);
1046
1047                                 while (ipcomp_subopttotallen >= 2) {
1048                                         TCHECK2(*p, 2);
1049                                         ipcomp_subopt = *p;
1050                                         ipcomp_suboptlen = *(p+1);
1051                                         
1052                                         /* sanity check */
1053                                         if (ipcomp_subopt == 0 ||
1054                                             ipcomp_suboptlen == 0 )
1055                                                 break;
1056
1057                                         /* XXX: just display the suboptions for now */
1058                                         printf("\n\t\t%s Suboption #%u, length %u",
1059                                                tok2str(ipcpopt_compproto_subopt_values,
1060                                                        "Unknown",
1061                                                        ipcomp_subopt),
1062                                                ipcomp_subopt,
1063                                                ipcomp_suboptlen);
1064
1065                                         ipcomp_subopttotallen -= ipcomp_suboptlen;
1066                                         p += ipcomp_suboptlen;
1067                                 }
1068                         }
1069                         break;
1070                 default:
1071                         break;
1072                 }
1073                 break;
1074
1075         case IPCPOPT_ADDR:     /* those options share the same format - fall through */
1076         case IPCPOPT_MOBILE4:
1077         case IPCPOPT_PRIDNS:
1078         case IPCPOPT_PRINBNS:
1079         case IPCPOPT_SECDNS:
1080         case IPCPOPT_SECNBNS:
1081                 if (len != 6)
1082                         goto invlen;
1083                 TCHECK2(*(p + 2), 4);
1084                 printf("%s", ipaddr_string(p + 2));
1085                 break;
1086         default:
1087                 if(vflag<2)
1088                         print_unknown_data(&p[2],"\n\t    ",len-2);
1089                 break;
1090         }
1091         if (vflag>1)
1092                 print_unknown_data(&p[2],"\n\t    ",len-2); /* exclude TLV header */
1093         return len;
1094
1095 invlen:
1096         printf(", invalid-length-%d", opt);
1097         return 0;
1098
1099 trunc:
1100         printf("[|ipcp]");
1101         return 0;
1102 }
1103
1104 /* IP6CP config options */
1105 static int
1106 print_ip6cp_config_options(const u_char *p, int length)
1107 {
1108         int len, opt;
1109
1110         if (length < 2)
1111                 return 0;
1112         TCHECK2(*p, 2);
1113         len = p[1];
1114         opt = p[0];
1115         if (length < len)
1116                 return 0;
1117         if (len < 2) {
1118                 printf("\n\t  %s Option (0x%02x), length %u (bogus, should be >= 2)",
1119                        tok2str(ip6cpopt_values,"unknown",opt),
1120                        opt,
1121                        len);
1122                 return 0;
1123         }
1124
1125         printf("\n\t  %s Option (0x%02x), length %u: ",
1126                tok2str(ip6cpopt_values,"unknown",opt),
1127                opt,
1128                len);
1129
1130         switch (opt) {
1131         case IP6CP_IFID:
1132                 if (len != 10)
1133                         goto invlen;
1134                 TCHECK2(*(p + 2), 8);
1135                 printf("%04x:%04x:%04x:%04x",
1136                        EXTRACT_16BITS(p + 2),
1137                        EXTRACT_16BITS(p + 4),
1138                        EXTRACT_16BITS(p + 6),
1139                        EXTRACT_16BITS(p + 8));
1140                 break;
1141         default:
1142                 if(vflag<2)
1143                         print_unknown_data(&p[2],"\n\t    ",len-2);
1144                 break;
1145         }
1146         if (vflag>1)
1147                 print_unknown_data(&p[2],"\n\t    ",len-2); /* exclude TLV header */
1148
1149         return len;
1150
1151 invlen:
1152         printf(", invalid-length-%d", opt);
1153         return 0;
1154
1155 trunc:
1156         printf("[|ip6cp]");
1157         return 0;
1158 }
1159
1160
1161 /* CCP config options */
1162 static int
1163 print_ccp_config_options(const u_char *p, int length)
1164 {
1165         int len, opt;
1166
1167         if (length < 2)
1168                 return 0;
1169         TCHECK2(*p, 2);
1170         len = p[1];
1171         opt = p[0];
1172         if (length < len)
1173                 return 0;
1174         if (len < 2) {
1175                 printf("\n\t  %s Option (0x%02x), length %u (bogus, should be >= 2)",
1176                        tok2str(ccpconfopts_values, "Unknown", opt),
1177                        opt,
1178                        len);
1179                 return 0;
1180         }
1181
1182         printf("\n\t  %s Option (0x%02x), length %u:",
1183                tok2str(ccpconfopts_values, "Unknown", opt),
1184                opt,
1185                len);
1186
1187         switch (opt) {
1188                 /* fall through --> default: nothing supported yet */
1189         case CCPOPT_OUI:
1190         case CCPOPT_PRED1:
1191         case CCPOPT_PRED2:
1192         case CCPOPT_PJUMP:
1193         case CCPOPT_HPPPC:
1194         case CCPOPT_STACLZS:
1195         case CCPOPT_MPPC:
1196         case CCPOPT_GFZA:
1197         case CCPOPT_V42BIS:
1198         case CCPOPT_BSDCOMP:
1199         case CCPOPT_LZSDCP:
1200         case CCPOPT_MVRCA:
1201         case CCPOPT_DEC:
1202         case CCPOPT_DEFLATE:
1203         case CCPOPT_RESV:
1204         default:
1205                 if(vflag<2)
1206                         print_unknown_data(&p[2],"\n\t    ",len-2);
1207                 break;
1208         }
1209         if (vflag>1)
1210                 print_unknown_data(&p[2],"\n\t    ",len-2); /* exclude TLV header */
1211
1212         return len;
1213
1214 trunc:
1215         printf("[|ccp]");
1216         return 0;
1217 }
1218
1219 /* BACP config options */
1220 static int
1221 print_bacp_config_options(const u_char *p, int length)
1222 {
1223         int len, opt;
1224
1225         if (length < 2)
1226                 return 0;
1227         TCHECK2(*p, 2);
1228         len = p[1];
1229         opt = p[0];
1230         if (length < len)
1231                 return 0;
1232         if (len < 2) {
1233                 printf("\n\t  %s Option (0x%02x), length %u (bogus, should be >= 2)",
1234                        tok2str(bacconfopts_values, "Unknown", opt),
1235                        opt,
1236                        len);
1237                 return 0;
1238         }
1239
1240         printf("\n\t  %s Option (0x%02x), length %u:",
1241                tok2str(bacconfopts_values, "Unknown", opt),
1242                opt,
1243                len);
1244
1245         switch (opt) {
1246         case BACPOPT_FPEER:
1247                 TCHECK2(*(p + 2), 4);
1248                 printf(", Magic-Num 0x%08x", EXTRACT_32BITS(p + 2));
1249                 break;
1250         default:
1251                 if(vflag<2)
1252                         print_unknown_data(&p[2],"\n\t    ",len-2);
1253                 break;
1254         }
1255         if (vflag>1)
1256                 print_unknown_data(&p[2],"\n\t    ",len-2); /* exclude TLV header */
1257
1258         return len;
1259
1260 trunc:
1261         printf("[|bacp]");
1262         return 0;
1263 }
1264
1265
1266 static void
1267 ppp_hdlc(const u_char *p, int length)
1268 {
1269         u_char *b, *s, *t, c;
1270         int i, proto;
1271         const void *se;
1272
1273         b = (u_int8_t *)malloc(length);
1274         if (b == NULL)
1275                 return;
1276
1277         /*
1278          * Unescape all the data into a temporary, private, buffer.
1279          * Do this so that we dont overwrite the original packet
1280          * contents.
1281          */
1282         for (s = (u_char *)p, t = b, i = length; i > 0; i--) {
1283                 c = *s++;
1284                 if (c == 0x7d) {
1285                         if (i > 1) {
1286                                 i--;
1287                                 c = *s++ ^ 0x20;
1288                         } else
1289                                 continue;
1290                 }
1291                 *t++ = c;
1292         }
1293
1294         se = snapend;
1295         snapend = t;
1296
1297         /* now lets guess about the payload codepoint format */
1298         proto = *b; /* start with a one-octet codepoint guess */
1299         
1300         switch (proto) {
1301         case PPP_IP:
1302                 ip_print(gndo, b+1, t - b - 1);
1303                 goto cleanup;
1304 #ifdef INET6
1305         case PPP_IPV6:
1306             ip6_print(b+1, t - b - 1);
1307             goto cleanup;
1308 #endif
1309         default: /* no luck - try next guess */
1310             break;
1311         }
1312
1313         proto = EXTRACT_16BITS(b); /* next guess - load two octets */
1314
1315         switch (proto) {
1316         case (PPP_ADDRESS << 8 | PPP_CONTROL): /* looks like a PPP frame */
1317             proto = EXTRACT_16BITS(b+2); /* load the PPP proto-id */
1318             handle_ppp(proto, b+4, t - b - 4);
1319             break;
1320         default: /* last guess - proto must be a PPP proto-id */
1321             handle_ppp(proto, b+2, t - b - 2);
1322             break;
1323         }
1324
1325 cleanup:
1326         snapend = se;
1327         free(b);
1328         return;
1329 }
1330
1331
1332 /* PPP */
1333 static void
1334 handle_ppp(u_int proto, const u_char *p, int length)
1335 {
1336         if ((proto & 0xff00) == 0x7e00) {/* is this an escape code ? */
1337             ppp_hdlc(p-1, length);
1338             return;
1339         }
1340
1341         switch (proto) {
1342         case PPP_LCP: /* fall through */
1343         case PPP_IPCP:
1344         case PPP_OSICP:
1345         case PPP_MPLSCP:
1346         case PPP_IPV6CP:
1347         case PPP_CCP:
1348         case PPP_BACP:
1349                 handle_ctrl_proto(proto, p, length);
1350                 break;
1351         case PPP_ML:
1352                 handle_mlppp(p, length);
1353                 break;
1354         case PPP_CHAP:
1355                 handle_chap(p, length);
1356                 break;
1357         case PPP_PAP:
1358                 handle_pap(p, length);
1359                 break;
1360         case PPP_BAP:           /* XXX: not yet completed */
1361                 handle_bap(p, length);
1362                 break;
1363         case ETHERTYPE_IP:      /*XXX*/
1364         case PPP_VJNC:
1365         case PPP_IP:
1366                 ip_print(gndo, p, length);
1367                 break;
1368 #ifdef INET6
1369         case ETHERTYPE_IPV6:    /*XXX*/
1370         case PPP_IPV6:
1371                 ip6_print(p, length);
1372                 break;
1373 #endif
1374         case ETHERTYPE_IPX:     /*XXX*/
1375         case PPP_IPX:
1376                 ipx_print(p, length);
1377                 break;
1378         case PPP_OSI:
1379                 isoclns_print(p, length, length);
1380                 break;
1381         case PPP_MPLS_UCAST:
1382         case PPP_MPLS_MCAST:
1383                 mpls_print(p, length);
1384                 break;
1385         case PPP_COMP:
1386                 printf("compressed PPP data");
1387                 break;
1388         default:
1389                 printf("%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto));
1390                 print_unknown_data(p,"\n\t",length);
1391                 break;
1392         }
1393 }
1394
1395 /* Standard PPP printer */
1396 u_int
1397 ppp_print(register const u_char *p, u_int length)
1398 {
1399         u_int proto,ppp_header;
1400         u_int olen = length; /* _o_riginal length */
1401         u_int hdr_len = 0;
1402
1403         /*
1404          * Here, we assume that p points to the Address and Control
1405          * field (if they present).
1406          */
1407         if (length < 2)
1408                 goto trunc;
1409         TCHECK2(*p, 2);
1410         ppp_header = EXTRACT_16BITS(p);
1411
1412         switch(ppp_header) {
1413         case (PPP_WITHDIRECTION_IN  << 8 | PPP_CONTROL):
1414             if (eflag) printf("In  ");
1415             p += 2;
1416             length -= 2;
1417             hdr_len += 2;
1418             break;
1419         case (PPP_WITHDIRECTION_OUT << 8 | PPP_CONTROL):
1420             if (eflag) printf("Out ");
1421             p += 2;
1422             length -= 2;
1423             hdr_len += 2;
1424             break;
1425         case (PPP_ADDRESS << 8 | PPP_CONTROL):
1426             p += 2;                     /* ACFC not used */
1427             length -= 2;
1428             hdr_len += 2;
1429             break;
1430
1431         default:
1432             break;
1433         }
1434
1435         if (length < 2)
1436                 goto trunc;
1437         TCHECK(*p);
1438         if (*p % 2) {
1439                 proto = *p;             /* PFC is used */
1440                 p++;
1441                 length--;
1442                 hdr_len++;
1443         } else {
1444                 TCHECK2(*p, 2);
1445                 proto = EXTRACT_16BITS(p);
1446                 p += 2;
1447                 length -= 2;
1448                 hdr_len += 2;
1449         }
1450
1451         if (eflag)
1452             printf("%s (0x%04x), length %u: ",
1453                    tok2str(ppptype2str, "unknown", proto),
1454                    proto,
1455                    olen);
1456
1457         handle_ppp(proto, p, length);
1458         return (hdr_len);
1459 trunc:
1460         printf("[|ppp]");
1461         return (0);
1462 }
1463
1464
1465 /* PPP I/F printer */
1466 u_int
1467 ppp_if_print(const struct pcap_pkthdr *h, register const u_char *p)
1468 {
1469         register u_int length = h->len;
1470         register u_int caplen = h->caplen;
1471
1472         if (caplen < PPP_HDRLEN) {
1473                 printf("[|ppp]");
1474                 return (caplen);
1475         }
1476
1477 #if 0
1478         /*
1479          * XXX: seems to assume that there are 2 octets prepended to an
1480          * actual PPP frame. The 1st octet looks like Input/Output flag
1481          * while 2nd octet is unknown, at least to me
1482          * (mshindo@mshindo.net).
1483          *
1484          * That was what the original tcpdump code did.
1485          *
1486          * FreeBSD's "if_ppp.c" *does* set the first octet to 1 for outbound
1487          * packets and 0 for inbound packets - but only if the
1488          * protocol field has the 0x8000 bit set (i.e., it's a network
1489          * control protocol); it does so before running the packet through
1490          * "bpf_filter" to see if it should be discarded, and to see
1491          * if we should update the time we sent the most recent packet...
1492          *
1493          * ...but it puts the original address field back after doing
1494          * so.
1495          *
1496          * NetBSD's "if_ppp.c" doesn't set the first octet in that fashion.
1497          *
1498          * I don't know if any PPP implementation handed up to a BPF
1499          * device packets with the first octet being 1 for outbound and
1500          * 0 for inbound packets, so I (guy@alum.mit.edu) don't know
1501          * whether that ever needs to be checked or not.
1502          *
1503          * Note that NetBSD has a DLT_PPP_SERIAL, which it uses for PPP,
1504          * and its tcpdump appears to assume that the frame always
1505          * begins with an address field and a control field, and that
1506          * the address field might be 0x0f or 0x8f, for Cisco
1507          * point-to-point with HDLC framing as per section 4.3.1 of RFC
1508          * 1547, as well as 0xff, for PPP in HDLC-like framing as per
1509          * RFC 1662.
1510          *
1511          * (Is the Cisco framing in question what DLT_C_HDLC, in
1512          * BSD/OS, is?)
1513          */
1514         if (eflag)
1515                 printf("%c %4d %02x ", p[0] ? 'O' : 'I', length, p[1]);
1516 #endif
1517
1518         ppp_print(p, length);
1519
1520         return (0);
1521 }
1522
1523 /*
1524  * PPP I/F printer to use if we know that RFC 1662-style PPP in HDLC-like
1525  * framing, or Cisco PPP with HDLC framing as per section 4.3.1 of RFC 1547,
1526  * is being used (i.e., we don't check for PPP_ADDRESS and PPP_CONTROL,
1527  * discard them *if* those are the first two octets, and parse the remaining
1528  * packet as a PPP packet, as "ppp_print()" does).
1529  *
1530  * This handles, for example, DLT_PPP_SERIAL in NetBSD.
1531  */
1532 u_int
1533 ppp_hdlc_if_print(const struct pcap_pkthdr *h, register const u_char *p)
1534 {
1535         register u_int length = h->len;
1536         register u_int caplen = h->caplen;
1537         u_int proto;
1538         u_int hdrlen = 0;
1539
1540         if (caplen < 2) {
1541                 printf("[|ppp]");
1542                 return (caplen);
1543         }
1544
1545         switch (p[0]) {
1546
1547         case PPP_ADDRESS:
1548                 if (caplen < 4) {
1549                         printf("[|ppp]");
1550                         return (caplen);
1551                 }
1552
1553                 if (eflag)
1554                         printf("%02x %02x %d ", p[0], p[1], length);
1555                 p += 2;
1556                 length -= 2;
1557                 hdrlen += 2;
1558
1559                 proto = EXTRACT_16BITS(p);
1560                 p += 2;
1561                 length -= 2;
1562                 hdrlen += 2;
1563                 printf("%s: ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto));
1564
1565                 handle_ppp(proto, p, length);
1566                 break;
1567
1568         case CHDLC_UNICAST:
1569         case CHDLC_BCAST:
1570                 return (chdlc_if_print(h, p));
1571
1572         default:
1573                 if (eflag)
1574                         printf("%02x %02x %d ", p[0], p[1], length);
1575                 p += 2;
1576                 length -= 2;
1577                 hdrlen += 2;
1578
1579                 /*
1580                  * XXX - NetBSD's "ppp_netbsd_serial_if_print()" treats
1581                  * the next two octets as an Ethernet type; does that
1582                  * ever happen?
1583                  */
1584                 printf("unknown addr %02x; ctrl %02x", p[0], p[1]);
1585                 break;
1586         }
1587
1588         return (hdrlen);
1589 }
1590
1591 #define PPP_BSDI_HDRLEN 24
1592
1593 /* BSD/OS specific PPP printer */
1594 u_int
1595 ppp_bsdos_if_print(const struct pcap_pkthdr *h _U_, register const u_char *p _U_)
1596 {
1597         register int hdrlength;
1598 #ifdef __bsdi__
1599         register u_int length = h->len;
1600         register u_int caplen = h->caplen;
1601         u_int16_t ptype;
1602         const u_char *q;
1603         int i;
1604
1605         if (caplen < PPP_BSDI_HDRLEN) {
1606                 printf("[|ppp]");
1607                 return (caplen)
1608         }
1609
1610         hdrlength = 0;
1611
1612 #if 0
1613         if (p[0] == PPP_ADDRESS && p[1] == PPP_CONTROL) {
1614                 if (eflag)
1615                         printf("%02x %02x ", p[0], p[1]);
1616                 p += 2;
1617                 hdrlength = 2;
1618         }
1619
1620         if (eflag)
1621                 printf("%d ", length);
1622         /* Retrieve the protocol type */
1623         if (*p & 01) {
1624                 /* Compressed protocol field */
1625                 ptype = *p;
1626                 if (eflag)
1627                         printf("%02x ", ptype);
1628                 p++;
1629                 hdrlength += 1;
1630         } else {
1631                 /* Un-compressed protocol field */
1632                 ptype = ntohs(*(u_int16_t *)p);
1633                 if (eflag)
1634                         printf("%04x ", ptype);
1635                 p += 2;
1636                 hdrlength += 2;
1637         }
1638 #else
1639         ptype = 0;      /*XXX*/
1640         if (eflag)
1641                 printf("%c ", p[SLC_DIR] ? 'O' : 'I');
1642         if (p[SLC_LLHL]) {
1643                 /* link level header */
1644                 struct ppp_header *ph;
1645
1646                 q = p + SLC_BPFHDRLEN;
1647                 ph = (struct ppp_header *)q;
1648                 if (ph->phdr_addr == PPP_ADDRESS
1649                  && ph->phdr_ctl == PPP_CONTROL) {
1650                         if (eflag)
1651                                 printf("%02x %02x ", q[0], q[1]);
1652                         ptype = ntohs(ph->phdr_type);
1653                         if (eflag && (ptype == PPP_VJC || ptype == PPP_VJNC)) {
1654                                 printf("%s ", tok2str(ppptype2str,
1655                                                 "proto-#%d", ptype));
1656                         }
1657                 } else {
1658                         if (eflag) {
1659                                 printf("LLH=[");
1660                                 for (i = 0; i < p[SLC_LLHL]; i++)
1661                                         printf("%02x", q[i]);
1662                                 printf("] ");
1663                         }
1664                 }
1665         }
1666         if (eflag)
1667                 printf("%d ", length);
1668         if (p[SLC_CHL]) {
1669                 q = p + SLC_BPFHDRLEN + p[SLC_LLHL];
1670
1671                 switch (ptype) {
1672                 case PPP_VJC:
1673                         ptype = vjc_print(q, ptype);
1674                         hdrlength = PPP_BSDI_HDRLEN;
1675                         p += hdrlength;
1676                         switch (ptype) {
1677                         case PPP_IP:
1678                                 ip_print(p, length);
1679                                 break;
1680 #ifdef INET6
1681                         case PPP_IPV6:
1682                                 ip6_print(p, length);
1683                                 break;
1684 #endif
1685                         case PPP_MPLS_UCAST:
1686                         case PPP_MPLS_MCAST:
1687                                 mpls_print(p, length);
1688                                 break;
1689                         }
1690                         goto printx;
1691                 case PPP_VJNC:
1692                         ptype = vjc_print(q, ptype);
1693                         hdrlength = PPP_BSDI_HDRLEN;
1694                         p += hdrlength;
1695                         switch (ptype) {
1696                         case PPP_IP:
1697                                 ip_print(p, length);
1698                                 break;
1699 #ifdef INET6
1700                         case PPP_IPV6:
1701                                 ip6_print(p, length);
1702                                 break;
1703 #endif
1704                         case PPP_MPLS_UCAST:
1705                         case PPP_MPLS_MCAST:
1706                                 mpls_print(p, length);
1707                                 break;
1708                         }
1709                         goto printx;
1710                 default:
1711                         if (eflag) {
1712                                 printf("CH=[");
1713                                 for (i = 0; i < p[SLC_LLHL]; i++)
1714                                         printf("%02x", q[i]);
1715                                 printf("] ");
1716                         }
1717                         break;
1718                 }
1719         }
1720
1721         hdrlength = PPP_BSDI_HDRLEN;
1722 #endif
1723
1724         length -= hdrlength;
1725         p += hdrlength;
1726
1727         switch (ptype) {
1728         case PPP_IP:
1729                 ip_print(p, length);
1730                 break;
1731 #ifdef INET6
1732         case PPP_IPV6:
1733                 ip6_print(p, length);
1734                 break;
1735 #endif
1736         case PPP_MPLS_UCAST:
1737         case PPP_MPLS_MCAST:
1738                 mpls_print(p, length);
1739                 break;
1740         default:
1741                 printf("%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", ptype));
1742         }
1743
1744 printx:
1745 #else /* __bsdi */
1746         hdrlength = 0;
1747 #endif /* __bsdi__ */
1748         return (hdrlength);
1749 }
1750
1751
1752 /*
1753  * Local Variables:
1754  * c-style: whitesmith
1755  * c-basic-offset: 8
1756  * End:
1757  */