xref: /freebsd/contrib/libpcap/rpcapd/daemon.c (revision 6f9cba8f)
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 #ifdef HAVE_CONFIG_H
3357e22627SCy Schubert #include <config.h>
3457e22627SCy Schubert #endif
3557e22627SCy Schubert 
3657e22627SCy Schubert #include "ftmacros.h"
3757e22627SCy Schubert #include "varattrs.h"
3857e22627SCy Schubert 
3957e22627SCy Schubert #include <errno.h>		// for the errno variable
4057e22627SCy Schubert #include <stdlib.h>		// for malloc(), free(), ...
4157e22627SCy Schubert #include <string.h>		// for strlen(), ...
42*6f9cba8fSJoseph Mingrone #include <limits.h>		// for INT_MAX
4357e22627SCy Schubert 
4457e22627SCy Schubert #ifdef _WIN32
4557e22627SCy Schubert   #include <process.h>		// for threads
4657e22627SCy Schubert #else
4757e22627SCy Schubert   #include <unistd.h>
4857e22627SCy Schubert   #include <pthread.h>
4957e22627SCy Schubert   #include <signal.h>
5057e22627SCy Schubert   #include <sys/time.h>
5157e22627SCy Schubert   #include <sys/types.h>	// for select() and such
5257e22627SCy Schubert   #include <pwd.h>		// for password management
5357e22627SCy Schubert #endif
5457e22627SCy Schubert 
5557e22627SCy Schubert #ifdef HAVE_GETSPNAM
5657e22627SCy Schubert #include <shadow.h>		// for password management
5757e22627SCy Schubert #endif
5857e22627SCy Schubert 
5957e22627SCy Schubert #include <pcap.h>		// for libpcap/WinPcap calls
6057e22627SCy Schubert 
6157e22627SCy Schubert #include "fmtutils.h"
6257e22627SCy Schubert #include "sockutils.h"		// for socket calls
6357e22627SCy Schubert #include "portability.h"
6457e22627SCy Schubert #include "rpcap-protocol.h"
6557e22627SCy Schubert #include "daemon.h"
6657e22627SCy Schubert #include "log.h"
6757e22627SCy Schubert 
68*6f9cba8fSJoseph Mingrone #ifdef HAVE_OPENSSL
69*6f9cba8fSJoseph Mingrone #include <openssl/ssl.h>
70*6f9cba8fSJoseph Mingrone #include "sslutils.h"
71*6f9cba8fSJoseph Mingrone #endif
72*6f9cba8fSJoseph Mingrone 
7357e22627SCy Schubert //
7457e22627SCy Schubert // Timeout, in seconds, when we're waiting for a client to send us an
7557e22627SCy Schubert // authentication request; if they don't send us a request within that
7657e22627SCy Schubert // interval, we drop the connection, so we don't stay stuck forever.
7757e22627SCy Schubert //
7857e22627SCy Schubert #define RPCAP_TIMEOUT_INIT 90
7957e22627SCy Schubert 
8057e22627SCy Schubert //
8157e22627SCy Schubert // Timeout, in seconds, when we're waiting for an authenticated client
8257e22627SCy Schubert // to send us a request, if a capture isn't in progress; if they don't
8357e22627SCy Schubert // send us a request within that interval, we drop the connection, so
8457e22627SCy Schubert // we don't stay stuck forever.
8557e22627SCy Schubert //
8657e22627SCy Schubert #define RPCAP_TIMEOUT_RUNTIME 180
8757e22627SCy Schubert 
8857e22627SCy Schubert //
8957e22627SCy Schubert // Time, in seconds, that we wait after a failed authentication attempt
9057e22627SCy Schubert // before processing the next request; this prevents a client from
9157e22627SCy Schubert // rapidly trying different accounts or passwords.
9257e22627SCy Schubert //
9357e22627SCy Schubert #define RPCAP_SUSPEND_WRONGAUTH 1
9457e22627SCy Schubert 
9557e22627SCy Schubert // Parameters for the service loop.
9657e22627SCy Schubert struct daemon_slpars
9757e22627SCy Schubert {
9857e22627SCy Schubert 	SOCKET sockctrl;	//!< SOCKET ID of the control connection
99*6f9cba8fSJoseph Mingrone 	SSL *ssl;		//!< Optional SSL handler for the controlling sockets
10057e22627SCy Schubert 	int isactive;		//!< Not null if the daemon has to run in active mode
10157e22627SCy Schubert 	int nullAuthAllowed;	//!< '1' if we permit NULL authentication, '0' otherwise
10257e22627SCy Schubert };
10357e22627SCy Schubert 
10457e22627SCy Schubert //
10557e22627SCy Schubert // Data for a session managed by a thread.
10657e22627SCy Schubert // It includes both a Boolean indicating whether we *have* a thread,
10757e22627SCy Schubert // and a platform-dependent (UN*X vs. Windows) identifier for the
10857e22627SCy Schubert // thread; on Windows, we could use an invalid handle to indicate
10957e22627SCy Schubert // that we don't have a thread, but there *is* no portable "no thread"
11057e22627SCy Schubert // value for a pthread_t on UN*X.
11157e22627SCy Schubert //
11257e22627SCy Schubert struct session {
11357e22627SCy Schubert 	SOCKET sockctrl;
11457e22627SCy Schubert 	SOCKET sockdata;
115*6f9cba8fSJoseph Mingrone 	SSL *ctrl_ssl, *data_ssl; // optional SSL handlers for sockctrl and sockdata.
11657e22627SCy Schubert 	uint8 protocol_version;
11757e22627SCy Schubert 	pcap_t *fp;
11857e22627SCy Schubert 	unsigned int TotCapt;
11957e22627SCy Schubert 	int	have_thread;
12057e22627SCy Schubert #ifdef _WIN32
12157e22627SCy Schubert 	HANDLE thread;
12257e22627SCy Schubert #else
12357e22627SCy Schubert 	pthread_t thread;
12457e22627SCy Schubert #endif
12557e22627SCy Schubert };
12657e22627SCy Schubert 
12757e22627SCy Schubert // Locally defined functions
128*6f9cba8fSJoseph Mingrone static int daemon_msg_err(SOCKET sockctrl, SSL *, uint32 plen);
12957e22627SCy Schubert static int daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen);
13057e22627SCy Schubert static int daemon_AuthUserPwd(char *username, char *password, char *errbuf);
13157e22627SCy Schubert 
13257e22627SCy Schubert static int daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars,
13357e22627SCy Schubert     uint32 plen);
13457e22627SCy Schubert 
13557e22627SCy Schubert static int daemon_msg_open_req(uint8 ver, struct daemon_slpars *pars,
13657e22627SCy Schubert     uint32 plen, char *source, size_t sourcelen);
13757e22627SCy Schubert static int daemon_msg_startcap_req(uint8 ver, struct daemon_slpars *pars,
13857e22627SCy Schubert     uint32 plen, char *source, struct session **sessionp,
139*6f9cba8fSJoseph Mingrone     struct rpcap_sampling *samp_param, int uses_ssl);
14057e22627SCy Schubert static int daemon_msg_endcap_req(uint8 ver, struct daemon_slpars *pars,
14157e22627SCy Schubert     struct session *session);
14257e22627SCy Schubert 
14357e22627SCy Schubert static int daemon_msg_updatefilter_req(uint8 ver, struct daemon_slpars *pars,
14457e22627SCy Schubert     struct session *session, uint32 plen);
145*6f9cba8fSJoseph Mingrone static int daemon_unpackapplyfilter(SOCKET sockctrl, SSL *, struct session *session, uint32 *plenp, char *errbuf);
14657e22627SCy Schubert 
14757e22627SCy Schubert static int daemon_msg_stats_req(uint8 ver, struct daemon_slpars *pars,
14857e22627SCy Schubert     struct session *session, uint32 plen, struct pcap_stat *stats,
14957e22627SCy Schubert     unsigned int svrcapt);
15057e22627SCy Schubert 
15157e22627SCy Schubert static int daemon_msg_setsampling_req(uint8 ver, struct daemon_slpars *pars,
15257e22627SCy Schubert     uint32 plen, struct rpcap_sampling *samp_param);
15357e22627SCy Schubert 
15457e22627SCy Schubert static void daemon_seraddr(struct sockaddr_storage *sockaddrin, struct rpcap_sockaddr *sockaddrout);
15557e22627SCy Schubert #ifdef _WIN32
15657e22627SCy Schubert static unsigned __stdcall daemon_thrdatamain(void *ptr);
15757e22627SCy Schubert #else
15857e22627SCy Schubert static void *daemon_thrdatamain(void *ptr);
15957e22627SCy Schubert static void noop_handler(int sign);
16057e22627SCy Schubert #endif
16157e22627SCy Schubert 
162*6f9cba8fSJoseph Mingrone static int rpcapd_recv_msg_header(SOCKET sock, SSL *, struct rpcap_header *headerp);
163*6f9cba8fSJoseph Mingrone static int rpcapd_recv(SOCKET sock, SSL *, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf);
164*6f9cba8fSJoseph Mingrone static int rpcapd_discard(SOCKET sock, SSL *, uint32 len);
16557e22627SCy Schubert static void session_close(struct session *);
16657e22627SCy Schubert 
167*6f9cba8fSJoseph Mingrone //
168*6f9cba8fSJoseph Mingrone // TLS record layer header; used when processing the first message from
169*6f9cba8fSJoseph Mingrone // the client, in case we aren't doing TLS but they are.
170*6f9cba8fSJoseph Mingrone //
171*6f9cba8fSJoseph Mingrone struct tls_record_header {
172*6f9cba8fSJoseph Mingrone 	uint8 type;		// ContentType - will be 22, for Handshake
173*6f9cba8fSJoseph Mingrone 	uint8 version_major;	// TLS protocol major version
174*6f9cba8fSJoseph Mingrone 	uint8 version_injor;	// TLS protocol minor version
175*6f9cba8fSJoseph Mingrone 	// This is *not* aligned on a 2-byte boundary; we just
176*6f9cba8fSJoseph Mingrone 	// declare it as two bytes.  Don't assume any particular
177*6f9cba8fSJoseph Mingrone 	// compiler's mechanism for saying "packed"!
178*6f9cba8fSJoseph Mingrone 	uint8 length_hi;	// Upper 8 bits of payload length
179*6f9cba8fSJoseph Mingrone 	uint8 length_lo;	// Low 8 bits of payload length
180*6f9cba8fSJoseph Mingrone };
181*6f9cba8fSJoseph Mingrone 
182*6f9cba8fSJoseph Mingrone #define TLS_RECORD_HEADER_LEN	5	// Don't use sizeof in case it's padded
183*6f9cba8fSJoseph Mingrone 
184*6f9cba8fSJoseph Mingrone #define TLS_RECORD_TYPE_ALERT		21
185*6f9cba8fSJoseph Mingrone #define TLS_RECORD_TYPE_HANDSHAKE	22
186*6f9cba8fSJoseph Mingrone 
187*6f9cba8fSJoseph Mingrone //
188*6f9cba8fSJoseph Mingrone // TLS alert message.
189*6f9cba8fSJoseph Mingrone //
190*6f9cba8fSJoseph Mingrone struct tls_alert {
191*6f9cba8fSJoseph Mingrone 	uint8 alert_level;
192*6f9cba8fSJoseph Mingrone 	uint8 alert_description;
193*6f9cba8fSJoseph Mingrone };
194*6f9cba8fSJoseph Mingrone 
195*6f9cba8fSJoseph Mingrone #define TLS_ALERT_LEN			2
196*6f9cba8fSJoseph Mingrone 
197*6f9cba8fSJoseph Mingrone #define TLS_ALERT_LEVEL_FATAL		2
198*6f9cba8fSJoseph Mingrone #define TLS_ALERT_HANDSHAKE_FAILURE	40
199*6f9cba8fSJoseph Mingrone 
20057e22627SCy Schubert static int is_url(const char *source);
20157e22627SCy Schubert 
202*6f9cba8fSJoseph Mingrone /*
203*6f9cba8fSJoseph Mingrone  * Maximum sizes for fixed-bit-width values.
204*6f9cba8fSJoseph Mingrone  */
205*6f9cba8fSJoseph Mingrone #ifndef UINT16_MAX
206*6f9cba8fSJoseph Mingrone #define UINT16_MAX	65535U
207*6f9cba8fSJoseph Mingrone #endif
208*6f9cba8fSJoseph Mingrone 
209*6f9cba8fSJoseph Mingrone #ifndef UINT32_MAX
210*6f9cba8fSJoseph Mingrone #define UINT32_MAX	4294967295U
211*6f9cba8fSJoseph Mingrone #endif
212*6f9cba8fSJoseph Mingrone 
21357e22627SCy Schubert int
daemon_serviceloop(SOCKET sockctrl,int isactive,char * passiveClients,int nullAuthAllowed,int uses_ssl)21457e22627SCy Schubert daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
215*6f9cba8fSJoseph Mingrone     int nullAuthAllowed, int uses_ssl)
21657e22627SCy Schubert {
217*6f9cba8fSJoseph Mingrone 	uint8 first_octet;
218*6f9cba8fSJoseph Mingrone 	struct tls_record_header tls_header;
219*6f9cba8fSJoseph Mingrone 	struct tls_alert tls_alert;
22057e22627SCy Schubert 	struct daemon_slpars pars;		// service loop parameters
22157e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed
22257e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE + 1];	// buffer for errors to send to the client
22357e22627SCy Schubert 	int host_port_check_status;
224*6f9cba8fSJoseph Mingrone 	SSL *ssl = NULL;
22557e22627SCy Schubert 	int nrecv;
22657e22627SCy Schubert 	struct rpcap_header header;		// RPCAP message general header
22757e22627SCy Schubert 	uint32 plen;				// payload length from header
22857e22627SCy Schubert 	int authenticated = 0;			// 1 if the client has successfully authenticated
22957e22627SCy Schubert 	char source[PCAP_BUF_SIZE+1];		// keeps the string that contains the interface to open
23057e22627SCy Schubert 	int got_source = 0;			// 1 if we've gotten the source from an open request
23157e22627SCy Schubert #ifndef _WIN32
23257e22627SCy Schubert 	struct sigaction action;
23357e22627SCy Schubert #endif
23457e22627SCy Schubert 	struct session *session = NULL;		// struct session main variable
23557e22627SCy Schubert 	const char *msg_type_string;		// string for message type
23657e22627SCy Schubert 	int client_told_us_to_close = 0;	// 1 if the client told us to close the capture
23757e22627SCy Schubert 
23857e22627SCy Schubert 	// needed to save the values of the statistics
23957e22627SCy Schubert 	struct pcap_stat stats;
24057e22627SCy Schubert 	unsigned int svrcapt;
24157e22627SCy Schubert 
24257e22627SCy Schubert 	struct rpcap_sampling samp_param;	// in case sampling has been requested
24357e22627SCy Schubert 
24457e22627SCy Schubert 	// Structures needed for the select() call
24557e22627SCy Schubert 	fd_set rfds;				// set of socket descriptors we have to check
24657e22627SCy Schubert 	struct timeval tv;			// maximum time the select() can block waiting for data
24757e22627SCy Schubert 	int retval;				// select() return value
24857e22627SCy Schubert 
24957e22627SCy Schubert 	*errbuf = 0;	// Initialize errbuf
25057e22627SCy Schubert 
251*6f9cba8fSJoseph Mingrone 	//
252*6f9cba8fSJoseph Mingrone 	// Peek into the socket to determine whether the client sent us
253*6f9cba8fSJoseph Mingrone 	// a TLS handshake message or a non-TLS rpcapd message.
254*6f9cba8fSJoseph Mingrone 	//
255*6f9cba8fSJoseph Mingrone 	// The first byte of an rpcapd request is the version number;
256*6f9cba8fSJoseph Mingrone 	// the first byte of a TLS handshake message is 22.  The
257*6f9cba8fSJoseph Mingrone 	// first request to an rpcapd server must be an authentication
258*6f9cba8fSJoseph Mingrone 	// request or a close request, and must have a version number
259*6f9cba8fSJoseph Mingrone 	// of 0, so it will be possible to distinguish between an
260*6f9cba8fSJoseph Mingrone 	// initial plaintext request to a server and an initial TLS
261*6f9cba8fSJoseph Mingrone 	// handshake message.
262*6f9cba8fSJoseph Mingrone 	//
263*6f9cba8fSJoseph Mingrone 	nrecv = sock_recv(sockctrl, NULL, (char *)&first_octet, 1,
264*6f9cba8fSJoseph Mingrone 	    SOCK_EOF_ISNT_ERROR|SOCK_MSG_PEEK, errbuf, PCAP_ERRBUF_SIZE);
265*6f9cba8fSJoseph Mingrone 	if (nrecv == -1)
266*6f9cba8fSJoseph Mingrone 	{
267*6f9cba8fSJoseph Mingrone 		// Fatal error.
268*6f9cba8fSJoseph Mingrone 		rpcapd_log(LOGPRIO_ERROR, "Peek from client failed: %s", errbuf);
269*6f9cba8fSJoseph Mingrone 		goto end;
270*6f9cba8fSJoseph Mingrone 	}
271*6f9cba8fSJoseph Mingrone 	if (nrecv == 0)
272*6f9cba8fSJoseph Mingrone 	{
273*6f9cba8fSJoseph Mingrone 		// Client closed the connection.
274*6f9cba8fSJoseph Mingrone 		goto end;
275*6f9cba8fSJoseph Mingrone 	}
276*6f9cba8fSJoseph Mingrone 
277*6f9cba8fSJoseph Mingrone #ifdef HAVE_OPENSSL
278*6f9cba8fSJoseph Mingrone 	//
279*6f9cba8fSJoseph Mingrone 	// We have to upgrade to TLS as soon as possible, so that the
280*6f9cba8fSJoseph Mingrone 	// whole protocol goes through the encrypted tunnel, including
281*6f9cba8fSJoseph Mingrone 	// early error messages.
282*6f9cba8fSJoseph Mingrone 	//
283*6f9cba8fSJoseph Mingrone 	// Even in active mode, the other end has to initiate the TLS
284*6f9cba8fSJoseph Mingrone 	// handshake as we still are the server as far as TLS is concerned,
285*6f9cba8fSJoseph Mingrone 	// so we don't check isactive.
286*6f9cba8fSJoseph Mingrone 	//
287*6f9cba8fSJoseph Mingrone 	if (uses_ssl)
288*6f9cba8fSJoseph Mingrone 	{
289*6f9cba8fSJoseph Mingrone 		//
290*6f9cba8fSJoseph Mingrone 		// We're expecting a TLS handshake message.  If this
291*6f9cba8fSJoseph Mingrone 		// isn't one, assume it's a non-TLS rpcapd message.
292*6f9cba8fSJoseph Mingrone 		//
293*6f9cba8fSJoseph Mingrone 		// The first octet of a TLS handshake is
294*6f9cba8fSJoseph Mingrone 		// TLS_RECORD_TYPE_HANDSHAKE.
295*6f9cba8fSJoseph Mingrone 		//
296*6f9cba8fSJoseph Mingrone 		if (first_octet != TLS_RECORD_TYPE_HANDSHAKE)
297*6f9cba8fSJoseph Mingrone 		{
298*6f9cba8fSJoseph Mingrone 			//
299*6f9cba8fSJoseph Mingrone 			// We assume this is a non-TLS rpcapd message.
300*6f9cba8fSJoseph Mingrone 			//
301*6f9cba8fSJoseph Mingrone 			// Read the message header from the client.
302*6f9cba8fSJoseph Mingrone 			//
303*6f9cba8fSJoseph Mingrone 			nrecv = rpcapd_recv_msg_header(sockctrl, NULL, &header);
304*6f9cba8fSJoseph Mingrone 			if (nrecv == -1)
305*6f9cba8fSJoseph Mingrone 			{
306*6f9cba8fSJoseph Mingrone 				// Fatal error.
307*6f9cba8fSJoseph Mingrone 				goto end;
308*6f9cba8fSJoseph Mingrone 			}
309*6f9cba8fSJoseph Mingrone 			if (nrecv == -2)
310*6f9cba8fSJoseph Mingrone 			{
311*6f9cba8fSJoseph Mingrone 				// Client closed the connection.
312*6f9cba8fSJoseph Mingrone 				goto end;
313*6f9cba8fSJoseph Mingrone 			}
314*6f9cba8fSJoseph Mingrone 			plen = header.plen;
315*6f9cba8fSJoseph Mingrone 
316*6f9cba8fSJoseph Mingrone 			// Discard the rest of the message.
317*6f9cba8fSJoseph Mingrone 			if (rpcapd_discard(sockctrl, NULL, plen) == -1)
318*6f9cba8fSJoseph Mingrone 			{
319*6f9cba8fSJoseph Mingrone 				// Network error.
320*6f9cba8fSJoseph Mingrone 				goto end;
321*6f9cba8fSJoseph Mingrone 			}
322*6f9cba8fSJoseph Mingrone 
323*6f9cba8fSJoseph Mingrone 			//
324*6f9cba8fSJoseph Mingrone 			// Send an authentication error, indicating
325*6f9cba8fSJoseph Mingrone 			// that we require TLS.
326*6f9cba8fSJoseph Mingrone 			//
327*6f9cba8fSJoseph Mingrone 			if (rpcap_senderror(sockctrl, NULL, header.ver,
328*6f9cba8fSJoseph Mingrone 			    PCAP_ERR_TLS_REQUIRED,
329*6f9cba8fSJoseph Mingrone 			    "TLS is required by this server", errbuf) == -1)
330*6f9cba8fSJoseph Mingrone 			{
331*6f9cba8fSJoseph Mingrone 				// That failed; log a message and give up.
332*6f9cba8fSJoseph Mingrone 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
333*6f9cba8fSJoseph Mingrone 				goto end;
334*6f9cba8fSJoseph Mingrone 			}
335*6f9cba8fSJoseph Mingrone 
336*6f9cba8fSJoseph Mingrone 			// Shut the session down.
337*6f9cba8fSJoseph Mingrone 			goto end;
338*6f9cba8fSJoseph Mingrone 		}
339*6f9cba8fSJoseph Mingrone 		ssl = ssl_promotion(1, sockctrl, errbuf, PCAP_ERRBUF_SIZE);
340*6f9cba8fSJoseph Mingrone 		if (! ssl)
341*6f9cba8fSJoseph Mingrone 		{
342*6f9cba8fSJoseph Mingrone 			rpcapd_log(LOGPRIO_ERROR, "TLS handshake on control connection failed: %s",
343*6f9cba8fSJoseph Mingrone 			    errbuf);
344*6f9cba8fSJoseph Mingrone 			goto end;
345*6f9cba8fSJoseph Mingrone 		}
346*6f9cba8fSJoseph Mingrone 	}
347*6f9cba8fSJoseph Mingrone 	else
348*6f9cba8fSJoseph Mingrone #endif
349*6f9cba8fSJoseph Mingrone 	{
350*6f9cba8fSJoseph Mingrone 		//
351*6f9cba8fSJoseph Mingrone 		// We're expecting a non-TLS rpcapd message.  If this
352*6f9cba8fSJoseph Mingrone 		// looks, instead, like a TLS handshake message, send
353*6f9cba8fSJoseph Mingrone 		// a TLS handshake_failed alert.
354*6f9cba8fSJoseph Mingrone 		//
355*6f9cba8fSJoseph Mingrone 		// The first octet of a TLS handshake is
356*6f9cba8fSJoseph Mingrone 		// TLS_RECORD_TYPE_HANDSHAKE.
357*6f9cba8fSJoseph Mingrone 		//
358*6f9cba8fSJoseph Mingrone 		if (first_octet == TLS_RECORD_TYPE_HANDSHAKE)
359*6f9cba8fSJoseph Mingrone 		{
360*6f9cba8fSJoseph Mingrone 			//
361*6f9cba8fSJoseph Mingrone 			// TLS handshake.
362*6f9cba8fSJoseph Mingrone 			// Read the record header.
363*6f9cba8fSJoseph Mingrone 			//
364*6f9cba8fSJoseph Mingrone 			nrecv = sock_recv(sockctrl, ssl, (char *) &tls_header,
365*6f9cba8fSJoseph Mingrone 			    sizeof tls_header, SOCK_RECEIVEALL_YES|SOCK_EOF_ISNT_ERROR,
366*6f9cba8fSJoseph Mingrone 			    errbuf, PCAP_ERRBUF_SIZE);
367*6f9cba8fSJoseph Mingrone 			if (nrecv == -1)
368*6f9cba8fSJoseph Mingrone 			{
369*6f9cba8fSJoseph Mingrone 				// Network error.
370*6f9cba8fSJoseph Mingrone 				rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
371*6f9cba8fSJoseph Mingrone 				goto end;
372*6f9cba8fSJoseph Mingrone 			}
373*6f9cba8fSJoseph Mingrone 			if (nrecv == 0)
374*6f9cba8fSJoseph Mingrone 			{
375*6f9cba8fSJoseph Mingrone 				// Immediate EOF
376*6f9cba8fSJoseph Mingrone 				goto end;
377*6f9cba8fSJoseph Mingrone 			}
378*6f9cba8fSJoseph Mingrone 			plen = (tls_header.length_hi << 8U) | tls_header.length_lo;
379*6f9cba8fSJoseph Mingrone 
380*6f9cba8fSJoseph Mingrone 			// Discard the rest of the message.
381*6f9cba8fSJoseph Mingrone 			if (rpcapd_discard(sockctrl, NULL, plen) == -1)
382*6f9cba8fSJoseph Mingrone 			{
383*6f9cba8fSJoseph Mingrone 				// Network error.
384*6f9cba8fSJoseph Mingrone 				goto end;
385*6f9cba8fSJoseph Mingrone 			}
386*6f9cba8fSJoseph Mingrone 
387*6f9cba8fSJoseph Mingrone 			//
388*6f9cba8fSJoseph Mingrone 			// Send a TLS handshake failure alert.
389*6f9cba8fSJoseph Mingrone 			// Use the same version the client sent us.
390*6f9cba8fSJoseph Mingrone 			//
391*6f9cba8fSJoseph Mingrone 			tls_header.type = TLS_RECORD_TYPE_ALERT;
392*6f9cba8fSJoseph Mingrone 			tls_header.length_hi = 0;
393*6f9cba8fSJoseph Mingrone 			tls_header.length_lo = TLS_ALERT_LEN;
394*6f9cba8fSJoseph Mingrone 
395*6f9cba8fSJoseph Mingrone 			if (sock_send(sockctrl, NULL, (char *) &tls_header,
396*6f9cba8fSJoseph Mingrone 			    TLS_RECORD_HEADER_LEN, errbuf, PCAP_ERRBUF_SIZE) == -1)
397*6f9cba8fSJoseph Mingrone 			{
398*6f9cba8fSJoseph Mingrone 				// That failed; log a message and give up.
399*6f9cba8fSJoseph Mingrone 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
400*6f9cba8fSJoseph Mingrone 				goto end;
401*6f9cba8fSJoseph Mingrone 			}
402*6f9cba8fSJoseph Mingrone 
403*6f9cba8fSJoseph Mingrone 			tls_alert.alert_level = TLS_ALERT_LEVEL_FATAL;
404*6f9cba8fSJoseph Mingrone 			tls_alert.alert_description = TLS_ALERT_HANDSHAKE_FAILURE;
405*6f9cba8fSJoseph Mingrone 			if (sock_send(sockctrl, NULL, (char *) &tls_alert,
406*6f9cba8fSJoseph Mingrone 			    TLS_ALERT_LEN, errbuf, PCAP_ERRBUF_SIZE) == -1)
407*6f9cba8fSJoseph Mingrone 			{
408*6f9cba8fSJoseph Mingrone 				// That failed; log a message and give up.
409*6f9cba8fSJoseph Mingrone 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
410*6f9cba8fSJoseph Mingrone 				goto end;
411*6f9cba8fSJoseph Mingrone 			}
412*6f9cba8fSJoseph Mingrone 			//
413*6f9cba8fSJoseph Mingrone 			// Give up anyway.
414*6f9cba8fSJoseph Mingrone 			//
415*6f9cba8fSJoseph Mingrone 			goto end;
416*6f9cba8fSJoseph Mingrone 		}
417*6f9cba8fSJoseph Mingrone 	}
418*6f9cba8fSJoseph Mingrone 
41957e22627SCy Schubert 	// Set parameters structure
42057e22627SCy Schubert 	pars.sockctrl = sockctrl;
421*6f9cba8fSJoseph Mingrone 	pars.ssl = ssl;
42257e22627SCy Schubert 	pars.isactive = isactive;		// active mode
42357e22627SCy Schubert 	pars.nullAuthAllowed = nullAuthAllowed;
42457e22627SCy Schubert 
42557e22627SCy Schubert 	//
42657e22627SCy Schubert 	// We have a connection.
42757e22627SCy Schubert 	//
42857e22627SCy Schubert 	// If it's a passive mode connection, check whether the connecting
42957e22627SCy Schubert 	// host is among the ones allowed.
43057e22627SCy Schubert 	//
43157e22627SCy Schubert 	// In either case, we were handed a copy of the host list; free it
43257e22627SCy Schubert 	// as soon as we're done with it.
43357e22627SCy Schubert 	//
43457e22627SCy Schubert 	if (pars.isactive)
43557e22627SCy Schubert 	{
43657e22627SCy Schubert 		// Nothing to do.
43757e22627SCy Schubert 		free(passiveClients);
43857e22627SCy Schubert 		passiveClients = NULL;
43957e22627SCy Schubert 	}
44057e22627SCy Schubert 	else
44157e22627SCy Schubert 	{
44257e22627SCy Schubert 		struct sockaddr_storage from;
44357e22627SCy Schubert 		socklen_t fromlen;
44457e22627SCy Schubert 
44557e22627SCy Schubert 		//
44657e22627SCy Schubert 		// Get the address of the other end of the connection.
44757e22627SCy Schubert 		//
44857e22627SCy Schubert 		fromlen = sizeof(struct sockaddr_storage);
44957e22627SCy Schubert 		if (getpeername(pars.sockctrl, (struct sockaddr *)&from,
45057e22627SCy Schubert 		    &fromlen) == -1)
45157e22627SCy Schubert 		{
452*6f9cba8fSJoseph Mingrone 			sock_geterrmsg(errmsgbuf, PCAP_ERRBUF_SIZE,
453*6f9cba8fSJoseph Mingrone 			    "getpeername() failed");
454*6f9cba8fSJoseph Mingrone 			if (rpcap_senderror(pars.sockctrl, pars.ssl, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
45557e22627SCy Schubert 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
45657e22627SCy Schubert 			goto end;
45757e22627SCy Schubert 		}
45857e22627SCy Schubert 
45957e22627SCy Schubert 		//
46057e22627SCy Schubert 		// Are they in the list of host/port combinations we allow?
46157e22627SCy Schubert 		//
46257e22627SCy Schubert 		host_port_check_status = sock_check_hostlist(passiveClients, RPCAP_HOSTLIST_SEP, &from, errmsgbuf, PCAP_ERRBUF_SIZE);
46357e22627SCy Schubert 		free(passiveClients);
46457e22627SCy Schubert 		passiveClients = NULL;
46557e22627SCy Schubert 		if (host_port_check_status < 0)
46657e22627SCy Schubert 		{
46757e22627SCy Schubert 			if (host_port_check_status == -2) {
46857e22627SCy Schubert 				//
46957e22627SCy Schubert 				// We got an error; log it.
47057e22627SCy Schubert 				//
47157e22627SCy Schubert 				rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
47257e22627SCy Schubert 			}
47357e22627SCy Schubert 
47457e22627SCy Schubert 			//
47557e22627SCy Schubert 			// Sorry, we can't let you in.
47657e22627SCy Schubert 			//
477*6f9cba8fSJoseph Mingrone 			if (rpcap_senderror(pars.sockctrl, pars.ssl, 0, PCAP_ERR_HOSTNOAUTH, errmsgbuf, errbuf) == -1)
47857e22627SCy Schubert 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
47957e22627SCy Schubert 			goto end;
48057e22627SCy Schubert 		}
48157e22627SCy Schubert 	}
48257e22627SCy Schubert 
48357e22627SCy Schubert #ifndef _WIN32
48457e22627SCy Schubert 	//
48557e22627SCy Schubert 	// Catch SIGUSR1, but do nothing.  We use it to interrupt the
48657e22627SCy Schubert 	// capture thread to break it out of a loop in which it's
48757e22627SCy Schubert 	// blocked waiting for packets to arrive.
48857e22627SCy Schubert 	//
48957e22627SCy Schubert 	// We don't want interrupted system calls to restart, so that
49057e22627SCy Schubert 	// the read routine for the pcap_t gets EINTR rather than
49157e22627SCy Schubert 	// restarting if it's blocked in a system call.
49257e22627SCy Schubert 	//
49357e22627SCy Schubert 	memset(&action, 0, sizeof (action));
49457e22627SCy Schubert 	action.sa_handler = noop_handler;
49557e22627SCy Schubert 	action.sa_flags = 0;
49657e22627SCy Schubert 	sigemptyset(&action.sa_mask);
49757e22627SCy Schubert 	sigaction(SIGUSR1, &action, NULL);
49857e22627SCy Schubert #endif
49957e22627SCy Schubert 
50057e22627SCy Schubert 	//
50157e22627SCy Schubert 	// The client must first authenticate; loop until they send us a
50257e22627SCy Schubert 	// message with a version we support and credentials we accept,
50357e22627SCy Schubert 	// they send us a close message indicating that they're giving up,
50457e22627SCy Schubert 	// or we get a network error or other fatal error.
50557e22627SCy Schubert 	//
50657e22627SCy Schubert 	while (!authenticated)
50757e22627SCy Schubert 	{
50857e22627SCy Schubert 		//
50957e22627SCy Schubert 		// If we're not in active mode, we use select(), with a
51057e22627SCy Schubert 		// timeout, to wait for an authentication request; if
51157e22627SCy Schubert 		// the timeout expires, we drop the connection, so that
51257e22627SCy Schubert 		// a client can't just connect to us and leave us
51357e22627SCy Schubert 		// waiting forever.
51457e22627SCy Schubert 		//
51557e22627SCy Schubert 		if (!pars.isactive)
51657e22627SCy Schubert 		{
51757e22627SCy Schubert 			FD_ZERO(&rfds);
51857e22627SCy Schubert 			// We do not have to block here
51957e22627SCy Schubert 			tv.tv_sec = RPCAP_TIMEOUT_INIT;
52057e22627SCy Schubert 			tv.tv_usec = 0;
52157e22627SCy Schubert 
52257e22627SCy Schubert 			FD_SET(pars.sockctrl, &rfds);
52357e22627SCy Schubert 
524*6f9cba8fSJoseph Mingrone 			retval = select((int)pars.sockctrl + 1, &rfds, NULL, NULL, &tv);
52557e22627SCy Schubert 			if (retval == -1)
52657e22627SCy Schubert 			{
527*6f9cba8fSJoseph Mingrone 				sock_geterrmsg(errmsgbuf, PCAP_ERRBUF_SIZE,
528*6f9cba8fSJoseph Mingrone 				    "select() failed");
529*6f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
53057e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
53157e22627SCy Schubert 				goto end;
53257e22627SCy Schubert 			}
53357e22627SCy Schubert 
53457e22627SCy Schubert 			// The timeout has expired
53557e22627SCy Schubert 			// So, this was a fake connection. Drop it down
53657e22627SCy Schubert 			if (retval == 0)
53757e22627SCy Schubert 			{
538*6f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl, 0, PCAP_ERR_INITTIMEOUT, "The RPCAP initial timeout has expired", errbuf) == -1)
53957e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
54057e22627SCy Schubert 				goto end;
54157e22627SCy Schubert 			}
54257e22627SCy Schubert 		}
54357e22627SCy Schubert 
54457e22627SCy Schubert 		//
54557e22627SCy Schubert 		// Read the message header from the client.
54657e22627SCy Schubert 		//
547*6f9cba8fSJoseph Mingrone 		nrecv = rpcapd_recv_msg_header(pars.sockctrl, pars.ssl, &header);
54857e22627SCy Schubert 		if (nrecv == -1)
54957e22627SCy Schubert 		{
55057e22627SCy Schubert 			// Fatal error.
55157e22627SCy Schubert 			goto end;
55257e22627SCy Schubert 		}
55357e22627SCy Schubert 		if (nrecv == -2)
55457e22627SCy Schubert 		{
55557e22627SCy Schubert 			// Client closed the connection.
55657e22627SCy Schubert 			goto end;
55757e22627SCy Schubert 		}
55857e22627SCy Schubert 
55957e22627SCy Schubert 		plen = header.plen;
56057e22627SCy Schubert 
56157e22627SCy Schubert 		//
56257e22627SCy Schubert 		// While we're in the authentication pharse, all requests
56357e22627SCy Schubert 		// must use version 0.
56457e22627SCy Schubert 		//
56557e22627SCy Schubert 		if (header.ver != 0)
56657e22627SCy Schubert 		{
56757e22627SCy Schubert 			//
56857e22627SCy Schubert 			// Send it back to them with their version.
56957e22627SCy Schubert 			//
570*6f9cba8fSJoseph Mingrone 			if (rpcap_senderror(pars.sockctrl, pars.ssl, header.ver,
57157e22627SCy Schubert 			    PCAP_ERR_WRONGVER,
57257e22627SCy Schubert 			    "RPCAP version in requests in the authentication phase must be 0",
57357e22627SCy Schubert 			    errbuf) == -1)
57457e22627SCy Schubert 			{
57557e22627SCy Schubert 				// That failed; log a message and give up.
57657e22627SCy Schubert 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
57757e22627SCy Schubert 				goto end;
57857e22627SCy Schubert 			}
57957e22627SCy Schubert 
58057e22627SCy Schubert 			// Discard the rest of the message and drop the
58157e22627SCy Schubert 			// connection.
582*6f9cba8fSJoseph Mingrone 			(void)rpcapd_discard(pars.sockctrl, pars.ssl, plen);
58357e22627SCy Schubert 			goto end;
58457e22627SCy Schubert 		}
58557e22627SCy Schubert 
58657e22627SCy Schubert 		switch (header.type)
58757e22627SCy Schubert 		{
58857e22627SCy Schubert 			case RPCAP_MSG_AUTH_REQ:
58957e22627SCy Schubert 				retval = daemon_msg_auth_req(&pars, plen);
59057e22627SCy Schubert 				if (retval == -1)
59157e22627SCy Schubert 				{
59257e22627SCy Schubert 					// Fatal error; a message has
59357e22627SCy Schubert 					// been logged, so just give up.
59457e22627SCy Schubert 					goto end;
59557e22627SCy Schubert 				}
59657e22627SCy Schubert 				if (retval == -2)
59757e22627SCy Schubert 				{
59857e22627SCy Schubert 					// Non-fatal error; we sent back
59957e22627SCy Schubert 					// an error message, so let them
60057e22627SCy Schubert 					// try again.
60157e22627SCy Schubert 					continue;
60257e22627SCy Schubert 				}
60357e22627SCy Schubert 
60457e22627SCy Schubert 				// OK, we're authenticated; we sent back
60557e22627SCy Schubert 				// a reply, so start serving requests.
60657e22627SCy Schubert 				authenticated = 1;
60757e22627SCy Schubert 				break;
60857e22627SCy Schubert 
60957e22627SCy Schubert 			case RPCAP_MSG_CLOSE:
61057e22627SCy Schubert 				//
61157e22627SCy Schubert 				// The client is giving up.
61257e22627SCy Schubert 				// Discard the rest of the message, if
61357e22627SCy Schubert 				// there is anything more.
61457e22627SCy Schubert 				//
615*6f9cba8fSJoseph Mingrone 				(void)rpcapd_discard(pars.sockctrl, pars.ssl, plen);
61657e22627SCy Schubert 				// We're done with this client.
61757e22627SCy Schubert 				goto end;
61857e22627SCy Schubert 
61957e22627SCy Schubert 			case RPCAP_MSG_ERROR:
62057e22627SCy Schubert 				// Log this and close the connection?
62157e22627SCy Schubert 				// XXX - is this what happens in active
62257e22627SCy Schubert 				// mode, where *we* initiate the
62357e22627SCy Schubert 				// connection, and the client gives us
62457e22627SCy Schubert 				// an error message rather than a "let
62557e22627SCy Schubert 				// me log in" message, indicating that
62657e22627SCy Schubert 				// we're not allowed to connect to them?
627*6f9cba8fSJoseph Mingrone 				(void)daemon_msg_err(pars.sockctrl, pars.ssl, plen);
62857e22627SCy Schubert 				goto end;
62957e22627SCy Schubert 
63057e22627SCy Schubert 			case RPCAP_MSG_FINDALLIF_REQ:
63157e22627SCy Schubert 			case RPCAP_MSG_OPEN_REQ:
63257e22627SCy Schubert 			case RPCAP_MSG_STARTCAP_REQ:
63357e22627SCy Schubert 			case RPCAP_MSG_UPDATEFILTER_REQ:
63457e22627SCy Schubert 			case RPCAP_MSG_STATS_REQ:
63557e22627SCy Schubert 			case RPCAP_MSG_ENDCAP_REQ:
63657e22627SCy Schubert 			case RPCAP_MSG_SETSAMPLING_REQ:
63757e22627SCy Schubert 				//
63857e22627SCy Schubert 				// These requests can't be sent until
63957e22627SCy Schubert 				// the client is authenticated.
64057e22627SCy Schubert 				//
64157e22627SCy Schubert 				msg_type_string = rpcap_msg_type_string(header.type);
64257e22627SCy Schubert 				if (msg_type_string != NULL)
64357e22627SCy Schubert 				{
644*6f9cba8fSJoseph Mingrone 					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "%s request sent before authentication was completed", msg_type_string);
64557e22627SCy Schubert 				}
64657e22627SCy Schubert 				else
64757e22627SCy Schubert 				{
648*6f9cba8fSJoseph Mingrone 					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message of type %u sent before authentication was completed", header.type);
64957e22627SCy Schubert 				}
650*6f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
651*6f9cba8fSJoseph Mingrone 				    header.ver, PCAP_ERR_WRONGMSG,
652*6f9cba8fSJoseph Mingrone 				    errmsgbuf, errbuf) == -1)
65357e22627SCy Schubert 				{
65457e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
65557e22627SCy Schubert 					goto end;
65657e22627SCy Schubert 				}
65757e22627SCy Schubert 				// Discard the rest of the message.
658*6f9cba8fSJoseph Mingrone 				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
65957e22627SCy Schubert 				{
66057e22627SCy Schubert 					// Network error.
66157e22627SCy Schubert 					goto end;
66257e22627SCy Schubert 				}
66357e22627SCy Schubert 				break;
66457e22627SCy Schubert 
66557e22627SCy Schubert 			case RPCAP_MSG_PACKET:
66657e22627SCy Schubert 			case RPCAP_MSG_FINDALLIF_REPLY:
66757e22627SCy Schubert 			case RPCAP_MSG_OPEN_REPLY:
66857e22627SCy Schubert 			case RPCAP_MSG_STARTCAP_REPLY:
66957e22627SCy Schubert 			case RPCAP_MSG_UPDATEFILTER_REPLY:
67057e22627SCy Schubert 			case RPCAP_MSG_AUTH_REPLY:
67157e22627SCy Schubert 			case RPCAP_MSG_STATS_REPLY:
67257e22627SCy Schubert 			case RPCAP_MSG_ENDCAP_REPLY:
67357e22627SCy Schubert 			case RPCAP_MSG_SETSAMPLING_REPLY:
67457e22627SCy Schubert 				//
67557e22627SCy Schubert 				// These are server-to-client messages.
67657e22627SCy Schubert 				//
67757e22627SCy Schubert 				msg_type_string = rpcap_msg_type_string(header.type);
67857e22627SCy Schubert 				if (msg_type_string != NULL)
67957e22627SCy Schubert 				{
680*6f9cba8fSJoseph Mingrone 					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message %s received from client", msg_type_string);
68157e22627SCy Schubert 				}
68257e22627SCy Schubert 				else
68357e22627SCy Schubert 				{
684*6f9cba8fSJoseph Mingrone 					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
68557e22627SCy Schubert 				}
686*6f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
687*6f9cba8fSJoseph Mingrone 				    header.ver, PCAP_ERR_WRONGMSG,
688*6f9cba8fSJoseph Mingrone 				    errmsgbuf, errbuf) == -1)
68957e22627SCy Schubert 				{
69057e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
69157e22627SCy Schubert 					goto end;
69257e22627SCy Schubert 				}
69357e22627SCy Schubert 				// Discard the rest of the message.
694*6f9cba8fSJoseph Mingrone 				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
69557e22627SCy Schubert 				{
69657e22627SCy Schubert 					// Fatal error.
69757e22627SCy Schubert 					goto end;
69857e22627SCy Schubert 				}
69957e22627SCy Schubert 				break;
70057e22627SCy Schubert 
70157e22627SCy Schubert 			default:
70257e22627SCy Schubert 				//
70357e22627SCy Schubert 				// Unknown message type.
70457e22627SCy Schubert 				//
705*6f9cba8fSJoseph Mingrone 				snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
706*6f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
707*6f9cba8fSJoseph Mingrone 				    header.ver, PCAP_ERR_WRONGMSG,
708*6f9cba8fSJoseph Mingrone 				    errmsgbuf, errbuf) == -1)
70957e22627SCy Schubert 				{
71057e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
71157e22627SCy Schubert 					goto end;
71257e22627SCy Schubert 				}
71357e22627SCy Schubert 				// Discard the rest of the message.
714*6f9cba8fSJoseph Mingrone 				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
71557e22627SCy Schubert 				{
71657e22627SCy Schubert 					// Fatal error.
71757e22627SCy Schubert 					goto end;
71857e22627SCy Schubert 				}
71957e22627SCy Schubert 				break;
72057e22627SCy Schubert 		}
72157e22627SCy Schubert 	}
72257e22627SCy Schubert 
72357e22627SCy Schubert 	//
72457e22627SCy Schubert 	// OK, the client has authenticated itself, and we can start
72557e22627SCy Schubert 	// processing regular requests from it.
72657e22627SCy Schubert 	//
72757e22627SCy Schubert 
72857e22627SCy Schubert 	//
72957e22627SCy Schubert 	// We don't have any statistics yet.
73057e22627SCy Schubert 	//
73157e22627SCy Schubert 	stats.ps_ifdrop = 0;
73257e22627SCy Schubert 	stats.ps_recv = 0;
73357e22627SCy Schubert 	stats.ps_drop = 0;
73457e22627SCy Schubert 	svrcapt = 0;
73557e22627SCy Schubert 
73657e22627SCy Schubert 	//
73757e22627SCy Schubert 	// Service requests.
73857e22627SCy Schubert 	//
73957e22627SCy Schubert 	for (;;)
74057e22627SCy Schubert 	{
74157e22627SCy Schubert 		errbuf[0] = 0;	// clear errbuf
74257e22627SCy Schubert 
74357e22627SCy Schubert 		// Avoid zombies connections; check if the connection is opens but no commands are performed
74457e22627SCy Schubert 		// from more than RPCAP_TIMEOUT_RUNTIME
74557e22627SCy Schubert 		// Conditions:
74657e22627SCy Schubert 		// - I have to be in normal mode (no active mode)
74757e22627SCy Schubert 		// - if the device is open, I don't have to be in the middle of a capture (session->sockdata)
74857e22627SCy Schubert 		// - if the device is closed, I have always to check if a new command arrives
74957e22627SCy Schubert 		//
75057e22627SCy Schubert 		// Be carefully: the capture can have been started, but an error occurred (so session != NULL, but
75157e22627SCy Schubert 		//  sockdata is 0
752*6f9cba8fSJoseph Mingrone 		if ((!pars.isactive) && (session == NULL || session->sockdata == 0))
75357e22627SCy Schubert 		{
75457e22627SCy Schubert 			// Check for the initial timeout
75557e22627SCy Schubert 			FD_ZERO(&rfds);
75657e22627SCy Schubert 			// We do not have to block here
75757e22627SCy Schubert 			tv.tv_sec = RPCAP_TIMEOUT_RUNTIME;
75857e22627SCy Schubert 			tv.tv_usec = 0;
75957e22627SCy Schubert 
76057e22627SCy Schubert 			FD_SET(pars.sockctrl, &rfds);
761*6f9cba8fSJoseph Mingrone #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
762*6f9cba8fSJoseph Mingrone 			retval = 1;
763*6f9cba8fSJoseph Mingrone #else
764*6f9cba8fSJoseph Mingrone 			retval = select((int)pars.sockctrl + 1, &rfds, NULL, NULL, &tv);
765*6f9cba8fSJoseph Mingrone #endif
76657e22627SCy Schubert 			if (retval == -1)
76757e22627SCy Schubert 			{
768*6f9cba8fSJoseph Mingrone 				sock_geterrmsg(errmsgbuf, PCAP_ERRBUF_SIZE,
769*6f9cba8fSJoseph Mingrone 				    "select() failed");
770*6f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
771*6f9cba8fSJoseph Mingrone 				    0, PCAP_ERR_NETW,
772*6f9cba8fSJoseph Mingrone 				    errmsgbuf, errbuf) == -1)
77357e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
77457e22627SCy Schubert 				goto end;
77557e22627SCy Schubert 			}
77657e22627SCy Schubert 
77757e22627SCy Schubert 			// The timeout has expired
77857e22627SCy Schubert 			// So, this was a fake connection. Drop it down
77957e22627SCy Schubert 			if (retval == 0)
78057e22627SCy Schubert 			{
781*6f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
782*6f9cba8fSJoseph Mingrone 				    0, PCAP_ERR_INITTIMEOUT,
78357e22627SCy Schubert 				    "The RPCAP initial timeout has expired",
78457e22627SCy Schubert 				    errbuf) == -1)
78557e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
78657e22627SCy Schubert 				goto end;
78757e22627SCy Schubert 			}
78857e22627SCy Schubert 		}
78957e22627SCy Schubert 
79057e22627SCy Schubert 		//
79157e22627SCy Schubert 		// Read the message header from the client.
79257e22627SCy Schubert 		//
793*6f9cba8fSJoseph Mingrone 		nrecv = rpcapd_recv_msg_header(pars.sockctrl, pars.ssl, &header);
79457e22627SCy Schubert 		if (nrecv == -1)
79557e22627SCy Schubert 		{
79657e22627SCy Schubert 			// Fatal error.
79757e22627SCy Schubert 			goto end;
79857e22627SCy Schubert 		}
79957e22627SCy Schubert 		if (nrecv == -2)
80057e22627SCy Schubert 		{
80157e22627SCy Schubert 			// Client closed the connection.
80257e22627SCy Schubert 			goto end;
80357e22627SCy Schubert 		}
80457e22627SCy Schubert 
80557e22627SCy Schubert 		plen = header.plen;
80657e22627SCy Schubert 
80757e22627SCy Schubert 		//
80857e22627SCy Schubert 		// Did the client specify a protocol version that we
80957e22627SCy Schubert 		// support?
81057e22627SCy Schubert 		//
81157e22627SCy Schubert 		if (!RPCAP_VERSION_IS_SUPPORTED(header.ver))
81257e22627SCy Schubert 		{
81357e22627SCy Schubert 			//
81457e22627SCy Schubert 			// Tell them it's not a supported version.
81557e22627SCy Schubert 			// Send the error message with their version,
81657e22627SCy Schubert 			// so they don't reject it as having the wrong
81757e22627SCy Schubert 			// version.
81857e22627SCy Schubert 			//
819*6f9cba8fSJoseph Mingrone 			if (rpcap_senderror(pars.sockctrl, pars.ssl,
82057e22627SCy Schubert 			    header.ver, PCAP_ERR_WRONGVER,
82157e22627SCy Schubert 			    "RPCAP version in message isn't supported by the server",
82257e22627SCy Schubert 			    errbuf) == -1)
82357e22627SCy Schubert 			{
82457e22627SCy Schubert 				// That failed; log a message and give up.
82557e22627SCy Schubert 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
82657e22627SCy Schubert 				goto end;
82757e22627SCy Schubert 			}
82857e22627SCy Schubert 
82957e22627SCy Schubert 			// Discard the rest of the message.
830*6f9cba8fSJoseph Mingrone 			(void)rpcapd_discard(pars.sockctrl, pars.ssl, plen);
83157e22627SCy Schubert 			// Give up on them.
83257e22627SCy Schubert 			goto end;
83357e22627SCy Schubert 		}
83457e22627SCy Schubert 
83557e22627SCy Schubert 		switch (header.type)
83657e22627SCy Schubert 		{
83757e22627SCy Schubert 			case RPCAP_MSG_ERROR:		// The other endpoint reported an error
83857e22627SCy Schubert 			{
839*6f9cba8fSJoseph Mingrone 				(void)daemon_msg_err(pars.sockctrl, pars.ssl, plen);
84057e22627SCy Schubert 				// Do nothing; just exit; the error code is already into the errbuf
84157e22627SCy Schubert 				// XXX - actually exit....
84257e22627SCy Schubert 				break;
84357e22627SCy Schubert 			}
84457e22627SCy Schubert 
84557e22627SCy Schubert 			case RPCAP_MSG_FINDALLIF_REQ:
84657e22627SCy Schubert 			{
84757e22627SCy Schubert 				if (daemon_msg_findallif_req(header.ver, &pars, plen) == -1)
84857e22627SCy Schubert 				{
84957e22627SCy Schubert 					// Fatal error; a message has
85057e22627SCy Schubert 					// been logged, so just give up.
85157e22627SCy Schubert 					goto end;
85257e22627SCy Schubert 				}
85357e22627SCy Schubert 				break;
85457e22627SCy Schubert 			}
85557e22627SCy Schubert 
85657e22627SCy Schubert 			case RPCAP_MSG_OPEN_REQ:
85757e22627SCy Schubert 			{
85857e22627SCy Schubert 				//
85957e22627SCy Schubert 				// Process the open request, and keep
86057e22627SCy Schubert 				// the source from it, for use later
86157e22627SCy Schubert 				// when the capture is started.
86257e22627SCy Schubert 				//
86357e22627SCy Schubert 				// XXX - we don't care if the client sends
86457e22627SCy Schubert 				// us multiple open requests, the last
86557e22627SCy Schubert 				// one wins.
86657e22627SCy Schubert 				//
86757e22627SCy Schubert 				retval = daemon_msg_open_req(header.ver, &pars,
86857e22627SCy Schubert 				    plen, source, sizeof(source));
86957e22627SCy Schubert 				if (retval == -1)
87057e22627SCy Schubert 				{
87157e22627SCy Schubert 					// Fatal error; a message has
87257e22627SCy Schubert 					// been logged, so just give up.
87357e22627SCy Schubert 					goto end;
87457e22627SCy Schubert 				}
87557e22627SCy Schubert 				got_source = 1;
87657e22627SCy Schubert 				break;
87757e22627SCy Schubert 			}
87857e22627SCy Schubert 
87957e22627SCy Schubert 			case RPCAP_MSG_STARTCAP_REQ:
88057e22627SCy Schubert 			{
88157e22627SCy Schubert 				if (!got_source)
88257e22627SCy Schubert 				{
88357e22627SCy Schubert 					// They never told us what device
88457e22627SCy Schubert 					// to capture on!
885*6f9cba8fSJoseph Mingrone 					if (rpcap_senderror(pars.sockctrl, pars.ssl,
88657e22627SCy Schubert 					    header.ver,
88757e22627SCy Schubert 					    PCAP_ERR_STARTCAPTURE,
88857e22627SCy Schubert 					    "No capture device was specified",
88957e22627SCy Schubert 					    errbuf) == -1)
89057e22627SCy Schubert 					{
89157e22627SCy Schubert 						// Fatal error; log an
89257e22627SCy Schubert 						// error and  give up.
89357e22627SCy Schubert 						rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
89457e22627SCy Schubert 						goto end;
89557e22627SCy Schubert 					}
896*6f9cba8fSJoseph Mingrone 					if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
89757e22627SCy Schubert 					{
89857e22627SCy Schubert 						goto end;
89957e22627SCy Schubert 					}
90057e22627SCy Schubert 					break;
90157e22627SCy Schubert 				}
90257e22627SCy Schubert 
90357e22627SCy Schubert 				if (daemon_msg_startcap_req(header.ver, &pars,
904*6f9cba8fSJoseph Mingrone 				    plen, source, &session, &samp_param,
905*6f9cba8fSJoseph Mingrone 				    uses_ssl) == -1)
90657e22627SCy Schubert 				{
90757e22627SCy Schubert 					// Fatal error; a message has
90857e22627SCy Schubert 					// been logged, so just give up.
90957e22627SCy Schubert 					goto end;
91057e22627SCy Schubert 				}
91157e22627SCy Schubert 				break;
91257e22627SCy Schubert 			}
91357e22627SCy Schubert 
91457e22627SCy Schubert 			case RPCAP_MSG_UPDATEFILTER_REQ:
91557e22627SCy Schubert 			{
91657e22627SCy Schubert 				if (session)
91757e22627SCy Schubert 				{
91857e22627SCy Schubert 					if (daemon_msg_updatefilter_req(header.ver,
91957e22627SCy Schubert 					    &pars, session, plen) == -1)
92057e22627SCy Schubert 					{
92157e22627SCy Schubert 						// Fatal error; a message has
92257e22627SCy Schubert 						// been logged, so just give up.
92357e22627SCy Schubert 						goto end;
92457e22627SCy Schubert 					}
92557e22627SCy Schubert 				}
92657e22627SCy Schubert 				else
92757e22627SCy Schubert 				{
928*6f9cba8fSJoseph Mingrone 					if (rpcap_senderror(pars.sockctrl, pars.ssl,
929*6f9cba8fSJoseph Mingrone 					    header.ver,
930*6f9cba8fSJoseph Mingrone 					    PCAP_ERR_UPDATEFILTER,
93157e22627SCy Schubert 					    "Device not opened. Cannot update filter",
93257e22627SCy Schubert 					    errbuf) == -1)
93357e22627SCy Schubert 					{
93457e22627SCy Schubert 						// That failed; log a message and give up.
93557e22627SCy Schubert 						rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
93657e22627SCy Schubert 						goto end;
93757e22627SCy Schubert 					}
93857e22627SCy Schubert 				}
93957e22627SCy Schubert 				break;
94057e22627SCy Schubert 			}
94157e22627SCy Schubert 
94257e22627SCy Schubert 			case RPCAP_MSG_CLOSE:		// The other endpoint close the pcap session
94357e22627SCy Schubert 			{
94457e22627SCy Schubert 				//
94557e22627SCy Schubert 				// Indicate to our caller that the client
94657e22627SCy Schubert 				// closed the control connection.
94757e22627SCy Schubert 				// This is used only in case of active mode.
94857e22627SCy Schubert 				//
94957e22627SCy Schubert 				client_told_us_to_close = 1;
95057e22627SCy Schubert 				rpcapd_log(LOGPRIO_DEBUG, "The other end system asked to close the connection.");
95157e22627SCy Schubert 				goto end;
95257e22627SCy Schubert 			}
95357e22627SCy Schubert 
95457e22627SCy Schubert 			case RPCAP_MSG_STATS_REQ:
95557e22627SCy Schubert 			{
95657e22627SCy Schubert 				if (daemon_msg_stats_req(header.ver, &pars,
95757e22627SCy Schubert 				    session, plen, &stats, svrcapt) == -1)
95857e22627SCy Schubert 				{
95957e22627SCy Schubert 					// Fatal error; a message has
96057e22627SCy Schubert 					// been logged, so just give up.
96157e22627SCy Schubert 					goto end;
96257e22627SCy Schubert 				}
96357e22627SCy Schubert 				break;
96457e22627SCy Schubert 			}
96557e22627SCy Schubert 
96657e22627SCy Schubert 			case RPCAP_MSG_ENDCAP_REQ:		// The other endpoint close the current capture session
96757e22627SCy Schubert 			{
96857e22627SCy Schubert 				if (session)
96957e22627SCy Schubert 				{
97057e22627SCy Schubert 					// Save statistics (we can need them in the future)
97157e22627SCy Schubert 					if (pcap_stats(session->fp, &stats))
97257e22627SCy Schubert 					{
97357e22627SCy Schubert 						svrcapt = session->TotCapt;
97457e22627SCy Schubert 					}
97557e22627SCy Schubert 					else
97657e22627SCy Schubert 					{
97757e22627SCy Schubert 						stats.ps_ifdrop = 0;
97857e22627SCy Schubert 						stats.ps_recv = 0;
97957e22627SCy Schubert 						stats.ps_drop = 0;
98057e22627SCy Schubert 						svrcapt = 0;
98157e22627SCy Schubert 					}
98257e22627SCy Schubert 
98357e22627SCy Schubert 					if (daemon_msg_endcap_req(header.ver,
98457e22627SCy Schubert 					    &pars, session) == -1)
98557e22627SCy Schubert 					{
98657e22627SCy Schubert 						free(session);
98757e22627SCy Schubert 						session = NULL;
98857e22627SCy Schubert 						// Fatal error; a message has
98957e22627SCy Schubert 						// been logged, so just give up.
99057e22627SCy Schubert 						goto end;
99157e22627SCy Schubert 					}
99257e22627SCy Schubert 					free(session);
99357e22627SCy Schubert 					session = NULL;
99457e22627SCy Schubert 				}
99557e22627SCy Schubert 				else
99657e22627SCy Schubert 				{
997*6f9cba8fSJoseph Mingrone 					rpcap_senderror(pars.sockctrl, pars.ssl,
998*6f9cba8fSJoseph Mingrone 					    header.ver,
999*6f9cba8fSJoseph Mingrone 					    PCAP_ERR_ENDCAPTURE,
100057e22627SCy Schubert 					    "Device not opened. Cannot close the capture",
100157e22627SCy Schubert 					    errbuf);
100257e22627SCy Schubert 				}
100357e22627SCy Schubert 				break;
100457e22627SCy Schubert 			}
100557e22627SCy Schubert 
100657e22627SCy Schubert 			case RPCAP_MSG_SETSAMPLING_REQ:
100757e22627SCy Schubert 			{
100857e22627SCy Schubert 				if (daemon_msg_setsampling_req(header.ver,
100957e22627SCy Schubert 				    &pars, plen, &samp_param) == -1)
101057e22627SCy Schubert 				{
101157e22627SCy Schubert 					// Fatal error; a message has
101257e22627SCy Schubert 					// been logged, so just give up.
101357e22627SCy Schubert 					goto end;
101457e22627SCy Schubert 				}
101557e22627SCy Schubert 				break;
101657e22627SCy Schubert 			}
101757e22627SCy Schubert 
101857e22627SCy Schubert 			case RPCAP_MSG_AUTH_REQ:
101957e22627SCy Schubert 			{
102057e22627SCy Schubert 				//
102157e22627SCy Schubert 				// We're already authenticated; you don't
102257e22627SCy Schubert 				// get to reauthenticate.
102357e22627SCy Schubert 				//
102457e22627SCy Schubert 				rpcapd_log(LOGPRIO_INFO, "The client sent an RPCAP_MSG_AUTH_REQ message after authentication was completed");
1025*6f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
1026*6f9cba8fSJoseph Mingrone 				    header.ver,
102757e22627SCy Schubert 				    PCAP_ERR_WRONGMSG,
102857e22627SCy Schubert 				    "RPCAP_MSG_AUTH_REQ request sent after authentication was completed",
102957e22627SCy Schubert 				    errbuf) == -1)
103057e22627SCy Schubert 				{
103157e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
103257e22627SCy Schubert 					goto end;
103357e22627SCy Schubert 				}
103457e22627SCy Schubert 				// Discard the rest of the message.
1035*6f9cba8fSJoseph Mingrone 				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
103657e22627SCy Schubert 				{
103757e22627SCy Schubert 					// Fatal error.
103857e22627SCy Schubert 					goto end;
103957e22627SCy Schubert 				}
104057e22627SCy Schubert 				goto end;
104157e22627SCy Schubert 
104257e22627SCy Schubert 			case RPCAP_MSG_PACKET:
104357e22627SCy Schubert 			case RPCAP_MSG_FINDALLIF_REPLY:
104457e22627SCy Schubert 			case RPCAP_MSG_OPEN_REPLY:
104557e22627SCy Schubert 			case RPCAP_MSG_STARTCAP_REPLY:
104657e22627SCy Schubert 			case RPCAP_MSG_UPDATEFILTER_REPLY:
104757e22627SCy Schubert 			case RPCAP_MSG_AUTH_REPLY:
104857e22627SCy Schubert 			case RPCAP_MSG_STATS_REPLY:
104957e22627SCy Schubert 			case RPCAP_MSG_ENDCAP_REPLY:
105057e22627SCy Schubert 			case RPCAP_MSG_SETSAMPLING_REPLY:
105157e22627SCy Schubert 				//
105257e22627SCy Schubert 				// These are server-to-client messages.
105357e22627SCy Schubert 				//
105457e22627SCy Schubert 				msg_type_string = rpcap_msg_type_string(header.type);
105557e22627SCy Schubert 				if (msg_type_string != NULL)
105657e22627SCy Schubert 				{
105757e22627SCy Schubert 					rpcapd_log(LOGPRIO_INFO, "The client sent a %s server-to-client message", msg_type_string);
1058*6f9cba8fSJoseph Mingrone 					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message %s received from client", msg_type_string);
105957e22627SCy Schubert 				}
106057e22627SCy Schubert 				else
106157e22627SCy Schubert 				{
106257e22627SCy Schubert 					rpcapd_log(LOGPRIO_INFO, "The client sent a server-to-client message of type %u", header.type);
1063*6f9cba8fSJoseph Mingrone 					snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
106457e22627SCy Schubert 				}
1065*6f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
1066*6f9cba8fSJoseph Mingrone 				    header.ver, PCAP_ERR_WRONGMSG,
1067*6f9cba8fSJoseph Mingrone 				    errmsgbuf, errbuf) == -1)
106857e22627SCy Schubert 				{
106957e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
107057e22627SCy Schubert 					goto end;
107157e22627SCy Schubert 				}
107257e22627SCy Schubert 				// Discard the rest of the message.
1073*6f9cba8fSJoseph Mingrone 				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
107457e22627SCy Schubert 				{
107557e22627SCy Schubert 					// Fatal error.
107657e22627SCy Schubert 					goto end;
107757e22627SCy Schubert 				}
107857e22627SCy Schubert 				goto end;
107957e22627SCy Schubert 
108057e22627SCy Schubert 			default:
108157e22627SCy Schubert 				//
108257e22627SCy Schubert 				// Unknown message type.
108357e22627SCy Schubert 				//
108457e22627SCy Schubert 				rpcapd_log(LOGPRIO_INFO, "The client sent a message of type %u", header.type);
1085*6f9cba8fSJoseph Mingrone 				snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
1086*6f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars.sockctrl, pars.ssl,
1087*6f9cba8fSJoseph Mingrone 				    header.ver, PCAP_ERR_WRONGMSG,
1088*6f9cba8fSJoseph Mingrone 				    errbuf, errmsgbuf) == -1)
108957e22627SCy Schubert 				{
109057e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
109157e22627SCy Schubert 					goto end;
109257e22627SCy Schubert 				}
109357e22627SCy Schubert 				// Discard the rest of the message.
1094*6f9cba8fSJoseph Mingrone 				if (rpcapd_discard(pars.sockctrl, pars.ssl, plen) == -1)
109557e22627SCy Schubert 				{
109657e22627SCy Schubert 					// Fatal error.
109757e22627SCy Schubert 					goto end;
109857e22627SCy Schubert 				}
109957e22627SCy Schubert 				goto end;
110057e22627SCy Schubert 			}
110157e22627SCy Schubert 		}
110257e22627SCy Schubert 	}
110357e22627SCy Schubert 
110457e22627SCy Schubert end:
110557e22627SCy Schubert 	// The service loop is finishing up.
110657e22627SCy Schubert 	// If we have a capture session running, close it.
110757e22627SCy Schubert 	if (session)
110857e22627SCy Schubert 	{
110957e22627SCy Schubert 		session_close(session);
111057e22627SCy Schubert 		free(session);
111157e22627SCy Schubert 		session = NULL;
111257e22627SCy Schubert 	}
111357e22627SCy Schubert 
1114*6f9cba8fSJoseph Mingrone 	if (passiveClients) {
1115*6f9cba8fSJoseph Mingrone 		free(passiveClients);
1116*6f9cba8fSJoseph Mingrone 	}
1117*6f9cba8fSJoseph Mingrone 	//
1118*6f9cba8fSJoseph Mingrone 	// Finish using the SSL handle for the control socket, if we
1119*6f9cba8fSJoseph Mingrone 	// have an SSL connection, and close the control socket.
1120*6f9cba8fSJoseph Mingrone 	//
1121*6f9cba8fSJoseph Mingrone #ifdef HAVE_OPENSSL
1122*6f9cba8fSJoseph Mingrone 	if (ssl)
1123*6f9cba8fSJoseph Mingrone 	{
1124*6f9cba8fSJoseph Mingrone 		// Finish using the SSL handle for the socket.
1125*6f9cba8fSJoseph Mingrone 		// This must be done *before* the socket is closed.
1126*6f9cba8fSJoseph Mingrone 		ssl_finish(ssl);
1127*6f9cba8fSJoseph Mingrone 	}
1128*6f9cba8fSJoseph Mingrone #endif
112957e22627SCy Schubert 	sock_close(sockctrl, NULL, 0);
113057e22627SCy Schubert 
113157e22627SCy Schubert 	// Print message and return
113257e22627SCy Schubert 	rpcapd_log(LOGPRIO_DEBUG, "I'm exiting from the child loop");
113357e22627SCy Schubert 
113457e22627SCy Schubert 	return client_told_us_to_close;
113557e22627SCy Schubert }
113657e22627SCy Schubert 
113757e22627SCy Schubert /*
113857e22627SCy Schubert  * This handles the RPCAP_MSG_ERR message.
113957e22627SCy Schubert  */
114057e22627SCy Schubert static int
daemon_msg_err(SOCKET sockctrl,SSL * ssl,uint32 plen)1141*6f9cba8fSJoseph Mingrone daemon_msg_err(SOCKET sockctrl, SSL *ssl, uint32 plen)
114257e22627SCy Schubert {
114357e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];
114457e22627SCy Schubert 	char remote_errbuf[PCAP_ERRBUF_SIZE];
114557e22627SCy Schubert 
114657e22627SCy Schubert 	if (plen >= PCAP_ERRBUF_SIZE)
114757e22627SCy Schubert 	{
114857e22627SCy Schubert 		/*
114957e22627SCy Schubert 		 * Message is too long; just read as much of it as we
115057e22627SCy Schubert 		 * can into the buffer provided, and discard the rest.
115157e22627SCy Schubert 		 */
1152*6f9cba8fSJoseph Mingrone 		if (sock_recv(sockctrl, ssl, remote_errbuf, PCAP_ERRBUF_SIZE - 1,
115357e22627SCy Schubert 		    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
115457e22627SCy Schubert 		    PCAP_ERRBUF_SIZE) == -1)
115557e22627SCy Schubert 		{
115657e22627SCy Schubert 			// Network error.
115757e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
115857e22627SCy Schubert 			return -1;
115957e22627SCy Schubert 		}
1160*6f9cba8fSJoseph Mingrone 		if (rpcapd_discard(sockctrl, ssl, plen - (PCAP_ERRBUF_SIZE - 1)) == -1)
116157e22627SCy Schubert 		{
116257e22627SCy Schubert 			// Network error.
116357e22627SCy Schubert 			return -1;
116457e22627SCy Schubert 		}
116557e22627SCy Schubert 
116657e22627SCy Schubert 		/*
116757e22627SCy Schubert 		 * Null-terminate it.
116857e22627SCy Schubert 		 */
116957e22627SCy Schubert 		remote_errbuf[PCAP_ERRBUF_SIZE - 1] = '\0';
117057e22627SCy Schubert 	}
117157e22627SCy Schubert 	else if (plen == 0)
117257e22627SCy Schubert 	{
117357e22627SCy Schubert 		/* Empty error string. */
117457e22627SCy Schubert 		remote_errbuf[0] = '\0';
117557e22627SCy Schubert 	}
117657e22627SCy Schubert 	else
117757e22627SCy Schubert 	{
1178*6f9cba8fSJoseph Mingrone 		if (sock_recv(sockctrl, ssl, remote_errbuf, plen,
117957e22627SCy Schubert 		    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
118057e22627SCy Schubert 		    PCAP_ERRBUF_SIZE) == -1)
118157e22627SCy Schubert 		{
118257e22627SCy Schubert 			// Network error.
118357e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
118457e22627SCy Schubert 			return -1;
118557e22627SCy Schubert 		}
118657e22627SCy Schubert 
118757e22627SCy Schubert 		/*
118857e22627SCy Schubert 		 * Null-terminate it.
118957e22627SCy Schubert 		 */
119057e22627SCy Schubert 		remote_errbuf[plen] = '\0';
119157e22627SCy Schubert 	}
119257e22627SCy Schubert 	// Log the message
119357e22627SCy Schubert 	rpcapd_log(LOGPRIO_ERROR, "Error from client: %s", remote_errbuf);
119457e22627SCy Schubert 	return 0;
119557e22627SCy Schubert }
119657e22627SCy Schubert 
119757e22627SCy Schubert /*
119857e22627SCy Schubert  * This handles the RPCAP_MSG_AUTH_REQ message.
119957e22627SCy Schubert  * It checks if the authentication credentials supplied by the user are valid.
120057e22627SCy Schubert  *
120157e22627SCy Schubert  * This function is called if the daemon receives a RPCAP_MSG_AUTH_REQ
120257e22627SCy Schubert  * message in its authentication loop.  It reads the body of the
120357e22627SCy Schubert  * authentication message from the network and checks whether the
120457e22627SCy Schubert  * credentials are valid.
120557e22627SCy Schubert  *
120657e22627SCy Schubert  * \param sockctrl: the socket for the control connection.
120757e22627SCy Schubert  *
120857e22627SCy Schubert  * \param nullAuthAllowed: '1' if the NULL authentication is allowed.
120957e22627SCy Schubert  *
121057e22627SCy Schubert  * \param errbuf: a user-allocated buffer in which the error message
121157e22627SCy Schubert  * (if one) has to be written.  It must be at least PCAP_ERRBUF_SIZE
121257e22627SCy Schubert  * bytes long.
121357e22627SCy Schubert  *
121457e22627SCy Schubert  * \return '0' if everything is fine, '-1' if an unrecoverable error occurred,
121557e22627SCy Schubert  * or '-2' if the authentication failed.  For errors, an error message is
121657e22627SCy Schubert  * returned in the 'errbuf' variable; this gives a message for the
121757e22627SCy Schubert  * unrecoverable error or for the authentication failure.
121857e22627SCy Schubert  */
121957e22627SCy Schubert static int
daemon_msg_auth_req(struct daemon_slpars * pars,uint32 plen)122057e22627SCy Schubert daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
122157e22627SCy Schubert {
122257e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
122357e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
122457e22627SCy Schubert 	int status;
122557e22627SCy Schubert 	struct rpcap_auth auth;			// RPCAP authentication header
122657e22627SCy Schubert 	char sendbuf[RPCAP_NETBUF_SIZE];	// temporary buffer in which data to be sent is buffered
122757e22627SCy Schubert 	int sendbufidx = 0;			// index which keeps the number of bytes currently buffered
122857e22627SCy Schubert 	struct rpcap_authreply *authreply;	// authentication reply message
122957e22627SCy Schubert 
1230*6f9cba8fSJoseph Mingrone 	status = rpcapd_recv(pars->sockctrl, pars->ssl, (char *) &auth, sizeof(struct rpcap_auth), &plen, errmsgbuf);
123157e22627SCy Schubert 	if (status == -1)
123257e22627SCy Schubert 	{
123357e22627SCy Schubert 		return -1;
123457e22627SCy Schubert 	}
123557e22627SCy Schubert 	if (status == -2)
123657e22627SCy Schubert 	{
123757e22627SCy Schubert 		goto error;
123857e22627SCy Schubert 	}
123957e22627SCy Schubert 
124057e22627SCy Schubert 	switch (ntohs(auth.type))
124157e22627SCy Schubert 	{
124257e22627SCy Schubert 		case RPCAP_RMTAUTH_NULL:
124357e22627SCy Schubert 		{
124457e22627SCy Schubert 			if (!pars->nullAuthAllowed)
124557e22627SCy Schubert 			{
124657e22627SCy Schubert 				// Send the client an error reply.
1247*6f9cba8fSJoseph Mingrone 				snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
124857e22627SCy Schubert 				    "Authentication failed; NULL authentication not permitted.");
1249*6f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars->sockctrl, pars->ssl,
1250*6f9cba8fSJoseph Mingrone 				    0, PCAP_ERR_AUTH_FAILED, errmsgbuf, errbuf) == -1)
125157e22627SCy Schubert 				{
125257e22627SCy Schubert 					// That failed; log a message and give up.
125357e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
125457e22627SCy Schubert 					return -1;
125557e22627SCy Schubert 				}
125657e22627SCy Schubert 				goto error_noreply;
125757e22627SCy Schubert 			}
125857e22627SCy Schubert 			break;
125957e22627SCy Schubert 		}
126057e22627SCy Schubert 
126157e22627SCy Schubert 		case RPCAP_RMTAUTH_PWD:
126257e22627SCy Schubert 		{
126357e22627SCy Schubert 			char *username, *passwd;
126457e22627SCy Schubert 			uint32 usernamelen, passwdlen;
126557e22627SCy Schubert 
126657e22627SCy Schubert 			usernamelen = ntohs(auth.slen1);
126757e22627SCy Schubert 			username = (char *) malloc (usernamelen + 1);
126857e22627SCy Schubert 			if (username == NULL)
126957e22627SCy Schubert 			{
127057e22627SCy Schubert 				pcap_fmt_errmsg_for_errno(errmsgbuf,
127157e22627SCy Schubert 				    PCAP_ERRBUF_SIZE, errno, "malloc() failed");
127257e22627SCy Schubert 				goto error;
127357e22627SCy Schubert 			}
1274*6f9cba8fSJoseph Mingrone 			status = rpcapd_recv(pars->sockctrl, pars->ssl, username, usernamelen, &plen, errmsgbuf);
127557e22627SCy Schubert 			if (status == -1)
127657e22627SCy Schubert 			{
127757e22627SCy Schubert 				free(username);
127857e22627SCy Schubert 				return -1;
127957e22627SCy Schubert 			}
128057e22627SCy Schubert 			if (status == -2)
128157e22627SCy Schubert 			{
128257e22627SCy Schubert 				free(username);
128357e22627SCy Schubert 				goto error;
128457e22627SCy Schubert 			}
128557e22627SCy Schubert 			username[usernamelen] = '\0';
128657e22627SCy Schubert 
128757e22627SCy Schubert 			passwdlen = ntohs(auth.slen2);
128857e22627SCy Schubert 			passwd = (char *) malloc (passwdlen + 1);
128957e22627SCy Schubert 			if (passwd == NULL)
129057e22627SCy Schubert 			{
129157e22627SCy Schubert 				pcap_fmt_errmsg_for_errno(errmsgbuf,
129257e22627SCy Schubert 				    PCAP_ERRBUF_SIZE, errno, "malloc() failed");
129357e22627SCy Schubert 				free(username);
129457e22627SCy Schubert 				goto error;
129557e22627SCy Schubert 			}
1296*6f9cba8fSJoseph Mingrone 			status = rpcapd_recv(pars->sockctrl, pars->ssl, passwd, passwdlen, &plen, errmsgbuf);
129757e22627SCy Schubert 			if (status == -1)
129857e22627SCy Schubert 			{
129957e22627SCy Schubert 				free(username);
130057e22627SCy Schubert 				free(passwd);
130157e22627SCy Schubert 				return -1;
130257e22627SCy Schubert 			}
130357e22627SCy Schubert 			if (status == -2)
130457e22627SCy Schubert 			{
130557e22627SCy Schubert 				free(username);
130657e22627SCy Schubert 				free(passwd);
130757e22627SCy Schubert 				goto error;
130857e22627SCy Schubert 			}
130957e22627SCy Schubert 			passwd[passwdlen] = '\0';
131057e22627SCy Schubert 
131157e22627SCy Schubert 			if (daemon_AuthUserPwd(username, passwd, errmsgbuf))
131257e22627SCy Schubert 			{
131357e22627SCy Schubert 				//
131457e22627SCy Schubert 				// Authentication failed.  Let the client
131557e22627SCy Schubert 				// know.
131657e22627SCy Schubert 				//
131757e22627SCy Schubert 				free(username);
131857e22627SCy Schubert 				free(passwd);
1319*6f9cba8fSJoseph Mingrone 				if (rpcap_senderror(pars->sockctrl, pars->ssl,
1320*6f9cba8fSJoseph Mingrone 				    0, PCAP_ERR_AUTH_FAILED, errmsgbuf, errbuf) == -1)
132157e22627SCy Schubert 				{
132257e22627SCy Schubert 					// That failed; log a message and give up.
132357e22627SCy Schubert 					rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
132457e22627SCy Schubert 					return -1;
132557e22627SCy Schubert 				}
132657e22627SCy Schubert 
132757e22627SCy Schubert 				//
132857e22627SCy Schubert 				// Suspend for 1 second, so that they can't
132957e22627SCy Schubert 				// hammer us with repeated tries with an
133057e22627SCy Schubert 				// attack such as a dictionary attack.
133157e22627SCy Schubert 				//
133257e22627SCy Schubert 				// WARNING: this delay is inserted only
133357e22627SCy Schubert 				// at this point; if the client closes the
133457e22627SCy Schubert 				// connection and reconnects, the suspension
133557e22627SCy Schubert 				// time does not have any effect.
133657e22627SCy Schubert 				//
133757e22627SCy Schubert 				sleep_secs(RPCAP_SUSPEND_WRONGAUTH);
133857e22627SCy Schubert 				goto error_noreply;
133957e22627SCy Schubert 			}
134057e22627SCy Schubert 
134157e22627SCy Schubert 			free(username);
134257e22627SCy Schubert 			free(passwd);
134357e22627SCy Schubert 			break;
134457e22627SCy Schubert 			}
134557e22627SCy Schubert 
134657e22627SCy Schubert 		default:
1347*6f9cba8fSJoseph Mingrone 			snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
134857e22627SCy Schubert 			    "Authentication type not recognized.");
1349*6f9cba8fSJoseph Mingrone 			if (rpcap_senderror(pars->sockctrl, pars->ssl,
1350*6f9cba8fSJoseph Mingrone 			    0, PCAP_ERR_AUTH_TYPE_NOTSUP, errmsgbuf, errbuf) == -1)
135157e22627SCy Schubert 			{
135257e22627SCy Schubert 				// That failed; log a message and give up.
135357e22627SCy Schubert 				rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
135457e22627SCy Schubert 				return -1;
135557e22627SCy Schubert 			}
135657e22627SCy Schubert 			goto error_noreply;
135757e22627SCy Schubert 	}
135857e22627SCy Schubert 
135957e22627SCy Schubert 	// The authentication succeeded; let the client know.
136057e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
136157e22627SCy Schubert 	    RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
136257e22627SCy Schubert 		goto error;
136357e22627SCy Schubert 
136457e22627SCy Schubert 	rpcap_createhdr((struct rpcap_header *) sendbuf, 0,
136557e22627SCy Schubert 	    RPCAP_MSG_AUTH_REPLY, 0, sizeof(struct rpcap_authreply));
136657e22627SCy Schubert 
136757e22627SCy Schubert 	authreply = (struct rpcap_authreply *) &sendbuf[sendbufidx];
136857e22627SCy Schubert 
136957e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_authreply), NULL, &sendbufidx,
137057e22627SCy Schubert 	    RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
137157e22627SCy Schubert 		goto error;
137257e22627SCy Schubert 
137357e22627SCy Schubert 	//
1374*6f9cba8fSJoseph Mingrone 	// Indicate to our peer what versions we support and what our
1375*6f9cba8fSJoseph Mingrone 	// version of the byte-order magic is (which will tell the
1376*6f9cba8fSJoseph Mingrone 	// client whether our byte order differs from theirs, in which
1377*6f9cba8fSJoseph Mingrone 	// case they will need to byte-swap some fields in some
1378*6f9cba8fSJoseph Mingrone 	// link-layer types' headers).
137957e22627SCy Schubert 	//
138057e22627SCy Schubert 	memset(authreply, 0, sizeof(struct rpcap_authreply));
138157e22627SCy Schubert 	authreply->minvers = RPCAP_MIN_VERSION;
138257e22627SCy Schubert 	authreply->maxvers = RPCAP_MAX_VERSION;
1383*6f9cba8fSJoseph Mingrone 	authreply->byte_order_magic = RPCAP_BYTE_ORDER_MAGIC;
138457e22627SCy Schubert 
138557e22627SCy Schubert 	// Send the reply.
1386*6f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
138757e22627SCy Schubert 	{
1388*6f9cba8fSJoseph Mingrone 		// That failed; log a message and give up.
138957e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
139057e22627SCy Schubert 		return -1;
139157e22627SCy Schubert 	}
139257e22627SCy Schubert 
139357e22627SCy Schubert 	// Check if all the data has been read; if not, discard the data in excess
1394*6f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
139557e22627SCy Schubert 	{
139657e22627SCy Schubert 		return -1;
139757e22627SCy Schubert 	}
139857e22627SCy Schubert 
139957e22627SCy Schubert 	return 0;
140057e22627SCy Schubert 
140157e22627SCy Schubert error:
1402*6f9cba8fSJoseph Mingrone 	if (rpcap_senderror(pars->sockctrl, pars->ssl, 0, PCAP_ERR_AUTH,
1403*6f9cba8fSJoseph Mingrone 	    errmsgbuf, errbuf) == -1)
140457e22627SCy Schubert 	{
140557e22627SCy Schubert 		// That failed; log a message and give up.
140657e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
140757e22627SCy Schubert 		return -1;
140857e22627SCy Schubert 	}
140957e22627SCy Schubert 
141057e22627SCy Schubert error_noreply:
141157e22627SCy Schubert 	// Check if all the data has been read; if not, discard the data in excess
1412*6f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
141357e22627SCy Schubert 	{
141457e22627SCy Schubert 		return -1;
141557e22627SCy Schubert 	}
141657e22627SCy Schubert 
141757e22627SCy Schubert 	return -2;
141857e22627SCy Schubert }
141957e22627SCy Schubert 
142057e22627SCy Schubert static int
daemon_AuthUserPwd(char * username,char * password,char * errbuf)142157e22627SCy Schubert daemon_AuthUserPwd(char *username, char *password, char *errbuf)
142257e22627SCy Schubert {
142357e22627SCy Schubert #ifdef _WIN32
142457e22627SCy Schubert 	/*
142557e22627SCy Schubert 	 * Warning: the user which launches the process must have the
142657e22627SCy Schubert 	 * SE_TCB_NAME right.
142757e22627SCy Schubert 	 * This corresponds to have the "Act as part of the Operating System"
142857e22627SCy Schubert 	 * turned on (administrative tools, local security settings, local
142957e22627SCy Schubert 	 * policies, user right assignment)
143057e22627SCy Schubert 	 * However, it seems to me that if you run it as a service, this
143157e22627SCy Schubert 	 * right should be provided by default.
143257e22627SCy Schubert 	 *
143357e22627SCy Schubert 	 * XXX - hopefully, this returns errors such as ERROR_LOGON_FAILURE,
143457e22627SCy Schubert 	 * which merely indicates that the user name or password is
143557e22627SCy Schubert 	 * incorrect, not whether it's the user name or the password
143657e22627SCy Schubert 	 * that's incorrect, so a client that's trying to brute-force
143757e22627SCy Schubert 	 * accounts doesn't know whether it's the user name or the
143857e22627SCy Schubert 	 * password that's incorrect, so it doesn't know whether to
143957e22627SCy Schubert 	 * stop trying to log in with a given user name and move on
144057e22627SCy Schubert 	 * to another user name.
144157e22627SCy Schubert 	 */
144257e22627SCy Schubert 	DWORD error;
144357e22627SCy Schubert 	HANDLE Token;
144457e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to log
144557e22627SCy Schubert 
144657e22627SCy Schubert 	if (LogonUser(username, ".", password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &Token) == 0)
144757e22627SCy Schubert 	{
1448*6f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
144957e22627SCy Schubert 		error = GetLastError();
145057e22627SCy Schubert 		if (error != ERROR_LOGON_FAILURE)
145157e22627SCy Schubert 		{
145257e22627SCy Schubert 			// Some error other than an authentication error;
145357e22627SCy Schubert 			// log it.
145457e22627SCy Schubert 			pcap_fmt_errmsg_for_win32_err(errmsgbuf,
145557e22627SCy Schubert 			    PCAP_ERRBUF_SIZE, error, "LogonUser() failed");
145657e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
145757e22627SCy Schubert 		}
145857e22627SCy Schubert 		return -1;
145957e22627SCy Schubert 	}
146057e22627SCy Schubert 
146157e22627SCy Schubert 	// This call should change the current thread to the selected user.
146257e22627SCy Schubert 	// I didn't test it.
146357e22627SCy Schubert 	if (ImpersonateLoggedOnUser(Token) == 0)
146457e22627SCy Schubert 	{
1465*6f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
146657e22627SCy Schubert 		pcap_fmt_errmsg_for_win32_err(errmsgbuf, PCAP_ERRBUF_SIZE,
146757e22627SCy Schubert 		    GetLastError(), "ImpersonateLoggedOnUser() failed");
146857e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
146957e22627SCy Schubert 		CloseHandle(Token);
147057e22627SCy Schubert 		return -1;
147157e22627SCy Schubert 	}
147257e22627SCy Schubert 
147357e22627SCy Schubert 	CloseHandle(Token);
147457e22627SCy Schubert 	return 0;
147557e22627SCy Schubert 
147657e22627SCy Schubert #else
147757e22627SCy Schubert 	/*
147857e22627SCy Schubert 	 * See
147957e22627SCy Schubert 	 *
1480*6f9cba8fSJoseph Mingrone 	 *	https://www.unixpapa.com/incnote/passwd.html
148157e22627SCy Schubert 	 *
148257e22627SCy Schubert 	 * We use the Solaris/Linux shadow password authentication if
148357e22627SCy Schubert 	 * we have getspnam(), otherwise we just do traditional
148457e22627SCy Schubert 	 * authentication, which, on some platforms, might work, even
148557e22627SCy Schubert 	 * with shadow passwords, if we're running as root.  Traditional
148657e22627SCy Schubert 	 * authenticaion won't work if we're not running as root, as
148757e22627SCy Schubert 	 * I think these days all UN*Xes either won't return the password
148857e22627SCy Schubert 	 * at all with getpwnam() or will only do so if you're root.
148957e22627SCy Schubert 	 *
149057e22627SCy Schubert 	 * XXX - perhaps what we *should* be using is PAM, if we have
149157e22627SCy Schubert 	 * it.  That might hide all the details of username/password
149257e22627SCy Schubert 	 * authentication, whether it's done with a visible-to-root-
149357e22627SCy Schubert 	 * only password database or some other authentication mechanism,
149457e22627SCy Schubert 	 * behind its API.
149557e22627SCy Schubert 	 */
149657e22627SCy Schubert 	int error;
149757e22627SCy Schubert 	struct passwd *user;
149857e22627SCy Schubert 	char *user_password;
149957e22627SCy Schubert #ifdef HAVE_GETSPNAM
150057e22627SCy Schubert 	struct spwd *usersp;
150157e22627SCy Schubert #endif
150257e22627SCy Schubert 	char *crypt_password;
150357e22627SCy Schubert 
150457e22627SCy Schubert 	// This call is needed to get the uid
150557e22627SCy Schubert 	if ((user = getpwnam(username)) == NULL)
150657e22627SCy Schubert 	{
1507*6f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
150857e22627SCy Schubert 		return -1;
150957e22627SCy Schubert 	}
151057e22627SCy Schubert 
151157e22627SCy Schubert #ifdef HAVE_GETSPNAM
151257e22627SCy Schubert 	// This call is needed to get the password; otherwise 'x' is returned
151357e22627SCy Schubert 	if ((usersp = getspnam(username)) == NULL)
151457e22627SCy Schubert 	{
1515*6f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
151657e22627SCy Schubert 		return -1;
151757e22627SCy Schubert 	}
151857e22627SCy Schubert 	user_password = usersp->sp_pwdp;
151957e22627SCy Schubert #else
152057e22627SCy Schubert 	/*
152157e22627SCy Schubert 	 * XXX - what about other platforms?
152257e22627SCy Schubert 	 * The unixpapa.com page claims this Just Works on *BSD if you're
152357e22627SCy Schubert 	 * running as root - it's from 2000, so it doesn't indicate whether
152457e22627SCy Schubert 	 * macOS (which didn't come out until 2001, under the name Mac OS
152557e22627SCy Schubert 	 * X) behaves like the *BSDs or not, and might also work on AIX.
152657e22627SCy Schubert 	 * HP-UX does something else.
152757e22627SCy Schubert 	 *
152857e22627SCy Schubert 	 * Again, hopefully PAM hides all that.
152957e22627SCy Schubert 	 */
153057e22627SCy Schubert 	user_password = user->pw_passwd;
153157e22627SCy Schubert #endif
153257e22627SCy Schubert 
153357e22627SCy Schubert 	//
153457e22627SCy Schubert 	// The Single UNIX Specification says that if crypt() fails it
153557e22627SCy Schubert 	// sets errno, but some implementatons that haven't been run
153657e22627SCy Schubert 	// through the SUS test suite might not do so.
153757e22627SCy Schubert 	//
153857e22627SCy Schubert 	errno = 0;
153957e22627SCy Schubert 	crypt_password = crypt(password, user_password);
154057e22627SCy Schubert 	if (crypt_password == NULL)
154157e22627SCy Schubert 	{
154257e22627SCy Schubert 		error = errno;
1543*6f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
154457e22627SCy Schubert 		if (error == 0)
154557e22627SCy Schubert 		{
154657e22627SCy Schubert 			// It didn't set errno.
154757e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "crypt() failed");
154857e22627SCy Schubert 		}
154957e22627SCy Schubert 		else
155057e22627SCy Schubert 		{
155157e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "crypt() failed: %s",
155257e22627SCy Schubert 			    strerror(error));
155357e22627SCy Schubert 		}
155457e22627SCy Schubert 		return -1;
155557e22627SCy Schubert 	}
155657e22627SCy Schubert 	if (strcmp(user_password, crypt_password) != 0)
155757e22627SCy Schubert 	{
1558*6f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
155957e22627SCy Schubert 		return -1;
156057e22627SCy Schubert 	}
156157e22627SCy Schubert 
156257e22627SCy Schubert 	if (setuid(user->pw_uid))
156357e22627SCy Schubert 	{
156457e22627SCy Schubert 		error = errno;
156557e22627SCy Schubert 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
156657e22627SCy Schubert 		    error, "setuid");
156757e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "setuid() failed: %s",
156857e22627SCy Schubert 		    strerror(error));
156957e22627SCy Schubert 		return -1;
157057e22627SCy Schubert 	}
157157e22627SCy Schubert 
157257e22627SCy Schubert /*	if (setgid(user->pw_gid))
157357e22627SCy Schubert 	{
157457e22627SCy Schubert 		error = errno;
157557e22627SCy Schubert 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
157657e22627SCy Schubert 		    errno, "setgid");
157757e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "setgid() failed: %s",
157857e22627SCy Schubert 		    strerror(error));
157957e22627SCy Schubert 		return -1;
158057e22627SCy Schubert 	}
158157e22627SCy Schubert */
158257e22627SCy Schubert 	return 0;
158357e22627SCy Schubert 
158457e22627SCy Schubert #endif
158557e22627SCy Schubert 
158657e22627SCy Schubert }
158757e22627SCy Schubert 
1588*6f9cba8fSJoseph Mingrone /*
1589*6f9cba8fSJoseph Mingrone  * Make sure that the reply length won't overflow 32 bits if we add the
1590*6f9cba8fSJoseph Mingrone  * specified amount to it.  If it won't, add that amount to it.
1591*6f9cba8fSJoseph Mingrone  *
1592*6f9cba8fSJoseph Mingrone  * We check whether replylen + itemlen > UINT32_MAX, but subtract itemlen
1593*6f9cba8fSJoseph Mingrone  * from both sides, to prevent overflow.
1594*6f9cba8fSJoseph Mingrone  */
1595*6f9cba8fSJoseph Mingrone #define CHECK_AND_INCREASE_REPLY_LEN(itemlen) \
1596*6f9cba8fSJoseph Mingrone 	if (replylen > UINT32_MAX - (itemlen)) { \
1597*6f9cba8fSJoseph Mingrone 		pcap_strlcpy(errmsgbuf, "Reply length doesn't fit in 32 bits", \
1598*6f9cba8fSJoseph Mingrone 		    sizeof (errmsgbuf)); \
1599*6f9cba8fSJoseph Mingrone 		goto error; \
1600*6f9cba8fSJoseph Mingrone 	} \
1601*6f9cba8fSJoseph Mingrone 	replylen += (uint32)(itemlen)
1602*6f9cba8fSJoseph Mingrone 
160357e22627SCy Schubert static int
daemon_msg_findallif_req(uint8 ver,struct daemon_slpars * pars,uint32 plen)160457e22627SCy Schubert daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars, uint32 plen)
160557e22627SCy Schubert {
160657e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
160757e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
160857e22627SCy Schubert 	char sendbuf[RPCAP_NETBUF_SIZE];	// temporary buffer in which data to be sent is buffered
160957e22627SCy Schubert 	int sendbufidx = 0;			// index which keeps the number of bytes currently buffered
161057e22627SCy Schubert 	pcap_if_t *alldevs = NULL;		// pointer to the header of the interface chain
161157e22627SCy Schubert 	pcap_if_t *d;				// temp pointer needed to scan the interface chain
161257e22627SCy Schubert 	struct pcap_addr *address;		// pcap structure that keeps a network address of an interface
161357e22627SCy Schubert 	uint32 replylen;			// length of reply payload
161457e22627SCy Schubert 	uint16 nif = 0;				// counts the number of interface listed
161557e22627SCy Schubert 
161657e22627SCy Schubert 	// Discard the rest of the message; there shouldn't be any payload.
1617*6f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
161857e22627SCy Schubert 	{
161957e22627SCy Schubert 		// Network error.
162057e22627SCy Schubert 		return -1;
162157e22627SCy Schubert 	}
162257e22627SCy Schubert 
162357e22627SCy Schubert 	// Retrieve the device list
162457e22627SCy Schubert 	if (pcap_findalldevs(&alldevs, errmsgbuf) == -1)
162557e22627SCy Schubert 		goto error;
162657e22627SCy Schubert 
162757e22627SCy Schubert 	if (alldevs == NULL)
162857e22627SCy Schubert 	{
1629*6f9cba8fSJoseph Mingrone 		if (rpcap_senderror(pars->sockctrl, pars->ssl, ver,
1630*6f9cba8fSJoseph Mingrone 			PCAP_ERR_NOREMOTEIF,
163157e22627SCy Schubert 			"No interfaces found! Make sure libpcap/WinPcap is properly installed"
163257e22627SCy Schubert 			" and you have the right to access to the remote device.",
163357e22627SCy Schubert 			errbuf) == -1)
163457e22627SCy Schubert 		{
163557e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
163657e22627SCy Schubert 			return -1;
163757e22627SCy Schubert 		}
163857e22627SCy Schubert 		return 0;
163957e22627SCy Schubert 	}
164057e22627SCy Schubert 
164157e22627SCy Schubert 	// This checks the number of interfaces and computes the total
164257e22627SCy Schubert 	// length of the payload.
164357e22627SCy Schubert 	replylen = 0;
164457e22627SCy Schubert 	for (d = alldevs; d != NULL; d = d->next)
164557e22627SCy Schubert 	{
164657e22627SCy Schubert 		nif++;
164757e22627SCy Schubert 
1648*6f9cba8fSJoseph Mingrone 		if (d->description) {
1649*6f9cba8fSJoseph Mingrone 			size_t stringlen = strlen(d->description);
1650*6f9cba8fSJoseph Mingrone 			if (stringlen > UINT16_MAX) {
1651*6f9cba8fSJoseph Mingrone 				pcap_strlcpy(errmsgbuf,
1652*6f9cba8fSJoseph Mingrone 				    "Description length doesn't fit in 16 bits",
1653*6f9cba8fSJoseph Mingrone 				    sizeof (errmsgbuf));
1654*6f9cba8fSJoseph Mingrone 				goto error;
1655*6f9cba8fSJoseph Mingrone 			}
1656*6f9cba8fSJoseph Mingrone 			CHECK_AND_INCREASE_REPLY_LEN(stringlen);
1657*6f9cba8fSJoseph Mingrone 		}
1658*6f9cba8fSJoseph Mingrone 		if (d->name) {
1659*6f9cba8fSJoseph Mingrone 			size_t stringlen = strlen(d->name);
1660*6f9cba8fSJoseph Mingrone 			if (stringlen > UINT16_MAX) {
1661*6f9cba8fSJoseph Mingrone 				pcap_strlcpy(errmsgbuf,
1662*6f9cba8fSJoseph Mingrone 				    "Name length doesn't fit in 16 bits",
1663*6f9cba8fSJoseph Mingrone 				    sizeof (errmsgbuf));
1664*6f9cba8fSJoseph Mingrone 				goto error;
1665*6f9cba8fSJoseph Mingrone 			}
1666*6f9cba8fSJoseph Mingrone 			CHECK_AND_INCREASE_REPLY_LEN(stringlen);
1667*6f9cba8fSJoseph Mingrone 		}
166857e22627SCy Schubert 
1669*6f9cba8fSJoseph Mingrone 		CHECK_AND_INCREASE_REPLY_LEN(sizeof(struct rpcap_findalldevs_if));
167057e22627SCy Schubert 
1671*6f9cba8fSJoseph Mingrone 		uint16_t naddrs = 0;
167257e22627SCy Schubert 		for (address = d->addresses; address != NULL; address = address->next)
167357e22627SCy Schubert 		{
167457e22627SCy Schubert 			/*
167557e22627SCy Schubert 			 * Send only IPv4 and IPv6 addresses over the wire.
167657e22627SCy Schubert 			 */
167757e22627SCy Schubert 			switch (address->addr->sa_family)
167857e22627SCy Schubert 			{
167957e22627SCy Schubert 			case AF_INET:
168057e22627SCy Schubert #ifdef AF_INET6
168157e22627SCy Schubert 			case AF_INET6:
168257e22627SCy Schubert #endif
1683*6f9cba8fSJoseph Mingrone 				CHECK_AND_INCREASE_REPLY_LEN(sizeof(struct rpcap_sockaddr) * 4);
1684*6f9cba8fSJoseph Mingrone 				if (naddrs == UINT16_MAX) {
1685*6f9cba8fSJoseph Mingrone 					pcap_strlcpy(errmsgbuf,
1686*6f9cba8fSJoseph Mingrone 					    "Number of interfaces doesn't fit in 16 bits",
1687*6f9cba8fSJoseph Mingrone 					    sizeof (errmsgbuf));
1688*6f9cba8fSJoseph Mingrone 					goto error;
1689*6f9cba8fSJoseph Mingrone 				}
1690*6f9cba8fSJoseph Mingrone 				naddrs++;
169157e22627SCy Schubert 				break;
169257e22627SCy Schubert 
169357e22627SCy Schubert 			default:
169457e22627SCy Schubert 				break;
169557e22627SCy Schubert 			}
169657e22627SCy Schubert 		}
169757e22627SCy Schubert 	}
169857e22627SCy Schubert 
1699*6f9cba8fSJoseph Mingrone 	// RPCAP findalldevs reply
170057e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
170157e22627SCy Schubert 	    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf,
170257e22627SCy Schubert 	    PCAP_ERRBUF_SIZE) == -1)
170357e22627SCy Schubert 		goto error;
170457e22627SCy Schubert 
170557e22627SCy Schubert 	rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
170657e22627SCy Schubert 	    RPCAP_MSG_FINDALLIF_REPLY, nif, replylen);
170757e22627SCy Schubert 
170857e22627SCy Schubert 	// send the interface list
170957e22627SCy Schubert 	for (d = alldevs; d != NULL; d = d->next)
171057e22627SCy Schubert 	{
171157e22627SCy Schubert 		uint16 lname, ldescr;
171257e22627SCy Schubert 
1713*6f9cba8fSJoseph Mingrone 		// Note: the findalldevs_if entries are *not* neatly
1714*6f9cba8fSJoseph Mingrone 		// aligned on 4-byte boundaries, because they're
1715*6f9cba8fSJoseph Mingrone 		// preceded by strings that aren't padded to 4-byte
1716*6f9cba8fSJoseph Mingrone 		// boundaries, so we cannot just cast output buffer
1717*6f9cba8fSJoseph Mingrone 		// boundaries to struct rpcap_findalldevs_if pointers
1718*6f9cba8fSJoseph Mingrone 		// and store into them - we must fill in a structure and
1719*6f9cba8fSJoseph Mingrone 		// then copy the structure to the buffer, as not all
1720*6f9cba8fSJoseph Mingrone 		// systems support unaligned access (some, such as
1721*6f9cba8fSJoseph Mingrone 		// SPARC, crash; others, such as Arm, may just ignore
1722*6f9cba8fSJoseph Mingrone 		// the lower-order bits).
1723*6f9cba8fSJoseph Mingrone 		struct rpcap_findalldevs_if findalldevs_if;
172457e22627SCy Schubert 
1725*6f9cba8fSJoseph Mingrone 		/*
1726*6f9cba8fSJoseph Mingrone 		 * We've already established that the string lengths
1727*6f9cba8fSJoseph Mingrone 		 * fit in 16 bits.
1728*6f9cba8fSJoseph Mingrone 		 */
1729*6f9cba8fSJoseph Mingrone 		if (d->description)
1730*6f9cba8fSJoseph Mingrone 			ldescr = (uint16) strlen(d->description);
1731*6f9cba8fSJoseph Mingrone 		else
1732*6f9cba8fSJoseph Mingrone 			ldescr = 0;
1733*6f9cba8fSJoseph Mingrone 		if (d->name)
1734*6f9cba8fSJoseph Mingrone 			lname = (uint16) strlen(d->name);
1735*6f9cba8fSJoseph Mingrone 		else
1736*6f9cba8fSJoseph Mingrone 			lname = 0;
173757e22627SCy Schubert 
1738*6f9cba8fSJoseph Mingrone 		findalldevs_if.desclen = htons(ldescr);
1739*6f9cba8fSJoseph Mingrone 		findalldevs_if.namelen = htons(lname);
1740*6f9cba8fSJoseph Mingrone 		findalldevs_if.flags = htonl(d->flags);
174157e22627SCy Schubert 
1742*6f9cba8fSJoseph Mingrone 		uint16_t naddrs = 0;
174357e22627SCy Schubert 		for (address = d->addresses; address != NULL; address = address->next)
174457e22627SCy Schubert 		{
174557e22627SCy Schubert 			/*
174657e22627SCy Schubert 			 * Send only IPv4 and IPv6 addresses over the wire.
174757e22627SCy Schubert 			 */
174857e22627SCy Schubert 			switch (address->addr->sa_family)
174957e22627SCy Schubert 			{
175057e22627SCy Schubert 			case AF_INET:
175157e22627SCy Schubert #ifdef AF_INET6
175257e22627SCy Schubert 			case AF_INET6:
175357e22627SCy Schubert #endif
1754*6f9cba8fSJoseph Mingrone 				naddrs++;
175557e22627SCy Schubert 				break;
175657e22627SCy Schubert 
175757e22627SCy Schubert 			default:
175857e22627SCy Schubert 				break;
175957e22627SCy Schubert 			}
176057e22627SCy Schubert 		}
1761*6f9cba8fSJoseph Mingrone 		findalldevs_if.naddr = htons(naddrs);
1762*6f9cba8fSJoseph Mingrone 		findalldevs_if.dummy = 0;
1763*6f9cba8fSJoseph Mingrone 
1764*6f9cba8fSJoseph Mingrone 		if (sock_bufferize(&findalldevs_if, sizeof(struct rpcap_findalldevs_if), sendbuf,
1765*6f9cba8fSJoseph Mingrone 		    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errmsgbuf,
1766*6f9cba8fSJoseph Mingrone 		    PCAP_ERRBUF_SIZE) == -1)
1767*6f9cba8fSJoseph Mingrone 			goto error;
176857e22627SCy Schubert 
176957e22627SCy Schubert 		if (sock_bufferize(d->name, lname, sendbuf, &sendbufidx,
177057e22627SCy Schubert 		    RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errmsgbuf,
177157e22627SCy Schubert 		    PCAP_ERRBUF_SIZE) == -1)
177257e22627SCy Schubert 			goto error;
177357e22627SCy Schubert 
177457e22627SCy Schubert 		if (sock_bufferize(d->description, ldescr, sendbuf, &sendbufidx,
177557e22627SCy Schubert 		    RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errmsgbuf,
177657e22627SCy Schubert 		    PCAP_ERRBUF_SIZE) == -1)
177757e22627SCy Schubert 			goto error;
177857e22627SCy Schubert 
177957e22627SCy Schubert 		// send all addresses
178057e22627SCy Schubert 		for (address = d->addresses; address != NULL; address = address->next)
178157e22627SCy Schubert 		{
178257e22627SCy Schubert 			struct rpcap_sockaddr *sockaddr;
178357e22627SCy Schubert 
178457e22627SCy Schubert 			/*
178557e22627SCy Schubert 			 * Send only IPv4 and IPv6 addresses over the wire.
178657e22627SCy Schubert 			 */
178757e22627SCy Schubert 			switch (address->addr->sa_family)
178857e22627SCy Schubert 			{
178957e22627SCy Schubert 			case AF_INET:
179057e22627SCy Schubert #ifdef AF_INET6
179157e22627SCy Schubert 			case AF_INET6:
179257e22627SCy Schubert #endif
179357e22627SCy Schubert 				sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
179457e22627SCy Schubert 				if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
179557e22627SCy Schubert 				    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
179657e22627SCy Schubert 					goto error;
179757e22627SCy Schubert 				daemon_seraddr((struct sockaddr_storage *) address->addr, sockaddr);
179857e22627SCy Schubert 
179957e22627SCy Schubert 				sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
180057e22627SCy Schubert 				if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
180157e22627SCy Schubert 				    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
180257e22627SCy Schubert 					goto error;
180357e22627SCy Schubert 				daemon_seraddr((struct sockaddr_storage *) address->netmask, sockaddr);
180457e22627SCy Schubert 
180557e22627SCy Schubert 				sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
180657e22627SCy Schubert 				if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
180757e22627SCy Schubert 				    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
180857e22627SCy Schubert 					goto error;
180957e22627SCy Schubert 				daemon_seraddr((struct sockaddr_storage *) address->broadaddr, sockaddr);
181057e22627SCy Schubert 
181157e22627SCy Schubert 				sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
181257e22627SCy Schubert 				if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
181357e22627SCy Schubert 				    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
181457e22627SCy Schubert 					goto error;
181557e22627SCy Schubert 				daemon_seraddr((struct sockaddr_storage *) address->dstaddr, sockaddr);
181657e22627SCy Schubert 				break;
181757e22627SCy Schubert 
181857e22627SCy Schubert 			default:
181957e22627SCy Schubert 				break;
182057e22627SCy Schubert 			}
182157e22627SCy Schubert 		}
182257e22627SCy Schubert 	}
182357e22627SCy Schubert 
182457e22627SCy Schubert 	// We no longer need the device list. Free it.
182557e22627SCy Schubert 	pcap_freealldevs(alldevs);
182657e22627SCy Schubert 
182757e22627SCy Schubert 	// Send a final command that says "now send it!"
1828*6f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
182957e22627SCy Schubert 	{
183057e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
183157e22627SCy Schubert 		return -1;
183257e22627SCy Schubert 	}
183357e22627SCy Schubert 
183457e22627SCy Schubert 	return 0;
183557e22627SCy Schubert 
183657e22627SCy Schubert error:
183757e22627SCy Schubert 	if (alldevs)
183857e22627SCy Schubert 		pcap_freealldevs(alldevs);
183957e22627SCy Schubert 
1840*6f9cba8fSJoseph Mingrone 	if (rpcap_senderror(pars->sockctrl, pars->ssl, ver,
1841*6f9cba8fSJoseph Mingrone 	    PCAP_ERR_FINDALLIF, errmsgbuf, errbuf) == -1)
184257e22627SCy Schubert 	{
184357e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
184457e22627SCy Schubert 		return -1;
184557e22627SCy Schubert 	}
184657e22627SCy Schubert 	return 0;
184757e22627SCy Schubert }
184857e22627SCy Schubert 
184957e22627SCy Schubert /*
185057e22627SCy Schubert 	\param plen: the length of the current message (needed in order to be able
185157e22627SCy Schubert 	to discard excess data in the message, if present)
185257e22627SCy Schubert */
185357e22627SCy Schubert static int
daemon_msg_open_req(uint8 ver,struct daemon_slpars * pars,uint32 plen,char * source,size_t sourcelen)185457e22627SCy Schubert daemon_msg_open_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
185557e22627SCy Schubert     char *source, size_t sourcelen)
185657e22627SCy Schubert {
185757e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
185857e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
185957e22627SCy Schubert 	pcap_t *fp;				// pcap_t main variable
186057e22627SCy Schubert 	int nread;
186157e22627SCy Schubert 	char sendbuf[RPCAP_NETBUF_SIZE];	// temporary buffer in which data to be sent is buffered
186257e22627SCy Schubert 	int sendbufidx = 0;			// index which keeps the number of bytes currently buffered
186357e22627SCy Schubert 	struct rpcap_openreply *openreply;	// open reply message
186457e22627SCy Schubert 
186557e22627SCy Schubert 	if (plen > sourcelen - 1)
186657e22627SCy Schubert 	{
1867*6f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Source string too long");
186857e22627SCy Schubert 		goto error;
186957e22627SCy Schubert 	}
187057e22627SCy Schubert 
1871*6f9cba8fSJoseph Mingrone 	nread = sock_recv(pars->sockctrl, pars->ssl, source, plen,
187257e22627SCy Schubert 	    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
187357e22627SCy Schubert 	if (nread == -1)
187457e22627SCy Schubert 	{
187557e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
187657e22627SCy Schubert 		return -1;
187757e22627SCy Schubert 	}
187857e22627SCy Schubert 	source[nread] = '\0';
187957e22627SCy Schubert 	plen -= nread;
188057e22627SCy Schubert 
188157e22627SCy Schubert 	// Is this a URL rather than a device?
188257e22627SCy Schubert 	// If so, reject it.
188357e22627SCy Schubert 	if (is_url(source))
188457e22627SCy Schubert 	{
1885*6f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Source string refers to a remote device");
188657e22627SCy Schubert 		goto error;
188757e22627SCy Schubert 	}
188857e22627SCy Schubert 
188957e22627SCy Schubert 	// Open the selected device
189057e22627SCy Schubert 	// This is a fake open, since we do that only to get the needed parameters, then we close the device again
189157e22627SCy Schubert 	if ((fp = pcap_open_live(source,
189257e22627SCy Schubert 			1500 /* fake snaplen */,
1893*6f9cba8fSJoseph Mingrone 			0 /* no promisc */,
189457e22627SCy Schubert 			1000 /* fake timeout */,
189557e22627SCy Schubert 			errmsgbuf)) == NULL)
189657e22627SCy Schubert 		goto error;
189757e22627SCy Schubert 
189857e22627SCy Schubert 	// Now, I can send a RPCAP open reply message
189957e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
190057e22627SCy Schubert 	    RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
190157e22627SCy Schubert 		goto error;
190257e22627SCy Schubert 
190357e22627SCy Schubert 	rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
190457e22627SCy Schubert 	    RPCAP_MSG_OPEN_REPLY, 0, sizeof(struct rpcap_openreply));
190557e22627SCy Schubert 
190657e22627SCy Schubert 	openreply = (struct rpcap_openreply *) &sendbuf[sendbufidx];
190757e22627SCy Schubert 
190857e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_openreply), NULL, &sendbufidx,
190957e22627SCy Schubert 	    RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
191057e22627SCy Schubert 		goto error;
191157e22627SCy Schubert 
191257e22627SCy Schubert 	memset(openreply, 0, sizeof(struct rpcap_openreply));
191357e22627SCy Schubert 	openreply->linktype = htonl(pcap_datalink(fp));
1914*6f9cba8fSJoseph Mingrone 	/*
1915*6f9cba8fSJoseph Mingrone 	 * This is always 0 for live captures; we no longer support it
1916*6f9cba8fSJoseph Mingrone 	 * as something we read from capture files and supply to
1917*6f9cba8fSJoseph Mingrone 	 * clients, but we have to send it over the wire, as open
1918*6f9cba8fSJoseph Mingrone 	 * replies are expected to have 8 bytes of payload by
1919*6f9cba8fSJoseph Mingrone 	 * existing clients.
1920*6f9cba8fSJoseph Mingrone 	 */
1921*6f9cba8fSJoseph Mingrone 	openreply->tzoff = 0;
192257e22627SCy Schubert 
192357e22627SCy Schubert 	// We're done with the pcap_t.
192457e22627SCy Schubert 	pcap_close(fp);
192557e22627SCy Schubert 
192657e22627SCy Schubert 	// Send the reply.
1927*6f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
192857e22627SCy Schubert 	{
192957e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
193057e22627SCy Schubert 		return -1;
193157e22627SCy Schubert 	}
193257e22627SCy Schubert 	return 0;
193357e22627SCy Schubert 
193457e22627SCy Schubert error:
1935*6f9cba8fSJoseph Mingrone 	if (rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_OPEN,
193657e22627SCy Schubert 	    errmsgbuf, errbuf) == -1)
193757e22627SCy Schubert 	{
193857e22627SCy Schubert 		// That failed; log a message and give up.
193957e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
194057e22627SCy Schubert 		return -1;
194157e22627SCy Schubert 	}
194257e22627SCy Schubert 
194357e22627SCy Schubert 	// Check if all the data has been read; if not, discard the data in excess
1944*6f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
194557e22627SCy Schubert 	{
194657e22627SCy Schubert 		return -1;
194757e22627SCy Schubert 	}
194857e22627SCy Schubert 	return 0;
194957e22627SCy Schubert }
195057e22627SCy Schubert 
195157e22627SCy Schubert /*
195257e22627SCy Schubert 	\param plen: the length of the current message (needed in order to be able
195357e22627SCy Schubert 	to discard excess data in the message, if present)
195457e22627SCy Schubert */
195557e22627SCy 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)195657e22627SCy Schubert daemon_msg_startcap_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
195757e22627SCy Schubert     char *source, struct session **sessionp,
1958*6f9cba8fSJoseph Mingrone     struct rpcap_sampling *samp_param _U_, int uses_ssl)
195957e22627SCy Schubert {
196057e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
196157e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
196257e22627SCy Schubert 	char portdata[PCAP_BUF_SIZE];		// temp variable needed to derive the data port
196357e22627SCy Schubert 	char peerhost[PCAP_BUF_SIZE];		// temp variable needed to derive the host name of our peer
196457e22627SCy Schubert 	struct session *session = NULL;		// saves state of session
196557e22627SCy Schubert 	int status;
196657e22627SCy Schubert 	char sendbuf[RPCAP_NETBUF_SIZE];	// temporary buffer in which data to be sent is buffered
196757e22627SCy Schubert 	int sendbufidx = 0;			// index which keeps the number of bytes currently buffered
196857e22627SCy Schubert 
196957e22627SCy Schubert 	// socket-related variables
197057e22627SCy Schubert 	struct addrinfo hints;			// temp, needed to open a socket connection
197157e22627SCy Schubert 	struct addrinfo *addrinfo;		// temp, needed to open a socket connection
197257e22627SCy Schubert 	struct sockaddr_storage saddr;		// temp, needed to retrieve the network data port chosen on the local machine
197357e22627SCy Schubert 	socklen_t saddrlen;			// temp, needed to retrieve the network data port chosen on the local machine
197457e22627SCy Schubert 	int ret;				// return value from functions
197557e22627SCy Schubert 
197657e22627SCy Schubert 	// RPCAP-related variables
197757e22627SCy Schubert 	struct rpcap_startcapreq startcapreq;		// start capture request message
197857e22627SCy Schubert 	struct rpcap_startcapreply *startcapreply;	// start capture reply message
197957e22627SCy Schubert 	int serveropen_dp;							// keeps who is going to open the data connection
198057e22627SCy Schubert 
198157e22627SCy Schubert 	addrinfo = NULL;
198257e22627SCy Schubert 
1983*6f9cba8fSJoseph Mingrone 	status = rpcapd_recv(pars->sockctrl, pars->ssl, (char *) &startcapreq,
198457e22627SCy Schubert 	    sizeof(struct rpcap_startcapreq), &plen, errmsgbuf);
198557e22627SCy Schubert 	if (status == -1)
198657e22627SCy Schubert 	{
198757e22627SCy Schubert 		goto fatal_error;
198857e22627SCy Schubert 	}
198957e22627SCy Schubert 	if (status == -2)
199057e22627SCy Schubert 	{
199157e22627SCy Schubert 		goto error;
199257e22627SCy Schubert 	}
199357e22627SCy Schubert 
199457e22627SCy Schubert 	startcapreq.flags = ntohs(startcapreq.flags);
199557e22627SCy Schubert 
1996*6f9cba8fSJoseph Mingrone 	// Check that the client does not ask for UDP is the server has been asked
1997*6f9cba8fSJoseph Mingrone 	// to enforce encryption, as SSL is not supported yet with UDP:
1998*6f9cba8fSJoseph Mingrone 	if (uses_ssl && (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM))
1999*6f9cba8fSJoseph Mingrone 	{
2000*6f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE,
2001*6f9cba8fSJoseph Mingrone 		    "SSL not supported with UDP forward of remote packets");
2002*6f9cba8fSJoseph Mingrone 		goto error;
2003*6f9cba8fSJoseph Mingrone 	}
2004*6f9cba8fSJoseph Mingrone 
200557e22627SCy Schubert 	// Create a session structure
200657e22627SCy Schubert 	session = malloc(sizeof(struct session));
200757e22627SCy Schubert 	if (session == NULL)
200857e22627SCy Schubert 	{
2009*6f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Can't allocate session structure");
201057e22627SCy Schubert 		goto error;
201157e22627SCy Schubert 	}
201257e22627SCy Schubert 
201357e22627SCy Schubert 	session->sockdata = INVALID_SOCKET;
2014*6f9cba8fSJoseph Mingrone 	session->ctrl_ssl = session->data_ssl = NULL;
201557e22627SCy Schubert 	// We don't have a thread yet.
201657e22627SCy Schubert 	session->have_thread = 0;
201757e22627SCy Schubert 	//
201857e22627SCy Schubert 	// We *shouldn't* have to initialize the thread indicator
201957e22627SCy Schubert 	// itself, because the compiler *should* realize that we
202057e22627SCy Schubert 	// only use this if have_thread isn't 0, but we *do* have
202157e22627SCy Schubert 	// to do it, because not all compilers *do* realize that.
202257e22627SCy Schubert 	//
202357e22627SCy Schubert 	// There is no "invalid thread handle" value for a UN*X
202457e22627SCy Schubert 	// pthread_t, so we just zero it out.
202557e22627SCy Schubert 	//
202657e22627SCy Schubert #ifdef _WIN32
202757e22627SCy Schubert 	session->thread = INVALID_HANDLE_VALUE;
202857e22627SCy Schubert #else
202957e22627SCy Schubert 	memset(&session->thread, 0, sizeof(session->thread));
203057e22627SCy Schubert #endif
203157e22627SCy Schubert 
203257e22627SCy Schubert 	// Open the selected device
203357e22627SCy Schubert 	if ((session->fp = pcap_open_live(source,
203457e22627SCy Schubert 			ntohl(startcapreq.snaplen),
203557e22627SCy Schubert 			(startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_PROMISC) ? 1 : 0 /* local device, other flags not needed */,
203657e22627SCy Schubert 			ntohl(startcapreq.read_timeout),
203757e22627SCy Schubert 			errmsgbuf)) == NULL)
203857e22627SCy Schubert 		goto error;
203957e22627SCy Schubert 
204057e22627SCy Schubert #if 0
204157e22627SCy Schubert 	// Apply sampling parameters
204257e22627SCy Schubert 	fp->rmt_samp.method = samp_param->method;
204357e22627SCy Schubert 	fp->rmt_samp.value = samp_param->value;
204457e22627SCy Schubert #endif
204557e22627SCy Schubert 
204657e22627SCy Schubert 	/*
204757e22627SCy Schubert 	We're in active mode if:
204857e22627SCy Schubert 	- we're using TCP, and the user wants us to be in active mode
204957e22627SCy Schubert 	- we're using UDP
205057e22627SCy Schubert 	*/
205157e22627SCy Schubert 	serveropen_dp = (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_SERVEROPEN) || (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) || pars->isactive;
205257e22627SCy Schubert 
205357e22627SCy Schubert 	/*
205457e22627SCy Schubert 	Gets the sockaddr structure referred to the other peer in the ctrl connection
205557e22627SCy Schubert 
205657e22627SCy Schubert 	We need that because:
205757e22627SCy Schubert 	- if we're in passive mode, we need to know the address family we want to use
205857e22627SCy Schubert 	(the same used for the ctrl socket)
205957e22627SCy Schubert 	- if we're in active mode, we need to know the network address of the other host
206057e22627SCy Schubert 	we want to connect to
206157e22627SCy Schubert 	*/
206257e22627SCy Schubert 	saddrlen = sizeof(struct sockaddr_storage);
206357e22627SCy Schubert 	if (getpeername(pars->sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
206457e22627SCy Schubert 	{
2065*6f9cba8fSJoseph Mingrone 		sock_geterrmsg(errmsgbuf, PCAP_ERRBUF_SIZE,
2066*6f9cba8fSJoseph Mingrone 		    "getpeername() failed");
206757e22627SCy Schubert 		goto error;
206857e22627SCy Schubert 	}
206957e22627SCy Schubert 
207057e22627SCy Schubert 	memset(&hints, 0, sizeof(struct addrinfo));
207157e22627SCy Schubert 	hints.ai_socktype = (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
207257e22627SCy Schubert 	hints.ai_family = saddr.ss_family;
207357e22627SCy Schubert 
207457e22627SCy Schubert 	// Now we have to create a new socket to send packets
207557e22627SCy Schubert 	if (serveropen_dp)		// Data connection is opened by the server toward the client
207657e22627SCy Schubert 	{
2077*6f9cba8fSJoseph Mingrone 		snprintf(portdata, sizeof portdata, "%d", ntohs(startcapreq.portdata));
207857e22627SCy Schubert 
207957e22627SCy Schubert 		// Get the name of the other peer (needed to connect to that specific network address)
208057e22627SCy Schubert 		if (getnameinfo((struct sockaddr *) &saddr, saddrlen, peerhost,
208157e22627SCy Schubert 				sizeof(peerhost), NULL, 0, NI_NUMERICHOST))
208257e22627SCy Schubert 		{
2083*6f9cba8fSJoseph Mingrone 			sock_geterrmsg(errmsgbuf, PCAP_ERRBUF_SIZE,
2084*6f9cba8fSJoseph Mingrone 			    "getnameinfo() failed");
208557e22627SCy Schubert 			goto error;
208657e22627SCy Schubert 		}
208757e22627SCy Schubert 
208857e22627SCy Schubert 		if (sock_initaddress(peerhost, portdata, &hints, &addrinfo, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
208957e22627SCy Schubert 			goto error;
209057e22627SCy Schubert 
2091*6f9cba8fSJoseph 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 
2098*6f9cba8fSJoseph Mingrone 		// Make the server socket pick up a free network port for us
2099*6f9cba8fSJoseph Mingrone 		if (sock_initaddress(NULL, NULL, &hints, &addrinfo, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
210057e22627SCy Schubert 			goto error;
210157e22627SCy Schubert 
2102*6f9cba8fSJoseph Mingrone 		if ((session->sockdata = sock_open(NULL, addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, errmsgbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
210357e22627SCy Schubert 			goto error;
210457e22627SCy Schubert 
210557e22627SCy Schubert 		// get the complete sockaddr structure used in the data connection
210657e22627SCy Schubert 		saddrlen = sizeof(struct sockaddr_storage);
210757e22627SCy Schubert 		if (getsockname(session->sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
210857e22627SCy Schubert 		{
2109*6f9cba8fSJoseph Mingrone 			sock_geterrmsg(errmsgbuf, PCAP_ERRBUF_SIZE,
2110*6f9cba8fSJoseph Mingrone 			    "getsockname() failed");
211157e22627SCy Schubert 			goto error;
211257e22627SCy Schubert 		}
211357e22627SCy Schubert 
211457e22627SCy Schubert 		// Get the local port the system picked up
211557e22627SCy Schubert 		if (getnameinfo((struct sockaddr *) &saddr, saddrlen, NULL,
211657e22627SCy Schubert 				0, portdata, sizeof(portdata), NI_NUMERICSERV))
211757e22627SCy Schubert 		{
2118*6f9cba8fSJoseph Mingrone 			sock_geterrmsg(errmsgbuf, PCAP_ERRBUF_SIZE,
2119*6f9cba8fSJoseph Mingrone 			    "getnameinfo() failed");
212057e22627SCy Schubert 			goto error;
212157e22627SCy Schubert 		}
212257e22627SCy Schubert 	}
212357e22627SCy Schubert 
212457e22627SCy Schubert 	// addrinfo is no longer used
212557e22627SCy Schubert 	freeaddrinfo(addrinfo);
212657e22627SCy Schubert 	addrinfo = NULL;
212757e22627SCy Schubert 
212857e22627SCy Schubert 	// Needed to send an error on the ctrl connection
212957e22627SCy Schubert 	session->sockctrl = pars->sockctrl;
2130*6f9cba8fSJoseph Mingrone 	session->ctrl_ssl = pars->ssl;
213157e22627SCy Schubert 	session->protocol_version = ver;
213257e22627SCy Schubert 
213357e22627SCy Schubert 	// Now I can set the filter
2134*6f9cba8fSJoseph Mingrone 	ret = daemon_unpackapplyfilter(pars->sockctrl, pars->ssl, session, &plen, errmsgbuf);
213557e22627SCy Schubert 	if (ret == -1)
213657e22627SCy Schubert 	{
213757e22627SCy Schubert 		// Fatal error.  A message has been logged; just give up.
213857e22627SCy Schubert 		goto fatal_error;
213957e22627SCy Schubert 	}
214057e22627SCy Schubert 	if (ret == -2)
214157e22627SCy Schubert 	{
214257e22627SCy Schubert 		// Non-fatal error.  Send an error message to the client.
214357e22627SCy Schubert 		goto error;
214457e22627SCy Schubert 	}
214557e22627SCy Schubert 
214657e22627SCy Schubert 	// Now, I can send a RPCAP start capture reply message
214757e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
214857e22627SCy Schubert 	    RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
214957e22627SCy Schubert 		goto error;
215057e22627SCy Schubert 
215157e22627SCy Schubert 	rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
215257e22627SCy Schubert 	    RPCAP_MSG_STARTCAP_REPLY, 0, sizeof(struct rpcap_startcapreply));
215357e22627SCy Schubert 
215457e22627SCy Schubert 	startcapreply = (struct rpcap_startcapreply *) &sendbuf[sendbufidx];
215557e22627SCy Schubert 
215657e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_startcapreply), NULL,
215757e22627SCy Schubert 	    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
215857e22627SCy Schubert 		goto error;
215957e22627SCy Schubert 
216057e22627SCy Schubert 	memset(startcapreply, 0, sizeof(struct rpcap_startcapreply));
216157e22627SCy Schubert 	startcapreply->bufsize = htonl(pcap_bufsize(session->fp));
216257e22627SCy Schubert 
216357e22627SCy Schubert 	if (!serveropen_dp)
216457e22627SCy Schubert 	{
216557e22627SCy Schubert 		unsigned short port = (unsigned short)strtoul(portdata,NULL,10);
216657e22627SCy Schubert 		startcapreply->portdata = htons(port);
216757e22627SCy Schubert 	}
216857e22627SCy Schubert 
2169*6f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
217057e22627SCy Schubert 	{
217157e22627SCy Schubert 		// That failed; log a message and give up.
217257e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
217357e22627SCy Schubert 		goto fatal_error;
217457e22627SCy Schubert 	}
217557e22627SCy Schubert 
217657e22627SCy Schubert 	if (!serveropen_dp)
217757e22627SCy Schubert 	{
217857e22627SCy Schubert 		SOCKET socktemp;	// We need another socket, since we're going to accept() a connection
217957e22627SCy Schubert 
218057e22627SCy Schubert 		// Connection creation
218157e22627SCy Schubert 		saddrlen = sizeof(struct sockaddr_storage);
218257e22627SCy Schubert 
218357e22627SCy Schubert 		socktemp = accept(session->sockdata, (struct sockaddr *) &saddr, &saddrlen);
218457e22627SCy Schubert 
218557e22627SCy Schubert 		if (socktemp == INVALID_SOCKET)
218657e22627SCy Schubert 		{
2187*6f9cba8fSJoseph Mingrone 			sock_geterrmsg(errbuf, PCAP_ERRBUF_SIZE,
2188*6f9cba8fSJoseph Mingrone 			   "accept() failed");
218957e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "Accept of data connection failed: %s",
219057e22627SCy Schubert 			    errbuf);
219157e22627SCy Schubert 			goto error;
219257e22627SCy Schubert 		}
219357e22627SCy Schubert 
219457e22627SCy Schubert 		// Now that I accepted the connection, the server socket is no longer needed
219557e22627SCy Schubert 		sock_close(session->sockdata, NULL, 0);
219657e22627SCy Schubert 		session->sockdata = socktemp;
219757e22627SCy Schubert 	}
219857e22627SCy Schubert 
2199*6f9cba8fSJoseph Mingrone 	SSL *ssl = NULL;
2200*6f9cba8fSJoseph Mingrone 	if (uses_ssl)
2201*6f9cba8fSJoseph Mingrone 	{
2202*6f9cba8fSJoseph Mingrone #ifdef HAVE_OPENSSL
2203*6f9cba8fSJoseph Mingrone 		/* In both active or passive cases, wait for the client to initiate the
2204*6f9cba8fSJoseph Mingrone 		 * TLS handshake. Yes during that time the control socket will not be
2205*6f9cba8fSJoseph Mingrone 		 * served, but the same was true from the above call to accept(). */
2206*6f9cba8fSJoseph Mingrone 		ssl = ssl_promotion(1, session->sockdata, errbuf, PCAP_ERRBUF_SIZE);
2207*6f9cba8fSJoseph Mingrone 		if (! ssl)
2208*6f9cba8fSJoseph Mingrone 		{
2209*6f9cba8fSJoseph Mingrone 			rpcapd_log(LOGPRIO_ERROR, "TLS handshake failed: %s", errbuf);
2210*6f9cba8fSJoseph Mingrone 			goto error;
2211*6f9cba8fSJoseph Mingrone 		}
2212*6f9cba8fSJoseph Mingrone #endif
2213*6f9cba8fSJoseph Mingrone 	}
2214*6f9cba8fSJoseph Mingrone 	session->data_ssl = ssl;
2215*6f9cba8fSJoseph Mingrone 
221657e22627SCy Schubert 	// Now we have to create a new thread to receive packets
221757e22627SCy Schubert #ifdef _WIN32
221857e22627SCy Schubert 	session->thread = (HANDLE)_beginthreadex(NULL, 0, daemon_thrdatamain,
221957e22627SCy Schubert 	    (void *) session, 0, NULL);
222057e22627SCy Schubert 	if (session->thread == 0)
222157e22627SCy Schubert 	{
2222*6f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread");
222357e22627SCy Schubert 		goto error;
222457e22627SCy Schubert 	}
222557e22627SCy Schubert #else
222657e22627SCy Schubert 	ret = pthread_create(&session->thread, NULL, daemon_thrdatamain,
222757e22627SCy Schubert 	    (void *) session);
222857e22627SCy Schubert 	if (ret != 0)
222957e22627SCy Schubert 	{
223057e22627SCy Schubert 		pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
223157e22627SCy Schubert 		    ret, "Error creating the data thread");
223257e22627SCy Schubert 		goto error;
223357e22627SCy Schubert 	}
223457e22627SCy Schubert #endif
223557e22627SCy Schubert 	session->have_thread = 1;
223657e22627SCy Schubert 
223757e22627SCy Schubert 	// Check if all the data has been read; if not, discard the data in excess
2238*6f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
223957e22627SCy Schubert 		goto fatal_error;
224057e22627SCy Schubert 
224157e22627SCy Schubert 	*sessionp = session;
224257e22627SCy Schubert 	return 0;
224357e22627SCy Schubert 
224457e22627SCy Schubert error:
224557e22627SCy Schubert 	//
224657e22627SCy Schubert 	// Not a fatal error, so send the client an error message and
224757e22627SCy Schubert 	// keep serving client requests.
224857e22627SCy Schubert 	//
224957e22627SCy Schubert 	*sessionp = NULL;
225057e22627SCy Schubert 
225157e22627SCy Schubert 	if (addrinfo)
225257e22627SCy Schubert 		freeaddrinfo(addrinfo);
225357e22627SCy Schubert 
225457e22627SCy Schubert 	if (session)
225557e22627SCy Schubert 	{
225657e22627SCy Schubert 		session_close(session);
225757e22627SCy Schubert 		free(session);
225857e22627SCy Schubert 	}
225957e22627SCy Schubert 
2260*6f9cba8fSJoseph Mingrone 	if (rpcap_senderror(pars->sockctrl, pars->ssl, ver,
2261*6f9cba8fSJoseph Mingrone 	    PCAP_ERR_STARTCAPTURE, errmsgbuf, errbuf) == -1)
226257e22627SCy Schubert 	{
226357e22627SCy Schubert 		// That failed; log a message and give up.
226457e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
226557e22627SCy Schubert 		return -1;
226657e22627SCy Schubert 	}
226757e22627SCy Schubert 
226857e22627SCy Schubert 	// Check if all the data has been read; if not, discard the data in excess
2269*6f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
227057e22627SCy Schubert 	{
227157e22627SCy Schubert 		// Network error.
227257e22627SCy Schubert 		return -1;
227357e22627SCy Schubert 	}
227457e22627SCy Schubert 
227557e22627SCy Schubert 	return 0;
227657e22627SCy Schubert 
227757e22627SCy Schubert fatal_error:
227857e22627SCy Schubert 	//
227957e22627SCy Schubert 	// Fatal network error, so don't try to communicate with
228057e22627SCy Schubert 	// the client, just give up.
228157e22627SCy Schubert 	//
228257e22627SCy Schubert 	*sessionp = NULL;
228357e22627SCy Schubert 
228457e22627SCy Schubert 	if (session)
228557e22627SCy Schubert 	{
228657e22627SCy Schubert 		session_close(session);
228757e22627SCy Schubert 		free(session);
228857e22627SCy Schubert 	}
228957e22627SCy Schubert 
229057e22627SCy Schubert 	return -1;
229157e22627SCy Schubert }
229257e22627SCy Schubert 
229357e22627SCy Schubert static int
daemon_msg_endcap_req(uint8 ver,struct daemon_slpars * pars,struct session * session)229457e22627SCy Schubert daemon_msg_endcap_req(uint8 ver, struct daemon_slpars *pars,
229557e22627SCy Schubert     struct session *session)
229657e22627SCy Schubert {
229757e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
229857e22627SCy Schubert 	struct rpcap_header header;
229957e22627SCy Schubert 
230057e22627SCy Schubert 	session_close(session);
230157e22627SCy Schubert 
230257e22627SCy Schubert 	rpcap_createhdr(&header, ver, RPCAP_MSG_ENDCAP_REPLY, 0, 0);
230357e22627SCy Schubert 
2304*6f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
230557e22627SCy Schubert 	{
230657e22627SCy Schubert 		// That failed; log a message and give up.
230757e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
230857e22627SCy Schubert 		return -1;
230957e22627SCy Schubert 	}
231057e22627SCy Schubert 
231157e22627SCy Schubert 	return 0;
231257e22627SCy Schubert }
231357e22627SCy Schubert 
231457e22627SCy Schubert //
231557e22627SCy Schubert // We impose a limit on the filter program size, so that, on Windows,
231657e22627SCy Schubert // where there's only one server process with multiple threads, it's
231757e22627SCy Schubert // harder to eat all the server address space by sending larger filter
231857e22627SCy Schubert // programs.  (This isn't an issue on UN*X, where there are multiple
231957e22627SCy Schubert // server processes, one per client connection.)
232057e22627SCy Schubert //
232157e22627SCy Schubert // We pick a value that limits each filter to 64K; that value is twice
232257e22627SCy Schubert // the in-kernel limit for Linux and 16 times the in-kernel limit for
232357e22627SCy Schubert // *BSD and macOS.
232457e22627SCy Schubert //
232557e22627SCy Schubert // It also prevents an overflow on 32-bit platforms when calculating
232657e22627SCy Schubert // the total size of the filter program.  (It's not an issue on 64-bit
232757e22627SCy Schubert // platforms with a 64-bit size_t, as the filter size is 32 bits.)
232857e22627SCy Schubert //
232957e22627SCy Schubert #define RPCAP_BPF_MAXINSNS	8192
233057e22627SCy Schubert 
233157e22627SCy Schubert static int
daemon_unpackapplyfilter(SOCKET sockctrl,SSL * ctrl_ssl,struct session * session,uint32 * plenp,char * errmsgbuf)2332*6f9cba8fSJoseph Mingrone daemon_unpackapplyfilter(SOCKET sockctrl, SSL *ctrl_ssl, struct session *session, uint32 *plenp, char *errmsgbuf)
233357e22627SCy Schubert {
233457e22627SCy Schubert 	int status;
233557e22627SCy Schubert 	struct rpcap_filter filter;
233657e22627SCy Schubert 	struct rpcap_filterbpf_insn insn;
233757e22627SCy Schubert 	struct bpf_insn *bf_insn;
233857e22627SCy Schubert 	struct bpf_program bf_prog;
233957e22627SCy Schubert 	unsigned int i;
234057e22627SCy Schubert 
2341*6f9cba8fSJoseph Mingrone 	status = rpcapd_recv(sockctrl, ctrl_ssl, (char *) &filter,
234257e22627SCy Schubert 	    sizeof(struct rpcap_filter), plenp, errmsgbuf);
234357e22627SCy Schubert 	if (status == -1)
234457e22627SCy Schubert 	{
234557e22627SCy Schubert 		return -1;
234657e22627SCy Schubert 	}
234757e22627SCy Schubert 	if (status == -2)
234857e22627SCy Schubert 	{
234957e22627SCy Schubert 		return -2;
235057e22627SCy Schubert 	}
235157e22627SCy Schubert 
235257e22627SCy Schubert 	bf_prog.bf_len = ntohl(filter.nitems);
235357e22627SCy Schubert 
235457e22627SCy Schubert 	if (ntohs(filter.filtertype) != RPCAP_UPDATEFILTER_BPF)
235557e22627SCy Schubert 	{
2356*6f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Only BPF/NPF filters are currently supported");
235757e22627SCy Schubert 		return -2;
235857e22627SCy Schubert 	}
235957e22627SCy Schubert 
236057e22627SCy Schubert 	if (bf_prog.bf_len > RPCAP_BPF_MAXINSNS)
236157e22627SCy Schubert 	{
2362*6f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
2363*6f9cba8fSJoseph Mingrone 		    "Filter program is larger than the maximum size of %d instructions",
236457e22627SCy Schubert 		    RPCAP_BPF_MAXINSNS);
236557e22627SCy Schubert 		return -2;
236657e22627SCy Schubert 	}
236757e22627SCy Schubert 	bf_insn = (struct bpf_insn *) malloc (sizeof(struct bpf_insn) * bf_prog.bf_len);
236857e22627SCy Schubert 	if (bf_insn == NULL)
236957e22627SCy Schubert 	{
237057e22627SCy Schubert 		pcap_fmt_errmsg_for_errno(errmsgbuf, PCAP_ERRBUF_SIZE,
237157e22627SCy Schubert 		    errno, "malloc() failed");
237257e22627SCy Schubert 		return -2;
237357e22627SCy Schubert 	}
237457e22627SCy Schubert 
237557e22627SCy Schubert 	bf_prog.bf_insns = bf_insn;
237657e22627SCy Schubert 
237757e22627SCy Schubert 	for (i = 0; i < bf_prog.bf_len; i++)
237857e22627SCy Schubert 	{
2379*6f9cba8fSJoseph Mingrone 		status = rpcapd_recv(sockctrl, ctrl_ssl, (char *) &insn,
238057e22627SCy Schubert 		    sizeof(struct rpcap_filterbpf_insn), plenp, errmsgbuf);
238157e22627SCy Schubert 		if (status == -1)
238257e22627SCy Schubert 		{
238357e22627SCy Schubert 			return -1;
238457e22627SCy Schubert 		}
238557e22627SCy Schubert 		if (status == -2)
238657e22627SCy Schubert 		{
238757e22627SCy Schubert 			return -2;
238857e22627SCy Schubert 		}
238957e22627SCy Schubert 
239057e22627SCy Schubert 		bf_insn->code = ntohs(insn.code);
239157e22627SCy Schubert 		bf_insn->jf = insn.jf;
239257e22627SCy Schubert 		bf_insn->jt = insn.jt;
239357e22627SCy Schubert 		bf_insn->k = ntohl(insn.k);
239457e22627SCy Schubert 
239557e22627SCy Schubert 		bf_insn++;
239657e22627SCy Schubert 	}
239757e22627SCy Schubert 
2398*6f9cba8fSJoseph Mingrone 	//
2399*6f9cba8fSJoseph Mingrone 	// XXX - pcap_setfilter() should do the validation for us.
2400*6f9cba8fSJoseph Mingrone 	//
240157e22627SCy Schubert 	if (bpf_validate(bf_prog.bf_insns, bf_prog.bf_len) == 0)
240257e22627SCy Schubert 	{
2403*6f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "The filter contains bogus instructions");
240457e22627SCy Schubert 		return -2;
240557e22627SCy Schubert 	}
240657e22627SCy Schubert 
240757e22627SCy Schubert 	if (pcap_setfilter(session->fp, &bf_prog))
240857e22627SCy Schubert 	{
2409*6f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "RPCAP error: %s", pcap_geterr(session->fp));
241057e22627SCy Schubert 		return -2;
241157e22627SCy Schubert 	}
241257e22627SCy Schubert 
241357e22627SCy Schubert 	return 0;
241457e22627SCy Schubert }
241557e22627SCy Schubert 
241657e22627SCy Schubert static int
daemon_msg_updatefilter_req(uint8 ver,struct daemon_slpars * pars,struct session * session,uint32 plen)241757e22627SCy Schubert daemon_msg_updatefilter_req(uint8 ver, struct daemon_slpars *pars,
241857e22627SCy Schubert     struct session *session, uint32 plen)
241957e22627SCy Schubert {
242057e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];
242157e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
242257e22627SCy Schubert 	int ret;				// status of daemon_unpackapplyfilter()
242357e22627SCy Schubert 	struct rpcap_header header;		// keeps the answer to the updatefilter command
242457e22627SCy Schubert 
2425*6f9cba8fSJoseph Mingrone 	ret = daemon_unpackapplyfilter(pars->sockctrl, pars->ssl, session, &plen, errmsgbuf);
242657e22627SCy Schubert 	if (ret == -1)
242757e22627SCy Schubert 	{
242857e22627SCy Schubert 		// Fatal error.  A message has been logged; just give up.
242957e22627SCy Schubert 		return -1;
243057e22627SCy Schubert 	}
243157e22627SCy Schubert 	if (ret == -2)
243257e22627SCy Schubert 	{
243357e22627SCy Schubert 		// Non-fatal error.  Send an error reply to the client.
243457e22627SCy Schubert 		goto error;
243557e22627SCy Schubert 	}
243657e22627SCy Schubert 
243757e22627SCy Schubert 	// Check if all the data has been read; if not, discard the data in excess
2438*6f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
243957e22627SCy Schubert 	{
244057e22627SCy Schubert 		// Network error.
244157e22627SCy Schubert 		return -1;
244257e22627SCy Schubert 	}
244357e22627SCy Schubert 
244457e22627SCy Schubert 	// A response is needed, otherwise the other host does not know that everything went well
244557e22627SCy Schubert 	rpcap_createhdr(&header, ver, RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);
244657e22627SCy Schubert 
2447*6f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE))
244857e22627SCy Schubert 	{
2449*6f9cba8fSJoseph Mingrone 		// That failed; log a message and give up.
245057e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
245157e22627SCy Schubert 		return -1;
245257e22627SCy Schubert 	}
245357e22627SCy Schubert 
245457e22627SCy Schubert 	return 0;
245557e22627SCy Schubert 
245657e22627SCy Schubert error:
2457*6f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
245857e22627SCy Schubert 	{
245957e22627SCy Schubert 		return -1;
246057e22627SCy Schubert 	}
2461*6f9cba8fSJoseph Mingrone 	rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_UPDATEFILTER,
246257e22627SCy Schubert 	    errmsgbuf, NULL);
246357e22627SCy Schubert 
246457e22627SCy Schubert 	return 0;
246557e22627SCy Schubert }
246657e22627SCy Schubert 
246757e22627SCy Schubert /*!
246857e22627SCy Schubert 	\brief Received the sampling parameters from remote host and it stores in the pcap_t structure.
246957e22627SCy Schubert */
247057e22627SCy Schubert static int
daemon_msg_setsampling_req(uint8 ver,struct daemon_slpars * pars,uint32 plen,struct rpcap_sampling * samp_param)247157e22627SCy Schubert daemon_msg_setsampling_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
247257e22627SCy Schubert     struct rpcap_sampling *samp_param)
247357e22627SCy Schubert {
247457e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
247557e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];
247657e22627SCy Schubert 	struct rpcap_header header;
247757e22627SCy Schubert 	struct rpcap_sampling rpcap_samp;
247857e22627SCy Schubert 	int status;
247957e22627SCy Schubert 
2480*6f9cba8fSJoseph Mingrone 	status = rpcapd_recv(pars->sockctrl, pars->ssl, (char *) &rpcap_samp, sizeof(struct rpcap_sampling), &plen, errmsgbuf);
248157e22627SCy Schubert 	if (status == -1)
248257e22627SCy Schubert 	{
248357e22627SCy Schubert 		return -1;
248457e22627SCy Schubert 	}
248557e22627SCy Schubert 	if (status == -2)
248657e22627SCy Schubert 	{
248757e22627SCy Schubert 		goto error;
248857e22627SCy Schubert 	}
248957e22627SCy Schubert 
249057e22627SCy Schubert 	// Save these settings in the pcap_t
249157e22627SCy Schubert 	samp_param->method = rpcap_samp.method;
249257e22627SCy Schubert 	samp_param->value = ntohl(rpcap_samp.value);
249357e22627SCy Schubert 
249457e22627SCy Schubert 	// A response is needed, otherwise the other host does not know that everything went well
249557e22627SCy Schubert 	rpcap_createhdr(&header, ver, RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);
249657e22627SCy Schubert 
2497*6f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
249857e22627SCy Schubert 	{
2499*6f9cba8fSJoseph Mingrone 		// That failed; log a message and give up.
250057e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
250157e22627SCy Schubert 		return -1;
250257e22627SCy Schubert 	}
250357e22627SCy Schubert 
2504*6f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
250557e22627SCy Schubert 	{
250657e22627SCy Schubert 		return -1;
250757e22627SCy Schubert 	}
250857e22627SCy Schubert 
250957e22627SCy Schubert 	return 0;
251057e22627SCy Schubert 
251157e22627SCy Schubert error:
2512*6f9cba8fSJoseph Mingrone 	if (rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_SETSAMPLING,
251357e22627SCy Schubert 	    errmsgbuf, errbuf) == -1)
251457e22627SCy Schubert 	{
251557e22627SCy Schubert 		// That failed; log a message and give up.
251657e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
251757e22627SCy Schubert 		return -1;
251857e22627SCy Schubert 	}
251957e22627SCy Schubert 
252057e22627SCy Schubert 	// Check if all the data has been read; if not, discard the data in excess
2521*6f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
252257e22627SCy Schubert 	{
252357e22627SCy Schubert 		return -1;
252457e22627SCy Schubert 	}
252557e22627SCy Schubert 
252657e22627SCy Schubert 	return 0;
252757e22627SCy Schubert }
252857e22627SCy Schubert 
252957e22627SCy 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)253057e22627SCy Schubert daemon_msg_stats_req(uint8 ver, struct daemon_slpars *pars,
253157e22627SCy Schubert     struct session *session, uint32 plen, struct pcap_stat *stats,
253257e22627SCy Schubert     unsigned int svrcapt)
253357e22627SCy Schubert {
253457e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
253557e22627SCy Schubert 	char errmsgbuf[PCAP_ERRBUF_SIZE];	// buffer for errors to send to the client
253657e22627SCy Schubert 	char sendbuf[RPCAP_NETBUF_SIZE];	// temporary buffer in which data to be sent is buffered
253757e22627SCy Schubert 	int sendbufidx = 0;			// index which keeps the number of bytes currently buffered
253857e22627SCy Schubert 	struct rpcap_stats *netstats;		// statistics sent on the network
253957e22627SCy Schubert 
254057e22627SCy Schubert 	// Checks that the header does not contain other data; if so, discard it
2541*6f9cba8fSJoseph Mingrone 	if (rpcapd_discard(pars->sockctrl, pars->ssl, plen) == -1)
254257e22627SCy Schubert 	{
254357e22627SCy Schubert 		// Network error.
254457e22627SCy Schubert 		return -1;
254557e22627SCy Schubert 	}
254657e22627SCy Schubert 
254757e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
254857e22627SCy Schubert 	    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
254957e22627SCy Schubert 		goto error;
255057e22627SCy Schubert 
255157e22627SCy Schubert 	rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
255257e22627SCy Schubert 	    RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));
255357e22627SCy Schubert 
255457e22627SCy Schubert 	netstats = (struct rpcap_stats *) &sendbuf[sendbufidx];
255557e22627SCy Schubert 
255657e22627SCy Schubert 	if (sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL,
255757e22627SCy Schubert 	    &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
255857e22627SCy Schubert 		goto error;
255957e22627SCy Schubert 
256057e22627SCy Schubert 	if (session && session->fp)
256157e22627SCy Schubert 	{
256257e22627SCy Schubert 		if (pcap_stats(session->fp, stats) == -1)
256357e22627SCy Schubert 		{
2564*6f9cba8fSJoseph Mingrone 			snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "%s", pcap_geterr(session->fp));
256557e22627SCy Schubert 			goto error;
256657e22627SCy Schubert 		}
256757e22627SCy Schubert 
256857e22627SCy Schubert 		netstats->ifdrop = htonl(stats->ps_ifdrop);
256957e22627SCy Schubert 		netstats->ifrecv = htonl(stats->ps_recv);
257057e22627SCy Schubert 		netstats->krnldrop = htonl(stats->ps_drop);
257157e22627SCy Schubert 		netstats->svrcapt = htonl(session->TotCapt);
257257e22627SCy Schubert 	}
257357e22627SCy Schubert 	else
257457e22627SCy Schubert 	{
257557e22627SCy Schubert 		// We have to keep compatibility with old applications,
257657e22627SCy Schubert 		// which ask for statistics also when the capture has
257757e22627SCy Schubert 		// already stopped.
257857e22627SCy Schubert 		netstats->ifdrop = htonl(stats->ps_ifdrop);
257957e22627SCy Schubert 		netstats->ifrecv = htonl(stats->ps_recv);
258057e22627SCy Schubert 		netstats->krnldrop = htonl(stats->ps_drop);
258157e22627SCy Schubert 		netstats->svrcapt = htonl(svrcapt);
258257e22627SCy Schubert 	}
258357e22627SCy Schubert 
258457e22627SCy Schubert 	// Send the packet
2585*6f9cba8fSJoseph Mingrone 	if (sock_send(pars->sockctrl, pars->ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
258657e22627SCy Schubert 	{
258757e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
258857e22627SCy Schubert 		return -1;
258957e22627SCy Schubert 	}
259057e22627SCy Schubert 
259157e22627SCy Schubert 	return 0;
259257e22627SCy Schubert 
259357e22627SCy Schubert error:
2594*6f9cba8fSJoseph Mingrone 	rpcap_senderror(pars->sockctrl, pars->ssl, ver, PCAP_ERR_GETSTATS,
259557e22627SCy Schubert 	    errmsgbuf, NULL);
259657e22627SCy Schubert 	return 0;
259757e22627SCy Schubert }
259857e22627SCy Schubert 
259957e22627SCy Schubert #ifdef _WIN32
260057e22627SCy Schubert static unsigned __stdcall
260157e22627SCy Schubert #else
260257e22627SCy Schubert static void *
260357e22627SCy Schubert #endif
daemon_thrdatamain(void * ptr)260457e22627SCy Schubert daemon_thrdatamain(void *ptr)
260557e22627SCy Schubert {
260657e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE + 1];	// error buffer
260757e22627SCy Schubert 	struct session *session;		// pointer to the struct session for this session
260857e22627SCy Schubert 	int retval;							// general variable used to keep the return value of other functions
260957e22627SCy Schubert 	struct rpcap_pkthdr *net_pkt_header;// header of the packet
261057e22627SCy Schubert 	struct pcap_pkthdr *pkt_header;		// pointer to the buffer that contains the header of the current packet
261157e22627SCy Schubert 	u_char *pkt_data;					// pointer to the buffer that contains the current packet
261257e22627SCy Schubert 	size_t sendbufsize;			// size for the send buffer
261357e22627SCy Schubert 	char *sendbuf;						// temporary buffer in which data to be sent is buffered
261457e22627SCy Schubert 	int sendbufidx;						// index which keeps the number of bytes currently buffered
261557e22627SCy Schubert 	int status;
261657e22627SCy Schubert #ifndef _WIN32
261757e22627SCy Schubert 	sigset_t sigusr1;			// signal set with just SIGUSR1
261857e22627SCy Schubert #endif
261957e22627SCy Schubert 
262057e22627SCy Schubert 	session = (struct session *) ptr;
262157e22627SCy Schubert 
262257e22627SCy Schubert 	session->TotCapt = 0;			// counter which is incremented each time a packet is received
262357e22627SCy Schubert 
262457e22627SCy Schubert 	// Initialize errbuf
262557e22627SCy Schubert 	memset(errbuf, 0, sizeof(errbuf));
262657e22627SCy Schubert 
262757e22627SCy Schubert 	//
262857e22627SCy Schubert 	// We need a buffer large enough to hold a buffer large enough
262957e22627SCy Schubert 	// for a maximum-size packet for this pcap_t.
263057e22627SCy Schubert 	//
263157e22627SCy Schubert 	if (pcap_snapshot(session->fp) < 0)
263257e22627SCy Schubert 	{
263357e22627SCy Schubert 		//
263457e22627SCy Schubert 		// The snapshot length is negative.
263557e22627SCy Schubert 		// This "should not happen".
263657e22627SCy Schubert 		//
263757e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR,
263857e22627SCy Schubert 		    "Unable to allocate the buffer for this child thread: snapshot length of %d is negative",
263957e22627SCy Schubert 		        pcap_snapshot(session->fp));
264057e22627SCy Schubert 		sendbuf = NULL;	// we can't allocate a buffer, so nothing to free
264157e22627SCy Schubert 		goto error;
264257e22627SCy Schubert 	}
264357e22627SCy Schubert 	//
264457e22627SCy Schubert 	// size_t is unsigned, and the result of pcap_snapshot() is signed;
264557e22627SCy Schubert 	// on no platform that we support is int larger than size_t.
264657e22627SCy Schubert 	// This means that, unless the extra information we prepend to
264757e22627SCy Schubert 	// a maximum-sized packet is impossibly large, the sum of the
264857e22627SCy Schubert 	// snapshot length and the size of that extra information will
264957e22627SCy Schubert 	// fit in a size_t.
265057e22627SCy Schubert 	//
265157e22627SCy Schubert 	// So we don't need to make sure that sendbufsize will overflow.
265257e22627SCy Schubert 	//
2653*6f9cba8fSJoseph Mingrone 	// However, we *do* need to make sure its value fits in an int,
2654*6f9cba8fSJoseph Mingrone 	// because sock_send() can't send more than INT_MAX bytes (it could
2655*6f9cba8fSJoseph Mingrone 	// do so on 64-bit UN*Xes, but can't do so on Windows, not even
2656*6f9cba8fSJoseph Mingrone 	// 64-bit Windows, as the send() buffer size argument is an int
2657*6f9cba8fSJoseph Mingrone 	// in Winsock).
2658*6f9cba8fSJoseph Mingrone 	//
265957e22627SCy Schubert 	sendbufsize = sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr) + pcap_snapshot(session->fp);
2660*6f9cba8fSJoseph Mingrone 	if (sendbufsize > INT_MAX)
2661*6f9cba8fSJoseph Mingrone 	{
2662*6f9cba8fSJoseph Mingrone 		rpcapd_log(LOGPRIO_ERROR,
2663*6f9cba8fSJoseph Mingrone 		    "Buffer size for this child thread would be larger than %d",
2664*6f9cba8fSJoseph Mingrone 		    INT_MAX);
2665*6f9cba8fSJoseph Mingrone 		sendbuf = NULL;	// we haven't allocated a buffer, so nothing to free
2666*6f9cba8fSJoseph Mingrone 		goto error;
2667*6f9cba8fSJoseph Mingrone 	}
266857e22627SCy Schubert 	sendbuf = (char *) malloc (sendbufsize);
266957e22627SCy Schubert 	if (sendbuf == NULL)
267057e22627SCy Schubert 	{
267157e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR,
267257e22627SCy Schubert 		    "Unable to allocate the buffer for this child thread");
267357e22627SCy Schubert 		goto error;
267457e22627SCy Schubert 	}
267557e22627SCy Schubert 
267657e22627SCy Schubert #ifndef _WIN32
267757e22627SCy Schubert 	//
267857e22627SCy Schubert 	// Set the signal set to include just SIGUSR1, and block that
267957e22627SCy Schubert 	// signal; we only want it unblocked when we're reading
268057e22627SCy Schubert 	// packets - we dn't want any other system calls, such as
268157e22627SCy Schubert 	// ones being used to send to the client or to log messages,
268257e22627SCy Schubert 	// to be interrupted.
268357e22627SCy Schubert 	//
268457e22627SCy Schubert 	sigemptyset(&sigusr1);
268557e22627SCy Schubert 	sigaddset(&sigusr1, SIGUSR1);
268657e22627SCy Schubert 	pthread_sigmask(SIG_BLOCK, &sigusr1, NULL);
268757e22627SCy Schubert #endif
268857e22627SCy Schubert 
268957e22627SCy Schubert 	// Retrieve the packets
269057e22627SCy Schubert 	for (;;)
269157e22627SCy Schubert 	{
269257e22627SCy Schubert #ifndef _WIN32
269357e22627SCy Schubert 		//
269457e22627SCy Schubert 		// Unblock SIGUSR1 while we might be waiting for packets.
269557e22627SCy Schubert 		//
269657e22627SCy Schubert 		pthread_sigmask(SIG_UNBLOCK, &sigusr1, NULL);
269757e22627SCy Schubert #endif
269857e22627SCy Schubert 		retval = pcap_next_ex(session->fp, &pkt_header, (const u_char **) &pkt_data);	// cast to avoid a compiler warning
269957e22627SCy Schubert #ifndef _WIN32
270057e22627SCy Schubert 		//
270157e22627SCy Schubert 		// Now block it again.
270257e22627SCy Schubert 		//
270357e22627SCy Schubert 		pthread_sigmask(SIG_BLOCK, &sigusr1, NULL);
270457e22627SCy Schubert #endif
270557e22627SCy Schubert 		if (retval < 0)
270657e22627SCy Schubert 			break;		// error
270757e22627SCy Schubert 		if (retval == 0)	// Read timeout elapsed
270857e22627SCy Schubert 			continue;
270957e22627SCy Schubert 
271057e22627SCy Schubert 		sendbufidx = 0;
271157e22627SCy Schubert 
271257e22627SCy Schubert 		// Bufferize the general header
271357e22627SCy Schubert 		if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
2714*6f9cba8fSJoseph Mingrone 		    &sendbufidx, (int)sendbufsize, SOCKBUF_CHECKONLY, errbuf,
271557e22627SCy Schubert 		    PCAP_ERRBUF_SIZE) == -1)
271657e22627SCy Schubert 		{
271757e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR,
271857e22627SCy Schubert 			    "sock_bufferize() error sending packet message: %s",
271957e22627SCy Schubert 			    errbuf);
272057e22627SCy Schubert 			goto error;
272157e22627SCy Schubert 		}
272257e22627SCy Schubert 
272357e22627SCy Schubert 		rpcap_createhdr((struct rpcap_header *) sendbuf,
272457e22627SCy Schubert 		    session->protocol_version, RPCAP_MSG_PACKET, 0,
272557e22627SCy Schubert 		    (uint16) (sizeof(struct rpcap_pkthdr) + pkt_header->caplen));
272657e22627SCy Schubert 
272757e22627SCy Schubert 		net_pkt_header = (struct rpcap_pkthdr *) &sendbuf[sendbufidx];
272857e22627SCy Schubert 
272957e22627SCy Schubert 		// Bufferize the pkt header
273057e22627SCy Schubert 		if (sock_bufferize(NULL, sizeof(struct rpcap_pkthdr), NULL,
2731*6f9cba8fSJoseph Mingrone 		    &sendbufidx, (int)sendbufsize, SOCKBUF_CHECKONLY, errbuf,
273257e22627SCy Schubert 		    PCAP_ERRBUF_SIZE) == -1)
273357e22627SCy Schubert 		{
273457e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR,
273557e22627SCy Schubert 			    "sock_bufferize() error sending packet message: %s",
273657e22627SCy Schubert 			    errbuf);
273757e22627SCy Schubert 			goto error;
273857e22627SCy Schubert 		}
273957e22627SCy Schubert 
274057e22627SCy Schubert 		net_pkt_header->caplen = htonl(pkt_header->caplen);
274157e22627SCy Schubert 		net_pkt_header->len = htonl(pkt_header->len);
274257e22627SCy Schubert 		net_pkt_header->npkt = htonl(++(session->TotCapt));
2743*6f9cba8fSJoseph Mingrone 		//
2744*6f9cba8fSJoseph Mingrone 		// This protocol needs to be updated with a new version
2745*6f9cba8fSJoseph Mingrone 		// before 2038-01-19 03:14:07 UTC.
2746*6f9cba8fSJoseph Mingrone 		//
2747*6f9cba8fSJoseph Mingrone 		net_pkt_header->timestamp_sec = htonl((uint32)pkt_header->ts.tv_sec);
2748*6f9cba8fSJoseph Mingrone 		net_pkt_header->timestamp_usec = htonl((uint32)pkt_header->ts.tv_usec);
274957e22627SCy Schubert 
275057e22627SCy Schubert 		// Bufferize the pkt data
275157e22627SCy Schubert 		if (sock_bufferize((char *) pkt_data, pkt_header->caplen,
2752*6f9cba8fSJoseph Mingrone 		    sendbuf, &sendbufidx, (int)sendbufsize, SOCKBUF_BUFFERIZE,
275357e22627SCy Schubert 		    errbuf, PCAP_ERRBUF_SIZE) == -1)
275457e22627SCy Schubert 		{
275557e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR,
275657e22627SCy Schubert 			    "sock_bufferize() error sending packet message: %s",
275757e22627SCy Schubert 			    errbuf);
275857e22627SCy Schubert 			goto error;
275957e22627SCy Schubert 		}
276057e22627SCy Schubert 
276157e22627SCy Schubert 		// Send the packet
276257e22627SCy Schubert 		// If the client dropped the connection, don't report an
276357e22627SCy Schubert 		// error, just quit.
2764*6f9cba8fSJoseph Mingrone 		status = sock_send(session->sockdata, session->data_ssl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE);
276557e22627SCy Schubert 		if (status < 0)
276657e22627SCy Schubert 		{
276757e22627SCy Schubert 			if (status == -1)
276857e22627SCy Schubert 			{
276957e22627SCy Schubert 				//
277057e22627SCy Schubert 				// Error other than "client closed the
277157e22627SCy Schubert 				// connection out from under us"; report
277257e22627SCy Schubert 				// it.
277357e22627SCy Schubert 				//
277457e22627SCy Schubert 				rpcapd_log(LOGPRIO_ERROR,
277557e22627SCy Schubert 				    "Send of packet to client failed: %s",
277657e22627SCy Schubert 				    errbuf);
277757e22627SCy Schubert 			}
277857e22627SCy Schubert 
277957e22627SCy Schubert 			//
278057e22627SCy Schubert 			// Give up in either case.
278157e22627SCy Schubert 			//
278257e22627SCy Schubert 			goto error;
278357e22627SCy Schubert 		}
278457e22627SCy Schubert 	}
278557e22627SCy Schubert 
278657e22627SCy Schubert 	if (retval < 0 && retval != PCAP_ERROR_BREAK)
278757e22627SCy Schubert 	{
278857e22627SCy Schubert 		//
278957e22627SCy Schubert 		// Failed with an error other than "we were told to break
279057e22627SCy Schubert 		// out of the loop".
279157e22627SCy Schubert 		//
279257e22627SCy Schubert 		// The latter just means that the client told us to stop
279357e22627SCy Schubert 		// capturing, so there's no error to report.
279457e22627SCy Schubert 		//
2795*6f9cba8fSJoseph Mingrone 		snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(session->fp));
2796*6f9cba8fSJoseph Mingrone 		rpcap_senderror(session->sockctrl, session->ctrl_ssl, session->protocol_version,
279757e22627SCy Schubert 		    PCAP_ERR_READEX, errbuf, NULL);
279857e22627SCy Schubert 	}
279957e22627SCy Schubert 
280057e22627SCy Schubert error:
280157e22627SCy Schubert 	//
280257e22627SCy Schubert 	// The main thread will clean up the session structure.
280357e22627SCy Schubert 	//
280457e22627SCy Schubert 	free(sendbuf);
280557e22627SCy Schubert 
280657e22627SCy Schubert 	return 0;
280757e22627SCy Schubert }
280857e22627SCy Schubert 
280957e22627SCy Schubert #ifndef _WIN32
281057e22627SCy Schubert //
281157e22627SCy Schubert // Do-nothing handler for SIGUSR1; the sole purpose of SIGUSR1 is to
281257e22627SCy Schubert // interrupt the data thread if it's blocked in a system call waiting
281357e22627SCy Schubert // for packets to arrive.
281457e22627SCy Schubert //
noop_handler(int sign _U_)281557e22627SCy Schubert static void noop_handler(int sign _U_)
281657e22627SCy Schubert {
281757e22627SCy Schubert }
281857e22627SCy Schubert #endif
281957e22627SCy Schubert 
282057e22627SCy Schubert /*!
282157e22627SCy Schubert 	\brief It serializes a network address.
282257e22627SCy Schubert 
282357e22627SCy Schubert 	It accepts a 'sockaddr_storage' structure as input, and it converts it appropriately into a format
282457e22627SCy Schubert 	that can be used to be sent on the network. Basically, it applies all the hton()
282557e22627SCy Schubert 	conversion required to the input variable.
282657e22627SCy Schubert 
282757e22627SCy Schubert 	\param sockaddrin a 'sockaddr_storage' pointer to the variable that has to be
282857e22627SCy Schubert 	serialized. This variable can be both a 'sockaddr_in' and 'sockaddr_in6'.
282957e22627SCy Schubert 
283057e22627SCy Schubert 	\param sockaddrout an 'rpcap_sockaddr' pointer to the variable that will contain
283157e22627SCy Schubert 	the serialized data. This variable has to be allocated by the user.
283257e22627SCy Schubert 
283357e22627SCy Schubert 	\warning This function supports only AF_INET and AF_INET6 address families.
283457e22627SCy Schubert */
283557e22627SCy Schubert static void
daemon_seraddr(struct sockaddr_storage * sockaddrin,struct rpcap_sockaddr * sockaddrout)283657e22627SCy Schubert daemon_seraddr(struct sockaddr_storage *sockaddrin, struct rpcap_sockaddr *sockaddrout)
283757e22627SCy Schubert {
283857e22627SCy Schubert 	memset(sockaddrout, 0, sizeof(struct sockaddr_storage));
283957e22627SCy Schubert 
284057e22627SCy Schubert 	// There can be the case in which the sockaddrin is not available
284157e22627SCy Schubert 	if (sockaddrin == NULL) return;
284257e22627SCy Schubert 
284357e22627SCy Schubert 	// Warning: we support only AF_INET and AF_INET6
2844*6f9cba8fSJoseph Mingrone 	//
2845*6f9cba8fSJoseph Mingrone 	// Note: as noted above, the output structures are not
2846*6f9cba8fSJoseph Mingrone 	// neatly aligned on 4-byte boundaries, so we must fill
2847*6f9cba8fSJoseph Mingrone 	// in an aligned structure and then copy it to the output
2848*6f9cba8fSJoseph Mingrone 	// buffer with memcpy().
284957e22627SCy Schubert 	switch (sockaddrin->ss_family)
285057e22627SCy Schubert 	{
285157e22627SCy Schubert 	case AF_INET:
285257e22627SCy Schubert 		{
285357e22627SCy Schubert 		struct sockaddr_in *sockaddrin_ipv4;
2854*6f9cba8fSJoseph Mingrone 		struct rpcap_sockaddr_in sockaddrout_ipv4;
285557e22627SCy Schubert 
285657e22627SCy Schubert 		sockaddrin_ipv4 = (struct sockaddr_in *) sockaddrin;
2857*6f9cba8fSJoseph Mingrone 
2858*6f9cba8fSJoseph Mingrone 		sockaddrout_ipv4.family = htons(RPCAP_AF_INET);
2859*6f9cba8fSJoseph Mingrone 		sockaddrout_ipv4.port = htons(sockaddrin_ipv4->sin_port);
2860*6f9cba8fSJoseph Mingrone 		memcpy(&sockaddrout_ipv4.addr, &sockaddrin_ipv4->sin_addr, sizeof(sockaddrout_ipv4.addr));
2861*6f9cba8fSJoseph Mingrone 		memset(sockaddrout_ipv4.zero, 0, sizeof(sockaddrout_ipv4.zero));
2862*6f9cba8fSJoseph Mingrone 		memcpy(sockaddrout, &sockaddrout_ipv4, sizeof(struct rpcap_sockaddr_in));
286357e22627SCy Schubert 		break;
286457e22627SCy Schubert 		}
286557e22627SCy Schubert 
286657e22627SCy Schubert #ifdef AF_INET6
286757e22627SCy Schubert 	case AF_INET6:
286857e22627SCy Schubert 		{
286957e22627SCy Schubert 		struct sockaddr_in6 *sockaddrin_ipv6;
2870*6f9cba8fSJoseph Mingrone 		struct rpcap_sockaddr_in6 sockaddrout_ipv6;
287157e22627SCy Schubert 
287257e22627SCy Schubert 		sockaddrin_ipv6 = (struct sockaddr_in6 *) sockaddrin;
2873*6f9cba8fSJoseph Mingrone 
2874*6f9cba8fSJoseph Mingrone 		sockaddrout_ipv6.family = htons(RPCAP_AF_INET6);
2875*6f9cba8fSJoseph Mingrone 		sockaddrout_ipv6.port = htons(sockaddrin_ipv6->sin6_port);
2876*6f9cba8fSJoseph Mingrone 		sockaddrout_ipv6.flowinfo = htonl(sockaddrin_ipv6->sin6_flowinfo);
2877*6f9cba8fSJoseph Mingrone 		memcpy(&sockaddrout_ipv6.addr, &sockaddrin_ipv6->sin6_addr, sizeof(sockaddrout_ipv6.addr));
2878*6f9cba8fSJoseph Mingrone 		sockaddrout_ipv6.scope_id = htonl(sockaddrin_ipv6->sin6_scope_id);
2879*6f9cba8fSJoseph Mingrone 		memcpy(sockaddrout, &sockaddrout_ipv6, sizeof(struct rpcap_sockaddr_in6));
288057e22627SCy Schubert 		break;
288157e22627SCy Schubert 		}
288257e22627SCy Schubert #endif
288357e22627SCy Schubert 	}
288457e22627SCy Schubert }
288557e22627SCy Schubert 
288657e22627SCy Schubert 
288757e22627SCy Schubert /*!
288857e22627SCy Schubert 	\brief Suspends a thread for secs seconds.
288957e22627SCy Schubert */
sleep_secs(int secs)289057e22627SCy Schubert void sleep_secs(int secs)
289157e22627SCy Schubert {
2892*6f9cba8fSJoseph Mingrone #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
289357e22627SCy Schubert #ifdef _WIN32
289457e22627SCy Schubert 	Sleep(secs*1000);
289557e22627SCy Schubert #else
289657e22627SCy Schubert 	unsigned secs_remaining;
289757e22627SCy Schubert 
289857e22627SCy Schubert 	if (secs <= 0)
289957e22627SCy Schubert 		return;
290057e22627SCy Schubert 	secs_remaining = secs;
290157e22627SCy Schubert 	while (secs_remaining != 0)
290257e22627SCy Schubert 		secs_remaining = sleep(secs_remaining);
290357e22627SCy Schubert #endif
2904*6f9cba8fSJoseph Mingrone #endif
290557e22627SCy Schubert }
290657e22627SCy Schubert 
290757e22627SCy Schubert /*
290857e22627SCy Schubert  * Read the header of a message.
290957e22627SCy Schubert  */
291057e22627SCy Schubert static int
rpcapd_recv_msg_header(SOCKET sock,SSL * ssl,struct rpcap_header * headerp)2911*6f9cba8fSJoseph Mingrone rpcapd_recv_msg_header(SOCKET sock, SSL *ssl, struct rpcap_header *headerp)
291257e22627SCy Schubert {
291357e22627SCy Schubert 	int nread;
291457e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
291557e22627SCy Schubert 
2916*6f9cba8fSJoseph Mingrone 	nread = sock_recv(sock, ssl, (char *) headerp, sizeof(struct rpcap_header),
291757e22627SCy Schubert 	    SOCK_RECEIVEALL_YES|SOCK_EOF_ISNT_ERROR, errbuf, PCAP_ERRBUF_SIZE);
291857e22627SCy Schubert 	if (nread == -1)
291957e22627SCy Schubert 	{
292057e22627SCy Schubert 		// Network error.
292157e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
292257e22627SCy Schubert 		return -1;
292357e22627SCy Schubert 	}
292457e22627SCy Schubert 	if (nread == 0)
292557e22627SCy Schubert 	{
292657e22627SCy Schubert 		// Immediate EOF; that's treated like a close message.
292757e22627SCy Schubert 		return -2;
292857e22627SCy Schubert 	}
292957e22627SCy Schubert 	headerp->plen = ntohl(headerp->plen);
293057e22627SCy Schubert 	return 0;
293157e22627SCy Schubert }
293257e22627SCy Schubert 
293357e22627SCy Schubert /*
293457e22627SCy Schubert  * Read data from a message.
293557e22627SCy Schubert  * If we're trying to read more data that remains, puts an error
293657e22627SCy Schubert  * message into errmsgbuf and returns -2.  Otherwise, tries to read
293757e22627SCy Schubert  * the data and, if that succeeds, subtracts the amount read from
293857e22627SCy Schubert  * the number of bytes of data that remains.
293957e22627SCy Schubert  * Returns 0 on success, logs a message and returns -1 on a network
294057e22627SCy Schubert  * error.
294157e22627SCy Schubert  */
294257e22627SCy Schubert static int
rpcapd_recv(SOCKET sock,SSL * ssl,char * buffer,size_t toread,uint32 * plen,char * errmsgbuf)2943*6f9cba8fSJoseph Mingrone rpcapd_recv(SOCKET sock, SSL *ssl, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf)
294457e22627SCy Schubert {
294557e22627SCy Schubert 	int nread;
294657e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE];		// buffer for network errors
294757e22627SCy Schubert 
294857e22627SCy Schubert 	if (toread > *plen)
294957e22627SCy Schubert 	{
295057e22627SCy Schubert 		// Tell the client and continue.
2951*6f9cba8fSJoseph Mingrone 		snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message payload is too short");
295257e22627SCy Schubert 		return -2;
295357e22627SCy Schubert 	}
2954*6f9cba8fSJoseph Mingrone 	nread = sock_recv(sock, ssl, buffer, toread,
295557e22627SCy Schubert 	    SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
295657e22627SCy Schubert 	if (nread == -1)
295757e22627SCy Schubert 	{
295857e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
295957e22627SCy Schubert 		return -1;
296057e22627SCy Schubert 	}
296157e22627SCy Schubert 	*plen -= nread;
296257e22627SCy Schubert 	return 0;
296357e22627SCy Schubert }
296457e22627SCy Schubert 
296557e22627SCy Schubert /*
296657e22627SCy Schubert  * Discard data from a connection.
296757e22627SCy Schubert  * Mostly used to discard wrong-sized messages.
296857e22627SCy Schubert  * Returns 0 on success, logs a message and returns -1 on a network
296957e22627SCy Schubert  * error.
297057e22627SCy Schubert  */
297157e22627SCy Schubert static int
rpcapd_discard(SOCKET sock,SSL * ssl,uint32 len)2972*6f9cba8fSJoseph Mingrone rpcapd_discard(SOCKET sock, SSL *ssl, uint32 len)
297357e22627SCy Schubert {
297457e22627SCy Schubert 	char errbuf[PCAP_ERRBUF_SIZE + 1];	// keeps the error string, prior to be printed
297557e22627SCy Schubert 
297657e22627SCy Schubert 	if (len != 0)
297757e22627SCy Schubert 	{
2978*6f9cba8fSJoseph Mingrone 		if (sock_discard(sock, ssl, len, errbuf, PCAP_ERRBUF_SIZE) == -1)
297957e22627SCy Schubert 		{
298057e22627SCy Schubert 			// Network error.
298157e22627SCy Schubert 			rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
298257e22627SCy Schubert 			return -1;
298357e22627SCy Schubert 		}
298457e22627SCy Schubert 	}
298557e22627SCy Schubert 	return 0;
298657e22627SCy Schubert }
298757e22627SCy Schubert 
298857e22627SCy Schubert //
298957e22627SCy Schubert // Shut down any packet-capture thread associated with the session,
299057e22627SCy Schubert // close the SSL handle for the data socket if we have one, close
299157e22627SCy Schubert // the data socket if we have one, and close the underlying packet
299257e22627SCy Schubert // capture handle if we have one.
299357e22627SCy Schubert //
299457e22627SCy Schubert // We do not, of course, touch the controlling socket that's also
299557e22627SCy Schubert // copied into the session, as the service loop might still use it.
299657e22627SCy Schubert //
session_close(struct session * session)299757e22627SCy Schubert static void session_close(struct session *session)
299857e22627SCy Schubert {
299957e22627SCy Schubert 	if (session->have_thread)
300057e22627SCy Schubert 	{
300157e22627SCy Schubert 		//
300257e22627SCy Schubert 		// Tell the data connection thread main capture loop to
300357e22627SCy Schubert 		// break out of that loop.
300457e22627SCy Schubert 		//
300557e22627SCy Schubert 		// This may be sufficient to wake up a blocked thread,
300657e22627SCy Schubert 		// but it's not guaranteed to be sufficient.
300757e22627SCy Schubert 		//
300857e22627SCy Schubert 		pcap_breakloop(session->fp);
300957e22627SCy Schubert 
301057e22627SCy Schubert #ifdef _WIN32
301157e22627SCy Schubert 		//
301257e22627SCy Schubert 		// Set the event on which a read would block, so that,
301357e22627SCy Schubert 		// if it's currently blocked waiting for packets to
301457e22627SCy Schubert 		// arrive, it'll wake up, so it can see the "break
301557e22627SCy Schubert 		// out of the loop" indication.  (pcap_breakloop()
301657e22627SCy Schubert 		// might do this, but older versions don't.  Setting
301757e22627SCy Schubert 		// it twice should, at worst, cause an extra wakeup,
301857e22627SCy Schubert 		// which shouldn't be a problem.)
301957e22627SCy Schubert 		//
302057e22627SCy Schubert 		// XXX - what about modules other than NPF?
302157e22627SCy Schubert 		//
302257e22627SCy Schubert 		SetEvent(pcap_getevent(session->fp));
302357e22627SCy Schubert 
302457e22627SCy Schubert 		//
302557e22627SCy Schubert 		// Wait for the thread to exit, so we don't close
302657e22627SCy Schubert 		// sockets out from under it.
302757e22627SCy Schubert 		//
302857e22627SCy Schubert 		// XXX - have a timeout, so we don't wait forever?
302957e22627SCy Schubert 		//
303057e22627SCy Schubert 		WaitForSingleObject(session->thread, INFINITE);
303157e22627SCy Schubert 
303257e22627SCy Schubert 		//
303357e22627SCy Schubert 		// Release the thread handle, as we're done with
303457e22627SCy Schubert 		// it.
303557e22627SCy Schubert 		//
303657e22627SCy Schubert 		CloseHandle(session->thread);
303757e22627SCy Schubert 		session->have_thread = 0;
303857e22627SCy Schubert 		session->thread = INVALID_HANDLE_VALUE;
303957e22627SCy Schubert #else
304057e22627SCy Schubert 		//
304157e22627SCy Schubert 		// Send a SIGUSR1 signal to the thread, so that, if
304257e22627SCy Schubert 		// it's currently blocked waiting for packets to arrive,
304357e22627SCy Schubert 		// it'll wake up (we've turned off SA_RESTART for
304457e22627SCy Schubert 		// SIGUSR1, so that the system call in which it's blocked
304557e22627SCy Schubert 		// should return EINTR rather than restarting).
304657e22627SCy Schubert 		//
304757e22627SCy Schubert 		pthread_kill(session->thread, SIGUSR1);
304857e22627SCy Schubert 
304957e22627SCy Schubert 		//
305057e22627SCy Schubert 		// Wait for the thread to exit, so we don't close
305157e22627SCy Schubert 		// sockets out from under it.
305257e22627SCy Schubert 		//
305357e22627SCy Schubert 		// XXX - have a timeout, so we don't wait forever?
305457e22627SCy Schubert 		//
305557e22627SCy Schubert 		pthread_join(session->thread, NULL);
305657e22627SCy Schubert 		session->have_thread = 0;
305757e22627SCy Schubert 		memset(&session->thread, 0, sizeof(session->thread));
305857e22627SCy Schubert #endif
305957e22627SCy Schubert 	}
306057e22627SCy Schubert 
3061*6f9cba8fSJoseph Mingrone #ifdef HAVE_OPENSSL
3062*6f9cba8fSJoseph Mingrone 	if (session->data_ssl)
3063*6f9cba8fSJoseph Mingrone 	{
3064*6f9cba8fSJoseph Mingrone 		// Finish using the SSL handle for the socket.
3065*6f9cba8fSJoseph Mingrone 		// This must be done *before* the socket is closed.
3066*6f9cba8fSJoseph Mingrone 		ssl_finish(session->data_ssl);
3067*6f9cba8fSJoseph Mingrone 		session->data_ssl = NULL;
3068*6f9cba8fSJoseph Mingrone 	}
3069*6f9cba8fSJoseph Mingrone #endif
3070*6f9cba8fSJoseph Mingrone 
307157e22627SCy Schubert 	if (session->sockdata != INVALID_SOCKET)
307257e22627SCy Schubert 	{
307357e22627SCy Schubert 		sock_close(session->sockdata, NULL, 0);
307457e22627SCy Schubert 		session->sockdata = INVALID_SOCKET;
307557e22627SCy Schubert 	}
307657e22627SCy Schubert 
307757e22627SCy Schubert 	if (session->fp)
307857e22627SCy Schubert 	{
307957e22627SCy Schubert 		pcap_close(session->fp);
308057e22627SCy Schubert 		session->fp = NULL;
308157e22627SCy Schubert 	}
308257e22627SCy Schubert }
308357e22627SCy Schubert 
308457e22627SCy Schubert //
308557e22627SCy Schubert // Check whether a capture source string is a URL or not.
308657e22627SCy Schubert // This includes URLs that refer to a local device; a scheme, followed
308757e22627SCy Schubert // by ://, followed by *another* scheme and ://, is just silly, and
308857e22627SCy Schubert // anybody who supplies that will get an error.
308957e22627SCy Schubert //
309057e22627SCy Schubert static int
is_url(const char * source)309157e22627SCy Schubert is_url(const char *source)
309257e22627SCy Schubert {
309357e22627SCy Schubert 	char *colonp;
309457e22627SCy Schubert 
309557e22627SCy Schubert 	/*
309657e22627SCy Schubert 	 * RFC 3986 says:
309757e22627SCy Schubert 	 *
309857e22627SCy Schubert 	 *   URI         = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
309957e22627SCy Schubert 	 *
310057e22627SCy Schubert 	 *   hier-part   = "//" authority path-abempty
310157e22627SCy Schubert 	 *               / path-absolute
310257e22627SCy Schubert 	 *               / path-rootless
310357e22627SCy Schubert 	 *               / path-empty
310457e22627SCy Schubert 	 *
310557e22627SCy Schubert 	 *   authority   = [ userinfo "@" ] host [ ":" port ]
310657e22627SCy Schubert 	 *
310757e22627SCy Schubert 	 *   userinfo    = *( unreserved / pct-encoded / sub-delims / ":" )
310857e22627SCy Schubert 	 *
310957e22627SCy Schubert 	 * Step 1: look for the ":" at the end of the scheme.
311057e22627SCy Schubert 	 * A colon in the source is *NOT* sufficient to indicate that
311157e22627SCy Schubert 	 * this is a URL, as interface names on some platforms might
311257e22627SCy Schubert 	 * include colons (e.g., I think some Solaris interfaces
311357e22627SCy Schubert 	 * might).
311457e22627SCy Schubert 	 */
311557e22627SCy Schubert 	colonp = strchr(source, ':');
311657e22627SCy Schubert 	if (colonp == NULL)
311757e22627SCy Schubert 	{
311857e22627SCy Schubert 		/*
311957e22627SCy Schubert 		 * The source is the device to open.  It's not a URL.
312057e22627SCy Schubert 		 */
312157e22627SCy Schubert 		return (0);
312257e22627SCy Schubert 	}
312357e22627SCy Schubert 
312457e22627SCy Schubert 	/*
312557e22627SCy Schubert 	 * All schemes must have "//" after them, i.e. we only support
312657e22627SCy Schubert 	 * hier-part   = "//" authority path-abempty, not
312757e22627SCy Schubert 	 * hier-part   = path-absolute
312857e22627SCy Schubert 	 * hier-part   = path-rootless
312957e22627SCy Schubert 	 * hier-part   = path-empty
313057e22627SCy Schubert 	 *
313157e22627SCy Schubert 	 * We need that in order to distinguish between a local device
313257e22627SCy Schubert 	 * name that happens to contain a colon and a URI.
313357e22627SCy Schubert 	 */
313457e22627SCy Schubert 	if (strncmp(colonp + 1, "//", 2) != 0)
313557e22627SCy Schubert 	{
313657e22627SCy Schubert 		/*
313757e22627SCy Schubert 		 * The source is the device to open.  It's not a URL.
313857e22627SCy Schubert 		 */
313957e22627SCy Schubert 		return (0);
314057e22627SCy Schubert 	}
314157e22627SCy Schubert 
314257e22627SCy Schubert 	/*
314357e22627SCy Schubert 	 * It's a URL.
314457e22627SCy Schubert 	 */
314557e22627SCy Schubert 	return (1);
314657e22627SCy Schubert }
3147