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

« back to all changes in this revision

Viewing changes to src/common/wpa_ctrl.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/hostapd control interface library
3
 
 * Copyright (c) 2004-2007, 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
 
 
15
 
#include "includes.h"
16
 
 
17
 
#ifdef CONFIG_CTRL_IFACE
18
 
 
19
 
#ifdef CONFIG_CTRL_IFACE_UNIX
20
 
#include <sys/un.h>
21
 
#endif /* CONFIG_CTRL_IFACE_UNIX */
22
 
 
23
 
#include "wpa_ctrl.h"
24
 
#include "common.h"
25
 
 
26
 
 
27
 
#if defined(CONFIG_CTRL_IFACE_UNIX) || defined(CONFIG_CTRL_IFACE_UDP)
28
 
#define CTRL_IFACE_SOCKET
29
 
#endif /* CONFIG_CTRL_IFACE_UNIX || CONFIG_CTRL_IFACE_UDP */
30
 
 
31
 
 
32
 
/**
33
 
 * struct wpa_ctrl - Internal structure for control interface library
34
 
 *
35
 
 * This structure is used by the wpa_supplicant/hostapd control interface
36
 
 * library to store internal data. Programs using the library should not touch
37
 
 * this data directly. They can only use the pointer to the data structure as
38
 
 * an identifier for the control interface connection and use this as one of
39
 
 * the arguments for most of the control interface library functions.
40
 
 */
41
 
struct wpa_ctrl {
42
 
#ifdef CONFIG_CTRL_IFACE_UDP
43
 
        int s;
44
 
        struct sockaddr_in local;
45
 
        struct sockaddr_in dest;
46
 
        char *cookie;
47
 
#endif /* CONFIG_CTRL_IFACE_UDP */
48
 
#ifdef CONFIG_CTRL_IFACE_UNIX
49
 
        int s;
50
 
        struct sockaddr_un local;
51
 
        struct sockaddr_un dest;
52
 
#endif /* CONFIG_CTRL_IFACE_UNIX */
53
 
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
54
 
        HANDLE pipe;
55
 
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
56
 
};
57
 
 
58
 
 
59
 
#ifdef CONFIG_CTRL_IFACE_UNIX
60
 
 
61
 
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
62
 
{
63
 
        struct wpa_ctrl *ctrl;
64
 
        static int counter = 0;
65
 
        int ret;
66
 
        size_t res;
67
 
 
68
 
        ctrl = os_malloc(sizeof(*ctrl));
69
 
        if (ctrl == NULL)
70
 
                return NULL;
71
 
        os_memset(ctrl, 0, sizeof(*ctrl));
72
 
 
73
 
        ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
74
 
        if (ctrl->s < 0) {
75
 
                os_free(ctrl);
76
 
                return NULL;
77
 
        }
78
 
 
79
 
        ctrl->local.sun_family = AF_UNIX;
80
 
        ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
81
 
                          "/tmp/wpa_ctrl_%d-%d", getpid(), counter++);
82
 
        if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
83
 
                close(ctrl->s);
84
 
                os_free(ctrl);
85
 
                return NULL;
86
 
        }
87
 
        if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
88
 
                    sizeof(ctrl->local)) < 0) {
89
 
                close(ctrl->s);
90
 
                os_free(ctrl);
91
 
                return NULL;
92
 
        }
93
 
 
94
 
        ctrl->dest.sun_family = AF_UNIX;
95
 
        res = os_strlcpy(ctrl->dest.sun_path, ctrl_path,
96
 
                         sizeof(ctrl->dest.sun_path));
97
 
        if (res >= sizeof(ctrl->dest.sun_path)) {
98
 
                close(ctrl->s);
99
 
                os_free(ctrl);
100
 
                return NULL;
101
 
        }
102
 
        if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
103
 
                    sizeof(ctrl->dest)) < 0) {
104
 
                close(ctrl->s);
105
 
                unlink(ctrl->local.sun_path);
106
 
                os_free(ctrl);
107
 
                return NULL;
108
 
        }
