~ubuntu-branches/ubuntu/vivid/wpasupplicant/vivid

« back to all changes in this revision

Viewing changes to wpa_ctrl.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2008-03-12 20:03:04 UTC
  • mfrom: (1.1.10 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080312200304-4331y9wj46pdd34z
Tags: 0.6.3-1
* New upstream release.
* Drop patches applied upstream:
  - debian/patches/30_wpa_gui_qt4_eventhistoryui_rework.patch
  - debian/patches/31_wpa_gui_qt4_eventhistory_always_scrollbar.patch
  - debian/patches/32_wpa_gui_qt4_eventhistory_scroll_with_events.patch
  - debian/patches/40_dbus_ssid_data.patch
* Tidy up the clean target of debian/rules. Now that the madwifi headers are
  handled differently we no longer need to do any cleanup.
* Fix formatting error in debian/ifupdown/wpa_action.8 to make lintian
  quieter.
* Add patch to fix formatting errors in manpages build from sgml source. Use
  <emphasis> tags to hightlight keywords instead of surrounding them in
  strong quotes.
  - debian/patches/41_manpage_format_fixes.patch
* wpasupplicant binary package no longer suggests pcscd, guessnet, iproute
  or wireless-tools, nor does it recommend dhcp3-client. These are not
  needed.
* Add debian/patches/10_silence_siocsiwauth_icotl_failure.patch to disable
  ioctl failure messages that occur under normal conditions.
* Cherry pick two upstream git commits concerning the dbus interface:
  - debian/patches/11_avoid_dbus_version_namespace.patch
  - debian/patches/12_fix_potential_use_after_free.patch
* Add debian/patches/42_manpage_explain_available_drivers.patch to explain
  that not all of the driver backends are available in the provided
  wpa_supplicant binary, and that the canonical list of supported driver
  backends can be retrieved from the wpa_supplicant -h (help) output.
  (Closes: #466910)
* Add debian/patches/20_wpa_gui_qt4_disable_link_prl.patch to remove
  link_prl CONFIG compile flag added by qmake-qt4 >= 4.3.4-2 to avoid excess
  linking.

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