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