Home | History | Annotate | Line # | Download | only in dist
      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 (at) 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