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.19 2003/12/18 23:32:33 guy Exp $ (LBL)";
    00036 #endif
    00037
    00038 #include <pcap-int.h>
    00039 #include <packet32.h>
    00040 #include <Ntddndis.h>
    00041 #ifdef HAVE_DAG_API
    00042 #include <dagnew.h>
    00043 #include <dagapi.h>
    00044 #endif /* HAVE_DAG_API */
    00045 #ifdef __MINGW32__
    00046 int* _errno();
    00047 #define errno (*_errno())
    00048 #endif /* __MINGW32__ */
    00049
    00050 #ifdef HAVE_REMOTE
    00051 #include <pcap-remote.h>
    00052 #endif  /* HAVE_REMOTE */
    00053
    00054
    00055 static int pcap_setfilter_win32_npf(pcap_t *, struct bpf_program *);
    00056 static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
    00057 static int pcap_getnonblock_win32(pcap_t *, char *);
    00058 static int pcap_setnonblock_win32(pcap_t *, int, char *);
    00059
    00060 #define PcapBufSize 256000  /*dimension of the buffer in the pcap_t structure*/
    00061 #define SIZE_BUF 1000000
    00062
    00063 /* Equivalent to ntohs(), but a lot faster under Windows */
    00064 #define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
    00065
    00066 /*
    00067  * Header that the WinPcap driver associates to the packets.
    00068  * Once was in bpf.h
    00069  */
    00070 struct bpf_hdr {
    00071     struct timeval  bh_tstamp;  /* time stamp */
    00072     bpf_u_int32 bh_caplen;  /* length of captured portion */
    00073     bpf_u_int32 bh_datalen; /* original length of packet */
    00074     u_short     bh_hdrlen;  /* length of bpf header (this struct
    00075                        plus alignment padding) */
    00076 };
    00077
    00078 /* Start winsock */
    00079 int
    00080 wsockinit()
    00081 {
    00082     WORD wVersionRequested;
    00083     WSADATA wsaData;
    00084     int err;
    00085     wVersionRequested = MAKEWORD( 1, 1);
    00086     err = WSAStartup( wVersionRequested, &wsaData );
    00087     if ( err != 0 )
    00088     {
    00089         return -1;
    00090     }
    00091     return 0;
    00092 }
    00093
    00094
    00095 static int
    00096 pcap_stats_win32(pcap_t *p, struct pcap_stat *ps)
    00097 {
    00098
    00099     if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){
    00100         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror());
    00101         return -1;
    00102     }
    00103
    00104 //  ps->ps_recv = p->md.stat.ps_recv + p->md.stat.ps_drop;
    00105     return 0;
    00106 }
    00107
    00108 static int
    00109 pcap_read_win32_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
    00110 {
    00111     int cc;
    00112     int n = 0;
    00113     register u_char *bp, *ep;
    00114
    00115 #ifdef HAVE_REMOTE
    00116     static int samp_npkt;               // parameter needed for sampling, with '1 out of N' method has been requested
    00117     static struct timeval samp_time;    // parameter needed for sampling, with '1 every N ms' method has been requested
    00118 #endif  /* HAVE_REMOTE */
    00119
    00120     cc = p->cc;
    00121     if (p->cc == 0) {
    00122         /*
    00123          * Has "pcap_breakloop()" been called?
    00124          */
    00125         if (p->break_loop) {
    00126             /*
    00127              * Yes - clear the flag that indicates that it
    00128              * has, and return -2 to indicate that we were
    00129              * told to break out of the loop.
    00130              */
    00131             p->break_loop = 0;
    00132             return (-2);
    00133         }
    00134
    00135         /* capture the packets */
    00136         if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){
    00137             snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
    00138             return (-1);
    00139         }
    00140
    00141         cc = p->Packet->ulBytesReceived;
    00142
    00143         bp = p->Packet->Buffer;
    00144     }
    00145     else
    00146         bp = p->bp;
    00147
    00148     /*
    00149      * Loop through each packet.
    00150      */
    00151 #define bhp ((struct bpf_hdr *)bp)
    00152     ep = bp + cc;
    00153     while (1) {
    00154         register int caplen, hdrlen;
    00155
    00156         /*
    00157          * Has "pcap_breakloop()" been called?
    00158          * If so, return immediately - if we haven't read any
    00159          * packets, clear the flag and return -2 to indicate
    00160          * that we were told to break out of the loop, otherwise
    00161          * leave the flag set, so that the *next* call will break
    00162          * out of the loop without having read any packets, and
    00163          * return the number of packets we've processed so far.
    00164          */
    00165         if (p->break_loop) {
    00166             if (n == 0) {
    00167                 p->break_loop = 0;
    00168                 return (-2);
    00169             } else {
    00170                 p->bp = bp;
    00171                 p->cc = ep - bp;
    00172                 return (n);
    00173             }
    00174         }
    00175         if (bp >= ep)
    00176             break;
    00177
    00178         caplen = bhp->bh_caplen;
    00179         hdrlen = bhp->bh_hdrlen;
    00180
    00181 #ifdef HAVE_REMOTE
    00182         if (p->rmt_samp.method == PCAP_SAMP_1_EVERY_N)
    00183         {
    00184             samp_npkt= (samp_npkt + 1) % p->rmt_samp.value;
    00185
    00186             // Discard all packets that are not '1 out of N'
    00187             if (samp_npkt != 0)
    00188             {
    00189                 bp += BPF_WORDALIGN(caplen + hdrlen);
    00190                 continue;
    00191             }
    00192         }
    00193
    00194         if (p->rmt_samp.method == PCAP_SAMP_FIRST_AFTER_N_MS)
    00195         {
    00196         struct pcap_pkthdr *pkt_header= (struct pcap_pkthdr*) bp;
    00197
    00198             // Check if the timestamp of the arrived packet is smaller than our target time
    00199             if ( (pkt_header->ts.tv_sec < samp_time.tv_sec) ||
    00200                     ( (pkt_header->ts.tv_sec == samp_time.tv_sec) && (pkt_header->ts.tv_usec < samp_time.tv_usec) ) )
    00201             {
    00202                 bp += BPF_WORDALIGN(caplen + hdrlen);
    00203                 continue;
    00204             }
    00205
    00206             // The arrived packet is suitable for being sent to the remote host
    00207             // So, let's update the target time
    00208             samp_time.tv_usec= pkt_header->ts.tv_usec + p->rmt_samp.value * 1000;
    00209             if (samp_time.tv_usec > 1000000)
    00210             {
    00211                 samp_time.tv_sec= pkt_header->ts.tv_sec + samp_time.tv_usec / 1000000;
    00212                 samp_time.tv_usec= samp_time.tv_usec % 1000000;
    00213             }
    00214         }
    00215 #endif  /* HAVE_REMOTE */
    00216
    00217         /*
    00218          * XXX A bpf_hdr matches a pcap_pkthdr.
    00219          */
    00220         (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen);
    00221         bp += BPF_WORDALIGN(caplen + hdrlen);
    00222         if (++n >= cnt && cnt > 0) {
    00223             p->bp = bp;
    00224             p->cc = ep - bp;
    00225             return (n);
    00226         }
    00227     }
    00228 #undef bhp
    00229     p->cc = 0;
    00230     return (n);
    00231 }
    00232
    00233 #ifdef HAVE_DAG_API
    00234 static int
    00235 pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
    00236 {
    00237     u_char *dp = NULL;
    00238     int packet_len = 0, caplen = 0;
    00239     struct pcap_pkthdr  pcap_header;
    00240     u_char *endofbuf;
    00241     int n = 0;
    00242     dag_record_t *header;
    00243     unsigned erf_record_len;
    00244     ULONGLONG ts;
    00245     int cc;
    00246     unsigned swt;
    00247     unsigned dfp = p->adapter->DagFastProcess;
    00248
    00249     cc = p->cc;
    00250     if (cc == 0) /* Get new packets only if we have processed all the ones of the previous read */
    00251     {
    00252         /* Get new packets from the network */
    00253         if(PacketReceivePacket(p->adapter, p->Packet, TRUE)==FALSE){
    00254             snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
    00255             return (-1);
    00256         }
    00257
    00258         cc = p->Packet->ulBytesReceived;
    00259         if(cc == 0)
    00260             /* The timeout has expired but we no packets arrived */
    00261             return 0;
    00262         header = (dag_record_t*)p->adapter->DagBuffer;
    00263     }
    00264     else
    00265         header = (dag_record_t*)p->bp;
    00266
    00267     endofbuf = (char*)header + cc;
    00268
    00269     /*
    00270      * Cycle through the packets
    00271      */
    00272     do
    00273     {
    00274         erf_record_len = SWAPS(header->rlen);
    00275         if((char*)header + erf_record_len > endofbuf)
    00276             break;
    00277
    00278         /* Increase the number of captured packets */
    00279         p->md.stat.ps_recv++;
    00280
    00281         /* Find the beginning of the packet */
    00282         dp = ((u_char *)header) + dag_record_size;
    00283
    00284         /* Determine actual packet len */
    00285         switch(header->type)
    00286         {
    00287         case TYPE_ATM:
    00288             packet_len = ATM_SNAPLEN;
    00289             caplen = ATM_SNAPLEN;
    00290             dp += 4;
    00291
    00292             break;
    00293
    00294         case TYPE_ETH:
    00295             swt = SWAPS(header->wlen);
    00296             packet_len = swt - (p->md.dag_fcs_bits);
    00297             caplen = erf_record_len - dag_record_size - 2;
    00298             if (caplen > packet_len)
    00299             {
    00300                 caplen = packet_len;
    00301             }
    00302             dp += 2;
    00303
    00304             break;
    00305
    00306         case TYPE_HDLC_POS:
    00307             swt = SWAPS(header->wlen);
    00308             packet_len = swt - (p->md.dag_fcs_bits);
    00309             caplen = erf_record_len - dag_record_size;
    00310             if (caplen > packet_len)
    00311             {
    00312                 caplen = packet_len;
    00313             }
    00314
    00315             break;
    00316         }
    00317
    00318         if(caplen > p->snapshot)
    00319             caplen = p->snapshot;
    00320
    00321         /*
    00322          * Has "pcap_breakloop()" been called?
    00323          * If so, return immediately - if we haven't read any
    00324          * packets, clear the flag and return -2 to indicate
    00325          * that we were told to break out of the loop, otherwise
    00326          * leave the flag set, so that the *next* call will break
    00327          * out of the loop without having read any packets, and
    00328          * return the number of packets we've processed so far.
    00329          */
    00330         if (p->break_loop)
    00331         {
    00332             if (n == 0)
    00333             {
    00334                 p->break_loop = 0;
    00335                 return (-2);
    00336             }
    00337             else
    00338             {
    00339                 p->bp = (char*)header;
    00340                 p->cc = endofbuf - (char*)header;
    00341                 return (n);
    00342             }
    00343         }
    00344
    00345         if(!dfp)
    00346         {
    00347             /* convert between timestamp formats */
    00348             ts = header->ts;
    00349             pcap_header.ts.tv_sec = (int)(ts >> 32);
    00350             ts = (ts & 0xffffffffi64) * 1000000;
    00351             ts += 0x80000000; /* rounding */
    00352             pcap_header.ts.tv_usec = (int)(ts >> 32);
    00353             if (pcap_header.ts.tv_usec >= 1000000) {
    00354                 pcap_header.ts.tv_usec -= 1000000;
    00355                 pcap_header.ts.tv_sec++;
    00356             }
    00357         }
    00358
    00359         /* No underlaying filtering system. We need to filter on our own */
    00360         if (p->fcode.bf_insns)
    00361         {
    00362             if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0)
    00363             {
    00364                 /* Move to next packet */
    00365                 header = (dag_record_t*)((char*)header + erf_record_len);
    00366                 continue;
    00367             }
    00368         }
    00369
    00370         /* Fill the header for the user suppplied callback function */
    00371         pcap_header.caplen = caplen;
    00372         pcap_header.len = packet_len;
    00373
    00374         /* Call the callback function */
    00375         (*callback)(user, &pcap_header, dp);
    00376
    00377         /* Move to next packet */
    00378         header = (dag_record_t*)((char*)header + erf_record_len);
    00379
    00380         /* Stop if the number of packets requested by user has been reached*/
    00381         if (++n >= cnt && cnt > 0)
    00382         {
    00383             p->bp = (char*)header;
    00384             p->cc = endofbuf - (char*)header;
    00385             return (n);
    00386         }
    00387     }
    00388     while((u_char*)header < endofbuf);
    00389
    00390   return 1;
    00391 }
    00392 #endif /* HAVE_DAG_API */
    00393
    00394 static void
    00395 pcap_close_win32(pcap_t *p)
    00396 {
    00397     if (p->buffer != NULL)
    00398         free(p->buffer);
    00399     if (p->adapter != NULL) {
    00400         PacketCloseAdapter(p->adapter);
    00401         p->adapter = NULL;
    00402     }
    00403 }
    00404
    00405 pcap_t *
    00406 pcap_open_live(const char *device, int snaplen, int promisc, int to_ms,
    00407     char *ebuf)
    00408 {
    00409     register pcap_t *p;
    00410     NetType type;
    00411
    00412 #ifdef HAVE_REMOTE
    00413     char host[PCAP_BUF_SIZE + 1];
    00414     char port[PCAP_BUF_SIZE + 1];
    00415     char name[PCAP_BUF_SIZE + 1];
    00416     int srctype;
    00417
    00418     /*
    00419         Retrofit; we have to make older applications compatible with the remote capture
    00420         So, we're calling the pcap_open_remote() from here, that is a very dirty thing.
    00421         Obviously, we cannot exploit all the new features; for instance, we cannot
    00422         send authentication, we cannot use a UDP data connection, and so on.
    00423     */
    00424     if (pcap_parsesrcstr(device, &srctype, host, port, name, ebuf) )
    00425         return NULL;
    00426
    00427     if (srctype == PCAP_SRC_IFREMOTE)
    00428     {
    00429         p= pcap_opensource_remote(device, NULL, ebuf);
    00430
    00431         if (p == NULL)
    00432             return NULL;
    00433
    00434         p->snapshot= snaplen;
    00435         p->timeout= to_ms;
    00436         p->rmt_flags= (promisc) ? PCAP_OPENFLAG_PROMISCUOUS : 0;
    00437
    00438         return p;
    00439     }
    00440 #endif
    00441
    00442     /* Init WinSock */
    00443     wsockinit();
    00444
    00445     p = (pcap_t *)malloc(sizeof(*p));
    00446     if (p == NULL)
    00447     {
    00448         snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
    00449         return (NULL);
    00450     }
    00451     memset(p, 0, sizeof(*p));
    00452     p->adapter=NULL;
    00453
    00454     p->adapter = PacketOpenAdapter((char*)device);
    00455
    00456     if (p->adapter == NULL)
    00457     {
    00458         /* Adapter detected but we are not able to open it. Return failure. */
    00459         snprintf(ebuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror());
    00460         return NULL;
    00461     }
    00462
    00463     /*get network type*/
    00464     if(PacketGetNetType (p->adapter,&type) == FALSE)
    00465     {
    00466         snprintf(ebuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror());
    00467         goto bad;
    00468     }
    00469
    00470     /*Set the linktype*/
    00471     switch (type.LinkType)
    00472     {
    00473     case NdisMediumWan:
    00474         p->linktype = DLT_EN10MB;
    00475         break;
    00476
    00477     case NdisMedium802_3:
    00478         p->linktype = DLT_EN10MB;
    00479         /*
    00480          * This is (presumably) a real Ethernet capture; give it a
    00481          * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
    00482          * that an application can let you choose it, in case you're
    00483          * capturing DOCSIS traffic that a Cisco Cable Modem
    00484          * Termination System is putting out onto an Ethernet (it
    00485          * doesn't put an Ethernet header onto the wire, it puts raw
    00486          * DOCSIS frames out on the wire inside the low-level
    00487          * Ethernet framing).
    00488          */
    00489         p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
    00490         /*
    00491          * If that fails, just leave the list empty.
    00492          */
    00493         if (p->dlt_list != NULL) {
    00494             p->dlt_list[0] = DLT_EN10MB;
    00495             p->dlt_list[1] = DLT_DOCSIS;
    00496             p->dlt_count = 2;
    00497         }
    00498         break;
    00499
    00500     case NdisMediumFddi:
    00501         p->linktype = DLT_FDDI;
    00502         break;
    00503
    00504     case NdisMedium802_5:
    00505         p->linktype = DLT_IEEE802;
    00506         break;
    00507
    00508     case NdisMediumArcnetRaw:
    00509         p->linktype = DLT_ARCNET;
    00510         break;
    00511
    00512     case NdisMediumArcnet878_2:
    00513         p->linktype = DLT_ARCNET;
    00514         break;
    00515
    00516     case NdisMediumAtm:
    00517         p->linktype = DLT_ATM_RFC1483;
    00518         break;
    00519
    00520     case NdisMediumCHDLC:
    00521         p->linktype = DLT_CHDLC;
    00522         break;
    00523
    00524     case NdisMediumPPPSerial:
    00525         p->linktype = DLT_PPP_SERIAL;
    00526         break;
    00527
    00528     case NdisMediumNull:
    00529         p->linktype = DLT_NULL;
    00530         break;
    00531
    00532     default:
    00533         p->linktype = DLT_EN10MB;           /*an unknown adapter is assumed to be ethernet*/
    00534         break;
    00535     }
    00536
    00537     /* Set promisquous mode */
    00538     if (promisc) PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS);
    00539      else PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL);
    00540
    00541     /* Set the buffer size */
    00542     p->bufsize = PcapBufSize;
    00543
    00544     /* allocate Packet structure used during the capture */
    00545     if((p->Packet = PacketAllocatePacket())==NULL)
    00546     {
    00547         snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure");
    00548         goto bad;
    00549     }
    00550
    00551     if(!(p->adapter->Flags & INFO_FLAG_DAG_CARD))
    00552     {
    00553     /*
    00554      * Traditional Adapter
    00555      */
    00556
    00557         p->buffer = (u_char *)malloc(PcapBufSize);
    00558         if (p->buffer == NULL)
    00559         {
    00560             snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
    00561             goto bad;
    00562         }
    00563
    00564         PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
    00565
    00566         p->snapshot = snaplen;
    00567
    00568         /* allocate the standard buffer in the driver */
    00569         if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE)
    00570         {
    00571             snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n");
    00572             goto bad;
    00573         }
    00574
    00575         /* tell the driver to copy the buffer only if it contains at least 16K */
    00576         if(PacketSetMinToCopy(p->adapter,16000)==FALSE)
    00577         {
    00578             snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror());
    00579             goto bad;
    00580         }
    00581     }
    00582     else
    00583 #ifdef HAVE_DAG_API
    00584     {
    00585     /*
    00586      * Dag Card
    00587      */
    00588         LONG    status;
    00589         HKEY    dagkey;
    00590         DWORD   lptype;
    00591         DWORD   lpcbdata;
    00592         int     postype = 0;
    00593         char    keyname[512];
    00594
    00595         snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
    00596             "SYSTEM\\CurrentControlSet\\Services\\DAG",
    00597             strstr(_strlwr((char*)device), "dag"));
    00598         do
    00599         {
    00600             status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey);
    00601             if(status != ERROR_SUCCESS)
    00602                 break;
    00603
    00604             status = RegQueryValueEx(dagkey,
    00605                 "PosType",
    00606                 NULL,
    00607                 &lptype,
    00608                 (char*)&postype,
    00609                 &lpcbdata);
    00610
    00611             if(status != ERROR_SUCCESS)
    00612             {
    00613                 postype = 0;
    00614             }
    00615
    00616             RegCloseKey(dagkey);
    00617         }
    00618         while(FALSE);
    00619
    00620
    00621         p->snapshot = PacketSetSnapLen(p->adapter, snaplen);
    00622
    00623         /* Set the length of the FCS associated to any packet. This value
    00624          * will be subtracted to the packet length */
    00625         p->md.dag_fcs_bits = p->adapter->DagFcsLen;
    00626     }
    00627 #else
    00628     goto bad;
    00629 #endif /* HAVE_DAG_API */
    00630
    00631     PacketSetReadTimeout(p->adapter, to_ms);
    00632
    00633 #ifdef HAVE_DAG_API
    00634     if(p->adapter->Flags & INFO_FLAG_DAG_CARD)
    00635     {
    00636         /* install dag specific handlers for read and setfilter */
    00637         p->read_op = pcap_read_win32_dag;
    00638         p->setfilter_op = pcap_setfilter_win32_dag;
    00639     }
    00640     else
    00641     {
    00642 #endif /* HAVE_DAG_API */
    00643         /* install traditional npf handlers for read and setfilter */
    00644         p->read_op = pcap_read_win32_npf;
    00645         p->setfilter_op = pcap_setfilter_win32_npf;
    00646 #ifdef HAVE_DAG_API
    00647     }
    00648 #endif /* HAVE_DAG_API */
    00649     p->set_datalink_op = NULL;  /* can't change data link type */
    00650     p->getnonblock_op = pcap_getnonblock_win32;
    00651     p->setnonblock_op = pcap_setnonblock_win32;
    00652     p->stats_op = pcap_stats_win32;
    00653     p->close_op = pcap_close_win32;
    00654
    00655     return (p);
    00656 bad:
    00657     if (p->adapter)
    00658         PacketCloseAdapter(p->adapter);
    00659     if (p->buffer != NULL)
    00660         free(p->buffer);
    00661     if(p->Packet)
    00662         PacketFreePacket(p->Packet);
    00663     /*
    00664      * Get rid of any link-layer type list we allocated.
    00665      */
    00666     if (p->dlt_list != NULL)
    00667         free(p->dlt_list);
    00668     free(p);
    00669     return (NULL);
    00670 }
    00671
    00672
    00673 static int
    00674 pcap_setfilter_win32_npf(pcap_t *p, struct bpf_program *fp)
    00675 {
    00676     if(PacketSetBpf(p->adapter,fp)==FALSE){
    00677         /* kernel filter not installed. */
    00678         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror());
    00679         return (-1);
    00680     }
    00681     return (0);
    00682 }
    00683
    00684 /*
    00685  * We filter at user level, since the kernel driver does't process the packets
    00686  */
    00687 static int
    00688 pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) {
    00689
    00690     if(!fp)
    00691     {
    00692         strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
    00693         return -1;
    00694     }
    00695
    00696     /* Install a user level filter */
    00697     if (install_bpf_program(p, fp) < 0)
    00698     {
    00699         snprintf(p->errbuf, sizeof(p->errbuf),
    00700             "setfilter, unable to install the filter: %s", pcap_strerror(errno));
    00701         return -1;
    00702     }
    00703
    00704     p->md.use_bpf = 0;
    00705
    00706     return (0);
    00707 }
    00708
    00709 static int
    00710 pcap_getnonblock_win32(pcap_t *p, char *errbuf)
    00711 {
    00712     /*
    00713      * XXX - if there were a PacketGetReadTimeout() call, we
    00714      * would use it, and return 1 if the timeout is -1
    00715      * and 0 otherwise.
    00716      */
    00717     return (p->nonblock);
    00718 }
    00719
    00720 static int
    00721 pcap_setnonblock_win32(pcap_t *p, int nonblock, char *errbuf)
    00722 {
    00723     int newtimeout;
    00724
    00725     if (nonblock) {
    00726         /*
    00727          * Set the read timeout to -1 for non-blocking mode.
    00728          */
    00729         newtimeout = -1;
    00730     } else {
    00731         /*
    00732          * Restore the timeout set when the device was opened.
    00733          * (Note that this may be -1, in which case we're not
    00734          * really leaving non-blocking mode.)
    00735          */
    00736         newtimeout = p->timeout;
    00737     }
    00738     if (!PacketSetReadTimeout(p->adapter, newtimeout)) {
    00739         snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
    00740             "PacketSetReadTimeout: %s", pcap_win32strerror());
    00741         return (-1);
    00742     }
    00743     p->nonblock = (newtimeout == -1);
    00744     return (0);
    00745 }
    00746
    00747 /* Set the driver working mode */
    00748 int
    00749 pcap_setmode(pcap_t *p, int mode){
    00750
    00751     if (p->adapter==NULL)
    00752     {
    00753         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file");
    00754         return -1;
    00755     }
    00756
    00757     if(PacketSetMode(p->adapter,mode)==FALSE)
    00758     {
    00759         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
    00760         return -1;
    00761     }
    00762
    00763     return 0;
    00764 }
    00765
    00766 /* Send a packet to the network */
    00767 int
    00768 pcap_sendpacket(pcap_t *p, u_char *buf, int size){
    00769     LPPACKET PacketToSend;
    00770
    00771     if (p->adapter==NULL)
    00772     {
    00773         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Writing a packet is allowed only on a physical adapter");
    00774         return -1;
    00775     }
    00776
    00777     PacketToSend=PacketAllocatePacket();
    00778     PacketInitPacket(PacketToSend,buf,size);
    00779     if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){
    00780         PacketFreePacket(PacketToSend);
    00781         return -1;
    00782     }
    00783
    00784     PacketFreePacket(PacketToSend);
    00785     return 0;
    00786 }
    00787
    00788 /* Set the dimension of the kernel-level capture buffer */
    00789 int
    00790 pcap_setbuff(pcap_t *p, int dim)
    00791 {
    00792 #ifdef HAVE_REMOTE
    00793     if (p->rmt_clientside)
    00794     {
    00795         /* Currently, this is a bug: the capture buffer cannot be set with remote capture */
    00796         return 0;
    00797     }
    00798 #endif  /* HAVE_REMOTE */
    00799
    00800     if (p->adapter==NULL)
    00801     {
    00802         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file");
    00803         return -1;
    00804     }
    00805
    00806     if(PacketSetBuff(p->adapter,dim)==FALSE)
    00807     {
    00808         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
    00809         return -1;
    00810     }
    00811     return 0;
    00812 }
    00813
    00814 /*set the minimum amount of data that will release a read call*/
    00815 int
    00816 pcap_setmintocopy(pcap_t *p, int size)
    00817 {
    00818     if (p->adapter==NULL)
    00819     {
    00820         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture");
    00821         return -1;
    00822     }
    00823
    00824     if(PacketSetMinToCopy(p->adapter, size)==FALSE)
    00825     {
    00826         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
    00827         return -1;
    00828     }
    00829     return 0;
    00830 }

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