109
 
 
110
 
        return ctrl;
111
 
}
112
 
 
113
 
 
114
 
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
115
 
{
116
 
        unlink(ctrl->local.sun_path);
117
 
        close(ctrl->s);
118
 
        os_free(ctrl);
119
 
}
120
 
 
121
 
#endif /* CONFIG_CTRL_IFACE_UNIX */
122
 
 
123
 
 
124
 
#ifdef CONFIG_CTRL_IFACE_UDP
125
 
 
126
 
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
127
 
{
128
 
        struct wpa_ctrl *ctrl;
129
 
        char buf[128];
130
 
        size_t len;
131
 
 
132
 
        ctrl = os_malloc(sizeof(*ctrl));
133
 
        if (ctrl == NULL)
134
 
                return NULL;
135
 
        os_memset(ctrl, 0, sizeof(*ctrl));
136
 
 
137
 
        ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
138
 
        if (ctrl->s < 0) {
139
 
                perror("socket");
140
 
                os_free(ctrl);
141
 
                return NULL;
142
 
        }
143
 
 
144
 
        ctrl->local.sin_family = AF_INET;
145
 
        ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
146
 
        if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
147
 
                 sizeof(ctrl->local)) < 0) {
148
 
                close(ctrl->s);
149
 
                os_free(ctrl);
150
 
                return NULL;
151
 
        }
152
 
 
153
 
        ctrl->dest.sin_family = AF_INET;
154
 
        ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
155
 
        ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
156
 
        if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
157
 
                    sizeof(ctrl->dest)) < 0) {
158
 
                perror("connect");
159
 
                close(ctrl->s);
160
 
                os_free(ctrl);
161
 
                return NULL;
162
 
        }
163
 
 
164
 
        len = sizeof(buf) - 1;
165
 
        if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) {
166
 
                buf[len] = '\0';
167
 
                ctrl->cookie = os_strdup(buf);
168
 
        }
169
 
 
170
 
        return ctrl;
171
 
}
172
 
 
173
 
 
174
 
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
175
 
{
176
 
        close(ctrl->s);
177
 
        os_free(ctrl->cookie);
178
 
        os_free(ctrl);
179
 
}
180
 
 
181
 
#endif /* CONFIG_CTRL_IFACE_UDP */
182
 
 
183
 
 
184
 
#ifdef CTRL_IFACE_SOCKET
185
 
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
186
 
                     char *reply, size_t *reply_len,
187
 
                     void (*msg_cb)(char *msg, size_t len))
188
 
{
189
 
        struct timeval tv;
190
 
        int res;
191
 
        fd_set rfds;
192
 
        const char *_cmd;
193
 
        char *cmd_buf = NULL;
194
 
        size_t _cmd_len;
195
 
 
196
 
#ifdef CONFIG_CTRL_IFACE_UDP
197
 
        if (ctrl->cookie) {
198
 
                char *pos;
199
 
                _cmd_len = os_strlen(ctrl->cookie) + 1 + cmd_len;
200
 
                cmd_buf = os_malloc(_cmd_len);
201
 
                if (cmd_buf == NULL)
202
 
                        return -1;
203
 
                _cmd = cmd_buf;
204
 
                pos = cmd_buf;
205
 
                os_strlcpy(pos, ctrl->cookie, _cmd_len);
206
 
                pos += os_strlen(ctrl->cookie);
207
 
                *pos++ = ' ';
208
 
                os_memcpy(pos, cmd, cmd_len);
209
 
        } else
210
 
#endif /* CONFIG_CTRL_IFACE_UDP */
211
 
        {
212
 
                _cmd = cmd;
213
 
                _cmd_len = cmd_len;
214
 
        }
215
 
 
216
 
        if (send(ctrl->s, _cmd, _cmd_len, 0) < 0) {
217
 
                os_free(cmd_buf);
218
 
                return -1;
219
 
        }
220
 
        os_free(cmd_buf);
221
 
 
222
 
        for (;;) {
223
 
                tv.tv_sec = 2;
224
 
                tv.tv_usec = 0;
225
 
                FD_ZERO(&rfds);
226
 
                FD_SET(ctrl->s, &rfds);
227
 
                res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
228
 
                if (FD_ISSET(ctrl->s, &rfds)) {
229
 
                        res = recv(ctrl->s, reply, *reply_len, 0);
230
 
                        if (res < 0)
231
 
                                return res;
232
 
                        if (res > 0 && reply[0] == '<') {
233
 
                                /* This is an unsolicited message from
234
 
                                 * wpa_supplicant, not the reply to the
235
 
                                 * request. Use msg_cb to report this to the
236
 
                                 * caller. */
237
 
                                if (msg_cb) {
238
 
                                        /* Make sure the message is nul
239
 
                                         * terminated. */
240
 
                                        if ((size_t) res == *reply_len)
241
 
                                                res = (*reply_len) - 1;
242
 
                                        reply[res] = '\0';
243
 
                                        msg_cb(reply, res);
244
 
                                }
245
 
                                continue;
246
 
                        }
247
 
                        *reply_len = res;
248
 
                        break;
249
 
                } else {
250
 
                        return -2;
251
 
                }
252
 
        }
253
 
        return 0;
254
 
}
255
 
