2 * Copyright (c) 1999, 2000
3 * Politecnico di Torino. All rights reserved.
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
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.
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)";
32 #define errno (*_errno())
33 #endif /* __MINGW32__ */
35 #define PcapBufSize 256000 /*dimension of the buffer in the pcap_t structure*/
36 #define SIZE_BUF 1000000
42 WORD wVersionRequested
;
45 wVersionRequested
= MAKEWORD( 1, 1);
46 err
= WSAStartup( wVersionRequested
, &wsaData
);
56 pcap_stats(pcap_t
*p
, struct pcap_stat
*ps
)
59 if(PacketGetStats(p
->adapter
, (struct bpf_stat
*)ps
) != TRUE
){
60 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
, "PacketGetStats error: %s", pcap_win32strerror());
68 pcap_read(pcap_t
*p
, int cnt
, pcap_handler callback
, u_char
*user
)
72 register u_char
*bp
, *ep
;
77 /* capture the packets */
78 if(PacketReceivePacket(p
->adapter
,p
->Packet
,TRUE
)==FALSE
){
79 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
, "read error: PacketReceivePacket failed");
83 cc
= p
->Packet
->ulBytesReceived
;
85 bp
= p
->Packet
->Buffer
;
91 * Loop through each packet.
93 #define bhp ((struct bpf_hdr *)bp)
96 register int caplen
, hdrlen
;
97 caplen
= bhp
->bh_caplen
;
98 hdrlen
= bhp
->bh_hdrlen
;
101 * XXX A bpf_hdr matches a pcap_pkthdr.
103 (*callback
)(user
, (struct pcap_pkthdr
*)bp
, bp
+ hdrlen
);
104 bp
+= BPF_WORDALIGN(caplen
+ hdrlen
);
105 if (++n
>= cnt
&& cnt
> 0) {
118 pcap_open_live(char *device
, int snaplen
, int promisc
, int to_ms
, char *ebuf
)
126 p
= (pcap_t
*)malloc(sizeof(*p
));
128 snprintf(ebuf
, PCAP_ERRBUF_SIZE
, "malloc: %s", pcap_strerror(errno
));
131 memset(p
, 0, sizeof(*p
));
134 p
->adapter
=PacketOpenAdapter(device
);
135 if (p
->adapter
==NULL
) {
136 snprintf(ebuf
, PCAP_ERRBUF_SIZE
, "Error opening adapter: %s", pcap_win32strerror());
141 if(PacketGetNetType (p
->adapter
,&type
)==FALSE
)
143 snprintf(ebuf
, PCAP_ERRBUF_SIZE
, "Cannot determine the network type: %s", pcap_win32strerror());
148 switch (type
.LinkType
) {
151 p
->linktype
= DLT_EN10MB
;
154 case NdisMedium802_3
:
155 p
->linktype
= DLT_EN10MB
;
159 p
->linktype
= DLT_FDDI
;
162 case NdisMedium802_5
:
163 p
->linktype
= DLT_IEEE802
;
166 case NdisMediumArcnet878_2
:
167 p
->linktype
= DLT_ARCNET
;
171 p
->linktype
= DLT_ATM_RFC1483
;
175 p
->linktype
= DLT_EN10MB
; /*an unknown adapter is assumed to be ethernet*/
178 /* Set promisquous mode */
179 if (promisc
) PacketSetHwFilter(p
->adapter
,NDIS_PACKET_TYPE_PROMISCUOUS
);
180 else PacketSetHwFilter(p
->adapter
,NDIS_PACKET_TYPE_ALL_LOCAL
);
182 /* Set the buffer size */
183 p
->bufsize
= PcapBufSize
;
185 p
->buffer
= (u_char
*)malloc(PcapBufSize
);
186 if (p
->buffer
== NULL
) {
187 snprintf(ebuf
, PCAP_ERRBUF_SIZE
, "malloc: %s", pcap_strerror(errno
));
191 p
->snapshot
= snaplen
;
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");
199 PacketInitPacket(p
->Packet
,(BYTE
*)p
->buffer
,p
->bufsize
);
201 /* allocate the standard buffer in the driver */
202 if(PacketSetBuff( p
->adapter
, SIZE_BUF
)==FALSE
)
204 snprintf(ebuf
, PCAP_ERRBUF_SIZE
,"driver error: not enough memory to allocate the kernel buffer\n");
208 /* tell the driver to copy the buffer only if it contains at least 16K */
209 if(PacketSetMinToCopy(p
->adapter
,16000)==FALSE
)
211 snprintf(ebuf
, PCAP_ERRBUF_SIZE
,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror());
215 PacketSetReadTimeout(p
->adapter
, to_ms
);
220 PacketCloseAdapter(p
->adapter
);
221 if (p
->buffer
!= NULL
)
229 pcap_setfilter(pcap_t
*p
, struct bpf_program
*fp
)
231 if(p
->adapter
==NULL
){
232 /* Offline capture: make our own copy of the filter */
233 if (install_bpf_program(p
, fp
) < 0)
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());
245 /* Set the driver working mode */
247 pcap_setmode(pcap_t
*p
, int mode
){
249 if (p
->adapter
==NULL
)
251 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
, "impossible to set mode while reading from a file");
255 if(PacketSetMode(p
->adapter
,mode
)==FALSE
)
257 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
, "driver error: working mode not recognized");
264 /* Send a packet to the network */
266 pcap_sendpacket(pcap_t
*p
, u_char
*buf
, int size
){
267 LPPACKET PacketToSend
;
269 if (p
->adapter
==NULL
)
271 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
, "Writing a packet is allowed only on a physical adapter");
275 PacketToSend
=PacketAllocatePacket();
276 PacketInitPacket(PacketToSend
,buf
,size
);
277 if(PacketSendPacket(p
->adapter
,PacketToSend
,TRUE
) == FALSE
){
278 PacketFreePacket(PacketToSend
);
282 PacketFreePacket(PacketToSend
);
286 /* Set the dimension of the kernel-level capture buffer */
288 pcap_setbuff(pcap_t
*p
, int dim
)
290 if (p
->adapter
==NULL
)
292 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
, "The kernel buffer size cannot be set while reading from a file");
296 if(PacketSetBuff(p
->adapter
,dim
)==FALSE
)
298 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
, "driver error: not enough memory to allocate the kernel buffer");
304 /*set the minimum amount of data that will release a read call*/
306 pcap_setmintocopy(pcap_t
*p
, int size
)
308 if (p
->adapter
==NULL
)
310 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
, "Impossible to set the mintocopy parameter on an offline capture");
314 if(PacketSetMinToCopy(p
->adapter
, size
)==FALSE
)
316 snprintf(p
->errbuf
, PCAP_ERRBUF_SIZE
, "driver error: unable to set the requested mintocopy size");