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

# daemon.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.h>       // for libpcap/WinPcap calls
    00034 #include <pcap-int.h>   // for the pcap_t definition
    00035 #include <errno.h>      // for the errno variable
    00036 #include <stdlib.h>     // for malloc(), free(), ...
    00037 #include <string.h>     // for strlen(), ...
    00038 #include <pthread.h>
    00039 #include "pcap-remote.h"
    00040 #include "daemon.h"
    00041 #include "sockutils.h"  // for socket calls
    00042
    00043 #ifndef WIN32           // for select() and such
    00044 #include <unistd.h>
    00045 #include <sys/time.h>
    00046 #include <sys/types.h>
    00047 #include <pwd.h>        // for password management
    00048 #endif
    00049
    00050 #ifdef linux
    00051 #include <shadow.h>     // for password management
    00052 #endif
    00053
    00054
    00055
    00056 // Locally defined functions
    00057 int daemon_checkauth(SOCKET sockctrl, int nullAuthAllowed, char *errbuf);
    00058 int daemon_AuthUserPwd(char *username, char *password, char *errbuf);
    00059
    00060 int daemon_findalldevs(SOCKET sockctrl, char *errbuf);
    00061
    00062 int daemon_opensource(SOCKET sockctrl, char *source, int srclen, uint32 plen, char *errbuf);
    00063 pcap_t *daemon_startcapture(SOCKET sockctrl, pthread_t *threaddata, char *source, int active,
    00064                             struct rpcap_sampling *samp_param, uint32 plen, char *errbuf);
    00065 int daemon_endcapture(pcap_t *fp, pthread_t *threaddata, char *errbuf);
    00066
    00067 int daemon_updatefilter(pcap_t *fp, uint32 plen);
    00068 int daemon_unpackapplyfilter(pcap_t *fp, unsigned int *nread, int *plen, char *errbuf);
    00069
    00070 int daemon_getstats(pcap_t *fp);
    00071 int daemon_getstatsnopcap(SOCKET sockctrl, unsigned int ifdrops, unsigned int ifrecv,
    00072                           unsigned int krnldrop, unsigned int svrcapt, char *errbuf);
    00073
    00074 int daemon_setsampling(SOCKET sockctrl, struct rpcap_sampling *samp_param, int plen, char *errbuf);
    00075
    00076 void daemon_seraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage *sockaddrout);
    00077 void *daemon_thrdatamain(void *ptr);
    00078
    00079
    00080
    00081
    00082
    00083
    00084
    00097 void daemon_serviceloop( void *ptr )
    00098 {
    00099 char errbuf[PCAP_ERRBUF_SIZE + 1];      // keeps the error string, prior to be printed
    00100 char source[PCAP_BUF_SIZE];             // keeps the string that contains the interface to open
    00101 struct rpcap_header header;             // RPCAP message general header
    00102 pcap_t *fp= NULL;                       // pcap_t main variable
    00103 struct daemon_slpars *pars;             // parameters related to the present daemon loop
    00104
    00105 pthread_t threaddata= 0;                // handle to the 'read from daemon and send to client' thread
    00106
    00107 unsigned int ifdrops, ifrecv, krnldrop, svrcapt;    // needed to save the values of the statistics
    00108
    00109 struct rpcap_sampling samp_param;       // in case sampling has been requested
    00110
    00111 // Structures needed for the select() call
    00112 fd_set rfds;                        // set of socket descriptors we have to check
    00113 struct timeval tv;                  // maximum time the select() can block waiting for data
    00114 int retval;                         // select() return value
    00115
    00116
    00117     pars= (struct daemon_slpars *) ptr;
    00118
    00119     *errbuf= 0; // Initialize errbuf
    00120
    00121     // If we're in active mode, this is not a separate thread
    00122     if (! pars->isactive)
    00123     {
    00124         // Modify thread params so that it can be killed at any time
    00125         if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) )
    00126             goto end;
    00127         if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) )
    00128             goto end;
    00129     }
    00130
    00131 auth_again:
    00132     // If we're in active mode, we have to check for the initial timeout
    00133     if (!pars->isactive)
    00134     {
    00135         FD_ZERO(&rfds);
    00136         // We do not have to block here
    00137         tv.tv_sec = RPCAP_TIMEOUT_INIT;
    00138         tv.tv_usec = 0;
    00139
    00140         FD_SET(pars->sockctrl, &rfds);
    00141
    00142         retval = select(pars->sockctrl + 1, &rfds, NULL, NULL, &tv);
    00143         if (retval == -1)
    00144         {
    00145             sock_geterror("select(): ", errbuf, PCAP_ERRBUF_SIZE);
    00146             rpcap_senderror(pars->sockctrl, errbuf, PCAP_ERR_NETW, NULL);
    00147             goto end;
    00148         }
    00149
    00150         // The timeout has expired
    00151         // So, this was a fake connection. Drop it down
    00152         if (retval == 0)
    00153         {
    00154             rpcap_senderror(pars->sockctrl, "The RPCAP initial timeout has expired", PCAP_ERR_INITTIMEOUT, NULL);
    00155             goto end;
    00156         }
    00157     }
    00158
    00159
    00160     retval= daemon_checkauth(pars->sockctrl, pars->nullAuthAllowed, errbuf);
    00161
    00162     if (retval)
    00163     {
    00164         // the other user requested to close the connection
    00165         // It can be also the case of 'active mode', in which this host is not
    00166         // allowed to connect to the other peer; in that case, it drops down the connection
    00167         if (retval == -3)
    00168             goto end;
    00169
    00170         // It can be an authentication failure or an unrecoverable error
    00171         rpcap_senderror(pars->sockctrl, errbuf, PCAP_ERR_AUTH, NULL);
    00172
    00173         // authentication error
    00174         if (retval == -2)
    00175         {
    00176             // suspend for 1 sec
    00177             // WARNING: this day is inserted only in this point; if the user drops down the connection
    00178             // and it connects again, this suspension time does not have any effects.
    00179             pthread_suspend(RPCAP_SUSPEND_WRONGAUTH*1000);
    00180             goto auth_again;
    00181         }
    00182
    00183          // Unrecoverable error
    00184         if (retval == -1)
    00185             goto end;
    00186     }
    00187
    00188     while (1)
    00189     {
    00190     int retval;
    00191
    00192         errbuf[0]= 0;   // clear errbuf
    00193
    00194         // Avoid zombies connections; check if the connection is opens but no commands are performed
    00195         // from more than RPCAP_TIMEOUT_RUNTIME
    00196         // Conditions:
    00197         // - I have to be in normal mode (no active mode)
    00198         // - if the device is open, I don't have to be in the middle of a capture (fp->rmt_sockdata)
    00199         // - if the device is closed, I have always to check if a new command arrives
    00200         //
    00201         // Be carefully: the capture can have been started, but an error occurred (so fp != NULL, but
    00202         //  rmt_sockdata is 0
    00203         if ( (!pars->isactive) &&  ( (fp == NULL) || ( (fp != NULL) && (fp->rmt_sockdata == 0) ) ))
    00204         {
    00205             // Check for the initial timeout
    00206             FD_ZERO(&rfds);
    00207             // We do not have to block here
    00208             tv.tv_sec = RPCAP_TIMEOUT_RUNTIME;
    00209             tv.tv_usec = 0;
    00210
    00211             FD_SET(pars->sockctrl, &rfds);
    00212
    00213             retval = select(pars->sockctrl + 1, &rfds, NULL, NULL, &tv);
    00214             if (retval == -1)
    00215             {
    00216                 sock_geterror("select(): ", errbuf, PCAP_ERRBUF_SIZE);
    00217                 rpcap_senderror(pars->sockctrl, errbuf, PCAP_ERR_NETW, NULL);
    00218                 goto end;
    00219             }
    00220
    00221             // The timeout has expired
    00222             // So, this was a fake connection. Drop it down
    00223             if (retval == 0)
    00224             {
    00225                 SOCK_ASSERT("The RPCAP runtime timeout has expired", 1);
    00226                 rpcap_senderror(pars->sockctrl, "The RPCAP runtime timeout has expired", PCAP_ERR_RUNTIMETIMEOUT, NULL);
    00227                 goto end;
    00228             }
    00229         }
    00230
    00231         if (sock_recv(pars->sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00232             goto end;
    00233
    00234         // Checks if the message is correct
    00235         // In case it is wrong, it discard the data
    00236         retval= rpcap_checkmsg(errbuf, pars->sockctrl, &header,
    00237             RPCAP_MSG_FINDALLIF_REQ,
    00238             RPCAP_MSG_OPEN_REQ,
    00239             RPCAP_MSG_STARTCAP_REQ,
    00240             RPCAP_MSG_UPDATEFILTER_REQ,
    00241             RPCAP_MSG_STATS_REQ,
    00242             RPCAP_MSG_ENDCAP_REQ,
    00243             RPCAP_MSG_SETSAMPLING_REQ,
    00244             RPCAP_MSG_CLOSE,
    00245             RPCAP_MSG_ERROR,
    00246             0);
    00247
    00248         switch (retval)
    00249         {
    00250             case -3:    // Unrecoverable network error
    00251                 goto end;   // Do nothing; just exit from findalldevs; the error code is already into the errbuf
    00252
    00253             case -2:    // The other endpoint send a message that is not allowed here
    00254             {
    00255                 rpcap_senderror(pars->sockctrl, "The RPCAP daemon received a message that is not valid", PCAP_ERR_WRONGMSG, errbuf);
    00256             }
    00257             case -1:    // The other endpoint has a version number that is not compatible with our
    00258             {
    00259                 rpcap_senderror(pars->sockctrl, "RPCAP version number mismatch", PCAP_ERR_WRONGVER, errbuf);
    00260             }
    00261             break;
    00262
    00263             case RPCAP_MSG_FINDALLIF_REQ:
    00264             {
    00265                 // Checks that the header does not contain other data; if so, discard it
    00266                 if (ntohl(header.plen))
    00267                     sock_discard(pars->sockctrl, ntohl(header.plen), errbuf, PCAP_ERRBUF_SIZE);
    00268
    00269                 if (daemon_findalldevs(pars->sockctrl, errbuf) )
    00270                     SOCK_ASSERT(errbuf, 1);
    00271
    00272                 break;
    00273             };
    00274
    00275             case RPCAP_MSG_OPEN_REQ:
    00276             {
    00277                 retval= daemon_opensource(pars->sockctrl, source, sizeof(source), ntohl(header.plen), errbuf);
    00278
    00279                 if (retval == -1)
    00280                     SOCK_ASSERT(errbuf, 1);
    00281
    00282                 break;
    00283             };
    00284
    00285             case RPCAP_MSG_SETSAMPLING_REQ:
    00286             {
    00287                 retval= daemon_setsampling(pars->sockctrl, &samp_param, ntohl(header.plen), errbuf);
    00288
    00289                 if (retval == -1)
    00290                     SOCK_ASSERT(errbuf, 1);
    00291
    00292                 break;
    00293             };
    00294
    00295             case RPCAP_MSG_STARTCAP_REQ:
    00296             {
    00297                 fp= daemon_startcapture(pars->sockctrl, &threaddata, source, pars->isactive, &samp_param, ntohl(header.plen), errbuf);
    00298
    00299                 if (fp == NULL)
    00300                     SOCK_ASSERT(errbuf, 1);
    00301
    00302                 break;
    00303             };
    00304
    00305             case RPCAP_MSG_UPDATEFILTER_REQ:
    00306             {
    00307                 if (fp)
    00308                 {
    00309                     if (daemon_updatefilter(fp, ntohl(header.plen)) )
    00310                         SOCK_ASSERT(fp->errbuf, 1);
    00311                 }
    00312                 else
    00313                 {
    00314                     rpcap_senderror(pars->sockctrl, "Device not opened. Cannot update filter", PCAP_ERR_UPDATEFILTER, errbuf);
    00315                 }
    00316
    00317                 break;
    00318             };
    00319
    00320             case RPCAP_MSG_STATS_REQ:
    00321             {
    00322                 // Checks that the header does not contain other data; if so, discard it
    00323                 if (ntohl(header.plen))
    00324                     sock_discard(pars->sockctrl, ntohl(header.plen), errbuf, PCAP_ERRBUF_SIZE);
    00325
    00326                 if (fp)
    00327                 {
    00328                     if (daemon_getstats(fp) )
    00329                         SOCK_ASSERT(fp->errbuf, 1);
    00330                 }
    00331                 else
    00332                 {
    00333                     SOCK_ASSERT("GetStats: this call should't be allowed here", 1);
    00334
    00335                     if (daemon_getstatsnopcap(pars->sockctrl, ifdrops, ifrecv, krnldrop, svrcapt, errbuf) )
    00336                         SOCK_ASSERT(errbuf, 1);
    00337                     // we have to keep compatibility with old applications, which ask for statistics
    00338                     // also when the capture has already stopped
    00339
    00340 //                  rpcap_senderror(pars->sockctrl, "Device not opened. Cannot get statistics", PCAP_ERR_GETSTATS, errbuf);
    00341                 }
    00342
    00343                 break;
    00344             };
    00345
    00346             case RPCAP_MSG_ENDCAP_REQ:      // The other endpoint close the current capture session
    00347             {
    00348                 if (fp)
    00349                 {
    00350                 struct pcap_stat stats;
    00351
    00352                     // Save statistics (we can need them in the future)
    00353                     if (pcap_stats(fp, &stats) )
    00354                     {
    00355                         ifdrops= stats.ps_ifdrop;
    00356                         ifrecv= stats.ps_recv;
    00357                         krnldrop= stats.ps_drop;
    00358                         svrcapt= fp->md.TotCapt;
    00359                     }
    00360                     else
    00361                         ifdrops= ifrecv= krnldrop= svrcapt= 0;
    00362
    00363                     if ( daemon_endcapture(fp, &threaddata, errbuf) )
    00364                         SOCK_ASSERT(errbuf, 1);
    00365                     fp= NULL;
    00366                 }
    00367                 else
    00368                 {
    00369                     rpcap_senderror(pars->sockctrl, "Device not opened. Cannot close the capture", PCAP_ERR_ENDCAPTURE, errbuf);
    00370                 }
    00371                 break;
    00372             };
    00373
    00374             case RPCAP_MSG_CLOSE:       // The other endpoint close the pcap session
    00375             {
    00376                 // signal to the main that the user closed the control connection
    00377                 // This is used only in case of active mode
    00378                 pars->activeclose= 1;
    00379                 SOCK_ASSERT("The other end system asked to close the connection.", 1);
    00380                 goto end;
    00381                 break;
    00382             };
    00383
    00384             case RPCAP_MSG_ERROR:       // The other endpoint reported an error
    00385             {
    00386                 // Do nothing; just exit; the error code is already into the errbuf
    00387                 SOCK_ASSERT(errbuf, 1);
    00388                 break;
    00389             };
    00390
    00391             default:
    00392             {
    00393                 SOCK_ASSERT("Internal error.", 1);
    00394                 break;
    00395             };
    00396         }
    00397     }
    00398
    00399 end:
    00400     // The child thread is about to end
    00401
    00402     // perform pcap_t cleanup, in case it has not been done
    00403     if (fp)
    00404     {
    00405         if (threaddata)
    00406         {
    00407             pthread_cancel(threaddata);
    00408             threaddata= 0;
    00409         }
    00410         if (fp->rmt_sockdata)
    00411         {
    00412             sock_close(fp->rmt_sockdata, NULL, 0);
    00413             fp->rmt_sockdata= 0;
    00414         }
    00415         pcap_close(fp);
    00416         fp= NULL;
    00417     }
    00418
    00419     // Print message and exit
    00420     SOCK_ASSERT("I'm exiting from the child loop", 1);
    00421     SOCK_ASSERT(errbuf, 1);
    00422
    00423     if (!pars->isactive)
    00424     {
    00425         if (pars->sockctrl)
    00426             sock_close(pars->sockctrl, NULL, 0);
    00427
    00428         free(pars);
    00429 #ifdef WIN32
    00430         pthread_exit(0);
    00431 #endif
    00432     }
    00433 }
    00434
    00435
    00459 int daemon_checkauth(SOCKET sockctrl, int nullAuthAllowed, char *errbuf)
    00460 {
    00461 struct rpcap_header header;         // RPCAP message general header
    00462 int retval;                         // generic return value
    00463 unsigned int nread;                 // number of bytes of the payload read from the socket
    00464 struct rpcap_auth auth;             // RPCAP authentication header
    00465 char *string1, *string2;            // two strings exchanged by the authentication message
    00466 unsigned int plen;                  // length of the payload
    00467 int retcode;                        // the value we have to return to the caller
    00468
    00469     if (sock_recv(sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00470         return -1;
    00471
    00472     plen= ntohl(header.plen);
    00473
    00474     retval= rpcap_checkmsg(errbuf, sockctrl, &header,
    00475         RPCAP_MSG_AUTH_REQ,
    00476         RPCAP_MSG_CLOSE,
    00477         0);
    00478
    00479     if (retval != RPCAP_MSG_AUTH_REQ)
    00480     {
    00481         switch (retval)
    00482         {
    00483             case -3:    // Unrecoverable network error
    00484                 return -1;  // Do nothing; just exit; the error code is already into the errbuf
    00485
    00486             case -2:    // The other endpoint send a message that is not allowed here
    00487             case -1:    // The other endpoint has a version number that is not compatible with our
    00488                 return -2;
    00489
    00490             case RPCAP_MSG_CLOSE:
    00491             {
    00492                 // Check if all the data has been read; if not, discard the data in excess
    00493                 if (ntohl(header.plen) )
    00494                 {
    00495                     if (sock_discard(sockctrl, ntohl(header.plen), NULL, 0) )
    00496                     {
    00497                         retcode= -1;
    00498                         goto error;
    00499                     }
    00500                 }
    00501                 return -3;
    00502             };
    00503
    00504             case RPCAP_MSG_ERROR:
    00505                 return -3;
    00506
    00507             default:
    00508             {
    00509                 SOCK_ASSERT("Internal error.", 1);
    00510                 retcode= -2;
    00511                 goto error;
    00512             };
    00513         }
    00514     }
    00515
    00516     // If it comes here, it means that we have an authentication request message
    00517     if ( (nread= sock_recv(sockctrl, (char *) &auth, sizeof(struct rpcap_auth), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    00518     {
    00519         retcode= -1;
    00520         goto error;
    00521     }
    00522
    00523     switch (ntohs(auth.type) )
    00524     {
    00525         case RPCAP_RMTAUTH_NULL:
    00526         {
    00527             if (!nullAuthAllowed)
    00528             {
    00529                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed; NULL autentication not permitted.");
    00530                 retcode= -2;
    00531                 goto error;
    00532             }
    00533             break;
    00534         }
    00535
    00536         case RPCAP_RMTAUTH_PWD:
    00537         {
    00538         int len1, len2;
    00539
    00540             len1= ntohs(auth.slen1);
    00541             len2= ntohs(auth.slen2);
    00542
    00543             string1= (char *) malloc (len1 + 1);
    00544             string2= (char *) malloc (len2 + 1);
    00545
    00546             if ( (string1 == NULL) || (string2 == NULL) )
    00547             {
    00548                 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    00549                 retcode= -1;
    00550                 goto error;
    00551             }
    00552
    00553             if ( (nread+= sock_recv(sockctrl, string1, len1, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    00554             {
    00555                 retcode= -1;
    00556                 goto error;
    00557             }
    00558             if ( (nread+= sock_recv(sockctrl, string2, len2, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    00559             {
    00560                 retcode= -1;
    00561                 goto error;
    00562             }
    00563
    00564             string1[len1]= 0;
    00565             string2[len2]= 0;
    00566
    00567             if (daemon_AuthUserPwd(string1, string2, errbuf) )
    00568             {
    00569                 retcode= -2;
    00570                 goto error;
    00571             }
    00572
    00573             break;
    00574             }
    00575
    00576         default:
    00577             snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
    00578             retcode= -2;
    00579             goto error;
    00580     }
    00581
    00582
    00583     // Check if all the data has been read; if not, discard the data in excess
    00584     if (nread != plen)
    00585     {
    00586         if (sock_discard(sockctrl, plen - nread, NULL, 0) )
    00587         {
    00588             retcode= -1;
    00589             goto error;
    00590         }
    00591     }
    00592
    00593     rpcap_createhdr(&header, RPCAP_MSG_AUTH_REPLY, 0, 0);
    00594
    00595     // Send the ok message back
    00596     if ( sock_send(sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
    00597     {
    00598         retcode= -1;
    00599         goto error;
    00600     }
    00601
    00602     return 0;
    00603
    00604 error:
    00605     // Check if all the data has been read; if not, discard the data in excess
    00606     if (nread != plen)
    00607         sock_discard(sockctrl, plen - nread, NULL, 0);
    00608
    00609     return retcode;
    00610 }
    00611
    00612
    00613
    00614 int daemon_AuthUserPwd(char *username, char *password, char *errbuf)
    00615 {
    00616 #ifdef WIN32
    00617     /*
    00618         Warning: the user which launches the process must have the SE_TCB_NAME right.
    00619         This corresponds to have the "Act as part of the Operating System" turined on
    00620         (administrative tools, local security settings, local policies, user right assignment)
    00621         However, it seems to me that if you run it as a service, this right should be
    00622         provided by default.
    00623     */
    00624     HANDLE Token;
    00625     if (LogonUser(username, ".", password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &Token) == 0)
    00626     {
    00627     int error;
    00628
    00629         error = GetLastError();
    00630         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
    00631             PCAP_ERRBUF_SIZE, NULL);
    00632
    00633         return -1;
    00634     }
    00635
    00636     // This call should change the current thread to the selected user.
    00637     // I didn't test it.
    00638     if (ImpersonateLoggedOnUser(Token) == 0)
    00639     {
    00640     int error;
    00641
    00642         error = GetLastError();
    00643         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
    00644             PCAP_ERRBUF_SIZE, NULL);
    00645
    00646         CloseHandle(Token);
    00647         return -1;
    00648     }
    00649
    00650     CloseHandle(Token);
    00651     return 0;
    00652
    00653 #else
    00654 /*  Standard user authentication:
    00655         http://www.unixpapa.com/incnote/passwd.html
    00656     Problem: it is not able to merge the standard pwd file with the shadow one
    00657
    00658     Shadow user authentication:
    00659         http://www.tldp.org/HOWTO/Shadow-Password-HOWTO-8.html
    00660     Problem: the program must either (1) run as root, or (2) run as user, but it
    00661     must be owned by root and must be SUID root (chmod u+s rpcapd)
    00662 */
    00663
    00664     struct passwd *user;
    00665 #ifdef linux
    00666     struct spwd *usersp;
    00667 #endif
    00668
    00669     // This call is needed to get the uid
    00670     if ((user= getpwnam(username)) == NULL)
    00671     {
    00672         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: no such user");
    00673         return -1;
    00674     }
    00675
    00676 #ifdef linux
    00677     // This call is needed to get the password; otherwise 'x' is returned
    00678     if ((usersp= getspnam(username)) == NULL)
    00679     {
    00680         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: no such user");
    00681         return -1;
    00682     }
    00683
    00684     if (strcmp(usersp->sp_pwdp, (char *) crypt(password, usersp->sp_pwdp) ) != 0)
    00685     {
    00686         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: password incorrect");
    00687         return -1;
    00688     }
    00689 #endif
    00690
    00691 #ifdef bsd
    00692     if (strcmp(user->pw_passwd, (char *) crypt(password, user->pw_passwd) ) != 0)
    00693     {
    00694         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: password incorrect");
    00695         return -1;
    00696     }
    00697 #endif
    00698
    00699     if (setuid(user->pw_uid) )
    00700     {
    00701         snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s", pcap_strerror(errno) );
    00702         return -1;
    00703     }
    00704
    00705 /*  if (setgid(user->pw_gid) )
    00706     {
    00707         SOCK_ASSERT("setgid failed", 1);
    00708         snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s", pcap_strerror(errno) );
    00709         return -1;
    00710     }
    00711 */
    00712     return 0;
    00713
    00714 #endif
    00715
    00716 }
    00717
    00718
    00719
    00720 // PORTING WARNING We assume u_int is a 32bit value
    00721 int daemon_findalldevs(SOCKET sockctrl, char *errbuf)
    00722 {
    00723 char sendbuf[RPCAP_NETBUF_SIZE];            // temporary buffer in which data to be sent is buffered
    00724 int sendbufidx= 0;                          // index which keeps the number of bytes currently buffered
    00725 pcap_if_t *alldevs;                         // pointer to the heade of the interface chain
    00726 pcap_if_t *d;                               // temp pointer neede to scan the interface chain
    00727 uint16 plen= 0;                             // length of the payload of this message
    00728 struct pcap_addr *address;                  // pcap structure that keeps a network address of an interface
    00729 struct rpcap_findalldevs_if *findalldevs_if;// rpcap structure that packet all the data of an interface together
    00730 uint16 nif= 0;                              // counts the number of interface listed
    00731
    00732     // Retrieve the device list
    00733     if (pcap_findalldevs(&alldevs, errbuf) == -1)
    00734     {
    00735         rpcap_senderror(sockctrl, errbuf, PCAP_ERR_FINDALLIF, NULL);
    00736         return -1;
    00737     }
    00738
    00739     if (alldevs == NULL)
    00740     {
    00741         rpcap_senderror(sockctrl,
    00742             "No interfaces found! Make sure libpcap/WinPcap is properly installed"
    00743             " and you have the right to access to the remote device.",
    00744             PCAP_ERR_NOREMOTEIF,
    00745             errbuf);
    00746         return -1;
    00747     }
    00748
    00749     // checks the number of interfaces and it computes the total length of the payload
    00750     for (d= alldevs; d != NULL; d= d->next)
    00751     {
    00752         nif++;
    00753
    00754         if (d->description)
    00755             plen+= strlen(d->description);
    00756         if (d->name)
    00757             plen+= strlen(d->name);
    00758
    00759         plen+= sizeof(struct rpcap_findalldevs_if);
    00760
    00761         for (address= d->addresses; address != NULL; address= address->next)
    00762             plen+= ( sizeof(struct sockaddr_storage) * 4);
    00763     }
    00764
    00765     // RPCAP findalldevs command
    00766     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
    00767         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00768         return -1;
    00769
    00770     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_FINDALLIF_REPLY, nif, plen);
    00771
    00772     // send the interface list
    00773     for (d= alldevs; d != NULL; d= d->next)
    00774     {
    00775     uint16 lname, ldescr;
    00776
    00777         findalldevs_if= (struct rpcap_findalldevs_if *) &sendbuf[sendbufidx];
    00778
    00779         if ( sock_bufferize(NULL, sizeof(struct rpcap_findalldevs_if), NULL,
    00780             &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00781             return -1;
    00782
    00783         memset(findalldevs_if, 0, sizeof(struct rpcap_findalldevs_if) );
    00784
    00785         if (d->description) ldescr= (short) strlen(d->description);
    00786         else ldescr= 0;
    00787         if (d->name) lname= (short) strlen(d->name);
    00788         else lname= 0;
    00789
    00790         findalldevs_if->desclen= htons(ldescr);
    00791         findalldevs_if->namelen= htons(lname);
    00792         findalldevs_if->flags= htonl(d->flags);
    00793
    00794         for (address= d->addresses; address != NULL; address= address->next)
    00795             findalldevs_if->naddr++;
    00796
    00797         findalldevs_if->naddr= htons(findalldevs_if->naddr);
    00798
    00799         if (sock_bufferize(d->name, lname, sendbuf, &sendbufidx,
    00800             RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00801             return -1;
    00802
    00803         if (sock_bufferize(d->description, ldescr, sendbuf, &sendbufidx,
    00804             RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00805             return -1;
    00806
    00807         // send all addresses
    00808         for (address= d->addresses; address != NULL; address= address->next)
    00809         {
    00810         struct sockaddr_storage *sockaddr;
    00811
    00812             sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
    00813             if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL,
    00814                 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00815                 return -1;
    00816             daemon_seraddr( (struct sockaddr_storage *) address->addr, sockaddr);
    00817
    00818             sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
    00819             if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL,
    00820                 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00821                 return -1;
    00822             daemon_seraddr( (struct sockaddr_storage *) address->netmask, sockaddr);
    00823
    00824             sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
    00825             if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL,
    00826                 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00827                 return -1;
    00828             daemon_seraddr( (struct sockaddr_storage *) address->broadaddr, sockaddr);
    00829
    00830             sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
    00831             if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL,
    00832                 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00833                 return -1;
    00834             daemon_seraddr( (struct sockaddr_storage *) address->dstaddr, sockaddr);
    00835         }
    00836     }
    00837
    00838     // Send a final command that says "now send it!"
    00839     if (sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00840         return -1;
    00841
    00842     // We do no longer need the device list. Free it
    00843     pcap_freealldevs(alldevs);
    00844
    00845     // everything is fine
    00846     return 0;
    00847 }
    00848
    00849
    00850
    00851
    00852
    00853 /*
    00854     \param plen: the length of the current message (needed in order to be able
    00855     to discard excess data in the message, if present)
    00856 */
    00857 int daemon_opensource(SOCKET sockctrl, char *source, int srclen, uint32 plen, char *errbuf)
    00858 {
    00859 pcap_t *fp= NULL;                   // pcap_t main variable
    00860 unsigned int nread;                 // number of bytes of the payload read from the socket
    00861 char sendbuf[RPCAP_NETBUF_SIZE];    // temporary buffer in which data to be sent is buffered
    00862 int sendbufidx= 0;                  // index which keeps the number of bytes currently buffered
    00863 struct rpcap_openreply *openreply;  // open reply message
    00864
    00865
    00866     strcpy(source, PCAP_SRC_IF_STRING);
    00867
    00868     if (srclen <= (int) (strlen(PCAP_SRC_IF_STRING) + plen) )
    00869     {
    00870         rpcap_senderror(sockctrl, "Source string too long", PCAP_ERR_OPEN, NULL);
    00871         return -1;
    00872     }
    00873
    00874     if ( (nread= sock_recv(sockctrl, &source[strlen(PCAP_SRC_IF_STRING)], plen, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    00875         return -1;
    00876
    00877     // Check if all the data has been read; if not, discard the data in excess
    00878     if (nread != plen)
    00879         sock_discard(sockctrl, plen - nread, NULL, 0);
    00880
    00881     // Puts a '0' to terminate the source string
    00882     source[strlen(PCAP_SRC_IF_STRING) + plen]= 0;
    00883
    00884     // Open the selected device
    00885     // This is a fake open, since we do that only to get the needed parameters, then we close the device again
    00886     if ( (fp= pcap_open(source,
    00887             1500 /* fake snaplen */,
    00888             0 /* no promis */,
    00889             1000 /* fake timeout */,
    00890             NULL /* local device, so no auth */,
    00891             errbuf)) == NULL)
    00892     {
    00893         rpcap_senderror(sockctrl, errbuf, PCAP_ERR_OPEN, NULL);
    00894         return -1;
    00895     }
    00896
    00897
    00898     // Now, I can send a RPCAP open reply message
    00899     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
    00900         RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00901         goto error;
    00902
    00903     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_OPEN_REPLY, 0, sizeof(struct rpcap_openreply) );
    00904
    00905     openreply= (struct rpcap_openreply *) &sendbuf[sendbufidx];
    00906
    00907     if ( sock_bufferize(NULL, sizeof(struct rpcap_openreply), NULL, &sendbufidx,
    00908         RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00909         goto error;
    00910
    00911     memset(openreply, 0, sizeof(struct rpcap_openreply) );
    00912     openreply->linktype= htonl(fp->linktype);
    00913     openreply->tzoff= htonl(fp->tzoff);
    00914
    00915     if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00916         goto error;
    00917
    00918     // I have to close the device again, since it has been opened with wrong parameters
    00919     pcap_close(fp);
    00920     fp= NULL;
    00921
    00922     return 0;
    00923
    00924 error:
    00925     if (fp)
    00926     {
    00927         pcap_close(fp);
    00928         fp= NULL;
    00929     }
    00930
    00931     return -1;
    00932 }
    00933
    00934
    00935
    00936
    00937
    00938 /*
    00939     \param plen: the length of the current message (needed in order to be able
    00940     to discard excess data in the message, if present)
    00941 */
    00942 pcap_t *daemon_startcapture(SOCKET sockctrl, pthread_t *threaddata, char *source, int active, struct rpcap_sampling *samp_param, uint32 plen, char *errbuf)
    00943 {
    00944 char portdata[PCAP_BUF_SIZE];       // temp variable needed to derive the data port
    00945 char peerhost[PCAP_BUF_SIZE];       // temp variable needed to derive the host name of our peer
    00946 pcap_t *fp= NULL;                   // pcap_t main variable
    00947 unsigned int nread;                 // number of bytes of the payload read from the socket
    00948 char sendbuf[RPCAP_NETBUF_SIZE];    // temporary buffer in which data to be sent is buffered
    00949 int sendbufidx= 0;                  // index which keeps the number of bytes currently buffered
    00950
    00951 // socket-related variables
    00952 SOCKET sockdata= 0;                 // socket descriptor of the data connection
    00953 struct addrinfo hints;              // temp, needed to open a socket connection
    00954 struct addrinfo *addrinfo;          // temp, needed to open a socket connection
    00955 struct sockaddr_storage saddr;      // temp, needed to retrieve the network data port chosen on the local machine
    00956 socklen_t saddrlen;                 // temp, needed to retrieve the network data port chosen on the local machine
    00957
    00958 pthread_attr_t detachedAttribute;   // temp, needed to set the created thread as detached
    00959
    00960 // RPCAP-related variables
    00961 struct rpcap_startcapreq startcapreq;       // start capture request message
    00962 struct rpcap_startcapreply *startcapreply;  // start capture reply message
    00963 int serveropen_dp;                          // keeps who is going to open the data connection
    00964
    00965     addrinfo= NULL;
    00966
    00967     if ( (nread= sock_recv(sockctrl, (char *) &startcapreq, sizeof(struct rpcap_startcapreq), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    00968         return NULL;
    00969
    00970     startcapreq.flags= ntohs(startcapreq.flags);
    00971
    00972     // Open the selected device
    00973     if ( (fp= pcap_open(source,
    00974             ntohl(startcapreq.snaplen),
    00975             (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_PROMISC) ? PCAP_OPENFLAG_PROMISCUOUS : 0 /* local device, other flags not needed */,
    00976             ntohl(startcapreq.read_timeout),
    00977             NULL /* local device, so no auth */,
    00978             errbuf)) == NULL)
    00979     {
    00980         rpcap_senderror(sockctrl, errbuf, PCAP_ERR_OPEN, NULL);
    00981         return NULL;
    00982     }
    00983
    00984     // Apply sampling parameters
    00985     fp->rmt_samp.method= samp_param->method;
    00986     fp->rmt_samp.value= samp_param->value;
    00987
    00988     /*
    00989     We're in active mode if:
    00990     - we're using TCP, and the user wants us to be in active mode
    00991     - we're using UDP
    00992     */
    00993     serveropen_dp= (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_SERVEROPEN) || (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) || active;
    00994
    00995     /*
    00996     Gets the sockaddr structure referred to the other peer in the ctrl connection
    00997
    00998     We need that because:
    00999     - if we're in passive mode, we need to know the address family we want to use
    01000     (the same used for the ctrl socket)
    01001     - if we're in active mode, we need to know the network address of the other host
    01002     we want to connect to
    01003     */
    01004     saddrlen = sizeof(struct sockaddr_storage);
    01005     if (getpeername(sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
    01006     {
    01007         sock_geterror("getpeername(): ", errbuf, PCAP_ERRBUF_SIZE);
    01008         goto error;
    01009     }
    01010
    01011     memset(&hints, 0, sizeof(struct addrinfo) );
    01012     hints.ai_socktype = (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
    01013     hints.ai_family = saddr.ss_family;
    01014
    01015     // Now we have to create a new socket to send packets
    01016     if (serveropen_dp)      // Data connection is opened by the server toward the client
    01017     {
    01018         sprintf(portdata, "%d", ntohs(startcapreq.portdata) );
    01019
    01020         // Get the name of the other peer (needed to connect to that specific network address)
    01021         if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, peerhost,
    01022                 sizeof(peerhost), NULL, 0, NI_NUMERICHOST) )
    01023         {
    01024             sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
    01025             goto error;
    01026         }
    01027
    01028         if (sock_initaddress(peerhost, portdata, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01029             goto error;
    01030
    01031         if ( (sockdata= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    01032             goto error;
    01033     }
    01034     else        // Data connection is opened by the client toward the server
    01035     {
    01036         hints.ai_flags = AI_PASSIVE;
    01037
    01038         // Let's the server socket pick up a free network port for us
    01039         if (sock_initaddress(NULL, "0", &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01040             goto error;
    01041
    01042         if ( (sockdata= sock_open(addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    01043             goto error;
    01044
    01045         // get the complete sockaddr structure used in the data connection
    01046         saddrlen = sizeof(struct sockaddr_storage);
    01047         if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
    01048         {
    01049             sock_geterror("getsockname(): ", errbuf, PCAP_ERRBUF_SIZE);
    01050             goto error;
    01051         }
    01052
    01053         // Get the local port the system picked up
    01054         if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, NULL,
    01055                 0, portdata, sizeof(portdata), NI_NUMERICSERV) )
    01056         {
    01057             sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
    01058             goto error;
    01059         }
    01060     }
    01061
    01062     // addrinfo is no longer used
    01063     freeaddrinfo(addrinfo);
    01064     addrinfo= NULL;
    01065
    01066     // save the socket ID for the next calls
    01067     fp->rmt_sockctrl= sockctrl; // Needed to send an error on the ctrl connection
    01068
    01069     // Now I can set the filter
    01070     if ( daemon_unpackapplyfilter(fp, &nread, &plen, errbuf) )
    01071         goto error;
    01072
    01073
    01074     // Now, I can send a RPCAP start capture reply message
    01075     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
    01076         RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01077         goto error;
    01078
    01079     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STARTCAP_REPLY, 0, sizeof(struct rpcap_startcapreply) );
    01080
    01081     startcapreply= (struct rpcap_startcapreply *) &sendbuf[sendbufidx];
    01082
    01083     if ( sock_bufferize(NULL, sizeof(struct rpcap_startcapreply), NULL,
    01084         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01085         goto error;
    01086
    01087     memset(startcapreply, 0, sizeof(struct rpcap_startcapreply) );
    01088     startcapreply->bufsize= htonl(fp->bufsize);
    01089
    01090     if (!serveropen_dp)
    01091     {
    01092         sscanf(portdata, "%d", (int *) &(startcapreply->portdata) );
    01093         startcapreply->portdata= htons(startcapreply->portdata);
    01094     }
    01095
    01096     if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01097         goto error;
    01098
    01099     if (!serveropen_dp)
    01100     {
    01101     SOCKET socktemp;    // We need another socket, since we're going to accept() a connection
    01102
    01103         // Connection creation
    01104         saddrlen = sizeof(struct sockaddr_storage);
    01105
    01106         socktemp= accept(sockdata, (struct sockaddr *) &saddr, &saddrlen);
    01107
    01108         if (socktemp == -1)
    01109         {
    01110             sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
    01111             goto error;
    01112         }
    01113
    01114         // Now that I accepted the connection, the server socket is no longer needed
    01115         sock_close(sockdata, errbuf, PCAP_ERRBUF_SIZE);
    01116         sockdata= socktemp;
    01117     }
    01118
    01119     fp->rmt_sockdata= sockdata;
    01120
    01121     /* GV we need this to create the thread as detached. */
    01122     /* GV otherwise, the thread handle is not destroyed  */
    01123     pthread_attr_init(&detachedAttribute);
    01124     pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED);
    01125
    01126     // Now we have to create a new thread to receive packets
    01127     if ( pthread_create(threaddata, &detachedAttribute, (void *) daemon_thrdatamain, (void *) fp) )
    01128     {
    01129         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread");
    01130         pthread_attr_destroy(&detachedAttribute);
    01131         goto error;
    01132     }
    01133
    01134     pthread_attr_destroy(&detachedAttribute);
    01135     // Check if all the data has been read; if not, discard the data in excess
    01136     if (nread != plen)
    01137         sock_discard(sockctrl, plen - nread, NULL, 0);
    01138
    01139     return fp;
    01140
    01141 error:
    01142     rpcap_senderror(sockctrl, errbuf, PCAP_ERR_STARTCAPTURE, NULL);
    01143
    01144     if (addrinfo)
    01145         freeaddrinfo(addrinfo);
    01146
    01147     if (threaddata)
    01148         pthread_cancel(*threaddata);
    01149
    01150     if (sockdata)
    01151         sock_close(sockdata, NULL, 0);
    01152
    01153     // Check if all the data has been read; if not, discard the data in excess
    01154     if (nread != plen)
    01155         sock_discard(sockctrl, plen - nread, NULL, 0);
    01156
    01157     if (fp)
    01158     {
    01159         pcap_close(fp);
    01160         fp= NULL;
    01161     }
    01162
    01163     return NULL;
    01164 }
    01165
    01166
    01167
    01168 int daemon_endcapture(pcap_t *fp, pthread_t *threaddata, char *errbuf)
    01169 {
    01170 struct rpcap_header header;
    01171 SOCKET sockctrl;
    01172
    01173     if (threaddata)
    01174     {
    01175         pthread_cancel(*threaddata);
    01176         threaddata= 0;
    01177     }
    01178     if (fp->rmt_sockdata)
    01179     {
    01180         sock_close(fp->rmt_sockdata, NULL, 0);
    01181         fp->rmt_sockdata= 0;
    01182     }
    01183
    01184     sockctrl= fp->rmt_sockctrl;
    01185
    01186     pcap_close(fp);
    01187     fp= NULL;
    01188
    01189     rpcap_createhdr( &header, RPCAP_MSG_ENDCAP_REPLY, 0, 0);
    01190
    01191     if ( sock_send(sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
    01192         return -1;
    01193
    01194     return 0;
    01195 }
    01196
    01197
    01198
    01199 int daemon_unpackapplyfilter(pcap_t *fp, unsigned int *nread, int *plen, char *errbuf)
    01200 {
    01201 struct rpcap_filter filter;
    01202 struct rpcap_filterbpf_insn insn;
    01203 struct bpf_insn *bf_insn;
    01204 struct bpf_program bf_prog;
    01205 unsigned int i;
    01206
    01207
    01208     if ( ( *nread+= sock_recv(fp->rmt_sockctrl, (char *) &filter, sizeof(struct rpcap_filter), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    01209     {
    01210         // to avoid blocking on the sock_discard()
    01211         *plen= *nread;
    01212         return -1;
    01213     }
    01214
    01215     bf_prog.bf_len= ntohl(filter.nitems);
    01216
    01217     if (ntohs(filter.filtertype) != RPCAP_UPDATEFILTER_BPF)
    01218     {
    01219         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Only BPF/NPF filters are currently supported");
    01220         return -1;
    01221     }
    01222
    01223     bf_insn= (struct bpf_insn *) malloc ( sizeof(struct bpf_insn) * bf_prog.bf_len);
    01224     if (bf_insn == NULL)
    01225     {
    01226         snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    01227         return -1;
    01228     }
    01229
    01230     bf_prog.bf_insns= bf_insn;
    01231
    01232     for (i= 0; i < bf_prog.bf_len; i++)
    01233     {
    01234         if ( ( *nread+= sock_recv(fp->rmt_sockctrl, (char *) &insn,
    01235             sizeof(struct rpcap_filterbpf_insn), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    01236             return -1;
    01237
    01238         bf_insn->code= ntohs(insn.code);
    01239         bf_insn->jf= insn.jf;
    01240         bf_insn->jt= insn.jt;
    01241         bf_insn->k= ntohl(insn.k);
    01242
    01243         bf_insn++;
    01244     }
    01245
    01246     if (bpf_validate(bf_prog.bf_insns, bf_prog.bf_len) == 0)
    01247     {
    01248         snprintf(errbuf, PCAP_ERRBUF_SIZE, "The filter contains bogus instructions");
    01249         return -1;
    01250     }
    01251
    01252     if (pcap_setfilter(fp, &bf_prog) )
    01253     {
    01254         snprintf(errbuf, PCAP_ERRBUF_SIZE, "RPCAP error: %s", fp->errbuf);
    01255         return -1;
    01256     }
    01257
    01258     return 0;
    01259 }
    01260
    01261
    01262
    01263 int daemon_updatefilter(pcap_t *fp, uint32 plen)
    01264 {
    01265 struct rpcap_header header;         // keeps the answer to the updatefilter command
    01266 unsigned int nread;
    01267
    01268     nread= 0;
    01269
    01270     if ( daemon_unpackapplyfilter(fp, &nread, &plen, fp->errbuf) )
    01271         goto error;
    01272
    01273     // Check if all the data has been read; if not, discard the data in excess
    01274     if (nread != plen)
    01275     {
    01276         if (sock_discard(fp->rmt_sockctrl, plen - nread, NULL, 0) )
    01277         {
    01278             nread= plen;        // just to avoid to call discard again in the 'error' section
    01279             goto error;
    01280         }
    01281     }
    01282
    01283     // A response is needed, otherwise the other host does not know that everything went well
    01284     rpcap_createhdr( &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);
    01285
    01286     if ( sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), fp->errbuf, PCAP_ERRBUF_SIZE) )
    01287         goto error;
    01288
    01289     return 0;
    01290
    01291
    01292 error:
    01293     if (nread != plen)
    01294         sock_discard(fp->rmt_sockctrl, plen - nread, NULL, 0);
    01295
    01296     rpcap_senderror(fp->rmt_sockctrl, fp->errbuf, PCAP_ERR_UPDATEFILTER, NULL);
    01297
    01298     return -1;
    01299 }
    01300
    01301
    01302
    01306 int daemon_setsampling(SOCKET sockctrl, struct rpcap_sampling *samp_param, int plen, char *errbuf)
    01307 {
    01308 struct rpcap_header header;
    01309 struct rpcap_sampling rpcap_samp;
    01310 int nread;                  // number of bytes of the payload read from the socket
    01311
    01312
    01313     if ( ( nread= sock_recv(sockctrl, (char *) &rpcap_samp, sizeof(struct rpcap_sampling),
    01314             SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    01315         goto error;
    01316
    01317
    01318     // Save these settings in the pcap_t
    01319     samp_param->method= rpcap_samp.method;
    01320     samp_param->value= ntohl(rpcap_samp.value);
    01321
    01322
    01323     // A response is needed, otherwise the other host does not know that everything went well
    01324     rpcap_createhdr( &header, RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);
    01325
    01326     if ( sock_send(sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) )
    01327         goto error;
    01328
    01329     if (nread != plen)
    01330         sock_discard(sockctrl, plen - nread, NULL, 0);
    01331
    01332     return 0;
    01333
    01334 error:
    01335     if (nread != plen)
    01336         sock_discard(sockctrl, plen - nread, NULL, 0);
    01337
    01338     rpcap_senderror(sockctrl, errbuf, PCAP_ERR_SETSAMPLING, NULL);
    01339
    01340     return -1;
    01341 }
    01342
    01343
    01344
    01345 int daemon_getstats(pcap_t *fp)
    01346 {
    01347 char sendbuf[RPCAP_NETBUF_SIZE];    // temporary buffer in which data to be sent is buffered
    01348 int sendbufidx= 0;                  // index which keeps the number of bytes currently buffered
    01349 struct pcap_stat stats;             // local statistics
    01350 struct rpcap_stats *netstats;       // statistics sent on the network
    01351
    01352     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
    01353         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
    01354         goto error;
    01355
    01356     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));
    01357
    01358     netstats= (struct rpcap_stats *) &sendbuf[sendbufidx];
    01359
    01360     if ( sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL,
    01361         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
    01362         goto error;
    01363
    01364     if (pcap_stats(fp, &stats) )
    01365         goto error;
    01366
    01367     netstats->ifdrop= htonl(stats.ps_ifdrop);
    01368     netstats->ifrecv= htonl(stats.ps_recv);
    01369     netstats->krnldrop= htonl(stats.ps_drop);
    01370     netstats->svrcapt= htonl(fp->md.TotCapt);
    01371
    01372     // Send the packet
    01373     if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
    01374         goto error;
    01375
    01376     return 0;
    01377
    01378 error:
    01379     rpcap_senderror(fp->rmt_sockctrl, fp->errbuf, PCAP_ERR_GETSTATS, NULL);
    01380     return -1;
    01381 }
    01382
    01383
    01384
    01385
    01386 int daemon_getstatsnopcap(SOCKET sockctrl, unsigned int ifdrops, unsigned int ifrecv,
    01387                           unsigned int krnldrop, unsigned int svrcapt, char *errbuf)
    01388 {
    01389 char sendbuf[RPCAP_NETBUF_SIZE];    // temporary buffer in which data to be sent is buffered
    01390 int sendbufidx= 0;                  // index which keeps the number of bytes currently buffered
    01391 struct rpcap_stats *netstats;       // statistics sent on the network
    01392
    01393     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
    01394         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01395         goto error;
    01396
    01397     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));
    01398
    01399     netstats= (struct rpcap_stats *) &sendbuf[sendbufidx];
    01400
    01401     if ( sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL,
    01402         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01403         goto error;
    01404
    01405     netstats->ifdrop= htonl(ifdrops);
    01406     netstats->ifrecv= htonl(ifrecv);
    01407     netstats->krnldrop= htonl(krnldrop);
    01408     netstats->svrcapt= htonl(svrcapt);
    01409
    01410     // Send the packet
    01411     if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01412         goto error;
    01413
    01414     return 0;
    01415
    01416 error:
    01417     rpcap_senderror(sockctrl, errbuf, PCAP_ERR_GETSTATS, NULL);
    01418     return -1;
    01419 }
    01420
    01421
    01422
    01423
    01424 void *daemon_thrdatamain(void *ptr)
    01425 {
    01426 char errbuf[PCAP_ERRBUF_SIZE + 1];  // error buffer
    01427 pcap_t *fp;                         // pointer to a 'pcap' structure
    01428 int retval;                         // general variable used to keep the return value of other functions
    01429 struct rpcap_pkthdr *net_pkt_header;// header of the packet
    01430 struct pcap_pkthdr *pkt_header;     // pointer to the buffer that contains the header of the current packet
    01431 u_char *pkt_data;                   // pointer to the buffer that contains the current packet
    01432 char *sendbuf;                      // temporary buffer in which data to be sent is buffered
    01433 int sendbufidx;                     // index which keeps the number of bytes currently buffered
    01434
    01435     fp= (pcap_t *) ptr;
    01436
    01437     fp->md.TotCapt= 0;          // counter which is incremented each time a packet is received
    01438
    01439     // Initialize errbuf
    01440     memset(errbuf, 0, sizeof(errbuf) );
    01441
    01442     // Some platforms (e.g. Win32) allow creating a static variable with this size
    01443     // However, others (e.g. BSD) do not, so we're forced to allocate this buffer dynamically
    01444     sendbuf= (char *) malloc (sizeof(char) * RPCAP_NETBUF_SIZE);
    01445     if (sendbuf == NULL)
    01446     {
    01447         snprintf(errbuf, sizeof(errbuf) - 1, "Unable to create the buffer for this child thread");
    01448         goto error;
    01449     }
    01450
    01451     // Modify thread params so that it can be killed at any time
    01452     if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) )
    01453         goto error;
    01454     if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) )
    01455         goto error;
    01456
    01457     // Retrieve the packets
    01458     while ((retval = pcap_next_ex(fp, &pkt_header, (const u_char **) &pkt_data)) >= 0)  // cast to avoid a compiler warning
    01459     {
    01460         if (retval == 0)    // Read timeout elapsed
    01461             continue;
    01462
    01463         sendbufidx= 0;
    01464
    01465         // Bufferize the general header
    01466         if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
    01467             RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01468             goto error;
    01469
    01470         rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_PACKET, 0,
    01471             (uint16) (sizeof(struct rpcap_pkthdr) + pkt_header->caplen) );
    01472
    01473         net_pkt_header= (struct rpcap_pkthdr *) &sendbuf[sendbufidx];
    01474
    01475         // Bufferize the pkt header
    01476         if ( sock_bufferize(NULL, sizeof(struct rpcap_pkthdr), NULL, &sendbufidx,
    01477             RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01478             goto error;
    01479
    01480         net_pkt_header->caplen= htonl(pkt_header->caplen);
    01481         net_pkt_header->len= htonl(pkt_header->len);
    01482         net_pkt_header->npkt= htonl( ++(fp->md.TotCapt) );
    01483         net_pkt_header->timestamp_sec= htonl(pkt_header->ts.tv_sec);
    01484         net_pkt_header->timestamp_usec= htonl(pkt_header->ts.tv_usec);
    01485
    01486         // Bufferize the pkt data
    01487         if ( sock_bufferize((char *) pkt_data, pkt_header->caplen, sendbuf, &sendbufidx,
    01488             RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01489             goto error;
    01490
    01491         // Send the packet
    01492         if ( sock_send(fp->rmt_sockdata, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01493             goto error;
    01494
    01495     }
    01496
    01497     if (retval == -1)
    01498     {
    01499         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(fp) );
    01500         rpcap_senderror(fp->rmt_sockctrl, errbuf, PCAP_ERR_READEX, NULL);
    01501         goto error;
    01502     }
    01503
    01504 error:
    01505
    01506     SOCK_ASSERT(errbuf, 1);
    01507     closesocket(fp->rmt_sockdata);
    01508     fp->rmt_sockdata= 0;
    01509
    01510     free(sendbuf);
    01511
    01512     return NULL;
    01513 }
    01514
    01515
    01516
    01534 void daemon_seraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage *sockaddrout)
    01535 {
    01536     memset(sockaddrout, 0, sizeof(struct sockaddr_storage) );
    01537
    01538     // There can be the case in which the sockaddrin is not available
    01539     if (sockaddrin == NULL) return;
    01540
    01541     // Warning: we support only AF_INET and AF_INET6
    01542     if (sockaddrin->ss_family == AF_INET)
    01543     {
    01544     struct sockaddr_in *sockaddr;
    01545
    01546         sockaddr= (struct sockaddr_in *) sockaddrin;
    01547         sockaddr->sin_family= htons(sockaddr->sin_family);
    01548         sockaddr->sin_port= htons(sockaddr->sin_port);
    01549         memcpy(sockaddrout, sockaddr, sizeof(struct sockaddr_in) );
    01550     }
    01551     else
    01552     {
    01553     struct sockaddr_in6 *sockaddr;
    01554
    01555         sockaddr= (struct sockaddr_in6 *) sockaddrin;
    01556         sockaddr->sin6_family= htons(sockaddr->sin6_family);
    01557         sockaddr->sin6_port= htons(sockaddr->sin6_port);
    01558         sockaddr->sin6_flowinfo= htonl(sockaddr->sin6_flowinfo);
    01559         sockaddr->sin6_scope_id= htonl(sockaddr->sin6_scope_id);
    01560         memcpy(sockaddrout, sockaddr, sizeof(struct sockaddr_in6) );
    01561     }
    01562 }
    01563
    01564
    01565
    01566
    01567
    01573 void pthread_suspend(int msec)
    01574 {
    01575 #ifdef WIN32
    01576     Sleep(msec);
    01577 #else
    01578 struct timespec abstime;
    01579 struct timeval now;
    01580
    01581     pthread_cond_t cond;
    01582     pthread_mutex_t mutex;
    01583     pthread_mutexattr_t attr;
    01584
    01585     pthread_mutexattr_init(&attr);
    01586     pthread_mutex_init(&mutex, &attr);
    01587     pthread_mutex_lock(&mutex);
    01588
    01589     pthread_cond_init(&cond, NULL);
    01590
    01591     gettimeofday(&now, NULL);
    01592
    01593     abstime.tv_sec = now.tv_sec + msec/1000;
    01594     abstime.tv_nsec = now.tv_usec * 1000 + (msec%1000) * 1000 * 1000;
    01595
    01596     pthread_cond_timedwait(&cond, &mutex, &abstime);
    01597
    01598     pthread_mutex_destroy(&mutex);
    01599     pthread_cond_destroy(&cond);
    01600 #endif
    01601 }
    01602
    01603
    01604

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