1127664Sbms/*
2172677Smlaier * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
3190225Srpaulo * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
4127664Sbms * All rights reserved.
5127664Sbms *
6127664Sbms * Redistribution and use in source and binary forms, with or without
7127664Sbms * modification, are permitted provided that the following conditions
8127664Sbms * are met:
9127664Sbms *
10127664Sbms * 1. Redistributions of source code must retain the above copyright
11127664Sbms * notice, this list of conditions and the following disclaimer.
12127664Sbms * 2. Redistributions in binary form must reproduce the above copyright
13127664Sbms * notice, this list of conditions and the following disclaimer in the
14127664Sbms * documentation and/or other materials provided with the distribution.
15172677Smlaier * 3. Neither the name of the Politecnico di Torino, CACE Technologies
16172677Smlaier * nor the names of its contributors may be used to endorse or promote
17172677Smlaier * products derived from this software without specific prior written
18172677Smlaier * permission.
19127664Sbms *
20127664Sbms * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21127664Sbms * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22127664Sbms * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23127664Sbms * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24127664Sbms * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25127664Sbms * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26127664Sbms * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27127664Sbms * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28127664Sbms * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29127664Sbms * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30127664Sbms * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31127664Sbms *
32127664Sbms */
33127664Sbms
34127664Sbms#ifndef lint
35127664Sbmsstatic const char rcsid[] _U_ =
36214518Srpaulo    "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.42 2008-05-21 22:15:25 gianluca Exp $ (LBL)";
37127664Sbms#endif
38127664Sbms
39127664Sbms#include <pcap-int.h>
40172677Smlaier#include <Packet32.h>
41190225Srpaulo#ifdef __MINGW32__
42235426Sdelphij#ifdef __MINGW64__
43235426Sdelphij#include <ntddndis.h>
44235426Sdelphij#else  /*__MINGW64__*/
45235426Sdelphij#include <ddk/ntddndis.h>
46190225Srpaulo#include <ddk/ndis.h>
47235426Sdelphij#endif /*__MINGW64__*/
48190225Srpaulo#else /*__MINGW32__*/
49190225Srpaulo#include <ntddndis.h>
50190225Srpaulo#endif /*__MINGW32__*/
51146768Ssam#ifdef HAVE_DAG_API
52146768Ssam#include <dagnew.h>
53146768Ssam#include <dagapi.h>
54146768Ssam#endif /* HAVE_DAG_API */
55127664Sbms#ifdef __MINGW32__
56127664Sbmsint* _errno();
57127664Sbms#define errno (*_errno())
58127664Sbms#endif /* __MINGW32__ */
59127664Sbms
60146768Ssamstatic int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *);
61146768Ssamstatic int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
62127664Sbmsstatic int pcap_getnonblock_win32(pcap_t *, char *);
63127664Sbmsstatic int pcap_setnonblock_win32(pcap_t *, int, char *);
64127664Sbms
65190225Srpaulo/*dimension of the buffer in the pcap_t structure*/
66190225Srpaulo#define	WIN32_DEFAULT_USER_BUFFER_SIZE 256000
67127664Sbms
68190225Srpaulo/*dimension of the buffer in the kernel driver NPF */
69190225Srpaulo#define	WIN32_DEFAULT_KERNEL_BUFFER_SIZE 1000000
70190225Srpaulo
71146768Ssam/* Equivalent to ntohs(), but a lot faster under Windows */
72146768Ssam#define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
73146768Ssam
74127664Sbms/*
75127664Sbms * Header that the WinPcap driver associates to the packets.
76127664Sbms * Once was in bpf.h
77127664Sbms */
78127664Sbmsstruct bpf_hdr {
79127664Sbms	struct timeval	bh_tstamp;	/* time stamp */
80127664Sbms	bpf_u_int32	bh_caplen;	/* length of captured portion */
81127664Sbms	bpf_u_int32	bh_datalen;	/* original length of packet */
82127664Sbms	u_short		bh_hdrlen;	/* length of bpf header (this struct
83127664Sbms					   plus alignment padding) */
84127664Sbms};
85127664Sbms
86214518SrpauloCRITICAL_SECTION g_PcapCompileCriticalSection;
87214518Srpaulo
88214518SrpauloBOOL WINAPI DllMain(
89214518Srpaulo  HANDLE hinstDLL,
90214518Srpaulo  DWORD dwReason,
91214518Srpaulo  LPVOID lpvReserved
92214518Srpaulo)
93214518Srpaulo{
94214518Srpaulo	if (dwReason == DLL_PROCESS_ATTACH)
95214518Srpaulo	{
96214518Srpaulo		InitializeCriticalSection(&g_PcapCompileCriticalSection);
97214518Srpaulo	}
98214518Srpaulo
99214518Srpaulo	return TRUE;
100214518Srpaulo}
101214518Srpaulo
102127664Sbms/* Start winsock */
103127664Sbmsint
104127664Sbmswsockinit()
105127664Sbms{
106127664Sbms	WORD wVersionRequested;
107127664Sbms	WSADATA wsaData;
108127664Sbms	int err;
109127664Sbms	wVersionRequested = MAKEWORD( 1, 1);
110127664Sbms	err = WSAStartup( wVersionRequested, &wsaData );
111127664Sbms	if ( err != 0 )
112127664Sbms	{
113127664Sbms		return -1;
114127664Sbms	}
115127664Sbms	return 0;
116127664Sbms}
117127664Sbms
118127664Sbms
119127664Sbmsstatic int
120127664Sbmspcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
121127664Sbms{
122127664Sbms
123127664Sbms	if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){
124127664Sbms		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror());
125127664Sbms		return -1;
126127664Sbms	}
127127664Sbms
128127664Sbms	return 0;
129127664Sbms}
130127664Sbms
131190225Srpaulo/* Set the dimension of the kernel-level capture buffer */
132127664Sbmsstatic int
133190225Srpaulopcap_setbuff_win32(pcap_t *p, int dim)
134190225Srpaulo{
135190225Srpaulo	if(PacketSetBuff(p->adapter,dim)==FALSE)
136190225Srpaulo	{
137190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
138190225Srpaulo		return -1;
139190225Srpaulo	}
140190225Srpaulo	return 0;
141190225Srpaulo}
142190225Srpaulo
143190225Srpaulo/* Set the driver working mode */
144190225Srpaulostatic int
145190225Srpaulopcap_setmode_win32(pcap_t *p, int mode)
146190225Srpaulo{
147190225Srpaulo	if(PacketSetMode(p->adapter,mode)==FALSE)
148190225Srpaulo	{
149190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
150190225Srpaulo		return -1;
151190225Srpaulo	}
152190225Srpaulo
153190225Srpaulo	return 0;
154190225Srpaulo}
155190225Srpaulo
156190225Srpaulo/*set the minimum amount of data that will release a read call*/
157190225Srpaulostatic int
158190225Srpaulopcap_setmintocopy_win32(pcap_t *p, int size)
159190225Srpaulo{
160190225Srpaulo	if(PacketSetMinToCopy(p->adapter, size)==FALSE)
161190225Srpaulo	{
162190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
163190225Srpaulo		return -1;
164190225Srpaulo	}
165190225Srpaulo	return 0;
166190225Srpaulo}
167190225Srpaulo
168190225Srpaulostatic int
169146768Ssampcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
170127664Sbms{
171127664Sbms	int cc;
172127664Sbms	int n = 0;
173127664Sbms	register u_char *bp, *ep;
174127664Sbms
175127664Sbms	cc = p->cc;
176127664Sbms	if (p->cc == 0) {
177127664Sbms		/*
178127664Sbms		 * Has "pcap_breakloop()" been called?
179127664Sbms		 */
180127664Sbms		if (p->break_loop) {
181127664Sbms			/*
182127664Sbms			 * Yes - clear the flag that indicates that it
183127664Sbms			 * has, and return -2 to indicate that we were
184127664Sbms			 * told to break out of the loop.
185127664Sbms			 */
186127664Sbms			p->break_loop = 0;
187127664Sbms			return (-2);
188127664Sbms		}
189127664Sbms
190127664Sbms	    /* capture the packets */
191127664Sbms		if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){
192127664Sbms			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
193127664Sbms			return (-1);
194127664Sbms		}
195127664Sbms
196127664Sbms		cc = p->Packet->ulBytesReceived;
197127664Sbms
198127664Sbms		bp = p->Packet->Buffer;
199127664Sbms	}
200127664Sbms	else
201127664Sbms		bp = p->bp;
202127664Sbms
203127664Sbms	/*
204127664Sbms	 * Loop through each packet.
205127664Sbms	 */
206127664Sbms#define bhp ((struct bpf_hdr *)bp)
207127664Sbms	ep = bp + cc;
208127664Sbms	while (1) {
209127664Sbms		register int caplen, hdrlen;
210127664Sbms
211127664Sbms		/*
212127664Sbms		 * Has "pcap_breakloop()" been called?
213127664Sbms		 * If so, return immediately - if we haven't read any
214127664Sbms		 * packets, clear the flag and return -2 to indicate
215127664Sbms		 * that we were told to break out of the loop, otherwise
216127664Sbms		 * leave the flag set, so that the *next* call will break
217127664Sbms		 * out of the loop without having read any packets, and
218127664Sbms		 * return the number of packets we've processed so far.
219127664Sbms		 */
220127664Sbms		if (p->break_loop) {
221127664Sbms			if (n == 0) {
222127664Sbms				p->break_loop = 0;
223127664Sbms				return (-2);
224127664Sbms			} else {
225127664Sbms				p->bp = bp;
226127664Sbms				p->cc = ep - bp;
227127664Sbms				return (n);
228127664Sbms			}
229127664Sbms		}
230127664Sbms		if (bp >= ep)
231127664Sbms			break;
232127664Sbms
233127664Sbms		caplen = bhp->bh_caplen;
234127664Sbms		hdrlen = bhp->bh_hdrlen;
235127664Sbms
236127664Sbms		/*
237127664Sbms		 * XXX A bpf_hdr matches a pcap_pkthdr.
238127664Sbms		 */
239127664Sbms		(*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
240235426Sdelphij		bp += Packet_WORDALIGN(caplen + hdrlen);
241127664Sbms		if (++n >= cnt && cnt > 0) {
242127664Sbms			p->bp = bp;
243127664Sbms			p->cc = ep - bp;
244127664Sbms			return (n);
245127664Sbms		}
246127664Sbms	}
247127664Sbms#undef bhp
248127664Sbms	p->cc = 0;
249127664Sbms	return (n);
250127664Sbms}
251127664Sbms
252146768Ssam#ifdef HAVE_DAG_API
253146768Ssamstatic int
254146768Ssampcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
255146768Ssam{
256146768Ssam	u_char *dp = NULL;
257146768Ssam	int	packet_len = 0, caplen = 0;
258146768Ssam	struct pcap_pkthdr	pcap_header;
259146768Ssam	u_char *endofbuf;
260146768Ssam	int n = 0;
261146768Ssam	dag_record_t *header;
262146768Ssam	unsigned erf_record_len;
263146768Ssam	ULONGLONG ts;
264146768Ssam	int cc;
265146768Ssam	unsigned swt;
266146768Ssam	unsigned dfp = p->adapter->DagFastProcess;
267127664Sbms
268146768Ssam	cc = p->cc;
269146768Ssam	if (cc == 0) /* Get new packets only if we have processed all the ones of the previous read */
270146768Ssam	{
271146768Ssam	    /* Get new packets from the network */
272146768Ssam		if(PacketReceivePacket(p->adapter, p->Packet, TRUE)==FALSE){
273146768Ssam			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
274146768Ssam			return (-1);
275146768Ssam		}
276146768Ssam
277146768Ssam		cc = p->Packet->ulBytesReceived;
278146768Ssam		if(cc == 0)
279146768Ssam			/* The timeout has expired but we no packets arrived */
280146768Ssam			return 0;
281146768Ssam		header = (dag_record_t*)p->adapter->DagBuffer;
282146768Ssam	}
283146768Ssam	else
284146768Ssam		header = (dag_record_t*)p->bp;
285146768Ssam
286146768Ssam	endofbuf = (char*)header + cc;
287146768Ssam
288146768Ssam	/*
289146768Ssam	 * Cycle through the packets
290146768Ssam	 */
291146768Ssam	do
292146768Ssam	{
293146768Ssam		erf_record_len = SWAPS(header->rlen);
294146768Ssam		if((char*)header + erf_record_len > endofbuf)
295146768Ssam			break;
296146768Ssam
297146768Ssam		/* Increase the number of captured packets */
298146768Ssam		p->md.stat.ps_recv++;
299146768Ssam
300146768Ssam		/* Find the beginning of the packet */
301146768Ssam		dp = ((u_char *)header) + dag_record_size;
302146768Ssam
303146768Ssam		/* Determine actual packet len */
304146768Ssam		switch(header->type)
305146768Ssam		{
306146768Ssam		case TYPE_ATM:
307146768Ssam			packet_len = ATM_SNAPLEN;
308146768Ssam			caplen = ATM_SNAPLEN;
309146768Ssam			dp += 4;
310146768Ssam
311146768Ssam			break;
312146768Ssam
313146768Ssam		case TYPE_ETH:
314146768Ssam			swt = SWAPS(header->wlen);
315146768Ssam			packet_len = swt - (p->md.dag_fcs_bits);
316146768Ssam			caplen = erf_record_len - dag_record_size - 2;
317146768Ssam			if (caplen > packet_len)
318146768Ssam			{
319146768Ssam				caplen = packet_len;
320146768Ssam			}
321146768Ssam			dp += 2;
322146768Ssam
323146768Ssam			break;
324146768Ssam
325146768Ssam		case TYPE_HDLC_POS:
326146768Ssam			swt = SWAPS(header->wlen);
327146768Ssam			packet_len = swt - (p->md.dag_fcs_bits);
328146768Ssam			caplen = erf_record_len - dag_record_size;
329146768Ssam			if (caplen > packet_len)
330146768Ssam			{
331146768Ssam				caplen = packet_len;
332146768Ssam			}
333146768Ssam
334146768Ssam			break;
335146768Ssam		}
336146768Ssam
337146768Ssam		if(caplen > p->snapshot)
338146768Ssam			caplen = p->snapshot;
339146768Ssam
340146768Ssam		/*
341146768Ssam		 * Has "pcap_breakloop()" been called?
342146768Ssam		 * If so, return immediately - if we haven't read any
343146768Ssam		 * packets, clear the flag and return -2 to indicate
344146768Ssam		 * that we were told to break out of the loop, otherwise
345146768Ssam		 * leave the flag set, so that the *next* call will break
346146768Ssam		 * out of the loop without having read any packets, and
347146768Ssam		 * return the number of packets we've processed so far.
348146768Ssam		 */
349146768Ssam		if (p->break_loop)
350146768Ssam		{
351146768Ssam			if (n == 0)
352146768Ssam			{
353146768Ssam				p->break_loop = 0;
354146768Ssam				return (-2);
355146768Ssam			}
356146768Ssam			else
357146768Ssam			{
358146768Ssam				p->bp = (char*)header;
359146768Ssam				p->cc = endofbuf - (char*)header;
360146768Ssam				return (n);
361146768Ssam			}
362146768Ssam		}
363146768Ssam
364146768Ssam		if(!dfp)
365146768Ssam		{
366146768Ssam			/* convert between timestamp formats */
367146768Ssam			ts = header->ts;
368146768Ssam			pcap_header.ts.tv_sec = (int)(ts >> 32);
369146768Ssam			ts = (ts & 0xffffffffi64) * 1000000;
370146768Ssam			ts += 0x80000000; /* rounding */
371146768Ssam			pcap_header.ts.tv_usec = (int)(ts >> 32);
372146768Ssam			if (pcap_header.ts.tv_usec >= 1000000) {
373146768Ssam				pcap_header.ts.tv_usec -= 1000000;
374146768Ssam				pcap_header.ts.tv_sec++;
375146768Ssam			}
376146768Ssam		}
377146768Ssam
378146768Ssam		/* No underlaying filtering system. We need to filter on our own */
379146768Ssam		if (p->fcode.bf_insns)
380146768Ssam		{
381146768Ssam			if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0)
382146768Ssam			{
383146768Ssam				/* Move to next packet */
384146768Ssam				header = (dag_record_t*)((char*)header + erf_record_len);
385146768Ssam				continue;
386146768Ssam			}
387146768Ssam		}
388146768Ssam
389146768Ssam		/* Fill the header for the user suppplied callback function */
390146768Ssam		pcap_header.caplen = caplen;
391146768Ssam		pcap_header.len = packet_len;
392146768Ssam
393146768Ssam		/* Call the callback function */
394146768Ssam		(*callback)(user, &pcap_header, dp);
395146768Ssam
396146768Ssam		/* Move to next packet */
397146768Ssam		header = (dag_record_t*)((char*)header + erf_record_len);
398146768Ssam
399146768Ssam		/* Stop if the number of packets requested by user has been reached*/
400146768Ssam		if (++n >= cnt && cnt > 0)
401146768Ssam		{
402146768Ssam			p->bp = (char*)header;
403146768Ssam			p->cc = endofbuf - (char*)header;
404146768Ssam			return (n);
405146768Ssam		}
406146768Ssam	}
407146768Ssam	while((u_char*)header < endofbuf);
408146768Ssam
409146768Ssam  return 1;
410146768Ssam}
411146768Ssam#endif /* HAVE_DAG_API */
412146768Ssam
413146768Ssam/* Send a packet to the network */
414146768Ssamstatic int
415146768Ssampcap_inject_win32(pcap_t *p, const void *buf, size_t size){
416146768Ssam	LPPACKET PacketToSend;
417146768Ssam
418146768Ssam	PacketToSend=PacketAllocatePacket();
419146768Ssam
420146768Ssam	if (PacketToSend == NULL)
421146768Ssam	{
422146768Ssam		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed");
423146768Ssam		return -1;
424146768Ssam	}
425146768Ssam
426146768Ssam	PacketInitPacket(PacketToSend,(PVOID)buf,size);
427146768Ssam	if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
428146768Ssam		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
429146768Ssam		PacketFreePacket(PacketToSend);
430146768Ssam		return -1;
431146768Ssam	}
432146768Ssam
433146768Ssam	PacketFreePacket(PacketToSend);
434146768Ssam
435146768Ssam	/*
436146768Ssam	 * We assume it all got sent if "PacketSendPacket()" succeeded.
437146768Ssam	 * "pcap_inject()" is expected to return the number of bytes
438146768Ssam	 * sent.
439146768Ssam	 */
440146768Ssam	return size;
441146768Ssam}
442146768Ssam
443127664Sbmsstatic void
444190225Srpaulopcap_cleanup_win32(pcap_t *p)
445127664Sbms{
446127664Sbms	if (p->adapter != NULL) {
447127664Sbms		PacketCloseAdapter(p->adapter);
448127664Sbms		p->adapter = NULL;
449127664Sbms	}
450146768Ssam	if (p->Packet) {
451146768Ssam		PacketFreePacket(p->Packet);
452146768Ssam		p->Packet = NULL;
453146768Ssam	}
454190225Srpaulo	pcap_cleanup_live_common(p);
455127664Sbms}
456127664Sbms
457190225Srpaulostatic int
458190225Srpaulopcap_activate_win32(pcap_t *p)
459127664Sbms{
460127664Sbms	NetType type;
461127664Sbms
462190225Srpaulo	if (p->opt.rfmon) {
463190225Srpaulo		/*
464190225Srpaulo		 * No monitor mode on Windows.  It could be done on
465190225Srpaulo		 * Vista with drivers that support the native 802.11
466190225Srpaulo		 * mechanism and monitor mode.
467190225Srpaulo		 */
468190225Srpaulo		return (PCAP_ERROR_RFMON_NOTSUP);
469190225Srpaulo	}
470190225Srpaulo
471127664Sbms	/* Init WinSock */
472127664Sbms	wsockinit();
473127664Sbms
474190225Srpaulo	p->adapter = PacketOpenAdapter(p->opt.source);
475127664Sbms
476127664Sbms	if (p->adapter == NULL)
477127664Sbms	{
478127664Sbms		/* Adapter detected but we are not able to open it. Return failure. */
479190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
480190225Srpaulo		return PCAP_ERROR;
481127664Sbms	}
482127664Sbms
483127664Sbms	/*get network type*/
484127664Sbms	if(PacketGetNetType (p->adapter,&type) == FALSE)
485127664Sbms	{
486190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
487127664Sbms		goto bad;
488127664Sbms	}
489127664Sbms
490127664Sbms	/*Set the linktype*/
491127664Sbms	switch (type.LinkType)
492127664Sbms	{
493127664Sbms	case NdisMediumWan:
494127664Sbms		p->linktype = DLT_EN10MB;
495127664Sbms		break;
496127664Sbms
497127664Sbms	case NdisMedium802_3:
498127664Sbms		p->linktype = DLT_EN10MB;
499146768Ssam		/*
500146768Ssam		 * This is (presumably) a real Ethernet capture; give it a
501146768Ssam		 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
502146768Ssam		 * that an application can let you choose it, in case you're
503146768Ssam		 * capturing DOCSIS traffic that a Cisco Cable Modem
504146768Ssam		 * Termination System is putting out onto an Ethernet (it
505146768Ssam		 * doesn't put an Ethernet header onto the wire, it puts raw
506146768Ssam		 * DOCSIS frames out on the wire inside the low-level
507146768Ssam		 * Ethernet framing).
508146768Ssam		 */
509146768Ssam		p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
510146768Ssam		/*
511146768Ssam		 * If that fails, just leave the list empty.
512146768Ssam		 */
513146768Ssam		if (p->dlt_list != NULL) {
514146768Ssam			p->dlt_list[0] = DLT_EN10MB;
515146768Ssam			p->dlt_list[1] = DLT_DOCSIS;
516146768Ssam			p->dlt_count = 2;
517146768Ssam		}
518127664Sbms		break;
519127664Sbms
520127664Sbms	case NdisMediumFddi:
521127664Sbms		p->linktype = DLT_FDDI;
522127664Sbms		break;
523127664Sbms
524127664Sbms	case NdisMedium802_5:
525127664Sbms		p->linktype = DLT_IEEE802;
526127664Sbms		break;
527127664Sbms
528127664Sbms	case NdisMediumArcnetRaw:
529127664Sbms		p->linktype = DLT_ARCNET;
530127664Sbms		break;
531127664Sbms
532127664Sbms	case NdisMediumArcnet878_2:
533127664Sbms		p->linktype = DLT_ARCNET;
534127664Sbms		break;
535127664Sbms
536127664Sbms	case NdisMediumAtm:
537127664Sbms		p->linktype = DLT_ATM_RFC1483;
538127664Sbms		break;
539127664Sbms
540146768Ssam	case NdisMediumCHDLC:
541146768Ssam		p->linktype = DLT_CHDLC;
542146768Ssam		break;
543146768Ssam
544146768Ssam	case NdisMediumPPPSerial:
545146768Ssam		p->linktype = DLT_PPP_SERIAL;
546146768Ssam		break;
547146768Ssam
548146768Ssam	case NdisMediumNull:
549146768Ssam		p->linktype = DLT_NULL;
550146768Ssam		break;
551146768Ssam
552172677Smlaier	case NdisMediumBare80211:
553172677Smlaier		p->linktype = DLT_IEEE802_11;
554172677Smlaier		break;
555172677Smlaier
556172677Smlaier	case NdisMediumRadio80211:
557172677Smlaier		p->linktype = DLT_IEEE802_11_RADIO;
558172677Smlaier		break;
559172677Smlaier
560172677Smlaier	case NdisMediumPpi:
561172677Smlaier		p->linktype = DLT_PPI;
562172677Smlaier		break;
563172677Smlaier
564127664Sbms	default:
565127664Sbms		p->linktype = DLT_EN10MB;			/*an unknown adapter is assumed to be ethernet*/
566127664Sbms		break;
567127664Sbms	}
568127664Sbms
569172677Smlaier	/* Set promiscuous mode */
570190225Srpaulo	if (p->opt.promisc)
571172677Smlaier	{
572127664Sbms
573172677Smlaier		if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE)
574172677Smlaier		{
575190225Srpaulo			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
576172677Smlaier			goto bad;
577172677Smlaier		}
578172677Smlaier	}
579172677Smlaier	else
580172677Smlaier	{
581172677Smlaier		if (PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL) == FALSE)
582172677Smlaier		{
583190225Srpaulo			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
584172677Smlaier			goto bad;
585172677Smlaier		}
586172677Smlaier	}
587172677Smlaier
588127664Sbms	/* Set the buffer size */
589190225Srpaulo	p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE;
590127664Sbms
591127664Sbms	/* allocate Packet structure used during the capture */
592127664Sbms	if((p->Packet = PacketAllocatePacket())==NULL)
593127664Sbms	{
594190225Srpaulo		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
595127664Sbms		goto bad;
596127664Sbms	}
597127664Sbms
598146768Ssam	if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD))
599127664Sbms	{
600146768Ssam	/*
601146768Ssam	 * Traditional Adapter
602146768Ssam	 */
603190225Srpaulo		/*
604190225Srpaulo		 * If the buffer size wasn't explicitly set, default to
605190225Srpaulo		 * WIN32_DEFAULT_USER_BUFFER_SIZE.
606190225Srpaulo		 */
607190225Srpaulo	 	if (p->opt.buffer_size == 0)
608190225Srpaulo	 		p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE;
609190225Srpaulo
610190225Srpaulo		if(PacketSetBuff(p->adapter,p->opt.buffer_size)==FALSE)
611190225Srpaulo		{
612190225Srpaulo			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
613190225Srpaulo			goto bad;
614190225Srpaulo		}
615146768Ssam
616190225Srpaulo		p->buffer = (u_char *)malloc(p->bufsize);
617146768Ssam		if (p->buffer == NULL)
618146768Ssam		{
619190225Srpaulo			snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
620146768Ssam			goto bad;
621146768Ssam		}
622146768Ssam
623146768Ssam		PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
624146768Ssam
625146768Ssam		/* tell the driver to copy the buffer only if it contains at least 16K */
626146768Ssam		if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
627146768Ssam		{
628190225Srpaulo			snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s", pcap_win32strerror());
629146768Ssam			goto bad;
630146768Ssam		}
631127664Sbms	}
632146768Ssam	else
633146768Ssam#ifdef HAVE_DAG_API
634127664Sbms	{
635146768Ssam	/*
636146768Ssam	 * Dag Card
637146768Ssam	 */
638146768Ssam		LONG	status;
639146768Ssam		HKEY	dagkey;
640146768Ssam		DWORD	lptype;
641146768Ssam		DWORD	lpcbdata;
642146768Ssam		int		postype = 0;
643146768Ssam		char	keyname[512];
644146768Ssam
645146768Ssam		snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
646146768Ssam			"SYSTEM\\CurrentControlSet\\Services\\DAG",
647190225Srpaulo			strstr(_strlwr(p->opt.source), "dag"));
648146768Ssam		do
649146768Ssam		{
650146768Ssam			status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey);
651146768Ssam			if(status != ERROR_SUCCESS)
652146768Ssam				break;
653146768Ssam
654146768Ssam			status = RegQueryValueEx(dagkey,
655146768Ssam				"PosType",
656146768Ssam				NULL,
657146768Ssam				&lptype,
658146768Ssam				(char*)&postype,
659146768Ssam				&lpcbdata);
660146768Ssam
661146768Ssam			if(status != ERROR_SUCCESS)
662146768Ssam			{
663146768Ssam				postype = 0;
664146768Ssam			}
665146768Ssam
666146768Ssam			RegCloseKey(dagkey);
667146768Ssam		}
668146768Ssam		while(FALSE);
669146768Ssam
670146768Ssam
671146768Ssam		p->snapshot = PacketSetSnapLen(p->adapter, snaplen);
672146768Ssam
673146768Ssam		/* Set the length of the FCS associated to any packet. This value
674146768Ssam		 * will be subtracted to the packet length */
675146768Ssam		p->md.dag_fcs_bits = p->adapter->DagFcsLen;
676127664Sbms	}
677146768Ssam#else
678146768Ssam	goto bad;
679146768Ssam#endif /* HAVE_DAG_API */
680146768Ssam
681190225Srpaulo	PacketSetReadTimeout(p->adapter, p->md.timeout);
682146768Ssam
683146768Ssam#ifdef HAVE_DAG_API
684146768Ssam	if(p->adapter->Flags & INFO_FLAG_DAG_CARD)
685146768Ssam	{
686146768Ssam		/* install dag specific handlers for read and setfilter */
687146768Ssam		p->read_op = pcap_read_win32_dag;
688146768Ssam		p->setfilter_op = pcap_setfilter_win32_dag;
689146768Ssam	}
690146768Ssam	else
691146768Ssam	{
692146768Ssam#endif /* HAVE_DAG_API */
693146768Ssam		/* install traditional npf handlers for read and setfilter */
694146768Ssam		p->read_op = pcap_read_win32_npf;
695146768Ssam		p->setfilter_op = pcap_setfilter_win32_npf;
696146768Ssam#ifdef HAVE_DAG_API
697146768Ssam	}
698146768Ssam#endif /* HAVE_DAG_API */
699147894Ssam	p->setdirection_op = NULL;	/* Not implemented. */
700147894Ssam	    /* XXX - can this be implemented on some versions of Windows? */
701146768Ssam	p->inject_op = pcap_inject_win32;
702127664Sbms	p->set_datalink_op = NULL;	/* can't change data link type */
703127664Sbms	p->getnonblock_op = pcap_getnonblock_win32;
704127664Sbms	p->setnonblock_op = pcap_setnonblock_win32;
705127664Sbms	p->stats_op = pcap_stats_win32;
706190225Srpaulo	p->setbuff_op = pcap_setbuff_win32;
707190225Srpaulo	p->setmode_op = pcap_setmode_win32;
708190225Srpaulo	p->setmintocopy_op = pcap_setmintocopy_win32;
709190225Srpaulo	p->cleanup_op = pcap_cleanup_win32;
710127664Sbms
711190225Srpaulo	return (0);
712127664Sbmsbad:
713190225Srpaulo	pcap_cleanup_win32(p);
714190225Srpaulo	return (PCAP_ERROR);
715127664Sbms}
716127664Sbms
717190225Srpaulopcap_t *
718251129Sdelphijpcap_create_interface(const char *device, char *ebuf)
719190225Srpaulo{
720190225Srpaulo	pcap_t *p;
721127664Sbms
722190225Srpaulo	if (strlen(device) == 1)
723190225Srpaulo	{
724190225Srpaulo		/*
725190225Srpaulo		 * It's probably a unicode string
726190225Srpaulo		 * Convert to ascii and pass it to pcap_create_common
727190225Srpaulo		 *
728190225Srpaulo		 * This wonderful hack is needed because pcap_lookupdev still returns
729190225Srpaulo		 * unicode strings, and it's used by windump when no device is specified
730190225Srpaulo		 * in the command line
731190225Srpaulo		 */
732190225Srpaulo		size_t length;
733190225Srpaulo		char* deviceAscii;
734190225Srpaulo
735190225Srpaulo		length = wcslen((wchar_t*)device);
736190225Srpaulo
737190225Srpaulo		deviceAscii = (char*)malloc(length + 1);
738190225Srpaulo
739190225Srpaulo		if (deviceAscii == NULL)
740190225Srpaulo		{
741190225Srpaulo			snprintf(ebuf, PCAP_ERRBUF_SIZE, "Malloc failed");
742190225Srpaulo			return NULL;
743190225Srpaulo		}
744190225Srpaulo
745190225Srpaulo		snprintf(deviceAscii, length + 1, "%ws", (wchar_t*)device);
746190225Srpaulo		p = pcap_create_common(deviceAscii, ebuf);
747190225Srpaulo		free(deviceAscii);
748190225Srpaulo	}
749190225Srpaulo	else
750190225Srpaulo	{
751190225Srpaulo		p = pcap_create_common(device, ebuf);
752190225Srpaulo	}
753190225Srpaulo
754190225Srpaulo	if (p == NULL)
755190225Srpaulo		return (NULL);
756190225Srpaulo
757190225Srpaulo	p->activate_op = pcap_activate_win32;
758190225Srpaulo	return (p);
759190225Srpaulo}
760190225Srpaulo
761127664Sbmsstatic int
762146768Ssampcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp)
763127664Sbms{
764127664Sbms	if(PacketSetBpf(p->adapter,fp)==FALSE){
765146768Ssam		/*
766146768Ssam		 * Kernel filter not installed.
767146768Ssam		 * XXX - fall back on userland filtering, as is done
768146768Ssam		 * on other platforms?
769146768Ssam		 */
770127664Sbms		snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror());
771127664Sbms		return (-1);
772127664Sbms	}
773146768Ssam
774146768Ssam	/*
775146768Ssam	 * Discard any previously-received packets, as they might have
776146768Ssam	 * passed whatever filter was formerly in effect, but might
777146768Ssam	 * not pass this filter (BIOCSETF discards packets buffered
778146768Ssam	 * in the kernel, so you can lose packets in any case).
779146768Ssam	 */
780146768Ssam	p->cc = 0;
781127664Sbms	return (0);
782127664Sbms}
783127664Sbms
784146768Ssam/*
785146768Ssam * We filter at user level, since the kernel driver does't process the packets
786146768Ssam */
787146768Ssamstatic int
788146768Ssampcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) {
789146768Ssam
790146768Ssam	if(!fp)
791146768Ssam	{
792146768Ssam		strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
793146768Ssam		return -1;
794146768Ssam	}
795146768Ssam
796146768Ssam	/* Install a user level filter */
797146768Ssam	if (install_bpf_program(p, fp) < 0)
798146768Ssam	{
799146768Ssam		snprintf(p->errbuf, sizeof(p->errbuf),
800146768Ssam			"setfilter, unable to install the filter: %s", pcap_strerror(errno));
801146768Ssam		return -1;
802146768Ssam	}
803146768Ssam
804146768Ssam	p->md.use_bpf = 0;
805146768Ssam
806146768Ssam	return (0);
807146768Ssam}
808127664Sbms
809127664Sbmsstatic int
810127664Sbmspcap_getnonblock_win32(pcap_t *p, char *errbuf)
811127664Sbms{
812127664Sbms	/*
813127664Sbms	 * XXX - if there were a PacketGetReadTimeout() call, we
814127664Sbms	 * would use it, and return 1 if the timeout is -1
815127664Sbms	 * and 0 otherwise.
816127664Sbms	 */
817127664Sbms	return (p->nonblock);
818127664Sbms}
819127664Sbms
820127664Sbmsstatic int
821127664Sbmspcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
822127664Sbms{
823127664Sbms	int newtimeout;
824127664Sbms
825127664Sbms	if (nonblock) {
826127664Sbms		/*
827127664Sbms		 * Set the read timeout to -1 for non-blocking mode.
828127664Sbms		 */
829127664Sbms		newtimeout = -1;
830127664Sbms	} else {
831127664Sbms		/*
832127664Sbms		 * Restore the timeout set when the device was opened.
833127664Sbms		 * (Note that this may be -1, in which case we're not
834127664Sbms		 * really leaving non-blocking mode.)
835127664Sbms		 */
836190225Srpaulo		newtimeout = p->md.timeout;
837127664Sbms	}
838127664Sbms	if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
839251129Sdelphij		snprintf(errbuf, PCAP_ERRBUF_SIZE,
840127664Sbms		    "PacketSetReadTimeout: %s", pcap_win32strerror());
841127664Sbms		return (-1);
842127664Sbms	}
843127664Sbms	p->nonblock = (newtimeout == -1);
844127664Sbms	return (0);
845127664Sbms}
846127664Sbms
847190225Srpaulo/*platform-dependent routine to add devices other than NDIS interfaces*/
848190225Srpauloint
849190225Srpaulopcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
850127664Sbms{
851190225Srpaulo	return (0);
852127664Sbms}
853