1f0fdf33pst/*
2ca0d84cfenner * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
3f0fdf33pst *	The Regents of the University of California.  All rights reserved.
4f0fdf33pst *
5f0fdf33pst * Redistribution and use in source and binary forms, with or without
6f0fdf33pst * modification, are permitted provided that the following conditions
7f0fdf33pst * are met:
8f0fdf33pst * 1. Redistributions of source code must retain the above copyright
9f0fdf33pst *    notice, this list of conditions and the following disclaimer.
10f0fdf33pst * 2. Redistributions in binary form must reproduce the above copyright
11f0fdf33pst *    notice, this list of conditions and the following disclaimer in the
12f0fdf33pst *    documentation and/or other materials provided with the distribution.
13f0fdf33pst * 3. All advertising materials mentioning features or use of this software
14f0fdf33pst *    must display the following acknowledgement:
15f0fdf33pst *	This product includes software developed by the Computer Systems
16f0fdf33pst *	Engineering Group at Lawrence Berkeley Laboratory.
17f0fdf33pst * 4. Neither the name of the University nor of the Laboratory may be used
18f0fdf33pst *    to endorse or promote products derived from this software without
19f0fdf33pst *    specific prior written permission.
20f0fdf33pst *
21f0fdf33pst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22f0fdf33pst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23f0fdf33pst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24f0fdf33pst * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25f0fdf33pst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26f0fdf33pst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27f0fdf33pst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28f0fdf33pst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29f0fdf33pst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30f0fdf33pst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31f0fdf33pst * SUCH DAMAGE.
32f0fdf33pst */
33f0fdf33pst
34a6bce88fenner#ifdef HAVE_CONFIG_H
3519bb0b8hselasky#include <config.h>
36f0fdf33pst#endif
37f0fdf33pst
3819bb0b8hselasky#include <pcap-types.h>
3919bb0b8hselasky#ifndef _WIN32
4019bb0b8hselasky#include <sys/param.h>
4119bb0b8hselasky#ifndef MSDOS
4219bb0b8hselasky#include <sys/file.h>
43724e1a0rpaulo#endif
4419bb0b8hselasky#include <sys/ioctl.h>
4519bb0b8hselasky#include <sys/socket.h>
4619bb0b8hselasky#ifdef HAVE_SYS_SOCKIO_H
4719bb0b8hselasky#include <sys/sockio.h>
48724e1a0rpaulo#endif
4919bb0b8hselasky
5019bb0b8hselaskystruct mbuf;		/* Squelch compiler warnings on some platforms for */
5119bb0b8hselaskystruct rtentry;		/* declarations in <net/if.h> */
5219bb0b8hselasky#include <net/if.h>
5319bb0b8hselasky#include <netinet/in.h>
5494960e5delphij#endif /* _WIN32 */
55f0fdf33pst
5619bb0b8hselasky#include <ctype.h>
57f0fdf33pst#include <stdio.h>
58f0fdf33pst#include <stdlib.h>
59f0fdf33pst#include <string.h>
60c5b3ac4gnn#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__MINGW32__)
61f0fdf33pst#include <unistd.h>
62da13a5abms#endif
631e8ea46fenner#include <fcntl.h>
641e8ea46fenner#include <errno.h>
6519bb0b8hselasky#ifdef HAVE_LIMITS_H
6619bb0b8hselasky#include <limits.h>
6719bb0b8hselasky#else
6819bb0b8hselasky#define INT_MAX		2147483647
6919bb0b8hselasky#endif
70f0fdf33pst
71f0fdf33pst#ifdef HAVE_OS_PROTO_H
72f0fdf33pst#include "os-proto.h"
73f0fdf33pst#endif
74f0fdf33pst
7570f7ae4sam#ifdef MSDOS
7670f7ae4sam#include "pcap-dos.h"
7770f7ae4sam#endif
7870f7ae4sam
79f0fdf33pst#include "pcap-int.h"
80f0fdf33pst
8119bb0b8hselasky#include "optimize.h"
8219bb0b8hselasky
83da13a5abms#ifdef HAVE_DAG_API
846181b42delphij#include "pcap-dag.h"
856181b42delphij#endif /* HAVE_DAG_API */
866181b42delphij
876181b42delphij#ifdef HAVE_SEPTEL_API
886181b42delphij#include "pcap-septel.h"
896181b42delphij#endif /* HAVE_SEPTEL_API */
906181b42delphij
916181b42delphij#ifdef HAVE_SNF_API
926181b42delphij#include "pcap-snf.h"
936181b42delphij#endif /* HAVE_SNF_API */
946181b42delphij
9594960e5delphij#ifdef HAVE_TC_API
9694960e5delphij#include "pcap-tc.h"
9794960e5delphij#endif /* HAVE_TC_API */
9894960e5delphij
996181b42delphij#ifdef PCAP_SUPPORT_USB
1006181b42delphij#include "pcap-usb-linux.h"
1016181b42delphij#endif
1026181b42delphij
1036181b42delphij#ifdef PCAP_SUPPORT_BT
1046181b42delphij#include "pcap-bt-linux.h"
1056181b42delphij#endif
1066181b42delphij
107489abeddelphij#ifdef PCAP_SUPPORT_BT_MONITOR
108489abeddelphij#include "pcap-bt-monitor-linux.h"
109489abeddelphij#endif
110489abeddelphij
1116181b42delphij#ifdef PCAP_SUPPORT_NETFILTER
1126181b42delphij#include "pcap-netfilter-linux.h"
113da13a5abms#endif
114da13a5abms
11519bb0b8hselasky#ifdef PCAP_SUPPORT_NETMAP
11619bb0b8hselasky#include "pcap-netmap.h"
11719bb0b8hselasky#endif
11819bb0b8hselasky
119489abeddelphij#ifdef PCAP_SUPPORT_DBUS
120489abeddelphij#include "pcap-dbus.h"
121489abeddelphij#endif
122489abeddelphij
12319bb0b8hselasky#ifdef PCAP_SUPPORT_RDMASNIFF
12419bb0b8hselasky#include "pcap-rdmasniff.h"
12519bb0b8hselasky#endif
12619bb0b8hselasky
12719bb0b8hselasky#ifdef _WIN32
12819bb0b8hselasky/*
12919bb0b8hselasky * DllMain(), required when built as a Windows DLL.
13019bb0b8hselasky */
13119bb0b8hselaskyBOOL WINAPI DllMain(
13219bb0b8hselasky  HANDLE hinstDLL,
13319bb0b8hselasky  DWORD dwReason,
13419bb0b8hselasky  LPVOID lpvReserved
13519bb0b8hselasky)
13619bb0b8hselasky{
13719bb0b8hselasky	return (TRUE);
13819bb0b8hselasky}
13919bb0b8hselasky
14019bb0b8hselasky/*
14119bb0b8hselasky * Start WinSock.
142c2630c9philip * Exported in case some applications using WinPcap/Npcap called it,
14319bb0b8hselasky * even though it wasn't exported.
14419bb0b8hselasky */
14519bb0b8hselaskyint
14619bb0b8hselaskywsockinit(void)
14719bb0b8hselasky{
14819bb0b8hselasky	WORD wVersionRequested;
14919bb0b8hselasky	WSADATA wsaData;
15019bb0b8hselasky	static int err = -1;
15119bb0b8hselasky	static int done = 0;
15219bb0b8hselasky
15319bb0b8hselasky	if (done)
15419bb0b8hselasky		return (err);
15519bb0b8hselasky
15619bb0b8hselasky	wVersionRequested = MAKEWORD( 1, 1);
15719bb0b8hselasky	err = WSAStartup( wVersionRequested, &wsaData );
15819bb0b8hselasky	atexit ((void(*)(void))WSACleanup);
15919bb0b8hselasky	done = 1;
16019bb0b8hselasky
16119bb0b8hselasky	if ( err != 0 )
16219bb0b8hselasky		err = -1;
16319bb0b8hselasky	return (err);
16419bb0b8hselasky}
16519bb0b8hselasky
16619bb0b8hselasky/*
16719bb0b8hselasky * This is the exported function; new programs should call this.
16819bb0b8hselasky */
16919bb0b8hselaskyint
17019bb0b8hselaskypcap_wsockinit(void)
17119bb0b8hselasky{
17219bb0b8hselasky       return (wsockinit());
17319bb0b8hselasky}
17419bb0b8hselasky#endif /* _WIN32 */
17519bb0b8hselasky
17619bb0b8hselasky/*
17719bb0b8hselasky * String containing the library version.
17819bb0b8hselasky * Not explicitly exported via a header file - the right API to use
17919bb0b8hselasky * is pcap_lib_version() - but some programs included it, so we
18019bb0b8hselasky * provide it.
18119bb0b8hselasky *
18219bb0b8hselasky * We declare it here, right before defining it, to squelch any
18319bb0b8hselasky * warnings we might get from compilers about the lack of a
18419bb0b8hselasky * declaration.
18519bb0b8hselasky */
18619bb0b8hselaskyPCAP_API char pcap_version[];
18719bb0b8hselaskyPCAP_API_DEF char pcap_version[] = PACKAGE_VERSION;
18819bb0b8hselasky
189c2630c9philipstatic void
190c2630c9philippcap_set_not_initialized_message(pcap_t *pcap)
191d8d18f6rpaulo{
19219bb0b8hselasky	if (pcap->activated) {
19319bb0b8hselasky		/* A module probably forgot to set the function pointer */
19419bb0b8hselasky		(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
19519bb0b8hselasky		    "This operation isn't properly handled by that device");
196c2630c9philip		return;
19719bb0b8hselasky	}
19894960e5delphij	/* in case the caller doesn't check for PCAP_ERROR_NOT_ACTIVATED */
19994960e5delphij	(void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
20094960e5delphij	    "This handle hasn't been activated yet");
201c2630c9philip}
202c2630c9philip
203c2630c9philipstatic int
204c2630c9philippcap_read_not_initialized(pcap_t *pcap, int cnt _U_, pcap_handler callback _U_,
205c2630c9philip    u_char *user _U_)
206c2630c9philip{
207c2630c9philip	pcap_set_not_initialized_message(pcap);
208c2630c9philip	/* this means 'not initialized' */
209c2630c9philip	return (PCAP_ERROR_NOT_ACTIVATED);
210c2630c9philip}
211c2630c9philip
212c2630c9philipstatic int
213c2630c9philippcap_inject_not_initialized(pcap_t *pcap, const void * buf _U_, size_t size _U_)
214c2630c9philip{
215c2630c9philip	pcap_set_not_initialized_message(pcap);
216c2630c9philip	/* this means 'not initialized' */
217c2630c9philip	return (PCAP_ERROR_NOT_ACTIVATED);
218c2630c9philip}
219c2630c9philip
220c2630c9philipstatic int
221c2630c9philippcap_setfilter_not_initialized(pcap_t *pcap, struct bpf_program *fp _U_)
222c2630c9philip{
223c2630c9philip	pcap_set_not_initialized_message(pcap);
224c2630c9philip	/* this means 'not initialized' */
225c2630c9philip	return (PCAP_ERROR_NOT_ACTIVATED);
226c2630c9philip}
227c2630c9philip
228c2630c9philipstatic int
229c2630c9philippcap_setdirection_not_initialized(pcap_t *pcap, pcap_direction_t d _U_)
230c2630c9philip{
231c2630c9philip	pcap_set_not_initialized_message(pcap);
232c2630c9philip	/* this means 'not initialized' */
233c2630c9philip	return (PCAP_ERROR_NOT_ACTIVATED);
234c2630c9philip}
235c2630c9philip
236c2630c9philipstatic int
237c2630c9philippcap_set_datalink_not_initialized(pcap_t *pcap, int dlt _U_)
238c2630c9philip{
239c2630c9philip	pcap_set_not_initialized_message(pcap);
240c2630c9philip	/* this means 'not initialized' */
241c2630c9philip	return (PCAP_ERROR_NOT_ACTIVATED);
242c2630c9philip}
243c2630c9philip
244c2630c9philipstatic int
245c2630c9philippcap_getnonblock_not_initialized(pcap_t *pcap)
246c2630c9philip{
247c2630c9philip	pcap_set_not_initialized_message(pcap);
248c2630c9philip	/* this means 'not initialized' */
249c2630c9philip	return (PCAP_ERROR_NOT_ACTIVATED);
250c2630c9philip}
251c2630c9philip
252c2630c9philipstatic int
253c2630c9philippcap_stats_not_initialized(pcap_t *pcap, struct pcap_stat *ps _U_)
254c2630c9philip{
255c2630c9philip	pcap_set_not_initialized_message(pcap);
256d8d18f6rpaulo	/* this means 'not initialized' */
257c5b3ac4gnn	return (PCAP_ERROR_NOT_ACTIVATED);
258d8d18f6rpaulo}
259d8d18f6rpaulo
26094960e5delphij#ifdef _WIN32
261c2630c9philipstruct pcap_stat *
262c2630c9philippcap_stats_ex_not_initialized(pcap_t *pcap, int *pcap_stat_size _U_)
26394960e5delphij{
264c2630c9philip	pcap_set_not_initialized_message(pcap);
26594960e5delphij	return (NULL);
26694960e5delphij}
26794960e5delphij
268c2630c9philipstatic int
269c2630c9philippcap_setbuff_not_initialized(pcap_t *pcap, int dim _U_)
270c2630c9philip{
271c2630c9philip	pcap_set_not_initialized_message(pcap);
272c2630c9philip	/* this means 'not initialized' */
273c2630c9philip	return (PCAP_ERROR_NOT_ACTIVATED);
274c2630c9philip}
275c2630c9philip
276c2630c9philipstatic int
277c2630c9philippcap_setmode_not_initialized(pcap_t *pcap, int mode _U_)
278c2630c9philip{
279c2630c9philip	pcap_set_not_initialized_message(pcap);
280c2630c9philip	/* this means 'not initialized' */
281c2630c9philip	return (PCAP_ERROR_NOT_ACTIVATED);
282c2630c9philip}
283c2630c9philip
284c2630c9philipstatic int
285c2630c9philippcap_setmintocopy_not_initialized(pcap_t *pcap, int size _U_)
286c2630c9philip{
287c2630c9philip	pcap_set_not_initialized_message(pcap);
288c2630c9philip	/* this means 'not initialized' */
289c2630c9philip	return (PCAP_ERROR_NOT_ACTIVATED);
290c2630c9philip}
291c2630c9philip
29294960e5delphijstatic HANDLE
29394960e5delphijpcap_getevent_not_initialized(pcap_t *pcap)
29494960e5delphij{
295c2630c9philip	pcap_set_not_initialized_message(pcap);
29694960e5delphij	return (INVALID_HANDLE_VALUE);
29794960e5delphij}
29894960e5delphij
299c2630c9philipstatic int
300c2630c9philippcap_oid_get_request_not_initialized(pcap_t *pcap, bpf_u_int32 oid _U_,
301c2630c9philip    void *data _U_, size_t *lenp _U_)
302c2630c9philip{
303c2630c9philip	pcap_set_not_initialized_message(pcap);
304c2630c9philip	return (PCAP_ERROR_NOT_ACTIVATED);
305c2630c9philip}
306c2630c9philip
307c2630c9philipstatic int
308c2630c9philippcap_oid_set_request_not_initialized(pcap_t *pcap, bpf_u_int32 oid _U_,
309c2630c9philip    const void *data _U_, size_t *lenp _U_)
310c2630c9philip{
311c2630c9philip	pcap_set_not_initialized_message(pcap);
312c2630c9philip	return (PCAP_ERROR_NOT_ACTIVATED);
313c2630c9philip}
314c2630c9philip
31594960e5delphijstatic u_int
31694960e5delphijpcap_sendqueue_transmit_not_initialized(pcap_t *pcap, pcap_send_queue* queue, int sync)
31794960e5delphij{
318c2630c9philip	pcap_set_not_initialized_message(pcap);
31994960e5delphij	return (0);
32094960e5delphij}
32194960e5delphij
322c2630c9philipstatic int
323c2630c9philippcap_setuserbuffer_not_initialized(pcap_t *pcap, int size _U_)
324c2630c9philip{
325c2630c9philip	pcap_set_not_initialized_message(pcap);
326c2630c9philip	return (PCAP_ERROR_NOT_ACTIVATED);
327c2630c9philip}
328c2630c9philip
329c2630c9philipstatic int
330c2630c9philippcap_live_dump_not_initialized(pcap_t *pcap, char *filename _U_, int maxsize _U_,
331c2630c9philip    int maxpacks _U_)
332c2630c9philip{
333c2630c9philip	pcap_set_not_initialized_message(pcap);
334c2630c9philip	return (PCAP_ERROR_NOT_ACTIVATED);
335c2630c9philip}
336c2630c9philip
337c2630c9philipstatic int
338c2630c9philippcap_live_dump_ended_not_initialized(pcap_t *pcap, int sync _U_)
339c2630c9philip{
340c2630c9philip	pcap_set_not_initialized_message(pcap);
341c2630c9philip	return (PCAP_ERROR_NOT_ACTIVATED);
342c2630c9philip}
343c2630c9philip
34494960e5delphijstatic PAirpcapHandle
34594960e5delphijpcap_get_airpcap_handle_not_initialized(pcap_t *pcap)
346489abeddelphij{
347c2630c9philip	pcap_set_not_initialized_message(pcap);
348489abeddelphij	return (NULL);
349489abeddelphij}
350489abeddelphij#endif
351489abeddelphij
352d8d18f6rpaulo/*
353d8d18f6rpaulo * Returns 1 if rfmon mode can be set on the pcap_t, 0 if it can't,
354d8d18f6rpaulo * a PCAP_ERROR value on an error.
355d8d18f6rpaulo */
356f0fdf33pstint
357d8d18f6rpaulopcap_can_set_rfmon(pcap_t *p)
358d8d18f6rpaulo{
359d8d18f6rpaulo	return (p->can_set_rfmon_op(p));
360d8d18f6rpaulo}
361d8d18f6rpaulo
362d8d18f6rpaulo/*
363d8d18f6rpaulo * For systems where rfmon mode is never supported.
364d8d18f6rpaulo */
365d8d18f6rpaulostatic int
366d8d18f6rpaulopcap_cant_set_rfmon(pcap_t *p _U_)
367d8d18f6rpaulo{
368d8d18f6rpaulo	return (0);
369d8d18f6rpaulo}
370d8d18f6rpaulo
371724e1a0rpaulo/*
372c5b3ac4gnn * Sets *tstamp_typesp to point to an array 1 or more supported time stamp
373c5b3ac4gnn * types; the return value is the number of supported time stamp types.
374c5b3ac4gnn * The list should be freed by a call to pcap_free_tstamp_types() when
375c5b3ac4gnn * you're done with it.
376c5b3ac4gnn *
377c5b3ac4gnn * A return value of 0 means "you don't get a choice of time stamp type",
378c5b3ac4gnn * in which case *tstamp_typesp is set to null.
379c5b3ac4gnn *
380c5b3ac4gnn * PCAP_ERROR is returned on error.
381c5b3ac4gnn */
382c5b3ac4gnnint
383c5b3ac4gnnpcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp)
384c5b3ac4gnn{
385c5b3ac4gnn	if (p->tstamp_type_count == 0) {
386c5b3ac4gnn		/*
387c5b3ac4gnn		 * We don't support multiple time stamp types.
388c2630c9philip		 * That means the only type we support is PCAP_TSTAMP_HOST;
389c2630c9philip		 * set up a list containing only that type.
390c5b3ac4gnn		 */
391c2630c9philip		*tstamp_typesp = (int*)malloc(sizeof(**tstamp_typesp));
392c2630c9philip		if (*tstamp_typesp == NULL) {
393c2630c9philip			pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
394c2630c9philip			    errno, "malloc");
395c2630c9philip			return (PCAP_ERROR);
396c2630c9philip		}
397c2630c9philip		**tstamp_typesp = PCAP_TSTAMP_HOST;
398c2630c9philip		return (1);
399c5b3ac4gnn	} else {
400c5b3ac4gnn		*tstamp_typesp = (int*)calloc(sizeof(**tstamp_typesp),
401c5b3ac4gnn		    p->tstamp_type_count);
402c5b3ac4gnn		if (*tstamp_typesp == NULL) {
40319bb0b8hselasky			pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
40419bb0b8hselasky			    errno, "malloc");
405c5b3ac4gnn			return (PCAP_ERROR);
406c5b3ac4gnn		}
407c5b3ac4gnn		(void)memcpy(*tstamp_typesp, p->tstamp_type_list,
408c5b3ac4gnn		    sizeof(**tstamp_typesp) * p->tstamp_type_count);
409c2630c9philip		return (p->tstamp_type_count);
410c5b3ac4gnn	}
411c5b3ac4gnn}
412c5b3ac4gnn
413c5b3ac4gnn/*
414c5b3ac4gnn * In Windows, you might have a library built with one version of the
415c5b3ac4gnn * C runtime library and an application built with another version of
416c5b3ac4gnn * the C runtime library, which means that the library might use one
417c5b3ac4gnn * version of malloc() and free() and the application might use another
418c5b3ac4gnn * version of malloc() and free().  If so, that means something
419c5b3ac4gnn * allocated by the library cannot be freed by the application, so we
420c5b3ac4gnn * need to have a pcap_free_tstamp_types() routine to free up the list
421c5b3ac4gnn * allocated by pcap_list_tstamp_types(), even though it's just a wrapper
422c5b3ac4gnn * around free().
423c5b3ac4gnn */
424c5b3ac4gnnvoid
425c5b3ac4gnnpcap_free_tstamp_types(int *tstamp_type_list)
426c5b3ac4gnn{
427c5b3ac4gnn	free(tstamp_type_list);
428c5b3ac4gnn}
429c5b3ac4gnn
430c5b3ac4gnn/*
431724e1a0rpaulo * Default one-shot callback; overridden for capture types where the
432724e1a0rpaulo * packet data cannot be guaranteed to be available after the callback
433724e1a0rpaulo * returns, so that a copy must be made.
434724e1a0rpaulo */
435489abeddelphijvoid
436724e1a0rpaulopcap_oneshot(u_char *user, const struct pcap_pkthdr *h, const u_char *pkt)
437724e1a0rpaulo{
438724e1a0rpaulo	struct oneshot_userdata *sp = (struct oneshot_userdata *)user;
439724e1a0rpaulo
440724e1a0rpaulo	*sp->hdr = *h;
441724e1a0rpaulo	*sp->pkt = pkt;
442724e1a0rpaulo}
443724e1a0rpaulo
444724e1a0rpauloconst u_char *
445724e1a0rpaulopcap_next(pcap_t *p, struct pcap_pkthdr *h)
446724e1a0rpaulo{
447724e1a0rpaulo	struct oneshot_userdata s;
448724e1a0rpaulo	const u_char *pkt;
449724e1a0rpaulo
450724e1a0rpaulo	s.hdr = h;
451724e1a0rpaulo	s.pkt = &pkt;
452724e1a0rpaulo	s.pd = p;
453724e1a0rpaulo	if (pcap_dispatch(p, 1, p->oneshot_callback, (u_char *)&s) <= 0)
454724e1a0rpaulo		return (0);
455724e1a0rpaulo	return (pkt);
456724e1a0rpaulo}
457724e1a0rpaulo
458489abeddelphijint
459724e1a0rpaulopcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
460724e1a0rpaulo    const u_char **pkt_data)
461724e1a0rpaulo{
462724e1a0rpaulo	struct oneshot_userdata s;
463724e1a0rpaulo
464724e1a0rpaulo	s.hdr = &p->pcap_header;
465724e1a0rpaulo	s.pkt = pkt_data;
466724e1a0rpaulo	s.pd = p;
467724e1a0rpaulo
468724e1a0rpaulo	/* Saves a pointer to the packet headers */
469724e1a0rpaulo	*pkt_header= &p->pcap_header;
470724e1a0rpaulo
471489abeddelphij	if (p->rfile != NULL) {
472724e1a0rpaulo		int status;
473724e1a0rpaulo
474724e1a0rpaulo		/* We are on an offline capture */
475c5b3ac4gnn		status = pcap_offline_read(p, 1, p->oneshot_callback,
476c5b3ac4gnn		    (u_char *)&s);
477724e1a0rpaulo
478724e1a0rpaulo		/*
479724e1a0rpaulo		 * Return codes for pcap_offline_read() are:
480724e1a0rpaulo		 *   -  0: EOF
481724e1a0rpaulo		 *   - -1: error
482724e1a0rpaulo		 *   - >1: OK
483724e1a0rpaulo		 * The first one ('0') conflicts with the return code of
484724e1a0rpaulo		 * 0 from pcap_read() meaning "no packets arrived before
485724e1a0rpaulo		 * the timeout expired", so we map it to -2 so you can
486724e1a0rpaulo		 * distinguish between an EOF from a savefile and a
487724e1a0rpaulo		 * "no packets arrived before the timeout expired, try
488724e1a0rpaulo		 * again" from a live capture.
489724e1a0rpaulo		 */
490724e1a0rpaulo		if (status == 0)
491724e1a0rpaulo			return (-2);
492724e1a0rpaulo		else
493724e1a0rpaulo			return (status);
494724e1a0rpaulo	}
495724e1a0rpaulo
496724e1a0rpaulo	/*
497724e1a0rpaulo	 * Return codes for pcap_read() are:
498724e1a0rpaulo	 *   -  0: timeout
499724e1a0rpaulo	 *   - -1: error
500724e1a0rpaulo	 *   - -2: loop was broken out of with pcap_breakloop()
501724e1a0rpaulo	 *   - >1: OK
502724e1a0rpaulo	 * The first one ('0') conflicts with the return code of 0 from
503724e1a0rpaulo	 * pcap_offline_read() meaning "end of file".
504724e1a0rpaulo	*/
505c5b3ac4gnn	return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s));
506724e1a0rpaulo}
507724e1a0rpaulo
50819bb0b8hselasky/*
50919bb0b8hselasky * Implementation of a pcap_if_list_t.
51019bb0b8hselasky */
51119bb0b8hselaskystruct pcap_if_list {
51219bb0b8hselasky	pcap_if_t *beginning;
51319bb0b8hselasky};
51419bb0b8hselasky
51594960e5delphijstatic struct capture_source_type {
51619bb0b8hselasky	int (*findalldevs_op)(pcap_if_list_t *, char *);
5176181b42delphij	pcap_t *(*create_op)(const char *, char *, int *);
5186181b42delphij} capture_source_types[] = {
5196181b42delphij#ifdef HAVE_DAG_API
5206181b42delphij	{ dag_findalldevs, dag_create },
5216181b42delphij#endif
5226181b42delphij#ifdef HAVE_SEPTEL_API
5236181b42delphij	{ septel_findalldevs, septel_create },
5246181b42delphij#endif
5256181b42delphij#ifdef HAVE_SNF_API
5266181b42delphij	{ snf_findalldevs, snf_create },
5276181b42delphij#endif
52894960e5delphij#ifdef HAVE_TC_API
52994960e5delphij	{ TcFindAllDevs, TcCreate },
53094960e5delphij#endif
5316181b42delphij#ifdef PCAP_SUPPORT_BT
5326181b42delphij	{ bt_findalldevs, bt_create },
5336181b42delphij#endif
534489abeddelphij#ifdef PCAP_SUPPORT_BT_MONITOR
535489abeddelphij	{ bt_monitor_findalldevs, bt_monitor_create },
536489abeddelphij#endif
5376181b42delphij#ifdef PCAP_SUPPORT_USB
5386181b42delphij	{ usb_findalldevs, usb_create },
5396181b42delphij#endif
5406181b42delphij#ifdef PCAP_SUPPORT_NETFILTER
5416181b42delphij	{ netfilter_findalldevs, netfilter_create },
5426181b42delphij#endif
54319bb0b8hselasky#ifdef PCAP_SUPPORT_NETMAP
54419bb0b8hselasky	{ pcap_netmap_findalldevs, pcap_netmap_create },
54519bb0b8hselasky#endif
546489abeddelphij#ifdef PCAP_SUPPORT_DBUS
547489abeddelphij	{ dbus_findalldevs, dbus_create },
548489abeddelphij#endif
54919bb0b8hselasky#ifdef PCAP_SUPPORT_RDMASNIFF
55019bb0b8hselasky	{ rdmasniff_findalldevs, rdmasniff_create },
55119bb0b8hselasky#endif
5526181b42delphij	{ NULL, NULL }
5536181b42delphij};
5546181b42delphij
5556181b42delphij/*
5566181b42delphij * Get a list of all capture sources that are up and that we can open.
5576181b42delphij * Returns -1 on error, 0 otherwise.
5586181b42delphij * The list, as returned through "alldevsp", may be null if no interfaces
5596181b42delphij * were up and could be opened.
5606181b42delphij */
5616181b42delphijint
5626181b42delphijpcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
5636181b42delphij{
5646181b42delphij	size_t i;
56519bb0b8hselasky	pcap_if_list_t devlist;
5666181b42delphij
5676181b42delphij	/*
56894960e5delphij	 * Find all the local network interfaces on which we
56994960e5delphij	 * can capture.
5706181b42delphij	 */
57119bb0b8hselasky	devlist.beginning = NULL;
57219bb0b8hselasky	if (pcap_platform_finddevs(&devlist, errbuf) == -1) {
57319bb0b8hselasky		/*
57419bb0b8hselasky		 * Failed - free all of the entries we were given
57519bb0b8hselasky		 * before we failed.
57619bb0b8hselasky		 */
57719bb0b8hselasky		if (devlist.beginning != NULL)
57819bb0b8hselasky			pcap_freealldevs(devlist.beginning);
57919bb0b8hselasky		*alldevsp = NULL;
5806181b42delphij		return (-1);
58119bb0b8hselasky	}
5826181b42delphij
5836181b42delphij	/*
5846181b42delphij	 * Ask each of the non-local-network-interface capture
5856181b42delphij	 * source types what interfaces they have.
5866181b42delphij	 */
5876181b42delphij	for (i = 0; capture_source_types[i].findalldevs_op != NULL; i++) {
58819bb0b8hselasky		if (capture_source_types[i].findalldevs_op(&devlist, errbuf) == -1) {
5896181b42delphij			/*
5906181b42delphij			 * We had an error; free the list we've been
5916181b42delphij			 * constructing.
5926181b42delphij			 */
59319bb0b8hselasky			if (devlist.beginning != NULL)
59419bb0b8hselasky				pcap_freealldevs(devlist.beginning);
59519bb0b8hselasky			*alldevsp = NULL;
5966181b42delphij			return (-1);
5976181b42delphij		}
5986181b42delphij	}
599489abeddelphij
60019bb0b8hselasky	/*
60119bb0b8hselasky	 * Return the first entry of the list of all devices.
60219bb0b8hselasky	 */
60319bb0b8hselasky	*alldevsp = devlist.beginning;
6046181b42delphij	return (0);
6056181b42delphij}
6066181b42delphij
60719bb0b8hselaskystatic struct sockaddr *
60819bb0b8hselaskydup_sockaddr(struct sockaddr *sa, size_t sa_length)
6096181b42delphij{
61019bb0b8hselasky	struct sockaddr *newsa;
6116181b42delphij
61219bb0b8hselasky	if ((newsa = malloc(sa_length)) == NULL)
61319bb0b8hselasky		return (NULL);
61419bb0b8hselasky	return (memcpy(newsa, sa, sa_length));
61519bb0b8hselasky}
61619bb0b8hselasky
61719bb0b8hselasky/*
61819bb0b8hselasky * Construct a "figure of merit" for an interface, for use when sorting
61919bb0b8hselasky * the list of interfaces, in which interfaces that are up are superior
62019bb0b8hselasky * to interfaces that aren't up, interfaces that are up and running are
62119bb0b8hselasky * superior to interfaces that are up but not running, and non-loopback
62219bb0b8hselasky * interfaces that are up and running are superior to loopback interfaces,
62319bb0b8hselasky * and interfaces with the same flags have a figure of merit that's higher
62419bb0b8hselasky * the lower the instance number.
62519bb0b8hselasky *
62619bb0b8hselasky * The goal is to try to put the interfaces most likely to be useful for
62719bb0b8hselasky * capture at the beginning of the list.
62819bb0b8hselasky *
62919bb0b8hselasky * The figure of merit, which is lower the "better" the interface is,
63019bb0b8hselasky * has the uppermost bit set if the interface isn't running, the bit
63119bb0b8hselasky * below that set if the interface isn't up, the bit below that set
63219bb0b8hselasky * if the interface is a loopback interface, and the interface index
63319bb0b8hselasky * in the 29 bits below that.  (Yes, we assume u_int is 32 bits.)
63419bb0b8hselasky */
63519bb0b8hselaskystatic u_int
63619bb0b8hselaskyget_figure_of_merit(pcap_if_t *dev)
63719bb0b8hselasky{
63819bb0b8hselasky	const char *cp;
63919bb0b8hselasky	u_int n;
64019bb0b8hselasky
64119bb0b8hselasky	if (strcmp(dev->name, "any") == 0) {
64294960e5delphij		/*
64319bb0b8hselasky		 * Give the "any" device an artificially high instance
64419bb0b8hselasky		 * number, so it shows up after all other non-loopback
64519bb0b8hselasky		 * interfaces.
64694960e5delphij		 */
64719bb0b8hselasky		n = 0x1FFFFFFF;	/* 29 all-1 bits */
64819bb0b8hselasky	} else {
64919bb0b8hselasky		/*
65019bb0b8hselasky		 * A number at the end of the device name string is
65119bb0b8hselasky		 * assumed to be an instance number.  Add 1 to the
65219bb0b8hselasky		 * instance number, and use 0 for "no instance
65319bb0b8hselasky		 * number", so we don't put "no instance number"
65419bb0b8hselasky		 * devices and "instance 0" devices together.
65519bb0b8hselasky		 */
65619bb0b8hselasky		cp = dev->name + strlen(dev->name) - 1;
65719bb0b8hselasky		while (cp-1 >= dev->name && *(cp-1) >= '0' && *(cp-1) <= '9')
65819bb0b8hselasky			cp--;
65919bb0b8hselasky		if (*cp >= '0' && *cp <= '9')
66019bb0b8hselasky			n = atoi(cp) + 1;
66119bb0b8hselasky		else
66219bb0b8hselasky			n = 0;
66319bb0b8hselasky	}
66419bb0b8hselasky	if (!(dev->flags & PCAP_IF_RUNNING))
66519bb0b8hselasky		n |= 0x80000000;
66619bb0b8hselasky	if (!(dev->flags & PCAP_IF_UP))
66719bb0b8hselasky		n |= 0x40000000;
66894960e5delphij
66919bb0b8hselasky	/*
67019bb0b8hselasky	 * Give non-wireless interfaces that aren't disconnected a better
67119bb0b8hselasky	 * figure of merit than interfaces that are disconnected, as
67219bb0b8hselasky	 * "disconnected" should indicate that the interface isn't
67319bb0b8hselasky	 * plugged into a network and thus won't give you any traffic.
67419bb0b8hselasky	 *
67519bb0b8hselasky	 * For wireless interfaces, it means "associated with a network",
67619bb0b8hselasky	 * which we presume not to necessarily prevent capture, as you
67719bb0b8hselasky	 * might run the adapter in some flavor of monitor mode.
67819bb0b8hselasky	 */
67919bb0b8hselasky	if (!(dev->flags & PCAP_IF_WIRELESS) &&
68019bb0b8hselasky	    (dev->flags & PCAP_IF_CONNECTION_STATUS) == PCAP_IF_CONNECTION_STATUS_DISCONNECTED)
68119bb0b8hselasky		n |= 0x20000000;
68294960e5delphij
68319bb0b8hselasky	/*
68419bb0b8hselasky	 * Sort loopback devices after non-loopback devices, *except* for
68519bb0b8hselasky	 * disconnected devices.
68619bb0b8hselasky	 */
68719bb0b8hselasky	if (dev->flags & PCAP_IF_LOOPBACK)
68819bb0b8hselasky		n |= 0x10000000;
68919bb0b8hselasky
69019bb0b8hselasky	return (n);
69119bb0b8hselasky}
69219bb0b8hselasky
69319bb0b8hselasky#ifndef _WIN32
69419bb0b8hselasky/*
69519bb0b8hselasky * Try to get a description for a given device.
69619bb0b8hselasky * Returns a mallocated description if it could and NULL if it couldn't.
69719bb0b8hselasky *
69819bb0b8hselasky * XXX - on FreeBSDs that support it, should it get the sysctl named
69919bb0b8hselasky * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
70019bb0b8hselasky * of the adapter?  Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
70119bb0b8hselasky * with my Cisco 350 card, so the name isn't entirely descriptive.  The
70219bb0b8hselasky * "dev.an.0.%pnpinfo" has a better description, although one might argue
70319bb0b8hselasky * that the problem is really a driver bug - if it can find out that it's
70419bb0b8hselasky * a Cisco 340 or 350, rather than an old Aironet card, it should use
70519bb0b8hselasky * that in the description.
70619bb0b8hselasky *
70719bb0b8hselasky * Do NetBSD, DragonflyBSD, or OpenBSD support this as well?  FreeBSD
70819bb0b8hselasky * and OpenBSD let you get a description, but it's not generated by the OS,
70919bb0b8hselasky * it's set with another ioctl that ifconfig supports; we use that to get
71019bb0b8hselasky * a description in FreeBSD and OpenBSD, but if there is no such
71119bb0b8hselasky * description available, it still might be nice to get some description
71219bb0b8hselasky * string based on the device type or something such as that.
71319bb0b8hselasky *
71419bb0b8hselasky * In macOS, the System Configuration framework can apparently return
71519bb0b8hselasky * names in 10.4 and later.
71619bb0b8hselasky *
71719bb0b8hselasky * It also appears that freedesktop.org's HAL offers an "info.product"
71819bb0b8hselasky * string, but the HAL specification says it "should not be used in any
71919bb0b8hselasky * UI" and "subsystem/capability specific properties" should be used
72019bb0b8hselasky * instead and, in any case, I think HAL is being deprecated in
72119bb0b8hselasky * favor of other stuff such as DeviceKit.  DeviceKit doesn't appear
72219bb0b8hselasky * to have any obvious product information for devices, but maybe
72319bb0b8hselasky * I haven't looked hard enough.
72419bb0b8hselasky *
72519bb0b8hselasky * Using the System Configuration framework, or HAL, or DeviceKit, or
72619bb0b8hselasky * whatever, would require that libpcap applications be linked with
72719bb0b8hselasky * the frameworks/libraries in question.  That shouldn't be a problem
72819bb0b8hselasky * for programs linking with the shared version of libpcap (unless
72919bb0b8hselasky * you're running on AIX - which I think is the only UN*X that doesn't
73019bb0b8hselasky * support linking a shared library with other libraries on which it
73119bb0b8hselasky * depends, and having an executable linked only with the first shared
73219bb0b8hselasky * library automatically pick up the other libraries when started -
73319bb0b8hselasky * and using HAL or whatever).  Programs linked with the static
73419bb0b8hselasky * version of libpcap would have to use pcap-config with the --static
73519bb0b8hselasky * flag in order to get the right linker flags in order to pick up
73619bb0b8hselasky * the additional libraries/frameworks; those programs need that anyway
73719bb0b8hselasky * for libpcap 1.1 and beyond on Linux, as, by default, it requires
73819bb0b8hselasky * -lnl.
73919bb0b8hselasky *
74019bb0b8hselasky * Do any other UN*Xes, or desktop environments support getting a
74119bb0b8hselasky * description?
74219bb0b8hselasky */
74319bb0b8hselaskystatic char *
74419bb0b8hselasky#ifdef SIOCGIFDESCR
74519bb0b8hselaskyget_if_description(const char *name)
74619bb0b8hselasky{
74719bb0b8hselasky	char *description = NULL;
74819bb0b8hselasky	int s;
74919bb0b8hselasky	struct ifreq ifrdesc;
75019bb0b8hselasky#ifndef IFDESCRSIZE
75119bb0b8hselasky	size_t descrlen = 64;
75219bb0b8hselasky#else
75319bb0b8hselasky	size_t descrlen = IFDESCRSIZE;
75419bb0b8hselasky#endif /* IFDESCRSIZE */
7556181b42delphij
7566181b42delphij	/*
75719bb0b8hselasky	 * Get the description for the interface.
7586181b42delphij	 */
75919bb0b8hselasky	memset(&ifrdesc, 0, sizeof ifrdesc);
760c2630c9philip	pcap_strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
76119bb0b8hselasky	s = socket(AF_INET, SOCK_DGRAM, 0);
76219bb0b8hselasky	if (s >= 0) {
76319bb0b8hselasky#ifdef __FreeBSD__
76419bb0b8hselasky		/*
76519bb0b8hselasky		 * On FreeBSD, if the buffer isn't big enough for the
76619bb0b8hselasky		 * description, the ioctl succeeds, but the description
76719bb0b8hselasky		 * isn't copied, ifr_buffer.length is set to the description
76819bb0b8hselasky		 * length, and ifr_buffer.buffer is set to NULL.
76919bb0b8hselasky		 */
77019bb0b8hselasky		for (;;) {
77119bb0b8hselasky			free(description);
77219bb0b8hselasky			if ((description = malloc(descrlen)) != NULL) {
77319bb0b8hselasky				ifrdesc.ifr_buffer.buffer = description;
77419bb0b8hselasky				ifrdesc.ifr_buffer.length = descrlen;
77519bb0b8hselasky				if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
77619bb0b8hselasky					if (ifrdesc.ifr_buffer.buffer ==
77719bb0b8hselasky					    description)
77819bb0b8hselasky						break;
77919bb0b8hselasky					else
78019bb0b8hselasky						descrlen = ifrdesc.ifr_buffer.length;
78119bb0b8hselasky				} else {
78219bb0b8hselasky					/*
78319bb0b8hselasky					 * Failed to get interface description.
78419bb0b8hselasky					 */
78519bb0b8hselasky					free(description);
78619bb0b8hselasky					description = NULL;
78719bb0b8hselasky					break;
78819bb0b8hselasky				}
78919bb0b8hselasky			} else
79019bb0b8hselasky				break;
79119bb0b8hselasky		}
79219bb0b8hselasky#else /* __FreeBSD__ */
79319bb0b8hselasky		/*
79419bb0b8hselasky		 * The only other OS that currently supports
79519bb0b8hselasky		 * SIOCGIFDESCR is OpenBSD, and it has no way
79619bb0b8hselasky		 * to get the description length - it's clamped
79719bb0b8hselasky		 * to a maximum of IFDESCRSIZE.
79819bb0b8hselasky		 */
79919bb0b8hselasky		if ((description = malloc(descrlen)) != NULL) {
80019bb0b8hselasky			ifrdesc.ifr_data = (caddr_t)description;
80119bb0b8hselasky			if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
80294960e5delphij				/*
80319bb0b8hselasky				 * Failed to get interface description.
80494960e5delphij				 */
80519bb0b8hselasky				free(description);
80619bb0b8hselasky				description = NULL;
80794960e5delphij			}
80819bb0b8hselasky		}
80919bb0b8hselasky#endif /* __FreeBSD__ */
81019bb0b8hselasky		close(s);
811c2630c9philip		if (description != NULL && description[0] == '\0') {
81219bb0b8hselasky			/*
81319bb0b8hselasky			 * Description is empty, so discard it.
81419bb0b8hselasky			 */
81519bb0b8hselasky			free(description);
81619bb0b8hselasky			description = NULL;
8176181b42delphij		}
8186181b42delphij	}
8196181b42delphij
82019bb0b8hselasky#ifdef __FreeBSD__
8216181b42delphij	/*
82219bb0b8hselasky	 * For FreeBSD, if we didn't get a description, and this is
82319bb0b8hselasky	 * a device with a name of the form usbusN, label it as a USB
82419bb0b8hselasky	 * bus.
8256181b42delphij	 */
82619bb0b8hselasky	if (description == NULL) {
82719bb0b8hselasky		if (strncmp(name, "usbus", 5) == 0) {
82819bb0b8hselasky			/*
82919bb0b8hselasky			 * OK, it begins with "usbus".
83019bb0b8hselasky			 */
83119bb0b8hselasky			long busnum;
83219bb0b8hselasky			char *p;
83319bb0b8hselasky
83419bb0b8hselasky			errno = 0;
83519bb0b8hselasky			busnum = strtol(name + 5, &p, 10);
83619bb0b8hselasky			if (errno == 0 && p != name + 5 && *p == '\0' &&
83719bb0b8hselasky			    busnum >= 0 && busnum <= INT_MAX) {
83819bb0b8hselasky				/*
83919bb0b8hselasky				 * OK, it's a valid number that's not
84019bb0b8hselasky				 * bigger than INT_MAX.  Construct
84119bb0b8hselasky				 * a description from it.
842c2630c9philip				 * (If that fails, we don't worry about
843c2630c9philip				 * it, we just return NULL.)
84419bb0b8hselasky				 */
845c2630c9philip				if (pcap_asprintf(&description,
846c2630c9philip				    "USB bus number %ld", busnum) == -1) {
847c2630c9philip					/* Failed. */
848c2630c9philip					description = NULL;
84919bb0b8hselasky				}
85019bb0b8hselasky			}
85119bb0b8hselasky		}
85294960e5delphij	}
85319bb0b8hselasky#endif
85419bb0b8hselasky	return (description);
85519bb0b8hselasky#else /* SIOCGIFDESCR */
85619bb0b8hselaskyget_if_description(const char *name _U_)
85719bb0b8hselasky{
85819bb0b8hselasky	return (NULL);
85919bb0b8hselasky#endif /* SIOCGIFDESCR */
8606181b42delphij}
8616181b42delphij
86219bb0b8hselasky/*
86319bb0b8hselasky * Look for a given device in the specified list of devices.
86419bb0b8hselasky *
86519bb0b8hselasky * If we find it, return a pointer to its entry.
86619bb0b8hselasky *
86719bb0b8hselasky * If we don't find it, attempt to add an entry for it, with the specified
86819bb0b8hselasky * IFF_ flags and description, and, if that succeeds, return a pointer to
86919bb0b8hselasky * the new entry, otherwise return NULL and set errbuf to an error message.
87019bb0b8hselasky */
87119bb0b8hselaskypcap_if_t *
87219bb0b8hselaskyfind_or_add_if(pcap_if_list_t *devlistp, const char *name,
87319bb0b8hselasky    bpf_u_int32 if_flags, get_if_flags_func get_flags_func, char *errbuf)
874724e1a0rpaulo{
87519bb0b8hselasky	bpf_u_int32 pcap_flags;
87619bb0b8hselasky
877724e1a0rpaulo	/*
87819bb0b8hselasky	 * Convert IFF_ flags to pcap flags.
879724e1a0rpaulo	 */
88019bb0b8hselasky	pcap_flags = 0;
88119bb0b8hselasky#ifdef IFF_LOOPBACK
88219bb0b8hselasky	if (if_flags & IFF_LOOPBACK)
88319bb0b8hselasky		pcap_flags |= PCAP_IF_LOOPBACK;
88419bb0b8hselasky#else
885724e1a0rpaulo	/*
88619bb0b8hselasky	 * We don't have IFF_LOOPBACK, so look at the device name to
88719bb0b8hselasky	 * see if it looks like a loopback device.
888724e1a0rpaulo	 */
88919bb0b8hselasky	if (name[0] == 'l' && name[1] == 'o' &&
89019bb0b8hselasky	    (isdigit((unsigned char)(name[2])) || name[2] == '\0')
89119bb0b8hselasky		pcap_flags |= PCAP_IF_LOOPBACK;
89219bb0b8hselasky#endif
89319bb0b8hselasky#ifdef IFF_UP
89419bb0b8hselasky	if (if_flags & IFF_UP)
89519bb0b8hselasky		pcap_flags |= PCAP_IF_UP;
89619bb0b8hselasky#endif
89719bb0b8hselasky#ifdef IFF_RUNNING
89819bb0b8hselasky	if (if_flags & IFF_RUNNING)
89919bb0b8hselasky		pcap_flags |= PCAP_IF_RUNNING;
90019bb0b8hselasky#endif
901724e1a0rpaulo
902724e1a0rpaulo	/*
90319bb0b8hselasky	 * Attempt to find an entry for this device; if we don't find one,
90419bb0b8hselasky	 * attempt to add one.
905724e1a0rpaulo	 */
90619bb0b8hselasky	return (find_or_add_dev(devlistp, name, pcap_flags,
90719bb0b8hselasky	    get_flags_func, get_if_description(name), errbuf));
908724e1a0rpaulo}
909724e1a0rpaulo
91019bb0b8hselasky/*
91119bb0b8hselasky * Look for a given device in the specified list of devices.
91219bb0b8hselasky *
91319bb0b8hselasky * If we find it, then, if the specified address isn't null, add it to
91419bb0b8hselasky * the list of addresses for the device and return 0.
91519bb0b8hselasky *
91619bb0b8hselasky * If we don't find it, attempt to add an entry for it, with the specified
91719bb0b8hselasky * IFF_ flags and description, and, if that succeeds, add the specified
91819bb0b8hselasky * address to its list of addresses if that address is non-null, and
91919bb0b8hselasky * return 0, otherwise return -1 and set errbuf to an error message.
92019bb0b8hselasky *
92119bb0b8hselasky * (We can get called with a null address because we might get a list
92219bb0b8hselasky * of interface name/address combinations from the underlying OS, with
92319bb0b8hselasky * the address being absent in some cases, rather than a list of
92419bb0b8hselasky * interfaces with each interface having a list of addresses, so this
92519bb0b8hselasky * call may be the only call made to add to the list, and we want to
92619bb0b8hselasky * add interfaces even if they have no addresses.)
92719bb0b8hselasky */
92819bb0b8hselaskyint
92919bb0b8hselaskyadd_addr_to_if(pcap_if_list_t *devlistp, const char *name,
93019bb0b8hselasky    bpf_u_int32 if_flags, get_if_flags_func get_flags_func,
93119bb0b8hselasky    struct sockaddr *addr, size_t addr_size,
93219bb0b8hselasky    struct sockaddr *netmask, size_t netmask_size,
93319bb0b8hselasky    struct sockaddr *broadaddr, size_t broadaddr_size,
93419bb0b8hselasky    struct sockaddr *dstaddr, size_t dstaddr_size,
93519bb0b8hselasky    char *errbuf)
936d8d18f6rpaulo{
93719bb0b8hselasky	pcap_if_t *curdev;
938d8d18f6rpaulo
939489abeddelphij	/*
94019bb0b8hselasky	 * Check whether the device exists and, if not, add it.
941489abeddelphij	 */
94219bb0b8hselasky	curdev = find_or_add_if(devlistp, name, if_flags, get_flags_func,
94319bb0b8hselasky	    errbuf);
94419bb0b8hselasky	if (curdev == NULL) {
94519bb0b8hselasky		/*
94619bb0b8hselasky		 * Error - give up.
94719bb0b8hselasky		 */
94819bb0b8hselasky		return (-1);
94919bb0b8hselasky	}
95019bb0b8hselasky
95119bb0b8hselasky	if (addr == NULL) {
95219bb0b8hselasky		/*
95319bb0b8hselasky		 * There's no address to add; this entry just meant
95419bb0b8hselasky		 * "here's a new interface".
95519bb0b8hselasky		 */
95619bb0b8hselasky		return (0);
957d8d18f6rpaulo	}
958489abeddelphij
959489abeddelphij	/*
96019bb0b8hselasky	 * "curdev" is an entry for this interface, and we have an
96119bb0b8hselasky	 * address for it; add an entry for that address to the
96219bb0b8hselasky	 * interface's list of addresses.
963489abeddelphij	 */
96419bb0b8hselasky	return (add_addr_to_dev(curdev, addr, addr_size, netmask,
96519bb0b8hselasky	    netmask_size, broadaddr, broadaddr_size, dstaddr,
96619bb0b8hselasky	    dstaddr_size, errbuf));
96719bb0b8hselasky}
96819bb0b8hselasky#endif /* _WIN32 */
96919bb0b8hselasky
97019bb0b8hselasky/*
97119bb0b8hselasky * Add an entry to the list of addresses for an interface.
97219bb0b8hselasky * "curdev" is the entry for that interface.
97319bb0b8hselasky */
97419bb0b8hselaskyint
97519bb0b8hselaskyadd_addr_to_dev(pcap_if_t *curdev,
97619bb0b8hselasky    struct sockaddr *addr, size_t addr_size,
97719bb0b8hselasky    struct sockaddr *netmask, size_t netmask_size,
97819bb0b8hselasky    struct sockaddr *broadaddr, size_t broadaddr_size,
97919bb0b8hselasky    struct sockaddr *dstaddr, size_t dstaddr_size,
98019bb0b8hselasky    char *errbuf)
98119bb0b8hselasky{
98219bb0b8hselasky	pcap_addr_t *curaddr, *prevaddr, *nextaddr;
98319bb0b8hselasky
98419bb0b8hselasky	/*
98519bb0b8hselasky	 * Allocate the new entry and fill it in.
98619bb0b8hselasky	 */
98719bb0b8hselasky	curaddr = (pcap_addr_t *)malloc(sizeof(pcap_addr_t));
98819bb0b8hselasky	if (curaddr == NULL) {
98919bb0b8hselasky		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
99019bb0b8hselasky		    errno, "malloc");
99119bb0b8hselasky		return (-1);
99219bb0b8hselasky	}
99319bb0b8hselasky
99419bb0b8hselasky	curaddr->next = NULL;
99519bb0b8hselasky	if (addr != NULL && addr_size != 0) {
99619bb0b8hselasky		curaddr->addr = (struct sockaddr *)dup_sockaddr(addr, addr_size);
99719bb0b8hselasky		if (curaddr->addr == NULL) {
99819bb0b8hselasky			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
99919bb0b8hselasky			    errno, "malloc");
100019bb0b8hselasky			free(curaddr);
100119bb0b8hselasky			return (-1);
100219bb0b8hselasky		}
100319bb0b8hselasky	} else
100419bb0b8hselasky		curaddr->addr = NULL;
100519bb0b8hselasky
100619bb0b8hselasky	if (netmask != NULL && netmask_size != 0) {
100719bb0b8hselasky		curaddr->netmask = (struct sockaddr *)dup_sockaddr(netmask, netmask_size);
100819bb0b8hselasky		if (curaddr->netmask == NULL) {
100919bb0b8hselasky			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
101019bb0b8hselasky			    errno, "malloc");
101119bb0b8hselasky			if (curaddr->addr != NULL)
101219bb0b8hselasky				free(curaddr->addr);
101319bb0b8hselasky			free(curaddr);
101419bb0b8hselasky			return (-1);
101519bb0b8hselasky		}
101619bb0b8hselasky	} else
101719bb0b8hselasky		curaddr->netmask = NULL;
101819bb0b8hselasky
101919bb0b8hselasky	if (broadaddr != NULL && broadaddr_size != 0) {
102019bb0b8hselasky		curaddr->broadaddr = (struct sockaddr *)dup_sockaddr(broadaddr, broadaddr_size);
102119bb0b8hselasky		if (curaddr->broadaddr == NULL) {
102219bb0b8hselasky			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
102319bb0b8hselasky			    errno, "malloc");
102419bb0b8hselasky			if (curaddr->netmask != NULL)
102519bb0b8hselasky				free(curaddr->netmask);
102619bb0b8hselasky			if (curaddr->addr != NULL)
102719bb0b8hselasky				free(curaddr->addr);
102819bb0b8hselasky			free(curaddr);
102919bb0b8hselasky			return (-1);
103019bb0b8hselasky		}
103119bb0b8hselasky	} else
103219bb0b8hselasky		curaddr->broadaddr = NULL;
103319bb0b8hselasky
103419bb0b8hselasky	if (dstaddr != NULL && dstaddr_size != 0) {
103519bb0b8hselasky		curaddr->dstaddr = (struct sockaddr *)dup_sockaddr(dstaddr, dstaddr_size);
103619bb0b8hselasky		if (curaddr->dstaddr == NULL) {
103719bb0b8hselasky			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
103819bb0b8hselasky			    errno, "malloc");
103919bb0b8hselasky			if (curaddr->broadaddr != NULL)
104019bb0b8hselasky				free(curaddr->broadaddr);
104119bb0b8hselasky			if (curaddr->netmask != NULL)
104219bb0b8hselasky				free(curaddr->netmask);
104319bb0b8hselasky			if (curaddr->addr != NULL)
104419bb0b8hselasky				free(curaddr->addr);
104519bb0b8hselasky			free(curaddr);
104619bb0b8hselasky			return (-1);
104719bb0b8hselasky		}
104819bb0b8hselasky	} else
104919bb0b8hselasky		curaddr->dstaddr = NULL;
105019bb0b8hselasky
105119bb0b8hselasky	/*
105219bb0b8hselasky	 * Find the end of the list of addresses.
105319bb0b8hselasky	 */
105419bb0b8hselasky	for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
105519bb0b8hselasky		nextaddr = prevaddr->next;
105619bb0b8hselasky		if (nextaddr == NULL) {
105719bb0b8hselasky			/*
105819bb0b8hselasky			 * This is the end of the list.
105919bb0b8hselasky			 */
106019bb0b8hselasky			break;
106119bb0b8hselasky		}
106219bb0b8hselasky	}
106319bb0b8hselasky
106419bb0b8hselasky	if (prevaddr == NULL) {
106519bb0b8hselasky		/*
106619bb0b8hselasky		 * The list was empty; this is the first member.
106719bb0b8hselasky		 */
106819bb0b8hselasky		curdev->addresses = curaddr;
106919bb0b8hselasky	} else {
107019bb0b8hselasky		/*
107119bb0b8hselasky		 * "prevaddr" is the last member of the list; append
107219bb0b8hselasky		 * this member to it.
107319bb0b8hselasky		 */
107419bb0b8hselasky		prevaddr->next = curaddr;
107519bb0b8hselasky	}
107619bb0b8hselasky
107719bb0b8hselasky	return (0);
107819bb0b8hselasky}
107919bb0b8hselasky
108019bb0b8hselasky/*
108119bb0b8hselasky * Look for a given device in the specified list of devices.
108219bb0b8hselasky *
108319bb0b8hselasky * If we find it, return 0 and set *curdev_ret to point to it.
108419bb0b8hselasky *
108519bb0b8hselasky * If we don't find it, attempt to add an entry for it, with the specified
108619bb0b8hselasky * flags and description, and, if that succeeds, return 0, otherwise
108719bb0b8hselasky * return -1 and set errbuf to an error message.
108819bb0b8hselasky */
108919bb0b8hselaskypcap_if_t *
109019bb0b8hselaskyfind_or_add_dev(pcap_if_list_t *devlistp, const char *name, bpf_u_int32 flags,
109119bb0b8hselasky    get_if_flags_func get_flags_func, const char *description, char *errbuf)
109219bb0b8hselasky{
109319bb0b8hselasky	pcap_if_t *curdev;
109419bb0b8hselasky
109519bb0b8hselasky	/*
109619bb0b8hselasky	 * Is there already an entry in the list for this device?
109719bb0b8hselasky	 */
109819bb0b8hselasky	curdev = find_dev(devlistp, name);
109919bb0b8hselasky	if (curdev != NULL) {
110019bb0b8hselasky		/*
110119bb0b8hselasky		 * Yes, return it.
110219bb0b8hselasky		 */
110319bb0b8hselasky		return (curdev);
110419bb0b8hselasky	}
110519bb0b8hselasky
110619bb0b8hselasky	/*
110719bb0b8hselasky	 * No, we didn't find it.
110819bb0b8hselasky	 */
110919bb0b8hselasky
111019bb0b8hselasky	/*
111119bb0b8hselasky	 * Try to get additional flags for the device.
111219bb0b8hselasky	 */
111319bb0b8hselasky	if ((*get_flags_func)(name, &flags, errbuf) == -1) {
111419bb0b8hselasky		/*
111519bb0b8hselasky		 * Failed.
111619bb0b8hselasky		 */
111719bb0b8hselasky		return (NULL);
111819bb0b8hselasky	}
111919bb0b8hselasky
112019bb0b8hselasky	/*
112119bb0b8hselasky	 * Now, try to add it to the list of devices.
112219bb0b8hselasky	 */
112319bb0b8hselasky	return (add_dev(devlistp, name, flags, description, errbuf));
112419bb0b8hselasky}
112519bb0b8hselasky
112619bb0b8hselasky/*
112719bb0b8hselasky * Look for a given device in the specified list of devices, and return
112819bb0b8hselasky * the entry for it if we find it or NULL if we don't.
112919bb0b8hselasky */
113019bb0b8hselaskypcap_if_t *
113119bb0b8hselaskyfind_dev(pcap_if_list_t *devlistp, const char *name)
113219bb0b8hselasky{
113319bb0b8hselasky	pcap_if_t *curdev;
113419bb0b8hselasky
113519bb0b8hselasky	/*
113619bb0b8hselasky	 * Is there an entry in the list for this device?
113719bb0b8hselasky	 */
113819bb0b8hselasky	for (curdev = devlistp->beginning; curdev != NULL;
113919bb0b8hselasky	    curdev = curdev->next) {
114019bb0b8hselasky		if (strcmp(name, curdev->name) == 0) {
114119bb0b8hselasky			/*
114219bb0b8hselasky			 * We found it, so, yes, there is.  No need to
114319bb0b8hselasky			 * add it.  Provide the entry we found to our
114419bb0b8hselasky			 * caller.
114519bb0b8hselasky			 */
114619bb0b8hselasky			return (curdev);
114719bb0b8hselasky		}
114819bb0b8hselasky	}
114919bb0b8hselasky
115019bb0b8hselasky	/*
115119bb0b8hselasky	 * No.
115219bb0b8hselasky	 */
115319bb0b8hselasky	return (NULL);
115419bb0b8hselasky}
115519bb0b8hselasky
115619bb0b8hselasky/*
115719bb0b8hselasky * Attempt to add an entry for a device, with the specified flags
115819bb0b8hselasky * and description, and, if that succeeds, return 0 and return a pointer
115919bb0b8hselasky * to the new entry, otherwise return NULL and set errbuf to an error
116019bb0b8hselasky * message.
116119bb0b8hselasky *
116219bb0b8hselasky * If we weren't given a description, try to get one.
116319bb0b8hselasky */
116419bb0b8hselaskypcap_if_t *
116519bb0b8hselaskyadd_dev(pcap_if_list_t *devlistp, const char *name, bpf_u_int32 flags,
116619bb0b8hselasky    const char *description, char *errbuf)
116719bb0b8hselasky{
116819bb0b8hselasky	pcap_if_t *curdev, *prevdev, *nextdev;
116919bb0b8hselasky	u_int this_figure_of_merit, nextdev_figure_of_merit;
117019bb0b8hselasky
117119bb0b8hselasky	curdev = malloc(sizeof(pcap_if_t));
117219bb0b8hselasky	if (curdev == NULL) {
117319bb0b8hselasky		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
117419bb0b8hselasky		    errno, "malloc");
117519bb0b8hselasky		return (NULL);
117619bb0b8hselasky	}
117719bb0b8hselasky
117819bb0b8hselasky	/*
117919bb0b8hselasky	 * Fill in the entry.
118019bb0b8hselasky	 */
118119bb0b8hselasky	curdev->next = NULL;
118219bb0b8hselasky	curdev->name = strdup(name);
118319bb0b8hselasky	if (curdev->name == NULL) {
118419bb0b8hselasky		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
118519bb0b8hselasky		    errno, "malloc");
118619bb0b8hselasky		free(curdev);
118719bb0b8hselasky		return (NULL);
118819bb0b8hselasky	}
118919bb0b8hselasky	if (description == NULL) {
119019bb0b8hselasky		/*
119119bb0b8hselasky		 * We weren't handed a description for the interface.
119219bb0b8hselasky		 */
119319bb0b8hselasky		curdev->description = NULL;
119419bb0b8hselasky	} else {
119519bb0b8hselasky		/*
119619bb0b8hselasky		 * We were handed a description; make a copy.
119719bb0b8hselasky		 */
119819bb0b8hselasky		curdev->description = strdup(description);
119919bb0b8hselasky		if (curdev->description == NULL) {
120019bb0b8hselasky			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
120119bb0b8hselasky			    errno, "malloc");
120219bb0b8hselasky			free(curdev->name);
120319bb0b8hselasky			free(curdev);
120419bb0b8hselasky			return (NULL);
120519bb0b8hselasky		}
120619bb0b8hselasky	}
120719bb0b8hselasky	curdev->addresses = NULL;	/* list starts out as empty */
120819bb0b8hselasky	curdev->flags = flags;
120919bb0b8hselasky
121019bb0b8hselasky	/*
121119bb0b8hselasky	 * Add it to the list, in the appropriate location.
121219bb0b8hselasky	 * First, get the "figure of merit" for this interface.
121319bb0b8hselasky	 */
121419bb0b8hselasky	this_figure_of_merit = get_figure_of_merit(curdev);
121519bb0b8hselasky
121619bb0b8hselasky	/*
121719bb0b8hselasky	 * Now look for the last interface with an figure of merit
121819bb0b8hselasky	 * less than or equal to the new interface's figure of merit.
121919bb0b8hselasky	 *
122019bb0b8hselasky	 * We start with "prevdev" being NULL, meaning we're before
122119bb0b8hselasky	 * the first element in the list.
122219bb0b8hselasky	 */
122319bb0b8hselasky	prevdev = NULL;
122419bb0b8hselasky	for (;;) {
122519bb0b8hselasky		/*
122619bb0b8hselasky		 * Get the interface after this one.
122719bb0b8hselasky		 */
122819bb0b8hselasky		if (prevdev == NULL) {
122919bb0b8hselasky			/*
123019bb0b8hselasky			 * The next element is the first element.
123119bb0b8hselasky			 */
123219bb0b8hselasky			nextdev = devlistp->beginning;
123319bb0b8hselasky		} else
123419bb0b8hselasky			nextdev = prevdev->next;
123519bb0b8hselasky
123619bb0b8hselasky		/*
123719bb0b8hselasky		 * Are we at the end of the list?
123819bb0b8hselasky		 */
123919bb0b8hselasky		if (nextdev == NULL) {
124019bb0b8hselasky			/*
124119bb0b8hselasky			 * Yes - we have to put the new entry after "prevdev".
124219bb0b8hselasky			 */
124319bb0b8hselasky			break;
124419bb0b8hselasky		}
124519bb0b8hselasky
124619bb0b8hselasky		/*
124719bb0b8hselasky		 * Is the new interface's figure of merit less
124819bb0b8hselasky		 * than the next interface's figure of merit,
124919bb0b8hselasky		 * meaning that the new interface is better
125019bb0b8hselasky		 * than the next interface?
125119bb0b8hselasky		 */
125219bb0b8hselasky		nextdev_figure_of_merit = get_figure_of_merit(nextdev);
125319bb0b8hselasky		if (this_figure_of_merit < nextdev_figure_of_merit) {
125419bb0b8hselasky			/*
125519bb0b8hselasky			 * Yes - we should put the new entry
125619bb0b8hselasky			 * before "nextdev", i.e. after "prevdev".
125719bb0b8hselasky			 */
125819bb0b8hselasky			break;
125919bb0b8hselasky		}
126019bb0b8hselasky
126119bb0b8hselasky		prevdev = nextdev;
126219bb0b8hselasky	}
126319bb0b8hselasky
126419bb0b8hselasky	/*
126519bb0b8hselasky	 * Insert before "nextdev".
126619bb0b8hselasky	 */
126719bb0b8hselasky	curdev->next = nextdev;
126819bb0b8hselasky
126919bb0b8hselasky	/*
127019bb0b8hselasky	 * Insert after "prevdev" - unless "prevdev" is null,
127119bb0b8hselasky	 * in which case this is the first interface.
127219bb0b8hselasky	 */
127319bb0b8hselasky	if (prevdev == NULL) {
127419bb0b8hselasky		/*
127519bb0b8hselasky		 * This is the first interface.  Make it
127619bb0b8hselasky		 * the first element in the list of devices.
127719bb0b8hselasky		 */
127819bb0b8hselasky		devlistp->beginning = curdev;
127919bb0b8hselasky	} else
128019bb0b8hselasky		prevdev->next = curdev;
128119bb0b8hselasky	return (curdev);
128219bb0b8hselasky}
128319bb0b8hselasky
128419bb0b8hselasky/*
128519bb0b8hselasky * Free a list of interfaces.
128619bb0b8hselasky */
128719bb0b8hselaskyvoid
128819bb0b8hselaskypcap_freealldevs(pcap_if_t *alldevs)
128919bb0b8hselasky{
129019bb0b8hselasky	pcap_if_t *curdev, *nextdev;
129119bb0b8hselasky	pcap_addr_t *curaddr, *nextaddr;
129219bb0b8hselasky
129319bb0b8hselasky	for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
129419bb0b8hselasky		nextdev = curdev->next;
129519bb0b8hselasky
129619bb0b8hselasky		/*
129719bb0b8hselasky		 * Free all addresses.
129819bb0b8hselasky		 */
129919bb0b8hselasky		for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
130019bb0b8hselasky			nextaddr = curaddr->next;
130119bb0b8hselasky			if (curaddr->addr)
130219bb0b8hselasky				free(curaddr->addr);
130319bb0b8hselasky			if (curaddr->netmask)
130419bb0b8hselasky				free(curaddr->netmask);
130519bb0b8hselasky			if (curaddr->broadaddr)
130619bb0b8hselasky				free(curaddr->broadaddr);
130719bb0b8hselasky			if (curaddr->dstaddr)
130819bb0b8hselasky				free(curaddr->dstaddr);
130919bb0b8hselasky			free(curaddr);
131019bb0b8hselasky		}
131119bb0b8hselasky
131219bb0b8hselasky		/*
131319bb0b8hselasky		 * Free the name string.
131419bb0b8hselasky		 */
131519bb0b8hselasky		free(curdev->name);
131619bb0b8hselasky
131719bb0b8hselasky		/*
131819bb0b8hselasky		 * Free the description string, if any.
131919bb0b8hselasky		 */
132019bb0b8hselasky		if (curdev->description != NULL)
132119bb0b8hselasky			free(curdev->description);
132219bb0b8hselasky
132319bb0b8hselasky		/*
132419bb0b8hselasky		 * Free the interface.
132519bb0b8hselasky		 */
132619bb0b8hselasky		free(curdev);
132719bb0b8hselasky	}
132819bb0b8hselasky}
132919bb0b8hselasky
133019bb0b8hselasky/*
133119bb0b8hselasky * pcap-npf.c has its own pcap_lookupdev(), for compatibility reasons, as
133219bb0b8hselasky * it actually returns the names of all interfaces, with a NUL separator
133319bb0b8hselasky * between them; some callers may depend on that.
133419bb0b8hselasky *
133519bb0b8hselasky * MS-DOS has its own pcap_lookupdev(), but that might be useful only
133619bb0b8hselasky * as an optimization.
133719bb0b8hselasky *
133819bb0b8hselasky * In all other cases, we just use pcap_findalldevs() to get a list of
133919bb0b8hselasky * devices, and pick from that list.
134019bb0b8hselasky */
134119bb0b8hselasky#if !defined(HAVE_PACKET32) && !defined(MSDOS)
134219bb0b8hselasky/*
134319bb0b8hselasky * Return the name of a network interface attached to the system, or NULL
134419bb0b8hselasky * if none can be found.  The interface must be configured up; the
134519bb0b8hselasky * lowest unit number is preferred; loopback is ignored.
134619bb0b8hselasky */
134719bb0b8hselaskychar *
134819bb0b8hselaskypcap_lookupdev(char *errbuf)
134919bb0b8hselasky{
135019bb0b8hselasky	pcap_if_t *alldevs;
135119bb0b8hselasky#ifdef _WIN32
135219bb0b8hselasky  /*
135319bb0b8hselasky   * Windows - use the same size as the old WinPcap 3.1 code.
135419bb0b8hselasky   * XXX - this is probably bigger than it needs to be.
135519bb0b8hselasky   */
135619bb0b8hselasky  #define IF_NAMESIZE 8192
135719bb0b8hselasky#else
135819bb0b8hselasky  /*
135919bb0b8hselasky   * UN*X - use the system's interface name size.
136019bb0b8hselasky   * XXX - that might not be large enough for capture devices
136119bb0b8hselasky   * that aren't regular network interfaces.
136219bb0b8hselasky   */
136319bb0b8hselasky  /* for old BSD systems, including bsdi3 */
136419bb0b8hselasky  #ifndef IF_NAMESIZE
136519bb0b8hselasky  #define IF_NAMESIZE IFNAMSIZ
136619bb0b8hselasky  #endif
136719bb0b8hselasky#endif
136819bb0b8hselasky	static char device[IF_NAMESIZE + 1];
136919bb0b8hselasky	char *ret;
137019bb0b8hselasky
137119bb0b8hselasky	if (pcap_findalldevs(&alldevs, errbuf) == -1)
137219bb0b8hselasky		return (NULL);
137319bb0b8hselasky
137419bb0b8hselasky	if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
137519bb0b8hselasky		/*
137619bb0b8hselasky		 * There are no devices on the list, or the first device
137719bb0b8hselasky		 * on the list is a loopback device, which means there
137819bb0b8hselasky		 * are no non-loopback devices on the list.  This means
137919bb0b8hselasky		 * we can't return any device.
138019bb0b8hselasky		 *
138119bb0b8hselasky		 * XXX - why not return a loopback device?  If we can't
138219bb0b8hselasky		 * capture on it, it won't be on the list, and if it's
138319bb0b8hselasky		 * on the list, there aren't any non-loopback devices,
138419bb0b8hselasky		 * so why not just supply it as the default device?
138519bb0b8hselasky		 */
1386c2630c9philip		(void)pcap_strlcpy(errbuf, "no suitable device found",
138719bb0b8hselasky		    PCAP_ERRBUF_SIZE);
138819bb0b8hselasky		ret = NULL;
138919bb0b8hselasky	} else {
139019bb0b8hselasky		/*
139119bb0b8hselasky		 * Return the name of the first device on the list.
139219bb0b8hselasky		 */
1393c2630c9philip		(void)pcap_strlcpy(device, alldevs->name, sizeof(device));
139419bb0b8hselasky		ret = device;
139519bb0b8hselasky	}
139619bb0b8hselasky
139719bb0b8hselasky	pcap_freealldevs(alldevs);
139819bb0b8hselasky	return (ret);
139919bb0b8hselasky}
140019bb0b8hselasky#endif /* !defined(HAVE_PACKET32) && !defined(MSDOS) */
140119bb0b8hselasky
140219bb0b8hselasky#if !defined(_WIN32) && !defined(MSDOS)
140319bb0b8hselasky/*
140419bb0b8hselasky * We don't just fetch the entire list of devices, search for the
140519bb0b8hselasky * particular device, and use its first IPv4 address, as that's too
140619bb0b8hselasky * much work to get just one device's netmask.
140719bb0b8hselasky *
140819bb0b8hselasky * If we had an API to get attributes for a given device, we could
140919bb0b8hselasky * use that.
141019bb0b8hselasky */
141119bb0b8hselaskyint
141219bb0b8hselaskypcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp,
141319bb0b8hselasky    char *errbuf)
141419bb0b8hselasky{
141519bb0b8hselasky	register int fd;
141619bb0b8hselasky	register struct sockaddr_in *sin4;
141719bb0b8hselasky	struct ifreq ifr;
141819bb0b8hselasky
141919bb0b8hselasky	/*
142019bb0b8hselasky	 * The pseudo-device "any" listens on all interfaces and therefore
142119bb0b8hselasky	 * has the network address and -mask "0.0.0.0" therefore catching
142219bb0b8hselasky	 * all traffic. Using NULL for the interface is the same as "any".
142319bb0b8hselasky	 */
142419bb0b8hselasky	if (!device || strcmp(device, "any") == 0
142519bb0b8hselasky#ifdef HAVE_DAG_API
142619bb0b8hselasky	    || strstr(device, "dag") != NULL
142719bb0b8hselasky#endif
142819bb0b8hselasky#ifdef HAVE_SEPTEL_API
142919bb0b8hselasky	    || strstr(device, "septel") != NULL
143019bb0b8hselasky#endif
143119bb0b8hselasky#ifdef PCAP_SUPPORT_BT
143219bb0b8hselasky	    || strstr(device, "bluetooth") != NULL
143319bb0b8hselasky#endif
143419bb0b8hselasky#ifdef PCAP_SUPPORT_USB
143519bb0b8hselasky	    || strstr(device, "usbmon") != NULL
143619bb0b8hselasky#endif
143719bb0b8hselasky#ifdef HAVE_SNF_API
143819bb0b8hselasky	    || strstr(device, "snf") != NULL
143919bb0b8hselasky#endif
144019bb0b8hselasky#ifdef PCAP_SUPPORT_NETMAP
144119bb0b8hselasky	    || strncmp(device, "netmap:", 7) == 0
144219bb0b8hselasky	    || strncmp(device, "vale", 4) == 0
144319bb0b8hselasky#endif
144419bb0b8hselasky	    ) {
144519bb0b8hselasky		*netp = *maskp = 0;
144619bb0b8hselasky		return 0;
144719bb0b8hselasky	}
144819bb0b8hselasky
144919bb0b8hselasky	fd = socket(AF_INET, SOCK_DGRAM, 0);
145019bb0b8hselasky	if (fd < 0) {
145119bb0b8hselasky		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
145219bb0b8hselasky		    errno, "socket");
145319bb0b8hselasky		return (-1);
145419bb0b8hselasky	}
145519bb0b8hselasky	memset(&ifr, 0, sizeof(ifr));
145619bb0b8hselasky#ifdef linux
145719bb0b8hselasky	/* XXX Work around Linux kernel bug */
145819bb0b8hselasky	ifr.ifr_addr.sa_family = AF_INET;
145919bb0b8hselasky#endif
1460c2630c9philip	(void)pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
146119bb0b8hselasky	if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
146219bb0b8hselasky		if (errno == EADDRNOTAVAIL) {
146319bb0b8hselasky			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
146419bb0b8hselasky			    "%s: no IPv4 address assigned", device);
146519bb0b8hselasky		} else {
146619bb0b8hselasky			pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
146719bb0b8hselasky			    errno, "SIOCGIFADDR: %s", device);
146819bb0b8hselasky		}
146919bb0b8hselasky		(void)close(fd);
147019bb0b8hselasky		return (-1);
147119bb0b8hselasky	}
147219bb0b8hselasky	sin4 = (struct sockaddr_in *)&ifr.ifr_addr;
147319bb0b8hselasky	*netp = sin4->sin_addr.s_addr;
147419bb0b8hselasky	memset(&ifr, 0, sizeof(ifr));
147519bb0b8hselasky#ifdef linux
147619bb0b8hselasky	/* XXX Work around Linux kernel bug */
147719bb0b8hselasky	ifr.ifr_addr.sa_family = AF_INET;
147819bb0b8hselasky#endif
1479c2630c9philip	(void)pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
148019bb0b8hselasky	if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
148119bb0b8hselasky		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
148219bb0b8hselasky		    errno, "SIOCGIFNETMASK: %s", device);
148319bb0b8hselasky		(void)close(fd);
148419bb0b8hselasky		return (-1);
148519bb0b8hselasky	}
148619bb0b8hselasky	(void)close(fd);
148719bb0b8hselasky	*maskp = sin4->sin_addr.s_addr;
148819bb0b8hselasky	if (*maskp == 0) {
148919bb0b8hselasky		if (IN_CLASSA(*netp))
149019bb0b8hselasky			*maskp = IN_CLASSA_NET;
149119bb0b8hselasky		else if (IN_CLASSB(*netp))
149219bb0b8hselasky			*maskp = IN_CLASSB_NET;
149319bb0b8hselasky		else if (IN_CLASSC(*netp))
149419bb0b8hselasky			*maskp = IN_CLASSC_NET;
149519bb0b8hselasky		else {
149619bb0b8hselasky			(void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
149719bb0b8hselasky			    "inet class for 0x%x unknown", *netp);
149819bb0b8hselasky			return (-1);
149919bb0b8hselasky		}
150019bb0b8hselasky	}
150119bb0b8hselasky	*netp &= *maskp;
150219bb0b8hselasky	return (0);
150319bb0b8hselasky}
150419bb0b8hselasky#endif /* !defined(_WIN32) && !defined(MSDOS) */
150519bb0b8hselasky
150619bb0b8hselasky#ifdef ENABLE_REMOTE
150719bb0b8hselasky#include "pcap-rpcap.h"
150819bb0b8hselasky
150919bb0b8hselasky/*
151019bb0b8hselasky * Extract a substring from a string.
151119bb0b8hselasky */
151219bb0b8hselaskystatic char *
151319bb0b8hselaskyget_substring(const char *p, size_t len, char *ebuf)
151419bb0b8hselasky{
151519bb0b8hselasky	char *token;
151619bb0b8hselasky
151719bb0b8hselasky	token = malloc(len + 1);
151819bb0b8hselasky	if (token == NULL) {
151919bb0b8hselasky		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
152019bb0b8hselasky		    errno, "malloc");
152119bb0b8hselasky		return (NULL);
152219bb0b8hselasky	}
152319bb0b8hselasky	memcpy(token, p, len);
152419bb0b8hselasky	token[len] = '\0';
152519bb0b8hselasky	return (token);
152619bb0b8hselasky}
152719bb0b8hselasky
152819bb0b8hselasky/*
152919bb0b8hselasky * Parse a capture source that might be a URL.
153019bb0b8hselasky *
153119bb0b8hselasky * If the source is not a URL, *schemep, *userinfop, *hostp, and *portp
153219bb0b8hselasky * are set to NULL, *pathp is set to point to the source, and 0 is
153319bb0b8hselasky * returned.
153419bb0b8hselasky *
153519bb0b8hselasky * If source is a URL, and the URL refers to a local device (a special
153619bb0b8hselasky * case of rpcap:), *schemep, *userinfop, *hostp, and *portp are set
153719bb0b8hselasky * to NULL, *pathp is set to point to the device name, and 0 is returned.
153819bb0b8hselasky *
153919bb0b8hselasky * If source is a URL, and it's not a special case that refers to a local
154019bb0b8hselasky * device, and the parse succeeds:
154119bb0b8hselasky *
154219bb0b8hselasky *    *schemep is set to point to an allocated string containing the scheme;
154319bb0b8hselasky *
154419bb0b8hselasky *    if user information is present in the URL, *userinfop is set to point
154519bb0b8hselasky *    to an allocated string containing the user information, otherwise
154619bb0b8hselasky *    it's set to NULL;
154719bb0b8hselasky *
154819bb0b8hselasky *    if host information is present in the URL, *hostp is set to point
154919bb0b8hselasky *    to an allocated string containing the host information, otherwise
155019bb0b8hselasky *    it's set to NULL;
155119bb0b8hselasky *
155219bb0b8hselasky *    if a port number is present in the URL, *portp is set to point
155319bb0b8hselasky *    to an allocated string containing the port number, otherwise
155419bb0b8hselasky *    it's set to NULL;
155519bb0b8hselasky *
155619bb0b8hselasky *    *pathp is set to point to an allocated string containing the
155719bb0b8hselasky *    path;
155819bb0b8hselasky *
155919bb0b8hselasky * and 0 is returned.
156019bb0b8hselasky *
156119bb0b8hselasky * If the parse fails, ebuf is set to an error string, and -1 is returned.
156219bb0b8hselasky */
156319bb0b8hselaskystatic int
156419bb0b8hselaskypcap_parse_source(const char *source, char **schemep, char **userinfop,
156519bb0b8hselasky    char **hostp, char **portp, char **pathp, char *ebuf)
156619bb0b8hselasky{
156719bb0b8hselasky	char *colonp;
156819bb0b8hselasky	size_t scheme_len;
156919bb0b8hselasky	char *scheme;
157019bb0b8hselasky	const char *endp;
157119bb0b8hselasky	size_t authority_len;
157219bb0b8hselasky	char *authority;
157319bb0b8hselasky	char *parsep, *atsignp, *bracketp;
157419bb0b8hselasky	char *userinfo, *host, *port, *path;
157519bb0b8hselasky
157619bb0b8hselasky	/*
157719bb0b8hselasky	 * Start out returning nothing.
157819bb0b8hselasky	 */
157919bb0b8hselasky	*schemep = NULL;
158019bb0b8hselasky	*userinfop = NULL;
158119bb0b8hselasky	*hostp = NULL;
158219bb0b8hselasky	*portp = NULL;
158319bb0b8hselasky	*pathp = NULL;
158419bb0b8hselasky
158519bb0b8hselasky	/*
158619bb0b8hselasky	 * RFC 3986 says:
158719bb0b8hselasky	 *
158819bb0b8hselasky	 *   URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
158919bb0b8hselasky	 *
159019bb0b8hselasky	 *   hier-part   = "//" authority path-abempty
159119bb0b8hselasky	 *               / path-absolute
159219bb0b8hselasky	 *               / path-rootless
159319bb0b8hselasky	 *               / path-empty
159419bb0b8hselasky	 *
159519bb0b8hselasky	 *   authority   = [ userinfo "@" ] host [ ":" port ]
159619bb0b8hselasky	 *
159719bb0b8hselasky	 *   userinfo    = *( unreserved / pct-encoded / sub-delims / ":" )
159819bb0b8hselasky         *
159919bb0b8hselasky         * Step 1: look for the ":" at the end of the scheme.
160019bb0b8hselasky	 * A colon in the source is *NOT* sufficient to indicate that
160119bb0b8hselasky	 * this is a URL, as interface names on some platforms might
160219bb0b8hselasky	 * include colons (e.g., I think some Solaris interfaces
160319bb0b8hselasky	 * might).
160419bb0b8hselasky	 */
160519bb0b8hselasky	colonp = strchr(source, ':');
160619bb0b8hselasky	if (colonp == NULL) {
160719bb0b8hselasky		/*
160819bb0b8hselasky		 * The source is the device to open.
160919bb0b8hselasky		 * Return a NULL pointer for the scheme, user information,
161019bb0b8hselasky		 * host, and port, and return the device as the path.
161119bb0b8hselasky		 */
161219bb0b8hselasky		*pathp = strdup(source);
161319bb0b8hselasky		if (*pathp == NULL) {
161419bb0b8hselasky			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
161519bb0b8hselasky			    errno, "malloc");
161619bb0b8hselasky			return (-1);
161719bb0b8hselasky		}
161819bb0b8hselasky		return (0);
161919bb0b8hselasky	}
162019bb0b8hselasky
162119bb0b8hselasky	/*
162219bb0b8hselasky	 * All schemes must have "//" after them, i.e. we only support
162319bb0b8hselasky	 * hier-part   = "//" authority path-abempty, not
162419bb0b8hselasky	 * hier-part   = path-absolute
162519bb0b8hselasky	 * hier-part   = path-rootless
162619bb0b8hselasky	 * hier-part   = path-empty
162719bb0b8hselasky	 *
162819bb0b8hselasky	 * We need that in order to distinguish between a local device
162919bb0b8hselasky	 * name that happens to contain a colon and a URI.
163019bb0b8hselasky	 */
163119bb0b8hselasky	if (strncmp(colonp + 1, "//", 2) != 0) {
163219bb0b8hselasky		/*
163319bb0b8hselasky		 * The source is the device to open.
163419bb0b8hselasky		 * Return a NULL pointer for the scheme, user information,
163519bb0b8hselasky		 * host, and port, and return the device as the path.
163619bb0b8hselasky		 */
163719bb0b8hselasky		*pathp = strdup(source);
163819bb0b8hselasky		if (*pathp == NULL) {
163919bb0b8hselasky			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
164019bb0b8hselasky			    errno, "malloc");
164119bb0b8hselasky			return (-1);
164219bb0b8hselasky		}
164319bb0b8hselasky		return (0);
164419bb0b8hselasky	}
164519bb0b8hselasky
164619bb0b8hselasky	/*
164719bb0b8hselasky	 * XXX - check whether the purported scheme could be a scheme?
164819bb0b8hselasky	 */
164919bb0b8hselasky
165019bb0b8hselasky	/*
165119bb0b8hselasky	 * OK, this looks like a URL.
165219bb0b8hselasky	 * Get the scheme.
165319bb0b8hselasky	 */
165419bb0b8hselasky	scheme_len = colonp - source;
165519bb0b8hselasky	scheme = malloc(scheme_len + 1);
165619bb0b8hselasky	if (scheme == NULL) {
165719bb0b8hselasky		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
165819bb0b8hselasky		    errno, "malloc");
165919bb0b8hselasky		return (-1);
166019bb0b8hselasky	}
166119bb0b8hselasky	memcpy(scheme, source, scheme_len);
166219bb0b8hselasky	scheme[scheme_len] = '\0';
166319bb0b8hselasky
166419bb0b8hselasky	/*
166519bb0b8hselasky	 * Treat file: specially - take everything after file:// as
166619bb0b8hselasky	 * the pathname.
166719bb0b8hselasky	 */
166819bb0b8hselasky	if (pcap_strcasecmp(scheme, "file") == 0) {
166919bb0b8hselasky		*pathp = strdup(colonp + 3);
167019bb0b8hselasky		if (*pathp == NULL) {
167119bb0b8hselasky			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
167219bb0b8hselasky			    errno, "malloc");
1673c2630c9philip			free(scheme);
167419bb0b8hselasky			return (-1);
167519bb0b8hselasky		}
1676c2630c9philip		*schemep = scheme;
167719bb0b8hselasky		return (0);
167819bb0b8hselasky	}
167919bb0b8hselasky
168019bb0b8hselasky	/*
168119bb0b8hselasky	 * The WinPcap documentation says you can specify a local
168219bb0b8hselasky	 * interface with "rpcap://{device}"; we special-case
168319bb0b8hselasky	 * that here.  If the scheme is "rpcap", and there are
168419bb0b8hselasky	 * no slashes past the "//", we just return the device.
168519bb0b8hselasky	 *
168619bb0b8hselasky	 * XXX - %-escaping?
168719bb0b8hselasky	 */
168819bb0b8hselasky	if (pcap_strcasecmp(scheme, "rpcap") == 0 &&
168919bb0b8hselasky	    strchr(colonp + 3, '/') == NULL) {
169019bb0b8hselasky		/*
169119bb0b8hselasky		 * Local device.
169219bb0b8hselasky		 *
169319bb0b8hselasky		 * Return a NULL pointer for the scheme, user information,
169419bb0b8hselasky		 * host, and port, and return the device as the path.
169519bb0b8hselasky		 */
169619bb0b8hselasky		free(scheme);
169719bb0b8hselasky		*pathp = strdup(colonp + 3);
169819bb0b8hselasky		if (*pathp == NULL) {
169919bb0b8hselasky			pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
170019bb0b8hselasky			    errno, "malloc");
170119bb0b8hselasky			return (-1);
170219bb0b8hselasky		}
170319bb0b8hselasky		return (0);
170419bb0b8hselasky	}
170519bb0b8hselasky
170619bb0b8hselasky	/*
170719bb0b8hselasky	 * OK, now start parsing the authority.
170819bb0b8hselasky	 * Get token, terminated with / or terminated at the end of
170919bb0b8hselasky	 * the string.
171019bb0b8hselasky	 */
171119bb0b8hselasky	authority_len = strcspn(colonp + 3, "/");
171219bb0b8hselasky	authority = get_substring(colonp + 3, authority_len, ebuf);
171319bb0b8hselasky	if (authority == NULL) {
171419bb0b8hselasky		/*
171519bb0b8hselasky		 * Error.
171619bb0b8hselasky		 */
171719bb0b8hselasky		free(scheme);
171819bb0b8hselasky		return (-1);
171919bb0b8hselasky	}
172019bb0b8hselasky	endp = colonp + 3 + authority_len;
172119bb0b8hselasky
172219bb0b8hselasky	/*
172319bb0b8hselasky	 * Now carve the authority field into its components.
172419bb0b8hselasky	 */
172519bb0b8hselasky	parsep = authority;
172619bb0b8hselasky
172719bb0b8hselasky	/*
172819bb0b8hselasky	 * Is there a userinfo field?
172919bb0b8hselasky	 */
173019bb0b8hselasky	atsignp = strchr(parsep, '@');
173119bb0b8hselasky	if (atsignp != NULL) {
173219bb0b8hselasky		/*
173319bb0b8hselasky		 * Yes.
173419bb0b8hselasky		 */
173519bb0b8hselasky		size_t userinfo_len;
173619bb0b8hselasky
173719bb0b8hselasky		userinfo_len = atsignp - parsep;
173819bb0b8hselasky		userinfo = get_substring(parsep, userinfo_len, ebuf);
173919bb0b8hselasky		if (userinfo == NULL) {
174019bb0b8hselasky			/*
174119bb0b8hselasky			 * Error.
174219bb0b8hselasky			 */
174319bb0b8hselasky			free(authority);
174419bb0b8hselasky			free(scheme);
174519bb0b8hselasky			return (-1);
174619bb0b8hselasky		}
174719bb0b8hselasky		parsep = atsignp + 1;
174819bb0b8hselasky	} else {
174919bb0b8hselasky		/*
175019bb0b8hselasky		 * No.
175119bb0b8hselasky		 */
175219bb0b8hselasky		userinfo = NULL;
175319bb0b8hselasky	}
175419bb0b8hselasky
175519bb0b8hselasky	/*
175619bb0b8hselasky	 * Is there a host field?
175719bb0b8hselasky	 */
175819bb0b8hselasky	if (*parsep == '\0') {
175919bb0b8hselasky		/*
176019bb0b8hselasky		 * No; there's no host field or port field.
176119bb0b8hselasky		 */
176219bb0b8hselasky		host = NULL;
176319bb0b8hselasky		port = NULL;
176419bb0b8hselasky	} else {
176519bb0b8hselasky		/*
176619bb0b8hselasky		 * Yes.
176719bb0b8hselasky		 */
176819bb0b8hselasky		size_t host_len;
176919bb0b8hselasky
177019bb0b8hselasky		/*
177119bb0b8hselasky		 * Is it an IP-literal?
177219bb0b8hselasky		 */
177319bb0b8hselasky		if (*parsep == '[') {
177419bb0b8hselasky			/*
177519bb0b8hselasky			 * Yes.
177619bb0b8hselasky			 * Treat verything up to the closing square
177719bb0b8hselasky			 * bracket as the IP-Literal; we don't worry
177819bb0b8hselasky			 * about whether it's a valid IPv6address or
1779c2630c9philip			 * IPvFuture (or an IPv4address, for that
1780c2630c9philip			 * matter, just in case we get handed a
1781c2630c9philip			 * URL with an IPv4 IP-Literal, of the sort
1782c2630c9philip			 * that pcap_createsrcstr() used to generate,
1783c2630c9philip			 * and that pcap_parsesrcstr(), in the original
1784c2630c9philip			 * WinPcap code, accepted).
178519bb0b8hselasky			 */
178619bb0b8hselasky			bracketp = strchr(parsep, ']');
178719bb0b8hselasky			if (bracketp == NULL) {
178819bb0b8hselasky				/*
178919bb0b8hselasky				 * There's no closing square bracket.
179019bb0b8hselasky				 */
179119bb0b8hselasky				pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
179219bb0b8hselasky				    "IP-literal in URL doesn't end with ]");
179319bb0b8hselasky				free(userinfo);
179419bb0b8hselasky				free(authority);
179519bb0b8hselasky				free(scheme);
179619bb0b8hselasky				return (-1);
179719bb0b8hselasky			}
179819bb0b8hselasky			if (*(bracketp + 1) != '\0' &&
179919bb0b8hselasky			    *(bracketp + 1) != ':') {
180019bb0b8hselasky				/*
180119bb0b8hselasky				 * There's extra crud after the
180219bb0b8hselasky				 * closing square bracketn.
180319bb0b8hselasky				 */
180419bb0b8hselasky				pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
180519bb0b8hselasky				    "Extra text after IP-literal in URL");
180619bb0b8hselasky				free(userinfo);
180719bb0b8hselasky				free(authority);
180819bb0b8hselasky				free(scheme);
180919bb0b8hselasky				return (-1);
181019bb0b8hselasky			}
181119bb0b8hselasky			host_len = (bracketp - 1) - parsep;
181219bb0b8hselasky			host = get_substring(parsep + 1, host_len, ebuf);
181319bb0b8hselasky			if (host == NULL) {
181419bb0b8hselasky				/*
181519bb0b8hselasky				 * Error.
181619bb0b8hselasky				 */
181719bb0b8hselasky				free(userinfo);
181819bb0b8hselasky				free(authority);
181919bb0b8hselasky				free(scheme);
182019bb0b8hselasky				return (-1);
182119bb0b8hselasky			}
182219bb0b8hselasky			parsep = bracketp + 1;
182319bb0b8hselasky		} else {
182419bb0b8hselasky			/*
182519bb0b8hselasky			 * No.
182619bb0b8hselasky			 * Treat everything up to a : or the end of
182719bb0b8hselasky			 * the string as the host.
182819bb0b8hselasky			 */
182919bb0b8hselasky			host_len = strcspn(parsep, ":");
183019bb0b8hselasky			host = get_substring(parsep, host_len, ebuf);
183119bb0b8hselasky			if (host == NULL) {
183219bb0b8hselasky				/*
183319bb0b8hselasky				 * Error.
183419bb0b8hselasky				 */
183519bb0b8hselasky				free(userinfo);
183619bb0b8hselasky				free(authority);
183719bb0b8hselasky				free(scheme);
183819bb0b8hselasky				return (-1);
183919bb0b8hselasky			}
184019bb0b8hselasky			parsep = parsep + host_len;
184119bb0b8hselasky		}
184219bb0b8hselasky
184319bb0b8hselasky		/*
184419bb0b8hselasky		 * Is there a port field?
184519bb0b8hselasky		 */
184619bb0b8hselasky		if (*parsep == ':') {
184719bb0b8hselasky			/*
184819bb0b8hselasky			 * Yes.  It's the rest of the authority field.
184919bb0b8hselasky			 */
185019bb0b8hselasky			size_t port_len;
185119bb0b8hselasky
185219bb0b8hselasky			parsep++;
185319bb0b8hselasky			port_len = strlen(parsep);
185419bb0b8hselasky			port = get_substring(parsep, port_len, ebuf);
185519bb0b8hselasky			if (port == NULL) {
185619bb0b8hselasky				/*
185719bb0b8hselasky				 * Error.
185819bb0b8hselasky				 */
185919bb0b8hselasky				free(host);
186019bb0b8hselasky				free(userinfo);
186119bb0b8hselasky				free(authority);
186219bb0b8hselasky				free(scheme);
186319bb0b8hselasky				return (-1);
186419bb0b8hselasky			}
186519bb0b8hselasky		} else {
186619bb0b8hselasky			/*
186719bb0b8hselasky			 * No.
186819bb0b8hselasky			 */
186919bb0b8hselasky			port = NULL;
187019bb0b8hselasky		}
187119bb0b8hselasky	}
187219bb0b8hselasky	free(authority);
187319bb0b8hselasky
187419bb0b8hselasky	/*
187519bb0b8hselasky	 * Everything else is the path.  Strip off the leading /.
187619bb0b8hselasky	 */
187719bb0b8hselasky	if (*endp == '\0')
187819bb0b8hselasky		path = strdup("");
187919bb0b8hselasky	else
188019bb0b8hselasky		path = strdup(endp + 1);
188119bb0b8hselasky	if (path == NULL) {
188219bb0b8hselasky		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
188319bb0b8hselasky		    errno, "malloc");
188419bb0b8hselasky		free(port);
188519bb0b8hselasky		free(host);
188619bb0b8hselasky		free(userinfo);
188719bb0b8hselasky		free(scheme);
188819bb0b8hselasky		return (-1);
188919bb0b8hselasky	}
189019bb0b8hselasky	*schemep = scheme;
189119bb0b8hselasky	*userinfop = userinfo;
189219bb0b8hselasky	*hostp = host;
189319bb0b8hselasky	*portp = port;
189419bb0b8hselasky	*pathp = path;
189519bb0b8hselasky	return (0);
189619bb0b8hselasky}
189719bb0b8hselasky
189819bb0b8hselaskyint
189919bb0b8hselaskypcap_createsrcstr(char *source, int type, const char *host, const char *port,
190019bb0b8hselasky    const char *name, char *errbuf)
190119bb0b8hselasky{
190219bb0b8hselasky	switch (type) {
190319bb0b8hselasky
190419bb0b8hselasky	case PCAP_SRC_FILE:
1905c2630c9philip		pcap_strlcpy(source, PCAP_SRC_FILE_STRING, PCAP_BUF_SIZE);
190619bb0b8hselasky		if (name != NULL && *name != '\0') {
1907c2630c9philip			pcap_strlcat(source, name, PCAP_BUF_SIZE);
190819bb0b8hselasky			return (0);
190919bb0b8hselasky		} else {
191019bb0b8hselasky			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
191119bb0b8hselasky			    "The file name cannot be NULL.");
191219bb0b8hselasky			return (-1);
191319bb0b8hselasky		}
191419bb0b8hselasky
191519bb0b8hselasky	case PCAP_SRC_IFREMOTE:
1916c2630c9philip		pcap_strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
191719bb0b8hselasky		if (host != NULL && *host != '\0') {
191819bb0b8hselasky			if (strchr(host, ':') != NULL) {
191919bb0b8hselasky				/*
192019bb0b8hselasky				 * The host name contains a colon, so it's
192119bb0b8hselasky				 * probably an IPv6 address, and needs to
192219bb0b8hselasky				 * be included in square brackets.
192319bb0b8hselasky				 */
1924c2630c9philip				pcap_strlcat(source, "[", PCAP_BUF_SIZE);
1925c2630c9philip				pcap_strlcat(source, host, PCAP_BUF_SIZE);
1926c2630c9philip				pcap_strlcat(source, "]", PCAP_BUF_SIZE);
192719bb0b8hselasky			} else
1928c2630c9philip				pcap_strlcat(source, host, PCAP_BUF_SIZE);
192919bb0b8hselasky
193019bb0b8hselasky			if (port != NULL && *port != '\0') {
1931c2630c9philip				pcap_strlcat(source, ":", PCAP_BUF_SIZE);
1932c2630c9philip				pcap_strlcat(source, port, PCAP_BUF_SIZE);
193319bb0b8hselasky			}
193419bb0b8hselasky
1935c2630c9philip			pcap_strlcat(source, "/", PCAP_BUF_SIZE);
193619bb0b8hselasky		} else {
193719bb0b8hselasky			pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
193819bb0b8hselasky			    "The host name cannot be NULL.");
193919bb0b8hselasky			return (-1);
194019bb0b8hselasky		}
194119bb0b8hselasky
194219bb0b8hselasky		if (name != NULL && *name != '\0')
1943c2630c9philip			pcap_strlcat(source, name, PCAP_BUF_SIZE);
194419bb0b8hselasky
194519bb0b8hselasky		return (0);
194619bb0b8hselasky
194719bb0b8hselasky	case PCAP_SRC_IFLOCAL:
1948c2630c9philip		pcap_strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
194919bb0b8hselasky
195019bb0b8hselasky		if (name != NULL && *name != '\0')
1951c2630c9philip			pcap_strlcat(source, name, PCAP_BUF_SIZE);
195219bb0b8hselasky
195319bb0b8hselasky		return (0);
195419bb0b8hselasky
195519bb0b8hselasky	default:
195619bb0b8hselasky		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
195719bb0b8hselasky		    "The interface type is not valid.");
195819bb0b8hselasky		return (-1);
195919bb0b8hselasky	}
196019bb0b8hselasky}
196119bb0b8hselasky
196219bb0b8hselaskyint
196319bb0b8hselaskypcap_parsesrcstr(const char *source, int *type, char *host, char *port,
196419bb0b8hselasky    char *name, char *errbuf)
196519bb0b8hselasky{
196619bb0b8hselasky	char *scheme, *tmpuserinfo, *tmphost, *tmpport, *tmppath;
196719bb0b8hselasky
196819bb0b8hselasky	/* Initialization stuff */
196919bb0b8hselasky	if (host)
197019bb0b8hselasky		*host = '\0';
197119bb0b8hselasky	if (port)
197219bb0b8hselasky		*port = '\0';
197319bb0b8hselasky	if (name)
197419bb0b8hselasky		*name = '\0';
197519bb0b8hselasky
197619bb0b8hselasky	/* Parse the source string */
197719bb0b8hselasky	if (pcap_parse_source(source, &scheme, &tmpuserinfo, &tmphost,
197819bb0b8hselasky	    &tmpport, &tmppath, errbuf) == -1) {
197919bb0b8hselasky		/*
198019bb0b8hselasky		 * Fail.
198119bb0b8hselasky		 */
198219bb0b8hselasky		return (-1);
198319bb0b8hselasky	}
198419bb0b8hselasky
198519bb0b8hselasky	if (scheme == NULL) {
198619bb0b8hselasky		/*
198719bb0b8hselasky		 * Local device.
198819bb0b8hselasky		 */
198919bb0b8hselasky		if (name && tmppath)
1990c2630c9philip			pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
199119bb0b8hselasky		if (type)
199219bb0b8hselasky			*type = PCAP_SRC_IFLOCAL;
199319bb0b8hselasky		free(tmppath);
199419bb0b8hselasky		free(tmpport);
199519bb0b8hselasky		free(tmphost);
199619bb0b8hselasky		free(tmpuserinfo);
199719bb0b8hselasky		return (0);
199819bb0b8hselasky	}
199919bb0b8hselasky
200019bb0b8hselasky	if (strcmp(scheme, "rpcap") == 0) {
200119bb0b8hselasky		/*
200219bb0b8hselasky		 * rpcap://
200319bb0b8hselasky		 *
200419bb0b8hselasky		 * pcap_parse_source() has already handled the case of
200519bb0b8hselasky		 * rpcap://device
200619bb0b8hselasky		 */
200719bb0b8hselasky		if (host && tmphost) {
200819bb0b8hselasky			if (tmpuserinfo)
200919bb0b8hselasky				pcap_snprintf(host, PCAP_BUF_SIZE, "%s@%s",
201019bb0b8hselasky				    tmpuserinfo, tmphost);
201119bb0b8hselasky			else
2012c2630c9philip				pcap_strlcpy(host, tmphost, PCAP_BUF_SIZE);
201319bb0b8hselasky		}
201419bb0b8hselasky		if (port && tmpport)
2015c2630c9philip			pcap_strlcpy(port, tmpport, PCAP_BUF_SIZE);
201619bb0b8hselasky		if (name && tmppath)
2017c2630c9philip			pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
201819bb0b8hselasky		if (type)
201919bb0b8hselasky			*type = PCAP_SRC_IFREMOTE;
202019bb0b8hselasky		free(tmppath);
202119bb0b8hselasky		free(tmpport);
202219bb0b8hselasky		free(tmphost);
202319bb0b8hselasky		free(tmpuserinfo);
202419bb0b8hselasky		free(scheme);
202519bb0b8hselasky		return (0);
202619bb0b8hselasky	}
202719bb0b8hselasky
202819bb0b8hselasky	if (strcmp(scheme, "file") == 0) {
202919bb0b8hselasky		/*
203019bb0b8hselasky		 * file://
203119bb0b8hselasky		 */
203219bb0b8hselasky		if (name && tmppath)
2033c2630c9philip			pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
203419bb0b8hselasky		if (type)
203519bb0b8hselasky			*type = PCAP_SRC_FILE;
203619bb0b8hselasky		free(tmppath);
203719bb0b8hselasky		free(tmpport);
203819bb0b8hselasky		free(tmphost);
203919bb0b8hselasky		free(tmpuserinfo);
204019bb0b8hselasky		free(scheme);
204119bb0b8hselasky		return (0);
204219bb0b8hselasky	}
204319bb0b8hselasky
204419bb0b8hselasky	/*
204519bb0b8hselasky	 * Neither rpcap: nor file:; just treat the entire string
204619bb0b8hselasky	 * as a local device.
204719bb0b8hselasky	 */
204819bb0b8hselasky	if (name)
2049c2630c9philip		pcap_strlcpy(name, source, PCAP_BUF_SIZE);
205019bb0b8hselasky	if (type)
205119bb0b8hselasky		*type = PCAP_SRC_IFLOCAL;
205219bb0b8hselasky	free(tmppath);
205319bb0b8hselasky	free(tmpport);
205419bb0b8hselasky	free(tmphost);
205519bb0b8hselasky	free(tmpuserinfo);
205619bb0b8hselasky	free(scheme);
205719bb0b8hselasky	return (0);
205819bb0b8hselasky}
205919bb0b8hselasky#endif
206019bb0b8hselasky
206119bb0b8hselaskypcap_t *
206219bb0b8hselaskypcap_create(const char *device, char *errbuf)
206319bb0b8hselasky{
206419bb0b8hselasky	size_t i;
206519bb0b8hselasky	int is_theirs;
206619bb0b8hselasky	pcap_t *p;
206719bb0b8hselasky	char *device_str;
206819bb0b8hselasky
206919bb0b8hselasky	/*
207019bb0b8hselasky	 * A null device name is equivalent to the "any" device -
207119bb0b8hselasky	 * which might not be supported on this platform, but
207219bb0b8hselasky	 * this means that you'll get a "not supported" error
207319bb0b8hselasky	 * rather than, say, a crash when we try to dereference
207419bb0b8hselasky	 * the null pointer.
207519bb0b8hselasky	 */
207619bb0b8hselasky	if (device == NULL)
207719bb0b8hselasky		device_str = strdup("any");
207819bb0b8hselasky	else {
207919bb0b8hselasky#ifdef _WIN32
208019bb0b8hselasky		/*
2081c2630c9philip		 * On Windows, for backwards compatibility reasons,
2082c2630c9philip		 * pcap_lookupdev() returns a pointer to a sequence of
2083c2630c9philip		 * pairs of UTF-16LE device names and local code page
2084c2630c9philip		 * description strings.
2085c2630c9philip		 *
2086c2630c9philip		 * This means that if a program uses pcap_lookupdev()
2087c2630c9philip		 * to get a default device, and hands that to an API
2088c2630c9philip		 * that opens devices, we'll get handed a UTF-16LE
2089c2630c9philip		 * string, not a string in the local code page.
209019bb0b8hselasky		 *
2091c2630c9philip		 * To work around that, we check whether the string
2092c2630c9philip		 * looks as if it might be a UTF-16LE strinh and, if
2093c2630c9philip		 * so, convert it back to the local code page's
2094c2630c9philip		 * extended ASCII.
2095c2630c9philip		 *
2096c2630c9philip		 * XXX - you *cannot* reliably detect whether a
2097c2630c9philip		 * string is UTF-16LE or not; "a" could either
2098c2630c9philip		 * be a one-character ASCII string or the first
2099c2630c9philip		 * character of a UTF-16LE string.  This particular
2100c2630c9philip		 * version of this heuristic dates back to WinPcap
2101c2630c9philip		 * 4.1.1; PacketOpenAdapter() does uses the same
2102c2630c9philip		 * heuristic, with the exact same vulnerability.
210319bb0b8hselasky		 */
210419bb0b8hselasky		if (device[0] != '\0' && device[1] == '\0') {
210519bb0b8hselasky			size_t length;
210619bb0b8hselasky
210719bb0b8hselasky			length = wcslen((wchar_t *)device);
210819bb0b8hselasky			device_str = (char *)malloc(length + 1);
210919bb0b8hselasky			if (device_str == NULL) {
211019bb0b8hselasky				pcap_fmt_errmsg_for_errno(errbuf,
211119bb0b8hselasky				    PCAP_ERRBUF_SIZE, errno,
211219bb0b8hselasky				    "malloc");
211319bb0b8hselasky				return (NULL);
211419bb0b8hselasky			}
211519bb0b8hselasky
211619bb0b8hselasky			pcap_snprintf(device_str, length + 1, "%ws",
211719bb0b8hselasky			    (const wchar_t *)device);
211819bb0b8hselasky		} else
211919bb0b8hselasky#endif
212019bb0b8hselasky			device_str = strdup(device);
212119bb0b8hselasky	}
212219bb0b8hselasky	if (device_str == NULL) {
212319bb0b8hselasky		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
212419bb0b8hselasky		    errno, "malloc");
212519bb0b8hselasky		return (NULL);
212619bb0b8hselasky	}
212719bb0b8hselasky
212819bb0b8hselasky	/*
212919bb0b8hselasky	 * Try each of the non-local-network-interface capture
213019bb0b8hselasky	 * source types until we find one that works for this
213119bb0b8hselasky	 * device or run out of types.
213219bb0b8hselasky	 */
213319bb0b8hselasky	for (i = 0; capture_source_types[i].create_op != NULL; i++) {
213419bb0b8hselasky		is_theirs = 0;
213519bb0b8hselasky		p = capture_source_types[i].create_op(device_str, errbuf,
213619bb0b8hselasky		    &is_theirs);
213719bb0b8hselasky		if (is_theirs) {
213819bb0b8hselasky			/*
213919bb0b8hselasky			 * The device name refers to a device of the
214019bb0b8hselasky			 * type in question; either it succeeded,
214119bb0b8hselasky			 * in which case p refers to a pcap_t to
214219bb0b8hselasky			 * later activate for the device, or it
214319bb0b8hselasky			 * failed, in which case p is null and we
214419bb0b8hselasky			 * should return that to report the failure
214519bb0b8hselasky			 * to create.
214619bb0b8hselasky			 */
214719bb0b8hselasky			if (p == NULL) {
214819bb0b8hselasky				/*
214919bb0b8hselasky				 * We assume the caller filled in errbuf.
215019bb0b8hselasky				 */
215119bb0b8hselasky				free(device_str);
215219bb0b8hselasky				return (NULL);
215319bb0b8hselasky			}
215419bb0b8hselasky			p->opt.device = device_str;
215519bb0b8hselasky			return (p);
215619bb0b8hselasky		}
215719bb0b8hselasky	}
215819bb0b8hselasky
215919bb0b8hselasky	/*
216019bb0b8hselasky	 * OK, try it as a regular network interface.
216119bb0b8hselasky	 */
216219bb0b8hselasky	p = pcap_create_interface(device_str, errbuf);
216319bb0b8hselasky	if (p == NULL) {
216419bb0b8hselasky		/*
216519bb0b8hselasky		 * We assume the caller filled in errbuf.
216619bb0b8hselasky		 */
216719bb0b8hselasky		free(device_str);
216819bb0b8hselasky		return (NULL);
216919bb0b8hselasky	}
217019bb0b8hselasky	p->opt.device = device_str;
217119bb0b8hselasky	return (p);
217219bb0b8hselasky}
217319bb0b8hselasky
217419bb0b8hselasky/*
217519bb0b8hselasky * Set nonblocking mode on an unactivated pcap_t; this sets a flag
217619bb0b8hselasky * checked by pcap_activate(), which sets the mode after calling
217719bb0b8hselasky * the activate routine.
217819bb0b8hselasky */
217919bb0b8hselaskystatic int
218019bb0b8hselaskypcap_setnonblock_unactivated(pcap_t *p, int nonblock)
218119bb0b8hselasky{
218219bb0b8hselasky	p->opt.nonblock = nonblock;
218319bb0b8hselasky	return (0);
218419bb0b8hselasky}
218519bb0b8hselasky
218619bb0b8hselaskystatic void
218719bb0b8hselaskyinitialize_ops(pcap_t *p)
218819bb0b8hselasky{
218919bb0b8hselasky	/*
219019bb0b8hselasky	 * Set operation pointers for operations that only work on
219119bb0b8hselasky	 * an activated pcap_t to point to a routine that returns
219219bb0b8hselasky	 * a "this isn't activated" error.
219319bb0b8hselasky	 */
2194c2630c9philip	p->read_op = pcap_read_not_initialized;
2195c2630c9philip	p->inject_op = pcap_inject_not_initialized;
2196c2630c9philip	p->setfilter_op = pcap_setfilter_not_initialized;
2197c2630c9philip	p->setdirection_op = pcap_setdirection_not_initialized;
2198c2630c9philip	p->set_datalink_op = pcap_set_datalink_not_initialized;
2199c2630c9philip	p->getnonblock_op = pcap_getnonblock_not_initialized;
2200c2630c9philip	p->stats_op = pcap_stats_not_initialized;
220119bb0b8hselasky#ifdef _WIN32
2202c2630c9philip	p->stats_ex_op = pcap_stats_ex_not_initialized;
2203c2630c9philip	p->setbuff_op = pcap_setbuff_not_initialized;
2204c2630c9philip	p->setmode_op = pcap_setmode_not_initialized;
2205c2630c9philip	p->setmintocopy_op = pcap_setmintocopy_not_initialized;
220619bb0b8hselasky	p->getevent_op = pcap_getevent_not_initialized;
2207c2630c9philip	p->oid_get_request_op = pcap_oid_get_request_not_initialized;
2208c2630c9philip	p->oid_set_request_op = pcap_oid_set_request_not_initialized;
220919bb0b8hselasky	p->sendqueue_transmit_op = pcap_sendqueue_transmit_not_initialized;
2210c2630c9philip	p->setuserbuffer_op = pcap_setuserbuffer_not_initialized;
2211c2630c9philip	p->live_dump_op = pcap_live_dump_not_initialized;
2212c2630c9philip	p->live_dump_ended_op = pcap_live_dump_ended_not_initialized;
221319bb0b8hselasky	p->get_airpcap_handle_op = pcap_get_airpcap_handle_not_initialized;
221419bb0b8hselasky#endif
221519bb0b8hselasky
221619bb0b8hselasky	/*
221719bb0b8hselasky	 * Default cleanup operation - implementations can override
221819bb0b8hselasky	 * this, but should call pcap_cleanup_live_common() after
221919bb0b8hselasky	 * doing their own additional cleanup.
222019bb0b8hselasky	 */
222119bb0b8hselasky	p->cleanup_op = pcap_cleanup_live_common;
222219bb0b8hselasky
222319bb0b8hselasky	/*
222419bb0b8hselasky	 * In most cases, the standard one-shot callback can
222519bb0b8hselasky	 * be used for pcap_next()/pcap_next_ex().
222619bb0b8hselasky	 */
222719bb0b8hselasky	p->oneshot_callback = pcap_oneshot;
222819bb0b8hselasky}
222919bb0b8hselasky
223019bb0b8hselaskystatic pcap_t *
223119bb0b8hselaskypcap_alloc_pcap_t(char *ebuf, size_t size)
223219bb0b8hselasky{
223319bb0b8hselasky	char *chunk;
223419bb0b8hselasky	pcap_t *p;
223519bb0b8hselasky
223619bb0b8hselasky	/*
223719bb0b8hselasky	 * Allocate a chunk of memory big enough for a pcap_t
223819bb0b8hselasky	 * plus a structure following it of size "size".  The
223919bb0b8hselasky	 * structure following it is a private data structure
224019bb0b8hselasky	 * for the routines that handle this pcap_t.
2241c2630c9philip	 *
2242c2630c9philip	 * The structure following it must be aligned on
2243c2630c9philip	 * the appropriate alignment boundary for this platform.
2244c2630c9philip	 * We align on an 8-byte boundary as that's probably what
2245c2630c9philip	 * at least some platforms do, even with 32-bit integers,
2246c2630c9philip	 * and because we can't be sure that some values won't
2247c2630c9philip	 * require 8-byte alignment even on platforms with 32-bit
2248c2630c9philip	 * integers.
224919bb0b8hselasky	 */
2250c2630c9philip#define PCAP_T_ALIGNED_SIZE	((sizeof(pcap_t) + 7U) & ~0x7U)
2251c2630c9philip	chunk = malloc(PCAP_T_ALIGNED_SIZE + size);
225219bb0b8hselasky	if (chunk == NULL) {
225319bb0b8hselasky		pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
225419bb0b8hselasky		    errno, "malloc");
225519bb0b8hselasky		return (NULL);
225619bb0b8hselasky	}
2257c2630c9philip	memset(chunk, 0, PCAP_T_ALIGNED_SIZE + size);
225819bb0b8hselasky
225919bb0b8hselasky	/*
226019bb0b8hselasky	 * Get a pointer to the pcap_t at the beginning.
226119bb0b8hselasky	 */
226219bb0b8hselasky	p = (pcap_t *)chunk;
226319bb0b8hselasky
226419bb0b8hselasky#ifdef _WIN32
226519bb0b8hselasky	p->handle = INVALID_HANDLE_VALUE;	/* not opened yet */
226619bb0b8hselasky#else /* _WIN32 */
2267d8d18f6rpaulo	p->fd = -1;	/* not opened yet */
226819bb0b8hselasky#ifndef MSDOS
2269724e1a0rpaulo	p->selectable_fd = -1;
227019bb0b8hselasky	p->required_select_timeout = NULL;
227119bb0b8hselasky#endif /* MSDOS */
227219bb0b8hselasky#endif /* _WIN32 */
2273489abeddelphij
2274489abeddelphij	if (size == 0) {
2275489abeddelphij		/* No private data was requested. */
2276489abeddelphij		p->priv = NULL;
2277489abeddelphij	} else {
2278489abeddelphij		/*
2279489abeddelphij		 * Set the pointer to the private data; that's the structure
2280489abeddelphij		 * of size "size" following the pcap_t.
2281489abeddelphij		 */
2282c2630c9philip		p->priv = (void *)(chunk + PCAP_T_ALIGNED_SIZE);
2283489abeddelphij	}
2284489abeddelphij
2285489abeddelphij	return (p);
2286489abeddelphij}
2287489abeddelphij
2288489abeddelphijpcap_t *
228994960e5delphijpcap_create_common(char *ebuf, size_t size)
2290489abeddelphij{
2291489abeddelphij	pcap_t *p;
2292489abeddelphij
2293489abeddelphij	p = pcap_alloc_pcap_t(ebuf, size);
2294489abeddelphij	if (p == NULL)
2295489abeddelphij		return (NULL);
2296d8d18f6rpaulo
2297d8d18f6rpaulo	/*
2298d8d18f6rpaulo	 * Default to "can't set rfmon mode"; if it's supported by
2299724e1a0rpaulo	 * a platform, the create routine that called us can set
2300724e1a0rpaulo	 * the op to its routine to check whether a particular
2301724e1a0rpaulo	 * device supports it.
2302d8d18f6rpaulo	 */
2303d8d18f6rpaulo	p->can_set_rfmon_op = pcap_cant_set_rfmon;
2304d8d18f6rpaulo
230519bb0b8hselasky	/*
230619bb0b8hselasky	 * If pcap_setnonblock() is called on a not-yet-activated
230719bb0b8hselasky	 * pcap_t, default to setting a flag and turning
230819bb0b8hselasky	 * on non-blocking mode when activated.
230919bb0b8hselasky	 */
231019bb0b8hselasky	p->setnonblock_op = pcap_setnonblock_unactivated;
231119bb0b8hselasky
2312724e1a0rpaulo	initialize_ops(p);
2313d8d18f6rpaulo
2314d8d18f6rpaulo	/* put in some defaults*/
231519bb0b8hselasky	p->snapshot = 0;		/* max packet size unspecified */
231694960e5delphij	p->opt.timeout = 0;		/* no timeout specified */
231794960e5delphij	p->opt.buffer_size = 0;		/* use the platform's default */
2318d8d18f6rpaulo	p->opt.promisc = 0;
2319489abeddelphij	p->opt.rfmon = 0;
2320489abeddelphij	p->opt.immediate = 0;
2321c5b3ac4gnn	p->opt.tstamp_type = -1;	/* default to not setting time stamp type */
2322489abeddelphij	p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
232319bb0b8hselasky	/*
232419bb0b8hselasky	 * Platform-dependent options.
232519bb0b8hselasky	 */
232619bb0b8hselasky#ifdef __linux__
232719bb0b8hselasky	p->opt.protocol = 0;
232819bb0b8hselasky#endif
232919bb0b8hselasky#ifdef _WIN32
233019bb0b8hselasky	p->opt.nocapture_local = 0;
233119bb0b8hselasky#endif
233294960e5delphij
233394960e5delphij	/*
233494960e5delphij	 * Start out with no BPF code generation flags set.
233594960e5delphij	 */
233694960e5delphij	p->bpf_codegen_flags = 0;
233794960e5delphij
2338d8d18f6rpaulo	return (p);
2339d8d18f6rpaulo}
2340d8d18f6rpaulo
2341d8d18f6rpauloint
2342d8d18f6rpaulopcap_check_activated(pcap_t *p)
2343d8d18f6rpaulo{
2344d8d18f6rpaulo	if (p->activated) {
234594960e5delphij		pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
2346d8d18f6rpaulo			" operation on activated capture");
2347c5b3ac4gnn		return (-1);
2348d8d18f6rpaulo	}
2349c5b3ac4gnn	return (0);
2350d8d18f6rpaulo}
2351d8d18f6rpaulo
2352d8d18f6rpauloint
2353d8d18f6rpaulopcap_set_snaplen(pcap_t *p, int snaplen)
2354d8d18f6rpaulo{
2355d8d18f6rpaulo	if (pcap_check_activated(p))
2356c5b3ac4gnn		return (PCAP_ERROR_ACTIVATED);
2357d8d18f6rpaulo	p->snapshot = snaplen;
2358c5b3ac4gnn	return (0);
2359d8d18f6rpaulo}
2360d8d18f6rpaulo
2361d8d18f6rpauloint
2362d8d18f6rpaulopcap_set_promisc(pcap_t *p, int promisc)
2363d8d18f6rpaulo{
2364d8d18f6rpaulo	if (pcap_check_activated(p))
2365c5b3ac4gnn		return (PCAP_ERROR_ACTIVATED);
2366d8d18f6rpaulo	p->opt.promisc = promisc;
2367c5b3ac4gnn	return (0);
2368d8d18f6rpaulo}
2369d8d18f6rpaulo
2370d8d18f6rpauloint
2371d8d18f6rpaulopcap_set_rfmon(pcap_t *p, int rfmon)
2372d8d18f6rpaulo{
2373d8d18f6rpaulo	if (pcap_check_activated(p))
2374c5b3ac4gnn		return (PCAP_ERROR_ACTIVATED);
2375d8d18f6rpaulo	p->opt.rfmon = rfmon;
2376c5b3ac4gnn	return (0);
2377d8d18f6rpaulo}
2378d8d18f6rpaulo
2379d8d18f6rpauloint
2380d8d18f6rpaulopcap_set_timeout(pcap_t *p, int timeout_ms)
2381f0fdf33pst{
2382d8d18f6rpaulo	if (pcap_check_activated(p))
2383c5b3ac4gnn		return (PCAP_ERROR_ACTIVATED);
2384489abeddelphij	p->opt.timeout = timeout_ms;
2385c5b3ac4gnn	return (0);
2386c5b3ac4gnn}
2387c5b3ac4gnn
2388c5b3ac4gnnint
2389c5b3ac4gnnpcap_set_tstamp_type(pcap_t *p, int tstamp_type)
2390c5b3ac4gnn{
2391c5b3ac4gnn	int i;
2392c5b3ac4gnn
2393c5b3ac4gnn	if (pcap_check_activated(p))
2394c5b3ac4gnn		return (PCAP_ERROR_ACTIVATED);
2395c5b3ac4gnn
2396c5b3ac4gnn	/*
239794960e5delphij	 * The argument should have been u_int, but that's too late
239894960e5delphij	 * to change now - it's an API.
239994960e5delphij	 */
240094960e5delphij	if (tstamp_type < 0)
240194960e5delphij		return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
240294960e5delphij
240394960e5delphij	/*
2404489abeddelphij	 * If p->tstamp_type_count is 0, we only support PCAP_TSTAMP_HOST;
2405489abeddelphij	 * the default time stamp type is PCAP_TSTAMP_HOST.
2406c5b3ac4gnn	 */
2407489abeddelphij	if (p->tstamp_type_count == 0) {
2408489abeddelphij		if (tstamp_type == PCAP_TSTAMP_HOST) {
2409c5b3ac4gnn			p->opt.tstamp_type = tstamp_type;
2410c5b3ac4gnn			return (0);
2411c5b3ac4gnn		}
2412489abeddelphij	} else {
2413489abeddelphij		/*
2414489abeddelphij		 * Check whether we claim to support this type of time stamp.
2415489abeddelphij		 */
2416489abeddelphij		for (i = 0; i < p->tstamp_type_count; i++) {
241794960e5delphij			if (p->tstamp_type_list[i] == (u_int)tstamp_type) {
2418489abeddelphij				/*
2419489abeddelphij				 * Yes.
2420489abeddelphij				 */
2421489abeddelphij				p->opt.tstamp_type = tstamp_type;
2422489abeddelphij				return (0);
2423489abeddelphij			}
2424489abeddelphij		}
2425c5b3ac4gnn	}
2426c5b3ac4gnn
2427c5b3ac4gnn	/*
2428489abeddelphij	 * We don't support this type of time stamp.
2429c5b3ac4gnn	 */
2430c5b3ac4gnn	return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
2431d8d18f6rpaulo}
2432d8d18f6rpaulo
2433d8d18f6rpauloint
2434489abeddelphijpcap_set_immediate_mode(pcap_t *p, int immediate)
2435489abeddelphij{
2436489abeddelphij	if (pcap_check_activated(p))
2437489abeddelphij		return (PCAP_ERROR_ACTIVATED);
2438489abeddelphij	p->opt.immediate = immediate;
2439489abeddelphij	return (0);
2440489abeddelphij}
2441489abeddelphij
2442489abeddelphijint
2443d8d18f6rpaulopcap_set_buffer_size(pcap_t *p, int buffer_size)
2444d8d18f6rpaulo{
2445d8d18f6rpaulo	if (pcap_check_activated(p))
2446c5b3ac4gnn		return (PCAP_ERROR_ACTIVATED);
244794960e5delphij	if (buffer_size <= 0) {
244894960e5delphij		/*
244994960e5delphij		 * Silently ignore invalid values.
245094960e5delphij		 */
245194960e5delphij		return (0);
245294960e5delphij	}
2453d8d18f6rpaulo	p->opt.buffer_size = buffer_size;
2454c5b3ac4gnn	return (0);
2455d8d18f6rpaulo}
2456d8d18f6rpaulo
2457d8d18f6rpauloint
2458489abeddelphijpcap_set_tstamp_precision(pcap_t *p, int tstamp_precision)
2459489abeddelphij{
2460489abeddelphij	int i;
2461489abeddelphij
2462489abeddelphij	if (pcap_check_activated(p))
2463489abeddelphij		return (PCAP_ERROR_ACTIVATED);
2464489abeddelphij
2465489abeddelphij	/*
246694960e5delphij	 * The argument should have been u_int, but that's too late
246794960e5delphij	 * to change now - it's an API.
246894960e5delphij	 */
246994960e5delphij	if (tstamp_precision < 0)
247094960e5delphij		return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
247194960e5delphij
247294960e5delphij	/*
2473489abeddelphij	 * If p->tstamp_precision_count is 0, we only support setting
2474489abeddelphij	 * the time stamp precision to microsecond precision; every
2475489abeddelphij	 * pcap module *MUST* support microsecond precision, even if
2476489abeddelphij	 * it does so by converting the native precision to
2477489abeddelphij	 * microseconds.
2478489abeddelphij	 */
2479489abeddelphij	if (p->tstamp_precision_count == 0) {
2480489abeddelphij		if (tstamp_precision == PCAP_TSTAMP_PRECISION_MICRO) {
2481489abeddelphij			p->opt.tstamp_precision = tstamp_precision;
2482489abeddelphij			return (0);
2483489abeddelphij		}
2484489abeddelphij	} else {
2485489abeddelphij		/*
2486489abeddelphij		 * Check whether we claim to support this precision of
2487489abeddelphij		 * time stamp.
2488489abeddelphij		 */
2489489abeddelphij		for (i = 0; i < p->tstamp_precision_count; i++) {
249094960e5delphij			if (p->tstamp_precision_list[i] == (u_int)tstamp_precision) {
2491489abeddelphij				/*
2492489abeddelphij				 * Yes.
2493489abeddelphij				 */
2494489abeddelphij				p->opt.tstamp_precision = tstamp_precision;
2495489abeddelphij				return (0);
2496489abeddelphij			}
2497489abeddelphij		}
2498489abeddelphij	}
2499489abeddelphij
2500489abeddelphij	/*
2501489abeddelphij	 * We don't support this time stamp precision.
2502489abeddelphij	 */
2503489abeddelphij	return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
2504489abeddelphij}
2505489abeddelphij
2506489abeddelphijint
2507489abeddelphijpcap_get_tstamp_precision(pcap_t *p)
2508489abeddelphij{
2509489abeddelphij        return (p->opt.tstamp_precision);
2510489abeddelphij}
2511489abeddelphij
2512489abeddelphijint
2513d8d18f6rpaulopcap_activate(pcap_t *p)
2514d8d18f6rpaulo{
2515d8d18f6rpaulo	int status;
2516f0fdf33pst
2517c5b3ac4gnn	/*
2518c5b3ac4gnn	 * Catch attempts to re-activate an already-activated
2519c5b3ac4gnn	 * pcap_t; this should, for example, catch code that
2520c5b3ac4gnn	 * calls pcap_open_live() followed by pcap_activate(),
2521c5b3ac4gnn	 * as some code that showed up in a Stack Exchange
2522c5b3ac4gnn	 * question did.
2523c5b3ac4gnn	 */
2524c5b3ac4gnn	if (pcap_check_activated(p))
2525c5b3ac4gnn		return (PCAP_ERROR_ACTIVATED);
2526d8d18f6rpaulo	status = p->activate_op(p);
252719bb0b8hselasky	if (status >= 0) {
252819bb0b8hselasky		/*
252919bb0b8hselasky		 * If somebody requested non-blocking mode before
253019bb0b8hselasky		 * calling pcap_activate(), turn it on now.
253119bb0b8hselasky		 */
253219bb0b8hselasky		if (p->opt.nonblock) {
253319bb0b8hselasky			status = p->setnonblock_op(p, 1);
253419bb0b8hselasky			if (status < 0) {
253519bb0b8hselasky				/*
253619bb0b8hselasky				 * Failed.  Undo everything done by
253719bb0b8hselasky				 * the activate operation.
253819bb0b8hselasky				 */
253919bb0b8hselasky				p->cleanup_op(p);
254019bb0b8hselasky				initialize_ops(p);
254119bb0b8hselasky				return (status);
254219bb0b8hselasky			}
254319bb0b8hselasky		}
2544d8d18f6rpaulo		p->activated = 1;
254519bb0b8hselasky	} else {
2546724e1a0rpaulo		if (p->errbuf[0] == '\0') {
2547724e1a0rpaulo			/*
2548724e1a0rpaulo			 * No error message supplied by the activate routine;
2549724e1a0rpaulo			 * for the benefit of programs that don't specially
2550724e1a0rpaulo			 * handle errors other than PCAP_ERROR, return the
2551724e1a0rpaulo			 * error message corresponding to the status.
2552724e1a0rpaulo			 */
255394960e5delphij			pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
2554724e1a0rpaulo			    pcap_statustostr(status));
2555724e1a0rpaulo		}
2556724e1a0rpaulo
2557724e1a0rpaulo		/*
2558724e1a0rpaulo		 * Undo any operation pointer setting, etc. done by
2559724e1a0rpaulo		 * the activate operation.
2560724e1a0rpaulo		 */
2561724e1a0rpaulo		initialize_ops(p);
2562724e1a0rpaulo	}
2563d8d18f6rpaulo	return (status);
2564d8d18f6rpaulo}
2565d8d18f6rpaulo
2566d8d18f6rpaulopcap_t *
256794960e5delphijpcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf)
2568d8d18f6rpaulo{
2569d8d18f6rpaulo	pcap_t *p;
2570d8d18f6rpaulo	int status;
257119bb0b8hselasky#ifdef ENABLE_REMOTE
257219bb0b8hselasky	char host[PCAP_BUF_SIZE + 1];
257319bb0b8hselasky	char port[PCAP_BUF_SIZE + 1];
257419bb0b8hselasky	char name[PCAP_BUF_SIZE + 1];
257519bb0b8hselasky	int srctype;
257619bb0b8hselasky
257719bb0b8hselasky	/*
2578c2630c9philip	 * A null device name is equivalent to the "any" device -
2579c2630c9philip	 * which might not be supported on this platform, but
2580c2630c9philip	 * this means that you'll get a "not supported" error
2581c2630c9philip	 * rather than, say, a crash when we try to dereference
2582c2630c9philip	 * the null pointer.
2583c2630c9philip	 */
2584c2630c9philip	if (device == NULL)
2585c2630c9philip		device = "any";
2586c2630c9philip
2587c2630c9philip	/*
258819bb0b8hselasky	 * Retrofit - we have to make older applications compatible with
258919bb0b8hselasky	 * remote capture.
259019bb0b8hselasky	 * So we're calling pcap_open_remote() from here; this is a very
259119bb0b8hselasky	 * dirty hack.
259219bb0b8hselasky	 * Obviously, we cannot exploit all the new features; for instance,
259319bb0b8hselasky	 * we cannot send authentication, we cannot use a UDP data connection,
259419bb0b8hselasky	 * and so on.
259519bb0b8hselasky	 */
259619bb0b8hselasky	if (pcap_parsesrcstr(device, &srctype, host, port, name, errbuf))
259719bb0b8hselasky		return (NULL);
259819bb0b8hselasky
259919bb0b8hselasky	if (srctype == PCAP_SRC_IFREMOTE) {
260019bb0b8hselasky		/*
260119bb0b8hselasky		 * Although we already have host, port and iface, we prefer
260219bb0b8hselasky		 * to pass only 'device' to pcap_open_rpcap(), so that it has
260319bb0b8hselasky		 * to call pcap_parsesrcstr() again.
260419bb0b8hselasky		 * This is less optimized, but much clearer.
260519bb0b8hselasky		 */
260619bb0b8hselasky		return (pcap_open_rpcap(device, snaplen,
260719bb0b8hselasky		    promisc ? PCAP_OPENFLAG_PROMISCUOUS : 0, to_ms,
260819bb0b8hselasky		    NULL, errbuf));
260919bb0b8hselasky	}
261019bb0b8hselasky	if (srctype == PCAP_SRC_FILE) {
261119bb0b8hselasky		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown URL scheme \"file\"");
261219bb0b8hselasky		return (NULL);
261319bb0b8hselasky	}
261419bb0b8hselasky	if (srctype == PCAP_SRC_IFLOCAL) {
261519bb0b8hselasky		/*
261619bb0b8hselasky		 * If it starts with rpcap://, that refers to a local device
261719bb0b8hselasky		 * (no host part in the URL). Remove the rpcap://, and
261819bb0b8hselasky		 * fall through to the regular open path.
261919bb0b8hselasky		 */
262019bb0b8hselasky		if (strncmp(device, PCAP_SRC_IF_STRING, strlen(PCAP_SRC_IF_STRING)) == 0) {
262119bb0b8hselasky			size_t len = strlen(device) - strlen(PCAP_SRC_IF_STRING) + 1;
262219bb0b8hselasky
262319bb0b8hselasky			if (len > 0)
262419bb0b8hselasky				device += strlen(PCAP_SRC_IF_STRING);
262519bb0b8hselasky		}
262619bb0b8hselasky	}
262719bb0b8hselasky#endif	/* ENABLE_REMOTE */
2628d8d18f6rpaulo
262994960e5delphij	p = pcap_create(device, errbuf);
2630d8d18f6rpaulo	if (p == NULL)
2631d8d18f6rpaulo		return (NULL);
2632d8d18f6rpaulo	status = pcap_set_snaplen(p, snaplen);
2633d8d18f6rpaulo	if (status < 0)
2634d8d18f6rpaulo		goto fail;
2635d8d18f6rpaulo	status = pcap_set_promisc(p, promisc);
2636d8d18f6rpaulo	if (status < 0)
2637d8d18f6rpaulo		goto fail;
2638d8d18f6rpaulo	status = pcap_set_timeout(p, to_ms);
2639d8d18f6rpaulo	if (status < 0)
2640d8d18f6rpaulo		goto fail;
2641d8d18f6rpaulo	/*
2642d8d18f6rpaulo	 * Mark this as opened with pcap_open_live(), so that, for
2643d8d18f6rpaulo	 * example, we show the full list of DLT_ values, rather
2644d8d18f6rpaulo	 * than just the ones that are compatible with capturing
2645d8d18f6rpaulo	 * when not in monitor mode.  That allows existing applications
2646d8d18f6rpaulo	 * to work the way they used to work, but allows new applications
2647d8d18f6rpaulo	 * that know about the new open API to, for example, find out the
2648d8d18f6rpaulo	 * DLT_ values that they can select without changing whether
2649d8d18f6rpaulo	 * the adapter is in monitor mode or not.
2650d8d18f6rpaulo	 */
2651d8d18f6rpaulo	p->oldstyle = 1;
2652d8d18f6rpaulo	status = pcap_activate(p);
2653d8d18f6rpaulo	if (status < 0)
2654d8d18f6rpaulo		goto fail;
2655d8d18f6rpaulo	return (p);
2656d8d18f6rpaulofail:
2657724e1a0rpaulo	if (status == PCAP_ERROR)
2658c2630c9philip		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %.*s", device,
2659c2630c9philip		    PCAP_ERRBUF_SIZE - 3, p->errbuf);
2660724e1a0rpaulo	else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
2661c5b3ac4gnn	    status == PCAP_ERROR_PERM_DENIED ||
2662c5b3ac4gnn	    status == PCAP_ERROR_PROMISC_PERM_DENIED)
2663c2630c9philip		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%.*s)", device,
2664c2630c9philip		    pcap_statustostr(status), PCAP_ERRBUF_SIZE - 6, p->errbuf);
2665d8d18f6rpaulo	else
266694960e5delphij		pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device,
2667d8d18f6rpaulo		    pcap_statustostr(status));
2668d8d18f6rpaulo	pcap_close(p);
2669d8d18f6rpaulo	return (NULL);
2670d8d18f6rpaulo}
2671d8d18f6rpaulo
2672489abeddelphijpcap_t *
2673489abeddelphijpcap_open_offline_common(char *ebuf, size_t size)
2674489abeddelphij{
2675489abeddelphij	pcap_t *p;
2676489abeddelphij
2677489abeddelphij	p = pcap_alloc_pcap_t(ebuf, size);
2678489abeddelphij	if (p == NULL)
2679489abeddelphij		return (NULL);
2680489abeddelphij
2681489abeddelphij	p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
2682489abeddelphij
2683489abeddelphij	return (p);
2684489abeddelphij}
2685489abeddelphij
2686d8d18f6rpauloint
2687d8d18f6rpaulopcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
2688d8d18f6rpaulo{
2689c5b3ac4gnn	return (p->read_op(p, cnt, callback, user));
2690da13a5abms}
2691da13a5abms
2692f0fdf33pstint
2693f0fdf33pstpcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
2694f0fdf33pst{
2695ca0d84cfenner	register int n;
2696ca0d84cfenner
2697f0fdf33pst	for (;;) {
2698489abeddelphij		if (p->rfile != NULL) {
2699da13a5abms			/*
2700da13a5abms			 * 0 means EOF, so don't loop if we get 0.
2701da13a5abms			 */
2702ca0d84cfenner			n = pcap_offline_read(p, cnt, callback, user);
2703da13a5abms		} else {
2704ca0d84cfenner			/*
2705ca0d84cfenner			 * XXX keep reading until we get something
2706ca0d84cfenner			 * (or an error occurs)
2707ca0d84cfenner			 */
2708ca0d84cfenner			do {
2709da13a5abms				n = p->read_op(p, cnt, callback, user);
2710ca0d84cfenner			} while (n == 0);
2711ca0d84cfenner		}
2712f0fdf33pst		if (n <= 0)
2713f0fdf33pst			return (n);
2714489abeddelphij		if (!PACKET_COUNT_IS_UNLIMITED(cnt)) {
2715f0fdf33pst			cnt -= n;
2716f0fdf33pst			if (cnt <= 0)
2717f0fdf33pst				return (0);
2718f0fdf33pst		}
2719f0fdf33pst	}
2720f0fdf33pst}
2721f0fdf33pst
2722da13a5abms/*
2723da13a5abms * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate.
2724da13a5abms */
2725da13a5abmsvoid
2726da13a5abmspcap_breakloop(pcap_t *p)
2727da13a5abms{
2728da13a5abms	p->break_loop = 1;
2729da13a5abms}
2730da13a5abms
2731f0fdf33pstint
2732f0fdf33pstpcap_datalink(pcap_t *p)
2733f0fdf33pst{
2734489abeddelphij	if (!p->activated)
2735489abeddelphij		return (PCAP_ERROR_NOT_ACTIVATED);
2736f0fdf33pst	return (p->linktype);
2737f0fdf33pst}
2738f0fdf33pst
2739f0fdf33pstint
2740d8d18f6rpaulopcap_datalink_ext(pcap_t *p)
2741d8d18f6rpaulo{
2742489abeddelphij	if (!p->activated)
2743489abeddelphij		return (PCAP_ERROR_NOT_ACTIVATED);
2744d8d18f6rpaulo	return (p->linktype_ext);
2745d8d18f6rpaulo}
2746d8d18f6rpaulo
2747d8d18f6rpauloint
274834111fdfennerpcap_list_datalinks(pcap_t *p, int **dlt_buffer)
274934111fdfenner{
2750489abeddelphij	if (!p->activated)
2751489abeddelphij		return (PCAP_ERROR_NOT_ACTIVATED);
2752da13a5abms	if (p->dlt_count == 0) {
2753da13a5abms		/*
2754da13a5abms		 * We couldn't fetch the list of DLTs, which means
2755da13a5abms		 * this platform doesn't support changing the
2756da13a5abms		 * DLT for an interface.  Return a list of DLTs
2757da13a5abms		 * containing only the DLT this device supports.
2758da13a5abms		 */
2759da13a5abms		*dlt_buffer = (int*)malloc(sizeof(**dlt_buffer));
2760da13a5abms		if (*dlt_buffer == NULL) {
276119bb0b8hselasky			pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
276219bb0b8hselasky			    errno, "malloc");
2763489abeddelphij			return (PCAP_ERROR);
2764da13a5abms		}
2765da13a5abms		**dlt_buffer = p->linktype;
2766da13a5abms		return (1);
2767da13a5abms	} else {
27684462427mlaier		*dlt_buffer = (int*)calloc(sizeof(**dlt_buffer), p->dlt_count);
2769da13a5abms		if (*dlt_buffer == NULL) {
277019bb0b8hselasky			pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
277119bb0b8hselasky			    errno, "malloc");
2772489abeddelphij			return (PCAP_ERROR);
2773da13a5abms		}
2774da13a5abms		(void)memcpy(*dlt_buffer, p->dlt_list,
2775da13a5abms		    sizeof(**dlt_buffer) * p->dlt_count);
2776da13a5abms		return (p->dlt_count);
277734111fdfenner	}
2778da13a5abms}
2779da13a5abms
2780d8d18f6rpaulo/*
2781d8d18f6rpaulo * In Windows, you might have a library built with one version of the
2782d8d18f6rpaulo * C runtime library and an application built with another version of
2783d8d18f6rpaulo * the C runtime library, which means that the library might use one
2784d8d18f6rpaulo * version of malloc() and free() and the application might use another
2785d8d18f6rpaulo * version of malloc() and free().  If so, that means something
2786d8d18f6rpaulo * allocated by the library cannot be freed by the application, so we
2787d8d18f6rpaulo * need to have a pcap_free_datalinks() routine to free up the list
2788d8d18f6rpaulo * allocated by pcap_list_datalinks(), even though it's just a wrapper
2789d8d18f6rpaulo * around free().
2790d8d18f6rpaulo */
2791d8d18f6rpaulovoid
2792d8d18f6rpaulopcap_free_datalinks(int *dlt_list)
2793d8d18f6rpaulo{
2794d8d18f6rpaulo	free(dlt_list);
2795d8d18f6rpaulo}
2796d8d18f6rpaulo
2797da13a5abmsint
2798da13a5abmspcap_set_datalink(pcap_t *p, int dlt)
2799da13a5abms{
2800da13a5abms	int i;
2801da13a5abms	const char *dlt_name;
2802da13a5abms
280394960e5delphij	if (dlt < 0)
280494960e5delphij		goto unsupported;
280594960e5delphij
2806da13a5abms	if (p->dlt_count == 0 || p->set_datalink_op == NULL) {
2807da13a5abms		/*
2808da13a5abms		 * We couldn't fetch the list of DLTs, or we don't
2809da13a5abms		 * have a "set datalink" operation, which means
2810da13a5abms		 * this platform doesn't support changing the
2811da13a5abms		 * DLT for an interface.  Check whether the new
2812da13a5abms		 * DLT is the one this interface supports.
2813da13a5abms		 */
2814da13a5abms		if (p->linktype != dlt)
2815da13a5abms			goto unsupported;
2816da13a5abms
2817da13a5abms		/*
2818da13a5abms		 * It is, so there's nothing we need to do here.
2819da13a5abms		 */
2820da13a5abms		return (0);
2821da13a5abms	}
2822da13a5abms	for (i = 0; i < p->dlt_count; i++)
282394960e5delphij		if (p->dlt_list[i] == (u_int)dlt)
2824da13a5abms			break;
2825da13a5abms	if (i >= p->dlt_count)
2826da13a5abms		goto unsupported;
282770f7ae4sam	if (p->dlt_count == 2 && p->dlt_list[0] == DLT_EN10MB &&
282870f7ae4sam	    dlt == DLT_DOCSIS) {
282970f7ae4sam		/*
283070f7ae4sam		 * This is presumably an Ethernet device, as the first
283170f7ae4sam		 * link-layer type it offers is DLT_EN10MB, and the only
283270f7ae4sam		 * other type it offers is DLT_DOCSIS.  That means that
283370f7ae4sam		 * we can't tell the driver to supply DOCSIS link-layer
283470f7ae4sam		 * headers - we're just pretending that's what we're
283570f7ae4sam		 * getting, as, presumably, we're capturing on a dedicated
283670f7ae4sam		 * link to a Cisco Cable Modem Termination System, and
283770f7ae4sam		 * it's putting raw DOCSIS frames on the wire inside low-level
283870f7ae4sam		 * Ethernet framing.
283970f7ae4sam		 */
284070f7ae4sam		p->linktype = dlt;
284170f7ae4sam		return (0);
284270f7ae4sam	}
2843da13a5abms	if (p->set_datalink_op(p, dlt) == -1)
2844da13a5abms		return (-1);
2845da13a5abms	p->linktype = dlt;
2846da13a5abms	return (0);
2847da13a5abms
2848da13a5abmsunsupported:
2849da13a5abms	dlt_name = pcap_datalink_val_to_name(dlt);
2850da13a5abms	if (dlt_name != NULL) {
285194960e5delphij		(void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
2852da13a5abms		    "%s is not one of the DLTs supported by this device",
2853da13a5abms		    dlt_name);
2854da13a5abms	} else {
285594960e5delphij		(void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
2856da13a5abms		    "DLT %d is not one of the DLTs supported by this device",
2857da13a5abms		    dlt);
2858da13a5abms	}
2859da13a5abms	return (-1);
2860da13a5abms}
2861da13a5abms
2862c5b3ac4gnn/*
2863c5b3ac4gnn * This array is designed for mapping upper and lower case letter
2864c5b3ac4gnn * together for a case independent comparison.  The mappings are
2865c5b3ac4gnn * based upon ascii character sequences.
2866c5b3ac4gnn */
2867c5b3ac4gnnstatic const u_char charmap[] = {
2868c5b3ac4gnn	(u_char)'\000', (u_char)'\001', (u_char)'\002', (u_char)'\003',
2869c5b3ac4gnn	(u_char)'\004', (u_char)'\005', (u_char)'\006', (u_char)'\007',
2870c5b3ac4gnn	(u_char)'\010', (u_char)'\011', (u_char)'\012', (u_char)'\013',
2871c5b3ac4gnn	(u_char)'\014', (u_char)'\015', (u_char)'\016', (u_char)'\017',
2872c5b3ac4gnn	(u_char)'\020', (u_char)'\021', (u_char)'\022', (u_char)'\023',
2873c5b3ac4gnn	(u_char)'\024', (u_char)'\025', (u_char)'\026', (u_char)'\027',
2874c5b3ac4gnn	(u_char)'\030', (u_char)'\031', (u_char)'\032', (u_char)'\033',
2875c5b3ac4gnn	(u_char)'\034', (u_char)'\035', (u_char)'\036', (u_char)'\037',
2876c5b3ac4gnn	(u_char)'\040', (u_char)'\041', (u_char)'\042', (u_char)'\043',
2877c5b3ac4gnn	(u_char)'\044', (u_char)'\045', (u_char)'\046', (u_char)'\047',
2878c5b3ac4gnn	(u_char)'\050', (u_char)'\051', (u_char)'\052', (u_char)'\053',
2879c5b3ac4gnn	(u_char)'\054', (u_char)'\055', (u_char)'\056', (u_char)'\057',
2880c5b3ac4gnn	(u_char)'\060', (u_char)'\061', (u_char)'\062', (u_char)'\063',
2881c5b3ac4gnn	(u_char)'\064', (u_char)'\065', (u_char)'\066', (u_char)'\067',
2882c5b3ac4gnn	(u_char)'\070', (u_char)'\071', (u_char)'\072', (u_char)'\073',
2883c5b3ac4gnn	(u_char)'\074', (u_char)'\075', (u_char)'\076', (u_char)'\077',
2884c5b3ac4gnn	(u_char)'\100', (u_char)'\141', (u_char)'\142', (u_char)'\143',
2885c5b3ac4gnn	(u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
2886c5b3ac4gnn	(u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
2887c5b3ac4gnn	(u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
2888c5b3ac4gnn	(u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
2889c5b3ac4gnn	(u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
2890c5b3ac4gnn	(u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\133',
2891c5b3ac4gnn	(u_char)'\134', (u_char)'\135', (u_char)'\136', (u_char)'\137',
2892c5b3ac4gnn	(u_char)'\140', (u_char)'\141', (u_char)'\142', (u_char)'\143',
2893c5b3ac4gnn	(u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
2894c5b3ac4gnn	(u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
2895c5b3ac4gnn	(u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
2896c5b3ac4gnn	(u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
2897c5b3ac4gnn	(u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
2898c5b3ac4gnn	(u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\173',
2899c5b3ac4gnn	(u_char)'\174', (u_char)'\175', (u_char)'\176', (u_char)'\177',
2900c5b3ac4gnn	(u_char)'\200', (u_char)'\201', (u_char)'\202', (u_char)'\203',
2901c5b3ac4gnn	(u_char)'\204', (u_char)'\205', (u_char)'\206', (u_char)'\207',
2902c5b3ac4gnn	(u_char)'\210', (u_char)'\211', (u_char)'\212', (u_char)'\213',
2903c5b3ac4gnn	(u_char)'\214', (u_char)'\215', (u_char)'\216', (u_char)'\217',
2904c5b3ac4gnn	(u_char)'\220', (u_char)'\221', (u_char)'\222', (u_char)'\223',
2905c5b3ac4gnn	(u_char)'\224', (u_char)'\225', (u_char)'\226', (u_char)'\227',
2906c5b3ac4gnn	(u_char)'\230', (u_char)'\231', (u_char)'\232', (u_char)'\233',
2907c5b3ac4gnn	(u_char)'\234', (u_char)'\235', (u_char)'\236', (u_char)'\237',
2908c5b3ac4gnn	(u_char)'\240', (u_char)'\241', (u_char)'\242', (u_char)'\243',
2909c5b3ac4gnn	(u_char)'\244', (u_char)'\245', (u_char)'\246', (u_char)'\247',
2910c5b3ac4gnn	(u_char)'\250', (u_char)'\251', (