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.