1/*
2 * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
3 * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the Politecnico di Torino, CACE Technologies
16 * nor the names of its contributors may be used to endorse or promote
17 * products derived from this software without specific prior written
18 * permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34#ifndef lint
35static const char rcsid[] _U_ =
36    "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.42 2008-05-21 22:15:25 gianluca Exp $ (LBL)";
37#endif
38
39#include <pcap-int.h>
40#include <Packet32.h>
41#ifdef __MINGW32__
42#ifdef __MINGW64__
43#include <ntddndis.h>
44#else  /*__MINGW64__*/
45#include <ddk/ntddndis.h>
46#include <ddk/ndis.h>
47#endif /*__MINGW64__*/
48#else /*__MINGW32__*/
49#include <ntddndis.h>
50#endif /*__MINGW32__*/
51#ifdef HAVE_DAG_API
52#include <dagnew.h>
53#include <dagapi.h>
54#endif /* HAVE_DAG_API */
55#ifdef __MINGW32__
56int* _errno();
57#define errno (*_errno())
58#endif /* __MINGW32__ */
59
60static int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *);
61static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
62static int pcap_getnonblock_win32(pcap_t *, char *);
63static int pcap_setnonblock_win32(pcap_t *, int, char *);
64
65/*dimension of the buffer in the pcap_t structure*/
66#define	WIN32_DEFAULT_USER_BUFFER_SIZE 256000
67
68/*dimension of the buffer in the kernel driver NPF */
69#define	WIN32_DEFAULT_KERNEL_BUFFER_SIZE 1000000
70
71/* Equivalent to ntohs(), but a lot faster under Windows */
72#define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
73
74/*
75 * Private data for capturing on WinPcap devices.
76 */
77struct pcap_win {
78	int nonblock;
79
80#ifdef HAVE_DAG_API
81	int	dag_fcs_bits;	/* Number of checksum bits from link layer */
82#endif
83};
84
85/*
86 * Header that the WinPcap driver associates to the packets.
87 * Once was in bpf.h
88 */
89struct bpf_hdr {
90	struct timeval	bh_tstamp;	/* time stamp */
91	bpf_u_int32	bh_caplen;	/* length of captured portion */
92	bpf_u_int32	bh_datalen;	/* original length of packet */
93	u_short		bh_hdrlen;	/* length of bpf header (this struct
94					   plus alignment padding) */
95};
96
97CRITICAL_SECTION g_PcapCompileCriticalSection;
98
99BOOL WINAPI DllMain(
100  HANDLE hinstDLL,
101  DWORD dwReason,
102  LPVOID lpvReserved
103)
104{
105	if (dwReason == DLL_PROCESS_ATTACH)
106	{
107		InitializeCriticalSection(&g_PcapCompileCriticalSection);
108	}
109
110	return TRUE;
111}
112
113/* Start winsock */
114int
115wsockinit()
116{
117	WORD wVersionRequested;
118	WSADATA wsaData;
119	int err;
120	wVersionRequested = MAKEWORD( 1, 1);
121	err = WSAStartup( wVersionRequested, &wsaData );
122	if ( err != 0 )
123	{
124		return -1;
125	}
126	return 0;
127}
128
129
130static int
131pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
132{
133
134	if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){
135		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror());
136		return -1;
137	}
138
139	return 0;
140}
141
142/* Set the dimension of the kernel-level capture buffer */
143static int
144pcap_setbuff_win32(pcap_t *p, int dim)
145{
146	if(PacketSetBuff(p->adapter,dim)==FALSE)
147	{
148		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
149		return -1;
150	}
151	return 0;
152}
153
154/* Set the driver working mode */
155static int
156pcap_setmode_win32(pcap_t *p, int mode)
157{
158	if(PacketSetMode(p->adapter,mode)==FALSE)
159	{
160		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
161		return -1;
162	}
163
164	return 0;
165}
166
167/*set the minimum amount of data that will release a read call*/
168static int
169pcap_setmintocopy_win32(pcap_t *p, int size)
170{
171	if(PacketSetMinToCopy(p->adapter, size)==FALSE)
172	{
173		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
174		return -1;
175	}
176	return 0;
177}
178
179/*return the Adapter for a pcap_t*/
180static Adapter *
181pcap_getadapter_win32(pcap_t *p)
182{
183	return p->adapter;
184}
185
186static int
187pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
188{
189	int cc;
190	int n = 0;
191	register u_char *bp, *ep;
192
193	cc = p->cc;
194	if (p->cc == 0) {
195		/*
196		 * Has "pcap_breakloop()" been called?
197		 */
198		if (p->break_loop) {
199			/*
200			 * Yes - clear the flag that indicates that it
201			 * has, and return -2 to indicate that we were
202			 * told to break out of the loop.
203			 */
204			p->break_loop = 0;
205			return (-2);
206		}
207
208	    /* capture the packets */
209		if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){
210			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
211			return (-1);
212		}
213
214		cc = p->Packet->ulBytesReceived;
215
216		bp = p->Packet->Buffer;
217	}
218	else
219		bp = p->bp;
220
221	/*
222	 * Loop through each packet.
223	 */
224#define bhp ((struct bpf_hdr *)bp)
225	ep = bp + cc;
226	while (1) {
227		register int caplen, hdrlen;
228
229		/*
230		 * Has "pcap_breakloop()" been called?
231		 * If so, return immediately - if we haven't read any
232		 * packets, clear the flag and return -2 to indicate
233		 * that we were told to break out of the loop, otherwise
234		 * leave the flag set, so that the *next* call will break
235		 * out of the loop without having read any packets, and
236		 * return the number of packets we've processed so far.
237		 */
238		if (p->break_loop) {
239			if (n == 0) {
240				p->break_loop = 0;
241				return (-2);
242			} else {
243				p->bp = bp;
244				p->cc = ep - bp;
245				return (n);
246			}
247		}
248		if (bp >= ep)
249			break;
250
251		caplen = bhp->bh_caplen;
252		hdrlen = bhp->bh_hdrlen;
253
254		/*
255		 * XXX A bpf_hdr matches a pcap_pkthdr.
256		 */
257		(*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
258		bp += Packet_WORDALIGN(caplen + hdrlen);
259		if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
260			p->bp = bp;
261			p->cc = ep - bp;
262			return (n);
263		}
264	}
265#undef bhp
266	p->cc = 0;
267	return (n);
268}
269
270#ifdef HAVE_DAG_API
271static int
272pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
273{
274	struct pcap_win *pw = p->priv;
275	u_char *dp = NULL;
276	int	packet_len = 0, caplen = 0;
277	struct pcap_pkthdr	pcap_header;
278	u_char *endofbuf;
279	int n = 0;
280	dag_record_t *header;
281	unsigned erf_record_len;
282	ULONGLONG ts;
283	int cc;
284	unsigned swt;
285	unsigned dfp = p->adapter->DagFastProcess;
286
287	cc = p->cc;
288	if (cc == 0) /* Get new packets only if we have processed all the ones of the previous read */
289	{
290	    /* Get new packets from the network */
291		if(PacketReceivePacket(p->adapter, p->Packet, TRUE)==FALSE){
292			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
293			return (-1);
294		}
295
296		cc = p->Packet->ulBytesReceived;
297		if(cc == 0)
298			/* The timeout has expired but we no packets arrived */
299			return 0;
300		header = (dag_record_t*)p->adapter->DagBuffer;
301	}
302	else
303		header = (dag_record_t*)p->bp;
304
305	endofbuf = (char*)header + cc;
306
307	/*
308	 * Cycle through the packets
309	 */
310	do
311	{
312		erf_record_len = SWAPS(header->rlen);
313		if((char*)header + erf_record_len > endofbuf)
314			break;
315
316		/* Increase the number of captured packets */
317		pw->stat.ps_recv++;
318
319		/* Find the beginning of the packet */
320		dp = ((u_char *)header) + dag_record_size;
321
322		/* Determine actual packet len */
323		switch(header->type)
324		{
325		case TYPE_ATM:
326			packet_len = ATM_SNAPLEN;
327			caplen = ATM_SNAPLEN;
328			dp += 4;
329
330			break;
331
332		case TYPE_ETH:
333			swt = SWAPS(header->wlen);
334			packet_len = swt - (pw->dag_fcs_bits);
335			caplen = erf_record_len - dag_record_size - 2;
336			if (caplen > packet_len)
337			{
338				caplen = packet_len;
339			}
340			dp += 2;
341
342			break;
343
344		case TYPE_HDLC_POS:
345			swt = SWAPS(header->wlen);
346			packet_len = swt - (pw->dag_fcs_bits);
347			caplen = erf_record_len - dag_record_size;
348			if (caplen > packet_len)
349			{
350				caplen = packet_len;
351			}
352
353			break;
354		}
355
356		if(caplen > p->snapshot)
357			caplen = p->snapshot;
358
359		/*
360		 * Has "pcap_breakloop()" been called?
361		 * If so, return immediately - if we haven't read any
362		 * packets, clear the flag and return -2 to indicate
363		 * that we were told to break out of the loop, otherwise
364		 * leave the flag set, so that the *next* call will break
365		 * out of the loop without having read any packets, and
366		 * return the number of packets we've processed so far.
367		 */
368		if (p->break_loop)
369		{
370			if (n == 0)
371			{
372				p->break_loop = 0;
373				return (-2);
374			}
375			else
376			{
377				p->bp = (char*)header;
378				p->cc = endofbuf - (char*)header;
379				return (n);
380			}
381		}
382
383		if(!dfp)
384		{
385			/* convert between timestamp formats */
386			ts = header->ts;
387			pcap_header.ts.tv_sec = (int)(ts >> 32);
388			ts = (ts & 0xffffffffi64) * 1000000;
389			ts += 0x80000000; /* rounding */
390			pcap_header.ts.tv_usec = (int)(ts >> 32);
391			if (pcap_header.ts.tv_usec >= 1000000) {
392				pcap_header.ts.tv_usec -= 1000000;
393				pcap_header.ts.tv_sec++;
394			}
395		}
396
397		/* No underlaying filtering system. We need to filter on our own */
398		if (p->fcode.bf_insns)
399		{
400			if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0)
401			{
402				/* Move to next packet */
403				header = (dag_record_t*)((char*)header + erf_record_len);
404				continue;
405			}
406		}
407
408		/* Fill the header for the user suppplied callback function */
409		pcap_header.caplen = caplen;
410		pcap_header.len = packet_len;
411
412		/* Call the callback function */
413		(*callback)(user, &pcap_header, dp);
414
415		/* Move to next packet */
416		header = (dag_record_t*)((char*)header + erf_record_len);
417
418		/* Stop if the number of packets requested by user has been reached*/
419		if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
420		{
421			p->bp = (char*)header;
422			p->cc = endofbuf - (char*)header;
423			return (n);
424		}
425	}
426	while((u_char*)header < endofbuf);
427
428  return 1;
429}
430#endif /* HAVE_DAG_API */
431
432/* Send a packet to the network */
433static int
434pcap_inject_win32(pcap_t *p, const void *buf, size_t size){
435	LPPACKET PacketToSend;
436
437	PacketToSend=PacketAllocatePacket();
438
439	if (PacketToSend == NULL)
440	{
441		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed");
442		return -1;
443	}
444
445	PacketInitPacket(PacketToSend,(PVOID)buf,size);
446	if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
447		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
448		PacketFreePacket(PacketToSend);
449		return -1;
450	}
451
452	PacketFreePacket(PacketToSend);
453
454	/*
455	 * We assume it all got sent if "PacketSendPacket()" succeeded.
456	 * "pcap_inject()" is expected to return the number of bytes
457	 * sent.
458	 */
459	return size;
460}
461
462static void
463pcap_cleanup_win32(pcap_t *p)
464{
465	if (p->adapter != NULL) {
466		PacketCloseAdapter(p->adapter);
467		p->adapter = NULL;
468	}
469	if (p->Packet) {
470		PacketFreePacket(p->Packet);
471		p->Packet = NULL;
472	}
473	pcap_cleanup_live_common(p);
474}
475
476static int
477pcap_activate_win32(pcap_t *p)
478{
479	struct pcap_win *pw = p->priv;
480	NetType type;
481
482	if (p->opt.rfmon) {
483		/*
484		 * No monitor mode on Windows.  It could be done on
485		 * Vista with drivers that support the native 802.11
486		 * mechanism and monitor mode.
487		 */
488		return (PCAP_ERROR_RFMON_NOTSUP);
489	}
490
491	/* Init WinSock */
492	wsockinit();
493
494	p->adapter = PacketOpenAdapter(p->opt.source);
495
496	if (p->adapter == NULL)
497	{
498		/* Adapter detected but we are not able to open it. Return failure. */
499		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
500		return PCAP_ERROR;
501	}
502
503	/*get network type*/
504	if(PacketGetNetType (p->adapter,&type) == FALSE)
505	{
506		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
507		goto bad;
508	}
509
510	/*Set the linktype*/
511	switch (type.LinkType)
512	{
513	case NdisMediumWan:
514		p->linktype = DLT_EN10MB;
515		break;
516
517	case NdisMedium802_3:
518		p->linktype = DLT_EN10MB;
519		/*
520		 * This is (presumably) a real Ethernet capture; give it a
521		 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
522		 * that an application can let you choose it, in case you're
523		 * capturing DOCSIS traffic that a Cisco Cable Modem
524		 * Termination System is putting out onto an Ethernet (it
525		 * doesn't put an Ethernet header onto the wire, it puts raw
526		 * DOCSIS frames out on the wire inside the low-level
527		 * Ethernet framing).
528		 */
529		p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
530		/*
531		 * If that fails, just leave the list empty.
532		 */
533		if (p->dlt_list != NULL) {
534			p->dlt_list[0] = DLT_EN10MB;
535			p->dlt_list[1] = DLT_DOCSIS;
536			p->dlt_count = 2;
537		}
538		break;
539
540	case NdisMediumFddi:
541		p->linktype = DLT_FDDI;
542		break;
543
544	case NdisMedium802_5:
545		p->linktype = DLT_IEEE802;
546		break;
547
548	case NdisMediumArcnetRaw:
549		p->linktype = DLT_ARCNET;
550		break;
551
552	case NdisMediumArcnet878_2:
553		p->linktype = DLT_ARCNET;
554		break;
555
556	case NdisMediumAtm:
557		p->linktype = DLT_ATM_RFC1483;
558		break;
559
560	case NdisMediumCHDLC:
561		p->linktype = DLT_CHDLC;
562		break;
563
564	case NdisMediumPPPSerial:
565		p->linktype = DLT_PPP_SERIAL;
566		break;
567
568	case NdisMediumNull:
569		p->linktype = DLT_NULL;
570		break;
571
572	case NdisMediumBare80211:
573		p->linktype = DLT_IEEE802_11;
574		break;
575
576	case NdisMediumRadio80211:
577		p->linktype = DLT_IEEE802_11_RADIO;
578		break;
579
580	case NdisMediumPpi:
581		p->linktype = DLT_PPI;
582		break;
583
584	default:
585		p->linktype = DLT_EN10MB;			/*an unknown adapter is assumed to be ethernet*/
586		break;
587	}
588
589	/* Set promiscuous mode */
590	if (p->opt.promisc)
591	{
592
593		if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE)
594		{
595			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
596			goto bad;
597		}
598	}
599	else
600	{
601		if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE)
602		{
603			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
604			goto bad;
605		}
606	}
607
608	/* Set the buffer size */
609	p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE;
610
611	/* allocate Packet structure used during the capture */
612	if((p->Packet = PacketAllocatePacket())==NULL)
613	{
614		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
615		goto bad;
616	}
617
618	if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD))
619	{
620	/*
621	 * Traditional Adapter
622	 */
623		/*
624		 * If the buffer size wasn't explicitly set, default to
625		 * WIN32_DEFAULT_USER_BUFFER_SIZE.
626		 */
627	 	if (p->opt.buffer_size == 0)
628	 		p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE;
629
630		if(PacketSetBuff(p->adapter,p->opt.buffer_size)==FALSE)
631		{
632			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
633			goto bad;
634		}
635
636		p->buffer = (u_char *)malloc(p->bufsize);
637		if (p->buffer == NULL)
638		{
639			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
640			goto bad;
641		}
642
643		PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
644
645		if (p-opt.immediate)
646		{
647			/* tell the driver to copy the buffer as soon as data arrives */
648			if(PacketSetMinToCopy(p->adapter,0)==FALSE)
649			{
650				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
651				goto bad;
652			}
653		}
654		else
655		{
656			/* tell the driver to copy the buffer only if it contains at least 16K */
657			if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
658			{
659				snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
660				goto bad;
661			}
662		}
663	}
664	else
665#ifdef HAVE_DAG_API
666	{
667	/*
668	 * Dag Card
669	 */
670		LONG	status;
671		HKEY	dagkey;
672		DWORD	lptype;
673		DWORD	lpcbdata;
674		int		postype = 0;
675		char	keyname[512];
676
677		snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
678			"SYSTEM\\CurrentControlSet\\Services\\DAG",
679			strstr(_strlwr(p->opt.source), "dag"));
680		do
681		{
682			status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey);
683			if(status != ERROR_SUCCESS)
684				break;
685
686			status = RegQueryValueEx(dagkey,
687				"PosType",
688				NULL,
689				&lptype,
690				(char*)&postype,
691				&lpcbdata);
692
693			if(status != ERROR_SUCCESS)
694			{
695				postype = 0;
696			}
697
698			RegCloseKey(dagkey);
699		}
700		while(FALSE);
701
702
703		p->snapshot = PacketSetSnapLen(p->adapter, snaplen);
704
705		/* Set the length of the FCS associated to any packet. This value
706		 * will be subtracted to the packet length */
707		pw->dag_fcs_bits = p->adapter->DagFcsLen;
708	}
709#else
710	goto bad;
711#endif /* HAVE_DAG_API */
712
713	PacketSetReadTimeout(p->adapter, p->opt.timeout);
714
715#ifdef HAVE_DAG_API
716	if(p->adapter->Flags & INFO_FLAG_DAG_CARD)
717	{
718		/* install dag specific handlers for read and setfilter */
719		p->read_op = pcap_read_win32_dag;
720		p->setfilter_op = pcap_setfilter_win32_dag;
721	}
722	else
723	{
724#endif /* HAVE_DAG_API */
725		/* install traditional npf handlers for read and setfilter */
726		p->read_op = pcap_read_win32_npf;
727		p->setfilter_op = pcap_setfilter_win32_npf;
728#ifdef HAVE_DAG_API
729	}
730#endif /* HAVE_DAG_API */
731	p->setdirection_op = NULL;	/* Not implemented. */
732	    /* XXX - can this be implemented on some versions of Windows? */
733	p->inject_op = pcap_inject_win32;
734	p->set_datalink_op = NULL;	/* can't change data link type */
735	p->getnonblock_op = pcap_getnonblock_win32;
736	p->setnonblock_op = pcap_setnonblock_win32;
737	p->stats_op = pcap_stats_win32;
738	p->setbuff_op = pcap_setbuff_win32;
739	p->setmode_op = pcap_setmode_win32;
740	p->setmintocopy_op = pcap_setmintocopy_win32;
741	p->getadapter_op = pcap_getadapter_win32;
742	p->cleanup_op = pcap_cleanup_win32;
743
744	return (0);
745bad:
746	pcap_cleanup_win32(p);
747	return (PCAP_ERROR);
748}
749
750pcap_t *
751pcap_create_interface(const char *device, char *ebuf)
752{
753	pcap_t *p;
754
755	if (strlen(device) == 1)
756	{
757		/*
758		 * It's probably a unicode string
759		 * Convert to ascii and pass it to pcap_create_common
760		 *
761		 * This wonderful hack is needed because pcap_lookupdev still returns
762		 * unicode strings, and it's used by windump when no device is specified
763		 * in the command line
764		 */
765		size_t length;
766		char* deviceAscii;
767
768		length = wcslen((wchar_t*)device);
769
770		deviceAscii = (char*)malloc(length + 1);
771
772		if (deviceAscii == NULL)
773		{
774			snprintf(ebuf, PCAP_ERRBUF_SIZE, "Malloc failed");
775			return NULL;
776		}
777
778		snprintf(deviceAscii, length + 1, "%ws", (wchar_t*)device);
779		p = pcap_create_common(deviceAscii, ebuf, sizeof (struct pcap_win));
780		free(deviceAscii);
781	}
782	else
783	{
784		p = pcap_create_common(device, ebuf, sizeof (struct pcap_win));
785	}
786
787	if (p == NULL)
788		return (NULL);
789
790	p->activate_op = pcap_activate_win32;
791	return (p);
792}
793
794static int
795pcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp)
796{
797	if(PacketSetBpf(p->adapter,fp)==FALSE){
798		/*
799		 * Kernel filter not installed.
800		 * XXX - fall back on userland filtering, as is done
801		 * on other platforms?
802		 */
803		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror());
804		return (-1);
805	}
806
807	/*
808	 * Discard any previously-received packets, as they might have
809	 * passed whatever filter was formerly in effect, but might
810	 * not pass this filter (BIOCSETF discards packets buffered
811	 * in the kernel, so you can lose packets in any case).
812	 */
813	p->cc = 0;
814	return (0);
815}
816
817/*
818 * We filter at user level, since the kernel driver does't process the packets
819 */
820static int
821pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) {
822
823	if(!fp)
824	{
825		strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
826		return -1;
827	}
828
829	/* Install a user level filter */
830	if (install_bpf_program(p, fp) < 0)
831	{
832		snprintf(p->errbuf, sizeof(p->errbuf),
833			"setfilter, unable to install the filter: %s", pcap_strerror(errno));
834		return -1;
835	}
836
837	return (0);
838}
839
840static int
841pcap_getnonblock_win32(pcap_t *p, char *errbuf)
842{
843	struct pcap_win *pw = p->priv;
844
845	/*
846	 * XXX - if there were a PacketGetReadTimeout() call, we
847	 * would use it, and return 1 if the timeout is -1
848	 * and 0 otherwise.
849	 */
850	return (pw->nonblock);
851}
852
853static int
854pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
855{
856	struct pcap_win *pw = p->priv;
857	int newtimeout;
858
859	if (nonblock) {
860		/*
861		 * Set the read timeout to -1 for non-blocking mode.
862		 */
863		newtimeout = -1;
864	} else {
865		/*
866		 * Restore the timeout set when the device was opened.
867		 * (Note that this may be -1, in which case we're not
868		 * really leaving non-blocking mode.)
869		 */
870		newtimeout = p->opt.timeout;
871	}
872	if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
873		snprintf(errbuf, PCAP_ERRBUF_SIZE,
874		    "PacketSetReadTimeout: %s", pcap_win32strerror());
875		return (-1);
876	}
877	pw->nonblock = (newtimeout == -1);
878	return (0);
879}
880
881/*platform-dependent routine to add devices other than NDIS interfaces*/
882int
883pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
884{
885	return (0);
886}
887