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 #ifndef WIN32
    00041 #include <dirent.h>     // for readdir
    00042 #endif
    00043
    00044
    00045 /*
    00046     \brief Global variable; needed to keep the message due to an error that we want to discard.
    00047
    00048     This can happen, for instance, because we already have an error message and we want to keep
    00049     the first one.
    00050 */
    00051 char fakeerrbuf[PCAP_ERRBUF_SIZE + 1];
    00052
    00053
    00055 extern struct activehosts *activeHosts;
    00056
    00057
    00063 SOCKET sockmain;
    00064
    00065
    00067 #define PCAP_TEXT_SOURCE_FILE "File"
    00068
    00069 #define PCAP_TEXT_SOURCE_ADAPTER "Network adapter"
    00070
    00072 #define PCAP_TEXT_SOURCE_ON_LOCAL_HOST "on local host"
    00073
    00074 #define PCAP_TEXT_SOURCE_ON_REMOTE_HOST "on remote node"
    00075
    00076
    00077
    00078 /****************************************************
    00079  *                                                  *
    00080  * Function bodies                                  *
    00081  *                                                  *
    00082  ****************************************************/
    00083
    00084
    00147 int pcap_findalldevs_ex(char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
    00148 {
    00149 SOCKET sockctrl;            // socket descriptor of the control connection
    00150 unsigned int nread= 0;      // number of bytes of the payload read from the socket
    00151 struct addrinfo hints;      // temp variable needed to resove hostnames into to socket representation
    00152 struct addrinfo *addrinfo;  // temp variable needed to resove hostnames into to socket representation
    00153 struct rpcap_header header; // structure that keeps the general header of the rpcap protocol
    00154 int i,j;        // temp variables
    00155 int naddr;      // temp var needed to avoid problems with IPv6 addresses
    00156 int retval;     // store the return value of the functions
    00157 int nif;        // Number of interfaces listed
    00158 int active= 0;  // 'true' if we the other end-party is in active mode
    00159 char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE], name[PCAP_BUF_SIZE], path[PCAP_BUF_SIZE], filename[PCAP_BUF_SIZE];
    00160 int type;
    00161 pcap_t *fp;
    00162 char tmpstring[PCAP_BUF_SIZE + 1];      // Needed to convert names and descriptions from 'old' syntax to the 'new' one
    00163
    00164     if (strlen(source) > PCAP_BUF_SIZE)
    00165     {
    00166         snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
    00167         return -1;
    00168     }
    00169
    00170     // determine the type of the source (file, local, remote)
    00171     if (pcap_parsesrcstr(source, &type, host, port, NULL /* we're not interested in interface name */, errbuf) == -1)
    00172         return -1;
    00173
    00174     if (type == PCAP_SRC_IFLOCAL)
    00175     {
    00176     pcap_if_t *dev;     // Previous device into the pcap_if_t chain
    00177
    00178         // Initialize temporary string
    00179         tmpstring[PCAP_BUF_SIZE]= 0;
    00180
    00181         // The user wants to retrieve adapters from a local host
    00182         if (pcap_findalldevs(alldevs, errbuf) == -1)
    00183             return -1;
    00184
    00185         if ( (alldevs == NULL) || (*alldevs == NULL) )
    00186         {
    00187             snprintf(errbuf, PCAP_ERRBUF_SIZE,
    00188                 "No interfaces found! Make sure libpcap/WinPcap is properly installed"
    00189                 " on the local machine.");
    00190             return -1;
    00191         }
    00192
    00193         // Scan all the interfaces and modify name and description
    00194         // This is a trick in order to avoid the re-implementation of the pcap_findalldevs here
    00195         dev= *alldevs;
    00196         while (dev)
    00197         {
    00198             // Create the new device identifier
    00199             if (pcap_createsrcstr(tmpstring, PCAP_SRC_IFLOCAL, NULL, NULL, dev->name, errbuf) == -1)
    00200                 return -1;
    00201
    00202             // Delete the old pointer
    00203             free(dev->name);
    00204
    00205             dev->name= (char *) malloc( strlen(tmpstring) + 1);
    00206
    00207             if (dev->name == NULL)
    00208             {
    00209                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    00210                 return -1;
    00211             }
    00212
    00213             // Copy the new device identifier into the correct memory location
    00214             strncpy(dev->name, tmpstring, strlen(tmpstring) + 1);
    00215
    00216
    00217             // Create the new device description
    00218             if ( (dev->description == NULL) || (dev->description[0] == 0) )
    00219                 snprintf(tmpstring, sizeof(tmpstring) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_ADAPTER,
    00220                     dev->name, PCAP_TEXT_SOURCE_ON_LOCAL_HOST);
    00221             else
    00222                 snprintf(tmpstring, sizeof(tmpstring) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_ADAPTER,
    00223                     dev->description, PCAP_TEXT_SOURCE_ON_LOCAL_HOST);
    00224
    00225             // Delete the old pointer
    00226             free(dev->description);
    00227
    00228             dev->description= (char *) malloc( strlen(tmpstring) + 1);
    00229
    00230             if (dev->description == NULL)
    00231             {
    00232                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    00233                 return -1;
    00234             }
    00235
    00236             // Copy the new device description into the correct memory location
    00237             strncpy(dev->description, tmpstring, strlen(tmpstring) + 1);
    00238
    00239             dev= dev->next;
    00240         }
    00241
    00242         return 0;
    00243     }
    00244
    00245     (*alldevs)= NULL;
    00246
    00247     if (type == PCAP_SRC_FILE)
    00248     {
    00249         int stringlen;
    00250 #ifdef WIN32
    00251         WIN32_FIND_DATA filedata;
    00252         HANDLE filehandle;
    00253 #else
    00254         struct dirent *filedata;
    00255         DIR *unixdir;
    00256 #endif
    00257
    00258         // Check that the filename is correct
    00259         stringlen= strlen(name);
    00260
    00261         // The directory must end with '\' in Win32 and '/' in UNIX
    00262 #ifdef WIN32
    00263     #define ENDING_CHAR '\\'
    00264 #else
    00265     #define ENDING_CHAR '/'
    00266 #endif
    00267
    00268         if (name[stringlen - 1] != ENDING_CHAR )
    00269         {
    00270             name[stringlen]= ENDING_CHAR;
    00271             name[stringlen + 1]= 0;
    00272
    00273             stringlen++;
    00274         }
    00275
    00276         // Save the path for future reference
    00277         snprintf(path, sizeof(path), "%s", name);
    00278
    00279 #ifdef WIN32
    00280         // To perform directory listing, Win32 must have an 'asterisk' as ending char
    00281         if (name[stringlen - 1] != '*' )
    00282         {
    00283             name[stringlen]= '*';
    00284             name[stringlen + 1]= 0;
    00285         }
    00286
    00287         filehandle = FindFirstFile(name, &filedata);
    00288
    00289         if (filehandle == INVALID_HANDLE_VALUE)
    00290         {
    00291             snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
    00292             return -1;
    00293         }
    00294
    00295 #else
    00296         // opening the folder
    00297         unixdir= opendir(path);
    00298
    00299         // get the first file into it
    00300         filedata= readdir(unixdir);
    00301
    00302         if (filedata == NULL)
    00303         {
    00304             snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
    00305             return -1;
    00306         }
    00307 #endif
    00308
    00309         do
    00310         {
    00311
    00312 #ifdef WIN32
    00313             snprintf(filename, sizeof(filename), "%s%s", path, filedata.cFileName);
    00314 #else
    00315             snprintf(filename, sizeof(filename), "%s%s", path, filedata->d_name);
    00316 #endif
    00317
    00318             fp= pcap_open_offline(filename, errbuf);
    00319
    00320             if (fp)
    00321             {
    00322             pcap_if_t *dev;     // Previous device into the pcap_if_t chain
    00323
    00324                 // allocate the main structure
    00325                 if (*alldevs == NULL)   // This is in case it is the first file
    00326                 {
    00327                     (*alldevs)= (pcap_if_t *) malloc(sizeof(pcap_if_t) );
    00328                     dev= (*alldevs);
    00329                 }
    00330                 else
    00331                 {
    00332                     dev->next= (pcap_if_t *) malloc(sizeof(pcap_if_t) );
    00333                     dev= dev->next;
    00334                 }
    00335
    00336                 // check that the malloc() didn't fail
    00337                 if (dev == NULL)
    00338                 {
    00339                     snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    00340                     return -1;
    00341                 }
    00342
    00343                 // Initialize the structure to 'zero'
    00344                 memset(dev, 0, sizeof(pcap_if_t) );
    00345
    00346                 // Create the new source identifier
    00347                 if (pcap_createsrcstr(tmpstring, PCAP_SRC_FILE, NULL, NULL, filename, errbuf) == -1)
    00348                     return -1;
    00349
    00350                 stringlen= strlen(tmpstring);
    00351
    00352                 dev->name= (char *) malloc(stringlen + 1);
    00353                 if (dev->name == NULL)
    00354                 {
    00355                     snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    00356                     return -1;
    00357                 }
    00358
    00359                 strncpy(dev->name, tmpstring, stringlen);
    00360
    00361                 dev->name[stringlen]= 0;
    00362
    00363                 // Create the description
    00364                 snprintf(tmpstring, sizeof(tmpstring) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_FILE,
    00365                     dev->name, PCAP_TEXT_SOURCE_ON_LOCAL_HOST);
    00366
    00367                 stringlen= strlen(tmpstring);
    00368
    00369                 dev->description= (char *) malloc(stringlen + 1);
    00370
    00371                 if (dev->description == NULL)
    00372                 {
    00373                     snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    00374                     return -1;
    00375                 }
    00376
    00377                 // Copy the new device description into the correct memory location
    00378                 strncpy(dev->description, tmpstring, stringlen + 1);
    00379
    00380                 pcap_close(fp);
    00381             }
    00382         }
    00383 #ifdef WIN32
    00384         while (FindNextFile(filehandle, &filedata) != 0);
    00385 #else
    00386         while ( (filedata= readdir(unixdir)) != NULL);
    00387 #endif
    00388
    00389
    00390 #ifdef WIN32
    00391         // Close the search handle.
    00392         FindClose(filehandle);
    00393 #endif
    00394
    00395         return 0;
    00396     }
    00397
    00398     // If we come here, it is a remote host
    00399
    00400     // Warning: this call can be the first one called by the user.
    00401     // For this reason, we have to initialize the WinSock support.
    00402     if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
    00403         return -1;
    00404
    00405     // Check for active mode
    00406     if ( (retval= rpcap_remoteact_getsock(host, errbuf)) == -1)
    00407         return -1;
    00408
    00409     if (retval)
    00410     {
    00411         sockctrl= retval;
    00412         active= 1;
    00413     }
    00414     else    // we're not in active mode; let's opening a new control connection (if needed)
    00415     {
    00416         addrinfo= NULL;
    00417
    00418         memset(&hints, 0, sizeof(struct addrinfo) );
    00419         hints.ai_family = PF_UNSPEC;
    00420         hints.ai_socktype = SOCK_STREAM;
    00421
    00422         if ( (port == NULL) || (port[0] == 0) )
    00423         {
    00424             // the user chose not to specify the port
    00425             if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00426                 return -1;
    00427         }
    00428         else
    00429         {
    00430             if (sock_initaddress(host, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00431                 return -1;
    00432         }
    00433
    00434         if ( (sockctrl= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    00435             goto error;
    00436
    00437         // addrinfo is no longer used
    00438         freeaddrinfo(addrinfo);
    00439         addrinfo= NULL;
    00440
    00441         if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1)
    00442         {
    00443             // Control connection has to be closed only in case the remote machine is in passive mode
    00444             if (!active)
    00445                 sock_close(sockctrl, fakeerrbuf, PCAP_ERRBUF_SIZE);
    00446             return -1;
    00447         }
    00448     }
    00449
    00450     // RPCAP findalldevs command
    00451     rpcap_createhdr(&header, RPCAP_MSG_FINDALLIF_REQ, 0, 0);
    00452
    00453     if ( sock_send(sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1 )
    00454         goto error;
    00455
    00456     if ( sock_recv(sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00457         goto error;
    00458
    00459     // Checks if the message is correct
    00460     retval= rpcap_checkmsg(errbuf, sockctrl, &header, RPCAP_MSG_FINDALLIF_REPLY, RPCAP_MSG_ERROR, 0);
    00461
    00462     if (retval != RPCAP_MSG_FINDALLIF_REPLY)        // the message is not the one expected
    00463     {
    00464         switch (retval)
    00465         {
    00466             case -3:    // Unrecoverable network error
    00467             case -2:    // The other endpoint send a message that is not allowed here
    00468             case -1:    // The other endpoint has a version number that is not compatible with our
    00469                 break;
    00470
    00471             case RPCAP_MSG_ERROR:       // The other endpoint reported an error
    00472                 break;
    00473
    00474             default:
    00475             {
    00476                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Internal error");
    00477                 break;
    00478             };
    00479         }
    00480
    00481         if (!active)
    00482             sock_close(sockctrl, fakeerrbuf, PCAP_ERRBUF_SIZE);
    00483
    00484         return -1;
    00485     }
    00486
    00487     // read the number of interfaces
    00488     nif= ntohs(header.value);
    00489
    00490     // loop until all interfaces have been received
    00491     for (i= 0; i < nif; i++)
    00492     {
    00493     struct rpcap_findalldevs_if findalldevs_if;
    00494     pcap_if_t *dev;     // Previous device into the pcap_if_t chain
    00495     char tmpstring2[PCAP_BUF_SIZE + 1];     // Needed to convert names and descriptions from 'old' syntax to the 'new' one
    00496     int stringlen;
    00497
    00498         tmpstring2[PCAP_BUF_SIZE]= 0;
    00499
    00500         // receive the findalldevs structure from remote hsot
    00501         if ( (nread+= sock_recv(sockctrl, (char *) &findalldevs_if,
    00502             sizeof(struct rpcap_findalldevs_if), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) ) == -1)
    00503             goto error;
    00504
    00505         findalldevs_if.namelen= ntohs(findalldevs_if.namelen);
    00506         findalldevs_if.desclen= ntohs(findalldevs_if.desclen);
    00507         findalldevs_if.naddr= ntohs(findalldevs_if.naddr);
    00508
    00509         // allocate the main structure
    00510         if (i == 0)
    00511         {
    00512             (*alldevs)= (pcap_if_t *) malloc(sizeof(pcap_if_t) );
    00513             dev= (*alldevs);
    00514         }
    00515         else
    00516         {
    00517             dev->next= (pcap_if_t *) malloc(sizeof(pcap_if_t) );
    00518             dev= dev->next;
    00519         }
    00520
    00521         // check that the malloc() didn't fail
    00522         if (dev == NULL)
    00523         {
    00524             snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    00525             goto error;
    00526         }
    00527
    00528         // Initialize the structure to 'zero'
    00529         memset(dev, 0, sizeof(pcap_if_t) );
    00530
    00531         // allocate mem for name and description
    00532         if (findalldevs_if.namelen)
    00533         {
    00534
    00535             if (findalldevs_if.namelen >= sizeof(tmpstring) )
    00536             {
    00537                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface name too long");
    00538                 goto error;
    00539             }
    00540
    00541             // Retrieve adapter name
    00542             if ( (nread+= sock_recv(sockctrl, tmpstring, findalldevs_if.namelen, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) ) == -1)
    00543                 goto error;
    00544
    00545             tmpstring[findalldevs_if.namelen]= 0;
    00546
    00547             // Create the new device identifier
    00548             if (pcap_createsrcstr(tmpstring2, PCAP_SRC_IFREMOTE, host, port, tmpstring, errbuf) == -1)
    00549                 return -1;
    00550
    00551             stringlen= strlen(tmpstring2);
    00552
    00553             dev->name= (char *) malloc(stringlen + 1);
    00554             if (dev->name == NULL)
    00555             {
    00556                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    00557                 goto error;
    00558             }
    00559
    00560             // Copy the new device name into the correct memory location
    00561             strncpy(dev->name, tmpstring2, stringlen + 1);
    00562         }
    00563
    00564         if (findalldevs_if.desclen)
    00565         {
    00566             if (findalldevs_if.desclen >= sizeof(tmpstring) )
    00567             {
    00568                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface description too long");
    00569                 goto error;
    00570             }
    00571
    00572             // Retrieve adapter description
    00573             if ( (nread+= sock_recv(sockctrl, tmpstring, findalldevs_if.desclen, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) ) == -1)
    00574                 goto error;
    00575
    00576             tmpstring[findalldevs_if.desclen]= 0;
    00577
    00578
    00579             snprintf(tmpstring2, sizeof(tmpstring2) - 1, "%s '%s' %s %s", PCAP_TEXT_SOURCE_ADAPTER,
    00580                 tmpstring, PCAP_TEXT_SOURCE_ON_REMOTE_HOST, host);
    00581
    00582             stringlen= strlen(tmpstring2);
    00583
    00584             dev->description= (char *) malloc(stringlen + 1);
    00585
    00586             if (dev->description == NULL)
    00587             {
    00588                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    00589                 goto error;
    00590             }
    00591
    00592             // Copy the new device description into the correct memory location
    00593             strncpy(dev->description, tmpstring2, stringlen + 1);
    00594         }
    00595
    00596         dev->flags= ntohl(findalldevs_if.flags);
    00597
    00598         naddr= 0;
    00599         // loop until all addresses have been received
    00600         for (j= 0; j < findalldevs_if.naddr; j++)
    00601         {
    00602         struct rpcap_findalldevs_ifaddr ifaddr;
    00603
    00604             // Retrieve the interface addresses
    00605             if (  (nread+= sock_recv(sockctrl, (char *) &ifaddr,
    00606                 sizeof(struct rpcap_findalldevs_ifaddr), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) ) == -1)
    00607                 goto error;
    00608
    00609             // WARNING libpcap bug: the address listing is available only for AF_INET
    00610             if ( ntohs(ifaddr.addr.ss_family) == AF_INET)
    00611             {
    00612             struct pcap_addr *addr;
    00613
    00614                 if (naddr == 0)
    00615                 {
    00616                     dev->addresses= (struct pcap_addr *) malloc ( sizeof(struct pcap_addr) );
    00617                     addr= dev->addresses;
    00618                 }
    00619                 else
    00620                 {
    00621                     addr->next= (struct pcap_addr *) malloc ( sizeof(struct pcap_addr) );
    00622                     addr= addr->next;
    00623                 }
    00624                 naddr++;
    00625
    00626                 if (addr == NULL)
    00627                 {
    00628                     snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    00629                     goto error;
    00630                 }
    00631                 addr->next= NULL;
    00632
    00633                 if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.addr,
    00634                     (struct sockaddr_storage **) &addr->addr, errbuf) == -1)
    00635                     goto error;
    00636                 if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.netmask,
    00637                     (struct sockaddr_storage **) &addr->netmask, errbuf) == -1)
    00638                     goto error;
    00639                 if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.broadaddr,
    00640                     (struct sockaddr_storage **) &addr->broadaddr, errbuf) == -1)
    00641                     goto error;
    00642                 if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.dstaddr,
    00643                     (struct sockaddr_storage **) &addr->dstaddr, errbuf) == -1)
    00644                     goto error;
    00645
    00646                 if ( (addr->addr == NULL) && (addr->netmask == NULL) &&
    00647                     (addr->broadaddr == NULL) && (addr->dstaddr == NULL) )
    00648                 {
    00649                     free(addr);
    00650                     addr= NULL;
    00651                     if (naddr == 1)
    00652                         naddr= 0;   // the first item of the list had NULL addresses
    00653                 }
    00654             }
    00655         }
    00656     }
    00657
    00658     // Checks if all the data has been read; if not, discard the data in excess
    00659     if (nread != ntohl(header.plen))
    00660     {
    00661         if (sock_discard(sockctrl, ntohl(header.plen) - nread, errbuf, PCAP_ERRBUF_SIZE) == 1)
    00662             return -1;
    00663     }
    00664
    00665     // Control connection has to be closed only in case the remote machine is in passive mode
    00666     if (!active)
    00667     {
    00668         // DO not send RPCAP_CLOSE, since we did not open a pcap_t; no need to free resources
    00669         if ( sock_close(sockctrl, errbuf, PCAP_ERRBUF_SIZE) )
    00670             return -1;
    00671     }
    00672
    00673     // To avoid inconsistencies in the number of sock_init()
    00674     sock_cleanup();
    00675
    00676     return 0;
    00677
    00678 error:
    00679     // In case there has been an error, I don't want to overwrite it with a new one
    00680     // if the following call fails. I want to return always the original error.
    00681     //
    00682     // Take care: this connection can already be closed when we try to close it.
    00683     // This happens because a previous error in the rpcapd, which requested to
    00684     // closed the connection. In that case, we already recognized that into the
    00685     // rpspck_isheaderok() and we already acknowledged the closing.
    00686     // In that sense, this call is useless here (however it is needed in case
    00687     // the client generates the error).
    00688
    00689     // Checks if all the data has been read; if not, discard the data in excess
    00690     if (nread != ntohl(header.plen))
    00691     {
    00692         if (sock_discard(sockctrl, ntohl(header.plen) - nread, fakeerrbuf, PCAP_ERRBUF_SIZE) == 1)
    00693             return -1;
    00694     }
    00695
    00696     // Control connection has to be closed only in case the remote machine is in passive mode
    00697     if (!active)
    00698         sock_close(sockctrl, fakeerrbuf, PCAP_ERRBUF_SIZE);
    00699
    00700     // To avoid inconsistencies in the number of sock_init()
    00701     sock_cleanup();
    00702
    00703     return -1;
    00704 }
    00705
    00706
    00707
    00708
    00753 int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf)
    00754 {
    00755     switch (type)
    00756     {
    00757         case PCAP_SRC_FILE:
    00758         {
    00759             strncpy(source, PCAP_SRC_FILE_STRING, PCAP_BUF_SIZE);
    00760             if ((name) && (*name) )
    00761             {
    00762                 strncat(source, name, PCAP_BUF_SIZE);
    00763                 return 0;
    00764             }
    00765             else
    00766             {
    00767                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The file name cannot be NULL.");
    00768                 return -1;
    00769             }
    00770         }
    00771
    00772         case PCAP_SRC_IFREMOTE:
    00773         {
    00774             strncpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
    00775             if ((host) && (*host) )
    00776             {
    00777                 if ( (strcspn(host, "aAbBcCdDeEfFgGhHjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ")) == strlen(host) )
    00778                 {
    00779                     // the host name does not contains alphabetic chars. So, it is a numeric address
    00780                     // In this case we have to include it between square brackets
    00781                     strncat(source, "[", PCAP_BUF_SIZE);
    00782                     strncat(source, host, PCAP_BUF_SIZE);
    00783                     strncat(source, "]", PCAP_BUF_SIZE);
    00784                 }
    00785                 else
    00786                     strncat(source, host, PCAP_BUF_SIZE);
    00787
    00788                 if ((port) && (*port) )
    00789                 {
    00790                     strncat(source, ":", PCAP_BUF_SIZE);
    00791                     strncat(source, port, PCAP_BUF_SIZE);
    00792                 }
    00793
    00794                 strncat(source, "/", PCAP_BUF_SIZE);
    00795             }
    00796             else
    00797             {
    00798                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host name cannot be NULL.");
    00799                 return -1;
    00800             }
    00801
    00802             if ((name) && (*name) )
    00803                 strncat(source, name, PCAP_BUF_SIZE);
    00804
    00805             return 0;
    00806         }
    00807
    00808         case PCAP_SRC_IFLOCAL:
    00809         {
    00810             strncpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
    00811
    00812             if ((name) && (*name) )
    00813                 strncat(source, name, PCAP_BUF_SIZE);
    00814
    00815             return 0;
    00816         }
    00817
    00818         default:
    00819         {
    00820             snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface type is not valid.");
    00821             return -1;
    00822         }
    00823     }
    00824 }
    00825
    00826
    00827
    00828
    00885 int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf)
    00886 {
    00887 char *ptr;
    00888 int ntoken;
    00889 char tmpname[PCAP_BUF_SIZE];
    00890 char tmphost[PCAP_BUF_SIZE];
    00891 char tmpport[PCAP_BUF_SIZE];
    00892 int tmptype;
    00893
    00894     // Initialization stuff
    00895     tmpname[0]= 0;
    00896     tmphost[0]= 0;
    00897     tmpport[0]= 0;
    00898
    00899     if (host)
    00900         *host= 0;
    00901     if (port)
    00902         *port= 0;
    00903     if (name)
    00904         *name= 0;
    00905
    00906     // Look for a 'rpcap://' identifier
    00907     if ( (ptr= strstr(source, PCAP_SRC_IF_STRING)) != NULL)
    00908     {
    00909         if (strlen(PCAP_SRC_IF_STRING) == strlen(source) )
    00910         {
    00911             // The source identifier contains only the 'rpcap://' string.
    00912             // So, this is a local capture.
    00913             *type= PCAP_SRC_IFLOCAL;
    00914             return 0;
    00915         }
    00916
    00917         ptr+= strlen(PCAP_SRC_IF_STRING);
    00918
    00919         if (strchr(ptr, '[')) // This is probably a numeric address
    00920         {
    00921             ntoken= sscanf(ptr, "[%[1234567890:.]]:%[^/]/%s", tmphost, tmpport, tmpname);
    00922
    00923             if (ntoken == 1)    // probably the port is missing
    00924                 ntoken= sscanf(ptr, "[%[1234567890:.]]/%s", tmphost, tmpname);
    00925
    00926             tmptype= PCAP_SRC_IFREMOTE;
    00927         }
    00928         else
    00929         {
    00930             ntoken= sscanf(ptr, "%[^/:]:%[^/]/%s", tmphost, tmpport, tmpname);
    00931
    00932             if (ntoken == 1)
    00933             {
    00934                 // This can be due to two reasons:
    00935                 // - we want a remote capture, but the network port is missing
    00936                 // - we want to do a local capture
    00937                 // To distinguish between the two, we look for the '/' char
    00938                 if (strchr(ptr, '/'))
    00939                 {
    00940                     // We're on a remote capture
    00941                     sscanf(ptr, "%[^/]/%s", tmphost, tmpname);
    00942                     tmptype= PCAP_SRC_IFREMOTE;
    00943                 }
    00944                 else
    00945                 {
    00946                     // We're on a local capture
    00947                     if (*ptr)
    00948                         strncpy(tmpname, ptr, PCAP_BUF_SIZE);
    00949
    00950                     // Clean the host name, since it is a remote capture
    00951                     // NOTE: the host name has been assigned in the previous "ntoken= sscanf(...)" line
    00952                     tmphost[0]= 0;
    00953
    00954                     tmptype= PCAP_SRC_IFLOCAL;
    00955                 }
    00956             }
    00957             else
    00958                 tmptype= PCAP_SRC_IFREMOTE;
    00959         }
    00960
    00961         if (host)
    00962             strcpy(host, tmphost);
    00963         if (port)
    00964             strcpy(port, tmpport);
    00965         if (type)
    00966             *type= tmptype;
    00967
    00968         if (name)
    00969         {
    00970             // If the user wants the host name, but it cannot be located into the source string, return error
    00971             // However, if the user is not interested in the interface name (e.g. if we're called by
    00972             // pcap_findalldevs_ex(), which does not have interface name, do not return error
    00973             if (tmpname[0])
    00974             {
    00975                 strcpy(name, tmpname);
    00976             }
    00977             else
    00978             {
    00979                 if (errbuf)
    00980                     snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name has not been specified.");
    00981
    00982                 return -1;
    00983             }
    00984         }
    00985
    00986         return 0;
    00987     }
    00988
    00989     // Look for a 'file://' identifier
    00990     if ( (ptr= strstr(source, PCAP_SRC_FILE_STRING)) != NULL)
    00991     {
    00992         ptr+= strlen(PCAP_SRC_FILE_STRING);
    00993         if (*ptr)
    00994         {
    00995             if (name)
    00996                 strncpy(name, ptr, PCAP_BUF_SIZE);
    00997
    00998             if (type)
    00999                 *type= PCAP_SRC_FILE;
    01000
    01001             return 0;
    01002         }
    01003         else
    01004         {
    01005             if (errbuf)
    01006                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The file name has not been specified.");
    01007
    01008             return -1;
    01009         }
    01010
    01011     }
    01012
    01013     // Backward compatibility; the user didn't use the 'rpcap://, file://'  specifiers
    01014     if ( (source) && (*source) )
    01015     {
    01016         if (name)
    01017             strncpy(name, source, PCAP_BUF_SIZE);
    01018
    01019         if (type)
    01020             *type= PCAP_SRC_IFLOCAL;
    01021
    01022         return 0;
    01023     }
    01024     else
    01025     {
    01026         if (errbuf)
    01027             snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name has not been specified.");
    01028
    01029         return -1;
    01030     }
    01031 };
    01032
    01033
    01034
    01102 pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf)
    01103 {
    01104 char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE], name[PCAP_BUF_SIZE];
    01105 int type;
    01106 pcap_t *fp;
    01107
    01108     if (strlen(source) > PCAP_BUF_SIZE)
    01109     {
    01110         snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
    01111         return NULL;
    01112     }
    01113
    01114     // determine the type of the source (file, local, remote)
    01115     if (pcap_parsesrcstr(source, &type, host, port, name, errbuf) == -1)
    01116         return NULL;
    01117
    01118
    01119     switch (type)
    01120     {
    01121         case PCAP_SRC_FILE:
    01122             fp = pcap_open_offline(name, errbuf);
    01123             break;
    01124
    01125         case PCAP_SRC_IFREMOTE:
    01126             // Although we already have host, port and iface, we prefer TO PASS only 'pars' to the
    01127             // pcap_open_remote() so that it has to call the pcap_parsesrcstr() again.
    01128             // This is less optimized, but much clearer.
    01129             fp= pcap_opensource_remote(source, auth, errbuf);
    01130
    01131             if (fp == NULL)
    01132                 return NULL;
    01133
    01134             fp->snapshot= snaplen;
    01135 #ifdef linux
    01136             fp->md.timeout= read_timeout;
    01137 #else
    01138             fp->timeout= read_timeout;
    01139 #endif
    01140             fp->rmt_flags= flags;
    01141             break;
    01142
    01143         case PCAP_SRC_IFLOCAL:
    01144             fp= pcap_open_live(name, snaplen, (flags & PCAP_OPENFLAG_PROMISCUOUS), read_timeout, errbuf);
    01145             break;
    01146
    01147         default:
    01148             strcpy(errbuf, "Source type not supported");
    01149             return NULL;
    01150     }
    01151     return fp;
    01152 }
    01153
    01154
    01169 struct pcap_samp *pcap_setsampling(pcap_t *p)
    01170 {
    01171     return &(p->rmt_samp);
    01172 }
    01173
    01174
    01237 SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf)
    01238 {
    01239 // socket-related variables
    01240 struct addrinfo hints;          // temporary struct to keep settings needed to open the new socket
    01241 struct addrinfo *addrinfo;      // keeps the addrinfo chain; required to open a new socket
    01242 struct sockaddr_storage from;   // generic sockaddr_storage variable
    01243 socklen_t fromlen;              // keeps the length of the sockaddr_storage variable
    01244 SOCKET sockctrl;                // keeps the main socket identifier
    01245 struct activehosts *temp, *prev;    // temp var needed to scan he host list chain
    01246
    01247     *connectinghost= 0;     // just in case
    01248
    01249     // Prepare to open a new server socket
    01250     memset(&hints, 0, sizeof(struct addrinfo));
    01251                                     // WARNING Currently it supports only ONE socket family among ipv4 and IPv6
    01252     hints.ai_family = AF_INET;      // PF_UNSPEC to have both IPv4 and IPv6 server
    01253     hints.ai_flags = AI_PASSIVE;    // Ready to a bind() socket
    01254     hints.ai_socktype = SOCK_STREAM;
    01255
    01256     // Warning: this call can be the first one called by the user.
    01257     // For this reason, we have to initialize the WinSock support.
    01258     if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
    01259         return -1;
    01260
    01261     // Do the work
    01262     if ((port == NULL) || (port[0] == 0) )
    01263     {
    01264         if (sock_initaddress(address, RPCAP_DEFAULT_NETPORT_ACTIVE, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01265         {
    01266             SOCK_ASSERT(errbuf, 1);
    01267             return -2;
    01268         }
    01269     }
    01270     else
    01271     {
    01272         if (sock_initaddress(address, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01273         {
    01274             SOCK_ASSERT(errbuf, 1);
    01275             return -2;
    01276         }
    01277     }
    01278
    01279
    01280     if ( (sockmain= sock_open(addrinfo, SOCKOPEN_SERVER, 1, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    01281     {
    01282         SOCK_ASSERT(errbuf, 1);
    01283         return -2;
    01284     }
    01285
    01286     // Connection creation
    01287     fromlen = sizeof(struct sockaddr_storage);
    01288
    01289     sockctrl= accept(sockmain, (struct sockaddr *) &from, &fromlen);
    01290
    01291     // We're not using sock_close, since we do not want to send a shutdown
    01292     // (which is not allowed on a non-connected socket)
    01293     closesocket(sockmain);
    01294     sockmain= 0;
    01295
    01296     if (sockctrl == -1)
    01297     {
    01298         sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
    01299         return -2;
    01300     }
    01301
    01302     // Get the numeric for of the name of the connecting host
    01303     if (getnameinfo( (struct sockaddr *) &from, fromlen, connectinghost, RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) )
    01304     {
    01305         sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
    01306         rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf);
    01307         sock_close(sockctrl, fakeerrbuf, PCAP_ERRBUF_SIZE);
    01308         return -1;
    01309     }
    01310
    01311     // checks if the connecting host is among the ones allowed
    01312     if (sock_check_hostlist((char *) hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0)
    01313     {
    01314         rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf);
    01315         sock_close(sockctrl, fakeerrbuf, PCAP_ERRBUF_SIZE);
    01316         return -1;
    01317     }
    01318
    01319     // Send authentication to the remote machine
    01320     if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1)
    01321     {
    01322         rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf);
    01323         sock_close(sockctrl, fakeerrbuf, PCAP_ERRBUF_SIZE);
    01324         return -3;
    01325     }
    01326
    01327     // Checks that this host does not already have a cntrl connection in place
    01328
    01329     // Initialize pointers
    01330     temp= activeHosts;
    01331     prev= NULL;
    01332
    01333     while (temp)
    01334     {
    01335         // This host already has an active connection in place, so I don't have to update the host list
    01336         if (sock_cmpaddr(&temp->host, &from) == 0)
    01337             return sockctrl;
    01338
    01339         prev= temp;
    01340         temp= temp->next;
    01341     }
    01342
    01343     // The host does not exist in the list; so I have to update the list
    01344     if (prev)
    01345     {
    01346         prev->next= (struct activehosts *) malloc (sizeof (struct activehosts) );
    01347         temp= prev->next;
    01348     }
    01349     else
    01350     {
    01351         activeHosts= (struct activehosts *) malloc (sizeof (struct activehosts) );
    01352         temp= activeHosts;
    01353     }
    01354
    01355     if (temp == NULL)
    01356     {
    01357         snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    01358         rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf);
    01359         sock_close(sockctrl, fakeerrbuf, PCAP_ERRBUF_SIZE);
    01360         return -1;
    01361     }
    01362
    01363     memcpy(&temp->host, &from, fromlen);
    01364     temp->sockctrl= sockctrl;
    01365     temp->next= NULL;
    01366
    01367     return sockctrl;
    01368 }
    01369
    01370
    01371
    01391 int pcap_remoteact_close(const char *host, char *errbuf)
    01392 {
    01393 struct activehosts *temp, *prev;    // temp var needed to scan the host list chain
    01394 struct addrinfo hints, *addrinfo, *ai_next; // temp var needed to translate between hostname to its address
    01395 int retval;
    01396
    01397     temp= activeHosts;
    01398     prev= NULL;
    01399
    01400     // retrieve the network address corresponding to 'host'
    01401     addrinfo = NULL;
    01402     memset(&hints, 0, sizeof (struct addrinfo) );
    01403     hints.ai_family = PF_UNSPEC;
    01404     hints.ai_socktype= SOCK_STREAM;
    01405
    01406     retval = getaddrinfo(host, "0", &hints, &addrinfo);
    01407     if (retval != 0)
    01408     {
    01409         snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
    01410         return -1;
    01411     }
    01412
    01413     while (temp)
    01414     {
    01415         ai_next= addrinfo;
    01416         while(ai_next)
    01417         {
    01418             if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr ) == 0)
    01419             {
    01420             struct rpcap_header header;
    01421
    01422                 // Close this connection
    01423                 rpcap_createhdr( &header, RPCAP_MSG_CLOSE, 0, 0);
    01424
    01425                 // I don't check for errors, since I'm going to close everything
    01426                 sock_send(temp->sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE);
    01427
    01428                 if (sock_close(temp->sockctrl, errbuf, PCAP_ERRBUF_SIZE) )
    01429                 {
    01430                     // To avoid inconsistencies in the number of sock_init()
    01431                     sock_cleanup();
    01432
    01433                     return -1;
    01434                 }
    01435
    01436                 if (prev)
    01437                     prev->next= temp->next;
    01438                 else
    01439                     activeHosts= temp->next;
    01440
    01441                 freeaddrinfo(addrinfo);
    01442
    01443                 free(temp);
    01444
    01445                 // To avoid inconsistencies in the number of sock_init()
    01446                 sock_cleanup();
    01447
    01448                 return 0;
    01449             }
    01450
    01451             ai_next= ai_next->ai_next;
    01452         }
    01453         prev= temp;
    01454         temp= temp->next;
    01455     }
    01456
    01457     if (addrinfo)
    01458         freeaddrinfo(addrinfo);
    01459
    01460     // To avoid inconsistencies in the number of sock_init()
    01461     sock_cleanup();
    01462
    01463     snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host you want to close the active connection is not known");
    01464     return -1;
    01465 }
    01466
    01467
    01489 void pcap_remoteact_cleanup()
    01490 {
    01491     // Very dirty, but it works
    01492     if (sockmain)
    01493     {
    01494         closesocket(sockmain);
    01495
    01496         // To avoid inconsistencies in the number of sock_init()
    01497         sock_cleanup();
    01498     }
    01499
    01500 }
    01501
    01502
    01526 int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf)
    01527 {
    01528 struct activehosts *temp;   // temp var needed to scan the host list chain
    01529 int len;
    01530 char hoststr[RPCAP_HOSTLIST_SIZE + 1];
    01531
    01532     temp= activeHosts;
    01533
    01534     len= 0;
    01535     *hostlist= 0;
    01536
    01537     while (temp)
    01538     {
    01539 //int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen)
    01540
    01541         // Get the numeric form of the name of the connecting host
    01542         if (sock_getascii_addrport( (struct sockaddr_storage *) &temp->host,hoststr,
    01543                 RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST, errbuf, PCAP_ERRBUF_SIZE) != -1)
    01544 //      if (getnameinfo( (struct sockaddr *) &temp->host, sizeof (struct sockaddr_storage), hoststr,
    01545 //              RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) )
    01546         {
    01547 //          sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
    01548             return -1;
    01549         }
    01550
    01551         len= len + strlen(hoststr) + 1 /* the separator */;
    01552
    01553         if (len >= size)
    01554         {
    01555             snprintf(errbuf, PCAP_ERRBUF_SIZE, "The string you provided is not able to keep "
    01556                 "the hostnames for all the active connections");
    01557             return -1;
    01558         }
    01559
    01560         strcat(hostlist, hoststr);
    01561         hostlist[len - 1]= sep;
    01562         hostlist[len]= 0;
    01563
    01564         temp= temp->next;
    01565     }
    01566
    01567     return 0;
    01568 }
    01569

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