~ubuntu-branches/ubuntu/precise/wpasupplicant/precise-security

« back to all changes in this revision

Viewing changes to ctrl_iface.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2006-10-05 08:04:01 UTC
  • mfrom: (1.2.1 upstream) (2.1.14 edgy)
  • Revision ID: james.westby@ubuntu.com-20061005080401-myfwjtq7di70dyeo
* 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
1
/*
2
 
 * WPA Supplicant / UNIX domain socket -based control interface
3
 
 * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
 
2
 * WPA Supplicant / Control interface (shared code for all backends)
 
3
 * Copyright (c) 2004-2006, Jouni Malinen <jkmaline@cc.hut.fi>
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or modify
6
6
 * it under the terms of the GNU General Public License version 2 as
12
12
 * See README and COPYING for more details.
13
13
 */
14
14
 
15
 
#include <stdlib.h>
16
 
#include <stdio.h>
17
 
#include <string.h>
18
 
#include <unistd.h>
19
 
#include <sys/types.h>
20
 
#include <sys/stat.h>
21
 
#include <errno.h>
22
 
#ifndef CONFIG_NATIVE_WINDOWS
23
 
#include <sys/socket.h>
24
 
#include <sys/un.h>
25
 
#include <sys/uio.h>
26
 
#endif /* CONFIG_NATIVE_WINDOWS */
 
15
#include "includes.h"
27
16
 
28
17
#include "common.h"
29
18
#include "eloop.h"
34
23
#include "wpa_supplicant_i.h"
35
24
#include "ctrl_iface.h"
36
25
#include "l2_packet.h"
37
 
 
38
 
 
39
 
#ifdef CONFIG_NATIVE_WINDOWS
40
 
typedef int socklen_t;
41
 
#endif /* CONFIG_NATIVE_WINDOWS */
42
 
 
43
 
#ifdef CONFIG_CTRL_IFACE_UDP
44
 
#define CTRL_IFACE_SOCK struct sockaddr_in
45
 
#else /* CONFIG_CTRL_IFACE_UDP */
46
 
#define CTRL_IFACE_SOCK struct sockaddr_un
47
 
#endif /* CONFIG_CTRL_IFACE_UDP */
48
 
 
49
 
 
50
 
struct wpa_ctrl_dst {
51
 
        struct wpa_ctrl_dst *next;
52
 
        CTRL_IFACE_SOCK addr;
53
 
        socklen_t addrlen;
54
 
        int debug_level;
55
 
        int errors;
56
 
};
57
 
 
58
 
 
59
 
static const char * wpa_state_txt(int state)
60
 
{
61
 
        switch (state) {
62
 
        case WPA_DISCONNECTED:
63
 
                return "DISCONNECTED";
64
 
        case WPA_SCANNING:
65
 
                return "SCANNING";
66
 
        case WPA_ASSOCIATING:
67
 
                return "ASSOCIATING";
68
 
        case WPA_ASSOCIATED:
69
 
                return "ASSOCIATED";
70
 
        case WPA_4WAY_HANDSHAKE:
71
 
                return "4WAY_HANDSHAKE";
72
 
        case WPA_GROUP_HANDSHAKE:
73
 
                return "GROUP_HANDSHAKE";
74
 
        case WPA_COMPLETED:
75
 
                return "COMPLETED";
76
 
        default:
77
 
                return "UNKNOWN";
78
 
        }
79
 
}
 
26
#include "preauth.h"
 
27
#include "pmksa_cache.h"
 
28
#include "wpa_ctrl.h"
 
29
#include "eap.h"
 
30
 
 
31
 
 
32
static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
 
33
                                                  char *buf, int len);
80
34
 
81
35
 
82
36
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
83
37
                                         char *cmd)
84
38
{
85
39
        char *value;
 
40
        int ret = 0;
86
41
 
87
42
        value = strchr(cmd, ' ');
88
43
        if (value == NULL)
102
57
        } else if (strcasecmp(cmd, "EAPOL::maxStart") == 0) {
103
58
                eapol_sm_configure(wpa_s->eapol,
104
59
                                   -1, -1, -1, atoi(value));
 
60
        } else if (strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
 
61
                if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
 
62
                                     atoi(value)))
 
63
                        ret = -1;
 
64
        } else if (strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 0) {
 
65
                if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
 
66
                                     atoi(value)))
 
67
                        ret = -1;
 
68
        } else if (strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
 
69
                if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
 
70
                        ret = -1;
105
71
        } else
106
 
                return -1;
107
 
        return 0;
 
72
                ret = -1;
 
73
 
 
74
        return ret;
108
75
}
109
76
 
110
77
 
120
87
        }
121
88
 
122
89
        wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
123
 
        rsn_preauth_deinit(wpa_s);
124
 
        if (rsn_preauth_init(wpa_s, bssid))
125
 
                return -1;
126
 
 
127
 
        return 0;
128
 
}
129
 
 
130
 
 
131
 
static int wpa_supplicant_ctrl_iface_attach(struct wpa_supplicant *wpa_s,
132
 
                                            CTRL_IFACE_SOCK *from,
133
 
                                            socklen_t fromlen)
134
 
{
135
 
        struct wpa_ctrl_dst *dst;
136
 
 
137
 
        dst = malloc(sizeof(*dst));
138
 
        if (dst == NULL)
139
 
                return -1;
140
 
        memset(dst, 0, sizeof(*dst));
141
 
        memcpy(&dst->addr, from, sizeof(CTRL_IFACE_SOCK));
142
 
        dst->addrlen = fromlen;
143
 
        dst->debug_level = MSG_INFO;
144
 
        dst->next = wpa_s->ctrl_dst;
145
 
        wpa_s->ctrl_dst = dst;
146
 
#ifdef CONFIG_CTRL_IFACE_UDP
147
 
        wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
148
 
                   inet_ntoa(from->sin_addr), ntohs(from->sin_port));
149
 
#else /* CONFIG_CTRL_IFACE_UDP */
150
 
        wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
151
 
                    (u8 *) from->sun_path, fromlen);
152
 
#endif /* CONFIG_CTRL_IFACE_UDP */
153
 
        return 0;
154
 
}
155
 
 
156
 
 
157
 
static int wpa_supplicant_ctrl_iface_detach(struct wpa_supplicant *wpa_s,
158
 
                                            CTRL_IFACE_SOCK *from,
159
 
                                            socklen_t fromlen)
160
 
{
161
 
        struct wpa_ctrl_dst *dst, *prev = NULL;
162
 
 
163
 
        dst = wpa_s->ctrl_dst;
164
 
        while (dst) {
165
 
#ifdef CONFIG_CTRL_IFACE_UDP
166
 
                if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
167
 
                    from->sin_port == dst->addr.sin_port) {
168
 
                        if (prev == NULL)
169
 
                                wpa_s->ctrl_dst = dst->next;
170
 
                        else
171
 
                                prev->next = dst->next;
172
 
                        free(dst);
173
 
                        wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached "
174
 
                                   "%s:%d", inet_ntoa(from->sin_addr),
175
 
                                   ntohs(from->sin_port));
176
 
                        return 0;
177
 
                }
178
 
#else /* CONFIG_CTRL_IFACE_UDP */
179
 
                if (fromlen == dst->addrlen &&
180
 
                    memcmp(from->sun_path, dst->addr.sun_path, fromlen) == 0) {
181
 
                        if (prev == NULL)
182
 
                                wpa_s->ctrl_dst = dst->next;
183
 
                        else
184
 
                                prev->next = dst->next;
185
 
                        free(dst);
186
 
                        wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
187
 
                                    (u8 *) from->sun_path, fromlen);
188
 
                        return 0;
189
 
                }
190
 
#endif /* CONFIG_CTRL_IFACE_UDP */
191
 
                prev = dst;
192
 
                dst = dst->next;
193
 
        }
194
 
        return -1;
195
 
}
196
 
 
197
 
 
198
 
static int wpa_supplicant_ctrl_iface_level(struct wpa_supplicant *wpa_s,
199
 
                                           CTRL_IFACE_SOCK *from,
200
 
                                           socklen_t fromlen,
201
 
                                           char *level)
202
 
{
203
 
        struct wpa_ctrl_dst *dst;
204
 
 
205
 
        wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
206
 
 
207
 
        dst = wpa_s->ctrl_dst;
208
 
        while (dst) {
209
 
#ifdef CONFIG_CTRL_IFACE_UDP
210
 
                if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
211
 
                    from->sin_port == dst->addr.sin_port) {
212
 
                        wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor "
213
 
                                   "level %s:%d", inet_ntoa(from->sin_addr),
214
 
                                   ntohs(from->sin_port));
215
 
                        dst->debug_level = atoi(level);
216
 
                        return 0;
217
 
                }
218
 
#else /* CONFIG_CTRL_IFACE_UDP */
219
 
                if (fromlen == dst->addrlen &&
220
 
                    memcmp(from->sun_path, dst->addr.sun_path, fromlen) == 0) {
221
 
                        wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
222
 
                                    "level", (u8 *) from->sun_path, fromlen);
