xref: /dflybsd-src/contrib/tcpdump/print-sll.c (revision 59c07fbdf8168fa08c76c515186d561b5a92690c)
141c99275SPeter Avalos /*
241c99275SPeter Avalos  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
341c99275SPeter Avalos  *	The Regents of the University of California.  All rights reserved.
441c99275SPeter Avalos  *
541c99275SPeter Avalos  * Redistribution and use in source and binary forms, with or without
641c99275SPeter Avalos  * modification, are permitted provided that: (1) source code distributions
741c99275SPeter Avalos  * retain the above copyright notice and this paragraph in its entirety, (2)
841c99275SPeter Avalos  * distributions including binary code include the above copyright notice and
941c99275SPeter Avalos  * this paragraph in its entirety in the documentation or other materials
1041c99275SPeter Avalos  * provided with the distribution, and (3) all advertising materials mentioning
1141c99275SPeter Avalos  * features or use of this software display the following acknowledgement:
1241c99275SPeter Avalos  * ``This product includes software developed by the University of California,
1341c99275SPeter Avalos  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1441c99275SPeter Avalos  * the University nor the names of its contributors may be used to endorse
1541c99275SPeter Avalos  * or promote products derived from this software without specific prior
1641c99275SPeter Avalos  * written permission.
1741c99275SPeter Avalos  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1841c99275SPeter Avalos  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1941c99275SPeter Avalos  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2041c99275SPeter Avalos  */
21411677aeSAaron LI 
22411677aeSAaron LI /* \summary: Linux cooked sockets capture printer */
2341c99275SPeter Avalos 
2441c99275SPeter Avalos #ifdef HAVE_CONFIG_H
25*ed775ee7SAntonio Huete Jimenez #include <config.h>
2641c99275SPeter Avalos #endif
2741c99275SPeter Avalos 
28*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_NET_IF_H
29*ed775ee7SAntonio Huete Jimenez #include <net/if.h>
30*ed775ee7SAntonio Huete Jimenez #endif
3141c99275SPeter Avalos 
32*ed775ee7SAntonio Huete Jimenez #include "netdissect-stdinc.h"
33*ed775ee7SAntonio Huete Jimenez 
34*ed775ee7SAntonio Huete Jimenez #define ND_LONGJMP_FROM_TCHECK
35411677aeSAaron LI #include "netdissect.h"
3641c99275SPeter Avalos #include "addrtoname.h"
3741c99275SPeter Avalos #include "ethertype.h"
3841c99275SPeter Avalos #include "extract.h"
3941c99275SPeter Avalos 
40411677aeSAaron LI /*
41411677aeSAaron LI  * For captures on Linux cooked sockets, we construct a fake header
42411677aeSAaron LI  * that includes:
43411677aeSAaron LI  *
44411677aeSAaron LI  *	a 2-byte "packet type" which is one of:
45411677aeSAaron LI  *
46411677aeSAaron LI  *		LINUX_SLL_HOST		packet was sent to us
47411677aeSAaron LI  *		LINUX_SLL_BROADCAST	packet was broadcast
48411677aeSAaron LI  *		LINUX_SLL_MULTICAST	packet was multicast
49411677aeSAaron LI  *		LINUX_SLL_OTHERHOST	packet was sent to somebody else
50411677aeSAaron LI  *		LINUX_SLL_OUTGOING	packet was sent *by* us;
51411677aeSAaron LI  *
52411677aeSAaron LI  *	a 2-byte Ethernet protocol field;
53411677aeSAaron LI  *
54411677aeSAaron LI  *	a 2-byte link-layer type;
55411677aeSAaron LI  *
56411677aeSAaron LI  *	a 2-byte link-layer address length;
57411677aeSAaron LI  *
58411677aeSAaron LI  *	an 8-byte source link-layer address, whose actual length is
59411677aeSAaron LI  *	specified by the previous value.
60411677aeSAaron LI  *
61411677aeSAaron LI  * All fields except for the link-layer address are in network byte order.
62411677aeSAaron LI  *
63411677aeSAaron LI  * DO NOT change the layout of this structure, or change any of the
64411677aeSAaron LI  * LINUX_SLL_ values below.  If you must change the link-layer header
65411677aeSAaron LI  * for a "cooked" Linux capture, introduce a new DLT_ type (ask
66411677aeSAaron LI  * "tcpdump-workers@lists.tcpdump.org" for one, so that you don't give it
67411677aeSAaron LI  * a value that collides with a value already being used), and use the
68411677aeSAaron LI  * new header in captures of that type, so that programs that can
69411677aeSAaron LI  * handle DLT_LINUX_SLL captures will continue to handle them correctly
70411677aeSAaron LI  * without any change, and so that capture files with different headers
71411677aeSAaron LI  * can be told apart and programs that read them can dissect the
72411677aeSAaron LI  * packets in them.
73411677aeSAaron LI  *
74411677aeSAaron LI  * This structure, and the #defines below, must be the same in the
75411677aeSAaron LI  * libpcap and tcpdump versions of "sll.h".
76411677aeSAaron LI  */
77411677aeSAaron LI 
78411677aeSAaron LI /*
79411677aeSAaron LI  * A DLT_LINUX_SLL fake link-layer header.
80411677aeSAaron LI  */
81411677aeSAaron LI #define SLL_HDR_LEN	16		/* total header length */
82411677aeSAaron LI #define SLL_ADDRLEN	8		/* length of address field */
83411677aeSAaron LI 
84411677aeSAaron LI struct sll_header {
85*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	sll_pkttype;	/* packet type */
86*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	sll_hatype;	/* link-layer address type */
87*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	sll_halen;	/* link-layer address length */
88*ed775ee7SAntonio Huete Jimenez 	nd_byte		sll_addr[SLL_ADDRLEN];	/* link-layer address */
89*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	sll_protocol;	/* protocol */
90*ed775ee7SAntonio Huete Jimenez };
91*ed775ee7SAntonio Huete Jimenez 
92*ed775ee7SAntonio Huete Jimenez /*
93*ed775ee7SAntonio Huete Jimenez  * A DLT_LINUX_SLL2 fake link-layer header.
94*ed775ee7SAntonio Huete Jimenez  */
95*ed775ee7SAntonio Huete Jimenez #define SLL2_HDR_LEN	20		/* total header length */
96*ed775ee7SAntonio Huete Jimenez 
97*ed775ee7SAntonio Huete Jimenez struct sll2_header {
98*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	sll2_protocol;		/* protocol */
99*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	sll2_reserved_mbz;	/* reserved - must be zero */
100*ed775ee7SAntonio Huete Jimenez 	nd_uint32_t	sll2_if_index;		/* 1-based interface index */
101*ed775ee7SAntonio Huete Jimenez 	nd_uint16_t	sll2_hatype;		/* link-layer address type */
102*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	sll2_pkttype;		/* packet type */
103*ed775ee7SAntonio Huete Jimenez 	nd_uint8_t	sll2_halen;		/* link-layer address length */
104*ed775ee7SAntonio Huete Jimenez 	nd_byte		sll2_addr[SLL_ADDRLEN];	/* link-layer address */
105411677aeSAaron LI };
106411677aeSAaron LI 
107411677aeSAaron LI /*
108411677aeSAaron LI  * The LINUX_SLL_ values for "sll_pkttype"; these correspond to the
109411677aeSAaron LI  * PACKET_ values on Linux, but are defined here so that they're
110411677aeSAaron LI  * available even on systems other than Linux, and so that they
111411677aeSAaron LI  * don't change even if the PACKET_ values change.
112411677aeSAaron LI  */
113411677aeSAaron LI #define LINUX_SLL_HOST		0
114411677aeSAaron LI #define LINUX_SLL_BROADCAST	1
115411677aeSAaron LI #define LINUX_SLL_MULTICAST	2
116411677aeSAaron LI #define LINUX_SLL_OTHERHOST	3
117411677aeSAaron LI #define LINUX_SLL_OUTGOING	4
118411677aeSAaron LI 
119411677aeSAaron LI /*
120411677aeSAaron LI  * The LINUX_SLL_ values for "sll_protocol"; these correspond to the
121411677aeSAaron LI  * ETH_P_ values on Linux, but are defined here so that they're
122411677aeSAaron LI  * available even on systems other than Linux.  We assume, for now,
123411677aeSAaron LI  * that the ETH_P_ values won't change in Linux; if they do, then:
124411677aeSAaron LI  *
125411677aeSAaron LI  *	if we don't translate them in "pcap-linux.c", capture files
126411677aeSAaron LI  *	won't necessarily be readable if captured on a system that
127411677aeSAaron LI  *	defines ETH_P_ values that don't match these values;
128411677aeSAaron LI  *
129411677aeSAaron LI  *	if we do translate them in "pcap-linux.c", that makes life
130411677aeSAaron LI  *	unpleasant for the BPF code generator, as the values you test
131411677aeSAaron LI  *	for in the kernel aren't the values that you test for when
132411677aeSAaron LI  *	reading a capture file, so the fixup code run on BPF programs
133411677aeSAaron LI  *	handed to the kernel ends up having to do more work.
134411677aeSAaron LI  *
135411677aeSAaron LI  * Add other values here as necessary, for handling packet types that
136411677aeSAaron LI  * might show up on non-Ethernet, non-802.x networks.  (Not all the ones
137411677aeSAaron LI  * in the Linux "if_ether.h" will, I suspect, actually show up in
138411677aeSAaron LI  * captures.)
139411677aeSAaron LI  */
140411677aeSAaron LI #define LINUX_SLL_P_802_3	0x0001	/* Novell 802.3 frames without 802.2 LLC header */
141411677aeSAaron LI #define LINUX_SLL_P_802_2	0x0004	/* 802.2 frames (not D/I/X Ethernet) */
142411677aeSAaron LI 
143411677aeSAaron LI static const struct tok sll_pkttype_values[] = {
14441c99275SPeter Avalos     { LINUX_SLL_HOST, "In" },
14541c99275SPeter Avalos     { LINUX_SLL_BROADCAST, "B" },
14641c99275SPeter Avalos     { LINUX_SLL_MULTICAST, "M" },
14741c99275SPeter Avalos     { LINUX_SLL_OTHERHOST, "P" },
14841c99275SPeter Avalos     { LINUX_SLL_OUTGOING, "Out" },
14941c99275SPeter Avalos     { 0, NULL}
15041c99275SPeter Avalos };
15141c99275SPeter Avalos 
152*ed775ee7SAntonio Huete Jimenez static void
sll_print(netdissect_options * ndo,const struct sll_header * sllp,u_int length)153*ed775ee7SAntonio Huete Jimenez sll_print(netdissect_options *ndo, const struct sll_header *sllp, u_int length)
15441c99275SPeter Avalos {
15541c99275SPeter Avalos 	u_short ether_type;
15641c99275SPeter Avalos 
157*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "sll";
158*ed775ee7SAntonio Huete Jimenez         ND_PRINT("%3s ",
159*ed775ee7SAntonio Huete Jimenez 		 tok2str(sll_pkttype_values,"?",GET_BE_U_2(sllp->sll_pkttype)));
16041c99275SPeter Avalos 
16141c99275SPeter Avalos 	/*
16241c99275SPeter Avalos 	 * XXX - check the link-layer address type value?
16341c99275SPeter Avalos 	 * For now, we just assume 6 means Ethernet.
16441c99275SPeter Avalos 	 * XXX - print others as strings of hex?
16541c99275SPeter Avalos 	 */
166*ed775ee7SAntonio Huete Jimenez 	if (GET_BE_U_2(sllp->sll_halen) == MAC_ADDR_LEN)
167*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%s ", GET_ETHERADDR_STRING(sllp->sll_addr));
16841c99275SPeter Avalos 
169411677aeSAaron LI 	if (!ndo->ndo_qflag) {
170*ed775ee7SAntonio Huete Jimenez 		ether_type = GET_BE_U_2(sllp->sll_protocol);
17141c99275SPeter Avalos 
172*ed775ee7SAntonio Huete Jimenez 		if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
17341c99275SPeter Avalos 			/*
17441c99275SPeter Avalos 			 * Not an Ethernet type; what type is it?
17541c99275SPeter Avalos 			 */
17641c99275SPeter Avalos 			switch (ether_type) {
17741c99275SPeter Avalos 
17841c99275SPeter Avalos 			case LINUX_SLL_P_802_3:
17941c99275SPeter Avalos 				/*
18041c99275SPeter Avalos 				 * Ethernet_802.3 IPX frame.
18141c99275SPeter Avalos 				 */
182*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("802.3");
18341c99275SPeter Avalos 				break;
18441c99275SPeter Avalos 
18541c99275SPeter Avalos 			case LINUX_SLL_P_802_2:
18641c99275SPeter Avalos 				/*
18741c99275SPeter Avalos 				 * 802.2.
18841c99275SPeter Avalos 				 */
189*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("802.2");
19041c99275SPeter Avalos 				break;
19141c99275SPeter Avalos 
19241c99275SPeter Avalos 			default:
19341c99275SPeter Avalos 				/*
19441c99275SPeter Avalos 				 * What is it?
19541c99275SPeter Avalos 				 */
196*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("ethertype Unknown (0x%04x)",
197*ed775ee7SAntonio Huete Jimenez 				    ether_type);
19841c99275SPeter Avalos 				break;
19941c99275SPeter Avalos 			}
20041c99275SPeter Avalos 		} else {
201*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("ethertype %s (0x%04x)",
20241c99275SPeter Avalos 			    tok2str(ethertype_values, "Unknown", ether_type),
203*ed775ee7SAntonio Huete Jimenez 			    ether_type);
20441c99275SPeter Avalos 		}
205*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", length %u: ", length);
20641c99275SPeter Avalos 	}
20741c99275SPeter Avalos }
20841c99275SPeter Avalos 
20941c99275SPeter Avalos /*
21041c99275SPeter Avalos  * This is the top level routine of the printer.  'p' points to the
21141c99275SPeter Avalos  * Linux "cooked capture" header of the packet, 'h->ts' is the timestamp,
21241c99275SPeter Avalos  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
21341c99275SPeter Avalos  * is the number of bytes actually captured.
21441c99275SPeter Avalos  */
215*ed775ee7SAntonio Huete Jimenez void
sll_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)216411677aeSAaron LI sll_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
21741c99275SPeter Avalos {
21841c99275SPeter Avalos 	u_int caplen = h->caplen;
21941c99275SPeter Avalos 	u_int length = h->len;
220*ed775ee7SAntonio Huete Jimenez 	const struct sll_header *sllp;
221411677aeSAaron LI 	u_short hatype;
22241c99275SPeter Avalos 	u_short ether_type;
223411677aeSAaron LI 	int llc_hdrlen;
224411677aeSAaron LI 	u_int hdrlen;
22541c99275SPeter Avalos 
226*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "sll";
227*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(p, SLL_HDR_LEN);
22841c99275SPeter Avalos 
22941c99275SPeter Avalos 	sllp = (const struct sll_header *)p;
23041c99275SPeter Avalos 
231411677aeSAaron LI 	if (ndo->ndo_eflag)
232411677aeSAaron LI 		sll_print(ndo, sllp, length);
23341c99275SPeter Avalos 
23441c99275SPeter Avalos 	/*
23541c99275SPeter Avalos 	 * Go past the cooked-mode header.
23641c99275SPeter Avalos 	 */
23741c99275SPeter Avalos 	length -= SLL_HDR_LEN;
23841c99275SPeter Avalos 	caplen -= SLL_HDR_LEN;
23941c99275SPeter Avalos 	p += SLL_HDR_LEN;
240411677aeSAaron LI 	hdrlen = SLL_HDR_LEN;
24141c99275SPeter Avalos 
242*ed775ee7SAntonio Huete Jimenez 	hatype = GET_BE_U_2(sllp->sll_hatype);
243411677aeSAaron LI 	switch (hatype) {
244411677aeSAaron LI 
245411677aeSAaron LI 	case 803:
246411677aeSAaron LI 		/*
247411677aeSAaron LI 		 * This is an packet with a radiotap header;
248411677aeSAaron LI 		 * just dissect the payload as such.
249411677aeSAaron LI 		 */
250*ed775ee7SAntonio Huete Jimenez 		ndo->ndo_ll_hdr_len += SLL_HDR_LEN;
251*ed775ee7SAntonio Huete Jimenez 		ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, length, caplen);
252*ed775ee7SAntonio Huete Jimenez 		return;
253411677aeSAaron LI 	}
254*ed775ee7SAntonio Huete Jimenez 	ether_type = GET_BE_U_2(sllp->sll_protocol);
25541c99275SPeter Avalos 
25627bfbee1SPeter Avalos recurse:
25741c99275SPeter Avalos 	/*
25841c99275SPeter Avalos 	 * Is it (gag) an 802.3 encapsulation, or some non-Ethernet
25941c99275SPeter Avalos 	 * packet type?
26041c99275SPeter Avalos 	 */
261*ed775ee7SAntonio Huete Jimenez 	if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
26241c99275SPeter Avalos 		/*
26341c99275SPeter Avalos 		 * Yes - what type is it?
26441c99275SPeter Avalos 		 */
26541c99275SPeter Avalos 		switch (ether_type) {
26641c99275SPeter Avalos 
26741c99275SPeter Avalos 		case LINUX_SLL_P_802_3:
26841c99275SPeter Avalos 			/*
26941c99275SPeter Avalos 			 * Ethernet_802.3 IPX frame.
27041c99275SPeter Avalos 			 */
271411677aeSAaron LI 			ipx_print(ndo, p, length);
27241c99275SPeter Avalos 			break;
27341c99275SPeter Avalos 
27441c99275SPeter Avalos 		case LINUX_SLL_P_802_2:
27541c99275SPeter Avalos 			/*
27641c99275SPeter Avalos 			 * 802.2.
27741c99275SPeter Avalos 			 * Try to print the LLC-layer header & higher layers.
27841c99275SPeter Avalos 			 */
279411677aeSAaron LI 			llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL);
280411677aeSAaron LI 			if (llc_hdrlen < 0)
28141c99275SPeter Avalos 				goto unknown;	/* unknown LLC type */
282411677aeSAaron LI 			hdrlen += llc_hdrlen;
28341c99275SPeter Avalos 			break;
28441c99275SPeter Avalos 
28541c99275SPeter Avalos 		default:
28641c99275SPeter Avalos 			/*FALLTHROUGH*/
28741c99275SPeter Avalos 
28841c99275SPeter Avalos 		unknown:
289411677aeSAaron LI 			/* packet type not known, print raw packet */
290411677aeSAaron LI 			if (!ndo->ndo_suppress_default_print)
291411677aeSAaron LI 				ND_DEFAULTPRINT(p, caplen);
29241c99275SPeter Avalos 			break;
29341c99275SPeter Avalos 		}
29427bfbee1SPeter Avalos 	} else if (ether_type == ETHERTYPE_8021Q) {
29527bfbee1SPeter Avalos 		/*
29627bfbee1SPeter Avalos 		 * Print VLAN information, and then go back and process
29727bfbee1SPeter Avalos 		 * the enclosed type field.
29827bfbee1SPeter Avalos 		 */
299411677aeSAaron LI 		if (caplen < 4) {
300*ed775ee7SAntonio Huete Jimenez 			ndo->ndo_protocol = "vlan";
301*ed775ee7SAntonio Huete Jimenez 			nd_print_trunc(ndo);
302*ed775ee7SAntonio Huete Jimenez 			ndo->ndo_ll_hdr_len += hdrlen + caplen;
303*ed775ee7SAntonio Huete Jimenez 			return;
304411677aeSAaron LI 		}
305411677aeSAaron LI 	        if (ndo->ndo_eflag) {
306*ed775ee7SAntonio Huete Jimenez 			uint16_t tag = GET_BE_U_2(p);
30727bfbee1SPeter Avalos 
308*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s, ", ieee8021q_tci_string(tag));
30927bfbee1SPeter Avalos 		}
31027bfbee1SPeter Avalos 
311*ed775ee7SAntonio Huete Jimenez 		ether_type = GET_BE_U_2(p + 2);
312*ed775ee7SAntonio Huete Jimenez 		if (ether_type <= MAX_ETHERNET_LENGTH_VAL)
31327bfbee1SPeter Avalos 			ether_type = LINUX_SLL_P_802_2;
314411677aeSAaron LI 		if (!ndo->ndo_qflag) {
315*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("ethertype %s, ",
316*ed775ee7SAntonio Huete Jimenez 			    tok2str(ethertype_values, "Unknown", ether_type));
31727bfbee1SPeter Avalos 		}
31827bfbee1SPeter Avalos 		p += 4;
31927bfbee1SPeter Avalos 		length -= 4;
32027bfbee1SPeter Avalos 		caplen -= 4;
321411677aeSAaron LI 		hdrlen += 4;
32227bfbee1SPeter Avalos 		goto recurse;
32327bfbee1SPeter Avalos 	} else {
324411677aeSAaron LI 		if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) {
32541c99275SPeter Avalos 			/* ether_type not known, print raw packet */
326411677aeSAaron LI 			if (!ndo->ndo_eflag)
327411677aeSAaron LI 				sll_print(ndo, sllp, length + SLL_HDR_LEN);
328411677aeSAaron LI 			if (!ndo->ndo_suppress_default_print)
329411677aeSAaron LI 				ND_DEFAULTPRINT(p, caplen);
33041c99275SPeter Avalos 		}
33127bfbee1SPeter Avalos 	}
33241c99275SPeter Avalos 
333*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_ll_hdr_len += hdrlen;
334*ed775ee7SAntonio Huete Jimenez }
335*ed775ee7SAntonio Huete Jimenez 
336*ed775ee7SAntonio Huete Jimenez static void
sll2_print(netdissect_options * ndo,const struct sll2_header * sllp,u_int length)337*ed775ee7SAntonio Huete Jimenez sll2_print(netdissect_options *ndo, const struct sll2_header *sllp, u_int length)
338*ed775ee7SAntonio Huete Jimenez {
339*ed775ee7SAntonio Huete Jimenez 	u_short ether_type;
340*ed775ee7SAntonio Huete Jimenez 
341*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "sll2";
342*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("ifindex %u ", GET_BE_U_4(sllp->sll2_if_index));
343*ed775ee7SAntonio Huete Jimenez 
344*ed775ee7SAntonio Huete Jimenez 	/*
345*ed775ee7SAntonio Huete Jimenez 	 * XXX - check the link-layer address type value?
346*ed775ee7SAntonio Huete Jimenez 	 * For now, we just assume 6 means Ethernet.
347*ed775ee7SAntonio Huete Jimenez 	 * XXX - print others as strings of hex?
348*ed775ee7SAntonio Huete Jimenez 	 */
349*ed775ee7SAntonio Huete Jimenez 	if (GET_U_1(sllp->sll2_halen) == MAC_ADDR_LEN)
350*ed775ee7SAntonio Huete Jimenez 		ND_PRINT("%s ", GET_ETHERADDR_STRING(sllp->sll2_addr));
351*ed775ee7SAntonio Huete Jimenez 
352*ed775ee7SAntonio Huete Jimenez 	if (!ndo->ndo_qflag) {
353*ed775ee7SAntonio Huete Jimenez 		ether_type = GET_BE_U_2(sllp->sll2_protocol);
354*ed775ee7SAntonio Huete Jimenez 
355*ed775ee7SAntonio Huete Jimenez 		if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
356*ed775ee7SAntonio Huete Jimenez 			/*
357*ed775ee7SAntonio Huete Jimenez 			 * Not an Ethernet type; what type is it?
358*ed775ee7SAntonio Huete Jimenez 			 */
359*ed775ee7SAntonio Huete Jimenez 			switch (ether_type) {
360*ed775ee7SAntonio Huete Jimenez 
361*ed775ee7SAntonio Huete Jimenez 			case LINUX_SLL_P_802_3:
362*ed775ee7SAntonio Huete Jimenez 				/*
363*ed775ee7SAntonio Huete Jimenez 				 * Ethernet_802.3 IPX frame.
364*ed775ee7SAntonio Huete Jimenez 				 */
365*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("802.3");
366*ed775ee7SAntonio Huete Jimenez 				break;
367*ed775ee7SAntonio Huete Jimenez 
368*ed775ee7SAntonio Huete Jimenez 			case LINUX_SLL_P_802_2:
369*ed775ee7SAntonio Huete Jimenez 				/*
370*ed775ee7SAntonio Huete Jimenez 				 * 802.2.
371*ed775ee7SAntonio Huete Jimenez 				 */
372*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("802.2");
373*ed775ee7SAntonio Huete Jimenez 				break;
374*ed775ee7SAntonio Huete Jimenez 
375*ed775ee7SAntonio Huete Jimenez 			default:
376*ed775ee7SAntonio Huete Jimenez 				/*
377*ed775ee7SAntonio Huete Jimenez 				 * What is it?
378*ed775ee7SAntonio Huete Jimenez 				 */
379*ed775ee7SAntonio Huete Jimenez 				ND_PRINT("ethertype Unknown (0x%04x)",
380*ed775ee7SAntonio Huete Jimenez 				    ether_type);
381*ed775ee7SAntonio Huete Jimenez 				break;
382*ed775ee7SAntonio Huete Jimenez 			}
383*ed775ee7SAntonio Huete Jimenez 		} else {
384*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("ethertype %s (0x%04x)",
385*ed775ee7SAntonio Huete Jimenez 			    tok2str(ethertype_values, "Unknown", ether_type),
386*ed775ee7SAntonio Huete Jimenez 			    ether_type);
387*ed775ee7SAntonio Huete Jimenez 		}
388*ed775ee7SAntonio Huete Jimenez 		ND_PRINT(", length %u: ", length);
389*ed775ee7SAntonio Huete Jimenez 	}
390*ed775ee7SAntonio Huete Jimenez }
391*ed775ee7SAntonio Huete Jimenez 
392*ed775ee7SAntonio Huete Jimenez /*
393*ed775ee7SAntonio Huete Jimenez  * This is the top level routine of the printer.  'p' points to the
394*ed775ee7SAntonio Huete Jimenez  * Linux "cooked capture" header of the packet, 'h->ts' is the timestamp,
395*ed775ee7SAntonio Huete Jimenez  * 'h->len' is the length of the packet off the wire, and 'h->caplen'
396*ed775ee7SAntonio Huete Jimenez  * is the number of bytes actually captured.
397*ed775ee7SAntonio Huete Jimenez  */
398*ed775ee7SAntonio Huete Jimenez void
sll2_if_print(netdissect_options * ndo,const struct pcap_pkthdr * h,const u_char * p)399*ed775ee7SAntonio Huete Jimenez sll2_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
400*ed775ee7SAntonio Huete Jimenez {
401*ed775ee7SAntonio Huete Jimenez 	u_int caplen = h->caplen;
402*ed775ee7SAntonio Huete Jimenez 	u_int length = h->len;
403*ed775ee7SAntonio Huete Jimenez 	const struct sll2_header *sllp;
404*ed775ee7SAntonio Huete Jimenez 	u_short hatype;
405*ed775ee7SAntonio Huete Jimenez 	u_short ether_type;
406*ed775ee7SAntonio Huete Jimenez 	int llc_hdrlen;
407*ed775ee7SAntonio Huete Jimenez 	u_int hdrlen;
408*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_NET_IF_H
409*ed775ee7SAntonio Huete Jimenez 	uint32_t if_index;
410*ed775ee7SAntonio Huete Jimenez 	char ifname[IF_NAMESIZE];
411*ed775ee7SAntonio Huete Jimenez #endif
412*ed775ee7SAntonio Huete Jimenez 
413*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_protocol = "sll2";
414*ed775ee7SAntonio Huete Jimenez 	ND_TCHECK_LEN(p, SLL2_HDR_LEN);
415*ed775ee7SAntonio Huete Jimenez 
416*ed775ee7SAntonio Huete Jimenez 	sllp = (const struct sll2_header *)p;
417*ed775ee7SAntonio Huete Jimenez #ifdef HAVE_NET_IF_H
418*ed775ee7SAntonio Huete Jimenez 	if_index = GET_BE_U_4(sllp->sll2_if_index);
419*ed775ee7SAntonio Huete Jimenez 	if (!if_indextoname(if_index, ifname))
420*ed775ee7SAntonio Huete Jimenez 		strncpy(ifname, "?", 2);
421*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("%-5s ", ifname);
422*ed775ee7SAntonio Huete Jimenez #endif
423*ed775ee7SAntonio Huete Jimenez 
424*ed775ee7SAntonio Huete Jimenez 	ND_PRINT("%-3s ",
425*ed775ee7SAntonio Huete Jimenez 		 tok2str(sll_pkttype_values, "?", GET_U_1(sllp->sll2_pkttype)));
426*ed775ee7SAntonio Huete Jimenez 
427*ed775ee7SAntonio Huete Jimenez 	if (ndo->ndo_eflag)
428*ed775ee7SAntonio Huete Jimenez 		sll2_print(ndo, sllp, length);
429*ed775ee7SAntonio Huete Jimenez 
430*ed775ee7SAntonio Huete Jimenez 	/*
431*ed775ee7SAntonio Huete Jimenez 	 * Go past the cooked-mode header.
432*ed775ee7SAntonio Huete Jimenez 	 */
433*ed775ee7SAntonio Huete Jimenez 	length -= SLL2_HDR_LEN;
434*ed775ee7SAntonio Huete Jimenez 	caplen -= SLL2_HDR_LEN;
435*ed775ee7SAntonio Huete Jimenez 	p += SLL2_HDR_LEN;
436*ed775ee7SAntonio Huete Jimenez 	hdrlen = SLL2_HDR_LEN;
437*ed775ee7SAntonio Huete Jimenez 
438*ed775ee7SAntonio Huete Jimenez 	hatype = GET_BE_U_2(sllp->sll2_hatype);
439*ed775ee7SAntonio Huete Jimenez 	switch (hatype) {
440*ed775ee7SAntonio Huete Jimenez 
441*ed775ee7SAntonio Huete Jimenez 	case 803:
442*ed775ee7SAntonio Huete Jimenez 		/*
443*ed775ee7SAntonio Huete Jimenez 		 * This is an packet with a radiotap header;
444*ed775ee7SAntonio Huete Jimenez 		 * just dissect the payload as such.
445*ed775ee7SAntonio Huete Jimenez 		 */
446*ed775ee7SAntonio Huete Jimenez 		ndo->ndo_ll_hdr_len += SLL2_HDR_LEN;
447*ed775ee7SAntonio Huete Jimenez 		ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, length, caplen);
448*ed775ee7SAntonio Huete Jimenez 		return;
449*ed775ee7SAntonio Huete Jimenez 	}
450*ed775ee7SAntonio Huete Jimenez 	ether_type = GET_BE_U_2(sllp->sll2_protocol);
451*ed775ee7SAntonio Huete Jimenez 
452*ed775ee7SAntonio Huete Jimenez recurse:
453*ed775ee7SAntonio Huete Jimenez 	/*
454*ed775ee7SAntonio Huete Jimenez 	 * Is it (gag) an 802.3 encapsulation, or some non-Ethernet
455*ed775ee7SAntonio Huete Jimenez 	 * packet type?
456*ed775ee7SAntonio Huete Jimenez 	 */
457*ed775ee7SAntonio Huete Jimenez 	if (ether_type <= MAX_ETHERNET_LENGTH_VAL) {
458*ed775ee7SAntonio Huete Jimenez 		/*
459*ed775ee7SAntonio Huete Jimenez 		 * Yes - what type is it?
460*ed775ee7SAntonio Huete Jimenez 		 */
461*ed775ee7SAntonio Huete Jimenez 		switch (ether_type) {
462*ed775ee7SAntonio Huete Jimenez 
463*ed775ee7SAntonio Huete Jimenez 		case LINUX_SLL_P_802_3:
464*ed775ee7SAntonio Huete Jimenez 			/*
465*ed775ee7SAntonio Huete Jimenez 			 * Ethernet_802.3 IPX frame.
466*ed775ee7SAntonio Huete Jimenez 			 */
467*ed775ee7SAntonio Huete Jimenez 			ipx_print(ndo, p, length);
468*ed775ee7SAntonio Huete Jimenez 			break;
469*ed775ee7SAntonio Huete Jimenez 
470*ed775ee7SAntonio Huete Jimenez 		case LINUX_SLL_P_802_2:
471*ed775ee7SAntonio Huete Jimenez 			/*
472*ed775ee7SAntonio Huete Jimenez 			 * 802.2.
473*ed775ee7SAntonio Huete Jimenez 			 * Try to print the LLC-layer header & higher layers.
474*ed775ee7SAntonio Huete Jimenez 			 */
475*ed775ee7SAntonio Huete Jimenez 			llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL);
476*ed775ee7SAntonio Huete Jimenez 			if (llc_hdrlen < 0)
477*ed775ee7SAntonio Huete Jimenez 				goto unknown;	/* unknown LLC type */
478*ed775ee7SAntonio Huete Jimenez 			hdrlen += llc_hdrlen;
479*ed775ee7SAntonio Huete Jimenez 			break;
480*ed775ee7SAntonio Huete Jimenez 
481*ed775ee7SAntonio Huete Jimenez 		default:
482*ed775ee7SAntonio Huete Jimenez 			/*FALLTHROUGH*/
483*ed775ee7SAntonio Huete Jimenez 
484*ed775ee7SAntonio Huete Jimenez 		unknown:
485*ed775ee7SAntonio Huete Jimenez 			/* packet type not known, print raw packet */
486*ed775ee7SAntonio Huete Jimenez 			if (!ndo->ndo_suppress_default_print)
487*ed775ee7SAntonio Huete Jimenez 				ND_DEFAULTPRINT(p, caplen);
488*ed775ee7SAntonio Huete Jimenez 			break;
489*ed775ee7SAntonio Huete Jimenez 		}
490*ed775ee7SAntonio Huete Jimenez 	} else if (ether_type == ETHERTYPE_8021Q) {
491*ed775ee7SAntonio Huete Jimenez 		/*
492*ed775ee7SAntonio Huete Jimenez 		 * Print VLAN information, and then go back and process
493*ed775ee7SAntonio Huete Jimenez 		 * the enclosed type field.
494*ed775ee7SAntonio Huete Jimenez 		 */
495*ed775ee7SAntonio Huete Jimenez 		if (caplen < 4) {
496*ed775ee7SAntonio Huete Jimenez 			ndo->ndo_protocol = "vlan";
497*ed775ee7SAntonio Huete Jimenez 			nd_print_trunc(ndo);
498*ed775ee7SAntonio Huete Jimenez 			ndo->ndo_ll_hdr_len += hdrlen + caplen;
499*ed775ee7SAntonio Huete Jimenez 			return;
500*ed775ee7SAntonio Huete Jimenez 		}
501*ed775ee7SAntonio Huete Jimenez 	        if (ndo->ndo_eflag) {
502*ed775ee7SAntonio Huete Jimenez 			uint16_t tag = GET_BE_U_2(p);
503*ed775ee7SAntonio Huete Jimenez 
504*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("%s, ", ieee8021q_tci_string(tag));
505*ed775ee7SAntonio Huete Jimenez 		}
506*ed775ee7SAntonio Huete Jimenez 
507*ed775ee7SAntonio Huete Jimenez 		ether_type = GET_BE_U_2(p + 2);
508*ed775ee7SAntonio Huete Jimenez 		if (ether_type <= MAX_ETHERNET_LENGTH_VAL)
509*ed775ee7SAntonio Huete Jimenez 			ether_type = LINUX_SLL_P_802_2;
510*ed775ee7SAntonio Huete Jimenez 		if (!ndo->ndo_qflag) {
511*ed775ee7SAntonio Huete Jimenez 			ND_PRINT("ethertype %s, ",
512*ed775ee7SAntonio Huete Jimenez 			    tok2str(ethertype_values, "Unknown", ether_type));
513*ed775ee7SAntonio Huete Jimenez 		}
514*ed775ee7SAntonio Huete Jimenez 		p += 4;
515*ed775ee7SAntonio Huete Jimenez 		length -= 4;
516*ed775ee7SAntonio Huete Jimenez 		caplen -= 4;
517*ed775ee7SAntonio Huete Jimenez 		hdrlen += 4;
518*ed775ee7SAntonio Huete Jimenez 		goto recurse;
519*ed775ee7SAntonio Huete Jimenez 	} else {
520*ed775ee7SAntonio Huete Jimenez 		if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) {
521*ed775ee7SAntonio Huete Jimenez 			/* ether_type not known, print raw packet */
522*ed775ee7SAntonio Huete Jimenez 			if (!ndo->ndo_eflag)
523*ed775ee7SAntonio Huete Jimenez 				sll2_print(ndo, sllp, length + SLL2_HDR_LEN);
524*ed775ee7SAntonio Huete Jimenez 			if (!ndo->ndo_suppress_default_print)
525*ed775ee7SAntonio Huete Jimenez 				ND_DEFAULTPRINT(p, caplen);
526*ed775ee7SAntonio Huete Jimenez 		}
527*ed775ee7SAntonio Huete Jimenez 	}
528*ed775ee7SAntonio Huete Jimenez 
529*ed775ee7SAntonio Huete Jimenez 	ndo->ndo_ll_hdr_len += hdrlen;
53041c99275SPeter Avalos }
531