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 CloseHandle(Token); 00647 return -1; 00648 } 00649 00650 CloseHandle(Token); 00651 return 0; 00652 00653 #else 00654 /* Standard user authentication: 00655 http://www.unixpapa.com/incnote/passwd.html 00656 Problem: it is not able to merge the standard pwd file with the shadow one 00657 00658 Shadow user authentication: 00659 http://www.tldp.org/HOWTO/Shadow-Password-HOWTO-8.html 00660 Problem: the program must either (1) run as root, or (2) run as user, but it 00661 must be owned by root and must be SUID root (chmod u+s rpcapd) 00662 */ 00663 00664 struct passwd *user; 00665 #ifdef linux 00666 struct spwd *usersp; 00667 #endif 00668 00669 // This call is needed to get the uid 00670 if ((user= getpwnam(username)) == NULL) 00671 { 00672 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: no such user"); 00673 return -1; 00674 } 00675 00676 #ifdef linux 00677 // This call is needed to get the password; otherwise 'x' is returned 00678 if ((usersp= getspnam(username)) == NULL) 00679 { 00680 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: no such user"); 00681 return -1; 00682 } 00683 00684 if (strcmp(usersp->sp_pwdp, (char *) crypt(password, usersp->sp_pwdp) ) != 0) 00685 { 00686 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: password incorrect"); 00687 return -1; 00688 } 00689 #endif 00690 00691 #ifdef bsd 00692 if (strcmp(user->pw_passwd, (char *) crypt(password, user->pw_passwd) ) != 0) 00693 { 00694 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: password incorrect"); 00695 return -1; 00696 } 00697 #endif 00698 00699 if (setuid(user->pw_uid) ) 00700 { 00701 snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s", pcap_strerror(errno) ); 00702 return -1; 00703 } 00704 00705 /* if (setgid(user->pw_gid) ) 00706 { 00707 SOCK_ASSERT("setgid failed", 1); 00708 snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s", pcap_strerror(errno) ); 00709 return -1; 00710 } 00711 */ 00712 return 0; 00713 00714 #endif 00715 00716 } 00717 00718 00719 00720 // PORTING WARNING We assume u_int is a 32bit value 00721 int daemon_findalldevs(SOCKET sockctrl, char *errbuf) 00722 { 00723 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered 00724 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 00725 pcap_if_t *alldevs; // pointer to the heade of the interface chain 00726 pcap_if_t *d; // temp pointer neede to scan the interface chain 00727 uint16 plen= 0; // length of the payload of this message 00728 struct pcap_addr *address; // pcap structure that keeps a network address of an interface 00729 struct rpcap_findalldevs_if *findalldevs_if;// rpcap structure that packet all the data of an interface together 00730 uint16 nif= 0; // counts the number of interface listed 00731 00732 // Retrieve the device list 00733 if (pcap_findalldevs(&alldevs, errbuf) == -1) 00734 { 00735 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_FINDALLIF, NULL); 00736 return -1; 00737 } 00738 00739 if (alldevs == NULL) 00740 { 00741 rpcap_senderror(sockctrl, 00742 "No interfaces found! Make sure libpcap/WinPcap is properly installed" 00743 " and you have the right to access to the remote device.", 00744 PCAP_ERR_NOREMOTEIF, 00745 errbuf); 00746 return -1; 00747 } 00748 00749 // checks the number of interfaces and it computes the total length of the payload 00750 for (d= alldevs; d != NULL; d= d->next) 00751 { 00752 nif++; 00753 00754 if (d->description) 00755 plen+= strlen(d->description); 00756 if (d->name) 00757 plen+= strlen(d->name); 00758 00759 plen+= sizeof(struct rpcap_findalldevs_if); 00760 00761 for (address= d->addresses; address != NULL; address= address->next) 00762 plen+= ( sizeof(struct sockaddr_storage) * 4); 00763 } 00764 00765 // RPCAP findalldevs command 00766 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 00767 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) 00768 return -1; 00769 00770 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_FINDALLIF_REPLY, nif, plen); 00771 00772 // send the interface list 00773 for (d= alldevs; d != NULL; d= d->next) 00774 { 00775 uint16 lname, ldescr; 00776 00777 findalldevs_if= (struct rpcap_findalldevs_if *) &sendbuf[sendbufidx]; 00778 00779 if ( sock_bufferize(NULL, sizeof(struct rpcap_findalldevs_if), NULL, 00780 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) 00781 return -1; 00782 00783 memset(findalldevs_if, 0, sizeof(struct rpcap_findalldevs_if) ); 00784 00785 if (d->description) ldescr= (short) strlen(d->description); 00786 else ldescr= 0; 00787 if (d->name) lname= (short) strlen(d->name); 00788 else lname= 0; 00789 00790 findalldevs_if->desclen= htons(ldescr); 00791 findalldevs_if->namelen= htons(lname); 00792 findalldevs_if->flags= htonl(d->flags); 00793 00794 for (address= d->addresses; address != NULL; address= address->next) 00795 findalldevs_if->naddr++; 00796 00797 findalldevs_if->naddr= htons(findalldevs_if->naddr); 00798 00799 if (sock_bufferize(d->name, lname, sendbuf, &sendbufidx, 00800 RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1) 00801 return -1; 00802 00803 if (sock_bufferize(d->description, ldescr, sendbuf, &sendbufidx, 00804 RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1) 00805 return -1; 00806 00807 // send all addresses 00808 for (address= d->addresses; address != NULL; address= address->next) 00809 { 00810 struct sockaddr_storage *sockaddr; 00811 00812 sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx]; 00813 if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL, 00814 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) 00815 return -1; 00816 daemon_seraddr( (struct sockaddr_storage *) address->addr, sockaddr); 00817 00818 sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx]; 00819 if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL, 00820 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) 00821 return -1; 00822 daemon_seraddr( (struct sockaddr_storage *) address->netmask, sockaddr); 00823 00824 sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx]; 00825 if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL, 00826 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) 00827 return -1; 00828 daemon_seraddr( (struct sockaddr_storage *) address->broadaddr, sockaddr); 00829 00830 sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx]; 00831 if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL, 00832 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) 00833 return -1; 00834 daemon_seraddr( (struct sockaddr_storage *) address->dstaddr, sockaddr); 00835 } 00836 } 00837 00838 // Send a final command that says "now send it!" 00839 if (sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1) 00840 return -1; 00841 00842 // We do no longer need the device list. Free it 00843 pcap_freealldevs(alldevs); 00844 00845 // everything is fine 00846 return 0; 00847 } 00848 00849 00850 00851 00852 00853 /* 00854 \param plen: the length of the current message (needed in order to be able 00855 to discard excess data in the message, if present) 00856 */ 00857 int daemon_opensource(SOCKET sockctrl, char *source, int srclen, uint32 plen, char *errbuf) 00858 { 00859 pcap_t *fp= NULL; // pcap_t main variable 00860 unsigned int nread; // number of bytes of the payload read from the socket 00861 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered 00862 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 00863 struct rpcap_openreply *openreply; // open reply message 00864 00865 00866 strcpy(source, PCAP_SRC_IF_STRING); 00867 00868 if (srclen <= (int) (strlen(PCAP_SRC_IF_STRING) + plen) ) 00869 { 00870 rpcap_senderror(sockctrl, "Source string too long", PCAP_ERR_OPEN, NULL); 00871 return -1; 00872 } 00873 00874 if ( (nread= sock_recv(sockctrl, &source[strlen(PCAP_SRC_IF_STRING)], plen, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1) 00875 return -1; 00876 00877 // Check if all the data has been read; if not, discard the data in excess 00878 if (nread != plen) 00879 sock_discard(sockctrl, plen - nread, NULL, 0); 00880 00881 // Puts a '0' to terminate the source string 00882 source[strlen(PCAP_SRC_IF_STRING) + plen]= 0; 00883 00884 // Open the selected device 00885 // This is a fake open, since we do that only to get the needed parameters, then we close the device again 00886 if ( (fp= pcap_open(source, 00887 1500 /* fake snaplen */, 00888 0 /* no promis */, 00889 1000 /* fake timeout */, 00890 NULL /* local device, so no auth */, 00891 errbuf)) == NULL) 00892 { 00893 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_OPEN, NULL); 00894 return -1; 00895 } 00896 00897 00898 // Now, I can send a RPCAP open reply message 00899 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, 00900 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) 00901 goto error; 00902 00903 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_OPEN_REPLY, 0, sizeof(struct rpcap_openreply) ); 00904 00905 openreply= (struct rpcap_openreply *) &sendbuf[sendbufidx]; 00906 00907 if ( sock_bufferize(NULL, sizeof(struct rpcap_openreply), NULL, &sendbufidx, 00908 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) 00909 goto error; 00910 00911 memset(openreply, 0, sizeof(struct rpcap_openreply) ); 00912 openreply->linktype= htonl(fp->linktype); 00913 openreply->tzoff= htonl(fp->tzoff); 00914 00915 if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1) 00916 goto error; 00917 00918 // I have to close the device again, since it has been opened with wrong parameters 00919 pcap_close(fp); 00920 fp= NULL; 00921 00922 return 0; 00923 00924 error: 00925 if (fp) 00926 { 00927 pcap_close(fp); 00928 fp= NULL; 00929 } 00930 00931 return -1; 00932 } 00933 00934 00935 00936 00937 00938 /* 00939 \param plen: the length of the current message (needed in order to be able 00940 to discard excess data in the message, if present) 00941 */ 00942 pcap_t *daemon_startcapture(SOCKET sockctrl, pthread_t *threaddata, char *source, int active, struct rpcap_sampling *samp_param, uint32 plen, char *errbuf) 00943 { 00944 char portdata[PCAP_BUF_SIZE]; // temp variable needed to derive the data port 00945 char peerhost[PCAP_BUF_SIZE]; // temp variable needed to derive the host name of our peer 00946 pcap_t *fp= NULL; // pcap_t main variable 00947 unsigned int nread; // number of bytes of the payload read from the socket 00948 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered 00949 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 00950 00951 // socket-related variables 00952 SOCKET sockdata= 0; // socket descriptor of the data connection 00953 struct addrinfo hints; // temp, needed to open a socket connection 00954 struct addrinfo *addrinfo; // temp, needed to open a socket connection 00955 struct sockaddr_storage saddr; // temp, needed to retrieve the network data port chosen on the local machine 00956 socklen_t saddrlen; // temp, needed to retrieve the network data port chosen on the local machine 00957 00958 pthread_attr_t detachedAttribute; // temp, needed to set the created thread as detached 00959 00960 // RPCAP-related variables 00961 struct rpcap_startcapreq startcapreq; // start capture request message 00962 struct rpcap_startcapreply *startcapreply; // start capture reply message 00963 int serveropen_dp; // keeps who is going to open the data connection 00964 00965 addrinfo= NULL; 00966 00967 if ( (nread= sock_recv(sockctrl, (char *) &startcapreq, sizeof(struct rpcap_startcapreq), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1) 00968 return NULL; 00969 00970 startcapreq.flags= ntohs(startcapreq.flags); 00971 00972 // Open the selected device 00973 if ( (fp= pcap_open(source, 00974 ntohl(startcapreq.snaplen), 00975 (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_PROMISC) ? PCAP_OPENFLAG_PROMISCUOUS : 0 /* local device, other flags not needed */, 00976 ntohl(startcapreq.read_timeout), 00977 NULL /* local device, so no auth */, 00978 errbuf)) == NULL) 00979 { 00980 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_OPEN, NULL); 00981 return NULL; 00982 } 00983 00984 // Apply sampling parameters 00985 fp->rmt_samp.method= samp_param->method; 00986 fp->rmt_samp.value= samp_param->value; 00987 00988 /* 00989 We're in active mode if: 00990 - we're using TCP, and the user wants us to be in active mode 00991 - we're using UDP 00992 */ 00993 serveropen_dp= (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_SERVEROPEN) || (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) || active; 00994 00995 /* 00996 Gets the sockaddr structure referred to the other peer in the ctrl connection 00997 00998 We need that because: 00999 - if we're in passive mode, we need to know the address family we want to use 01000 (the same used for the ctrl socket) 01001 - if we're in active mode, we need to know the network address of the other host 01002 we want to connect to 01003 */ 01004 saddrlen = sizeof(struct sockaddr_storage); 01005 if (getpeername(sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1) 01006 { 01007 sock_geterror("getpeername(): ", errbuf, PCAP_ERRBUF_SIZE); 01008 goto error; 01009 } 01010 01011 memset(&hints, 0, sizeof(struct addrinfo) ); 01012 hints.ai_socktype = (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) ? SOCK_DGRAM : SOCK_STREAM; 01013 hints.ai_family = saddr.ss_family; 01014 01015 // Now we have to create a new socket to send packets 01016 if (serveropen_dp) // Data connection is opened by the server toward the client 01017 { 01018 sprintf(portdata, "%d", ntohs(startcapreq.portdata) ); 01019 01020 // Get the name of the other peer (needed to connect to that specific network address) 01021 if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, peerhost, 01022 sizeof(peerhost), NULL, 0, NI_NUMERICHOST) ) 01023 { 01024 sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE); 01025 goto error; 01026 } 01027 01028 if (sock_initaddress(peerhost, portdata, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1) 01029 goto error; 01030 01031 if ( (sockdata= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1) 01032 goto error; 01033 } 01034 else // Data connection is opened by the client toward the server 01035 { 01036 hints.ai_flags = AI_PASSIVE; 01037 01038 // Let's the server socket pick up a free network port for us 01039 if (sock_initaddress(NULL, "0", &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1) 01040 goto error; 01041 01042 if ( (sockdata= sock_open(addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, errbuf, PCAP_ERRBUF_SIZE)) == -1) 01043 goto error; 01044 01045 // get the complete sockaddr structure used in the data connection 01046 saddrlen = sizeof(struct sockaddr_storage); 01047 if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1) 01048 { 01049 sock_geterror("getsockname(): ", errbuf, PCAP_ERRBUF_SIZE); 01050 goto error; 01051 } 01052 01053 // Get the local port the system picked up 01054 if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, NULL, 01055 0, portdata, sizeof(portdata), NI_NUMERICSERV) ) 01056 { 01057 sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE); 01058 goto error; 01059 } 01060 } 01061 01062 // addrinfo is no longer used 01063 freeaddrinfo(addrinfo); 01064 addrinfo= NULL; 01065 01066 // save the socket ID for the next calls 01067 fp->rmt_sockctrl= sockctrl; // Needed to send an error on the ctrl connection 01068 01069 // Now I can set the filter 01070 if ( daemon_unpackapplyfilter(fp, &nread, &plen, errbuf) ) 01071 goto error; 01072 01073 01074 // Now, I can send a RPCAP start capture reply message 01075 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, 01076 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) 01077 goto error; 01078 01079 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STARTCAP_REPLY, 0, sizeof(struct rpcap_startcapreply) ); 01080 01081 startcapreply= (struct rpcap_startcapreply *) &sendbuf[sendbufidx]; 01082 01083 if ( sock_bufferize(NULL, sizeof(struct rpcap_startcapreply), NULL, 01084 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) 01085 goto error; 01086 01087 memset(startcapreply, 0, sizeof(struct rpcap_startcapreply) ); 01088 startcapreply->bufsize= htonl(fp->bufsize); 01089 01090 if (!serveropen_dp) 01091 { 01092 sscanf(portdata, "%d", (int *) &(startcapreply->portdata) ); 01093 startcapreply->portdata= htons(startcapreply->portdata); 01094 } 01095 01096 if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1) 01097 goto error; 01098 01099 if (!serveropen_dp) 01100 { 01101 SOCKET socktemp; // We need another socket, since we're going to accept() a connection 01102 01103 // Connection creation 01104 saddrlen = sizeof(struct sockaddr_storage); 01105 01106 socktemp= accept(sockdata, (struct sockaddr *) &saddr, &saddrlen); 01107 01108 if (socktemp == -1) 01109 { 01110 sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE); 01111 goto error; 01112 } 01113 01114 // Now that I accepted the connection, the server socket is no longer needed 01115 sock_close(sockdata, errbuf, PCAP_ERRBUF_SIZE); 01116 sockdata= socktemp; 01117 } 01118 01119 fp->rmt_sockdata= sockdata; 01120 01121 /* GV we need this to create the thread as detached. */ 01122 /* GV otherwise, the thread handle is not destroyed */ 01123 pthread_attr_init(&detachedAttribute); 01124 pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED); 01125 01126 // Now we have to create a new thread to receive packets 01127 if ( pthread_create(threaddata, &detachedAttribute, (void *) daemon_thrdatamain, (void *) fp) ) 01128 { 01129 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread"); 01130 pthread_attr_destroy(&detachedAttribute); 01131 goto error; 01132 } 01133 01134 pthread_attr_destroy(&detachedAttribute); 01135 // Check if all the data has been read; if not, discard the data in excess 01136 if (nread != plen) 01137 sock_discard(sockctrl, plen - nread, NULL, 0); 01138 01139 return fp; 01140 01141 error: 01142 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_STARTCAPTURE, NULL); 01143 01144 if (addrinfo) 01145 freeaddrinfo(addrinfo); 01146 01147 if (threaddata) 01148 pthread_cancel(*threaddata); 01149 01150 if (sockdata) 01151 sock_close(sockdata, NULL, 0); 01152 01153 // Check if all the data has been read; if not, discard the data in excess 01154 if (nread != plen) 01155 sock_discard(sockctrl, plen - nread, NULL, 0); 01156 01157 if (fp) 01158 { 01159 pcap_close(fp); 01160 fp= NULL; 01161 } 01162 01163 return NULL; 01164 } 01165 01166 01167 01168 int daemon_endcapture(pcap_t *fp, pthread_t *threaddata, char *errbuf) 01169 { 01170 struct rpcap_header header; 01171 SOCKET sockctrl; 01172 01173 if (threaddata) 01174 { 01175 pthread_cancel(*threaddata); 01176 threaddata= 0; 01177 } 01178 if (fp->rmt_sockdata) 01179 { 01180 sock_close(fp->rmt_sockdata, NULL, 0); 01181 fp->rmt_sockdata= 0; 01182 } 01183 01184 sockctrl= fp->rmt_sockctrl; 01185 01186 pcap_close(fp); 01187 fp= NULL; 01188 01189 rpcap_createhdr( &header, RPCAP_MSG_ENDCAP_REPLY, 0, 0); 01190 01191 if ( sock_send(sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1) 01192 return -1; 01193 01194 return 0; 01195 } 01196 01197 01198 01199 int daemon_unpackapplyfilter(pcap_t *fp, unsigned int *nread, int *plen, char *errbuf) 01200 { 01201 struct rpcap_filter filter; 01202 struct rpcap_filterbpf_insn insn; 01203 struct bpf_insn *bf_insn; 01204 struct bpf_program bf_prog; 01205 unsigned int i; 01206 01207 01208 if ( ( *nread+= sock_recv(fp->rmt_sockctrl, (char *) &filter, sizeof(struct rpcap_filter), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1) 01209 { 01210 // to avoid blocking on the sock_discard() 01211 *plen= *nread; 01212 return -1; 01213 } 01214 01215 bf_prog.bf_len= ntohl(filter.nitems); 01216 01217 if (ntohs(filter.filtertype) != RPCAP_UPDATEFILTER_BPF) 01218 { 01219 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Only BPF/NPF filters are currently supported"); 01220 return -1; 01221 } 01222 01223 bf_insn= (struct bpf_insn *) malloc ( sizeof(struct bpf_insn) * bf_prog.bf_len); 01224 if (bf_insn == NULL) 01225 { 01226 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); 01227 return -1; 01228 } 01229 01230 bf_prog.bf_insns= bf_insn; 01231 01232 for (i= 0; i < bf_prog.bf_len; i++) 01233 { 01234 if ( ( *nread+= sock_recv(fp->rmt_sockctrl, (char *) &insn, 01235 sizeof(struct rpcap_filterbpf_insn), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1) 01236 return -1; 01237 01238 bf_insn->code= ntohs(insn.code); 01239 bf_insn->jf= insn.jf; 01240 bf_insn->jt= insn.jt; 01241 bf_insn->k= ntohl(insn.k); 01242 01243 bf_insn++; 01244 } 01245 01246 if (bpf_validate(bf_prog.bf_insns, bf_prog.bf_len) == 0) 01247 { 01248 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The filter contains bogus instructions"); 01249 return -1; 01250 } 01251 01252 if (pcap_setfilter(fp, &bf_prog) ) 01253 { 01254 snprintf(errbuf, PCAP_ERRBUF_SIZE, "RPCAP error: %s", fp->errbuf); 01255 return -1; 01256 } 01257 01258 return 0; 01259 } 01260 01261 01262 01263 int daemon_updatefilter(pcap_t *fp, uint32 plen) 01264 { 01265 struct rpcap_header header; // keeps the answer to the updatefilter command 01266 unsigned int nread; 01267 01268 nread= 0; 01269 01270 if ( daemon_unpackapplyfilter(fp, &nread, &plen, fp->errbuf) ) 01271 goto error; 01272 01273 // Check if all the data has been read; if not, discard the data in excess 01274 if (nread != plen) 01275 { 01276 if (sock_discard(fp->rmt_sockctrl, plen - nread, NULL, 0) ) 01277 { 01278 nread= plen; // just to avoid to call discard again in the 'error' section 01279 goto error; 01280 } 01281 } 01282 01283 // A response is needed, otherwise the other host does not know that everything went well 01284 rpcap_createhdr( &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0); 01285 01286 if ( sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), fp->errbuf, PCAP_ERRBUF_SIZE) ) 01287 goto error; 01288 01289 return 0; 01290 01291 01292 error: 01293 if (nread != plen) 01294 sock_discard(fp->rmt_sockctrl, plen - nread, NULL, 0); 01295 01296 rpcap_senderror(fp->rmt_sockctrl, fp->errbuf, PCAP_ERR_UPDATEFILTER, NULL); 01297 01298 return -1; 01299 } 01300 01301 01302 01306 int daemon_setsampling(SOCKET sockctrl, struct rpcap_sampling *samp_param, int plen, char *errbuf) 01307 { 01308 struct rpcap_header header; 01309 struct rpcap_sampling rpcap_samp; 01310 int nread; // number of bytes of the payload read from the socket 01311 01312 01313 if ( ( nread= sock_recv(sockctrl, (char *) &rpcap_samp, sizeof(struct rpcap_sampling), 01314 SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1) 01315 goto error; 01316 01317 01318 // Save these settings in the pcap_t 01319 samp_param->method= rpcap_samp.method; 01320 samp_param->value= ntohl(rpcap_samp.value); 01321 01322 01323 // A response is needed, otherwise the other host does not know that everything went well 01324 rpcap_createhdr( &header, RPCAP_MSG_SETSAMPLING_REPLY, 0, 0); 01325 01326 if ( sock_send(sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) ) 01327 goto error; 01328 01329 if (nread != plen) 01330 sock_discard(sockctrl, plen - nread, NULL, 0); 01331 01332 return 0; 01333 01334 error: 01335 if (nread != plen) 01336 sock_discard(sockctrl, plen - nread, NULL, 0); 01337 01338 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_SETSAMPLING, NULL); 01339 01340 return -1; 01341 } 01342 01343 01344 01345 int daemon_getstats(pcap_t *fp) 01346 { 01347 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered 01348 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 01349 struct pcap_stat stats; // local statistics 01350 struct rpcap_stats *netstats; // statistics sent on the network 01351 01352 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 01353 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) == -1) 01354 goto error; 01355 01356 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats)); 01357 01358 netstats= (struct rpcap_stats *) &sendbuf[sendbufidx]; 01359 01360 if ( sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL, 01361 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) == -1) 01362 goto error; 01363 01364 if (pcap_stats(fp, &stats) ) 01365 goto error; 01366 01367 netstats->ifdrop= htonl(stats.ps_ifdrop); 01368 netstats->ifrecv= htonl(stats.ps_recv); 01369 netstats->krnldrop= htonl(stats.ps_drop); 01370 netstats->svrcapt= htonl(fp->md.TotCapt); 01371 01372 // Send the packet 01373 if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) == -1) 01374 goto error; 01375 01376 return 0; 01377 01378 error: 01379 rpcap_senderror(fp->rmt_sockctrl, fp->errbuf, PCAP_ERR_GETSTATS, NULL); 01380 return -1; 01381 } 01382 01383 01384 01385 01386 int daemon_getstatsnopcap(SOCKET sockctrl, unsigned int ifdrops, unsigned int ifrecv, 01387 unsigned int krnldrop, unsigned int svrcapt, char *errbuf) 01388 { 01389 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered 01390 int sendbufidx= 0; // index which keeps the number of bytes currently buffered 01391 struct rpcap_stats *netstats; // statistics sent on the network 01392 01393 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, 01394 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) 01395 goto error; 01396 01397 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats)); 01398 01399 netstats= (struct rpcap_stats *) &sendbuf[sendbufidx]; 01400 01401 if ( sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL, 01402 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) 01403 goto error; 01404 01405 netstats->ifdrop= htonl(ifdrops); 01406 netstats->ifrecv= htonl(ifrecv); 01407 netstats->krnldrop= htonl(krnldrop); 01408 netstats->svrcapt= htonl(svrcapt); 01409 01410 // Send the packet 01411 if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1) 01412 goto error; 01413 01414 return 0; 01415 01416 error: 01417 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_GETSTATS, NULL); 01418 return -1; 01419 } 01420 01421 01422 01423 01424 void *daemon_thrdatamain(void *ptr) 01425 { 01426 char errbuf[PCAP_ERRBUF_SIZE + 1]; // error buffer 01427 pcap_t *fp; // pointer to a 'pcap' structure 01428 int retval; // general variable used to keep the return value of other functions 01429 struct rpcap_pkthdr *net_pkt_header;// header of the packet 01430 struct pcap_pkthdr *pkt_header; // pointer to the buffer that contains the header of the current packet 01431 u_char *pkt_data; // pointer to the buffer that contains the current packet 01432 char *sendbuf; // temporary buffer in which data to be sent is buffered 01433 int sendbufidx; // index which keeps the number of bytes currently buffered 01434 01435 fp= (pcap_t *) ptr; 01436 01437 fp->md.TotCapt= 0; // counter which is incremented each time a packet is received 01438 01439 // Initialize errbuf 01440 memset(errbuf, 0, sizeof(errbuf) ); 01441 01442 // Some platforms (e.g. Win32) allow creating a static variable with this size 01443 // However, others (e.g. BSD) do not, so we're forced to allocate this buffer dynamically 01444 sendbuf= (char *) malloc (sizeof(char) * RPCAP_NETBUF_SIZE); 01445 if (sendbuf == NULL) 01446 { 01447 snprintf(errbuf, sizeof(errbuf) - 1, "Unable to create the buffer for this child thread"); 01448 goto error; 01449 } 01450 01451 // Modify thread params so that it can be killed at any time 01452 if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) ) 01453 goto error; 01454 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) ) 01455 goto error; 01456 01457 // Retrieve the packets 01458 while ((retval = pcap_next_ex(fp, &pkt_header, (const u_char **) &pkt_data)) >= 0) // cast to avoid a compiler warning 01459 { 01460 if (retval == 0) // Read timeout elapsed 01461 continue; 01462 01463 sendbufidx= 0; 01464 01465 // Bufferize the general header 01466 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, 01467 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) 01468 goto error; 01469 01470 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_PACKET, 0, 01471 (uint16) (sizeof(struct rpcap_pkthdr) + pkt_header->caplen) ); 01472 01473 net_pkt_header= (struct rpcap_pkthdr *) &sendbuf[sendbufidx]; 01474 01475 // Bufferize the pkt header 01476 if ( sock_bufferize(NULL, sizeof(struct rpcap_pkthdr), NULL, &sendbufidx, 01477 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) 01478 goto error; 01479 01480 net_pkt_header->caplen= htonl(pkt_header->caplen); 01481 net_pkt_header->len= htonl(pkt_header->len); 01482 net_pkt_header->npkt= htonl( ++(fp->md.TotCapt) ); 01483 net_pkt_header->timestamp_sec= htonl(pkt_header->ts.tv_sec); 01484 net_pkt_header->timestamp_usec= htonl(pkt_header->ts.tv_usec); 01485 01486 // Bufferize the pkt data 01487 if ( sock_bufferize((char *) pkt_data, pkt_header->caplen, sendbuf, &sendbufidx, 01488 RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1) 01489 goto error; 01490 01491 // Send the packet 01492 if ( sock_send(fp->rmt_sockdata, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1) 01493 goto error; 01494 01495 } 01496 01497 if (retval == -1) 01498 { 01499 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(fp) ); 01500 rpcap_senderror(fp->rmt_sockctrl, errbuf, PCAP_ERR_READEX, NULL); 01501 goto error; 01502 } 01503 01504 error: 01505 01506 SOCK_ASSERT(errbuf, 1); 01507 closesocket(fp->rmt_sockdata); 01508 fp->rmt_sockdata= 0; 01509 01510 free(sendbuf); 01511 01512 return NULL; 01513 } 01514 01515 01516 01534 void daemon_seraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage *sockaddrout) 01535 { 01536 memset(sockaddrout, 0, sizeof(struct sockaddr_storage) ); 01537 01538 // There can be the case in which the sockaddrin is not available 01539 if (sockaddrin == NULL) return; 01540 01541 // Warning: we support only AF_INET and AF_INET6 01542 if (sockaddrin->ss_family == AF_INET) 01543 { 01544 struct sockaddr_in *sockaddr; 01545 01546 sockaddr= (struct sockaddr_in *) sockaddrin; 01547 sockaddr->sin_family= htons(sockaddr->sin_family); 01548 sockaddr->sin_port= htons(sockaddr->sin_port); 01549 memcpy(sockaddrout, sockaddr, sizeof(struct sockaddr_in) ); 01550 } 01551 else 01552 { 01553 struct sockaddr_in6 *sockaddr; 01554 01555 sockaddr= (struct sockaddr_in6 *) sockaddrin; 01556 sockaddr->sin6_family= htons(sockaddr->sin6_family); 01557 sockaddr->sin6_port= htons(sockaddr->sin6_port); 01558 sockaddr->sin6_flowinfo= htonl(sockaddr->sin6_flowinfo); 01559 sockaddr->sin6_scope_id= htonl(sockaddr->sin6_scope_id); 01560 memcpy(sockaddrout, sockaddr, sizeof(struct sockaddr_in6) ); 01561 } 01562 } 01563 01564 01565 01566 01567 01573 void pthread_suspend(int msec) 01574 { 01575 #ifdef WIN32 01576 Sleep(msec); 01577 #else 01578 struct timespec abstime; 01579 struct timeval now; 01580 01581 pthread_cond_t cond; 01582 pthread_mutex_t mutex; 01583 pthread_mutexattr_t attr; 01584 01585 pthread_mutexattr_init(&attr); 01586 pthread_mutex_init(&mutex, &attr); 01587 pthread_mutex_lock(&mutex); 01588 01589 pthread_cond_init(&cond, NULL); 01590 01591 gettimeofday(&now, NULL); 01592 01593 abstime.tv_sec = now.tv_sec + msec/1000; 01594 abstime.tv_nsec = now.tv_usec * 1000 + (msec%1000) * 1000 * 1000; 01595 01596 pthread_cond_timedwait(&cond, &mutex, &abstime); 01597 01598 pthread_mutex_destroy(&mutex); 01599 pthread_cond_destroy(&cond); 01600 #endif 01601 } 01602 01603 01604
documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.