223
 
                        dst->debug_level = atoi(level);
224
 
                        return 0;
225
 
                }
226
 
#endif /* CONFIG_CTRL_IFACE_UDP */
227
 
                dst = dst->next;
228
 
        }
229
 
 
230
 
        return -1;
231
 
}
 
90
        rsn_preauth_deinit(wpa_s->wpa);
 
91
        if (rsn_preauth_init(wpa_s->wpa, bssid, wpa_s->current_ssid))
 
92
                return -1;
 
93
 
 
94
        return 0;
 
95
}
 
96
 
 
97
 
 
98
#ifdef CONFIG_STAKEY
 
99
static int wpa_supplicant_ctrl_iface_stakey_request(
 
100
        struct wpa_supplicant *wpa_s, char *addr)
 
101
{
 
102
        u8 peer[ETH_ALEN];
 
103
 
 
104
        if (hwaddr_aton(addr, peer)) {
 
105
                wpa_printf(MSG_DEBUG, "CTRL_IFACE STAKEY-REQUEST: invalid "
 
106
                           "address '%s'", peer);
 
107
                return -1;
 
108
        }
 
109
 
 
110
        wpa_printf(MSG_DEBUG, "CTRL_IFACE STAKEY-REQUEST " MACSTR,
 
111
                   MAC2STR(peer));
 
112
 
 
113
        return wpa_sm_stakey_request(wpa_s->wpa, peer);
 
114
}
 
115
#endif /* CONFIG_STAKEY */
 
116
 
 
117
 
 
118
#ifdef CONFIG_PEERKEY
 
119
/* MLME-STKSTART.request(peer) */
 
120
static int wpa_supplicant_ctrl_iface_stkstart(
 
121
        struct wpa_supplicant *wpa_s, char *addr)
 
122
{
 
123
        u8 peer[ETH_ALEN];
 
124
 
 
125
        if (hwaddr_aton(addr, peer)) {
 
126
                wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART: invalid "
 
127
                           "address '%s'", peer);
 
128
                return -1;
 
129
        }
 
130
 
 
131
        wpa_printf(MSG_DEBUG, "CTRL_IFACE STKSTART " MACSTR,
 
132
                   MAC2STR(peer));
 
133
 
 
134
        return wpa_sm_stkstart(wpa_s->wpa, peer);
 
135
}
 
136
#endif /* CONFIG_PEERKEY */
232
137
 
233
138
 
234
139
static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
235
140
                                              char *rsp)
236
141
{
 
142
#ifdef IEEE8021X_EAPOL
237
143
        char *pos, *id_pos;
238
144
        int id;
239
145
        struct wpa_ssid *ssid;
248
154
                return -1;
249
155
        *pos++ = '\0';
250
156
        id = atoi(id_pos);
251
 
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d value='%s'",
252
 
                   rsp, id, pos);
253
 
 
254
 
        ssid = wpa_s->conf->ssid;
255
 
        while (ssid) {
256
 
                if (id == ssid->id)
257
 
                        break;
258
 
                ssid = ssid->next;
259
 
        }
260
 
 
 
157
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
 
158
        wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
 
159
                              (u8 *) pos, strlen(pos));
 
160
 
 
161
        ssid = wpa_config_get_network(wpa_s->conf, id);
261
162
        if (ssid == NULL) {
262
163
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
263
164
                           "to update", id);
278
179
                ssid->pending_req_password = 0;
279
180
                if (ssid == wpa_s->current_ssid)
280
181
                        wpa_s->reassociate = 1;
 
182
        } else if (strcmp(rsp, "NEW_PASSWORD") == 0) {
 
183
                free(ssid->new_password);
 
184
                ssid->new_password = (u8 *) strdup(pos);
 
185
                ssid->new_password_len = strlen(pos);
 
186
                ssid->pending_req_new_password = 0;
 
187
                if (ssid == wpa_s->current_ssid)
 
188
                        wpa_s->reassociate = 1;
 
189
        } else if (strcmp(rsp, "PIN") == 0) {
 
190
                free(ssid->pin);
 
191
                ssid->pin = strdup(pos);
 
192
                ssid->pending_req_pin = 0;
 
193
                if (ssid == wpa_s->current_ssid)
 
194
                        wpa_s->reassociate = 1;
281
195
        } else if (strcmp(rsp, "OTP") == 0) {
282
196
                free(ssid->otp);
283
197
                ssid->otp = (u8 *) strdup(pos);
285
199
                free(ssid->pending_req_otp);
286
200
                ssid->pending_req_otp = NULL;
287
201
                ssid->pending_req_otp_len = 0;
 
202
        } else if (strcmp(rsp, "PASSPHRASE") == 0) {
 
203
                free(ssid->private_key_passwd);
 
204
                ssid->private_key_passwd = (u8 *) strdup(pos);
 
205
                ssid->pending_req_passphrase = 0;
 
206
                if (ssid == wpa_s->current_ssid)
 
207
                        wpa_s->reassociate = 1;
288
208
        } else {
289
209
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
290
210
                return -1;
291
211
        }
292
212
 
293
213
        return 0;
 
214
#else /* IEEE8021X_EAPOL */
 
215
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
 
216
        return -1;
 
217
#endif /* IEEE8021X_EAPOL */
294
218
}
295
219
 
296
220
 
298
222
                                            const char *params,
299
223
                                            char *buf, size_t buflen)
300
224
{
301
 
        char *pos, *end;
302
 
        int res, verbose;
 
225
        char *pos, *end, tmp[30];
 
226
        int res, verbose, ret;
303
227
 
304
228
        verbose = strcmp(params, "-VERBOSE") == 0;
305
229
        pos = buf;
306
230
        end = buf + buflen;
307
 
        pos += snprintf(pos, end - pos, "bssid=" MACSTR "\n",
308
 
                        MAC2STR(wpa_s->bssid));
309
 
        if (wpa_s->current_ssid) {
310
 
                pos += snprintf(pos, end - pos, "ssid=%s\n",
311
 
                                wpa_ssid_txt(wpa_s->current_ssid->ssid,
312
 
                                             wpa_s->current_ssid->ssid_len));
313
 
        }
314
 
        pos += snprintf(pos, end - pos,
315
 
                        "pairwise_cipher=%s\n"
316
 
                        "group_cipher=%s\n"
317
 
                        "key_mgmt=%s\n"
318
 
                        "wpa_state=%s\n",
319
 
                        wpa_cipher_txt(wpa_s->pairwise_cipher),
320
 
                        wpa_cipher_txt(wpa_s->group_cipher),
321
 
                        wpa_key_mgmt_txt(wpa_s->key_mgmt, wpa_s->proto),
322
 
                        wpa_state_txt(wpa_s->wpa_state));
323
 
 
324
 
        res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos, verbose);
325
 
        if (res >= 0)
326
 
                pos += res;
327
 
 
328
 
        if (wpa_s->preauth_eapol) {
329
 
                pos += snprintf(pos, end - pos, "Pre-authentication "
330
 
                                "EAPOL state machines:\n");
331
 
                res = eapol_sm_get_status(wpa_s->preauth_eapol,
332
 
                                          pos, end - pos, verbose);
 
231
        if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
 
232
                struct wpa_ssid *ssid = wpa_s->current_ssid;
 
233
                ret = snprintf(pos, end - pos, "bssid=" MACSTR "\n",
 
234
                               MAC2STR(wpa_s->bssid));
 
235
                if (ret < 0 || ret >= end - pos)
 
236
                        return pos - buf;
 
237
                pos += ret;
 
238
                if (ssid) {
 
239
                        u8 *_ssid = ssid->ssid;
 
240
                        size_t ssid_len = ssid->ssid_len;
 
241
                        u8 ssid_buf[MAX_SSID_LEN];
 
242
                        if (ssid_len == 0) {
 
243
                                int res = wpa_drv_get_ssid(wpa_s, ssid_buf);
 
244
                                if (res < 0)
 
245
                                        ssid_len = 0;
 
246
                                else
 
247
                                        ssid_len = res;
 
248
                                _ssid = ssid_buf;
 
249
                        }
 
250
                        ret = snprintf(pos, end - pos, "ssid=%s\nid=%d\n",
 
251
                                       wpa_ssid_txt(_ssid, ssid_len),
 
252
                                       ssid->id);
 
253
                        if (ret < 0 || ret >= end - pos)
 
254
                                return pos - buf;
 
255
                        pos += ret;
 
256
 
 
257
                        if (ssid->id_str) {
 
258
                                ret = snprintf(pos, end - pos, "id_str=%s\n",
 
259
                                               ssid->id_str);
 
260
                                if (ret < 0 || ret >= end - pos)
 
261
                                        return pos - buf;
 
262
                                pos += ret;
 
263
                        }
 
264
                }
 
265
 
 
266
                pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
 
267
        }
 
268
        ret = snprintf(pos, end - pos, "wpa_state=%s\n",
 
269
                       wpa_supplicant_state_txt(wpa_s->wpa_state));
 
