xref: /freebsd/contrib/libpcap/rpcapd/daemon.c (revision afdbf109c6a661a729938f68211054a0a50d38ac)
157e22627SCy Schubert /*
257e22627SCy Schubert  * Copyright (c) 2002 - 2003
357e22627SCy Schubert  * NetGroup, Politecnico di Torino (Italy)
457e22627SCy Schubert  * All rights reserved.
557e22627SCy Schubert  *
657e22627SCy Schubert  * Redistribution and use in source and binary forms, with or without
757e22627SCy Schubert  * modification, are permitted provided that the following conditions
857e22627SCy Schubert  * are met:
957e22627SCy Schubert  *
1057e22627SCy Schubert  * 1. Redistributions of source code must retain the above copyright
1157e22627SCy Schubert  * notice, this list of conditions and the following disclaimer.
1257e22627SCy Schubert  * 2. Redistributions in binary form must reproduce the above copyright
1357e22627SCy Schubert  * notice, this list of conditions and the following disclaimer in the
1457e22627SCy Schubert  * documentation and/or other materials provided with the distribution.
1557e22627SCy Schubert  * 3. Neither the name of the Politecnico di Torino nor the names of its
1657e22627SCy Schubert  * contributors may be used to endorse or promote products derived from
1757e22627SCy Schubert  * this software without specific prior written permission.
1857e22627SCy Schubert  *
1957e22627SCy Schubert  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2057e22627SCy Schubert  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2157e22627SCy Schubert  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2257e22627SCy Schubert  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2357e22627SCy Schubert  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2457e22627SCy Schubert  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2557e22627SCy Schubert  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2657e22627SCy Schubert  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2757e22627SCy Schubert  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2857e22627SCy Schubert  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2957e22627SCy Schubert  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3057e22627SCy Schubert  */
3157e22627SCy Schubert 
3257e22627SCy Schubert #include <config.h>
3357e22627SCy Schubert 
3457e22627SCy Schubert #include "ftmacros.h"
3557e22627SCy Schubert #include "varattrs.h"
3657e22627SCy Schubert 
3757e22627SCy Schubert #include <errno.h>		// for the errno variable
3857e22627SCy Schubert #include <stdlib.h>		// for malloc(), free(), ...
3957e22627SCy Schubert #include <string.h>		// for strlen(), ...
406f9cba8fSJoseph Mingrone #include <limits.h>		// for INT_MAX
4157e22627SCy Schubert 
4257e22627SCy Schubert #ifdef _WIN32
4357e22627SCy Schubert   #include <process.h>		// for threads
4457e22627SCy Schubert #else
4557e22627SCy Schubert   #include <unistd.h>
4657e22627SCy Schubert   #include <pthread.h>
4757e22627SCy Schubert   #include <signal.h>
4857e22627SCy Schubert   #include <sys/time.h>
4957e22627SCy Schubert   #include <sys/types.h>	// for select() and such
5057e22627SCy Schubert   #include <pwd.h>		// for password management
5157e22627SCy Schubert #endif
5257e22627SCy Schubert 
5357e22627SCy Schubert #ifdef HAVE_GETSPNAM
5457e22627SCy Schubert #include <shadow.h>		// for password management
5557e22627SCy Schubert #endif
5657e22627SCy Schubert 
5757e22627SCy Schubert #include <pcap.h>		// for libpcap/WinPcap calls
5857e22627SCy Schubert 
5957e22627SCy Schubert #include "fmtutils.h"
6057e22627SCy Schubert #include "sockutils.h"		// for socket calls
6157e22627SCy Schubert #include "portability.h"
6257e22627SCy Schubert #include "rpcap-protocol.h"
6357e22627SCy Schubert #include "daemon.h"
6457e22627SCy Schubert #include "log.h"
6557e22627SCy Schubert 
666f9cba8fSJoseph Mingrone #ifdef HAVE_OPENSSL
676f9cba8fSJoseph Mingrone #include <openssl/ssl.h>
686f9cba8fSJoseph Mingrone #include "sslutils.h"
696f9cba8fSJoseph Mingrone #endif
706f9cba8fSJoseph Mingrone 
7157e22627SCy Schubert //
7257e22627SCy Schubert // Timeout, in seconds, when we're waiting for a client to send us an
7357e22627SCy Schubert // authentication request; if they don't send us a request within that
7457e22627SCy Schubert // interval, we drop the connection, so we don't stay stuck forever.
7557e22627SCy Schubert //
7657e22627SCy Schubert #define RPCAP_TIMEOUT_INIT 90
7757e22627SCy Schubert 
7857e22627SCy Schubert //
7957e22627SCy Schubert // Timeout, in seconds, when we're waiting for an authenticated client
8057e22627SCy Schubert // to send us a request, if a capture isn't in progress; if they don't
8157e22627SCy Schubert // send us a request within that interval, we drop the connection, so
8257e22627SCy Schubert // we don't stay stuck forever.
8357e22627SCy Schubert //
8457e22627SCy Schubert #define RPCAP_TIMEOUT_RUNTIME 180
8557e22627SCy Schubert 
8657e22627SCy Schubert //
8757e22627SCy Schubert // Time, in seconds, that we wait after a failed authentication attempt
8857e22627SCy Schubert // before processing the next request; this prevents a client from
8957e22627SCy Schubert // rapidly trying different accounts or passwords.
9057e22627SCy Schubert //
9157e22627SCy Schubert #define RPCAP_SUSPEND_WRONGAUTH 1
9257e22627SCy Schubert 
9357e22627SCy Schubert // Parameters for the service loop.
9457e22627SCy Schubert struct daemon_slpars
9557e22627SCy Schubert {
96*afdbf109SJoseph Mingrone 	PCAP_SOCKET sockctrl;	//!< PCAP_SOCKET ID of the control connection
976f9cba8fSJoseph Mingrone 	SSL *ssl;		//!< Optional SSL handler for the controlling sockets
9857e22627SCy Schubert 	int isactive;		//!< Not null if the daemon has to run in active mode
9957e22627SCy Schubert 	int nullAuthAllowed;	//!< '1' if we permit NULL authentication, '0' otherwise
10057e22627SCy Schubert };
10157e22627SCy Schubert 
10257e22627SCy Schubert //
10357e22627SCy Schubert // Data for a session managed by a thread.
10457e22627SCy Schubert // It includes both a Boolean indicating whether we *have* a thread,
10557e22627SCy Schubert // and a platform-dependent (UN*X vs. Windows) identifier for the
10657e22627SCy Schubert // thread; on Windows, we could use an invalid handle to indicate
10757e22627SCy Schubert // that we don't have a thread, but there *is* no portable "no thread"
10857e22627SCy Schubert // value for a pthread_t on UN*X.
10957e22627SCy Schubert //
11057e22627SCy Schubert struct session {
111*afdbf109SJoseph Mingrone 	PCAP_SOCKET sockctrl;
112*afdbf109SJoseph Mingrone 	PCAP_SOCKET sockdata;
1136f9cba8fSJoseph Mingrone 	SSL *ctrl_ssl, *data_ssl; // optional SSL handlers for sockctrl and sockdata.
11457e22627SCy Schubert 	uint8 protocol_version;
11557e22627SCy Schubert 	pcap_t *fp;
11657e22627SCy Schubert 	unsigned int TotCapt;
11757e22627SCy Schubert 	int	have_thread;
11857e22627SCy Schubert #ifdef _WIN32
11957e22627SCy Schubert 	HANDLE thread;
12057e22627SCy Schubert #else
12157e22627SCy Schubert 	pthread_t thread;
12257e22627SCy Schubert #endif
12357e22627SCy Schubert };
12457e22627SCy Schubert 
12557e22627SCy Schubert // Locally defined functions
126*afdbf109SJoseph Mingrone static int daemon_msg_err(PCAP_SOCKET sockctrl, SSL *, uint32 plen);
12757e22627SCy Schubert static int daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen);
12857e22627SCy Schubert static int daemon_AuthUserPwd(char *username, char *password, char *errbuf);
12957e22627SCy Schubert 
13057e22627SCy Schubert static int daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars,
13157e22627SCy Schubert     uint32 plen);
13257e22627SCy Schubert 
13357e22627SCy Schubert static int daemon_msg_open_req(uint8 ver, struct daemon_slpars *pars,
13457e22627SCy Schubert     uint32 plen, char *source, size_t sourcelen);
13557e22627SCy Schubert static int daemon_msg_startcap_req(uint8 ver, struct daemon_slpars *pars,
13657e22627SCy Schubert     uint32 plen, char *source, struct session **sessionp,
1376f9cba8fSJoseph Mingrone     struct rpcap_sampling *samp_param, int uses_ssl);
13857e22627SCy Schubert static int daemon_msg_endcap_req(uint8 ver, struct daemon_slpars *pars,
13957e22627SCy Schubert     struct session *session);
14057e22627SCy Schubert 
14157e22627SCy Schubert static int daemon_msg_updatefilter_req(uint8 ver, struct daemon_slpars *pars,
14257e22627SCy Schubert     struct session *session, uint32 plen);
143*afdbf109SJoseph Mingrone static int daemon_unpackapplyfilter(PCAP_SOCKET sockctrl, SSL *, struct session *session, uint32 *plenp, char *errbuf);
14457e22627SCy Schubert 
14557e22627SCy Schubert static int daemon_msg_stats_req(uint8 ver, struct daemon_slpars *pars,
14657e22627SCy Schubert     struct session *session, uint32 plen, struct pcap_stat *stats,
14757e22627SCy Schubert     unsigned int svrcapt);
14857e22627SCy Schubert 
14957e22627SCy Schubert static int daemon_msg_setsampling_req(uint8 ver, struct daemon_slpars *pars,
15057e22627SCy Schubert     uint32 plen, struct rpcap_sampling *samp_param);
15157e22627SCy Schubert 
15257e22627SCy Schubert static void daemon_seraddr(struct sockaddr_storage *sockaddrin, struct rpcap_sockaddr *sockaddrout);
15357e22627SCy Schubert #ifdef _WIN32
15457e22627SCy Schubert static unsigned __stdcall daemon_thrdatamain(void *ptr);
15557e22627SCy Schubert #else
15657e22627SCy Schubert static void *daemon_thrdatamain(void *ptr);
15757e22627SCy Schubert static void noop_handler(int sign);
15857e22627SCy Schubert #endif
15957e22627SCy Schubert 
160*afdbf109SJoseph Mingrone static int rpcapd_recv_msg_header(PCAP_SOCKET sock, SSL *, struct rpcap_header *headerp);
161*afdbf109SJoseph Mingrone static int rpcapd_recv(PCAP_SOCKET sock, SSL *, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf);
162*afdbf109SJoseph Mingrone static int rpcapd_discard(PCAP_SOCKET sock, SSL *, uint32 len);
16357e22627SCy Schubert static void session_close(struct session *);
16457e22627SCy Schubert 
1656f9cba8fSJoseph Mingrone //
1666f9cba8fSJoseph Mingrone // TLS record layer header; used when processing the first message from
1676f9cba8fSJoseph Mingrone // the client, in case we aren't doing TLS but they are.
1686f9cba8fSJoseph Mingrone //
1696f9cba8fSJoseph Mingrone struct tls_record_header {
1706f9cba8fSJoseph Mingrone 	uint8 type;		// ContentType - will be 22, for Handshake
1716f9cba8fSJoseph Mingrone 	uint8 version_major;	// TLS protocol major version
1726f9cba8fSJoseph Mingrone 	uint8 version_injor;	// TLS protocol minor version
1736f9cba8fSJoseph Mingrone 	// This is *not* aligned on a 2-byte boundary; we just
1746f9cba8fSJoseph Mingrone 	// declare it as two bytes.  Don't assume any particular
1756f9cba8fSJoseph Mingrone 	// compiler's mechanism for saying "packed"!
1766f9cba8fSJoseph Mingrone 	uint8 length_hi;	// Upper 8 bits of payload length
1776f9cba8fSJoseph Mingrone 	uint8 length_lo;	// Low 8 bits of payload length
1786f9cba8fSJoseph Mingrone };
1796f9cba8fSJoseph Mingrone 
1806f9cba8fSJoseph Mingrone #define TLS_RECORD_HEADER_LEN	5	// Don't use sizeof in case it's padded
1816f9cba8fSJoseph Mingrone 
1826f9cba8fSJoseph Mingrone #define TLS_RECORD_TYPE_ALERT		21
1836f9cba8fSJoseph Mingrone #define TLS_RECORD_TYPE_HANDSHAKE	22
1846f9cba8fSJoseph Mingrone 
1856f9cba8fSJoseph Mingrone //
1866f9cba8fSJoseph Mingrone // TLS alert message.
1876f9cba8fSJoseph Mingrone //
1886f9cba8fSJoseph Mingrone struct tls_alert {
1896f9cba8fSJoseph Mingrone 	uint8 alert_level;
1906f9cba8fSJoseph Mingrone 	uint8 alert_description;
1916f9cba8fSJoseph Mingrone };
1926f9cba8fSJoseph Mingrone 
1936f9cba8fSJoseph Mingrone #define TLS_ALERT_LEN			2
1946f9cba8fSJoseph Mingrone 
1956f9cba8fSJoseph Mingrone #define TLS_ALERT_LEVEL_FATAL		2
1966f9cba8fSJoseph Mingrone #define TLS_ALERT_HANDSHAKE_FAILURE	40
1976f9cba8fSJoseph Mingrone 
19857e22627SCy Schubert static int is_url(const char *source);
19957e22627SCy Schubert 
2006f9cba8fSJoseph Mingrone /*
2016f9cba8fSJoseph Mingrone  * Maximum sizes for fixed-bit-width values.
2026f9cba8fSJoseph Mingrone  */
2036f9cba8fSJoseph Mingrone #ifndef UINT16_MAX
2046f9cba8fSJoseph Mingrone #define UINT16_MAX	65535U
2056f9cba8fSJoseph Mingrone #endif
2066f9cba8fSJoseph Mingrone 
2076f9cba8fSJoseph Mingrone #ifndef UINT32_MAX
2086f9cba8fSJoseph Mingrone #define UINT32_MAX	4294967295U
2096f9cba8fSJoseph Mingrone #endif
2106f9cba8fSJoseph Mingrone 
21157e22627SCy Schubert int
daemon_serviceloop(PCAP_SOCKET sockctrl,int isactive,char * passiveClients,int nullAuthAllowed,int uses_ssl)212*afdbf109SJoseph Mingrone daemon_serviceloop(PCAP_SOCKET sockctrl, int isactive, char *passiveClients,
2136f9cba8fSJoseph Mingrone     int nullAuthAllowed, int uses_ssl)
21457e22627SCy Schubert {
2156f9cba8fSJoseph Mingrone 	uint8 first_octet;
2166f9cba8fSJoseph Mingrone 	struct tls_record_header tls_header;
2176f9cba8fSJoseph Mingrone 	struct tls_alert tls_alert;
21857e22627SCy Schubert 	struct daemon_slpars pars;		// service loop parameters
21957e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed
22057e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE + 1];	// buffer for errors to send to the client
22157e22627SCy Schubert 	int host_port_check_status;
2226f9cba8fSJoseph Mingrone 	SSL *ssl = NULL;
22357e22627SCy Schubert 	int nrecv;
22457e22627SCy Schubert 	struct rpcap_header header;		// RPCAP message general header
22557e22627SCy Schubert 	uint32 plen;				// payload length from header
22657e22627SCy Schubert 	int authenticated = 0;			// 1 if the client has successfully authenticated
22757e22627SCy Schubert 	char source[PCAP_BUF_SIZE+1];		// keeps the string that contains the interface to open
22857e22627SCy Schubert 	int got_source = 0;			// 1 if we've gotten the source from an open request
22957e22627SCy Schubert #ifndef _WIN32
23057e22627SCy Schubert 	struct sigaction action;
23157e22627SCy Schubert #endif
23257e22627SCy Schubert 	struct session *session = NULL;		// struct session main variable
23357e22627SCy Schubert 	const char *msg_type_string;		// string for message type
23457e22627SCy Schubert 	int client_told_us_to_close = 0;	// 1 if the client told us to close the capture
23557e22627SCy Schubert 
23657e22627SCy Schubert 	// needed to save the values of the statistics
23757e22627SCy Schubert 	struct pcap_stat stats;
23857e22627SCy Schubert 	unsigned int svrcapt;
23957e22627SCy Schubert 
24057e22627SCy Schubert 	struct rpcap_sampling samp_param;	// in case sampling has been requested
24157e22627SCy Schubert 
24257e22627SCy Schubert 	// Structures needed for the select() call
24357e22627SCy Schubert 	fd_set rfds;				// set of socket descriptors we have to check
24457e22627SCy Schubert 	struct timeval tv;			// maximum time the select() can block waiting for data
24557e22627SCy Schubert 	int retval;				// select() return value
24657e22627SCy Schubert 
24757e22627SCy Schubert 	*errbuf = 0;	// Initialize errbuf
24857e22627SCy Schubert 
2496f9cba8fSJoseph Mingrone 	//
2506f9cba8fSJoseph Mingrone 	// Peek into the socket to determine whether the client sent us
2516f9cba8fSJoseph Mingrone 	// a TLS handshake message or a non-TLS rpcapd message.
2526f9cba8fSJoseph Mingrone 	//
2536f9cba8fSJoseph Mingrone 	// The first byte of an rpcapd request is the version number;
2546f9cba8fSJoseph Mingrone 	// the first byte of a TLS handshake message is 22.  The
2556f9cba8fSJoseph Mingrone 	// first request to an rpcapd server must be an authentication
2566f9cba8fSJoseph Mingrone 	// request or a close request, and must have a version number
2576f9cba8fSJoseph Mingrone 	// of 0, so it will be possible to distinguish between an
2586f9cba8fSJoseph Mingrone 	// initial plaintext request to a server and an initial TLS
2596f9cba8fSJoseph Mingrone 	// handshake message.
2606f9cba8fSJoseph Mingrone 	//
2616f9cba8fSJoseph Mingrone 	nrecv = sock_recv(sockctrl, NULL, (char *)&first_octet, 1,
2626f9cba8fSJoseph Mingrone 	    SOCK_EOF_ISNT_ERROR|SOCK_MSG_PEEK, errbuf, PCAP_ERRBUF_SIZE);
2636f9cba8fSJoseph Mingrone 	if (nrecv == -1)
2646f9cba8fSJoseph Mingrone 	{
2656f9cba8fSJoseph Mingrone 		// Fatal error.
2666f9cba8fSJoseph Mingrone 		rpcapd_log(LOGPRIO_ERROR, "Peek from client failed: %s", errbuf);
2676f9cba8fSJoseph Mingrone 		goto end;
2686f9cba8fSJoseph Mingrone 	}
2696f9cba8fSJoseph Mingrone 	if (nrecv == 0)
2706f9cba8fSJoseph Mingrone 	{
2716f9cba8fSJoseph Mingrone 		// Client closed the connection.
2726f9cba8fSJoseph Mingrone 		goto end;
2736f9cba8fSJoseph Mingrone 	}
2746f9cba8fSJoseph Mingrone 
2756f9cba8fSJoseph Mingrone #ifdef HAVE_OPENSSL
2766f9cba8fSJoseph Mingrone 	//
2776f9cba8fSJoseph Mingrone 	// We have to upgrade to TLS as soon as possible, so that the
2786f9cba8fSJoseph Mingrone 	// whole protocol goes through the encrypted tunnel, including
2796f9cba8fSJoseph Mingrone 	// early error messages.
2806f9cba8fSJoseph Mingrone 	//
2816f9cba8fSJoseph Mingrone 	// Even in active mode, the other end has to initiate the TLS
2826f9cba8fSJoseph Mingrone 	// handshake as we still are the server as far as TLS is concerned,
2836f9cba8fSJoseph Mingrone 	// so we don't check isactive.
2846f9cba8fSJoseph Mingrone 	//
2856f9cba8fSJoseph Mingrone 	if (uses_ssl)
2866f9cba8fSJoseph Mingrone 	{
2876f9cba8fSJoseph Mingrone 		//
2886f9cba8fSJoseph Mingrone 		// We're expecting a TLS handshake message.  If this
2896f9cba8fSJoseph Mingrone 		// isn't one, assume it's a non-TLS rpcapd message.
2906f9cba8fSJoseph Mingrone 		//
2916f9cba8fSJoseph Mingrone 		// The first octet of a TLS handshake is
2926f9cba8fSJoseph Mingrone 		// TLS_RECORD_TYPE_HANDSHAKE.
2936f9cba8fSJoseph Mingrone 		//
2946f9cba8fSJoseph Mingrone 		if (first_octet != TLS_RECORD_TYPE_HANDSHAKE)
2956f9cba8fSJoseph Mingrone 		{
2966f9cba8fSJoseph Mingrone 			//
2976f9cba8fSJoseph Mingrone 			// We assume this is a non-TLS rpcapd message.
2986f9cba8fSJoseph Mingrone 			//
2996f9cba8fSJoseph Mingrone 			// Read the message header from the client.
3006f9cba8fSJoseph Mingrone 			//
3016f9cba8fSJoseph Mingrone 			nrecv = rpcapd_recv_msg_header(sockctrl, NULL, &header);
3026f9cba8fSJoseph Mingrone 			if (nrecv == -1)
3036f9cba8fSJoseph Mingrone 			{
3046f9cba8fSJoseph Mingrone 				// Fatal error.
3056f9cba8fSJoseph Mingrone 				goto end;
3066f9cba8fSJoseph Mingrone 			}
3076f9cba8fSJoseph Mingrone 			if (nrecv == -2)
3086f9cba8fSJoseph Mingrone 			{
3096f9cba8fSJoseph Mingrone 				// Client closed the connection.
3106f9cba8fSJoseph Mingrone 				goto end;
3116f9cba8fSJoseph Mingrone 			}
3126f9cba8fSJoseph Mingrone 			plen = header.plen;
3136f9cba8fSJoseph Mingrone 
3146f9cba8fSJoseph Mingrone 			// Discard the rest of the message.
3156f9cba8fSJoseph Mingrone 			if (rpcapd_discard(sockctrl, NULL, plen) == -1)
3166f9cba8fSJoseph Mingrone 			{
3176f9cba8fSJoseph Mingrone 				// Network error.
3186f9cba8fSJoseph Mingrone 				goto end;
3196f9cba8fSJoseph Mingrone 			}
3206f9cba8fSJoseph Mingrone 
3216f9cba8fSJoseph Mingrone 			//
3226f9cba8fSJoseph Mingrone 			// Send an authentication error, indicating
3236f9cba8fSJoseph Mingrone 			// that we require TLS.
3246f9cba8fSJoseph Mingrone 			//
3256f9cba8fSJoseph Mingrone 			if (rpcap_senderror(sockctrl, NULL, header.ver,
3266f9cba8fSJoseph Mingrone 			    PCAP_ERR_TLS_REQUIRED,
3276f9cba8fSJoseph Mingrone 			    "TLS is required by this server", errbuf) == -1)
3286f9cba8fSJoseph Mingrone 			{
3296f9cba8fSJoseph Mingrone 				// That failed; log a message and give up.
3306f9cba8fSJoseph Mingrone 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
3316f9cba8fSJoseph Mingrone 				goto end;
3326f9cba8fSJoseph Mingrone 			}
3336f9cba8fSJoseph Mingrone 
3346f9cba8fSJoseph Mingrone 			// Shut the session down.
3356f9cba8fSJoseph Mingrone 			goto end;
3366f9cba8fSJoseph Mingrone 		}
3376f9cba8fSJoseph Mingrone 		ssl = ssl_promotion(1, sockctrl, errbuf, PCAP_ERRBUF_SIZE);
3386f9cba8fSJoseph Mingrone 		if (! ssl)
3396f9cba8fSJoseph Mingrone 		{
3406f9cba8fSJoseph Mingrone 			rpcapd_log(LOGPRIO_ERROR, "TLS handshake on control connection failed: %s",
3416f9cba8fSJoseph Mingrone 			    errbuf);
3426f9cba8fSJoseph Mingrone 			goto end;
3436f9cba8fSJoseph Mingrone 		}
3446f9cba8fSJoseph Mingrone 	}
3456f9cba8fSJoseph Mingrone 	else
3466f9cba8fSJoseph Mingrone #endif
3476f9cba8fSJoseph Mingrone 	{
3486f9cba8fSJoseph Mingrone 		//
3496f9cba8fSJoseph Mingrone 		// We're expecting a non-TLS rpcapd message.  If this
3506f9cba8fSJoseph Mingrone 		// looks, instead, like a TLS handshake message, send
3516f9cba8fSJoseph Mingrone 		// a TLS handshake_failed alert.
3526f9cba8fSJoseph Mingrone 		//
3536f9cba8fSJoseph Mingrone 		// The first octet of a TLS handshake is
3546f9cba8fSJoseph Mingrone 		// TLS_RECORD_TYPE_HANDSHAKE.
3556f9cba8fSJoseph Mingrone 		//
3566f9cba8fSJoseph Mingrone 		if (first_octet == TLS_RECORD_TYPE_HANDSHAKE)
3576f9cba8fSJoseph Mingrone 		{
3586f9cba8fSJoseph Mingrone 			//
3596f9cba8fSJoseph Mingrone 			// TLS handshake.
3606f9cba8fSJoseph Mingrone 			// Read the record header.
3616f9cba8fSJoseph Mingrone 			//
3626f9cba8fSJoseph Mingrone 			nrecv = sock_recv(sockctrl, ssl, (char *) &tls_header,
3636f9cba8fSJoseph Mingrone 			    sizeof tls_header, SOCK_RECEIVEALL_YES|SOCK_EOF_ISNT_ERROR,
3646f9cba8fSJoseph Mingrone 			    errbuf, PCAP_ERRBUF_SIZE);
3656f9cba8fSJoseph Mingrone 			if (nrecv == -1)
3666f9cba8fSJoseph Mingrone 			{
3676f9cba8fSJoseph Mingrone 				// Network error.
3686f9cba8fSJoseph Mingrone 				rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
3696f9cba8fSJoseph Mingrone 				goto end;
3706f9cba8fSJoseph Mingrone 			}
3716f9cba8fSJoseph Mingrone 			if (nrecv == 0)
3726f9cba8fSJoseph Mingrone 			{
3736f9cba8fSJoseph Mingrone 				// Immediate EOF
3746f9cba8fSJoseph Mingrone 				goto end;
3756f9cba8fSJoseph Mingrone 			}
3766f9cba8fSJoseph Mingrone 			plen = (tls_header.length_hi << 8U) | tls_header.length_lo;
3776f9cba8fSJoseph Mingrone 
3786f9cba8fSJoseph Mingrone 			// Discard the rest of the message.
3796f9cba8fSJoseph Mingrone 			if (rpcapd_discard(sockctrl, NULL, plen) == -1)
3806f9cba8fSJoseph Mingrone 			{
3816f9cba8fSJoseph Mingrone 				// Network error.
3826f9cba8fSJoseph Mingrone 				goto end;
3836f9cba8fSJoseph Mingrone 			}
3846f9cba8fSJoseph Mingrone 
3856f9cba8fSJoseph Mingrone 			//
3866f9cba8fSJoseph Mingrone 			// Send a TLS handshake failure alert.
3876f9cba8fSJoseph Mingrone 			// Use the same version the client sent us.
3886f9cba8fSJoseph Mingrone 			//
3896f9cba8fSJoseph Mingrone 			tls_header.type = TLS_RECORD_TYPE_ALERT;
3906f9cba8fSJoseph Mingrone 			tls_header.length_hi = 0;
3916f9cba8fSJoseph Mingrone 			tls_header.length_lo = TLS_ALERT_LEN;
3926f9cba8fSJoseph Mingrone 
3936f9cba8fSJoseph Mingrone 			if (sock_send(sockctrl, NULL, (char *) &tls_header,
3946f9cba8fSJoseph Mingrone 			    TLS_RECORD_HEADER_LEN, errbuf, PCAP_ERRBUF_SIZE) == -1)
3956f9cba8fSJoseph Mingrone 			{
3966f9cba8fSJoseph Mingrone 				// That failed; log a message and give up.
3976f9cba8fSJoseph Mingrone 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
3986f9cba8fSJoseph Mingrone 				goto end;
3996f9cba8fSJoseph Mingrone 			}
4006f9cba8fSJoseph Mingrone 
4016f9cba8fSJoseph Mingrone 			tls_alert.alert_level = TLS_ALERT_LEVEL_FATAL;
4026f9cba8fSJoseph Mingrone 			tls_alert.alert_description = TLS_ALERT_HANDSHAKE_FAILURE;
4036f9cba8fSJoseph Mingrone 			if (sock_send(sockctrl, NULL, (char *) &tls_alert,
4046f9cba8fSJoseph Mingrone 			    TLS_ALERT_LEN, errbuf, PCAP_ERRBUF_SIZE) == -1)
4056f9cba8fSJoseph Mingrone 			{
4066f9cba8fSJoseph Mingrone 				// That failed; log a message and give up.
4076f9cba8fSJoseph Mingrone 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
4086f9cba8fSJoseph Mingrone 				goto end;
4096f9cba8fSJoseph Mingrone 			}
4106f9cba8fSJoseph Mingrone 			//
4116f9cba8fSJoseph Mingrone 			// Give up anyway.
4126f9cba8fSJoseph Mingrone 			//
4136f9cba8fSJoseph Mingrone 			goto end;
4146f9cba8fSJoseph Mingrone 		}
4156f9cba8fSJoseph Mingrone 	}
4166f9cba8fSJoseph Mingrone 
41757e22627SCy Schubert 	// Set parameters structure
41857e22627SCy Schubert 	pars.sockctrl = sockctrl;
4196f9cba8fSJoseph Mingrone 	pars.ssl = ssl;
42057e22627SCy Schubert 	pars.isactive = isactive;		// active mode
42157e22627SCy Schubert 	pars.nullAuthAllowed = nullAuthAllowed;
42257e22627SCy Schubert 
42357e22627SCy Schubert 	//
42457e22627SCy Schubert 	// We have a connection.
42557e22627SCy Schubert 	//
42657e22627SCy Schubert 	// If it's a passive mode connection, check whether the connecting
42757e22627SCy Schubert 	// host is among the ones allowed.
42857e22627SCy Schubert 	//
42957e22627SCy Schubert 	// In either case, we were handed a copy of the host list; free it
43057e22627SCy Schubert 	// as soon as we're done with it.
43157e22627SCy Schubert 	//
43257e22627SCy Schubert 	if (pars.isactive)
43357e22627SCy Schubert 	{
43457e22627SCy Schubert 		// Nothing to do.
43557e22627SCy Schubert 		free(passiveClients);
43657e22627SCy Schubert 		passiveClients = NULL;
43757e22627SCy Schubert 	}
43857e22627SCy Schubert 	else
43957e22627SCy Schubert 	{
44057e22627SCy Schubert 		struct sockaddr_storage from;
44157e22627SCy Schubert 		socklen_t fromlen;
44257e22627SCy Schubert 
44357e22627SCy Schubert 		//
44457e22627SCy Schubert 		// Get the address of the other end of the connection.
44557e22627SCy Schubert 		//
44657e22627SCy Schubert 		fromlen = sizeof(struct sockaddr_storage);
44757e22627SCy Schubert 		if (getpeername(pars.sockctrl, (struct sockaddr *)&from,
44857e22627SCy Schubert 		    &fromlen) == -1)
44957e22627SCy Schubert 		{
4506f9cba8fSJoseph Mingrone 			sock_geterrmsg(errmsgbuf, PCAP_ERRBUF_SIZE,
4516f9cba8fSJoseph Mingrone 			    "getpeername() failed");
4526f9cba8fSJoseph Mingrone 			if (rpcap_senderror(pars.sockctrl, pars.ssl, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
45357e22627SCy Schubert 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
45457e22627SCy Schubert 			goto end;
45557e22627SCy Schubert 		}
45657e22627SCy Schubert 
45757e22627SCy Schubert 		//
45857e22627SCy Schubert 		// Are they in the list of host/port combinations we allow?
45957e22627SCy Schubert 		//
46057e22627SCy Schubert 		host_port_check_status = sock_check_hostlist(passiveClients, RPCAP_HOSTLIST_SEP, &from, errmsgbuf, PCAP_ERRBUF_SIZE);
46157e22627SCy Schubert 		free(passiveClients);
46257e22627SCy Schubert 		passiveClients = NULL;
46357e22627SCy Schubert 		if (host_port_check_status < 0)
46457e22627SCy Schubert 		{
46557e22627SCy Schubert 			if (host_port_check_status == -2) {
46657e22627SCy Schubert 				//
46757e22627SCy Schubert 				// We got an error; log it.
46857e22627SCy Schubert 				//
46957e22627SCy Schubert 				rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
47057e22627SCy Schubert 			}
47157e22627SCy Schubert 
47257e22627SCy Schubert 			//
47357e22627SCy Schubert 			// Sorry, we can't let you in.
47457e22627SCy Schubert 			//
4756f9cba8fSJoseph Mingrone 			if (rpcap_senderror(pars.sockctrl, pars.ssl, 0, PCAP_ERR_HOSTNOAUTH, errmsgbuf, errbuf) == -1)
47657e22627SCy Schubert 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
47757e22627SCy Schubert 			goto end;
47857e22627SCy Schubert 		}
47957e22627SCy Schubert 	}
48057e22627SCy Schubert 
48157e22627SCy Schubert #ifndef _WIN32
48257e22627SCy Schubert 	//
48357e22627SCy Schubert 	// Catch SIGUSR1, but do nothing.  We use it to interrupt the
48457e22627SCy Schubert 	// capture thread to break it out of a loop in which it's
48557e22627SCy Schubert 	// blocked waiting for packets to arrive.
48657e22627SCy Schubert 	//
48757e22627SCy Schubert 	// We don't want interrupted system calls to restart, so that
48857e22627SCy Schubert 	// the read routine for the pcap_t gets EINTR rather than
48957e22627SCy Schubert 	// restarting if it's blocked in a system call.
49057e22627SCy Schubert 	//
49157e22627SCy Schubert 	memset(&action, 0, sizeof (action));
49257e22627SCy Schubert 	action.sa_handler = noop_handler;
49357e22627SCy Schubert 	action.sa_flags = 0;
49457e22627SCy Schubert 	sigemptyset(&action.sa_mask);
49557e22627SCy Schubert 	sigaction(SIGUSR1, &action, NULL);
49657e22627SCy Schubert #endif
49757e22627SCy Schubert 
49857e22627SCy Schubert 	//
49957e22627SCy Schubert 	// The client must first authenticate; loop until they send us a
50057e22627SCy Schubert 	// message with a version we support and credentials we accept,
50157e22627SCy Schubert 	// they send us a close message indicating that they're giving up,
50257e22627SCy Schubert 	// or we get a network error or other fatal error.
50357e22627SCy Schubert 	//
50457e22627SCy Schubert 	while (!authenticated)
50557e22627SCy Schubert 	{
50657e22627SCy Schubert 		//
50757e22627SCy Schubert 		// If we're not in active mode, we use select(), with a
50857e22627SCy Schubert 		// timeout, to wait for an authentication request; if
50957e22627SCy Schubert 		// the timeout expires, we drop the connection, so that
51057e22627SCy Schubert 		// a client can't just connect to us and leave us
51157e22627SCy Schubert 		// waiting forever.
51257e22627SCy Schubert 		//
51357e22627SCy Schubert 		if (!pars.isactive)
51457e22627SCy Schubert 		{
51557e22627SCy Schubert 			FD_ZERO(&rfds);
51657e22627SCy Schubert 			// We do not have to block here
51757e22627SCy Schubert 			tv.tv_sec = RPCAP_TIMEOUT_INIT;
51857e22627SCy Schubert 			tv.tv_usec = 0;
51957e22627SCy Schubert 
52057e22627SCy Schubert 			FD_SET(pars.sockctrl, &rfds);
52157e22627SCy Schubert 
5226f9cba8fSJoseph Mingrone 			retval = select((int)pars.sockctrl + 1, &rfds, NULL, NULL, &tv);
52357e22627SCy Schubert 			if (retval == -1)
52457e22627SCy Schubert 			{
5256f9cba8fSJoseph Mingrone 				sock_geterrmsg(errmsgbuf, PCAP_ERRBUF_SIZE,
5266f9cba8fSJoseph Mingrone 				    "select() failed");
5276f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
52857e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
52957e22627SCy Schubert 				goto end;
53057e22627SCy Schubert 			}
53157e22627SCy Schubert 
53257e22627SCy Schubert 			// The timeout has expired
53357e22627SCy Schubert 			// So, this was a fake connection. Drop it down
53457e22627SCy Schubert 			if (retval == 0)
53557e22627SCy Schubert 			{
5366f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl, 0, PCAP_ERR_INITTIMEOUT, "The RPCAP initial timeout has expired", errbuf) == -1)
53757e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
53857e22627SCy Schubert 				goto end;
53957e22627SCy Schubert 			}
54057e22627SCy Schubert 		}
54157e22627SCy Schubert 
54257e22627SCy Schubert 		//
54357e22627SCy Schubert 		// Read the message header from the client.
54457e22627SCy Schubert 		//
5456f9cba8fSJoseph Mingrone 		nrecv = rpcapd_recv_msg_header(pars.sockctrl, pars.ssl, &header);
54657e22627SCy Schubert 		if (nrecv == -1)
54757e22627SCy Schubert 		{
54857e22627SCy Schubert 			// Fatal error.
54957e22627SCy Schubert 			goto end;
55057e22627SCy Schubert 		}
55157e22627SCy Schubert 		if (nrecv == -2)
55257e22627SCy Schubert 		{
55357e22627SCy Schubert 			// Client closed the connection.
55457e22627SCy Schubert 			goto end;
55557e22627SCy Schubert 		}
55657e22627SCy Schubert 
55757e22627SCy Schubert 		plen = header.plen;
55857e22627SCy Schubert 
55957e22627SCy Schubert 		//
560*afdbf109SJoseph Mingrone 		// While we're in the authentication phase, all requests
56157e22627SCy Schubert 		// must use version 0.
56257e22627SCy Schubert 		//
56357e22627SCy Schubert 		if (header.ver != 0)
56457e22627SCy Schubert 		{
56557e22627SCy Schubert 			//
56657e22627SCy Schubert 			// Send it back to them with their version.
56757e22627SCy Schubert 			//
5686f9cba8fSJoseph Mingrone 			if (rpcap_senderror(pars.sockctrl, pars.ssl, header.ver,
56957e22627SCy Schubert 			    PCAP_ERR_WRONGVER,
57057e22627SCy Schubert 			    "RPCAP version in requests in the authentication phase must be 0",
57157e22627SCy Schubert 			    errbuf) == -1)
57257e22627SCy Schubert 			{
57357e22627SCy Schubert 				// That failed; log a message and give up.
57457e22627SCy Schubert 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
57557e22627SCy Schubert 				goto end;
57657e22627SCy Schubert 			}
57757e22627SCy Schubert 
57857e22627SCy Schubert 			// Discard the rest of the message and drop the
57957e22627SCy Schubert 			// connection.
5806f9cba8fSJoseph Mingrone 			(void)rpcapd_discard(pars.sockctrl, pars.ssl, plen);
58157e22627SCy Schubert 			goto end;
58257e22627SCy Schubert 		}
58357e22627SCy Schubert 
58457e22627SCy Schubert 		switch (header.type)
58557e22627SCy Schubert 		{
58657e22627SCy Schubert 			case RPCAP_MSG_AUTH_REQ:
58757e22627SCy Schubert 				retval = daemon_msg_auth_req(&pars, plen);
58857e22627SCy Schubert 				if (retval == -1)
58957e22627SCy Schubert 				{
59057e22627SCy Schubert 					// Fatal error; a message has
59157e22627SCy Schubert 					// been logged, so just give up.
59257e22627SCy Schubert 					goto end;
59357e22627SCy Schubert 				}
59457e22627SCy Schubert 				if (retval == -2)
59557e22627SCy Schubert 				{
59657e22627SCy Schubert 					// Non-fatal error; we sent back
59757e22627SCy Schubert 					// an error message, so let them
59857e22627SCy Schubert 					// try again.
59957e22627SCy Schubert 					continue;
60057e22627SCy Schubert 				}
60157e22627SCy Schubert 
60257e22627SCy Schubert 				// OK, we're authenticated; we sent back
60357e22627SCy Schubert 				// a reply, so start serving requests.
60457e22627SCy Schubert 				authenticated = 1;
60557e22627SCy Schubert 				break;
60657e22627SCy Schubert 
60757e22627SCy Schubert 			case RPCAP_MSG_CLOSE:
60857e22627SCy Schubert 				//
60957e22627SCy Schubert 				// The client is giving up.
61057e22627SCy Schubert 				// Discard the rest of the message, if
61157e22627SCy Schubert 				// there is anything more.
61257e22627SCy Schubert 				//
6136f9cba8fSJoseph Mingrone 				(void)rpcapd_discard(pars.sockctrl, pars.ssl, plen);
61457e22627SCy Schubert 				// We're done with this client.
61557e22627SCy Schubert 				goto end;
61657e22627SCy Schubert 
61757e22627SCy Schubert 			case RPCAP_MSG_ERROR:
61857e22627SCy Schubert 				// Log this and close the connection?
61957e22627SCy Schubert 				// XXX - is this what happens in active
62057e22627SCy Schubert 				// mode, where *we* initiate the
62157e22627SCy Schubert 				// connection, and the client gives us
62257e22627SCy Schubert 				// an error message rather than a "let
62357e22627SCy Schubert 				// me log in" message, indicating that
62457e22627SCy Schubert 				// we're not allowed to connect to them?
6256f9cba8fSJoseph Mingrone 				(void)daemon_msg_err(pars.sockctrl, pars.ssl, plen);
62657e22627SCy Schubert 				goto end;
62757e22627SCy Schubert 
62857e22627SCy Schubert 			case RPCAP_MSG_FINDALLIF_REQ:
62957e22627SCy Schubert 			case RPCAP_MSG_OPEN_REQ:
63057e22627SCy Schubert 			case RPCAP_MSG_STARTCAP_REQ:
63157e22627SCy Schubert 			case RPCAP_MSG_UPDATEFILTER_REQ:
63257e22627SCy Schubert 			case RPCAP_MSG_STATS_REQ:
63357e22627SCy Schubert 			case RPCAP_MSG_ENDCAP_REQ:
63457e22627SCy Schubert 			case RPCAP_MSG_SETSAMPLING_REQ:
63557e22627SCy Schubert 				//
63657e22627SCy Schubert 				// These requests can't be sent until
63757e22627SCy Schubert 				// the client is authenticated.
63857e22627SCy Schubert 				//
63957e22627SCy Schubert 				msg_type_string = rpcap_msg_type_string(header.type);
64057e22627SCy Schubert 				if (msg_type_string != NULL)
64157e22627SCy Schubert 				{
6426f9cba8fSJoseph Mingrone 					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "%s request sent before authentication was completed", msg_type_string);
64357e22627SCy Schubert 				}
64457e22627SCy Schubert 				else
64557e22627SCy Schubert 				{
6466f9cba8fSJoseph Mingrone 					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message of type %u sent before authentication was completed", header.type);
64757e22627SCy Schubert 				}
6486f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
6496f9cba8fSJoseph Mingrone 				    header.ver, PCAP_ERR_WRONGMSG,
6506f9cba8fSJoseph Mingrone 				    errmsgbuf, errbuf) == -1)
65157e22627SCy Schubert 				{
65257e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
65357e22627SCy Schubert 					goto end;
65457e22627SCy Schubert 				}
65557e22627SCy Schubert 				// Discard the rest of the message.
6566f9cba8fSJoseph Mingrone 				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
65757e22627SCy Schubert 				{
65857e22627SCy Schubert 					// Network error.
65957e22627SCy Schubert 					goto end;
66057e22627SCy Schubert 				}
66157e22627SCy Schubert 				break;
66257e22627SCy Schubert 
66357e22627SCy Schubert 			case RPCAP_MSG_PACKET:
66457e22627SCy Schubert 			case RPCAP_MSG_FINDALLIF_REPLY:
66557e22627SCy Schubert 			case RPCAP_MSG_OPEN_REPLY:
66657e22627SCy Schubert 			case RPCAP_MSG_STARTCAP_REPLY:
66757e22627SCy Schubert 			case RPCAP_MSG_UPDATEFILTER_REPLY:
66857e22627SCy Schubert 			case RPCAP_MSG_AUTH_REPLY:
66957e22627SCy Schubert 			case RPCAP_MSG_STATS_REPLY:
67057e22627SCy Schubert 			case RPCAP_MSG_ENDCAP_REPLY:
67157e22627SCy Schubert 			case RPCAP_MSG_SETSAMPLING_REPLY:
67257e22627SCy Schubert 				//
67357e22627SCy Schubert 				// These are server-to-client messages.
67457e22627SCy Schubert 				//
67557e22627SCy Schubert 				msg_type_string = rpcap_msg_type_string(header.type);
67657e22627SCy Schubert 				if (msg_type_string != NULL)
67757e22627SCy Schubert 				{
6786f9cba8fSJoseph Mingrone 					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message %s received from client", msg_type_string);
67957e22627SCy Schubert 				}
68057e22627SCy Schubert 				else
68157e22627SCy Schubert 				{
6826f9cba8fSJoseph Mingrone 					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
68357e22627SCy Schubert 				}
6846f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
6856f9cba8fSJoseph Mingrone 				    header.ver, PCAP_ERR_WRONGMSG,
6866f9cba8fSJoseph Mingrone 				    errmsgbuf, errbuf) == -1)
68757e22627SCy Schubert 				{
68857e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
68957e22627SCy Schubert 					goto end;
69057e22627SCy Schubert 				}
69157e22627SCy Schubert 				// Discard the rest of the message.
6926f9cba8fSJoseph Mingrone 				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
69357e22627SCy Schubert 				{
69457e22627SCy Schubert 					// Fatal error.
69557e22627SCy Schubert 					goto end;
69657e22627SCy Schubert 				}
69757e22627SCy Schubert 				break;
69857e22627SCy Schubert 
69957e22627SCy Schubert 			default:
70057e22627SCy Schubert 				//
70157e22627SCy Schubert 				// Unknown message type.
70257e22627SCy Schubert 				//
7036f9cba8fSJoseph Mingrone 				snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
7046f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
7056f9cba8fSJoseph Mingrone 				    header.ver, PCAP_ERR_WRONGMSG,
7066f9cba8fSJoseph Mingrone 				    errmsgbuf, errbuf) == -1)
70757e22627SCy Schubert 				{
70857e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
70957e22627SCy Schubert 					goto end;
71057e22627SCy Schubert 				}
71157e22627SCy Schubert 				// Discard the rest of the message.
7126f9cba8fSJoseph Mingrone 				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
71357e22627SCy Schubert 				{
71457e22627SCy Schubert 					// Fatal error.
71557e22627SCy Schubert 					goto end;
71657e22627SCy Schubert 				}
71757e22627SCy Schubert 				break;
71857e22627SCy Schubert 		}
71957e22627SCy Schubert 	}
72057e22627SCy Schubert 
72157e22627SCy Schubert 	//
72257e22627SCy Schubert 	// OK, the client has authenticated itself, and we can start
72357e22627SCy Schubert 	// processing regular requests from it.
72457e22627SCy Schubert 	//
72557e22627SCy Schubert 
72657e22627SCy Schubert 	//
72757e22627SCy Schubert 	// We don't have any statistics yet.
72857e22627SCy Schubert 	//
72957e22627SCy Schubert 	stats.ps_ifdrop = 0;
73057e22627SCy Schubert 	stats.ps_recv = 0;
73157e22627SCy Schubert 	stats.ps_drop = 0;
73257e22627SCy Schubert 	svrcapt = 0;
73357e22627SCy Schubert 
73457e22627SCy Schubert 	//
73557e22627SCy Schubert 	// Service requests.
73657e22627SCy Schubert 	//
73757e22627SCy Schubert 	for (;;)
73857e22627SCy Schubert 	{
73957e22627SCy Schubert 		errbuf[0] = 0;	// clear errbuf
74057e22627SCy Schubert 
74157e22627SCy Schubert 		// Avoid zombies connections; check if the connection is opens but no commands are performed
74257e22627SCy Schubert 		// from more than RPCAP_TIMEOUT_RUNTIME
74357e22627SCy Schubert 		// Conditions:
74457e22627SCy Schubert 		// - I have to be in normal mode (no active mode)
74557e22627SCy Schubert 		// - if the device is open, I don't have to be in the middle of a capture (session->sockdata)
74657e22627SCy Schubert 		// - if the device is closed, I have always to check if a new command arrives
74757e22627SCy Schubert 		//
74857e22627SCy Schubert 		// Be carefully: the capture can have been started, but an error occurred (so session != NULL, but
74957e22627SCy Schubert 		//  sockdata is 0
7506f9cba8fSJoseph Mingrone 		if ((!pars.isactive) && (session == NULL || session->sockdata == 0))
75157e22627SCy Schubert 		{
75257e22627SCy Schubert 			// Check for the initial timeout
75357e22627SCy Schubert 			FD_ZERO(&rfds);
75457e22627SCy Schubert 			// We do not have to block here
75557e22627SCy Schubert 			tv.tv_sec = RPCAP_TIMEOUT_RUNTIME;
75657e22627SCy Schubert 			tv.tv_usec = 0;
75757e22627SCy Schubert 
75857e22627SCy Schubert 			FD_SET(pars.sockctrl, &rfds);
7596f9cba8fSJoseph Mingrone #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
7606f9cba8fSJoseph Mingrone 			retval = 1;
7616f9cba8fSJoseph Mingrone #else
7626f9cba8fSJoseph Mingrone 			retval = select((int)pars.sockctrl + 1, &rfds, NULL, NULL, &tv);
7636f9cba8fSJoseph Mingrone #endif
76457e22627SCy Schubert 			if (retval == -1)
76557e22627SCy Schubert 			{
7666f9cba8fSJoseph Mingrone 				sock_geterrmsg(errmsgbuf, PCAP_ERRBUF_SIZE,
7676f9cba8fSJoseph Mingrone 				    "select() failed");
7686f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
7696f9cba8fSJoseph Mingrone 				    0, PCAP_ERR_NETW,
7706f9cba8fSJoseph Mingrone 				    errmsgbuf, errbuf) == -1)
77157e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
77257e22627SCy Schubert 				goto end;
77357e22627SCy Schubert 			}
77457e22627SCy Schubert 
77557e22627SCy Schubert 			// The timeout has expired
77657e22627SCy Schubert 			// So, this was a fake connection. Drop it down
77757e22627SCy Schubert 			if (retval == 0)
77857e22627SCy Schubert 			{
7796f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
7806f9cba8fSJoseph Mingrone 				    0, PCAP_ERR_INITTIMEOUT,
78157e22627SCy Schubert 				    "The RPCAP initial timeout has expired",
78257e22627SCy Schubert 				    errbuf) == -1)
78357e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
78457e22627SCy Schubert 				goto end;
78557e22627SCy Schubert 			}
78657e22627SCy Schubert 		}
78757e22627SCy Schubert 
78857e22627SCy Schubert 		//
78957e22627SCy Schubert 		// Read the message header from the client.
79057e22627SCy Schubert 		//
7916f9cba8fSJoseph Mingrone 		nrecv = rpcapd_recv_msg_header(pars.sockctrl, pars.ssl, &header);
79257e22627SCy Schubert 		if (nrecv == -1)
79357e22627SCy Schubert 		{
79457e22627SCy Schubert 			// Fatal error.
79557e22627SCy Schubert 			goto end;
79657e22627SCy Schubert 		}
79757e22627SCy Schubert 		if (nrecv == -2)
79857e22627SCy Schubert 		{
79957e22627SCy Schubert 			// Client closed the connection.
80057e22627SCy Schubert 			goto end;
80157e22627SCy Schubert 		}
80257e22627SCy Schubert 
80357e22627SCy Schubert 		plen = header.plen;
80457e22627SCy Schubert 
80557e22627SCy Schubert 		//
80657e22627SCy Schubert 		// Did the client specify a protocol version that we
80757e22627SCy Schubert 		// support?
80857e22627SCy Schubert 		//
80957e22627SCy Schubert 		if (!RPCAP_VERSION_IS_SUPPORTED(header.ver))
81057e22627SCy Schubert 		{
81157e22627SCy Schubert 			//
81257e22627SCy Schubert 			// Tell them it's not a supported version.
81357e22627SCy Schubert 			// Send the error message with their version,
81457e22627SCy Schubert 			// so they don't reject it as having the wrong
81557e22627SCy Schubert 			// version.
81657e22627SCy Schubert 			//
8176f9cba8fSJoseph Mingrone 			if (rpcap_senderror(pars.sockctrl, pars.ssl,
81857e22627SCy Schubert 			    header.ver, PCAP_ERR_WRONGVER,
81957e22627SCy Schubert 			    "RPCAP version in message isn't supported by the server",
82057e22627SCy Schubert 			    errbuf) == -1)
82157e22627SCy Schubert 			{
82257e22627SCy Schubert 				// That failed; log a message and give up.
82357e22627SCy Schubert 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
82457e22627SCy Schubert 				goto end;
82557e22627SCy Schubert 			}
82657e22627SCy Schubert 
82757e22627SCy Schubert 			// Discard the rest of the message.
8286f9cba8fSJoseph Mingrone 			(void)rpcapd_discard(pars.sockctrl, pars.ssl, plen);
82957e22627SCy Schubert 			// Give up on them.
83057e22627SCy Schubert 			goto end;
83157e22627SCy Schubert 		}
83257e22627SCy Schubert 
83357e22627SCy Schubert 		switch (header.type)
83457e22627SCy Schubert 		{
83557e22627SCy Schubert 			case RPCAP_MSG_ERROR:		// The other endpoint reported an error
83657e22627SCy Schubert 			{
8376f9cba8fSJoseph Mingrone 				(void)daemon_msg_err(pars.sockctrl, pars.ssl, plen);
83857e22627SCy Schubert 				// Do nothing; just exit; the error code is already into the errbuf
83957e22627SCy Schubert 				// XXX - actually exit....
84057e22627SCy Schubert 				break;
84157e22627SCy Schubert 			}
84257e22627SCy Schubert 
84357e22627SCy Schubert 			case RPCAP_MSG_FINDALLIF_REQ:
84457e22627SCy Schubert 			{
84557e22627SCy Schubert 				if (daemon_msg_findallif_req(header.ver, &pars, plen) == -1)
84657e22627SCy Schubert 				{
84757e22627SCy Schubert 					// Fatal error; a message has
84857e22627SCy Schubert 					// been logged, so just give up.
84957e22627SCy Schubert 					goto end;
85057e22627SCy Schubert 				}
85157e22627SCy Schubert 				break;
85257e22627SCy Schubert 			}
85357e22627SCy Schubert 
85457e22627SCy Schubert 			case RPCAP_MSG_OPEN_REQ:
85557e22627SCy Schubert 			{
85657e22627SCy Schubert 				//
85757e22627SCy Schubert 				// Process the open request, and keep
85857e22627SCy Schubert 				// the source from it, for use later
85957e22627SCy Schubert 				// when the capture is started.
86057e22627SCy Schubert 				//
86157e22627SCy Schubert 				// XXX - we don't care if the client sends
86257e22627SCy Schubert 				// us multiple open requests, the last
86357e22627SCy Schubert 				// one wins.
86457e22627SCy Schubert 				//
86557e22627SCy Schubert 				retval = daemon_msg_open_req(header.ver, &pars,
86657e22627SCy Schubert 				    plen, source, sizeof(source));
86757e22627SCy Schubert 				if (retval == -1)
86857e22627SCy Schubert 				{
86957e22627SCy Schubert 					// Fatal error; a message has
87057e22627SCy Schubert 					// been logged, so just give up.
87157e22627SCy Schubert 					goto end;
87257e22627SCy Schubert 				}
87357e22627SCy Schubert 				got_source = 1;
87457e22627SCy Schubert 				break;
87557e22627SCy Schubert 			}
87657e22627SCy Schubert 
87757e22627SCy Schubert 			case RPCAP_MSG_STARTCAP_REQ:
87857e22627SCy Schubert 			{
87957e22627SCy Schubert 				if (!got_source)
88057e22627SCy Schubert 				{
88157e22627SCy Schubert 					// They never told us what device
88257e22627SCy Schubert 					// to capture on!
8836f9cba8fSJoseph Mingrone 					if (rpcap_senderror(pars.sockctrl, pars.ssl,
88457e22627SCy Schubert 					    header.ver,
88557e22627SCy Schubert 					    PCAP_ERR_STARTCAPTURE,
88657e22627SCy Schubert 					    "No capture device was specified",
88757e22627SCy Schubert 					    errbuf) == -1)
88857e22627SCy Schubert 					{
88957e22627SCy Schubert 						// Fatal error; log an
89057e22627SCy Schubert 						// error and  give up.
89157e22627SCy Schubert 						rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
89257e22627SCy Schubert 						goto end;
89357e22627SCy Schubert 					}
8946f9cba8fSJoseph Mingrone 					if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
89557e22627SCy Schubert 					{
89657e22627SCy Schubert 						goto end;
89757e22627SCy Schubert 					}
89857e22627SCy Schubert 					break;
89957e22627SCy Schubert 				}
90057e22627SCy Schubert 
90157e22627SCy Schubert 				if (daemon_msg_startcap_req(header.ver, &pars,
9026f9cba8fSJoseph Mingrone 				    plen, source, &session, &samp_param,
9036f9cba8fSJoseph Mingrone 				    uses_ssl) == -1)
90457e22627SCy Schubert 				{
90557e22627SCy Schubert 					// Fatal error; a message has
90657e22627SCy Schubert 					// been logged, so just give up.
90757e22627SCy Schubert 					goto end;
90857e22627SCy Schubert 				}
90957e22627SCy Schubert 				break;
91057e22627SCy Schubert 			}
91157e22627SCy Schubert 
91257e22627SCy Schubert 			case RPCAP_MSG_UPDATEFILTER_REQ:
91357e22627SCy Schubert 			{
91457e22627SCy Schubert 				if (session)
91557e22627SCy Schubert 				{
91657e22627SCy Schubert 					if (daemon_msg_updatefilter_req(header.ver,
91757e22627SCy Schubert 					    &pars, session, plen) == -1)
91857e22627SCy Schubert 					{
91957e22627SCy Schubert 						// Fatal error; a message has
92057e22627SCy Schubert 						// been logged, so just give up.
92157e22627SCy Schubert 						goto end;
92257e22627SCy Schubert 					}
92357e22627SCy Schubert 				}
92457e22627SCy Schubert 				else
92557e22627SCy Schubert 				{
9266f9cba8fSJoseph Mingrone 					if (rpcap_senderror(pars.sockctrl, pars.ssl,
9276f9cba8fSJoseph Mingrone 					    header.ver,
9286f9cba8fSJoseph Mingrone 					    PCAP_ERR_UPDATEFILTER,
92957e22627SCy Schubert 					    "Device not opened. Cannot update filter",
93057e22627SCy Schubert 					    errbuf) == -1)
93157e22627SCy Schubert 					{
93257e22627SCy Schubert 						// That failed; log a message and give up.
93357e22627SCy Schubert 						rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
93457e22627SCy Schubert 						goto end;
93557e22627SCy Schubert 					}
93657e22627SCy Schubert 				}
93757e22627SCy Schubert 				break;
93857e22627SCy Schubert 			}
93957e22627SCy Schubert 
94057e22627SCy Schubert 			case RPCAP_MSG_CLOSE:		// The other endpoint close the pcap session
94157e22627SCy Schubert 			{
94257e22627SCy Schubert 				//
94357e22627SCy Schubert 				// Indicate to our caller that the client
94457e22627SCy Schubert 				// closed the control connection.
94557e22627SCy Schubert 				// This is used only in case of active mode.
94657e22627SCy Schubert 				//
94757e22627SCy Schubert 				client_told_us_to_close = 1;
94857e22627SCy Schubert 				rpcapd_log(LOGPRIO_DEBUG, "The other end system asked to close the connection.");
94957e22627SCy Schubert 				goto end;
95057e22627SCy Schubert 			}
95157e22627SCy Schubert 
95257e22627SCy Schubert 			case RPCAP_MSG_STATS_REQ:
95357e22627SCy Schubert 			{
95457e22627SCy Schubert 				if (daemon_msg_stats_req(header.ver, &pars,
95557e22627SCy Schubert 				    session, plen, &stats, svrcapt) == -1)
95657e22627SCy Schubert 				{
95757e22627SCy Schubert 					// Fatal error; a message has
95857e22627SCy Schubert 					// been logged, so just give up.
95957e22627SCy Schubert 					goto end;
96057e22627SCy Schubert 				}
96157e22627SCy Schubert 				break;
96257e22627SCy Schubert 			}
96357e22627SCy Schubert 
96457e22627SCy Schubert 			case RPCAP_MSG_ENDCAP_REQ:		// The other endpoint close the current capture session
96557e22627SCy Schubert 			{
96657e22627SCy Schubert 				if (session)
96757e22627SCy Schubert 				{
96857e22627SCy Schubert 					// Save statistics (we can need them in the future)
96957e22627SCy Schubert 					if (pcap_stats(session->fp, &stats))
97057e22627SCy Schubert 					{
97157e22627SCy Schubert 						svrcapt = session->TotCapt;
97257e22627SCy Schubert 					}
97357e22627SCy Schubert 					else
97457e22627SCy Schubert 					{
97557e22627SCy Schubert 						stats.ps_ifdrop = 0;
97657e22627SCy Schubert 						stats.ps_recv = 0;
97757e22627SCy Schubert 						stats.ps_drop = 0;
97857e22627SCy Schubert 						svrcapt = 0;
97957e22627SCy Schubert 					}
98057e22627SCy Schubert 
98157e22627SCy Schubert 					if (daemon_msg_endcap_req(header.ver,
98257e22627SCy Schubert 					    &pars, session) == -1)
98357e22627SCy Schubert 					{
98457e22627SCy Schubert 						free(session);
98557e22627SCy Schubert 						session = NULL;
98657e22627SCy Schubert 						// Fatal error; a message has
98757e22627SCy Schubert 						// been logged, so just give up.
98857e22627SCy Schubert 						goto end;
98957e22627SCy Schubert 					}
99057e22627SCy Schubert 					free(session);
99157e22627SCy Schubert 					session = NULL;
99257e22627SCy Schubert 				}
99357e22627SCy Schubert 				else
99457e22627SCy Schubert 				{
9956f9cba8fSJoseph Mingrone 					rpcap_senderror(pars.sockctrl, pars.ssl,
9966f9cba8fSJoseph Mingrone 					    header.ver,
9976f9cba8fSJoseph Mingrone 					    PCAP_ERR_ENDCAPTURE,
99857e22627SCy Schubert 					    "Device not opened. Cannot close the capture",
99957e22627SCy Schubert 					    errbuf);
100057e22627SCy Schubert 				}
100157e22627SCy Schubert 				break;
100257e22627SCy Schubert 			}
100357e22627SCy Schubert 
100457e22627SCy Schubert 			case RPCAP_MSG_SETSAMPLING_REQ:
100557e22627SCy Schubert 			{
100657e22627SCy Schubert 				if (daemon_msg_setsampling_req(header.ver,
100757e22627SCy Schubert 				    &pars, plen, &samp_param) == -1)
100857e22627SCy Schubert 				{
100957e22627SCy Schubert 					// Fatal error; a message has
101057e22627SCy Schubert 					// been logged, so just give up.
101157e22627SCy Schubert 					goto end;
101257e22627SCy Schubert 				}
101357e22627SCy Schubert 				break;
101457e22627SCy Schubert 			}
101557e22627SCy Schubert 
101657e22627SCy Schubert 			case RPCAP_MSG_AUTH_REQ:
101757e22627SCy Schubert 			{
101857e22627SCy Schubert 				//
101957e22627SCy Schubert 				// We're already authenticated; you don't
102057e22627SCy Schubert 				// get to reauthenticate.
102157e22627SCy Schubert 				//
102257e22627SCy Schubert 				rpcapd_log(LOGPRIO_INFO, "The client sent an RPCAP_MSG_AUTH_REQ message after authentication was completed");
10236f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
10246f9cba8fSJoseph Mingrone 				    header.ver,
102557e22627SCy Schubert 				    PCAP_ERR_WRONGMSG,
102657e22627SCy Schubert 				    "RPCAP_MSG_AUTH_REQ request sent after authentication was completed",
102757e22627SCy Schubert 				    errbuf) == -1)
102857e22627SCy Schubert 				{
102957e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
103057e22627SCy Schubert 					goto end;
103157e22627SCy Schubert 				}
103257e22627SCy Schubert 				// Discard the rest of the message.
10336f9cba8fSJoseph Mingrone 				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
103457e22627SCy Schubert 				{
103557e22627SCy Schubert 					// Fatal error.
103657e22627SCy Schubert 					goto end;
103757e22627SCy Schubert 				}
103857e22627SCy Schubert 				goto end;
103957e22627SCy Schubert 
104057e22627SCy Schubert 			case RPCAP_MSG_PACKET:
104157e22627SCy Schubert 			case RPCAP_MSG_FINDALLIF_REPLY:
104257e22627SCy Schubert 			case RPCAP_MSG_OPEN_REPLY:
104357e22627SCy Schubert 			case RPCAP_MSG_STARTCAP_REPLY:
104457e22627SCy Schubert 			case RPCAP_MSG_UPDATEFILTER_REPLY:
104557e22627SCy Schubert 			case RPCAP_MSG_AUTH_REPLY:
104657e22627SCy Schubert 			case RPCAP_MSG_STATS_REPLY:
104757e22627SCy Schubert 			case RPCAP_MSG_ENDCAP_REPLY:
104857e22627SCy Schubert 			case RPCAP_MSG_SETSAMPLING_REPLY:
104957e22627SCy Schubert 				//
105057e22627SCy Schubert 				// These are server-to-client messages.
105157e22627SCy Schubert 				//
105257e22627SCy Schubert 				msg_type_string = rpcap_msg_type_string(header.type);
105357e22627SCy Schubert 				if (msg_type_string != NULL)
105457e22627SCy Schubert 				{
105557e22627SCy Schubert 					rpcapd_log(LOGPRIO_INFO, "The client sent a %s server-to-client message", msg_type_string);
10566f9cba8fSJoseph Mingrone 					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message %s received from client", msg_type_string);
105757e22627SCy Schubert 				}
105857e22627SCy Schubert 				else
105957e22627SCy Schubert 				{
106057e22627SCy Schubert 					rpcapd_log(LOGPRIO_INFO, "The client sent a server-to-client message of type %u", header.type);
10616f9cba8fSJoseph Mingrone 					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
106257e22627SCy Schubert 				}
10636f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
10646f9cba8fSJoseph Mingrone 				    header.ver, PCAP_ERR_WRONGMSG,
10656f9cba8fSJoseph Mingrone 				    errmsgbuf, errbuf) == -1)
106657e22627SCy Schubert 				{
106757e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
106857e22627SCy Schubert 					goto end;
106957e22627SCy Schubert 				}
107057e22627SCy Schubert 				// Discard the rest of the message.
10716f9cba8fSJoseph Mingrone 				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
107257e22627SCy Schubert 				{
107357e22627SCy Schubert 					// Fatal error.
107457e22627SCy Schubert 					goto end;
107557e22627SCy Schubert 				}
107657e22627SCy Schubert 				goto end;
107757e22627SCy Schubert 
107857e22627SCy Schubert 			default:
107957e22627SCy Schubert 				//
108057e22627SCy Schubert 				// Unknown message type.
108157e22627SCy Schubert 				//
108257e22627SCy Schubert 				rpcapd_log(LOGPRIO_INFO, "The client sent a message of type %u", header.type);
10836f9cba8fSJoseph Mingrone 				snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
10846f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
10856f9cba8fSJoseph Mingrone 				    header.ver, PCAP_ERR_WRONGMSG,
10866f9cba8fSJoseph Mingrone 				    errbuf, errmsgbuf) == -1)
108757e22627SCy Schubert 				{
108857e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
108957e22627SCy Schubert 					goto end;
109057e22627SCy Schubert 				}
109157e22627SCy Schubert 				// Discard the rest of the message.
10926f9cba8fSJoseph Mingrone 				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
109357e22627SCy Schubert 				{
109457e22627SCy Schubert 					// Fatal error.
109557e22627SCy Schubert 					goto end;
109657e22627SCy Schubert 				}
109757e22627SCy Schubert 				goto end;
109857e22627SCy Schubert 			}
109957e22627SCy Schubert 		}
110057e22627SCy Schubert 	}
110157e22627SCy Schubert 
110257e22627SCy Schubert end:
110357e22627SCy Schubert 	// The service loop is finishing up.
110457e22627SCy Schubert 	// If we have a capture session running, close it.
110557e22627SCy Schubert 	if (session)
110657e22627SCy Schubert 	{
110757e22627SCy Schubert 		session_close(session);
110857e22627SCy Schubert 		free(session);
110957e22627SCy Schubert 		session = NULL;
111057e22627SCy Schubert 	}
111157e22627SCy Schubert 
11126f9cba8fSJoseph Mingrone 	if (passiveClients) {
11136f9cba8fSJoseph Mingrone 		free(passiveClients);
11146f9cba8fSJoseph Mingrone 	}
11156f9cba8fSJoseph Mingrone 	//
11166f9cba8fSJoseph Mingrone 	// Finish using the SSL handle for the control socket, if we
11176f9cba8fSJoseph Mingrone 	// have an SSL connection, and close the control socket.
11186f9cba8fSJoseph Mingrone 	//
11196f9cba8fSJoseph Mingrone #ifdef HAVE_OPENSSL
11206f9cba8fSJoseph Mingrone 	if (ssl)
11216f9cba8fSJoseph Mingrone 	{
11226f9cba8fSJoseph Mingrone 		// Finish using the SSL handle for the socket.
11236f9cba8fSJoseph Mingrone 		// This must be done *before* the socket is closed.
11246f9cba8fSJoseph Mingrone 		ssl_finish(ssl);
11256f9cba8fSJoseph Mingrone 	}
11266f9cba8fSJoseph Mingrone #endif
112757e22627SCy Schubert 	sock_close(sockctrl, NULL, 0);
112857e22627SCy Schubert 
112957e22627SCy Schubert 	// Print message and return
113057e22627SCy Schubert 	rpcapd_log(LOGPRIO_DEBUG, "I'm exiting from the child loop");
113157e22627SCy Schubert 
113257e22627SCy Schubert 	return client_told_us_to_close;
113357e22627SCy Schubert }
113457e22627SCy Schubert 
113557e22627SCy Schubert /*
113657e22627SCy Schubert  * This handles the RPCAP_MSG_ERR message.
113757e22627SCy Schubert  */
113857e22627SCy Schubert static int
daemon_msg_err(PCAP_SOCKET sockctrl,SSL * ssl,uint32 plen)1139*afdbf109SJoseph Mingrone daemon_msg_err(PCAP_SOCKET sockctrl, SSL *ssl, uint32 plen)
114057e22627SCy Schubert {
114157e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];
114257e22627SCy Schubert 	char remote_errbuf[PCAP_ERRBUF_SIZE];
114357e22627SCy Schubert 
114457e22627SCy Schubert 	if (plen >= PCAP_ERRBUF_SIZE)
114557e22627SCy Schubert 	{
114657e22627SCy Schubert 		/*
114757e22627SCy Schubert 		 * Message is too long; just read as much of it as we
114857e22627SCy Schubert 		 * can into the buffer provided, and discard the rest.
114957e22627SCy Schubert 		 */
11506f9cba8fSJoseph Mingrone 		if (sock_recv(sockctrl, ssl, remote_errbuf, PCAP_ERRBUF_SIZE - 1,
115157e22627SCy Schubert 		    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
115257e22627SCy Schubert 		    PCAP_ERRBUF_SIZE) == -1)
115357e22627SCy Schubert 		{
115457e22627SCy Schubert 			// Network error.
115557e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
115657e22627SCy Schubert 			return -1;
115757e22627SCy Schubert 		}
11586f9cba8fSJoseph Mingrone 		if (rpcapd_discard(sockctrl, ssl, plen - (PCAP_ERRBUF_SIZE - 1)) == -1)
115957e22627SCy Schubert 		{
116057e22627SCy Schubert 			// Network error.
116157e22627SCy Schubert 			return -1;
116257e22627SCy Schubert 		}
116357e22627SCy Schubert 
116457e22627SCy Schubert 		/*
116557e22627SCy Schubert 		 * Null-terminate it.
116657e22627SCy Schubert 		 */
116757e22627SCy Schubert 		remote_errbuf[PCAP_ERRBUF_SIZE - 1] = '\0';
116857e22627SCy Schubert 	}
116957e22627SCy Schubert 	else if (plen == 0)
117057e22627SCy Schubert 	{
117157e22627SCy Schubert 		/* Empty error string. */
117257e22627SCy Schubert 		remote_errbuf[0] = '\0';
117357e22627SCy Schubert 	}
117457e22627SCy Schubert 	else
117557e22627SCy Schubert 	{
11766f9cba8fSJoseph Mingrone 		if (sock_recv(sockctrl, ssl, remote_errbuf, plen,
117757e22627SCy Schubert 		    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
117857e22627SCy Schubert 		    PCAP_ERRBUF_SIZE) == -1)
117957e22627SCy Schubert 		{
118057e22627SCy Schubert 			// Network error.
118157e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
118257e22627SCy Schubert 			return -1;
118357e22627SCy Schubert 		}
118457e22627SCy Schubert 
118557e22627SCy Schubert 		/*
118657e22627SCy Schubert 		 * Null-terminate it.
118757e22627SCy Schubert 		 */
118857e22627SCy Schubert 		remote_errbuf[plen] = '\0';
118957e22627SCy Schubert 	}
119057e22627SCy Schubert 	// Log the message
119157e22627SCy Schubert 	rpcapd_log(LOGPRIO_ERROR, "Error from client: %s", remote_errbuf);
119257e22627SCy Schubert 	return 0;
119357e22627SCy Schubert }
119457e22627SCy Schubert 
119557e22627SCy Schubert /*
119657e22627SCy Schubert  * This handles the RPCAP_MSG_AUTH_REQ message.
119757e22627SCy Schubert  * It checks if the authentication credentials supplied by the user are valid.
119857e22627SCy Schubert  *
119957e22627SCy Schubert  * This function is called if the daemon receives a RPCAP_MSG_AUTH_REQ
120057e22627SCy Schubert  * message in its authentication loop.  It reads the body of the
120157e22627SCy Schubert  * authentication message from the network and checks whether the
120257e22627SCy Schubert  * credentials are valid.
120357e22627SCy Schubert  *
120457e22627SCy Schubert  * \param sockctrl: the socket for the control connection.
120557e22627SCy Schubert  *
120657e22627SCy Schubert  * \param nullAuthAllowed: '1' if the NULL authentication is allowed.
120757e22627SCy Schubert  *
120857e22627SCy Schubert  * \param errbuf: a user-allocated buffer in which the error message
120957e22627SCy Schubert  * (if one) has to be written.  It must be at least PCAP_ERRBUF_SIZE
121057e22627SCy Schubert  * bytes long.
121157e22627SCy Schubert  *
121257e22627SCy Schubert  * \return '0' if everything is fine, '-1' if an unrecoverable error occurred,
121357e22627SCy Schubert  * or '-2' if the authentication failed.  For errors, an error message is
121457e22627SCy Schubert  * returned in the 'errbuf' variable; this gives a message for the
121557e22627SCy Schubert  * unrecoverable error or for the authentication failure.
121657e22627SCy Schubert  */
121757e22627SCy Schubert static int
daemon_msg_auth_req(struct daemon_slpars * pars,uint32 plen)121857e22627SCy Schubert daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
121957e22627SCy Schubert {
122057e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
122157e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
122257e22627SCy Schubert 	int status;
122357e22627SCy Schubert 	struct rpcap_auth auth;			// RPCAP authentication header
122457e22627SCy Schubert 	char sendbuf[RPCAP_NETBUF_SIZE];	// temporary buffer in which data to be sent is buffered
122557e22627SCy Schubert 	int sendbufidx = 0;			// index which keeps the number of bytes currently buffered
122657e22627SCy Schubert 	struct rpcap_authreply *authreply;	// authentication reply message
122757e22627SCy Schubert 
12286f9cba8fSJoseph Mingrone 	status = rpcapd_recv(pars->sockctrl, pars->ssl, (char *) &auth, sizeof(struct rpcap_auth), &plen, errmsgbuf);
122957e22627SCy Schubert 	if (status == -1)
123057e22627SCy Schubert 	{
123157e22627SCy Schubert 		return -1;
123257e22627SCy Schubert 	}
123357e22627SCy Schubert 	if (status == -2)
123457e22627SCy Schubert 	{
123557e22627SCy Schubert 		goto error;
123657e22627SCy Schubert 	}
123757e22627SCy Schubert 
123857e22627SCy Schubert 	switch (ntohs(auth.type))
123957e22627SCy Schubert 	{
124057e22627SCy Schubert 		case RPCAP_RMTAUTH_NULL:
124157e22627SCy Schubert 		{
124257e22627SCy Schubert 			if (!pars->nullAuthAllowed)
124357e22627SCy Schubert 			{
124457e22627SCy Schubert 				// Send the client an error reply.
12456f9cba8fSJoseph Mingrone 				snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
124657e22627SCy Schubert 				    "Authentication failed; NULL authentication not permitted.");
12476f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars->sockctrl, pars->ssl,
12486f9cba8fSJoseph Mingrone 				    0, PCAP_ERR_AUTH_FAILED, errmsgbuf, errbuf) == -1)
124957e22627SCy Schubert 				{
125057e22627SCy Schubert 					// That failed; log a message and give up.
125157e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
125257e22627SCy Schubert 					return -1;
125357e22627SCy Schubert 				}
125457e22627SCy Schubert 				goto error_noreply;
125557e22627SCy Schubert 			}
125657e22627SCy Schubert 			break;
125757e22627SCy Schubert 		}
125857e22627SCy Schubert 
125957e22627SCy Schubert 		case RPCAP_RMTAUTH_PWD:
126057e22627SCy Schubert 		{
126157e22627SCy Schubert 			char *username, *passwd;
126257e22627SCy Schubert 			uint32 usernamelen, passwdlen;
126357e22627SCy Schubert 
126457e22627SCy Schubert 			usernamelen = ntohs(auth.slen1);
126557e22627SCy Schubert 			username = (char *) malloc (usernamelen + 1);
126657e22627SCy Schubert 			if (username == NULL)
126757e22627SCy Schubert 			{
1268*afdbf109SJoseph Mingrone 				pcapint_fmt_errmsg_for_errno(errmsgbuf,
126957e22627SCy Schubert 				    PCAP_ERRBUF_SIZE, errno, "malloc() failed");
127057e22627SCy Schubert 				goto error;
127157e22627SCy Schubert 			}
12726f9cba8fSJoseph Mingrone 			status = rpcapd_recv(pars->sockctrl, pars->ssl, username, usernamelen, &plen, errmsgbuf);
127357e22627SCy Schubert 			if (status == -1)
127457e22627SCy Schubert 			{
127557e22627SCy Schubert 				free(username);
127657e22627SCy Schubert 				return -1;
127757e22627SCy Schubert 			}
127857e22627SCy Schubert 			if (status == -2)
127957e22627SCy Schubert 			{
128057e22627SCy Schubert 				free(username);
128157e22627SCy Schubert 				goto error;
128257e22627SCy Schubert 			}
128357e22627SCy Schubert 			username[usernamelen] = '\0';
128457e22627SCy Schubert 
128557e22627SCy Schubert 			passwdlen = ntohs(auth.slen2);
128657e22627SCy Schubert 			passwd = (char *) malloc (passwdlen + 1);
128757e22627SCy Schubert 			if (passwd == NULL)
128857e22627SCy Schubert 			{
1289*afdbf109SJoseph Mingrone 				pcapint_fmt_errmsg_for_errno(errmsgbuf,
129057e22627SCy Schubert 				    PCAP_ERRBUF_SIZE, errno, "malloc() failed");
129157e22627SCy Schubert 				free(username);
129257e22627SCy Schubert 				goto error;
129357e22627SCy Schubert 			}
12946f9cba8fSJoseph Mingrone 			status = rpcapd_recv(pars->sockctrl, pars->ssl, passwd, passwdlen, &plen, errmsgbuf);
129557e22627SCy Schubert 			if (status == -1)
129657e22627SCy Schubert 			{
129757e22627SCy Schubert 				free(username);
129857e22627SCy Schubert 				free(passwd);
129957e22627SCy Schubert 				return -1;
130057e22627SCy Schubert 			}
130157e22627SCy Schubert 			if (status == -2)
130257e22627SCy Schubert 			{
130357e22627SCy Schubert 				free(username);
130457e22627SCy Schubert 				free(passwd);
130557e22627SCy Schubert 				goto error;
130657e22627SCy Schubert 			}
130757e22627SCy Schubert 			passwd[passwdlen] = '\0';
130857e22627SCy Schubert 
130957e22627SCy Schubert 			if (daemon_AuthUserPwd(username, passwd, errmsgbuf))
131057e22627SCy Schubert 			{
131157e22627SCy Schubert 				//
131257e22627SCy Schubert 				// Authentication failed.  Let the client
131357e22627SCy Schubert 				// know.
131457e22627SCy Schubert 				//
131557e22627SCy Schubert 				free(username);
131657e22627SCy Schubert 				free(passwd);
13176f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars->sockctrl, pars->ssl,
13186f9cba8fSJoseph Mingrone 				    0, PCAP_ERR_AUTH_FAILED, errmsgbuf, errbuf) == -1)
131957e22627SCy Schubert 				{
132057e22627SCy Schubert 					// That failed; log a message and give up.
132157e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
132257e22627SCy Schubert 					return -1;
132357e22627SCy Schubert 				}
132457e22627SCy Schubert 
132557e22627SCy Schubert 				//
132657e22627SCy Schubert 				// Suspend for 1 second, so that they can't
132757e22627SCy Schubert 				// hammer us with repeated tries with an
132857e22627SCy Schubert 				// attack such as a dictionary attack.
132957e22627SCy Schubert 				//
133057e22627SCy Schubert 				// WARNING: this delay is inserted only
133157e22627SCy Schubert 				// at this point; if the client closes the
133257e22627SCy Schubert 				// connection and reconnects, the suspension
133357e22627SCy Schubert 				// time does not have any effect.
133457e22627SCy Schubert 				//
133557e22627SCy Schubert 				sleep_secs(RPCAP_SUSPEND_WRONGAUTH);
133657e22627SCy Schubert 				goto error_noreply;
133757e22627SCy Schubert 			}
133857e22627SCy Schubert 
133957e22627SCy Schubert 			free(username);
134057e22627SCy Schubert 			free(passwd);
134157e22627SCy Schubert 			break;
134257e22627SCy Schubert 			}
134357e22627SCy Schubert 
134457e22627SCy Schubert 		default:
13456f9cba8fSJoseph Mingrone 			snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
134657e22627SCy Schubert 			    "Authentication type not recognized.");
13476f9cba8fSJoseph Mingrone 			if (rpcap_senderror(pars->sockctrl, pars->ssl,
13486f9cba8fSJoseph Mingrone 			    0, PCAP_ERR_AUTH_TYPE_NOTSUP, errmsgbuf, errbuf) == -1)
134957e22627SCy Schubert 			{
135057e22627SCy Schubert 				// That failed; log a message and give up.
135157e22627SCy Schubert 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
135257e22627SCy Schubert 				return -1;
135357e22627SCy Schubert 			}
135457e22627SCy Schubert 			goto error_noreply;
135557e22627SCy Schubert 	}
135657e22627SCy Schubert 
135757e22627SCy Schubert 	// The authentication succeeded; let the client know.
135857e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
135957e22627SCy Schubert 	    RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
136057e22627SCy Schubert 		goto error;
136157e22627SCy Schubert 
136257e22627SCy Schubert 	rpcap_createhdr((struct rpcap_header *) sendbuf, 0,
136357e22627SCy Schubert 	    RPCAP_MSG_AUTH_REPLY, 0, sizeof(struct rpcap_authreply));
136457e22627SCy Schubert 
136557e22627SCy Schubert 	authreply = (struct rpcap_authreply *) &sendbuf[sendbufidx];
136657e22627SCy Schubert 
136757e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_authreply), NULL, &sendbufidx,
136857e22627SCy Schubert 	    RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
136957e22627SCy Schubert 		goto error;
137057e22627SCy Schubert 
137157e22627SCy Schubert 	//
13726f9cba8fSJoseph Mingrone 	// Indicate to our peer what versions we support and what our
13736f9cba8fSJoseph Mingrone 	// version of the byte-order magic is (which will tell the
13746f9cba8fSJoseph Mingrone 	// client whether our byte order differs from theirs, in which
13756f9cba8fSJoseph Mingrone 	// case they will need to byte-swap some fields in some
13766f9cba8fSJoseph Mingrone 	// link-layer types' headers).
137757e22627SCy Schubert 	//
137857e22627SCy Schubert 	memset(authreply, 0, sizeof(struct rpcap_authreply));
137957e22627SCy Schubert 	authreply->minvers = RPCAP_MIN_VERSION;
138057e22627SCy Schubert 	authreply->maxvers = RPCAP_MAX_VERSION;
13816f9cba8fSJoseph Mingrone 	authreply->byte_order_magic = RPCAP_BYTE_ORDER_MAGIC;
138257e22627SCy Schubert 
138357e22627SCy Schubert 	// Send the reply.
13846f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
138557e22627SCy Schubert 	{
13866f9cba8fSJoseph Mingrone 		// That failed; log a message and give up.
138757e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
138857e22627SCy Schubert 		return -1;
138957e22627SCy Schubert 	}
139057e22627SCy Schubert 
139157e22627SCy Schubert 	// Check if all the data has been read; if not, discard the data in excess
13926f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
139357e22627SCy Schubert 	{
139457e22627SCy Schubert 		return -1;
139557e22627SCy Schubert 	}
139657e22627SCy Schubert 
139757e22627SCy Schubert 	return 0;
139857e22627SCy Schubert 
139957e22627SCy Schubert error:
14006f9cba8fSJoseph Mingrone 	if (rpcap_senderror(pars->sockctrl, pars->ssl, 0, PCAP_ERR_AUTH,
14016f9cba8fSJoseph Mingrone 	    errmsgbuf, errbuf) == -1)
140257e22627SCy Schubert 	{
140357e22627SCy Schubert 		// That failed; log a message and give up.
140457e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
140557e22627SCy Schubert 		return -1;
140657e22627SCy Schubert 	}
140757e22627SCy Schubert 
140857e22627SCy Schubert error_noreply:
140957e22627SCy Schubert 	// Check if all the data has been read; if not, discard the data in excess
14106f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
141157e22627SCy Schubert 	{
141257e22627SCy Schubert 		return -1;
141357e22627SCy Schubert 	}
141457e22627SCy Schubert 
141557e22627SCy Schubert 	return -2;
141657e22627SCy Schubert }
141757e22627SCy Schubert 
141857e22627SCy Schubert static int
daemon_AuthUserPwd(char * username,char * password,char * errbuf)141957e22627SCy Schubert daemon_AuthUserPwd(char *username, char *password, char *errbuf)
142057e22627SCy Schubert {
142157e22627SCy Schubert #ifdef _WIN32
142257e22627SCy Schubert 	/*
142357e22627SCy Schubert 	 * Warning: the user which launches the process must have the
142457e22627SCy Schubert 	 * SE_TCB_NAME right.
142557e22627SCy Schubert 	 * This corresponds to have the "Act as part of the Operating System"
142657e22627SCy Schubert 	 * turned on (administrative tools, local security settings, local
142757e22627SCy Schubert 	 * policies, user right assignment)
142857e22627SCy Schubert 	 * However, it seems to me that if you run it as a service, this
142957e22627SCy Schubert 	 * right should be provided by default.
143057e22627SCy Schubert 	 *
143157e22627SCy Schubert 	 * XXX - hopefully, this returns errors such as ERROR_LOGON_FAILURE,
143257e22627SCy Schubert 	 * which merely indicates that the user name or password is
143357e22627SCy Schubert 	 * incorrect, not whether it's the user name or the password
143457e22627SCy Schubert 	 * that's incorrect, so a client that's trying to brute-force
143557e22627SCy Schubert 	 * accounts doesn't know whether it's the user name or the
143657e22627SCy Schubert 	 * password that's incorrect, so it doesn't know whether to
143757e22627SCy Schubert 	 * stop trying to log in with a given user name and move on
143857e22627SCy Schubert 	 * to another user name.
143957e22627SCy Schubert 	 */
144057e22627SCy Schubert 	DWORD error;
144157e22627SCy Schubert 	HANDLE Token;
144257e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to log
144357e22627SCy Schubert 
144457e22627SCy Schubert 	if (LogonUser(username, ".", password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &Token) == 0)
144557e22627SCy Schubert 	{
14466f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
144757e22627SCy Schubert 		error = GetLastError();
144857e22627SCy Schubert 		if (error != ERROR_LOGON_FAILURE)
144957e22627SCy Schubert 		{
145057e22627SCy Schubert 			// Some error other than an authentication error;
145157e22627SCy Schubert 			// log it.
1452*afdbf109SJoseph Mingrone 			pcapint_fmt_errmsg_for_win32_err(errmsgbuf,
145357e22627SCy Schubert 			    PCAP_ERRBUF_SIZE, error, "LogonUser() failed");
145457e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
145557e22627SCy Schubert 		}
145657e22627SCy Schubert 		return -1;
145757e22627SCy Schubert 	}
145857e22627SCy Schubert 
145957e22627SCy Schubert 	// This call should change the current thread to the selected user.
146057e22627SCy Schubert 	// I didn't test it.
146157e22627SCy Schubert 	if (ImpersonateLoggedOnUser(Token) == 0)
146257e22627SCy Schubert 	{
14636f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
1464*afdbf109SJoseph Mingrone 		pcapint_fmt_errmsg_for_win32_err(errmsgbuf, PCAP_ERRBUF_SIZE,
146557e22627SCy Schubert 		    GetLastError(), "ImpersonateLoggedOnUser() failed");
146657e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
146757e22627SCy Schubert 		CloseHandle(Token);
146857e22627SCy Schubert 		return -1;
146957e22627SCy Schubert 	}
147057e22627SCy Schubert 
147157e22627SCy Schubert 	CloseHandle(Token);
147257e22627SCy Schubert 	return 0;
147357e22627SCy Schubert 
147457e22627SCy Schubert #else
147557e22627SCy Schubert 	/*
147657e22627SCy Schubert 	 * See
147757e22627SCy Schubert 	 *
14786f9cba8fSJoseph Mingrone 	 *	https://www.unixpapa.com/incnote/passwd.html
147957e22627SCy Schubert 	 *
148057e22627SCy Schubert 	 * We use the Solaris/Linux shadow password authentication if
148157e22627SCy Schubert 	 * we have getspnam(), otherwise we just do traditional
148257e22627SCy Schubert 	 * authentication, which, on some platforms, might work, even
148357e22627SCy Schubert 	 * with shadow passwords, if we're running as root.  Traditional
1484*afdbf109SJoseph Mingrone 	 * authentication won't work if we're not running as root, as
148557e22627SCy Schubert 	 * I think these days all UN*Xes either won't return the password
148657e22627SCy Schubert 	 * at all with getpwnam() or will only do so if you're root.
148757e22627SCy Schubert 	 *
148857e22627SCy Schubert 	 * XXX - perhaps what we *should* be using is PAM, if we have
148957e22627SCy Schubert 	 * it.  That might hide all the details of username/password
149057e22627SCy Schubert 	 * authentication, whether it's done with a visible-to-root-
149157e22627SCy Schubert 	 * only password database or some other authentication mechanism,
149257e22627SCy Schubert 	 * behind its API.
149357e22627SCy Schubert 	 */
149457e22627SCy Schubert 	int error;
149557e22627SCy Schubert 	struct passwd *user;
149657e22627SCy Schubert 	char *user_password;
149757e22627SCy Schubert #ifdef HAVE_GETSPNAM
149857e22627SCy Schubert 	struct spwd *usersp;
149957e22627SCy Schubert #endif
150057e22627SCy Schubert 	char *crypt_password;
150157e22627SCy Schubert 
150257e22627SCy Schubert 	// This call is needed to get the uid
150357e22627SCy Schubert 	if ((user = getpwnam(username)) == NULL)
150457e22627SCy Schubert 	{
15056f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
150657e22627SCy Schubert 		return -1;
150757e22627SCy Schubert 	}
150857e22627SCy Schubert 
150957e22627SCy Schubert #ifdef HAVE_GETSPNAM
151057e22627SCy Schubert 	// This call is needed to get the password; otherwise 'x' is returned
151157e22627SCy Schubert 	if ((usersp = getspnam(username)) == NULL)
151257e22627SCy Schubert 	{
15136f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
151457e22627SCy Schubert 		return -1;
151557e22627SCy Schubert 	}
151657e22627SCy Schubert 	user_password = usersp->sp_pwdp;
151757e22627SCy Schubert #else
151857e22627SCy Schubert 	/*
151957e22627SCy Schubert 	 * XXX - what about other platforms?
152057e22627SCy Schubert 	 * The unixpapa.com page claims this Just Works on *BSD if you're
152157e22627SCy Schubert 	 * running as root - it's from 2000, so it doesn't indicate whether
152257e22627SCy Schubert 	 * macOS (which didn't come out until 2001, under the name Mac OS
152357e22627SCy Schubert 	 * X) behaves like the *BSDs or not, and might also work on AIX.
152457e22627SCy Schubert 	 * HP-UX does something else.
152557e22627SCy Schubert 	 *
152657e22627SCy Schubert 	 * Again, hopefully PAM hides all that.
152757e22627SCy Schubert 	 */
152857e22627SCy Schubert 	user_password = user->pw_passwd;
152957e22627SCy Schubert #endif
153057e22627SCy Schubert 
153157e22627SCy Schubert 	//
153257e22627SCy Schubert 	// The Single UNIX Specification says that if crypt() fails it
1533*afdbf109SJoseph Mingrone 	// sets errno, but some implementations that haven't been run
153457e22627SCy Schubert 	// through the SUS test suite might not do so.
153557e22627SCy Schubert 	//
153657e22627SCy Schubert 	errno = 0;
153757e22627SCy Schubert 	crypt_password = crypt(password, user_password);
153857e22627SCy Schubert 	if (crypt_password == NULL)
153957e22627SCy Schubert 	{
154057e22627SCy Schubert 		error = errno;
15416f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
154257e22627SCy Schubert 		if (error == 0)
154357e22627SCy Schubert 		{
154457e22627SCy Schubert 			// It didn't set errno.
154557e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "crypt() failed");
154657e22627SCy Schubert 		}
154757e22627SCy Schubert 		else
154857e22627SCy Schubert 		{
154957e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "crypt() failed: %s",
155057e22627SCy Schubert 			    strerror(error));
155157e22627SCy Schubert 		}
155257e22627SCy Schubert 		return -1;
155357e22627SCy Schubert 	}
155457e22627SCy Schubert 	if (strcmp(user_password, crypt_password) != 0)
155557e22627SCy Schubert 	{
15566f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
155757e22627SCy Schubert 		return -1;
155857e22627SCy Schubert 	}
155957e22627SCy Schubert 
156057e22627SCy Schubert 	if (setuid(user->pw_uid))
156157e22627SCy Schubert 	{
156257e22627SCy Schubert 		error = errno;
1563*afdbf109SJoseph Mingrone 		pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
156457e22627SCy Schubert 		    error, "setuid");
156557e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "setuid() failed: %s",
156657e22627SCy Schubert 		    strerror(error));
156757e22627SCy Schubert 		return -1;
156857e22627SCy Schubert 	}
156957e22627SCy Schubert 
157057e22627SCy Schubert /*	if (setgid(user->pw_gid))
157157e22627SCy Schubert 	{
157257e22627SCy Schubert 		error = errno;
1573*afdbf109SJoseph Mingrone 		pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
157457e22627SCy Schubert 		    errno, "setgid");
157557e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "setgid() failed: %s",
157657e22627SCy Schubert 		    strerror(error));
157757e22627SCy Schubert 		return -1;
157857e22627SCy Schubert 	}
157957e22627SCy Schubert */
158057e22627SCy Schubert 	return 0;
158157e22627SCy Schubert 
158257e22627SCy Schubert #endif
158357e22627SCy Schubert 
158457e22627SCy Schubert }
158557e22627SCy Schubert 
15866f9cba8fSJoseph Mingrone /*
15876f9cba8fSJoseph Mingrone  * Make sure that the reply length won't overflow 32 bits if we add the
15886f9cba8fSJoseph Mingrone  * specified amount to it.  If it won't, add that amount to it.
15896f9cba8fSJoseph Mingrone  *
15906f9cba8fSJoseph Mingrone  * We check whether replylen + itemlen > UINT32_MAX, but subtract itemlen
15916f9cba8fSJoseph Mingrone  * from both sides, to prevent overflow.
15926f9cba8fSJoseph Mingrone  */
15936f9cba8fSJoseph Mingrone #define CHECK_AND_INCREASE_REPLY_LEN(itemlen) \
15946f9cba8fSJoseph Mingrone 	if (replylen > UINT32_MAX - (itemlen)) { \
1595*afdbf109SJoseph Mingrone 		pcapint_strlcpy(errmsgbuf, "Reply length doesn't fit in 32 bits", \
15966f9cba8fSJoseph Mingrone 		    sizeof (errmsgbuf)); \
15976f9cba8fSJoseph Mingrone 		goto error; \
15986f9cba8fSJoseph Mingrone 	} \
15996f9cba8fSJoseph Mingrone 	replylen += (uint32)(itemlen)
16006f9cba8fSJoseph Mingrone 
160157e22627SCy Schubert static int
daemon_msg_findallif_req(uint8 ver,struct daemon_slpars * pars,uint32 plen)160257e22627SCy Schubert daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars, uint32 plen)
160357e22627SCy Schubert {
160457e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
160557e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
160657e22627SCy Schubert 	char sendbuf[RPCAP_NETBUF_SIZE];	// temporary buffer in which data to be sent is buffered
160757e22627SCy Schubert 	int sendbufidx = 0;			// index which keeps the number of bytes currently buffered
160857e22627SCy Schubert 	pcap_if_t *alldevs = NULL;		// pointer to the header of the interface chain
160957e22627SCy Schubert 	pcap_if_t *d;				// temp pointer needed to scan the interface chain
161057e22627SCy Schubert 	struct pcap_addr *address;		// pcap structure that keeps a network address of an interface
161157e22627SCy Schubert 	uint32 replylen;			// length of reply payload
161257e22627SCy Schubert 	uint16 nif = 0;				// counts the number of interface listed
161357e22627SCy Schubert 
161457e22627SCy Schubert 	// Discard the rest of the message; there shouldn't be any payload.
16156f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
161657e22627SCy Schubert 	{
161757e22627SCy Schubert 		// Network error.
161857e22627SCy Schubert 		return -1;
161957e22627SCy Schubert 	}
162057e22627SCy Schubert 
162157e22627SCy Schubert 	// Retrieve the device list
162257e22627SCy Schubert 	if (pcap_findalldevs(&alldevs, errmsgbuf) == -1)
162357e22627SCy Schubert 		goto error;
162457e22627SCy Schubert 
162557e22627SCy Schubert 	if (alldevs == NULL)
162657e22627SCy Schubert 	{
16276f9cba8fSJoseph Mingrone 		if (rpcap_senderror(pars->sockctrl, pars->ssl, ver,
16286f9cba8fSJoseph Mingrone 			PCAP_ERR_NOREMOTEIF,
162957e22627SCy Schubert 			"No interfaces found! Make sure libpcap/WinPcap is properly installed"
163057e22627SCy Schubert 			" and you have the right to access to the remote device.",
163157e22627SCy Schubert 			errbuf) == -1)
163257e22627SCy Schubert 		{
163357e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
163457e22627SCy Schubert 			return -1;
163557e22627SCy Schubert 		}
163657e22627SCy Schubert 		return 0;
163757e22627SCy Schubert 	}
163857e22627SCy Schubert 
163957e22627SCy Schubert 	// This checks the number of interfaces and computes the total
164057e22627SCy Schubert 	// length of the payload.
164157e22627SCy Schubert 	replylen = 0;
164257e22627SCy Schubert 	for (d = alldevs; d != NULL; d = d->next)
164357e22627SCy Schubert 	{
164457e22627SCy Schubert 		nif++;
164557e22627SCy Schubert 
16466f9cba8fSJoseph Mingrone 		if (d->description) {
16476f9cba8fSJoseph Mingrone 			size_t stringlen = strlen(d->description);
16486f9cba8fSJoseph Mingrone 			if (stringlen > UINT16_MAX) {
1649*afdbf109SJoseph Mingrone 				pcapint_strlcpy(errmsgbuf,
16506f9cba8fSJoseph Mingrone 				    "Description length doesn't fit in 16 bits",
16516f9cba8fSJoseph Mingrone 				    sizeof (errmsgbuf));
16526f9cba8fSJoseph Mingrone 				goto error;
16536f9cba8fSJoseph Mingrone 			}
16546f9cba8fSJoseph Mingrone 			CHECK_AND_INCREASE_REPLY_LEN(stringlen);
16556f9cba8fSJoseph Mingrone 		}
16566f9cba8fSJoseph Mingrone 		if (d->name) {
16576f9cba8fSJoseph Mingrone 			size_t stringlen = strlen(d->name);
16586f9cba8fSJoseph Mingrone 			if (stringlen > UINT16_MAX) {
1659*afdbf109SJoseph Mingrone 				pcapint_strlcpy(errmsgbuf,
16606f9cba8fSJoseph Mingrone 				    "Name length doesn't fit in 16 bits",
16616f9cba8fSJoseph Mingrone 				    sizeof (errmsgbuf));
16626f9cba8fSJoseph Mingrone 				goto error;
16636f9cba8fSJoseph Mingrone 			}
16646f9cba8fSJoseph Mingrone 			CHECK_AND_INCREASE_REPLY_LEN(stringlen);
16656f9cba8fSJoseph Mingrone 		}
166657e22627SCy Schubert 
16676f9cba8fSJoseph Mingrone 		CHECK_AND_INCREASE_REPLY_LEN(sizeof(struct rpcap_findalldevs_if));
166857e22627SCy Schubert 
16696f9cba8fSJoseph Mingrone 		uint16_t naddrs = 0;
167057e22627SCy Schubert 		for (address = d->addresses; address != NULL; address = address->next)
167157e22627SCy Schubert 		{
167257e22627SCy Schubert 			/*
167357e22627SCy Schubert 			 * Send only IPv4 and IPv6 addresses over the wire.
167457e22627SCy Schubert 			 */
167557e22627SCy Schubert 			switch (address->addr->sa_family)
167657e22627SCy Schubert 			{
167757e22627SCy Schubert 			case AF_INET:
167857e22627SCy Schubert #ifdef AF_INET6
167957e22627SCy Schubert 			case AF_INET6:
168057e22627SCy Schubert #endif
16816f9cba8fSJoseph Mingrone 				CHECK_AND_INCREASE_REPLY_LEN(sizeof(struct rpcap_sockaddr) * 4);
16826f9cba8fSJoseph Mingrone 				if (naddrs == UINT16_MAX) {
1683*afdbf109SJoseph Mingrone 					pcapint_strlcpy(errmsgbuf,
16846f9cba8fSJoseph Mingrone 					    "Number of interfaces doesn't fit in 16 bits",
16856f9cba8fSJoseph Mingrone 					    sizeof (errmsgbuf));
16866f9cba8fSJoseph Mingrone 					goto error;
16876f9cba8fSJoseph Mingrone 				}
16886f9cba8fSJoseph Mingrone 				naddrs++;
168957e22627SCy Schubert 				break;
169057e22627SCy Schubert 
169157e22627SCy Schubert 			default:
169257e22627SCy Schubert 				break;
169357e22627SCy Schubert 			}
169457e22627SCy Schubert 		}
169557e22627SCy Schubert 	}
169657e22627SCy Schubert 
16976f9cba8fSJoseph Mingrone 	// RPCAP findalldevs reply
169857e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
169957e22627SCy Schubert 	    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf,
170057e22627SCy Schubert 	    PCAP_ERRBUF_SIZE) == -1)
170157e22627SCy Schubert 		goto error;
170257e22627SCy Schubert 
170357e22627SCy Schubert 	rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
170457e22627SCy Schubert 	    RPCAP_MSG_FINDALLIF_REPLY, nif, replylen);
170557e22627SCy Schubert 
170657e22627SCy Schubert 	// send the interface list
170757e22627SCy Schubert 	for (d = alldevs; d != NULL; d = d->next)
170857e22627SCy Schubert 	{
170957e22627SCy Schubert 		uint16 lname, ldescr;
171057e22627SCy Schubert 
17116f9cba8fSJoseph Mingrone 		// Note: the findalldevs_if entries are *not* neatly
17126f9cba8fSJoseph Mingrone 		// aligned on 4-byte boundaries, because they're
17136f9cba8fSJoseph Mingrone 		// preceded by strings that aren't padded to 4-byte
17146f9cba8fSJoseph Mingrone 		// boundaries, so we cannot just cast output buffer
17156f9cba8fSJoseph Mingrone 		// boundaries to struct rpcap_findalldevs_if pointers
17166f9cba8fSJoseph Mingrone 		// and store into them - we must fill in a structure and
17176f9cba8fSJoseph Mingrone 		// then copy the structure to the buffer, as not all
17186f9cba8fSJoseph Mingrone 		// systems support unaligned access (some, such as
17196f9cba8fSJoseph Mingrone 		// SPARC, crash; others, such as Arm, may just ignore
17206f9cba8fSJoseph Mingrone 		// the lower-order bits).
17216f9cba8fSJoseph Mingrone 		struct rpcap_findalldevs_if findalldevs_if;
172257e22627SCy Schubert 
17236f9cba8fSJoseph Mingrone 		/*
17246f9cba8fSJoseph Mingrone 		 * We've already established that the string lengths
17256f9cba8fSJoseph Mingrone 		 * fit in 16 bits.
17266f9cba8fSJoseph Mingrone 		 */
17276f9cba8fSJoseph Mingrone 		if (d->description)
17286f9cba8fSJoseph Mingrone 			ldescr = (uint16) strlen(d->description);
17296f9cba8fSJoseph Mingrone 		else
17306f9cba8fSJoseph Mingrone 			ldescr = 0;
17316f9cba8fSJoseph Mingrone 		if (d->name)
17326f9cba8fSJoseph Mingrone 			lname = (uint16) strlen(d->name);
17336f9cba8fSJoseph Mingrone 		else
17346f9cba8fSJoseph Mingrone 			lname = 0;
173557e22627SCy Schubert 
17366f9cba8fSJoseph Mingrone 		findalldevs_if.desclen = htons(ldescr);
17376f9cba8fSJoseph Mingrone 		findalldevs_if.namelen = htons(lname);
17386f9cba8fSJoseph Mingrone 		findalldevs_if.flags = htonl(d->flags);
173957e22627SCy Schubert 
17406f9cba8fSJoseph Mingrone 		uint16_t naddrs = 0;
174157e22627SCy Schubert 		for (address = d->addresses; address != NULL; address = address->next)
174257e22627SCy Schubert 		{
174357e22627SCy Schubert 			/*
174457e22627SCy Schubert 			 * Send only IPv4 and IPv6 addresses over the wire.
174557e22627SCy Schubert 			 */
174657e22627SCy Schubert 			switch (address->addr->sa_family)
174757e22627SCy Schubert 			{
174857e22627SCy Schubert 			case AF_INET:
174957e22627SCy Schubert #ifdef AF_INET6
175057e22627SCy Schubert 			case AF_INET6:
175157e22627SCy Schubert #endif
17526f9cba8fSJoseph Mingrone 				naddrs++;
175357e22627SCy Schubert 				break;
175457e22627SCy Schubert 
175557e22627SCy Schubert 			default:
175657e22627SCy Schubert 				break;
175757e22627SCy Schubert 			}
175857e22627SCy Schubert 		}
17596f9cba8fSJoseph Mingrone 		findalldevs_if.naddr = htons(naddrs);
17606f9cba8fSJoseph Mingrone 		findalldevs_if.dummy = 0;
17616f9cba8fSJoseph Mingrone 
17626f9cba8fSJoseph Mingrone 		if (sock_bufferize(&findalldevs_if, sizeof(struct rpcap_findalldevs_if), sendbuf,
17636f9cba8fSJoseph Mingrone 		    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errmsgbuf,
17646f9cba8fSJoseph Mingrone 		    PCAP_ERRBUF_SIZE) == -1)
17656f9cba8fSJoseph Mingrone 			goto error;
176657e22627SCy Schubert 
176757e22627SCy Schubert 		if (sock_bufferize(d->name, lname, sendbuf, &sendbufidx,
176857e22627SCy Schubert 		    RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errmsgbuf,
176957e22627SCy Schubert 		    PCAP_ERRBUF_SIZE) == -1)
177057e22627SCy Schubert 			goto error;
177157e22627SCy Schubert 
177257e22627SCy Schubert 		if (sock_bufferize(d->description, ldescr, sendbuf, &sendbufidx,
177357e22627SCy Schubert 		    RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errmsgbuf,
177457e22627SCy Schubert 		    PCAP_ERRBUF_SIZE) == -1)
177557e22627SCy Schubert 			goto error;
177657e22627SCy Schubert 
177757e22627SCy Schubert 		// send all addresses
177857e22627SCy Schubert 		for (address = d->addresses; address != NULL; address = address->next)
177957e22627SCy Schubert 		{
178057e22627SCy Schubert 			struct rpcap_sockaddr *sockaddr;
178157e22627SCy Schubert 
178257e22627SCy Schubert 			/*
178357e22627SCy Schubert 			 * Send only IPv4 and IPv6 addresses over the wire.
178457e22627SCy Schubert 			 */
178557e22627SCy Schubert 			switch (address->addr->sa_family)
178657e22627SCy Schubert 			{
178757e22627SCy Schubert 			case AF_INET:
178857e22627SCy Schubert #ifdef AF_INET6
178957e22627SCy Schubert 			case AF_INET6:
179057e22627SCy Schubert #endif
179157e22627SCy Schubert 				sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
179257e22627SCy Schubert 				if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
179357e22627SCy Schubert 				    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
179457e22627SCy Schubert 					goto error;
179557e22627SCy Schubert 				daemon_seraddr((struct sockaddr_storage *) address->addr, sockaddr);
179657e22627SCy Schubert 
179757e22627SCy Schubert 				sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
179857e22627SCy Schubert 				if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
179957e22627SCy Schubert 				    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
180057e22627SCy Schubert 					goto error;
180157e22627SCy Schubert 				daemon_seraddr((struct sockaddr_storage *) address->netmask, sockaddr);
180257e22627SCy Schubert 
180357e22627SCy Schubert 				sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
180457e22627SCy Schubert 				if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
180557e22627SCy Schubert 				    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
180657e22627SCy Schubert 					goto error;
180757e22627SCy Schubert 				daemon_seraddr((struct sockaddr_storage *) address->broadaddr, sockaddr);
180857e22627SCy Schubert 
180957e22627SCy Schubert 				sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
181057e22627SCy Schubert 				if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
181157e22627SCy Schubert 				    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
181257e22627SCy Schubert 					goto error;
181357e22627SCy Schubert 				daemon_seraddr((struct sockaddr_storage *) address->dstaddr, sockaddr);
181457e22627SCy Schubert 				break;
181557e22627SCy Schubert 
181657e22627SCy Schubert 			default:
181757e22627SCy Schubert 				break;
181857e22627SCy Schubert 			}
181957e22627SCy Schubert 		}
182057e22627SCy Schubert 	}
182157e22627SCy Schubert 
182257e22627SCy Schubert 	// We no longer need the device list. Free it.
182357e22627SCy Schubert 	pcap_freealldevs(alldevs);
182457e22627SCy Schubert 
182557e22627SCy Schubert 	// Send a final command that says "now send it!"
18266f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
182757e22627SCy Schubert 	{
182857e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
182957e22627SCy Schubert 		return -1;
183057e22627SCy Schubert 	}
183157e22627SCy Schubert 
183257e22627SCy Schubert 	return 0;
183357e22627SCy Schubert 
183457e22627SCy Schubert error:
183557e22627SCy Schubert 	if (alldevs)
183657e22627SCy Schubert 		pcap_freealldevs(alldevs);
183757e22627SCy Schubert 
18386f9cba8fSJoseph Mingrone 	if (rpcap_senderror(pars->sockctrl, pars->ssl, ver,
18396f9cba8fSJoseph Mingrone 	    PCAP_ERR_FINDALLIF, errmsgbuf, errbuf) == -1)
184057e22627SCy Schubert 	{
184157e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
184257e22627SCy Schubert 		return -1;
184357e22627SCy Schubert 	}
184457e22627SCy Schubert 	return 0;
184557e22627SCy Schubert }
184657e22627SCy Schubert 
184757e22627SCy Schubert /*
184857e22627SCy Schubert 	\param plen: the length of the current message (needed in order to be able
184957e22627SCy Schubert 	to discard excess data in the message, if present)
185057e22627SCy Schubert */
185157e22627SCy Schubert static int
daemon_msg_open_req(uint8 ver,struct daemon_slpars * pars,uint32 plen,char * source,size_t sourcelen)185257e22627SCy Schubert daemon_msg_open_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
185357e22627SCy Schubert     char *source, size_t sourcelen)
185457e22627SCy Schubert {
185557e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
185657e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
185757e22627SCy Schubert 	pcap_t *fp;				// pcap_t main variable
185857e22627SCy Schubert 	int nread;
185957e22627SCy Schubert 	char sendbuf[RPCAP_NETBUF_SIZE];	// temporary buffer in which data to be sent is buffered
186057e22627SCy Schubert 	int sendbufidx = 0;			// index which keeps the number of bytes currently buffered
186157e22627SCy Schubert 	struct rpcap_openreply *openreply;	// open reply message
186257e22627SCy Schubert 
186357e22627SCy Schubert 	if (plen > sourcelen - 1)
186457e22627SCy Schubert 	{
18656f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Source string too long");
186657e22627SCy Schubert 		goto error;
186757e22627SCy Schubert 	}
186857e22627SCy Schubert 
18696f9cba8fSJoseph Mingrone 	nread = sock_recv(pars->sockctrl, pars->ssl, source, plen,
187057e22627SCy Schubert 	    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
187157e22627SCy Schubert 	if (nread == -1)
187257e22627SCy Schubert 	{
187357e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
187457e22627SCy Schubert 		return -1;
187557e22627SCy Schubert 	}
187657e22627SCy Schubert 	source[nread] = '\0';
187757e22627SCy Schubert 	plen -= nread;
187857e22627SCy Schubert 
187957e22627SCy Schubert 	// Is this a URL rather than a device?
188057e22627SCy Schubert 	// If so, reject it.
188157e22627SCy Schubert 	if (is_url(source))
188257e22627SCy Schubert 	{
18836f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Source string refers to a remote device");
188457e22627SCy Schubert 		goto error;
188557e22627SCy Schubert 	}
188657e22627SCy Schubert 
188757e22627SCy Schubert 	// Open the selected device
188857e22627SCy Schubert 	// This is a fake open, since we do that only to get the needed parameters, then we close the device again
188957e22627SCy Schubert 	if ((fp = pcap_open_live(source,
189057e22627SCy Schubert 			1500 /* fake snaplen */,
18916f9cba8fSJoseph Mingrone 			0 /* no promisc */,
189257e22627SCy Schubert 			1000 /* fake timeout */,
189357e22627SCy Schubert 			errmsgbuf)) == NULL)
189457e22627SCy Schubert 		goto error;
189557e22627SCy Schubert 
189657e22627SCy Schubert 	// Now, I can send a RPCAP open reply message
189757e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
189857e22627SCy Schubert 	    RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
189957e22627SCy Schubert 		goto error;
190057e22627SCy Schubert 
190157e22627SCy Schubert 	rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
190257e22627SCy Schubert 	    RPCAP_MSG_OPEN_REPLY, 0, sizeof(struct rpcap_openreply));
190357e22627SCy Schubert 
190457e22627SCy Schubert 	openreply = (struct rpcap_openreply *) &sendbuf[sendbufidx];
190557e22627SCy Schubert 
190657e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_openreply), NULL, &sendbufidx,
190757e22627SCy Schubert 	    RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
190857e22627SCy Schubert 		goto error;
190957e22627SCy Schubert 
191057e22627SCy Schubert 	memset(openreply, 0, sizeof(struct rpcap_openreply));
191157e22627SCy Schubert 	openreply->linktype = htonl(pcap_datalink(fp));
19126f9cba8fSJoseph Mingrone 	/*
19136f9cba8fSJoseph Mingrone 	 * This is always 0 for live captures; we no longer support it
19146f9cba8fSJoseph Mingrone 	 * as something we read from capture files and supply to
19156f9cba8fSJoseph Mingrone 	 * clients, but we have to send it over the wire, as open
19166f9cba8fSJoseph Mingrone 	 * replies are expected to have 8 bytes of payload by
19176f9cba8fSJoseph Mingrone 	 * existing clients.
19186f9cba8fSJoseph Mingrone 	 */
19196f9cba8fSJoseph Mingrone 	openreply->tzoff = 0;
192057e22627SCy Schubert 
192157e22627SCy Schubert 	// We're done with the pcap_t.
192257e22627SCy Schubert 	pcap_close(fp);
192357e22627SCy Schubert 
192457e22627SCy Schubert 	// Send the reply.
19256f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
192657e22627SCy Schubert 	{
192757e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
192857e22627SCy Schubert 		return -1;
192957e22627SCy Schubert 	}
193057e22627SCy Schubert 	return 0;
193157e22627SCy Schubert 
193257e22627SCy Schubert error:
19336f9cba8fSJoseph Mingrone 	if (rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_OPEN,
193457e22627SCy Schubert 	    errmsgbuf, errbuf) == -1)
193557e22627SCy Schubert 	{
193657e22627SCy Schubert 		// That failed; log a message and give up.
193757e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
193857e22627SCy Schubert 		return -1;
193957e22627SCy Schubert 	}
194057e22627SCy Schubert 
194157e22627SCy Schubert 	// Check if all the data has been read; if not, discard the data in excess
19426f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
194357e22627SCy Schubert 	{
194457e22627SCy Schubert 		return -1;
194557e22627SCy Schubert 	}
194657e22627SCy Schubert 	return 0;
194757e22627SCy Schubert }
194857e22627SCy Schubert 
194957e22627SCy Schubert /*
195057e22627SCy Schubert 	\param plen: the length of the current message (needed in order to be able
195157e22627SCy Schubert 	to discard excess data in the message, if present)
195257e22627SCy Schubert */
195357e22627SCy Schubert static int
daemon_msg_startcap_req(uint8 ver,struct daemon_slpars * pars,uint32 plen,char * source,struct session ** sessionp,struct rpcap_sampling * samp_param _U_,int uses_ssl)195457e22627SCy Schubert daemon_msg_startcap_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
195557e22627SCy Schubert     char *source, struct session **sessionp,
19566f9cba8fSJoseph Mingrone     struct rpcap_sampling *samp_param _U_, int uses_ssl)
195757e22627SCy Schubert {
195857e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
195957e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
196057e22627SCy Schubert 	char portdata[PCAP_BUF_SIZE];		// temp variable needed to derive the data port
196157e22627SCy Schubert 	char peerhost[PCAP_BUF_SIZE];		// temp variable needed to derive the host name of our peer
196257e22627SCy Schubert 	struct session *session = NULL;		// saves state of session
196357e22627SCy Schubert 	int status;
196457e22627SCy Schubert 	char sendbuf[RPCAP_NETBUF_SIZE];	// temporary buffer in which data to be sent is buffered
196557e22627SCy Schubert 	int sendbufidx = 0;			// index which keeps the number of bytes currently buffered
196657e22627SCy Schubert 
196757e22627SCy Schubert 	// socket-related variables
196857e22627SCy Schubert 	struct addrinfo hints;			// temp, needed to open a socket connection
196957e22627SCy Schubert 	struct addrinfo *addrinfo;		// temp, needed to open a socket connection
197057e22627SCy Schubert 	struct sockaddr_storage saddr;		// temp, needed to retrieve the network data port chosen on the local machine
197157e22627SCy Schubert 	socklen_t saddrlen;			// temp, needed to retrieve the network data port chosen on the local machine
197257e22627SCy Schubert 	int ret;				// return value from functions
197357e22627SCy Schubert 
197457e22627SCy Schubert 	// RPCAP-related variables
197557e22627SCy Schubert 	struct rpcap_startcapreq startcapreq;		// start capture request message
197657e22627SCy Schubert 	struct rpcap_startcapreply *startcapreply;	// start capture reply message
197757e22627SCy Schubert 	int serveropen_dp;							// keeps who is going to open the data connection
197857e22627SCy Schubert 
197957e22627SCy Schubert 	addrinfo = NULL;
198057e22627SCy Schubert 
19816f9cba8fSJoseph Mingrone 	status = rpcapd_recv(pars->sockctrl, pars->ssl, (char *) &startcapreq,
198257e22627SCy Schubert 	    sizeof(struct rpcap_startcapreq), &plen, errmsgbuf);
198357e22627SCy Schubert 	if (status == -1)
198457e22627SCy Schubert 	{
198557e22627SCy Schubert 		goto fatal_error;
198657e22627SCy Schubert 	}
198757e22627SCy Schubert 	if (status == -2)
198857e22627SCy Schubert 	{
198957e22627SCy Schubert 		goto error;
199057e22627SCy Schubert 	}
199157e22627SCy Schubert 
199257e22627SCy Schubert 	startcapreq.flags = ntohs(startcapreq.flags);
199357e22627SCy Schubert 
19946f9cba8fSJoseph Mingrone 	// Check that the client does not ask for UDP is the server has been asked
19956f9cba8fSJoseph Mingrone 	// to enforce encryption, as SSL is not supported yet with UDP:
19966f9cba8fSJoseph Mingrone 	if (uses_ssl && (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM))
19976f9cba8fSJoseph Mingrone 	{
19986f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
19996f9cba8fSJoseph Mingrone 		    "SSL not supported with UDP forward of remote packets");
20006f9cba8fSJoseph Mingrone 		goto error;
20016f9cba8fSJoseph Mingrone 	}
20026f9cba8fSJoseph Mingrone 
200357e22627SCy Schubert 	// Create a session structure
200457e22627SCy Schubert 	session = malloc(sizeof(struct session));
200557e22627SCy Schubert 	if (session == NULL)
200657e22627SCy Schubert 	{
20076f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Can't allocate session structure");
200857e22627SCy Schubert 		goto error;
200957e22627SCy Schubert 	}
201057e22627SCy Schubert 
201157e22627SCy Schubert 	session->sockdata = INVALID_SOCKET;
20126f9cba8fSJoseph Mingrone 	session->ctrl_ssl = session->data_ssl = NULL;
201357e22627SCy Schubert 	// We don't have a thread yet.
201457e22627SCy Schubert 	session->have_thread = 0;
201557e22627SCy Schubert 	//
201657e22627SCy Schubert 	// We *shouldn't* have to initialize the thread indicator
201757e22627SCy Schubert 	// itself, because the compiler *should* realize that we
201857e22627SCy Schubert 	// only use this if have_thread isn't 0, but we *do* have
201957e22627SCy Schubert 	// to do it, because not all compilers *do* realize that.
202057e22627SCy Schubert 	//
202157e22627SCy Schubert 	// There is no "invalid thread handle" value for a UN*X
202257e22627SCy Schubert 	// pthread_t, so we just zero it out.
202357e22627SCy Schubert 	//
202457e22627SCy Schubert #ifdef _WIN32
202557e22627SCy Schubert 	session->thread = INVALID_HANDLE_VALUE;
202657e22627SCy Schubert #else
202757e22627SCy Schubert 	memset(&session->thread, 0, sizeof(session->thread));
202857e22627SCy Schubert #endif
202957e22627SCy Schubert 
203057e22627SCy Schubert 	// Open the selected device
203157e22627SCy Schubert 	if ((session->fp = pcap_open_live(source,
203257e22627SCy Schubert 			ntohl(startcapreq.snaplen),
203357e22627SCy Schubert 			(startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_PROMISC) ? 1 : 0 /* local device, other flags not needed */,
203457e22627SCy Schubert 			ntohl(startcapreq.read_timeout),
203557e22627SCy Schubert 			errmsgbuf)) == NULL)
203657e22627SCy Schubert 		goto error;
203757e22627SCy Schubert 
203857e22627SCy Schubert #if 0
203957e22627SCy Schubert 	// Apply sampling parameters
204057e22627SCy Schubert 	fp->rmt_samp.method = samp_param->method;
204157e22627SCy Schubert 	fp->rmt_samp.value = samp_param->value;
204257e22627SCy Schubert #endif
204357e22627SCy Schubert 
204457e22627SCy Schubert 	/*
204557e22627SCy Schubert 	We're in active mode if:
204657e22627SCy Schubert 	- we're using TCP, and the user wants us to be in active mode
204757e22627SCy Schubert 	- we're using UDP
204857e22627SCy Schubert 	*/
204957e22627SCy Schubert 	serveropen_dp = (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_SERVEROPEN) || (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) || pars->isactive;
205057e22627SCy Schubert 
205157e22627SCy Schubert 	/*
205257e22627SCy Schubert 	Gets the sockaddr structure referred to the other peer in the ctrl connection
205357e22627SCy Schubert 
205457e22627SCy Schubert 	We need that because:
205557e22627SCy Schubert 	- if we're in passive mode, we need to know the address family we want to use
205657e22627SCy Schubert 	(the same used for the ctrl socket)
205757e22627SCy Schubert 	- if we're in active mode, we need to know the network address of the other host
205857e22627SCy Schubert 	we want to connect to
205957e22627SCy Schubert 	*/
206057e22627SCy Schubert 	saddrlen = sizeof(struct sockaddr_storage);
206157e22627SCy Schubert 	if (getpeername(pars->sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
206257e22627SCy Schubert 	{
20636f9cba8fSJoseph Mingrone 		sock_geterrmsg(errmsgbuf, PCAP_ERRBUF_SIZE,
20646f9cba8fSJoseph Mingrone 		    "getpeername() failed");
206557e22627SCy Schubert 		goto error;
206657e22627SCy Schubert 	}
206757e22627SCy Schubert 
206857e22627SCy Schubert 	memset(&hints, 0, sizeof(struct addrinfo));
206957e22627SCy Schubert 	hints.ai_socktype = (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
207057e22627SCy Schubert 	hints.ai_family = saddr.ss_family;
207157e22627SCy Schubert 
207257e22627SCy Schubert 	// Now we have to create a new socket to send packets
207357e22627SCy Schubert 	if (serveropen_dp)		// Data connection is opened by the server toward the client
207457e22627SCy Schubert 	{
20756f9cba8fSJoseph Mingrone 		snprintf(portdata, sizeof portdata, "%d", ntohs(startcapreq.portdata));
207657e22627SCy Schubert 
207757e22627SCy Schubert 		// Get the name of the other peer (needed to connect to that specific network address)
207857e22627SCy Schubert 		if (getnameinfo((struct sockaddr *) &saddr, saddrlen, peerhost,
207957e22627SCy Schubert 				sizeof(peerhost), NULL, 0, NI_NUMERICHOST))
208057e22627SCy Schubert 		{
20816f9cba8fSJoseph Mingrone 			sock_geterrmsg(errmsgbuf, PCAP_ERRBUF_SIZE,
20826f9cba8fSJoseph Mingrone 			    "getnameinfo() failed");
208357e22627SCy Schubert 			goto error;
208457e22627SCy Schubert 		}
208557e22627SCy Schubert 
2086*afdbf109SJoseph Mingrone 		addrinfo = sock_initaddress(peerhost, portdata, &hints,
2087*afdbf109SJoseph Mingrone 		    errmsgbuf, PCAP_ERRBUF_SIZE);
2088*afdbf109SJoseph Mingrone 		if (addrinfo == NULL)
208957e22627SCy Schubert 			goto error;
209057e22627SCy Schubert 
20916f9cba8fSJoseph Mingrone 		if ((session->sockdata = sock_open(peerhost, addrinfo, SOCKOPEN_CLIENT, 0, errmsgbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
209257e22627SCy Schubert 			goto error;
209357e22627SCy Schubert 	}
209457e22627SCy Schubert 	else		// Data connection is opened by the client toward the server
209557e22627SCy Schubert 	{
209657e22627SCy Schubert 		hints.ai_flags = AI_PASSIVE;
209757e22627SCy Schubert 
20986f9cba8fSJoseph Mingrone 		// Make the server socket pick up a free network port for us
2099*afdbf109SJoseph Mingrone 		addrinfo = sock_initaddress(NULL, NULL, &hints, errmsgbuf,
2100*afdbf109SJoseph Mingrone 		    PCAP_ERRBUF_SIZE);
2101*afdbf109SJoseph Mingrone 		if (addrinfo == NULL)
210257e22627SCy Schubert 			goto error;
210357e22627SCy Schubert 
21046f9cba8fSJoseph Mingrone 		if ((session->sockdata = sock_open(NULL, addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, errmsgbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
210557e22627SCy Schubert 			goto error;
210657e22627SCy Schubert 
210757e22627SCy Schubert 		// get the complete sockaddr structure used in the data connection
210857e22627SCy Schubert 		saddrlen = sizeof(struct sockaddr_storage);
210957e22627SCy Schubert 		if (getsockname(session->sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
211057e22627SCy Schubert 		{
21116f9cba8fSJoseph Mingrone 			sock_geterrmsg(errmsgbuf, PCAP_ERRBUF_SIZE,
21126f9cba8fSJoseph Mingrone 			    "getsockname() failed");
211357e22627SCy Schubert 			goto error;
211457e22627SCy Schubert 		}
211557e22627SCy Schubert 
211657e22627SCy Schubert 		// Get the local port the system picked up
211757e22627SCy Schubert 		if (getnameinfo((struct sockaddr *) &saddr, saddrlen, NULL,
211857e22627SCy Schubert 				0, portdata, sizeof(portdata), NI_NUMERICSERV))
211957e22627SCy Schubert 		{
21206f9cba8fSJoseph Mingrone 			sock_geterrmsg(errmsgbuf, PCAP_ERRBUF_SIZE,
21216f9cba8fSJoseph Mingrone 			    "getnameinfo() failed");
212257e22627SCy Schubert 			goto error;
212357e22627SCy Schubert 		}
212457e22627SCy Schubert 	}
212557e22627SCy Schubert 
212657e22627SCy Schubert 	// addrinfo is no longer used
212757e22627SCy Schubert 	freeaddrinfo(addrinfo);
212857e22627SCy Schubert 	addrinfo = NULL;
212957e22627SCy Schubert 
213057e22627SCy Schubert 	// Needed to send an error on the ctrl connection
213157e22627SCy Schubert 	session->sockctrl = pars->sockctrl;
21326f9cba8fSJoseph Mingrone 	session->ctrl_ssl = pars->ssl;
213357e22627SCy Schubert 	session->protocol_version = ver;
213457e22627SCy Schubert 
213557e22627SCy Schubert 	// Now I can set the filter
21366f9cba8fSJoseph Mingrone 	ret = daemon_unpackapplyfilter(pars->sockctrl, pars->ssl, session, &plen, errmsgbuf);
213757e22627SCy Schubert 	if (ret == -1)
213857e22627SCy Schubert 	{
213957e22627SCy Schubert 		// Fatal error.  A message has been logged; just give up.
214057e22627SCy Schubert 		goto fatal_error;
214157e22627SCy Schubert 	}
214257e22627SCy Schubert 	if (ret == -2)
214357e22627SCy Schubert 	{
214457e22627SCy Schubert 		// Non-fatal error.  Send an error message to the client.
214557e22627SCy Schubert 		goto error;
214657e22627SCy Schubert 	}
214757e22627SCy Schubert 
214857e22627SCy Schubert 	// Now, I can send a RPCAP start capture reply message
214957e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
215057e22627SCy Schubert 	    RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
215157e22627SCy Schubert 		goto error;
215257e22627SCy Schubert 
215357e22627SCy Schubert 	rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
215457e22627SCy Schubert 	    RPCAP_MSG_STARTCAP_REPLY, 0, sizeof(struct rpcap_startcapreply));
215557e22627SCy Schubert 
215657e22627SCy Schubert 	startcapreply = (struct rpcap_startcapreply *) &sendbuf[sendbufidx];
215757e22627SCy Schubert 
215857e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_startcapreply), NULL,
215957e22627SCy Schubert 	    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
216057e22627SCy Schubert 		goto error;
216157e22627SCy Schubert 
216257e22627SCy Schubert 	memset(startcapreply, 0, sizeof(struct rpcap_startcapreply));
216357e22627SCy Schubert 	startcapreply->bufsize = htonl(pcap_bufsize(session->fp));
216457e22627SCy Schubert 
216557e22627SCy Schubert 	if (!serveropen_dp)
216657e22627SCy Schubert 	{
216757e22627SCy Schubert 		unsigned short port = (unsigned short)strtoul(portdata,NULL,10);
216857e22627SCy Schubert 		startcapreply->portdata = htons(port);
216957e22627SCy Schubert 	}
217057e22627SCy Schubert 
21716f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
217257e22627SCy Schubert 	{
217357e22627SCy Schubert 		// That failed; log a message and give up.
217457e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
217557e22627SCy Schubert 		goto fatal_error;
217657e22627SCy Schubert 	}
217757e22627SCy Schubert 
217857e22627SCy Schubert 	if (!serveropen_dp)
217957e22627SCy Schubert 	{
2180*afdbf109SJoseph Mingrone 		PCAP_SOCKET socktemp;	// We need another socket, since we're going to accept() a connection
218157e22627SCy Schubert 
218257e22627SCy Schubert 		// Connection creation
218357e22627SCy Schubert 		saddrlen = sizeof(struct sockaddr_storage);
218457e22627SCy Schubert 
218557e22627SCy Schubert 		socktemp = accept(session->sockdata, (struct sockaddr *) &saddr, &saddrlen);
218657e22627SCy Schubert 
218757e22627SCy Schubert 		if (socktemp == INVALID_SOCKET)
218857e22627SCy Schubert 		{
21896f9cba8fSJoseph Mingrone 			sock_geterrmsg(errbuf, PCAP_ERRBUF_SIZE,
21906f9cba8fSJoseph Mingrone 			   "accept() failed");
219157e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "Accept of data connection failed: %s",
219257e22627SCy Schubert 			    errbuf);
219357e22627SCy Schubert 			goto error;
219457e22627SCy Schubert 		}
219557e22627SCy Schubert 
219657e22627SCy Schubert 		// Now that I accepted the connection, the server socket is no longer needed
219757e22627SCy Schubert 		sock_close(session->sockdata, NULL, 0);
219857e22627SCy Schubert 		session->sockdata = socktemp;
219957e22627SCy Schubert 	}
220057e22627SCy Schubert 
22016f9cba8fSJoseph Mingrone 	SSL *ssl = NULL;
22026f9cba8fSJoseph Mingrone 	if (uses_ssl)
22036f9cba8fSJoseph Mingrone 	{
22046f9cba8fSJoseph Mingrone #ifdef HAVE_OPENSSL
22056f9cba8fSJoseph Mingrone 		/* In both active or passive cases, wait for the client to initiate the
22066f9cba8fSJoseph Mingrone 		 * TLS handshake. Yes during that time the control socket will not be
22076f9cba8fSJoseph Mingrone 		 * served, but the same was true from the above call to accept(). */
22086f9cba8fSJoseph Mingrone 		ssl = ssl_promotion(1, session->sockdata, errbuf, PCAP_ERRBUF_SIZE);
22096f9cba8fSJoseph Mingrone 		if (! ssl)
22106f9cba8fSJoseph Mingrone 		{
22116f9cba8fSJoseph Mingrone 			rpcapd_log(LOGPRIO_ERROR, "TLS handshake failed: %s", errbuf);
22126f9cba8fSJoseph Mingrone 			goto error;
22136f9cba8fSJoseph Mingrone 		}
22146f9cba8fSJoseph Mingrone #endif
22156f9cba8fSJoseph Mingrone 	}
22166f9cba8fSJoseph Mingrone 	session->data_ssl = ssl;
22176f9cba8fSJoseph Mingrone 
221857e22627SCy Schubert 	// Now we have to create a new thread to receive packets
221957e22627SCy Schubert #ifdef _WIN32
222057e22627SCy Schubert 	session->thread = (HANDLE)_beginthreadex(NULL, 0, daemon_thrdatamain,
222157e22627SCy Schubert 	    (void *) session, 0, NULL);
222257e22627SCy Schubert 	if (session->thread == 0)
222357e22627SCy Schubert 	{
22246f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread");
222557e22627SCy Schubert 		goto error;
222657e22627SCy Schubert 	}
222757e22627SCy Schubert #else
222857e22627SCy Schubert 	ret = pthread_create(&session->thread, NULL, daemon_thrdatamain,
222957e22627SCy Schubert 	    (void *) session);
223057e22627SCy Schubert 	if (ret != 0)
223157e22627SCy Schubert 	{
2232*afdbf109SJoseph Mingrone 		pcapint_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
223357e22627SCy Schubert 		    ret, "Error creating the data thread");
223457e22627SCy Schubert 		goto error;
223557e22627SCy Schubert 	}
223657e22627SCy Schubert #endif
223757e22627SCy Schubert 	session->have_thread = 1;
223857e22627SCy Schubert 
223957e22627SCy Schubert 	// Check if all the data has been read; if not, discard the data in excess
22406f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
224157e22627SCy Schubert 		goto fatal_error;
224257e22627SCy Schubert 
224357e22627SCy Schubert 	*sessionp = session;
224457e22627SCy Schubert 	return 0;
224557e22627SCy Schubert 
224657e22627SCy Schubert error:
224757e22627SCy Schubert 	//
224857e22627SCy Schubert 	// Not a fatal error, so send the client an error message and
224957e22627SCy Schubert 	// keep serving client requests.
225057e22627SCy Schubert 	//
225157e22627SCy Schubert 	*sessionp = NULL;
225257e22627SCy Schubert 
225357e22627SCy Schubert 	if (addrinfo)
225457e22627SCy Schubert 		freeaddrinfo(addrinfo);
225557e22627SCy Schubert 
225657e22627SCy Schubert 	if (session)
225757e22627SCy Schubert 	{
225857e22627SCy Schubert 		session_close(session);
225957e22627SCy Schubert 		free(session);
226057e22627SCy Schubert 	}
226157e22627SCy Schubert 
22626f9cba8fSJoseph Mingrone 	if (rpcap_senderror(pars->sockctrl, pars->ssl, ver,
22636f9cba8fSJoseph Mingrone 	    PCAP_ERR_STARTCAPTURE, errmsgbuf, errbuf) == -1)
226457e22627SCy Schubert 	{
226557e22627SCy Schubert 		// That failed; log a message and give up.
226657e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
226757e22627SCy Schubert 		return -1;
226857e22627SCy Schubert 	}
226957e22627SCy Schubert 
227057e22627SCy Schubert 	// Check if all the data has been read; if not, discard the data in excess
22716f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
227257e22627SCy Schubert 	{
227357e22627SCy Schubert 		// Network error.
227457e22627SCy Schubert 		return -1;
227557e22627SCy Schubert 	}
227657e22627SCy Schubert 
227757e22627SCy Schubert 	return 0;
227857e22627SCy Schubert 
227957e22627SCy Schubert fatal_error:
228057e22627SCy Schubert 	//
228157e22627SCy Schubert 	// Fatal network error, so don't try to communicate with
228257e22627SCy Schubert 	// the client, just give up.
228357e22627SCy Schubert 	//
228457e22627SCy Schubert 	*sessionp = NULL;
228557e22627SCy Schubert 
228657e22627SCy Schubert 	if (session)
228757e22627SCy Schubert 	{
228857e22627SCy Schubert 		session_close(session);
228957e22627SCy Schubert 		free(session);
229057e22627SCy Schubert 	}
229157e22627SCy Schubert 
229257e22627SCy Schubert 	return -1;
229357e22627SCy Schubert }
229457e22627SCy Schubert 
229557e22627SCy Schubert static int
daemon_msg_endcap_req(uint8 ver,struct daemon_slpars * pars,struct session * session)229657e22627SCy Schubert daemon_msg_endcap_req(uint8 ver, struct daemon_slpars *pars,
229757e22627SCy Schubert     struct session *session)
229857e22627SCy Schubert {
229957e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
230057e22627SCy Schubert 	struct rpcap_header header;
230157e22627SCy Schubert 
230257e22627SCy Schubert 	session_close(session);
230357e22627SCy Schubert 
230457e22627SCy Schubert 	rpcap_createhdr(&header, ver, RPCAP_MSG_ENDCAP_REPLY, 0, 0);
230557e22627SCy Schubert 
23066f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
230757e22627SCy Schubert 	{
230857e22627SCy Schubert 		// That failed; log a message and give up.
230957e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
231057e22627SCy Schubert 		return -1;
231157e22627SCy Schubert 	}
231257e22627SCy Schubert 
231357e22627SCy Schubert 	return 0;
231457e22627SCy Schubert }
231557e22627SCy Schubert 
231657e22627SCy Schubert //
231757e22627SCy Schubert // We impose a limit on the filter program size, so that, on Windows,
231857e22627SCy Schubert // where there's only one server process with multiple threads, it's
231957e22627SCy Schubert // harder to eat all the server address space by sending larger filter
232057e22627SCy Schubert // programs.  (This isn't an issue on UN*X, where there are multiple
232157e22627SCy Schubert // server processes, one per client connection.)
232257e22627SCy Schubert //
232357e22627SCy Schubert // We pick a value that limits each filter to 64K; that value is twice
232457e22627SCy Schubert // the in-kernel limit for Linux and 16 times the in-kernel limit for
232557e22627SCy Schubert // *BSD and macOS.
232657e22627SCy Schubert //
232757e22627SCy Schubert // It also prevents an overflow on 32-bit platforms when calculating
232857e22627SCy Schubert // the total size of the filter program.  (It's not an issue on 64-bit
232957e22627SCy Schubert // platforms with a 64-bit size_t, as the filter size is 32 bits.)
233057e22627SCy Schubert //
233157e22627SCy Schubert #define RPCAP_BPF_MAXINSNS	8192
233257e22627SCy Schubert 
233357e22627SCy Schubert static int
daemon_unpackapplyfilter(PCAP_SOCKET sockctrl,SSL * ctrl_ssl,struct session * session,uint32 * plenp,char * errmsgbuf)2334*afdbf109SJoseph Mingrone daemon_unpackapplyfilter(PCAP_SOCKET sockctrl, SSL *ctrl_ssl, struct session *session, uint32 *plenp, char *errmsgbuf)
233557e22627SCy Schubert {
233657e22627SCy Schubert 	int status;
233757e22627SCy Schubert 	struct rpcap_filter filter;
233857e22627SCy Schubert 	struct rpcap_filterbpf_insn insn;
233957e22627SCy Schubert 	struct bpf_insn *bf_insn;
234057e22627SCy Schubert 	struct bpf_program bf_prog;
234157e22627SCy Schubert 	unsigned int i;
234257e22627SCy Schubert 
23436f9cba8fSJoseph Mingrone 	status = rpcapd_recv(sockctrl, ctrl_ssl, (char *) &filter,
234457e22627SCy Schubert 	    sizeof(struct rpcap_filter), plenp, errmsgbuf);
234557e22627SCy Schubert 	if (status == -1)
234657e22627SCy Schubert 	{
234757e22627SCy Schubert 		return -1;
234857e22627SCy Schubert 	}
234957e22627SCy Schubert 	if (status == -2)
235057e22627SCy Schubert 	{
235157e22627SCy Schubert 		return -2;
235257e22627SCy Schubert 	}
235357e22627SCy Schubert 
235457e22627SCy Schubert 	bf_prog.bf_len = ntohl(filter.nitems);
235557e22627SCy Schubert 
235657e22627SCy Schubert 	if (ntohs(filter.filtertype) != RPCAP_UPDATEFILTER_BPF)
235757e22627SCy Schubert 	{
23586f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Only BPF/NPF filters are currently supported");
235957e22627SCy Schubert 		return -2;
236057e22627SCy Schubert 	}
236157e22627SCy Schubert 
236257e22627SCy Schubert 	if (bf_prog.bf_len > RPCAP_BPF_MAXINSNS)
236357e22627SCy Schubert 	{
23646f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
23656f9cba8fSJoseph Mingrone 		    "Filter program is larger than the maximum size of %d instructions",
236657e22627SCy Schubert 		    RPCAP_BPF_MAXINSNS);
236757e22627SCy Schubert 		return -2;
236857e22627SCy Schubert 	}
236957e22627SCy Schubert 	bf_insn = (struct bpf_insn *) malloc (sizeof(struct bpf_insn) * bf_prog.bf_len);
237057e22627SCy Schubert 	if (bf_insn == NULL)
237157e22627SCy Schubert 	{
2372*afdbf109SJoseph Mingrone 		pcapint_fmt_errmsg_for_errno(errmsgbuf, PCAP_ERRBUF_SIZE,
237357e22627SCy Schubert 		    errno, "malloc() failed");
237457e22627SCy Schubert 		return -2;
237557e22627SCy Schubert 	}
237657e22627SCy Schubert 
237757e22627SCy Schubert 	bf_prog.bf_insns = bf_insn;
237857e22627SCy Schubert 
237957e22627SCy Schubert 	for (i = 0; i < bf_prog.bf_len; i++)
238057e22627SCy Schubert 	{
23816f9cba8fSJoseph Mingrone 		status = rpcapd_recv(sockctrl, ctrl_ssl, (char *) &insn,
238257e22627SCy Schubert 		    sizeof(struct rpcap_filterbpf_insn), plenp, errmsgbuf);
238357e22627SCy Schubert 		if (status == -1)
238457e22627SCy Schubert 		{
238557e22627SCy Schubert 			return -1;
238657e22627SCy Schubert 		}
238757e22627SCy Schubert 		if (status == -2)
238857e22627SCy Schubert 		{
238957e22627SCy Schubert 			return -2;
239057e22627SCy Schubert 		}
239157e22627SCy Schubert 
239257e22627SCy Schubert 		bf_insn->code = ntohs(insn.code);
239357e22627SCy Schubert 		bf_insn->jf = insn.jf;
239457e22627SCy Schubert 		bf_insn->jt = insn.jt;
239557e22627SCy Schubert 		bf_insn->k = ntohl(insn.k);
239657e22627SCy Schubert 
239757e22627SCy Schubert 		bf_insn++;
239857e22627SCy Schubert 	}
239957e22627SCy Schubert 
24006f9cba8fSJoseph Mingrone 	//
24016f9cba8fSJoseph Mingrone 	// XXX - pcap_setfilter() should do the validation for us.
24026f9cba8fSJoseph Mingrone 	//
240357e22627SCy Schubert 	if (bpf_validate(bf_prog.bf_insns, bf_prog.bf_len) == 0)
240457e22627SCy Schubert 	{
24056f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "The filter contains bogus instructions");
240657e22627SCy Schubert 		return -2;
240757e22627SCy Schubert 	}
240857e22627SCy Schubert 
240957e22627SCy Schubert 	if (pcap_setfilter(session->fp, &bf_prog))
241057e22627SCy Schubert 	{
24116f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "RPCAP error: %s", pcap_geterr(session->fp));
241257e22627SCy Schubert 		return -2;
241357e22627SCy Schubert 	}
241457e22627SCy Schubert 
241557e22627SCy Schubert 	return 0;
241657e22627SCy Schubert }
241757e22627SCy Schubert 
241857e22627SCy Schubert static int
daemon_msg_updatefilter_req(uint8 ver,struct daemon_slpars * pars,struct session * session,uint32 plen)241957e22627SCy Schubert daemon_msg_updatefilter_req(uint8 ver, struct daemon_slpars *pars,
242057e22627SCy Schubert     struct session *session, uint32 plen)
242157e22627SCy Schubert {
242257e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];
242357e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
242457e22627SCy Schubert 	int ret;				// status of daemon_unpackapplyfilter()
242557e22627SCy Schubert 	struct rpcap_header header;		// keeps the answer to the updatefilter command
242657e22627SCy Schubert 
24276f9cba8fSJoseph Mingrone 	ret = daemon_unpackapplyfilter(pars->sockctrl, pars->ssl, session, &plen, errmsgbuf);
242857e22627SCy Schubert 	if (ret == -1)
242957e22627SCy Schubert 	{
243057e22627SCy Schubert 		// Fatal error.  A message has been logged; just give up.
243157e22627SCy Schubert 		return -1;
243257e22627SCy Schubert 	}
243357e22627SCy Schubert 	if (ret == -2)
243457e22627SCy Schubert 	{
243557e22627SCy Schubert 		// Non-fatal error.  Send an error reply to the client.
243657e22627SCy Schubert 		goto error;
243757e22627SCy Schubert 	}
243857e22627SCy Schubert 
243957e22627SCy Schubert 	// Check if all the data has been read; if not, discard the data in excess
24406f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
244157e22627SCy Schubert 	{
244257e22627SCy Schubert 		// Network error.
244357e22627SCy Schubert 		return -1;
244457e22627SCy Schubert 	}
244557e22627SCy Schubert 
244657e22627SCy Schubert 	// A response is needed, otherwise the other host does not know that everything went well
244757e22627SCy Schubert 	rpcap_createhdr(&header, ver, RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);
244857e22627SCy Schubert 
24496f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE))
245057e22627SCy Schubert 	{
24516f9cba8fSJoseph Mingrone 		// That failed; log a message and give up.
245257e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
245357e22627SCy Schubert 		return -1;
245457e22627SCy Schubert 	}
245557e22627SCy Schubert 
245657e22627SCy Schubert 	return 0;
245757e22627SCy Schubert 
245857e22627SCy Schubert error:
24596f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
246057e22627SCy Schubert 	{
246157e22627SCy Schubert 		return -1;
246257e22627SCy Schubert 	}
24636f9cba8fSJoseph Mingrone 	rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_UPDATEFILTER,
246457e22627SCy Schubert 	    errmsgbuf, NULL);
246557e22627SCy Schubert 
246657e22627SCy Schubert 	return 0;
246757e22627SCy Schubert }
246857e22627SCy Schubert 
246957e22627SCy Schubert /*!
247057e22627SCy Schubert 	\brief Received the sampling parameters from remote host and it stores in the pcap_t structure.
247157e22627SCy Schubert */
247257e22627SCy Schubert static int
daemon_msg_setsampling_req(uint8 ver,struct daemon_slpars * pars,uint32 plen,struct rpcap_sampling * samp_param)247357e22627SCy Schubert daemon_msg_setsampling_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
247457e22627SCy Schubert     struct rpcap_sampling *samp_param)
247557e22627SCy Schubert {
247657e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
247757e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];
247857e22627SCy Schubert 	struct rpcap_header header;
247957e22627SCy Schubert 	struct rpcap_sampling rpcap_samp;
248057e22627SCy Schubert 	int status;
248157e22627SCy Schubert 
24826f9cba8fSJoseph Mingrone 	status = rpcapd_recv(pars->sockctrl, pars->ssl, (char *) &rpcap_samp, sizeof(struct rpcap_sampling), &plen, errmsgbuf);
248357e22627SCy Schubert 	if (status == -1)
248457e22627SCy Schubert 	{
248557e22627SCy Schubert 		return -1;
248657e22627SCy Schubert 	}
248757e22627SCy Schubert 	if (status == -2)
248857e22627SCy Schubert 	{
248957e22627SCy Schubert 		goto error;
249057e22627SCy Schubert 	}
249157e22627SCy Schubert 
249257e22627SCy Schubert 	// Save these settings in the pcap_t
249357e22627SCy Schubert 	samp_param->method = rpcap_samp.method;
249457e22627SCy Schubert 	samp_param->value = ntohl(rpcap_samp.value);
249557e22627SCy Schubert 
249657e22627SCy Schubert 	// A response is needed, otherwise the other host does not know that everything went well
249757e22627SCy Schubert 	rpcap_createhdr(&header, ver, RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);
249857e22627SCy Schubert 
24996f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
250057e22627SCy Schubert 	{
25016f9cba8fSJoseph Mingrone 		// That failed; log a message and give up.
250257e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
250357e22627SCy Schubert 		return -1;
250457e22627SCy Schubert 	}
250557e22627SCy Schubert 
25066f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
250757e22627SCy Schubert 	{
250857e22627SCy Schubert 		return -1;
250957e22627SCy Schubert 	}
251057e22627SCy Schubert 
251157e22627SCy Schubert 	return 0;
251257e22627SCy Schubert 
251357e22627SCy Schubert error:
25146f9cba8fSJoseph Mingrone 	if (rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_SETSAMPLING,
251557e22627SCy Schubert 	    errmsgbuf, errbuf) == -1)
251657e22627SCy Schubert 	{
251757e22627SCy Schubert 		// That failed; log a message and give up.
251857e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
251957e22627SCy Schubert 		return -1;
252057e22627SCy Schubert 	}
252157e22627SCy Schubert 
252257e22627SCy Schubert 	// Check if all the data has been read; if not, discard the data in excess
25236f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
252457e22627SCy Schubert 	{
252557e22627SCy Schubert 		return -1;
252657e22627SCy Schubert 	}
252757e22627SCy Schubert 
252857e22627SCy Schubert 	return 0;
252957e22627SCy Schubert }
253057e22627SCy Schubert 
253157e22627SCy Schubert static int
daemon_msg_stats_req(uint8 ver,struct daemon_slpars * pars,struct session * session,uint32 plen,struct pcap_stat * stats,unsigned int svrcapt)253257e22627SCy Schubert daemon_msg_stats_req(uint8 ver, struct daemon_slpars *pars,
253357e22627SCy Schubert     struct session *session, uint32 plen, struct pcap_stat *stats,
253457e22627SCy Schubert     unsigned int svrcapt)
253557e22627SCy Schubert {
253657e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
253757e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
253857e22627SCy Schubert 	char sendbuf[RPCAP_NETBUF_SIZE];	// temporary buffer in which data to be sent is buffered
253957e22627SCy Schubert 	int sendbufidx = 0;			// index which keeps the number of bytes currently buffered
254057e22627SCy Schubert 	struct rpcap_stats *netstats;		// statistics sent on the network
254157e22627SCy Schubert 
254257e22627SCy Schubert 	// Checks that the header does not contain other data; if so, discard it
25436f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
254457e22627SCy Schubert 	{
254557e22627SCy Schubert 		// Network error.
254657e22627SCy Schubert 		return -1;
254757e22627SCy Schubert 	}
254857e22627SCy Schubert 
254957e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
255057e22627SCy Schubert 	    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
255157e22627SCy Schubert 		goto error;
255257e22627SCy Schubert 
255357e22627SCy Schubert 	rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
255457e22627SCy Schubert 	    RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));
255557e22627SCy Schubert 
255657e22627SCy Schubert 	netstats = (struct rpcap_stats *) &sendbuf[sendbufidx];
255757e22627SCy Schubert 
255857e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL,
255957e22627SCy Schubert 	    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
256057e22627SCy Schubert 		goto error;
256157e22627SCy Schubert 
256257e22627SCy Schubert 	if (session && session->fp)
256357e22627SCy Schubert 	{
256457e22627SCy Schubert 		if (pcap_stats(session->fp, stats) == -1)
256557e22627SCy Schubert 		{
25666f9cba8fSJoseph Mingrone 			snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "%s", pcap_geterr(session->fp));
256757e22627SCy Schubert 			goto error;
256857e22627SCy Schubert 		}
256957e22627SCy Schubert 
257057e22627SCy Schubert 		netstats->ifdrop = htonl(stats->ps_ifdrop);
257157e22627SCy Schubert 		netstats->ifrecv = htonl(stats->ps_recv);
257257e22627SCy Schubert 		netstats->krnldrop = htonl(stats->ps_drop);
257357e22627SCy Schubert 		netstats->svrcapt = htonl(session->TotCapt);
257457e22627SCy Schubert 	}
257557e22627SCy Schubert 	else
257657e22627SCy Schubert 	{
257757e22627SCy Schubert 		// We have to keep compatibility with old applications,
257857e22627SCy Schubert 		// which ask for statistics also when the capture has
257957e22627SCy Schubert 		// already stopped.
258057e22627SCy Schubert 		netstats->ifdrop = htonl(stats->ps_ifdrop);
258157e22627SCy Schubert 		netstats->ifrecv = htonl(stats->ps_recv);
258257e22627SCy Schubert 		netstats->krnldrop = htonl(stats->ps_drop);
258357e22627SCy Schubert 		netstats->svrcapt = htonl(svrcapt);
258457e22627SCy Schubert 	}
258557e22627SCy Schubert 
258657e22627SCy Schubert 	// Send the packet
25876f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
258857e22627SCy Schubert 	{
258957e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
259057e22627SCy Schubert 		return -1;
259157e22627SCy Schubert 	}
259257e22627SCy Schubert 
259357e22627SCy Schubert 	return 0;
259457e22627SCy Schubert 
259557e22627SCy Schubert error:
25966f9cba8fSJoseph Mingrone 	rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_GETSTATS,
259757e22627SCy Schubert 	    errmsgbuf, NULL);
259857e22627SCy Schubert 	return 0;
259957e22627SCy Schubert }
260057e22627SCy Schubert 
260157e22627SCy Schubert #ifdef _WIN32
260257e22627SCy Schubert static unsigned __stdcall
260357e22627SCy Schubert #else
260457e22627SCy Schubert static void *
260557e22627SCy Schubert #endif
daemon_thrdatamain(void * ptr)260657e22627SCy Schubert daemon_thrdatamain(void *ptr)
260757e22627SCy Schubert {
260857e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE + 1];	// error buffer
260957e22627SCy Schubert 	struct session *session;		// pointer to the struct session for this session
261057e22627SCy Schubert 	int retval;							// general variable used to keep the return value of other functions
261157e22627SCy Schubert 	struct rpcap_pkthdr *net_pkt_header;// header of the packet
261257e22627SCy Schubert 	struct pcap_pkthdr *pkt_header;		// pointer to the buffer that contains the header of the current packet
261357e22627SCy Schubert 	u_char *pkt_data;					// pointer to the buffer that contains the current packet
261457e22627SCy Schubert 	size_t sendbufsize;			// size for the send buffer
261557e22627SCy Schubert 	char *sendbuf;						// temporary buffer in which data to be sent is buffered
261657e22627SCy Schubert 	int sendbufidx;						// index which keeps the number of bytes currently buffered
261757e22627SCy Schubert 	int status;
261857e22627SCy Schubert #ifndef _WIN32
261957e22627SCy Schubert 	sigset_t sigusr1;			// signal set with just SIGUSR1
262057e22627SCy Schubert #endif
262157e22627SCy Schubert 
262257e22627SCy Schubert 	session = (struct session *) ptr;
262357e22627SCy Schubert 
262457e22627SCy Schubert 	session->TotCapt = 0;			// counter which is incremented each time a packet is received
262557e22627SCy Schubert 
262657e22627SCy Schubert 	// Initialize errbuf
262757e22627SCy Schubert 	memset(errbuf, 0, sizeof(errbuf));
262857e22627SCy Schubert 
262957e22627SCy Schubert 	//
263057e22627SCy Schubert 	// We need a buffer large enough to hold a buffer large enough
263157e22627SCy Schubert 	// for a maximum-size packet for this pcap_t.
263257e22627SCy Schubert 	//
263357e22627SCy Schubert 	if (pcap_snapshot(session->fp) < 0)
263457e22627SCy Schubert 	{
263557e22627SCy Schubert 		//
263657e22627SCy Schubert 		// The snapshot length is negative.
263757e22627SCy Schubert 		// This "should not happen".
263857e22627SCy Schubert 		//
263957e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR,
264057e22627SCy Schubert 		    "Unable to allocate the buffer for this child thread: snapshot length of %d is negative",
264157e22627SCy Schubert 		        pcap_snapshot(session->fp));
264257e22627SCy Schubert 		sendbuf = NULL;	// we can't allocate a buffer, so nothing to free
264357e22627SCy Schubert 		goto error;
264457e22627SCy Schubert 	}
264557e22627SCy Schubert 	//
264657e22627SCy Schubert 	// size_t is unsigned, and the result of pcap_snapshot() is signed;
264757e22627SCy Schubert 	// on no platform that we support is int larger than size_t.
264857e22627SCy Schubert 	// This means that, unless the extra information we prepend to
264957e22627SCy Schubert 	// a maximum-sized packet is impossibly large, the sum of the
265057e22627SCy Schubert 	// snapshot length and the size of that extra information will
265157e22627SCy Schubert 	// fit in a size_t.
265257e22627SCy Schubert 	//
265357e22627SCy Schubert 	// So we don't need to make sure that sendbufsize will overflow.
265457e22627SCy Schubert 	//
26556f9cba8fSJoseph Mingrone 	// However, we *do* need to make sure its value fits in an int,
26566f9cba8fSJoseph Mingrone 	// because sock_send() can't send more than INT_MAX bytes (it could
26576f9cba8fSJoseph Mingrone 	// do so on 64-bit UN*Xes, but can't do so on Windows, not even
26586f9cba8fSJoseph Mingrone 	// 64-bit Windows, as the send() buffer size argument is an int
26596f9cba8fSJoseph Mingrone 	// in Winsock).
26606f9cba8fSJoseph Mingrone 	//
266157e22627SCy Schubert 	sendbufsize = sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr) + pcap_snapshot(session->fp);
26626f9cba8fSJoseph Mingrone 	if (sendbufsize > INT_MAX)
26636f9cba8fSJoseph Mingrone 	{
26646f9cba8fSJoseph Mingrone 		rpcapd_log(LOGPRIO_ERROR,
26656f9cba8fSJoseph Mingrone 		    "Buffer size for this child thread would be larger than %d",
26666f9cba8fSJoseph Mingrone 		    INT_MAX);
26676f9cba8fSJoseph Mingrone 		sendbuf = NULL;	// we haven't allocated a buffer, so nothing to free
26686f9cba8fSJoseph Mingrone 		goto error;
26696f9cba8fSJoseph Mingrone 	}
267057e22627SCy Schubert 	sendbuf = (char *) malloc (sendbufsize);
267157e22627SCy Schubert 	if (sendbuf == NULL)
267257e22627SCy Schubert 	{
267357e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR,
267457e22627SCy Schubert 		    "Unable to allocate the buffer for this child thread");
267557e22627SCy Schubert 		goto error;
267657e22627SCy Schubert 	}
267757e22627SCy Schubert 
267857e22627SCy Schubert #ifndef _WIN32
267957e22627SCy Schubert 	//
268057e22627SCy Schubert 	// Set the signal set to include just SIGUSR1, and block that
268157e22627SCy Schubert 	// signal; we only want it unblocked when we're reading
268257e22627SCy Schubert 	// packets - we dn't want any other system calls, such as
268357e22627SCy Schubert 	// ones being used to send to the client or to log messages,
268457e22627SCy Schubert 	// to be interrupted.
268557e22627SCy Schubert 	//
268657e22627SCy Schubert 	sigemptyset(&sigusr1);
268757e22627SCy Schubert 	sigaddset(&sigusr1, SIGUSR1);
268857e22627SCy Schubert 	pthread_sigmask(SIG_BLOCK, &sigusr1, NULL);
268957e22627SCy Schubert #endif
269057e22627SCy Schubert 
269157e22627SCy Schubert 	// Retrieve the packets
269257e22627SCy Schubert 	for (;;)
269357e22627SCy Schubert 	{
269457e22627SCy Schubert #ifndef _WIN32
269557e22627SCy Schubert 		//
269657e22627SCy Schubert 		// Unblock SIGUSR1 while we might be waiting for packets.
269757e22627SCy Schubert 		//
269857e22627SCy Schubert 		pthread_sigmask(SIG_UNBLOCK, &sigusr1, NULL);
269957e22627SCy Schubert #endif
270057e22627SCy Schubert 		retval = pcap_next_ex(session->fp, &pkt_header, (const u_char **) &pkt_data);	// cast to avoid a compiler warning
270157e22627SCy Schubert #ifndef _WIN32
270257e22627SCy Schubert 		//
270357e22627SCy Schubert 		// Now block it again.
270457e22627SCy Schubert 		//
270557e22627SCy Schubert 		pthread_sigmask(SIG_BLOCK, &sigusr1, NULL);
270657e22627SCy Schubert #endif
270757e22627SCy Schubert 		if (retval < 0)
270857e22627SCy Schubert 			break;		// error
270957e22627SCy Schubert 		if (retval == 0)	// Read timeout elapsed
271057e22627SCy Schubert 			continue;
271157e22627SCy Schubert 
271257e22627SCy Schubert 		sendbufidx = 0;
271357e22627SCy Schubert 
271457e22627SCy Schubert 		// Bufferize the general header
271557e22627SCy Schubert 		if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
27166f9cba8fSJoseph Mingrone 		    &sendbufidx, (int)sendbufsize, SOCKBUF_CHECKONLY, errbuf,
271757e22627SCy Schubert 		    PCAP_ERRBUF_SIZE) == -1)
271857e22627SCy Schubert 		{
271957e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR,
272057e22627SCy Schubert 			    "sock_bufferize() error sending packet message: %s",
272157e22627SCy Schubert 			    errbuf);
272257e22627SCy Schubert 			goto error;
272357e22627SCy Schubert 		}
272457e22627SCy Schubert 
272557e22627SCy Schubert 		rpcap_createhdr((struct rpcap_header *) sendbuf,
272657e22627SCy Schubert 		    session->protocol_version, RPCAP_MSG_PACKET, 0,
272757e22627SCy Schubert 		    (uint16) (sizeof(struct rpcap_pkthdr) + pkt_header->caplen));
272857e22627SCy Schubert 
272957e22627SCy Schubert 		net_pkt_header = (struct rpcap_pkthdr *) &sendbuf[sendbufidx];
273057e22627SCy Schubert 
273157e22627SCy Schubert 		// Bufferize the pkt header
273257e22627SCy Schubert 		if (sock_bufferize(NULL, sizeof(struct rpcap_pkthdr), NULL,
27336f9cba8fSJoseph Mingrone 		    &sendbufidx, (int)sendbufsize, SOCKBUF_CHECKONLY, errbuf,
273457e22627SCy Schubert 		    PCAP_ERRBUF_SIZE) == -1)
273557e22627SCy Schubert 		{
273657e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR,
273757e22627SCy Schubert 			    "sock_bufferize() error sending packet message: %s",
273857e22627SCy Schubert 			    errbuf);
273957e22627SCy Schubert 			goto error;
274057e22627SCy Schubert 		}
274157e22627SCy Schubert 
274257e22627SCy Schubert 		net_pkt_header->caplen = htonl(pkt_header->caplen);
274357e22627SCy Schubert 		net_pkt_header->len = htonl(pkt_header->len);
274457e22627SCy Schubert 		net_pkt_header->npkt = htonl(++(session->TotCapt));
27456f9cba8fSJoseph Mingrone 		//
27466f9cba8fSJoseph Mingrone 		// This protocol needs to be updated with a new version
27476f9cba8fSJoseph Mingrone 		// before 2038-01-19 03:14:07 UTC.
27486f9cba8fSJoseph Mingrone 		//
27496f9cba8fSJoseph Mingrone 		net_pkt_header->timestamp_sec = htonl((uint32)pkt_header->ts.tv_sec);
27506f9cba8fSJoseph Mingrone 		net_pkt_header->timestamp_usec = htonl((uint32)pkt_header->ts.tv_usec);
275157e22627SCy Schubert 
275257e22627SCy Schubert 		// Bufferize the pkt data
275357e22627SCy Schubert 		if (sock_bufferize((char *) pkt_data, pkt_header->caplen,
27546f9cba8fSJoseph Mingrone 		    sendbuf, &sendbufidx, (int)sendbufsize, SOCKBUF_BUFFERIZE,
275557e22627SCy Schubert 		    errbuf, PCAP_ERRBUF_SIZE) == -1)
275657e22627SCy Schubert 		{
275757e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR,
275857e22627SCy Schubert 			    "sock_bufferize() error sending packet message: %s",
275957e22627SCy Schubert 			    errbuf);
276057e22627SCy Schubert 			goto error;
276157e22627SCy Schubert 		}
276257e22627SCy Schubert 
276357e22627SCy Schubert 		// Send the packet
276457e22627SCy Schubert 		// If the client dropped the connection, don't report an
276557e22627SCy Schubert 		// error, just quit.
27666f9cba8fSJoseph Mingrone 		status = sock_send(session->sockdata, session->data_ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE);
276757e22627SCy Schubert 		if (status < 0)
276857e22627SCy Schubert 		{
276957e22627SCy Schubert 			if (status == -1)
277057e22627SCy Schubert 			{
277157e22627SCy Schubert 				//
277257e22627SCy Schubert 				// Error other than "client closed the
277357e22627SCy Schubert 				// connection out from under us"; report
277457e22627SCy Schubert 				// it.
277557e22627SCy Schubert 				//
277657e22627SCy Schubert 				rpcapd_log(LOGPRIO_ERROR,
277757e22627SCy Schubert 				    "Send of packet to client failed: %s",
277857e22627SCy Schubert 				    errbuf);
277957e22627SCy Schubert 			}
278057e22627SCy Schubert 
278157e22627SCy Schubert 			//
278257e22627SCy Schubert 			// Give up in either case.
278357e22627SCy Schubert 			//
278457e22627SCy Schubert 			goto error;
278557e22627SCy Schubert 		}
278657e22627SCy Schubert 	}
278757e22627SCy Schubert 
278857e22627SCy Schubert 	if (retval < 0 && retval != PCAP_ERROR_BREAK)
278957e22627SCy Schubert 	{
279057e22627SCy Schubert 		//
279157e22627SCy Schubert 		// Failed with an error other than "we were told to break
279257e22627SCy Schubert 		// out of the loop".
279357e22627SCy Schubert 		//
279457e22627SCy Schubert 		// The latter just means that the client told us to stop
279557e22627SCy Schubert 		// capturing, so there's no error to report.
279657e22627SCy Schubert 		//
27976f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(session->fp));
27986f9cba8fSJoseph Mingrone 		rpcap_senderror(session->sockctrl, session->ctrl_ssl, session->protocol_version,
279957e22627SCy Schubert 		    PCAP_ERR_READEX, errbuf, NULL);
280057e22627SCy Schubert 	}
280157e22627SCy Schubert 
280257e22627SCy Schubert error:
280357e22627SCy Schubert 	//
280457e22627SCy Schubert 	// The main thread will clean up the session structure.
280557e22627SCy Schubert 	//
280657e22627SCy Schubert 	free(sendbuf);
280757e22627SCy Schubert 
280857e22627SCy Schubert 	return 0;
280957e22627SCy Schubert }
281057e22627SCy Schubert 
281157e22627SCy Schubert #ifndef _WIN32
281257e22627SCy Schubert //
281357e22627SCy Schubert // Do-nothing handler for SIGUSR1; the sole purpose of SIGUSR1 is to
281457e22627SCy Schubert // interrupt the data thread if it's blocked in a system call waiting
281557e22627SCy Schubert // for packets to arrive.
281657e22627SCy Schubert //
noop_handler(int sign _U_)281757e22627SCy Schubert static void noop_handler(int sign _U_)
281857e22627SCy Schubert {
281957e22627SCy Schubert }
282057e22627SCy Schubert #endif
282157e22627SCy Schubert 
282257e22627SCy Schubert /*!
282357e22627SCy Schubert 	\brief It serializes a network address.
282457e22627SCy Schubert 
282557e22627SCy Schubert 	It accepts a 'sockaddr_storage' structure as input, and it converts it appropriately into a format
282657e22627SCy Schubert 	that can be used to be sent on the network. Basically, it applies all the hton()
282757e22627SCy Schubert 	conversion required to the input variable.
282857e22627SCy Schubert 
282957e22627SCy Schubert 	\param sockaddrin a 'sockaddr_storage' pointer to the variable that has to be
283057e22627SCy Schubert 	serialized. This variable can be both a 'sockaddr_in' and 'sockaddr_in6'.
283157e22627SCy Schubert 
283257e22627SCy Schubert 	\param sockaddrout an 'rpcap_sockaddr' pointer to the variable that will contain
283357e22627SCy Schubert 	the serialized data. This variable has to be allocated by the user.
283457e22627SCy Schubert 
283557e22627SCy Schubert 	\warning This function supports only AF_INET and AF_INET6 address families.
283657e22627SCy Schubert */
283757e22627SCy Schubert static void
daemon_seraddr(struct sockaddr_storage * sockaddrin,struct rpcap_sockaddr * sockaddrout)283857e22627SCy Schubert daemon_seraddr(struct sockaddr_storage *sockaddrin, struct rpcap_sockaddr *sockaddrout)
283957e22627SCy Schubert {
284057e22627SCy Schubert 	memset(sockaddrout, 0, sizeof(struct sockaddr_storage));
284157e22627SCy Schubert 
284257e22627SCy Schubert 	// There can be the case in which the sockaddrin is not available
284357e22627SCy Schubert 	if (sockaddrin == NULL) return;
284457e22627SCy Schubert 
284557e22627SCy Schubert 	// Warning: we support only AF_INET and AF_INET6
28466f9cba8fSJoseph Mingrone 	//
28476f9cba8fSJoseph Mingrone 	// Note: as noted above, the output structures are not
28486f9cba8fSJoseph Mingrone 	// neatly aligned on 4-byte boundaries, so we must fill
28496f9cba8fSJoseph Mingrone 	// in an aligned structure and then copy it to the output
28506f9cba8fSJoseph Mingrone 	// buffer with memcpy().
285157e22627SCy Schubert 	switch (sockaddrin->ss_family)
285257e22627SCy Schubert 	{
285357e22627SCy Schubert 	case AF_INET:
285457e22627SCy Schubert 		{
285557e22627SCy Schubert 		struct sockaddr_in *sockaddrin_ipv4;
28566f9cba8fSJoseph Mingrone 		struct rpcap_sockaddr_in sockaddrout_ipv4;
285757e22627SCy Schubert 
285857e22627SCy Schubert 		sockaddrin_ipv4 = (struct sockaddr_in *) sockaddrin;
28596f9cba8fSJoseph Mingrone 
28606f9cba8fSJoseph Mingrone 		sockaddrout_ipv4.family = htons(RPCAP_AF_INET);
28616f9cba8fSJoseph Mingrone 		sockaddrout_ipv4.port = htons(sockaddrin_ipv4->sin_port);
28626f9cba8fSJoseph Mingrone 		memcpy(&sockaddrout_ipv4.addr, &sockaddrin_ipv4->sin_addr, sizeof(sockaddrout_ipv4.addr));
28636f9cba8fSJoseph Mingrone 		memset(sockaddrout_ipv4.zero, 0, sizeof(sockaddrout_ipv4.zero));
28646f9cba8fSJoseph Mingrone 		memcpy(sockaddrout, &sockaddrout_ipv4, sizeof(struct rpcap_sockaddr_in));
286557e22627SCy Schubert 		break;
286657e22627SCy Schubert 		}
286757e22627SCy Schubert 
286857e22627SCy Schubert #ifdef AF_INET6
286957e22627SCy Schubert 	case AF_INET6:
287057e22627SCy Schubert 		{
287157e22627SCy Schubert 		struct sockaddr_in6 *sockaddrin_ipv6;
28726f9cba8fSJoseph Mingrone 		struct rpcap_sockaddr_in6 sockaddrout_ipv6;
287357e22627SCy Schubert 
287457e22627SCy Schubert 		sockaddrin_ipv6 = (struct sockaddr_in6 *) sockaddrin;
28756f9cba8fSJoseph Mingrone 
28766f9cba8fSJoseph Mingrone 		sockaddrout_ipv6.family = htons(RPCAP_AF_INET6);
28776f9cba8fSJoseph Mingrone 		sockaddrout_ipv6.port = htons(sockaddrin_ipv6->sin6_port);
28786f9cba8fSJoseph Mingrone 		sockaddrout_ipv6.flowinfo = htonl(sockaddrin_ipv6->sin6_flowinfo);
28796f9cba8fSJoseph Mingrone 		memcpy(&sockaddrout_ipv6.addr, &sockaddrin_ipv6->sin6_addr, sizeof(sockaddrout_ipv6.addr));
28806f9cba8fSJoseph Mingrone 		sockaddrout_ipv6.scope_id = htonl(sockaddrin_ipv6->sin6_scope_id);
28816f9cba8fSJoseph Mingrone 		memcpy(sockaddrout, &sockaddrout_ipv6, sizeof(struct rpcap_sockaddr_in6));
288257e22627SCy Schubert 		break;
288357e22627SCy Schubert 		}
288457e22627SCy Schubert #endif
288557e22627SCy Schubert 	}
288657e22627SCy Schubert }
288757e22627SCy Schubert 
288857e22627SCy Schubert 
288957e22627SCy Schubert /*!
289057e22627SCy Schubert 	\brief Suspends a thread for secs seconds.
289157e22627SCy Schubert */
sleep_secs(int secs)289257e22627SCy Schubert void sleep_secs(int secs)
289357e22627SCy Schubert {
28946f9cba8fSJoseph Mingrone #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
289557e22627SCy Schubert #ifdef _WIN32
289657e22627SCy Schubert 	Sleep(secs*1000);
289757e22627SCy Schubert #else
289857e22627SCy Schubert 	unsigned secs_remaining;
289957e22627SCy Schubert 
290057e22627SCy Schubert 	if (secs <= 0)
290157e22627SCy Schubert 		return;
290257e22627SCy Schubert 	secs_remaining = secs;
290357e22627SCy Schubert 	while (secs_remaining != 0)
290457e22627SCy Schubert 		secs_remaining = sleep(secs_remaining);
290557e22627SCy Schubert #endif
29066f9cba8fSJoseph Mingrone #endif
290757e22627SCy Schubert }
290857e22627SCy Schubert 
290957e22627SCy Schubert /*
291057e22627SCy Schubert  * Read the header of a message.
291157e22627SCy Schubert  */
291257e22627SCy Schubert static int
rpcapd_recv_msg_header(PCAP_SOCKET sock,SSL * ssl,struct rpcap_header * headerp)2913*afdbf109SJoseph Mingrone rpcapd_recv_msg_header(PCAP_SOCKET sock, SSL *ssl, struct rpcap_header *headerp)
291457e22627SCy Schubert {
291557e22627SCy Schubert 	int nread;
291657e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
291757e22627SCy Schubert 
29186f9cba8fSJoseph Mingrone 	nread = sock_recv(sock, ssl, (char *) headerp, sizeof(struct rpcap_header),
291957e22627SCy Schubert 	    SOCK_RECEIVEALL_YES|SOCK_EOF_ISNT_ERROR, errbuf, PCAP_ERRBUF_SIZE);
292057e22627SCy Schubert 	if (nread == -1)
292157e22627SCy Schubert 	{
292257e22627SCy Schubert 		// Network error.
292357e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
292457e22627SCy Schubert 		return -1;
292557e22627SCy Schubert 	}
292657e22627SCy Schubert 	if (nread == 0)
292757e22627SCy Schubert 	{
292857e22627SCy Schubert 		// Immediate EOF; that's treated like a close message.
292957e22627SCy Schubert 		return -2;
293057e22627SCy Schubert 	}
293157e22627SCy Schubert 	headerp->plen = ntohl(headerp->plen);
293257e22627SCy Schubert 	return 0;
293357e22627SCy Schubert }
293457e22627SCy Schubert 
293557e22627SCy Schubert /*
293657e22627SCy Schubert  * Read data from a message.
293757e22627SCy Schubert  * If we're trying to read more data that remains, puts an error
293857e22627SCy Schubert  * message into errmsgbuf and returns -2.  Otherwise, tries to read
293957e22627SCy Schubert  * the data and, if that succeeds, subtracts the amount read from
294057e22627SCy Schubert  * the number of bytes of data that remains.
294157e22627SCy Schubert  * Returns 0 on success, logs a message and returns -1 on a network
294257e22627SCy Schubert  * error.
294357e22627SCy Schubert  */
294457e22627SCy Schubert static int
rpcapd_recv(PCAP_SOCKET sock,SSL * ssl,char * buffer,size_t toread,uint32 * plen,char * errmsgbuf)2945*afdbf109SJoseph Mingrone rpcapd_recv(PCAP_SOCKET sock, SSL *ssl, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf)
294657e22627SCy Schubert {
294757e22627SCy Schubert 	int nread;
294857e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
294957e22627SCy Schubert 
295057e22627SCy Schubert 	if (toread > *plen)
295157e22627SCy Schubert 	{
295257e22627SCy Schubert 		// Tell the client and continue.
29536f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message payload is too short");
295457e22627SCy Schubert 		return -2;
295557e22627SCy Schubert 	}
29566f9cba8fSJoseph Mingrone 	nread = sock_recv(sock, ssl, buffer, toread,
295757e22627SCy Schubert 	    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
295857e22627SCy Schubert 	if (nread == -1)
295957e22627SCy Schubert 	{
296057e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
296157e22627SCy Schubert 		return -1;
296257e22627SCy Schubert 	}
296357e22627SCy Schubert 	*plen -= nread;
296457e22627SCy Schubert 	return 0;
296557e22627SCy Schubert }
296657e22627SCy Schubert 
296757e22627SCy Schubert /*
296857e22627SCy Schubert  * Discard data from a connection.
296957e22627SCy Schubert  * Mostly used to discard wrong-sized messages.
297057e22627SCy Schubert  * Returns 0 on success, logs a message and returns -1 on a network
297157e22627SCy Schubert  * error.
297257e22627SCy Schubert  */
297357e22627SCy Schubert static int
rpcapd_discard(PCAP_SOCKET sock,SSL * ssl,uint32 len)2974*afdbf109SJoseph Mingrone rpcapd_discard(PCAP_SOCKET sock, SSL *ssl, uint32 len)
297557e22627SCy Schubert {
297657e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed
297757e22627SCy Schubert 
297857e22627SCy Schubert 	if (len != 0)
297957e22627SCy Schubert 	{
29806f9cba8fSJoseph Mingrone 		if (sock_discard(sock, ssl, len, errbuf, PCAP_ERRBUF_SIZE) == -1)
298157e22627SCy Schubert 		{
298257e22627SCy Schubert 			// Network error.
298357e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
298457e22627SCy Schubert 			return -1;
298557e22627SCy Schubert 		}
298657e22627SCy Schubert 	}
298757e22627SCy Schubert 	return 0;
298857e22627SCy Schubert }
298957e22627SCy Schubert 
299057e22627SCy Schubert //
299157e22627SCy Schubert // Shut down any packet-capture thread associated with the session,
299257e22627SCy Schubert // close the SSL handle for the data socket if we have one, close
299357e22627SCy Schubert // the data socket if we have one, and close the underlying packet
299457e22627SCy Schubert // capture handle if we have one.
299557e22627SCy Schubert //
299657e22627SCy Schubert // We do not, of course, touch the controlling socket that's also
299757e22627SCy Schubert // copied into the session, as the service loop might still use it.
299857e22627SCy Schubert //
session_close(struct session * session)299957e22627SCy Schubert static void session_close(struct session *session)
300057e22627SCy Schubert {
300157e22627SCy Schubert 	if (session->have_thread)
300257e22627SCy Schubert 	{
300357e22627SCy Schubert 		//
300457e22627SCy Schubert 		// Tell the data connection thread main capture loop to
300557e22627SCy Schubert 		// break out of that loop.
300657e22627SCy Schubert 		//
300757e22627SCy Schubert 		// This may be sufficient to wake up a blocked thread,
300857e22627SCy Schubert 		// but it's not guaranteed to be sufficient.
300957e22627SCy Schubert 		//
301057e22627SCy Schubert 		pcap_breakloop(session->fp);
301157e22627SCy Schubert 
301257e22627SCy Schubert #ifdef _WIN32
301357e22627SCy Schubert 		//
301457e22627SCy Schubert 		// Set the event on which a read would block, so that,
301557e22627SCy Schubert 		// if it's currently blocked waiting for packets to
301657e22627SCy Schubert 		// arrive, it'll wake up, so it can see the "break
301757e22627SCy Schubert 		// out of the loop" indication.  (pcap_breakloop()
301857e22627SCy Schubert 		// might do this, but older versions don't.  Setting
301957e22627SCy Schubert 		// it twice should, at worst, cause an extra wakeup,
302057e22627SCy Schubert 		// which shouldn't be a problem.)
302157e22627SCy Schubert 		//
302257e22627SCy Schubert 		// XXX - what about modules other than NPF?
302357e22627SCy Schubert 		//
302457e22627SCy Schubert 		SetEvent(pcap_getevent(session->fp));
302557e22627SCy Schubert 
302657e22627SCy Schubert 		//
302757e22627SCy Schubert 		// Wait for the thread to exit, so we don't close
302857e22627SCy Schubert 		// sockets out from under it.
302957e22627SCy Schubert 		//
303057e22627SCy Schubert 		// XXX - have a timeout, so we don't wait forever?
303157e22627SCy Schubert 		//
303257e22627SCy Schubert 		WaitForSingleObject(session->thread, INFINITE);
303357e22627SCy Schubert 
303457e22627SCy Schubert 		//
303557e22627SCy Schubert 		// Release the thread handle, as we're done with
303657e22627SCy Schubert 		// it.
303757e22627SCy Schubert 		//
303857e22627SCy Schubert 		CloseHandle(session->thread);
303957e22627SCy Schubert 		session->have_thread = 0;
304057e22627SCy Schubert 		session->thread = INVALID_HANDLE_VALUE;
304157e22627SCy Schubert #else
304257e22627SCy Schubert 		//
304357e22627SCy Schubert 		// Send a SIGUSR1 signal to the thread, so that, if
304457e22627SCy Schubert 		// it's currently blocked waiting for packets to arrive,
304557e22627SCy Schubert 		// it'll wake up (we've turned off SA_RESTART for
304657e22627SCy Schubert 		// SIGUSR1, so that the system call in which it's blocked
304757e22627SCy Schubert 		// should return EINTR rather than restarting).
304857e22627SCy Schubert 		//
304957e22627SCy Schubert 		pthread_kill(session->thread, SIGUSR1);
305057e22627SCy Schubert 
305157e22627SCy Schubert 		//
305257e22627SCy Schubert 		// Wait for the thread to exit, so we don't close
305357e22627SCy Schubert 		// sockets out from under it.
305457e22627SCy Schubert 		//
305557e22627SCy Schubert 		// XXX - have a timeout, so we don't wait forever?
305657e22627SCy Schubert 		//
305757e22627SCy Schubert 		pthread_join(session->thread, NULL);
305857e22627SCy Schubert 		session->have_thread = 0;
305957e22627SCy Schubert 		memset(&session->thread, 0, sizeof(session->thread));
306057e22627SCy Schubert #endif
306157e22627SCy Schubert 	}
306257e22627SCy Schubert 
30636f9cba8fSJoseph Mingrone #ifdef HAVE_OPENSSL
30646f9cba8fSJoseph Mingrone 	if (session->data_ssl)
30656f9cba8fSJoseph Mingrone 	{
30666f9cba8fSJoseph Mingrone 		// Finish using the SSL handle for the socket.
30676f9cba8fSJoseph Mingrone 		// This must be done *before* the socket is closed.
30686f9cba8fSJoseph Mingrone 		ssl_finish(session->data_ssl);
30696f9cba8fSJoseph Mingrone 		session->data_ssl = NULL;
30706f9cba8fSJoseph Mingrone 	}
30716f9cba8fSJoseph Mingrone #endif
30726f9cba8fSJoseph Mingrone 
307357e22627SCy Schubert 	if (session->sockdata != INVALID_SOCKET)
307457e22627SCy Schubert 	{
307557e22627SCy Schubert 		sock_close(session->sockdata, NULL, 0);
307657e22627SCy Schubert 		session->sockdata = INVALID_SOCKET;
307757e22627SCy Schubert 	}
307857e22627SCy Schubert 
307957e22627SCy Schubert 	if (session->fp)
308057e22627SCy Schubert 	{
308157e22627SCy Schubert 		pcap_close(session->fp);
308257e22627SCy Schubert 		session->fp = NULL;
308357e22627SCy Schubert 	}
308457e22627SCy Schubert }
308557e22627SCy Schubert 
308657e22627SCy Schubert //
308757e22627SCy Schubert // Check whether a capture source string is a URL or not.
308857e22627SCy Schubert // This includes URLs that refer to a local device; a scheme, followed
308957e22627SCy Schubert // by ://, followed by *another* scheme and ://, is just silly, and
309057e22627SCy Schubert // anybody who supplies that will get an error.
309157e22627SCy Schubert //
309257e22627SCy Schubert static int
is_url(const char * source)309357e22627SCy Schubert is_url(const char *source)
309457e22627SCy Schubert {
309557e22627SCy Schubert 	char *colonp;
309657e22627SCy Schubert 
309757e22627SCy Schubert 	/*
309857e22627SCy Schubert 	 * RFC 3986 says:
309957e22627SCy Schubert 	 *
310057e22627SCy Schubert 	 *   URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
310157e22627SCy Schubert 	 *
310257e22627SCy Schubert 	 *   hier-part   = "//" authority path-abempty
310357e22627SCy Schubert 	 *               / path-absolute
310457e22627SCy Schubert 	 *               / path-rootless
310557e22627SCy Schubert 	 *               / path-empty
310657e22627SCy Schubert 	 *
310757e22627SCy Schubert 	 *   authority   = [ userinfo "@" ] host [ ":" port ]
310857e22627SCy Schubert 	 *
310957e22627SCy Schubert 	 *   userinfo    = *( unreserved / pct-encoded / sub-delims / ":" )
311057e22627SCy Schubert 	 *
311157e22627SCy Schubert 	 * Step 1: look for the ":" at the end of the scheme.
311257e22627SCy Schubert 	 * A colon in the source is *NOT* sufficient to indicate that
311357e22627SCy Schubert 	 * this is a URL, as interface names on some platforms might
311457e22627SCy Schubert 	 * include colons (e.g., I think some Solaris interfaces
311557e22627SCy Schubert 	 * might).
311657e22627SCy Schubert 	 */
311757e22627SCy Schubert 	colonp = strchr(source, ':');
311857e22627SCy Schubert 	if (colonp == NULL)
311957e22627SCy Schubert 	{
312057e22627SCy Schubert 		/*
312157e22627SCy Schubert 		 * The source is the device to open.  It's not a URL.
312257e22627SCy Schubert 		 */
312357e22627SCy Schubert 		return (0);
312457e22627SCy Schubert 	}
312557e22627SCy Schubert 
312657e22627SCy Schubert 	/*
312757e22627SCy Schubert 	 * All schemes must have "//" after them, i.e. we only support
312857e22627SCy Schubert 	 * hier-part   = "//" authority path-abempty, not
312957e22627SCy Schubert 	 * hier-part   = path-absolute
313057e22627SCy Schubert 	 * hier-part   = path-rootless
313157e22627SCy Schubert 	 * hier-part   = path-empty
313257e22627SCy Schubert 	 *
313357e22627SCy Schubert 	 * We need that in order to distinguish between a local device
313457e22627SCy Schubert 	 * name that happens to contain a colon and a URI.
313557e22627SCy Schubert 	 */
313657e22627SCy Schubert 	if (strncmp(colonp + 1, "//", 2) != 0)
313757e22627SCy Schubert 	{
313857e22627SCy Schubert 		/*
313957e22627SCy Schubert 		 * The source is the device to open.  It's not a URL.
314057e22627SCy Schubert 		 */
314157e22627SCy Schubert 		return (0);
314257e22627SCy Schubert 	}
314357e22627SCy Schubert 
314457e22627SCy Schubert 	/*
314557e22627SCy Schubert 	 * It's a URL.
314657e22627SCy Schubert 	 */
314757e22627SCy Schubert 	return (1);
314857e22627SCy Schubert }
3149