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

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