Merge from vendor branch NTPD:
[dragonfly.git] / contrib / libpcap-0.8.3 / pcap-win32.c
1 /*
2  * Copyright (c) 1999 - 2003
3  * NetGroup, Politecnico di Torino (Italy)
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 nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32
33 #ifndef lint
34 static const char rcsid[] _U_ =
35     "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.15.2.3 2003/11/30 02:32:02 guy Exp $ (LBL)";
36 #endif
37
38 #include <pcap-int.h>
39 #include <packet32.h>
40 #include <Ntddndis.h>
41 #ifdef __MINGW32__
42 int* _errno();
43 #define errno (*_errno())
44 #endif /* __MINGW32__ */
45
46 static int pcap_setfilter_win32(pcap_t *, struct bpf_program *);
47 static int pcap_getnonblock_win32(pcap_t *, char *);
48 static int pcap_setnonblock_win32(pcap_t *, int, char *);
49
50 #define PcapBufSize 256000      /*dimension of the buffer in the pcap_t structure*/
51 #define SIZE_BUF 1000000
52
53 /*
54  * Header that the WinPcap driver associates to the packets.
55  * Once was in bpf.h
56  */
57 struct bpf_hdr {
58         struct timeval  bh_tstamp;      /* time stamp */
59         bpf_u_int32     bh_caplen;      /* length of captured portion */
60         bpf_u_int32     bh_datalen;     /* original length of packet */
61         u_short         bh_hdrlen;      /* length of bpf header (this struct
62                                            plus alignment padding) */
63 };
64
65 /* Start winsock */
66 int 
67 wsockinit()
68 {
69         WORD wVersionRequested;
70         WSADATA wsaData;
71         int err;
72         wVersionRequested = MAKEWORD( 1, 1); 
73         err = WSAStartup( wVersionRequested, &wsaData );
74         if ( err != 0 )
75         {
76                 return -1;
77         }
78         return 0;
79 }
80
81
82 static int
83 pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
84 {
85
86         if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){
87                 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror());
88                 return -1;
89         }
90
91         return 0;
92 }
93
94 static int
95 pcap_read_win32(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
96 {
97         int cc;
98         int n = 0;
99         register u_char *bp, *ep;
100
101         cc = p->cc;
102         if (p->cc == 0) {
103                 /*
104                  * Has "pcap_breakloop()" been called?
105                  */
106                 if (p->break_loop) {
107                         /*
108                          * Yes - clear the flag that indicates that it
109                          * has, and return -2 to indicate that we were
110                          * told to break out of the loop.
111                          */
112                         p->break_loop = 0;
113                         return (-2);
114                 }
115
116             /* capture the packets */
117                 if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){
118                         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
119                         return (-1);
120                 }
121                         
122                 cc = p->Packet->ulBytesReceived;
123
124                 bp = p->Packet->Buffer;
125         } 
126         else
127                 bp = p->bp;
128
129         /*
130          * Loop through each packet.
131          */
132 #define bhp ((struct bpf_hdr *)bp)
133         ep = bp + cc;
134         while (1) {
135                 register int caplen, hdrlen;
136
137                 /*
138                  * Has "pcap_breakloop()" been called?
139                  * If so, return immediately - if we haven't read any
140                  * packets, clear the flag and return -2 to indicate
141                  * that we were told to break out of the loop, otherwise
142                  * leave the flag set, so that the *next* call will break
143                  * out of the loop without having read any packets, and
144                  * return the number of packets we've processed so far.
145                  */
146                 if (p->break_loop) {
147                         if (n == 0) {
148                                 p->break_loop = 0;
149                                 return (-2);
150                         } else {
151                                 p->bp = bp;
152                                 p->cc = ep - bp;
153                                 return (n);
154                         }
155                 }
156                 if (bp >= ep)
157                         break;
158
159                 caplen = bhp->bh_caplen;
160                 hdrlen = bhp->bh_hdrlen;
161
162                 /*
163                  * XXX A bpf_hdr matches a pcap_pkthdr.
164                  */
165                 (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
166                 bp += BPF_WORDALIGN(caplen + hdrlen);
167                 if (++n >= cnt && cnt > 0) {
168                         p->bp = bp;
169                         p->cc = ep - bp;
170                         return (n);
171                 }
172         }
173 #undef bhp
174         p->cc = 0;
175         return (n);
176 }
177
178
179 static void
180 pcap_close_win32(pcap_t *p)
181 {
182         if (p->buffer != NULL)
183                 free(p->buffer);
184         if (p->adapter != NULL) {
185                 PacketCloseAdapter(p->adapter);
186                 p->adapter = NULL;
187         }
188 }
189
190 pcap_t *
191 pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
192     char *ebuf)
193 {
194         register pcap_t *p;
195         NetType type;
196
197         /* Init WinSock */
198         wsockinit();
199
200         p = (pcap_t *)malloc(sizeof(*p));
201         if (p == NULL) 
202         {
203                 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
204                 return (NULL);
205         }
206         memset(p, 0, sizeof(*p));
207         p->adapter=NULL;
208
209         p->adapter = PacketOpenAdapter((char*)device);
210         
211         if (p->adapter == NULL)
212         {
213                 /* Adapter detected but we are not able to open it. Return failure. */
214                 snprintf(ebuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
215                 return NULL;
216         }
217         
218         /*get network type*/
219         if(PacketGetNetType (p->adapter,&type) == FALSE)
220         {
221                 snprintf(ebuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
222                 goto bad;
223         }
224         
225         /*Set the linktype*/
226         switch (type.LinkType) 
227         {
228         case NdisMediumWan:
229                 p->linktype = DLT_EN10MB;
230                 break;
231                 
232         case NdisMedium802_3:
233                 p->linktype = DLT_EN10MB;
234                 break;
235                 
236         case NdisMediumFddi:
237                 p->linktype = DLT_FDDI;
238                 break;
239                 
240         case NdisMedium802_5:                   
241                 p->linktype = DLT_IEEE802;      
242                 break;
243                 
244         case NdisMediumArcnetRaw:
245                 p->linktype = DLT_ARCNET;
246                 break;
247                 
248         case NdisMediumArcnet878_2:
249                 p->linktype = DLT_ARCNET;
250                 break;
251                 
252         case NdisMediumAtm:
253                 p->linktype = DLT_ATM_RFC1483;
254                 break;
255                 
256         default:
257                 p->linktype = DLT_EN10MB;                       /*an unknown adapter is assumed to be ethernet*/
258                 break;
259         }
260
261         /* Set promisquous mode */
262         if (promisc) PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS);
263          else PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL);
264
265         /* Set the buffer size */
266         p->bufsize = PcapBufSize;
267
268         p->buffer = (u_char *)malloc(PcapBufSize);
269         if (p->buffer == NULL) 
270         {
271                 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
272                 goto bad;
273         }
274
275         p->snapshot = snaplen;
276
277         /* allocate Packet structure used during the capture */
278         if((p->Packet = PacketAllocatePacket())==NULL)
279         {
280                 snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
281                 goto bad;
282         }
283
284         PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
285
286         /* allocate the standard buffer in the driver */
287         if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE)
288         {
289                 snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n");
290                 goto bad;
291         }
292
293         /* tell the driver to copy the buffer only if it contains at least 16K */
294         if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
295         {
296                 snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror());
297                 goto bad;
298         }
299
300         PacketSetReadTimeout(p->adapter, to_ms);
301
302         p->read_op = pcap_read_win32;
303         p->setfilter_op = pcap_setfilter_win32;
304         p->set_datalink_op = NULL;      /* can't change data link type */
305         p->getnonblock_op = pcap_getnonblock_win32;
306         p->setnonblock_op = pcap_setnonblock_win32;
307         p->stats_op = pcap_stats_win32;
308         p->close_op = pcap_close_win32;
309
310         return (p);
311 bad:
312         if (p->adapter)
313             PacketCloseAdapter(p->adapter);
314         if (p->buffer != NULL)
315                 free(p->buffer);
316         free(p);
317         return (NULL);
318 }
319
320
321 static int
322 pcap_setfilter_win32(pcap_t *p, struct bpf_program *fp)
323 {
324         if(PacketSetBpf(p->adapter,fp)==FALSE){
325                 /* kernel filter not installed. */
326                 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror());
327                 return (-1);
328         }
329         return (0);
330 }
331
332
333 static int
334 pcap_getnonblock_win32(pcap_t *p, char *errbuf)
335 {
336         /*
337          * XXX - if there were a PacketGetReadTimeout() call, we
338          * would use it, and return 1 if the timeout is -1
339          * and 0 otherwise.
340          */
341         return (p->nonblock);
342 }
343
344 static int
345 pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
346 {
347         int newtimeout;
348
349         if (nonblock) {
350                 /*
351                  * Set the read timeout to -1 for non-blocking mode.
352                  */
353                 newtimeout = -1;
354         } else {
355                 /*
356                  * Restore the timeout set when the device was opened.
357                  * (Note that this may be -1, in which case we're not
358                  * really leaving non-blocking mode.)
359                  */
360                 newtimeout = p->timeout;
361         }
362         if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
363                 snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
364                     "PacketSetReadTimeout: %s", pcap_win32strerror());
365                 return (-1);
366         }
367         p->nonblock = (newtimeout == -1);
368         return (0);
369 }
370
371 /* Set the driver working mode */
372 int 
373 pcap_setmode(pcap_t *p, int mode){
374         
375         if (p->adapter==NULL)
376         {
377                 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file");
378                 return -1;
379         }
380
381         if(PacketSetMode(p->adapter,mode)==FALSE)
382         {
383                 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
384                 return -1;
385         }
386
387         return 0;
388 }
389
390 /* Send a packet to the network */
391 int 
392 pcap_sendpacket(pcap_t *p, u_char *buf, int size){
393         LPPACKET PacketToSend;
394
395         if (p->adapter==NULL)
396         {
397                 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Writing a packet is allowed only on a physical adapter");
398                 return -1;
399         }
400
401         PacketToSend=PacketAllocatePacket();
402         PacketInitPacket(PacketToSend,buf,size);
403         if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
404                 PacketFreePacket(PacketToSend);
405                 return -1;
406         }
407
408         PacketFreePacket(PacketToSend);
409         return 0;
410 }
411
412 /* Set the dimension of the kernel-level capture buffer */
413 int 
414 pcap_setbuff(pcap_t *p, int dim)
415 {
416         if (p->adapter==NULL)
417         {
418                 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file");
419                 return -1;
420         }
421         
422         if(PacketSetBuff(p->adapter,dim)==FALSE)
423         {
424                 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
425                 return -1;
426         }
427         return 0;
428 }
429
430 /*set the minimum amount of data that will release a read call*/
431 int 
432 pcap_setmintocopy(pcap_t *p, int size)
433 {
434         if (p->adapter==NULL)
435         {
436                 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture");
437                 return -1;
438         }       
439
440         if(PacketSetMinToCopy(p->adapter, size)==FALSE)
441         {
442                 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
443                 return -1;
444         }
445         return 0;
446 }