270
        if (ret < 0 || ret >= end - pos)
 
271
                return pos - buf;
 
272
        pos += ret;
 
273
 
 
274
        if (wpa_s->l2 &&
 
275
            l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0) {
 
276
                ret = snprintf(pos, end - pos, "ip_address=%s\n", tmp);
 
277
                if (ret < 0 || ret >= end - pos)
 
278
                        return pos - buf;
 
279
                pos += ret;
 
280
        }
 
281
 
 
282
        if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
 
283
            wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
 
284
                res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
 
285
                                          verbose);
333
286
                if (res >= 0)
334
287
                        pos += res;
335
288
        }
336
289
 
337
 
        return pos - buf;
338
 
}
339
 
 
340
 
 
341
 
static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
342
 
                                              void *sock_ctx)
343
 
{
344
 
        struct wpa_supplicant *wpa_s = eloop_ctx;
345
 
        char buf[256];
346
 
        int res;
347
 
        CTRL_IFACE_SOCK from;
348
 
        socklen_t fromlen = sizeof(from);
 
290
        res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
 
291
        if (res >= 0)
 
292
                pos += res;
 
293
 
 
294
        return pos - buf;
 
295
}
 
296
 
 
297
 
 
298
static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
 
299
                                           char *cmd)
 
300
{
 
301
        char *pos;
 
302
        int id;
 
303
        struct wpa_ssid *ssid;
 
304
        u8 bssid[ETH_ALEN];
 
305
 
 
306
        /* cmd: "<network id> <BSSID>" */
 
307
        pos = strchr(cmd, ' ');
 
308
        if (pos == NULL)
 
309
                return -1;
 
310
        *pos++ = '\0';
 
311
        id = atoi(cmd);
 
312
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
 
313
        if (hwaddr_aton(pos, bssid)) {
 
314
                wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
 
315
                return -1;
 
316
        }
 
317
 
 
318
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
319
        if (ssid == NULL) {
 
320
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
 
321
                           "to update", id);
 
322
                return -1;
 
323
        }
 
324
 
 
325
        memcpy(ssid->bssid, bssid, ETH_ALEN);
 
326
        ssid->bssid_set =
 
327
                memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0;
 
328
                
 
329
 
 
330
        return 0;
 
331
}
 
332
 
 
333
 
 
334
static int wpa_supplicant_ctrl_iface_list_networks(
 
335
        struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
 
336
{
 
337
        char *pos, *end;
 
338
        struct wpa_ssid *ssid;
 
339
        int ret;
 
340
 
 
341
        pos = buf;
 
342
        end = buf + buflen;
 
343
        ret = snprintf(pos, end - pos, "network id / ssid / bssid / flags\n");
 
344
        if (ret < 0 || ret >= end - pos)
 
345
                return pos - buf;
 
346
        pos += ret;
 
347
 
 
348
        ssid = wpa_s->conf->ssid;
 
349
        while (ssid) {
 
350
                ret = snprintf(pos, end - pos, "%d\t%s",
 
351
                               ssid->id,
 
352
                               wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
 
353
                if (ret < 0 || ret >= end - pos)
 
354
                        return pos - buf;
 
355
                pos += ret;
 
356
                if (ssid->bssid_set) {
 
357
                        ret = snprintf(pos, end - pos, "\t" MACSTR,
 
358
                                       MAC2STR(ssid->bssid));
 
359
                } else {
 
360
                        ret = snprintf(pos, end - pos, "\tany");
 
361
                }
 
362
                if (ret < 0 || ret >= end - pos)
 
363
                        return pos - buf;
 
364
                pos += ret;
 
365
                ret = snprintf(pos, end - pos, "\t%s%s",
 
366
                               ssid == wpa_s->current_ssid ? "[CURRENT]" : "",
 
367
                               ssid->disabled ? "[DISABLED]" : "");
 
368
                if (ret < 0 || ret >= end - pos)
 
369
                        return pos - buf;
 
370
                pos += ret;
 
371
                ret = snprintf(pos, end - pos, "\n");
 
372
                if (ret < 0 || ret >= end - pos)
 
373
                        return pos - buf;
 
374
                pos += ret;
 
375
 
 
376
                ssid = ssid->next;
 
377
        }
 
378
 
 
379
        return pos - buf;
 
380
}
 
381
 
 
382
 
 
383
static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
 
384
{
 
385
        int first = 1, ret;
 
386
        ret = snprintf(pos, end - pos, "-");
 
387
        if (ret < 0 || ret >= end - pos)
 
388
                return pos;
 
389
        pos += ret;
 
390
        if (cipher & WPA_CIPHER_NONE) {
 
391
                ret = snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
 
392
                if (ret < 0 || ret >= end - pos)
 
393
                        return pos;
 
394
                pos += ret;
 
395
                first = 0;
 
396
        }
 
397
        if (cipher & WPA_CIPHER_WEP40) {
 
398
                ret = snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
 
399
                if (ret < 0 || ret >= end - pos)
 
400
                        return pos;
 
401
                pos += ret;
 
402
                first = 0;
 
403
        }
 
404
        if (cipher & WPA_CIPHER_WEP104) {
 
405
                ret = snprintf(pos, end - pos, "%sWEP104", first ? "" : "+");
 
406
                if (ret < 0 || ret >= end - pos)
 
407
                        return pos;
 
408
                pos += ret;
 
409
                first = 0;
 
410
        }
 
411
        if (cipher & WPA_CIPHER_TKIP) {
 
412
                ret = snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
 
413
                if (ret < 0 || ret >= end - pos)
 
414
                        return pos;
 
415
                pos += ret;
 
416
                first = 0;
 
417
        }
 
418
        if (cipher & WPA_CIPHER_CCMP) {
 
419
                ret = snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
 
420
                if (ret < 0 || ret >= end - pos)
 
421
                        return pos;
 
422
                pos += ret;
 
423
                first = 0;
 
424
        }
 
425
        return pos;
 
426
}
 
427
 
 
428
 
 
429
static char * wpa_supplicant_ie_txt(char *pos, char *end, const char *proto,
 
430
                                    const u8 *ie, size_t ie_len)
 
431
{
 
432
        struct wpa_ie_data data;
 
433
        int first, ret;
 
434
 
 
435
        ret = snprintf(pos, end - pos, "[%s-", proto);
 
436
        if (ret < 0 || ret >= end - pos)
 
437
                return pos;
 
438
        pos += ret;
 
439
 
 
440
        if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
 
441
                ret = snprintf(pos, end - pos, "?]");
 
442
                if (ret < 0 || ret >= end - pos)
 
443
                        return pos;
 
444
                pos += ret;
 
445
                return pos;
 
446
        }
 
447
 
 
448
        first = 1;
 
449
        if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
 
450
                ret = snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
 
451
                if (ret < 0 || ret >= end - pos)
 
452
                        return pos;
 
453
                pos += ret;
 
454
                first = 0;
 
455
        }
 
456
        if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
 
457
                ret = snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
 
458
                if (ret < 0 || ret >= end - pos)
 
459
                        return pos;
 
460
                pos += ret;
 
461
                first = 0;
 
462
        }
 
463
        if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
 
464
                ret = snprintf(pos, end - pos, "%sNone", first ? "" : "+");
 
465
                if (ret < 0 || ret >= end - pos)
 
466
                        return pos;
 
467
                pos += ret;
 
468
                first = 0;
 
469
        }
 
470
 
 
471
        pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
 
472
 
 
473
        if (data.capabilities & WPA_CAPABILITY_PREAUTH) {
 
474
                ret = snprintf(pos, end - pos, "-preauth");
 
475
                if (ret < 0 || ret >= end - pos)
 
476
                        return pos;
 
477
                pos += ret;
 
478
        }
 
479
 
 
480
        ret = snprintf(pos, end - pos, "]");
 
481
        if (ret < 0 || ret >= end - pos)
 
482
                return pos;
 
483
        pos += ret;
 
484
 
 
485
        return pos;
 
486
}
 
