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

daemon.c

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

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