xref: /freebsd/contrib/libpcap/pcap.c (revision 57e22627f9459b9dfd6043b32e02ecfcf205e176)
18cf6c252SPaul Traina /*
2a4b5b39fSBill Fenner  * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
38cf6c252SPaul Traina  *	The Regents of the University of California.  All rights reserved.
48cf6c252SPaul Traina  *
58cf6c252SPaul Traina  * Redistribution and use in source and binary forms, with or without
68cf6c252SPaul Traina  * modification, are permitted provided that the following conditions
78cf6c252SPaul Traina  * are met:
88cf6c252SPaul Traina  * 1. Redistributions of source code must retain the above copyright
98cf6c252SPaul Traina  *    notice, this list of conditions and the following disclaimer.
108cf6c252SPaul Traina  * 2. Redistributions in binary form must reproduce the above copyright
118cf6c252SPaul Traina  *    notice, this list of conditions and the following disclaimer in the
128cf6c252SPaul Traina  *    documentation and/or other materials provided with the distribution.
138cf6c252SPaul Traina  * 3. All advertising materials mentioning features or use of this software
148cf6c252SPaul Traina  *    must display the following acknowledgement:
158cf6c252SPaul Traina  *	This product includes software developed by the Computer Systems
168cf6c252SPaul Traina  *	Engineering Group at Lawrence Berkeley Laboratory.
178cf6c252SPaul Traina  * 4. Neither the name of the University nor of the Laboratory may be used
188cf6c252SPaul Traina  *    to endorse or promote products derived from this software without
198cf6c252SPaul Traina  *    specific prior written permission.
208cf6c252SPaul Traina  *
218cf6c252SPaul Traina  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
228cf6c252SPaul Traina  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
238cf6c252SPaul Traina  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
248cf6c252SPaul Traina  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
258cf6c252SPaul Traina  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
268cf6c252SPaul Traina  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
278cf6c252SPaul Traina  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
288cf6c252SPaul Traina  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
298cf6c252SPaul Traina  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
308cf6c252SPaul Traina  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
318cf6c252SPaul Traina  * SUCH DAMAGE.
328cf6c252SPaul Traina  */
338cf6c252SPaul Traina 
34dc2c7305SBill Fenner #ifdef HAVE_CONFIG_H
35b00ab754SHans Petter Selasky #include <config.h>
368cf6c252SPaul Traina #endif
378cf6c252SPaul Traina 
38b00ab754SHans Petter Selasky #include <pcap-types.h>
39b00ab754SHans Petter Selasky #ifndef _WIN32
40b00ab754SHans Petter Selasky #include <sys/param.h>
41b00ab754SHans Petter Selasky #ifndef MSDOS
42b00ab754SHans Petter Selasky #include <sys/file.h>
43a0ee43a1SRui Paulo #endif
44b00ab754SHans Petter Selasky #include <sys/ioctl.h>
45b00ab754SHans Petter Selasky #include <sys/socket.h>
46b00ab754SHans Petter Selasky #ifdef HAVE_SYS_SOCKIO_H
47b00ab754SHans Petter Selasky #include <sys/sockio.h>
48a0ee43a1SRui Paulo #endif
49b00ab754SHans Petter Selasky 
50b00ab754SHans Petter Selasky struct mbuf;		/* Squelch compiler warnings on some platforms for */
51b00ab754SHans Petter Selasky struct rtentry;		/* declarations in <net/if.h> */
52b00ab754SHans Petter Selasky #include <net/if.h>
53b00ab754SHans Petter Selasky #include <netinet/in.h>
54ada6f083SXin LI #endif /* _WIN32 */
558cf6c252SPaul Traina 
56b00ab754SHans Petter Selasky #include <ctype.h>
578cf6c252SPaul Traina #include <stdio.h>
588cf6c252SPaul Traina #include <stdlib.h>
598cf6c252SPaul Traina #include <string.h>
60d1e87331SXin LI #if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__MINGW32__)
618cf6c252SPaul Traina #include <unistd.h>
62feb4ecdbSBruce M Simpson #endif
630a94d38fSBill Fenner #include <fcntl.h>
640a94d38fSBill Fenner #include <errno.h>
65b00ab754SHans Petter Selasky #ifdef HAVE_LIMITS_H
66b00ab754SHans Petter Selasky #include <limits.h>
67b00ab754SHans Petter Selasky #else
68b00ab754SHans Petter Selasky #define INT_MAX		2147483647
69b00ab754SHans Petter Selasky #endif
708cf6c252SPaul Traina 
718cf6c252SPaul Traina #ifdef HAVE_OS_PROTO_H
728cf6c252SPaul Traina #include "os-proto.h"
738cf6c252SPaul Traina #endif
748cf6c252SPaul Traina 
7504fb2745SSam Leffler #ifdef MSDOS
7604fb2745SSam Leffler #include "pcap-dos.h"
7704fb2745SSam Leffler #endif
7804fb2745SSam Leffler 
798cf6c252SPaul Traina #include "pcap-int.h"
808cf6c252SPaul Traina 
81b00ab754SHans Petter Selasky #include "optimize.h"
82b00ab754SHans Petter Selasky 
83feb4ecdbSBruce M Simpson #ifdef HAVE_DAG_API
84edc89b24SXin LI #include "pcap-dag.h"
85edc89b24SXin LI #endif /* HAVE_DAG_API */
86edc89b24SXin LI 
87edc89b24SXin LI #ifdef HAVE_SEPTEL_API
88edc89b24SXin LI #include "pcap-septel.h"
89edc89b24SXin LI #endif /* HAVE_SEPTEL_API */
90edc89b24SXin LI 
91edc89b24SXin LI #ifdef HAVE_SNF_API
92edc89b24SXin LI #include "pcap-snf.h"
93edc89b24SXin LI #endif /* HAVE_SNF_API */
94edc89b24SXin LI 
95ada6f083SXin LI #ifdef HAVE_TC_API
96ada6f083SXin LI #include "pcap-tc.h"
97ada6f083SXin LI #endif /* HAVE_TC_API */
98ada6f083SXin LI 
99edc89b24SXin LI #ifdef PCAP_SUPPORT_USB
100edc89b24SXin LI #include "pcap-usb-linux.h"
101edc89b24SXin LI #endif
102edc89b24SXin LI 
103edc89b24SXin LI #ifdef PCAP_SUPPORT_BT
104edc89b24SXin LI #include "pcap-bt-linux.h"
105edc89b24SXin LI #endif
106edc89b24SXin LI 
107681ed54cSXin LI #ifdef PCAP_SUPPORT_BT_MONITOR
108681ed54cSXin LI #include "pcap-bt-monitor-linux.h"
109681ed54cSXin LI #endif
110681ed54cSXin LI 
111edc89b24SXin LI #ifdef PCAP_SUPPORT_NETFILTER
112edc89b24SXin LI #include "pcap-netfilter-linux.h"
113feb4ecdbSBruce M Simpson #endif
114feb4ecdbSBruce M Simpson 
11586f82ef9SLuigi Rizzo #ifdef PCAP_SUPPORT_NETMAP
116b00ab754SHans Petter Selasky #include "pcap-netmap.h"
11786f82ef9SLuigi Rizzo #endif
11886f82ef9SLuigi Rizzo 
119681ed54cSXin LI #ifdef PCAP_SUPPORT_DBUS
120681ed54cSXin LI #include "pcap-dbus.h"
121681ed54cSXin LI #endif
122681ed54cSXin LI 
123b00ab754SHans Petter Selasky #ifdef PCAP_SUPPORT_RDMASNIFF
124b00ab754SHans Petter Selasky #include "pcap-rdmasniff.h"
125b00ab754SHans Petter Selasky #endif
126b00ab754SHans Petter Selasky 
127b00ab754SHans Petter Selasky #ifdef _WIN32
128b00ab754SHans Petter Selasky /*
129b00ab754SHans Petter Selasky  * DllMain(), required when built as a Windows DLL.
130b00ab754SHans Petter Selasky  */
131b00ab754SHans Petter Selasky BOOL WINAPI DllMain(
132b00ab754SHans Petter Selasky   HANDLE hinstDLL,
133b00ab754SHans Petter Selasky   DWORD dwReason,
134b00ab754SHans Petter Selasky   LPVOID lpvReserved
135b00ab754SHans Petter Selasky )
136b00ab754SHans Petter Selasky {
137b00ab754SHans Petter Selasky 	return (TRUE);
138b00ab754SHans Petter Selasky }
139b00ab754SHans Petter Selasky 
140b00ab754SHans Petter Selasky /*
141b00ab754SHans Petter Selasky  * Start WinSock.
142*57e22627SCy Schubert  * Exported in case some applications using WinPcap/Npcap called it,
143b00ab754SHans Petter Selasky  * even though it wasn't exported.
144b00ab754SHans Petter Selasky  */
145b00ab754SHans Petter Selasky int
146b00ab754SHans Petter Selasky wsockinit(void)
147b00ab754SHans Petter Selasky {
148b00ab754SHans Petter Selasky 	WORD wVersionRequested;
149b00ab754SHans Petter Selasky 	WSADATA wsaData;
150b00ab754SHans Petter Selasky 	static int err = -1;
151b00ab754SHans Petter Selasky 	static int done = 0;
152b00ab754SHans Petter Selasky 
153b00ab754SHans Petter Selasky 	if (done)
154b00ab754SHans Petter Selasky 		return (err);
155b00ab754SHans Petter Selasky 
156b00ab754SHans Petter Selasky 	wVersionRequested = MAKEWORD( 1, 1);
157b00ab754SHans Petter Selasky 	err = WSAStartup( wVersionRequested, &wsaData );
158b00ab754SHans Petter Selasky 	atexit ((void(*)(void))WSACleanup);
159b00ab754SHans Petter Selasky 	done = 1;
160b00ab754SHans Petter Selasky 
161b00ab754SHans Petter Selasky 	if ( err != 0 )
162b00ab754SHans Petter Selasky 		err = -1;
163b00ab754SHans Petter Selasky 	return (err);
164b00ab754SHans Petter Selasky }
165b00ab754SHans Petter Selasky 
166b00ab754SHans Petter Selasky /*
167b00ab754SHans Petter Selasky  * This is the exported function; new programs should call this.
168b00ab754SHans Petter Selasky  */
169b00ab754SHans Petter Selasky int
170b00ab754SHans Petter Selasky pcap_wsockinit(void)
171b00ab754SHans Petter Selasky {
172b00ab754SHans Petter Selasky        return (wsockinit());
173b00ab754SHans Petter Selasky }
174b00ab754SHans Petter Selasky #endif /* _WIN32 */
175b00ab754SHans Petter Selasky 
176b00ab754SHans Petter Selasky /*
177b00ab754SHans Petter Selasky  * String containing the library version.
178b00ab754SHans Petter Selasky  * Not explicitly exported via a header file - the right API to use
179b00ab754SHans Petter Selasky  * is pcap_lib_version() - but some programs included it, so we
180b00ab754SHans Petter Selasky  * provide it.
181b00ab754SHans Petter Selasky  *
182b00ab754SHans Petter Selasky  * We declare it here, right before defining it, to squelch any
183b00ab754SHans Petter Selasky  * warnings we might get from compilers about the lack of a
184b00ab754SHans Petter Selasky  * declaration.
185b00ab754SHans Petter Selasky  */
186b00ab754SHans Petter Selasky PCAP_API char pcap_version[];
187b00ab754SHans Petter Selasky PCAP_API_DEF char pcap_version[] = PACKAGE_VERSION;
188b00ab754SHans Petter Selasky 
189*57e22627SCy Schubert static void
190*57e22627SCy Schubert pcap_set_not_initialized_message(pcap_t *pcap)
191a8e07101SRui Paulo {
192b00ab754SHans Petter Selasky 	if (pcap->activated) {
193b00ab754SHans Petter Selasky 		/* A module probably forgot to set the function pointer */
194b00ab754SHans Petter Selasky 		(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
195b00ab754SHans Petter Selasky 		    "This operation isn't properly handled by that device");
196*57e22627SCy Schubert 		return;
197b00ab754SHans Petter Selasky 	}
198ada6f083SXin LI 	/* in case the caller doesn't check for PCAP_ERROR_NOT_ACTIVATED */
199ada6f083SXin LI 	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
200ada6f083SXin LI 	    "This handle hasn't been activated yet");
201*57e22627SCy Schubert }
202*57e22627SCy Schubert 
203*57e22627SCy Schubert static int
204*57e22627SCy Schubert pcap_read_not_initialized(pcap_t *pcap, int cnt _U_, pcap_handler callback _U_,
205*57e22627SCy Schubert     u_char *user _U_)
206*57e22627SCy Schubert {
207*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
208*57e22627SCy Schubert 	/* this means 'not initialized' */
209*57e22627SCy Schubert 	return (PCAP_ERROR_NOT_ACTIVATED);
210*57e22627SCy Schubert }
211*57e22627SCy Schubert 
212*57e22627SCy Schubert static int
213*57e22627SCy Schubert pcap_inject_not_initialized(pcap_t *pcap, const void * buf _U_, size_t size _U_)
214*57e22627SCy Schubert {
215*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
216*57e22627SCy Schubert 	/* this means 'not initialized' */
217*57e22627SCy Schubert 	return (PCAP_ERROR_NOT_ACTIVATED);
218*57e22627SCy Schubert }
219*57e22627SCy Schubert 
220*57e22627SCy Schubert static int
221*57e22627SCy Schubert pcap_setfilter_not_initialized(pcap_t *pcap, struct bpf_program *fp _U_)
222*57e22627SCy Schubert {
223*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
224*57e22627SCy Schubert 	/* this means 'not initialized' */
225*57e22627SCy Schubert 	return (PCAP_ERROR_NOT_ACTIVATED);
226*57e22627SCy Schubert }
227*57e22627SCy Schubert 
228*57e22627SCy Schubert static int
229*57e22627SCy Schubert pcap_setdirection_not_initialized(pcap_t *pcap, pcap_direction_t d _U_)
230*57e22627SCy Schubert {
231*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
232*57e22627SCy Schubert 	/* this means 'not initialized' */
233*57e22627SCy Schubert 	return (PCAP_ERROR_NOT_ACTIVATED);
234*57e22627SCy Schubert }
235*57e22627SCy Schubert 
236*57e22627SCy Schubert static int
237*57e22627SCy Schubert pcap_set_datalink_not_initialized(pcap_t *pcap, int dlt _U_)
238*57e22627SCy Schubert {
239*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
240*57e22627SCy Schubert 	/* this means 'not initialized' */
241*57e22627SCy Schubert 	return (PCAP_ERROR_NOT_ACTIVATED);
242*57e22627SCy Schubert }
243*57e22627SCy Schubert 
244*57e22627SCy Schubert static int
245*57e22627SCy Schubert pcap_getnonblock_not_initialized(pcap_t *pcap)
246*57e22627SCy Schubert {
247*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
248*57e22627SCy Schubert 	/* this means 'not initialized' */
249*57e22627SCy Schubert 	return (PCAP_ERROR_NOT_ACTIVATED);
250*57e22627SCy Schubert }
251*57e22627SCy Schubert 
252*57e22627SCy Schubert static int
253*57e22627SCy Schubert pcap_stats_not_initialized(pcap_t *pcap, struct pcap_stat *ps _U_)
254*57e22627SCy Schubert {
255*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
256a8e07101SRui Paulo 	/* this means 'not initialized' */
257d1e87331SXin LI 	return (PCAP_ERROR_NOT_ACTIVATED);
258a8e07101SRui Paulo }
259a8e07101SRui Paulo 
260ada6f083SXin LI #ifdef _WIN32
261*57e22627SCy Schubert struct pcap_stat *
262*57e22627SCy Schubert pcap_stats_ex_not_initialized(pcap_t *pcap, int *pcap_stat_size _U_)
263681ed54cSXin LI {
264*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
265b00ab754SHans Petter Selasky 	return (NULL);
266b00ab754SHans Petter Selasky }
267*57e22627SCy Schubert 
268*57e22627SCy Schubert static int
269*57e22627SCy Schubert pcap_setbuff_not_initialized(pcap_t *pcap, int dim _U_)
270*57e22627SCy Schubert {
271*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
272*57e22627SCy Schubert 	/* this means 'not initialized' */
273*57e22627SCy Schubert 	return (PCAP_ERROR_NOT_ACTIVATED);
274*57e22627SCy Schubert }
275*57e22627SCy Schubert 
276*57e22627SCy Schubert static int
277*57e22627SCy Schubert pcap_setmode_not_initialized(pcap_t *pcap, int mode _U_)
278*57e22627SCy Schubert {
279*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
280*57e22627SCy Schubert 	/* this means 'not initialized' */
281*57e22627SCy Schubert 	return (PCAP_ERROR_NOT_ACTIVATED);
282*57e22627SCy Schubert }
283*57e22627SCy Schubert 
284*57e22627SCy Schubert static int
285*57e22627SCy Schubert pcap_setmintocopy_not_initialized(pcap_t *pcap, int size _U_)
286*57e22627SCy Schubert {
287*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
288*57e22627SCy Schubert 	/* this means 'not initialized' */
289*57e22627SCy Schubert 	return (PCAP_ERROR_NOT_ACTIVATED);
290ada6f083SXin LI }
291ada6f083SXin LI 
292ada6f083SXin LI static HANDLE
293ada6f083SXin LI pcap_getevent_not_initialized(pcap_t *pcap)
294ada6f083SXin LI {
295*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
296b00ab754SHans Petter Selasky 	return (INVALID_HANDLE_VALUE);
297b00ab754SHans Petter Selasky }
298*57e22627SCy Schubert 
299*57e22627SCy Schubert static int
300*57e22627SCy Schubert pcap_oid_get_request_not_initialized(pcap_t *pcap, bpf_u_int32 oid _U_,
301*57e22627SCy Schubert     void *data _U_, size_t *lenp _U_)
302*57e22627SCy Schubert {
303*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
304*57e22627SCy Schubert 	return (PCAP_ERROR_NOT_ACTIVATED);
305*57e22627SCy Schubert }
306*57e22627SCy Schubert 
307*57e22627SCy Schubert static int
308*57e22627SCy Schubert pcap_oid_set_request_not_initialized(pcap_t *pcap, bpf_u_int32 oid _U_,
309*57e22627SCy Schubert     const void *data _U_, size_t *lenp _U_)
310*57e22627SCy Schubert {
311*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
312*57e22627SCy Schubert 	return (PCAP_ERROR_NOT_ACTIVATED);
313ada6f083SXin LI }
314ada6f083SXin LI 
315ada6f083SXin LI static u_int
316ada6f083SXin LI pcap_sendqueue_transmit_not_initialized(pcap_t *pcap, pcap_send_queue* queue, int sync)
317ada6f083SXin LI {
318*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
319b00ab754SHans Petter Selasky 	return (0);
320b00ab754SHans Petter Selasky }
321*57e22627SCy Schubert 
322*57e22627SCy Schubert static int
323*57e22627SCy Schubert pcap_setuserbuffer_not_initialized(pcap_t *pcap, int size _U_)
324*57e22627SCy Schubert {
325*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
326*57e22627SCy Schubert 	return (PCAP_ERROR_NOT_ACTIVATED);
327*57e22627SCy Schubert }
328*57e22627SCy Schubert 
329*57e22627SCy Schubert static int
330*57e22627SCy Schubert pcap_live_dump_not_initialized(pcap_t *pcap, char *filename _U_, int maxsize _U_,
331*57e22627SCy Schubert     int maxpacks _U_)
332*57e22627SCy Schubert {
333*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
334*57e22627SCy Schubert 	return (PCAP_ERROR_NOT_ACTIVATED);
335*57e22627SCy Schubert }
336*57e22627SCy Schubert 
337*57e22627SCy Schubert static int
338*57e22627SCy Schubert pcap_live_dump_ended_not_initialized(pcap_t *pcap, int sync _U_)
339*57e22627SCy Schubert {
340*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
341*57e22627SCy Schubert 	return (PCAP_ERROR_NOT_ACTIVATED);
342ada6f083SXin LI }
343ada6f083SXin LI 
344ada6f083SXin LI static PAirpcapHandle
345ada6f083SXin LI pcap_get_airpcap_handle_not_initialized(pcap_t *pcap)
346ada6f083SXin LI {
347*57e22627SCy Schubert 	pcap_set_not_initialized_message(pcap);
348681ed54cSXin LI 	return (NULL);
349681ed54cSXin LI }
350681ed54cSXin LI #endif
351681ed54cSXin LI 
352a8e07101SRui Paulo /*
353a8e07101SRui Paulo  * Returns 1 if rfmon mode can be set on the pcap_t, 0 if it can't,
354a8e07101SRui Paulo  * a PCAP_ERROR value on an error.
355a8e07101SRui Paulo  */
356a8e07101SRui Paulo int
357a8e07101SRui Paulo pcap_can_set_rfmon(pcap_t *p)
358a8e07101SRui Paulo {
359a8e07101SRui Paulo 	return (p->can_set_rfmon_op(p));
360a8e07101SRui Paulo }
361a8e07101SRui Paulo 
362a8e07101SRui Paulo /*
363a8e07101SRui Paulo  * For systems where rfmon mode is never supported.
364a8e07101SRui Paulo  */
365a8e07101SRui Paulo static int
366a8e07101SRui Paulo pcap_cant_set_rfmon(pcap_t *p _U_)
367a8e07101SRui Paulo {
368a8e07101SRui Paulo 	return (0);
369a8e07101SRui Paulo }
370a8e07101SRui Paulo 
371a8e07101SRui Paulo /*
372d1e87331SXin LI  * Sets *tstamp_typesp to point to an array 1 or more supported time stamp
373d1e87331SXin LI  * types; the return value is the number of supported time stamp types.
374d1e87331SXin LI  * The list should be freed by a call to pcap_free_tstamp_types() when
375d1e87331SXin LI  * you're done with it.
376d1e87331SXin LI  *
377d1e87331SXin LI  * A return value of 0 means "you don't get a choice of time stamp type",
378d1e87331SXin LI  * in which case *tstamp_typesp is set to null.
379d1e87331SXin LI  *
380d1e87331SXin LI  * PCAP_ERROR is returned on error.
381d1e87331SXin LI  */
382d1e87331SXin LI int
383d1e87331SXin LI pcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp)
384d1e87331SXin LI {
385d1e87331SXin LI 	if (p->tstamp_type_count == 0) {
386d1e87331SXin LI 		/*
387d1e87331SXin LI 		 * We don't support multiple time stamp types.
388*57e22627SCy Schubert 		 * That means the only type we support is PCAP_TSTAMP_HOST;
389*57e22627SCy Schubert 		 * set up a list containing only that type.
390d1e87331SXin LI 		 */
391*57e22627SCy Schubert 		*tstamp_typesp = (int*)malloc(sizeof(**tstamp_typesp));
392*57e22627SCy Schubert 		if (*tstamp_typesp == NULL) {
393*57e22627SCy Schubert 			pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
394*57e22627SCy Schubert 			    errno, "malloc");
395*57e22627SCy Schubert 			return (PCAP_ERROR);
396*57e22627SCy Schubert 		}
397*57e22627SCy Schubert 		**tstamp_typesp = PCAP_TSTAMP_HOST;
398*57e22627SCy Schubert 		return (1);
399d1e87331SXin LI 	} else {
400d1e87331SXin LI 		*tstamp_typesp = (int*)calloc(sizeof(**tstamp_typesp),
401d1e87331SXin LI 		    p->tstamp_type_count);
402d1e87331SXin LI 		if (*tstamp_typesp == NULL) {
403b00ab754SHans Petter Selasky 			pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
404b00ab754SHans Petter Selasky 			    errno, "malloc");
405d1e87331SXin LI 			return (PCAP_ERROR);
406d1e87331SXin LI 		}
407d1e87331SXin LI 		(void)memcpy(*tstamp_typesp, p->tstamp_type_list,
408d1e87331SXin LI 		    sizeof(**tstamp_typesp) * p->tstamp_type_count);
409d1e87331SXin LI 		return (p->tstamp_type_count);
410d1e87331SXin LI 	}
411*57e22627SCy Schubert }
412d1e87331SXin LI 
413d1e87331SXin LI /*
414d1e87331SXin LI  * In Windows, you might have a library built with one version of the
415d1e87331SXin LI  * C runtime library and an application built with another version of
416d1e87331SXin LI  * the C runtime library, which means that the library might use one
417d1e87331SXin LI  * version of malloc() and free() and the application might use another
418d1e87331SXin LI  * version of malloc() and free().  If so, that means something
419d1e87331SXin LI  * allocated by the library cannot be freed by the application, so we
420d1e87331SXin LI  * need to have a pcap_free_tstamp_types() routine to free up the list
421d1e87331SXin LI  * allocated by pcap_list_tstamp_types(), even though it's just a wrapper
422d1e87331SXin LI  * around free().
423d1e87331SXin LI  */
424d1e87331SXin LI void
425d1e87331SXin LI pcap_free_tstamp_types(int *tstamp_type_list)
426d1e87331SXin LI {
427d1e87331SXin LI 	free(tstamp_type_list);
428d1e87331SXin LI }
429d1e87331SXin LI 
430d1e87331SXin LI /*
431a0ee43a1SRui Paulo  * Default one-shot callback; overridden for capture types where the
432a0ee43a1SRui Paulo  * packet data cannot be guaranteed to be available after the callback
433a0ee43a1SRui Paulo  * returns, so that a copy must be made.
434a8e07101SRui Paulo  */
435681ed54cSXin LI void
436a0ee43a1SRui Paulo pcap_oneshot(u_char *user, const struct pcap_pkthdr *h, const u_char *pkt)
437a0ee43a1SRui Paulo {
438a0ee43a1SRui Paulo 	struct oneshot_userdata *sp = (struct oneshot_userdata *)user;
439a0ee43a1SRui Paulo 
440a0ee43a1SRui Paulo 	*sp->hdr = *h;
441a0ee43a1SRui Paulo 	*sp->pkt = pkt;
442a0ee43a1SRui Paulo }
443a0ee43a1SRui Paulo 
444a0ee43a1SRui Paulo const u_char *
445a0ee43a1SRui Paulo pcap_next(pcap_t *p, struct pcap_pkthdr *h)
446a0ee43a1SRui Paulo {
447a0ee43a1SRui Paulo 	struct oneshot_userdata s;
448a0ee43a1SRui Paulo 	const u_char *pkt;
449a0ee43a1SRui Paulo 
450a0ee43a1SRui Paulo 	s.hdr = h;
451a0ee43a1SRui Paulo 	s.pkt = &pkt;
452a0ee43a1SRui Paulo 	s.pd = p;
453a0ee43a1SRui Paulo 	if (pcap_dispatch(p, 1, p->oneshot_callback, (u_char *)&s) <= 0)
454a0ee43a1SRui Paulo 		return (0);
455a0ee43a1SRui Paulo 	return (pkt);
456a0ee43a1SRui Paulo }
457a0ee43a1SRui Paulo 
458a0ee43a1SRui Paulo int
459a0ee43a1SRui Paulo pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
460a0ee43a1SRui Paulo     const u_char **pkt_data)
461a0ee43a1SRui Paulo {
462a0ee43a1SRui Paulo 	struct oneshot_userdata s;
463a0ee43a1SRui Paulo 
464a0ee43a1SRui Paulo 	s.hdr = &p->pcap_header;
465a0ee43a1SRui Paulo 	s.pkt = pkt_data;
466a0ee43a1SRui Paulo 	s.pd = p;
467a0ee43a1SRui Paulo 
468a0ee43a1SRui Paulo 	/* Saves a pointer to the packet headers */
469a0ee43a1SRui Paulo 	*pkt_header= &p->pcap_header;
470a0ee43a1SRui Paulo 
471681ed54cSXin LI 	if (p->rfile != NULL) {
472a0ee43a1SRui Paulo 		int status;
473a0ee43a1SRui Paulo 
474a0ee43a1SRui Paulo 		/* We are on an offline capture */
475d1e87331SXin LI 		status = pcap_offline_read(p, 1, p->oneshot_callback,
476d1e87331SXin LI 		    (u_char *)&s);
477a8e07101SRui Paulo 
478a8e07101SRui Paulo 		/*
479a0ee43a1SRui Paulo 		 * Return codes for pcap_offline_read() are:
480a0ee43a1SRui Paulo 		 *   -  0: EOF
481a0ee43a1SRui Paulo 		 *   - -1: error
482a0ee43a1SRui Paulo 		 *   - >1: OK
483a0ee43a1SRui Paulo 		 * The first one ('0') conflicts with the return code of
484a0ee43a1SRui Paulo 		 * 0 from pcap_read() meaning "no packets arrived before
485a0ee43a1SRui Paulo 		 * the timeout expired", so we map it to -2 so you can
486a0ee43a1SRui Paulo 		 * distinguish between an EOF from a savefile and a
487a0ee43a1SRui Paulo 		 * "no packets arrived before the timeout expired, try
488a0ee43a1SRui Paulo 		 * again" from a live capture.
489a0ee43a1SRui Paulo 		 */
490a0ee43a1SRui Paulo 		if (status == 0)
491a0ee43a1SRui Paulo 			return (-2);
492a0ee43a1SRui Paulo 		else
493a0ee43a1SRui Paulo 			return (status);
494a0ee43a1SRui Paulo 	}
495a0ee43a1SRui Paulo 
496a0ee43a1SRui Paulo 	/*
497a0ee43a1SRui Paulo 	 * Return codes for pcap_read() are:
498a0ee43a1SRui Paulo 	 *   -  0: timeout
499a0ee43a1SRui Paulo 	 *   - -1: error
500a0ee43a1SRui Paulo 	 *   - -2: loop was broken out of with pcap_breakloop()
501a0ee43a1SRui Paulo 	 *   - >1: OK
502a0ee43a1SRui Paulo 	 * The first one ('0') conflicts with the return code of 0 from
503a0ee43a1SRui Paulo 	 * pcap_offline_read() meaning "end of file".
504a0ee43a1SRui Paulo 	*/
505d1e87331SXin LI 	return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s));
506a0ee43a1SRui Paulo }
507a0ee43a1SRui Paulo 
508b00ab754SHans Petter Selasky /*
509b00ab754SHans Petter Selasky  * Implementation of a pcap_if_list_t.
510b00ab754SHans Petter Selasky  */
511b00ab754SHans Petter Selasky struct pcap_if_list {
512b00ab754SHans Petter Selasky 	pcap_if_t *beginning;
513b00ab754SHans Petter Selasky };
514b00ab754SHans Petter Selasky 
515ada6f083SXin LI static struct capture_source_type {
516b00ab754SHans Petter Selasky 	int (*findalldevs_op)(pcap_if_list_t *, char *);
517edc89b24SXin LI 	pcap_t *(*create_op)(const char *, char *, int *);
518edc89b24SXin LI } capture_source_types[] = {
519edc89b24SXin LI #ifdef HAVE_DAG_API
520edc89b24SXin LI 	{ dag_findalldevs, dag_create },
521edc89b24SXin LI #endif
522edc89b24SXin LI #ifdef HAVE_SEPTEL_API
523edc89b24SXin LI 	{ septel_findalldevs, septel_create },
524edc89b24SXin LI #endif
525edc89b24SXin LI #ifdef HAVE_SNF_API
526edc89b24SXin LI 	{ snf_findalldevs, snf_create },
527edc89b24SXin LI #endif
528ada6f083SXin LI #ifdef HAVE_TC_API
529ada6f083SXin LI 	{ TcFindAllDevs, TcCreate },
530ada6f083SXin LI #endif
531edc89b24SXin LI #ifdef PCAP_SUPPORT_BT
532edc89b24SXin LI 	{ bt_findalldevs, bt_create },
533edc89b24SXin LI #endif
534681ed54cSXin LI #ifdef PCAP_SUPPORT_BT_MONITOR
535681ed54cSXin LI 	{ bt_monitor_findalldevs, bt_monitor_create },
536681ed54cSXin LI #endif
537edc89b24SXin LI #ifdef PCAP_SUPPORT_USB
538edc89b24SXin LI 	{ usb_findalldevs, usb_create },
539edc89b24SXin LI #endif
540edc89b24SXin LI #ifdef PCAP_SUPPORT_NETFILTER
541edc89b24SXin LI 	{ netfilter_findalldevs, netfilter_create },
542edc89b24SXin LI #endif
543b00ab754SHans Petter Selasky #ifdef PCAP_SUPPORT_NETMAP
544b00ab754SHans Petter Selasky 	{ pcap_netmap_findalldevs, pcap_netmap_create },
545b00ab754SHans Petter Selasky #endif
546681ed54cSXin LI #ifdef PCAP_SUPPORT_DBUS
547681ed54cSXin LI 	{ dbus_findalldevs, dbus_create },
548681ed54cSXin LI #endif
549b00ab754SHans Petter Selasky #ifdef PCAP_SUPPORT_RDMASNIFF
550b00ab754SHans Petter Selasky 	{ rdmasniff_findalldevs, rdmasniff_create },
551b00ab754SHans Petter Selasky #endif
552edc89b24SXin LI 	{ NULL, NULL }
553edc89b24SXin LI };
554edc89b24SXin LI 
555edc89b24SXin LI /*
556edc89b24SXin LI  * Get a list of all capture sources that are up and that we can open.
557edc89b24SXin LI  * Returns -1 on error, 0 otherwise.
558edc89b24SXin LI  * The list, as returned through "alldevsp", may be null if no interfaces
559edc89b24SXin LI  * were up and could be opened.
560edc89b24SXin LI  */
561edc89b24SXin LI int
562edc89b24SXin LI pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
563edc89b24SXin LI {
564edc89b24SXin LI 	size_t i;
565b00ab754SHans Petter Selasky 	pcap_if_list_t devlist;
566edc89b24SXin LI 
567edc89b24SXin LI 	/*
568ada6f083SXin LI 	 * Find all the local network interfaces on which we
569ada6f083SXin LI 	 * can capture.
570edc89b24SXin LI 	 */
571b00ab754SHans Petter Selasky 	devlist.beginning = NULL;
572b00ab754SHans Petter Selasky 	if (pcap_platform_finddevs(&devlist, errbuf) == -1) {
573b00ab754SHans Petter Selasky 		/*
574b00ab754SHans Petter Selasky 		 * Failed - free all of the entries we were given
575b00ab754SHans Petter Selasky 		 * before we failed.
576b00ab754SHans Petter Selasky 		 */
577b00ab754SHans Petter Selasky 		if (devlist.beginning != NULL)
578b00ab754SHans Petter Selasky 			pcap_freealldevs(devlist.beginning);
579b00ab754SHans Petter Selasky 		*alldevsp = NULL;
580edc89b24SXin LI 		return (-1);
581b00ab754SHans Petter Selasky 	}
582edc89b24SXin LI 
583edc89b24SXin LI 	/*
584edc89b24SXin LI 	 * Ask each of the non-local-network-interface capture
585edc89b24SXin LI 	 * source types what interfaces they have.
586edc89b24SXin LI 	 */
587edc89b24SXin LI 	for (i = 0; capture_source_types[i].findalldevs_op != NULL; i++) {
588b00ab754SHans Petter Selasky 		if (capture_source_types[i].findalldevs_op(&devlist, errbuf) == -1) {
589edc89b24SXin LI 			/*
590edc89b24SXin LI 			 * We had an error; free the list we've been
591edc89b24SXin LI 			 * constructing.
592edc89b24SXin LI 			 */
593b00ab754SHans Petter Selasky 			if (devlist.beginning != NULL)
594b00ab754SHans Petter Selasky 				pcap_freealldevs(devlist.beginning);
595edc89b24SXin LI 			*alldevsp = NULL;
596edc89b24SXin LI 			return (-1);
597edc89b24SXin LI 		}
598edc89b24SXin LI 	}
599681ed54cSXin LI 
600b00ab754SHans Petter Selasky 	/*
601b00ab754SHans Petter Selasky 	 * Return the first entry of the list of all devices.
602b00ab754SHans Petter Selasky 	 */
603b00ab754SHans Petter Selasky 	*alldevsp = devlist.beginning;
604edc89b24SXin LI 	return (0);
605edc89b24SXin LI }
606edc89b24SXin LI 
607b00ab754SHans Petter Selasky static struct sockaddr *
608b00ab754SHans Petter Selasky dup_sockaddr(struct sockaddr *sa, size_t sa_length)
609b00ab754SHans Petter Selasky {
610b00ab754SHans Petter Selasky 	struct sockaddr *newsa;
611b00ab754SHans Petter Selasky 
612b00ab754SHans Petter Selasky 	if ((newsa = malloc(sa_length)) == NULL)
613b00ab754SHans Petter Selasky 		return (NULL);
614b00ab754SHans Petter Selasky 	return (memcpy(newsa, sa, sa_length));
615b00ab754SHans Petter Selasky }
616b00ab754SHans Petter Selasky 
617b00ab754SHans Petter Selasky /*
618b00ab754SHans Petter Selasky  * Construct a "figure of merit" for an interface, for use when sorting
619b00ab754SHans Petter Selasky  * the list of interfaces, in which interfaces that are up are superior
620b00ab754SHans Petter Selasky  * to interfaces that aren't up, interfaces that are up and running are
621b00ab754SHans Petter Selasky  * superior to interfaces that are up but not running, and non-loopback
622b00ab754SHans Petter Selasky  * interfaces that are up and running are superior to loopback interfaces,
623b00ab754SHans Petter Selasky  * and interfaces with the same flags have a figure of merit that's higher
624b00ab754SHans Petter Selasky  * the lower the instance number.
625b00ab754SHans Petter Selasky  *
626b00ab754SHans Petter Selasky  * The goal is to try to put the interfaces most likely to be useful for
627b00ab754SHans Petter Selasky  * capture at the beginning of the list.
628b00ab754SHans Petter Selasky  *
629b00ab754SHans Petter Selasky  * The figure of merit, which is lower the "better" the interface is,
630b00ab754SHans Petter Selasky  * has the uppermost bit set if the interface isn't running, the bit
631b00ab754SHans Petter Selasky  * below that set if the interface isn't up, the bit below that set
632b00ab754SHans Petter Selasky  * if the interface is a loopback interface, and the interface index
633b00ab754SHans Petter Selasky  * in the 29 bits below that.  (Yes, we assume u_int is 32 bits.)
634b00ab754SHans Petter Selasky  */
635b00ab754SHans Petter Selasky static u_int
636b00ab754SHans Petter Selasky get_figure_of_merit(pcap_if_t *dev)
637b00ab754SHans Petter Selasky {
638b00ab754SHans Petter Selasky 	const char *cp;
639b00ab754SHans Petter Selasky 	u_int n;
640b00ab754SHans Petter Selasky 
641b00ab754SHans Petter Selasky 	if (strcmp(dev->name, "any") == 0) {
642b00ab754SHans Petter Selasky 		/*
643b00ab754SHans Petter Selasky 		 * Give the "any" device an artificially high instance
644b00ab754SHans Petter Selasky 		 * number, so it shows up after all other non-loopback
645b00ab754SHans Petter Selasky 		 * interfaces.
646b00ab754SHans Petter Selasky 		 */
647b00ab754SHans Petter Selasky 		n = 0x1FFFFFFF;	/* 29 all-1 bits */
648b00ab754SHans Petter Selasky 	} else {
649b00ab754SHans Petter Selasky 		/*
650b00ab754SHans Petter Selasky 		 * A number at the end of the device name string is
651b00ab754SHans Petter Selasky 		 * assumed to be an instance number.  Add 1 to the
652b00ab754SHans Petter Selasky 		 * instance number, and use 0 for "no instance
653b00ab754SHans Petter Selasky 		 * number", so we don't put "no instance number"
654b00ab754SHans Petter Selasky 		 * devices and "instance 0" devices together.
655b00ab754SHans Petter Selasky 		 */
656b00ab754SHans Petter Selasky 		cp = dev->name + strlen(dev->name) - 1;
657b00ab754SHans Petter Selasky 		while (cp-1 >= dev->name && *(cp-1) >= '0' && *(cp-1) <= '9')
658b00ab754SHans Petter Selasky 			cp--;
659b00ab754SHans Petter Selasky 		if (*cp >= '0' && *cp <= '9')
660b00ab754SHans Petter Selasky 			n = atoi(cp) + 1;
661b00ab754SHans Petter Selasky 		else
662b00ab754SHans Petter Selasky 			n = 0;
663b00ab754SHans Petter Selasky 	}
664b00ab754SHans Petter Selasky 	if (!(dev->flags & PCAP_IF_RUNNING))
665b00ab754SHans Petter Selasky 		n |= 0x80000000;
666b00ab754SHans Petter Selasky 	if (!(dev->flags & PCAP_IF_UP))
667b00ab754SHans Petter Selasky 		n |= 0x40000000;
668b00ab754SHans Petter Selasky 
669b00ab754SHans Petter Selasky 	/*
670b00ab754SHans Petter Selasky 	 * Give non-wireless interfaces that aren't disconnected a better
671b00ab754SHans Petter Selasky 	 * figure of merit than interfaces that are disconnected, as
672b00ab754SHans Petter Selasky 	 * "disconnected" should indicate that the interface isn't
673b00ab754SHans Petter Selasky 	 * plugged into a network and thus won't give you any traffic.
674b00ab754SHans Petter Selasky 	 *
675b00ab754SHans Petter Selasky 	 * For wireless interfaces, it means "associated with a network",
676b00ab754SHans Petter Selasky 	 * which we presume not to necessarily prevent capture, as you
677b00ab754SHans Petter Selasky 	 * might run the adapter in some flavor of monitor mode.
678b00ab754SHans Petter Selasky 	 */
679b00ab754SHans Petter Selasky 	if (!(dev->flags & PCAP_IF_WIRELESS) &&
680b00ab754SHans Petter Selasky 	    (dev->flags & PCAP_IF_CONNECTION_STATUS) == PCAP_IF_CONNECTION_STATUS_DISCONNECTED)
681b00ab754SHans Petter Selasky 		n |= 0x20000000;
682b00ab754SHans Petter Selasky 
683b00ab754SHans Petter Selasky 	/*
684b00ab754SHans Petter Selasky 	 * Sort loopback devices after non-loopback devices, *except* for
685b00ab754SHans Petter Selasky 	 * disconnected devices.
686b00ab754SHans Petter Selasky 	 */
687b00ab754SHans Petter Selasky 	if (dev->flags & PCAP_IF_LOOPBACK)
688b00ab754SHans Petter Selasky 		n |= 0x10000000;
689b00ab754SHans Petter Selasky 
690b00ab754SHans Petter Selasky 	return (n);
691b00ab754SHans Petter Selasky }
692b00ab754SHans Petter Selasky 
693b00ab754SHans Petter Selasky #ifndef _WIN32
694b00ab754SHans Petter Selasky /*
695b00ab754SHans Petter Selasky  * Try to get a description for a given device.
696b00ab754SHans Petter Selasky  * Returns a mallocated description if it could and NULL if it couldn't.
697b00ab754SHans Petter Selasky  *
698b00ab754SHans Petter Selasky  * XXX - on FreeBSDs that support it, should it get the sysctl named
699b00ab754SHans Petter Selasky  * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
700b00ab754SHans Petter Selasky  * of the adapter?  Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
701b00ab754SHans Petter Selasky  * with my Cisco 350 card, so the name isn't entirely descriptive.  The
702b00ab754SHans Petter Selasky  * "dev.an.0.%pnpinfo" has a better description, although one might argue
703b00ab754SHans Petter Selasky  * that the problem is really a driver bug - if it can find out that it's
704b00ab754SHans Petter Selasky  * a Cisco 340 or 350, rather than an old Aironet card, it should use
705b00ab754SHans Petter Selasky  * that in the description.
706b00ab754SHans Petter Selasky  *
707b00ab754SHans Petter Selasky  * Do NetBSD, DragonflyBSD, or OpenBSD support this as well?  FreeBSD
708b00ab754SHans Petter Selasky  * and OpenBSD let you get a description, but it's not generated by the OS,
709b00ab754SHans Petter Selasky  * it's set with another ioctl that ifconfig supports; we use that to get
710b00ab754SHans Petter Selasky  * a description in FreeBSD and OpenBSD, but if there is no such
711b00ab754SHans Petter Selasky  * description available, it still might be nice to get some description
712b00ab754SHans Petter Selasky  * string based on the device type or something such as that.
713b00ab754SHans Petter Selasky  *
714b00ab754SHans Petter Selasky  * In macOS, the System Configuration framework can apparently return
715b00ab754SHans Petter Selasky  * names in 10.4 and later.
716b00ab754SHans Petter Selasky  *
717b00ab754SHans Petter Selasky  * It also appears that freedesktop.org's HAL offers an "info.product"
718b00ab754SHans Petter Selasky  * string, but the HAL specification says it "should not be used in any
719b00ab754SHans Petter Selasky  * UI" and "subsystem/capability specific properties" should be used
720b00ab754SHans Petter Selasky  * instead and, in any case, I think HAL is being deprecated in
721b00ab754SHans Petter Selasky  * favor of other stuff such as DeviceKit.  DeviceKit doesn't appear
722b00ab754SHans Petter Selasky  * to have any obvious product information for devices, but maybe
723b00ab754SHans Petter Selasky  * I haven't looked hard enough.
724b00ab754SHans Petter Selasky  *
725b00ab754SHans Petter Selasky  * Using the System Configuration framework, or HAL, or DeviceKit, or
726b00ab754SHans Petter Selasky  * whatever, would require that libpcap applications be linked with
727b00ab754SHans Petter Selasky  * the frameworks/libraries in question.  That shouldn't be a problem
728b00ab754SHans Petter Selasky  * for programs linking with the shared version of libpcap (unless
729b00ab754SHans Petter Selasky  * you're running on AIX - which I think is the only UN*X that doesn't
730b00ab754SHans Petter Selasky  * support linking a shared library with other libraries on which it
731b00ab754SHans Petter Selasky  * depends, and having an executable linked only with the first shared
732b00ab754SHans Petter Selasky  * library automatically pick up the other libraries when started -
733b00ab754SHans Petter Selasky  * and using HAL or whatever).  Programs linked with the static
734b00ab754SHans Petter Selasky  * version of libpcap would have to use pcap-config with the --static
735b00ab754SHans Petter Selasky  * flag in order to get the right linker flags in order to pick up
736b00ab754SHans Petter Selasky  * the additional libraries/frameworks; those programs need that anyway
737b00ab754SHans Petter Selasky  * for libpcap 1.1 and beyond on Linux, as, by default, it requires
738b00ab754SHans Petter Selasky  * -lnl.
739b00ab754SHans Petter Selasky  *
740b00ab754SHans Petter Selasky  * Do any other UN*Xes, or desktop environments support getting a
741b00ab754SHans Petter Selasky  * description?
742b00ab754SHans Petter Selasky  */
743b00ab754SHans Petter Selasky static char *
744b00ab754SHans Petter Selasky #ifdef SIOCGIFDESCR
745b00ab754SHans Petter Selasky get_if_description(const char *name)
746b00ab754SHans Petter Selasky {
747b00ab754SHans Petter Selasky 	char *description = NULL;
748b00ab754SHans Petter Selasky 	int s;
749b00ab754SHans Petter Selasky 	struct ifreq ifrdesc;
750b00ab754SHans Petter Selasky #ifndef IFDESCRSIZE
751b00ab754SHans Petter Selasky 	size_t descrlen = 64;
752b00ab754SHans Petter Selasky #else
753b00ab754SHans Petter Selasky 	size_t descrlen = IFDESCRSIZE;
754b00ab754SHans Petter Selasky #endif /* IFDESCRSIZE */
755b00ab754SHans Petter Selasky 
756b00ab754SHans Petter Selasky 	/*
757b00ab754SHans Petter Selasky 	 * Get the description for the interface.
758b00ab754SHans Petter Selasky 	 */
759b00ab754SHans Petter Selasky 	memset(&ifrdesc, 0, sizeof ifrdesc);
760*57e22627SCy Schubert 	pcap_strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
761b00ab754SHans Petter Selasky 	s = socket(AF_INET, SOCK_DGRAM, 0);
762b00ab754SHans Petter Selasky 	if (s >= 0) {
763b00ab754SHans Petter Selasky #ifdef __FreeBSD__
764b00ab754SHans Petter Selasky 		/*
765b00ab754SHans Petter Selasky 		 * On FreeBSD, if the buffer isn't big enough for the
766b00ab754SHans Petter Selasky 		 * description, the ioctl succeeds, but the description
767b00ab754SHans Petter Selasky 		 * isn't copied, ifr_buffer.length is set to the description
768b00ab754SHans Petter Selasky 		 * length, and ifr_buffer.buffer is set to NULL.
769b00ab754SHans Petter Selasky 		 */
770b00ab754SHans Petter Selasky 		for (;;) {
771b00ab754SHans Petter Selasky 			free(description);
772b00ab754SHans Petter Selasky 			if ((description = malloc(descrlen)) != NULL) {
773b00ab754SHans Petter Selasky 				ifrdesc.ifr_buffer.buffer = description;
774b00ab754SHans Petter Selasky 				ifrdesc.ifr_buffer.length = descrlen;
775b00ab754SHans Petter Selasky 				if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
776b00ab754SHans Petter Selasky 					if (ifrdesc.ifr_buffer.buffer ==
777b00ab754SHans Petter Selasky 					    description)
778b00ab754SHans Petter Selasky 						break;
779b00ab754SHans Petter Selasky 					else
780b00ab754SHans Petter Selasky 						descrlen = ifrdesc.ifr_buffer.length;
781b00ab754SHans Petter Selasky 				} else {
782b00ab754SHans Petter Selasky 					/*
783b00ab754SHans Petter Selasky 					 * Failed to get interface description.
784b00ab754SHans Petter Selasky 					 */
785b00ab754SHans Petter Selasky 					free(description);
786b00ab754SHans Petter Selasky 					description = NULL;
787b00ab754SHans Petter Selasky 					break;
788b00ab754SHans Petter Selasky 				}
789b00ab754SHans Petter Selasky 			} else
790b00ab754SHans Petter Selasky 				break;
791b00ab754SHans Petter Selasky 		}
792b00ab754SHans Petter Selasky #else /* __FreeBSD__ */
793b00ab754SHans Petter Selasky 		/*
794b00ab754SHans Petter Selasky 		 * The only other OS that currently supports
795b00ab754SHans Petter Selasky 		 * SIOCGIFDESCR is OpenBSD, and it has no way
796b00ab754SHans Petter Selasky 		 * to get the description length - it's clamped
797b00ab754SHans Petter Selasky 		 * to a maximum of IFDESCRSIZE.
798b00ab754SHans Petter Selasky 		 */
799b00ab754SHans Petter Selasky 		if ((description = malloc(descrlen)) != NULL) {
800b00ab754SHans Petter Selasky 			ifrdesc.ifr_data = (caddr_t)description;
801b00ab754SHans Petter Selasky 			if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
802b00ab754SHans Petter Selasky 				/*
803b00ab754SHans Petter Selasky 				 * Failed to get interface description.
804b00ab754SHans Petter Selasky 				 */
805b00ab754SHans Petter Selasky 				free(description);
806b00ab754SHans Petter Selasky 				description = NULL;
807b00ab754SHans Petter Selasky 			}
808b00ab754SHans Petter Selasky 		}
809b00ab754SHans Petter Selasky #endif /* __FreeBSD__ */
810b00ab754SHans Petter Selasky 		close(s);
811*57e22627SCy Schubert 		if (description != NULL && description[0] == '\0') {
812b00ab754SHans Petter Selasky 			/*
813b00ab754SHans Petter Selasky 			 * Description is empty, so discard it.
814b00ab754SHans Petter Selasky 			 */
815b00ab754SHans Petter Selasky 			free(description);
816b00ab754SHans Petter Selasky 			description = NULL;
817b00ab754SHans Petter Selasky 		}
818b00ab754SHans Petter Selasky 	}
819b00ab754SHans Petter Selasky 
820b00ab754SHans Petter Selasky #ifdef __FreeBSD__
821b00ab754SHans Petter Selasky 	/*
822b00ab754SHans Petter Selasky 	 * For FreeBSD, if we didn't get a description, and this is
823b00ab754SHans Petter Selasky 	 * a device with a name of the form usbusN, label it as a USB
824b00ab754SHans Petter Selasky 	 * bus.
825b00ab754SHans Petter Selasky 	 */
826b00ab754SHans Petter Selasky 	if (description == NULL) {
827b00ab754SHans Petter Selasky 		if (strncmp(name, "usbus", 5) == 0) {
828b00ab754SHans Petter Selasky 			/*
829b00ab754SHans Petter Selasky 			 * OK, it begins with "usbus".
830b00ab754SHans Petter Selasky 			 */
831b00ab754SHans Petter Selasky 			long busnum;
832b00ab754SHans Petter Selasky 			char *p;
833b00ab754SHans Petter Selasky 
834b00ab754SHans Petter Selasky 			errno = 0;
835b00ab754SHans Petter Selasky 			busnum = strtol(name + 5, &p, 10);
836b00ab754SHans Petter Selasky 			if (errno == 0 && p != name + 5 && *p == '\0' &&
837b00ab754SHans Petter Selasky 			    busnum >= 0 && busnum <= INT_MAX) {
838b00ab754SHans Petter Selasky 				/*
839b00ab754SHans Petter Selasky 				 * OK, it's a valid number that's not
840b00ab754SHans Petter Selasky 				 * bigger than INT_MAX.  Construct
841b00ab754SHans Petter Selasky 				 * a description from it.
842*57e22627SCy Schubert 				 * (If that fails, we don't worry about
843*57e22627SCy Schubert 				 * it, we just return NULL.)
844b00ab754SHans Petter Selasky 				 */
845*57e22627SCy Schubert 				if (pcap_asprintf(&description,
846*57e22627SCy Schubert 				    "USB bus number %ld", busnum) == -1) {
847*57e22627SCy Schubert 					/* Failed. */
848*57e22627SCy Schubert 					description = NULL;
849b00ab754SHans Petter Selasky 				}
850b00ab754SHans Petter Selasky 			}
851b00ab754SHans Petter Selasky 		}
852b00ab754SHans Petter Selasky 	}
853b00ab754SHans Petter Selasky #endif
854b00ab754SHans Petter Selasky 	return (description);
855b00ab754SHans Petter Selasky #else /* SIOCGIFDESCR */
856b00ab754SHans Petter Selasky get_if_description(const char *name _U_)
857b00ab754SHans Petter Selasky {
858b00ab754SHans Petter Selasky 	return (NULL);
859b00ab754SHans Petter Selasky #endif /* SIOCGIFDESCR */
860b00ab754SHans Petter Selasky }
861b00ab754SHans Petter Selasky 
862b00ab754SHans Petter Selasky /*
863b00ab754SHans Petter Selasky  * Look for a given device in the specified list of devices.
864b00ab754SHans Petter Selasky  *
865b00ab754SHans Petter Selasky  * If we find it, return a pointer to its entry.
866b00ab754SHans Petter Selasky  *
867b00ab754SHans Petter Selasky  * If we don't find it, attempt to add an entry for it, with the specified
868b00ab754SHans Petter Selasky  * IFF_ flags and description, and, if that succeeds, return a pointer to
869b00ab754SHans Petter Selasky  * the new entry, otherwise return NULL and set errbuf to an error message.
870b00ab754SHans Petter Selasky  */
871b00ab754SHans Petter Selasky pcap_if_t *
872b00ab754SHans Petter Selasky find_or_add_if(pcap_if_list_t *devlistp, const char *name,
873b00ab754SHans Petter Selasky     bpf_u_int32 if_flags, get_if_flags_func get_flags_func, char *errbuf)
874b00ab754SHans Petter Selasky {
875b00ab754SHans Petter Selasky 	bpf_u_int32 pcap_flags;
876b00ab754SHans Petter Selasky 
877b00ab754SHans Petter Selasky 	/*
878b00ab754SHans Petter Selasky 	 * Convert IFF_ flags to pcap flags.
879b00ab754SHans Petter Selasky 	 */
880b00ab754SHans Petter Selasky 	pcap_flags = 0;
881b00ab754SHans Petter Selasky #ifdef IFF_LOOPBACK
882b00ab754SHans Petter Selasky 	if (if_flags & IFF_LOOPBACK)
883b00ab754SHans Petter Selasky 		pcap_flags |= PCAP_IF_LOOPBACK;
884b00ab754SHans Petter Selasky #else
885b00ab754SHans Petter Selasky 	/*
886b00ab754SHans Petter Selasky 	 * We don't have IFF_LOOPBACK, so look at the device name to
887b00ab754SHans Petter Selasky 	 * see if it looks like a loopback device.
888b00ab754SHans Petter Selasky 	 */
889b00ab754SHans Petter Selasky 	if (name[0] == 'l' && name[1] == 'o' &&
890b00ab754SHans Petter Selasky 	    (isdigit((unsigned char)(name[2])) || name[2] == '\0')
891b00ab754SHans Petter Selasky 		pcap_flags |= PCAP_IF_LOOPBACK;
892b00ab754SHans Petter Selasky #endif
893b00ab754SHans Petter Selasky #ifdef IFF_UP
894b00ab754SHans Petter Selasky 	if (if_flags & IFF_UP)
895b00ab754SHans Petter Selasky 		pcap_flags |= PCAP_IF_UP;
896b00ab754SHans Petter Selasky #endif
897b00ab754SHans Petter Selasky #ifdef IFF_RUNNING
898b00ab754SHans Petter Selasky 	if (if_flags & IFF_RUNNING)
899b00ab754SHans Petter Selasky 		pcap_flags |= PCAP_IF_RUNNING;
900b00ab754SHans Petter Selasky #endif
901b00ab754SHans Petter Selasky 
902b00ab754SHans Petter Selasky 	/*
903b00ab754SHans Petter Selasky 	 * Attempt to find an entry for this device; if we don't find one,
904b00ab754SHans Petter Selasky 	 * attempt to add one.
905b00ab754SHans Petter Selasky 	 */
906b00ab754SHans Petter Selasky 	return (find_or_add_dev(devlistp, name, pcap_flags,
907b00ab754SHans Petter Selasky 	    get_flags_func, get_if_description(name), errbuf));
908b00ab754SHans Petter Selasky }
909b00ab754SHans Petter Selasky 
910b00ab754SHans Petter Selasky /*
911b00ab754SHans Petter Selasky  * Look for a given device in the specified list of devices.
912b00ab754SHans Petter Selasky  *
913b00ab754SHans Petter Selasky  * If we find it, then, if the specified address isn't null, add it to
914b00ab754SHans Petter Selasky  * the list of addresses for the device and return 0.
915b00ab754SHans Petter Selasky  *
916b00ab754SHans Petter Selasky  * If we don't find it, attempt to add an entry for it, with the specified
917b00ab754SHans Petter Selasky  * IFF_ flags and description, and, if that succeeds, add the specified
918b00ab754SHans Petter Selasky  * address to its list of addresses if that address is non-null, and
919b00ab754SHans Petter Selasky  * return 0, otherwise return -1 and set errbuf to an error message.
920b00ab754SHans Petter Selasky  *
921b00ab754SHans Petter Selasky  * (We can get called with a null address because we might get a list
922b00ab754SHans Petter Selasky  * of interface name/address combinations from the underlying OS, with
923b00ab754SHans Petter Selasky  * the address being absent in some cases, rather than a list of
924b00ab754SHans Petter Selasky  * interfaces with each interface having a list of addresses, so this
925b00ab754SHans Petter Selasky  * call may be the only call made to add to the list, and we want to
926b00ab754SHans Petter Selasky  * add interfaces even if they have no addresses.)
927b00ab754SHans Petter Selasky  */
928b00ab754SHans Petter Selasky int
929b00ab754SHans Petter Selasky add_addr_to_if(pcap_if_list_t *devlistp, const char *name,
930b00ab754SHans Petter Selasky     bpf_u_int32 if_flags, get_if_flags_func get_flags_func,
931b00ab754SHans Petter Selasky     struct sockaddr *addr, size_t addr_size,
932b00ab754SHans Petter Selasky     struct sockaddr *netmask, size_t netmask_size,
933b00ab754SHans Petter Selasky     struct sockaddr *broadaddr, size_t broadaddr_size,
934b00ab754SHans Petter Selasky     struct sockaddr *dstaddr, size_t dstaddr_size,
935b00ab754SHans Petter Selasky     char *errbuf)
936b00ab754SHans Petter Selasky {
937b00ab754SHans Petter Selasky 	pcap_if_t *curdev;
938b00ab754SHans Petter Selasky 
939b00ab754SHans Petter Selasky 	/*
940b00ab754SHans Petter Selasky 	 * Check whether the device exists and, if not, add it.
941b00ab754SHans Petter Selasky 	 */
942b00ab754SHans Petter Selasky 	curdev = find_or_add_if(devlistp, name, if_flags, get_flags_func,
943b00ab754SHans Petter Selasky 	    errbuf);
944b00ab754SHans Petter Selasky 	if (curdev == NULL) {
945b00ab754SHans Petter Selasky 		/*
946b00ab754SHans Petter Selasky 		 * Error - give up.
947b00ab754SHans Petter Selasky 		 */
948b00ab754SHans Petter Selasky 		return (-1);
949b00ab754SHans Petter Selasky 	}
950b00ab754SHans Petter Selasky 
951b00ab754SHans Petter Selasky 	if (addr == NULL) {
952b00ab754SHans Petter Selasky 		/*
953b00ab754SHans Petter Selasky 		 * There's no address to add; this entry just meant
954b00ab754SHans Petter Selasky 		 * "here's a new interface".
955b00ab754SHans Petter Selasky 		 */
956b00ab754SHans Petter Selasky 		return (0);
957b00ab754SHans Petter Selasky 	}
958b00ab754SHans Petter Selasky 
959b00ab754SHans Petter Selasky 	/*
960b00ab754SHans Petter Selasky 	 * "curdev" is an entry for this interface, and we have an
961b00ab754SHans Petter Selasky 	 * address for it; add an entry for that address to the
962b00ab754SHans Petter Selasky 	 * interface's list of addresses.
963b00ab754SHans Petter Selasky 	 */
964b00ab754SHans Petter Selasky 	return (add_addr_to_dev(curdev, addr, addr_size, netmask,
965b00ab754SHans Petter Selasky 	    netmask_size, broadaddr, broadaddr_size, dstaddr,
966b00ab754SHans Petter Selasky 	    dstaddr_size, errbuf));
967b00ab754SHans Petter Selasky }
968b00ab754SHans Petter Selasky #endif /* _WIN32 */
969b00ab754SHans Petter Selasky 
970b00ab754SHans Petter Selasky /*
971b00ab754SHans Petter Selasky  * Add an entry to the list of addresses for an interface.
972b00ab754SHans Petter Selasky  * "curdev" is the entry for that interface.
973b00ab754SHans Petter Selasky  */
974b00ab754SHans Petter Selasky int
975b00ab754SHans Petter Selasky add_addr_to_dev(pcap_if_t *curdev,
976b00ab754SHans Petter Selasky     struct sockaddr *addr, size_t addr_size,
977b00ab754SHans Petter Selasky     struct sockaddr *netmask, size_t netmask_size,
978b00ab754SHans Petter Selasky     struct sockaddr *broadaddr, size_t broadaddr_size,
979b00ab754SHans Petter Selasky     struct sockaddr *dstaddr, size_t dstaddr_size,
980b00ab754SHans Petter Selasky     char *errbuf)
981b00ab754SHans Petter Selasky {
982b00ab754SHans Petter Selasky 	pcap_addr_t *curaddr, *prevaddr, *nextaddr;
983b00ab754SHans Petter Selasky 
984b00ab754SHans Petter Selasky 	/*
985b00ab754SHans Petter Selasky 	 * Allocate the new entry and fill it in.
986b00ab754SHans Petter Selasky 	 */
987b00ab754SHans Petter Selasky 	curaddr = (pcap_addr_t *)malloc(sizeof(pcap_addr_t));
988b00ab754SHans Petter Selasky 	if (curaddr == NULL) {
989b00ab754SHans Petter Selasky 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
990b00ab754SHans Petter Selasky 		    errno, "malloc");
991b00ab754SHans Petter Selasky 		return (-1);
992b00ab754SHans Petter Selasky 	}
993b00ab754SHans Petter Selasky 
994b00ab754SHans Petter Selasky 	curaddr->next = NULL;
995b00ab754SHans Petter Selasky 	if (addr != NULL && addr_size != 0) {
996b00ab754SHans Petter Selasky 		curaddr->addr = (struct sockaddr *)dup_sockaddr(addr, addr_size);
997b00ab754SHans Petter Selasky 		if (curaddr->addr == NULL) {
998b00ab754SHans Petter Selasky 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
999b00ab754SHans Petter Selasky 			    errno, "malloc");
1000b00ab754SHans Petter Selasky 			free(curaddr);
1001b00ab754SHans Petter Selasky 			return (-1);
1002b00ab754SHans Petter Selasky 		}
1003b00ab754SHans Petter Selasky 	} else
1004b00ab754SHans Petter Selasky 		curaddr->addr = NULL;
1005b00ab754SHans Petter Selasky 
1006b00ab754SHans Petter Selasky 	if (netmask != NULL && netmask_size != 0) {
1007b00ab754SHans Petter Selasky 		curaddr->netmask = (struct sockaddr *)dup_sockaddr(netmask, netmask_size);
1008b00ab754SHans Petter Selasky 		if (curaddr->netmask == NULL) {
1009b00ab754SHans Petter Selasky 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1010b00ab754SHans Petter Selasky 			    errno, "malloc");
1011b00ab754SHans Petter Selasky 			if (curaddr->addr != NULL)
1012b00ab754SHans Petter Selasky 				free(curaddr->addr);
1013b00ab754SHans Petter Selasky 			free(curaddr);
1014b00ab754SHans Petter Selasky 			return (-1);
1015b00ab754SHans Petter Selasky 		}
1016b00ab754SHans Petter Selasky 	} else
1017b00ab754SHans Petter Selasky 		curaddr->netmask = NULL;
1018b00ab754SHans Petter Selasky 
1019b00ab754SHans Petter Selasky 	if (broadaddr != NULL && broadaddr_size != 0) {
1020b00ab754SHans Petter Selasky 		curaddr->broadaddr = (struct sockaddr *)dup_sockaddr(broadaddr, broadaddr_size);
1021b00ab754SHans Petter Selasky 		if (curaddr->broadaddr == NULL) {
1022b00ab754SHans Petter Selasky 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1023b00ab754SHans Petter Selasky 			    errno, "malloc");
1024b00ab754SHans Petter Selasky 			if (curaddr->netmask != NULL)
1025b00ab754SHans Petter Selasky 				free(curaddr->netmask);
1026b00ab754SHans Petter Selasky 			if (curaddr->addr != NULL)
1027b00ab754SHans Petter Selasky 				free(curaddr->addr);
1028b00ab754SHans Petter Selasky 			free(curaddr);
1029b00ab754SHans Petter Selasky 			return (-1);
1030b00ab754SHans Petter Selasky 		}
1031b00ab754SHans Petter Selasky 	} else
1032b00ab754SHans Petter Selasky 		curaddr->broadaddr = NULL;
1033b00ab754SHans Petter Selasky 
1034b00ab754SHans Petter Selasky 	if (dstaddr != NULL && dstaddr_size != 0) {
1035b00ab754SHans Petter Selasky 		curaddr->dstaddr = (struct sockaddr *)dup_sockaddr(dstaddr, dstaddr_size);
1036b00ab754SHans Petter Selasky 		if (curaddr->dstaddr == NULL) {
1037b00ab754SHans Petter Selasky 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1038b00ab754SHans Petter Selasky 			    errno, "malloc");
1039b00ab754SHans Petter Selasky 			if (curaddr->broadaddr != NULL)
1040b00ab754SHans Petter Selasky 				free(curaddr->broadaddr);
1041b00ab754SHans Petter Selasky 			if (curaddr->netmask != NULL)
1042b00ab754SHans Petter Selasky 				free(curaddr->netmask);
1043b00ab754SHans Petter Selasky 			if (curaddr->addr != NULL)
1044b00ab754SHans Petter Selasky 				free(curaddr->addr);
1045b00ab754SHans Petter Selasky 			free(curaddr);
1046b00ab754SHans Petter Selasky 			return (-1);
1047b00ab754SHans Petter Selasky 		}
1048b00ab754SHans Petter Selasky 	} else
1049b00ab754SHans Petter Selasky 		curaddr->dstaddr = NULL;
1050b00ab754SHans Petter Selasky 
1051b00ab754SHans Petter Selasky 	/*
1052b00ab754SHans Petter Selasky 	 * Find the end of the list of addresses.
1053b00ab754SHans Petter Selasky 	 */
1054b00ab754SHans Petter Selasky 	for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
1055b00ab754SHans Petter Selasky 		nextaddr = prevaddr->next;
1056b00ab754SHans Petter Selasky 		if (nextaddr == NULL) {
1057b00ab754SHans Petter Selasky 			/*
1058b00ab754SHans Petter Selasky 			 * This is the end of the list.
1059b00ab754SHans Petter Selasky 			 */
1060b00ab754SHans Petter Selasky 			break;
1061b00ab754SHans Petter Selasky 		}
1062b00ab754SHans Petter Selasky 	}
1063b00ab754SHans Petter Selasky 
1064b00ab754SHans Petter Selasky 	if (prevaddr == NULL) {
1065b00ab754SHans Petter Selasky 		/*
1066b00ab754SHans Petter Selasky 		 * The list was empty; this is the first member.
1067b00ab754SHans Petter Selasky 		 */
1068b00ab754SHans Petter Selasky 		curdev->addresses = curaddr;
1069b00ab754SHans Petter Selasky 	} else {
1070b00ab754SHans Petter Selasky 		/*
1071b00ab754SHans Petter Selasky 		 * "prevaddr" is the last member of the list; append
1072b00ab754SHans Petter Selasky 		 * this member to it.
1073b00ab754SHans Petter Selasky 		 */
1074b00ab754SHans Petter Selasky 		prevaddr->next = curaddr;
1075b00ab754SHans Petter Selasky 	}
1076b00ab754SHans Petter Selasky 
1077b00ab754SHans Petter Selasky 	return (0);
1078b00ab754SHans Petter Selasky }
1079b00ab754SHans Petter Selasky 
1080b00ab754SHans Petter Selasky /*
1081b00ab754SHans Petter Selasky  * Look for a given device in the specified list of devices.
1082b00ab754SHans Petter Selasky  *
1083b00ab754SHans Petter Selasky  * If we find it, return 0 and set *curdev_ret to point to it.
1084b00ab754SHans Petter Selasky  *
1085b00ab754SHans Petter Selasky  * If we don't find it, attempt to add an entry for it, with the specified
1086b00ab754SHans Petter Selasky  * flags and description, and, if that succeeds, return 0, otherwise
1087b00ab754SHans Petter Selasky  * return -1 and set errbuf to an error message.
1088b00ab754SHans Petter Selasky  */
1089b00ab754SHans Petter Selasky pcap_if_t *
1090b00ab754SHans Petter Selasky find_or_add_dev(pcap_if_list_t *devlistp, const char *name, bpf_u_int32 flags,
1091b00ab754SHans Petter Selasky     get_if_flags_func get_flags_func, const char *description, char *errbuf)
1092b00ab754SHans Petter Selasky {
1093b00ab754SHans Petter Selasky 	pcap_if_t *curdev;
1094b00ab754SHans Petter Selasky 
1095b00ab754SHans Petter Selasky 	/*
1096b00ab754SHans Petter Selasky 	 * Is there already an entry in the list for this device?
1097b00ab754SHans Petter Selasky 	 */
1098b00ab754SHans Petter Selasky 	curdev = find_dev(devlistp, name);
1099b00ab754SHans Petter Selasky 	if (curdev != NULL) {
1100b00ab754SHans Petter Selasky 		/*
1101b00ab754SHans Petter Selasky 		 * Yes, return it.
1102b00ab754SHans Petter Selasky 		 */
1103b00ab754SHans Petter Selasky 		return (curdev);
1104b00ab754SHans Petter Selasky 	}
1105b00ab754SHans Petter Selasky 
1106b00ab754SHans Petter Selasky 	/*
1107b00ab754SHans Petter Selasky 	 * No, we didn't find it.
1108b00ab754SHans Petter Selasky 	 */
1109b00ab754SHans Petter Selasky 
1110b00ab754SHans Petter Selasky 	/*
1111b00ab754SHans Petter Selasky 	 * Try to get additional flags for the device.
1112b00ab754SHans Petter Selasky 	 */
1113b00ab754SHans Petter Selasky 	if ((*get_flags_func)(name, &flags, errbuf) == -1) {
1114b00ab754SHans Petter Selasky 		/*
1115b00ab754SHans Petter Selasky 		 * Failed.
1116b00ab754SHans Petter Selasky 		 */
1117b00ab754SHans Petter Selasky 		return (NULL);
1118b00ab754SHans Petter Selasky 	}
1119b00ab754SHans Petter Selasky 
1120b00ab754SHans Petter Selasky 	/*
1121b00ab754SHans Petter Selasky 	 * Now, try to add it to the list of devices.
1122b00ab754SHans Petter Selasky 	 */
1123b00ab754SHans Petter Selasky 	return (add_dev(devlistp, name, flags, description, errbuf));
1124b00ab754SHans Petter Selasky }
1125b00ab754SHans Petter Selasky 
1126b00ab754SHans Petter Selasky /*
1127b00ab754SHans Petter Selasky  * Look for a given device in the specified list of devices, and return
1128b00ab754SHans Petter Selasky  * the entry for it if we find it or NULL if we don't.
1129b00ab754SHans Petter Selasky  */
1130b00ab754SHans Petter Selasky pcap_if_t *
1131b00ab754SHans Petter Selasky find_dev(pcap_if_list_t *devlistp, const char *name)
1132b00ab754SHans Petter Selasky {
1133b00ab754SHans Petter Selasky 	pcap_if_t *curdev;
1134b00ab754SHans Petter Selasky 
1135b00ab754SHans Petter Selasky 	/*
1136b00ab754SHans Petter Selasky 	 * Is there an entry in the list for this device?
1137b00ab754SHans Petter Selasky 	 */
1138b00ab754SHans Petter Selasky 	for (curdev = devlistp->beginning; curdev != NULL;
1139b00ab754SHans Petter Selasky 	    curdev = curdev->next) {
1140b00ab754SHans Petter Selasky 		if (strcmp(name, curdev->name) == 0) {
1141b00ab754SHans Petter Selasky 			/*
1142b00ab754SHans Petter Selasky 			 * We found it, so, yes, there is.  No need to
1143b00ab754SHans Petter Selasky 			 * add it.  Provide the entry we found to our
1144b00ab754SHans Petter Selasky 			 * caller.
1145b00ab754SHans Petter Selasky 			 */
1146b00ab754SHans Petter Selasky 			return (curdev);
1147b00ab754SHans Petter Selasky 		}
1148b00ab754SHans Petter Selasky 	}
1149b00ab754SHans Petter Selasky 
1150b00ab754SHans Petter Selasky 	/*
1151b00ab754SHans Petter Selasky 	 * No.
1152b00ab754SHans Petter Selasky 	 */
1153b00ab754SHans Petter Selasky 	return (NULL);
1154b00ab754SHans Petter Selasky }
1155b00ab754SHans Petter Selasky 
1156b00ab754SHans Petter Selasky /*
1157b00ab754SHans Petter Selasky  * Attempt to add an entry for a device, with the specified flags
1158b00ab754SHans Petter Selasky  * and description, and, if that succeeds, return 0 and return a pointer
1159b00ab754SHans Petter Selasky  * to the new entry, otherwise return NULL and set errbuf to an error
1160b00ab754SHans Petter Selasky  * message.
1161b00ab754SHans Petter Selasky  *
1162b00ab754SHans Petter Selasky  * If we weren't given a description, try to get one.
1163b00ab754SHans Petter Selasky  */
1164b00ab754SHans Petter Selasky pcap_if_t *
1165b00ab754SHans Petter Selasky add_dev(pcap_if_list_t *devlistp, const char *name, bpf_u_int32 flags,
1166b00ab754SHans Petter Selasky     const char *description, char *errbuf)
1167b00ab754SHans Petter Selasky {
1168b00ab754SHans Petter Selasky 	pcap_if_t *curdev, *prevdev, *nextdev;
1169b00ab754SHans Petter Selasky 	u_int this_figure_of_merit, nextdev_figure_of_merit;
1170b00ab754SHans Petter Selasky 
1171b00ab754SHans Petter Selasky 	curdev = malloc(sizeof(pcap_if_t));
1172b00ab754SHans Petter Selasky 	if (curdev == NULL) {
1173b00ab754SHans Petter Selasky 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1174b00ab754SHans Petter Selasky 		    errno, "malloc");
1175b00ab754SHans Petter Selasky 		return (NULL);
1176b00ab754SHans Petter Selasky 	}
1177b00ab754SHans Petter Selasky 
1178b00ab754SHans Petter Selasky 	/*
1179b00ab754SHans Petter Selasky 	 * Fill in the entry.
1180b00ab754SHans Petter Selasky 	 */
1181b00ab754SHans Petter Selasky 	curdev->next = NULL;
1182b00ab754SHans Petter Selasky 	curdev->name = strdup(name);
1183b00ab754SHans Petter Selasky 	if (curdev->name == NULL) {
1184b00ab754SHans Petter Selasky 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1185b00ab754SHans Petter Selasky 		    errno, "malloc");
1186b00ab754SHans Petter Selasky 		free(curdev);
1187b00ab754SHans Petter Selasky 		return (NULL);
1188b00ab754SHans Petter Selasky 	}
1189b00ab754SHans Petter Selasky 	if (description == NULL) {
1190b00ab754SHans Petter Selasky 		/*
1191b00ab754SHans Petter Selasky 		 * We weren't handed a description for the interface.
1192b00ab754SHans Petter Selasky 		 */
1193b00ab754SHans Petter Selasky 		curdev->description = NULL;
1194b00ab754SHans Petter Selasky 	} else {
1195b00ab754SHans Petter Selasky 		/*
1196b00ab754SHans Petter Selasky 		 * We were handed a description; make a copy.
1197b00ab754SHans Petter Selasky 		 */
1198b00ab754SHans Petter Selasky 		curdev->description = strdup(description);
1199b00ab754SHans Petter Selasky 		if (curdev->description == NULL) {
1200b00ab754SHans Petter Selasky 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1201b00ab754SHans Petter Selasky 			    errno, "malloc");
1202b00ab754SHans Petter Selasky 			free(curdev->name);
1203b00ab754SHans Petter Selasky 			free(curdev);
1204b00ab754SHans Petter Selasky 			return (NULL);
1205b00ab754SHans Petter Selasky 		}
1206b00ab754SHans Petter Selasky 	}
1207b00ab754SHans Petter Selasky 	curdev->addresses = NULL;	/* list starts out as empty */
1208b00ab754SHans Petter Selasky 	curdev->flags = flags;
1209b00ab754SHans Petter Selasky 
1210b00ab754SHans Petter Selasky 	/*
1211b00ab754SHans Petter Selasky 	 * Add it to the list, in the appropriate location.
1212b00ab754SHans Petter Selasky 	 * First, get the "figure of merit" for this interface.
1213b00ab754SHans Petter Selasky 	 */
1214b00ab754SHans Petter Selasky 	this_figure_of_merit = get_figure_of_merit(curdev);
1215b00ab754SHans Petter Selasky 
1216b00ab754SHans Petter Selasky 	/*
1217b00ab754SHans Petter Selasky 	 * Now look for the last interface with an figure of merit
1218b00ab754SHans Petter Selasky 	 * less than or equal to the new interface's figure of merit.
1219b00ab754SHans Petter Selasky 	 *
1220b00ab754SHans Petter Selasky 	 * We start with "prevdev" being NULL, meaning we're before
1221b00ab754SHans Petter Selasky 	 * the first element in the list.
1222b00ab754SHans Petter Selasky 	 */
1223b00ab754SHans Petter Selasky 	prevdev = NULL;
1224b00ab754SHans Petter Selasky 	for (;;) {
1225b00ab754SHans Petter Selasky 		/*
1226b00ab754SHans Petter Selasky 		 * Get the interface after this one.
1227b00ab754SHans Petter Selasky 		 */
1228b00ab754SHans Petter Selasky 		if (prevdev == NULL) {
1229b00ab754SHans Petter Selasky 			/*
1230b00ab754SHans Petter Selasky 			 * The next element is the first element.
1231b00ab754SHans Petter Selasky 			 */
1232b00ab754SHans Petter Selasky 			nextdev = devlistp->beginning;
1233b00ab754SHans Petter Selasky 		} else
1234b00ab754SHans Petter Selasky 			nextdev = prevdev->next;
1235b00ab754SHans Petter Selasky 
1236b00ab754SHans Petter Selasky 		/*
1237b00ab754SHans Petter Selasky 		 * Are we at the end of the list?
1238b00ab754SHans Petter Selasky 		 */
1239b00ab754SHans Petter Selasky 		if (nextdev == NULL) {
1240b00ab754SHans Petter Selasky 			/*
1241b00ab754SHans Petter Selasky 			 * Yes - we have to put the new entry after "prevdev".
1242b00ab754SHans Petter Selasky 			 */
1243b00ab754SHans Petter Selasky 			break;
1244b00ab754SHans Petter Selasky 		}
1245b00ab754SHans Petter Selasky 
1246b00ab754SHans Petter Selasky 		/*
1247b00ab754SHans Petter Selasky 		 * Is the new interface's figure of merit less
1248b00ab754SHans Petter Selasky 		 * than the next interface's figure of merit,
1249b00ab754SHans Petter Selasky 		 * meaning that the new interface is better
1250b00ab754SHans Petter Selasky 		 * than the next interface?
1251b00ab754SHans Petter Selasky 		 */
1252b00ab754SHans Petter Selasky 		nextdev_figure_of_merit = get_figure_of_merit(nextdev);
1253b00ab754SHans Petter Selasky 		if (this_figure_of_merit < nextdev_figure_of_merit) {
1254b00ab754SHans Petter Selasky 			/*
1255b00ab754SHans Petter Selasky 			 * Yes - we should put the new entry
1256b00ab754SHans Petter Selasky 			 * before "nextdev", i.e. after "prevdev".
1257b00ab754SHans Petter Selasky 			 */
1258b00ab754SHans Petter Selasky 			break;
1259b00ab754SHans Petter Selasky 		}
1260b00ab754SHans Petter Selasky 
1261b00ab754SHans Petter Selasky 		prevdev = nextdev;
1262b00ab754SHans Petter Selasky 	}
1263b00ab754SHans Petter Selasky 
1264b00ab754SHans Petter Selasky 	/*
1265b00ab754SHans Petter Selasky 	 * Insert before "nextdev".
1266b00ab754SHans Petter Selasky 	 */
1267b00ab754SHans Petter Selasky 	curdev->next = nextdev;
1268b00ab754SHans Petter Selasky 
1269b00ab754SHans Petter Selasky 	/*
1270b00ab754SHans Petter Selasky 	 * Insert after "prevdev" - unless "prevdev" is null,
1271b00ab754SHans Petter Selasky 	 * in which case this is the first interface.
1272b00ab754SHans Petter Selasky 	 */
1273b00ab754SHans Petter Selasky 	if (prevdev == NULL) {
1274b00ab754SHans Petter Selasky 		/*
1275b00ab754SHans Petter Selasky 		 * This is the first interface.  Make it
1276b00ab754SHans Petter Selasky 		 * the first element in the list of devices.
1277b00ab754SHans Petter Selasky 		 */
1278b00ab754SHans Petter Selasky 		devlistp->beginning = curdev;
1279b00ab754SHans Petter Selasky 	} else
1280b00ab754SHans Petter Selasky 		prevdev->next = curdev;
1281b00ab754SHans Petter Selasky 	return (curdev);
1282b00ab754SHans Petter Selasky }
1283b00ab754SHans Petter Selasky 
1284b00ab754SHans Petter Selasky /*
1285b00ab754SHans Petter Selasky  * Free a list of interfaces.
1286b00ab754SHans Petter Selasky  */
1287b00ab754SHans Petter Selasky void
1288b00ab754SHans Petter Selasky pcap_freealldevs(pcap_if_t *alldevs)
1289b00ab754SHans Petter Selasky {
1290b00ab754SHans Petter Selasky 	pcap_if_t *curdev, *nextdev;
1291b00ab754SHans Petter Selasky 	pcap_addr_t *curaddr, *nextaddr;
1292b00ab754SHans Petter Selasky 
1293b00ab754SHans Petter Selasky 	for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
1294b00ab754SHans Petter Selasky 		nextdev = curdev->next;
1295b00ab754SHans Petter Selasky 
1296b00ab754SHans Petter Selasky 		/*
1297b00ab754SHans Petter Selasky 		 * Free all addresses.
1298b00ab754SHans Petter Selasky 		 */
1299b00ab754SHans Petter Selasky 		for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
1300b00ab754SHans Petter Selasky 			nextaddr = curaddr->next;
1301b00ab754SHans Petter Selasky 			if (curaddr->addr)
1302b00ab754SHans Petter Selasky 				free(curaddr->addr);
1303b00ab754SHans Petter Selasky 			if (curaddr->netmask)
1304b00ab754SHans Petter Selasky 				free(curaddr->netmask);
1305b00ab754SHans Petter Selasky 			if (curaddr->broadaddr)
1306b00ab754SHans Petter Selasky 				free(curaddr->broadaddr);
1307b00ab754SHans Petter Selasky 			if (curaddr->dstaddr)
1308b00ab754SHans Petter Selasky 				free(curaddr->dstaddr);
1309b00ab754SHans Petter Selasky 			free(curaddr);
1310b00ab754SHans Petter Selasky 		}
1311b00ab754SHans Petter Selasky 
1312b00ab754SHans Petter Selasky 		/*
1313b00ab754SHans Petter Selasky 		 * Free the name string.
1314b00ab754SHans Petter Selasky 		 */
1315b00ab754SHans Petter Selasky 		free(curdev->name);
1316b00ab754SHans Petter Selasky 
1317b00ab754SHans Petter Selasky 		/*
1318b00ab754SHans Petter Selasky 		 * Free the description string, if any.
1319b00ab754SHans Petter Selasky 		 */
1320b00ab754SHans Petter Selasky 		if (curdev->description != NULL)
1321b00ab754SHans Petter Selasky 			free(curdev->description);
1322b00ab754SHans Petter Selasky 
1323b00ab754SHans Petter Selasky 		/*
1324b00ab754SHans Petter Selasky 		 * Free the interface.
1325b00ab754SHans Petter Selasky 		 */
1326b00ab754SHans Petter Selasky 		free(curdev);
1327b00ab754SHans Petter Selasky 	}
1328b00ab754SHans Petter Selasky }
1329b00ab754SHans Petter Selasky 
1330b00ab754SHans Petter Selasky /*
1331b00ab754SHans Petter Selasky  * pcap-npf.c has its own pcap_lookupdev(), for compatibility reasons, as
1332b00ab754SHans Petter Selasky  * it actually returns the names of all interfaces, with a NUL separator
1333b00ab754SHans Petter Selasky  * between them; some callers may depend on that.
1334b00ab754SHans Petter Selasky  *
1335b00ab754SHans Petter Selasky  * MS-DOS has its own pcap_lookupdev(), but that might be useful only
1336b00ab754SHans Petter Selasky  * as an optimization.
1337b00ab754SHans Petter Selasky  *
1338b00ab754SHans Petter Selasky  * In all other cases, we just use pcap_findalldevs() to get a list of
1339b00ab754SHans Petter Selasky  * devices, and pick from that list.
1340b00ab754SHans Petter Selasky  */
1341b00ab754SHans Petter Selasky #if !defined(HAVE_PACKET32) && !defined(MSDOS)
1342b00ab754SHans Petter Selasky /*
1343b00ab754SHans Petter Selasky  * Return the name of a network interface attached to the system, or NULL
1344b00ab754SHans Petter Selasky  * if none can be found.  The interface must be configured up; the
1345b00ab754SHans Petter Selasky  * lowest unit number is preferred; loopback is ignored.
1346b00ab754SHans Petter Selasky  */
1347b00ab754SHans Petter Selasky char *
1348b00ab754SHans Petter Selasky pcap_lookupdev(char *errbuf)
1349b00ab754SHans Petter Selasky {
1350b00ab754SHans Petter Selasky 	pcap_if_t *alldevs;
1351b00ab754SHans Petter Selasky #ifdef _WIN32
1352b00ab754SHans Petter Selasky   /*
1353b00ab754SHans Petter Selasky    * Windows - use the same size as the old WinPcap 3.1 code.
1354b00ab754SHans Petter Selasky    * XXX - this is probably bigger than it needs to be.
1355b00ab754SHans Petter Selasky    */
1356b00ab754SHans Petter Selasky   #define IF_NAMESIZE 8192
1357b00ab754SHans Petter Selasky #else
1358b00ab754SHans Petter Selasky   /*
1359b00ab754SHans Petter Selasky    * UN*X - use the system's interface name size.
1360b00ab754SHans Petter Selasky    * XXX - that might not be large enough for capture devices
1361b00ab754SHans Petter Selasky    * that aren't regular network interfaces.
1362b00ab754SHans Petter Selasky    */
1363b00ab754SHans Petter Selasky   /* for old BSD systems, including bsdi3 */
1364b00ab754SHans Petter Selasky   #ifndef IF_NAMESIZE
1365b00ab754SHans Petter Selasky   #define IF_NAMESIZE IFNAMSIZ
1366b00ab754SHans Petter Selasky   #endif
1367b00ab754SHans Petter Selasky #endif
1368b00ab754SHans Petter Selasky 	static char device[IF_NAMESIZE + 1];
1369b00ab754SHans Petter Selasky 	char *ret;
1370b00ab754SHans Petter Selasky 
1371b00ab754SHans Petter Selasky 	if (pcap_findalldevs(&alldevs, errbuf) == -1)
1372b00ab754SHans Petter Selasky 		return (NULL);
1373b00ab754SHans Petter Selasky 
1374b00ab754SHans Petter Selasky 	if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
1375b00ab754SHans Petter Selasky 		/*
1376b00ab754SHans Petter Selasky 		 * There are no devices on the list, or the first device
1377b00ab754SHans Petter Selasky 		 * on the list is a loopback device, which means there
1378b00ab754SHans Petter Selasky 		 * are no non-loopback devices on the list.  This means
1379b00ab754SHans Petter Selasky 		 * we can't return any device.
1380b00ab754SHans Petter Selasky 		 *
1381b00ab754SHans Petter Selasky 		 * XXX - why not return a loopback device?  If we can't
1382b00ab754SHans Petter Selasky 		 * capture on it, it won't be on the list, and if it's
1383b00ab754SHans Petter Selasky 		 * on the list, there aren't any non-loopback devices,
1384b00ab754SHans Petter Selasky 		 * so why not just supply it as the default device?
1385b00ab754SHans Petter Selasky 		 */
1386*57e22627SCy Schubert 		(void)pcap_strlcpy(errbuf, "no suitable device found",
1387b00ab754SHans Petter Selasky 		    PCAP_ERRBUF_SIZE);
1388b00ab754SHans Petter Selasky 		ret = NULL;
1389b00ab754SHans Petter Selasky 	} else {
1390b00ab754SHans Petter Selasky 		/*
1391b00ab754SHans Petter Selasky 		 * Return the name of the first device on the list.
1392b00ab754SHans Petter Selasky 		 */
1393*57e22627SCy Schubert 		(void)pcap_strlcpy(device, alldevs->name, sizeof(device));
1394b00ab754SHans Petter Selasky 		ret = device;
1395b00ab754SHans Petter Selasky 	}
1396b00ab754SHans Petter Selasky 
1397b00ab754SHans Petter Selasky 	pcap_freealldevs(alldevs);
1398b00ab754SHans Petter Selasky 	return (ret);
1399b00ab754SHans Petter Selasky }
1400b00ab754SHans Petter Selasky #endif /* !defined(HAVE_PACKET32) && !defined(MSDOS) */
1401b00ab754SHans Petter Selasky 
1402b00ab754SHans Petter Selasky #if !defined(_WIN32) && !defined(MSDOS)
1403b00ab754SHans Petter Selasky /*
1404b00ab754SHans Petter Selasky  * We don't just fetch the entire list of devices, search for the
1405b00ab754SHans Petter Selasky  * particular device, and use its first IPv4 address, as that's too
1406b00ab754SHans Petter Selasky  * much work to get just one device's netmask.
1407b00ab754SHans Petter Selasky  *
1408b00ab754SHans Petter Selasky  * If we had an API to get attributes for a given device, we could
1409b00ab754SHans Petter Selasky  * use that.
1410b00ab754SHans Petter Selasky  */
1411b00ab754SHans Petter Selasky int
1412b00ab754SHans Petter Selasky pcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp,
1413b00ab754SHans Petter Selasky     char *errbuf)
1414b00ab754SHans Petter Selasky {
1415b00ab754SHans Petter Selasky 	register int fd;
1416b00ab754SHans Petter Selasky 	register struct sockaddr_in *sin4;
1417b00ab754SHans Petter Selasky 	struct ifreq ifr;
1418b00ab754SHans Petter Selasky 
1419b00ab754SHans Petter Selasky 	/*
1420b00ab754SHans Petter Selasky 	 * The pseudo-device "any" listens on all interfaces and therefore
1421b00ab754SHans Petter Selasky 	 * has the network address and -mask "0.0.0.0" therefore catching
1422b00ab754SHans Petter Selasky 	 * all traffic. Using NULL for the interface is the same as "any".
1423b00ab754SHans Petter Selasky 	 */
1424b00ab754SHans Petter Selasky 	if (!device || strcmp(device, "any") == 0
1425b00ab754SHans Petter Selasky #ifdef HAVE_DAG_API
1426b00ab754SHans Petter Selasky 	    || strstr(device, "dag") != NULL
1427b00ab754SHans Petter Selasky #endif
1428b00ab754SHans Petter Selasky #ifdef HAVE_SEPTEL_API
1429b00ab754SHans Petter Selasky 	    || strstr(device, "septel") != NULL
1430b00ab754SHans Petter Selasky #endif
1431b00ab754SHans Petter Selasky #ifdef PCAP_SUPPORT_BT
1432b00ab754SHans Petter Selasky 	    || strstr(device, "bluetooth") != NULL
1433b00ab754SHans Petter Selasky #endif
1434b00ab754SHans Petter Selasky #ifdef PCAP_SUPPORT_USB
1435b00ab754SHans Petter Selasky 	    || strstr(device, "usbmon") != NULL
1436b00ab754SHans Petter Selasky #endif
1437b00ab754SHans Petter Selasky #ifdef HAVE_SNF_API
1438b00ab754SHans Petter Selasky 	    || strstr(device, "snf") != NULL
1439b00ab754SHans Petter Selasky #endif
1440b00ab754SHans Petter Selasky #ifdef PCAP_SUPPORT_NETMAP
1441b00ab754SHans Petter Selasky 	    || strncmp(device, "netmap:", 7) == 0
1442b00ab754SHans Petter Selasky 	    || strncmp(device, "vale", 4) == 0
1443b00ab754SHans Petter Selasky #endif
1444b00ab754SHans Petter Selasky 	    ) {
1445b00ab754SHans Petter Selasky 		*netp = *maskp = 0;
1446b00ab754SHans Petter Selasky 		return 0;
1447b00ab754SHans Petter Selasky 	}
1448b00ab754SHans Petter Selasky 
1449b00ab754SHans Petter Selasky 	fd = socket(AF_INET, SOCK_DGRAM, 0);
1450b00ab754SHans Petter Selasky 	if (fd < 0) {
1451b00ab754SHans Petter Selasky 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1452b00ab754SHans Petter Selasky 		    errno, "socket");
1453b00ab754SHans Petter Selasky 		return (-1);
1454b00ab754SHans Petter Selasky 	}
1455b00ab754SHans Petter Selasky 	memset(&ifr, 0, sizeof(ifr));
1456b00ab754SHans Petter Selasky #ifdef linux
1457b00ab754SHans Petter Selasky 	/* XXX Work around Linux kernel bug */
1458b00ab754SHans Petter Selasky 	ifr.ifr_addr.sa_family = AF_INET;
1459b00ab754SHans Petter Selasky #endif
1460*57e22627SCy Schubert 	(void)pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
1461b00ab754SHans Petter Selasky 	if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
1462b00ab754SHans Petter Selasky 		if (errno == EADDRNOTAVAIL) {
1463b00ab754SHans Petter Selasky 			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
1464b00ab754SHans Petter Selasky 			    "%s: no IPv4 address assigned", device);
1465b00ab754SHans Petter Selasky 		} else {
1466b00ab754SHans Petter Selasky 			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1467b00ab754SHans Petter Selasky 			    errno, "SIOCGIFADDR: %s", device);
1468b00ab754SHans Petter Selasky 		}
1469b00ab754SHans Petter Selasky 		(void)close(fd);
1470b00ab754SHans Petter Selasky 		return (-1);
1471b00ab754SHans Petter Selasky 	}
1472b00ab754SHans Petter Selasky 	sin4 = (struct sockaddr_in *)&ifr.ifr_addr;
1473b00ab754SHans Petter Selasky 	*netp = sin4->sin_addr.s_addr;
1474b00ab754SHans Petter Selasky 	memset(&ifr, 0, sizeof(ifr));
1475b00ab754SHans Petter Selasky #ifdef linux
1476b00ab754SHans Petter Selasky 	/* XXX Work around Linux kernel bug */
1477b00ab754SHans Petter Selasky 	ifr.ifr_addr.sa_family = AF_INET;
1478b00ab754SHans Petter Selasky #endif
1479*57e22627SCy Schubert 	(void)pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
1480b00ab754SHans Petter Selasky 	if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
1481b00ab754SHans Petter Selasky 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1482b00ab754SHans Petter Selasky 		    errno, "SIOCGIFNETMASK: %s", device);
1483b00ab754SHans Petter Selasky 		(void)close(fd);
1484b00ab754SHans Petter Selasky 		return (-1);
1485b00ab754SHans Petter Selasky 	}
1486b00ab754SHans Petter Selasky 	(void)close(fd);
1487b00ab754SHans Petter Selasky 	*maskp = sin4->sin_addr.s_addr;
1488b00ab754SHans Petter Selasky 	if (*maskp == 0) {
1489b00ab754SHans Petter Selasky 		if (IN_CLASSA(*netp))
1490b00ab754SHans Petter Selasky 			*maskp = IN_CLASSA_NET;
1491b00ab754SHans Petter Selasky 		else if (IN_CLASSB(*netp))
1492b00ab754SHans Petter Selasky 			*maskp = IN_CLASSB_NET;
1493b00ab754SHans Petter Selasky 		else if (IN_CLASSC(*netp))
1494b00ab754SHans Petter Selasky 			*maskp = IN_CLASSC_NET;
1495b00ab754SHans Petter Selasky 		else {
1496b00ab754SHans Petter Selasky 			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
1497b00ab754SHans Petter Selasky 			    "inet class for 0x%x unknown", *netp);
1498b00ab754SHans Petter Selasky 			return (-1);
1499b00ab754SHans Petter Selasky 		}
1500b00ab754SHans Petter Selasky 	}
1501b00ab754SHans Petter Selasky 	*netp &= *maskp;
1502b00ab754SHans Petter Selasky 	return (0);
1503b00ab754SHans Petter Selasky }
1504b00ab754SHans Petter Selasky #endif /* !defined(_WIN32) && !defined(MSDOS) */
1505b00ab754SHans Petter Selasky 
1506b00ab754SHans Petter Selasky #ifdef ENABLE_REMOTE
1507b00ab754SHans Petter Selasky #include "pcap-rpcap.h"
1508b00ab754SHans Petter Selasky 
1509b00ab754SHans Petter Selasky /*
1510b00ab754SHans Petter Selasky  * Extract a substring from a string.
1511b00ab754SHans Petter Selasky  */
1512b00ab754SHans Petter Selasky static char *
1513b00ab754SHans Petter Selasky get_substring(const char *p, size_t len, char *ebuf)
1514b00ab754SHans Petter Selasky {
1515b00ab754SHans Petter Selasky 	char *token;
1516b00ab754SHans Petter Selasky 
1517b00ab754SHans Petter Selasky 	token = malloc(len + 1);
1518b00ab754SHans Petter Selasky 	if (token == NULL) {
1519b00ab754SHans Petter Selasky 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
1520b00ab754SHans Petter Selasky 		    errno, "malloc");
1521b00ab754SHans Petter Selasky 		return (NULL);
1522b00ab754SHans Petter Selasky 	}
1523b00ab754SHans Petter Selasky 	memcpy(token, p, len);
1524b00ab754SHans Petter Selasky 	token[len] = '\0';
1525b00ab754SHans Petter Selasky 	return (token);
1526b00ab754SHans Petter Selasky }
1527b00ab754SHans Petter Selasky 
1528b00ab754SHans Petter Selasky /*
1529b00ab754SHans Petter Selasky  * Parse a capture source that might be a URL.
1530b00ab754SHans Petter Selasky  *
1531b00ab754SHans Petter Selasky  * If the source is not a URL, *schemep, *userinfop, *hostp, and *portp
1532b00ab754SHans Petter Selasky  * are set to NULL, *pathp is set to point to the source, and 0 is
1533b00ab754SHans Petter Selasky  * returned.
1534b00ab754SHans Petter Selasky  *
1535b00ab754SHans Petter Selasky  * If source is a URL, and the URL refers to a local device (a special
1536b00ab754SHans Petter Selasky  * case of rpcap:), *schemep, *userinfop, *hostp, and *portp are set
1537b00ab754SHans Petter Selasky  * to NULL, *pathp is set to point to the device name, and 0 is returned.
1538b00ab754SHans Petter Selasky  *
1539b00ab754SHans Petter Selasky  * If source is a URL, and it's not a special case that refers to a local
1540b00ab754SHans Petter Selasky  * device, and the parse succeeds:
1541b00ab754SHans Petter Selasky  *
1542b00ab754SHans Petter Selasky  *    *schemep is set to point to an allocated string containing the scheme;
1543b00ab754SHans Petter Selasky  *
1544b00ab754SHans Petter Selasky  *    if user information is present in the URL, *userinfop is set to point
1545b00ab754SHans Petter Selasky  *    to an allocated string containing the user information, otherwise
1546b00ab754SHans Petter Selasky  *    it's set to NULL;
1547b00ab754SHans Petter Selasky  *
1548b00ab754SHans Petter Selasky  *    if host information is present in the URL, *hostp is set to point
1549b00ab754SHans Petter Selasky  *    to an allocated string containing the host information, otherwise
1550b00ab754SHans Petter Selasky  *    it's set to NULL;
1551b00ab754SHans Petter Selasky  *
1552b00ab754SHans Petter Selasky  *    if a port number is present in the URL, *portp is set to point
1553b00ab754SHans Petter Selasky  *    to an allocated string containing the port number, otherwise
1554b00ab754SHans Petter Selasky  *    it's set to NULL;
1555b00ab754SHans Petter Selasky  *
1556b00ab754SHans Petter Selasky  *    *pathp is set to point to an allocated string containing the
1557b00ab754SHans Petter Selasky  *    path;
1558b00ab754SHans Petter Selasky  *
1559b00ab754SHans Petter Selasky  * and 0 is returned.
1560b00ab754SHans Petter Selasky  *
1561b00ab754SHans Petter Selasky  * If the parse fails, ebuf is set to an error string, and -1 is returned.
1562b00ab754SHans Petter Selasky  */
1563b00ab754SHans Petter Selasky static int
1564b00ab754SHans Petter Selasky pcap_parse_source(const char *source, char **schemep, char **userinfop,
1565b00ab754SHans Petter Selasky     char **hostp, char **portp, char **pathp, char *ebuf)
1566b00ab754SHans Petter Selasky {
1567b00ab754SHans Petter Selasky 	char *colonp;
1568b00ab754SHans Petter Selasky 	size_t scheme_len;
1569b00ab754SHans Petter Selasky 	char *scheme;
1570b00ab754SHans Petter Selasky 	const char *endp;
1571b00ab754SHans Petter Selasky 	size_t authority_len;
1572b00ab754SHans Petter Selasky 	char *authority;
1573b00ab754SHans Petter Selasky 	char *parsep, *atsignp, *bracketp;
1574b00ab754SHans Petter Selasky 	char *userinfo, *host, *port, *path;
1575b00ab754SHans Petter Selasky 
1576b00ab754SHans Petter Selasky 	/*
1577b00ab754SHans Petter Selasky 	 * Start out returning nothing.
1578b00ab754SHans Petter Selasky 	 */
1579b00ab754SHans Petter Selasky 	*schemep = NULL;
1580b00ab754SHans Petter Selasky 	*userinfop = NULL;
1581b00ab754SHans Petter Selasky 	*hostp = NULL;
1582b00ab754SHans Petter Selasky 	*portp = NULL;
1583b00ab754SHans Petter Selasky 	*pathp = NULL;
1584b00ab754SHans Petter Selasky 
1585b00ab754SHans Petter Selasky 	/*
1586b00ab754SHans Petter Selasky 	 * RFC 3986 says:
1587b00ab754SHans Petter Selasky 	 *
1588b00ab754SHans Petter Selasky 	 *   URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
1589b00ab754SHans Petter Selasky 	 *
1590b00ab754SHans Petter Selasky 	 *   hier-part   = "//" authority path-abempty
1591b00ab754SHans Petter Selasky 	 *               / path-absolute
1592b00ab754SHans Petter Selasky 	 *               / path-rootless
1593b00ab754SHans Petter Selasky 	 *               / path-empty
1594b00ab754SHans Petter Selasky 	 *
1595b00ab754SHans Petter Selasky 	 *   authority   = [ userinfo "@" ] host [ ":" port ]
1596b00ab754SHans Petter Selasky 	 *
1597b00ab754SHans Petter Selasky 	 *   userinfo    = *( unreserved / pct-encoded / sub-delims / ":" )
1598b00ab754SHans Petter Selasky          *
1599b00ab754SHans Petter Selasky          * Step 1: look for the ":" at the end of the scheme.
1600b00ab754SHans Petter Selasky 	 * A colon in the source is *NOT* sufficient to indicate that
1601b00ab754SHans Petter Selasky 	 * this is a URL, as interface names on some platforms might
1602b00ab754SHans Petter Selasky 	 * include colons (e.g., I think some Solaris interfaces
1603b00ab754SHans Petter Selasky 	 * might).
1604b00ab754SHans Petter Selasky 	 */
1605b00ab754SHans Petter Selasky 	colonp = strchr(source, ':');
1606b00ab754SHans Petter Selasky 	if (colonp == NULL) {
1607b00ab754SHans Petter Selasky 		/*
1608b00ab754SHans Petter Selasky 		 * The source is the device to open.
1609b00ab754SHans Petter Selasky 		 * Return a NULL pointer for the scheme, user information,
1610b00ab754SHans Petter Selasky 		 * host, and port, and return the device as the path.
1611b00ab754SHans Petter Selasky 		 */
1612b00ab754SHans Petter Selasky 		*pathp = strdup(source);
1613b00ab754SHans Petter Selasky 		if (*pathp == NULL) {
1614b00ab754SHans Petter Selasky 			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
1615b00ab754SHans Petter Selasky 			    errno, "malloc");
1616b00ab754SHans Petter Selasky 			return (-1);
1617b00ab754SHans Petter Selasky 		}
1618b00ab754SHans Petter Selasky 		return (0);
1619b00ab754SHans Petter Selasky 	}
1620b00ab754SHans Petter Selasky 
1621b00ab754SHans Petter Selasky 	/*
1622b00ab754SHans Petter Selasky 	 * All schemes must have "//" after them, i.e. we only support
1623b00ab754SHans Petter Selasky 	 * hier-part   = "//" authority path-abempty, not
1624b00ab754SHans Petter Selasky 	 * hier-part   = path-absolute
1625b00ab754SHans Petter Selasky 	 * hier-part   = path-rootless
1626b00ab754SHans Petter Selasky 	 * hier-part   = path-empty
1627b00ab754SHans Petter Selasky 	 *
1628b00ab754SHans Petter Selasky 	 * We need that in order to distinguish between a local device
1629b00ab754SHans Petter Selasky 	 * name that happens to contain a colon and a URI.
1630b00ab754SHans Petter Selasky 	 */
1631b00ab754SHans Petter Selasky 	if (strncmp(colonp + 1, "//", 2) != 0) {
1632b00ab754SHans Petter Selasky 		/*
1633b00ab754SHans Petter Selasky 		 * The source is the device to open.
1634b00ab754SHans Petter Selasky 		 * Return a NULL pointer for the scheme, user information,
1635b00ab754SHans Petter Selasky 		 * host, and port, and return the device as the path.
1636b00ab754SHans Petter Selasky 		 */
1637b00ab754SHans Petter Selasky 		*pathp = strdup(source);
1638b00ab754SHans Petter Selasky 		if (*pathp == NULL) {
1639b00ab754SHans Petter Selasky 			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
1640b00ab754SHans Petter Selasky 			    errno, "malloc");
1641b00ab754SHans Petter Selasky 			return (-1);
1642b00ab754SHans Petter Selasky 		}
1643b00ab754SHans Petter Selasky 		return (0);
1644b00ab754SHans Petter Selasky 	}
1645b00ab754SHans Petter Selasky 
1646b00ab754SHans Petter Selasky 	/*
1647b00ab754SHans Petter Selasky 	 * XXX - check whether the purported scheme could be a scheme?
1648b00ab754SHans Petter Selasky 	 */
1649b00ab754SHans Petter Selasky 
1650b00ab754SHans Petter Selasky 	/*
1651b00ab754SHans Petter Selasky 	 * OK, this looks like a URL.
1652b00ab754SHans Petter Selasky 	 * Get the scheme.
1653b00ab754SHans Petter Selasky 	 */
1654b00ab754SHans Petter Selasky 	scheme_len = colonp - source;
1655b00ab754SHans Petter Selasky 	scheme = malloc(scheme_len + 1);
1656b00ab754SHans Petter Selasky 	if (scheme == NULL) {
1657b00ab754SHans Petter Selasky 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
1658b00ab754SHans Petter Selasky 		    errno, "malloc");
1659b00ab754SHans Petter Selasky 		return (-1);
1660b00ab754SHans Petter Selasky 	}
1661b00ab754SHans Petter Selasky 	memcpy(scheme, source, scheme_len);
1662b00ab754SHans Petter Selasky 	scheme[scheme_len] = '\0';
1663b00ab754SHans Petter Selasky 
1664b00ab754SHans Petter Selasky 	/*
1665b00ab754SHans Petter Selasky 	 * Treat file: specially - take everything after file:// as
1666b00ab754SHans Petter Selasky 	 * the pathname.
1667b00ab754SHans Petter Selasky 	 */
1668b00ab754SHans Petter Selasky 	if (pcap_strcasecmp(scheme, "file") == 0) {
1669b00ab754SHans Petter Selasky 		*pathp = strdup(colonp + 3);
1670b00ab754SHans Petter Selasky 		if (*pathp == NULL) {
1671b00ab754SHans Petter Selasky 			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
1672b00ab754SHans Petter Selasky 			    errno, "malloc");
1673*57e22627SCy Schubert 			free(scheme);
1674b00ab754SHans Petter Selasky 			return (-1);
1675b00ab754SHans Petter Selasky 		}
1676*57e22627SCy Schubert 		*schemep = scheme;
1677b00ab754SHans Petter Selasky 		return (0);
1678b00ab754SHans Petter Selasky 	}
1679b00ab754SHans Petter Selasky 
1680b00ab754SHans Petter Selasky 	/*
1681b00ab754SHans Petter Selasky 	 * The WinPcap documentation says you can specify a local
1682b00ab754SHans Petter Selasky 	 * interface with "rpcap://{device}"; we special-case
1683b00ab754SHans Petter Selasky 	 * that here.  If the scheme is "rpcap", and there are
1684b00ab754SHans Petter Selasky 	 * no slashes past the "//", we just return the device.
1685b00ab754SHans Petter Selasky 	 *
1686b00ab754SHans Petter Selasky 	 * XXX - %-escaping?
1687b00ab754SHans Petter Selasky 	 */
1688b00ab754SHans Petter Selasky 	if (pcap_strcasecmp(scheme, "rpcap") == 0 &&
1689b00ab754SHans Petter Selasky 	    strchr(colonp + 3, '/') == NULL) {
1690b00ab754SHans Petter Selasky 		/*
1691b00ab754SHans Petter Selasky 		 * Local device.
1692b00ab754SHans Petter Selasky 		 *
1693b00ab754SHans Petter Selasky 		 * Return a NULL pointer for the scheme, user information,
1694b00ab754SHans Petter Selasky 		 * host, and port, and return the device as the path.
1695b00ab754SHans Petter Selasky 		 */
1696b00ab754SHans Petter Selasky 		free(scheme);
1697b00ab754SHans Petter Selasky 		*pathp = strdup(colonp + 3);
1698b00ab754SHans Petter Selasky 		if (*pathp == NULL) {
1699b00ab754SHans Petter Selasky 			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
1700b00ab754SHans Petter Selasky 			    errno, "malloc");
1701b00ab754SHans Petter Selasky 			return (-1);
1702b00ab754SHans Petter Selasky 		}
1703b00ab754SHans Petter Selasky 		return (0);
1704b00ab754SHans Petter Selasky 	}
1705b00ab754SHans Petter Selasky 
1706b00ab754SHans Petter Selasky 	/*
1707b00ab754SHans Petter Selasky 	 * OK, now start parsing the authority.
1708b00ab754SHans Petter Selasky 	 * Get token, terminated with / or terminated at the end of
1709b00ab754SHans Petter Selasky 	 * the string.
1710b00ab754SHans Petter Selasky 	 */
1711b00ab754SHans Petter Selasky 	authority_len = strcspn(colonp + 3, "/");
1712b00ab754SHans Petter Selasky 	authority = get_substring(colonp + 3, authority_len, ebuf);
1713b00ab754SHans Petter Selasky 	if (authority == NULL) {
1714b00ab754SHans Petter Selasky 		/*
1715b00ab754SHans Petter Selasky 		 * Error.
1716b00ab754SHans Petter Selasky 		 */
1717b00ab754SHans Petter Selasky 		free(scheme);
1718b00ab754SHans Petter Selasky 		return (-1);
1719b00ab754SHans Petter Selasky 	}
1720b00ab754SHans Petter Selasky 	endp = colonp + 3 + authority_len;
1721b00ab754SHans Petter Selasky 
1722b00ab754SHans Petter Selasky 	/*
1723b00ab754SHans Petter Selasky 	 * Now carve the authority field into its components.
1724b00ab754SHans Petter Selasky 	 */
1725b00ab754SHans Petter Selasky 	parsep = authority;
1726b00ab754SHans Petter Selasky 
1727b00ab754SHans Petter Selasky 	/*
1728b00ab754SHans Petter Selasky 	 * Is there a userinfo field?
1729b00ab754SHans Petter Selasky 	 */
1730b00ab754SHans Petter Selasky 	atsignp = strchr(parsep, '@');
1731b00ab754SHans Petter Selasky 	if (atsignp != NULL) {
1732b00ab754SHans Petter Selasky 		/*
1733b00ab754SHans Petter Selasky 		 * Yes.
1734b00ab754SHans Petter Selasky 		 */
1735b00ab754SHans Petter Selasky 		size_t userinfo_len;
1736b00ab754SHans Petter Selasky 
1737b00ab754SHans Petter Selasky 		userinfo_len = atsignp - parsep;
1738b00ab754SHans Petter Selasky 		userinfo = get_substring(parsep, userinfo_len, ebuf);
1739b00ab754SHans Petter Selasky 		if (userinfo == NULL) {
1740b00ab754SHans Petter Selasky 			/*
1741b00ab754SHans Petter Selasky 			 * Error.
1742b00ab754SHans Petter Selasky 			 */
1743b00ab754SHans Petter Selasky 			free(authority);
1744b00ab754SHans Petter Selasky 			free(scheme);
1745b00ab754SHans Petter Selasky 			return (-1);
1746b00ab754SHans Petter Selasky 		}
1747b00ab754SHans Petter Selasky 		parsep = atsignp + 1;
1748b00ab754SHans Petter Selasky 	} else {
1749b00ab754SHans Petter Selasky 		/*
1750b00ab754SHans Petter Selasky 		 * No.
1751b00ab754SHans Petter Selasky 		 */
1752b00ab754SHans Petter Selasky 		userinfo = NULL;
1753b00ab754SHans Petter Selasky 	}
1754b00ab754SHans Petter Selasky 
1755b00ab754SHans Petter Selasky 	/*
1756b00ab754SHans Petter Selasky 	 * Is there a host field?
1757b00ab754SHans Petter Selasky 	 */
1758b00ab754SHans Petter Selasky 	if (*parsep == '\0') {
1759b00ab754SHans Petter Selasky 		/*
1760b00ab754SHans Petter Selasky 		 * No; there's no host field or port field.
1761b00ab754SHans Petter Selasky 		 */
1762b00ab754SHans Petter Selasky 		host = NULL;
1763b00ab754SHans Petter Selasky 		port = NULL;
1764b00ab754SHans Petter Selasky 	} else {
1765b00ab754SHans Petter Selasky 		/*
1766b00ab754SHans Petter Selasky 		 * Yes.
1767b00ab754SHans Petter Selasky 		 */
1768b00ab754SHans Petter Selasky 		size_t host_len;
1769b00ab754SHans Petter Selasky 
1770b00ab754SHans Petter Selasky 		/*
1771b00ab754SHans Petter Selasky 		 * Is it an IP-literal?
1772b00ab754SHans Petter Selasky 		 */
1773b00ab754SHans Petter Selasky 		if (*parsep == '[') {
1774b00ab754SHans Petter Selasky 			/*
1775b00ab754SHans Petter Selasky 			 * Yes.
1776b00ab754SHans Petter Selasky 			 * Treat verything up to the closing square
1777b00ab754SHans Petter Selasky 			 * bracket as the IP-Literal; we don't worry
1778b00ab754SHans Petter Selasky 			 * about whether it's a valid IPv6address or
1779*57e22627SCy Schubert 			 * IPvFuture (or an IPv4address, for that
1780*57e22627SCy Schubert 			 * matter, just in case we get handed a
1781*57e22627SCy Schubert 			 * URL with an IPv4 IP-Literal, of the sort
1782*57e22627SCy Schubert 			 * that pcap_createsrcstr() used to generate,
1783*57e22627SCy Schubert 			 * and that pcap_parsesrcstr(), in the original
1784*57e22627SCy Schubert 			 * WinPcap code, accepted).
1785b00ab754SHans Petter Selasky 			 */
1786b00ab754SHans Petter Selasky 			bracketp = strchr(parsep, ']');
1787b00ab754SHans Petter Selasky 			if (bracketp == NULL) {
1788b00ab754SHans Petter Selasky 				/*
1789b00ab754SHans Petter Selasky 				 * There's no closing square bracket.
1790b00ab754SHans Petter Selasky 				 */
1791b00ab754SHans Petter Selasky 				pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
1792b00ab754SHans Petter Selasky 				    "IP-literal in URL doesn't end with ]");
1793b00ab754SHans Petter Selasky 				free(userinfo);
1794b00ab754SHans Petter Selasky 				free(authority);
1795b00ab754SHans Petter Selasky 				free(scheme);
1796b00ab754SHans Petter Selasky 				return (-1);
1797b00ab754SHans Petter Selasky 			}
1798b00ab754SHans Petter Selasky 			if (*(bracketp + 1) != '\0' &&
1799b00ab754SHans Petter Selasky 			    *(bracketp + 1) != ':') {
1800b00ab754SHans Petter Selasky 				/*
1801b00ab754SHans Petter Selasky 				 * There's extra crud after the
1802b00ab754SHans Petter Selasky 				 * closing square bracketn.
1803b00ab754SHans Petter Selasky 				 */
1804b00ab754SHans Petter Selasky 				pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
1805b00ab754SHans Petter Selasky 				    "Extra text after IP-literal in URL");
1806b00ab754SHans Petter Selasky 				free(userinfo);
1807b00ab754SHans Petter Selasky 				free(authority);
1808b00ab754SHans Petter Selasky 				free(scheme);
1809b00ab754SHans Petter Selasky 				return (-1);
1810b00ab754SHans Petter Selasky 			}
1811b00ab754SHans Petter Selasky 			host_len = (bracketp - 1) - parsep;
1812b00ab754SHans Petter Selasky 			host = get_substring(parsep + 1, host_len, ebuf);
1813b00ab754SHans Petter Selasky 			if (host == NULL) {
1814b00ab754SHans Petter Selasky 				/*
1815b00ab754SHans Petter Selasky 				 * Error.
1816b00ab754SHans Petter Selasky 				 */
1817b00ab754SHans Petter Selasky 				free(userinfo);
1818b00ab754SHans Petter Selasky 				free(authority);
1819b00ab754SHans Petter Selasky 				free(scheme);
1820b00ab754SHans Petter Selasky 				return (-1);
1821b00ab754SHans Petter Selasky 			}
1822b00ab754SHans Petter Selasky 			parsep = bracketp + 1;
1823b00ab754SHans Petter Selasky 		} else {
1824b00ab754SHans Petter Selasky 			/*
1825b00ab754SHans Petter Selasky 			 * No.
1826b00ab754SHans Petter Selasky 			 * Treat everything up to a : or the end of
1827b00ab754SHans Petter Selasky 			 * the string as the host.
1828b00ab754SHans Petter Selasky 			 */
1829b00ab754SHans Petter Selasky 			host_len = strcspn(parsep, ":");
1830b00ab754SHans Petter Selasky 			host = get_substring(parsep, host_len, ebuf);
1831b00ab754SHans Petter Selasky 			if (host == NULL) {
1832b00ab754SHans Petter Selasky 				/*
1833b00ab754SHans Petter Selasky 				 * Error.
1834b00ab754SHans Petter Selasky 				 */
1835b00ab754SHans Petter Selasky 				free(userinfo);
1836b00ab754SHans Petter Selasky 				free(authority);
1837b00ab754SHans Petter Selasky 				free(scheme);
1838b00ab754SHans Petter Selasky 				return (-1);
1839b00ab754SHans Petter Selasky 			}
1840b00ab754SHans Petter Selasky 			parsep = parsep + host_len;
1841b00ab754SHans Petter Selasky 		}
1842b00ab754SHans Petter Selasky 
1843b00ab754SHans Petter Selasky 		/*
1844b00ab754SHans Petter Selasky 		 * Is there a port field?
1845b00ab754SHans Petter Selasky 		 */
1846b00ab754SHans Petter Selasky 		if (*parsep == ':') {
1847b00ab754SHans Petter Selasky 			/*
1848b00ab754SHans Petter Selasky 			 * Yes.  It's the rest of the authority field.
1849b00ab754SHans Petter Selasky 			 */
1850b00ab754SHans Petter Selasky 			size_t port_len;
1851b00ab754SHans Petter Selasky 
1852b00ab754SHans Petter Selasky 			parsep++;
1853b00ab754SHans Petter Selasky 			port_len = strlen(parsep);
1854b00ab754SHans Petter Selasky 			port = get_substring(parsep, port_len, ebuf);
1855b00ab754SHans Petter Selasky 			if (port == NULL) {
1856b00ab754SHans Petter Selasky 				/*
1857b00ab754SHans Petter Selasky 				 * Error.
1858b00ab754SHans Petter Selasky 				 */
1859b00ab754SHans Petter Selasky 				free(host);
1860b00ab754SHans Petter Selasky 				free(userinfo);
1861b00ab754SHans Petter Selasky 				free(authority);
1862b00ab754SHans Petter Selasky 				free(scheme);
1863b00ab754SHans Petter Selasky 				return (-1);
1864b00ab754SHans Petter Selasky 			}
1865b00ab754SHans Petter Selasky 		} else {
1866b00ab754SHans Petter Selasky 			/*
1867b00ab754SHans Petter Selasky 			 * No.
1868b00ab754SHans Petter Selasky 			 */
1869b00ab754SHans Petter Selasky 			port = NULL;
1870b00ab754SHans Petter Selasky 		}
1871b00ab754SHans Petter Selasky 	}
1872b00ab754SHans Petter Selasky 	free(authority);
1873b00ab754SHans Petter Selasky 
1874b00ab754SHans Petter Selasky 	/*
1875b00ab754SHans Petter Selasky 	 * Everything else is the path.  Strip off the leading /.
1876b00ab754SHans Petter Selasky 	 */
1877b00ab754SHans Petter Selasky 	if (*endp == '\0')
1878b00ab754SHans Petter Selasky 		path = strdup("");
1879b00ab754SHans Petter Selasky 	else
1880b00ab754SHans Petter Selasky 		path = strdup(endp + 1);
1881b00ab754SHans Petter Selasky 	if (path == NULL) {
1882b00ab754SHans Petter Selasky 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
1883b00ab754SHans Petter Selasky 		    errno, "malloc");
1884b00ab754SHans Petter Selasky 		free(port);
1885b00ab754SHans Petter Selasky 		free(host);
1886b00ab754SHans Petter Selasky 		free(userinfo);
1887b00ab754SHans Petter Selasky 		free(scheme);
1888b00ab754SHans Petter Selasky 		return (-1);
1889b00ab754SHans Petter Selasky 	}
1890b00ab754SHans Petter Selasky 	*schemep = scheme;
1891b00ab754SHans Petter Selasky 	*userinfop = userinfo;
1892b00ab754SHans Petter Selasky 	*hostp = host;
1893b00ab754SHans Petter Selasky 	*portp = port;
1894b00ab754SHans Petter Selasky 	*pathp = path;
1895b00ab754SHans Petter Selasky 	return (0);
1896b00ab754SHans Petter Selasky }
1897b00ab754SHans Petter Selasky 
1898b00ab754SHans Petter Selasky int
1899b00ab754SHans Petter Selasky pcap_createsrcstr(char *source, int type, const char *host, const char *port,
1900b00ab754SHans Petter Selasky     const char *name, char *errbuf)
1901b00ab754SHans Petter Selasky {
1902b00ab754SHans Petter Selasky 	switch (type) {
1903b00ab754SHans Petter Selasky 
1904b00ab754SHans Petter Selasky 	case PCAP_SRC_FILE:
1905*57e22627SCy Schubert 		pcap_strlcpy(source, PCAP_SRC_FILE_STRING, PCAP_BUF_SIZE);
1906b00ab754SHans Petter Selasky 		if (name != NULL && *name != '\0') {
1907*57e22627SCy Schubert 			pcap_strlcat(source, name, PCAP_BUF_SIZE);
1908b00ab754SHans Petter Selasky 			return (0);
1909b00ab754SHans Petter Selasky 		} else {
1910b00ab754SHans Petter Selasky 			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
1911b00ab754SHans Petter Selasky 			    "The file name cannot be NULL.");
1912b00ab754SHans Petter Selasky 			return (-1);
1913b00ab754SHans Petter Selasky 		}
1914b00ab754SHans Petter Selasky 
1915b00ab754SHans Petter Selasky 	case PCAP_SRC_IFREMOTE:
1916*57e22627SCy Schubert 		pcap_strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
1917b00ab754SHans Petter Selasky 		if (host != NULL && *host != '\0') {
1918b00ab754SHans Petter Selasky 			if (strchr(host, ':') != NULL) {
1919b00ab754SHans Petter Selasky 				/*
1920b00ab754SHans Petter Selasky 				 * The host name contains a colon, so it's
1921b00ab754SHans Petter Selasky 				 * probably an IPv6 address, and needs to
1922b00ab754SHans Petter Selasky 				 * be included in square brackets.
1923b00ab754SHans Petter Selasky 				 */
1924*57e22627SCy Schubert 				pcap_strlcat(source, "[", PCAP_BUF_SIZE);
1925*57e22627SCy Schubert 				pcap_strlcat(source, host, PCAP_BUF_SIZE);
1926*57e22627SCy Schubert 				pcap_strlcat(source, "]", PCAP_BUF_SIZE);
1927b00ab754SHans Petter Selasky 			} else
1928*57e22627SCy Schubert 				pcap_strlcat(source, host, PCAP_BUF_SIZE);
1929b00ab754SHans Petter Selasky 
1930b00ab754SHans Petter Selasky 			if (port != NULL && *port != '\0') {
1931*57e22627SCy Schubert 				pcap_strlcat(source, ":", PCAP_BUF_SIZE);
1932*57e22627SCy Schubert 				pcap_strlcat(source, port, PCAP_BUF_SIZE);
1933b00ab754SHans Petter Selasky 			}
1934b00ab754SHans Petter Selasky 
1935*57e22627SCy Schubert 			pcap_strlcat(source, "/", PCAP_BUF_SIZE);
1936b00ab754SHans Petter Selasky 		} else {
1937b00ab754SHans Petter Selasky 			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
1938b00ab754SHans Petter Selasky 			    "The host name cannot be NULL.");
1939b00ab754SHans Petter Selasky 			return (-1);
1940b00ab754SHans Petter Selasky 		}
1941b00ab754SHans Petter Selasky 
1942b00ab754SHans Petter Selasky 		if (name != NULL && *name != '\0')
1943*57e22627SCy Schubert 			pcap_strlcat(source, name, PCAP_BUF_SIZE);
1944b00ab754SHans Petter Selasky 
1945b00ab754SHans Petter Selasky 		return (0);
1946b00ab754SHans Petter Selasky 
1947b00ab754SHans Petter Selasky 	case PCAP_SRC_IFLOCAL:
1948*57e22627SCy Schubert 		pcap_strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
1949b00ab754SHans Petter Selasky 
1950b00ab754SHans Petter Selasky 		if (name != NULL && *name != '\0')
1951*57e22627SCy Schubert 			pcap_strlcat(source, name, PCAP_BUF_SIZE);
1952b00ab754SHans Petter Selasky 
1953b00ab754SHans Petter Selasky 		return (0);
1954b00ab754SHans Petter Selasky 
1955b00ab754SHans Petter Selasky 	default:
1956b00ab754SHans Petter Selasky 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
1957b00ab754SHans Petter Selasky 		    "The interface type is not valid.");
1958b00ab754SHans Petter Selasky 		return (-1);
1959b00ab754SHans Petter Selasky 	}
1960b00ab754SHans Petter Selasky }
1961b00ab754SHans Petter Selasky 
1962b00ab754SHans Petter Selasky int
1963b00ab754SHans Petter Selasky pcap_parsesrcstr(const char *source, int *type, char *host, char *port,
1964b00ab754SHans Petter Selasky     char *name, char *errbuf)
1965b00ab754SHans Petter Selasky {
1966b00ab754SHans Petter Selasky 	char *scheme, *tmpuserinfo, *tmphost, *tmpport, *tmppath;
1967b00ab754SHans Petter Selasky 
1968b00ab754SHans Petter Selasky 	/* Initialization stuff */
1969b00ab754SHans Petter Selasky 	if (host)
1970b00ab754SHans Petter Selasky 		*host = '\0';
1971b00ab754SHans Petter Selasky 	if (port)
1972b00ab754SHans Petter Selasky 		*port = '\0';
1973b00ab754SHans Petter Selasky 	if (name)
1974b00ab754SHans Petter Selasky 		*name = '\0';
1975b00ab754SHans Petter Selasky 
1976b00ab754SHans Petter Selasky 	/* Parse the source string */
1977b00ab754SHans Petter Selasky 	if (pcap_parse_source(source, &scheme, &tmpuserinfo, &tmphost,
1978b00ab754SHans Petter Selasky 	    &tmpport, &tmppath, errbuf) == -1) {
1979b00ab754SHans Petter Selasky 		/*
1980b00ab754SHans Petter Selasky 		 * Fail.
1981b00ab754SHans Petter Selasky 		 */
1982b00ab754SHans Petter Selasky 		return (-1);
1983b00ab754SHans Petter Selasky 	}
1984b00ab754SHans Petter Selasky 
1985b00ab754SHans Petter Selasky 	if (scheme == NULL) {
1986b00ab754SHans Petter Selasky 		/*
1987b00ab754SHans Petter Selasky 		 * Local device.
1988b00ab754SHans Petter Selasky 		 */
1989b00ab754SHans Petter Selasky 		if (name && tmppath)
1990*57e22627SCy Schubert 			pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
1991b00ab754SHans Petter Selasky 		if (type)
1992b00ab754SHans Petter Selasky 			*type = PCAP_SRC_IFLOCAL;
1993b00ab754SHans Petter Selasky 		free(tmppath);
1994b00ab754SHans Petter Selasky 		free(tmpport);
1995b00ab754SHans Petter Selasky 		free(tmphost);
1996b00ab754SHans Petter Selasky 		free(tmpuserinfo);
1997b00ab754SHans Petter Selasky 		return (0);
1998b00ab754SHans Petter Selasky 	}
1999b00ab754SHans Petter Selasky 
2000b00ab754SHans Petter Selasky 	if (strcmp(scheme, "rpcap") == 0) {
2001b00ab754SHans Petter Selasky 		/*
2002b00ab754SHans Petter Selasky 		 * rpcap://
2003b00ab754SHans Petter Selasky 		 *
2004b00ab754SHans Petter Selasky 		 * pcap_parse_source() has already handled the case of
2005b00ab754SHans Petter Selasky 		 * rpcap://device
2006b00ab754SHans Petter Selasky 		 */
2007b00ab754SHans Petter Selasky 		if (host && tmphost) {
2008b00ab754SHans Petter Selasky 			if (tmpuserinfo)
2009b00ab754SHans Petter Selasky 				pcap_snprintf(host, PCAP_BUF_SIZE, "%s@%s",
2010b00ab754SHans Petter Selasky 				    tmpuserinfo, tmphost);
2011b00ab754SHans Petter Selasky 			else
2012*57e22627SCy Schubert 				pcap_strlcpy(host, tmphost, PCAP_BUF_SIZE);
2013b00ab754SHans Petter Selasky 		}
2014b00ab754SHans Petter Selasky 		if (port && tmpport)
2015*57e22627SCy Schubert 			pcap_strlcpy(port, tmpport, PCAP_BUF_SIZE);
2016b00ab754SHans Petter Selasky 		if (name && tmppath)
2017*57e22627SCy Schubert 			pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
2018b00ab754SHans Petter Selasky 		if (type)
2019b00ab754SHans Petter Selasky 			*type = PCAP_SRC_IFREMOTE;
2020b00ab754SHans Petter Selasky 		free(tmppath);
2021b00ab754SHans Petter Selasky 		free(tmpport);
2022b00ab754SHans Petter Selasky 		free(tmphost);
2023b00ab754SHans Petter Selasky 		free(tmpuserinfo);
2024b00ab754SHans Petter Selasky 		free(scheme);
2025b00ab754SHans Petter Selasky 		return (0);
2026b00ab754SHans Petter Selasky 	}
2027b00ab754SHans Petter Selasky 
2028b00ab754SHans Petter Selasky 	if (strcmp(scheme, "file") == 0) {
2029b00ab754SHans Petter Selasky 		/*
2030b00ab754SHans Petter Selasky 		 * file://
2031b00ab754SHans Petter Selasky 		 */
2032b00ab754SHans Petter Selasky 		if (name && tmppath)
2033*57e22627SCy Schubert 			pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
2034b00ab754SHans Petter Selasky 		if (type)
2035b00ab754SHans Petter Selasky 			*type = PCAP_SRC_FILE;
2036b00ab754SHans Petter Selasky 		free(tmppath);
2037b00ab754SHans Petter Selasky 		free(tmpport);
2038b00ab754SHans Petter Selasky 		free(tmphost);
2039b00ab754SHans Petter Selasky 		free(tmpuserinfo);
2040b00ab754SHans Petter Selasky 		free(scheme);
2041b00ab754SHans Petter Selasky 		return (0);
2042b00ab754SHans Petter Selasky 	}
2043b00ab754SHans Petter Selasky 
2044b00ab754SHans Petter Selasky 	/*
2045b00ab754SHans Petter Selasky 	 * Neither rpcap: nor file:; just treat the entire string
2046b00ab754SHans Petter Selasky 	 * as a local device.
2047b00ab754SHans Petter Selasky 	 */
2048b00ab754SHans Petter Selasky 	if (name)
2049*57e22627SCy Schubert 		pcap_strlcpy(name, source, PCAP_BUF_SIZE);
2050b00ab754SHans Petter Selasky 	if (type)
2051b00ab754SHans Petter Selasky 		*type = PCAP_SRC_IFLOCAL;
2052b00ab754SHans Petter Selasky 	free(tmppath);
2053b00ab754SHans Petter Selasky 	free(tmpport);
2054b00ab754SHans Petter Selasky 	free(tmphost);
2055b00ab754SHans Petter Selasky 	free(tmpuserinfo);
2056b00ab754SHans Petter Selasky 	free(scheme);
2057b00ab754SHans Petter Selasky 	return (0);
2058b00ab754SHans Petter Selasky }
2059b00ab754SHans Petter Selasky #endif
2060b00ab754SHans Petter Selasky 
2061edc89b24SXin LI pcap_t *
2062ada6f083SXin LI pcap_create(const char *device, char *errbuf)
2063edc89b24SXin LI {
2064edc89b24SXin LI 	size_t i;
2065edc89b24SXin LI 	int is_theirs;
2066edc89b24SXin LI 	pcap_t *p;
2067ada6f083SXin LI 	char *device_str;
2068edc89b24SXin LI 
2069edc89b24SXin LI 	/*
2070ada6f083SXin LI 	 * A null device name is equivalent to the "any" device -
2071edc89b24SXin LI 	 * which might not be supported on this platform, but
2072edc89b24SXin LI 	 * this means that you'll get a "not supported" error
2073edc89b24SXin LI 	 * rather than, say, a crash when we try to dereference
2074edc89b24SXin LI 	 * the null pointer.
2075edc89b24SXin LI 	 */
2076ada6f083SXin LI 	if (device == NULL)
2077ada6f083SXin LI 		device_str = strdup("any");
2078ada6f083SXin LI 	else {
2079ada6f083SXin LI #ifdef _WIN32
2080ada6f083SXin LI 		/*
2081*57e22627SCy Schubert 		 * On Windows, for backwards compatibility reasons,
2082*57e22627SCy Schubert 		 * pcap_lookupdev() returns a pointer to a sequence of
2083*57e22627SCy Schubert 		 * pairs of UTF-16LE device names and local code page
2084*57e22627SCy Schubert 		 * description strings.
2085ada6f083SXin LI 		 *
2086*57e22627SCy Schubert 		 * This means that if a program uses pcap_lookupdev()
2087*57e22627SCy Schubert 		 * to get a default device, and hands that to an API
2088*57e22627SCy Schubert 		 * that opens devices, we'll get handed a UTF-16LE
2089*57e22627SCy Schubert 		 * string, not a string in the local code page.
2090*57e22627SCy Schubert 		 *
2091*57e22627SCy Schubert 		 * To work around that, we check whether the string
2092*57e22627SCy Schubert 		 * looks as if it might be a UTF-16LE strinh and, if
2093*57e22627SCy Schubert 		 * so, convert it back to the local code page's
2094*57e22627SCy Schubert 		 * extended ASCII.
2095*57e22627SCy Schubert 		 *
2096*57e22627SCy Schubert 		 * XXX - you *cannot* reliably detect whether a
2097*57e22627SCy Schubert 		 * string is UTF-16LE or not; "a" could either
2098*57e22627SCy Schubert 		 * be a one-character ASCII string or the first
2099*57e22627SCy Schubert 		 * character of a UTF-16LE string.  This particular
2100*57e22627SCy Schubert 		 * version of this heuristic dates back to WinPcap
2101*57e22627SCy Schubert 		 * 4.1.1; PacketOpenAdapter() does uses the same
2102*57e22627SCy Schubert 		 * heuristic, with the exact same vulnerability.
2103ada6f083SXin LI 		 */
2104ada6f083SXin LI 		if (device[0] != '\0' && device[1] == '\0') {
2105ada6f083SXin LI 			size_t length;
2106ada6f083SXin LI 
2107ada6f083SXin LI 			length = wcslen((wchar_t *)device);
2108ada6f083SXin LI 			device_str = (char *)malloc(length + 1);
2109ada6f083SXin LI 			if (device_str == NULL) {
2110b00ab754SHans Petter Selasky 				pcap_fmt_errmsg_for_errno(errbuf,
2111b00ab754SHans Petter Selasky 				    PCAP_ERRBUF_SIZE, errno,
2112b00ab754SHans Petter Selasky 				    "malloc");
2113ada6f083SXin LI 				return (NULL);
2114ada6f083SXin LI 			}
2115ada6f083SXin LI 
2116ada6f083SXin LI 			pcap_snprintf(device_str, length + 1, "%ws",
2117ada6f083SXin LI 			    (const wchar_t *)device);
2118ada6f083SXin LI 		} else
2119ada6f083SXin LI #endif
2120ada6f083SXin LI 			device_str = strdup(device);
2121ada6f083SXin LI 	}
2122ada6f083SXin LI 	if (device_str == NULL) {
2123b00ab754SHans Petter Selasky 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
2124b00ab754SHans Petter Selasky 		    errno, "malloc");
2125ada6f083SXin LI 		return (NULL);
2126ada6f083SXin LI 	}
2127edc89b24SXin LI 
2128edc89b24SXin LI 	/*
2129edc89b24SXin LI 	 * Try each of the non-local-network-interface capture
2130edc89b24SXin LI 	 * source types until we find one that works for this
2131edc89b24SXin LI 	 * device or run out of types.
2132edc89b24SXin LI 	 */
2133edc89b24SXin LI 	for (i = 0; capture_source_types[i].create_op != NULL; i++) {
2134edc89b24SXin LI 		is_theirs = 0;
2135ada6f083SXin LI 		p = capture_source_types[i].create_op(device_str, errbuf,
2136ada6f083SXin LI 		    &is_theirs);
2137edc89b24SXin LI 		if (is_theirs) {
2138edc89b24SXin LI 			/*
2139edc89b24SXin LI 			 * The device name refers to a device of the
2140edc89b24SXin LI 			 * type in question; either it succeeded,
2141edc89b24SXin LI 			 * in which case p refers to a pcap_t to
2142edc89b24SXin LI 			 * later activate for the device, or it
2143edc89b24SXin LI 			 * failed, in which case p is null and we
2144edc89b24SXin LI 			 * should return that to report the failure
2145edc89b24SXin LI 			 * to create.
2146edc89b24SXin LI 			 */
2147ada6f083SXin LI 			if (p == NULL) {
2148ada6f083SXin LI 				/*
2149ada6f083SXin LI 				 * We assume the caller filled in errbuf.
2150ada6f083SXin LI 				 */
2151ada6f083SXin LI 				free(device_str);
2152ada6f083SXin LI 				return (NULL);
2153ada6f083SXin LI 			}
2154ada6f083SXin LI 			p->opt.device = device_str;
2155edc89b24SXin LI 			return (p);
2156edc89b24SXin LI 		}
2157edc89b24SXin LI 	}
2158edc89b24SXin LI 
2159edc89b24SXin LI 	/*
2160edc89b24SXin LI 	 * OK, try it as a regular network interface.
2161edc89b24SXin LI 	 */
2162ada6f083SXin LI 	p = pcap_create_interface(device_str, errbuf);
2163ada6f083SXin LI 	if (p == NULL) {
2164ada6f083SXin LI 		/*
2165ada6f083SXin LI 		 * We assume the caller filled in errbuf.
2166ada6f083SXin LI 		 */
2167ada6f083SXin LI 		free(device_str);
2168ada6f083SXin LI 		return (NULL);
2169edc89b24SXin LI 	}
2170ada6f083SXin LI 	p->opt.device = device_str;
2171ada6f083SXin LI 	return (p);
2172ada6f083SXin LI }
2173edc89b24SXin LI 
2174b00ab754SHans Petter Selasky /*
2175b00ab754SHans Petter Selasky  * Set nonblocking mode on an unactivated pcap_t; this sets a flag
2176b00ab754SHans Petter Selasky  * checked by pcap_activate(), which sets the mode after calling
2177b00ab754SHans Petter Selasky  * the activate routine.
2178b00ab754SHans Petter Selasky  */
2179b00ab754SHans Petter Selasky static int
2180b00ab754SHans Petter Selasky pcap_setnonblock_unactivated(pcap_t *p, int nonblock)
2181b00ab754SHans Petter Selasky {
2182b00ab754SHans Petter Selasky 	p->opt.nonblock = nonblock;
2183b00ab754SHans Petter Selasky 	return (0);
2184b00ab754SHans Petter Selasky }
2185b00ab754SHans Petter Selasky 
2186a0ee43a1SRui Paulo static void
2187a0ee43a1SRui Paulo initialize_ops(pcap_t *p)
2188a0ee43a1SRui Paulo {
2189a0ee43a1SRui Paulo 	/*
2190a0ee43a1SRui Paulo 	 * Set operation pointers for operations that only work on
2191a0ee43a1SRui Paulo 	 * an activated pcap_t to point to a routine that returns
2192a0ee43a1SRui Paulo 	 * a "this isn't activated" error.
2193a8e07101SRui Paulo 	 */
2194*57e22627SCy Schubert 	p->read_op = pcap_read_not_initialized;
2195*57e22627SCy Schubert 	p->inject_op = pcap_inject_not_initialized;
2196*57e22627SCy Schubert 	p->setfilter_op = pcap_setfilter_not_initialized;
2197*57e22627SCy Schubert 	p->setdirection_op = pcap_setdirection_not_initialized;
2198*57e22627SCy Schubert 	p->set_datalink_op = pcap_set_datalink_not_initialized;
2199*57e22627SCy Schubert 	p->getnonblock_op = pcap_getnonblock_not_initialized;
2200*57e22627SCy Schubert 	p->stats_op = pcap_stats_not_initialized;
2201ada6f083SXin LI #ifdef _WIN32
2202*57e22627SCy Schubert 	p->stats_ex_op = pcap_stats_ex_not_initialized;
2203*57e22627SCy Schubert 	p->setbuff_op = pcap_setbuff_not_initialized;
2204*57e22627SCy Schubert 	p->setmode_op = pcap_setmode_not_initialized;
2205*57e22627SCy Schubert 	p->setmintocopy_op = pcap_setmintocopy_not_initialized;
2206ada6f083SXin LI 	p->getevent_op = pcap_getevent_not_initialized;
2207*57e22627SCy Schubert 	p->oid_get_request_op = pcap_oid_get_request_not_initialized;
2208*57e22627SCy Schubert 	p->oid_set_request_op = pcap_oid_set_request_not_initialized;
2209ada6f083SXin LI 	p->sendqueue_transmit_op = pcap_sendqueue_transmit_not_initialized;
2210*57e22627SCy Schubert 	p->setuserbuffer_op = pcap_setuserbuffer_not_initialized;
2211*57e22627SCy Schubert 	p->live_dump_op = pcap_live_dump_not_initialized;
2212*57e22627SCy Schubert 	p->live_dump_ended_op = pcap_live_dump_ended_not_initialized;
2213ada6f083SXin LI 	p->get_airpcap_handle_op = pcap_get_airpcap_handle_not_initialized;
2214a8e07101SRui Paulo #endif
2215a0ee43a1SRui Paulo 
2216a0ee43a1SRui Paulo 	/*
2217a0ee43a1SRui Paulo 	 * Default cleanup operation - implementations can override
2218a0ee43a1SRui Paulo 	 * this, but should call pcap_cleanup_live_common() after
2219a0ee43a1SRui Paulo 	 * doing their own additional cleanup.
2220a0ee43a1SRui Paulo 	 */
2221a8e07101SRui Paulo 	p->cleanup_op = pcap_cleanup_live_common;
2222a8e07101SRui Paulo 
2223a0ee43a1SRui Paulo 	/*
2224681ed54cSXin LI 	 * In most cases, the standard one-shot callback can
2225a0ee43a1SRui Paulo 	 * be used for pcap_next()/pcap_next_ex().
2226a0ee43a1SRui Paulo 	 */
2227a0ee43a1SRui Paulo 	p->oneshot_callback = pcap_oneshot;
2228a0ee43a1SRui Paulo }
2229a0ee43a1SRui Paulo 
2230681ed54cSXin LI static pcap_t *
2231681ed54cSXin LI pcap_alloc_pcap_t(char *ebuf, size_t size)
2232a0ee43a1SRui Paulo {
2233681ed54cSXin LI 	char *chunk;
2234a0ee43a1SRui Paulo 	pcap_t *p;
2235a0ee43a1SRui Paulo 
2236681ed54cSXin LI 	/*
2237681ed54cSXin LI 	 * Allocate a chunk of memory big enough for a pcap_t
2238681ed54cSXin LI 	 * plus a structure following it of size "size".  The
2239681ed54cSXin LI 	 * structure following it is a private data structure
2240681ed54cSXin LI 	 * for the routines that handle this pcap_t.
2241*57e22627SCy Schubert 	 *
2242*57e22627SCy Schubert 	 * The structure following it must be aligned on
2243*57e22627SCy Schubert 	 * the appropriate alignment boundary for this platform.
2244*57e22627SCy Schubert 	 * We align on an 8-byte boundary as that's probably what
2245*57e22627SCy Schubert 	 * at least some platforms do, even with 32-bit integers,
2246*57e22627SCy Schubert 	 * and because we can't be sure that some values won't
2247*57e22627SCy Schubert 	 * require 8-byte alignment even on platforms with 32-bit
2248*57e22627SCy Schubert 	 * integers.
2249681ed54cSXin LI 	 */
2250*57e22627SCy Schubert #define PCAP_T_ALIGNED_SIZE	((sizeof(pcap_t) + 7U) & ~0x7U)
2251*57e22627SCy Schubert 	chunk = malloc(PCAP_T_ALIGNED_SIZE + size);
2252681ed54cSXin LI 	if (chunk == NULL) {
2253b00ab754SHans Petter Selasky 		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
2254b00ab754SHans Petter Selasky 		    errno, "malloc");
2255a0ee43a1SRui Paulo 		return (NULL);
2256a0ee43a1SRui Paulo 	}
2257*57e22627SCy Schubert 	memset(chunk, 0, PCAP_T_ALIGNED_SIZE + size);
2258681ed54cSXin LI 
2259681ed54cSXin LI 	/*
2260681ed54cSXin LI 	 * Get a pointer to the pcap_t at the beginning.
2261681ed54cSXin LI 	 */
2262681ed54cSXin LI 	p = (pcap_t *)chunk;
2263681ed54cSXin LI 
2264b00ab754SHans Petter Selasky #ifdef _WIN32
2265b00ab754SHans Petter Selasky 	p->handle = INVALID_HANDLE_VALUE;	/* not opened yet */
2266b00ab754SHans Petter Selasky #else /* _WIN32 */
2267a0ee43a1SRui Paulo 	p->fd = -1;	/* not opened yet */
2268b00ab754SHans Petter Selasky #ifndef MSDOS
2269a0ee43a1SRui Paulo 	p->selectable_fd = -1;
2270b00ab754SHans Petter Selasky 	p->required_select_timeout = NULL;
2271b00ab754SHans Petter Selasky #endif /* MSDOS */
2272b00ab754SHans Petter Selasky #endif /* _WIN32 */
2273a0ee43a1SRui Paulo 
2274681ed54cSXin LI 	if (size == 0) {
2275681ed54cSXin LI 		/* No private data was requested. */
2276681ed54cSXin LI 		p->priv = NULL;
2277681ed54cSXin LI 	} else {
2278681ed54cSXin LI 		/*
2279681ed54cSXin LI 		 * Set the pointer to the private data; that's the structure
2280681ed54cSXin LI 		 * of size "size" following the pcap_t.
2281681ed54cSXin LI 		 */
2282*57e22627SCy Schubert 		p->priv = (void *)(chunk + PCAP_T_ALIGNED_SIZE);
2283681ed54cSXin LI 	}
2284681ed54cSXin LI 
2285681ed54cSXin LI 	return (p);
2286681ed54cSXin LI }
2287681ed54cSXin LI 
2288681ed54cSXin LI pcap_t *
2289ada6f083SXin LI pcap_create_common(char *ebuf, size_t size)
2290681ed54cSXin LI {
2291681ed54cSXin LI 	pcap_t *p;
2292681ed54cSXin LI 
2293681ed54cSXin LI 	p = pcap_alloc_pcap_t(ebuf, size);
2294681ed54cSXin LI 	if (p == NULL)
2295681ed54cSXin LI 		return (NULL);
2296681ed54cSXin LI 
2297a0ee43a1SRui Paulo 	/*
2298a0ee43a1SRui Paulo 	 * Default to "can't set rfmon mode"; if it's supported by
2299a0ee43a1SRui Paulo 	 * a platform, the create routine that called us can set
2300a0ee43a1SRui Paulo 	 * the op to its routine to check whether a particular
2301a0ee43a1SRui Paulo 	 * device supports it.
2302a0ee43a1SRui Paulo 	 */
2303a0ee43a1SRui Paulo 	p->can_set_rfmon_op = pcap_cant_set_rfmon;
2304a0ee43a1SRui Paulo 
2305b00ab754SHans Petter Selasky 	/*
2306b00ab754SHans Petter Selasky 	 * If pcap_setnonblock() is called on a not-yet-activated
2307b00ab754SHans Petter Selasky 	 * pcap_t, default to setting a flag and turning
2308b00ab754SHans Petter Selasky 	 * on non-blocking mode when activated.
2309b00ab754SHans Petter Selasky 	 */
2310b00ab754SHans Petter Selasky 	p->setnonblock_op = pcap_setnonblock_unactivated;
2311b00ab754SHans Petter Selasky 
2312a0ee43a1SRui Paulo 	initialize_ops(p);
2313a0ee43a1SRui Paulo 
2314a8e07101SRui Paulo 	/* put in some defaults*/
2315b00ab754SHans Petter Selasky 	p->snapshot = 0;		/* max packet size unspecified */
2316681ed54cSXin LI 	p->opt.timeout = 0;		/* no timeout specified */
2317681ed54cSXin LI 	p->opt.buffer_size = 0;		/* use the platform's default */
2318a8e07101SRui Paulo 	p->opt.promisc = 0;
2319681ed54cSXin LI 	p->opt.rfmon = 0;
2320681ed54cSXin LI 	p->opt.immediate = 0;
2321d1e87331SXin LI 	p->opt.tstamp_type = -1;	/* default to not setting time stamp type */
2322681ed54cSXin LI 	p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
2323b00ab754SHans Petter Selasky 	/*
2324b00ab754SHans Petter Selasky 	 * Platform-dependent options.
2325b00ab754SHans Petter Selasky 	 */
2326b00ab754SHans Petter Selasky #ifdef __linux__
2327b00ab754SHans Petter Selasky 	p->opt.protocol = 0;
2328b00ab754SHans Petter Selasky #endif
2329b00ab754SHans Petter Selasky #ifdef _WIN32
2330b00ab754SHans Petter Selasky 	p->opt.nocapture_local = 0;
2331b00ab754SHans Petter Selasky #endif
2332ada6f083SXin LI 
2333ada6f083SXin LI 	/*
2334ada6f083SXin LI 	 * Start out with no BPF code generation flags set.
2335ada6f083SXin LI 	 */
2336ada6f083SXin LI 	p->bpf_codegen_flags = 0;
2337ada6f083SXin LI 
2338a8e07101SRui Paulo 	return (p);
2339a8e07101SRui Paulo }
2340a8e07101SRui Paulo 
2341a8e07101SRui Paulo int
2342a8e07101SRui Paulo pcap_check_activated(pcap_t *p)
2343a8e07101SRui Paulo {
2344a8e07101SRui Paulo 	if (p->activated) {
2345ada6f083SXin LI 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
2346a8e07101SRui Paulo 			" operation on activated capture");
2347d1e87331SXin LI 		return (-1);
2348a8e07101SRui Paulo 	}
2349d1e87331SXin LI 	return (0);
2350a8e07101SRui Paulo }
2351a8e07101SRui Paulo 
2352a8e07101SRui Paulo int
2353a8e07101SRui Paulo pcap_set_snaplen(pcap_t *p, int snaplen)
2354a8e07101SRui Paulo {
2355a8e07101SRui Paulo 	if (pcap_check_activated(p))
2356d1e87331SXin LI 		return (PCAP_ERROR_ACTIVATED);
2357a8e07101SRui Paulo 	p->snapshot = snaplen;
2358d1e87331SXin LI 	return (0);
2359a8e07101SRui Paulo }
2360a8e07101SRui Paulo 
2361a8e07101SRui Paulo int
2362a8e07101SRui Paulo pcap_set_promisc(pcap_t *p, int promisc)
2363a8e07101SRui Paulo {
2364a8e07101SRui Paulo 	if (pcap_check_activated(p))
2365d1e87331SXin LI 		return (PCAP_ERROR_ACTIVATED);
2366a8e07101SRui Paulo 	p->opt.promisc = promisc;
2367d1e87331SXin LI 	return (0);
2368a8e07101SRui Paulo }
2369a8e07101SRui Paulo 
2370a8e07101SRui Paulo int
2371a8e07101SRui Paulo pcap_set_rfmon(pcap_t *p, int rfmon)
2372a8e07101SRui Paulo {
2373a8e07101SRui Paulo 	if (pcap_check_activated(p))
2374d1e87331SXin LI 		return (PCAP_ERROR_ACTIVATED);
2375a8e07101SRui Paulo 	p->opt.rfmon = rfmon;
2376d1e87331SXin LI 	return (0);
2377a8e07101SRui Paulo }
2378a8e07101SRui Paulo 
2379a8e07101SRui Paulo int
2380a8e07101SRui Paulo pcap_set_timeout(pcap_t *p, int timeout_ms)
2381a8e07101SRui Paulo {
2382a8e07101SRui Paulo 	if (pcap_check_activated(p))
2383d1e87331SXin LI 		return (PCAP_ERROR_ACTIVATED);
2384681ed54cSXin LI 	p->opt.timeout = timeout_ms;
2385d1e87331SXin LI 	return (0);
2386d1e87331SXin LI }
2387d1e87331SXin LI 
2388d1e87331SXin LI int
2389d1e87331SXin LI pcap_set_tstamp_type(pcap_t *p, int tstamp_type)
2390d1e87331SXin LI {
2391d1e87331SXin LI 	int i;
2392d1e87331SXin LI 
2393d1e87331SXin LI 	if (pcap_check_activated(p))
2394d1e87331SXin LI 		return (PCAP_ERROR_ACTIVATED);
2395d1e87331SXin LI 
2396d1e87331SXin LI 	/*
2397ada6f083SXin LI 	 * The argument should have been u_int, but that's too late
2398ada6f083SXin LI 	 * to change now - it's an API.
2399ada6f083SXin LI 	 */
2400ada6f083SXin LI 	if (tstamp_type < 0)
2401ada6f083SXin LI 		return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
2402ada6f083SXin LI 
2403ada6f083SXin LI 	/*
2404681ed54cSXin LI 	 * If p->tstamp_type_count is 0, we only support PCAP_TSTAMP_HOST;
2405681ed54cSXin LI 	 * the default time stamp type is PCAP_TSTAMP_HOST.
2406d1e87331SXin LI 	 */
2407681ed54cSXin LI 	if (p->tstamp_type_count == 0) {
2408681ed54cSXin LI 		if (tstamp_type == PCAP_TSTAMP_HOST) {
2409681ed54cSXin LI 			p->opt.tstamp_type = tstamp_type;
2410681ed54cSXin LI 			return (0);
2411681ed54cSXin LI 		}
2412681ed54cSXin LI 	} else {
2413d1e87331SXin LI 		/*
2414d1e87331SXin LI 		 * Check whether we claim to support this type of time stamp.
2415d1e87331SXin LI 		 */
2416d1e87331SXin LI 		for (i = 0; i < p->tstamp_type_count; i++) {
2417ada6f083SXin LI 			if (p->tstamp_type_list[i] == (u_int)tstamp_type) {
2418d1e87331SXin LI 				/*
2419d1e87331SXin LI 				 * Yes.
2420d1e87331SXin LI 				 */
2421d1e87331SXin LI 				p->opt.tstamp_type = tstamp_type;
2422d1e87331SXin LI 				return (0);
2423d1e87331SXin LI 			}
2424d1e87331SXin LI 		}
2425681ed54cSXin LI 	}
2426d1e87331SXin LI 
2427d1e87331SXin LI 	/*
2428681ed54cSXin LI 	 * We don't support this type of time stamp.
2429d1e87331SXin LI 	 */
2430d1e87331SXin LI 	return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
2431a8e07101SRui Paulo }
2432a8e07101SRui Paulo 
2433a8e07101SRui Paulo int
2434681ed54cSXin LI pcap_set_immediate_mode(pcap_t *p, int immediate)
2435681ed54cSXin LI {
2436681ed54cSXin LI 	if (pcap_check_activated(p))
2437681ed54cSXin LI 		return (PCAP_ERROR_ACTIVATED);
2438681ed54cSXin LI 	p->opt.immediate = immediate;
2439681ed54cSXin LI 	return (0);
2440681ed54cSXin LI }
2441681ed54cSXin LI 
2442681ed54cSXin LI int
2443a8e07101SRui Paulo pcap_set_buffer_size(pcap_t *p, int buffer_size)
2444a8e07101SRui Paulo {
2445a8e07101SRui Paulo 	if (pcap_check_activated(p))
2446d1e87331SXin LI 		return (PCAP_ERROR_ACTIVATED);
2447ada6f083SXin LI 	if (buffer_size <= 0) {
2448ada6f083SXin LI 		/*
2449ada6f083SXin LI 		 * Silently ignore invalid values.
2450ada6f083SXin LI 		 */
2451ada6f083SXin LI 		return (0);
2452ada6f083SXin LI 	}
2453a8e07101SRui Paulo 	p->opt.buffer_size = buffer_size;
2454d1e87331SXin LI 	return (0);
2455a8e07101SRui Paulo }
2456a8e07101SRui Paulo 
2457a8e07101SRui Paulo int
2458681ed54cSXin LI pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision)
2459681ed54cSXin LI {
2460681ed54cSXin LI 	int i;
2461681ed54cSXin LI 
2462681ed54cSXin LI 	if (pcap_check_activated(p))
2463681ed54cSXin LI 		return (PCAP_ERROR_ACTIVATED);
2464681ed54cSXin LI 
2465681ed54cSXin LI 	/*
2466ada6f083SXin LI 	 * The argument should have been u_int, but that's too late
2467ada6f083SXin LI 	 * to change now - it's an API.
2468ada6f083SXin LI 	 */
2469ada6f083SXin LI 	if (tstamp_precision < 0)
2470ada6f083SXin LI 		return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
2471ada6f083SXin LI 
2472ada6f083SXin LI 	/*
2473681ed54cSXin LI 	 * If p->tstamp_precision_count is 0, we only support setting
2474681ed54cSXin LI 	 * the time stamp precision to microsecond precision; every
2475681ed54cSXin LI 	 * pcap module *MUST* support microsecond precision, even if
2476681ed54cSXin LI 	 * it does so by converting the native precision to
2477681ed54cSXin LI 	 * microseconds.
2478681ed54cSXin LI 	 */
2479681ed54cSXin LI 	if (p->tstamp_precision_count == 0) {
2480681ed54cSXin LI 		if (tstamp_precision == PCAP_TSTAMP_PRECISION_MICRO) {
2481681ed54cSXin LI 			p->opt.tstamp_precision = tstamp_precision;
2482681ed54cSXin LI 			return (0);
2483681ed54cSXin LI 		}
2484681ed54cSXin LI 	} else {
2485681ed54cSXin LI 		/*
2486681ed54cSXin LI 		 * Check whether we claim to support this precision of
2487681ed54cSXin LI 		 * time stamp.
2488681ed54cSXin LI 		 */
2489681ed54cSXin LI 		for (i = 0; i < p->tstamp_precision_count; i++) {
2490ada6f083SXin LI 			if (p->tstamp_precision_list[i] == (u_int)tstamp_precision) {
2491681ed54cSXin LI 				/*
2492681ed54cSXin LI 				 * Yes.
2493681ed54cSXin LI 				 */
2494681ed54cSXin LI 				p->opt.tstamp_precision = tstamp_precision;
2495681ed54cSXin LI 				return (0);
2496681ed54cSXin LI 			}
2497681ed54cSXin LI 		}
2498681ed54cSXin LI 	}
2499681ed54cSXin LI 
2500681ed54cSXin LI 	/*
2501681ed54cSXin LI 	 * We don't support this time stamp precision.
2502681ed54cSXin LI 	 */
2503681ed54cSXin LI 	return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
2504681ed54cSXin LI }
2505681ed54cSXin LI 
2506681ed54cSXin LI int
2507681ed54cSXin LI pcap_get_tstamp_precision(pcap_t *p)
2508681ed54cSXin LI {
2509681ed54cSXin LI         return (p->opt.tstamp_precision);
2510681ed54cSXin LI }
2511681ed54cSXin LI 
2512681ed54cSXin LI int
2513a8e07101SRui Paulo pcap_activate(pcap_t *p)
2514a8e07101SRui Paulo {
2515a8e07101SRui Paulo 	int status;
2516a8e07101SRui Paulo 
2517d1e87331SXin LI 	/*
2518d1e87331SXin LI 	 * Catch attempts to re-activate an already-activated
2519d1e87331SXin LI 	 * pcap_t; this should, for example, catch code that
2520d1e87331SXin LI 	 * calls pcap_open_live() followed by pcap_activate(),
2521d1e87331SXin LI 	 * as some code that showed up in a Stack Exchange
2522d1e87331SXin LI 	 * question did.
2523d1e87331SXin LI 	 */
2524d1e87331SXin LI 	if (pcap_check_activated(p))
2525d1e87331SXin LI 		return (PCAP_ERROR_ACTIVATED);
2526a8e07101SRui Paulo 	status = p->activate_op(p);
2527b00ab754SHans Petter Selasky 	if (status >= 0) {
2528b00ab754SHans Petter Selasky 		/*
2529b00ab754SHans Petter Selasky 		 * If somebody requested non-blocking mode before
2530b00ab754SHans Petter Selasky 		 * calling pcap_activate(), turn it on now.
2531b00ab754SHans Petter Selasky 		 */
2532b00ab754SHans Petter Selasky 		if (p->opt.nonblock) {
2533b00ab754SHans Petter Selasky 			status = p->setnonblock_op(p, 1);
2534b00ab754SHans Petter Selasky 			if (status < 0) {
2535b00ab754SHans Petter Selasky 				/*
2536b00ab754SHans Petter Selasky 				 * Failed.  Undo everything done by
2537b00ab754SHans Petter Selasky 				 * the activate operation.
2538b00ab754SHans Petter Selasky 				 */
2539b00ab754SHans Petter Selasky 				p->cleanup_op(p);
2540b00ab754SHans Petter Selasky 				initialize_ops(p);
2541b00ab754SHans Petter Selasky 				return (status);
2542b00ab754SHans Petter Selasky 			}
2543b00ab754SHans Petter Selasky 		}
2544a8e07101SRui Paulo 		p->activated = 1;
2545b00ab754SHans Petter Selasky 	} else {
2546a0ee43a1SRui Paulo 		if (p->errbuf[0] == '\0') {
2547a0ee43a1SRui Paulo 			/*
2548a0ee43a1SRui Paulo 			 * No error message supplied by the activate routine;
2549a0ee43a1SRui Paulo 			 * for the benefit of programs that don't specially
2550a0ee43a1SRui Paulo 			 * handle errors other than PCAP_ERROR, return the
2551a0ee43a1SRui Paulo 			 * error message corresponding to the status.
2552a0ee43a1SRui Paulo 			 */
2553ada6f083SXin LI 			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
2554a0ee43a1SRui Paulo 			    pcap_statustostr(status));
2555a0ee43a1SRui Paulo 		}
2556a0ee43a1SRui Paulo 
2557a0ee43a1SRui Paulo 		/*
2558a0ee43a1SRui Paulo 		 * Undo any operation pointer setting, etc. done by
2559a0ee43a1SRui Paulo 		 * the activate operation.
2560a0ee43a1SRui Paulo 		 */
2561a0ee43a1SRui Paulo 		initialize_ops(p);
2562a0ee43a1SRui Paulo 	}
2563a8e07101SRui Paulo 	return (status);
2564a8e07101SRui Paulo }
2565a8e07101SRui Paulo 
2566a8e07101SRui Paulo pcap_t *
2567ada6f083SXin LI pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf)
2568a8e07101SRui Paulo {
2569a8e07101SRui Paulo 	pcap_t *p;
2570a8e07101SRui Paulo 	int status;
2571b00ab754SHans Petter Selasky #ifdef ENABLE_REMOTE
2572b00ab754SHans Petter Selasky 	char host[PCAP_BUF_SIZE + 1];
2573b00ab754SHans Petter Selasky 	char port[PCAP_BUF_SIZE + 1];
2574b00ab754SHans Petter Selasky 	char name[PCAP_BUF_SIZE + 1];
2575b00ab754SHans Petter Selasky 	int srctype;
2576b00ab754SHans Petter Selasky 
2577b00ab754SHans Petter Selasky 	/*
2578*57e22627SCy Schubert 	 * A null device name is equivalent to the "any" device -
2579*57e22627SCy Schubert 	 * which might not be supported on this platform, but
2580*57e22627SCy Schubert 	 * this means that you'll get a "not supported" error
2581*57e22627SCy Schubert 	 * rather than, say, a crash when we try to dereference
2582*57e22627SCy Schubert 	 * the null pointer.
2583*57e22627SCy Schubert 	 */
2584*57e22627SCy Schubert 	if (device == NULL)
2585*57e22627SCy Schubert 		device = "any";
2586*57e22627SCy Schubert 
2587*57e22627SCy Schubert 	/*
2588b00ab754SHans Petter Selasky 	 * Retrofit - we have to make older applications compatible with
2589b00ab754SHans Petter Selasky 	 * remote capture.
2590b00ab754SHans Petter Selasky 	 * So we're calling pcap_open_remote() from here; this is a very
2591b00ab754SHans Petter Selasky 	 * dirty hack.
2592b00ab754SHans Petter Selasky 	 * Obviously, we cannot exploit all the new features; for instance,
2593b00ab754SHans Petter Selasky 	 * we cannot send authentication, we cannot use a UDP data connection,
2594b00ab754SHans Petter Selasky 	 * and so on.
2595b00ab754SHans Petter Selasky 	 */
2596b00ab754SHans Petter Selasky 	if (pcap_parsesrcstr(device, &srctype, host, port, name, errbuf))
2597b00ab754SHans Petter Selasky 		return (NULL);
2598b00ab754SHans Petter Selasky 
2599b00ab754SHans Petter Selasky 	if (srctype == PCAP_SRC_IFREMOTE) {
2600b00ab754SHans Petter Selasky 		/*
2601b00ab754SHans Petter Selasky 		 * Although we already have host, port and iface, we prefer
2602b00ab754SHans Petter Selasky 		 * to pass only 'device' to pcap_open_rpcap(), so that it has
2603b00ab754SHans Petter Selasky 		 * to call pcap_parsesrcstr() again.
2604b00ab754SHans Petter Selasky 		 * This is less optimized, but much clearer.
2605b00ab754SHans Petter Selasky 		 */
2606b00ab754SHans Petter Selasky 		return (pcap_open_rpcap(device, snaplen,
2607b00ab754SHans Petter Selasky 		    promisc ? PCAP_OPENFLAG_PROMISCUOUS : 0, to_ms,
2608b00ab754SHans Petter Selasky 		    NULL, errbuf));
2609b00ab754SHans Petter Selasky 	}
2610b00ab754SHans Petter Selasky 	if (srctype == PCAP_SRC_FILE) {
2611b00ab754SHans Petter Selasky 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown URL scheme \"file\"");
2612b00ab754SHans Petter Selasky 		return (NULL);
2613b00ab754SHans Petter Selasky 	}
2614b00ab754SHans Petter Selasky 	if (srctype == PCAP_SRC_IFLOCAL) {
2615b00ab754SHans Petter Selasky 		/*
2616b00ab754SHans Petter Selasky 		 * If it starts with rpcap://, that refers to a local device
2617b00ab754SHans Petter Selasky 		 * (no host part in the URL). Remove the rpcap://, and
2618b00ab754SHans Petter Selasky 		 * fall through to the regular open path.
2619b00ab754SHans Petter Selasky 		 */
2620b00ab754SHans Petter Selasky 		if (strncmp(device, PCAP_SRC_IF_STRING, strlen(PCAP_SRC_IF_STRING)) == 0) {
2621b00ab754SHans Petter Selasky 			size_t len = strlen(device) - strlen(PCAP_SRC_IF_STRING) + 1;
2622b00ab754SHans Petter Selasky 
2623b00ab754SHans Petter Selasky 			if (len > 0)
2624b00ab754SHans Petter Selasky 				device += strlen(PCAP_SRC_IF_STRING);
2625b00ab754SHans Petter Selasky 		}
2626b00ab754SHans Petter Selasky 	}
2627b00ab754SHans Petter Selasky #endif	/* ENABLE_REMOTE */
2628a8e07101SRui Paulo 
2629ada6f083SXin LI 	p = pcap_create(device, errbuf);
2630a8e07101SRui Paulo 	if (p == NULL)
2631a8e07101SRui Paulo 		return (NULL);
2632a8e07101SRui Paulo 	status = pcap_set_snaplen(p, snaplen);
2633a8e07101SRui Paulo 	if (status < 0)
2634a8e07101SRui Paulo 		goto fail;
2635a8e07101SRui Paulo 	status = pcap_set_promisc(p, promisc);
2636a8e07101SRui Paulo 	if (status < 0)
2637a8e07101SRui Paulo 		goto fail;
2638a8e07101SRui Paulo 	status = pcap_set_timeout(p, to_ms);
2639a8e07101SRui Paulo 	if (status < 0)
2640a8e07101SRui Paulo 		goto fail;
2641a8e07101SRui Paulo 	/*
2642a8e07101SRui Paulo 	 * Mark this as opened with pcap_open_live(), so that, for
2643a8e07101SRui Paulo 	 * example, we show the full list of DLT_ values, rather
2644a8e07101SRui Paulo 	 * than just the ones that are compatible with capturing
2645a8e07101SRui Paulo 	 * when not in monitor mode.  That allows existing applications
2646a8e07101SRui Paulo 	 * to work the way they used to work, but allows new applications
2647a8e07101SRui Paulo 	 * that know about the new open API to, for example, find out the
2648a8e07101SRui Paulo 	 * DLT_ values that they can select without changing whether
2649a8e07101SRui Paulo 	 * the adapter is in monitor mode or not.
2650a8e07101SRui Paulo 	 */
2651a8e07101SRui Paulo 	p->oldstyle = 1;
2652a8e07101SRui Paulo 	status = pcap_activate(p);
2653a8e07101SRui Paulo 	if (status < 0)
2654a8e07101SRui Paulo 		goto fail;
2655a8e07101SRui Paulo 	return (p);
2656a8e07101SRui Paulo fail:
2657a0ee43a1SRui Paulo 	if (status == PCAP_ERROR)
2658*57e22627SCy Schubert 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %.*s", device,
2659*57e22627SCy Schubert 		    PCAP_ERRBUF_SIZE - 3, p->errbuf);
2660a0ee43a1SRui Paulo 	else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
2661d1e87331SXin LI 	    status == PCAP_ERROR_PERM_DENIED ||
2662d1e87331SXin LI 	    status == PCAP_ERROR_PROMISC_PERM_DENIED)
2663*57e22627SCy Schubert 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%.*s)", device,
2664*57e22627SCy Schubert 		    pcap_statustostr(status), PCAP_ERRBUF_SIZE - 6, p->errbuf);
2665a8e07101SRui Paulo 	else
2666ada6f083SXin LI 		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device,
2667a8e07101SRui Paulo 		    pcap_statustostr(status));
2668a8e07101SRui Paulo 	pcap_close(p);
2669a8e07101SRui Paulo 	return (NULL);
2670a8e07101SRui Paulo }
2671a8e07101SRui Paulo 
2672681ed54cSXin LI pcap_t *
2673681ed54cSXin LI pcap_open_offline_common(char *ebuf, size_t size)
2674681ed54cSXin LI {
2675681ed54cSXin LI 	pcap_t *p;
2676681ed54cSXin LI 
2677681ed54cSXin LI 	p = pcap_alloc_pcap_t(ebuf, size);
2678681ed54cSXin LI 	if (p == NULL)
2679681ed54cSXin LI 		return (NULL);
2680681ed54cSXin LI 
2681681ed54cSXin LI 	p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
2682681ed54cSXin LI 
2683681ed54cSXin LI 	return (p);
2684681ed54cSXin LI }
2685681ed54cSXin LI 
2686a8e07101SRui Paulo int
26878cf6c252SPaul Traina pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
26888cf6c252SPaul Traina {
2689d1e87331SXin LI 	return (p->read_op(p, cnt, callback, user));
2690feb4ecdbSBruce M Simpson }
2691feb4ecdbSBruce M Simpson 
26928cf6c252SPaul Traina int
26938cf6c252SPaul Traina pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
26948cf6c252SPaul Traina {
2695a4b5b39fSBill Fenner 	register int n;
2696a4b5b39fSBill Fenner 
26978cf6c252SPaul Traina 	for (;;) {
2698681ed54cSXin LI 		if (p->rfile != NULL) {
2699feb4ecdbSBruce M Simpson 			/*
2700feb4ecdbSBruce M Simpson 			 * 0 means EOF, so don't loop if we get 0.
2701feb4ecdbSBruce M Simpson 			 */
2702a4b5b39fSBill Fenner 			n = pcap_offline_read(p, cnt, callback, user);
2703feb4ecdbSBruce M Simpson 		} else {
2704a4b5b39fSBill Fenner 			/*
2705a4b5b39fSBill Fenner 			 * XXX keep reading until we get something
2706a4b5b39fSBill Fenner 			 * (or an error occurs)
2707a4b5b39fSBill Fenner 			 */
2708a4b5b39fSBill Fenner 			do {
2709feb4ecdbSBruce M Simpson 				n = p->read_op(p, cnt, callback, user);
2710a4b5b39fSBill Fenner 			} while (n == 0);
2711a4b5b39fSBill Fenner 		}
27128cf6c252SPaul Traina 		if (n <= 0)
27138cf6c252SPaul Traina 			return (n);
2714681ed54cSXin LI 		if (!PACKET_COUNT_IS_UNLIMITED(cnt)) {
27158cf6c252SPaul Traina 			cnt -= n;
27168cf6c252SPaul Traina 			if (cnt <= 0)
27178cf6c252SPaul Traina 				return (0);
27188cf6c252SPaul Traina 		}
27198cf6c252SPaul Traina 	}
27208cf6c252SPaul Traina }
27218cf6c252SPaul Traina 
2722feb4ecdbSBruce M Simpson /*
2723feb4ecdbSBruce M Simpson  * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate.
2724feb4ecdbSBruce M Simpson  */
2725feb4ecdbSBruce M Simpson void
2726feb4ecdbSBruce M Simpson pcap_breakloop(pcap_t *p)
2727feb4ecdbSBruce M Simpson {
2728feb4ecdbSBruce M Simpson 	p->break_loop = 1;
2729feb4ecdbSBruce M Simpson }
2730feb4ecdbSBruce M Simpson 
27318cf6c252SPaul Traina int
27328cf6c252SPaul Traina pcap_datalink(pcap_t *p)
27338cf6c252SPaul Traina {
2734681ed54cSXin LI 	if (!p->activated)
2735681ed54cSXin LI 		return (PCAP_ERROR_NOT_ACTIVATED);
27368cf6c252SPaul Traina 	return (p->linktype);
27378cf6c252SPaul Traina }
27388cf6c252SPaul Traina 
27398cf6c252SPaul Traina int
2740a8e07101SRui Paulo pcap_datalink_ext(pcap_t *p)
2741a8e07101SRui Paulo {
2742681ed54cSXin LI 	if (!p->activated)
2743681ed54cSXin LI 		return (PCAP_ERROR_NOT_ACTIVATED);
2744a8e07101SRui Paulo 	return (p->linktype_ext);
2745a8e07101SRui Paulo }
2746a8e07101SRui Paulo 
2747a8e07101SRui Paulo int
274809f33d61SBill Fenner pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
274909f33d61SBill Fenner {
2750681ed54cSXin LI 	if (!p->activated)
2751681ed54cSXin LI 		return (PCAP_ERROR_NOT_ACTIVATED);
2752feb4ecdbSBruce M Simpson 	if (p->dlt_count == 0) {
2753feb4ecdbSBruce M Simpson 		/*
2754feb4ecdbSBruce M Simpson 		 * We couldn't fetch the list of DLTs, which means
2755feb4ecdbSBruce M Simpson 		 * this platform doesn't support changing the
2756feb4ecdbSBruce M Simpson 		 * DLT for an interface.  Return a list of DLTs
2757feb4ecdbSBruce M Simpson 		 * containing only the DLT this device supports.
2758feb4ecdbSBruce M Simpson 		 */
2759feb4ecdbSBruce M Simpson 		*dlt_buffer = (int*)malloc(sizeof(**dlt_buffer));
2760feb4ecdbSBruce M Simpson 		if (*dlt_buffer == NULL) {
2761b00ab754SHans Petter Selasky 			pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
2762b00ab754SHans Petter Selasky 			    errno, "malloc");
2763681ed54cSXin LI 			return (PCAP_ERROR);
276409f33d61SBill Fenner 		}
2765feb4ecdbSBruce M Simpson 		**dlt_buffer = p->linktype;
2766feb4ecdbSBruce M Simpson 		return (1);
2767feb4ecdbSBruce M Simpson 	} else {
2768ef96d74fSMax Laier 		*dlt_buffer = (int*)calloc(sizeof(**dlt_buffer), p->dlt_count);
276909f33d61SBill Fenner 		if (*dlt_buffer == NULL) {
2770b00ab754SHans Petter Selasky 			pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
2771b00ab754SHans Petter Selasky 			    errno, "malloc");
2772681ed54cSXin LI 			return (PCAP_ERROR);
277309f33d61SBill Fenner 		}
277409f33d61SBill Fenner 		(void)memcpy(*dlt_buffer, p->dlt_list,
277509f33d61SBill Fenner 		    sizeof(**dlt_buffer) * p->dlt_count);
277609f33d61SBill Fenner 		return (p->dlt_count);
277709f33d61SBill Fenner 	}
2778feb4ecdbSBruce M Simpson }
2779feb4ecdbSBruce M Simpson 
2780a8e07101SRui Paulo /*
2781a8e07101SRui Paulo  * In Windows, you might have a library built with one version of the
2782a8e07101SRui Paulo  * C runtime library and an application built with another version of
2783a8e07101SRui Paulo  * the C runtime library, which means that the library might use one
2784a8e07101SRui Paulo  * version of malloc() and free() and the application might use another
2785a8e07101SRui Paulo  * version of malloc() and free().  If so, that means something
2786a8e07101SRui Paulo  * allocated by the library cannot be freed by the application, so we
2787a8e07101SRui Paulo  * need to have a pcap_free_datalinks() routine to free up the list
2788a8e07101SRui Paulo  * allocated by pcap_list_datalinks(), even though it's just a wrapper
2789a8e07101SRui Paulo  * around free().
2790a8e07101SRui Paulo  */
2791a8e07101SRui Paulo void
2792a8e07101SRui Paulo pcap_free_datalinks(int *dlt_list)
2793a8e07101SRui Paulo {
2794a8e07101SRui Paulo 	free(dlt_list);
2795a8e07101SRui Paulo }
2796a8e07101SRui Paulo 
2797feb4ecdbSBruce M Simpson int
2798feb4ecdbSBruce M Simpson pcap_set_datalink(pcap_t *p, int dlt)
2799feb4ecdbSBruce M Simpson {
2800feb4ecdbSBruce M Simpson 	int i;
2801feb4ecdbSBruce M Simpson 	const char *dlt_name;
2802feb4ecdbSBruce M Simpson 
2803ada6f083SXin LI 	if (dlt < 0)
2804ada6f083SXin LI 		goto unsupported;
2805ada6f083SXin LI 
2806feb4ecdbSBruce M Simpson 	if (p->dlt_count == 0 || p->set_datalink_op == NULL) {
2807feb4ecdbSBruce M Simpson 		/*
2808feb4ecdbSBruce M Simpson 		 * We couldn't fetch the list of DLTs, or we don't
2809feb4ecdbSBruce M Simpson 		 * have a "set datalink" operation, which means
2810feb4ecdbSBruce M Simpson 		 * this platform doesn't support changing the
2811feb4ecdbSBruce M Simpson 		 * DLT for an interface.  Check whether the new
2812feb4ecdbSBruce M Simpson 		 * DLT is the one this interface supports.
2813feb4ecdbSBruce M Simpson 		 */
2814feb4ecdbSBruce M Simpson 		if (p->linktype != dlt)
2815feb4ecdbSBruce M Simpson 			goto unsupported;
2816feb4ecdbSBruce M Simpson 
2817feb4ecdbSBruce M Simpson 		/*
2818feb4ecdbSBruce M Simpson 		 * It is, so there's nothing we need to do here.
2819feb4ecdbSBruce M Simpson 		 */
2820feb4ecdbSBruce M Simpson 		return (0);
2821feb4ecdbSBruce M Simpson 	}
2822feb4ecdbSBruce M Simpson 	for (i = 0; i < p->dlt_count; i++)
2823ada6f083SXin LI 		if (p->dlt_list[i] == (u_int)dlt)
2824feb4ecdbSBruce M Simpson 			break;
2825feb4ecdbSBruce M Simpson 	if (i >= p->dlt_count)
2826feb4ecdbSBruce M Simpson 		goto unsupported;
282704fb2745SSam Leffler 	if (p->dlt_count == 2 && p->dlt_list[0] == DLT_EN10MB &&
282804fb2745SSam Leffler 	    dlt == DLT_DOCSIS) {
282904fb2745SSam Leffler 		/*
283004fb2745SSam Leffler 		 * This is presumably an Ethernet device, as the first
283104fb2745SSam Leffler 		 * link-layer type it offers is DLT_EN10MB, and the only
283204fb2745SSam Leffler 		 * other type it offers is DLT_DOCSIS.  That means that
283304fb2745SSam Leffler 		 * we can't tell the driver to supply DOCSIS link-layer
283404fb2745SSam Leffler 		 * headers - we're just pretending that's what we're
283504fb2745SSam Leffler 		 * getting, as, presumably, we're capturing on a dedicated
283604fb2745SSam Leffler 		 * link to a Cisco Cable Modem Termination System, and
283704fb2745SSam Leffler 		 * it's putting raw DOCSIS frames on the wire inside low-level
283804fb2745SSam Leffler 		 * Ethernet framing.
283904fb2745SSam Leffler 		 */
284004fb2745SSam Leffler 		p->linktype = dlt;
284104fb2745SSam Leffler 		return (0);
284204fb2745SSam Leffler 	}
2843feb4ecdbSBruce M Simpson 	if (p->set_datalink_op(p, dlt) == -1)
2844feb4ecdbSBruce M Simpson 		return (-1);
2845feb4ecdbSBruce M Simpson 	p->linktype = dlt;
2846feb4ecdbSBruce M Simpson 	return (0);
2847feb4ecdbSBruce M Simpson 
2848feb4ecdbSBruce M Simpson unsupported:
2849feb4ecdbSBruce M Simpson 	dlt_name = pcap_datalink_val_to_name(dlt);
2850feb4ecdbSBruce M Simpson 	if (dlt_name != NULL) {
2851ada6f083SXin LI 		(void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
2852feb4ecdbSBruce M Simpson 		    "%s is not one of the DLTs supported by this device",
2853feb4ecdbSBruce M Simpson 		    dlt_name);
2854feb4ecdbSBruce M Simpson 	} else {
2855ada6f083SXin LI 		(void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
2856feb4ecdbSBruce M Simpson 		    "DLT %d is not one of the DLTs supported by this device",
2857feb4ecdbSBruce M Simpson 		    dlt);
2858feb4ecdbSBruce M Simpson 	}
2859feb4ecdbSBruce M Simpson 	return (-1);
2860feb4ecdbSBruce M Simpson }
2861feb4ecdbSBruce M Simpson 
2862feb4ecdbSBruce M Simpson /*
2863feb4ecdbSBruce M Simpson  * This array is designed for mapping upper and lower case letter
2864feb4ecdbSBruce M Simpson  * together for a case independent comparison.  The mappings are
2865feb4ecdbSBruce M Simpson  * based upon ascii character sequences.
2866feb4ecdbSBruce M Simpson  */
2867feb4ecdbSBruce M Simpson static const u_char charmap[] = {
2868feb4ecdbSBruce M Simpson 	(u_char)'\000', (u_char)'\001', (u_char)'\002', (u_char)'\003',
2869feb4ecdbSBruce M Simpson 	(u_char)'\004', (u_char)'\005', (u_char)'\006', (u_char)'\007',
2870feb4ecdbSBruce M Simpson 	(u_char)'\010', (u_char)'\011', (u_char)'\012', (u_char)'\013',
2871feb4ecdbSBruce M Simpson 	(u_char)'\014', (u_char)'\015', (u_char)'\016', (u_char)'\017',
2872feb4ecdbSBruce M Simpson 	(u_char)'\020', (u_char)'\021', (u_char)'\022', (u_char)'\023',
2873feb4ecdbSBruce M Simpson 	(u_char)'\024', (u_char)'\025', (u_char)'\026', (u_char)'\027',
2874feb4ecdbSBruce M Simpson 	(u_char)'\030', (u_char)'\031', (u_char)'\032', (u_char)'\033',
2875feb4ecdbSBruce M Simpson 	(u_char)'\034', (u_char)'\035', (u_char)'\036', (u_char)'\037',
2876feb4ecdbSBruce M Simpson 	(u_char)'\040', (u_char)'\041', (u_char)'\042', (u_char)'\043',
2877feb4ecdbSBruce M Simpson 	(u_char)'\044', (u_char)'\045', (u_char)'\046', (u_char)'\047',
2878feb4ecdbSBruce M Simpson 	(u_char)'\050', (u_char)'\051', (u_char)'\052', (u_char)'\053',
2879feb4ecdbSBruce M Simpson 	(u_char)'\054', (u_char)'\055', (u_char)'\056', (u_char)'\057',
2880feb4ecdbSBruce M Simpson 	(u_char)'\060', (u_char)'\061', (u_char)'\062', (u_char)'\063',
2881feb4ecdbSBruce M Simpson 	(u_char)'\064', (u_char)'\065', (u_char)'\066', (u_char)'\067',
2882feb4ecdbSBruce M Simpson 	(u_char)'\070', (u_char)'\071', (u_char)'\072', (u_char)'\073',
2883feb4ecdbSBruce M Simpson 	(u_char)'\074', (u_char)'\075', (u_char)'\076', (u_char)'\077',
2884feb4ecdbSBruce M Simpson 	(u_char)'\100', (u_char)'\141', (u_char)'\142', (u_char)'\143',
2885feb4ecdbSBruce M Simpson 	(u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
2886feb4ecdbSBruce M Simpson 	(u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
2887feb4ecdbSBruce M Simpson 	(u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
2888feb4ecdbSBruce M Simpson 	(u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
2889feb4ecdbSBruce M Simpson 	(u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
2890feb4ecdbSBruce M Simpson 	(u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\133',
2891feb4ecdbSBruce M Simpson 	(u_char)'\134', (u_char)'\135', (u_char)'\136', (u_char)'\137',
2892feb4ecdbSBruce M Simpson 	(u_char)'\140', (u_char)'\141', (u_char)'\142', (u_char)'\143',
2893feb4ecdbSBruce M Simpson 	(u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
2894feb4ecdbSBruce M Simpson 	(u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
2895feb4ecdbSBruce M Simpson 	(u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
2896feb4ecdbSBruce M Simpson 	(u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
2897feb4ecdbSBruce M Simpson 	(u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
2898feb4ecdbSBruce M Simpson 	(u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\173',
2899feb4ecdbSBruce M Simpson 	(u_char)'\174', (u_char)'\175', (u_char)'\176', (u_char)'\177',
2900feb4ecdbSBruce M Simpson 	(u_char)'\200', (u_char)'\201', (u_char)'\202', (u_char)'\203',
2901feb4ecdbSBruce M Simpson 	(u_char)'\204', (u_char)'\205', (u_char)'\206', (u_char)'\207',
2902feb4ecdbSBruce M Simpson 	(u_char)'\210', (u_char)'\211', (u_char)'\212', (u_char)'\213',
2903feb4ecdbSBruce M Simpson 	(u_char)'\214', (u_char)'\215', (u_char)'\216', (u_char)'\217',
2904feb4ecdbSBruce M Simpson 	(u_char)'\220', (u_char)'\221', (u_char)'\222', (u_char)'\223',
2905feb4ecdbSBruce M Simpson 	(u_char)'\224', (u_char)'\225', (u_char)'\226', (u_char)'\227',
2906feb4ecdbSBruce M Simpson 	(u_char)'\230', (u_char)'\231', (u_char)'\232', (u_char)'\233',
2907feb4ecdbSBruce M Simpson 	(u_char)'\234', (u_char)'\235', (u_char)'\236', (u_char)'\237',
2908feb4ecdbSBruce M Simpson 	(u_char)'\240', (u_char)'\241', (u_char)'\242', (u_char)'\243',
2909feb4ecdbSBruce M Simpson 	(u_char)'\244', (u_char)'\245', (u_char)'\246', (u_char)'\247',
2910feb4ecdbSBruce M Simpson 	(u_char)'\250', (u_char)'\251', (u_char)'\252', (u_char)'\253',
2911feb4ecdbSBruce M Simpson 	(u_char)'\254', (u_char)'\255', (u_char)'\256', (u_char)'\257',
2912feb4ecdbSBruce M Simpson 	(u_char)'\260', (u_char)'\261', (u_char)'\262', (u_char)'\263',
2913feb4ecdbSBruce M Simpson 	(u_char)'\264', (u_char)'\265', (u_char)'\266', (u_char)'\267',
2914feb4ecdbSBruce M Simpson 	(u_char)'\270', (u_char)'\271', (u_char)'\272', (u_char)'\273',
2915feb4ecdbSBruce M Simpson 	(u_char)'\274', (u_char)'\275', (u_char)'\276', (u_char)'\277',
2916feb4ecdbSBruce M Simpson 	(u_char)'\300', (u_char)'\341', (u_char)'\342', (u_char)'\343',
2917feb4ecdbSBruce M Simpson 	(u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347',
2918feb4ecdbSBruce M Simpson 	(u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353',
2919feb4ecdbSBruce M Simpson 	(u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357',
2920feb4ecdbSBruce M Simpson 	(u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363',
2921feb4ecdbSBruce M Simpson 	(u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367',
2922feb4ecdbSBruce M Simpson 	(u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\333',
2923feb4ecdbSBruce M Simpson 	(u_char)'\334', (u_char)'\335', (u_char)'\336', (u_char)'\337',
2924feb4ecdbSBruce M Simpson 	(u_char)'\340', (u_char)'\341', (u_char)'\342', (u_char)'\343',
2925feb4ecdbSBruce M Simpson 	(u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347',
2926feb4ecdbSBruce M Simpson 	(u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353',
2927feb4ecdbSBruce M Simpson 	(u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357',
2928feb4ecdbSBruce M Simpson 	(u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363',
2929feb4ecdbSBruce M Simpson 	(u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367',
2930feb4ecdbSBruce M Simpson 	(u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\373',
2931feb4ecdbSBruce M Simpson 	(u_char)'\374', (u_char)'\375', (u_char)'\376', (u_char)'\377',
2932feb4ecdbSBruce M Simpson };
2933feb4ecdbSBruce M Simpson 
2934feb4ecdbSBruce M Simpson int
2935feb4ecdbSBruce M Simpson pcap_strcasecmp(const char *s1, const char *s2)
2936feb4ecdbSBruce M Simpson {
2937feb4ecdbSBruce M Simpson 	register const u_char	*cm = charmap,
2938ef96d74fSMax Laier 				*us1 = (const u_char *)s1,
2939ef96d74fSMax Laier 				*us2 = (const u_char *)s2;
2940feb4ecdbSBruce M Simpson 
2941feb4ecdbSBruce M Simpson 	while (cm[*us1] == cm[*us2++])
2942feb4ecdbSBruce M Simpson 		if (*us1++ == '\0')
2943feb4ecdbSBruce M Simpson 			return(0);
2944feb4ecdbSBruce M Simpson 	return (cm[*us1] - cm[*--us2]);
2945feb4ecdbSBruce M Simpson }
2946feb4ecdbSBruce M Simpson 
2947d1e87331SXin LI struct dlt_choice {
2948d1e87331SXin LI 	const char *name;
2949d1e87331SXin LI 	const char *description;
2950d1e87331SXin LI 	int	dlt;
2951d1e87331SXin LI };
2952d1e87331SXin LI 
2953ada6f083SXin LI #define DLT_CHOICE(code, description) { #code, description, DLT_ ## code }
2954d1e87331SXin LI #define DLT_CHOICE_SENTINEL { NULL, NULL, 0 }
2955d1e87331SXin LI 
2956d1e87331SXin LI static struct dlt_choice dlt_choices[] = {
2957ada6f083SXin LI 	DLT_CHOICE(NULL, "BSD loopback"),
2958ada6f083SXin LI 	DLT_CHOICE(EN10MB, "Ethernet"),
2959ada6f083SXin LI 	DLT_CHOICE(IEEE802, "Token ring"),
2960ada6f083SXin LI 	DLT_CHOICE(ARCNET, "BSD ARCNET"),
2961ada6f083SXin LI 	DLT_CHOICE(SLIP, "SLIP"),
2962ada6f083SXin LI 	DLT_CHOICE(PPP, "PPP"),
2963ada6f083SXin LI 	DLT_CHOICE(FDDI, "FDDI"),
2964ada6f083SXin LI 	DLT_CHOICE(ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"),
2965ada6f083SXin LI 	DLT_CHOICE(RAW, "Raw IP"),
2966ada6f083SXin LI 	DLT_CHOICE(SLIP_BSDOS, "BSD/OS SLIP"),
2967ada6f083SXin LI 	DLT_CHOICE(PPP_BSDOS, "BSD/OS PPP"),
2968ada6f083SXin LI 	DLT_CHOICE(ATM_CLIP, "Linux Classical IP-over-ATM"),
2969ada6f083SXin LI 	DLT_CHOICE(PPP_SERIAL, "PPP over serial"),
2970ada6f083SXin LI 	DLT_CHOICE(PPP_ETHER, "PPPoE"),
2971ada6f083SXin LI 	DLT_CHOICE(SYMANTEC_FIREWALL, "Symantec Firewall"),
2972ada6f083SXin LI 	DLT_CHOICE(C_HDLC, "Cisco HDLC"),
2973ada6f083SXin LI 	DLT_CHOICE(IEEE802_11, "802.11"),
2974ada6f083SXin LI 	DLT_CHOICE(FRELAY, "Frame Relay"),
2975ada6f083SXin LI 	DLT_CHOICE(LOOP, "OpenBSD loopback"),
2976ada6f083SXin LI 	DLT_CHOICE(ENC, "OpenBSD encapsulated IP"),
2977*57e22627SCy Schubert 	DLT_CHOICE(LINUX_SLL, "Linux cooked v1"),
2978ada6f083SXin LI 	DLT_CHOICE(LTALK, "Localtalk"),
2979ada6f083SXin LI 	DLT_CHOICE(PFLOG, "OpenBSD pflog file"),
2980ada6f083SXin LI 	DLT_CHOICE(PFSYNC, "Packet filter state syncing"),
2981ada6f083SXin LI 	DLT_CHOICE(PRISM_HEADER, "802.11 plus Prism header"),
2982ada6f083SXin LI 	DLT_CHOICE(IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
2983ada6f083SXin LI 	DLT_CHOICE(SUNATM, "Sun raw ATM"),
2984ada6f083SXin LI 	DLT_CHOICE(IEEE802_11_RADIO, "802.11 plus radiotap header"),
2985ada6f083SXin LI 	DLT_CHOICE(ARCNET_LINUX, "Linux ARCNET"),
2986ada6f083SXin LI 	DLT_CHOICE(JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
2987ada6f083SXin LI 	DLT_CHOICE(JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
2988ada6f083SXin LI 	DLT_CHOICE(JUNIPER_ES, "Juniper Encryption Services PIC"),
2989ada6f083SXin LI 	DLT_CHOICE(JUNIPER_GGSN, "Juniper GGSN PIC"),
2990ada6f083SXin LI 	DLT_CHOICE(JUNIPER_MFR, "Juniper FRF.16 Frame Relay"),
2991ada6f083SXin LI 	DLT_CHOICE(JUNIPER_ATM2, "Juniper ATM2 PIC"),
2992ada6f083SXin LI 	DLT_CHOICE(JUNIPER_SERVICES, "Juniper Advanced Services PIC"),
2993ada6f083SXin LI 	DLT_CHOICE(JUNIPER_ATM1, "Juniper ATM1 PIC"),
2994ada6f083SXin LI 	DLT_CHOICE(APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
2995ada6f083SXin LI 	DLT_CHOICE(MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"),
2996ada6f083SXin LI 	DLT_CHOICE(MTP2, "SS7 MTP2"),
2997ada6f083SXin LI 	DLT_CHOICE(MTP3, "SS7 MTP3"),
2998ada6f083SXin LI 	DLT_CHOICE(SCCP, "SS7 SCCP"),
2999ada6f083SXin LI 	DLT_CHOICE(DOCSIS, "DOCSIS"),
3000ada6f083SXin LI 	DLT_CHOICE(LINUX_IRDA, "Linux IrDA"),
3001ada6f083SXin LI 	DLT_CHOICE(IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
3002ada6f083SXin LI 	DLT_CHOICE(JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
3003ada6f083SXin LI 	DLT_CHOICE(BACNET_MS_TP, "BACnet MS/TP"),
3004ada6f083SXin LI 	DLT_CHOICE(PPP_PPPD, "PPP for pppd, with direction flag"),
3005ada6f083SXin LI 	DLT_CHOICE(JUNIPER_PPPOE, "Juniper PPPoE"),
3006ada6f083SXin LI 	DLT_CHOICE(JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
3007ada6f083SXin LI 	DLT_CHOICE(GPRS_LLC, "GPRS LLC"),
3008ada6f083SXin LI 	DLT_CHOICE(GPF_T, "GPF-T"),
3009ada6f083SXin LI 	DLT_CHOICE(GPF_F, "GPF-F"),
3010ada6f083SXin LI 	DLT_CHOICE(JUNIPER_PIC_PEER, "Juniper PIC Peer"),
3011ada6f083SXin LI 	DLT_CHOICE(ERF_ETH, "Ethernet with Endace ERF header"),
3012ada6f083SXin LI 	DLT_CHOICE(ERF_POS, "Packet-over-SONET with Endace ERF header"),
3013ada6f083SXin LI 	DLT_CHOICE(LINUX_LAPD, "Linux vISDN LAPD"),
3014ada6f083SXin LI 	DLT_CHOICE(JUNIPER_ETHER, "Juniper Ethernet"),
3015ada6f083SXin LI 	DLT_CHOICE(JUNIPER_PPP, "Juniper PPP"),
3016ada6f083SXin LI 	DLT_CHOICE(JUNIPER_FRELAY, "Juniper Frame Relay"),
3017ada6f083SXin LI 	DLT_CHOICE(JUNIPER_CHDLC, "Juniper C-HDLC"),
3018ada6f083SXin LI 	DLT_CHOICE(MFR, "FRF.16 Frame Relay"),
3019ada6f083SXin LI 	DLT_CHOICE(JUNIPER_VP, "Juniper Voice PIC"),
3020ada6f083SXin LI 	DLT_CHOICE(A429, "Arinc 429"),
3021ada6f083SXin LI 	DLT_CHOICE(A653_ICM, "Arinc 653 Interpartition Communication"),
3022ada6f083SXin LI 	DLT_CHOICE(USB_FREEBSD, "USB with FreeBSD header"),
3023ada6f083SXin LI 	DLT_CHOICE(BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"),
3024ada6f083SXin LI 	DLT_CHOICE(IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"),
3025ada6f083SXin LI 	DLT_CHOICE(USB_LINUX, "USB with Linux header"),
3026ada6f083SXin LI 	DLT_CHOICE(CAN20B, "Controller Area Network (CAN) v. 2.0B"),
3027ada6f083SXin LI 	DLT_CHOICE(IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"),
3028ada6f083SXin LI 	DLT_CHOICE(PPI, "Per-Packet Information"),
3029ada6f083SXin LI 	DLT_CHOICE(IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"),
3030ada6f083SXin LI 	DLT_CHOICE(JUNIPER_ISM, "Juniper Integrated Service Module"),
3031ada6f083SXin LI 	DLT_CHOICE(IEEE802_15_4, "IEEE 802.15.4 with FCS"),
3032ada6f083SXin LI 	DLT_CHOICE(SITA, "SITA pseudo-header"),
3033ada6f083SXin LI 	DLT_CHOICE(ERF, "Endace ERF header"),
3034ada6f083SXin LI 	DLT_CHOICE(RAIF1, "Ethernet with u10 Networks pseudo-header"),
3035*57e22627SCy Schubert 	DLT_CHOICE(IPMB_KONTRON, "IPMB with Kontron pseudo-header"),
3036ada6f083SXin LI 	DLT_CHOICE(JUNIPER_ST, "Juniper Secure Tunnel"),
3037ada6f083SXin LI 	DLT_CHOICE(BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"),
3038ada6f083SXin LI 	DLT_CHOICE(AX25_KISS, "AX.25 with KISS header"),
3039*57e22627SCy Schubert 	DLT_CHOICE(IPMB_LINUX, "IPMB with Linux/Pigeon Point pseudo-header"),
3040ada6f083SXin LI 	DLT_CHOICE(IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"),
3041ada6f083SXin LI 	DLT_CHOICE(MPLS, "MPLS with label as link-layer header"),
3042ada6f083SXin LI 	DLT_CHOICE(LINUX_EVDEV, "Linux evdev events"),
3043ada6f083SXin LI 	DLT_CHOICE(USB_LINUX_MMAPPED, "USB with padded Linux header"),
3044ada6f083SXin LI 	DLT_CHOICE(DECT, "DECT"),
3045ada6f083SXin LI 	DLT_CHOICE(AOS, "AOS Space Data Link protocol"),
3046ada6f083SXin LI 	DLT_CHOICE(WIHART, "Wireless HART"),
3047ada6f083SXin LI 	DLT_CHOICE(FC_2, "Fibre Channel FC-2"),
3048ada6f083SXin LI 	DLT_CHOICE(FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"),
3049ada6f083SXin LI 	DLT_CHOICE(IPNET, "Solaris ipnet"),
3050ada6f083SXin LI 	DLT_CHOICE(CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"),
3051ada6f083SXin LI 	DLT_CHOICE(IPV4, "Raw IPv4"),
3052ada6f083SXin LI 	DLT_CHOICE(IPV6, "Raw IPv6"),
3053ada6f083SXin LI 	DLT_CHOICE(IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"),
3054ada6f083SXin LI 	DLT_CHOICE(DBUS, "D-Bus"),
3055ada6f083SXin LI 	DLT_CHOICE(JUNIPER_VS, "Juniper Virtual Server"),
3056ada6f083SXin LI 	DLT_CHOICE(JUNIPER_SRX_E2E, "Juniper SRX E2E"),
3057ada6f083SXin LI 	DLT_CHOICE(JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"),
3058ada6f083SXin LI 	DLT_CHOICE(DVB_CI, "DVB-CI"),
3059ada6f083SXin LI 	DLT_CHOICE(MUX27010, "MUX27010"),
3060ada6f083SXin LI 	DLT_CHOICE(STANAG_5066_D_PDU, "STANAG 5066 D_PDUs"),
3061ada6f083SXin LI 	DLT_CHOICE(JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"),
3062ada6f083SXin LI 	DLT_CHOICE(NFLOG, "Linux netfilter log messages"),
3063ada6f083SXin LI 	DLT_CHOICE(NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"),
3064ada6f083SXin LI 	DLT_CHOICE(NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"),
3065ada6f083SXin LI 	DLT_CHOICE(IPOIB, "RFC 4391 IP-over-Infiniband"),
3066ada6f083SXin LI 	DLT_CHOICE(MPEG_2_TS, "MPEG-2 transport stream"),
3067ada6f083SXin LI 	DLT_CHOICE(NG40, "ng40 protocol tester Iub/Iur"),
3068ada6f083SXin LI 	DLT_CHOICE(NFC_LLCP, "NFC LLCP PDUs with pseudo-header"),
3069ada6f083SXin LI 	DLT_CHOICE(INFINIBAND, "InfiniBand"),
3070ada6f083SXin LI 	DLT_CHOICE(SCTP, "SCTP"),
3071ada6f083SXin LI 	DLT_CHOICE(USBPCAP, "USB with USBPcap header"),
3072ada6f083SXin LI 	DLT_CHOICE(RTAC_SERIAL, "Schweitzer Engineering Laboratories RTAC packets"),
3073ada6f083SXin LI 	DLT_CHOICE(BLUETOOTH_LE_LL, "Bluetooth Low Energy air interface"),
3074ada6f083SXin LI 	DLT_CHOICE(NETLINK, "Linux netlink"),
3075ada6f083SXin LI 	DLT_CHOICE(BLUETOOTH_LINUX_MONITOR, "Bluetooth Linux Monitor"),
3076ada6f083SXin LI 	DLT_CHOICE(BLUETOOTH_BREDR_BB, "Bluetooth Basic Rate/Enhanced Data Rate baseband packets"),
3077ada6f083SXin LI 	DLT_CHOICE(BLUETOOTH_LE_LL_WITH_PHDR, "Bluetooth Low Energy air interface with pseudo-header"),
3078ada6f083SXin LI 	DLT_CHOICE(PROFIBUS_DL, "PROFIBUS data link layer"),
3079ada6f083SXin LI 	DLT_CHOICE(PKTAP, "Apple DLT_PKTAP"),
3080ada6f083SXin LI 	DLT_CHOICE(EPON, "Ethernet with 802.3 Clause 65 EPON preamble"),
3081ada6f083SXin LI 	DLT_CHOICE(IPMI_HPM_2, "IPMI trace packets"),
3082ada6f083SXin LI 	DLT_CHOICE(ZWAVE_R1_R2, "Z-Wave RF profile R1 and R2 packets"),
3083ada6f083SXin LI 	DLT_CHOICE(ZWAVE_R3, "Z-Wave RF profile R3 packets"),
3084ada6f083SXin LI 	DLT_CHOICE(WATTSTOPPER_DLM, "WattStopper Digital Lighting Management (DLM) and Legrand Nitoo Open protocol"),
3085ada6f083SXin LI 	DLT_CHOICE(ISO_14443, "ISO 14443 messages"),
3086ada6f083SXin LI 	DLT_CHOICE(RDS, "IEC 62106 Radio Data System groups"),
3087b00ab754SHans Petter Selasky 	DLT_CHOICE(USB_DARWIN, "USB with Darwin header"),
3088b00ab754SHans Petter Selasky 	DLT_CHOICE(OPENFLOW, "OpenBSD DLT_OPENFLOW"),
3089b00ab754SHans Petter Selasky 	DLT_CHOICE(SDLC, "IBM SDLC frames"),
3090b00ab754SHans Petter Selasky 	DLT_CHOICE(TI_LLN_SNIFFER, "TI LLN sniffer frames"),
3091b00ab754SHans Petter Selasky 	DLT_CHOICE(VSOCK, "Linux vsock"),
3092b00ab754SHans Petter Selasky 	DLT_CHOICE(NORDIC_BLE, "Nordic Semiconductor Bluetooth LE sniffer frames"),
3093b00ab754SHans Petter Selasky 	DLT_CHOICE(DOCSIS31_XRA31, "Excentis XRA-31 DOCSIS 3.1 RF sniffer frames"),
3094b00ab754SHans Petter Selasky 	DLT_CHOICE(ETHERNET_MPACKET, "802.3br mPackets"),
3095b00ab754SHans Petter Selasky 	DLT_CHOICE(DISPLAYPORT_AUX, "DisplayPort AUX channel monitoring data"),
3096*57e22627SCy Schubert 	DLT_CHOICE(LINUX_SLL2, "Linux cooked v2"),
3097d1e87331SXin LI 	DLT_CHOICE_SENTINEL
3098d1e87331SXin LI };
3099d1e87331SXin LI 
3100feb4ecdbSBruce M Simpson int
3101feb4ecdbSBruce M Simpson pcap_datalink_name_to_val(const char *name)
3102feb4ecdbSBruce M Simpson {
3103feb4ecdbSBruce M Simpson 	int i;
3104feb4ecdbSBruce M Simpson 
3105feb4ecdbSBruce M Simpson 	for (i = 0; dlt_choices[i].name != NULL; i++) {
3106ada6f083SXin LI 		if (pcap_strcasecmp(dlt_choices[i].name, name) == 0)
3107feb4ecdbSBruce M Simpson 			return (dlt_choices[i].dlt);
3108feb4ecdbSBruce M Simpson 	}
3109feb4ecdbSBruce M Simpson 	return (-1);
3110feb4ecdbSBruce M Simpson }
3111feb4ecdbSBruce M Simpson 
3112feb4ecdbSBruce M Simpson const char *
3113feb4ecdbSBruce M Simpson pcap_datalink_val_to_name(int dlt)
3114feb4ecdbSBruce M Simpson {
3115feb4ecdbSBruce M Simpson 	int i;
3116feb4ecdbSBruce M Simpson 
3117feb4ecdbSBruce M Simpson 	for (i = 0; dlt_choices[i].name != NULL; i++) {
3118feb4ecdbSBruce M Simpson 		if (dlt_choices[i].dlt == dlt)
3119ada6f083SXin LI 			return (dlt_choices[i].name);
3120feb4ecdbSBruce M Simpson 	}
3121feb4ecdbSBruce M Simpson 	return (NULL);
3122feb4ecdbSBruce M Simpson }
3123feb4ecdbSBruce M Simpson 
3124feb4ecdbSBruce M Simpson const char *
3125feb4ecdbSBruce M Simpson pcap_datalink_val_to_description(int dlt)
3126feb4ecdbSBruce M Simpson {
3127feb4ecdbSBruce M Simpson 	int i;
3128feb4ecdbSBruce M Simpson 
3129feb4ecdbSBruce M Simpson 	for (i = 0; dlt_choices[i].name != NULL; i++) {
3130feb4ecdbSBruce M Simpson 		if (dlt_choices[i].dlt == dlt)
3131feb4ecdbSBruce M Simpson 			return (dlt_choices[i].description);
3132feb4ecdbSBruce M Simpson 	}
3133feb4ecdbSBruce M Simpson 	return (NULL);
3134feb4ecdbSBruce M Simpson }
313509f33d61SBill Fenner 
3136*57e22627SCy Schubert const char *
3137*57e22627SCy Schubert pcap_datalink_val_to_description_or_dlt(int dlt)
3138*57e22627SCy Schubert {
3139*57e22627SCy Schubert         static char unkbuf[40];
3140*57e22627SCy Schubert         const char *description;
3141*57e22627SCy Schubert 
3142*57e22627SCy Schubert         description = pcap_datalink_val_to_description(dlt);
3143*57e22627SCy Schubert         if (description != NULL) {
3144*57e22627SCy Schubert                 return description;
3145*57e22627SCy Schubert         } else {
3146*57e22627SCy Schubert                 (void)pcap_snprintf(unkbuf, sizeof(unkbuf), "DLT %u", dlt);
3147*57e22627SCy Schubert                 return unkbuf;
3148*57e22627SCy Schubert         }
3149*57e22627SCy Schubert }
3150*57e22627SCy Schubert 
3151d1e87331SXin LI struct tstamp_type_choice {
3152d1e87331SXin LI 	const char *name;
3153d1e87331SXin LI 	const char *description;
3154d1e87331SXin LI 	int	type;
3155d1e87331SXin LI };
3156d1e87331SXin LI 
3157d1e87331SXin LI static struct tstamp_type_choice tstamp_type_choices[] = {
3158d1e87331SXin LI 	{ "host", "Host", PCAP_TSTAMP_HOST },
3159d1e87331SXin LI 	{ "host_lowprec", "Host, low precision", PCAP_TSTAMP_HOST_LOWPREC },
3160d1e87331SXin LI 	{ "host_hiprec", "Host, high precision", PCAP_TSTAMP_HOST_HIPREC },
3161d1e87331SXin LI 	{ "adapter", "Adapter", PCAP_TSTAMP_ADAPTER },
3162d1e87331SXin LI 	{ "adapter_unsynced", "Adapter, not synced with system time", PCAP_TSTAMP_ADAPTER_UNSYNCED },
3163d1e87331SXin LI 	{ NULL, NULL, 0 }
3164d1e87331SXin LI };
3165d1e87331SXin LI 
3166d1e87331SXin LI int
3167d1e87331SXin LI pcap_tstamp_type_name_to_val(const char *name)
3168d1e87331SXin LI {
3169d1e87331SXin LI 	int i;
3170d1e87331SXin LI 
3171d1e87331SXin LI 	for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
3172d1e87331SXin LI 		if (pcap_strcasecmp(tstamp_type_choices[i].name, name) == 0)
3173d1e87331SXin LI 			return (tstamp_type_choices[i].type);
3174d1e87331SXin LI 	}
3175d1e87331SXin LI 	return (PCAP_ERROR);
3176d1e87331SXin LI }
3177d1e87331SXin LI 
3178d1e87331SXin LI const char *
3179d1e87331SXin LI pcap_tstamp_type_val_to_name(int tstamp_type)
3180d1e87331SXin LI {
3181d1e87331SXin LI 	int i;
3182d1e87331SXin LI 
3183d1e87331SXin LI 	for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
3184d1e87331SXin LI 		if (tstamp_type_choices[i].type == tstamp_type)
3185d1e87331SXin LI 			return (tstamp_type_choices[i].name);
3186d1e87331SXin LI 	}
3187d1e87331SXin LI 	return (NULL);
3188d1e87331SXin LI }
3189d1e87331SXin LI 
3190d1e87331SXin LI const char *
3191d1e87331SXin LI pcap_tstamp_type_val_to_description(int tstamp_type)
3192d1e87331SXin LI {
3193d1e87331SXin LI 	int i;
3194d1e87331SXin LI 
3195d1e87331SXin LI 	for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
3196d1e87331SXin LI 		if (tstamp_type_choices[i].type == tstamp_type)
3197d1e87331SXin LI 			return (tstamp_type_choices[i].description);
3198d1e87331SXin LI 	}
3199d1e87331SXin LI 	return (NULL);
3200d1e87331SXin LI }
3201d1e87331SXin LI 
320209f33d61SBill Fenner int
32038cf6c252SPaul Traina pcap_snapshot(pcap_t *p)
32048cf6c252SPaul Traina {
3205681ed54cSXin LI 	if (!p->activated)
3206681ed54cSXin LI 		return (PCAP_ERROR_NOT_ACTIVATED);
32078cf6c252SPaul Traina 	return (p->snapshot);
32088cf6c252SPaul Traina }
32098cf6c252SPaul Traina 
32108cf6c252SPaul Traina int
32118cf6c252SPaul Traina pcap_is_swapped(pcap_t *p)
32128cf6c252SPaul Traina {
3213681ed54cSXin LI 	if (!p->activated)
3214681ed54cSXin LI 		return (PCAP_ERROR_NOT_ACTIVATED);
3215681ed54cSXin LI 	return (p->swapped);
32168cf6c252SPaul Traina }
32178cf6c252SPaul Traina 
32188cf6c252SPaul Traina int
32198cf6c252SPaul Traina pcap_major_version(pcap_t *p)
32208cf6c252SPaul Traina {
3221681ed54cSXin LI 	if (!p->activated)
3222681ed54cSXin LI 		return (PCAP_ERROR_NOT_ACTIVATED);
3223681ed54cSXin LI 	return (p->version_major);
32248cf6c252SPaul Traina }
32258cf6c252SPaul Traina 
32268cf6c252SPaul Traina int
32278cf6c252SPaul Traina pcap_minor_version(pcap_t *p)
32288cf6c252SPaul Traina {
3229681ed54cSXin LI 	if (!p->activated)
3230681ed54cSXin LI 		return (PCAP_ERROR_NOT_ACTIVATED);
3231681ed54cSXin LI 	return (p->version_minor);
32328cf6c252SPaul Traina }
32338cf6c252SPaul Traina 
3234b00ab754SHans Petter Selasky int
3235b00ab754SHans Petter Selasky pcap_bufsize(pcap_t *p)
3236b00ab754SHans Petter Selasky {
3237b00ab754SHans Petter Selasky 	if (!p->activated)
3238b00ab754SHans Petter Selasky 		return (PCAP_ERROR_NOT_ACTIVATED);
3239b00ab754SHans Petter Selasky 	return (p->bufsize);
3240b00ab754SHans Petter Selasky }
3241b00ab754SHans Petter Selasky 
32428cf6c252SPaul Traina FILE *
32438cf6c252SPaul Traina pcap_file(pcap_t *p)
32448cf6c252SPaul Traina {
3245681ed54cSXin LI 	return (p->rfile);
32468cf6c252SPaul Traina }
32478cf6c252SPaul Traina 
32488cf6c252SPaul Traina int
32498cf6c252SPaul Traina pcap_fileno(pcap_t *p)
32508cf6c252SPaul Traina {
3251ada6f083SXin LI #ifndef _WIN32
32528cf6c252SPaul Traina 	return (p->fd);
3253feb4ecdbSBruce M Simpson #else
3254b00ab754SHans Petter Selasky 	if (p->handle != INVALID_HANDLE_VALUE)
3255b00ab754SHans Petter Selasky 		return ((int)(DWORD)p->handle);
3256feb4ecdbSBruce M Simpson 	else
3257681ed54cSXin LI 		return (PCAP_ERROR);
3258feb4ecdbSBruce M Simpson #endif
32598cf6c252SPaul Traina }
32608cf6c252SPaul Traina 
3261ada6f083SXin LI #if !defined(_WIN32) && !defined(MSDOS)
3262feb4ecdbSBruce M Simpson int
3263feb4ecdbSBruce M Simpson pcap_get_selectable_fd(pcap_t *p)
3264feb4ecdbSBruce M Simpson {
3265feb4ecdbSBruce M Simpson 	return (p->selectable_fd);
3266feb4ecdbSBruce M Simpson }
3267b00ab754SHans Petter Selasky 
3268b00ab754SHans Petter Selasky struct timeval *
3269b00ab754SHans Petter Selasky pcap_get_required_select_timeout(pcap_t *p)
3270b00ab754SHans Petter Selasky {
3271b00ab754SHans Petter Selasky 	return (p->required_select_timeout);
3272b00ab754SHans Petter Selasky }
3273feb4ecdbSBruce M Simpson #endif
3274feb4ecdbSBruce M Simpson 
32758cf6c252SPaul Traina void
3276ada6f083SXin LI pcap_perror(pcap_t *p, const char *prefix)
32778cf6c252SPaul Traina {
32788cf6c252SPaul Traina 	fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
32798cf6c252SPaul Traina }
32808cf6c252SPaul Traina 
32818cf6c252SPaul Traina char *
32828cf6c252SPaul Traina pcap_geterr(pcap_t *p)
32838cf6c252SPaul Traina {
32848cf6c252SPaul Traina 	return (p->errbuf);
32858cf6c252SPaul Traina }
32868cf6c252SPaul Traina 
32870a94d38fSBill Fenner int
32880a94d38fSBill Fenner pcap_getnonblock(pcap_t *p, char *errbuf)
32890a94d38fSBill Fenner {
3290edc89b24SXin LI 	int ret;
3291edc89b24SXin LI 
3292b00ab754SHans Petter Selasky 	ret = p->getnonblock_op(p);
3293edc89b24SXin LI 	if (ret == -1) {
3294edc89b24SXin LI 		/*
3295b00ab754SHans Petter Selasky 		 * The get nonblock operation sets p->errbuf; this
3296b00ab754SHans Petter Selasky 		 * function *shouldn't* have had a separate errbuf
3297b00ab754SHans Petter Selasky 		 * argument, as it didn't need one, but I goofed
3298b00ab754SHans Petter Selasky 		 * when adding it.
3299b00ab754SHans Petter Selasky 		 *
3300b00ab754SHans Petter Selasky 		 * We copy the error message to errbuf, so callers
3301b00ab754SHans Petter Selasky 		 * can find it in either place.
3302edc89b24SXin LI 		 */
3303*57e22627SCy Schubert 		pcap_strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
3304edc89b24SXin LI 	}
3305edc89b24SXin LI 	return (ret);
3306feb4ecdbSBruce M Simpson }
3307feb4ecdbSBruce M Simpson 
3308feb4ecdbSBruce M Simpson /*
3309feb4ecdbSBruce M Simpson  * Get the current non-blocking mode setting, under the assumption that
3310feb4ecdbSBruce M Simpson  * it's just the standard POSIX non-blocking flag.
3311feb4ecdbSBruce M Simpson  */
3312ada6f083SXin LI #if !defined(_WIN32) && !defined(MSDOS)
3313feb4ecdbSBruce M Simpson int
3314b00ab754SHans Petter Selasky pcap_getnonblock_fd(pcap_t *p)
3315feb4ecdbSBruce M Simpson {
33160a94d38fSBill Fenner 	int fdflags;
33170a94d38fSBill Fenner 
33180a94d38fSBill Fenner 	fdflags = fcntl(p->fd, F_GETFL, 0);
33190a94d38fSBill Fenner 	if (fdflags == -1) {
3320b00ab754SHans Petter Selasky 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
3321b00ab754SHans Petter Selasky 		    errno, "F_GETFL");
33220a94d38fSBill Fenner 		return (-1);
33230a94d38fSBill Fenner 	}
33240a94d38fSBill Fenner 	if (fdflags & O_NONBLOCK)
33250a94d38fSBill Fenner 		return (1);
33260a94d38fSBill Fenner 	else
33270a94d38fSBill Fenner 		return (0);
33280a94d38fSBill Fenner }
3329feb4ecdbSBruce M Simpson #endif
33300a94d38fSBill Fenner 
33310a94d38fSBill Fenner int
33320a94d38fSBill Fenner pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
33330a94d38fSBill Fenner {
3334edc89b24SXin LI 	int ret;
3335edc89b24SXin LI 
3336b00ab754SHans Petter Selasky 	ret = p->setnonblock_op(p, nonblock);
3337edc89b24SXin LI 	if (ret == -1) {
3338edc89b24SXin LI 		/*
3339b00ab754SHans Petter Selasky 		 * The set nonblock operation sets p->errbuf; this
3340b00ab754SHans Petter Selasky 		 * function *shouldn't* have had a separate errbuf
3341b00ab754SHans Petter Selasky 		 * argument, as it didn't need one, but I goofed
3342b00ab754SHans Petter Selasky 		 * when adding it.
3343b00ab754SHans Petter Selasky 		 *
3344b00ab754SHans Petter Selasky 		 * We copy the error message to errbuf, so callers
3345b00ab754SHans Petter Selasky 		 * can find it in either place.
3346edc89b24SXin LI 		 */
3347*57e22627SCy Schubert 		pcap_strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
3348edc89b24SXin LI 	}
3349edc89b24SXin LI 	return (ret);
3350feb4ecdbSBruce M Simpson }
3351feb4ecdbSBruce M Simpson 
3352ada6f083SXin LI #if !defined(_WIN32) && !defined(MSDOS)
3353feb4ecdbSBruce M Simpson /*
3354feb4ecdbSBruce M Simpson  * Set non-blocking mode, under the assumption that it's just the
3355feb4ecdbSBruce M Simpson  * standard POSIX non-blocking flag.  (This can be called by the
3356feb4ecdbSBruce M Simpson  * per-platform non-blocking-mode routine if that routine also
3357feb4ecdbSBruce M Simpson  * needs to do some additional work.)
3358feb4ecdbSBruce M Simpson  */
3359feb4ecdbSBruce M Simpson int
3360b00ab754SHans Petter Selasky pcap_setnonblock_fd(pcap_t *p, int nonblock)
3361feb4ecdbSBruce M Simpson {
33620a94d38fSBill Fenner 	int fdflags;
33630a94d38fSBill Fenner 
33640a94d38fSBill Fenner 	fdflags = fcntl(p->fd, F_GETFL, 0);
33650a94d38fSBill Fenner 	if (fdflags == -1) {
3366b00ab754SHans Petter Selasky 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
3367b00ab754SHans Petter Selasky 		    errno, "F_GETFL");
33680a94d38fSBill Fenner 		return (-1);
33690a94d38fSBill Fenner 	}
33700a94d38fSBill Fenner 	if (nonblock)
33710a94d38fSBill Fenner 		fdflags |= O_NONBLOCK;
33720a94d38fSBill Fenner 	else
33730a94d38fSBill Fenner 		fdflags &= ~O_NONBLOCK;
33740a94d38fSBill Fenner 	if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
3375b00ab754SHans Petter Selasky 		pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
3376b00ab754SHans Petter Selasky 		    errno, "F_SETFL");
33770a94d38fSBill Fenner 		return (-1);
33780a94d38fSBill Fenner 	}
33790a94d38fSBill Fenner 	return (0);
33800a94d38fSBill Fenner }
3381feb4ecdbSBruce M Simpson #endif
3382feb4ecdbSBruce M Simpson 
33830a94d38fSBill Fenner /*
3384a8e07101SRui Paulo  * Generate error strings for PCAP_ERROR_ and PCAP_WARNING_ values.
3385a8e07101SRui Paulo  */
3386a8e07101SRui Paulo const char *
3387a8e07101SRui Paulo pcap_statustostr(int errnum)
3388a8e07101SRui Paulo {
3389a8e07101SRui Paulo 	static char ebuf[15+10+1];
3390a8e07101SRui Paulo 
3391a8e07101SRui Paulo 	switch (errnum) {
3392a8e07101SRui Paulo 
3393a8e07101SRui Paulo 	case PCAP_WARNING:
3394a8e07101SRui Paulo 		return("Generic warning");
3395a8e07101SRui Paulo 
3396d1e87331SXin LI 	case PCAP_WARNING_TSTAMP_TYPE_NOTSUP:
3397d1e87331SXin LI 		return ("That type of time stamp is not supported by that device");
3398d1e87331SXin LI 
3399a8e07101SRui Paulo 	case PCAP_WARNING_PROMISC_NOTSUP:
3400a8e07101SRui Paulo 		return ("That device doesn't support promiscuous mode");
3401a8e07101SRui Paulo 
3402a8e07101SRui Paulo 	case PCAP_ERROR:
3403a8e07101SRui Paulo 		return("Generic error");
3404a8e07101SRui Paulo 
3405a8e07101SRui Paulo 	case PCAP_ERROR_BREAK:
3406a8e07101SRui Paulo 		return("Loop terminated by pcap_breakloop");
3407a8e07101SRui Paulo 
3408a8e07101SRui Paulo 	case PCAP_ERROR_NOT_ACTIVATED:
3409a8e07101SRui Paulo 		return("The pcap_t has not been activated");
3410a8e07101SRui Paulo 
3411a8e07101SRui Paulo 	case PCAP_ERROR_ACTIVATED:
3412a8e07101SRui Paulo 		return ("The setting can't be changed after the pcap_t is activated");
3413a8e07101SRui Paulo 
3414a8e07101SRui Paulo 	case PCAP_ERROR_NO_SUCH_DEVICE:
3415a8e07101SRui Paulo 		return ("No such device exists");
3416a8e07101SRui Paulo 
3417a8e07101SRui Paulo 	case PCAP_ERROR_RFMON_NOTSUP:
3418a8e07101SRui Paulo 		return ("That device doesn't support monitor mode");
3419a8e07101SRui Paulo 
3420a8e07101SRui Paulo 	case PCAP_ERROR_NOT_RFMON:
3421a8e07101SRui Paulo 		return ("That operation is supported only in monitor mode");
3422a8e07101SRui Paulo 
3423a8e07101SRui Paulo 	case PCAP_ERROR_PERM_DENIED:
3424a8e07101SRui Paulo 		return ("You don't have permission to capture on that device");
3425a8e07101SRui Paulo 
3426a8e07101SRui Paulo 	case PCAP_ERROR_IFACE_NOT_UP:
3427a8e07101SRui Paulo 		return ("That device is not up");
3428d1e87331SXin LI 
3429d1e87331SXin LI 	case PCAP_ERROR_CANTSET_TSTAMP_TYPE:
3430d1e87331SXin LI 		return ("That device doesn't support setting the time stamp type");
3431d1e87331SXin LI 
3432d1e87331SXin LI 	case PCAP_ERROR_PROMISC_PERM_DENIED:
3433d1e87331SXin LI 		return ("You don't have permission to capture in promiscuous mode on that device");
3434681ed54cSXin LI 
3435681ed54cSXin LI 	case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
3436681ed54cSXin LI 		return ("That device doesn't support that time stamp precision");
3437a8e07101SRui Paulo 	}
3438ada6f083SXin LI 	(void)pcap_snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
3439a8e07101SRui Paulo 	return(ebuf);
3440a8e07101SRui Paulo }
3441a8e07101SRui Paulo 
3442a8e07101SRui Paulo /*
34438cf6c252SPaul Traina  * Not all systems have strerror().
34448cf6c252SPaul Traina  */
3445ef96d74fSMax Laier const char *
34468cf6c252SPaul Traina pcap_strerror(int errnum)
34478cf6c252SPaul Traina {
34488cf6c252SPaul Traina #ifdef HAVE_STRERROR
3449ada6f083SXin LI #ifdef _WIN32
3450ada6f083SXin LI 	static char errbuf[PCAP_ERRBUF_SIZE];
3451b00ab754SHans Petter Selasky 	errno_t err = strerror_s(errbuf, PCAP_ERRBUF_SIZE, errnum);
3452b00ab754SHans Petter Selasky 
3453b00ab754SHans Petter Selasky 	if (err != 0) /* err = 0 if successful */
3454*57e22627SCy Schubert 		pcap_strlcpy(errbuf, "strerror_s() error", PCAP_ERRBUF_SIZE);
3455ada6f083SXin LI 	return (errbuf);
3456ada6f083SXin LI #else
34578cf6c252SPaul Traina 	return (strerror(errnum));
3458ada6f083SXin LI #endif /* _WIN32 */
34598cf6c252SPaul Traina #else
34608cf6c252SPaul Traina 	extern int sys_nerr;
34618cf6c252SPaul Traina 	extern const char *const sys_errlist[];
3462ada6f083SXin LI 	static char errbuf[PCAP_ERRBUF_SIZE];
34638cf6c252SPaul Traina 
34648cf6c252SPaul Traina 	if ((unsigned int)errnum < sys_nerr)
34658cf6c252SPaul Traina 		return ((char *)sys_errlist[errnum]);
3466ada6f083SXin LI 	(void)pcap_snprintf(errbuf, sizeof errbuf, "Unknown error: %d", errnum);
3467ada6f083SXin LI 	return (errbuf);
34688cf6c252SPaul Traina #endif
34698cf6c252SPaul Traina }
34708cf6c252SPaul Traina 
3471feb4ecdbSBruce M Simpson int
3472feb4ecdbSBruce M Simpson pcap_setfilter(pcap_t *p, struct bpf_program *fp)
3473feb4ecdbSBruce M Simpson {
3474d1e87331SXin LI 	return (p->setfilter_op(p, fp));
3475feb4ecdbSBruce M Simpson }
3476feb4ecdbSBruce M Simpson 
3477ee2dd488SSam Leffler /*
3478ee2dd488SSam Leffler  * Set direction flag, which controls whether we accept only incoming
3479ee2dd488SSam Leffler  * packets, only outgoing packets, or both.
3480ee2dd488SSam Leffler  * Note that, depending on the platform, some or all direction arguments
3481ee2dd488SSam Leffler  * might not be supported.
3482ee2dd488SSam Leffler  */
3483ee2dd488SSam Leffler int
34845d18909fSSam Leffler pcap_setdirection(pcap_t *p, pcap_direction_t d)
3485ee2dd488SSam Leffler {
3486ee2dd488SSam Leffler 	if (p->setdirection_op == NULL) {
3487ada6f083SXin LI 		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3488ee2dd488SSam Leffler 		    "Setting direction is not implemented on this platform");
3489d1e87331SXin LI 		return (-1);
3490ee2dd488SSam Leffler 	} else
3491d1e87331SXin LI 		return (p->setdirection_op(p, d));
3492ee2dd488SSam Leffler }
3493ee2dd488SSam Leffler 
3494feb4ecdbSBruce M Simpson int
3495feb4ecdbSBruce M Simpson pcap_stats(pcap_t *p, struct pcap_stat *ps)
3496feb4ecdbSBruce M Simpson {
3497d1e87331SXin LI 	return (p->stats_op(p, ps));
3498feb4ecdbSBruce M Simpson }
3499feb4ecdbSBruce M Simpson 
3500ada6f083SXin LI #ifdef _WIN32
3501ada6f083SXin LI struct pcap_stat *
3502ada6f083SXin LI pcap_stats_ex(pcap_t *p, int *pcap_stat_size)
3503ada6f083SXin LI {
3504ada6f083SXin LI 	return (p->stats_ex_op(p, pcap_stat_size));
3505ada6f083SXin LI }
3506ada6f083SXin LI 
3507a8e07101SRui Paulo int
3508a8e07101SRui Paulo pcap_setbuff(pcap_t *p, int dim)
350904fb2745SSam Leffler {
3510d1e87331SXin LI 	return (p->setbuff_op(p, dim));
3511a8e07101SRui Paulo }
3512a8e07101SRui Paulo 
3513a8e07101SRui Paulo int
3514a8e07101SRui Paulo pcap_setmode(pcap_t *p, int mode)
3515a8e07101SRui Paulo {
3516d1e87331SXin LI 	return (p->setmode_op(p, mode));
3517a8e07101SRui Paulo }
3518a8e07101SRui Paulo 
3519a8e07101SRui Paulo int
3520a8e07101SRui Paulo pcap_setmintocopy(pcap_t *p, int size)
3521a8e07101SRui Paulo {
3522d1e87331SXin LI 	return (p->setmintocopy_op(p, size));
3523a8e07101SRui Paulo }
3524a8e07101SRui Paulo 
3525ada6f083SXin LI HANDLE
3526ada6f083SXin LI pcap_getevent(pcap_t *p)
3527ada6f083SXin LI {
3528ada6f083SXin LI 	return (p->getevent_op(p));
3529ada6f083SXin LI }
3530ada6f083SXin LI 
3531ada6f083SXin LI int
3532ada6f083SXin LI pcap_oid_get_request(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
3533ada6f083SXin LI {
3534ada6f083SXin LI 	return (p->oid_get_request_op(p, oid, data, lenp));
3535ada6f083SXin LI }
3536ada6f083SXin LI 
3537ada6f083SXin LI int
3538ada6f083SXin LI pcap_oid_set_request(pcap_t *p, bpf_u_int32 oid, const void *data, size_t *lenp)
3539ada6f083SXin LI {
3540ada6f083SXin LI 	return (p->oid_set_request_op(p, oid, data, lenp));
3541ada6f083SXin LI }
3542ada6f083SXin LI 
3543ada6f083SXin LI pcap_send_queue *
3544ada6f083SXin LI pcap_sendqueue_alloc(u_int memsize)
3545ada6f083SXin LI {
3546ada6f083SXin LI 	pcap_send_queue *tqueue;
3547ada6f083SXin LI 
3548ada6f083SXin LI 	/* Allocate the queue */
3549ada6f083SXin LI 	tqueue = (pcap_send_queue *)malloc(sizeof(pcap_send_queue));
3550ada6f083SXin LI 	if (tqueue == NULL){
3551ada6f083SXin LI 		return (NULL);
3552ada6f083SXin LI 	}
3553ada6f083SXin LI 
3554ada6f083SXin LI 	/* Allocate the buffer */
3555ada6f083SXin LI 	tqueue->buffer = (char *)malloc(memsize);
3556ada6f083SXin LI 	if (tqueue->buffer == NULL) {
3557ada6f083SXin LI 		free(tqueue);
3558ada6f083SXin LI 		return (NULL);
3559ada6f083SXin LI 	}
3560ada6f083SXin LI 
3561ada6f083SXin LI 	tqueue->maxlen = memsize;
3562ada6f083SXin LI 	tqueue->len = 0;
3563ada6f083SXin LI 
3564ada6f083SXin LI 	return (tqueue);
3565ada6f083SXin LI }
3566ada6f083SXin LI 
3567ada6f083SXin LI void
3568ada6f083SXin LI pcap_sendqueue_destroy(pcap_send_queue *queue)
3569ada6f083SXin LI {
3570ada6f083SXin LI 	free(queue->buffer);
3571ada6f083SXin LI 	free(queue);
3572ada6f083SXin LI }
3573ada6f083SXin LI 
3574ada6f083SXin LI int
3575ada6f083SXin LI pcap_sendqueue_queue(pcap_send_queue *queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
3576ada6f083SXin LI {
3577ada6f083SXin LI 	if (queue->len + sizeof(struct pcap_pkthdr) + pkt_header->caplen > queue->maxlen){
3578ada6f083SXin LI 		return (-1);
3579ada6f083SXin LI 	}
3580ada6f083SXin LI 
3581ada6f083SXin LI 	/* Copy the pcap_pkthdr header*/
3582ada6f083SXin LI 	memcpy(queue->buffer + queue->len, pkt_header, sizeof(struct pcap_pkthdr));
3583ada6f083SXin LI 	queue->len += sizeof(struct pcap_pkthdr);
3584ada6f083SXin LI 
3585ada6f083SXin LI 	/* copy the packet */
3586ada6f083SXin LI 	memcpy(queue->buffer + queue->len, pkt_data, pkt_header->caplen);
3587ada6f083SXin LI 	queue->len += pkt_header->caplen;
3588ada6f083SXin LI 
3589ada6f083SXin LI 	return (0);
3590ada6f083SXin LI }
3591ada6f083SXin LI 
3592ada6f083SXin LI u_int
3593ada6f083SXin LI pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue, int sync)
3594ada6f083SXin LI {
3595ada6f083SXin LI 	return (p->sendqueue_transmit_op(p, queue, sync));
3596ada6f083SXin LI }
3597ada6f083SXin LI 
3598ada6f083SXin LI int
3599ada6f083SXin LI pcap_setuserbuffer(pcap_t *p, int size)
3600ada6f083SXin LI {
3601ada6f083SXin LI 	return (p->setuserbuffer_op(p, size));
3602ada6f083SXin LI }
3603ada6f083SXin LI 
3604ada6f083SXin LI int
3605ada6f083SXin LI pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks)
3606ada6f083SXin LI {
3607ada6f083SXin LI 	return (p->live_dump_op(p, filename, maxsize, maxpacks));
3608ada6f083SXin LI }
3609ada6f083SXin LI 
3610ada6f083SXin LI int
3611ada6f083SXin LI pcap_live_dump_ended(pcap_t *p, int sync)
3612ada6f083SXin LI {
3613ada6f083SXin LI 	return (p->live_dump_ended_op(p, sync));
3614ada6f083SXin LI }
3615ada6f083SXin LI 
3616ada6f083SXin LI PAirpcapHandle
3617ada6f083SXin LI pcap_get_airpcap_handle(pcap_t *p)
3618ada6f083SXin LI {
3619ada6f083SXin LI 	PAirpcapHandle handle;
3620ada6f083SXin LI 
3621ada6f083SXin LI 	handle = p->get_airpcap_handle_op(p);
3622ada6f083SXin LI 	if (handle == NULL) {
3623ada6f083SXin LI 		(void)pcap_snprintf(p->errbuf, sizeof(p->errbuf),
3624ada6f083SXin LI 		    "This isn't an AirPcap device");
3625ada6f083SXin LI 	}
3626ada6f083SXin LI 	return (handle);
3627ada6f083SXin LI }
3628154bbe41SChristian S.J. Peron #endif
3629a8e07101SRui Paulo 
3630a8e07101SRui Paulo /*
3631a8e07101SRui Paulo  * On some platforms, we need to clean up promiscuous or monitor mode
3632a8e07101SRui Paulo  * when we close a device - and we want that to happen even if the
3633a8e07101SRui Paulo  * application just exits without explicitl closing devices.
3634a8e07101SRui Paulo  * On those platforms, we need to register a "close all the pcaps"
3635a8e07101SRui Paulo  * routine to be called when we exit, and need to maintain a list of
3636a8e07101SRui Paulo  * pcaps that need to be closed to clean up modes.
3637a8e07101SRui Paulo  *
3638a8e07101SRui Paulo  * XXX - not thread-safe.
3639a8e07101SRui Paulo  */
3640a8e07101SRui Paulo 
3641a8e07101SRui Paulo /*
3642a8e07101SRui Paulo  * List of pcaps on which we've done something that needs to be
3643a8e07101SRui Paulo  * cleaned up.
3644a8e07101SRui Paulo  * If there are any such pcaps, we arrange to call "pcap_close_all()"
3645a8e07101SRui Paulo  * when we exit, and have it close all of them.
3646a8e07101SRui Paulo  */
3647a8e07101SRui Paulo static struct pcap *pcaps_to_close;
3648a8e07101SRui Paulo 
3649a8e07101SRui Paulo /*
3650a8e07101SRui Paulo  * TRUE if we've already called "atexit()" to cause "pcap_close_all()" to
3651a8e07101SRui Paulo  * be called on exit.
3652a8e07101SRui Paulo  */
3653a8e07101SRui Paulo static int did_atexit;
3654a8e07101SRui Paulo 
3655a8e07101SRui Paulo static void
3656a8e07101SRui Paulo pcap_close_all(void)
3657a8e07101SRui Paulo {
3658a8e07101SRui Paulo 	struct pcap *handle;
3659a8e07101SRui Paulo 
3660a8e07101SRui Paulo 	while ((handle = pcaps_to_close) != NULL)
3661a8e07101SRui Paulo 		pcap_close(handle);
3662a8e07101SRui Paulo }
3663a8e07101SRui Paulo 
3664a8e07101SRui Paulo int
3665a8e07101SRui Paulo pcap_do_addexit(pcap_t *p)
3666a8e07101SRui Paulo {
3667a8e07101SRui Paulo 	/*
3668a8e07101SRui Paulo 	 * If we haven't already done so, arrange to have
3669a8e07101SRui Paulo 	 * "pcap_close_all()" called when we exit.
3670a8e07101SRui Paulo 	 */
3671a8e07101SRui Paulo 	if (!did_atexit) {
3672ada6f083SXin LI 		if (atexit(pcap_close_all) != 0) {
3673a8e07101SRui Paulo 			/*
3674a8e07101SRui Paulo 			 * "atexit()" failed; let our caller know.
3675a8e07101SRui Paulo 			 */
3676*57e22627SCy Schubert 			pcap_strlcpy(p->errbuf, "atexit failed", PCAP_ERRBUF_SIZE);
3677a8e07101SRui Paulo 			return (0);
3678a8e07101SRui Paulo 		}
3679a8e07101SRui Paulo 		did_atexit = 1;
3680a8e07101SRui Paulo 	}
3681a8e07101SRui Paulo 	return (1);
3682a8e07101SRui Paulo }
3683a8e07101SRui Paulo 
3684a8e07101SRui Paulo void
3685a8e07101SRui Paulo pcap_add_to_pcaps_to_close(pcap_t *p)
3686a8e07101SRui Paulo {
3687681ed54cSXin LI 	p->next = pcaps_to_close;
3688a8e07101SRui Paulo 	pcaps_to_close = p;
3689a8e07101SRui Paulo }
3690a8e07101SRui Paulo 
3691a8e07101SRui Paulo void
3692a8e07101SRui Paulo pcap_remove_from_pcaps_to_close(pcap_t *p)
3693a8e07101SRui Paulo {
3694a8e07101SRui Paulo 	pcap_t *pc, *prevpc;
3695a8e07101SRui Paulo 
3696a8e07101SRui Paulo 	for (pc = pcaps_to_close, prevpc = NULL; pc != NULL;
3697681ed54cSXin LI 	    prevpc = pc, pc = pc->next) {
3698a8e07101SRui Paulo 		if (pc == p) {
3699a8e07101SRui Paulo 			/*
3700a8e07101SRui Paulo 			 * Found it.  Remove it from the list.
3701a8e07101SRui Paulo 			 */
3702a8e07101SRui Paulo 			if (prevpc == NULL) {
3703a8e07101SRui Paulo 				/*
3704a8e07101SRui Paulo 				 * It was at the head of the list.
3705a8e07101SRui Paulo 				 */
3706681ed54cSXin LI 				pcaps_to_close = pc->next;
3707a8e07101SRui Paulo 			} else {
3708a8e07101SRui Paulo 				/*
3709a8e07101SRui Paulo 				 * It was in the middle of the list.
3710a8e07101SRui Paulo 				 */
3711681ed54cSXin LI 				prevpc->next = pc->next;
3712a8e07101SRui Paulo 			}
3713a8e07101SRui Paulo 			break;
3714a8e07101SRui Paulo 		}
3715a8e07101SRui Paulo 	}
3716a8e07101SRui Paulo }
3717a8e07101SRui Paulo 
3718a8e07101SRui Paulo void
3719a8e07101SRui Paulo pcap_cleanup_live_common(pcap_t *p)
3720a8e07101SRui Paulo {
3721a8e07101SRui Paulo 	if (p->buffer != NULL) {
372204fb2745SSam Leffler 		free(p->buffer);
3723a8e07101SRui Paulo 		p->buffer = NULL;
3724a8e07101SRui Paulo 	}
3725a8e07101SRui Paulo 	if (p->dlt_list != NULL) {
3726a8e07101SRui Paulo 		free(p->dlt_list);
3727a8e07101SRui Paulo 		p->dlt_list = NULL;
3728a8e07101SRui Paulo 		p->dlt_count = 0;
3729a8e07101SRui Paulo 	}
3730d1e87331SXin LI 	if (p->tstamp_type_list != NULL) {
3731d1e87331SXin LI 		free(p->tstamp_type_list);
3732d1e87331SXin LI 		p->tstamp_type_list = NULL;
3733d1e87331SXin LI 		p->tstamp_type_count = 0;
3734d1e87331SXin LI 	}
3735681ed54cSXin LI 	if (p->tstamp_precision_list != NULL) {
3736681ed54cSXin LI 		free(p->tstamp_precision_list);
3737681ed54cSXin LI 		p->tstamp_precision_list = NULL;
3738681ed54cSXin LI 		p->tstamp_precision_count = 0;
3739681ed54cSXin LI 	}
3740a8e07101SRui Paulo 	pcap_freecode(&p->fcode);
3741ada6f083SXin LI #if !defined(_WIN32) && !defined(MSDOS)
3742a8e07101SRui Paulo 	if (p->fd >= 0) {
374304fb2745SSam Leffler 		close(p->fd);
3744a8e07101SRui Paulo 		p->fd = -1;
3745a8e07101SRui Paulo 	}
3746a0ee43a1SRui Paulo 	p->selectable_fd = -1;
374704fb2745SSam Leffler #endif
374804fb2745SSam Leffler }
374904fb2745SSam Leffler 
375004fb2745SSam Leffler /*
375104fb2745SSam Leffler  * API compatible with WinPcap's "send a packet" routine - returns -1
375204fb2745SSam Leffler  * on error, 0 otherwise.
375304fb2745SSam Leffler  *
375404fb2745SSam Leffler  * XXX - what if we get a short write?
375504fb2745SSam Leffler  */
375604fb2745SSam Leffler int
375704fb2745SSam Leffler pcap_sendpacket(pcap_t *p, const u_char *buf, int size)
375804fb2745SSam Leffler {
375904fb2745SSam Leffler 	if (p->inject_op(p, buf, size) == -1)
376004fb2745SSam Leffler 		return (-1);
376104fb2745SSam Leffler 	return (0);
376204fb2745SSam Leffler }
376304fb2745SSam Leffler 
376404fb2745SSam Leffler /*
376504fb2745SSam Leffler  * API compatible with OpenBSD's "send a packet" routine - returns -1 on
376604fb2745SSam Leffler  * error, number of bytes written otherwise.
376704fb2745SSam Leffler  */
376804fb2745SSam Leffler int
376904fb2745SSam Leffler pcap_inject(pcap_t *p, const void *buf, size_t size)
377004fb2745SSam Leffler {
377104fb2745SSam Leffler 	return (p->inject_op(p, buf, size));
377204fb2745SSam Leffler }
377304fb2745SSam Leffler 
37748cf6c252SPaul Traina void
37758cf6c252SPaul Traina pcap_close(pcap_t *p)
37768cf6c252SPaul Traina {
3777ada6f083SXin LI 	if (p->opt.device != NULL)
3778ada6f083SXin LI 		free(p->opt.device);
3779a8e07101SRui Paulo 	p->cleanup_op(p);
37808cf6c252SPaul Traina 	free(p);
37818cf6c252SPaul Traina }
3782feb4ecdbSBruce M Simpson 
3783feb4ecdbSBruce M Simpson /*
3784a8e07101SRui Paulo  * Given a BPF program, a pcap_pkthdr structure for a packet, and the raw
3785a8e07101SRui Paulo  * data for the packet, check whether the packet passes the filter.
3786a8e07101SRui Paulo  * Returns the return value of the filter program, which will be zero if
3787a8e07101SRui Paulo  * the packet doesn't pass and non-zero if the packet does pass.
3788a8e07101SRui Paulo  */
3789a8e07101SRui Paulo int
3790edc89b24SXin LI pcap_offline_filter(const struct bpf_program *fp, const struct pcap_pkthdr *h,
3791a8e07101SRui Paulo     const u_char *pkt)
3792a8e07101SRui Paulo {
3793edc89b24SXin LI 	const struct bpf_insn *fcode = fp->bf_insns;
3794a8e07101SRui Paulo 
3795a8e07101SRui Paulo 	if (fcode != NULL)
3796a8e07101SRui Paulo 		return (bpf_filter(fcode, pkt, h->len, h->caplen));
3797a8e07101SRui Paulo 	else
3798a8e07101SRui Paulo 		return (0);
3799a8e07101SRui Paulo }
3800a8e07101SRui Paulo 
3801b00ab754SHans Petter Selasky static int
3802b00ab754SHans Petter Selasky pcap_can_set_rfmon_dead(pcap_t *p)
3803b00ab754SHans Petter Selasky {
3804b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3805b00ab754SHans Petter Selasky 	    "Rfmon mode doesn't apply on a pcap_open_dead pcap_t");
3806b00ab754SHans Petter Selasky 	return (PCAP_ERROR);
3807b00ab754SHans Petter Selasky }
3808b00ab754SHans Petter Selasky 
3809b00ab754SHans Petter Selasky static int
3810b00ab754SHans Petter Selasky pcap_read_dead(pcap_t *p, int cnt _U_, pcap_handler callback _U_,
3811b00ab754SHans Petter Selasky     u_char *user _U_)
3812b00ab754SHans Petter Selasky {
3813b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3814b00ab754SHans Petter Selasky 	    "Packets aren't available from a pcap_open_dead pcap_t");
3815b00ab754SHans Petter Selasky 	return (-1);
3816b00ab754SHans Petter Selasky }
3817b00ab754SHans Petter Selasky 
3818b00ab754SHans Petter Selasky static int
3819b00ab754SHans Petter Selasky pcap_inject_dead(pcap_t *p, const void *buf _U_, size_t size _U_)
3820b00ab754SHans Petter Selasky {
3821b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3822b00ab754SHans Petter Selasky 	    "Packets can't be sent on a pcap_open_dead pcap_t");
3823b00ab754SHans Petter Selasky 	return (-1);
3824b00ab754SHans Petter Selasky }
3825b00ab754SHans Petter Selasky 
3826b00ab754SHans Petter Selasky static int
3827b00ab754SHans Petter Selasky pcap_setfilter_dead(pcap_t *p, struct bpf_program *fp _U_)
3828b00ab754SHans Petter Selasky {
3829b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3830b00ab754SHans Petter Selasky 	    "A filter cannot be set on a pcap_open_dead pcap_t");
3831b00ab754SHans Petter Selasky 	return (-1);
3832b00ab754SHans Petter Selasky }
3833b00ab754SHans Petter Selasky 
3834b00ab754SHans Petter Selasky static int
3835b00ab754SHans Petter Selasky pcap_setdirection_dead(pcap_t *p, pcap_direction_t d _U_)
3836b00ab754SHans Petter Selasky {
3837b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3838b00ab754SHans Petter Selasky 	    "The packet direction cannot be set on a pcap_open_dead pcap_t");
3839b00ab754SHans Petter Selasky 	return (-1);
3840b00ab754SHans Petter Selasky }
3841b00ab754SHans Petter Selasky 
3842b00ab754SHans Petter Selasky static int
3843b00ab754SHans Petter Selasky pcap_set_datalink_dead(pcap_t *p, int dlt _U_)
3844b00ab754SHans Petter Selasky {
3845b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3846b00ab754SHans Petter Selasky 	    "The link-layer header type cannot be set on a pcap_open_dead pcap_t");
3847b00ab754SHans Petter Selasky 	return (-1);
3848b00ab754SHans Petter Selasky }
3849b00ab754SHans Petter Selasky 
3850b00ab754SHans Petter Selasky static int
3851b00ab754SHans Petter Selasky pcap_getnonblock_dead(pcap_t *p)
3852b00ab754SHans Petter Selasky {
3853b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3854b00ab754SHans Petter Selasky 	    "A pcap_open_dead pcap_t does not have a non-blocking mode setting");
3855b00ab754SHans Petter Selasky 	return (-1);
3856b00ab754SHans Petter Selasky }
3857b00ab754SHans Petter Selasky 
3858b00ab754SHans Petter Selasky static int
3859b00ab754SHans Petter Selasky pcap_setnonblock_dead(pcap_t *p, int nonblock _U_)
3860b00ab754SHans Petter Selasky {
3861b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3862b00ab754SHans Petter Selasky 	    "A pcap_open_dead pcap_t does not have a non-blocking mode setting");
3863b00ab754SHans Petter Selasky 	return (-1);
3864b00ab754SHans Petter Selasky }
3865b00ab754SHans Petter Selasky 
3866b00ab754SHans Petter Selasky static int
3867b00ab754SHans Petter Selasky pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_)
3868b00ab754SHans Petter Selasky {
3869b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3870b00ab754SHans Petter Selasky 	    "Statistics aren't available from a pcap_open_dead pcap_t");
3871b00ab754SHans Petter Selasky 	return (-1);
3872b00ab754SHans Petter Selasky }
387304fb2745SSam Leffler 
3874ada6f083SXin LI #ifdef _WIN32
3875b00ab754SHans Petter Selasky struct pcap_stat *
3876b00ab754SHans Petter Selasky pcap_stats_ex_dead(pcap_t *p, int *pcap_stat_size _U_)
3877feb4ecdbSBruce M Simpson {
3878b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3879b00ab754SHans Petter Selasky 	    "Statistics aren't available from a pcap_open_dead pcap_t");
3880681ed54cSXin LI 	return (NULL);
3881feb4ecdbSBruce M Simpson }
388204fb2745SSam Leffler 
3883b00ab754SHans Petter Selasky static int
3884b00ab754SHans Petter Selasky pcap_setbuff_dead(pcap_t *p, int dim)
3885ada6f083SXin LI {
3886b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3887b00ab754SHans Petter Selasky 	    "The kernel buffer size cannot be set on a pcap_open_dead pcap_t");
3888b00ab754SHans Petter Selasky 	return (-1);
3889ada6f083SXin LI }
3890ada6f083SXin LI 
3891b00ab754SHans Petter Selasky static int
3892b00ab754SHans Petter Selasky pcap_setmode_dead(pcap_t *p, int mode)
389304fb2745SSam Leffler {
3894b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3895b00ab754SHans Petter Selasky 	    "impossible to set mode on a pcap_open_dead pcap_t");
3896b00ab754SHans Petter Selasky 	return (-1);
389704fb2745SSam Leffler }
389804fb2745SSam Leffler 
3899b00ab754SHans Petter Selasky static int
3900b00ab754SHans Petter Selasky pcap_setmintocopy_dead(pcap_t *p, int size)
3901feb4ecdbSBruce M Simpson {
3902b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3903b00ab754SHans Petter Selasky 	    "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t");
3904b00ab754SHans Petter Selasky 	return (-1);
3905feb4ecdbSBruce M Simpson }
3906b00ab754SHans Petter Selasky 
3907b00ab754SHans Petter Selasky static HANDLE
3908b00ab754SHans Petter Selasky pcap_getevent_dead(pcap_t *p)
3909b00ab754SHans Petter Selasky {
3910b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3911b00ab754SHans Petter Selasky 	    "A pcap_open_dead pcap_t has no event handle");
3912b00ab754SHans Petter Selasky 	return (INVALID_HANDLE_VALUE);
3913b00ab754SHans Petter Selasky }
3914b00ab754SHans Petter Selasky 
3915b00ab754SHans Petter Selasky static int
3916b00ab754SHans Petter Selasky pcap_oid_get_request_dead(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_,
3917b00ab754SHans Petter Selasky     size_t *lenp _U_)
3918b00ab754SHans Petter Selasky {
3919b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3920b00ab754SHans Petter Selasky 	    "An OID get request cannot be performed on a pcap_open_dead pcap_t");
3921b00ab754SHans Petter Selasky 	return (PCAP_ERROR);
3922b00ab754SHans Petter Selasky }
3923b00ab754SHans Petter Selasky 
3924b00ab754SHans Petter Selasky static int
3925b00ab754SHans Petter Selasky pcap_oid_set_request_dead(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
3926b00ab754SHans Petter Selasky     size_t *lenp _U_)
3927b00ab754SHans Petter Selasky {
3928b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3929b00ab754SHans Petter Selasky 	    "An OID set request cannot be performed on a pcap_open_dead pcap_t");
3930b00ab754SHans Petter Selasky 	return (PCAP_ERROR);
3931b00ab754SHans Petter Selasky }
3932b00ab754SHans Petter Selasky 
3933b00ab754SHans Petter Selasky static u_int
3934b00ab754SHans Petter Selasky pcap_sendqueue_transmit_dead(pcap_t *p, pcap_send_queue *queue, int sync)
3935b00ab754SHans Petter Selasky {
3936b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3937b00ab754SHans Petter Selasky 	    "Packets cannot be transmitted on a pcap_open_dead pcap_t");
3938b00ab754SHans Petter Selasky 	return (0);
3939b00ab754SHans Petter Selasky }
3940b00ab754SHans Petter Selasky 
3941b00ab754SHans Petter Selasky static int
3942b00ab754SHans Petter Selasky pcap_setuserbuffer_dead(pcap_t *p, int size)
3943b00ab754SHans Petter Selasky {
3944b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3945b00ab754SHans Petter Selasky 	    "The user buffer cannot be set on a pcap_open_dead pcap_t");
3946b00ab754SHans Petter Selasky 	return (-1);
3947b00ab754SHans Petter Selasky }
3948b00ab754SHans Petter Selasky 
3949b00ab754SHans Petter Selasky static int
3950b00ab754SHans Petter Selasky pcap_live_dump_dead(pcap_t *p, char *filename, int maxsize, int maxpacks)
3951b00ab754SHans Petter Selasky {
3952b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3953b00ab754SHans Petter Selasky 	    "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
3954b00ab754SHans Petter Selasky 	return (-1);
3955b00ab754SHans Petter Selasky }
3956b00ab754SHans Petter Selasky 
3957b00ab754SHans Petter Selasky static int
3958b00ab754SHans Petter Selasky pcap_live_dump_ended_dead(pcap_t *p, int sync)
3959b00ab754SHans Petter Selasky {
3960b00ab754SHans Petter Selasky 	pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3961b00ab754SHans Petter Selasky 	    "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
3962b00ab754SHans Petter Selasky 	return (-1);
3963b00ab754SHans Petter Selasky }
3964b00ab754SHans Petter Selasky 
3965b00ab754SHans Petter Selasky static PAirpcapHandle
3966b00ab754SHans Petter Selasky pcap_get_airpcap_handle_dead(pcap_t *p)
3967b00ab754SHans Petter Selasky {
3968b00ab754SHans Petter Selasky 	return (NULL);
3969b00ab754SHans Petter Selasky }
3970b00ab754SHans Petter Selasky #endif /* _WIN32 */
3971b00ab754SHans Petter Selasky 
3972b00ab754SHans Petter Selasky static void
3973b00ab754SHans Petter Selasky pcap_cleanup_dead(pcap_t *p _U_)
3974b00ab754SHans Petter Selasky {
3975b00ab754SHans Petter Selasky 	/* Nothing to do. */
3976b00ab754SHans Petter Selasky }
3977b00ab754SHans Petter Selasky 
3978b00ab754SHans Petter Selasky pcap_t *
3979b00ab754SHans Petter Selasky pcap_open_dead_with_tstamp_precision(int linktype, int snaplen, u_int precision)
3980b00ab754SHans Petter Selasky {
3981b00ab754SHans Petter Selasky 	pcap_t *p;
3982b00ab754SHans Petter Selasky 
3983b00ab754SHans Petter Selasky 	switch (precision) {
3984b00ab754SHans Petter Selasky 
3985b00ab754SHans Petter Selasky 	case PCAP_TSTAMP_PRECISION_MICRO:
3986b00ab754SHans Petter Selasky 	case PCAP_TSTAMP_PRECISION_NANO:
3987b00ab754SHans Petter Selasky 		break;
3988b00ab754SHans Petter Selasky 
3989b00ab754SHans Petter Selasky 	default:
3990b00ab754SHans Petter Selasky 		/*
3991b00ab754SHans Petter Selasky 		 * This doesn't really matter, but we don't have any way
3992b00ab754SHans Petter Selasky 		 * to report particular errors, so the only failure we
3993b00ab754SHans Petter Selasky 		 * should have is a memory allocation failure.  Just
3994b00ab754SHans Petter Selasky 		 * pick microsecond precision.
3995b00ab754SHans Petter Selasky 		 */
3996b00ab754SHans Petter Selasky 		precision = PCAP_TSTAMP_PRECISION_MICRO;
3997b00ab754SHans Petter Selasky 		break;
3998b00ab754SHans Petter Selasky 	}
3999b00ab754SHans Petter Selasky 	p = malloc(sizeof(*p));
4000b00ab754SHans Petter Selasky 	if (p == NULL)
4001b00ab754SHans Petter Selasky 		return NULL;
4002b00ab754SHans Petter Selasky 	memset (p, 0, sizeof(*p));
4003b00ab754SHans Petter Selasky 	p->snapshot = snaplen;
4004b00ab754SHans Petter Selasky 	p->linktype = linktype;
4005b00ab754SHans Petter Selasky 	p->opt.tstamp_precision = precision;
4006b00ab754SHans Petter Selasky 	p->can_set_rfmon_op = pcap_can_set_rfmon_dead;
4007b00ab754SHans Petter Selasky 	p->read_op = pcap_read_dead;
4008b00ab754SHans Petter Selasky 	p->inject_op = pcap_inject_dead;
4009b00ab754SHans Petter Selasky 	p->setfilter_op = pcap_setfilter_dead;
4010b00ab754SHans Petter Selasky 	p->setdirection_op = pcap_setdirection_dead;
4011b00ab754SHans Petter Selasky 	p->set_datalink_op = pcap_set_datalink_dead;
4012b00ab754SHans Petter Selasky 	p->getnonblock_op = pcap_getnonblock_dead;
4013b00ab754SHans Petter Selasky 	p->setnonblock_op = pcap_setnonblock_dead;
4014b00ab754SHans Petter Selasky 	p->stats_op = pcap_stats_dead;
4015b00ab754SHans Petter Selasky #ifdef _WIN32
4016b00ab754SHans Petter Selasky 	p->stats_ex_op = pcap_stats_ex_dead;
4017b00ab754SHans Petter Selasky 	p->setbuff_op = pcap_setbuff_dead;
4018b00ab754SHans Petter Selasky 	p->setmode_op = pcap_setmode_dead;
4019b00ab754SHans Petter Selasky 	p->setmintocopy_op = pcap_setmintocopy_dead;
4020b00ab754SHans Petter Selasky 	p->getevent_op = pcap_getevent_dead;
4021b00ab754SHans Petter Selasky 	p->oid_get_request_op = pcap_oid_get_request_dead;
4022b00ab754SHans Petter Selasky 	p->oid_set_request_op = pcap_oid_set_request_dead;
4023b00ab754SHans Petter Selasky 	p->sendqueue_transmit_op = pcap_sendqueue_transmit_dead;
4024b00ab754SHans Petter Selasky 	p->setuserbuffer_op = pcap_setuserbuffer_dead;
4025b00ab754SHans Petter Selasky 	p->live_dump_op = pcap_live_dump_dead;
4026b00ab754SHans Petter Selasky 	p->live_dump_ended_op = pcap_live_dump_ended_dead;
4027b00ab754SHans Petter Selasky 	p->get_airpcap_handle_op = pcap_get_airpcap_handle_dead;
4028feb4ecdbSBruce M Simpson #endif
4029b00ab754SHans Petter Selasky 	p->cleanup_op = pcap_cleanup_dead;
4030b00ab754SHans Petter Selasky 
4031b00ab754SHans Petter Selasky 	/*
4032b00ab754SHans Petter Selasky 	 * A "dead" pcap_t never requires special BPF code generation.
4033b00ab754SHans Petter Selasky 	 */
4034b00ab754SHans Petter Selasky 	p->bpf_codegen_flags = 0;
4035b00ab754SHans Petter Selasky 
4036b00ab754SHans Petter Selasky 	p->activated = 1;
4037b00ab754SHans Petter Selasky 	return (p);
4038b00ab754SHans Petter Selasky }
4039b00ab754SHans Petter Selasky 
4040b00ab754SHans Petter Selasky pcap_t *
4041b00ab754SHans Petter Selasky pcap_open_dead(int linktype, int snaplen)
4042b00ab754SHans Petter Selasky {
4043b00ab754SHans Petter Selasky 	return (pcap_open_dead_with_tstamp_precision(linktype, snaplen,
4044b00ab754SHans Petter Selasky 	    PCAP_TSTAMP_PRECISION_MICRO));
4045b00ab754SHans Petter Selasky }
4046ada6f083SXin LI 
4047ada6f083SXin LI #ifdef YYDEBUG
4048ada6f083SXin LI /*
4049ada6f083SXin LI  * Set the internal "debug printout" flag for the filter expression parser.
4050ada6f083SXin LI  * The code to print that stuff is present only if YYDEBUG is defined, so
4051ada6f083SXin LI  * the flag, and the routine to set it, are defined only if YYDEBUG is
4052ada6f083SXin LI  * defined.
4053ada6f083SXin LI  *
4054ada6f083SXin LI  * This is intended for libpcap developers, not for general use.
4055ada6f083SXin LI  * If you want to set these in a program, you'll have to declare this
4056ada6f083SXin LI  * routine yourself, with the appropriate DLL import attribute on Windows;
4057ada6f083SXin LI  * it's not declared in any header file, and won't be declared in any
4058ada6f083SXin LI  * header file provided by libpcap.
4059ada6f083SXin LI  */
4060ada6f083SXin LI PCAP_API void pcap_set_parser_debug(int value);
4061ada6f083SXin LI 
4062ada6f083SXin LI PCAP_API_DEF void
4063ada6f083SXin LI pcap_set_parser_debug(int value)
4064ada6f083SXin LI {
4065ada6f083SXin LI 	pcap_debug = value;
4066ada6f083SXin LI }
4067ada6f083SXin LI #endif
4068