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         return -1;
    00647     }
    00648
    00649     return 0;
    00650
    00651 #else
    00652 /*  Standard user authentication:
    00653         http://www.unixpapa.com/incnote/passwd.html
    00654     Problem: it is not able to merge the standard pwd file with the shadow one
    00655
    00656     Shadow user authentication:
    00657         http://www.tldp.org/HOWTO/Shadow-Password-HOWTO-8.html
    00658     Problem: the program must either (1) run as root, or (2) run as user, but it
    00659     must be owned by root and must be SUID root (chmod u+s rpcapd)
    00660 */
    00661
    00662     struct passwd *user;
    00663 #ifdef linux
    00664     struct spwd *usersp;
    00665 #endif
    00666
    00667     // This call is needed to get the uid
    00668     if ((user= getpwnam(username)) == NULL)
    00669     {
    00670         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: no such user");
    00671         return -1;
    00672     }
    00673
    00674 #ifdef linux
    00675     // This call is needed to get the password; otherwise 'x' is returned
    00676     if ((usersp= getspnam(username)) == NULL)
    00677     {
    00678         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: no such user");
    00679         return -1;
    00680     }
    00681
    00682     if (strcmp(usersp->sp_pwdp, (char *) crypt(password, usersp->sp_pwdp) ) != 0)
    00683     {
    00684         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: password incorrect");
    00685         return -1;
    00686     }
    00687 #endif
    00688
    00689 #ifdef bsd
    00690     if (strcmp(user->pw_passwd, (char *) crypt(password, user->pw_passwd) ) != 0)
    00691     {
    00692         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: password incorrect");
    00693         return -1;
    00694     }
    00695 #endif
    00696
    00697     if (setuid(user->pw_uid) )
    00698     {
    00699         snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s", pcap_strerror(errno) );
    00700         return -1;
    00701     }
    00702
    00703 /*  if (setgid(user->pw_gid) )
    00704     {
    00705         SOCK_ASSERT("setgid failed", 1);
    00706         snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s", pcap_strerror(errno) );
    00707         return -1;
    00708     }
    00709 */
    00710     return 0;
    00711
    00712 #endif
    00713
    00714 }
    00715
    00716
    00717
    00718 // PORTING WARNING We assume u_int is a 32bit value
    00719 int daemon_findalldevs(SOCKET sockctrl, char *errbuf)
    00720 {
    00721 char sendbuf[RPCAP_NETBUF_SIZE];            // temporary buffer in which data to be sent is buffered
    00722 int sendbufidx= 0;                          // index which keeps the number of bytes currently buffered
    00723 pcap_if_t *alldevs;                         // pointer to the heade of the interface chain
    00724 pcap_if_t *d;                               // temp pointer neede to scan the interface chain
    00725 uint16 plen= 0;                             // length of the payload of this message
    00726 struct pcap_addr *address;                  // pcap structure that keeps a network address of an interface
    00727 struct rpcap_findalldevs_if *findalldevs_if;// rpcap structure that packet all the data of an interface together
    00728 uint16 nif= 0;                              // counts the number of interface listed
    00729
    00730     // Retrieve the device list
    00731     if (pcap_findalldevs(&alldevs, errbuf) == -1)
    00732     {
    00733         rpcap_senderror(sockctrl, errbuf, PCAP_ERR_FINDALLIF, NULL);
    00734         return -1;
    00735     }
    00736
    00737     if (alldevs == NULL)
    00738     {
    00739         rpcap_senderror(sockctrl,
    00740             "No interfaces found! Make sure libpcap/WinPcap is properly installed"
    00741             " and you have the right to access to the remote device.",
    00742             PCAP_ERR_NOREMOTEIF,
    00743             errbuf);
    00744         return -1;
    00745     }
    00746
    00747     // checks the number of interfaces and it computes the total length of the payload
    00748     for (d= alldevs; d != NULL; d= d->next)
    00749     {
    00750         nif++;
    00751
    00752         if (d->description)
    00753             plen+= strlen(d->description);
    00754         if (d->name)
    00755             plen+= strlen(d->name);
    00756
    00757         plen+= sizeof(struct rpcap_findalldevs_if);
    00758
    00759         for (address= d->addresses; address != NULL; address= address->next)
    00760             plen+= ( sizeof(struct sockaddr_storage) * 4);
    00761     }
    00762
    00763     // RPCAP findalldevs command
    00764     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
    00765         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00766         return -1;
    00767
    00768     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_FINDALLIF_REPLY, nif, plen);
    00769
    00770     // send the interface list
    00771     for (d= alldevs; d != NULL; d= d->next)
    00772     {
    00773     uint16 lname, ldescr;
    00774
    00775         findalldevs_if= (struct rpcap_findalldevs_if *) &sendbuf[sendbufidx];
    00776
    00777         if ( sock_bufferize(NULL, sizeof(struct rpcap_findalldevs_if), NULL,
    00778             &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00779             return -1;
    00780
    00781         memset(findalldevs_if, 0, sizeof(struct rpcap_findalldevs_if) );
    00782
    00783         if (d->description) ldescr= (short) strlen(d->description);
    00784         else ldescr= 0;
    00785         if (d->name) lname= (short) strlen(d->name);
    00786         else lname= 0;
    00787
    00788         findalldevs_if->desclen= htons(ldescr);
    00789         findalldevs_if->namelen= htons(lname);
    00790         findalldevs_if->flags= htonl(d->flags);
    00791
    00792         for (address= d->addresses; address != NULL; address= address->next)
    00793             findalldevs_if->naddr++;
    00794
    00795         findalldevs_if->naddr= htons(findalldevs_if->naddr);
    00796
    00797         if (sock_bufferize(d->name, lname, sendbuf, &sendbufidx,
    00798             RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00799             return -1;
    00800
    00801         if (sock_bufferize(d->description, ldescr, sendbuf, &sendbufidx,
    00802             RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00803             return -1;
    00804
    00805         // send all addresses
    00806         for (address= d->addresses; address != NULL; address= address->next)
    00807         {
    00808         struct sockaddr_storage *sockaddr;
    00809
    00810             sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
    00811             if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL,
    00812                 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00813                 return -1;
    00814             daemon_seraddr( (struct sockaddr_storage *) address->addr, sockaddr);
    00815
    00816             sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
    00817             if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL,
    00818                 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00819                 return -1;
    00820             daemon_seraddr( (struct sockaddr_storage *) address->netmask, sockaddr);
    00821
    00822             sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
    00823             if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL,
    00824                 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00825                 return -1;
    00826             daemon_seraddr( (struct sockaddr_storage *) address->broadaddr, sockaddr);
    00827
    00828             sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
    00829             if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL,
    00830                 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00831                 return -1;
    00832             daemon_seraddr( (struct sockaddr_storage *) address->dstaddr, sockaddr);
    00833         }
    00834     }
    00835
    00836     // Send a final command that says "now send it!"
    00837     if (sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00838         return -1;
    00839
    00840     // We do no longer need the device list. Free it
    00841     pcap_freealldevs(alldevs);
    00842
    00843     // everything is fine
    00844     return 0;
    00845 }
    00846
    00847
    00848
    00849
    00850
    00851 /*
    00852     \param plen: the length of the current message (needed in order to be able
    00853     to discard excess data in the message, if present)
    00854 */
    00855 int daemon_opensource(SOCKET sockctrl, char *source, int srclen, uint32 plen, char *errbuf)
    00856 {
    00857 pcap_t *fp= NULL;                   // pcap_t main variable
    00858 unsigned int nread;                 // number of bytes of the payload read from the socket
    00859 char sendbuf[RPCAP_NETBUF_SIZE];    // temporary buffer in which data to be sent is buffered
    00860 int sendbufidx= 0;                  // index which keeps the number of bytes currently buffered
    00861 struct rpcap_openreply *openreply;  // open reply message
    00862
    00863
    00864     strcpy(source, PCAP_SRC_IF_STRING);
    00865
    00866     if (srclen <= (int) (strlen(PCAP_SRC_IF_STRING) + plen) )
    00867     {
    00868         rpcap_senderror(sockctrl, "Source string too long", PCAP_ERR_OPEN, NULL);
    00869         return -1;
    00870     }
    00871
    00872     if ( (nread= sock_recv(sockctrl, &source[strlen(PCAP_SRC_IF_STRING)], plen, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    00873         return -1;
    00874
    00875     // Check if all the data has been read; if not, discard the data in excess
    00876     if (nread != plen)
    00877         sock_discard(sockctrl, plen - nread, NULL, 0);
    00878
    00879     // Puts a '0' to terminate the source string
    00880     source[strlen(PCAP_SRC_IF_STRING) + plen]= 0;
    00881
    00882     // Open the selected device
    00883     // This is a fake open, since we do that only to get the needed parameters, then we close the device again
    00884     if ( (fp= pcap_open(source,
    00885             1500 /* fake snaplen */,
    00886             0 /* no promis */,
    00887             1000 /* fake timeout */,
    00888             NULL /* local device, so no auth */,
    00889             errbuf)) == NULL)
    00890     {
    00891         rpcap_senderror(sockctrl, errbuf, PCAP_ERR_OPEN, NULL);
    00892         return -1;
    00893     }
    00894
    00895
    00896     // Now, I can send a RPCAP open reply message
    00897     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
    00898         RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00899         goto error;
    00900
    00901     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_OPEN_REPLY, 0, sizeof(struct rpcap_openreply) );
    00902
    00903     openreply= (struct rpcap_openreply *) &sendbuf[sendbufidx];
    00904
    00905     if ( sock_bufferize(NULL, sizeof(struct rpcap_openreply), NULL, &sendbufidx,
    00906         RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00907         goto error;
    00908
    00909     memset(openreply, 0, sizeof(struct rpcap_openreply) );
    00910     openreply->linktype= htonl(fp->linktype);
    00911     openreply->tzoff= htonl(fp->tzoff);
    00912
    00913     if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
    00914         goto error;
    00915
    00916     // I have to close the device again, since it has been opened with wrong parameters
    00917     pcap_close(fp);
    00918     fp= NULL;
    00919
    00920     return 0;
    00921
    00922 error:
    00923     if (fp)
    00924     {
    00925         pcap_close(fp);
    00926         fp= NULL;
    00927     }
    00928
    00929     return -1;
    00930 }
    00931
    00932
    00933
    00934
    00935
    00936 /*
    00937     \param plen: the length of the current message (needed in order to be able
    00938     to discard excess data in the message, if present)
    00939 */
    00940 pcap_t *daemon_startcapture(SOCKET sockctrl, pthread_t *threaddata, char *source, int active, struct rpcap_sampling *samp_param, uint32 plen, char *errbuf)
    00941 {
    00942 char portdata[PCAP_BUF_SIZE];       // temp variable needed to derive the data port
    00943 char peerhost[PCAP_BUF_SIZE];       // temp variable needed to derive the host name of our peer
    00944 pcap_t *fp= NULL;                   // pcap_t main variable
    00945 unsigned int nread;                 // number of bytes of the payload read from the socket
    00946 char sendbuf[RPCAP_NETBUF_SIZE];    // temporary buffer in which data to be sent is buffered
    00947 int sendbufidx= 0;                  // index which keeps the number of bytes currently buffered
    00948
    00949 // socket-related variables
    00950 SOCKET sockdata= 0;                 // socket descriptor of the data connection
    00951 struct addrinfo hints;              // temp, needed to open a socket connection
    00952 struct addrinfo *addrinfo;          // temp, needed to open a socket connection
    00953 struct sockaddr_storage saddr;      // temp, needed to retrieve the network data port chosen on the local machine
    00954 socklen_t saddrlen;                 // temp, needed to retrieve the network data port chosen on the local machine
    00955
    00956 // RPCAP-related variables
    00957 struct rpcap_startcapreq startcapreq;       // start capture request message
    00958 struct rpcap_startcapreply *startcapreply;  // start capture reply message
    00959 int serveropen_dp;                          // keeps who is going to open the data connection
    00960
    00961     addrinfo= NULL;
    00962
    00963     if ( (nread= sock_recv(sockctrl, (char *) &startcapreq, sizeof(struct rpcap_startcapreq), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    00964         return NULL;
    00965
    00966     startcapreq.flags= ntohs(startcapreq.flags);
    00967
    00968     // Open the selected device
    00969     if ( (fp= pcap_open(source,
    00970             ntohl(startcapreq.snaplen),
    00971             (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_PROMISC) ? PCAP_OPENFLAG_PROMISCUOUS : 0 /* local device, other flags not needed */,
    00972             ntohl(startcapreq.read_timeout),
    00973             NULL /* local device, so no auth */,
    00974             errbuf)) == NULL)
    00975     {
    00976         rpcap_senderror(sockctrl, errbuf, PCAP_ERR_OPEN, NULL);
    00977         return NULL;
    00978     }
    00979
    00980     // Apply sampling parameters
    00981     fp->rmt_samp.method= samp_param->method;
    00982     fp->rmt_samp.value= samp_param->value;
    00983
    00984     /*
    00985     We're in active mode if:
    00986     - we're using TCP, and the user wants us to be in active mode
    00987     - we're using UDP
    00988     */
    00989     serveropen_dp= (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_SERVEROPEN) || (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) || active;
    00990
    00991     /*
    00992     Gets the sockaddr structure referred to the other peer in the ctrl connection
    00993
    00994     We need that because:
    00995     - if we're in passive mode, we need to know the address family we want to use
    00996     (the same used for the ctrl socket)
    00997     - if we're in active mode, we need to know the network address of the other host
    00998     we want to connect to
    00999     */
    01000     saddrlen = sizeof(struct sockaddr_storage);
    01001     if (getpeername(sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
    01002     {
    01003         sock_geterror("getpeername(): ", errbuf, PCAP_ERRBUF_SIZE);
    01004         goto error;
    01005     }
    01006
    01007     memset(&hints, 0, sizeof(struct addrinfo) );
    01008     hints.ai_socktype = (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
    01009     hints.ai_family = saddr.ss_family;
    01010
    01011     // Now we have to create a new socket to send packets
    01012     if (serveropen_dp)      // Data connection is opened by the server toward the client
    01013     {
    01014         sprintf(portdata, "%d", ntohs(startcapreq.portdata) );
    01015
    01016         // Get the name of the other peer (needed to connect to that specific network address)
    01017         if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, peerhost,
    01018                 sizeof(peerhost), NULL, 0, NI_NUMERICHOST) )
    01019         {
    01020             sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
    01021             goto error;
    01022         }
    01023
    01024         if (sock_initaddress(peerhost, portdata, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01025             goto error;
    01026
    01027         if ( (sockdata= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    01028             goto error;
    01029     }
    01030     else        // Data connection is opened by the client toward the server
    01031     {
    01032         hints.ai_flags = AI_PASSIVE;
    01033
    01034         // Let's the server socket pick up a free network port for us
    01035         if (sock_initaddress(NULL, "0", &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01036             goto error;
    01037
    01038         if ( (sockdata= sock_open(addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    01039             goto error;
    01040
    01041         // get the complete sockaddr structure used in the data connection
    01042         saddrlen = sizeof(struct sockaddr_storage);
    01043         if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
    01044         {
    01045             sock_geterror("getsockname(): ", errbuf, PCAP_ERRBUF_SIZE);
    01046             goto error;
    01047         }
    01048
    01049         // Get the local port the system picked up
    01050         if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, NULL,
    01051                 0, portdata, sizeof(portdata), NI_NUMERICSERV) )
    01052         {
    01053             sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
    01054             goto error;
    01055         }
    01056     }
    01057
    01058     // addrinfo is no longer used
    01059     freeaddrinfo(addrinfo);
    01060     addrinfo= NULL;
    01061
    01062     // save the socket ID for the next calls
    01063     fp->rmt_sockctrl= sockctrl; // Needed to send an error on the ctrl connection
    01064
    01065     // Now I can set the filter
    01066     if ( daemon_unpackapplyfilter(fp, &nread, &plen, errbuf) )
    01067         goto error;
    01068
    01069
    01070     // Now, I can send a RPCAP start capture reply message
    01071     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
    01072         RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01073         goto error;
    01074
    01075     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STARTCAP_REPLY, 0, sizeof(struct rpcap_startcapreply) );
    01076
    01077     startcapreply= (struct rpcap_startcapreply *) &sendbuf[sendbufidx];
    01078
    01079     if ( sock_bufferize(NULL, sizeof(struct rpcap_startcapreply), NULL,
    01080         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01081         goto error;
    01082
    01083     memset(startcapreply, 0, sizeof(struct rpcap_startcapreply) );
    01084     startcapreply->bufsize= htonl(fp->bufsize);
    01085
    01086     if (!serveropen_dp)
    01087     {
    01088         sscanf(portdata, "%d", (int *) &(startcapreply->portdata) );
    01089         startcapreply->portdata= htons(startcapreply->portdata);
    01090     }
    01091
    01092     if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01093         goto error;
    01094
    01095     if (!serveropen_dp)
    01096     {
    01097     SOCKET socktemp;    // We need another socket, since we're going to accept() a connection
    01098
    01099         // Connection creation
    01100         saddrlen = sizeof(struct sockaddr_storage);
    01101
    01102         socktemp= accept(sockdata, (struct sockaddr *) &saddr, &saddrlen);
    01103
    01104         if (socktemp == -1)
    01105         {
    01106             sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
    01107             goto error;
    01108         }
    01109
    01110         // Now that I accepted the connection, the server socket is no longer needed
    01111         sock_close(sockdata, errbuf, PCAP_ERRBUF_SIZE);
    01112         sockdata= socktemp;
    01113     }
    01114
    01115     fp->rmt_sockdata= sockdata;
    01116
    01117     // Now we have to create a new thread to receive packets
    01118     if ( pthread_create(threaddata, NULL, (void *) daemon_thrdatamain, (void *) fp) )
    01119     {
    01120         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread");
    01121         goto error;
    01122     }
    01123
    01124     // Check if all the data has been read; if not, discard the data in excess
    01125     if (nread != plen)
    01126         sock_discard(sockctrl, plen - nread, NULL, 0);
    01127
    01128     return fp;
    01129
    01130 error:
    01131     rpcap_senderror(sockctrl, errbuf, PCAP_ERR_STARTCAPTURE, NULL);
    01132
    01133     if (addrinfo)
    01134         freeaddrinfo(addrinfo);
    01135
    01136     if (threaddata)
    01137         pthread_cancel(*threaddata);
    01138
    01139     if (sockdata)
    01140         sock_close(sockdata, NULL, 0);
    01141
    01142     // Check if all the data has been read; if not, discard the data in excess
    01143     if (nread != plen)
    01144         sock_discard(sockctrl, plen - nread, NULL, 0);
    01145
    01146     if (fp)
    01147     {
    01148         pcap_close(fp);
    01149         fp= NULL;
    01150     }
    01151
    01152     return NULL;
    01153 }
    01154
    01155
    01156
    01157 int daemon_endcapture(pcap_t *fp, pthread_t *threaddata, char *errbuf)
    01158 {
    01159 struct rpcap_header header;
    01160 SOCKET sockctrl;
    01161
    01162     if (threaddata)
    01163     {
    01164         pthread_cancel(*threaddata);
    01165         threaddata= 0;
    01166     }
    01167     if (fp->rmt_sockdata)
    01168     {
    01169         sock_close(fp->rmt_sockdata, NULL, 0);
    01170         fp->rmt_sockdata= 0;
    01171     }
    01172
    01173     sockctrl= fp->rmt_sockctrl;
    01174
    01175     pcap_close(fp);
    01176     fp= NULL;
    01177
    01178     rpcap_createhdr( &header, RPCAP_MSG_ENDCAP_REPLY, 0, 0);
    01179
    01180     if ( sock_send(sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
    01181         return -1;
    01182
    01183     return 0;
    01184 }
    01185
    01186
    01187
    01188 int daemon_unpackapplyfilter(pcap_t *fp, unsigned int *nread, int *plen, char *errbuf)
    01189 {
    01190 struct rpcap_filter filter;
    01191 struct rpcap_filterbpf_insn insn;
    01192 struct bpf_insn *bf_insn;
    01193 struct bpf_program bf_prog;
    01194 unsigned int i;
    01195
    01196
    01197     if ( ( *nread+= sock_recv(fp->rmt_sockctrl, (char *) &filter, sizeof(struct rpcap_filter), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    01198     {
    01199         // to avoid blocking on the sock_discard()
    01200         *plen= *nread;
    01201         return -1;
    01202     }
    01203
    01204     bf_prog.bf_len= ntohl(filter.nitems);
    01205
    01206     if (ntohs(filter.filtertype) != RPCAP_UPDATEFILTER_BPF)
    01207     {
    01208         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Only BPF/NPF filters are currently supported");
    01209         return -1;
    01210     }
    01211
    01212     bf_insn= (struct bpf_insn *) malloc ( sizeof(struct bpf_insn) * bf_prog.bf_len);
    01213     if (bf_insn == NULL)
    01214     {
    01215         snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
    01216         return -1;
    01217     }
    01218
    01219     bf_prog.bf_insns= bf_insn;
    01220
    01221     for (i= 0; i < bf_prog.bf_len; i++)
    01222     {
    01223         if ( ( *nread+= sock_recv(fp->rmt_sockctrl, (char *) &insn,
    01224             sizeof(struct rpcap_filterbpf_insn), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    01225             return -1;
    01226
    01227         bf_insn->code= ntohs(insn.code);
    01228         bf_insn->jf= insn.jf;
    01229         bf_insn->jt= insn.jt;
    01230         bf_insn->k= ntohl(insn.k);
    01231
    01232         bf_insn++;
    01233     }
    01234
    01235     if (bpf_validate(bf_prog.bf_insns, bf_prog.bf_len) == 0)
    01236     {
    01237         snprintf(errbuf, PCAP_ERRBUF_SIZE, "The filter contains bogus instructions");
    01238         return -1;
    01239     }
    01240
    01241     if (pcap_setfilter(fp, &bf_prog) )
    01242     {
    01243         snprintf(errbuf, PCAP_ERRBUF_SIZE, "RPCAP error: %s", fp->errbuf);
    01244         return -1;
    01245     }
    01246
    01247     return 0;
    01248 }
    01249
    01250
    01251
    01252 int daemon_updatefilter(pcap_t *fp, uint32 plen)
    01253 {
    01254 struct rpcap_header header;         // keeps the answer to the updatefilter command
    01255 unsigned int nread;
    01256
    01257     nread= 0;
    01258
    01259     if ( daemon_unpackapplyfilter(fp, &nread, &plen, fp->errbuf) )
    01260         goto error;
    01261
    01262     // Check if all the data has been read; if not, discard the data in excess
    01263     if (nread != plen)
    01264     {
    01265         if (sock_discard(fp->rmt_sockctrl, plen - nread, NULL, 0) )
    01266         {
    01267             nread= plen;        // just to avoid to call discard again in the 'error' section
    01268             goto error;
    01269         }
    01270     }
    01271
    01272     // A response is needed, otherwise the other host does not know that everything went well
    01273     rpcap_createhdr( &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);
    01274
    01275     if ( sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), fp->errbuf, PCAP_ERRBUF_SIZE) )
    01276         goto error;
    01277
    01278     return 0;
    01279
    01280
    01281 error:
    01282     if (nread != plen)
    01283         sock_discard(fp->rmt_sockctrl, plen - nread, NULL, 0);
    01284
    01285     rpcap_senderror(fp->rmt_sockctrl, fp->errbuf, PCAP_ERR_UPDATEFILTER, NULL);
    01286
    01287     return -1;
    01288 }
    01289
    01290
    01291
    01295 int daemon_setsampling(SOCKET sockctrl, struct rpcap_sampling *samp_param, int plen, char *errbuf)
    01296 {
    01297 struct rpcap_header header;
    01298 struct rpcap_sampling rpcap_samp;
    01299 int nread;                  // number of bytes of the payload read from the socket
    01300
    01301
    01302     if ( ( nread= sock_recv(sockctrl, (char *) &rpcap_samp, sizeof(struct rpcap_sampling),
    01303             SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
    01304         goto error;
    01305
    01306
    01307     // Save these settings in the pcap_t
    01308     samp_param->method= rpcap_samp.method;
    01309     samp_param->value= ntohl(rpcap_samp.value);
    01310
    01311
    01312     // A response is needed, otherwise the other host does not know that everything went well
    01313     rpcap_createhdr( &header, RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);
    01314
    01315     if ( sock_send(sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) )
    01316         goto error;
    01317
    01318     if (nread != plen)
    01319         sock_discard(sockctrl, plen - nread, NULL, 0);
    01320
    01321     return 0;
    01322
    01323 error:
    01324     if (nread != plen)
    01325         sock_discard(sockctrl, plen - nread, NULL, 0);
    01326
    01327     rpcap_senderror(sockctrl, errbuf, PCAP_ERR_SETSAMPLING, NULL);
    01328
    01329     return -1;
    01330 }
    01331
    01332
    01333
    01334 int daemon_getstats(pcap_t *fp)
    01335 {
    01336 char sendbuf[RPCAP_NETBUF_SIZE];    // temporary buffer in which data to be sent is buffered
    01337 int sendbufidx= 0;                  // index which keeps the number of bytes currently buffered
    01338 struct pcap_stat stats;             // local statistics
    01339 struct rpcap_stats *netstats;       // statistics sent on the network
    01340
    01341     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
    01342         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
    01343         goto error;
    01344
    01345     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));
    01346
    01347     netstats= (struct rpcap_stats *) &sendbuf[sendbufidx];
    01348
    01349     if ( sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL,
    01350         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
    01351         goto error;
    01352
    01353     if (pcap_stats(fp, &stats) )
    01354         goto error;
    01355
    01356     netstats->ifdrop= htonl(stats.ps_ifdrop);
    01357     netstats->ifrecv= htonl(stats.ps_recv);
    01358     netstats->krnldrop= htonl(stats.ps_drop);
    01359     netstats->svrcapt= htonl(fp->md.TotCapt);
    01360
    01361     // Send the packet
    01362     if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
    01363         goto error;
    01364
    01365     return 0;
    01366
    01367 error:
    01368     rpcap_senderror(fp->rmt_sockctrl, fp->errbuf, PCAP_ERR_GETSTATS, NULL);
    01369     return -1;
    01370 }
    01371
    01372
    01373
    01374
    01375 int daemon_getstatsnopcap(SOCKET sockctrl, unsigned int ifdrops, unsigned int ifrecv,
    01376                           unsigned int krnldrop, unsigned int svrcapt, char *errbuf)
    01377 {
    01378 char sendbuf[RPCAP_NETBUF_SIZE];    // temporary buffer in which data to be sent is buffered
    01379 int sendbufidx= 0;                  // index which keeps the number of bytes currently buffered
    01380 struct rpcap_stats *netstats;       // statistics sent on the network
    01381
    01382     if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
    01383         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01384         goto error;
    01385
    01386     rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));
    01387
    01388     netstats= (struct rpcap_stats *) &sendbuf[sendbufidx];
    01389
    01390     if ( sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL,
    01391         &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01392         goto error;
    01393
    01394     netstats->ifdrop= htonl(ifdrops);
    01395     netstats->ifrecv= htonl(ifrecv);
    01396     netstats->krnldrop= htonl(krnldrop);
    01397     netstats->svrcapt= htonl(svrcapt);
    01398
    01399     // Send the packet
    01400     if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01401         goto error;
    01402
    01403     return 0;
    01404
    01405 error:
    01406     rpcap_senderror(sockctrl, errbuf, PCAP_ERR_GETSTATS, NULL);
    01407     return -1;
    01408 }
    01409
    01410
    01411
    01412
    01413 void *daemon_thrdatamain(void *ptr)
    01414 {
    01415 char errbuf[PCAP_ERRBUF_SIZE + 1];  // error buffer
    01416 pcap_t *fp;                         // pointer to a 'pcap' structure
    01417 int retval;                         // general variable used to keep the return value of other functions
    01418 struct rpcap_pkthdr *net_pkt_header;// header of the packet
    01419 struct pcap_pkthdr *pkt_header;     // pointer to the buffer that contains the header of the current packet
    01420 u_char *pkt_data;                   // pointer to the buffer that contains the current packet
    01421 char *sendbuf;                      // temporary buffer in which data to be sent is buffered
    01422 int sendbufidx;                     // index which keeps the number of bytes currently buffered
    01423
    01424     fp= (pcap_t *) ptr;
    01425
    01426     fp->md.TotCapt= 0;          // counter which is incremented each time a packet is received
    01427
    01428     // Initialize errbuf
    01429     memset(errbuf, 0, sizeof(errbuf) );
    01430
    01431     // Some platforms (e.g. Win32) allow creating a static variable with this size
    01432     // However, others (e.g. BSD) do not, so we're forced to allocate this buffer dynamically
    01433     sendbuf= (char *) malloc (sizeof(char) * RPCAP_NETBUF_SIZE);
    01434     if (sendbuf == NULL)
    01435     {
    01436         snprintf(errbuf, sizeof(errbuf) - 1, "Unable to create the buffer for this child thread");
    01437         goto error;
    01438     }
    01439
    01440     // Modify thread params so that it can be killed at any time
    01441     if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) )
    01442         goto error;
    01443     if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) )
    01444         goto error;
    01445
    01446     // Retrieve the packets
    01447     while ((retval = pcap_next_ex(fp, &pkt_header, (const u_char **) &pkt_data)) >= 0)  // cast to avoid a compiler warning
    01448     {
    01449         if (retval == 0)    // Read timeout elapsed
    01450             continue;
    01451
    01452         sendbufidx= 0;
    01453
    01454         // Bufferize the general header
    01455         if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
    01456             RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01457             goto error;
    01458
    01459         rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_PACKET, 0,
    01460             (uint16) (sizeof(struct rpcap_pkthdr) + pkt_header->caplen) );
    01461
    01462         net_pkt_header= (struct rpcap_pkthdr *) &sendbuf[sendbufidx];
    01463
    01464         // Bufferize the pkt header
    01465         if ( sock_bufferize(NULL, sizeof(struct rpcap_pkthdr), NULL, &sendbufidx,
    01466             RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01467             goto error;
    01468
    01469         net_pkt_header->caplen= htonl(pkt_header->caplen);
    01470         net_pkt_header->len= htonl(pkt_header->len);
    01471         net_pkt_header->npkt= htonl( ++(fp->md.TotCapt) );
    01472         net_pkt_header->timestamp_sec= htonl(pkt_header->ts.tv_sec);
    01473         net_pkt_header->timestamp_usec= htonl(pkt_header->ts.tv_usec);
    01474
    01475         // Bufferize the pkt data
    01476         if ( sock_bufferize((char *) pkt_data, pkt_header->caplen, sendbuf, &sendbufidx,
    01477             RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01478             goto error;
    01479
    01480         // Send the packet
    01481         if ( sock_send(fp->rmt_sockdata, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
    01482             goto error;
    01483
    01484     }
    01485
    01486     if (retval == -1)
    01487     {
    01488         snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(fp) );
    01489         rpcap_senderror(fp->rmt_sockctrl, errbuf, PCAP_ERR_READEX, NULL);
    01490         goto error;
    01491     }
    01492
    01493 error:
    01494
    01495     SOCK_ASSERT(errbuf, 1);
    01496     closesocket(fp->rmt_sockdata);
    01497     fp->rmt_sockdata= 0;
    01498
    01499     free(sendbuf);
    01500
    01501     return NULL;
    01502 }
    01503
    01504
    01505
    01523 void daemon_seraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage *sockaddrout)
    01524 {
    01525     memset(sockaddrout, 0, sizeof(struct sockaddr_storage) );
    01526
    01527     // There can be the case in which the sockaddrin is not available
    01528     if (sockaddrin == NULL) return;
    01529
    01530     // Warning: we support only AF_INET and AF_INET6
    01531     if (sockaddrin->ss_family == AF_INET)
    01532     {
    01533     struct sockaddr_in *sockaddr;
    01534
    01535         sockaddr= (struct sockaddr_in *) sockaddrin;
    01536         sockaddr->sin_family= htons(sockaddr->sin_family);
    01537         sockaddr->sin_port= htons(sockaddr->sin_port);
    01538         memcpy(sockaddrout, sockaddr, sizeof(struct sockaddr_in) );
    01539     }
    01540     else
    01541     {
    01542     struct sockaddr_in6 *sockaddr;
    01543
    01544         sockaddr= (struct sockaddr_in6 *) sockaddrin;
    01545         sockaddr->sin6_family= htons(sockaddr->sin6_family);
    01546         sockaddr->sin6_port= htons(sockaddr->sin6_port);
    01547         sockaddr->sin6_flowinfo= htonl(sockaddr->sin6_flowinfo);
    01548         sockaddr->sin6_scope_id= htonl(sockaddr->sin6_scope_id);
    01549         memcpy(sockaddrout, sockaddr, sizeof(struct sockaddr_in6) );
    01550     }
    01551 }
    01552
    01553
    01554
    01555
    01556
    01562 void pthread_suspend(int msec)
    01563 {
    01564 #ifdef WIN32
    01565     Sleep(msec);
    01566 #else
    01567 struct timespec abstime;
    01568 struct timeval now;
    01569
    01570     pthread_cond_t cond;
    01571     pthread_mutex_t mutex;
    01572     pthread_mutexattr_t attr;
    01573
    01574     pthread_mutexattr_init(&attr);
    01575     pthread_mutex_init(&mutex, &attr);
    01576     pthread_mutex_lock(&mutex);
    01577
    01578     pthread_cond_init(&cond, NULL);
    01579
    01580     gettimeofday(&now, NULL);
    01581
    01582     abstime.tv_sec = now.tv_sec + msec/1000;
    01583     abstime.tv_nsec = now.tv_usec * 1000 + (msec%1000) * 1000 * 1000;
    01584
    01585     pthread_cond_timedwait(&cond, &mutex, &abstime);
    01586
    01587     pthread_mutex_destroy(&mutex);
    01588     pthread_cond_destroy(&cond);
    01589 #endif
    01590 }
    01591
    01592
    01593

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