Blame rpcapd/win32-svc.c

Packit 209cc3
/*
Packit 209cc3
 * Copyright (c) 2002 - 2003
Packit 209cc3
 * NetGroup, Politecnico di Torino (Italy)
Packit 209cc3
 * All rights reserved.
Packit 209cc3
 *
Packit 209cc3
 * Redistribution and use in source and binary forms, with or without
Packit 209cc3
 * modification, are permitted provided that the following conditions
Packit 209cc3
 * are met:
Packit 209cc3
 *
Packit 209cc3
 * 1. Redistributions of source code must retain the above copyright
Packit 209cc3
 * notice, this list of conditions and the following disclaimer.
Packit 209cc3
 * 2. Redistributions in binary form must reproduce the above copyright
Packit 209cc3
 * notice, this list of conditions and the following disclaimer in the
Packit 209cc3
 * documentation and/or other materials provided with the distribution.
Packit 209cc3
 * 3. Neither the name of the Politecnico di Torino nor the names of its
Packit 209cc3
 * contributors may be used to endorse or promote products derived from
Packit 209cc3
 * this software without specific prior written permission.
Packit 209cc3
 *
Packit 209cc3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 209cc3
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 209cc3
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 209cc3
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 209cc3
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 209cc3
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 209cc3
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 209cc3
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 209cc3
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 209cc3
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 209cc3
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 209cc3
 *
Packit 209cc3
 */
