| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 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 |  */ | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 21 |  | 
| Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 22 | /* \summary: Linux cooked sockets capture printer */ | 
 | 23 |  | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 24 | #ifdef HAVE_CONFIG_H | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 25 | #include <config.h> | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 26 | #endif | 
 | 27 |  | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 28 | #ifdef HAVE_NET_IF_H | 
 | 29 | #include <net/if.h> | 
 | 30 | #endif | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 31 |  | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 32 | #include "netdissect-stdinc.h" | 
 | 33 |  | 
 | 34 | #define ND_LONGJMP_FROM_TCHECK | 
| Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 35 | #include "netdissect.h" | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 36 | #include "addrtoname.h" | 
 | 37 | #include "ethertype.h" | 
 | 38 | #include "extract.h" | 
 | 39 |  | 
| Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 40 | /* | 
 | 41 |  * For captures on Linux cooked sockets, we construct a fake header | 
 | 42 |  * that includes: | 
 | 43 |  * | 
 | 44 |  *	a 2-byte "packet type" which is one of: | 
 | 45 |  * | 
 | 46 |  *		LINUX_SLL_HOST		packet was sent to us | 
 | 47 |  *		LINUX_SLL_BROADCAST	packet was broadcast | 
 | 48 |  *		LINUX_SLL_MULTICAST	packet was multicast | 
 | 49 |  *		LINUX_SLL_OTHERHOST	packet was sent to somebody else | 
 | 50 |  *		LINUX_SLL_OUTGOING	packet was sent *by* us; | 
 | 51 |  * | 
 | 52 |  *	a 2-byte Ethernet protocol field; | 
 | 53 |  * | 
 | 54 |  *	a 2-byte link-layer type; | 
 | 55 |  * | 
 | 56 |  *	a 2-byte link-layer address length; | 
 | 57 |  * | 
 | 58 |  *	an 8-byte source link-layer address, whose actual length is | 
 | 59 |  *	specified by the previous value. | 
 | 60 |  * | 
 | 61 |  * All fields except for the link-layer address are in network byte order. | 
 | 62 |  * | 
 | 63 |  * DO NOT change the layout of this structure, or change any of the | 
 | 64 |  * LINUX_SLL_ values below.  If you must change the link-layer header | 
 | 65 |  * for a "cooked" Linux capture, introduce a new DLT_ type (ask | 
 | 66 |  * "tcpdump-workers@lists.tcpdump.org" for one, so that you don't give it | 
 | 67 |  * a value that collides with a value already being used), and use the | 
 | 68 |  * new header in captures of that type, so that programs that can | 
 | 69 |  * handle DLT_LINUX_SLL captures will continue to handle them correctly | 
 | 70 |  * without any change, and so that capture files with different headers | 
 | 71 |  * can be told apart and programs that read them can dissect the | 
 | 72 |  * packets in them. | 
 | 73 |  * | 
 | 74 |  * This structure, and the #defines below, must be the same in the | 
 | 75 |  * libpcap and tcpdump versions of "sll.h". | 
 | 76 |  */ | 
 | 77 |  | 
 | 78 | /* | 
 | 79 |  * A DLT_LINUX_SLL fake link-layer header. | 
 | 80 |  */ | 
 | 81 | #define SLL_HDR_LEN	16		/* total header length */ | 
 | 82 | #define SLL_ADDRLEN	8		/* length of address field */ | 
 | 83 |  | 
 | 84 | struct sll_header { | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 85 | 	nd_uint16_t	sll_pkttype;	/* packet type */ | 
 | 86 | 	nd_uint16_t	sll_hatype;	/* link-layer address type */ | 
 | 87 | 	nd_uint16_t	sll_halen;	/* link-layer address length */ | 
 | 88 | 	nd_byte		sll_addr[SLL_ADDRLEN];	/* link-layer address */ | 
 | 89 | 	nd_uint16_t	sll_protocol;	/* protocol */ | 
 | 90 | }; | 
 | 91 |  | 
 | 92 | /* | 
 | 93 |  * A DLT_LINUX_SLL2 fake link-layer header. | 
 | 94 |  */ | 
 | 95 | #define SLL2_HDR_LEN	20		/* total header length */ | 
 | 96 |  | 
 | 97 | struct sll2_header { | 
 | 98 | 	nd_uint16_t	sll2_protocol;		/* protocol */ | 
 | 99 | 	nd_uint16_t	sll2_reserved_mbz;	/* reserved - must be zero */ | 
 | 100 | 	nd_uint32_t	sll2_if_index;		/* 1-based interface index */ | 
 | 101 | 	nd_uint16_t	sll2_hatype;		/* link-layer address type */ | 
 | 102 | 	nd_uint8_t	sll2_pkttype;		/* packet type */ | 
 | 103 | 	nd_uint8_t	sll2_halen;		/* link-layer address length */ | 
 | 104 | 	nd_byte		sll2_addr[SLL_ADDRLEN];	/* link-layer address */ | 
| Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 105 | }; | 
 | 106 |  | 
 | 107 | /* | 
 | 108 |  * The LINUX_SLL_ values for "sll_pkttype"; these correspond to the | 
 | 109 |  * PACKET_ values on Linux, but are defined here so that they're | 
 | 110 |  * available even on systems other than Linux, and so that they | 
 | 111 |  * don't change even if the PACKET_ values change. | 
 | 112 |  */ | 
 | 113 | #define LINUX_SLL_HOST		0 | 
 | 114 | #define LINUX_SLL_BROADCAST	1 | 
 | 115 | #define LINUX_SLL_MULTICAST	2 | 
 | 116 | #define LINUX_SLL_OTHERHOST	3 | 
 | 117 | #define LINUX_SLL_OUTGOING	4 | 
 | 118 |  | 
 | 119 | /* | 
 | 120 |  * The LINUX_SLL_ values for "sll_protocol"; these correspond to the | 
 | 121 |  * ETH_P_ values on Linux, but are defined here so that they're | 
 | 122 |  * available even on systems other than Linux.  We assume, for now, | 
 | 123 |  * that the ETH_P_ values won't change in Linux; if they do, then: | 
 | 124 |  * | 
 | 125 |  *	if we don't translate them in "pcap-linux.c", capture files | 
 | 126 |  *	won't necessarily be readable if captured on a system that | 
 | 127 |  *	defines ETH_P_ values that don't match these values; | 
 | 128 |  * | 
 | 129 |  *	if we do translate them in "pcap-linux.c", that makes life | 
 | 130 |  *	unpleasant for the BPF code generator, as the values you test | 
 | 131 |  *	for in the kernel aren't the values that you test for when | 
 | 132 |  *	reading a capture file, so the fixup code run on BPF programs | 
 | 133 |  *	handed to the kernel ends up having to do more work. | 
 | 134 |  * | 
 | 135 |  * Add other values here as necessary, for handling packet types that | 
 | 136 |  * might show up on non-Ethernet, non-802.x networks.  (Not all the ones | 
 | 137 |  * in the Linux "if_ether.h" will, I suspect, actually show up in | 
 | 138 |  * captures.) | 
 | 139 |  */ | 
 | 140 | #define LINUX_SLL_P_802_3	0x0001	/* Novell 802.3 frames without 802.2 LLC header */ | 
 | 141 | #define LINUX_SLL_P_802_2	0x0004	/* 802.2 frames (not D/I/X Ethernet) */ | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 142 |  | 
| JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 143 | static const struct tok sll_pkttype_values[] = { | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 144 |     { LINUX_SLL_HOST, "In" }, | 
 | 145 |     { LINUX_SLL_BROADCAST, "B" }, | 
 | 146 |     { LINUX_SLL_MULTICAST, "M" }, | 
 | 147 |     { LINUX_SLL_OTHERHOST, "P" }, | 
 | 148 |     { LINUX_SLL_OUTGOING, "Out" }, | 
 | 149 |     { 0, NULL} | 
 | 150 | }; | 
 | 151 |  | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 152 | static void | 
 | 153 | sll_print(netdissect_options *ndo, const struct sll_header *sllp, u_int length) | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 154 | { | 
 | 155 | 	u_short ether_type; | 
 | 156 |  | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 157 | 	ndo->ndo_protocol = "sll"; | 
 | 158 |         ND_PRINT("%3s ", | 
 | 159 | 		 tok2str(sll_pkttype_values,"?",GET_BE_U_2(sllp->sll_pkttype))); | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 160 |  | 
 | 161 | 	/* | 
 | 162 | 	 * XXX - check the link-layer address type value? | 
 | 163 | 	 * For now, we just assume 6 means Ethernet. | 
 | 164 | 	 * XXX - print others as strings of hex? | 
 | 165 | 	 */ | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 166 | 	if (GET_BE_U_2(sllp->sll_halen) == MAC_ADDR_LEN) | 
 | 167 | 		ND_PRINT("%s ", GET_ETHERADDR_STRING(sllp->sll_addr)); | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 168 |  | 
| Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 169 | 	if (!ndo->ndo_qflag) { | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 170 | 		ether_type = GET_BE_U_2(sllp->sll_protocol); | 
| Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 171 |  | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 172 | 		if (ether_type <= MAX_ETHERNET_LENGTH_VAL) { | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 173 | 			/* | 
 | 174 | 			 * Not an Ethernet type; what type is it? | 
 | 175 | 			 */ | 
 | 176 | 			switch (ether_type) { | 
 | 177 |  | 
 | 178 | 			case LINUX_SLL_P_802_3: | 
 | 179 | 				/* | 
 | 180 | 				 * Ethernet_802.3 IPX frame. | 
 | 181 | 				 */ | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 182 | 				ND_PRINT("802.3"); | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 183 | 				break; | 
 | 184 |  | 
 | 185 | 			case LINUX_SLL_P_802_2: | 
 | 186 | 				/* | 
 | 187 | 				 * 802.2. | 
 | 188 | 				 */ | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 189 | 				ND_PRINT("802.2"); | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 190 | 				break; | 
 | 191 |  | 
 | 192 | 			default: | 
 | 193 | 				/* | 
 | 194 | 				 * What is it? | 
 | 195 | 				 */ | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 196 | 				ND_PRINT("ethertype Unknown (0x%04x)", | 
 | 197 | 				    ether_type); | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 198 | 				break; | 
 | 199 | 			} | 
 | 200 | 		} else { | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 201 | 			ND_PRINT("ethertype %s (0x%04x)", | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 202 | 			    tok2str(ethertype_values, "Unknown", ether_type), | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 203 | 			    ether_type); | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 204 | 		} | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 205 | 		ND_PRINT(", length %u: ", length); | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 206 | 	} | 
 | 207 | } | 
 | 208 |  | 
 | 209 | /* | 
 | 210 |  * This is the top level routine of the printer.  'p' points to the | 
 | 211 |  * Linux "cooked capture" header of the packet, 'h->ts' is the timestamp, | 
 | 212 |  * 'h->len' is the length of the packet off the wire, and 'h->caplen' | 
 | 213 |  * is the number of bytes actually captured. | 
 | 214 |  */ | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 215 | void | 
| Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 216 | sll_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 217 | { | 
 | 218 | 	u_int caplen = h->caplen; | 
 | 219 | 	u_int length = h->len; | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 220 | 	const struct sll_header *sllp; | 
 | 221 | 	u_short hatype; | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 222 | 	u_short ether_type; | 
| Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 223 | 	int llc_hdrlen; | 
 | 224 | 	u_int hdrlen; | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 225 |  | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 226 | 	ndo->ndo_protocol = "sll"; | 
 | 227 | 	ND_TCHECK_LEN(p, SLL_HDR_LEN); | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 228 |  | 
 | 229 | 	sllp = (const struct sll_header *)p; | 
 | 230 |  | 
| Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 231 | 	if (ndo->ndo_eflag) | 
 | 232 | 		sll_print(ndo, sllp, length); | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 233 |  | 
 | 234 | 	/* | 
 | 235 | 	 * Go past the cooked-mode header. | 
 | 236 | 	 */ | 
 | 237 | 	length -= SLL_HDR_LEN; | 
 | 238 | 	caplen -= SLL_HDR_LEN; | 
 | 239 | 	p += SLL_HDR_LEN; | 
| Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 240 | 	hdrlen = SLL_HDR_LEN; | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 241 |  | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 242 | 	hatype = GET_BE_U_2(sllp->sll_hatype); | 
 | 243 | 	switch (hatype) { | 
 | 244 |  | 
 | 245 | 	case 803: | 
 | 246 | 		/* | 
 | 247 | 		 * This is an packet with a radiotap header; | 
 | 248 | 		 * just dissect the payload as such. | 
 | 249 | 		 */ | 
 | 250 | 		ndo->ndo_ll_hdr_len += SLL_HDR_LEN; | 
 | 251 | 		ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, length, caplen); | 
 | 252 | 		return; | 
 | 253 | 	} | 
 | 254 | 	ether_type = GET_BE_U_2(sllp->sll_protocol); | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 255 |  | 
| JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 256 | recurse: | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 257 | 	/* | 
 | 258 | 	 * Is it (gag) an 802.3 encapsulation, or some non-Ethernet | 
 | 259 | 	 * packet type? | 
 | 260 | 	 */ | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 261 | 	if (ether_type <= MAX_ETHERNET_LENGTH_VAL) { | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 262 | 		/* | 
 | 263 | 		 * Yes - what type is it? | 
 | 264 | 		 */ | 
 | 265 | 		switch (ether_type) { | 
 | 266 |  | 
 | 267 | 		case LINUX_SLL_P_802_3: | 
 | 268 | 			/* | 
 | 269 | 			 * Ethernet_802.3 IPX frame. | 
 | 270 | 			 */ | 
| Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 271 | 			ipx_print(ndo, p, length); | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 272 | 			break; | 
 | 273 |  | 
 | 274 | 		case LINUX_SLL_P_802_2: | 
 | 275 | 			/* | 
 | 276 | 			 * 802.2. | 
 | 277 | 			 * Try to print the LLC-layer header & higher layers. | 
 | 278 | 			 */ | 
| Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 279 | 			llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL); | 
 | 280 | 			if (llc_hdrlen < 0) | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 281 | 				goto unknown;	/* unknown LLC type */ | 
| Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 282 | 			hdrlen += llc_hdrlen; | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 283 | 			break; | 
 | 284 |  | 
 | 285 | 		default: | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 286 | 			/*FALLTHROUGH*/ | 
 | 287 |  | 
 | 288 | 		unknown: | 
| Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 289 | 			/* packet type not known, print raw packet */ | 
| Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 290 | 			if (!ndo->ndo_suppress_default_print) | 
 | 291 | 				ND_DEFAULTPRINT(p, caplen); | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 292 | 			break; | 
 | 293 | 		} | 
| JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 294 | 	} else if (ether_type == ETHERTYPE_8021Q) { | 
 | 295 | 		/* | 
 | 296 | 		 * Print VLAN information, and then go back and process | 
 | 297 | 		 * the enclosed type field. | 
 | 298 | 		 */ | 
| Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 299 | 		if (caplen < 4) { | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 300 | 			ndo->ndo_protocol = "vlan"; | 
 | 301 | 			nd_print_trunc(ndo); | 
 | 302 | 			ndo->ndo_ll_hdr_len += hdrlen + caplen; | 
 | 303 | 			return; | 
| JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 304 | 		} | 
| Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 305 | 	        if (ndo->ndo_eflag) { | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 306 | 			uint16_t tag = GET_BE_U_2(p); | 
| JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 307 |  | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 308 | 			ND_PRINT("%s, ", ieee8021q_tci_string(tag)); | 
| JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 309 | 		} | 
 | 310 |  | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 311 | 		ether_type = GET_BE_U_2(p + 2); | 
 | 312 | 		if (ether_type <= MAX_ETHERNET_LENGTH_VAL) | 
| JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 313 | 			ether_type = LINUX_SLL_P_802_2; | 
| Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 314 | 		if (!ndo->ndo_qflag) { | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 315 | 			ND_PRINT("ethertype %s, ", | 
 | 316 | 			    tok2str(ethertype_values, "Unknown", ether_type)); | 
| JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 317 | 		} | 
 | 318 | 		p += 4; | 
 | 319 | 		length -= 4; | 
 | 320 | 		caplen -= 4; | 
| Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 321 | 		hdrlen += 4; | 
| JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 322 | 		goto recurse; | 
 | 323 | 	} else { | 
| Elliott Hughes | e2e3bd1 | 2017-05-15 10:59:29 -0700 | [diff] [blame] | 324 | 		if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) { | 
| JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 325 | 			/* ether_type not known, print raw packet */ | 
| Elliott Hughes | 892a68b | 2015-10-19 14:43:53 -0700 | [diff] [blame] | 326 | 			if (!ndo->ndo_eflag) | 
 | 327 | 				sll_print(ndo, sllp, length + SLL_HDR_LEN); | 
 | 328 | 			if (!ndo->ndo_suppress_default_print) | 
 | 329 | 				ND_DEFAULTPRINT(p, caplen); | 
| JP Abgrall | 53f17a9 | 2014-02-12 14:02:41 -0800 | [diff] [blame] | 330 | 		} | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 331 | 	} | 
 | 332 |  | 
