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