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 41*6f9cba8fSJoseph Mingrone #include "win32-svc.h" // for Win32 service stuff 42*6f9cba8fSJoseph 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); 47*6f9cba8fSJoseph Mingrone static void WINAPI svc_control_handler(DWORD Opcode); 4857e22627SCy Schubert static void update_svc_status(DWORD state, DWORD progress_indicator); 4957e22627SCy Schubert 50*6f9cba8fSJoseph Mingrone BOOL svc_start(void) 5157e22627SCy Schubert { 52*6f9cba8fSJoseph 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) { 6357e22627SCy Schubert pcap_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 71*6f9cba8fSJoseph Mingrone static void WINAPI 72*6f9cba8fSJoseph 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 137*6f9cba8fSJoseph Mingrone static void WINAPI 138*6f9cba8fSJoseph 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 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