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.