xref: /freebsd/contrib/tcpdump/print-ppp.c (revision d74e86d9e30043893d6b308468008b65640ddcae)
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 
22 #ifndef lint
23 static const char rcsid[] =
24     "@(#) $Header: print-ppp.c,v 1.26 97/06/12 14:21:29 leres Exp $ (LBL)";
25 #endif
26 
27 #include <sys/param.h>
28 #include <sys/time.h>
29 #include <sys/socket.h>
30 #include <sys/file.h>
31 #include <sys/ioctl.h>
32 
33 #if __STDC__
34 struct mbuf;
35 struct rtentry;
36 #endif
37 #include <net/if.h>
38 
39 #include <netinet/in.h>
40 #include <netinet/in_systm.h>
41 #include <netinet/ip.h>
42 
43 #include <ctype.h>
44 #include <netdb.h>
45 #include <pcap.h>
46 #include <stdio.h>
47 
48 #include <net/ethernet.h>
49 #include "ethertype.h"
50 
51 #include <net/ppp_defs.h>
52 #include "interface.h"
53 #include "addrtoname.h"
54 #include "ppp.h"
55 
56 struct protonames {
57 	u_short protocol;
58 	char *name;
59 };
60 
61 static struct protonames protonames[] = {
62 	/*
63 	 * Protocol field values.
64 	 */
65 	PPP_IP,		"IP",		/* Internet Protocol */
66 	PPP_XNS,	"XNS",		/* Xerox NS */
67 	PPP_IPX,	"IPX",		/* IPX Datagram (RFC1552) */
68 	PPP_VJC_COMP,	"VJC_UNCOMP",	/* VJ compressed TCP */
69 	PPP_VJC_UNCOMP,	"VJC_UNCOMP",	/* VJ uncompressed TCP */
70 	PPP_COMP,	"COMP",		/* compressed packet */
71 	PPP_IPCP,	"IPCP",		/* IP Control Protocol */
72 	PPP_IPXCP,	"IPXCP",	/* IPX Control Protocol (RFC1552) */
73 	PPP_CCP,	"CCP",		/* Compression Control Protocol */
74 	PPP_LCP,	"LCP",		/* Link Control Protocol */
75 	PPP_PAP,	"PAP",		/* Password Authentication Protocol */
76 	PPP_LQR,	"LQR",		/* Link Quality Report protocol */
77 	PPP_CHAP,	"CHAP",		/* Cryptographic Handshake Auth. Proto*/
78 };
79 
80 /* LCP */
81 
82 #define LCP_CONF_REQ	1
83 #define LCP_CONF_ACK	2
84 #define LCP_CONF_NAK	3
85 #define LCP_CONF_REJ	4
86 #define LCP_TERM_REQ	5
87 #define LCP_TERM_ACK	6
88 #define LCP_CODE_REJ	7
89 #define LCP_PROT_REJ	8
90 #define LCP_ECHO_REQ	9
91 #define LCP_ECHO_RPL	10
92 #define LCP_DISC_REQ	11
93 
94 #define LCP_MIN	LCP_CONF_REQ
95 #define LCP_MAX LCP_DISC_REQ
96 
97 static char *lcpcodes[] = {
98 	/*
99 	 * LCP code values (RFC1661, pp26)
100 	 */
101 	"Configure-Request",
102 	"Configure-Ack",
103 	"Configure-Nak",
104 	"Configure-Reject",
105 	"Terminate-Request",
106 	"Terminate-Ack",
107  	"Code-Reject",
108 	"Protocol-Reject",
109 	"Echo-Request",
110 	"Echo-Reply",
111 	"Discard-Request",
112 };
113 
114 #define LCPOPT_VEXT	0
115 #define LCPOPT_MRU	1
116 #define LCPOPT_ACCM	2
117 #define LCPOPT_AP	3
118 #define LCPOPT_QP	4
119 #define LCPOPT_MN	5
120 #define LCPOPT_PFC	7
121 #define LCPOPT_ACFC	8
122 
123 #define LCPOPT_MIN 0
124 #define LCPOPT_MAX 24
125 
126 static char *lcpconfopts[] = {
127 	"Vendor-Ext",
128 	"Max-Rx-Unit",
129 	"Async-Ctrl-Char-Map",
130 	"Auth-Prot",
131 	"Quality-Prot",
132 	"Magic-Number",
133 	"unassigned (6)",
134 	"Prot-Field-Compr",
135 	"Add-Ctrl-Field-Compr",
136 	"FCS-Alternatives",
137 	"Self-Describing-Pad",
138 	"Numbered-Mode",
139 	"Multi-Link-Procedure",
140 	"Call-Back",
141 	"Connect-Time"
142 	"Compund-Frames",
143 	"Nominal-Data-Encap",
144 	"Multilink-MRRU",
145 	"Multilink-SSNHF",
146 	"Multilink-ED",
147 	"Proprietary",
148 	"DCE-Identifier",
149 	"Multilink-Plus-Proc",
150 	"Link-Discriminator",
151 	"LCP-Auth-Option",
152 };
153 
154 /* CHAP */
155 
156 #define CHAP_CHAL	1
157 #define CHAP_RESP	2
158 #define CHAP_SUCC	3
159 #define CHAP_FAIL	4
160 
161 #define CHAP_CODEMIN 1
162 #define CHAP_CODEMAX 4
163 
164 static char *chapcode[] = {
165 	"Challenge",
166 	"Response",
167 	"Success",
168 	"Failure",
169 };
170 
171 /* PAP */
172 
173 #define PAP_AREQ	1
174 #define PAP_AACK	2
175 #define PAP_ANAK	3
176 
177 #define PAP_CODEMIN	1
178 #define PAP_CODEMAX	3
179 
180 static char *papcode[] = {
181 	"Authenticate-Request",
182 	"Authenticate-Ack",
183 	"Authenticate-Nak",
184 };
185 
186 /* IPCP */
187 
188 #define IPCP_2ADDR	1
189 #define IPCP_CP		2
190 #define IPCP_ADDR	3
191 
192 static int handle_lcp(const u_char *p, int length);
193 static int print_lcp_config_options(u_char *p);
194 static int handle_chap(const u_char *p, int length);
195 static int handle_ipcp(const u_char *p, int length);
196 static int handle_pap(const u_char *p, int length);
197 
198 /* Standard PPP printer */
199 void
200 ppp_hdlc_print(const u_char *p, int length)
201 {
202 	int proto = PPP_PROTOCOL(p);
203 	int i, j, x;
204 	u_char *ptr;
205 
206 	printf("ID-%03d ", *(p+5));
207 
208 	for (i = (sizeof(protonames) / sizeof(protonames[0])) - 1; i >= 0; --i)
209 	{
210 		if (proto == protonames[i].protocol)
211 		{
212 			printf("%s: ", protonames[i].name);
213 
214 			switch(proto)
215 			{
216 				case PPP_LCP:
217 					handle_lcp(p, length);
218 					break;
219 				case PPP_CHAP:
220 					handle_chap(p, length);
221 					break;
222 				case PPP_PAP:
223 					handle_pap(p, length);
224 					break;
225 				case PPP_IPCP:
226 					handle_ipcp(p, length);
227 					break;
228 			}
229 			break;
230 		}
231 	}
232 	if (i < 0)
233 	{
234 		printf("%04x: ", proto);
235 	}
236 }
237 
238 /* print LCP frame */
239 
240 static int
241 handle_lcp(const u_char *p, int length)
242 {
243 	int x, j;
244 	u_char *ptr;
245 
246 	x = *(p+4);
247 
248 	if((x >= LCP_MIN) && (x <= LCP_MAX))
249 	{
250 		printf("%s", lcpcodes[x-1]);
251 	}
252 	else
253 	{
254 		printf("0x%02x", x);
255 		return;
256 	}
257 
258 	length -= 4;
259 
260 	switch(x)
261 	{
262 		case LCP_CONF_REQ:
263 		case LCP_CONF_ACK:
264 		case LCP_CONF_NAK:
265 		case LCP_CONF_REJ:
266 			x = length;
267 			ptr = (u_char *)p+8;
268 			do
269 			{
270 				if((j = print_lcp_config_options(ptr)) == 0)
271 					break;
272 				x -= j;
273 				ptr += j;
274 			}
275 			while(x > 0);
276 			break;
277 
278 		case LCP_ECHO_REQ:
279 		case LCP_ECHO_RPL:
280 			printf(", Magic-Number=%d", ((*(p+8) << 24) + (*(p+9) << 16) + (*(p+10) << 8) + (*(p+11))));
281 			break;
282 		case LCP_TERM_REQ:
283 		case LCP_TERM_ACK:
284 		case LCP_CODE_REJ:
285 		case LCP_PROT_REJ:
286 		case LCP_DISC_REQ:
287 		default:
288 			break;
289 	}
290 }
291 
292 /* LCP config options */
293 
294 static int
295 print_lcp_config_options(u_char *p)
296 {
297 	int len	= *(p+1);
298 	int opt = *p;
299 
300 	if((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX))
301 		printf(", %s", lcpconfopts[opt]);
302 
303 	switch(opt)
304 	{
305 		case LCPOPT_MRU:
306 			if(len == 4)
307 				printf("=%d", (*(p+2) << 8) + *(p+3));
308 			break;
309 		case LCPOPT_AP:
310 			if(len >= 4)
311 			{
312 				if(*(p+2) == 0xc0 && *(p+3) == 0x23)
313 				{
314 					printf(" PAP");
315 				}
316 				else if(*(p+2) == 0xc2 && *(p+3) == 0x23)
317 				{
318 					printf(" CHAP/");
319 					switch(*(p+4))
320 					{
321 						default:
322 							printf("unknown-algorithm-%d", *(p+4));
323 							break;
324 						case 5:
325 							printf("MD5");
326 							break;
327 						case 0x80:
328 							printf("Microsoft");
329 							break;
330 					}
331 				}
332 				else if(*(p+2) == 0xc2 && *(p+3) == 0x27)
333 				{
334 					printf(" EAP");
335 				}
336 				else if(*(p+2) == 0xc0 && *(p+3) == 0x27)
337 				{
338 					printf(" SPAP");
339 				}
340 				else if(*(p+2) == 0xc1 && *(p+3) == 0x23)
341 				{
342 					printf(" Old-SPAP");
343 				}
344 				else
345 				{
346 					printf("unknown");
347 				}
348 			}
349 			break;
350 		case LCPOPT_QP:
351 			if(len >= 4)
352 			{
353 				if(*(p+2) == 0xc0 && *(p+3) == 0x25)
354 					printf(" LQR");
355 				else
356 					printf(" unknown");
357 			}
358 			break;
359 		case LCPOPT_MN:
360 			if(len == 6)
361 			{
362 				printf("=%d", ((*(p+2) << 24) + (*(p+3) << 16) + (*(p+4) << 8) + (*(p+5))));
363 			}
364 			break;
365 		case LCPOPT_PFC:
366 			printf(" PFC");
367 			break;
368 		case LCPOPT_ACFC:
369 			printf(" ACFC");
370 			break;
371 	}
372 	return(len);
373 }
374 
375 /* CHAP */
376 
377 static int
378 handle_chap(const u_char *p, int length)
379 {
380 	int x, j;
381 	u_char *ptr;
382 
383 	x = *(p+4);
384 
385 	if((x >= CHAP_CODEMIN) && (x <= CHAP_CODEMAX))
386 	{
387 		printf("%s", chapcode[x-1]);
388 	}
389 	else
390 	{
391 		printf("0x%02x", x);
392 		return;
393 	}
394 
395 	length -= 4;
396 
397 	switch(x)
398 	{
399 		case CHAP_CHAL:
400 		case CHAP_RESP:
401 			printf(", Value=");
402 			x = *(p+8);	/* value size */
403 			ptr = (u_char *)p+9;
404 			while(--x >= 0)
405 				printf("%02x", *ptr++);
406 			x = length - *(p+8) - 1;
407 			printf(", Name=");
408 			while(--x >= 0)
409 				printf("%c", *ptr++);
410 			break;
411 	}
412 }
413 
414 /* PAP */
415 
416 static int
417 handle_pap(const u_char *p, int length)
418 {
419 	int x, j;
420 	u_char *ptr;
421 
422 	x = *(p+4);
423 
424 	if((x >= PAP_CODEMIN) && (x <= PAP_CODEMAX))
425 	{
426 		printf("%s", papcode[x-1]);
427 	}
428 	else
429 	{
430 		printf("0x%02x", x);
431 		return;
432 	}
433 
434 	length -= 4;
435 
436 	switch(x)
437 	{
438 		case PAP_AREQ:
439 			printf(", Peer-Id=");
440 			x = *(p+8);	/* peerid size */
441 			ptr = (u_char *)p+9;
442 			while(--x >= 0)
443 				printf("%c", *ptr++);
444 			x = *ptr++;
445 			printf(", Passwd=");
446 			while(--x >= 0)
447 				printf("%c", *ptr++);
448 			break;
449 		case PAP_AACK:
450 		case PAP_ANAK:
451 			break;
452 	}
453 }
454 
455 /* IPCP */
456 
457 static int
458 handle_ipcp(const u_char *p, int length)
459 {
460 	int x, j;
461 
462 	x = *(p+8);
463 
464 	length -= 4;
465 
466 	switch(x)
467 	{
468 		case IPCP_2ADDR:
469 			printf("IP-Addresses");
470 			printf(", Src=%d.%d.%d.%d", *(p+10), *(p+11), *(p+12), *(p+13));
471 			printf(", Dst=%d.%d.%d.%d", *(p+14), *(p+15), *(p+16), *(p+17));
472 			break;
473 
474 		case IPCP_CP:
475 			printf("IP-Compression-Protocol");
476 			break;
477 
478 		case IPCP_ADDR:
479 			printf("IP-Address=%d.%d.%d.%d", *(p+10), *(p+11), *(p+12), *(p+13));
480 			break;
481 	}
482 }
483 
484 void
485 ppp_if_print(u_char *user, const struct pcap_pkthdr *h,
486 	     register const u_char *p)
487 {
488 	register u_int length = h->len;
489 	register u_int caplen = h->caplen;
490 
491 	ts_print(&h->ts);
492 
493 	if (caplen < PPP_HDRLEN) {
494 		printf("[|ppp]");
495 		goto out;
496 	}
497 
498 	/*
499 	 * Some printers want to get back at the link level addresses,
500 	 * and/or check that they're not walking off the end of the packet.
501 	 * Rather than pass them all the way down, we set these globals.
502 	 */
503 	packetp = p;
504 	snapend = p + caplen;
505 
506 	if (eflag)
507 		ppp_hdlc_print(p, length);
508 
509 	length -= PPP_HDRLEN;
510 
511 	switch(PPP_PROTOCOL(p)) {
512 	case PPP_IP:
513 	case ETHERTYPE_IP:
514 		ip_print((const u_char *)(p + PPP_HDRLEN), length);
515 		break;
516 	case PPP_IPX:
517 	case ETHERTYPE_IPX:
518 		ipx_print((const u_char *)(p + PPP_HDRLEN), length);
519 		break;
520 
521 	default:
522 		if(!eflag)
523 			ppp_hdlc_print(p, length);
524 		if(!xflag)
525 			default_print((const u_char *)(p + PPP_HDRLEN),
526 					caplen - PPP_HDRLEN);
527 	}
528 
529 	if (xflag)
530 		default_print((const u_char *)(p + PPP_HDRLEN),
531 				caplen - PPP_HDRLEN);
532 out:
533 	putchar('\n');
534 }
535 
536 /* proto type to string mapping */
537 static struct tok ptype2str[] = {
538 	{ PPP_VJC,	"VJC" },
539 	{ PPP_VJNC,	"VJNC" },
540 	{ PPP_OSI,	"OSI" },
541 	{ PPP_LCP,	"LCP" },
542 	{ PPP_IPCP,	"IPCP" },
543 	{ 0,		NULL }
544 };
545 
546 #define PPP_BSDI_HDRLEN 24
547 
548 /* BSD/OS specific PPP printer */
549 void
550 ppp_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h,
551 	     register const u_char *p)
552 {
553 	register u_int length = h->len;
554 	register u_int caplen = h->caplen;
555 	register int hdrlength;
556 	u_short ptype;
557 
558 	ts_print(&h->ts);
559 
560 	if (caplen < PPP_BSDI_HDRLEN) {
561 		printf("[|ppp]");
562 		goto out;
563 	}
564 
565 	/*
566 	 * Some printers want to get back at the link level addresses,
567 	 * and/or check that they're not walking off the end of the packet.
568 	 * Rather than pass them all the way down, we set these globals.
569 	 */
570 	packetp = p;
571 	snapend = p + caplen;
572 	hdrlength = 0;
573 
574 	if (p[0] == PPP_ADDRESS && p[1] == PPP_CONTROL) {
575 		if (eflag)
576 			printf("%02x %02x ", p[0], p[1]);
577 		p += 2;
578 		hdrlength = 2;
579 	}
580 
581 	if (eflag)
582 		printf("%d ", length);
583 	/* Retrieve the protocol type */
584 	if (*p & 01) {
585 		/* Compressed protocol field */
586 		ptype = *p;
587 		if (eflag)
588 			printf("%02x ", ptype);
589 		p++;
590 		hdrlength += 1;
591 	} else {
592 		/* Un-compressed protocol field */
593 		ptype = ntohs(*(u_short *)p);
594 		if (eflag)
595 			printf("%04x ", ptype);
596 		p += 2;
597 		hdrlength += 2;
598 	}
599 
600 	length -= hdrlength;
601 
602 	if (ptype == PPP_IP)
603 		ip_print(p, length);
604 	else
605 		printf("%s ", tok2str(ptype2str, "proto-#%d", ptype));
606 
607 	if (xflag)
608 		default_print((const u_char *)p, caplen - hdrlength);
609 out:
610 	putchar('\n');
611 }
612