11077d0bdSPeter Avalos /*
21077d0bdSPeter Avalos * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
31077d0bdSPeter Avalos * The Regents of the University of California. All rights reserved.
41077d0bdSPeter Avalos *
51077d0bdSPeter Avalos * Redistribution and use in source and binary forms, with or without
61077d0bdSPeter Avalos * modification, are permitted provided that the following conditions
71077d0bdSPeter Avalos * are met:
81077d0bdSPeter Avalos * 1. Redistributions of source code must retain the above copyright
91077d0bdSPeter Avalos * notice, this list of conditions and the following disclaimer.
101077d0bdSPeter Avalos * 2. Redistributions in binary form must reproduce the above copyright
111077d0bdSPeter Avalos * notice, this list of conditions and the following disclaimer in the
121077d0bdSPeter Avalos * documentation and/or other materials provided with the distribution.
131077d0bdSPeter Avalos * 3. All advertising materials mentioning features or use of this software
141077d0bdSPeter Avalos * must display the following acknowledgement:
151077d0bdSPeter Avalos * This product includes software developed by the Computer Systems
161077d0bdSPeter Avalos * Engineering Group at Lawrence Berkeley Laboratory.
171077d0bdSPeter Avalos * 4. Neither the name of the University nor of the Laboratory may be used
181077d0bdSPeter Avalos * to endorse or promote products derived from this software without
191077d0bdSPeter Avalos * specific prior written permission.
201077d0bdSPeter Avalos *
211077d0bdSPeter Avalos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221077d0bdSPeter Avalos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231077d0bdSPeter Avalos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241077d0bdSPeter Avalos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251077d0bdSPeter Avalos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261077d0bdSPeter Avalos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271077d0bdSPeter Avalos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281077d0bdSPeter Avalos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291077d0bdSPeter Avalos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301077d0bdSPeter Avalos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311077d0bdSPeter Avalos * SUCH DAMAGE.
321077d0bdSPeter Avalos */
331077d0bdSPeter Avalos
341077d0bdSPeter Avalos #ifdef HAVE_CONFIG_H
353a289941SAaron LI #include <config.h>
361077d0bdSPeter Avalos #endif
371077d0bdSPeter Avalos
383a289941SAaron LI #include <pcap-types.h>
393a289941SAaron LI #ifndef _WIN32
403a289941SAaron LI #include <sys/param.h>
413a289941SAaron LI #ifndef MSDOS
423a289941SAaron LI #include <sys/file.h>
43a85e14b0SPeter Avalos #endif
443a289941SAaron LI #include <sys/ioctl.h>
453a289941SAaron LI #include <sys/socket.h>
463a289941SAaron LI #ifdef HAVE_SYS_SOCKIO_H
473a289941SAaron LI #include <sys/sockio.h>
48a85e14b0SPeter Avalos #endif
493a289941SAaron LI
503a289941SAaron LI struct mbuf; /* Squelch compiler warnings on some platforms for */
513a289941SAaron LI struct rtentry; /* declarations in <net/if.h> */
523a289941SAaron LI #include <net/if.h>
533a289941SAaron LI #include <netinet/in.h>
5497a9217aSAntonio Huete Jimenez #endif /* _WIN32 */
551077d0bdSPeter Avalos
561077d0bdSPeter Avalos #include <stdio.h>
571077d0bdSPeter Avalos #include <stdlib.h>
581077d0bdSPeter Avalos #include <string.h>
59a85e14b0SPeter Avalos #if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__MINGW32__)
601077d0bdSPeter Avalos #include <unistd.h>
611077d0bdSPeter Avalos #endif
621077d0bdSPeter Avalos #include <fcntl.h>
631077d0bdSPeter Avalos #include <errno.h>
643a289941SAaron LI #include <limits.h>
65*ea16f64eSAntonio Huete Jimenez
66*ea16f64eSAntonio Huete Jimenez #include "diag-control.h"
671077d0bdSPeter Avalos
681077d0bdSPeter Avalos #ifdef HAVE_OS_PROTO_H
691077d0bdSPeter Avalos #include "os-proto.h"
701077d0bdSPeter Avalos #endif
711077d0bdSPeter Avalos
721077d0bdSPeter Avalos #ifdef MSDOS
731077d0bdSPeter Avalos #include "pcap-dos.h"
741077d0bdSPeter Avalos #endif
751077d0bdSPeter Avalos
761077d0bdSPeter Avalos #include "pcap-int.h"
771077d0bdSPeter Avalos
783a289941SAaron LI #include "optimize.h"
793a289941SAaron LI
801077d0bdSPeter Avalos #ifdef HAVE_DAG_API
810e381983SMatthew Dillon #include "pcap-dag.h"
820e381983SMatthew Dillon #endif /* HAVE_DAG_API */
830e381983SMatthew Dillon
840e381983SMatthew Dillon #ifdef HAVE_SEPTEL_API
850e381983SMatthew Dillon #include "pcap-septel.h"
860e381983SMatthew Dillon #endif /* HAVE_SEPTEL_API */
870e381983SMatthew Dillon
880e381983SMatthew Dillon #ifdef HAVE_SNF_API
890e381983SMatthew Dillon #include "pcap-snf.h"
900e381983SMatthew Dillon #endif /* HAVE_SNF_API */
910e381983SMatthew Dillon
9297a9217aSAntonio Huete Jimenez #ifdef HAVE_TC_API
9397a9217aSAntonio Huete Jimenez #include "pcap-tc.h"
9497a9217aSAntonio Huete Jimenez #endif /* HAVE_TC_API */
9597a9217aSAntonio Huete Jimenez
96*ea16f64eSAntonio Huete Jimenez #ifdef PCAP_SUPPORT_LINUX_USBMON
970e381983SMatthew Dillon #include "pcap-usb-linux.h"
980e381983SMatthew Dillon #endif
990e381983SMatthew Dillon
1000e381983SMatthew Dillon #ifdef PCAP_SUPPORT_BT
1010e381983SMatthew Dillon #include "pcap-bt-linux.h"
1020e381983SMatthew Dillon #endif
1030e381983SMatthew Dillon
10497a9217aSAntonio Huete Jimenez #ifdef PCAP_SUPPORT_BT_MONITOR
10597a9217aSAntonio Huete Jimenez #include "pcap-bt-monitor-linux.h"
1060e381983SMatthew Dillon #endif
1070e381983SMatthew Dillon
1080e381983SMatthew Dillon #ifdef PCAP_SUPPORT_NETFILTER
1090e381983SMatthew Dillon #include "pcap-netfilter-linux.h"
1101077d0bdSPeter Avalos #endif
1111077d0bdSPeter Avalos
1123a289941SAaron LI #ifdef PCAP_SUPPORT_NETMAP
1133a289941SAaron LI #include "pcap-netmap.h"
1143a289941SAaron LI #endif
1153a289941SAaron LI
11697a9217aSAntonio Huete Jimenez #ifdef PCAP_SUPPORT_DBUS
11797a9217aSAntonio Huete Jimenez #include "pcap-dbus.h"
11897a9217aSAntonio Huete Jimenez #endif
11997a9217aSAntonio Huete Jimenez
1203a289941SAaron LI #ifdef PCAP_SUPPORT_RDMASNIFF
1213a289941SAaron LI #include "pcap-rdmasniff.h"
1223a289941SAaron LI #endif
1233a289941SAaron LI
124*ea16f64eSAntonio Huete Jimenez #ifdef PCAP_SUPPORT_DPDK
125*ea16f64eSAntonio Huete Jimenez #include "pcap-dpdk.h"
126*ea16f64eSAntonio Huete Jimenez #endif
127*ea16f64eSAntonio Huete Jimenez
128*ea16f64eSAntonio Huete Jimenez #ifdef HAVE_AIRPCAP_API
129*ea16f64eSAntonio Huete Jimenez #include "pcap-airpcap.h"
130*ea16f64eSAntonio Huete Jimenez #endif
131*ea16f64eSAntonio Huete Jimenez
1323a289941SAaron LI #ifdef _WIN32
1333a289941SAaron LI /*
1343a289941SAaron LI * DllMain(), required when built as a Windows DLL.
135*ea16f64eSAntonio Huete Jimenez *
136*ea16f64eSAntonio Huete Jimenez * To quote the WSAStartup() documentation:
137*ea16f64eSAntonio Huete Jimenez *
138*ea16f64eSAntonio Huete Jimenez * The WSAStartup function typically leads to protocol-specific helper
139*ea16f64eSAntonio Huete Jimenez * DLLs being loaded. As a result, the WSAStartup function should not
140*ea16f64eSAntonio Huete Jimenez * be called from the DllMain function in a application DLL. This can
141*ea16f64eSAntonio Huete Jimenez * potentially cause deadlocks.
142*ea16f64eSAntonio Huete Jimenez *
143*ea16f64eSAntonio Huete Jimenez * and the WSACleanup() documentation:
144*ea16f64eSAntonio Huete Jimenez *
145*ea16f64eSAntonio Huete Jimenez * The WSACleanup function typically leads to protocol-specific helper
146*ea16f64eSAntonio Huete Jimenez * DLLs being unloaded. As a result, the WSACleanup function should not
147*ea16f64eSAntonio Huete Jimenez * be called from the DllMain function in a application DLL. This can
148*ea16f64eSAntonio Huete Jimenez * potentially cause deadlocks.
149*ea16f64eSAntonio Huete Jimenez *
150*ea16f64eSAntonio Huete Jimenez * So we don't initialize Winsock here. pcap_init() should be called
151*ea16f64eSAntonio Huete Jimenez * to initialize pcap on both UN*X and Windows; it will initialize
152*ea16f64eSAntonio Huete Jimenez * Winsock on Windows. (It will also be initialized as needed if
153*ea16f64eSAntonio Huete Jimenez * pcap_init() hasn't been called.)
1543a289941SAaron LI */
DllMain(HANDLE hinstDLL _U_,DWORD dwReason _U_,LPVOID lpvReserved _U_)1553a289941SAaron LI BOOL WINAPI DllMain(
156*ea16f64eSAntonio Huete Jimenez HANDLE hinstDLL _U_,
157*ea16f64eSAntonio Huete Jimenez DWORD dwReason _U_,
158*ea16f64eSAntonio Huete Jimenez LPVOID lpvReserved _U_
1593a289941SAaron LI )
160de0d3203SPeter Avalos {
1613a289941SAaron LI return (TRUE);
1623a289941SAaron LI }
1633a289941SAaron LI
1643a289941SAaron LI /*
165*ea16f64eSAntonio Huete Jimenez * Start Winsock.
166*ea16f64eSAntonio Huete Jimenez * Internal routine.
167*ea16f64eSAntonio Huete Jimenez */
168*ea16f64eSAntonio Huete Jimenez static int
internal_wsockinit(char * errbuf)169*ea16f64eSAntonio Huete Jimenez internal_wsockinit(char *errbuf)
170*ea16f64eSAntonio Huete Jimenez {
171*ea16f64eSAntonio Huete Jimenez WORD wVersionRequested;
172*ea16f64eSAntonio Huete Jimenez WSADATA wsaData;
173*ea16f64eSAntonio Huete Jimenez static int err = -1;
174*ea16f64eSAntonio Huete Jimenez static int done = 0;
175*ea16f64eSAntonio Huete Jimenez int status;
176*ea16f64eSAntonio Huete Jimenez
177*ea16f64eSAntonio Huete Jimenez if (done)
178*ea16f64eSAntonio Huete Jimenez return (err);
179*ea16f64eSAntonio Huete Jimenez
180*ea16f64eSAntonio Huete Jimenez /*
181*ea16f64eSAntonio Huete Jimenez * Versions of Windows that don't support Winsock 2.2 are
182*ea16f64eSAntonio Huete Jimenez * too old for us.
183*ea16f64eSAntonio Huete Jimenez */
184*ea16f64eSAntonio Huete Jimenez wVersionRequested = MAKEWORD(2, 2);
185*ea16f64eSAntonio Huete Jimenez status = WSAStartup(wVersionRequested, &wsaData);
186*ea16f64eSAntonio Huete Jimenez done = 1;
187*ea16f64eSAntonio Huete Jimenez if (status != 0) {
188*ea16f64eSAntonio Huete Jimenez if (errbuf != NULL) {
189*ea16f64eSAntonio Huete Jimenez pcap_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
190*ea16f64eSAntonio Huete Jimenez status, "WSAStartup() failed");
191*ea16f64eSAntonio Huete Jimenez }
192*ea16f64eSAntonio Huete Jimenez return (err);
193*ea16f64eSAntonio Huete Jimenez }
194*ea16f64eSAntonio Huete Jimenez atexit ((void(*)(void))WSACleanup);
195*ea16f64eSAntonio Huete Jimenez err = 0;
196*ea16f64eSAntonio Huete Jimenez return (err);
197*ea16f64eSAntonio Huete Jimenez }
198*ea16f64eSAntonio Huete Jimenez
199*ea16f64eSAntonio Huete Jimenez /*
2003a289941SAaron LI * Exported in case some applications using WinPcap/Npcap called it,
2013a289941SAaron LI * even though it wasn't exported.
2023a289941SAaron LI */
2033a289941SAaron LI int
wsockinit(void)2043a289941SAaron LI wsockinit(void)
2053a289941SAaron LI {
206*ea16f64eSAntonio Huete Jimenez return (internal_wsockinit(NULL));
2073a289941SAaron LI }
2083a289941SAaron LI
2093a289941SAaron LI /*
2103a289941SAaron LI * This is the exported function; new programs should call this.
211*ea16f64eSAntonio Huete Jimenez * *Newer* programs should call pcap_init().
2123a289941SAaron LI */
2133a289941SAaron LI int
pcap_wsockinit(void)2143a289941SAaron LI pcap_wsockinit(void)
2153a289941SAaron LI {
216*ea16f64eSAntonio Huete Jimenez return (internal_wsockinit(NULL));
2173a289941SAaron LI }
2183a289941SAaron LI #endif /* _WIN32 */
2193a289941SAaron LI
2203a289941SAaron LI /*
221*ea16f64eSAntonio Huete Jimenez * Do whatever initialization is needed for libpcap.
222*ea16f64eSAntonio Huete Jimenez *
223*ea16f64eSAntonio Huete Jimenez * The argument specifies whether we use the local code page or UTF-8
224*ea16f64eSAntonio Huete Jimenez * for strings; on UN*X, we just assume UTF-8 in places where the encoding
225*ea16f64eSAntonio Huete Jimenez * would matter, whereas, on Windows, we use the local code page for
226*ea16f64eSAntonio Huete Jimenez * PCAP_CHAR_ENC_LOCAL and UTF-8 for PCAP_CHAR_ENC_UTF_8.
227*ea16f64eSAntonio Huete Jimenez *
228*ea16f64eSAntonio Huete Jimenez * On Windows, we also disable the hack in pcap_create() to deal with
229*ea16f64eSAntonio Huete Jimenez * being handed UTF-16 strings, because if the user calls this they're
230*ea16f64eSAntonio Huete Jimenez * explicitly declaring that they will either be passing local code
231*ea16f64eSAntonio Huete Jimenez * page strings or UTF-8 strings, so we don't need to allow UTF-16LE
232*ea16f64eSAntonio Huete Jimenez * strings to be passed. For good measure, on Windows *and* UN*X,
233*ea16f64eSAntonio Huete Jimenez * we disable pcap_lookupdev(), to prevent anybody from even
234*ea16f64eSAntonio Huete Jimenez * *trying* to pass the result of pcap_lookupdev() - which might be
235*ea16f64eSAntonio Huete Jimenez * UTF-16LE on Windows, for ugly compatibility reasons - to pcap_create()
236*ea16f64eSAntonio Huete Jimenez * or pcap_open_live() or pcap_open().
237*ea16f64eSAntonio Huete Jimenez *
238*ea16f64eSAntonio Huete Jimenez * Returns 0 on success, -1 on error.
239*ea16f64eSAntonio Huete Jimenez */
240*ea16f64eSAntonio Huete Jimenez int pcap_new_api; /* pcap_lookupdev() always fails */
241*ea16f64eSAntonio Huete Jimenez int pcap_utf_8_mode; /* Strings should be in UTF-8. */
242*ea16f64eSAntonio Huete Jimenez
243*ea16f64eSAntonio Huete Jimenez int
pcap_init(unsigned int opts,char * errbuf)244*ea16f64eSAntonio Huete Jimenez pcap_init(unsigned int opts, char *errbuf)
245*ea16f64eSAntonio Huete Jimenez {
246*ea16f64eSAntonio Huete Jimenez static int initialized;
247*ea16f64eSAntonio Huete Jimenez
248*ea16f64eSAntonio Huete Jimenez /*
249*ea16f64eSAntonio Huete Jimenez * Don't allow multiple calls that set different modes; that
250*ea16f64eSAntonio Huete Jimenez * may mean a library is initializing pcap in one mode and
251*ea16f64eSAntonio Huete Jimenez * a program using that library, or another library used by
252*ea16f64eSAntonio Huete Jimenez * that program, is initializing it in another mode.
253*ea16f64eSAntonio Huete Jimenez */
254*ea16f64eSAntonio Huete Jimenez switch (opts) {
255*ea16f64eSAntonio Huete Jimenez
256*ea16f64eSAntonio Huete Jimenez case PCAP_CHAR_ENC_LOCAL:
257*ea16f64eSAntonio Huete Jimenez /* Leave "UTF-8 mode" off. */
258*ea16f64eSAntonio Huete Jimenez if (initialized) {
259*ea16f64eSAntonio Huete Jimenez if (pcap_utf_8_mode) {
260*ea16f64eSAntonio Huete Jimenez snprintf(errbuf, PCAP_ERRBUF_SIZE,
261*ea16f64eSAntonio Huete Jimenez "Multiple pcap_init calls with different character encodings");
262*ea16f64eSAntonio Huete Jimenez return (-1);
263*ea16f64eSAntonio Huete Jimenez }
264*ea16f64eSAntonio Huete Jimenez }
265*ea16f64eSAntonio Huete Jimenez break;
266*ea16f64eSAntonio Huete Jimenez
267*ea16f64eSAntonio Huete Jimenez case PCAP_CHAR_ENC_UTF_8:
268*ea16f64eSAntonio Huete Jimenez /* Turn on "UTF-8 mode". */
269*ea16f64eSAntonio Huete Jimenez if (initialized) {
270*ea16f64eSAntonio Huete Jimenez if (!pcap_utf_8_mode) {
271*ea16f64eSAntonio Huete Jimenez snprintf(errbuf, PCAP_ERRBUF_SIZE,
272*ea16f64eSAntonio Huete Jimenez "Multiple pcap_init calls with different character encodings");
273*ea16f64eSAntonio Huete Jimenez return (-1);
274*ea16f64eSAntonio Huete Jimenez }
275*ea16f64eSAntonio Huete Jimenez }
276*ea16f64eSAntonio Huete Jimenez pcap_utf_8_mode = 1;
277*ea16f64eSAntonio Huete Jimenez break;
278*ea16f64eSAntonio Huete Jimenez
279*ea16f64eSAntonio Huete Jimenez default:
280*ea16f64eSAntonio Huete Jimenez snprintf(errbuf, PCAP_ERRBUF_SIZE, "Unknown options specified");
281*ea16f64eSAntonio Huete Jimenez return (-1);
282*ea16f64eSAntonio Huete Jimenez }
283*ea16f64eSAntonio Huete Jimenez
284*ea16f64eSAntonio Huete Jimenez /*
285*ea16f64eSAntonio Huete Jimenez * Turn the appropriate mode on for error messages; those routines
286*ea16f64eSAntonio Huete Jimenez * are also used in rpcapd, which has no access to pcap's internal
287*ea16f64eSAntonio Huete Jimenez * UTF-8 mode flag, so we have to call a routine to set its
288*ea16f64eSAntonio Huete Jimenez * UTF-8 mode flag.
289*ea16f64eSAntonio Huete Jimenez */
290*ea16f64eSAntonio Huete Jimenez pcap_fmt_set_encoding(opts);
291*ea16f64eSAntonio Huete Jimenez
292*ea16f64eSAntonio Huete Jimenez if (initialized) {
293*ea16f64eSAntonio Huete Jimenez /*
294*ea16f64eSAntonio Huete Jimenez * Nothing more to do; for example, on Windows, we've
295*ea16f64eSAntonio Huete Jimenez * already initialized Winsock.
296*ea16f64eSAntonio Huete Jimenez */
297*ea16f64eSAntonio Huete Jimenez return (0);
298*ea16f64eSAntonio Huete Jimenez }
299*ea16f64eSAntonio Huete Jimenez
300*ea16f64eSAntonio Huete Jimenez #ifdef _WIN32
301*ea16f64eSAntonio Huete Jimenez /*
302*ea16f64eSAntonio Huete Jimenez * Now set up Winsock.
303*ea16f64eSAntonio Huete Jimenez */
304*ea16f64eSAntonio Huete Jimenez if (internal_wsockinit(errbuf) == -1) {
305*ea16f64eSAntonio Huete Jimenez /* Failed. */
306*ea16f64eSAntonio Huete Jimenez return (-1);
307*ea16f64eSAntonio Huete Jimenez }
308*ea16f64eSAntonio Huete Jimenez #endif
309*ea16f64eSAntonio Huete Jimenez
310*ea16f64eSAntonio Huete Jimenez /*
311*ea16f64eSAntonio Huete Jimenez * We're done.
312*ea16f64eSAntonio Huete Jimenez */
313*ea16f64eSAntonio Huete Jimenez initialized = 1;
314*ea16f64eSAntonio Huete Jimenez pcap_new_api = 1;
315*ea16f64eSAntonio Huete Jimenez return (0);
316*ea16f64eSAntonio Huete Jimenez }
317*ea16f64eSAntonio Huete Jimenez
318*ea16f64eSAntonio Huete Jimenez /*
3193a289941SAaron LI * String containing the library version.
3203a289941SAaron LI * Not explicitly exported via a header file - the right API to use
3213a289941SAaron LI * is pcap_lib_version() - but some programs included it, so we
3223a289941SAaron LI * provide it.
3233a289941SAaron LI *
3243a289941SAaron LI * We declare it here, right before defining it, to squelch any
3253a289941SAaron LI * warnings we might get from compilers about the lack of a
3263a289941SAaron LI * declaration.
3273a289941SAaron LI */
3283a289941SAaron LI PCAP_API char pcap_version[];
3293a289941SAaron LI PCAP_API_DEF char pcap_version[] = PACKAGE_VERSION;
3303a289941SAaron LI
3313a289941SAaron LI static void
pcap_set_not_initialized_message(pcap_t * pcap)3323a289941SAaron LI pcap_set_not_initialized_message(pcap_t *pcap)
3333a289941SAaron LI {
3343a289941SAaron LI if (pcap->activated) {
3353a289941SAaron LI /* A module probably forgot to set the function pointer */
336*ea16f64eSAntonio Huete Jimenez (void)snprintf(pcap->errbuf, sizeof(pcap->errbuf),
3373a289941SAaron LI "This operation isn't properly handled by that device");
3383a289941SAaron LI return;
3393a289941SAaron LI }
34097a9217aSAntonio Huete Jimenez /* in case the caller doesn't check for PCAP_ERROR_NOT_ACTIVATED */
341*ea16f64eSAntonio Huete Jimenez (void)snprintf(pcap->errbuf, sizeof(pcap->errbuf),
34297a9217aSAntonio Huete Jimenez "This handle hasn't been activated yet");
3433a289941SAaron LI }
3443a289941SAaron LI
3453a289941SAaron LI static int
pcap_read_not_initialized(pcap_t * pcap,int cnt _U_,pcap_handler callback _U_,u_char * user _U_)3463a289941SAaron LI pcap_read_not_initialized(pcap_t *pcap, int cnt _U_, pcap_handler callback _U_,
3473a289941SAaron LI u_char *user _U_)
3483a289941SAaron LI {
3493a289941SAaron LI pcap_set_not_initialized_message(pcap);
3503a289941SAaron LI /* this means 'not initialized' */
3513a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
3523a289941SAaron LI }
3533a289941SAaron LI
3543a289941SAaron LI static int
pcap_inject_not_initialized(pcap_t * pcap,const void * buf _U_,int size _U_)355*ea16f64eSAntonio Huete Jimenez pcap_inject_not_initialized(pcap_t *pcap, const void * buf _U_, int size _U_)
3563a289941SAaron LI {
3573a289941SAaron LI pcap_set_not_initialized_message(pcap);
3583a289941SAaron LI /* this means 'not initialized' */
3593a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
3603a289941SAaron LI }
3613a289941SAaron LI
3623a289941SAaron LI static int
pcap_setfilter_not_initialized(pcap_t * pcap,struct bpf_program * fp _U_)3633a289941SAaron LI pcap_setfilter_not_initialized(pcap_t *pcap, struct bpf_program *fp _U_)
3643a289941SAaron LI {
3653a289941SAaron LI pcap_set_not_initialized_message(pcap);
3663a289941SAaron LI /* this means 'not initialized' */
3673a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
3683a289941SAaron LI }
3693a289941SAaron LI
3703a289941SAaron LI static int
pcap_setdirection_not_initialized(pcap_t * pcap,pcap_direction_t d _U_)3713a289941SAaron LI pcap_setdirection_not_initialized(pcap_t *pcap, pcap_direction_t d _U_)
3723a289941SAaron LI {
3733a289941SAaron LI pcap_set_not_initialized_message(pcap);
3743a289941SAaron LI /* this means 'not initialized' */
3753a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
3763a289941SAaron LI }
3773a289941SAaron LI
3783a289941SAaron LI static int
pcap_set_datalink_not_initialized(pcap_t * pcap,int dlt _U_)3793a289941SAaron LI pcap_set_datalink_not_initialized(pcap_t *pcap, int dlt _U_)
3803a289941SAaron LI {
3813a289941SAaron LI pcap_set_not_initialized_message(pcap);
3823a289941SAaron LI /* this means 'not initialized' */
3833a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
3843a289941SAaron LI }
3853a289941SAaron LI
3863a289941SAaron LI static int
pcap_getnonblock_not_initialized(pcap_t * pcap)3873a289941SAaron LI pcap_getnonblock_not_initialized(pcap_t *pcap)
3883a289941SAaron LI {
3893a289941SAaron LI pcap_set_not_initialized_message(pcap);
3903a289941SAaron LI /* this means 'not initialized' */
3913a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
3923a289941SAaron LI }
3933a289941SAaron LI
3943a289941SAaron LI static int
pcap_stats_not_initialized(pcap_t * pcap,struct pcap_stat * ps _U_)3953a289941SAaron LI pcap_stats_not_initialized(pcap_t *pcap, struct pcap_stat *ps _U_)
3963a289941SAaron LI {
3973a289941SAaron LI pcap_set_not_initialized_message(pcap);
398de0d3203SPeter Avalos /* this means 'not initialized' */
399a85e14b0SPeter Avalos return (PCAP_ERROR_NOT_ACTIVATED);
400de0d3203SPeter Avalos }
401de0d3203SPeter Avalos
40297a9217aSAntonio Huete Jimenez #ifdef _WIN32
403*ea16f64eSAntonio Huete Jimenez static struct pcap_stat *
pcap_stats_ex_not_initialized(pcap_t * pcap,int * pcap_stat_size _U_)4043a289941SAaron LI pcap_stats_ex_not_initialized(pcap_t *pcap, int *pcap_stat_size _U_)
40597a9217aSAntonio Huete Jimenez {
4063a289941SAaron LI pcap_set_not_initialized_message(pcap);
40797a9217aSAntonio Huete Jimenez return (NULL);
40897a9217aSAntonio Huete Jimenez }
40997a9217aSAntonio Huete Jimenez
4103a289941SAaron LI static int
pcap_setbuff_not_initialized(pcap_t * pcap,int dim _U_)4113a289941SAaron LI pcap_setbuff_not_initialized(pcap_t *pcap, int dim _U_)
4123a289941SAaron LI {
4133a289941SAaron LI pcap_set_not_initialized_message(pcap);
4143a289941SAaron LI /* this means 'not initialized' */
4153a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
4163a289941SAaron LI }
4173a289941SAaron LI
4183a289941SAaron LI static int
pcap_setmode_not_initialized(pcap_t * pcap,int mode _U_)4193a289941SAaron LI pcap_setmode_not_initialized(pcap_t *pcap, int mode _U_)
4203a289941SAaron LI {
4213a289941SAaron LI pcap_set_not_initialized_message(pcap);
4223a289941SAaron LI /* this means 'not initialized' */
4233a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
4243a289941SAaron LI }
4253a289941SAaron LI
4263a289941SAaron LI static int
pcap_setmintocopy_not_initialized(pcap_t * pcap,int size _U_)4273a289941SAaron LI pcap_setmintocopy_not_initialized(pcap_t *pcap, int size _U_)
4283a289941SAaron LI {
4293a289941SAaron LI pcap_set_not_initialized_message(pcap);
4303a289941SAaron LI /* this means 'not initialized' */
4313a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
4323a289941SAaron LI }
4333a289941SAaron LI
43497a9217aSAntonio Huete Jimenez static HANDLE
pcap_getevent_not_initialized(pcap_t * pcap)43597a9217aSAntonio Huete Jimenez pcap_getevent_not_initialized(pcap_t *pcap)
43697a9217aSAntonio Huete Jimenez {
4373a289941SAaron LI pcap_set_not_initialized_message(pcap);
43897a9217aSAntonio Huete Jimenez return (INVALID_HANDLE_VALUE);
43997a9217aSAntonio Huete Jimenez }
44097a9217aSAntonio Huete Jimenez
4413a289941SAaron LI static int
pcap_oid_get_request_not_initialized(pcap_t * pcap,bpf_u_int32 oid _U_,void * data _U_,size_t * lenp _U_)4423a289941SAaron LI pcap_oid_get_request_not_initialized(pcap_t *pcap, bpf_u_int32 oid _U_,
4433a289941SAaron LI void *data _U_, size_t *lenp _U_)
4443a289941SAaron LI {
4453a289941SAaron LI pcap_set_not_initialized_message(pcap);
4463a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
4473a289941SAaron LI }
4483a289941SAaron LI
4493a289941SAaron LI static int
pcap_oid_set_request_not_initialized(pcap_t * pcap,bpf_u_int32 oid _U_,const void * data _U_,size_t * lenp _U_)4503a289941SAaron LI pcap_oid_set_request_not_initialized(pcap_t *pcap, bpf_u_int32 oid _U_,
4513a289941SAaron LI const void *data _U_, size_t *lenp _U_)
4523a289941SAaron LI {
4533a289941SAaron LI pcap_set_not_initialized_message(pcap);
4543a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
4553a289941SAaron LI }
4563a289941SAaron LI
45797a9217aSAntonio Huete Jimenez static u_int
pcap_sendqueue_transmit_not_initialized(pcap_t * pcap,pcap_send_queue * queue _U_,int sync _U_)458*ea16f64eSAntonio Huete Jimenez pcap_sendqueue_transmit_not_initialized(pcap_t *pcap, pcap_send_queue* queue _U_,
459*ea16f64eSAntonio Huete Jimenez int sync _U_)
46097a9217aSAntonio Huete Jimenez {
4613a289941SAaron LI pcap_set_not_initialized_message(pcap);
46297a9217aSAntonio Huete Jimenez return (0);
46397a9217aSAntonio Huete Jimenez }
46497a9217aSAntonio Huete Jimenez
4653a289941SAaron LI static int
pcap_setuserbuffer_not_initialized(pcap_t * pcap,int size _U_)4663a289941SAaron LI pcap_setuserbuffer_not_initialized(pcap_t *pcap, int size _U_)
4673a289941SAaron LI {
4683a289941SAaron LI pcap_set_not_initialized_message(pcap);
4693a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
4703a289941SAaron LI }
4713a289941SAaron LI
4723a289941SAaron LI static int
pcap_live_dump_not_initialized(pcap_t * pcap,char * filename _U_,int maxsize _U_,int maxpacks _U_)4733a289941SAaron LI pcap_live_dump_not_initialized(pcap_t *pcap, char *filename _U_, int maxsize _U_,
4743a289941SAaron LI int maxpacks _U_)
4753a289941SAaron LI {
4763a289941SAaron LI pcap_set_not_initialized_message(pcap);
4773a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
4783a289941SAaron LI }
4793a289941SAaron LI
4803a289941SAaron LI static int
pcap_live_dump_ended_not_initialized(pcap_t * pcap,int sync _U_)4813a289941SAaron LI pcap_live_dump_ended_not_initialized(pcap_t *pcap, int sync _U_)
4823a289941SAaron LI {
4833a289941SAaron LI pcap_set_not_initialized_message(pcap);
4843a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
4853a289941SAaron LI }
4863a289941SAaron LI
48797a9217aSAntonio Huete Jimenez static PAirpcapHandle
pcap_get_airpcap_handle_not_initialized(pcap_t * pcap)48897a9217aSAntonio Huete Jimenez pcap_get_airpcap_handle_not_initialized(pcap_t *pcap)
48997a9217aSAntonio Huete Jimenez {
4903a289941SAaron LI pcap_set_not_initialized_message(pcap);
49197a9217aSAntonio Huete Jimenez return (NULL);
49297a9217aSAntonio Huete Jimenez }
49397a9217aSAntonio Huete Jimenez #endif
49497a9217aSAntonio Huete Jimenez
495de0d3203SPeter Avalos /*
496de0d3203SPeter Avalos * Returns 1 if rfmon mode can be set on the pcap_t, 0 if it can't,
497de0d3203SPeter Avalos * a PCAP_ERROR value on an error.
498de0d3203SPeter Avalos */
499de0d3203SPeter Avalos int
pcap_can_set_rfmon(pcap_t * p)500de0d3203SPeter Avalos pcap_can_set_rfmon(pcap_t *p)
501de0d3203SPeter Avalos {
502de0d3203SPeter Avalos return (p->can_set_rfmon_op(p));
503de0d3203SPeter Avalos }
504de0d3203SPeter Avalos
505de0d3203SPeter Avalos /*
506de0d3203SPeter Avalos * For systems where rfmon mode is never supported.
507de0d3203SPeter Avalos */
508de0d3203SPeter Avalos static int
pcap_cant_set_rfmon(pcap_t * p _U_)509de0d3203SPeter Avalos pcap_cant_set_rfmon(pcap_t *p _U_)
510de0d3203SPeter Avalos {
511de0d3203SPeter Avalos return (0);
512de0d3203SPeter Avalos }
513de0d3203SPeter Avalos
514de0d3203SPeter Avalos /*
515a85e14b0SPeter Avalos * Sets *tstamp_typesp to point to an array 1 or more supported time stamp
516a85e14b0SPeter Avalos * types; the return value is the number of supported time stamp types.
517a85e14b0SPeter Avalos * The list should be freed by a call to pcap_free_tstamp_types() when
518a85e14b0SPeter Avalos * you're done with it.
519a85e14b0SPeter Avalos *
520a85e14b0SPeter Avalos * A return value of 0 means "you don't get a choice of time stamp type",
521a85e14b0SPeter Avalos * in which case *tstamp_typesp is set to null.
522a85e14b0SPeter Avalos *
523a85e14b0SPeter Avalos * PCAP_ERROR is returned on error.
524de0d3203SPeter Avalos */
525a85e14b0SPeter Avalos int
pcap_list_tstamp_types(pcap_t * p,int ** tstamp_typesp)526a85e14b0SPeter Avalos pcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp)
527a85e14b0SPeter Avalos {
528a85e14b0SPeter Avalos if (p->tstamp_type_count == 0) {
529a85e14b0SPeter Avalos /*
530a85e14b0SPeter Avalos * We don't support multiple time stamp types.
5313a289941SAaron LI * That means the only type we support is PCAP_TSTAMP_HOST;
5323a289941SAaron LI * set up a list containing only that type.
533a85e14b0SPeter Avalos */
5343a289941SAaron LI *tstamp_typesp = (int*)malloc(sizeof(**tstamp_typesp));
5353a289941SAaron LI if (*tstamp_typesp == NULL) {
5363a289941SAaron LI pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
5373a289941SAaron LI errno, "malloc");
5383a289941SAaron LI return (PCAP_ERROR);
5393a289941SAaron LI }
5403a289941SAaron LI **tstamp_typesp = PCAP_TSTAMP_HOST;
5413a289941SAaron LI return (1);
542a85e14b0SPeter Avalos } else {
543a85e14b0SPeter Avalos *tstamp_typesp = (int*)calloc(sizeof(**tstamp_typesp),
544a85e14b0SPeter Avalos p->tstamp_type_count);
545a85e14b0SPeter Avalos if (*tstamp_typesp == NULL) {
5463a289941SAaron LI pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
5473a289941SAaron LI errno, "malloc");
548a85e14b0SPeter Avalos return (PCAP_ERROR);
549a85e14b0SPeter Avalos }
550a85e14b0SPeter Avalos (void)memcpy(*tstamp_typesp, p->tstamp_type_list,
551a85e14b0SPeter Avalos sizeof(**tstamp_typesp) * p->tstamp_type_count);
552a85e14b0SPeter Avalos return (p->tstamp_type_count);
553a85e14b0SPeter Avalos }
5543a289941SAaron LI }
555de0d3203SPeter Avalos
556de0d3203SPeter Avalos /*
557a85e14b0SPeter Avalos * In Windows, you might have a library built with one version of the
558a85e14b0SPeter Avalos * C runtime library and an application built with another version of
559a85e14b0SPeter Avalos * the C runtime library, which means that the library might use one
560a85e14b0SPeter Avalos * version of malloc() and free() and the application might use another
561a85e14b0SPeter Avalos * version of malloc() and free(). If so, that means something
562a85e14b0SPeter Avalos * allocated by the library cannot be freed by the application, so we
563a85e14b0SPeter Avalos * need to have a pcap_free_tstamp_types() routine to free up the list
564a85e14b0SPeter Avalos * allocated by pcap_list_tstamp_types(), even though it's just a wrapper
565a85e14b0SPeter Avalos * around free().
566a85e14b0SPeter Avalos */
567a85e14b0SPeter Avalos void
pcap_free_tstamp_types(int * tstamp_type_list)568a85e14b0SPeter Avalos pcap_free_tstamp_types(int *tstamp_type_list)
569a85e14b0SPeter Avalos {
570a85e14b0SPeter Avalos free(tstamp_type_list);
571a85e14b0SPeter Avalos }
572a85e14b0SPeter Avalos
573a85e14b0SPeter Avalos /*
574a85e14b0SPeter Avalos * Default one-shot callback; overridden for capture types where the
575a85e14b0SPeter Avalos * packet data cannot be guaranteed to be available after the callback
576a85e14b0SPeter Avalos * returns, so that a copy must be made.
577a85e14b0SPeter Avalos */
57897a9217aSAntonio Huete Jimenez void
pcap_oneshot(u_char * user,const struct pcap_pkthdr * h,const u_char * pkt)579a85e14b0SPeter Avalos pcap_oneshot(u_char *user, const struct pcap_pkthdr *h, const u_char *pkt)
580a85e14b0SPeter Avalos {
581a85e14b0SPeter Avalos struct oneshot_userdata *sp = (struct oneshot_userdata *)user;
582a85e14b0SPeter Avalos
583a85e14b0SPeter Avalos *sp->hdr = *h;
584a85e14b0SPeter Avalos *sp->pkt = pkt;
585a85e14b0SPeter Avalos }
586a85e14b0SPeter Avalos
587a85e14b0SPeter Avalos const u_char *
pcap_next(pcap_t * p,struct pcap_pkthdr * h)588a85e14b0SPeter Avalos pcap_next(pcap_t *p, struct pcap_pkthdr *h)
589a85e14b0SPeter Avalos {
590a85e14b0SPeter Avalos struct oneshot_userdata s;
591a85e14b0SPeter Avalos const u_char *pkt;
592a85e14b0SPeter Avalos
593a85e14b0SPeter Avalos s.hdr = h;
594a85e14b0SPeter Avalos s.pkt = &pkt;
595a85e14b0SPeter Avalos s.pd = p;
596a85e14b0SPeter Avalos if (pcap_dispatch(p, 1, p->oneshot_callback, (u_char *)&s) <= 0)
597a85e14b0SPeter Avalos return (0);
598a85e14b0SPeter Avalos return (pkt);
599a85e14b0SPeter Avalos }
600a85e14b0SPeter Avalos
601a85e14b0SPeter Avalos int
pcap_next_ex(pcap_t * p,struct pcap_pkthdr ** pkt_header,const u_char ** pkt_data)602a85e14b0SPeter Avalos pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
603a85e14b0SPeter Avalos const u_char **pkt_data)
604a85e14b0SPeter Avalos {
605a85e14b0SPeter Avalos struct oneshot_userdata s;
606a85e14b0SPeter Avalos
607a85e14b0SPeter Avalos s.hdr = &p->pcap_header;
608a85e14b0SPeter Avalos s.pkt = pkt_data;
609a85e14b0SPeter Avalos s.pd = p;
610a85e14b0SPeter Avalos
611a85e14b0SPeter Avalos /* Saves a pointer to the packet headers */
612a85e14b0SPeter Avalos *pkt_header= &p->pcap_header;
613a85e14b0SPeter Avalos
61497a9217aSAntonio Huete Jimenez if (p->rfile != NULL) {
615a85e14b0SPeter Avalos int status;
616a85e14b0SPeter Avalos
617a85e14b0SPeter Avalos /* We are on an offline capture */
618a85e14b0SPeter Avalos status = pcap_offline_read(p, 1, p->oneshot_callback,
619a85e14b0SPeter Avalos (u_char *)&s);
620a85e14b0SPeter Avalos
621a85e14b0SPeter Avalos /*
622a85e14b0SPeter Avalos * Return codes for pcap_offline_read() are:
623a85e14b0SPeter Avalos * - 0: EOF
624a85e14b0SPeter Avalos * - -1: error
625a85e14b0SPeter Avalos * - >1: OK
626a85e14b0SPeter Avalos * The first one ('0') conflicts with the return code of
627a85e14b0SPeter Avalos * 0 from pcap_read() meaning "no packets arrived before
628a85e14b0SPeter Avalos * the timeout expired", so we map it to -2 so you can
629a85e14b0SPeter Avalos * distinguish between an EOF from a savefile and a
630a85e14b0SPeter Avalos * "no packets arrived before the timeout expired, try
631a85e14b0SPeter Avalos * again" from a live capture.
632a85e14b0SPeter Avalos */
633a85e14b0SPeter Avalos if (status == 0)
634a85e14b0SPeter Avalos return (-2);
635a85e14b0SPeter Avalos else
636a85e14b0SPeter Avalos return (status);
637a85e14b0SPeter Avalos }
638a85e14b0SPeter Avalos
639a85e14b0SPeter Avalos /*
640a85e14b0SPeter Avalos * Return codes for pcap_read() are:
641a85e14b0SPeter Avalos * - 0: timeout
642a85e14b0SPeter Avalos * - -1: error
643a85e14b0SPeter Avalos * - -2: loop was broken out of with pcap_breakloop()
644a85e14b0SPeter Avalos * - >1: OK
645a85e14b0SPeter Avalos * The first one ('0') conflicts with the return code of 0 from
646a85e14b0SPeter Avalos * pcap_offline_read() meaning "end of file".
647a85e14b0SPeter Avalos */
648a85e14b0SPeter Avalos return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s));
649a85e14b0SPeter Avalos }
650a85e14b0SPeter Avalos
6513a289941SAaron LI /*
6523a289941SAaron LI * Implementation of a pcap_if_list_t.
6533a289941SAaron LI */
6543a289941SAaron LI struct pcap_if_list {
6553a289941SAaron LI pcap_if_t *beginning;
6563a289941SAaron LI };
6573a289941SAaron LI
65897a9217aSAntonio Huete Jimenez static struct capture_source_type {
6593a289941SAaron LI int (*findalldevs_op)(pcap_if_list_t *, char *);
6600e381983SMatthew Dillon pcap_t *(*create_op)(const char *, char *, int *);
6610e381983SMatthew Dillon } capture_source_types[] = {
6620e381983SMatthew Dillon #ifdef HAVE_DAG_API
6630e381983SMatthew Dillon { dag_findalldevs, dag_create },
6640e381983SMatthew Dillon #endif
6650e381983SMatthew Dillon #ifdef HAVE_SEPTEL_API
6660e381983SMatthew Dillon { septel_findalldevs, septel_create },
6670e381983SMatthew Dillon #endif
6680e381983SMatthew Dillon #ifdef HAVE_SNF_API
6690e381983SMatthew Dillon { snf_findalldevs, snf_create },
6700e381983SMatthew Dillon #endif
67197a9217aSAntonio Huete Jimenez #ifdef HAVE_TC_API
67297a9217aSAntonio Huete Jimenez { TcFindAllDevs, TcCreate },
67397a9217aSAntonio Huete Jimenez #endif
6740e381983SMatthew Dillon #ifdef PCAP_SUPPORT_BT
6750e381983SMatthew Dillon { bt_findalldevs, bt_create },
6760e381983SMatthew Dillon #endif
67797a9217aSAntonio Huete Jimenez #ifdef PCAP_SUPPORT_BT_MONITOR
67897a9217aSAntonio Huete Jimenez { bt_monitor_findalldevs, bt_monitor_create },
6790e381983SMatthew Dillon #endif
680*ea16f64eSAntonio Huete Jimenez #ifdef PCAP_SUPPORT_LINUX_USBMON
6810e381983SMatthew Dillon { usb_findalldevs, usb_create },
6820e381983SMatthew Dillon #endif
6830e381983SMatthew Dillon #ifdef PCAP_SUPPORT_NETFILTER
6840e381983SMatthew Dillon { netfilter_findalldevs, netfilter_create },
6850e381983SMatthew Dillon #endif
6863a289941SAaron LI #ifdef PCAP_SUPPORT_NETMAP
6873a289941SAaron LI { pcap_netmap_findalldevs, pcap_netmap_create },
6883a289941SAaron LI #endif
68997a9217aSAntonio Huete Jimenez #ifdef PCAP_SUPPORT_DBUS
69097a9217aSAntonio Huete Jimenez { dbus_findalldevs, dbus_create },
69197a9217aSAntonio Huete Jimenez #endif
6923a289941SAaron LI #ifdef PCAP_SUPPORT_RDMASNIFF
6933a289941SAaron LI { rdmasniff_findalldevs, rdmasniff_create },
6943a289941SAaron LI #endif
695*ea16f64eSAntonio Huete Jimenez #ifdef PCAP_SUPPORT_DPDK
696*ea16f64eSAntonio Huete Jimenez { pcap_dpdk_findalldevs, pcap_dpdk_create },
697*ea16f64eSAntonio Huete Jimenez #endif
698*ea16f64eSAntonio Huete Jimenez #ifdef HAVE_AIRPCAP_API
699*ea16f64eSAntonio Huete Jimenez { airpcap_findalldevs, airpcap_create },
700*ea16f64eSAntonio Huete Jimenez #endif
7010e381983SMatthew Dillon { NULL, NULL }
7020e381983SMatthew Dillon };
7030e381983SMatthew Dillon
7040e381983SMatthew Dillon /*
7050e381983SMatthew Dillon * Get a list of all capture sources that are up and that we can open.
7060e381983SMatthew Dillon * Returns -1 on error, 0 otherwise.
7070e381983SMatthew Dillon * The list, as returned through "alldevsp", may be null if no interfaces
7080e381983SMatthew Dillon * were up and could be opened.
7090e381983SMatthew Dillon */
7100e381983SMatthew Dillon int
pcap_findalldevs(pcap_if_t ** alldevsp,char * errbuf)7110e381983SMatthew Dillon pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
7120e381983SMatthew Dillon {
7130e381983SMatthew Dillon size_t i;
7143a289941SAaron LI pcap_if_list_t devlist;
7150e381983SMatthew Dillon
7160e381983SMatthew Dillon /*
71797a9217aSAntonio Huete Jimenez * Find all the local network interfaces on which we
71897a9217aSAntonio Huete Jimenez * can capture.
7190e381983SMatthew Dillon */
7203a289941SAaron LI devlist.beginning = NULL;
7213a289941SAaron LI if (pcap_platform_finddevs(&devlist, errbuf) == -1) {
7223a289941SAaron LI /*
7233a289941SAaron LI * Failed - free all of the entries we were given
7243a289941SAaron LI * before we failed.
7253a289941SAaron LI */
7263a289941SAaron LI if (devlist.beginning != NULL)
7273a289941SAaron LI pcap_freealldevs(devlist.beginning);
7283a289941SAaron LI *alldevsp = NULL;
7290e381983SMatthew Dillon return (-1);
7303a289941SAaron LI }
7310e381983SMatthew Dillon
7320e381983SMatthew Dillon /*
7330e381983SMatthew Dillon * Ask each of the non-local-network-interface capture
7340e381983SMatthew Dillon * source types what interfaces they have.
7350e381983SMatthew Dillon */
7360e381983SMatthew Dillon for (i = 0; capture_source_types[i].findalldevs_op != NULL; i++) {
7373a289941SAaron LI if (capture_source_types[i].findalldevs_op(&devlist, errbuf) == -1) {
7380e381983SMatthew Dillon /*
7390e381983SMatthew Dillon * We had an error; free the list we've been
7400e381983SMatthew Dillon * constructing.
7410e381983SMatthew Dillon */
7423a289941SAaron LI if (devlist.beginning != NULL)
7433a289941SAaron LI pcap_freealldevs(devlist.beginning);
7440e381983SMatthew Dillon *alldevsp = NULL;
7450e381983SMatthew Dillon return (-1);
7460e381983SMatthew Dillon }
7470e381983SMatthew Dillon }
74897a9217aSAntonio Huete Jimenez
7493a289941SAaron LI /*
7503a289941SAaron LI * Return the first entry of the list of all devices.
7513a289941SAaron LI */
7523a289941SAaron LI *alldevsp = devlist.beginning;
7530e381983SMatthew Dillon return (0);
7540e381983SMatthew Dillon }
7550e381983SMatthew Dillon
7563a289941SAaron LI static struct sockaddr *
dup_sockaddr(struct sockaddr * sa,size_t sa_length)7573a289941SAaron LI dup_sockaddr(struct sockaddr *sa, size_t sa_length)
7583a289941SAaron LI {
7593a289941SAaron LI struct sockaddr *newsa;
7603a289941SAaron LI
7613a289941SAaron LI if ((newsa = malloc(sa_length)) == NULL)
7623a289941SAaron LI return (NULL);
7633a289941SAaron LI return (memcpy(newsa, sa, sa_length));
7643a289941SAaron LI }
7653a289941SAaron LI
7663a289941SAaron LI /*
7673a289941SAaron LI * Construct a "figure of merit" for an interface, for use when sorting
7683a289941SAaron LI * the list of interfaces, in which interfaces that are up are superior
7693a289941SAaron LI * to interfaces that aren't up, interfaces that are up and running are
7703a289941SAaron LI * superior to interfaces that are up but not running, and non-loopback
7713a289941SAaron LI * interfaces that are up and running are superior to loopback interfaces,
7723a289941SAaron LI * and interfaces with the same flags have a figure of merit that's higher
7733a289941SAaron LI * the lower the instance number.
7743a289941SAaron LI *
7753a289941SAaron LI * The goal is to try to put the interfaces most likely to be useful for
7763a289941SAaron LI * capture at the beginning of the list.
7773a289941SAaron LI *
7783a289941SAaron LI * The figure of merit, which is lower the "better" the interface is,
7793a289941SAaron LI * has the uppermost bit set if the interface isn't running, the bit
780*ea16f64eSAntonio Huete Jimenez * below that set if the interface isn't up, the bit below that
781*ea16f64eSAntonio Huete Jimenez * set if the interface is a loopback interface, and the bit below
782*ea16f64eSAntonio Huete Jimenez * that set if it's the "any" interface.
783*ea16f64eSAntonio Huete Jimenez *
784*ea16f64eSAntonio Huete Jimenez * Note: we don't sort by unit number because 1) not all interfaces have
785*ea16f64eSAntonio Huete Jimenez * a unit number (systemd, for example, might assign interface names
786*ea16f64eSAntonio Huete Jimenez * based on the interface's MAC address or on the physical location of
787*ea16f64eSAntonio Huete Jimenez * the adapter's connector), and 2) if the name does end with a simple
788*ea16f64eSAntonio Huete Jimenez * unit number, it's not a global property of the interface, it's only
789*ea16f64eSAntonio Huete Jimenez * useful as a sort key for device names with the same prefix, so xyz0
790*ea16f64eSAntonio Huete Jimenez * shouldn't necessarily sort before abc2. This means that interfaces
791*ea16f64eSAntonio Huete Jimenez * with the same figure of merit will be sorted by the order in which
792*ea16f64eSAntonio Huete Jimenez * the mechanism from which we're getting the interfaces supplies them.
7933a289941SAaron LI */
7943a289941SAaron LI static u_int
get_figure_of_merit(pcap_if_t * dev)7953a289941SAaron LI get_figure_of_merit(pcap_if_t *dev)
7963a289941SAaron LI {
7973a289941SAaron LI u_int n;
7983a289941SAaron LI
7993a289941SAaron LI n = 0;
8003a289941SAaron LI if (!(dev->flags & PCAP_IF_RUNNING))
8013a289941SAaron LI n |= 0x80000000;
8023a289941SAaron LI if (!(dev->flags & PCAP_IF_UP))
8033a289941SAaron LI n |= 0x40000000;
8043a289941SAaron LI
8053a289941SAaron LI /*
8063a289941SAaron LI * Give non-wireless interfaces that aren't disconnected a better
8073a289941SAaron LI * figure of merit than interfaces that are disconnected, as
8083a289941SAaron LI * "disconnected" should indicate that the interface isn't
8093a289941SAaron LI * plugged into a network and thus won't give you any traffic.
8103a289941SAaron LI *
8113a289941SAaron LI * For wireless interfaces, it means "associated with a network",
8123a289941SAaron LI * which we presume not to necessarily prevent capture, as you
8133a289941SAaron LI * might run the adapter in some flavor of monitor mode.
8143a289941SAaron LI */
8153a289941SAaron LI if (!(dev->flags & PCAP_IF_WIRELESS) &&
8163a289941SAaron LI (dev->flags & PCAP_IF_CONNECTION_STATUS) == PCAP_IF_CONNECTION_STATUS_DISCONNECTED)
8173a289941SAaron LI n |= 0x20000000;
8183a289941SAaron LI
8193a289941SAaron LI /*
8203a289941SAaron LI * Sort loopback devices after non-loopback devices, *except* for
8213a289941SAaron LI * disconnected devices.
8223a289941SAaron LI */
8233a289941SAaron LI if (dev->flags & PCAP_IF_LOOPBACK)
8243a289941SAaron LI n |= 0x10000000;
8253a289941SAaron LI
826*ea16f64eSAntonio Huete Jimenez /*
827*ea16f64eSAntonio Huete Jimenez * Sort the "any" device before loopback and disconnected devices,
828*ea16f64eSAntonio Huete Jimenez * but after all other devices.
829*ea16f64eSAntonio Huete Jimenez */
830*ea16f64eSAntonio Huete Jimenez if (strcmp(dev->name, "any") == 0)
831*ea16f64eSAntonio Huete Jimenez n |= 0x08000000;
832*ea16f64eSAntonio Huete Jimenez
8333a289941SAaron LI return (n);
8343a289941SAaron LI }
8353a289941SAaron LI
8363a289941SAaron LI #ifndef _WIN32
8373a289941SAaron LI /*
8383a289941SAaron LI * Try to get a description for a given device.
8393a289941SAaron LI * Returns a mallocated description if it could and NULL if it couldn't.
8403a289941SAaron LI *
8413a289941SAaron LI * XXX - on FreeBSDs that support it, should it get the sysctl named
8423a289941SAaron LI * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
8433a289941SAaron LI * of the adapter? Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
8443a289941SAaron LI * with my Cisco 350 card, so the name isn't entirely descriptive. The
8453a289941SAaron LI * "dev.an.0.%pnpinfo" has a better description, although one might argue
8463a289941SAaron LI * that the problem is really a driver bug - if it can find out that it's
8473a289941SAaron LI * a Cisco 340 or 350, rather than an old Aironet card, it should use
8483a289941SAaron LI * that in the description.
8493a289941SAaron LI *
8503a289941SAaron LI * Do NetBSD, DragonflyBSD, or OpenBSD support this as well? FreeBSD
8513a289941SAaron LI * and OpenBSD let you get a description, but it's not generated by the OS,
8523a289941SAaron LI * it's set with another ioctl that ifconfig supports; we use that to get
8533a289941SAaron LI * a description in FreeBSD and OpenBSD, but if there is no such
8543a289941SAaron LI * description available, it still might be nice to get some description
8553a289941SAaron LI * string based on the device type or something such as that.
8563a289941SAaron LI *
8573a289941SAaron LI * In macOS, the System Configuration framework can apparently return
8583a289941SAaron LI * names in 10.4 and later.
8593a289941SAaron LI *
8603a289941SAaron LI * It also appears that freedesktop.org's HAL offers an "info.product"
8613a289941SAaron LI * string, but the HAL specification says it "should not be used in any
8623a289941SAaron LI * UI" and "subsystem/capability specific properties" should be used
8633a289941SAaron LI * instead and, in any case, I think HAL is being deprecated in
8643a289941SAaron LI * favor of other stuff such as DeviceKit. DeviceKit doesn't appear
8653a289941SAaron LI * to have any obvious product information for devices, but maybe
8663a289941SAaron LI * I haven't looked hard enough.
8673a289941SAaron LI *
8683a289941SAaron LI * Using the System Configuration framework, or HAL, or DeviceKit, or
8693a289941SAaron LI * whatever, would require that libpcap applications be linked with
8703a289941SAaron LI * the frameworks/libraries in question. That shouldn't be a problem
8713a289941SAaron LI * for programs linking with the shared version of libpcap (unless
8723a289941SAaron LI * you're running on AIX - which I think is the only UN*X that doesn't
8733a289941SAaron LI * support linking a shared library with other libraries on which it
8743a289941SAaron LI * depends, and having an executable linked only with the first shared
8753a289941SAaron LI * library automatically pick up the other libraries when started -
8763a289941SAaron LI * and using HAL or whatever). Programs linked with the static
8773a289941SAaron LI * version of libpcap would have to use pcap-config with the --static
8783a289941SAaron LI * flag in order to get the right linker flags in order to pick up
8793a289941SAaron LI * the additional libraries/frameworks; those programs need that anyway
8803a289941SAaron LI * for libpcap 1.1 and beyond on Linux, as, by default, it requires
8813a289941SAaron LI * -lnl.
8823a289941SAaron LI *
8833a289941SAaron LI * Do any other UN*Xes, or desktop environments support getting a
8843a289941SAaron LI * description?
8853a289941SAaron LI */
8863a289941SAaron LI static char *
8873a289941SAaron LI #ifdef SIOCGIFDESCR
get_if_description(const char * name)8883a289941SAaron LI get_if_description(const char *name)
8893a289941SAaron LI {
8903a289941SAaron LI char *description = NULL;
8913a289941SAaron LI int s;
8923a289941SAaron LI struct ifreq ifrdesc;
8933a289941SAaron LI #ifndef IFDESCRSIZE
8943a289941SAaron LI size_t descrlen = 64;
8953a289941SAaron LI #else
8963a289941SAaron LI size_t descrlen = IFDESCRSIZE;
8973a289941SAaron LI #endif /* IFDESCRSIZE */
8983a289941SAaron LI
8993a289941SAaron LI /*
9003a289941SAaron LI * Get the description for the interface.
9013a289941SAaron LI */
9023a289941SAaron LI memset(&ifrdesc, 0, sizeof ifrdesc);
9033a289941SAaron LI pcap_strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
9043a289941SAaron LI s = socket(AF_INET, SOCK_DGRAM, 0);
9053a289941SAaron LI if (s >= 0) {
9063a289941SAaron LI #ifdef __FreeBSD__
9073a289941SAaron LI /*
9083a289941SAaron LI * On FreeBSD, if the buffer isn't big enough for the
9093a289941SAaron LI * description, the ioctl succeeds, but the description
9103a289941SAaron LI * isn't copied, ifr_buffer.length is set to the description
9113a289941SAaron LI * length, and ifr_buffer.buffer is set to NULL.
9123a289941SAaron LI */
9133a289941SAaron LI for (;;) {
9143a289941SAaron LI free(description);
9153a289941SAaron LI if ((description = malloc(descrlen)) != NULL) {
9163a289941SAaron LI ifrdesc.ifr_buffer.buffer = description;
9173a289941SAaron LI ifrdesc.ifr_buffer.length = descrlen;
9183a289941SAaron LI if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
9193a289941SAaron LI if (ifrdesc.ifr_buffer.buffer ==
9203a289941SAaron LI description)
9213a289941SAaron LI break;
9223a289941SAaron LI else
9233a289941SAaron LI descrlen = ifrdesc.ifr_buffer.length;
9243a289941SAaron LI } else {
9253a289941SAaron LI /*
9263a289941SAaron LI * Failed to get interface description.
9273a289941SAaron LI */
9283a289941SAaron LI free(description);
9293a289941SAaron LI description = NULL;
9303a289941SAaron LI break;
9313a289941SAaron LI }
9323a289941SAaron LI } else
9333a289941SAaron LI break;
9343a289941SAaron LI }
9353a289941SAaron LI #else /* __FreeBSD__ */
9363a289941SAaron LI /*
9373a289941SAaron LI * The only other OS that currently supports
9383a289941SAaron LI * SIOCGIFDESCR is OpenBSD, and it has no way
9393a289941SAaron LI * to get the description length - it's clamped
9403a289941SAaron LI * to a maximum of IFDESCRSIZE.
9413a289941SAaron LI */
9423a289941SAaron LI if ((description = malloc(descrlen)) != NULL) {
9433a289941SAaron LI ifrdesc.ifr_data = (caddr_t)description;
9443a289941SAaron LI if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
9453a289941SAaron LI /*
9463a289941SAaron LI * Failed to get interface description.
9473a289941SAaron LI */
9483a289941SAaron LI free(description);
9493a289941SAaron LI description = NULL;
9503a289941SAaron LI }
9513a289941SAaron LI }
9523a289941SAaron LI #endif /* __FreeBSD__ */
9533a289941SAaron LI close(s);
9543a289941SAaron LI if (description != NULL && description[0] == '\0') {
9553a289941SAaron LI /*
9563a289941SAaron LI * Description is empty, so discard it.
9573a289941SAaron LI */
9583a289941SAaron LI free(description);
9593a289941SAaron LI description = NULL;
9603a289941SAaron LI }
9613a289941SAaron LI }
9623a289941SAaron LI
9633a289941SAaron LI #ifdef __FreeBSD__
9643a289941SAaron LI /*
9653a289941SAaron LI * For FreeBSD, if we didn't get a description, and this is
9663a289941SAaron LI * a device with a name of the form usbusN, label it as a USB
9673a289941SAaron LI * bus.
9683a289941SAaron LI */
9693a289941SAaron LI if (description == NULL) {
9703a289941SAaron LI if (strncmp(name, "usbus", 5) == 0) {
9713a289941SAaron LI /*
9723a289941SAaron LI * OK, it begins with "usbus".
9733a289941SAaron LI */
9743a289941SAaron LI long busnum;
9753a289941SAaron LI char *p;
9763a289941SAaron LI
9773a289941SAaron LI errno = 0;
9783a289941SAaron LI busnum = strtol(name + 5, &p, 10);
9793a289941SAaron LI if (errno == 0 && p != name + 5 && *p == '\0' &&
9803a289941SAaron LI busnum >= 0 && busnum <= INT_MAX) {
9813a289941SAaron LI /*
9823a289941SAaron LI * OK, it's a valid number that's not
9833a289941SAaron LI * bigger than INT_MAX. Construct
9843a289941SAaron LI * a description from it.
9853a289941SAaron LI * (If that fails, we don't worry about
9863a289941SAaron LI * it, we just return NULL.)
9873a289941SAaron LI */
9883a289941SAaron LI if (pcap_asprintf(&description,
9893a289941SAaron LI "USB bus number %ld", busnum) == -1) {
9903a289941SAaron LI /* Failed. */
9913a289941SAaron LI description = NULL;
9923a289941SAaron LI }
9933a289941SAaron LI }
9943a289941SAaron LI }
9953a289941SAaron LI }
9963a289941SAaron LI #endif
9973a289941SAaron LI return (description);
9983a289941SAaron LI #else /* SIOCGIFDESCR */
9993a289941SAaron LI get_if_description(const char *name _U_)
10003a289941SAaron LI {
10013a289941SAaron LI return (NULL);
10023a289941SAaron LI #endif /* SIOCGIFDESCR */
10033a289941SAaron LI }
10043a289941SAaron LI
10053a289941SAaron LI /*
10063a289941SAaron LI * Look for a given device in the specified list of devices.
10073a289941SAaron LI *
10083a289941SAaron LI * If we find it, return a pointer to its entry.
10093a289941SAaron LI *
10103a289941SAaron LI * If we don't find it, attempt to add an entry for it, with the specified
10113a289941SAaron LI * IFF_ flags and description, and, if that succeeds, return a pointer to
10123a289941SAaron LI * the new entry, otherwise return NULL and set errbuf to an error message.
10133a289941SAaron LI */
10143a289941SAaron LI pcap_if_t *
10153a289941SAaron LI find_or_add_if(pcap_if_list_t *devlistp, const char *name,
10163a289941SAaron LI bpf_u_int32 if_flags, get_if_flags_func get_flags_func, char *errbuf)
10173a289941SAaron LI {
10183a289941SAaron LI bpf_u_int32 pcap_flags;
10193a289941SAaron LI
10203a289941SAaron LI /*
10213a289941SAaron LI * Convert IFF_ flags to pcap flags.
10223a289941SAaron LI */
10233a289941SAaron LI pcap_flags = 0;
10243a289941SAaron LI #ifdef IFF_LOOPBACK
10253a289941SAaron LI if (if_flags & IFF_LOOPBACK)
10263a289941SAaron LI pcap_flags |= PCAP_IF_LOOPBACK;
10273a289941SAaron LI #else
10283a289941SAaron LI /*
10293a289941SAaron LI * We don't have IFF_LOOPBACK, so look at the device name to
10303a289941SAaron LI * see if it looks like a loopback device.
10313a289941SAaron LI */
10323a289941SAaron LI if (name[0] == 'l' && name[1] == 'o' &&
1033*ea16f64eSAntonio Huete Jimenez (PCAP_ISDIGIT(name[2]) || name[2] == '\0'))
10343a289941SAaron LI pcap_flags |= PCAP_IF_LOOPBACK;
10353a289941SAaron LI #endif
10363a289941SAaron LI #ifdef IFF_UP
10373a289941SAaron LI if (if_flags & IFF_UP)
10383a289941SAaron LI pcap_flags |= PCAP_IF_UP;
10393a289941SAaron LI #endif
10403a289941SAaron LI #ifdef IFF_RUNNING
10413a289941SAaron LI if (if_flags & IFF_RUNNING)
10423a289941SAaron LI pcap_flags |= PCAP_IF_RUNNING;
10433a289941SAaron LI #endif
10443a289941SAaron LI
10453a289941SAaron LI /*
10463a289941SAaron LI * Attempt to find an entry for this device; if we don't find one,
10473a289941SAaron LI * attempt to add one.
10483a289941SAaron LI */
10493a289941SAaron LI return (find_or_add_dev(devlistp, name, pcap_flags,
10503a289941SAaron LI get_flags_func, get_if_description(name), errbuf));
10513a289941SAaron LI }
10523a289941SAaron LI
10533a289941SAaron LI /*
10543a289941SAaron LI * Look for a given device in the specified list of devices.
10553a289941SAaron LI *
10563a289941SAaron LI * If we find it, then, if the specified address isn't null, add it to
10573a289941SAaron LI * the list of addresses for the device and return 0.
10583a289941SAaron LI *
10593a289941SAaron LI * If we don't find it, attempt to add an entry for it, with the specified
10603a289941SAaron LI * IFF_ flags and description, and, if that succeeds, add the specified
10613a289941SAaron LI * address to its list of addresses if that address is non-null, and
10623a289941SAaron LI * return 0, otherwise return -1 and set errbuf to an error message.
10633a289941SAaron LI *
10643a289941SAaron LI * (We can get called with a null address because we might get a list
10653a289941SAaron LI * of interface name/address combinations from the underlying OS, with
10663a289941SAaron LI * the address being absent in some cases, rather than a list of
10673a289941SAaron LI * interfaces with each interface having a list of addresses, so this
10683a289941SAaron LI * call may be the only call made to add to the list, and we want to
10693a289941SAaron LI * add interfaces even if they have no addresses.)
10703a289941SAaron LI */
10713a289941SAaron LI int
10723a289941SAaron LI add_addr_to_if(pcap_if_list_t *devlistp, const char *name,
10733a289941SAaron LI bpf_u_int32 if_flags, get_if_flags_func get_flags_func,
10743a289941SAaron LI struct sockaddr *addr, size_t addr_size,
10753a289941SAaron LI struct sockaddr *netmask, size_t netmask_size,
10763a289941SAaron LI struct sockaddr *broadaddr, size_t broadaddr_size,
10773a289941SAaron LI struct sockaddr *dstaddr, size_t dstaddr_size,
10783a289941SAaron LI char *errbuf)
10793a289941SAaron LI {
10803a289941SAaron LI pcap_if_t *curdev;
10813a289941SAaron LI
10823a289941SAaron LI /*
10833a289941SAaron LI * Check whether the device exists and, if not, add it.
10843a289941SAaron LI */
10853a289941SAaron LI curdev = find_or_add_if(devlistp, name, if_flags, get_flags_func,
10863a289941SAaron LI errbuf);
10873a289941SAaron LI if (curdev == NULL) {
10883a289941SAaron LI /*
10893a289941SAaron LI * Error - give up.
10903a289941SAaron LI */
10913a289941SAaron LI return (-1);
10923a289941SAaron LI }
10933a289941SAaron LI
10943a289941SAaron LI if (addr == NULL) {
10953a289941SAaron LI /*
10963a289941SAaron LI * There's no address to add; this entry just meant
10973a289941SAaron LI * "here's a new interface".
10983a289941SAaron LI */
10993a289941SAaron LI return (0);
11003a289941SAaron LI }
11013a289941SAaron LI
11023a289941SAaron LI /*
11033a289941SAaron LI * "curdev" is an entry for this interface, and we have an
11043a289941SAaron LI * address for it; add an entry for that address to the
11053a289941SAaron LI * interface's list of addresses.
11063a289941SAaron LI */
11073a289941SAaron LI return (add_addr_to_dev(curdev, addr, addr_size, netmask,
11083a289941SAaron LI netmask_size, broadaddr, broadaddr_size, dstaddr,
11093a289941SAaron LI dstaddr_size, errbuf));
11103a289941SAaron LI }
11113a289941SAaron LI #endif /* _WIN32 */
11123a289941SAaron LI
11133a289941SAaron LI /*
11143a289941SAaron LI * Add an entry to the list of addresses for an interface.
11153a289941SAaron LI * "curdev" is the entry for that interface.
11163a289941SAaron LI */
11173a289941SAaron LI int
11183a289941SAaron LI add_addr_to_dev(pcap_if_t *curdev,
11193a289941SAaron LI struct sockaddr *addr, size_t addr_size,
11203a289941SAaron LI struct sockaddr *netmask, size_t netmask_size,
11213a289941SAaron LI struct sockaddr *broadaddr, size_t broadaddr_size,
11223a289941SAaron LI struct sockaddr *dstaddr, size_t dstaddr_size,
11233a289941SAaron LI char *errbuf)
11243a289941SAaron LI {
11253a289941SAaron LI pcap_addr_t *curaddr, *prevaddr, *nextaddr;
11263a289941SAaron LI
11273a289941SAaron LI /*
11283a289941SAaron LI * Allocate the new entry and fill it in.
11293a289941SAaron LI */
11303a289941SAaron LI curaddr = (pcap_addr_t *)malloc(sizeof(pcap_addr_t));
11313a289941SAaron LI if (curaddr == NULL) {
11323a289941SAaron LI pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
11333a289941SAaron LI errno, "malloc");
11343a289941SAaron LI return (-1);
11353a289941SAaron LI }
11363a289941SAaron LI
11373a289941SAaron LI curaddr->next = NULL;
11383a289941SAaron LI if (addr != NULL && addr_size != 0) {
11393a289941SAaron LI curaddr->addr = (struct sockaddr *)dup_sockaddr(addr, addr_size);
11403a289941SAaron LI if (curaddr->addr == NULL) {
11413a289941SAaron LI pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
11423a289941SAaron LI errno, "malloc");
11433a289941SAaron LI free(curaddr);
11443a289941SAaron LI return (-1);
11453a289941SAaron LI }
11463a289941SAaron LI } else
11473a289941SAaron LI curaddr->addr = NULL;
11483a289941SAaron LI
11493a289941SAaron LI if (netmask != NULL && netmask_size != 0) {
11503a289941SAaron LI curaddr->netmask = (struct sockaddr *)dup_sockaddr(netmask, netmask_size);
11513a289941SAaron LI if (curaddr->netmask == NULL) {
11523a289941SAaron LI pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
11533a289941SAaron LI errno, "malloc");
11543a289941SAaron LI if (curaddr->addr != NULL)
11553a289941SAaron LI free(curaddr->addr);
11563a289941SAaron LI free(curaddr);
11573a289941SAaron LI return (-1);
11583a289941SAaron LI }
11593a289941SAaron LI } else
11603a289941SAaron LI curaddr->netmask = NULL;
11613a289941SAaron LI
11623a289941SAaron LI if (broadaddr != NULL && broadaddr_size != 0) {
11633a289941SAaron LI curaddr->broadaddr = (struct sockaddr *)dup_sockaddr(broadaddr, broadaddr_size);
11643a289941SAaron LI if (curaddr->broadaddr == NULL) {
11653a289941SAaron LI pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
11663a289941SAaron LI errno, "malloc");
11673a289941SAaron LI if (curaddr->netmask != NULL)
11683a289941SAaron LI free(curaddr->netmask);
11693a289941SAaron LI if (curaddr->addr != NULL)
11703a289941SAaron LI free(curaddr->addr);
11713a289941SAaron LI free(curaddr);
11723a289941SAaron LI return (-1);
11733a289941SAaron LI }
11743a289941SAaron LI } else
11753a289941SAaron LI curaddr->broadaddr = NULL;
11763a289941SAaron LI
11773a289941SAaron LI if (dstaddr != NULL && dstaddr_size != 0) {
11783a289941SAaron LI curaddr->dstaddr = (struct sockaddr *)dup_sockaddr(dstaddr, dstaddr_size);
11793a289941SAaron LI if (curaddr->dstaddr == NULL) {
11803a289941SAaron LI pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
11813a289941SAaron LI errno, "malloc");
11823a289941SAaron LI if (curaddr->broadaddr != NULL)
11833a289941SAaron LI free(curaddr->broadaddr);
11843a289941SAaron LI if (curaddr->netmask != NULL)
11853a289941SAaron LI free(curaddr->netmask);
11863a289941SAaron LI if (curaddr->addr != NULL)
11873a289941SAaron LI free(curaddr->addr);
11883a289941SAaron LI free(curaddr);
11893a289941SAaron LI return (-1);
11903a289941SAaron LI }
11913a289941SAaron LI } else
11923a289941SAaron LI curaddr->dstaddr = NULL;
11933a289941SAaron LI
11943a289941SAaron LI /*
11953a289941SAaron LI * Find the end of the list of addresses.
11963a289941SAaron LI */
11973a289941SAaron LI for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
11983a289941SAaron LI nextaddr = prevaddr->next;
11993a289941SAaron LI if (nextaddr == NULL) {
12003a289941SAaron LI /*
12013a289941SAaron LI * This is the end of the list.
12023a289941SAaron LI */
12033a289941SAaron LI break;
12043a289941SAaron LI }
12053a289941SAaron LI }
12063a289941SAaron LI
12073a289941SAaron LI if (prevaddr == NULL) {
12083a289941SAaron LI /*
12093a289941SAaron LI * The list was empty; this is the first member.
12103a289941SAaron LI */
12113a289941SAaron LI curdev->addresses = curaddr;
12123a289941SAaron LI } else {
12133a289941SAaron LI /*
12143a289941SAaron LI * "prevaddr" is the last member of the list; append
12153a289941SAaron LI * this member to it.
12163a289941SAaron LI */
12173a289941SAaron LI prevaddr->next = curaddr;
12183a289941SAaron LI }
12193a289941SAaron LI
12203a289941SAaron LI return (0);
12213a289941SAaron LI }
12223a289941SAaron LI
12233a289941SAaron LI /*
12243a289941SAaron LI * Look for a given device in the specified list of devices.
12253a289941SAaron LI *
12263a289941SAaron LI * If we find it, return 0 and set *curdev_ret to point to it.
12273a289941SAaron LI *
12283a289941SAaron LI * If we don't find it, attempt to add an entry for it, with the specified
12293a289941SAaron LI * flags and description, and, if that succeeds, return 0, otherwise
12303a289941SAaron LI * return -1 and set errbuf to an error message.
12313a289941SAaron LI */
12323a289941SAaron LI pcap_if_t *
12333a289941SAaron LI find_or_add_dev(pcap_if_list_t *devlistp, const char *name, bpf_u_int32 flags,
12343a289941SAaron LI get_if_flags_func get_flags_func, const char *description, char *errbuf)
12353a289941SAaron LI {
12363a289941SAaron LI pcap_if_t *curdev;
12373a289941SAaron LI
12383a289941SAaron LI /*
12393a289941SAaron LI * Is there already an entry in the list for this device?
12403a289941SAaron LI */
12413a289941SAaron LI curdev = find_dev(devlistp, name);
12423a289941SAaron LI if (curdev != NULL) {
12433a289941SAaron LI /*
12443a289941SAaron LI * Yes, return it.
12453a289941SAaron LI */
12463a289941SAaron LI return (curdev);
12473a289941SAaron LI }
12483a289941SAaron LI
12493a289941SAaron LI /*
12503a289941SAaron LI * No, we didn't find it.
12513a289941SAaron LI */
12523a289941SAaron LI
12533a289941SAaron LI /*
12543a289941SAaron LI * Try to get additional flags for the device.
12553a289941SAaron LI */
12563a289941SAaron LI if ((*get_flags_func)(name, &flags, errbuf) == -1) {
12573a289941SAaron LI /*
12583a289941SAaron LI * Failed.
12593a289941SAaron LI */
12603a289941SAaron LI return (NULL);
12613a289941SAaron LI }
12623a289941SAaron LI
12633a289941SAaron LI /*
12643a289941SAaron LI * Now, try to add it to the list of devices.
12653a289941SAaron LI */
12663a289941SAaron LI return (add_dev(devlistp, name, flags, description, errbuf));
12673a289941SAaron LI }
12683a289941SAaron LI
12693a289941SAaron LI /*
12703a289941SAaron LI * Look for a given device in the specified list of devices, and return
12713a289941SAaron LI * the entry for it if we find it or NULL if we don't.
12723a289941SAaron LI */
12733a289941SAaron LI pcap_if_t *
12743a289941SAaron LI find_dev(pcap_if_list_t *devlistp, const char *name)
12753a289941SAaron LI {
12763a289941SAaron LI pcap_if_t *curdev;
12773a289941SAaron LI
12783a289941SAaron LI /*
12793a289941SAaron LI * Is there an entry in the list for this device?
12803a289941SAaron LI */
12813a289941SAaron LI for (curdev = devlistp->beginning; curdev != NULL;
12823a289941SAaron LI curdev = curdev->next) {
12833a289941SAaron LI if (strcmp(name, curdev->name) == 0) {
12843a289941SAaron LI /*
12853a289941SAaron LI * We found it, so, yes, there is. No need to
12863a289941SAaron LI * add it. Provide the entry we found to our
12873a289941SAaron LI * caller.
12883a289941SAaron LI */
12893a289941SAaron LI return (curdev);
12903a289941SAaron LI }
12913a289941SAaron LI }
12923a289941SAaron LI
12933a289941SAaron LI /*
12943a289941SAaron LI * No.
12953a289941SAaron LI */
12963a289941SAaron LI return (NULL);
12973a289941SAaron LI }
12983a289941SAaron LI
12993a289941SAaron LI /*
13003a289941SAaron LI * Attempt to add an entry for a device, with the specified flags
13013a289941SAaron LI * and description, and, if that succeeds, return 0 and return a pointer
13023a289941SAaron LI * to the new entry, otherwise return NULL and set errbuf to an error
13033a289941SAaron LI * message.
13043a289941SAaron LI *
13053a289941SAaron LI * If we weren't given a description, try to get one.
13063a289941SAaron LI */
13073a289941SAaron LI pcap_if_t *
13083a289941SAaron LI add_dev(pcap_if_list_t *devlistp, const char *name, bpf_u_int32 flags,
13093a289941SAaron LI const char *description, char *errbuf)
13103a289941SAaron LI {
13113a289941SAaron LI pcap_if_t *curdev, *prevdev, *nextdev;
13123a289941SAaron LI u_int this_figure_of_merit, nextdev_figure_of_merit;
13133a289941SAaron LI
13143a289941SAaron LI curdev = malloc(sizeof(pcap_if_t));
13153a289941SAaron LI if (curdev == NULL) {
13163a289941SAaron LI pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
13173a289941SAaron LI errno, "malloc");
13183a289941SAaron LI return (NULL);
13193a289941SAaron LI }
13203a289941SAaron LI
13213a289941SAaron LI /*
13223a289941SAaron LI * Fill in the entry.
13233a289941SAaron LI */
13243a289941SAaron LI curdev->next = NULL;
13253a289941SAaron LI curdev->name = strdup(name);
13263a289941SAaron LI if (curdev->name == NULL) {
13273a289941SAaron LI pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
13283a289941SAaron LI errno, "malloc");
13293a289941SAaron LI free(curdev);
13303a289941SAaron LI return (NULL);
13313a289941SAaron LI }
13323a289941SAaron LI if (description == NULL) {
13333a289941SAaron LI /*
13343a289941SAaron LI * We weren't handed a description for the interface.
13353a289941SAaron LI */
13363a289941SAaron LI curdev->description = NULL;
13373a289941SAaron LI } else {
13383a289941SAaron LI /*
13393a289941SAaron LI * We were handed a description; make a copy.
13403a289941SAaron LI */
13413a289941SAaron LI curdev->description = strdup(description);
13423a289941SAaron LI if (curdev->description == NULL) {
13433a289941SAaron LI pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
13443a289941SAaron LI errno, "malloc");
13453a289941SAaron LI free(curdev->name);
13463a289941SAaron LI free(curdev);
13473a289941SAaron LI return (NULL);
13483a289941SAaron LI }
13493a289941SAaron LI }
13503a289941SAaron LI curdev->addresses = NULL; /* list starts out as empty */
13513a289941SAaron LI curdev->flags = flags;
13523a289941SAaron LI
13533a289941SAaron LI /*
13543a289941SAaron LI * Add it to the list, in the appropriate location.
13553a289941SAaron LI * First, get the "figure of merit" for this interface.
13563a289941SAaron LI */
13573a289941SAaron LI this_figure_of_merit = get_figure_of_merit(curdev);
13583a289941SAaron LI
13593a289941SAaron LI /*
13603a289941SAaron LI * Now look for the last interface with an figure of merit
13613a289941SAaron LI * less than or equal to the new interface's figure of merit.
13623a289941SAaron LI *
13633a289941SAaron LI * We start with "prevdev" being NULL, meaning we're before
13643a289941SAaron LI * the first element in the list.
13653a289941SAaron LI */
13663a289941SAaron LI prevdev = NULL;
13673a289941SAaron LI for (;;) {
13683a289941SAaron LI /*
13693a289941SAaron LI * Get the interface after this one.
13703a289941SAaron LI */
13713a289941SAaron LI if (prevdev == NULL) {
13723a289941SAaron LI /*
13733a289941SAaron LI * The next element is the first element.
13743a289941SAaron LI */
13753a289941SAaron LI nextdev = devlistp->beginning;
13763a289941SAaron LI } else
13773a289941SAaron LI nextdev = prevdev->next;
13783a289941SAaron LI
13793a289941SAaron LI /*
13803a289941SAaron LI * Are we at the end of the list?
13813a289941SAaron LI */
13823a289941SAaron LI if (nextdev == NULL) {
13833a289941SAaron LI /*
13843a289941SAaron LI * Yes - we have to put the new entry after "prevdev".
13853a289941SAaron LI */
13863a289941SAaron LI break;
13873a289941SAaron LI }
13883a289941SAaron LI
13893a289941SAaron LI /*
13903a289941SAaron LI * Is the new interface's figure of merit less
13913a289941SAaron LI * than the next interface's figure of merit,
13923a289941SAaron LI * meaning that the new interface is better
13933a289941SAaron LI * than the next interface?
13943a289941SAaron LI */
13953a289941SAaron LI nextdev_figure_of_merit = get_figure_of_merit(nextdev);
13963a289941SAaron LI if (this_figure_of_merit < nextdev_figure_of_merit) {
13973a289941SAaron LI /*
13983a289941SAaron LI * Yes - we should put the new entry
13993a289941SAaron LI * before "nextdev", i.e. after "prevdev".
14003a289941SAaron LI */
14013a289941SAaron LI break;
14023a289941SAaron LI }
14033a289941SAaron LI
14043a289941SAaron LI prevdev = nextdev;
14053a289941SAaron LI }
14063a289941SAaron LI
14073a289941SAaron LI /*
14083a289941SAaron LI * Insert before "nextdev".
14093a289941SAaron LI */
14103a289941SAaron LI curdev->next = nextdev;
14113a289941SAaron LI
14123a289941SAaron LI /*
14133a289941SAaron LI * Insert after "prevdev" - unless "prevdev" is null,
14143a289941SAaron LI * in which case this is the first interface.
14153a289941SAaron LI */
14163a289941SAaron LI if (prevdev == NULL) {
14173a289941SAaron LI /*
14183a289941SAaron LI * This is the first interface. Make it
14193a289941SAaron LI * the first element in the list of devices.
14203a289941SAaron LI */
14213a289941SAaron LI devlistp->beginning = curdev;
14223a289941SAaron LI } else
14233a289941SAaron LI prevdev->next = curdev;
14243a289941SAaron LI return (curdev);
14253a289941SAaron LI }
14263a289941SAaron LI
14273a289941SAaron LI /*
14283a289941SAaron LI * Free a list of interfaces.
14293a289941SAaron LI */
14303a289941SAaron LI void
14313a289941SAaron LI pcap_freealldevs(pcap_if_t *alldevs)
14323a289941SAaron LI {
14333a289941SAaron LI pcap_if_t *curdev, *nextdev;
14343a289941SAaron LI pcap_addr_t *curaddr, *nextaddr;
14353a289941SAaron LI
14363a289941SAaron LI for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
14373a289941SAaron LI nextdev = curdev->next;
14383a289941SAaron LI
14393a289941SAaron LI /*
14403a289941SAaron LI * Free all addresses.
14413a289941SAaron LI */
14423a289941SAaron LI for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
14433a289941SAaron LI nextaddr = curaddr->next;
14443a289941SAaron LI if (curaddr->addr)
14453a289941SAaron LI free(curaddr->addr);
14463a289941SAaron LI if (curaddr->netmask)
14473a289941SAaron LI free(curaddr->netmask);
14483a289941SAaron LI if (curaddr->broadaddr)
14493a289941SAaron LI free(curaddr->broadaddr);
14503a289941SAaron LI if (curaddr->dstaddr)
14513a289941SAaron LI free(curaddr->dstaddr);
14523a289941SAaron LI free(curaddr);
14533a289941SAaron LI }
14543a289941SAaron LI
14553a289941SAaron LI /*
14563a289941SAaron LI * Free the name string.
14573a289941SAaron LI */
14583a289941SAaron LI free(curdev->name);
14593a289941SAaron LI
14603a289941SAaron LI /*
14613a289941SAaron LI * Free the description string, if any.
14623a289941SAaron LI */
14633a289941SAaron LI if (curdev->description != NULL)
14643a289941SAaron LI free(curdev->description);
14653a289941SAaron LI
14663a289941SAaron LI /*
14673a289941SAaron LI * Free the interface.
14683a289941SAaron LI */
14693a289941SAaron LI free(curdev);
14703a289941SAaron LI }
14713a289941SAaron LI }
14723a289941SAaron LI
14733a289941SAaron LI /*
14743a289941SAaron LI * pcap-npf.c has its own pcap_lookupdev(), for compatibility reasons, as
14753a289941SAaron LI * it actually returns the names of all interfaces, with a NUL separator
14763a289941SAaron LI * between them; some callers may depend on that.
14773a289941SAaron LI *
14783a289941SAaron LI * MS-DOS has its own pcap_lookupdev(), but that might be useful only
14793a289941SAaron LI * as an optimization.
14803a289941SAaron LI *
14813a289941SAaron LI * In all other cases, we just use pcap_findalldevs() to get a list of
14823a289941SAaron LI * devices, and pick from that list.
14833a289941SAaron LI */
14843a289941SAaron LI #if !defined(HAVE_PACKET32) && !defined(MSDOS)
14853a289941SAaron LI /*
14863a289941SAaron LI * Return the name of a network interface attached to the system, or NULL
14873a289941SAaron LI * if none can be found. The interface must be configured up; the
14883a289941SAaron LI * lowest unit number is preferred; loopback is ignored.
14893a289941SAaron LI */
14903a289941SAaron LI char *
14913a289941SAaron LI pcap_lookupdev(char *errbuf)
14923a289941SAaron LI {
14933a289941SAaron LI pcap_if_t *alldevs;
14943a289941SAaron LI #ifdef _WIN32
14953a289941SAaron LI /*
14963a289941SAaron LI * Windows - use the same size as the old WinPcap 3.1 code.
14973a289941SAaron LI * XXX - this is probably bigger than it needs to be.
14983a289941SAaron LI */
14993a289941SAaron LI #define IF_NAMESIZE 8192
15003a289941SAaron LI #else
15013a289941SAaron LI /*
15023a289941SAaron LI * UN*X - use the system's interface name size.
15033a289941SAaron LI * XXX - that might not be large enough for capture devices
15043a289941SAaron LI * that aren't regular network interfaces.
15053a289941SAaron LI */
15063a289941SAaron LI /* for old BSD systems, including bsdi3 */
15073a289941SAaron LI #ifndef IF_NAMESIZE
15083a289941SAaron LI #define IF_NAMESIZE IFNAMSIZ
15093a289941SAaron LI #endif
15103a289941SAaron LI #endif
15113a289941SAaron LI static char device[IF_NAMESIZE + 1];
15123a289941SAaron LI char *ret;
15133a289941SAaron LI
1514*ea16f64eSAntonio Huete Jimenez /*
1515*ea16f64eSAntonio Huete Jimenez * We disable this in "new API" mode, because 1) in WinPcap/Npcap,
1516*ea16f64eSAntonio Huete Jimenez * it may return UTF-16 strings, for backwards-compatibility
1517*ea16f64eSAntonio Huete Jimenez * reasons, and we're also disabling the hack to make that work,
1518*ea16f64eSAntonio Huete Jimenez * for not-going-past-the-end-of-a-string reasons, and 2) we
1519*ea16f64eSAntonio Huete Jimenez * want its behavior to be consistent.
1520*ea16f64eSAntonio Huete Jimenez *
1521*ea16f64eSAntonio Huete Jimenez * In addition, it's not thread-safe, so we've marked it as
1522*ea16f64eSAntonio Huete Jimenez * deprecated.
1523*ea16f64eSAntonio Huete Jimenez */
1524*ea16f64eSAntonio Huete Jimenez if (pcap_new_api) {
1525*ea16f64eSAntonio Huete Jimenez snprintf(errbuf, PCAP_ERRBUF_SIZE,
1526*ea16f64eSAntonio Huete Jimenez "pcap_lookupdev() is deprecated and is not supported in programs calling pcap_init()");
1527*ea16f64eSAntonio Huete Jimenez return (NULL);
1528*ea16f64eSAntonio Huete Jimenez }
1529*ea16f64eSAntonio Huete Jimenez
15303a289941SAaron LI if (pcap_findalldevs(&alldevs, errbuf) == -1)
15313a289941SAaron LI return (NULL);
15323a289941SAaron LI
15333a289941SAaron LI if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
15343a289941SAaron LI /*
15353a289941SAaron LI * There are no devices on the list, or the first device
15363a289941SAaron LI * on the list is a loopback device, which means there
15373a289941SAaron LI * are no non-loopback devices on the list. This means
15383a289941SAaron LI * we can't return any device.
15393a289941SAaron LI *
15403a289941SAaron LI * XXX - why not return a loopback device? If we can't
15413a289941SAaron LI * capture on it, it won't be on the list, and if it's
15423a289941SAaron LI * on the list, there aren't any non-loopback devices,
15433a289941SAaron LI * so why not just supply it as the default device?
15443a289941SAaron LI */
15453a289941SAaron LI (void)pcap_strlcpy(errbuf, "no suitable device found",
15463a289941SAaron LI PCAP_ERRBUF_SIZE);
15473a289941SAaron LI ret = NULL;
15483a289941SAaron LI } else {
15493a289941SAaron LI /*
15503a289941SAaron LI * Return the name of the first device on the list.
15513a289941SAaron LI */
15523a289941SAaron LI (void)pcap_strlcpy(device, alldevs->name, sizeof(device));
15533a289941SAaron LI ret = device;
15543a289941SAaron LI }
15553a289941SAaron LI
15563a289941SAaron LI pcap_freealldevs(alldevs);
15573a289941SAaron LI return (ret);
15583a289941SAaron LI }
15593a289941SAaron LI #endif /* !defined(HAVE_PACKET32) && !defined(MSDOS) */
15603a289941SAaron LI
15613a289941SAaron LI #if !defined(_WIN32) && !defined(MSDOS)
15623a289941SAaron LI /*
15633a289941SAaron LI * We don't just fetch the entire list of devices, search for the
15643a289941SAaron LI * particular device, and use its first IPv4 address, as that's too
15653a289941SAaron LI * much work to get just one device's netmask.
15663a289941SAaron LI *
15673a289941SAaron LI * If we had an API to get attributes for a given device, we could
15683a289941SAaron LI * use that.
15693a289941SAaron LI */
15703a289941SAaron LI int
15713a289941SAaron LI pcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp,
15723a289941SAaron LI char *errbuf)
15733a289941SAaron LI {
15743a289941SAaron LI register int fd;
15753a289941SAaron LI register struct sockaddr_in *sin4;
15763a289941SAaron LI struct ifreq ifr;
15773a289941SAaron LI
15783a289941SAaron LI /*
15793a289941SAaron LI * The pseudo-device "any" listens on all interfaces and therefore
15803a289941SAaron LI * has the network address and -mask "0.0.0.0" therefore catching
15813a289941SAaron LI * all traffic. Using NULL for the interface is the same as "any".
15823a289941SAaron LI */
15833a289941SAaron LI if (!device || strcmp(device, "any") == 0
15843a289941SAaron LI #ifdef HAVE_DAG_API
15853a289941SAaron LI || strstr(device, "dag") != NULL
15863a289941SAaron LI #endif
15873a289941SAaron LI #ifdef HAVE_SEPTEL_API
15883a289941SAaron LI || strstr(device, "septel") != NULL
15893a289941SAaron LI #endif
15903a289941SAaron LI #ifdef PCAP_SUPPORT_BT
15913a289941SAaron LI || strstr(device, "bluetooth") != NULL
15923a289941SAaron LI #endif
1593*ea16f64eSAntonio Huete Jimenez #ifdef PCAP_SUPPORT_LINUX_USBMON
15943a289941SAaron LI || strstr(device, "usbmon") != NULL
15953a289941SAaron LI #endif
15963a289941SAaron LI #ifdef HAVE_SNF_API
15973a289941SAaron LI || strstr(device, "snf") != NULL
15983a289941SAaron LI #endif
15993a289941SAaron LI #ifdef PCAP_SUPPORT_NETMAP
16003a289941SAaron LI || strncmp(device, "netmap:", 7) == 0
16013a289941SAaron LI || strncmp(device, "vale", 4) == 0
16023a289941SAaron LI #endif
1603*ea16f64eSAntonio Huete Jimenez #ifdef PCAP_SUPPORT_DPDK
1604*ea16f64eSAntonio Huete Jimenez || strncmp(device, "dpdk:", 5) == 0
1605*ea16f64eSAntonio Huete Jimenez #endif
16063a289941SAaron LI ) {
16073a289941SAaron LI *netp = *maskp = 0;
16083a289941SAaron LI return 0;
16093a289941SAaron LI }
16103a289941SAaron LI
16113a289941SAaron LI fd = socket(AF_INET, SOCK_DGRAM, 0);
16123a289941SAaron LI if (fd < 0) {
16133a289941SAaron LI pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
16143a289941SAaron LI errno, "socket");
16153a289941SAaron LI return (-1);
16163a289941SAaron LI }
16173a289941SAaron LI memset(&ifr, 0, sizeof(ifr));
16183a289941SAaron LI #ifdef linux
16193a289941SAaron LI /* XXX Work around Linux kernel bug */
16203a289941SAaron LI ifr.ifr_addr.sa_family = AF_INET;
16213a289941SAaron LI #endif
16223a289941SAaron LI (void)pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
16233a289941SAaron LI if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
16243a289941SAaron LI if (errno == EADDRNOTAVAIL) {
1625*ea16f64eSAntonio Huete Jimenez (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
16263a289941SAaron LI "%s: no IPv4 address assigned", device);
16273a289941SAaron LI } else {
16283a289941SAaron LI pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
16293a289941SAaron LI errno, "SIOCGIFADDR: %s", device);
16303a289941SAaron LI }
16313a289941SAaron LI (void)close(fd);
16323a289941SAaron LI return (-1);
16333a289941SAaron LI }
16343a289941SAaron LI sin4 = (struct sockaddr_in *)&ifr.ifr_addr;
16353a289941SAaron LI *netp = sin4->sin_addr.s_addr;
16363a289941SAaron LI memset(&ifr, 0, sizeof(ifr));
16373a289941SAaron LI #ifdef linux
16383a289941SAaron LI /* XXX Work around Linux kernel bug */
16393a289941SAaron LI ifr.ifr_addr.sa_family = AF_INET;
16403a289941SAaron LI #endif
16413a289941SAaron LI (void)pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
16423a289941SAaron LI if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
16433a289941SAaron LI pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
16443a289941SAaron LI errno, "SIOCGIFNETMASK: %s", device);
16453a289941SAaron LI (void)close(fd);
16463a289941SAaron LI return (-1);
16473a289941SAaron LI }
16483a289941SAaron LI (void)close(fd);
16493a289941SAaron LI *maskp = sin4->sin_addr.s_addr;
16503a289941SAaron LI if (*maskp == 0) {
16513a289941SAaron LI if (IN_CLASSA(*netp))
16523a289941SAaron LI *maskp = IN_CLASSA_NET;
16533a289941SAaron LI else if (IN_CLASSB(*netp))
16543a289941SAaron LI *maskp = IN_CLASSB_NET;
16553a289941SAaron LI else if (IN_CLASSC(*netp))
16563a289941SAaron LI *maskp = IN_CLASSC_NET;
16573a289941SAaron LI else {
1658*ea16f64eSAntonio Huete Jimenez (void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
16593a289941SAaron LI "inet class for 0x%x unknown", *netp);
16603a289941SAaron LI return (-1);
16613a289941SAaron LI }
16623a289941SAaron LI }
16633a289941SAaron LI *netp &= *maskp;
16643a289941SAaron LI return (0);
16653a289941SAaron LI }
16663a289941SAaron LI #endif /* !defined(_WIN32) && !defined(MSDOS) */
16673a289941SAaron LI
16683a289941SAaron LI #ifdef ENABLE_REMOTE
16693a289941SAaron LI #include "pcap-rpcap.h"
16703a289941SAaron LI
16713a289941SAaron LI /*
16723a289941SAaron LI * Extract a substring from a string.
16733a289941SAaron LI */
16743a289941SAaron LI static char *
16753a289941SAaron LI get_substring(const char *p, size_t len, char *ebuf)
16763a289941SAaron LI {
16773a289941SAaron LI char *token;
16783a289941SAaron LI
16793a289941SAaron LI token = malloc(len + 1);
16803a289941SAaron LI if (token == NULL) {
16813a289941SAaron LI pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
16823a289941SAaron LI errno, "malloc");
16833a289941SAaron LI return (NULL);
16843a289941SAaron LI }
16853a289941SAaron LI memcpy(token, p, len);
16863a289941SAaron LI token[len] = '\0';
16873a289941SAaron LI return (token);
16883a289941SAaron LI }
16893a289941SAaron LI
16903a289941SAaron LI /*
16913a289941SAaron LI * Parse a capture source that might be a URL.
16923a289941SAaron LI *
16933a289941SAaron LI * If the source is not a URL, *schemep, *userinfop, *hostp, and *portp
16943a289941SAaron LI * are set to NULL, *pathp is set to point to the source, and 0 is
16953a289941SAaron LI * returned.
16963a289941SAaron LI *
16973a289941SAaron LI * If source is a URL, and the URL refers to a local device (a special
16983a289941SAaron LI * case of rpcap:), *schemep, *userinfop, *hostp, and *portp are set
16993a289941SAaron LI * to NULL, *pathp is set to point to the device name, and 0 is returned.
17003a289941SAaron LI *
17013a289941SAaron LI * If source is a URL, and it's not a special case that refers to a local
17023a289941SAaron LI * device, and the parse succeeds:
17033a289941SAaron LI *
17043a289941SAaron LI * *schemep is set to point to an allocated string containing the scheme;
17053a289941SAaron LI *
17063a289941SAaron LI * if user information is present in the URL, *userinfop is set to point
17073a289941SAaron LI * to an allocated string containing the user information, otherwise
17083a289941SAaron LI * it's set to NULL;
17093a289941SAaron LI *
17103a289941SAaron LI * if host information is present in the URL, *hostp is set to point
17113a289941SAaron LI * to an allocated string containing the host information, otherwise
17123a289941SAaron LI * it's set to NULL;
17133a289941SAaron LI *
17143a289941SAaron LI * if a port number is present in the URL, *portp is set to point
17153a289941SAaron LI * to an allocated string containing the port number, otherwise
17163a289941SAaron LI * it's set to NULL;
17173a289941SAaron LI *
17183a289941SAaron LI * *pathp is set to point to an allocated string containing the
17193a289941SAaron LI * path;
17203a289941SAaron LI *
17213a289941SAaron LI * and 0 is returned.
17223a289941SAaron LI *
17233a289941SAaron LI * If the parse fails, ebuf is set to an error string, and -1 is returned.
17243a289941SAaron LI */
17253a289941SAaron LI static int
17263a289941SAaron LI pcap_parse_source(const char *source, char **schemep, char **userinfop,
17273a289941SAaron LI char **hostp, char **portp, char **pathp, char *ebuf)
17283a289941SAaron LI {
17293a289941SAaron LI char *colonp;
17303a289941SAaron LI size_t scheme_len;
17313a289941SAaron LI char *scheme;
17323a289941SAaron LI const char *endp;
17333a289941SAaron LI size_t authority_len;
17343a289941SAaron LI char *authority;
17353a289941SAaron LI char *parsep, *atsignp, *bracketp;
17363a289941SAaron LI char *userinfo, *host, *port, *path;
17373a289941SAaron LI
17383a289941SAaron LI /*
17393a289941SAaron LI * Start out returning nothing.
17403a289941SAaron LI */
17413a289941SAaron LI *schemep = NULL;
17423a289941SAaron LI *userinfop = NULL;
17433a289941SAaron LI *hostp = NULL;
17443a289941SAaron LI *portp = NULL;
17453a289941SAaron LI *pathp = NULL;
17463a289941SAaron LI
17473a289941SAaron LI /*
17483a289941SAaron LI * RFC 3986 says:
17493a289941SAaron LI *
17503a289941SAaron LI * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
17513a289941SAaron LI *
17523a289941SAaron LI * hier-part = "//" authority path-abempty
17533a289941SAaron LI * / path-absolute
17543a289941SAaron LI * / path-rootless
17553a289941SAaron LI * / path-empty
17563a289941SAaron LI *
17573a289941SAaron LI * authority = [ userinfo "@" ] host [ ":" port ]
17583a289941SAaron LI *
17593a289941SAaron LI * userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
17603a289941SAaron LI *
17613a289941SAaron LI * Step 1: look for the ":" at the end of the scheme.
17623a289941SAaron LI * A colon in the source is *NOT* sufficient to indicate that
17633a289941SAaron LI * this is a URL, as interface names on some platforms might
17643a289941SAaron LI * include colons (e.g., I think some Solaris interfaces
17653a289941SAaron LI * might).
17663a289941SAaron LI */
17673a289941SAaron LI colonp = strchr(source, ':');
17683a289941SAaron LI if (colonp == NULL) {
17693a289941SAaron LI /*
17703a289941SAaron LI * The source is the device to open.
17713a289941SAaron LI * Return a NULL pointer for the scheme, user information,
17723a289941SAaron LI * host, and port, and return the device as the path.
17733a289941SAaron LI */
17743a289941SAaron LI *pathp = strdup(source);
17753a289941SAaron LI if (*pathp == NULL) {
17763a289941SAaron LI pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
17773a289941SAaron LI errno, "malloc");
17783a289941SAaron LI return (-1);
17793a289941SAaron LI }
17803a289941SAaron LI return (0);
17813a289941SAaron LI }
17823a289941SAaron LI
17833a289941SAaron LI /*
17843a289941SAaron LI * All schemes must have "//" after them, i.e. we only support
17853a289941SAaron LI * hier-part = "//" authority path-abempty, not
17863a289941SAaron LI * hier-part = path-absolute
17873a289941SAaron LI * hier-part = path-rootless
17883a289941SAaron LI * hier-part = path-empty
17893a289941SAaron LI *
17903a289941SAaron LI * We need that in order to distinguish between a local device
17913a289941SAaron LI * name that happens to contain a colon and a URI.
17923a289941SAaron LI */
17933a289941SAaron LI if (strncmp(colonp + 1, "//", 2) != 0) {
17943a289941SAaron LI /*
17953a289941SAaron LI * The source is the device to open.
17963a289941SAaron LI * Return a NULL pointer for the scheme, user information,
17973a289941SAaron LI * host, and port, and return the device as the path.
17983a289941SAaron LI */
17993a289941SAaron LI *pathp = strdup(source);
18003a289941SAaron LI if (*pathp == NULL) {
18013a289941SAaron LI pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
18023a289941SAaron LI errno, "malloc");
18033a289941SAaron LI return (-1);
18043a289941SAaron LI }
18053a289941SAaron LI return (0);
18063a289941SAaron LI }
18073a289941SAaron LI
18083a289941SAaron LI /*
18093a289941SAaron LI * XXX - check whether the purported scheme could be a scheme?
18103a289941SAaron LI */
18113a289941SAaron LI
18123a289941SAaron LI /*
18133a289941SAaron LI * OK, this looks like a URL.
18143a289941SAaron LI * Get the scheme.
18153a289941SAaron LI */
18163a289941SAaron LI scheme_len = colonp - source;
18173a289941SAaron LI scheme = malloc(scheme_len + 1);
18183a289941SAaron LI if (scheme == NULL) {
18193a289941SAaron LI pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
18203a289941SAaron LI errno, "malloc");
18213a289941SAaron LI return (-1);
18223a289941SAaron LI }
18233a289941SAaron LI memcpy(scheme, source, scheme_len);
18243a289941SAaron LI scheme[scheme_len] = '\0';
18253a289941SAaron LI
18263a289941SAaron LI /*
18273a289941SAaron LI * Treat file: specially - take everything after file:// as
18283a289941SAaron LI * the pathname.
18293a289941SAaron LI */
18303a289941SAaron LI if (pcap_strcasecmp(scheme, "file") == 0) {
18313a289941SAaron LI *pathp = strdup(colonp + 3);
18323a289941SAaron LI if (*pathp == NULL) {
18333a289941SAaron LI pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
18343a289941SAaron LI errno, "malloc");
18353a289941SAaron LI free(scheme);
18363a289941SAaron LI return (-1);
18373a289941SAaron LI }
18383a289941SAaron LI *schemep = scheme;
18393a289941SAaron LI return (0);
18403a289941SAaron LI }
18413a289941SAaron LI
18423a289941SAaron LI /*
18433a289941SAaron LI * The WinPcap documentation says you can specify a local
18443a289941SAaron LI * interface with "rpcap://{device}"; we special-case
18453a289941SAaron LI * that here. If the scheme is "rpcap", and there are
18463a289941SAaron LI * no slashes past the "//", we just return the device.
18473a289941SAaron LI *
18483a289941SAaron LI * XXX - %-escaping?
18493a289941SAaron LI */
1850*ea16f64eSAntonio Huete Jimenez if ((pcap_strcasecmp(scheme, "rpcap") == 0 ||
1851*ea16f64eSAntonio Huete Jimenez pcap_strcasecmp(scheme, "rpcaps") == 0) &&
18523a289941SAaron LI strchr(colonp + 3, '/') == NULL) {
18533a289941SAaron LI /*
18543a289941SAaron LI * Local device.
18553a289941SAaron LI *
18563a289941SAaron LI * Return a NULL pointer for the scheme, user information,
18573a289941SAaron LI * host, and port, and return the device as the path.
18583a289941SAaron LI */
18593a289941SAaron LI free(scheme);
18603a289941SAaron LI *pathp = strdup(colonp + 3);
18613a289941SAaron LI if (*pathp == NULL) {
18623a289941SAaron LI pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
18633a289941SAaron LI errno, "malloc");
18643a289941SAaron LI return (-1);
18653a289941SAaron LI }
18663a289941SAaron LI return (0);
18673a289941SAaron LI }
18683a289941SAaron LI
18693a289941SAaron LI /*
18703a289941SAaron LI * OK, now start parsing the authority.
18713a289941SAaron LI * Get token, terminated with / or terminated at the end of
18723a289941SAaron LI * the string.
18733a289941SAaron LI */
18743a289941SAaron LI authority_len = strcspn(colonp + 3, "/");
18753a289941SAaron LI authority = get_substring(colonp + 3, authority_len, ebuf);
18763a289941SAaron LI if (authority == NULL) {
18773a289941SAaron LI /*
18783a289941SAaron LI * Error.
18793a289941SAaron LI */
18803a289941SAaron LI free(scheme);
18813a289941SAaron LI return (-1);
18823a289941SAaron LI }
18833a289941SAaron LI endp = colonp + 3 + authority_len;
18843a289941SAaron LI
18853a289941SAaron LI /*
18863a289941SAaron LI * Now carve the authority field into its components.
18873a289941SAaron LI */
18883a289941SAaron LI parsep = authority;
18893a289941SAaron LI
18903a289941SAaron LI /*
18913a289941SAaron LI * Is there a userinfo field?
18923a289941SAaron LI */
18933a289941SAaron LI atsignp = strchr(parsep, '@');
18943a289941SAaron LI if (atsignp != NULL) {
18953a289941SAaron LI /*
18963a289941SAaron LI * Yes.
18973a289941SAaron LI */
18983a289941SAaron LI size_t userinfo_len;
18993a289941SAaron LI
19003a289941SAaron LI userinfo_len = atsignp - parsep;
19013a289941SAaron LI userinfo = get_substring(parsep, userinfo_len, ebuf);
19023a289941SAaron LI if (userinfo == NULL) {
19033a289941SAaron LI /*
19043a289941SAaron LI * Error.
19053a289941SAaron LI */
19063a289941SAaron LI free(authority);
19073a289941SAaron LI free(scheme);
19083a289941SAaron LI return (-1);
19093a289941SAaron LI }
19103a289941SAaron LI parsep = atsignp + 1;
19113a289941SAaron LI } else {
19123a289941SAaron LI /*
19133a289941SAaron LI * No.
19143a289941SAaron LI */
19153a289941SAaron LI userinfo = NULL;
19163a289941SAaron LI }
19173a289941SAaron LI
19183a289941SAaron LI /*
19193a289941SAaron LI * Is there a host field?
19203a289941SAaron LI */
19213a289941SAaron LI if (*parsep == '\0') {
19223a289941SAaron LI /*
19233a289941SAaron LI * No; there's no host field or port field.
19243a289941SAaron LI */
19253a289941SAaron LI host = NULL;
19263a289941SAaron LI port = NULL;
19273a289941SAaron LI } else {
19283a289941SAaron LI /*
19293a289941SAaron LI * Yes.
19303a289941SAaron LI */
19313a289941SAaron LI size_t host_len;
19323a289941SAaron LI
19333a289941SAaron LI /*
19343a289941SAaron LI * Is it an IP-literal?
19353a289941SAaron LI */
19363a289941SAaron LI if (*parsep == '[') {
19373a289941SAaron LI /*
19383a289941SAaron LI * Yes.
19393a289941SAaron LI * Treat verything up to the closing square
19403a289941SAaron LI * bracket as the IP-Literal; we don't worry
19413a289941SAaron LI * about whether it's a valid IPv6address or
19423a289941SAaron LI * IPvFuture (or an IPv4address, for that
19433a289941SAaron LI * matter, just in case we get handed a
19443a289941SAaron LI * URL with an IPv4 IP-Literal, of the sort
19453a289941SAaron LI * that pcap_createsrcstr() used to generate,
19463a289941SAaron LI * and that pcap_parsesrcstr(), in the original
19473a289941SAaron LI * WinPcap code, accepted).
19483a289941SAaron LI */
19493a289941SAaron LI bracketp = strchr(parsep, ']');
19503a289941SAaron LI if (bracketp == NULL) {
19513a289941SAaron LI /*
19523a289941SAaron LI * There's no closing square bracket.
19533a289941SAaron LI */
1954*ea16f64eSAntonio Huete Jimenez snprintf(ebuf, PCAP_ERRBUF_SIZE,
19553a289941SAaron LI "IP-literal in URL doesn't end with ]");
19563a289941SAaron LI free(userinfo);
19573a289941SAaron LI free(authority);
19583a289941SAaron LI free(scheme);
19593a289941SAaron LI return (-1);
19603a289941SAaron LI }
19613a289941SAaron LI if (*(bracketp + 1) != '\0' &&
19623a289941SAaron LI *(bracketp + 1) != ':') {
19633a289941SAaron LI /*
19643a289941SAaron LI * There's extra crud after the
19653a289941SAaron LI * closing square bracketn.
19663a289941SAaron LI */
1967*ea16f64eSAntonio Huete Jimenez snprintf(ebuf, PCAP_ERRBUF_SIZE,
19683a289941SAaron LI "Extra text after IP-literal in URL");
19693a289941SAaron LI free(userinfo);
19703a289941SAaron LI free(authority);
19713a289941SAaron LI free(scheme);
19723a289941SAaron LI return (-1);
19733a289941SAaron LI }
19743a289941SAaron LI host_len = (bracketp - 1) - parsep;
19753a289941SAaron LI host = get_substring(parsep + 1, host_len, ebuf);
19763a289941SAaron LI if (host == NULL) {
19773a289941SAaron LI /*
19783a289941SAaron LI * Error.
19793a289941SAaron LI */
19803a289941SAaron LI free(userinfo);
19813a289941SAaron LI free(authority);
19823a289941SAaron LI free(scheme);
19833a289941SAaron LI return (-1);
19843a289941SAaron LI }
19853a289941SAaron LI parsep = bracketp + 1;
19863a289941SAaron LI } else {
19873a289941SAaron LI /*
19883a289941SAaron LI * No.
19893a289941SAaron LI * Treat everything up to a : or the end of
19903a289941SAaron LI * the string as the host.
19913a289941SAaron LI */
19923a289941SAaron LI host_len = strcspn(parsep, ":");
19933a289941SAaron LI host = get_substring(parsep, host_len, ebuf);
19943a289941SAaron LI if (host == NULL) {
19953a289941SAaron LI /*
19963a289941SAaron LI * Error.
19973a289941SAaron LI */
19983a289941SAaron LI free(userinfo);
19993a289941SAaron LI free(authority);
20003a289941SAaron LI free(scheme);
20013a289941SAaron LI return (-1);
20023a289941SAaron LI }
20033a289941SAaron LI parsep = parsep + host_len;
20043a289941SAaron LI }
20053a289941SAaron LI
20063a289941SAaron LI /*
20073a289941SAaron LI * Is there a port field?
20083a289941SAaron LI */
20093a289941SAaron LI if (*parsep == ':') {
20103a289941SAaron LI /*
20113a289941SAaron LI * Yes. It's the rest of the authority field.
20123a289941SAaron LI */
20133a289941SAaron LI size_t port_len;
20143a289941SAaron LI
20153a289941SAaron LI parsep++;
20163a289941SAaron LI port_len = strlen(parsep);
20173a289941SAaron LI port = get_substring(parsep, port_len, ebuf);
20183a289941SAaron LI if (port == NULL) {
20193a289941SAaron LI /*
20203a289941SAaron LI * Error.
20213a289941SAaron LI */
20223a289941SAaron LI free(host);
20233a289941SAaron LI free(userinfo);
20243a289941SAaron LI free(authority);
20253a289941SAaron LI free(scheme);
20263a289941SAaron LI return (-1);
20273a289941SAaron LI }
20283a289941SAaron LI } else {
20293a289941SAaron LI /*
20303a289941SAaron LI * No.
20313a289941SAaron LI */
20323a289941SAaron LI port = NULL;
20333a289941SAaron LI }
20343a289941SAaron LI }
20353a289941SAaron LI free(authority);
20363a289941SAaron LI
20373a289941SAaron LI /*
20383a289941SAaron LI * Everything else is the path. Strip off the leading /.
20393a289941SAaron LI */
20403a289941SAaron LI if (*endp == '\0')
20413a289941SAaron LI path = strdup("");
20423a289941SAaron LI else
20433a289941SAaron LI path = strdup(endp + 1);
20443a289941SAaron LI if (path == NULL) {
20453a289941SAaron LI pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
20463a289941SAaron LI errno, "malloc");
20473a289941SAaron LI free(port);
20483a289941SAaron LI free(host);
20493a289941SAaron LI free(userinfo);
20503a289941SAaron LI free(scheme);
20513a289941SAaron LI return (-1);
20523a289941SAaron LI }
20533a289941SAaron LI *schemep = scheme;
20543a289941SAaron LI *userinfop = userinfo;
20553a289941SAaron LI *hostp = host;
20563a289941SAaron LI *portp = port;
20573a289941SAaron LI *pathp = path;
20583a289941SAaron LI return (0);
20593a289941SAaron LI }
20603a289941SAaron LI
20613a289941SAaron LI int
2062*ea16f64eSAntonio Huete Jimenez pcap_createsrcstr_ex(char *source, int type, const char *host, const char *port,
2063*ea16f64eSAntonio Huete Jimenez const char *name, unsigned char uses_ssl, char *errbuf)
20643a289941SAaron LI {
20653a289941SAaron LI switch (type) {
20663a289941SAaron LI
20673a289941SAaron LI case PCAP_SRC_FILE:
20683a289941SAaron LI pcap_strlcpy(source, PCAP_SRC_FILE_STRING, PCAP_BUF_SIZE);
20693a289941SAaron LI if (name != NULL && *name != '\0') {
20703a289941SAaron LI pcap_strlcat(source, name, PCAP_BUF_SIZE);
20713a289941SAaron LI return (0);
20723a289941SAaron LI } else {
2073*ea16f64eSAntonio Huete Jimenez snprintf(errbuf, PCAP_ERRBUF_SIZE,
20743a289941SAaron LI "The file name cannot be NULL.");
20753a289941SAaron LI return (-1);
20763a289941SAaron LI }
20773a289941SAaron LI
20783a289941SAaron LI case PCAP_SRC_IFREMOTE:
2079*ea16f64eSAntonio Huete Jimenez pcap_strlcpy(source,
2080*ea16f64eSAntonio Huete Jimenez (uses_ssl ? "rpcaps://" : PCAP_SRC_IF_STRING),
2081*ea16f64eSAntonio Huete Jimenez PCAP_BUF_SIZE);
20823a289941SAaron LI if (host != NULL && *host != '\0') {
20833a289941SAaron LI if (strchr(host, ':') != NULL) {
20843a289941SAaron LI /*
20853a289941SAaron LI * The host name contains a colon, so it's
20863a289941SAaron LI * probably an IPv6 address, and needs to
20873a289941SAaron LI * be included in square brackets.
20883a289941SAaron LI */
20893a289941SAaron LI pcap_strlcat(source, "[", PCAP_BUF_SIZE);
20903a289941SAaron LI pcap_strlcat(source, host, PCAP_BUF_SIZE);
20913a289941SAaron LI pcap_strlcat(source, "]", PCAP_BUF_SIZE);
20923a289941SAaron LI } else
20933a289941SAaron LI pcap_strlcat(source, host, PCAP_BUF_SIZE);
20943a289941SAaron LI
20953a289941SAaron LI if (port != NULL && *port != '\0') {
20963a289941SAaron LI pcap_strlcat(source, ":", PCAP_BUF_SIZE);
20973a289941SAaron LI pcap_strlcat(source, port, PCAP_BUF_SIZE);
20983a289941SAaron LI }
20993a289941SAaron LI
21003a289941SAaron LI pcap_strlcat(source, "/", PCAP_BUF_SIZE);
21013a289941SAaron LI } else {
2102*ea16f64eSAntonio Huete Jimenez snprintf(errbuf, PCAP_ERRBUF_SIZE,
21033a289941SAaron LI "The host name cannot be NULL.");
21043a289941SAaron LI return (-1);
21053a289941SAaron LI }
21063a289941SAaron LI
21073a289941SAaron LI if (name != NULL && *name != '\0')
21083a289941SAaron LI pcap_strlcat(source, name, PCAP_BUF_SIZE);
21093a289941SAaron LI
21103a289941SAaron LI return (0);
21113a289941SAaron LI
21123a289941SAaron LI case PCAP_SRC_IFLOCAL:
21133a289941SAaron LI pcap_strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
21143a289941SAaron LI
21153a289941SAaron LI if (name != NULL && *name != '\0')
21163a289941SAaron LI pcap_strlcat(source, name, PCAP_BUF_SIZE);
21173a289941SAaron LI
21183a289941SAaron LI return (0);
21193a289941SAaron LI
21203a289941SAaron LI default:
2121*ea16f64eSAntonio Huete Jimenez snprintf(errbuf, PCAP_ERRBUF_SIZE,
21223a289941SAaron LI "The interface type is not valid.");
21233a289941SAaron LI return (-1);
21243a289941SAaron LI }
21253a289941SAaron LI }
21263a289941SAaron LI
2127*ea16f64eSAntonio Huete Jimenez
21283a289941SAaron LI int
2129*ea16f64eSAntonio Huete Jimenez pcap_createsrcstr(char *source, int type, const char *host, const char *port,
2130*ea16f64eSAntonio Huete Jimenez const char *name, char *errbuf)
2131*ea16f64eSAntonio Huete Jimenez {
2132*ea16f64eSAntonio Huete Jimenez return (pcap_createsrcstr_ex(source, type, host, port, name, 0, errbuf));
2133*ea16f64eSAntonio Huete Jimenez }
2134*ea16f64eSAntonio Huete Jimenez
2135*ea16f64eSAntonio Huete Jimenez int
2136*ea16f64eSAntonio Huete Jimenez pcap_parsesrcstr_ex(const char *source, int *type, char *host, char *port,
2137*ea16f64eSAntonio Huete Jimenez char *name, unsigned char *uses_ssl, char *errbuf)
21383a289941SAaron LI {
21393a289941SAaron LI char *scheme, *tmpuserinfo, *tmphost, *tmpport, *tmppath;
21403a289941SAaron LI
21413a289941SAaron LI /* Initialization stuff */
21423a289941SAaron LI if (host)
21433a289941SAaron LI *host = '\0';
21443a289941SAaron LI if (port)
21453a289941SAaron LI *port = '\0';
21463a289941SAaron LI if (name)
21473a289941SAaron LI *name = '\0';
2148*ea16f64eSAntonio Huete Jimenez if (uses_ssl)
2149*ea16f64eSAntonio Huete Jimenez *uses_ssl = 0;
21503a289941SAaron LI
21513a289941SAaron LI /* Parse the source string */
21523a289941SAaron LI if (pcap_parse_source(source, &scheme, &tmpuserinfo, &tmphost,
21533a289941SAaron LI &tmpport, &tmppath, errbuf) == -1) {
21543a289941SAaron LI /*
21553a289941SAaron LI * Fail.
21563a289941SAaron LI */
21573a289941SAaron LI return (-1);
21583a289941SAaron LI }
21593a289941SAaron LI
21603a289941SAaron LI if (scheme == NULL) {
21613a289941SAaron LI /*
21623a289941SAaron LI * Local device.
21633a289941SAaron LI */
21643a289941SAaron LI if (name && tmppath)
21653a289941SAaron LI pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
21663a289941SAaron LI if (type)
21673a289941SAaron LI *type = PCAP_SRC_IFLOCAL;
21683a289941SAaron LI free(tmppath);
21693a289941SAaron LI free(tmpport);
21703a289941SAaron LI free(tmphost);
21713a289941SAaron LI free(tmpuserinfo);
21723a289941SAaron LI return (0);
21733a289941SAaron LI }
21743a289941SAaron LI
2175*ea16f64eSAntonio Huete Jimenez int is_rpcap = 0;
2176*ea16f64eSAntonio Huete Jimenez if (strcmp(scheme, "rpcaps") == 0) {
2177*ea16f64eSAntonio Huete Jimenez is_rpcap = 1;
2178*ea16f64eSAntonio Huete Jimenez if (uses_ssl) *uses_ssl = 1;
2179*ea16f64eSAntonio Huete Jimenez } else if (strcmp(scheme, "rpcap") == 0) {
2180*ea16f64eSAntonio Huete Jimenez is_rpcap = 1;
2181*ea16f64eSAntonio Huete Jimenez }
2182*ea16f64eSAntonio Huete Jimenez
2183*ea16f64eSAntonio Huete Jimenez if (is_rpcap) {
21843a289941SAaron LI /*
2185*ea16f64eSAntonio Huete Jimenez * rpcap[s]://
21863a289941SAaron LI *
21873a289941SAaron LI * pcap_parse_source() has already handled the case of
2188*ea16f64eSAntonio Huete Jimenez * rpcap[s]://device
21893a289941SAaron LI */
21903a289941SAaron LI if (host && tmphost) {
21913a289941SAaron LI if (tmpuserinfo)
2192*ea16f64eSAntonio Huete Jimenez snprintf(host, PCAP_BUF_SIZE, "%s@%s",
21933a289941SAaron LI tmpuserinfo, tmphost);
21943a289941SAaron LI else
21953a289941SAaron LI pcap_strlcpy(host, tmphost, PCAP_BUF_SIZE);
21963a289941SAaron LI }
21973a289941SAaron LI if (port && tmpport)
21983a289941SAaron LI pcap_strlcpy(port, tmpport, PCAP_BUF_SIZE);
21993a289941SAaron LI if (name && tmppath)
22003a289941SAaron LI pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
22013a289941SAaron LI if (type)
22023a289941SAaron LI *type = PCAP_SRC_IFREMOTE;
22033a289941SAaron LI free(tmppath);
22043a289941SAaron LI free(tmpport);
22053a289941SAaron LI free(tmphost);
22063a289941SAaron LI free(tmpuserinfo);
22073a289941SAaron LI free(scheme);
22083a289941SAaron LI return (0);
22093a289941SAaron LI }
22103a289941SAaron LI
22113a289941SAaron LI if (strcmp(scheme, "file") == 0) {
22123a289941SAaron LI /*
22133a289941SAaron LI * file://
22143a289941SAaron LI */
22153a289941SAaron LI if (name && tmppath)
22163a289941SAaron LI pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
22173a289941SAaron LI if (type)
22183a289941SAaron LI *type = PCAP_SRC_FILE;
22193a289941SAaron LI free(tmppath);
22203a289941SAaron LI free(tmpport);
22213a289941SAaron LI free(tmphost);
22223a289941SAaron LI free(tmpuserinfo);
22233a289941SAaron LI free(scheme);
22243a289941SAaron LI return (0);
22253a289941SAaron LI }
22263a289941SAaron LI
22273a289941SAaron LI /*
22283a289941SAaron LI * Neither rpcap: nor file:; just treat the entire string
22293a289941SAaron LI * as a local device.
22303a289941SAaron LI */
22313a289941SAaron LI if (name)
22323a289941SAaron LI pcap_strlcpy(name, source, PCAP_BUF_SIZE);
22333a289941SAaron LI if (type)
22343a289941SAaron LI *type = PCAP_SRC_IFLOCAL;
22353a289941SAaron LI free(tmppath);
22363a289941SAaron LI free(tmpport);
22373a289941SAaron LI free(tmphost);
22383a289941SAaron LI free(tmpuserinfo);
22393a289941SAaron LI free(scheme);
22403a289941SAaron LI return (0);
22413a289941SAaron LI }
2242*ea16f64eSAntonio Huete Jimenez
2243*ea16f64eSAntonio Huete Jimenez int
2244*ea16f64eSAntonio Huete Jimenez pcap_parsesrcstr(const char *source, int *type, char *host, char *port,
2245*ea16f64eSAntonio Huete Jimenez char *name, char *errbuf)
2246*ea16f64eSAntonio Huete Jimenez {
2247*ea16f64eSAntonio Huete Jimenez return (pcap_parsesrcstr_ex(source, type, host, port, name, NULL, errbuf));
2248*ea16f64eSAntonio Huete Jimenez }
22493a289941SAaron LI #endif
22503a289941SAaron LI
22510e381983SMatthew Dillon pcap_t *
225297a9217aSAntonio Huete Jimenez pcap_create(const char *device, char *errbuf)
22530e381983SMatthew Dillon {
22540e381983SMatthew Dillon size_t i;
22550e381983SMatthew Dillon int is_theirs;
22560e381983SMatthew Dillon pcap_t *p;
225797a9217aSAntonio Huete Jimenez char *device_str;
22580e381983SMatthew Dillon
22590e381983SMatthew Dillon /*
226097a9217aSAntonio Huete Jimenez * A null device name is equivalent to the "any" device -
22610e381983SMatthew Dillon * which might not be supported on this platform, but
22620e381983SMatthew Dillon * this means that you'll get a "not supported" error
22630e381983SMatthew Dillon * rather than, say, a crash when we try to dereference
22640e381983SMatthew Dillon * the null pointer.
22650e381983SMatthew Dillon */
226697a9217aSAntonio Huete Jimenez if (device == NULL)
226797a9217aSAntonio Huete Jimenez device_str = strdup("any");
226897a9217aSAntonio Huete Jimenez else {
226997a9217aSAntonio Huete Jimenez #ifdef _WIN32
227097a9217aSAntonio Huete Jimenez /*
22713a289941SAaron LI * On Windows, for backwards compatibility reasons,
22723a289941SAaron LI * pcap_lookupdev() returns a pointer to a sequence of
22733a289941SAaron LI * pairs of UTF-16LE device names and local code page
22743a289941SAaron LI * description strings.
227597a9217aSAntonio Huete Jimenez *
22763a289941SAaron LI * This means that if a program uses pcap_lookupdev()
22773a289941SAaron LI * to get a default device, and hands that to an API
22783a289941SAaron LI * that opens devices, we'll get handed a UTF-16LE
22793a289941SAaron LI * string, not a string in the local code page.
22803a289941SAaron LI *
22813a289941SAaron LI * To work around that, we check whether the string
2282*ea16f64eSAntonio Huete Jimenez * looks as if it might be a UTF-16LE string and, if
22833a289941SAaron LI * so, convert it back to the local code page's
22843a289941SAaron LI * extended ASCII.
22853a289941SAaron LI *
2286*ea16f64eSAntonio Huete Jimenez * We disable that check in "new API" mode, because:
2287*ea16f64eSAntonio Huete Jimenez *
2288*ea16f64eSAntonio Huete Jimenez * 1) You *cannot* reliably detect whether a
22893a289941SAaron LI * string is UTF-16LE or not; "a" could either
22903a289941SAaron LI * be a one-character ASCII string or the first
2291*ea16f64eSAntonio Huete Jimenez * character of a UTF-16LE string.
2292*ea16f64eSAntonio Huete Jimenez *
2293*ea16f64eSAntonio Huete Jimenez * 2) Doing that test can run past the end of
2294*ea16f64eSAntonio Huete Jimenez * the string, if it's a 1-character ASCII
2295*ea16f64eSAntonio Huete Jimenez * string
2296*ea16f64eSAntonio Huete Jimenez *
2297*ea16f64eSAntonio Huete Jimenez * This particular version of this heuristic dates
2298*ea16f64eSAntonio Huete Jimenez * back to WinPcap 4.1.1; PacketOpenAdapter() does
2299*ea16f64eSAntonio Huete Jimenez * uses the same heuristic, with the exact same
2300*ea16f64eSAntonio Huete Jimenez * vulnerability.
2301*ea16f64eSAntonio Huete Jimenez *
2302*ea16f64eSAntonio Huete Jimenez * That's why we disable this in "new API" mode.
2303*ea16f64eSAntonio Huete Jimenez * We keep it around in legacy mode for backwards
2304*ea16f64eSAntonio Huete Jimenez * compatibility.
230597a9217aSAntonio Huete Jimenez */
2306*ea16f64eSAntonio Huete Jimenez if (!pcap_new_api && device[0] != '\0' && device[1] == '\0') {
230797a9217aSAntonio Huete Jimenez size_t length;
230897a9217aSAntonio Huete Jimenez
230997a9217aSAntonio Huete Jimenez length = wcslen((wchar_t *)device);
231097a9217aSAntonio Huete Jimenez device_str = (char *)malloc(length + 1);
231197a9217aSAntonio Huete Jimenez if (device_str == NULL) {
23123a289941SAaron LI pcap_fmt_errmsg_for_errno(errbuf,
23133a289941SAaron LI PCAP_ERRBUF_SIZE, errno,
23143a289941SAaron LI "malloc");
231597a9217aSAntonio Huete Jimenez return (NULL);
231697a9217aSAntonio Huete Jimenez }
231797a9217aSAntonio Huete Jimenez
2318*ea16f64eSAntonio Huete Jimenez snprintf(device_str, length + 1, "%ws",
231997a9217aSAntonio Huete Jimenez (const wchar_t *)device);
232097a9217aSAntonio Huete Jimenez } else
232197a9217aSAntonio Huete Jimenez #endif
232297a9217aSAntonio Huete Jimenez device_str = strdup(device);
232397a9217aSAntonio Huete Jimenez }
232497a9217aSAntonio Huete Jimenez if (device_str == NULL) {
23253a289941SAaron LI pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
23263a289941SAaron LI errno, "malloc");
232797a9217aSAntonio Huete Jimenez return (NULL);
232897a9217aSAntonio Huete Jimenez }
23290e381983SMatthew Dillon
23300e381983SMatthew Dillon /*
23310e381983SMatthew Dillon * Try each of the non-local-network-interface capture
23320e381983SMatthew Dillon * source types until we find one that works for this
23330e381983SMatthew Dillon * device or run out of types.
23340e381983SMatthew Dillon */
23350e381983SMatthew Dillon for (i = 0; capture_source_types[i].create_op != NULL; i++) {
23360e381983SMatthew Dillon is_theirs = 0;
233797a9217aSAntonio Huete Jimenez p = capture_source_types[i].create_op(device_str, errbuf,
233897a9217aSAntonio Huete Jimenez &is_theirs);
23390e381983SMatthew Dillon if (is_theirs) {
23400e381983SMatthew Dillon /*
23410e381983SMatthew Dillon * The device name refers to a device of the
23420e381983SMatthew Dillon * type in question; either it succeeded,
23430e381983SMatthew Dillon * in which case p refers to a pcap_t to
23440e381983SMatthew Dillon * later activate for the device, or it
23450e381983SMatthew Dillon * failed, in which case p is null and we
23460e381983SMatthew Dillon * should return that to report the failure
23470e381983SMatthew Dillon * to create.
23480e381983SMatthew Dillon */
234997a9217aSAntonio Huete Jimenez if (p == NULL) {
235097a9217aSAntonio Huete Jimenez /*
235197a9217aSAntonio Huete Jimenez * We assume the caller filled in errbuf.
235297a9217aSAntonio Huete Jimenez */
235397a9217aSAntonio Huete Jimenez free(device_str);
235497a9217aSAntonio Huete Jimenez return (NULL);
235597a9217aSAntonio Huete Jimenez }
235697a9217aSAntonio Huete Jimenez p->opt.device = device_str;
23570e381983SMatthew Dillon return (p);
23580e381983SMatthew Dillon }
23590e381983SMatthew Dillon }
23600e381983SMatthew Dillon
23610e381983SMatthew Dillon /*
23620e381983SMatthew Dillon * OK, try it as a regular network interface.
23630e381983SMatthew Dillon */
236497a9217aSAntonio Huete Jimenez p = pcap_create_interface(device_str, errbuf);
236597a9217aSAntonio Huete Jimenez if (p == NULL) {
236697a9217aSAntonio Huete Jimenez /*
236797a9217aSAntonio Huete Jimenez * We assume the caller filled in errbuf.
236897a9217aSAntonio Huete Jimenez */
236997a9217aSAntonio Huete Jimenez free(device_str);
237097a9217aSAntonio Huete Jimenez return (NULL);
23710e381983SMatthew Dillon }
237297a9217aSAntonio Huete Jimenez p->opt.device = device_str;
237397a9217aSAntonio Huete Jimenez return (p);
237497a9217aSAntonio Huete Jimenez }
23750e381983SMatthew Dillon
23763a289941SAaron LI /*
23773a289941SAaron LI * Set nonblocking mode on an unactivated pcap_t; this sets a flag
23783a289941SAaron LI * checked by pcap_activate(), which sets the mode after calling
23793a289941SAaron LI * the activate routine.
23803a289941SAaron LI */
23813a289941SAaron LI static int
23823a289941SAaron LI pcap_setnonblock_unactivated(pcap_t *p, int nonblock)
23833a289941SAaron LI {
23843a289941SAaron LI p->opt.nonblock = nonblock;
23853a289941SAaron LI return (0);
23863a289941SAaron LI }
23873a289941SAaron LI
2388a85e14b0SPeter Avalos static void
2389a85e14b0SPeter Avalos initialize_ops(pcap_t *p)
2390a85e14b0SPeter Avalos {
2391a85e14b0SPeter Avalos /*
2392a85e14b0SPeter Avalos * Set operation pointers for operations that only work on
2393a85e14b0SPeter Avalos * an activated pcap_t to point to a routine that returns
2394a85e14b0SPeter Avalos * a "this isn't activated" error.
2395de0d3203SPeter Avalos */
23963a289941SAaron LI p->read_op = pcap_read_not_initialized;
23973a289941SAaron LI p->inject_op = pcap_inject_not_initialized;
23983a289941SAaron LI p->setfilter_op = pcap_setfilter_not_initialized;
23993a289941SAaron LI p->setdirection_op = pcap_setdirection_not_initialized;
24003a289941SAaron LI p->set_datalink_op = pcap_set_datalink_not_initialized;
24013a289941SAaron LI p->getnonblock_op = pcap_getnonblock_not_initialized;
24023a289941SAaron LI p->stats_op = pcap_stats_not_initialized;
240397a9217aSAntonio Huete Jimenez #ifdef _WIN32
24043a289941SAaron LI p->stats_ex_op = pcap_stats_ex_not_initialized;
24053a289941SAaron LI p->setbuff_op = pcap_setbuff_not_initialized;
24063a289941SAaron LI p->setmode_op = pcap_setmode_not_initialized;
24073a289941SAaron LI p->setmintocopy_op = pcap_setmintocopy_not_initialized;
240897a9217aSAntonio Huete Jimenez p->getevent_op = pcap_getevent_not_initialized;
24093a289941SAaron LI p->oid_get_request_op = pcap_oid_get_request_not_initialized;
24103a289941SAaron LI p->oid_set_request_op = pcap_oid_set_request_not_initialized;
241197a9217aSAntonio Huete Jimenez p->sendqueue_transmit_op = pcap_sendqueue_transmit_not_initialized;
24123a289941SAaron LI p->setuserbuffer_op = pcap_setuserbuffer_not_initialized;
24133a289941SAaron LI p->live_dump_op = pcap_live_dump_not_initialized;
24143a289941SAaron LI p->live_dump_ended_op = pcap_live_dump_ended_not_initialized;
241597a9217aSAntonio Huete Jimenez p->get_airpcap_handle_op = pcap_get_airpcap_handle_not_initialized;
2416de0d3203SPeter Avalos #endif
2417a85e14b0SPeter Avalos
2418a85e14b0SPeter Avalos /*
2419a85e14b0SPeter Avalos * Default cleanup operation - implementations can override
2420a85e14b0SPeter Avalos * this, but should call pcap_cleanup_live_common() after
2421a85e14b0SPeter Avalos * doing their own additional cleanup.
2422a85e14b0SPeter Avalos */
2423de0d3203SPeter Avalos p->cleanup_op = pcap_cleanup_live_common;
2424de0d3203SPeter Avalos
2425a85e14b0SPeter Avalos /*
242697a9217aSAntonio Huete Jimenez * In most cases, the standard one-shot callback can
2427a85e14b0SPeter Avalos * be used for pcap_next()/pcap_next_ex().
2428a85e14b0SPeter Avalos */
2429a85e14b0SPeter Avalos p->oneshot_callback = pcap_oneshot;
2430*ea16f64eSAntonio Huete Jimenez
2431*ea16f64eSAntonio Huete Jimenez /*
2432*ea16f64eSAntonio Huete Jimenez * Default breakloop operation - implementations can override
2433*ea16f64eSAntonio Huete Jimenez * this, but should call pcap_breakloop_common() before doing
2434*ea16f64eSAntonio Huete Jimenez * their own logic.
2435*ea16f64eSAntonio Huete Jimenez */
2436*ea16f64eSAntonio Huete Jimenez p->breakloop_op = pcap_breakloop_common;
2437a85e14b0SPeter Avalos }
2438a85e14b0SPeter Avalos
243997a9217aSAntonio Huete Jimenez static pcap_t *
2440*ea16f64eSAntonio Huete Jimenez pcap_alloc_pcap_t(char *ebuf, size_t total_size, size_t private_offset)
244197a9217aSAntonio Huete Jimenez {
244297a9217aSAntonio Huete Jimenez char *chunk;
244397a9217aSAntonio Huete Jimenez pcap_t *p;
244497a9217aSAntonio Huete Jimenez
244597a9217aSAntonio Huete Jimenez /*
2446*ea16f64eSAntonio Huete Jimenez * total_size is the size of a structure containing a pcap_t
2447*ea16f64eSAntonio Huete Jimenez * followed by a private structure.
244897a9217aSAntonio Huete Jimenez */
2449*ea16f64eSAntonio Huete Jimenez chunk = calloc(total_size, 1);
245097a9217aSAntonio Huete Jimenez if (chunk == NULL) {
24513a289941SAaron LI pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
24523a289941SAaron LI errno, "malloc");
245397a9217aSAntonio Huete Jimenez return (NULL);
245497a9217aSAntonio Huete Jimenez }
245597a9217aSAntonio Huete Jimenez
245697a9217aSAntonio Huete Jimenez /*
245797a9217aSAntonio Huete Jimenez * Get a pointer to the pcap_t at the beginning.
245897a9217aSAntonio Huete Jimenez */
245997a9217aSAntonio Huete Jimenez p = (pcap_t *)chunk;
246097a9217aSAntonio Huete Jimenez
24613a289941SAaron LI #ifdef _WIN32
24623a289941SAaron LI p->handle = INVALID_HANDLE_VALUE; /* not opened yet */
24633a289941SAaron LI #else /* _WIN32 */
246497a9217aSAntonio Huete Jimenez p->fd = -1; /* not opened yet */
24653a289941SAaron LI #ifndef MSDOS
246697a9217aSAntonio Huete Jimenez p->selectable_fd = -1;
24673a289941SAaron LI p->required_select_timeout = NULL;
24683a289941SAaron LI #endif /* MSDOS */
24693a289941SAaron LI #endif /* _WIN32 */
247097a9217aSAntonio Huete Jimenez
247197a9217aSAntonio Huete Jimenez /*
2472*ea16f64eSAntonio Huete Jimenez * private_offset is the offset, in bytes, of the private
2473*ea16f64eSAntonio Huete Jimenez * data from the beginning of the structure.
2474*ea16f64eSAntonio Huete Jimenez *
2475*ea16f64eSAntonio Huete Jimenez * Set the pointer to the private data; that's private_offset
2476*ea16f64eSAntonio Huete Jimenez * bytes past the pcap_t.
247797a9217aSAntonio Huete Jimenez */
2478*ea16f64eSAntonio Huete Jimenez p->priv = (void *)(chunk + private_offset);
247997a9217aSAntonio Huete Jimenez
248097a9217aSAntonio Huete Jimenez return (p);
248197a9217aSAntonio Huete Jimenez }
248297a9217aSAntonio Huete Jimenez
2483a85e14b0SPeter Avalos pcap_t *
2484*ea16f64eSAntonio Huete Jimenez pcap_create_common(char *ebuf, size_t total_size, size_t private_offset)
2485a85e14b0SPeter Avalos {
2486a85e14b0SPeter Avalos pcap_t *p;
2487a85e14b0SPeter Avalos
2488*ea16f64eSAntonio Huete Jimenez p = pcap_alloc_pcap_t(ebuf, total_size, private_offset);
248997a9217aSAntonio Huete Jimenez if (p == NULL)
2490a85e14b0SPeter Avalos return (NULL);
2491a85e14b0SPeter Avalos
2492a85e14b0SPeter Avalos /*
2493a85e14b0SPeter Avalos * Default to "can't set rfmon mode"; if it's supported by
2494a85e14b0SPeter Avalos * a platform, the create routine that called us can set
2495a85e14b0SPeter Avalos * the op to its routine to check whether a particular
2496a85e14b0SPeter Avalos * device supports it.
2497a85e14b0SPeter Avalos */
2498a85e14b0SPeter Avalos p->can_set_rfmon_op = pcap_cant_set_rfmon;
2499a85e14b0SPeter Avalos
25003a289941SAaron LI /*
25013a289941SAaron LI * If pcap_setnonblock() is called on a not-yet-activated
25023a289941SAaron LI * pcap_t, default to setting a flag and turning
25033a289941SAaron LI * on non-blocking mode when activated.
25043a289941SAaron LI */
25053a289941SAaron LI p->setnonblock_op = pcap_setnonblock_unactivated;
25063a289941SAaron LI
2507a85e14b0SPeter Avalos initialize_ops(p);
2508a85e14b0SPeter Avalos
2509de0d3203SPeter Avalos /* put in some defaults*/
25103a289941SAaron LI p->snapshot = 0; /* max packet size unspecified */
251197a9217aSAntonio Huete Jimenez p->opt.timeout = 0; /* no timeout specified */
251297a9217aSAntonio Huete Jimenez p->opt.buffer_size = 0; /* use the platform's default */
2513de0d3203SPeter Avalos p->opt.promisc = 0;
251497a9217aSAntonio Huete Jimenez p->opt.rfmon = 0;
251597a9217aSAntonio Huete Jimenez p->opt.immediate = 0;
2516a85e14b0SPeter Avalos p->opt.tstamp_type = -1; /* default to not setting time stamp type */
251797a9217aSAntonio Huete Jimenez p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
25183a289941SAaron LI /*
25193a289941SAaron LI * Platform-dependent options.
25203a289941SAaron LI */
25213a289941SAaron LI #ifdef __linux__
25223a289941SAaron LI p->opt.protocol = 0;
25233a289941SAaron LI #endif
25243a289941SAaron LI #ifdef _WIN32
25253a289941SAaron LI p->opt.nocapture_local = 0;
25263a289941SAaron LI #endif
252797a9217aSAntonio Huete Jimenez
252897a9217aSAntonio Huete Jimenez /*
252997a9217aSAntonio Huete Jimenez * Start out with no BPF code generation flags set.
253097a9217aSAntonio Huete Jimenez */
253197a9217aSAntonio Huete Jimenez p->bpf_codegen_flags = 0;
253297a9217aSAntonio Huete Jimenez
2533de0d3203SPeter Avalos return (p);
2534de0d3203SPeter Avalos }
2535de0d3203SPeter Avalos
2536de0d3203SPeter Avalos int
2537de0d3203SPeter Avalos pcap_check_activated(pcap_t *p)
2538de0d3203SPeter Avalos {
2539de0d3203SPeter Avalos if (p->activated) {
2540*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
2541de0d3203SPeter Avalos " operation on activated capture");
2542a85e14b0SPeter Avalos return (-1);
2543de0d3203SPeter Avalos }
2544a85e14b0SPeter Avalos return (0);
2545de0d3203SPeter Avalos }
2546de0d3203SPeter Avalos
2547de0d3203SPeter Avalos int
2548de0d3203SPeter Avalos pcap_set_snaplen(pcap_t *p, int snaplen)
2549de0d3203SPeter Avalos {
2550de0d3203SPeter Avalos if (pcap_check_activated(p))
2551a85e14b0SPeter Avalos return (PCAP_ERROR_ACTIVATED);
2552de0d3203SPeter Avalos p->snapshot = snaplen;
2553a85e14b0SPeter Avalos return (0);
2554de0d3203SPeter Avalos }
2555de0d3203SPeter Avalos
2556de0d3203SPeter Avalos int
2557de0d3203SPeter Avalos pcap_set_promisc(pcap_t *p, int promisc)
2558de0d3203SPeter Avalos {
2559de0d3203SPeter Avalos if (pcap_check_activated(p))
2560a85e14b0SPeter Avalos return (PCAP_ERROR_ACTIVATED);
2561de0d3203SPeter Avalos p->opt.promisc = promisc;
2562a85e14b0SPeter Avalos return (0);
2563de0d3203SPeter Avalos }
2564de0d3203SPeter Avalos
2565de0d3203SPeter Avalos int
2566de0d3203SPeter Avalos pcap_set_rfmon(pcap_t *p, int rfmon)
2567de0d3203SPeter Avalos {
2568de0d3203SPeter Avalos if (pcap_check_activated(p))
2569a85e14b0SPeter Avalos return (PCAP_ERROR_ACTIVATED);
2570de0d3203SPeter Avalos p->opt.rfmon = rfmon;
2571a85e14b0SPeter Avalos return (0);
2572de0d3203SPeter Avalos }
2573de0d3203SPeter Avalos
2574de0d3203SPeter Avalos int
2575de0d3203SPeter Avalos pcap_set_timeout(pcap_t *p, int timeout_ms)
2576de0d3203SPeter Avalos {
2577de0d3203SPeter Avalos if (pcap_check_activated(p))
2578a85e14b0SPeter Avalos return (PCAP_ERROR_ACTIVATED);
257997a9217aSAntonio Huete Jimenez p->opt.timeout = timeout_ms;
2580a85e14b0SPeter Avalos return (0);
2581a85e14b0SPeter Avalos }
2582a85e14b0SPeter Avalos
2583a85e14b0SPeter Avalos int
2584a85e14b0SPeter Avalos pcap_set_tstamp_type(pcap_t *p, int tstamp_type)
2585a85e14b0SPeter Avalos {
2586a85e14b0SPeter Avalos int i;
2587a85e14b0SPeter Avalos
2588a85e14b0SPeter Avalos if (pcap_check_activated(p))
2589a85e14b0SPeter Avalos return (PCAP_ERROR_ACTIVATED);
2590a85e14b0SPeter Avalos
2591a85e14b0SPeter Avalos /*
259297a9217aSAntonio Huete Jimenez * The argument should have been u_int, but that's too late
259397a9217aSAntonio Huete Jimenez * to change now - it's an API.
2594a85e14b0SPeter Avalos */
259597a9217aSAntonio Huete Jimenez if (tstamp_type < 0)
259697a9217aSAntonio Huete Jimenez return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
2597a85e14b0SPeter Avalos
2598a85e14b0SPeter Avalos /*
259997a9217aSAntonio Huete Jimenez * If p->tstamp_type_count is 0, we only support PCAP_TSTAMP_HOST;
260097a9217aSAntonio Huete Jimenez * the default time stamp type is PCAP_TSTAMP_HOST.
260197a9217aSAntonio Huete Jimenez */
260297a9217aSAntonio Huete Jimenez if (p->tstamp_type_count == 0) {
260397a9217aSAntonio Huete Jimenez if (tstamp_type == PCAP_TSTAMP_HOST) {
260497a9217aSAntonio Huete Jimenez p->opt.tstamp_type = tstamp_type;
260597a9217aSAntonio Huete Jimenez return (0);
260697a9217aSAntonio Huete Jimenez }
260797a9217aSAntonio Huete Jimenez } else {
260897a9217aSAntonio Huete Jimenez /*
2609a85e14b0SPeter Avalos * Check whether we claim to support this type of time stamp.
2610a85e14b0SPeter Avalos */
2611a85e14b0SPeter Avalos for (i = 0; i < p->tstamp_type_count; i++) {
261297a9217aSAntonio Huete Jimenez if (p->tstamp_type_list[i] == (u_int)tstamp_type) {
2613a85e14b0SPeter Avalos /*
2614a85e14b0SPeter Avalos * Yes.
2615a85e14b0SPeter Avalos */
2616a85e14b0SPeter Avalos p->opt.tstamp_type = tstamp_type;
2617a85e14b0SPeter Avalos return (0);
2618a85e14b0SPeter Avalos }
2619a85e14b0SPeter Avalos }
262097a9217aSAntonio Huete Jimenez }
2621a85e14b0SPeter Avalos
2622a85e14b0SPeter Avalos /*
262397a9217aSAntonio Huete Jimenez * We don't support this type of time stamp.
2624a85e14b0SPeter Avalos */
2625a85e14b0SPeter Avalos return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
2626de0d3203SPeter Avalos }
2627de0d3203SPeter Avalos
2628de0d3203SPeter Avalos int
262997a9217aSAntonio Huete Jimenez pcap_set_immediate_mode(pcap_t *p, int immediate)
263097a9217aSAntonio Huete Jimenez {
263197a9217aSAntonio Huete Jimenez if (pcap_check_activated(p))
263297a9217aSAntonio Huete Jimenez return (PCAP_ERROR_ACTIVATED);
263397a9217aSAntonio Huete Jimenez p->opt.immediate = immediate;
263497a9217aSAntonio Huete Jimenez return (0);
263597a9217aSAntonio Huete Jimenez }
263697a9217aSAntonio Huete Jimenez
263797a9217aSAntonio Huete Jimenez int
2638de0d3203SPeter Avalos pcap_set_buffer_size(pcap_t *p, int buffer_size)
2639de0d3203SPeter Avalos {
2640de0d3203SPeter Avalos if (pcap_check_activated(p))
2641a85e14b0SPeter Avalos return (PCAP_ERROR_ACTIVATED);
264297a9217aSAntonio Huete Jimenez if (buffer_size <= 0) {
264397a9217aSAntonio Huete Jimenez /*
264497a9217aSAntonio Huete Jimenez * Silently ignore invalid values.
264597a9217aSAntonio Huete Jimenez */
264697a9217aSAntonio Huete Jimenez return (0);
264797a9217aSAntonio Huete Jimenez }
2648de0d3203SPeter Avalos p->opt.buffer_size = buffer_size;
2649a85e14b0SPeter Avalos return (0);
2650de0d3203SPeter Avalos }
2651de0d3203SPeter Avalos
2652de0d3203SPeter Avalos int
265397a9217aSAntonio Huete Jimenez pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision)
265497a9217aSAntonio Huete Jimenez {
265597a9217aSAntonio Huete Jimenez int i;
265697a9217aSAntonio Huete Jimenez
265797a9217aSAntonio Huete Jimenez if (pcap_check_activated(p))
265897a9217aSAntonio Huete Jimenez return (PCAP_ERROR_ACTIVATED);
265997a9217aSAntonio Huete Jimenez
266097a9217aSAntonio Huete Jimenez /*
266197a9217aSAntonio Huete Jimenez * The argument should have been u_int, but that's too late
266297a9217aSAntonio Huete Jimenez * to change now - it's an API.
266397a9217aSAntonio Huete Jimenez */
266497a9217aSAntonio Huete Jimenez if (tstamp_precision < 0)
266597a9217aSAntonio Huete Jimenez return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
266697a9217aSAntonio Huete Jimenez
266797a9217aSAntonio Huete Jimenez /*
266897a9217aSAntonio Huete Jimenez * If p->tstamp_precision_count is 0, we only support setting
266997a9217aSAntonio Huete Jimenez * the time stamp precision to microsecond precision; every
267097a9217aSAntonio Huete Jimenez * pcap module *MUST* support microsecond precision, even if
267197a9217aSAntonio Huete Jimenez * it does so by converting the native precision to
267297a9217aSAntonio Huete Jimenez * microseconds.
267397a9217aSAntonio Huete Jimenez */
267497a9217aSAntonio Huete Jimenez if (p->tstamp_precision_count == 0) {
267597a9217aSAntonio Huete Jimenez if (tstamp_precision == PCAP_TSTAMP_PRECISION_MICRO) {
267697a9217aSAntonio Huete Jimenez p->opt.tstamp_precision = tstamp_precision;
267797a9217aSAntonio Huete Jimenez return (0);
267897a9217aSAntonio Huete Jimenez }
267997a9217aSAntonio Huete Jimenez } else {
268097a9217aSAntonio Huete Jimenez /*
268197a9217aSAntonio Huete Jimenez * Check whether we claim to support this precision of
268297a9217aSAntonio Huete Jimenez * time stamp.
268397a9217aSAntonio Huete Jimenez */
268497a9217aSAntonio Huete Jimenez for (i = 0; i < p->tstamp_precision_count; i++) {
268597a9217aSAntonio Huete Jimenez if (p->tstamp_precision_list[i] == (u_int)tstamp_precision) {
268697a9217aSAntonio Huete Jimenez /*
268797a9217aSAntonio Huete Jimenez * Yes.
268897a9217aSAntonio Huete Jimenez */
268997a9217aSAntonio Huete Jimenez p->opt.tstamp_precision = tstamp_precision;
269097a9217aSAntonio Huete Jimenez return (0);
269197a9217aSAntonio Huete Jimenez }
269297a9217aSAntonio Huete Jimenez }
269397a9217aSAntonio Huete Jimenez }
269497a9217aSAntonio Huete Jimenez
269597a9217aSAntonio Huete Jimenez /*
269697a9217aSAntonio Huete Jimenez * We don't support this time stamp precision.
269797a9217aSAntonio Huete Jimenez */
269897a9217aSAntonio Huete Jimenez return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
269997a9217aSAntonio Huete Jimenez }
270097a9217aSAntonio Huete Jimenez
270197a9217aSAntonio Huete Jimenez int
270297a9217aSAntonio Huete Jimenez pcap_get_tstamp_precision(pcap_t *p)
270397a9217aSAntonio Huete Jimenez {
270497a9217aSAntonio Huete Jimenez return (p->opt.tstamp_precision);
270597a9217aSAntonio Huete Jimenez }
270697a9217aSAntonio Huete Jimenez
270797a9217aSAntonio Huete Jimenez int
2708de0d3203SPeter Avalos pcap_activate(pcap_t *p)
2709de0d3203SPeter Avalos {
2710de0d3203SPeter Avalos int status;
2711de0d3203SPeter Avalos
2712a85e14b0SPeter Avalos /*
2713a85e14b0SPeter Avalos * Catch attempts to re-activate an already-activated
2714a85e14b0SPeter Avalos * pcap_t; this should, for example, catch code that
2715a85e14b0SPeter Avalos * calls pcap_open_live() followed by pcap_activate(),
2716a85e14b0SPeter Avalos * as some code that showed up in a Stack Exchange
2717a85e14b0SPeter Avalos * question did.
2718a85e14b0SPeter Avalos */
2719a85e14b0SPeter Avalos if (pcap_check_activated(p))
2720a85e14b0SPeter Avalos return (PCAP_ERROR_ACTIVATED);
2721de0d3203SPeter Avalos status = p->activate_op(p);
27223a289941SAaron LI if (status >= 0) {
27233a289941SAaron LI /*
27243a289941SAaron LI * If somebody requested non-blocking mode before
27253a289941SAaron LI * calling pcap_activate(), turn it on now.
27263a289941SAaron LI */
27273a289941SAaron LI if (p->opt.nonblock) {
27283a289941SAaron LI status = p->setnonblock_op(p, 1);
27293a289941SAaron LI if (status < 0) {
27303a289941SAaron LI /*
27313a289941SAaron LI * Failed. Undo everything done by
27323a289941SAaron LI * the activate operation.
27333a289941SAaron LI */
27343a289941SAaron LI p->cleanup_op(p);
27353a289941SAaron LI initialize_ops(p);
27363a289941SAaron LI return (status);
27373a289941SAaron LI }
27383a289941SAaron LI }
2739de0d3203SPeter Avalos p->activated = 1;
27403a289941SAaron LI } else {
2741a85e14b0SPeter Avalos if (p->errbuf[0] == '\0') {
2742a85e14b0SPeter Avalos /*
2743a85e14b0SPeter Avalos * No error message supplied by the activate routine;
2744a85e14b0SPeter Avalos * for the benefit of programs that don't specially
2745a85e14b0SPeter Avalos * handle errors other than PCAP_ERROR, return the
2746a85e14b0SPeter Avalos * error message corresponding to the status.
2747a85e14b0SPeter Avalos */
2748*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
2749a85e14b0SPeter Avalos pcap_statustostr(status));
2750a85e14b0SPeter Avalos }
2751a85e14b0SPeter Avalos
2752a85e14b0SPeter Avalos /*
2753a85e14b0SPeter Avalos * Undo any operation pointer setting, etc. done by
2754a85e14b0SPeter Avalos * the activate operation.
2755a85e14b0SPeter Avalos */
2756a85e14b0SPeter Avalos initialize_ops(p);
2757a85e14b0SPeter Avalos }
2758de0d3203SPeter Avalos return (status);
2759de0d3203SPeter Avalos }
2760de0d3203SPeter Avalos
2761de0d3203SPeter Avalos pcap_t *
276297a9217aSAntonio Huete Jimenez pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf)
2763de0d3203SPeter Avalos {
2764de0d3203SPeter Avalos pcap_t *p;
2765de0d3203SPeter Avalos int status;
27663a289941SAaron LI #ifdef ENABLE_REMOTE
27673a289941SAaron LI char host[PCAP_BUF_SIZE + 1];
27683a289941SAaron LI char port[PCAP_BUF_SIZE + 1];
27693a289941SAaron LI char name[PCAP_BUF_SIZE + 1];
27703a289941SAaron LI int srctype;
27713a289941SAaron LI
27723a289941SAaron LI /*
27733a289941SAaron LI * A null device name is equivalent to the "any" device -
27743a289941SAaron LI * which might not be supported on this platform, but
27753a289941SAaron LI * this means that you'll get a "not supported" error
27763a289941SAaron LI * rather than, say, a crash when we try to dereference
27773a289941SAaron LI * the null pointer.
27783a289941SAaron LI */
27793a289941SAaron LI if (device == NULL)
27803a289941SAaron LI device = "any";
27813a289941SAaron LI
27823a289941SAaron LI /*
27833a289941SAaron LI * Retrofit - we have to make older applications compatible with
27843a289941SAaron LI * remote capture.
27853a289941SAaron LI * So we're calling pcap_open_remote() from here; this is a very
27863a289941SAaron LI * dirty hack.
27873a289941SAaron LI * Obviously, we cannot exploit all the new features; for instance,
27883a289941SAaron LI * we cannot send authentication, we cannot use a UDP data connection,
27893a289941SAaron LI * and so on.
27903a289941SAaron LI */
27913a289941SAaron LI if (pcap_parsesrcstr(device, &srctype, host, port, name, errbuf))
27923a289941SAaron LI return (NULL);
27933a289941SAaron LI
27943a289941SAaron LI if (srctype == PCAP_SRC_IFREMOTE) {
27953a289941SAaron LI /*
27963a289941SAaron LI * Although we already have host, port and iface, we prefer
27973a289941SAaron LI * to pass only 'device' to pcap_open_rpcap(), so that it has
27983a289941SAaron LI * to call pcap_parsesrcstr() again.
27993a289941SAaron LI * This is less optimized, but much clearer.
28003a289941SAaron LI */
28013a289941SAaron LI return (pcap_open_rpcap(device, snaplen,
28023a289941SAaron LI promisc ? PCAP_OPENFLAG_PROMISCUOUS : 0, to_ms,
28033a289941SAaron LI NULL, errbuf));
28043a289941SAaron LI }
28053a289941SAaron LI if (srctype == PCAP_SRC_FILE) {
2806*ea16f64eSAntonio Huete Jimenez snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown URL scheme \"file\"");
28073a289941SAaron LI return (NULL);
28083a289941SAaron LI }
28093a289941SAaron LI if (srctype == PCAP_SRC_IFLOCAL) {
28103a289941SAaron LI /*
28113a289941SAaron LI * If it starts with rpcap://, that refers to a local device
28123a289941SAaron LI * (no host part in the URL). Remove the rpcap://, and
28133a289941SAaron LI * fall through to the regular open path.
28143a289941SAaron LI */
28153a289941SAaron LI if (strncmp(device, PCAP_SRC_IF_STRING, strlen(PCAP_SRC_IF_STRING)) == 0) {
28163a289941SAaron LI size_t len = strlen(device) - strlen(PCAP_SRC_IF_STRING) + 1;
28173a289941SAaron LI
28183a289941SAaron LI if (len > 0)
28193a289941SAaron LI device += strlen(PCAP_SRC_IF_STRING);
28203a289941SAaron LI }
28213a289941SAaron LI }
28223a289941SAaron LI #endif /* ENABLE_REMOTE */
2823de0d3203SPeter Avalos
282497a9217aSAntonio Huete Jimenez p = pcap_create(device, errbuf);
2825de0d3203SPeter Avalos if (p == NULL)
2826de0d3203SPeter Avalos return (NULL);
2827de0d3203SPeter Avalos status = pcap_set_snaplen(p, snaplen);
2828de0d3203SPeter Avalos if (status < 0)
2829de0d3203SPeter Avalos goto fail;
2830de0d3203SPeter Avalos status = pcap_set_promisc(p, promisc);
2831de0d3203SPeter Avalos if (status < 0)
2832de0d3203SPeter Avalos goto fail;
2833de0d3203SPeter Avalos status = pcap_set_timeout(p, to_ms);
2834de0d3203SPeter Avalos if (status < 0)
2835de0d3203SPeter Avalos goto fail;
2836de0d3203SPeter Avalos /*
2837de0d3203SPeter Avalos * Mark this as opened with pcap_open_live(), so that, for
2838de0d3203SPeter Avalos * example, we show the full list of DLT_ values, rather
2839de0d3203SPeter Avalos * than just the ones that are compatible with capturing
2840de0d3203SPeter Avalos * when not in monitor mode. That allows existing applications
2841de0d3203SPeter Avalos * to work the way they used to work, but allows new applications
2842de0d3203SPeter Avalos * that know about the new open API to, for example, find out the
2843de0d3203SPeter Avalos * DLT_ values that they can select without changing whether
2844de0d3203SPeter Avalos * the adapter is in monitor mode or not.
2845de0d3203SPeter Avalos */
2846de0d3203SPeter Avalos p->oldstyle = 1;
2847de0d3203SPeter Avalos status = pcap_activate(p);
2848de0d3203SPeter Avalos if (status < 0)
2849de0d3203SPeter Avalos goto fail;
2850de0d3203SPeter Avalos return (p);
2851de0d3203SPeter Avalos fail:
2852a85e14b0SPeter Avalos if (status == PCAP_ERROR)
2853*ea16f64eSAntonio Huete Jimenez snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %.*s", device,
28543a289941SAaron LI PCAP_ERRBUF_SIZE - 3, p->errbuf);
2855a85e14b0SPeter Avalos else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
2856a85e14b0SPeter Avalos status == PCAP_ERROR_PERM_DENIED ||
2857a85e14b0SPeter Avalos status == PCAP_ERROR_PROMISC_PERM_DENIED)
2858*ea16f64eSAntonio Huete Jimenez snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%.*s)", device,
28593a289941SAaron LI pcap_statustostr(status), PCAP_ERRBUF_SIZE - 6, p->errbuf);
2860de0d3203SPeter Avalos else
2861*ea16f64eSAntonio Huete Jimenez snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device,
2862de0d3203SPeter Avalos pcap_statustostr(status));
2863de0d3203SPeter Avalos pcap_close(p);
2864de0d3203SPeter Avalos return (NULL);
2865de0d3203SPeter Avalos }
2866de0d3203SPeter Avalos
286797a9217aSAntonio Huete Jimenez pcap_t *
2868*ea16f64eSAntonio Huete Jimenez pcap_open_offline_common(char *ebuf, size_t total_size, size_t private_offset)
286997a9217aSAntonio Huete Jimenez {
287097a9217aSAntonio Huete Jimenez pcap_t *p;
287197a9217aSAntonio Huete Jimenez
2872*ea16f64eSAntonio Huete Jimenez p = pcap_alloc_pcap_t(ebuf, total_size, private_offset);
287397a9217aSAntonio Huete Jimenez if (p == NULL)
287497a9217aSAntonio Huete Jimenez return (NULL);
287597a9217aSAntonio Huete Jimenez
287697a9217aSAntonio Huete Jimenez p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
287797a9217aSAntonio Huete Jimenez
287897a9217aSAntonio Huete Jimenez return (p);
287997a9217aSAntonio Huete Jimenez }
288097a9217aSAntonio Huete Jimenez
2881de0d3203SPeter Avalos int
28821077d0bdSPeter Avalos pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
28831077d0bdSPeter Avalos {
2884a85e14b0SPeter Avalos return (p->read_op(p, cnt, callback, user));
28851077d0bdSPeter Avalos }
28861077d0bdSPeter Avalos
28871077d0bdSPeter Avalos int
28881077d0bdSPeter Avalos pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
28891077d0bdSPeter Avalos {
28901077d0bdSPeter Avalos register int n;
28911077d0bdSPeter Avalos
28921077d0bdSPeter Avalos for (;;) {
289397a9217aSAntonio Huete Jimenez if (p->rfile != NULL) {
28941077d0bdSPeter Avalos /*
28951077d0bdSPeter Avalos * 0 means EOF, so don't loop if we get 0.
28961077d0bdSPeter Avalos */
28971077d0bdSPeter Avalos n = pcap_offline_read(p, cnt, callback, user);
28981077d0bdSPeter Avalos } else {
28991077d0bdSPeter Avalos /*
29001077d0bdSPeter Avalos * XXX keep reading until we get something
29011077d0bdSPeter Avalos * (or an error occurs)
29021077d0bdSPeter Avalos */
29031077d0bdSPeter Avalos do {
29041077d0bdSPeter Avalos n = p->read_op(p, cnt, callback, user);
29051077d0bdSPeter Avalos } while (n == 0);
29061077d0bdSPeter Avalos }
29071077d0bdSPeter Avalos if (n <= 0)
29081077d0bdSPeter Avalos return (n);
290997a9217aSAntonio Huete Jimenez if (!PACKET_COUNT_IS_UNLIMITED(cnt)) {
29101077d0bdSPeter Avalos cnt -= n;
29111077d0bdSPeter Avalos if (cnt <= 0)
29121077d0bdSPeter Avalos return (0);
29131077d0bdSPeter Avalos }
29141077d0bdSPeter Avalos }
29151077d0bdSPeter Avalos }
29161077d0bdSPeter Avalos
29171077d0bdSPeter Avalos /*
29181077d0bdSPeter Avalos * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate.
29191077d0bdSPeter Avalos */
29201077d0bdSPeter Avalos void
29211077d0bdSPeter Avalos pcap_breakloop(pcap_t *p)
29221077d0bdSPeter Avalos {
2923*ea16f64eSAntonio Huete Jimenez p->breakloop_op(p);
29241077d0bdSPeter Avalos }
29251077d0bdSPeter Avalos
29261077d0bdSPeter Avalos int
29271077d0bdSPeter Avalos pcap_datalink(pcap_t *p)
29281077d0bdSPeter Avalos {
292997a9217aSAntonio Huete Jimenez if (!p->activated)
293097a9217aSAntonio Huete Jimenez return (PCAP_ERROR_NOT_ACTIVATED);
29311077d0bdSPeter Avalos return (p->linktype);
29321077d0bdSPeter Avalos }
29331077d0bdSPeter Avalos
29341077d0bdSPeter Avalos int
2935de0d3203SPeter Avalos pcap_datalink_ext(pcap_t *p)
2936de0d3203SPeter Avalos {
293797a9217aSAntonio Huete Jimenez if (!p->activated)
293897a9217aSAntonio Huete Jimenez return (PCAP_ERROR_NOT_ACTIVATED);
2939de0d3203SPeter Avalos return (p->linktype_ext);
2940de0d3203SPeter Avalos }
2941de0d3203SPeter Avalos
2942de0d3203SPeter Avalos int
29431077d0bdSPeter Avalos pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
29441077d0bdSPeter Avalos {
294597a9217aSAntonio Huete Jimenez if (!p->activated)
294697a9217aSAntonio Huete Jimenez return (PCAP_ERROR_NOT_ACTIVATED);
29471077d0bdSPeter Avalos if (p->dlt_count == 0) {
29481077d0bdSPeter Avalos /*
29491077d0bdSPeter Avalos * We couldn't fetch the list of DLTs, which means
29501077d0bdSPeter Avalos * this platform doesn't support changing the
29511077d0bdSPeter Avalos * DLT for an interface. Return a list of DLTs
29521077d0bdSPeter Avalos * containing only the DLT this device supports.
29531077d0bdSPeter Avalos */
29541077d0bdSPeter Avalos *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer));
29551077d0bdSPeter Avalos if (*dlt_buffer == NULL) {
29563a289941SAaron LI pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
29573a289941SAaron LI errno, "malloc");
295897a9217aSAntonio Huete Jimenez return (PCAP_ERROR);
29591077d0bdSPeter Avalos }
29601077d0bdSPeter Avalos **dlt_buffer = p->linktype;
29611077d0bdSPeter Avalos return (1);
29621077d0bdSPeter Avalos } else {
29631077d0bdSPeter Avalos *dlt_buffer = (int*)calloc(sizeof(**dlt_buffer), p->dlt_count);
29641077d0bdSPeter Avalos if (*dlt_buffer == NULL) {
29653a289941SAaron LI pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
29663a289941SAaron LI errno, "malloc");
296797a9217aSAntonio Huete Jimenez return (PCAP_ERROR);
29681077d0bdSPeter Avalos }
29691077d0bdSPeter Avalos (void)memcpy(*dlt_buffer, p->dlt_list,
29701077d0bdSPeter Avalos sizeof(**dlt_buffer) * p->dlt_count);
29711077d0bdSPeter Avalos return (p->dlt_count);
29721077d0bdSPeter Avalos }
29731077d0bdSPeter Avalos }
29741077d0bdSPeter Avalos
2975de0d3203SPeter Avalos /*
2976de0d3203SPeter Avalos * In Windows, you might have a library built with one version of the
2977de0d3203SPeter Avalos * C runtime library and an application built with another version of
2978de0d3203SPeter Avalos * the C runtime library, which means that the library might use one
2979de0d3203SPeter Avalos * version of malloc() and free() and the application might use another
2980de0d3203SPeter Avalos * version of malloc() and free(). If so, that means something
2981de0d3203SPeter Avalos * allocated by the library cannot be freed by the application, so we
2982de0d3203SPeter Avalos * need to have a pcap_free_datalinks() routine to free up the list
2983de0d3203SPeter Avalos * allocated by pcap_list_datalinks(), even though it's just a wrapper
2984de0d3203SPeter Avalos * around free().
2985de0d3203SPeter Avalos */
2986de0d3203SPeter Avalos void
2987de0d3203SPeter Avalos pcap_free_datalinks(int *dlt_list)
2988de0d3203SPeter Avalos {
2989de0d3203SPeter Avalos free(dlt_list);
2990de0d3203SPeter Avalos }
2991de0d3203SPeter Avalos
29921077d0bdSPeter Avalos int
29931077d0bdSPeter Avalos pcap_set_datalink(pcap_t *p, int dlt)
29941077d0bdSPeter Avalos {
29951077d0bdSPeter Avalos int i;
29961077d0bdSPeter Avalos const char *dlt_name;
29971077d0bdSPeter Avalos
299897a9217aSAntonio Huete Jimenez if (dlt < 0)
299997a9217aSAntonio Huete Jimenez goto unsupported;
300097a9217aSAntonio Huete Jimenez
30011077d0bdSPeter Avalos if (p->dlt_count == 0 || p->set_datalink_op == NULL) {
30021077d0bdSPeter Avalos /*
30031077d0bdSPeter Avalos * We couldn't fetch the list of DLTs, or we don't
30041077d0bdSPeter Avalos * have a "set datalink" operation, which means
30051077d0bdSPeter Avalos * this platform doesn't support changing the
30061077d0bdSPeter Avalos * DLT for an interface. Check whether the new
30071077d0bdSPeter Avalos * DLT is the one this interface supports.
30081077d0bdSPeter Avalos */
30091077d0bdSPeter Avalos if (p->linktype != dlt)
30101077d0bdSPeter Avalos goto unsupported;
30111077d0bdSPeter Avalos
30121077d0bdSPeter Avalos /*
30131077d0bdSPeter Avalos * It is, so there's nothing we need to do here.
30141077d0bdSPeter Avalos */
30151077d0bdSPeter Avalos return (0);
30161077d0bdSPeter Avalos }
30171077d0bdSPeter Avalos for (i = 0; i < p->dlt_count; i++)
301897a9217aSAntonio Huete Jimenez if (p->dlt_list[i] == (u_int)dlt)
30191077d0bdSPeter Avalos break;
30201077d0bdSPeter Avalos if (i >= p->dlt_count)
30211077d0bdSPeter Avalos goto unsupported;
30221077d0bdSPeter Avalos if (p->dlt_count == 2 && p->dlt_list[0] == DLT_EN10MB &&
30231077d0bdSPeter Avalos dlt == DLT_DOCSIS) {
30241077d0bdSPeter Avalos /*
30251077d0bdSPeter Avalos * This is presumably an Ethernet device, as the first
30261077d0bdSPeter Avalos * link-layer type it offers is DLT_EN10MB, and the only
30271077d0bdSPeter Avalos * other type it offers is DLT_DOCSIS. That means that
30281077d0bdSPeter Avalos * we can't tell the driver to supply DOCSIS link-layer
30291077d0bdSPeter Avalos * headers - we're just pretending that's what we're
30301077d0bdSPeter Avalos * getting, as, presumably, we're capturing on a dedicated
30311077d0bdSPeter Avalos * link to a Cisco Cable Modem Termination System, and
30321077d0bdSPeter Avalos * it's putting raw DOCSIS frames on the wire inside low-level
30331077d0bdSPeter Avalos * Ethernet framing.
30341077d0bdSPeter Avalos */
30351077d0bdSPeter Avalos p->linktype = dlt;
30361077d0bdSPeter Avalos return (0);
30371077d0bdSPeter Avalos }
30381077d0bdSPeter Avalos if (p->set_datalink_op(p, dlt) == -1)
30391077d0bdSPeter Avalos return (-1);
30401077d0bdSPeter Avalos p->linktype = dlt;
30411077d0bdSPeter Avalos return (0);
30421077d0bdSPeter Avalos
30431077d0bdSPeter Avalos unsupported:
30441077d0bdSPeter Avalos dlt_name = pcap_datalink_val_to_name(dlt);
30451077d0bdSPeter Avalos if (dlt_name != NULL) {
3046*ea16f64eSAntonio Huete Jimenez (void) snprintf(p->errbuf, sizeof(p->errbuf),
30471077d0bdSPeter Avalos "%s is not one of the DLTs supported by this device",
30481077d0bdSPeter Avalos dlt_name);
30491077d0bdSPeter Avalos } else {
3050*ea16f64eSAntonio Huete Jimenez (void) snprintf(p->errbuf, sizeof(p->errbuf),
30511077d0bdSPeter Avalos "DLT %d is not one of the DLTs supported by this device",
30521077d0bdSPeter Avalos dlt);
30531077d0bdSPeter Avalos }
30541077d0bdSPeter Avalos return (-1);
30551077d0bdSPeter Avalos }
30561077d0bdSPeter Avalos
30571077d0bdSPeter Avalos /*
30581077d0bdSPeter Avalos * This array is designed for mapping upper and lower case letter
30591077d0bdSPeter Avalos * together for a case independent comparison. The mappings are
30601077d0bdSPeter Avalos * based upon ascii character sequences.
30611077d0bdSPeter Avalos */
30621077d0bdSPeter Avalos static const u_char charmap[] = {
30631077d0bdSPeter Avalos (u_char)'\000', (u_char)'\001', (u_char)'\002', (u_char)'\003',
30641077d0bdSPeter Avalos (u_char)'\004', (u_char)'\005', (u_char)'\006', (u_char)'\007',
30651077d0bdSPeter Avalos (u_char)'\010', (u_char)'\011', (u_char)'\012', (u_char)'\013',
30661077d0bdSPeter Avalos (u_char)'\014', (u_char)'\015', (u_char)'\016', (u_char)'\017',
30671077d0bdSPeter Avalos (u_char)'\020', (u_char)'\021', (u_char)'\022', (u_char)'\023',
30681077d0bdSPeter Avalos (u_char)'\024', (u_char)'\025', (u_char)'\026', (u_char)'\027',
30691077d0bdSPeter Avalos (u_char)'\030', (u_char)'\031', (u_char)'\032', (u_char)'\033',
30701077d0bdSPeter Avalos (u_char)'\034', (u_char)'\035', (u_char)'\036', (u_char)'\037',
30711077d0bdSPeter Avalos (u_char)'\040', (u_char)'\041', (u_char)'\042', (u_char)'\043',
30721077d0bdSPeter Avalos (u_char)'\044', (u_char)'\045', (u_char)'\046', (u_char)'\047',
30731077d0bdSPeter Avalos (u_char)'\050', (u_char)'\051', (u_char)'\052', (u_char)'\053',
30741077d0bdSPeter Avalos (u_char)'\054', (u_char)'\055', (u_char)'\056', (u_char)'\057',
30751077d0bdSPeter Avalos (u_char)'\060', (u_char)'\061', (u_char)'\062', (u_char)'\063',
30761077d0bdSPeter Avalos (u_char)'\064', (u_char)'\065', (u_char)'\066', (u_char)'\067',
30771077d0bdSPeter Avalos (u_char)'\070', (u_char)'\071', (u_char)'\072', (u_char)'\073',
30781077d0bdSPeter Avalos (u_char)'\074', (u_char)'\075', (u_char)'\076', (u_char)'\077',
30791077d0bdSPeter Avalos (u_char)'\100', (u_char)'\141', (u_char)'\142', (u_char)'\143',
30801077d0bdSPeter Avalos (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
30811077d0bdSPeter Avalos (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
30821077d0bdSPeter Avalos (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
30831077d0bdSPeter Avalos (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
30841077d0bdSPeter Avalos (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
30851077d0bdSPeter Avalos (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\133',
30861077d0bdSPeter Avalos (u_char)'\134', (u_char)'\135', (u_char)'\136', (u_char)'\137',
30871077d0bdSPeter Avalos (u_char)'\140', (u_char)'\141', (u_char)'\142', (u_char)'\143',
30881077d0bdSPeter Avalos (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
30891077d0bdSPeter Avalos (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
30901077d0bdSPeter Avalos (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
30911077d0bdSPeter Avalos (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
30921077d0bdSPeter Avalos (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
30931077d0bdSPeter Avalos (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\173',
30941077d0bdSPeter Avalos (u_char)'\174', (u_char)'\175', (u_char)'\176', (u_char)'\177',
30951077d0bdSPeter Avalos (u_char)'\200', (u_char)'\201', (u_char)'\202', (u_char)'\203',
30961077d0bdSPeter Avalos (u_char)'\204', (u_char)'\205', (u_char)'\206', (u_char)'\207',
30971077d0bdSPeter Avalos (u_char)'\210', (u_char)'\211', (u_char)'\212', (u_char)'\213',
30981077d0bdSPeter Avalos (u_char)'\214', (u_char)'\215', (u_char)'\216', (u_char)'\217',
30991077d0bdSPeter Avalos (u_char)'\220', (u_char)'\221', (u_char)'\222', (u_char)'\223',
31001077d0bdSPeter Avalos (u_char)'\224', (u_char)'\225', (u_char)'\226', (u_char)'\227',
31011077d0bdSPeter Avalos (u_char)'\230', (u_char)'\231', (u_char)'\232', (u_char)'\233',
31021077d0bdSPeter Avalos (u_char)'\234', (u_char)'\235', (u_char)'\236', (u_char)'\237',
31031077d0bdSPeter Avalos (u_char)'\240', (u_char)'\241', (u_char)'\242', (u_char)'\243',
31041077d0bdSPeter Avalos (u_char)'\244', (u_char)'\245', (u_char)'\246', (u_char)'\247',
31051077d0bdSPeter Avalos (u_char)'\250', (u_char)'\251', (u_char)'\252', (u_char)'\253',
31061077d0bdSPeter Avalos (u_char)'\254', (u_char)'\255', (u_char)'\256', (u_char)'\257',
31071077d0bdSPeter Avalos (u_char)'\260', (u_char)'\261', (u_char)'\262', (u_char)'\263',
31081077d0bdSPeter Avalos (u_char)'\264', (u_char)'\265', (u_char)'\266', (u_char)'\267',
31091077d0bdSPeter Avalos (u_char)'\270', (u_char)'\271', (u_char)'\272', (u_char)'\273',
31101077d0bdSPeter Avalos (u_char)'\274', (u_char)'\275', (u_char)'\276', (u_char)'\277',
31111077d0bdSPeter Avalos (u_char)'\300', (u_char)'\341', (u_char)'\342', (u_char)'\343',
31121077d0bdSPeter Avalos (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347',
31131077d0bdSPeter Avalos (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353',
31141077d0bdSPeter Avalos (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357',
31151077d0bdSPeter Avalos (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363',
31161077d0bdSPeter Avalos (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367',
31171077d0bdSPeter Avalos (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\333',
31181077d0bdSPeter Avalos (u_char)'\334', (u_char)'\335', (u_char)'\336', (u_char)'\337',
31191077d0bdSPeter Avalos (u_char)'\340', (u_char)'\341', (u_char)'\342', (u_char)'\343',
31201077d0bdSPeter Avalos (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347',
31211077d0bdSPeter Avalos (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353',
31221077d0bdSPeter Avalos (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357',
31231077d0bdSPeter Avalos (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363',
31241077d0bdSPeter Avalos (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367',
31251077d0bdSPeter Avalos (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\373',
31261077d0bdSPeter Avalos (u_char)'\374', (u_char)'\375', (u_char)'\376', (u_char)'\377',
31271077d0bdSPeter Avalos };
31281077d0bdSPeter Avalos
31291077d0bdSPeter Avalos int
31301077d0bdSPeter Avalos pcap_strcasecmp(const char *s1, const char *s2)
31311077d0bdSPeter Avalos {
31321077d0bdSPeter Avalos register const u_char *cm = charmap,
31331077d0bdSPeter Avalos *us1 = (const u_char *)s1,
31341077d0bdSPeter Avalos *us2 = (const u_char *)s2;
31351077d0bdSPeter Avalos
31361077d0bdSPeter Avalos while (cm[*us1] == cm[*us2++])
31371077d0bdSPeter Avalos if (*us1++ == '\0')
31381077d0bdSPeter Avalos return(0);
31391077d0bdSPeter Avalos return (cm[*us1] - cm[*--us2]);
31401077d0bdSPeter Avalos }
31411077d0bdSPeter Avalos
3142a85e14b0SPeter Avalos struct dlt_choice {
3143a85e14b0SPeter Avalos const char *name;
3144a85e14b0SPeter Avalos const char *description;
3145a85e14b0SPeter Avalos int dlt;
3146a85e14b0SPeter Avalos };
3147a85e14b0SPeter Avalos
314897a9217aSAntonio Huete Jimenez #define DLT_CHOICE(code, description) { #code, description, DLT_ ## code }
3149a85e14b0SPeter Avalos #define DLT_CHOICE_SENTINEL { NULL, NULL, 0 }
3150a85e14b0SPeter Avalos
3151a85e14b0SPeter Avalos static struct dlt_choice dlt_choices[] = {
315297a9217aSAntonio Huete Jimenez DLT_CHOICE(NULL, "BSD loopback"),
315397a9217aSAntonio Huete Jimenez DLT_CHOICE(EN10MB, "Ethernet"),
315497a9217aSAntonio Huete Jimenez DLT_CHOICE(IEEE802, "Token ring"),
315597a9217aSAntonio Huete Jimenez DLT_CHOICE(ARCNET, "BSD ARCNET"),
315697a9217aSAntonio Huete Jimenez DLT_CHOICE(SLIP, "SLIP"),
315797a9217aSAntonio Huete Jimenez DLT_CHOICE(PPP, "PPP"),
315897a9217aSAntonio Huete Jimenez DLT_CHOICE(FDDI, "FDDI"),
315997a9217aSAntonio Huete Jimenez DLT_CHOICE(ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"),
316097a9217aSAntonio Huete Jimenez DLT_CHOICE(RAW, "Raw IP"),
316197a9217aSAntonio Huete Jimenez DLT_CHOICE(SLIP_BSDOS, "BSD/OS SLIP"),
316297a9217aSAntonio Huete Jimenez DLT_CHOICE(PPP_BSDOS, "BSD/OS PPP"),
3163*ea16f64eSAntonio Huete Jimenez DLT_CHOICE(ATM_CLIP, "Linux Classical IP over ATM"),
316497a9217aSAntonio Huete Jimenez DLT_CHOICE(PPP_SERIAL, "PPP over serial"),
316597a9217aSAntonio Huete Jimenez DLT_CHOICE(PPP_ETHER, "PPPoE"),
316697a9217aSAntonio Huete Jimenez DLT_CHOICE(SYMANTEC_FIREWALL, "Symantec Firewall"),
316797a9217aSAntonio Huete Jimenez DLT_CHOICE(C_HDLC, "Cisco HDLC"),
316897a9217aSAntonio Huete Jimenez DLT_CHOICE(IEEE802_11, "802.11"),
316997a9217aSAntonio Huete Jimenez DLT_CHOICE(FRELAY, "Frame Relay"),
317097a9217aSAntonio Huete Jimenez DLT_CHOICE(LOOP, "OpenBSD loopback"),
317197a9217aSAntonio Huete Jimenez DLT_CHOICE(ENC, "OpenBSD encapsulated IP"),
31723a289941SAaron LI DLT_CHOICE(LINUX_SLL, "Linux cooked v1"),
317397a9217aSAntonio Huete Jimenez DLT_CHOICE(LTALK, "Localtalk"),
317497a9217aSAntonio Huete Jimenez DLT_CHOICE(PFLOG, "OpenBSD pflog file"),
317597a9217aSAntonio Huete Jimenez DLT_CHOICE(PFSYNC, "Packet filter state syncing"),
317697a9217aSAntonio Huete Jimenez DLT_CHOICE(PRISM_HEADER, "802.11 plus Prism header"),
317797a9217aSAntonio Huete Jimenez DLT_CHOICE(IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
317897a9217aSAntonio Huete Jimenez DLT_CHOICE(SUNATM, "Sun raw ATM"),
317997a9217aSAntonio Huete Jimenez DLT_CHOICE(IEEE802_11_RADIO, "802.11 plus radiotap header"),
318097a9217aSAntonio Huete Jimenez DLT_CHOICE(ARCNET_LINUX, "Linux ARCNET"),
318197a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
318297a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
318397a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_ES, "Juniper Encryption Services PIC"),
318497a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_GGSN, "Juniper GGSN PIC"),
318597a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_MFR, "Juniper FRF.16 Frame Relay"),
318697a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_ATM2, "Juniper ATM2 PIC"),
318797a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_SERVICES, "Juniper Advanced Services PIC"),
318897a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_ATM1, "Juniper ATM1 PIC"),
318997a9217aSAntonio Huete Jimenez DLT_CHOICE(APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
319097a9217aSAntonio Huete Jimenez DLT_CHOICE(MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"),
319197a9217aSAntonio Huete Jimenez DLT_CHOICE(MTP2, "SS7 MTP2"),
319297a9217aSAntonio Huete Jimenez DLT_CHOICE(MTP3, "SS7 MTP3"),
319397a9217aSAntonio Huete Jimenez DLT_CHOICE(SCCP, "SS7 SCCP"),
319497a9217aSAntonio Huete Jimenez DLT_CHOICE(DOCSIS, "DOCSIS"),
319597a9217aSAntonio Huete Jimenez DLT_CHOICE(LINUX_IRDA, "Linux IrDA"),
319697a9217aSAntonio Huete Jimenez DLT_CHOICE(IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
319797a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
319897a9217aSAntonio Huete Jimenez DLT_CHOICE(BACNET_MS_TP, "BACnet MS/TP"),
319997a9217aSAntonio Huete Jimenez DLT_CHOICE(PPP_PPPD, "PPP for pppd, with direction flag"),
320097a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_PPPOE, "Juniper PPPoE"),
320197a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
320297a9217aSAntonio Huete Jimenez DLT_CHOICE(GPRS_LLC, "GPRS LLC"),
320397a9217aSAntonio Huete Jimenez DLT_CHOICE(GPF_T, "GPF-T"),
320497a9217aSAntonio Huete Jimenez DLT_CHOICE(GPF_F, "GPF-F"),
320597a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_PIC_PEER, "Juniper PIC Peer"),
320697a9217aSAntonio Huete Jimenez DLT_CHOICE(ERF_ETH, "Ethernet with Endace ERF header"),
320797a9217aSAntonio Huete Jimenez DLT_CHOICE(ERF_POS, "Packet-over-SONET with Endace ERF header"),
320897a9217aSAntonio Huete Jimenez DLT_CHOICE(LINUX_LAPD, "Linux vISDN LAPD"),
320997a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_ETHER, "Juniper Ethernet"),
321097a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_PPP, "Juniper PPP"),
321197a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_FRELAY, "Juniper Frame Relay"),
321297a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_CHDLC, "Juniper C-HDLC"),
321397a9217aSAntonio Huete Jimenez DLT_CHOICE(MFR, "FRF.16 Frame Relay"),
321497a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_VP, "Juniper Voice PIC"),
321597a9217aSAntonio Huete Jimenez DLT_CHOICE(A429, "Arinc 429"),
321697a9217aSAntonio Huete Jimenez DLT_CHOICE(A653_ICM, "Arinc 653 Interpartition Communication"),
321797a9217aSAntonio Huete Jimenez DLT_CHOICE(USB_FREEBSD, "USB with FreeBSD header"),
321897a9217aSAntonio Huete Jimenez DLT_CHOICE(BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"),
321997a9217aSAntonio Huete Jimenez DLT_CHOICE(IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"),
322097a9217aSAntonio Huete Jimenez DLT_CHOICE(USB_LINUX, "USB with Linux header"),
322197a9217aSAntonio Huete Jimenez DLT_CHOICE(CAN20B, "Controller Area Network (CAN) v. 2.0B"),
322297a9217aSAntonio Huete Jimenez DLT_CHOICE(IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"),
322397a9217aSAntonio Huete Jimenez DLT_CHOICE(PPI, "Per-Packet Information"),
322497a9217aSAntonio Huete Jimenez DLT_CHOICE(IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"),
322597a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_ISM, "Juniper Integrated Service Module"),
322697a9217aSAntonio Huete Jimenez DLT_CHOICE(IEEE802_15_4, "IEEE 802.15.4 with FCS"),
322797a9217aSAntonio Huete Jimenez DLT_CHOICE(SITA, "SITA pseudo-header"),
322897a9217aSAntonio Huete Jimenez DLT_CHOICE(ERF, "Endace ERF header"),
322997a9217aSAntonio Huete Jimenez DLT_CHOICE(RAIF1, "Ethernet with u10 Networks pseudo-header"),
32303a289941SAaron LI DLT_CHOICE(IPMB_KONTRON, "IPMB with Kontron pseudo-header"),
323197a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_ST, "Juniper Secure Tunnel"),
323297a9217aSAntonio Huete Jimenez DLT_CHOICE(BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"),
323397a9217aSAntonio Huete Jimenez DLT_CHOICE(AX25_KISS, "AX.25 with KISS header"),
32343a289941SAaron LI DLT_CHOICE(IPMB_LINUX, "IPMB with Linux/Pigeon Point pseudo-header"),
323597a9217aSAntonio Huete Jimenez DLT_CHOICE(IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"),
323697a9217aSAntonio Huete Jimenez DLT_CHOICE(MPLS, "MPLS with label as link-layer header"),
323797a9217aSAntonio Huete Jimenez DLT_CHOICE(LINUX_EVDEV, "Linux evdev events"),
323897a9217aSAntonio Huete Jimenez DLT_CHOICE(USB_LINUX_MMAPPED, "USB with padded Linux header"),
323997a9217aSAntonio Huete Jimenez DLT_CHOICE(DECT, "DECT"),
324097a9217aSAntonio Huete Jimenez DLT_CHOICE(AOS, "AOS Space Data Link protocol"),
324197a9217aSAntonio Huete Jimenez DLT_CHOICE(WIHART, "Wireless HART"),
324297a9217aSAntonio Huete Jimenez DLT_CHOICE(FC_2, "Fibre Channel FC-2"),
324397a9217aSAntonio Huete Jimenez DLT_CHOICE(FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"),
324497a9217aSAntonio Huete Jimenez DLT_CHOICE(IPNET, "Solaris ipnet"),
324597a9217aSAntonio Huete Jimenez DLT_CHOICE(CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"),
324697a9217aSAntonio Huete Jimenez DLT_CHOICE(IPV4, "Raw IPv4"),
324797a9217aSAntonio Huete Jimenez DLT_CHOICE(IPV6, "Raw IPv6"),
324897a9217aSAntonio Huete Jimenez DLT_CHOICE(IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"),
324997a9217aSAntonio Huete Jimenez DLT_CHOICE(DBUS, "D-Bus"),
325097a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_VS, "Juniper Virtual Server"),
325197a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_SRX_E2E, "Juniper SRX E2E"),
325297a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"),
325397a9217aSAntonio Huete Jimenez DLT_CHOICE(DVB_CI, "DVB-CI"),
325497a9217aSAntonio Huete Jimenez DLT_CHOICE(MUX27010, "MUX27010"),
325597a9217aSAntonio Huete Jimenez DLT_CHOICE(STANAG_5066_D_PDU, "STANAG 5066 D_PDUs"),
325697a9217aSAntonio Huete Jimenez DLT_CHOICE(JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"),
325797a9217aSAntonio Huete Jimenez DLT_CHOICE(NFLOG, "Linux netfilter log messages"),
325897a9217aSAntonio Huete Jimenez DLT_CHOICE(NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"),
325997a9217aSAntonio Huete Jimenez DLT_CHOICE(NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"),
326097a9217aSAntonio Huete Jimenez DLT_CHOICE(IPOIB, "RFC 4391 IP-over-Infiniband"),
326197a9217aSAntonio Huete Jimenez DLT_CHOICE(MPEG_2_TS, "MPEG-2 transport stream"),
326297a9217aSAntonio Huete Jimenez DLT_CHOICE(NG40, "ng40 protocol tester Iub/Iur"),
326397a9217aSAntonio Huete Jimenez DLT_CHOICE(NFC_LLCP, "NFC LLCP PDUs with pseudo-header"),
326497a9217aSAntonio Huete Jimenez DLT_CHOICE(INFINIBAND, "InfiniBand"),
326597a9217aSAntonio Huete Jimenez DLT_CHOICE(SCTP, "SCTP"),
326697a9217aSAntonio Huete Jimenez DLT_CHOICE(USBPCAP, "USB with USBPcap header"),
326797a9217aSAntonio Huete Jimenez DLT_CHOICE(RTAC_SERIAL, "Schweitzer Engineering Laboratories RTAC packets"),
326897a9217aSAntonio Huete Jimenez DLT_CHOICE(BLUETOOTH_LE_LL, "Bluetooth Low Energy air interface"),
326997a9217aSAntonio Huete Jimenez DLT_CHOICE(NETLINK, "Linux netlink"),
327097a9217aSAntonio Huete Jimenez DLT_CHOICE(BLUETOOTH_LINUX_MONITOR, "Bluetooth Linux Monitor"),
327197a9217aSAntonio Huete Jimenez DLT_CHOICE(BLUETOOTH_BREDR_BB, "Bluetooth Basic Rate/Enhanced Data Rate baseband packets"),
327297a9217aSAntonio Huete Jimenez DLT_CHOICE(BLUETOOTH_LE_LL_WITH_PHDR, "Bluetooth Low Energy air interface with pseudo-header"),
327397a9217aSAntonio Huete Jimenez DLT_CHOICE(PROFIBUS_DL, "PROFIBUS data link layer"),
327497a9217aSAntonio Huete Jimenez DLT_CHOICE(PKTAP, "Apple DLT_PKTAP"),
327597a9217aSAntonio Huete Jimenez DLT_CHOICE(EPON, "Ethernet with 802.3 Clause 65 EPON preamble"),
327697a9217aSAntonio Huete Jimenez DLT_CHOICE(IPMI_HPM_2, "IPMI trace packets"),
327797a9217aSAntonio Huete Jimenez DLT_CHOICE(ZWAVE_R1_R2, "Z-Wave RF profile R1 and R2 packets"),
327897a9217aSAntonio Huete Jimenez DLT_CHOICE(ZWAVE_R3, "Z-Wave RF profile R3 packets"),
327997a9217aSAntonio Huete Jimenez DLT_CHOICE(WATTSTOPPER_DLM, "WattStopper Digital Lighting Management (DLM) and Legrand Nitoo Open protocol"),
328097a9217aSAntonio Huete Jimenez DLT_CHOICE(ISO_14443, "ISO 14443 messages"),
328197a9217aSAntonio Huete Jimenez DLT_CHOICE(RDS, "IEC 62106 Radio Data System groups"),
32823a289941SAaron LI DLT_CHOICE(USB_DARWIN, "USB with Darwin header"),
32833a289941SAaron LI DLT_CHOICE(OPENFLOW, "OpenBSD DLT_OPENFLOW"),
32843a289941SAaron LI DLT_CHOICE(SDLC, "IBM SDLC frames"),
32853a289941SAaron LI DLT_CHOICE(TI_LLN_SNIFFER, "TI LLN sniffer frames"),
32863a289941SAaron LI DLT_CHOICE(VSOCK, "Linux vsock"),
32873a289941SAaron LI DLT_CHOICE(NORDIC_BLE, "Nordic Semiconductor Bluetooth LE sniffer frames"),
32883a289941SAaron LI DLT_CHOICE(DOCSIS31_XRA31, "Excentis XRA-31 DOCSIS 3.1 RF sniffer frames"),
32893a289941SAaron LI DLT_CHOICE(ETHERNET_MPACKET, "802.3br mPackets"),
32903a289941SAaron LI DLT_CHOICE(DISPLAYPORT_AUX, "DisplayPort AUX channel monitoring data"),
32913a289941SAaron LI DLT_CHOICE(LINUX_SLL2, "Linux cooked v2"),
3292*ea16f64eSAntonio Huete Jimenez DLT_CHOICE(OPENVIZSLA, "OpenVizsla USB"),
3293*ea16f64eSAntonio Huete Jimenez DLT_CHOICE(EBHSCR, "Elektrobit High Speed Capture and Replay (EBHSCR)"),
3294*ea16f64eSAntonio Huete Jimenez DLT_CHOICE(VPP_DISPATCH, "VPP graph dispatch tracer"),
3295*ea16f64eSAntonio Huete Jimenez DLT_CHOICE(DSA_TAG_BRCM, "Broadcom tag"),
3296*ea16f64eSAntonio Huete Jimenez DLT_CHOICE(DSA_TAG_BRCM_PREPEND, "Broadcom tag (prepended)"),
3297*ea16f64eSAntonio Huete Jimenez DLT_CHOICE(IEEE802_15_4_TAP, "IEEE 802.15.4 with pseudo-header"),
3298*ea16f64eSAntonio Huete Jimenez DLT_CHOICE(DSA_TAG_DSA, "Marvell DSA"),
3299*ea16f64eSAntonio Huete Jimenez DLT_CHOICE(DSA_TAG_EDSA, "Marvell EDSA"),
3300*ea16f64eSAntonio Huete Jimenez DLT_CHOICE(ELEE, "ELEE lawful intercept packets"),
3301*ea16f64eSAntonio Huete Jimenez DLT_CHOICE(Z_WAVE_SERIAL, "Z-Wave serial frames between host and chip"),
3302*ea16f64eSAntonio Huete Jimenez DLT_CHOICE(USB_2_0, "USB 2.0/1.1/1.0 as transmitted over the cable"),
3303*ea16f64eSAntonio Huete Jimenez DLT_CHOICE(ATSC_ALP, "ATSC Link-Layer Protocol packets"),
3304a85e14b0SPeter Avalos DLT_CHOICE_SENTINEL
3305a85e14b0SPeter Avalos };
3306a85e14b0SPeter Avalos
33071077d0bdSPeter Avalos int
33081077d0bdSPeter Avalos pcap_datalink_name_to_val(const char *name)
33091077d0bdSPeter Avalos {
33101077d0bdSPeter Avalos int i;
33111077d0bdSPeter Avalos
33121077d0bdSPeter Avalos for (i = 0; dlt_choices[i].name != NULL; i++) {
331397a9217aSAntonio Huete Jimenez if (pcap_strcasecmp(dlt_choices[i].name, name) == 0)
33141077d0bdSPeter Avalos return (dlt_choices[i].dlt);
33151077d0bdSPeter Avalos }
33161077d0bdSPeter Avalos return (-1);
33171077d0bdSPeter Avalos }
33181077d0bdSPeter Avalos
33191077d0bdSPeter Avalos const char *
33201077d0bdSPeter Avalos pcap_datalink_val_to_name(int dlt)
33211077d0bdSPeter Avalos {
33221077d0bdSPeter Avalos int i;
33231077d0bdSPeter Avalos
33241077d0bdSPeter Avalos for (i = 0; dlt_choices[i].name != NULL; i++) {
33251077d0bdSPeter Avalos if (dlt_choices[i].dlt == dlt)
332697a9217aSAntonio Huete Jimenez return (dlt_choices[i].name);
33271077d0bdSPeter Avalos }
33281077d0bdSPeter Avalos return (NULL);
33291077d0bdSPeter Avalos }
33301077d0bdSPeter Avalos
33311077d0bdSPeter Avalos const char *
33321077d0bdSPeter Avalos pcap_datalink_val_to_description(int dlt)
33331077d0bdSPeter Avalos {
33341077d0bdSPeter Avalos int i;
33351077d0bdSPeter Avalos
33361077d0bdSPeter Avalos for (i = 0; dlt_choices[i].name != NULL; i++) {
33371077d0bdSPeter Avalos if (dlt_choices[i].dlt == dlt)
33381077d0bdSPeter Avalos return (dlt_choices[i].description);
33391077d0bdSPeter Avalos }
33401077d0bdSPeter Avalos return (NULL);
33411077d0bdSPeter Avalos }
33421077d0bdSPeter Avalos
33433a289941SAaron LI const char *
33443a289941SAaron LI pcap_datalink_val_to_description_or_dlt(int dlt)
33453a289941SAaron LI {
33463a289941SAaron LI static char unkbuf[40];
33473a289941SAaron LI const char *description;
33483a289941SAaron LI
33493a289941SAaron LI description = pcap_datalink_val_to_description(dlt);
33503a289941SAaron LI if (description != NULL) {
33513a289941SAaron LI return description;
33523a289941SAaron LI } else {
3353*ea16f64eSAntonio Huete Jimenez (void)snprintf(unkbuf, sizeof(unkbuf), "DLT %u", dlt);
33543a289941SAaron LI return unkbuf;
33553a289941SAaron LI }
33563a289941SAaron LI }
33573a289941SAaron LI
3358a85e14b0SPeter Avalos struct tstamp_type_choice {
3359a85e14b0SPeter Avalos const char *name;
3360a85e14b0SPeter Avalos const char *description;
3361a85e14b0SPeter Avalos int type;
3362a85e14b0SPeter Avalos };
3363a85e14b0SPeter Avalos
3364a85e14b0SPeter Avalos static struct tstamp_type_choice tstamp_type_choices[] = {
3365a85e14b0SPeter Avalos { "host", "Host", PCAP_TSTAMP_HOST },
3366a85e14b0SPeter Avalos { "host_lowprec", "Host, low precision", PCAP_TSTAMP_HOST_LOWPREC },
3367a85e14b0SPeter Avalos { "host_hiprec", "Host, high precision", PCAP_TSTAMP_HOST_HIPREC },
3368a85e14b0SPeter Avalos { "adapter", "Adapter", PCAP_TSTAMP_ADAPTER },
3369a85e14b0SPeter Avalos { "adapter_unsynced", "Adapter, not synced with system time", PCAP_TSTAMP_ADAPTER_UNSYNCED },
3370*ea16f64eSAntonio Huete Jimenez { "host_hiprec_unsynced", "Host, high precision, not synced with system time", PCAP_TSTAMP_HOST_HIPREC_UNSYNCED },
3371a85e14b0SPeter Avalos { NULL, NULL, 0 }
3372a85e14b0SPeter Avalos };
3373a85e14b0SPeter Avalos
3374a85e14b0SPeter Avalos int
3375a85e14b0SPeter Avalos pcap_tstamp_type_name_to_val(const char *name)
3376a85e14b0SPeter Avalos {
3377a85e14b0SPeter Avalos int i;
3378a85e14b0SPeter Avalos
3379a85e14b0SPeter Avalos for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
3380a85e14b0SPeter Avalos if (pcap_strcasecmp(tstamp_type_choices[i].name, name) == 0)
3381a85e14b0SPeter Avalos return (tstamp_type_choices[i].type);
3382a85e14b0SPeter Avalos }
3383a85e14b0SPeter Avalos return (PCAP_ERROR);
3384a85e14b0SPeter Avalos }
3385a85e14b0SPeter Avalos
3386a85e14b0SPeter Avalos const char *
3387a85e14b0SPeter Avalos pcap_tstamp_type_val_to_name(int tstamp_type)
3388a85e14b0SPeter Avalos {
3389a85e14b0SPeter Avalos int i;
3390a85e14b0SPeter Avalos
3391a85e14b0SPeter Avalos for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
3392a85e14b0SPeter Avalos if (tstamp_type_choices[i].type == tstamp_type)
3393a85e14b0SPeter Avalos return (tstamp_type_choices[i].name);
3394a85e14b0SPeter Avalos }
3395a85e14b0SPeter Avalos return (NULL);
3396a85e14b0SPeter Avalos }
3397a85e14b0SPeter Avalos
3398a85e14b0SPeter Avalos const char *
3399a85e14b0SPeter Avalos pcap_tstamp_type_val_to_description(int tstamp_type)
3400a85e14b0SPeter Avalos {
3401a85e14b0SPeter Avalos int i;
3402a85e14b0SPeter Avalos
3403a85e14b0SPeter Avalos for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
3404a85e14b0SPeter Avalos if (tstamp_type_choices[i].type == tstamp_type)
3405a85e14b0SPeter Avalos return (tstamp_type_choices[i].description);
3406a85e14b0SPeter Avalos }
3407a85e14b0SPeter Avalos return (NULL);
3408a85e14b0SPeter Avalos }
3409a85e14b0SPeter Avalos
34101077d0bdSPeter Avalos int
34111077d0bdSPeter Avalos pcap_snapshot(pcap_t *p)
34121077d0bdSPeter Avalos {
341397a9217aSAntonio Huete Jimenez if (!p->activated)
341497a9217aSAntonio Huete Jimenez return (PCAP_ERROR_NOT_ACTIVATED);
34151077d0bdSPeter Avalos return (p->snapshot);
34161077d0bdSPeter Avalos }
34171077d0bdSPeter Avalos
34181077d0bdSPeter Avalos int
34191077d0bdSPeter Avalos pcap_is_swapped(pcap_t *p)
34201077d0bdSPeter Avalos {
342197a9217aSAntonio Huete Jimenez if (!p->activated)
342297a9217aSAntonio Huete Jimenez return (PCAP_ERROR_NOT_ACTIVATED);
342397a9217aSAntonio Huete Jimenez return (p->swapped);
34241077d0bdSPeter Avalos }
34251077d0bdSPeter Avalos
34261077d0bdSPeter Avalos int
34271077d0bdSPeter Avalos pcap_major_version(pcap_t *p)
34281077d0bdSPeter Avalos {
342997a9217aSAntonio Huete Jimenez if (!p->activated)
343097a9217aSAntonio Huete Jimenez return (PCAP_ERROR_NOT_ACTIVATED);
343197a9217aSAntonio Huete Jimenez return (p->version_major);
34321077d0bdSPeter Avalos }
34331077d0bdSPeter Avalos
34341077d0bdSPeter Avalos int
34351077d0bdSPeter Avalos pcap_minor_version(pcap_t *p)
34361077d0bdSPeter Avalos {
343797a9217aSAntonio Huete Jimenez if (!p->activated)
343897a9217aSAntonio Huete Jimenez return (PCAP_ERROR_NOT_ACTIVATED);
343997a9217aSAntonio Huete Jimenez return (p->version_minor);
34401077d0bdSPeter Avalos }
34411077d0bdSPeter Avalos
34423a289941SAaron LI int
34433a289941SAaron LI pcap_bufsize(pcap_t *p)
34443a289941SAaron LI {
34453a289941SAaron LI if (!p->activated)
34463a289941SAaron LI return (PCAP_ERROR_NOT_ACTIVATED);
34473a289941SAaron LI return (p->bufsize);
34483a289941SAaron LI }
34493a289941SAaron LI
34501077d0bdSPeter Avalos FILE *
34511077d0bdSPeter Avalos pcap_file(pcap_t *p)
34521077d0bdSPeter Avalos {
345397a9217aSAntonio Huete Jimenez return (p->rfile);
34541077d0bdSPeter Avalos }
34551077d0bdSPeter Avalos
3456*ea16f64eSAntonio Huete Jimenez #ifdef _WIN32
34571077d0bdSPeter Avalos int
34581077d0bdSPeter Avalos pcap_fileno(pcap_t *p)
34591077d0bdSPeter Avalos {
3460*ea16f64eSAntonio Huete Jimenez if (p->handle != INVALID_HANDLE_VALUE) {
3461*ea16f64eSAntonio Huete Jimenez /*
3462*ea16f64eSAntonio Huete Jimenez * This is a bogus and now-deprecated API; we
3463*ea16f64eSAntonio Huete Jimenez * squelch the narrowing warning for the cast
3464*ea16f64eSAntonio Huete Jimenez * from HANDLE to DWORD. If Windows programmmers
3465*ea16f64eSAntonio Huete Jimenez * need to get at the HANDLE for a pcap_t, *if*
3466*ea16f64eSAntonio Huete Jimenez * there is one, they should request such a
3467*ea16f64eSAntonio Huete Jimenez * routine (and be prepared for it to return
3468*ea16f64eSAntonio Huete Jimenez * INVALID_HANDLE_VALUE).
3469*ea16f64eSAntonio Huete Jimenez */
3470*ea16f64eSAntonio Huete Jimenez DIAG_OFF_NARROWING
34713a289941SAaron LI return ((int)(DWORD)p->handle);
3472*ea16f64eSAntonio Huete Jimenez DIAG_ON_NARROWING
3473*ea16f64eSAntonio Huete Jimenez } else
347497a9217aSAntonio Huete Jimenez return (PCAP_ERROR);
34751077d0bdSPeter Avalos }
3476*ea16f64eSAntonio Huete Jimenez #else /* _WIN32 */
3477*ea16f64eSAntonio Huete Jimenez int
3478*ea16f64eSAntonio Huete Jimenez pcap_fileno(pcap_t *p)
3479*ea16f64eSAntonio Huete Jimenez {
3480*ea16f64eSAntonio Huete Jimenez return (p->fd);
3481*ea16f64eSAntonio Huete Jimenez }
3482*ea16f64eSAntonio Huete Jimenez #endif /* _WIN32 */
34831077d0bdSPeter Avalos
348497a9217aSAntonio Huete Jimenez #if !defined(_WIN32) && !defined(MSDOS)
34851077d0bdSPeter Avalos int
34861077d0bdSPeter Avalos pcap_get_selectable_fd(pcap_t *p)
34871077d0bdSPeter Avalos {
34881077d0bdSPeter Avalos return (p->selectable_fd);
34891077d0bdSPeter Avalos }
34903a289941SAaron LI
3491*ea16f64eSAntonio Huete Jimenez const struct timeval *
34923a289941SAaron LI pcap_get_required_select_timeout(pcap_t *p)
34933a289941SAaron LI {
34943a289941SAaron LI return (p->required_select_timeout);
34953a289941SAaron LI }
34961077d0bdSPeter Avalos #endif
34971077d0bdSPeter Avalos
34981077d0bdSPeter Avalos void
349997a9217aSAntonio Huete Jimenez pcap_perror(pcap_t *p, const char *prefix)
35001077d0bdSPeter Avalos {
35011077d0bdSPeter Avalos fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
35021077d0bdSPeter Avalos }
35031077d0bdSPeter Avalos
35041077d0bdSPeter Avalos char *
35051077d0bdSPeter Avalos pcap_geterr(pcap_t *p)
35061077d0bdSPeter Avalos {
35071077d0bdSPeter Avalos return (p->errbuf);
35081077d0bdSPeter Avalos }
35091077d0bdSPeter Avalos
35101077d0bdSPeter Avalos int
35111077d0bdSPeter Avalos pcap_getnonblock(pcap_t *p, char *errbuf)
35121077d0bdSPeter Avalos {
35130e381983SMatthew Dillon int ret;
35140e381983SMatthew Dillon
35153a289941SAaron LI ret = p->getnonblock_op(p);
35160e381983SMatthew Dillon if (ret == -1) {
35170e381983SMatthew Dillon /*
35183a289941SAaron LI * The get nonblock operation sets p->errbuf; this
35193a289941SAaron LI * function *shouldn't* have had a separate errbuf
35203a289941SAaron LI * argument, as it didn't need one, but I goofed
35213a289941SAaron LI * when adding it.
35223a289941SAaron LI *
35233a289941SAaron LI * We copy the error message to errbuf, so callers
35243a289941SAaron LI * can find it in either place.
35250e381983SMatthew Dillon */
35263a289941SAaron LI pcap_strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
35270e381983SMatthew Dillon }
35280e381983SMatthew Dillon return (ret);
35291077d0bdSPeter Avalos }
35301077d0bdSPeter Avalos
35311077d0bdSPeter Avalos /*
35321077d0bdSPeter Avalos * Get the current non-blocking mode setting, under the assumption that
35331077d0bdSPeter Avalos * it's just the standard POSIX non-blocking flag.
35341077d0bdSPeter Avalos */
353597a9217aSAntonio Huete Jimenez #if !defined(_WIN32) && !defined(MSDOS)
35361077d0bdSPeter Avalos int
35373a289941SAaron LI pcap_getnonblock_fd(pcap_t *p)
35381077d0bdSPeter Avalos {
35391077d0bdSPeter Avalos int fdflags;
35401077d0bdSPeter Avalos
35411077d0bdSPeter Avalos fdflags = fcntl(p->fd, F_GETFL, 0);
35421077d0bdSPeter Avalos if (fdflags == -1) {
35433a289941SAaron LI pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
35443a289941SAaron LI errno, "F_GETFL");
35451077d0bdSPeter Avalos return (-1);
35461077d0bdSPeter Avalos }
35471077d0bdSPeter Avalos if (fdflags & O_NONBLOCK)
35481077d0bdSPeter Avalos return (1);
35491077d0bdSPeter Avalos else
35501077d0bdSPeter Avalos return (0);
35511077d0bdSPeter Avalos }
35521077d0bdSPeter Avalos #endif
35531077d0bdSPeter Avalos
35541077d0bdSPeter Avalos int
35551077d0bdSPeter Avalos pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
35561077d0bdSPeter Avalos {
35570e381983SMatthew Dillon int ret;
35580e381983SMatthew Dillon
35593a289941SAaron LI ret = p->setnonblock_op(p, nonblock);
35600e381983SMatthew Dillon if (ret == -1) {
35610e381983SMatthew Dillon /*
35623a289941SAaron LI * The set nonblock operation sets p->errbuf; this
35633a289941SAaron LI * function *shouldn't* have had a separate errbuf
35643a289941SAaron LI * argument, as it didn't need one, but I goofed
35653a289941SAaron LI * when adding it.
35663a289941SAaron LI *
35673a289941SAaron LI * We copy the error message to errbuf, so callers
35683a289941SAaron LI * can find it in either place.
35690e381983SMatthew Dillon */
35703a289941SAaron LI pcap_strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
35710e381983SMatthew Dillon }
35720e381983SMatthew Dillon return (ret);
35731077d0bdSPeter Avalos }
35741077d0bdSPeter Avalos
357597a9217aSAntonio Huete Jimenez #if !defined(_WIN32) && !defined(MSDOS)
35761077d0bdSPeter Avalos /*
35771077d0bdSPeter Avalos * Set non-blocking mode, under the assumption that it's just the
35781077d0bdSPeter Avalos * standard POSIX non-blocking flag. (This can be called by the
35791077d0bdSPeter Avalos * per-platform non-blocking-mode routine if that routine also
35801077d0bdSPeter Avalos * needs to do some additional work.)
35811077d0bdSPeter Avalos */
35821077d0bdSPeter Avalos int
35833a289941SAaron LI pcap_setnonblock_fd(pcap_t *p, int nonblock)
35841077d0bdSPeter Avalos {
35851077d0bdSPeter Avalos int fdflags;
35861077d0bdSPeter Avalos
35871077d0bdSPeter Avalos fdflags = fcntl(p->fd, F_GETFL, 0);
35881077d0bdSPeter Avalos if (fdflags == -1) {
35893a289941SAaron LI pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
35903a289941SAaron LI errno, "F_GETFL");
35911077d0bdSPeter Avalos return (-1);
35921077d0bdSPeter Avalos }
35931077d0bdSPeter Avalos if (nonblock)
35941077d0bdSPeter Avalos fdflags |= O_NONBLOCK;
35951077d0bdSPeter Avalos else
35961077d0bdSPeter Avalos fdflags &= ~O_NONBLOCK;
35971077d0bdSPeter Avalos if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
35983a289941SAaron LI pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
35993a289941SAaron LI errno, "F_SETFL");
36001077d0bdSPeter Avalos return (-1);
36011077d0bdSPeter Avalos }
36021077d0bdSPeter Avalos return (0);
36031077d0bdSPeter Avalos }
36041077d0bdSPeter Avalos #endif
36051077d0bdSPeter Avalos
36061077d0bdSPeter Avalos /*
3607de0d3203SPeter Avalos * Generate error strings for PCAP_ERROR_ and PCAP_WARNING_ values.
3608de0d3203SPeter Avalos */
3609de0d3203SPeter Avalos const char *
3610de0d3203SPeter Avalos pcap_statustostr(int errnum)
3611de0d3203SPeter Avalos {
3612de0d3203SPeter Avalos static char ebuf[15+10+1];
3613de0d3203SPeter Avalos
3614de0d3203SPeter Avalos switch (errnum) {
3615de0d3203SPeter Avalos
3616de0d3203SPeter Avalos case PCAP_WARNING:
3617de0d3203SPeter Avalos return("Generic warning");
3618de0d3203SPeter Avalos
3619a85e14b0SPeter Avalos case PCAP_WARNING_TSTAMP_TYPE_NOTSUP:
3620a85e14b0SPeter Avalos return ("That type of time stamp is not supported by that device");
3621a85e14b0SPeter Avalos
3622de0d3203SPeter Avalos case PCAP_WARNING_PROMISC_NOTSUP:
3623de0d3203SPeter Avalos return ("That device doesn't support promiscuous mode");
3624de0d3203SPeter Avalos
3625de0d3203SPeter Avalos case PCAP_ERROR:
3626de0d3203SPeter Avalos return("Generic error");
3627de0d3203SPeter Avalos
3628de0d3203SPeter Avalos case PCAP_ERROR_BREAK:
3629de0d3203SPeter Avalos return("Loop terminated by pcap_breakloop");
3630de0d3203SPeter Avalos
3631de0d3203SPeter Avalos case PCAP_ERROR_NOT_ACTIVATED:
3632de0d3203SPeter Avalos return("The pcap_t has not been activated");
3633de0d3203SPeter Avalos
3634de0d3203SPeter Avalos case PCAP_ERROR_ACTIVATED:
3635de0d3203SPeter Avalos return ("The setting can't be changed after the pcap_t is activated");
3636de0d3203SPeter Avalos
3637de0d3203SPeter Avalos case PCAP_ERROR_NO_SUCH_DEVICE:
3638de0d3203SPeter Avalos return ("No such device exists");
3639de0d3203SPeter Avalos
3640de0d3203SPeter Avalos case PCAP_ERROR_RFMON_NOTSUP:
3641de0d3203SPeter Avalos return ("That device doesn't support monitor mode");
3642de0d3203SPeter Avalos
3643de0d3203SPeter Avalos case PCAP_ERROR_NOT_RFMON:
3644de0d3203SPeter Avalos return ("That operation is supported only in monitor mode");
3645de0d3203SPeter Avalos
3646de0d3203SPeter Avalos case PCAP_ERROR_PERM_DENIED:
3647de0d3203SPeter Avalos return ("You don't have permission to capture on that device");
3648de0d3203SPeter Avalos
3649de0d3203SPeter Avalos case PCAP_ERROR_IFACE_NOT_UP:
3650de0d3203SPeter Avalos return ("That device is not up");
3651a85e14b0SPeter Avalos
3652a85e14b0SPeter Avalos case PCAP_ERROR_CANTSET_TSTAMP_TYPE:
3653a85e14b0SPeter Avalos return ("That device doesn't support setting the time stamp type");
3654a85e14b0SPeter Avalos
3655a85e14b0SPeter Avalos case PCAP_ERROR_PROMISC_PERM_DENIED:
3656a85e14b0SPeter Avalos return ("You don't have permission to capture in promiscuous mode on that device");
365797a9217aSAntonio Huete Jimenez
365897a9217aSAntonio Huete Jimenez case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
365997a9217aSAntonio Huete Jimenez return ("That device doesn't support that time stamp precision");
3660de0d3203SPeter Avalos }
3661*ea16f64eSAntonio Huete Jimenez (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
3662de0d3203SPeter Avalos return(ebuf);
3663de0d3203SPeter Avalos }
3664de0d3203SPeter Avalos
3665de0d3203SPeter Avalos /*
36661077d0bdSPeter Avalos * Not all systems have strerror().
36671077d0bdSPeter Avalos */
36681077d0bdSPeter Avalos const char *
36691077d0bdSPeter Avalos pcap_strerror(int errnum)
36701077d0bdSPeter Avalos {
36711077d0bdSPeter Avalos #ifdef HAVE_STRERROR
367297a9217aSAntonio Huete Jimenez #ifdef _WIN32
367397a9217aSAntonio Huete Jimenez static char errbuf[PCAP_ERRBUF_SIZE];
36743a289941SAaron LI errno_t err = strerror_s(errbuf, PCAP_ERRBUF_SIZE, errnum);
36753a289941SAaron LI
36763a289941SAaron LI if (err != 0) /* err = 0 if successful */
36773a289941SAaron LI pcap_strlcpy(errbuf, "strerror_s() error", PCAP_ERRBUF_SIZE);
367897a9217aSAntonio Huete Jimenez return (errbuf);
367997a9217aSAntonio Huete Jimenez #else
36801077d0bdSPeter Avalos return (strerror(errnum));
368197a9217aSAntonio Huete Jimenez #endif /* _WIN32 */
36821077d0bdSPeter Avalos #else
36831077d0bdSPeter Avalos extern int sys_nerr;
36841077d0bdSPeter Avalos extern const char *const sys_errlist[];
368597a9217aSAntonio Huete Jimenez static char errbuf[PCAP_ERRBUF_SIZE];
36861077d0bdSPeter Avalos
36871077d0bdSPeter Avalos if ((unsigned int)errnum < sys_nerr)
36881077d0bdSPeter Avalos return ((char *)sys_errlist[errnum]);
3689*ea16f64eSAntonio Huete Jimenez (void)snprintf(errbuf, sizeof errbuf, "Unknown error: %d", errnum);
369097a9217aSAntonio Huete Jimenez return (errbuf);
36911077d0bdSPeter Avalos #endif
36921077d0bdSPeter Avalos }
36931077d0bdSPeter Avalos
36941077d0bdSPeter Avalos int
36951077d0bdSPeter Avalos pcap_setfilter(pcap_t *p, struct bpf_program *fp)
36961077d0bdSPeter Avalos {
3697a85e14b0SPeter Avalos return (p->setfilter_op(p, fp));
36981077d0bdSPeter Avalos }
36991077d0bdSPeter Avalos
37001077d0bdSPeter Avalos /*
37011077d0bdSPeter Avalos * Set direction flag, which controls whether we accept only incoming
37021077d0bdSPeter Avalos * packets, only outgoing packets, or both.
37031077d0bdSPeter Avalos * Note that, depending on the platform, some or all direction arguments
37041077d0bdSPeter Avalos * might not be supported.
37051077d0bdSPeter Avalos */
37061077d0bdSPeter Avalos int
37071077d0bdSPeter Avalos pcap_setdirection(pcap_t *p, pcap_direction_t d)
37081077d0bdSPeter Avalos {
37091077d0bdSPeter Avalos if (p->setdirection_op == NULL) {
3710*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
3711*ea16f64eSAntonio Huete Jimenez "Setting direction is not supported on this device");
3712a85e14b0SPeter Avalos return (-1);
3713*ea16f64eSAntonio Huete Jimenez } else {
3714*ea16f64eSAntonio Huete Jimenez switch (d) {
3715*ea16f64eSAntonio Huete Jimenez
3716*ea16f64eSAntonio Huete Jimenez case PCAP_D_IN:
3717*ea16f64eSAntonio Huete Jimenez case PCAP_D_OUT:
3718*ea16f64eSAntonio Huete Jimenez case PCAP_D_INOUT:
3719*ea16f64eSAntonio Huete Jimenez /*
3720*ea16f64eSAntonio Huete Jimenez * Valid direction.
3721*ea16f64eSAntonio Huete Jimenez */
3722a85e14b0SPeter Avalos return (p->setdirection_op(p, d));
3723*ea16f64eSAntonio Huete Jimenez
3724*ea16f64eSAntonio Huete Jimenez default:
3725*ea16f64eSAntonio Huete Jimenez /*
3726*ea16f64eSAntonio Huete Jimenez * Invalid direction.
3727*ea16f64eSAntonio Huete Jimenez */
3728*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, sizeof(p->errbuf),
3729*ea16f64eSAntonio Huete Jimenez "Invalid direction");
3730*ea16f64eSAntonio Huete Jimenez return (-1);
3731*ea16f64eSAntonio Huete Jimenez }
3732*ea16f64eSAntonio Huete Jimenez }
37331077d0bdSPeter Avalos }
37341077d0bdSPeter Avalos
37351077d0bdSPeter Avalos int
37361077d0bdSPeter Avalos pcap_stats(pcap_t *p, struct pcap_stat *ps)
37371077d0bdSPeter Avalos {
3738a85e14b0SPeter Avalos return (p->stats_op(p, ps));
37391077d0bdSPeter Avalos }
37401077d0bdSPeter Avalos
374197a9217aSAntonio Huete Jimenez #ifdef _WIN32
374297a9217aSAntonio Huete Jimenez struct pcap_stat *
374397a9217aSAntonio Huete Jimenez pcap_stats_ex(pcap_t *p, int *pcap_stat_size)
374497a9217aSAntonio Huete Jimenez {
374597a9217aSAntonio Huete Jimenez return (p->stats_ex_op(p, pcap_stat_size));
374697a9217aSAntonio Huete Jimenez }
374797a9217aSAntonio Huete Jimenez
3748de0d3203SPeter Avalos int
3749de0d3203SPeter Avalos pcap_setbuff(pcap_t *p, int dim)
37501077d0bdSPeter Avalos {
3751a85e14b0SPeter Avalos return (p->setbuff_op(p, dim));
3752de0d3203SPeter Avalos }
3753de0d3203SPeter Avalos
3754de0d3203SPeter Avalos int
3755de0d3203SPeter Avalos pcap_setmode(pcap_t *p, int mode)
3756de0d3203SPeter Avalos {
3757a85e14b0SPeter Avalos return (p->setmode_op(p, mode));
3758de0d3203SPeter Avalos }
3759de0d3203SPeter Avalos
3760de0d3203SPeter Avalos int
3761de0d3203SPeter Avalos pcap_setmintocopy(pcap_t *p, int size)
3762de0d3203SPeter Avalos {
3763a85e14b0SPeter Avalos return (p->setmintocopy_op(p, size));
3764de0d3203SPeter Avalos }
3765de0d3203SPeter Avalos
376697a9217aSAntonio Huete Jimenez HANDLE
376797a9217aSAntonio Huete Jimenez pcap_getevent(pcap_t *p)
376897a9217aSAntonio Huete Jimenez {
376997a9217aSAntonio Huete Jimenez return (p->getevent_op(p));
377097a9217aSAntonio Huete Jimenez }
377197a9217aSAntonio Huete Jimenez
377297a9217aSAntonio Huete Jimenez int
377397a9217aSAntonio Huete Jimenez pcap_oid_get_request(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
377497a9217aSAntonio Huete Jimenez {
377597a9217aSAntonio Huete Jimenez return (p->oid_get_request_op(p, oid, data, lenp));
377697a9217aSAntonio Huete Jimenez }
377797a9217aSAntonio Huete Jimenez
377897a9217aSAntonio Huete Jimenez int
377997a9217aSAntonio Huete Jimenez pcap_oid_set_request(pcap_t *p, bpf_u_int32 oid, const void *data, size_t *lenp)
378097a9217aSAntonio Huete Jimenez {
378197a9217aSAntonio Huete Jimenez return (p->oid_set_request_op(p, oid, data, lenp));
378297a9217aSAntonio Huete Jimenez }
378397a9217aSAntonio Huete Jimenez
378497a9217aSAntonio Huete Jimenez pcap_send_queue *
378597a9217aSAntonio Huete Jimenez pcap_sendqueue_alloc(u_int memsize)
378697a9217aSAntonio Huete Jimenez {
378797a9217aSAntonio Huete Jimenez pcap_send_queue *tqueue;
378897a9217aSAntonio Huete Jimenez
378997a9217aSAntonio Huete Jimenez /* Allocate the queue */
379097a9217aSAntonio Huete Jimenez tqueue = (pcap_send_queue *)malloc(sizeof(pcap_send_queue));
379197a9217aSAntonio Huete Jimenez if (tqueue == NULL){
379297a9217aSAntonio Huete Jimenez return (NULL);
379397a9217aSAntonio Huete Jimenez }
379497a9217aSAntonio Huete Jimenez
379597a9217aSAntonio Huete Jimenez /* Allocate the buffer */
379697a9217aSAntonio Huete Jimenez tqueue->buffer = (char *)malloc(memsize);
379797a9217aSAntonio Huete Jimenez if (tqueue->buffer == NULL) {
379897a9217aSAntonio Huete Jimenez free(tqueue);
379997a9217aSAntonio Huete Jimenez return (NULL);
380097a9217aSAntonio Huete Jimenez }
380197a9217aSAntonio Huete Jimenez
380297a9217aSAntonio Huete Jimenez tqueue->maxlen = memsize;
380397a9217aSAntonio Huete Jimenez tqueue->len = 0;
380497a9217aSAntonio Huete Jimenez
380597a9217aSAntonio Huete Jimenez return (tqueue);
380697a9217aSAntonio Huete Jimenez }
380797a9217aSAntonio Huete Jimenez
380897a9217aSAntonio Huete Jimenez void
380997a9217aSAntonio Huete Jimenez pcap_sendqueue_destroy(pcap_send_queue *queue)
381097a9217aSAntonio Huete Jimenez {
381197a9217aSAntonio Huete Jimenez free(queue->buffer);
381297a9217aSAntonio Huete Jimenez free(queue);
381397a9217aSAntonio Huete Jimenez }
381497a9217aSAntonio Huete Jimenez
381597a9217aSAntonio Huete Jimenez int
381697a9217aSAntonio Huete Jimenez pcap_sendqueue_queue(pcap_send_queue *queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
381797a9217aSAntonio Huete Jimenez {
381897a9217aSAntonio Huete Jimenez if (queue->len + sizeof(struct pcap_pkthdr) + pkt_header->caplen > queue->maxlen){
381997a9217aSAntonio Huete Jimenez return (-1);
382097a9217aSAntonio Huete Jimenez }
382197a9217aSAntonio Huete Jimenez
382297a9217aSAntonio Huete Jimenez /* Copy the pcap_pkthdr header*/
382397a9217aSAntonio Huete Jimenez memcpy(queue->buffer + queue->len, pkt_header, sizeof(struct pcap_pkthdr));
382497a9217aSAntonio Huete Jimenez queue->len += sizeof(struct pcap_pkthdr);
382597a9217aSAntonio Huete Jimenez
382697a9217aSAntonio Huete Jimenez /* copy the packet */
382797a9217aSAntonio Huete Jimenez memcpy(queue->buffer + queue->len, pkt_data, pkt_header->caplen);
382897a9217aSAntonio Huete Jimenez queue->len += pkt_header->caplen;
382997a9217aSAntonio Huete Jimenez
383097a9217aSAntonio Huete Jimenez return (0);
383197a9217aSAntonio Huete Jimenez }
383297a9217aSAntonio Huete Jimenez
383397a9217aSAntonio Huete Jimenez u_int
383497a9217aSAntonio Huete Jimenez pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue, int sync)
383597a9217aSAntonio Huete Jimenez {
383697a9217aSAntonio Huete Jimenez return (p->sendqueue_transmit_op(p, queue, sync));
383797a9217aSAntonio Huete Jimenez }
383897a9217aSAntonio Huete Jimenez
383997a9217aSAntonio Huete Jimenez int
384097a9217aSAntonio Huete Jimenez pcap_setuserbuffer(pcap_t *p, int size)
384197a9217aSAntonio Huete Jimenez {
384297a9217aSAntonio Huete Jimenez return (p->setuserbuffer_op(p, size));
384397a9217aSAntonio Huete Jimenez }
384497a9217aSAntonio Huete Jimenez
384597a9217aSAntonio Huete Jimenez int
384697a9217aSAntonio Huete Jimenez pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks)
384797a9217aSAntonio Huete Jimenez {
384897a9217aSAntonio Huete Jimenez return (p->live_dump_op(p, filename, maxsize, maxpacks));
384997a9217aSAntonio Huete Jimenez }
385097a9217aSAntonio Huete Jimenez
385197a9217aSAntonio Huete Jimenez int
385297a9217aSAntonio Huete Jimenez pcap_live_dump_ended(pcap_t *p, int sync)
385397a9217aSAntonio Huete Jimenez {
385497a9217aSAntonio Huete Jimenez return (p->live_dump_ended_op(p, sync));
385597a9217aSAntonio Huete Jimenez }
385697a9217aSAntonio Huete Jimenez
385797a9217aSAntonio Huete Jimenez PAirpcapHandle
385897a9217aSAntonio Huete Jimenez pcap_get_airpcap_handle(pcap_t *p)
385997a9217aSAntonio Huete Jimenez {
386097a9217aSAntonio Huete Jimenez PAirpcapHandle handle;
386197a9217aSAntonio Huete Jimenez
386297a9217aSAntonio Huete Jimenez handle = p->get_airpcap_handle_op(p);
386397a9217aSAntonio Huete Jimenez if (handle == NULL) {
3864*ea16f64eSAntonio Huete Jimenez (void)snprintf(p->errbuf, sizeof(p->errbuf),
386597a9217aSAntonio Huete Jimenez "This isn't an AirPcap device");
386697a9217aSAntonio Huete Jimenez }
386797a9217aSAntonio Huete Jimenez return (handle);
386897a9217aSAntonio Huete Jimenez }
3869de0d3203SPeter Avalos #endif
3870de0d3203SPeter Avalos
3871de0d3203SPeter Avalos /*
3872de0d3203SPeter Avalos * On some platforms, we need to clean up promiscuous or monitor mode
3873de0d3203SPeter Avalos * when we close a device - and we want that to happen even if the
3874de0d3203SPeter Avalos * application just exits without explicitl closing devices.
3875de0d3203SPeter Avalos * On those platforms, we need to register a "close all the pcaps"
3876de0d3203SPeter Avalos * routine to be called when we exit, and need to maintain a list of
3877de0d3203SPeter Avalos * pcaps that need to be closed to clean up modes.
3878de0d3203SPeter Avalos *
3879de0d3203SPeter Avalos * XXX - not thread-safe.
3880de0d3203SPeter Avalos */
3881de0d3203SPeter Avalos
3882de0d3203SPeter Avalos /*
3883de0d3203SPeter Avalos * List of pcaps on which we've done something that needs to be
3884de0d3203SPeter Avalos * cleaned up.
3885de0d3203SPeter Avalos * If there are any such pcaps, we arrange to call "pcap_close_all()"
3886de0d3203SPeter Avalos * when we exit, and have it close all of them.
3887de0d3203SPeter Avalos */
3888de0d3203SPeter Avalos static struct pcap *pcaps_to_close;
3889de0d3203SPeter Avalos
3890de0d3203SPeter Avalos /*
3891de0d3203SPeter Avalos * TRUE if we've already called "atexit()" to cause "pcap_close_all()" to
3892de0d3203SPeter Avalos * be called on exit.
3893de0d3203SPeter Avalos */
3894de0d3203SPeter Avalos static int did_atexit;
3895de0d3203SPeter Avalos
3896de0d3203SPeter Avalos static void
3897de0d3203SPeter Avalos pcap_close_all(void)
3898de0d3203SPeter Avalos {
3899de0d3203SPeter Avalos struct pcap *handle;
3900de0d3203SPeter Avalos
3901*ea16f64eSAntonio Huete Jimenez while ((handle = pcaps_to_close) != NULL) {
3902de0d3203SPeter Avalos pcap_close(handle);
3903*ea16f64eSAntonio Huete Jimenez
3904*ea16f64eSAntonio Huete Jimenez /*
3905*ea16f64eSAntonio Huete Jimenez * If a pcap module adds a pcap_t to the "close all"
3906*ea16f64eSAntonio Huete Jimenez * list by calling pcap_add_to_pcaps_to_close(), it
3907*ea16f64eSAntonio Huete Jimenez * must have a cleanup routine that removes it from the
3908*ea16f64eSAntonio Huete Jimenez * list, by calling pcap_remove_from_pcaps_to_close(),
3909*ea16f64eSAntonio Huete Jimenez * and must make that cleanup routine the cleanup_op
3910*ea16f64eSAntonio Huete Jimenez * for the pcap_t.
3911*ea16f64eSAntonio Huete Jimenez *
3912*ea16f64eSAntonio Huete Jimenez * That means that, after pcap_close() - which calls
3913*ea16f64eSAntonio Huete Jimenez * the cleanup_op for the pcap_t - the pcap_t must
3914*ea16f64eSAntonio Huete Jimenez * have been removed from the list, so pcaps_to_close
3915*ea16f64eSAntonio Huete Jimenez * must not be equal to handle.
3916*ea16f64eSAntonio Huete Jimenez *
3917*ea16f64eSAntonio Huete Jimenez * We check for that, and abort if handle is still
3918*ea16f64eSAntonio Huete Jimenez * at the head of the list, to prevent infinite loops.
3919*ea16f64eSAntonio Huete Jimenez */
3920*ea16f64eSAntonio Huete Jimenez if (pcaps_to_close == handle)
3921*ea16f64eSAntonio Huete Jimenez abort();
3922*ea16f64eSAntonio Huete Jimenez }
3923de0d3203SPeter Avalos }
3924de0d3203SPeter Avalos
3925de0d3203SPeter Avalos int
3926de0d3203SPeter Avalos pcap_do_addexit(pcap_t *p)
3927de0d3203SPeter Avalos {
3928de0d3203SPeter Avalos /*
3929de0d3203SPeter Avalos * If we haven't already done so, arrange to have
3930de0d3203SPeter Avalos * "pcap_close_all()" called when we exit.
3931de0d3203SPeter Avalos */
3932de0d3203SPeter Avalos if (!did_atexit) {
393397a9217aSAntonio Huete Jimenez if (atexit(pcap_close_all) != 0) {
3934de0d3203SPeter Avalos /*
3935de0d3203SPeter Avalos * "atexit()" failed; let our caller know.
3936de0d3203SPeter Avalos */
39373a289941SAaron LI pcap_strlcpy(p->errbuf, "atexit failed", PCAP_ERRBUF_SIZE);
3938de0d3203SPeter Avalos return (0);
3939de0d3203SPeter Avalos }
3940de0d3203SPeter Avalos did_atexit = 1;
3941de0d3203SPeter Avalos }
3942de0d3203SPeter Avalos return (1);
3943de0d3203SPeter Avalos }
3944de0d3203SPeter Avalos
3945de0d3203SPeter Avalos void
3946de0d3203SPeter Avalos pcap_add_to_pcaps_to_close(pcap_t *p)
3947de0d3203SPeter Avalos {
394897a9217aSAntonio Huete Jimenez p->next = pcaps_to_close;
3949de0d3203SPeter Avalos pcaps_to_close = p;
3950de0d3203SPeter Avalos }
3951de0d3203SPeter Avalos
3952de0d3203SPeter Avalos void
3953de0d3203SPeter Avalos pcap_remove_from_pcaps_to_close(pcap_t *p)
3954de0d3203SPeter Avalos {
3955de0d3203SPeter Avalos pcap_t *pc, *prevpc;
3956de0d3203SPeter Avalos
3957de0d3203SPeter Avalos for (pc = pcaps_to_close, prevpc = NULL; pc != NULL;
395897a9217aSAntonio Huete Jimenez prevpc = pc, pc = pc->next) {
3959de0d3203SPeter Avalos if (pc == p) {
3960de0d3203SPeter Avalos /*
3961de0d3203SPeter Avalos * Found it. Remove it from the list.
3962de0d3203SPeter Avalos */
3963de0d3203SPeter Avalos if (prevpc == NULL) {
3964de0d3203SPeter Avalos /*
3965de0d3203SPeter Avalos * It was at the head of the list.
3966de0d3203SPeter Avalos */
396797a9217aSAntonio Huete Jimenez pcaps_to_close = pc->next;
3968de0d3203SPeter Avalos } else {
3969de0d3203SPeter Avalos /*
3970de0d3203SPeter Avalos * It was in the middle of the list.
3971de0d3203SPeter Avalos */
397297a9217aSAntonio Huete Jimenez prevpc->next = pc->next;
3973de0d3203SPeter Avalos }
3974de0d3203SPeter Avalos break;
3975de0d3203SPeter Avalos }
3976de0d3203SPeter Avalos }
3977de0d3203SPeter Avalos }
3978de0d3203SPeter Avalos
3979de0d3203SPeter Avalos void
3980*ea16f64eSAntonio Huete Jimenez pcap_breakloop_common(pcap_t *p)
3981*ea16f64eSAntonio Huete Jimenez {
3982*ea16f64eSAntonio Huete Jimenez p->break_loop = 1;
3983*ea16f64eSAntonio Huete Jimenez }
3984*ea16f64eSAntonio Huete Jimenez
3985*ea16f64eSAntonio Huete Jimenez
3986*ea16f64eSAntonio Huete Jimenez void
3987de0d3203SPeter Avalos pcap_cleanup_live_common(pcap_t *p)
3988de0d3203SPeter Avalos {
3989de0d3203SPeter Avalos if (p->buffer != NULL) {
39901077d0bdSPeter Avalos free(p->buffer);
3991de0d3203SPeter Avalos p->buffer = NULL;
3992de0d3203SPeter Avalos }
3993de0d3203SPeter Avalos if (p->dlt_list != NULL) {
3994de0d3203SPeter Avalos free(p->dlt_list);
3995de0d3203SPeter Avalos p->dlt_list = NULL;
3996de0d3203SPeter Avalos p->dlt_count = 0;
3997de0d3203SPeter Avalos }
3998a85e14b0SPeter Avalos if (p->tstamp_type_list != NULL) {
3999a85e14b0SPeter Avalos free(p->tstamp_type_list);
4000a85e14b0SPeter Avalos p->tstamp_type_list = NULL;
4001a85e14b0SPeter Avalos p->tstamp_type_count = 0;
4002a85e14b0SPeter Avalos }
400397a9217aSAntonio Huete Jimenez if (p->tstamp_precision_list != NULL) {
400497a9217aSAntonio Huete Jimenez free(p->tstamp_precision_list);
400597a9217aSAntonio Huete Jimenez p->tstamp_precision_list = NULL;
400697a9217aSAntonio Huete Jimenez p->tstamp_precision_count = 0;
400797a9217aSAntonio Huete Jimenez }
4008de0d3203SPeter Avalos pcap_freecode(&p->fcode);
400997a9217aSAntonio Huete Jimenez #if !defined(_WIN32) && !defined(MSDOS)
4010de0d3203SPeter Avalos if (p->fd >= 0) {
40111077d0bdSPeter Avalos close(p->fd);
4012de0d3203SPeter Avalos p->fd = -1;
4013de0d3203SPeter Avalos }
4014a85e14b0SPeter Avalos p->selectable_fd = -1;
40151077d0bdSPeter Avalos #endif
40161077d0bdSPeter Avalos }
40171077d0bdSPeter Avalos
40181077d0bdSPeter Avalos /*
40191077d0bdSPeter Avalos * API compatible with WinPcap's "send a packet" routine - returns -1
40201077d0bdSPeter Avalos * on error, 0 otherwise.
40211077d0bdSPeter Avalos *
40221077d0bdSPeter Avalos * XXX - what if we get a short write?
40231077d0bdSPeter Avalos */
40241077d0bdSPeter Avalos int
40251077d0bdSPeter Avalos pcap_sendpacket(pcap_t *p, const u_char *buf, int size)
40261077d0bdSPeter Avalos {
4027*ea16f64eSAntonio Huete Jimenez if (size <= 0) {
4028*ea16f64eSAntonio Huete Jimenez pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
4029*ea16f64eSAntonio Huete Jimenez errno, "The number of bytes to be sent must be positive");
4030*ea16f64eSAntonio Huete Jimenez return (PCAP_ERROR);
4031*ea16f64eSAntonio Huete Jimenez }
4032*ea16f64eSAntonio Huete Jimenez
40331077d0bdSPeter Avalos if (p->inject_op(p, buf, size) == -1)
40341077d0bdSPeter Avalos return (-1);
40351077d0bdSPeter Avalos return (0);
40361077d0bdSPeter Avalos }
40371077d0bdSPeter Avalos
40381077d0bdSPeter Avalos /*
40391077d0bdSPeter Avalos * API compatible with OpenBSD's "send a packet" routine - returns -1 on
40401077d0bdSPeter Avalos * error, number of bytes written otherwise.
40411077d0bdSPeter Avalos */
40421077d0bdSPeter Avalos int
40431077d0bdSPeter Avalos pcap_inject(pcap_t *p, const void *buf, size_t size)
40441077d0bdSPeter Avalos {
4045*ea16f64eSAntonio Huete Jimenez /*
4046*ea16f64eSAntonio Huete Jimenez * We return the number of bytes written, so the number of
4047*ea16f64eSAntonio Huete Jimenez * bytes to write must fit in an int.
4048*ea16f64eSAntonio Huete Jimenez */
4049*ea16f64eSAntonio Huete Jimenez if (size > INT_MAX) {
4050*ea16f64eSAntonio Huete Jimenez pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
4051*ea16f64eSAntonio Huete Jimenez errno, "More than %d bytes cannot be injected", INT_MAX);
4052*ea16f64eSAntonio Huete Jimenez return (PCAP_ERROR);
4053*ea16f64eSAntonio Huete Jimenez }
4054*ea16f64eSAntonio Huete Jimenez
4055*ea16f64eSAntonio Huete Jimenez if (size == 0) {
4056*ea16f64eSAntonio Huete Jimenez pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
4057*ea16f64eSAntonio Huete Jimenez errno, "The number of bytes to be injected must not be zero");
4058*ea16f64eSAntonio Huete Jimenez return (PCAP_ERROR);
4059*ea16f64eSAntonio Huete Jimenez }
4060*ea16f64eSAntonio Huete Jimenez
4061*ea16f64eSAntonio Huete Jimenez return (p->inject_op(p, buf, (int)size));
40621077d0bdSPeter Avalos }
40631077d0bdSPeter Avalos
40641077d0bdSPeter Avalos void
40651077d0bdSPeter Avalos pcap_close(pcap_t *p)
40661077d0bdSPeter Avalos {
406797a9217aSAntonio Huete Jimenez if (p->opt.device != NULL)
406897a9217aSAntonio Huete Jimenez free(p->opt.device);
4069de0d3203SPeter Avalos p->cleanup_op(p);
40701077d0bdSPeter Avalos free(p);
40711077d0bdSPeter Avalos }
40721077d0bdSPeter Avalos
40731077d0bdSPeter Avalos /*
4074*ea16f64eSAntonio Huete Jimenez * Helpers for safely loding code at run time.
4075*ea16f64eSAntonio Huete Jimenez * Currently Windows-only.
4076*ea16f64eSAntonio Huete Jimenez */
4077*ea16f64eSAntonio Huete Jimenez #ifdef _WIN32
4078*ea16f64eSAntonio Huete Jimenez //
4079*ea16f64eSAntonio Huete Jimenez // This wrapper around loadlibrary appends the system folder (usually
4080*ea16f64eSAntonio Huete Jimenez // C:\Windows\System32) to the relative path of the DLL, so that the DLL
4081*ea16f64eSAntonio Huete Jimenez // is always loaded from an absolute path (it's no longer possible to
4082*ea16f64eSAntonio Huete Jimenez // load modules from the application folder).
4083*ea16f64eSAntonio Huete Jimenez // This solves the DLL Hijacking issue discovered in August 2010:
4084*ea16f64eSAntonio Huete Jimenez //
4085*ea16f64eSAntonio Huete Jimenez // https://blog.rapid7.com/2010/08/23/exploiting-dll-hijacking-flaws/
4086*ea16f64eSAntonio Huete Jimenez // https://blog.rapid7.com/2010/08/23/application-dll-load-hijacking/
4087*ea16f64eSAntonio Huete Jimenez // (the purported Rapid7 blog post link in the first of those two links
4088*ea16f64eSAntonio Huete Jimenez // is broken; the second of those links works.)
4089*ea16f64eSAntonio Huete Jimenez //
4090*ea16f64eSAntonio Huete Jimenez // If any links there are broken from all the content shuffling Rapid&
4091*ea16f64eSAntonio Huete Jimenez // did, see archived versions of the posts at their original homes, at
4092*ea16f64eSAntonio Huete Jimenez //
4093*ea16f64eSAntonio Huete Jimenez // https://web.archive.org/web/20110122175058/http://blog.metasploit.com/2010/08/exploiting-dll-hijacking-flaws.html
4094*ea16f64eSAntonio Huete Jimenez // https://web.archive.org/web/20100828112111/http://blog.rapid7.com/?p=5325
4095*ea16f64eSAntonio Huete Jimenez //
4096*ea16f64eSAntonio Huete Jimenez pcap_code_handle_t
4097*ea16f64eSAntonio Huete Jimenez pcap_load_code(const char *name)
4098*ea16f64eSAntonio Huete Jimenez {
4099*ea16f64eSAntonio Huete Jimenez /*
4100*ea16f64eSAntonio Huete Jimenez * XXX - should this work in UTF-16LE rather than in the local
4101*ea16f64eSAntonio Huete Jimenez * ANSI code page?
4102*ea16f64eSAntonio Huete Jimenez */
4103*ea16f64eSAntonio Huete Jimenez CHAR path[MAX_PATH];
4104*ea16f64eSAntonio Huete Jimenez CHAR fullFileName[MAX_PATH];
4105*ea16f64eSAntonio Huete Jimenez UINT res;
4106*ea16f64eSAntonio Huete Jimenez HMODULE hModule = NULL;
4107*ea16f64eSAntonio Huete Jimenez
4108*ea16f64eSAntonio Huete Jimenez do
4109*ea16f64eSAntonio Huete Jimenez {
4110*ea16f64eSAntonio Huete Jimenez res = GetSystemDirectoryA(path, MAX_PATH);
4111*ea16f64eSAntonio Huete Jimenez
4112*ea16f64eSAntonio Huete Jimenez if (res == 0) {
4113*ea16f64eSAntonio Huete Jimenez //
4114*ea16f64eSAntonio Huete Jimenez // some bad failure occurred;
4115*ea16f64eSAntonio Huete Jimenez //
4116*ea16f64eSAntonio Huete Jimenez break;
4117*ea16f64eSAntonio Huete Jimenez }
4118*ea16f64eSAntonio Huete Jimenez
4119*ea16f64eSAntonio Huete Jimenez if (res > MAX_PATH) {
4120*ea16f64eSAntonio Huete Jimenez //
4121*ea16f64eSAntonio Huete Jimenez // the buffer was not big enough
4122*ea16f64eSAntonio Huete Jimenez //
4123*ea16f64eSAntonio Huete Jimenez SetLastError(ERROR_INSUFFICIENT_BUFFER);
4124*ea16f64eSAntonio Huete Jimenez break;
4125*ea16f64eSAntonio Huete Jimenez }
4126*ea16f64eSAntonio Huete Jimenez
4127*ea16f64eSAntonio Huete Jimenez if (res + 1 + strlen(name) + 1 < MAX_PATH) {
4128*ea16f64eSAntonio Huete Jimenez memcpy(fullFileName, path, res * sizeof(TCHAR));
4129*ea16f64eSAntonio Huete Jimenez fullFileName[res] = '\\';
4130*ea16f64eSAntonio Huete Jimenez memcpy(&fullFileName[res + 1], name, (strlen(name) + 1) * sizeof(TCHAR));
4131*ea16f64eSAntonio Huete Jimenez
4132*ea16f64eSAntonio Huete Jimenez hModule = LoadLibraryA(fullFileName);
4133*ea16f64eSAntonio Huete Jimenez } else
4134*ea16f64eSAntonio Huete Jimenez SetLastError(ERROR_INSUFFICIENT_BUFFER);
4135*ea16f64eSAntonio Huete Jimenez
4136*ea16f64eSAntonio Huete Jimenez } while(FALSE);
4137*ea16f64eSAntonio Huete Jimenez
4138*ea16f64eSAntonio Huete Jimenez return hModule;
4139*ea16f64eSAntonio Huete Jimenez }
4140*ea16f64eSAntonio Huete Jimenez
4141*ea16f64eSAntonio Huete Jimenez pcap_funcptr_t
4142*ea16f64eSAntonio Huete Jimenez pcap_find_function(pcap_code_handle_t code, const char *func)
4143*ea16f64eSAntonio Huete Jimenez {
4144*ea16f64eSAntonio Huete Jimenez return (GetProcAddress(code, func));
4145*ea16f64eSAntonio Huete Jimenez }
4146*ea16f64eSAntonio Huete Jimenez #endif
4147*ea16f64eSAntonio Huete Jimenez
4148*ea16f64eSAntonio Huete Jimenez /*
4149de0d3203SPeter Avalos * Given a BPF program, a pcap_pkthdr structure for a packet, and the raw
4150de0d3203SPeter Avalos * data for the packet, check whether the packet passes the filter.
4151de0d3203SPeter Avalos * Returns the return value of the filter program, which will be zero if
4152de0d3203SPeter Avalos * the packet doesn't pass and non-zero if the packet does pass.
4153de0d3203SPeter Avalos */
4154de0d3203SPeter Avalos int
41550e381983SMatthew Dillon pcap_offline_filter(const struct bpf_program *fp, const struct pcap_pkthdr *h,
4156de0d3203SPeter Avalos const u_char *pkt)
4157de0d3203SPeter Avalos {
41580e381983SMatthew Dillon const struct bpf_insn *fcode = fp->bf_insns;
4159de0d3203SPeter Avalos
4160de0d3203SPeter Avalos if (fcode != NULL)
4161*ea16f64eSAntonio Huete Jimenez return (pcap_filter(fcode, pkt, h->len, h->caplen));
4162de0d3203SPeter Avalos else
4163de0d3203SPeter Avalos return (0);
4164de0d3203SPeter Avalos }
4165de0d3203SPeter Avalos
41663a289941SAaron LI static int
41673a289941SAaron LI pcap_can_set_rfmon_dead(pcap_t *p)
41683a289941SAaron LI {
4169*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
41703a289941SAaron LI "Rfmon mode doesn't apply on a pcap_open_dead pcap_t");
41713a289941SAaron LI return (PCAP_ERROR);
41723a289941SAaron LI }
41733a289941SAaron LI
41743a289941SAaron LI static int
41753a289941SAaron LI pcap_read_dead(pcap_t *p, int cnt _U_, pcap_handler callback _U_,
41763a289941SAaron LI u_char *user _U_)
41773a289941SAaron LI {
4178*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
41793a289941SAaron LI "Packets aren't available from a pcap_open_dead pcap_t");
41803a289941SAaron LI return (-1);
41813a289941SAaron LI }
41823a289941SAaron LI
41833a289941SAaron LI static int
4184*ea16f64eSAntonio Huete Jimenez pcap_inject_dead(pcap_t *p, const void *buf _U_, int size _U_)
41853a289941SAaron LI {
4186*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
41873a289941SAaron LI "Packets can't be sent on a pcap_open_dead pcap_t");
41883a289941SAaron LI return (-1);
41893a289941SAaron LI }
41903a289941SAaron LI
41913a289941SAaron LI static int
41923a289941SAaron LI pcap_setfilter_dead(pcap_t *p, struct bpf_program *fp _U_)
41933a289941SAaron LI {
4194*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
41953a289941SAaron LI "A filter cannot be set on a pcap_open_dead pcap_t");
41963a289941SAaron LI return (-1);
41973a289941SAaron LI }
41983a289941SAaron LI
41993a289941SAaron LI static int
42003a289941SAaron LI pcap_setdirection_dead(pcap_t *p, pcap_direction_t d _U_)
42013a289941SAaron LI {
4202*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
42033a289941SAaron LI "The packet direction cannot be set on a pcap_open_dead pcap_t");
42043a289941SAaron LI return (-1);
42053a289941SAaron LI }
42063a289941SAaron LI
42073a289941SAaron LI static int
42083a289941SAaron LI pcap_set_datalink_dead(pcap_t *p, int dlt _U_)
42093a289941SAaron LI {
4210*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
42113a289941SAaron LI "The link-layer header type cannot be set on a pcap_open_dead pcap_t");
42123a289941SAaron LI return (-1);
42133a289941SAaron LI }
42143a289941SAaron LI
42153a289941SAaron LI static int
42163a289941SAaron LI pcap_getnonblock_dead(pcap_t *p)
42173a289941SAaron LI {
4218*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
42193a289941SAaron LI "A pcap_open_dead pcap_t does not have a non-blocking mode setting");
42203a289941SAaron LI return (-1);
42213a289941SAaron LI }
42223a289941SAaron LI
42233a289941SAaron LI static int
42243a289941SAaron LI pcap_setnonblock_dead(pcap_t *p, int nonblock _U_)
42253a289941SAaron LI {
4226*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
42273a289941SAaron LI "A pcap_open_dead pcap_t does not have a non-blocking mode setting");
42283a289941SAaron LI return (-1);
42293a289941SAaron LI }
42303a289941SAaron LI
42313a289941SAaron LI static int
42323a289941SAaron LI pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_)
42333a289941SAaron LI {
4234*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
42353a289941SAaron LI "Statistics aren't available from a pcap_open_dead pcap_t");
42363a289941SAaron LI return (-1);
42373a289941SAaron LI }
42381077d0bdSPeter Avalos
423997a9217aSAntonio Huete Jimenez #ifdef _WIN32
4240*ea16f64eSAntonio Huete Jimenez static struct pcap_stat *
42413a289941SAaron LI pcap_stats_ex_dead(pcap_t *p, int *pcap_stat_size _U_)
42421077d0bdSPeter Avalos {
4243*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
42443a289941SAaron LI "Statistics aren't available from a pcap_open_dead pcap_t");
424597a9217aSAntonio Huete Jimenez return (NULL);
42461077d0bdSPeter Avalos }
42471077d0bdSPeter Avalos
42483a289941SAaron LI static int
4249*ea16f64eSAntonio Huete Jimenez pcap_setbuff_dead(pcap_t *p, int dim _U_)
425097a9217aSAntonio Huete Jimenez {
4251*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
42523a289941SAaron LI "The kernel buffer size cannot be set on a pcap_open_dead pcap_t");
42533a289941SAaron LI return (-1);
425497a9217aSAntonio Huete Jimenez }
425597a9217aSAntonio Huete Jimenez
42563a289941SAaron LI static int
4257*ea16f64eSAntonio Huete Jimenez pcap_setmode_dead(pcap_t *p, int mode _U_)
42581077d0bdSPeter Avalos {
4259*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
42603a289941SAaron LI "impossible to set mode on a pcap_open_dead pcap_t");
42613a289941SAaron LI return (-1);
42621077d0bdSPeter Avalos }
42631077d0bdSPeter Avalos
42643a289941SAaron LI static int
4265*ea16f64eSAntonio Huete Jimenez pcap_setmintocopy_dead(pcap_t *p, int size _U_)
42661077d0bdSPeter Avalos {
4267*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
42683a289941SAaron LI "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t");
42693a289941SAaron LI return (-1);
42701077d0bdSPeter Avalos }
42713a289941SAaron LI
42723a289941SAaron LI static HANDLE
42733a289941SAaron LI pcap_getevent_dead(pcap_t *p)
42743a289941SAaron LI {
4275*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
42763a289941SAaron LI "A pcap_open_dead pcap_t has no event handle");
42773a289941SAaron LI return (INVALID_HANDLE_VALUE);
42783a289941SAaron LI }
42793a289941SAaron LI
42803a289941SAaron LI static int
42813a289941SAaron LI pcap_oid_get_request_dead(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_,
42823a289941SAaron LI size_t *lenp _U_)
42833a289941SAaron LI {
4284*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
42853a289941SAaron LI "An OID get request cannot be performed on a pcap_open_dead pcap_t");
42863a289941SAaron LI return (PCAP_ERROR);
42873a289941SAaron LI }
42883a289941SAaron LI
42893a289941SAaron LI static int
42903a289941SAaron LI pcap_oid_set_request_dead(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
42913a289941SAaron LI size_t *lenp _U_)
42923a289941SAaron LI {
4293*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
42943a289941SAaron LI "An OID set request cannot be performed on a pcap_open_dead pcap_t");
42953a289941SAaron LI return (PCAP_ERROR);
42963a289941SAaron LI }
42973a289941SAaron LI
42983a289941SAaron LI static u_int
4299*ea16f64eSAntonio Huete Jimenez pcap_sendqueue_transmit_dead(pcap_t *p, pcap_send_queue *queue _U_,
4300*ea16f64eSAntonio Huete Jimenez int sync _U_)
43013a289941SAaron LI {
4302*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
43033a289941SAaron LI "Packets cannot be transmitted on a pcap_open_dead pcap_t");
43043a289941SAaron LI return (0);
43053a289941SAaron LI }
43063a289941SAaron LI
43073a289941SAaron LI static int
4308*ea16f64eSAntonio Huete Jimenez pcap_setuserbuffer_dead(pcap_t *p, int size _U_)
43093a289941SAaron LI {
4310*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
43113a289941SAaron LI "The user buffer cannot be set on a pcap_open_dead pcap_t");
43123a289941SAaron LI return (-1);
43133a289941SAaron LI }
43143a289941SAaron LI
43153a289941SAaron LI static int
4316*ea16f64eSAntonio Huete Jimenez pcap_live_dump_dead(pcap_t *p, char *filename _U_, int maxsize _U_,
4317*ea16f64eSAntonio Huete Jimenez int maxpacks _U_)
43183a289941SAaron LI {
4319*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
43203a289941SAaron LI "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
43213a289941SAaron LI return (-1);
43223a289941SAaron LI }
43233a289941SAaron LI
43243a289941SAaron LI static int
4325*ea16f64eSAntonio Huete Jimenez pcap_live_dump_ended_dead(pcap_t *p, int sync _U_)
43263a289941SAaron LI {
4327*ea16f64eSAntonio Huete Jimenez snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
43283a289941SAaron LI "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
43293a289941SAaron LI return (-1);
43303a289941SAaron LI }
43313a289941SAaron LI
43323a289941SAaron LI static PAirpcapHandle
4333*ea16f64eSAntonio Huete Jimenez pcap_get_airpcap_handle_dead(pcap_t *p _U_)
43343a289941SAaron LI {
43353a289941SAaron LI return (NULL);
43363a289941SAaron LI }
43373a289941SAaron LI #endif /* _WIN32 */
43383a289941SAaron LI
43393a289941SAaron LI static void
43403a289941SAaron LI pcap_cleanup_dead(pcap_t *p _U_)
43413a289941SAaron LI {
43423a289941SAaron LI /* Nothing to do. */
43433a289941SAaron LI }
43443a289941SAaron LI
43453a289941SAaron LI pcap_t *
43463a289941SAaron LI pcap_open_dead_with_tstamp_precision(int linktype, int snaplen, u_int precision)
43473a289941SAaron LI {
43483a289941SAaron LI pcap_t *p;
43493a289941SAaron LI
43503a289941SAaron LI switch (precision) {
43513a289941SAaron LI
43523a289941SAaron LI case PCAP_TSTAMP_PRECISION_MICRO:
43533a289941SAaron LI case PCAP_TSTAMP_PRECISION_NANO:
43543a289941SAaron LI break;
43553a289941SAaron LI
43563a289941SAaron LI default:
43573a289941SAaron LI /*
43583a289941SAaron LI * This doesn't really matter, but we don't have any way
43593a289941SAaron LI * to report particular errors, so the only failure we
43603a289941SAaron LI * should have is a memory allocation failure. Just
43613a289941SAaron LI * pick microsecond precision.
43623a289941SAaron LI */
43633a289941SAaron LI precision = PCAP_TSTAMP_PRECISION_MICRO;
43643a289941SAaron LI break;
43653a289941SAaron LI }
43663a289941SAaron LI p = malloc(sizeof(*p));
43673a289941SAaron LI if (p == NULL)
43683a289941SAaron LI return NULL;
43693a289941SAaron LI memset (p, 0, sizeof(*p));
43703a289941SAaron LI p->snapshot = snaplen;
43713a289941SAaron LI p->linktype = linktype;
43723a289941SAaron LI p->opt.tstamp_precision = precision;
43733a289941SAaron LI p->can_set_rfmon_op = pcap_can_set_rfmon_dead;
43743a289941SAaron LI p->read_op = pcap_read_dead;
43753a289941SAaron LI p->inject_op = pcap_inject_dead;
43763a289941SAaron LI p->setfilter_op = pcap_setfilter_dead;
43773a289941SAaron LI p->setdirection_op = pcap_setdirection_dead;
43783a289941SAaron LI p->set_datalink_op = pcap_set_datalink_dead;
43793a289941SAaron LI p->getnonblock_op = pcap_getnonblock_dead;
43803a289941SAaron LI p->setnonblock_op = pcap_setnonblock_dead;
43813a289941SAaron LI p->stats_op = pcap_stats_dead;
43823a289941SAaron LI #ifdef _WIN32
43833a289941SAaron LI p->stats_ex_op = pcap_stats_ex_dead;
43843a289941SAaron LI p->setbuff_op = pcap_setbuff_dead;
43853a289941SAaron LI p->setmode_op = pcap_setmode_dead;
43863a289941SAaron LI p->setmintocopy_op = pcap_setmintocopy_dead;
43873a289941SAaron LI p->getevent_op = pcap_getevent_dead;
43883a289941SAaron LI p->oid_get_request_op = pcap_oid_get_request_dead;
43893a289941SAaron LI p->oid_set_request_op = pcap_oid_set_request_dead;
43903a289941SAaron LI p->sendqueue_transmit_op = pcap_sendqueue_transmit_dead;
43913a289941SAaron LI p->setuserbuffer_op = pcap_setuserbuffer_dead;
43923a289941SAaron LI p->live_dump_op = pcap_live_dump_dead;
43933a289941SAaron LI p->live_dump_ended_op = pcap_live_dump_ended_dead;
43943a289941SAaron LI p->get_airpcap_handle_op = pcap_get_airpcap_handle_dead;
43951077d0bdSPeter Avalos #endif
43963a289941SAaron LI p->cleanup_op = pcap_cleanup_dead;
43973a289941SAaron LI
43983a289941SAaron LI /*
43993a289941SAaron LI * A "dead" pcap_t never requires special BPF code generation.
44003a289941SAaron LI */
44013a289941SAaron LI p->bpf_codegen_flags = 0;
44023a289941SAaron LI
44033a289941SAaron LI p->activated = 1;
44043a289941SAaron LI return (p);
44053a289941SAaron LI }
44063a289941SAaron LI
44073a289941SAaron LI pcap_t *
44083a289941SAaron LI pcap_open_dead(int linktype, int snaplen)
44093a289941SAaron LI {
44103a289941SAaron LI return (pcap_open_dead_with_tstamp_precision(linktype, snaplen,
44113a289941SAaron LI PCAP_TSTAMP_PRECISION_MICRO));
44123a289941SAaron LI }
441397a9217aSAntonio Huete Jimenez
441497a9217aSAntonio Huete Jimenez #ifdef YYDEBUG
441597a9217aSAntonio Huete Jimenez /*
441697a9217aSAntonio Huete Jimenez * Set the internal "debug printout" flag for the filter expression parser.
441797a9217aSAntonio Huete Jimenez * The code to print that stuff is present only if YYDEBUG is defined, so
441897a9217aSAntonio Huete Jimenez * the flag, and the routine to set it, are defined only if YYDEBUG is
441997a9217aSAntonio Huete Jimenez * defined.
442097a9217aSAntonio Huete Jimenez *
442197a9217aSAntonio Huete Jimenez * This is intended for libpcap developers, not for general use.
442297a9217aSAntonio Huete Jimenez * If you want to set these in a program, you'll have to declare this
442397a9217aSAntonio Huete Jimenez * routine yourself, with the appropriate DLL import attribute on Windows;
442497a9217aSAntonio Huete Jimenez * it's not declared in any header file, and won't be declared in any
442597a9217aSAntonio Huete Jimenez * header file provided by libpcap.
442697a9217aSAntonio Huete Jimenez */
442797a9217aSAntonio Huete Jimenez PCAP_API void pcap_set_parser_debug(int value);
442897a9217aSAntonio Huete Jimenez
442997a9217aSAntonio Huete Jimenez PCAP_API_DEF void
443097a9217aSAntonio Huete Jimenez pcap_set_parser_debug(int value)
443197a9217aSAntonio Huete Jimenez {
443297a9217aSAntonio Huete Jimenez pcap_debug = value;
443397a9217aSAntonio Huete Jimenez }
443497a9217aSAntonio Huete Jimenez #endif
4435