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 
00135 int rpcap_deseraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf)
00136 {
00137     // Warning: we support only AF_INET and AF_INET6
00138     if ( ntohs(sockaddrin->ss_family) == AF_INET)
00139     {
00140     struct sockaddr_in *sockaddr;
00141     
00142         sockaddr= (struct sockaddr_in *) sockaddrin;
00143         sockaddr->sin_family= ntohs(sockaddr->sin_family);
00144         sockaddr->sin_port= ntohs(sockaddr->sin_port);
00145 
00146         (*sockaddrout)= (struct sockaddr_storage *) malloc ( sizeof(struct sockaddr_in) );
00147         if ( (*sockaddrout) == NULL)
00148         {
00149             snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00150             return -1;
00151         }
00152         memcpy( *sockaddrout, sockaddr, sizeof(struct sockaddr_in) );
00153         return 0;
00154     }
00155     if ( ntohs(sockaddrin->ss_family) == AF_INET6)
00156     {
00157     struct sockaddr_in6 *sockaddr;
00158     
00159         sockaddr= (struct sockaddr_in6 *) sockaddrin;
00160         sockaddr->sin6_family= ntohs(sockaddr->sin6_family);
00161         sockaddr->sin6_port= ntohs(sockaddr->sin6_port);
00162         sockaddr->sin6_flowinfo= ntohl(sockaddr->sin6_flowinfo);
00163         sockaddr->sin6_scope_id= ntohl(sockaddr->sin6_scope_id);
00164 
00165         (*sockaddrout)= (struct sockaddr_storage *) malloc ( sizeof(struct sockaddr_in6) );
00166         if ( (*sockaddrout) == NULL)
00167         {
00168             snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00169             return -1;
00170         }
00171         memcpy( *sockaddrout, sockaddr, sizeof(struct sockaddr_in6) );
00172         return 0;
00173     }
00174 
00175     // It is neither AF_INET nor AF_INET6
00176     *sockaddrout= NULL;
00177     return 0;
00178 }
00179 
00180 
00181 
00205 int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr **pkt_header, u_char **pkt_data)
00206 {
00207 struct rpcap_header *header;            // general header according to the RPCAP format
00208 struct rpcap_pkthdr *net_pkt_header;    // header of the packet
00209 char netbuf[RPCAP_NETBUF_SIZE]; // size of the network buffer in which the packet is copied, just for UDP
00210 unsigned int nread;                     // number of bytes (of payload) currently read from the network (referred to the current pkt)
00211 int retval;                             // generic return value
00212 
00213 // Structures needed for the select() call
00214 fd_set rfds;                            // set of socket descriptors we have to check
00215 struct timeval tv;                      // maximum time the select() can block waiting for data
00216 
00217 
00218     // Define the read timeout, to be used in the select()
00219     // 'timeout', in pcap_t, is in milliseconds; we have to convert it into sec and microsec
00220 #ifdef linux
00221     tv.tv_sec = p->md.timeout/1000;
00222     tv.tv_usec = (p->md.timeout - tv.tv_sec * 1000 )* 1000;
00223 #else
00224     tv.tv_sec = p->timeout/1000;
00225     tv.tv_usec = (p->timeout - tv.tv_sec * 1000 )* 1000;
00226 #endif
00227 
00228     // Watch out sockdata to see if it has input
00229     FD_ZERO(&rfds);
00230 
00231     // 'fp->rmt_sockdata' has always to be set before calling the select(),
00232     // since it is cleared by the select()
00233     FD_SET(p->rmt_sockdata, &rfds);
00234 
00235     retval = select(p->rmt_sockdata + 1, &rfds, NULL, NULL, &tv);
00236     if (retval == -1)
00237     {
00238         sock_geterror("select(): ", p->errbuf, PCAP_ERRBUF_SIZE);
00239         return -1;
00240     }
00241 
00242     // There is no data waiting, so return '0'
00243     if (retval == 0)
00244         return 0;
00245 
00246     // data is here; so, let's copy it into the user buffer
00247     // I'm going to read a new packet; so I reset the number of bytes (payload only) read
00248     nread= 0;
00249 
00250     // We have to define 'header' as a pointer to a larger buffer, 
00251     // because in case of UDP we have to read all the message within a single call
00252     header= (struct rpcap_header *) netbuf;
00253     net_pkt_header= (struct rpcap_pkthdr *) (netbuf + sizeof(struct rpcap_header) );
00254 
00255     if (p->rmt_flags & PCAP_OPENFLAG_UDP_DP)
00256     {
00257         // Read the entire message from the network
00258         if (sock_recv(p->rmt_sockdata, netbuf, RPCAP_NETBUF_SIZE, SOCK_RECEIVEALL_NO, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
00259             return -1;
00260     }
00261     else
00262     {
00263         if (sock_recv(p->rmt_sockdata, netbuf, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
00264             return -1;
00265     }
00266 
00267     // Checks if the message is correct
00268     retval= rpcap_checkmsg(p->errbuf, p->rmt_sockdata, header, RPCAP_MSG_PACKET, 0);
00269 
00270     if (retval != RPCAP_MSG_PACKET)     // the message is not the one expected
00271     {
00272         switch (retval)
00273         {
00274             case -3:        // Unrecoverable network error                                  
00275                 return -1;  // Do nothing; just exit from here; the error code is already into the errbuf
00276 
00277             case -2:        // The other endpoint sent a message that is not allowed here
00278             case -1:        // The other endpoint has a version number that is not compatible with our
00279                 return 0;   // Return 'no packets received'
00280 
00281             default:
00282             {
00283                 SOCK_ASSERT("Internal error", 1);
00284                 return 0;   // Return 'no packets received
00285             };
00286         }
00287     }
00288     
00289     // In case of TCP, read the remaining of the packet from the socket
00290     if ( !(p->rmt_flags & PCAP_OPENFLAG_UDP_DP))
00291     {
00292         // Read the RPCAP packet header from the network
00293         if ( (nread= sock_recv(p->rmt_sockdata, (char *) net_pkt_header, 
00294                     sizeof(struct rpcap_pkthdr), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE)) == -1)
00295             return -1;
00296     }
00297 
00298     if ( (ntohl(net_pkt_header->caplen) + sizeof(struct pcap_pkthdr) ) <= ( (unsigned) p->bufsize) )
00299     {
00300         // Initialize returned structures
00301         *pkt_header= (struct pcap_pkthdr *) p->buffer;
00302         *pkt_data= p->buffer + sizeof(struct pcap_pkthdr);
00303 
00304         (*pkt_header)->caplen= ntohl(net_pkt_header->caplen);
00305         (*pkt_header)->len= ntohl(net_pkt_header->len);
00306         (*pkt_header)->ts.tv_sec= ntohl(net_pkt_header->timestamp_sec);
00307         (*pkt_header)->ts.tv_usec= ntohl(net_pkt_header->timestamp_usec);
00308 
00309         // I don't update the counter of the packets dropped by the network since we're using TCP;
00310         // therefore no packets are dropped. Just update the number of packets received correctly
00311         p->md.TotCapt++;
00312 
00313         // Copies the packet into the data buffer
00314         if (p->rmt_flags & PCAP_OPENFLAG_UDP_DP)
00315         {
00316         unsigned int npkt;
00317 
00318             // In case of UDP the packet has already been read; we have to copy it into 'buffer'
00319             // Another option should bne to declare 'netbuf' as 'static'; however this prevents
00320             // using several pcap instances within the same process (because the static buffer is shared among
00321             // all processes)
00322             strncpy(*pkt_data, netbuf + sizeof(struct rpcap_header) + sizeof(struct pcap_pkthdr), (*pkt_header)->caplen);
00323 
00324             // We're using UDP, so we need to update the counter of the packets dropped by the network
00325             npkt= ntohl(net_pkt_header->npkt);
00326 
00327             if (p->md.TotCapt != npkt)
00328             {
00329                 p->md.TotNetDrops+= (npkt - p->md.TotCapt);
00330                 p->md.TotCapt= npkt;
00331             }
00332 
00333         }
00334         else
00335         {
00336             // In case of TCP, read the remaining of the packet from the socket
00337             if ( (nread+= sock_recv(p->rmt_sockdata, *pkt_data, (*pkt_header)->caplen, SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE)) == -1)
00338                 return -1;
00339 
00340             // Checks if all the data has been read; if not, discard the data in excess
00341             // This check has to be done only on TCP connections
00342             if (nread != ntohl(header->plen))
00343                 sock_discard(p->rmt_sockdata, ntohl(header->plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE);
00344         }
00345 
00346 
00347         // Packet read successfully
00348         return 1;
00349     }
00350     else
00351     {
00352         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Received a packet that is larger than the internal buffer size.");
00353         return -1;
00354     }
00355 
00356 }
00357 
00358 
00373 int pcap_read_remote(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
00374 {
00375 struct pcap_pkthdr *pkt_header;
00376 u_char *pkt_data;
00377 int n = 0;
00378 
00379     while ( (++n <= cnt) || (cnt < 0) )
00380     {
00381         if (pcap_read_nocb_remote(p, &pkt_header, &pkt_data) )
00382             (*callback)(user, pkt_header, pkt_data);
00383         else
00384             return n;
00385     }
00386     return n;
00387 }
00388 
00389 
00403 void pcap_close_remote(pcap_t *fp)
00404 {
00405 struct rpcap_header header;     // header of the RPCAP packet
00406 struct activehosts *temp;       // temp var needed to scan the host list chain, to detect if we're in active mode
00407 int active= 0;                  // active mode or not?
00408 
00409     // detect if we're in active mode
00410     temp= activeHosts;
00411     while (temp)
00412     {
00413         if (temp->sockctrl == fp->rmt_sockctrl)
00414         {
00415             active= 1;
00416             break;
00417         }
00418         temp= temp->next;
00419     }
00420 
00421     if (!active)
00422     {
00423         rpcap_createhdr( &header, RPCAP_MSG_CLOSE, 0, 0);
00424 
00425         // I don't check for errors, since I'm going to close everything
00426         sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), fakeerrbuf, PCAP_ERRBUF_SIZE);
00427     }
00428     else
00429     {
00430         rpcap_createhdr( &header, RPCAP_MSG_ENDCAP_REQ, 0, 0);
00431 
00432         // I don't check for errors, since I'm going to close everything
00433         sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), fakeerrbuf, PCAP_ERRBUF_SIZE);
00434 
00435         // wait for the answer
00436         // Don't check what we got, since the present libpcap does not uses this pcap_t anymore
00437         sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fakeerrbuf, PCAP_ERRBUF_SIZE);
00438 
00439         if ( ntohl(header.plen) != 0)
00440             sock_discard(fp->rmt_sockctrl, ntohl(header.plen), fakeerrbuf, PCAP_ERRBUF_SIZE);
00441     }
00442 
00443     if (fp->rmt_sockdata)
00444     {
00445         sock_close(fp->rmt_sockdata, fakeerrbuf, PCAP_ERRBUF_SIZE);
00446         fp->rmt_sockdata= 0;
00447     }
00448 
00449     if ( (!active) && (fp->rmt_sockctrl) )
00450         sock_close(fp->rmt_sockctrl, fakeerrbuf, PCAP_ERRBUF_SIZE);
00451 
00452     fp->rmt_sockctrl= 0;
00453 
00454     // To avoid inconsistencies in the number of sock_init()
00455     sock_cleanup();
00456 }
00457 
00458 
00459 
00469 int pcap_stats_remote(pcap_t *p, struct pcap_stat *ps)
00470 {
00471 struct pcap_stat *retval;
00472 
00473     retval= rpcap_stats_remote(p, ps, PCAP_STATS_STANDARD);
00474 
00475     if (retval)
00476         return 0;
00477     else
00478         return -1;
00479 }
00480 
00481 
00482 
00492 struct pcap_stat *pcap_stats_ex_remote(pcap_t *p)
00493 {
00494     // '0' (third param) means 'standard pcap_stats()'
00495     return (rpcap_stats_remote(p, &(p->md.stat), PCAP_STATS_EX));
00496 }
00497 
00498 
00499 
00530 struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode)
00531 {
00532 struct rpcap_header header;         // header of the RPCAP packet
00533 struct rpcap_stats netstats;        // statistics sent on the network
00534 unsigned int nread= 0;              // number of bytes of the payload read from the socket
00535 int retval;                         // temp variable which stores functions return value
00536 
00537     rpcap_createhdr(&header, RPCAP_MSG_STATS_REQ, 0, 0);
00538 
00539     // Send the PCAP_STATS command
00540     if (sock_send(p->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), p->errbuf, PCAP_ERRBUF_SIZE) )
00541         goto error;
00542 
00543     // Receive the RPCAP stats reply message
00544     if (sock_recv(p->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
00545         goto error;
00546 
00547     // Checks if the message is correct
00548     retval= rpcap_checkmsg(p->errbuf, p->rmt_sockctrl, &header, RPCAP_MSG_STATS_REPLY, RPCAP_MSG_ERROR, 0);
00549 
00550     if (retval != RPCAP_MSG_STATS_REPLY)        // the message is not the one expected
00551     {
00552         switch (retval)
00553         {
00554             case -3:        // Unrecoverable network error
00555             case -2:        // The other endpoint send a message that is not allowed here
00556             case -1:    // The other endpoint has a version number that is not compatible with our
00557                 goto error;
00558 
00559             case RPCAP_MSG_ERROR:       // The other endpoint reported an error
00560                 // Update nread, since the rpcap_checkmsg() already purged the buffer
00561                 nread = ntohl(header.plen);
00562 
00563                 // Do nothing; just exit; the error code is already into the errbuf
00564                 goto error;
00565 
00566             default:
00567             {
00568                 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
00569                 goto error;
00570             };
00571         }
00572     }
00573 
00574     if ( (nread= sock_recv(p->rmt_sockctrl, (char *) &netstats, sizeof(struct rpcap_stats), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE)) == -1)
00575         goto error;
00576 
00577     if (mode == PCAP_STATS_STANDARD)
00578     {
00579         ps->ps_drop= ntohl(netstats.krnldrop);
00580         ps->ps_ifdrop= ntohl(netstats.ifdrop);
00581         ps->ps_recv= ntohl(netstats.ifrecv);
00582     }
00583     else
00584     {
00585         ps->ps_capt= p->md.TotCapt;
00586         ps->ps_drop= ntohl(netstats.krnldrop);
00587         ps->ps_ifdrop= ntohl(netstats.ifdrop);
00588         ps->ps_netdrop= p->md.TotNetDrops;
00589         ps->ps_recv= ntohl(netstats.ifrecv);
00590         ps->ps_sent= ntohl(netstats.svrcapt);
00591     }
00592 
00593     // Checks if all the data has been read; if not, discard the data in excess
00594     if (nread != ntohl(header.plen))
00595     {
00596         if (sock_discard(p->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE) == 1)
00597             goto error;
00598     }
00599 
00600     return ps;
00601 
00602 error:
00603     if (nread != ntohl(header.plen))
00604         sock_discard(p->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE);
00605 
00606     return NULL;
00607 }
00608 
00609 
00610 
00611 
00650 pcap_t *pcap_opensource_remote(const char *source, struct pcap_rmtauth *auth, char *errbuf)
00651 {
00652 char host[PCAP_BUF_SIZE], ctrlport[PCAP_BUF_SIZE], iface[PCAP_BUF_SIZE];
00653 
00654 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered
00655 int sendbufidx= 0;              // index which keeps the number of bytes currently buffered
00656 struct pcap *fp= NULL;          // pcap_t main variable
00657 unsigned int nread= 0;          // number of bytes of the payload read from the socket
00658 int retval;                     // store the return value of the functions
00659 int active= 0;                      // '1' if we're in active mode
00660 
00661 // socket-related variables
00662 struct addrinfo hints;          // temp, needed to open a socket connection
00663 struct addrinfo *addrinfo;      // temp, needed to open a socket connection
00664 SOCKET sockctrl= 0;             // socket descriptor of the control connection
00665 
00666 // RPCAP-related variables
00667 struct rpcap_header header;         // header of the RPCAP packet
00668 struct rpcap_openreply openreply;   // open reply message
00669 
00670 
00671     // determine the type of the source (NULL, file, local, remote)
00672     // You must have a valid source string even if we're in active mode, because otherwise
00673     // the call to the following funciton will fail.
00674     if (pcap_parsesrcstr(source, &retval, host, ctrlport, iface, errbuf) == -1)
00675         return NULL;
00676 
00677     if ( retval != PCAP_SRC_IFREMOTE)
00678     {
00679         snprintf(errbuf, PCAP_ERRBUF_SIZE, "This function is able to open only remote interfaces");
00680         return NULL;
00681     }
00682 
00683     addrinfo= NULL;
00684 
00685     // Warning: this call can be the first one called by the user.
00686     // For this reason, we have to initialize the WinSock support.
00687     if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
00688         return NULL;
00689 
00690     retval= rpcap_remoteact_getsock(host, errbuf);
00691 
00692     if (retval == -1)
00693         return NULL;
00694 
00695     // The capturing machine is in active mode
00696     if (retval)
00697     {
00698         sockctrl= retval;
00699         active= 1;
00700     }
00701     else
00702     {
00703         memset(&hints, 0, sizeof(struct addrinfo) );
00704         hints.ai_family = PF_UNSPEC;
00705         hints.ai_socktype = SOCK_STREAM;
00706 
00707         if ( (ctrlport == NULL) || (ctrlport[0] == 0) )
00708         {
00709             // the user chose not to specify the port
00710             if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
00711                 return NULL;
00712         }
00713         else
00714         {
00715             // the user chose not to specify the port
00716             if (sock_initaddress(host, ctrlport, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
00717                 return NULL;
00718         }
00719 
00720         if ( (sockctrl= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1)
00721             goto error;
00722 
00723         freeaddrinfo(addrinfo);
00724         addrinfo= NULL;
00725 
00726         if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1)
00727             goto error;
00728     }
00729 
00730 
00731     // Now it's time to start playing with the RPCAP protocol
00732     // RPCAP open command: create the request message
00733     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 
00734         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) )
00735         goto error;
00736 
00737     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_OPEN_REQ, 0, strlen(iface) );
00738 
00739     if ( sock_bufferize(iface, strlen(iface), sendbuf, &sendbufidx, 
00740         RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) )
00741         goto error;
00742 
00743     if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) )
00744         goto error;
00745 
00746     // Receive the RPCAP open reply message
00747     if (sock_recv(sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
00748         goto error;
00749 
00750     // Checks if the message is correct
00751     retval= rpcap_checkmsg(errbuf, sockctrl, &header, RPCAP_MSG_OPEN_REPLY, RPCAP_MSG_ERROR, 0);
00752 
00753     if (retval != RPCAP_MSG_OPEN_REPLY)     // the message is not the one expected
00754     {
00755         switch (retval)
00756         {
00757             case -3:        // Unrecoverable network error
00758             case -2:        // The other endpoint send a message that is not allowed here
00759             case -1:    // The other endpoint has a version number that is not compatible with our
00760                 goto error;
00761 
00762             case RPCAP_MSG_ERROR:       // The other endpoint reported an error
00763                 // Update nread, since the rpcap_checkmsg() already purged the buffer
00764                 nread = ntohl(header.plen);
00765                 // Do nothing; just exit; the error code is already into the errbuf
00766                 goto error;
00767 
00768             default:
00769             {
00770                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Internal error");
00771                 goto error;
00772             };
00773         }
00774     }
00775 
00776 
00777     if ( (nread+= sock_recv(sockctrl, (char *) &openreply, sizeof(struct rpcap_openreply), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
00778         goto error;
00779 
00780     // Allocates a pcap_t struct for this end of the connection
00781     fp = (pcap_t *) malloc( sizeof(pcap_t) );
00782     if (fp == NULL)
00783     {
00784         snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00785         goto error;
00786     }
00787 
00788     memset(fp, 0, sizeof(pcap_t));
00789 
00790     // Set proper fields into the pcap_t struct
00791     fp->linktype= ntohl(openreply.linktype);
00792     fp->tzoff= ntohl(openreply.tzoff);
00793     fp->rmt_sockctrl= sockctrl;
00794     fp->rmt_clientside= 1;
00795 
00796 
00797     // Checks if all the data has been read; if not, discard the data in excess
00798     if (nread != ntohl(header.plen))
00799     {
00800         if (sock_discard(sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE) == 1)
00801             goto error;
00802     }
00803     return fp;
00804 
00805 error:
00806 // When the connection has been established, we have to close it. So, at the
00807 // beginning of this function, if an error occur we return immediately with
00808 // a return NULL; when the connection is established, we have to come here 
00809 // ('goto error;') in order to close everything properly.
00810 
00811     // Checks if all the data has been read; if not, discard the data in excess
00812     if (nread != ntohl(header.plen))
00813         sock_discard(sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE);
00814 
00815     if (addrinfo)
00816         freeaddrinfo(addrinfo);
00817 
00818     if (!active)
00819         sock_close(sockctrl, fakeerrbuf, PCAP_ERRBUF_SIZE);
00820 
00821     if (fp)
00822     {
00823         pcap_close(fp);
00824         fp= NULL;
00825     }
00826 
00827     return NULL;
00828 }
00829 
00830 
00831 
00832 
00833 
00834 
00835 
00858 int pcap_startcapture_remote(pcap_t *fp)
00859 {
00860 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered
00861 int sendbufidx= 0;              // index which keeps the number of bytes currently buffered
00862 char portdata[PCAP_BUF_SIZE];   // temp variable needed to keep the network port for the the data connection
00863 unsigned int nread= 0;          // number of bytes of the payload read from the socket
00864 int retval;                     // store the return value of the functions
00865 int active= 0;                  // '1' if we're in active mode
00866 struct activehosts *temp;       // temp var needed to scan the host list chain, to detect if we're in active mode
00867 char host[INET6_ADDRSTRLEN + 1];    // numeric name of the other host
00868 
00869 // socket-related variables
00870 struct addrinfo hints;          // temp, needed to open a socket connection
00871 struct addrinfo *addrinfo;      // temp, needed to open a socket connection
00872 SOCKET sockdata= 0;             // socket descriptor of the data connection
00873 struct sockaddr_storage saddr;  // temp, needed to retrieve the network data port chosen on the local machine
00874 socklen_t saddrlen;             // temp, needed to retrieve the network data port chosen on the local machine
00875 int ai_family;                  // temp, keeps the address family used by the control connection
00876 
00877 // RPCAP-related variables
00878 struct rpcap_header header;                 // header of the RPCAP packet
00879 struct rpcap_startcapreq *startcapreq;      // start capture request message
00880 struct rpcap_startcapreply startcapreply;   // start capture reply message
00881 
00882 // Variables related to the buffer setting
00883 int res, itemp;
00884 int sockbufsize= 0;
00885 
00886 
00887     // Let's check if sampling has been required.
00888     // If so, let's set it first
00889     if (pcap_setsampling_remote(fp) != 0)
00890         return -1;
00891 
00892 
00893     // detect if we're in active mode
00894     temp= activeHosts;
00895     while (temp)
00896     {
00897         if (temp->sockctrl == fp->rmt_sockctrl)
00898         {
00899             active= 1;
00900             break;
00901         }
00902         temp= temp->next;
00903     }
00904 
00905     addrinfo= NULL;
00906 
00907     // Gets the complete sockaddr structure used in the ctrl connection
00908     // This is needed to get the address family of the control socket
00909     // Tip: I cannot save the ai_family of the ctrl sock in the pcap_t struct,
00910     // since the ctrl socket can already be open in case of active mode;
00911     // so I would have to call getpeername() anyway
00912     saddrlen = sizeof(struct sockaddr_storage);
00913     if (getpeername(fp->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
00914     {
00915         sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
00916         goto error;
00917     }
00918     ai_family= ((struct sockaddr_storage *) &saddr)->ss_family;
00919 
00920     // Get the numeric address of the remote host we are connected to
00921     if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, host, 
00922             sizeof(host), NULL, 0, NI_NUMERICHOST) )
00923     {
00924         sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
00925         goto error;
00926     }
00927 
00928     /*
00929         Data connection is opened by the server toward the client if:
00930         - we're using TCP, and the user wants us to be in active mode
00931         - we're using UDP
00932     */
00933     if ( (active) || (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) )
00934     {
00935         // We have to create a new socket to receive packets
00936         // We have to do that immediately, since we have to tell the other 
00937         // end which network port we picked up
00938         memset(&hints, 0, sizeof(struct addrinfo) );
00939         // TEMP addrinfo is NULL in case of active
00940         hints.ai_family = ai_family;    // Use the same address family of the control socket
00941         hints.ai_socktype = (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) ? SOCK_DGRAM : SOCK_STREAM;
00942         hints.ai_flags = AI_PASSIVE;    // Data connection is opened by the server toward the client
00943 
00944         // Let's the server pick up a free network port for us
00945         if (sock_initaddress(NULL, "0", &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
00946             goto error;
00947 
00948         if ( (sockdata= sock_open(addrinfo, SOCKOPEN_SERVER, 
00949             1 /* max 1 connection in queue */, fp->errbuf, PCAP_ERRBUF_SIZE)) == -1)
00950             goto error;
00951 
00952         // addrinfo is no longer used
00953         freeaddrinfo(addrinfo);
00954         addrinfo= NULL;
00955 
00956         // get the complete sockaddr structure used in the data connection
00957         saddrlen = sizeof(struct sockaddr_storage);
00958         if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
00959         {
00960             sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
00961             goto error;
00962         }
00963 
00964         // Get the local port the system picked up
00965         if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, NULL, 
00966                 0, portdata, sizeof(portdata), NI_NUMERICSERV) )
00967         {
00968             sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
00969             goto error;
00970         }
00971     }
00972 
00973     // Now it's time to start playing with the RPCAP protocol
00974     // RPCAP start ca[ture command: create the request message
00975     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 
00976         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) )
00977         goto error;
00978 
00979     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STARTCAP_REQ, 0,
00980         sizeof(struct rpcap_startcapreq) + sizeof(struct rpcap_filter) + fp->fcode.bf_len * sizeof(struct rpcap_filterbpf_insn) );
00981 
00982     // Fill the structure needed to open an adapter remotely
00983     startcapreq= (struct rpcap_startcapreq *) &sendbuf[sendbufidx];
00984 
00985     if ( sock_bufferize(NULL, sizeof(struct rpcap_startcapreq), NULL, 
00986         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) )
00987         goto error;
00988 
00989     memset(startcapreq, 0, sizeof(struct rpcap_startcapreq) );
00990 
00991     // By default, apply half the timeout on one side, half of the other
00992 #ifdef linux
00993     fp->md.timeout= fp->md.timeout/2;
00994     startcapreq->read_timeout= htonl(fp->md.timeout);
00995 #else
00996     fp->timeout= fp->timeout/2;
00997     startcapreq->read_timeout= htonl(fp->timeout);
00998 #endif
00999 
01000     // portdata on the openreq is meaningful only if we're in active mode
01001     if ( (active) || (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) )
01002     {
01003         sscanf(portdata, "%d", &(startcapreq->portdata));
01004         startcapreq->portdata= htons(startcapreq->portdata);
01005     }
01006 
01007     startcapreq->snaplen= htonl(fp->snapshot);
01008     startcapreq->flags= 0;
01009     if (fp->rmt_flags & PCAP_OPENFLAG_PROMISCUOUS)
01010         startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_PROMISC;
01011     if (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP)
01012         startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_DGRAM;
01013     if (active)
01014         startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_SERVEROPEN;
01015 
01016     startcapreq->flags= htons(startcapreq->flags);
01017 
01018     // Pack the capture filter
01019     if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, &fp->fcode) )
01020         goto error;
01021 
01022     if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) )
01023         goto error;
01024 
01025 
01026     // Receive the RPCAP start capture reply message
01027     if (sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
01028         goto error;
01029 
01030     // Checks if the message is correct
01031     retval= rpcap_checkmsg(fp->errbuf, fp->rmt_sockctrl, &header, RPCAP_MSG_STARTCAP_REPLY, RPCAP_MSG_ERROR, 0);
01032 
01033     if (retval != RPCAP_MSG_STARTCAP_REPLY)     // the message is not the one expected
01034     {
01035         switch (retval)
01036         {
01037             case -3:        // Unrecoverable network error
01038             case -2:        // The other endpoint send a message that is not allowed here
01039             case -1:    // The other endpoint has a version number that is not compatible with our
01040                 goto error;
01041 
01042             case RPCAP_MSG_ERROR:       // The other endpoint reported an error
01043                 // Update nread, since the rpcap_checkmsg() already purged the buffer
01044                 nread = ntohl(header.plen);
01045                 // Do nothing; just exit; the error code is already into the errbuf
01046                 goto error;
01047 
01048             default:
01049             {
01050                 snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
01051                 goto error;
01052             };
01053         }
01054     }
01055 
01056 
01057     if ( (nread+= sock_recv(fp->rmt_sockctrl, (char *) &startcapreply, 
01058         sizeof(struct rpcap_startcapreply), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE)) == -1)
01059         goto error;
01060 
01061     // In case of UDP data stream, the connection is always opened by the daemon
01062     // So, this case is already covered by the code above.
01063     // Now, we have still to handle TCP connections, because:
01064     // - if we're in active mode, we have to wait for a remote connection
01065     // - if we're in passive more, we have to start a connection
01066     //
01067     // We have to do he job in two steps because in case we're opening a tcp connection, we have
01068     // to tell the port we're using to the remote side; in case we're accepting a TCP
01069     // connection, we have to wait this info from the remote side.
01070 
01071     if (!(fp->rmt_flags & PCAP_OPENFLAG_UDP_DP))
01072     {
01073         if (!active)
01074         {
01075             memset(&hints, 0, sizeof(struct addrinfo) );
01076             hints.ai_family = ai_family;        // Use the same address family of the control socket
01077             hints.ai_socktype = (fp->rmt_flags & PCAP_OPENFLAG_UDP_DP) ? SOCK_DGRAM : SOCK_STREAM;
01078 
01079             sprintf(portdata, "%d", ntohs(startcapreply.portdata) );
01080 
01081             // Let's the server pick up a free network port for us
01082             if (sock_initaddress(host, portdata, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
01083                 goto error;
01084 
01085             if ( (sockdata= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf, PCAP_ERRBUF_SIZE)) == -1)
01086                 goto error;
01087 
01088             // addrinfo is no longer used
01089             freeaddrinfo(addrinfo);
01090             addrinfo= NULL;
01091         }
01092         else
01093         {
01094         SOCKET socktemp;    // We need another socket, since we're going to accept() a connection
01095 
01096             // Connection creation
01097             saddrlen = sizeof(struct sockaddr_storage);
01098 
01099             socktemp= accept(sockdata, (struct sockaddr *) &saddr, &saddrlen);
01100             
01101             if (socktemp == -1)
01102             {
01103                 sock_geterror("accept(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
01104                 goto error;
01105             }
01106 
01107             // Now that I accepted the connection, the server socket is no longer needed
01108             sock_close(sockdata, fp->errbuf, PCAP_ERRBUF_SIZE);
01109             sockdata= socktemp;
01110         }
01111     }
01112 
01113     // Let's save the socket of the data connection
01114     fp->rmt_sockdata= sockdata;
01115 
01116     // Allocates WinPcap/libpcap user buffer, which is a socket buffer in case of a remote capture
01117     // It has the same size of the one used on the other side of the connection
01118     fp->bufsize= ntohl(startcapreply.bufsize);
01119 
01120     // Let's get the actual size of the socket buffer
01121     itemp= sizeof(sockbufsize);
01122 
01123     res= getsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, &itemp);
01124     if (res == -1)
01125     {
01126         sock_geterror("pcap_startcapture_remote()", fp->errbuf, PCAP_ERRBUF_SIZE);
01127         SOCK_ASSERT(fp->errbuf, 1);
01128     }
01129 
01130     /*
01131         Warning: on some kernels (e.g. linux), the size of the user buffer does not take
01132         into account the pcap_header and such, and it is set equal to the snaplen.
01133         In my view, this is wrong (the meaning of the bufsize becames a bit strange).
01134         So, here bufsize is the whole size of the user buffer.
01135         In case the bufsize returned is too small, let's adjust it accordingly.
01136     */
01137     if (fp->bufsize <= fp->snapshot)
01138         fp->bufsize+= sizeof (struct pcap_pkthdr);
01139 
01140     // if the current socket buffer is smaller than the desired one
01141     if (sockbufsize < fp->bufsize)
01142     {
01143         // Loop until the buffer size is OK or the original socket buffer size is larger than this one
01144         while (1)
01145         {
01146             res= setsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *) &(fp->bufsize), sizeof(fp->bufsize) );
01147 
01148             if (res == 0)
01149                 break;
01150 
01151             // If something goes wrong, half the buffer size (checking that it does not become smaller than
01152             // the current one)
01153             fp->bufsize/= 2;
01154 
01155             if (sockbufsize >= fp->bufsize)
01156             {
01157                 fp->bufsize= sockbufsize;
01158                 break;
01159             }
01160         }
01161     }
01162 
01163     // Let's allocate the packet; this is required in order to put the packet somewhere when 
01164     // extracting data from the socket
01165     // Since buffering has already been done in the socket buffer, here we need just a buffer,
01166     // whose size is equal to the pcap header plus the snapshot length
01167     fp->bufsize= fp->snapshot + sizeof (struct pcap_pkthdr);
01168 
01169     fp->buffer = (u_char *) malloc(fp->bufsize);
01170     if (fp->buffer == NULL)
01171     {
01172         snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
01173         goto error;
01174     }
01175 
01176 
01177     // Checks if all the data has been read; if not, discard the data in excess
01178     if (nread != ntohl(header.plen))
01179     {
01180         if (sock_discard(fp->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE) == 1)
01181             goto error;
01182     }
01183     return 0;
01184 
01185 error:
01186 // When the connection has been established, we have to close it. So, at the
01187 // beginning of this function, if an error occur we return immediately with
01188 // a return NULL; when the connection is established, we have to come here 
01189 // ('goto error;') in order to close everything properly.
01190 
01191     // Checks if all the data has been read; if not, discard the data in excess
01192     if (nread != ntohl(header.plen))
01193         sock_discard(fp->rmt_sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE);
01194 
01195     if ((sockdata) && (sockdata != -1))     // we can be here because sockdata said 'error'
01196         sock_close(sockdata, fakeerrbuf, PCAP_ERRBUF_SIZE);
01197 
01198     if (!active)
01199         sock_close(fp->rmt_sockctrl, fakeerrbuf, PCAP_ERRBUF_SIZE);
01200 
01201     if (fp)
01202     {
01203         pcap_close(fp);
01204         fp= NULL;
01205     }
01206 
01207     return -1;
01208 }
01209 
01210 
01211 
01212 
01213 
01237 int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog)
01238 {
01239 struct rpcap_filter *filter;
01240 struct rpcap_filterbpf_insn *insn;
01241 struct bpf_insn *bf_insn;
01242 unsigned int i;
01243 
01244     filter= (struct rpcap_filter *) sendbuf;
01245 
01246     if ( sock_bufferize(NULL, sizeof(struct rpcap_filter), NULL, sendbufidx, 
01247         RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) )
01248         return -1;
01249 
01250     filter->filtertype= htons(RPCAP_UPDATEFILTER_BPF);
01251     filter->nitems= htonl( (int32) prog->bf_len);
01252 
01253     if ( sock_bufferize(NULL, prog->bf_len * sizeof(struct rpcap_filterbpf_insn), 
01254         NULL, sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) )
01255         return -1;
01256     
01257     insn= (struct rpcap_filterbpf_insn *) (filter + 1);
01258     bf_insn= prog->bf_insns;
01259 
01260     for (i= 0; i < prog->bf_len; i++)
01261     {
01262         insn->code= htons(bf_insn->code);
01263         insn->jf= bf_insn->jf;
01264         insn->jt= bf_insn->jt;
01265         insn->k= htonl(bf_insn->k);
01266 
01267         insn++;
01268         bf_insn++;
01269     }
01270     return 0;
01271 }
01272 
01273 
01274 
01275 
01276 
01296 int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog)
01297 {
01298 int retval;                     // general variable used to keep the return value of other functions
01299 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered
01300 int sendbufidx= 0;              // index which keeps the number of bytes currently buffered
01301 struct rpcap_header header;     // To keep the reply message
01302 
01303 
01304     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, 
01305         RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) )
01306         return -1;
01307 
01308     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_UPDATEFILTER_REQ, 0,
01309         sizeof(struct rpcap_filter) + prog->bf_len * sizeof(struct rpcap_filterbpf_insn));
01310 
01311     if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, prog) )
01312         return -1;
01313 
01314     if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) )
01315         return -1;
01316 
01317     // Waits for the answer
01318     if (sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
01319         return -1;
01320 
01321     // Checks if the message is correct
01322     retval= rpcap_checkmsg(fp->errbuf, fp->rmt_sockctrl, &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0);
01323 
01324     if (retval != RPCAP_MSG_UPDATEFILTER_REPLY)     // the message is not the one expected
01325     {
01326         switch (retval)
01327         {
01328             case -3:        // Unrecoverable network error
01329             case -2:        // The other endpoint sent a message that is not allowed here
01330             case -1:    // The other endpoint has a version number that is not compatible with our
01331                 // Do nothing; just exit from here; the error code is already into the errbuf
01332                 return -1;
01333 
01334             default:
01335             {
01336                 SOCK_ASSERT("Internal error", 0);
01337                 return -1;
01338             };
01339         }
01340     }
01341 
01342     if (ntohl(header.plen) != 0)    // the message has an unexpected size
01343     {
01344         if (sock_discard(fp->rmt_sockctrl, ntohl(header.plen), fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
01345             return -1;
01346     }
01347 
01348     return 0;
01349 }
01350 
01351 
01352 
01353 
01365 int pcap_setfilter_remote(pcap_t *fp, struct bpf_program *prog)
01366 {
01367     if (!fp->rmt_capstarted)
01368     {
01369         // copy filter into the pcap_t structure
01370         if (install_bpf_program(fp, prog) == -1)
01371             return -1;
01372         return 0;
01373     }
01374 
01375     // we have to update a filter during run-time
01376     if (pcap_updatefilter_remote(fp, prog) )
01377         return -1;
01378 
01379     return 0;
01380 }
01381 
01382 
01383 
01398 int pcap_setsampling_remote(pcap_t *p)
01399 {
01400 int retval;                     // general variable used to keep the return value of other functions
01401 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered
01402 int sendbufidx= 0;              // index which keeps the number of bytes currently buffered
01403 struct rpcap_header header;     // To keep the reply message
01404 struct rpcap_sampling *sampling_pars;   // Structure that is needed to send sampling parameters to the remote host
01405 
01406     // If no samping is requested, return 'ok'
01407     if (p->rmt_samp.method == PCAP_SAMP_NOSAMP)
01408         return 0;
01409 
01410     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 
01411         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, p->errbuf, PCAP_ERRBUF_SIZE) )
01412         return -1;
01413 
01414     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_SETSAMPLING_REQ, 0, sizeof(struct rpcap_sampling) );
01415 
01416     // Fill the structure needed to open an adapter remotely
01417     sampling_pars= (struct rpcap_sampling *) &sendbuf[sendbufidx];
01418 
01419     if ( sock_bufferize(NULL, sizeof(struct rpcap_sampling), NULL, 
01420         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, p->errbuf, PCAP_ERRBUF_SIZE) )
01421         return -1;
01422 
01423     memset(sampling_pars, 0, sizeof(struct rpcap_sampling) );
01424 
01425     sampling_pars->method= p->rmt_samp.method;
01426     sampling_pars->value= htonl(p->rmt_samp.value);
01427 
01428     if ( sock_send(p->rmt_sockctrl, sendbuf, sendbufidx, p->errbuf, PCAP_ERRBUF_SIZE) )
01429         return -1;
01430 
01431     // Waits for the answer
01432     if (sock_recv(p->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
01433         return -1;
01434 
01435     // Checks if the message is correct
01436     retval= rpcap_checkmsg(p->errbuf, p->rmt_sockctrl, &header, RPCAP_MSG_SETSAMPLING_REPLY, 0);
01437 
01438     if (retval != RPCAP_MSG_SETSAMPLING_REPLY)      // the message is not the one expected
01439     {
01440         switch (retval)
01441         {
01442             case -3:        // Unrecoverable network error
01443             case -2:        // The other endpoint sent a message that is not allowed here
01444             case -1:    // The other endpoint has a version number that is not compatible with our
01445             case RPCAP_MSG_ERROR:
01446                 // Do nothing; just exit from here; the error code is already into the errbuf
01447                 return -1;
01448 
01449             default:
01450             {
01451                 SOCK_ASSERT("Internal error", 0);
01452                 return -1;
01453             };
01454         }
01455     }
01456 
01457     if (ntohl(header.plen) != 0)    // the message has an unexpected size
01458     {
01459         if (sock_discard(p->rmt_sockctrl, ntohl(header.plen), p->errbuf, PCAP_ERRBUF_SIZE) == -1)
01460             return -1;
01461     }
01462 
01463     return 0;
01464 
01465 }
01466 
01467 
01468 
01469 
01470 
01471 /*********************************************************
01472  *                                                       *
01473  * Miscellaneous functions                               *
01474  *                                                       *
01475  *********************************************************/
01476 
01477 
01502 int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf)
01503 {
01504 char sendbuf[RPCAP_NETBUF_SIZE];            // temporary buffer in which data to be sent is buffered
01505 int sendbufidx= 0;                          // index which keeps the number of bytes currently buffered
01506 uint16 length;
01507 
01508     length= (uint16) strlen(error);
01509 
01510     if (length > PCAP_ERRBUF_SIZE)
01511         length= PCAP_ERRBUF_SIZE;
01512 
01513     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_ERROR, errcode, length);
01514 
01515     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, 
01516         RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) )
01517         return -1;
01518 
01519     if ( sock_bufferize(error, length, sendbuf, &sendbufidx, 
01520         RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) )
01521         return -1;
01522 
01523     if ( sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) )
01524         return -1;
01525 
01526     return 0;
01527 }
01528 
01529 
01530 
01549 int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf)
01550 {
01551 char sendbuf[RPCAP_NETBUF_SIZE];    // temporary buffer in which data that has to be sent is buffered
01552 int sendbufidx= 0;                  // index which keeps the number of bytes currently buffered
01553 uint16 length;                      // length of the payload of this message
01554 struct rpcap_auth *rpauth;
01555 uint16 auth_type;
01556 struct rpcap_header header;
01557 int retval;                         // temp variable which stores functions return value
01558 
01559     if (auth)
01560     {
01561     auth_type= auth->type;
01562 
01563         switch (auth->type)
01564         {
01565             case RPCAP_RMTAUTH_NULL:
01566                 length= sizeof (struct rpcap_auth);
01567                 break;
01568 
01569             case RPCAP_RMTAUTH_PWD:
01570                 length= sizeof (struct rpcap_auth);
01571                 if (auth->username) length+= strlen(auth->username);
01572                 if (auth->password) length+= strlen(auth->password);
01573                 break;
01574 
01575             default:
01576                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
01577                 return -1;
01578         }
01579     }
01580     else
01581     {
01582         auth_type= RPCAP_RMTAUTH_NULL;
01583         length= sizeof (struct rpcap_auth);
01584     }
01585 
01586 
01587     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 
01588         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) )
01589         return -1;
01590 
01591     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_AUTH_REQ, 0, length);
01592 
01593     rpauth= (struct rpcap_auth *) &sendbuf[sendbufidx];
01594 
01595     if ( sock_bufferize(NULL, sizeof(struct rpcap_auth), NULL, 
01596         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) )
01597         return -1;
01598 
01599     memset(rpauth, 0, sizeof (struct rpcap_auth) );
01600 
01601     rpauth->type= htons(auth_type);
01602 
01603     if (auth_type == RPCAP_RMTAUTH_PWD)
01604     {
01605 
01606         if (auth->username)
01607             rpauth->slen1= strlen(auth->username);
01608         else
01609             rpauth->slen1= 0;
01610 
01611         if ( sock_bufferize(auth->username, rpauth->slen1, sendbuf, 
01612             &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) )
01613             return -1;
01614 
01615         if (auth->password)
01616             rpauth->slen2= strlen(auth->password);
01617         else
01618             rpauth->slen2= 0;
01619 
01620         if ( sock_bufferize(auth->password, rpauth->slen2, sendbuf, 
01621             &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) )
01622             return -1;
01623 
01624         rpauth->slen1= htons (rpauth->slen1);
01625         rpauth->slen2= htons (rpauth->slen2);
01626     }
01627 
01628     if ( sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) )
01629         return -1;
01630 
01631     if ( sock_recv(sock, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
01632         return -1;
01633 
01634     retval= rpcap_checkmsg(errbuf, sock, &header, RPCAP_MSG_AUTH_REPLY, RPCAP_MSG_ERROR, 0);
01635 
01636     if (retval != RPCAP_MSG_AUTH_REPLY)     // the message is not the one expected
01637     {
01638         switch (retval)
01639         {
01640             case -3:        // Unrecoverable network error
01641             case -2:        // The other endpoint sent a message that is not allowed here
01642             case -1:    // The other endpoint has a version number that is not compatible with our
01643                 // Do nothing; just exit from here; the error code is already into the errbuf
01644                 return -1;
01645 
01646             case RPCAP_MSG_ERROR:
01647             {
01648                 return -1;
01649             };
01650 
01651             default:
01652             {
01653                 SOCK_ASSERT("Internal error", 0);
01654                 return -1;
01655             };
01656         }
01657     }
01658 
01659     if (ntohl(header.plen) )
01660     {
01661         if (sock_discard(sock, ntohl(header.plen), errbuf, PCAP_ERRBUF_SIZE) )
01662             return -1;
01663     }
01664     
01665     return 0;
01666 }
01667 
01668 
01669 
01691 void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length)
01692 {
01693     memset(header, 0, sizeof (struct rpcap_header) );
01694 
01695     header->ver= RPCAP_VERSION;
01696     header->type= type;
01697     header->value= htons(value);
01698     header->plen= htonl(length);
01699 }
01700 
01701 
01702 
01746 int rpcap_checkmsg(char *errbuf, SOCKET sock, struct rpcap_header *header, uint8 first, ...)
01747 {
01748 va_list ap;
01749 uint8 type;
01750 int32 len;
01751 
01752     va_start(ap, first);
01753 
01754     // Check if the present version of the protocol can handle this message
01755     if ( rpcap_checkver(sock, header, errbuf) )
01756     {
01757         SOCK_ASSERT(errbuf, 1);
01758 
01759         va_end(ap);
01760         return -1;
01761     }
01762 
01763     type= first;
01764 
01765     while ( type != 0 )
01766     {
01767         // The message matches with one of the types listed
01768         // There is no need of conversions since both values are uint8
01769 
01770         // Check if the other side reported an error.
01771         // If yes, it retrieves it and it returns it back to the caller
01772         if (header->type == RPCAP_MSG_ERROR)
01773         {
01774             len= ntohl(header->plen);
01775 
01776             if (len >= PCAP_ERRBUF_SIZE)
01777             {
01778                 if (sock_recv(sock, errbuf, PCAP_ERRBUF_SIZE - 1, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) )
01779                     return -3;
01780 
01781                 sock_discard(sock, len - (PCAP_ERRBUF_SIZE - 1), fakeerrbuf, PCAP_ERRBUF_SIZE);
01782 
01783                 // Put '\0' at the end of the string
01784                 errbuf[PCAP_ERRBUF_SIZE - 1]= 0;
01785             }
01786             else
01787             {
01788                 if (sock_recv(sock, errbuf, len, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
01789                     return -3;
01790 
01791                 // Put '\0' at the end of the string
01792                 errbuf[len]= 0;
01793             }
01794 
01795 
01796             va_end(ap);
01797             return header->type;
01798         }
01799 
01800         if (header->type == type)
01801         {
01802             va_end(ap);
01803             return header->type;
01804         }
01805         
01806         // get next argument
01807         type= va_arg(ap, int);
01808     }
01809 
01810     // we already have an error, so please discard this one
01811     sock_discard(sock, ntohl(header->plen), fakeerrbuf, PCAP_ERRBUF_SIZE);
01812 
01813     snprintf(errbuf, PCAP_ERRBUF_SIZE, "The other endpoint sent a message that is not allowed here.");
01814     SOCK_ASSERT(errbuf, 1);
01815 
01816     va_end(ap);
01817     return -2;
01818 }
01819 
01820 
01821 
01845 int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf)
01846 {
01847     /*
01848     This is a sample function.
01849 
01850     In the real world, you have to check at the type code, 
01851     and decide accordingly.
01852     */
01853 
01854     if (header->ver != RPCAP_VERSION)
01855     {
01856         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Incompatible version number: message discarded.");
01857 
01858         // we already have an error, so please discard this one
01859         sock_discard(sock, ntohl(header->plen), fakeerrbuf, PCAP_ERRBUF_SIZE);
01860         return -1;
01861     }
01862 
01863     return 0;
01864 }
01865 
01866 
01867 
01888 int rpcap_remoteact_getsock(const char *host, char *errbuf)
01889 {
01890 struct activehosts *temp;                   // temp var needed to scan the host list chain
01891 struct addrinfo hints, *addrinfo, *ai_next; // temp var needed to translate between hostname to its address
01892 int retval;
01893 
01894     // retrieve the network address corresponding to 'host'
01895     addrinfo = NULL;
01896     memset(&hints, 0, sizeof (struct addrinfo) );
01897     hints.ai_family = PF_UNSPEC;
01898     hints.ai_socktype= SOCK_STREAM;
01899 
01900     retval = getaddrinfo(host, "0", &hints, &addrinfo);
01901     if (retval != 0)
01902     {
01903         snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
01904         return -1;
01905     }
01906 
01907     temp= activeHosts;
01908 
01909     while (temp)
01910     {
01911         ai_next= addrinfo;
01912         while(ai_next)
01913         {
01914             if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr ) == 0)
01915                 return (temp->sockctrl );
01916 
01917             ai_next= ai_next->ai_next;
01918         }
01919         temp= temp->next;
01920     }
01921 
01922     if (addrinfo)
01923         freeaddrinfo(addrinfo);
01924 
01925     // The host you want to get the socket ID does not have an active connection
01926     return 0;
01927 }
01928 
01929 
01930 
01931 
01932 

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