1784088dfSchristos /* 2784088dfSchristos * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 3784088dfSchristos * The Regents of the University of California. All rights reserved. 4784088dfSchristos * 5784088dfSchristos * Redistribution and use in source and binary forms, with or without 6784088dfSchristos * modification, are permitted provided that: (1) source code distributions 7784088dfSchristos * retain the above copyright notice and this paragraph in its entirety, (2) 8784088dfSchristos * distributions including binary code include the above copyright notice and 9784088dfSchristos * this paragraph in its entirety in the documentation or other materials 10784088dfSchristos * provided with the distribution, and (3) all advertising materials mentioning 11784088dfSchristos * features or use of this software display the following acknowledgement: 12784088dfSchristos * ``This product includes software developed by the University of California, 13784088dfSchristos * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14784088dfSchristos * the University nor the names of its contributors may be used to endorse 15784088dfSchristos * or promote products derived from this software without specific prior 16784088dfSchristos * written permission. 17784088dfSchristos * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18784088dfSchristos * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19784088dfSchristos * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20784088dfSchristos * 21784088dfSchristos * Support for splitting captures into multiple files with a maximum 22784088dfSchristos * file size: 23784088dfSchristos * 24784088dfSchristos * Copyright (c) 2001 25784088dfSchristos * Seth Webster <swebster@sst.ll.mit.edu> 26784088dfSchristos */ 27784088dfSchristos 28fdccd7e4Schristos #include <sys/cdefs.h> 29fdccd7e4Schristos #ifndef lint 30*26ba0b50Schristos __RCSID("$NetBSD: print.c,v 1.6 2024/09/02 16:15:33 christos Exp $"); 31fdccd7e4Schristos #endif 32fdccd7e4Schristos 33c74ad251Schristos #include <config.h> 34784088dfSchristos 35784088dfSchristos #include <stdlib.h> 36784088dfSchristos #include <string.h> 37c74ad251Schristos #include <setjmp.h> 38784088dfSchristos 39c74ad251Schristos #include "netdissect-stdinc.h" 40784088dfSchristos 41784088dfSchristos #include "netdissect.h" 42784088dfSchristos #include "addrtoname.h" 43784088dfSchristos #include "print.h" 44c74ad251Schristos #include "netdissect-alloc.h" 45c74ad251Schristos 46c74ad251Schristos #include "pcap-missing.h" 47784088dfSchristos 48784088dfSchristos struct printer { 49784088dfSchristos if_printer f; 50784088dfSchristos int type; 51784088dfSchristos }; 52784088dfSchristos 53784088dfSchristos static const struct printer printers[] = { 54c74ad251Schristos #ifdef DLT_APPLE_IP_OVER_IEEE1394 55c74ad251Schristos { ap1394_if_print, DLT_APPLE_IP_OVER_IEEE1394 }, 56c74ad251Schristos #endif 57c74ad251Schristos { arcnet_if_print, DLT_ARCNET }, 58c74ad251Schristos #ifdef DLT_ARCNET_LINUX 59c74ad251Schristos { arcnet_linux_if_print, DLT_ARCNET_LINUX }, 60c74ad251Schristos #endif 61c74ad251Schristos { atm_if_print, DLT_ATM_RFC1483 }, 62c74ad251Schristos #ifdef DLT_DSA_TAG_BRCM 63c74ad251Schristos { brcm_tag_if_print, DLT_DSA_TAG_BRCM }, 64c74ad251Schristos #endif 65c74ad251Schristos #ifdef DLT_DSA_TAG_BRCM_PREPEND 66c74ad251Schristos { brcm_tag_prepend_if_print, DLT_DSA_TAG_BRCM_PREPEND }, 67c74ad251Schristos #endif 68c74ad251Schristos #ifdef DLT_BLUETOOTH_HCI_H4_WITH_PHDR 69c74ad251Schristos { bt_if_print, DLT_BLUETOOTH_HCI_H4_WITH_PHDR}, 70c74ad251Schristos #endif 71c74ad251Schristos #ifdef DLT_C_HDLC 72c74ad251Schristos { chdlc_if_print, DLT_C_HDLC }, 73c74ad251Schristos #endif 74c74ad251Schristos #ifdef DLT_HDLC 75c74ad251Schristos { chdlc_if_print, DLT_HDLC }, 76c74ad251Schristos #endif 77c74ad251Schristos #ifdef DLT_ATM_CLIP 78c74ad251Schristos { cip_if_print, DLT_ATM_CLIP }, 79c74ad251Schristos #endif 80c74ad251Schristos #ifdef DLT_CIP 81c74ad251Schristos { cip_if_print, DLT_CIP }, 82c74ad251Schristos #endif 83c74ad251Schristos #ifdef DLT_DSA_TAG_DSA 84c74ad251Schristos { dsa_if_print, DLT_DSA_TAG_DSA }, 85c74ad251Schristos #endif 86c74ad251Schristos #ifdef DLT_DSA_TAG_EDSA 87c74ad251Schristos { edsa_if_print, DLT_DSA_TAG_EDSA }, 88c74ad251Schristos #endif 89c74ad251Schristos #ifdef DLT_ENC 90c74ad251Schristos { enc_if_print, DLT_ENC }, 91c74ad251Schristos #endif 92784088dfSchristos { ether_if_print, DLT_EN10MB }, 93c74ad251Schristos { fddi_if_print, DLT_FDDI }, 94c74ad251Schristos #ifdef DLT_FR 95c74ad251Schristos { fr_if_print, DLT_FR }, 96c74ad251Schristos #endif 97c74ad251Schristos #ifdef DLT_FRELAY 98c74ad251Schristos { fr_if_print, DLT_FRELAY }, 99c74ad251Schristos #endif 100c74ad251Schristos #ifdef DLT_IEEE802_11 101c74ad251Schristos { ieee802_11_if_print, DLT_IEEE802_11}, 102c74ad251Schristos #endif 103c74ad251Schristos #ifdef DLT_IEEE802_11_RADIO_AVS 104c74ad251Schristos { ieee802_11_radio_avs_if_print, DLT_IEEE802_11_RADIO_AVS }, 105c74ad251Schristos #endif 106c74ad251Schristos #ifdef DLT_IEEE802_11_RADIO 107c74ad251Schristos { ieee802_11_radio_if_print, DLT_IEEE802_11_RADIO }, 108784088dfSchristos #endif 109784088dfSchristos #ifdef DLT_IEEE802_15_4 110784088dfSchristos { ieee802_15_4_if_print, DLT_IEEE802_15_4 }, 111784088dfSchristos #endif 112784088dfSchristos #ifdef DLT_IEEE802_15_4_NOFCS 113784088dfSchristos { ieee802_15_4_if_print, DLT_IEEE802_15_4_NOFCS }, 114784088dfSchristos #endif 115c74ad251Schristos #ifdef DLT_IEEE802_15_4_TAP 116c74ad251Schristos { ieee802_15_4_tap_if_print, DLT_IEEE802_15_4_TAP }, 117c74ad251Schristos #endif 118c74ad251Schristos #ifdef DLT_IP_OVER_FC 119c74ad251Schristos { ipfc_if_print, DLT_IP_OVER_FC }, 120c74ad251Schristos #endif 121c74ad251Schristos #ifdef DLT_IPNET 122c74ad251Schristos { ipnet_if_print, DLT_IPNET }, 123c74ad251Schristos #endif 124c74ad251Schristos #ifdef DLT_IPOIB 125c74ad251Schristos { ipoib_if_print, DLT_IPOIB }, 126c74ad251Schristos #endif 127c74ad251Schristos #ifdef DLT_JUNIPER_ATM1 128c74ad251Schristos { juniper_atm1_if_print, DLT_JUNIPER_ATM1 }, 129c74ad251Schristos #endif 130c74ad251Schristos #ifdef DLT_JUNIPER_ATM2 131c74ad251Schristos { juniper_atm2_if_print, DLT_JUNIPER_ATM2 }, 132c74ad251Schristos #endif 133c74ad251Schristos #ifdef DLT_JUNIPER_CHDLC 134c74ad251Schristos { juniper_chdlc_if_print, DLT_JUNIPER_CHDLC }, 135c74ad251Schristos #endif 136c74ad251Schristos #ifdef DLT_JUNIPER_ES 137c74ad251Schristos { juniper_es_if_print, DLT_JUNIPER_ES }, 138c74ad251Schristos #endif 139c74ad251Schristos #ifdef DLT_JUNIPER_ETHER 140c74ad251Schristos { juniper_ether_if_print, DLT_JUNIPER_ETHER }, 141c74ad251Schristos #endif 142c74ad251Schristos #ifdef DLT_JUNIPER_FRELAY 143c74ad251Schristos { juniper_frelay_if_print, DLT_JUNIPER_FRELAY }, 144c74ad251Schristos #endif 145c74ad251Schristos #ifdef DLT_JUNIPER_GGSN 146c74ad251Schristos { juniper_ggsn_if_print, DLT_JUNIPER_GGSN }, 147c74ad251Schristos #endif 148c74ad251Schristos #ifdef DLT_JUNIPER_MFR 149c74ad251Schristos { juniper_mfr_if_print, DLT_JUNIPER_MFR }, 150c74ad251Schristos #endif 151c74ad251Schristos #ifdef DLT_JUNIPER_MLFR 152c74ad251Schristos { juniper_mlfr_if_print, DLT_JUNIPER_MLFR }, 153c74ad251Schristos #endif 154c74ad251Schristos #ifdef DLT_JUNIPER_MLPPP 155c74ad251Schristos { juniper_mlppp_if_print, DLT_JUNIPER_MLPPP }, 156c74ad251Schristos #endif 157c74ad251Schristos #ifdef DLT_JUNIPER_MONITOR 158c74ad251Schristos { juniper_monitor_if_print, DLT_JUNIPER_MONITOR }, 159c74ad251Schristos #endif 160c74ad251Schristos #ifdef DLT_JUNIPER_PPP 161c74ad251Schristos { juniper_ppp_if_print, DLT_JUNIPER_PPP }, 162c74ad251Schristos #endif 163c74ad251Schristos #ifdef DLT_JUNIPER_PPPOE_ATM 164c74ad251Schristos { juniper_pppoe_atm_if_print, DLT_JUNIPER_PPPOE_ATM }, 165c74ad251Schristos #endif 166c74ad251Schristos #ifdef DLT_JUNIPER_PPPOE 167c74ad251Schristos { juniper_pppoe_if_print, DLT_JUNIPER_PPPOE }, 168c74ad251Schristos #endif 169c74ad251Schristos #ifdef DLT_JUNIPER_SERVICES 170c74ad251Schristos { juniper_services_if_print, DLT_JUNIPER_SERVICES }, 171c74ad251Schristos #endif 172c74ad251Schristos #ifdef DLT_LTALK 173c74ad251Schristos { ltalk_if_print, DLT_LTALK }, 174c74ad251Schristos #endif 175c74ad251Schristos #ifdef DLT_MFR 176c74ad251Schristos { mfr_if_print, DLT_MFR }, 177784088dfSchristos #endif 178784088dfSchristos #ifdef DLT_NETANALYZER 179784088dfSchristos { netanalyzer_if_print, DLT_NETANALYZER }, 180784088dfSchristos #endif 181784088dfSchristos #ifdef DLT_NETANALYZER_TRANSPARENT 182784088dfSchristos { netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT }, 183784088dfSchristos #endif 184c74ad251Schristos #ifdef DLT_NFLOG 185784088dfSchristos { nflog_if_print, DLT_NFLOG}, 186784088dfSchristos #endif 187784088dfSchristos { null_if_print, DLT_NULL }, 188784088dfSchristos #ifdef DLT_LOOP 189784088dfSchristos { null_if_print, DLT_LOOP }, 190784088dfSchristos #endif 191c74ad251Schristos #ifdef DLT_PFLOG 192c74ad251Schristos { pflog_if_print, DLT_PFLOG }, 193784088dfSchristos #endif 194c74ad251Schristos #ifdef DLT_PKTAP 195c74ad251Schristos { pktap_if_print, DLT_PKTAP }, 196784088dfSchristos #endif 197c74ad251Schristos #ifdef DLT_PPI 198c74ad251Schristos { ppi_if_print, DLT_PPI }, 199784088dfSchristos #endif 200c74ad251Schristos #ifdef DLT_PPP_BSDOS 201c74ad251Schristos { ppp_bsdos_if_print, DLT_PPP_BSDOS }, 202c74ad251Schristos #endif 203c74ad251Schristos #ifdef DLT_PPP_SERIAL 204c74ad251Schristos { ppp_hdlc_if_print, DLT_PPP_SERIAL }, 205c74ad251Schristos #endif 206c74ad251Schristos { ppp_if_print, DLT_PPP }, 207c74ad251Schristos #ifdef DLT_PPP_PPPD 208c74ad251Schristos { ppp_if_print, DLT_PPP_PPPD }, 209c74ad251Schristos #endif 210c74ad251Schristos #ifdef DLT_PPP_ETHER 211c74ad251Schristos { pppoe_if_print, DLT_PPP_ETHER }, 212c74ad251Schristos #endif 213c74ad251Schristos #ifdef DLT_PRISM_HEADER 214c74ad251Schristos { prism_if_print, DLT_PRISM_HEADER }, 215784088dfSchristos #endif 216784088dfSchristos { raw_if_print, DLT_RAW }, 217784088dfSchristos #ifdef DLT_IPV4 218784088dfSchristos { raw_if_print, DLT_IPV4 }, 219784088dfSchristos #endif 220784088dfSchristos #ifdef DLT_IPV6 221784088dfSchristos { raw_if_print, DLT_IPV6 }, 222784088dfSchristos #endif 223784088dfSchristos #ifdef DLT_SLIP_BSDOS 224784088dfSchristos { sl_bsdos_if_print, DLT_SLIP_BSDOS }, 225784088dfSchristos #endif 226c74ad251Schristos { sl_if_print, DLT_SLIP }, 227c74ad251Schristos #ifdef DLT_LINUX_SLL 228c74ad251Schristos { sll_if_print, DLT_LINUX_SLL }, 229784088dfSchristos #endif 230c74ad251Schristos #ifdef DLT_LINUX_SLL2 231c74ad251Schristos { sll2_if_print, DLT_LINUX_SLL2 }, 232784088dfSchristos #endif 233c74ad251Schristos #ifdef DLT_SUNATM 234c74ad251Schristos { sunatm_if_print, DLT_SUNATM }, 235784088dfSchristos #endif 236c74ad251Schristos #ifdef DLT_SYMANTEC_FIREWALL 237c74ad251Schristos { symantec_if_print, DLT_SYMANTEC_FIREWALL }, 238784088dfSchristos #endif 239c74ad251Schristos { token_if_print, DLT_IEEE802 }, 240c74ad251Schristos #ifdef DLT_USB_LINUX 241c74ad251Schristos { usb_linux_48_byte_if_print, DLT_USB_LINUX}, 242c74ad251Schristos #endif /* DLT_USB_LINUX */ 243c74ad251Schristos #ifdef DLT_USB_LINUX_MMAPPED 244c74ad251Schristos { usb_linux_64_byte_if_print, DLT_USB_LINUX_MMAPPED}, 245c74ad251Schristos #endif /* DLT_USB_LINUX_MMAPPED */ 246c74ad251Schristos #ifdef DLT_VSOCK 247c74ad251Schristos { vsock_if_print, DLT_VSOCK }, 248784088dfSchristos #endif 249fdccd7e4Schristos #ifdef DLT_PFSYNC 250fdccd7e4Schristos { pfsync_if_print, DLT_PFSYNC }, 251fdccd7e4Schristos #endif 252784088dfSchristos { NULL, 0 }, 253784088dfSchristos }; 254784088dfSchristos 255784088dfSchristos static void ndo_default_print(netdissect_options *ndo, const u_char *bp, 256784088dfSchristos u_int length); 257784088dfSchristos 258c74ad251Schristos static void NORETURN ndo_error(netdissect_options *ndo, 259c74ad251Schristos status_exit_codes_t status, 26072c96ff3Schristos FORMAT_STRING(const char *fmt), ...) 261c74ad251Schristos PRINTFLIKE(3, 4); 26272c96ff3Schristos static void ndo_warning(netdissect_options *ndo, 26372c96ff3Schristos FORMAT_STRING(const char *fmt), ...) 26472c96ff3Schristos PRINTFLIKE(2, 3); 265784088dfSchristos 26672c96ff3Schristos static int ndo_printf(netdissect_options *ndo, 26772c96ff3Schristos FORMAT_STRING(const char *fmt), ...) 26872c96ff3Schristos PRINTFLIKE(2, 3); 269784088dfSchristos 270784088dfSchristos void 271c74ad251Schristos init_print(netdissect_options *ndo, uint32_t localnet, uint32_t mask) 272784088dfSchristos { 273784088dfSchristos init_addrtoname(ndo, localnet, mask); 274784088dfSchristos } 275784088dfSchristos 276784088dfSchristos if_printer 277784088dfSchristos lookup_printer(int type) 278784088dfSchristos { 279784088dfSchristos const struct printer *p; 280784088dfSchristos 281784088dfSchristos for (p = printers; p->f; ++p) 282784088dfSchristos if (type == p->type) 283784088dfSchristos return p->f; 284784088dfSchristos 285784088dfSchristos #if defined(DLT_USER2) && defined(DLT_PKTAP) 286784088dfSchristos /* 287784088dfSchristos * Apple incorrectly chose to use DLT_USER2 for their PKTAP 288784088dfSchristos * header. 289784088dfSchristos * 290784088dfSchristos * We map DLT_PKTAP, whether it's DLT_USER2 as it is on Darwin- 291784088dfSchristos * based OSes or the same value as LINKTYPE_PKTAP as it is on 292784088dfSchristos * other OSes, to LINKTYPE_PKTAP, so files written with 293784088dfSchristos * this version of libpcap for a DLT_PKTAP capture have a link- 294784088dfSchristos * layer header type of LINKTYPE_PKTAP. 295784088dfSchristos * 296784088dfSchristos * However, files written on OS X Mavericks for a DLT_PKTAP 297784088dfSchristos * capture have a link-layer header type of LINKTYPE_USER2. 298784088dfSchristos * If we don't have a printer for DLT_USER2, and type is 299784088dfSchristos * DLT_USER2, we look up the printer for DLT_PKTAP and use 300784088dfSchristos * that. 301784088dfSchristos */ 302784088dfSchristos if (type == DLT_USER2) { 303784088dfSchristos for (p = printers; p->f; ++p) 304784088dfSchristos if (DLT_PKTAP == p->type) 305784088dfSchristos return p->f; 306784088dfSchristos } 307784088dfSchristos #endif 308784088dfSchristos 309784088dfSchristos return NULL; 310784088dfSchristos /* NOTREACHED */ 311784088dfSchristos } 312784088dfSchristos 313784088dfSchristos int 314784088dfSchristos has_printer(int type) 315784088dfSchristos { 316784088dfSchristos return (lookup_printer(type) != NULL); 317784088dfSchristos } 318784088dfSchristos 319784088dfSchristos if_printer 320c74ad251Schristos get_if_printer(int type) 321784088dfSchristos { 322784088dfSchristos if_printer printer; 323784088dfSchristos 324784088dfSchristos printer = lookup_printer(type); 325c74ad251Schristos if (printer == NULL) 326c74ad251Schristos printer = unsupported_if_print; 327784088dfSchristos return printer; 328784088dfSchristos } 329784088dfSchristos 330*26ba0b50Schristos #ifdef ENABLE_INSTRUMENT_FUNCTIONS 331*26ba0b50Schristos extern int profile_func_level; 332*26ba0b50Schristos static int pretty_print_packet_level = -1; 333*26ba0b50Schristos #endif 334*26ba0b50Schristos 335784088dfSchristos void 336784088dfSchristos pretty_print_packet(netdissect_options *ndo, const struct pcap_pkthdr *h, 337784088dfSchristos const u_char *sp, u_int packets_captured) 338784088dfSchristos { 339c74ad251Schristos u_int hdrlen = 0; 340c74ad251Schristos int invalid_header = 0; 341784088dfSchristos 342*26ba0b50Schristos #ifdef ENABLE_INSTRUMENT_FUNCTIONS 343*26ba0b50Schristos if (pretty_print_packet_level == -1) 344*26ba0b50Schristos pretty_print_packet_level = profile_func_level; 345*26ba0b50Schristos #endif 346*26ba0b50Schristos 347784088dfSchristos if (ndo->ndo_packet_number) 348c74ad251Schristos ND_PRINT("%5u ", packets_captured); 349784088dfSchristos 350c74ad251Schristos /* Sanity checks on packet length / capture length */ 351c74ad251Schristos if (h->caplen == 0) { 352c74ad251Schristos invalid_header = 1; 353c74ad251Schristos ND_PRINT("[Invalid header: caplen==0"); 354c74ad251Schristos } 355c74ad251Schristos if (h->len == 0) { 356c74ad251Schristos if (!invalid_header) { 357c74ad251Schristos invalid_header = 1; 358c74ad251Schristos ND_PRINT("[Invalid header:"); 359c74ad251Schristos } else 360c74ad251Schristos ND_PRINT(","); 361c74ad251Schristos ND_PRINT(" len==0"); 362c74ad251Schristos } else if (h->len < h->caplen) { 363c74ad251Schristos if (!invalid_header) { 364c74ad251Schristos invalid_header = 1; 365c74ad251Schristos ND_PRINT("[Invalid header:"); 366c74ad251Schristos } else 367c74ad251Schristos ND_PRINT(","); 368c74ad251Schristos ND_PRINT(" len(%u) < caplen(%u)", h->len, h->caplen); 369c74ad251Schristos } 370c74ad251Schristos if (h->caplen > MAXIMUM_SNAPLEN) { 371c74ad251Schristos if (!invalid_header) { 372c74ad251Schristos invalid_header = 1; 373c74ad251Schristos ND_PRINT("[Invalid header:"); 374c74ad251Schristos } else 375c74ad251Schristos ND_PRINT(","); 376c74ad251Schristos ND_PRINT(" caplen(%u) > %u", h->caplen, MAXIMUM_SNAPLEN); 377c74ad251Schristos } 378c74ad251Schristos if (h->len > MAXIMUM_SNAPLEN) { 379c74ad251Schristos if (!invalid_header) { 380c74ad251Schristos invalid_header = 1; 381c74ad251Schristos ND_PRINT("[Invalid header:"); 382c74ad251Schristos } else 383c74ad251Schristos ND_PRINT(","); 384c74ad251Schristos ND_PRINT(" len(%u) > %u", h->len, MAXIMUM_SNAPLEN); 385c74ad251Schristos } 386c74ad251Schristos if (invalid_header) { 387c74ad251Schristos ND_PRINT("]\n"); 388c74ad251Schristos return; 389c74ad251Schristos } 390784088dfSchristos 391784088dfSchristos /* 392c74ad251Schristos * At this point: 393c74ad251Schristos * capture length != 0, 394c74ad251Schristos * packet length != 0, 395c74ad251Schristos * capture length <= MAXIMUM_SNAPLEN, 396c74ad251Schristos * packet length <= MAXIMUM_SNAPLEN, 397c74ad251Schristos * packet length >= capture length. 398c74ad251Schristos * 399c74ad251Schristos * Currently, there is no D-Bus printer, thus no need for 400c74ad251Schristos * bigger lengths. 401c74ad251Schristos */ 402c74ad251Schristos 403c74ad251Schristos /* 404c74ad251Schristos * The header /usr/include/pcap/pcap.h in OpenBSD declares h->ts as 405c74ad251Schristos * struct bpf_timeval, not struct timeval. The former comes from 406c74ad251Schristos * /usr/include/net/bpf.h and uses 32-bit unsigned types instead of 407c74ad251Schristos * the types used in struct timeval. 408c74ad251Schristos */ 409c74ad251Schristos struct timeval tvbuf; 410c74ad251Schristos tvbuf.tv_sec = h->ts.tv_sec; 411c74ad251Schristos tvbuf.tv_usec = h->ts.tv_usec; 412c74ad251Schristos ts_print(ndo, &tvbuf); 413c74ad251Schristos 414c74ad251Schristos /* 415c74ad251Schristos * Printers must check that they're not walking off the end of 416c74ad251Schristos * the packet. 417784088dfSchristos * Rather than pass it all the way down, we set this member 418784088dfSchristos * of the netdissect_options structure. 419784088dfSchristos */ 420784088dfSchristos ndo->ndo_snapend = sp + h->caplen; 421c74ad251Schristos ndo->ndo_packetp = sp; 422784088dfSchristos 423c74ad251Schristos ndo->ndo_protocol = ""; 424c74ad251Schristos ndo->ndo_ll_hdr_len = 0; 425c74ad251Schristos switch (setjmp(ndo->ndo_early_end)) { 426c74ad251Schristos case 0: 427c74ad251Schristos /* Print the packet. */ 428c74ad251Schristos (ndo->ndo_if_printer)(ndo, h, sp); 429c74ad251Schristos break; 430c74ad251Schristos case ND_TRUNCATED: 431c74ad251Schristos /* A printer quit because the packet was truncated; report it */ 432c74ad251Schristos nd_print_trunc(ndo); 433c74ad251Schristos /* Print the full packet */ 434c74ad251Schristos ndo->ndo_ll_hdr_len = 0; 435*26ba0b50Schristos #ifdef ENABLE_INSTRUMENT_FUNCTIONS 436*26ba0b50Schristos /* truncation => reassignment */ 437*26ba0b50Schristos profile_func_level = pretty_print_packet_level; 438*26ba0b50Schristos #endif 439c74ad251Schristos break; 440c74ad251Schristos } 441c74ad251Schristos hdrlen = ndo->ndo_ll_hdr_len; 442c74ad251Schristos 443c74ad251Schristos /* 444c74ad251Schristos * Empty the stack of packet information, freeing all pushed buffers; 445c74ad251Schristos * if we got here by a printer quitting, we need to release anything 446c74ad251Schristos * that didn't get released because we longjmped out of the code 447c74ad251Schristos * before it popped the packet information. 448c74ad251Schristos */ 449c74ad251Schristos nd_pop_all_packet_info(ndo); 450784088dfSchristos 451784088dfSchristos /* 452*26ba0b50Schristos * Restore the originals snapend and packetp, as a printer 453*26ba0b50Schristos * might have changed them. 454*26ba0b50Schristos * 455*26ba0b50Schristos * XXX - nd_pop_all_packet_info() should have restored the 456*26ba0b50Schristos * original values, but, just in case.... 457784088dfSchristos */ 458784088dfSchristos ndo->ndo_snapend = sp + h->caplen; 459*26ba0b50Schristos ndo->ndo_packetp = sp; 460784088dfSchristos if (ndo->ndo_Xflag) { 461784088dfSchristos /* 462784088dfSchristos * Print the raw packet data in hex and ASCII. 463784088dfSchristos */ 464784088dfSchristos if (ndo->ndo_Xflag > 1) { 465784088dfSchristos /* 466784088dfSchristos * Include the link-layer header. 467784088dfSchristos */ 468784088dfSchristos hex_and_ascii_print(ndo, "\n\t", sp, h->caplen); 469784088dfSchristos } else { 470784088dfSchristos /* 471784088dfSchristos * Don't include the link-layer header - and if 472784088dfSchristos * we have nothing past the link-layer header, 473784088dfSchristos * print nothing. 474784088dfSchristos */ 475784088dfSchristos if (h->caplen > hdrlen) 476784088dfSchristos hex_and_ascii_print(ndo, "\n\t", sp + hdrlen, 477784088dfSchristos h->caplen - hdrlen); 478784088dfSchristos } 479784088dfSchristos } else if (ndo->ndo_xflag) { 480784088dfSchristos /* 481784088dfSchristos * Print the raw packet data in hex. 482784088dfSchristos */ 483784088dfSchristos if (ndo->ndo_xflag > 1) { 484784088dfSchristos /* 485784088dfSchristos * Include the link-layer header. 486784088dfSchristos */ 487784088dfSchristos hex_print(ndo, "\n\t", sp, h->caplen); 488784088dfSchristos } else { 489784088dfSchristos /* 490784088dfSchristos * Don't include the link-layer header - and if 491784088dfSchristos * we have nothing past the link-layer header, 492784088dfSchristos * print nothing. 493784088dfSchristos */ 494784088dfSchristos if (h->caplen > hdrlen) 495784088dfSchristos hex_print(ndo, "\n\t", sp + hdrlen, 496784088dfSchristos h->caplen - hdrlen); 497784088dfSchristos } 498784088dfSchristos } else if (ndo->ndo_Aflag) { 499784088dfSchristos /* 500784088dfSchristos * Print the raw packet data in ASCII. 501784088dfSchristos */ 502784088dfSchristos if (ndo->ndo_Aflag > 1) { 503784088dfSchristos /* 504784088dfSchristos * Include the link-layer header. 505784088dfSchristos */ 506784088dfSchristos ascii_print(ndo, sp, h->caplen); 507784088dfSchristos } else { 508784088dfSchristos /* 509784088dfSchristos * Don't include the link-layer header - and if 510784088dfSchristos * we have nothing past the link-layer header, 511784088dfSchristos * print nothing. 512784088dfSchristos */ 513784088dfSchristos if (h->caplen > hdrlen) 514784088dfSchristos ascii_print(ndo, sp + hdrlen, h->caplen - hdrlen); 515784088dfSchristos } 516784088dfSchristos } 517784088dfSchristos 518c74ad251Schristos ND_PRINT("\n"); 519c74ad251Schristos nd_free_all(ndo); 520784088dfSchristos } 521784088dfSchristos 522784088dfSchristos /* 523784088dfSchristos * By default, print the specified data out in hex and ASCII. 524784088dfSchristos */ 525784088dfSchristos static void 526784088dfSchristos ndo_default_print(netdissect_options *ndo, const u_char *bp, u_int length) 527784088dfSchristos { 528784088dfSchristos hex_and_ascii_print(ndo, "\n\t", bp, length); /* pass on lf and indentation string */ 529784088dfSchristos } 530784088dfSchristos 531784088dfSchristos /* VARARGS */ 532784088dfSchristos static void 533c74ad251Schristos ndo_error(netdissect_options *ndo, status_exit_codes_t status, 534c74ad251Schristos const char *fmt, ...) 535784088dfSchristos { 536784088dfSchristos va_list ap; 537784088dfSchristos 538784088dfSchristos if (ndo->program_name) 539784088dfSchristos (void)fprintf(stderr, "%s: ", ndo->program_name); 540784088dfSchristos va_start(ap, fmt); 541784088dfSchristos (void)vfprintf(stderr, fmt, ap); 542784088dfSchristos va_end(ap); 543784088dfSchristos if (*fmt) { 544784088dfSchristos fmt += strlen(fmt); 545784088dfSchristos if (fmt[-1] != '\n') 546784088dfSchristos (void)fputc('\n', stderr); 547784088dfSchristos } 548dc860a36Sspz nd_cleanup(); 549c74ad251Schristos exit(status); 550784088dfSchristos /* NOTREACHED */ 551784088dfSchristos } 552784088dfSchristos 553784088dfSchristos /* VARARGS */ 554784088dfSchristos static void 555784088dfSchristos ndo_warning(netdissect_options *ndo, const char *fmt, ...) 556784088dfSchristos { 557784088dfSchristos va_list ap; 558784088dfSchristos 559784088dfSchristos if (ndo->program_name) 560784088dfSchristos (void)fprintf(stderr, "%s: ", ndo->program_name); 561784088dfSchristos (void)fprintf(stderr, "WARNING: "); 562784088dfSchristos va_start(ap, fmt); 563784088dfSchristos (void)vfprintf(stderr, fmt, ap); 564784088dfSchristos va_end(ap); 565784088dfSchristos if (*fmt) { 566784088dfSchristos fmt += strlen(fmt); 567784088dfSchristos if (fmt[-1] != '\n') 568784088dfSchristos (void)fputc('\n', stderr); 569784088dfSchristos } 570784088dfSchristos } 571784088dfSchristos 572784088dfSchristos static int 573dc860a36Sspz ndo_printf(netdissect_options *ndo, const char *fmt, ...) 574784088dfSchristos { 575784088dfSchristos va_list args; 576784088dfSchristos int ret; 577784088dfSchristos 578784088dfSchristos va_start(args, fmt); 579784088dfSchristos ret = vfprintf(stdout, fmt, args); 580784088dfSchristos va_end(args); 581784088dfSchristos 582784088dfSchristos if (ret < 0) 583c74ad251Schristos ndo_error(ndo, S_ERR_ND_WRITE_FILE, 584c74ad251Schristos "Unable to write output: %s", pcap_strerror(errno)); 585784088dfSchristos return (ret); 586784088dfSchristos } 587784088dfSchristos 588784088dfSchristos void 589784088dfSchristos ndo_set_function_pointers(netdissect_options *ndo) 590784088dfSchristos { 591784088dfSchristos ndo->ndo_default_print=ndo_default_print; 592784088dfSchristos ndo->ndo_printf=ndo_printf; 593784088dfSchristos ndo->ndo_error=ndo_error; 594784088dfSchristos ndo->ndo_warning=ndo_warning; 595784088dfSchristos } 596