00001 /* 00002 * Copyright (c) 1999, 2000 00003 * Politecnico di Torino. All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that: (1) source code distributions 00007 * retain the above copyright notice and this paragraph in its entirety, (2) 00008 * distributions including binary code include the above copyright notice and 00009 * this paragraph in its entirety in the documentation or other materials 00010 * provided with the distribution, and (3) all advertising materials mentioning 00011 * features or use of this software display the following acknowledgement: 00012 * ``This product includes software developed by the Politecnico 00013 * di Torino, and its contributors.'' Neither the name of 00014 * the University nor the names of its contributors may be used to endorse 00015 * or promote products derived from this software without specific prior 00016 * written permission. 00017 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 00018 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 00019 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00020 */ 00021 00022 #ifndef lint 00023 static const char rcsid[] = 00024 "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.2 2002/08/05 07:45:09 guy Exp $ (LBL)"; 00025 #endif 00026 00027 #include <pcap-int.h> 00028 #include <packet32.h> 00029 #include <Ntddndis.h> 00030 #ifdef __MINGW32__ 00031 int* _errno(); 00032 #define errno (*_errno()) 00033 #endif /* __MINGW32__ */ 00034 00035 #define PcapBufSize 256000 /*dimension of the buffer in the pcap_t structure*/ 00036 #define SIZE_BUF 1000000 00037 00038 /*start winsock*/ 00039 int 00040 wsockinit() 00041 { 00042 WORD wVersionRequested; 00043 WSADATA wsaData; 00044 int err; 00045 wVersionRequested = MAKEWORD( 1, 1); 00046 err = WSAStartup( wVersionRequested, &wsaData ); 00047 if ( err != 0 ) 00048 { 00049 return -1; 00050 } 00051 return 0; 00052 } 00053 00054 00055 int 00056 pcap_stats(pcap_t *p, struct pcap_stat *ps) 00057 { 00058 00059 if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){ 00060 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror()); 00061 return -1; 00062 } 00063 00064 return 0; 00065 } 00066 00067 int 00068 pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 00069 { 00070 int cc; 00071 int n = 0; 00072 register u_char *bp, *ep; 00073 00074 cc = p->cc; 00075 if (p->cc == 0) { 00076 00077 /* capture the packets */ 00078 if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){ 00079 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed"); 00080 return (-1); 00081 } 00082 00083 cc = p->Packet->ulBytesReceived; 00084 00085 bp = p->Packet->Buffer; 00086 } 00087 else 00088 bp = p->bp; 00089 00090 /* 00091 * Loop through each packet. 00092 */ 00093 #define bhp ((struct bpf_hdr *)bp) 00094 ep = bp + cc; 00095 while (bp < ep) { 00096 register int caplen, hdrlen; 00097 caplen = bhp->bh_caplen; 00098 hdrlen = bhp->bh_hdrlen; 00099 00100 /* 00101 * XXX A bpf_hdr matches a pcap_pkthdr. 00102 */ 00103 (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); 00104 bp += BPF_WORDALIGN(caplen + hdrlen); 00105 if (++n >= cnt && cnt > 0) { 00106 p->bp = bp; 00107 p->cc = ep - bp; 00108 return (n); 00109 } 00110 } 00111 #undef bhp 00112 p->cc = 0; 00113 return (n); 00114 } 00115 00116 00117 pcap_t * 00118 pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) 00119 { 00120 register pcap_t *p; 00121 NetType type; 00122 00123 /* Init WinSock */ 00124 wsockinit(); 00125 00126 p = (pcap_t *)malloc(sizeof(*p)); 00127 if (p == NULL) { 00128 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 00129 return (NULL); 00130 } 00131 memset(p, 0, sizeof(*p)); 00132 p->adapter=NULL; 00133 00134 p->adapter=PacketOpenAdapter(device); 00135 if (p->adapter==NULL) { 00136 snprintf(ebuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror()); 00137 return NULL; 00138 } 00139 00140 /*get network type*/ 00141 if(PacketGetNetType (p->adapter,&type)==FALSE) 00142 { 00143 snprintf(ebuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror()); 00144 goto bad; 00145 } 00146 00147 /*Set the linktype*/ 00148 switch (type.LinkType) { 00149 00150 case NdisMediumWan: 00151 p->linktype = DLT_EN10MB; 00152 break; 00153 00154 case NdisMedium802_3: 00155 p->linktype = DLT_EN10MB; 00156 break; 00157 00158 case NdisMediumFddi: 00159 p->linktype = DLT_FDDI; 00160 break; 00161 00162 case NdisMedium802_5: 00163 p->linktype = DLT_IEEE802; 00164 break; 00165 00166 case NdisMediumArcnet878_2: 00167 p->linktype = DLT_ARCNET; 00168 break; 00169 00170 case NdisMediumAtm: 00171 p->linktype = DLT_ATM_RFC1483; 00172 break; 00173 00174 default: 00175 p->linktype = DLT_EN10MB; /*an unknown adapter is assumed to be ethernet*/ 00176 } 00177 00178 /* Set promisquous mode */ 00179 if (promisc) PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS); 00180 else PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL); 00181 00182 /* Set the buffer size */ 00183 p->bufsize = PcapBufSize; 00184 00185 p->buffer = (u_char *)malloc(PcapBufSize); 00186 if (p->buffer == NULL) { 00187 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 00188 goto bad; 00189 } 00190 00191 p->snapshot = snaplen; 00192 00193 /* allocate Packet structure used during the capture */ 00194 if((p->Packet = PacketAllocatePacket())==NULL){ 00195 snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure"); 00196 goto bad; 00197 } 00198 00199 PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize); 00200 00201 /* allocate the standard buffer in the driver */ 00202 if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE) 00203 { 00204 snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n"); 00205 goto bad; 00206 } 00207 00208 /* tell the driver to copy the buffer only if it contains at least 16K */ 00209 if(PacketSetMinToCopy(p->adapter,16000)==FALSE) 00210 { 00211 snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror()); 00212 goto bad; 00213 } 00214 00215 PacketSetReadTimeout(p->adapter, to_ms); 00216 00217 return (p); 00218 bad: 00219 if (p->adapter) 00220 PacketCloseAdapter(p->adapter); 00221 if (p->buffer != NULL) 00222 free(p->buffer); 00223 free(p); 00224 return (NULL); 00225 } 00226 00227 00228 int 00229 pcap_setfilter(pcap_t *p, struct bpf_program *fp) 00230 { 00231 if(p->adapter==NULL){ 00232 /* Offline capture: make our own copy of the filter */ 00233 if (install_bpf_program(p, fp) < 0) 00234 return (-1); 00235 } 00236 else if(PacketSetBpf(p->adapter,fp)==FALSE){ 00237 /* kernel filter not installed. */ 00238 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror()); 00239 return (-1); 00240 } 00241 return (0); 00242 } 00243 00244 00245 /* Set the driver working mode */ 00246 int 00247 pcap_setmode(pcap_t *p, int mode){ 00248 00249 if (p->adapter==NULL) 00250 { 00251 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file"); 00252 return -1; 00253 } 00254 00255 if(PacketSetMode(p->adapter,mode)==FALSE) 00256 { 00257 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized"); 00258 return -1; 00259 } 00260 00261 return 0; 00262 } 00263 00264 /* Send a packet to the network */ 00265 int 00266 pcap_sendpacket(pcap_t *p, u_char *buf, int size){ 00267 LPPACKET PacketToSend; 00268 00269 if (p->adapter==NULL) 00270 { 00271 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Writing a packet is allowed only on a physical adapter"); 00272 return -1; 00273 } 00274 00275 PacketToSend=PacketAllocatePacket(); 00276 PacketInitPacket(PacketToSend,buf,size); 00277 if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){ 00278 PacketFreePacket(PacketToSend); 00279 return -1; 00280 } 00281 00282 PacketFreePacket(PacketToSend); 00283 return 0; 00284 } 00285 00286 /* Set the dimension of the kernel-level capture buffer */ 00287 int 00288 pcap_setbuff(pcap_t *p, int dim) 00289 { 00290 if (p->adapter==NULL) 00291 { 00292 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file"); 00293 return -1; 00294 } 00295 00296 if(PacketSetBuff(p->adapter,dim)==FALSE) 00297 { 00298 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer"); 00299 return -1; 00300 } 00301 return 0; 00302 } 00303 00304 /*set the minimum amount of data that will release a read call*/ 00305 int 00306 pcap_setmintocopy(pcap_t *p, int size) 00307 { 00308 if (p->adapter==NULL) 00309 { 00310 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture"); 00311 return -1; 00312 } 00313 00314 if(PacketSetMinToCopy(p->adapter, size)==FALSE) 00315 { 00316 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size"); 00317 return -1; 00318 } 00319 return 0; 00320 } 00321 00322
documentation. Copyright (c) 2002 Politecnico di Torino. All rights reserved.