xref: /freebsd/contrib/tcpdump/print.c (revision 0bff6a5af8cb6d8e5123f8b667df78cac885dbb7)
13340d773SGleb Smirnoff /*
23340d773SGleb Smirnoff  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
33340d773SGleb Smirnoff  *	The Regents of the University of California.  All rights reserved.
43340d773SGleb Smirnoff  *
53340d773SGleb Smirnoff  * Redistribution and use in source and binary forms, with or without
63340d773SGleb Smirnoff  * modification, are permitted provided that: (1) source code distributions
73340d773SGleb Smirnoff  * retain the above copyright notice and this paragraph in its entirety, (2)
83340d773SGleb Smirnoff  * distributions including binary code include the above copyright notice and
93340d773SGleb Smirnoff  * this paragraph in its entirety in the documentation or other materials
103340d773SGleb Smirnoff  * provided with the distribution, and (3) all advertising materials mentioning
113340d773SGleb Smirnoff  * features or use of this software display the following acknowledgement:
123340d773SGleb Smirnoff  * ``This product includes software developed by the University of California,
133340d773SGleb Smirnoff  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
143340d773SGleb Smirnoff  * the University nor the names of its contributors may be used to endorse
153340d773SGleb Smirnoff  * or promote products derived from this software without specific prior
163340d773SGleb Smirnoff  * written permission.
173340d773SGleb Smirnoff  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
183340d773SGleb Smirnoff  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
193340d773SGleb Smirnoff  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
203340d773SGleb Smirnoff  *
213340d773SGleb Smirnoff  * Support for splitting captures into multiple files with a maximum
223340d773SGleb Smirnoff  * file size:
233340d773SGleb Smirnoff  *
243340d773SGleb Smirnoff  * Copyright (c) 2001
253340d773SGleb Smirnoff  *	Seth Webster <swebster@sst.ll.mit.edu>
263340d773SGleb Smirnoff  */
273340d773SGleb Smirnoff 
283340d773SGleb Smirnoff #ifdef HAVE_CONFIG_H
293340d773SGleb Smirnoff #include "config.h"
303340d773SGleb Smirnoff #endif
313340d773SGleb Smirnoff 
323340d773SGleb Smirnoff #include <stdlib.h>
333340d773SGleb Smirnoff #include <string.h>
343340d773SGleb Smirnoff 
353340d773SGleb Smirnoff #include <netdissect-stdinc.h>
363340d773SGleb Smirnoff 
373340d773SGleb Smirnoff #include "netdissect.h"
383340d773SGleb Smirnoff #include "addrtoname.h"
393340d773SGleb Smirnoff #include "print.h"
403340d773SGleb Smirnoff 
413340d773SGleb Smirnoff struct printer {
423340d773SGleb Smirnoff 	if_printer f;
433340d773SGleb Smirnoff 	int type;
443340d773SGleb Smirnoff };
453340d773SGleb Smirnoff 
463340d773SGleb Smirnoff static const struct printer printers[] = {
473340d773SGleb Smirnoff 	{ ether_if_print,	DLT_EN10MB },
483340d773SGleb Smirnoff #ifdef DLT_IPNET
493340d773SGleb Smirnoff 	{ ipnet_if_print,	DLT_IPNET },
503340d773SGleb Smirnoff #endif
513340d773SGleb Smirnoff #ifdef DLT_IEEE802_15_4
523340d773SGleb Smirnoff 	{ ieee802_15_4_if_print, DLT_IEEE802_15_4 },
533340d773SGleb Smirnoff #endif
543340d773SGleb Smirnoff #ifdef DLT_IEEE802_15_4_NOFCS
553340d773SGleb Smirnoff 	{ ieee802_15_4_if_print, DLT_IEEE802_15_4_NOFCS },
563340d773SGleb Smirnoff #endif
573340d773SGleb Smirnoff #ifdef DLT_PPI
583340d773SGleb Smirnoff 	{ ppi_if_print,		DLT_PPI },
593340d773SGleb Smirnoff #endif
603340d773SGleb Smirnoff #ifdef DLT_NETANALYZER
613340d773SGleb Smirnoff 	{ netanalyzer_if_print, DLT_NETANALYZER },
623340d773SGleb Smirnoff #endif
633340d773SGleb Smirnoff #ifdef DLT_NETANALYZER_TRANSPARENT
643340d773SGleb Smirnoff 	{ netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT },
653340d773SGleb Smirnoff #endif
663340d773SGleb Smirnoff #if defined(DLT_NFLOG) && defined(HAVE_PCAP_NFLOG_H)
673340d773SGleb Smirnoff 	{ nflog_if_print,	DLT_NFLOG},
683340d773SGleb Smirnoff #endif
693340d773SGleb Smirnoff #ifdef DLT_CIP
703340d773SGleb Smirnoff 	{ cip_if_print,         DLT_CIP },
713340d773SGleb Smirnoff #endif
723340d773SGleb Smirnoff #ifdef DLT_ATM_CLIP
733340d773SGleb Smirnoff 	{ cip_if_print,		DLT_ATM_CLIP },
743340d773SGleb Smirnoff #endif
753340d773SGleb Smirnoff #ifdef DLT_IP_OVER_FC
763340d773SGleb Smirnoff 	{ ipfc_if_print,	DLT_IP_OVER_FC },
773340d773SGleb Smirnoff #endif
783340d773SGleb Smirnoff 	{ null_if_print,	DLT_NULL },
793340d773SGleb Smirnoff #ifdef DLT_LOOP
803340d773SGleb Smirnoff 	{ null_if_print,	DLT_LOOP },
813340d773SGleb Smirnoff #endif
823340d773SGleb Smirnoff #ifdef DLT_APPLE_IP_OVER_IEEE1394
833340d773SGleb Smirnoff 	{ ap1394_if_print,	DLT_APPLE_IP_OVER_IEEE1394 },
843340d773SGleb Smirnoff #endif
853340d773SGleb Smirnoff #if defined(DLT_BLUETOOTH_HCI_H4_WITH_PHDR) && defined(HAVE_PCAP_BLUETOOTH_H)
863340d773SGleb Smirnoff 	{ bt_if_print,		DLT_BLUETOOTH_HCI_H4_WITH_PHDR},
873340d773SGleb Smirnoff #endif
883340d773SGleb Smirnoff #ifdef DLT_LANE8023
893340d773SGleb Smirnoff 	{ lane_if_print,        DLT_LANE8023 },
903340d773SGleb Smirnoff #endif
913340d773SGleb Smirnoff 	{ arcnet_if_print,	DLT_ARCNET },
923340d773SGleb Smirnoff #ifdef DLT_ARCNET_LINUX
933340d773SGleb Smirnoff 	{ arcnet_linux_if_print, DLT_ARCNET_LINUX },
943340d773SGleb Smirnoff #endif
953340d773SGleb Smirnoff 	{ raw_if_print,		DLT_RAW },
963340d773SGleb Smirnoff #ifdef DLT_IPV4
973340d773SGleb Smirnoff 	{ raw_if_print,		DLT_IPV4 },
983340d773SGleb Smirnoff #endif
993340d773SGleb Smirnoff #ifdef DLT_IPV6
1003340d773SGleb Smirnoff 	{ raw_if_print,		DLT_IPV6 },
1013340d773SGleb Smirnoff #endif
1023340d773SGleb Smirnoff #ifdef HAVE_PCAP_USB_H
1033340d773SGleb Smirnoff #ifdef DLT_USB_LINUX
1043340d773SGleb Smirnoff 	{ usb_linux_48_byte_print, DLT_USB_LINUX},
1053340d773SGleb Smirnoff #endif /* DLT_USB_LINUX */
1063340d773SGleb Smirnoff #ifdef DLT_USB_LINUX_MMAPPED
1073340d773SGleb Smirnoff 	{ usb_linux_64_byte_print, DLT_USB_LINUX_MMAPPED},
1083340d773SGleb Smirnoff #endif /* DLT_USB_LINUX_MMAPPED */
1093340d773SGleb Smirnoff #endif /* HAVE_PCAP_USB_H */
1103340d773SGleb Smirnoff #ifdef DLT_SYMANTEC_FIREWALL
1113340d773SGleb Smirnoff 	{ symantec_if_print,	DLT_SYMANTEC_FIREWALL },
1123340d773SGleb Smirnoff #endif
1133340d773SGleb Smirnoff #ifdef DLT_C_HDLC
1143340d773SGleb Smirnoff 	{ chdlc_if_print,	DLT_C_HDLC },
1153340d773SGleb Smirnoff #endif
1163340d773SGleb Smirnoff #ifdef DLT_HDLC
1173340d773SGleb Smirnoff 	{ chdlc_if_print,	DLT_HDLC },
1183340d773SGleb Smirnoff #endif
1193340d773SGleb Smirnoff #ifdef DLT_PPP_ETHER
1203340d773SGleb Smirnoff 	{ pppoe_if_print,	DLT_PPP_ETHER },
1213340d773SGleb Smirnoff #endif
1223340d773SGleb Smirnoff #if defined(DLT_PFLOG) && defined(HAVE_NET_IF_PFLOG_H)
1233340d773SGleb Smirnoff 	{ pflog_if_print,	DLT_PFLOG },
1243340d773SGleb Smirnoff #endif
1253340d773SGleb Smirnoff 	{ token_if_print,	DLT_IEEE802 },
1263340d773SGleb Smirnoff 	{ fddi_if_print,	DLT_FDDI },
1273340d773SGleb Smirnoff #ifdef DLT_LINUX_SLL
1283340d773SGleb Smirnoff 	{ sll_if_print,		DLT_LINUX_SLL },
1293340d773SGleb Smirnoff #endif
1303340d773SGleb Smirnoff #ifdef DLT_FR
1313340d773SGleb Smirnoff 	{ fr_if_print,		DLT_FR },
1323340d773SGleb Smirnoff #endif
1333340d773SGleb Smirnoff #ifdef DLT_FRELAY
1343340d773SGleb Smirnoff 	{ fr_if_print,		DLT_FRELAY },
1353340d773SGleb Smirnoff #endif
1363340d773SGleb Smirnoff #ifdef DLT_MFR
1373340d773SGleb Smirnoff 	{ mfr_if_print,		DLT_MFR },
1383340d773SGleb Smirnoff #endif
1393340d773SGleb Smirnoff 	{ atm_if_print,		DLT_ATM_RFC1483 },
1403340d773SGleb Smirnoff #ifdef DLT_SUNATM
1413340d773SGleb Smirnoff 	{ sunatm_if_print,	DLT_SUNATM },
1423340d773SGleb Smirnoff #endif
1433340d773SGleb Smirnoff #ifdef DLT_ENC
1443340d773SGleb Smirnoff 	{ enc_if_print,		DLT_ENC },
1453340d773SGleb Smirnoff #endif
1463340d773SGleb Smirnoff 	{ sl_if_print,		DLT_SLIP },
1473340d773SGleb Smirnoff #ifdef DLT_SLIP_BSDOS
1483340d773SGleb Smirnoff 	{ sl_bsdos_if_print,	DLT_SLIP_BSDOS },
1493340d773SGleb Smirnoff #endif
1503340d773SGleb Smirnoff #ifdef DLT_LTALK
1513340d773SGleb Smirnoff 	{ ltalk_if_print,	DLT_LTALK },
1523340d773SGleb Smirnoff #endif
1533340d773SGleb Smirnoff #ifdef DLT_JUNIPER_ATM1
1543340d773SGleb Smirnoff 	{ juniper_atm1_print,	DLT_JUNIPER_ATM1 },
1553340d773SGleb Smirnoff #endif
1563340d773SGleb Smirnoff #ifdef DLT_JUNIPER_ATM2
1573340d773SGleb Smirnoff 	{ juniper_atm2_print,	DLT_JUNIPER_ATM2 },
1583340d773SGleb Smirnoff #endif
1593340d773SGleb Smirnoff #ifdef DLT_JUNIPER_MFR
1603340d773SGleb Smirnoff 	{ juniper_mfr_print,	DLT_JUNIPER_MFR },
1613340d773SGleb Smirnoff #endif
1623340d773SGleb Smirnoff #ifdef DLT_JUNIPER_MLFR
1633340d773SGleb Smirnoff 	{ juniper_mlfr_print,	DLT_JUNIPER_MLFR },
1643340d773SGleb Smirnoff #endif
1653340d773SGleb Smirnoff #ifdef DLT_JUNIPER_MLPPP
1663340d773SGleb Smirnoff 	{ juniper_mlppp_print,	DLT_JUNIPER_MLPPP },
1673340d773SGleb Smirnoff #endif
1683340d773SGleb Smirnoff #ifdef DLT_JUNIPER_PPPOE
1693340d773SGleb Smirnoff 	{ juniper_pppoe_print,	DLT_JUNIPER_PPPOE },
1703340d773SGleb Smirnoff #endif
1713340d773SGleb Smirnoff #ifdef DLT_JUNIPER_PPPOE_ATM
1723340d773SGleb Smirnoff 	{ juniper_pppoe_atm_print, DLT_JUNIPER_PPPOE_ATM },
1733340d773SGleb Smirnoff #endif
1743340d773SGleb Smirnoff #ifdef DLT_JUNIPER_GGSN
1753340d773SGleb Smirnoff 	{ juniper_ggsn_print,	DLT_JUNIPER_GGSN },
1763340d773SGleb Smirnoff #endif
1773340d773SGleb Smirnoff #ifdef DLT_JUNIPER_ES
1783340d773SGleb Smirnoff 	{ juniper_es_print,	DLT_JUNIPER_ES },
1793340d773SGleb Smirnoff #endif
1803340d773SGleb Smirnoff #ifdef DLT_JUNIPER_MONITOR
1813340d773SGleb Smirnoff 	{ juniper_monitor_print, DLT_JUNIPER_MONITOR },
1823340d773SGleb Smirnoff #endif
1833340d773SGleb Smirnoff #ifdef DLT_JUNIPER_SERVICES
1843340d773SGleb Smirnoff 	{ juniper_services_print, DLT_JUNIPER_SERVICES },
1853340d773SGleb Smirnoff #endif
1863340d773SGleb Smirnoff #ifdef DLT_JUNIPER_ETHER
1873340d773SGleb Smirnoff 	{ juniper_ether_print,	DLT_JUNIPER_ETHER },
1883340d773SGleb Smirnoff #endif
1893340d773SGleb Smirnoff #ifdef DLT_JUNIPER_PPP
1903340d773SGleb Smirnoff 	{ juniper_ppp_print,	DLT_JUNIPER_PPP },
1913340d773SGleb Smirnoff #endif
1923340d773SGleb Smirnoff #ifdef DLT_JUNIPER_FRELAY
1933340d773SGleb Smirnoff 	{ juniper_frelay_print,	DLT_JUNIPER_FRELAY },
1943340d773SGleb Smirnoff #endif
1953340d773SGleb Smirnoff #ifdef DLT_JUNIPER_CHDLC
1963340d773SGleb Smirnoff 	{ juniper_chdlc_print,	DLT_JUNIPER_CHDLC },
1973340d773SGleb Smirnoff #endif
1983340d773SGleb Smirnoff #ifdef DLT_PKTAP
1993340d773SGleb Smirnoff 	{ pktap_if_print,	DLT_PKTAP },
2003340d773SGleb Smirnoff #endif
2013340d773SGleb Smirnoff #ifdef DLT_IEEE802_11_RADIO
2023340d773SGleb Smirnoff 	{ ieee802_11_radio_if_print,	DLT_IEEE802_11_RADIO },
2033340d773SGleb Smirnoff #endif
2043340d773SGleb Smirnoff #ifdef DLT_IEEE802_11
2053340d773SGleb Smirnoff 	{ ieee802_11_if_print,	DLT_IEEE802_11},
2063340d773SGleb Smirnoff #endif
2073340d773SGleb Smirnoff #ifdef DLT_IEEE802_11_RADIO_AVS
2083340d773SGleb Smirnoff 	{ ieee802_11_radio_avs_if_print,	DLT_IEEE802_11_RADIO_AVS },
2093340d773SGleb Smirnoff #endif
2103340d773SGleb Smirnoff #ifdef DLT_PRISM_HEADER
2113340d773SGleb Smirnoff 	{ prism_if_print,	DLT_PRISM_HEADER },
2123340d773SGleb Smirnoff #endif
2133340d773SGleb Smirnoff 	{ ppp_if_print,		DLT_PPP },
2143340d773SGleb Smirnoff #ifdef DLT_PPP_WITHDIRECTION
2153340d773SGleb Smirnoff 	{ ppp_if_print,		DLT_PPP_WITHDIRECTION },
2163340d773SGleb Smirnoff #endif
2173340d773SGleb Smirnoff #ifdef DLT_PPP_BSDOS
2183340d773SGleb Smirnoff 	{ ppp_bsdos_if_print,	DLT_PPP_BSDOS },
2193340d773SGleb Smirnoff #endif
2203340d773SGleb Smirnoff #ifdef DLT_PPP_SERIAL
2213340d773SGleb Smirnoff 	{ ppp_hdlc_if_print,	DLT_PPP_SERIAL },
2223340d773SGleb Smirnoff #endif
2233340d773SGleb Smirnoff 	{ NULL,			0 },
2243340d773SGleb Smirnoff };
2253340d773SGleb Smirnoff 
2263340d773SGleb Smirnoff static void	ndo_default_print(netdissect_options *ndo, const u_char *bp,
2273340d773SGleb Smirnoff 		    u_int length);
2283340d773SGleb Smirnoff 
229*0bff6a5aSEd Maste static void	ndo_error(netdissect_options *ndo,
230*0bff6a5aSEd Maste 		    FORMAT_STRING(const char *fmt), ...)
231*0bff6a5aSEd Maste 		    NORETURN PRINTFLIKE(2, 3);
232*0bff6a5aSEd Maste static void	ndo_warning(netdissect_options *ndo,
233*0bff6a5aSEd Maste 		    FORMAT_STRING(const char *fmt), ...)
234*0bff6a5aSEd Maste 		    PRINTFLIKE(2, 3);
2353340d773SGleb Smirnoff 
236*0bff6a5aSEd Maste static int	ndo_printf(netdissect_options *ndo,
237*0bff6a5aSEd Maste 		     FORMAT_STRING(const char *fmt), ...)
238*0bff6a5aSEd Maste 		     PRINTFLIKE(2, 3);
2393340d773SGleb Smirnoff 
2403340d773SGleb Smirnoff void
2413340d773SGleb Smirnoff init_print(netdissect_options *ndo, uint32_t localnet, uint32_t mask,
2423340d773SGleb Smirnoff     uint32_t timezone_offset)
2433340d773SGleb Smirnoff {
2443340d773SGleb Smirnoff 
2453340d773SGleb Smirnoff 	thiszone = timezone_offset;
2463340d773SGleb Smirnoff 	init_addrtoname(ndo, localnet, mask);
2473340d773SGleb Smirnoff 	init_checksum();
2483340d773SGleb Smirnoff }
2493340d773SGleb Smirnoff 
2503340d773SGleb Smirnoff if_printer
2513340d773SGleb Smirnoff lookup_printer(int type)
2523340d773SGleb Smirnoff {
2533340d773SGleb Smirnoff 	const struct printer *p;
2543340d773SGleb Smirnoff 
2553340d773SGleb Smirnoff 	for (p = printers; p->f; ++p)
2563340d773SGleb Smirnoff 		if (type == p->type)
2573340d773SGleb Smirnoff 			return p->f;
2583340d773SGleb Smirnoff 
2593340d773SGleb Smirnoff #if defined(DLT_USER2) && defined(DLT_PKTAP)
2603340d773SGleb Smirnoff 	/*
2613340d773SGleb Smirnoff 	 * Apple incorrectly chose to use DLT_USER2 for their PKTAP
2623340d773SGleb Smirnoff 	 * header.
2633340d773SGleb Smirnoff 	 *
2643340d773SGleb Smirnoff 	 * We map DLT_PKTAP, whether it's DLT_USER2 as it is on Darwin-
2653340d773SGleb Smirnoff 	 * based OSes or the same value as LINKTYPE_PKTAP as it is on
2663340d773SGleb Smirnoff 	 * other OSes, to LINKTYPE_PKTAP, so files written with
2673340d773SGleb Smirnoff 	 * this version of libpcap for a DLT_PKTAP capture have a link-
2683340d773SGleb Smirnoff 	 * layer header type of LINKTYPE_PKTAP.
2693340d773SGleb Smirnoff 	 *
2703340d773SGleb Smirnoff 	 * However, files written on OS X Mavericks for a DLT_PKTAP
2713340d773SGleb Smirnoff 	 * capture have a link-layer header type of LINKTYPE_USER2.
2723340d773SGleb Smirnoff 	 * If we don't have a printer for DLT_USER2, and type is
2733340d773SGleb Smirnoff 	 * DLT_USER2, we look up the printer for DLT_PKTAP and use
2743340d773SGleb Smirnoff 	 * that.
2753340d773SGleb Smirnoff 	 */
2763340d773SGleb Smirnoff 	if (type == DLT_USER2) {
2773340d773SGleb Smirnoff 		for (p = printers; p->f; ++p)
2783340d773SGleb Smirnoff 			if (DLT_PKTAP == p->type)
2793340d773SGleb Smirnoff 				return p->f;
2803340d773SGleb Smirnoff 	}
2813340d773SGleb Smirnoff #endif
2823340d773SGleb Smirnoff 
2833340d773SGleb Smirnoff 	return NULL;
2843340d773SGleb Smirnoff 	/* NOTREACHED */
2853340d773SGleb Smirnoff }
2863340d773SGleb Smirnoff 
2873340d773SGleb Smirnoff int
2883340d773SGleb Smirnoff has_printer(int type)
2893340d773SGleb Smirnoff {
2903340d773SGleb Smirnoff 	return (lookup_printer(type) != NULL);
2913340d773SGleb Smirnoff }
2923340d773SGleb Smirnoff 
2933340d773SGleb Smirnoff if_printer
2943340d773SGleb Smirnoff get_if_printer(netdissect_options *ndo, int type)
2953340d773SGleb Smirnoff {
2963340d773SGleb Smirnoff 	const char *dltname;
2973340d773SGleb Smirnoff 	if_printer printer;
2983340d773SGleb Smirnoff 
2993340d773SGleb Smirnoff 	printer = lookup_printer(type);
3003340d773SGleb Smirnoff 	if (printer == NULL) {
3013340d773SGleb Smirnoff 		dltname = pcap_datalink_val_to_name(type);
3023340d773SGleb Smirnoff 		if (dltname != NULL)
3033340d773SGleb Smirnoff 			(*ndo->ndo_error)(ndo,
3043340d773SGleb Smirnoff 					  "packet printing is not supported for link type %s: use -w",
3053340d773SGleb Smirnoff 					  dltname);
3063340d773SGleb Smirnoff 		else
3073340d773SGleb Smirnoff 			(*ndo->ndo_error)(ndo,
3083340d773SGleb Smirnoff 					  "packet printing is not supported for link type %d: use -w", type);
3093340d773SGleb Smirnoff 	}
3103340d773SGleb Smirnoff 	return printer;
3113340d773SGleb Smirnoff }
3123340d773SGleb Smirnoff 
3133340d773SGleb Smirnoff void
3143340d773SGleb Smirnoff pretty_print_packet(netdissect_options *ndo, const struct pcap_pkthdr *h,
3153340d773SGleb Smirnoff     const u_char *sp, u_int packets_captured)
3163340d773SGleb Smirnoff {
3173340d773SGleb Smirnoff 	u_int hdrlen;
3183340d773SGleb Smirnoff 
3193340d773SGleb Smirnoff 	if(ndo->ndo_packet_number)
3203340d773SGleb Smirnoff 		ND_PRINT((ndo, "%5u  ", packets_captured));
3213340d773SGleb Smirnoff 
3223340d773SGleb Smirnoff 	ts_print(ndo, &h->ts);
3233340d773SGleb Smirnoff 
3243340d773SGleb Smirnoff 	/*
3253340d773SGleb Smirnoff 	 * Some printers want to check that they're not walking off the
3263340d773SGleb Smirnoff 	 * end of the packet.
3273340d773SGleb Smirnoff 	 * Rather than pass it all the way down, we set this member
3283340d773SGleb Smirnoff 	 * of the netdissect_options structure.
3293340d773SGleb Smirnoff 	 */
3303340d773SGleb Smirnoff 	ndo->ndo_snapend = sp + h->caplen;
3313340d773SGleb Smirnoff 
3323340d773SGleb Smirnoff         hdrlen = (ndo->ndo_if_printer)(ndo, h, sp);
3333340d773SGleb Smirnoff 
3343340d773SGleb Smirnoff 	/*
3353340d773SGleb Smirnoff 	 * Restore the original snapend, as a printer might have
3363340d773SGleb Smirnoff 	 * changed it.
3373340d773SGleb Smirnoff 	 */
3383340d773SGleb Smirnoff 	ndo->ndo_snapend = sp + h->caplen;
3393340d773SGleb Smirnoff 	if (ndo->ndo_Xflag) {
3403340d773SGleb Smirnoff 		/*
3413340d773SGleb Smirnoff 		 * Print the raw packet data in hex and ASCII.
3423340d773SGleb Smirnoff 		 */
3433340d773SGleb Smirnoff 		if (ndo->ndo_Xflag > 1) {
3443340d773SGleb Smirnoff 			/*
3453340d773SGleb Smirnoff 			 * Include the link-layer header.
3463340d773SGleb Smirnoff 			 */
3473340d773SGleb Smirnoff 			hex_and_ascii_print(ndo, "\n\t", sp, h->caplen);
3483340d773SGleb Smirnoff 		} else {
3493340d773SGleb Smirnoff 			/*
3503340d773SGleb Smirnoff 			 * Don't include the link-layer header - and if
3513340d773SGleb Smirnoff 			 * we have nothing past the link-layer header,
3523340d773SGleb Smirnoff 			 * print nothing.
3533340d773SGleb Smirnoff 			 */
3543340d773SGleb Smirnoff 			if (h->caplen > hdrlen)
3553340d773SGleb Smirnoff 				hex_and_ascii_print(ndo, "\n\t", sp + hdrlen,
3563340d773SGleb Smirnoff 				    h->caplen - hdrlen);
3573340d773SGleb Smirnoff 		}
3583340d773SGleb Smirnoff 	} else if (ndo->ndo_xflag) {
3593340d773SGleb Smirnoff 		/*
3603340d773SGleb Smirnoff 		 * Print the raw packet data in hex.
3613340d773SGleb Smirnoff 		 */
3623340d773SGleb Smirnoff 		if (ndo->ndo_xflag > 1) {
3633340d773SGleb Smirnoff 			/*
3643340d773SGleb Smirnoff 			 * Include the link-layer header.
3653340d773SGleb Smirnoff 			 */
3663340d773SGleb Smirnoff                         hex_print(ndo, "\n\t", sp, h->caplen);
3673340d773SGleb Smirnoff 		} else {
3683340d773SGleb Smirnoff 			/*
3693340d773SGleb Smirnoff 			 * Don't include the link-layer header - and if
3703340d773SGleb Smirnoff 			 * we have nothing past the link-layer header,
3713340d773SGleb Smirnoff 			 * print nothing.
3723340d773SGleb Smirnoff 			 */
3733340d773SGleb Smirnoff 			if (h->caplen > hdrlen)
3743340d773SGleb Smirnoff 				hex_print(ndo, "\n\t", sp + hdrlen,
3753340d773SGleb Smirnoff                                           h->caplen - hdrlen);
3763340d773SGleb Smirnoff 		}
3773340d773SGleb Smirnoff 	} else if (ndo->ndo_Aflag) {
3783340d773SGleb Smirnoff 		/*
3793340d773SGleb Smirnoff 		 * Print the raw packet data in ASCII.
3803340d773SGleb Smirnoff 		 */
3813340d773SGleb Smirnoff 		if (ndo->ndo_Aflag > 1) {
3823340d773SGleb Smirnoff 			/*
3833340d773SGleb Smirnoff 			 * Include the link-layer header.
3843340d773SGleb Smirnoff 			 */
3853340d773SGleb Smirnoff 			ascii_print(ndo, sp, h->caplen);
3863340d773SGleb Smirnoff 		} else {
3873340d773SGleb Smirnoff 			/*
3883340d773SGleb Smirnoff 			 * Don't include the link-layer header - and if
3893340d773SGleb Smirnoff 			 * we have nothing past the link-layer header,
3903340d773SGleb Smirnoff 			 * print nothing.
3913340d773SGleb Smirnoff 			 */
3923340d773SGleb Smirnoff 			if (h->caplen > hdrlen)
3933340d773SGleb Smirnoff 				ascii_print(ndo, sp + hdrlen, h->caplen - hdrlen);
3943340d773SGleb Smirnoff 		}
3953340d773SGleb Smirnoff 	}
3963340d773SGleb Smirnoff 
3973340d773SGleb Smirnoff 	ND_PRINT((ndo, "\n"));
3983340d773SGleb Smirnoff }
3993340d773SGleb Smirnoff 
4003340d773SGleb Smirnoff /*
4013340d773SGleb Smirnoff  * By default, print the specified data out in hex and ASCII.
4023340d773SGleb Smirnoff  */
4033340d773SGleb Smirnoff static void
4043340d773SGleb Smirnoff ndo_default_print(netdissect_options *ndo, const u_char *bp, u_int length)
4053340d773SGleb Smirnoff {
4063340d773SGleb Smirnoff 	hex_and_ascii_print(ndo, "\n\t", bp, length); /* pass on lf and indentation string */
4073340d773SGleb Smirnoff }
4083340d773SGleb Smirnoff 
4093340d773SGleb Smirnoff /* VARARGS */
4103340d773SGleb Smirnoff static void
4113340d773SGleb Smirnoff ndo_error(netdissect_options *ndo, const char *fmt, ...)
4123340d773SGleb Smirnoff {
4133340d773SGleb Smirnoff 	va_list ap;
4143340d773SGleb Smirnoff 
4153340d773SGleb Smirnoff 	if(ndo->program_name)
4163340d773SGleb Smirnoff 		(void)fprintf(stderr, "%s: ", ndo->program_name);
4173340d773SGleb Smirnoff 	va_start(ap, fmt);
4183340d773SGleb Smirnoff 	(void)vfprintf(stderr, fmt, ap);
4193340d773SGleb Smirnoff 	va_end(ap);
4203340d773SGleb Smirnoff 	if (*fmt) {
4213340d773SGleb Smirnoff 		fmt += strlen(fmt);
4223340d773SGleb Smirnoff 		if (fmt[-1] != '\n')
4233340d773SGleb Smirnoff 			(void)fputc('\n', stderr);
4243340d773SGleb Smirnoff 	}
4253340d773SGleb Smirnoff 	nd_cleanup();
4263340d773SGleb Smirnoff 	exit(1);
4273340d773SGleb Smirnoff 	/* NOTREACHED */
4283340d773SGleb Smirnoff }
4293340d773SGleb Smirnoff 
4303340d773SGleb Smirnoff /* VARARGS */
4313340d773SGleb Smirnoff static void
4323340d773SGleb Smirnoff ndo_warning(netdissect_options *ndo, const char *fmt, ...)
4333340d773SGleb Smirnoff {
4343340d773SGleb Smirnoff 	va_list ap;
4353340d773SGleb Smirnoff 
4363340d773SGleb Smirnoff 	if(ndo->program_name)
4373340d773SGleb Smirnoff 		(void)fprintf(stderr, "%s: ", ndo->program_name);
4383340d773SGleb Smirnoff 	(void)fprintf(stderr, "WARNING: ");
4393340d773SGleb Smirnoff 	va_start(ap, fmt);
4403340d773SGleb Smirnoff 	(void)vfprintf(stderr, fmt, ap);
4413340d773SGleb Smirnoff 	va_end(ap);
4423340d773SGleb Smirnoff 	if (*fmt) {
4433340d773SGleb Smirnoff 		fmt += strlen(fmt);
4443340d773SGleb Smirnoff 		if (fmt[-1] != '\n')
4453340d773SGleb Smirnoff 			(void)fputc('\n', stderr);
4463340d773SGleb Smirnoff 	}
4473340d773SGleb Smirnoff }
4483340d773SGleb Smirnoff 
4493340d773SGleb Smirnoff static int
4503340d773SGleb Smirnoff ndo_printf(netdissect_options *ndo, const char *fmt, ...)
4513340d773SGleb Smirnoff {
4523340d773SGleb Smirnoff 	va_list args;
4533340d773SGleb Smirnoff 	int ret;
4543340d773SGleb Smirnoff 
4553340d773SGleb Smirnoff 	va_start(args, fmt);
4563340d773SGleb Smirnoff 	ret = vfprintf(stdout, fmt, args);
4573340d773SGleb Smirnoff 	va_end(args);
4583340d773SGleb Smirnoff 
4593340d773SGleb Smirnoff 	if (ret < 0)
4603340d773SGleb Smirnoff 		ndo_error(ndo, "Unable to write output: %s", pcap_strerror(errno));
4613340d773SGleb Smirnoff 	return (ret);
4623340d773SGleb Smirnoff }
4633340d773SGleb Smirnoff 
4643340d773SGleb Smirnoff void
4653340d773SGleb Smirnoff ndo_set_function_pointers(netdissect_options *ndo)
4663340d773SGleb Smirnoff {
4673340d773SGleb Smirnoff 	ndo->ndo_default_print=ndo_default_print;
4683340d773SGleb Smirnoff 	ndo->ndo_printf=ndo_printf;
4693340d773SGleb Smirnoff 	ndo->ndo_error=ndo_error;
4703340d773SGleb Smirnoff 	ndo->ndo_warning=ndo_warning;
4713340d773SGleb Smirnoff }
4723340d773SGleb Smirnoff /*
4733340d773SGleb Smirnoff  * Local Variables:
4743340d773SGleb Smirnoff  * c-style: whitesmith
4753340d773SGleb Smirnoff  * c-basic-offset: 8
4763340d773SGleb Smirnoff  * End:
4773340d773SGleb Smirnoff  */
478