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