Main Page Modules Data Structures File List Data Fields Globals Related Pages

# 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. All rights reserved.