add winpcap 4.0.2 from url http://www.winpcap.org/
[natblaster.git] / winpcap / wpcap / libpcap / rpcapd / daemon.c
blob6d31b7d559972a53aa8f8eaf1078067c19738348
1 /*
2 * Copyright (c) 2002 - 2003
3 * NetGroup, Politecnico di Torino (Italy)
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the Politecnico di Torino nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <pcap.h> // for libpcap/WinPcap calls
34 #include <pcap-int.h> // for the pcap_t definition
35 #include <errno.h> // for the errno variable
36 #include <stdlib.h> // for malloc(), free(), ...
37 #include <string.h> // for strlen(), ...
38 #include <pthread.h>
39 #include "pcap-remote.h"
40 #include "daemon.h"
41 #include "sockutils.h" // for socket calls
43 #ifndef WIN32 // for select() and such
44 #include <unistd.h>
45 #include <sys/time.h>
46 #include <sys/types.h>
47 #include <pwd.h> // for password management
48 #endif
50 #ifdef linux
51 #include <shadow.h> // for password management
52 #endif
56 // Locally defined functions
57 int daemon_checkauth(SOCKET sockctrl, int nullAuthAllowed, char *errbuf);
58 int daemon_AuthUserPwd(char *username, char *password, char *errbuf);
60 int daemon_findalldevs(SOCKET sockctrl, char *errbuf);
62 int daemon_opensource(SOCKET sockctrl, char *source, int srclen, uint32 plen, char *errbuf);
63 pcap_t *daemon_startcapture(SOCKET sockctrl, pthread_t *threaddata, char *source, int active,
64 struct rpcap_sampling *samp_param, uint32 plen, char *errbuf);
65 int daemon_endcapture(pcap_t *fp, pthread_t *threaddata, char *errbuf);
67 int daemon_updatefilter(pcap_t *fp, uint32 plen);
68 int daemon_unpackapplyfilter(pcap_t *fp, unsigned int *nread, int *plen, char *errbuf);
70 int daemon_getstats(pcap_t *fp);
71 int daemon_getstatsnopcap(SOCKET sockctrl, unsigned int ifdrops, unsigned int ifrecv,
72 unsigned int krnldrop, unsigned int svrcapt, char *errbuf);
74 int daemon_setsampling(SOCKET sockctrl, struct rpcap_sampling *samp_param, int plen, char *errbuf);
76 void daemon_seraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage *sockaddrout);
77 void *daemon_thrdatamain(void *ptr);
85 /*!
86 \brief Main serving funtion
87 This function is the one which does the job. It is the main() of the child
88 thread, which is created as soon as a new connection is accepted.
90 \param ptr: a void pointer that keeps the reference of the 'pthread_chain'
91 value corrisponding to this thread. This variable is casted into a 'pthread_chain'
92 value in order to retrieve the socket we're currently using, the therad ID, and
93 some pointers to the previous and next elements into this struct.
95 \return None.
97 void daemon_serviceloop( void *ptr )
99 char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
100 char source[PCAP_BUF_SIZE]; // keeps the string that contains the interface to open
101 struct rpcap_header header; // RPCAP message general header
102 pcap_t *fp= NULL; // pcap_t main variable
103 struct daemon_slpars *pars; // parameters related to the present daemon loop
105 pthread_t threaddata= 0; // handle to the 'read from daemon and send to client' thread
107 unsigned int ifdrops, ifrecv, krnldrop, svrcapt; // needed to save the values of the statistics
109 struct rpcap_sampling samp_param; // in case sampling has been requested
111 // Structures needed for the select() call
112 fd_set rfds; // set of socket descriptors we have to check
113 struct timeval tv; // maximum time the select() can block waiting for data
114 int retval; // select() return value
117 pars= (struct daemon_slpars *) ptr;
119 *errbuf= 0; // Initialize errbuf
121 // If we're in active mode, this is not a separate thread
122 if (! pars->isactive)
124 // Modify thread params so that it can be killed at any time
125 if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) )
126 goto end;
127 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) )
128 goto end;
131 auth_again:
132 // If we're in active mode, we have to check for the initial timeout
133 if (!pars->isactive)
135 FD_ZERO(&rfds);
136 // We do not have to block here
137 tv.tv_sec = RPCAP_TIMEOUT_INIT;
138 tv.tv_usec = 0;
140 FD_SET(pars->sockctrl, &rfds);
142 retval = select(pars->sockctrl + 1, &rfds, NULL, NULL, &tv);
143 if (retval == -1)
145 sock_geterror("select(): ", errbuf, PCAP_ERRBUF_SIZE);
146 rpcap_senderror(pars->sockctrl, errbuf, PCAP_ERR_NETW, NULL);
147 goto end;
150 // The timeout has expired
151 // So, this was a fake connection. Drop it down
152 if (retval == 0)
154 rpcap_senderror(pars->sockctrl, "The RPCAP initial timeout has expired", PCAP_ERR_INITTIMEOUT, NULL);
155 goto end;
160 retval= daemon_checkauth(pars->sockctrl, pars->nullAuthAllowed, errbuf);
162 if (retval)
164 // the other user requested to close the connection
165 // It can be also the case of 'active mode', in which this host is not
166 // allowed to connect to the other peer; in that case, it drops down the connection
167 if (retval == -3)
168 goto end;
170 // It can be an authentication failure or an unrecoverable error
171 rpcap_senderror(pars->sockctrl, errbuf, PCAP_ERR_AUTH, NULL);
173 // authentication error
174 if (retval == -2)
176 // suspend for 1 sec
177 // WARNING: this day is inserted only in this point; if the user drops down the connection
178 // and it connects again, this suspension time does not have any effects.
179 pthread_suspend(RPCAP_SUSPEND_WRONGAUTH*1000);
180 goto auth_again;
183 // Unrecoverable error
184 if (retval == -1)
185 goto end;
188 while (1)
190 int retval;
192 errbuf[0]= 0; // clear errbuf
194 // Avoid zombies connections; check if the connection is opens but no commands are performed
195 // from more than RPCAP_TIMEOUT_RUNTIME
196 // Conditions:
197 // - I have to be in normal mode (no active mode)
198 // - if the device is open, I don't have to be in the middle of a capture (fp->rmt_sockdata)
199 // - if the device is closed, I have always to check if a new command arrives
201 // Be carefully: the capture can have been started, but an error occurred (so fp != NULL, but
202 // rmt_sockdata is 0
203 if ( (!pars->isactive) && ( (fp == NULL) || ( (fp != NULL) && (fp->rmt_sockdata == 0) ) ))
205 // Check for the initial timeout
206 FD_ZERO(&rfds);
207 // We do not have to block here
208 tv.tv_sec = RPCAP_TIMEOUT_RUNTIME;
209 tv.tv_usec = 0;
211 FD_SET(pars->sockctrl, &rfds);
213 retval = select(pars->sockctrl + 1, &rfds, NULL, NULL, &tv);
214 if (retval == -1)
216 sock_geterror("select(): ", errbuf, PCAP_ERRBUF_SIZE);
217 rpcap_senderror(pars->sockctrl, errbuf, PCAP_ERR_NETW, NULL);
218 goto end;
221 // The timeout has expired
222 // So, this was a fake connection. Drop it down
223 if (retval == 0)
225 SOCK_ASSERT("The RPCAP runtime timeout has expired", 1);
226 rpcap_senderror(pars->sockctrl, "The RPCAP runtime timeout has expired", PCAP_ERR_RUNTIMETIMEOUT, NULL);
227 goto end;
231 if (sock_recv(pars->sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
232 goto end;
234 // Checks if the message is correct
235 // In case it is wrong, it discard the data
236 retval= rpcap_checkmsg(errbuf, pars->sockctrl, &header,
237 RPCAP_MSG_FINDALLIF_REQ,
238 RPCAP_MSG_OPEN_REQ,
239 RPCAP_MSG_STARTCAP_REQ,
240 RPCAP_MSG_UPDATEFILTER_REQ,
241 RPCAP_MSG_STATS_REQ,
242 RPCAP_MSG_ENDCAP_REQ,
243 RPCAP_MSG_SETSAMPLING_REQ,
244 RPCAP_MSG_CLOSE,
245 RPCAP_MSG_ERROR,
248 switch (retval)
250 case -3: // Unrecoverable network error
251 goto end; // Do nothing; just exit from findalldevs; the error code is already into the errbuf
253 case -2: // The other endpoint send a message that is not allowed here
255 rpcap_senderror(pars->sockctrl, "The RPCAP daemon received a message that is not valid", PCAP_ERR_WRONGMSG, errbuf);
257 case -1: // The other endpoint has a version number that is not compatible with our
259 rpcap_senderror(pars->sockctrl, "RPCAP version number mismatch", PCAP_ERR_WRONGVER, errbuf);
261 break;
263 case RPCAP_MSG_FINDALLIF_REQ:
265 // Checks that the header does not contain other data; if so, discard it
266 if (ntohl(header.plen))
267 sock_discard(pars->sockctrl, ntohl(header.plen), errbuf, PCAP_ERRBUF_SIZE);
269 if (daemon_findalldevs(pars->sockctrl, errbuf) )
270 SOCK_ASSERT(errbuf, 1);
272 break;
275 case RPCAP_MSG_OPEN_REQ:
277 retval= daemon_opensource(pars->sockctrl, source, sizeof(source), ntohl(header.plen), errbuf);
279 if (retval == -1)
280 SOCK_ASSERT(errbuf, 1);
282 break;
285 case RPCAP_MSG_SETSAMPLING_REQ:
287 retval= daemon_setsampling(pars->sockctrl, &samp_param, ntohl(header.plen), errbuf);
289 if (retval == -1)
290 SOCK_ASSERT(errbuf, 1);
292 break;
295 case RPCAP_MSG_STARTCAP_REQ:
297 fp= daemon_startcapture(pars->sockctrl, &threaddata, source, pars->isactive, &samp_param, ntohl(header.plen), errbuf);
299 if (fp == NULL)
300 SOCK_ASSERT(errbuf, 1);
302 break;
305 case RPCAP_MSG_UPDATEFILTER_REQ:
307 if (fp)
309 if (daemon_updatefilter(fp, ntohl(header.plen)) )
310 SOCK_ASSERT(fp->errbuf, 1);
312 else
314 rpcap_senderror(pars->sockctrl, "Device not opened. Cannot update filter", PCAP_ERR_UPDATEFILTER, errbuf);
317 break;
320 case RPCAP_MSG_STATS_REQ:
322 // Checks that the header does not contain other data; if so, discard it
323 if (ntohl(header.plen))
324 sock_discard(pars->sockctrl, ntohl(header.plen), errbuf, PCAP_ERRBUF_SIZE);
326 if (fp)
328 if (daemon_getstats(fp) )
329 SOCK_ASSERT(fp->errbuf, 1);
331 else
333 SOCK_ASSERT("GetStats: this call should't be allowed here", 1);
335 if (daemon_getstatsnopcap(pars->sockctrl, ifdrops, ifrecv, krnldrop, svrcapt, errbuf) )
336 SOCK_ASSERT(errbuf, 1);
337 // we have to keep compatibility with old applications, which ask for statistics
338 // also when the capture has already stopped
340 // rpcap_senderror(pars->sockctrl, "Device not opened. Cannot get statistics", PCAP_ERR_GETSTATS, errbuf);
343 break;
346 case RPCAP_MSG_ENDCAP_REQ: // The other endpoint close the current capture session
348 if (fp)
350 struct pcap_stat stats;
352 // Save statistics (we can need them in the future)
353 if (pcap_stats(fp, &stats) )
355 ifdrops= stats.ps_ifdrop;
356 ifrecv= stats.ps_recv;
357 krnldrop= stats.ps_drop;
358 svrcapt= fp->md.TotCapt;
360 else
361 ifdrops= ifrecv= krnldrop= svrcapt= 0;
363 if ( daemon_endcapture(fp, &threaddata, errbuf) )
364 SOCK_ASSERT(errbuf, 1);
365 fp= NULL;
367 else
369 rpcap_senderror(pars->sockctrl, "Device not opened. Cannot close the capture", PCAP_ERR_ENDCAPTURE, errbuf);
371 break;
374 case RPCAP_MSG_CLOSE: // The other endpoint close the pcap session
376 // signal to the main that the user closed the control connection
377 // This is used only in case of active mode
378 pars->activeclose= 1;
379 SOCK_ASSERT("The other end system asked to close the connection.", 1);
380 goto end;
381 break;
384 case RPCAP_MSG_ERROR: // The other endpoint reported an error
386 // Do nothing; just exit; the error code is already into the errbuf
387 SOCK_ASSERT(errbuf, 1);
388 break;
391 default:
393 SOCK_ASSERT("Internal error.", 1);
394 break;
399 end:
400 // The child thread is about to end
402 // perform pcap_t cleanup, in case it has not been done
403 if (fp)
405 if (threaddata)
407 pthread_cancel(threaddata);
408 threaddata= 0;
410 if (fp->rmt_sockdata)
412 sock_close(fp->rmt_sockdata, NULL, 0);
413 fp->rmt_sockdata= 0;
415 pcap_close(fp);
416 fp= NULL;
419 // Print message and exit
420 SOCK_ASSERT("I'm exiting from the child loop", 1);
421 SOCK_ASSERT(errbuf, 1);
423 if (!pars->isactive)
425 if (pars->sockctrl)
426 sock_close(pars->sockctrl, NULL, 0);
428 free(pars);
429 #ifdef WIN32
430 pthread_exit(0);
431 #endif
437 \brief It checks if the authentication credentials supplied by the user are valid.
439 This function is called each time the rpcap daemon starts a new serving thread.
440 It reads the authentication message from the network and it checks that the
441 user information are valid.
443 \param sockctrl: the socket if of the control connection.
445 \param nullAuthAllowed: '1' if the NULL authentication is allowed.
447 \param errbuf: a user-allocated buffer in which the error message (if one) has to be written.
449 \return '0' if everything is fine, '-1' if an unrecoverable error occurred.
450 The error message is returned in the 'errbuf' variable.
451 '-2' is returned in case the authentication failed or in case of a recoverable error (like
452 wrong version). In that case, 'errbuf' keeps the reason of the failure. This provides
453 a way to know that the connection does not have to be closed.
455 In case the message is a 'CLOSE' or an 'ERROR', it returns -3. The error can be due to a
456 connection refusal in active mode, since this host cannot be allowed to connect to the remote
457 peer.
459 int daemon_checkauth(SOCKET sockctrl, int nullAuthAllowed, char *errbuf)
461 struct rpcap_header header; // RPCAP message general header
462 int retval; // generic return value
463 unsigned int nread; // number of bytes of the payload read from the socket
464 struct rpcap_auth auth; // RPCAP authentication header
465 char *string1, *string2; // two strings exchanged by the authentication message
466 unsigned int plen; // length of the payload
467 int retcode; // the value we have to return to the caller
469 if (sock_recv(sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -1)
470 return -1;
472 plen= ntohl(header.plen);
474 retval= rpcap_checkmsg(errbuf, sockctrl, &header,
475 RPCAP_MSG_AUTH_REQ,
476 RPCAP_MSG_CLOSE,
479 if (retval != RPCAP_MSG_AUTH_REQ)
481 switch (retval)
483 case -3: // Unrecoverable network error
484 return -1; // Do nothing; just exit; the error code is already into the errbuf
486 case -2: // The other endpoint send a message that is not allowed here
487 case -1: // The other endpoint has a version number that is not compatible with our
488 return -2;
490 case RPCAP_MSG_CLOSE:
492 // Check if all the data has been read; if not, discard the data in excess
493 if (ntohl(header.plen) )
495 if (sock_discard(sockctrl, ntohl(header.plen), NULL, 0) )
497 retcode= -1;
498 goto error;
501 return -3;
504 case RPCAP_MSG_ERROR:
505 return -3;
507 default:
509 SOCK_ASSERT("Internal error.", 1);
510 retcode= -2;
511 goto error;
516 // If it comes here, it means that we have an authentication request message
517 if ( (nread= sock_recv(sockctrl, (char *) &auth, sizeof(struct rpcap_auth), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
519 retcode= -1;
520 goto error;
523 switch (ntohs(auth.type) )
525 case RPCAP_RMTAUTH_NULL:
527 if (!nullAuthAllowed)
529 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed; NULL autentication not permitted.");
530 retcode= -2;
531 goto error;
533 break;
536 case RPCAP_RMTAUTH_PWD:
538 int len1, len2;
540 len1= ntohs(auth.slen1);
541 len2= ntohs(auth.slen2);
543 string1= (char *) malloc (len1 + 1);
544 string2= (char *) malloc (len2 + 1);
546 if ( (string1 == NULL) || (string2 == NULL) )
548 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
549 retcode= -1;
550 goto error;
553 if ( (nread+= sock_recv(sockctrl, string1, len1, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
555 retcode= -1;
556 goto error;
558 if ( (nread+= sock_recv(sockctrl, string2, len2, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
560 retcode= -1;
561 goto error;
564 string1[len1]= 0;
565 string2[len2]= 0;
567 if (daemon_AuthUserPwd(string1, string2, errbuf) )
569 retcode= -2;
570 goto error;
573 break;
576 default:
577 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
578 retcode= -2;
579 goto error;
583 // Check if all the data has been read; if not, discard the data in excess
584 if (nread != plen)
586 if (sock_discard(sockctrl, plen - nread, NULL, 0) )
588 retcode= -1;
589 goto error;
593 rpcap_createhdr(&header, RPCAP_MSG_AUTH_REPLY, 0, 0);
595 // Send the ok message back
596 if ( sock_send(sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
598 retcode= -1;
599 goto error;
602 return 0;
604 error:
605 // Check if all the data has been read; if not, discard the data in excess
606 if (nread != plen)
607 sock_discard(sockctrl, plen - nread, NULL, 0);
609 return retcode;
614 int daemon_AuthUserPwd(char *username, char *password, char *errbuf)
616 #ifdef WIN32
618 Warning: the user which launches the process must have the SE_TCB_NAME right.
619 This corresponds to have the "Act as part of the Operating System" turined on
620 (administrative tools, local security settings, local policies, user right assignment)
621 However, it seems to me that if you run it as a service, this right should be
622 provided by default.
624 HANDLE Token;
625 if (LogonUser(username, ".", password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &Token) == 0)
627 int error;
629 error = GetLastError();
630 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
631 PCAP_ERRBUF_SIZE, NULL);
633 return -1;
636 // This call should change the current thread to the selected user.
637 // I didn't test it.
638 if (ImpersonateLoggedOnUser(Token) == 0)
640 int error;
642 error = GetLastError();
643 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
644 PCAP_ERRBUF_SIZE, NULL);
646 CloseHandle(Token);
647 return -1;
650 CloseHandle(Token);
651 return 0;
653 #else
654 /* Standard user authentication:
655 http://www.unixpapa.com/incnote/passwd.html
656 Problem: it is not able to merge the standard pwd file with the shadow one
658 Shadow user authentication:
659 http://www.tldp.org/HOWTO/Shadow-Password-HOWTO-8.html
660 Problem: the program must either (1) run as root, or (2) run as user, but it
661 must be owned by root and must be SUID root (chmod u+s rpcapd)
664 struct passwd *user;
665 #ifdef linux
666 struct spwd *usersp;
667 #endif
669 // This call is needed to get the uid
670 if ((user= getpwnam(username)) == NULL)
672 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: no such user");
673 return -1;
676 #ifdef linux
677 // This call is needed to get the password; otherwise 'x' is returned
678 if ((usersp= getspnam(username)) == NULL)
680 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: no such user");
681 return -1;
684 if (strcmp(usersp->sp_pwdp, (char *) crypt(password, usersp->sp_pwdp) ) != 0)
686 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: password incorrect");
687 return -1;
689 #endif
691 #ifdef bsd
692 if (strcmp(user->pw_passwd, (char *) crypt(password, user->pw_passwd) ) != 0)
694 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed: password incorrect");
695 return -1;
697 #endif
699 if (setuid(user->pw_uid) )
701 snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s", pcap_strerror(errno) );
702 return -1;
705 /* if (setgid(user->pw_gid) )
707 SOCK_ASSERT("setgid failed", 1);
708 snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s", pcap_strerror(errno) );
709 return -1;
712 return 0;
714 #endif
720 // PORTING WARNING We assume u_int is a 32bit value
721 int daemon_findalldevs(SOCKET sockctrl, char *errbuf)
723 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered
724 int sendbufidx= 0; // index which keeps the number of bytes currently buffered
725 pcap_if_t *alldevs; // pointer to the heade of the interface chain
726 pcap_if_t *d; // temp pointer neede to scan the interface chain
727 uint16 plen= 0; // length of the payload of this message
728 struct pcap_addr *address; // pcap structure that keeps a network address of an interface
729 struct rpcap_findalldevs_if *findalldevs_if;// rpcap structure that packet all the data of an interface together
730 uint16 nif= 0; // counts the number of interface listed
732 // Retrieve the device list
733 if (pcap_findalldevs(&alldevs, errbuf) == -1)
735 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_FINDALLIF, NULL);
736 return -1;
739 if (alldevs == NULL)
741 rpcap_senderror(sockctrl,
742 "No interfaces found! Make sure libpcap/WinPcap is properly installed"
743 " and you have the right to access to the remote device.",
744 PCAP_ERR_NOREMOTEIF,
745 errbuf);
746 return -1;
749 // checks the number of interfaces and it computes the total length of the payload
750 for (d= alldevs; d != NULL; d= d->next)
752 nif++;
754 if (d->description)
755 plen+= strlen(d->description);
756 if (d->name)
757 plen+= strlen(d->name);
759 plen+= sizeof(struct rpcap_findalldevs_if);
761 for (address= d->addresses; address != NULL; address= address->next)
762 plen+= ( sizeof(struct sockaddr_storage) * 4);
765 // RPCAP findalldevs command
766 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
767 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
768 return -1;
770 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_FINDALLIF_REPLY, nif, plen);
772 // send the interface list
773 for (d= alldevs; d != NULL; d= d->next)
775 uint16 lname, ldescr;
777 findalldevs_if= (struct rpcap_findalldevs_if *) &sendbuf[sendbufidx];
779 if ( sock_bufferize(NULL, sizeof(struct rpcap_findalldevs_if), NULL,
780 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
781 return -1;
783 memset(findalldevs_if, 0, sizeof(struct rpcap_findalldevs_if) );
785 if (d->description) ldescr= (short) strlen(d->description);
786 else ldescr= 0;
787 if (d->name) lname= (short) strlen(d->name);
788 else lname= 0;
790 findalldevs_if->desclen= htons(ldescr);
791 findalldevs_if->namelen= htons(lname);
792 findalldevs_if->flags= htonl(d->flags);
794 for (address= d->addresses; address != NULL; address= address->next)
795 findalldevs_if->naddr++;
797 findalldevs_if->naddr= htons(findalldevs_if->naddr);
799 if (sock_bufferize(d->name, lname, sendbuf, &sendbufidx,
800 RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1)
801 return -1;
803 if (sock_bufferize(d->description, ldescr, sendbuf, &sendbufidx,
804 RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1)
805 return -1;
807 // send all addresses
808 for (address= d->addresses; address != NULL; address= address->next)
810 struct sockaddr_storage *sockaddr;
812 sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
813 if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL,
814 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
815 return -1;
816 daemon_seraddr( (struct sockaddr_storage *) address->addr, sockaddr);
818 sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
819 if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL,
820 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
821 return -1;
822 daemon_seraddr( (struct sockaddr_storage *) address->netmask, sockaddr);
824 sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
825 if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL,
826 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
827 return -1;
828 daemon_seraddr( (struct sockaddr_storage *) address->broadaddr, sockaddr);
830 sockaddr= (struct sockaddr_storage *) &sendbuf[sendbufidx];
831 if (sock_bufferize(NULL, sizeof(struct sockaddr_storage), NULL,
832 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
833 return -1;
834 daemon_seraddr( (struct sockaddr_storage *) address->dstaddr, sockaddr);
838 // Send a final command that says "now send it!"
839 if (sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
840 return -1;
842 // We do no longer need the device list. Free it
843 pcap_freealldevs(alldevs);
845 // everything is fine
846 return 0;
854 \param plen: the length of the current message (needed in order to be able
855 to discard excess data in the message, if present)
857 int daemon_opensource(SOCKET sockctrl, char *source, int srclen, uint32 plen, char *errbuf)
859 pcap_t *fp= NULL; // pcap_t main variable
860 unsigned int nread; // number of bytes of the payload read from the socket
861 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered
862 int sendbufidx= 0; // index which keeps the number of bytes currently buffered
863 struct rpcap_openreply *openreply; // open reply message
866 strcpy(source, PCAP_SRC_IF_STRING);
868 if (srclen <= (int) (strlen(PCAP_SRC_IF_STRING) + plen) )
870 rpcap_senderror(sockctrl, "Source string too long", PCAP_ERR_OPEN, NULL);
871 return -1;
874 if ( (nread= sock_recv(sockctrl, &source[strlen(PCAP_SRC_IF_STRING)], plen, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
875 return -1;
877 // Check if all the data has been read; if not, discard the data in excess
878 if (nread != plen)
879 sock_discard(sockctrl, plen - nread, NULL, 0);
881 // Puts a '0' to terminate the source string
882 source[strlen(PCAP_SRC_IF_STRING) + plen]= 0;
884 // Open the selected device
885 // This is a fake open, since we do that only to get the needed parameters, then we close the device again
886 if ( (fp= pcap_open(source,
887 1500 /* fake snaplen */,
888 0 /* no promis */,
889 1000 /* fake timeout */,
890 NULL /* local device, so no auth */,
891 errbuf)) == NULL)
893 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_OPEN, NULL);
894 return -1;
898 // Now, I can send a RPCAP open reply message
899 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
900 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
901 goto error;
903 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_OPEN_REPLY, 0, sizeof(struct rpcap_openreply) );
905 openreply= (struct rpcap_openreply *) &sendbuf[sendbufidx];
907 if ( sock_bufferize(NULL, sizeof(struct rpcap_openreply), NULL, &sendbufidx,
908 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
909 goto error;
911 memset(openreply, 0, sizeof(struct rpcap_openreply) );
912 openreply->linktype= htonl(fp->linktype);
913 openreply->tzoff= htonl(fp->tzoff);
915 if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
916 goto error;
918 // I have to close the device again, since it has been opened with wrong parameters
919 pcap_close(fp);
920 fp= NULL;
922 return 0;
924 error:
925 if (fp)
927 pcap_close(fp);
928 fp= NULL;
931 return -1;
939 \param plen: the length of the current message (needed in order to be able
940 to discard excess data in the message, if present)
942 pcap_t *daemon_startcapture(SOCKET sockctrl, pthread_t *threaddata, char *source, int active, struct rpcap_sampling *samp_param, uint32 plen, char *errbuf)
944 char portdata[PCAP_BUF_SIZE]; // temp variable needed to derive the data port
945 char peerhost[PCAP_BUF_SIZE]; // temp variable needed to derive the host name of our peer
946 pcap_t *fp= NULL; // pcap_t main variable
947 unsigned int nread; // number of bytes of the payload read from the socket
948 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered
949 int sendbufidx= 0; // index which keeps the number of bytes currently buffered
951 // socket-related variables
952 SOCKET sockdata= 0; // socket descriptor of the data connection
953 struct addrinfo hints; // temp, needed to open a socket connection
954 struct addrinfo *addrinfo; // temp, needed to open a socket connection
955 struct sockaddr_storage saddr; // temp, needed to retrieve the network data port chosen on the local machine
956 socklen_t saddrlen; // temp, needed to retrieve the network data port chosen on the local machine
958 pthread_attr_t detachedAttribute; // temp, needed to set the created thread as detached
960 // RPCAP-related variables
961 struct rpcap_startcapreq startcapreq; // start capture request message
962 struct rpcap_startcapreply *startcapreply; // start capture reply message
963 int serveropen_dp; // keeps who is going to open the data connection
965 addrinfo= NULL;
967 if ( (nread= sock_recv(sockctrl, (char *) &startcapreq, sizeof(struct rpcap_startcapreq), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
968 return NULL;
970 startcapreq.flags= ntohs(startcapreq.flags);
972 // Open the selected device
973 if ( (fp= pcap_open(source,
974 ntohl(startcapreq.snaplen),
975 (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_PROMISC) ? PCAP_OPENFLAG_PROMISCUOUS : 0 /* local device, other flags not needed */,
976 ntohl(startcapreq.read_timeout),
977 NULL /* local device, so no auth */,
978 errbuf)) == NULL)
980 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_OPEN, NULL);
981 return NULL;
984 // Apply sampling parameters
985 fp->rmt_samp.method= samp_param->method;
986 fp->rmt_samp.value= samp_param->value;
989 We're in active mode if:
990 - we're using TCP, and the user wants us to be in active mode
991 - we're using UDP
993 serveropen_dp= (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_SERVEROPEN) || (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) || active;
996 Gets the sockaddr structure referred to the other peer in the ctrl connection
998 We need that because:
999 - if we're in passive mode, we need to know the address family we want to use
1000 (the same used for the ctrl socket)
1001 - if we're in active mode, we need to know the network address of the other host
1002 we want to connect to
1004 saddrlen = sizeof(struct sockaddr_storage);
1005 if (getpeername(sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
1007 sock_geterror("getpeername(): ", errbuf, PCAP_ERRBUF_SIZE);
1008 goto error;
1011 memset(&hints, 0, sizeof(struct addrinfo) );
1012 hints.ai_socktype = (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
1013 hints.ai_family = saddr.ss_family;
1015 // Now we have to create a new socket to send packets
1016 if (serveropen_dp) // Data connection is opened by the server toward the client
1018 sprintf(portdata, "%d", ntohs(startcapreq.portdata) );
1020 // Get the name of the other peer (needed to connect to that specific network address)
1021 if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, peerhost,
1022 sizeof(peerhost), NULL, 0, NI_NUMERICHOST) )
1024 sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
1025 goto error;
1028 if (sock_initaddress(peerhost, portdata, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
1029 goto error;
1031 if ( (sockdata= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1)
1032 goto error;
1034 else // Data connection is opened by the client toward the server
1036 hints.ai_flags = AI_PASSIVE;
1038 // Let's the server socket pick up a free network port for us
1039 if (sock_initaddress(NULL, "0", &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
1040 goto error;
1042 if ( (sockdata= sock_open(addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, errbuf, PCAP_ERRBUF_SIZE)) == -1)
1043 goto error;
1045 // get the complete sockaddr structure used in the data connection
1046 saddrlen = sizeof(struct sockaddr_storage);
1047 if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
1049 sock_geterror("getsockname(): ", errbuf, PCAP_ERRBUF_SIZE);
1050 goto error;
1053 // Get the local port the system picked up
1054 if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, NULL,
1055 0, portdata, sizeof(portdata), NI_NUMERICSERV) )
1057 sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
1058 goto error;
1062 // addrinfo is no longer used
1063 freeaddrinfo(addrinfo);
1064 addrinfo= NULL;
1066 // save the socket ID for the next calls
1067 fp->rmt_sockctrl= sockctrl; // Needed to send an error on the ctrl connection
1069 // Now I can set the filter
1070 if ( daemon_unpackapplyfilter(fp, &nread, &plen, errbuf) )
1071 goto error;
1074 // Now, I can send a RPCAP start capture reply message
1075 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
1076 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
1077 goto error;
1079 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STARTCAP_REPLY, 0, sizeof(struct rpcap_startcapreply) );
1081 startcapreply= (struct rpcap_startcapreply *) &sendbuf[sendbufidx];
1083 if ( sock_bufferize(NULL, sizeof(struct rpcap_startcapreply), NULL,
1084 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
1085 goto error;
1087 memset(startcapreply, 0, sizeof(struct rpcap_startcapreply) );
1088 startcapreply->bufsize= htonl(fp->bufsize);
1090 if (!serveropen_dp)
1092 unsigned short port = (unsigned short)strtoul(portdata,NULL,10);
1093 startcapreply->portdata= htons(port);
1096 if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
1097 goto error;
1099 if (!serveropen_dp)
1101 SOCKET socktemp; // We need another socket, since we're going to accept() a connection
1103 // Connection creation
1104 saddrlen = sizeof(struct sockaddr_storage);
1106 socktemp= accept(sockdata, (struct sockaddr *) &saddr, &saddrlen);
1108 if (socktemp == -1)
1110 sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
1111 goto error;
1114 // Now that I accepted the connection, the server socket is no longer needed
1115 sock_close(sockdata, errbuf, PCAP_ERRBUF_SIZE);
1116 sockdata= socktemp;
1119 fp->rmt_sockdata= sockdata;
1121 /* GV we need this to create the thread as detached. */
1122 /* GV otherwise, the thread handle is not destroyed */
1123 pthread_attr_init(&detachedAttribute);
1124 pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED);
1126 // Now we have to create a new thread to receive packets
1127 if ( pthread_create(threaddata, &detachedAttribute, (void *) daemon_thrdatamain, (void *) fp) )
1129 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread");
1130 pthread_attr_destroy(&detachedAttribute);
1131 goto error;
1134 pthread_attr_destroy(&detachedAttribute);
1135 // Check if all the data has been read; if not, discard the data in excess
1136 if (nread != plen)
1137 sock_discard(sockctrl, plen - nread, NULL, 0);
1139 return fp;
1141 error:
1142 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_STARTCAPTURE, NULL);
1144 if (addrinfo)
1145 freeaddrinfo(addrinfo);
1147 if (threaddata)
1148 pthread_cancel(*threaddata);
1150 if (sockdata)
1151 sock_close(sockdata, NULL, 0);
1153 // Check if all the data has been read; if not, discard the data in excess
1154 if (nread != plen)
1155 sock_discard(sockctrl, plen - nread, NULL, 0);
1157 if (fp)
1159 pcap_close(fp);
1160 fp= NULL;
1163 return NULL;
1168 int daemon_endcapture(pcap_t *fp, pthread_t *threaddata, char *errbuf)
1170 struct rpcap_header header;
1171 SOCKET sockctrl;
1173 if (threaddata)
1175 pthread_cancel(*threaddata);
1176 threaddata= 0;
1178 if (fp->rmt_sockdata)
1180 sock_close(fp->rmt_sockdata, NULL, 0);
1181 fp->rmt_sockdata= 0;
1184 sockctrl= fp->rmt_sockctrl;
1186 pcap_close(fp);
1187 fp= NULL;
1189 rpcap_createhdr( &header, RPCAP_MSG_ENDCAP_REPLY, 0, 0);
1191 if ( sock_send(sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
1192 return -1;
1194 return 0;
1199 int daemon_unpackapplyfilter(pcap_t *fp, unsigned int *nread, int *plen, char *errbuf)
1201 struct rpcap_filter filter;
1202 struct rpcap_filterbpf_insn insn;
1203 struct bpf_insn *bf_insn;
1204 struct bpf_program bf_prog;
1205 unsigned int i;
1208 if ( ( *nread+= sock_recv(fp->rmt_sockctrl, (char *) &filter, sizeof(struct rpcap_filter), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
1210 // to avoid blocking on the sock_discard()
1211 *plen= *nread;
1212 return -1;
1215 bf_prog.bf_len= ntohl(filter.nitems);
1217 if (ntohs(filter.filtertype) != RPCAP_UPDATEFILTER_BPF)
1219 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Only BPF/NPF filters are currently supported");
1220 return -1;
1223 bf_insn= (struct bpf_insn *) malloc ( sizeof(struct bpf_insn) * bf_prog.bf_len);
1224 if (bf_insn == NULL)
1226 snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
1227 return -1;
1230 bf_prog.bf_insns= bf_insn;
1232 for (i= 0; i < bf_prog.bf_len; i++)
1234 if ( ( *nread+= sock_recv(fp->rmt_sockctrl, (char *) &insn,
1235 sizeof(struct rpcap_filterbpf_insn), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
1236 return -1;
1238 bf_insn->code= ntohs(insn.code);
1239 bf_insn->jf= insn.jf;
1240 bf_insn->jt= insn.jt;
1241 bf_insn->k= ntohl(insn.k);
1243 bf_insn++;
1246 if (bpf_validate(bf_prog.bf_insns, bf_prog.bf_len) == 0)
1248 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The filter contains bogus instructions");
1249 return -1;
1252 if (pcap_setfilter(fp, &bf_prog) )
1254 snprintf(errbuf, PCAP_ERRBUF_SIZE, "RPCAP error: %s", fp->errbuf);
1255 return -1;
1258 return 0;
1263 int daemon_updatefilter(pcap_t *fp, uint32 plen)
1265 struct rpcap_header header; // keeps the answer to the updatefilter command
1266 unsigned int nread;
1268 nread= 0;
1270 if ( daemon_unpackapplyfilter(fp, &nread, &plen, fp->errbuf) )
1271 goto error;
1273 // Check if all the data has been read; if not, discard the data in excess
1274 if (nread != plen)
1276 if (sock_discard(fp->rmt_sockctrl, plen - nread, NULL, 0) )
1278 nread= plen; // just to avoid to call discard again in the 'error' section
1279 goto error;
1283 // A response is needed, otherwise the other host does not know that everything went well
1284 rpcap_createhdr( &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);
1286 if ( sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), fp->errbuf, PCAP_ERRBUF_SIZE) )
1287 goto error;
1289 return 0;
1292 error:
1293 if (nread != plen)
1294 sock_discard(fp->rmt_sockctrl, plen - nread, NULL, 0);
1296 rpcap_senderror(fp->rmt_sockctrl, fp->errbuf, PCAP_ERR_UPDATEFILTER, NULL);
1298 return -1;
1304 \brief Received the sampling parameters from remote host and it stores in the pcap_t structure.
1306 int daemon_setsampling(SOCKET sockctrl, struct rpcap_sampling *samp_param, int plen, char *errbuf)
1308 struct rpcap_header header;
1309 struct rpcap_sampling rpcap_samp;
1310 int nread; // number of bytes of the payload read from the socket
1313 if ( ( nread= sock_recv(sockctrl, (char *) &rpcap_samp, sizeof(struct rpcap_sampling),
1314 SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
1315 goto error;
1318 // Save these settings in the pcap_t
1319 samp_param->method= rpcap_samp.method;
1320 samp_param->value= ntohl(rpcap_samp.value);
1323 // A response is needed, otherwise the other host does not know that everything went well
1324 rpcap_createhdr( &header, RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);
1326 if ( sock_send(sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) )
1327 goto error;
1329 if (nread != plen)
1330 sock_discard(sockctrl, plen - nread, NULL, 0);
1332 return 0;
1334 error:
1335 if (nread != plen)
1336 sock_discard(sockctrl, plen - nread, NULL, 0);
1338 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_SETSAMPLING, NULL);
1340 return -1;
1345 int daemon_getstats(pcap_t *fp)
1347 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered
1348 int sendbufidx= 0; // index which keeps the number of bytes currently buffered
1349 struct pcap_stat stats; // local statistics
1350 struct rpcap_stats *netstats; // statistics sent on the network
1352 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
1353 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
1354 goto error;
1356 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));
1358 netstats= (struct rpcap_stats *) &sendbuf[sendbufidx];
1360 if ( sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL,
1361 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
1362 goto error;
1364 if (pcap_stats(fp, &stats) )
1365 goto error;
1367 netstats->ifdrop= htonl(stats.ps_ifdrop);
1368 netstats->ifrecv= htonl(stats.ps_recv);
1369 netstats->krnldrop= htonl(stats.ps_drop);
1370 netstats->svrcapt= htonl(fp->md.TotCapt);
1372 // Send the packet
1373 if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
1374 goto error;
1376 return 0;
1378 error:
1379 rpcap_senderror(fp->rmt_sockctrl, fp->errbuf, PCAP_ERR_GETSTATS, NULL);
1380 return -1;
1386 int daemon_getstatsnopcap(SOCKET sockctrl, unsigned int ifdrops, unsigned int ifrecv,
1387 unsigned int krnldrop, unsigned int svrcapt, char *errbuf)
1389 char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered
1390 int sendbufidx= 0; // index which keeps the number of bytes currently buffered
1391 struct rpcap_stats *netstats; // statistics sent on the network
1393 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
1394 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
1395 goto error;
1397 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));
1399 netstats= (struct rpcap_stats *) &sendbuf[sendbufidx];
1401 if ( sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL,
1402 &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
1403 goto error;
1405 netstats->ifdrop= htonl(ifdrops);
1406 netstats->ifrecv= htonl(ifrecv);
1407 netstats->krnldrop= htonl(krnldrop);
1408 netstats->svrcapt= htonl(svrcapt);
1410 // Send the packet
1411 if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
1412 goto error;
1414 return 0;
1416 error:
1417 rpcap_senderror(sockctrl, errbuf, PCAP_ERR_GETSTATS, NULL);
1418 return -1;
1424 void *daemon_thrdatamain(void *ptr)
1426 char errbuf[PCAP_ERRBUF_SIZE + 1]; // error buffer
1427 pcap_t *fp; // pointer to a 'pcap' structure
1428 int retval; // general variable used to keep the return value of other functions
1429 struct rpcap_pkthdr *net_pkt_header;// header of the packet
1430 struct pcap_pkthdr *pkt_header; // pointer to the buffer that contains the header of the current packet
1431 u_char *pkt_data; // pointer to the buffer that contains the current packet
1432 char *sendbuf; // temporary buffer in which data to be sent is buffered
1433 int sendbufidx; // index which keeps the number of bytes currently buffered
1435 fp= (pcap_t *) ptr;
1437 fp->md.TotCapt= 0; // counter which is incremented each time a packet is received
1439 // Initialize errbuf
1440 memset(errbuf, 0, sizeof(errbuf) );
1442 // Some platforms (e.g. Win32) allow creating a static variable with this size
1443 // However, others (e.g. BSD) do not, so we're forced to allocate this buffer dynamically
1444 sendbuf= (char *) malloc (sizeof(char) * RPCAP_NETBUF_SIZE);
1445 if (sendbuf == NULL)
1447 snprintf(errbuf, sizeof(errbuf) - 1, "Unable to create the buffer for this child thread");
1448 goto error;
1451 // Modify thread params so that it can be killed at any time
1452 if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) )
1453 goto error;
1454 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) )
1455 goto error;
1457 // Retrieve the packets
1458 while ((retval = pcap_next_ex(fp, &pkt_header, (const u_char **) &pkt_data)) >= 0) // cast to avoid a compiler warning
1460 if (retval == 0) // Read timeout elapsed
1461 continue;
1463 sendbufidx= 0;
1465 // Bufferize the general header
1466 if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
1467 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
1468 goto error;
1470 rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_PACKET, 0,
1471 (uint16) (sizeof(struct rpcap_pkthdr) + pkt_header->caplen) );
1473 net_pkt_header= (struct rpcap_pkthdr *) &sendbuf[sendbufidx];
1475 // Bufferize the pkt header
1476 if ( sock_bufferize(NULL, sizeof(struct rpcap_pkthdr), NULL, &sendbufidx,
1477 RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
1478 goto error;
1480 net_pkt_header->caplen= htonl(pkt_header->caplen);
1481 net_pkt_header->len= htonl(pkt_header->len);
1482 net_pkt_header->npkt= htonl( ++(fp->md.TotCapt) );
1483 net_pkt_header->timestamp_sec= htonl(pkt_header->ts.tv_sec);
1484 net_pkt_header->timestamp_usec= htonl(pkt_header->ts.tv_usec);
1486 // Bufferize the pkt data
1487 if ( sock_bufferize((char *) pkt_data, pkt_header->caplen, sendbuf, &sendbufidx,
1488 RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1)
1489 goto error;
1491 // Send the packet
1492 if ( sock_send(fp->rmt_sockdata, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
1493 goto error;
1497 if (retval == -1)
1499 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(fp) );
1500 rpcap_senderror(fp->rmt_sockctrl, errbuf, PCAP_ERR_READEX, NULL);
1501 goto error;
1504 error:
1506 SOCK_ASSERT(errbuf, 1);
1507 closesocket(fp->rmt_sockdata);
1508 fp->rmt_sockdata= 0;
1510 free(sendbuf);
1512 return NULL;
1518 \brief It serializes a network address.
1520 It accepts a 'sockaddr_storage' structure as input, and it converts it appropriately into a format
1521 that can be used to be sent on the network. Basically, it applies all the hton()
1522 conversion required to the input variable.
1524 \param sockaddrin: a 'sockaddr_storage' pointer to the variable that has to be
1525 serialized. This variable can be both a 'sockaddr_in' and 'sockaddr_in6'.
1527 \param sockaddrout: a 'sockaddr_storage' pointer to the variable that will contain
1528 the serialized data. This variable has to be allocated by the user.
1530 \return None
1532 \warning This function supports only AF_INET and AF_INET6 address families.
1534 void daemon_seraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage *sockaddrout)
1536 memset(sockaddrout, 0, sizeof(struct sockaddr_storage) );
1538 // There can be the case in which the sockaddrin is not available
1539 if (sockaddrin == NULL) return;
1541 // Warning: we support only AF_INET and AF_INET6
1542 if (sockaddrin->ss_family == AF_INET)
1544 struct sockaddr_in *sockaddr;
1546 sockaddr= (struct sockaddr_in *) sockaddrin;
1547 sockaddr->sin_family= htons(sockaddr->sin_family);
1548 sockaddr->sin_port= htons(sockaddr->sin_port);
1549 memcpy(sockaddrout, sockaddr, sizeof(struct sockaddr_in) );
1551 else
1553 struct sockaddr_in6 *sockaddr;
1555 sockaddr= (struct sockaddr_in6 *) sockaddrin;
1556 sockaddr->sin6_family= htons(sockaddr->sin6_family);
1557 sockaddr->sin6_port= htons(sockaddr->sin6_port);
1558 sockaddr->sin6_flowinfo= htonl(sockaddr->sin6_flowinfo);
1559 sockaddr->sin6_scope_id= htonl(sockaddr->sin6_scope_id);
1560 memcpy(sockaddrout, sockaddr, sizeof(struct sockaddr_in6) );
1569 \brief Suspends a pthread for msec milliseconds.
1571 This function is provided since pthreads do not have a suspend() call.
1573 void pthread_suspend(int msec)
1575 #ifdef WIN32
1576 Sleep(msec);
1577 #else
1578 struct timespec abstime;
1579 struct timeval now;
1581 pthread_cond_t cond;
1582 pthread_mutex_t mutex;
1583 pthread_mutexattr_t attr;
1585 pthread_mutexattr_init(&attr);
1586 pthread_mutex_init(&mutex, &attr);
1587 pthread_mutex_lock(&mutex);
1589 pthread_cond_init(&cond, NULL);
1591 gettimeofday(&now, NULL);
1593 abstime.tv_sec = now.tv_sec + msec/1000;
1594 abstime.tv_nsec = now.tv_usec * 1000 + (msec%1000) * 1000 * 1000;
1596 pthread_cond_timedwait(&cond, &mutex, &abstime);
1598 pthread_mutex_destroy(&mutex);
1599 pthread_cond_destroy(&cond);
1600 #endif