2 * Copyright (c) 2002 - 2003
3 * NetGroup, Politecnico di Torino (Italy)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
38 #include <pcap.h> // for libpcap/WinPcap calls
39 #include <errno.h> // for the errno variable
40 #include <stdlib.h> // for malloc(), free(), ...
41 #include <string.h> // for strlen(), ...
42 #include "sockutils.h" // for socket calls
43 #include "portability.h"
44 #include "rpcap-protocol.h"
49 #include <process.h> // for threads
54 #include <sys/types.h> // for select() and such
55 #include <pwd.h> // for password management
59 #include <shadow.h> // for password management
62 #define RPCAP_TIMEOUT_INIT 90 /* Initial timeout for RPCAP connections (default: 90 sec) */
63 #define RPCAP_TIMEOUT_RUNTIME 180 /* Run-time timeout for RPCAP connections (default: 3 min) */
64 #define RPCAP_SUSPEND_WRONGAUTH 1 /* If the authentication is wrong, stops 1 sec before accepting a new auth message */
67 * Data for a session managed by a thread.
72 uint8 protocol_version
;
77 // Locally defined functions
78 static int daemon_msg_err(SOCKET sockctrl
, uint32 plen
);
79 static int daemon_msg_auth_req(SOCKET sockctrl
, uint8 ver
, uint32 plen
, int nullAuthAllowed
);
80 static int daemon_AuthUserPwd(char *username
, char *password
, char *errbuf
);
82 static int daemon_msg_findallif_req(struct daemon_slpars
*pars
, uint32 plen
);
84 static int daemon_msg_open_req(struct daemon_slpars
*pars
, uint32 plen
, char *source
, size_t sourcelen
);
86 static int daemon_msg_startcap_req(struct daemon_slpars
*pars
, uint32 plen
, int *have_thread
, HANDLE
*threaddata
, char *source
, int active
, struct session
**sessionp
, struct rpcap_sampling
*samp_param
);
87 static int daemon_msg_endcap_req(struct daemon_slpars
*pars
, struct session
*session
, int *have_thread
, HANDLE threaddata
);
89 static int daemon_msg_startcap_req(struct daemon_slpars
*pars
, uint32 plen
, int *have_thread
, pthread_t
*threaddata
, char *source
, int active
, struct session
**sessionp
, struct rpcap_sampling
*samp_param
);
90 static int daemon_msg_endcap_req(struct daemon_slpars
*pars
, struct session
*session
, int *have_thread
, pthread_t threaddata
);
93 static int daemon_msg_updatefilter_req(struct daemon_slpars
*pars
, struct session
*session
, uint32 plen
);
94 static int daemon_unpackapplyfilter(SOCKET sockctrl
, struct session
*session
, uint32
*plenp
, char *errbuf
);
96 static int daemon_msg_stats_req(struct daemon_slpars
*pars
, struct session
*session
, uint32 plen
, struct pcap_stat
*stats
, unsigned int svrcapt
);
98 static int daemon_msg_setsampling_req(struct daemon_slpars
*pars
, uint32 plen
, struct rpcap_sampling
*samp_param
);
100 static void daemon_seraddr(struct sockaddr_storage
*sockaddrin
, struct rpcap_sockaddr
*sockaddrout
);
102 static unsigned __stdcall
daemon_thrdatamain(void *ptr
);
104 static void *daemon_thrdatamain(void *ptr
);
107 static int rpcapd_recv_msg_header(SOCKET sock
, struct rpcap_header
*headerp
);
108 static int rpcapd_recv(SOCKET sock
, char *buffer
, size_t toread
, uint32
*plen
, char *errmsgbuf
);
109 static int rpcapd_discard(SOCKET sock
, uint32 len
);
112 \brief Main serving function
113 This function is the one which does the job. It is the main() of the child
114 thread, which is created as soon as a new connection is accepted.
116 \param ptr: a void pointer that keeps the reference of the 'pthread_chain'
117 value corresponding to this thread. This variable is casted into a 'pthread_chain'
118 value in order to retrieve the socket we're currently using, the thread ID, and
119 some pointers to the previous and next elements into this struct.
124 unsigned __stdcall
daemon_serviceloop(void *ptr
)
126 void *daemon_serviceloop(void *ptr
)
129 char errbuf
[PCAP_ERRBUF_SIZE
+ 1]; // keeps the error string, prior to be printed
130 char errmsgbuf
[PCAP_ERRBUF_SIZE
+ 1]; // buffer for errors to send to the client
132 struct rpcap_header header
; // RPCAP message general header
133 uint32 plen
; // payload length from header
134 int authenticated
= 0; // 1 if the client has successfully authenticated
135 char source
[PCAP_BUF_SIZE
+1]; // keeps the string that contains the interface to open
136 int got_source
= 0; // 1 if we've gotten the source from an open request
137 struct session
*session
= NULL
; // struct session main variable
138 struct daemon_slpars
*pars
; // parameters related to the present daemon loop
139 const char *msg_type_string
; // string for message type
141 int have_thread
= 0; // 1 if threaddata refers to a thread we've created
143 HANDLE threaddata
; // handle to the 'read from daemon and send to client' thread
145 pthread_t threaddata
; // handle to the 'read from daemon and send to client' thread
148 // needed to save the values of the statistics
149 struct pcap_stat stats
;
150 unsigned int svrcapt
;
152 struct rpcap_sampling samp_param
; // in case sampling has been requested
154 // Structures needed for the select() call
155 fd_set rfds
; // set of socket descriptors we have to check
156 struct timeval tv
; // maximum time the select() can block waiting for data
157 int retval
; // select() return value
159 pars
= (struct daemon_slpars
*) ptr
;
161 *errbuf
= 0; // Initialize errbuf
164 // If we're in active mode, this is not a separate thread
165 if (! pars
->isactive
)
167 // Modify thread params so that it can be killed at any time
168 if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, NULL
))
170 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
))
176 // The client must first authenticate; loop until they send us a
177 // message with a version we support and credentials we accept,
178 // they send us a close message indicating that they're giving up,
179 // or we get a network error or other fatal error.
181 while (!authenticated
)
184 // If we're in active mode, we have to check for the
187 // XXX - do this on *every* trip through the loop?
192 // We do not have to block here
193 tv
.tv_sec
= RPCAP_TIMEOUT_INIT
;
196 FD_SET(pars
->sockctrl
, &rfds
);
198 retval
= select(pars
->sockctrl
+ 1, &rfds
, NULL
, NULL
, &tv
);
201 sock_geterror("select failed: ", errmsgbuf
, PCAP_ERRBUF_SIZE
);
202 if (rpcap_senderror(pars
->sockctrl
, 0, PCAP_ERR_NETW
, errmsgbuf
, errbuf
) == -1)
203 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
207 // The timeout has expired
208 // So, this was a fake connection. Drop it down
211 if (rpcap_senderror(pars
->sockctrl
, 0, PCAP_ERR_INITTIMEOUT
, "The RPCAP initial timeout has expired", errbuf
) == -1)
212 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
218 // Read the message header from the client.
220 nrecv
= rpcapd_recv_msg_header(pars
->sockctrl
, &header
);
228 // Client closed the connection.
235 // Did the client specify a version we can handle?
237 if (header
.ver
< RPCAP_MIN_VERSION
||
238 header
.ver
> RPCAP_MAX_VERSION
)
241 // Tell them it's not a valid protocol version.
245 if (header
.ver
< RPCAP_MIN_VERSION
)
248 // Their maximum version is too old;
249 // there *is* no version we can both
250 // handle, and they might reject
251 // an error with a version they don't
252 // understand, so reply with the
253 // version they sent. That may
254 // make them retry with that version,
255 // but they'll give up on that
258 reply_version
= header
.ver
;
263 // Their maximum version is too new,
264 // but they might be able to handle
265 // *our* maximum version, so reply
266 // with that version.
268 reply_version
= RPCAP_MAX_VERSION
;
270 if (rpcap_senderror(pars
->sockctrl
, reply_version
,
271 PCAP_ERR_WRONGVER
, "RPCAP version number mismatch",
274 // That failed; log a message and give up.
275 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
279 // Discard the rest of the message.
280 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
286 // Let them try again.
291 // OK, we use the version the client specified.
293 pars
->protocol_version
= header
.ver
;
297 case RPCAP_MSG_AUTH_REQ
:
298 retval
= daemon_msg_auth_req(pars
->sockctrl
, pars
->protocol_version
, plen
, pars
->nullAuthAllowed
);
301 // Fatal error; a message has
302 // been logged, so just give up.
307 // Non-fatal error; we sent back
308 // an error message, so let them
313 // OK, we're authenticated; we sent back
314 // a reply, so start serving requests.
318 case RPCAP_MSG_CLOSE
:
320 // The client is giving up.
321 // Discard the rest of the message, if
322 // there is anything more.
324 (void)rpcapd_discard(pars
->sockctrl
, plen
);
325 // We're done with this client.
328 case RPCAP_MSG_ERROR
:
329 // Log this and close the connection?
330 // XXX - is this what happens in active
331 // mode, where *we* initiate the
332 // connection, and the client gives us
333 // an error message rather than a "let
334 // me log in" message, indicating that
335 // we're not allowed to connect to them?
336 (void)daemon_msg_err(pars
->sockctrl
, plen
);
339 case RPCAP_MSG_FINDALLIF_REQ
:
340 case RPCAP_MSG_OPEN_REQ
:
341 case RPCAP_MSG_STARTCAP_REQ
:
342 case RPCAP_MSG_UPDATEFILTER_REQ
:
343 case RPCAP_MSG_STATS_REQ
:
344 case RPCAP_MSG_ENDCAP_REQ
:
345 case RPCAP_MSG_SETSAMPLING_REQ
:
347 // These requests can't be sent until
348 // the client is authenticated.
350 msg_type_string
= rpcap_msg_type_string(header
.type
);
351 if (msg_type_string
!= NULL
)
353 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "%s request sent before authentication was completed", msg_type_string
);
357 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Message of type %u sent before authentication was completed", header
.type
);
359 if (rpcap_senderror(pars
->sockctrl
,
360 pars
->protocol_version
, PCAP_ERR_WRONGMSG
,
361 errmsgbuf
, errbuf
) == -1)
363 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
366 // Discard the rest of the message.
367 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
374 case RPCAP_MSG_PACKET
:
375 case RPCAP_MSG_FINDALLIF_REPLY
:
376 case RPCAP_MSG_OPEN_REPLY
:
377 case RPCAP_MSG_STARTCAP_REPLY
:
378 case RPCAP_MSG_UPDATEFILTER_REPLY
:
379 case RPCAP_MSG_AUTH_REPLY
:
380 case RPCAP_MSG_STATS_REPLY
:
381 case RPCAP_MSG_ENDCAP_REPLY
:
382 case RPCAP_MSG_SETSAMPLING_REPLY
:
384 // These are server-to-client messages.
386 msg_type_string
= rpcap_msg_type_string(header
.type
);
387 if (msg_type_string
!= NULL
)
389 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Server-to-client message %s received from client", msg_type_string
);
393 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Server-to-client message of type %u received from client", header
.type
);
395 if (rpcap_senderror(pars
->sockctrl
,
396 pars
->protocol_version
, PCAP_ERR_WRONGMSG
,
397 errmsgbuf
, errbuf
) == -1)
399 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
402 // Discard the rest of the message.
403 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
412 // Unknown message type.
414 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Unknown message type %u", header
.type
);
415 if (rpcap_senderror(pars
->sockctrl
,
416 pars
->protocol_version
, PCAP_ERR_WRONGMSG
,
417 errmsgbuf
, errbuf
) == -1)
419 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
422 // Discard the rest of the message.
423 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
433 // OK, the client has authenticated itself, and we can start
434 // processing regular requests from it.
438 // We don't have any statistics yet.
450 errbuf
[0] = 0; // clear errbuf
452 // Avoid zombies connections; check if the connection is opens but no commands are performed
453 // from more than RPCAP_TIMEOUT_RUNTIME
455 // - I have to be in normal mode (no active mode)
456 // - if the device is open, I don't have to be in the middle of a capture (session->sockdata)
457 // - if the device is closed, I have always to check if a new command arrives
459 // Be carefully: the capture can have been started, but an error occurred (so session != NULL, but
461 if ((!pars
->isactive
) && ((session
== NULL
) || ((session
!= NULL
) && (session
->sockdata
== 0))))
463 // Check for the initial timeout
465 // We do not have to block here
466 tv
.tv_sec
= RPCAP_TIMEOUT_RUNTIME
;
469 FD_SET(pars
->sockctrl
, &rfds
);
471 retval
= select(pars
->sockctrl
+ 1, &rfds
, NULL
, NULL
, &tv
);
474 sock_geterror("select failed: ", errmsgbuf
, PCAP_ERRBUF_SIZE
);
475 if (rpcap_senderror(pars
->sockctrl
,
476 pars
->protocol_version
, PCAP_ERR_NETW
,
477 errmsgbuf
, errbuf
) == -1)
478 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
482 // The timeout has expired
483 // So, this was a fake connection. Drop it down
486 if (rpcap_senderror(pars
->sockctrl
,
487 pars
->protocol_version
,
488 PCAP_ERR_INITTIMEOUT
,
489 "The RPCAP initial timeout has expired",
491 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
497 // Read the message header from the client.
499 nrecv
= rpcapd_recv_msg_header(pars
->sockctrl
, &header
);
507 // Client closed the connection.
514 // Did the client specify the version we negotiated?
516 // For now, there's only one version.
518 if (header
.ver
!= pars
->protocol_version
)
521 // Tell them it's not the negotiated version.
522 // Send the error message with their version,
523 // so they don't reject it as having the wrong
526 if (rpcap_senderror(pars
->sockctrl
,
527 header
.ver
, PCAP_ERR_WRONGVER
,
528 "RPCAP version in message isn't the negotiated version",
531 // That failed; log a message and give up.
532 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
536 // Discard the rest of the message.
537 (void)rpcapd_discard(pars
->sockctrl
, plen
);
544 case RPCAP_MSG_ERROR
: // The other endpoint reported an error
546 (void)daemon_msg_err(pars
->sockctrl
, plen
);
547 // Do nothing; just exit; the error code is already into the errbuf
548 // XXX - actually exit....
552 case RPCAP_MSG_FINDALLIF_REQ
:
554 if (daemon_msg_findallif_req(pars
, plen
) == -1)
556 // Fatal error; a message has
557 // been logged, so just give up.
563 case RPCAP_MSG_OPEN_REQ
:
566 // Process the open request, and keep
567 // the source from it, for use later
568 // when the capture is started.
570 // XXX - we don't care if the client sends
571 // us multiple open requests, the last
574 retval
= daemon_msg_open_req(pars
, plen
, source
, sizeof(source
));
577 // Fatal error; a message has
578 // been logged, so just give up.
585 case RPCAP_MSG_STARTCAP_REQ
:
589 // They never told us what device
591 if (rpcap_senderror(pars
->sockctrl
,
592 pars
->protocol_version
,
593 PCAP_ERR_STARTCAPTURE
,
594 "No capture device was specified",
597 // Fatal error; log an
598 // error and give up.
599 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
602 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
609 if (daemon_msg_startcap_req(pars
, plen
, &have_thread
, &threaddata
, source
, pars
->isactive
, &session
, &samp_param
) == -1)
611 // Fatal error; a message has
612 // been logged, so just give up.
618 case RPCAP_MSG_UPDATEFILTER_REQ
:
622 if (daemon_msg_updatefilter_req(pars
, session
, plen
) == -1)
624 // Fatal error; a message has
625 // been logged, so just give up.
631 if (rpcap_senderror(pars
->sockctrl
,
632 pars
->protocol_version
,
633 PCAP_ERR_UPDATEFILTER
,
634 "Device not opened. Cannot update filter",
637 // That failed; log a message and give up.
638 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
645 case RPCAP_MSG_CLOSE
: // The other endpoint close the pcap session
647 // signal to the main that the user closed the control connection
648 // This is used only in case of active mode
649 pars
->activeclose
= 1;
650 SOCK_ASSERT("The other end system asked to close the connection.", 1);
655 case RPCAP_MSG_STATS_REQ
:
657 if (daemon_msg_stats_req(pars
, session
, plen
, &stats
, svrcapt
) == -1)
659 // Fatal error; a message has
660 // been logged, so just give up.
666 case RPCAP_MSG_ENDCAP_REQ
: // The other endpoint close the current capture session
670 // Save statistics (we can need them in the future)
671 if (pcap_stats(session
->fp
, &stats
))
673 svrcapt
= session
->TotCapt
;
683 if (daemon_msg_endcap_req(pars
, session
, &have_thread
, threaddata
) == -1)
687 // Fatal error; a message has
688 // been logged, so just give up.
696 rpcap_senderror(pars
->sockctrl
,
697 pars
->protocol_version
,
699 "Device not opened. Cannot close the capture",
705 case RPCAP_MSG_SETSAMPLING_REQ
:
707 if (daemon_msg_setsampling_req(pars
, plen
, &samp_param
) == -1)
709 // Fatal error; a message has
710 // been logged, so just give up.
716 case RPCAP_MSG_AUTH_REQ
:
719 // We're already authenticated; you don't
720 // get to reauthenticate.
722 rpcapd_log(LOGPRIO_INFO
, "The client sent an RPCAP_MSG_AUTH_REQ message after authentication was completed");
723 if (rpcap_senderror(pars
->sockctrl
,
724 pars
->protocol_version
,
726 "RPCAP_MSG_AUTH_REQ request sent after authentication was completed",
729 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
732 // Discard the rest of the message.
733 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
740 case RPCAP_MSG_PACKET
:
741 case RPCAP_MSG_FINDALLIF_REPLY
:
742 case RPCAP_MSG_OPEN_REPLY
:
743 case RPCAP_MSG_STARTCAP_REPLY
:
744 case RPCAP_MSG_UPDATEFILTER_REPLY
:
745 case RPCAP_MSG_AUTH_REPLY
:
746 case RPCAP_MSG_STATS_REPLY
:
747 case RPCAP_MSG_ENDCAP_REPLY
:
748 case RPCAP_MSG_SETSAMPLING_REPLY
:
750 // These are server-to-client messages.
752 msg_type_string
= rpcap_msg_type_string(header
.type
);
753 if (msg_type_string
!= NULL
)
755 rpcapd_log(LOGPRIO_INFO
, "The client sent a %s server-to-client message", msg_type_string
);
756 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Server-to-client message %s received from client", msg_type_string
);
760 rpcapd_log(LOGPRIO_INFO
, "The client sent a server-to-client message of type %u", header
.type
);
761 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Server-to-client message of type %u received from client", header
.type
);
763 if (rpcap_senderror(pars
->sockctrl
,
764 pars
->protocol_version
, PCAP_ERR_WRONGMSG
,
765 errmsgbuf
, errbuf
) == -1)
767 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
770 // Discard the rest of the message.
771 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
780 // Unknown message type.
782 rpcapd_log(LOGPRIO_INFO
, "The client sent a message of type %u", header
.type
);
783 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Unknown message type %u", header
.type
);
784 if (rpcap_senderror(pars
->sockctrl
,
785 pars
->protocol_version
, PCAP_ERR_WRONGMSG
,
786 errbuf
, errmsgbuf
) == -1)
788 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
791 // Discard the rest of the message.
792 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
803 // The child thread is about to end
805 // perform pcap_t cleanup, in case it has not been done
812 // Tell the data connection thread main capture
813 // loop to break out of that loop.
815 pcap_breakloop(session
->fp
);
818 // If it's currently blocked waiting for packets
819 // to arrive, try to wake it up, so it can see
820 // the "break out of the loop" indication.
822 SetEvent(pcap_getevent(session
->fp
));
825 // Wait for the thread to exit, so we don't close
826 // sockets out from under it.
828 // XXX - have a timeout, so we don't wait forever?
830 WaitForSingleObject(threaddata
, INFINITE
);
833 // Release the thread handle, as we're done with
836 CloseHandle(threaddata
);
838 pthread_cancel(threaddata
);
842 if (session
->sockdata
)
844 sock_close(session
->sockdata
, NULL
, 0);
845 session
->sockdata
= 0;
847 pcap_close(session
->fp
);
852 // Print message and exit
853 SOCK_ASSERT("I'm exiting from the child loop", 1);
854 SOCK_ASSERT(errbuf
, 1);
859 sock_close(pars
->sockctrl
, NULL
, 0);
867 * This handles the RPCAP_MSG_ERR message.
869 int daemon_msg_err(SOCKET sockctrl
, uint32 plen
)
871 char errbuf
[PCAP_ERRBUF_SIZE
];
872 char remote_errbuf
[PCAP_ERRBUF_SIZE
];
874 if (plen
>= PCAP_ERRBUF_SIZE
)
877 * Message is too long; just read as much of it as we
878 * can into the buffer provided, and discard the rest.
880 if (sock_recv(sockctrl
, remote_errbuf
, PCAP_ERRBUF_SIZE
- 1,
881 SOCK_RECEIVEALL_YES
|SOCK_EOF_IS_ERROR
, errbuf
,
882 PCAP_ERRBUF_SIZE
) == -1)
885 rpcapd_log(LOGPRIO_ERROR
, "Read from client failed: %s", errbuf
);
888 if (rpcapd_discard(sockctrl
, plen
- (PCAP_ERRBUF_SIZE
- 1)) == -1)
897 remote_errbuf
[PCAP_ERRBUF_SIZE
- 1] = '\0';
901 /* Empty error string. */
902 remote_errbuf
[0] = '\0';
906 if (sock_recv(sockctrl
, remote_errbuf
, plen
,
907 SOCK_RECEIVEALL_YES
|SOCK_EOF_IS_ERROR
, errbuf
,
908 PCAP_ERRBUF_SIZE
) == -1)
911 rpcapd_log(LOGPRIO_ERROR
, "Read from client failed: %s", errbuf
);
918 remote_errbuf
[plen
] = '\0';
921 rpcapd_log(LOGPRIO_ERROR
, "Error from client: %s", remote_errbuf
);
926 * This handles the RPCAP_MSG_AUTH_REQ message.
927 * It checks if the authentication credentials supplied by the user are valid.
929 * This function is called if the daemon receives a RPCAP_MSG_AUTH_REQ
930 * message in its authentication loop. It reads the body of the
931 * authentication message from the network and checks whether the
932 * credentials are valid.
934 * \param sockctrl: the socket for the control connection.
936 * \param nullAuthAllowed: '1' if the NULL authentication is allowed.
938 * \param errbuf: a user-allocated buffer in which the error message
939 * (if one) has to be written. It must be at least PCAP_ERRBUF_SIZE
942 * \return '0' if everything is fine, '-1' if an unrecoverable error occurred,
943 * or '-2' if the authentication failed. For errors, an error message is
944 * returned in the 'errbuf' variable; this gives a message for the
945 * unrecoverable error or for the authentication failure.
947 int daemon_msg_auth_req(SOCKET sockctrl
, uint8 ver
, uint32 plen
, int nullAuthAllowed
)
949 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
950 char errmsgbuf
[PCAP_ERRBUF_SIZE
]; // buffer for errors to send to the client
951 struct rpcap_header header
; // RPCAP message general header
953 struct rpcap_auth auth
; // RPCAP authentication header
955 status
= rpcapd_recv(sockctrl
, (char *) &auth
, sizeof(struct rpcap_auth
), &plen
, errmsgbuf
);
965 switch (ntohs(auth
.type
))
967 case RPCAP_RMTAUTH_NULL
:
969 if (!nullAuthAllowed
)
971 // Send the client an error reply.
972 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Authentication failed; NULL authentication not permitted.");
978 case RPCAP_RMTAUTH_PWD
:
980 char *username
, *passwd
;
981 uint32 usernamelen
, passwdlen
;
983 usernamelen
= ntohs(auth
.slen1
);
984 username
= (char *) malloc (usernamelen
+ 1);
985 if (username
== NULL
)
987 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
990 status
= rpcapd_recv(sockctrl
, username
, usernamelen
, &plen
, errmsgbuf
);
1001 username
[usernamelen
] = '\0';
1003 passwdlen
= ntohs(auth
.slen2
);
1004 passwd
= (char *) malloc (passwdlen
+ 1);
1007 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
1011 status
= rpcapd_recv(sockctrl
, passwd
, passwdlen
, &plen
, errmsgbuf
);
1024 passwd
[passwdlen
] = '\0';
1026 if (daemon_AuthUserPwd(username
, passwd
, errmsgbuf
))
1029 // Authentication failed. Let the client
1034 if (rpcap_senderror(sockctrl
, ver
,
1035 PCAP_ERR_AUTH
, errmsgbuf
, errbuf
) == -1)
1037 // That failed; log a message and give up.
1038 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1043 // Suspend for 1 second, so that they can't
1044 // hammer us with repeated tries with an
1045 // attack such as a dictionary attack.
1047 // WARNING: this delay is inserted only
1048 // at this point; if the client closes the
1049 // connection and reconnects, the suspension
1050 // time does not have any effect.
1052 sleep_secs(RPCAP_SUSPEND_WRONGAUTH
);
1062 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Authentication type not recognized.");
1066 // The authentication succeeded; let the client know.
1067 rpcap_createhdr(&header
, ver
, RPCAP_MSG_AUTH_REPLY
, 0, 0);
1069 // Send the ok message back
1070 if (sock_send(sockctrl
, (char *) &header
, sizeof (struct rpcap_header
), errbuf
, PCAP_ERRBUF_SIZE
) == -1)
1072 // That failed; log a messsage and give up.
1073 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1077 // Check if all the data has been read; if not, discard the data in excess
1078 if (rpcapd_discard(sockctrl
, plen
) == -1)
1086 if (rpcap_senderror(sockctrl
, ver
, PCAP_ERR_AUTH
, errmsgbuf
,
1089 // That failed; log a message and give up.
1090 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1095 // Check if all the data has been read; if not, discard the data in excess
1096 if (rpcapd_discard(sockctrl
, plen
) == -1)
1104 int daemon_AuthUserPwd(char *username
, char *password
, char *errbuf
)
1108 * Warning: the user which launches the process must have the
1109 * SE_TCB_NAME right.
1110 * This corresponds to have the "Act as part of the Operating System"
1111 * turned on (administrative tools, local security settings, local
1112 * policies, user right assignment)
1113 * However, it seems to me that if you run it as a service, this
1114 * right should be provided by default.
1117 if (LogonUser(username
, ".", password
, LOGON32_LOGON_NETWORK
, LOGON32_PROVIDER_DEFAULT
, &Token
) == 0)
1121 error
= GetLastError();
1122 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, error
, 0, errbuf
,
1123 PCAP_ERRBUF_SIZE
, NULL
);
1128 // This call should change the current thread to the selected user.
1129 // I didn't test it.
1130 if (ImpersonateLoggedOnUser(Token
) == 0)
1134 error
= GetLastError();
1135 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, error
, 0, errbuf
,
1136 PCAP_ERRBUF_SIZE
, NULL
);
1149 * http://www.unixpapa.com/incnote/passwd.html
1151 * We use the Solaris/Linux shadow password authentication if
1152 * we have getspnam(), otherwise we just do traditional
1153 * authentication, which, on some platforms, might work, even
1154 * with shadow passwords, if we're running as root. Traditional
1155 * authenticaion won't work if we're not running as root, as
1156 * I think these days all UN*Xes either won't return the password
1157 * at all with getpwnam() or will only do so if you're root.
1159 * XXX - perhaps what we *should* be using is PAM, if we have
1160 * it. That might hide all the details of username/password
1161 * authentication, whether it's done with a visible-to-root-
1162 * only password database or some other authentication mechanism,
1165 struct passwd
*user
;
1166 char *user_password
;
1167 #ifdef HAVE_GETSPNAM
1168 struct spwd
*usersp
;
1171 // This call is needed to get the uid
1172 if ((user
= getpwnam(username
)) == NULL
)
1174 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Authentication failed: no such user");
1178 #ifdef HAVE_GETSPNAM
1179 // This call is needed to get the password; otherwise 'x' is returned
1180 if ((usersp
= getspnam(username
)) == NULL
)
1182 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Authentication failed: no such user");
1185 user_password
= usersp
->sp_pwdp
;
1188 * XXX - what about other platforms?
1189 * The unixpapa.com page claims this Just Works on *BSD if you're
1190 * running as root - it's from 2000, so it doesn't indicate whether
1191 * macOS (which didn't come out until 2001, under the name Mac OS
1192 * X) behaves like the *BSDs or not, and might also work on AIX.
1193 * HP-UX does something else.
1195 * Again, hopefully PAM hides all that.
1197 user_password
= user
->pw_passwd
;
1200 if (strcmp(user_password
, (char *) crypt(password
, user_password
)) != 0)
1202 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Authentication failed: password incorrect");
1206 if (setuid(user
->pw_uid
))
1208 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "%s", pcap_strerror(errno
));
1212 /* if (setgid(user->pw_gid))
1214 SOCK_ASSERT("setgid failed", 1);
1215 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s", pcap_strerror(errno));
1225 static int daemon_msg_findallif_req(struct daemon_slpars
*pars
, uint32 plen
)
1227 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
1228 char errmsgbuf
[PCAP_ERRBUF_SIZE
]; // buffer for errors to send to the client
1229 char sendbuf
[RPCAP_NETBUF_SIZE
]; // temporary buffer in which data to be sent is buffered
1230 int sendbufidx
= 0; // index which keeps the number of bytes currently buffered
1231 pcap_if_t
*alldevs
= NULL
; // pointer to the header of the interface chain
1232 pcap_if_t
*d
; // temp pointer needed to scan the interface chain
1233 struct pcap_addr
*address
; // pcap structure that keeps a network address of an interface
1234 struct rpcap_findalldevs_if
*findalldevs_if
;// rpcap structure that packet all the data of an interface together
1235 uint16 nif
= 0; // counts the number of interface listed
1237 // Discard the rest of the message; there shouldn't be any payload.
1238 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
1244 // Retrieve the device list
1245 if (pcap_findalldevs(&alldevs
, errmsgbuf
) == -1)
1248 if (alldevs
== NULL
)
1250 if (rpcap_senderror(pars
->sockctrl
, pars
->protocol_version
,
1251 PCAP_ERR_NOREMOTEIF
,
1252 "No interfaces found! Make sure libpcap/WinPcap is properly installed"
1253 " and you have the right to access to the remote device.",
1256 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1262 // checks the number of interfaces and it computes the total length of the payload
1263 for (d
= alldevs
; d
!= NULL
; d
= d
->next
)
1268 plen
+= strlen(d
->description
);
1270 plen
+= strlen(d
->name
);
1272 plen
+= sizeof(struct rpcap_findalldevs_if
);
1274 for (address
= d
->addresses
; address
!= NULL
; address
= address
->next
)
1277 * Send only IPv4 and IPv6 addresses over the wire.
1279 switch (address
->addr
->sa_family
)
1285 plen
+= (sizeof(struct rpcap_sockaddr
) * 4);
1294 // RPCAP findalldevs command
1295 if (sock_bufferize(NULL
, sizeof(struct rpcap_header
), NULL
,
1296 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
,
1297 PCAP_ERRBUF_SIZE
) == -1)
1300 rpcap_createhdr((struct rpcap_header
*) sendbuf
, pars
->protocol_version
,
1301 RPCAP_MSG_FINDALLIF_REPLY
, nif
, plen
);
1303 // send the interface list
1304 for (d
= alldevs
; d
!= NULL
; d
= d
->next
)
1306 uint16 lname
, ldescr
;
1308 findalldevs_if
= (struct rpcap_findalldevs_if
*) &sendbuf
[sendbufidx
];
1310 if (sock_bufferize(NULL
, sizeof(struct rpcap_findalldevs_if
), NULL
,
1311 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1314 memset(findalldevs_if
, 0, sizeof(struct rpcap_findalldevs_if
));
1316 if (d
->description
) ldescr
= (short) strlen(d
->description
);
1318 if (d
->name
) lname
= (short) strlen(d
->name
);
1321 findalldevs_if
->desclen
= htons(ldescr
);
1322 findalldevs_if
->namelen
= htons(lname
);
1323 findalldevs_if
->flags
= htonl(d
->flags
);
1325 for (address
= d
->addresses
; address
!= NULL
; address
= address
->next
)
1328 * Send only IPv4 and IPv6 addresses over the wire.
1330 switch (address
->addr
->sa_family
)
1336 findalldevs_if
->naddr
++;
1343 findalldevs_if
->naddr
= htons(findalldevs_if
->naddr
);
1345 if (sock_bufferize(d
->name
, lname
, sendbuf
, &sendbufidx
,
1346 RPCAP_NETBUF_SIZE
, SOCKBUF_BUFFERIZE
, errmsgbuf
,
1347 PCAP_ERRBUF_SIZE
) == -1)
1350 if (sock_bufferize(d
->description
, ldescr
, sendbuf
, &sendbufidx
,
1351 RPCAP_NETBUF_SIZE
, SOCKBUF_BUFFERIZE
, errmsgbuf
,
1352 PCAP_ERRBUF_SIZE
) == -1)
1355 // send all addresses
1356 for (address
= d
->addresses
; address
!= NULL
; address
= address
->next
)
1358 struct rpcap_sockaddr
*sockaddr
;
1361 * Send only IPv4 and IPv6 addresses over the wire.
1363 switch (address
->addr
->sa_family
)
1369 sockaddr
= (struct rpcap_sockaddr
*) &sendbuf
[sendbufidx
];
1370 if (sock_bufferize(NULL
, sizeof(struct rpcap_sockaddr
), NULL
,
1371 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1373 daemon_seraddr((struct sockaddr_storage
*) address
->addr
, sockaddr
);
1375 sockaddr
= (struct rpcap_sockaddr
*) &sendbuf
[sendbufidx
];
1376 if (sock_bufferize(NULL
, sizeof(struct rpcap_sockaddr
), NULL
,
1377 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1379 daemon_seraddr((struct sockaddr_storage
*) address
->netmask
, sockaddr
);
1381 sockaddr
= (struct rpcap_sockaddr
*) &sendbuf
[sendbufidx
];
1382 if (sock_bufferize(NULL
, sizeof(struct rpcap_sockaddr
), NULL
,
1383 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1385 daemon_seraddr((struct sockaddr_storage
*) address
->broadaddr
, sockaddr
);
1387 sockaddr
= (struct rpcap_sockaddr
*) &sendbuf
[sendbufidx
];
1388 if (sock_bufferize(NULL
, sizeof(struct rpcap_sockaddr
), NULL
,
1389 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1391 daemon_seraddr((struct sockaddr_storage
*) address
->dstaddr
, sockaddr
);
1400 // We no longer need the device list. Free it.
1401 pcap_freealldevs(alldevs
);
1403 // Send a final command that says "now send it!"
1404 if (sock_send(pars
->sockctrl
, sendbuf
, sendbufidx
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
1406 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1414 pcap_freealldevs(alldevs
);
1416 if (rpcap_senderror(pars
->sockctrl
, pars
->protocol_version
,
1417 PCAP_ERR_FINDALLIF
, errmsgbuf
, errbuf
) == -1)
1419 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1426 \param plen: the length of the current message (needed in order to be able
1427 to discard excess data in the message, if present)
1429 static int daemon_msg_open_req(struct daemon_slpars
*pars
, uint32 plen
, char *source
, size_t sourcelen
)
1431 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
1432 char errmsgbuf
[PCAP_ERRBUF_SIZE
]; // buffer for errors to send to the client
1433 pcap_t
*fp
; // pcap_t main variable
1435 char sendbuf
[RPCAP_NETBUF_SIZE
]; // temporary buffer in which data to be sent is buffered
1436 int sendbufidx
= 0; // index which keeps the number of bytes currently buffered
1437 struct rpcap_openreply
*openreply
; // open reply message
1439 if (plen
> sourcelen
- 1)
1441 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Source string too long");
1445 nread
= sock_recv(pars
->sockctrl
, source
, plen
,
1446 SOCK_RECEIVEALL_YES
|SOCK_EOF_IS_ERROR
, errbuf
, PCAP_ERRBUF_SIZE
);
1449 rpcapd_log(LOGPRIO_ERROR
, "Read from client failed: %s", errbuf
);
1452 source
[nread
] = '\0';
1455 // XXX - make sure it's *not* a URL; we don't support opening
1456 // remote devices here.
1458 // Open the selected device
1459 // This is a fake open, since we do that only to get the needed parameters, then we close the device again
1460 if ((fp
= pcap_open_live(source
,
1461 1500 /* fake snaplen */,
1463 1000 /* fake timeout */,
1464 errmsgbuf
)) == NULL
)
1467 // Now, I can send a RPCAP open reply message
1468 if (sock_bufferize(NULL
, sizeof(struct rpcap_header
), NULL
, &sendbufidx
,
1469 RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1472 rpcap_createhdr((struct rpcap_header
*) sendbuf
, pars
->protocol_version
,
1473 RPCAP_MSG_OPEN_REPLY
, 0, sizeof(struct rpcap_openreply
));
1475 openreply
= (struct rpcap_openreply
*) &sendbuf
[sendbufidx
];
1477 if (sock_bufferize(NULL
, sizeof(struct rpcap_openreply
), NULL
, &sendbufidx
,
1478 RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1481 memset(openreply
, 0, sizeof(struct rpcap_openreply
));
1482 openreply
->linktype
= htonl(pcap_datalink(fp
));
1483 openreply
->tzoff
= 0; /* This is always 0 for live captures */
1485 // We're done with the pcap_t.
1489 if (sock_send(pars
->sockctrl
, sendbuf
, sendbufidx
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
1491 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1497 if (rpcap_senderror(pars
->sockctrl
, pars
->protocol_version
,
1498 PCAP_ERR_OPEN
, errmsgbuf
, errbuf
) == -1)
1500 // That failed; log a message and give up.
1501 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1505 // Check if all the data has been read; if not, discard the data in excess
1506 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
1514 \param plen: the length of the current message (needed in order to be able
1515 to discard excess data in the message, if present)
1518 static int daemon_msg_startcap_req(struct daemon_slpars
*pars
, uint32 plen
, int *have_thread
, HANDLE
*threaddata
, char *source
, int active
, struct session
**sessionp
, struct rpcap_sampling
*samp_param
)
1520 static int daemon_msg_startcap_req(struct daemon_slpars
*pars
, uint32 plen
, int *have_thread
, pthread_t
*threaddata
, char *source
, int active
, struct session
**sessionp
, struct rpcap_sampling
*samp_param
)
1523 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
1524 char errmsgbuf
[PCAP_ERRBUF_SIZE
]; // buffer for errors to send to the client
1525 char portdata
[PCAP_BUF_SIZE
]; // temp variable needed to derive the data port
1526 char peerhost
[PCAP_BUF_SIZE
]; // temp variable needed to derive the host name of our peer
1527 struct session
*session
= NULL
; // saves state of session
1529 char sendbuf
[RPCAP_NETBUF_SIZE
]; // temporary buffer in which data to be sent is buffered
1530 int sendbufidx
= 0; // index which keeps the number of bytes currently buffered
1532 // socket-related variables
1533 SOCKET sockdata
= INVALID_SOCKET
; // socket descriptor of the data connection
1534 struct addrinfo hints
; // temp, needed to open a socket connection
1535 struct addrinfo
*addrinfo
; // temp, needed to open a socket connection
1536 struct sockaddr_storage saddr
; // temp, needed to retrieve the network data port chosen on the local machine
1537 socklen_t saddrlen
; // temp, needed to retrieve the network data port chosen on the local machine
1538 int ret
; // return value from functions
1542 pthread_attr_t detachedAttribute
; // temp, needed to set the created thread as detached
1545 // RPCAP-related variables
1546 struct rpcap_startcapreq startcapreq
; // start capture request message
1547 struct rpcap_startcapreply
*startcapreply
; // start capture reply message
1548 int serveropen_dp
; // keeps who is going to open the data connection
1552 status
= rpcapd_recv(pars
->sockctrl
, (char *) &startcapreq
,
1553 sizeof(struct rpcap_startcapreq
), &plen
, errmsgbuf
);
1563 startcapreq
.flags
= ntohs(startcapreq
.flags
);
1565 // Create a session structure
1566 session
= malloc(sizeof(struct session
));
1567 if (session
== NULL
)
1569 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Can't allocate session structure");
1573 // Open the selected device
1574 if ((session
->fp
= pcap_open_live(source
,
1575 ntohl(startcapreq
.snaplen
),
1576 (startcapreq
.flags
& RPCAP_STARTCAPREQ_FLAG_PROMISC
) ? 1 : 0 /* local device, other flags not needed */,
1577 ntohl(startcapreq
.read_timeout
),
1578 errmsgbuf
)) == NULL
)
1582 // Apply sampling parameters
1583 fp
->rmt_samp
.method
= samp_param
->method
;
1584 fp
->rmt_samp
.value
= samp_param
->value
;
1588 We're in active mode if:
1589 - we're using TCP, and the user wants us to be in active mode
1592 serveropen_dp
= (startcapreq
.flags
& RPCAP_STARTCAPREQ_FLAG_SERVEROPEN
) || (startcapreq
.flags
& RPCAP_STARTCAPREQ_FLAG_DGRAM
) || active
;
1595 Gets the sockaddr structure referred to the other peer in the ctrl connection
1597 We need that because:
1598 - if we're in passive mode, we need to know the address family we want to use
1599 (the same used for the ctrl socket)
1600 - if we're in active mode, we need to know the network address of the other host
1601 we want to connect to
1603 saddrlen
= sizeof(struct sockaddr_storage
);
1604 if (getpeername(pars
->sockctrl
, (struct sockaddr
*) &saddr
, &saddrlen
) == -1)
1606 sock_geterror("getpeername(): ", errmsgbuf
, PCAP_ERRBUF_SIZE
);
1610 memset(&hints
, 0, sizeof(struct addrinfo
));
1611 hints
.ai_socktype
= (startcapreq
.flags
& RPCAP_STARTCAPREQ_FLAG_DGRAM
) ? SOCK_DGRAM
: SOCK_STREAM
;
1612 hints
.ai_family
= saddr
.ss_family
;
1614 // Now we have to create a new socket to send packets
1615 if (serveropen_dp
) // Data connection is opened by the server toward the client
1617 sprintf(portdata
, "%d", ntohs(startcapreq
.portdata
));
1619 // Get the name of the other peer (needed to connect to that specific network address)
1620 if (getnameinfo((struct sockaddr
*) &saddr
, saddrlen
, peerhost
,
1621 sizeof(peerhost
), NULL
, 0, NI_NUMERICHOST
))
1623 sock_geterror("getnameinfo(): ", errmsgbuf
, PCAP_ERRBUF_SIZE
);
1627 if (sock_initaddress(peerhost
, portdata
, &hints
, &addrinfo
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1630 if ((sockdata
= sock_open(addrinfo
, SOCKOPEN_CLIENT
, 0, errmsgbuf
, PCAP_ERRBUF_SIZE
)) == INVALID_SOCKET
)
1633 else // Data connection is opened by the client toward the server
1635 hints
.ai_flags
= AI_PASSIVE
;
1637 // Let's the server socket pick up a free network port for us
1638 if (sock_initaddress(NULL
, "0", &hints
, &addrinfo
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1641 if ((sockdata
= sock_open(addrinfo
, SOCKOPEN_SERVER
, 1 /* max 1 connection in queue */, errmsgbuf
, PCAP_ERRBUF_SIZE
)) == INVALID_SOCKET
)
1644 // get the complete sockaddr structure used in the data connection
1645 saddrlen
= sizeof(struct sockaddr_storage
);
1646 if (getsockname(sockdata
, (struct sockaddr
*) &saddr
, &saddrlen
) == -1)
1648 sock_geterror("getsockname(): ", errmsgbuf
, PCAP_ERRBUF_SIZE
);
1652 // Get the local port the system picked up
1653 if (getnameinfo((struct sockaddr
*) &saddr
, saddrlen
, NULL
,
1654 0, portdata
, sizeof(portdata
), NI_NUMERICSERV
))
1656 sock_geterror("getnameinfo(): ", errmsgbuf
, PCAP_ERRBUF_SIZE
);
1661 // addrinfo is no longer used
1662 freeaddrinfo(addrinfo
);
1665 // Needed to send an error on the ctrl connection
1666 session
->sockctrl
= pars
->sockctrl
;
1667 session
->protocol_version
= pars
->protocol_version
;
1669 // Now I can set the filter
1670 ret
= daemon_unpackapplyfilter(pars
->sockctrl
, session
, &plen
, errmsgbuf
);
1673 // Fatal error. A message has been logged; just give up.
1678 // Non-fatal error. Send an error message to the client.
1682 // Now, I can send a RPCAP start capture reply message
1683 if (sock_bufferize(NULL
, sizeof(struct rpcap_header
), NULL
, &sendbufidx
,
1684 RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1687 rpcap_createhdr((struct rpcap_header
*) sendbuf
, pars
->protocol_version
,
1688 RPCAP_MSG_STARTCAP_REPLY
, 0, sizeof(struct rpcap_startcapreply
));
1690 startcapreply
= (struct rpcap_startcapreply
*) &sendbuf
[sendbufidx
];
1692 if (sock_bufferize(NULL
, sizeof(struct rpcap_startcapreply
), NULL
,
1693 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1696 memset(startcapreply
, 0, sizeof(struct rpcap_startcapreply
));
1697 startcapreply
->bufsize
= htonl(pcap_bufsize(session
->fp
));
1701 unsigned short port
= (unsigned short)strtoul(portdata
,NULL
,10);
1702 startcapreply
->portdata
= htons(port
);
1705 if (sock_send(pars
->sockctrl
, sendbuf
, sendbufidx
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
1707 // That failed; log a message and give up.
1708 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1714 SOCKET socktemp
; // We need another socket, since we're going to accept() a connection
1716 // Connection creation
1717 saddrlen
= sizeof(struct sockaddr_storage
);
1719 socktemp
= accept(sockdata
, (struct sockaddr
*) &saddr
, &saddrlen
);
1721 if (socktemp
== INVALID_SOCKET
)
1723 sock_geterror("accept(): ", errbuf
, PCAP_ERRBUF_SIZE
);
1724 rpcapd_log(LOGPRIO_ERROR
, "Accept of data connection failed: %s",
1729 // Now that I accepted the connection, the server socket is no longer needed
1730 sock_close(sockdata
, NULL
, 0);
1731 sockdata
= socktemp
;
1734 session
->sockdata
= sockdata
;
1736 // Now we have to create a new thread to receive packets
1738 *threaddata
= (HANDLE
)_beginthreadex(NULL
, 0, daemon_thrdatamain
,
1739 (void *) session
, 0, NULL
);
1740 if (*threaddata
== 0)
1742 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Error creating the data thread");
1746 /* GV we need this to create the thread as detached. */
1747 /* GV otherwise, the thread handle is not destroyed */
1748 pthread_attr_init(&detachedAttribute
);
1749 pthread_attr_setdetachstate(&detachedAttribute
, PTHREAD_CREATE_DETACHED
);
1750 ret
= pthread_create(threaddata
, &detachedAttribute
,
1751 daemon_thrdatamain
, (void *) session
);
1754 char thread_errbuf
[PCAP_ERRBUF_SIZE
];
1756 strerror_r(ret
, thread_errbuf
, PCAP_ERRBUF_SIZE
);
1757 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Error creating the data thread: %s", thread_errbuf
);
1758 pthread_attr_destroy(&detachedAttribute
);
1761 pthread_attr_destroy(&detachedAttribute
);
1765 // Check if all the data has been read; if not, discard the data in excess
1766 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
1769 *sessionp
= session
;
1774 // Not a fatal error, so send the client an error message and
1775 // keep serving client requests.
1780 freeaddrinfo(addrinfo
);
1787 pcap_breakloop(session
->fp
);
1788 SetEvent(pcap_getevent(session
->fp
));
1790 CloseHandle(*threaddata
);
1792 pthread_cancel(*threaddata
);
1797 if (sockdata
!= INVALID_SOCKET
)
1798 sock_close(sockdata
, NULL
, 0);
1803 pcap_close(session
->fp
);
1807 if (rpcap_senderror(pars
->sockctrl
, pars
->protocol_version
,
1808 PCAP_ERR_STARTCAPTURE
, errmsgbuf
, errbuf
) == -1)
1810 // That failed; log a message and give up.
1811 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1815 // Check if all the data has been read; if not, discard the data in excess
1816 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
1826 // Fatal network error, so don't try to communicate with
1827 // the client, just give up.
1832 freeaddrinfo(addrinfo
);
1837 if (session
&& session
->fp
)
1840 // Tell the data connection thread main capture
1841 // loop to break out of that loop.
1843 pcap_breakloop(session
->fp
);
1846 // If it's currently blocked waiting for packets
1847 // to arrive, try to wake it up, so it can see
1848 // the "break out of the loop" indication.
1850 SetEvent(pcap_getevent(session
->fp
));
1854 // Wait for the thread to exit, so we don't close
1855 // sockets out from under it.
1857 // XXX - have a timeout, so we don't wait forever?
1859 WaitForSingleObject(*threaddata
, INFINITE
);
1862 // Release the thread handle, as we're done with
1865 CloseHandle(*threaddata
);
1867 pthread_cancel(*threaddata
);
1872 if (sockdata
!= INVALID_SOCKET
)
1873 sock_close(sockdata
, NULL
, 0);
1878 pcap_close(session
->fp
);
1886 static int daemon_msg_endcap_req(struct daemon_slpars
*pars
, struct session
*session
, int *have_thread
, HANDLE threaddata
)
1888 static int daemon_msg_endcap_req(struct daemon_slpars
*pars
, struct session
*session
, int *have_thread
, pthread_t threaddata
)
1891 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
1892 struct rpcap_header header
;
1898 // Tell the data connection thread main capture loop to
1899 // break out of that loop.
1901 pcap_breakloop(session
->fp
);
1904 // If it's currently blocked waiting for packets to
1905 // arrive, try to wake it up, so it can see the "break
1906 // out of the loop" indication.
1908 SetEvent(pcap_getevent(session
->fp
));
1911 // Wait for the thread to exit, so we don't close
1912 // sockets out from under it.
1914 // XXX - have a timeout, so we don't wait forever?
1916 WaitForSingleObject(threaddata
, INFINITE
);
1919 // Release the thread handle, as we're done with
1922 CloseHandle(threaddata
);
1924 pthread_cancel(threaddata
);
1928 if (session
->sockdata
)
1930 sock_close(session
->sockdata
, NULL
, 0);
1931 session
->sockdata
= 0;
1934 pcap_close(session
->fp
);
1936 rpcap_createhdr(&header
, pars
->protocol_version
,
1937 RPCAP_MSG_ENDCAP_REPLY
, 0, 0);
1939 if (sock_send(pars
->sockctrl
, (char *) &header
, sizeof(struct rpcap_header
), errbuf
, PCAP_ERRBUF_SIZE
) == -1)
1941 // That failed; log a message and give up.
1942 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1949 static int daemon_unpackapplyfilter(SOCKET sockctrl
, struct session
*session
, uint32
*plenp
, char *errmsgbuf
)
1952 struct rpcap_filter filter
;
1953 struct rpcap_filterbpf_insn insn
;
1954 struct bpf_insn
*bf_insn
;
1955 struct bpf_program bf_prog
;
1958 status
= rpcapd_recv(sockctrl
, (char *) &filter
,
1959 sizeof(struct rpcap_filter
), plenp
, errmsgbuf
);
1969 bf_prog
.bf_len
= ntohl(filter
.nitems
);
1971 if (ntohs(filter
.filtertype
) != RPCAP_UPDATEFILTER_BPF
)
1973 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Only BPF/NPF filters are currently supported");
1977 bf_insn
= (struct bpf_insn
*) malloc (sizeof(struct bpf_insn
) * bf_prog
.bf_len
);
1978 if (bf_insn
== NULL
)
1980 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
1984 bf_prog
.bf_insns
= bf_insn
;
1986 for (i
= 0; i
< bf_prog
.bf_len
; i
++)
1988 status
= rpcapd_recv(sockctrl
, (char *) &insn
,
1989 sizeof(struct rpcap_filterbpf_insn
), plenp
, errmsgbuf
);
1999 bf_insn
->code
= ntohs(insn
.code
);
2000 bf_insn
->jf
= insn
.jf
;
2001 bf_insn
->jt
= insn
.jt
;
2002 bf_insn
->k
= ntohl(insn
.k
);
2007 if (bpf_validate(bf_prog
.bf_insns
, bf_prog
.bf_len
) == 0)
2009 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "The filter contains bogus instructions");
2013 if (pcap_setfilter(session
->fp
, &bf_prog
))
2015 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "RPCAP error: %s", pcap_geterr(session
->fp
));
2022 int daemon_msg_updatefilter_req(struct daemon_slpars
*pars
, struct session
*session
, uint32 plen
)
2024 char errbuf
[PCAP_ERRBUF_SIZE
];
2025 char errmsgbuf
[PCAP_ERRBUF_SIZE
]; // buffer for errors to send to the client
2026 int ret
; // status of daemon_unpackapplyfilter()
2027 struct rpcap_header header
; // keeps the answer to the updatefilter command
2029 ret
= daemon_unpackapplyfilter(pars
->sockctrl
, session
, &plen
, errmsgbuf
);
2032 // Fatal error. A message has been logged; just give up.
2037 // Non-fatal error. Send an error reply to the client.
2041 // Check if all the data has been read; if not, discard the data in excess
2042 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
2048 // A response is needed, otherwise the other host does not know that everything went well
2049 rpcap_createhdr(&header
, pars
->protocol_version
,
2050 RPCAP_MSG_UPDATEFILTER_REPLY
, 0, 0);
2052 if (sock_send(pars
->sockctrl
, (char *) &header
, sizeof (struct rpcap_header
), pcap_geterr(session
->fp
), PCAP_ERRBUF_SIZE
))
2054 // That failed; log a messsage and give up.
2055 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
2062 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
2066 rpcap_senderror(pars
->sockctrl
, pars
->protocol_version
,
2067 PCAP_ERR_UPDATEFILTER
, errmsgbuf
, NULL
);
2073 \brief Received the sampling parameters from remote host and it stores in the pcap_t structure.
2075 int daemon_msg_setsampling_req(struct daemon_slpars
*pars
, uint32 plen
, struct rpcap_sampling
*samp_param
)
2077 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
2078 char errmsgbuf
[PCAP_ERRBUF_SIZE
];
2079 struct rpcap_header header
;
2080 struct rpcap_sampling rpcap_samp
;
2083 status
= rpcapd_recv(pars
->sockctrl
, (char *) &rpcap_samp
, sizeof(struct rpcap_sampling
), &plen
, errmsgbuf
);
2093 // Save these settings in the pcap_t
2094 samp_param
->method
= rpcap_samp
.method
;
2095 samp_param
->value
= ntohl(rpcap_samp
.value
);
2097 // A response is needed, otherwise the other host does not know that everything went well
2098 rpcap_createhdr(&header
, pars
->protocol_version
,
2099 RPCAP_MSG_SETSAMPLING_REPLY
, 0, 0);
2101 if (sock_send(pars
->sockctrl
, (char *) &header
, sizeof (struct rpcap_header
), errbuf
, PCAP_ERRBUF_SIZE
) == -1)
2103 // That failed; log a messsage and give up.
2104 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
2108 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
2116 if (rpcap_senderror(pars
->sockctrl
, pars
->protocol_version
,
2117 PCAP_ERR_AUTH
, errmsgbuf
, errbuf
) == -1)
2119 // That failed; log a message and give up.
2120 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
2124 // Check if all the data has been read; if not, discard the data in excess
2125 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
2133 static int daemon_msg_stats_req(struct daemon_slpars
*pars
, struct session
*session
, uint32 plen
, struct pcap_stat
*stats
, unsigned int svrcapt
)
2135 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
2136 char errmsgbuf
[PCAP_ERRBUF_SIZE
]; // buffer for errors to send to the client
2137 char sendbuf
[RPCAP_NETBUF_SIZE
]; // temporary buffer in which data to be sent is buffered
2138 int sendbufidx
= 0; // index which keeps the number of bytes currently buffered
2139 struct rpcap_stats
*netstats
; // statistics sent on the network
2141 // Checks that the header does not contain other data; if so, discard it
2142 if (rpcapd_discard(pars
->sockctrl
, plen
) == -1)
2148 if (sock_bufferize(NULL
, sizeof(struct rpcap_header
), NULL
,
2149 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
2152 rpcap_createhdr((struct rpcap_header
*) sendbuf
, pars
->protocol_version
,
2153 RPCAP_MSG_STATS_REPLY
, 0, (uint16
) sizeof(struct rpcap_stats
));
2155 netstats
= (struct rpcap_stats
*) &sendbuf
[sendbufidx
];
2157 if (sock_bufferize(NULL
, sizeof(struct rpcap_stats
), NULL
,
2158 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
2161 if (session
&& session
->fp
)
2163 if (pcap_stats(session
->fp
, stats
) == -1)
2165 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "%s", pcap_geterr(session
->fp
));
2169 netstats
->ifdrop
= htonl(stats
->ps_ifdrop
);
2170 netstats
->ifrecv
= htonl(stats
->ps_recv
);
2171 netstats
->krnldrop
= htonl(stats
->ps_drop
);
2172 netstats
->svrcapt
= htonl(session
->TotCapt
);
2176 // We have to keep compatibility with old applications,
2177 // which ask for statistics also when the capture has
2179 netstats
->ifdrop
= htonl(stats
->ps_ifdrop
);
2180 netstats
->ifrecv
= htonl(stats
->ps_recv
);
2181 netstats
->krnldrop
= htonl(stats
->ps_drop
);
2182 netstats
->svrcapt
= htonl(svrcapt
);
2186 if (sock_send(pars
->sockctrl
, sendbuf
, sendbufidx
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
2188 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
2195 rpcap_senderror(pars
->sockctrl
, pars
->protocol_version
,
2196 PCAP_ERR_GETSTATS
, errmsgbuf
, NULL
);
2201 static unsigned __stdcall
2205 daemon_thrdatamain(void *ptr
)
2207 char errbuf
[PCAP_ERRBUF_SIZE
+ 1]; // error buffer
2208 struct session
*session
; // pointer to the struct session for this session
2209 int retval
; // general variable used to keep the return value of other functions
2210 struct rpcap_pkthdr
*net_pkt_header
;// header of the packet
2211 struct pcap_pkthdr
*pkt_header
; // pointer to the buffer that contains the header of the current packet
2212 u_char
*pkt_data
; // pointer to the buffer that contains the current packet
2213 size_t sendbufsize
; // size for the send buffer
2214 char *sendbuf
; // temporary buffer in which data to be sent is buffered
2215 int sendbufidx
; // index which keeps the number of bytes currently buffered
2217 session
= (struct session
*) ptr
;
2219 session
->TotCapt
= 0; // counter which is incremented each time a packet is received
2221 // Initialize errbuf
2222 memset(errbuf
, 0, sizeof(errbuf
));
2225 // We need a buffer large enough to hold a buffer large enough
2226 // for a maximum-size packet for this pcap_t.
2228 sendbufsize
= sizeof(struct rpcap_header
) + sizeof(struct rpcap_pkthdr
) + pcap_snapshot(session
->fp
);
2229 sendbuf
= (char *) malloc (sendbufsize
);
2230 if (sendbuf
== NULL
)
2232 rpcapd_log(LOGPRIO_ERROR
,
2233 "Unable to allocate the buffer for this child thread");
2238 // Modify thread params so that it can be killed at any time
2239 retval
= pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, NULL
);
2242 strerror_r(retval
, errbuf
, PCAP_ERRBUF_SIZE
);
2243 rpcapd_log(LOGPRIO_ERROR
,
2244 "Can't set cancel state on data thread: %s", errbuf
);
2247 if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
))
2249 strerror_r(retval
, errbuf
, PCAP_ERRBUF_SIZE
);
2250 rpcapd_log(LOGPRIO_ERROR
,
2251 "Can't set cancel type on data thread: %s", errbuf
);
2256 // Retrieve the packets
2257 while ((retval
= pcap_next_ex(session
->fp
, &pkt_header
, (const u_char
**) &pkt_data
)) >= 0) // cast to avoid a compiler warning
2259 if (retval
== 0) // Read timeout elapsed
2264 // Bufferize the general header
2265 if (sock_bufferize(NULL
, sizeof(struct rpcap_header
), NULL
,
2266 &sendbufidx
, sendbufsize
, SOCKBUF_CHECKONLY
, errbuf
,
2267 PCAP_ERRBUF_SIZE
) == -1)
2269 rpcapd_log(LOGPRIO_ERROR
,
2270 "sock_bufferize() error sending packet message: %s",
2275 rpcap_createhdr((struct rpcap_header
*) sendbuf
,
2276 session
->protocol_version
, RPCAP_MSG_PACKET
, 0,
2277 (uint16
) (sizeof(struct rpcap_pkthdr
) + pkt_header
->caplen
));
2279 net_pkt_header
= (struct rpcap_pkthdr
*) &sendbuf
[sendbufidx
];
2281 // Bufferize the pkt header
2282 if (sock_bufferize(NULL
, sizeof(struct rpcap_pkthdr
), NULL
,
2283 &sendbufidx
, sendbufsize
, SOCKBUF_CHECKONLY
, errbuf
,
2284 PCAP_ERRBUF_SIZE
) == -1)
2286 rpcapd_log(LOGPRIO_ERROR
,
2287 "sock_bufferize() error sending packet message: %s",
2292 net_pkt_header
->caplen
= htonl(pkt_header
->caplen
);
2293 net_pkt_header
->len
= htonl(pkt_header
->len
);
2294 net_pkt_header
->npkt
= htonl(++(session
->TotCapt
));
2295 net_pkt_header
->timestamp_sec
= htonl(pkt_header
->ts
.tv_sec
);
2296 net_pkt_header
->timestamp_usec
= htonl(pkt_header
->ts
.tv_usec
);
2298 // Bufferize the pkt data
2299 if (sock_bufferize((char *) pkt_data
, pkt_header
->caplen
,
2300 sendbuf
, &sendbufidx
, sendbufsize
, SOCKBUF_BUFFERIZE
,
2301 errbuf
, PCAP_ERRBUF_SIZE
) == -1)
2303 rpcapd_log(LOGPRIO_ERROR
,
2304 "sock_bufferize() error sending packet message: %s",
2310 if (sock_send(session
->sockdata
, sendbuf
, sendbufidx
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
2312 rpcapd_log(LOGPRIO_ERROR
,
2313 "Send of packet to client failed: %s", errbuf
);
2320 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Error reading the packets: %s", pcap_geterr(session
->fp
));
2321 rpcap_senderror(session
->sockctrl
, session
->protocol_version
,
2322 PCAP_ERR_READEX
, errbuf
, NULL
);
2327 closesocket(session
->sockdata
);
2328 session
->sockdata
= 0;
2336 \brief It serializes a network address.
2338 It accepts a 'sockaddr_storage' structure as input, and it converts it appropriately into a format
2339 that can be used to be sent on the network. Basically, it applies all the hton()
2340 conversion required to the input variable.
2342 \param sockaddrin: a 'sockaddr_storage' pointer to the variable that has to be
2343 serialized. This variable can be both a 'sockaddr_in' and 'sockaddr_in6'.
2345 \param sockaddrout: an 'rpcap_sockaddr' pointer to the variable that will contain
2346 the serialized data. This variable has to be allocated by the user.
2350 \warning This function supports only AF_INET and AF_INET6 address families.
2352 void daemon_seraddr(struct sockaddr_storage
*sockaddrin
, struct rpcap_sockaddr
*sockaddrout
)
2354 memset(sockaddrout
, 0, sizeof(struct sockaddr_storage
));
2356 // There can be the case in which the sockaddrin is not available
2357 if (sockaddrin
== NULL
) return;
2359 // Warning: we support only AF_INET and AF_INET6
2360 switch (sockaddrin
->ss_family
)
2364 struct sockaddr_in
*sockaddrin_ipv4
;
2365 struct rpcap_sockaddr_in
*sockaddrout_ipv4
;
2367 sockaddrin_ipv4
= (struct sockaddr_in
*) sockaddrin
;
2368 sockaddrout_ipv4
= (struct rpcap_sockaddr_in
*) sockaddrout
;
2369 sockaddrout_ipv4
->family
= htons(RPCAP_AF_INET
);
2370 sockaddrout_ipv4
->port
= htons(sockaddrin_ipv4
->sin_port
);
2371 memcpy(&sockaddrout_ipv4
->addr
, &sockaddrin_ipv4
->sin_addr
, sizeof(sockaddrout_ipv4
->addr
));
2372 memset(sockaddrout_ipv4
->zero
, 0, sizeof(sockaddrout_ipv4
->zero
));
2379 struct sockaddr_in6
*sockaddrin_ipv6
;
2380 struct rpcap_sockaddr_in6
*sockaddrout_ipv6
;
2382 sockaddrin_ipv6
= (struct sockaddr_in6
*) sockaddrin
;
2383 sockaddrout_ipv6
= (struct rpcap_sockaddr_in6
*) sockaddrout
;
2384 sockaddrout_ipv6
->family
= htons(RPCAP_AF_INET6
);
2385 sockaddrout_ipv6
->port
= htons(sockaddrin_ipv6
->sin6_port
);
2386 sockaddrout_ipv6
->flowinfo
= htonl(sockaddrin_ipv6
->sin6_flowinfo
);
2387 memcpy(&sockaddrout_ipv6
->addr
, &sockaddrin_ipv6
->sin6_addr
, sizeof(sockaddrout_ipv6
->addr
));
2388 sockaddrout_ipv6
->scope_id
= htonl(sockaddrin_ipv6
->sin6_scope_id
);
2397 \brief Suspends a thread for secs seconds.
2399 void sleep_secs(int secs
)
2404 unsigned secs_remaining
;
2408 secs_remaining
= secs
;
2409 while (secs_remaining
!= 0)
2410 secs_remaining
= sleep(secs_remaining
);
2415 * Read the header of a message.
2417 static int rpcapd_recv_msg_header(SOCKET sock
, struct rpcap_header
*headerp
)
2420 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
2422 nread
= sock_recv(sock
, (char *) headerp
, sizeof(struct rpcap_header
),
2423 SOCK_RECEIVEALL_YES
|SOCK_EOF_ISNT_ERROR
, errbuf
, PCAP_ERRBUF_SIZE
);
2427 rpcapd_log(LOGPRIO_ERROR
, "Read from client failed: %s", errbuf
);
2432 // Immediate EOF; that's treated like a close message.
2435 headerp
->plen
= ntohl(headerp
->plen
);
2440 * Read data from a message.
2441 * If we're trying to read more data that remains, puts an error
2442 * message into errmsgbuf and returns -2. Otherwise, tries to read
2443 * the data and, if that succeeds, subtracts the amount read from
2444 * the number of bytes of data that remains.
2445 * Returns 0 on success, logs a message and returns -1 on a network
2448 static int rpcapd_recv(SOCKET sock
, char *buffer
, size_t toread
, uint32
*plen
, char *errmsgbuf
)
2451 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
2455 // Tell the client and continue.
2456 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Message payload is too short");
2459 nread
= sock_recv(sock
, buffer
, toread
,
2460 SOCK_RECEIVEALL_YES
|SOCK_EOF_IS_ERROR
, errbuf
, PCAP_ERRBUF_SIZE
);
2463 rpcapd_log(LOGPRIO_ERROR
, "Read from client failed: %s", errbuf
);
2471 * Discard data from a connection.
2472 * Mostly used to discard wrong-sized messages.
2473 * Returns 0 on success, logs a message and returns -1 on a network
2476 static int rpcapd_discard(SOCKET sock
, uint32 len
)
2478 char errbuf
[PCAP_ERRBUF_SIZE
+ 1]; // keeps the error string, prior to be printed
2482 if (sock_discard(sock
, len
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
2485 rpcapd_log(LOGPRIO_ERROR
, "Read from client failed: %s", errbuf
);