Add a remote host capability for both the source and target directory
[dragonfly.git] / contrib / wpa_supplicant-0.4.9 / ctrl_iface.c
1 /*
2  * WPA Supplicant / UNIX domain and UDP socket -based control interface
3  * Copyright (c) 2004-2005, Jouni Malinen <jkmaline@cc.hut.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #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 <netinet/in.h>
25 #include <arpa/inet.h>
26 #include <sys/un.h>
27 #include <sys/uio.h>
28 #endif /* CONFIG_NATIVE_WINDOWS */
29
30 #include "common.h"
31 #include "eloop.h"
32 #include "wpa.h"
33 #include "wpa_supplicant.h"
34 #include "config.h"
35 #include "eapol_sm.h"
36 #include "wpa_supplicant_i.h"
37 #include "ctrl_iface.h"
38 #include "l2_packet.h"
39 #include "preauth.h"
40 #include "wpa_ctrl.h"
41 #include "eap.h"
42
43
44 #ifdef CONFIG_CTRL_IFACE_UDP
45 #define CTRL_IFACE_SOCK struct sockaddr_in
46 #else /* CONFIG_CTRL_IFACE_UDP */
47 #define CTRL_IFACE_SOCK struct sockaddr_un
48 #endif /* CONFIG_CTRL_IFACE_UDP */
49
50
51 /**
52  * struct wpa_ctrl_dst - Internal data structure of control interface monitors
53  *
54  * This structure is used to store information about registered control
55  * interface monitors into struct wpa_supplicant. This data is private to
56  * ctrl_iface.c and should not be touched directly from other files.
57  */
58 struct wpa_ctrl_dst {
59         struct wpa_ctrl_dst *next;
60         CTRL_IFACE_SOCK addr;
61         socklen_t addrlen;
62         int debug_level;
63         int errors;
64 };
65
66
67 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
68                                          char *cmd)
69 {
70         char *value;
71         int ret = 0;
72
73         value = strchr(cmd, ' ');
74         if (value == NULL)
75                 return -1;
76         *value++ = '\0';
77
78         wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
79         if (strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
80                 eapol_sm_configure(wpa_s->eapol,
81                                    atoi(value), -1, -1, -1);
82         } else if (strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
83                 eapol_sm_configure(wpa_s->eapol,
84                                    -1, atoi(value), -1, -1);
85         } else if (strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
86                 eapol_sm_configure(wpa_s->eapol,
87                                    -1, -1, atoi(value), -1);
88         } else if (strcasecmp(cmd, "EAPOL::maxStart") == 0) {
89                 eapol_sm_configure(wpa_s->eapol,
90                                    -1, -1, -1, atoi(value));
91         } else if (strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
92                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
93                                      atoi(value)))
94                         ret = -1;
95         } else if (strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 0) {
96                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
97                                      atoi(value)))
98                         ret = -1;
99         } else if (strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
100                 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
101                         ret = -1;
102         } else
103                 ret = -1;
104
105         return ret;
106 }
107
108
109 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
110                                              char *addr)
111 {
112         u8 bssid[ETH_ALEN];
113
114         if (hwaddr_aton(addr, bssid)) {
115                 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
116                            "'%s'", addr);
117                 return -1;
118         }
119
120         wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
121         rsn_preauth_deinit(wpa_s->wpa);
122         if (rsn_preauth_init(wpa_s->wpa, bssid, wpa_s->current_ssid))
123                 return -1;
124
125         return 0;
126 }
127
128
129 static int wpa_supplicant_ctrl_iface_attach(struct wpa_supplicant *wpa_s,
130                                             CTRL_IFACE_SOCK *from,
131                                             socklen_t fromlen)
132 {
133         struct wpa_ctrl_dst *dst;
134
135         dst = malloc(sizeof(*dst));
136         if (dst == NULL)
137                 return -1;
138         memset(dst, 0, sizeof(*dst));
139         memcpy(&dst->addr, from, sizeof(CTRL_IFACE_SOCK));
140         dst->addrlen = fromlen;
141         dst->debug_level = MSG_INFO;
142         dst->next = wpa_s->ctrl_dst;
143         wpa_s->ctrl_dst = dst;
144 #ifdef CONFIG_CTRL_IFACE_UDP
145         wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
146                    inet_ntoa(from->sin_addr), ntohs(from->sin_port));
147 #else /* CONFIG_CTRL_IFACE_UDP */
148         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
149                     (u8 *) from->sun_path, fromlen - sizeof(from->sun_family));
150 #endif /* CONFIG_CTRL_IFACE_UDP */
151         return 0;
152 }
153
154
155 static int wpa_supplicant_ctrl_iface_detach(struct wpa_supplicant *wpa_s,
156                                             CTRL_IFACE_SOCK *from,
157                                             socklen_t fromlen)
158 {
159         struct wpa_ctrl_dst *dst, *prev = NULL;
160
161         dst = wpa_s->ctrl_dst;
162         while (dst) {
163 #ifdef CONFIG_CTRL_IFACE_UDP
164                 if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
165                     from->sin_port == dst->addr.sin_port) {
166                         if (prev == NULL)
167                                 wpa_s->ctrl_dst = dst->next;
168                         else
169                                 prev->next = dst->next;
170                         free(dst);
171                         wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached "
172                                    "%s:%d", inet_ntoa(from->sin_addr),
173                                    ntohs(from->sin_port));
174                         return 0;
175                 }
176 #else /* CONFIG_CTRL_IFACE_UDP */
177                 if (fromlen == dst->addrlen &&
178                     memcmp(from->sun_path, dst->addr.sun_path,
179                            fromlen - sizeof(from->sun_family)) == 0) {
180                         if (prev == NULL)
181                                 wpa_s->ctrl_dst = dst->next;
182                         else
183                                 prev->next = dst->next;
184                         free(dst);
185                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
186                                     (u8 *) from->sun_path,
187                                     fromlen - sizeof(from->sun_family));
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,
221                            fromlen - sizeof(from->sun_family)) == 0) {
222                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
223                                     "level", (u8 *) from->sun_path,
224                                     fromlen - sizeof(from->sun_family));
225                         dst->debug_level = atoi(level);
226                         return 0;
227                 }
228 #endif /* CONFIG_CTRL_IFACE_UDP */
229                 dst = dst->next;
230         }
231
232         return -1;
233 }
234
235
236 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
237                                               char *rsp)
238 {
239         char *pos, *id_pos;
240         int id;
241         struct wpa_ssid *ssid;
242
243         pos = strchr(rsp, '-');
244         if (pos == NULL)
245                 return -1;
246         *pos++ = '\0';
247         id_pos = pos;
248         pos = strchr(pos, ':');
249         if (pos == NULL)
250                 return -1;
251         *pos++ = '\0';
252         id = atoi(id_pos);
253         wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
254         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
255                               (u8 *) pos, strlen(pos));
256
257         ssid = wpa_config_get_network(wpa_s->conf, id);
258         if (ssid == NULL) {
259                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
260                            "to update", id);
261                 return -1;
262         }
263
264         if (strcmp(rsp, "IDENTITY") == 0) {
265                 free(ssid->identity);
266                 ssid->identity = (u8 *) strdup(pos);
267                 ssid->identity_len = strlen(pos);
268                 ssid->pending_req_identity = 0;
269                 if (ssid == wpa_s->current_ssid)
270                         wpa_s->reassociate = 1;
271         } else if (strcmp(rsp, "PASSWORD") == 0) {
272                 free(ssid->password);
273                 ssid->password = (u8 *) strdup(pos);
274                 ssid->password_len = strlen(pos);
275                 ssid->pending_req_password = 0;
276                 if (ssid == wpa_s->current_ssid)
277                         wpa_s->reassociate = 1;
278         } else if (strcmp(rsp, "NEW_PASSWORD") == 0) {
279                 free(ssid->new_password);
280                 ssid->new_password = (u8 *) strdup(pos);
281                 ssid->new_password_len = strlen(pos);
282                 ssid->pending_req_new_password = 0;
283                 if (ssid == wpa_s->current_ssid)
284                         wpa_s->reassociate = 1;
285         } else if (strcmp(rsp, "PIN") == 0) {
286                 free(ssid->pin);
287                 ssid->pin = strdup(pos);
288                 ssid->pending_req_pin = 0;
289                 if (ssid == wpa_s->current_ssid)
290                         wpa_s->reassociate = 1;
291         } else if (strcmp(rsp, "OTP") == 0) {
292                 free(ssid->otp);
293                 ssid->otp = (u8 *) strdup(pos);
294                 ssid->otp_len = strlen(pos);
295                 free(ssid->pending_req_otp);
296                 ssid->pending_req_otp = NULL;
297                 ssid->pending_req_otp_len = 0;
298         } else if (strcmp(rsp, "PASSPHRASE") == 0) {
299                 free(ssid->private_key_passwd);
300                 ssid->private_key_passwd = (u8 *) strdup(pos);
301                 ssid->pending_req_passphrase = 0;
302                 if (ssid == wpa_s->current_ssid)
303                         wpa_s->reassociate = 1;
304         } else {
305                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
306                 return -1;
307         }
308
309         return 0;
310 }
311
312
313 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
314                                             const char *params,
315                                             char *buf, size_t buflen)
316 {
317         char *pos, *end, tmp[30];
318         int res, verbose;
319
320         verbose = strcmp(params, "-VERBOSE") == 0;
321         pos = buf;
322         end = buf + buflen;
323         if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
324                 pos += snprintf(pos, end - pos, "bssid=" MACSTR "\n",
325                                 MAC2STR(wpa_s->bssid));
326                 if (wpa_s->current_ssid) {
327                         pos += snprintf(pos, end - pos, "ssid=%s\n",
328                                         wpa_ssid_txt(wpa_s->current_ssid->ssid,
329                                                      wpa_s->current_ssid->
330                                                      ssid_len));
331                 }
332
333                 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
334         }
335         pos += snprintf(pos, end - pos, "wpa_state=%s\n",
336                         wpa_supplicant_state_txt(wpa_s->wpa_state));
337
338         if (wpa_s->l2 &&
339             l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0)
340                 pos += snprintf(pos, end - pos, "ip_address=%s\n", tmp);
341
342         if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
343             wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
344                 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
345                                           verbose);
346                 if (res >= 0)
347                         pos += res;
348         }
349
350         res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
351         if (res >= 0)
352                 pos += res;
353
354         return pos - buf;
355 }
356
357
358 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
359                                            char *cmd)
360 {
361         char *pos;
362         int id;
363         struct wpa_ssid *ssid;
364         u8 bssid[ETH_ALEN];
365
366         /* cmd: "<network id> <BSSID>" */
367         pos = strchr(cmd, ' ');
368         if (pos == NULL)
369                 return -1;
370         *pos++ = '\0';
371         id = atoi(cmd);
372         wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
373         if (hwaddr_aton(pos, bssid)) {
374                 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
375                 return -1;
376         }
377
378         ssid = wpa_config_get_network(wpa_s->conf, id);
379         if (ssid == NULL) {
380                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
381                            "to update", id);
382                 return -1;
383         }
384
385         memcpy(ssid->bssid, bssid, ETH_ALEN);
386         ssid->bssid_set =
387                 memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0;
388                 
389
390         return 0;
391 }
392
393
394 static int wpa_supplicant_ctrl_iface_list_networks(
395         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
396 {
397         char *pos, *end;
398         struct wpa_ssid *ssid;
399
400         pos = buf;
401         end = buf + buflen;
402         pos += snprintf(pos, end - pos, "network id / ssid / bssid / flags\n");
403
404         ssid = wpa_s->conf->ssid;
405         while (ssid) {
406                 pos += snprintf(pos, end - pos, "%d\t%s",
407                                 ssid->id,
408                                 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
409                 if (ssid->bssid_set) {
410                         pos += snprintf(pos, end - pos, "\t" MACSTR,
411                                         MAC2STR(ssid->bssid));
412                 } else {
413                         pos += snprintf(pos, end - pos, "\tany");
414                 }
415                 pos += snprintf(pos, end - pos, "\t%s%s",
416                                 ssid == wpa_s->current_ssid ? "[CURRENT]" : "",
417                                 ssid->disabled ? "[DISABLED]" : "");
418                 pos += snprintf(pos, end - pos, "\n");
419
420                 ssid = ssid->next;
421         }
422
423         return pos - buf;
424 }
425
426
427 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
428 {
429         int first = 1;
430         pos += snprintf(pos, end - pos, "-");
431         if (cipher & WPA_CIPHER_NONE) {
432                 pos += snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
433                 first = 0;
434         }
435         if (cipher & WPA_CIPHER_WEP40) {
436                 pos += snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
437                 first = 0;
438         }
439         if (cipher & WPA_CIPHER_WEP104) {
440                 pos += snprintf(pos, end - pos, "%sWEP104", first ? "" : "+");
441                 first = 0;
442         }
443         if (cipher & WPA_CIPHER_TKIP) {
444                 pos += snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
445                 first = 0;
446         }
447         if (cipher & WPA_CIPHER_CCMP) {
448                 pos += snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
449                 first = 0;
450         }
451         return pos;
452 }
453
454
455 static char * wpa_supplicant_ie_txt(struct wpa_supplicant *wpa_s,
456                                     char *pos, char *end, const char *proto,
457                                     const u8 *ie, size_t ie_len)
458 {
459         struct wpa_ie_data data;
460         int first;
461
462         pos += snprintf(pos, end - pos, "[%s-", proto);
463
464         if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
465                 pos += snprintf(pos, end - pos, "?]");
466                 return pos;
467         }
468
469         first = 1;
470         if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
471                 pos += snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
472                 first = 0;
473         }
474         if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
475                 pos += snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
476                 first = 0;
477         }
478         if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
479                 pos += snprintf(pos, end - pos, "%sNone", first ? "" : "+");
480                 first = 0;
481         }
482
483         pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
484
485         if (data.capabilities & WPA_CAPABILITY_PREAUTH)
486                 pos += snprintf(pos, end - pos, "-preauth");
487
488         pos += snprintf(pos, end - pos, "]");
489
490         return pos;
491 }
492
493
494 static int wpa_supplicant_ctrl_iface_scan_results(
495         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
496 {
497         char *pos, *end;
498         struct wpa_scan_result *res;
499         int i;
500
501         if (wpa_s->scan_results == NULL &&
502             wpa_supplicant_get_scan_results(wpa_s) < 0)
503                 return 0;
504
505         pos = buf;
506         end = buf + buflen;
507         pos += snprintf(pos, end - pos, "bssid / frequency / signal level / "
508                         "flags / ssid\n");
509
510         for (i = 0; i < wpa_s->num_scan_results; i++) {
511                 res = &wpa_s->scan_results[i];
512                 pos += snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
513                                 MAC2STR(res->bssid), res->freq, res->level);
514                 if (res->wpa_ie_len) {
515                         pos = wpa_supplicant_ie_txt(wpa_s, pos, end, "WPA",
516                                                     res->wpa_ie,
517                                                     res->wpa_ie_len);
518                 }
519                 if (res->rsn_ie_len) {
520                         pos = wpa_supplicant_ie_txt(wpa_s, pos, end, "WPA2",
521                                                     res->rsn_ie,
522                                                     res->rsn_ie_len);
523                 }
524                 if (!res->wpa_ie_len && !res->rsn_ie_len &&
525                     res->caps & IEEE80211_CAP_PRIVACY)
526                         pos += snprintf(pos, end - pos, "[WEP]");
527                 if (res->caps & IEEE80211_CAP_IBSS)
528                         pos += snprintf(pos, end - pos, "[IBSS]");
529
530                 pos += snprintf(pos, end - pos, "\t%s",
531                                 wpa_ssid_txt(res->ssid, res->ssid_len));
532
533                 pos += snprintf(pos, end - pos, "\n");
534         }
535
536         return pos - buf;
537 }
538
539
540 static int wpa_supplicant_ctrl_iface_select_network(
541         struct wpa_supplicant *wpa_s, char *cmd)
542 {
543         int id;
544         struct wpa_ssid *ssid;
545
546         /* cmd: "<network id>" or "any" */
547         if (strcmp(cmd, "any") == 0) {
548                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
549                 ssid = wpa_s->conf->ssid;
550                 while (ssid) {
551                         ssid->disabled = 0;
552                         ssid = ssid->next;
553                 }
554                 wpa_s->reassociate = 1;
555                 wpa_supplicant_req_scan(wpa_s, 0, 0);
556                 return 0;
557         }
558
559         id = atoi(cmd);
560         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
561
562         ssid = wpa_config_get_network(wpa_s->conf, id);
563         if (ssid == NULL) {
564                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
565                            "id=%d", id);
566                 return -1;
567         }
568
569         if (ssid != wpa_s->current_ssid && wpa_s->current_ssid)
570                 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
571
572         /* Mark all other networks disabled and trigger reassociation */
573         ssid = wpa_s->conf->ssid;
574         while (ssid) {
575                 ssid->disabled = id != ssid->id;
576                 ssid = ssid->next;
577         }
578         wpa_s->reassociate = 1;
579         wpa_supplicant_req_scan(wpa_s, 0, 0);
580
581         return 0;
582 }
583
584
585 static int wpa_supplicant_ctrl_iface_enable_network(
586         struct wpa_supplicant *wpa_s, char *cmd)
587 {
588         int id;
589         struct wpa_ssid *ssid;
590
591         /* cmd: "<network id>" */
592         id = atoi(cmd);
593         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
594
595         ssid = wpa_config_get_network(wpa_s->conf, id);
596         if (ssid == NULL) {
597                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
598                            "id=%d", id);
599                 return -1;
600         }
601
602         if (wpa_s->current_ssid == NULL && ssid->disabled) {
603                 /*
604                  * Try to reassociate since there is no current configuration
605                  * and a new network was made available. */
606                 wpa_s->reassociate = 1;
607                 wpa_supplicant_req_scan(wpa_s, 0, 0);
608         }
609         ssid->disabled = 0;
610
611         return 0;
612 }
613
614
615 static int wpa_supplicant_ctrl_iface_disable_network(
616         struct wpa_supplicant *wpa_s, char *cmd)
617 {
618         int id;
619         struct wpa_ssid *ssid;
620
621         /* cmd: "<network id>" */
622         id = atoi(cmd);
623         wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
624
625         ssid = wpa_config_get_network(wpa_s->conf, id);
626         if (ssid == NULL) {
627                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
628                            "id=%d", id);
629                 return -1;
630         }
631
632         if (ssid == wpa_s->current_ssid)
633                 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
634         ssid->disabled = 1;
635
636         return 0;
637 }
638
639
640 static int wpa_supplicant_ctrl_iface_add_network(
641         struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
642 {
643         struct wpa_ssid *ssid;
644
645         wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
646
647         ssid = wpa_config_add_network(wpa_s->conf);
648         if (ssid == NULL)
649                 return -1;
650         ssid->disabled = 1;
651         wpa_config_set_network_defaults(ssid);
652
653         return snprintf(buf, buflen, "%d\n", ssid->id);
654 }
655
656
657 static int wpa_supplicant_ctrl_iface_remove_network(
658         struct wpa_supplicant *wpa_s, char *cmd)
659 {
660         int id;
661         struct wpa_ssid *ssid;
662
663         /* cmd: "<network id>" */
664         id = atoi(cmd);
665         wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
666
667         ssid = wpa_config_get_network(wpa_s->conf, id);
668         if (ssid == NULL ||
669             wpa_config_remove_network(wpa_s->conf, id) < 0) {
670                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
671                            "id=%d", id);
672                 return -1;
673         }
674
675         if (ssid == wpa_s->current_ssid)
676                 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
677
678         return 0;
679 }
680
681
682 static int wpa_supplicant_ctrl_iface_set_network(
683         struct wpa_supplicant *wpa_s, char *cmd)
684 {
685         int id;
686         struct wpa_ssid *ssid;
687         char *name, *value;
688
689         /* cmd: "<network id> <variable name> <value>" */
690         name = strchr(cmd, ' ');
691         if (name == NULL)
692                 return -1;
693         *name++ = '\0';
694
695         value = strchr(name, ' ');
696         if (value == NULL)
697                 return -1;
698         *value++ = '\0';
699
700         id = atoi(cmd);
701         wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
702                    id, name);
703         wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
704                               (u8 *) value, strlen(value));
705
706         ssid = wpa_config_get_network(wpa_s->conf, id);
707         if (ssid == NULL) {
708                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
709                            "id=%d", id);
710                 return -1;
711         }
712
713         if (wpa_config_set(ssid, name, value, 0) < 0) {
714                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
715                            "variable '%s'", name);
716                 return -1;
717         }
718
719         if ((strcmp(name, "psk") == 0 && value[0] == '"' && ssid->ssid_len) ||
720             (strcmp(name, "ssid") == 0 && ssid->passphrase))
721                 wpa_config_update_psk(ssid);
722
723         return 0;
724 }
725
726
727 static int wpa_supplicant_ctrl_iface_get_network(
728         struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
729 {
730         int id;
731         struct wpa_ssid *ssid;
732         char *name, *value;
733
734         /* cmd: "<network id> <variable name>" */
735         name = strchr(cmd, ' ');
736         if (name == NULL)
737                 return -1;
738         *name++ = '\0';
739
740         id = atoi(cmd);
741         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
742                    id, name);
743
744         ssid = wpa_config_get_network(wpa_s->conf, id);
745         if (ssid == NULL) {
746                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
747                            "id=%d", id);
748                 return -1;
749         }
750
751         value = wpa_config_get(ssid, name);
752         if (value == NULL) {
753                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
754                            "variable '%s'", name);
755                 return -1;
756         }
757
758         snprintf(buf, buflen, "%s", value);
759
760         free(value);
761
762         return strlen(buf);
763 }
764
765
766 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
767 {
768         int ret;
769
770         if (!wpa_s->conf->update_config) {
771                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
772                            "to update configuration (update_config=0)");
773                 return -1;
774         }
775
776         ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
777         if (ret) {
778                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
779                            "update configuration");
780         } else {
781                 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
782                            " updated");
783         }
784
785         return ret;
786 }
787
788
789 static int wpa_supplicant_ctrl_iface_get_capability(
790         struct wpa_supplicant *wpa_s, const char *field, char *buf,
791         size_t buflen)
792 {
793         struct wpa_driver_capa capa;
794         int res, first = 1;
795         char *pos, *end;
796
797         wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'", field);
798
799         if (strcmp(field, "eap") == 0) {
800                 return eap_get_names(buf, buflen);
801         }
802
803         res = wpa_drv_get_capa(wpa_s, &capa);
804
805         pos = buf;
806         end = pos + buflen;
807
808         if (strcmp(field, "pairwise") == 0) {
809                 if (res < 0)
810                         return snprintf(buf, buflen, "CCMP TKIP NONE");
811
812                 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
813                         pos += snprintf(pos, end - pos, "%sCCMP",
814                                         first ? "" : " ");
815                         first = 0;
816                 }
817
818                 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
819                         pos += snprintf(pos, end - pos, "%sTKIP",
820                                         first ? "" : " ");
821                         first = 0;
822                 }
823
824                 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
825                         pos += snprintf(pos, end - pos, "%sNONE",
826                                         first ? "" : " ");
827                         first = 0;
828                 }
829
830                 return pos - buf;
831         }
832
833         if (strcmp(field, "group") == 0) {
834                 if (res < 0)
835                         return snprintf(buf, buflen, "CCMP TKIP WEP104 WEP40");
836
837                 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
838                         pos += snprintf(pos, end - pos, "%sCCMP",
839                                         first ? "" : " ");
840                         first = 0;
841                 }
842
843                 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
844                         pos += snprintf(pos, end - pos, "%sTKIP",
845                                         first ? "" : " ");
846                         first = 0;
847                 }
848
849                 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
850                         pos += snprintf(pos, end - pos, "%sWEP104",
851                                         first ? "" : " ");
852                         first = 0;
853                 }
854
855                 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
856                         pos += snprintf(pos, end - pos, "%sWEP40",
857                                         first ? "" : " ");
858                         first = 0;
859                 }
860
861                 return pos - buf;
862         }
863
864         if (strcmp(field, "key_mgmt") == 0) {
865                 if (res < 0) {
866                         return snprintf(buf, buflen, "WPA-PSK WPA-EAP "
867                                         "IEEE8021X WPA-NONE NONE");
868                 }
869
870                 pos += snprintf(pos, end - pos, "NONE IEEE8021X");
871
872                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
873                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA2))
874                         pos += snprintf(pos, end - pos, " WPA-EAP");
875
876                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
877                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK))
878                         pos += snprintf(pos, end - pos, " WPA-PSK");
879
880                 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE)
881                         pos += snprintf(pos, end - pos, " WPA-NONE");
882
883                 return pos - buf;
884         }
885
886         if (strcmp(field, "proto") == 0) {
887                 if (res < 0)
888                         return snprintf(buf, buflen, "RSN WPA");
889
890                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
891                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
892                         pos += snprintf(pos, end - pos, "%sRSN",
893                                         first ? "" : " ");
894                         first = 0;
895                 }
896
897                 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
898                                      WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
899                         pos += snprintf(pos, end - pos, "%sWPA",
900                                         first ? "" : " ");
901                         first = 0;
902                 }
903
904                 return pos - buf;
905         }
906
907         if (strcmp(field, "auth_alg") == 0) {
908                 if (res < 0)
909                         return snprintf(buf, buflen, "OPEN SHARED LEAP");
910
911                 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
912                         pos += snprintf(pos, end - pos, "%sOPEN",
913                                         first ? "" : " ");
914                         first = 0;
915                 }
916
917                 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
918                         pos += snprintf(pos, end - pos, "%sSHARED",
919                                         first ? "" : " ");
920                         first = 0;
921                 }
922
923                 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
924                         pos += snprintf(pos, end - pos, "%sLEAP",
925                                         first ? "" : " ");
926                         first = 0;
927                 }
928
929                 return pos - buf;
930         }
931
932         wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
933                    field);
934
935         return -1;
936 }
937
938
939 static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
940                                               void *sock_ctx)
941 {
942         struct wpa_supplicant *wpa_s = eloop_ctx;
943         char buf[256];
944         int res;
945         CTRL_IFACE_SOCK from;
946         socklen_t fromlen = sizeof(from);
947         char *reply;
948         const int reply_size = 2048;
949         int reply_len;
950         int new_attached = 0, ctrl_rsp = 0;
951
952         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
953                        (struct sockaddr *) &from, &fromlen);
954         if (res < 0) {
955                 perror("recvfrom(ctrl_iface)");
956                 return;
957         }
958         buf[res] = '\0';
959         if (strncmp(buf, WPA_CTRL_RSP, strlen(WPA_CTRL_RSP)) == 0 ||
960             strncmp(buf, "SET_NETWORK ", 12) == 0) {
961                 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
962                                       (u8 *) buf, res);
963         } else {
964                 wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (u8 *) buf, res);
965         }
966
967         reply = malloc(reply_size);
968         if (reply == NULL) {
969                 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
970                        fromlen);
971                 return;
972         }
973
974         memcpy(reply, "OK\n", 3);
975         reply_len = 3;
976
977         if (strcmp(buf, "PING") == 0) {
978                 memcpy(reply, "PONG\n", 5);
979                 reply_len = 5;
980         } else if (strcmp(buf, "MIB") == 0) {
981                 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
982                 if (reply_len >= 0) {
983                         res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
984                                                reply_size - reply_len);
985                         if (res < 0)
986                                 reply_len = -1;
987                         else
988                                 reply_len += res;
989                 }
990         } else if (strncmp(buf, "STATUS", 6) == 0) {
991                 reply_len = wpa_supplicant_ctrl_iface_status(
992                         wpa_s, buf + 6, reply, reply_size);
993         } else if (strcmp(buf, "PMKSA") == 0) {
994                 reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size);
995         } else if (strncmp(buf, "SET ", 4) == 0) {
996                 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
997                         reply_len = -1;
998         } else if (strcmp(buf, "LOGON") == 0) {
999                 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
1000         } else if (strcmp(buf, "LOGOFF") == 0) {
1001                 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
1002         } else if (strcmp(buf, "REASSOCIATE") == 0) {
1003                 wpa_s->disconnected = 0;
1004                 wpa_s->reassociate = 1;
1005                 wpa_supplicant_req_scan(wpa_s, 0, 0);
1006         } else if (strncmp(buf, "PREAUTH ", 8) == 0) {
1007                 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
1008                         reply_len = -1;
1009         } else if (strcmp(buf, "ATTACH") == 0) {
1010                 if (wpa_supplicant_ctrl_iface_attach(wpa_s, &from, fromlen))
1011                         reply_len = -1;
1012                 else
1013                         new_attached = 1;
1014         } else if (strcmp(buf, "DETACH") == 0) {
1015                 if (wpa_supplicant_ctrl_iface_detach(wpa_s, &from, fromlen))
1016                         reply_len = -1;
1017         } else if (strncmp(buf, "LEVEL ", 6) == 0) {
1018                 if (wpa_supplicant_ctrl_iface_level(wpa_s, &from, fromlen,
1019                                                     buf + 6))
1020                         reply_len = -1;
1021         } else if (strncmp(buf, WPA_CTRL_RSP, strlen(WPA_CTRL_RSP)) == 0) {
1022                 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
1023                             wpa_s, buf + strlen(WPA_CTRL_RSP)))
1024                         reply_len = -1;
1025                 else
1026                         ctrl_rsp = 1;
1027         } else if (strcmp(buf, "RECONFIGURE") == 0) {
1028                 if (wpa_supplicant_reload_configuration(wpa_s))
1029                         reply_len = -1;
1030         } else if (strcmp(buf, "TERMINATE") == 0) {
1031                 eloop_terminate();
1032         } else if (strncmp(buf, "BSSID ", 6) == 0) {
1033                 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
1034                         reply_len = -1;
1035         } else if (strcmp(buf, "LIST_NETWORKS") == 0) {
1036                 reply_len = wpa_supplicant_ctrl_iface_list_networks(
1037                         wpa_s, reply, reply_size);
1038         } else if (strcmp(buf, "DISCONNECT") == 0) {
1039                 wpa_s->disconnected = 1;
1040                 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
1041         } else if (strcmp(buf, "SCAN") == 0) {
1042                 wpa_s->scan_req = 2;
1043                 wpa_supplicant_req_scan(wpa_s, 0, 0);
1044         } else if (strcmp(buf, "SCAN_RESULTS") == 0) {
1045                 reply_len = wpa_supplicant_ctrl_iface_scan_results(
1046                         wpa_s, reply, reply_size);
1047         } else if (strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
1048                 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
1049                         reply_len = -1;
1050         } else if (strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
1051                 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
1052                         reply_len = -1;
1053         } else if (strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
1054                 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
1055                         reply_len = -1;
1056         } else if (strcmp(buf, "ADD_NETWORK") == 0) {
1057                 reply_len = wpa_supplicant_ctrl_iface_add_network(
1058                         wpa_s, reply, reply_size);
1059         } else if (strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
1060                 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
1061                         reply_len = -1;
1062         } else if (strncmp(buf, "SET_NETWORK ", 12) == 0) {
1063                 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
1064                         reply_len = -1;
1065         } else if (strncmp(buf, "GET_NETWORK ", 12) == 0) {
1066                 reply_len = wpa_supplicant_ctrl_iface_get_network(
1067                         wpa_s, buf + 12, reply, reply_size);
1068         } else if (strcmp(buf, "SAVE_CONFIG") == 0) {
1069                 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
1070                         reply_len = -1;
1071         } else if (strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
1072                 reply_len = wpa_supplicant_ctrl_iface_get_capability(
1073                         wpa_s, buf + 15, reply, reply_size);
1074         } else {
1075                 memcpy(reply, "UNKNOWN COMMAND\n", 16);
1076                 reply_len = 16;
1077         }
1078
1079         if (reply_len < 0) {
1080                 memcpy(reply, "FAIL\n", 5);
1081                 reply_len = 5;
1082         }
1083         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
1084         free(reply);
1085
1086         if (new_attached)
1087                 eapol_sm_notify_ctrl_attached(wpa_s->eapol);
1088         if (ctrl_rsp)
1089                 eapol_sm_notify_ctrl_response(wpa_s->eapol);
1090 }
1091
1092
1093 #ifndef CONFIG_CTRL_IFACE_UDP
1094 static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s)
1095 {
1096         char *buf;
1097         size_t len;
1098
1099         if (wpa_s->conf->ctrl_interface == NULL)
1100                 return NULL;
1101
1102         len = strlen(wpa_s->conf->ctrl_interface) + strlen(wpa_s->ifname) + 2;
1103         buf = malloc(len);
1104         if (buf == NULL)
1105                 return NULL;
1106
1107         snprintf(buf, len, "%s/%s",
1108                  wpa_s->conf->ctrl_interface, wpa_s->ifname);
1109 #ifdef __CYGWIN__
1110         {
1111                 /* Windows/WinPcap uses interface names that are not suitable
1112                  * as a file name - convert invalid chars to underscores */
1113                 char *pos = buf;
1114                 while (*pos) {
1115                         if (*pos == '\\')
1116                                 *pos = '_';
1117                         pos++;
1118                 }
1119         }
1120 #endif /* __CYGWIN__ */
1121         return buf;
1122 }
1123 #endif /* CONFIG_CTRL_IFACE_UDP */
1124
1125
1126 /**
1127  * wpa_supplicant_ctrl_iface_init - Initialize control interface
1128  * @wpa_s: Pointer to wpa_supplicant data
1129  * Returns: 0 on success, -1 on failure
1130  *
1131  * Initialize the control interface and start receiving commands from external
1132  * programs.
1133  */
1134 int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
1135 {
1136         CTRL_IFACE_SOCK addr;
1137         int s = -1;
1138 #ifndef CONFIG_CTRL_IFACE_UDP
1139         char *fname = NULL;
1140 #endif /* CONFIG_CTRL_IFACE_UDP */
1141
1142         wpa_s->ctrl_sock = -1;
1143
1144         if (wpa_s->conf->ctrl_interface == NULL)
1145                 return 0;
1146
1147 #ifdef CONFIG_CTRL_IFACE_UDP
1148         s = socket(PF_INET, SOCK_DGRAM, 0);
1149         if (s < 0) {
1150                 perror("socket(PF_INET)");
1151                 goto fail;
1152         }
1153
1154         memset(&addr, 0, sizeof(addr));
1155         addr.sin_family = AF_INET;
1156         addr.sin_addr.s_addr = htonl((127 << 24) | 1);
1157         addr.sin_port = htons(WPA_CTRL_IFACE_PORT);
1158         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1159                 perror("bind(AF_INET)");
1160                 goto fail;
1161         }
1162 #else /* CONFIG_CTRL_IFACE_UDP */
1163         if (mkdir(wpa_s->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
1164                 if (errno == EEXIST) {
1165                         wpa_printf(MSG_DEBUG, "Using existing control "
1166                                    "interface directory.");
1167                 } else {
1168                         perror("mkdir[ctrl_interface]");
1169                         goto fail;
1170                 }
1171         }
1172
1173         if (wpa_s->conf->ctrl_interface_gid_set &&
1174             chown(wpa_s->conf->ctrl_interface, 0,
1175                   wpa_s->conf->ctrl_interface_gid) < 0) {
1176                 perror("chown[ctrl_interface]");
1177                 return -1;
1178         }
1179
1180         if (strlen(wpa_s->conf->ctrl_interface) + 1 + strlen(wpa_s->ifname) >=
1181             sizeof(addr.sun_path))
1182                 goto fail;
1183
1184         s = socket(PF_UNIX, SOCK_DGRAM, 0);
1185         if (s < 0) {
1186                 perror("socket(PF_UNIX)");
1187                 goto fail;
1188         }
1189
1190         memset(&addr, 0, sizeof(addr));
1191         addr.sun_family = AF_UNIX;
1192         fname = wpa_supplicant_ctrl_iface_path(wpa_s);
1193         if (fname == NULL)
1194                 goto fail;
1195         strncpy(addr.sun_path, fname, sizeof(addr.sun_path));
1196         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1197                 perror("bind(PF_UNIX)");
1198                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1199                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1200                                    " allow connections - assuming it was left"
1201                                    "over from forced program termination");
1202                         if (unlink(fname) < 0) {
1203                                 perror("unlink[ctrl_iface]");
1204                                 wpa_printf(MSG_ERROR, "Could not unlink "
1205                                            "existing ctrl_iface socket '%s'",
1206                                            fname);
1207                                 goto fail;
1208                         }
1209                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
1210                             0) {
1211                                 perror("bind(PF_UNIX)");
1212                                 goto fail;
1213                         }
1214                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1215                                    "ctrl_iface socket '%s'", fname);
1216                 } else {
1217                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1218                                    "be in use - cannot override it");
1219                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1220                                    "not used anymore", fname);
1221                         free(fname);
1222                         fname = NULL;
1223                         goto fail;
1224                 }
1225         }
1226
1227         if (wpa_s->conf->ctrl_interface_gid_set &&
1228             chown(fname, 0, wpa_s->conf->ctrl_interface_gid) < 0) {
1229                 perror("chown[ctrl_interface/ifname]");
1230                 goto fail;
1231         }
1232
1233         if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
1234                 perror("chmod[ctrl_interface/ifname]");
1235                 goto fail;
1236         }
1237         free(fname);
1238 #endif /* CONFIG_CTRL_IFACE_UDP */
1239
1240         wpa_s->ctrl_sock = s;
1241         eloop_register_read_sock(s, wpa_supplicant_ctrl_iface_receive, wpa_s,
1242                                  NULL);
1243
1244         return 0;
1245
1246 fail:
1247         if (s >= 0)
1248                 close(s);
1249 #ifndef CONFIG_CTRL_IFACE_UDP
1250         if (fname) {
1251                 unlink(fname);
1252                 free(fname);
1253         }
1254 #endif /* CONFIG_CTRL_IFACE_UDP */
1255         return -1;
1256 }
1257
1258
1259 /**
1260  * wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface
1261  * @wpa_s: Pointer to wpa_supplicant data
1262  *
1263  * Deinitialize the control interface that was initialized with
1264  * wpa_supplicant_ctrl_iface_init().
1265  */
1266 void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s)
1267 {
1268         struct wpa_ctrl_dst *dst, *prev;
1269
1270         if (wpa_s->ctrl_sock > -1) {
1271 #ifndef CONFIG_CTRL_IFACE_UDP
1272                 char *fname;
1273 #endif /* CONFIG_CTRL_IFACE_UDP */
1274                 eloop_unregister_read_sock(wpa_s->ctrl_sock);
1275                 if (wpa_s->ctrl_dst) {
1276                         /*
1277                          * Wait a second before closing the control socket if
1278                          * there are any attached monitors in order to allow
1279                          * them to receive any pending messages.
1280                          */
1281                         wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
1282                                    "monitors to receive messages");
1283                         sleep(1);
1284                 }
1285                 close(wpa_s->ctrl_sock);
1286                 wpa_s->ctrl_sock = -1;
1287 #ifndef CONFIG_CTRL_IFACE_UDP
1288                 fname = wpa_supplicant_ctrl_iface_path(wpa_s);
1289                 if (fname)
1290                         unlink(fname);
1291                 free(fname);
1292
1293                 if (rmdir(wpa_s->conf->ctrl_interface) < 0) {
1294                         if (errno == ENOTEMPTY) {
1295                                 wpa_printf(MSG_DEBUG, "Control interface "
1296                                            "directory not empty - leaving it "
1297                                            "behind");
1298                         } else {
1299                                 perror("rmdir[ctrl_interface]");
1300                         }
1301                 }
1302 #endif /* CONFIG_CTRL_IFACE_UDP */
1303         }
1304
1305         dst = wpa_s->ctrl_dst;
1306         while (dst) {
1307                 prev = dst;
1308                 dst = dst->next;
1309                 free(prev);
1310         }
1311 }
1312
1313
1314 /**
1315  * wpa_supplicant_ctrl_iface_send - Send a control interface packet to monitors
1316  * @wpa_s: Pointer to wpa_supplicant data
1317  * @level: Priority level of the message
1318  * @buf: Message data
1319  * @len: Message length
1320  *
1321  * Send a packet to all monitor programs attached to the control interface.
1322  */
1323 void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level,
1324                                     char *buf, size_t len)
1325 {
1326         struct wpa_ctrl_dst *dst, *next;
1327         char levelstr[10];
1328         int idx;
1329 #ifdef CONFIG_CTRL_IFACE_UDP
1330         char *sbuf;
1331         int llen;
1332
1333         dst = wpa_s->ctrl_dst;
1334         if (wpa_s->ctrl_sock < 0 || dst == NULL)
1335                 return;
1336
1337         snprintf(levelstr, sizeof(levelstr), "<%d>", level);
1338
1339         llen = strlen(levelstr);
1340         sbuf = malloc(llen + len);
1341         if (sbuf == NULL)
1342                 return;
1343
1344         memcpy(sbuf, levelstr, llen);
1345         memcpy(sbuf + llen, buf, len);
1346
1347         idx = 0;
1348         while (dst) {
1349                 next = dst->next;
1350                 if (level >= dst->debug_level) {
1351                         wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
1352                                    inet_ntoa(dst->addr.sin_addr),
1353                                    ntohs(dst->addr.sin_port));
1354                         if (sendto(wpa_s->ctrl_sock, sbuf, llen + len, 0,
1355                                    (struct sockaddr *) &dst->addr,
1356                                    sizeof(dst->addr)) < 0) {
1357                                 perror("sendto(CTRL_IFACE monitor)");
1358                                 dst->errors++;
1359                                 if (dst->errors > 10) {
1360                                         wpa_supplicant_ctrl_iface_detach(
1361                                                 wpa_s, &dst->addr,
1362                                                 dst->addrlen);
1363                                 }
1364                         } else
1365                                 dst->errors = 0;
1366                 }
1367                 idx++;
1368                 dst = next;
1369         }
1370         free(sbuf);
1371 #else /* CONFIG_CTRL_IFACE_UDP */
1372         struct msghdr msg;
1373         struct iovec io[2];
1374
1375         dst = wpa_s->ctrl_dst;
1376         if (wpa_s->ctrl_sock < 0 || dst == NULL)
1377                 return;
1378
1379         snprintf(levelstr, sizeof(levelstr), "<%d>", level);
1380         io[0].iov_base = levelstr;
1381         io[0].iov_len = strlen(levelstr);
1382         io[1].iov_base = buf;
1383         io[1].iov_len = len;
1384         memset(&msg, 0, sizeof(msg));
1385         msg.msg_iov = io;
1386         msg.msg_iovlen = 2;
1387
1388         idx = 0;
1389         while (dst) {
1390                 next = dst->next;
1391                 if (level >= dst->debug_level) {
1392                         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
1393                                     (u8 *) dst->addr.sun_path, dst->addrlen -
1394                                     sizeof(dst->addr.sun_family));
1395                         msg.msg_name = &dst->addr;
1396                         msg.msg_namelen = dst->addrlen;
1397                         if (sendmsg(wpa_s->ctrl_sock, &msg, 0) < 0) {
1398                                 perror("sendmsg(CTRL_IFACE monitor)");
1399                                 dst->errors++;
1400                                 if (dst->errors > 10) {
1401                                         wpa_supplicant_ctrl_iface_detach(
1402                                                 wpa_s, &dst->addr,
1403                                                 dst->addrlen);
1404                                 }
1405                         } else
1406                                 dst->errors = 0;
1407                 }
1408                 idx++;
1409                 dst = next;
1410         }
1411 #endif /* CONFIG_CTRL_IFACE_UDP */
1412 }
1413
1414
1415 /**
1416  * wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor
1417  * @wpa_s: Pointer to wpa_supplicant data
1418  *
1419  * Wait until the first message from an external program using the control
1420  * interface is received. This function can be used to delay normal startup
1421  * processing to allow control interface programs to attach with
1422  * %wpa_supplicant before normal operations are started.
1423  */
1424 void wpa_supplicant_ctrl_iface_wait(struct wpa_supplicant *wpa_s)
1425 {
1426         fd_set rfds;
1427
1428         if (wpa_s->ctrl_sock < 0)
1429                 return;
1430
1431         wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor",
1432                    wpa_s->ifname);
1433
1434         FD_ZERO(&rfds);
1435         FD_SET(wpa_s->ctrl_sock, &rfds);
1436         select(wpa_s->ctrl_sock + 1, &rfds, NULL, NULL, NULL);
1437 }
1438
1439
1440 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
1441                                            char *cmd)
1442 {
1443         struct wpa_interface iface;
1444         char *pos;
1445
1446         /*
1447          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
1448          */
1449         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
1450
1451         memset(&iface, 0, sizeof(iface));
1452
1453         do {
1454                 iface.ifname = pos = cmd;
1455                 pos = strchr(pos, '\t');
1456                 if (pos)
1457                         *pos++ = '\0';
1458                 if (iface.ifname[0] == '\0')
1459                         return -1;
1460                 if (pos == NULL)
1461                         break;
1462
1463                 iface.confname = pos;
1464                 pos = strchr(pos, '\t');
1465                 if (pos)
1466                         *pos++ = '\0';
1467                 if (iface.confname[0] == '\0')
1468                         iface.confname = NULL;
1469                 if (pos == NULL)
1470                         break;
1471
1472                 iface.driver = pos;
1473                 pos = strchr(pos, '\t');
1474                 if (pos)
1475                         *pos++ = '\0';
1476                 if (iface.driver[0] == '\0')
1477                         iface.driver = NULL;
1478                 if (pos == NULL)
1479                         break;
1480
1481                 iface.ctrl_interface = pos;
1482                 pos = strchr(pos, '\t');
1483                 if (pos)
1484                         *pos++ = '\0';
1485                 if (iface.ctrl_interface[0] == '\0')
1486                         iface.ctrl_interface = NULL;
1487                 if (pos == NULL)
1488                         break;
1489
1490                 iface.driver_param = pos;
1491                 pos = strchr(pos, '\t');
1492                 if (pos)
1493                         *pos++ = '\0';
1494                 if (iface.driver_param[0] == '\0')
1495                         iface.driver_param = NULL;
1496                 if (pos == NULL)
1497                         break;
1498         } while (0);
1499
1500         if (wpa_supplicant_get_iface(global, iface.ifname))
1501                 return -1;
1502
1503         return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
1504 }
1505
1506
1507 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
1508                                               char *cmd)
1509 {
1510         struct wpa_supplicant *wpa_s;
1511
1512         wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
1513
1514         wpa_s = wpa_supplicant_get_iface(global, cmd);
1515         if (wpa_s == NULL)
1516                 return -1;
1517         return wpa_supplicant_remove_iface(global, wpa_s);
1518 }
1519
1520
1521 static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
1522                                                      void *sock_ctx)
1523 {
1524         struct wpa_global *global = eloop_ctx;
1525         char buf[256];
1526         int res;
1527         CTRL_IFACE_SOCK from;
1528         socklen_t fromlen = sizeof(from);
1529         char *reply;
1530         const int reply_size = 2048;
1531         int reply_len;
1532
1533         res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
1534                        (struct sockaddr *) &from, &fromlen);
1535         if (res < 0) {
1536                 perror("recvfrom(ctrl_iface)");
1537                 return;
1538         }
1539         buf[res] = '\0';
1540         wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface", (u8 *) buf, res);
1541
1542         reply = malloc(reply_size);
1543         if (reply == NULL) {
1544                 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
1545                        fromlen);
1546                 return;
1547         }
1548
1549         memcpy(reply, "OK\n", 3);
1550         reply_len = 3;
1551
1552         if (strcmp(buf, "PING") == 0) {
1553                 memcpy(reply, "PONG\n", 5);
1554                 reply_len = 5;
1555         } else if (strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
1556                 if (wpa_supplicant_global_iface_add(global, buf + 14))
1557                         reply_len = -1;
1558         } else if (strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
1559                 if (wpa_supplicant_global_iface_remove(global, buf + 17))
1560                         reply_len = -1;
1561         } else {
1562                 memcpy(reply, "UNKNOWN COMMAND\n", 16);
1563                 reply_len = 16;
1564         }
1565
1566         if (reply_len < 0) {
1567                 memcpy(reply, "FAIL\n", 5);
1568                 reply_len = 5;
1569         }
1570         sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
1571         free(reply);
1572 }
1573
1574
1575 /**
1576  * wpa_supplicant_global_ctrl_iface_init - Initialize global control interface
1577  * @global: Pointer to global data from wpa_supplicant_init()
1578  * Returns: 0 on success, -1 on failure
1579  *
1580  * Initialize the global control interface and start receiving commands from
1581  * external programs.
1582  */
1583 int wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
1584 {
1585         CTRL_IFACE_SOCK addr;
1586         int s = -1;
1587
1588         global->ctrl_sock = -1;
1589
1590         if (global->params.ctrl_interface == NULL)
1591                 return 0;
1592
1593         wpa_printf(MSG_DEBUG, "Global control interface '%s'",
1594                    global->params.ctrl_interface);
1595
1596 #ifdef CONFIG_CTRL_IFACE_UDP
1597         s = socket(PF_INET, SOCK_DGRAM, 0);
1598         if (s < 0) {
1599                 perror("socket(PF_INET)");
1600                 goto fail;
1601         }
1602
1603         memset(&addr, 0, sizeof(addr));
1604         addr.sin_family = AF_INET;
1605         addr.sin_addr.s_addr = htonl((127 << 24) | 1);
1606         addr.sin_port = htons(WPA_GLOBAL_CTRL_IFACE_PORT);
1607         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1608                 perror("bind(AF_INET)");
1609                 goto fail;
1610         }
1611 #else /* CONFIG_CTRL_IFACE_UDP */
1612         s = socket(PF_UNIX, SOCK_DGRAM, 0);
1613         if (s < 0) {
1614                 perror("socket(PF_UNIX)");
1615                 goto fail;
1616         }
1617
1618         memset(&addr, 0, sizeof(addr));
1619         addr.sun_family = AF_UNIX;
1620         strncpy(addr.sun_path, global->params.ctrl_interface,
1621                 sizeof(addr.sun_path));
1622         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1623                 perror("bind(PF_UNIX)");
1624                 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
1625                         wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
1626                                    " allow connections - assuming it was left"
1627                                    "over from forced program termination");
1628                         if (unlink(global->params.ctrl_interface) < 0) {
1629                                 perror("unlink[ctrl_iface]");
1630                                 wpa_printf(MSG_ERROR, "Could not unlink "
1631                                            "existing ctrl_iface socket '%s'",
1632                                            global->params.ctrl_interface);
1633                                 goto fail;
1634                         }
1635                         if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
1636                             0) {
1637                                 perror("bind(PF_UNIX)");
1638                                 goto fail;
1639                         }
1640                         wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
1641                                    "ctrl_iface socket '%s'",
1642                                    global->params.ctrl_interface);
1643                 } else {
1644                         wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
1645                                    "be in use - cannot override it");
1646                         wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
1647                                    "not used anymore",
1648                                    global->params.ctrl_interface);
1649                         goto fail;
1650                 }
1651         }
1652 #endif /* CONFIG_CTRL_IFACE_UDP */
1653
1654         global->ctrl_sock = s;
1655         eloop_register_read_sock(s, wpa_supplicant_global_ctrl_iface_receive,
1656                                  global, NULL);
1657
1658         return 0;
1659
1660 fail:
1661         if (s >= 0)
1662                 close(s);
1663         return -1;
1664 }
1665
1666
1667 /**
1668  * wpa_supplicant_global_ctrl_iface_deinit - Deinitialize global ctrl interface
1669  * @global: Pointer to global data from wpa_supplicant_init()
1670  *
1671  * Deinitialize the global control interface that was initialized with
1672  * wpa_supplicant_global_ctrl_iface_init().
1673  */
1674 void wpa_supplicant_global_ctrl_iface_deinit(struct wpa_global *global)
1675 {
1676         if (global->ctrl_sock < 0)
1677                 return;
1678
1679         eloop_unregister_read_sock(global->ctrl_sock);
1680         close(global->ctrl_sock);
1681         global->ctrl_sock = -1;
1682
1683 #ifndef CONFIG_CTRL_IFACE_UDP
1684         if (global->params.ctrl_interface)
1685                 unlink(global->params.ctrl_interface);
1686 #endif /* CONFIG_CTRL_IFACE_UDP */
1687 }