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