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