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.
39 #include <errno.h> // for the errno variable
40 #include <stdlib.h> // for malloc(), free(), ...
41 #include <string.h> // for strlen(), ...
44 #include <process.h> // for threads
49 #include <sys/types.h> // for select() and such
50 #include <pwd.h> // for password management
54 #include <shadow.h> // for password management
57 #include <pcap.h> // for libpcap/WinPcap calls
60 #include "sockutils.h" // for socket calls
61 #include "portability.h"
62 #include "rpcap-protocol.h"
66 #define RPCAP_TIMEOUT_INIT 90 /* Initial timeout for RPCAP connections (default: 90 sec) */
67 #define RPCAP_TIMEOUT_RUNTIME 180 /* Run-time timeout for RPCAP connections (default: 3 min) */
68 #define RPCAP_SUSPEND_WRONGAUTH 1 /* If the authentication is wrong, stops 1 sec before accepting a new auth message */
70 // Parameters for the service loop.
73 SOCKET sockctrl_in
; //!< SOCKET ID of the input side of the control connection
74 SOCKET sockctrl_out
; //!< SOCKET ID of the output side of the control connection
75 uint8 protocol_version
; //!< negotiated protocol version
76 int isactive
; //!< Not null if the daemon has to run in active mode
77 int nullAuthAllowed
; //!< '1' if we permit NULL authentication, '0' otherwise
81 * Data for a session managed by a thread.
86 uint8 protocol_version
;
92 // Structure to refer to a thread.
93 // It includes both a Boolean indicating whether we *have* a thread,
94 // and a platform-dependent (UN*X vs. Windows) identifier for the
95 // thread; on Windows, we could use an invalid handle to indicate
96 // that we don't have a thread, but there *is* no portable "no thread"
97 // value for a pthread_t on UN*X.
99 struct thread_handle
{
108 // Locally defined functions
109 static int daemon_msg_err(SOCKET sockctrl_in
, uint32 plen
);
110 static int daemon_msg_auth_req(struct daemon_slpars
*pars
, uint32 plen
);
111 static int daemon_AuthUserPwd(char *username
, char *password
, char *errbuf
);
113 static int daemon_msg_findallif_req(struct daemon_slpars
*pars
, uint32 plen
);
115 static int daemon_msg_open_req(struct daemon_slpars
*pars
, uint32 plen
, char *source
, size_t sourcelen
);
116 static int daemon_msg_startcap_req(struct daemon_slpars
*pars
, uint32 plen
, struct thread_handle
*threaddata
, char *source
, struct session
**sessionp
, struct rpcap_sampling
*samp_param
);
117 static int daemon_msg_endcap_req(struct daemon_slpars
*pars
, struct session
*session
, struct thread_handle
*threaddata
);
119 static int daemon_msg_updatefilter_req(struct daemon_slpars
*pars
, struct session
*session
, uint32 plen
);
120 static int daemon_unpackapplyfilter(SOCKET sockctrl_in
, struct session
*session
, uint32
*plenp
, char *errbuf
);
122 static int daemon_msg_stats_req(struct daemon_slpars
*pars
, struct session
*session
, uint32 plen
, struct pcap_stat
*stats
, unsigned int svrcapt
);
124 static int daemon_msg_setsampling_req(struct daemon_slpars
*pars
, uint32 plen
, struct rpcap_sampling
*samp_param
);
126 static void daemon_seraddr(struct sockaddr_storage
*sockaddrin
, struct rpcap_sockaddr
*sockaddrout
);
128 static unsigned __stdcall
daemon_thrdatamain(void *ptr
);
130 static void *daemon_thrdatamain(void *ptr
);
133 static int rpcapd_recv_msg_header(SOCKET sock
, struct rpcap_header
*headerp
);
134 static int rpcapd_recv(SOCKET sock
, char *buffer
, size_t toread
, uint32
*plen
, char *errmsgbuf
);
135 static int rpcapd_discard(SOCKET sock
, uint32 len
);
138 daemon_serviceloop(SOCKET sockctrl_in
, SOCKET sockctrl_out
, int isactive
, int nullAuthAllowed
)
140 struct daemon_slpars pars
; // service loop parameters
141 char errbuf
[PCAP_ERRBUF_SIZE
+ 1]; // keeps the error string, prior to be printed
142 char errmsgbuf
[PCAP_ERRBUF_SIZE
+ 1]; // buffer for errors to send to the client
144 struct rpcap_header header
; // RPCAP message general header
145 uint32 plen
; // payload length from header
146 int authenticated
= 0; // 1 if the client has successfully authenticated
147 char source
[PCAP_BUF_SIZE
+1]; // keeps the string that contains the interface to open
148 int got_source
= 0; // 1 if we've gotten the source from an open request
149 struct session
*session
= NULL
; // struct session main variable
150 const char *msg_type_string
; // string for message type
151 int client_told_us_to_close
= 0; // 1 if the client told us to close the capture
153 struct thread_handle threaddata
; // 'read from daemon and send to client' thread
155 // needed to save the values of the statistics
156 struct pcap_stat stats
;
157 unsigned int svrcapt
;
159 struct rpcap_sampling samp_param
; // in case sampling has been requested
161 // Structures needed for the select() call
162 fd_set rfds
; // set of socket descriptors we have to check
163 struct timeval tv
; // maximum time the select() can block waiting for data
164 int retval
; // select() return value
166 // Set parameters structure
167 pars
.sockctrl_in
= sockctrl_in
;
168 pars
.sockctrl_out
= sockctrl_out
;
169 pars
.protocol_version
= 0; // not yet known
170 pars
.isactive
= isactive
; // active mode
171 pars
.nullAuthAllowed
= nullAuthAllowed
;
173 // We don't have a thread yet.
174 threaddata
.have_thread
= 0;
176 // We *shouldn't* have to initialize the thread indicator
177 // itself, because the compiler *should* realize that we
178 // only use this if have_thread isn't 0, but we *do* have
179 // to do it, because not all compilers *do* realize that.
181 // There is no "invalid thread handle" value for a UN*X
182 // pthread_t, so we just zero it out.
185 threaddata
.thread
= INVALID_HANDLE_VALUE
;
187 memset(&threaddata
.thread
, 0, sizeof(threaddata
.thread
));
190 *errbuf
= 0; // Initialize errbuf
193 // The client must first authenticate; loop until they send us a
194 // message with a version we support and credentials we accept,
195 // they send us a close message indicating that they're giving up,
196 // or we get a network error or other fatal error.
198 while (!authenticated
)
201 // If we're in active mode, we have to check for the
204 // XXX - do this on *every* trip through the loop?
209 // We do not have to block here
210 tv
.tv_sec
= RPCAP_TIMEOUT_INIT
;
213 FD_SET(pars
.sockctrl_in
, &rfds
);
215 retval
= select(pars
.sockctrl_in
+ 1, &rfds
, NULL
, NULL
, &tv
);
218 sock_geterror("select failed: ", errmsgbuf
, PCAP_ERRBUF_SIZE
);
219 if (rpcap_senderror(pars
.sockctrl_out
, 0, PCAP_ERR_NETW
, errmsgbuf
, errbuf
) == -1)
220 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
224 // The timeout has expired
225 // So, this was a fake connection. Drop it down
228 if (rpcap_senderror(pars
.sockctrl_out
, 0, PCAP_ERR_INITTIMEOUT
, "The RPCAP initial timeout has expired", errbuf
) == -1)
229 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
235 // Read the message header from the client.
237 nrecv
= rpcapd_recv_msg_header(pars
.sockctrl_in
, &header
);
245 // Client closed the connection.
252 // Did the client specify a version we can handle?
254 if (!RPCAP_VERSION_IS_SUPPORTED(header
.ver
))
257 // Tell them it's not a valid protocol version.
262 // If RPCAP_MIN_VERSION is 0, no version is too
263 // old, as the oldest supported version is 0,
264 // and there are no negative versions.
266 #if RPCAP_MIN_VERSION != 0
267 if (header
.ver
< RPCAP_MIN_VERSION
)
270 // Their maximum version is too old;
271 // there *is* no version we can both
272 // handle, and they might reject
273 // an error with a version they don't
274 // understand, so reply with the
275 // version they sent. That may
276 // make them retry with that version,
277 // but they'll give up on that
280 reply_version
= header
.ver
;
286 // Their maximum version is too new,
287 // but they might be able to handle
288 // *our* maximum version, so reply
289 // with that version.
291 reply_version
= RPCAP_MAX_VERSION
;
293 if (rpcap_senderror(pars
.sockctrl_out
, reply_version
,
294 PCAP_ERR_WRONGVER
, "RPCAP version number mismatch",
297 // That failed; log a message and give up.
298 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
302 // Discard the rest of the message.
303 if (rpcapd_discard(pars
.sockctrl_in
, plen
) == -1)
309 // Let them try again.
314 // OK, we use the version the client specified.
316 pars
.protocol_version
= header
.ver
;
320 case RPCAP_MSG_AUTH_REQ
:
321 retval
= daemon_msg_auth_req(&pars
, plen
);
324 // Fatal error; a message has
325 // been logged, so just give up.
330 // Non-fatal error; we sent back
331 // an error message, so let them
336 // OK, we're authenticated; we sent back
337 // a reply, so start serving requests.
341 case RPCAP_MSG_CLOSE
:
343 // The client is giving up.
344 // Discard the rest of the message, if
345 // there is anything more.
347 (void)rpcapd_discard(pars
.sockctrl_in
, plen
);
348 // We're done with this client.
351 case RPCAP_MSG_ERROR
:
352 // Log this and close the connection?
353 // XXX - is this what happens in active
354 // mode, where *we* initiate the
355 // connection, and the client gives us
356 // an error message rather than a "let
357 // me log in" message, indicating that
358 // we're not allowed to connect to them?
359 (void)daemon_msg_err(pars
.sockctrl_in
, plen
);
362 case RPCAP_MSG_FINDALLIF_REQ
:
363 case RPCAP_MSG_OPEN_REQ
:
364 case RPCAP_MSG_STARTCAP_REQ
:
365 case RPCAP_MSG_UPDATEFILTER_REQ
:
366 case RPCAP_MSG_STATS_REQ
:
367 case RPCAP_MSG_ENDCAP_REQ
:
368 case RPCAP_MSG_SETSAMPLING_REQ
:
370 // These requests can't be sent until
371 // the client is authenticated.
373 msg_type_string
= rpcap_msg_type_string(header
.type
);
374 if (msg_type_string
!= NULL
)
376 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "%s request sent before authentication was completed", msg_type_string
);
380 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Message of type %u sent before authentication was completed", header
.type
);
382 if (rpcap_senderror(pars
.sockctrl_out
,
383 pars
.protocol_version
, PCAP_ERR_WRONGMSG
,
384 errmsgbuf
, errbuf
) == -1)
386 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
389 // Discard the rest of the message.
390 if (rpcapd_discard(pars
.sockctrl_in
, plen
) == -1)
397 case RPCAP_MSG_PACKET
:
398 case RPCAP_MSG_FINDALLIF_REPLY
:
399 case RPCAP_MSG_OPEN_REPLY
:
400 case RPCAP_MSG_STARTCAP_REPLY
:
401 case RPCAP_MSG_UPDATEFILTER_REPLY
:
402 case RPCAP_MSG_AUTH_REPLY
:
403 case RPCAP_MSG_STATS_REPLY
:
404 case RPCAP_MSG_ENDCAP_REPLY
:
405 case RPCAP_MSG_SETSAMPLING_REPLY
:
407 // These are server-to-client messages.
409 msg_type_string
= rpcap_msg_type_string(header
.type
);
410 if (msg_type_string
!= NULL
)
412 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Server-to-client message %s received from client", msg_type_string
);
416 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Server-to-client message of type %u received from client", header
.type
);
418 if (rpcap_senderror(pars
.sockctrl_out
,
419 pars
.protocol_version
, PCAP_ERR_WRONGMSG
,
420 errmsgbuf
, errbuf
) == -1)
422 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
425 // Discard the rest of the message.
426 if (rpcapd_discard(pars
.sockctrl_in
, plen
) == -1)
435 // Unknown message type.
437 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Unknown message type %u", header
.type
);
438 if (rpcap_senderror(pars
.sockctrl_out
,
439 pars
.protocol_version
, PCAP_ERR_WRONGMSG
,
440 errmsgbuf
, errbuf
) == -1)
442 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
445 // Discard the rest of the message.
446 if (rpcapd_discard(pars
.sockctrl_in
, plen
) == -1)
456 // OK, the client has authenticated itself, and we can start
457 // processing regular requests from it.
461 // We don't have any statistics yet.
473 errbuf
[0] = 0; // clear errbuf
475 // Avoid zombies connections; check if the connection is opens but no commands are performed
476 // from more than RPCAP_TIMEOUT_RUNTIME
478 // - I have to be in normal mode (no active mode)
479 // - if the device is open, I don't have to be in the middle of a capture (session->sockdata)
480 // - if the device is closed, I have always to check if a new command arrives
482 // Be carefully: the capture can have been started, but an error occurred (so session != NULL, but
484 if ((!pars
.isactive
) && ((session
== NULL
) || ((session
!= NULL
) && (session
->sockdata
== 0))))
486 // Check for the initial timeout
488 // We do not have to block here
489 tv
.tv_sec
= RPCAP_TIMEOUT_RUNTIME
;
492 FD_SET(pars
.sockctrl_in
, &rfds
);
494 retval
= select(pars
.sockctrl_in
+ 1, &rfds
, NULL
, NULL
, &tv
);
497 sock_geterror("select failed: ", errmsgbuf
, PCAP_ERRBUF_SIZE
);
498 if (rpcap_senderror(pars
.sockctrl_out
,
499 pars
.protocol_version
, PCAP_ERR_NETW
,
500 errmsgbuf
, errbuf
) == -1)
501 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
505 // The timeout has expired
506 // So, this was a fake connection. Drop it down
509 if (rpcap_senderror(pars
.sockctrl_out
,
510 pars
.protocol_version
,
511 PCAP_ERR_INITTIMEOUT
,
512 "The RPCAP initial timeout has expired",
514 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
520 // Read the message header from the client.
522 nrecv
= rpcapd_recv_msg_header(pars
.sockctrl_in
, &header
);
530 // Client closed the connection.
537 // Did the client specify the version we negotiated?
539 // For now, there's only one version.
541 if (header
.ver
!= pars
.protocol_version
)
544 // Tell them it's not the negotiated version.
545 // Send the error message with their version,
546 // so they don't reject it as having the wrong
549 if (rpcap_senderror(pars
.sockctrl_out
,
550 header
.ver
, PCAP_ERR_WRONGVER
,
551 "RPCAP version in message isn't the negotiated version",
554 // That failed; log a message and give up.
555 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
559 // Discard the rest of the message.
560 (void)rpcapd_discard(pars
.sockctrl_in
, plen
);
567 case RPCAP_MSG_ERROR
: // The other endpoint reported an error
569 (void)daemon_msg_err(pars
.sockctrl_in
, plen
);
570 // Do nothing; just exit; the error code is already into the errbuf
571 // XXX - actually exit....
575 case RPCAP_MSG_FINDALLIF_REQ
:
577 if (daemon_msg_findallif_req(&pars
, plen
) == -1)
579 // Fatal error; a message has
580 // been logged, so just give up.
586 case RPCAP_MSG_OPEN_REQ
:
589 // Process the open request, and keep
590 // the source from it, for use later
591 // when the capture is started.
593 // XXX - we don't care if the client sends
594 // us multiple open requests, the last
597 retval
= daemon_msg_open_req(&pars
, plen
, source
, sizeof(source
));
600 // Fatal error; a message has
601 // been logged, so just give up.
608 case RPCAP_MSG_STARTCAP_REQ
:
612 // They never told us what device
614 if (rpcap_senderror(pars
.sockctrl_out
,
615 pars
.protocol_version
,
616 PCAP_ERR_STARTCAPTURE
,
617 "No capture device was specified",
620 // Fatal error; log an
621 // error and give up.
622 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
625 if (rpcapd_discard(pars
.sockctrl_in
, plen
) == -1)
632 if (daemon_msg_startcap_req(&pars
, plen
, &threaddata
, source
, &session
, &samp_param
) == -1)
634 // Fatal error; a message has
635 // been logged, so just give up.
641 case RPCAP_MSG_UPDATEFILTER_REQ
:
645 if (daemon_msg_updatefilter_req(&pars
, session
, plen
) == -1)
647 // Fatal error; a message has
648 // been logged, so just give up.
654 if (rpcap_senderror(pars
.sockctrl_out
,
655 pars
.protocol_version
,
656 PCAP_ERR_UPDATEFILTER
,
657 "Device not opened. Cannot update filter",
660 // That failed; log a message and give up.
661 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
668 case RPCAP_MSG_CLOSE
: // The other endpoint close the pcap session
671 // Indicate to our caller that the client
672 // closed the control connection.
673 // This is used only in case of active mode.
675 client_told_us_to_close
= 1;
676 SOCK_DEBUG_MESSAGE("The other end system asked to close the connection.");
680 case RPCAP_MSG_STATS_REQ
:
682 if (daemon_msg_stats_req(&pars
, session
, plen
, &stats
, svrcapt
) == -1)
684 // Fatal error; a message has
685 // been logged, so just give up.
691 case RPCAP_MSG_ENDCAP_REQ
: // The other endpoint close the current capture session
695 // Save statistics (we can need them in the future)
696 if (pcap_stats(session
->fp
, &stats
))
698 svrcapt
= session
->TotCapt
;
708 if (daemon_msg_endcap_req(&pars
, session
, &threaddata
) == -1)
712 // Fatal error; a message has
713 // been logged, so just give up.
721 rpcap_senderror(pars
.sockctrl_out
,
722 pars
.protocol_version
,
724 "Device not opened. Cannot close the capture",
730 case RPCAP_MSG_SETSAMPLING_REQ
:
732 if (daemon_msg_setsampling_req(&pars
, plen
, &samp_param
) == -1)
734 // Fatal error; a message has
735 // been logged, so just give up.
741 case RPCAP_MSG_AUTH_REQ
:
744 // We're already authenticated; you don't
745 // get to reauthenticate.
747 rpcapd_log(LOGPRIO_INFO
, "The client sent an RPCAP_MSG_AUTH_REQ message after authentication was completed");
748 if (rpcap_senderror(pars
.sockctrl_out
,
749 pars
.protocol_version
,
751 "RPCAP_MSG_AUTH_REQ request sent after authentication was completed",
754 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
757 // Discard the rest of the message.
758 if (rpcapd_discard(pars
.sockctrl_in
, plen
) == -1)
765 case RPCAP_MSG_PACKET
:
766 case RPCAP_MSG_FINDALLIF_REPLY
:
767 case RPCAP_MSG_OPEN_REPLY
:
768 case RPCAP_MSG_STARTCAP_REPLY
:
769 case RPCAP_MSG_UPDATEFILTER_REPLY
:
770 case RPCAP_MSG_AUTH_REPLY
:
771 case RPCAP_MSG_STATS_REPLY
:
772 case RPCAP_MSG_ENDCAP_REPLY
:
773 case RPCAP_MSG_SETSAMPLING_REPLY
:
775 // These are server-to-client messages.
777 msg_type_string
= rpcap_msg_type_string(header
.type
);
778 if (msg_type_string
!= NULL
)
780 rpcapd_log(LOGPRIO_INFO
, "The client sent a %s server-to-client message", msg_type_string
);
781 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Server-to-client message %s received from client", msg_type_string
);
785 rpcapd_log(LOGPRIO_INFO
, "The client sent a server-to-client message of type %u", header
.type
);
786 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Server-to-client message of type %u received from client", header
.type
);
788 if (rpcap_senderror(pars
.sockctrl_out
,
789 pars
.protocol_version
, PCAP_ERR_WRONGMSG
,
790 errmsgbuf
, errbuf
) == -1)
792 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
795 // Discard the rest of the message.
796 if (rpcapd_discard(pars
.sockctrl_in
, plen
) == -1)
805 // Unknown message type.
807 rpcapd_log(LOGPRIO_INFO
, "The client sent a message of type %u", header
.type
);
808 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Unknown message type %u", header
.type
);
809 if (rpcap_senderror(pars
.sockctrl_out
,
810 pars
.protocol_version
, PCAP_ERR_WRONGMSG
,
811 errbuf
, errmsgbuf
) == -1)
813 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
816 // Discard the rest of the message.
817 if (rpcapd_discard(pars
.sockctrl_in
, plen
) == -1)
828 // The child thread is about to end
830 // perform pcap_t cleanup, in case it has not been done
833 if (threaddata
.have_thread
)
837 // Tell the data connection thread main capture
838 // loop to break out of that loop.
840 pcap_breakloop(session
->fp
);
843 // If it's currently blocked waiting for packets
844 // to arrive, try to wake it up, so it can see
845 // the "break out of the loop" indication.
847 SetEvent(pcap_getevent(session
->fp
));
850 // Wait for the thread to exit, so we don't close
851 // sockets out from under it.
853 // XXX - have a timeout, so we don't wait forever?
855 WaitForSingleObject(threaddata
.thread
, INFINITE
);
858 // Release the thread handle, as we're done with
861 CloseHandle(threaddata
.thread
);
863 pthread_cancel(threaddata
.thread
);
865 threaddata
.have_thread
= 0;
867 if (session
->sockdata
)
869 sock_close(session
->sockdata
, NULL
, 0);
870 session
->sockdata
= 0;
872 pcap_close(session
->fp
);
877 // Print message and return
878 SOCK_DEBUG_MESSAGE("I'm exiting from the child loop");
879 SOCK_DEBUG_MESSAGE(errbuf
);
881 return client_told_us_to_close
;
885 * This handles the RPCAP_MSG_ERR message.
888 daemon_msg_err(SOCKET sockctrl_in
, uint32 plen
)
890 char errbuf
[PCAP_ERRBUF_SIZE
];
891 char remote_errbuf
[PCAP_ERRBUF_SIZE
];
893 if (plen
>= PCAP_ERRBUF_SIZE
)
896 * Message is too long; just read as much of it as we
897 * can into the buffer provided, and discard the rest.
899 if (sock_recv(sockctrl_in
, remote_errbuf
, PCAP_ERRBUF_SIZE
- 1,
900 SOCK_RECEIVEALL_YES
|SOCK_EOF_IS_ERROR
, errbuf
,
901 PCAP_ERRBUF_SIZE
) == -1)
904 rpcapd_log(LOGPRIO_ERROR
, "Read from client failed: %s", errbuf
);
907 if (rpcapd_discard(sockctrl_in
, plen
- (PCAP_ERRBUF_SIZE
- 1)) == -1)
916 remote_errbuf
[PCAP_ERRBUF_SIZE
- 1] = '\0';
920 /* Empty error string. */
921 remote_errbuf
[0] = '\0';
925 if (sock_recv(sockctrl_in
, remote_errbuf
, plen
,
926 SOCK_RECEIVEALL_YES
|SOCK_EOF_IS_ERROR
, errbuf
,
927 PCAP_ERRBUF_SIZE
) == -1)
930 rpcapd_log(LOGPRIO_ERROR
, "Read from client failed: %s", errbuf
);
937 remote_errbuf
[plen
] = '\0';
940 rpcapd_log(LOGPRIO_ERROR
, "Error from client: %s", remote_errbuf
);
945 * This handles the RPCAP_MSG_AUTH_REQ message.
946 * It checks if the authentication credentials supplied by the user are valid.
948 * This function is called if the daemon receives a RPCAP_MSG_AUTH_REQ
949 * message in its authentication loop. It reads the body of the
950 * authentication message from the network and checks whether the
951 * credentials are valid.
953 * \param sockctrl: the socket for the control connection.
955 * \param nullAuthAllowed: '1' if the NULL authentication is allowed.
957 * \param errbuf: a user-allocated buffer in which the error message
958 * (if one) has to be written. It must be at least PCAP_ERRBUF_SIZE
961 * \return '0' if everything is fine, '-1' if an unrecoverable error occurred,
962 * or '-2' if the authentication failed. For errors, an error message is
963 * returned in the 'errbuf' variable; this gives a message for the
964 * unrecoverable error or for the authentication failure.
967 daemon_msg_auth_req(struct daemon_slpars
*pars
, uint32 plen
)
969 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
970 char errmsgbuf
[PCAP_ERRBUF_SIZE
]; // buffer for errors to send to the client
971 struct rpcap_header header
; // RPCAP message general header
973 struct rpcap_auth auth
; // RPCAP authentication header
975 status
= rpcapd_recv(pars
->sockctrl_in
, (char *) &auth
, sizeof(struct rpcap_auth
), &plen
, errmsgbuf
);
985 switch (ntohs(auth
.type
))
987 case RPCAP_RMTAUTH_NULL
:
989 if (!pars
->nullAuthAllowed
)
991 // Send the client an error reply.
992 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Authentication failed; NULL authentication not permitted.");
998 case RPCAP_RMTAUTH_PWD
:
1000 char *username
, *passwd
;
1001 uint32 usernamelen
, passwdlen
;
1003 usernamelen
= ntohs(auth
.slen1
);
1004 username
= (char *) malloc (usernamelen
+ 1);
1005 if (username
== NULL
)
1007 pcap_fmt_errmsg_for_errno(errmsgbuf
,
1008 PCAP_ERRBUF_SIZE
, errno
, "malloc() failed");
1011 status
= rpcapd_recv(pars
->sockctrl_in
, username
, usernamelen
, &plen
, errmsgbuf
);
1022 username
[usernamelen
] = '\0';
1024 passwdlen
= ntohs(auth
.slen2
);
1025 passwd
= (char *) malloc (passwdlen
+ 1);
1028 pcap_fmt_errmsg_for_errno(errmsgbuf
,
1029 PCAP_ERRBUF_SIZE
, errno
, "malloc() failed");
1033 status
= rpcapd_recv(pars
->sockctrl_in
, passwd
, passwdlen
, &plen
, errmsgbuf
);
1046 passwd
[passwdlen
] = '\0';
1048 if (daemon_AuthUserPwd(username
, passwd
, errmsgbuf
))
1051 // Authentication failed. Let the client
1056 if (rpcap_senderror(pars
->sockctrl_out
,
1057 pars
->protocol_version
,
1058 PCAP_ERR_AUTH
, errmsgbuf
, errbuf
) == -1)
1060 // That failed; log a message and give up.
1061 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1066 // Suspend for 1 second, so that they can't
1067 // hammer us with repeated tries with an
1068 // attack such as a dictionary attack.
1070 // WARNING: this delay is inserted only
1071 // at this point; if the client closes the
1072 // connection and reconnects, the suspension
1073 // time does not have any effect.
1075 sleep_secs(RPCAP_SUSPEND_WRONGAUTH
);
1085 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Authentication type not recognized.");
1089 // The authentication succeeded; let the client know.
1090 rpcap_createhdr(&header
, pars
->protocol_version
, RPCAP_MSG_AUTH_REPLY
, 0, 0);
1092 // Send the ok message back
1093 if (sock_send(pars
->sockctrl_out
, (char *) &header
, sizeof (struct rpcap_header
), errbuf
, PCAP_ERRBUF_SIZE
) == -1)
1095 // That failed; log a messsage and give up.
1096 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1100 // Check if all the data has been read; if not, discard the data in excess
1101 if (rpcapd_discard(pars
->sockctrl_in
, plen
) == -1)
1109 if (rpcap_senderror(pars
->sockctrl_out
, pars
->protocol_version
,
1110 PCAP_ERR_AUTH
, errmsgbuf
, errbuf
) == -1)
1112 // That failed; log a message and give up.
1113 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1118 // Check if all the data has been read; if not, discard the data in excess
1119 if (rpcapd_discard(pars
->sockctrl_in
, plen
) == -1)
1128 daemon_AuthUserPwd(char *username
, char *password
, char *errbuf
)
1132 * Warning: the user which launches the process must have the
1133 * SE_TCB_NAME right.
1134 * This corresponds to have the "Act as part of the Operating System"
1135 * turned on (administrative tools, local security settings, local
1136 * policies, user right assignment)
1137 * However, it seems to me that if you run it as a service, this
1138 * right should be provided by default.
1141 if (LogonUser(username
, ".", password
, LOGON32_LOGON_NETWORK
, LOGON32_PROVIDER_DEFAULT
, &Token
) == 0)
1145 error
= GetLastError();
1146 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, error
, 0, errbuf
,
1147 PCAP_ERRBUF_SIZE
, NULL
);
1152 // This call should change the current thread to the selected user.
1153 // I didn't test it.
1154 if (ImpersonateLoggedOnUser(Token
) == 0)
1158 error
= GetLastError();
1159 FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM
, NULL
, error
, 0, errbuf
,
1160 PCAP_ERRBUF_SIZE
, NULL
);
1173 * http://www.unixpapa.com/incnote/passwd.html
1175 * We use the Solaris/Linux shadow password authentication if
1176 * we have getspnam(), otherwise we just do traditional
1177 * authentication, which, on some platforms, might work, even
1178 * with shadow passwords, if we're running as root. Traditional
1179 * authenticaion won't work if we're not running as root, as
1180 * I think these days all UN*Xes either won't return the password
1181 * at all with getpwnam() or will only do so if you're root.
1183 * XXX - perhaps what we *should* be using is PAM, if we have
1184 * it. That might hide all the details of username/password
1185 * authentication, whether it's done with a visible-to-root-
1186 * only password database or some other authentication mechanism,
1189 struct passwd
*user
;
1190 char *user_password
;
1191 #ifdef HAVE_GETSPNAM
1192 struct spwd
*usersp
;
1195 // This call is needed to get the uid
1196 if ((user
= getpwnam(username
)) == NULL
)
1198 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Authentication failed: no such user");
1202 #ifdef HAVE_GETSPNAM
1203 // This call is needed to get the password; otherwise 'x' is returned
1204 if ((usersp
= getspnam(username
)) == NULL
)
1206 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Authentication failed: no such user");
1209 user_password
= usersp
->sp_pwdp
;
1212 * XXX - what about other platforms?
1213 * The unixpapa.com page claims this Just Works on *BSD if you're
1214 * running as root - it's from 2000, so it doesn't indicate whether
1215 * macOS (which didn't come out until 2001, under the name Mac OS
1216 * X) behaves like the *BSDs or not, and might also work on AIX.
1217 * HP-UX does something else.
1219 * Again, hopefully PAM hides all that.
1221 user_password
= user
->pw_passwd
;
1224 if (strcmp(user_password
, (char *) crypt(password
, user_password
)) != 0)
1226 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Authentication failed: password incorrect");
1230 if (setuid(user
->pw_uid
))
1232 pcap_fmt_errmsg_for_errno(errbuf
, PCAP_ERRBUF_SIZE
,
1237 /* if (setgid(user->pw_gid))
1239 pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1251 daemon_msg_findallif_req(struct daemon_slpars
*pars
, uint32 plen
)
1253 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
1254 char errmsgbuf
[PCAP_ERRBUF_SIZE
]; // buffer for errors to send to the client
1255 char sendbuf
[RPCAP_NETBUF_SIZE
]; // temporary buffer in which data to be sent is buffered
1256 int sendbufidx
= 0; // index which keeps the number of bytes currently buffered
1257 pcap_if_t
*alldevs
= NULL
; // pointer to the header of the interface chain
1258 pcap_if_t
*d
; // temp pointer needed to scan the interface chain
1259 struct pcap_addr
*address
; // pcap structure that keeps a network address of an interface
1260 struct rpcap_findalldevs_if
*findalldevs_if
;// rpcap structure that packet all the data of an interface together
1261 uint16 nif
= 0; // counts the number of interface listed
1263 // Discard the rest of the message; there shouldn't be any payload.
1264 if (rpcapd_discard(pars
->sockctrl_in
, plen
) == -1)
1270 // Retrieve the device list
1271 if (pcap_findalldevs(&alldevs
, errmsgbuf
) == -1)
1274 if (alldevs
== NULL
)
1276 if (rpcap_senderror(pars
->sockctrl_out
, pars
->protocol_version
,
1277 PCAP_ERR_NOREMOTEIF
,
1278 "No interfaces found! Make sure libpcap/WinPcap is properly installed"
1279 " and you have the right to access to the remote device.",
1282 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1288 // checks the number of interfaces and it computes the total length of the payload
1289 for (d
= alldevs
; d
!= NULL
; d
= d
->next
)
1294 plen
+= strlen(d
->description
);
1296 plen
+= strlen(d
->name
);
1298 plen
+= sizeof(struct rpcap_findalldevs_if
);
1300 for (address
= d
->addresses
; address
!= NULL
; address
= address
->next
)
1303 * Send only IPv4 and IPv6 addresses over the wire.
1305 switch (address
->addr
->sa_family
)
1311 plen
+= (sizeof(struct rpcap_sockaddr
) * 4);
1320 // RPCAP findalldevs command
1321 if (sock_bufferize(NULL
, sizeof(struct rpcap_header
), NULL
,
1322 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
,
1323 PCAP_ERRBUF_SIZE
) == -1)
1326 rpcap_createhdr((struct rpcap_header
*) sendbuf
, pars
->protocol_version
,
1327 RPCAP_MSG_FINDALLIF_REPLY
, nif
, plen
);
1329 // send the interface list
1330 for (d
= alldevs
; d
!= NULL
; d
= d
->next
)
1332 uint16 lname
, ldescr
;
1334 findalldevs_if
= (struct rpcap_findalldevs_if
*) &sendbuf
[sendbufidx
];
1336 if (sock_bufferize(NULL
, sizeof(struct rpcap_findalldevs_if
), NULL
,
1337 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1340 memset(findalldevs_if
, 0, sizeof(struct rpcap_findalldevs_if
));
1342 if (d
->description
) ldescr
= (short) strlen(d
->description
);
1344 if (d
->name
) lname
= (short) strlen(d
->name
);
1347 findalldevs_if
->desclen
= htons(ldescr
);
1348 findalldevs_if
->namelen
= htons(lname
);
1349 findalldevs_if
->flags
= htonl(d
->flags
);
1351 for (address
= d
->addresses
; address
!= NULL
; address
= address
->next
)
1354 * Send only IPv4 and IPv6 addresses over the wire.
1356 switch (address
->addr
->sa_family
)
1362 findalldevs_if
->naddr
++;
1369 findalldevs_if
->naddr
= htons(findalldevs_if
->naddr
);
1371 if (sock_bufferize(d
->name
, lname
, sendbuf
, &sendbufidx
,
1372 RPCAP_NETBUF_SIZE
, SOCKBUF_BUFFERIZE
, errmsgbuf
,
1373 PCAP_ERRBUF_SIZE
) == -1)
1376 if (sock_bufferize(d
->description
, ldescr
, sendbuf
, &sendbufidx
,
1377 RPCAP_NETBUF_SIZE
, SOCKBUF_BUFFERIZE
, errmsgbuf
,
1378 PCAP_ERRBUF_SIZE
) == -1)
1381 // send all addresses
1382 for (address
= d
->addresses
; address
!= NULL
; address
= address
->next
)
1384 struct rpcap_sockaddr
*sockaddr
;
1387 * Send only IPv4 and IPv6 addresses over the wire.
1389 switch (address
->addr
->sa_family
)
1395 sockaddr
= (struct rpcap_sockaddr
*) &sendbuf
[sendbufidx
];
1396 if (sock_bufferize(NULL
, sizeof(struct rpcap_sockaddr
), NULL
,
1397 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1399 daemon_seraddr((struct sockaddr_storage
*) address
->addr
, sockaddr
);
1401 sockaddr
= (struct rpcap_sockaddr
*) &sendbuf
[sendbufidx
];
1402 if (sock_bufferize(NULL
, sizeof(struct rpcap_sockaddr
), NULL
,
1403 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1405 daemon_seraddr((struct sockaddr_storage
*) address
->netmask
, sockaddr
);
1407 sockaddr
= (struct rpcap_sockaddr
*) &sendbuf
[sendbufidx
];
1408 if (sock_bufferize(NULL
, sizeof(struct rpcap_sockaddr
), NULL
,
1409 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1411 daemon_seraddr((struct sockaddr_storage
*) address
->broadaddr
, sockaddr
);
1413 sockaddr
= (struct rpcap_sockaddr
*) &sendbuf
[sendbufidx
];
1414 if (sock_bufferize(NULL
, sizeof(struct rpcap_sockaddr
), NULL
,
1415 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1417 daemon_seraddr((struct sockaddr_storage
*) address
->dstaddr
, sockaddr
);
1426 // We no longer need the device list. Free it.
1427 pcap_freealldevs(alldevs
);
1429 // Send a final command that says "now send it!"
1430 if (sock_send(pars
->sockctrl_out
, sendbuf
, sendbufidx
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
1432 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1440 pcap_freealldevs(alldevs
);
1442 if (rpcap_senderror(pars
->sockctrl_out
, pars
->protocol_version
,
1443 PCAP_ERR_FINDALLIF
, errmsgbuf
, errbuf
) == -1)
1445 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1452 \param plen: the length of the current message (needed in order to be able
1453 to discard excess data in the message, if present)
1456 daemon_msg_open_req(struct daemon_slpars
*pars
, uint32 plen
, char *source
, size_t sourcelen
)
1458 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
1459 char errmsgbuf
[PCAP_ERRBUF_SIZE
]; // buffer for errors to send to the client
1460 pcap_t
*fp
; // pcap_t main variable
1462 char sendbuf
[RPCAP_NETBUF_SIZE
]; // temporary buffer in which data to be sent is buffered
1463 int sendbufidx
= 0; // index which keeps the number of bytes currently buffered
1464 struct rpcap_openreply
*openreply
; // open reply message
1466 if (plen
> sourcelen
- 1)
1468 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Source string too long");
1472 nread
= sock_recv(pars
->sockctrl_in
, source
, plen
,
1473 SOCK_RECEIVEALL_YES
|SOCK_EOF_IS_ERROR
, errbuf
, PCAP_ERRBUF_SIZE
);
1476 rpcapd_log(LOGPRIO_ERROR
, "Read from client failed: %s", errbuf
);
1479 source
[nread
] = '\0';
1482 // XXX - make sure it's *not* a URL; we don't support opening
1483 // remote devices here.
1485 // Open the selected device
1486 // This is a fake open, since we do that only to get the needed parameters, then we close the device again
1487 if ((fp
= pcap_open_live(source
,
1488 1500 /* fake snaplen */,
1490 1000 /* fake timeout */,
1491 errmsgbuf
)) == NULL
)
1494 // Now, I can send a RPCAP open reply message
1495 if (sock_bufferize(NULL
, sizeof(struct rpcap_header
), NULL
, &sendbufidx
,
1496 RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1499 rpcap_createhdr((struct rpcap_header
*) sendbuf
, pars
->protocol_version
,
1500 RPCAP_MSG_OPEN_REPLY
, 0, sizeof(struct rpcap_openreply
));
1502 openreply
= (struct rpcap_openreply
*) &sendbuf
[sendbufidx
];
1504 if (sock_bufferize(NULL
, sizeof(struct rpcap_openreply
), NULL
, &sendbufidx
,
1505 RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1508 memset(openreply
, 0, sizeof(struct rpcap_openreply
));
1509 openreply
->linktype
= htonl(pcap_datalink(fp
));
1511 // We're done with the pcap_t.
1515 if (sock_send(pars
->sockctrl_out
, sendbuf
, sendbufidx
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
1517 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1523 if (rpcap_senderror(pars
->sockctrl_out
, pars
->protocol_version
,
1524 PCAP_ERR_OPEN
, errmsgbuf
, errbuf
) == -1)
1526 // That failed; log a message and give up.
1527 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1531 // Check if all the data has been read; if not, discard the data in excess
1532 if (rpcapd_discard(pars
->sockctrl_in
, plen
) == -1)
1540 \param plen: the length of the current message (needed in order to be able
1541 to discard excess data in the message, if present)
1544 daemon_msg_startcap_req(struct daemon_slpars
*pars
, uint32 plen
, struct thread_handle
*threaddata
, char *source
, struct session
**sessionp
, struct rpcap_sampling
*samp_param _U_
)
1546 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
1547 char errmsgbuf
[PCAP_ERRBUF_SIZE
]; // buffer for errors to send to the client
1548 char portdata
[PCAP_BUF_SIZE
]; // temp variable needed to derive the data port
1549 char peerhost
[PCAP_BUF_SIZE
]; // temp variable needed to derive the host name of our peer
1550 struct session
*session
= NULL
; // saves state of session
1552 char sendbuf
[RPCAP_NETBUF_SIZE
]; // temporary buffer in which data to be sent is buffered
1553 int sendbufidx
= 0; // index which keeps the number of bytes currently buffered
1555 // socket-related variables
1556 SOCKET sockdata
= INVALID_SOCKET
; // socket descriptor of the data connection
1557 struct addrinfo hints
; // temp, needed to open a socket connection
1558 struct addrinfo
*addrinfo
; // temp, needed to open a socket connection
1559 struct sockaddr_storage saddr
; // temp, needed to retrieve the network data port chosen on the local machine
1560 socklen_t saddrlen
; // temp, needed to retrieve the network data port chosen on the local machine
1561 int ret
; // return value from functions
1564 pthread_attr_t detachedAttribute
; // temp, needed to set the created thread as detached
1567 // RPCAP-related variables
1568 struct rpcap_startcapreq startcapreq
; // start capture request message
1569 struct rpcap_startcapreply
*startcapreply
; // start capture reply message
1570 int serveropen_dp
; // keeps who is going to open the data connection
1574 status
= rpcapd_recv(pars
->sockctrl_in
, (char *) &startcapreq
,
1575 sizeof(struct rpcap_startcapreq
), &plen
, errmsgbuf
);
1585 startcapreq
.flags
= ntohs(startcapreq
.flags
);
1587 // Create a session structure
1588 session
= malloc(sizeof(struct session
));
1589 if (session
== NULL
)
1591 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Can't allocate session structure");
1595 // Open the selected device
1596 if ((session
->fp
= pcap_open_live(source
,
1597 ntohl(startcapreq
.snaplen
),
1598 (startcapreq
.flags
& RPCAP_STARTCAPREQ_FLAG_PROMISC
) ? 1 : 0 /* local device, other flags not needed */,
1599 ntohl(startcapreq
.read_timeout
),
1600 errmsgbuf
)) == NULL
)
1604 // Apply sampling parameters
1605 fp
->rmt_samp
.method
= samp_param
->method
;
1606 fp
->rmt_samp
.value
= samp_param
->value
;
1610 We're in active mode if:
1611 - we're using TCP, and the user wants us to be in active mode
1614 serveropen_dp
= (startcapreq
.flags
& RPCAP_STARTCAPREQ_FLAG_SERVEROPEN
) || (startcapreq
.flags
& RPCAP_STARTCAPREQ_FLAG_DGRAM
) || pars
->isactive
;
1617 Gets the sockaddr structure referred to the other peer in the ctrl connection
1619 We need that because:
1620 - if we're in passive mode, we need to know the address family we want to use
1621 (the same used for the ctrl socket)
1622 - if we're in active mode, we need to know the network address of the other host
1623 we want to connect to
1625 saddrlen
= sizeof(struct sockaddr_storage
);
1626 if (getpeername(pars
->sockctrl_in
, (struct sockaddr
*) &saddr
, &saddrlen
) == -1)
1628 sock_geterror("getpeername(): ", errmsgbuf
, PCAP_ERRBUF_SIZE
);
1632 memset(&hints
, 0, sizeof(struct addrinfo
));
1633 hints
.ai_socktype
= (startcapreq
.flags
& RPCAP_STARTCAPREQ_FLAG_DGRAM
) ? SOCK_DGRAM
: SOCK_STREAM
;
1634 hints
.ai_family
= saddr
.ss_family
;
1636 // Now we have to create a new socket to send packets
1637 if (serveropen_dp
) // Data connection is opened by the server toward the client
1639 pcap_snprintf(portdata
, sizeof portdata
, "%d", ntohs(startcapreq
.portdata
));
1641 // Get the name of the other peer (needed to connect to that specific network address)
1642 if (getnameinfo((struct sockaddr
*) &saddr
, saddrlen
, peerhost
,
1643 sizeof(peerhost
), NULL
, 0, NI_NUMERICHOST
))
1645 sock_geterror("getnameinfo(): ", errmsgbuf
, PCAP_ERRBUF_SIZE
);
1649 if (sock_initaddress(peerhost
, portdata
, &hints
, &addrinfo
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1652 if ((sockdata
= sock_open(addrinfo
, SOCKOPEN_CLIENT
, 0, errmsgbuf
, PCAP_ERRBUF_SIZE
)) == INVALID_SOCKET
)
1655 else // Data connection is opened by the client toward the server
1657 hints
.ai_flags
= AI_PASSIVE
;
1659 // Let's the server socket pick up a free network port for us
1660 if (sock_initaddress(NULL
, "0", &hints
, &addrinfo
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1663 if ((sockdata
= sock_open(addrinfo
, SOCKOPEN_SERVER
, 1 /* max 1 connection in queue */, errmsgbuf
, PCAP_ERRBUF_SIZE
)) == INVALID_SOCKET
)
1666 // get the complete sockaddr structure used in the data connection
1667 saddrlen
= sizeof(struct sockaddr_storage
);
1668 if (getsockname(sockdata
, (struct sockaddr
*) &saddr
, &saddrlen
) == -1)
1670 sock_geterror("getsockname(): ", errmsgbuf
, PCAP_ERRBUF_SIZE
);
1674 // Get the local port the system picked up
1675 if (getnameinfo((struct sockaddr
*) &saddr
, saddrlen
, NULL
,
1676 0, portdata
, sizeof(portdata
), NI_NUMERICSERV
))
1678 sock_geterror("getnameinfo(): ", errmsgbuf
, PCAP_ERRBUF_SIZE
);
1683 // addrinfo is no longer used
1684 freeaddrinfo(addrinfo
);
1687 // Needed to send an error on the ctrl connection
1688 session
->sockctrl_out
= pars
->sockctrl_out
;
1689 session
->protocol_version
= pars
->protocol_version
;
1691 // Now I can set the filter
1692 ret
= daemon_unpackapplyfilter(pars
->sockctrl_in
, session
, &plen
, errmsgbuf
);
1695 // Fatal error. A message has been logged; just give up.
1700 // Non-fatal error. Send an error message to the client.
1704 // Now, I can send a RPCAP start capture reply message
1705 if (sock_bufferize(NULL
, sizeof(struct rpcap_header
), NULL
, &sendbufidx
,
1706 RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1709 rpcap_createhdr((struct rpcap_header
*) sendbuf
, pars
->protocol_version
,
1710 RPCAP_MSG_STARTCAP_REPLY
, 0, sizeof(struct rpcap_startcapreply
));
1712 startcapreply
= (struct rpcap_startcapreply
*) &sendbuf
[sendbufidx
];
1714 if (sock_bufferize(NULL
, sizeof(struct rpcap_startcapreply
), NULL
,
1715 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
1718 memset(startcapreply
, 0, sizeof(struct rpcap_startcapreply
));
1719 startcapreply
->bufsize
= htonl(pcap_bufsize(session
->fp
));
1723 unsigned short port
= (unsigned short)strtoul(portdata
,NULL
,10);
1724 startcapreply
->portdata
= htons(port
);
1727 if (sock_send(pars
->sockctrl_out
, sendbuf
, sendbufidx
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
1729 // That failed; log a message and give up.
1730 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1736 SOCKET socktemp
; // We need another socket, since we're going to accept() a connection
1738 // Connection creation
1739 saddrlen
= sizeof(struct sockaddr_storage
);
1741 socktemp
= accept(sockdata
, (struct sockaddr
*) &saddr
, &saddrlen
);
1743 if (socktemp
== INVALID_SOCKET
)
1745 sock_geterror("accept(): ", errbuf
, PCAP_ERRBUF_SIZE
);
1746 rpcapd_log(LOGPRIO_ERROR
, "Accept of data connection failed: %s",
1751 // Now that I accepted the connection, the server socket is no longer needed
1752 sock_close(sockdata
, NULL
, 0);
1753 sockdata
= socktemp
;
1756 session
->sockdata
= sockdata
;
1758 // Now we have to create a new thread to receive packets
1760 threaddata
->thread
= (HANDLE
)_beginthreadex(NULL
, 0, daemon_thrdatamain
,
1761 (void *) session
, 0, NULL
);
1762 if (threaddata
->thread
== 0)
1764 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Error creating the data thread");
1768 /* GV we need this to create the thread as detached. */
1769 /* GV otherwise, the thread handle is not destroyed */
1770 pthread_attr_init(&detachedAttribute
);
1771 pthread_attr_setdetachstate(&detachedAttribute
, PTHREAD_CREATE_DETACHED
);
1772 ret
= pthread_create(&threaddata
->thread
, &detachedAttribute
,
1773 daemon_thrdatamain
, (void *) session
);
1776 pcap_fmt_errmsg_for_errno(errbuf
, PCAP_ERRBUF_SIZE
,
1777 ret
, "Error creating the data thread");
1778 pthread_attr_destroy(&detachedAttribute
);
1781 pthread_attr_destroy(&detachedAttribute
);
1783 threaddata
->have_thread
= 1;
1785 // Check if all the data has been read; if not, discard the data in excess
1786 if (rpcapd_discard(pars
->sockctrl_in
, plen
) == -1)
1789 *sessionp
= session
;
1794 // Not a fatal error, so send the client an error message and
1795 // keep serving client requests.
1800 freeaddrinfo(addrinfo
);
1802 if (threaddata
->have_thread
)
1807 pcap_breakloop(session
->fp
);
1808 SetEvent(pcap_getevent(session
->fp
));
1810 CloseHandle(threaddata
->thread
);
1812 pthread_cancel(threaddata
->thread
);
1814 threaddata
->have_thread
= 0;
1817 if (sockdata
!= INVALID_SOCKET
)
1818 sock_close(sockdata
, NULL
, 0);
1823 pcap_close(session
->fp
);
1827 if (rpcap_senderror(pars
->sockctrl_out
, pars
->protocol_version
,
1828 PCAP_ERR_STARTCAPTURE
, errmsgbuf
, errbuf
) == -1)
1830 // That failed; log a message and give up.
1831 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1835 // Check if all the data has been read; if not, discard the data in excess
1836 if (rpcapd_discard(pars
->sockctrl_in
, plen
) == -1)
1846 // Fatal network error, so don't try to communicate with
1847 // the client, just give up.
1851 if (threaddata
->have_thread
)
1854 if (session
&& session
->fp
)
1857 // Tell the data connection thread main capture
1858 // loop to break out of that loop.
1860 pcap_breakloop(session
->fp
);
1863 // If it's currently blocked waiting for packets
1864 // to arrive, try to wake it up, so it can see
1865 // the "break out of the loop" indication.
1867 SetEvent(pcap_getevent(session
->fp
));
1871 // Wait for the thread to exit, so we don't close
1872 // sockets out from under it.
1874 // XXX - have a timeout, so we don't wait forever?
1876 WaitForSingleObject(threaddata
->thread
, INFINITE
);
1879 // Release the thread handle, as we're done with
1882 CloseHandle(threaddata
->thread
);
1884 pthread_cancel(threaddata
->thread
);
1886 threaddata
->have_thread
= 0;
1889 if (sockdata
!= INVALID_SOCKET
)
1890 sock_close(sockdata
, NULL
, 0);
1895 pcap_close(session
->fp
);
1903 daemon_msg_endcap_req(struct daemon_slpars
*pars
, struct session
*session
, struct thread_handle
*threaddata
)
1905 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
1906 struct rpcap_header header
;
1908 if (threaddata
->have_thread
)
1912 // Tell the data connection thread main capture loop to
1913 // break out of that loop.
1915 pcap_breakloop(session
->fp
);
1918 // If it's currently blocked waiting for packets to
1919 // arrive, try to wake it up, so it can see the "break
1920 // out of the loop" indication.
1922 SetEvent(pcap_getevent(session
->fp
));
1925 // Wait for the thread to exit, so we don't close
1926 // sockets out from under it.
1928 // XXX - have a timeout, so we don't wait forever?
1930 WaitForSingleObject(threaddata
->thread
, INFINITE
);
1933 // Release the thread handle, as we're done with
1936 CloseHandle(threaddata
->thread
);
1938 pthread_cancel(threaddata
->thread
);
1940 threaddata
->have_thread
= 0;
1942 if (session
->sockdata
)
1944 sock_close(session
->sockdata
, NULL
, 0);
1945 session
->sockdata
= 0;
1948 pcap_close(session
->fp
);
1950 rpcap_createhdr(&header
, pars
->protocol_version
,
1951 RPCAP_MSG_ENDCAP_REPLY
, 0, 0);
1953 if (sock_send(pars
->sockctrl_out
, (char *) &header
, sizeof(struct rpcap_header
), errbuf
, PCAP_ERRBUF_SIZE
) == -1)
1955 // That failed; log a message and give up.
1956 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
1964 daemon_unpackapplyfilter(SOCKET sockctrl_in
, struct session
*session
, uint32
*plenp
, char *errmsgbuf
)
1967 struct rpcap_filter filter
;
1968 struct rpcap_filterbpf_insn insn
;
1969 struct bpf_insn
*bf_insn
;
1970 struct bpf_program bf_prog
;
1973 status
= rpcapd_recv(sockctrl_in
, (char *) &filter
,
1974 sizeof(struct rpcap_filter
), plenp
, errmsgbuf
);
1984 bf_prog
.bf_len
= ntohl(filter
.nitems
);
1986 if (ntohs(filter
.filtertype
) != RPCAP_UPDATEFILTER_BPF
)
1988 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Only BPF/NPF filters are currently supported");
1992 bf_insn
= (struct bpf_insn
*) malloc (sizeof(struct bpf_insn
) * bf_prog
.bf_len
);
1993 if (bf_insn
== NULL
)
1995 pcap_fmt_errmsg_for_errno(errmsgbuf
, PCAP_ERRBUF_SIZE
,
1996 errno
, "malloc() failed");
2000 bf_prog
.bf_insns
= bf_insn
;
2002 for (i
= 0; i
< bf_prog
.bf_len
; i
++)
2004 status
= rpcapd_recv(sockctrl_in
, (char *) &insn
,
2005 sizeof(struct rpcap_filterbpf_insn
), plenp
, errmsgbuf
);
2015 bf_insn
->code
= ntohs(insn
.code
);
2016 bf_insn
->jf
= insn
.jf
;
2017 bf_insn
->jt
= insn
.jt
;
2018 bf_insn
->k
= ntohl(insn
.k
);
2024 // XXX - pcap_setfilter() should do the validation for us.
2026 if (bpf_validate(bf_prog
.bf_insns
, bf_prog
.bf_len
) == 0)
2028 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "The filter contains bogus instructions");
2032 if (pcap_setfilter(session
->fp
, &bf_prog
))
2034 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "RPCAP error: %s", pcap_geterr(session
->fp
));
2042 daemon_msg_updatefilter_req(struct daemon_slpars
*pars
, struct session
*session
, uint32 plen
)
2044 char errbuf
[PCAP_ERRBUF_SIZE
];
2045 char errmsgbuf
[PCAP_ERRBUF_SIZE
]; // buffer for errors to send to the client
2046 int ret
; // status of daemon_unpackapplyfilter()
2047 struct rpcap_header header
; // keeps the answer to the updatefilter command
2049 ret
= daemon_unpackapplyfilter(pars
->sockctrl_in
, session
, &plen
, errmsgbuf
);
2052 // Fatal error. A message has been logged; just give up.
2057 // Non-fatal error. Send an error reply to the client.
2061 // Check if all the data has been read; if not, discard the data in excess
2062 if (rpcapd_discard(pars
->sockctrl_in
, plen
) == -1)
2068 // A response is needed, otherwise the other host does not know that everything went well
2069 rpcap_createhdr(&header
, pars
->protocol_version
,
2070 RPCAP_MSG_UPDATEFILTER_REPLY
, 0, 0);
2072 if (sock_send(pars
->sockctrl_out
, (char *) &header
, sizeof (struct rpcap_header
), pcap_geterr(session
->fp
), PCAP_ERRBUF_SIZE
))
2074 // That failed; log a messsage and give up.
2075 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
2082 if (rpcapd_discard(pars
->sockctrl_in
, plen
) == -1)
2086 rpcap_senderror(pars
->sockctrl_out
, pars
->protocol_version
,
2087 PCAP_ERR_UPDATEFILTER
, errmsgbuf
, NULL
);
2093 \brief Received the sampling parameters from remote host and it stores in the pcap_t structure.
2096 daemon_msg_setsampling_req(struct daemon_slpars
*pars
, uint32 plen
, struct rpcap_sampling
*samp_param
)
2098 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
2099 char errmsgbuf
[PCAP_ERRBUF_SIZE
];
2100 struct rpcap_header header
;
2101 struct rpcap_sampling rpcap_samp
;
2104 status
= rpcapd_recv(pars
->sockctrl_in
, (char *) &rpcap_samp
, sizeof(struct rpcap_sampling
), &plen
, errmsgbuf
);
2114 // Save these settings in the pcap_t
2115 samp_param
->method
= rpcap_samp
.method
;
2116 samp_param
->value
= ntohl(rpcap_samp
.value
);
2118 // A response is needed, otherwise the other host does not know that everything went well
2119 rpcap_createhdr(&header
, pars
->protocol_version
,
2120 RPCAP_MSG_SETSAMPLING_REPLY
, 0, 0);
2122 if (sock_send(pars
->sockctrl_out
, (char *) &header
, sizeof (struct rpcap_header
), errbuf
, PCAP_ERRBUF_SIZE
) == -1)
2124 // That failed; log a messsage and give up.
2125 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
2129 if (rpcapd_discard(pars
->sockctrl_in
, plen
) == -1)
2137 if (rpcap_senderror(pars
->sockctrl_out
, pars
->protocol_version
,
2138 PCAP_ERR_AUTH
, errmsgbuf
, errbuf
) == -1)
2140 // That failed; log a message and give up.
2141 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
2145 // Check if all the data has been read; if not, discard the data in excess
2146 if (rpcapd_discard(pars
->sockctrl_in
, plen
) == -1)
2155 daemon_msg_stats_req(struct daemon_slpars
*pars
, struct session
*session
, uint32 plen
, struct pcap_stat
*stats
, unsigned int svrcapt
)
2157 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
2158 char errmsgbuf
[PCAP_ERRBUF_SIZE
]; // buffer for errors to send to the client
2159 char sendbuf
[RPCAP_NETBUF_SIZE
]; // temporary buffer in which data to be sent is buffered
2160 int sendbufidx
= 0; // index which keeps the number of bytes currently buffered
2161 struct rpcap_stats
*netstats
; // statistics sent on the network
2163 // Checks that the header does not contain other data; if so, discard it
2164 if (rpcapd_discard(pars
->sockctrl_in
, plen
) == -1)
2170 if (sock_bufferize(NULL
, sizeof(struct rpcap_header
), NULL
,
2171 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
2174 rpcap_createhdr((struct rpcap_header
*) sendbuf
, pars
->protocol_version
,
2175 RPCAP_MSG_STATS_REPLY
, 0, (uint16
) sizeof(struct rpcap_stats
));
2177 netstats
= (struct rpcap_stats
*) &sendbuf
[sendbufidx
];
2179 if (sock_bufferize(NULL
, sizeof(struct rpcap_stats
), NULL
,
2180 &sendbufidx
, RPCAP_NETBUF_SIZE
, SOCKBUF_CHECKONLY
, errmsgbuf
, PCAP_ERRBUF_SIZE
) == -1)
2183 if (session
&& session
->fp
)
2185 if (pcap_stats(session
->fp
, stats
) == -1)
2187 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "%s", pcap_geterr(session
->fp
));
2191 netstats
->ifdrop
= htonl(stats
->ps_ifdrop
);
2192 netstats
->ifrecv
= htonl(stats
->ps_recv
);
2193 netstats
->krnldrop
= htonl(stats
->ps_drop
);
2194 netstats
->svrcapt
= htonl(session
->TotCapt
);
2198 // We have to keep compatibility with old applications,
2199 // which ask for statistics also when the capture has
2201 netstats
->ifdrop
= htonl(stats
->ps_ifdrop
);
2202 netstats
->ifrecv
= htonl(stats
->ps_recv
);
2203 netstats
->krnldrop
= htonl(stats
->ps_drop
);
2204 netstats
->svrcapt
= htonl(svrcapt
);
2208 if (sock_send(pars
->sockctrl_out
, sendbuf
, sendbufidx
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
2210 rpcapd_log(LOGPRIO_ERROR
, "Send to client failed: %s", errbuf
);
2217 rpcap_senderror(pars
->sockctrl_out
, pars
->protocol_version
,
2218 PCAP_ERR_GETSTATS
, errmsgbuf
, NULL
);
2223 static unsigned __stdcall
2227 daemon_thrdatamain(void *ptr
)
2229 char errbuf
[PCAP_ERRBUF_SIZE
+ 1]; // error buffer
2230 struct session
*session
; // pointer to the struct session for this session
2231 int retval
; // general variable used to keep the return value of other functions
2232 struct rpcap_pkthdr
*net_pkt_header
;// header of the packet
2233 struct pcap_pkthdr
*pkt_header
; // pointer to the buffer that contains the header of the current packet
2234 u_char
*pkt_data
; // pointer to the buffer that contains the current packet
2235 size_t sendbufsize
; // size for the send buffer
2236 char *sendbuf
; // temporary buffer in which data to be sent is buffered
2237 int sendbufidx
; // index which keeps the number of bytes currently buffered
2240 session
= (struct session
*) ptr
;
2242 session
->TotCapt
= 0; // counter which is incremented each time a packet is received
2244 // Initialize errbuf
2245 memset(errbuf
, 0, sizeof(errbuf
));
2248 // We need a buffer large enough to hold a buffer large enough
2249 // for a maximum-size packet for this pcap_t.
2251 if (pcap_snapshot(session
->fp
) < 0)
2254 // The snapshot length is negative.
2255 // This "should not happen".
2257 rpcapd_log(LOGPRIO_ERROR
,
2258 "Unable to allocate the buffer for this child thread: snapshot length of %d is negative",
2259 pcap_snapshot(session
->fp
));
2260 sendbuf
= NULL
; // we can't allocate a buffer, so nothing to free
2264 // size_t is unsigned, and the result of pcap_snapshot() is signed;
2265 // on no platform that we support is int larger than size_t.
2266 // This means that, unless the extra information we prepend to
2267 // a maximum-sized packet is impossibly large, the sum of the
2268 // snapshot length and the size of that extra information will
2271 // So we don't need to make sure that sendbufsize will overflow.
2273 sendbufsize
= sizeof(struct rpcap_header
) + sizeof(struct rpcap_pkthdr
) + pcap_snapshot(session
->fp
);
2274 sendbuf
= (char *) malloc (sendbufsize
);
2275 if (sendbuf
== NULL
)
2277 rpcapd_log(LOGPRIO_ERROR
,
2278 "Unable to allocate the buffer for this child thread");
2283 // Modify thread params so that it can be killed at any time
2284 retval
= pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, NULL
);
2287 pcap_fmt_errmsg_for_errno(errbuf
, PCAP_ERRBUF_SIZE
,
2288 retval
, "pthread_setcancelstate");
2289 rpcapd_log(LOGPRIO_ERROR
,
2290 "Can't set cancel state on data thread: %s", errbuf
);
2293 retval
= pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS
, NULL
);
2296 pcap_fmt_errmsg_for_errno(errbuf
, PCAP_ERRBUF_SIZE
,
2297 retval
, "pthread_setcanceltype");
2298 rpcapd_log(LOGPRIO_ERROR
,
2299 "Can't set cancel type on data thread: %s", errbuf
);
2304 // Retrieve the packets
2305 while ((retval
= pcap_next_ex(session
->fp
, &pkt_header
, (const u_char
**) &pkt_data
)) >= 0) // cast to avoid a compiler warning
2307 if (retval
== 0) // Read timeout elapsed
2312 // Bufferize the general header
2313 if (sock_bufferize(NULL
, sizeof(struct rpcap_header
), NULL
,
2314 &sendbufidx
, sendbufsize
, SOCKBUF_CHECKONLY
, errbuf
,
2315 PCAP_ERRBUF_SIZE
) == -1)
2317 rpcapd_log(LOGPRIO_ERROR
,
2318 "sock_bufferize() error sending packet message: %s",
2323 rpcap_createhdr((struct rpcap_header
*) sendbuf
,
2324 session
->protocol_version
, RPCAP_MSG_PACKET
, 0,
2325 (uint16
) (sizeof(struct rpcap_pkthdr
) + pkt_header
->caplen
));
2327 net_pkt_header
= (struct rpcap_pkthdr
*) &sendbuf
[sendbufidx
];
2329 // Bufferize the pkt header
2330 if (sock_bufferize(NULL
, sizeof(struct rpcap_pkthdr
), NULL
,
2331 &sendbufidx
, sendbufsize
, SOCKBUF_CHECKONLY
, errbuf
,
2332 PCAP_ERRBUF_SIZE
) == -1)
2334 rpcapd_log(LOGPRIO_ERROR
,
2335 "sock_bufferize() error sending packet message: %s",
2340 net_pkt_header
->caplen
= htonl(pkt_header
->caplen
);
2341 net_pkt_header
->len
= htonl(pkt_header
->len
);
2342 net_pkt_header
->npkt
= htonl(++(session
->TotCapt
));
2343 net_pkt_header
->timestamp_sec
= htonl(pkt_header
->ts
.tv_sec
);
2344 net_pkt_header
->timestamp_usec
= htonl(pkt_header
->ts
.tv_usec
);
2346 // Bufferize the pkt data
2347 if (sock_bufferize((char *) pkt_data
, pkt_header
->caplen
,
2348 sendbuf
, &sendbufidx
, sendbufsize
, SOCKBUF_BUFFERIZE
,
2349 errbuf
, PCAP_ERRBUF_SIZE
) == -1)
2351 rpcapd_log(LOGPRIO_ERROR
,
2352 "sock_bufferize() error sending packet message: %s",
2358 // If the client dropped the connection, don't report an
2359 // error, just quit.
2360 status
= sock_send(session
->sockdata
, sendbuf
, sendbufidx
, errbuf
, PCAP_ERRBUF_SIZE
);
2366 // Error other than "client closed the
2367 // connection out from under us"; report
2370 rpcapd_log(LOGPRIO_ERROR
,
2371 "Send of packet to client failed: %s",
2376 // Give up in either case.
2384 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Error reading the packets: %s", pcap_geterr(session
->fp
));
2385 rpcap_senderror(session
->sockctrl_out
, session
->protocol_version
,
2386 PCAP_ERR_READEX
, errbuf
, NULL
);
2391 closesocket(session
->sockdata
);
2392 session
->sockdata
= 0;
2400 \brief It serializes a network address.
2402 It accepts a 'sockaddr_storage' structure as input, and it converts it appropriately into a format
2403 that can be used to be sent on the network. Basically, it applies all the hton()
2404 conversion required to the input variable.
2406 \param sockaddrin a 'sockaddr_storage' pointer to the variable that has to be
2407 serialized. This variable can be both a 'sockaddr_in' and 'sockaddr_in6'.
2409 \param sockaddrout an 'rpcap_sockaddr' pointer to the variable that will contain
2410 the serialized data. This variable has to be allocated by the user.
2412 \warning This function supports only AF_INET and AF_INET6 address families.
2415 daemon_seraddr(struct sockaddr_storage
*sockaddrin
, struct rpcap_sockaddr
*sockaddrout
)
2417 memset(sockaddrout
, 0, sizeof(struct sockaddr_storage
));
2419 // There can be the case in which the sockaddrin is not available
2420 if (sockaddrin
== NULL
) return;
2422 // Warning: we support only AF_INET and AF_INET6
2423 switch (sockaddrin
->ss_family
)
2427 struct sockaddr_in
*sockaddrin_ipv4
;
2428 struct rpcap_sockaddr_in
*sockaddrout_ipv4
;
2430 sockaddrin_ipv4
= (struct sockaddr_in
*) sockaddrin
;
2431 sockaddrout_ipv4
= (struct rpcap_sockaddr_in
*) sockaddrout
;
2432 sockaddrout_ipv4
->family
= htons(RPCAP_AF_INET
);
2433 sockaddrout_ipv4
->port
= htons(sockaddrin_ipv4
->sin_port
);
2434 memcpy(&sockaddrout_ipv4
->addr
, &sockaddrin_ipv4
->sin_addr
, sizeof(sockaddrout_ipv4
->addr
));
2435 memset(sockaddrout_ipv4
->zero
, 0, sizeof(sockaddrout_ipv4
->zero
));
2442 struct sockaddr_in6
*sockaddrin_ipv6
;
2443 struct rpcap_sockaddr_in6
*sockaddrout_ipv6
;
2445 sockaddrin_ipv6
= (struct sockaddr_in6
*) sockaddrin
;
2446 sockaddrout_ipv6
= (struct rpcap_sockaddr_in6
*) sockaddrout
;
2447 sockaddrout_ipv6
->family
= htons(RPCAP_AF_INET6
);
2448 sockaddrout_ipv6
->port
= htons(sockaddrin_ipv6
->sin6_port
);
2449 sockaddrout_ipv6
->flowinfo
= htonl(sockaddrin_ipv6
->sin6_flowinfo
);
2450 memcpy(&sockaddrout_ipv6
->addr
, &sockaddrin_ipv6
->sin6_addr
, sizeof(sockaddrout_ipv6
->addr
));
2451 sockaddrout_ipv6
->scope_id
= htonl(sockaddrin_ipv6
->sin6_scope_id
);
2460 \brief Suspends a thread for secs seconds.
2462 void sleep_secs(int secs
)
2467 unsigned secs_remaining
;
2471 secs_remaining
= secs
;
2472 while (secs_remaining
!= 0)
2473 secs_remaining
= sleep(secs_remaining
);
2478 * Read the header of a message.
2481 rpcapd_recv_msg_header(SOCKET sock
, struct rpcap_header
*headerp
)
2484 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
2486 nread
= sock_recv(sock
, (char *) headerp
, sizeof(struct rpcap_header
),
2487 SOCK_RECEIVEALL_YES
|SOCK_EOF_ISNT_ERROR
, errbuf
, PCAP_ERRBUF_SIZE
);
2491 rpcapd_log(LOGPRIO_ERROR
, "Read from client failed: %s", errbuf
);
2496 // Immediate EOF; that's treated like a close message.
2499 headerp
->plen
= ntohl(headerp
->plen
);
2504 * Read data from a message.
2505 * If we're trying to read more data that remains, puts an error
2506 * message into errmsgbuf and returns -2. Otherwise, tries to read
2507 * the data and, if that succeeds, subtracts the amount read from
2508 * the number of bytes of data that remains.
2509 * Returns 0 on success, logs a message and returns -1 on a network
2513 rpcapd_recv(SOCKET sock
, char *buffer
, size_t toread
, uint32
*plen
, char *errmsgbuf
)
2516 char errbuf
[PCAP_ERRBUF_SIZE
]; // buffer for network errors
2520 // Tell the client and continue.
2521 pcap_snprintf(errmsgbuf
, PCAP_ERRBUF_SIZE
, "Message payload is too short");
2524 nread
= sock_recv(sock
, buffer
, toread
,
2525 SOCK_RECEIVEALL_YES
|SOCK_EOF_IS_ERROR
, errbuf
, PCAP_ERRBUF_SIZE
);
2528 rpcapd_log(LOGPRIO_ERROR
, "Read from client failed: %s", errbuf
);
2536 * Discard data from a connection.
2537 * Mostly used to discard wrong-sized messages.
2538 * Returns 0 on success, logs a message and returns -1 on a network
2542 rpcapd_discard(SOCKET sock
, uint32 len
)
2544 char errbuf
[PCAP_ERRBUF_SIZE
+ 1]; // keeps the error string, prior to be printed
2548 if (sock_discard(sock
, len
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
2551 rpcapd_log(LOGPRIO_ERROR
, "Read from client failed: %s", errbuf
);