| Elliott Hughes | 820eced | 2021-08-20 18:00:50 -0700 | [diff] [blame] | 333 | 	ndo->ndo_ll_hdr_len += hdrlen; | 
 | 334 | } | 
 | 335 |  | 
 | 336 | static void | 
 | 337 | sll2_print(netdissect_options *ndo, const struct sll2_header *sllp, u_int length) | 
 | 338 | { | 
 | 339 | 	u_short ether_type; | 
 | 340 |  | 
 | 341 | 	ndo->ndo_protocol = "sll2"; | 
 | 342 | 	ND_PRINT("ifindex %u ", GET_BE_U_4(sllp->sll2_if_index)); | 
 | 343 |  | 
 | 344 | 	/* | 
 | 345 | 	 * XXX - check the link-layer address type value? | 
 | 346 | 	 * For now, we just assume 6 means Ethernet. | 
 | 347 | 	 * XXX - print others as strings of hex? | 
 | 348 | 	 */ | 
 | 349 | 	if (GET_U_1(sllp->sll2_halen) == MAC_ADDR_LEN) | 
 | 350 | 		ND_PRINT("%s ", GET_ETHERADDR_STRING(sllp->sll2_addr)); | 
 | 351 |  | 
 | 352 | 	if (!ndo->ndo_qflag) { | 
 | 353 | 		ether_type = GET_BE_U_2(sllp->sll2_protocol); | 
 | 354 |  | 
 | 355 | 		if (ether_type <= MAX_ETHERNET_LENGTH_VAL) { | 
 | 356 | 			/* | 
 | 357 | 			 * Not an Ethernet type; what type is it? | 
 | 358 | 			 */ | 
 | 359 | 			switch (ether_type) { | 
 | 360 |  | 
 | 361 | 			case LINUX_SLL_P_802_3: | 
 | 362 | 				/* | 
 | 363 | 				 * Ethernet_802.3 IPX frame. | 
 | 364 | 				 */ | 
 | 365 | 				ND_PRINT("802.3"); | 
 | 366 | 				break; | 
 | 367 |  | 
 | 368 | 			case LINUX_SLL_P_802_2: | 
 | 369 | 				/* | 
 | 370 | 				 * 802.2. | 
 | 371 | 				 */ | 
 | 372 | 				ND_PRINT("802.2"); | 
 | 373 | 				break; | 
 | 374 |  | 
 | 375 | 			default: | 
 | 376 | 				/* | 
 | 377 | 				 * What is it? | 
 | 378 | 				 */ | 
 | 379 | 				ND_PRINT("ethertype Unknown (0x%04x)", | 
 | 380 | 				    ether_type); | 
 | 381 | 				break; | 
 | 382 | 			} | 
 | 383 | 		} else { | 
 | 384 | 			ND_PRINT("ethertype %s (0x%04x)", | 
 | 385 | 			    tok2str(ethertype_values, "Unknown", ether_type), | 
 | 386 | 			    ether_type); | 
 | 387 | 		} | 
 | 388 | 		ND_PRINT(", length %u: ", length); | 
 | 389 | 	} | 
 | 390 | } | 
 | 391 |  | 
 | 392 | /* | 
 | 393 |  * This is the top level routine of the printer.  'p' points to the | 
 | 394 |  * Linux "cooked capture" header of the packet, 'h->ts' is the timestamp, | 
 | 395 |  * 'h->len' is the length of the packet off the wire, and 'h->caplen' | 
 | 396 |  * is the number of bytes actually captured. | 
 | 397 |  */ | 
 | 398 | void | 
 | 399 | sll2_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) | 
 | 400 | { | 
 | 401 | 	u_int caplen = h->caplen; | 
 | 402 | 	u_int length = h->len; | 
 | 403 | 	const struct sll2_header *sllp; | 
 | 404 | 	u_short hatype; | 
 | 405 | 	u_short ether_type; | 
 | 406 | 	int llc_hdrlen; | 
 | 407 | 	u_int hdrlen; | 
 | 408 | #ifdef HAVE_NET_IF_H | 
 | 409 | 	uint32_t if_index; | 
 | 410 | 	char ifname[IF_NAMESIZE]; | 
 | 411 | #endif | 
 | 412 |  | 
 | 413 | 	ndo->ndo_protocol = "sll2"; | 
 | 414 | 	ND_TCHECK_LEN(p, SLL2_HDR_LEN); | 
 | 415 |  | 
 | 416 | 	sllp = (const struct sll2_header *)p; | 
 | 417 | #ifdef HAVE_NET_IF_H | 
 | 418 | 	if_index = GET_BE_U_4(sllp->sll2_if_index); | 
 | 419 | 	if (!if_indextoname(if_index, ifname)) | 
 | 420 | 		strncpy(ifname, "?", 2); | 
 | 421 | 	ND_PRINT("%-5s ", ifname); | 
 | 422 | #endif | 
 | 423 |  | 
 | 424 | 	ND_PRINT("%-3s ", | 
 | 425 | 		 tok2str(sll_pkttype_values, "?", GET_U_1(sllp->sll2_pkttype))); | 
 | 426 |  | 
 | 427 | 	if (ndo->ndo_eflag) | 
 | 428 | 		sll2_print(ndo, sllp, length); | 
 | 429 |  | 
 | 430 | 	/* | 
 | 431 | 	 * Go past the cooked-mode header. | 
 | 432 | 	 */ | 
 | 433 | 	length -= SLL2_HDR_LEN; | 
 | 434 | 	caplen -= SLL2_HDR_LEN; | 
 | 435 | 	p += SLL2_HDR_LEN; | 
 | 436 | 	hdrlen = SLL2_HDR_LEN; | 
 | 437 |  | 
 | 438 | 	hatype = GET_BE_U_2(sllp->sll2_hatype); | 
 | 439 | 	switch (hatype) { | 
 | 440 |  | 
 | 441 | 	case 803: | 
 | 442 | 		/* | 
 | 443 | 		 * This is an packet with a radiotap header; | 
 | 444 | 		 * just dissect the payload as such. | 
 | 445 | 		 */ | 
 | 446 | 		ndo->ndo_ll_hdr_len += SLL2_HDR_LEN; | 
 | 447 | 		ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, length, caplen); | 
 | 448 | 		return; | 
 | 449 | 	} | 
 | 450 | 	ether_type = GET_BE_U_2(sllp->sll2_protocol); | 
 | 451 |  | 
 | 452 | recurse: | 
 | 453 | 	/* | 
 | 454 | 	 * Is it (gag) an 802.3 encapsulation, or some non-Ethernet | 
 | 455 | 	 * packet type? | 
 | 456 | 	 */ | 
 | 457 | 	if (ether_type <= MAX_ETHERNET_LENGTH_VAL) { | 
 | 458 | 		/* | 
 | 459 | 		 * Yes - what type is it? | 
 | 460 | 		 */ | 
 | 461 | 		switch (ether_type) { | 
 | 462 |  | 
 | 463 | 		case LINUX_SLL_P_802_3: | 
 | 464 | 			/* | 
 | 465 | 			 * Ethernet_802.3 IPX frame. | 
 | 466 | 			 */ | 
 | 467 | 			ipx_print(ndo, p, length); | 
 | 468 | 			break; | 
 | 469 |  | 
 | 470 | 		case LINUX_SLL_P_802_2: | 
 | 471 | 			/* | 
 | 472 | 			 * 802.2. | 
 | 473 | 			 * Try to print the LLC-layer header & higher layers. | 
 | 474 | 			 */ | 
 | 475 | 			llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL); | 
 | 476 | 			if (llc_hdrlen < 0) | 
 | 477 | 				goto unknown;	/* unknown LLC type */ | 
 | 478 | 			hdrlen += llc_hdrlen; | 
 | 479 | 			break; | 
 | 480 |  | 
 | 481 | 		default: | 
 | 482 | 			/*FALLTHROUGH*/ | 
 | 483 |  | 
 | 484 | 		unknown: | 
 | 485 | 			/* packet type not known, print raw packet */ | 
 | 486 | 			if (!ndo->ndo_suppress_default_print) | 
 | 487 | 				ND_DEFAULTPRINT(p, caplen); | 
 | 488 | 			break; | 
 | 489 | 		} | 
 | 490 | 	} else if (ether_type == ETHERTYPE_8021Q) { | 
 | 491 | 		/* | 
 | 492 | 		 * Print VLAN information, and then go back and process | 
 | 493 | 		 * the enclosed type field. | 
 | 494 | 		 */ | 
 | 495 | 		if (caplen < 4) { | 
 | 496 | 			ndo->ndo_protocol = "vlan"; | 
 | 497 | 			nd_print_trunc(ndo); | 
 | 498 | 			ndo->ndo_ll_hdr_len += hdrlen + caplen; | 
 | 499 | 			return; | 
 | 500 | 		} | 
 | 501 | 	        if (ndo->ndo_eflag) { | 
 | 502 | 			uint16_t tag = GET_BE_U_2(p); | 
 | 503 |  | 
 | 504 | 			ND_PRINT("%s, ", ieee8021q_tci_string(tag)); | 
 | 505 | 		} | 
 | 506 |  | 
 | 507 | 		ether_type = GET_BE_U_2(p + 2); | 
 | 508 | 		if (ether_type <= MAX_ETHERNET_LENGTH_VAL) | 
 | 509 | 			ether_type = LINUX_SLL_P_802_2; | 
 | 510 | 		if (!ndo->ndo_qflag) { | 
 | 511 | 			ND_PRINT("ethertype %s, ", | 
 | 512 | 			    tok2str(ethertype_values, "Unknown", ether_type)); | 
 | 513 | 		} | 
 | 514 | 		p += 4; | 
 | 515 | 		length -= 4; | 
 | 516 | 		caplen -= 4; | 
 | 517 | 		hdrlen += 4; | 
 | 518 | 		goto recurse; | 
 | 519 | 	} else { | 
 | 520 | 		if (ethertype_print(ndo, ether_type, p, length, caplen, NULL, NULL) == 0) { | 
 | 521 | 			/* ether_type not known, print raw packet */ | 
 | 522 | 			if (!ndo->ndo_eflag) | 
 | 523 | 				sll2_print(ndo, sllp, length + SLL2_HDR_LEN); | 
 | 524 | 			if (!ndo->ndo_suppress_default_print) | 
 | 525 | 				ND_DEFAULTPRINT(p, caplen); | 
 | 526 | 		} | 
 | 527 | 	} | 
 | 528 |  | 
 | 529 | 	ndo->ndo_ll_hdr_len += hdrlen; | 
| The Android Open Source Project | 2949f58 | 2009-03-03 19:30:46 -0800 | [diff] [blame] | 530 | } |