487
 
 
488
 
 
489
static int wpa_supplicant_ctrl_iface_scan_results(
 
490
        struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
 
491
{
 
492
        char *pos, *end;
 
493
        struct wpa_scan_result *res;
 
494
        int i, ret;
 
495
 
 
496
        if (wpa_s->scan_results == NULL &&
 
497
            wpa_supplicant_get_scan_results(wpa_s) < 0)
 
498
                return 0;
 
499
 
 
500
        pos = buf;
 
501
        end = buf + buflen;
 
502
        ret = snprintf(pos, end - pos, "bssid / frequency / signal level / "
 
503
                       "flags / ssid\n");
 
504
        if (ret < 0 || ret >= end - pos)
 
505
                return pos - buf;
 
506
        pos += ret;
 
507
 
 
508
        for (i = 0; i < wpa_s->num_scan_results; i++) {
 
509
                res = &wpa_s->scan_results[i];
 
510
                ret = snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
 
511
                               MAC2STR(res->bssid), res->freq, res->level);
 
512
                if (ret < 0 || ret >= end - pos)
 
513
                        return pos - buf;
 
514
                pos += ret;
 
515
                if (res->wpa_ie_len) {
 
516
                        pos = wpa_supplicant_ie_txt(pos, end, "WPA",
 
517
                                                    res->wpa_ie,
 
518
                                                    res->wpa_ie_len);
 
519
                }
 
520
                if (res->rsn_ie_len) {
 
521
                        pos = wpa_supplicant_ie_txt(pos, end, "WPA2",
 
522
                                                    res->rsn_ie,
 
523
                                                    res->rsn_ie_len);
 
524
                }
 
525
                if (!res->wpa_ie_len && !res->rsn_ie_len &&
 
526
                    res->caps & IEEE80211_CAP_PRIVACY) {
 
527
                        ret = snprintf(pos, end - pos, "[WEP]");
 
528
                        if (ret < 0 || ret >= end - pos)
 
529
                                return pos - buf;
 
530
                        pos += ret;
 
531
                }
 
532
                if (res->caps & IEEE80211_CAP_IBSS) {
 
533
                        ret = snprintf(pos, end - pos, "[IBSS]");
 
534
                        if (ret < 0 || ret >= end - pos)
 
535
                                return pos - buf;
 
536
                        pos += ret;
 
537
                }
 
538
 
 
539
                ret = snprintf(pos, end - pos, "\t%s",
 
540
                               wpa_ssid_txt(res->ssid, res->ssid_len));
 
541
                if (ret < 0 || ret >= end - pos)
 
542
                        return pos - buf;
 
543
                pos += ret;
 
544
 
 
545
                ret = snprintf(pos, end - pos, "\n");
 
546
                if (ret < 0 || ret >= end - pos)
 
547
                        return pos - buf;
 
548
                pos += ret;
 
549
        }
 
550
 
 
551
        return pos - buf;
 
552
}
 
553
 
 
554
 
 
555
static int wpa_supplicant_ctrl_iface_select_network(
 
556
        struct wpa_supplicant *wpa_s, char *cmd)
 
557
{
 
558
        int id;
 
559
        struct wpa_ssid *ssid;
 
560
 
 
561
        /* cmd: "<network id>" or "any" */
 
562
        if (strcmp(cmd, "any") == 0) {
 
563
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
 
564
                ssid = wpa_s->conf->ssid;
 
565
                while (ssid) {
 
566
                        ssid->disabled = 0;
 
567
                        ssid = ssid->next;
 
568
                }
 
569
                wpa_s->reassociate = 1;
 
570
                wpa_supplicant_req_scan(wpa_s, 0, 0);
 
571
                return 0;
 
572
        }
 
573
 
 
574
        id = atoi(cmd);
 
575
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
 
576
 
 
577
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
578
        if (ssid == NULL) {
 
579
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
580
                           "id=%d", id);
 
581
                return -1;
 
582
        }
 
583
 
 
584
        if (ssid != wpa_s->current_ssid && wpa_s->current_ssid)
 
585
                wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
 
586
 
 
587
        /* Mark all other networks disabled and trigger reassociation */
 
588
        ssid = wpa_s->conf->ssid;
 
589
        while (ssid) {
 
590
                ssid->disabled = id != ssid->id;
 
591
                ssid = ssid->next;
 
592
        }
 
593
        wpa_s->reassociate = 1;
 
594
        wpa_supplicant_req_scan(wpa_s, 0, 0);
 
595
 
 
596
        return 0;
 
597
}
 
598
 
 
599
 
 
600
static int wpa_supplicant_ctrl_iface_enable_network(
 
601
        struct wpa_supplicant *wpa_s, char *cmd)
 
602
{
 
603
        int id;
 
604
        struct wpa_ssid *ssid;
 
605
 
 
606
        /* cmd: "<network id>" */
 
607
        id = atoi(cmd);
 
608
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
 
609
 
 
610
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
611
        if (ssid == NULL) {
 
612
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
613
                           "id=%d", id);
 
614
                return -1;
 
615
        }
 
616
 
 
617
        if (wpa_s->current_ssid == NULL && ssid->disabled) {
 
618
                /*
 
619
                 * Try to reassociate since there is no current configuration
 
620
                 * and a new network was made available. */
 
621
                wpa_s->reassociate = 1;
 
622
                wpa_supplicant_req_scan(wpa_s, 0, 0);
 
623
        }
 
624
        ssid->disabled = 0;
 
625
 
 
626
        return 0;
 
627
}
 
628
 
 
629
 
 
630
static int wpa_supplicant_ctrl_iface_disable_network(
 
631
        struct wpa_supplicant *wpa_s, char *cmd)
 
632
{
 
633
        int id;
 
634
        struct wpa_ssid *ssid;
 
635
 
 
636
        /* cmd: "<network id>" */
 
637
        id = atoi(cmd);
 
638
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
 
639
 
 
640
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
641
        if (ssid == NULL) {
 
642
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
643
                           "id=%d", id);
 
644
                return -1;
 
645
        }
 
646
 
 
647
        if (ssid == wpa_s->current_ssid)
 
648
                wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
 
649
        ssid->disabled = 1;
 
650
 
 
651
        return 0;
 
652
}
 
653
 
 
654
 
 
655
static int wpa_supplicant_ctrl_iface_add_network(
 
656
        struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
 
657
{
 
658
        struct wpa_ssid *ssid;
 
659
        int ret;
 
660
 
 
661
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
 
662
 
 
663
        ssid = wpa_config_add_network(wpa_s->conf);
 
664
        if (ssid == NULL)
 
665
                return -1;
 
666
        ssid->disabled = 1;
 
667
        wpa_config_set_network_defaults(ssid);
 
668
 
 
669
        ret = snprintf(buf, buflen, "%d\n", ssid->id);
 
670
        if (ret < 0 || (size_t) ret >= buflen)
 
671
                return -1;
 
672
        return ret;
 
673
}
 
674
 
 
675
 
 
676
static int wpa_supplicant_ctrl_iface_remove_network(
 
677
        struct wpa_supplicant *wpa_s, char *cmd)
 
678
{
 
679
        int id;
 
680
        struct wpa_ssid *ssid;
 
681
 
 
682
        /* cmd: "<network id>" */
 
683
        id = atoi(cmd);
 
684
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
 
685
 
 
686
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
687
        if (ssid == NULL ||
 
688
            wpa_config_remove_network(wpa_s->conf, id) < 0) {
 
689
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
690
                           "id=%d", id);
 
691
                return -1;
 
692
        }
 
693
 
 
694
        if (ssid == wpa_s->current_ssid)
 
695
                wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
 
696
 
 
697
        return 0;
 
698
}
 
699
 
 
700
 
 
701
static int wpa_supplicant_ctrl_iface_set_network(
 
702
        struct wpa_supplicant *wpa_s, char *cmd)
 
703
{
 
704
        int id;
 
705
        struct wpa_ssid *ssid;
 
706
        char *name, *value;
 
707
 
 
708
        /* cmd: "<network id> <variable name> <value>" */
 
709
        name = strchr(cmd, ' ');
 
710
        if (name == NULL)
 
711
                return -1;
 
712
        *name++ = '\0';
 
713
 
 
714
        value = strchr(name, ' ');
 
715
        if (value == NULL)
 
716
                return -1;
 
717
        *value++ = '\0';
 
718
 
 
719
        id = atoi(cmd);
 
720
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
 
721
                   id, name);
 
722
        wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
 
723
                              (u8 *) value, strlen(value));
 
724
 
 
725
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
726
        if (ssid == NULL) {
 
727
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
728
                           "id=%d", id);
 
729
                return -1;
 
730
        }
 
731
 
 
732
        if (wpa_config_set(ssid, name, value, 0) < 0) {
 
733
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
 
734
                           "variable '%s'", name);
 
735
                return -1;
 
736
        }
 
737
 
 
738
        if ((strcmp(name, "psk") == 0 && value[0] == '"' && ssid->ssid_len) ||
 
739
            (strcmp(name, "ssid") == 0 && ssid->passphrase))
 
740
                wpa_config_update_psk(ssid);
 
741
 
 
742
        return 0;
 
743
}
 
744
 
 
745
 
 
746
static int wpa_supplicant_ctrl_iface_get_network(
 
747
        struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
 
748
{
 
749
        int id;
 
750
        struct wpa_ssid *ssid;
 
751
        char *name, *value;
 
752
 
 
753
        /* cmd: "<network id> <variable name>" */
 
754
        name = strchr(cmd, ' ');
 
755
        if (name == NULL || buflen == 0)
 
756
                return -1;
 
757
        *name++ = '\0';
 
758
 
 
759
        id = atoi(cmd);
 
760
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
 
761
                   id, name);
 
762
 
 
763
        ssid = wpa_config_get_network(wpa_s->conf, id);
 
764
        if (ssid == NULL) {
 
765
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
 
766
                           "id=%d", id);
 
767
                return -1;
 
768
        }
 
769
 
 
770
        value = wpa_config_get(ssid, name);
 
