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

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