#endif /* CTRL_IFACE_SOCKET */
256
 
 
257
 
 
258
 
static int wpa_ctrl_attach_helper(struct wpa_ctrl *ctrl, int attach)
259
 
{
260
 
        char buf[10];
261
 
        int ret;
262
 
        size_t len = 10;
263
 
 
264
 
        ret = wpa_ctrl_request(ctrl, attach ? "ATTACH" : "DETACH", 6,
265
 
                               buf, &len, NULL);
266
 
        if (ret < 0)
267
 
                return ret;
268
 
        if (len == 3 && os_memcmp(buf, "OK\n", 3) == 0)
269
 
                return 0;
270
 
        return -1;
271
 
}
272
 
 
273
 
 
274
 
int wpa_ctrl_attach(struct wpa_ctrl *ctrl)
275
 
{
276
 
        return wpa_ctrl_attach_helper(ctrl, 1);
277
 
}
278
 
 
279
 
 
280
 
int wpa_ctrl_detach(struct wpa_ctrl *ctrl)
281
 
{
282
 
        return wpa_ctrl_attach_helper(ctrl, 0);
283
 
}
284
 
 
285
 
 
286
 
#ifdef CTRL_IFACE_SOCKET
287
 
 
288
 
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
289
 
{
290
 
        int res;
291
 
 
292
 
        res = recv(ctrl->s, reply, *reply_len, 0);
293
 
        if (res < 0)
294
 
                return res;
295
 
        *reply_len = res;
296
 
        return 0;
297
 
}
298
 
 
299
 
 
300
 
int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
301
 
{
302
 
        struct timeval tv;
303
 
        fd_set rfds;
304
 
        tv.tv_sec = 0;
305
 
        tv.tv_usec = 0;
306
 
        FD_ZERO(&rfds);
307
 
        FD_SET(ctrl->s, &rfds);
308
 
        select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
309
 
        return FD_ISSET(ctrl->s, &rfds);
310
 
}
311
 
 
312
 
 
313
 
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
314
 
{
315
 
        return ctrl->s;
316
 
}
317
 
 
318
 
#endif /* CTRL_IFACE_SOCKET */
319
 
 
320
 
 
321
 
#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
322
 
 
323
 
#ifndef WPA_SUPPLICANT_NAMED_PIPE
324
 
#define WPA_SUPPLICANT_NAMED_PIPE "WpaSupplicant"
325
 
#endif
326
 
#define NAMED_PIPE_PREFIX TEXT("\\\\.\\pipe\\") TEXT(WPA_SUPPLICANT_NAMED_PIPE)
327
 
 
328
 
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
329
 
