メイン   モジュール   デー タ構造   ファイルリスト   データフィールド   グローバル   関連ページ   注意事項   English

pcap-new.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 #include <pcap-int.h>   // for the details of the pcap_t structure
00034 #include <pcap-remote.h>
00035 #include <sockutils.h>
00036 #include <errno.h>  // for the errno variable
00037 #include <stdlib.h>     // for malloc(), free(), ...
00038 #include <string.h>     // for strstr, etc
00039 
00040 
00041 
00042 /*
00043     \brief Global variable; needed to keep the message due to an error that we want to discard.
00044     
00045     This can happen, for instance, because we already have an error message and we want to keep 
00046     the first one.
00047 */
00048 char fakeerrbuf[PCAP_ERRBUF_SIZE + 1];
00049 
00050 
00052 extern struct activehosts *activeHosts;
00053 
00054 
00060 SOCKET sockmain;
00061 
00062 
00063 
00064 
00065 
00066 
00067 /****************************************************
00068  *                                                  *
00069  * Function bodies                                  *
00070  *                                                  *
00071  ****************************************************/
00072 
00073 
00150 int pcap_findalldevs_ex(char *host, char *port, SOCKET sockctrl, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf) 
00151 {
00152 unsigned int nread= 0;      // number of bytes of the payload read from the socket
00153 struct addrinfo hints;      // temp variable needed to resove hostnames into to socket representation
00154 struct addrinfo *addrinfo;  // temp variable needed to resove hostnames into to socket representation
00155 struct rpcap_header header; // structure that keeps the general header of the rpcap protocol
00156 int i,j;        // temp variables
00157 int naddr;      // temp var needed to avoid problems with IPv6 addresses
00158 int retval;     // store the return value of the functions
00159 int nif;        // Number of interfaces listed
00160 int active= 0;  // 'true' if we the other end-party is in active mode
00161 
00162 
00163     // We have to perform two controls here, because the user can call this function in two ways:
00164     //   pcap_findalldevs_ex(NULL, ...) ==> address == NULL
00165     //   pcap_findalldevs_ex("", ...) ==> address[0] == 0
00166     if ( (host == NULL) || (host[0] == 0) )
00167     {
00168         // The user wants to retrieve adapters from a local host
00169         if (pcap_findalldevs(alldevs, errbuf) == -1)
00170             return -1;
00171         if ( (alldevs == NULL) || (*alldevs == NULL) )
00172         {
00173             snprintf(errbuf, PCAP_ERRBUF_SIZE,
00174                 "No interfaces found! Make sure libpcap/WinPcap is properly installed"
00175                 " on the local machine.");
00176             return -1;
00177         }
00178         return 0;
00179     }
00180 
00181     // Warning: this call can be the first one called by the user.
00182     // For this reason, we have to initialize the WinSock support.
00183     if (sock_init(errbuf) == -1)
00184         return -1;
00185 
00186     // Check for active mode
00187     if ( (retval= rpcap_remoteact_getsock(host, errbuf)) == -1)
00188         return -1;
00189 
00190     if (retval)
00191     {
00192         sockctrl= retval;
00193         active= 1;
00194     }
00195     else    // we're not in active mode; let's opening a new control connection (if needed)
00196     {
00197         addrinfo= NULL;
00198 
00199         memset(&hints, 0, sizeof(struct addrinfo) );
00200         hints.ai_family = PF_UNSPEC;
00201         hints.ai_socktype = SOCK_STREAM;
00202 
00203         if ( (port == NULL) || (port[0] == 0) )
00204         {
00205             // the user chose not to specify the port
00206             if (sock_validaddr(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf) == -1)
00207                 return -1;
00208         }
00209         else
00210         {
00211             if (sock_validaddr(host, port, &hints, &addrinfo, errbuf) == -1)
00212                 return -1;
00213         }
00214 
00215         if ( (sockctrl= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf)) == -1)
00216             goto error;
00217 
00218         // addrinfo is no longer used
00219         freeaddrinfo(addrinfo);
00220         addrinfo= NULL;
00221 
00222         if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1)
00223         {
00224             // Control connection has to be closed only in case the remote machine is in passive mode
00225             if (!active)
00226                 sock_close(sockctrl, fakeerrbuf);
00227             return -1;
00228         }
00229     }
00230 
00231     // RPCAP findalldevs command
00232     rpcap_createhdr(&header, RPCAP_MSG_FINDALLIF_REQ, 0, 0);
00233 
00234     if ( sock_send(sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf) == -1 )
00235         goto error;
00236 
00237     if ( sock_recv(sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf) == -1)
00238         goto error;
00239 
00240     // Checks if the message is correct
00241     retval= rpcap_checkmsg(errbuf, sockctrl, &header, RPCAP_MSG_FINDALLIF_REPLY, RPCAP_MSG_ERROR, 0);
00242 
00243     if (retval != RPCAP_MSG_FINDALLIF_REPLY)        // the message is not the one expected
00244     {
00245         switch (retval)
00246         {
00247             case -3:    // Unrecoverable network error
00248             case -2:    // The other endpoint send a message that is not allowed here
00249             case -1:    // The other endpoint has a version number that is not compatible with our
00250                 break;
00251 
00252             case RPCAP_MSG_ERROR:       // The other endpoint reported an error
00253                 break;
00254 
00255             default:
00256             {
00257                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Internal error");
00258                 break;
00259             };
00260         }
00261 
00262         if (!active)
00263             sock_close(sockctrl, fakeerrbuf);
00264 
00265         return -1;
00266     }
00267 
00268     // read the number of interfaces
00269     nif= ntohs(header.value);
00270 
00271     // loop until all interfaces have been received
00272     for (i= 0; i < nif; i++)
00273     {
00274     struct rpcap_findalldevs_if findalldevs_if;
00275     pcap_if_t *dev;     // Previous device into the pcap_if_t chain
00276 
00277         // receive the findalldevs structure from remote hsot
00278         if ( (nread+= sock_recv(sockctrl, (char *) &findalldevs_if, 
00279             sizeof(struct rpcap_findalldevs_if), errbuf) ) == -1)
00280             goto error;
00281 
00282         findalldevs_if.namelen= ntohs(findalldevs_if.namelen);
00283         findalldevs_if.desclen= ntohs(findalldevs_if.desclen);
00284         findalldevs_if.naddr= ntohs(findalldevs_if.naddr);
00285 
00286         // allocate the main structure
00287         if (i == 0)
00288         {
00289             (*alldevs)= (pcap_if_t *) malloc(sizeof(pcap_if_t) );
00290             dev= (*alldevs);
00291         }
00292         else
00293         {
00294             dev->next= (pcap_if_t *) malloc(sizeof(pcap_if_t) );
00295             dev= dev->next;
00296         }
00297 
00298         // check that the malloc() didn't fail
00299         if (dev == NULL)
00300         {
00301             snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00302             goto error;
00303         }
00304         dev->next= NULL;
00305         dev->addresses= NULL;
00306 
00307         // allocate mem for name and description
00308         if (findalldevs_if.namelen)
00309         {
00310             dev->name= (char *) malloc(findalldevs_if.namelen + 1);
00311             if (dev->name == NULL)
00312             {
00313                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00314                 goto error;
00315             }
00316             // Retrieve adapter name and description
00317             if ( (nread+= sock_recv(sockctrl, dev->name, findalldevs_if.namelen, errbuf) ) == -1)
00318                 goto error;
00319             dev->name[findalldevs_if.namelen]= 0;
00320         }
00321         else
00322             dev->name= NULL;
00323 
00324         if (findalldevs_if.desclen)
00325         {
00326             dev->description= (char *) malloc(findalldevs_if.desclen + 1);
00327             if (dev->description == NULL)
00328             {
00329                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00330                 goto error;
00331             }
00332             // Retrieve adapter name and description
00333             if ( (nread+= sock_recv(sockctrl, dev->description, findalldevs_if.desclen, errbuf) ) == -1)
00334                 goto error;
00335             dev->description[findalldevs_if.desclen]= 0;
00336         }
00337         else
00338             dev->description= NULL;
00339 
00340         dev->flags= ntohl(findalldevs_if.flags);
00341 
00342         naddr= 0;
00343         // loop until all addresses have been received
00344         for (j= 0; j < findalldevs_if.naddr; j++)
00345         {
00346         struct rpcap_findalldevs_ifaddr ifaddr;
00347 
00348             // Retrieve the interface addresses
00349             if (  (nread+= sock_recv(sockctrl, (char *) &ifaddr, 
00350                 sizeof(struct rpcap_findalldevs_ifaddr), errbuf) ) == -1)
00351                 goto error;
00352 
00353             // WARNING libpcap bug: the address listing is available only for AF_INET
00354             if ( ntohs(ifaddr.addr.ss_family) == AF_INET)
00355             {
00356             struct pcap_addr *addr;
00357 
00358                 if (naddr == 0)
00359                 {
00360                     dev->addresses= (struct pcap_addr *) malloc ( sizeof(struct pcap_addr) );
00361                     addr= dev->addresses;
00362                 }
00363                 else
00364                 {
00365                     addr->next= (struct pcap_addr *) malloc ( sizeof(struct pcap_addr) );
00366                     addr= addr->next;
00367                 }
00368                 naddr++;
00369 
00370                 if (addr == NULL)
00371                 {
00372                     snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
00373                     goto error;
00374                 }
00375                 addr->next= NULL;
00376 
00377                 if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.addr, 
00378                     (struct sockaddr_storage **) &addr->addr, errbuf) == -1)
00379                     goto error;
00380                 if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.netmask, 
00381                     (struct sockaddr_storage **) &addr->netmask, errbuf) == -1)
00382                     goto error;
00383                 if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.broadaddr, 
00384                     (struct sockaddr_storage **) &addr->broadaddr, errbuf) == -1)
00385                     goto error;
00386                 if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.dstaddr, 
00387                     (struct sockaddr_storage **) &addr->dstaddr, errbuf) == -1)
00388                     goto error;
00389 
00390                 if ( (addr->addr == NULL) && (addr->netmask == NULL) && 
00391                     (addr->broadaddr == NULL) && (addr->dstaddr == NULL) )
00392                 {
00393                     free(addr);
00394                     addr= NULL;
00395                     if (naddr == 1)
00396                         naddr= 0;   // the first item of the list had NULL addresses
00397                 }
00398             }
00399         }
00400     }
00401 
00402     // Checks if all the data has been read; if not, discard the data in excess
00403     if (nread != ntohl(header.plen))
00404     {
00405         if (sock_discard(sockctrl, ntohl(header.plen) - nread, errbuf) == 1)
00406             return -1;
00407     }
00408 
00409     // Control connection has to be closed only in case the remote machine is in passive mode
00410     if (!active)
00411     {
00412         // DO not send RPCAP_CLOSE, since we did not open a pcap_t; no need to free resources
00413         if ( sock_close(sockctrl, errbuf) )
00414             return -1;
00415     }
00416 
00417     // To avoid inconsistencies in the number of sock_init()
00418     sock_cleanup();
00419 
00420     return 0;
00421 
00422 error:
00423     // In case there has been an error, I don't want to overwrite it with a new one
00424     // if the following call fails. I want to return always the original error.
00425     //
00426     // Take care: this connection can already be closed when we try to close it.
00427     // This happens because a previous error in the rpcapd, which requested to
00428     // closed the connection. In that case, we already recognized that into the
00429     // rpspck_isheaderok() and we already acknowledged the closing.
00430     // In that sense, this call is useless here (however it is needed in case
00431     // the client generates the error).
00432 
00433     // Checks if all the data has been read; if not, discard the data in excess
00434     if (nread != ntohl(header.plen))
00435     {
00436         if (sock_discard(sockctrl, ntohl(header.plen) - nread, fakeerrbuf) == 1)
00437             return -1;
00438     }
00439 
00440     // Control connection has to be closed only in case the remote machine is in passive mode
00441     if (!active)
00442         sock_close(sockctrl, fakeerrbuf);
00443 
00444     // To avoid inconsistencies in the number of sock_init()
00445     sock_cleanup();
00446 
00447     return -1;
00448 }
00449 
00450 
00451 
00452 
00495 int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf)
00496 {
00497     switch (type)
00498     {
00499         case PCAP_SRC_FILE:
00500         {
00501             strncpy(source, PCAP_SRC_FILE_KEY, PCAP_BUF_SIZE);
00502             if ((name) && (*name) )
00503             {
00504                 strncat(source, name, PCAP_BUF_SIZE);
00505                 return 0;
00506             }
00507             else
00508             {
00509                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The file name cannot be NULL.");
00510                 return -1;
00511             }
00512         }
00513         case PCAP_SRC_IFREMOTE:
00514         {
00515             strncpy(source, PCAP_SRC_IF_KEY, PCAP_BUF_SIZE);
00516             if ((host) && (*host) )
00517             {
00518                 if ( (strcspn(host, "aAbBcCdDeEfFgGhHjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ")) == strlen(host) )
00519                 {
00520                     // the host name does not contains alphabetic chars. So, it is a numeric address
00521                     // In this case we have to include it between square brackets
00522                     strncat(source, "[", PCAP_BUF_SIZE);
00523                     strncat(source, host, PCAP_BUF_SIZE);
00524                     strncat(source, "]", PCAP_BUF_SIZE);
00525                 }
00526                 else
00527                     strncat(source, host, PCAP_BUF_SIZE);
00528 
00529                 if ((port) && (*port) )
00530                 {
00531                     strncat(source, ":", PCAP_BUF_SIZE);
00532                     strncat(source, port, PCAP_BUF_SIZE);
00533                 }
00534 
00535                 strncat(source, "/", PCAP_BUF_SIZE);
00536             }
00537             else
00538             {
00539                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host name cannot be NULL.");
00540                 return -1;
00541             }
00542 
00543             if ((name) && (*name) )
00544             {
00545                 strncat(source, name, PCAP_BUF_SIZE);
00546                 return 0;
00547             }
00548             else
00549             {
00550                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name cannot be NULL.");
00551                 return -1;
00552             }
00553         }
00554         case PCAP_SRC_IFLOCAL:
00555         {
00556             strncpy(source, PCAP_SRC_IF_KEY, PCAP_BUF_SIZE);
00557             if ((name) && (*name) )
00558             {
00559                 strncat(source, name, PCAP_BUF_SIZE);
00560                 return 0;
00561             }
00562             else
00563             {
00564                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name cannot be NULL.");
00565                 return -1;
00566             }
00567         }
00568         default:
00569         {
00570             snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface type is not valid.");
00571             return -1;
00572         }
00573     }
00574 }
00575 
00576 
00577 
00578 
00636 int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf)
00637 {
00638 char *ptr;
00639 int ntoken;
00640 char tmpname[PCAP_BUF_SIZE];
00641 char tmphost[PCAP_BUF_SIZE];
00642 char tmpport[PCAP_BUF_SIZE];
00643 int tmptype;
00644 
00645     // Initialization stuff
00646     tmpname[0]= 0;
00647     tmphost[0]= 0;
00648     tmpport[0]= 0;
00649 
00650     if (host)
00651         *host= 0;
00652     if (port) 
00653         *port= 0;
00654     if (name)
00655         *name= 0;
00656 
00657     // Look for a 'rpcap://' identifier
00658     if ( (ptr= strstr(source, PCAP_SRC_IF_KEY)) != NULL)
00659     {
00660         ptr+= strlen(PCAP_SRC_IF_KEY);
00661 
00662         if (strchr(ptr, '[')) // This is probably a numeric address
00663         {
00664             ntoken= sscanf(ptr, "[%[1234567890:.]]:%[^/]/%s", tmphost, tmpport, tmpname);
00665 
00666             if (ntoken == 1)    // probably the port is missing
00667                 ntoken= sscanf(ptr, "[%[1234567890:.]]/%s", tmphost, tmpname);
00668 
00669             tmptype= PCAP_SRC_IFREMOTE;
00670         }
00671         else
00672         {
00673             ntoken= sscanf(ptr, "%[^/:]:%[^/]/%s", tmphost, tmpport, tmpname);
00674 
00675             if (ntoken == 1)
00676             {
00677                 // This can be due to two reasons:
00678                 // - we want a remote capture, but the network port is missing
00679                 // - we want to do a local capture
00680                 // To distinguish between the two, we look for the '/' char
00681                 if (strchr(ptr, '/'))
00682                 {
00683                     // We're on a remote capture
00684                     sscanf(ptr, "%[^/]/%s", tmphost, tmpname);
00685                     tmptype= PCAP_SRC_IFREMOTE;
00686                 }
00687                 else
00688                 {
00689                     // We're on a local capture
00690                     if (*ptr)
00691                         strncpy(tmpname, ptr, PCAP_BUF_SIZE);
00692 
00693                     // Clean the host name, since it is a remote capture
00694                     // NOTE: the host name has been assigned in the previous "ntoken= sscanf(...)" line
00695                     tmphost[0]= 0;
00696 
00697                     tmptype= PCAP_SRC_IFLOCAL;
00698                 }
00699             }
00700             else
00701                 tmptype= PCAP_SRC_IFREMOTE;
00702         }
00703 
00704         if (tmpname[0])
00705         {
00706             if (host)
00707                 strcpy(host, tmphost);
00708             if (port) 
00709                 strcpy(port, tmpport);
00710             if (name)
00711                 strcpy(name, tmpname);
00712             if (type)
00713                 *type= tmptype;
00714 
00715             return 0;
00716         }
00717         else
00718         {
00719             if (errbuf)
00720                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name has not been specified.");
00721 
00722             return -1;
00723         }
00724     }
00725 
00726     // Look for a 'file://' identifier
00727     if ( (ptr= strstr(source, PCAP_SRC_FILE_KEY)) != NULL)
00728     {
00729         ptr+= strlen(PCAP_SRC_FILE_KEY);
00730         if (*ptr)
00731         {
00732             if (name)
00733                 strncpy(name, ptr, PCAP_BUF_SIZE);
00734 
00735             if (type)
00736                 *type= PCAP_SRC_FILE;
00737 
00738             return 0;
00739         }
00740         else
00741         {
00742             if (errbuf)
00743                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The file name has not been specified.");
00744 
00745             return -1;
00746         }
00747 
00748     }
00749 
00750     // Backward compatibility; the user didn't use the 'rpcap://, file://'  specifiers
00751     if ( (source) && (*source) )
00752     {
00753         if (name)
00754             strncpy(name, source, PCAP_BUF_SIZE);
00755 
00756         if (type)
00757             *type= PCAP_SRC_IFLOCAL;
00758 
00759         return 0;
00760     }
00761     else
00762     {
00763         if (errbuf)
00764             snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name has not been specified.");
00765 
00766         return -1;
00767     }
00768 };
00769 
00770 
00771 
00881 pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf)
00882 {
00883 char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE], name[PCAP_BUF_SIZE];
00884 int type;
00885 pcap_t *fp;
00886 
00887     if (strlen(source) > PCAP_BUF_SIZE)
00888     {
00889         snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
00890         return NULL;
00891     }
00892 
00893     // determine the type of the source (NULL, file, local, remote)
00894     if (pcap_parsesrcstr(source, &type, host, port, name, errbuf) == -1)
00895         return NULL;
00896 
00897 
00898     switch (type) 
00899     {
00900         case PCAP_SRC_FILE:
00901             fp = pcap_open_offline(name, NULL);
00902             break;
00903 
00904         case PCAP_SRC_IFREMOTE:
00905             // Although we already have host, port and iface, we prefer TO PASS only 'pars' to the 
00906             // pcap_open_remote() so that it has to call the pcap_parsesrcstr() again.
00907             // This is less optimized, but much clearer.
00908             fp= pcap_opensource_remote(source, auth, errbuf);
00909 
00910             if (fp == NULL)
00911                 return NULL;
00912 
00913             fp->snapshot= snaplen;
00914 #ifdef WIN32
00915             fp->timeout= read_timeout;
00916 #else
00917             fp->md.timeout= read_timeout;
00918 #endif
00919             fp->rmt_flags= flags;
00920             break;
00921 
00922         case PCAP_SRC_IFLOCAL:
00923             fp= pcap_open_live(name, snaplen, (flags & PCAP_OPENFLAG_PROMISCUOUS), read_timeout, errbuf);
00924             break;
00925 
00926         default:
00927             strcpy(errbuf, "Source type not supported");
00928             return NULL;
00929     }
00930     return fp;
00931 }
00932 
00933 
00934 
00996 int pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf)
00997 {
00998 // socket-related variables
00999 struct addrinfo hints;          // temporary struct to keep settings needed to open the new socket
01000 struct addrinfo *addrinfo;      // keeps the addrinfo chain; required to open a new socket
01001 struct sockaddr_storage from;   // generic sockaddr_storage variable
01002 socklen_t fromlen;              // keeps the length of the sockaddr_storage variable
01003 SOCKET sockctrl;                // keeps the main socket identifier
01004 struct activehosts *temp, *prev;    // temp var needed to scan he host list chain
01005 
01006     *connectinghost= 0;     // just in case
01007 
01008     // Prepare to open a new server socket
01009     memset(&hints, 0, sizeof(struct addrinfo));
01010                                     // WARNING Currently it supports only ONE socket family among ipv4 and IPv6 
01011     hints.ai_family = AF_INET;      // PF_UNSPEC to have both IPv4 and IPv6 server
01012     hints.ai_flags = AI_PASSIVE;    // Ready to a bind() socket
01013     hints.ai_socktype = SOCK_STREAM;
01014 
01015     // Warning: this call can be the first one called by the user.
01016     // For this reason, we have to initialize the WinSock support.
01017     if (sock_init(errbuf) == -1)
01018         return -1;
01019 
01020     // Do the work
01021     if ((port == NULL) || (port[0] == 0) )
01022     {   
01023         if (sock_validaddr(address, RPCAP_DEFAULT_NETPORT_ACTIVE, &hints, &addrinfo, errbuf) == -1)
01024         {
01025             SOCK_ASSERT(errbuf, 1);
01026             return -2;
01027         }
01028     }
01029     else
01030     {
01031         if (sock_validaddr(address, port, &hints, &addrinfo, errbuf) == -1)
01032         {
01033             SOCK_ASSERT(errbuf, 1);
01034             return -2;
01035         }
01036     }
01037 
01038 
01039     if ( (sockmain= sock_open(addrinfo, SOCKOPEN_SERVER, 1, errbuf)) == -1)
01040     {
01041         SOCK_ASSERT(errbuf, 1);
01042         return -2;
01043     }
01044 
01045     // Connection creation
01046     fromlen = sizeof(struct sockaddr_storage);
01047 
01048     sockctrl= accept(sockmain, (struct sockaddr *) &from, &fromlen);
01049 
01050     // We're not using sock_close, since we do not want to send a shutdown
01051     // (which is not allowed on a non-connected socket)
01052     closesocket(sockmain);
01053     sockmain= 0;
01054 
01055     if (sockctrl == -1)
01056     {
01057         sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
01058         return -2;
01059     }
01060 
01061     // Get the numeric for of the name of the connecting host
01062     if (getnameinfo( (struct sockaddr *) &from, fromlen, connectinghost, 
01063             RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) )
01064     {
01065         sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
01066         rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf);
01067         sock_close(sockctrl, fakeerrbuf);
01068         return -1;
01069     }
01070 
01071     // checks if the connecting host is among the ones allowed
01072     if ( (hostlist) && (hostlist[0]) )
01073     {
01074         if (sock_check_hostlist((char *) hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf) )
01075         {
01076             rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf);
01077             sock_close(sockctrl, fakeerrbuf);
01078             return -1;
01079         }
01080     }
01081 
01082     // Send authentication to the remote machine
01083     if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1)
01084     {
01085         rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf);
01086         sock_close(sockctrl, fakeerrbuf);
01087         return -3;
01088     }
01089 
01090     // Checks that this host does not already have a cntrl connection in place
01091 
01092     // Initialize pointers
01093     temp= activeHosts;
01094     prev= NULL;
01095     
01096     while (temp)
01097     {
01098         // This host already has an active connection in place, so I don't have to update the host list
01099         if (sock_cmpaddr(&temp->host, &from) == 0)
01100             return sockctrl;
01101 
01102         prev= temp;
01103         temp= temp->next;
01104     }
01105 
01106     // The host does not exist in the list; so I have to update the list
01107     if (prev)
01108     {
01109         prev->next= (struct activehosts *) malloc (sizeof (struct activehosts) );
01110         temp= prev->next;
01111     }
01112     else
01113     {
01114         activeHosts= (struct activehosts *) malloc (sizeof (struct activehosts) );
01115         temp= activeHosts;
01116     }
01117 
01118     if (temp == NULL)
01119     {
01120         snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
01121         rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf);
01122         sock_close(sockctrl, fakeerrbuf);
01123         return -1;
01124     }
01125 
01126     memcpy(&temp->host, &from, fromlen);
01127     temp->sockctrl= sockctrl;
01128     temp->next= NULL;
01129 
01130     return sockctrl;
01131 }
01132 
01133 
01134 
01153 int pcap_remoteact_close(const char *host, char *errbuf)
01154 {
01155 struct activehosts *temp, *prev;    // temp var needed to scan the host list chain
01156 struct addrinfo hints, *addrinfo, *ai_next; // temp var needed to translate between hostname to its address
01157 int retval;
01158 
01159     temp= activeHosts;
01160     prev= NULL;
01161 
01162     // retrieve the network address corresponding to 'host'
01163     addrinfo = NULL;
01164     memset(&hints, 0, sizeof (struct addrinfo) );
01165     hints.ai_family = PF_UNSPEC;
01166     hints.ai_socktype= SOCK_STREAM;
01167 
01168     retval = getaddrinfo(host, "0", &hints, &addrinfo);
01169     if (retval != 0)
01170     {
01171         snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
01172         return -1;
01173     }
01174 
01175     while (temp)
01176     {
01177         ai_next= addrinfo;
01178         while(ai_next)
01179         {
01180             if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr ) == 0)
01181             {
01182             struct rpcap_header header;
01183 
01184                 // Close this connection
01185                 rpcap_createhdr( &header, RPCAP_MSG_CLOSE, 0, 0);
01186 
01187                 // I don't check for errors, since I'm going to close everything
01188                 sock_send(temp->sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf);
01189 
01190                 if (sock_close(temp->sockctrl, errbuf) )
01191                 {
01192                     // To avoid inconsistencies in the number of sock_init()
01193                     sock_cleanup();
01194 
01195                     return -1;
01196                 }
01197 
01198                 if (prev)
01199                     prev->next= temp->next;
01200                 else
01201                     activeHosts= temp->next;
01202 
01203                 freeaddrinfo(addrinfo);
01204 
01205                 free(temp);
01206 
01207                 // To avoid inconsistencies in the number of sock_init()
01208                 sock_cleanup();
01209 
01210                 return 0;
01211             }
01212 
01213             ai_next= ai_next->ai_next;
01214         }
01215         prev= temp;
01216         temp= temp->next;
01217     }
01218 
01219     if (addrinfo)
01220         freeaddrinfo(addrinfo);
01221 
01222     // To avoid inconsistencies in the number of sock_init()
01223     sock_cleanup();
01224 
01225     snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host you want to close the active connection is not known");
01226     return -1;
01227 }
01228 
01229 
01249 void pcap_remoteact_cleanup()
01250 {
01251     // Very dirty, but it works
01252     if (sockmain)
01253     {
01254         closesocket(sockmain);
01255 
01256         // To avoid inconsistencies in the number of sock_init()
01257         sock_cleanup();
01258     }
01259 
01260 }
01261 
01262 
01285 int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf)
01286 {
01287 struct activehosts *temp;   // temp var needed to scan the host list chain
01288 int len;
01289 char hoststr[RPCAP_HOSTLIST_SIZE + 1];
01290 
01291     temp= activeHosts;
01292 
01293     len= 0;
01294     *hostlist= 0;
01295 
01296     while (temp)
01297     {
01298         // Get the numeric for of the name of the connecting host
01299         if (getnameinfo( (struct sockaddr *) &temp->host, sizeof (struct sockaddr_storage), hoststr, 
01300                 RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) )
01301         {
01302             sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
01303             return -1;
01304         }
01305 
01306         len= len + strlen(hoststr) + 1 /* the separator */;
01307 
01308         if (len >= size)
01309         {
01310             snprintf(errbuf, PCAP_ERRBUF_SIZE, "The string you provided is not able to keep "
01311                 "the hostnames for all the active connections");
01312             return -1;
01313         }
01314 
01315         strcat(hostlist, hoststr);
01316         hostlist[len - 1]= sep;
01317         hostlist[len]= 0;
01318 
01319         temp= temp->next;
01320     }
01321 
01322     return 0;
01323 }
01324 

documentation. Copyright (c)2002-2003 Politecnico di Torino.
2005 translated by Telebusiness,Inc.
 All rights reserved.