]> The Tcpdump Group git mirrors - libpcap/blob - pcap-win32.c
f16da44eaee5c61fdededc4189853b4a3e6e09f1
[libpcap] / 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.19 2003-12-18 23:32:33 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 /*
235 * This is (presumably) a real Ethernet capture; give it a
236 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
237 * that an application can let you choose it, in case you're
238 * capturing DOCSIS traffic that a Cisco Cable Modem
239 * Termination System is putting out onto an Ethernet (it
240 * doesn't put an Ethernet header onto the wire, it puts raw
241 * DOCSIS frames out on the wire inside the low-level
242 * Ethernet framing).
243 */
244 p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
245 /*
246 * If that fails, just leave the list empty.
247 */
248 if (p->dlt_list != NULL) {
249 p->dlt_list[0] = DLT_EN10MB;
250 p->dlt_list[1] = DLT_DOCSIS;
251 p->dlt_count = 2;
252 }
253 break;
254
255 case NdisMediumFddi:
256 p->linktype = DLT_FDDI;
257 break;
258
259 case NdisMedium802_5:
260 p->linktype = DLT_IEEE802;
261 break;
262
263 case NdisMediumArcnetRaw:
264 p->linktype = DLT_ARCNET;
265 break;
266
267 case NdisMediumArcnet878_2:
268 p->linktype = DLT_ARCNET;
269 break;
270
271 case NdisMediumAtm:
272 p->linktype = DLT_ATM_RFC1483;
273 break;
274
275 default:
276 p->linktype = DLT_EN10MB; /*an unknown adapter is assumed to be ethernet*/
277 break;
278 }
279
280 /* Set promisquous mode */
281 if (promisc) PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS);
282 else PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL);
283
284 /* Set the buffer size */
285 p->bufsize = PcapBufSize;
286
287 p->buffer = (u_char *)malloc(PcapBufSize);
288 if (p->buffer == NULL)
289 {
290 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
291 goto bad;
292 }
293
294 p->snapshot = snaplen;
295
296 /* allocate Packet structure used during the capture */
297 if((p->Packet = PacketAllocatePacket())==NULL)
298 {
299 snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
300 goto bad;
301 }
302
303 PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
304
305 /* allocate the standard buffer in the driver */
306 if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE)
307 {
308 snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n");
309 goto bad;
310 }
311
312 /* tell the driver to copy the buffer only if it contains at least 16K */
313 if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
314 {
315 snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror());
316 goto bad;
317 }
318
319 PacketSetReadTimeout(p->adapter, to_ms);
320
321 p->read_op = pcap_read_win32;
322 p->setfilter_op = pcap_setfilter_win32;
323 p->set_datalink_op = NULL; /* can't change data link type */
324 p->getnonblock_op = pcap_getnonblock_win32;
325 p->setnonblock_op = pcap_setnonblock_win32;
326 p->stats_op = pcap_stats_win32;
327 p->close_op = pcap_close_win32;
328
329 return (p);
330 bad:
331 if (p->adapter)
332 PacketCloseAdapter(p->adapter);
333 if (p->buffer != NULL)
334 free(p->buffer);
335 /*
336 * Get rid of any link-layer type list we allocated.
337 */
338 if (p->dlt_list != NULL)
339 free(p->dlt_list);
340 free(p);
341 return (NULL);
342 }
343
344
345 static int
346 pcap_setfilter_win32(pcap_t *p, struct bpf_program *fp)
347 {
348 if(PacketSetBpf(p->adapter,fp)==FALSE){
349 /* kernel filter not installed. */
350 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror());
351 return (-1);
352 }
353 return (0);
354 }
355
356
357 static int
358 pcap_getnonblock_win32(pcap_t *p, char *errbuf)
359 {
360 /*
361 * XXX - if there were a PacketGetReadTimeout() call, we
362 * would use it, and return 1 if the timeout is -1
363 * and 0 otherwise.
364 */
365 return (p->nonblock);
366 }
367
368 static int
369 pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
370 {
371 int newtimeout;
372
373 if (nonblock) {
374 /*
375 * Set the read timeout to -1 for non-blocking mode.
376 */
377 newtimeout = -1;
378 } else {
379 /*
380 * Restore the timeout set when the device was opened.
381 * (Note that this may be -1, in which case we're not
382 * really leaving non-blocking mode.)
383 */
384 newtimeout = p->timeout;
385 }
386 if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
387 snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
388 "PacketSetReadTimeout: %s", pcap_win32strerror());
389 return (-1);
390 }
391 p->nonblock = (newtimeout == -1);
392 return (0);
393 }
394
395 /* Set the driver working mode */
396 int
397 pcap_setmode(pcap_t *p, int mode){
398
399 if (p->adapter==NULL)
400 {
401 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file");
402 return -1;
403 }
404
405 if(PacketSetMode(p->adapter,mode)==FALSE)
406 {
407 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
408 return -1;
409 }
410
411 return 0;
412 }
413
414 /* Send a packet to the network */
415 int
416 pcap_sendpacket(pcap_t *p, u_char *buf, int size){
417 LPPACKET PacketToSend;
418
419 if (p->adapter==NULL)
420 {
421 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Writing a packet is allowed only on a physical adapter");
422 return -1;
423 }
424
425 PacketToSend=PacketAllocatePacket();
426 PacketInitPacket(PacketToSend,buf,size);
427 if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
428 PacketFreePacket(PacketToSend);
429 return -1;
430 }
431
432 PacketFreePacket(PacketToSend);
433 return 0;
434 }
435
436 /* Set the dimension of the kernel-level capture buffer */
437 int
438 pcap_setbuff(pcap_t *p, int dim)
439 {
440 if (p->adapter==NULL)
441 {
442 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file");
443 return -1;
444 }
445
446 if(PacketSetBuff(p->adapter,dim)==FALSE)
447 {
448 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
449 return -1;
450 }
451 return 0;
452 }
453
454 /*set the minimum amount of data that will release a read call*/
455 int
456 pcap_setmintocopy(pcap_t *p, int size)
457 {
458 if (p->adapter==NULL)
459 {
460 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture");
461 return -1;
462 }
463
464 if(PacketSetMinToCopy(p->adapter, size)==FALSE)
465 {
466 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
467 return -1;
468 }
469 return 0;
470 }