{
330
 
        struct wpa_ctrl *ctrl;
331
 
        DWORD mode;
332
 
        TCHAR name[256];
333
 
        int i, ret;
334
 
 
335
 
        ctrl = os_malloc(sizeof(*ctrl));
336
 
        if (ctrl == NULL)
337
 
                return NULL;
338
 
        os_memset(ctrl, 0, sizeof(*ctrl));
339
 
 
340
 
#ifdef UNICODE
341
 
        if (ctrl_path == NULL)
342
 
                ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX);
343
 
        else
344
 
                ret = _snwprintf(name, 256, NAMED_PIPE_PREFIX TEXT("-%S"),
345
 
                                 ctrl_path);
346
 
#else /* UNICODE */
347
 
        if (ctrl_path == NULL)
348
 
                ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX);
349
 
        else
350
 
                ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
351
 
                                  ctrl_path);
352
 
#endif /* UNICODE */
353
 
        if (ret < 0 || ret >= 256) {
354
 
                os_free(ctrl);
355
 
                return NULL;
356
 
        }
357
 
 
358
 
        for (i = 0; i < 10; i++) {
359
 
                ctrl->pipe = CreateFile(name, GENERIC_READ | GENERIC_WRITE, 0,
360
 
                                        NULL, OPEN_EXISTING, 0, NULL);
361
 
                /*
362
 
                 * Current named pipe server side in wpa_supplicant is
363
 
                 * re-opening the pipe for new clients only after the previous
364
 
                 * one is taken into use. This leaves a small window for race
365
 
                 * conditions when two connections are being opened at almost
366
 
                 * the same time. Retry if that was the case.
367
 
                 */
368
 
                if (ctrl->pipe != INVALID_HANDLE_VALUE ||
369
 
                    GetLastError() != ERROR_PIPE_BUSY)
370
 
                        break;
371
 
                WaitNamedPipe(name, 1000);
372
 
        }
373
 
        if (ctrl->pipe == INVALID_HANDLE_VALUE) {
374
 
                os_free(ctrl);
375
 
                return NULL;
376
 
        }
377
 
 
378
 
        mode = PIPE_READMODE_MESSAGE;
379
 
        if (!SetNamedPipeHandleState(ctrl->pipe, &mode, NULL, NULL)) {
380
 
                CloseHandle(ctrl->pipe);
381
 
                os_free(ctrl);
382
 
                return NULL;
383
 
        }
384
 
 
385
 
        return ctrl;
386
 
}
387
 
 
388
 
 
389
 
void wpa_ctrl_close(struct wpa_ctrl *ctrl)
390
 
{
391
 
        CloseHandle(ctrl->pipe);
392
 
        os_free(ctrl);
393
 
}
394
 
 
395
 
 
396
 
int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len,
397
 
                     char *reply, size_t *reply_len,
398
 
                     void (*msg_cb)(char *msg, size_t len))
399
 
{
400
 
        DWORD written;
401
 
        DWORD readlen = *reply_len;
402
 
 
403
 
        if (!WriteFile(ctrl->pipe, cmd, cmd_len, &written, NULL))
404
 
                return -1;
405
 
 
406
 
        if (!ReadFile(ctrl->pipe, reply, *reply_len, &readlen, NULL))
407
 
                return -1;
408
 
        *reply_len = readlen;
409
 
 
410
 
        return 0;
411
 
}
412
 
 
413
 
 
414
 
int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len)
415
 
{
416
 
        DWORD len = *reply_len;
417
 
        if (!ReadFile(ctrl->pipe, reply, *reply_len, &len, NULL))
418
 
                return -1;
419
 
        *reply_len = len;
420
 
        return 0;
421
 
}
422
 
 
423
 
 
424
 
int wpa_ctrl_pending(struct wpa_ctrl *ctrl)
425
 
{
426
 
        DWORD left;
427
 
 
428
 
        if (!PeekNamedPipe(ctrl->pipe, NULL, 0, NULL, &left, NULL))
429
 
                return -1;
430
 
        return left ? 1 : 0;
431
 
}
432
 
 
433
 
 
434
 
int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl)
435
 
{
436
 
        return -1;
437
 
}
438
 
 
439
 
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
440
 
 
441
 
#endif /* CONFIG_CTRL_IFACE */