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