]> The Tcpdump Group git mirrors - libpcap/blob - pcap-win32.c
The value pointed to by "gen_pf_ifname()"'s argument isn't modified, so
[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.7 2003-04-09 10:01:10 risso 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 /*
39 * Header that the WinPcap driver associates to the packets.
40 * Once was in bpf.h
41 */
42 struct bpf_hdr {
43 struct timeval bh_tstamp; /* time stamp */
44 bpf_u_int32 bh_caplen; /* length of captured portion */
45 bpf_u_int32 bh_datalen; /* original length of packet */
46 u_short bh_hdrlen; /* length of bpf header (this struct
47 plus alignment padding) */
48 };
49
50 /* Start winsock */
51 int
52 wsockinit()
53 {
54 WORD wVersionRequested;
55 WSADATA wsaData;
56 int err;
57 wVersionRequested = MAKEWORD( 1, 1);
58 err = WSAStartup( wVersionRequested, &wsaData );
59 if ( err != 0 )
60 {
61 return -1;
62 }
63 return 0;
64 }
65
66
67 int
68 pcap_stats(pcap_t *p, struct pcap_stat *ps)
69 {
70
71 if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){
72 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror());
73 return -1;
74 }
75
76 return 0;
77 }
78
79 int
80 pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
81 {
82 int cc;
83 int n = 0;
84 register u_char *bp, *ep;
85
86 cc = p->cc;
87 if (p->cc == 0) {
88
89 /* capture the packets */
90 if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){
91 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
92 return (-1);
93 }
94
95 cc = p->Packet->ulBytesReceived;
96
97 bp = p->Packet->Buffer;
98 }
99 else
100 bp = p->bp;
101
102 /*
103 * Loop through each packet.
104 */
105 #define bhp ((struct bpf_hdr *)bp)
106 ep = bp + cc;
107 while (bp < ep) {
108 register int caplen, hdrlen;
109 caplen = bhp->bh_caplen;
110 hdrlen = bhp->bh_hdrlen;
111
112 /*
113 * XXX A bpf_hdr matches a pcap_pkthdr.
114 */
115 (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
116 bp += BPF_WORDALIGN(caplen + hdrlen);
117 if (++n >= cnt && cnt > 0) {
118 p->bp = bp;
119 p->cc = ep - bp;
120 return (n);
121 }
122 }
123 #undef bhp
124 p->cc = 0;
125 return (n);
126 }
127
128
129 pcap_t *
130 pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
131 char *ebuf)
132 {
133 register pcap_t *p;
134 NetType type;
135
136 /* Init WinSock */
137 wsockinit();
138
139 p = (pcap_t *)malloc(sizeof(*p));
140 if (p == NULL) {
141 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
142 return (NULL);
143 }
144 memset(p, 0, sizeof(*p));
145 p->adapter=NULL;
146
147 p->adapter=PacketOpenAdapter(device);
148 if (p->adapter==NULL) {
149 snprintf(ebuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
150 return NULL;
151 }
152
153 /*get network type*/
154 if(PacketGetNetType (p->adapter,&type)==FALSE)
155 {
156 snprintf(ebuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
157 goto bad;
158 }
159
160 /*Set the linktype*/
161 switch (type.LinkType) {
162
163 case NdisMediumWan:
164 p->linktype = DLT_EN10MB;
165 break;
166
167 case NdisMedium802_3:
168 p->linktype = DLT_EN10MB;
169 break;
170
171 case NdisMediumFddi:
172 p->linktype = DLT_FDDI;
173 break;
174
175 case NdisMedium802_5:
176 p->linktype = DLT_IEEE802;
177 break;
178
179 case NdisMediumArcnetRaw:
180 p->linktype = DLT_ARCNET;
181 break;
182
183 case NdisMediumArcnet878_2:
184 p->linktype = DLT_ARCNET;
185 break;
186
187 case NdisMediumAtm:
188 p->linktype = DLT_ATM_RFC1483;
189 break;
190
191 default:
192 p->linktype = DLT_EN10MB; /*an unknown adapter is assumed to be ethernet*/
193 break;
194 }
195
196 /* Set promisquous mode */
197 if (promisc) PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS);
198 else PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL);
199
200 /* Set the buffer size */
201 p->bufsize = PcapBufSize;
202
203 p->buffer = (u_char *)malloc(PcapBufSize);
204 if (p->buffer == NULL) {
205 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
206 goto bad;
207 }
208
209 p->snapshot = snaplen;
210
211 /* allocate Packet structure used during the capture */
212 if((p->Packet = PacketAllocatePacket())==NULL){
213 snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
214 goto bad;
215 }
216
217 PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
218
219 /* allocate the standard buffer in the driver */
220 if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE)
221 {
222 snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n");
223 goto bad;
224 }
225
226 /* tell the driver to copy the buffer only if it contains at least 16K */
227 if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
228 {
229 snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror());
230 goto bad;
231 }
232
233 PacketSetReadTimeout(p->adapter, to_ms);
234
235 return (p);
236 bad:
237 if (p->adapter)
238 PacketCloseAdapter(p->adapter);
239 if (p->buffer != NULL)
240 free(p->buffer);
241 free(p);
242 return (NULL);
243 }
244
245
246 int
247 pcap_setfilter(pcap_t *p, struct bpf_program *fp)
248 {
249 if(p->adapter==NULL){
250 /* Offline capture: make our own copy of the filter */
251 if (install_bpf_program(p, fp) < 0)
252 return (-1);
253 }
254 else if(PacketSetBpf(p->adapter,fp)==FALSE){
255 /* kernel filter not installed. */
256 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror());
257 return (-1);
258 }
259 return (0);
260 }
261
262
263 /* Set the driver working mode */
264 int
265 pcap_setmode(pcap_t *p, int mode){
266
267 if (p->adapter==NULL)
268 {
269 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file");
270 return -1;
271 }
272
273 if(PacketSetMode(p->adapter,mode)==FALSE)
274 {
275 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
276 return -1;
277 }
278
279 return 0;
280 }
281
282 /* Send a packet to the network */
283 int
284 pcap_sendpacket(pcap_t *p, u_char *buf, int size){
285 LPPACKET PacketToSend;
286
287 if (p->adapter==NULL)
288 {
289 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Writing a packet is allowed only on a physical adapter");
290 return -1;
291 }
292
293 PacketToSend=PacketAllocatePacket();
294 PacketInitPacket(PacketToSend,buf,size);
295 if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
296 PacketFreePacket(PacketToSend);
297 return -1;
298 }
299
300 PacketFreePacket(PacketToSend);
301 return 0;
302 }
303
304 /* Set the dimension of the kernel-level capture buffer */
305 int
306 pcap_setbuff(pcap_t *p, int dim)
307 {
308 if (p->adapter==NULL)
309 {
310 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file");
311 return -1;
312 }
313
314 if(PacketSetBuff(p->adapter,dim)==FALSE)
315 {
316 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
317 return -1;
318 }
319 return 0;
320 }
321
322 /*set the minimum amount of data that will release a read call*/
323 int
324 pcap_setmintocopy(pcap_t *p, int size)
325 {
326 if (p->adapter==NULL)
327 {
328 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture");
329 return -1;
330 }
331
332 if(PacketSetMinToCopy(p->adapter, size)==FALSE)
333 {
334 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
335 return -1;
336 }
337 return 0;
338 }
339
340 int
341 pcap_set_datalink_platform(pcap_t *p, int dlt)
342 {
343 return (0);
344 }