~ubuntu-branches/ubuntu/lucid/wpasupplicant/lucid-updates

« back to all changes in this revision

Viewing changes to ndis_events.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2006-10-05 08:04:01 UTC
  • mfrom: (1.1.5 upstream) (3 etch)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20061005080401-r8lqlix4390yos7b
Tags: 0.5.5-2
* Update madwifi headers to latest SVN. (Closes: #388316)
* Remove failed attempt at action locking. [debian/functions.sh,
  debian/wpa_action.sh]
* Add hysteresis checking functions, to avoid "event loops" while
  using wpa-roam. [debian/functions.sh, debian/wpa_action.sh]
* Change of co-maintainer email address.
* Add ishex() function to functions.sh to determine wpa-psk value type in
  plaintext or hex. This effectively eliminates the need for the bogus and
  somewhat confusing wpa-passphrase contruct specific to our scripts and
  allows wpa-psk to work with either a 8 to 63 character long plaintext
  string or 64 character long hex string.
* Adjust README.modes to not refer to the redundant wpa-passphrase stuff.
* Add big fat NOTE about acceptable wpa-psk's to top of example gallery.
* Strip surrounding quotes from wpa-ssid if present, instead of just whining
  about them.
* Update email address in copyright blurb of functions.sh, ifupdown.sh and
  wpa_action.sh.  

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * ndis_events - test program for receiving NdisMIndicateStatus() events
3
 
 * Copyright (c) 2004-2006, Jouni Malinen <jkmaline@cc.hut.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
 
 
15
 
#define _WIN32_WINNT    0x0400
16
 
 
17
 
#include <windows.h>
18
 
#include <stdio.h>
19
 
#include <wbemidl.h>
20
 
#include <winsock.h>
21
 
 
22
 
struct ndis_events_data {
23
 
};
24
 
 
25
 
 
26
 
class CNdisSink : public IWbemObjectSink
27
 
{
28
 
public:
29
 
        CNdisSink();
30
 
        ~CNdisSink();
31
 
 
32
 
        // IUnknown members
33
 
        STDMETHODIMP         QueryInterface(REFIID, LPVOID *);
34
 
        STDMETHODIMP_(ULONG) AddRef(void);
35
 
        STDMETHODIMP_(ULONG) Release(void);
36
 
 
37
 
        virtual HRESULT STDMETHODCALLTYPE Indicate(
38
 
                long lObjectCount,
39
 
                IWbemClassObject __RPC_FAR *__RPC_FAR *ppObjArray);
40
 
 
41
 
        virtual HRESULT STDMETHODCALLTYPE SetStatus(
42
 
                long lFlags, HRESULT hResult, BSTR strParam,
43
 
                IWbemClassObject __RPC_FAR *pObjParam);
44
 
 
45
 
#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
46
 
        HANDLE read_pipe, event_avail;
47
 
#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
48
 
 
49
 
private:
50
 
        void media_connect(IWbemClassObject *pObj);
51
 
        void media_disconnect(IWbemClassObject *pObj);
52
 
        void media_specific(IWbemClassObject *pObj);
53
 
        void adapter_arrival(IWbemClassObject *pObj);
54
 
        void adapter_removal(IWbemClassObject *pObj);
55
 
        enum event_types { EVENT_CONNECT, EVENT_DISCONNECT,
56
 
                           EVENT_MEDIA_SPECIFIC, EVENT_ADAPTER_ARRIVAL,
57
 
                           EVENT_ADAPTER_REMOVAL };
58
 
        int send_event(enum event_types type, BSTR instance,
59
 
                       char *data = NULL, size_t data_len = 0);
60
 
 
61
 
        UINT m_cRef;
62
 
 
63
 
#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
64
 
        HANDLE write_pipe;
65
 
#else /* CONFIG_NDIS_EVENTS_INTEGRATED */
66
 
        SOCKET sock;
67
 
        struct sockaddr_in dst;
68
 
#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
69
 
};
70
 
 
71
 
 
72
 
CNdisSink::CNdisSink()
73
 
{
74
 
        m_cRef = 1;
75
 
 
76
 
#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
77
 
        if (!CreatePipe(&read_pipe, &write_pipe, NULL, 512)) {
78
 
                printf("CreatePipe() failed: %d\n", (int) GetLastError());
79
 
                return;
80
 
        }
81
 
        event_avail = CreateEvent(NULL, TRUE, FALSE, NULL);
82
 
        if (event_avail == NULL) {
83
 
                printf("CreateEvent() failed: %d\n", (int) GetLastError());
84
 
                CloseHandle(read_pipe);
85
 
                CloseHandle(write_pipe);
86
 
                return;
87
 
        }
88
 
#else /* CONFIG_NDIS_EVENTS_INTEGRATED */
89
 
        sock = socket(AF_INET, SOCK_DGRAM, 0);
90
 
        if (sock == INVALID_SOCKET) {
91
 
                perror("socket");
92
 
                return;
93
 
        }
94
 
 
95
 
        memset(&dst, 0, sizeof(dst));
96
 
        dst.sin_family = AF_INET;
97
 
        dst.sin_addr.s_addr = inet_addr("127.0.0.1");
98
 
        dst.sin_port = htons(9876);
99
 
#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
100
 
}
101
 
 
102
 
 
103
 
CNdisSink::~CNdisSink()
104
 
{
105
 
#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
106
 
        CloseHandle(read_pipe);
107
 
        CloseHandle(write_pipe);
108
 
        CloseHandle(event_avail);
109
 
#else /* CONFIG_NDIS_EVENTS_INTEGRATED */
110
 
        if (sock != INVALID_SOCKET)
111
 
                closesocket(sock);
112
 
#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
113
 
}
114
 
 
115
 
 
116
 
STDMETHODIMP CNdisSink::QueryInterface(REFIID riid, LPVOID *ppv)
117
 
{
118
 
        *ppv = 0;
119
 
 
120
 
        if (riid == IID_IUnknown || riid == IID_IWbemObjectSink) {
121
 
                *ppv = (IWbemObjectSink *) this;
122
 
                AddRef();
123
 
                return NOERROR;
124
 
        }
125
 
 
126
 
        return E_NOINTERFACE;
127
 
}
128
 
 
129
 
 
130
 
ULONG CNdisSink::AddRef()
131
 
{
132
 
        return ++m_cRef;
133
 
}
134
 
 
135
 
 
136
 
ULONG CNdisSink::Release()
137
 
{
138
 
        if (--m_cRef != 0)
139
 
                return m_cRef;
140
 
 
141
 
        delete this;
142
 
        return 0;
143
 
}
144
 
 
145
 
 
146
 
int CNdisSink::send_event(enum event_types type, BSTR instance,
147
 
                          char *data, size_t data_len)
148
 
{
149
 
        char buf[512], *pos, *end;
150
 
        int len, _type;
151
 
 
152
 
        end = buf + sizeof(buf);
153
 
        _type = (int) type;
154
 
        memcpy(buf, &_type, sizeof(_type));
155
 
        pos = buf + sizeof(_type);
156
 
 
157
 
        len = _snprintf(pos + 1, end - pos - 1, "%S", instance);
158
 
        if (len < 0)
159
 
                return -1;
160
 
        if (len > 255)
161
 
                len = 255;
162
 
        *pos = (unsigned char) len;
163
 
        pos += 1 + len;
164
 
        if (data) {
165
 
                if (data_len > 255 || 1 + data_len > (size_t) (end - pos)) {
166
 
                        printf("Not enough room for send_event data (%d)\n",
167
 
                               data_len);
168
 
                        return -1;
169
 
                }
170
 
                *pos++ = (unsigned char) data_len;
171
 
                memcpy(pos, data, data_len);
172
 
                pos += data_len;
173
 
        }
174
 
 
175
 
#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
176
 
        DWORD written;
177
 
        if (WriteFile(write_pipe, buf, pos - buf, &written, NULL)) {
178
 
                SetEvent(event_avail);
179
 
                return 0;
180
 
        }
181
 
        printf("WriteFile() failed: %d\n", (int) GetLastError());
182
 
        return -1;
183
 
#else /* CONFIG_NDIS_EVENTS_INTEGRATED */
184
 
        return sendto(sock, buf, pos - buf, 0, (struct sockaddr *) &dst,
185
 
                      sizeof(dst));
186
 
#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
187
 
}
188
 
 
189
 
 
190
 
void CNdisSink::media_connect(IWbemClassObject *pObj)
191
 
{
192
 
        VARIANT vt;
193
 
        HRESULT hr;
194
 
        printf("MSNdis_StatusMediaConnect\n");
195
 
        hr = pObj->Get(L"InstanceName", 0, &vt, NULL, NULL);
196
 
        if (SUCCEEDED(hr)) {
197
 
                printf("  InstanceName: '%S'\n", vt.bstrVal);
198
 
                send_event(EVENT_CONNECT, vt.bstrVal);
199
 
                VariantClear(&vt);
200
 
        }
201
 
}
202
 
 
203
 
 
204
 
void CNdisSink::media_disconnect(IWbemClassObject *pObj)
205
 
{
206
 
        VARIANT vt;
207
 
        HRESULT hr;
208
 
        printf("MSNdis_StatusMediaDisconnect\n");
209
 
        hr = pObj->Get(L"InstanceName", 0, &vt, NULL, NULL);
210
 
        if (SUCCEEDED(hr)) {
211
 
                printf("  InstanceName: '%S'\n", vt.bstrVal);
212
 
                send_event(EVENT_DISCONNECT, vt.bstrVal);
213
 
                VariantClear(&vt);
214
 
        }
215
 
}
216
 
 
217
 
 
218
 
void CNdisSink::media_specific(IWbemClassObject *pObj)
219
 
{
220
 
        VARIANT vt;
221
 
        HRESULT hr;
222
 
        LONG lower, upper, k;
223
 
        UCHAR ch;
224
 
        char *data, *pos;
225
 
        size_t data_len;
226
 
 
227
 
        printf("MSNdis_StatusMediaSpecificIndication\n");
228
 
 
229
 
        /* This is the StatusBuffer from NdisMIndicateStatus() call */
230
 
        hr = pObj->Get(L"NdisStatusMediaSpecificIndication", 0, &vt, NULL,
231
 
                       NULL);
232
 
        if (FAILED(hr)) {
233
 
                printf("Could not get NdisStatusMediaSpecificIndication from "
234
 
                       "the object?!\n");
235
 
                return;
236
 
        }
237
 
 
238
 
        SafeArrayGetLBound(V_ARRAY(&vt), 1, &lower);
239
 
        SafeArrayGetUBound(V_ARRAY(&vt), 1, &upper);
240
 
        data_len = upper - lower + 1;
241
 
        data = (char *) malloc(data_len);
242
 
        if (data == NULL) {
243
 
                printf("Failed to allocate buffer for event data\n");
244
 
                VariantClear(&vt);
245
 
                return;
246
 
        }
247
 
 
248
 
        printf("  Data(len=%d):", data_len);
249
 
        pos = data;
250
 
        for (k = lower; k <= upper; k++) {
251
 
                SafeArrayGetElement(V_ARRAY(&vt), &k, &ch);
252
 
                *pos++ = ch;
253
 
                printf(" %02x", ch);
254
 
        }
255
 
        printf("\n");
256
 
 
257
 
        VariantClear(&vt);
258
 
 
259
 
        hr = pObj->Get(L"InstanceName", 0, &vt, NULL, NULL);
260
 
        if (SUCCEEDED(hr)) {
261
 
                printf("  InstanceName: '%S'\n", vt.bstrVal);
262
 
                send_event(EVENT_MEDIA_SPECIFIC, vt.bstrVal, data, data_len);
263
 
                VariantClear(&vt);
264
 
        }
265
 
 
266
 
        free(data);
267
 
}
268
 
 
269
 
 
270
 
void CNdisSink::adapter_arrival(IWbemClassObject *pObj)
271
 
{
272
 
        VARIANT vt;
273
 
        HRESULT hr;
274
 
        printf("MSNdis_NotifyAdapterArrival\n");
275
 
        hr = pObj->Get(L"InstanceName", 0, &vt, NULL, NULL);
276
 
        if (SUCCEEDED(hr)) {
277
 
                printf("  InstanceName: '%S'\n", vt.bstrVal);
278
 
                send_event(EVENT_ADAPTER_ARRIVAL, vt.bstrVal);
279
 
                VariantClear(&vt);
280
 
        }
281
 
}
282
 
 
283
 
 
284
 
void CNdisSink::adapter_removal(IWbemClassObject *pObj)
285
 
{
286
 
        VARIANT vt;
287
 
        HRESULT hr;
288
 
        printf("MSNdis_NotifyAdapterRemoval\n");
289
 
        hr = pObj->Get(L"InstanceName", 0, &vt, NULL, NULL);
290
 
        if (SUCCEEDED(hr)) {
291
 
                printf("  InstanceName: '%S'\n", vt.bstrVal);
292
 
                send_event(EVENT_ADAPTER_REMOVAL, vt.bstrVal);
293
 
                VariantClear(&vt);
294
 
        }
295
 
}
296
 
 
297
 
 
298
 
HRESULT CNdisSink::Indicate(long lObjectCount,
299
 
                            IWbemClassObject __RPC_FAR *__RPC_FAR *ppObjArray)
300
 
{
301
 
        //printf("Notification received - %d object(s)\n", lObjectCount);
302
 
 
303
 
        for (long i = 0; i < lObjectCount; i++) {
304
 
                IWbemClassObject *pObj = ppObjArray[i];
305
 
                HRESULT hr;
306
 
                VARIANT vtClass;
307
 
 
308
 
                hr = pObj->Get(L"__CLASS", 0, &vtClass, NULL, NULL);
309
 
                if (FAILED(hr)) {
310
 
                        printf("Failed to get __CLASS from event.\n");
311
 
                        break;
312
 
                }
313
 
                //printf("CLASS: '%S'\n", vtClass.bstrVal);
314
 
 
315
 
                if (wcscmp(vtClass.bstrVal,
316
 
                           L"MSNdis_StatusMediaSpecificIndication") == 0) {
317
 
                        media_specific(pObj);
318
 
                } else if (wcscmp(vtClass.bstrVal,
319
 
                                  L"MSNdis_StatusMediaConnect") == 0) {
320
 
                        media_connect(pObj);
321
 
                } else if (wcscmp(vtClass.bstrVal,
322
 
                                  L"MSNdis_StatusMediaDisconnect") == 0) {
323
 
                        media_disconnect(pObj);
324
 
                } else if (wcscmp(vtClass.bstrVal,
325
 
                                  L"MSNdis_NotifyAdapterArrival") == 0) {
326
 
                        adapter_arrival(pObj);
327
 
                } else if (wcscmp(vtClass.bstrVal,
328
 
                                  L"MSNdis_NotifyAdapterRemoval") == 0) {
329
 
                        adapter_removal(pObj);
330
 
                } else {
331
 
                        printf("Unepected event - __CLASS: '%S'\n",
332
 
                               vtClass.bstrVal);
333
 
                }
334
 
 
335
 
                VariantClear(&vtClass);
336
 
        }
337
 
 
338
 
        return WBEM_NO_ERROR;
339
 
}
340
 
 
341
 
 
342
 
HRESULT CNdisSink::SetStatus(long lFlags, HRESULT hResult, BSTR strParam,
343
 
                           IWbemClassObject __RPC_FAR *pObjParam)
344
 
{
345
 
        return WBEM_NO_ERROR;
346
 
}
347
 
 
348
 
 
349
 
static int register_async_notification(IWbemObjectSink *pDestSink,
350
 
                                       IWbemServices *pSvc)
351
 
{
352
 
        HRESULT hr;
353
 
        int err = 0;
354
 
        BSTR lang = ::SysAllocString(L"WQL");
355
 
 
356
 
        BSTR query = ::SysAllocString(
357
 
                L"SELECT * FROM MSNdis_StatusMediaConnect");
358
 
        hr = pSvc->ExecNotificationQueryAsync(lang, query, 0, 0, pDestSink);
359
 
        ::SysFreeString(query);
360
 
        if (FAILED(hr)) {
361
 
                printf("ExecNotificationQueryAsync for "
362
 
                       "MSNdis_StatusMediaConnect failed with hresult of "
363
 
                       "0x%x\n", hr);
364
 
                err = -1;
365
 
        }
366
 
 
367
 
        query = ::SysAllocString(
368
 
                L"SELECT * FROM MSNdis_StatusMediaDisconnect");
369
 
        hr = pSvc->ExecNotificationQueryAsync(lang, query, 0, 0, pDestSink);
370
 
        ::SysFreeString(query);
371
 
        if (FAILED(hr)) {
372
 
                printf("ExecNotificationQueryAsync for "
373
 
                       "MSNdis_StatusMediaDisconnect failed with hresult of "
374
 
                       "0x%x\n", hr);
375
 
                err = -1;
376
 
        }
377
 
 
378
 
        query = ::SysAllocString(
379
 
                L"SELECT * FROM MSNdis_StatusMediaSpecificIndication");
380
 
        hr = pSvc->ExecNotificationQueryAsync(lang, query, 0, 0, pDestSink);
381
 
        ::SysFreeString(query);
382
 
        if (FAILED(hr)) {
383
 
                printf("ExecNotificationQueryAsync for "
384
 
                       "MSNdis_StatusMediaSpecificIndication failed with "
385
 
                       "hresult of 0x%x\n", hr);
386
 
                err = -1;
387
 
        }
388
 
 
389
 
        query = ::SysAllocString(
390
 
                L"SELECT * FROM MSNdis_NotifyAdapterArrival");
391
 
        hr = pSvc->ExecNotificationQueryAsync(lang, query, 0, 0, pDestSink);
392
 
        ::SysFreeString(query);
393
 
        if (FAILED(hr)) {
394
 
                printf("ExecNotificationQueryAsync for "
395
 
                       "MSNdis_NotifyAdapterArrival failed with "
396
 
                       "hresult of 0x%x\n", hr);
397
 
                err = -1;
398
 
        }
399
 
 
400
 
        query = ::SysAllocString(
401
 
                L"SELECT * FROM MSNdis_NotifyAdapterRemoval");
402
 
        hr = pSvc->ExecNotificationQueryAsync(lang, query, 0, 0, pDestSink);
403
 
        ::SysFreeString(query);
404
 
        if (FAILED(hr)) {
405
 
                printf("ExecNotificationQueryAsync for "
406
 
                       "MSNdis_NotifyAdapterRemoval failed with "
407
 
                       "hresult of 0x%x\n", hr);
408
 
                err = -1;
409
 
        }
410
 
 
411
 
        ::SysFreeString(lang);
412
 
 
413
 
        return err;
414
 
}
415
 
 
416
 
 
417
 
#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
418
 
extern "C" {
419
 
#endif
420
 
 
421
 
static IWbemServices *pSvc = 0;
422
 
static IWbemLocator *pLoc = NULL;
423
 
static CNdisSink *pSink = NULL;
424
 
 
425
 
void ndis_events_deinit(struct ndis_events_data *events)
426
 
{
427
 
        pSvc->CancelAsyncCall(pSink);
428
 
        pSink->Release();
429
 
        pSvc->Release();
430
 
        pLoc->Release();
431
 
        CoUninitialize();
432
 
}
433
 
 
434
 
 
435
 
#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
436
 
int ndis_events_main(HANDLE *read_pipe, HANDLE *event_avail)
437
 
#else
438
 
int main(int argc, char *argv[])
439
 
#endif
440
 
{
441
 
        HRESULT hr;
442
 
 
443
 
        hr = CoInitializeEx(0, COINIT_MULTITHREADED);
444
 
        if (FAILED(hr)) {
445
 
                printf("CoInitializeEx() failed - returned 0x%x", hr);
446
 
                return -1;
447
 
        }
448
 
 
449
 
        hr = CoInitializeSecurity(NULL, -1, NULL, NULL,
450
 
                                  RPC_C_AUTHN_LEVEL_PKT_PRIVACY,
451
 
                                  RPC_C_IMP_LEVEL_IMPERSONATE,
452
 
                                  NULL, EOAC_SECURE_REFS, NULL);
453
 
        if (FAILED(hr)) {
454
 
                printf("CoInitializeSecurity() failed - returned 0x%x", hr);
455
 
                return -1;
456
 
        }
457
 
 
458
 
        hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER,
459
 
                              IID_IWbemLocator, (LPVOID *) &pLoc);
460
 
        if (FAILED(hr)) {
461
 
                printf("CoCreateInstance() failed - returned 0x%x\n", hr);
462
 
                CoUninitialize();
463
 
                return -1;
464
 
        }
465
 
 
466
 
        hr = pLoc->ConnectServer(L"ROOT\\WMI", NULL, NULL, 0, 0, 0, 0, &pSvc);
467
 
        if (hr) {
468
 
                printf("Could not connect to server - error 0x%x\n", hr);
469
 
                CoUninitialize();
470
 
                return -1;
471
 
        }
472
 
        printf("Connected to ROOT\\WMI.\n");
473
 
 
474
 
#ifndef CONFIG_NDIS_EVENTS_INTEGRATED
475
 
        WSADATA wsaData;
476
 
        if (WSAStartup(MAKEWORD(2, 2), &wsaData)) {
477
 
                printf("Could not find a usable winsock.dll.\n");
478
 
                CoUninitialize();
479
 
                return -1;
480
 
        }
481
 
#endif
482
 
 
483
 
        pSink = new CNdisSink;
484
 
        if (pSink == NULL) {
485
 
                printf("Could not allocate sink for events.\n");
486
 
                CoUninitialize();
487
 
                return -1;
488
 
        }
489
 
 
490
 
        if (register_async_notification(pSink, pSvc) < 0) {
491
 
                printf("Failed to register async notifications\n");
492
 
                CoUninitialize();
493
 
                return -1;
494
 
        }
495
 
 
496
 
#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
497
 
        *read_pipe = pSink->read_pipe;
498
 
        *event_avail = pSink->event_avail;
499
 
#else /* CONFIG_NDIS_EVENTS_INTEGRATED */
500
 
        /* Just wait.. sink will be called with events.. */
501
 
        while (getchar() != '\n');
502
 
 
503
 
        ndis_events_deinit(NULL);
504
 
 
505
 
        WSACleanup();
506
 
#endif /* CONFIG_NDIS_EVENTS_INTEGRATED */
507
 
 
508
 
        return 0;
509
 
}
510
 
 
511
 
#ifdef CONFIG_NDIS_EVENTS_INTEGRATED
512
 
struct ndis_events_data *
513
 
ndis_events_init(HANDLE *read_pipe, HANDLE *event_avail)
514
 
{
515
 
        struct ndis_events_data *events;
516
 
 
517
 
        events = (struct ndis_events_data *) malloc(sizeof(*events));
518
 
        if (events == NULL)
519
 
                return NULL;
520
 
 
521
 
        if (ndis_events_main(read_pipe, event_avail)) {
522
 
                free(events);
523
 
                return NULL;
524
 
        }
525
 
 
526
 
        return events;
527
 
}
528
 
 
529
 
}
530
 
#endif