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

Win32-Extensions.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 #include "pcap-int.h"
00034 #include <packet32.h>
00035 
00036 #ifdef HAVE_REMOTE
00037 #include <pcap-remote.h>
00038 #endif
00039 
00040 
00041 HANDLE
00042 pcap_getevent(pcap_t *p)
00043 {
00044     if (p->adapter==NULL)
00045     {
00046         sprintf(p->errbuf, "The read event cannot be retrieved while reading from a file");
00047         return NULL;
00048     }   
00049 
00050     return PacketGetReadEvent(p->adapter);
00051 }
00052 
00053 
00054 
00055 /*
00056 This way is definitely safer than passing the pcap_stat * from the userland. In fact, there could
00057 happen than the user allocates a variable which is not big enough for the new structure, and the
00058 library will write in a zone which is not allocated to this variable.
00059 In this way, we're pretty sure we are writing on memory allocated to this variable.
00060 */
00061 struct pcap_stat *
00062 pcap_stats_ex(pcap_t *p, int *pcap_stat_size)
00063 {
00064     *pcap_stat_size= sizeof (struct pcap_stat);
00065 
00066 #ifdef HAVE_REMOTE
00067     if (p->rmt_clientside)
00068     {
00069         /* We are on an remote capture */
00070         return pcap_stats_ex_remote(p);
00071     }
00072 #endif
00073     if(PacketGetStatsEx(p->adapter, (struct bpf_stat*) (&p->md.stat) ) != TRUE){
00074         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStatsEx error: %s", pcap_win32strerror());
00075         return NULL;
00076     }
00077     return (&p->md.stat);
00078 }
00079 
00080 
00081 pcap_send_queue* 
00082 pcap_sendqueue_alloc(u_int memsize)
00083 {
00084 
00085     pcap_send_queue *tqueue;
00086 
00087     /* Allocate the queue */
00088     tqueue = (pcap_send_queue*)malloc(sizeof(pcap_send_queue));
00089     if(tqueue == NULL){
00090         return NULL;
00091     }
00092 
00093     /* Allocate the buffer */
00094     tqueue->buffer = (char*)malloc(memsize);
00095     if(tqueue->buffer == NULL){
00096         free(tqueue);
00097         return NULL;
00098     }
00099 
00100     tqueue->maxlen = memsize;
00101     tqueue->len = 0;
00102 
00103     return tqueue;
00104 }
00105 
00106 void 
00107 pcap_sendqueue_destroy(pcap_send_queue* queue)
00108 {
00109     free(queue->buffer);
00110     free(queue);
00111 }
00112 
00113 int 
00114 pcap_sendqueue_queue(pcap_send_queue* queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
00115 {
00116 
00117     if(queue->len + sizeof(struct pcap_pkthdr) + pkt_header->caplen > queue->maxlen){
00118         return -1;
00119     }
00120 
00121     /* Copy the pcap_pkthdr header*/
00122     memcpy(queue->buffer + queue->len, pkt_header, sizeof(struct pcap_pkthdr));
00123     queue->len += sizeof(struct pcap_pkthdr);
00124 
00125     /* copy the packet */
00126     memcpy(queue->buffer + queue->len, pkt_data, pkt_header->caplen);
00127     queue->len += pkt_header->caplen;
00128 
00129     return 0;
00130 }
00131 
00132 u_int 
00133 pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue* queue, int sync){
00134 
00135     u_int res;
00136     DWORD error;
00137     int errlen;
00138 
00139     if (p->adapter==NULL)
00140     {
00141         sprintf(p->errbuf, "Cannot transmit a queue to an offline capture");
00142         return -1;
00143     }   
00144 
00145     res = PacketSendPackets(p->adapter,
00146         queue->buffer,
00147         queue->len,
00148         (BOOLEAN)sync);
00149 
00150     if(res != queue->len){
00151         error = GetLastError();
00152         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,NULL,error,0,p->errbuf,PCAP_ERRBUF_SIZE,NULL);
00153         /*
00154         * "FormatMessage()" "helpfully" sticks CR/LF at the end of
00155         * the message.  Get rid of it.
00156         */
00157         errlen = strlen(p->errbuf);
00158         if (errlen >= 2) {
00159             p->errbuf[errlen - 1] = '\0';
00160             p->errbuf[errlen - 2] = '\0';
00161         }
00162         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", p->errbuf);
00163     }
00164 
00165     return res;
00166 }
00167 
00168 
00169 #ifdef WE_HAVE_TO_DELETE_IT_ASAP
00170 int 
00171 pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header, u_char **pkt_data)
00172 {
00173     /* Check the capture type */
00174 
00175 #ifdef HAVE_REMOTE
00176     if (p->rmt_clientside)
00177     {
00178         /* We are on an remote capture */
00179         if (!p->rmt_capstarted)
00180         {
00181             // if the capture has not started yet, please start it
00182             if (pcap_startcapture_remote(p) )
00183                 return -1;
00184             p->rmt_capstarted= 1;
00185         }
00186         return pcap_next_ex_remote(p, pkt_header, pkt_data);
00187     }
00188 #endif
00189 
00190     if (p->adapter!=NULL)
00191     {
00192         /* We are on a live capture */
00193         int cc;
00194         int n = 0;
00195         register u_char *bp, *ep;
00196         
00197         cc = p->cc;
00198         if (p->cc == 0) 
00199         {
00200             /* capture the packets */
00201             if(PacketReceivePacket(p->adapter, p->Packet, TRUE) == FALSE)
00202             {
00203                 sprintf(p->errbuf, "read error: PacketReceivePacket failed");
00204                 return (-1);
00205             }
00206             
00207             cc = p->Packet->ulBytesReceived;
00208             
00209             bp = p->Packet->Buffer;
00210         } 
00211         else
00212             bp = p->bp;
00213         
00214         /*
00215          * Loop through each packet.
00216          */
00217         ep = bp + cc;
00218         if (bp < ep) 
00219         {
00220             register int caplen, hdrlen;
00221             caplen = ((struct bpf_hdr *)bp)->bh_caplen;
00222             hdrlen = ((struct bpf_hdr *)bp)->bh_hdrlen;
00223             
00224             /*
00225              * XXX A bpf_hdr matches a pcap_pkthdr.
00226              */
00227             *pkt_header = (struct pcap_pkthdr*)bp;
00228             *pkt_data = bp + hdrlen;
00229             bp += BPF_WORDALIGN(caplen + hdrlen);
00230             
00231             p->bp = bp;
00232             p->cc = ep - bp;
00233             return (1);
00234         }
00235         else{
00236             p->cc = 0;
00237             return (0);
00238         }
00239     }   
00240     else
00241     {
00242         /* We are on an offline capture */
00243         struct bpf_insn *fcode = p->fcode.bf_insns;
00244         int status;
00245         int n = 0;
00246         
00247         struct pcap_pkthdr *h=(struct pcap_pkthdr*)(p->buffer+p->bufsize-sizeof(struct pcap_pkthdr));
00248         
00249         while (1)
00250         {
00251             status = sf_next_packet(p, h, p->buffer, p->bufsize);
00252             if (status==1)
00253                 /* EOF */
00254                 return (-2);
00255             if (status==-1)
00256                 /* Error */
00257                 return (-1);
00258             
00259             if (fcode == NULL ||
00260                 bpf_filter(fcode, p->buffer, h->len, h->caplen)) 
00261             {
00262                 *pkt_header = h;
00263                 *pkt_data = p->buffer;
00264                 return (1);
00265             }           
00266             
00267         }
00268     }
00269 }
00270 #endif
00271 
00272 
00273 int
00274 pcap_setuserbuffer(pcap_t *p, int size)
00275 
00276 {
00277     unsigned char *new_buff;
00278 
00279     if (!p->adapter) {
00280         sprintf(p->errbuf,"Impossible to set user buffer while reading from a file");
00281         return -1;
00282     }
00283 
00284     if (size<=0) {
00285         /* Bogus parameter */
00286         sprintf(p->errbuf,"Error: invalid size %d",size);
00287         return -1;
00288     }
00289 
00290     /* Allocate the buffer */
00291     new_buff=(unsigned char*)malloc(sizeof(char)*size);
00292 
00293     if (!new_buff) {
00294         sprintf(p->errbuf,"Error: not enough memory");
00295         return -1;
00296     }
00297 
00298     free(p->buffer);
00299     
00300     p->buffer=new_buff;
00301     p->bufsize=size;
00302 
00303     /* Associate the buffer with the capture packet */
00304     PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize);
00305 
00306     return 0;
00307 
00308 }
00309 
00310 int
00311 pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks){
00312 
00313     BOOLEAN res;
00314 
00315     if (p->adapter==NULL)
00316     {
00317         sprintf(p->errbuf, "live dump needs a physical interface");
00318         return -1;
00319     }   
00320 
00321     /* Set the packet driver in dump mode */
00322     res = PacketSetMode(p->adapter, PACKET_MODE_DUMP);
00323     if(res == FALSE){
00324         sprintf(p->errbuf, "Error setting dump mode");
00325         return -1;
00326     }
00327 
00328     /* Set the name of the dump file */
00329     res = PacketSetDumpName(p->adapter, filename, strlen(filename));
00330     if(res == FALSE){
00331         sprintf(p->errbuf, "Error setting kernel dump file name");
00332         return -1;
00333     }
00334 
00335     /* Set the limits of the dump file */
00336     res = PacketSetDumpLimits(p->adapter, maxsize, maxpacks);
00337 
00338     return 0;
00339 }
00340 
00341 int 
00342 pcap_live_dump_ended(pcap_t *p, int sync){
00343 
00344     if (p->adapter == NULL)
00345     {
00346         sprintf(p->errbuf, "wrong interface type. A physical interface is needed");
00347         return -1;
00348     }   
00349 
00350     return PacketIsDumpEnded(p->adapter, (BOOLEAN)sync);
00351 
00352 }
00353 
00354 
00355 int pcap_offline_filter(struct bpf_program *prog, const struct pcap_pkthdr *header, const u_char *pkt_data)
00356 {
00357     struct bpf_insn *fcode = prog->bf_insns;
00358 
00359     if (fcode != NULL) 
00360         return (bpf_filter(fcode, (u_char *) pkt_data, header->len, header->caplen));
00361     else
00362         return 0;
00363 }

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