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