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

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