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