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.