• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2002 - 2003
3  * NetGroup, Politecnico di Torino (Italy)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in the
14  * documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the Politecnico di Torino nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
33 
34 #include "rpcapd.h"
35 #include <pcap.h>		// for PCAP_ERRBUF_SIZE
36 #include "sockutils.h"		// for SOCK_DEBUG_MESSAGE
37 #include "portability.h"
38 #include "fileconf.h"
39 
40 static SERVICE_STATUS_HANDLE service_status_handle;
41 static SERVICE_STATUS service_status;
42 
43 void svc_geterr(char *str);
44 static void WINAPI svc_main(DWORD argc, char **argv);
45 static void update_svc_status(DWORD state, DWORD progress_indicator);
46 
svc_start(void)47 int svc_start(void)
48 {
49 	int rc;
50 	SERVICE_TABLE_ENTRY ste[] =
51 	{
52 		{ PROGRAM_NAME, svc_main },
53 		{ NULL, NULL }
54 	};
55 
56 	// This call is blocking. A new thread is created which will launch
57 	// the svc_main() function
58 	if ( (rc = StartServiceCtrlDispatcher(ste)) == 0)
59 		svc_geterr("StartServiceCtrlDispatcher()");
60 
61 	return rc; // FALSE if this is not started as a service
62 }
63 
svc_geterr(char * str)64 void svc_geterr(char *str)
65 {
66 	char message[PCAP_ERRBUF_SIZE];
67 	char string[PCAP_ERRBUF_SIZE];
68 	int val;
69 
70 	val = GetLastError();
71 	FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
72 				  FORMAT_MESSAGE_MAX_WIDTH_MASK,
73 				  NULL, val, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
74 				  (LPSTR) string, PCAP_ERRBUF_SIZE, NULL);
75 
76 	pcap_snprintf(message, PCAP_ERRBUF_SIZE, "%s failed with error %d: %s", str, val, string);
77 
78 	SOCK_DEBUG_MESSAGE(message);
79 }
80 
svc_control_handler(DWORD Opcode)81 void WINAPI svc_control_handler(DWORD Opcode)
82 {
83 	switch(Opcode)
84 	{
85 		case SERVICE_CONTROL_STOP:
86 			//
87 			// XXX - is this sufficient to clean up the service?
88 			// To be really honest, only the main socket and
89 			// such these stuffs are cleared; however the threads
90 			// that are running are not stopped.
91 			// This can be seen by placing a breakpoint at the
92 			// end of svc_main(), in which you will see that is
93 			// never reached. However, as soon as you set the
94 			// service status to "stopped",	the
95 			// StartServiceCtrlDispatcher() returns and the main
96 			// thread ends. Then, Win32 has a good automatic
97 			// cleanup, so that all the threads which are still
98 			// running are stopped when the main thread ends.
99 			//
100 			send_shutdown_notification();
101 
102 			update_svc_status(SERVICE_STOP_PENDING, 0);
103 			break;
104 
105 		/*
106 			Pause and Continue have an usual meaning and they are used just to be able
107 			to change the running parameters at run-time. In other words, they act
108 			like the SIGHUP signal on UNIX. All the running threads continue to run and
109 			they are not paused at all.
110 			Particularly,
111 			- PAUSE does nothing
112 			- CONTINUE re-reads the configuration file and creates the new threads that
113 			can be needed according to the new configuration.
114 		*/
115 		case SERVICE_CONTROL_PAUSE:
116 			update_svc_status(SERVICE_PAUSED, 0);
117 			break;
118 
119 		case SERVICE_CONTROL_CONTINUE:
120 			update_svc_status(SERVICE_RUNNING, 0);
121 			//
122 			// Tell the main loop to re-read the configuration.
123 			//
124 			send_reread_configuration_notification();
125 			break;
126 
127 		case SERVICE_CONTROL_INTERROGATE:
128 			// Fall through to send current status.
129 			//	WARNING: not implemented
130 			update_svc_status(SERVICE_RUNNING, 0);
131 			MessageBox(NULL, "Not implemented", "warning", MB_OK);
132 			break;
133 
134 		case SERVICE_CONTROL_PARAMCHANGE:
135 			//
136 			// Tell the main loop to re-read the configuration.
137 			//
138 			send_reread_configuration_notification();
139 			break;
140 	}
141 
142 	// Send current status.
143 	return;
144 }
145 
svc_main(DWORD argc,char ** argv)146 void WINAPI svc_main(DWORD argc, char **argv)
147 {
148 	service_status_handle = RegisterServiceCtrlHandler(PROGRAM_NAME, svc_control_handler);
149 
150 	if (!service_status_handle)
151 		return;
152 
153 	service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
154 	service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_PARAMCHANGE;
155 	// | SERVICE_ACCEPT_SHUTDOWN ;
156 	update_svc_status(SERVICE_RUNNING, 0);
157 
158 	//
159 	// Service requests until we're told to stop.
160 	//
161 	main_startup();
162 
163 	//
164 	// It returned, so we were told to stop.
165 	//
166 	update_svc_status(SERVICE_STOPPED, 0);
167 }
168 
169 static void
update_svc_status(DWORD state,DWORD progress_indicator)170 update_svc_status(DWORD state, DWORD progress_indicator)
171 {
172 	service_status.dwWin32ExitCode = NO_ERROR;
173 	service_status.dwCurrentState = state;
174 	service_status.dwCheckPoint = progress_indicator;
175 	service_status.dwWaitHint = 0;
176 	SetServiceStatus(service_status_handle, &service_status);
177 }
178 
179 /*
180 sc create rpcapd DisplayName= "Remote Packet Capture Protocol v.0 (experimental)" binpath= "C:\cvsroot\winpcap\wpcap\PRJ\Debug\rpcapd -d -f rpcapd.ini"
181 sc description rpcapd "Allows to capture traffic on this host from a remote machine."
182 */
183