117683Spst/*
239291Sfenner * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
317683Spst *	The Regents of the University of California.  All rights reserved.
417683Spst *
517683Spst * Redistribution and use in source and binary forms, with or without
617683Spst * modification, are permitted provided that the following conditions
717683Spst * are met:
817683Spst * 1. Redistributions of source code must retain the above copyright
917683Spst *    notice, this list of conditions and the following disclaimer.
1017683Spst * 2. Redistributions in binary form must reproduce the above copyright
1117683Spst *    notice, this list of conditions and the following disclaimer in the
1217683Spst *    documentation and/or other materials provided with the distribution.
1317683Spst * 3. All advertising materials mentioning features or use of this software
1417683Spst *    must display the following acknowledgement:
1517683Spst *	This product includes software developed by the Computer Systems
1617683Spst *	Engineering Group at Lawrence Berkeley Laboratory.
1717683Spst * 4. Neither the name of the University nor of the Laboratory may be used
1817683Spst *    to endorse or promote products derived from this software without
1917683Spst *    specific prior written permission.
2017683Spst *
2117683Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2217683Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2317683Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2417683Spst * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2517683Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2617683Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2717683Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2817683Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2917683Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3017683Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3117683Spst * SUCH DAMAGE.
3217683Spst */
3317683Spst
3417683Spst#ifndef lint
35127664Sbmsstatic const char rcsid[] _U_ =
36214518Srpaulo    "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.128 2008-12-23 20:13:29 guy Exp $ (LBL)";
3717683Spst#endif
3817683Spst
3975107Sfenner#ifdef HAVE_CONFIG_H
4075107Sfenner#include "config.h"
4175107Sfenner#endif
4275107Sfenner
43127664Sbms#ifdef WIN32
44127664Sbms#include <pcap-stdinc.h>
45127664Sbms#else /* WIN32 */
46214518Srpaulo#if HAVE_INTTYPES_H
47214518Srpaulo#include <inttypes.h>
48214518Srpaulo#elif HAVE_STDINT_H
49214518Srpaulo#include <stdint.h>
50214518Srpaulo#endif
51214518Srpaulo#ifdef HAVE_SYS_BITYPES_H
52214518Srpaulo#include <sys/bitypes.h>
53214518Srpaulo#endif
5417683Spst#include <sys/types.h>
55183102Scsjp#include <sys/mman.h>
56127664Sbms#endif /* WIN32 */
5717683Spst
5817683Spst#include <stdio.h>
5917683Spst#include <stdlib.h>
6017683Spst#include <string.h>
61235426Sdelphij#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__MINGW32__)
6217683Spst#include <unistd.h>
63127664Sbms#endif
6498530Sfenner#include <fcntl.h>
6598530Sfenner#include <errno.h>
6617683Spst
6717683Spst#ifdef HAVE_OS_PROTO_H
6817683Spst#include "os-proto.h"
6917683Spst#endif
7017683Spst
71146768Ssam#ifdef MSDOS
72146768Ssam#include "pcap-dos.h"
73146768Ssam#endif
74146768Ssam
7517683Spst#include "pcap-int.h"
7617683Spst
77127664Sbms#ifdef HAVE_DAG_API
78251129Sdelphij#include "pcap-dag.h"
79251129Sdelphij#endif /* HAVE_DAG_API */
80251129Sdelphij
81251129Sdelphij#ifdef HAVE_SEPTEL_API
82251129Sdelphij#include "pcap-septel.h"
83251129Sdelphij#endif /* HAVE_SEPTEL_API */
84251129Sdelphij
85251129Sdelphij#ifdef HAVE_SNF_API
86251129Sdelphij#include "pcap-snf.h"
87251129Sdelphij#endif /* HAVE_SNF_API */
88251129Sdelphij
89251129Sdelphij#ifdef PCAP_SUPPORT_USB
90251129Sdelphij#include "pcap-usb-linux.h"
91127664Sbms#endif
92127664Sbms
93251129Sdelphij#ifdef PCAP_SUPPORT_BT
94251129Sdelphij#include "pcap-bt-linux.h"
95251129Sdelphij#endif
96251129Sdelphij
97251129Sdelphij#ifdef PCAP_SUPPORT_CAN
98251129Sdelphij#include "pcap-can-linux.h"
99251129Sdelphij#endif
100251129Sdelphij
101251129Sdelphij#ifdef PCAP_SUPPORT_CANUSB
102251129Sdelphij#include "pcap-canusb-linux.h"
103251129Sdelphij#endif
104251129Sdelphij
105251129Sdelphij#ifdef PCAP_SUPPORT_NETFILTER
106251129Sdelphij#include "pcap-netfilter-linux.h"
107251129Sdelphij#endif
108251129Sdelphij
109190225Srpauloint
110190225Srpaulopcap_not_initialized(pcap_t *pcap)
111190225Srpaulo{
112190225Srpaulo	/* this means 'not initialized' */
113235426Sdelphij	return (PCAP_ERROR_NOT_ACTIVATED);
114190225Srpaulo}
115190225Srpaulo
116190225Srpaulo/*
117190225Srpaulo * Returns 1 if rfmon mode can be set on the pcap_t, 0 if it can't,
118190225Srpaulo * a PCAP_ERROR value on an error.
119190225Srpaulo */
12017683Spstint
121190225Srpaulopcap_can_set_rfmon(pcap_t *p)
122190225Srpaulo{
123190225Srpaulo	return (p->can_set_rfmon_op(p));
124190225Srpaulo}
125190225Srpaulo
126190225Srpaulo/*
127190225Srpaulo * For systems where rfmon mode is never supported.
128190225Srpaulo */
129190225Srpaulostatic int
130190225Srpaulopcap_cant_set_rfmon(pcap_t *p _U_)
131190225Srpaulo{
132190225Srpaulo	return (0);
133190225Srpaulo}
134190225Srpaulo
135214518Srpaulo/*
136235426Sdelphij * Sets *tstamp_typesp to point to an array 1 or more supported time stamp
137235426Sdelphij * types; the return value is the number of supported time stamp types.
138235426Sdelphij * The list should be freed by a call to pcap_free_tstamp_types() when
139235426Sdelphij * you're done with it.
140235426Sdelphij *
141235426Sdelphij * A return value of 0 means "you don't get a choice of time stamp type",
142235426Sdelphij * in which case *tstamp_typesp is set to null.
143235426Sdelphij *
144235426Sdelphij * PCAP_ERROR is returned on error.
145235426Sdelphij */
146235426Sdelphijint
147235426Sdelphijpcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp)
148235426Sdelphij{
149235426Sdelphij	if (p->tstamp_type_count == 0) {
150235426Sdelphij		/*
151235426Sdelphij		 * We don't support multiple time stamp types.
152235426Sdelphij		 */
153235426Sdelphij		*tstamp_typesp = NULL;
154235426Sdelphij	} else {
155235426Sdelphij		*tstamp_typesp = (int*)calloc(sizeof(**tstamp_typesp),
156235426Sdelphij		    p->tstamp_type_count);
157235426Sdelphij		if (*tstamp_typesp == NULL) {
158235426Sdelphij			(void)snprintf(p->errbuf, sizeof(p->errbuf),
159235426Sdelphij			    "malloc: %s", pcap_strerror(errno));
160235426Sdelphij			return (PCAP_ERROR);
161235426Sdelphij		}
162235426Sdelphij		(void)memcpy(*tstamp_typesp, p->tstamp_type_list,
163235426Sdelphij		    sizeof(**tstamp_typesp) * p->tstamp_type_count);
164235426Sdelphij	}
165235426Sdelphij	return (p->tstamp_type_count);
166235426Sdelphij}
167235426Sdelphij
168235426Sdelphij/*
169235426Sdelphij * In Windows, you might have a library built with one version of the
170235426Sdelphij * C runtime library and an application built with another version of
171235426Sdelphij * the C runtime library, which means that the library might use one
172235426Sdelphij * version of malloc() and free() and the application might use another
173235426Sdelphij * version of malloc() and free().  If so, that means something
174235426Sdelphij * allocated by the library cannot be freed by the application, so we
175235426Sdelphij * need to have a pcap_free_tstamp_types() routine to free up the list
176235426Sdelphij * allocated by pcap_list_tstamp_types(), even though it's just a wrapper
177235426Sdelphij * around free().
178235426Sdelphij */
179235426Sdelphijvoid
180235426Sdelphijpcap_free_tstamp_types(int *tstamp_type_list)
181235426Sdelphij{
182235426Sdelphij	free(tstamp_type_list);
183235426Sdelphij}
184235426Sdelphij
185235426Sdelphij/*
186214518Srpaulo * Default one-shot callback; overridden for capture types where the
187214518Srpaulo * packet data cannot be guaranteed to be available after the callback
188214518Srpaulo * returns, so that a copy must be made.
189214518Srpaulo */
190214518Srpaulostatic void
191214518Srpaulopcap_oneshot(u_char *user, const struct pcap_pkthdr *h, const u_char *pkt)
192214518Srpaulo{
193214518Srpaulo	struct oneshot_userdata *sp = (struct oneshot_userdata *)user;
194214518Srpaulo
195214518Srpaulo	*sp->hdr = *h;
196214518Srpaulo	*sp->pkt = pkt;
197214518Srpaulo}
198214518Srpaulo
199214518Srpauloconst u_char *
200214518Srpaulopcap_next(pcap_t *p, struct pcap_pkthdr *h)
201214518Srpaulo{
202214518Srpaulo	struct oneshot_userdata s;
203214518Srpaulo	const u_char *pkt;
204214518Srpaulo
205214518Srpaulo	s.hdr = h;
206214518Srpaulo	s.pkt = &pkt;
207214518Srpaulo	s.pd = p;
208214518Srpaulo	if (pcap_dispatch(p, 1, p->oneshot_callback, (u_char *)&s) <= 0)
209214518Srpaulo		return (0);
210214518Srpaulo	return (pkt);
211214518Srpaulo}
212214518Srpaulo
213214518Srpauloint
214214518Srpaulopcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
215214518Srpaulo    const u_char **pkt_data)
216214518Srpaulo{
217214518Srpaulo	struct oneshot_userdata s;
218214518Srpaulo
219214518Srpaulo	s.hdr = &p->pcap_header;
220214518Srpaulo	s.pkt = pkt_data;
221214518Srpaulo	s.pd = p;
222214518Srpaulo
223214518Srpaulo	/* Saves a pointer to the packet headers */
224214518Srpaulo	*pkt_header= &p->pcap_header;
225214518Srpaulo
226214518Srpaulo	if (p->sf.rfile != NULL) {
227214518Srpaulo		int status;
228214518Srpaulo
229214518Srpaulo		/* We are on an offline capture */
230235426Sdelphij		status = pcap_offline_read(p, 1, p->oneshot_callback,
231235426Sdelphij		    (u_char *)&s);
232214518Srpaulo
233214518Srpaulo		/*
234214518Srpaulo		 * Return codes for pcap_offline_read() are:
235214518Srpaulo		 *   -  0: EOF
236214518Srpaulo		 *   - -1: error
237214518Srpaulo		 *   - >1: OK
238214518Srpaulo		 * The first one ('0') conflicts with the return code of
239214518Srpaulo		 * 0 from pcap_read() meaning "no packets arrived before
240214518Srpaulo		 * the timeout expired", so we map it to -2 so you can
241214518Srpaulo		 * distinguish between an EOF from a savefile and a
242214518Srpaulo		 * "no packets arrived before the timeout expired, try
243214518Srpaulo		 * again" from a live capture.
244214518Srpaulo		 */
245214518Srpaulo		if (status == 0)
246214518Srpaulo			return (-2);
247214518Srpaulo		else
248214518Srpaulo			return (status);
249214518Srpaulo	}
250214518Srpaulo
251214518Srpaulo	/*
252214518Srpaulo	 * Return codes for pcap_read() are:
253214518Srpaulo	 *   -  0: timeout
254214518Srpaulo	 *   - -1: error
255214518Srpaulo	 *   - -2: loop was broken out of with pcap_breakloop()
256214518Srpaulo	 *   - >1: OK
257214518Srpaulo	 * The first one ('0') conflicts with the return code of 0 from
258214518Srpaulo	 * pcap_offline_read() meaning "end of file".
259214518Srpaulo	*/
260235426Sdelphij	return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s));
261214518Srpaulo}
262214518Srpaulo
263251129Sdelphij#if defined(DAG_ONLY)
264251129Sdelphijint
265251129Sdelphijpcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
266251129Sdelphij{
267251129Sdelphij	return (dag_findalldevs(alldevsp, errbuf));
268251129Sdelphij}
269251129Sdelphij
270251129Sdelphijpcap_t *
271251129Sdelphijpcap_create(const char *source, char *errbuf)
272251129Sdelphij{
273251129Sdelphij	return (dag_create(source, errbuf));
274251129Sdelphij}
275251129Sdelphij#elif defined(SEPTEL_ONLY)
276251129Sdelphijint
277251129Sdelphijpcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
278251129Sdelphij{
279251129Sdelphij	return (septel_findalldevs(alldevsp, errbuf));
280251129Sdelphij}
281251129Sdelphij
282251129Sdelphijpcap_t *
283251129Sdelphijpcap_create(const char *source, char *errbuf)
284251129Sdelphij{
285251129Sdelphij	return (septel_create(source, errbuf));
286251129Sdelphij}
287251129Sdelphij#elif defined(SNF_ONLY)
288251129Sdelphijint
289251129Sdelphijpcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
290251129Sdelphij{
291251129Sdelphij	return (snf_findalldevs(alldevsp, errbuf));
292251129Sdelphij}
293251129Sdelphij
294251129Sdelphijpcap_t *
295251129Sdelphijpcap_create(const char *source, char *errbuf)
296251129Sdelphij{
297251129Sdelphij	return (snf_create(source, errbuf));
298251129Sdelphij}
299251129Sdelphij#else /* regular pcap */
300251129Sdelphijstruct capture_source_type {
301251129Sdelphij	int (*findalldevs_op)(pcap_if_t **, char *);
302251129Sdelphij	pcap_t *(*create_op)(const char *, char *, int *);
303251129Sdelphij} capture_source_types[] = {
304251129Sdelphij#ifdef HAVE_DAG_API
305251129Sdelphij	{ dag_findalldevs, dag_create },
306251129Sdelphij#endif
307251129Sdelphij#ifdef HAVE_SEPTEL_API
308251129Sdelphij	{ septel_findalldevs, septel_create },
309251129Sdelphij#endif
310251129Sdelphij#ifdef HAVE_SNF_API
311251129Sdelphij	{ snf_findalldevs, snf_create },
312251129Sdelphij#endif
313251129Sdelphij#ifdef PCAP_SUPPORT_BT
314251129Sdelphij	{ bt_findalldevs, bt_create },
315251129Sdelphij#endif
316251129Sdelphij#if PCAP_SUPPORT_CANUSB
317251129Sdelphij	{ canusb_findalldevs, canusb_create },
318251129Sdelphij#endif
319251129Sdelphij#ifdef PCAP_SUPPORT_CAN
320251129Sdelphij	{ can_findalldevs, can_create },
321251129Sdelphij#endif
322251129Sdelphij#ifdef PCAP_SUPPORT_USB
323251129Sdelphij	{ usb_findalldevs, usb_create },
324251129Sdelphij#endif
325251129Sdelphij#ifdef PCAP_SUPPORT_NETFILTER
326251129Sdelphij	{ netfilter_findalldevs, netfilter_create },
327251129Sdelphij#endif
328251129Sdelphij	{ NULL, NULL }
329251129Sdelphij};
330251129Sdelphij
331251129Sdelphij/*
332251129Sdelphij * Get a list of all capture sources that are up and that we can open.
333251129Sdelphij * Returns -1 on error, 0 otherwise.
334251129Sdelphij * The list, as returned through "alldevsp", may be null if no interfaces
335251129Sdelphij * were up and could be opened.
336251129Sdelphij */
337251129Sdelphijint
338251129Sdelphijpcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
339251129Sdelphij{
340251129Sdelphij	size_t i;
341251129Sdelphij
342251129Sdelphij	/*
343251129Sdelphij	 * Get the list of regular interfaces first.
344251129Sdelphij	 */
345251129Sdelphij	if (pcap_findalldevs_interfaces(alldevsp, errbuf) == -1)
346251129Sdelphij		return (-1);	/* failure */
347251129Sdelphij
348251129Sdelphij	/*
349251129Sdelphij	 * Add any interfaces that need a platform-specific mechanism
350251129Sdelphij	 * to find.
351251129Sdelphij	 */
352251129Sdelphij	if (pcap_platform_finddevs(alldevsp, errbuf) == -1) {
353251129Sdelphij		/*
354251129Sdelphij		 * We had an error; free the list we've been
355251129Sdelphij		 * constructing.
356251129Sdelphij		 */
357251129Sdelphij		if (*alldevsp != NULL) {
358251129Sdelphij			pcap_freealldevs(*alldevsp);
359251129Sdelphij			*alldevsp = NULL;
360251129Sdelphij		}
361251129Sdelphij		return (-1);
362251129Sdelphij	}
363251129Sdelphij
364251129Sdelphij	/*
365251129Sdelphij	 * Ask each of the non-local-network-interface capture
366251129Sdelphij	 * source types what interfaces they have.
367251129Sdelphij	 */
368251129Sdelphij	for (i = 0; capture_source_types[i].findalldevs_op != NULL; i++) {
369251129Sdelphij		if (capture_source_types[i].findalldevs_op(alldevsp, errbuf) == -1) {
370251129Sdelphij			/*
371251129Sdelphij			 * We had an error; free the list we've been
372251129Sdelphij			 * constructing.
373251129Sdelphij			 */
374251129Sdelphij			if (*alldevsp != NULL) {
375251129Sdelphij				pcap_freealldevs(*alldevsp);
376251129Sdelphij				*alldevsp = NULL;
377251129Sdelphij			}
378251129Sdelphij			return (-1);
379251129Sdelphij		}
380251129Sdelphij	}
381251129Sdelphij	return (0);
382251129Sdelphij}
383251129Sdelphij
384251129Sdelphijpcap_t *
385251129Sdelphijpcap_create(const char *source, char *errbuf)
386251129Sdelphij{
387251129Sdelphij	size_t i;
388251129Sdelphij	int is_theirs;
389251129Sdelphij	pcap_t *p;
390251129Sdelphij
391251129Sdelphij	/*
392251129Sdelphij	 * A null source name is equivalent to the "any" device -
393251129Sdelphij	 * which might not be supported on this platform, but
394251129Sdelphij	 * this means that you'll get a "not supported" error
395251129Sdelphij	 * rather than, say, a crash when we try to dereference
396251129Sdelphij	 * the null pointer.
397251129Sdelphij	 */
398251129Sdelphij	if (source == NULL)
399251129Sdelphij		source = "any";
400251129Sdelphij
401251129Sdelphij	/*
402251129Sdelphij	 * Try each of the non-local-network-interface capture
403251129Sdelphij	 * source types until we find one that works for this
404251129Sdelphij	 * device or run out of types.
405251129Sdelphij	 */
406251129Sdelphij	for (i = 0; capture_source_types[i].create_op != NULL; i++) {
407251129Sdelphij		is_theirs = 0;
408251129Sdelphij		p = capture_source_types[i].create_op(source, errbuf, &is_theirs);
409251129Sdelphij		if (is_theirs) {
410251129Sdelphij			/*
411251129Sdelphij			 * The device name refers to a device of the
412251129Sdelphij			 * type in question; either it succeeded,
413251129Sdelphij			 * in which case p refers to a pcap_t to
414251129Sdelphij			 * later activate for the device, or it
415251129Sdelphij			 * failed, in which case p is null and we
416251129Sdelphij			 * should return that to report the failure
417251129Sdelphij			 * to create.
418251129Sdelphij			 */
419251129Sdelphij			return (p);
420251129Sdelphij		}
421251129Sdelphij	}
422251129Sdelphij
423251129Sdelphij	/*
424251129Sdelphij	 * OK, try it as a regular network interface.
425251129Sdelphij	 */
426251129Sdelphij	return (pcap_create_interface(source, errbuf));
427251129Sdelphij}
428251129Sdelphij#endif
429251129Sdelphij
430214518Srpaulostatic void
431214518Srpauloinitialize_ops(pcap_t *p)
432214518Srpaulo{
433214518Srpaulo	/*
434214518Srpaulo	 * Set operation pointers for operations that only work on
435214518Srpaulo	 * an activated pcap_t to point to a routine that returns
436214518Srpaulo	 * a "this isn't activated" error.
437214518Srpaulo	 */
438214518Srpaulo	p->read_op = (read_op_t)pcap_not_initialized;
439214518Srpaulo	p->inject_op = (inject_op_t)pcap_not_initialized;
440214518Srpaulo	p->setfilter_op = (setfilter_op_t)pcap_not_initialized;
441214518Srpaulo	p->setdirection_op = (setdirection_op_t)pcap_not_initialized;
442214518Srpaulo	p->set_datalink_op = (set_datalink_op_t)pcap_not_initialized;
443214518Srpaulo	p->getnonblock_op = (getnonblock_op_t)pcap_not_initialized;
444214518Srpaulo	p->setnonblock_op = (setnonblock_op_t)pcap_not_initialized;
445214518Srpaulo	p->stats_op = (stats_op_t)pcap_not_initialized;
446214518Srpaulo#ifdef WIN32
447214518Srpaulo	p->setbuff_op = (setbuff_op_t)pcap_not_initialized;
448214518Srpaulo	p->setmode_op = (setmode_op_t)pcap_not_initialized;
449214518Srpaulo	p->setmintocopy_op = (setmintocopy_op_t)pcap_not_initialized;
450214518Srpaulo#endif
451214518Srpaulo
452214518Srpaulo	/*
453214518Srpaulo	 * Default cleanup operation - implementations can override
454214518Srpaulo	 * this, but should call pcap_cleanup_live_common() after
455214518Srpaulo	 * doing their own additional cleanup.
456214518Srpaulo	 */
457214518Srpaulo	p->cleanup_op = pcap_cleanup_live_common;
458214518Srpaulo
459214518Srpaulo	/*
460214518Srpaulo	 * In most cases, the standard one-short callback can
461214518Srpaulo	 * be used for pcap_next()/pcap_next_ex().
462214518Srpaulo	 */
463214518Srpaulo	p->oneshot_callback = pcap_oneshot;
464214518Srpaulo}
465214518Srpaulo
466190225Srpaulopcap_t *
467190225Srpaulopcap_create_common(const char *source, char *ebuf)
468190225Srpaulo{
469190225Srpaulo	pcap_t *p;
470190225Srpaulo
471190225Srpaulo	p = malloc(sizeof(*p));
472190225Srpaulo	if (p == NULL) {
473190225Srpaulo		snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
474190225Srpaulo		    pcap_strerror(errno));
475190225Srpaulo		return (NULL);
476190225Srpaulo	}
477190225Srpaulo	memset(p, 0, sizeof(*p));
478190225Srpaulo#ifndef WIN32
479190225Srpaulo	p->fd = -1;	/* not opened yet */
480214518Srpaulo	p->selectable_fd = -1;
481214518Srpaulo	p->send_fd = -1;
482190225Srpaulo#endif
483190225Srpaulo
484190225Srpaulo	p->opt.source = strdup(source);
485190225Srpaulo	if (p->opt.source == NULL) {
486190225Srpaulo		snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s",
487190225Srpaulo		    pcap_strerror(errno));
488190225Srpaulo		free(p);
489190225Srpaulo		return (NULL);
490190225Srpaulo	}
491190225Srpaulo
492190225Srpaulo	/*
493190225Srpaulo	 * Default to "can't set rfmon mode"; if it's supported by
494214518Srpaulo	 * a platform, the create routine that called us can set
495214518Srpaulo	 * the op to its routine to check whether a particular
496214518Srpaulo	 * device supports it.
497190225Srpaulo	 */
498190225Srpaulo	p->can_set_rfmon_op = pcap_cant_set_rfmon;
499190225Srpaulo
500214518Srpaulo	initialize_ops(p);
501190225Srpaulo
502190225Srpaulo	/* put in some defaults*/
503190225Srpaulo	pcap_set_timeout(p, 0);
504190225Srpaulo	pcap_set_snaplen(p, 65535);	/* max packet size */
505190225Srpaulo	p->opt.promisc = 0;
506190225Srpaulo	p->opt.buffer_size = 0;
507235426Sdelphij	p->opt.tstamp_type = -1;	/* default to not setting time stamp type */
508190225Srpaulo	return (p);
509190225Srpaulo}
510190225Srpaulo
511190225Srpauloint
512190225Srpaulopcap_check_activated(pcap_t *p)
513190225Srpaulo{
514190225Srpaulo	if (p->activated) {
515190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
516190225Srpaulo			" operation on activated capture");
517235426Sdelphij		return (-1);
518190225Srpaulo	}
519235426Sdelphij	return (0);
520190225Srpaulo}
521190225Srpaulo
522190225Srpauloint
523190225Srpaulopcap_set_snaplen(pcap_t *p, int snaplen)
524190225Srpaulo{
525190225Srpaulo	if (pcap_check_activated(p))
526235426Sdelphij		return (PCAP_ERROR_ACTIVATED);
527190225Srpaulo	p->snapshot = snaplen;
528235426Sdelphij	return (0);
529190225Srpaulo}
530190225Srpaulo
531190225Srpauloint
532190225Srpaulopcap_set_promisc(pcap_t *p, int promisc)
533190225Srpaulo{
534190225Srpaulo	if (pcap_check_activated(p))
535235426Sdelphij		return (PCAP_ERROR_ACTIVATED);
536190225Srpaulo	p->opt.promisc = promisc;
537235426Sdelphij	return (0);
538190225Srpaulo}
539190225Srpaulo
540190225Srpauloint
541190225Srpaulopcap_set_rfmon(pcap_t *p, int rfmon)
542190225Srpaulo{
543190225Srpaulo	if (pcap_check_activated(p))
544235426Sdelphij		return (PCAP_ERROR_ACTIVATED);
545190225Srpaulo	p->opt.rfmon = rfmon;
546235426Sdelphij	return (0);
547190225Srpaulo}
548190225Srpaulo
549190225Srpauloint
550190225Srpaulopcap_set_timeout(pcap_t *p, int timeout_ms)
551190225Srpaulo{
552190225Srpaulo	if (pcap_check_activated(p))
553235426Sdelphij		return (PCAP_ERROR_ACTIVATED);
554190225Srpaulo	p->md.timeout = timeout_ms;
555235426Sdelphij	return (0);
556190225Srpaulo}
557190225Srpaulo
558190225Srpauloint
559235426Sdelphijpcap_set_tstamp_type(pcap_t *p, int tstamp_type)
560235426Sdelphij{
561235426Sdelphij	int i;
562235426Sdelphij
563235426Sdelphij	if (pcap_check_activated(p))
564235426Sdelphij		return (PCAP_ERROR_ACTIVATED);
565235426Sdelphij
566235426Sdelphij	/*
567235426Sdelphij	 * If p->tstamp_type_count is 0, we don't support setting
568235426Sdelphij	 * the time stamp type at all.
569235426Sdelphij	 */
570235426Sdelphij	if (p->tstamp_type_count == 0)
571235426Sdelphij		return (PCAP_ERROR_CANTSET_TSTAMP_TYPE);
572235426Sdelphij
573235426Sdelphij	/*
574235426Sdelphij	 * Check whether we claim to support this type of time stamp.
575235426Sdelphij	 */
576235426Sdelphij	for (i = 0; i < p->tstamp_type_count; i++) {
577235426Sdelphij		if (p->tstamp_type_list[i] == tstamp_type) {
578235426Sdelphij			/*
579235426Sdelphij			 * Yes.
580235426Sdelphij			 */
581235426Sdelphij			p->opt.tstamp_type = tstamp_type;
582235426Sdelphij			return (0);
583235426Sdelphij		}
584235426Sdelphij	}
585235426Sdelphij
586235426Sdelphij	/*
587235426Sdelphij	 * No.  We support setting the time stamp type, but not to this
588235426Sdelphij	 * particular value.
589235426Sdelphij	 */
590235426Sdelphij	return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
591235426Sdelphij}
592235426Sdelphij
593235426Sdelphijint
594190225Srpaulopcap_set_buffer_size(pcap_t *p, int buffer_size)
595190225Srpaulo{
596190225Srpaulo	if (pcap_check_activated(p))
597235426Sdelphij		return (PCAP_ERROR_ACTIVATED);
598190225Srpaulo	p->opt.buffer_size = buffer_size;
599235426Sdelphij	return (0);
600190225Srpaulo}
601190225Srpaulo
602190225Srpauloint
603190225Srpaulopcap_activate(pcap_t *p)
604190225Srpaulo{
605190225Srpaulo	int status;
606190225Srpaulo
607235426Sdelphij	/*
608235426Sdelphij	 * Catch attempts to re-activate an already-activated
609235426Sdelphij	 * pcap_t; this should, for example, catch code that
610235426Sdelphij	 * calls pcap_open_live() followed by pcap_activate(),
611235426Sdelphij	 * as some code that showed up in a Stack Exchange
612235426Sdelphij	 * question did.
613235426Sdelphij	 */
614235426Sdelphij	if (pcap_check_activated(p))
615235426Sdelphij		return (PCAP_ERROR_ACTIVATED);
616190225Srpaulo	status = p->activate_op(p);
617190225Srpaulo	if (status >= 0)
618190225Srpaulo		p->activated = 1;
619214518Srpaulo	else {
620214518Srpaulo		if (p->errbuf[0] == '\0') {
621214518Srpaulo			/*
622214518Srpaulo			 * No error message supplied by the activate routine;
623214518Srpaulo			 * for the benefit of programs that don't specially
624214518Srpaulo			 * handle errors other than PCAP_ERROR, return the
625214518Srpaulo			 * error message corresponding to the status.
626214518Srpaulo			 */
627214518Srpaulo			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
628214518Srpaulo			    pcap_statustostr(status));
629214518Srpaulo		}
630214518Srpaulo
631214518Srpaulo		/*
632214518Srpaulo		 * Undo any operation pointer setting, etc. done by
633214518Srpaulo		 * the activate operation.
634214518Srpaulo		 */
635214518Srpaulo		initialize_ops(p);
636214518Srpaulo	}
637190225Srpaulo	return (status);
638190225Srpaulo}
639190225Srpaulo
640190225Srpaulopcap_t *
641190225Srpaulopcap_open_live(const char *source, int snaplen, int promisc, int to_ms, char *errbuf)
642190225Srpaulo{
643190225Srpaulo	pcap_t *p;
644190225Srpaulo	int status;
645190225Srpaulo
646190225Srpaulo	p = pcap_create(source, errbuf);
647190225Srpaulo	if (p == NULL)
648190225Srpaulo		return (NULL);
649190225Srpaulo	status = pcap_set_snaplen(p, snaplen);
650190225Srpaulo	if (status < 0)
651190225Srpaulo		goto fail;
652190225Srpaulo	status = pcap_set_promisc(p, promisc);
653190225Srpaulo	if (status < 0)
654190225Srpaulo		goto fail;
655190225Srpaulo	status = pcap_set_timeout(p, to_ms);
656190225Srpaulo	if (status < 0)
657190225Srpaulo		goto fail;
658190225Srpaulo	/*
659190225Srpaulo	 * Mark this as opened with pcap_open_live(), so that, for
660190225Srpaulo	 * example, we show the full list of DLT_ values, rather
661190225Srpaulo	 * than just the ones that are compatible with capturing
662190225Srpaulo	 * when not in monitor mode.  That allows existing applications
663190225Srpaulo	 * to work the way they used to work, but allows new applications
664190225Srpaulo	 * that know about the new open API to, for example, find out the
665190225Srpaulo	 * DLT_ values that they can select without changing whether
666190225Srpaulo	 * the adapter is in monitor mode or not.
667190225Srpaulo	 */
668190225Srpaulo	p->oldstyle = 1;
669190225Srpaulo	status = pcap_activate(p);
670190225Srpaulo	if (status < 0)
671190225Srpaulo		goto fail;
672190225Srpaulo	return (p);
673190225Srpaulofail:
674214518Srpaulo	if (status == PCAP_ERROR)
675214518Srpaulo		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source,
676214518Srpaulo		    p->errbuf);
677214518Srpaulo	else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
678235426Sdelphij	    status == PCAP_ERROR_PERM_DENIED ||
679235426Sdelphij	    status == PCAP_ERROR_PROMISC_PERM_DENIED)
680214518Srpaulo		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)", source,
681214518Srpaulo		    pcap_statustostr(status), p->errbuf);
682190225Srpaulo	else
683190225Srpaulo		snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", source,
684190225Srpaulo		    pcap_statustostr(status));
685190225Srpaulo	pcap_close(p);
686190225Srpaulo	return (NULL);
687190225Srpaulo}
688190225Srpaulo
689190225Srpauloint
69017683Spstpcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
69117683Spst{
692235426Sdelphij	return (p->read_op(p, cnt, callback, user));
69317683Spst}
69417683Spst
695127664Sbms/*
696127664Sbms * XXX - is this necessary?
697127664Sbms */
69817683Spstint
699127664Sbmspcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
700127664Sbms{
701127664Sbms
702235426Sdelphij	return (p->read_op(p, cnt, callback, user));
703127664Sbms}
704127664Sbms
705127664Sbmsint
70617683Spstpcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
70717683Spst{
70839291Sfenner	register int n;
70939291Sfenner
71017683Spst	for (;;) {
711127664Sbms		if (p->sf.rfile != NULL) {
712127664Sbms			/*
713127664Sbms			 * 0 means EOF, so don't loop if we get 0.
714127664Sbms			 */
71539291Sfenner			n = pcap_offline_read(p, cnt, callback, user);
716127664Sbms		} else {
71739291Sfenner			/*
71839291Sfenner			 * XXX keep reading until we get something
71939291Sfenner			 * (or an error occurs)
72039291Sfenner			 */
72139291Sfenner			do {
722127664Sbms				n = p->read_op(p, cnt, callback, user);
72339291Sfenner			} while (n == 0);
72439291Sfenner		}
72517683Spst		if (n <= 0)
72617683Spst			return (n);
72717683Spst		if (cnt > 0) {
72817683Spst			cnt -= n;
72917683Spst			if (cnt <= 0)
73017683Spst				return (0);
73117683Spst		}
73217683Spst	}
73317683Spst}
73417683Spst
735127664Sbms/*
736127664Sbms * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate.
737127664Sbms */
738127664Sbmsvoid
739127664Sbmspcap_breakloop(pcap_t *p)
740127664Sbms{
741127664Sbms	p->break_loop = 1;
742127664Sbms}
743127664Sbms
74417683Spstint
74517683Spstpcap_datalink(pcap_t *p)
74617683Spst{
74717683Spst	return (p->linktype);
74817683Spst}
74917683Spst
75017683Spstint
751190225Srpaulopcap_datalink_ext(pcap_t *p)
752190225Srpaulo{
753190225Srpaulo	return (p->linktype_ext);
754190225Srpaulo}
755190225Srpaulo
756190225Srpauloint
757109839Sfennerpcap_list_datalinks(pcap_t *p, int **dlt_buffer)
758109839Sfenner{
759127664Sbms	if (p->dlt_count == 0) {
760127664Sbms		/*
761127664Sbms		 * We couldn't fetch the list of DLTs, which means
762127664Sbms		 * this platform doesn't support changing the
763127664Sbms		 * DLT for an interface.  Return a list of DLTs
764127664Sbms		 * containing only the DLT this device supports.
765127664Sbms		 */
766127664Sbms		*dlt_buffer = (int*)malloc(sizeof(**dlt_buffer));
767127664Sbms		if (*dlt_buffer == NULL) {
768127664Sbms			(void)snprintf(p->errbuf, sizeof(p->errbuf),
769127664Sbms			    "malloc: %s", pcap_strerror(errno));
770127664Sbms			return (-1);
771127664Sbms		}
772127664Sbms		**dlt_buffer = p->linktype;
773127664Sbms		return (1);
774127664Sbms	} else {
775172677Smlaier		*dlt_buffer = (int*)calloc(sizeof(**dlt_buffer), p->dlt_count);
776127664Sbms		if (*dlt_buffer == NULL) {
777127664Sbms			(void)snprintf(p->errbuf, sizeof(p->errbuf),
778127664Sbms			    "malloc: %s", pcap_strerror(errno));
779127664Sbms			return (-1);
780127664Sbms		}
781127664Sbms		(void)memcpy(*dlt_buffer, p->dlt_list,
782127664Sbms		    sizeof(**dlt_buffer) * p->dlt_count);
783127664Sbms		return (p->dlt_count);
784109839Sfenner	}
785127664Sbms}
786127664Sbms
787190225Srpaulo/*
788190225Srpaulo * In Windows, you might have a library built with one version of the
789190225Srpaulo * C runtime library and an application built with another version of
790190225Srpaulo * the C runtime library, which means that the library might use one
791190225Srpaulo * version of malloc() and free() and the application might use another
792190225Srpaulo * version of malloc() and free().  If so, that means something
793190225Srpaulo * allocated by the library cannot be freed by the application, so we
794190225Srpaulo * need to have a pcap_free_datalinks() routine to free up the list
795190225Srpaulo * allocated by pcap_list_datalinks(), even though it's just a wrapper
796190225Srpaulo * around free().
797190225Srpaulo */
798190225Srpaulovoid
799190225Srpaulopcap_free_datalinks(int *dlt_list)
800190225Srpaulo{
801190225Srpaulo	free(dlt_list);
802190225Srpaulo}
803190225Srpaulo
804127664Sbmsint
805127664Sbmspcap_set_datalink(pcap_t *p, int dlt)
806127664Sbms{
807127664Sbms	int i;
808127664Sbms	const char *dlt_name;
809127664Sbms
810127664Sbms	if (p->dlt_count == 0 || p->set_datalink_op == NULL) {
811127664Sbms		/*
812127664Sbms		 * We couldn't fetch the list of DLTs, or we don't
813127664Sbms		 * have a "set datalink" operation, which means
814127664Sbms		 * this platform doesn't support changing the
815127664Sbms		 * DLT for an interface.  Check whether the new
816127664Sbms		 * DLT is the one this interface supports.
817127664Sbms		 */
818127664Sbms		if (p->linktype != dlt)
819127664Sbms			goto unsupported;
820127664Sbms
821127664Sbms		/*
822127664Sbms		 * It is, so there's nothing we need to do here.
823127664Sbms		 */
824127664Sbms		return (0);
825109839Sfenner	}
826127664Sbms	for (i = 0; i < p->dlt_count; i++)
827127664Sbms		if (p->dlt_list[i] == dlt)
828127664Sbms			break;
829127664Sbms	if (i >= p->dlt_count)
830127664Sbms		goto unsupported;
831146768Ssam	if (p->dlt_count == 2 && p->dlt_list[0] == DLT_EN10MB &&
832146768Ssam	    dlt == DLT_DOCSIS) {
833146768Ssam		/*
834146768Ssam		 * This is presumably an Ethernet device, as the first
835146768Ssam		 * link-layer type it offers is DLT_EN10MB, and the only
836146768Ssam		 * other type it offers is DLT_DOCSIS.  That means that
837146768Ssam		 * we can't tell the driver to supply DOCSIS link-layer
838146768Ssam		 * headers - we're just pretending that's what we're
839146768Ssam		 * getting, as, presumably, we're capturing on a dedicated
840146768Ssam		 * link to a Cisco Cable Modem Termination System, and
841146768Ssam		 * it's putting raw DOCSIS frames on the wire inside low-level
842146768Ssam		 * Ethernet framing.
843146768Ssam		 */
844146768Ssam		p->linktype = dlt;
845146768Ssam		return (0);
846146768Ssam	}
847127664Sbms	if (p->set_datalink_op(p, dlt) == -1)
848127664Sbms		return (-1);
849127664Sbms	p->linktype = dlt;
850127664Sbms	return (0);
851127664Sbms
852127664Sbmsunsupported:
853127664Sbms	dlt_name = pcap_datalink_val_to_name(dlt);
854127664Sbms	if (dlt_name != NULL) {
855127664Sbms		(void) snprintf(p->errbuf, sizeof(p->errbuf),
856127664Sbms		    "%s is not one of the DLTs supported by this device",
857127664Sbms		    dlt_name);
858127664Sbms	} else {
859127664Sbms		(void) snprintf(p->errbuf, sizeof(p->errbuf),
860127664Sbms		    "DLT %d is not one of the DLTs supported by this device",
861127664Sbms		    dlt);
862127664Sbms	}
863127664Sbms	return (-1);
864109839Sfenner}
865109839Sfenner
866235426Sdelphij/*
867235426Sdelphij * This array is designed for mapping upper and lower case letter
868235426Sdelphij * together for a case independent comparison.  The mappings are
869235426Sdelphij * based upon ascii character sequences.
870235426Sdelphij */
871235426Sdelphijstatic const u_char charmap[] = {
872235426Sdelphij	(u_char)'\000', (u_char)'\001', (u_char)'\002', (u_char)'\003',
873235426Sdelphij	(u_char)'\004', (u_char)'\005', (u_char)'\006', (u_char)'\007',
874235426Sdelphij	(u_char)'\010', (u_char)'\011', (u_char)'\012', (u_char)'\013',
875235426Sdelphij	(u_char)'\014', (u_char)'\015', (u_char)'\016', (u_char)'\017',
876235426Sdelphij	(u_char)'\020', (u_char)'\021', (u_char)'\022', (u_char)'\023',
877235426Sdelphij	(u_char)'\024', (u_char)'\025', (u_char)'\026', (u_char)'\027',
878235426Sdelphij	(u_char)'\030', (u_char)'\031', (u_char)'\032', (u_char)'\033',
879235426Sdelphij	(u_char)'\034', (u_char)'\035', (u_char)'\036', (u_char)'\037',
880235426Sdelphij	(u_char)'\040', (u_char)'\041', (u_char)'\042', (u_char)'\043',
881235426Sdelphij	(u_char)'\044', (u_char)'\045', (u_char)'\046', (u_char)'\047',
882235426Sdelphij	(u_char)'\050', (u_char)'\051', (u_char)'\052', (u_char)'\053',
883235426Sdelphij	(u_char)'\054', (u_char)'\055', (u_char)'\056', (u_char)'\057',
884235426Sdelphij	(u_char)'\060', (u_char)'\061', (u_char)'\062', (u_char)'\063',
885235426Sdelphij	(u_char)'\064', (u_char)'\065', (u_char)'\066', (u_char)'\067',
886235426Sdelphij	(u_char)'\070', (u_char)'\071', (u_char)'\072', (u_char)'\073',
887235426Sdelphij	(u_char)'\074', (u_char)'\075', (u_char)'\076', (u_char)'\077',
888235426Sdelphij	(u_char)'\100', (u_char)'\141', (u_char)'\142', (u_char)'\143',
889235426Sdelphij	(u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
890235426Sdelphij	(u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
891235426Sdelphij	(u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
892235426Sdelphij	(u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
893235426Sdelphij	(u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
894235426Sdelphij	(u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\133',
895235426Sdelphij	(u_char)'\134', (u_char)'\135', (u_char)'\136', (u_char)'\137',
896235426Sdelphij	(u_char)'\140', (u_char)'\141', (u_char)'\142', (u_char)'\143',
897235426Sdelphij	(u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
898235426Sdelphij	(u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
899235426Sdelphij	(u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
900235426Sdelphij	(u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
901235426Sdelphij	(u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
902235426Sdelphij	(u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\173',
903235426Sdelphij	(u_char)'\174', (u_char)'\175', (u_char)'\176', (u_char)'\177',
904235426Sdelphij	(u_char)'\200', (u_char)'\201', (u_char)'\202', (u_char)'\203',
905235426Sdelphij	(u_char)'\204', (u_char)'\205', (u_char)'\206', (u_char)'\207',
906235426Sdelphij	(u_char)'\210', (u_char)'\211', (u_char)'\212', (u_char)'\213',
907235426Sdelphij	(u_char)'\214', (u_char)'\215', (u_char)'\216', (u_char)'\217',
908235426Sdelphij	(u_char)'\220', (u_char)'\221', (u_char)'\222', (u_char)'\223',
909235426Sdelphij	(u_char)'\224', (u_char)'\225', (u_char)'\226', (u_char)'\227',
910235426Sdelphij	(u_char)'\230', (u_char)'\231', (u_char)'\232', (u_char)'\233',
911235426Sdelphij	(u_char)'\234', (u_char)'\235', (u_char)'\236', (u_char)'\237',
912235426Sdelphij	(u_char)'\240', (u_char)'\241', (u_char)'\242', (u_char)'\243',
913235426Sdelphij	(u_char)'\244', (u_char)'\245', (u_char)'\246', (u_char)'\247',
914235426Sdelphij	(u_char)'\250', (u_char)'\251', (u_char)'\252', (u_char)'\253',
915235426Sdelphij	(u_char)'\254', (u_char)'\255', (u_char)'\256', (u_char)'\257',
916235426Sdelphij	(u_char)'\260', (u_char)'\261', (u_char)'\262', (u_char)'\263',
917235426Sdelphij	(u_char)'\264', (u_char)'\265', (u_char)'\266', (u_char)'\267',
918235426Sdelphij	(u_char)'\270', (u_char)'\271', (u_char)'\272', (u_char)'\273',
919235426Sdelphij	(u_char)'\274', (u_char)'\275', (u_char)'\276', (u_char)'\277',
920235426Sdelphij	(u_char)'\300', (u_char)'\341', (u_char)'\342', (u_char)'\343',
921235426Sdelphij	(u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347',
922235426Sdelphij	(u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353',
923235426Sdelphij	(u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357',
924235426Sdelphij	(u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363',
925235426Sdelphij	(u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367',
926235426Sdelphij	(u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\333',
927235426Sdelphij	(u_char)'\334', (u_char)'\335', (u_char)'\336', (u_char)'\337',
928235426Sdelphij	(u_char)'\340', (u_char)'\341', (u_char)'\342', (u_char)'\343',
929235426Sdelphij	(u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347',
930235426Sdelphij	(u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353',
931235426Sdelphij	(u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357',
932235426Sdelphij	(u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363',
933235426Sdelphij	(u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367',
934235426Sdelphij	(u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\373',
935235426Sdelphij	(u_char)'\374', (u_char)'\375', (u_char)'\376', (u_char)'\377',
936235426Sdelphij};
937235426Sdelphij
938235426Sdelphijint
939235426Sdelphijpcap_strcasecmp(const char *s1, const char *s2)
940235426Sdelphij{
941235426Sdelphij	register const u_char	*cm = charmap,
942235426Sdelphij				*us1 = (const u_char *)s1,
943235426Sdelphij				*us2 = (const u_char *)s2;
944235426Sdelphij
945235426Sdelphij	while (cm[*us1] == cm[*us2++])
946235426Sdelphij		if (*us1++ == '\0')
947235426Sdelphij			return(0);
948235426Sdelphij	return (cm[*us1] - cm[*--us2]);
949235426Sdelphij}
950235426Sdelphij
951127664Sbmsstruct dlt_choice {
952127664Sbms	const char *name;
953127664Sbms	const char *description;
954127664Sbms	int	dlt;
955127664Sbms};
956127664Sbms
957127664Sbms#define DLT_CHOICE(code, description) { #code, description, code }
958127664Sbms#define DLT_CHOICE_SENTINEL { NULL, NULL, 0 }
959127664Sbms
960127664Sbmsstatic struct dlt_choice dlt_choices[] = {
961127664Sbms	DLT_CHOICE(DLT_NULL, "BSD loopback"),
962127664Sbms	DLT_CHOICE(DLT_EN10MB, "Ethernet"),
963127664Sbms	DLT_CHOICE(DLT_IEEE802, "Token ring"),
964190225Srpaulo	DLT_CHOICE(DLT_ARCNET, "BSD ARCNET"),
965127664Sbms	DLT_CHOICE(DLT_SLIP, "SLIP"),
966127664Sbms	DLT_CHOICE(DLT_PPP, "PPP"),
967127664Sbms	DLT_CHOICE(DLT_FDDI, "FDDI"),
968147894Ssam	DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"),
969127664Sbms	DLT_CHOICE(DLT_RAW, "Raw IP"),
970127664Sbms	DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"),
971127664Sbms	DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"),
972127664Sbms	DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"),
973127664Sbms	DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"),
974127664Sbms	DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"),
975190225Srpaulo        DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"),
976127664Sbms	DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"),
977127664Sbms	DLT_CHOICE(DLT_IEEE802_11, "802.11"),
978127664Sbms	DLT_CHOICE(DLT_FRELAY, "Frame Relay"),
979127664Sbms	DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"),
980127664Sbms	DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"),
981127664Sbms	DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"),
982127664Sbms	DLT_CHOICE(DLT_LTALK, "Localtalk"),
983127664Sbms	DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"),
984241231Sdelphij	DLT_CHOICE(DLT_PFSYNC, "Packet filter state syncing"),
985127664Sbms	DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"),
986127664Sbms	DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
987127664Sbms	DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"),
988190225Srpaulo	DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus radiotap header"),
989190225Srpaulo	DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"),
990190225Srpaulo        DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
991190225Srpaulo	DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
992190225Srpaulo        DLT_CHOICE(DLT_JUNIPER_ES, "Juniper Encryption Services PIC"),
993190225Srpaulo        DLT_CHOICE(DLT_JUNIPER_GGSN, "Juniper GGSN PIC"),
994190225Srpaulo	DLT_CHOICE(DLT_JUNIPER_MFR, "Juniper FRF.16 Frame Relay"),
995190225Srpaulo        DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"),
996190225Srpaulo        DLT_CHOICE(DLT_JUNIPER_SERVICES, "Juniper Advanced Services PIC"),
997190225Srpaulo        DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"),
998127664Sbms	DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
999190225Srpaulo	DLT_CHOICE(DLT_MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"),
1000190225Srpaulo	DLT_CHOICE(DLT_MTP2, "SS7 MTP2"),
1001190225Srpaulo	DLT_CHOICE(DLT_MTP3, "SS7 MTP3"),
1002190225Srpaulo	DLT_CHOICE(DLT_SCCP, "SS7 SCCP"),
1003146768Ssam	DLT_CHOICE(DLT_DOCSIS, "DOCSIS"),
1004127664Sbms	DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
1005127664Sbms	DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
1006190225Srpaulo        DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
1007172677Smlaier	DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"),
1008172677Smlaier	DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"),
1009172677Smlaier	DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
1010172677Smlaier	DLT_CHOICE(DLT_GPRS_LLC, "GPRS LLC"),
1011172677Smlaier	DLT_CHOICE(DLT_GPF_T, "GPF-T"),
1012172677Smlaier	DLT_CHOICE(DLT_GPF_F, "GPF-F"),
1013172677Smlaier	DLT_CHOICE(DLT_JUNIPER_PIC_PEER, "Juniper PIC Peer"),
1014146768Ssam	DLT_CHOICE(DLT_ERF_ETH,	"Ethernet with Endace ERF header"),
1015146768Ssam	DLT_CHOICE(DLT_ERF_POS, "Packet-over-SONET with Endace ERF header"),
1016190225Srpaulo	DLT_CHOICE(DLT_LINUX_LAPD, "Linux vISDN LAPD"),
1017172677Smlaier	DLT_CHOICE(DLT_JUNIPER_ETHER, "Juniper Ethernet"),
1018172677Smlaier	DLT_CHOICE(DLT_JUNIPER_PPP, "Juniper PPP"),
1019172677Smlaier	DLT_CHOICE(DLT_JUNIPER_FRELAY, "Juniper Frame Relay"),
1020172677Smlaier	DLT_CHOICE(DLT_JUNIPER_CHDLC, "Juniper C-HDLC"),
1021172677Smlaier	DLT_CHOICE(DLT_MFR, "FRF.16 Frame Relay"),
1022172677Smlaier	DLT_CHOICE(DLT_JUNIPER_VP, "Juniper Voice PIC"),
1023172677Smlaier	DLT_CHOICE(DLT_A429, "Arinc 429"),
1024172677Smlaier	DLT_CHOICE(DLT_A653_ICM, "Arinc 653 Interpartition Communication"),
1025172677Smlaier	DLT_CHOICE(DLT_USB, "USB"),
1026172677Smlaier	DLT_CHOICE(DLT_BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"),
1027190225Srpaulo	DLT_CHOICE(DLT_IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"),
1028190225Srpaulo	DLT_CHOICE(DLT_USB_LINUX, "USB with Linux header"),
1029172677Smlaier	DLT_CHOICE(DLT_CAN20B, "Controller Area Network (CAN) v. 2.0B"),
1030190225Srpaulo	DLT_CHOICE(DLT_IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"),
1031190225Srpaulo	DLT_CHOICE(DLT_PPI, "Per-Packet Information"),
1032190225Srpaulo	DLT_CHOICE(DLT_IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"),
1033190225Srpaulo	DLT_CHOICE(DLT_JUNIPER_ISM, "Juniper Integrated Service Module"),
1034235426Sdelphij	DLT_CHOICE(DLT_IEEE802_15_4, "IEEE 802.15.4 with FCS"),
1035190225Srpaulo	DLT_CHOICE(DLT_SITA, "SITA pseudo-header"),
1036190225Srpaulo	DLT_CHOICE(DLT_ERF, "Endace ERF header"),
1037190225Srpaulo	DLT_CHOICE(DLT_RAIF1, "Ethernet with u10 Networks pseudo-header"),
1038190225Srpaulo	DLT_CHOICE(DLT_IPMB, "IPMB"),
1039190225Srpaulo	DLT_CHOICE(DLT_JUNIPER_ST, "Juniper Secure Tunnel"),
1040190225Srpaulo	DLT_CHOICE(DLT_BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"),
1041190225Srpaulo	DLT_CHOICE(DLT_AX25_KISS, "AX.25 with KISS header"),
1042190225Srpaulo	DLT_CHOICE(DLT_IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"),
1043214518Srpaulo	DLT_CHOICE(DLT_MPLS, "MPLS with label as link-layer header"),
1044214518Srpaulo	DLT_CHOICE(DLT_USB_LINUX_MMAPPED, "USB with padded Linux header"),
1045214518Srpaulo	DLT_CHOICE(DLT_DECT, "DECT"),
1046214518Srpaulo	DLT_CHOICE(DLT_AOS, "AOS Space Data Link protocol"),
1047214518Srpaulo	DLT_CHOICE(DLT_WIHART, "Wireless HART"),
1048214518Srpaulo	DLT_CHOICE(DLT_FC_2, "Fibre Channel FC-2"),
1049214518Srpaulo	DLT_CHOICE(DLT_FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"),
1050214518Srpaulo	DLT_CHOICE(DLT_IPNET, "Solaris ipnet"),
1051214518Srpaulo	DLT_CHOICE(DLT_CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"),
1052214518Srpaulo	DLT_CHOICE(DLT_IPV4, "Raw IPv4"),
1053214518Srpaulo	DLT_CHOICE(DLT_IPV6, "Raw IPv6"),
1054235426Sdelphij	DLT_CHOICE(DLT_IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"),
1055235426Sdelphij	DLT_CHOICE(DLT_JUNIPER_VS, "Juniper Virtual Server"),
1056235426Sdelphij	DLT_CHOICE(DLT_JUNIPER_SRX_E2E, "Juniper SRX E2E"),
1057235426Sdelphij	DLT_CHOICE(DLT_JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"),
1058235426Sdelphij	DLT_CHOICE(DLT_DVB_CI, "DVB-CI"),
1059235426Sdelphij	DLT_CHOICE(DLT_JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"),
1060235426Sdelphij	DLT_CHOICE(DLT_NFLOG, "Linux netfilter log messages"),
1061235426Sdelphij	DLT_CHOICE(DLT_NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"),
1062235426Sdelphij	DLT_CHOICE(DLT_NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"),
1063235426Sdelphij	DLT_CHOICE(DLT_IPOIB, "RFC 4391 IP-over-Infiniband"),
1064127664Sbms	DLT_CHOICE_SENTINEL
1065127664Sbms};
1066127664Sbms
1067109839Sfennerint
1068127664Sbmspcap_datalink_name_to_val(const char *name)
1069127664Sbms{
1070127664Sbms	int i;
1071127664Sbms
1072127664Sbms	for (i = 0; dlt_choices[i].name != NULL; i++) {
1073127664Sbms		if (pcap_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1,
1074127664Sbms		    name) == 0)
1075127664Sbms			return (dlt_choices[i].dlt);
1076127664Sbms	}
1077127664Sbms	return (-1);
1078127664Sbms}
1079127664Sbms
1080127664Sbmsconst char *
1081127664Sbmspcap_datalink_val_to_name(int dlt)
1082127664Sbms{
1083127664Sbms	int i;
1084127664Sbms
1085127664Sbms	for (i = 0; dlt_choices[i].name != NULL; i++) {
1086127664Sbms		if (dlt_choices[i].dlt == dlt)
1087127664Sbms			return (dlt_choices[i].name + sizeof("DLT_") - 1);
1088127664Sbms	}
1089127664Sbms	return (NULL);
1090127664Sbms}
1091127664Sbms
1092127664Sbmsconst char *
1093127664Sbmspcap_datalink_val_to_description(int dlt)
1094127664Sbms{
1095127664Sbms	int i;
1096127664Sbms
1097127664Sbms	for (i = 0; dlt_choices[i].name != NULL; i++) {
1098127664Sbms		if (dlt_choices[i].dlt == dlt)
1099127664Sbms			return (dlt_choices[i].description);
1100127664Sbms	}
1101127664Sbms	return (NULL);
1102127664Sbms}
1103127664Sbms
1104235426Sdelphijstruct tstamp_type_choice {
1105235426Sdelphij	const char *name;
1106235426Sdelphij	const char *description;
1107235426Sdelphij	int	type;
1108235426Sdelphij};
1109235426Sdelphij
1110235426Sdelphijstatic struct tstamp_type_choice tstamp_type_choices[] = {
1111235426Sdelphij	{ "host", "Host", PCAP_TSTAMP_HOST },
1112235426Sdelphij	{ "host_lowprec", "Host, low precision", PCAP_TSTAMP_HOST_LOWPREC },
1113235426Sdelphij	{ "host_hiprec", "Host, high precision", PCAP_TSTAMP_HOST_HIPREC },
1114235426Sdelphij	{ "adapter", "Adapter", PCAP_TSTAMP_ADAPTER },
1115235426Sdelphij	{ "adapter_unsynced", "Adapter, not synced with system time", PCAP_TSTAMP_ADAPTER_UNSYNCED },
1116235426Sdelphij	{ NULL, NULL, 0 }
1117235426Sdelphij};
1118235426Sdelphij
1119127664Sbmsint
1120235426Sdelphijpcap_tstamp_type_name_to_val(const char *name)
1121235426Sdelphij{
1122235426Sdelphij	int i;
1123235426Sdelphij
1124235426Sdelphij	for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
1125235426Sdelphij		if (pcap_strcasecmp(tstamp_type_choices[i].name, name) == 0)
1126235426Sdelphij			return (tstamp_type_choices[i].type);
1127235426Sdelphij	}
1128235426Sdelphij	return (PCAP_ERROR);
1129235426Sdelphij}
1130235426Sdelphij
1131235426Sdelphijconst char *
1132235426Sdelphijpcap_tstamp_type_val_to_name(int tstamp_type)
1133235426Sdelphij{
1134235426Sdelphij	int i;
1135235426Sdelphij
1136235426Sdelphij	for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
1137235426Sdelphij		if (tstamp_type_choices[i].type == tstamp_type)
1138235426Sdelphij			return (tstamp_type_choices[i].name);
1139235426Sdelphij	}
1140235426Sdelphij	return (NULL);
1141235426Sdelphij}
1142235426Sdelphij
1143235426Sdelphijconst char *
1144235426Sdelphijpcap_tstamp_type_val_to_description(int tstamp_type)
1145235426Sdelphij{
1146235426Sdelphij	int i;
1147235426Sdelphij
1148235426Sdelphij	for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
1149235426Sdelphij		if (tstamp_type_choices[i].type == tstamp_type)
1150235426Sdelphij			return (tstamp_type_choices[i].description);
1151235426Sdelphij	}
1152235426Sdelphij	return (NULL);
1153235426Sdelphij}
1154235426Sdelphij
1155235426Sdelphijint
115617683Spstpcap_snapshot(pcap_t *p)
115717683Spst{
115817683Spst	return (p->snapshot);
115917683Spst}
116017683Spst
116117683Spstint
116217683Spstpcap_is_swapped(pcap_t *p)
116317683Spst{
116417683Spst	return (p->sf.swapped);
116517683Spst}
116617683Spst
116717683Spstint
116817683Spstpcap_major_version(pcap_t *p)
116917683Spst{
117017683Spst	return (p->sf.version_major);
117117683Spst}
117217683Spst
117317683Spstint
117417683Spstpcap_minor_version(pcap_t *p)
117517683Spst{
117617683Spst	return (p->sf.version_minor);
117717683Spst}
117817683Spst
117917683SpstFILE *
118017683Spstpcap_file(pcap_t *p)
118117683Spst{
118217683Spst	return (p->sf.rfile);
118317683Spst}
118417683Spst
118517683Spstint
118617683Spstpcap_fileno(pcap_t *p)
118717683Spst{
1188127664Sbms#ifndef WIN32
118917683Spst	return (p->fd);
1190127664Sbms#else
1191127664Sbms	if (p->adapter != NULL)
1192127664Sbms		return ((int)(DWORD)p->adapter->hFile);
1193127664Sbms	else
1194127664Sbms		return (-1);
1195127664Sbms#endif
119617683Spst}
119717683Spst
1198146768Ssam#if !defined(WIN32) && !defined(MSDOS)
1199127664Sbmsint
1200127664Sbmspcap_get_selectable_fd(pcap_t *p)
1201127664Sbms{
1202127664Sbms	return (p->selectable_fd);
1203127664Sbms}
1204127664Sbms#endif
1205127664Sbms
120617683Spstvoid
120717683Spstpcap_perror(pcap_t *p, char *prefix)
120817683Spst{
120917683Spst	fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
121017683Spst}
121117683Spst
121217683Spstchar *
121317683Spstpcap_geterr(pcap_t *p)
121417683Spst{
121517683Spst	return (p->errbuf);
121617683Spst}
121717683Spst
1218127664Sbmsint
1219127664Sbmspcap_getnonblock(pcap_t *p, char *errbuf)
1220127664Sbms{
1221251129Sdelphij	int ret;
1222251129Sdelphij
1223251129Sdelphij	ret = p->getnonblock_op(p, errbuf);
1224251129Sdelphij	if (ret == -1) {
1225251129Sdelphij		/*
1226251129Sdelphij		 * In case somebody depended on the bug wherein
1227251129Sdelphij		 * the error message was put into p->errbuf
1228251129Sdelphij		 * by pcap_getnonblock_fd().
1229251129Sdelphij		 */
1230251129Sdelphij		strlcpy(p->errbuf, errbuf, PCAP_ERRBUF_SIZE);
1231251129Sdelphij	}
1232251129Sdelphij	return (ret);
1233127664Sbms}
1234127664Sbms
123517683Spst/*
1236127664Sbms * Get the current non-blocking mode setting, under the assumption that
1237127664Sbms * it's just the standard POSIX non-blocking flag.
1238127664Sbms *
1239127664Sbms * We don't look at "p->nonblock", in case somebody tweaked the FD
1240127664Sbms * directly.
124198530Sfenner */
1242146768Ssam#if !defined(WIN32) && !defined(MSDOS)
124398530Sfennerint
1244127664Sbmspcap_getnonblock_fd(pcap_t *p, char *errbuf)
124598530Sfenner{
124698530Sfenner	int fdflags;
124798530Sfenner
124898530Sfenner	fdflags = fcntl(p->fd, F_GETFL, 0);
124998530Sfenner	if (fdflags == -1) {
1250251129Sdelphij		snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
125198530Sfenner		    pcap_strerror(errno));
125298530Sfenner		return (-1);
125398530Sfenner	}
125498530Sfenner	if (fdflags & O_NONBLOCK)
125598530Sfenner		return (1);
125698530Sfenner	else
125798530Sfenner		return (0);
125898530Sfenner}
1259127664Sbms#endif
126098530Sfenner
126198530Sfennerint
126298530Sfennerpcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
126398530Sfenner{
1264251129Sdelphij	int ret;
1265251129Sdelphij
1266251129Sdelphij	ret = p->setnonblock_op(p, nonblock, errbuf);
1267251129Sdelphij	if (ret == -1) {
1268251129Sdelphij		/*
1269251129Sdelphij		 * In case somebody depended on the bug wherein
1270251129Sdelphij		 * the error message was put into p->errbuf
1271251129Sdelphij		 * by pcap_setnonblock_fd().
1272251129Sdelphij		 */
1273251129Sdelphij		strlcpy(p->errbuf, errbuf, PCAP_ERRBUF_SIZE);
1274251129Sdelphij	}
1275251129Sdelphij	return (ret);
1276127664Sbms}
1277127664Sbms
1278146768Ssam#if !defined(WIN32) && !defined(MSDOS)
1279127664Sbms/*
1280127664Sbms * Set non-blocking mode, under the assumption that it's just the
1281127664Sbms * standard POSIX non-blocking flag.  (This can be called by the
1282127664Sbms * per-platform non-blocking-mode routine if that routine also
1283127664Sbms * needs to do some additional work.)
1284127664Sbms */
1285127664Sbmsint
1286127664Sbmspcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf)
1287127664Sbms{
128898530Sfenner	int fdflags;
128998530Sfenner
129098530Sfenner	fdflags = fcntl(p->fd, F_GETFL, 0);
129198530Sfenner	if (fdflags == -1) {
1292251129Sdelphij		snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
129398530Sfenner		    pcap_strerror(errno));
129498530Sfenner		return (-1);
129598530Sfenner	}
129698530Sfenner	if (nonblock)
129798530Sfenner		fdflags |= O_NONBLOCK;
129898530Sfenner	else
129998530Sfenner		fdflags &= ~O_NONBLOCK;
130098530Sfenner	if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
1301251129Sdelphij		snprintf(errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
130298530Sfenner		    pcap_strerror(errno));
130398530Sfenner		return (-1);
130498530Sfenner	}
130598530Sfenner	return (0);
130698530Sfenner}
1307127664Sbms#endif
130898530Sfenner
1309127664Sbms#ifdef WIN32
131098530Sfenner/*
1311127664Sbms * Generate a string for the last Win32-specific error (i.e. an error generated when
1312127664Sbms * calling a Win32 API).
1313127664Sbms * For errors occurred during standard C calls, we still use pcap_strerror()
1314127664Sbms */
1315127664Sbmschar *
1316127664Sbmspcap_win32strerror(void)
1317127664Sbms{
1318127664Sbms	DWORD error;
1319127664Sbms	static char errbuf[PCAP_ERRBUF_SIZE+1];
1320127664Sbms	int errlen;
1321146768Ssam	char *p;
1322127664Sbms
1323127664Sbms	error = GetLastError();
1324127664Sbms	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
1325127664Sbms	    PCAP_ERRBUF_SIZE, NULL);
1326127664Sbms
1327127664Sbms	/*
1328127664Sbms	 * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
1329127664Sbms	 * message.  Get rid of it.
1330127664Sbms	 */
1331127664Sbms	errlen = strlen(errbuf);
1332127664Sbms	if (errlen >= 2) {
1333127664Sbms		errbuf[errlen - 1] = '\0';
1334127664Sbms		errbuf[errlen - 2] = '\0';
1335127664Sbms	}
1336146768Ssam	p = strchr(errbuf, '\0');
1337146768Ssam	snprintf (p, sizeof(errbuf)-(p-errbuf), " (%lu)", error);
1338127664Sbms	return (errbuf);
1339127664Sbms}
1340127664Sbms#endif
1341127664Sbms
1342127664Sbms/*
1343190225Srpaulo * Generate error strings for PCAP_ERROR_ and PCAP_WARNING_ values.
1344190225Srpaulo */
1345190225Srpauloconst char *
1346190225Srpaulopcap_statustostr(int errnum)
1347190225Srpaulo{
1348190225Srpaulo	static char ebuf[15+10+1];
1349190225Srpaulo
1350190225Srpaulo	switch (errnum) {
1351190225Srpaulo
1352190225Srpaulo	case PCAP_WARNING:
1353190225Srpaulo		return("Generic warning");
1354190225Srpaulo
1355235426Sdelphij	case PCAP_WARNING_TSTAMP_TYPE_NOTSUP:
1356235426Sdelphij		return ("That type of time stamp is not supported by that device");
1357235426Sdelphij
1358190225Srpaulo	case PCAP_WARNING_PROMISC_NOTSUP:
1359190225Srpaulo		return ("That device doesn't support promiscuous mode");
1360190225Srpaulo
1361190225Srpaulo	case PCAP_ERROR:
1362190225Srpaulo		return("Generic error");
1363190225Srpaulo
1364190225Srpaulo	case PCAP_ERROR_BREAK:
1365190225Srpaulo		return("Loop terminated by pcap_breakloop");
1366190225Srpaulo
1367190225Srpaulo	case PCAP_ERROR_NOT_ACTIVATED:
1368190225Srpaulo		return("The pcap_t has not been activated");
1369190225Srpaulo
1370190225Srpaulo	case PCAP_ERROR_ACTIVATED:
1371190225Srpaulo		return ("The setting can't be changed after the pcap_t is activated");
1372190225Srpaulo
1373190225Srpaulo	case PCAP_ERROR_NO_SUCH_DEVICE:
1374190225Srpaulo		return ("No such device exists");
1375190225Srpaulo
1376190225Srpaulo	case PCAP_ERROR_RFMON_NOTSUP:
1377190225Srpaulo		return ("That device doesn't support monitor mode");
1378190225Srpaulo
1379190225Srpaulo	case PCAP_ERROR_NOT_RFMON:
1380190225Srpaulo		return ("That operation is supported only in monitor mode");
1381190225Srpaulo
1382190225Srpaulo	case PCAP_ERROR_PERM_DENIED:
1383190225Srpaulo		return ("You don't have permission to capture on that device");
1384190225Srpaulo
1385190225Srpaulo	case PCAP_ERROR_IFACE_NOT_UP:
1386190225Srpaulo		return ("That device is not up");
1387235426Sdelphij
1388235426Sdelphij	case PCAP_ERROR_CANTSET_TSTAMP_TYPE:
1389235426Sdelphij		return ("That device doesn't support setting the time stamp type");
1390235426Sdelphij
1391235426Sdelphij	case PCAP_ERROR_PROMISC_PERM_DENIED:
1392235426Sdelphij		return ("You don't have permission to capture in promiscuous mode on that device");
1393190225Srpaulo	}
1394190225Srpaulo	(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
1395190225Srpaulo	return(ebuf);
1396190225Srpaulo}
1397190225Srpaulo
1398190225Srpaulo/*
139917683Spst * Not all systems have strerror().
140017683Spst */
1401172677Smlaierconst char *
140217683Spstpcap_strerror(int errnum)
140317683Spst{
140417683Spst#ifdef HAVE_STRERROR
140517683Spst	return (strerror(errnum));
140617683Spst#else
140717683Spst	extern int sys_nerr;
140817683Spst	extern const char *const sys_errlist[];
1409190225Srpaulo	static char ebuf[15+10+1];
141017683Spst
141117683Spst	if ((unsigned int)errnum < sys_nerr)
141217683Spst		return ((char *)sys_errlist[errnum]);
141375107Sfenner	(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
141417683Spst	return(ebuf);
141517683Spst#endif
141617683Spst}
141717683Spst
1418127664Sbmsint
1419127664Sbmspcap_setfilter(pcap_t *p, struct bpf_program *fp)
1420127664Sbms{
1421235426Sdelphij	return (p->setfilter_op(p, fp));
1422127664Sbms}
1423127664Sbms
1424147894Ssam/*
1425147894Ssam * Set direction flag, which controls whether we accept only incoming
1426147894Ssam * packets, only outgoing packets, or both.
1427147894Ssam * Note that, depending on the platform, some or all direction arguments
1428147894Ssam * might not be supported.
1429147894Ssam */
1430127664Sbmsint
1431162012Ssampcap_setdirection(pcap_t *p, pcap_direction_t d)
1432147894Ssam{
1433147894Ssam	if (p->setdirection_op == NULL) {
1434147894Ssam		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1435147894Ssam		    "Setting direction is not implemented on this platform");
1436235426Sdelphij		return (-1);
1437147894Ssam	} else
1438235426Sdelphij		return (p->setdirection_op(p, d));
1439147894Ssam}
1440147894Ssam
1441147894Ssamint
1442127664Sbmspcap_stats(pcap_t *p, struct pcap_stat *ps)
1443127664Sbms{
1444235426Sdelphij	return (p->stats_op(p, ps));
1445127664Sbms}
1446127664Sbms
1447127664Sbmsstatic int
1448146768Ssampcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_)
1449127664Sbms{
1450127664Sbms	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1451127664Sbms	    "Statistics aren't available from a pcap_open_dead pcap_t");
1452127664Sbms	return (-1);
1453127664Sbms}
1454127664Sbms
1455190225Srpaulo#ifdef WIN32
1456190225Srpauloint
1457190225Srpaulopcap_setbuff(pcap_t *p, int dim)
1458146768Ssam{
1459235426Sdelphij	return (p->setbuff_op(p, dim));
1460190225Srpaulo}
1461190225Srpaulo
1462190225Srpaulostatic int
1463190225Srpaulopcap_setbuff_dead(pcap_t *p, int dim)
1464190225Srpaulo{
1465190225Srpaulo	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1466190225Srpaulo	    "The kernel buffer size cannot be set on a pcap_open_dead pcap_t");
1467190225Srpaulo	return (-1);
1468190225Srpaulo}
1469190225Srpaulo
1470190225Srpauloint
1471190225Srpaulopcap_setmode(pcap_t *p, int mode)
1472190225Srpaulo{
1473235426Sdelphij	return (p->setmode_op(p, mode));
1474190225Srpaulo}
1475190225Srpaulo
1476190225Srpaulostatic int
1477190225Srpaulopcap_setmode_dead(pcap_t *p, int mode)
1478190225Srpaulo{
1479190225Srpaulo	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1480190225Srpaulo	    "impossible to set mode on a pcap_open_dead pcap_t");
1481190225Srpaulo	return (-1);
1482190225Srpaulo}
1483190225Srpaulo
1484190225Srpauloint
1485190225Srpaulopcap_setmintocopy(pcap_t *p, int size)
1486190225Srpaulo{
1487235426Sdelphij	return (p->setmintocopy_op(p, size));
1488190225Srpaulo}
1489190225Srpaulo
1490190225Srpaulostatic int
1491190225Srpaulopcap_setmintocopy_dead(pcap_t *p, int size)
1492190225Srpaulo{
1493190225Srpaulo	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
1494190225Srpaulo	    "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t");
1495190225Srpaulo	return (-1);
1496190225Srpaulo}
1497190225Srpaulo#endif
1498190225Srpaulo
1499190225Srpaulo/*
1500190225Srpaulo * On some platforms, we need to clean up promiscuous or monitor mode
1501190225Srpaulo * when we close a device - and we want that to happen even if the
1502190225Srpaulo * application just exits without explicitl closing devices.
1503190225Srpaulo * On those platforms, we need to register a "close all the pcaps"
1504190225Srpaulo * routine to be called when we exit, and need to maintain a list of
1505190225Srpaulo * pcaps that need to be closed to clean up modes.
1506190225Srpaulo *
1507190225Srpaulo * XXX - not thread-safe.
1508190225Srpaulo */
1509190225Srpaulo
1510190225Srpaulo/*
1511190225Srpaulo * List of pcaps on which we've done something that needs to be
1512190225Srpaulo * cleaned up.
1513190225Srpaulo * If there are any such pcaps, we arrange to call "pcap_close_all()"
1514190225Srpaulo * when we exit, and have it close all of them.
1515190225Srpaulo */
1516190225Srpaulostatic struct pcap *pcaps_to_close;
1517190225Srpaulo
1518190225Srpaulo/*
1519190225Srpaulo * TRUE if we've already called "atexit()" to cause "pcap_close_all()" to
1520190225Srpaulo * be called on exit.
1521190225Srpaulo */
1522190225Srpaulostatic int did_atexit;
1523190225Srpaulo
1524190225Srpaulostatic void
1525190225Srpaulopcap_close_all(void)
1526190225Srpaulo{
1527190225Srpaulo	struct pcap *handle;
1528190225Srpaulo
1529190225Srpaulo	while ((handle = pcaps_to_close) != NULL)
1530190225Srpaulo		pcap_close(handle);
1531190225Srpaulo}
1532190225Srpaulo
1533190225Srpauloint
1534190225Srpaulopcap_do_addexit(pcap_t *p)
1535190225Srpaulo{
1536183102Scsjp	/*
1537190225Srpaulo	 * If we haven't already done so, arrange to have
1538190225Srpaulo	 * "pcap_close_all()" called when we exit.
1539183102Scsjp	 */
1540190225Srpaulo	if (!did_atexit) {
1541190225Srpaulo		if (atexit(pcap_close_all) == -1) {
1542190225Srpaulo			/*
1543190225Srpaulo			 * "atexit()" failed; let our caller know.
1544190225Srpaulo			 */
1545190225Srpaulo			strncpy(p->errbuf, "atexit failed",
1546190225Srpaulo			    PCAP_ERRBUF_SIZE);
1547190225Srpaulo			return (0);
1548190225Srpaulo		}
1549190225Srpaulo		did_atexit = 1;
1550190225Srpaulo	}
1551190225Srpaulo	return (1);
1552190225Srpaulo}
1553190225Srpaulo
1554190225Srpaulovoid
1555190225Srpaulopcap_add_to_pcaps_to_close(pcap_t *p)
1556190225Srpaulo{
1557190225Srpaulo	p->md.next = pcaps_to_close;
1558190225Srpaulo	pcaps_to_close = p;
1559190225Srpaulo}
1560190225Srpaulo
1561190225Srpaulovoid
1562190225Srpaulopcap_remove_from_pcaps_to_close(pcap_t *p)
1563190225Srpaulo{
1564190225Srpaulo	pcap_t *pc, *prevpc;
1565190225Srpaulo
1566190225Srpaulo	for (pc = pcaps_to_close, prevpc = NULL; pc != NULL;
1567190225Srpaulo	    prevpc = pc, pc = pc->md.next) {
1568190225Srpaulo		if (pc == p) {
1569190225Srpaulo			/*
1570190225Srpaulo			 * Found it.  Remove it from the list.
1571190225Srpaulo			 */
1572190225Srpaulo			if (prevpc == NULL) {
1573190225Srpaulo				/*
1574190225Srpaulo				 * It was at the head of the list.
1575190225Srpaulo				 */
1576190225Srpaulo				pcaps_to_close = pc->md.next;
1577190225Srpaulo			} else {
1578190225Srpaulo				/*
1579190225Srpaulo				 * It was in the middle of the list.
1580190225Srpaulo				 */
1581190225Srpaulo				prevpc->md.next = pc->md.next;
1582190225Srpaulo			}
1583190225Srpaulo			break;
1584190225Srpaulo		}
1585190225Srpaulo	}
1586190225Srpaulo}
1587190225Srpaulo
1588190225Srpaulovoid
1589190225Srpaulopcap_cleanup_live_common(pcap_t *p)
1590190225Srpaulo{
1591190225Srpaulo	if (p->buffer != NULL) {
1592190225Srpaulo		free(p->buffer);
1593183102Scsjp		p->buffer = NULL;
1594190225Srpaulo	}
1595190225Srpaulo	if (p->dlt_list != NULL) {
1596190225Srpaulo		free(p->dlt_list);
1597190225Srpaulo		p->dlt_list = NULL;
1598190225Srpaulo		p->dlt_count = 0;
1599190225Srpaulo	}
1600235426Sdelphij	if (p->tstamp_type_list != NULL) {
1601235426Sdelphij		free(p->tstamp_type_list);
1602235426Sdelphij		p->tstamp_type_list = NULL;
1603235426Sdelphij		p->tstamp_type_count = 0;
1604235426Sdelphij	}
1605190225Srpaulo	pcap_freecode(&p->fcode);
1606146768Ssam#if !defined(WIN32) && !defined(MSDOS)
1607190225Srpaulo	if (p->fd >= 0) {
1608146768Ssam		close(p->fd);
1609190225Srpaulo		p->fd = -1;
1610190225Srpaulo	}
1611214518Srpaulo	p->selectable_fd = -1;
1612214518Srpaulo	p->send_fd = -1;
1613146768Ssam#endif
1614146768Ssam}
1615146768Ssam
1616127664Sbmsstatic void
1617190225Srpaulopcap_cleanup_dead(pcap_t *p _U_)
1618127664Sbms{
1619127664Sbms	/* Nothing to do. */
1620127664Sbms}
1621127664Sbms
162275107Sfennerpcap_t *
162375107Sfennerpcap_open_dead(int linktype, int snaplen)
162475107Sfenner{
162575107Sfenner	pcap_t *p;
162675107Sfenner
162775107Sfenner	p = malloc(sizeof(*p));
162875107Sfenner	if (p == NULL)
162975107Sfenner		return NULL;
163075107Sfenner	memset (p, 0, sizeof(*p));
163175107Sfenner	p->snapshot = snaplen;
163275107Sfenner	p->linktype = linktype;
1633127664Sbms	p->stats_op = pcap_stats_dead;
1634190225Srpaulo#ifdef WIN32
1635190225Srpaulo	p->setbuff_op = pcap_setbuff_dead;
1636190225Srpaulo	p->setmode_op = pcap_setmode_dead;
1637190225Srpaulo	p->setmintocopy_op = pcap_setmintocopy_dead;
1638190225Srpaulo#endif
1639190225Srpaulo	p->cleanup_op = pcap_cleanup_dead;
1640190225Srpaulo	p->activated = 1;
1641235426Sdelphij	return (p);
164275107Sfenner}
164375107Sfenner
1644146768Ssam/*
1645146768Ssam * API compatible with WinPcap's "send a packet" routine - returns -1
1646146768Ssam * on error, 0 otherwise.
1647146768Ssam *
1648146768Ssam * XXX - what if we get a short write?
1649146768Ssam */
1650146768Ssamint
1651146768Ssampcap_sendpacket(pcap_t *p, const u_char *buf, int size)
1652146768Ssam{
1653146768Ssam	if (p->inject_op(p, buf, size) == -1)
1654146768Ssam		return (-1);
1655146768Ssam	return (0);
1656146768Ssam}
1657146768Ssam
1658146768Ssam/*
1659146768Ssam * API compatible with OpenBSD's "send a packet" routine - returns -1 on
1660146768Ssam * error, number of bytes written otherwise.
1661146768Ssam */
1662146768Ssamint
1663146768Ssampcap_inject(pcap_t *p, const void *buf, size_t size)
1664146768Ssam{
1665146768Ssam	return (p->inject_op(p, buf, size));
1666146768Ssam}
1667146768Ssam
166817683Spstvoid
166917683Spstpcap_close(pcap_t *p)
167017683Spst{
1671190225Srpaulo	if (p->opt.source != NULL)
1672190225Srpaulo		free(p->opt.source);
1673190225Srpaulo	p->cleanup_op(p);
167417683Spst	free(p);
167517683Spst}
1676127664Sbms
1677127664Sbms/*
1678190225Srpaulo * Given a BPF program, a pcap_pkthdr structure for a packet, and the raw
1679190225Srpaulo * data for the packet, check whether the packet passes the filter.
1680190225Srpaulo * Returns the return value of the filter program, which will be zero if
1681190225Srpaulo * the packet doesn't pass and non-zero if the packet does pass.
1682190225Srpaulo */
1683190225Srpauloint
1684251129Sdelphijpcap_offline_filter(const struct bpf_program *fp, const struct pcap_pkthdr *h,
1685190225Srpaulo    const u_char *pkt)
1686190225Srpaulo{
1687251129Sdelphij	const struct bpf_insn *fcode = fp->bf_insns;
1688190225Srpaulo
1689190225Srpaulo	if (fcode != NULL)
1690190225Srpaulo		return (bpf_filter(fcode, pkt, h->len, h->caplen));
1691190225Srpaulo	else
1692190225Srpaulo		return (0);
1693190225Srpaulo}
1694190225Srpaulo
1695190225Srpaulo/*
1696127664Sbms * We make the version string static, and return a pointer to it, rather
1697127664Sbms * than exporting the version string directly.  On at least some UNIXes,
1698127664Sbms * if you import data from a shared library into an program, the data is
1699127664Sbms * bound into the program binary, so if the string in the version of the
1700127664Sbms * library with which the program was linked isn't the same as the
1701127664Sbms * string in the version of the library with which the program is being
1702127664Sbms * run, various undesirable things may happen (warnings, the string
1703127664Sbms * being the one from the version of the library with which the program
1704127664Sbms * was linked, or even weirder things, such as the string being the one
1705127664Sbms * from the library but being truncated).
1706127664Sbms */
1707146768Ssam#ifdef HAVE_VERSION_H
1708146768Ssam#include "version.h"
1709146768Ssam#else
1710214518Srpaulostatic const char pcap_version_string[] = "libpcap version 1.x.y";
1711146768Ssam#endif
1712146768Ssam
1713127664Sbms#ifdef WIN32
1714127664Sbms/*
1715127664Sbms * XXX - it'd be nice if we could somehow generate the WinPcap and libpcap
1716127664Sbms * version numbers when building WinPcap.  (It'd be nice to do so for
1717127664Sbms * the packet.dll version number as well.)
1718127664Sbms */
1719172677Smlaierstatic const char wpcap_version_string[] = "4.0";
1720127664Sbmsstatic const char pcap_version_string_fmt[] =
1721146768Ssam    "WinPcap version %s, based on %s";
1722127664Sbmsstatic const char pcap_version_string_packet_dll_fmt[] =
1723146768Ssam    "WinPcap version %s (packet.dll version %s), based on %s";
1724146768Ssamstatic char *full_pcap_version_string;
1725127664Sbms
1726127664Sbmsconst char *
1727127664Sbmspcap_lib_version(void)
1728127664Sbms{
1729127664Sbms	char *packet_version_string;
1730146768Ssam	size_t full_pcap_version_string_len;
1731127664Sbms
1732146768Ssam	if (full_pcap_version_string == NULL) {
1733127664Sbms		/*
1734127664Sbms		 * Generate the version string.
1735127664Sbms		 */
1736127664Sbms		packet_version_string = PacketGetVersion();
1737127664Sbms		if (strcmp(wpcap_version_string, packet_version_string) == 0) {
1738127664Sbms			/*
1739127664Sbms			 * WinPcap version string and packet.dll version
1740127664Sbms			 * string are the same; just report the WinPcap
1741127664Sbms			 * version.
1742127664Sbms			 */
1743146768Ssam			full_pcap_version_string_len =
1744146768Ssam			    (sizeof pcap_version_string_fmt - 4) +
1745146768Ssam			    strlen(wpcap_version_string) +
1746146768Ssam			    strlen(pcap_version_string);
1747146768Ssam			full_pcap_version_string =
1748146768Ssam			    malloc(full_pcap_version_string_len);
1749146768Ssam			sprintf(full_pcap_version_string,
1750146768Ssam			    pcap_version_string_fmt, wpcap_version_string,
1751146768Ssam			    pcap_version_string);
1752127664Sbms		} else {
1753127664Sbms			/*
1754127664Sbms			 * WinPcap version string and packet.dll version
1755127664Sbms			 * string are different; that shouldn't be the
1756127664Sbms			 * case (the two libraries should come from the
1757127664Sbms			 * same version of WinPcap), so we report both
1758127664Sbms			 * versions.
1759127664Sbms			 */
1760146768Ssam			full_pcap_version_string_len =
1761146768Ssam			    (sizeof pcap_version_string_packet_dll_fmt - 6) +
1762127664Sbms			    strlen(wpcap_version_string) +
1763146768Ssam			    strlen(packet_version_string) +
1764146768Ssam			    strlen(pcap_version_string);
1765146768Ssam			full_pcap_version_string = malloc(full_pcap_version_string_len);
1766146768Ssam
1767146768Ssam			sprintf(full_pcap_version_string,
1768127664Sbms			    pcap_version_string_packet_dll_fmt,
1769146768Ssam			    wpcap_version_string, packet_version_string,
1770146768Ssam			    pcap_version_string);
1771127664Sbms		}
1772127664Sbms	}
1773146768Ssam	return (full_pcap_version_string);
1774127664Sbms}
1775127664Sbms
1776146768Ssam#elif defined(MSDOS)
1777146768Ssam
1778146768Ssamstatic char *full_pcap_version_string;
1779146768Ssam
1780127664Sbmsconst char *
1781146768Ssampcap_lib_version (void)
1782146768Ssam{
1783146768Ssam	char *packet_version_string;
1784146768Ssam	size_t full_pcap_version_string_len;
1785146768Ssam	static char dospfx[] = "DOS-";
1786146768Ssam
1787146768Ssam	if (full_pcap_version_string == NULL) {
1788146768Ssam		/*
1789146768Ssam		 * Generate the version string.
1790146768Ssam		 */
1791146768Ssam		full_pcap_version_string_len =
1792146768Ssam		    sizeof dospfx + strlen(pcap_version_string);
1793146768Ssam		full_pcap_version_string =
1794146768Ssam		    malloc(full_pcap_version_string_len);
1795146768Ssam		strcpy(full_pcap_version_string, dospfx);
1796146768Ssam		strcat(full_pcap_version_string, pcap_version_string);
1797146768Ssam	}
1798146768Ssam	return (full_pcap_version_string);
1799146768Ssam}
1800146768Ssam
1801146768Ssam#else /* UN*X */
1802146768Ssam
1803146768Ssamconst char *
1804127664Sbmspcap_lib_version(void)
1805127664Sbms{
1806127664Sbms	return (pcap_version_string);
1807127664Sbms}
1808127664Sbms#endif
1809