~ubuntu-branches/ubuntu/gutsy/wpasupplicant/gutsy

« back to all changes in this revision

Viewing changes to wpa_supplicant/main_winsvc.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * WPA Supplicant / main() function for Win32 service
3
 
 * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
4
 
 *
5
 
 * This program is free software; you can redistribute it and/or modify
6
 
 * it under the terms of the GNU General Public License version 2 as
7
 
 * published by the Free Software Foundation.
8
 
 *
9
 
 * Alternatively, this software may be distributed under the terms of BSD
10
 
 * license.
11
 
 *
12
 
 * See README and COPYING for more details.
13
 
 *
14
 
 * The root of wpa_supplicant configuration in registry is
15
 
 * HKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant. This level includes global
16
 
 * parameters and a 'interfaces' subkey with all the interface configuration
17
 
 * (adapter to confname mapping). Each such mapping is a subkey that has
18
 
 * 'adapter' and 'config' values.
19
 
 *
20
 
 * This program can be run either as a normal command line application, e.g.,
21
 
 * for debugging, with 'wpasvc.exe app' or as a Windows service. Service need
22
 
 * to be registered with 'wpasvc.exe reg <full path to wpasvc.exe>'. After
23
 
 * this, it can be started like any other Windows service (e.g., 'net start
24
 
 * wpasvc') or it can be configured to start automatically through the Services
25
 
 * tool in administrative tasks. The service can be unregistered with
26
 
 * 'wpasvc.exe unreg'.
27
 
 */
28
 
 
29
 
#include "includes.h"
30
 
#include <windows.h>
31
 
 
32
 
#include "common.h"
33
 
#include "wpa_supplicant_i.h"
34
 
#include "eloop.h"
35
 
 
36
 
#ifndef WPASVC_NAME
37
 
#define WPASVC_NAME TEXT("wpasvc")
38
 
#endif
39
 
#ifndef WPASVC_DISPLAY_NAME
40
 
#define WPASVC_DISPLAY_NAME TEXT("wpa_supplicant service")
41
 
#endif
42
 
#ifndef WPASVC_DESCRIPTION
43
 
#define WPASVC_DESCRIPTION \
44
 
TEXT("Provides IEEE 802.1X and WPA/WPA2 supplicant functionality")
45
 
#endif
46
 
 
47
 
static HANDLE kill_svc;
48
 
 
49
 
static SERVICE_STATUS_HANDLE svc_status_handle;
50
 
static SERVICE_STATUS svc_status;
51
 
 
52
 
 
53
 
#ifndef WPA_KEY_ROOT
54
 
#define WPA_KEY_ROOT HKEY_LOCAL_MACHINE
55
 
#endif
56
 
#ifndef WPA_KEY_PREFIX
57
 
#define WPA_KEY_PREFIX TEXT("SOFTWARE\\wpa_supplicant")
58
 
#endif
59
 
 
60
 
#ifdef UNICODE
61
 
#define TSTR "%S"
62
 
#else /* UNICODE */
63
 
#define TSTR "%s"
64
 
#endif /* UNICODE */
65
 
 
66
 
 
67
 
static int read_interface(struct wpa_global *global, HKEY _hk,
68
 
                          const TCHAR *name)
69
 
{
70
 
        HKEY hk;
71
 
#define TBUFLEN 255
72
 
        TCHAR adapter[TBUFLEN], config[TBUFLEN], ctrl_interface[TBUFLEN];
73
 
        DWORD buflen;
74
 
        LONG ret;
75
 
        struct wpa_interface iface;
76
 
 
77
 
        ret = RegOpenKeyEx(_hk, name, 0, KEY_QUERY_VALUE, &hk);
78
 
        if (ret != ERROR_SUCCESS) {
79
 
                printf("Could not open wpa_supplicant interface key\n");
80
 
                return -1;
81
 
        }
82
 
 
83
 
        os_memset(&iface, 0, sizeof(iface));
84
 
        iface.driver = "ndis";
85
 
 
86
 
        buflen = sizeof(ctrl_interface);
87
 
        ret = RegQueryValueEx(hk, TEXT("ctrl_interface"), NULL, NULL,
88
 
                              (LPBYTE) ctrl_interface, &buflen);
89
 
        if (ret == ERROR_SUCCESS) {
90
 
                ctrl_interface[TBUFLEN - 1] = TEXT('\0');
91
 
                wpa_unicode2ascii_inplace(ctrl_interface);
92
 
                printf("ctrl_interface[len=%d] '%s'\n",
93
 
                       (int) buflen, (char *) ctrl_interface);
94
 
                iface.ctrl_interface = (char *) ctrl_interface;
95
 
        }
96
 
 
97
 
        buflen = sizeof(adapter);
98
 
        ret = RegQueryValueEx(hk, TEXT("adapter"), NULL, NULL,
99
 
                              (LPBYTE) adapter, &buflen);
100
 
        if (ret == ERROR_SUCCESS) {
101
 
                adapter[TBUFLEN - 1] = TEXT('\0');
102
 
                wpa_unicode2ascii_inplace(adapter);
103
 
                printf("adapter[len=%d] '%s'\n",
104
 
                       (int) buflen, (char *) adapter);
105
 
                iface.ifname = (char *) adapter;
106
 
        }
107
 
 
108
 
        buflen = sizeof(config);
109
 
        ret = RegQueryValueEx(hk, TEXT("config"), NULL, NULL,
110
 
                              (LPBYTE) config, &buflen);
111
 
        if (ret == ERROR_SUCCESS) {
112
 
                config[sizeof(config) - 1] = '\0';
113
 
                wpa_unicode2ascii_inplace(config);
114
 
                printf("config[len=%d] '%s'\n",
115
 
                       (int) buflen, (char *) config);
116
 
                iface.confname = (char *) config;
117
 
        }
118
 
 
119
 
        RegCloseKey(hk);
120
 
 
121
 
        if (wpa_supplicant_add_iface(global, &iface) == NULL)
122
 
                return -1;
123
 
 
124
 
        return 0;
125
 
}
126
 
 
127
 
 
128
 
static int wpa_supplicant_thread(void)
129
 
{
130
 
        int exitcode;
131
 
        struct wpa_params params;
132
 
        struct wpa_global *global;
133
 
        HKEY hk, ihk;
134
 
        DWORD val, buflen, i;
135
 
        LONG ret;
136
 
 
137
 
        if (os_program_init())
138
 
                return -1;
139
 
 
140
 
        os_memset(&params, 0, sizeof(params));
141
 
        params.wpa_debug_level = MSG_INFO;
142
 
 
143
 
        ret = RegOpenKeyEx(WPA_KEY_ROOT, WPA_KEY_PREFIX,
144
 
                           0, KEY_QUERY_VALUE, &hk);
145
 
        if (ret != ERROR_SUCCESS) {
146
 
                printf("Could not open wpa_supplicant registry key\n");
147
 
                return -1;
148
 
        }
149
 
 
150
 
        buflen = sizeof(val);
151
 
        ret = RegQueryValueEx(hk, TEXT("debug_level"), NULL, NULL,
152
 
                              (LPBYTE) &val, &buflen);
153
 
        if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
154
 
                params.wpa_debug_level = val;
155
 
        }
156
 
 
157
 
        buflen = sizeof(val);
158
 
        ret = RegQueryValueEx(hk, TEXT("debug_show_keys"), NULL, NULL,
159
 
                              (LPBYTE) &val, &buflen);
160
 
        if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
161
 
                params.wpa_debug_show_keys = val;
162
 
        }
