]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-ppp.c
This commit was generated by cvs2svn to compensate for changes in r135446,
[FreeBSD/FreeBSD.git] / contrib / tcpdump / 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  * $FreeBSD$
25  */
26
27 /*
28  * TODO:
29  * o resolve XXX as much as possible
30  * o MP support
31  * o BAP support
32  */
33
34 #ifndef lint
35 static const char rcsid[] _U_ =
36     "@(#) $Header: /tcpdump/master/tcpdump/print-ppp.c,v 1.89.2.3 2004/03/24 03:32:43 guy Exp $ (LBL)";
37 #endif
38
39 #ifdef HAVE_CONFIG_H
40 #include "config.h"
41 #endif
42
43 #include <tcpdump-stdinc.h>
44
45 #ifdef __bsdi__
46 #include <net/slcompress.h>
47 #include <net/if_ppp.h>
48 #endif
49
50 #include <pcap.h>
51 #include <stdio.h>
52
53 #include "interface.h"
54 #include "extract.h"
55 #include "addrtoname.h"
56 #include "ppp.h"
57 #include "chdlc.h"
58 #include "ethertype.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" },
76         { PPP_VJNC,       "VJNC" },
77         { PPP_BRPDU,      "BRPDU" },
78         { PPP_STII,       "STII" },
79         { PPP_VINES,      "VINES" },
80         { PPP_MPLS_UCAST, "MPLS" },
81         { PPP_MPLS_MCAST, "MPLS" },
82
83         { PPP_HELLO,      "HELLO" },
84         { PPP_LUXCOM,     "LUXCOM" },
85         { PPP_SNS,        "SNS" },
86         { PPP_IPCP,       "IPCP" },
87         { PPP_OSICP,      "OSICP" },
88         { PPP_NSCP,       "NSCP" },
89         { PPP_DECNETCP,   "DECNETCP" },
90         { PPP_APPLECP,    "APPLECP" },
91         { PPP_IPXCP,      "IPXCP" },
92         { PPP_STIICP,     "STIICP" },
93         { PPP_VINESCP,    "VINESCP" },
94         { PPP_MPLSCP,     "MPLSCP" },
95
96         { PPP_LCP,        "LCP" },
97         { PPP_PAP,        "PAP" },
98         { PPP_LQM,        "LQM" },
99         { PPP_CHAP,       "CHAP" },
100         { PPP_BACP,       "BACP" },
101         { PPP_BAP,        "BAP" },
102         { PPP_MP,         "ML" },
103         { 0,              NULL }
104 };
105
106 /* Control Protocols (LCP/IPCP/CCP etc.) Codes defined in RFC 1661 */
107
108 #define CPCODES_VEXT            0       /* Vendor-Specific (RFC2153) */
109 #define CPCODES_CONF_REQ        1       /* Configure-Request */
110 #define CPCODES_CONF_ACK        2       /* Configure-Ack */
111 #define CPCODES_CONF_NAK        3       /* Configure-Nak */
112 #define CPCODES_CONF_REJ        4       /* Configure-Reject */
113 #define CPCODES_TERM_REQ        5       /* Terminate-Request */
114 #define CPCODES_TERM_ACK        6       /* Terminate-Ack */
115 #define CPCODES_CODE_REJ        7       /* Code-Reject */
116 #define CPCODES_PROT_REJ        8       /* Protocol-Reject (LCP only) */
117 #define CPCODES_ECHO_REQ        9       /* Echo-Request (LCP only) */
118 #define CPCODES_ECHO_RPL        10      /* Echo-Reply (LCP only) */
119 #define CPCODES_DISC_REQ        11      /* Discard-Request (LCP only) */
120 #define CPCODES_ID              12      /* Identification (LCP only) RFC1570 */
121 #define CPCODES_TIME_REM        13      /* Time-Remaining (LCP only) RFC1570 */
122 #define CPCODES_RESET_REQ       14      /* Reset-Request (CCP only) RFC1962 */
123 #define CPCODES_RESET_REP       15      /* Reset-Reply (CCP only) */
124
125 struct tok cpcodes[] = {
126         {CPCODES_VEXT,      "Vendor-Extension"}, /* RFC2153 */
127         {CPCODES_CONF_REQ,  "Conf-Request"},
128         {CPCODES_CONF_ACK,  "Conf-Ack"},
129         {CPCODES_CONF_NAK,  "Conf-Nack"},
130         {CPCODES_CONF_REJ,  "Conf-Reject"},
131         {CPCODES_TERM_REQ,  "Term-Request"},
132         {CPCODES_TERM_ACK,  "Term-Ack"},
133         {CPCODES_CODE_REJ,  "Code-Reject"},
134         {CPCODES_PROT_REJ,  "Prot-Reject"},
135         {CPCODES_ECHO_REQ,  "Echo-Request"},
136         {CPCODES_ECHO_RPL,  "Echo-Reply"},
137         {CPCODES_DISC_REQ,  "Disc-Req"},
138         {CPCODES_ID,        "Ident"},            /* RFC1570 */
139         {CPCODES_TIME_REM,  "Time-Rem"},         /* RFC1570 */
140         {CPCODES_RESET_REQ, "Reset-Req"},        /* RFC1962 */
141         {CPCODES_RESET_REP, "Reset-Ack"},        /* RFC1962 */
142         {0,                 NULL}
143 };
144
145 /* LCP Config Options */
146
147 #define LCPOPT_VEXT     0
148 #define LCPOPT_MRU      1
149 #define LCPOPT_ACCM     2
150 #define LCPOPT_AP       3
151 #define LCPOPT_QP       4
152 #define LCPOPT_MN       5
153 #define LCPOPT_DEP6     6
154 #define LCPOPT_PFC      7
155 #define LCPOPT_ACFC     8
156 #define LCPOPT_FCSALT   9
157 #define LCPOPT_SDP      10
158 #define LCPOPT_NUMMODE  11
159 #define LCPOPT_DEP12    12
160 #define LCPOPT_CBACK    13
161 #define LCPOPT_DEP14    14
162 #define LCPOPT_DEP15    15
163 #define LCPOPT_DEP16    16
164 #define LCPOPT_MLMRRU   17
165 #define LCPOPT_MLSSNHF  18
166 #define LCPOPT_MLED     19
167 #define LCPOPT_PROP     20
168 #define LCPOPT_DCEID    21
169 #define LCPOPT_MPP      22
170 #define LCPOPT_LD       23
171 #define LCPOPT_LCPAOPT  24
172 #define LCPOPT_COBS     25
173 #define LCPOPT_PE       26
174 #define LCPOPT_MLHF     27
175 #define LCPOPT_I18N     28
176 #define LCPOPT_SDLOS    29
177 #define LCPOPT_PPPMUX   30
178
179 #define LCPOPT_MIN LCPOPT_VEXT
180 #define LCPOPT_MAX LCPOPT_PPPMUX
181
182 static const char *lcpconfopts[] = {
183         "Vend-Ext",             /* (0) */
184         "MRU",                  /* (1) */
185         "ACCM",                 /* (2) */
186         "Auth-Prot",            /* (3) */
187         "Qual-Prot",            /* (4) */
188         "Magic-Num",            /* (5) */
189         "deprecated(6)",        /* used to be a Quality Protocol */
190         "PFC",                  /* (7) */
191         "ACFC",                 /* (8) */
192         "FCS-Alt",              /* (9) */
193         "SDP",                  /* (10) */
194         "Num-Mode",             /* (11) */
195         "deprecated(12)",       /* used to be a Multi-Link-Procedure*/
196         "Call-Back",            /* (13) */
197         "deprecated(14)",       /* used to be a Connect-Time */
198         "deprecated(15)",       /* used to be a Compund-Frames */
199         "deprecated(16)",       /* used to be a Nominal-Data-Encap */
200         "MRRU",                 /* (17) */
201         "SSNHF",                /* (18) */
202         "End-Disc",             /* (19) */
203         "Proprietary",          /* (20) */
204         "DCE-Id",               /* (21) */
205         "MP+",                  /* (22) */
206         "Link-Disc",            /* (23) */
207         "LCP-Auth-Opt",         /* (24) */
208         "COBS",                 /* (25) */
209         "Prefix-elision",       /* (26) */
210         "Multilink-header-Form",/* (27) */
211         "I18N",                 /* (28) */
212         "SDL-over-SONET/SDH",   /* (29) */
213         "PPP-Muxing",           /* (30) */
214 };
215
216 /* IPV6CP - to be supported */
217 /* ECP - to be supported */
218
219 /* CCP Config Options */
220
221 #define CCPOPT_OUI      0       /* RFC1962 */
222 #define CCPOPT_PRED1    1       /* RFC1962 */
223 #define CCPOPT_PRED2    2       /* RFC1962 */
224 #define CCPOPT_PJUMP    3       /* RFC1962 */
225 /* 4-15 unassigned */
226 #define CCPOPT_HPPPC    16      /* RFC1962 */
227 #define CCPOPT_STACLZS  17      /* RFC1974 */
228 #define CCPOPT_MPPC     18      /* RFC2118 */
229 #define CCPOPT_GFZA     19      /* RFC1962 */
230 #define CCPOPT_V42BIS   20      /* RFC1962 */
231 #define CCPOPT_BSDCOMP  21      /* RFC1977 */
232 /* 22 unassigned */
233 #define CCPOPT_LZSDCP   23      /* RFC1967 */
234 #define CCPOPT_MVRCA    24      /* RFC1975 */
235 #define CCPOPT_DEC      25      /* RFC1976 */
236 #define CCPOPT_DEFLATE  26      /* RFC1979 */
237 /* 27-254 unassigned */
238 #define CCPOPT_RESV     255     /* RFC1962 */
239
240 #define CCPOPT_MIN CCPOPT_OUI
241 #define CCPOPT_MAX CCPOPT_DEFLATE    /* XXX: should be CCPOPT_RESV but... */
242
243 static const char *ccpconfopts[] = {
244         "OUI",                  /* (0) */
245         "Pred-1",               /* (1) */
246         "Pred-2",               /* (2) */
247         "Puddle",               /* (3) */
248         "unassigned(4)",        /* (4) */
249         "unassigned(5)",        /* (5) */
250         "unassigned(6)",        /* (6) */
251         "unassigned(7)",        /* (7) */
252         "unassigned(8)",        /* (8) */
253         "unassigned(9)",        /* (9) */
254         "unassigned(10)",       /* (10) */
255         "unassigned(11)",       /* (11) */
256         "unassigned(12)",       /* (12) */
257         "unassigned(13)",       /* (13) */
258         "unassigned(14)",       /* (14) */
259         "unassigned(15)",       /* (15) */
260         "HP-PPC",               /* (16) */
261         "Stac-LZS",             /* (17) */
262         "MPPC",                 /* (18) */
263         "Gand-FZA",             /* (19) */
264         "V.42bis",              /* (20) */
265         "BSD-Comp",             /* (21) */
266         "unassigned(22)",       /* (22) */
267         "LZS-DCP",              /* (23) */
268         "MVRCA",                /* (24) */
269         "DEC",                  /* (25) */
270         "Deflate",              /* (26) */
271 };
272
273 /* BACP Config Options */
274
275 #define BACPOPT_FPEER   1       /* RFC2125 */
276
277 /* SDCP - to be supported */
278
279 /* IPCP Config Options */
280
281 #define IPCPOPT_2ADDR   1       /* RFC1172, RFC1332 (deprecated) */
282 #define IPCPOPT_IPCOMP  2       /* RFC1332 */
283 #define IPCPOPT_ADDR    3       /* RFC1332 */
284 #define IPCPOPT_MOBILE4 4       /* RFC2290 */
285
286 #define IPCPOPT_PRIDNS  129     /* RFC1877 */
287 #define IPCPOPT_PRINBNS 130     /* RFC1877 */
288 #define IPCPOPT_SECDNS  131     /* RFC1877 */
289 #define IPCPOPT_SECNBNS 132     /* RFC1877 */
290
291 /* ATCP - to be supported */
292 /* OSINLCP - to be supported */
293 /* BVCP - to be supported */
294 /* BCP - to be supported */
295 /* IPXCP - to be supported */
296 /* MPLSCP - to be supported */
297
298 /* Auth Algorithms */
299
300 /* 0-4 Reserved (RFC1994) */
301 #define AUTHALG_CHAPMD5 5       /* RFC1994 */
302 #define AUTHALG_MSCHAP1 128     /* RFC2433 */
303 #define AUTHALG_MSCHAP2 129     /* RFC2795 */
304
305 /* FCS Alternatives - to be supported */
306
307 /* Multilink Endpoint Discriminator (RFC1717) */
308 #define MEDCLASS_NULL   0       /* Null Class */
309 #define MEDCLASS_LOCAL  1       /* Locally Assigned */
310 #define MEDCLASS_IPV4   2       /* Internet Protocol (IPv4) */
311 #define MEDCLASS_MAC    3       /* IEEE 802.1 global MAC address */
312 #define MEDCLASS_MNB    4       /* PPP Magic Number Block */
313 #define MEDCLASS_PSNDN  5       /* Public Switched Network Director Number */
314
315 /* PPP LCP Callback */
316 #define CALLBACK_AUTH   0       /* Location determined by user auth */
317 #define CALLBACK_DSTR   1       /* Dialing string */
318 #define CALLBACK_LID    2       /* Location identifier */
319 #define CALLBACK_E164   3       /* E.164 number */
320 #define CALLBACK_X500   4       /* X.500 distinguished name */
321 #define CALLBACK_CBCP   6       /* Location is determined during CBCP nego */
322
323 /* CHAP */
324
325 #define CHAP_CHAL       1
326 #define CHAP_RESP       2
327 #define CHAP_SUCC       3
328 #define CHAP_FAIL       4
329
330 #define CHAP_CODEMIN CHAP_CHAL
331 #define CHAP_CODEMAX CHAP_FAIL
332
333 static const char *chapcode[] = {
334         "Chal",         /* (1) */
335         "Resp",         /* (2) */
336         "Succ",         /* (3) */
337         "Fail",         /* (4) */
338 };
339
340 /* PAP */
341
342 #define PAP_AREQ        1
343 #define PAP_AACK        2
344 #define PAP_ANAK        3
345
346 #define PAP_CODEMIN     PAP_AREQ
347 #define PAP_CODEMAX     PAP_ANAK
348
349 static const char *papcode[] = {
350         "Auth-Req",     /* (1) */
351         "Auth-Ack",     /* (2) */
352         "Auth-Nak",     /* (3) */
353 };
354
355 /* BAP */
356 #define BAP_CALLREQ     1
357 #define BAP_CALLRES     2
358 #define BAP_CBREQ       3
359 #define BAP_CBRES       4
360 #define BAP_LDQREQ      5
361 #define BAP_LDQRES      6
362 #define BAP_CSIND       7
363 #define BAP_CSRES       8
364
365 static void handle_ctrl_proto (u_int proto,const u_char *p, int length);
366 static void handle_chap (const u_char *p, int length);
367 static void handle_pap (const u_char *p, int length);
368 static void handle_bap (const u_char *p, int length);
369 static int print_lcp_config_options (const u_char *p, int);
370 static int print_ipcp_config_options (const u_char *p, int);
371 static int print_ccp_config_options (const u_char *p, int);
372 static int print_bacp_config_options (const u_char *p, int);
373 static void handle_ppp (u_int proto, const u_char *p, int length);
374
375 /* generic Control Protocol (e.g. LCP, IPCP, CCP, etc.) handler */
376 static void
377 handle_ctrl_proto(u_int proto, const u_char *pptr, int length)
378 {
379         const char *typestr;
380         u_int code, len;
381         int (*pfunc)(const u_char *, int);
382         int x, j;
383         const u_char *tptr;
384
385         tptr=pptr;
386
387         typestr = tok2str(ppptype2str, "unknown", proto);
388         printf("%s, ",typestr);
389
390         if (length < 4) /* FIXME weak boundary checking */
391                 goto trunc;
392         TCHECK2(*tptr, 2);
393
394         code = *tptr++;
395         
396         printf("%s (0x%02x), id %u",
397                tok2str(cpcodes, "Unknown Opcode",code),
398                code,
399                *tptr++); /* ID */
400
401         TCHECK2(*tptr, 2);
402         len = EXTRACT_16BITS(tptr);
403         tptr += 2;
404
405         if (length <= 4)
406                 return;         /* there may be a NULL confreq etc. */
407
408         switch (code) {
409         case CPCODES_VEXT:
410                 if (length < 11)
411                         break;
412                 TCHECK2(*tptr, 4);
413                 printf(", Magic-Num 0x%08x", EXTRACT_32BITS(tptr));
414                 tptr += 4;
415                 TCHECK2(*tptr, 3);
416                 printf(" OUI 0x%06x", EXTRACT_24BITS(tptr));
417                 /* XXX: need to decode Kind and Value(s)? */
418                 break;
419         case CPCODES_CONF_REQ:
420         case CPCODES_CONF_ACK:
421         case CPCODES_CONF_NAK:
422         case CPCODES_CONF_REJ:
423                 x = len - 4;    /* Code(1), Identifier(1) and Length(2) */
424                 do {
425                         switch (proto) {
426                         case PPP_LCP:
427                                 pfunc = print_lcp_config_options;
428                                 break;
429                         case PPP_IPCP:
430                                 pfunc = print_ipcp_config_options;
431                                 break;
432                         case PPP_CCP:
433                                 pfunc = print_ccp_config_options;
434                                 break;
435                         case PPP_BACP:
436                                 pfunc = print_bacp_config_options;
437                                 break;
438                         default:
439                                 /*
440                                  * This should never happen, but we set
441                                  * "pfunc" to squelch uninitialized
442                                  * variable warnings from compilers.
443                                  */
444                                 pfunc = NULL;
445                                 break;
446                         }
447                         if ((j = (*pfunc)(tptr, len)) == 0)
448                                 break;
449                         x -= j;
450                         tptr += j;
451                 } while (x > 0);
452                 break;
453
454         case CPCODES_TERM_REQ:
455         case CPCODES_TERM_ACK:
456                 /* XXX: need to decode Data? */
457                 break;
458         case CPCODES_CODE_REJ:
459                 /* XXX: need to decode Rejected-Packet? */
460                 break;
461         case CPCODES_PROT_REJ:
462                 if (length < 6)
463                         break;
464                 TCHECK2(*tptr, 2);
465                 printf(", Rejected %s Protocol (0x%04x)",
466                        tok2str(ppptype2str,"unknown", EXTRACT_16BITS(tptr)),
467                        EXTRACT_16BITS(tptr));
468                 /* XXX: need to decode Rejected-Information? */
469                 break;
470         case CPCODES_ECHO_REQ:
471         case CPCODES_ECHO_RPL:
472         case CPCODES_DISC_REQ:
473         case CPCODES_ID:
474                 if (length < 8)
475                         break;
476                 TCHECK2(*tptr, 4);
477                 printf(", Magic-Num 0x%08x", EXTRACT_32BITS(tptr));
478                 /* XXX: need to decode Data? */
479                 break;
480         case CPCODES_TIME_REM:
481                 if (length < 12)
482                         break;
483                 TCHECK2(*tptr, 4);
484                 printf(", Magic-Num 0x%08x", EXTRACT_32BITS(tptr));
485                 TCHECK2(*(tptr + 4), 4);
486                 printf(", Seconds-Remaining %us", EXTRACT_32BITS(tptr + 4));
487                 /* XXX: need to decode Message? */
488                 break;
489         default:
490             /* XXX this is dirty but we do not get the
491              * original pointer passed to the begin
492              * the PPP packet */
493                 if (vflag <= 1)
494                     print_unknown_data(pptr-2,"\n\t",length+2);
495                 break;
496         }
497         printf(", length %u", length);
498
499         if (vflag >1)
500             print_unknown_data(pptr-2,"\n\t",length+2);
501         return;
502
503 trunc:
504         printf("[|%s]", typestr);
505 }
506
507 /* LCP config options */
508 static int
509 print_lcp_config_options(const u_char *p, int length)
510 {
511         int len, opt;
512
513         if (length < 2)
514                 return 0;
515         TCHECK2(*p, 2);
516         len = p[1];
517         opt = p[0];
518         if (length < len)
519                 return 0;
520         if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX))
521                 printf(", %s ", lcpconfopts[opt]);
522         else {
523                 printf(", unknown LCP option 0x%02x", opt);
524                 return len;
525         }
526
527         switch (opt) {
528         case LCPOPT_VEXT:
529                 if (len >= 6) {
530                         TCHECK2(*(p + 2), 3);
531                         printf(" OUI 0x%06x", EXTRACT_24BITS(p+2));
532 #if 0
533                         TCHECK(p[5]);
534                         printf(" kind 0x%02x", p[5]);
535                         printf(" val 0x")
536                         for (i = 0; i < len - 6; i++) {
537                                 TCHECK(p[6 + i]);
538                                 printf("%02x", p[6 + i]);
539                         }
540 #endif
541                 }
542                 break;
543         case LCPOPT_MRU:
544                 if (len == 4) {
545                         TCHECK2(*(p + 2), 2);
546                         printf(" %u", EXTRACT_16BITS(p + 2));
547                 }
548                 break;
549         case LCPOPT_ACCM:
550                 if (len == 6) {
551                         TCHECK2(*(p + 2), 4);
552                         printf(" %08x", EXTRACT_32BITS(p + 2));
553                 }
554                 break;
555         case LCPOPT_AP:
556                 if (len >= 4) {
557                     TCHECK2(*(p + 2), 2);
558                     switch (EXTRACT_16BITS(p+2)) {
559                     case PPP_PAP:
560                         printf(" PAP");
561                         break;
562                     case PPP_CHAP:
563                         printf(" CHAP");
564                         TCHECK(p[4]);
565                         switch (p[4]) {
566                         default:
567                             printf(", unknown-algorithm-%u", p[4]);
568                             break;
569                         case AUTHALG_CHAPMD5:
570                             printf(", MD5");
571                             break;
572                         case AUTHALG_MSCHAP1:
573                             printf(", MSCHAPv1");
574                             break;
575                         case AUTHALG_MSCHAP2:
576                             printf(", MSCHAPv2");
577                             break;
578                         }
579                         break;
580                     case PPP_EAP:
581                         printf(" EAP");
582                         break;
583                     case PPP_SPAP:
584                         printf(" SPAP");
585                         break;
586                     case PPP_SPAP_OLD:
587                         printf(" Old-SPAP");
588                         break;
589                     default:
590                       printf("unknown");
591                     }
592                 }
593                 break;
594         case LCPOPT_QP:
595                 if (len >= 4) {
596                         TCHECK2(*(p + 2), 2);
597                         if (EXTRACT_16BITS(p+2) == PPP_LQM)
598                                 printf(" LQR");
599                         else
600                                 printf(" unknown");
601                 }
602                 break;
603         case LCPOPT_MN:
604                 if (len == 6) {
605                         TCHECK2(*(p + 2), 4);
606                         printf(" 0x%08x", EXTRACT_32BITS(p + 2));
607                 }
608                 break;
609         case LCPOPT_PFC:
610                 break;
611         case LCPOPT_ACFC:
612                 break;
613         case LCPOPT_LD:
614                 if (len == 4) {
615                         TCHECK2(*(p + 2), 2);
616                         printf(" 0x%04x", EXTRACT_16BITS(p + 2));
617                 }
618                 break;
619         case LCPOPT_CBACK:
620                 if (len < 3)
621                         break;
622                 TCHECK(p[2]);
623                 switch (p[2]) {         /* Operation */
624                 case CALLBACK_AUTH:
625                         printf(" UserAuth");
626                         break;
627                 case CALLBACK_DSTR:
628                         printf(" DialString");
629                         break;
630                 case CALLBACK_LID:
631                         printf(" LocalID");
632                         break;
633                 case CALLBACK_E164:
634                         printf(" E.164");
635                         break;
636                 case CALLBACK_X500:
637                         printf(" X.500");
638                         break;
639                 case CALLBACK_CBCP:
640                         printf(" CBCP");
641                         break;
642                 default:
643                         printf(" unknown-operation=%u", p[2]);
644                         break;
645                 }
646                 break;
647         case LCPOPT_MLMRRU:
648                 if (len == 4) {
649                         TCHECK2(*(p + 2), 2);
650                         printf(" %u", EXTRACT_16BITS(p + 2));
651                 }
652                 break;
653         case LCPOPT_MLED:
654                 if (len < 3)
655                         break;
656                 TCHECK(p[2]);
657                 switch (p[2]) {         /* class */
658                 case MEDCLASS_NULL:
659                         printf(" Null");
660                         break;
661                 case MEDCLASS_LOCAL:
662                         printf(" Local"); /* XXX */
663                         break;
664                 case MEDCLASS_IPV4:
665                         if (len != 7)
666                                 break;
667                         TCHECK2(*(p + 3), 4);
668                         printf(" IPv4 %s", ipaddr_string(p + 3));
669                         break;
670                 case MEDCLASS_MAC:
671                         if (len != 9)
672                                 break;
673                         TCHECK(p[8]);
674                         printf(" MAC %02x:%02x:%02x:%02x:%02x:%02x",
675                                p[3], p[4], p[5], p[6], p[7], p[8]);
676                         break;
677                 case MEDCLASS_MNB:
678                         printf(" Magic-Num-Block"); /* XXX */
679                         break;
680                 case MEDCLASS_PSNDN:
681                         printf(" PSNDN"); /* XXX */
682                         break;
683                 }
684                 break;
685
686 /* XXX: to be supported */
687 #if 0
688         case LCPOPT_DEP6:
689         case LCPOPT_FCSALT:
690         case LCPOPT_SDP:
691         case LCPOPT_NUMMODE:
692         case LCPOPT_DEP12:
693         case LCPOPT_DEP14:
694         case LCPOPT_DEP15:
695         case LCPOPT_DEP16:
696         case LCPOPT_MLSSNHF:
697         case LCPOPT_PROP:
698         case LCPOPT_DCEID:
699         case LCPOPT_MPP:
700         case LCPOPT_LCPAOPT:
701         case LCPOPT_COBS:
702         case LCPOPT_PE:
703         case LCPOPT_MLHF:
704         case LCPOPT_I18N:
705         case LCPOPT_SDLOS:
706         case LCPOPT_PPPMUX:
707                 break;
708 #endif
709         }
710         return len;
711
712 trunc:
713         printf("[|lcp]");
714         return 0;
715 }
716
717 /* CHAP */
718 static void
719 handle_chap(const u_char *p, int length)
720 {
721         u_int code, len;
722         int val_size, name_size, msg_size;
723         const u_char *p0;
724         int i;
725
726         p0 = p;
727         if (length < 1) {
728                 printf("[|chap]");
729                 return;
730         } else if (length < 4) {
731                 TCHECK(*p);
732                 printf("[|chap 0x%02x]", *p);
733                 return;
734         }
735
736         TCHECK(*p);
737         code = *p;
738         if ((code >= CHAP_CODEMIN) && (code <= CHAP_CODEMAX))
739                 printf("%s", chapcode[code - 1]);
740         else {
741                 printf("0x%02x", code);
742                 return;
743         }
744         p++;
745
746         TCHECK(*p);
747         printf("(%u)", *p);             /* ID */
748         p++;
749
750         TCHECK2(*p, 2);
751         len = EXTRACT_16BITS(p);
752         p += 2;
753
754         /*
755          * Note that this is a generic CHAP decoding routine. Since we
756          * don't know which flavor of CHAP (i.e. CHAP-MD5, MS-CHAPv1,
757          * MS-CHAPv2) is used at this point, we can't decode packet
758          * specifically to each algorithms. Instead, we simply decode
759          * the GCD (Gratest Common Denominator) for all algorithms.
760          */
761         switch (code) {
762         case CHAP_CHAL:
763         case CHAP_RESP:
764                 if (length - (p - p0) < 1)
765                         return;
766                 TCHECK(*p);
767                 val_size = *p;          /* value size */
768                 p++;
769                 if (length - (p - p0) < val_size)
770                         return;
771                 printf(", Value ");
772                 for (i = 0; i < val_size; i++) {
773                         TCHECK(*p);
774                         printf("%02x", *p++);
775                 }
776                 name_size = len - (p - p0);
777                 printf(", Name ");
778                 for (i = 0; i < name_size; i++) {
779                         TCHECK(*p);
780                         safeputchar(*p++);
781                 }
782                 break;
783         case CHAP_SUCC:
784         case CHAP_FAIL:
785                 msg_size = len - (p - p0);
786                 printf(", Msg ");
787                 for (i = 0; i< msg_size; i++) {
788                         TCHECK(*p);
789                         safeputchar(*p++);
790                 }
791                 break;
792         }
793         return;
794
795 trunc:
796         printf("[|chap]");
797 }
798
799 /* PAP (see RFC 1334) */
800 static void
801 handle_pap(const u_char *p, int length)
802 {
803         u_int code, len;
804         int peerid_len, passwd_len, msg_len;
805         const u_char *p0;
806         int i;
807
808         p0 = p;
809         if (length < 1) {
810                 printf("[|pap]");
811                 return;
812         } else if (length < 4) {
813                 TCHECK(*p);
814                 printf("[|pap 0x%02x]", *p);
815                 return;
816         }
817
818         TCHECK(*p);
819         code = *p;
820         if ((code >= PAP_CODEMIN) && (code <= PAP_CODEMAX))
821                 printf("%s", papcode[code - 1]);
822         else {
823                 printf("0x%02x", code);
824                 return;
825         }
826         p++;
827
828         TCHECK(*p);
829         printf("(%u)", *p);             /* ID */
830         p++;
831
832         TCHECK2(*p, 2);
833         len = EXTRACT_16BITS(p);
834         p += 2;
835
836         switch (code) {
837         case PAP_AREQ:
838                 if (length - (p - p0) < 1)
839                         return;
840                 TCHECK(*p);
841                 peerid_len = *p;        /* Peer-ID Length */
842                 p++;
843                 if (length - (p - p0) < peerid_len)
844                         return;
845                 printf(", Peer ");
846                 for (i = 0; i < peerid_len; i++) {
847                         TCHECK(*p);
848                         safeputchar(*p++);
849                 }
850
851                 if (length - (p - p0) < 1)
852                         return;
853                 TCHECK(*p);
854                 passwd_len = *p;        /* Password Length */
855                 p++;
856                 if (length - (p - p0) < passwd_len)
857                         return;
858                 printf(", Name ");
859                 for (i = 0; i < passwd_len; i++) {
860                         TCHECK(*p);
861                         safeputchar(*p++);
862                 }
863                 break;
864         case PAP_AACK:
865         case PAP_ANAK:
866                 if (length - (p - p0) < 1)
867                         return;
868                 TCHECK(*p);
869                 msg_len = *p;           /* Msg-Length */
870                 p++;
871                 if (length - (p - p0) < msg_len)
872                         return;
873                 printf(", Msg ");
874                 for (i = 0; i< msg_len; i++) {
875                         TCHECK(*p);
876                         safeputchar(*p++);
877                 }
878                 break;
879         }
880         return;
881
882 trunc:
883         printf("[|pap]");
884 }
885
886 /* BAP */
887 static void
888 handle_bap(const u_char *p _U_, int length _U_)
889 {
890         /* XXX: to be supported!! */
891 }
892
893
894 /* IPCP config options */
895 static int
896 print_ipcp_config_options(const u_char *p, int length)
897 {
898         int len, opt;
899
900         if (length < 2)
901                 return 0;
902         TCHECK2(*p, 2);
903         len = p[1];
904         opt = p[0];
905         if (length < len)
906                 return 0;
907         switch (opt) {
908         case IPCPOPT_2ADDR:             /* deprecated */
909                 if (len != 10)
910                         goto invlen;
911                 TCHECK2(*(p + 6), 4);
912                 printf(", IP-Addrs src %s, dst %s",
913                        ipaddr_string(p + 2),
914                        ipaddr_string(p + 6));
915                 break;
916         case IPCPOPT_IPCOMP:
917                 if (len < 4)
918                         goto invlen;
919                 printf(", IP-Comp");
920                 TCHECK2(*(p + 2), 2);
921                 if (EXTRACT_16BITS(p + 2) == PPP_VJC) {
922                         printf(" VJ-Comp");
923                         /* XXX: VJ-Comp parameters should be decoded */
924                 } else
925                         printf(" unknown-comp-proto=%04x", EXTRACT_16BITS(p + 2));
926                 break;
927         case IPCPOPT_ADDR:
928                 if (len != 6)
929                         goto invlen;
930                 TCHECK2(*(p + 2), 4);
931                 printf(", IP-Addr %s", ipaddr_string(p + 2));
932                 break;
933         case IPCPOPT_MOBILE4:
934                 if (len != 6)
935                         goto invlen;
936                 TCHECK2(*(p + 2), 4);
937                 printf(", Home-Addr %s", ipaddr_string(p + 2));
938                 break;
939         case IPCPOPT_PRIDNS:
940                 if (len != 6)
941                         goto invlen;
942                 TCHECK2(*(p + 2), 4);
943                 printf(", Pri-DNS %s", ipaddr_string(p + 2));
944                 break;
945         case IPCPOPT_PRINBNS:
946                 if (len != 6)
947                         goto invlen;
948                 TCHECK2(*(p + 2), 4);
949                 printf(", Pri-NBNS %s", ipaddr_string(p + 2));
950                 break;
951         case IPCPOPT_SECDNS:
952                 if (len != 6)
953                         goto invlen;
954                 TCHECK2(*(p + 2), 4);
955                 printf(", Sec-DNS %s", ipaddr_string(p + 2));
956                 break;
957         case IPCPOPT_SECNBNS:
958                 if (len != 6)
959                         goto invlen;
960                 TCHECK2(*(p + 2), 4);
961                 printf(", Sec-NBNS %s", ipaddr_string(p + 2));
962                 break;
963         default:
964                 printf(", unknown-%d", opt);
965                 break;
966         }
967         return len;
968
969 invlen:
970         printf(", invalid-length-%d", opt);
971         return 0;
972
973 trunc:
974         printf("[|ipcp]");
975         return 0;
976 }
977
978 /* CCP config options */
979 static int
980 print_ccp_config_options(const u_char *p, int length)
981 {
982         int len, opt;
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 ((opt >= CCPOPT_MIN) && (opt <= CCPOPT_MAX))
992                 printf(", %s", ccpconfopts[opt]);
993 #if 0   /* XXX */
994         switch (opt) {
995         case CCPOPT_OUI:
996         case CCPOPT_PRED1:
997         case CCPOPT_PRED2:
998         case CCPOPT_PJUMP:
999         case CCPOPT_HPPPC:
1000         case CCPOPT_STACLZS:
1001         case CCPOPT_MPPC:
1002         case CCPOPT_GFZA:
1003         case CCPOPT_V42BIS:
1004         case CCPOPT_BSDCOMP:
1005         case CCPOPT_LZSDCP:
1006         case CCPOPT_MVRCA:
1007         case CCPOPT_DEC:
1008         case CCPOPT_DEFLATE:
1009         case CCPOPT_RESV:
1010                 break;
1011
1012         default:
1013                 printf(", unknown-%d", opt);
1014                 break;
1015         }
1016 #endif
1017         return len;
1018
1019 trunc:
1020         printf("[|ccp]");
1021         return 0;
1022 }
1023
1024 /* BACP config options */
1025 static int
1026 print_bacp_config_options(const u_char *p, int length)
1027 {
1028         int len, opt;
1029
1030         if (length < 2)
1031                 return 0;
1032         TCHECK2(*p, 2);
1033         len = p[1];
1034         opt = p[0];
1035         if (length < len)
1036                 return 0;
1037         if (opt == BACPOPT_FPEER) {
1038                 TCHECK2(*(p + 2), 4);
1039                 printf(", Favored-Peer");
1040                 printf(", Magic-Num 0x%08x", EXTRACT_32BITS(p + 2));
1041         } else {
1042                 printf(", unknown-option-%d", opt);
1043         }
1044         return len;
1045
1046 trunc:
1047         printf("[|bacp]");
1048         return 0;
1049 }
1050
1051
1052 /* PPP */
1053 static void
1054 handle_ppp(u_int proto, const u_char *p, int length)
1055 {
1056         switch (proto) {
1057         case PPP_LCP:
1058         case PPP_IPCP:
1059         case PPP_OSICP:
1060         case PPP_MPLSCP:
1061         case PPP_IPV6CP:
1062         case PPP_CCP:
1063         case PPP_BACP:
1064                 handle_ctrl_proto(proto, p, length);
1065                 break;
1066         case PPP_CHAP:
1067                 handle_chap(p, length);
1068                 break;
1069         case PPP_PAP:
1070                 handle_pap(p, length);
1071                 break;
1072         case PPP_BAP:           /* XXX: not yet completed */
1073                 handle_bap(p, length);
1074                 break;
1075         case ETHERTYPE_IP:      /*XXX*/
1076         case PPP_IP:
1077                 ip_print(p, length);
1078                 break;
1079 #ifdef INET6
1080         case ETHERTYPE_IPV6:    /*XXX*/
1081         case PPP_IPV6:
1082                 ip6_print(p, length);
1083                 break;
1084 #endif
1085         case ETHERTYPE_IPX:     /*XXX*/
1086         case PPP_IPX:
1087                 ipx_print(p, length);
1088                 break;
1089         case PPP_OSI:
1090                 isoclns_print(p, length, length);
1091                 break;
1092         case PPP_MPLS_UCAST:
1093         case PPP_MPLS_MCAST:
1094                 mpls_print(p, length);
1095                 break;
1096         default:
1097                 printf("unknown PPP protocol (0x%04x)", proto);
1098                 print_unknown_data(p,"\n\t",length);
1099                 break;
1100         }
1101 }
1102
1103 /* Standard PPP printer */
1104 u_int
1105 ppp_print(register const u_char *p, u_int length)
1106 {
1107         u_int proto;
1108         u_int olen = length; /* _o_riginal length */
1109         u_int hdr_len = 0;
1110
1111         /*
1112          * Here, we assume that p points to the Address and Control
1113          * field (if they present).
1114          */
1115         if (length < 2)
1116                 goto trunc;
1117         TCHECK2(*p, 2);
1118         if (*p == PPP_ADDRESS && *(p + 1) == PPP_CONTROL) {
1119                 p += 2;                 /* ACFC not used */
1120                 length -= 2;
1121                 hdr_len += 2;
1122         }
1123
1124         if (length < 2)
1125                 goto trunc;
1126         TCHECK(*p);
1127         if (*p % 2) {
1128                 proto = *p;             /* PFC is used */
1129                 p++;
1130                 length--;
1131                 hdr_len++;
1132         } else {
1133                 TCHECK2(*p, 2);
1134                 proto = EXTRACT_16BITS(p);
1135                 p += 2;
1136                 length -= 2;
1137                 hdr_len += 2;
1138         }
1139
1140         if (eflag)
1141             printf("PPP-%s (0x%04x), length %u: ",
1142                    tok2str(ppptype2str, "unknown", proto),
1143                    proto,
1144                    olen);
1145
1146         handle_ppp(proto, p, length);
1147         return (hdr_len);
1148 trunc:
1149         printf("[|ppp]");
1150         return (0);
1151 }
1152
1153
1154 /* PPP I/F printer */
1155 u_int
1156 ppp_if_print(const struct pcap_pkthdr *h, register const u_char *p)
1157 {
1158         register u_int length = h->len;
1159         register u_int caplen = h->caplen;
1160
1161         if (caplen < PPP_HDRLEN) {
1162                 printf("[|ppp]");
1163                 return (caplen);
1164         }
1165
1166 #if 0
1167         /*
1168          * XXX: seems to assume that there are 2 octets prepended to an
1169          * actual PPP frame. The 1st octet looks like Input/Output flag
1170          * while 2nd octet is unknown, at least to me
1171          * (mshindo@mshindo.net).
1172          *
1173          * That was what the original tcpdump code did.
1174          *
1175          * FreeBSD's "if_ppp.c" *does* set the first octet to 1 for outbound
1176          * packets and 0 for inbound packets - but only if the
1177          * protocol field has the 0x8000 bit set (i.e., it's a network
1178          * control protocol); it does so before running the packet through
1179          * "bpf_filter" to see if it should be discarded, and to see
1180          * if we should update the time we sent the most recent packet...
1181          *
1182          * ...but it puts the original address field back after doing
1183          * so.
1184          *
1185          * NetBSD's "if_ppp.c" doesn't set the first octet in that fashion.
1186          *
1187          * I don't know if any PPP implementation handed up to a BPF
1188          * device packets with the first octet being 1 for outbound and
1189          * 0 for inbound packets, so I (guy@alum.mit.edu) don't know
1190          * whether that ever needs to be checked or not.
1191          *
1192          * Note that NetBSD has a DLT_PPP_SERIAL, which it uses for PPP,
1193          * and its tcpdump appears to assume that the frame always
1194          * begins with an address field and a control field, and that
1195          * the address field might be 0x0f or 0x8f, for Cisco
1196          * point-to-point with HDLC framing as per section 4.3.1 of RFC
1197          * 1547, as well as 0xff, for PPP in HDLC-like framing as per
1198          * RFC 1662.
1199          *
1200          * (Is the Cisco framing in question what DLT_C_HDLC, in
1201          * BSD/OS, is?)
1202          */
1203         if (eflag)
1204                 printf("%c %4d %02x ", p[0] ? 'O' : 'I', length, p[1]);
1205 #endif
1206
1207         ppp_print(p, length);
1208
1209         return (0);
1210 }
1211
1212 /*
1213  * PPP I/F printer to use if we know that RFC 1662-style PPP in HDLC-like
1214  * framing, or Cisco PPP with HDLC framing as per section 4.3.1 of RFC 1547,
1215  * is being used (i.e., we don't check for PPP_ADDRESS and PPP_CONTROL,
1216  * discard them *if* those are the first two octets, and parse the remaining
1217  * packet as a PPP packet, as "ppp_print()" does).
1218  *
1219  * This handles, for example, DLT_PPP_SERIAL in NetBSD.
1220  */
1221 u_int
1222 ppp_hdlc_if_print(const struct pcap_pkthdr *h, register const u_char *p)
1223 {
1224         register u_int length = h->len;
1225         register u_int caplen = h->caplen;
1226         u_int proto;
1227         u_int hdrlen = 0;
1228
1229         if (caplen < 2) {
1230                 printf("[|ppp]");
1231                 return (caplen);
1232         }
1233
1234         switch (p[0]) {
1235
1236         case PPP_ADDRESS:
1237                 if (caplen < 4) {
1238                         printf("[|ppp]");
1239                         return (caplen);
1240                 }
1241
1242                 if (eflag)
1243                         printf("%02x %02x %d ", p[0], p[1], length);
1244                 p += 2;
1245                 length -= 2;
1246                 hdrlen += 2;
1247
1248                 proto = EXTRACT_16BITS(p);
1249                 p += 2;
1250                 length -= 2;
1251                 hdrlen += 2;
1252                 printf("%s: ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto));
1253
1254                 handle_ppp(proto, p, length);
1255                 break;
1256
1257         case CHDLC_UNICAST:
1258         case CHDLC_BCAST:
1259                 return (chdlc_if_print(h, p));
1260
1261         default:
1262                 if (eflag)
1263                         printf("%02x %02x %d ", p[0], p[1], length);
1264                 p += 2;
1265                 length -= 2;
1266                 hdrlen += 2;
1267
1268                 /*
1269                  * XXX - NetBSD's "ppp_netbsd_serial_if_print()" treats
1270                  * the next two octets as an Ethernet type; does that
1271                  * ever happen?
1272                  */
1273                 printf("unknown addr %02x; ctrl %02x", p[0], p[1]);
1274                 break;
1275         }
1276
1277         return (hdrlen);
1278 }
1279
1280 #define PPP_BSDI_HDRLEN 24
1281
1282 /* BSD/OS specific PPP printer */
1283 u_int
1284 ppp_bsdos_if_print(const struct pcap_pkthdr *h _U_, register const u_char *p _U_)
1285 {
1286         register int hdrlength;
1287 #ifdef __bsdi__
1288         register u_int length = h->len;
1289         register u_int caplen = h->caplen;
1290         u_int16_t ptype;
1291         const u_char *q;
1292         int i;
1293
1294         if (caplen < PPP_BSDI_HDRLEN) {
1295                 printf("[|ppp]");
1296                 return (caplen)
1297         }
1298
1299         hdrlength = 0;
1300
1301 #if 0
1302         if (p[0] == PPP_ADDRESS && p[1] == PPP_CONTROL) {
1303                 if (eflag)
1304                         printf("%02x %02x ", p[0], p[1]);
1305                 p += 2;
1306                 hdrlength = 2;
1307         }
1308
1309         if (eflag)
1310                 printf("%d ", length);
1311         /* Retrieve the protocol type */
1312         if (*p & 01) {
1313                 /* Compressed protocol field */
1314                 ptype = *p;
1315                 if (eflag)
1316                         printf("%02x ", ptype);
1317                 p++;
1318                 hdrlength += 1;
1319         } else {
1320                 /* Un-compressed protocol field */
1321                 ptype = ntohs(*(u_int16_t *)p);
1322                 if (eflag)
1323                         printf("%04x ", ptype);
1324                 p += 2;
1325                 hdrlength += 2;
1326         }
1327 #else
1328         ptype = 0;      /*XXX*/
1329         if (eflag)
1330                 printf("%c ", p[SLC_DIR] ? 'O' : 'I');
1331         if (p[SLC_LLHL]) {
1332                 /* link level header */
1333                 struct ppp_header *ph;
1334
1335                 q = p + SLC_BPFHDRLEN;
1336                 ph = (struct ppp_header *)q;
1337                 if (ph->phdr_addr == PPP_ADDRESS
1338                  && ph->phdr_ctl == PPP_CONTROL) {
1339                         if (eflag)
1340                                 printf("%02x %02x ", q[0], q[1]);
1341                         ptype = ntohs(ph->phdr_type);
1342                         if (eflag && (ptype == PPP_VJC || ptype == PPP_VJNC)) {
1343                                 printf("%s ", tok2str(ppptype2str,
1344                                                 "proto-#%d", ptype));
1345                         }
1346                 } else {
1347                         if (eflag) {
1348                                 printf("LLH=[");
1349                                 for (i = 0; i < p[SLC_LLHL]; i++)
1350                                         printf("%02x", q[i]);
1351                                 printf("] ");
1352                         }
1353                 }
1354         }
1355         if (eflag)
1356                 printf("%d ", length);
1357         if (p[SLC_CHL]) {
1358                 q = p + SLC_BPFHDRLEN + p[SLC_LLHL];
1359
1360                 switch (ptype) {
1361                 case PPP_VJC:
1362                         ptype = vjc_print(q, ptype);
1363                         hdrlength = PPP_BSDI_HDRLEN;
1364                         p += hdrlength;
1365                         switch (ptype) {
1366                         case PPP_IP:
1367                                 ip_print(p, length);
1368                                 break;
1369 #ifdef INET6
1370                         case PPP_IPV6:
1371                                 ip6_print(p, length);
1372                                 break;
1373 #endif
1374                         case PPP_MPLS_UCAST:
1375                         case PPP_MPLS_MCAST:
1376                                 mpls_print(p, length);
1377                                 break;
1378                         }
1379                         goto printx;
1380                 case PPP_VJNC:
1381                         ptype = vjc_print(q, ptype);
1382                         hdrlength = PPP_BSDI_HDRLEN;
1383                         p += hdrlength;
1384                         switch (ptype) {
1385                         case PPP_IP:
1386                                 ip_print(p, length);
1387                                 break;
1388 #ifdef INET6
1389                         case PPP_IPV6:
1390                                 ip6_print(p, length);
1391                                 break;
1392 #endif
1393                         case PPP_MPLS_UCAST:
1394                         case PPP_MPLS_MCAST:
1395                                 mpls_print(p, length);
1396                                 break;
1397                         }
1398                         goto printx;
1399                 default:
1400                         if (eflag) {
1401                                 printf("CH=[");
1402                                 for (i = 0; i < p[SLC_LLHL]; i++)
1403                                         printf("%02x", q[i]);
1404                                 printf("] ");
1405                         }
1406                         break;
1407                 }
1408         }
1409
1410         hdrlength = PPP_BSDI_HDRLEN;
1411 #endif
1412
1413         length -= hdrlength;
1414         p += hdrlength;
1415
1416         switch (ptype) {
1417         case PPP_IP:
1418                 ip_print(p, length);
1419                 break;
1420 #ifdef INET6
1421         case PPP_IPV6:
1422                 ip6_print(p, length);
1423                 break;
1424 #endif
1425         case PPP_MPLS_UCAST:
1426         case PPP_MPLS_MCAST:
1427                 mpls_print(p, length);
1428                 break;
1429         default:
1430                 printf("%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", ptype));
1431         }
1432
1433 printx:
1434 #else /* __bsdi */
1435         hdrlength = 0;
1436 #endif /* __bsdi__ */
1437         return (hdrlength);
1438 }