]> The Tcpdump Group git mirrors - libpcap/blob - pcap-win32.c
18001d534d1d0176f07b24737fbe43329e811c28
[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.4 2002-12-19 09:05:48 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 NdisMediumArcnetRaw:
167 p->linktype = DLT_ARCNET;
168
169 case NdisMediumArcnet878_2:
170 p->linktype = DLT_ARCNET;
171 break;
172
173 case NdisMediumAtm:
174 p->linktype = DLT_ATM_RFC1483;
175 break;
176
177 default:
178 p->linktype = DLT_EN10MB; /*an unknown adapter is assumed to be ethernet*/
179 }
180
181 /* Set promisquous mode */
182 if (promisc) PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS);
183 else PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL);
184
185 /* Set the buffer size */
186 p->bufsize = PcapBufSize;
187
188 p->buffer = (u_char *)malloc(PcapBufSize);
189 if (p->buffer == NULL) {
190 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
191 goto bad;
192 }
193
194 p->snapshot = snaplen;
195
196 /* allocate Packet structure used during the capture */
197 if((p->Packet = PacketAllocatePacket())==NULL){
198 snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
199 goto bad;
200 }
201
202 PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
203
204 /* allocate the standard buffer in the driver */
205 if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE)
206 {
207 snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n");
208 goto bad;
209 }
210
211 /* tell the driver to copy the buffer only if it contains at least 16K */
212 if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
213 {
214 snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror());
215 goto bad;
216 }
217
218 PacketSetReadTimeout(p->adapter, to_ms);
219
220 return (p);
221 bad:
222 if (p->adapter)
223 PacketCloseAdapter(p->adapter);
224 if (p->buffer != NULL)
225 free(p->buffer);
226 free(p);
227 return (NULL);
228 }
229
230
231 int
232 pcap_setfilter(pcap_t *p, struct bpf_program *fp)
233 {
234 if(p->adapter==NULL){
235 /* Offline capture: make our own copy of the filter */
236 if (install_bpf_program(p, fp) < 0)
237 return (-1);
238 }
239 else if(PacketSetBpf(p->adapter,fp)==FALSE){
240 /* kernel filter not installed. */
241 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror());
242 return (-1);
243 }
244 return (0);
245 }
246
247
248 /* Set the driver working mode */
249 int
250 pcap_setmode(pcap_t *p, int mode){
251
252 if (p->adapter==NULL)
253 {
254 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file");
255 return -1;
256 }
257
258 if(PacketSetMode(p->adapter,mode)==FALSE)
259 {
260 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
261 return -1;
262 }
263
264 return 0;
265 }
266
267 /* Send a packet to the network */
268 int
269 pcap_sendpacket(pcap_t *p, u_char *buf, int size){
270 LPPACKET PacketToSend;
271
272 if (p->adapter==NULL)
273 {
274 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Writing a packet is allowed only on a physical adapter");
275 return -1;
276 }
277
278 PacketToSend=PacketAllocatePacket();
279 PacketInitPacket(PacketToSend,buf,size);
280 if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
281 PacketFreePacket(PacketToSend);
282 return -1;
283 }
284
285 PacketFreePacket(PacketToSend);
286 return 0;
287 }
288
289 /* Set the dimension of the kernel-level capture buffer */
290 int
291 pcap_setbuff(pcap_t *p, int dim)
292 {
293 if (p->adapter==NULL)
294 {
295 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file");
296 return -1;
297 }
298
299 if(PacketSetBuff(p->adapter,dim)==FALSE)
300 {
301 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
302 return -1;
303 }
304 return 0;
305 }
306
307 /*set the minimum amount of data that will release a read call*/
308 int
309 pcap_setmintocopy(pcap_t *p, int size)
310 {
311 if (p->adapter==NULL)
312 {
313 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture");
314 return -1;
315 }
316
317 if(PacketSetMinToCopy(p->adapter, size)==FALSE)
318 {
319 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
320 return -1;
321 }
322 return 0;
323 }
324
325 int
326 pcap_set_datalink_platform(pcap_t *p, int dlt)
327 {
328 return (0);
329 }