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.6 2003/01/23 09:40: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 #ifdef HAVE_REMOTE 00036 #include <pcap-remote.h> 00037 #endif 00038 00039 #define PcapBufSize 256000 /*dimension of the buffer in the pcap_t structure*/ 00040 #define SIZE_BUF 1000000 00041 00042 /*start winsock*/ 00043 int 00044 wsockinit() 00045 { 00046 WORD wVersionRequested; 00047 WSADATA wsaData; 00048 int err; 00049 wVersionRequested = MAKEWORD( 1, 1); 00050 err = WSAStartup( wVersionRequested, &wsaData ); 00051 if ( err != 0 ) 00052 { 00053 return -1; 00054 } 00055 return 0; 00056 } 00057 00058 00059 int 00060 pcap_stats(pcap_t *p, struct pcap_stat *ps) 00061 { 00062 #ifdef HAVE_REMOTE 00063 if (p->rmt_clientside) 00064 { 00065 /* We are on an remote capture */ 00066 return pcap_stats_remote(p, ps); 00067 } 00068 #endif 00069 00070 if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){ 00071 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror()); 00072 return -1; 00073 } 00074 00075 return 0; 00076 } 00077 00078 int 00079 pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 00080 { 00081 int cc; 00082 int n = 0; 00083 register u_char *bp, *ep; 00084 00085 #ifdef HAVE_REMOTE 00086 if (p->rmt_clientside) 00087 { 00088 /* We are on an remote capture */ 00089 if (!p->rmt_capstarted) 00090 { 00091 // if the capture has not started yet, please start it 00092 if (pcap_startcapture_remote(p) ) 00093 return -1; 00094 p->rmt_capstarted= 1; 00095 } 00096 return pcap_read_remote(p, cnt, callback, user); 00097 } 00098 #endif 00099 00100 cc = p->cc; 00101 if (p->cc == 0) { 00102 00103 /* capture the packets */ 00104 if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){ 00105 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed"); 00106 return (-1); 00107 } 00108 00109 cc = p->Packet->ulBytesReceived; 00110 00111 bp = p->Packet->Buffer; 00112 } 00113 else 00114 bp = p->bp; 00115 00116 /* 00117 * Loop through each packet. 00118 */ 00119 #define bhp ((struct bpf_hdr *)bp) 00120 ep = bp + cc; 00121 while (bp < ep) { 00122 register int caplen, hdrlen; 00123 caplen = bhp->bh_caplen; 00124 hdrlen = bhp->bh_hdrlen; 00125 00126 /* 00127 * XXX A bpf_hdr matches a pcap_pkthdr. 00128 */ 00129 (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); 00130 bp += BPF_WORDALIGN(caplen + hdrlen); 00131 if (++n >= cnt && cnt > 0) { 00132 p->bp = bp; 00133 p->cc = ep - bp; 00134 return (n); 00135 } 00136 } 00137 #undef bhp 00138 p->cc = 0; 00139 return (n); 00140 } 00141 00142 00143 pcap_t * 00144 pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, 00145 char *ebuf) 00146 { 00147 register pcap_t *p; 00148 NetType type; 00149 00150 #ifdef HAVE_REMOTE 00151 /* 00152 Retrofit; we have to make older applications compatible with the remote capture 00153 So, we're calling the pcap_open_remote() from here, that is a very dirty thing. 00154 Obviously, we cannot exploit all the new features; for instance, we cannot 00155 send authentication, we cannot use a UDP data connection, and so on. 00156 */ 00157 00158 char host[PCAP_BUF_SIZE + 1]; 00159 char port[PCAP_BUF_SIZE + 1]; 00160 char name[PCAP_BUF_SIZE + 1]; 00161 int srctype; 00162 00163 if (pcap_parsesrcstr(device, &srctype, host, port, name, ebuf) ) 00164 return NULL; 00165 00166 if (srctype == PCAP_SRC_IFREMOTE) 00167 { 00168 p= pcap_opensource_remote(device, NULL, ebuf); 00169 00170 if (p == NULL) 00171 return NULL; 00172 00173 p->snapshot= snaplen; 00174 p->timeout= to_ms; 00175 p->rmt_flags= (promisc) ? PCAP_OPENFLAG_PROMISCUOUS : 0; 00176 00177 return p; 00178 } 00179 #endif 00180 00181 /* Init WinSock */ 00182 wsockinit(); 00183 00184 p = (pcap_t *)malloc(sizeof(*p)); 00185 if (p == NULL) { 00186 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 00187 return (NULL); 00188 } 00189 memset(p, 0, sizeof(*p)); 00190 p->adapter=NULL; 00191 00192 p->adapter=PacketOpenAdapter(device); 00193 if (p->adapter==NULL) { 00194 snprintf(ebuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror()); 00195 return NULL; 00196 } 00197 00198 /*get network type*/ 00199 if(PacketGetNetType (p->adapter,&type)==FALSE) 00200 { 00201 snprintf(ebuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror()); 00202 goto bad; 00203 } 00204 00205 /*Set the linktype*/ 00206 switch (type.LinkType) { 00207 00208 case NdisMediumWan: 00209 p->linktype = DLT_EN10MB; 00210 break; 00211 00212 case NdisMedium802_3: 00213 p->linktype = DLT_EN10MB; 00214 break; 00215 00216 case NdisMediumFddi: 00217 p->linktype = DLT_FDDI; 00218 break; 00219 00220 case NdisMedium802_5: 00221 p->linktype = DLT_IEEE802; 00222 break; 00223 00224 case NdisMediumArcnetRaw: 00225 p->linktype = DLT_ARCNET; 00226 break; 00227 00228 case NdisMediumArcnet878_2: 00229 p->linktype = DLT_ARCNET; 00230 break; 00231 00232 case NdisMediumAtm: 00233 p->linktype = DLT_ATM_RFC1483; 00234 break; 00235 00236 default: 00237 p->linktype = DLT_EN10MB; /*an unknown adapter is assumed to be ethernet*/ 00238 break; 00239 } 00240 00241 /* Set promisquous mode */ 00242 if (promisc) PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS); 00243 else PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL); 00244 00245 /* Set the buffer size */ 00246 p->bufsize = PcapBufSize; 00247 00248 p->buffer = (u_char *)malloc(PcapBufSize); 00249 if (p->buffer == NULL) { 00250 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); 00251 goto bad; 00252 } 00253 00254 p->snapshot = snaplen; 00255 00256 /* allocate Packet structure used during the capture */ 00257 if((p->Packet = PacketAllocatePacket())==NULL){ 00258 snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure"); 00259 goto bad; 00260 } 00261 00262 PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize); 00263 00264 /* allocate the standard buffer in the driver */ 00265 if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE) 00266 { 00267 snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n"); 00268 goto bad; 00269 } 00270 00271 /* tell the driver to copy the buffer only if it contains at least 16K */ 00272 if(PacketSetMinToCopy(p->adapter,16000)==FALSE) 00273 { 00274 snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror()); 00275 goto bad; 00276 } 00277 00278 PacketSetReadTimeout(p->adapter, to_ms); 00279 00280 return (p); 00281 bad: 00282 if (p->adapter) 00283 PacketCloseAdapter(p->adapter); 00284 if (p->buffer != NULL) 00285 free(p->buffer); 00286 free(p); 00287 return (NULL); 00288 } 00289 00290 00291 int 00292 pcap_setfilter(pcap_t *p, struct bpf_program *fp) 00293 { 00294 #ifdef HAVE_REMOTE 00295 if (p->rmt_clientside) 00296 { 00297 /* We are on an remote capture */ 00298 return pcap_setfilter_remote(p, fp); 00299 } 00300 #endif 00301 00302 if(p->adapter==NULL){ 00303 /* Offline capture: make our own copy of the filter */ 00304 if (install_bpf_program(p, fp) < 0) 00305 return (-1); 00306 } 00307 else if(PacketSetBpf(p->adapter,fp)==FALSE){ 00308 /* kernel filter not installed. */ 00309 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror()); 00310 return (-1); 00311 } 00312 return (0); 00313 } 00314 00315 00316 /* Set the driver working mode */ 00317 int 00318 pcap_setmode(pcap_t *p, int mode){ 00319 00320 if (p->adapter==NULL) 00321 { 00322 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file"); 00323 return -1; 00324 } 00325 00326 if(PacketSetMode(p->adapter,mode)==FALSE) 00327 { 00328 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized"); 00329 return -1; 00330 } 00331 00332 return 0; 00333 } 00334 00335 /* Send a packet to the network */ 00336 int 00337 pcap_sendpacket(pcap_t *p, u_char *buf, int size){ 00338 LPPACKET PacketToSend; 00339 00340 if (p->adapter==NULL) 00341 { 00342 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Writing a packet is allowed only on a physical adapter"); 00343 return -1; 00344 } 00345 00346 PacketToSend=PacketAllocatePacket(); 00347 PacketInitPacket(PacketToSend,buf,size); 00348 if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){ 00349 PacketFreePacket(PacketToSend); 00350 return -1; 00351 } 00352 00353 PacketFreePacket(PacketToSend); 00354 return 0; 00355 } 00356 00357 /* Set the dimension of the kernel-level capture buffer */ 00358 int 00359 pcap_setbuff(pcap_t *p, int dim) 00360 { 00361 #ifdef HAVE_REMOTE 00362 if (p->rmt_clientside) 00363 { 00364 /* Currently, this is a bug: the capture buffer cannot be set with remote capture */ 00365 return 0; 00366 } 00367 #endif 00368 00369 if (p->adapter==NULL) 00370 { 00371 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file"); 00372 return -1; 00373 } 00374 00375 if(PacketSetBuff(p->adapter,dim)==FALSE) 00376 { 00377 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer"); 00378 return -1; 00379 } 00380 return 0; 00381 } 00382 00383 /*set the minimum amount of data that will release a read call*/ 00384 int 00385 pcap_setmintocopy(pcap_t *p, int size) 00386 { 00387 if (p->adapter==NULL) 00388 { 00389 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture"); 00390 return -1; 00391 } 00392 00393 if(PacketSetMinToCopy(p->adapter, size)==FALSE) 00394 { 00395 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size"); 00396 return -1; 00397 } 00398 return 0; 00399 } 00400 00401 int 00402 pcap_set_datalink_platform(pcap_t *p, int dlt) 00403 { 00404 return (0); 00405 }
documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.