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
34b00ab754SHans Petter Selasky #include <config.h>
35*afdbf109SJoseph Mingrone
36*afdbf109SJoseph Mingrone /* Get the same variety of strerror_r() as Autoconf/CMake has detected. */
37*afdbf109SJoseph Mingrone #include "ftmacros.h"
388cf6c252SPaul Traina
39b00ab754SHans Petter Selasky #include <pcap-types.h>
40b00ab754SHans Petter Selasky #ifndef _WIN32
41b00ab754SHans Petter Selasky #include <sys/param.h>
42b00ab754SHans Petter Selasky #ifndef MSDOS
43b00ab754SHans Petter Selasky #include <sys/file.h>
44a0ee43a1SRui Paulo #endif
45b00ab754SHans Petter Selasky #include <sys/ioctl.h>
46b00ab754SHans Petter Selasky #include <sys/socket.h>
47b00ab754SHans Petter Selasky #ifdef HAVE_SYS_SOCKIO_H
48b00ab754SHans Petter Selasky #include <sys/sockio.h>
49a0ee43a1SRui Paulo #endif
50b00ab754SHans Petter Selasky
51b00ab754SHans Petter Selasky struct mbuf; /* Squelch compiler warnings on some platforms for */
52b00ab754SHans Petter Selasky struct rtentry; /* declarations in <net/if.h> */
53b00ab754SHans Petter Selasky #include <net/if.h>
54b00ab754SHans Petter Selasky #include <netinet/in.h>
55ada6f083SXin LI #endif /* _WIN32 */
568cf6c252SPaul Traina
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 #include <limits.h>
666f9cba8fSJoseph Mingrone
676f9cba8fSJoseph Mingrone #include "diag-control.h"
688cf6c252SPaul Traina
69*afdbf109SJoseph Mingrone #include "thread-local.h"
70*afdbf109SJoseph Mingrone
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
996f9cba8fSJoseph Mingrone #ifdef PCAP_SUPPORT_LINUX_USBMON
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
1276f9cba8fSJoseph Mingrone #ifdef PCAP_SUPPORT_DPDK
1286f9cba8fSJoseph Mingrone #include "pcap-dpdk.h"
1296f9cba8fSJoseph Mingrone #endif
1306f9cba8fSJoseph Mingrone
1316f9cba8fSJoseph Mingrone #ifdef HAVE_AIRPCAP_API
1326f9cba8fSJoseph Mingrone #include "pcap-airpcap.h"
1336f9cba8fSJoseph Mingrone #endif
1346f9cba8fSJoseph Mingrone
135b00ab754SHans Petter Selasky #ifdef _WIN32
136b00ab754SHans Petter Selasky /*
1376f9cba8fSJoseph Mingrone * To quote the WSAStartup() documentation:
1386f9cba8fSJoseph Mingrone *
1396f9cba8fSJoseph Mingrone * The WSAStartup function typically leads to protocol-specific helper
1406f9cba8fSJoseph Mingrone * DLLs being loaded. As a result, the WSAStartup function should not
1416f9cba8fSJoseph Mingrone * be called from the DllMain function in a application DLL. This can
1426f9cba8fSJoseph Mingrone * potentially cause deadlocks.
1436f9cba8fSJoseph Mingrone *
1446f9cba8fSJoseph Mingrone * and the WSACleanup() documentation:
1456f9cba8fSJoseph Mingrone *
1466f9cba8fSJoseph Mingrone * The WSACleanup function typically leads to protocol-specific helper
1476f9cba8fSJoseph Mingrone * DLLs being unloaded. As a result, the WSACleanup function should not
1486f9cba8fSJoseph Mingrone * be called from the DllMain function in a application DLL. This can
1496f9cba8fSJoseph Mingrone * potentially cause deadlocks.
1506f9cba8fSJoseph Mingrone *
1516f9cba8fSJoseph Mingrone * So we don't initialize Winsock in a DllMain() routine.
1526f9cba8fSJoseph Mingrone *
1536f9cba8fSJoseph Mingrone * pcap_init() should be called to initialize pcap on both UN*X and
1546f9cba8fSJoseph Mingrone * Windows; it will initialize Winsock on Windows. (It will also be
1556f9cba8fSJoseph Mingrone * initialized as needed if pcap_init() hasn't been called.)
156b00ab754SHans Petter Selasky */
1576f9cba8fSJoseph Mingrone
1586f9cba8fSJoseph Mingrone /*
159*afdbf109SJoseph Mingrone * Shut down Winsock.
160*afdbf109SJoseph Mingrone *
161*afdbf109SJoseph Mingrone * Ignores the return value of WSACleanup(); given that this is
162*afdbf109SJoseph Mingrone * an atexit() routine, there's nothing much we can do about
163*afdbf109SJoseph Mingrone * a failure.
164*afdbf109SJoseph Mingrone */
165*afdbf109SJoseph Mingrone static void
internal_wsockfini(void)166*afdbf109SJoseph Mingrone internal_wsockfini(void)
167*afdbf109SJoseph Mingrone {
168*afdbf109SJoseph Mingrone WSACleanup();
169*afdbf109SJoseph Mingrone }
170*afdbf109SJoseph Mingrone
171*afdbf109SJoseph Mingrone /*
1726f9cba8fSJoseph Mingrone * Start Winsock.
1736f9cba8fSJoseph Mingrone * Internal routine.
1746f9cba8fSJoseph Mingrone */
1756f9cba8fSJoseph Mingrone static int
internal_wsockinit(char * errbuf)1766f9cba8fSJoseph Mingrone internal_wsockinit(char *errbuf)
177b00ab754SHans Petter Selasky {
1786f9cba8fSJoseph Mingrone WORD wVersionRequested;
1796f9cba8fSJoseph Mingrone WSADATA wsaData;
1806f9cba8fSJoseph Mingrone static int err = -1;
1816f9cba8fSJoseph Mingrone static int done = 0;
1826f9cba8fSJoseph Mingrone int status;
1836f9cba8fSJoseph Mingrone
1846f9cba8fSJoseph Mingrone if (done)
1856f9cba8fSJoseph Mingrone return (err);
1866f9cba8fSJoseph Mingrone
1876f9cba8fSJoseph Mingrone /*
1886f9cba8fSJoseph Mingrone * Versions of Windows that don't support Winsock 2.2 are
1896f9cba8fSJoseph Mingrone * too old for us.
1906f9cba8fSJoseph Mingrone */
1916f9cba8fSJoseph Mingrone wVersionRequested = MAKEWORD(2, 2);
1926f9cba8fSJoseph Mingrone status = WSAStartup(wVersionRequested, &wsaData);
1936f9cba8fSJoseph Mingrone done = 1;
1946f9cba8fSJoseph Mingrone if (status != 0) {
1956f9cba8fSJoseph Mingrone if (errbuf != NULL) {
196*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
1976f9cba8fSJoseph Mingrone status, "WSAStartup() failed");
1986f9cba8fSJoseph Mingrone }
1996f9cba8fSJoseph Mingrone return (err);
2006f9cba8fSJoseph Mingrone }
201*afdbf109SJoseph Mingrone atexit(internal_wsockfini);
2026f9cba8fSJoseph Mingrone err = 0;
2036f9cba8fSJoseph Mingrone return (err);
204b00ab754SHans Petter Selasky }
205b00ab754SHans Petter Selasky
206b00ab754SHans Petter Selasky /*
20757e22627SCy Schubert * Exported in case some applications using WinPcap/Npcap called it,
208b00ab754SHans Petter Selasky * even though it wasn't exported.
209b00ab754SHans Petter Selasky */
210b00ab754SHans Petter Selasky int
wsockinit(void)211b00ab754SHans Petter Selasky wsockinit(void)
212b00ab754SHans Petter Selasky {
2136f9cba8fSJoseph Mingrone return (internal_wsockinit(NULL));
214b00ab754SHans Petter Selasky }
215b00ab754SHans Petter Selasky
216b00ab754SHans Petter Selasky /*
217b00ab754SHans Petter Selasky * This is the exported function; new programs should call this.
2186f9cba8fSJoseph Mingrone * *Newer* programs should call pcap_init().
219b00ab754SHans Petter Selasky */
220b00ab754SHans Petter Selasky int
pcap_wsockinit(void)221b00ab754SHans Petter Selasky pcap_wsockinit(void)
222b00ab754SHans Petter Selasky {
2236f9cba8fSJoseph Mingrone return (internal_wsockinit(NULL));
224b00ab754SHans Petter Selasky }
225b00ab754SHans Petter Selasky #endif /* _WIN32 */
226b00ab754SHans Petter Selasky
227b00ab754SHans Petter Selasky /*
2286f9cba8fSJoseph Mingrone * Do whatever initialization is needed for libpcap.
2296f9cba8fSJoseph Mingrone *
2306f9cba8fSJoseph Mingrone * The argument specifies whether we use the local code page or UTF-8
2316f9cba8fSJoseph Mingrone * for strings; on UN*X, we just assume UTF-8 in places where the encoding
2326f9cba8fSJoseph Mingrone * would matter, whereas, on Windows, we use the local code page for
2336f9cba8fSJoseph Mingrone * PCAP_CHAR_ENC_LOCAL and UTF-8 for PCAP_CHAR_ENC_UTF_8.
2346f9cba8fSJoseph Mingrone *
2356f9cba8fSJoseph Mingrone * On Windows, we also disable the hack in pcap_create() to deal with
2366f9cba8fSJoseph Mingrone * being handed UTF-16 strings, because if the user calls this they're
2376f9cba8fSJoseph Mingrone * explicitly declaring that they will either be passing local code
2386f9cba8fSJoseph Mingrone * page strings or UTF-8 strings, so we don't need to allow UTF-16LE
2396f9cba8fSJoseph Mingrone * strings to be passed. For good measure, on Windows *and* UN*X,
2406f9cba8fSJoseph Mingrone * we disable pcap_lookupdev(), to prevent anybody from even
2416f9cba8fSJoseph Mingrone * *trying* to pass the result of pcap_lookupdev() - which might be
2426f9cba8fSJoseph Mingrone * UTF-16LE on Windows, for ugly compatibility reasons - to pcap_create()
2436f9cba8fSJoseph Mingrone * or pcap_open_live() or pcap_open().
2446f9cba8fSJoseph Mingrone *
2456f9cba8fSJoseph Mingrone * Returns 0 on success, -1 on error.
2466f9cba8fSJoseph Mingrone */
247*afdbf109SJoseph Mingrone int pcapint_new_api; /* pcap_lookupdev() always fails */
248*afdbf109SJoseph Mingrone int pcapint_utf_8_mode; /* Strings should be in UTF-8. */
2496f9cba8fSJoseph Mingrone
2506f9cba8fSJoseph Mingrone int
pcap_init(unsigned int opts,char * errbuf)2516f9cba8fSJoseph Mingrone pcap_init(unsigned int opts, char *errbuf)
2526f9cba8fSJoseph Mingrone {
2536f9cba8fSJoseph Mingrone static int initialized;
2546f9cba8fSJoseph Mingrone
2556f9cba8fSJoseph Mingrone /*
2566f9cba8fSJoseph Mingrone * Don't allow multiple calls that set different modes; that
2576f9cba8fSJoseph Mingrone * may mean a library is initializing pcap in one mode and
2586f9cba8fSJoseph Mingrone * a program using that library, or another library used by
2596f9cba8fSJoseph Mingrone * that program, is initializing it in another mode.
2606f9cba8fSJoseph Mingrone */
2616f9cba8fSJoseph Mingrone switch (opts) {
2626f9cba8fSJoseph Mingrone
2636f9cba8fSJoseph Mingrone case PCAP_CHAR_ENC_LOCAL:
2646f9cba8fSJoseph Mingrone /* Leave "UTF-8 mode" off. */
2656f9cba8fSJoseph Mingrone if (initialized) {
266*afdbf109SJoseph Mingrone if (pcapint_utf_8_mode) {
2676f9cba8fSJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE,
2686f9cba8fSJoseph Mingrone "Multiple pcap_init calls with different character encodings");
2696f9cba8fSJoseph Mingrone return (PCAP_ERROR);
2706f9cba8fSJoseph Mingrone }
2716f9cba8fSJoseph Mingrone }
2726f9cba8fSJoseph Mingrone break;
2736f9cba8fSJoseph Mingrone
2746f9cba8fSJoseph Mingrone case PCAP_CHAR_ENC_UTF_8:
2756f9cba8fSJoseph Mingrone /* Turn on "UTF-8 mode". */
2766f9cba8fSJoseph Mingrone if (initialized) {
277*afdbf109SJoseph Mingrone if (!pcapint_utf_8_mode) {
2786f9cba8fSJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE,
2796f9cba8fSJoseph Mingrone "Multiple pcap_init calls with different character encodings");
2806f9cba8fSJoseph Mingrone return (PCAP_ERROR);
2816f9cba8fSJoseph Mingrone }
2826f9cba8fSJoseph Mingrone }
283*afdbf109SJoseph Mingrone pcapint_utf_8_mode = 1;
2846f9cba8fSJoseph Mingrone break;
2856f9cba8fSJoseph Mingrone
2866f9cba8fSJoseph Mingrone default:
2876f9cba8fSJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE, "Unknown options specified");
2886f9cba8fSJoseph Mingrone return (PCAP_ERROR);
2896f9cba8fSJoseph Mingrone }
2906f9cba8fSJoseph Mingrone
2916f9cba8fSJoseph Mingrone /*
2926f9cba8fSJoseph Mingrone * Turn the appropriate mode on for error messages; those routines
2936f9cba8fSJoseph Mingrone * are also used in rpcapd, which has no access to pcap's internal
2946f9cba8fSJoseph Mingrone * UTF-8 mode flag, so we have to call a routine to set its
2956f9cba8fSJoseph Mingrone * UTF-8 mode flag.
2966f9cba8fSJoseph Mingrone */
297*afdbf109SJoseph Mingrone pcapint_fmt_set_encoding(opts);
2986f9cba8fSJoseph Mingrone
2996f9cba8fSJoseph Mingrone if (initialized) {
3006f9cba8fSJoseph Mingrone /*
3016f9cba8fSJoseph Mingrone * Nothing more to do; for example, on Windows, we've
3026f9cba8fSJoseph Mingrone * already initialized Winsock.
3036f9cba8fSJoseph Mingrone */
3046f9cba8fSJoseph Mingrone return (0);
3056f9cba8fSJoseph Mingrone }
3066f9cba8fSJoseph Mingrone
3076f9cba8fSJoseph Mingrone #ifdef _WIN32
3086f9cba8fSJoseph Mingrone /*
3096f9cba8fSJoseph Mingrone * Now set up Winsock.
3106f9cba8fSJoseph Mingrone */
3116f9cba8fSJoseph Mingrone if (internal_wsockinit(errbuf) == -1) {
3126f9cba8fSJoseph Mingrone /* Failed. */
3136f9cba8fSJoseph Mingrone return (PCAP_ERROR);
3146f9cba8fSJoseph Mingrone }
3156f9cba8fSJoseph Mingrone #endif
3166f9cba8fSJoseph Mingrone
3176f9cba8fSJoseph Mingrone /*
3186f9cba8fSJoseph Mingrone * We're done.
3196f9cba8fSJoseph Mingrone */
3206f9cba8fSJoseph Mingrone initialized = 1;
321*afdbf109SJoseph Mingrone pcapint_new_api = 1;
3226f9cba8fSJoseph Mingrone return (0);
3236f9cba8fSJoseph Mingrone }
3246f9cba8fSJoseph Mingrone
3256f9cba8fSJoseph Mingrone /*
326b00ab754SHans Petter Selasky * String containing the library version.
327b00ab754SHans Petter Selasky * Not explicitly exported via a header file - the right API to use
328b00ab754SHans Petter Selasky * is pcap_lib_version() - but some programs included it, so we
329b00ab754SHans Petter Selasky * provide it.
330b00ab754SHans Petter Selasky *
331b00ab754SHans Petter Selasky * We declare it here, right before defining it, to squelch any
332b00ab754SHans Petter Selasky * warnings we might get from compilers about the lack of a
333b00ab754SHans Petter Selasky * declaration.
334b00ab754SHans Petter Selasky */
335b00ab754SHans Petter Selasky PCAP_API char pcap_version[];
336b00ab754SHans Petter Selasky PCAP_API_DEF char pcap_version[] = PACKAGE_VERSION;
337b00ab754SHans Petter Selasky
33857e22627SCy Schubert static void
pcap_set_not_initialized_message(pcap_t * pcap)33957e22627SCy Schubert pcap_set_not_initialized_message(pcap_t *pcap)
340a8e07101SRui Paulo {
341b00ab754SHans Petter Selasky if (pcap->activated) {
342b00ab754SHans Petter Selasky /* A module probably forgot to set the function pointer */
3436f9cba8fSJoseph Mingrone (void)snprintf(pcap->errbuf, sizeof(pcap->errbuf),
344b00ab754SHans Petter Selasky "This operation isn't properly handled by that device");
34557e22627SCy Schubert return;
346b00ab754SHans Petter Selasky }
347ada6f083SXin LI /* in case the caller doesn't check for PCAP_ERROR_NOT_ACTIVATED */
3486f9cba8fSJoseph Mingrone (void)snprintf(pcap->errbuf, sizeof(pcap->errbuf),
349ada6f083SXin LI "This handle hasn't been activated yet");
35057e22627SCy Schubert }
35157e22627SCy Schubert
35257e22627SCy Schubert static int
pcap_read_not_initialized(pcap_t * pcap,int cnt _U_,pcap_handler callback _U_,u_char * user _U_)35357e22627SCy Schubert pcap_read_not_initialized(pcap_t *pcap, int cnt _U_, pcap_handler callback _U_,
35457e22627SCy Schubert u_char *user _U_)
35557e22627SCy Schubert {
35657e22627SCy Schubert pcap_set_not_initialized_message(pcap);
35757e22627SCy Schubert /* this means 'not initialized' */
35857e22627SCy Schubert return (PCAP_ERROR_NOT_ACTIVATED);
35957e22627SCy Schubert }
36057e22627SCy Schubert
36157e22627SCy Schubert static int
pcap_inject_not_initialized(pcap_t * pcap,const void * buf _U_,int size _U_)3626f9cba8fSJoseph Mingrone pcap_inject_not_initialized(pcap_t *pcap, const void * buf _U_, int size _U_)
36357e22627SCy Schubert {
36457e22627SCy Schubert pcap_set_not_initialized_message(pcap);
36557e22627SCy Schubert /* this means 'not initialized' */
36657e22627SCy Schubert return (PCAP_ERROR_NOT_ACTIVATED);
36757e22627SCy Schubert }
36857e22627SCy Schubert
36957e22627SCy Schubert static int
pcap_setfilter_not_initialized(pcap_t * pcap,struct bpf_program * fp _U_)37057e22627SCy Schubert pcap_setfilter_not_initialized(pcap_t *pcap, struct bpf_program *fp _U_)
37157e22627SCy Schubert {
37257e22627SCy Schubert pcap_set_not_initialized_message(pcap);
37357e22627SCy Schubert /* this means 'not initialized' */
37457e22627SCy Schubert return (PCAP_ERROR_NOT_ACTIVATED);
37557e22627SCy Schubert }
37657e22627SCy Schubert
37757e22627SCy Schubert static int
pcap_setdirection_not_initialized(pcap_t * pcap,pcap_direction_t d _U_)37857e22627SCy Schubert pcap_setdirection_not_initialized(pcap_t *pcap, pcap_direction_t d _U_)
37957e22627SCy Schubert {
38057e22627SCy Schubert pcap_set_not_initialized_message(pcap);
38157e22627SCy Schubert /* this means 'not initialized' */
38257e22627SCy Schubert return (PCAP_ERROR_NOT_ACTIVATED);
38357e22627SCy Schubert }
38457e22627SCy Schubert
38557e22627SCy Schubert static int
pcap_set_datalink_not_initialized(pcap_t * pcap,int dlt _U_)38657e22627SCy Schubert pcap_set_datalink_not_initialized(pcap_t *pcap, int dlt _U_)
38757e22627SCy Schubert {
38857e22627SCy Schubert pcap_set_not_initialized_message(pcap);
38957e22627SCy Schubert /* this means 'not initialized' */
39057e22627SCy Schubert return (PCAP_ERROR_NOT_ACTIVATED);
39157e22627SCy Schubert }
39257e22627SCy Schubert
39357e22627SCy Schubert static int
pcap_getnonblock_not_initialized(pcap_t * pcap)39457e22627SCy Schubert pcap_getnonblock_not_initialized(pcap_t *pcap)
39557e22627SCy Schubert {
39657e22627SCy Schubert pcap_set_not_initialized_message(pcap);
39757e22627SCy Schubert /* this means 'not initialized' */
39857e22627SCy Schubert return (PCAP_ERROR_NOT_ACTIVATED);
39957e22627SCy Schubert }
40057e22627SCy Schubert
40157e22627SCy Schubert static int
pcap_stats_not_initialized(pcap_t * pcap,struct pcap_stat * ps _U_)40257e22627SCy Schubert pcap_stats_not_initialized(pcap_t *pcap, struct pcap_stat *ps _U_)
40357e22627SCy Schubert {
40457e22627SCy Schubert pcap_set_not_initialized_message(pcap);
405a8e07101SRui Paulo /* this means 'not initialized' */
406d1e87331SXin LI return (PCAP_ERROR_NOT_ACTIVATED);
407a8e07101SRui Paulo }
408a8e07101SRui Paulo
409ada6f083SXin LI #ifdef _WIN32
4106f9cba8fSJoseph Mingrone static struct pcap_stat *
pcap_stats_ex_not_initialized(pcap_t * pcap,int * pcap_stat_size _U_)41157e22627SCy Schubert pcap_stats_ex_not_initialized(pcap_t *pcap, int *pcap_stat_size _U_)
412681ed54cSXin LI {
41357e22627SCy Schubert pcap_set_not_initialized_message(pcap);
414b00ab754SHans Petter Selasky return (NULL);
415b00ab754SHans Petter Selasky }
41657e22627SCy Schubert
41757e22627SCy Schubert static int
pcap_setbuff_not_initialized(pcap_t * pcap,int dim _U_)41857e22627SCy Schubert pcap_setbuff_not_initialized(pcap_t *pcap, int dim _U_)
41957e22627SCy Schubert {
42057e22627SCy Schubert pcap_set_not_initialized_message(pcap);
42157e22627SCy Schubert /* this means 'not initialized' */
42257e22627SCy Schubert return (PCAP_ERROR_NOT_ACTIVATED);
42357e22627SCy Schubert }
42457e22627SCy Schubert
42557e22627SCy Schubert static int
pcap_setmode_not_initialized(pcap_t * pcap,int mode _U_)42657e22627SCy Schubert pcap_setmode_not_initialized(pcap_t *pcap, int mode _U_)
42757e22627SCy Schubert {
42857e22627SCy Schubert pcap_set_not_initialized_message(pcap);
42957e22627SCy Schubert /* this means 'not initialized' */
43057e22627SCy Schubert return (PCAP_ERROR_NOT_ACTIVATED);
43157e22627SCy Schubert }
43257e22627SCy Schubert
43357e22627SCy Schubert static int
pcap_setmintocopy_not_initialized(pcap_t * pcap,int size _U_)43457e22627SCy Schubert pcap_setmintocopy_not_initialized(pcap_t *pcap, int size _U_)
43557e22627SCy Schubert {
43657e22627SCy Schubert pcap_set_not_initialized_message(pcap);
43757e22627SCy Schubert /* this means 'not initialized' */
43857e22627SCy Schubert return (PCAP_ERROR_NOT_ACTIVATED);
439ada6f083SXin LI }
440ada6f083SXin LI
441ada6f083SXin LI static HANDLE
pcap_getevent_not_initialized(pcap_t * pcap)442ada6f083SXin LI pcap_getevent_not_initialized(pcap_t *pcap)
443ada6f083SXin LI {
44457e22627SCy Schubert pcap_set_not_initialized_message(pcap);
445b00ab754SHans Petter Selasky return (INVALID_HANDLE_VALUE);
446b00ab754SHans Petter Selasky }
44757e22627SCy Schubert
44857e22627SCy Schubert static int
pcap_oid_get_request_not_initialized(pcap_t * pcap,bpf_u_int32 oid _U_,void * data _U_,size_t * lenp _U_)44957e22627SCy Schubert pcap_oid_get_request_not_initialized(pcap_t *pcap, bpf_u_int32 oid _U_,
45057e22627SCy Schubert void *data _U_, size_t *lenp _U_)
45157e22627SCy Schubert {
45257e22627SCy Schubert pcap_set_not_initialized_message(pcap);
45357e22627SCy Schubert return (PCAP_ERROR_NOT_ACTIVATED);
45457e22627SCy Schubert }
45557e22627SCy Schubert
45657e22627SCy Schubert static int
pcap_oid_set_request_not_initialized(pcap_t * pcap,bpf_u_int32 oid _U_,const void * data _U_,size_t * lenp _U_)45757e22627SCy Schubert pcap_oid_set_request_not_initialized(pcap_t *pcap, bpf_u_int32 oid _U_,
45857e22627SCy Schubert const void *data _U_, size_t *lenp _U_)
45957e22627SCy Schubert {
46057e22627SCy Schubert pcap_set_not_initialized_message(pcap);
46157e22627SCy Schubert return (PCAP_ERROR_NOT_ACTIVATED);
462ada6f083SXin LI }
463ada6f083SXin LI
464ada6f083SXin LI static u_int
pcap_sendqueue_transmit_not_initialized(pcap_t * pcap,pcap_send_queue * queue _U_,int sync _U_)4656f9cba8fSJoseph Mingrone pcap_sendqueue_transmit_not_initialized(pcap_t *pcap, pcap_send_queue* queue _U_,
4666f9cba8fSJoseph Mingrone int sync _U_)
467ada6f083SXin LI {
46857e22627SCy Schubert pcap_set_not_initialized_message(pcap);
469b00ab754SHans Petter Selasky return (0);
470b00ab754SHans Petter Selasky }
47157e22627SCy Schubert
47257e22627SCy Schubert static int
pcap_setuserbuffer_not_initialized(pcap_t * pcap,int size _U_)47357e22627SCy Schubert pcap_setuserbuffer_not_initialized(pcap_t *pcap, int size _U_)
47457e22627SCy Schubert {
47557e22627SCy Schubert pcap_set_not_initialized_message(pcap);
47657e22627SCy Schubert return (PCAP_ERROR_NOT_ACTIVATED);
47757e22627SCy Schubert }
47857e22627SCy Schubert
47957e22627SCy Schubert static int
pcap_live_dump_not_initialized(pcap_t * pcap,char * filename _U_,int maxsize _U_,int maxpacks _U_)48057e22627SCy Schubert pcap_live_dump_not_initialized(pcap_t *pcap, char *filename _U_, int maxsize _U_,
48157e22627SCy Schubert int maxpacks _U_)
48257e22627SCy Schubert {
48357e22627SCy Schubert pcap_set_not_initialized_message(pcap);
48457e22627SCy Schubert return (PCAP_ERROR_NOT_ACTIVATED);
48557e22627SCy Schubert }
48657e22627SCy Schubert
48757e22627SCy Schubert static int
pcap_live_dump_ended_not_initialized(pcap_t * pcap,int sync _U_)48857e22627SCy Schubert pcap_live_dump_ended_not_initialized(pcap_t *pcap, int sync _U_)
48957e22627SCy Schubert {
49057e22627SCy Schubert pcap_set_not_initialized_message(pcap);
49157e22627SCy Schubert return (PCAP_ERROR_NOT_ACTIVATED);
492ada6f083SXin LI }
493ada6f083SXin LI
494ada6f083SXin LI static PAirpcapHandle
pcap_get_airpcap_handle_not_initialized(pcap_t * pcap)495ada6f083SXin LI pcap_get_airpcap_handle_not_initialized(pcap_t *pcap)
496ada6f083SXin LI {
49757e22627SCy Schubert pcap_set_not_initialized_message(pcap);
498681ed54cSXin LI return (NULL);
499681ed54cSXin LI }
500681ed54cSXin LI #endif
501681ed54cSXin LI
502a8e07101SRui Paulo /*
503a8e07101SRui Paulo * Returns 1 if rfmon mode can be set on the pcap_t, 0 if it can't,
504a8e07101SRui Paulo * a PCAP_ERROR value on an error.
505a8e07101SRui Paulo */
506a8e07101SRui Paulo int
pcap_can_set_rfmon(pcap_t * p)507a8e07101SRui Paulo pcap_can_set_rfmon(pcap_t *p)
508a8e07101SRui Paulo {
509a8e07101SRui Paulo return (p->can_set_rfmon_op(p));
510a8e07101SRui Paulo }
511a8e07101SRui Paulo
512a8e07101SRui Paulo /*
513a8e07101SRui Paulo * For systems where rfmon mode is never supported.
514a8e07101SRui Paulo */
515a8e07101SRui Paulo static int
pcap_cant_set_rfmon(pcap_t * p _U_)516a8e07101SRui Paulo pcap_cant_set_rfmon(pcap_t *p _U_)
517a8e07101SRui Paulo {
518a8e07101SRui Paulo return (0);
519a8e07101SRui Paulo }
520a8e07101SRui Paulo
521a8e07101SRui Paulo /*
522d1e87331SXin LI * Sets *tstamp_typesp to point to an array 1 or more supported time stamp
523d1e87331SXin LI * types; the return value is the number of supported time stamp types.
524d1e87331SXin LI * The list should be freed by a call to pcap_free_tstamp_types() when
525d1e87331SXin LI * you're done with it.
526d1e87331SXin LI *
527d1e87331SXin LI * A return value of 0 means "you don't get a choice of time stamp type",
528d1e87331SXin LI * in which case *tstamp_typesp is set to null.
529d1e87331SXin LI *
530d1e87331SXin LI * PCAP_ERROR is returned on error.
531d1e87331SXin LI */
532d1e87331SXin LI int
pcap_list_tstamp_types(pcap_t * p,int ** tstamp_typesp)533d1e87331SXin LI pcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp)
534d1e87331SXin LI {
535d1e87331SXin LI if (p->tstamp_type_count == 0) {
536d1e87331SXin LI /*
537d1e87331SXin LI * We don't support multiple time stamp types.
53857e22627SCy Schubert * That means the only type we support is PCAP_TSTAMP_HOST;
53957e22627SCy Schubert * set up a list containing only that type.
540d1e87331SXin LI */
54157e22627SCy Schubert *tstamp_typesp = (int*)malloc(sizeof(**tstamp_typesp));
54257e22627SCy Schubert if (*tstamp_typesp == NULL) {
543*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
54457e22627SCy Schubert errno, "malloc");
54557e22627SCy Schubert return (PCAP_ERROR);
54657e22627SCy Schubert }
54757e22627SCy Schubert **tstamp_typesp = PCAP_TSTAMP_HOST;
54857e22627SCy Schubert return (1);
549d1e87331SXin LI } else {
550*afdbf109SJoseph Mingrone *tstamp_typesp = (int*)calloc(p->tstamp_type_count,
551*afdbf109SJoseph Mingrone sizeof(**tstamp_typesp));
552d1e87331SXin LI if (*tstamp_typesp == NULL) {
553*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
554b00ab754SHans Petter Selasky errno, "malloc");
555d1e87331SXin LI return (PCAP_ERROR);
556d1e87331SXin LI }
557d1e87331SXin LI (void)memcpy(*tstamp_typesp, p->tstamp_type_list,
558d1e87331SXin LI sizeof(**tstamp_typesp) * p->tstamp_type_count);
559d1e87331SXin LI return (p->tstamp_type_count);
560d1e87331SXin LI }
56157e22627SCy Schubert }
562d1e87331SXin LI
563d1e87331SXin LI /*
564d1e87331SXin LI * In Windows, you might have a library built with one version of the
565d1e87331SXin LI * C runtime library and an application built with another version of
566d1e87331SXin LI * the C runtime library, which means that the library might use one
567d1e87331SXin LI * version of malloc() and free() and the application might use another
568d1e87331SXin LI * version of malloc() and free(). If so, that means something
569d1e87331SXin LI * allocated by the library cannot be freed by the application, so we
570d1e87331SXin LI * need to have a pcap_free_tstamp_types() routine to free up the list
571d1e87331SXin LI * allocated by pcap_list_tstamp_types(), even though it's just a wrapper
572d1e87331SXin LI * around free().
573d1e87331SXin LI */
574d1e87331SXin LI void
pcap_free_tstamp_types(int * tstamp_type_list)575d1e87331SXin LI pcap_free_tstamp_types(int *tstamp_type_list)
576d1e87331SXin LI {
577d1e87331SXin LI free(tstamp_type_list);
578d1e87331SXin LI }
579d1e87331SXin LI
580d1e87331SXin LI /*
581a0ee43a1SRui Paulo * Default one-shot callback; overridden for capture types where the
582a0ee43a1SRui Paulo * packet data cannot be guaranteed to be available after the callback
583a0ee43a1SRui Paulo * returns, so that a copy must be made.
584a8e07101SRui Paulo */
585681ed54cSXin LI void
pcapint_oneshot(u_char * user,const struct pcap_pkthdr * h,const u_char * pkt)586*afdbf109SJoseph Mingrone pcapint_oneshot(u_char *user, const struct pcap_pkthdr *h, const u_char *pkt)
587a0ee43a1SRui Paulo {
588a0ee43a1SRui Paulo struct oneshot_userdata *sp = (struct oneshot_userdata *)user;
589a0ee43a1SRui Paulo
590a0ee43a1SRui Paulo *sp->hdr = *h;
591a0ee43a1SRui Paulo *sp->pkt = pkt;
592a0ee43a1SRui Paulo }
593a0ee43a1SRui Paulo
594a0ee43a1SRui Paulo const u_char *
pcap_next(pcap_t * p,struct pcap_pkthdr * h)595a0ee43a1SRui Paulo pcap_next(pcap_t *p, struct pcap_pkthdr *h)
596a0ee43a1SRui Paulo {
597a0ee43a1SRui Paulo struct oneshot_userdata s;
598a0ee43a1SRui Paulo const u_char *pkt;
599a0ee43a1SRui Paulo
600a0ee43a1SRui Paulo s.hdr = h;
601a0ee43a1SRui Paulo s.pkt = &pkt;
602a0ee43a1SRui Paulo s.pd = p;
603a0ee43a1SRui Paulo if (pcap_dispatch(p, 1, p->oneshot_callback, (u_char *)&s) <= 0)
604a0ee43a1SRui Paulo return (0);
605a0ee43a1SRui Paulo return (pkt);
606a0ee43a1SRui Paulo }
607a0ee43a1SRui Paulo
608a0ee43a1SRui Paulo int
pcap_next_ex(pcap_t * p,struct pcap_pkthdr ** pkt_header,const u_char ** pkt_data)609a0ee43a1SRui Paulo pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
610a0ee43a1SRui Paulo const u_char **pkt_data)
611a0ee43a1SRui Paulo {
612a0ee43a1SRui Paulo struct oneshot_userdata s;
613a0ee43a1SRui Paulo
614a0ee43a1SRui Paulo s.hdr = &p->pcap_header;
615a0ee43a1SRui Paulo s.pkt = pkt_data;
616a0ee43a1SRui Paulo s.pd = p;
617a0ee43a1SRui Paulo
618a0ee43a1SRui Paulo /* Saves a pointer to the packet headers */
619a0ee43a1SRui Paulo *pkt_header= &p->pcap_header;
620a0ee43a1SRui Paulo
621681ed54cSXin LI if (p->rfile != NULL) {
622a0ee43a1SRui Paulo int status;
623a0ee43a1SRui Paulo
624a0ee43a1SRui Paulo /* We are on an offline capture */
625*afdbf109SJoseph Mingrone status = pcapint_offline_read(p, 1, p->oneshot_callback,
626d1e87331SXin LI (u_char *)&s);
627a8e07101SRui Paulo
628a8e07101SRui Paulo /*
629*afdbf109SJoseph Mingrone * Return codes for pcapint_offline_read() are:
630a0ee43a1SRui Paulo * - 0: EOF
631a0ee43a1SRui Paulo * - -1: error
6326f9cba8fSJoseph Mingrone * - >0: OK - result is number of packets read, so
6336f9cba8fSJoseph Mingrone * it will be 1 in this case, as we've passed
6346f9cba8fSJoseph Mingrone * a maximum packet count of 1
635a0ee43a1SRui Paulo * The first one ('0') conflicts with the return code of
636a0ee43a1SRui Paulo * 0 from pcap_read() meaning "no packets arrived before
637a0ee43a1SRui Paulo * the timeout expired", so we map it to -2 so you can
638a0ee43a1SRui Paulo * distinguish between an EOF from a savefile and a
639a0ee43a1SRui Paulo * "no packets arrived before the timeout expired, try
640a0ee43a1SRui Paulo * again" from a live capture.
641a0ee43a1SRui Paulo */
642a0ee43a1SRui Paulo if (status == 0)
643a0ee43a1SRui Paulo return (-2);
644a0ee43a1SRui Paulo else
645a0ee43a1SRui Paulo return (status);
646a0ee43a1SRui Paulo }
647a0ee43a1SRui Paulo
648a0ee43a1SRui Paulo /*
649a0ee43a1SRui Paulo * Return codes for pcap_read() are:
650a0ee43a1SRui Paulo * - 0: timeout
651a0ee43a1SRui Paulo * - -1: error
652a0ee43a1SRui Paulo * - -2: loop was broken out of with pcap_breakloop()
6536f9cba8fSJoseph Mingrone * - >0: OK, result is number of packets captured, so
6546f9cba8fSJoseph Mingrone * it will be 1 in this case, as we've passed
6556f9cba8fSJoseph Mingrone * a maximum packet count of 1
656a0ee43a1SRui Paulo * The first one ('0') conflicts with the return code of 0 from
657*afdbf109SJoseph Mingrone * pcapint_offline_read() meaning "end of file".
658a0ee43a1SRui Paulo */
659d1e87331SXin LI return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s));
660a0ee43a1SRui Paulo }
661a0ee43a1SRui Paulo
662b00ab754SHans Petter Selasky /*
663b00ab754SHans Petter Selasky * Implementation of a pcap_if_list_t.
664b00ab754SHans Petter Selasky */
665b00ab754SHans Petter Selasky struct pcap_if_list {
666b00ab754SHans Petter Selasky pcap_if_t *beginning;
667b00ab754SHans Petter Selasky };
668b00ab754SHans Petter Selasky
669ada6f083SXin LI static struct capture_source_type {
670b00ab754SHans Petter Selasky int (*findalldevs_op)(pcap_if_list_t *, char *);
671edc89b24SXin LI pcap_t *(*create_op)(const char *, char *, int *);
672edc89b24SXin LI } capture_source_types[] = {
673edc89b24SXin LI #ifdef HAVE_DAG_API
674edc89b24SXin LI { dag_findalldevs, dag_create },
675edc89b24SXin LI #endif
676edc89b24SXin LI #ifdef HAVE_SEPTEL_API
677edc89b24SXin LI { septel_findalldevs, septel_create },
678edc89b24SXin LI #endif
679edc89b24SXin LI #ifdef HAVE_SNF_API
680edc89b24SXin LI { snf_findalldevs, snf_create },
681edc89b24SXin LI #endif
682ada6f083SXin LI #ifdef HAVE_TC_API
683ada6f083SXin LI { TcFindAllDevs, TcCreate },
684ada6f083SXin LI #endif
685edc89b24SXin LI #ifdef PCAP_SUPPORT_BT
686edc89b24SXin LI { bt_findalldevs, bt_create },
687edc89b24SXin LI #endif
688681ed54cSXin LI #ifdef PCAP_SUPPORT_BT_MONITOR
689681ed54cSXin LI { bt_monitor_findalldevs, bt_monitor_create },
690681ed54cSXin LI #endif
6916f9cba8fSJoseph Mingrone #ifdef PCAP_SUPPORT_LINUX_USBMON
692edc89b24SXin LI { usb_findalldevs, usb_create },
693edc89b24SXin LI #endif
694edc89b24SXin LI #ifdef PCAP_SUPPORT_NETFILTER
695edc89b24SXin LI { netfilter_findalldevs, netfilter_create },
696edc89b24SXin LI #endif
697b00ab754SHans Petter Selasky #ifdef PCAP_SUPPORT_NETMAP
698b00ab754SHans Petter Selasky { pcap_netmap_findalldevs, pcap_netmap_create },
699b00ab754SHans Petter Selasky #endif
700681ed54cSXin LI #ifdef PCAP_SUPPORT_DBUS
701681ed54cSXin LI { dbus_findalldevs, dbus_create },
702681ed54cSXin LI #endif
703b00ab754SHans Petter Selasky #ifdef PCAP_SUPPORT_RDMASNIFF
704b00ab754SHans Petter Selasky { rdmasniff_findalldevs, rdmasniff_create },
705b00ab754SHans Petter Selasky #endif
7066f9cba8fSJoseph Mingrone #ifdef PCAP_SUPPORT_DPDK
7076f9cba8fSJoseph Mingrone { pcap_dpdk_findalldevs, pcap_dpdk_create },
7086f9cba8fSJoseph Mingrone #endif
7096f9cba8fSJoseph Mingrone #ifdef HAVE_AIRPCAP_API
7106f9cba8fSJoseph Mingrone { airpcap_findalldevs, airpcap_create },
7116f9cba8fSJoseph Mingrone #endif
712edc89b24SXin LI { NULL, NULL }
713edc89b24SXin LI };
714edc89b24SXin LI
715edc89b24SXin LI /*
716edc89b24SXin LI * Get a list of all capture sources that are up and that we can open.
717edc89b24SXin LI * Returns -1 on error, 0 otherwise.
718edc89b24SXin LI * The list, as returned through "alldevsp", may be null if no interfaces
719edc89b24SXin LI * were up and could be opened.
720edc89b24SXin LI */
721edc89b24SXin LI int
pcap_findalldevs(pcap_if_t ** alldevsp,char * errbuf)722edc89b24SXin LI pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
723edc89b24SXin LI {
724edc89b24SXin LI size_t i;
725b00ab754SHans Petter Selasky pcap_if_list_t devlist;
726edc89b24SXin LI
727edc89b24SXin LI /*
728ada6f083SXin LI * Find all the local network interfaces on which we
729ada6f083SXin LI * can capture.
730edc89b24SXin LI */
731b00ab754SHans Petter Selasky devlist.beginning = NULL;
732*afdbf109SJoseph Mingrone if (pcapint_platform_finddevs(&devlist, errbuf) == -1) {
733b00ab754SHans Petter Selasky /*
734b00ab754SHans Petter Selasky * Failed - free all of the entries we were given
735b00ab754SHans Petter Selasky * before we failed.
736b00ab754SHans Petter Selasky */
737b00ab754SHans Petter Selasky if (devlist.beginning != NULL)
738b00ab754SHans Petter Selasky pcap_freealldevs(devlist.beginning);
739b00ab754SHans Petter Selasky *alldevsp = NULL;
740edc89b24SXin LI return (-1);
741b00ab754SHans Petter Selasky }
742edc89b24SXin LI
743edc89b24SXin LI /*
744edc89b24SXin LI * Ask each of the non-local-network-interface capture
745edc89b24SXin LI * source types what interfaces they have.
746edc89b24SXin LI */
747edc89b24SXin LI for (i = 0; capture_source_types[i].findalldevs_op != NULL; i++) {
748b00ab754SHans Petter Selasky if (capture_source_types[i].findalldevs_op(&devlist, errbuf) == -1) {
749edc89b24SXin LI /*
750edc89b24SXin LI * We had an error; free the list we've been
751edc89b24SXin LI * constructing.
752edc89b24SXin LI */
753b00ab754SHans Petter Selasky if (devlist.beginning != NULL)
754b00ab754SHans Petter Selasky pcap_freealldevs(devlist.beginning);
755edc89b24SXin LI *alldevsp = NULL;
756edc89b24SXin LI return (-1);
757edc89b24SXin LI }
758edc89b24SXin LI }
759681ed54cSXin LI
760b00ab754SHans Petter Selasky /*
761b00ab754SHans Petter Selasky * Return the first entry of the list of all devices.
762b00ab754SHans Petter Selasky */
763b00ab754SHans Petter Selasky *alldevsp = devlist.beginning;
764edc89b24SXin LI return (0);
765edc89b24SXin LI }
766edc89b24SXin LI
767b00ab754SHans Petter Selasky static struct sockaddr *
dup_sockaddr(struct sockaddr * sa,size_t sa_length)768b00ab754SHans Petter Selasky dup_sockaddr(struct sockaddr *sa, size_t sa_length)
769b00ab754SHans Petter Selasky {
770b00ab754SHans Petter Selasky struct sockaddr *newsa;
771b00ab754SHans Petter Selasky
772b00ab754SHans Petter Selasky if ((newsa = malloc(sa_length)) == NULL)
773b00ab754SHans Petter Selasky return (NULL);
774b00ab754SHans Petter Selasky return (memcpy(newsa, sa, sa_length));
775b00ab754SHans Petter Selasky }
776b00ab754SHans Petter Selasky
777b00ab754SHans Petter Selasky /*
778b00ab754SHans Petter Selasky * Construct a "figure of merit" for an interface, for use when sorting
779b00ab754SHans Petter Selasky * the list of interfaces, in which interfaces that are up are superior
780b00ab754SHans Petter Selasky * to interfaces that aren't up, interfaces that are up and running are
781b00ab754SHans Petter Selasky * superior to interfaces that are up but not running, and non-loopback
782b00ab754SHans Petter Selasky * interfaces that are up and running are superior to loopback interfaces,
783b00ab754SHans Petter Selasky * and interfaces with the same flags have a figure of merit that's higher
784b00ab754SHans Petter Selasky * the lower the instance number.
785b00ab754SHans Petter Selasky *
786b00ab754SHans Petter Selasky * The goal is to try to put the interfaces most likely to be useful for
787b00ab754SHans Petter Selasky * capture at the beginning of the list.
788b00ab754SHans Petter Selasky *
789b00ab754SHans Petter Selasky * The figure of merit, which is lower the "better" the interface is,
790b00ab754SHans Petter Selasky * has the uppermost bit set if the interface isn't running, the bit
7916f9cba8fSJoseph Mingrone * below that set if the interface isn't up, the bit below that
7926f9cba8fSJoseph Mingrone * set if the interface is a loopback interface, and the bit below
7936f9cba8fSJoseph Mingrone * that set if it's the "any" interface.
7946f9cba8fSJoseph Mingrone *
7956f9cba8fSJoseph Mingrone * Note: we don't sort by unit number because 1) not all interfaces have
7966f9cba8fSJoseph Mingrone * a unit number (systemd, for example, might assign interface names
7976f9cba8fSJoseph Mingrone * based on the interface's MAC address or on the physical location of
7986f9cba8fSJoseph Mingrone * the adapter's connector), and 2) if the name does end with a simple
7996f9cba8fSJoseph Mingrone * unit number, it's not a global property of the interface, it's only
8006f9cba8fSJoseph Mingrone * useful as a sort key for device names with the same prefix, so xyz0
8016f9cba8fSJoseph Mingrone * shouldn't necessarily sort before abc2. This means that interfaces
8026f9cba8fSJoseph Mingrone * with the same figure of merit will be sorted by the order in which
8036f9cba8fSJoseph Mingrone * the mechanism from which we're getting the interfaces supplies them.
804b00ab754SHans Petter Selasky */
805b00ab754SHans Petter Selasky static u_int
get_figure_of_merit(pcap_if_t * dev)806b00ab754SHans Petter Selasky get_figure_of_merit(pcap_if_t *dev)
807b00ab754SHans Petter Selasky {
808b00ab754SHans Petter Selasky u_int n;
809b00ab754SHans Petter Selasky
810b00ab754SHans Petter Selasky n = 0;
811b00ab754SHans Petter Selasky if (!(dev->flags & PCAP_IF_RUNNING))
812b00ab754SHans Petter Selasky n |= 0x80000000;
813b00ab754SHans Petter Selasky if (!(dev->flags & PCAP_IF_UP))
814b00ab754SHans Petter Selasky n |= 0x40000000;
815b00ab754SHans Petter Selasky
816b00ab754SHans Petter Selasky /*
817b00ab754SHans Petter Selasky * Give non-wireless interfaces that aren't disconnected a better
818b00ab754SHans Petter Selasky * figure of merit than interfaces that are disconnected, as
819b00ab754SHans Petter Selasky * "disconnected" should indicate that the interface isn't
820b00ab754SHans Petter Selasky * plugged into a network and thus won't give you any traffic.
821b00ab754SHans Petter Selasky *
822b00ab754SHans Petter Selasky * For wireless interfaces, it means "associated with a network",
823b00ab754SHans Petter Selasky * which we presume not to necessarily prevent capture, as you
824b00ab754SHans Petter Selasky * might run the adapter in some flavor of monitor mode.
825b00ab754SHans Petter Selasky */
826b00ab754SHans Petter Selasky if (!(dev->flags & PCAP_IF_WIRELESS) &&
827b00ab754SHans Petter Selasky (dev->flags & PCAP_IF_CONNECTION_STATUS) == PCAP_IF_CONNECTION_STATUS_DISCONNECTED)
828b00ab754SHans Petter Selasky n |= 0x20000000;
829b00ab754SHans Petter Selasky
830b00ab754SHans Petter Selasky /*
831b00ab754SHans Petter Selasky * Sort loopback devices after non-loopback devices, *except* for
832b00ab754SHans Petter Selasky * disconnected devices.
833b00ab754SHans Petter Selasky */
834b00ab754SHans Petter Selasky if (dev->flags & PCAP_IF_LOOPBACK)
835b00ab754SHans Petter Selasky n |= 0x10000000;
836b00ab754SHans Petter Selasky
8376f9cba8fSJoseph Mingrone /*
8386f9cba8fSJoseph Mingrone * Sort the "any" device before loopback and disconnected devices,
8396f9cba8fSJoseph Mingrone * but after all other devices.
8406f9cba8fSJoseph Mingrone */
8416f9cba8fSJoseph Mingrone if (strcmp(dev->name, "any") == 0)
8426f9cba8fSJoseph Mingrone n |= 0x08000000;
8436f9cba8fSJoseph Mingrone
844b00ab754SHans Petter Selasky return (n);
845b00ab754SHans Petter Selasky }
846b00ab754SHans Petter Selasky
847b00ab754SHans Petter Selasky #ifndef _WIN32
848b00ab754SHans Petter Selasky /*
849b00ab754SHans Petter Selasky * Try to get a description for a given device.
850*afdbf109SJoseph Mingrone * Returns a malloced description if it could and NULL if it couldn't.
851b00ab754SHans Petter Selasky *
852b00ab754SHans Petter Selasky * XXX - on FreeBSDs that support it, should it get the sysctl named
853b00ab754SHans Petter Selasky * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
854b00ab754SHans Petter Selasky * of the adapter? Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
855b00ab754SHans Petter Selasky * with my Cisco 350 card, so the name isn't entirely descriptive. The
856b00ab754SHans Petter Selasky * "dev.an.0.%pnpinfo" has a better description, although one might argue
857b00ab754SHans Petter Selasky * that the problem is really a driver bug - if it can find out that it's
858b00ab754SHans Petter Selasky * a Cisco 340 or 350, rather than an old Aironet card, it should use
859b00ab754SHans Petter Selasky * that in the description.
860b00ab754SHans Petter Selasky *
861b00ab754SHans Petter Selasky * Do NetBSD, DragonflyBSD, or OpenBSD support this as well? FreeBSD
862b00ab754SHans Petter Selasky * and OpenBSD let you get a description, but it's not generated by the OS,
863b00ab754SHans Petter Selasky * it's set with another ioctl that ifconfig supports; we use that to get
864b00ab754SHans Petter Selasky * a description in FreeBSD and OpenBSD, but if there is no such
865b00ab754SHans Petter Selasky * description available, it still might be nice to get some description
866b00ab754SHans Petter Selasky * string based on the device type or something such as that.
867b00ab754SHans Petter Selasky *
868b00ab754SHans Petter Selasky * In macOS, the System Configuration framework can apparently return
869b00ab754SHans Petter Selasky * names in 10.4 and later.
870b00ab754SHans Petter Selasky *
871b00ab754SHans Petter Selasky * It also appears that freedesktop.org's HAL offers an "info.product"
872b00ab754SHans Petter Selasky * string, but the HAL specification says it "should not be used in any
873b00ab754SHans Petter Selasky * UI" and "subsystem/capability specific properties" should be used
874b00ab754SHans Petter Selasky * instead and, in any case, I think HAL is being deprecated in
875b00ab754SHans Petter Selasky * favor of other stuff such as DeviceKit. DeviceKit doesn't appear
876b00ab754SHans Petter Selasky * to have any obvious product information for devices, but maybe
877b00ab754SHans Petter Selasky * I haven't looked hard enough.
878b00ab754SHans Petter Selasky *
879b00ab754SHans Petter Selasky * Using the System Configuration framework, or HAL, or DeviceKit, or
880b00ab754SHans Petter Selasky * whatever, would require that libpcap applications be linked with
881b00ab754SHans Petter Selasky * the frameworks/libraries in question. That shouldn't be a problem
882b00ab754SHans Petter Selasky * for programs linking with the shared version of libpcap (unless
883b00ab754SHans Petter Selasky * you're running on AIX - which I think is the only UN*X that doesn't
884b00ab754SHans Petter Selasky * support linking a shared library with other libraries on which it
885b00ab754SHans Petter Selasky * depends, and having an executable linked only with the first shared
886b00ab754SHans Petter Selasky * library automatically pick up the other libraries when started -
887b00ab754SHans Petter Selasky * and using HAL or whatever). Programs linked with the static
888b00ab754SHans Petter Selasky * version of libpcap would have to use pcap-config with the --static
889b00ab754SHans Petter Selasky * flag in order to get the right linker flags in order to pick up
890b00ab754SHans Petter Selasky * the additional libraries/frameworks; those programs need that anyway
891b00ab754SHans Petter Selasky * for libpcap 1.1 and beyond on Linux, as, by default, it requires
892b00ab754SHans Petter Selasky * -lnl.
893b00ab754SHans Petter Selasky *
894b00ab754SHans Petter Selasky * Do any other UN*Xes, or desktop environments support getting a
895b00ab754SHans Petter Selasky * description?
896b00ab754SHans Petter Selasky */
897b00ab754SHans Petter Selasky static char *
898b00ab754SHans Petter Selasky #ifdef SIOCGIFDESCR
get_if_description(const char * name)899b00ab754SHans Petter Selasky get_if_description(const char *name)
900b00ab754SHans Petter Selasky {
901b00ab754SHans Petter Selasky char *description = NULL;
902b00ab754SHans Petter Selasky int s;
903b00ab754SHans Petter Selasky struct ifreq ifrdesc;
904b00ab754SHans Petter Selasky #ifndef IFDESCRSIZE
905b00ab754SHans Petter Selasky size_t descrlen = 64;
906b00ab754SHans Petter Selasky #else
907b00ab754SHans Petter Selasky size_t descrlen = IFDESCRSIZE;
908b00ab754SHans Petter Selasky #endif /* IFDESCRSIZE */
909b00ab754SHans Petter Selasky
910b00ab754SHans Petter Selasky /*
911b00ab754SHans Petter Selasky * Get the description for the interface.
912b00ab754SHans Petter Selasky */
913b00ab754SHans Petter Selasky memset(&ifrdesc, 0, sizeof ifrdesc);
914*afdbf109SJoseph Mingrone pcapint_strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
915b00ab754SHans Petter Selasky s = socket(AF_INET, SOCK_DGRAM, 0);
916b00ab754SHans Petter Selasky if (s >= 0) {
917b00ab754SHans Petter Selasky #ifdef __FreeBSD__
918b00ab754SHans Petter Selasky /*
919b00ab754SHans Petter Selasky * On FreeBSD, if the buffer isn't big enough for the
920b00ab754SHans Petter Selasky * description, the ioctl succeeds, but the description
921b00ab754SHans Petter Selasky * isn't copied, ifr_buffer.length is set to the description
922b00ab754SHans Petter Selasky * length, and ifr_buffer.buffer is set to NULL.
923b00ab754SHans Petter Selasky */
924b00ab754SHans Petter Selasky for (;;) {
925b00ab754SHans Petter Selasky free(description);
926b00ab754SHans Petter Selasky if ((description = malloc(descrlen)) != NULL) {
927b00ab754SHans Petter Selasky ifrdesc.ifr_buffer.buffer = description;
928b00ab754SHans Petter Selasky ifrdesc.ifr_buffer.length = descrlen;
929b00ab754SHans Petter Selasky if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
930b00ab754SHans Petter Selasky if (ifrdesc.ifr_buffer.buffer ==
931b00ab754SHans Petter Selasky description)
932b00ab754SHans Petter Selasky break;
933b00ab754SHans Petter Selasky else
934b00ab754SHans Petter Selasky descrlen = ifrdesc.ifr_buffer.length;
935b00ab754SHans Petter Selasky } else {
936b00ab754SHans Petter Selasky /*
937b00ab754SHans Petter Selasky * Failed to get interface description.
938b00ab754SHans Petter Selasky */
939b00ab754SHans Petter Selasky free(description);
940b00ab754SHans Petter Selasky description = NULL;
941b00ab754SHans Petter Selasky break;
942b00ab754SHans Petter Selasky }
943b00ab754SHans Petter Selasky } else
944b00ab754SHans Petter Selasky break;
945b00ab754SHans Petter Selasky }
946b00ab754SHans Petter Selasky #else /* __FreeBSD__ */
947b00ab754SHans Petter Selasky /*
948b00ab754SHans Petter Selasky * The only other OS that currently supports
949b00ab754SHans Petter Selasky * SIOCGIFDESCR is OpenBSD, and it has no way
950b00ab754SHans Petter Selasky * to get the description length - it's clamped
951b00ab754SHans Petter Selasky * to a maximum of IFDESCRSIZE.
952b00ab754SHans Petter Selasky */
953b00ab754SHans Petter Selasky if ((description = malloc(descrlen)) != NULL) {
954b00ab754SHans Petter Selasky ifrdesc.ifr_data = (caddr_t)description;
955b00ab754SHans Petter Selasky if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
956b00ab754SHans Petter Selasky /*
957b00ab754SHans Petter Selasky * Failed to get interface description.
958b00ab754SHans Petter Selasky */
959b00ab754SHans Petter Selasky free(description);
960b00ab754SHans Petter Selasky description = NULL;
961b00ab754SHans Petter Selasky }
962b00ab754SHans Petter Selasky }
963b00ab754SHans Petter Selasky #endif /* __FreeBSD__ */
964b00ab754SHans Petter Selasky close(s);
96557e22627SCy Schubert if (description != NULL && description[0] == '\0') {
966b00ab754SHans Petter Selasky /*
967b00ab754SHans Petter Selasky * Description is empty, so discard it.
968b00ab754SHans Petter Selasky */
969b00ab754SHans Petter Selasky free(description);
970b00ab754SHans Petter Selasky description = NULL;
971b00ab754SHans Petter Selasky }
972b00ab754SHans Petter Selasky }
973b00ab754SHans Petter Selasky
974b00ab754SHans Petter Selasky #ifdef __FreeBSD__
975b00ab754SHans Petter Selasky /*
976b00ab754SHans Petter Selasky * For FreeBSD, if we didn't get a description, and this is
977b00ab754SHans Petter Selasky * a device with a name of the form usbusN, label it as a USB
978b00ab754SHans Petter Selasky * bus.
979b00ab754SHans Petter Selasky */
980b00ab754SHans Petter Selasky if (description == NULL) {
981b00ab754SHans Petter Selasky if (strncmp(name, "usbus", 5) == 0) {
982b00ab754SHans Petter Selasky /*
983b00ab754SHans Petter Selasky * OK, it begins with "usbus".
984b00ab754SHans Petter Selasky */
985b00ab754SHans Petter Selasky long busnum;
986b00ab754SHans Petter Selasky char *p;
987b00ab754SHans Petter Selasky
988b00ab754SHans Petter Selasky errno = 0;
989b00ab754SHans Petter Selasky busnum = strtol(name + 5, &p, 10);
990b00ab754SHans Petter Selasky if (errno == 0 && p != name + 5 && *p == '\0' &&
991b00ab754SHans Petter Selasky busnum >= 0 && busnum <= INT_MAX) {
992b00ab754SHans Petter Selasky /*
993b00ab754SHans Petter Selasky * OK, it's a valid number that's not
994b00ab754SHans Petter Selasky * bigger than INT_MAX. Construct
995b00ab754SHans Petter Selasky * a description from it.
99657e22627SCy Schubert * (If that fails, we don't worry about
99757e22627SCy Schubert * it, we just return NULL.)
998b00ab754SHans Petter Selasky */
999*afdbf109SJoseph Mingrone if (pcapint_asprintf(&description,
100057e22627SCy Schubert "USB bus number %ld", busnum) == -1) {
100157e22627SCy Schubert /* Failed. */
100257e22627SCy Schubert description = NULL;
1003b00ab754SHans Petter Selasky }
1004b00ab754SHans Petter Selasky }
1005b00ab754SHans Petter Selasky }
1006b00ab754SHans Petter Selasky }
1007b00ab754SHans Petter Selasky #endif
1008b00ab754SHans Petter Selasky return (description);
1009b00ab754SHans Petter Selasky #else /* SIOCGIFDESCR */
1010b00ab754SHans Petter Selasky get_if_description(const char *name _U_)
1011b00ab754SHans Petter Selasky {
1012b00ab754SHans Petter Selasky return (NULL);
1013b00ab754SHans Petter Selasky #endif /* SIOCGIFDESCR */
1014b00ab754SHans Petter Selasky }
1015b00ab754SHans Petter Selasky
1016b00ab754SHans Petter Selasky /*
1017b00ab754SHans Petter Selasky * Look for a given device in the specified list of devices.
1018b00ab754SHans Petter Selasky *
1019b00ab754SHans Petter Selasky * If we find it, return a pointer to its entry.
1020b00ab754SHans Petter Selasky *
1021b00ab754SHans Petter Selasky * If we don't find it, attempt to add an entry for it, with the specified
1022b00ab754SHans Petter Selasky * IFF_ flags and description, and, if that succeeds, return a pointer to
1023b00ab754SHans Petter Selasky * the new entry, otherwise return NULL and set errbuf to an error message.
1024b00ab754SHans Petter Selasky */
1025b00ab754SHans Petter Selasky pcap_if_t *
1026*afdbf109SJoseph Mingrone pcapint_find_or_add_if(pcap_if_list_t *devlistp, const char *name,
1027*afdbf109SJoseph Mingrone uint64_t if_flags, get_if_flags_func get_flags_func, char *errbuf)
1028b00ab754SHans Petter Selasky {
1029b00ab754SHans Petter Selasky bpf_u_int32 pcap_flags;
1030b00ab754SHans Petter Selasky
1031b00ab754SHans Petter Selasky /*
1032b00ab754SHans Petter Selasky * Convert IFF_ flags to pcap flags.
1033b00ab754SHans Petter Selasky */
1034b00ab754SHans Petter Selasky pcap_flags = 0;
1035b00ab754SHans Petter Selasky #ifdef IFF_LOOPBACK
1036b00ab754SHans Petter Selasky if (if_flags & IFF_LOOPBACK)
1037b00ab754SHans Petter Selasky pcap_flags |= PCAP_IF_LOOPBACK;
1038b00ab754SHans Petter Selasky #else
1039b00ab754SHans Petter Selasky /*
1040b00ab754SHans Petter Selasky * We don't have IFF_LOOPBACK, so look at the device name to
1041b00ab754SHans Petter Selasky * see if it looks like a loopback device.
1042b00ab754SHans Petter Selasky */
1043b00ab754SHans Petter Selasky if (name[0] == 'l' && name[1] == 'o' &&
10446f9cba8fSJoseph Mingrone (PCAP_ISDIGIT(name[2]) || name[2] == '\0'))
1045b00ab754SHans Petter Selasky pcap_flags |= PCAP_IF_LOOPBACK;
1046b00ab754SHans Petter Selasky #endif
1047b00ab754SHans Petter Selasky #ifdef IFF_UP
1048b00ab754SHans Petter Selasky if (if_flags & IFF_UP)
1049b00ab754SHans Petter Selasky pcap_flags |= PCAP_IF_UP;
1050b00ab754SHans Petter Selasky #endif
1051b00ab754SHans Petter Selasky #ifdef IFF_RUNNING
1052b00ab754SHans Petter Selasky if (if_flags & IFF_RUNNING)
1053b00ab754SHans Petter Selasky pcap_flags |= PCAP_IF_RUNNING;
1054b00ab754SHans Petter Selasky #endif
1055b00ab754SHans Petter Selasky
1056b00ab754SHans Petter Selasky /*
1057b00ab754SHans Petter Selasky * Attempt to find an entry for this device; if we don't find one,
1058b00ab754SHans Petter Selasky * attempt to add one.
1059b00ab754SHans Petter Selasky */
1060*afdbf109SJoseph Mingrone return (pcapint_find_or_add_dev(devlistp, name, pcap_flags,
1061b00ab754SHans Petter Selasky get_flags_func, get_if_description(name), errbuf));
1062b00ab754SHans Petter Selasky }
1063b00ab754SHans Petter Selasky
1064b00ab754SHans Petter Selasky /*
1065b00ab754SHans Petter Selasky * Look for a given device in the specified list of devices.
1066b00ab754SHans Petter Selasky *
1067b00ab754SHans Petter Selasky * If we find it, then, if the specified address isn't null, add it to
1068b00ab754SHans Petter Selasky * the list of addresses for the device and return 0.
1069b00ab754SHans Petter Selasky *
1070b00ab754SHans Petter Selasky * If we don't find it, attempt to add an entry for it, with the specified
1071b00ab754SHans Petter Selasky * IFF_ flags and description, and, if that succeeds, add the specified
1072b00ab754SHans Petter Selasky * address to its list of addresses if that address is non-null, and
1073b00ab754SHans Petter Selasky * return 0, otherwise return -1 and set errbuf to an error message.
1074b00ab754SHans Petter Selasky *
1075b00ab754SHans Petter Selasky * (We can get called with a null address because we might get a list
1076b00ab754SHans Petter Selasky * of interface name/address combinations from the underlying OS, with
1077b00ab754SHans Petter Selasky * the address being absent in some cases, rather than a list of
1078b00ab754SHans Petter Selasky * interfaces with each interface having a list of addresses, so this
1079b00ab754SHans Petter Selasky * call may be the only call made to add to the list, and we want to
1080b00ab754SHans Petter Selasky * add interfaces even if they have no addresses.)
1081b00ab754SHans Petter Selasky */
1082b00ab754SHans Petter Selasky int
1083*afdbf109SJoseph Mingrone pcapint_add_addr_to_if(pcap_if_list_t *devlistp, const char *name,
1084*afdbf109SJoseph Mingrone uint64_t if_flags, get_if_flags_func get_flags_func,
1085b00ab754SHans Petter Selasky struct sockaddr *addr, size_t addr_size,
1086b00ab754SHans Petter Selasky struct sockaddr *netmask, size_t netmask_size,
1087b00ab754SHans Petter Selasky struct sockaddr *broadaddr, size_t broadaddr_size,
1088b00ab754SHans Petter Selasky struct sockaddr *dstaddr, size_t dstaddr_size,
1089b00ab754SHans Petter Selasky char *errbuf)
1090b00ab754SHans Petter Selasky {
1091b00ab754SHans Petter Selasky pcap_if_t *curdev;
1092b00ab754SHans Petter Selasky
1093b00ab754SHans Petter Selasky /*
1094b00ab754SHans Petter Selasky * Check whether the device exists and, if not, add it.
1095b00ab754SHans Petter Selasky */
1096*afdbf109SJoseph Mingrone curdev = pcapint_find_or_add_if(devlistp, name, if_flags, get_flags_func,
1097b00ab754SHans Petter Selasky errbuf);
1098b00ab754SHans Petter Selasky if (curdev == NULL) {
1099b00ab754SHans Petter Selasky /*
1100b00ab754SHans Petter Selasky * Error - give up.
1101b00ab754SHans Petter Selasky */
1102b00ab754SHans Petter Selasky return (-1);
1103b00ab754SHans Petter Selasky }
1104b00ab754SHans Petter Selasky
1105b00ab754SHans Petter Selasky if (addr == NULL) {
1106b00ab754SHans Petter Selasky /*
1107b00ab754SHans Petter Selasky * There's no address to add; this entry just meant
1108b00ab754SHans Petter Selasky * "here's a new interface".
1109b00ab754SHans Petter Selasky */
1110b00ab754SHans Petter Selasky return (0);
1111b00ab754SHans Petter Selasky }
1112b00ab754SHans Petter Selasky
1113b00ab754SHans Petter Selasky /*
1114b00ab754SHans Petter Selasky * "curdev" is an entry for this interface, and we have an
1115b00ab754SHans Petter Selasky * address for it; add an entry for that address to the
1116b00ab754SHans Petter Selasky * interface's list of addresses.
1117b00ab754SHans Petter Selasky */
1118*afdbf109SJoseph Mingrone return (pcapint_add_addr_to_dev(curdev, addr, addr_size, netmask,
1119b00ab754SHans Petter Selasky netmask_size, broadaddr, broadaddr_size, dstaddr,
1120b00ab754SHans Petter Selasky dstaddr_size, errbuf));
1121b00ab754SHans Petter Selasky }
1122b00ab754SHans Petter Selasky #endif /* _WIN32 */
1123b00ab754SHans Petter Selasky
1124b00ab754SHans Petter Selasky /*
1125b00ab754SHans Petter Selasky * Add an entry to the list of addresses for an interface.
1126b00ab754SHans Petter Selasky * "curdev" is the entry for that interface.
1127b00ab754SHans Petter Selasky */
1128b00ab754SHans Petter Selasky int
1129*afdbf109SJoseph Mingrone pcapint_add_addr_to_dev(pcap_if_t *curdev,
1130b00ab754SHans Petter Selasky struct sockaddr *addr, size_t addr_size,
1131b00ab754SHans Petter Selasky struct sockaddr *netmask, size_t netmask_size,
1132b00ab754SHans Petter Selasky struct sockaddr *broadaddr, size_t broadaddr_size,
1133b00ab754SHans Petter Selasky struct sockaddr *dstaddr, size_t dstaddr_size,
1134b00ab754SHans Petter Selasky char *errbuf)
1135b00ab754SHans Petter Selasky {
1136b00ab754SHans Petter Selasky pcap_addr_t *curaddr, *prevaddr, *nextaddr;
1137b00ab754SHans Petter Selasky
1138b00ab754SHans Petter Selasky /*
1139b00ab754SHans Petter Selasky * Allocate the new entry and fill it in.
1140b00ab754SHans Petter Selasky */
1141b00ab754SHans Petter Selasky curaddr = (pcap_addr_t *)malloc(sizeof(pcap_addr_t));
1142b00ab754SHans Petter Selasky if (curaddr == NULL) {
1143*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1144b00ab754SHans Petter Selasky errno, "malloc");
1145b00ab754SHans Petter Selasky return (-1);
1146b00ab754SHans Petter Selasky }
1147b00ab754SHans Petter Selasky
1148b00ab754SHans Petter Selasky curaddr->next = NULL;
1149b00ab754SHans Petter Selasky if (addr != NULL && addr_size != 0) {
1150b00ab754SHans Petter Selasky curaddr->addr = (struct sockaddr *)dup_sockaddr(addr, addr_size);
1151b00ab754SHans Petter Selasky if (curaddr->addr == NULL) {
1152*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1153b00ab754SHans Petter Selasky errno, "malloc");
1154b00ab754SHans Petter Selasky free(curaddr);
1155b00ab754SHans Petter Selasky return (-1);
1156b00ab754SHans Petter Selasky }
1157b00ab754SHans Petter Selasky } else
1158b00ab754SHans Petter Selasky curaddr->addr = NULL;
1159b00ab754SHans Petter Selasky
1160b00ab754SHans Petter Selasky if (netmask != NULL && netmask_size != 0) {
1161b00ab754SHans Petter Selasky curaddr->netmask = (struct sockaddr *)dup_sockaddr(netmask, netmask_size);
1162b00ab754SHans Petter Selasky if (curaddr->netmask == NULL) {
1163*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1164b00ab754SHans Petter Selasky errno, "malloc");
1165b00ab754SHans Petter Selasky if (curaddr->addr != NULL)
1166b00ab754SHans Petter Selasky free(curaddr->addr);
1167b00ab754SHans Petter Selasky free(curaddr);
1168b00ab754SHans Petter Selasky return (-1);
1169b00ab754SHans Petter Selasky }
1170b00ab754SHans Petter Selasky } else
1171b00ab754SHans Petter Selasky curaddr->netmask = NULL;
1172b00ab754SHans Petter Selasky
1173b00ab754SHans Petter Selasky if (broadaddr != NULL && broadaddr_size != 0) {
1174b00ab754SHans Petter Selasky curaddr->broadaddr = (struct sockaddr *)dup_sockaddr(broadaddr, broadaddr_size);
1175b00ab754SHans Petter Selasky if (curaddr->broadaddr == NULL) {
1176*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1177b00ab754SHans Petter Selasky errno, "malloc");
1178b00ab754SHans Petter Selasky if (curaddr->netmask != NULL)
1179b00ab754SHans Petter Selasky free(curaddr->netmask);
1180b00ab754SHans Petter Selasky if (curaddr->addr != NULL)
1181b00ab754SHans Petter Selasky free(curaddr->addr);
1182b00ab754SHans Petter Selasky free(curaddr);
1183b00ab754SHans Petter Selasky return (-1);
1184b00ab754SHans Petter Selasky }
1185b00ab754SHans Petter Selasky } else
1186b00ab754SHans Petter Selasky curaddr->broadaddr = NULL;
1187b00ab754SHans Petter Selasky
1188b00ab754SHans Petter Selasky if (dstaddr != NULL && dstaddr_size != 0) {
1189b00ab754SHans Petter Selasky curaddr->dstaddr = (struct sockaddr *)dup_sockaddr(dstaddr, dstaddr_size);
1190b00ab754SHans Petter Selasky if (curaddr->dstaddr == NULL) {
1191*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1192b00ab754SHans Petter Selasky errno, "malloc");
1193b00ab754SHans Petter Selasky if (curaddr->broadaddr != NULL)
1194b00ab754SHans Petter Selasky free(curaddr->broadaddr);
1195b00ab754SHans Petter Selasky if (curaddr->netmask != NULL)
1196b00ab754SHans Petter Selasky free(curaddr->netmask);
1197b00ab754SHans Petter Selasky if (curaddr->addr != NULL)
1198b00ab754SHans Petter Selasky free(curaddr->addr);
1199b00ab754SHans Petter Selasky free(curaddr);
1200b00ab754SHans Petter Selasky return (-1);
1201b00ab754SHans Petter Selasky }
1202b00ab754SHans Petter Selasky } else
1203b00ab754SHans Petter Selasky curaddr->dstaddr = NULL;
1204b00ab754SHans Petter Selasky
1205b00ab754SHans Petter Selasky /*
1206b00ab754SHans Petter Selasky * Find the end of the list of addresses.
1207b00ab754SHans Petter Selasky */
1208b00ab754SHans Petter Selasky for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
1209b00ab754SHans Petter Selasky nextaddr = prevaddr->next;
1210b00ab754SHans Petter Selasky if (nextaddr == NULL) {
1211b00ab754SHans Petter Selasky /*
1212b00ab754SHans Petter Selasky * This is the end of the list.
1213b00ab754SHans Petter Selasky */
1214b00ab754SHans Petter Selasky break;
1215b00ab754SHans Petter Selasky }
1216b00ab754SHans Petter Selasky }
1217b00ab754SHans Petter Selasky
1218b00ab754SHans Petter Selasky if (prevaddr == NULL) {
1219b00ab754SHans Petter Selasky /*
1220b00ab754SHans Petter Selasky * The list was empty; this is the first member.
1221b00ab754SHans Petter Selasky */
1222b00ab754SHans Petter Selasky curdev->addresses = curaddr;
1223b00ab754SHans Petter Selasky } else {
1224b00ab754SHans Petter Selasky /*
1225b00ab754SHans Petter Selasky * "prevaddr" is the last member of the list; append
1226b00ab754SHans Petter Selasky * this member to it.
1227b00ab754SHans Petter Selasky */
1228b00ab754SHans Petter Selasky prevaddr->next = curaddr;
1229b00ab754SHans Petter Selasky }
1230b00ab754SHans Petter Selasky
1231b00ab754SHans Petter Selasky return (0);
1232b00ab754SHans Petter Selasky }
1233b00ab754SHans Petter Selasky
1234b00ab754SHans Petter Selasky /*
1235b00ab754SHans Petter Selasky * Look for a given device in the specified list of devices.
1236b00ab754SHans Petter Selasky *
1237b00ab754SHans Petter Selasky * If we find it, return 0 and set *curdev_ret to point to it.
1238b00ab754SHans Petter Selasky *
1239b00ab754SHans Petter Selasky * If we don't find it, attempt to add an entry for it, with the specified
1240b00ab754SHans Petter Selasky * flags and description, and, if that succeeds, return 0, otherwise
1241b00ab754SHans Petter Selasky * return -1 and set errbuf to an error message.
1242b00ab754SHans Petter Selasky */
1243b00ab754SHans Petter Selasky pcap_if_t *
1244*afdbf109SJoseph Mingrone pcapint_find_or_add_dev(pcap_if_list_t *devlistp, const char *name, bpf_u_int32 flags,
1245b00ab754SHans Petter Selasky get_if_flags_func get_flags_func, const char *description, char *errbuf)
1246b00ab754SHans Petter Selasky {
1247b00ab754SHans Petter Selasky pcap_if_t *curdev;
1248b00ab754SHans Petter Selasky
1249b00ab754SHans Petter Selasky /*
1250b00ab754SHans Petter Selasky * Is there already an entry in the list for this device?
1251b00ab754SHans Petter Selasky */
1252*afdbf109SJoseph Mingrone curdev = pcapint_find_dev(devlistp, name);
1253b00ab754SHans Petter Selasky if (curdev != NULL) {
1254b00ab754SHans Petter Selasky /*
1255b00ab754SHans Petter Selasky * Yes, return it.
1256b00ab754SHans Petter Selasky */
1257b00ab754SHans Petter Selasky return (curdev);
1258b00ab754SHans Petter Selasky }
1259b00ab754SHans Petter Selasky
1260b00ab754SHans Petter Selasky /*
1261b00ab754SHans Petter Selasky * No, we didn't find it.
1262b00ab754SHans Petter Selasky */
1263b00ab754SHans Petter Selasky
1264b00ab754SHans Petter Selasky /*
1265b00ab754SHans Petter Selasky * Try to get additional flags for the device.
1266b00ab754SHans Petter Selasky */
1267b00ab754SHans Petter Selasky if ((*get_flags_func)(name, &flags, errbuf) == -1) {
1268b00ab754SHans Petter Selasky /*
1269b00ab754SHans Petter Selasky * Failed.
1270b00ab754SHans Petter Selasky */
1271b00ab754SHans Petter Selasky return (NULL);
1272b00ab754SHans Petter Selasky }
1273b00ab754SHans Petter Selasky
1274b00ab754SHans Petter Selasky /*
1275b00ab754SHans Petter Selasky * Now, try to add it to the list of devices.
1276b00ab754SHans Petter Selasky */
1277*afdbf109SJoseph Mingrone return (pcapint_add_dev(devlistp, name, flags, description, errbuf));
1278b00ab754SHans Petter Selasky }
1279b00ab754SHans Petter Selasky
1280b00ab754SHans Petter Selasky /*
1281b00ab754SHans Petter Selasky * Look for a given device in the specified list of devices, and return
1282b00ab754SHans Petter Selasky * the entry for it if we find it or NULL if we don't.
1283b00ab754SHans Petter Selasky */
1284b00ab754SHans Petter Selasky pcap_if_t *
1285*afdbf109SJoseph Mingrone pcapint_find_dev(pcap_if_list_t *devlistp, const char *name)
1286b00ab754SHans Petter Selasky {
1287b00ab754SHans Petter Selasky pcap_if_t *curdev;
1288b00ab754SHans Petter Selasky
1289b00ab754SHans Petter Selasky /*
1290b00ab754SHans Petter Selasky * Is there an entry in the list for this device?
1291b00ab754SHans Petter Selasky */
1292b00ab754SHans Petter Selasky for (curdev = devlistp->beginning; curdev != NULL;
1293b00ab754SHans Petter Selasky curdev = curdev->next) {
1294b00ab754SHans Petter Selasky if (strcmp(name, curdev->name) == 0) {
1295b00ab754SHans Petter Selasky /*
1296b00ab754SHans Petter Selasky * We found it, so, yes, there is. No need to
1297b00ab754SHans Petter Selasky * add it. Provide the entry we found to our
1298b00ab754SHans Petter Selasky * caller.
1299b00ab754SHans Petter Selasky */
1300b00ab754SHans Petter Selasky return (curdev);
1301b00ab754SHans Petter Selasky }
1302b00ab754SHans Petter Selasky }
1303b00ab754SHans Petter Selasky
1304b00ab754SHans Petter Selasky /*
1305b00ab754SHans Petter Selasky * No.
1306b00ab754SHans Petter Selasky */
1307b00ab754SHans Petter Selasky return (NULL);
1308b00ab754SHans Petter Selasky }
1309b00ab754SHans Petter Selasky
1310b00ab754SHans Petter Selasky /*
1311b00ab754SHans Petter Selasky * Attempt to add an entry for a device, with the specified flags
1312b00ab754SHans Petter Selasky * and description, and, if that succeeds, return 0 and return a pointer
1313b00ab754SHans Petter Selasky * to the new entry, otherwise return NULL and set errbuf to an error
1314b00ab754SHans Petter Selasky * message.
1315b00ab754SHans Petter Selasky *
1316b00ab754SHans Petter Selasky * If we weren't given a description, try to get one.
1317b00ab754SHans Petter Selasky */
1318b00ab754SHans Petter Selasky pcap_if_t *
1319*afdbf109SJoseph Mingrone pcapint_add_dev(pcap_if_list_t *devlistp, const char *name, bpf_u_int32 flags,
1320b00ab754SHans Petter Selasky const char *description, char *errbuf)
1321b00ab754SHans Petter Selasky {
1322b00ab754SHans Petter Selasky pcap_if_t *curdev, *prevdev, *nextdev;
1323b00ab754SHans Petter Selasky u_int this_figure_of_merit, nextdev_figure_of_merit;
1324b00ab754SHans Petter Selasky
1325b00ab754SHans Petter Selasky curdev = malloc(sizeof(pcap_if_t));
1326b00ab754SHans Petter Selasky if (curdev == NULL) {
1327*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1328b00ab754SHans Petter Selasky errno, "malloc");
1329b00ab754SHans Petter Selasky return (NULL);
1330b00ab754SHans Petter Selasky }
1331b00ab754SHans Petter Selasky
1332b00ab754SHans Petter Selasky /*
1333b00ab754SHans Petter Selasky * Fill in the entry.
1334b00ab754SHans Petter Selasky */
1335b00ab754SHans Petter Selasky curdev->next = NULL;
1336b00ab754SHans Petter Selasky curdev->name = strdup(name);
1337b00ab754SHans Petter Selasky if (curdev->name == NULL) {
1338*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1339b00ab754SHans Petter Selasky errno, "malloc");
1340b00ab754SHans Petter Selasky free(curdev);
1341b00ab754SHans Petter Selasky return (NULL);
1342b00ab754SHans Petter Selasky }
1343b00ab754SHans Petter Selasky if (description == NULL) {
1344b00ab754SHans Petter Selasky /*
1345b00ab754SHans Petter Selasky * We weren't handed a description for the interface.
1346b00ab754SHans Petter Selasky */
1347b00ab754SHans Petter Selasky curdev->description = NULL;
1348b00ab754SHans Petter Selasky } else {
1349b00ab754SHans Petter Selasky /*
1350b00ab754SHans Petter Selasky * We were handed a description; make a copy.
1351b00ab754SHans Petter Selasky */
1352b00ab754SHans Petter Selasky curdev->description = strdup(description);
1353b00ab754SHans Petter Selasky if (curdev->description == NULL) {
1354*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1355b00ab754SHans Petter Selasky errno, "malloc");
1356b00ab754SHans Petter Selasky free(curdev->name);
1357b00ab754SHans Petter Selasky free(curdev);
1358b00ab754SHans Petter Selasky return (NULL);
1359b00ab754SHans Petter Selasky }
1360b00ab754SHans Petter Selasky }
1361b00ab754SHans Petter Selasky curdev->addresses = NULL; /* list starts out as empty */
1362b00ab754SHans Petter Selasky curdev->flags = flags;
1363b00ab754SHans Petter Selasky
1364b00ab754SHans Petter Selasky /*
1365b00ab754SHans Petter Selasky * Add it to the list, in the appropriate location.
1366b00ab754SHans Petter Selasky * First, get the "figure of merit" for this interface.
1367b00ab754SHans Petter Selasky */
1368b00ab754SHans Petter Selasky this_figure_of_merit = get_figure_of_merit(curdev);
1369b00ab754SHans Petter Selasky
1370b00ab754SHans Petter Selasky /*
1371b00ab754SHans Petter Selasky * Now look for the last interface with an figure of merit
1372b00ab754SHans Petter Selasky * less than or equal to the new interface's figure of merit.
1373b00ab754SHans Petter Selasky *
1374b00ab754SHans Petter Selasky * We start with "prevdev" being NULL, meaning we're before
1375b00ab754SHans Petter Selasky * the first element in the list.
1376b00ab754SHans Petter Selasky */
1377b00ab754SHans Petter Selasky prevdev = NULL;
1378b00ab754SHans Petter Selasky for (;;) {
1379b00ab754SHans Petter Selasky /*
1380b00ab754SHans Petter Selasky * Get the interface after this one.
1381b00ab754SHans Petter Selasky */
1382b00ab754SHans Petter Selasky if (prevdev == NULL) {
1383b00ab754SHans Petter Selasky /*
1384b00ab754SHans Petter Selasky * The next element is the first element.
1385b00ab754SHans Petter Selasky */
1386b00ab754SHans Petter Selasky nextdev = devlistp->beginning;
1387b00ab754SHans Petter Selasky } else
1388b00ab754SHans Petter Selasky nextdev = prevdev->next;
1389b00ab754SHans Petter Selasky
1390b00ab754SHans Petter Selasky /*
1391b00ab754SHans Petter Selasky * Are we at the end of the list?
1392b00ab754SHans Petter Selasky */
1393b00ab754SHans Petter Selasky if (nextdev == NULL) {
1394b00ab754SHans Petter Selasky /*
1395b00ab754SHans Petter Selasky * Yes - we have to put the new entry after "prevdev".
1396b00ab754SHans Petter Selasky */
1397b00ab754SHans Petter Selasky break;
1398b00ab754SHans Petter Selasky }
1399b00ab754SHans Petter Selasky
1400b00ab754SHans Petter Selasky /*
1401b00ab754SHans Petter Selasky * Is the new interface's figure of merit less
1402b00ab754SHans Petter Selasky * than the next interface's figure of merit,
1403b00ab754SHans Petter Selasky * meaning that the new interface is better
1404b00ab754SHans Petter Selasky * than the next interface?
1405b00ab754SHans Petter Selasky */
1406b00ab754SHans Petter Selasky nextdev_figure_of_merit = get_figure_of_merit(nextdev);
1407b00ab754SHans Petter Selasky if (this_figure_of_merit < nextdev_figure_of_merit) {
1408b00ab754SHans Petter Selasky /*
1409b00ab754SHans Petter Selasky * Yes - we should put the new entry
1410b00ab754SHans Petter Selasky * before "nextdev", i.e. after "prevdev".
1411b00ab754SHans Petter Selasky */
1412b00ab754SHans Petter Selasky break;
1413b00ab754SHans Petter Selasky }
1414b00ab754SHans Petter Selasky
1415b00ab754SHans Petter Selasky prevdev = nextdev;
1416b00ab754SHans Petter Selasky }
1417b00ab754SHans Petter Selasky
1418b00ab754SHans Petter Selasky /*
1419b00ab754SHans Petter Selasky * Insert before "nextdev".
1420b00ab754SHans Petter Selasky */
1421b00ab754SHans Petter Selasky curdev->next = nextdev;
1422b00ab754SHans Petter Selasky
1423b00ab754SHans Petter Selasky /*
1424b00ab754SHans Petter Selasky * Insert after "prevdev" - unless "prevdev" is null,
1425b00ab754SHans Petter Selasky * in which case this is the first interface.
1426b00ab754SHans Petter Selasky */
1427b00ab754SHans Petter Selasky if (prevdev == NULL) {
1428b00ab754SHans Petter Selasky /*
1429b00ab754SHans Petter Selasky * This is the first interface. Make it
1430b00ab754SHans Petter Selasky * the first element in the list of devices.
1431b00ab754SHans Petter Selasky */
1432b00ab754SHans Petter Selasky devlistp->beginning = curdev;
1433b00ab754SHans Petter Selasky } else
1434b00ab754SHans Petter Selasky prevdev->next = curdev;
1435b00ab754SHans Petter Selasky return (curdev);
1436b00ab754SHans Petter Selasky }
1437b00ab754SHans Petter Selasky
1438b00ab754SHans Petter Selasky /*
1439*afdbf109SJoseph Mingrone * Add an entry for the "any" device.
1440*afdbf109SJoseph Mingrone */
1441*afdbf109SJoseph Mingrone pcap_if_t *
1442*afdbf109SJoseph Mingrone pcap_add_any_dev(pcap_if_list_t *devlistp, char *errbuf)
1443*afdbf109SJoseph Mingrone {
1444*afdbf109SJoseph Mingrone static const char any_descr[] = "Pseudo-device that captures on all interfaces";
1445*afdbf109SJoseph Mingrone
1446*afdbf109SJoseph Mingrone /*
1447*afdbf109SJoseph Mingrone * As it refers to all network devices, not to any particular
1448*afdbf109SJoseph Mingrone * network device, the notion of "connected" vs. "disconnected"
1449*afdbf109SJoseph Mingrone * doesn't apply to the "any" device.
1450*afdbf109SJoseph Mingrone */
1451*afdbf109SJoseph Mingrone return pcapint_add_dev(devlistp, "any",
1452*afdbf109SJoseph Mingrone PCAP_IF_UP|PCAP_IF_RUNNING|PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
1453*afdbf109SJoseph Mingrone any_descr, errbuf);
1454*afdbf109SJoseph Mingrone }
1455*afdbf109SJoseph Mingrone
1456*afdbf109SJoseph Mingrone /*
1457b00ab754SHans Petter Selasky * Free a list of interfaces.
1458b00ab754SHans Petter Selasky */
1459b00ab754SHans Petter Selasky void
1460b00ab754SHans Petter Selasky pcap_freealldevs(pcap_if_t *alldevs)
1461b00ab754SHans Petter Selasky {
1462b00ab754SHans Petter Selasky pcap_if_t *curdev, *nextdev;
1463b00ab754SHans Petter Selasky pcap_addr_t *curaddr, *nextaddr;
1464b00ab754SHans Petter Selasky
1465b00ab754SHans Petter Selasky for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
1466b00ab754SHans Petter Selasky nextdev = curdev->next;
1467b00ab754SHans Petter Selasky
1468b00ab754SHans Petter Selasky /*
1469b00ab754SHans Petter Selasky * Free all addresses.
1470b00ab754SHans Petter Selasky */
1471b00ab754SHans Petter Selasky for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
1472b00ab754SHans Petter Selasky nextaddr = curaddr->next;
1473b00ab754SHans Petter Selasky if (curaddr->addr)
1474b00ab754SHans Petter Selasky free(curaddr->addr);
1475b00ab754SHans Petter Selasky if (curaddr->netmask)
1476b00ab754SHans Petter Selasky free(curaddr->netmask);
1477b00ab754SHans Petter Selasky if (curaddr->broadaddr)
1478b00ab754SHans Petter Selasky free(curaddr->broadaddr);
1479b00ab754SHans Petter Selasky if (curaddr->dstaddr)
1480b00ab754SHans Petter Selasky free(curaddr->dstaddr);
1481b00ab754SHans Petter Selasky free(curaddr);
1482b00ab754SHans Petter Selasky }
1483b00ab754SHans Petter Selasky
1484b00ab754SHans Petter Selasky /*
1485b00ab754SHans Petter Selasky * Free the name string.
1486b00ab754SHans Petter Selasky */
1487b00ab754SHans Petter Selasky free(curdev->name);
1488b00ab754SHans Petter Selasky
1489b00ab754SHans Petter Selasky /*
1490b00ab754SHans Petter Selasky * Free the description string, if any.
1491b00ab754SHans Petter Selasky */
1492b00ab754SHans Petter Selasky if (curdev->description != NULL)
1493b00ab754SHans Petter Selasky free(curdev->description);
1494b00ab754SHans Petter Selasky
1495b00ab754SHans Petter Selasky /*
1496b00ab754SHans Petter Selasky * Free the interface.
1497b00ab754SHans Petter Selasky */
1498b00ab754SHans Petter Selasky free(curdev);
1499b00ab754SHans Petter Selasky }
1500b00ab754SHans Petter Selasky }
1501b00ab754SHans Petter Selasky
1502b00ab754SHans Petter Selasky /*
1503b00ab754SHans Petter Selasky * pcap-npf.c has its own pcap_lookupdev(), for compatibility reasons, as
1504b00ab754SHans Petter Selasky * it actually returns the names of all interfaces, with a NUL separator
1505b00ab754SHans Petter Selasky * between them; some callers may depend on that.
1506b00ab754SHans Petter Selasky *
1507b00ab754SHans Petter Selasky * MS-DOS has its own pcap_lookupdev(), but that might be useful only
1508b00ab754SHans Petter Selasky * as an optimization.
1509b00ab754SHans Petter Selasky *
1510b00ab754SHans Petter Selasky * In all other cases, we just use pcap_findalldevs() to get a list of
1511b00ab754SHans Petter Selasky * devices, and pick from that list.
1512b00ab754SHans Petter Selasky */
1513b00ab754SHans Petter Selasky #if !defined(HAVE_PACKET32) && !defined(MSDOS)
1514b00ab754SHans Petter Selasky /*
1515b00ab754SHans Petter Selasky * Return the name of a network interface attached to the system, or NULL
1516b00ab754SHans Petter Selasky * if none can be found. The interface must be configured up; the
1517b00ab754SHans Petter Selasky * lowest unit number is preferred; loopback is ignored.
1518b00ab754SHans Petter Selasky */
1519b00ab754SHans Petter Selasky char *
1520b00ab754SHans Petter Selasky pcap_lookupdev(char *errbuf)
1521b00ab754SHans Petter Selasky {
1522b00ab754SHans Petter Selasky pcap_if_t *alldevs;
1523b00ab754SHans Petter Selasky #ifdef _WIN32
1524b00ab754SHans Petter Selasky /*
1525b00ab754SHans Petter Selasky * Windows - use the same size as the old WinPcap 3.1 code.
1526b00ab754SHans Petter Selasky * XXX - this is probably bigger than it needs to be.
1527b00ab754SHans Petter Selasky */
1528b00ab754SHans Petter Selasky #define IF_NAMESIZE 8192
1529b00ab754SHans Petter Selasky #else
1530b00ab754SHans Petter Selasky /*
1531b00ab754SHans Petter Selasky * UN*X - use the system's interface name size.
1532b00ab754SHans Petter Selasky * XXX - that might not be large enough for capture devices
1533b00ab754SHans Petter Selasky * that aren't regular network interfaces.
1534b00ab754SHans Petter Selasky */
1535b00ab754SHans Petter Selasky /* for old BSD systems, including bsdi3 */
1536b00ab754SHans Petter Selasky #ifndef IF_NAMESIZE
1537b00ab754SHans Petter Selasky #define IF_NAMESIZE IFNAMSIZ
1538b00ab754SHans Petter Selasky #endif
1539b00ab754SHans Petter Selasky #endif
1540b00ab754SHans Petter Selasky static char device[IF_NAMESIZE + 1];
1541b00ab754SHans Petter Selasky char *ret;
1542b00ab754SHans Petter Selasky
15436f9cba8fSJoseph Mingrone /*
15446f9cba8fSJoseph Mingrone * We disable this in "new API" mode, because 1) in WinPcap/Npcap,
15456f9cba8fSJoseph Mingrone * it may return UTF-16 strings, for backwards-compatibility
15466f9cba8fSJoseph Mingrone * reasons, and we're also disabling the hack to make that work,
15476f9cba8fSJoseph Mingrone * for not-going-past-the-end-of-a-string reasons, and 2) we
15486f9cba8fSJoseph Mingrone * want its behavior to be consistent.
15496f9cba8fSJoseph Mingrone *
15506f9cba8fSJoseph Mingrone * In addition, it's not thread-safe, so we've marked it as
15516f9cba8fSJoseph Mingrone * deprecated.
15526f9cba8fSJoseph Mingrone */
1553*afdbf109SJoseph Mingrone if (pcapint_new_api) {
15546f9cba8fSJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE,
15556f9cba8fSJoseph Mingrone "pcap_lookupdev() is deprecated and is not supported in programs calling pcap_init()");
15566f9cba8fSJoseph Mingrone return (NULL);
15576f9cba8fSJoseph Mingrone }
15586f9cba8fSJoseph Mingrone
1559b00ab754SHans Petter Selasky if (pcap_findalldevs(&alldevs, errbuf) == -1)
1560b00ab754SHans Petter Selasky return (NULL);
1561b00ab754SHans Petter Selasky
1562b00ab754SHans Petter Selasky if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
1563b00ab754SHans Petter Selasky /*
1564b00ab754SHans Petter Selasky * There are no devices on the list, or the first device
1565b00ab754SHans Petter Selasky * on the list is a loopback device, which means there
1566b00ab754SHans Petter Selasky * are no non-loopback devices on the list. This means
1567b00ab754SHans Petter Selasky * we can't return any device.
1568b00ab754SHans Petter Selasky *
1569b00ab754SHans Petter Selasky * XXX - why not return a loopback device? If we can't
1570b00ab754SHans Petter Selasky * capture on it, it won't be on the list, and if it's
1571b00ab754SHans Petter Selasky * on the list, there aren't any non-loopback devices,
1572b00ab754SHans Petter Selasky * so why not just supply it as the default device?
1573b00ab754SHans Petter Selasky */
1574*afdbf109SJoseph Mingrone (void)pcapint_strlcpy(errbuf, "no suitable device found",
1575b00ab754SHans Petter Selasky PCAP_ERRBUF_SIZE);
1576b00ab754SHans Petter Selasky ret = NULL;
1577b00ab754SHans Petter Selasky } else {
1578b00ab754SHans Petter Selasky /*
1579b00ab754SHans Petter Selasky * Return the name of the first device on the list.
1580b00ab754SHans Petter Selasky */
1581*afdbf109SJoseph Mingrone (void)pcapint_strlcpy(device, alldevs->name, sizeof(device));
1582b00ab754SHans Petter Selasky ret = device;
1583b00ab754SHans Petter Selasky }
1584b00ab754SHans Petter Selasky
1585b00ab754SHans Petter Selasky pcap_freealldevs(alldevs);
1586b00ab754SHans Petter Selasky return (ret);
1587b00ab754SHans Petter Selasky }
1588b00ab754SHans Petter Selasky #endif /* !defined(HAVE_PACKET32) && !defined(MSDOS) */
1589b00ab754SHans Petter Selasky
1590b00ab754SHans Petter Selasky #if !defined(_WIN32) && !defined(MSDOS)
1591b00ab754SHans Petter Selasky /*
1592b00ab754SHans Petter Selasky * We don't just fetch the entire list of devices, search for the
1593b00ab754SHans Petter Selasky * particular device, and use its first IPv4 address, as that's too
1594b00ab754SHans Petter Selasky * much work to get just one device's netmask.
1595b00ab754SHans Petter Selasky *
1596b00ab754SHans Petter Selasky * If we had an API to get attributes for a given device, we could
1597b00ab754SHans Petter Selasky * use that.
1598b00ab754SHans Petter Selasky */
1599b00ab754SHans Petter Selasky int
1600b00ab754SHans Petter Selasky pcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp,
1601b00ab754SHans Petter Selasky char *errbuf)
1602b00ab754SHans Petter Selasky {
1603b00ab754SHans Petter Selasky register int fd;
1604b00ab754SHans Petter Selasky register struct sockaddr_in *sin4;
1605b00ab754SHans Petter Selasky struct ifreq ifr;
1606b00ab754SHans Petter Selasky
1607b00ab754SHans Petter Selasky /*
1608b00ab754SHans Petter Selasky * The pseudo-device "any" listens on all interfaces and therefore
1609b00ab754SHans Petter Selasky * has the network address and -mask "0.0.0.0" therefore catching
1610b00ab754SHans Petter Selasky * all traffic. Using NULL for the interface is the same as "any".
1611b00ab754SHans Petter Selasky */
1612b00ab754SHans Petter Selasky if (!device || strcmp(device, "any") == 0
1613b00ab754SHans Petter Selasky #ifdef HAVE_DAG_API
1614b00ab754SHans Petter Selasky || strstr(device, "dag") != NULL
1615b00ab754SHans Petter Selasky #endif
1616b00ab754SHans Petter Selasky #ifdef HAVE_SEPTEL_API
1617b00ab754SHans Petter Selasky || strstr(device, "septel") != NULL
1618b00ab754SHans Petter Selasky #endif
1619b00ab754SHans Petter Selasky #ifdef PCAP_SUPPORT_BT
1620b00ab754SHans Petter Selasky || strstr(device, "bluetooth") != NULL
1621b00ab754SHans Petter Selasky #endif
16226f9cba8fSJoseph Mingrone #ifdef PCAP_SUPPORT_LINUX_USBMON
1623b00ab754SHans Petter Selasky || strstr(device, "usbmon") != NULL
1624b00ab754SHans Petter Selasky #endif
1625b00ab754SHans Petter Selasky #ifdef HAVE_SNF_API
1626b00ab754SHans Petter Selasky || strstr(device, "snf") != NULL
1627b00ab754SHans Petter Selasky #endif
1628b00ab754SHans Petter Selasky #ifdef PCAP_SUPPORT_NETMAP
1629b00ab754SHans Petter Selasky || strncmp(device, "netmap:", 7) == 0
1630b00ab754SHans Petter Selasky || strncmp(device, "vale", 4) == 0
1631b00ab754SHans Petter Selasky #endif
16326f9cba8fSJoseph Mingrone #ifdef PCAP_SUPPORT_DPDK
16336f9cba8fSJoseph Mingrone || strncmp(device, "dpdk:", 5) == 0
16346f9cba8fSJoseph Mingrone #endif
1635b00ab754SHans Petter Selasky ) {
1636b00ab754SHans Petter Selasky *netp = *maskp = 0;
1637b00ab754SHans Petter Selasky return 0;
1638b00ab754SHans Petter Selasky }
1639b00ab754SHans Petter Selasky
1640b00ab754SHans Petter Selasky fd = socket(AF_INET, SOCK_DGRAM, 0);
1641b00ab754SHans Petter Selasky if (fd < 0) {
1642*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1643b00ab754SHans Petter Selasky errno, "socket");
1644b00ab754SHans Petter Selasky return (-1);
1645b00ab754SHans Petter Selasky }
1646b00ab754SHans Petter Selasky memset(&ifr, 0, sizeof(ifr));
1647*afdbf109SJoseph Mingrone #ifdef __linux__
1648b00ab754SHans Petter Selasky /* XXX Work around Linux kernel bug */
1649b00ab754SHans Petter Selasky ifr.ifr_addr.sa_family = AF_INET;
1650b00ab754SHans Petter Selasky #endif
1651*afdbf109SJoseph Mingrone (void)pcapint_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
1652*afdbf109SJoseph Mingrone #if defined(__HAIKU__) && defined(__clang__)
1653*afdbf109SJoseph Mingrone /*
1654*afdbf109SJoseph Mingrone * In Haiku R1/beta4 <unistd.h> ioctl() is a macro that needs to take 4
1655*afdbf109SJoseph Mingrone * arguments to initialize its intermediate 2-member structure fully so
1656*afdbf109SJoseph Mingrone * that Clang does not generate a -Wmissing-field-initializers warning
1657*afdbf109SJoseph Mingrone * (which manifests only when it runs with -Werror). This workaround
1658*afdbf109SJoseph Mingrone * can be removed as soon as there is a Haiku release that fixes the
1659*afdbf109SJoseph Mingrone * problem. See also https://review.haiku-os.org/c/haiku/+/6369
1660*afdbf109SJoseph Mingrone */
1661*afdbf109SJoseph Mingrone if (ioctl(fd, SIOCGIFADDR, (char *)&ifr, sizeof(ifr)) < 0) {
1662*afdbf109SJoseph Mingrone #else
1663b00ab754SHans Petter Selasky if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
1664*afdbf109SJoseph Mingrone #endif /* __HAIKU__ && __clang__ */
1665b00ab754SHans Petter Selasky if (errno == EADDRNOTAVAIL) {
16666f9cba8fSJoseph Mingrone (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
1667b00ab754SHans Petter Selasky "%s: no IPv4 address assigned", device);
1668b00ab754SHans Petter Selasky } else {
1669*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1670b00ab754SHans Petter Selasky errno, "SIOCGIFADDR: %s", device);
1671b00ab754SHans Petter Selasky }
1672b00ab754SHans Petter Selasky (void)close(fd);
1673b00ab754SHans Petter Selasky return (-1);
1674b00ab754SHans Petter Selasky }
1675b00ab754SHans Petter Selasky sin4 = (struct sockaddr_in *)&ifr.ifr_addr;
1676b00ab754SHans Petter Selasky *netp = sin4->sin_addr.s_addr;
1677b00ab754SHans Petter Selasky memset(&ifr, 0, sizeof(ifr));
1678*afdbf109SJoseph Mingrone #ifdef __linux__
1679b00ab754SHans Petter Selasky /* XXX Work around Linux kernel bug */
1680b00ab754SHans Petter Selasky ifr.ifr_addr.sa_family = AF_INET;
1681b00ab754SHans Petter Selasky #endif
1682*afdbf109SJoseph Mingrone (void)pcapint_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
1683*afdbf109SJoseph Mingrone #if defined(__HAIKU__) && defined(__clang__)
1684*afdbf109SJoseph Mingrone /* Same as above. */
1685*afdbf109SJoseph Mingrone if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr, sizeof(ifr)) < 0) {
1686*afdbf109SJoseph Mingrone #else
1687b00ab754SHans Petter Selasky if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
1688*afdbf109SJoseph Mingrone #endif /* __HAIKU__ && __clang__ */
1689*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1690b00ab754SHans Petter Selasky errno, "SIOCGIFNETMASK: %s", device);
1691b00ab754SHans Petter Selasky (void)close(fd);
1692b00ab754SHans Petter Selasky return (-1);
1693b00ab754SHans Petter Selasky }
1694b00ab754SHans Petter Selasky (void)close(fd);
1695b00ab754SHans Petter Selasky *maskp = sin4->sin_addr.s_addr;
1696b00ab754SHans Petter Selasky if (*maskp == 0) {
1697b00ab754SHans Petter Selasky if (IN_CLASSA(*netp))
1698b00ab754SHans Petter Selasky *maskp = IN_CLASSA_NET;
1699b00ab754SHans Petter Selasky else if (IN_CLASSB(*netp))
1700b00ab754SHans Petter Selasky *maskp = IN_CLASSB_NET;
1701b00ab754SHans Petter Selasky else if (IN_CLASSC(*netp))
1702b00ab754SHans Petter Selasky *maskp = IN_CLASSC_NET;
1703b00ab754SHans Petter Selasky else {
17046f9cba8fSJoseph Mingrone (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
1705b00ab754SHans Petter Selasky "inet class for 0x%x unknown", *netp);
1706b00ab754SHans Petter Selasky return (-1);
1707b00ab754SHans Petter Selasky }
1708b00ab754SHans Petter Selasky }
1709b00ab754SHans Petter Selasky *netp &= *maskp;
1710b00ab754SHans Petter Selasky return (0);
1711b00ab754SHans Petter Selasky }
1712b00ab754SHans Petter Selasky #endif /* !defined(_WIN32) && !defined(MSDOS) */
1713b00ab754SHans Petter Selasky
1714b00ab754SHans Petter Selasky #ifdef ENABLE_REMOTE
1715b00ab754SHans Petter Selasky #include "pcap-rpcap.h"
1716b00ab754SHans Petter Selasky
1717b00ab754SHans Petter Selasky /*
1718b00ab754SHans Petter Selasky * Extract a substring from a string.
1719b00ab754SHans Petter Selasky */
1720b00ab754SHans Petter Selasky static char *
1721b00ab754SHans Petter Selasky get_substring(const char *p, size_t len, char *ebuf)
1722b00ab754SHans Petter Selasky {
1723b00ab754SHans Petter Selasky char *token;
1724b00ab754SHans Petter Selasky
1725b00ab754SHans Petter Selasky token = malloc(len + 1);
1726b00ab754SHans Petter Selasky if (token == NULL) {
1727*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
1728b00ab754SHans Petter Selasky errno, "malloc");
1729b00ab754SHans Petter Selasky return (NULL);
1730b00ab754SHans Petter Selasky }
1731b00ab754SHans Petter Selasky memcpy(token, p, len);
1732b00ab754SHans Petter Selasky token[len] = '\0';
1733b00ab754SHans Petter Selasky return (token);
1734b00ab754SHans Petter Selasky }
1735b00ab754SHans Petter Selasky
1736b00ab754SHans Petter Selasky /*
1737b00ab754SHans Petter Selasky * Parse a capture source that might be a URL.
1738b00ab754SHans Petter Selasky *
1739b00ab754SHans Petter Selasky * If the source is not a URL, *schemep, *userinfop, *hostp, and *portp
1740b00ab754SHans Petter Selasky * are set to NULL, *pathp is set to point to the source, and 0 is
1741b00ab754SHans Petter Selasky * returned.
1742b00ab754SHans Petter Selasky *
1743b00ab754SHans Petter Selasky * If source is a URL, and the URL refers to a local device (a special
1744b00ab754SHans Petter Selasky * case of rpcap:), *schemep, *userinfop, *hostp, and *portp are set
1745b00ab754SHans Petter Selasky * to NULL, *pathp is set to point to the device name, and 0 is returned.
1746b00ab754SHans Petter Selasky *
1747b00ab754SHans Petter Selasky * If source is a URL, and it's not a special case that refers to a local
1748b00ab754SHans Petter Selasky * device, and the parse succeeds:
1749b00ab754SHans Petter Selasky *
1750b00ab754SHans Petter Selasky * *schemep is set to point to an allocated string containing the scheme;
1751b00ab754SHans Petter Selasky *
1752b00ab754SHans Petter Selasky * if user information is present in the URL, *userinfop is set to point
1753b00ab754SHans Petter Selasky * to an allocated string containing the user information, otherwise
1754b00ab754SHans Petter Selasky * it's set to NULL;
1755b00ab754SHans Petter Selasky *
1756b00ab754SHans Petter Selasky * if host information is present in the URL, *hostp is set to point
1757b00ab754SHans Petter Selasky * to an allocated string containing the host information, otherwise
1758b00ab754SHans Petter Selasky * it's set to NULL;
1759b00ab754SHans Petter Selasky *
1760b00ab754SHans Petter Selasky * if a port number is present in the URL, *portp is set to point
1761b00ab754SHans Petter Selasky * to an allocated string containing the port number, otherwise
1762b00ab754SHans Petter Selasky * it's set to NULL;
1763b00ab754SHans Petter Selasky *
1764b00ab754SHans Petter Selasky * *pathp is set to point to an allocated string containing the
1765b00ab754SHans Petter Selasky * path;
1766b00ab754SHans Petter Selasky *
1767b00ab754SHans Petter Selasky * and 0 is returned.
1768b00ab754SHans Petter Selasky *
1769b00ab754SHans Petter Selasky * If the parse fails, ebuf is set to an error string, and -1 is returned.
1770b00ab754SHans Petter Selasky */
1771b00ab754SHans Petter Selasky static int
1772b00ab754SHans Petter Selasky pcap_parse_source(const char *source, char **schemep, char **userinfop,
1773b00ab754SHans Petter Selasky char **hostp, char **portp, char **pathp, char *ebuf)
1774b00ab754SHans Petter Selasky {
1775b00ab754SHans Petter Selasky char *colonp;
1776b00ab754SHans Petter Selasky size_t scheme_len;
1777b00ab754SHans Petter Selasky char *scheme;
1778b00ab754SHans Petter Selasky const char *endp;
1779b00ab754SHans Petter Selasky size_t authority_len;
1780b00ab754SHans Petter Selasky char *authority;
1781b00ab754SHans Petter Selasky char *parsep, *atsignp, *bracketp;
1782b00ab754SHans Petter Selasky char *userinfo, *host, *port, *path;
1783b00ab754SHans Petter Selasky
1784b00ab754SHans Petter Selasky /*
1785b00ab754SHans Petter Selasky * Start out returning nothing.
1786b00ab754SHans Petter Selasky */
1787b00ab754SHans Petter Selasky *schemep = NULL;
1788b00ab754SHans Petter Selasky *userinfop = NULL;
1789b00ab754SHans Petter Selasky *hostp = NULL;
1790b00ab754SHans Petter Selasky *portp = NULL;
1791b00ab754SHans Petter Selasky *pathp = NULL;
1792b00ab754SHans Petter Selasky
1793b00ab754SHans Petter Selasky /*
1794b00ab754SHans Petter Selasky * RFC 3986 says:
1795b00ab754SHans Petter Selasky *
1796b00ab754SHans Petter Selasky * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
1797b00ab754SHans Petter Selasky *
1798b00ab754SHans Petter Selasky * hier-part = "//" authority path-abempty
1799b00ab754SHans Petter Selasky * / path-absolute
1800b00ab754SHans Petter Selasky * / path-rootless
1801b00ab754SHans Petter Selasky * / path-empty
1802b00ab754SHans Petter Selasky *
1803b00ab754SHans Petter Selasky * authority = [ userinfo "@" ] host [ ":" port ]
1804b00ab754SHans Petter Selasky *
1805b00ab754SHans Petter Selasky * userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
1806b00ab754SHans Petter Selasky *
1807b00ab754SHans Petter Selasky * Step 1: look for the ":" at the end of the scheme.
1808b00ab754SHans Petter Selasky * A colon in the source is *NOT* sufficient to indicate that
1809b00ab754SHans Petter Selasky * this is a URL, as interface names on some platforms might
1810b00ab754SHans Petter Selasky * include colons (e.g., I think some Solaris interfaces
1811b00ab754SHans Petter Selasky * might).
1812b00ab754SHans Petter Selasky */
1813b00ab754SHans Petter Selasky colonp = strchr(source, ':');
1814b00ab754SHans Petter Selasky if (colonp == NULL) {
1815b00ab754SHans Petter Selasky /*
1816b00ab754SHans Petter Selasky * The source is the device to open.
1817b00ab754SHans Petter Selasky * Return a NULL pointer for the scheme, user information,
1818b00ab754SHans Petter Selasky * host, and port, and return the device as the path.
1819b00ab754SHans Petter Selasky */
1820b00ab754SHans Petter Selasky *pathp = strdup(source);
1821b00ab754SHans Petter Selasky if (*pathp == NULL) {
1822*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
1823b00ab754SHans Petter Selasky errno, "malloc");
1824b00ab754SHans Petter Selasky return (-1);
1825b00ab754SHans Petter Selasky }
1826b00ab754SHans Petter Selasky return (0);
1827b00ab754SHans Petter Selasky }
1828b00ab754SHans Petter Selasky
1829b00ab754SHans Petter Selasky /*
1830b00ab754SHans Petter Selasky * All schemes must have "//" after them, i.e. we only support
1831b00ab754SHans Petter Selasky * hier-part = "//" authority path-abempty, not
1832b00ab754SHans Petter Selasky * hier-part = path-absolute
1833b00ab754SHans Petter Selasky * hier-part = path-rootless
1834b00ab754SHans Petter Selasky * hier-part = path-empty
1835b00ab754SHans Petter Selasky *
1836b00ab754SHans Petter Selasky * We need that in order to distinguish between a local device
1837b00ab754SHans Petter Selasky * name that happens to contain a colon and a URI.
1838b00ab754SHans Petter Selasky */
1839b00ab754SHans Petter Selasky if (strncmp(colonp + 1, "//", 2) != 0) {
1840b00ab754SHans Petter Selasky /*
1841b00ab754SHans Petter Selasky * The source is the device to open.
1842b00ab754SHans Petter Selasky * Return a NULL pointer for the scheme, user information,
1843b00ab754SHans Petter Selasky * host, and port, and return the device as the path.
1844b00ab754SHans Petter Selasky */
1845b00ab754SHans Petter Selasky *pathp = strdup(source);
1846b00ab754SHans Petter Selasky if (*pathp == NULL) {
1847*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
1848b00ab754SHans Petter Selasky errno, "malloc");
1849b00ab754SHans Petter Selasky return (-1);
1850b00ab754SHans Petter Selasky }
1851b00ab754SHans Petter Selasky return (0);
1852b00ab754SHans Petter Selasky }
1853b00ab754SHans Petter Selasky
1854b00ab754SHans Petter Selasky /*
1855b00ab754SHans Petter Selasky * XXX - check whether the purported scheme could be a scheme?
1856b00ab754SHans Petter Selasky */
1857b00ab754SHans Petter Selasky
1858b00ab754SHans Petter Selasky /*
1859b00ab754SHans Petter Selasky * OK, this looks like a URL.
1860b00ab754SHans Petter Selasky * Get the scheme.
1861b00ab754SHans Petter Selasky */
1862b00ab754SHans Petter Selasky scheme_len = colonp - source;
1863b00ab754SHans Petter Selasky scheme = malloc(scheme_len + 1);
1864b00ab754SHans Petter Selasky if (scheme == NULL) {
1865*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
1866b00ab754SHans Petter Selasky errno, "malloc");
1867b00ab754SHans Petter Selasky return (-1);
1868b00ab754SHans Petter Selasky }
1869b00ab754SHans Petter Selasky memcpy(scheme, source, scheme_len);
1870b00ab754SHans Petter Selasky scheme[scheme_len] = '\0';
1871b00ab754SHans Petter Selasky
1872b00ab754SHans Petter Selasky /*
1873b00ab754SHans Petter Selasky * Treat file: specially - take everything after file:// as
1874b00ab754SHans Petter Selasky * the pathname.
1875b00ab754SHans Petter Selasky */
1876*afdbf109SJoseph Mingrone if (pcapint_strcasecmp(scheme, "file") == 0) {
1877b00ab754SHans Petter Selasky *pathp = strdup(colonp + 3);
1878b00ab754SHans Petter Selasky if (*pathp == NULL) {
1879*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
1880b00ab754SHans Petter Selasky errno, "malloc");
188157e22627SCy Schubert free(scheme);
1882b00ab754SHans Petter Selasky return (-1);
1883b00ab754SHans Petter Selasky }
188457e22627SCy Schubert *schemep = scheme;
1885b00ab754SHans Petter Selasky return (0);
1886b00ab754SHans Petter Selasky }
1887b00ab754SHans Petter Selasky
1888b00ab754SHans Petter Selasky /*
1889b00ab754SHans Petter Selasky * The WinPcap documentation says you can specify a local
1890b00ab754SHans Petter Selasky * interface with "rpcap://{device}"; we special-case
1891b00ab754SHans Petter Selasky * that here. If the scheme is "rpcap", and there are
1892b00ab754SHans Petter Selasky * no slashes past the "//", we just return the device.
1893b00ab754SHans Petter Selasky *
1894b00ab754SHans Petter Selasky * XXX - %-escaping?
1895b00ab754SHans Petter Selasky */
1896*afdbf109SJoseph Mingrone if ((pcapint_strcasecmp(scheme, "rpcap") == 0 ||
1897*afdbf109SJoseph Mingrone pcapint_strcasecmp(scheme, "rpcaps") == 0) &&
1898b00ab754SHans Petter Selasky strchr(colonp + 3, '/') == NULL) {
1899b00ab754SHans Petter Selasky /*
1900b00ab754SHans Petter Selasky * Local device.
1901b00ab754SHans Petter Selasky *
1902b00ab754SHans Petter Selasky * Return a NULL pointer for the scheme, user information,
1903b00ab754SHans Petter Selasky * host, and port, and return the device as the path.
1904b00ab754SHans Petter Selasky */
1905b00ab754SHans Petter Selasky free(scheme);
1906b00ab754SHans Petter Selasky *pathp = strdup(colonp + 3);
1907b00ab754SHans Petter Selasky if (*pathp == NULL) {
1908*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
1909b00ab754SHans Petter Selasky errno, "malloc");
1910b00ab754SHans Petter Selasky return (-1);
1911b00ab754SHans Petter Selasky }
1912b00ab754SHans Petter Selasky return (0);
1913b00ab754SHans Petter Selasky }
1914b00ab754SHans Petter Selasky
1915b00ab754SHans Petter Selasky /*
1916b00ab754SHans Petter Selasky * OK, now start parsing the authority.
1917b00ab754SHans Petter Selasky * Get token, terminated with / or terminated at the end of
1918b00ab754SHans Petter Selasky * the string.
1919b00ab754SHans Petter Selasky */
1920b00ab754SHans Petter Selasky authority_len = strcspn(colonp + 3, "/");
1921b00ab754SHans Petter Selasky authority = get_substring(colonp + 3, authority_len, ebuf);
1922b00ab754SHans Petter Selasky if (authority == NULL) {
1923b00ab754SHans Petter Selasky /*
1924b00ab754SHans Petter Selasky * Error.
1925b00ab754SHans Petter Selasky */
1926b00ab754SHans Petter Selasky free(scheme);
1927b00ab754SHans Petter Selasky return (-1);
1928b00ab754SHans Petter Selasky }
1929b00ab754SHans Petter Selasky endp = colonp + 3 + authority_len;
1930b00ab754SHans Petter Selasky
1931b00ab754SHans Petter Selasky /*
1932b00ab754SHans Petter Selasky * Now carve the authority field into its components.
1933b00ab754SHans Petter Selasky */
1934b00ab754SHans Petter Selasky parsep = authority;
1935b00ab754SHans Petter Selasky
1936b00ab754SHans Petter Selasky /*
1937b00ab754SHans Petter Selasky * Is there a userinfo field?
1938b00ab754SHans Petter Selasky */
1939b00ab754SHans Petter Selasky atsignp = strchr(parsep, '@');
1940b00ab754SHans Petter Selasky if (atsignp != NULL) {
1941b00ab754SHans Petter Selasky /*
1942b00ab754SHans Petter Selasky * Yes.
1943b00ab754SHans Petter Selasky */
1944b00ab754SHans Petter Selasky size_t userinfo_len;
1945b00ab754SHans Petter Selasky
1946b00ab754SHans Petter Selasky userinfo_len = atsignp - parsep;
1947b00ab754SHans Petter Selasky userinfo = get_substring(parsep, userinfo_len, ebuf);
1948b00ab754SHans Petter Selasky if (userinfo == NULL) {
1949b00ab754SHans Petter Selasky /*
1950b00ab754SHans Petter Selasky * Error.
1951b00ab754SHans Petter Selasky */
1952b00ab754SHans Petter Selasky free(authority);
1953b00ab754SHans Petter Selasky free(scheme);
1954b00ab754SHans Petter Selasky return (-1);
1955b00ab754SHans Petter Selasky }
1956b00ab754SHans Petter Selasky parsep = atsignp + 1;
1957b00ab754SHans Petter Selasky } else {
1958b00ab754SHans Petter Selasky /*
1959b00ab754SHans Petter Selasky * No.
1960b00ab754SHans Petter Selasky */
1961b00ab754SHans Petter Selasky userinfo = NULL;
1962b00ab754SHans Petter Selasky }
1963b00ab754SHans Petter Selasky
1964b00ab754SHans Petter Selasky /*
1965b00ab754SHans Petter Selasky * Is there a host field?
1966b00ab754SHans Petter Selasky */
1967b00ab754SHans Petter Selasky if (*parsep == '\0') {
1968b00ab754SHans Petter Selasky /*
1969b00ab754SHans Petter Selasky * No; there's no host field or port field.
1970b00ab754SHans Petter Selasky */
1971b00ab754SHans Petter Selasky host = NULL;
1972b00ab754SHans Petter Selasky port = NULL;
1973b00ab754SHans Petter Selasky } else {
1974b00ab754SHans Petter Selasky /*
1975b00ab754SHans Petter Selasky * Yes.
1976b00ab754SHans Petter Selasky */
1977b00ab754SHans Petter Selasky size_t host_len;
1978b00ab754SHans Petter Selasky
1979b00ab754SHans Petter Selasky /*
1980b00ab754SHans Petter Selasky * Is it an IP-literal?
1981b00ab754SHans Petter Selasky */
1982b00ab754SHans Petter Selasky if (*parsep == '[') {
1983b00ab754SHans Petter Selasky /*
1984b00ab754SHans Petter Selasky * Yes.
1985*afdbf109SJoseph Mingrone * Treat everything up to the closing square
1986b00ab754SHans Petter Selasky * bracket as the IP-Literal; we don't worry
1987b00ab754SHans Petter Selasky * about whether it's a valid IPv6address or
198857e22627SCy Schubert * IPvFuture (or an IPv4address, for that
198957e22627SCy Schubert * matter, just in case we get handed a
199057e22627SCy Schubert * URL with an IPv4 IP-Literal, of the sort
199157e22627SCy Schubert * that pcap_createsrcstr() used to generate,
199257e22627SCy Schubert * and that pcap_parsesrcstr(), in the original
199357e22627SCy Schubert * WinPcap code, accepted).
1994b00ab754SHans Petter Selasky */
1995b00ab754SHans Petter Selasky bracketp = strchr(parsep, ']');
1996b00ab754SHans Petter Selasky if (bracketp == NULL) {
1997b00ab754SHans Petter Selasky /*
1998b00ab754SHans Petter Selasky * There's no closing square bracket.
1999b00ab754SHans Petter Selasky */
20006f9cba8fSJoseph Mingrone snprintf(ebuf, PCAP_ERRBUF_SIZE,
2001b00ab754SHans Petter Selasky "IP-literal in URL doesn't end with ]");
2002b00ab754SHans Petter Selasky free(userinfo);
2003b00ab754SHans Petter Selasky free(authority);
2004b00ab754SHans Petter Selasky free(scheme);
2005b00ab754SHans Petter Selasky return (-1);
2006b00ab754SHans Petter Selasky }
2007b00ab754SHans Petter Selasky if (*(bracketp + 1) != '\0' &&
2008b00ab754SHans Petter Selasky *(bracketp + 1) != ':') {
2009b00ab754SHans Petter Selasky /*
2010b00ab754SHans Petter Selasky * There's extra crud after the
2011*afdbf109SJoseph Mingrone * closing square bracket.
2012b00ab754SHans Petter Selasky */
20136f9cba8fSJoseph Mingrone snprintf(ebuf, PCAP_ERRBUF_SIZE,
2014b00ab754SHans Petter Selasky "Extra text after IP-literal in URL");
2015b00ab754SHans Petter Selasky free(userinfo);
2016b00ab754SHans Petter Selasky free(authority);
2017b00ab754SHans Petter Selasky free(scheme);
2018b00ab754SHans Petter Selasky return (-1);
2019b00ab754SHans Petter Selasky }
2020b00ab754SHans Petter Selasky host_len = (bracketp - 1) - parsep;
2021b00ab754SHans Petter Selasky host = get_substring(parsep + 1, host_len, ebuf);
2022b00ab754SHans Petter Selasky if (host == NULL) {
2023b00ab754SHans Petter Selasky /*
2024b00ab754SHans Petter Selasky * Error.
2025b00ab754SHans Petter Selasky */
2026b00ab754SHans Petter Selasky free(userinfo);
2027b00ab754SHans Petter Selasky free(authority);
2028b00ab754SHans Petter Selasky free(scheme);
2029b00ab754SHans Petter Selasky return (-1);
2030b00ab754SHans Petter Selasky }
2031b00ab754SHans Petter Selasky parsep = bracketp + 1;
2032b00ab754SHans Petter Selasky } else {
2033b00ab754SHans Petter Selasky /*
2034b00ab754SHans Petter Selasky * No.
2035b00ab754SHans Petter Selasky * Treat everything up to a : or the end of
2036b00ab754SHans Petter Selasky * the string as the host.
2037b00ab754SHans Petter Selasky */
2038b00ab754SHans Petter Selasky host_len = strcspn(parsep, ":");
2039b00ab754SHans Petter Selasky host = get_substring(parsep, host_len, ebuf);
2040b00ab754SHans Petter Selasky if (host == NULL) {
2041b00ab754SHans Petter Selasky /*
2042b00ab754SHans Petter Selasky * Error.
2043b00ab754SHans Petter Selasky */
2044b00ab754SHans Petter Selasky free(userinfo);
2045b00ab754SHans Petter Selasky free(authority);
2046b00ab754SHans Petter Selasky free(scheme);
2047b00ab754SHans Petter Selasky return (-1);
2048b00ab754SHans Petter Selasky }
2049b00ab754SHans Petter Selasky parsep = parsep + host_len;
2050b00ab754SHans Petter Selasky }
2051b00ab754SHans Petter Selasky
2052b00ab754SHans Petter Selasky /*
2053b00ab754SHans Petter Selasky * Is there a port field?
2054b00ab754SHans Petter Selasky */
2055b00ab754SHans Petter Selasky if (*parsep == ':') {
2056b00ab754SHans Petter Selasky /*
2057b00ab754SHans Petter Selasky * Yes. It's the rest of the authority field.
2058b00ab754SHans Petter Selasky */
2059b00ab754SHans Petter Selasky size_t port_len;
2060b00ab754SHans Petter Selasky
2061b00ab754SHans Petter Selasky parsep++;
2062b00ab754SHans Petter Selasky port_len = strlen(parsep);
2063b00ab754SHans Petter Selasky port = get_substring(parsep, port_len, ebuf);
2064b00ab754SHans Petter Selasky if (port == NULL) {
2065b00ab754SHans Petter Selasky /*
2066b00ab754SHans Petter Selasky * Error.
2067b00ab754SHans Petter Selasky */
2068b00ab754SHans Petter Selasky free(host);
2069b00ab754SHans Petter Selasky free(userinfo);
2070b00ab754SHans Petter Selasky free(authority);
2071b00ab754SHans Petter Selasky free(scheme);
2072b00ab754SHans Petter Selasky return (-1);
2073b00ab754SHans Petter Selasky }
2074b00ab754SHans Petter Selasky } else {
2075b00ab754SHans Petter Selasky /*
2076b00ab754SHans Petter Selasky * No.
2077b00ab754SHans Petter Selasky */
2078b00ab754SHans Petter Selasky port = NULL;
2079b00ab754SHans Petter Selasky }
2080b00ab754SHans Petter Selasky }
2081b00ab754SHans Petter Selasky free(authority);
2082b00ab754SHans Petter Selasky
2083b00ab754SHans Petter Selasky /*
2084b00ab754SHans Petter Selasky * Everything else is the path. Strip off the leading /.
2085b00ab754SHans Petter Selasky */
2086b00ab754SHans Petter Selasky if (*endp == '\0')
2087b00ab754SHans Petter Selasky path = strdup("");
2088b00ab754SHans Petter Selasky else
2089b00ab754SHans Petter Selasky path = strdup(endp + 1);
2090b00ab754SHans Petter Selasky if (path == NULL) {
2091*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
2092b00ab754SHans Petter Selasky errno, "malloc");
2093b00ab754SHans Petter Selasky free(port);
2094b00ab754SHans Petter Selasky free(host);
2095b00ab754SHans Petter Selasky free(userinfo);
2096b00ab754SHans Petter Selasky free(scheme);
2097b00ab754SHans Petter Selasky return (-1);
2098b00ab754SHans Petter Selasky }
2099b00ab754SHans Petter Selasky *schemep = scheme;
2100b00ab754SHans Petter Selasky *userinfop = userinfo;
2101b00ab754SHans Petter Selasky *hostp = host;
2102b00ab754SHans Petter Selasky *portp = port;
2103b00ab754SHans Petter Selasky *pathp = path;
2104b00ab754SHans Petter Selasky return (0);
2105b00ab754SHans Petter Selasky }
2106b00ab754SHans Petter Selasky
2107b00ab754SHans Petter Selasky int
2108*afdbf109SJoseph Mingrone pcapint_createsrcstr_ex(char *source, int type, const char *host, const char *port,
21096f9cba8fSJoseph Mingrone const char *name, unsigned char uses_ssl, char *errbuf)
2110b00ab754SHans Petter Selasky {
2111b00ab754SHans Petter Selasky switch (type) {
2112b00ab754SHans Petter Selasky
2113b00ab754SHans Petter Selasky case PCAP_SRC_FILE:
2114*afdbf109SJoseph Mingrone pcapint_strlcpy(source, PCAP_SRC_FILE_STRING, PCAP_BUF_SIZE);
2115b00ab754SHans Petter Selasky if (name != NULL && *name != '\0') {
2116*afdbf109SJoseph Mingrone pcapint_strlcat(source, name, PCAP_BUF_SIZE);
2117b00ab754SHans Petter Selasky return (0);
2118b00ab754SHans Petter Selasky } else {
21196f9cba8fSJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE,
2120b00ab754SHans Petter Selasky "The file name cannot be NULL.");
2121b00ab754SHans Petter Selasky return (-1);
2122b00ab754SHans Petter Selasky }
2123b00ab754SHans Petter Selasky
2124b00ab754SHans Petter Selasky case PCAP_SRC_IFREMOTE:
2125*afdbf109SJoseph Mingrone pcapint_strlcpy(source,
21266f9cba8fSJoseph Mingrone (uses_ssl ? "rpcaps://" : PCAP_SRC_IF_STRING),
21276f9cba8fSJoseph Mingrone PCAP_BUF_SIZE);
2128b00ab754SHans Petter Selasky if (host != NULL && *host != '\0') {
2129b00ab754SHans Petter Selasky if (strchr(host, ':') != NULL) {
2130b00ab754SHans Petter Selasky /*
2131b00ab754SHans Petter Selasky * The host name contains a colon, so it's
2132b00ab754SHans Petter Selasky * probably an IPv6 address, and needs to
2133b00ab754SHans Petter Selasky * be included in square brackets.
2134b00ab754SHans Petter Selasky */
2135*afdbf109SJoseph Mingrone pcapint_strlcat(source, "[", PCAP_BUF_SIZE);
2136*afdbf109SJoseph Mingrone pcapint_strlcat(source, host, PCAP_BUF_SIZE);
2137*afdbf109SJoseph Mingrone pcapint_strlcat(source, "]", PCAP_BUF_SIZE);
2138b00ab754SHans Petter Selasky } else
2139*afdbf109SJoseph Mingrone pcapint_strlcat(source, host, PCAP_BUF_SIZE);
2140b00ab754SHans Petter Selasky
2141b00ab754SHans Petter Selasky if (port != NULL && *port != '\0') {
2142*afdbf109SJoseph Mingrone pcapint_strlcat(source, ":", PCAP_BUF_SIZE);
2143*afdbf109SJoseph Mingrone pcapint_strlcat(source, port, PCAP_BUF_SIZE);
2144b00ab754SHans Petter Selasky }
2145b00ab754SHans Petter Selasky
2146*afdbf109SJoseph Mingrone pcapint_strlcat(source, "/", PCAP_BUF_SIZE);
2147b00ab754SHans Petter Selasky } else {
21486f9cba8fSJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE,
2149b00ab754SHans Petter Selasky "The host name cannot be NULL.");
2150b00ab754SHans Petter Selasky return (-1);
2151b00ab754SHans Petter Selasky }
2152b00ab754SHans Petter Selasky
2153b00ab754SHans Petter Selasky if (name != NULL && *name != '\0')
2154*afdbf109SJoseph Mingrone pcapint_strlcat(source, name, PCAP_BUF_SIZE);
2155b00ab754SHans Petter Selasky
2156b00ab754SHans Petter Selasky return (0);
2157b00ab754SHans Petter Selasky
2158b00ab754SHans Petter Selasky case PCAP_SRC_IFLOCAL:
2159*afdbf109SJoseph Mingrone pcapint_strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
2160b00ab754SHans Petter Selasky
2161b00ab754SHans Petter Selasky if (name != NULL && *name != '\0')
2162*afdbf109SJoseph Mingrone pcapint_strlcat(source, name, PCAP_BUF_SIZE);
2163b00ab754SHans Petter Selasky
2164b00ab754SHans Petter Selasky return (0);
2165b00ab754SHans Petter Selasky
2166b00ab754SHans Petter Selasky default:
21676f9cba8fSJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE,
2168b00ab754SHans Petter Selasky "The interface type is not valid.");
2169b00ab754SHans Petter Selasky return (-1);
2170b00ab754SHans Petter Selasky }
2171b00ab754SHans Petter Selasky }
2172b00ab754SHans Petter Selasky
21736f9cba8fSJoseph Mingrone
2174b00ab754SHans Petter Selasky int
21756f9cba8fSJoseph Mingrone pcap_createsrcstr(char *source, int type, const char *host, const char *port,
21766f9cba8fSJoseph Mingrone const char *name, char *errbuf)
21776f9cba8fSJoseph Mingrone {
2178*afdbf109SJoseph Mingrone return (pcapint_createsrcstr_ex(source, type, host, port, name, 0, errbuf));
21796f9cba8fSJoseph Mingrone }
21806f9cba8fSJoseph Mingrone
21816f9cba8fSJoseph Mingrone int
2182*afdbf109SJoseph Mingrone pcapint_parsesrcstr_ex(const char *source, int *type, char *host, char *port,
21836f9cba8fSJoseph Mingrone char *name, unsigned char *uses_ssl, char *errbuf)
2184b00ab754SHans Petter Selasky {
2185b00ab754SHans Petter Selasky char *scheme, *tmpuserinfo, *tmphost, *tmpport, *tmppath;
2186b00ab754SHans Petter Selasky
2187b00ab754SHans Petter Selasky /* Initialization stuff */
2188b00ab754SHans Petter Selasky if (host)
2189b00ab754SHans Petter Selasky *host = '\0';
2190b00ab754SHans Petter Selasky if (port)
2191b00ab754SHans Petter Selasky *port = '\0';
2192b00ab754SHans Petter Selasky if (name)
2193b00ab754SHans Petter Selasky *name = '\0';
21946f9cba8fSJoseph Mingrone if (uses_ssl)
21956f9cba8fSJoseph Mingrone *uses_ssl = 0;
2196b00ab754SHans Petter Selasky
2197b00ab754SHans Petter Selasky /* Parse the source string */
2198b00ab754SHans Petter Selasky if (pcap_parse_source(source, &scheme, &tmpuserinfo, &tmphost,
2199b00ab754SHans Petter Selasky &tmpport, &tmppath, errbuf) == -1) {
2200b00ab754SHans Petter Selasky /*
2201b00ab754SHans Petter Selasky * Fail.
2202b00ab754SHans Petter Selasky */
2203b00ab754SHans Petter Selasky return (-1);
2204b00ab754SHans Petter Selasky }
2205b00ab754SHans Petter Selasky
2206b00ab754SHans Petter Selasky if (scheme == NULL) {
2207b00ab754SHans Petter Selasky /*
2208b00ab754SHans Petter Selasky * Local device.
2209b00ab754SHans Petter Selasky */
2210b00ab754SHans Petter Selasky if (name && tmppath)
2211*afdbf109SJoseph Mingrone pcapint_strlcpy(name, tmppath, PCAP_BUF_SIZE);
2212b00ab754SHans Petter Selasky if (type)
2213b00ab754SHans Petter Selasky *type = PCAP_SRC_IFLOCAL;
2214b00ab754SHans Petter Selasky free(tmppath);
2215b00ab754SHans Petter Selasky free(tmpport);
2216b00ab754SHans Petter Selasky free(tmphost);
2217b00ab754SHans Petter Selasky free(tmpuserinfo);
2218b00ab754SHans Petter Selasky return (0);
2219b00ab754SHans Petter Selasky }
2220b00ab754SHans Petter Selasky
22216f9cba8fSJoseph Mingrone int is_rpcap = 0;
22226f9cba8fSJoseph Mingrone if (strcmp(scheme, "rpcaps") == 0) {
22236f9cba8fSJoseph Mingrone is_rpcap = 1;
22246f9cba8fSJoseph Mingrone if (uses_ssl) *uses_ssl = 1;
22256f9cba8fSJoseph Mingrone } else if (strcmp(scheme, "rpcap") == 0) {
22266f9cba8fSJoseph Mingrone is_rpcap = 1;
22276f9cba8fSJoseph Mingrone }
22286f9cba8fSJoseph Mingrone
22296f9cba8fSJoseph Mingrone if (is_rpcap) {
2230b00ab754SHans Petter Selasky /*
22316f9cba8fSJoseph Mingrone * rpcap[s]://
2232b00ab754SHans Petter Selasky *
2233b00ab754SHans Petter Selasky * pcap_parse_source() has already handled the case of
22346f9cba8fSJoseph Mingrone * rpcap[s]://device
2235b00ab754SHans Petter Selasky */
2236b00ab754SHans Petter Selasky if (host && tmphost) {
2237b00ab754SHans Petter Selasky if (tmpuserinfo)
22386f9cba8fSJoseph Mingrone snprintf(host, PCAP_BUF_SIZE, "%s@%s",
2239b00ab754SHans Petter Selasky tmpuserinfo, tmphost);
2240b00ab754SHans Petter Selasky else
2241*afdbf109SJoseph Mingrone pcapint_strlcpy(host, tmphost, PCAP_BUF_SIZE);
2242b00ab754SHans Petter Selasky }
2243b00ab754SHans Petter Selasky if (port && tmpport)
2244*afdbf109SJoseph Mingrone pcapint_strlcpy(port, tmpport, PCAP_BUF_SIZE);
2245b00ab754SHans Petter Selasky if (name && tmppath)
2246*afdbf109SJoseph Mingrone pcapint_strlcpy(name, tmppath, PCAP_BUF_SIZE);
2247b00ab754SHans Petter Selasky if (type)
2248b00ab754SHans Petter Selasky *type = PCAP_SRC_IFREMOTE;
2249b00ab754SHans Petter Selasky free(tmppath);
2250b00ab754SHans Petter Selasky free(tmpport);
2251b00ab754SHans Petter Selasky free(tmphost);
2252b00ab754SHans Petter Selasky free(tmpuserinfo);
2253b00ab754SHans Petter Selasky free(scheme);
2254b00ab754SHans Petter Selasky return (0);
2255b00ab754SHans Petter Selasky }
2256b00ab754SHans Petter Selasky
2257b00ab754SHans Petter Selasky if (strcmp(scheme, "file") == 0) {
2258b00ab754SHans Petter Selasky /*
2259b00ab754SHans Petter Selasky * file://
2260b00ab754SHans Petter Selasky */
2261b00ab754SHans Petter Selasky if (name && tmppath)
2262*afdbf109SJoseph Mingrone pcapint_strlcpy(name, tmppath, PCAP_BUF_SIZE);
2263b00ab754SHans Petter Selasky if (type)
2264b00ab754SHans Petter Selasky *type = PCAP_SRC_FILE;
2265b00ab754SHans Petter Selasky free(tmppath);
2266b00ab754SHans Petter Selasky free(tmpport);
2267b00ab754SHans Petter Selasky free(tmphost);
2268b00ab754SHans Petter Selasky free(tmpuserinfo);
2269b00ab754SHans Petter Selasky free(scheme);
2270b00ab754SHans Petter Selasky return (0);
2271b00ab754SHans Petter Selasky }
2272b00ab754SHans Petter Selasky
2273b00ab754SHans Petter Selasky /*
2274b00ab754SHans Petter Selasky * Neither rpcap: nor file:; just treat the entire string
2275b00ab754SHans Petter Selasky * as a local device.
2276b00ab754SHans Petter Selasky */
2277b00ab754SHans Petter Selasky if (name)
2278*afdbf109SJoseph Mingrone pcapint_strlcpy(name, source, PCAP_BUF_SIZE);
2279b00ab754SHans Petter Selasky if (type)
2280b00ab754SHans Petter Selasky *type = PCAP_SRC_IFLOCAL;
2281b00ab754SHans Petter Selasky free(tmppath);
2282b00ab754SHans Petter Selasky free(tmpport);
2283b00ab754SHans Petter Selasky free(tmphost);
2284b00ab754SHans Petter Selasky free(tmpuserinfo);
2285b00ab754SHans Petter Selasky free(scheme);
2286b00ab754SHans Petter Selasky return (0);
2287b00ab754SHans Petter Selasky }
22886f9cba8fSJoseph Mingrone
22896f9cba8fSJoseph Mingrone int
22906f9cba8fSJoseph Mingrone pcap_parsesrcstr(const char *source, int *type, char *host, char *port,
22916f9cba8fSJoseph Mingrone char *name, char *errbuf)
22926f9cba8fSJoseph Mingrone {
2293*afdbf109SJoseph Mingrone return (pcapint_parsesrcstr_ex(source, type, host, port, name, NULL, errbuf));
22946f9cba8fSJoseph Mingrone }
2295b00ab754SHans Petter Selasky #endif
2296b00ab754SHans Petter Selasky
2297edc89b24SXin LI pcap_t *
2298ada6f083SXin LI pcap_create(const char *device, char *errbuf)
2299edc89b24SXin LI {
2300edc89b24SXin LI size_t i;
2301edc89b24SXin LI int is_theirs;
2302edc89b24SXin LI pcap_t *p;
2303ada6f083SXin LI char *device_str;
2304edc89b24SXin LI
2305edc89b24SXin LI /*
2306ada6f083SXin LI * A null device name is equivalent to the "any" device -
2307edc89b24SXin LI * which might not be supported on this platform, but
2308edc89b24SXin LI * this means that you'll get a "not supported" error
2309edc89b24SXin LI * rather than, say, a crash when we try to dereference
2310edc89b24SXin LI * the null pointer.
2311edc89b24SXin LI */
2312ada6f083SXin LI if (device == NULL)
2313ada6f083SXin LI device_str = strdup("any");
2314ada6f083SXin LI else {
2315ada6f083SXin LI #ifdef _WIN32
2316ada6f083SXin LI /*
231757e22627SCy Schubert * On Windows, for backwards compatibility reasons,
231857e22627SCy Schubert * pcap_lookupdev() returns a pointer to a sequence of
231957e22627SCy Schubert * pairs of UTF-16LE device names and local code page
232057e22627SCy Schubert * description strings.
2321ada6f083SXin LI *
232257e22627SCy Schubert * This means that if a program uses pcap_lookupdev()
232357e22627SCy Schubert * to get a default device, and hands that to an API
232457e22627SCy Schubert * that opens devices, we'll get handed a UTF-16LE
232557e22627SCy Schubert * string, not a string in the local code page.
232657e22627SCy Schubert *
232757e22627SCy Schubert * To work around that, we check whether the string
23286f9cba8fSJoseph Mingrone * looks as if it might be a UTF-16LE string and, if
232957e22627SCy Schubert * so, convert it back to the local code page's
233057e22627SCy Schubert * extended ASCII.
233157e22627SCy Schubert *
23326f9cba8fSJoseph Mingrone * We disable that check in "new API" mode, because:
23336f9cba8fSJoseph Mingrone *
23346f9cba8fSJoseph Mingrone * 1) You *cannot* reliably detect whether a
233557e22627SCy Schubert * string is UTF-16LE or not; "a" could either
233657e22627SCy Schubert * be a one-character ASCII string or the first
23376f9cba8fSJoseph Mingrone * character of a UTF-16LE string.
23386f9cba8fSJoseph Mingrone *
23396f9cba8fSJoseph Mingrone * 2) Doing that test can run past the end of
23406f9cba8fSJoseph Mingrone * the string, if it's a 1-character ASCII
23416f9cba8fSJoseph Mingrone * string
23426f9cba8fSJoseph Mingrone *
23436f9cba8fSJoseph Mingrone * This particular version of this heuristic dates
23446f9cba8fSJoseph Mingrone * back to WinPcap 4.1.1; PacketOpenAdapter() does
23456f9cba8fSJoseph Mingrone * uses the same heuristic, with the exact same
23466f9cba8fSJoseph Mingrone * vulnerability.
23476f9cba8fSJoseph Mingrone *
23486f9cba8fSJoseph Mingrone * That's why we disable this in "new API" mode.
23496f9cba8fSJoseph Mingrone * We keep it around in legacy mode for backwards
23506f9cba8fSJoseph Mingrone * compatibility.
2351ada6f083SXin LI */
2352*afdbf109SJoseph Mingrone if (!pcapint_new_api && device[0] != '\0' && device[1] == '\0') {
2353ada6f083SXin LI size_t length;
2354ada6f083SXin LI
2355ada6f083SXin LI length = wcslen((wchar_t *)device);
2356ada6f083SXin LI device_str = (char *)malloc(length + 1);
2357ada6f083SXin LI if (device_str == NULL) {
2358*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf,
2359b00ab754SHans Petter Selasky PCAP_ERRBUF_SIZE, errno,
2360b00ab754SHans Petter Selasky "malloc");
2361ada6f083SXin LI return (NULL);
2362ada6f083SXin LI }
2363ada6f083SXin LI
23646f9cba8fSJoseph Mingrone snprintf(device_str, length + 1, "%ws",
2365ada6f083SXin LI (const wchar_t *)device);
2366ada6f083SXin LI } else
2367ada6f083SXin LI #endif
2368ada6f083SXin LI device_str = strdup(device);
2369ada6f083SXin LI }
2370ada6f083SXin LI if (device_str == NULL) {
2371*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
2372b00ab754SHans Petter Selasky errno, "malloc");
2373ada6f083SXin LI return (NULL);
2374ada6f083SXin LI }
2375edc89b24SXin LI
2376edc89b24SXin LI /*
2377edc89b24SXin LI * Try each of the non-local-network-interface capture
2378edc89b24SXin LI * source types until we find one that works for this
2379edc89b24SXin LI * device or run out of types.
2380edc89b24SXin LI */
2381edc89b24SXin LI for (i = 0; capture_source_types[i].create_op != NULL; i++) {
2382edc89b24SXin LI is_theirs = 0;
2383ada6f083SXin LI p = capture_source_types[i].create_op(device_str, errbuf,
2384ada6f083SXin LI &is_theirs);
2385edc89b24SXin LI if (is_theirs) {
2386edc89b24SXin LI /*
2387edc89b24SXin LI * The device name refers to a device of the
2388edc89b24SXin LI * type in question; either it succeeded,
2389edc89b24SXin LI * in which case p refers to a pcap_t to
2390edc89b24SXin LI * later activate for the device, or it
2391edc89b24SXin LI * failed, in which case p is null and we
2392edc89b24SXin LI * should return that to report the failure
2393edc89b24SXin LI * to create.
2394edc89b24SXin LI */
2395ada6f083SXin LI if (p == NULL) {
2396ada6f083SXin LI /*
2397ada6f083SXin LI * We assume the caller filled in errbuf.
2398ada6f083SXin LI */
2399ada6f083SXin LI free(device_str);
2400ada6f083SXin LI return (NULL);
2401ada6f083SXin LI }
2402ada6f083SXin LI p->opt.device = device_str;
2403edc89b24SXin LI return (p);
2404edc89b24SXin LI }
2405edc89b24SXin LI }
2406edc89b24SXin LI
2407edc89b24SXin LI /*
2408edc89b24SXin LI * OK, try it as a regular network interface.
2409edc89b24SXin LI */
2410*afdbf109SJoseph Mingrone p = pcapint_create_interface(device_str, errbuf);
2411ada6f083SXin LI if (p == NULL) {
2412ada6f083SXin LI /*
2413ada6f083SXin LI * We assume the caller filled in errbuf.
2414ada6f083SXin LI */
2415ada6f083SXin LI free(device_str);
2416ada6f083SXin LI return (NULL);
2417edc89b24SXin LI }
2418ada6f083SXin LI p->opt.device = device_str;
2419ada6f083SXin LI return (p);
2420ada6f083SXin LI }
2421edc89b24SXin LI
2422b00ab754SHans Petter Selasky /*
2423b00ab754SHans Petter Selasky * Set nonblocking mode on an unactivated pcap_t; this sets a flag
2424b00ab754SHans Petter Selasky * checked by pcap_activate(), which sets the mode after calling
2425b00ab754SHans Petter Selasky * the activate routine.
2426b00ab754SHans Petter Selasky */
2427b00ab754SHans Petter Selasky static int
2428b00ab754SHans Petter Selasky pcap_setnonblock_unactivated(pcap_t *p, int nonblock)
2429b00ab754SHans Petter Selasky {
2430b00ab754SHans Petter Selasky p->opt.nonblock = nonblock;
2431b00ab754SHans Petter Selasky return (0);
2432b00ab754SHans Petter Selasky }
2433b00ab754SHans Petter Selasky
2434a0ee43a1SRui Paulo static void
2435a0ee43a1SRui Paulo initialize_ops(pcap_t *p)
2436a0ee43a1SRui Paulo {
2437a0ee43a1SRui Paulo /*
2438a0ee43a1SRui Paulo * Set operation pointers for operations that only work on
2439a0ee43a1SRui Paulo * an activated pcap_t to point to a routine that returns
2440a0ee43a1SRui Paulo * a "this isn't activated" error.
2441a8e07101SRui Paulo */
244257e22627SCy Schubert p->read_op = pcap_read_not_initialized;
244357e22627SCy Schubert p->inject_op = pcap_inject_not_initialized;
244457e22627SCy Schubert p->setfilter_op = pcap_setfilter_not_initialized;
244557e22627SCy Schubert p->setdirection_op = pcap_setdirection_not_initialized;
244657e22627SCy Schubert p->set_datalink_op = pcap_set_datalink_not_initialized;
244757e22627SCy Schubert p->getnonblock_op = pcap_getnonblock_not_initialized;
244857e22627SCy Schubert p->stats_op = pcap_stats_not_initialized;
2449ada6f083SXin LI #ifdef _WIN32
245057e22627SCy Schubert p->stats_ex_op = pcap_stats_ex_not_initialized;
245157e22627SCy Schubert p->setbuff_op = pcap_setbuff_not_initialized;
245257e22627SCy Schubert p->setmode_op = pcap_setmode_not_initialized;
245357e22627SCy Schubert p->setmintocopy_op = pcap_setmintocopy_not_initialized;
2454ada6f083SXin LI p->getevent_op = pcap_getevent_not_initialized;
245557e22627SCy Schubert p->oid_get_request_op = pcap_oid_get_request_not_initialized;
245657e22627SCy Schubert p->oid_set_request_op = pcap_oid_set_request_not_initialized;
2457ada6f083SXin LI p->sendqueue_transmit_op = pcap_sendqueue_transmit_not_initialized;
245857e22627SCy Schubert p->setuserbuffer_op = pcap_setuserbuffer_not_initialized;
245957e22627SCy Schubert p->live_dump_op = pcap_live_dump_not_initialized;
246057e22627SCy Schubert p->live_dump_ended_op = pcap_live_dump_ended_not_initialized;
2461ada6f083SXin LI p->get_airpcap_handle_op = pcap_get_airpcap_handle_not_initialized;
2462a8e07101SRui Paulo #endif
2463a0ee43a1SRui Paulo
2464a0ee43a1SRui Paulo /*
2465a0ee43a1SRui Paulo * Default cleanup operation - implementations can override
2466*afdbf109SJoseph Mingrone * this, but should call pcapint_cleanup_live_common() after
2467a0ee43a1SRui Paulo * doing their own additional cleanup.
2468a0ee43a1SRui Paulo */
2469*afdbf109SJoseph Mingrone p->cleanup_op = pcapint_cleanup_live_common;
2470a8e07101SRui Paulo
2471a0ee43a1SRui Paulo /*
2472681ed54cSXin LI * In most cases, the standard one-shot callback can
2473a0ee43a1SRui Paulo * be used for pcap_next()/pcap_next_ex().
2474a0ee43a1SRui Paulo */
2475*afdbf109SJoseph Mingrone p->oneshot_callback = pcapint_oneshot;
24766f9cba8fSJoseph Mingrone
24776f9cba8fSJoseph Mingrone /*
24786f9cba8fSJoseph Mingrone * Default breakloop operation - implementations can override
2479*afdbf109SJoseph Mingrone * this, but should call pcapint_breakloop_common() before doing
24806f9cba8fSJoseph Mingrone * their own logic.
24816f9cba8fSJoseph Mingrone */
2482*afdbf109SJoseph Mingrone p->breakloop_op = pcapint_breakloop_common;
2483a0ee43a1SRui Paulo }
2484a0ee43a1SRui Paulo
2485681ed54cSXin LI static pcap_t *
24866f9cba8fSJoseph Mingrone pcap_alloc_pcap_t(char *ebuf, size_t total_size, size_t private_offset)
2487a0ee43a1SRui Paulo {
2488681ed54cSXin LI char *chunk;
2489a0ee43a1SRui Paulo pcap_t *p;
2490a0ee43a1SRui Paulo
2491681ed54cSXin LI /*
24926f9cba8fSJoseph Mingrone * total_size is the size of a structure containing a pcap_t
24936f9cba8fSJoseph Mingrone * followed by a private structure.
2494681ed54cSXin LI */
24956f9cba8fSJoseph Mingrone chunk = calloc(total_size, 1);
2496681ed54cSXin LI if (chunk == NULL) {
2497*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
2498b00ab754SHans Petter Selasky errno, "malloc");
2499a0ee43a1SRui Paulo return (NULL);
2500a0ee43a1SRui Paulo }
2501681ed54cSXin LI
2502681ed54cSXin LI /*
2503681ed54cSXin LI * Get a pointer to the pcap_t at the beginning.
2504681ed54cSXin LI */
2505681ed54cSXin LI p = (pcap_t *)chunk;
2506681ed54cSXin LI
2507b00ab754SHans Petter Selasky #ifdef _WIN32
2508b00ab754SHans Petter Selasky p->handle = INVALID_HANDLE_VALUE; /* not opened yet */
2509b00ab754SHans Petter Selasky #else /* _WIN32 */
2510a0ee43a1SRui Paulo p->fd = -1; /* not opened yet */
2511b00ab754SHans Petter Selasky #ifndef MSDOS
2512a0ee43a1SRui Paulo p->selectable_fd = -1;
2513b00ab754SHans Petter Selasky p->required_select_timeout = NULL;
2514b00ab754SHans Petter Selasky #endif /* MSDOS */
2515b00ab754SHans Petter Selasky #endif /* _WIN32 */
2516a0ee43a1SRui Paulo
2517681ed54cSXin LI /*
25186f9cba8fSJoseph Mingrone * private_offset is the offset, in bytes, of the private
25196f9cba8fSJoseph Mingrone * data from the beginning of the structure.
25206f9cba8fSJoseph Mingrone *
25216f9cba8fSJoseph Mingrone * Set the pointer to the private data; that's private_offset
25226f9cba8fSJoseph Mingrone * bytes past the pcap_t.
2523681ed54cSXin LI */
25246f9cba8fSJoseph Mingrone p->priv = (void *)(chunk + private_offset);
2525681ed54cSXin LI
2526681ed54cSXin LI return (p);
2527681ed54cSXin LI }
2528681ed54cSXin LI
2529681ed54cSXin LI pcap_t *
2530*afdbf109SJoseph Mingrone pcapint_create_common(char *ebuf, size_t total_size, size_t private_offset)
2531681ed54cSXin LI {
2532681ed54cSXin LI pcap_t *p;
2533681ed54cSXin LI
25346f9cba8fSJoseph Mingrone p = pcap_alloc_pcap_t(ebuf, total_size, private_offset);
2535681ed54cSXin LI if (p == NULL)
2536681ed54cSXin LI return (NULL);
2537681ed54cSXin LI
2538a0ee43a1SRui Paulo /*
2539a0ee43a1SRui Paulo * Default to "can't set rfmon mode"; if it's supported by
2540a0ee43a1SRui Paulo * a platform, the create routine that called us can set
2541a0ee43a1SRui Paulo * the op to its routine to check whether a particular
2542a0ee43a1SRui Paulo * device supports it.
2543a0ee43a1SRui Paulo */
2544a0ee43a1SRui Paulo p->can_set_rfmon_op = pcap_cant_set_rfmon;
2545a0ee43a1SRui Paulo
2546b00ab754SHans Petter Selasky /*
2547b00ab754SHans Petter Selasky * If pcap_setnonblock() is called on a not-yet-activated
2548b00ab754SHans Petter Selasky * pcap_t, default to setting a flag and turning
2549b00ab754SHans Petter Selasky * on non-blocking mode when activated.
2550b00ab754SHans Petter Selasky */
2551b00ab754SHans Petter Selasky p->setnonblock_op = pcap_setnonblock_unactivated;
2552b00ab754SHans Petter Selasky
2553a0ee43a1SRui Paulo initialize_ops(p);
2554a0ee43a1SRui Paulo
2555a8e07101SRui Paulo /* put in some defaults*/
2556b00ab754SHans Petter Selasky p->snapshot = 0; /* max packet size unspecified */
2557681ed54cSXin LI p->opt.timeout = 0; /* no timeout specified */
2558681ed54cSXin LI p->opt.buffer_size = 0; /* use the platform's default */
2559a8e07101SRui Paulo p->opt.promisc = 0;
2560681ed54cSXin LI p->opt.rfmon = 0;
2561681ed54cSXin LI p->opt.immediate = 0;
2562d1e87331SXin LI p->opt.tstamp_type = -1; /* default to not setting time stamp type */
2563681ed54cSXin LI p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
2564b00ab754SHans Petter Selasky /*
2565b00ab754SHans Petter Selasky * Platform-dependent options.
2566b00ab754SHans Petter Selasky */
2567b00ab754SHans Petter Selasky #ifdef __linux__
2568b00ab754SHans Petter Selasky p->opt.protocol = 0;
2569b00ab754SHans Petter Selasky #endif
2570b00ab754SHans Petter Selasky #ifdef _WIN32
2571b00ab754SHans Petter Selasky p->opt.nocapture_local = 0;
2572b00ab754SHans Petter Selasky #endif
2573ada6f083SXin LI
2574ada6f083SXin LI /*
2575ada6f083SXin LI * Start out with no BPF code generation flags set.
2576ada6f083SXin LI */
2577ada6f083SXin LI p->bpf_codegen_flags = 0;
2578ada6f083SXin LI
2579a8e07101SRui Paulo return (p);
2580a8e07101SRui Paulo }
2581a8e07101SRui Paulo
2582a8e07101SRui Paulo int
2583*afdbf109SJoseph Mingrone pcapint_check_activated(pcap_t *p)
2584a8e07101SRui Paulo {
2585a8e07101SRui Paulo if (p->activated) {
25866f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
2587a8e07101SRui Paulo " operation on activated capture");
2588d1e87331SXin LI return (-1);
2589a8e07101SRui Paulo }
2590d1e87331SXin LI return (0);
2591a8e07101SRui Paulo }
2592a8e07101SRui Paulo
2593a8e07101SRui Paulo int
2594a8e07101SRui Paulo pcap_set_snaplen(pcap_t *p, int snaplen)
2595a8e07101SRui Paulo {
2596*afdbf109SJoseph Mingrone if (pcapint_check_activated(p))
2597d1e87331SXin LI return (PCAP_ERROR_ACTIVATED);
2598a8e07101SRui Paulo p->snapshot = snaplen;
2599d1e87331SXin LI return (0);
2600a8e07101SRui Paulo }
2601a8e07101SRui Paulo
2602a8e07101SRui Paulo int
2603a8e07101SRui Paulo pcap_set_promisc(pcap_t *p, int promisc)
2604a8e07101SRui Paulo {
2605*afdbf109SJoseph Mingrone if (pcapint_check_activated(p))
2606d1e87331SXin LI return (PCAP_ERROR_ACTIVATED);
2607a8e07101SRui Paulo p->opt.promisc = promisc;
2608d1e87331SXin LI return (0);
2609a8e07101SRui Paulo }
2610a8e07101SRui Paulo
2611a8e07101SRui Paulo int
2612a8e07101SRui Paulo pcap_set_rfmon(pcap_t *p, int rfmon)
2613a8e07101SRui Paulo {
2614*afdbf109SJoseph Mingrone if (pcapint_check_activated(p))
2615d1e87331SXin LI return (PCAP_ERROR_ACTIVATED);
2616a8e07101SRui Paulo p->opt.rfmon = rfmon;
2617d1e87331SXin LI return (0);
2618a8e07101SRui Paulo }
2619a8e07101SRui Paulo
2620a8e07101SRui Paulo int
2621a8e07101SRui Paulo pcap_set_timeout(pcap_t *p, int timeout_ms)
2622a8e07101SRui Paulo {
2623*afdbf109SJoseph Mingrone if (pcapint_check_activated(p))
2624d1e87331SXin LI return (PCAP_ERROR_ACTIVATED);
2625681ed54cSXin LI p->opt.timeout = timeout_ms;
2626d1e87331SXin LI return (0);
2627d1e87331SXin LI }
2628d1e87331SXin LI
2629d1e87331SXin LI int
2630d1e87331SXin LI pcap_set_tstamp_type(pcap_t *p, int tstamp_type)
2631d1e87331SXin LI {
2632d1e87331SXin LI int i;
2633d1e87331SXin LI
2634*afdbf109SJoseph Mingrone if (pcapint_check_activated(p))
2635d1e87331SXin LI return (PCAP_ERROR_ACTIVATED);
2636d1e87331SXin LI
2637d1e87331SXin LI /*
2638ada6f083SXin LI * The argument should have been u_int, but that's too late
2639ada6f083SXin LI * to change now - it's an API.
2640ada6f083SXin LI */
2641ada6f083SXin LI if (tstamp_type < 0)
2642ada6f083SXin LI return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
2643ada6f083SXin LI
2644ada6f083SXin LI /*
2645681ed54cSXin LI * If p->tstamp_type_count is 0, we only support PCAP_TSTAMP_HOST;
2646681ed54cSXin LI * the default time stamp type is PCAP_TSTAMP_HOST.
2647d1e87331SXin LI */
2648681ed54cSXin LI if (p->tstamp_type_count == 0) {
2649681ed54cSXin LI if (tstamp_type == PCAP_TSTAMP_HOST) {
2650681ed54cSXin LI p->opt.tstamp_type = tstamp_type;
2651681ed54cSXin LI return (0);
2652681ed54cSXin LI }
2653681ed54cSXin LI } else {
2654d1e87331SXin LI /*
2655d1e87331SXin LI * Check whether we claim to support this type of time stamp.
2656d1e87331SXin LI */
2657d1e87331SXin LI for (i = 0; i < p->tstamp_type_count; i++) {
2658ada6f083SXin LI if (p->tstamp_type_list[i] == (u_int)tstamp_type) {
2659d1e87331SXin LI /*
2660d1e87331SXin LI * Yes.
2661d1e87331SXin LI */
2662d1e87331SXin LI p->opt.tstamp_type = tstamp_type;
2663d1e87331SXin LI return (0);
2664d1e87331SXin LI }
2665d1e87331SXin LI }
2666681ed54cSXin LI }
2667d1e87331SXin LI
2668d1e87331SXin LI /*
2669681ed54cSXin LI * We don't support this type of time stamp.
2670d1e87331SXin LI */
2671d1e87331SXin LI return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
2672a8e07101SRui Paulo }
2673a8e07101SRui Paulo
2674a8e07101SRui Paulo int
2675681ed54cSXin LI pcap_set_immediate_mode(pcap_t *p, int immediate)
2676681ed54cSXin LI {
2677*afdbf109SJoseph Mingrone if (pcapint_check_activated(p))
2678681ed54cSXin LI return (PCAP_ERROR_ACTIVATED);
2679681ed54cSXin LI p->opt.immediate = immediate;
2680681ed54cSXin LI return (0);
2681681ed54cSXin LI }
2682681ed54cSXin LI
2683681ed54cSXin LI int
2684a8e07101SRui Paulo pcap_set_buffer_size(pcap_t *p, int buffer_size)
2685a8e07101SRui Paulo {
2686*afdbf109SJoseph Mingrone if (pcapint_check_activated(p))
2687d1e87331SXin LI return (PCAP_ERROR_ACTIVATED);
2688ada6f083SXin LI if (buffer_size <= 0) {
2689ada6f083SXin LI /*
2690ada6f083SXin LI * Silently ignore invalid values.
2691ada6f083SXin LI */
2692ada6f083SXin LI return (0);
2693ada6f083SXin LI }
2694a8e07101SRui Paulo p->opt.buffer_size = buffer_size;
2695d1e87331SXin LI return (0);
2696a8e07101SRui Paulo }
2697a8e07101SRui Paulo
2698a8e07101SRui Paulo int
2699681ed54cSXin LI pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision)
2700681ed54cSXin LI {
2701681ed54cSXin LI int i;
2702681ed54cSXin LI
2703*afdbf109SJoseph Mingrone if (pcapint_check_activated(p))
2704681ed54cSXin LI return (PCAP_ERROR_ACTIVATED);
2705681ed54cSXin LI
2706681ed54cSXin LI /*
2707ada6f083SXin LI * The argument should have been u_int, but that's too late
2708ada6f083SXin LI * to change now - it's an API.
2709ada6f083SXin LI */
2710ada6f083SXin LI if (tstamp_precision < 0)
2711ada6f083SXin LI return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
2712ada6f083SXin LI
2713ada6f083SXin LI /*
2714681ed54cSXin LI * If p->tstamp_precision_count is 0, we only support setting
2715681ed54cSXin LI * the time stamp precision to microsecond precision; every
2716681ed54cSXin LI * pcap module *MUST* support microsecond precision, even if
2717681ed54cSXin LI * it does so by converting the native precision to
2718681ed54cSXin LI * microseconds.
2719681ed54cSXin LI */
2720681ed54cSXin LI if (p->tstamp_precision_count == 0) {
2721681ed54cSXin LI if (tstamp_precision == PCAP_TSTAMP_PRECISION_MICRO) {
2722681ed54cSXin LI p->opt.tstamp_precision = tstamp_precision;
2723681ed54cSXin LI return (0);
2724681ed54cSXin LI }
2725681ed54cSXin LI } else {
2726681ed54cSXin LI /*
2727681ed54cSXin LI * Check whether we claim to support this precision of
2728681ed54cSXin LI * time stamp.
2729681ed54cSXin LI */
2730681ed54cSXin LI for (i = 0; i < p->tstamp_precision_count; i++) {
2731ada6f083SXin LI if (p->tstamp_precision_list[i] == (u_int)tstamp_precision) {
2732681ed54cSXin LI /*
2733681ed54cSXin LI * Yes.
2734681ed54cSXin LI */
2735681ed54cSXin LI p->opt.tstamp_precision = tstamp_precision;
2736681ed54cSXin LI return (0);
2737681ed54cSXin LI }
2738681ed54cSXin LI }
2739681ed54cSXin LI }
2740681ed54cSXin LI
2741681ed54cSXin LI /*
2742681ed54cSXin LI * We don't support this time stamp precision.
2743681ed54cSXin LI */
2744681ed54cSXin LI return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
2745681ed54cSXin LI }
2746681ed54cSXin LI
2747681ed54cSXin LI int
2748681ed54cSXin LI pcap_get_tstamp_precision(pcap_t *p)
2749681ed54cSXin LI {
2750681ed54cSXin LI return (p->opt.tstamp_precision);
2751681ed54cSXin LI }
2752681ed54cSXin LI
2753681ed54cSXin LI int
2754a8e07101SRui Paulo pcap_activate(pcap_t *p)
2755a8e07101SRui Paulo {
2756a8e07101SRui Paulo int status;
2757a8e07101SRui Paulo
2758d1e87331SXin LI /*
2759d1e87331SXin LI * Catch attempts to re-activate an already-activated
2760d1e87331SXin LI * pcap_t; this should, for example, catch code that
2761d1e87331SXin LI * calls pcap_open_live() followed by pcap_activate(),
2762d1e87331SXin LI * as some code that showed up in a Stack Exchange
2763d1e87331SXin LI * question did.
2764d1e87331SXin LI */
2765*afdbf109SJoseph Mingrone if (pcapint_check_activated(p))
2766d1e87331SXin LI return (PCAP_ERROR_ACTIVATED);
2767a8e07101SRui Paulo status = p->activate_op(p);
2768b00ab754SHans Petter Selasky if (status >= 0) {
2769b00ab754SHans Petter Selasky /*
2770b00ab754SHans Petter Selasky * If somebody requested non-blocking mode before
2771b00ab754SHans Petter Selasky * calling pcap_activate(), turn it on now.
2772b00ab754SHans Petter Selasky */
2773b00ab754SHans Petter Selasky if (p->opt.nonblock) {
2774b00ab754SHans Petter Selasky status = p->setnonblock_op(p, 1);
2775b00ab754SHans Petter Selasky if (status < 0) {
2776b00ab754SHans Petter Selasky /*
2777b00ab754SHans Petter Selasky * Failed. Undo everything done by
2778b00ab754SHans Petter Selasky * the activate operation.
2779b00ab754SHans Petter Selasky */
2780b00ab754SHans Petter Selasky p->cleanup_op(p);
2781b00ab754SHans Petter Selasky initialize_ops(p);
2782b00ab754SHans Petter Selasky return (status);
2783b00ab754SHans Petter Selasky }
2784b00ab754SHans Petter Selasky }
2785a8e07101SRui Paulo p->activated = 1;
2786b00ab754SHans Petter Selasky } else {
2787a0ee43a1SRui Paulo if (p->errbuf[0] == '\0') {
2788a0ee43a1SRui Paulo /*
2789a0ee43a1SRui Paulo * No error message supplied by the activate routine;
2790a0ee43a1SRui Paulo * for the benefit of programs that don't specially
2791a0ee43a1SRui Paulo * handle errors other than PCAP_ERROR, return the
2792a0ee43a1SRui Paulo * error message corresponding to the status.
2793a0ee43a1SRui Paulo */
27946f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
2795a0ee43a1SRui Paulo pcap_statustostr(status));
2796a0ee43a1SRui Paulo }
2797a0ee43a1SRui Paulo
2798a0ee43a1SRui Paulo /*
2799a0ee43a1SRui Paulo * Undo any operation pointer setting, etc. done by
2800a0ee43a1SRui Paulo * the activate operation.
2801a0ee43a1SRui Paulo */
2802a0ee43a1SRui Paulo initialize_ops(p);
2803a0ee43a1SRui Paulo }
2804a8e07101SRui Paulo return (status);
2805a8e07101SRui Paulo }
2806a8e07101SRui Paulo
2807a8e07101SRui Paulo pcap_t *
2808ada6f083SXin LI pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf)
2809a8e07101SRui Paulo {
2810a8e07101SRui Paulo pcap_t *p;
2811a8e07101SRui Paulo int status;
2812b00ab754SHans Petter Selasky #ifdef ENABLE_REMOTE
2813b00ab754SHans Petter Selasky char host[PCAP_BUF_SIZE + 1];
2814b00ab754SHans Petter Selasky char port[PCAP_BUF_SIZE + 1];
2815b00ab754SHans Petter Selasky char name[PCAP_BUF_SIZE + 1];
2816b00ab754SHans Petter Selasky int srctype;
2817b00ab754SHans Petter Selasky
2818b00ab754SHans Petter Selasky /*
281957e22627SCy Schubert * A null device name is equivalent to the "any" device -
282057e22627SCy Schubert * which might not be supported on this platform, but
282157e22627SCy Schubert * this means that you'll get a "not supported" error
282257e22627SCy Schubert * rather than, say, a crash when we try to dereference
282357e22627SCy Schubert * the null pointer.
282457e22627SCy Schubert */
282557e22627SCy Schubert if (device == NULL)
282657e22627SCy Schubert device = "any";
282757e22627SCy Schubert
282857e22627SCy Schubert /*
2829b00ab754SHans Petter Selasky * Retrofit - we have to make older applications compatible with
2830b00ab754SHans Petter Selasky * remote capture.
2831b00ab754SHans Petter Selasky * So we're calling pcap_open_remote() from here; this is a very
2832b00ab754SHans Petter Selasky * dirty hack.
2833b00ab754SHans Petter Selasky * Obviously, we cannot exploit all the new features; for instance,
2834b00ab754SHans Petter Selasky * we cannot send authentication, we cannot use a UDP data connection,
2835b00ab754SHans Petter Selasky * and so on.
2836b00ab754SHans Petter Selasky */
2837b00ab754SHans Petter Selasky if (pcap_parsesrcstr(device, &srctype, host, port, name, errbuf))
2838b00ab754SHans Petter Selasky return (NULL);
2839b00ab754SHans Petter Selasky
2840b00ab754SHans Petter Selasky if (srctype == PCAP_SRC_IFREMOTE) {
2841b00ab754SHans Petter Selasky /*
2842b00ab754SHans Petter Selasky * Although we already have host, port and iface, we prefer
2843b00ab754SHans Petter Selasky * to pass only 'device' to pcap_open_rpcap(), so that it has
2844b00ab754SHans Petter Selasky * to call pcap_parsesrcstr() again.
2845b00ab754SHans Petter Selasky * This is less optimized, but much clearer.
2846b00ab754SHans Petter Selasky */
2847b00ab754SHans Petter Selasky return (pcap_open_rpcap(device, snaplen,
2848b00ab754SHans Petter Selasky promisc ? PCAP_OPENFLAG_PROMISCUOUS : 0, to_ms,
2849b00ab754SHans Petter Selasky NULL, errbuf));
2850b00ab754SHans Petter Selasky }
2851b00ab754SHans Petter Selasky if (srctype == PCAP_SRC_FILE) {
28526f9cba8fSJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown URL scheme \"file\"");
2853b00ab754SHans Petter Selasky return (NULL);
2854b00ab754SHans Petter Selasky }
2855b00ab754SHans Petter Selasky if (srctype == PCAP_SRC_IFLOCAL) {
2856b00ab754SHans Petter Selasky /*
2857b00ab754SHans Petter Selasky * If it starts with rpcap://, that refers to a local device
2858b00ab754SHans Petter Selasky * (no host part in the URL). Remove the rpcap://, and
2859b00ab754SHans Petter Selasky * fall through to the regular open path.
2860b00ab754SHans Petter Selasky */
2861b00ab754SHans Petter Selasky if (strncmp(device, PCAP_SRC_IF_STRING, strlen(PCAP_SRC_IF_STRING)) == 0) {
2862b00ab754SHans Petter Selasky size_t len = strlen(device) - strlen(PCAP_SRC_IF_STRING) + 1;
2863b00ab754SHans Petter Selasky
2864b00ab754SHans Petter Selasky if (len > 0)
2865b00ab754SHans Petter Selasky device += strlen(PCAP_SRC_IF_STRING);
2866b00ab754SHans Petter Selasky }
2867b00ab754SHans Petter Selasky }
2868b00ab754SHans Petter Selasky #endif /* ENABLE_REMOTE */
2869a8e07101SRui Paulo
2870ada6f083SXin LI p = pcap_create(device, errbuf);
2871a8e07101SRui Paulo if (p == NULL)
2872a8e07101SRui Paulo return (NULL);
2873a8e07101SRui Paulo status = pcap_set_snaplen(p, snaplen);
2874a8e07101SRui Paulo if (status < 0)
2875a8e07101SRui Paulo goto fail;
2876a8e07101SRui Paulo status = pcap_set_promisc(p, promisc);
2877a8e07101SRui Paulo if (status < 0)
2878a8e07101SRui Paulo goto fail;
2879a8e07101SRui Paulo status = pcap_set_timeout(p, to_ms);
2880a8e07101SRui Paulo if (status < 0)
2881a8e07101SRui Paulo goto fail;
2882a8e07101SRui Paulo /*
2883a8e07101SRui Paulo * Mark this as opened with pcap_open_live(), so that, for
2884a8e07101SRui Paulo * example, we show the full list of DLT_ values, rather
2885a8e07101SRui Paulo * than just the ones that are compatible with capturing
2886a8e07101SRui Paulo * when not in monitor mode. That allows existing applications
2887a8e07101SRui Paulo * to work the way they used to work, but allows new applications
2888a8e07101SRui Paulo * that know about the new open API to, for example, find out the
2889a8e07101SRui Paulo * DLT_ values that they can select without changing whether
2890a8e07101SRui Paulo * the adapter is in monitor mode or not.
2891a8e07101SRui Paulo */
2892a8e07101SRui Paulo p->oldstyle = 1;
2893a8e07101SRui Paulo status = pcap_activate(p);
2894a8e07101SRui Paulo if (status < 0)
2895a8e07101SRui Paulo goto fail;
2896a8e07101SRui Paulo return (p);
2897a8e07101SRui Paulo fail:
28986f9cba8fSJoseph Mingrone if (status == PCAP_ERROR) {
28996f9cba8fSJoseph Mingrone /*
29006f9cba8fSJoseph Mingrone * Another buffer is a bit cumbersome, but it avoids
29016f9cba8fSJoseph Mingrone * -Wformat-truncation.
29026f9cba8fSJoseph Mingrone */
29036f9cba8fSJoseph Mingrone char trimbuf[PCAP_ERRBUF_SIZE - 5]; /* 2 bytes shorter */
29046f9cba8fSJoseph Mingrone
2905*afdbf109SJoseph Mingrone pcapint_strlcpy(trimbuf, p->errbuf, sizeof(trimbuf));
29066f9cba8fSJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %.*s", device,
29076f9cba8fSJoseph Mingrone PCAP_ERRBUF_SIZE - 3, trimbuf);
29086f9cba8fSJoseph Mingrone } else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
2909d1e87331SXin LI status == PCAP_ERROR_PERM_DENIED ||
29106f9cba8fSJoseph Mingrone status == PCAP_ERROR_PROMISC_PERM_DENIED) {
29116f9cba8fSJoseph Mingrone /*
29126f9cba8fSJoseph Mingrone * Only show the additional message if it's not
29136f9cba8fSJoseph Mingrone * empty.
29146f9cba8fSJoseph Mingrone */
29156f9cba8fSJoseph Mingrone if (p->errbuf[0] != '\0') {
29166f9cba8fSJoseph Mingrone /*
29176f9cba8fSJoseph Mingrone * Idem.
29186f9cba8fSJoseph Mingrone */
29196f9cba8fSJoseph Mingrone char trimbuf[PCAP_ERRBUF_SIZE - 8]; /* 2 bytes shorter */
29206f9cba8fSJoseph Mingrone
2921*afdbf109SJoseph Mingrone pcapint_strlcpy(trimbuf, p->errbuf, sizeof(trimbuf));
29226f9cba8fSJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%.*s)",
29236f9cba8fSJoseph Mingrone device, pcap_statustostr(status),
29246f9cba8fSJoseph Mingrone PCAP_ERRBUF_SIZE - 6, trimbuf);
29256f9cba8fSJoseph Mingrone } else {
29266f9cba8fSJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
29276f9cba8fSJoseph Mingrone device, pcap_statustostr(status));
29286f9cba8fSJoseph Mingrone }
29296f9cba8fSJoseph Mingrone } else {
29306f9cba8fSJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device,
2931a8e07101SRui Paulo pcap_statustostr(status));
29326f9cba8fSJoseph Mingrone }
2933a8e07101SRui Paulo pcap_close(p);
2934a8e07101SRui Paulo return (NULL);
2935a8e07101SRui Paulo }
2936a8e07101SRui Paulo
2937681ed54cSXin LI pcap_t *
2938*afdbf109SJoseph Mingrone pcapint_open_offline_common(char *ebuf, size_t total_size, size_t private_offset)
2939681ed54cSXin LI {
2940681ed54cSXin LI pcap_t *p;
2941681ed54cSXin LI
29426f9cba8fSJoseph Mingrone p = pcap_alloc_pcap_t(ebuf, total_size, private_offset);
2943681ed54cSXin LI if (p == NULL)
2944681ed54cSXin LI return (NULL);
2945681ed54cSXin LI
2946681ed54cSXin LI p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
2947681ed54cSXin LI
2948681ed54cSXin LI return (p);
2949681ed54cSXin LI }
2950681ed54cSXin LI
2951a8e07101SRui Paulo int
29528cf6c252SPaul Traina pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
29538cf6c252SPaul Traina {
2954d1e87331SXin LI return (p->read_op(p, cnt, callback, user));
2955feb4ecdbSBruce M Simpson }
2956feb4ecdbSBruce M Simpson
29578cf6c252SPaul Traina int
29588cf6c252SPaul Traina pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
29598cf6c252SPaul Traina {
2960a4b5b39fSBill Fenner register int n;
2961a4b5b39fSBill Fenner
29628cf6c252SPaul Traina for (;;) {
2963681ed54cSXin LI if (p->rfile != NULL) {
2964feb4ecdbSBruce M Simpson /*
2965feb4ecdbSBruce M Simpson * 0 means EOF, so don't loop if we get 0.
2966feb4ecdbSBruce M Simpson */
2967*afdbf109SJoseph Mingrone n = pcapint_offline_read(p, cnt, callback, user);
2968feb4ecdbSBruce M Simpson } else {
2969a4b5b39fSBill Fenner /*
2970a4b5b39fSBill Fenner * XXX keep reading until we get something
2971a4b5b39fSBill Fenner * (or an error occurs)
2972a4b5b39fSBill Fenner */
2973a4b5b39fSBill Fenner do {
2974feb4ecdbSBruce M Simpson n = p->read_op(p, cnt, callback, user);
2975a4b5b39fSBill Fenner } while (n == 0);
2976a4b5b39fSBill Fenner }
29778cf6c252SPaul Traina if (n <= 0)
29788cf6c252SPaul Traina return (n);
2979681ed54cSXin LI if (!PACKET_COUNT_IS_UNLIMITED(cnt)) {
29808cf6c252SPaul Traina cnt -= n;
29818cf6c252SPaul Traina if (cnt <= 0)
29828cf6c252SPaul Traina return (0);
29838cf6c252SPaul Traina }
29848cf6c252SPaul Traina }
29858cf6c252SPaul Traina }
29868cf6c252SPaul Traina
2987feb4ecdbSBruce M Simpson /*
2988feb4ecdbSBruce M Simpson * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate.
2989feb4ecdbSBruce M Simpson */
2990feb4ecdbSBruce M Simpson void
2991feb4ecdbSBruce M Simpson pcap_breakloop(pcap_t *p)
2992feb4ecdbSBruce M Simpson {
29936f9cba8fSJoseph Mingrone p->breakloop_op(p);
2994feb4ecdbSBruce M Simpson }
2995feb4ecdbSBruce M Simpson
29968cf6c252SPaul Traina int
29978cf6c252SPaul Traina pcap_datalink(pcap_t *p)
29988cf6c252SPaul Traina {
2999681ed54cSXin LI if (!p->activated)
3000681ed54cSXin LI return (PCAP_ERROR_NOT_ACTIVATED);
30018cf6c252SPaul Traina return (p->linktype);
30028cf6c252SPaul Traina }
30038cf6c252SPaul Traina
30048cf6c252SPaul Traina int
3005a8e07101SRui Paulo pcap_datalink_ext(pcap_t *p)
3006a8e07101SRui Paulo {
3007681ed54cSXin LI if (!p->activated)
3008681ed54cSXin LI return (PCAP_ERROR_NOT_ACTIVATED);
3009a8e07101SRui Paulo return (p->linktype_ext);
3010a8e07101SRui Paulo }
3011a8e07101SRui Paulo
3012a8e07101SRui Paulo int
301309f33d61SBill Fenner pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
301409f33d61SBill Fenner {
3015681ed54cSXin LI if (!p->activated)
3016681ed54cSXin LI return (PCAP_ERROR_NOT_ACTIVATED);
3017feb4ecdbSBruce M Simpson if (p->dlt_count == 0) {
3018feb4ecdbSBruce M Simpson /*
3019feb4ecdbSBruce M Simpson * We couldn't fetch the list of DLTs, which means
3020feb4ecdbSBruce M Simpson * this platform doesn't support changing the
3021feb4ecdbSBruce M Simpson * DLT for an interface. Return a list of DLTs
3022feb4ecdbSBruce M Simpson * containing only the DLT this device supports.
3023feb4ecdbSBruce M Simpson */
3024feb4ecdbSBruce M Simpson *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer));
3025feb4ecdbSBruce M Simpson if (*dlt_buffer == NULL) {
3026*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
3027b00ab754SHans Petter Selasky errno, "malloc");
3028681ed54cSXin LI return (PCAP_ERROR);
302909f33d61SBill Fenner }
3030feb4ecdbSBruce M Simpson **dlt_buffer = p->linktype;
3031feb4ecdbSBruce M Simpson return (1);
3032feb4ecdbSBruce M Simpson } else {
3033*afdbf109SJoseph Mingrone *dlt_buffer = (int*)calloc(p->dlt_count, sizeof(**dlt_buffer));
303409f33d61SBill Fenner if (*dlt_buffer == NULL) {
3035*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
3036b00ab754SHans Petter Selasky errno, "malloc");
3037681ed54cSXin LI return (PCAP_ERROR);
303809f33d61SBill Fenner }
303909f33d61SBill Fenner (void)memcpy(*dlt_buffer, p->dlt_list,
304009f33d61SBill Fenner sizeof(**dlt_buffer) * p->dlt_count);
304109f33d61SBill Fenner return (p->dlt_count);
304209f33d61SBill Fenner }
3043feb4ecdbSBruce M Simpson }
3044feb4ecdbSBruce M Simpson
3045a8e07101SRui Paulo /*
3046a8e07101SRui Paulo * In Windows, you might have a library built with one version of the
3047a8e07101SRui Paulo * C runtime library and an application built with another version of
3048a8e07101SRui Paulo * the C runtime library, which means that the library might use one
3049a8e07101SRui Paulo * version of malloc() and free() and the application might use another
3050a8e07101SRui Paulo * version of malloc() and free(). If so, that means something
3051a8e07101SRui Paulo * allocated by the library cannot be freed by the application, so we
3052a8e07101SRui Paulo * need to have a pcap_free_datalinks() routine to free up the list
3053a8e07101SRui Paulo * allocated by pcap_list_datalinks(), even though it's just a wrapper
3054a8e07101SRui Paulo * around free().
3055a8e07101SRui Paulo */
3056a8e07101SRui Paulo void
3057a8e07101SRui Paulo pcap_free_datalinks(int *dlt_list)
3058a8e07101SRui Paulo {
3059a8e07101SRui Paulo free(dlt_list);
3060a8e07101SRui Paulo }
3061a8e07101SRui Paulo
3062feb4ecdbSBruce M Simpson int
3063feb4ecdbSBruce M Simpson pcap_set_datalink(pcap_t *p, int dlt)
3064feb4ecdbSBruce M Simpson {
3065feb4ecdbSBruce M Simpson int i;
3066feb4ecdbSBruce M Simpson const char *dlt_name;
3067feb4ecdbSBruce M Simpson
3068ada6f083SXin LI if (dlt < 0)
3069ada6f083SXin LI goto unsupported;
3070ada6f083SXin LI
3071feb4ecdbSBruce M Simpson if (p->dlt_count == 0 || p->set_datalink_op == NULL) {
3072feb4ecdbSBruce M Simpson /*
3073feb4ecdbSBruce M Simpson * We couldn't fetch the list of DLTs, or we don't
3074feb4ecdbSBruce M Simpson * have a "set datalink" operation, which means
3075feb4ecdbSBruce M Simpson * this platform doesn't support changing the
3076feb4ecdbSBruce M Simpson * DLT for an interface. Check whether the new
3077feb4ecdbSBruce M Simpson * DLT is the one this interface supports.
3078feb4ecdbSBruce M Simpson */
3079feb4ecdbSBruce M Simpson if (p->linktype != dlt)
3080feb4ecdbSBruce M Simpson goto unsupported;
3081feb4ecdbSBruce M Simpson
3082feb4ecdbSBruce M Simpson /*
3083feb4ecdbSBruce M Simpson * It is, so there's nothing we need to do here.
3084feb4ecdbSBruce M Simpson */
3085feb4ecdbSBruce M Simpson return (0);
3086feb4ecdbSBruce M Simpson }
3087feb4ecdbSBruce M Simpson for (i = 0; i < p->dlt_count; i++)
3088ada6f083SXin LI if (p->dlt_list[i] == (u_int)dlt)
3089feb4ecdbSBruce M Simpson break;
3090feb4ecdbSBruce M Simpson if (i >= p->dlt_count)
3091feb4ecdbSBruce M Simpson goto unsupported;
309204fb2745SSam Leffler if (p->dlt_count == 2 && p->dlt_list[0] == DLT_EN10MB &&
309304fb2745SSam Leffler dlt == DLT_DOCSIS) {
309404fb2745SSam Leffler /*
309504fb2745SSam Leffler * This is presumably an Ethernet device, as the first
309604fb2745SSam Leffler * link-layer type it offers is DLT_EN10MB, and the only
309704fb2745SSam Leffler * other type it offers is DLT_DOCSIS. That means that
309804fb2745SSam Leffler * we can't tell the driver to supply DOCSIS link-layer
309904fb2745SSam Leffler * headers - we're just pretending that's what we're
310004fb2745SSam Leffler * getting, as, presumably, we're capturing on a dedicated
310104fb2745SSam Leffler * link to a Cisco Cable Modem Termination System, and
310204fb2745SSam Leffler * it's putting raw DOCSIS frames on the wire inside low-level
310304fb2745SSam Leffler * Ethernet framing.
310404fb2745SSam Leffler */
310504fb2745SSam Leffler p->linktype = dlt;
310604fb2745SSam Leffler return (0);
310704fb2745SSam Leffler }
3108feb4ecdbSBruce M Simpson if (p->set_datalink_op(p, dlt) == -1)
3109feb4ecdbSBruce M Simpson return (-1);
3110feb4ecdbSBruce M Simpson p->linktype = dlt;
3111feb4ecdbSBruce M Simpson return (0);
3112feb4ecdbSBruce M Simpson
3113feb4ecdbSBruce M Simpson unsupported:
3114feb4ecdbSBruce M Simpson dlt_name = pcap_datalink_val_to_name(dlt);
3115feb4ecdbSBruce M Simpson if (dlt_name != NULL) {
31166f9cba8fSJoseph Mingrone (void) snprintf(p->errbuf, sizeof(p->errbuf),
3117feb4ecdbSBruce M Simpson "%s is not one of the DLTs supported by this device",
3118feb4ecdbSBruce M Simpson dlt_name);
3119feb4ecdbSBruce M Simpson } else {
31206f9cba8fSJoseph Mingrone (void) snprintf(p->errbuf, sizeof(p->errbuf),
3121feb4ecdbSBruce M Simpson "DLT %d is not one of the DLTs supported by this device",
3122feb4ecdbSBruce M Simpson dlt);
3123feb4ecdbSBruce M Simpson }
3124feb4ecdbSBruce M Simpson return (-1);
3125feb4ecdbSBruce M Simpson }
3126feb4ecdbSBruce M Simpson
3127feb4ecdbSBruce M Simpson /*
3128feb4ecdbSBruce M Simpson * This array is designed for mapping upper and lower case letter
3129feb4ecdbSBruce M Simpson * together for a case independent comparison. The mappings are
3130feb4ecdbSBruce M Simpson * based upon ascii character sequences.
3131feb4ecdbSBruce M Simpson */
3132feb4ecdbSBruce M Simpson static const u_char charmap[] = {
3133feb4ecdbSBruce M Simpson (u_char)'\000', (u_char)'\001', (u_char)'\002', (u_char)'\003',
3134feb4ecdbSBruce M Simpson (u_char)'\004', (u_char)'\005', (u_char)'\006', (u_char)'\007',
3135feb4ecdbSBruce M Simpson (u_char)'\010', (u_char)'\011', (u_char)'\012', (u_char)'\013',
3136feb4ecdbSBruce M Simpson (u_char)'\014', (u_char)'\015', (u_char)'\016', (u_char)'\017',
3137feb4ecdbSBruce M Simpson (u_char)'\020', (u_char)'\021', (u_char)'\022', (u_char)'\023',
3138feb4ecdbSBruce M Simpson (u_char)'\024', (u_char)'\025', (u_char)'\026', (u_char)'\027',
3139feb4ecdbSBruce M Simpson (u_char)'\030', (u_char)'\031', (u_char)'\032', (u_char)'\033',
3140feb4ecdbSBruce M Simpson (u_char)'\034', (u_char)'\035', (u_char)'\036', (u_char)'\037',
3141feb4ecdbSBruce M Simpson (u_char)'\040', (u_char)'\041', (u_char)'\042', (u_char)'\043',
3142feb4ecdbSBruce M Simpson (u_char)'\044', (u_char)'\045', (u_char)'\046', (u_char)'\047',
3143feb4ecdbSBruce M Simpson (u_char)'\050', (u_char)'\051', (u_char)'\052', (u_char)'\053',
3144feb4ecdbSBruce M Simpson (u_char)'\054', (u_char)'\055', (u_char)'\056', (u_char)'\057',
3145feb4ecdbSBruce M Simpson (u_char)'\060', (u_char)'\061', (u_char)'\062', (u_char)'\063',
3146feb4ecdbSBruce M Simpson (u_char)'\064', (u_char)'\065', (u_char)'\066', (u_char)'\067',
3147feb4ecdbSBruce M Simpson (u_char)'\070', (u_char)'\071', (u_char)'\072', (u_char)'\073',
3148feb4ecdbSBruce M Simpson (u_char)'\074', (u_char)'\075', (u_char)'\076', (u_char)'\077',
3149feb4ecdbSBruce M Simpson (u_char)'\100', (u_char)'\141', (u_char)'\142', (u_char)'\143',
3150feb4ecdbSBruce M Simpson (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
3151feb4ecdbSBruce M Simpson (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
3152feb4ecdbSBruce M Simpson (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
3153feb4ecdbSBruce M Simpson (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
3154feb4ecdbSBruce M Simpson (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
3155feb4ecdbSBruce M Simpson (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\133',
3156feb4ecdbSBruce M Simpson (u_char)'\134', (u_char)'\135', (u_char)'\136', (u_char)'\137',
3157feb4ecdbSBruce M Simpson (u_char)'\140', (u_char)'\141', (u_char)'\142', (u_char)'\143',
3158feb4ecdbSBruce M Simpson (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
3159feb4ecdbSBruce M Simpson (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
3160feb4ecdbSBruce M Simpson (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
3161feb4ecdbSBruce M Simpson (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
3162feb4ecdbSBruce M Simpson (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
3163feb4ecdbSBruce M Simpson (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\173',
3164feb4ecdbSBruce M Simpson (u_char)'\174', (u_char)'\175', (u_char)'\176', (u_char)'\177',
3165feb4ecdbSBruce M Simpson (u_char)'\200', (u_char)'\201', (u_char)'\202', (u_char)'\203',
3166feb4ecdbSBruce M Simpson (u_char)'\204', (u_char)'\205', (u_char)'\206', (u_char)'\207',
3167feb4ecdbSBruce M Simpson (u_char)'\210', (u_char)'\211', (u_char)'\212', (u_char)'\213',
3168feb4ecdbSBruce M Simpson (u_char)'\214', (u_char)'\215', (u_char)'\216', (u_char)'\217',
3169feb4ecdbSBruce M Simpson (u_char)'\220', (u_char)'\221', (u_char)'\222', (u_char)'\223',
3170feb4ecdbSBruce M Simpson (u_char)'\224', (u_char)'\225', (u_char)'\226', (u_char)'\227',
3171feb4ecdbSBruce M Simpson (u_char)'\230', (u_char)'\231', (u_char)'\232', (u_char)'\233',
3172feb4ecdbSBruce M Simpson (u_char)'\234', (u_char)'\235', (u_char)'\236', (u_char)'\237',
3173feb4ecdbSBruce M Simpson (u_char)'\240', (u_char)'\241', (u_char)'\242', (u_char)'\243',
3174feb4ecdbSBruce M Simpson (u_char)'\244', (u_char)'\245', (u_char)'\246', (u_char)'\247',
3175feb4ecdbSBruce M Simpson (u_char)'\250', (u_char)'\251', (u_char)'\252', (u_char)'\253',
3176feb4ecdbSBruce M Simpson (u_char)'\254', (u_char)'\255', (u_char)'\256', (u_char)'\257',
3177feb4ecdbSBruce M Simpson (u_char)'\260', (u_char)'\261', (u_char)'\262', (u_char)'\263',
3178feb4ecdbSBruce M Simpson (u_char)'\264', (u_char)'\265', (u_char)'\266', (u_char)'\267',
3179feb4ecdbSBruce M Simpson (u_char)'\270', (u_char)'\271', (u_char)'\272', (u_char)'\273',
3180feb4ecdbSBruce M Simpson (u_char)'\274', (u_char)'\275', (u_char)'\276', (u_char)'\277',
3181feb4ecdbSBruce M Simpson (u_char)'\300', (u_char)'\341', (u_char)'\342', (u_char)'\343',
3182feb4ecdbSBruce M Simpson (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347',
3183feb4ecdbSBruce M Simpson (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353',
3184feb4ecdbSBruce M Simpson (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357',
3185feb4ecdbSBruce M Simpson (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363',
3186feb4ecdbSBruce M Simpson (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367',
3187feb4ecdbSBruce M Simpson (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\333',
3188feb4ecdbSBruce M Simpson (u_char)'\334', (u_char)'\335', (u_char)'\336', (u_char)'\337',
3189feb4ecdbSBruce M Simpson (u_char)'\340', (u_char)'\341', (u_char)'\342', (u_char)'\343',
3190feb4ecdbSBruce M Simpson (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347',
3191feb4ecdbSBruce M Simpson (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353',
3192feb4ecdbSBruce M Simpson (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357',
3193feb4ecdbSBruce M Simpson (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363',
3194feb4ecdbSBruce M Simpson (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367',
3195feb4ecdbSBruce M Simpson (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\373',
3196feb4ecdbSBruce M Simpson (u_char)'\374', (u_char)'\375', (u_char)'\376', (u_char)'\377',
3197feb4ecdbSBruce M Simpson };
3198feb4ecdbSBruce M Simpson
3199feb4ecdbSBruce M Simpson int
3200*afdbf109SJoseph Mingrone pcapint_strcasecmp(const char *s1, const char *s2)
3201feb4ecdbSBruce M Simpson {
3202feb4ecdbSBruce M Simpson register const u_char *cm = charmap,
3203ef96d74fSMax Laier *us1 = (const u_char *)s1,
3204ef96d74fSMax Laier *us2 = (const u_char *)s2;
3205feb4ecdbSBruce M Simpson
3206feb4ecdbSBruce M Simpson while (cm[*us1] == cm[*us2++])
3207feb4ecdbSBruce M Simpson if (*us1++ == '\0')
3208feb4ecdbSBruce M Simpson return(0);
3209feb4ecdbSBruce M Simpson return (cm[*us1] - cm[*--us2]);
3210feb4ecdbSBruce M Simpson }
3211feb4ecdbSBruce M Simpson
3212d1e87331SXin LI struct dlt_choice {
3213d1e87331SXin LI const char *name;
3214d1e87331SXin LI const char *description;
3215d1e87331SXin LI int dlt;
3216d1e87331SXin LI };
3217d1e87331SXin LI
3218ada6f083SXin LI #define DLT_CHOICE(code, description) { #code, description, DLT_ ## code }
3219d1e87331SXin LI #define DLT_CHOICE_SENTINEL { NULL, NULL, 0 }
3220d1e87331SXin LI
3221d1e87331SXin LI static struct dlt_choice dlt_choices[] = {
3222ada6f083SXin LI DLT_CHOICE(NULL, "BSD loopback"),
3223ada6f083SXin LI DLT_CHOICE(EN10MB, "Ethernet"),
3224ada6f083SXin LI DLT_CHOICE(IEEE802, "Token ring"),
3225ada6f083SXin LI DLT_CHOICE(ARCNET, "BSD ARCNET"),
3226ada6f083SXin LI DLT_CHOICE(SLIP, "SLIP"),
3227ada6f083SXin LI DLT_CHOICE(PPP, "PPP"),
3228ada6f083SXin LI DLT_CHOICE(FDDI, "FDDI"),
3229ada6f083SXin LI DLT_CHOICE(ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"),
3230ada6f083SXin LI DLT_CHOICE(RAW, "Raw IP"),
3231ada6f083SXin LI DLT_CHOICE(SLIP_BSDOS, "BSD/OS SLIP"),
3232ada6f083SXin LI DLT_CHOICE(PPP_BSDOS, "BSD/OS PPP"),
32336f9cba8fSJoseph Mingrone DLT_CHOICE(ATM_CLIP, "Linux Classical IP over ATM"),
3234ada6f083SXin LI DLT_CHOICE(PPP_SERIAL, "PPP over serial"),
3235ada6f083SXin LI DLT_CHOICE(PPP_ETHER, "PPPoE"),
3236ada6f083SXin LI DLT_CHOICE(SYMANTEC_FIREWALL, "Symantec Firewall"),
3237ada6f083SXin LI DLT_CHOICE(C_HDLC, "Cisco HDLC"),
3238ada6f083SXin LI DLT_CHOICE(IEEE802_11, "802.11"),
3239ada6f083SXin LI DLT_CHOICE(FRELAY, "Frame Relay"),
3240ada6f083SXin LI DLT_CHOICE(LOOP, "OpenBSD loopback"),
3241ada6f083SXin LI DLT_CHOICE(ENC, "OpenBSD encapsulated IP"),
324257e22627SCy Schubert DLT_CHOICE(LINUX_SLL, "Linux cooked v1"),
3243ada6f083SXin LI DLT_CHOICE(LTALK, "Localtalk"),
3244ada6f083SXin LI DLT_CHOICE(PFLOG, "OpenBSD pflog file"),
3245ada6f083SXin LI DLT_CHOICE(PFSYNC, "Packet filter state syncing"),
3246ada6f083SXin LI DLT_CHOICE(PRISM_HEADER, "802.11 plus Prism header"),
3247ada6f083SXin LI DLT_CHOICE(IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
3248ada6f083SXin LI DLT_CHOICE(SUNATM, "Sun raw ATM"),
3249ada6f083SXin LI DLT_CHOICE(IEEE802_11_RADIO, "802.11 plus radiotap header"),
3250ada6f083SXin LI DLT_CHOICE(ARCNET_LINUX, "Linux ARCNET"),
3251ada6f083SXin LI DLT_CHOICE(JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
3252ada6f083SXin LI DLT_CHOICE(JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
3253ada6f083SXin LI DLT_CHOICE(JUNIPER_ES, "Juniper Encryption Services PIC"),
3254ada6f083SXin LI DLT_CHOICE(JUNIPER_GGSN, "Juniper GGSN PIC"),
3255ada6f083SXin LI DLT_CHOICE(JUNIPER_MFR, "Juniper FRF.16 Frame Relay"),
3256ada6f083SXin LI DLT_CHOICE(JUNIPER_ATM2, "Juniper ATM2 PIC"),
3257ada6f083SXin LI DLT_CHOICE(JUNIPER_SERVICES, "Juniper Advanced Services PIC"),
3258ada6f083SXin LI DLT_CHOICE(JUNIPER_ATM1, "Juniper ATM1 PIC"),
3259ada6f083SXin LI DLT_CHOICE(APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
3260ada6f083SXin LI DLT_CHOICE(MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"),
3261ada6f083SXin LI DLT_CHOICE(MTP2, "SS7 MTP2"),
3262ada6f083SXin LI DLT_CHOICE(MTP3, "SS7 MTP3"),
3263ada6f083SXin LI DLT_CHOICE(SCCP, "SS7 SCCP"),
3264ada6f083SXin LI DLT_CHOICE(DOCSIS, "DOCSIS"),
3265ada6f083SXin LI DLT_CHOICE(LINUX_IRDA, "Linux IrDA"),
3266ada6f083SXin LI DLT_CHOICE(IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
3267ada6f083SXin LI DLT_CHOICE(JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
3268ada6f083SXin LI DLT_CHOICE(BACNET_MS_TP, "BACnet MS/TP"),
3269ada6f083SXin LI DLT_CHOICE(PPP_PPPD, "PPP for pppd, with direction flag"),
3270ada6f083SXin LI DLT_CHOICE(JUNIPER_PPPOE, "Juniper PPPoE"),
3271ada6f083SXin LI DLT_CHOICE(JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
3272ada6f083SXin LI DLT_CHOICE(GPRS_LLC, "GPRS LLC"),
3273ada6f083SXin LI DLT_CHOICE(GPF_T, "GPF-T"),
3274ada6f083SXin LI DLT_CHOICE(GPF_F, "GPF-F"),
3275ada6f083SXin LI DLT_CHOICE(JUNIPER_PIC_PEER, "Juniper PIC Peer"),
3276ada6f083SXin LI DLT_CHOICE(ERF_ETH, "Ethernet with Endace ERF header"),
3277ada6f083SXin LI DLT_CHOICE(ERF_POS, "Packet-over-SONET with Endace ERF header"),
3278ada6f083SXin LI DLT_CHOICE(LINUX_LAPD, "Linux vISDN LAPD"),
3279ada6f083SXin LI DLT_CHOICE(JUNIPER_ETHER, "Juniper Ethernet"),
3280ada6f083SXin LI DLT_CHOICE(JUNIPER_PPP, "Juniper PPP"),
3281ada6f083SXin LI DLT_CHOICE(JUNIPER_FRELAY, "Juniper Frame Relay"),
3282ada6f083SXin LI DLT_CHOICE(JUNIPER_CHDLC, "Juniper C-HDLC"),
3283ada6f083SXin LI DLT_CHOICE(MFR, "FRF.16 Frame Relay"),
3284ada6f083SXin LI DLT_CHOICE(JUNIPER_VP, "Juniper Voice PIC"),
3285ada6f083SXin LI DLT_CHOICE(A429, "Arinc 429"),
3286ada6f083SXin LI DLT_CHOICE(A653_ICM, "Arinc 653 Interpartition Communication"),
3287ada6f083SXin LI DLT_CHOICE(USB_FREEBSD, "USB with FreeBSD header"),
3288ada6f083SXin LI DLT_CHOICE(BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"),
3289ada6f083SXin LI DLT_CHOICE(IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"),
3290ada6f083SXin LI DLT_CHOICE(USB_LINUX, "USB with Linux header"),
3291ada6f083SXin LI DLT_CHOICE(CAN20B, "Controller Area Network (CAN) v. 2.0B"),
3292ada6f083SXin LI DLT_CHOICE(IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"),
3293ada6f083SXin LI DLT_CHOICE(PPI, "Per-Packet Information"),
3294ada6f083SXin LI DLT_CHOICE(IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"),
3295ada6f083SXin LI DLT_CHOICE(JUNIPER_ISM, "Juniper Integrated Service Module"),
3296ada6f083SXin LI DLT_CHOICE(IEEE802_15_4, "IEEE 802.15.4 with FCS"),
3297ada6f083SXin LI DLT_CHOICE(SITA, "SITA pseudo-header"),
3298ada6f083SXin LI DLT_CHOICE(ERF, "Endace ERF header"),
3299ada6f083SXin LI DLT_CHOICE(RAIF1, "Ethernet with u10 Networks pseudo-header"),
330057e22627SCy Schubert DLT_CHOICE(IPMB_KONTRON, "IPMB with Kontron pseudo-header"),
3301ada6f083SXin LI DLT_CHOICE(JUNIPER_ST, "Juniper Secure Tunnel"),
3302ada6f083SXin LI DLT_CHOICE(BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"),
3303ada6f083SXin LI DLT_CHOICE(AX25_KISS, "AX.25 with KISS header"),
330457e22627SCy Schubert DLT_CHOICE(IPMB_LINUX, "IPMB with Linux/Pigeon Point pseudo-header"),
3305ada6f083SXin LI DLT_CHOICE(IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"),
3306ada6f083SXin LI DLT_CHOICE(MPLS, "MPLS with label as link-layer header"),
3307ada6f083SXin LI DLT_CHOICE(LINUX_EVDEV, "Linux evdev events"),
3308ada6f083SXin LI DLT_CHOICE(USB_LINUX_MMAPPED, "USB with padded Linux header"),
3309ada6f083SXin LI DLT_CHOICE(DECT, "DECT"),
3310ada6f083SXin LI DLT_CHOICE(AOS, "AOS Space Data Link protocol"),
3311ada6f083SXin LI DLT_CHOICE(WIHART, "WirelessHART"),
3312ada6f083SXin LI DLT_CHOICE(FC_2, "Fibre Channel FC-2"),
3313ada6f083SXin LI DLT_CHOICE(FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"),
3314ada6f083SXin LI DLT_CHOICE(IPNET, "Solaris ipnet"),
3315ada6f083SXin LI DLT_CHOICE(CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"),
3316ada6f083SXin LI DLT_CHOICE(IPV4, "Raw IPv4"),
3317ada6f083SXin LI DLT_CHOICE(IPV6, "Raw IPv6"),
3318ada6f083SXin LI DLT_CHOICE(IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"),
3319ada6f083SXin LI DLT_CHOICE(DBUS, "D-Bus"),
3320ada6f083SXin LI DLT_CHOICE(JUNIPER_VS, "Juniper Virtual Server"),
3321ada6f083SXin LI DLT_CHOICE(JUNIPER_SRX_E2E, "Juniper SRX E2E"),
3322ada6f083SXin LI DLT_CHOICE(JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"),
3323ada6f083SXin LI DLT_CHOICE(DVB_CI, "DVB-CI"),
3324ada6f083SXin LI DLT_CHOICE(MUX27010, "MUX27010"),
3325ada6f083SXin LI DLT_CHOICE(STANAG_5066_D_PDU, "STANAG 5066 D_PDUs"),
3326ada6f083SXin LI DLT_CHOICE(JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"),
3327ada6f083SXin LI DLT_CHOICE(NFLOG, "Linux netfilter log messages"),
3328ada6f083SXin LI DLT_CHOICE(NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"),
3329ada6f083SXin LI DLT_CHOICE(NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"),
3330ada6f083SXin LI DLT_CHOICE(IPOIB, "RFC 4391 IP-over-Infiniband"),
3331ada6f083SXin LI DLT_CHOICE(MPEG_2_TS, "MPEG-2 transport stream"),
3332ada6f083SXin LI DLT_CHOICE(NG40, "ng40 protocol tester Iub/Iur"),
3333ada6f083SXin LI DLT_CHOICE(NFC_LLCP, "NFC LLCP PDUs with pseudo-header"),
3334ada6f083SXin LI DLT_CHOICE(INFINIBAND, "InfiniBand"),
3335ada6f083SXin LI DLT_CHOICE(SCTP, "SCTP"),
3336ada6f083SXin LI DLT_CHOICE(USBPCAP, "USB with USBPcap header"),
3337ada6f083SXin LI DLT_CHOICE(RTAC_SERIAL, "Schweitzer Engineering Laboratories RTAC packets"),
3338ada6f083SXin LI DLT_CHOICE(BLUETOOTH_LE_LL, "Bluetooth Low Energy air interface"),
3339ada6f083SXin LI DLT_CHOICE(NETLINK, "Linux netlink"),
3340ada6f083SXin LI DLT_CHOICE(BLUETOOTH_LINUX_MONITOR, "Bluetooth Linux Monitor"),
3341ada6f083SXin LI DLT_CHOICE(BLUETOOTH_BREDR_BB, "Bluetooth Basic Rate/Enhanced Data Rate baseband packets"),
3342ada6f083SXin LI DLT_CHOICE(BLUETOOTH_LE_LL_WITH_PHDR, "Bluetooth Low Energy air interface with pseudo-header"),
3343ada6f083SXin LI DLT_CHOICE(PROFIBUS_DL, "PROFIBUS data link layer"),
3344ada6f083SXin LI DLT_CHOICE(PKTAP, "Apple DLT_PKTAP"),
3345ada6f083SXin LI DLT_CHOICE(EPON, "Ethernet with 802.3 Clause 65 EPON preamble"),
3346ada6f083SXin LI DLT_CHOICE(IPMI_HPM_2, "IPMI trace packets"),
3347ada6f083SXin LI DLT_CHOICE(ZWAVE_R1_R2, "Z-Wave RF profile R1 and R2 packets"),
3348ada6f083SXin LI DLT_CHOICE(ZWAVE_R3, "Z-Wave RF profile R3 packets"),
3349ada6f083SXin LI DLT_CHOICE(WATTSTOPPER_DLM, "WattStopper Digital Lighting Management (DLM) and Legrand Nitoo Open protocol"),
3350ada6f083SXin LI DLT_CHOICE(ISO_14443, "ISO 14443 messages"),
3351ada6f083SXin LI DLT_CHOICE(RDS, "IEC 62106 Radio Data System groups"),
3352b00ab754SHans Petter Selasky DLT_CHOICE(USB_DARWIN, "USB with Darwin header"),
3353b00ab754SHans Petter Selasky DLT_CHOICE(OPENFLOW, "OpenBSD DLT_OPENFLOW"),
3354b00ab754SHans Petter Selasky DLT_CHOICE(SDLC, "IBM SDLC frames"),
3355b00ab754SHans Petter Selasky DLT_CHOICE(TI_LLN_SNIFFER, "TI LLN sniffer frames"),
3356b00ab754SHans Petter Selasky DLT_CHOICE(VSOCK, "Linux vsock"),
3357b00ab754SHans Petter Selasky DLT_CHOICE(NORDIC_BLE, "Nordic Semiconductor Bluetooth LE sniffer frames"),
3358b00ab754SHans Petter Selasky DLT_CHOICE(DOCSIS31_XRA31, "Excentis XRA-31 DOCSIS 3.1 RF sniffer frames"),
3359b00ab754SHans Petter Selasky DLT_CHOICE(ETHERNET_MPACKET, "802.3br mPackets"),
3360b00ab754SHans Petter Selasky DLT_CHOICE(DISPLAYPORT_AUX, "DisplayPort AUX channel monitoring data"),
336157e22627SCy Schubert DLT_CHOICE(LINUX_SLL2, "Linux cooked v2"),
33626f9cba8fSJoseph Mingrone DLT_CHOICE(OPENVIZSLA, "OpenVizsla USB"),
33636f9cba8fSJoseph Mingrone DLT_CHOICE(EBHSCR, "Elektrobit High Speed Capture and Replay (EBHSCR)"),
33646f9cba8fSJoseph Mingrone DLT_CHOICE(VPP_DISPATCH, "VPP graph dispatch tracer"),
33656f9cba8fSJoseph Mingrone DLT_CHOICE(DSA_TAG_BRCM, "Broadcom tag"),
33666f9cba8fSJoseph Mingrone DLT_CHOICE(DSA_TAG_BRCM_PREPEND, "Broadcom tag (prepended)"),
33676f9cba8fSJoseph Mingrone DLT_CHOICE(IEEE802_15_4_TAP, "IEEE 802.15.4 with pseudo-header"),
33686f9cba8fSJoseph Mingrone DLT_CHOICE(DSA_TAG_DSA, "Marvell DSA"),
33696f9cba8fSJoseph Mingrone DLT_CHOICE(DSA_TAG_EDSA, "Marvell EDSA"),
33706f9cba8fSJoseph Mingrone DLT_CHOICE(ELEE, "ELEE lawful intercept packets"),
33716f9cba8fSJoseph Mingrone DLT_CHOICE(Z_WAVE_SERIAL, "Z-Wave serial frames between host and chip"),
33726f9cba8fSJoseph Mingrone DLT_CHOICE(USB_2_0, "USB 2.0/1.1/1.0 as transmitted over the cable"),
33736f9cba8fSJoseph Mingrone DLT_CHOICE(ATSC_ALP, "ATSC Link-Layer Protocol packets"),
3374d1e87331SXin LI DLT_CHOICE_SENTINEL
3375d1e87331SXin LI };
3376d1e87331SXin LI
3377feb4ecdbSBruce M Simpson int
3378feb4ecdbSBruce M Simpson pcap_datalink_name_to_val(const char *name)
3379feb4ecdbSBruce M Simpson {
3380feb4ecdbSBruce M Simpson int i;
3381feb4ecdbSBruce M Simpson
3382feb4ecdbSBruce M Simpson for (i = 0; dlt_choices[i].name != NULL; i++) {
3383*afdbf109SJoseph Mingrone if (pcapint_strcasecmp(dlt_choices[i].name, name) == 0)
3384feb4ecdbSBruce M Simpson return (dlt_choices[i].dlt);
3385feb4ecdbSBruce M Simpson }
3386feb4ecdbSBruce M Simpson return (-1);
3387feb4ecdbSBruce M Simpson }
3388feb4ecdbSBruce M Simpson
3389feb4ecdbSBruce M Simpson const char *
3390feb4ecdbSBruce M Simpson pcap_datalink_val_to_name(int dlt)
3391feb4ecdbSBruce M Simpson {
3392feb4ecdbSBruce M Simpson int i;
3393feb4ecdbSBruce M Simpson
3394feb4ecdbSBruce M Simpson for (i = 0; dlt_choices[i].name != NULL; i++) {
3395feb4ecdbSBruce M Simpson if (dlt_choices[i].dlt == dlt)
3396ada6f083SXin LI return (dlt_choices[i].name);
3397feb4ecdbSBruce M Simpson }
3398feb4ecdbSBruce M Simpson return (NULL);
3399feb4ecdbSBruce M Simpson }
3400feb4ecdbSBruce M Simpson
3401feb4ecdbSBruce M Simpson const char *
3402feb4ecdbSBruce M Simpson pcap_datalink_val_to_description(int dlt)
3403feb4ecdbSBruce M Simpson {
3404feb4ecdbSBruce M Simpson int i;
3405feb4ecdbSBruce M Simpson
3406feb4ecdbSBruce M Simpson for (i = 0; dlt_choices[i].name != NULL; i++) {
3407feb4ecdbSBruce M Simpson if (dlt_choices[i].dlt == dlt)
3408feb4ecdbSBruce M Simpson return (dlt_choices[i].description);
3409feb4ecdbSBruce M Simpson }
3410feb4ecdbSBruce M Simpson return (NULL);
3411feb4ecdbSBruce M Simpson }
341209f33d61SBill Fenner
341357e22627SCy Schubert const char *
341457e22627SCy Schubert pcap_datalink_val_to_description_or_dlt(int dlt)
341557e22627SCy Schubert {
3416*afdbf109SJoseph Mingrone static thread_local char unkbuf[40];
341757e22627SCy Schubert const char *description;
341857e22627SCy Schubert
341957e22627SCy Schubert description = pcap_datalink_val_to_description(dlt);
342057e22627SCy Schubert if (description != NULL) {
342157e22627SCy Schubert return description;
342257e22627SCy Schubert } else {
34236f9cba8fSJoseph Mingrone (void)snprintf(unkbuf, sizeof(unkbuf), "DLT %d", dlt);
342457e22627SCy Schubert return unkbuf;
342557e22627SCy Schubert }
342657e22627SCy Schubert }
342757e22627SCy Schubert
3428d1e87331SXin LI struct tstamp_type_choice {
3429d1e87331SXin LI const char *name;
3430d1e87331SXin LI const char *description;
3431d1e87331SXin LI int type;
3432d1e87331SXin LI };
3433d1e87331SXin LI
3434d1e87331SXin LI static struct tstamp_type_choice tstamp_type_choices[] = {
3435d1e87331SXin LI { "host", "Host", PCAP_TSTAMP_HOST },
3436d1e87331SXin LI { "host_lowprec", "Host, low precision", PCAP_TSTAMP_HOST_LOWPREC },
3437d1e87331SXin LI { "host_hiprec", "Host, high precision", PCAP_TSTAMP_HOST_HIPREC },
3438d1e87331SXin LI { "adapter", "Adapter", PCAP_TSTAMP_ADAPTER },
3439d1e87331SXin LI { "adapter_unsynced", "Adapter, not synced with system time", PCAP_TSTAMP_ADAPTER_UNSYNCED },
34406f9cba8fSJoseph Mingrone { "host_hiprec_unsynced", "Host, high precision, not synced with system time", PCAP_TSTAMP_HOST_HIPREC_UNSYNCED },
3441d1e87331SXin LI { NULL, NULL, 0 }
3442d1e87331SXin LI };
3443d1e87331SXin LI
3444d1e87331SXin LI int
3445d1e87331SXin LI pcap_tstamp_type_name_to_val(const char *name)
3446d1e87331SXin LI {
3447d1e87331SXin LI int i;
3448d1e87331SXin LI
3449d1e87331SXin LI for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
3450*afdbf109SJoseph Mingrone if (pcapint_strcasecmp(tstamp_type_choices[i].name, name) == 0)
3451d1e87331SXin LI return (tstamp_type_choices[i].type);
3452d1e87331SXin LI }
3453d1e87331SXin LI return (PCAP_ERROR);
3454d1e87331SXin LI }
3455d1e87331SXin LI
3456d1e87331SXin LI const char *
3457d1e87331SXin LI pcap_tstamp_type_val_to_name(int tstamp_type)
3458d1e87331SXin LI {
3459d1e87331SXin LI int i;
3460d1e87331SXin LI
3461d1e87331SXin LI for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
3462d1e87331SXin LI if (tstamp_type_choices[i].type == tstamp_type)
3463d1e87331SXin LI return (tstamp_type_choices[i].name);
3464d1e87331SXin LI }
3465d1e87331SXin LI return (NULL);
3466d1e87331SXin LI }
3467d1e87331SXin LI
3468d1e87331SXin LI const char *
3469d1e87331SXin LI pcap_tstamp_type_val_to_description(int tstamp_type)
3470d1e87331SXin LI {
3471d1e87331SXin LI int i;
3472d1e87331SXin LI
3473d1e87331SXin LI for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
3474d1e87331SXin LI if (tstamp_type_choices[i].type == tstamp_type)
3475d1e87331SXin LI return (tstamp_type_choices[i].description);
3476d1e87331SXin LI }
3477d1e87331SXin LI return (NULL);
3478d1e87331SXin LI }
3479d1e87331SXin LI
348009f33d61SBill Fenner int
34818cf6c252SPaul Traina pcap_snapshot(pcap_t *p)
34828cf6c252SPaul Traina {
3483681ed54cSXin LI if (!p->activated)
3484681ed54cSXin LI return (PCAP_ERROR_NOT_ACTIVATED);
34858cf6c252SPaul Traina return (p->snapshot);
34868cf6c252SPaul Traina }
34878cf6c252SPaul Traina
34888cf6c252SPaul Traina int
34898cf6c252SPaul Traina pcap_is_swapped(pcap_t *p)
34908cf6c252SPaul Traina {
3491681ed54cSXin LI if (!p->activated)
3492681ed54cSXin LI return (PCAP_ERROR_NOT_ACTIVATED);
3493681ed54cSXin LI return (p->swapped);
34948cf6c252SPaul Traina }
34958cf6c252SPaul Traina
34968cf6c252SPaul Traina int
34978cf6c252SPaul Traina pcap_major_version(pcap_t *p)
34988cf6c252SPaul Traina {
3499681ed54cSXin LI if (!p->activated)
3500681ed54cSXin LI return (PCAP_ERROR_NOT_ACTIVATED);
3501681ed54cSXin LI return (p->version_major);
35028cf6c252SPaul Traina }
35038cf6c252SPaul Traina
35048cf6c252SPaul Traina int
35058cf6c252SPaul Traina pcap_minor_version(pcap_t *p)
35068cf6c252SPaul Traina {
3507681ed54cSXin LI if (!p->activated)
3508681ed54cSXin LI return (PCAP_ERROR_NOT_ACTIVATED);
3509681ed54cSXin LI return (p->version_minor);
35108cf6c252SPaul Traina }
35118cf6c252SPaul Traina
3512b00ab754SHans Petter Selasky int
3513b00ab754SHans Petter Selasky pcap_bufsize(pcap_t *p)
3514b00ab754SHans Petter Selasky {
3515b00ab754SHans Petter Selasky if (!p->activated)
3516b00ab754SHans Petter Selasky return (PCAP_ERROR_NOT_ACTIVATED);
3517b00ab754SHans Petter Selasky return (p->bufsize);
3518b00ab754SHans Petter Selasky }
3519b00ab754SHans Petter Selasky
35208cf6c252SPaul Traina FILE *
35218cf6c252SPaul Traina pcap_file(pcap_t *p)
35228cf6c252SPaul Traina {
3523681ed54cSXin LI return (p->rfile);
35248cf6c252SPaul Traina }
35258cf6c252SPaul Traina
35266f9cba8fSJoseph Mingrone #ifdef _WIN32
35278cf6c252SPaul Traina int
35288cf6c252SPaul Traina pcap_fileno(pcap_t *p)
35298cf6c252SPaul Traina {
35306f9cba8fSJoseph Mingrone if (p->handle != INVALID_HANDLE_VALUE) {
35316f9cba8fSJoseph Mingrone /*
35326f9cba8fSJoseph Mingrone * This is a bogus and now-deprecated API; we
35336f9cba8fSJoseph Mingrone * squelch the narrowing warning for the cast
3534*afdbf109SJoseph Mingrone * from HANDLE to intptr_t. If Windows programmers
35356f9cba8fSJoseph Mingrone * need to get at the HANDLE for a pcap_t, *if*
35366f9cba8fSJoseph Mingrone * there is one, they should request such a
35376f9cba8fSJoseph Mingrone * routine (and be prepared for it to return
35386f9cba8fSJoseph Mingrone * INVALID_HANDLE_VALUE).
35396f9cba8fSJoseph Mingrone */
35406f9cba8fSJoseph Mingrone DIAG_OFF_NARROWING
35416f9cba8fSJoseph Mingrone return ((int)(intptr_t)p->handle);
35426f9cba8fSJoseph Mingrone DIAG_ON_NARROWING
35436f9cba8fSJoseph Mingrone } else
3544681ed54cSXin LI return (PCAP_ERROR);
35458cf6c252SPaul Traina }
35466f9cba8fSJoseph Mingrone #else /* _WIN32 */
35476f9cba8fSJoseph Mingrone int
35486f9cba8fSJoseph Mingrone pcap_fileno(pcap_t *p)
35496f9cba8fSJoseph Mingrone {
35506f9cba8fSJoseph Mingrone return (p->fd);
35516f9cba8fSJoseph Mingrone }
35526f9cba8fSJoseph Mingrone #endif /* _WIN32 */
35538cf6c252SPaul Traina
3554ada6f083SXin LI #if !defined(_WIN32) && !defined(MSDOS)
3555feb4ecdbSBruce M Simpson int
3556feb4ecdbSBruce M Simpson pcap_get_selectable_fd(pcap_t *p)
3557feb4ecdbSBruce M Simpson {
3558feb4ecdbSBruce M Simpson return (p->selectable_fd);
3559feb4ecdbSBruce M Simpson }
3560b00ab754SHans Petter Selasky
35616f9cba8fSJoseph Mingrone const struct timeval *
3562b00ab754SHans Petter Selasky pcap_get_required_select_timeout(pcap_t *p)
3563b00ab754SHans Petter Selasky {
3564b00ab754SHans Petter Selasky return (p->required_select_timeout);
3565b00ab754SHans Petter Selasky }
3566feb4ecdbSBruce M Simpson #endif
3567feb4ecdbSBruce M Simpson
35688cf6c252SPaul Traina void
3569ada6f083SXin LI pcap_perror(pcap_t *p, const char *prefix)
35708cf6c252SPaul Traina {
35718cf6c252SPaul Traina fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
35728cf6c252SPaul Traina }
35738cf6c252SPaul Traina
35748cf6c252SPaul Traina char *
35758cf6c252SPaul Traina pcap_geterr(pcap_t *p)
35768cf6c252SPaul Traina {
35778cf6c252SPaul Traina return (p->errbuf);
35788cf6c252SPaul Traina }
35798cf6c252SPaul Traina
35800a94d38fSBill Fenner int
35810a94d38fSBill Fenner pcap_getnonblock(pcap_t *p, char *errbuf)
35820a94d38fSBill Fenner {
3583edc89b24SXin LI int ret;
3584edc89b24SXin LI
3585b00ab754SHans Petter Selasky ret = p->getnonblock_op(p);
3586edc89b24SXin LI if (ret == -1) {
3587edc89b24SXin LI /*
3588b00ab754SHans Petter Selasky * The get nonblock operation sets p->errbuf; this
3589b00ab754SHans Petter Selasky * function *shouldn't* have had a separate errbuf
3590b00ab754SHans Petter Selasky * argument, as it didn't need one, but I goofed
3591b00ab754SHans Petter Selasky * when adding it.
3592b00ab754SHans Petter Selasky *
3593b00ab754SHans Petter Selasky * We copy the error message to errbuf, so callers
3594b00ab754SHans Petter Selasky * can find it in either place.
3595edc89b24SXin LI */
3596*afdbf109SJoseph Mingrone pcapint_strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
3597edc89b24SXin LI }
3598edc89b24SXin LI return (ret);
3599feb4ecdbSBruce M Simpson }
3600feb4ecdbSBruce M Simpson
3601feb4ecdbSBruce M Simpson /*
3602feb4ecdbSBruce M Simpson * Get the current non-blocking mode setting, under the assumption that
3603feb4ecdbSBruce M Simpson * it's just the standard POSIX non-blocking flag.
3604feb4ecdbSBruce M Simpson */
3605ada6f083SXin LI #if !defined(_WIN32) && !defined(MSDOS)
3606feb4ecdbSBruce M Simpson int
3607*afdbf109SJoseph Mingrone pcapint_getnonblock_fd(pcap_t *p)
3608feb4ecdbSBruce M Simpson {
36090a94d38fSBill Fenner int fdflags;
36100a94d38fSBill Fenner
36110a94d38fSBill Fenner fdflags = fcntl(p->fd, F_GETFL, 0);
36120a94d38fSBill Fenner if (fdflags == -1) {
3613*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
3614b00ab754SHans Petter Selasky errno, "F_GETFL");
36150a94d38fSBill Fenner return (-1);
36160a94d38fSBill Fenner }
36170a94d38fSBill Fenner if (fdflags & O_NONBLOCK)
36180a94d38fSBill Fenner return (1);
36190a94d38fSBill Fenner else
36200a94d38fSBill Fenner return (0);
36210a94d38fSBill Fenner }
3622feb4ecdbSBruce M Simpson #endif
36230a94d38fSBill Fenner
36240a94d38fSBill Fenner int
36250a94d38fSBill Fenner pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
36260a94d38fSBill Fenner {
3627edc89b24SXin LI int ret;
3628edc89b24SXin LI
3629b00ab754SHans Petter Selasky ret = p->setnonblock_op(p, nonblock);
3630edc89b24SXin LI if (ret == -1) {
3631edc89b24SXin LI /*
3632b00ab754SHans Petter Selasky * The set nonblock operation sets p->errbuf; this
3633b00ab754SHans Petter Selasky * function *shouldn't* have had a separate errbuf
3634b00ab754SHans Petter Selasky * argument, as it didn't need one, but I goofed
3635b00ab754SHans Petter Selasky * when adding it.
3636b00ab754SHans Petter Selasky *
3637b00ab754SHans Petter Selasky * We copy the error message to errbuf, so callers
3638b00ab754SHans Petter Selasky * can find it in either place.
3639edc89b24SXin LI */
3640*afdbf109SJoseph Mingrone pcapint_strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
3641edc89b24SXin LI }
3642edc89b24SXin LI return (ret);
3643feb4ecdbSBruce M Simpson }
3644feb4ecdbSBruce M Simpson
3645ada6f083SXin LI #if !defined(_WIN32) && !defined(MSDOS)
3646feb4ecdbSBruce M Simpson /*
3647feb4ecdbSBruce M Simpson * Set non-blocking mode, under the assumption that it's just the
3648feb4ecdbSBruce M Simpson * standard POSIX non-blocking flag. (This can be called by the
3649feb4ecdbSBruce M Simpson * per-platform non-blocking-mode routine if that routine also
3650feb4ecdbSBruce M Simpson * needs to do some additional work.)
3651feb4ecdbSBruce M Simpson */
3652feb4ecdbSBruce M Simpson int
3653*afdbf109SJoseph Mingrone pcapint_setnonblock_fd(pcap_t *p, int nonblock)
3654feb4ecdbSBruce M Simpson {
36550a94d38fSBill Fenner int fdflags;
36560a94d38fSBill Fenner
36570a94d38fSBill Fenner fdflags = fcntl(p->fd, F_GETFL, 0);
36580a94d38fSBill Fenner if (fdflags == -1) {
3659*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
3660b00ab754SHans Petter Selasky errno, "F_GETFL");
36610a94d38fSBill Fenner return (-1);
36620a94d38fSBill Fenner }
36630a94d38fSBill Fenner if (nonblock)
36640a94d38fSBill Fenner fdflags |= O_NONBLOCK;
36650a94d38fSBill Fenner else
36660a94d38fSBill Fenner fdflags &= ~O_NONBLOCK;
36670a94d38fSBill Fenner if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
3668*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
3669b00ab754SHans Petter Selasky errno, "F_SETFL");
36700a94d38fSBill Fenner return (-1);
36710a94d38fSBill Fenner }
36720a94d38fSBill Fenner return (0);
36730a94d38fSBill Fenner }
3674feb4ecdbSBruce M Simpson #endif
3675feb4ecdbSBruce M Simpson
36760a94d38fSBill Fenner /*
3677a8e07101SRui Paulo * Generate error strings for PCAP_ERROR_ and PCAP_WARNING_ values.
3678a8e07101SRui Paulo */
3679a8e07101SRui Paulo const char *
3680a8e07101SRui Paulo pcap_statustostr(int errnum)
3681a8e07101SRui Paulo {
3682*afdbf109SJoseph Mingrone static thread_local char ebuf[15+10+1];
3683a8e07101SRui Paulo
3684a8e07101SRui Paulo switch (errnum) {
3685a8e07101SRui Paulo
3686a8e07101SRui Paulo case PCAP_WARNING:
3687a8e07101SRui Paulo return("Generic warning");
3688a8e07101SRui Paulo
3689d1e87331SXin LI case PCAP_WARNING_TSTAMP_TYPE_NOTSUP:
3690d1e87331SXin LI return ("That type of time stamp is not supported by that device");
3691d1e87331SXin LI
3692a8e07101SRui Paulo case PCAP_WARNING_PROMISC_NOTSUP:
3693a8e07101SRui Paulo return ("That device doesn't support promiscuous mode");
3694a8e07101SRui Paulo
3695a8e07101SRui Paulo case PCAP_ERROR:
3696a8e07101SRui Paulo return("Generic error");
3697a8e07101SRui Paulo
3698a8e07101SRui Paulo case PCAP_ERROR_BREAK:
3699a8e07101SRui Paulo return("Loop terminated by pcap_breakloop");
3700a8e07101SRui Paulo
3701a8e07101SRui Paulo case PCAP_ERROR_NOT_ACTIVATED:
3702a8e07101SRui Paulo return("The pcap_t has not been activated");
3703a8e07101SRui Paulo
3704a8e07101SRui Paulo case PCAP_ERROR_ACTIVATED:
3705a8e07101SRui Paulo return ("The setting can't be changed after the pcap_t is activated");
3706a8e07101SRui Paulo
3707a8e07101SRui Paulo case PCAP_ERROR_NO_SUCH_DEVICE:
3708a8e07101SRui Paulo return ("No such device exists");
3709a8e07101SRui Paulo
3710a8e07101SRui Paulo case PCAP_ERROR_RFMON_NOTSUP:
3711a8e07101SRui Paulo return ("That device doesn't support monitor mode");
3712a8e07101SRui Paulo
3713a8e07101SRui Paulo case PCAP_ERROR_NOT_RFMON:
3714a8e07101SRui Paulo return ("That operation is supported only in monitor mode");
3715a8e07101SRui Paulo
3716a8e07101SRui Paulo case PCAP_ERROR_PERM_DENIED:
37176f9cba8fSJoseph Mingrone return ("You don't have permission to perform this capture on that device");
3718a8e07101SRui Paulo
3719a8e07101SRui Paulo case PCAP_ERROR_IFACE_NOT_UP:
3720a8e07101SRui Paulo return ("That device is not up");
3721d1e87331SXin LI
3722d1e87331SXin LI case PCAP_ERROR_CANTSET_TSTAMP_TYPE:
3723d1e87331SXin LI return ("That device doesn't support setting the time stamp type");
3724d1e87331SXin LI
3725d1e87331SXin LI case PCAP_ERROR_PROMISC_PERM_DENIED:
3726d1e87331SXin LI return ("You don't have permission to capture in promiscuous mode on that device");
3727681ed54cSXin LI
3728681ed54cSXin LI case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
3729681ed54cSXin LI return ("That device doesn't support that time stamp precision");
3730*afdbf109SJoseph Mingrone
3731*afdbf109SJoseph Mingrone case PCAP_ERROR_CAPTURE_NOTSUP:
3732*afdbf109SJoseph Mingrone return ("Packet capture is not supported on that device");
3733a8e07101SRui Paulo }
37346f9cba8fSJoseph Mingrone (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
3735a8e07101SRui Paulo return(ebuf);
3736a8e07101SRui Paulo }
3737a8e07101SRui Paulo
3738a8e07101SRui Paulo /*
3739*afdbf109SJoseph Mingrone * A long time ago the purpose of this function was to hide the difference
3740*afdbf109SJoseph Mingrone * between those Unix-like OSes that implemented strerror() and those that
3741*afdbf109SJoseph Mingrone * didn't. All the currently supported OSes implement strerror(), which is in
3742*afdbf109SJoseph Mingrone * POSIX.1-2001, uniformly and that particular problem no longer exists. But
3743*afdbf109SJoseph Mingrone * now they implement a few incompatible thread-safe variants of strerror(),
3744*afdbf109SJoseph Mingrone * and hiding that difference is the current purpose of this function.
37458cf6c252SPaul Traina */
3746ef96d74fSMax Laier const char *
37478cf6c252SPaul Traina pcap_strerror(int errnum)
37488cf6c252SPaul Traina {
3749ada6f083SXin LI #ifdef _WIN32
3750*afdbf109SJoseph Mingrone static thread_local char errbuf[PCAP_ERRBUF_SIZE];
3751b00ab754SHans Petter Selasky errno_t err = strerror_s(errbuf, PCAP_ERRBUF_SIZE, errnum);
3752b00ab754SHans Petter Selasky
3753b00ab754SHans Petter Selasky if (err != 0) /* err = 0 if successful */
3754*afdbf109SJoseph Mingrone pcapint_strlcpy(errbuf, "strerror_s() error", PCAP_ERRBUF_SIZE);
3755ada6f083SXin LI return (errbuf);
3756*afdbf109SJoseph Mingrone #elif defined(HAVE_GNU_STRERROR_R)
3757*afdbf109SJoseph Mingrone /*
3758*afdbf109SJoseph Mingrone * We have a GNU-style strerror_r(), which is *not* guaranteed to
3759*afdbf109SJoseph Mingrone * do anything to the buffer handed to it, and which returns a
3760*afdbf109SJoseph Mingrone * pointer to the error string, which may or may not be in
3761*afdbf109SJoseph Mingrone * the buffer.
3762*afdbf109SJoseph Mingrone *
3763*afdbf109SJoseph Mingrone * It is, however, guaranteed to succeed.
3764*afdbf109SJoseph Mingrone *
3765*afdbf109SJoseph Mingrone * At the time of this writing this applies to the following cases,
3766*afdbf109SJoseph Mingrone * each of which allows to use either the GNU implementation or the
3767*afdbf109SJoseph Mingrone * POSIX implementation, and this source tree defines _GNU_SOURCE to
3768*afdbf109SJoseph Mingrone * use the GNU implementation:
3769*afdbf109SJoseph Mingrone * - Hurd
3770*afdbf109SJoseph Mingrone * - Linux with GNU libc
3771*afdbf109SJoseph Mingrone * - Linux with uClibc-ng
3772*afdbf109SJoseph Mingrone */
3773*afdbf109SJoseph Mingrone static thread_local char errbuf[PCAP_ERRBUF_SIZE];
3774*afdbf109SJoseph Mingrone return strerror_r(errnum, errbuf, PCAP_ERRBUF_SIZE);
3775*afdbf109SJoseph Mingrone #elif defined(HAVE_POSIX_STRERROR_R)
3776*afdbf109SJoseph Mingrone /*
3777*afdbf109SJoseph Mingrone * We have a POSIX-style strerror_r(), which is guaranteed to fill
3778*afdbf109SJoseph Mingrone * in the buffer, but is not guaranteed to succeed.
3779*afdbf109SJoseph Mingrone *
3780*afdbf109SJoseph Mingrone * At the time of this writing this applies to the following cases:
3781*afdbf109SJoseph Mingrone * - AIX 7
3782*afdbf109SJoseph Mingrone * - FreeBSD
3783*afdbf109SJoseph Mingrone * - Haiku
3784*afdbf109SJoseph Mingrone * - HP-UX 11
3785*afdbf109SJoseph Mingrone * - illumos
3786*afdbf109SJoseph Mingrone * - Linux with musl libc
3787*afdbf109SJoseph Mingrone * - macOS
3788*afdbf109SJoseph Mingrone * - NetBSD
3789*afdbf109SJoseph Mingrone * - OpenBSD
3790*afdbf109SJoseph Mingrone * - Solaris 10 & 11
3791*afdbf109SJoseph Mingrone */
3792*afdbf109SJoseph Mingrone static thread_local char errbuf[PCAP_ERRBUF_SIZE];
3793*afdbf109SJoseph Mingrone int err = strerror_r(errnum, errbuf, PCAP_ERRBUF_SIZE);
3794*afdbf109SJoseph Mingrone switch (err) {
3795*afdbf109SJoseph Mingrone case 0:
3796*afdbf109SJoseph Mingrone /* That worked. */
3797*afdbf109SJoseph Mingrone break;
3798*afdbf109SJoseph Mingrone
3799*afdbf109SJoseph Mingrone case EINVAL:
3800*afdbf109SJoseph Mingrone /*
3801*afdbf109SJoseph Mingrone * UNIX 03 says this isn't guaranteed to produce a
3802*afdbf109SJoseph Mingrone * fallback error message.
3803*afdbf109SJoseph Mingrone */
3804*afdbf109SJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE,
3805*afdbf109SJoseph Mingrone "Unknown error: %d", errnum);
3806*afdbf109SJoseph Mingrone break;
3807*afdbf109SJoseph Mingrone case ERANGE:
3808*afdbf109SJoseph Mingrone /*
3809*afdbf109SJoseph Mingrone * UNIX 03 says this isn't guaranteed to produce a
3810*afdbf109SJoseph Mingrone * fallback error message.
3811*afdbf109SJoseph Mingrone */
3812*afdbf109SJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE,
3813*afdbf109SJoseph Mingrone "Message for error %d is too long", errnum);
3814*afdbf109SJoseph Mingrone break;
3815*afdbf109SJoseph Mingrone default:
3816*afdbf109SJoseph Mingrone snprintf(errbuf, PCAP_ERRBUF_SIZE,
3817*afdbf109SJoseph Mingrone "strerror_r(%d, ...) unexpectedly returned %d",
3818*afdbf109SJoseph Mingrone errnum, err);
3819*afdbf109SJoseph Mingrone }
3820*afdbf109SJoseph Mingrone return errbuf;
3821ada6f083SXin LI #else
3822*afdbf109SJoseph Mingrone /*
3823*afdbf109SJoseph Mingrone * At the time of this writing every supported OS implements strerror()
3824*afdbf109SJoseph Mingrone * and at least one thread-safe variant thereof, so this is a very
3825*afdbf109SJoseph Mingrone * unlikely last-resort branch. Particular implementations of strerror()
3826*afdbf109SJoseph Mingrone * may be thread-safe, but this is neither required nor guaranteed.
3827*afdbf109SJoseph Mingrone */
38288cf6c252SPaul Traina return (strerror(errnum));
3829ada6f083SXin LI #endif /* _WIN32 */
38308cf6c252SPaul Traina }
38318cf6c252SPaul Traina
3832feb4ecdbSBruce M Simpson int
3833feb4ecdbSBruce M Simpson pcap_setfilter(pcap_t *p, struct bpf_program *fp)
3834feb4ecdbSBruce M Simpson {
3835d1e87331SXin LI return (p->setfilter_op(p, fp));
3836feb4ecdbSBruce M Simpson }
3837feb4ecdbSBruce M Simpson
3838ee2dd488SSam Leffler /*
3839ee2dd488SSam Leffler * Set direction flag, which controls whether we accept only incoming
3840ee2dd488SSam Leffler * packets, only outgoing packets, or both.
3841ee2dd488SSam Leffler * Note that, depending on the platform, some or all direction arguments
3842ee2dd488SSam Leffler * might not be supported.
3843ee2dd488SSam Leffler */
3844ee2dd488SSam Leffler int
38455d18909fSSam Leffler pcap_setdirection(pcap_t *p, pcap_direction_t d)
3846ee2dd488SSam Leffler {
3847ee2dd488SSam Leffler if (p->setdirection_op == NULL) {
38486f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
38496f9cba8fSJoseph Mingrone "Setting direction is not supported on this device");
3850d1e87331SXin LI return (-1);
38516f9cba8fSJoseph Mingrone } else {
38526f9cba8fSJoseph Mingrone switch (d) {
38536f9cba8fSJoseph Mingrone
38546f9cba8fSJoseph Mingrone case PCAP_D_IN:
38556f9cba8fSJoseph Mingrone case PCAP_D_OUT:
38566f9cba8fSJoseph Mingrone case PCAP_D_INOUT:
38576f9cba8fSJoseph Mingrone /*
38586f9cba8fSJoseph Mingrone * Valid direction.
38596f9cba8fSJoseph Mingrone */
3860d1e87331SXin LI return (p->setdirection_op(p, d));
38616f9cba8fSJoseph Mingrone
38626f9cba8fSJoseph Mingrone default:
38636f9cba8fSJoseph Mingrone /*
38646f9cba8fSJoseph Mingrone * Invalid direction.
38656f9cba8fSJoseph Mingrone */
38666f9cba8fSJoseph Mingrone snprintf(p->errbuf, sizeof(p->errbuf),
38676f9cba8fSJoseph Mingrone "Invalid direction");
38686f9cba8fSJoseph Mingrone return (-1);
38696f9cba8fSJoseph Mingrone }
38706f9cba8fSJoseph Mingrone }
3871ee2dd488SSam Leffler }
3872ee2dd488SSam Leffler
3873feb4ecdbSBruce M Simpson int
3874feb4ecdbSBruce M Simpson pcap_stats(pcap_t *p, struct pcap_stat *ps)
3875feb4ecdbSBruce M Simpson {
3876d1e87331SXin LI return (p->stats_op(p, ps));
3877feb4ecdbSBruce M Simpson }
3878feb4ecdbSBruce M Simpson
3879ada6f083SXin LI #ifdef _WIN32
3880ada6f083SXin LI struct pcap_stat *
3881ada6f083SXin LI pcap_stats_ex(pcap_t *p, int *pcap_stat_size)
3882ada6f083SXin LI {
3883ada6f083SXin LI return (p->stats_ex_op(p, pcap_stat_size));
3884ada6f083SXin LI }
3885ada6f083SXin LI
3886a8e07101SRui Paulo int
3887a8e07101SRui Paulo pcap_setbuff(pcap_t *p, int dim)
388804fb2745SSam Leffler {
3889d1e87331SXin LI return (p->setbuff_op(p, dim));
3890a8e07101SRui Paulo }
3891a8e07101SRui Paulo
3892a8e07101SRui Paulo int
3893a8e07101SRui Paulo pcap_setmode(pcap_t *p, int mode)
3894a8e07101SRui Paulo {
3895d1e87331SXin LI return (p->setmode_op(p, mode));
3896a8e07101SRui Paulo }
3897a8e07101SRui Paulo
3898a8e07101SRui Paulo int
3899a8e07101SRui Paulo pcap_setmintocopy(pcap_t *p, int size)
3900a8e07101SRui Paulo {
3901d1e87331SXin LI return (p->setmintocopy_op(p, size));
3902a8e07101SRui Paulo }
3903a8e07101SRui Paulo
3904ada6f083SXin LI HANDLE
3905ada6f083SXin LI pcap_getevent(pcap_t *p)
3906ada6f083SXin LI {
3907ada6f083SXin LI return (p->getevent_op(p));
3908ada6f083SXin LI }
3909ada6f083SXin LI
3910ada6f083SXin LI int
3911ada6f083SXin LI pcap_oid_get_request(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
3912ada6f083SXin LI {
3913ada6f083SXin LI return (p->oid_get_request_op(p, oid, data, lenp));
3914ada6f083SXin LI }
3915ada6f083SXin LI
3916ada6f083SXin LI int
3917ada6f083SXin LI pcap_oid_set_request(pcap_t *p, bpf_u_int32 oid, const void *data, size_t *lenp)
3918ada6f083SXin LI {
3919ada6f083SXin LI return (p->oid_set_request_op(p, oid, data, lenp));
3920ada6f083SXin LI }
3921ada6f083SXin LI
3922ada6f083SXin LI pcap_send_queue *
3923ada6f083SXin LI pcap_sendqueue_alloc(u_int memsize)
3924ada6f083SXin LI {
3925ada6f083SXin LI pcap_send_queue *tqueue;
3926ada6f083SXin LI
3927ada6f083SXin LI /* Allocate the queue */
3928ada6f083SXin LI tqueue = (pcap_send_queue *)malloc(sizeof(pcap_send_queue));
3929ada6f083SXin LI if (tqueue == NULL){
3930ada6f083SXin LI return (NULL);
3931ada6f083SXin LI }
3932ada6f083SXin LI
3933ada6f083SXin LI /* Allocate the buffer */
3934ada6f083SXin LI tqueue->buffer = (char *)malloc(memsize);
3935ada6f083SXin LI if (tqueue->buffer == NULL) {
3936ada6f083SXin LI free(tqueue);
3937ada6f083SXin LI return (NULL);
3938ada6f083SXin LI }
3939ada6f083SXin LI
3940ada6f083SXin LI tqueue->maxlen = memsize;
3941ada6f083SXin LI tqueue->len = 0;
3942ada6f083SXin LI
3943ada6f083SXin LI return (tqueue);
3944ada6f083SXin LI }
3945ada6f083SXin LI
3946ada6f083SXin LI void
3947ada6f083SXin LI pcap_sendqueue_destroy(pcap_send_queue *queue)
3948ada6f083SXin LI {
3949ada6f083SXin LI free(queue->buffer);
3950ada6f083SXin LI free(queue);
3951ada6f083SXin LI }
3952ada6f083SXin LI
3953ada6f083SXin LI int
3954ada6f083SXin LI pcap_sendqueue_queue(pcap_send_queue *queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
3955ada6f083SXin LI {
3956ada6f083SXin LI if (queue->len + sizeof(struct pcap_pkthdr) + pkt_header->caplen > queue->maxlen){
3957ada6f083SXin LI return (-1);
3958ada6f083SXin LI }
3959ada6f083SXin LI
3960ada6f083SXin LI /* Copy the pcap_pkthdr header*/
3961ada6f083SXin LI memcpy(queue->buffer + queue->len, pkt_header, sizeof(struct pcap_pkthdr));
3962ada6f083SXin LI queue->len += sizeof(struct pcap_pkthdr);
3963ada6f083SXin LI
3964ada6f083SXin LI /* copy the packet */
3965ada6f083SXin LI memcpy(queue->buffer + queue->len, pkt_data, pkt_header->caplen);
3966ada6f083SXin LI queue->len += pkt_header->caplen;
3967ada6f083SXin LI
3968ada6f083SXin LI return (0);
3969ada6f083SXin LI }
3970ada6f083SXin LI
3971ada6f083SXin LI u_int
3972ada6f083SXin LI pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue, int sync)
3973ada6f083SXin LI {
3974ada6f083SXin LI return (p->sendqueue_transmit_op(p, queue, sync));
3975ada6f083SXin LI }
3976ada6f083SXin LI
3977ada6f083SXin LI int
3978ada6f083SXin LI pcap_setuserbuffer(pcap_t *p, int size)
3979ada6f083SXin LI {
3980ada6f083SXin LI return (p->setuserbuffer_op(p, size));
3981ada6f083SXin LI }
3982ada6f083SXin LI
3983ada6f083SXin LI int
3984ada6f083SXin LI pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks)
3985ada6f083SXin LI {
3986ada6f083SXin LI return (p->live_dump_op(p, filename, maxsize, maxpacks));
3987ada6f083SXin LI }
3988ada6f083SXin LI
3989ada6f083SXin LI int
3990ada6f083SXin LI pcap_live_dump_ended(pcap_t *p, int sync)
3991ada6f083SXin LI {
3992ada6f083SXin LI return (p->live_dump_ended_op(p, sync));
3993ada6f083SXin LI }
3994ada6f083SXin LI
3995ada6f083SXin LI PAirpcapHandle
3996ada6f083SXin LI pcap_get_airpcap_handle(pcap_t *p)
3997ada6f083SXin LI {
3998ada6f083SXin LI PAirpcapHandle handle;
3999ada6f083SXin LI
4000ada6f083SXin LI handle = p->get_airpcap_handle_op(p);
4001ada6f083SXin LI if (handle == NULL) {
40026f9cba8fSJoseph Mingrone (void)snprintf(p->errbuf, sizeof(p->errbuf),
4003ada6f083SXin LI "This isn't an AirPcap device");
4004ada6f083SXin LI }
4005ada6f083SXin LI return (handle);
4006ada6f083SXin LI }
4007154bbe41SChristian S.J. Peron #endif
4008a8e07101SRui Paulo
4009a8e07101SRui Paulo /*
4010a8e07101SRui Paulo * On some platforms, we need to clean up promiscuous or monitor mode
4011a8e07101SRui Paulo * when we close a device - and we want that to happen even if the
4012*afdbf109SJoseph Mingrone * application just exits without explicitly closing devices.
4013a8e07101SRui Paulo * On those platforms, we need to register a "close all the pcaps"
4014a8e07101SRui Paulo * routine to be called when we exit, and need to maintain a list of
4015a8e07101SRui Paulo * pcaps that need to be closed to clean up modes.
4016a8e07101SRui Paulo *
4017a8e07101SRui Paulo * XXX - not thread-safe.
4018a8e07101SRui Paulo */
4019a8e07101SRui Paulo
4020a8e07101SRui Paulo /*
4021a8e07101SRui Paulo * List of pcaps on which we've done something that needs to be
4022a8e07101SRui Paulo * cleaned up.
4023a8e07101SRui Paulo * If there are any such pcaps, we arrange to call "pcap_close_all()"
4024a8e07101SRui Paulo * when we exit, and have it close all of them.
4025a8e07101SRui Paulo */
4026a8e07101SRui Paulo static struct pcap *pcaps_to_close;
4027a8e07101SRui Paulo
4028a8e07101SRui Paulo /*
4029a8e07101SRui Paulo * TRUE if we've already called "atexit()" to cause "pcap_close_all()" to
4030a8e07101SRui Paulo * be called on exit.
4031a8e07101SRui Paulo */
4032a8e07101SRui Paulo static int did_atexit;
4033a8e07101SRui Paulo
4034a8e07101SRui Paulo static void
4035a8e07101SRui Paulo pcap_close_all(void)
4036a8e07101SRui Paulo {
4037a8e07101SRui Paulo struct pcap *handle;
4038a8e07101SRui Paulo
40396f9cba8fSJoseph Mingrone while ((handle = pcaps_to_close) != NULL) {
4040a8e07101SRui Paulo pcap_close(handle);
40416f9cba8fSJoseph Mingrone
40426f9cba8fSJoseph Mingrone /*
40436f9cba8fSJoseph Mingrone * If a pcap module adds a pcap_t to the "close all"
4044*afdbf109SJoseph Mingrone * list by calling pcapint_add_to_pcaps_to_close(), it
40456f9cba8fSJoseph Mingrone * must have a cleanup routine that removes it from the
4046*afdbf109SJoseph Mingrone * list, by calling pcapint_remove_from_pcaps_to_close(),
40476f9cba8fSJoseph Mingrone * and must make that cleanup routine the cleanup_op
40486f9cba8fSJoseph Mingrone * for the pcap_t.
40496f9cba8fSJoseph Mingrone *
40506f9cba8fSJoseph Mingrone * That means that, after pcap_close() - which calls
40516f9cba8fSJoseph Mingrone * the cleanup_op for the pcap_t - the pcap_t must
40526f9cba8fSJoseph Mingrone * have been removed from the list, so pcaps_to_close
40536f9cba8fSJoseph Mingrone * must not be equal to handle.
40546f9cba8fSJoseph Mingrone *
40556f9cba8fSJoseph Mingrone * We check for that, and abort if handle is still
40566f9cba8fSJoseph Mingrone * at the head of the list, to prevent infinite loops.
40576f9cba8fSJoseph Mingrone */
40586f9cba8fSJoseph Mingrone if (pcaps_to_close == handle)
40596f9cba8fSJoseph Mingrone abort();
40606f9cba8fSJoseph Mingrone }
4061a8e07101SRui Paulo }
4062a8e07101SRui Paulo
4063a8e07101SRui Paulo int
4064*afdbf109SJoseph Mingrone pcapint_do_addexit(pcap_t *p)
4065a8e07101SRui Paulo {
4066a8e07101SRui Paulo /*
4067a8e07101SRui Paulo * If we haven't already done so, arrange to have
4068a8e07101SRui Paulo * "pcap_close_all()" called when we exit.
4069a8e07101SRui Paulo */
4070a8e07101SRui Paulo if (!did_atexit) {
4071ada6f083SXin LI if (atexit(pcap_close_all) != 0) {
4072a8e07101SRui Paulo /*
4073a8e07101SRui Paulo * "atexit()" failed; let our caller know.
4074a8e07101SRui Paulo */
4075*afdbf109SJoseph Mingrone pcapint_strlcpy(p->errbuf, "atexit failed", PCAP_ERRBUF_SIZE);
4076a8e07101SRui Paulo return (0);
4077a8e07101SRui Paulo }
4078a8e07101SRui Paulo did_atexit = 1;
4079a8e07101SRui Paulo }
4080a8e07101SRui Paulo return (1);
4081a8e07101SRui Paulo }
4082a8e07101SRui Paulo
4083a8e07101SRui Paulo void
4084*afdbf109SJoseph Mingrone pcapint_add_to_pcaps_to_close(pcap_t *p)
4085a8e07101SRui Paulo {
4086681ed54cSXin LI p->next = pcaps_to_close;
4087a8e07101SRui Paulo pcaps_to_close = p;
4088a8e07101SRui Paulo }
4089a8e07101SRui Paulo
4090a8e07101SRui Paulo void
4091*afdbf109SJoseph Mingrone pcapint_remove_from_pcaps_to_close(pcap_t *p)
4092a8e07101SRui Paulo {
4093a8e07101SRui Paulo pcap_t *pc, *prevpc;
4094a8e07101SRui Paulo
4095a8e07101SRui Paulo for (pc = pcaps_to_close, prevpc = NULL; pc != NULL;
4096681ed54cSXin LI prevpc = pc, pc = pc->next) {
4097a8e07101SRui Paulo if (pc == p) {
4098a8e07101SRui Paulo /*
4099a8e07101SRui Paulo * Found it. Remove it from the list.
4100a8e07101SRui Paulo */
4101a8e07101SRui Paulo if (prevpc == NULL) {
4102a8e07101SRui Paulo /*
4103a8e07101SRui Paulo * It was at the head of the list.
4104a8e07101SRui Paulo */
4105681ed54cSXin LI pcaps_to_close = pc->next;
4106a8e07101SRui Paulo } else {
4107a8e07101SRui Paulo /*
4108a8e07101SRui Paulo * It was in the middle of the list.
4109a8e07101SRui Paulo */
4110681ed54cSXin LI prevpc->next = pc->next;
4111a8e07101SRui Paulo }
4112a8e07101SRui Paulo break;
4113a8e07101SRui Paulo }
4114a8e07101SRui Paulo }
4115a8e07101SRui Paulo }
4116a8e07101SRui Paulo
4117a8e07101SRui Paulo void
4118*afdbf109SJoseph Mingrone pcapint_breakloop_common(pcap_t *p)
41196f9cba8fSJoseph Mingrone {
41206f9cba8fSJoseph Mingrone p->break_loop = 1;
41216f9cba8fSJoseph Mingrone }
41226f9cba8fSJoseph Mingrone
41236f9cba8fSJoseph Mingrone
41246f9cba8fSJoseph Mingrone void
4125*afdbf109SJoseph Mingrone pcapint_cleanup_live_common(pcap_t *p)
4126a8e07101SRui Paulo {
41276f9cba8fSJoseph Mingrone if (p->opt.device != NULL) {
41286f9cba8fSJoseph Mingrone free(p->opt.device);
41296f9cba8fSJoseph Mingrone p->opt.device = NULL;
41306f9cba8fSJoseph Mingrone }
4131a8e07101SRui Paulo if (p->buffer != NULL) {
413204fb2745SSam Leffler free(p->buffer);
4133a8e07101SRui Paulo p->buffer = NULL;
4134a8e07101SRui Paulo }
4135a8e07101SRui Paulo if (p->dlt_list != NULL) {
4136a8e07101SRui Paulo free(p->dlt_list);
4137a8e07101SRui Paulo p->dlt_list = NULL;
4138a8e07101SRui Paulo p->dlt_count = 0;
4139a8e07101SRui Paulo }
4140d1e87331SXin LI if (p->tstamp_type_list != NULL) {
4141d1e87331SXin LI free(p->tstamp_type_list);
4142d1e87331SXin LI p->tstamp_type_list = NULL;
4143d1e87331SXin LI p->tstamp_type_count = 0;
4144d1e87331SXin LI }
4145681ed54cSXin LI if (p->tstamp_precision_list != NULL) {
4146681ed54cSXin LI free(p->tstamp_precision_list);
4147681ed54cSXin LI p->tstamp_precision_list = NULL;
4148681ed54cSXin LI p->tstamp_precision_count = 0;
4149681ed54cSXin LI }
4150a8e07101SRui Paulo pcap_freecode(&p->fcode);
4151ada6f083SXin LI #if !defined(_WIN32) && !defined(MSDOS)
4152a8e07101SRui Paulo if (p->fd >= 0) {
415304fb2745SSam Leffler close(p->fd);
4154a8e07101SRui Paulo p->fd = -1;
4155a8e07101SRui Paulo }
4156a0ee43a1SRui Paulo p->selectable_fd = -1;
415704fb2745SSam Leffler #endif
415804fb2745SSam Leffler }
415904fb2745SSam Leffler
416004fb2745SSam Leffler /*
416104fb2745SSam Leffler * API compatible with WinPcap's "send a packet" routine - returns -1
416204fb2745SSam Leffler * on error, 0 otherwise.
416304fb2745SSam Leffler *
416404fb2745SSam Leffler * XXX - what if we get a short write?
416504fb2745SSam Leffler */
416604fb2745SSam Leffler int
416704fb2745SSam Leffler pcap_sendpacket(pcap_t *p, const u_char *buf, int size)
416804fb2745SSam Leffler {
41696f9cba8fSJoseph Mingrone if (size <= 0) {
4170*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
41716f9cba8fSJoseph Mingrone errno, "The number of bytes to be sent must be positive");
41726f9cba8fSJoseph Mingrone return (PCAP_ERROR);
41736f9cba8fSJoseph Mingrone }
41746f9cba8fSJoseph Mingrone
417504fb2745SSam Leffler if (p->inject_op(p, buf, size) == -1)
417604fb2745SSam Leffler return (-1);
417704fb2745SSam Leffler return (0);
417804fb2745SSam Leffler }
417904fb2745SSam Leffler
418004fb2745SSam Leffler /*
418104fb2745SSam Leffler * API compatible with OpenBSD's "send a packet" routine - returns -1 on
418204fb2745SSam Leffler * error, number of bytes written otherwise.
418304fb2745SSam Leffler */
418404fb2745SSam Leffler int
418504fb2745SSam Leffler pcap_inject(pcap_t *p, const void *buf, size_t size)
418604fb2745SSam Leffler {
41876f9cba8fSJoseph Mingrone /*
41886f9cba8fSJoseph Mingrone * We return the number of bytes written, so the number of
41896f9cba8fSJoseph Mingrone * bytes to write must fit in an int.
41906f9cba8fSJoseph Mingrone */
41916f9cba8fSJoseph Mingrone if (size > INT_MAX) {
4192*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
41936f9cba8fSJoseph Mingrone errno, "More than %d bytes cannot be injected", INT_MAX);
41946f9cba8fSJoseph Mingrone return (PCAP_ERROR);
41956f9cba8fSJoseph Mingrone }
41966f9cba8fSJoseph Mingrone
41976f9cba8fSJoseph Mingrone if (size == 0) {
4198*afdbf109SJoseph Mingrone pcapint_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
41996f9cba8fSJoseph Mingrone errno, "The number of bytes to be injected must not be zero");
42006f9cba8fSJoseph Mingrone return (PCAP_ERROR);
42016f9cba8fSJoseph Mingrone }
42026f9cba8fSJoseph Mingrone
42036f9cba8fSJoseph Mingrone return (p->inject_op(p, buf, (int)size));
420404fb2745SSam Leffler }
420504fb2745SSam Leffler
42068cf6c252SPaul Traina void
42078cf6c252SPaul Traina pcap_close(pcap_t *p)
42088cf6c252SPaul Traina {
4209a8e07101SRui Paulo p->cleanup_op(p);
42108cf6c252SPaul Traina free(p);
42118cf6c252SPaul Traina }
4212feb4ecdbSBruce M Simpson
4213feb4ecdbSBruce M Simpson /*
42146f9cba8fSJoseph Mingrone * Helpers for safely loading code at run time.
42156f9cba8fSJoseph Mingrone * Currently Windows-only.
42166f9cba8fSJoseph Mingrone */
42176f9cba8fSJoseph Mingrone #ifdef _WIN32
42186f9cba8fSJoseph Mingrone //
42196f9cba8fSJoseph Mingrone // This wrapper around loadlibrary appends the system folder (usually
42206f9cba8fSJoseph Mingrone // C:\Windows\System32) to the relative path of the DLL, so that the DLL
42216f9cba8fSJoseph Mingrone // is always loaded from an absolute path (it's no longer possible to
42226f9cba8fSJoseph Mingrone // load modules from the application folder).
42236f9cba8fSJoseph Mingrone // This solves the DLL Hijacking issue discovered in August 2010:
42246f9cba8fSJoseph Mingrone //
42256f9cba8fSJoseph Mingrone // https://blog.rapid7.com/2010/08/23/exploiting-dll-hijacking-flaws/
42266f9cba8fSJoseph Mingrone // https://blog.rapid7.com/2010/08/23/application-dll-load-hijacking/
42276f9cba8fSJoseph Mingrone // (the purported Rapid7 blog post link in the first of those two links
42286f9cba8fSJoseph Mingrone // is broken; the second of those links works.)
42296f9cba8fSJoseph Mingrone //
42306f9cba8fSJoseph Mingrone // If any links there are broken from all the content shuffling Rapid&
42316f9cba8fSJoseph Mingrone // did, see archived versions of the posts at their original homes, at
42326f9cba8fSJoseph Mingrone //
42336f9cba8fSJoseph Mingrone // https://web.archive.org/web/20110122175058/http://blog.metasploit.com/2010/08/exploiting-dll-hijacking-flaws.html
42346f9cba8fSJoseph Mingrone // https://web.archive.org/web/20100828112111/http://blog.rapid7.com/?p=5325
42356f9cba8fSJoseph Mingrone //
42366f9cba8fSJoseph Mingrone pcap_code_handle_t
4237*afdbf109SJoseph Mingrone pcapint_load_code(const char *name)
42386f9cba8fSJoseph Mingrone {
42396f9cba8fSJoseph Mingrone /*
42406f9cba8fSJoseph Mingrone * XXX - should this work in UTF-16LE rather than in the local
42416f9cba8fSJoseph Mingrone * ANSI code page?
42426f9cba8fSJoseph Mingrone */
42436f9cba8fSJoseph Mingrone CHAR path[MAX_PATH];
42446f9cba8fSJoseph Mingrone CHAR fullFileName[MAX_PATH];
42456f9cba8fSJoseph Mingrone UINT res;
42466f9cba8fSJoseph Mingrone HMODULE hModule = NULL;
42476f9cba8fSJoseph Mingrone
42486f9cba8fSJoseph Mingrone do
42496f9cba8fSJoseph Mingrone {
42506f9cba8fSJoseph Mingrone res = GetSystemDirectoryA(path, MAX_PATH);
42516f9cba8fSJoseph Mingrone
42526f9cba8fSJoseph Mingrone if (res == 0) {
42536f9cba8fSJoseph Mingrone //
42546f9cba8fSJoseph Mingrone // some bad failure occurred;
42556f9cba8fSJoseph Mingrone //
42566f9cba8fSJoseph Mingrone break;
42576f9cba8fSJoseph Mingrone }
42586f9cba8fSJoseph Mingrone
42596f9cba8fSJoseph Mingrone if (res > MAX_PATH) {
42606f9cba8fSJoseph Mingrone //
42616f9cba8fSJoseph Mingrone // the buffer was not big enough
42626f9cba8fSJoseph Mingrone //
42636f9cba8fSJoseph Mingrone SetLastError(ERROR_INSUFFICIENT_BUFFER);
42646f9cba8fSJoseph Mingrone break;
42656f9cba8fSJoseph Mingrone }
42666f9cba8fSJoseph Mingrone
42676f9cba8fSJoseph Mingrone if (res + 1 + strlen(name) + 1 < MAX_PATH) {
42686f9cba8fSJoseph Mingrone memcpy(fullFileName, path, res * sizeof(TCHAR));
42696f9cba8fSJoseph Mingrone fullFileName[res] = '\\';
42706f9cba8fSJoseph Mingrone memcpy(&fullFileName[res + 1], name, (strlen(name) + 1) * sizeof(TCHAR));
42716f9cba8fSJoseph Mingrone
42726f9cba8fSJoseph Mingrone hModule = LoadLibraryA(fullFileName);
42736f9cba8fSJoseph Mingrone } else
42746f9cba8fSJoseph Mingrone SetLastError(ERROR_INSUFFICIENT_BUFFER);
42756f9cba8fSJoseph Mingrone
42766f9cba8fSJoseph Mingrone } while(FALSE);
42776f9cba8fSJoseph Mingrone
42786f9cba8fSJoseph Mingrone return hModule;
42796f9cba8fSJoseph Mingrone }
42806f9cba8fSJoseph Mingrone
42816f9cba8fSJoseph Mingrone pcap_funcptr_t
4282*afdbf109SJoseph Mingrone pcapint_find_function(pcap_code_handle_t code, const char *func)
42836f9cba8fSJoseph Mingrone {
42846f9cba8fSJoseph Mingrone return (GetProcAddress(code, func));
42856f9cba8fSJoseph Mingrone }
42866f9cba8fSJoseph Mingrone #endif
42876f9cba8fSJoseph Mingrone
42886f9cba8fSJoseph Mingrone /*
4289a8e07101SRui Paulo * Given a BPF program, a pcap_pkthdr structure for a packet, and the raw
4290a8e07101SRui Paulo * data for the packet, check whether the packet passes the filter.
4291a8e07101SRui Paulo * Returns the return value of the filter program, which will be zero if
4292a8e07101SRui Paulo * the packet doesn't pass and non-zero if the packet does pass.
4293a8e07101SRui Paulo */
4294a8e07101SRui Paulo int
4295edc89b24SXin LI pcap_offline_filter(const struct bpf_program *fp, const struct pcap_pkthdr *h,
4296a8e07101SRui Paulo const u_char *pkt)
4297a8e07101SRui Paulo {
4298edc89b24SXin LI const struct bpf_insn *fcode = fp->bf_insns;
4299a8e07101SRui Paulo
4300a8e07101SRui Paulo if (fcode != NULL)
4301*afdbf109SJoseph Mingrone return (pcapint_filter(fcode, pkt, h->len, h->caplen));
4302a8e07101SRui Paulo else
4303a8e07101SRui Paulo return (0);
4304a8e07101SRui Paulo }
4305a8e07101SRui Paulo
4306b00ab754SHans Petter Selasky static int
4307b00ab754SHans Petter Selasky pcap_can_set_rfmon_dead(pcap_t *p)
4308b00ab754SHans Petter Selasky {
43096f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4310b00ab754SHans Petter Selasky "Rfmon mode doesn't apply on a pcap_open_dead pcap_t");
4311b00ab754SHans Petter Selasky return (PCAP_ERROR);
4312b00ab754SHans Petter Selasky }
4313b00ab754SHans Petter Selasky
4314b00ab754SHans Petter Selasky static int
4315b00ab754SHans Petter Selasky pcap_read_dead(pcap_t *p, int cnt _U_, pcap_handler callback _U_,
4316b00ab754SHans Petter Selasky u_char *user _U_)
4317b00ab754SHans Petter Selasky {
43186f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4319b00ab754SHans Petter Selasky "Packets aren't available from a pcap_open_dead pcap_t");
4320b00ab754SHans Petter Selasky return (-1);
4321b00ab754SHans Petter Selasky }
4322b00ab754SHans Petter Selasky
43236f9cba8fSJoseph Mingrone static void
43246f9cba8fSJoseph Mingrone pcap_breakloop_dead(pcap_t *p _U_)
4325b00ab754SHans Petter Selasky {
43266f9cba8fSJoseph Mingrone /*
43276f9cba8fSJoseph Mingrone * A "dead" pcap_t is just a placeholder to use in order to
43286f9cba8fSJoseph Mingrone * compile a filter to BPF code or to open a savefile for
43296f9cba8fSJoseph Mingrone * writing. It doesn't support any operations, including
43306f9cba8fSJoseph Mingrone * capturing or reading packets, so there will never be a
43316f9cba8fSJoseph Mingrone * get-packets loop in progress to break out *of*.
43326f9cba8fSJoseph Mingrone *
43336f9cba8fSJoseph Mingrone * As such, this routine doesn't need to do anything.
43346f9cba8fSJoseph Mingrone */
43356f9cba8fSJoseph Mingrone }
43366f9cba8fSJoseph Mingrone
43376f9cba8fSJoseph Mingrone static int
43386f9cba8fSJoseph Mingrone pcap_inject_dead(pcap_t *p, const void *buf _U_, int size _U_)
43396f9cba8fSJoseph Mingrone {
43406f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4341b00ab754SHans Petter Selasky "Packets can't be sent on a pcap_open_dead pcap_t");
4342b00ab754SHans Petter Selasky return (-1);
4343b00ab754SHans Petter Selasky }
4344b00ab754SHans Petter Selasky
4345b00ab754SHans Petter Selasky static int
4346b00ab754SHans Petter Selasky pcap_setfilter_dead(pcap_t *p, struct bpf_program *fp _U_)
4347b00ab754SHans Petter Selasky {
43486f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4349b00ab754SHans Petter Selasky "A filter cannot be set on a pcap_open_dead pcap_t");
4350b00ab754SHans Petter Selasky return (-1);
4351b00ab754SHans Petter Selasky }
4352b00ab754SHans Petter Selasky
4353b00ab754SHans Petter Selasky static int
4354b00ab754SHans Petter Selasky pcap_setdirection_dead(pcap_t *p, pcap_direction_t d _U_)
4355b00ab754SHans Petter Selasky {
43566f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4357b00ab754SHans Petter Selasky "The packet direction cannot be set on a pcap_open_dead pcap_t");
4358b00ab754SHans Petter Selasky return (-1);
4359b00ab754SHans Petter Selasky }
4360b00ab754SHans Petter Selasky
4361b00ab754SHans Petter Selasky static int
4362b00ab754SHans Petter Selasky pcap_set_datalink_dead(pcap_t *p, int dlt _U_)
4363b00ab754SHans Petter Selasky {
43646f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4365b00ab754SHans Petter Selasky "The link-layer header type cannot be set on a pcap_open_dead pcap_t");
4366b00ab754SHans Petter Selasky return (-1);
4367b00ab754SHans Petter Selasky }
4368b00ab754SHans Petter Selasky
4369b00ab754SHans Petter Selasky static int
4370b00ab754SHans Petter Selasky pcap_getnonblock_dead(pcap_t *p)
4371b00ab754SHans Petter Selasky {
43726f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4373b00ab754SHans Petter Selasky "A pcap_open_dead pcap_t does not have a non-blocking mode setting");
4374b00ab754SHans Petter Selasky return (-1);
4375b00ab754SHans Petter Selasky }
4376b00ab754SHans Petter Selasky
4377b00ab754SHans Petter Selasky static int
4378b00ab754SHans Petter Selasky pcap_setnonblock_dead(pcap_t *p, int nonblock _U_)
4379b00ab754SHans Petter Selasky {
43806f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4381b00ab754SHans Petter Selasky "A pcap_open_dead pcap_t does not have a non-blocking mode setting");
4382b00ab754SHans Petter Selasky return (-1);
4383b00ab754SHans Petter Selasky }
4384b00ab754SHans Petter Selasky
4385b00ab754SHans Petter Selasky static int
4386b00ab754SHans Petter Selasky pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_)
4387b00ab754SHans Petter Selasky {
43886f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4389b00ab754SHans Petter Selasky "Statistics aren't available from a pcap_open_dead pcap_t");
4390b00ab754SHans Petter Selasky return (-1);
4391b00ab754SHans Petter Selasky }
439204fb2745SSam Leffler
4393ada6f083SXin LI #ifdef _WIN32
43946f9cba8fSJoseph Mingrone static struct pcap_stat *
4395b00ab754SHans Petter Selasky pcap_stats_ex_dead(pcap_t *p, int *pcap_stat_size _U_)
4396feb4ecdbSBruce M Simpson {
43976f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4398b00ab754SHans Petter Selasky "Statistics aren't available from a pcap_open_dead pcap_t");
4399681ed54cSXin LI return (NULL);
4400feb4ecdbSBruce M Simpson }
440104fb2745SSam Leffler
4402b00ab754SHans Petter Selasky static int
44036f9cba8fSJoseph Mingrone pcap_setbuff_dead(pcap_t *p, int dim _U_)
4404ada6f083SXin LI {
44056f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4406b00ab754SHans Petter Selasky "The kernel buffer size cannot be set on a pcap_open_dead pcap_t");
4407b00ab754SHans Petter Selasky return (-1);
4408ada6f083SXin LI }
4409ada6f083SXin LI
4410b00ab754SHans Petter Selasky static int
44116f9cba8fSJoseph Mingrone pcap_setmode_dead(pcap_t *p, int mode _U_)
441204fb2745SSam Leffler {
44136f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4414b00ab754SHans Petter Selasky "impossible to set mode on a pcap_open_dead pcap_t");
4415b00ab754SHans Petter Selasky return (-1);
441604fb2745SSam Leffler }
441704fb2745SSam Leffler
4418b00ab754SHans Petter Selasky static int
44196f9cba8fSJoseph Mingrone pcap_setmintocopy_dead(pcap_t *p, int size _U_)
4420feb4ecdbSBruce M Simpson {
44216f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4422b00ab754SHans Petter Selasky "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t");
4423b00ab754SHans Petter Selasky return (-1);
4424feb4ecdbSBruce M Simpson }
4425b00ab754SHans Petter Selasky
4426b00ab754SHans Petter Selasky static HANDLE
4427b00ab754SHans Petter Selasky pcap_getevent_dead(pcap_t *p)
4428b00ab754SHans Petter Selasky {
44296f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4430b00ab754SHans Petter Selasky "A pcap_open_dead pcap_t has no event handle");
4431b00ab754SHans Petter Selasky return (INVALID_HANDLE_VALUE);
4432b00ab754SHans Petter Selasky }
4433b00ab754SHans Petter Selasky
4434b00ab754SHans Petter Selasky static int
4435b00ab754SHans Petter Selasky pcap_oid_get_request_dead(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_,
4436b00ab754SHans Petter Selasky size_t *lenp _U_)
4437b00ab754SHans Petter Selasky {
44386f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4439b00ab754SHans Petter Selasky "An OID get request cannot be performed on a pcap_open_dead pcap_t");
4440b00ab754SHans Petter Selasky return (PCAP_ERROR);
4441b00ab754SHans Petter Selasky }
4442b00ab754SHans Petter Selasky
4443b00ab754SHans Petter Selasky static int
4444b00ab754SHans Petter Selasky pcap_oid_set_request_dead(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
4445b00ab754SHans Petter Selasky size_t *lenp _U_)
4446b00ab754SHans Petter Selasky {
44476f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4448b00ab754SHans Petter Selasky "An OID set request cannot be performed on a pcap_open_dead pcap_t");
4449b00ab754SHans Petter Selasky return (PCAP_ERROR);
4450b00ab754SHans Petter Selasky }
4451b00ab754SHans Petter Selasky
4452b00ab754SHans Petter Selasky static u_int
44536f9cba8fSJoseph Mingrone pcap_sendqueue_transmit_dead(pcap_t *p, pcap_send_queue *queue _U_,
44546f9cba8fSJoseph Mingrone int sync _U_)
4455b00ab754SHans Petter Selasky {
44566f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4457b00ab754SHans Petter Selasky "Packets cannot be transmitted on a pcap_open_dead pcap_t");
4458b00ab754SHans Petter Selasky return (0);
4459b00ab754SHans Petter Selasky }
4460b00ab754SHans Petter Selasky
4461b00ab754SHans Petter Selasky static int
44626f9cba8fSJoseph Mingrone pcap_setuserbuffer_dead(pcap_t *p, int size _U_)
4463b00ab754SHans Petter Selasky {
44646f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4465b00ab754SHans Petter Selasky "The user buffer cannot be set on a pcap_open_dead pcap_t");
4466b00ab754SHans Petter Selasky return (-1);
4467b00ab754SHans Petter Selasky }
4468b00ab754SHans Petter Selasky
4469b00ab754SHans Petter Selasky static int
44706f9cba8fSJoseph Mingrone pcap_live_dump_dead(pcap_t *p, char *filename _U_, int maxsize _U_,
44716f9cba8fSJoseph Mingrone int maxpacks _U_)
4472b00ab754SHans Petter Selasky {
44736f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4474b00ab754SHans Petter Selasky "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
4475b00ab754SHans Petter Selasky return (-1);
4476b00ab754SHans Petter Selasky }
4477b00ab754SHans Petter Selasky
4478b00ab754SHans Petter Selasky static int
44796f9cba8fSJoseph Mingrone pcap_live_dump_ended_dead(pcap_t *p, int sync _U_)
4480b00ab754SHans Petter Selasky {
44816f9cba8fSJoseph Mingrone snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
4482b00ab754SHans Petter Selasky "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
4483b00ab754SHans Petter Selasky return (-1);
4484b00ab754SHans Petter Selasky }
4485b00ab754SHans Petter Selasky
4486b00ab754SHans Petter Selasky static PAirpcapHandle
44876f9cba8fSJoseph Mingrone pcap_get_airpcap_handle_dead(pcap_t *p _U_)
4488b00ab754SHans Petter Selasky {
4489b00ab754SHans Petter Selasky return (NULL);
4490b00ab754SHans Petter Selasky }
4491b00ab754SHans Petter Selasky #endif /* _WIN32 */
4492b00ab754SHans Petter Selasky
4493b00ab754SHans Petter Selasky static void
4494b00ab754SHans Petter Selasky pcap_cleanup_dead(pcap_t *p _U_)
4495b00ab754SHans Petter Selasky {
4496b00ab754SHans Petter Selasky /* Nothing to do. */
4497b00ab754SHans Petter Selasky }
4498b00ab754SHans Petter Selasky
4499b00ab754SHans Petter Selasky pcap_t *
4500b00ab754SHans Petter Selasky pcap_open_dead_with_tstamp_precision(int linktype, int snaplen, u_int precision)
4501b00ab754SHans Petter Selasky {
4502b00ab754SHans Petter Selasky pcap_t *p;
4503b00ab754SHans Petter Selasky
4504b00ab754SHans Petter Selasky switch (precision) {
4505b00ab754SHans Petter Selasky
4506b00ab754SHans Petter Selasky case PCAP_TSTAMP_PRECISION_MICRO:
4507b00ab754SHans Petter Selasky case PCAP_TSTAMP_PRECISION_NANO:
4508b00ab754SHans Petter Selasky break;
4509b00ab754SHans Petter Selasky
4510b00ab754SHans Petter Selasky default:
4511b00ab754SHans Petter Selasky /*
4512b00ab754SHans Petter Selasky * This doesn't really matter, but we don't have any way
4513b00ab754SHans Petter Selasky * to report particular errors, so the only failure we
4514b00ab754SHans Petter Selasky * should have is a memory allocation failure. Just
4515b00ab754SHans Petter Selasky * pick microsecond precision.
4516b00ab754SHans Petter Selasky */
4517b00ab754SHans Petter Selasky precision = PCAP_TSTAMP_PRECISION_MICRO;
4518b00ab754SHans Petter Selasky break;
4519b00ab754SHans Petter Selasky }
4520b00ab754SHans Petter Selasky p = malloc(sizeof(*p));
4521b00ab754SHans Petter Selasky if (p == NULL)
4522b00ab754SHans Petter Selasky return NULL;
4523b00ab754SHans Petter Selasky memset (p, 0, sizeof(*p));
4524b00ab754SHans Petter Selasky p->snapshot = snaplen;
4525b00ab754SHans Petter Selasky p->linktype = linktype;
4526b00ab754SHans Petter Selasky p->opt.tstamp_precision = precision;
4527b00ab754SHans Petter Selasky p->can_set_rfmon_op = pcap_can_set_rfmon_dead;
4528b00ab754SHans Petter Selasky p->read_op = pcap_read_dead;
4529b00ab754SHans Petter Selasky p->inject_op = pcap_inject_dead;
4530b00ab754SHans Petter Selasky p->setfilter_op = pcap_setfilter_dead;
4531b00ab754SHans Petter Selasky p->setdirection_op = pcap_setdirection_dead;
4532b00ab754SHans Petter Selasky p->set_datalink_op = pcap_set_datalink_dead;
4533b00ab754SHans Petter Selasky p->getnonblock_op = pcap_getnonblock_dead;
4534b00ab754SHans Petter Selasky p->setnonblock_op = pcap_setnonblock_dead;
4535b00ab754SHans Petter Selasky p->stats_op = pcap_stats_dead;
4536b00ab754SHans Petter Selasky #ifdef _WIN32
4537b00ab754SHans Petter Selasky p->stats_ex_op = pcap_stats_ex_dead;
4538b00ab754SHans Petter Selasky p->setbuff_op = pcap_setbuff_dead;
4539b00ab754SHans Petter Selasky p->setmode_op = pcap_setmode_dead;
4540b00ab754SHans Petter Selasky p->setmintocopy_op = pcap_setmintocopy_dead;
4541b00ab754SHans Petter Selasky p->getevent_op = pcap_getevent_dead;
4542b00ab754SHans Petter Selasky p->oid_get_request_op = pcap_oid_get_request_dead;
4543b00ab754SHans Petter Selasky p->oid_set_request_op = pcap_oid_set_request_dead;
4544b00ab754SHans Petter Selasky p->sendqueue_transmit_op = pcap_sendqueue_transmit_dead;
4545b00ab754SHans Petter Selasky p->setuserbuffer_op = pcap_setuserbuffer_dead;
4546b00ab754SHans Petter Selasky p->live_dump_op = pcap_live_dump_dead;
4547b00ab754SHans Petter Selasky p->live_dump_ended_op = pcap_live_dump_ended_dead;
4548b00ab754SHans Petter Selasky p->get_airpcap_handle_op = pcap_get_airpcap_handle_dead;
4549feb4ecdbSBruce M Simpson #endif
45506f9cba8fSJoseph Mingrone p->breakloop_op = pcap_breakloop_dead;
4551b00ab754SHans Petter Selasky p->cleanup_op = pcap_cleanup_dead;
4552b00ab754SHans Petter Selasky
4553b00ab754SHans Petter Selasky /*
4554b00ab754SHans Petter Selasky * A "dead" pcap_t never requires special BPF code generation.
4555b00ab754SHans Petter Selasky */
4556b00ab754SHans Petter Selasky p->bpf_codegen_flags = 0;
4557b00ab754SHans Petter Selasky
4558b00ab754SHans Petter Selasky p->activated = 1;
4559b00ab754SHans Petter Selasky return (p);
4560b00ab754SHans Petter Selasky }
4561b00ab754SHans Petter Selasky
4562b00ab754SHans Petter Selasky pcap_t *
4563b00ab754SHans Petter Selasky pcap_open_dead(int linktype, int snaplen)
4564b00ab754SHans Petter Selasky {
4565b00ab754SHans Petter Selasky return (pcap_open_dead_with_tstamp_precision(linktype, snaplen,
4566b00ab754SHans Petter Selasky PCAP_TSTAMP_PRECISION_MICRO));
4567b00ab754SHans Petter Selasky }
4568ada6f083SXin LI
4569ada6f083SXin LI #ifdef YYDEBUG
4570ada6f083SXin LI /*
4571ada6f083SXin LI * Set the internal "debug printout" flag for the filter expression parser.
4572ada6f083SXin LI * The code to print that stuff is present only if YYDEBUG is defined, so
4573ada6f083SXin LI * the flag, and the routine to set it, are defined only if YYDEBUG is
4574ada6f083SXin LI * defined.
4575ada6f083SXin LI *
4576ada6f083SXin LI * This is intended for libpcap developers, not for general use.
4577ada6f083SXin LI * If you want to set these in a program, you'll have to declare this
4578ada6f083SXin LI * routine yourself, with the appropriate DLL import attribute on Windows;
4579ada6f083SXin LI * it's not declared in any header file, and won't be declared in any
4580ada6f083SXin LI * header file provided by libpcap.
4581ada6f083SXin LI */
4582ada6f083SXin LI PCAP_API void pcap_set_parser_debug(int value);
4583ada6f083SXin LI
4584ada6f083SXin LI PCAP_API_DEF void
4585ada6f083SXin LI pcap_set_parser_debug(int value)
4586ada6f083SXin LI {
4587ada6f083SXin LI pcap_debug = value;
4588ada6f083SXin LI }
4589ada6f083SXin LI #endif
4590