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

daemon.c

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

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