pcap.c revision 162012
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_ =
36162012Ssam    "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.88.2.8 2005/08/13 22:29:46 hannes 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 */
4617683Spst#include <sys/types.h>
47127664Sbms#endif /* WIN32 */
4817683Spst
4917683Spst#include <stdio.h>
5017683Spst#include <stdlib.h>
5117683Spst#include <string.h>
52146768Ssam#if !defined(_MSC_VER) && !defined(__BORLANDC__)
5317683Spst#include <unistd.h>
54127664Sbms#endif
5598530Sfenner#include <fcntl.h>
5698530Sfenner#include <errno.h>
5717683Spst
5817683Spst#ifdef HAVE_OS_PROTO_H
5917683Spst#include "os-proto.h"
6017683Spst#endif
6117683Spst
62146768Ssam#ifdef MSDOS
63146768Ssam#include "pcap-dos.h"
64146768Ssam#endif
65146768Ssam
6617683Spst#include "pcap-int.h"
6717683Spst
68127664Sbms#ifdef HAVE_DAG_API
69127664Sbms#include <dagnew.h>
70127664Sbms#include <dagapi.h>
71127664Sbms#endif
72127664Sbms
7317683Spstint
7417683Spstpcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
7517683Spst{
7617683Spst
77127664Sbms	return p->read_op(p, cnt, callback, user);
7817683Spst}
7917683Spst
80127664Sbms/*
81127664Sbms * XXX - is this necessary?
82127664Sbms */
8317683Spstint
84127664Sbmspcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
85127664Sbms{
86127664Sbms
87127664Sbms	return p->read_op(p, cnt, callback, user);
88127664Sbms}
89127664Sbms
90127664Sbmsint
9117683Spstpcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
9217683Spst{
9339291Sfenner	register int n;
9439291Sfenner
9517683Spst	for (;;) {
96127664Sbms		if (p->sf.rfile != NULL) {
97127664Sbms			/*
98127664Sbms			 * 0 means EOF, so don't loop if we get 0.
99127664Sbms			 */
10039291Sfenner			n = pcap_offline_read(p, cnt, callback, user);
101127664Sbms		} else {
10239291Sfenner			/*
10339291Sfenner			 * XXX keep reading until we get something
10439291Sfenner			 * (or an error occurs)
10539291Sfenner			 */
10639291Sfenner			do {
107127664Sbms				n = p->read_op(p, cnt, callback, user);
10839291Sfenner			} while (n == 0);
10939291Sfenner		}
11017683Spst		if (n <= 0)
11117683Spst			return (n);
11217683Spst		if (cnt > 0) {
11317683Spst			cnt -= n;
11417683Spst			if (cnt <= 0)
11517683Spst				return (0);
11617683Spst		}
11717683Spst	}
11817683Spst}
11917683Spst
12017683Spststruct singleton {
12117683Spst	struct pcap_pkthdr *hdr;
12217683Spst	const u_char *pkt;
12317683Spst};
12417683Spst
12517683Spst
12617683Spststatic void
12717683Spstpcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt)
12817683Spst{
12917683Spst	struct singleton *sp = (struct singleton *)userData;
13017683Spst	*sp->hdr = *h;
13117683Spst	sp->pkt = pkt;
13217683Spst}
13317683Spst
13417683Spstconst u_char *
13517683Spstpcap_next(pcap_t *p, struct pcap_pkthdr *h)
13617683Spst{
13717683Spst	struct singleton s;
13817683Spst
13917683Spst	s.hdr = h;
14017683Spst	if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) <= 0)
14117683Spst		return (0);
14217683Spst	return (s.pkt);
14317683Spst}
14417683Spst
145127664Sbmsstruct pkt_for_fakecallback {
146127664Sbms	struct pcap_pkthdr *hdr;
147127664Sbms	const u_char **pkt;
148127664Sbms};
149127664Sbms
150127664Sbmsstatic void
151127664Sbmspcap_fakecallback(u_char *userData, const struct pcap_pkthdr *h,
152127664Sbms    const u_char *pkt)
153127664Sbms{
154127664Sbms	struct pkt_for_fakecallback *sp = (struct pkt_for_fakecallback *)userData;
155127664Sbms
156127664Sbms	*sp->hdr = *h;
157127664Sbms	*sp->pkt = pkt;
158127664Sbms}
159127664Sbms
160127664Sbmsint
161127664Sbmspcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
162127664Sbms    const u_char **pkt_data)
163127664Sbms{
164127664Sbms	struct pkt_for_fakecallback s;
165127664Sbms
166127664Sbms	s.hdr = &p->pcap_header;
167127664Sbms	s.pkt = pkt_data;
168127664Sbms
169127664Sbms	/* Saves a pointer to the packet headers */
170127664Sbms	*pkt_header= &p->pcap_header;
171127664Sbms
172127664Sbms	if (p->sf.rfile != NULL) {
173127664Sbms		int status;
174127664Sbms
175127664Sbms		/* We are on an offline capture */
176127664Sbms		status = pcap_offline_read(p, 1, pcap_fakecallback,
177127664Sbms		    (u_char *)&s);
178127664Sbms
179127664Sbms		/*
180127664Sbms		 * Return codes for pcap_offline_read() are:
181127664Sbms		 *   -  0: EOF
182127664Sbms		 *   - -1: error
183127664Sbms		 *   - >1: OK
184127664Sbms		 * The first one ('0') conflicts with the return code of
185127664Sbms		 * 0 from pcap_read() meaning "no packets arrived before
186127664Sbms		 * the timeout expired", so we map it to -2 so you can
187127664Sbms		 * distinguish between an EOF from a savefile and a
188127664Sbms		 * "no packets arrived before the timeout expired, try
189127664Sbms		 * again" from a live capture.
190127664Sbms		 */
191127664Sbms		if (status == 0)
192127664Sbms			return (-2);
193127664Sbms		else
194127664Sbms			return (status);
195127664Sbms	}
196127664Sbms
197127664Sbms	/*
198127664Sbms	 * Return codes for pcap_read() are:
199127664Sbms	 *   -  0: timeout
200127664Sbms	 *   - -1: error
201127664Sbms	 *   - -2: loop was broken out of with pcap_breakloop()
202127664Sbms	 *   - >1: OK
203127664Sbms	 * The first one ('0') conflicts with the return code of 0 from
204127664Sbms	 * pcap_offline_read() meaning "end of file".
205127664Sbms	*/
206127664Sbms	return (p->read_op(p, 1, pcap_fakecallback, (u_char *)&s));
207127664Sbms}
208127664Sbms
209127664Sbms/*
210127664Sbms * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate.
211127664Sbms */
212127664Sbmsvoid
213127664Sbmspcap_breakloop(pcap_t *p)
214127664Sbms{
215127664Sbms	p->break_loop = 1;
216127664Sbms}
217127664Sbms
21817683Spstint
21917683Spstpcap_datalink(pcap_t *p)
22017683Spst{
22117683Spst	return (p->linktype);
22217683Spst}
22317683Spst
22417683Spstint
225109839Sfennerpcap_list_datalinks(pcap_t *p, int **dlt_buffer)
226109839Sfenner{
227127664Sbms	if (p->dlt_count == 0) {
228127664Sbms		/*
229127664Sbms		 * We couldn't fetch the list of DLTs, which means
230127664Sbms		 * this platform doesn't support changing the
231127664Sbms		 * DLT for an interface.  Return a list of DLTs
232127664Sbms		 * containing only the DLT this device supports.
233127664Sbms		 */
234127664Sbms		*dlt_buffer = (int*)malloc(sizeof(**dlt_buffer));
235127664Sbms		if (*dlt_buffer == NULL) {
236127664Sbms			(void)snprintf(p->errbuf, sizeof(p->errbuf),
237127664Sbms			    "malloc: %s", pcap_strerror(errno));
238127664Sbms			return (-1);
239127664Sbms		}
240127664Sbms		**dlt_buffer = p->linktype;
241127664Sbms		return (1);
242127664Sbms	} else {
243127664Sbms		*dlt_buffer = (int*)malloc(sizeof(**dlt_buffer) * p->dlt_count);
244127664Sbms		if (*dlt_buffer == NULL) {
245127664Sbms			(void)snprintf(p->errbuf, sizeof(p->errbuf),
246127664Sbms			    "malloc: %s", pcap_strerror(errno));
247127664Sbms			return (-1);
248127664Sbms		}
249127664Sbms		(void)memcpy(*dlt_buffer, p->dlt_list,
250127664Sbms		    sizeof(**dlt_buffer) * p->dlt_count);
251127664Sbms		return (p->dlt_count);
252109839Sfenner	}
253127664Sbms}
254127664Sbms
255127664Sbmsint
256127664Sbmspcap_set_datalink(pcap_t *p, int dlt)
257127664Sbms{
258127664Sbms	int i;
259127664Sbms	const char *dlt_name;
260127664Sbms
261127664Sbms	if (p->dlt_count == 0 || p->set_datalink_op == NULL) {
262127664Sbms		/*
263127664Sbms		 * We couldn't fetch the list of DLTs, or we don't
264127664Sbms		 * have a "set datalink" operation, which means
265127664Sbms		 * this platform doesn't support changing the
266127664Sbms		 * DLT for an interface.  Check whether the new
267127664Sbms		 * DLT is the one this interface supports.
268127664Sbms		 */
269127664Sbms		if (p->linktype != dlt)
270127664Sbms			goto unsupported;
271127664Sbms
272127664Sbms		/*
273127664Sbms		 * It is, so there's nothing we need to do here.
274127664Sbms		 */
275127664Sbms		return (0);
276109839Sfenner	}
277127664Sbms	for (i = 0; i < p->dlt_count; i++)
278127664Sbms		if (p->dlt_list[i] == dlt)
279127664Sbms			break;
280127664Sbms	if (i >= p->dlt_count)
281127664Sbms		goto unsupported;
282146768Ssam	if (p->dlt_count == 2 && p->dlt_list[0] == DLT_EN10MB &&
283146768Ssam	    dlt == DLT_DOCSIS) {
284146768Ssam		/*
285146768Ssam		 * This is presumably an Ethernet device, as the first
286146768Ssam		 * link-layer type it offers is DLT_EN10MB, and the only
287146768Ssam		 * other type it offers is DLT_DOCSIS.  That means that
288146768Ssam		 * we can't tell the driver to supply DOCSIS link-layer
289146768Ssam		 * headers - we're just pretending that's what we're
290146768Ssam		 * getting, as, presumably, we're capturing on a dedicated
291146768Ssam		 * link to a Cisco Cable Modem Termination System, and
292146768Ssam		 * it's putting raw DOCSIS frames on the wire inside low-level
293146768Ssam		 * Ethernet framing.
294146768Ssam		 */
295146768Ssam		p->linktype = dlt;
296146768Ssam		return (0);
297146768Ssam	}
298127664Sbms	if (p->set_datalink_op(p, dlt) == -1)
299127664Sbms		return (-1);
300127664Sbms	p->linktype = dlt;
301127664Sbms	return (0);
302127664Sbms
303127664Sbmsunsupported:
304127664Sbms	dlt_name = pcap_datalink_val_to_name(dlt);
305127664Sbms	if (dlt_name != NULL) {
306127664Sbms		(void) snprintf(p->errbuf, sizeof(p->errbuf),
307127664Sbms		    "%s is not one of the DLTs supported by this device",
308127664Sbms		    dlt_name);
309127664Sbms	} else {
310127664Sbms		(void) snprintf(p->errbuf, sizeof(p->errbuf),
311127664Sbms		    "DLT %d is not one of the DLTs supported by this device",
312127664Sbms		    dlt);
313127664Sbms	}
314127664Sbms	return (-1);
315109839Sfenner}
316109839Sfenner
317127664Sbmsstruct dlt_choice {
318127664Sbms	const char *name;
319127664Sbms	const char *description;
320127664Sbms	int	dlt;
321127664Sbms};
322127664Sbms
323127664Sbms#define DLT_CHOICE(code, description) { #code, description, code }
324127664Sbms#define DLT_CHOICE_SENTINEL { NULL, NULL, 0 }
325127664Sbms
326127664Sbmsstatic struct dlt_choice dlt_choices[] = {
327127664Sbms	DLT_CHOICE(DLT_NULL, "BSD loopback"),
328127664Sbms	DLT_CHOICE(DLT_EN10MB, "Ethernet"),
329127664Sbms	DLT_CHOICE(DLT_IEEE802, "Token ring"),
330127664Sbms	DLT_CHOICE(DLT_ARCNET, "ARCNET"),
331127664Sbms	DLT_CHOICE(DLT_SLIP, "SLIP"),
332127664Sbms	DLT_CHOICE(DLT_PPP, "PPP"),
333127664Sbms	DLT_CHOICE(DLT_FDDI, "FDDI"),
334147894Ssam	DLT_CHOICE(DLT_ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"),
335127664Sbms	DLT_CHOICE(DLT_RAW, "Raw IP"),
336127664Sbms	DLT_CHOICE(DLT_SLIP_BSDOS, "BSD/OS SLIP"),
337127664Sbms	DLT_CHOICE(DLT_PPP_BSDOS, "BSD/OS PPP"),
338127664Sbms	DLT_CHOICE(DLT_ATM_CLIP, "Linux Classical IP-over-ATM"),
339127664Sbms	DLT_CHOICE(DLT_PPP_SERIAL, "PPP over serial"),
340127664Sbms	DLT_CHOICE(DLT_PPP_ETHER, "PPPoE"),
341127664Sbms	DLT_CHOICE(DLT_C_HDLC, "Cisco HDLC"),
342127664Sbms	DLT_CHOICE(DLT_IEEE802_11, "802.11"),
343127664Sbms	DLT_CHOICE(DLT_FRELAY, "Frame Relay"),
344127664Sbms	DLT_CHOICE(DLT_LOOP, "OpenBSD loopback"),
345127664Sbms	DLT_CHOICE(DLT_ENC, "OpenBSD encapsulated IP"),
346127664Sbms	DLT_CHOICE(DLT_LINUX_SLL, "Linux cooked"),
347127664Sbms	DLT_CHOICE(DLT_LTALK, "Localtalk"),
348127664Sbms	DLT_CHOICE(DLT_PFLOG, "OpenBSD pflog file"),
349127664Sbms	DLT_CHOICE(DLT_PRISM_HEADER, "802.11 plus Prism header"),
350127664Sbms	DLT_CHOICE(DLT_IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
351127664Sbms	DLT_CHOICE(DLT_SUNATM, "Sun raw ATM"),
352127664Sbms	DLT_CHOICE(DLT_IEEE802_11_RADIO, "802.11 plus BSD radio information header"),
353127664Sbms	DLT_CHOICE(DLT_APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
354127664Sbms	DLT_CHOICE(DLT_ARCNET_LINUX, "Linux ARCNET"),
355146768Ssam	DLT_CHOICE(DLT_DOCSIS, "DOCSIS"),
356127664Sbms	DLT_CHOICE(DLT_LINUX_IRDA, "Linux IrDA"),
357127664Sbms	DLT_CHOICE(DLT_IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
358146768Ssam        DLT_CHOICE(DLT_SYMANTEC_FIREWALL, "Symantec Firewall"),
359146768Ssam        DLT_CHOICE(DLT_JUNIPER_ATM1, "Juniper ATM1 PIC"),
360146768Ssam        DLT_CHOICE(DLT_JUNIPER_ATM2, "Juniper ATM2 PIC"),
361146768Ssam        DLT_CHOICE(DLT_JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
362146768Ssam 	DLT_CHOICE(DLT_PPP_PPPD, "PPP for pppd, with direction flag"),
363146768Ssam 	DLT_CHOICE(DLT_JUNIPER_PPPOE, "Juniper PPPoE"),
364146768Ssam 	DLT_CHOICE(DLT_JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
365146768Ssam 	DLT_CHOICE(DLT_GPRS_LLC, "GPRS LLC"),
366146768Ssam 	DLT_CHOICE(DLT_GPF_T, "GPF-T"),
367146768Ssam 	DLT_CHOICE(DLT_GPF_F, "GPF-F"),
368146768Ssam 	DLT_CHOICE(DLT_JUNIPER_PIC_PEER, "Juniper PIC Peer"),
369146768Ssam 	DLT_CHOICE(DLT_JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
370146768Ssam	DLT_CHOICE(DLT_ERF_ETH,	"Ethernet with Endace ERF header"),
371146768Ssam	DLT_CHOICE(DLT_ERF_POS, "Packet-over-SONET with Endace ERF header"),
372147894Ssam        DLT_CHOICE(DLT_JUNIPER_GGSN, "Juniper GGSN PIC"),
373147894Ssam        DLT_CHOICE(DLT_JUNIPER_ES, "Juniper Encryption Services PIC"),
374147894Ssam        DLT_CHOICE(DLT_JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
375147894Ssam        DLT_CHOICE(DLT_JUNIPER_SERVICES, "Juniper Advanced Services PIC"),
376162012Ssam 	DLT_CHOICE(DLT_JUNIPER_MFR, "Juniper FRF.16 Frame Relay"),
377162012Ssam 	DLT_CHOICE(DLT_JUNIPER_ETHER, "Juniper Ethernet"),
378162012Ssam 	DLT_CHOICE(DLT_JUNIPER_PPP, "Juniper PPP"),
379162012Ssam 	DLT_CHOICE(DLT_JUNIPER_FRELAY, "Juniper Frame Relay"),
380162012Ssam 	DLT_CHOICE(DLT_JUNIPER_CHDLC, "Juniper C-HDLC"),
381127664Sbms	DLT_CHOICE_SENTINEL
382127664Sbms};
383127664Sbms
384127664Sbms/*
385127664Sbms * This array is designed for mapping upper and lower case letter
386127664Sbms * together for a case independent comparison.  The mappings are
387127664Sbms * based upon ascii character sequences.
388127664Sbms */
389127664Sbmsstatic const u_char charmap[] = {
390127664Sbms	(u_char)'\000', (u_char)'\001', (u_char)'\002', (u_char)'\003',
391127664Sbms	(u_char)'\004', (u_char)'\005', (u_char)'\006', (u_char)'\007',
392127664Sbms	(u_char)'\010', (u_char)'\011', (u_char)'\012', (u_char)'\013',
393127664Sbms	(u_char)'\014', (u_char)'\015', (u_char)'\016', (u_char)'\017',
394127664Sbms	(u_char)'\020', (u_char)'\021', (u_char)'\022', (u_char)'\023',
395127664Sbms	(u_char)'\024', (u_char)'\025', (u_char)'\026', (u_char)'\027',
396127664Sbms	(u_char)'\030', (u_char)'\031', (u_char)'\032', (u_char)'\033',
397127664Sbms	(u_char)'\034', (u_char)'\035', (u_char)'\036', (u_char)'\037',
398127664Sbms	(u_char)'\040', (u_char)'\041', (u_char)'\042', (u_char)'\043',
399127664Sbms	(u_char)'\044', (u_char)'\045', (u_char)'\046', (u_char)'\047',
400127664Sbms	(u_char)'\050', (u_char)'\051', (u_char)'\052', (u_char)'\053',
401127664Sbms	(u_char)'\054', (u_char)'\055', (u_char)'\056', (u_char)'\057',
402127664Sbms	(u_char)'\060', (u_char)'\061', (u_char)'\062', (u_char)'\063',
403127664Sbms	(u_char)'\064', (u_char)'\065', (u_char)'\066', (u_char)'\067',
404127664Sbms	(u_char)'\070', (u_char)'\071', (u_char)'\072', (u_char)'\073',
405127664Sbms	(u_char)'\074', (u_char)'\075', (u_char)'\076', (u_char)'\077',
406127664Sbms	(u_char)'\100', (u_char)'\141', (u_char)'\142', (u_char)'\143',
407127664Sbms	(u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
408127664Sbms	(u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
409127664Sbms	(u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
410127664Sbms	(u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
411127664Sbms	(u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
412127664Sbms	(u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\133',
413127664Sbms	(u_char)'\134', (u_char)'\135', (u_char)'\136', (u_char)'\137',
414127664Sbms	(u_char)'\140', (u_char)'\141', (u_char)'\142', (u_char)'\143',
415127664Sbms	(u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
416127664Sbms	(u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
417127664Sbms	(u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
418127664Sbms	(u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
419127664Sbms	(u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
420127664Sbms	(u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\173',
421127664Sbms	(u_char)'\174', (u_char)'\175', (u_char)'\176', (u_char)'\177',
422127664Sbms	(u_char)'\200', (u_char)'\201', (u_char)'\202', (u_char)'\203',
423127664Sbms	(u_char)'\204', (u_char)'\205', (u_char)'\206', (u_char)'\207',
424127664Sbms	(u_char)'\210', (u_char)'\211', (u_char)'\212', (u_char)'\213',
425127664Sbms	(u_char)'\214', (u_char)'\215', (u_char)'\216', (u_char)'\217',
426127664Sbms	(u_char)'\220', (u_char)'\221', (u_char)'\222', (u_char)'\223',
427127664Sbms	(u_char)'\224', (u_char)'\225', (u_char)'\226', (u_char)'\227',
428127664Sbms	(u_char)'\230', (u_char)'\231', (u_char)'\232', (u_char)'\233',
429127664Sbms	(u_char)'\234', (u_char)'\235', (u_char)'\236', (u_char)'\237',
430127664Sbms	(u_char)'\240', (u_char)'\241', (u_char)'\242', (u_char)'\243',
431127664Sbms	(u_char)'\244', (u_char)'\245', (u_char)'\246', (u_char)'\247',
432127664Sbms	(u_char)'\250', (u_char)'\251', (u_char)'\252', (u_char)'\253',
433127664Sbms	(u_char)'\254', (u_char)'\255', (u_char)'\256', (u_char)'\257',
434127664Sbms	(u_char)'\260', (u_char)'\261', (u_char)'\262', (u_char)'\263',
435127664Sbms	(u_char)'\264', (u_char)'\265', (u_char)'\266', (u_char)'\267',
436127664Sbms	(u_char)'\270', (u_char)'\271', (u_char)'\272', (u_char)'\273',
437127664Sbms	(u_char)'\274', (u_char)'\275', (u_char)'\276', (u_char)'\277',
438127664Sbms	(u_char)'\300', (u_char)'\341', (u_char)'\342', (u_char)'\343',
439127664Sbms	(u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347',
440127664Sbms	(u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353',
441127664Sbms	(u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357',
442127664Sbms	(u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363',
443127664Sbms	(u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367',
444127664Sbms	(u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\333',
445127664Sbms	(u_char)'\334', (u_char)'\335', (u_char)'\336', (u_char)'\337',
446127664Sbms	(u_char)'\340', (u_char)'\341', (u_char)'\342', (u_char)'\343',
447127664Sbms	(u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347',
448127664Sbms	(u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353',
449127664Sbms	(u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357',
450127664Sbms	(u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363',
451127664Sbms	(u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367',
452127664Sbms	(u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\373',
453127664Sbms	(u_char)'\374', (u_char)'\375', (u_char)'\376', (u_char)'\377',
454127664Sbms};
455127664Sbms
456109839Sfennerint
457127664Sbmspcap_strcasecmp(const char *s1, const char *s2)
458127664Sbms{
459127664Sbms	register const u_char	*cm = charmap,
460127664Sbms				*us1 = (u_char *)s1,
461127664Sbms				*us2 = (u_char *)s2;
462127664Sbms
463127664Sbms	while (cm[*us1] == cm[*us2++])
464127664Sbms		if (*us1++ == '\0')
465127664Sbms			return(0);
466127664Sbms	return (cm[*us1] - cm[*--us2]);
467127664Sbms}
468127664Sbms
469127664Sbmsint
470127664Sbmspcap_datalink_name_to_val(const char *name)
471127664Sbms{
472127664Sbms	int i;
473127664Sbms
474127664Sbms	for (i = 0; dlt_choices[i].name != NULL; i++) {
475127664Sbms		if (pcap_strcasecmp(dlt_choices[i].name + sizeof("DLT_") - 1,
476127664Sbms		    name) == 0)
477127664Sbms			return (dlt_choices[i].dlt);
478127664Sbms	}
479127664Sbms	return (-1);
480127664Sbms}
481127664Sbms
482127664Sbmsconst char *
483127664Sbmspcap_datalink_val_to_name(int dlt)
484127664Sbms{
485127664Sbms	int i;
486127664Sbms
487127664Sbms	for (i = 0; dlt_choices[i].name != NULL; i++) {
488127664Sbms		if (dlt_choices[i].dlt == dlt)
489127664Sbms			return (dlt_choices[i].name + sizeof("DLT_") - 1);
490127664Sbms	}
491127664Sbms	return (NULL);
492127664Sbms}
493127664Sbms
494127664Sbmsconst char *
495127664Sbmspcap_datalink_val_to_description(int dlt)
496127664Sbms{
497127664Sbms	int i;
498127664Sbms
499127664Sbms	for (i = 0; dlt_choices[i].name != NULL; i++) {
500127664Sbms		if (dlt_choices[i].dlt == dlt)
501127664Sbms			return (dlt_choices[i].description);
502127664Sbms	}
503127664Sbms	return (NULL);
504127664Sbms}
505127664Sbms
506127664Sbmsint
50717683Spstpcap_snapshot(pcap_t *p)
50817683Spst{
50917683Spst	return (p->snapshot);
51017683Spst}
51117683Spst
51217683Spstint
51317683Spstpcap_is_swapped(pcap_t *p)
51417683Spst{
51517683Spst	return (p->sf.swapped);
51617683Spst}
51717683Spst
51817683Spstint
51917683Spstpcap_major_version(pcap_t *p)
52017683Spst{
52117683Spst	return (p->sf.version_major);
52217683Spst}
52317683Spst
52417683Spstint
52517683Spstpcap_minor_version(pcap_t *p)
52617683Spst{
52717683Spst	return (p->sf.version_minor);
52817683Spst}
52917683Spst
53017683SpstFILE *
53117683Spstpcap_file(pcap_t *p)
53217683Spst{
53317683Spst	return (p->sf.rfile);
53417683Spst}
53517683Spst
53617683Spstint
53717683Spstpcap_fileno(pcap_t *p)
53817683Spst{
539127664Sbms#ifndef WIN32
54017683Spst	return (p->fd);
541127664Sbms#else
542127664Sbms	if (p->adapter != NULL)
543127664Sbms		return ((int)(DWORD)p->adapter->hFile);
544127664Sbms	else
545127664Sbms		return (-1);
546127664Sbms#endif
54717683Spst}
54817683Spst
549146768Ssam#if !defined(WIN32) && !defined(MSDOS)
550127664Sbmsint
551127664Sbmspcap_get_selectable_fd(pcap_t *p)
552127664Sbms{
553127664Sbms	return (p->selectable_fd);
554127664Sbms}
555127664Sbms#endif
556127664Sbms
55717683Spstvoid
55817683Spstpcap_perror(pcap_t *p, char *prefix)
55917683Spst{
56017683Spst	fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
56117683Spst}
56217683Spst
56317683Spstchar *
56417683Spstpcap_geterr(pcap_t *p)
56517683Spst{
56617683Spst	return (p->errbuf);
56717683Spst}
56817683Spst
569127664Sbmsint
570127664Sbmspcap_getnonblock(pcap_t *p, char *errbuf)
571127664Sbms{
572127664Sbms	return p->getnonblock_op(p, errbuf);
573127664Sbms}
574127664Sbms
57517683Spst/*
576127664Sbms * Get the current non-blocking mode setting, under the assumption that
577127664Sbms * it's just the standard POSIX non-blocking flag.
578127664Sbms *
579127664Sbms * We don't look at "p->nonblock", in case somebody tweaked the FD
580127664Sbms * directly.
58198530Sfenner */
582146768Ssam#if !defined(WIN32) && !defined(MSDOS)
58398530Sfennerint
584127664Sbmspcap_getnonblock_fd(pcap_t *p, char *errbuf)
58598530Sfenner{
58698530Sfenner	int fdflags;
58798530Sfenner
58898530Sfenner	fdflags = fcntl(p->fd, F_GETFL, 0);
58998530Sfenner	if (fdflags == -1) {
59098530Sfenner		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
59198530Sfenner		    pcap_strerror(errno));
59298530Sfenner		return (-1);
59398530Sfenner	}
59498530Sfenner	if (fdflags & O_NONBLOCK)
59598530Sfenner		return (1);
59698530Sfenner	else
59798530Sfenner		return (0);
59898530Sfenner}
599127664Sbms#endif
60098530Sfenner
60198530Sfennerint
60298530Sfennerpcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
60398530Sfenner{
604127664Sbms	return p->setnonblock_op(p, nonblock, errbuf);
605127664Sbms}
606127664Sbms
607146768Ssam#if !defined(WIN32) && !defined(MSDOS)
608127664Sbms/*
609127664Sbms * Set non-blocking mode, under the assumption that it's just the
610127664Sbms * standard POSIX non-blocking flag.  (This can be called by the
611127664Sbms * per-platform non-blocking-mode routine if that routine also
612127664Sbms * needs to do some additional work.)
613127664Sbms */
614127664Sbmsint
615127664Sbmspcap_setnonblock_fd(pcap_t *p, int nonblock, char *errbuf)
616127664Sbms{
61798530Sfenner	int fdflags;
61898530Sfenner
61998530Sfenner	fdflags = fcntl(p->fd, F_GETFL, 0);
62098530Sfenner	if (fdflags == -1) {
62198530Sfenner		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s",
62298530Sfenner		    pcap_strerror(errno));
62398530Sfenner		return (-1);
62498530Sfenner	}
62598530Sfenner	if (nonblock)
62698530Sfenner		fdflags |= O_NONBLOCK;
62798530Sfenner	else
62898530Sfenner		fdflags &= ~O_NONBLOCK;
62998530Sfenner	if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
63098530Sfenner		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s",
63198530Sfenner		    pcap_strerror(errno));
63298530Sfenner		return (-1);
63398530Sfenner	}
63498530Sfenner	return (0);
63598530Sfenner}
636127664Sbms#endif
63798530Sfenner
638127664Sbms#ifdef WIN32
63998530Sfenner/*
640127664Sbms * Generate a string for the last Win32-specific error (i.e. an error generated when
641127664Sbms * calling a Win32 API).
642127664Sbms * For errors occurred during standard C calls, we still use pcap_strerror()
643127664Sbms */
644127664Sbmschar *
645127664Sbmspcap_win32strerror(void)
646127664Sbms{
647127664Sbms	DWORD error;
648127664Sbms	static char errbuf[PCAP_ERRBUF_SIZE+1];
649127664Sbms	int errlen;
650146768Ssam	char *p;
651127664Sbms
652127664Sbms	error = GetLastError();
653127664Sbms	FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
654127664Sbms	    PCAP_ERRBUF_SIZE, NULL);
655127664Sbms
656127664Sbms	/*
657127664Sbms	 * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
658127664Sbms	 * message.  Get rid of it.
659127664Sbms	 */
660127664Sbms	errlen = strlen(errbuf);
661127664Sbms	if (errlen >= 2) {
662127664Sbms		errbuf[errlen - 1] = '\0';
663127664Sbms		errbuf[errlen - 2] = '\0';
664127664Sbms	}
665146768Ssam	p = strchr(errbuf, '\0');
666146768Ssam	snprintf (p, sizeof(errbuf)-(p-errbuf), " (%lu)", error);
667127664Sbms	return (errbuf);
668127664Sbms}
669127664Sbms#endif
670127664Sbms
671127664Sbms/*
67217683Spst * Not all systems have strerror().
67317683Spst */
67417683Spstchar *
67517683Spstpcap_strerror(int errnum)
67617683Spst{
67717683Spst#ifdef HAVE_STRERROR
67817683Spst	return (strerror(errnum));
67917683Spst#else
68017683Spst	extern int sys_nerr;
68117683Spst	extern const char *const sys_errlist[];
68217683Spst	static char ebuf[20];
68317683Spst
68417683Spst	if ((unsigned int)errnum < sys_nerr)
68517683Spst		return ((char *)sys_errlist[errnum]);
68675107Sfenner	(void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
68717683Spst	return(ebuf);
68817683Spst#endif
68917683Spst}
69017683Spst
691127664Sbmsint
692127664Sbmspcap_setfilter(pcap_t *p, struct bpf_program *fp)
693127664Sbms{
694127664Sbms	return p->setfilter_op(p, fp);
695127664Sbms}
696127664Sbms
697147894Ssam/*
698147894Ssam * Set direction flag, which controls whether we accept only incoming
699147894Ssam * packets, only outgoing packets, or both.
700147894Ssam * Note that, depending on the platform, some or all direction arguments
701147894Ssam * might not be supported.
702147894Ssam */
703127664Sbmsint
704162012Ssampcap_setdirection(pcap_t *p, pcap_direction_t d)
705147894Ssam{
706147894Ssam	if (p->setdirection_op == NULL) {
707147894Ssam		snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
708147894Ssam		    "Setting direction is not implemented on this platform");
709147894Ssam		return -1;
710147894Ssam	} else
711147894Ssam		return p->setdirection_op(p, d);
712147894Ssam}
713147894Ssam
714147894Ssamint
715127664Sbmspcap_stats(pcap_t *p, struct pcap_stat *ps)
716127664Sbms{
717127664Sbms	return p->stats_op(p, ps);
718127664Sbms}
719127664Sbms
720127664Sbmsstatic int
721146768Ssampcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_)
722127664Sbms{
723127664Sbms	snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
724127664Sbms	    "Statistics aren't available from a pcap_open_dead pcap_t");
725127664Sbms	return (-1);
726127664Sbms}
727127664Sbms
728146768Ssamvoid
729146768Ssampcap_close_common(pcap_t *p)
730146768Ssam{
731146768Ssam	if (p->buffer != NULL)
732146768Ssam		free(p->buffer);
733146768Ssam#if !defined(WIN32) && !defined(MSDOS)
734146768Ssam	if (p->fd >= 0)
735146768Ssam		close(p->fd);
736146768Ssam#endif
737146768Ssam}
738146768Ssam
739127664Sbmsstatic void
740146768Ssampcap_close_dead(pcap_t *p _U_)
741127664Sbms{
742127664Sbms	/* Nothing to do. */
743127664Sbms}
744127664Sbms
74575107Sfennerpcap_t *
74675107Sfennerpcap_open_dead(int linktype, int snaplen)
74775107Sfenner{
74875107Sfenner	pcap_t *p;
74975107Sfenner
75075107Sfenner	p = malloc(sizeof(*p));
75175107Sfenner	if (p == NULL)
75275107Sfenner		return NULL;
75375107Sfenner	memset (p, 0, sizeof(*p));
75475107Sfenner	p->snapshot = snaplen;
75575107Sfenner	p->linktype = linktype;
756127664Sbms	p->stats_op = pcap_stats_dead;
757127664Sbms	p->close_op = pcap_close_dead;
75875107Sfenner	return p;
75975107Sfenner}
76075107Sfenner
761146768Ssam/*
762146768Ssam * API compatible with WinPcap's "send a packet" routine - returns -1
763146768Ssam * on error, 0 otherwise.
764146768Ssam *
765146768Ssam * XXX - what if we get a short write?
766146768Ssam */
767146768Ssamint
768146768Ssampcap_sendpacket(pcap_t *p, const u_char *buf, int size)
769146768Ssam{
770146768Ssam	if (p->inject_op(p, buf, size) == -1)
771146768Ssam		return (-1);
772146768Ssam	return (0);
773146768Ssam}
774146768Ssam
775146768Ssam/*
776146768Ssam * API compatible with OpenBSD's "send a packet" routine - returns -1 on
777146768Ssam * error, number of bytes written otherwise.
778146768Ssam */
779146768Ssamint
780146768Ssampcap_inject(pcap_t *p, const void *buf, size_t size)
781146768Ssam{
782146768Ssam	return (p->inject_op(p, buf, size));
783146768Ssam}
784146768Ssam
78517683Spstvoid
78617683Spstpcap_close(pcap_t *p)
78717683Spst{
788127664Sbms	p->close_op(p);
789109839Sfenner	if (p->dlt_list != NULL)
790109839Sfenner		free(p->dlt_list);
79175107Sfenner	pcap_freecode(&p->fcode);
79217683Spst	free(p);
79317683Spst}
794127664Sbms
795127664Sbms/*
796127664Sbms * We make the version string static, and return a pointer to it, rather
797127664Sbms * than exporting the version string directly.  On at least some UNIXes,
798127664Sbms * if you import data from a shared library into an program, the data is
799127664Sbms * bound into the program binary, so if the string in the version of the
800127664Sbms * library with which the program was linked isn't the same as the
801127664Sbms * string in the version of the library with which the program is being
802127664Sbms * run, various undesirable things may happen (warnings, the string
803127664Sbms * being the one from the version of the library with which the program
804127664Sbms * was linked, or even weirder things, such as the string being the one
805127664Sbms * from the library but being truncated).
806127664Sbms */
807146768Ssam#ifdef HAVE_VERSION_H
808146768Ssam#include "version.h"
809146768Ssam#else
810146768Ssamstatic const char pcap_version_string[] = "libpcap version 0.9[.x]";
811146768Ssam#endif
812146768Ssam
813127664Sbms#ifdef WIN32
814127664Sbms/*
815127664Sbms * XXX - it'd be nice if we could somehow generate the WinPcap and libpcap
816127664Sbms * version numbers when building WinPcap.  (It'd be nice to do so for
817127664Sbms * the packet.dll version number as well.)
818127664Sbms */
819146768Ssamstatic const char wpcap_version_string[] = "3.1";
820127664Sbmsstatic const char pcap_version_string_fmt[] =
821146768Ssam    "WinPcap version %s, based on %s";
822127664Sbmsstatic const char pcap_version_string_packet_dll_fmt[] =
823146768Ssam    "WinPcap version %s (packet.dll version %s), based on %s";
824146768Ssamstatic char *full_pcap_version_string;
825127664Sbms
826127664Sbmsconst char *
827127664Sbmspcap_lib_version(void)
828127664Sbms{
829127664Sbms	char *packet_version_string;
830146768Ssam	size_t full_pcap_version_string_len;
831127664Sbms
832146768Ssam	if (full_pcap_version_string == NULL) {
833127664Sbms		/*
834127664Sbms		 * Generate the version string.
835127664Sbms		 */
836127664Sbms		packet_version_string = PacketGetVersion();
837127664Sbms		if (strcmp(wpcap_version_string, packet_version_string) == 0) {
838127664Sbms			/*
839127664Sbms			 * WinPcap version string and packet.dll version
840127664Sbms			 * string are the same; just report the WinPcap
841127664Sbms			 * version.
842127664Sbms			 */
843146768Ssam			full_pcap_version_string_len =
844146768Ssam			    (sizeof pcap_version_string_fmt - 4) +
845146768Ssam			    strlen(wpcap_version_string) +
846146768Ssam			    strlen(pcap_version_string);
847146768Ssam			full_pcap_version_string =
848146768Ssam			    malloc(full_pcap_version_string_len);
849146768Ssam			sprintf(full_pcap_version_string,
850146768Ssam			    pcap_version_string_fmt, wpcap_version_string,
851146768Ssam			    pcap_version_string);
852127664Sbms		} else {
853127664Sbms			/*
854127664Sbms			 * WinPcap version string and packet.dll version
855127664Sbms			 * string are different; that shouldn't be the
856127664Sbms			 * case (the two libraries should come from the
857127664Sbms			 * same version of WinPcap), so we report both
858127664Sbms			 * versions.
859127664Sbms			 */
860146768Ssam			full_pcap_version_string_len =
861146768Ssam			    (sizeof pcap_version_string_packet_dll_fmt - 6) +
862127664Sbms			    strlen(wpcap_version_string) +
863146768Ssam			    strlen(packet_version_string) +
864146768Ssam			    strlen(pcap_version_string);
865146768Ssam			full_pcap_version_string = malloc(full_pcap_version_string_len);
866146768Ssam
867146768Ssam			sprintf(full_pcap_version_string,
868127664Sbms			    pcap_version_string_packet_dll_fmt,
869146768Ssam			    wpcap_version_string, packet_version_string,
870146768Ssam			    pcap_version_string);
871127664Sbms		}
872127664Sbms	}
873146768Ssam	return (full_pcap_version_string);
874127664Sbms}
875127664Sbms
876146768Ssam#elif defined(MSDOS)
877146768Ssam
878146768Ssamstatic char *full_pcap_version_string;
879146768Ssam
880127664Sbmsconst char *
881146768Ssampcap_lib_version (void)
882146768Ssam{
883146768Ssam	char *packet_version_string;
884146768Ssam	size_t full_pcap_version_string_len;
885146768Ssam	static char dospfx[] = "DOS-";
886146768Ssam
887146768Ssam	if (full_pcap_version_string == NULL) {
888146768Ssam		/*
889146768Ssam		 * Generate the version string.
890146768Ssam		 */
891146768Ssam		full_pcap_version_string_len =
892146768Ssam		    sizeof dospfx + strlen(pcap_version_string);
893146768Ssam		full_pcap_version_string =
894146768Ssam		    malloc(full_pcap_version_string_len);
895146768Ssam		strcpy(full_pcap_version_string, dospfx);
896146768Ssam		strcat(full_pcap_version_string, pcap_version_string);
897146768Ssam	}
898146768Ssam	return (full_pcap_version_string);
899146768Ssam}
900146768Ssam
901146768Ssam#else /* UN*X */
902146768Ssam
903146768Ssamconst char *
904127664Sbmspcap_lib_version(void)
905127664Sbms{
906127664Sbms	return (pcap_version_string);
907127664Sbms}
908127664Sbms#endif
909