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

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