xref: /netbsd-src/external/bsd/tcpdump/dist/print-sll.c (revision 26ba0b503b498a5194a71ac319838b7f5497f3fe)
10f74e101Schristos /*
20f74e101Schristos  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
30f74e101Schristos  *	The Regents of the University of California.  All rights reserved.
40f74e101Schristos  *
50f74e101Schristos  * Redistribution and use in source and binary forms, with or without
60f74e101Schristos  * modification, are permitted provided that: (1) source code distributions
70f74e101Schristos  * retain the above copyright notice and this paragraph in its entirety, (2)
80f74e101Schristos  * distributions including binary code include the above copyright notice and
90f74e101Schristos  * this paragraph in its entirety in the documentation or other materials
100f74e101Schristos  * provided with the distribution, and (3) all advertising materials mentioning
110f74e101Schristos  * features or use of this software display the following acknowledgement:
120f74e101Schristos  * ``This product includes software developed by the University of California,
130f74e101Schristos  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
140f74e101Schristos  * the University nor the names of its contributors may be used to endorse
150f74e101Schristos  * or promote products derived from this software without specific prior
160f74e101Schristos  * written permission.
170f74e101Schristos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
180f74e101Schristos  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
190f74e101Schristos  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
200f74e101Schristos  */
21b3a00663Schristos 
2211b3aaa1Schristos #include <sys/cdefs.h>
230f74e101Schristos #ifndef lint
24*26ba0b50Schristos __RCSID("$NetBSD: print-sll.c,v 1.11 2024/09/02 16:15:33 christos Exp $");
250f74e101Schristos #endif
260f74e101Schristos 
27dc860a36Sspz /* \summary: Linux cooked sockets capture printer */
28dc860a36Sspz 
29c74ad251Schristos #include <config.h>
300f74e101Schristos 
31c74ad251Schristos #ifdef HAVE_NET_IF_H
32c74ad251Schristos /*
33c74ad251Schristos  * Include diag-control.h before <net/if.h>, which too defines a macro
34c74ad251Schristos  * named ND_UNREACHABLE.
35c74ad251Schristos  */
36c74ad251Schristos #include "diag-control.h"
37c74ad251Schristos #include <net/if.h>
38c74ad251Schristos #endif
390f74e101Schristos 
40c74ad251Schristos #include "netdissect-stdinc.h"
41c74ad251Schristos 
42c74ad251Schristos #define ND_LONGJMP_FROM_TCHECK
43fdccd7e4Schristos #include "netdissect.h"
440f74e101Schristos #include "addrtoname.h"
450f74e101Schristos #include "ethertype.h"
460f74e101Schristos #include "extract.h"
470f74e101Schristos 
48b3a00663Schristos /*
49b3a00663Schristos  * For captures on Linux cooked sockets, we construct a fake header
50b3a00663Schristos  * that includes:
51b3a00663Schristos  *
52b3a00663Schristos  *	a 2-byte "packet type" which is one of:
53b3a00663Schristos  *
54b3a00663Schristos  *		LINUX_SLL_HOST		packet was sent to us
55b3a00663Schristos  *		LINUX_SLL_BROADCAST	packet was broadcast
56b3a00663Schristos  *		LINUX_SLL_MULTICAST	packet was multicast
57b3a00663Schristos  *		LINUX_SLL_OTHERHOST	packet was sent to somebody else
58b3a00663Schristos  *		LINUX_SLL_OUTGOING	packet was sent *by* us;
59b3a00663Schristos  *
60b3a00663Schristos  *	a 2-byte Ethernet protocol field;
61b3a00663Schristos  *
62b3a00663Schristos  *	a 2-byte link-layer type;
63b3a00663Schristos  *
64b3a00663Schristos  *	a 2-byte link-layer address length;
65b3a00663Schristos  *
66b3a00663Schristos  *	an 8-byte source link-layer address, whose actual length is
67b3a00663Schristos  *	specified by the previous value.
68b3a00663Schristos  *
69b3a00663Schristos  * All fields except for the link-layer address are in network byte order.
70b3a00663Schristos  *
71b3a00663Schristos  * DO NOT change the layout of this structure, or change any of the
72b3a00663Schristos  * LINUX_SLL_ values below.  If you must change the link-layer header
73b3a00663Schristos  * for a "cooked" Linux capture, introduce a new DLT_ type (ask
74b3a00663Schristos  * "tcpdump-workers@lists.tcpdump.org" for one, so that you don't give it
75b3a00663Schristos  * a value that collides with a value already being used), and use the
76b3a00663Schristos  * new header in captures of that type, so that programs that can
77b3a00663Schristos  * handle DLT_LINUX_SLL captures will continue to handle them correctly
78b3a00663Schristos  * without any change, and so that capture files with different headers
79b3a00663Schristos  * can be told apart and programs that read them can dissect the
80b3a00663Schristos  * packets in them.
81b3a00663Schristos  *
82b3a00663Schristos  * This structure, and the #defines below, must be the same in the
83b3a00663Schristos  * libpcap and tcpdump versions of "sll.h".
84b3a00663Schristos  */
85b3a00663Schristos 
86b3a00663Schristos /*
87b3a00663Schristos  * A DLT_LINUX_SLL fake link-layer header.
88b3a00663Schristos  */
89b3a00663Schristos #define SLL_HDR_LEN	16		/* total header length */
90b3a00663Schristos #define SLL_ADDRLEN	8		/* length of address field */
91b3a00663Schristos 
92b3a00663Schristos struct sll_header {
93c74ad251Schristos 	nd_uint16_t	sll_pkttype;	/* packet type */
94c74ad251Schristos 	nd_uint16_t	sll_hatype;	/* link-layer address type */
95c74ad251Schristos 	nd_uint16_t	sll_halen;	/* link-layer address length */
96c74ad251Schristos 	nd_byte		sll_addr[SLL_ADDRLEN];	/* link-layer address */
97c74ad251Schristos 	nd_uint16_t	sll_protocol;	/* protocol */
98c74ad251Schristos };
99c74ad251Schristos 
100c74ad251Schristos /*
101c74ad251Schristos  * A DLT_LINUX_SLL2 fake link-layer header.
102c74ad251Schristos  */
103c74ad251Schristos #define SLL2_HDR_LEN	20		/* total header length */
104c74ad251Schristos 
105c74ad251Schristos struct sll2_header {
106c74ad251Schristos 	nd_uint16_t	sll2_protocol;		/* protocol */
107c74ad251Schristos 	nd_uint16_t	sll2_reserved_mbz;	/* reserved - must be zero */
108c74ad251Schristos 	nd_uint32_t	sll2_if_index;		/* 1-based interface index */
109c74ad251Schristos 	nd_uint16_t	sll2_hatype;		/* link-layer address type */
110c74ad251Schristos 	nd_uint8_t	sll2_pkttype;		/* packet type */
111c74ad251Schristos 	nd_uint8_t	sll2_halen;		/* link-layer address length */
112c74ad251Schristos 	nd_byte		sll2_addr[SLL_ADDRLEN];	/* link-layer address */
113b3a00663Schristos };
114b3a00663Schristos 
115b3a00663Schristos /*
116b3a00663Schristos  * The LINUX_SLL_ values for "sll_pkttype"; these correspond to the
117b3a00663Schristos  * PACKET_ values on Linux, but are defined here so that they're
118b3a00663Schristos  * available even on systems other than Linux, and so that they
119b3a00663Schristos  * don't change even if the PACKET_ values change.
120b3a00663Schristos  */
121b3a00663Schristos #define LINUX_SLL_HOST		0
122b3a00663Schristos #define LINUX_SLL_BROADCAST	1
123b3a00663Schristos #define LINUX_SLL_MULTICAST	2
124b3a00663Schristos #define LINUX_SLL_OTHERHOST	3
125b3a00663Schristos #define LINUX_SLL_OUTGOING	4
126b3a00663Schristos 
127b3a00663Schristos /*
128b3a00663Schristos  * The LINUX_SLL_ values for "sll_protocol"; these correspond to the
129b3a00663Schristos  * ETH_P_ values on Linux, but are defined here so that they're
130b3a00663Schristos  * available even on systems other than Linux.  We assume, for now,
131b3a00663Schristos  * that the ETH_P_ values won't change in Linux; if they do, then:
132b3a00663Schristos  *
133b3a00663Schristos  *	if we don't translate them in "pcap-linux.c", capture files
134b3a00663Schristos  *	won't necessarily be readable if captured on a system that
135b3a00663Schristos  *	defines ETH_P_ values that don't match these values;
136b3a00663Schristos  *
137b3a00663Schristos  *	if we do translate them in "pcap-linux.c", that makes life
138b3a00663Schristos  *	unpleasant for the BPF code generator, as the values you test
139b3a00663Schristos  *	for in the kernel aren't the values that you test for when
140b3a00663Schristos  *	reading a capture file, so the fixup code run on BPF programs
141b3a00663Schristos  *	handed to the kernel ends up having to do more work.
142b3a00663Schristos  *
143b3a00663Schristos  * Add other values here as necessary, for handling packet types that
144b3a00663Schristos  * might show up on non-Ethernet, non-802.x networks.  (Not all the ones
145b3a00663Schristos  * in the Linux "if_ether.h" will, I suspect, actually show up in
146b3a00663Schristos  * captures.)
147b3a00663Schristos  */
148b3a00663Schristos #define LINUX_SLL_P_802_3	0x0001	/* Novell 802.3 frames without 802.2 LLC header */
149b3a00663Schristos #define LINUX_SLL_P_802_2	0x0004	/* 802.2 frames (not D/I/X Ethernet) */
1500f74e101Schristos 
151870189d2Schristos static const struct tok sll_pkttype_values[] = {
1520f74e101Schristos     { LINUX_SLL_HOST, "In" },
1530f74e101Schristos     { LINUX_SLL_BROADCAST, "B" },
1540f74e101Schristos     { LINUX_SLL_MULTICAST, "M" },
1550f74e101Schristos     { LINUX_SLL_OTHERHOST, "P" },
1560f74e101Schristos     { LINUX_SLL_OUTGOING, "Out" },
1570f74e101Schristos     { 0, NULL}
1580f74e101Schristos };
1590f74e101Schristos 
160c74ad251Schristos static void
161c74ad251Schristos sll_print(netdissect_options *ndo, const struct sll_header *sllp, u_int length)
1620f74e101Schristos {
1630f74e101Schristos 	u_short ether_type;
1640f74e101Schristos 
165c74ad251Schristos 	ndo->ndo_protocol = "sll";
166c74ad251Schristos         ND_PRINT("%3s ",
167c74ad251Schristos 		 tok2str(sll_pkttype_values,"?",GET_BE_U_2(sllp->sll_pkttype)));
1680f74e101Schristos 
1690f74e101Schristos 	/*
1700f74e101Schristos 	 * XXX - check the link-layer address type value?
1710f74e101Schristos 	 * For now, we just assume 6 means Ethernet.
1720f74e101Schristos 	 * XXX - print others as strings of hex?
1730f74e101Schristos 	 */
174c74ad251Schristos 	if (GET_BE_U_2(sllp->sll_halen) == MAC_ADDR_LEN)
175c74ad251Schristos 		ND_PRINT("%s ", GET_ETHERADDR_STRING(sllp->sll_addr));
1760f74e101Schristos 
177b3a00663Schristos 	if (!ndo->ndo_qflag) {
178c74ad251Schristos 		ether_type = GET_BE_U_2(sllp->sll_protocol);
1790f74e101Schristos 
180c74ad251Schristos 		if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
1810f74e101Schristos 			/*
1820f74e101Schristos 			 * Not an Ethernet type; what type is it?
1830f74e101Schristos 			 */
1840f74e101Schristos 			switch (ether_type) {
1850f74e101Schristos 
1860f74e101Schristos 			case LINUX_SLL_P_802_3:
1870f74e101Schristos 				/*
1880f74e101Schristos 				 * Ethernet_802.3 IPX frame.
1890f74e101Schristos 				 */
190c74ad251Schristos 				ND_PRINT("802.3");
1910f74e101Schristos 				break;
1920f74e101Schristos 
1930f74e101Schristos 			case LINUX_SLL_P_802_2:
1940f74e101Schristos 				/*
1950f74e101Schristos 				 * 802.2.
1960f74e101Schristos 				 */
197c74ad251Schristos 				ND_PRINT("802.2");
1980f74e101Schristos 				break;
1990f74e101Schristos 
2000f74e101Schristos 			default:
2010f74e101Schristos 				/*
2020f74e101Schristos 				 * What is it?
2030f74e101Schristos 				 */
204c74ad251Schristos 				ND_PRINT("ethertype Unknown (0x%04x)",
205c74ad251Schristos 				    ether_type);
2060f74e101Schristos 				break;
2070f74e101Schristos 			}
2080f74e101Schristos 		} else {
209c74ad251Schristos 			ND_PRINT("ethertype %s (0x%04x)",
2100f74e101Schristos 			    tok2str(ethertype_values, "Unknown", ether_type),
211c74ad251Schristos 			    ether_type);
2120f74e101Schristos 		}
213c74ad251Schristos 		ND_PRINT(", length %u: ", length);
2140f74e101Schristos 	}
2150f74e101Schristos }
2160f74e101Schristos 
2170f74e101Schristos /*
2180f74e101Schristos  * This is the top level routine of the printer.  'p' points to the
2190f74e101Schristos  * Linux "cooked capture" header of the packet, 'h->ts' is the timestamp,
2200f74e101Schristos  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
2210f74e101Schristos  * is the number of bytes actually captured.
2220f74e101Schristos  */
223c74ad251Schristos void
224b3a00663Schristos sll_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
2250f74e101Schristos {
2260f74e101Schristos 	u_int caplen = h->caplen;
2270f74e101Schristos 	u_int length = h->len;
228c74ad251Schristos 	const struct sll_header *sllp;
229817e9a7eSchristos 	u_short hatype;
2300f74e101Schristos 	u_short ether_type;
231fdccd7e4Schristos 	int llc_hdrlen;
232fdccd7e4Schristos 	u_int hdrlen;
2330f74e101Schristos 
234c74ad251Schristos 	ndo->ndo_protocol = "sll";
235c74ad251Schristos 	ND_TCHECK_LEN(p, SLL_HDR_LEN);
2360f74e101Schristos 
2370f74e101Schristos 	sllp = (const struct sll_header *)p;
2380f74e101Schristos 
239b3a00663Schristos 	if (ndo->ndo_eflag)
240b3a00663Schristos 		sll_print(ndo, sllp, length);
2410f74e101Schristos 
2420f74e101Schristos 	/*
2430f74e101Schristos 	 * Go past the cooked-mode header.
2440f74e101Schristos 	 */
2450f74e101Schristos 	length -= SLL_HDR_LEN;
2460f74e101Schristos 	caplen -= SLL_HDR_LEN;
2470f74e101Schristos 	p += SLL_HDR_LEN;
248fdccd7e4Schristos 	hdrlen = SLL_HDR_LEN;
2490f74e101Schristos 
250c74ad251Schristos 	hatype = GET_BE_U_2(sllp->sll_hatype);
251817e9a7eSchristos 	switch (hatype) {
252817e9a7eSchristos 
253817e9a7eSchristos 	case 803:
254817e9a7eSchristos 		/*
255817e9a7eSchristos 		 * This is an packet with a radiotap header;
256817e9a7eSchristos 		 * just dissect the payload as such.
257817e9a7eSchristos 		 */
258c74ad251Schristos 		ndo->ndo_ll_hdr_len += SLL_HDR_LEN;
259c74ad251Schristos 		ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, length, caplen);
260c74ad251Schristos 		return;
261817e9a7eSchristos 	}
262c74ad251Schristos 	ether_type = GET_BE_U_2(sllp->sll_protocol);
2630f74e101Schristos 
2640f74e101Schristos recurse:
2650f74e101Schristos 	/*
2660f74e101Schristos 	 * Is it (gag) an 802.3 encapsulation, or some non-Ethernet
2670f74e101Schristos 	 * packet type?
2680f74e101Schristos 	 */
269c74ad251Schristos 	if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
2700f74e101Schristos 		/*
2710f74e101Schristos 		 * Yes - what type is it?
2720f74e101Schristos 		 */
2730f74e101Schristos 		switch (ether_type) {
2740f74e101Schristos 
2750f74e101Schristos 		case LINUX_SLL_P_802_3:
2760f74e101Schristos 			/*
2770f74e101Schristos 			 * Ethernet_802.3 IPX frame.
2780f74e101Schristos 			 */
279b3a00663Schristos 			ipx_print(ndo, p, length);
2800f74e101Schristos 			break;
2810f74e101Schristos 
2820f74e101Schristos 		case LINUX_SLL_P_802_2:
2830f74e101Schristos 			/*
2840f74e101Schristos 			 * 802.2.
2850f74e101Schristos 			 * Try to print the LLC-layer header & higher layers.
2860f74e101Schristos 			 */
287fdccd7e4Schristos 			llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL);
288fdccd7e4Schristos 			if (llc_hdrlen < 0)
2890f74e101Schristos 				goto unknown;	/* unknown LLC type */
290fdccd7e4Schristos 			hdrlen += llc_hdrlen;
2910f74e101Schristos 			break;
2920f74e101Schristos 
2930f74e101Schristos 		default:
2940f74e101Schristos 			/*FALLTHROUGH*/
2950f74e101Schristos 
2960f74e101Schristos 		unknown:
297fdccd7e4Schristos 			/* packet type not known, print raw packet */
298b3a00663Schristos 			if (!ndo->ndo_suppress_default_print)
299b3a00663Schristos 				ND_DEFAULTPRINT(p, caplen);
3000f74e101Schristos 			break;
3010f74e101Schristos 		}
3020f74e101Schristos 	} else if (ether_type == ETHERTYPE_8021Q) {
3030f74e101Schristos 		/*
3040f74e101Schristos 		 * Print VLAN information, and then go back and process
3050f74e101Schristos 		 * the enclosed type field.
3060f74e101Schristos 		 */
307fdccd7e4Schristos 		if (caplen < 4) {
308c74ad251Schristos 			ndo->ndo_protocol = "vlan";
309c74ad251Schristos 			nd_print_trunc(ndo);
310c74ad251Schristos 			ndo->ndo_ll_hdr_len += hdrlen + caplen;
311c74ad251Schristos 			return;
3120f74e101Schristos 		}
313b3a00663Schristos 	        if (ndo->ndo_eflag) {
314c74ad251Schristos 			uint16_t tag = GET_BE_U_2(p);
3150f74e101Schristos 
316c74ad251Schristos 			ND_PRINT("%s, ", ieee8021q_tci_string(tag));
3170f74e101Schristos 		}
3180f74e101Schristos 
319c74ad251Schristos 		ether_type = GET_BE_U_2(p + 2);
320c74ad251Schristos 		if (ether_type <= MAX_ETHERNET_LENGTH_VAL)
3210f74e101Schristos 			ether_type = LINUX_SLL_P_802_2;
322b3a00663Schristos 		if (!ndo->ndo_qflag) {
323c74ad251Schristos 			ND_PRINT("ethertype %s, ",
324c74ad251Schristos 			    tok2str(ethertype_values, "Unknown", ether_type));
3250f74e101Schristos 		}
3260f74e101Schristos 		p += 4;
3270f74e101Schristos 		length -= 4;
3280f74e101Schristos 		caplen -= 4;
329fdccd7e4Schristos 		hdrlen += 4;
3300f74e101Schristos 		goto recurse;
3310f74e101Schristos 	} else {
332dc860a36Sspz 		if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) {
3330f74e101Schristos 			/* ether_type not known, print raw packet */
334b3a00663Schristos 			if (!ndo->ndo_eflag)
335b3a00663Schristos 				sll_print(ndo, sllp, length + SLL_HDR_LEN);
336b3a00663Schristos 			if (!ndo->ndo_suppress_default_print)
337b3a00663Schristos 				ND_DEFAULTPRINT(p, caplen);
3380f74e101Schristos 		}
3390f74e101Schristos 	}
3400f74e101Schristos 
341c74ad251Schristos 	ndo->ndo_ll_hdr_len += hdrlen;
342c74ad251Schristos }
343c74ad251Schristos 
344c74ad251Schristos static void
345c74ad251Schristos sll2_print(netdissect_options *ndo, const struct sll2_header *sllp, u_int length)
346c74ad251Schristos {
347c74ad251Schristos 	u_short ether_type;
348c74ad251Schristos 
349c74ad251Schristos 	ndo->ndo_protocol = "sll2";
350c74ad251Schristos 	ND_PRINT("ifindex %u ", GET_BE_U_4(sllp->sll2_if_index));
351c74ad251Schristos 
352c74ad251Schristos 	/*
353c74ad251Schristos 	 * XXX - check the link-layer address type value?
354c74ad251Schristos 	 * For now, we just assume 6 means Ethernet.
355c74ad251Schristos 	 * XXX - print others as strings of hex?
356c74ad251Schristos 	 */
357c74ad251Schristos 	if (GET_U_1(sllp->sll2_halen) == MAC_ADDR_LEN)
358c74ad251Schristos 		ND_PRINT("%s ", GET_ETHERADDR_STRING(sllp->sll2_addr));
359c74ad251Schristos 
360c74ad251Schristos 	if (!ndo->ndo_qflag) {
361c74ad251Schristos 		ether_type = GET_BE_U_2(sllp->sll2_protocol);
362c74ad251Schristos 
363c74ad251Schristos 		if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
364c74ad251Schristos 			/*
365c74ad251Schristos 			 * Not an Ethernet type; what type is it?
366c74ad251Schristos 			 */
367c74ad251Schristos 			switch (ether_type) {
368c74ad251Schristos 
369c74ad251Schristos 			case LINUX_SLL_P_802_3:
370c74ad251Schristos 				/*
371c74ad251Schristos 				 * Ethernet_802.3 IPX frame.
372c74ad251Schristos 				 */
373c74ad251Schristos 				ND_PRINT("802.3");
374c74ad251Schristos 				break;
375c74ad251Schristos 
376c74ad251Schristos 			case LINUX_SLL_P_802_2:
377c74ad251Schristos 				/*
378c74ad251Schristos 				 * 802.2.
379c74ad251Schristos 				 */
380c74ad251Schristos 				ND_PRINT("802.2");
381c74ad251Schristos 				break;
382c74ad251Schristos 
383c74ad251Schristos 			default:
384c74ad251Schristos 				/*
385c74ad251Schristos 				 * What is it?
386c74ad251Schristos 				 */
387c74ad251Schristos 				ND_PRINT("ethertype Unknown (0x%04x)",
388c74ad251Schristos 				    ether_type);
389c74ad251Schristos 				break;
390c74ad251Schristos 			}
391c74ad251Schristos 		} else {
392c74ad251Schristos 			ND_PRINT("ethertype %s (0x%04x)",
393c74ad251Schristos 			    tok2str(ethertype_values, "Unknown", ether_type),
394c74ad251Schristos 			    ether_type);
395c74ad251Schristos 		}
396c74ad251Schristos 		ND_PRINT(", length %u: ", length);
397c74ad251Schristos 	}
398c74ad251Schristos }
399c74ad251Schristos 
400c74ad251Schristos /*
401c74ad251Schristos  * This is the top level routine of the printer.  'p' points to the
402c74ad251Schristos  * Linux "cooked capture" header of the packet, 'h->ts' is the timestamp,
403c74ad251Schristos  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
404c74ad251Schristos  * is the number of bytes actually captured.
405c74ad251Schristos  */
406c74ad251Schristos void
407c74ad251Schristos sll2_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
408c74ad251Schristos {
409c74ad251Schristos 	u_int caplen = h->caplen;
410c74ad251Schristos 	u_int length = h->len;
411c74ad251Schristos 	const struct sll2_header *sllp;
412c74ad251Schristos 	u_short hatype;
413c74ad251Schristos 	u_short ether_type;
414c74ad251Schristos 	int llc_hdrlen;
415c74ad251Schristos 	u_int hdrlen;
416c74ad251Schristos #ifdef HAVE_NET_IF_H
417c74ad251Schristos 	uint32_t if_index;
418c74ad251Schristos 	char ifname[IF_NAMESIZE];
419c74ad251Schristos #endif
420c74ad251Schristos 
421c74ad251Schristos 	ndo->ndo_protocol = "sll2";
422c74ad251Schristos 	ND_TCHECK_LEN(p, SLL2_HDR_LEN);
423c74ad251Schristos 
424c74ad251Schristos 	sllp = (const struct sll2_header *)p;
425c74ad251Schristos #ifdef HAVE_NET_IF_H
426c74ad251Schristos 	if_index = GET_BE_U_4(sllp->sll2_if_index);
427c74ad251Schristos 	if (!if_indextoname(if_index, ifname))
428c74ad251Schristos 		strncpy(ifname, "?", 2);
429c74ad251Schristos 	ND_PRINT("%-5s ", ifname);
430c74ad251Schristos #endif
431c74ad251Schristos 
432c74ad251Schristos 	ND_PRINT("%-3s ",
433c74ad251Schristos 		 tok2str(sll_pkttype_values, "?", GET_U_1(sllp->sll2_pkttype)));
434c74ad251Schristos 
435c74ad251Schristos 	if (ndo->ndo_eflag)
436c74ad251Schristos 		sll2_print(ndo, sllp, length);
437c74ad251Schristos 
438c74ad251Schristos 	/*
439c74ad251Schristos 	 * Go past the cooked-mode header.
440c74ad251Schristos 	 */
441c74ad251Schristos 	length -= SLL2_HDR_LEN;
442c74ad251Schristos 	caplen -= SLL2_HDR_LEN;
443c74ad251Schristos 	p += SLL2_HDR_LEN;
444c74ad251Schristos 	hdrlen = SLL2_HDR_LEN;
445c74ad251Schristos 
446c74ad251Schristos 	hatype = GET_BE_U_2(sllp->sll2_hatype);
447c74ad251Schristos 	switch (hatype) {
448c74ad251Schristos 
449c74ad251Schristos 	case 803:
450c74ad251Schristos 		/*
451c74ad251Schristos 		 * This is an packet with a radiotap header;
452c74ad251Schristos 		 * just dissect the payload as such.
453c74ad251Schristos 		 */
454c74ad251Schristos 		ndo->ndo_ll_hdr_len += SLL2_HDR_LEN;
455c74ad251Schristos 		ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, length, caplen);
456c74ad251Schristos 		return;
457c74ad251Schristos 	}
458c74ad251Schristos 	ether_type = GET_BE_U_2(sllp->sll2_protocol);
459c74ad251Schristos 
460c74ad251Schristos recurse:
461c74ad251Schristos 	/*
462c74ad251Schristos 	 * Is it (gag) an 802.3 encapsulation, or some non-Ethernet
463c74ad251Schristos 	 * packet type?
464c74ad251Schristos 	 */
465c74ad251Schristos 	if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
466c74ad251Schristos 		/*
467c74ad251Schristos 		 * Yes - what type is it?
468c74ad251Schristos 		 */
469c74ad251Schristos 		switch (ether_type) {
470c74ad251Schristos 
471c74ad251Schristos 		case LINUX_SLL_P_802_3:
472c74ad251Schristos 			/*
473c74ad251Schristos 			 * Ethernet_802.3 IPX frame.
474c74ad251Schristos 			 */
475c74ad251Schristos 			ipx_print(ndo, p, length);
476c74ad251Schristos 			break;
477c74ad251Schristos 
478c74ad251Schristos 		case LINUX_SLL_P_802_2:
479c74ad251Schristos 			/*
480c74ad251Schristos 			 * 802.2.
481c74ad251Schristos 			 * Try to print the LLC-layer header & higher layers.
482c74ad251Schristos 			 */
483c74ad251Schristos 			llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL);
484c74ad251Schristos 			if (llc_hdrlen < 0)
485c74ad251Schristos 				goto unknown;	/* unknown LLC type */
486c74ad251Schristos 			hdrlen += llc_hdrlen;
487c74ad251Schristos 			break;
488c74ad251Schristos 
489c74ad251Schristos 		default:
490c74ad251Schristos 			/*FALLTHROUGH*/
491c74ad251Schristos 
492c74ad251Schristos 		unknown:
493c74ad251Schristos 			/* packet type not known, print raw packet */
494c74ad251Schristos 			if (!ndo->ndo_suppress_default_print)
495c74ad251Schristos 				ND_DEFAULTPRINT(p, caplen);
496c74ad251Schristos 			break;
497c74ad251Schristos 		}
498c74ad251Schristos 	} else if (ether_type == ETHERTYPE_8021Q) {
499c74ad251Schristos 		/*
500c74ad251Schristos 		 * Print VLAN information, and then go back and process
501c74ad251Schristos 		 * the enclosed type field.
502c74ad251Schristos 		 */
503c74ad251Schristos 		if (caplen < 4) {
504c74ad251Schristos 			ndo->ndo_protocol = "vlan";
505c74ad251Schristos 			nd_print_trunc(ndo);
506c74ad251Schristos 			ndo->ndo_ll_hdr_len += hdrlen + caplen;
507c74ad251Schristos 			return;
508c74ad251Schristos 		}
509c74ad251Schristos 	        if (ndo->ndo_eflag) {
510c74ad251Schristos 			uint16_t tag = GET_BE_U_2(p);
511c74ad251Schristos 
512c74ad251Schristos 			ND_PRINT("%s, ", ieee8021q_tci_string(tag));
513c74ad251Schristos 		}
514c74ad251Schristos 
515c74ad251Schristos 		ether_type = GET_BE_U_2(p + 2);
516c74ad251Schristos 		if (ether_type <= MAX_ETHERNET_LENGTH_VAL)
517c74ad251Schristos 			ether_type = LINUX_SLL_P_802_2;
518c74ad251Schristos 		if (!ndo->ndo_qflag) {
519c74ad251Schristos 			ND_PRINT("ethertype %s, ",
520c74ad251Schristos 			    tok2str(ethertype_values, "Unknown", ether_type));
521c74ad251Schristos 		}
522c74ad251Schristos 		p += 4;
523c74ad251Schristos 		length -= 4;
524c74ad251Schristos 		caplen -= 4;
525c74ad251Schristos 		hdrlen += 4;
526c74ad251Schristos 		goto recurse;
527c74ad251Schristos 	} else {
528c74ad251Schristos 		if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) {
529c74ad251Schristos 			/* ether_type not known, print raw packet */
530c74ad251Schristos 			if (!ndo->ndo_eflag)
531c74ad251Schristos 				sll2_print(ndo, sllp, length + SLL2_HDR_LEN);
532c74ad251Schristos 			if (!ndo->ndo_suppress_default_print)
533c74ad251Schristos 				ND_DEFAULTPRINT(p, caplen);
534c74ad251Schristos 		}
535c74ad251Schristos 	}
536c74ad251Schristos 
537c74ad251Schristos 	ndo->ndo_ll_hdr_len += hdrlen;
5380f74e101Schristos }
539