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