| /* |
| * Copyright (c) 2002 - 2003 |
| * NetGroup, Politecnico di Torino (Italy) |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * 3. Neither the name of the Politecnico di Torino nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| */ |
| |
| |
| #include "rpcapd.h" |
| #include <pcap.h> // for PCAP_ERRBUF_SIZE |
| #include "fmtutils.h" |
| #include "portability.h" |
| #include "fileconf.h" |
| #include "log.h" |
| |
| #include "win32-svc.h" // for Win32 service stuff |
| |
| static SERVICE_STATUS_HANDLE service_status_handle; |
| static SERVICE_STATUS service_status; |
| |
| static void WINAPI svc_main(DWORD argc, char **argv); |
| static void WINAPI svc_control_handler(DWORD Opcode); |
| static void update_svc_status(DWORD state, DWORD progress_indicator); |
| |
| BOOL svc_start(void) |
| { |
| BOOL rc; |
| SERVICE_TABLE_ENTRY ste[] = |
| { |
| { PROGRAM_NAME, svc_main }, |
| { NULL, NULL } |
| }; |
| char string[PCAP_ERRBUF_SIZE]; |
| |
| // This call is blocking. A new thread is created which will launch |
| // the svc_main() function |
| if ((rc = StartServiceCtrlDispatcher(ste)) == 0) { |
| pcap_fmt_errmsg_for_win32_err(string, sizeof (string), |
| GetLastError(), "StartServiceCtrlDispatcher() failed"); |
| rpcapd_log(LOGPRIO_ERROR, "%s", string); |
| } |
| |
| return rc; // FALSE if this is not started as a service |
| } |
| |
| static void WINAPI |
| svc_control_handler(DWORD Opcode) |
| { |
| switch(Opcode) |
| { |
| case SERVICE_CONTROL_STOP: |
| // |
| // XXX - is this sufficient to clean up the service? |
| // To be really honest, only the main socket and |
| // such these stuffs are cleared; however the threads |
| // that are running are not stopped. |
| // This can be seen by placing a breakpoint at the |
| // end of svc_main(), in which you will see that is |
| // never reached. However, as soon as you set the |
| // service status to "stopped", the |
| // StartServiceCtrlDispatcher() returns and the main |
| // thread ends. Then, Win32 has a good automatic |
| // cleanup, so that all the threads which are still |
| // running are stopped when the main thread ends. |
| // |
| send_shutdown_notification(); |
| |
| update_svc_status(SERVICE_STOP_PENDING, 0); |
| break; |
| |
| /* |
| Pause and Continue have an usual meaning and they are used just to be able |
| to change the running parameters at run-time. In other words, they act |
| like the SIGHUP signal on UNIX. All the running threads continue to run and |
| they are not paused at all. |
| Particularly, |
| - PAUSE does nothing |
| - CONTINUE re-reads the configuration file and creates the new threads that |
| can be needed according to the new configuration. |
| */ |
| case SERVICE_CONTROL_PAUSE: |
| update_svc_status(SERVICE_PAUSED, 0); |
| break; |
| |
| case SERVICE_CONTROL_CONTINUE: |
| update_svc_status(SERVICE_RUNNING, 0); |
| // |
| // Tell the main loop to re-read the configuration. |
| // |
| send_reread_configuration_notification(); |
| break; |
| |
| case SERVICE_CONTROL_INTERROGATE: |
| // Fall through to send current status. |
| // WARNING: not implemented |
| update_svc_status(SERVICE_RUNNING, 0); |
| MessageBox(NULL, "Not implemented", "warning", MB_OK); |
| break; |
| |
| case SERVICE_CONTROL_PARAMCHANGE: |
| // |
| // Tell the main loop to re-read the configuration. |
| // |
| send_reread_configuration_notification(); |
| break; |
| } |
| |
| // Send current status. |
| return; |
| } |
| |
| static void WINAPI |
| svc_main(DWORD argc, char **argv) |
| { |
| service_status_handle = RegisterServiceCtrlHandler(PROGRAM_NAME, svc_control_handler); |
| |
| if (!service_status_handle) |
| return; |
| |
| service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS; |
| service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_PARAMCHANGE; |
| // | SERVICE_ACCEPT_SHUTDOWN ; |
| update_svc_status(SERVICE_RUNNING, 0); |
| |
| // |
| // Service requests until we're told to stop. |
| // |
| main_startup(); |
| |
| // |
| // It returned, so we were told to stop. |
| // |
| update_svc_status(SERVICE_STOPPED, 0); |
| } |
| |
| static void |
| update_svc_status(DWORD state, DWORD progress_indicator) |
| { |
| service_status.dwWin32ExitCode = NO_ERROR; |
| service_status.dwCurrentState = state; |
| service_status.dwCheckPoint = progress_indicator; |
| service_status.dwWaitHint = 0; |
| SetServiceStatus(service_status_handle, &service_status); |
| } |
| |
| /* |
| sc create rpcapd DisplayName= "Remote Packet Capture Protocol v.0 (experimental)" binpath= "C:\cvsroot\winpcap\wpcap\PRJ\Debug\rpcapd -d -f rpcapd.ini" |
| sc description rpcapd "Allows to capture traffic on this host from a remote machine." |
| */ |