163
 
 
164
 
        buflen = sizeof(val);
165
 
        ret = RegQueryValueEx(hk, TEXT("debug_use_file"), NULL, NULL,
166
 
                              (LPBYTE) &val, &buflen);
167
 
        if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
168
 
                params.wpa_debug_use_file = val;
169
 
        }
170
 
 
171
 
        exitcode = 0;
172
 
        global = wpa_supplicant_init(&params);
173
 
        if (global == NULL) {
174
 
                printf("Failed to initialize wpa_supplicant\n");
175
 
                exitcode = -1;
176
 
        }
177
 
 
178
 
        ret = RegOpenKeyEx(hk, TEXT("interfaces"), 0, KEY_ENUMERATE_SUB_KEYS,
179
 
                           &ihk);
180
 
        RegCloseKey(hk);
181
 
        if (ret != ERROR_SUCCESS) {
182
 
                printf("Could not open wpa_supplicant interfaces registry "
183
 
                       "key\n");
184
 
                return -1;
185
 
        }
186
 
 
187
 
        for (i = 0; ; i++) {
188
 
                TCHAR name[255];
189
 
                DWORD namelen;
190
 
 
191
 
                namelen = 255;
192
 
                ret = RegEnumKeyEx(ihk, i, name, &namelen, NULL, NULL, NULL,
193
 
                                   NULL);
194
 
 
195
 
                if (ret == ERROR_NO_MORE_ITEMS)
196
 
                        break;
197
 
 
198
 
                if (ret != ERROR_SUCCESS) {
199
 
                        printf("RegEnumKeyEx failed: 0x%x\n",
200
 
                               (unsigned int) ret);
201
 
                        break;
202
 
                }
203
 
 
204
 
                if (namelen >= 255)
205
 
                        namelen = 255 - 1;
206
 
                name[namelen] = '\0';
207
 
 
208
 
                wpa_printf(MSG_DEBUG, "interface %d: %s\n", (int) i, name);
209
 
                if (read_interface(global, ihk, name) < 0)
210
 
                        exitcode = -1;
211
 
        }
