print-ppp.c revision 53146
1193326Sed/*
2193326Sed * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3193326Sed *	The Regents of the University of California.  All rights reserved.
4193326Sed *
5193326Sed * Redistribution and use in source and binary forms, with or without
6193326Sed * modification, are permitted provided that: (1) source code distributions
7193326Sed * retain the above copyright notice and this paragraph in its entirety, (2)
8193326Sed * distributions including binary code include the above copyright notice and
9193326Sed * this paragraph in its entirety in the documentation or other materials
10193326Sed * provided with the distribution, and (3) all advertising materials mentioning
11193326Sed * features or use of this software display the following acknowledgement:
12193326Sed * ``This product includes software developed by the University of California,
13193326Sed * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14193326Sed * the University nor the names of its contributors may be used to endorse
15249423Sdim * or promote products derived from this software without specific prior
16193326Sed * written permission.
17212904Sdim * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18212904Sdim * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19193326Sed * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20198398Srdivacky *
21193326Sed * $FreeBSD: head/contrib/tcpdump/print-ppp.c 53146 1999-11-14 11:28:11Z brian $
22193326Sed */
23193326Sed
24234353Sdim#ifndef lint
25234353Sdimstatic const char rcsid[] =
26234353Sdim    "@(#) $Header: print-ppp.c,v 1.26 97/06/12 14:21:29 leres Exp $ (LBL)";
27234353Sdim#endif
28234353Sdim
29234353Sdim#include <sys/param.h>
30234353Sdim#include <sys/time.h>
31234353Sdim#include <sys/socket.h>
32193326Sed#include <sys/file.h>
33234353Sdim#include <sys/ioctl.h>
34234353Sdim
35234353Sdim#if __STDC__
36249423Sdimstruct mbuf;
37193326Sedstruct rtentry;
38234353Sdim#endif
39234353Sdim#include <net/if.h>
40234353Sdim
41234353Sdim#include <netinet/in.h>
42234353Sdim#include <netinet/in_systm.h>
43234353Sdim#include <netinet/ip.h>
44234353Sdim
45234353Sdim#include <ctype.h>
46234353Sdim#include <netdb.h>
47234353Sdim#include <pcap.h>
48234353Sdim#include <stdio.h>
49234353Sdim
50234353Sdim#include <net/ethernet.h>
51234353Sdim#include "ethertype.h"
52234353Sdim
53234353Sdim#include <net/ppp_defs.h>
54234353Sdim#include "interface.h"
55234353Sdim#include "addrtoname.h"
56234353Sdim#include "ppp.h"
57234353Sdim
58234353Sdimstruct protonames {
59234353Sdim	u_short protocol;
60234353Sdim	char *name;
61234353Sdim};
62234353Sdim
63234353Sdimstatic struct protonames protonames[] = {
64193326Sed	/*
65193326Sed	 * Protocol field values.
66193326Sed	 */
67234353Sdim	PPP_IP,		"IP",		/* Internet Protocol */
68234353Sdim	PPP_XNS,	"XNS",		/* Xerox NS */
69276479Sdim	PPP_IPX,	"IPX",		/* IPX Datagram (RFC1552) */
70234353Sdim	PPP_VJC_COMP,	"VJC_UNCOMP",	/* VJ compressed TCP */
71276479Sdim	PPP_VJC_UNCOMP,	"VJC_UNCOMP",	/* VJ uncompressed TCP */
72276479Sdim	PPP_COMP,	"COMP",		/* compressed packet */
73276479Sdim	PPP_IPCP,	"IPCP",		/* IP Control Protocol */
74276479Sdim	PPP_IPXCP,	"IPXCP",	/* IPX Control Protocol (RFC1552) */
75276479Sdim	PPP_CCP,	"CCP",		/* Compression Control Protocol */
76276479Sdim	PPP_LCP,	"LCP",		/* Link Control Protocol */
77276479Sdim	PPP_PAP,	"PAP",		/* Password Authentication Protocol */
78276479Sdim	PPP_LQR,	"LQR",		/* Link Quality Report protocol */
79276479Sdim	PPP_CHAP,	"CHAP",		/* Cryptographic Handshake Auth. Proto*/
80234353Sdim};
81276479Sdim
82276479Sdim/* LCP */
83276479Sdim
84276479Sdim#define LCP_CONF_REQ	1
85276479Sdim#define LCP_CONF_ACK	2
86276479Sdim#define LCP_CONF_NAK	3
87276479Sdim#define LCP_CONF_REJ	4
88276479Sdim#define LCP_TERM_REQ	5
89276479Sdim#define LCP_TERM_ACK	6
90276479Sdim#define LCP_CODE_REJ	7
91276479Sdim#define LCP_PROT_REJ	8
92193326Sed#define LCP_ECHO_REQ	9
93193326Sed#define LCP_ECHO_RPL	10
94207619Srdivacky#define LCP_DISC_REQ	11
95207619Srdivacky
96207619Srdivacky#define LCP_MIN	LCP_CONF_REQ
97207619Srdivacky#define LCP_MAX LCP_DISC_REQ
98207619Srdivacky
99207619Srdivackystatic char *lcpcodes[] = {
100207619Srdivacky	/*
101207619Srdivacky	 * LCP code values (RFC1661, pp26)
102207619Srdivacky	 */
103207619Srdivacky	"Configure-Request",
104207619Srdivacky	"Configure-Ack",
105207619Srdivacky	"Configure-Nak",
106207619Srdivacky	"Configure-Reject",
107193326Sed	"Terminate-Request",
108193326Sed	"Terminate-Ack",
109193326Sed 	"Code-Reject",
110193326Sed	"Protocol-Reject",
111193326Sed	"Echo-Request",
112193326Sed	"Echo-Reply",
113193326Sed	"Discard-Request",
114193326Sed};
115193326Sed
116193326Sed#define LCPOPT_VEXT	0
117193326Sed#define LCPOPT_MRU	1
118193326Sed#define LCPOPT_ACCM	2
119193326Sed#define LCPOPT_AP	3
120193326Sed#define LCPOPT_QP	4
121193326Sed#define LCPOPT_MN	5
122193326Sed#define LCPOPT_PFC	7
123193326Sed#define LCPOPT_ACFC	8
124193326Sed
125193326Sed#define LCPOPT_MIN 0
126193326Sed#define LCPOPT_MAX 24
127193326Sed
128193326Sedstatic char *lcpconfopts[] = {
129193326Sed	"Vendor-Ext",
130193326Sed	"Max-Rx-Unit",
131212904Sdim	"Async-Ctrl-Char-Map",
132193326Sed	"Auth-Prot",
133193326Sed	"Quality-Prot",
134193326Sed	"Magic-Number",
135193326Sed	"unassigned (6)",
136193326Sed	"Prot-Field-Compr",
137193326Sed	"Add-Ctrl-Field-Compr",
138193326Sed	"FCS-Alternatives",
139193326Sed	"Self-Describing-Pad",
140234353Sdim	"Numbered-Mode",
141198398Srdivacky	"Multi-Link-Procedure",
142198398Srdivacky	"Call-Back",
143193326Sed	"Connect-Time",
144193326Sed	"Compund-Frames",
145198092Srdivacky	"Nominal-Data-Encap",
146193326Sed	"Multilink-MRRU",
147193326Sed	"Multilink-SSNHF",
148193326Sed	"Multilink-ED",
149226633Sdim	"Proprietary",
150206084Srdivacky	"DCE-Identifier",
151288943Sdim	"Multilink-Plus-Proc",
152193326Sed	"Link-Discriminator",
153193326Sed	"LCP-Auth-Option",
154193326Sed};
155198092Srdivacky
156193326Sed/* CHAP */
157193326Sed
158198092Srdivacky#define CHAP_CHAL	1
159193326Sed#define CHAP_RESP	2
160193326Sed#define CHAP_SUCC	3
161193326Sed#define CHAP_FAIL	4
162193326Sed
163198092Srdivacky#define CHAP_CODEMIN 1
164193326Sed#define CHAP_CODEMAX 4
165193326Sed
166193326Sedstatic char *chapcode[] = {
167193326Sed	"Challenge",
168193326Sed	"Response",
169198092Srdivacky	"Success",
170193326Sed	"Failure",
171193326Sed};
172193326Sed
173193326Sed/* PAP */
174198092Srdivacky
175193326Sed#define PAP_AREQ	1
176193326Sed#define PAP_AACK	2
177193326Sed#define PAP_ANAK	3
178193326Sed
179193326Sed#define PAP_CODEMIN	1
180198092Srdivacky#define PAP_CODEMAX	3
181193326Sed
182193326Sedstatic char *papcode[] = {
183198092Srdivacky	"Authenticate-Request",
184193326Sed	"Authenticate-Ack",
185193326Sed	"Authenticate-Nak",
186193326Sed};
187193326Sed
188193326Sed/* IPCP */
189193326Sed
190193326Sed#define IPCP_2ADDR	1
191193326Sed#define IPCP_CP		2
192193326Sed#define IPCP_ADDR	3
193193326Sed
194193326Sed/* PPPoE */
195193326Sed
196234353Sdimstruct typenames {
197234353Sdim	u_short type;
198234353Sdim	char *name;
199234353Sdim};
200234353Sdim
201218893Sdimstatic struct typenames typenames[] = {
202218893Sdim	/*
203226633Sdim	 * PPPoE type field values
204226633Sdim	 */
205226633Sdim	0x00,	"DATA",			/* PPPoE Data packet                */
206226633Sdim	0x09,	"PADI",			/* Active Discovery Initiation      */
207212904Sdim	0x07,	"PADO",			/* Active Discovery Offer           */
208198092Srdivacky	0x19,	"PADR",			/* Active Discovery Request         */
209207619Srdivacky	0x65,	"PADS",			/* Active Discovery Session-Confirm */
210207619Srdivacky	0xa7,	"PADT",			/* Active Discovery Terminate       */
211207619Srdivacky};
212207619Srdivacky
213234353Sdimstruct tagnames {
214207619Srdivacky	u_short tag;
215207619Srdivacky	char *name;
216218893Sdim	int isascii;
217218893Sdim};
218207619Srdivacky
219207619Srdivackystatic struct tagnames tagnames[] = {
220212904Sdim  /*
221212904Sdim   * PPPoE tag field values
222276479Sdim   */
223207619Srdivacky  0x0000, "End-Of-List",	0,	/* Optional last tag (len 0) */
224193326Sed  0x0101, "Service-Name",	1,	/* The (ascii) service */
225207619Srdivacky  0x0102, "AC-Name",		-1,	/* Access Concentrator */
226207619Srdivacky  0x0103, "Host-Uniq",		0,	/* Associate PAD[OS] with PAD[IR] */
227207619Srdivacky  0x0104, "AC-Cookie",		0,	/* Optional at PADO time */
228207619Srdivacky  0x0105, "Vendor-Specific",	0,	/* First 4 bytes special (ignore) */
229261991Sdim  0x0110, "Relay-Session-Id",	0,	/* Max 12 octets, added by gateway */
230207619Srdivacky  0x0201, "Service-Name-Error",	-1,	/* Request not honoured */
231207619Srdivacky  0x0203, "Generic-Error",	1	/* Access Concentrator error */
232207619Srdivacky};
233207619Srdivacky
234207619Srdivackystatic int handle_lcp(const u_char *p, int length);
235207619Srdivackystatic int print_lcp_config_options(u_char *p);
236207619Srdivackystatic int handle_chap(const u_char *p, int length);
237207619Srdivackystatic int handle_ipcp(const u_char *p, int length);
238207619Srdivackystatic int handle_pap(const u_char *p, int length);
239212904Sdimstatic void do_ppp_print(const u_char *p, u_int length, u_int caplen);
240276479Sdim
241207619Srdivacky/* Standard PPP printer */
242207619Srdivackyvoid
243207619Srdivackyppp_hdlc_print(const u_char *p, int length)
244207619Srdivacky{
245207619Srdivacky	int proto = PPP_PROTOCOL(p);
246207619Srdivacky	int i, j, x;
247212904Sdim	u_char *ptr;
248234353Sdim
249207619Srdivacky	printf("ID-%03d ", *(p+5));
250207619Srdivacky
251212904Sdim	for (i = (sizeof(protonames) / sizeof(protonames[0])) - 1; i >= 0; --i)
252207619Srdivacky	{
253207619Srdivacky		if (proto == protonames[i].protocol)
254207619Srdivacky		{
255288943Sdim			printf("%s: ", protonames[i].name);
256288943Sdim
257288943Sdim			switch(proto)
258212904Sdim			{
259288943Sdim				case PPP_LCP:
260288943Sdim					handle_lcp(p, length);
261288943Sdim					break;
262288943Sdim				case PPP_CHAP:
263288943Sdim					handle_chap(p, length);
264288943Sdim					break;
265212904Sdim				case PPP_PAP:
266207619Srdivacky					handle_pap(p, length);
267207619Srdivacky					break;
268207619Srdivacky				case PPP_IPCP:
269261991Sdim					handle_ipcp(p, length);
270207619Srdivacky					break;
271207619Srdivacky			}
272207619Srdivacky			break;
273288943Sdim		}
274288943Sdim	}
275288943Sdim	if (i < 0)
276288943Sdim	{
277288943Sdim		printf("%04x: ", proto);
278288943Sdim	}
279288943Sdim}
280288943Sdim
281288943Sdim/* print LCP frame */
282288943Sdim
283288943Sdimstatic int
284288943Sdimhandle_lcp(const u_char *p, int length)
285288943Sdim{
286288943Sdim	int x, j;
287288943Sdim	u_char *ptr;
288288943Sdim
289207619Srdivacky	x = *(p+4);
290207619Srdivacky
291276479Sdim	if((x >= LCP_MIN) && (x <= LCP_MAX))
292207619Srdivacky	{
293212904Sdim		printf("%s", lcpcodes[x-1]);
294207619Srdivacky	}
295207619Srdivacky	else
296207619Srdivacky	{
297207619Srdivacky		printf("0x%02x", x);
298207619Srdivacky		return;
299193326Sed	}
300193326Sed
301207619Srdivacky	length -= 4;
302207619Srdivacky
303193326Sed	switch(x)
304193326Sed	{
305193326Sed		case LCP_CONF_REQ:
306207619Srdivacky		case LCP_CONF_ACK:
307207619Srdivacky		case LCP_CONF_NAK:
308207619Srdivacky		case LCP_CONF_REJ:
309207619Srdivacky			x = length;
310207619Srdivacky			ptr = (u_char *)p+8;
311261991Sdim			do
312243830Sdim			{
313207619Srdivacky				if((j = print_lcp_config_options(ptr)) == 0)
314193326Sed					break;
315198092Srdivacky				x -= j;
316193326Sed				ptr += j;
317193326Sed			}
318198092Srdivacky			while(x > 0);
319193326Sed			break;
320234353Sdim
321193326Sed		case LCP_ECHO_REQ:
322207619Srdivacky		case LCP_ECHO_RPL:
323193326Sed			printf(", Magic-Number=%d", ((*(p+8) << 24) + (*(p+9) << 16) + (*(p+10) << 8) + (*(p+11))));
324193326Sed			break;
325212904Sdim		case LCP_TERM_REQ:
326276479Sdim		case LCP_TERM_ACK:
327193326Sed		case LCP_CODE_REJ:
328193326Sed		case LCP_PROT_REJ:
329193326Sed		case LCP_DISC_REQ:
330193326Sed		default:
331276479Sdim			break;
332193326Sed	}
333193326Sed}
334193326Sed
335193326Sed/* LCP config options */
336193326Sed
337212904Sdimstatic int
338193326Sedprint_lcp_config_options(u_char *p)
339261991Sdim{
340243830Sdim	int len	= *(p+1);
341193326Sed	int opt = *p;
342276479Sdim
343276479Sdim	if((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX))
344193326Sed		printf(", %s", lcpconfopts[opt]);
345193326Sed
346193326Sed	switch(opt)
347226633Sdim	{
348226633Sdim		case LCPOPT_MRU:
349226633Sdim			if(len == 4)
350193326Sed				printf("=%d", (*(p+2) << 8) + *(p+3));
351193326Sed			break;
352193326Sed		case LCPOPT_AP:
353193326Sed			if(len >= 4)
354193326Sed			{
355193326Sed				if(*(p+2) == 0xc0 && *(p+3) == 0x23)
356193326Sed				{
357193326Sed					printf(" PAP");
358193326Sed				}
359193326Sed				else if(*(p+2) == 0xc2 && *(p+3) == 0x23)
360193326Sed				{
361193326Sed					printf(" CHAP/");
362193326Sed					switch(*(p+4))
363193326Sed					{
364193326Sed						default:
365193326Sed							printf("unknown-algorithm-%d", *(p+4));
366193326Sed							break;
367193326Sed						case 5:
368193326Sed							printf("MD5");
369198092Srdivacky							break;
370193326Sed						case 0x80:
371193326Sed							printf("Microsoft");
372193326Sed							break;
373206084Srdivacky					}
374193326Sed				}
375193326Sed				else if(*(p+2) == 0xc2 && *(p+3) == 0x27)
376193326Sed				{
377193326Sed					printf(" EAP");
378193326Sed				}
379193326Sed				else if(*(p+2) == 0xc0 && *(p+3) == 0x27)
380193326Sed				{
381193326Sed					printf(" SPAP");
382193326Sed				}
383193326Sed				else if(*(p+2) == 0xc1 && *(p+3) == 0x23)
384193326Sed				{
385193326Sed					printf(" Old-SPAP");
386193326Sed				}
387193326Sed				else
388193326Sed				{
389193326Sed					printf("unknown");
390193326Sed				}
391193326Sed			}
392218893Sdim			break;
393218893Sdim		case LCPOPT_QP:
394193326Sed			if(len >= 4)
395212904Sdim			{
396218893Sdim				if(*(p+2) == 0xc0 && *(p+3) == 0x25)
397218893Sdim					printf(" LQR");
398226633Sdim				else
399226633Sdim					printf(" unknown");
400226633Sdim			}
401193326Sed			break;
402193326Sed		case LCPOPT_MN:
403193326Sed			if(len == 6)
404243830Sdim			{
405193326Sed				printf("=%d", ((*(p+2) << 24) + (*(p+3) << 16) + (*(p+4) << 8) + (*(p+5))));
406193326Sed			}
407193326Sed			break;
408234353Sdim		case LCPOPT_PFC:
409193326Sed			printf(" PFC");
410193326Sed			break;
411251662Sdim		case LCPOPT_ACFC:
412193326Sed			printf(" ACFC");
413193326Sed			break;
414193326Sed	}
415193326Sed	return(len);
416193326Sed}
417234353Sdim
418234353Sdim/* CHAP */
419234353Sdim
420234353Sdimstatic int
421234353Sdimhandle_chap(const u_char *p, int length)
422234353Sdim{
423234353Sdim	int x, j;
424234353Sdim	u_char *ptr;
425234353Sdim
426234353Sdim	x = *(p+4);
427234353Sdim
428193326Sed	if((x >= CHAP_CODEMIN) && (x <= CHAP_CODEMAX))
429193326Sed	{
430193326Sed		printf("%s", chapcode[x-1]);
431193326Sed	}
432212904Sdim	else
433234353Sdim	{
434193326Sed		printf("0x%02x", x);
435193326Sed		return;
436193326Sed	}
437198092Srdivacky
438218893Sdim	length -= 4;
439218893Sdim
440280031Sdim	switch(x)
441280031Sdim	{
442280031Sdim		case CHAP_CHAL:
443193326Sed		case CHAP_RESP:
444280031Sdim			printf(", Value=");
445276479Sdim			x = *(p+8);	/* value size */
446193326Sed			ptr = (u_char *)p+9;
447193326Sed			while(--x >= 0)
448198092Srdivacky				printf("%02x", *ptr++);
449193326Sed			x = length - *(p+8) - 1;
450221345Sdim			printf(", Name=");
451193326Sed			while(--x >= 0)
452193326Sed				printf("%c", *ptr++);
453193326Sed			break;
454193326Sed	}
455193326Sed}
456193326Sed
457193326Sed/* PAP */
458261991Sdim
459193326Sedstatic int
460193326Sedhandle_pap(const u_char *p, int length)
461193326Sed{
462193326Sed	int x, j;
463193326Sed	u_char *ptr;
464193326Sed
465193326Sed	x = *(p+4);
466193326Sed
467193326Sed	if((x >= PAP_CODEMIN) && (x <= PAP_CODEMAX))
468193326Sed	{
469193326Sed		printf("%s", papcode[x-1]);
470193326Sed	}
471193326Sed	else
472226633Sdim	{
473226633Sdim		printf("0x%02x", x);
474226633Sdim		return;
475226633Sdim	}
476243830Sdim
477226633Sdim	length -= 4;
478193326Sed
479193326Sed	switch(x)
480193326Sed	{
481193326Sed		case PAP_AREQ:
482234353Sdim			printf(", Peer-Id=");
483234353Sdim			x = *(p+8);	/* peerid size */
484234353Sdim			ptr = (u_char *)p+9;
485234353Sdim			while(--x >= 0)
486234353Sdim				printf("%c", *ptr++);
487234353Sdim			x = *ptr++;
488234353Sdim			printf(", Passwd=");
489234353Sdim			while(--x >= 0)
490234353Sdim				printf("%c", *ptr++);
491234353Sdim			break;
492234353Sdim		case PAP_AACK:
493234353Sdim		case PAP_ANAK:
494276479Sdim			break;
495234353Sdim	}
496234353Sdim}
497234353Sdim
498234353Sdim/* IPCP */
499234353Sdim
500234353Sdimstatic int
501234353Sdimhandle_ipcp(const u_char *p, int length)
502234353Sdim{
503234353Sdim	int x, j;
504234353Sdim
505234353Sdim	x = *(p+8);
506234353Sdim
507234353Sdim	length -= 4;
508234353Sdim
509234353Sdim	switch(x)
510234353Sdim	{
511234353Sdim		case IPCP_2ADDR:
512234353Sdim			printf("IP-Addresses");
513276479Sdim			printf(", Src=%d.%d.%d.%d", *(p+10), *(p+11), *(p+12), *(p+13));
514234353Sdim			printf(", Dst=%d.%d.%d.%d", *(p+14), *(p+15), *(p+16), *(p+17));
515234353Sdim			break;
516234353Sdim
517234353Sdim		case IPCP_CP:
518234353Sdim			printf("IP-Compression-Protocol");
519234353Sdim			break;
520234353Sdim
521234353Sdim		case IPCP_ADDR:
522234353Sdim			printf("IP-Address=%d.%d.%d.%d", *(p+10), *(p+11), *(p+12), *(p+13));
523234353Sdim			break;
524234353Sdim	}
525234353Sdim}
526234353Sdim
527234353Sdimvoid
528276479Sdimppp_if_print(u_char *user, const struct pcap_pkthdr *h,
529234353Sdim	     register const u_char *p)
530234353Sdim{
531234353Sdim	register u_int length = h->len;
532234353Sdim	register u_int caplen = h->caplen;
533234353Sdim
534234353Sdim	ts_print(&h->ts);
535234353Sdim
536234353Sdim	if (caplen < PPP_HDRLEN) {
537234353Sdim		puts("[|ppp]");
538234353Sdim		return;
539234353Sdim	}
540234353Sdim
541234353Sdim	/*
542234353Sdim	 * Some printers want to get back at the link level addresses,
543234353Sdim	 * and/or check that they're not walking off the end of the packet.
544234353Sdim	 * Rather than pass them all the way down, we set these globals.
545	 */
546	packetp = p;
547	snapend = p + caplen;
548
549	do_ppp_print(p, length, caplen);
550}
551
552/*
553 * Print PPPoE discovery & session packets
554 */
555void
556pppoe_print(const u_char *p, u_int length)
557{
558	u_short tag, len, tlen;
559	u_char type;
560	int f, asc;
561
562	fputs("PPPoE ", stdout);
563
564	/*
565	 * A PPPoE header:
566	 *
567	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
568	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
569	 * |  VER  | TYPE  |      CODE     |          SESSION_ID           |
570	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
571	 * |            LENGTH             |           payload             ~
572	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
573	 */
574
575	type = p[1];
576	for (f = sizeof typenames / sizeof typenames[0] - 1; f >= 0; f--)
577		if (typenames[f].type == type) {
578			fputs(typenames[f].name, stdout);
579			break;
580		}
581
582	if (f == -1) {
583		printf("<0x%02x>\n", type);
584	}
585
586	len = ntohs(*(u_short *)(p + 4));
587	printf(" v%d, type %d, sess %d len %d", p[0] >> 4, p[0] & 0xf,
588	    ntohs(*(u_short *)(p + 2)), len);
589
590	if (type == 0x00) {
591		p += 4;
592		length -= 4;
593		if (len > length)
594			len = length;	/* puke ! */
595		/* This is a data packet */
596		fputs("] ", stdout);
597		do_ppp_print(p, len, len);
598		return;
599	}
600
601	p += 6;
602	length -= 6;
603	if (len > length)
604		len = length;	/* puke ! */
605
606	/*
607	 * A PPPoE tag:
608	 *
609	 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
610	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
611	 * |          TAG_TYPE             |        TAG_LENGTH             |
612	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
613	 * |          TAG_VALUE ...                                        ~
614	 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
615	 */
616
617	while (len >= 4) {
618		tag = ntohs(*(u_short *)p);
619		tlen = ntohs(*(u_short *)(p + 2));
620
621		fputs(" [", stdout);
622		for (f = sizeof tagnames / sizeof tagnames[0] - 1; f >= 0; f--)
623			if (tagnames[f].tag == tag) {
624				asc = tagnames[f].isascii;
625				fputs(tagnames[f].name, stdout);
626        			break;
627      			}
628
629		if (f == -1) {
630			printf("<0x%04x>", tag);
631			asc = -1;
632		}
633
634		p += 4;
635		if (tlen > 0) {
636			if (asc == -1) {
637				for (f = 0; f < tlen; f++)
638					if (!isascii(p[f]))
639						break;
640				asc = f == tlen;
641			}
642			fputc(' ', stdout);
643			if (asc)
644				printf("%.*s", (int)tlen, p);
645			else for (f = 0; f < tlen; f++)
646				printf("%02x", p[f]);
647		}
648		fputc(']', stdout);
649
650		p += tlen;
651		len -= tlen + 4;
652	}
653}
654
655/*
656 * Actually do the job
657 */
658static void
659do_ppp_print(const u_char *p, u_int length, u_int caplen)
660{
661	if (eflag)
662		ppp_hdlc_print(p, length);
663
664	length -= PPP_HDRLEN;
665
666	switch(PPP_PROTOCOL(p)) {
667	case PPP_IP:
668	case ETHERTYPE_IP:
669		ip_print((const u_char *)(p + PPP_HDRLEN), length);
670		break;
671	case PPP_IPX:
672	case ETHERTYPE_IPX:
673		ipx_print((const u_char *)(p + PPP_HDRLEN), length);
674		break;
675
676	default:
677		if(!eflag)
678			ppp_hdlc_print(p, length);
679		if(!xflag)
680			default_print((const u_char *)(p + PPP_HDRLEN),
681					caplen - PPP_HDRLEN);
682	}
683
684	if (xflag)
685		default_print((const u_char *)(p + PPP_HDRLEN),
686				caplen - PPP_HDRLEN);
687out:
688	putchar('\n');
689}
690
691/* proto type to string mapping */
692static struct tok ptype2str[] = {
693	{ PPP_VJC,	"VJC" },
694	{ PPP_VJNC,	"VJNC" },
695	{ PPP_OSI,	"OSI" },
696	{ PPP_LCP,	"LCP" },
697	{ PPP_IPCP,	"IPCP" },
698	{ 0,		NULL }
699};
700
701#define PPP_BSDI_HDRLEN 24
702
703/* BSD/OS specific PPP printer */
704void
705ppp_bsdos_if_print(u_char *user, const struct pcap_pkthdr *h,
706	     register const u_char *p)
707{
708	register u_int length = h->len;
709	register u_int caplen = h->caplen;
710	register int hdrlength;
711	u_short ptype;
712
713	ts_print(&h->ts);
714
715	if (caplen < PPP_BSDI_HDRLEN) {
716		printf("[|ppp]");
717		goto out;
718	}
719
720	/*
721	 * Some printers want to get back at the link level addresses,
722	 * and/or check that they're not walking off the end of the packet.
723	 * Rather than pass them all the way down, we set these globals.
724	 */
725	packetp = p;
726	snapend = p + caplen;
727	hdrlength = 0;
728
729	if (p[0] == PPP_ADDRESS && p[1] == PPP_CONTROL) {
730		if (eflag)
731			printf("%02x %02x ", p[0], p[1]);
732		p += 2;
733		hdrlength = 2;
734	}
735
736	if (eflag)
737		printf("%d ", length);
738	/* Retrieve the protocol type */
739	if (*p & 01) {
740		/* Compressed protocol field */
741		ptype = *p;
742		if (eflag)
743			printf("%02x ", ptype);
744		p++;
745		hdrlength += 1;
746	} else {
747		/* Un-compressed protocol field */
748		ptype = ntohs(*(u_short *)p);
749		if (eflag)
750			printf("%04x ", ptype);
751		p += 2;
752		hdrlength += 2;
753	}
754
755	length -= hdrlength;
756
757	if (ptype == PPP_IP)
758		ip_print(p, length);
759	else
760		printf("%s ", tok2str(ptype2str, "proto-#%d", ptype));
761
762	if (xflag)
763		default_print((const u_char *)p, caplen - hdrlength);
764out:
765	putchar('\n');
766}
767