メイン   モジュール   デー タ構造   ファイルリスト   データフィールド   グローバル   関連ページ   注意事項   English

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 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 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 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 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 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     if (p->adapter==NULL)
00362     {
00363         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file");
00364         return -1;
00365     }
00366     
00367     if(PacketSetBuff(p->adapter,dim)==FALSE)
00368     {
00369         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
00370         return -1;
00371     }
00372     return 0;
00373 }
00374 
00375 /*set the minimum amount of data that will release a read call*/
00376 int 
00377 pcap_setmintocopy(pcap_t *p, int size)
00378 {
00379     if (p->adapter==NULL)
00380     {
00381         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture");
00382         return -1;
00383     }   
00384 
00385     if(PacketSetMinToCopy(p->adapter, size)==FALSE)
00386     {
00387         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
00388         return -1;
00389     }
00390     return 0;
00391 }
00392 
00393 int
00394 pcap_set_datalink_platform(pcap_t *p, int dlt)
00395 {
00396     return (0);
00397 }

documentation. Copyright (c)2002-2003 Politecnico di Torino.
2005 translated by Telebusiness,Inc.
 All rights reserved.