771
        if (value == NULL) {
 
772
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
 
773
                           "variable '%s'", name);
 
774
                return -1;
 
775
        }
 
776
 
 
777
        snprintf(buf, buflen, "%s", value);
 
778
        buf[buflen - 1] = '\0';
 
779
 
 
780
        free(value);
 
781
 
 
782
        return strlen(buf);
 
783
}
 
784
 
 
785
 
 
786
static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
 
787
{
 
788
        int ret;
 
789
 
 
790
        if (!wpa_s->conf->update_config) {
 
791
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
 
792
                           "to update configuration (update_config=0)");
 
793
                return -1;
 
794
        }
 
795
 
 
796
        ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
 
797
        if (ret) {
 
798
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
 
799
                           "update configuration");
 
800
        } else {
 
801
                wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
 
802
                           " updated");
 
803
        }
 
804
 
 
805
        return ret;
 
806
}
 
807
 
 
808
 
 
809
static int wpa_supplicant_ctrl_iface_get_capability(
 
810
        struct wpa_supplicant *wpa_s, const char *_field, char *buf,
 
811
        size_t buflen)
 
812
{
 
813
        struct wpa_driver_capa capa;
 
814
        int res, first = 1, ret;
 
815
        char *pos, *end, *strict;
 
816
        char field[30];
 
817
 
 
818
        /* Determine whether or not strict checking was requested */
 
819
        snprintf(field, sizeof(field), "%s", _field);
 
820
        field[sizeof(field) - 1] = '\0';
 
821
        strict = strchr(field, ' ');
 
822
        if (strict != NULL) {
 
823
                *strict++ = '\0';
 
824
                if (strcmp(strict, "strict") != 0) {
 
825
                        free(field);
 
826
                        return -1;
 
827
                }
 
828
        }
 
829
 
 
830
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
 
831
                field, strict ? strict : "");
 
832
 
 
833
        if (strcmp(field, "eap") == 0) {
 
834
                return eap_get_names(buf, buflen);
 
835
        }
 
836
 
 
837
        res = wpa_drv_get_capa(wpa_s, &capa);
 
838
 
 
839
        pos = buf;
 
840
        end = pos + buflen;
 
841
 
 
842
        if (strcmp(field, "pairwise") == 0) {
 
843
                if (res < 0) {
 
844
                        if (strict)
 
845
                                return 0;
 
846
                        ret = snprintf(buf, buflen, "CCMP TKIP NONE");
 
847
                        if (ret < 0 || (size_t) ret >= buflen)
 
848
                                return -1;
 
849
                        return ret;
 
850
                }
 
851
 
 
852
                if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
 
853
                        ret = snprintf(pos, end - pos, "%sCCMP",
 
854
                                       first ? "" : " ");
 
855
                        if (ret < 0 || ret >= end - pos)
 
856
                                return pos - buf;
 
857
                        pos += ret;
 
858
                        first = 0;
 
859
                }
 
860
 
 
861
                if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
 
862
                        ret = snprintf(pos, end - pos, "%sTKIP",
 
863
                                       first ? "" : " ");
 
864
                        if (ret < 0 || ret >= end - pos)
 
865
                                return pos - buf;
 
866
                        pos += ret;
 
867
                        first = 0;
 
868
                }
 
869
 
 
870
                if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
 
871
                        ret = snprintf(pos, end - pos, "%sNONE",
 
872
                                       first ? "" : " ");
 
873
                        if (ret < 0 || ret >= end - pos)
 
874
                                return pos - buf;
 
875
                        pos += ret;
 
876
                        first = 0;
 
877
                }
 
878
 
 
879
                return pos - buf;
 
880
        }
 
881
 
 
882
        if (strcmp(field, "group") == 0) {
 
883
                if (res < 0) {
 
884
                        if (strict)
 
885
                                return 0;
 
886
                        ret = snprintf(buf, buflen, "CCMP TKIP WEP104 WEP40");
 
887
                        if (ret < 0 || (size_t) ret >= buflen)
 
888
                                return -1;
 
889
                        return ret;
 
890
                }
 
891
 
 
892
                if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
 
893
                        ret = snprintf(pos, end - pos, "%sCCMP",
 
894
                                       first ? "" : " ");
 
895
                        if (ret < 0 || ret >= end - pos)
 
896
                                return pos - buf;
 
897
                        pos += ret;
 
898
                        first = 0;
 
899
                }
 
900
 
 
901
                if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
 
902
                        ret = snprintf(pos, end - pos, "%sTKIP",
 
903
                                       first ? "" : " ");
 
904
                        if (ret < 0 || ret >= end - pos)
 
905
                                return pos - buf;
 
906
                        pos += ret;
 
907
                        first = 0;
 
908
                }
 
909
 
 
910
                if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
 
911
                        ret = snprintf(pos, end - pos, "%sWEP104",
 
912
                                       first ? "" : " ");
 
913
                        if (ret < 0 || ret >= end - pos)
 
914
                                return pos - buf;
 
915
                        pos += ret;
 
916
                        first = 0;
 
917
                }
 
918
 
 
919
                if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
 
920
                        ret = snprintf(pos, end - pos, "%sWEP40",
 
921
                                       first ? "" : " ");
 
922
                        if (ret < 0 || ret >= end - pos)
 
923
                                return pos - buf;
 
924
                        pos += ret;
 
925
                        first = 0;
 
926
                }
 
927
 
 
928
                return pos - buf;
 
929
        }
 
930
 
 
931
        if (strcmp(field, "key_mgmt") == 0) {
 
932
                if (res < 0) {
 
933
                        if (strict)
 
934
                                return 0;
 
935
                        ret = snprintf(buf, buflen, "WPA-PSK WPA-EAP "
 
936
                                       "IEEE8021X WPA-NONE NONE");
 
937
                        if (ret < 0 || (size_t) ret >= buflen)
 
938
                                return -1;
 
939
                        return ret;
 
940
                }
 
941
 
 
942
                ret = snprintf(pos, end - pos, "NONE IEEE8021X");
 
943
                if (ret < 0 || ret >= end - pos)
 
944
                        return pos - buf;
 
945
                pos += ret;
 
946
 
 
947
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
 
948
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
 
949
                        ret = snprintf(pos, end - pos, " WPA-EAP");
 
950
                        if (ret < 0 || ret >= end - pos)
 
951
                                return pos - buf;
 
952
                        pos += ret;
 
953
                }
 
954
 
 
955
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
 
956
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
 
957
                        ret = snprintf(pos, end - pos, " WPA-PSK");
 
958
                        if (ret < 0 || ret >= end - pos)
 
959
                                return pos - buf;
 
960
                        pos += ret;
 
961
                }
 
962
 
 
963
                if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
 
964
                        ret = snprintf(pos, end - pos, " WPA-NONE");
 
965
                        if (ret < 0 || ret >= end - pos)
 
966
                                return pos - buf;
 
967
                        pos += ret;
 
968
                }
 
969
 
 
970
                return pos - buf;
 
971
        }
 
972
 
 
973
        if (strcmp(field, "proto") == 0) {
 
974
                if (res < 0) {
 
975
                        if (strict)
 
976
                                return 0;
 
977
                        ret = snprintf(buf, buflen, "RSN WPA");
 
978
                        if (ret < 0 || (size_t) ret >= buflen)
 
979
                                return -1;
 
980
                        return ret;
 
981
                }
 
982
 
 
983
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
 
984
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
 
985
                        ret = snprintf(pos, end - pos, "%sRSN",
 
986
                                       first ? "" : " ");
 
987
                        if (ret < 0 || ret >= end - pos)
 
988
                                return pos - buf;
 
989
                        pos += ret;
 
990
                        first = 0;
 
991
                }
 
992
 
 
993
                if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
 
994
                                     WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
 
995
                        ret = snprintf(pos, end - pos, "%sWPA",
 
996
                                       first ? "" : " ");
 
997
                        if (ret < 0 || ret >= end - pos)
 
998
                                return pos - buf;
 
999
                        pos += ret;
 
1000
                        first = 0;
 
1001
                }
 
1002
 
 
1003
                return pos - buf;
 
1004
        }
 
1005
 
 
1006
        if (strcmp(field, "auth_alg") == 0) {
 
1007
                if (res < 0) {
 
1008
                        if (strict)
 
1009
                                return 0;
 
1010
                        ret = snprintf(buf, buflen, "OPEN SHARED LEAP");
 
1011
                        if (ret < 0 || (size_t) ret >= buflen)
 
1012
                                return -1;
 
1013
                        return ret;
 
1014
                }
 
1015
 
 
1016
                if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
 
1017
                        ret = snprintf(pos, end - pos, "%sOPEN",
 
1018
                                       first ? "" : " ");
 
1019
                        if (ret < 0 || ret >= end - pos)
 
1020
                                return pos - buf;
 
1021
                        pos += ret;
 
1022
                        first = 0;
 
1023
                }
 
1024
 
 
1025
                if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
 
1026
                        ret = snprintf(pos, end - pos, "%sSHARED",
 
1027
                                       first ? "" : " ");
 