212
 
 
213
 
        RegCloseKey(ihk);
214
 
 
215
 
        if (exitcode == 0)
216
 
                exitcode = wpa_supplicant_run(global);
217
 
 
218
 
        wpa_supplicant_deinit(global);
219
 
 
220
 
        os_program_deinit();
221
 
 
222
 
        return exitcode;
223
 
}
224
 
 
225
 
 
226
 
static DWORD svc_thread(LPDWORD param)
227
 
{
228
 
        int ret = wpa_supplicant_thread();
229
 
 
230
 
        svc_status.dwCurrentState = SERVICE_STOPPED;
231
 
        svc_status.dwWaitHint = 0;
232
 
        if (!SetServiceStatus(svc_status_handle, &svc_status)) {
233
 
                printf("SetServiceStatus() failed: %d\n",
234
 
                       (int) GetLastError());
235
 
        }
236
 
 
237
 
        return ret;
238
 
}
239
 
 
240
 
 
241
 
static int register_service(const TCHAR *exe)
242
 
{
243
 
        SC_HANDLE svc, scm;
244
 
        SERVICE_DESCRIPTION sd;
245
 
 
246
 
        printf("Registering service: " TSTR "\n", WPASVC_NAME);
247
 
 
248
 
        scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
249
 
        if (!scm) {
250
 
                printf("OpenSCManager failed: %d\n", (int) GetLastError());
251
 
                return -1;
252
 
        }
253
 
 
254
 
        svc = CreateService(scm, WPASVC_NAME, WPASVC_DISPLAY_NAME,
255
 
                            SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
256
 
                            SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
257
 
                            exe, NULL, NULL, NULL, NULL, NULL);
258
 
 
259
 
        if (!svc) {
260
 
                printf("CreateService failed: %d\n\n", (int) GetLastError());
261
 
                CloseServiceHandle(scm);
262
 
                return -1;
263
 
        }
264
 
 
265
 
        os_memset(&sd, 0, sizeof(sd));
266
 
        sd.lpDescription = WPASVC_DESCRIPTION;
267
 
        if (!ChangeServiceConfig2(svc, SERVICE_CONFIG_DESCRIPTION, &sd)) {
268
 
                printf("ChangeServiceConfig2 failed: %d\n",
269
 
                       (int) GetLastError());
270
 
                /* This is not a fatal error, so continue anyway. */
271
 
        }
272
 
 
273
 
        CloseServiceHandle(svc);
274
 
        CloseServiceHandle(scm);
275
 
 
276
 
        printf("Service registered successfully.\n");
277
 
 
278
 
        return 0;
279
 
}
280
 
 
281
 
 
282
 
static int unregister_service(void)
283
 
{
284
 
        SC_HANDLE svc, scm;
285
 
        SERVICE_STATUS status;
286
 
 
287
 
        printf("Unregistering service: " TSTR "\n", WPASVC_NAME);
288
 
 
289
 
        scm = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
290
 
        if (!scm) {
291
 
                printf("OpenSCManager failed: %d\n", (int) GetLastError());
292
 
                return -1;
293
 
        }
294
 
 
295
 
        svc = OpenService(scm, WPASVC_NAME, SERVICE_ALL_ACCESS | DELETE);
296
 
        if (!svc) {
297
 
                printf("OpenService failed: %d\n\n", (int) GetLastError());
298
 
                CloseServiceHandle(scm);
299
 
                return -1;
300
 
        }
301
 
 
302
 
        if (QueryServiceStatus(svc, &status)) {
303
 
                if (status.dwCurrentState != SERVICE_STOPPED) {
304
 
                        printf("Service currently active - stopping "
305
 
                               "service...\n");
306
 
                        if (!ControlService(svc, SERVICE_CONTROL_STOP,
307
 
                                            &status)) {
308
 
                                printf("ControlService failed: %d\n",
309
 
                                       (int) GetLastError());
310
 
                        }
311
 
                        Sleep(500);
312
 
                }
313
 
        }
314
 
 
315
 
        if (DeleteService(svc)) {
316
 
                printf("Service unregistered successfully.\n");
317
 
        } else {
318
 
                printf("DeleteService failed: %d\n", (int) GetLastError());
319
 
        }
320
 
 
321
 
        CloseServiceHandle(svc);
322
 
        CloseServiceHandle(scm);
323
 
 
324
 
        return 0;
325
 
}
326
 
 
327
 
 
328
 
static void WINAPI service_ctrl_handler(DWORD control_code)
329
 
