メイン   モジュール   デー タ構造   ファイルリスト   データフィールド   グローバル   関連ページ   注意事項   English

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.
2005 translated by Telebusiness,Inc.
 All rights reserved.