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