{
330
 
        switch (control_code) {
331
 
        case SERVICE_CONTROL_INTERROGATE:
332
 
                break;
333
 
        case SERVICE_CONTROL_SHUTDOWN:
334
 
        case SERVICE_CONTROL_STOP:
335
 
                svc_status.dwCurrentState = SERVICE_STOP_PENDING;
336
 
                svc_status.dwWaitHint = 2000;
337
 
                eloop_terminate();
338
 
                SetEvent(kill_svc);
339
 
                break;
340
 
        }
341
 
 
342
 
        if (!SetServiceStatus(svc_status_handle, &svc_status)) {
343
 
                printf("SetServiceStatus() failed: %d\n",
344
 
                       (int) GetLastError());
345
 
        }
346
 
}
347
 
 
348
 
 
349
 
static void WINAPI service_start(DWORD argc, LPTSTR *argv)
350
 
{
351
 
        DWORD id;
352
 
 
353
 
        svc_status_handle = RegisterServiceCtrlHandler(WPASVC_NAME,
354
 
                                                       service_ctrl_handler);
355
 
        if (svc_status_handle == (SERVICE_STATUS_HANDLE) 0) {
356
 
                printf("RegisterServiceCtrlHandler failed: %d\n",
357
 
                       (int) GetLastError());
358
 
                return;
359
 
        }
360
 
 
361
 
        os_memset(&svc_status, 0, sizeof(svc_status));
362
 
        svc_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
363
 
        svc_status.dwCurrentState = SERVICE_START_PENDING;
364
 
        svc_status.dwWaitHint = 1000;
365
 
 
366
 
        if (!SetServiceStatus(svc_status_handle, &svc_status)) {
367
 
                printf("SetServiceStatus() failed: %d\n",
368
 
                       (int) GetLastError());
369
 
                return;
370
 
        }
371
 
 
372
 
        kill_svc = CreateEvent(0, TRUE, FALSE, 0);
373
 
        if (!kill_svc) {
374
 
                printf("CreateEvent failed: %d\n", (int) GetLastError());
375
 
                return;
376
 
        }
377
 
 
378
 
        if (CreateThread(0, 0, (LPTHREAD_START_ROUTINE) svc_thread, 0, 0, &id)
379
 
            == 0) {
380
 
                printf("CreateThread failed: %d\n", (int) GetLastError());
381
 
                return;
382
 
        }
383
 
 
384
 
        if (svc_status.dwCurrentState == SERVICE_START_PENDING) {
385
 
                svc_status.dwCurrentState = SERVICE_RUNNING;
386
 
                svc_status.dwWaitHint = 0;
387
 
                svc_status.dwControlsAccepted = SERVICE_ACCEPT_STOP |
388
 
                        SERVICE_ACCEPT_SHUTDOWN;
389
 
        }
390
 
 
391
 
        if (!SetServiceStatus(svc_status_handle, &svc_status)) {
392
 
                printf("SetServiceStatus() failed: %d\n",
393
 
                       (int) GetLastError());
394
 
                return;
395
 
        }
396
 
 
397
 
        /* wait until service gets killed */
398
 
        WaitForSingleObject(kill_svc, INFINITE);
399
 
}
400
 
 
401
 
 
402
 
int main(int argc, char *argv[])
403
 
{
404
 
        SERVICE_TABLE_ENTRY dt[] = {
405
 
                { WPASVC_NAME, service_start },
406
 
                { NULL, NULL }
407
 
        };
408
 
 
409
 
        if (argc > 1) {
410
 
                if (os_strcmp(argv[1], "reg") == 0) {
411
 
                        TCHAR *path;
412
 
                        int ret;
413
 
 
414
 
                        if (argc < 3) {
415
 
                                path = os_malloc(MAX_PATH * sizeof(TCHAR));
416
 
                                if (path == NULL)
417
 
                                        return -1;
418
 
                                if (!GetModuleFileName(NULL, path, MAX_PATH)) {
419
 
                                        printf("GetModuleFileName failed: "
420
 
                                               "%d\n", (int) GetLastError());
421
 
                                        os_free(path);
422
 
                                        return -1;
423
 
                                }
424
 
                        } else {
425
 
                                path = wpa_strdup_tchar(argv[2]);
426
 
                                if (path == NULL)
427
 
                                        return -1;
428
 
                        }
429
 
                        ret = register_service(path);
430
 
                        os_free(path);
431
 
                        return ret;
432
 
                } else if (os_strcmp(argv[1], "unreg") == 0) {
433
 
                        return unregister_service();
434
 
                } else if (os_strcmp(argv[1], "app") == 0) {
435
 
                        return wpa_supplicant_thread();
436
 
                }
437
 
        }
438
 
 
439
 
        if (!StartServiceCtrlDispatcher(dt)) {
440
 
                printf("StartServiceCtrlDispatcher failed: %d\n",
441
 
                       (int) GetLastError());
442
 
        }
443
 
 
444
 
        return 0;
445
 
}