]> The Tcpdump Group git mirrors - libpcap/blob - pcap-win32.c
feb1a3bd6fadd957152dfd256b9e86b9ff76dc88
[libpcap] / pcap-win32.c
1 /*
2 * Copyright (c) 1999, 2000
3 * Politecnico di Torino. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the Politecnico
13 * di Torino, and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22 #ifndef lint
23 static const char rcsid[] =
24 "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.2 2002-08-05 07:45:09 guy Exp $ (LBL)";
25 #endif
26
27 #include <pcap-int.h>
28 #include <packet32.h>
29 #include <Ntddndis.h>
30 #ifdef __MINGW32__
31 int* _errno();
32 #define errno (*_errno())
33 #endif /* __MINGW32__ */
34
35 #define PcapBufSize 256000 /*dimension of the buffer in the pcap_t structure*/
36 #define SIZE_BUF 1000000
37
38 /*start winsock*/
39 int
40 wsockinit()
41 {
42 WORD wVersionRequested;
43 WSADATA wsaData;
44 int err;
45 wVersionRequested = MAKEWORD( 1, 1);
46 err = WSAStartup( wVersionRequested, &wsaData );
47 if ( err != 0 )
48 {
49 return -1;
50 }
51 return 0;
52 }
53
54
55 int
56 pcap_stats(pcap_t *p, struct pcap_stat *ps)
57 {
58
59 if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){
60 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror());
61 return -1;
62 }
63
64 return 0;
65 }
66
67 int
68 pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
69 {
70 int cc;
71 int n = 0;
72 register u_char *bp, *ep;
73
74 cc = p->cc;
75 if (p->cc == 0) {
76
77 /* capture the packets */
78 if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){
79 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
80 return (-1);
81 }
82
83 cc = p->Packet->ulBytesReceived;
84
85 bp = p->Packet->Buffer;
86 }
87 else
88 bp = p->bp;
89
90 /*
91 * Loop through each packet.
92 */
93 #define bhp ((struct bpf_hdr *)bp)
94 ep = bp + cc;
95 while (bp < ep) {
96 register int caplen, hdrlen;
97 caplen = bhp->bh_caplen;
98 hdrlen = bhp->bh_hdrlen;
99
100 /*
101 * XXX A bpf_hdr matches a pcap_pkthdr.
102 */
103 (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
104 bp += BPF_WORDALIGN(caplen + hdrlen);
105 if (++n >= cnt && cnt > 0) {
106 p->bp = bp;
107 p->cc = ep - bp;
108 return (n);
109 }
110 }
111 #undef bhp
112 p->cc = 0;
113 return (n);
114 }
115
116
117 pcap_t *
118 pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf)
119 {
120 register pcap_t *p;
121 NetType type;
122
123 /* Init WinSock */
124 wsockinit();
125
126 p = (pcap_t *)malloc(sizeof(*p));
127 if (p == NULL) {
128 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
129 return (NULL);
130 }
131 memset(p, 0, sizeof(*p));
132 p->adapter=NULL;
133
134 p->adapter=PacketOpenAdapter(device);
135 if (p->adapter==NULL) {
136 snprintf(ebuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
137 return NULL;
138 }
139
140 /*get network type*/
141 if(PacketGetNetType (p->adapter,&type)==FALSE)
142 {
143 snprintf(ebuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
144 goto bad;
145 }
146
147 /*Set the linktype*/
148 switch (type.LinkType) {
149
150 case NdisMediumWan:
151 p->linktype = DLT_EN10MB;
152 break;
153
154 case NdisMedium802_3:
155 p->linktype = DLT_EN10MB;
156 break;
157
158 case NdisMediumFddi:
159 p->linktype = DLT_FDDI;
160 break;
161
162 case NdisMedium802_5:
163 p->linktype = DLT_IEEE802;
164 break;
165
166 case NdisMediumArcnet878_2:
167 p->linktype = DLT_ARCNET;
168 break;
169
170 case NdisMediumAtm:
171 p->linktype = DLT_ATM_RFC1483;
172 break;
173
174 default:
175 p->linktype = DLT_EN10MB; /*an unknown adapter is assumed to be ethernet*/
176 }
177
178 /* Set promisquous mode */
179 if (promisc) PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS);
180 else PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL);
181
182 /* Set the buffer size */
183 p->bufsize = PcapBufSize;
184
185 p->buffer = (u_char *)malloc(PcapBufSize);
186 if (p->buffer == NULL) {
187 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
188 goto bad;
189 }
190
191 p->snapshot = snaplen;
192
193 /* allocate Packet structure used during the capture */
194 if((p->Packet = PacketAllocatePacket())==NULL){
195 snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
196 goto bad;
197 }
198
199 PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
200
201 /* allocate the standard buffer in the driver */
202 if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE)
203 {
204 snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n");
205 goto bad;
206 }
207
208 /* tell the driver to copy the buffer only if it contains at least 16K */
209 if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
210 {
211 snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror());
212 goto bad;
213 }
214
215 PacketSetReadTimeout(p->adapter, to_ms);
216
217 return (p);
218 bad:
219 if (p->adapter)
220 PacketCloseAdapter(p->adapter);
221 if (p->buffer != NULL)
222 free(p->buffer);
223 free(p);
224 return (NULL);
225 }
226
227
228 int
229 pcap_setfilter(pcap_t *p, struct bpf_program *fp)
230 {
231 if(p->adapter==NULL){
232 /* Offline capture: make our own copy of the filter */
233 if (install_bpf_program(p, fp) < 0)
234 return (-1);
235 }
236 else if(PacketSetBpf(p->adapter,fp)==FALSE){
237 /* kernel filter not installed. */
238 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror());
239 return (-1);
240 }
241 return (0);
242 }
243
244
245 /* Set the driver working mode */
246 int
247 pcap_setmode(pcap_t *p, int mode){
248
249 if (p->adapter==NULL)
250 {
251 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file");
252 return -1;
253 }
254
255 if(PacketSetMode(p->adapter,mode)==FALSE)
256 {
257 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
258 return -1;
259 }
260
261 return 0;
262 }
263
264 /* Send a packet to the network */
265 int
266 pcap_sendpacket(pcap_t *p, u_char *buf, int size){
267 LPPACKET PacketToSend;
268
269 if (p->adapter==NULL)
270 {
271 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Writing a packet is allowed only on a physical adapter");
272 return -1;
273 }
274
275 PacketToSend=PacketAllocatePacket();
276 PacketInitPacket(PacketToSend,buf,size);
277 if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
278 PacketFreePacket(PacketToSend);
279 return -1;
280 }
281
282 PacketFreePacket(PacketToSend);
283 return 0;
284 }
285
286 /* Set the dimension of the kernel-level capture buffer */
287 int
288 pcap_setbuff(pcap_t *p, int dim)
289 {
290 if (p->adapter==NULL)
291 {
292 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file");
293 return -1;
294 }
295
296 if(PacketSetBuff(p->adapter,dim)==FALSE)
297 {
298 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
299 return -1;
300 }
301 return 0;
302 }
303
304 /*set the minimum amount of data that will release a read call*/
305 int
306 pcap_setmintocopy(pcap_t *p, int size)
307 {
308 if (p->adapter==NULL)
309 {
310 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture");
311 return -1;
312 }
313
314 if(PacketSetMinToCopy(p->adapter, size)==FALSE)
315 {
316 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
317 return -1;
318 }
319 return 0;
320 }
321
322