1028
                        if (ret < 0 || ret >= end - pos)
 
1029
                                return pos - buf;
 
1030
                        pos += ret;
 
1031
                        first = 0;
 
1032
                }
 
1033
 
 
1034
                if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
 
1035
                        ret = snprintf(pos, end - pos, "%sLEAP",
 
1036
                                       first ? "" : " ");
 
1037
                        if (ret < 0 || ret >= end - pos)
 
1038
                                return pos - buf;
 
1039
                        pos += ret;
 
1040
                        first = 0;
 
1041
                }
 
1042
 
 
1043
                return pos - buf;
 
1044
        }
 
1045
 
 
1046
        wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
 
1047
                   field);
 
1048
 
 
1049
        return -1;
 
1050
}
 
1051
 
 
1052
 
 
1053
static int wpa_supplicant_ctrl_iface_ap_scan(
 
1054
        struct wpa_supplicant *wpa_s, char *cmd)
 
1055
{
 
1056
        int ap_scan = atoi(cmd);
 
1057
 
 
1058
        if (ap_scan < 0 || ap_scan > 2)
 
1059
                return -1;
 
1060
        wpa_s->conf->ap_scan = ap_scan;
 
1061
        return 0;
 
1062
}
 
1063
 
 
1064
 
 
1065
char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s,
 
1066
                                         char *buf, size_t *resp_len)
 
1067
{
349
1068
        char *reply;
350
1069
        const int reply_size = 2048;
 
1070
        int ctrl_rsp = 0;
351
1071
        int reply_len;
352
 
        int new_attached = 0, ctrl_rsp = 0;
353
1072
 
354
 
        res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
355
 
                       (struct sockaddr *) &from, &fromlen);
356
 
        if (res < 0) {
357
 
                perror("recvfrom(ctrl_iface)");
358
 
                return;
359
 
        }
360
 
        buf[res] = '\0';
361
 
        if (strncmp(buf, "CTRL-RSP-", 9) == 0) {
 
1073
        if (strncmp(buf, WPA_CTRL_RSP, strlen(WPA_CTRL_RSP)) == 0 ||
 
1074
            strncmp(buf, "SET_NETWORK ", 12) == 0) {
362
1075
                wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
363
 
                                      (u8 *) buf, res);
 
1076
                                      (const u8 *) buf, strlen(buf));
364
1077
        } else {
365
 
                wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (u8 *) buf, res);
 
1078
                wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface",
 
1079
                                  (const u8 *) buf, strlen(buf));
366
1080
        }
367
1081
 
368
1082
        reply = malloc(reply_size);
369
1083
        if (reply == NULL) {
370
 
                sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
371
 
                       fromlen);
372
 
                return;
 
1084
                *resp_len = 1;
 
1085
                return NULL;
373
1086
        }
374
1087
 
375
1088
        memcpy(reply, "OK\n", 3);
379
1092
                memcpy(reply, "PONG\n", 5);
380
1093
                reply_len = 5;
381
1094
        } else if (strcmp(buf, "MIB") == 0) {
382
 
                reply_len = wpa_get_mib(wpa_s, reply, reply_size);
 
1095
                reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
383
1096
                if (reply_len >= 0) {
 
1097
                        int res;
384
1098
                        res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
385
1099
                                               reply_size - reply_len);
386
1100
                        if (res < 0)
392
1106
                reply_len = wpa_supplicant_ctrl_iface_status(
393
1107
                        wpa_s, buf + 6, reply, reply_size);
394
1108
        } else if (strcmp(buf, "PMKSA") == 0) {
395
 
                reply_len = pmksa_cache_list(wpa_s, reply, reply_size);
 
1109
                reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size);
396
1110
        } else if (strncmp(buf, "SET ", 4) == 0) {
397
1111
                if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
398
1112
                        reply_len = -1;
401
1115
        } else if (strcmp(buf, "LOGOFF") == 0) {
402
1116
                eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
403
1117
        } else if (strcmp(buf, "REASSOCIATE") == 0) {
 
1118
                wpa_s->disconnected = 0;
404
1119
                wpa_s->reassociate = 1;
405
1120
                wpa_supplicant_req_scan(wpa_s, 0, 0);
406
1121
        } else if (strncmp(buf, "PREAUTH ", 8) == 0) {
407
1122
                if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
408
1123
                        reply_len = -1;
409
 
        } else if (strcmp(buf, "ATTACH") == 0) {
410
 
                if (wpa_supplicant_ctrl_iface_attach(wpa_s, &from, fromlen))
411
 
                        reply_len = -1;
412
 
                else
413
 
                        new_attached = 1;
414
 
        } else if (strcmp(buf, "DETACH") == 0) {
415
 
                if (wpa_supplicant_ctrl_iface_detach(wpa_s, &from, fromlen))
416
 
                        reply_len = -1;
417
 
        } else if (strncmp(buf, "LEVEL ", 6) == 0) {
418
 
                if (wpa_supplicant_ctrl_iface_level(wpa_s, &from, fromlen,
419
 
                                                    buf + 6))
420
 
                        reply_len = -1;
421
 
        } else if (strncmp(buf, "CTRL-RSP-", 9) == 0) {
422
 
                if (wpa_supplicant_ctrl_iface_ctrl_rsp(wpa_s, buf + 9))
 
1124
#ifdef CONFIG_STAKEY
 
1125
        } else if (strncmp(buf, "STAKEY-REQUEST ", 15) == 0) {
 
1126
                if (wpa_supplicant_ctrl_iface_stakey_request(wpa_s, buf + 15))
 
1127
                        reply_len = -1;
 
1128
#endif /* CONFIG_STAKEY */
 
1129
#ifdef CONFIG_PEERKEY
 
1130
        } else if (strncmp(buf, "STKSTART ", 9) == 0) {
 
1131
                if (wpa_supplicant_ctrl_iface_stkstart(wpa_s, buf + 9))
 
1132
                        reply_len = -1;
 
1133
#endif /* CONFIG_PEERKEY */
 
1134
        } else if (strncmp(buf, WPA_CTRL_RSP, strlen(WPA_CTRL_RSP)) == 0) {
 
1135
                if (wpa_supplicant_ctrl_iface_ctrl_rsp(
 
1136
                            wpa_s, buf + strlen(WPA_CTRL_RSP)))
423
1137
                        reply_len = -1;
424
1138
                else
425
1139
                        ctrl_rsp = 1;
428
1142
                        reply_len = -1;
429
1143
        } else if (strcmp(buf, "TERMINATE") == 0) {
430
1144
                eloop_terminate();
 
1145
        } else if (strncmp(buf, "BSSID ", 6) == 0) {
 
1146
                if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
 
1147
                        reply_len = -1;
 
1148
        } else if (strcmp(buf, "LIST_NETWORKS") == 0) {
 
1149
                reply_len = wpa_supplicant_ctrl_iface_list_networks(
 
1150
                        wpa_s, reply, reply_size);
 
1151
        } else if (strcmp(buf, "DISCONNECT") == 0) {
 
1152
                wpa_s->disconnected = 1;
 
1153
                wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
 
1154
        } else if (strcmp(buf, "SCAN") == 0) {
 
1155
                wpa_s->scan_req = 2;
 
1156
                wpa_supplicant_req_scan(wpa_s, 0, 0);
 
1157
        } else if (strcmp(buf, "SCAN_RESULTS") == 0) {
 
1158
                reply_len = wpa_supplicant_ctrl_iface_scan_results(
 
1159
                        wpa_s, reply, reply_size);
 
1160
        } else if (strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
 
1161
                if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
 
1162
                        reply_len = -1;
 
1163
        } else if (strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
 
1164
                if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
 
1165
                        reply_len = -1;
 
1166
        } else if (strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
 
1167
                if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
 
1168
                        reply_len = -1;
 
1169
        } else if (strcmp(buf, "ADD_NETWORK") == 0) {
 
1170
                reply_len = wpa_supplicant_ctrl_iface_add_network(
 
1171
                        wpa_s, reply, reply_size);
 
1172
        } else if (strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
 
1173
                if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
 
1174
                        reply_len = -1;
 
1175
        } else if (strncmp(buf, "SET_NETWORK ", 12) == 0) {
 
1176
                if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
 
1177
                        reply_len = -1;
 
1178
        } else if (strncmp(buf, "GET_NETWORK ", 12) == 0) {
 
1179
                reply_len = wpa_supplicant_ctrl_iface_get_network(
 
1180
                        wpa_s, buf + 12, reply, reply_size);
 
1181
        } else if (strcmp(buf, "SAVE_CONFIG") == 0) {
 
1182
                if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
 
1183
                        reply_len = -1;
 
1184
        } else if (strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
 
1185
                reply_len = wpa_supplicant_ctrl_iface_get_capability(
 
1186
                        wpa_s, buf + 15, reply, reply_size);
 
1187
        } else if (strncmp(buf, "AP_SCAN ", 8) == 0) {
 
1188
                if (wpa_supplicant_ctrl_iface_ap_scan(wpa_s, buf + 8))
 
1189
                        reply_len = -1;
 
1190
        } else if (strcmp(buf, "INTERFACES") == 0) {
 
1191
                reply_len = wpa_supplicant_global_iface_interfaces(
 
1192
                        wpa_s->global, reply, reply_size);
431
1193
        } else {
432
1194
                memcpy(reply, "UNKNOWN COMMAND\n", 16);
433
1195
                reply_len = 16;
437
1199
                memcpy(reply, "FAIL\n", 5);
438
1200
                reply_len = 5;
439
1201
        }
