xref: /freebsd/contrib/tcpdump/print.c (revision 1ad8d2ee1f7dec1d747ec955a68fbbb362958315)
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
29ee67461eSJoseph Mingrone #include <config.h>
303340d773SGleb Smirnoff #endif
313340d773SGleb Smirnoff 
323340d773SGleb Smirnoff #include <stdlib.h>
333340d773SGleb Smirnoff #include <string.h>
34ee67461eSJoseph Mingrone #include <setjmp.h>
353340d773SGleb Smirnoff 
36ee67461eSJoseph Mingrone #include "netdissect-stdinc.h"
373340d773SGleb Smirnoff 
383340d773SGleb Smirnoff #include "netdissect.h"
393340d773SGleb Smirnoff #include "addrtoname.h"
403340d773SGleb Smirnoff #include "print.h"
41ee67461eSJoseph Mingrone #include "netdissect-alloc.h"
42ee67461eSJoseph Mingrone 
43ee67461eSJoseph Mingrone #include "pcap-missing.h"
443340d773SGleb Smirnoff 
453340d773SGleb Smirnoff struct printer {
463340d773SGleb Smirnoff 	if_printer f;
473340d773SGleb Smirnoff 	int type;
483340d773SGleb Smirnoff };
493340d773SGleb Smirnoff 
503340d773SGleb Smirnoff static const struct printer printers[] = {
51ee67461eSJoseph Mingrone #ifdef DLT_APPLE_IP_OVER_IEEE1394
52ee67461eSJoseph Mingrone 	{ ap1394_if_print,	DLT_APPLE_IP_OVER_IEEE1394 },
53ee67461eSJoseph Mingrone #endif
54ee67461eSJoseph Mingrone 	{ arcnet_if_print,	DLT_ARCNET },
55ee67461eSJoseph Mingrone #ifdef DLT_ARCNET_LINUX
56ee67461eSJoseph Mingrone 	{ arcnet_linux_if_print, DLT_ARCNET_LINUX },
57ee67461eSJoseph Mingrone #endif
58ee67461eSJoseph Mingrone 	{ atm_if_print,		DLT_ATM_RFC1483 },
59ee67461eSJoseph Mingrone #ifdef DLT_DSA_TAG_BRCM
60ee67461eSJoseph Mingrone 	{ brcm_tag_if_print,	DLT_DSA_TAG_BRCM },
61ee67461eSJoseph Mingrone #endif
62ee67461eSJoseph Mingrone #ifdef DLT_DSA_TAG_BRCM_PREPEND
63ee67461eSJoseph Mingrone 	{ brcm_tag_prepend_if_print, DLT_DSA_TAG_BRCM_PREPEND },
64ee67461eSJoseph Mingrone #endif
65ee67461eSJoseph Mingrone #ifdef DLT_BLUETOOTH_HCI_H4_WITH_PHDR
66ee67461eSJoseph Mingrone 	{ bt_if_print,		DLT_BLUETOOTH_HCI_H4_WITH_PHDR},
67ee67461eSJoseph Mingrone #endif
68ee67461eSJoseph Mingrone #ifdef DLT_C_HDLC
69ee67461eSJoseph Mingrone 	{ chdlc_if_print,	DLT_C_HDLC },
70ee67461eSJoseph Mingrone #endif
71ee67461eSJoseph Mingrone #ifdef DLT_HDLC
72ee67461eSJoseph Mingrone 	{ chdlc_if_print,	DLT_HDLC },
73ee67461eSJoseph Mingrone #endif
74ee67461eSJoseph Mingrone #ifdef DLT_ATM_CLIP
75ee67461eSJoseph Mingrone 	{ cip_if_print,		DLT_ATM_CLIP },
76ee67461eSJoseph Mingrone #endif
77ee67461eSJoseph Mingrone #ifdef DLT_CIP
78ee67461eSJoseph Mingrone 	{ cip_if_print,		DLT_CIP },
79ee67461eSJoseph Mingrone #endif
80ee67461eSJoseph Mingrone #ifdef DLT_DSA_TAG_DSA
81ee67461eSJoseph Mingrone 	{ dsa_if_print,		DLT_DSA_TAG_DSA },
82ee67461eSJoseph Mingrone #endif
83ee67461eSJoseph Mingrone #ifdef DLT_DSA_TAG_EDSA
84ee67461eSJoseph Mingrone 	{ edsa_if_print,	DLT_DSA_TAG_EDSA },
85ee67461eSJoseph Mingrone #endif
86ee67461eSJoseph Mingrone #ifdef DLT_ENC
87ee67461eSJoseph Mingrone 	{ enc_if_print,		DLT_ENC },
88ee67461eSJoseph Mingrone #endif
893340d773SGleb Smirnoff 	{ ether_if_print,	DLT_EN10MB },
90ee67461eSJoseph Mingrone 	{ fddi_if_print,	DLT_FDDI },
91ee67461eSJoseph Mingrone #ifdef DLT_FR
92ee67461eSJoseph Mingrone 	{ fr_if_print,		DLT_FR },
93ee67461eSJoseph Mingrone #endif
94ee67461eSJoseph Mingrone #ifdef DLT_FRELAY
95ee67461eSJoseph Mingrone 	{ fr_if_print,		DLT_FRELAY },
96ee67461eSJoseph Mingrone #endif
97ee67461eSJoseph Mingrone #ifdef DLT_IEEE802_11
98ee67461eSJoseph Mingrone 	{ ieee802_11_if_print,	DLT_IEEE802_11},
99ee67461eSJoseph Mingrone #endif
100ee67461eSJoseph Mingrone #ifdef DLT_IEEE802_11_RADIO_AVS
101ee67461eSJoseph Mingrone 	{ ieee802_11_radio_avs_if_print, DLT_IEEE802_11_RADIO_AVS },
102ee67461eSJoseph Mingrone #endif
103ee67461eSJoseph Mingrone #ifdef DLT_IEEE802_11_RADIO
104ee67461eSJoseph Mingrone 	{ ieee802_11_radio_if_print,	DLT_IEEE802_11_RADIO },
1053340d773SGleb Smirnoff #endif
1063340d773SGleb Smirnoff #ifdef DLT_IEEE802_15_4
1073340d773SGleb Smirnoff 	{ ieee802_15_4_if_print, DLT_IEEE802_15_4 },
1083340d773SGleb Smirnoff #endif
1093340d773SGleb Smirnoff #ifdef DLT_IEEE802_15_4_NOFCS
1103340d773SGleb Smirnoff 	{ ieee802_15_4_if_print, DLT_IEEE802_15_4_NOFCS },
1113340d773SGleb Smirnoff #endif
112ee67461eSJoseph Mingrone #ifdef DLT_IEEE802_15_4_TAP
113ee67461eSJoseph Mingrone 	{ ieee802_15_4_tap_if_print, DLT_IEEE802_15_4_TAP },
114ee67461eSJoseph Mingrone #endif
115ee67461eSJoseph Mingrone #ifdef DLT_IP_OVER_FC
116ee67461eSJoseph Mingrone 	{ ipfc_if_print,	DLT_IP_OVER_FC },
117ee67461eSJoseph Mingrone #endif
118ee67461eSJoseph Mingrone #ifdef DLT_IPNET
119ee67461eSJoseph Mingrone 	{ ipnet_if_print,	DLT_IPNET },
120ee67461eSJoseph Mingrone #endif
121ee67461eSJoseph Mingrone #ifdef DLT_IPOIB
122ee67461eSJoseph Mingrone 	{ ipoib_if_print,       DLT_IPOIB },
123ee67461eSJoseph Mingrone #endif
124ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_ATM1
125ee67461eSJoseph Mingrone 	{ juniper_atm1_if_print, DLT_JUNIPER_ATM1 },
126ee67461eSJoseph Mingrone #endif
127ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_ATM2
128ee67461eSJoseph Mingrone 	{ juniper_atm2_if_print, DLT_JUNIPER_ATM2 },
129ee67461eSJoseph Mingrone #endif
130ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_CHDLC
131ee67461eSJoseph Mingrone 	{ juniper_chdlc_if_print,	DLT_JUNIPER_CHDLC },
132ee67461eSJoseph Mingrone #endif
133ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_ES
134ee67461eSJoseph Mingrone 	{ juniper_es_if_print,	DLT_JUNIPER_ES },
135ee67461eSJoseph Mingrone #endif
136ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_ETHER
137ee67461eSJoseph Mingrone 	{ juniper_ether_if_print,	DLT_JUNIPER_ETHER },
138ee67461eSJoseph Mingrone #endif
139ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_FRELAY
140ee67461eSJoseph Mingrone 	{ juniper_frelay_if_print,	DLT_JUNIPER_FRELAY },
141ee67461eSJoseph Mingrone #endif
142ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_GGSN
143ee67461eSJoseph Mingrone 	{ juniper_ggsn_if_print, DLT_JUNIPER_GGSN },
144ee67461eSJoseph Mingrone #endif
145ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_MFR
146ee67461eSJoseph Mingrone 	{ juniper_mfr_if_print,	DLT_JUNIPER_MFR },
147ee67461eSJoseph Mingrone #endif
148ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_MLFR
149ee67461eSJoseph Mingrone 	{ juniper_mlfr_if_print, DLT_JUNIPER_MLFR },
150ee67461eSJoseph Mingrone #endif
151ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_MLPPP
152ee67461eSJoseph Mingrone 	{ juniper_mlppp_if_print, DLT_JUNIPER_MLPPP },
153ee67461eSJoseph Mingrone #endif
154ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_MONITOR
155ee67461eSJoseph Mingrone 	{ juniper_monitor_if_print, DLT_JUNIPER_MONITOR },
156ee67461eSJoseph Mingrone #endif
157ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_PPP
158ee67461eSJoseph Mingrone 	{ juniper_ppp_if_print,	DLT_JUNIPER_PPP },
159ee67461eSJoseph Mingrone #endif
160ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_PPPOE_ATM
161ee67461eSJoseph Mingrone 	{ juniper_pppoe_atm_if_print, DLT_JUNIPER_PPPOE_ATM },
162ee67461eSJoseph Mingrone #endif
163ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_PPPOE
164ee67461eSJoseph Mingrone 	{ juniper_pppoe_if_print, DLT_JUNIPER_PPPOE },
165ee67461eSJoseph Mingrone #endif
166ee67461eSJoseph Mingrone #ifdef DLT_JUNIPER_SERVICES
167ee67461eSJoseph Mingrone 	{ juniper_services_if_print, DLT_JUNIPER_SERVICES },
168ee67461eSJoseph Mingrone #endif
169ee67461eSJoseph Mingrone #ifdef DLT_LTALK
170ee67461eSJoseph Mingrone 	{ ltalk_if_print,	DLT_LTALK },
171ee67461eSJoseph Mingrone #endif
172ee67461eSJoseph Mingrone #ifdef DLT_MFR
173ee67461eSJoseph Mingrone 	{ mfr_if_print,		DLT_MFR },
1743340d773SGleb Smirnoff #endif
1753340d773SGleb Smirnoff #ifdef DLT_NETANALYZER
1763340d773SGleb Smirnoff 	{ netanalyzer_if_print, DLT_NETANALYZER },
1773340d773SGleb Smirnoff #endif
1783340d773SGleb Smirnoff #ifdef DLT_NETANALYZER_TRANSPARENT
1793340d773SGleb Smirnoff 	{ netanalyzer_transparent_if_print, DLT_NETANALYZER_TRANSPARENT },
1803340d773SGleb Smirnoff #endif
181ee67461eSJoseph Mingrone #ifdef DLT_NFLOG
1823340d773SGleb Smirnoff 	{ nflog_if_print,	DLT_NFLOG},
1833340d773SGleb Smirnoff #endif
1843340d773SGleb Smirnoff 	{ null_if_print,	DLT_NULL },
1853340d773SGleb Smirnoff #ifdef DLT_LOOP
1863340d773SGleb Smirnoff 	{ null_if_print,	DLT_LOOP },
1873340d773SGleb Smirnoff #endif
188171a7bbfSGleb Smirnoff #if defined(DLT_PFLOG) && defined(HAVE_NET_IF_PFLOG_H)
189ee67461eSJoseph Mingrone 	{ pflog_if_print,	DLT_PFLOG },
1903340d773SGleb Smirnoff #endif
191*1ad8d2eeSJoseph Mingrone #if defined(DLT_PFSYNC) && defined(HAVE_NET_PFVAR_H)
192*1ad8d2eeSJoseph Mingrone 	{ pfsync_if_print,	DLT_PFSYNC},
193*1ad8d2eeSJoseph Mingrone #endif
194ee67461eSJoseph Mingrone #ifdef DLT_PKTAP
195ee67461eSJoseph Mingrone 	{ pktap_if_print,	DLT_PKTAP },
1963340d773SGleb Smirnoff #endif
197ee67461eSJoseph Mingrone #ifdef DLT_PPI
198ee67461eSJoseph Mingrone 	{ ppi_if_print,		DLT_PPI },
1993340d773SGleb Smirnoff #endif
200ee67461eSJoseph Mingrone #ifdef DLT_PPP_BSDOS
201ee67461eSJoseph Mingrone 	{ ppp_bsdos_if_print,	DLT_PPP_BSDOS },
202ee67461eSJoseph Mingrone #endif
203ee67461eSJoseph Mingrone #ifdef DLT_PPP_SERIAL
204ee67461eSJoseph Mingrone 	{ ppp_hdlc_if_print,	DLT_PPP_SERIAL },
205ee67461eSJoseph Mingrone #endif
206ee67461eSJoseph Mingrone 	{ ppp_if_print,		DLT_PPP },
207ee67461eSJoseph Mingrone #ifdef DLT_PPP_PPPD
208ee67461eSJoseph Mingrone 	{ ppp_if_print,		DLT_PPP_PPPD },
209ee67461eSJoseph Mingrone #endif
210ee67461eSJoseph Mingrone #ifdef DLT_PPP_ETHER
211ee67461eSJoseph Mingrone 	{ pppoe_if_print,	DLT_PPP_ETHER },
212ee67461eSJoseph Mingrone #endif
213ee67461eSJoseph Mingrone #ifdef DLT_PRISM_HEADER
214ee67461eSJoseph Mingrone 	{ prism_if_print,	DLT_PRISM_HEADER },
2153340d773SGleb Smirnoff #endif
2163340d773SGleb Smirnoff 	{ raw_if_print,		DLT_RAW },
2173340d773SGleb Smirnoff #ifdef DLT_IPV4
2183340d773SGleb Smirnoff 	{ raw_if_print,		DLT_IPV4 },
2193340d773SGleb Smirnoff #endif
2203340d773SGleb Smirnoff #ifdef DLT_IPV6
2213340d773SGleb Smirnoff 	{ raw_if_print,		DLT_IPV6 },
2223340d773SGleb Smirnoff #endif
2233340d773SGleb Smirnoff #ifdef DLT_SLIP_BSDOS
2243340d773SGleb Smirnoff 	{ sl_bsdos_if_print,	DLT_SLIP_BSDOS },
2253340d773SGleb Smirnoff #endif
226ee67461eSJoseph Mingrone 	{ sl_if_print,		DLT_SLIP },
227ee67461eSJoseph Mingrone #ifdef DLT_LINUX_SLL
228ee67461eSJoseph Mingrone 	{ sll_if_print,		DLT_LINUX_SLL },
2293340d773SGleb Smirnoff #endif
230ee67461eSJoseph Mingrone #ifdef DLT_LINUX_SLL2
231ee67461eSJoseph Mingrone 	{ sll2_if_print,	DLT_LINUX_SLL2 },
2323340d773SGleb Smirnoff #endif
233ee67461eSJoseph Mingrone #ifdef DLT_SUNATM
234ee67461eSJoseph Mingrone 	{ sunatm_if_print,	DLT_SUNATM },
2353340d773SGleb Smirnoff #endif
236ee67461eSJoseph Mingrone #ifdef DLT_SYMANTEC_FIREWALL
237ee67461eSJoseph Mingrone 	{ symantec_if_print,	DLT_SYMANTEC_FIREWALL },
2383340d773SGleb Smirnoff #endif
239ee67461eSJoseph Mingrone 	{ token_if_print,	DLT_IEEE802 },
240ee67461eSJoseph Mingrone #ifdef DLT_USB_LINUX
241ee67461eSJoseph Mingrone 	{ usb_linux_48_byte_if_print, DLT_USB_LINUX},
242ee67461eSJoseph Mingrone #endif /* DLT_USB_LINUX */
243ee67461eSJoseph Mingrone #ifdef DLT_USB_LINUX_MMAPPED
244ee67461eSJoseph Mingrone 	{ usb_linux_64_byte_if_print, DLT_USB_LINUX_MMAPPED},
245ee67461eSJoseph Mingrone #endif /* DLT_USB_LINUX_MMAPPED */
246ee67461eSJoseph Mingrone #ifdef DLT_VSOCK
247ee67461eSJoseph Mingrone 	{ vsock_if_print,	DLT_VSOCK },
2483340d773SGleb Smirnoff #endif
2493340d773SGleb Smirnoff 	{ NULL,                 0 },
2503340d773SGleb Smirnoff };
2513340d773SGleb Smirnoff 
2523340d773SGleb Smirnoff static void	ndo_default_print(netdissect_options *ndo, const u_char *bp,
2533340d773SGleb Smirnoff 		    u_int length);
2543340d773SGleb Smirnoff 
255ee67461eSJoseph Mingrone static void NORETURN ndo_error(netdissect_options *ndo,
256ee67461eSJoseph Mingrone 		     status_exit_codes_t status,
2570bff6a5aSEd Maste 		     FORMAT_STRING(const char *fmt), ...)
258ee67461eSJoseph Mingrone 		     PRINTFLIKE(3, 4);
2590bff6a5aSEd Maste static void	ndo_warning(netdissect_options *ndo,
2600bff6a5aSEd Maste 		    FORMAT_STRING(const char *fmt), ...)
2610bff6a5aSEd Maste 		    PRINTFLIKE(2, 3);
2623340d773SGleb Smirnoff 
2630bff6a5aSEd Maste static int	ndo_printf(netdissect_options *ndo,
2640bff6a5aSEd Maste 		     FORMAT_STRING(const char *fmt), ...)
2650bff6a5aSEd Maste 		     PRINTFLIKE(2, 3);
2663340d773SGleb Smirnoff 
2673340d773SGleb Smirnoff void
268ee67461eSJoseph Mingrone init_print(netdissect_options *ndo, uint32_t localnet, uint32_t mask)
2693340d773SGleb Smirnoff {
2703340d773SGleb Smirnoff 
2713340d773SGleb Smirnoff 	init_addrtoname(ndo, localnet, mask);
2723340d773SGleb Smirnoff 	init_checksum();
2733340d773SGleb Smirnoff }
2743340d773SGleb Smirnoff 
2753340d773SGleb Smirnoff if_printer
2763340d773SGleb Smirnoff lookup_printer(int type)
2773340d773SGleb Smirnoff {
2783340d773SGleb Smirnoff 	const struct printer *p;
2793340d773SGleb Smirnoff 
2803340d773SGleb Smirnoff 	for (p = printers; p->f; ++p)
2813340d773SGleb Smirnoff 		if (type == p->type)
2823340d773SGleb Smirnoff 			return p->f;
2833340d773SGleb Smirnoff 
2843340d773SGleb Smirnoff #if defined(DLT_USER2) && defined(DLT_PKTAP)
2853340d773SGleb Smirnoff 	/*
2863340d773SGleb Smirnoff 	 * Apple incorrectly chose to use DLT_USER2 for their PKTAP
2873340d773SGleb Smirnoff 	 * header.
2883340d773SGleb Smirnoff 	 *
2893340d773SGleb Smirnoff 	 * We map DLT_PKTAP, whether it's DLT_USER2 as it is on Darwin-
2903340d773SGleb Smirnoff 	 * based OSes or the same value as LINKTYPE_PKTAP as it is on
2913340d773SGleb Smirnoff 	 * other OSes, to LINKTYPE_PKTAP, so files written with
2923340d773SGleb Smirnoff 	 * this version of libpcap for a DLT_PKTAP capture have a link-
2933340d773SGleb Smirnoff 	 * layer header type of LINKTYPE_PKTAP.
2943340d773SGleb Smirnoff 	 *
2953340d773SGleb Smirnoff 	 * However, files written on OS X Mavericks for a DLT_PKTAP
2963340d773SGleb Smirnoff 	 * capture have a link-layer header type of LINKTYPE_USER2.
2973340d773SGleb Smirnoff 	 * If we don't have a printer for DLT_USER2, and type is
2983340d773SGleb Smirnoff 	 * DLT_USER2, we look up the printer for DLT_PKTAP and use
2993340d773SGleb Smirnoff 	 * that.
3003340d773SGleb Smirnoff 	 */
3013340d773SGleb Smirnoff 	if (type == DLT_USER2) {
3023340d773SGleb Smirnoff 		for (p = printers; p->f; ++p)
3033340d773SGleb Smirnoff 			if (DLT_PKTAP == p->type)
3043340d773SGleb Smirnoff 				return p->f;
3053340d773SGleb Smirnoff 	}
3063340d773SGleb Smirnoff #endif
3073340d773SGleb Smirnoff 
3083340d773SGleb Smirnoff 	return NULL;
3093340d773SGleb Smirnoff 	/* NOTREACHED */
3103340d773SGleb Smirnoff }
3113340d773SGleb Smirnoff 
3123340d773SGleb Smirnoff int
3133340d773SGleb Smirnoff has_printer(int type)
3143340d773SGleb Smirnoff {
3153340d773SGleb Smirnoff 	return (lookup_printer(type) != NULL);
3163340d773SGleb Smirnoff }
3173340d773SGleb Smirnoff 
3183340d773SGleb Smirnoff if_printer
319ee67461eSJoseph Mingrone get_if_printer(int type)
3203340d773SGleb Smirnoff {
3213340d773SGleb Smirnoff 	if_printer printer;
3223340d773SGleb Smirnoff 
3233340d773SGleb Smirnoff 	printer = lookup_printer(type);
324ee67461eSJoseph Mingrone 	if (printer == NULL)
325ee67461eSJoseph Mingrone 		printer = unsupported_if_print;
3263340d773SGleb Smirnoff 	return printer;
3273340d773SGleb Smirnoff }
3283340d773SGleb Smirnoff 
3293340d773SGleb Smirnoff void
3303340d773SGleb Smirnoff pretty_print_packet(netdissect_options *ndo, const struct pcap_pkthdr *h,
3313340d773SGleb Smirnoff 		    const u_char *sp, u_int packets_captured)
3323340d773SGleb Smirnoff {
333ee67461eSJoseph Mingrone 	u_int hdrlen = 0;
334ee67461eSJoseph Mingrone 	int invalid_header = 0;
3353340d773SGleb Smirnoff 
3363340d773SGleb Smirnoff 	if (ndo->ndo_packet_number)
337ee67461eSJoseph Mingrone 		ND_PRINT("%5u  ", packets_captured);
3383340d773SGleb Smirnoff 
339ee67461eSJoseph Mingrone 	/* Sanity checks on packet length / capture length */
340ee67461eSJoseph Mingrone 	if (h->caplen == 0) {
341ee67461eSJoseph Mingrone 		invalid_header = 1;
342ee67461eSJoseph Mingrone 		ND_PRINT("[Invalid header: caplen==0");
343ee67461eSJoseph Mingrone 	}
344ee67461eSJoseph Mingrone 	if (h->len == 0) {
345ee67461eSJoseph Mingrone 		if (!invalid_header) {
346ee67461eSJoseph Mingrone 			invalid_header = 1;
347ee67461eSJoseph Mingrone 			ND_PRINT("[Invalid header:");
348ee67461eSJoseph Mingrone 		} else
349ee67461eSJoseph Mingrone 			ND_PRINT(",");
350ee67461eSJoseph Mingrone 		ND_PRINT(" len==0");
351ee67461eSJoseph Mingrone 	} else if (h->len < h->caplen) {
352ee67461eSJoseph Mingrone 		if (!invalid_header) {
353ee67461eSJoseph Mingrone 			invalid_header = 1;
354ee67461eSJoseph Mingrone 			ND_PRINT("[Invalid header:");
355ee67461eSJoseph Mingrone 		} else
356ee67461eSJoseph Mingrone 			ND_PRINT(",");
357ee67461eSJoseph Mingrone 		ND_PRINT(" len(%u) < caplen(%u)", h->len, h->caplen);
358ee67461eSJoseph Mingrone 	}
359ee67461eSJoseph Mingrone 	if (h->caplen > MAXIMUM_SNAPLEN) {
360ee67461eSJoseph Mingrone 		if (!invalid_header) {
361ee67461eSJoseph Mingrone 			invalid_header = 1;
362ee67461eSJoseph Mingrone 			ND_PRINT("[Invalid header:");
363ee67461eSJoseph Mingrone 		} else
364ee67461eSJoseph Mingrone 			ND_PRINT(",");
365ee67461eSJoseph Mingrone 		ND_PRINT(" caplen(%u) > %u", h->caplen, MAXIMUM_SNAPLEN);
366ee67461eSJoseph Mingrone 	}
367ee67461eSJoseph Mingrone 	if (h->len > MAXIMUM_SNAPLEN) {
368ee67461eSJoseph Mingrone 		if (!invalid_header) {
369ee67461eSJoseph Mingrone 			invalid_header = 1;
370ee67461eSJoseph Mingrone 			ND_PRINT("[Invalid header:");
371ee67461eSJoseph Mingrone 		} else
372ee67461eSJoseph Mingrone 			ND_PRINT(",");
373ee67461eSJoseph Mingrone 		ND_PRINT(" len(%u) > %u", h->len, MAXIMUM_SNAPLEN);
374ee67461eSJoseph Mingrone 	}
375ee67461eSJoseph Mingrone 	if (invalid_header) {
376ee67461eSJoseph Mingrone 		ND_PRINT("]\n");
377ee67461eSJoseph Mingrone 		return;
378ee67461eSJoseph Mingrone 	}
3793340d773SGleb Smirnoff 
3803340d773SGleb Smirnoff 	/*
381ee67461eSJoseph Mingrone 	 * At this point:
382ee67461eSJoseph Mingrone 	 *   capture length != 0,
383ee67461eSJoseph Mingrone 	 *   packet length != 0,
384ee67461eSJoseph Mingrone 	 *   capture length <= MAXIMUM_SNAPLEN,
385ee67461eSJoseph Mingrone 	 *   packet length <= MAXIMUM_SNAPLEN,
386ee67461eSJoseph Mingrone 	 *   packet length >= capture length.
387ee67461eSJoseph Mingrone 	 *
388ee67461eSJoseph Mingrone 	 * Currently, there is no D-Bus printer, thus no need for
389ee67461eSJoseph Mingrone 	 * bigger lengths.
390ee67461eSJoseph Mingrone 	 */
391ee67461eSJoseph Mingrone 
392ee67461eSJoseph Mingrone 	/*
393ee67461eSJoseph Mingrone 	 * The header /usr/include/pcap/pcap.h in OpenBSD declares h->ts as
394ee67461eSJoseph Mingrone 	 * struct bpf_timeval, not struct timeval. The former comes from
395ee67461eSJoseph Mingrone 	 * /usr/include/net/bpf.h and uses 32-bit unsigned types instead of
396ee67461eSJoseph Mingrone 	 * the types used in struct timeval.
397ee67461eSJoseph Mingrone 	 */
398ee67461eSJoseph Mingrone 	struct timeval tvbuf;
399ee67461eSJoseph Mingrone 	tvbuf.tv_sec = h->ts.tv_sec;
400ee67461eSJoseph Mingrone 	tvbuf.tv_usec = h->ts.tv_usec;
401ee67461eSJoseph Mingrone 	ts_print(ndo, &tvbuf);
402ee67461eSJoseph Mingrone 
403ee67461eSJoseph Mingrone 	/*
404ee67461eSJoseph Mingrone 	 * Printers must check that they're not walking off the end of
405ee67461eSJoseph Mingrone 	 * the packet.
4063340d773SGleb Smirnoff 	 * Rather than pass it all the way down, we set this member
4073340d773SGleb Smirnoff 	 * of the netdissect_options structure.
4083340d773SGleb Smirnoff 	 */
4093340d773SGleb Smirnoff 	ndo->ndo_snapend = sp + h->caplen;
410ee67461eSJoseph Mingrone 	ndo->ndo_packetp = sp;
4113340d773SGleb Smirnoff 
412ee67461eSJoseph Mingrone 	ndo->ndo_protocol = "";
413ee67461eSJoseph Mingrone 	ndo->ndo_ll_hdr_len = 0;
414ee67461eSJoseph Mingrone 	switch (setjmp(ndo->ndo_early_end)) {
415ee67461eSJoseph Mingrone 	case 0:
416ee67461eSJoseph Mingrone 		/* Print the packet. */
417ee67461eSJoseph Mingrone 		(ndo->ndo_if_printer)(ndo, h, sp);
418ee67461eSJoseph Mingrone 		break;
419ee67461eSJoseph Mingrone 	case ND_TRUNCATED:
420ee67461eSJoseph Mingrone 		/* A printer quit because the packet was truncated; report it */
421ee67461eSJoseph Mingrone 		nd_print_trunc(ndo);
422ee67461eSJoseph Mingrone 		/* Print the full packet */
423ee67461eSJoseph Mingrone 		ndo->ndo_ll_hdr_len = 0;
424ee67461eSJoseph Mingrone 		break;
425ee67461eSJoseph Mingrone 	}
426ee67461eSJoseph Mingrone 	hdrlen = ndo->ndo_ll_hdr_len;
427ee67461eSJoseph Mingrone 
428ee67461eSJoseph Mingrone 	/*
429ee67461eSJoseph Mingrone 	 * Empty the stack of packet information, freeing all pushed buffers;
430ee67461eSJoseph Mingrone 	 * if we got here by a printer quitting, we need to release anything
431ee67461eSJoseph Mingrone 	 * that didn't get released because we longjmped out of the code
432ee67461eSJoseph Mingrone 	 * before it popped the packet information.
433ee67461eSJoseph Mingrone 	 */
434ee67461eSJoseph Mingrone 	nd_pop_all_packet_info(ndo);
4353340d773SGleb Smirnoff 
4363340d773SGleb Smirnoff 	/*
4373340d773SGleb Smirnoff 	 * Restore the original snapend, as a printer might have
4383340d773SGleb Smirnoff 	 * changed it.
4393340d773SGleb Smirnoff 	 */
4403340d773SGleb Smirnoff 	ndo->ndo_snapend = sp + h->caplen;
4413340d773SGleb Smirnoff 	if (ndo->ndo_Xflag) {
4423340d773SGleb Smirnoff 		/*
4433340d773SGleb Smirnoff 		 * Print the raw packet data in hex and ASCII.
4443340d773SGleb Smirnoff 		 */
4453340d773SGleb Smirnoff 		if (ndo->ndo_Xflag > 1) {
4463340d773SGleb Smirnoff 			/*
4473340d773SGleb Smirnoff 			 * Include the link-layer header.
4483340d773SGleb Smirnoff 			 */
4493340d773SGleb Smirnoff 			hex_and_ascii_print(ndo, "\n\t", sp, h->caplen);
4503340d773SGleb Smirnoff 		} else {
4513340d773SGleb Smirnoff 			/*
4523340d773SGleb Smirnoff 			 * Don't include the link-layer header - and if
4533340d773SGleb Smirnoff 			 * we have nothing past the link-layer header,
4543340d773SGleb Smirnoff 			 * print nothing.
4553340d773SGleb Smirnoff 			 */
4563340d773SGleb Smirnoff 			if (h->caplen > hdrlen)
4573340d773SGleb Smirnoff 				hex_and_ascii_print(ndo, "\n\t", sp + hdrlen,
4583340d773SGleb Smirnoff 						    h->caplen - hdrlen);
4593340d773SGleb Smirnoff 		}
4603340d773SGleb Smirnoff 	} else if (ndo->ndo_xflag) {
4613340d773SGleb Smirnoff 		/*
4623340d773SGleb Smirnoff 		 * Print the raw packet data in hex.
4633340d773SGleb Smirnoff 		 */
4643340d773SGleb Smirnoff 		if (ndo->ndo_xflag > 1) {
4653340d773SGleb Smirnoff 			/*
4663340d773SGleb Smirnoff 			 * Include the link-layer header.
4673340d773SGleb Smirnoff 			 */
4683340d773SGleb Smirnoff 			hex_print(ndo, "\n\t", sp, h->caplen);
4693340d773SGleb Smirnoff 		} else {
4703340d773SGleb Smirnoff 			/*
4713340d773SGleb Smirnoff 			 * Don't include the link-layer header - and if
4723340d773SGleb Smirnoff 			 * we have nothing past the link-layer header,
4733340d773SGleb Smirnoff 			 * print nothing.
4743340d773SGleb Smirnoff 			 */
4753340d773SGleb Smirnoff 			if (h->caplen > hdrlen)
4763340d773SGleb Smirnoff 				hex_print(ndo, "\n\t", sp + hdrlen,
4773340d773SGleb Smirnoff 					  h->caplen - hdrlen);
4783340d773SGleb Smirnoff 		}
4793340d773SGleb Smirnoff 	} else if (ndo->ndo_Aflag) {
4803340d773SGleb Smirnoff 		/*
4813340d773SGleb Smirnoff 		 * Print the raw packet data in ASCII.
4823340d773SGleb Smirnoff 		 */
4833340d773SGleb Smirnoff 		if (ndo->ndo_Aflag > 1) {
4843340d773SGleb Smirnoff 			/*
4853340d773SGleb Smirnoff 			 * Include the link-layer header.
4863340d773SGleb Smirnoff 			 */
4873340d773SGleb Smirnoff 			ascii_print(ndo, sp, h->caplen);
4883340d773SGleb Smirnoff 		} else {
4893340d773SGleb Smirnoff 			/*
4903340d773SGleb Smirnoff 			 * Don't include the link-layer header - and if
4913340d773SGleb Smirnoff 			 * we have nothing past the link-layer header,
4923340d773SGleb Smirnoff 			 * print nothing.
4933340d773SGleb Smirnoff 			 */
4943340d773SGleb Smirnoff 			if (h->caplen > hdrlen)
4953340d773SGleb Smirnoff 				ascii_print(ndo, sp + hdrlen, h->caplen - hdrlen);
4963340d773SGleb Smirnoff 		}
4973340d773SGleb Smirnoff 	}
4983340d773SGleb Smirnoff 
499ee67461eSJoseph Mingrone 	ND_PRINT("\n");
500ee67461eSJoseph Mingrone 	nd_free_all(ndo);
5013340d773SGleb Smirnoff }
5023340d773SGleb Smirnoff 
5033340d773SGleb Smirnoff /*
5043340d773SGleb Smirnoff  * By default, print the specified data out in hex and ASCII.
5053340d773SGleb Smirnoff  */
5063340d773SGleb Smirnoff static void
5073340d773SGleb Smirnoff ndo_default_print(netdissect_options *ndo, const u_char *bp, u_int length)
5083340d773SGleb Smirnoff {
5093340d773SGleb Smirnoff 	hex_and_ascii_print(ndo, "\n\t", bp, length); /* pass on lf and indentation string */
5103340d773SGleb Smirnoff }
5113340d773SGleb Smirnoff 
5123340d773SGleb Smirnoff /* VARARGS */
5133340d773SGleb Smirnoff static void
514ee67461eSJoseph Mingrone ndo_error(netdissect_options *ndo, status_exit_codes_t status,
515ee67461eSJoseph Mingrone 	  const char *fmt, ...)
5163340d773SGleb Smirnoff {
5173340d773SGleb Smirnoff 	va_list ap;
5183340d773SGleb Smirnoff 
5193340d773SGleb Smirnoff 	if (ndo->program_name)
5203340d773SGleb Smirnoff 		(void)fprintf(stderr, "%s: ", ndo->program_name);
5213340d773SGleb Smirnoff 	va_start(ap, fmt);
5223340d773SGleb Smirnoff 	(void)vfprintf(stderr, fmt, ap);
5233340d773SGleb Smirnoff 	va_end(ap);
5243340d773SGleb Smirnoff 	if (*fmt) {
5253340d773SGleb Smirnoff 		fmt += strlen(fmt);
5263340d773SGleb Smirnoff 		if (fmt[-1] != '\n')
5273340d773SGleb Smirnoff 			(void)fputc('\n', stderr);
5283340d773SGleb Smirnoff 	}
5293340d773SGleb Smirnoff 	nd_cleanup();
530ee67461eSJoseph Mingrone 	exit(status);
5313340d773SGleb Smirnoff 	/* NOTREACHED */
5323340d773SGleb Smirnoff }
5333340d773SGleb Smirnoff 
5343340d773SGleb Smirnoff /* VARARGS */
5353340d773SGleb Smirnoff static void
5363340d773SGleb Smirnoff ndo_warning(netdissect_options *ndo, const char *fmt, ...)
5373340d773SGleb Smirnoff {
5383340d773SGleb Smirnoff 	va_list ap;
5393340d773SGleb Smirnoff 
5403340d773SGleb Smirnoff 	if (ndo->program_name)
5413340d773SGleb Smirnoff 		(void)fprintf(stderr, "%s: ", ndo->program_name);
5423340d773SGleb Smirnoff 	(void)fprintf(stderr, "WARNING: ");
5433340d773SGleb Smirnoff 	va_start(ap, fmt);
5443340d773SGleb Smirnoff 	(void)vfprintf(stderr, fmt, ap);
5453340d773SGleb Smirnoff 	va_end(ap);
5463340d773SGleb Smirnoff 	if (*fmt) {
5473340d773SGleb Smirnoff 		fmt += strlen(fmt);
5483340d773SGleb Smirnoff 		if (fmt[-1] != '\n')
5493340d773SGleb Smirnoff 			(void)fputc('\n', stderr);
5503340d773SGleb Smirnoff 	}
5513340d773SGleb Smirnoff }
5523340d773SGleb Smirnoff 
5533340d773SGleb Smirnoff static int
5543340d773SGleb Smirnoff ndo_printf(netdissect_options *ndo, const char *fmt, ...)
5553340d773SGleb Smirnoff {
5563340d773SGleb Smirnoff 	va_list args;
5573340d773SGleb Smirnoff 	int ret;
5583340d773SGleb Smirnoff 
5593340d773SGleb Smirnoff 	va_start(args, fmt);
5603340d773SGleb Smirnoff 	ret = vfprintf(stdout, fmt, args);
5613340d773SGleb Smirnoff 	va_end(args);
5623340d773SGleb Smirnoff 
5633340d773SGleb Smirnoff 	if (ret < 0)
564ee67461eSJoseph Mingrone 		ndo_error(ndo, S_ERR_ND_WRITE_FILE,
565ee67461eSJoseph Mingrone 			  "Unable to write output: %s", pcap_strerror(errno));
5663340d773SGleb Smirnoff 	return (ret);
5673340d773SGleb Smirnoff }
5683340d773SGleb Smirnoff 
5693340d773SGleb Smirnoff void
5703340d773SGleb Smirnoff ndo_set_function_pointers(netdissect_options *ndo)
5713340d773SGleb Smirnoff {
5723340d773SGleb Smirnoff 	ndo->ndo_default_print=ndo_default_print;
5733340d773SGleb Smirnoff 	ndo->ndo_printf=ndo_printf;
5743340d773SGleb Smirnoff 	ndo->ndo_error=ndo_error;
5753340d773SGleb Smirnoff 	ndo->ndo_warning=ndo_warning;
5763340d773SGleb Smirnoff }
577