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.