440
 
        sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
441
 
        free(reply);
442
1202
 
443
 
        if (new_attached)
444
 
                eapol_sm_notify_ctrl_attached(wpa_s->eapol);
445
1203
        if (ctrl_rsp)
446
1204
                eapol_sm_notify_ctrl_response(wpa_s->eapol);
447
 
}
448
 
 
449
 
 
450
 
static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s)
451
 
{
452
 
        char *buf;
453
 
        size_t len;
454
 
 
455
 
        if (wpa_s->conf->ctrl_interface == NULL)
456
 
                return NULL;
457
 
 
458
 
        len = strlen(wpa_s->conf->ctrl_interface) + strlen(wpa_s->ifname) + 2;
459
 
        buf = malloc(len);
460
 
        if (buf == NULL)
461
 
                return NULL;
462
 
 
463
 
        snprintf(buf, len, "%s/%s",
464
 
                 wpa_s->conf->ctrl_interface, wpa_s->ifname);
465
 
#ifdef __CYGWIN__
466
 
        {
467
 
                /* Windows/WinPcap uses interface names that are not suitable
468
 
                 * as a file name - convert invalid chars to underscores */
469
 
                char *pos = buf;
470
 
                while (*pos) {
471
 
                        if (*pos == '\\')
472
 
                                *pos = '_';
473
 
                        pos++;
474
 
                }
475
 
        }
476
 
#endif /* __CYGWIN__ */
477
 
        return buf;
478
 
}
479
 
 
480
 
 
481
 
int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
482
 
{
483
 
        CTRL_IFACE_SOCK addr;
484
 
        int s = -1;
485
 
        char *fname = NULL;
486
 
 
487
 
        wpa_s->ctrl_sock = -1;
488
 
 
489
 
        if (wpa_s->conf->ctrl_interface == NULL)
490
 
                return 0;
491
 
 
492
 
#ifdef CONFIG_CTRL_IFACE_UDP
493
 
        s = socket(PF_INET, SOCK_DGRAM, 0);
494
 
        if (s < 0) {
495
 
                perror("socket(PF_INET)");
496
 
                goto fail;
497
 
        }
498
 
 
499
 
        memset(&addr, 0, sizeof(addr));
500
 
        addr.sin_family = AF_INET;
501
 
        addr.sin_addr.s_addr = htonl((127 << 24) | 1);
502
 
        addr.sin_port = htons(9877);
503
 
        if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
504
 
                perror("bind(AF_UNIX)");
505
 
                goto fail;
506
 
        }
507
 
#else /* CONFIG_CTRL_IFACE_UDP */
508
 
        if (mkdir(wpa_s->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
509
 
                if (errno == EEXIST) {
510
 
                        wpa_printf(MSG_DEBUG, "Using existing control "
511
 
                                   "interface directory.");
512
 
                } else {
513
 
                        perror("mkdir[ctrl_interface]");
514
 
                        goto fail;
515
 
                }
516
 
        }
517
 
 
518
 
        if (wpa_s->conf->ctrl_interface_gid_set &&
519
 
            chown(wpa_s->conf->ctrl_interface, 0,
520
 
                  wpa_s->conf->ctrl_interface_gid) < 0) {
521
 
                perror("chown[ctrl_interface]");
522
 
                return -1;
523
 
        }
524
 
 
525
 
        if (strlen(wpa_s->conf->ctrl_interface) + 1 + strlen(wpa_s->ifname) >=
526
 
            sizeof(addr.sun_path))
527
 
                goto fail;
528
 
 
529
 
        s = socket(PF_UNIX, SOCK_DGRAM, 0);
530
 
        if (s < 0) {
531
 
                perror("socket(PF_UNIX)");
532
 
                goto fail;
533
 
        }
534
 
 
535
 
        memset(&addr, 0, sizeof(addr));
536
 
        addr.sun_family = AF_UNIX;
537
 
        fname = wpa_supplicant_ctrl_iface_path(wpa_s);
538
 
        if (fname == NULL)
539
 
                goto fail;
540
 
        strncpy(addr.sun_path, fname, sizeof(addr.sun_path));
541
 
        if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
542
 
                perror("bind(PF_UNIX)");
543
 
                if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
544
 
                        wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
545
 
                                   " allow connections - assuming it was left"
546
 
                                   "over from forced program termination");
547
 
                        if (unlink(fname) < 0) {
548
 
                                perror("unlink[ctrl_iface]");
549
 
                                wpa_printf(MSG_ERROR, "Could not unlink "
550
 
                                           "existing ctrl_iface socket '%s'",
551
 
                                           fname);
552
 
                                goto fail;
553
 
                        }
554
 
                        if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
555
 
                            0) {
556
 
                                perror("bind(PF_UNIX)");
557
 
                                goto fail;
558
 
                        }
559
 
                        wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
560
 
                                   "ctrl_iface socket '%s'", fname);
561
 
                } else {
562
 
                        wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
563
 
                                   "be in use - cannot override it");
564
 
                        wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
565
 
                                   "not used anymore", fname);
566
 
                        free(fname);
567
 
                        fname = NULL;
568
 
                        goto fail;
569
 
                }
570
 
        }
571
 
 
572
 
        if (wpa_s->conf->ctrl_interface_gid_set &&
573
 
            chown(fname, 0, wpa_s->conf->ctrl_interface_gid) < 0) {
574
 
                perror("chown[ctrl_interface/ifname]");
575
 
                goto fail;
576
 
        }
577
 
 
578
 
        if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
579
 
                perror("chmod[ctrl_interface/ifname]");
580
 
                goto fail;
581
 
        }
582
 
        free(fname);
583
 
#endif /* CONFIG_CTRL_IFACE_UDP */
584
 
 
585
 
        wpa_s->ctrl_sock = s;
586
 
        eloop_register_read_sock(s, wpa_supplicant_ctrl_iface_receive, wpa_s,
587
 
                                 NULL);
588
 
 
589
 
        return 0;
590
 
 
591
 
fail:
592
 
        if (s >= 0)
593
 
                close(s);
594
 
        if (fname) {
595
 
                unlink(fname);
596
 
                free(fname);
597
 
        }
598
 
        return -1;
599
 
}
600
 
 
601
 
 
602
 
void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s)
603
 
{
604
 
        struct wpa_ctrl_dst *dst, *prev;
605
 
 
606
 
        if (wpa_s->ctrl_sock > -1) {
607
 
                char *fname;
608
 
                eloop_unregister_read_sock(wpa_s->ctrl_sock);
609
 
                close(wpa_s->ctrl_sock);
610
 
                wpa_s->ctrl_sock = -1;
611
 
                fname = wpa_supplicant_ctrl_iface_path(wpa_s);
612
 
                if (fname)
613
 
                        unlink(fname);
614
 
                free(fname);
615
 
 
616
 
                if (rmdir(wpa_s->conf->ctrl_interface) < 0) {
617
 
                        if (errno == ENOTEMPTY) {
618
 
                                wpa_printf(MSG_DEBUG, "Control interface "
619
 
                                           "directory not empty - leaving it "
620
 
                                           "behind");
621
 
                        } else {
622
 
                                perror("rmdir[ctrl_interface]");
623
 
                        }
624
 
                }
625
 
        }
626
 
 
627
 
        dst = wpa_s->ctrl_dst;
628
 
        while (dst) {
629
 
                prev = dst;
630
 
                dst = dst->next;
631
 
                free(prev);
632
 
        }
633
 
}
634
 
 
635
 
 
636
 
void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level,
637
 
                                    char *buf, size_t len)
638
 
{
639
 
        struct wpa_ctrl_dst *dst, *next;
640
 
        char levelstr[10];
641
 
        int idx;
642
 
#ifdef CONFIG_CTRL_IFACE_UDP
643
 
        char *sbuf;
644
 
        int llen;
645
 
 
646
 
        dst = wpa_s->ctrl_dst;
647
 
        if (wpa_s->ctrl_sock < 0 || dst == NULL)
648
 
                return;
649
 
 
650
 
        snprintf(levelstr, sizeof(levelstr), "<%d>", level);
651
 
 
652
 
        llen = strlen(levelstr);
653
 
        sbuf = malloc(llen + len);
654
 
        if (sbuf == NULL)
655
 
                return;
656
 
 
657
 
        memcpy(sbuf, levelstr, llen);
658
 
        memcpy(sbuf + llen, buf, len);
659
 
 
660
 
        idx = 0;
661
 
        while (dst) {
662
 
                next = dst->next;
663
 
                if (level >= dst->debug_level) {
664
 
                        wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
665
 
                                   inet_ntoa(dst->addr.sin_addr),
666
 
                                   ntohs(dst->addr.sin_port));
667
 
                        if (sendto(wpa_s->ctrl_sock, sbuf, llen + len, 0,
668
 
                                   (struct sockaddr *) &dst->addr,
669
 
                                   sizeof(dst->addr)) < 0) {
670
 
                                fprintf(stderr, "CTRL_IFACE monitor[%d]: ",
671
 
                                        idx);
672
 
                                perror("sendto");
673
 
                                dst->errors++;
674
 
                                if (dst->errors > 10) {
675
 
                                        wpa_supplicant_ctrl_iface_detach(
676
 
                                                wpa_s, &dst->addr,
677
 
                                                dst->addrlen);
678
 
                                }
679
 
                        } else
680
 
                                dst->errors = 0;
681
 
                }
682
 
                idx++;
683
 
                dst = next;
684
 
        }
