Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

# win32-svc.c

Go to the documentation of this file.

    00001 /*
    00002  * Copyright (c) 2002 - 2003
    00003  * NetGroup, Politecnico di Torino (Italy)
    00004  * All rights reserved.
    00005  *
    00006  * Redistribution and use in source and binary forms, with or without
    00007  * modification, are permitted provided that the following conditions
    00008  * are met:
    00009  *
    00010  * 1. Redistributions of source code must retain the above copyright
    00011  * notice, this list of conditions and the following disclaimer.
    00012  * 2. Redistributions in binary form must reproduce the above copyright
    00013  * notice, this list of conditions and the following disclaimer in the
    00014  * documentation and/or other materials provided with the distribution.
    00015  * 3. Neither the name of the Politecnico di Torino nor the names of its
    00016  * contributors may be used to endorse or promote products derived from
    00017  * this software without specific prior written permission.
    00018  *
    00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    00020  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    00022  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    00023  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    00024  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    00025  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    00026  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    00027  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    00028  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    00029  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00030  *
    00031  */
    00032
    00033
    00034 #include "rpcapd.h"
    00035 #include <signal.h>
    00036 #define _WINSOCKAPI_
    00037 #include "windows.h"
    00038 #include <pcap.h>       // for PCAP_ERRBUF_SIZE
    00039 #include "sockutils.h"  // for SOCK_ASSERT
    00040 #include "fileconf.h"
    00041
    00042
    00043 SERVICE_STATUS_HANDLE service_status_handle;
    00044 SERVICE_STATUS service_status;
    00045
    00046
    00047 void svc_geterr(char *str);
    00048 void WINAPI svc_main(DWORD argc, char **argv);
    00049
    00050
    00051
    00052 int svc_start(void)
    00053 {
    00054     int rc;
    00055     SERVICE_TABLE_ENTRY ste[] =
    00056     {
    00057         { PROGRAM_NAME, svc_main },
    00058         { NULL, NULL }
    00059     };
    00060
    00061     // This call is blocking. A new thread is created which will launch
    00062     // the svc_main() function
    00063     if ( (rc = StartServiceCtrlDispatcher(ste)) == 0)
    00064         svc_geterr("StartServiceCtrlDispatcher()");
    00065
    00066     return rc; // FALSE if this is not started as a service
    00067 }
    00068
    00069
    00070 void svc_geterr(char *str)
    00071 {
    00072 char message[PCAP_ERRBUF_SIZE];
    00073 char string[PCAP_ERRBUF_SIZE];
    00074 int val;
    00075
    00076     val= GetLastError();
    00077     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
    00078                   FORMAT_MESSAGE_MAX_WIDTH_MASK,
    00079                   NULL, val, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    00080                   (LPSTR) string, PCAP_ERRBUF_SIZE, NULL);
    00081
    00082     snprintf(message, PCAP_ERRBUF_SIZE, "%s failed with error %d: %s", str, val, string);
    00083
    00084     SOCK_ASSERT(message, 1);
    00085 }
    00086
    00087
    00088
    00089 void WINAPI svc_control_handler(DWORD Opcode)
    00090 {
    00091     service_status.dwWin32ExitCode= 0;
    00092     service_status.dwCheckPoint= 0;
    00093     service_status.dwWaitHint= 0;
    00094
    00095     switch(Opcode)
    00096     {
    00097         case SERVICE_CONTROL_STOP:
    00098             service_status.dwCurrentState= SERVICE_STOPPED;
    00099
    00100             /*
    00101                 Uses ABORT to clean up the service. To be really honest, only the main socket and
    00102                 such these stuffs are cleared; however the thread which are running are not stopped.
    00103                 This can be seen by placing a breakpoint at the end of svc_main(), in which you will
    00104                 see that is never reached. However, as soon as you set the service status to "stopped",
    00105                 the StartServiceCtrlDispatcher() returns and the main thread ends. Then, Win32 has a good
    00106                 authomatic cleanup, so that all the threads which are still running are stopped
    00107                 when the main thread ends.
    00108             */
    00109             raise(SIGABRT);
    00110
    00111             SetServiceStatus(service_status_handle, &service_status);
    00112             break;
    00113
    00114         /*
    00115             Pause and Continue have an usual meaning and they are used just to be able
    00116             to change the running parameters at run-time. In other words, they act
    00117             like the SIGHUP signal on UNIX. All the running threads continue to run and
    00118             they are not paused at all.
    00119             Particularly,
    00120             - PAUSE does nothing
    00121             - CONTINUE re-reads the configuration file and creates the new threads that
    00122             can be needed according to the new configuration.
    00123         */
    00124         case SERVICE_CONTROL_PAUSE:
    00125             service_status.dwCurrentState= SERVICE_PAUSED;
    00126             SetServiceStatus(service_status_handle, &service_status);
    00127             break;
    00128
    00129         case SERVICE_CONTROL_CONTINUE:
    00130             service_status.dwCurrentState= SERVICE_RUNNING;
    00131             SetServiceStatus(service_status_handle, &service_status);
    00132             fileconf_read(0);
    00133             break;
    00134
    00135         case SERVICE_CONTROL_INTERROGATE:
    00136             // Fall through to send current status.
    00137             //  WARNING: not implemented
    00138             SetServiceStatus(service_status_handle, &service_status);
    00139             MessageBox(NULL, "Not implemented", "warning", MB_OK);
    00140             break;
    00141     }
    00142
    00143     // Send current status.
    00144     return;
    00145 }
    00146
    00147
    00148
    00149 void WINAPI svc_main(DWORD argc, char **argv)
    00150 {
    00151     service_status_handle = RegisterServiceCtrlHandler(PROGRAM_NAME, svc_control_handler);
    00152
    00153     if (!service_status_handle)
    00154         return;
    00155
    00156     service_status.dwServiceType= SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
    00157     service_status.dwCurrentState= SERVICE_RUNNING;
    00158     service_status.dwControlsAccepted= SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
    00159     // | SERVICE_ACCEPT_SHUTDOWN ;
    00160     service_status.dwWin32ExitCode= 0;
    00161     service_status.dwServiceSpecificExitCode= 0;
    00162     service_status.dwCheckPoint= 0;
    00163     service_status.dwWaitHint= 0;
    00164
    00165     SetServiceStatus(service_status_handle, &service_status);
    00166
    00167     main_startup();
    00168 }
    00169
    00170 /*
    00171 sc create rpcapd DisplayName= "Remote Packet Capture Protocol v.0 (experimental)" binpath= "C:\cvsroot\winpcap\wpcap\PRJ\Debug\rpcapd -d -f rpcapd.ini"
    00172 sc description rpcapd "Allows to capture traffic on this host from a remote machine."
    00173 */

documentation. Copyright (c) 2002-2003 Politecnico di Torino. All rights reserved.