1 /* 2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 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 * Support for splitting captures into multiple files with a maximum 22 * file size: 23 * 24 * Copyright (c) 2001 25 * Seth Webster <swebster@sst.ll.mit.edu> 26 */ 27 28 #include <sys/cdefs.h> 29 #ifndef lint 30 __RCSID("$NetBSD: print.c,v 1.6 2024/09/02 16:15:33 christos Exp $"); 31 #endif 32 33 #include <config.h> 34 35 #include <stdlib.h> 36 #include <string.h> 37 #include <setjmp.h> 38 39 #include "netdissect-stdinc.h" 40 41 #include "netdissect.h" 42 #include "addrtoname.h" 43 #include "print.h" 44 #include "netdissect-alloc.h" 45 46 #include "pcap-missing.h" 47 48 struct printer { 49 if_printer f; 50 int type; 51 }; 52 53 static const struct printer printers[] = { 54 #ifdef DLT_APPLE_IP_OVER_IEEE1394 55 { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, 56 #endif 57 { arcnet_if_print, DLT_ARCNET }, 58 #ifdef DLT_ARCNET_LINUX 59 { arcnet_linux_if_print, DLT_ARCNET_LINUX }, 60 #endif 61 { atm_if_print, DLT_ATM_RFC1483 }, 62 #ifdef DLT_DSA_TAG_BRCM 63 { brcm_tag_if_print, DLT_DSA_TAG_BRCM }, 64 #endif 65 #ifdef DLT_DSA_TAG_BRCM_PREPEND 66 { brcm_tag_prepend_if_print, DLT_DSA_TAG_BRCM_PREPEND }, 67 #endif 68 #ifdef DLT_BLUETOOTH_HCI_H4_WITH_PHDR 69 { bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR}, 70 #endif 71 #ifdef DLT_C_HDLC 72 { chdlc_if_print, DLT_C_HDLC }, 73 #endif 74 #ifdef DLT_HDLC 75 { chdlc_if_print, DLT_HDLC }, 76 #endif 77 #ifdef DLT_ATM_CLIP 78 { cip_if_print, DLT_ATM_CLIP }, 79 #endif 80 #ifdef DLT_CIP 81 { cip_if_print, DLT_CIP }, 82 #endif 83 #ifdef DLT_DSA_TAG_DSA 84 { dsa_if_print, DLT_DSA_TAG_DSA }, 85 #endif 86 #ifdef DLT_DSA_TAG_EDSA 87 { edsa_if_print, DLT_DSA_TAG_EDSA }, 88 #endif 89 #ifdef DLT_ENC 90 { enc_if_print, DLT_ENC }, 91 #endif 92 { ether_if_print, DLT_EN10MB }, 93 { fddi_if_print, DLT_FDDI }, 94 #ifdef DLT_FR 95 { fr_if_print, DLT_FR }, 96 #endif 97 #ifdef DLT_FRELAY 98 { fr_if_print, DLT_FRELAY }, 99 #endif 100 #ifdef DLT_IEEE802_11 101 { ieee802_11_if_print, DLT_IEEE802_11}, 102 #endif 103 #ifdef DLT_IEEE802_11_RADIO_AVS 104 { ieee802_11_radio_avs_if_print, DLT_IEEE802_11_RADIO_AVS }, 105 #endif 106 #ifdef DLT_IEEE802_11_RADIO 107 { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO }, 108 #endif 109 #ifdef DLT_IEEE802_15_4 110 { ieee802_15_4_if_print, DLT_IEEE802_15_4 }, 111 #endif 112 #ifdef DLT_IEEE802_15_4_NOFCS 113 { ieee802_15_4_if_print, DLT_IEEE802_15_4_NOFCS }, 114 #endif 115 #ifdef DLT_IEEE802_15_4_TAP 116 { ieee802_15_4_tap_if_print, DLT_IEEE802_15_4_TAP }, 117 #endif 118 #ifdef DLT_IP_OVER_FC 119 { ipfc_if_print, DLT_IP_OVER_FC }, 120 #endif 121 #ifdef DLT_IPNET 122 { ipnet_if_print, DLT_IPNET }, 123 #endif 124 #ifdef DLT_IPOIB 125 { ipoib_if_print, DLT_IPOIB }, 126 #endif 127 #ifdef DLT_JUNIPER_ATM1 128 { juniper_atm1_if_print, DLT_JUNIPER_ATM1 }, 129 #endif 130 #ifdef DLT_JUNIPER_ATM2 131 { juniper_atm2_if_print, DLT_JUNIPER_ATM2 }, 132 #endif 133 #ifdef DLT_JUNIPER_CHDLC 134 { juniper_chdlc_if_print, DLT_JUNIPER_CHDLC }, 135 #endif 136 #ifdef DLT_JUNIPER_ES 137 { juniper_es_if_print, DLT_JUNIPER_ES }, 138 #endif 139 #ifdef DLT_JUNIPER_ETHER 140 { juniper_ether_if_print, DLT_JUNIPER_ETHER }, 141 #endif 142 #ifdef DLT_JUNIPER_FRELAY 143 { juniper_frelay_if_print, DLT_JUNIPER_FRELAY }, 144 #endif 145 #ifdef DLT_JUNIPER_GGSN 146 { juniper_ggsn_if_print, DLT_JUNIPER_GGSN }, 147 #endif 148 #ifdef DLT_JUNIPER_MFR 149 { juniper_mfr_if_print, DLT_JUNIPER_MFR }, 150 #endif 151 #ifdef DLT_JUNIPER_MLFR 152 { juniper_mlfr_if_print, DLT_JUNIPER_MLFR }, 153 #endif 154 #ifdef DLT_JUNIPER_MLPPP 155 { juniper_mlppp_if_print, DLT_JUNIPER_MLPPP }, 156 #endif 157 #ifdef DLT_JUNIPER_MONITOR 158 { juniper_monitor_if_print, DLT_JUNIPER_MONITOR }, 159 #endif 160 #ifdef DLT_JUNIPER_PPP 161 { juniper_ppp_if_print, DLT_JUNIPER_PPP }, 162 #endif 163 #ifdef DLT_JUNIPER_PPPOE_ATM 164 { juniper_pppoe_atm_if_print, DLT_JUNIPER_PPPOE_ATM }, 165 #endif 166 #ifdef DLT_JUNIPER_PPPOE 167 { juniper_pppoe_if_print, DLT_JUNIPER_PPPOE }, 168 #endif 169 #ifdef DLT_JUNIPER_SERVICES 170 { juniper_services_if_print, DLT_JUNIPER_SERVICES }, 171 #endif 172 #ifdef DLT_LTALK 173 { ltalk_if_print, DLT_LTALK }, 174 #endif 175 #ifdef DLT_MFR 176 { mfr_if_print, DLT_MFR }, 177 #endif 178 #ifdef DLT_NETANALYZER 179 { netanalyzer_if_print, DLT_NETANALYZER }, 180 #endif 181 #ifdef DLT_NETANALYZER_TRANSPARENT 182 { netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT }, 183 #endif 184 #ifdef DLT_NFLOG 185 { nflog_if_print, DLT_NFLOG}, 186 #endif 187 { null_if_print, DLT_NULL }, 188 #ifdef DLT_LOOP 189 { null_if_print, DLT_LOOP }, 190 #endif 191 #ifdef DLT_PFLOG 192 { pflog_if_print, DLT_PFLOG }, 193 #endif 194 #ifdef DLT_PKTAP 195 { pktap_if_print, DLT_PKTAP }, 196 #endif 197 #ifdef DLT_PPI 198 { ppi_if_print, DLT_PPI }, 199 #endif 200 #ifdef DLT_PPP_BSDOS 201 { ppp_bsdos_if_print, DLT_PPP_BSDOS }, 202 #endif 203 #ifdef DLT_PPP_SERIAL 204 { ppp_hdlc_if_print, DLT_PPP_SERIAL }, 205 #endif 206 { ppp_if_print, DLT_PPP }, 207 #ifdef DLT_PPP_PPPD 208 { ppp_if_print, DLT_PPP_PPPD }, 209 #endif 210 #ifdef DLT_PPP_ETHER 211 { pppoe_if_print, DLT_PPP_ETHER }, 212 #endif 213 #ifdef DLT_PRISM_HEADER 214 { prism_if_print, DLT_PRISM_HEADER }, 215 #endif 216 { raw_if_print, DLT_RAW }, 217 #ifdef DLT_IPV4 218 { raw_if_print, DLT_IPV4 }, 219 #endif 220 #ifdef DLT_IPV6 221 { raw_if_print, DLT_IPV6 }, 222 #endif 223 #ifdef DLT_SLIP_BSDOS 224 { sl_bsdos_if_print, DLT_SLIP_BSDOS }, 225 #endif 226 { sl_if_print, DLT_SLIP }, 227 #ifdef DLT_LINUX_SLL 228 { sll_if_print, DLT_LINUX_SLL }, 229 #endif 230 #ifdef DLT_LINUX_SLL2 231 { sll2_if_print, DLT_LINUX_SLL2 }, 232 #endif 233 #ifdef DLT_SUNATM 234 { sunatm_if_print, DLT_SUNATM }, 235 #endif 236 #ifdef DLT_SYMANTEC_FIREWALL 237 { symantec_if_print, DLT_SYMANTEC_FIREWALL }, 238 #endif 239 { token_if_print, DLT_IEEE802 }, 240 #ifdef DLT_USB_LINUX 241 { usb_linux_48_byte_if_print, DLT_USB_LINUX}, 242 #endif /* DLT_USB_LINUX */ 243 #ifdef DLT_USB_LINUX_MMAPPED 244 { usb_linux_64_byte_if_print, DLT_USB_LINUX_MMAPPED}, 245 #endif /* DLT_USB_LINUX_MMAPPED */ 246 #ifdef DLT_VSOCK 247 { vsock_if_print, DLT_VSOCK }, 248 #endif 249 #ifdef DLT_PFSYNC 250 { pfsync_if_print, DLT_PFSYNC }, 251 #endif 252 { NULL, 0 }, 253 }; 254 255 static void ndo_default_print(netdissect_options *ndo, const u_char *bp, 256 u_int length); 257 258 static void NORETURN ndo_error(netdissect_options *ndo, 259 status_exit_codes_t status, 260 FORMAT_STRING(const char *fmt), ...) 261 PRINTFLIKE(3, 4); 262 static void ndo_warning(netdissect_options *ndo, 263 FORMAT_STRING(const char *fmt), ...) 264 PRINTFLIKE(2, 3); 265 266 static int ndo_printf(netdissect_options *ndo, 267 FORMAT_STRING(const char *fmt), ...) 268 PRINTFLIKE(2, 3); 269 270 void 271 init_print(netdissect_options *ndo, uint32_t localnet, uint32_t mask) 272 { 273 init_addrtoname(ndo, localnet, mask); 274 } 275 276 if_printer 277 lookup_printer(int type) 278 { 279 const struct printer *p; 280 281 for (p = printers; p->f; ++p) 282 if (type == p->type) 283 return p->f; 284 285 #if defined(DLT_USER2) && defined(DLT_PKTAP) 286 /* 287 * Apple incorrectly chose to use DLT_USER2 for their PKTAP 288 * header. 289 * 290 * We map DLT_PKTAP, whether it's DLT_USER2 as it is on Darwin- 291 * based OSes or the same value as LINKTYPE_PKTAP as it is on 292 * other OSes, to LINKTYPE_PKTAP, so files written with 293 * this version of libpcap for a DLT_PKTAP capture have a link- 294 * layer header type of LINKTYPE_PKTAP. 295 * 296 * However, files written on OS X Mavericks for a DLT_PKTAP 297 * capture have a link-layer header type of LINKTYPE_USER2. 298 * If we don't have a printer for DLT_USER2, and type is 299 * DLT_USER2, we look up the printer for DLT_PKTAP and use 300 * that. 301 */ 302 if (type == DLT_USER2) { 303 for (p = printers; p->f; ++p) 304 if (DLT_PKTAP == p->type) 305 return p->f; 306 } 307 #endif 308 309 return NULL; 310 /* NOTREACHED */ 311 } 312 313 int 314 has_printer(int type) 315 { 316 return (lookup_printer(type) != NULL); 317 } 318 319 if_printer 320 get_if_printer(int type) 321 { 322 if_printer printer; 323 324 printer = lookup_printer(type); 325 if (printer == NULL) 326 printer = unsupported_if_print; 327 return printer; 328 } 329 330 #ifdef ENABLE_INSTRUMENT_FUNCTIONS 331 extern int profile_func_level; 332 static int pretty_print_packet_level = -1; 333 #endif 334 335 void 336 pretty_print_packet(netdissect_options *ndo, const struct pcap_pkthdr *h, 337 const u_char *sp, u_int packets_captured) 338 { 339 u_int hdrlen = 0; 340 int invalid_header = 0; 341 342 #ifdef ENABLE_INSTRUMENT_FUNCTIONS 343 if (pretty_print_packet_level == -1) 344 pretty_print_packet_level = profile_func_level; 345 #endif 346 347 if (ndo->ndo_packet_number) 348 ND_PRINT("%5u ", packets_captured); 349 350 /* Sanity checks on packet length / capture length */ 351 if (h->caplen == 0) { 352 invalid_header = 1; 353 ND_PRINT("[Invalid header: caplen==0"); 354 } 355 if (h->len == 0) { 356 if (!invalid_header) { 357 invalid_header = 1; 358 ND_PRINT("[Invalid header:"); 359 } else 360 ND_PRINT(","); 361 ND_PRINT(" len==0"); 362 } else if (h->len < h->caplen) { 363 if (!invalid_header) { 364 invalid_header = 1; 365 ND_PRINT("[Invalid header:"); 366 } else 367 ND_PRINT(","); 368 ND_PRINT(" len(%u) < caplen(%u)", h->len, h->caplen); 369 } 370 if (h->caplen > MAXIMUM_SNAPLEN) { 371 if (!invalid_header) { 372 invalid_header = 1; 373 ND_PRINT("[Invalid header:"); 374 } else 375 ND_PRINT(","); 376 ND_PRINT(" caplen(%u) > %u", h->caplen, MAXIMUM_SNAPLEN); 377 } 378 if (h->len > MAXIMUM_SNAPLEN) { 379 if (!invalid_header) { 380 invalid_header = 1; 381 ND_PRINT("[Invalid header:"); 382 } else 383 ND_PRINT(","); 384 ND_PRINT(" len(%u) > %u", h->len, MAXIMUM_SNAPLEN); 385 } 386 if (invalid_header) { 387 ND_PRINT("]\n"); 388 return; 389 } 390 391 /* 392 * At this point: 393 * capture length != 0, 394 * packet length != 0, 395 * capture length <= MAXIMUM_SNAPLEN, 396 * packet length <= MAXIMUM_SNAPLEN, 397 * packet length >= capture length. 398 * 399 * Currently, there is no D-Bus printer, thus no need for 400 * bigger lengths. 401 */ 402 403 /* 404 * The header /usr/include/pcap/pcap.h in OpenBSD declares h->ts as 405 * struct bpf_timeval, not struct timeval. The former comes from 406 * /usr/include/net/bpf.h and uses 32-bit unsigned types instead of 407 * the types used in struct timeval. 408 */ 409 struct timeval tvbuf; 410 tvbuf.tv_sec = h->ts.tv_sec; 411 tvbuf.tv_usec = h->ts.tv_usec; 412 ts_print(ndo, &tvbuf); 413 414 /* 415 * Printers must check that they're not walking off the end of 416 * the packet. 417 * Rather than pass it all the way down, we set this member 418 * of the netdissect_options structure. 419 */ 420 ndo->ndo_snapend = sp + h->caplen; 421 ndo->ndo_packetp = sp; 422 423 ndo->ndo_protocol = ""; 424 ndo->ndo_ll_hdr_len = 0; 425 switch (setjmp(ndo->ndo_early_end)) { 426 case 0: 427 /* Print the packet. */ 428 (ndo->ndo_if_printer)(ndo, h, sp); 429 break; 430 case ND_TRUNCATED: 431 /* A printer quit because the packet was truncated; report it */ 432 nd_print_trunc(ndo); 433 /* Print the full packet */ 434 ndo->ndo_ll_hdr_len = 0; 435 #ifdef ENABLE_INSTRUMENT_FUNCTIONS 436 /* truncation => reassignment */ 437 profile_func_level = pretty_print_packet_level; 438 #endif 439 break; 440 } 441 hdrlen = ndo->ndo_ll_hdr_len; 442 443 /* 444 * Empty the stack of packet information, freeing all pushed buffers; 445 * if we got here by a printer quitting, we need to release anything 446 * that didn't get released because we longjmped out of the code 447 * before it popped the packet information. 448 */ 449 nd_pop_all_packet_info(ndo); 450 451 /* 452 * Restore the originals snapend and packetp, as a printer 453 * might have changed them. 454 * 455 * XXX - nd_pop_all_packet_info() should have restored the 456 * original values, but, just in case.... 457 */ 458 ndo->ndo_snapend = sp + h->caplen; 459 ndo->ndo_packetp = sp; 460 if (ndo->ndo_Xflag) { 461 /* 462 * Print the raw packet data in hex and ASCII. 463 */ 464 if (ndo->ndo_Xflag > 1) { 465 /* 466 * Include the link-layer header. 467 */ 468 hex_and_ascii_print(ndo, "\n\t", sp, h->caplen); 469 } else { 470 /* 471 * Don't include the link-layer header - and if 472 * we have nothing past the link-layer header, 473 * print nothing. 474 */ 475 if (h->caplen > hdrlen) 476 hex_and_ascii_print(ndo, "\n\t", sp + hdrlen, 477 h->caplen - hdrlen); 478 } 479 } else if (ndo->ndo_xflag) { 480 /* 481 * Print the raw packet data in hex. 482 */ 483 if (ndo->ndo_xflag > 1) { 484 /* 485 * Include the link-layer header. 486 */ 487 hex_print(ndo, "\n\t", sp, h->caplen); 488 } else { 489 /* 490 * Don't include the link-layer header - and if 491 * we have nothing past the link-layer header, 492 * print nothing. 493 */ 494 if (h->caplen > hdrlen) 495 hex_print(ndo, "\n\t", sp + hdrlen, 496 h->caplen - hdrlen); 497 } 498 } else if (ndo->ndo_Aflag) { 499 /* 500 * Print the raw packet data in ASCII. 501 */ 502 if (ndo->ndo_Aflag > 1) { 503 /* 504 * Include the link-layer header. 505 */ 506 ascii_print(ndo, sp, h->caplen); 507 } else { 508 /* 509 * Don't include the link-layer header - and if 510 * we have nothing past the link-layer header, 511 * print nothing. 512 */ 513 if (h->caplen > hdrlen) 514 ascii_print(ndo, sp + hdrlen, h->caplen - hdrlen); 515 } 516 } 517 518 ND_PRINT("\n"); 519 nd_free_all(ndo); 520 } 521 522 /* 523 * By default, print the specified data out in hex and ASCII. 524 */ 525 static void 526 ndo_default_print(netdissect_options *ndo, const u_char *bp, u_int length) 527 { 528 hex_and_ascii_print(ndo, "\n\t", bp, length); /* pass on lf and indentation string */ 529 } 530 531 /* VARARGS */ 532 static void 533 ndo_error(netdissect_options *ndo, status_exit_codes_t status, 534 const char *fmt, ...) 535 { 536 va_list ap; 537 538 if (ndo->program_name) 539 (void)fprintf(stderr, "%s: ", ndo->program_name); 540 va_start(ap, fmt); 541 (void)vfprintf(stderr, fmt, ap); 542 va_end(ap); 543 if (*fmt) { 544 fmt += strlen(fmt); 545 if (fmt[-1] != '\n') 546 (void)fputc('\n', stderr); 547 } 548 nd_cleanup(); 549 exit(status); 550 /* NOTREACHED */ 551 } 552 553 /* VARARGS */ 554 static void 555 ndo_warning(netdissect_options *ndo, const char *fmt, ...) 556 { 557 va_list ap; 558 559 if (ndo->program_name) 560 (void)fprintf(stderr, "%s: ", ndo->program_name); 561 (void)fprintf(stderr, "WARNING: "); 562 va_start(ap, fmt); 563 (void)vfprintf(stderr, fmt, ap); 564 va_end(ap); 565 if (*fmt) { 566 fmt += strlen(fmt); 567 if (fmt[-1] != '\n') 568 (void)fputc('\n', stderr); 569 } 570 } 571 572 static int 573 ndo_printf(netdissect_options *ndo, const char *fmt, ...) 574 { 575 va_list args; 576 int ret; 577 578 va_start(args, fmt); 579 ret = vfprintf(stdout, fmt, args); 580 va_end(args); 581 582 if (ret < 0) 583 ndo_error(ndo, S_ERR_ND_WRITE_FILE, 584 "Unable to write output: %s", pcap_strerror(errno)); 585 return (ret); 586 } 587 588 void 589 ndo_set_function_pointers(netdissect_options *ndo) 590 { 591 ndo->ndo_default_print=ndo_default_print; 592 ndo->ndo_printf=ndo_printf; 593 ndo->ndo_error=ndo_error; 594 ndo->ndo_warning=ndo_warning; 595 } 596