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

pcap-remote.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2002 - 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 
00034 #include <string.h>     // for strlen(), ...
00035 #include <stdlib.h>     // for malloc(), free(), ...
00036 #include <stdarg.h>     // for functions with variable number of arguments
00037 #include <errno.h>      // for the errno variable
00038 #include <pcap.h>
00039 #include <pcap-int.h>
00040 #include <pcap-remote.h>
00041 #include <sockutils.h>
00042 
00043 
00065 #define PCAP_STATS_STANDARD 0   
00066 #define PCAP_STATS_EX 1         
00069 /*
00070     \brief Global variable; needed to keep the message due to an error that we want to discard.
00071     
00072     This can happen, for instance, because we already have an error message and we want to keep 
00073     the first one.
00074 */
00075 char fakeerrbuf[PCAP_ERRBUF_SIZE + 1];
00076 
00077 
00079 struct activehosts *activeHosts;
00080 
00081 
00082 /****************************************************
00083  *                                                  *
00084  * Locally defined functions                        *
00085  *                                                  *
00086  ****************************************************/
00087 void rpcap_thrdatamain_stream(void *ptr);
00088 void rpcap_thrdatamain_dgram(void *ptr);
00089 int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf);
00090 struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode);
00091 int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog);
00092 
00093 
00094 
00095 
00096 /****************************************************
00097  *                                                  *
00098  * Function bodies                                 *
00099  *                                                  *
00100  ****************************************************/
00101 
00133 int rpcap_deseraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf)
00134 {
00135     // Warning: we support only AF_INET and AF_INET6
00136     if ( ntohs(sockaddrin->ss_family) == AF_INET)
00137     {
00138     struct sockaddr_in *sockaddr;
00139     
00140         sockaddr= (struct sockaddr_in *) sockaddrin;
00141         sockaddr->sin_family= ntohs(sockaddr->sin_family);
00142         sockaddr->sin_port= ntohs(sockaddr->sin_port);
00143 
00144         (*sockaddrout)= (struct sockaddr_storage *) malloc ( sizeof(struct sockaddr_in) );
00145         if ( (*sockaddrout) == NULL)
00146         {
00147             snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00148             return -1;
00149         }
00150         memcpy( *sockaddrout, sockaddr, sizeof(struct sockaddr_in) );
00151         return 0;
00152     }
00153     if ( ntohs(sockaddrin->ss_family) == AF_INET6)
00154     {
00155     struct sockaddr_in6 *sockaddr;
00156     
00157         sockaddr= (struct sockaddr_in6 *) sockaddrin;
00158         sockaddr->sin6_family= ntohs(sockaddr->sin6_family);
00159         sockaddr->sin6_port= ntohs(sockaddr->sin6_port);
00160         sockaddr->sin6_flowinfo= ntohl(sockaddr->sin6_flowinfo);
00161         sockaddr->sin6_scope_id= ntohl(sockaddr->sin6_scope_id);
00162 
00163         (*sockaddrout)= (struct sockaddr_storage *) malloc ( sizeof(struct sockaddr_in6) );
00164         if ( (*sockaddrout) == NULL)
00165         {
00166             snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00167             return -1;
00168         }
00169         memcpy( *sockaddrout, sockaddr, sizeof(struct sockaddr_in6) );
00170         return 0;
00171     }
00172 
00173     // It is neither AF_INET nor AF_INET6
00174     *sockaddrout= NULL;
00175     return 0;
00176 }
00177 
00178 
00179 
00203 int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr **pkt_header, u_char **pkt_data)
00204 {
00205 int cc;
00206 register u_char *ep, *bp;
00207 
00208     cc= p->cc;
00209     bp= p->bp;
00210 
00211     ep = bp + cc;
00212 
00213     if (bp < ep) 
00214     {
00215         register int caplen, hdrlen;
00216 again:
00217         caplen = ((struct pcap_pkthdr *)bp)->caplen;
00218         hdrlen= sizeof(struct pcap_pkthdr);
00219             
00220         /*
00221          * XXX A bpf_hdr matches a pcap_pkthdr.
00222          */
00223         *pkt_header = (struct pcap_pkthdr *) bp;
00224         *pkt_data = bp + hdrlen;
00225         bp += BPF_WORDALIGN(caplen + hdrlen);
00226         
00227         p->bp = bp;
00228         p->cc = ep - bp;
00229         return (1);
00230     }
00231     else
00232     {
00233         p->cc = 0;
00234         // If there are no packets, the read thread must be suspended
00235 // another horrible difference...
00236 #ifdef linux
00237         pthread_suspend(p->md.timeout);
00238 #endif
00239 #ifdef WIN32
00240         pthread_suspend(p->timeout);
00241 #endif
00242         // check if now if have data; otherwise returns
00243         cc= p->cc;
00244         bp= p->bp;
00245 
00246         ep = bp + cc;
00247 
00248         if (bp < ep) 
00249             goto again;
00250 
00251         return (0);
00252     }
00253 }
00254 
00255 
00270 int pcap_read_remote(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
00271 {
00272 struct pcap_pkthdr *pkt_header;
00273 u_char *pkt_data;
00274 int n = 0;
00275 
00276     while ( (++n <= cnt) || (cnt < 0) )
00277     {
00278         if (pcap_read_nocb_remote(p, &pkt_header, &pkt_data) )
00279             (*callback)(user, pkt_header, pkt_data);
00280         else
00281             return n;
00282     }
00283     return n;
00284 }
00285 
00286 
00300 void pcap_close_remote(pcap_t *fp)
00301 {
00302 struct rpcap_header header;     // header of the RPCAP packet
00303 struct activehosts *temp;       // temp var needed to scan the host list chain, to detect if we're in active mode
00304 int active= 0;                  // active mode or not?
00305 
00306     // detect if we're in active mode
00307     temp= activeHosts;
00308     while (temp)
00309     {
00310         if (temp->sockctrl == fp->rmt_sockctrl)
00311         {
00312             active= 1;
00313             break;
00314         }
00315         temp= temp->next;
00316     }
00317 
00318     if (!active)
00319     {
00320         rpcap_createhdr( &header, RPCAP_MSG_CLOSE, 0, 0);
00321 
00322         // I don't check for errors, since I'm going to close everything
00323         sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), fakeerrbuf);
00324     }
00325     else
00326     {
00327         rpcap_createhdr( &header, RPCAP_MSG_ENDCAP_REQ, 0, 0);
00328 
00329         // I don't check for errors, since I'm going to close everything
00330         sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), fakeerrbuf);
00331 
00332         // wait for the answer
00333         // Don't check what we got, since the present libpcap does not uses this pcap_t anymore
00334         sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), fakeerrbuf);
00335 
00336         if ( ntohl(header.plen) != 0)
00337             sock_discard(fp->rmt_sockctrl, ntohl(header.plen), fakeerrbuf);
00338     }
00339 
00340 
00341     if (fp->rmt_threaddata)
00342     {
00343         pthread_cancel(fp->rmt_threaddata);
00344         fp->rmt_threaddata= 0;
00345     }
00346 
00347     if (fp->rmt_sockdata)
00348     {
00349         sock_close(fp->rmt_sockdata, fakeerrbuf);
00350         fp->rmt_sockdata= 0;
00351     }
00352 
00353     if ( (!active) && (fp->rmt_sockctrl) )
00354         sock_close(fp->rmt_sockctrl, fakeerrbuf);
00355 
00356     fp->rmt_sockctrl= 0;
00357 
00358     // To avoid inconsistencies in the number of sock_init()
00359     sock_cleanup();
00360 }
00361 
00362 
00363 
00373 int pcap_stats_remote(pcap_t *p, struct pcap_stat *ps)
00374 {
00375 struct pcap_stat *retval;
00376 
00377     retval= rpcap_stats_remote(p, ps, PCAP_STATS_STANDARD);
00378 
00379     if (retval)
00380         return 0;
00381     else
00382         return -1;
00383 }
00384 
00385 
00386 
00396 struct pcap_stat *pcap_stats_ex_remote(pcap_t *p)
00397 {
00398     // '0' (third param) means 'standard pcap_stats()'
00399     return (rpcap_stats_remote(p, &(p->md.stat), PCAP_STATS_EX));
00400 }
00401 
00402 
00403 
00434 struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode)
00435 {
00436 struct rpcap_header header;         // header of the RPCAP packet
00437 struct rpcap_stats netstats;        // statistics sent on the network
00438 unsigned int nread= 0;              // number of bytes of the payload read from the socket
00439 int retval;                         // temp variable which stores functions return value
00440 
00441     rpcap_createhdr(&header, RPCAP_MSG_STATS_REQ, 0, 0);
00442 
00443     // Send the PCAP_STATS command
00444     if (sock_send(p->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), p->errbuf) )
00445         goto error;
00446 
00447     // Receive the RPCAP stats reply message
00448     if (sock_recv(p->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), p->errbuf) == -1)
00449         goto error;
00450 
00451     // Checks if the message is correct
00452     retval= rpcap_checkmsg(p->errbuf, p->rmt_sockctrl, &header, RPCAP_MSG_STATS_REPLY, RPCAP_MSG_ERROR, 0);
00453 
00454     if (retval != RPCAP_MSG_STATS_REPLY)        // the message is not the one expected
00455     {
00456         switch (retval)
00457         {
00458             case -3:        // Unrecoverable network error
00459             case -2:        // The other endpoint send a message that is not allowed here
00460             case -1:    // The other endpoint has a version number that is not compatible with our
00461                 goto error;
00462 
00463             case RPCAP_MSG_ERROR:       // The other endpoint reported an error
00464                 // Update nread, since the rpcap_checkmsg() already purged the buffer
00465                 nread = ntohl(header.plen);
00466 
00467                 // Do nothing; just exit; the error code is already into the errbuf
00468                 goto error;
00469 
00470             default:
00471             {
00472                 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
00473                 goto error;
00474             };
00475         }
00476     }
00477 
00478     if ( (nread= sock_recv(p->rmt_sockctrl, (char *) &netstats, sizeof(struct rpcap_stats), p->errbuf)) == -1)
00479         goto error;
00480 
00481     if (mode == PCAP_STATS_STANDARD)
00482     {
00483         ps->ps_drop= ntohl(netstats.krnldrop);
00484         ps->ps_ifdrop= ntohl(netstats.ifdrop);
00485         ps->ps_recv= ntohl(netstats.ifrecv);
00486     }
00487     else
00488     {
00489         ps->ps_capt= p->md.TotCapt;
00490         ps->ps_drop= ntohl(netstats.krnldrop);
00491         ps->ps_ifdrop= ntohl(netstats.ifdrop);
00492         ps->ps_netdrop= p->md.TotNetDrops;
00493         ps->ps_recv= ntohl(netstats.ifrecv);
00494         ps->ps_sent= ntohl(netstats.svrcapt);
00495     }
00496 
00497     // Checks if all the data has been read; if not, discard the data in excess
00498     if (nread != ntohl(header.plen))
00499     {
00500         if (sock_discard(p->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf) == 1)
00501             goto error;
00502     }
00503 
00504     return ps;
00505 
00506 error:
00507     if (nread != ntohl(header.plen))
00508         sock_discard(p->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf);
00509 
00510     return NULL;
00511 }
00512 
00513 
00514 
00515 
00554 pcap_t *pcap_opensource_remote(const char *source, struct pcap_rmtauth *auth, char *errbuf)
00555 {
00556 char host[PCAP_BUF_SIZE], ctrlport[PCAP_BUF_SIZE], iface[PCAP_BUF_SIZE];
00557 
00558 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered
00559 int sendbufidx= 0;              // index which keeps the number of bytes currently buffered
00560 pthread_t threaddata= 0;        // handle to the receiving thread
00561 struct pcap *fp= NULL;          // pcap_t main variable
00562 unsigned int nread= 0;          // number of bytes of the payload read from the socket
00563 int retval;                     // store the return value of the functions
00564 int active= 0;                      // '1' if we're in active mode
00565 
00566 // socket-related variables
00567 struct addrinfo hints;          // temp, needed to open a socket connection
00568 struct addrinfo *addrinfo;      // temp, needed to open a socket connection
00569 SOCKET sockctrl= 0;             // socket descriptor of the control connection
00570 
00571 // RPCAP-related variables
00572 struct rpcap_header header;         // header of the RPCAP packet
00573 struct rpcap_openreply openreply;   // open reply message
00574 
00575 
00576     // determine the type of the source (NULL, file, local, remote)
00577     // You must have a valid source string even if we're in active mode, because otherwise
00578     // the call to the following funciton will fail.
00579     if (pcap_parsesrcstr(source, &retval, host, ctrlport, iface, errbuf) == -1)
00580         return NULL;
00581 
00582     if ( retval != PCAP_SRC_IFREMOTE)
00583     {
00584         snprintf(errbuf, PCAP_ERRBUF_SIZE, "This function is able to open only remote interfaces");
00585         return NULL;
00586     }
00587 
00588     addrinfo= NULL;
00589 
00590     // Warning: this call can be the first one called by the user.
00591     // For this reason, we have to initialize the WinSock support.
00592     if (sock_init(errbuf) == -1)
00593         return NULL;
00594 
00595     retval= rpcap_remoteact_getsock(host, errbuf);
00596 
00597     if (retval == -1)
00598         return NULL;
00599 
00600     // The capturing machine is in active mode
00601     if (retval)
00602     {
00603         sockctrl= retval;
00604         active= 1;
00605     }
00606     else
00607     {
00608         memset(&hints, 0, sizeof(struct addrinfo) );
00609         hints.ai_family = PF_UNSPEC;
00610         hints.ai_socktype = SOCK_STREAM;
00611 
00612         if ( (ctrlport == NULL) || (ctrlport[0] == 0) )
00613         {
00614             // the user chose not to specify the port
00615             if (sock_validaddr(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf) == -1)
00616                 return NULL;
00617         }
00618         else
00619         {
00620             // the user chose not to specify the port
00621             if (sock_validaddr(host, ctrlport, &hints, &addrinfo, errbuf) == -1)
00622                 return NULL;
00623         }
00624 
00625         if ( (sockctrl= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf)) == -1)
00626             goto error;
00627 
00628         freeaddrinfo(addrinfo);
00629         addrinfo= NULL;
00630 
00631         if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1)
00632             goto error;
00633     }
00634 
00635 
00636     // Now it's time to start playing with the RPCAP protocol
00637     // RPCAP open command: create the request message
00638     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf) )
00639         goto error;
00640 
00641     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_OPEN_REQ, 0, strlen(iface) );
00642 
00643     if ( sock_bufferize(iface, strlen(iface), sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf) )
00644         goto error;
00645 
00646     if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf) )
00647         goto error;
00648 
00649     // Receive the RPCAP open reply message
00650     if (sock_recv(sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf) == -1)
00651         goto error;
00652 
00653     // Checks if the message is correct
00654     retval= rpcap_checkmsg(errbuf, sockctrl, &header, RPCAP_MSG_OPEN_REPLY, RPCAP_MSG_ERROR, 0);
00655 
00656     if (retval != RPCAP_MSG_OPEN_REPLY)     // the message is not the one expected
00657     {
00658         switch (retval)
00659         {
00660             case -3:        // Unrecoverable network error
00661             case -2:        // The other endpoint send a message that is not allowed here
00662             case -1:    // The other endpoint has a version number that is not compatible with our
00663                 goto error;
00664 
00665             case RPCAP_MSG_ERROR:       // The other endpoint reported an error
00666                 // Update nread, since the rpcap_checkmsg() already purged the buffer
00667                 nread = ntohl(header.plen);
00668                 // Do nothing; just exit; the error code is already into the errbuf
00669                 goto error;
00670 
00671             default:
00672             {
00673                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Internal error");
00674                 goto error;
00675             };
00676         }
00677     }
00678 
00679 
00680     if ( (nread+= sock_recv(sockctrl, (char *) &openreply, sizeof(struct rpcap_openreply), errbuf)) == -1)
00681         goto error;
00682 
00683     // Allocates a pcap_t struct for this end of the connection
00684     fp = (pcap_t *) malloc( sizeof(pcap_t) );
00685     if (fp == NULL)
00686     {
00687         snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00688         goto error;
00689     }
00690 
00691     memset(fp, 0, sizeof(pcap_t));
00692 
00693     // Set proper fields into the pcap_t struct
00694     fp->linktype= ntohl(openreply.linktype);
00695     fp->tzoff= ntohl(openreply.tzoff);
00696     fp->rmt_sockctrl= sockctrl;
00697     fp->rmt_clientside= 1;
00698 
00699 
00700     // Checks if all the data has been read; if not, discard the data in excess
00701     if (nread != ntohl(header.plen))
00702     {
00703         if (sock_discard(sockctrl, ntohl(header.plen) - nread, fakeerrbuf) == 1)
00704             goto error;
00705     }
00706     return fp;
00707 
00708 error:
00709 // When the connection has been established, we have to close it. So, at the
00710 // beginning of this function, if an error occur we return immediately with
00711 // a return NULL; when the connection is established, we have to come here 
00712 // ('goto error;') in order to close everything properly.
00713 
00714     // Checks if all the data has been read; if not, discard the data in excess
00715     if (nread != ntohl(header.plen))
00716         sock_discard(sockctrl, ntohl(header.plen) - nread, fakeerrbuf);
00717 
00718     if (addrinfo)
00719         freeaddrinfo(addrinfo);
00720 
00721     if (!active)
00722         sock_close(sockctrl, fakeerrbuf);
00723 
00724     if (fp)
00725     {
00726         pcap_close(fp);
00727         fp= NULL;
00728     }
00729 
00730     return NULL;
00731 }
00732 
00733 
00734 
00735 
00736 
00737 
00738 
00761 int pcap_startcapture_remote(pcap_t *fp)
00762 {
00763 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered
00764 int sendbufidx= 0;              // index which keeps the number of bytes currently buffered
00765 char portdata[PCAP_BUF_SIZE];   // temp variable needed to keep the network port for the the data connection
00766 pthread_t threaddata= 0;        // handle to the receiving thread
00767 unsigned int nread= 0;          // number of bytes of the payload read from the socket
00768 int retval;                     // store the return value of the functions
00769 int active= 0;                  // '1' if we're in active mode
00770 struct activehosts *temp;       // temp var needed to scan the host list chain, to detect if we're in active mode
00771 char host[INET6_ADDRSTRLEN + 1];    // numeric name of the other host
00772 
00773 // socket-related variables
00774 struct addrinfo hints;          // temp, needed to open a socket connection
00775 struct addrinfo *addrinfo;      // temp, needed to open a socket connection
00776 SOCKET sockdata= 0;             // socket descriptor of the data connection
00777 struct sockaddr_storage saddr;  // temp, needed to retrieve the network data port chosen on the local machine
00778 socklen_t saddrlen;             // temp, needed to retrieve the network data port chosen on the local machine
00779 int ai_family;                  // temp, keeps the address family used by the control connection
00780 
00781 // RPCAP-related variables
00782 struct rpcap_header header;                 // header of the RPCAP packet
00783 struct rpcap_startcapreq *startcapreq;      // start capture request message
00784 struct rpcap_startcapreply startcapreply;   // start capture reply message
00785 
00786 
00787     // detect if we're in active mode
00788     temp= activeHosts;
00789     while (temp)
00790     {
00791         if (temp->sockctrl == fp->rmt_sockctrl)
00792         {
00793             active= 1;
00794             break;
00795         }
00796         temp= temp->next;
00797     }
00798 
00799     addrinfo= NULL;
00800 
00801     // Gets the complete sockaddr structure used in the ctrl connection
00802     // This is needed to get the address family of the control socket
00803     // Tip: I cannot save the ai_family of the ctrl sock in the pcap_t struct,
00804     // since the ctrl socket can already be open in case of active mode;
00805     // so I would have to call getpeername() anyway
00806     saddrlen = sizeof(struct sockaddr_storage);
00807     if (getpeername(fp->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
00808     {
00809         sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
00810         goto error;
00811     }
00812     ai_family= ((struct sockaddr_storage *) &saddr)->ss_family;
00813 
00814     // Get the numeric address of the remote host we are connected to
00815     if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, host, 
00816             sizeof(host), NULL, 0, NI_NUMERICHOST) )
00817     {
00818         sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
00819         goto error;
00820     }
00821 
00822     /*
00823         Data connection is opened by the server toward the client if:
00824         - we're using TCP, and the user wants us to be in active mode
00825         - we're using UDP
00826     */
00827     if ( (active) || (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) )
00828     {
00829         // We have to create a new socket to receive packets
00830         // We have to do that immediately, since we have to tell the other 
00831         // end which network port we picked up
00832         memset(&hints, 0, sizeof(struct addrinfo) );
00833         // TEMP addrinfo is NULL in case of active
00834         hints.ai_family = ai_family;    // Use the same address family of the control socket
00835         hints.ai_socktype = (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) ? SOCK_DGRAM : SOCK_STREAM;
00836         hints.ai_flags = AI_PASSIVE;    // Data connection is opened by the server toward the client
00837 
00838         // Let's the server pick up a free network port for us
00839         if (sock_validaddr(NULL, "0", &hints, &addrinfo, fp->errbuf) == -1)
00840             goto error;
00841 
00842         if ( (sockdata= sock_open(addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, fp->errbuf)) == -1)
00843             goto error;
00844 
00845         // addrinfo is no longer used
00846         freeaddrinfo(addrinfo);
00847         addrinfo= NULL;
00848 
00849         // get the complete sockaddr structure used in the data connection
00850         saddrlen = sizeof(struct sockaddr_storage);
00851         if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
00852         {
00853             sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
00854             goto error;
00855         }
00856 
00857         // Get the local port the system picked up
00858         if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, NULL, 
00859                 0, portdata, sizeof(portdata), NI_NUMERICSERV) )
00860         {
00861             sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
00862             goto error;
00863         }
00864     }
00865 
00866     // Now it's time to start playing with the RPCAP protocol
00867     // RPCAP start ca[ture command: create the request message
00868     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf) )
00869         goto error;
00870 
00871     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STARTCAP_REQ, 0,
00872         sizeof(struct rpcap_startcapreq) + sizeof(struct rpcap_filter) + fp->fcode.bf_len * sizeof(struct rpcap_filterbpf_insn) );
00873 
00874     // Fill the structure needed to open an adapter remotely
00875     startcapreq= (struct rpcap_startcapreq *) &sendbuf[sendbufidx];
00876 
00877     if ( sock_bufferize(NULL, sizeof(struct rpcap_startcapreq), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf) )
00878         goto error;
00879 
00880     memset(startcapreq, 0, sizeof(struct rpcap_startcapreq) );
00881 
00882     // By default, apply half the timeout on one side, half of the other
00883 #ifdef linux
00884     fp->md.timeout= fp->md.timeout/2;
00885     startcapreq->read_timeout= htonl(fp->md.timeout);
00886 #endif
00887 #ifdef WIN32
00888     fp->timeout= fp->timeout/2;
00889     startcapreq->read_timeout= htonl(fp->timeout);
00890 #endif
00891 
00892     // portdata on the openreq is meaningful only if we're in active mode
00893     if ( (active) || (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) )
00894     {
00895         sscanf(portdata, "%d", &(startcapreq->portdata));
00896         startcapreq->portdata= htons(startcapreq->portdata);
00897     }
00898 
00899     startcapreq->snaplen= htonl(fp->snapshot);
00900     startcapreq->flags= 0;
00901     if (fp->rmt_flags & PCAP_OPENFLAG_PROMISCUOUS)
00902         startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_PROMISC;
00903     if (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP)
00904         startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_DGRAM;
00905     if (active)
00906         startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_SERVEROPEN;
00907 
00908     startcapreq->flags= htons(startcapreq->flags);
00909 
00910     // Pack the capture filter
00911     if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, &fp->fcode) )
00912         goto error;
00913 
00914     if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf) )
00915         goto error;
00916 
00917 
00918     // Receive the RPCAP start capture reply message
00919     if (sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), fp->errbuf) == -1)
00920         goto error;
00921 
00922     // Checks if the message is correct
00923     retval= rpcap_checkmsg(fp->errbuf, fp->rmt_sockctrl, &header, RPCAP_MSG_STARTCAP_REPLY, RPCAP_MSG_ERROR, 0);
00924 
00925     if (retval != RPCAP_MSG_STARTCAP_REPLY)     // the message is not the one expected
00926     {
00927         switch (retval)
00928         {
00929             case -3:        // Unrecoverable network error
00930             case -2:        // The other endpoint send a message that is not allowed here
00931             case -1:    // The other endpoint has a version number that is not compatible with our
00932                 goto error;
00933 
00934             case RPCAP_MSG_ERROR:       // The other endpoint reported an error
00935                 // Update nread, since the rpcap_checkmsg() already purged the buffer
00936                 nread = ntohl(header.plen);
00937                 // Do nothing; just exit; the error code is already into the errbuf
00938                 goto error;
00939 
00940             default:
00941             {
00942                 snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
00943                 goto error;
00944             };
00945         }
00946     }
00947 
00948 
00949     if ( (nread+= sock_recv(fp->rmt_sockctrl, (char *) &startcapreply, sizeof(struct rpcap_startcapreply), fp->errbuf)) == -1)
00950         goto error;
00951 
00952     // Data connection is opened by the client toward the server
00953     // This happens because (a) we're not in active mode, and (b) we're not using UDP
00954     // So, let's start the connection
00955     if ( (!active) && !(fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) )
00956     {
00957         memset(&hints, 0, sizeof(struct addrinfo) );
00958         hints.ai_family = ai_family;        // Use the same address family of the control socket
00959         hints.ai_socktype = (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) ? SOCK_DGRAM : SOCK_STREAM;
00960 
00961         sprintf(portdata, "%d", ntohs(startcapreply.portdata) );
00962 
00963         // Let's the server pick up a free network port for us
00964         if (sock_validaddr(host, portdata, &hints, &addrinfo, fp->errbuf) == -1)
00965             goto error;
00966 
00967         if ( (sockdata= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf)) == -1)
00968             goto error;
00969 
00970         // addrinfo is no longer used
00971         freeaddrinfo(addrinfo);
00972         addrinfo= NULL;
00973     }
00974 
00975 
00976     // Allocates WinPcap/libpcap user buffer
00977     // It has the same size of the one used on the other side of the connection
00978     fp->bufsize= ntohl(startcapreply.bufsize);
00979 
00980     /*
00981         Warning: on some kernels (e.g. linux), the size of the user buffer does not take
00982         into account the pcap_header and such, and it is set equal to the snaplen.
00983         In our view, this is wrong (the meaning of the bufsize becames a bit strange).
00984         So, in our view, bufsize is the whole size of the user buffer.
00985         In case the bufsize returned is too small, adjust it accordingly.
00986     */
00987     if (fp->bufsize <= fp->snapshot)
00988         fp->bufsize+= sizeof (struct pcap_pkthdr);
00989 
00990     fp->buffer = (u_char *) malloc(fp->bufsize);
00991     if (fp->buffer == NULL)
00992     {
00993         snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
00994         goto error;
00995     }
00996 
00997     // The server is trying to connect to me; so it have to block on an accept() call
00998     // However, if the data connection is UDP, I don't have to call accept()
00999     if ( (active) && !(fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) )
01000     {
01001     SOCKET socktemp;    // We need another socket, since we're going to accept() a connection
01002 
01003         // Connection creation
01004         saddrlen = sizeof(struct sockaddr_storage);
01005 
01006         socktemp= accept(sockdata, (struct sockaddr *) &saddr, &saddrlen);
01007         
01008         if (socktemp == -1)
01009         {
01010             sock_geterror("accept(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
01011             goto error;
01012         }
01013 
01014         // Now that I accepted the connection, the server socket is no longer needed
01015         sock_close(sockdata, fp->errbuf);
01016         sockdata= socktemp;
01017     }
01018 
01019     fp->rmt_sockdata= sockdata;
01020 
01021     // Now we have to create a new thread to receive packets
01022     if (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP)
01023     {
01024         if ( pthread_create( &threaddata, NULL, (void *) &rpcap_thrdatamain_dgram, (void *) fp) )
01025         {
01026             snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread");
01027             goto error;
01028         }
01029     }
01030     else
01031     {
01032         if ( pthread_create( &threaddata, NULL, (void *) &rpcap_thrdatamain_stream, (void *) fp) )
01033         {
01034             snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread");
01035             goto error;
01036         }
01037     }
01038 
01039     fp->rmt_threaddata= threaddata;
01040 
01041     // Checks if all the data has been read; if not, discard the data in excess
01042     if (nread != ntohl(header.plen))
01043     {
01044         if (sock_discard(fp->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf) == 1)
01045             goto error;
01046     }
01047     return 0;
01048 
01049 error:
01050 // When the connection has been established, we have to close it. So, at the
01051 // beginning of this function, if an error occur we return immediately with
01052 // a return NULL; when the connection is established, we have to come here 
01053 // ('goto error;') in order to close everything properly.
01054 
01055     // Checks if all the data has been read; if not, discard the data in excess
01056     if (nread != ntohl(header.plen))
01057         sock_discard(fp->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf);
01058 
01059     if (threaddata)
01060         pthread_cancel(threaddata);
01061 
01062     if ((sockdata) && (sockdata != -1))     // we can be here because sockdata said 'error'
01063         sock_close(sockdata, fakeerrbuf);
01064 
01065     if (!active)
01066         sock_close(fp->rmt_sockctrl, fakeerrbuf);
01067 
01068     if (fp)
01069     {
01070         pcap_close(fp);
01071         fp= NULL;
01072     }
01073 
01074     return -1;
01075 }
01076 
01077 
01078 
01079 
01080 
01104 int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog)
01105 {
01106 struct rpcap_filter *filter;
01107 struct rpcap_filterbpf_insn *insn;
01108 struct bpf_insn *bf_insn;
01109 unsigned int i;
01110 
01111     filter= (struct rpcap_filter *) sendbuf;
01112 
01113     if ( sock_bufferize(NULL, sizeof(struct rpcap_filter), NULL, sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf) )
01114         return -1;
01115 
01116     filter->filtertype= htons(RPCAP_UPDATEFILTER_BPF);
01117     filter->nitems= htonl( (int32) prog->bf_len);
01118 
01119     if ( sock_bufferize(NULL, prog->bf_len * sizeof(struct rpcap_filterbpf_insn), NULL, sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf) )
01120         return -1;
01121     
01122     insn= (struct rpcap_filterbpf_insn *) (filter + 1);
01123     bf_insn= prog->bf_insns;
01124 
01125     for (i= 0; i < prog->bf_len; i++)
01126     {
01127         insn->code= htons(bf_insn->code);
01128         insn->jf= bf_insn->jf;
01129         insn->jt= bf_insn->jt;
01130         insn->k= htonl(bf_insn->k);
01131 
01132         insn++;
01133         bf_insn++;
01134     }
01135     return 0;
01136 }
01137 
01138 
01139 
01140 
01141 
01161 int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog)
01162 {
01163 int retval;                     // general variable used to keep the return value of other functions
01164 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered
01165 int sendbufidx= 0;              // index which keeps the number of bytes currently buffered
01166 struct rpcap_header header;     // To keep the reply message
01167 
01168 
01169     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf) )
01170         return -1;
01171 
01172     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_UPDATEFILTER_REQ, 0,
01173         sizeof(struct rpcap_filter) + prog->bf_len * sizeof(struct rpcap_filterbpf_insn));
01174 
01175     if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, prog) )
01176         return -1;
01177 
01178     if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf) )
01179         return -1;
01180 
01181     // Waits for the answer
01182     if (sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), fp->errbuf) == -1)
01183         return -1;
01184 
01185     // Checks if the message is correct
01186     retval= rpcap_checkmsg(fp->errbuf, fp->rmt_sockctrl, &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0);
01187 
01188     if (retval != RPCAP_MSG_UPDATEFILTER_REPLY)     // the message is not the one expected
01189     {
01190         switch (retval)
01191         {
01192             case -3:        // Unrecoverable network error
01193             case -2:        // The other endpoint sent a message that is not allowed here
01194             case -1:    // The other endpoint has a version number that is not compatible with our
01195                 // Do nothing; just exit from here; the error code is already into the errbuf
01196                 return -1;
01197 
01198             default:
01199             {
01200                 SOCK_ASSERT("Internal error", 0);
01201                 return -1;
01202             };
01203         }
01204     }
01205 
01206     if (ntohl(header.plen) != 0)    // the message has an unexpected size
01207     {
01208         if (sock_discard(fp->rmt_sockctrl, ntohl(header.plen), fp->errbuf) == -1)
01209             return -1;
01210     }
01211 
01212     return 0;
01213 }
01214 
01215 
01216 
01217 
01228 int pcap_setfilter_remote(pcap_t *fp, struct bpf_program *prog)
01229 {
01230     if (!fp->rmt_capstarted)
01231     {
01232         // copy filter into the pcap_t structure
01233         if (install_bpf_program(fp, prog) == -1)
01234             return -1;
01235         return 0;
01236     }
01237 
01238     // we have to update a filter during run-time
01239     if (pcap_updatefilter_remote(fp, prog) )
01240         return -1;
01241 
01242     return 0;
01243 }
01244 
01245 
01246 
01252 void pthread_suspend(int msec)
01253 {
01254 #ifdef WIN32
01255     Sleep(msec);
01256 #else
01257 struct timespec abstime;
01258 struct timeval now;
01259 
01260     pthread_cond_t cond;
01261     pthread_mutex_t mutex;
01262     pthread_mutexattr_t attr;
01263 
01264     pthread_mutexattr_init(&attr);
01265     pthread_mutex_init(&mutex, &attr);
01266     pthread_mutex_lock(&mutex);
01267 
01268     pthread_cond_init(&cond, NULL);
01269 
01270     gettimeofday(&now, NULL);
01271     
01272     abstime.tv_sec = now.tv_sec + msec/1000;
01273     abstime.tv_nsec = now.tv_usec * 1000 + (msec%1000) * 1000 * 1000;
01274 
01275     pthread_cond_timedwait(&cond, &mutex, &abstime);
01276 
01277     pthread_mutex_destroy(&mutex);
01278     pthread_cond_destroy(&cond);
01279 #endif
01280 }
01281 
01282 
01283 
01298 void rpcap_thrdatamain_stream(void *ptr)
01299 {
01300 char errbuf[PCAP_ERRBUF_SIZE + 1];  // error buffer
01301 pcap_t *fp;                         // pointer to a 'pcap' structure
01302 int retval;                         // general variable used to keep the return value of other functions
01303 struct rpcap_pkthdr net_pkt_header; // header of the packet
01304 struct pcap_pkthdr *pkt_header;     // pointer to the buffer that contains the header of the current packet
01305 struct rpcap_header header;         // general header according to the RPCAP format
01306 int cc;                             // number of bytes of data available into the user buffer
01307 unsigned int nread;                 // number of bytes (of payload) currently read from the network (referred to the current pkt)
01308 int pending= 0;                     // '1' if we've already read the pkt header, but there was not enough space to read the pkt data
01309 
01310 // Structures needed for the select() call
01311 fd_set rfds;                        // set of socket descriptors we have to check
01312 struct timeval tv;                  // maximum time the select() can block waiting for data
01313 
01314     fp= (pcap_t *) ptr;
01315 
01316     *errbuf= 0; // Initialize errbuf
01317 
01318     // Modify thread params so that it can be killed at any time
01319     if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) )
01320         goto error;
01321     if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) )
01322         goto error;
01323 
01324     // Watch out sockdata to see if it has input
01325     FD_ZERO(&rfds);
01326 
01327     // We do not have to block on the select()
01328     tv.tv_sec = 0;
01329     tv.tv_usec = 0;
01330 
01331     /*
01332         The algorithm chosen to manage ths user buffer is quite simple, although
01333         not completely optimized. For instance, this is the same algorithm that
01334         is implemented when a packet is read from the kernel.
01335 
01336         The producer (i.e. this thread) reads data from the network only when the
01337         user has already consumed all the data into the buffer.
01338         When data is read, it is copied at the beginning of the buffer.
01339         So, this is not a circular buffer.
01340         This job ends when (1) there is no data coming from the network, (2)
01341         the user buffer is completely full.
01342 
01343         The consumer (i.e. the thread that calls pcap_next_ex) can read only when
01344         the producer finished its job. In other words, even if there is already 
01345         data into the user buffer, the consumer cannot read it because the producer
01346         updates the status variables (fp->cc, fp->bp) only when it ends its job.
01347         This is the reason we do not need spinlocks.
01348 
01349         This algorithm has two main drawbacks:
01350         - even if there is data into the user buffer, the application could not be 
01351         able to see it
01352         - the producer reads the data from the network all at once, so the resulting
01353         behaviour is that all of a sudden the socket buffer is emptied and the TCP
01354         starts sending several acknowledges at the same time. This could lead to
01355         bursty traffic patterns.
01356     */
01357     while (1)
01358     {
01359         if (fp->cc == 0) 
01360         {
01361             u_char *bp= fp->buffer;
01362             cc= 0;
01363 
01364             /*
01365                 We will exit from this cycle while when:
01366                 - the socket does not have data in it
01367                 - the buffer does not have space left
01368 
01369                 In all cases, the pcap status variables will be updated
01370                 before calling 'break'.
01371             */
01372             while (1)
01373             {
01374 again:
01375                 // 'fp->rmt_sockdata' has always to be set before calling the select(),
01376                 // since it is cleared by the select()
01377                 FD_SET(fp->rmt_sockdata, &rfds);
01378 
01379                 retval = select(fp->rmt_sockdata + 1, &rfds, NULL, NULL, &tv);
01380                 if (retval == -1)
01381                 {
01382                     sock_geterror("select(): ", errbuf, PCAP_ERRBUF_SIZE);
01383                         goto error;
01384                 }
01385 
01386                 // There is no data waiting
01387                 if (retval == 0)
01388                 {
01389                     // Update the pcap_t pointers so that the user application can read from the buffer
01390                     fp->bp= fp->buffer;
01391                     fp->cc= cc;
01392 
01393                     pthread_suspend(100);   // Suspend 100 ms
01394                     break;
01395                 }
01396 
01397                 if (!pending)
01398                 {
01399                     // I'm going to read a new packet; so I reset the number of bytes (payload only) read
01400                     nread= 0;
01401 
01402                     if (sock_recv(fp->rmt_sockdata, (char *) &header, sizeof(struct rpcap_header), errbuf) == -1)
01403                         goto error;
01404 
01405                     // Checks if the message is correct
01406                     retval= rpcap_checkmsg(errbuf, fp->rmt_sockdata, &header, RPCAP_MSG_PACKET, 0);
01407 
01408                     if (retval != RPCAP_MSG_PACKET)     // the message is not the one expected
01409                     {
01410                         switch (retval)
01411                         {
01412                             case -3:        // Unrecoverable network error                                  
01413                                 goto error; // Do nothing; just exit from here; the error code is already into the errbuf
01414 
01415                             case -2:        // The other endpoint sent a message that is not allowed here
01416                             case -1:        // The other endpoint has a version number that is not compatible with our
01417                                 goto again;
01418 
01419                             default:
01420                             {
01421                                 SOCK_ASSERT("Internal error", 1);
01422                                 goto error;
01423                             };
01424                         }
01425                     }
01426 
01427                     // Read the RPCAP packet header from the network
01428                     if ( (nread= sock_recv(fp->rmt_sockdata, (char *) &net_pkt_header, sizeof(struct rpcap_pkthdr), errbuf)) == -1)
01429                         goto error;
01430                 }
01431 
01432                 if ( (cc + ntohl(net_pkt_header.caplen) + sizeof(struct pcap_pkthdr) ) <= ( (unsigned) fp->bufsize) )
01433                 {
01434                     pending= 0;
01435 
01436                     pkt_header= (struct pcap_pkthdr *) bp;
01437                     pkt_header->caplen= ntohl(net_pkt_header.caplen);
01438                     pkt_header->len= ntohl(net_pkt_header.len);
01439                     pkt_header->ts.tv_sec= ntohl(net_pkt_header.timestamp_sec);
01440                     pkt_header->ts.tv_usec= ntohl(net_pkt_header.timestamp_usec);
01441 
01442                     // I don't update the counter of the packets dropped by the network since we're using TCP;
01443                     // therefore no packets are dropped. Just update the number of packets received correctly
01444                     fp->md.TotCapt++;
01445 
01446                     // Copies the packet into the data buffer
01447                     if ( (nread+= sock_recv(fp->rmt_sockdata, (char *) bp + sizeof(struct pcap_pkthdr), pkt_header->caplen, errbuf)) == -1)
01448                         goto error;
01449 
01450                     bp += BPF_WORDALIGN(pkt_header->caplen + sizeof(struct pcap_pkthdr));
01451                     cc += BPF_WORDALIGN(pkt_header->caplen + sizeof(struct pcap_pkthdr));
01452 
01453                     // Checks if all the data has been read; if not, discard the data in excess
01454                     if (nread != ntohl(header.plen))
01455                         sock_discard(fp->rmt_sockdata, ntohl(header.plen) - nread, fakeerrbuf);
01456 
01457                 }
01458                 else
01459                 {
01460                     pending= 1;
01461 
01462                     // Update the pcap_t pointers so that the user application can read from the buffer
01463                     fp->bp= fp->buffer;
01464                     fp->cc= cc;
01465 
01466                     break;
01467                 }
01468             } // end while (1)
01469         }
01470         else
01471         {
01472             pthread_suspend(100);   // Suspend 100 ms
01473         }
01474 
01475     }   // end main while(1)
01476 
01477 error:
01478     SOCK_ASSERT("Exiting from the child data thread", 1);
01479     SOCK_ASSERT(errbuf, 1);
01480 
01481     // Removes the descriptor s from set
01482     FD_CLR(fp->rmt_sockdata, &rfds);
01483 
01484     closesocket(fp->rmt_sockdata);
01485     fp->rmt_sockdata= 0;
01486     fp->rmt_threaddata= 0;
01487 }
01488 
01489 
01490 
01514 void rpcap_thrdatamain_dgram(void *ptr)
01515 {
01516 char errbuf[PCAP_ERRBUF_SIZE + 1];  // error buffer
01517 char netbuf[RPCAP_NETBUF_SIZE];     // size of the network buffer in which the packet is copied
01518 pcap_t *fp;                         // pointer to a 'pcap' structure
01519 int retval;                         // general variable used to keep the return value of other functions
01520 struct rpcap_header *header;        // general header according to the RPCAP format
01521 struct rpcap_pkthdr *net_pkt_header;// header of the packet
01522 struct pcap_pkthdr *pkt_header;     // pointer to the buffer that contains the header of the current packet
01523 int cc;                             // number of bytes of data available into the user buffer
01524 int pending= 0;                     // '1' if we've already read the pkt header, but there was not enough space to read the pkt data
01525 
01526 // Structures needed for the select() call
01527 fd_set rfds;                        // set of socket descriptors we have to check
01528 struct timeval tv;                  // maximum time the select() can block waiting for data
01529 
01530 
01531     // See the rpcap_thrdatamain_stream() for any comment about the code
01532     fp= (pcap_t *) ptr;
01533 
01534     *errbuf= 0; // Initialize errbuf
01535 
01536     // Modify thread params so that it can be killed at any time
01537     if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) )
01538         goto error;
01539     if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) )
01540         goto error;
01541 
01542     // Watch out sockdata to see if it has input
01543     FD_ZERO(&rfds);
01544 
01545     // We do not have to block here
01546     tv.tv_sec = 0;
01547     tv.tv_usec = 0;
01548 
01549     while (1)
01550     {
01551         if (fp->cc == 0) 
01552         {
01553             u_char *bp= fp->buffer;
01554             cc= 0;
01555 
01556             while (1)
01557             {
01558 again:
01559                 FD_SET(fp->rmt_sockdata, &rfds);
01560 
01561                 retval = select(1, &rfds, NULL, NULL, &tv);
01562                 if (retval == -1)
01563                 {
01564                     sock_geterror("select(): ", errbuf, PCAP_ERRBUF_SIZE);
01565                         goto error;
01566                 }
01567 
01568                 // There is no data waiting
01569                 if (retval == 0)
01570                 {
01571                     // Update the pcap_t pointers so that the user application can read from the buffer
01572                     fp->bp= fp->buffer;
01573                     fp->cc= cc;
01574 
01575                     pthread_suspend(100);   // Suspend 100 ms
01576                     break;
01577                 }
01578 
01579                 if (!pending)
01580                 {
01581                     // Read the entire message from the network
01582                     if (sock_recv_dgram(fp->rmt_sockdata, netbuf, RPCAP_NETBUF_SIZE, errbuf) == -1)
01583                         goto error;
01584                     header= (struct rpcap_header *) netbuf;
01585 
01586                     // Checks if the message is correct
01587                     retval= rpcap_checkmsg(errbuf, fp->rmt_sockdata, (struct rpcap_header *) netbuf, RPCAP_MSG_PACKET, 0);
01588 
01589                     if (retval != RPCAP_MSG_PACKET)     // the message is not the one expected
01590                     {
01591                         switch (retval)
01592                         {
01593                             case -3:        // Unrecoverable network error                          
01594                                 goto error; // Do nothing; just exit from here; the error code is already into the errbuf
01595 
01596                             case -2:        // The other endpoint sent a message that is not allowed here
01597                             case -1:    // The other endpoint has a version number that is not compatible with our
01598                                 goto again;
01599 
01600                             default:
01601                             {
01602                                 SOCK_ASSERT("Internal error", 0);
01603                                 goto error;
01604                             };
01605                         }
01606                     }
01607 
01608                     // Set a pointer to the RPCAP packet header
01609                     net_pkt_header= (struct rpcap_pkthdr *) (netbuf + sizeof(struct rpcap_header));
01610                 }
01611 
01612                 if ( (cc + ntohl(net_pkt_header->caplen) + sizeof(struct pcap_pkthdr) ) <= ( (unsigned) fp->bufsize) )
01613                 {
01614                     unsigned int npkt;
01615                     pending= 0;
01616 
01617                     pkt_header= (struct pcap_pkthdr *) bp;
01618                     pkt_header->caplen= ntohl(net_pkt_header->caplen);
01619                     pkt_header->len= ntohl(net_pkt_header->len);
01620                     pkt_header->ts.tv_sec= ntohl(net_pkt_header->timestamp_sec);
01621                     pkt_header->ts.tv_usec= ntohl(net_pkt_header->timestamp_usec);
01622 
01623                     // Update the number of packets received correctly
01624                     fp->md.TotCapt++;
01625 
01626                     // We're using UDP, so I need to update the counter of the packets dropped by the network
01627                     npkt= ntohl(net_pkt_header->npkt);
01628 
01629                     if (fp->md.TotCapt != npkt)
01630                     {
01631                         fp->md.TotNetDrops+= (npkt - fp->md.TotCapt);
01632                         fp->md.TotCapt= npkt;
01633                     }
01634 
01635                     // Copies the packet into the data buffer
01636                     memcpy( bp + sizeof(struct pcap_pkthdr), netbuf + sizeof(struct rpcap_header), pkt_header->caplen);
01637 
01638                     bp += BPF_WORDALIGN(pkt_header->caplen + sizeof(struct pcap_pkthdr));
01639                     cc += BPF_WORDALIGN(pkt_header->caplen + sizeof(struct pcap_pkthdr));
01640                 }
01641                 else
01642                 {
01643                     pending= 1;
01644 
01645                     // Update the pcap_t pointers so that the user application can read from the buffer
01646                     fp->bp= fp->buffer;
01647                     fp->cc= cc;
01648 
01649                     break;
01650                 }
01651             } // end while (1)
01652         }
01653         else
01654         {
01655             pthread_suspend(100);   // Suspend 100 ms
01656         }
01657     }   // end main while(1)
01658 
01659 error:
01660     SOCK_ASSERT("Exiting from the child data thread", 1);
01661     SOCK_ASSERT(errbuf, 1);
01662 
01663     // Removes the descriptor s from set
01664     FD_CLR(fp->rmt_sockdata, &rfds);
01665 
01666     closesocket(fp->rmt_sockdata);
01667     fp->rmt_sockdata= 0;
01668     fp->rmt_threaddata= 0;
01669 }
01670 
01671 
01672 
01673 
01674 
01675 
01676 /*********************************************************
01677  *                                                       *
01678  * Miscellaneous functions                               *
01679  *                                                       *
01680  *********************************************************/
01681 
01682 
01707 int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf)
01708 {
01709 char sendbuf[RPCAP_NETBUF_SIZE];            // temporary buffer in which data to be sent is buffered
01710 int sendbufidx= 0;                          // index which keeps the number of bytes currently buffered
01711 uint16 length;
01712 
01713     length= (uint16) strlen(error);
01714 
01715     if (length > PCAP_ERRBUF_SIZE)
01716         length= PCAP_ERRBUF_SIZE;
01717 
01718     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_ERROR, errcode, length);
01719 
01720     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf) )
01721         return -1;
01722 
01723     if ( sock_bufferize(error, length, sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf) )
01724         return -1;
01725 
01726     if ( sock_send(sock, sendbuf, sendbufidx, errbuf) )
01727         return -1;
01728 
01729     return 0;
01730 }
01731 
01732 
01733 
01752 int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf)
01753 {
01754 char sendbuf[RPCAP_NETBUF_SIZE];    // temporary buffer in which data that has to be sent is buffered
01755 int sendbufidx= 0;                  // index which keeps the number of bytes currently buffered
01756 uint16 length;                      // length of the payload of this message
01757 struct rpcap_auth *rpauth;
01758 uint16 auth_type;
01759 struct rpcap_header header;
01760 int retval;                         // temp variable which stores functions return value
01761 
01762     if (auth)
01763     {
01764     auth_type= auth->type;
01765 
01766         switch (auth->type)
01767         {
01768             case RPCAP_RMTAUTH_NULL:
01769                 length= sizeof (struct rpcap_auth);
01770                 break;
01771 
01772             case RPCAP_RMTAUTH_PWD:
01773                 length= sizeof (struct rpcap_auth);
01774                 if (auth->username) length+= strlen(auth->username);
01775                 if (auth->password) length+= strlen(auth->password);
01776                 break;
01777 
01778             default:
01779                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
01780                 return -1;
01781         }
01782     }
01783     else
01784     {
01785         auth_type= RPCAP_RMTAUTH_NULL;
01786         length= sizeof (struct rpcap_auth);
01787     }
01788 
01789 
01790     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf) )
01791         return -1;
01792 
01793     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_AUTH_REQ, 0, length);
01794 
01795     rpauth= (struct rpcap_auth *) &sendbuf[sendbufidx];
01796 
01797     if ( sock_bufferize(NULL, sizeof(struct rpcap_auth), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf) )
01798         return -1;
01799 
01800     memset(rpauth, 0, sizeof (struct rpcap_auth) );
01801 
01802     rpauth->type= htons(auth_type);
01803 
01804     if (auth_type == RPCAP_RMTAUTH_PWD)
01805     {
01806 
01807         if (auth->username)
01808             rpauth->slen1= strlen(auth->username);
01809         else
01810             rpauth->slen1= 0;
01811 
01812         if ( sock_bufferize(auth->username, rpauth->slen1, sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf) )
01813             return -1;
01814 
01815         if (auth->password)
01816             rpauth->slen2= strlen(auth->password);
01817         else
01818             rpauth->slen2= 0;
01819 
01820         if ( sock_bufferize(auth->password, rpauth->slen2, sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf) )
01821             return -1;
01822 
01823         rpauth->slen1= htons (rpauth->slen1);
01824         rpauth->slen2= htons (rpauth->slen2);
01825     }
01826 
01827     if ( sock_send(sock, sendbuf, sendbufidx, errbuf) )
01828         return -1;
01829 
01830     if ( sock_recv(sock, (char *) &header, sizeof(struct rpcap_header), errbuf) == -1)
01831         return -1;
01832 
01833     retval= rpcap_checkmsg(errbuf, sock, &header, RPCAP_MSG_AUTH_REPLY, RPCAP_MSG_ERROR, 0);
01834 
01835     if (retval != RPCAP_MSG_AUTH_REPLY)     // the message is not the one expected
01836     {
01837         switch (retval)
01838         {
01839             case -3:        // Unrecoverable network error
01840             case -2:        // The other endpoint sent a message that is not allowed here
01841             case -1:    // The other endpoint has a version number that is not compatible with our
01842                 // Do nothing; just exit from here; the error code is already into the errbuf
01843                 return -1;
01844 
01845             case RPCAP_MSG_ERROR:
01846             {
01847                 return -1;
01848             };
01849 
01850             default:
01851             {
01852                 SOCK_ASSERT("Internal error", 0);
01853                 return -1;
01854             };
01855         }
01856     }
01857 
01858     if (ntohl(header.plen) )
01859     {
01860         if (sock_discard(sock, ntohl(header.plen), errbuf) )
01861             return -1;
01862     }
01863     
01864     return 0;
01865 }
01866 
01867 
01868 
01890 void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length)
01891 {
01892     memset(header, 0, sizeof (struct rpcap_header) );
01893 
01894     header->ver= RPCAP_VERSION;
01895     header->type= type;
01896     header->value= htons(value);
01897     header->plen= htonl(length);
01898 }
01899 
01900 
01901 
01945 int rpcap_checkmsg(char *errbuf, SOCKET sock, struct rpcap_header *header, uint8 first, ...)
01946 {
01947 va_list ap;
01948 uint8 type;
01949 int32 len;
01950 
01951     va_start(ap, first);
01952 
01953     // Check if the present version of the protocol can handle this message
01954     if ( rpcap_checkver(sock, header, errbuf) )
01955     {
01956         SOCK_ASSERT(errbuf, 1);
01957 
01958         va_end(ap);
01959         return -1;
01960     }
01961 
01962     type= first;
01963 
01964     while ( type != 0 )
01965     {
01966         // The message matches with one of the types listed
01967         // There is no need of conversions since both values are uint8
01968 
01969         // Check if the other side reported an error.
01970         // If yes, it retrieves it and it returns it back to the caller
01971         if (header->type == RPCAP_MSG_ERROR)
01972         {
01973             len= ntohl(header->plen);
01974 
01975             if (len >= PCAP_ERRBUF_SIZE)
01976             {
01977                 if (sock_recv(sock, errbuf, PCAP_ERRBUF_SIZE -1, errbuf) )
01978                     return -3;
01979                 sock_discard(sock, len - (PCAP_ERRBUF_SIZE - 1), fakeerrbuf);
01980 
01981                 // Put '\0' at the end of the string
01982                 errbuf[PCAP_ERRBUF_SIZE - 1]= 0;
01983             }
01984             else
01985             {
01986                 if (sock_recv(sock, errbuf, len, errbuf) == -1)
01987                     return -3;
01988 
01989                 // Put '\0' at the end of the string
01990                 errbuf[len]= 0;
01991             }
01992 
01993 
01994             va_end(ap);
01995             return header->type;
01996         }
01997 
01998         if (header->type == type)
01999         {
02000             va_end(ap);
02001             return header->type;
02002         }
02003         
02004         // get next argument
02005         type= va_arg(ap, int);
02006     }
02007 
02008     // we already have an error, so please discard this one
02009     sock_discard(sock, ntohl(header->plen), fakeerrbuf);
02010 
02011     snprintf(errbuf, PCAP_ERRBUF_SIZE, "The other endpoint sent a message that is not allowed here.");
02012     SOCK_ASSERT(errbuf, 1);
02013 
02014     va_end(ap);
02015     return -2;
02016 }
02017 
02018 
02019 
02043 int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf)
02044 {
02045     /*
02046     This is a sample function.
02047 
02048     In the real world, you have to check at the type code, 
02049     and decide accordingly.
02050     */
02051 
02052     if (header->ver != RPCAP_VERSION)
02053     {
02054         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Incompatible version number: message discarded.");
02055 
02056         // we already have an error, so please discard this one
02057         sock_discard(sock, ntohl(header->plen), fakeerrbuf);
02058         return -1;
02059     }
02060 
02061     return 0;
02062 }
02063 
02064 
02065 
02086 int rpcap_remoteact_getsock(const char *host, char *errbuf)
02087 {
02088 struct activehosts *temp;                   // temp var needed to scan the host list chain
02089 struct addrinfo hints, *addrinfo, *ai_next; // temp var needed to translate between hostname to its address
02090 int retval;
02091 
02092     // retrieve the network address corresponding to 'host'
02093     addrinfo = NULL;
02094     memset(&hints, 0, sizeof (struct addrinfo) );
02095     hints.ai_family = PF_UNSPEC;
02096     hints.ai_socktype= SOCK_STREAM;
02097 
02098     retval = getaddrinfo(host, "0", &hints, &addrinfo);
02099     if (retval != 0)
02100     {
02101         snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
02102         return -1;
02103     }
02104 
02105     temp= activeHosts;
02106 
02107     while (temp)
02108     {
02109         ai_next= addrinfo;
02110         while(ai_next)
02111         {
02112             if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr ) == 0)
02113                 return (temp->sockctrl );
02114 
02115             ai_next= ai_next->ai_next;
02116         }
02117         temp= temp->next;
02118     }
02119 
02120     if (addrinfo)
02121         freeaddrinfo(addrinfo);
02122 
02123     // The host you want to get the socket ID does not have an active connection
02124     return 0;
02125 }
02126 
02127 
02128 
02129 
02130 

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