main_winsvc.c
Go to the documentation of this file.
00001 /*
00002  * WPA Supplicant / main() function for Win32 service
00003  * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
00008  *
00009  * Alternatively, this software may be distributed under the terms of BSD
00010  * license.
00011  *
00012  * See README and COPYING for more details.
00013  *
00014  * The root of wpa_supplicant configuration in registry is
00015  * HKEY_LOCAL_MACHINE\\SOFTWARE\\%wpa_supplicant. This level includes global
00016  * parameters and a 'interfaces' subkey with all the interface configuration
00017  * (adapter to confname mapping). Each such mapping is a subkey that has
00018  * 'adapter' and 'config' values.
00019  *
00020  * This program can be run either as a normal command line application, e.g.,
00021  * for debugging, with 'wpasvc.exe app' or as a Windows service. Service need
00022  * to be registered with 'wpasvc.exe reg <full path to wpasvc.exe>'. After
00023  * this, it can be started like any other Windows service (e.g., 'net start
00024  * wpasvc') or it can be configured to start automatically through the Services
00025  * tool in administrative tasks. The service can be unregistered with
00026  * 'wpasvc.exe unreg'.
00027  */
00028 
00029 #include "includes.h"
00030 #include <windows.h>
00031 
00032 #include "common.h"
00033 #include "wpa_supplicant_i.h"
00034 #include "eloop.h"
00035 
00036 #ifndef WPASVC_NAME
00037 #define WPASVC_NAME TEXT("wpasvc")
00038 #endif
00039 #ifndef WPASVC_DISPLAY_NAME
00040 #define WPASVC_DISPLAY_NAME TEXT("wpa_supplicant service")
00041 #endif
00042 #ifndef WPASVC_DESCRIPTION
00043 #define WPASVC_DESCRIPTION \
00044 TEXT("Provides IEEE 802.1X and WPA/WPA2 supplicant functionality")
00045 #endif
00046 
00047 static HANDLE kill_svc;
00048 
00049 static SERVICE_STATUS_HANDLE svc_status_handle;
00050 static SERVICE_STATUS svc_status;
00051 
00052 
00053 #ifndef WPA_KEY_ROOT
00054 #define WPA_KEY_ROOT HKEY_LOCAL_MACHINE
00055 #endif
00056 #ifndef WPA_KEY_PREFIX
00057 #define WPA_KEY_PREFIX TEXT("SOFTWARE\\wpa_supplicant")
00058 #endif
00059 
00060 #ifdef UNICODE
00061 #define TSTR "%S"
00062 #else /* UNICODE */
00063 #define TSTR "%s"
00064 #endif /* UNICODE */
00065 
00066 
00067 static int read_interface(struct wpa_global *global, HKEY _hk,
00068                           const TCHAR *name)
00069 {
00070         HKEY hk;
00071 #define TBUFLEN 255
00072         TCHAR adapter[TBUFLEN], config[TBUFLEN], ctrl_interface[TBUFLEN];
00073         DWORD buflen, val;
00074         LONG ret;
00075         struct wpa_interface iface;
00076         int skip_on_error = 0;
00077 
00078         ret = RegOpenKeyEx(_hk, name, 0, KEY_QUERY_VALUE, &hk);
00079         if (ret != ERROR_SUCCESS) {
00080                 printf("Could not open wpa_supplicant interface key\n");
00081                 return -1;
00082         }
00083 
00084         os_memset(&iface, 0, sizeof(iface));
00085         iface.driver = "ndis";
00086 
00087         buflen = sizeof(ctrl_interface);
00088         ret = RegQueryValueEx(hk, TEXT("ctrl_interface"), NULL, NULL,
00089                               (LPBYTE) ctrl_interface, &buflen);
00090         if (ret == ERROR_SUCCESS) {
00091                 ctrl_interface[TBUFLEN - 1] = TEXT('\0');
00092                 wpa_unicode2ascii_inplace(ctrl_interface);
00093                 printf("ctrl_interface[len=%d] '%s'\n",
00094                        (int) buflen, (char *) ctrl_interface);
00095                 iface.ctrl_interface = (char *) ctrl_interface;
00096         }
00097 
00098         buflen = sizeof(adapter);
00099         ret = RegQueryValueEx(hk, TEXT("adapter"), NULL, NULL,
00100                               (LPBYTE) adapter, &buflen);
00101         if (ret == ERROR_SUCCESS) {
00102                 adapter[TBUFLEN - 1] = TEXT('\0');
00103                 wpa_unicode2ascii_inplace(adapter);
00104                 printf("adapter[len=%d] '%s'\n",
00105                        (int) buflen, (char *) adapter);
00106                 iface.ifname = (char *) adapter;
00107         }
00108 
00109         buflen = sizeof(config);
00110         ret = RegQueryValueEx(hk, TEXT("config"), NULL, NULL,
00111                               (LPBYTE) config, &buflen);
00112         if (ret == ERROR_SUCCESS) {
00113                 config[sizeof(config) - 1] = '\0';
00114                 wpa_unicode2ascii_inplace(config);
00115                 printf("config[len=%d] '%s'\n",
00116                        (int) buflen, (char *) config);
00117                 iface.confname = (char *) config;
00118         }
00119 
00120         buflen = sizeof(val);
00121         ret = RegQueryValueEx(hk, TEXT("skip_on_error"), NULL, NULL,
00122                               (LPBYTE) &val, &buflen);
00123         if (ret == ERROR_SUCCESS && buflen == sizeof(val))
00124                 skip_on_error = val;
00125 
00126         RegCloseKey(hk);
00127 
00128         if (wpa_supplicant_add_iface(global, &iface) == NULL) {
00129                 if (skip_on_error)
00130                         wpa_printf(MSG_DEBUG, "Skipped interface '%s' due to "
00131                                    "initialization failure", iface.ifname);
00132                 else
00133                         return -1;
00134         }
00135 
00136         return 0;
00137 }
00138 
00139 
00140 static int wpa_supplicant_thread(void)
00141 {
00142         int exitcode;
00143         struct wpa_params params;
00144         struct wpa_global *global;
00145         HKEY hk, ihk;
00146         DWORD val, buflen, i;
00147         LONG ret;
00148 
00149         if (os_program_init())
00150                 return -1;
00151 
00152         os_memset(&params, 0, sizeof(params));
00153         params.wpa_debug_level = MSG_INFO;
00154 
00155         ret = RegOpenKeyEx(WPA_KEY_ROOT, WPA_KEY_PREFIX,
00156                            0, KEY_QUERY_VALUE, &hk);
00157         if (ret != ERROR_SUCCESS) {
00158                 printf("Could not open wpa_supplicant registry key\n");
00159                 return -1;
00160         }
00161 
00162         buflen = sizeof(val);
00163         ret = RegQueryValueEx(hk, TEXT("debug_level"), NULL, NULL,
00164                               (LPBYTE) &val, &buflen);
00165         if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
00166                 params.wpa_debug_level = val;
00167         }
00168 
00169         buflen = sizeof(val);
00170         ret = RegQueryValueEx(hk, TEXT("debug_show_keys"), NULL, NULL,
00171                               (LPBYTE) &val, &buflen);
00172         if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
00173                 params.wpa_debug_show_keys = val;
00174         }
00175 
00176         buflen = sizeof(val);
00177         ret = RegQueryValueEx(hk, TEXT("debug_timestamp"), NULL, NULL,
00178                               (LPBYTE) &val, &buflen);
00179         if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
00180                 params.wpa_debug_timestamp = val;
00181         }
00182 
00183         buflen = sizeof(val);
00184         ret = RegQueryValueEx(hk, TEXT("debug_use_file"), NULL, NULL,
00185                               (LPBYTE) &val, &buflen);
00186         if (ret == ERROR_SUCCESS && buflen == sizeof(val) && val) {
00187                 params.wpa_debug_file_path = "\\Temp\\wpa_supplicant-log.txt";
00188         }
00189 
00190         exitcode = 0;
00191         global = wpa_supplicant_init(&params);
00192         if (global == NULL) {
00193                 printf("Failed to initialize wpa_supplicant\n");
00194                 exitcode = -1;
00195         }
00196 
00197         ret = RegOpenKeyEx(hk, TEXT("interfaces"), 0, KEY_ENUMERATE_SUB_KEYS,
00198                            &ihk);
00199         RegCloseKey(hk);
00200         if (ret != ERROR_SUCCESS) {
00201                 printf("Could not open wpa_supplicant interfaces registry "
00202                        "key\n");
00203                 return -1;
00204         }
00205 
00206         for (i = 0; ; i++) {
00207                 TCHAR name[255];
00208                 DWORD namelen;
00209 
00210                 namelen = 255;
00211                 ret = RegEnumKeyEx(ihk, i, name, &namelen, NULL, NULL, NULL,
00212                                    NULL);
00213 
00214                 if (ret == ERROR_NO_MORE_ITEMS)
00215                         break;
00216 
00217                 if (ret != ERROR_SUCCESS) {
00218                         printf("RegEnumKeyEx failed: 0x%x\n",
00219                                (unsigned int) ret);
00220                         break;
00221                 }
00222 
00223                 if (namelen >= 255)
00224                         namelen = 255 - 1;
00225                 name[namelen] = '\0';
00226 
00227                 wpa_printf(MSG_DEBUG, "interface %d: %s\n", (int) i, name);
00228                 if (read_interface(global, ihk, name) < 0)
00229                         exitcode = -1;
00230         }
00231 
00232         RegCloseKey(ihk);
00233 
00234         if (exitcode == 0)
00235                 exitcode = wpa_supplicant_run(global);
00236 
00237         wpa_supplicant_deinit(global);
00238 
00239         os_program_deinit();
00240 
00241         return exitcode;
00242 }
00243 
00244 
00245 static DWORD svc_thread(LPDWORD param)
00246 {
00247         int ret = wpa_supplicant_thread();
00248 
00249         svc_status.dwCurrentState = SERVICE_STOPPED;
00250         svc_status.dwWaitHint = 0;
00251         if (!SetServiceStatus(svc_status_handle, &svc_status)) {
00252                 printf("SetServiceStatus() failed: %d\n",
00253                        (int) GetLastError());
00254         }
00255 
00256         return ret;
00257 }
00258 
00259 
00260 static int register_service(const TCHAR *exe)
00261 {
00262         SC_HANDLE svc, scm;
00263         SERVICE_DESCRIPTION sd;
00264 
00265         printf("Registering service: " TSTR "\n", WPASVC_NAME);
00266 
00267         scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
00268         if (!scm) {
00269                 printf("OpenSCManager failed: %d\n", (int) GetLastError());
00270                 return -1;
00271         }
00272 
00273         svc = CreateService(scm, WPASVC_NAME, WPASVC_DISPLAY_NAME,
00274                             SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
00275                             SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
00276                             exe, NULL, NULL, NULL, NULL, NULL);
00277 
00278         if (!svc) {
00279                 printf("CreateService failed: %d\n\n", (int) GetLastError());
00280                 CloseServiceHandle(scm);
00281                 return -1;
00282         }
00283 
00284         os_memset(&sd, 0, sizeof(sd));
00285         sd.lpDescription = WPASVC_DESCRIPTION;
00286         if (!ChangeServiceConfig2(svc, SERVICE_CONFIG_DESCRIPTION, &sd)) {
00287                 printf("ChangeServiceConfig2 failed: %d\n",
00288                        (int) GetLastError());
00289                 /* This is not a fatal error, so continue anyway. */
00290         }
00291 
00292         CloseServiceHandle(svc);
00293         CloseServiceHandle(scm);
00294 
00295         printf("Service registered successfully.\n");
00296 
00297         return 0;
00298 }
00299 
00300 
00301 static int unregister_service(void)
00302 {
00303         SC_HANDLE svc, scm;
00304         SERVICE_STATUS status;
00305 
00306         printf("Unregistering service: " TSTR "\n", WPASVC_NAME);
00307 
00308         scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
00309         if (!scm) {
00310                 printf("OpenSCManager failed: %d\n", (int) GetLastError());
00311                 return -1;
00312         }
00313 
00314         svc = OpenService(scm, WPASVC_NAME, SERVICE_ALL_ACCESS | DELETE);
00315         if (!svc) {
00316                 printf("OpenService failed: %d\n\n", (int) GetLastError());
00317                 CloseServiceHandle(scm);
00318                 return -1;
00319         }
00320 
00321         if (QueryServiceStatus(svc, &status)) {
00322                 if (status.dwCurrentState != SERVICE_STOPPED) {
00323                         printf("Service currently active - stopping "
00324                                "service...\n");
00325                         if (!ControlService(svc, SERVICE_CONTROL_STOP,
00326                                             &status)) {
00327                                 printf("ControlService failed: %d\n",
00328                                        (int) GetLastError());
00329                         }
00330                         Sleep(500);
00331                 }
00332         }
00333 
00334         if (DeleteService(svc)) {
00335                 printf("Service unregistered successfully.\n");
00336         } else {
00337                 printf("DeleteService failed: %d\n", (int) GetLastError());
00338         }
00339 
00340         CloseServiceHandle(svc);
00341         CloseServiceHandle(scm);
00342 
00343         return 0;
00344 }
00345 
00346 
00347 static void WINAPI service_ctrl_handler(DWORD control_code)
00348 {
00349         switch (control_code) {
00350         case SERVICE_CONTROL_INTERROGATE:
00351                 break;
00352         case SERVICE_CONTROL_SHUTDOWN:
00353         case SERVICE_CONTROL_STOP:
00354                 svc_status.dwCurrentState = SERVICE_STOP_PENDING;
00355                 svc_status.dwWaitHint = 2000;
00356                 eloop_terminate();
00357                 SetEvent(kill_svc);
00358                 break;
00359         }
00360 
00361         if (!SetServiceStatus(svc_status_handle, &svc_status)) {
00362                 printf("SetServiceStatus() failed: %d\n",
00363                        (int) GetLastError());
00364         }
00365 }
00366 
00367 
00368 static void WINAPI service_start(DWORD argc, LPTSTR *argv)
00369 {
00370         DWORD id;
00371 
00372         svc_status_handle = RegisterServiceCtrlHandler(WPASVC_NAME,
00373                                                        service_ctrl_handler);
00374         if (svc_status_handle == (SERVICE_STATUS_HANDLE) 0) {
00375                 printf("RegisterServiceCtrlHandler failed: %d\n",
00376                        (int) GetLastError());
00377                 return;
00378         }
00379 
00380         os_memset(&svc_status, 0, sizeof(svc_status));
00381         svc_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
00382         svc_status.dwCurrentState = SERVICE_START_PENDING;
00383         svc_status.dwWaitHint = 1000;
00384 
00385         if (!SetServiceStatus(svc_status_handle, &svc_status)) {
00386                 printf("SetServiceStatus() failed: %d\n",
00387                        (int) GetLastError());
00388                 return;
00389         }
00390 
00391         kill_svc = CreateEvent(0, TRUE, FALSE, 0);
00392         if (!kill_svc) {
00393                 printf("CreateEvent failed: %d\n", (int) GetLastError());
00394                 return;
00395         }
00396 
00397         if (CreateThread(0, 0, (LPTHREAD_START_ROUTINE) svc_thread, 0, 0, &id)
00398             == 0) {
00399                 printf("CreateThread failed: %d\n", (int) GetLastError());
00400                 return;
00401         }
00402 
00403         if (svc_status.dwCurrentState == SERVICE_START_PENDING) {
00404                 svc_status.dwCurrentState = SERVICE_RUNNING;
00405                 svc_status.dwWaitHint = 0;
00406                 svc_status.dwControlsAccepted = SERVICE_ACCEPT_STOP |
00407                         SERVICE_ACCEPT_SHUTDOWN;
00408         }
00409 
00410         if (!SetServiceStatus(svc_status_handle, &svc_status)) {
00411                 printf("SetServiceStatus() failed: %d\n",
00412                        (int) GetLastError());
00413                 return;
00414         }
00415 
00416         /* wait until service gets killed */
00417         WaitForSingleObject(kill_svc, INFINITE);
00418 }
00419 
00420 
00421 int main(int argc, char *argv[])
00422 {
00423         SERVICE_TABLE_ENTRY dt[] = {
00424                 { WPASVC_NAME, service_start },
00425                 { NULL, NULL }
00426         };
00427 
00428         if (argc > 1) {
00429                 if (os_strcmp(argv[1], "reg") == 0) {
00430                         TCHAR *path;
00431                         int ret;
00432 
00433                         if (argc < 3) {
00434                                 path = os_malloc(MAX_PATH * sizeof(TCHAR));
00435                                 if (path == NULL)
00436                                         return -1;
00437                                 if (!GetModuleFileName(NULL, path, MAX_PATH)) {
00438                                         printf("GetModuleFileName failed: "
00439                                                "%d\n", (int) GetLastError());
00440                                         os_free(path);
00441                                         return -1;
00442                                 }
00443                         } else {
00444                                 path = wpa_strdup_tchar(argv[2]);
00445                                 if (path == NULL)
00446                                         return -1;
00447                         }
00448                         ret = register_service(path);
00449                         os_free(path);
00450                         return ret;
00451                 } else if (os_strcmp(argv[1], "unreg") == 0) {
00452                         return unregister_service();
00453                 } else if (os_strcmp(argv[1], "app") == 0) {
00454                         return wpa_supplicant_thread();
00455                 }
00456         }
00457 
00458         if (!StartServiceCtrlDispatcher(dt)) {
00459                 printf("StartServiceCtrlDispatcher failed: %d\n",
00460                        (int) GetLastError());
00461         }
00462 
00463         return 0;
00464 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:26:38