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, 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.