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
35 static 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__
56 int* _errno();
57 #define errno (*_errno())
58 #endif /* __MINGW32__ */
59 
60 static int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *);
61 static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
62 static int pcap_getnonblock_win32(pcap_t *, char *);
63 static 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  */
77 struct 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  */
89 struct 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 
97 CRITICAL_SECTION g_PcapCompileCriticalSection;
98 
DllMain(HANDLE hinstDLL,DWORD dwReason,LPVOID lpvReserved)99 BOOL 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 */
114 int
wsockinit()115 wsockinit()
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 
130 static int
pcap_stats_win32(pcap_t * p,struct pcap_stat * ps)131 pcap_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 */
143 static int
pcap_setbuff_win32(pcap_t * p,int dim)144 pcap_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 */
155 static int
pcap_setmode_win32(pcap_t * p,int mode)156 pcap_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*/
168 static int
pcap_setmintocopy_win32(pcap_t * p,int size)169 pcap_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*/
180 static Adapter *
pcap_getadapter_win32(pcap_t * p)181 pcap_getadapter_win32(pcap_t *p)
182 {
183 	return p->adapter;
184 }
185 
186 static int
pcap_read_win32_npf(pcap_t * p,int cnt,pcap_handler callback,u_char * user)187 pcap_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
271 static int
pcap_read_win32_dag(pcap_t * p,int cnt,pcap_handler callback,u_char * user)272 pcap_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 */
433 static int
pcap_inject_win32(pcap_t * p,const void * buf,size_t size)434 pcap_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 
462 static void
pcap_cleanup_win32(pcap_t * p)463 pcap_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 
476 static int
pcap_activate_win32(pcap_t * p)477 pcap_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);
745 bad:
746 	pcap_cleanup_win32(p);
747 	return (PCAP_ERROR);
748 }
749 
750 pcap_t *
pcap_create_interface(const char * device,char * ebuf)751 pcap_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 
794 static int
pcap_setfilter_win32_npf(pcap_t * p,struct bpf_program * fp)795 pcap_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  */
820 static int
pcap_setfilter_win32_dag(pcap_t * p,struct bpf_program * fp)821 pcap_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 
840 static int
pcap_getnonblock_win32(pcap_t * p,char * errbuf)841 pcap_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 
853 static int
pcap_setnonblock_win32(pcap_t * p,int nonblock,char * errbuf)854 pcap_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*/
882 int
pcap_platform_finddevs(pcap_if_t ** alldevsp,char * errbuf)883 pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
884 {
885 	return (0);
886 }
887