Main Page   Modules   Data Structures   File List   Data Fields   Globals  

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