Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

# Pcap-win32.c

Go to the documentation of this file.

    00001 /*
    00002  * Copyright (c) 1999 - 2003
    00003  * NetGroup, Politecnico di Torino (Italy)
    00004  * All rights reserved.
    00005  *
    00006  * Redistribution and use in source and binary forms, with or without
    00007  * modification, are permitted provided that the following conditions
    00008  * are met:
    00009  *
    00010  * 1. Redistributions of source code must retain the above copyright
    00011  * notice, this list of conditions and the following disclaimer.
    00012  * 2. Redistributions in binary form must reproduce the above copyright
    00013  * notice, this list of conditions and the following disclaimer in the
    00014  * documentation and/or other materials provided with the distribution.
    00015  * 3. Neither the name of the Politecnico di Torino nor the names of its
    00016  * contributors may be used to endorse or promote products derived from
    00017  * this software without specific prior written permission.
    00018  *
    00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    00020  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    00022  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    00023  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    00024  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    00025  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    00026  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    00027  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00028  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    00029  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00030  *
    00031  */
    00032
    00033 #ifndef lint
    00034 static const char rcsid[] _U_ =
    00035     "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.15.2.5 2004/06/16 15:51:32 risso Exp $ (LBL)";
    00036 #endif
    00037
    00038 #include <pcap-int.h>
    00039 #include <packet32.h>
    00040 #include <Ntddndis.h>
    00041 #ifdef __MINGW32__
    00042 int* _errno();
    00043 #define errno (*_errno())
    00044 #endif /* __MINGW32__ */
    00045
    00046 #ifdef HAVE_REMOTE
    00047 #include <pcap-remote.h>
    00048 #endif  /* HAVE_REMOTE */
    00049
    00050
    00051 static int pcap_setfilter_win32(pcap_t *, struct bpf_program *);
    00052 static int pcap_getnonblock_win32(pcap_t *, char *);
    00053 static int pcap_setnonblock_win32(pcap_t *, int, char *);
    00054
    00055 #define PcapBufSize 256000  /*dimension of the buffer in the pcap_t structure*/
    00056 #define SIZE_BUF 1000000
    00057
    00058 /*
    00059  * Header that the WinPcap driver associates to the packets.
    00060  * Once was in bpf.h
    00061  */
    00062 struct bpf_hdr {
    00063     struct timeval  bh_tstamp;  /* time stamp */
    00064     bpf_u_int32 bh_caplen;  /* length of captured portion */
    00065     bpf_u_int32 bh_datalen; /* original length of packet */
    00066     u_short     bh_hdrlen;  /* length of bpf header (this struct
    00067                        plus alignment padding) */
    00068 };
    00069
    00070 /* Start winsock */
    00071 int
    00072 wsockinit()
    00073 {
    00074     WORD wVersionRequested;
    00075     WSADATA wsaData;
    00076     int err;
    00077     wVersionRequested = MAKEWORD( 1, 1);
    00078     err = WSAStartup( wVersionRequested, &wsaData );
    00079     if ( err != 0 )
    00080     {
    00081         return -1;
    00082     }
    00083     return 0;
    00084 }
    00085
    00086
    00087 static int
    00088 pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
    00089 {
    00090
    00091     if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){
    00092         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror());
    00093         return -1;
    00094     }
    00095
    00096     return 0;
    00097 }
    00098
    00099 static int
    00100 pcap_read_win32(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
    00101 {
    00102     int cc;
    00103     int n = 0;
    00104     register u_char *bp, *ep;
    00105
    00106 #ifdef HAVE_REMOTE
    00107     static int samp_npkt;               // parameter needed for sampling, with '1 out of N' method has been requested
    00108     static struct timeval samp_time;    // parameter needed for sampling, with '1 every N ms' method has been requested
    00109 #endif  /* HAVE_REMOTE */
    00110
    00111     cc = p->cc;
    00112     if (p->cc == 0) {
    00113         /*
    00114          * Has "pcap_breakloop()" been called?
    00115          */
    00116         if (p->break_loop) {
    00117             /*
    00118              * Yes - clear the flag that indicates that it
    00119              * has, and return -2 to indicate that we were
    00120              * told to break out of the loop.
    00121              */
    00122             p->break_loop = 0;
    00123             return (-2);
    00124         }
    00125
    00126         /* capture the packets */
    00127         if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){
    00128             snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
    00129             return (-1);
    00130         }
    00131
    00132         cc = p->Packet->ulBytesReceived;
    00133
    00134         bp = p->Packet->Buffer;
    00135     }
    00136     else
    00137         bp = p->bp;
    00138
    00139     /*
    00140      * Loop through each packet.
    00141      */
    00142 #define bhp ((struct bpf_hdr *)bp)
    00143     ep = bp + cc;
    00144     while (1) {
    00145         register int caplen, hdrlen;
    00146
    00147         /*
    00148          * Has "pcap_breakloop()" been called?
    00149          * If so, return immediately - if we haven't read any
    00150          * packets, clear the flag and return -2 to indicate
    00151          * that we were told to break out of the loop, otherwise
    00152          * leave the flag set, so that the *next* call will break
    00153          * out of the loop without having read any packets, and
    00154          * return the number of packets we've processed so far.
    00155          */
    00156         if (p->break_loop) {
    00157             if (n == 0) {
    00158                 p->break_loop = 0;
    00159                 return (-2);
    00160             } else {
    00161                 p->bp = bp;
    00162                 p->cc = ep - bp;
    00163                 return (n);
    00164             }
    00165         }
    00166         if (bp >= ep)
    00167             break;
    00168
    00169         caplen = bhp->bh_caplen;
    00170         hdrlen = bhp->bh_hdrlen;
    00171
    00172 #ifdef HAVE_REMOTE
    00173         if (p->rmt_samp.method == PCAP_SAMP_1_EVERY_N)
    00174         {
    00175             samp_npkt= (samp_npkt + 1) % p->rmt_samp.value;
    00176
    00177             // Discard all packets that are not '1 out of N'
    00178             if (samp_npkt != 0)
    00179             {
    00180                 bp += BPF_WORDALIGN(caplen + hdrlen);
    00181                 continue;
    00182             }
    00183         }
    00184
    00185         if (p->rmt_samp.method == PCAP_SAMP_FIRST_AFTER_N_MS)
    00186         {
    00187         struct pcap_pkthdr *pkt_header= (struct pcap_pkthdr*) bp;
    00188
    00189             // Check if the timestamp of the arrived packet is smaller than our target time
    00190             if ( (pkt_header->ts.tv_sec < samp_time.tv_sec) ||
    00191                     ( (pkt_header->ts.tv_sec == samp_time.tv_sec) && (pkt_header->ts.tv_usec < samp_time.tv_usec) ) )
    00192             {
    00193                 bp += BPF_WORDALIGN(caplen + hdrlen);
    00194                 continue;
    00195             }
    00196
    00197             // The arrived packet is suitable for being sent to the remote host
    00198             // So, let's update the target time
    00199             samp_time.tv_usec= pkt_header->ts.tv_usec + p->rmt_samp.value * 1000;
    00200             if (samp_time.tv_usec > 1000000)
    00201             {
    00202                 samp_time.tv_sec= pkt_header->ts.tv_sec + samp_time.tv_usec / 1000000;
    00203                 samp_time.tv_usec= samp_time.tv_usec % 1000000;
    00204             }
    00205         }
    00206 #endif  /* HAVE_REMOTE */
    00207
    00208         /*
    00209          * XXX A bpf_hdr matches a pcap_pkthdr.
    00210          */
    00211         (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
    00212         bp += BPF_WORDALIGN(caplen + hdrlen);
    00213         if (++n >= cnt && cnt > 0) {
    00214             p->bp = bp;
    00215             p->cc = ep - bp;
    00216             return (n);
    00217         }
    00218     }
    00219 #undef bhp
    00220     p->cc = 0;
    00221     return (n);
    00222 }
    00223
    00224
    00225 static void
    00226 pcap_close_win32(pcap_t *p)
    00227 {
    00228     if (p->buffer != NULL)
    00229         free(p->buffer);
    00230     if (p->adapter != NULL) {
    00231         PacketCloseAdapter(p->adapter);
    00232         p->adapter = NULL;
    00233     }
    00234     if (p->Packet) {
    00235         PacketFreePacket(p->Packet);
    00236         p->Packet = NULL;
    00237     }
    00238 }
    00239
    00240 pcap_t *
    00241 pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
    00242     char *ebuf)
    00243 {
    00244     register pcap_t *p;
    00245     NetType type;
    00246
    00247 #ifdef HAVE_REMOTE
    00248     char host[PCAP_BUF_SIZE + 1];
    00249     char port[PCAP_BUF_SIZE + 1];
    00250     char name[PCAP_BUF_SIZE + 1];
    00251     int srctype;
    00252
    00253     /*
    00254         Retrofit; we have to make older applications compatible with the remote capture
    00255         So, we're calling the pcap_open_remote() from here, that is a very dirty thing.
    00256         Obviously, we cannot exploit all the new features; for instance, we cannot
    00257         send authentication, we cannot use a UDP data connection, and so on.
    00258     */
    00259     if (pcap_parsesrcstr(device, &srctype, host, port, name, ebuf) )
    00260         return NULL;
    00261
    00262     if (srctype == PCAP_SRC_IFREMOTE)
    00263     {
    00264         p= pcap_opensource_remote(device, NULL, ebuf);
    00265
    00266         if (p == NULL)
    00267             return NULL;
    00268
    00269         p->snapshot= snaplen;
    00270         p->timeout= to_ms;
    00271         p->rmt_flags= (promisc) ? PCAP_OPENFLAG_PROMISCUOUS : 0;
    00272
    00273         return p;
    00274     }
    00275 #endif  /* HAVE_REMOTE */
    00276
    00277     /* Init WinSock */
    00278     wsockinit();
    00279
    00280     p = (pcap_t *)malloc(sizeof(*p));
    00281     if (p == NULL)
    00282     {
    00283         snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
    00284         return (NULL);
    00285     }
    00286     memset(p, 0, sizeof(*p));
    00287     p->adapter=NULL;
    00288
    00289     p->adapter = PacketOpenAdapter((char*)device);
    00290
    00291     if (p->adapter == NULL)
    00292     {
    00293         /* Adapter detected but we are not able to open it. Return failure. */
    00294         snprintf(ebuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
    00295         return NULL;
    00296     }
    00297
    00298     /*get network type*/
    00299     if(PacketGetNetType (p->adapter,&type) == FALSE)
    00300     {
    00301         snprintf(ebuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
    00302         goto bad;
    00303     }
    00304
    00305     /*Set the linktype*/
    00306     switch (type.LinkType)
    00307     {
    00308     case NdisMediumWan:
    00309         p->linktype = DLT_EN10MB;
    00310         break;
    00311
    00312     case NdisMedium802_3:
    00313         p->linktype = DLT_EN10MB;
    00314         break;
    00315
    00316     case NdisMediumFddi:
    00317         p->linktype = DLT_FDDI;
    00318         break;
    00319
    00320     case NdisMedium802_5:
    00321         p->linktype = DLT_IEEE802;
    00322         break;
    00323
    00324     case NdisMediumArcnetRaw:
    00325         p->linktype = DLT_ARCNET;
    00326         break;
    00327
    00328     case NdisMediumArcnet878_2:
    00329         p->linktype = DLT_ARCNET;
    00330         break;
    00331
    00332     case NdisMediumAtm:
    00333         p->linktype = DLT_ATM_RFC1483;
    00334         break;
    00335
    00336     default:
    00337         p->linktype = DLT_EN10MB;           /*an unknown adapter is assumed to be ethernet*/
    00338         break;
    00339     }
    00340
    00341     /* Set promisquous mode */
    00342     if (promisc) PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS);
    00343      else PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL);
    00344
    00345     /* Set the buffer size */
    00346     p->bufsize = PcapBufSize;
    00347
    00348     p->buffer = (u_char *)malloc(PcapBufSize);
    00349     if (p->buffer == NULL)
    00350     {
    00351         snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
    00352         goto bad;
    00353     }
    00354
    00355     p->snapshot = snaplen;
    00356
    00357     /* allocate Packet structure used during the capture */
    00358     if((p->Packet = PacketAllocatePacket())==NULL)
    00359     {
    00360         snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
    00361         goto bad;
    00362     }
    00363
    00364     PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
    00365
    00366     /* allocate the standard buffer in the driver */
    00367     if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE)
    00368     {
    00369         snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n");
    00370         goto bad;
    00371     }
    00372
    00373     /* tell the driver to copy the buffer only if it contains at least 16K */
    00374     if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
    00375     {
    00376         snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror());
    00377         goto bad;
    00378     }
    00379
    00380     PacketSetReadTimeout(p->adapter, to_ms);
    00381
    00382     p->read_op = pcap_read_win32;
    00383     p->setfilter_op = pcap_setfilter_win32;
    00384     p->set_datalink_op = NULL;  /* can't change data link type */
    00385     p->getnonblock_op = pcap_getnonblock_win32;
    00386     p->setnonblock_op = pcap_setnonblock_win32;
    00387     p->stats_op = pcap_stats_win32;
    00388     p->close_op = pcap_close_win32;
    00389
    00390     return (p);
    00391 bad:
    00392     if (p->adapter)
    00393         PacketCloseAdapter(p->adapter);
    00394     if (p->buffer != NULL)
    00395         free(p->buffer);
    00396     free(p);
    00397     return (NULL);
    00398 }
    00399
    00400
    00401 static int
    00402 pcap_setfilter_win32(pcap_t *p, struct bpf_program *fp)
    00403 {
    00404     if(PacketSetBpf(p->adapter,fp)==FALSE){
    00405         /* kernel filter not installed. */
    00406         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror());
    00407         return (-1);
    00408     }
    00409     return (0);
    00410 }
    00411
    00412
    00413 static int
    00414 pcap_getnonblock_win32(pcap_t *p, char *errbuf)
    00415 {
    00416     /*
    00417      * XXX - if there were a PacketGetReadTimeout() call, we
    00418      * would use it, and return 1 if the timeout is -1
    00419      * and 0 otherwise.
    00420      */
    00421     return (p->nonblock);
    00422 }
    00423
    00424 static int
    00425 pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
    00426 {
    00427     int newtimeout;
    00428
    00429     if (nonblock) {
    00430         /*
    00431          * Set the read timeout to -1 for non-blocking mode.
    00432          */
    00433         newtimeout = -1;
    00434     } else {
    00435         /*
    00436          * Restore the timeout set when the device was opened.
    00437          * (Note that this may be -1, in which case we're not
    00438          * really leaving non-blocking mode.)
    00439          */
    00440         newtimeout = p->timeout;
    00441     }
    00442     if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
    00443         snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    00444             "PacketSetReadTimeout: %s", pcap_win32strerror());
    00445         return (-1);
    00446     }
    00447     p->nonblock = (newtimeout == -1);
    00448     return (0);
    00449 }
    00450
    00451 /* Set the driver working mode */
    00452 int
    00453 pcap_setmode(pcap_t *p, int mode){
    00454
    00455     if (p->adapter==NULL)
    00456     {
    00457         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file");
    00458         return -1;
    00459     }
    00460
    00461     if(PacketSetMode(p->adapter,mode)==FALSE)
    00462     {
    00463         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
    00464         return -1;
    00465     }
    00466
    00467     return 0;
    00468 }
    00469
    00470 /* Send a packet to the network */
    00471 int
    00472 pcap_sendpacket(pcap_t *p, u_char *buf, int size){
    00473     LPPACKET PacketToSend;
    00474
    00475     if (p->adapter==NULL)
    00476     {
    00477         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Writing a packet is allowed only on a physical adapter");
    00478         return -1;
    00479     }
    00480
    00481     PacketToSend=PacketAllocatePacket();
    00482
    00483     if (PacketToSend == NULL)
    00484     {
    00485         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketAllocatePacket failed");
    00486         return -1;
    00487     }
    00488
    00489     PacketInitPacket(PacketToSend,buf,size);
    00490     if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
    00491         PacketFreePacket(PacketToSend);
    00492         return -1;
    00493     }
    00494
    00495     PacketFreePacket(PacketToSend);
    00496     return 0;
    00497 }
    00498
    00499 /* Set the dimension of the kernel-level capture buffer */
    00500 int
    00501 pcap_setbuff(pcap_t *p, int dim)
    00502 {
    00503 #ifdef HAVE_REMOTE
    00504     if (p->rmt_clientside)
    00505     {
    00506         /* Currently, this is a bug: the capture buffer cannot be set with remote capture */
    00507         return 0;
    00508     }
    00509 #endif  /* HAVE_REMOTE */
    00510
    00511     if (p->adapter==NULL)
    00512     {
    00513         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file");
    00514         return -1;
    00515     }
    00516
    00517     if(PacketSetBuff(p->adapter,dim)==FALSE)
    00518     {
    00519         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
    00520         return -1;
    00521     }
    00522     return 0;
    00523 }
    00524
    00525 /*set the minimum amount of data that will release a read call*/
    00526 int
    00527 pcap_setmintocopy(pcap_t *p, int size)
    00528 {
    00529     if (p->adapter==NULL)
    00530     {
    00531         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture");
    00532         return -1;
    00533     }
    00534
    00535     if(PacketSetMinToCopy(p->adapter, size)==FALSE)
    00536     {
    00537         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
    00538         return -1;
    00539     }
    00540     return 0;
    00541 }

documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.