("" < 3.4) always evaluates to true, which unconditionally
[dragonfly.git] / contrib / libpcap-0.8.3 / pcap-win32.c
blobef1b0f35697d1905e6e59f733b9b228b85763bd1
1 /*
2 * Copyright (c) 1999 - 2003
3 * NetGroup, Politecnico di Torino (Italy)
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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.
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.
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
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__ */
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 *);
50 #define PcapBufSize 256000 /*dimension of the buffer in the pcap_t structure*/
51 #define SIZE_BUF 1000000
54 * Header that the WinPcap driver associates to the packets.
55 * Once was in bpf.h
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) */
65 /* Start winsock */
66 int
67 wsockinit()
69 WORD wVersionRequested;
70 WSADATA wsaData;
71 int err;
72 wVersionRequested = MAKEWORD( 1, 1);
73 err = WSAStartup( wVersionRequested, &wsaData );
74 if ( err != 0 )
76 return -1;
78 return 0;
82 static int
83 pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
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;
91 return 0;
94 static int
95 pcap_read_win32(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
97 int cc;
98 int n = 0;
99 register u_char *bp, *ep;
101 cc = p->cc;
102 if (p->cc == 0) {
104 * Has "pcap_breakloop()" been called?
106 if (p->break_loop) {
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.
112 p->break_loop = 0;
113 return (-2);
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);
122 cc = p->Packet->ulBytesReceived;
124 bp = p->Packet->Buffer;
126 else
127 bp = p->bp;
130 * Loop through each packet.
132 #define bhp ((struct bpf_hdr *)bp)
133 ep = bp + cc;
134 while (1) {
135 register int caplen, hdrlen;
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.
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);
156 if (bp >= ep)
157 break;
159 caplen = bhp->bh_caplen;
160 hdrlen = bhp->bh_hdrlen;
163 * XXX A bpf_hdr matches a pcap_pkthdr.
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);
173 #undef bhp
174 p->cc = 0;
175 return (n);
179 static void
180 pcap_close_win32(pcap_t *p)
182 if (p->buffer != NULL)
183 free(p->buffer);
184 if (p->adapter != NULL) {
185 PacketCloseAdapter(p->adapter);
186 p->adapter = NULL;
190 pcap_t *
191 pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
192 char *ebuf)
194 register pcap_t *p;
195 NetType type;
197 /* Init WinSock */
198 wsockinit();
200 p = (pcap_t *)malloc(sizeof(*p));
201 if (p == NULL)
203 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
204 return (NULL);
206 memset(p, 0, sizeof(*p));
207 p->adapter=NULL;
209 p->adapter = PacketOpenAdapter((char*)device);
211 if (p->adapter == NULL)
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;
218 /*get network type*/
219 if(PacketGetNetType (p->adapter,&type) == FALSE)
221 snprintf(ebuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
222 goto bad;
225 /*Set the linktype*/
226 switch (type.LinkType)
228 case NdisMediumWan:
229 p->linktype = DLT_EN10MB;
230 break;
232 case NdisMedium802_3:
233 p->linktype = DLT_EN10MB;
234 break;
236 case NdisMediumFddi:
237 p->linktype = DLT_FDDI;
238 break;
240 case NdisMedium802_5:
241 p->linktype = DLT_IEEE802;
242 break;
244 case NdisMediumArcnetRaw:
245 p->linktype = DLT_ARCNET;
246 break;
248 case NdisMediumArcnet878_2:
249 p->linktype = DLT_ARCNET;
250 break;
252 case NdisMediumAtm:
253 p->linktype = DLT_ATM_RFC1483;
254 break;
256 default:
257 p->linktype = DLT_EN10MB; /*an unknown adapter is assumed to be ethernet*/
258 break;
261 /* Set promisquous mode */
262 if (promisc) PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS);
263 else PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL);
265 /* Set the buffer size */
266 p->bufsize = PcapBufSize;
268 p->buffer = (u_char *)malloc(PcapBufSize);
269 if (p->buffer == NULL)
271 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
272 goto bad;
275 p->snapshot = snaplen;
277 /* allocate Packet structure used during the capture */
278 if((p->Packet = PacketAllocatePacket())==NULL)
280 snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
281 goto bad;
284 PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
286 /* allocate the standard buffer in the driver */
287 if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE)
289 snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n");
290 goto bad;
293 /* tell the driver to copy the buffer only if it contains at least 16K */
294 if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
296 snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror());
297 goto bad;
300 PacketSetReadTimeout(p->adapter, to_ms);
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;
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);
321 static int
322 pcap_setfilter_win32(pcap_t *p, struct bpf_program *fp)
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);
329 return (0);
333 static int
334 pcap_getnonblock_win32(pcap_t *p, char *errbuf)
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.
341 return (p->nonblock);
344 static int
345 pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
347 int newtimeout;
349 if (nonblock) {
351 * Set the read timeout to -1 for non-blocking mode.
353 newtimeout = -1;
354 } else {
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.)
360 newtimeout = p->timeout;
362 if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
363 snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
364 "PacketSetReadTimeout: %s", pcap_win32strerror());
365 return (-1);
367 p->nonblock = (newtimeout == -1);
368 return (0);
371 /* Set the driver working mode */
372 int
373 pcap_setmode(pcap_t *p, int mode){
375 if (p->adapter==NULL)
377 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file");
378 return -1;
381 if(PacketSetMode(p->adapter,mode)==FALSE)
383 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
384 return -1;
387 return 0;
390 /* Send a packet to the network */
391 int
392 pcap_sendpacket(pcap_t *p, u_char *buf, int size){
393 LPPACKET PacketToSend;
395 if (p->adapter==NULL)
397 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Writing a packet is allowed only on a physical adapter");
398 return -1;
401 PacketToSend=PacketAllocatePacket();
402 PacketInitPacket(PacketToSend,buf,size);
403 if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
404 PacketFreePacket(PacketToSend);
405 return -1;
408 PacketFreePacket(PacketToSend);
409 return 0;
412 /* Set the dimension of the kernel-level capture buffer */
413 int
414 pcap_setbuff(pcap_t *p, int dim)
416 if (p->adapter==NULL)
418 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file");
419 return -1;
422 if(PacketSetBuff(p->adapter,dim)==FALSE)
424 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
425 return -1;
427 return 0;
430 /*set the minimum amount of data that will release a read call*/
431 int
432 pcap_setmintocopy(pcap_t *p, int size)
434 if (p->adapter==NULL)
436 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture");
437 return -1;
440 if(PacketSetMinToCopy(p->adapter, size)==FALSE)
442 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
443 return -1;
445 return 0;