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