Packit 209cc3
Packit 209cc3
Packit 209cc3
#include "rpcapd.h"
Packit 209cc3
#include <pcap.h>		// for PCAP_ERRBUF_SIZE
Packit 209cc3
#include "fmtutils.h"
Packit 209cc3
#include "portability.h"
Packit 209cc3
#include "fileconf.h"
Packit 209cc3
#include "log.h"
Packit 209cc3
Packit 209cc3
static SERVICE_STATUS_HANDLE service_status_handle;
Packit 209cc3
static SERVICE_STATUS service_status;
Packit 209cc3
Packit 209cc3
static void WINAPI svc_main(DWORD argc, char **argv);
Packit 209cc3
static void update_svc_status(DWORD state, DWORD progress_indicator);
Packit 209cc3
Packit 209cc3
int svc_start(void)
Packit 209cc3
{
Packit 209cc3
	int rc;
Packit 209cc3
	SERVICE_TABLE_ENTRY ste[] =
Packit 209cc3
	{
Packit 209cc3
		{ PROGRAM_NAME, svc_main },
Packit 209cc3
		{ NULL, NULL }
Packit 209cc3
	};
Packit 209cc3
	char string[PCAP_ERRBUF_SIZE];
Packit 209cc3
Packit 209cc3
	// This call is blocking. A new thread is created which will launch
Packit 209cc3
	// the svc_main() function
Packit 209cc3
	if ((rc = StartServiceCtrlDispatcher(ste)) == 0) {
Packit 209cc3
		pcap_fmt_errmsg_for_win32_err(string, sizeof (string),
Packit 209cc3
		    GetLastError(), "StartServiceCtrlDispatcher() failed");
Packit 209cc3
		rpcapd_log(LOGPRIO_ERROR, "%s", string);
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	return rc; // FALSE if this is not started as a service
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
void WINAPI svc_control_handler(DWORD Opcode)
Packit 209cc3
{
Packit 209cc3
	switch(Opcode)
Packit 209cc3
	{
Packit 209cc3
		case SERVICE_CONTROL_STOP:
Packit 209cc3
			//
Packit 209cc3
			// XXX - is this sufficient to clean up the service?
Packit 209cc3
			// To be really honest, only the main socket and
Packit 209cc3
			// such these stuffs are cleared; however the threads
Packit 209cc3
			// that are running are not stopped.
Packit 209cc3
			// This can be seen by placing a breakpoint at the
Packit 209cc3
			// end of svc_main(), in which you will see that is
Packit 209cc3
			// never reached. However, as soon as you set the
Packit 209cc3
			// service status to "stopped",	the
Packit 209cc3
			// StartServiceCtrlDispatcher() returns and the main
Packit 209cc3
			// thread ends. Then, Win32 has a good automatic
Packit 209cc3
			// cleanup, so that all the threads which are still
Packit 209cc3
			// running are stopped when the main thread ends.
Packit 209cc3
			//
Packit 209cc3
			send_shutdown_notification();
Packit 209cc3
Packit 209cc3
			update_svc_status(SERVICE_STOP_PENDING, 0);
Packit 209cc3
			break;
Packit 209cc3
Packit 209cc3
		/*
Packit 209cc3
			Pause and Continue have an usual meaning and they are used just to be able
Packit 209cc3
			to change the running parameters at run-time. In other words, they act
Packit 209cc3
			like the SIGHUP signal on UNIX. All the running threads continue to run and
Packit 209cc3
			they are not paused at all.
Packit 209cc3
			Particularly,
Packit 209cc3
			- PAUSE does nothing
Packit 209cc3
			- CONTINUE re-reads the configuration file and creates the new threads that
Packit 209cc3
			can be needed according to the new configuration.
Packit 209cc3
		*/
Packit 209cc3
		case SERVICE_CONTROL_PAUSE:
Packit 209cc3
			update_svc_status(SERVICE_PAUSED, 0);
Packit 209cc3
			break;
Packit 209cc3
Packit 209cc3
		case SERVICE_CONTROL_CONTINUE:
Packit 209cc3
			update_svc_status(SERVICE_RUNNING, 0);
Packit 209cc3
			//
Packit 209cc3
			// Tell the main loop to re-read the configuration.
Packit 209cc3
			//
Packit 209cc3
			send_reread_configuration_notification();
Packit 209cc3
			break;
Packit 209cc3
Packit 209cc3
		case SERVICE_CONTROL_INTERROGATE:
Packit 209cc3
			// Fall through to send current status.
Packit 209cc3
			//	WARNING: not implemented
Packit 209cc3
			update_svc_status(SERVICE_RUNNING, 0);
Packit 209cc3
			MessageBox(NULL, "Not implemented", "warning", MB_OK);
Packit 209cc3
			break;
Packit 209cc3
Packit 209cc3
		case SERVICE_CONTROL_PARAMCHANGE:
Packit 209cc3
			//
Packit 209cc3
			// Tell the main loop to re-read the configuration.
Packit 209cc3
			//
Packit 209cc3
			send_reread_configuration_notification();
Packit 209cc3
			break;
Packit 209cc3
	}
Packit 209cc3
Packit 209cc3
	// Send current status.
Packit 209cc3
	return;
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
void WINAPI svc_main(DWORD argc, char **argv)
Packit 209cc3
{
Packit 209cc3
	service_status_handle = RegisterServiceCtrlHandler(PROGRAM_NAME, svc_control_handler);
Packit 209cc3
Packit 209cc3
	if (!service_status_handle)
Packit 209cc3
		return;
Packit 209cc3
Packit 209cc3
	service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
Packit 209cc3
	service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_PARAMCHANGE;
Packit 209cc3
	// | SERVICE_ACCEPT_SHUTDOWN ;
Packit 209cc3
	update_svc_status(SERVICE_RUNNING, 0);
Packit 209cc3
Packit 209cc3
	//
Packit 209cc3
	// Service requests until we're told to stop.
Packit 209cc3
	//
Packit 209cc3
	main_startup();
Packit 209cc3
Packit 209cc3
	//
Packit 209cc3
	// It returned, so we were told to stop.
Packit 209cc3
	//
Packit 209cc3
	update_svc_status(SERVICE_STOPPED, 0);
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
static void
Packit 209cc3
update_svc_status(DWORD state, DWORD progress_indicator)
Packit 209cc3
{
Packit 209cc3
	service_status.dwWin32ExitCode = NO_ERROR;
Packit 209cc3
	service_status.dwCurrentState = state;
Packit 209cc3
	service_status.dwCheckPoint = progress_indicator;
Packit 209cc3
	service_status.dwWaitHint = 0;
Packit 209cc3
	SetServiceStatus(service_status_handle, &service_status);
Packit 209cc3
}
Packit 209cc3
Packit 209cc3
/*
Packit 209cc3
sc create rpcapd DisplayName= "Remote Packet Capture Protocol v.0 (experimental)" binpath= "C:\cvsroot\winpcap\wpcap\PRJ\Debug\rpcapd -d -f rpcapd.ini"
Packit 209cc3
sc description rpcapd "Allows to capture traffic on this host from a remote machine."
Packit 209cc3
*/