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         
00070 
00071 struct activehosts *activeHosts;
00072 
00073 
00074 /****************************************************
00075  *                                                  *
00076  * Locally defined functions                        *
00077  *                                                  *
00078  ****************************************************/
00079 int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf);
00080 struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode);
00081 int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog);
00082 int pcap_createfilter_norpcappkt(pcap_t *fp, struct bpf_program *prog);
00083 
00084 
00085 
00086 
00087 /****************************************************
00088  *                                                  *
00089  * Function bodies                                 *
00090  *                                                  *
00091  ****************************************************/
00092 
00126 int rpcap_deseraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf)
00127 {
00128     // Warning: we support only AF_INET and AF_INET6
00129     if ( ntohs(sockaddrin->ss_family) == AF_INET)
00130     {
00131     struct sockaddr_in *sockaddr;
00132     
00133         sockaddr= (struct sockaddr_in *) sockaddrin;
00134         sockaddr->sin_family= ntohs(sockaddr->sin_family);
00135         sockaddr->sin_port= ntohs(sockaddr->sin_port);
00136 
00137         (*sockaddrout)= (struct sockaddr_storage *) malloc ( sizeof(struct sockaddr_in) );
00138         if ( (*sockaddrout) == NULL)
00139         {
00140             snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00141             return -1;
00142         }
00143         memcpy( *sockaddrout, sockaddr, sizeof(struct sockaddr_in) );
00144         return 0;
00145     }
00146     if ( ntohs(sockaddrin->ss_family) == AF_INET6)
00147     {
00148     struct sockaddr_in6 *sockaddr;
00149     
00150         sockaddr= (struct sockaddr_in6 *) sockaddrin;
00151         sockaddr->sin6_family= ntohs(sockaddr->sin6_family);
00152         sockaddr->sin6_port= ntohs(sockaddr->sin6_port);
00153         sockaddr->sin6_flowinfo= ntohl(sockaddr->sin6_flowinfo);
00154         sockaddr->sin6_scope_id= ntohl(sockaddr->sin6_scope_id);
00155 
00156         (*sockaddrout)= (struct sockaddr_storage *) malloc ( sizeof(struct sockaddr_in6) );
00157         if ( (*sockaddrout) == NULL)
00158         {
00159             snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00160             return -1;
00161         }
00162         memcpy( *sockaddrout, sockaddr, sizeof(struct sockaddr_in6) );
00163         return 0;
00164     }
00165 
00166     // It is neither AF_INET nor AF_INET6
00167     *sockaddrout= NULL;
00168     return 0;
00169 }
00170 
00171 
00172 
00196 int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr **pkt_header, u_char **pkt_data)
00197 {
00198 struct rpcap_header *header;            // general header according to the RPCAP format
00199 struct rpcap_pkthdr *net_pkt_header;    // header of the packet
00200 char netbuf[RPCAP_NETBUF_SIZE];         // size of the network buffer in which the packet is copied, just for UDP
00201 unsigned int nread;                     // number of bytes (of payload) currently read from the network (referred to the current pkt)
00202 int retval;                             // generic return value
00203 
00204 // Structures needed for the select() call
00205 fd_set rfds;                            // set of socket descriptors we have to check
00206 struct timeval tv;                      // maximum time the select() can block waiting for data
00207 
00208 
00209     // Define the read timeout, to be used in the select()
00210     // 'timeout', in pcap_t, is in milliseconds; we have to convert it into sec and microsec
00211 #ifdef linux
00212     tv.tv_sec = p->md.timeout/1000;
00213     tv.tv_usec = (p->md.timeout - tv.tv_sec * 1000 )* 1000;
00214 #else
00215     tv.tv_sec = p->timeout/1000;
00216     tv.tv_usec = (p->timeout - tv.tv_sec * 1000 )* 1000;
00217 #endif
00218 
00219     // Watch out sockdata to see if it has input
00220     FD_ZERO(&rfds);
00221 
00222     // 'fp->rmt_sockdata' has always to be set before calling the select(),
00223     // since it is cleared by the select()
00224     FD_SET(p->rmt_sockdata, &rfds);
00225 
00226     retval = select(p->rmt_sockdata + 1, &rfds, NULL, NULL, &tv);
00227     if (retval == -1)
00228     {
00229         sock_geterror("select(): ", p->errbuf, PCAP_ERRBUF_SIZE);
00230         return -1;
00231     }
00232 
00233     // There is no data waiting, so return '0'
00234     if (retval == 0)
00235         return 0;
00236 
00237     // data is here; so, let's copy it into the user buffer
00238     // I'm going to read a new packet; so I reset the number of bytes (payload only) read
00239     nread= 0;
00240 
00241     // We have to define 'header' as a pointer to a larger buffer, 
00242     // because in case of UDP we have to read all the message within a single call
00243     header= (struct rpcap_header *) netbuf;
00244     net_pkt_header= (struct rpcap_pkthdr *) (netbuf + sizeof(struct rpcap_header) );
00245 
00246     if (p->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
00247     {
00248         // Read the entire message from the network
00249         if (sock_recv(p->rmt_sockdata, netbuf, RPCAP_NETBUF_SIZE, SOCK_RECEIVEALL_NO, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
00250             return -1;
00251     }
00252     else
00253     {
00254         if (sock_recv(p->rmt_sockdata, netbuf, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
00255             return -1;
00256     }
00257 
00258     // Checks if the message is correct
00259     retval= rpcap_checkmsg(p->errbuf, p->rmt_sockdata, header, RPCAP_MSG_PACKET, 0);
00260 
00261     if (retval != RPCAP_MSG_PACKET)     // the message is not the one expected
00262     {
00263         switch (retval)
00264         {
00265             case -3:        // Unrecoverable network error                                  
00266                 return -1;  // Do nothing; just exit from here; the error code is already into the errbuf
00267 
00268             case -2:        // The other endpoint sent a message that is not allowed here
00269             case -1:        // The other endpoint has a version number that is not compatible with our
00270                 return 0;   // Return 'no packets received'
00271 
00272             default:
00273             {
00274                 SOCK_ASSERT("Internal error", 1);
00275                 return 0;   // Return 'no packets received
00276             };
00277         }
00278     }
00279     
00280     // In case of TCP, read the remaining of the packet from the socket
00281     if ( !(p->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
00282     {
00283         // Read the RPCAP packet header from the network
00284         if ( (nread= sock_recv(p->rmt_sockdata, (char *) net_pkt_header, 
00285                     sizeof(struct rpcap_pkthdr), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE)) == -1)
00286             return -1;
00287     }
00288 
00289     if ( (ntohl(net_pkt_header->caplen) + sizeof(struct pcap_pkthdr) ) <= ( (unsigned) p->bufsize) )
00290     {
00291         // Initialize returned structures
00292         *pkt_header= (struct pcap_pkthdr *) p->buffer;
00293         *pkt_data= p->buffer + sizeof(struct pcap_pkthdr);
00294 
00295         (*pkt_header)->caplen= ntohl(net_pkt_header->caplen);
00296         (*pkt_header)->len= ntohl(net_pkt_header->len);
00297         (*pkt_header)->ts.tv_sec= ntohl(net_pkt_header->timestamp_sec);
00298         (*pkt_header)->ts.tv_usec= ntohl(net_pkt_header->timestamp_usec);
00299 
00300         // I don't update the counter of the packets dropped by the network since we're using TCP;
00301         // therefore no packets are dropped. Just update the number of packets received correctly
00302         p->md.TotCapt++;
00303 
00304         // Copies the packet into the data buffer
00305         if (p->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
00306         {
00307         unsigned int npkt;
00308 
00309             // In case of UDP the packet has already been read; we have to copy it into 'buffer'
00310             // Another option should bne to declare 'netbuf' as 'static'; however this prevents
00311             // using several pcap instances within the same process (because the static buffer is shared among
00312             // all processes)
00313             memcpy(*pkt_data, netbuf + sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr), (*pkt_header)->caplen);
00314 
00315             // We're using UDP, so we need to update the counter of the packets dropped by the network
00316             npkt= ntohl(net_pkt_header->npkt);
00317 
00318             if (p->md.TotCapt != npkt)
00319             {
00320                 p->md.TotNetDrops+= (npkt - p->md.TotCapt);
00321                 p->md.TotCapt= npkt;
00322             }
00323 
00324         }
00325         else
00326         {
00327             // In case of TCP, read the remaining of the packet from the socket
00328             if ( (nread+= sock_recv(p->rmt_sockdata, *pkt_data, (*pkt_header)->caplen, SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE)) == -1)
00329                 return -1;
00330 
00331             // Checks if all the data has been read; if not, discard the data in excess
00332             // This check has to be done only on TCP connections
00333             if (nread != ntohl(header->plen))
00334                 sock_discard(p->rmt_sockdata, ntohl(header->plen) - nread, NULL, 0);
00335         }
00336 
00337 
00338         // Packet read successfully
00339         return 1;
00340     }
00341     else
00342     {
00343         snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Received a packet that is larger than the internal buffer size.");
00344         return -1;
00345     }
00346 
00347 }
00348 
00349 
00364 int pcap_read_remote(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
00365 {
00366 struct pcap_pkthdr *pkt_header;
00367 u_char *pkt_data;
00368 int n = 0;
00369 
00370     while ( (++n <= cnt) || (cnt < 0) )
00371     {
00372         if (pcap_read_nocb_remote(p, &pkt_header, &pkt_data) == 1)
00373             (*callback)(user, pkt_header, pkt_data);
00374         else
00375             return n;
00376     }
00377     return n;
00378 }
00379 
00380 
00394 void pcap_close_remote(pcap_t *fp)
00395 {
00396 struct rpcap_header header;     // header of the RPCAP packet
00397 struct activehosts *temp;       // temp var needed to scan the host list chain, to detect if we're in active mode
00398 int active= 0;                  // active mode or not?
00399 
00400     // detect if we're in active mode
00401     temp= activeHosts;
00402     while (temp)
00403     {
00404         if (temp->sockctrl == fp->rmt_sockctrl)
00405         {
00406             active= 1;
00407             break;
00408         }
00409         temp= temp->next;
00410     }
00411 
00412     if (!active)
00413     {
00414         rpcap_createhdr( &header, RPCAP_MSG_CLOSE, 0, 0);
00415 
00416         // I don't check for errors, since I'm going to close everything
00417         sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), NULL, 0);
00418     }
00419     else
00420     {
00421         rpcap_createhdr( &header, RPCAP_MSG_ENDCAP_REQ, 0, 0);
00422 
00423         // I don't check for errors, since I'm going to close everything
00424         sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), NULL, 0);
00425 
00426         // wait for the answer
00427         // Don't check what we got, since the present libpcap does not uses this pcap_t anymore
00428         sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, NULL, 0);
00429 
00430         if ( ntohl(header.plen) != 0)
00431             sock_discard(fp->rmt_sockctrl, ntohl(header.plen), NULL, 0);
00432     }
00433 
00434     if (fp->rmt_sockdata)
00435     {
00436         sock_close(fp->rmt_sockdata, NULL, 0);
00437         fp->rmt_sockdata= 0;
00438     }
00439 
00440     if ( (!active) && (fp->rmt_sockctrl) )
00441         sock_close(fp->rmt_sockctrl, NULL, 0);
00442 
00443     fp->rmt_sockctrl= 0;
00444 
00445     if (fp->currentfilter)
00446     {
00447         free(fp->currentfilter);
00448         fp->currentfilter= NULL;
00449     }
00450 
00451     // To avoid inconsistencies in the number of sock_init()
00452     sock_cleanup();
00453 }
00454 
00455 
00456 
00466 int pcap_stats_remote(pcap_t *p, struct pcap_stat *ps)
00467 {
00468 struct pcap_stat *retval;
00469 
00470     retval= rpcap_stats_remote(p, ps, PCAP_STATS_STANDARD);
00471 
00472     if (retval)
00473         return 0;
00474     else
00475         return -1;
00476 }
00477 
00478 
00479 
00489 struct pcap_stat *pcap_stats_ex_remote(pcap_t *p)
00490 {
00491     // '0' (third param) means 'standard pcap_stats()'
00492     return (rpcap_stats_remote(p, &(p->md.stat), PCAP_STATS_EX));
00493 }
00494 
00495 
00496 
00527 struct pcap_stat *rpcap_stats_remote(pcap_t *p, struct pcap_stat *ps, int mode)
00528 {
00529 struct rpcap_header header;         // header of the RPCAP packet
00530 struct rpcap_stats netstats;        // statistics sent on the network
00531 unsigned int nread= 0;              // number of bytes of the payload read from the socket
00532 int retval;                         // temp variable which stores functions return value
00533 
00534     // If the capture has still to start, we cannot ask statistics to the other peer
00535     // So, we return a fake number
00536     if (!p->rmt_capstarted) 
00537     {
00538         if (mode == PCAP_STATS_STANDARD)
00539         {
00540             ps->ps_drop= 0;
00541             ps->ps_ifdrop= 0;
00542             ps->ps_recv= 0;
00543         }
00544         else
00545         {
00546             ps->ps_capt= 0;
00547             ps->ps_drop= 0;
00548             ps->ps_ifdrop= 0;
00549             ps->ps_netdrop= 0;
00550             ps->ps_recv= 0;
00551             ps->ps_sent= 0;
00552         }
00553 
00554         return ps;
00555     }
00556 
00557     rpcap_createhdr(&header, RPCAP_MSG_STATS_REQ, 0, 0);
00558 
00559     // Send the PCAP_STATS command
00560     if (sock_send(p->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), p->errbuf, PCAP_ERRBUF_SIZE) )
00561         goto error;
00562 
00563     // Receive the RPCAP stats reply message
00564     if (sock_recv(p->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
00565         goto error;
00566 
00567     // Checks if the message is correct
00568     retval= rpcap_checkmsg(p->errbuf, p->rmt_sockctrl, &header, RPCAP_MSG_STATS_REPLY, RPCAP_MSG_ERROR, 0);
00569 
00570     if (retval != RPCAP_MSG_STATS_REPLY)        // the message is not the one expected
00571     {
00572         switch (retval)
00573         {
00574             case -3:        // Unrecoverable network error
00575             case -2:        // The other endpoint send a message that is not allowed here
00576             case -1:    // The other endpoint has a version number that is not compatible with our
00577                 goto error;
00578 
00579             case RPCAP_MSG_ERROR:       // The other endpoint reported an error
00580                 // Update nread, since the rpcap_checkmsg() already purged the buffer
00581                 nread = ntohl(header.plen);
00582 
00583                 // Do nothing; just exit; the error code is already into the errbuf
00584                 goto error;
00585 
00586             default:
00587             {
00588                 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
00589                 goto error;
00590             };
00591         }
00592     }
00593 
00594     if ( (nread= sock_recv(p->rmt_sockctrl, (char *) &netstats, sizeof(struct rpcap_stats), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE)) == -1)
00595         goto error;
00596 
00597     if (mode == PCAP_STATS_STANDARD)
00598     {
00599         ps->ps_drop= ntohl(netstats.krnldrop);
00600         ps->ps_ifdrop= ntohl(netstats.ifdrop);
00601         ps->ps_recv= ntohl(netstats.ifrecv);
00602     }
00603     else
00604     {
00605         ps->ps_capt= p->md.TotCapt;
00606         ps->ps_drop= ntohl(netstats.krnldrop);
00607         ps->ps_ifdrop= ntohl(netstats.ifdrop);
00608         ps->ps_netdrop= p->md.TotNetDrops;
00609         ps->ps_recv= ntohl(netstats.ifrecv);
00610         ps->ps_sent= ntohl(netstats.svrcapt);
00611     }
00612 
00613     // Checks if all the data has been read; if not, discard the data in excess
00614     if (nread != ntohl(header.plen))
00615     {
00616         if (sock_discard(p->rmt_sockctrl, ntohl(header.plen) - nread, NULL, 0) == 1)
00617             goto error;
00618     }
00619 
00620     return ps;
00621 
00622 error:
00623     if (nread != ntohl(header.plen))
00624         sock_discard(p->rmt_sockctrl, ntohl(header.plen) - nread, NULL, 0);
00625 
00626     return NULL;
00627 }
00628 
00629 
00630 
00631 
00670 pcap_t *pcap_opensource_remote(const char *source, struct pcap_rmtauth *auth, char *errbuf)
00671 {
00672 char host[PCAP_BUF_SIZE], ctrlport[PCAP_BUF_SIZE], iface[PCAP_BUF_SIZE];
00673 
00674 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered
00675 int sendbufidx= 0;              // index which keeps the number of bytes currently buffered
00676 struct pcap *fp= NULL;          // pcap_t main variable
00677 unsigned int nread= 0;          // number of bytes of the payload read from the socket
00678 int retval;                     // store the return value of the functions
00679 int active= 0;                      // '1' if we're in active mode
00680 
00681 // socket-related variables
00682 struct addrinfo hints;          // temp, needed to open a socket connection
00683 struct addrinfo *addrinfo;      // temp, needed to open a socket connection
00684 SOCKET sockctrl= 0;             // socket descriptor of the control connection
00685 
00686 // RPCAP-related variables
00687 struct rpcap_header header;         // header of the RPCAP packet
00688 struct rpcap_openreply openreply;   // open reply message
00689 
00690 
00691     // determine the type of the source (NULL, file, local, remote)
00692     // You must have a valid source string even if we're in active mode, because otherwise
00693     // the call to the following funciton will fail.
00694     if (pcap_parsesrcstr(source, &retval, host, ctrlport, iface, errbuf) == -1)
00695         return NULL;
00696 
00697     if ( retval != PCAP_SRC_IFREMOTE)
00698     {
00699         snprintf(errbuf, PCAP_ERRBUF_SIZE, "This function is able to open only remote interfaces");
00700         return NULL;
00701     }
00702 
00703     addrinfo= NULL;
00704 
00705     // Warning: this call can be the first one called by the user.
00706     // For this reason, we have to initialize the WinSock support.
00707     if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
00708         return NULL;
00709 
00710     retval= rpcap_remoteact_getsock(host, errbuf);
00711 
00712     if (retval == -1)
00713         return NULL;
00714 
00715     // The capturing machine is in active mode
00716     if (retval)
00717     {
00718         sockctrl= retval;
00719         active= 1;
00720     }
00721     else
00722     {
00723         memset(&hints, 0, sizeof(struct addrinfo) );
00724         hints.ai_family = PF_UNSPEC;
00725         hints.ai_socktype = SOCK_STREAM;
00726 
00727         if ( (ctrlport == NULL) || (ctrlport[0] == 0) )
00728         {
00729             // the user chose not to specify the port
00730             if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
00731                 return NULL;
00732         }
00733         else
00734         {
00735             // the user chose not to specify the port
00736             if (sock_initaddress(host, ctrlport, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
00737                 return NULL;
00738         }
00739 
00740         if ( (sockctrl= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1)
00741             goto error;
00742 
00743         freeaddrinfo(addrinfo);
00744         addrinfo= NULL;
00745 
00746         if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1)
00747             goto error;
00748     }
00749 
00750 
00751     // Now it's time to start playing with the RPCAP protocol
00752     // RPCAP open command: create the request message
00753     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 
00754         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) )
00755         goto error;
00756 
00757     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_OPEN_REQ, 0, strlen(iface) );
00758 
00759     if ( sock_bufferize(iface, strlen(iface), sendbuf, &sendbufidx, 
00760         RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) )
00761         goto error;
00762 
00763     if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) )
00764         goto error;
00765 
00766     // Receive the RPCAP open reply message
00767     if (sock_recv(sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
00768         goto error;
00769 
00770     // Checks if the message is correct
00771     retval= rpcap_checkmsg(errbuf, sockctrl, &header, RPCAP_MSG_OPEN_REPLY, RPCAP_MSG_ERROR, 0);
00772 
00773     if (retval != RPCAP_MSG_OPEN_REPLY)     // the message is not the one expected
00774     {
00775         switch (retval)
00776         {
00777             case -3:        // Unrecoverable network error
00778             case -2:        // The other endpoint send a message that is not allowed here
00779             case -1:    // The other endpoint has a version number that is not compatible with our
00780                 goto error;
00781 
00782             case RPCAP_MSG_ERROR:       // The other endpoint reported an error
00783                 // Update nread, since the rpcap_checkmsg() already purged the buffer
00784                 nread = ntohl(header.plen);
00785                 // Do nothing; just exit; the error code is already into the errbuf
00786                 goto error;
00787 
00788             default:
00789             {
00790                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Internal error");
00791                 goto error;
00792             };
00793         }
00794     }
00795 
00796 
00797     if ( (nread+= sock_recv(sockctrl, (char *) &openreply, sizeof(struct rpcap_openreply), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
00798         goto error;
00799 
00800     // Allocates a pcap_t struct for this end of the connection
00801     fp = (pcap_t *) malloc( sizeof(pcap_t) );
00802     if (fp == NULL)
00803     {
00804         snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00805         goto error;
00806     }
00807 
00808     memset(fp, 0, sizeof(pcap_t));
00809 
00810     // Set proper fields into the pcap_t struct
00811     fp->linktype= ntohl(openreply.linktype);
00812     fp->tzoff= ntohl(openreply.tzoff);
00813     fp->rmt_sockctrl= sockctrl;
00814     fp->rmt_clientside= 1;
00815 
00816 
00817     // This code is duplicated from the end of this function
00818     fp->read_op= pcap_read_remote;
00819     fp->setfilter_op= pcap_setfilter_remote;
00820     fp->getnonblock_op= NULL;                   // This is not implemented in remote capture
00821     fp->setnonblock_op= NULL;   // This is not implemented in remote capture
00822     fp->stats_op= pcap_stats_remote;
00823     fp->close_op= pcap_close_remote;
00824 
00825     // Checks if all the data has been read; if not, discard the data in excess
00826     if (nread != ntohl(header.plen))
00827     {
00828         if (sock_discard(sockctrl, ntohl(header.plen) - nread, NULL, 0) == 1)
00829             goto error;
00830     }
00831     return fp;
00832 
00833 error:
00834 // When the connection has been established, we have to close it. So, at the
00835 // beginning of this function, if an error occur we return immediately with
00836 // a return NULL; when the connection is established, we have to come here 
00837 // ('goto error;') in order to close everything properly.
00838 
00839     // Checks if all the data has been read; if not, discard the data in excess
00840     if (nread != ntohl(header.plen))
00841         sock_discard(sockctrl, ntohl(header.plen) - nread, NULL, 0);
00842 
00843     if (addrinfo)
00844         freeaddrinfo(addrinfo);
00845 
00846     if (!active)
00847         sock_close(sockctrl, NULL, 0);
00848 
00849     if (fp)
00850     {
00851         pcap_close(fp);
00852         fp= NULL;
00853     }
00854 
00855     return NULL;
00856 }
00857 
00858 
00859 
00860 
00861 
00862 
00863 
00886 int pcap_startcapture_remote(pcap_t *fp)
00887 {
00888 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered
00889 int sendbufidx= 0;              // index which keeps the number of bytes currently buffered
00890 char portdata[PCAP_BUF_SIZE];   // temp variable needed to keep the network port for the the data connection
00891 unsigned int nread= 0;          // number of bytes of the payload read from the socket
00892 int retval;                     // store the return value of the functions
00893 int active= 0;                  // '1' if we're in active mode
00894 struct activehosts *temp;       // temp var needed to scan the host list chain, to detect if we're in active mode
00895 char host[INET6_ADDRSTRLEN + 1];    // numeric name of the other host
00896 
00897 // socket-related variables
00898 struct addrinfo hints;          // temp, needed to open a socket connection
00899 struct addrinfo *addrinfo;      // temp, needed to open a socket connection
00900 SOCKET sockdata= 0;             // socket descriptor of the data connection
00901 struct sockaddr_storage saddr;  // temp, needed to retrieve the network data port chosen on the local machine
00902 socklen_t saddrlen;             // temp, needed to retrieve the network data port chosen on the local machine
00903 int ai_family;                  // temp, keeps the address family used by the control connection
00904 
00905 // RPCAP-related variables
00906 struct rpcap_header header;                 // header of the RPCAP packet
00907 struct rpcap_startcapreq *startcapreq;      // start capture request message
00908 struct rpcap_startcapreply startcapreply;   // start capture reply message
00909 
00910 // Variables related to the buffer setting
00911 int res, itemp;
00912 int sockbufsize= 0;
00913 
00914 
00915     // Let's check if sampling has been required.
00916     // If so, let's set it first
00917     if (pcap_setsampling_remote(fp) != 0)
00918         return -1;
00919 
00920 
00921     // detect if we're in active mode
00922     temp= activeHosts;
00923     while (temp)
00924     {
00925         if (temp->sockctrl == fp->rmt_sockctrl)
00926         {
00927             active= 1;
00928             break;
00929         }
00930         temp= temp->next;
00931     }
00932 
00933     addrinfo= NULL;
00934 
00935     // Gets the complete sockaddr structure used in the ctrl connection
00936     // This is needed to get the address family of the control socket
00937     // Tip: I cannot save the ai_family of the ctrl sock in the pcap_t struct,
00938     // since the ctrl socket can already be open in case of active mode;
00939     // so I would have to call getpeername() anyway
00940     saddrlen = sizeof(struct sockaddr_storage);
00941     if (getpeername(fp->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
00942     {
00943         sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
00944         goto error;
00945     }
00946     ai_family= ((struct sockaddr_storage *) &saddr)->ss_family;
00947 
00948     // Get the numeric address of the remote host we are connected to
00949     if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, host, 
00950             sizeof(host), NULL, 0, NI_NUMERICHOST) )
00951     {
00952         sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
00953         goto error;
00954     }
00955 
00956     /*
00957         Data connection is opened by the server toward the client if:
00958         - we're using TCP, and the user wants us to be in active mode
00959         - we're using UDP
00960     */
00961     if ( (active) || (fp->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) )
00962     {
00963         // We have to create a new socket to receive packets
00964         // We have to do that immediately, since we have to tell the other 
00965         // end which network port we picked up
00966         memset(&hints, 0, sizeof(struct addrinfo) );
00967         // TEMP addrinfo is NULL in case of active
00968         hints.ai_family = ai_family;    // Use the same address family of the control socket
00969         hints.ai_socktype = (fp->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ? SOCK_DGRAM : SOCK_STREAM;
00970         hints.ai_flags = AI_PASSIVE;    // Data connection is opened by the server toward the client
00971 
00972         // Let's the server pick up a free network port for us
00973         if (sock_initaddress(NULL, "0", &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
00974             goto error;
00975 
00976         if ( (sockdata= sock_open(addrinfo, SOCKOPEN_SERVER, 
00977             1 /* max 1 connection in queue */, fp->errbuf, PCAP_ERRBUF_SIZE)) == -1)
00978             goto error;
00979 
00980         // addrinfo is no longer used
00981         freeaddrinfo(addrinfo);
00982         addrinfo= NULL;
00983 
00984         // get the complete sockaddr structure used in the data connection
00985         saddrlen = sizeof(struct sockaddr_storage);
00986         if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
00987         {
00988             sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
00989             goto error;
00990         }
00991 
00992         // Get the local port the system picked up
00993         if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, NULL, 
00994                 0, portdata, sizeof(portdata), NI_NUMERICSERV) )
00995         {
00996             sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
00997             goto error;
00998         }
00999     }
01000 
01001     // Now it's time to start playing with the RPCAP protocol
01002     // RPCAP start ca[ture command: create the request message
01003     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 
01004         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) )
01005         goto error;
01006 
01007     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STARTCAP_REQ, 0,
01008         sizeof(struct rpcap_startcapreq) + sizeof(struct rpcap_filter) + fp->fcode.bf_len * sizeof(struct rpcap_filterbpf_insn) );
01009 
01010     // Fill the structure needed to open an adapter remotely
01011     startcapreq= (struct rpcap_startcapreq *) &sendbuf[sendbufidx];
01012 
01013     if ( sock_bufferize(NULL, sizeof(struct rpcap_startcapreq), NULL, 
01014         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) )
01015         goto error;
01016 
01017     memset(startcapreq, 0, sizeof(struct rpcap_startcapreq) );
01018 
01019     // By default, apply half the timeout on one side, half of the other
01020 #ifdef linux
01021     fp->md.timeout= fp->md.timeout/2;
01022     startcapreq->read_timeout= htonl(fp->md.timeout);
01023 #else
01024     fp->timeout= fp->timeout/2;
01025     startcapreq->read_timeout= htonl(fp->timeout);
01026 #endif
01027 
01028     // portdata on the openreq is meaningful only if we're in active mode
01029     if ( (active) || (fp->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) )
01030     {
01031         sscanf(portdata, "%d", (int *) &(startcapreq->portdata));   // cast to avoid a compiler warning
01032         startcapreq->portdata= htons(startcapreq->portdata);
01033     }
01034 
01035     startcapreq->snaplen= htonl(fp->snapshot);
01036     startcapreq->flags= 0;
01037 
01038     if (fp->rmt_flags & PCAP_OPENFLAG_PROMISCUOUS)
01039         startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_PROMISC;
01040     if (fp->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
01041         startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_DGRAM;
01042     if (active)
01043         startcapreq->flags|= RPCAP_STARTCAPREQ_FLAG_SERVEROPEN;
01044 
01045     startcapreq->flags= htons(startcapreq->flags);
01046 
01047     // Pack the capture filter
01048     if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, &fp->fcode) )
01049         goto error;
01050 
01051     if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) )
01052         goto error;
01053 
01054 
01055     // Receive the RPCAP start capture reply message
01056     if (sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
01057         goto error;
01058 
01059     // Checks if the message is correct
01060     retval= rpcap_checkmsg(fp->errbuf, fp->rmt_sockctrl, &header, RPCAP_MSG_STARTCAP_REPLY, RPCAP_MSG_ERROR, 0);
01061 
01062     if (retval != RPCAP_MSG_STARTCAP_REPLY)     // the message is not the one expected
01063     {
01064         switch (retval)
01065         {
01066             case -3:        // Unrecoverable network error
01067             case -2:        // The other endpoint send a message that is not allowed here
01068             case -1:    // The other endpoint has a version number that is not compatible with our
01069                 goto error;
01070 
01071             case RPCAP_MSG_ERROR:       // The other endpoint reported an error
01072                 // Update nread, since the rpcap_checkmsg() already purged the buffer
01073                 nread = ntohl(header.plen);
01074                 // Do nothing; just exit; the error code is already into the errbuf
01075                 goto error;
01076 
01077             default:
01078             {
01079                 snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "Internal error");
01080                 goto error;
01081             };
01082         }
01083     }
01084 
01085 
01086     if ( (nread+= sock_recv(fp->rmt_sockctrl, (char *) &startcapreply, 
01087         sizeof(struct rpcap_startcapreply), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE)) == -1)
01088         goto error;
01089 
01090     // In case of UDP data stream, the connection is always opened by the daemon
01091     // So, this case is already covered by the code above.
01092     // Now, we have still to handle TCP connections, because:
01093     // - if we're in active mode, we have to wait for a remote connection
01094     // - if we're in passive more, we have to start a connection
01095     //
01096     // We have to do he job in two steps because in case we're opening a tcp connection, we have
01097     // to tell the port we're using to the remote side; in case we're accepting a TCP
01098     // connection, we have to wait this info from the remote side.
01099 
01100     if (!(fp->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
01101     {
01102         if (!active)
01103         {
01104             memset(&hints, 0, sizeof(struct addrinfo) );
01105             hints.ai_family = ai_family;        // Use the same address family of the control socket
01106             hints.ai_socktype = (fp->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ? SOCK_DGRAM : SOCK_STREAM;
01107 
01108             sprintf(portdata, "%d", ntohs(startcapreply.portdata) );
01109 
01110             // Let's the server pick up a free network port for us
01111             if (sock_initaddress(host, portdata, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
01112                 goto error;
01113 
01114             if ( (sockdata= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf, PCAP_ERRBUF_SIZE)) == -1)
01115                 goto error;
01116 
01117             // addrinfo is no longer used
01118             freeaddrinfo(addrinfo);
01119             addrinfo= NULL;
01120         }
01121         else
01122         {
01123         SOCKET socktemp;    // We need another socket, since we're going to accept() a connection
01124 
01125             // Connection creation
01126             saddrlen = sizeof(struct sockaddr_storage);
01127 
01128             socktemp= accept(sockdata, (struct sockaddr *) &saddr, &saddrlen);
01129             
01130             if (socktemp == -1)
01131             {
01132                 sock_geterror("accept(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
01133                 goto error;
01134             }
01135 
01136             // Now that I accepted the connection, the server socket is no longer needed
01137             sock_close(sockdata, fp->errbuf, PCAP_ERRBUF_SIZE);
01138             sockdata= socktemp;
01139         }
01140     }
01141 
01142     // Let's save the socket of the data connection
01143     fp->rmt_sockdata= sockdata;
01144 
01145     // Allocates WinPcap/libpcap user buffer, which is a socket buffer in case of a remote capture
01146     // It has the same size of the one used on the other side of the connection
01147     fp->bufsize= ntohl(startcapreply.bufsize);
01148 
01149     // Let's get the actual size of the socket buffer
01150     itemp= sizeof(sockbufsize);
01151 
01152     res= getsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *) &sockbufsize, &itemp);
01153     if (res == -1)
01154     {
01155         sock_geterror("pcap_startcapture_remote()", fp->errbuf, PCAP_ERRBUF_SIZE);
01156         SOCK_ASSERT(fp->errbuf, 1);
01157     }
01158 
01159     /*
01160         Warning: on some kernels (e.g. linux), the size of the user buffer does not take
01161         into account the pcap_header and such, and it is set equal to the snaplen.
01162         In my view, this is wrong (the meaning of the bufsize becames a bit strange).
01163         So, here bufsize is the whole size of the user buffer.
01164         In case the bufsize returned is too small, let's adjust it accordingly.
01165     */
01166     if (fp->bufsize <= fp->snapshot)
01167         fp->bufsize+= sizeof (struct pcap_pkthdr);
01168 
01169     // if the current socket buffer is smaller than the desired one
01170     if (sockbufsize < fp->bufsize)
01171     {
01172         // Loop until the buffer size is OK or the original socket buffer size is larger than this one
01173         while (1)
01174         {
01175             res= setsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *) &(fp->bufsize), sizeof(fp->bufsize) );
01176 
01177             if (res == 0)
01178                 break;
01179 
01180             // If something goes wrong, half the buffer size (checking that it does not become smaller than
01181             // the current one)
01182             fp->bufsize/= 2;
01183 
01184             if (sockbufsize >= fp->bufsize)
01185             {
01186                 fp->bufsize= sockbufsize;
01187                 break;
01188             }
01189         }
01190     }
01191 
01192     // Let's allocate the packet; this is required in order to put the packet somewhere when 
01193     // extracting data from the socket
01194     // Since buffering has already been done in the socket buffer, here we need just a buffer,
01195     // whose size is equal to the pcap header plus the snapshot length
01196     fp->bufsize= fp->snapshot + sizeof (struct pcap_pkthdr);
01197 
01198     fp->buffer = (u_char *) malloc(fp->bufsize);
01199     if (fp->buffer == NULL)
01200     {
01201         snprintf(fp->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno));
01202         goto error;
01203     }
01204 
01205 
01206     // Checks if all the data has been read; if not, discard the data in excess
01207     if (nread != ntohl(header.plen))
01208     {
01209         if (sock_discard(fp->rmt_sockctrl, ntohl(header.plen) - nread, NULL, 0) == 1)
01210             goto error;
01211     }
01212 
01213     // In case the user does not want to capture RPCAP packets, let's update the filter
01214     // We have to update it here (instead of sending it into the 'StartCapture' message
01215     // because when we generate the 'start capture' we do not know (yet) all the ports
01216     // we're currently using.
01217     if (fp->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP)
01218     {
01219     struct bpf_program fcode;
01220 
01221         if (pcap_createfilter_norpcappkt(fp, &fcode) == -1)
01222             goto error;
01223 
01224         // We cannot use 'pcap_setfilter_remote' because formally the capture has not been started yet
01225         // (the 'fp->rmt_capstarted' variable will be updated some lines below)
01226         if (pcap_updatefilter_remote(fp, &fcode) == -1)
01227             goto error;
01228 
01229         pcap_freecode(&fcode);
01230     }
01231 
01232     fp->rmt_capstarted= 1;
01233     return 0;
01234 
01235 error:
01236 // When the connection has been established, we have to close it. So, at the
01237 // beginning of this function, if an error occur we return immediately with
01238 // a return NULL; when the connection is established, we have to come here 
01239 // ('goto error;') in order to close everything properly.
01240 
01241     // Checks if all the data has been read; if not, discard the data in excess
01242     if (nread != ntohl(header.plen))
01243         sock_discard(fp->rmt_sockctrl, ntohl(header.plen) - nread, NULL, 0);
01244 
01245     if ((sockdata) && (sockdata != -1))     // we can be here because sockdata said 'error'
01246         sock_close(sockdata, NULL, 0);
01247 
01248     if (!active)
01249         sock_close(fp->rmt_sockctrl, NULL, 0);
01250 
01251     // We do not have to call pcap_close() here, because this function is always called 
01252     // by the user in case something bad happens
01253 //  if (fp)
01254 //  {
01255 //      pcap_close(fp);
01256 //      fp= NULL;
01257 //  }
01258 
01259     return -1;
01260 }
01261 
01262 
01263 
01264 
01265 
01289 int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog)
01290 {
01291 struct rpcap_filter *filter;
01292 struct rpcap_filterbpf_insn *insn;
01293 struct bpf_insn *bf_insn;
01294 struct bpf_program fake_prog;       // To be used just in case the user forgot to set a filter
01295 unsigned int i;
01296 
01297 
01298     if (prog->bf_len == 0)  // No filters have been specified; so, let's apply a "fake" filter
01299     {
01300         if (pcap_compile(fp, &fake_prog, NULL /*buffer*/, 1, 0) == -1)
01301             return -1;
01302 
01303         prog= &fake_prog;
01304     }
01305 
01306     filter= (struct rpcap_filter *) sendbuf;
01307 
01308     if ( sock_bufferize(NULL, sizeof(struct rpcap_filter), NULL, sendbufidx, 
01309         RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) )
01310         return -1;
01311 
01312     filter->filtertype= htons(RPCAP_UPDATEFILTER_BPF);
01313     filter->nitems= htonl( (int32) prog->bf_len);
01314 
01315     if ( sock_bufferize(NULL, prog->bf_len * sizeof(struct rpcap_filterbpf_insn), 
01316         NULL, sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) )
01317         return -1;
01318     
01319     insn= (struct rpcap_filterbpf_insn *) (filter + 1);
01320     bf_insn= prog->bf_insns;
01321 
01322     for (i= 0; i < prog->bf_len; i++)
01323     {
01324         insn->code= htons(bf_insn->code);
01325         insn->jf= bf_insn->jf;
01326         insn->jt= bf_insn->jt;
01327         insn->k= htonl(bf_insn->k);
01328 
01329         insn++;
01330         bf_insn++;
01331     }
01332 
01333     return 0;
01334 }
01335 
01336 
01337 
01338 
01339 
01359 int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog)
01360 {
01361 int retval;                     // general variable used to keep the return value of other functions
01362 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered
01363 int sendbufidx= 0;              // index which keeps the number of bytes currently buffered
01364 struct rpcap_header header;     // To keep the reply message
01365 
01366 
01367     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, 
01368         RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) )
01369         return -1;
01370 
01371     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_UPDATEFILTER_REQ, 0,
01372         sizeof(struct rpcap_filter) + prog->bf_len * sizeof(struct rpcap_filterbpf_insn));
01373 
01374     if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, prog) )
01375         return -1;
01376 
01377     if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) )
01378         return -1;
01379 
01380     // Waits for the answer
01381     if (sock_recv(fp->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
01382         return -1;
01383 
01384     // Checks if the message is correct
01385     retval= rpcap_checkmsg(fp->errbuf, fp->rmt_sockctrl, &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0);
01386 
01387     if (retval != RPCAP_MSG_UPDATEFILTER_REPLY)     // the message is not the one expected
01388     {
01389         switch (retval)
01390         {
01391             case -3:        // Unrecoverable network error
01392             case -2:        // The other endpoint sent a message that is not allowed here
01393             case -1:    // The other endpoint has a version number that is not compatible with our
01394                 // Do nothing; just exit from here; the error code is already into the errbuf
01395                 return -1;
01396 
01397             default:
01398             {
01399                 SOCK_ASSERT("Internal error", 0);
01400                 return -1;
01401             };
01402         }
01403     }
01404 
01405     if (ntohl(header.plen) != 0)    // the message has an unexpected size
01406     {
01407         if (sock_discard(fp->rmt_sockctrl, ntohl(header.plen), fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
01408             return -1;
01409     }
01410 
01411     return 0;
01412 }
01413 
01414 
01415 
01416 
01428 int pcap_setfilter_remote(pcap_t *fp, struct bpf_program *prog)
01429 {
01430     if (!fp->rmt_capstarted)
01431     {
01432         // copy filter into the pcap_t structure
01433         if (install_bpf_program(fp, prog) == -1)
01434             return -1;
01435         return 0;
01436     }
01437 
01438     // we have to update a filter during run-time
01439     if (pcap_updatefilter_remote(fp, prog) )
01440         return -1;
01441 
01442     return 0;
01443 }
01444 
01445 
01446 
01447 
01448 
01460 int pcap_createfilter_norpcappkt(pcap_t *fp, struct bpf_program *prog)
01461 {
01462 int RetVal= 0;
01463 
01464     // We do not want to capture our RPCAP traffic. So, let's update the filter
01465     if (fp->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP)
01466     {
01467     struct sockaddr_storage saddr;      // temp, needed to retrieve the network data port chosen on the local machine
01468     socklen_t saddrlen;                 // temp, needed to retrieve the network data port chosen on the local machine
01469     char myaddress[128];
01470     char myctrlport[128];
01471     char mydataport[128];
01472     char peeraddress[128];
01473     char peerctrlport[128];
01474     char *newfilter;
01475     const int newstringsize= 1024;
01476     int currentfiltersize;
01477 
01478         // Get the name/port of the other peer
01479         saddrlen = sizeof(struct sockaddr_storage);
01480         if (getpeername(fp->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
01481         {
01482             sock_geterror("getpeername(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
01483             return -1;
01484         }
01485 
01486         if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, peeraddress, 
01487                 sizeof(peeraddress), peerctrlport, sizeof(peerctrlport), NI_NUMERICHOST | NI_NUMERICSERV) )
01488         {
01489             sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
01490             return -1;
01491         }
01492 
01493         // We cannot check the data port, because this is available only in case of TCP sockets
01494 
01495         // Get the name/port of the current host
01496         if (getsockname(fp->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
01497         {
01498             sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
01499             return -1;
01500         }
01501 
01502         // Get the local port the system picked up
01503         if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, myaddress, 
01504                 sizeof(myaddress), myctrlport, sizeof(myctrlport), NI_NUMERICHOST | NI_NUMERICSERV) )
01505         {
01506             sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
01507             return -1;
01508         }
01509 
01510         // Let's now check the data port
01511         if (getsockname(fp->rmt_sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
01512         {
01513             sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
01514             return -1;
01515         }
01516 
01517         // Get the local port the system picked up
01518         if (getnameinfo( (struct sockaddr *) &saddr, saddrlen,NULL, 0, mydataport, sizeof(mydataport), NI_NUMERICSERV) )
01519         {
01520             sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
01521             return -1;
01522         }
01523 
01524         currentfiltersize= strlen(fp->currentfilter);
01525 
01526         newfilter= (char *) malloc (currentfiltersize + newstringsize + 1);
01527 
01528         if (currentfiltersize)
01529         {
01530             snprintf(newfilter, currentfiltersize + newstringsize, 
01531                 "(%s) and not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)", 
01532                 fp->currentfilter, myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
01533         }
01534         else
01535         {
01536             snprintf(newfilter, currentfiltersize + newstringsize, 
01537                 "not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)", 
01538                 myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
01539         }
01540 
01541         newfilter[currentfiltersize + newstringsize]= 0;
01542 
01543         // This is only an hack to make the pcap_compile() working properly
01544         fp->rmt_clientside= 0;
01545 
01546         if (pcap_compile(fp, prog, newfilter, 1, 0) == -1)
01547             RetVal= -1;
01548 
01549         // This is only an hack to make the pcap_compile() working properly
01550         fp->rmt_clientside= 1;
01551 
01552         free(newfilter);
01553     }
01554 
01555     return RetVal;
01556 }
01557 
01572 int pcap_setsampling_remote(pcap_t *p)
01573 {
01574 int retval;                     // general variable used to keep the return value of other functions
01575 char sendbuf[RPCAP_NETBUF_SIZE];// temporary buffer in which data to be sent is buffered
01576 int sendbufidx= 0;              // index which keeps the number of bytes currently buffered
01577 struct rpcap_header header;     // To keep the reply message
01578 struct rpcap_sampling *sampling_pars;   // Structure that is needed to send sampling parameters to the remote host
01579 
01580     // If no samping is requested, return 'ok'
01581     if (p->rmt_samp.method == PCAP_SAMP_NOSAMP)
01582         return 0;
01583 
01584     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 
01585         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, p->errbuf, PCAP_ERRBUF_SIZE) )
01586         return -1;
01587 
01588     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_SETSAMPLING_REQ, 0, sizeof(struct rpcap_sampling) );
01589 
01590     // Fill the structure needed to open an adapter remotely
01591     sampling_pars= (struct rpcap_sampling *) &sendbuf[sendbufidx];
01592 
01593     if ( sock_bufferize(NULL, sizeof(struct rpcap_sampling), NULL, 
01594         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, p->errbuf, PCAP_ERRBUF_SIZE) )
01595         return -1;
01596 
01597     memset(sampling_pars, 0, sizeof(struct rpcap_sampling) );
01598 
01599     sampling_pars->method= p->rmt_samp.method;
01600     sampling_pars->value= htonl(p->rmt_samp.value);
01601 
01602     if ( sock_send(p->rmt_sockctrl, sendbuf, sendbufidx, p->errbuf, PCAP_ERRBUF_SIZE) )
01603         return -1;
01604 
01605     // Waits for the answer
01606     if (sock_recv(p->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
01607         return -1;
01608 
01609     // Checks if the message is correct
01610     retval= rpcap_checkmsg(p->errbuf, p->rmt_sockctrl, &header, RPCAP_MSG_SETSAMPLING_REPLY, 0);
01611 
01612     if (retval != RPCAP_MSG_SETSAMPLING_REPLY)      // the message is not the one expected
01613     {
01614         switch (retval)
01615         {
01616             case -3:        // Unrecoverable network error
01617             case -2:        // The other endpoint sent a message that is not allowed here
01618             case -1:    // The other endpoint has a version number that is not compatible with our
01619             case RPCAP_MSG_ERROR:
01620                 // Do nothing; just exit from here; the error code is already into the errbuf
01621                 return -1;
01622 
01623             default:
01624             {
01625                 SOCK_ASSERT("Internal error", 0);
01626                 return -1;
01627             };
01628         }
01629     }
01630 
01631     if (ntohl(header.plen) != 0)    // the message has an unexpected size
01632     {
01633         if (sock_discard(p->rmt_sockctrl, ntohl(header.plen), p->errbuf, PCAP_ERRBUF_SIZE) == -1)
01634             return -1;
01635     }
01636 
01637     return 0;
01638 
01639 }
01640 
01641 
01642 
01643 
01644 
01645 /*********************************************************
01646  *                                                       *
01647  * Miscellaneous functions                               *
01648  *                                                       *
01649  *********************************************************/
01650 
01651 
01676 int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf)
01677 {
01678 char sendbuf[RPCAP_NETBUF_SIZE];            // temporary buffer in which data to be sent is buffered
01679 int sendbufidx= 0;                          // index which keeps the number of bytes currently buffered
01680 uint16 length;
01681 
01682     length= (uint16) strlen(error);
01683 
01684     if (length > PCAP_ERRBUF_SIZE)
01685         length= PCAP_ERRBUF_SIZE;
01686 
01687     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_ERROR, errcode, length);
01688 
01689     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, 
01690         RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) )
01691         return -1;
01692 
01693     if ( sock_bufferize(error, length, sendbuf, &sendbufidx, 
01694         RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) )
01695         return -1;
01696 
01697     if ( sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) )
01698         return -1;
01699 
01700     return 0;
01701 }
01702 
01703 
01704 
01723 int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf)
01724 {
01725 char sendbuf[RPCAP_NETBUF_SIZE];    // temporary buffer in which data that has to be sent is buffered
01726 int sendbufidx= 0;                  // index which keeps the number of bytes currently buffered
01727 uint16 length;                      // length of the payload of this message
01728 struct rpcap_auth *rpauth;
01729 uint16 auth_type;
01730 struct rpcap_header header;
01731 int retval;                         // temp variable which stores functions return value
01732 
01733     if (auth)
01734     {
01735     auth_type= auth->type;
01736 
01737         switch (auth->type)
01738         {
01739             case RPCAP_RMTAUTH_NULL:
01740                 length= sizeof (struct rpcap_auth);
01741                 break;
01742 
01743             case RPCAP_RMTAUTH_PWD:
01744                 length= sizeof (struct rpcap_auth);
01745                 if (auth->username) length+= strlen(auth->username);
01746                 if (auth->password) length+= strlen(auth->password);
01747                 break;
01748 
01749             default:
01750                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
01751                 return -1;
01752         }
01753     }
01754     else
01755     {
01756         auth_type= RPCAP_RMTAUTH_NULL;
01757         length= sizeof (struct rpcap_auth);
01758     }
01759 
01760 
01761     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 
01762         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) )
01763         return -1;
01764 
01765     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_AUTH_REQ, 0, length);
01766 
01767     rpauth= (struct rpcap_auth *) &sendbuf[sendbufidx];
01768 
01769     if ( sock_bufferize(NULL, sizeof(struct rpcap_auth), NULL, 
01770         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) )
01771         return -1;
01772 
01773     memset(rpauth, 0, sizeof (struct rpcap_auth) );
01774 
01775     rpauth->type= htons(auth_type);
01776 
01777     if (auth_type == RPCAP_RMTAUTH_PWD)
01778     {
01779 
01780         if (auth->username)
01781             rpauth->slen1= strlen(auth->username);
01782         else
01783             rpauth->slen1= 0;
01784 
01785         if ( sock_bufferize(auth->username, rpauth->slen1, sendbuf, 
01786             &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) )
01787             return -1;
01788 
01789         if (auth->password)
01790             rpauth->slen2= strlen(auth->password);
01791         else
01792             rpauth->slen2= 0;
01793 
01794         if ( sock_bufferize(auth->password, rpauth->slen2, sendbuf, 
01795             &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) )
01796             return -1;
01797 
01798         rpauth->slen1= htons (rpauth->slen1);
01799         rpauth->slen2= htons (rpauth->slen2);
01800     }
01801 
01802     if ( sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) )
01803         return -1;
01804 
01805     if ( sock_recv(sock, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
01806         return -1;
01807 
01808     retval= rpcap_checkmsg(errbuf, sock, &header, RPCAP_MSG_AUTH_REPLY, RPCAP_MSG_ERROR, 0);
01809 
01810     if (retval != RPCAP_MSG_AUTH_REPLY)     // the message is not the one expected
01811     {
01812         switch (retval)
01813         {
01814             case -3:        // Unrecoverable network error
01815             case -2:        // The other endpoint sent a message that is not allowed here
01816             case -1:    // The other endpoint has a version number that is not compatible with our
01817                 // Do nothing; just exit from here; the error code is already into the errbuf
01818                 return -1;
01819 
01820             case RPCAP_MSG_ERROR:
01821             {
01822                 return -1;
01823             };
01824 
01825             default:
01826             {
01827                 SOCK_ASSERT("Internal error", 0);
01828                 return -1;
01829             };
01830         }
01831     }
01832 
01833     if (ntohl(header.plen) )
01834     {
01835         if (sock_discard(sock, ntohl(header.plen), errbuf, PCAP_ERRBUF_SIZE) )
01836             return -1;
01837     }
01838     
01839     return 0;
01840 }
01841 
01842 
01843 
01865 void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length)
01866 {
01867     memset(header, 0, sizeof (struct rpcap_header) );
01868 
01869     header->ver= RPCAP_VERSION;
01870     header->type= type;
01871     header->value= htons(value);
01872     header->plen= htonl(length);
01873 }
01874 
01875 
01876 
01920 int rpcap_checkmsg(char *errbuf, SOCKET sock, struct rpcap_header *header, uint8 first, ...)
01921 {
01922 va_list ap;
01923 uint8 type;
01924 int32 len;
01925 
01926     va_start(ap, first);
01927 
01928     // Check if the present version of the protocol can handle this message
01929     if ( rpcap_checkver(sock, header, errbuf) )
01930     {
01931         SOCK_ASSERT(errbuf, 1);
01932 
01933         va_end(ap);
01934         return -1;
01935     }
01936 
01937     type= first;
01938 
01939     while ( type != 0 )
01940     {
01941         // The message matches with one of the types listed
01942         // There is no need of conversions since both values are uint8
01943 
01944         // Check if the other side reported an error.
01945         // If yes, it retrieves it and it returns it back to the caller
01946         if (header->type == RPCAP_MSG_ERROR)
01947         {
01948             len= ntohl(header->plen);
01949 
01950             if (len >= PCAP_ERRBUF_SIZE)
01951             {
01952                 if (sock_recv(sock, errbuf, PCAP_ERRBUF_SIZE - 1, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) )
01953                     return -3;
01954 
01955                 sock_discard(sock, len - (PCAP_ERRBUF_SIZE - 1), NULL, 0);
01956 
01957                 // Put '\0' at the end of the string
01958                 errbuf[PCAP_ERRBUF_SIZE - 1]= 0;
01959             }
01960             else
01961             {
01962                 if (sock_recv(sock, errbuf, len, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
01963                     return -3;
01964 
01965                 // Put '\0' at the end of the string
01966                 errbuf[len]= 0;
01967             }
01968 
01969 
01970             va_end(ap);
01971             return header->type;
01972         }
01973 
01974         if (header->type == type)
01975         {
01976             va_end(ap);
01977             return header->type;
01978         }
01979         
01980         // get next argument
01981         type= va_arg(ap, int);
01982     }
01983 
01984     // we already have an error, so please discard this one
01985     sock_discard(sock, ntohl(header->plen), NULL, 0);
01986 
01987     snprintf(errbuf, PCAP_ERRBUF_SIZE, "The other endpoint sent a message that is not allowed here.");
01988     SOCK_ASSERT(errbuf, 1);
01989 
01990     va_end(ap);
01991     return -2;
01992 }
01993 
01994 
01995 
02019 int rpcap_checkver(SOCKET sock, struct rpcap_header *header, char *errbuf)
02020 {
02021     /*
02022     This is a sample function.
02023 
02024     In the real world, you have to check at the type code, 
02025     and decide accordingly.
02026     */
02027 
02028     if (header->ver != RPCAP_VERSION)
02029     {
02030         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Incompatible version number: message discarded.");
02031 
02032         // we already have an error, so please discard this one
02033         sock_discard(sock, ntohl(header->plen), NULL, 0);
02034         return -1;
02035     }
02036 
02037     return 0;
02038 }
02039 
02040 
02041 
02062 int rpcap_remoteact_getsock(const char *host, char *errbuf)
02063 {
02064 struct activehosts *temp;                   // temp var needed to scan the host list chain
02065 struct addrinfo hints, *addrinfo, *ai_next; // temp var needed to translate between hostname to its address
02066 int retval;
02067 
02068     // retrieve the network address corresponding to 'host'
02069     addrinfo = NULL;
02070     memset(&hints, 0, sizeof (struct addrinfo) );
02071     hints.ai_family = PF_UNSPEC;
02072     hints.ai_socktype= SOCK_STREAM;
02073 
02074     retval = getaddrinfo(host, "0", &hints, &addrinfo);
02075     if (retval != 0)
02076     {
02077         snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
02078         return -1;
02079     }
02080 
02081     temp= activeHosts;
02082 
02083     while (temp)
02084     {
02085         ai_next= addrinfo;
02086         while(ai_next)
02087         {
02088             if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr ) == 0)
02089                 return (temp->sockctrl );
02090 
02091             ai_next= ai_next->ai_next;
02092         }
02093         temp= temp->next;
02094     }
02095 
02096     if (addrinfo)
02097         freeaddrinfo(addrinfo);
02098 
02099     // The host you want to get the socket ID does not have an active connection
02100     return 0;
02101 }
02102 
02103 
02104 
02105 
02106 

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