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.