685
 
        free(sbuf);
686
 
#else /* CONFIG_CTRL_IFACE_UDP */
687
 
        struct msghdr msg;
688
 
        struct iovec io[2];
689
 
 
690
 
        dst = wpa_s->ctrl_dst;
691
 
        if (wpa_s->ctrl_sock < 0 || dst == NULL)
692
 
                return;
693
 
 
694
 
        snprintf(levelstr, sizeof(levelstr), "<%d>", level);
695
 
        io[0].iov_base = levelstr;
696
 
        io[0].iov_len = strlen(levelstr);
697
 
        io[1].iov_base = buf;
698
 
        io[1].iov_len = len;
699
 
        memset(&msg, 0, sizeof(msg));
700
 
        msg.msg_iov = io;
701
 
        msg.msg_iovlen = 2;
702
 
 
703
 
        idx = 0;
704
 
        while (dst) {
705
 
                next = dst->next;
706
 
                if (level >= dst->debug_level) {
707
 
                        wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
708
 
                                    (u8 *) dst->addr.sun_path, dst->addrlen);
709
 
                        msg.msg_name = &dst->addr;
710
 
                        msg.msg_namelen = dst->addrlen;
711
 
                        if (sendmsg(wpa_s->ctrl_sock, &msg, 0) < 0) {
712
 
                                fprintf(stderr, "CTRL_IFACE monitor[%d]: ",
713
 
                                        idx);
714
 
                                perror("sendmsg");
715
 
                                dst->errors++;
716
 
                                if (dst->errors > 10) {
717
 
                                        wpa_supplicant_ctrl_iface_detach(
718
 
                                                wpa_s, &dst->addr,
719
 
                                                dst->addrlen);
720
 
                                }
721
 
                        } else
722
 
                                dst->errors = 0;
723
 
                }
724
 
                idx++;
725
 
                dst = next;
726
 
        }
727
 
#endif /* CONFIG_CTRL_IFACE_UDP */
 
1205
 
 
1206
        *resp_len = reply_len;
 
1207
        return reply;
 
1208
}
 
1209
 
 
1210
 
 
1211
static int wpa_supplicant_global_iface_add(struct wpa_global *global,
 
1212
                                           char *cmd)
 
1213
{
 
1214
        struct wpa_interface iface;
 
1215
        char *pos;
 
1216
 
 
1217
        /*
 
1218
         * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
 
1219
         * TAB<bridge_ifname>
 
1220
         */
 
1221
        wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
 
1222
 
 
1223
        memset(&iface, 0, sizeof(iface));
 
1224
 
 
1225
        do {
 
1226
                iface.ifname = pos = cmd;
 
1227
                pos = strchr(pos, '\t');
 
1228
                if (pos)
 
1229
                        *pos++ = '\0';
 
1230
                if (iface.ifname[0] == '\0')
 
1231
                        return -1;
 
1232
                if (pos == NULL)
 
1233
                        break;
 
1234
 
 
1235
                iface.confname = pos;
 
1236
                pos = strchr(pos, '\t');
 
1237
                if (pos)
 
1238
                        *pos++ = '\0';
 
1239
                if (iface.confname[0] == '\0')
 
1240
                        iface.confname = NULL;
 
1241
                if (pos == NULL)
 
1242
                        break;
 
1243
 
 
1244
                iface.driver = pos;
 
1245
                pos = strchr(pos, '\t');
 
1246
                if (pos)
 
1247
                        *pos++ = '\0';
 
1248
                if (iface.driver[0] == '\0')
 
1249
                        iface.driver = NULL;
 
1250
                if (pos == NULL)
 
1251
                        break;
 
1252
 
 
1253
                iface.ctrl_interface = pos;
 
1254
                pos = strchr(pos, '\t');
 
1255
                if (pos)
 
1256
                        *pos++ = '\0';
 
1257
                if (iface.ctrl_interface[0] == '\0')
 
1258
                        iface.ctrl_interface = NULL;
 
1259
                if (pos == NULL)
 
1260
                        break;
 
1261
 
 
1262
                iface.driver_param = pos;
 
1263
                pos = strchr(pos, '\t');
 
1264
                if (pos)
 
1265
                        *pos++ = '\0';
 
1266
                if (iface.driver_param[0] == '\0')
 
1267
                        iface.driver_param = NULL;
 
1268
                if (pos == NULL)
 
1269
                        break;
 
1270
 
 
1271
                iface.bridge_ifname = pos;
 
1272
                pos = strchr(pos, '\t');
 
1273
                if (pos)
 
1274
                        *pos++ = '\0';
 
1275
                if (iface.bridge_ifname[0] == '\0')
 
1276
                        iface.bridge_ifname = NULL;
 
1277
                if (pos == NULL)
 
1278
                        break;
 
1279
        } while (0);
 
1280
 
 
1281
        if (wpa_supplicant_get_iface(global, iface.ifname))
 
1282
                return -1;
 
1283
 
 
1284
        return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
 
1285
}
 
1286
 
 
1287
 
 
1288
static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
 
1289
                                              char *cmd)
 
1290
{
 
1291
        struct wpa_supplicant *wpa_s;
 
1292
 
 
1293
        wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
 
1294
 
 
1295
        wpa_s = wpa_supplicant_get_iface(global, cmd);
 
1296
        if (wpa_s == NULL)
 
1297
                return -1;
 
1298
        return wpa_supplicant_remove_iface(global, wpa_s);
 
1299
}
 
1300
 
 
1301
 
 
1302
static int wpa_supplicant_global_iface_interfaces(struct wpa_global *global,
 
1303
                                                  char *buf, int len)
 
1304
{
 
1305
        int res;
 
1306
        char *pos, *end;
 
1307
        struct wpa_supplicant *wpa_s;
 
1308
 
 
1309
        wpa_s = global->ifaces;
 
1310
        pos = buf;
 
1311
        end = buf + len;
 
1312
 
 
1313
        while (wpa_s) {
 
1314
                res = snprintf(pos, end - pos, "%s\n", wpa_s->ifname);
 
1315
                if (res < 0 || res >= end - pos) {
 
1316
                        *pos = '\0';
 
1317
                        break;
 
1318
                }
 
1319
                pos += res;
 
1320
                wpa_s = wpa_s->next;
 
1321
        }
 
1322
        return pos - buf;
 
1323
}
 
1324
 
 
1325
 
 
1326
char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global,
 
1327
                                                char *buf, size_t *resp_len)
 
1328
{
 
1329
        char *reply;
 
1330
        const int reply_size = 2048;
 
1331
        int reply_len;
 
1332
 
 
1333
        wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
 
1334
                          (const u8 *) buf, strlen(buf));
 
1335
 
 
1336
        reply = malloc(reply_size);
 
1337
        if (reply == NULL) {
 
1338
                *resp_len = 1;
 
1339
                return NULL;
 
1340
        }
 
1341
 
 
1342
        memcpy(reply, "OK\n", 3);
 
1343
        reply_len = 3;
 
1344
 
 
1345
        if (strcmp(buf, "PING") == 0) {
 
1346
                memcpy(reply, "PONG\n", 5);
 
1347
                reply_len = 5;
 
1348
        } else if (strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
 
1349
                if (wpa_supplicant_global_iface_add(global, buf + 14))
 
1350
                        reply_len = -1;
 
1351
        } else if (strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
 
1352
                if (wpa_supplicant_global_iface_remove(global, buf + 17))
 
1353
                        reply_len = -1;
 
1354
        } else if (strcmp(buf, "INTERFACES") == 0) {
 
1355
                reply_len = wpa_supplicant_global_iface_interfaces(
 
1356
                        global, reply, reply_size);
 
1357
        } else {
 
1358
                memcpy(reply, "UNKNOWN COMMAND\n", 16);
 
1359
                reply_len = 16;
 
1360
        }
 
1361
 
 
1362
        if (reply_len < 0) {
 
1363
                memcpy(reply, "FAIL\n", 5);
 
1364
                reply_len = 5;
 
1365
        }
 
1366
 
 
1367
        *resp_len = reply_len;
 
1368
        return reply;
728
1369
}