xref: /freebsd/contrib/libpcap/rpcapd/win32-svc.c (revision afdbf109c6a661a729938f68211054a0a50d38ac)
157e22627SCy Schubert /*
257e22627SCy Schubert  * Copyright (c) 2002 - 2003
357e22627SCy Schubert  * NetGroup, Politecnico di Torino (Italy)
457e22627SCy Schubert  * All rights reserved.
557e22627SCy Schubert  *
657e22627SCy Schubert  * Redistribution and use in source and binary forms, with or without
757e22627SCy Schubert  * modification, are permitted provided that the following conditions
857e22627SCy Schubert  * are met:
957e22627SCy Schubert  *
1057e22627SCy Schubert  * 1. Redistributions of source code must retain the above copyright
1157e22627SCy Schubert  * notice, this list of conditions and the following disclaimer.
1257e22627SCy Schubert  * 2. Redistributions in binary form must reproduce the above copyright
1357e22627SCy Schubert  * notice, this list of conditions and the following disclaimer in the
1457e22627SCy Schubert  * documentation and/or other materials provided with the distribution.
1557e22627SCy Schubert  * 3. Neither the name of the Politecnico di Torino nor the names of its
1657e22627SCy Schubert  * contributors may be used to endorse or promote products derived from
1757e22627SCy Schubert  * this software without specific prior written permission.
1857e22627SCy Schubert  *
1957e22627SCy Schubert  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2057e22627SCy Schubert  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2157e22627SCy Schubert  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2257e22627SCy Schubert  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2357e22627SCy Schubert  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2457e22627SCy Schubert  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2557e22627SCy Schubert  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2657e22627SCy Schubert  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2757e22627SCy Schubert  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2857e22627SCy Schubert  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2957e22627SCy Schubert  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3057e22627SCy Schubert  *
3157e22627SCy Schubert  */
3257e22627SCy Schubert 
3357e22627SCy Schubert 
3457e22627SCy Schubert #include "rpcapd.h"
3557e22627SCy Schubert #include <pcap.h>		// for PCAP_ERRBUF_SIZE
3657e22627SCy Schubert #include "fmtutils.h"
3757e22627SCy Schubert #include "portability.h"
3857e22627SCy Schubert #include "fileconf.h"
3957e22627SCy Schubert #include "log.h"
4057e22627SCy Schubert 
416f9cba8fSJoseph Mingrone #include "win32-svc.h"	// for Win32 service stuff
426f9cba8fSJoseph Mingrone 
4357e22627SCy Schubert static SERVICE_STATUS_HANDLE service_status_handle;
4457e22627SCy Schubert static SERVICE_STATUS service_status;
4557e22627SCy Schubert 
4657e22627SCy Schubert static void WINAPI svc_main(DWORD argc, char **argv);
476f9cba8fSJoseph Mingrone static void WINAPI svc_control_handler(DWORD Opcode);
4857e22627SCy Schubert static void update_svc_status(DWORD state, DWORD progress_indicator);
4957e22627SCy Schubert 
svc_start(void)506f9cba8fSJoseph Mingrone BOOL svc_start(void)
5157e22627SCy Schubert {
526f9cba8fSJoseph Mingrone 	BOOL rc;
5357e22627SCy Schubert 	SERVICE_TABLE_ENTRY ste[] =
5457e22627SCy Schubert 	{
5557e22627SCy Schubert 		{ PROGRAM_NAME, svc_main },
5657e22627SCy Schubert 		{ NULL, NULL }
5757e22627SCy Schubert 	};
5857e22627SCy Schubert 	char string[PCAP_ERRBUF_SIZE];
5957e22627SCy Schubert 
6057e22627SCy Schubert 	// This call is blocking. A new thread is created which will launch
6157e22627SCy Schubert 	// the svc_main() function
6257e22627SCy Schubert 	if ((rc = StartServiceCtrlDispatcher(ste)) == 0) {
63*afdbf109SJoseph Mingrone 		pcapint_fmt_errmsg_for_win32_err(string, sizeof (string),
6457e22627SCy Schubert 		    GetLastError(), "StartServiceCtrlDispatcher() failed");
6557e22627SCy Schubert 		rpcapd_log(LOGPRIO_ERROR, "%s", string);
6657e22627SCy Schubert 	}
6757e22627SCy Schubert 
6857e22627SCy Schubert 	return rc; // FALSE if this is not started as a service
6957e22627SCy Schubert }
7057e22627SCy Schubert 
716f9cba8fSJoseph Mingrone static void WINAPI
svc_control_handler(DWORD Opcode)726f9cba8fSJoseph Mingrone svc_control_handler(DWORD Opcode)
7357e22627SCy Schubert {
7457e22627SCy Schubert 	switch(Opcode)
7557e22627SCy Schubert 	{
7657e22627SCy Schubert 		case SERVICE_CONTROL_STOP:
7757e22627SCy Schubert 			//
7857e22627SCy Schubert 			// XXX - is this sufficient to clean up the service?
7957e22627SCy Schubert 			// To be really honest, only the main socket and
8057e22627SCy Schubert 			// such these stuffs are cleared; however the threads
8157e22627SCy Schubert 			// that are running are not stopped.
8257e22627SCy Schubert 			// This can be seen by placing a breakpoint at the
8357e22627SCy Schubert 			// end of svc_main(), in which you will see that is
8457e22627SCy Schubert 			// never reached. However, as soon as you set the
8557e22627SCy Schubert 			// service status to "stopped",	the
8657e22627SCy Schubert 			// StartServiceCtrlDispatcher() returns and the main
8757e22627SCy Schubert 			// thread ends. Then, Win32 has a good automatic
8857e22627SCy Schubert 			// cleanup, so that all the threads which are still
8957e22627SCy Schubert 			// running are stopped when the main thread ends.
9057e22627SCy Schubert 			//
9157e22627SCy Schubert 			send_shutdown_notification();
9257e22627SCy Schubert 
9357e22627SCy Schubert 			update_svc_status(SERVICE_STOP_PENDING, 0);
9457e22627SCy Schubert 			break;
9557e22627SCy Schubert 
9657e22627SCy Schubert 		/*
9757e22627SCy Schubert 			Pause and Continue have an usual meaning and they are used just to be able
9857e22627SCy Schubert 			to change the running parameters at run-time. In other words, they act
9957e22627SCy Schubert 			like the SIGHUP signal on UNIX. All the running threads continue to run and
10057e22627SCy Schubert 			they are not paused at all.
10157e22627SCy Schubert 			Particularly,
10257e22627SCy Schubert 			- PAUSE does nothing
10357e22627SCy Schubert 			- CONTINUE re-reads the configuration file and creates the new threads that
10457e22627SCy Schubert 			can be needed according to the new configuration.
10557e22627SCy Schubert 		*/
10657e22627SCy Schubert 		case SERVICE_CONTROL_PAUSE:
10757e22627SCy Schubert 			update_svc_status(SERVICE_PAUSED, 0);
10857e22627SCy Schubert 			break;
10957e22627SCy Schubert 
11057e22627SCy Schubert 		case SERVICE_CONTROL_CONTINUE:
11157e22627SCy Schubert 			update_svc_status(SERVICE_RUNNING, 0);
11257e22627SCy Schubert 			//
11357e22627SCy Schubert 			// Tell the main loop to re-read the configuration.
11457e22627SCy Schubert 			//
11557e22627SCy Schubert 			send_reread_configuration_notification();
11657e22627SCy Schubert 			break;
11757e22627SCy Schubert 
11857e22627SCy Schubert 		case SERVICE_CONTROL_INTERROGATE:
11957e22627SCy Schubert 			// Fall through to send current status.
12057e22627SCy Schubert 			//	WARNING: not implemented
12157e22627SCy Schubert 			update_svc_status(SERVICE_RUNNING, 0);
12257e22627SCy Schubert 			MessageBox(NULL, "Not implemented", "warning", MB_OK);
12357e22627SCy Schubert 			break;
12457e22627SCy Schubert 
12557e22627SCy Schubert 		case SERVICE_CONTROL_PARAMCHANGE:
12657e22627SCy Schubert 			//
12757e22627SCy Schubert 			// Tell the main loop to re-read the configuration.
12857e22627SCy Schubert 			//
12957e22627SCy Schubert 			send_reread_configuration_notification();
13057e22627SCy Schubert 			break;
13157e22627SCy Schubert 	}
13257e22627SCy Schubert 
13357e22627SCy Schubert 	// Send current status.
13457e22627SCy Schubert 	return;
13557e22627SCy Schubert }
13657e22627SCy Schubert 
1376f9cba8fSJoseph Mingrone static void WINAPI
svc_main(DWORD argc,char ** argv)1386f9cba8fSJoseph Mingrone svc_main(DWORD argc, char **argv)
13957e22627SCy Schubert {
14057e22627SCy Schubert 	service_status_handle = RegisterServiceCtrlHandler(PROGRAM_NAME, svc_control_handler);
14157e22627SCy Schubert 
14257e22627SCy Schubert 	if (!service_status_handle)
14357e22627SCy Schubert 		return;
14457e22627SCy Schubert 
14557e22627SCy Schubert 	service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
14657e22627SCy Schubert 	service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_PARAMCHANGE;
14757e22627SCy Schubert 	// | SERVICE_ACCEPT_SHUTDOWN ;
14857e22627SCy Schubert 	update_svc_status(SERVICE_RUNNING, 0);
14957e22627SCy Schubert 
15057e22627SCy Schubert 	//
15157e22627SCy Schubert 	// Service requests until we're told to stop.
15257e22627SCy Schubert 	//
15357e22627SCy Schubert 	main_startup();
15457e22627SCy Schubert 
15557e22627SCy Schubert 	//
15657e22627SCy Schubert 	// It returned, so we were told to stop.
15757e22627SCy Schubert 	//
15857e22627SCy Schubert 	update_svc_status(SERVICE_STOPPED, 0);
15957e22627SCy Schubert }
16057e22627SCy Schubert 
16157e22627SCy Schubert static void
update_svc_status(DWORD state,DWORD progress_indicator)16257e22627SCy Schubert update_svc_status(DWORD state, DWORD progress_indicator)
16357e22627SCy Schubert {
16457e22627SCy Schubert 	service_status.dwWin32ExitCode = NO_ERROR;
16557e22627SCy Schubert 	service_status.dwCurrentState = state;
16657e22627SCy Schubert 	service_status.dwCheckPoint = progress_indicator;
16757e22627SCy Schubert 	service_status.dwWaitHint = 0;
16857e22627SCy Schubert 	SetServiceStatus(service_status_handle, &service_status);
16957e22627SCy Schubert }
17057e22627SCy Schubert 
17157e22627SCy Schubert /*
17257e22627SCy Schubert sc create rpcapd DisplayName= "Remote Packet Capture Protocol v.0 (experimental)" binpath= "C:\cvsroot\winpcap\wpcap\PRJ\Debug\rpcapd -d -f rpcapd.ini"
17357e22627SCy Schubert sc description rpcapd "Allows to capture traffic on this host from a remote machine."
17457e22627SCy Schubert */
175