00001
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019 #include <unistd.h>
00020 #include <sys/types.h>
00021 #include <sys/stat.h>
00022 #include <errno.h>
00023 #ifndef CONFIG_NATIVE_WINDOWS
00024 #include <sys/socket.h>
00025 #include <netinet/in.h>
00026 #include <arpa/inet.h>
00027 #include <sys/un.h>
00028 #include <sys/uio.h>
00029 #endif
00030
00031 #include "common.h"
00032 #include "eloop.h"
00033 #include "wpa.h"
00034 #include "wpa_supplicant.h"
00035 #include "config.h"
00036 #include "eapol_sm.h"
00037 #include "wpa_supplicant_i.h"
00038 #include "ctrl_iface.h"
00039 #include "l2_packet.h"
00040 #include "preauth.h"
00041 #include "wpa_ctrl.h"
00042 #include "eap.h"
00043
00044
00045 #ifdef CONFIG_CTRL_IFACE_UDP
00046 #define CTRL_IFACE_SOCK struct sockaddr_in
00047 #else
00048 #define CTRL_IFACE_SOCK struct sockaddr_un
00049 #endif
00050
00051
00060 struct wpa_ctrl_dst {
00061 struct wpa_ctrl_dst *next;
00062 CTRL_IFACE_SOCK addr;
00063 socklen_t addrlen;
00064 int debug_level;
00065 int errors;
00066 };
00067
00068
00069 static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
00070 char *cmd)
00071 {
00072 char *value;
00073 int ret = 0;
00074
00075 value = strchr(cmd, ' ');
00076 if (value == NULL)
00077 return -1;
00078 *value++ = '\0';
00079
00080 wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value);
00081 if (strcasecmp(cmd, "EAPOL::heldPeriod") == 0) {
00082 eapol_sm_configure(wpa_s->eapol,
00083 atoi(value), -1, -1, -1);
00084 } else if (strcasecmp(cmd, "EAPOL::authPeriod") == 0) {
00085 eapol_sm_configure(wpa_s->eapol,
00086 -1, atoi(value), -1, -1);
00087 } else if (strcasecmp(cmd, "EAPOL::startPeriod") == 0) {
00088 eapol_sm_configure(wpa_s->eapol,
00089 -1, -1, atoi(value), -1);
00090 } else if (strcasecmp(cmd, "EAPOL::maxStart") == 0) {
00091 eapol_sm_configure(wpa_s->eapol,
00092 -1, -1, -1, atoi(value));
00093 } else if (strcasecmp(cmd, "dot11RSNAConfigPMKLifetime") == 0) {
00094 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME,
00095 atoi(value)))
00096 ret = -1;
00097 } else if (strcasecmp(cmd, "dot11RSNAConfigPMKReauthThreshold") == 0) {
00098 if (wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD,
00099 atoi(value)))
00100 ret = -1;
00101 } else if (strcasecmp(cmd, "dot11RSNAConfigSATimeout") == 0) {
00102 if (wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, atoi(value)))
00103 ret = -1;
00104 } else
00105 ret = -1;
00106
00107 return ret;
00108 }
00109
00110
00111 static int wpa_supplicant_ctrl_iface_preauth(struct wpa_supplicant *wpa_s,
00112 char *addr)
00113 {
00114 u8 bssid[ETH_ALEN];
00115
00116 if (hwaddr_aton(addr, bssid)) {
00117 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH: invalid address "
00118 "'%s'", addr);
00119 return -1;
00120 }
00121
00122 wpa_printf(MSG_DEBUG, "CTRL_IFACE PREAUTH " MACSTR, MAC2STR(bssid));
00123 rsn_preauth_deinit(wpa_s->wpa);
00124 if (rsn_preauth_init(wpa_s->wpa, bssid, wpa_s->current_ssid))
00125 return -1;
00126
00127 return 0;
00128 }
00129
00130
00131 static int wpa_supplicant_ctrl_iface_attach(struct wpa_supplicant *wpa_s,
00132 CTRL_IFACE_SOCK *from,
00133 socklen_t fromlen)
00134 {
00135 struct wpa_ctrl_dst *dst;
00136
00137 dst = malloc(sizeof(*dst));
00138 if (dst == NULL)
00139 return -1;
00140 memset(dst, 0, sizeof(*dst));
00141 memcpy(&dst->addr, from, sizeof(CTRL_IFACE_SOCK));
00142 dst->addrlen = fromlen;
00143 dst->debug_level = MSG_INFO;
00144 dst->next = wpa_s->ctrl_dst;
00145 wpa_s->ctrl_dst = dst;
00146 #ifdef CONFIG_CTRL_IFACE_UDP
00147 wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
00148 inet_ntoa(from->sin_addr), ntohs(from->sin_port));
00149 #else
00150 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
00151 (u8 *) from->sun_path, fromlen - sizeof(from->sun_family));
00152 #endif
00153 return 0;
00154 }
00155
00156
00157 static int wpa_supplicant_ctrl_iface_detach(struct wpa_supplicant *wpa_s,
00158 CTRL_IFACE_SOCK *from,
00159 socklen_t fromlen)
00160 {
00161 struct wpa_ctrl_dst *dst, *prev = NULL;
00162
00163 dst = wpa_s->ctrl_dst;
00164 while (dst) {
00165 #ifdef CONFIG_CTRL_IFACE_UDP
00166 if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
00167 from->sin_port == dst->addr.sin_port) {
00168 if (prev == NULL)
00169 wpa_s->ctrl_dst = dst->next;
00170 else
00171 prev->next = dst->next;
00172 free(dst);
00173 wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached "
00174 "%s:%d", inet_ntoa(from->sin_addr),
00175 ntohs(from->sin_port));
00176 return 0;
00177 }
00178 #else
00179 if (fromlen == dst->addrlen &&
00180 memcmp(from->sun_path, dst->addr.sun_path,
00181 fromlen - sizeof(from->sun_family)) == 0) {
00182 if (prev == NULL)
00183 wpa_s->ctrl_dst = dst->next;
00184 else
00185 prev->next = dst->next;
00186 free(dst);
00187 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor detached",
00188 (u8 *) from->sun_path,
00189 fromlen - sizeof(from->sun_family));
00190 return 0;
00191 }
00192 #endif
00193 prev = dst;
00194 dst = dst->next;
00195 }
00196 return -1;
00197 }
00198
00199
00200 static int wpa_supplicant_ctrl_iface_level(struct wpa_supplicant *wpa_s,
00201 CTRL_IFACE_SOCK *from,
00202 socklen_t fromlen,
00203 char *level)
00204 {
00205 struct wpa_ctrl_dst *dst;
00206
00207 wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
00208
00209 dst = wpa_s->ctrl_dst;
00210 while (dst) {
00211 #ifdef CONFIG_CTRL_IFACE_UDP
00212 if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
00213 from->sin_port == dst->addr.sin_port) {
00214 wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor "
00215 "level %s:%d", inet_ntoa(from->sin_addr),
00216 ntohs(from->sin_port));
00217 dst->debug_level = atoi(level);
00218 return 0;
00219 }
00220 #else
00221 if (fromlen == dst->addrlen &&
00222 memcmp(from->sun_path, dst->addr.sun_path,
00223 fromlen - sizeof(from->sun_family)) == 0) {
00224 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE changed monitor "
00225 "level", (u8 *) from->sun_path,
00226 fromlen - sizeof(from->sun_family));
00227 dst->debug_level = atoi(level);
00228 return 0;
00229 }
00230 #endif
00231 dst = dst->next;
00232 }
00233
00234 return -1;
00235 }
00236
00237
00238 static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
00239 char *rsp)
00240 {
00241 char *pos, *id_pos;
00242 int id;
00243 struct wpa_ssid *ssid;
00244
00245 pos = strchr(rsp, '-');
00246 if (pos == NULL)
00247 return -1;
00248 *pos++ = '\0';
00249 id_pos = pos;
00250 pos = strchr(pos, ':');
00251 if (pos == NULL)
00252 return -1;
00253 *pos++ = '\0';
00254 id = atoi(id_pos);
00255 wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
00256 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
00257 (u8 *) pos, strlen(pos));
00258
00259 ssid = wpa_config_get_network(wpa_s->conf, id);
00260 if (ssid == NULL) {
00261 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
00262 "to update", id);
00263 return -1;
00264 }
00265
00266 if (strcmp(rsp, "IDENTITY") == 0) {
00267 free(ssid->identity);
00268 ssid->identity = (u8 *) strdup(pos);
00269 ssid->identity_len = strlen(pos);
00270 ssid->pending_req_identity = 0;
00271 if (ssid == wpa_s->current_ssid)
00272 wpa_s->reassociate = 1;
00273 } else if (strcmp(rsp, "PASSWORD") == 0) {
00274 free(ssid->password);
00275 ssid->password = (u8 *) strdup(pos);
00276 ssid->password_len = strlen(pos);
00277 ssid->pending_req_password = 0;
00278 if (ssid == wpa_s->current_ssid)
00279 wpa_s->reassociate = 1;
00280 } else if (strcmp(rsp, "NEW_PASSWORD") == 0) {
00281 free(ssid->new_password);
00282 ssid->new_password = (u8 *) strdup(pos);
00283 ssid->new_password_len = strlen(pos);
00284 ssid->pending_req_new_password = 0;
00285 if (ssid == wpa_s->current_ssid)
00286 wpa_s->reassociate = 1;
00287 } else if (strcmp(rsp, "PIN") == 0) {
00288 free(ssid->pin);
00289 ssid->pin = strdup(pos);
00290 ssid->pending_req_pin = 0;
00291 if (ssid == wpa_s->current_ssid)
00292 wpa_s->reassociate = 1;
00293 } else if (strcmp(rsp, "OTP") == 0) {
00294 free(ssid->otp);
00295 ssid->otp = (u8 *) strdup(pos);
00296 ssid->otp_len = strlen(pos);
00297 free(ssid->pending_req_otp);
00298 ssid->pending_req_otp = NULL;
00299 ssid->pending_req_otp_len = 0;
00300 } else if (strcmp(rsp, "PASSPHRASE") == 0) {
00301 free(ssid->private_key_passwd);
00302 ssid->private_key_passwd = (u8 *) strdup(pos);
00303 ssid->pending_req_passphrase = 0;
00304 if (ssid == wpa_s->current_ssid)
00305 wpa_s->reassociate = 1;
00306 } else {
00307 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
00308 return -1;
00309 }
00310
00311 return 0;
00312 }
00313
00314
00315 static int wpa_supplicant_ctrl_iface_status(struct wpa_supplicant *wpa_s,
00316 const char *params,
00317 char *buf, size_t buflen)
00318 {
00319 char *pos, *end, tmp[30];
00320 int res, verbose;
00321
00322 verbose = strcmp(params, "-VERBOSE") == 0;
00323 pos = buf;
00324 end = buf + buflen;
00325 if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
00326 pos += snprintf(pos, end - pos, "bssid=" MACSTR "\n",
00327 MAC2STR(wpa_s->bssid));
00328 if (wpa_s->current_ssid) {
00329 pos += snprintf(pos, end - pos, "ssid=%s\n",
00330 wpa_ssid_txt(wpa_s->current_ssid->ssid,
00331 wpa_s->current_ssid->
00332 ssid_len));
00333 }
00334
00335 pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
00336 }
00337 pos += snprintf(pos, end - pos, "wpa_state=%s\n",
00338 wpa_supplicant_state_txt(wpa_s->wpa_state));
00339
00340 if (wpa_s->l2 &&
00341 l2_packet_get_ip_addr(wpa_s->l2, tmp, sizeof(tmp)) >= 0)
00342 pos += snprintf(pos, end - pos, "ip_address=%s\n", tmp);
00343
00344 if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X ||
00345 wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) {
00346 res = eapol_sm_get_status(wpa_s->eapol, pos, end - pos,
00347 verbose);
00348 if (res >= 0)
00349 pos += res;
00350 }
00351
00352 res = rsn_preauth_get_status(wpa_s->wpa, pos, end - pos, verbose);
00353 if (res >= 0)
00354 pos += res;
00355
00356 return pos - buf;
00357 }
00358
00359
00360 static int wpa_supplicant_ctrl_iface_bssid(struct wpa_supplicant *wpa_s,
00361 char *cmd)
00362 {
00363 char *pos;
00364 int id;
00365 struct wpa_ssid *ssid;
00366 u8 bssid[ETH_ALEN];
00367
00368
00369 pos = strchr(cmd, ' ');
00370 if (pos == NULL)
00371 return -1;
00372 *pos++ = '\0';
00373 id = atoi(cmd);
00374 wpa_printf(MSG_DEBUG, "CTRL_IFACE: id=%d bssid='%s'", id, pos);
00375 if (hwaddr_aton(pos, bssid)) {
00376 wpa_printf(MSG_DEBUG ,"CTRL_IFACE: invalid BSSID '%s'", pos);
00377 return -1;
00378 }
00379
00380 ssid = wpa_config_get_network(wpa_s->conf, id);
00381 if (ssid == NULL) {
00382 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
00383 "to update", id);
00384 return -1;
00385 }
00386
00387 memcpy(ssid->bssid, bssid, ETH_ALEN);
00388 ssid->bssid_set =
00389 memcmp(bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) != 0;
00390
00391
00392 return 0;
00393 }
00394
00395
00396 static int wpa_supplicant_ctrl_iface_list_networks(
00397 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
00398 {
00399 char *pos, *end;
00400 struct wpa_ssid *ssid;
00401
00402 pos = buf;
00403 end = buf + buflen;
00404 pos += snprintf(pos, end - pos, "network id / ssid / bssid / flags\n");
00405
00406 ssid = wpa_s->conf->ssid;
00407 while (ssid) {
00408 pos += snprintf(pos, end - pos, "%d\t%s",
00409 ssid->id,
00410 wpa_ssid_txt(ssid->ssid, ssid->ssid_len));
00411 if (ssid->bssid_set) {
00412 pos += snprintf(pos, end - pos, "\t" MACSTR,
00413 MAC2STR(ssid->bssid));
00414 } else {
00415 pos += snprintf(pos, end - pos, "\tany");
00416 }
00417 pos += snprintf(pos, end - pos, "\t%s%s",
00418 ssid == wpa_s->current_ssid ? "[CURRENT]" : "",
00419 ssid->disabled ? "[DISABLED]" : "");
00420 pos += snprintf(pos, end - pos, "\n");
00421
00422 ssid = ssid->next;
00423 }
00424
00425 return pos - buf;
00426 }
00427
00428
00429 static char * wpa_supplicant_cipher_txt(char *pos, char *end, int cipher)
00430 {
00431 int first = 1;
00432 pos += snprintf(pos, end - pos, "-");
00433 if (cipher & WPA_CIPHER_NONE) {
00434 pos += snprintf(pos, end - pos, "%sNONE", first ? "" : "+");
00435 first = 0;
00436 }
00437 if (cipher & WPA_CIPHER_WEP40) {
00438 pos += snprintf(pos, end - pos, "%sWEP40", first ? "" : "+");
00439 first = 0;
00440 }
00441 if (cipher & WPA_CIPHER_WEP104) {
00442 pos += snprintf(pos, end - pos, "%sWEP104", first ? "" : "+");
00443 first = 0;
00444 }
00445 if (cipher & WPA_CIPHER_TKIP) {
00446 pos += snprintf(pos, end - pos, "%sTKIP", first ? "" : "+");
00447 first = 0;
00448 }
00449 if (cipher & WPA_CIPHER_CCMP) {
00450 pos += snprintf(pos, end - pos, "%sCCMP", first ? "" : "+");
00451 first = 0;
00452 }
00453 return pos;
00454 }
00455
00456
00457 static char * wpa_supplicant_ie_txt(struct wpa_supplicant *wpa_s,
00458 char *pos, char *end, const char *proto,
00459 const u8 *ie, size_t ie_len)
00460 {
00461 struct wpa_ie_data data;
00462 int first;
00463
00464 pos += snprintf(pos, end - pos, "[%s-", proto);
00465
00466 if (wpa_parse_wpa_ie(ie, ie_len, &data) < 0) {
00467 pos += snprintf(pos, end - pos, "?]");
00468 return pos;
00469 }
00470
00471 first = 1;
00472 if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) {
00473 pos += snprintf(pos, end - pos, "%sEAP", first ? "" : "+");
00474 first = 0;
00475 }
00476 if (data.key_mgmt & WPA_KEY_MGMT_PSK) {
00477 pos += snprintf(pos, end - pos, "%sPSK", first ? "" : "+");
00478 first = 0;
00479 }
00480 if (data.key_mgmt & WPA_KEY_MGMT_WPA_NONE) {
00481 pos += snprintf(pos, end - pos, "%sNone", first ? "" : "+");
00482 first = 0;
00483 }
00484
00485 pos = wpa_supplicant_cipher_txt(pos, end, data.pairwise_cipher);
00486
00487 if (data.capabilities & WPA_CAPABILITY_PREAUTH)
00488 pos += snprintf(pos, end - pos, "-preauth");
00489
00490 pos += snprintf(pos, end - pos, "]");
00491
00492 return pos;
00493 }
00494
00495
00496 static int wpa_supplicant_ctrl_iface_scan_results(
00497 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
00498 {
00499 char *pos, *end;
00500 struct wpa_scan_result *res;
00501 int i;
00502
00503 if (wpa_s->scan_results == NULL &&
00504 wpa_supplicant_get_scan_results(wpa_s) < 0)
00505 return 0;
00506
00507 pos = buf;
00508 end = buf + buflen;
00509 pos += snprintf(pos, end - pos, "bssid / frequency / signal level / "
00510 "flags / ssid\n");
00511
00512 for (i = 0; i < wpa_s->num_scan_results; i++) {
00513 res = &wpa_s->scan_results[i];
00514 pos += snprintf(pos, end - pos, MACSTR "\t%d\t%d\t",
00515 MAC2STR(res->bssid), res->freq, res->level);
00516 if (res->wpa_ie_len) {
00517 pos = wpa_supplicant_ie_txt(wpa_s, pos, end, "WPA",
00518 res->wpa_ie,
00519 res->wpa_ie_len);
00520 }
00521 if (res->rsn_ie_len) {
00522 pos = wpa_supplicant_ie_txt(wpa_s, pos, end, "WPA2",
00523 res->rsn_ie,
00524 res->rsn_ie_len);
00525 }
00526 if (!res->wpa_ie_len && !res->rsn_ie_len &&
00527 res->caps & IEEE80211_CAP_PRIVACY)
00528 pos += snprintf(pos, end - pos, "[WEP]");
00529 if (res->caps & IEEE80211_CAP_IBSS)
00530 pos += snprintf(pos, end - pos, "[IBSS]");
00531
00532 pos += snprintf(pos, end - pos, "\t%s",
00533 wpa_ssid_txt(res->ssid, res->ssid_len));
00534
00535 pos += snprintf(pos, end - pos, "\n");
00536 }
00537
00538 return pos - buf;
00539 }
00540
00541
00542 static int wpa_supplicant_ctrl_iface_select_network(
00543 struct wpa_supplicant *wpa_s, char *cmd)
00544 {
00545 int id;
00546 struct wpa_ssid *ssid;
00547
00548
00549 if (strcmp(cmd, "any") == 0) {
00550 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
00551 ssid = wpa_s->conf->ssid;
00552 while (ssid) {
00553 ssid->disabled = 0;
00554 ssid = ssid->next;
00555 }
00556 wpa_s->reassociate = 1;
00557 wpa_supplicant_req_scan(wpa_s, 0, 0);
00558 return 0;
00559 }
00560
00561 id = atoi(cmd);
00562 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
00563
00564 ssid = wpa_config_get_network(wpa_s->conf, id);
00565 if (ssid == NULL) {
00566 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
00567 "id=%d", id);
00568 return -1;
00569 }
00570
00571 if (ssid != wpa_s->current_ssid && wpa_s->current_ssid)
00572 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
00573
00574
00575 ssid = wpa_s->conf->ssid;
00576 while (ssid) {
00577 ssid->disabled = id != ssid->id;
00578 ssid = ssid->next;
00579 }
00580 wpa_s->reassociate = 1;
00581 wpa_supplicant_req_scan(wpa_s, 0, 0);
00582
00583 return 0;
00584 }
00585
00586
00587 static int wpa_supplicant_ctrl_iface_enable_network(
00588 struct wpa_supplicant *wpa_s, char *cmd)
00589 {
00590 int id;
00591 struct wpa_ssid *ssid;
00592
00593
00594 id = atoi(cmd);
00595 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
00596
00597 ssid = wpa_config_get_network(wpa_s->conf, id);
00598 if (ssid == NULL) {
00599 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
00600 "id=%d", id);
00601 return -1;
00602 }
00603
00604 if (wpa_s->current_ssid == NULL && ssid->disabled) {
00605
00606
00607
00608 wpa_s->reassociate = 1;
00609 wpa_supplicant_req_scan(wpa_s, 0, 0);
00610 }
00611 ssid->disabled = 0;
00612
00613 return 0;
00614 }
00615
00616
00617 static int wpa_supplicant_ctrl_iface_disable_network(
00618 struct wpa_supplicant *wpa_s, char *cmd)
00619 {
00620 int id;
00621 struct wpa_ssid *ssid;
00622
00623
00624 id = atoi(cmd);
00625 wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
00626
00627 ssid = wpa_config_get_network(wpa_s->conf, id);
00628 if (ssid == NULL) {
00629 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
00630 "id=%d", id);
00631 return -1;
00632 }
00633
00634 if (ssid == wpa_s->current_ssid)
00635 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
00636 ssid->disabled = 1;
00637
00638 return 0;
00639 }
00640
00641
00642 static int wpa_supplicant_ctrl_iface_add_network(
00643 struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
00644 {
00645 struct wpa_ssid *ssid;
00646
00647 wpa_printf(MSG_DEBUG, "CTRL_IFACE: ADD_NETWORK");
00648
00649 ssid = wpa_config_add_network(wpa_s->conf);
00650 if (ssid == NULL)
00651 return -1;
00652 ssid->disabled = 1;
00653 wpa_config_set_network_defaults(ssid);
00654
00655 return snprintf(buf, buflen, "%d\n", ssid->id);
00656 }
00657
00658
00659 static int wpa_supplicant_ctrl_iface_remove_network(
00660 struct wpa_supplicant *wpa_s, char *cmd)
00661 {
00662 int id;
00663 struct wpa_ssid *ssid;
00664
00665
00666 id = atoi(cmd);
00667 wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
00668
00669 ssid = wpa_config_get_network(wpa_s->conf, id);
00670 if (ssid == NULL ||
00671 wpa_config_remove_network(wpa_s->conf, id) < 0) {
00672 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
00673 "id=%d", id);
00674 return -1;
00675 }
00676
00677 if (ssid == wpa_s->current_ssid)
00678 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
00679
00680 return 0;
00681 }
00682
00683
00684 static int wpa_supplicant_ctrl_iface_set_network(
00685 struct wpa_supplicant *wpa_s, char *cmd)
00686 {
00687 int id;
00688 struct wpa_ssid *ssid;
00689 char *name, *value;
00690
00691
00692 name = strchr(cmd, ' ');
00693 if (name == NULL)
00694 return -1;
00695 *name++ = '\0';
00696
00697 value = strchr(name, ' ');
00698 if (value == NULL)
00699 return -1;
00700 *value++ = '\0';
00701
00702 id = atoi(cmd);
00703 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
00704 id, name);
00705 wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
00706 (u8 *) value, strlen(value));
00707
00708 ssid = wpa_config_get_network(wpa_s->conf, id);
00709 if (ssid == NULL) {
00710 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
00711 "id=%d", id);
00712 return -1;
00713 }
00714
00715 if (wpa_config_set(ssid, name, value, 0) < 0) {
00716 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
00717 "variable '%s'", name);
00718 return -1;
00719 }
00720
00721 if ((strcmp(name, "psk") == 0 && value[0] == '"' && ssid->ssid_len) ||
00722 (strcmp(name, "ssid") == 0 && ssid->passphrase))
00723 wpa_config_update_psk(ssid);
00724
00725 return 0;
00726 }
00727
00728
00729 static int wpa_supplicant_ctrl_iface_get_network(
00730 struct wpa_supplicant *wpa_s, char *cmd, char *buf, size_t buflen)
00731 {
00732 int id;
00733 struct wpa_ssid *ssid;
00734 char *name, *value;
00735
00736
00737 name = strchr(cmd, ' ');
00738 if (name == NULL)
00739 return -1;
00740 *name++ = '\0';
00741
00742 id = atoi(cmd);
00743 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_NETWORK id=%d name='%s'",
00744 id, name);
00745
00746 ssid = wpa_config_get_network(wpa_s->conf, id);
00747 if (ssid == NULL) {
00748 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
00749 "id=%d", id);
00750 return -1;
00751 }
00752
00753 value = wpa_config_get(ssid, name);
00754 if (value == NULL) {
00755 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to get network "
00756 "variable '%s'", name);
00757 return -1;
00758 }
00759
00760 snprintf(buf, buflen, "%s", value);
00761
00762 free(value);
00763
00764 return strlen(buf);
00765 }
00766
00767
00768 static int wpa_supplicant_ctrl_iface_save_config(struct wpa_supplicant *wpa_s)
00769 {
00770 int ret;
00771
00772 if (!wpa_s->conf->update_config) {
00773 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Not allowed "
00774 "to update configuration (update_config=0)");
00775 return -1;
00776 }
00777
00778 ret = wpa_config_write(wpa_s->confname, wpa_s->conf);
00779 if (ret) {
00780 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Failed to "
00781 "update configuration");
00782 } else {
00783 wpa_printf(MSG_DEBUG, "CTRL_IFACE: SAVE_CONFIG - Configuration"
00784 " updated");
00785 }
00786
00787 return ret;
00788 }
00789
00790
00791 static int wpa_supplicant_ctrl_iface_get_capability(
00792 struct wpa_supplicant *wpa_s, const char *field, char *buf,
00793 size_t buflen)
00794 {
00795 struct wpa_driver_capa capa;
00796 int res, first = 1;
00797 char *pos, *end;
00798
00799 wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s'", field);
00800
00801 if (strcmp(field, "eap") == 0) {
00802 return eap_get_names(buf, buflen);
00803 }
00804
00805 res = wpa_drv_get_capa(wpa_s, &capa);
00806
00807 pos = buf;
00808 end = pos + buflen;
00809
00810 if (strcmp(field, "pairwise") == 0) {
00811 if (res < 0)
00812 return snprintf(buf, buflen, "CCMP TKIP NONE");
00813
00814 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
00815 pos += snprintf(pos, end - pos, "%sCCMP",
00816 first ? "" : " ");
00817 first = 0;
00818 }
00819
00820 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
00821 pos += snprintf(pos, end - pos, "%sTKIP",
00822 first ? "" : " ");
00823 first = 0;
00824 }
00825
00826 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
00827 pos += snprintf(pos, end - pos, "%sNONE",
00828 first ? "" : " ");
00829 first = 0;
00830 }
00831
00832 return pos - buf;
00833 }
00834
00835 if (strcmp(field, "group") == 0) {
00836 if (res < 0)
00837 return snprintf(buf, buflen, "CCMP TKIP WEP104 WEP40");
00838
00839 if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
00840 pos += snprintf(pos, end - pos, "%sCCMP",
00841 first ? "" : " ");
00842 first = 0;
00843 }
00844
00845 if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
00846 pos += snprintf(pos, end - pos, "%sTKIP",
00847 first ? "" : " ");
00848 first = 0;
00849 }
00850
00851 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
00852 pos += snprintf(pos, end - pos, "%sWEP104",
00853 first ? "" : " ");
00854 first = 0;
00855 }
00856
00857 if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
00858 pos += snprintf(pos, end - pos, "%sWEP40",
00859 first ? "" : " ");
00860 first = 0;
00861 }
00862
00863 return pos - buf;
00864 }
00865
00866 if (strcmp(field, "key_mgmt") == 0) {
00867 if (res < 0) {
00868 return snprintf(buf, buflen, "WPA-PSK WPA-EAP "
00869 "IEEE8021X WPA-NONE NONE");
00870 }
00871
00872 pos += snprintf(pos, end - pos, "NONE IEEE8021X");
00873
00874 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
00875 WPA_DRIVER_CAPA_KEY_MGMT_WPA2))
00876 pos += snprintf(pos, end - pos, " WPA-EAP");
00877
00878 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |
00879 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK))
00880 pos += snprintf(pos, end - pos, " WPA-PSK");
00881
00882 if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE)
00883 pos += snprintf(pos, end - pos, " WPA-NONE");
00884
00885 return pos - buf;
00886 }
00887
00888 if (strcmp(field, "proto") == 0) {
00889 if (res < 0)
00890 return snprintf(buf, buflen, "RSN WPA");
00891
00892 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |
00893 WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {
00894 pos += snprintf(pos, end - pos, "%sRSN",
00895 first ? "" : " ");
00896 first = 0;
00897 }
00898
00899 if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
00900 WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {
00901 pos += snprintf(pos, end - pos, "%sWPA",
00902 first ? "" : " ");
00903 first = 0;
00904 }
00905
00906 return pos - buf;
00907 }
00908
00909 if (strcmp(field, "auth_alg") == 0) {
00910 if (res < 0)
00911 return snprintf(buf, buflen, "OPEN SHARED LEAP");
00912
00913 if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {
00914 pos += snprintf(pos, end - pos, "%sOPEN",
00915 first ? "" : " ");
00916 first = 0;
00917 }
00918
00919 if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {
00920 pos += snprintf(pos, end - pos, "%sSHARED",
00921 first ? "" : " ");
00922 first = 0;
00923 }
00924
00925 if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {
00926 pos += snprintf(pos, end - pos, "%sLEAP",
00927 first ? "" : " ");
00928 first = 0;
00929 }
00930
00931 return pos - buf;
00932 }
00933
00934 wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",
00935 field);
00936
00937 return -1;
00938 }
00939
00940
00941 static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
00942 void *sock_ctx)
00943 {
00944 struct wpa_supplicant *wpa_s = eloop_ctx;
00945 char buf[256];
00946 int res;
00947 CTRL_IFACE_SOCK from;
00948 socklen_t fromlen = sizeof(from);
00949 char *reply;
00950 const int reply_size = 2048;
00951 int reply_len;
00952 int new_attached = 0, ctrl_rsp = 0;
00953
00954 res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
00955 (struct sockaddr *) &from, &fromlen);
00956 if (res < 0) {
00957 perror("recvfrom(ctrl_iface)");
00958 return;
00959 }
00960 buf[res] = '\0';
00961 if (strncmp(buf, WPA_CTRL_RSP, strlen(WPA_CTRL_RSP)) == 0 ||
00962 strncmp(buf, "SET_NETWORK ", 12) == 0) {
00963 wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",
00964 (u8 *) buf, res);
00965 } else {
00966 wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (u8 *) buf, res);
00967 }
00968
00969 reply = malloc(reply_size);
00970 if (reply == NULL) {
00971 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
00972 fromlen);
00973 return;
00974 }
00975
00976 memcpy(reply, "OK\n", 3);
00977 reply_len = 3;
00978
00979 if (strcmp(buf, "PING") == 0) {
00980 memcpy(reply, "PONG\n", 5);
00981 reply_len = 5;
00982 } else if (strcmp(buf, "MIB") == 0) {
00983 reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);
00984 if (reply_len >= 0) {
00985 res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,
00986 reply_size - reply_len);
00987 if (res < 0)
00988 reply_len = -1;
00989 else
00990 reply_len += res;
00991 }
00992 } else if (strncmp(buf, "STATUS", 6) == 0) {
00993 reply_len = wpa_supplicant_ctrl_iface_status(
00994 wpa_s, buf + 6, reply, reply_size);
00995 } else if (strcmp(buf, "PMKSA") == 0) {
00996 reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size);
00997 } else if (strncmp(buf, "SET ", 4) == 0) {
00998 if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
00999 reply_len = -1;
01000 } else if (strcmp(buf, "LOGON") == 0) {
01001 eapol_sm_notify_logoff(wpa_s->eapol, FALSE);
01002 } else if (strcmp(buf, "LOGOFF") == 0) {
01003 eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
01004 } else if (strcmp(buf, "REASSOCIATE") == 0) {
01005 wpa_s->disconnected = 0;
01006 wpa_s->reassociate = 1;
01007 wpa_supplicant_req_scan(wpa_s, 0, 0);
01008 } else if (strncmp(buf, "PREAUTH ", 8) == 0) {
01009 if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))
01010 reply_len = -1;
01011 } else if (strcmp(buf, "ATTACH") == 0) {
01012 if (wpa_supplicant_ctrl_iface_attach(wpa_s, &from, fromlen))
01013 reply_len = -1;
01014 else
01015 new_attached = 1;
01016 } else if (strcmp(buf, "DETACH") == 0) {
01017 if (wpa_supplicant_ctrl_iface_detach(wpa_s, &from, fromlen))
01018 reply_len = -1;
01019 } else if (strncmp(buf, "LEVEL ", 6) == 0) {
01020 if (wpa_supplicant_ctrl_iface_level(wpa_s, &from, fromlen,
01021 buf + 6))
01022 reply_len = -1;
01023 } else if (strncmp(buf, WPA_CTRL_RSP, strlen(WPA_CTRL_RSP)) == 0) {
01024 if (wpa_supplicant_ctrl_iface_ctrl_rsp(
01025 wpa_s, buf + strlen(WPA_CTRL_RSP)))
01026 reply_len = -1;
01027 else
01028 ctrl_rsp = 1;
01029 } else if (strcmp(buf, "RECONFIGURE") == 0) {
01030 if (wpa_supplicant_reload_configuration(wpa_s))
01031 reply_len = -1;
01032 } else if (strcmp(buf, "TERMINATE") == 0) {
01033 eloop_terminate();
01034 } else if (strncmp(buf, "BSSID ", 6) == 0) {
01035 if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
01036 reply_len = -1;
01037 } else if (strcmp(buf, "LIST_NETWORKS") == 0) {
01038 reply_len = wpa_supplicant_ctrl_iface_list_networks(
01039 wpa_s, reply, reply_size);
01040 } else if (strcmp(buf, "DISCONNECT") == 0) {
01041 wpa_s->disconnected = 1;
01042 wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);
01043 } else if (strcmp(buf, "SCAN") == 0) {
01044 wpa_s->scan_req = 2;
01045 wpa_supplicant_req_scan(wpa_s, 0, 0);
01046 } else if (strcmp(buf, "SCAN_RESULTS") == 0) {
01047 reply_len = wpa_supplicant_ctrl_iface_scan_results(
01048 wpa_s, reply, reply_size);
01049 } else if (strncmp(buf, "SELECT_NETWORK ", 15) == 0) {
01050 if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))
01051 reply_len = -1;
01052 } else if (strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {
01053 if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))
01054 reply_len = -1;
01055 } else if (strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {
01056 if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))
01057 reply_len = -1;
01058 } else if (strcmp(buf, "ADD_NETWORK") == 0) {
01059 reply_len = wpa_supplicant_ctrl_iface_add_network(
01060 wpa_s, reply, reply_size);
01061 } else if (strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {
01062 if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))
01063 reply_len = -1;
01064 } else if (strncmp(buf, "SET_NETWORK ", 12) == 0) {
01065 if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))
01066 reply_len = -1;
01067 } else if (strncmp(buf, "GET_NETWORK ", 12) == 0) {
01068 reply_len = wpa_supplicant_ctrl_iface_get_network(
01069 wpa_s, buf + 12, reply, reply_size);
01070 } else if (strcmp(buf, "SAVE_CONFIG") == 0) {
01071 if (wpa_supplicant_ctrl_iface_save_config(wpa_s))
01072 reply_len = -1;
01073 } else if (strncmp(buf, "GET_CAPABILITY ", 15) == 0) {
01074 reply_len = wpa_supplicant_ctrl_iface_get_capability(
01075 wpa_s, buf + 15, reply, reply_size);
01076 } else {
01077 memcpy(reply, "UNKNOWN COMMAND\n", 16);
01078 reply_len = 16;
01079 }
01080
01081 if (reply_len < 0) {
01082 memcpy(reply, "FAIL\n", 5);
01083 reply_len = 5;
01084 }
01085 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
01086 free(reply);
01087
01088 if (new_attached)
01089 eapol_sm_notify_ctrl_attached(wpa_s->eapol);
01090 if (ctrl_rsp)
01091 eapol_sm_notify_ctrl_response(wpa_s->eapol);
01092 }
01093
01094
01095 #ifndef CONFIG_CTRL_IFACE_UDP
01096 static char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s)
01097 {
01098 char *buf;
01099 size_t len;
01100
01101 if (wpa_s->conf->ctrl_interface == NULL)
01102 return NULL;
01103
01104 len = strlen(wpa_s->conf->ctrl_interface) + strlen(wpa_s->ifname) + 2;
01105 buf = malloc(len);
01106 if (buf == NULL)
01107 return NULL;
01108
01109 snprintf(buf, len, "%s/%s",
01110 wpa_s->conf->ctrl_interface, wpa_s->ifname);
01111 #ifdef __CYGWIN__
01112 {
01113
01114
01115 char *pos = buf;
01116 while (*pos) {
01117 if (*pos == '\\')
01118 *pos = '_';
01119 pos++;
01120 }
01121 }
01122 #endif
01123 return buf;
01124 }
01125 #endif
01126
01127
01137 int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
01138 {
01139 CTRL_IFACE_SOCK addr;
01140 int s = -1;
01141 #ifndef CONFIG_CTRL_IFACE_UDP
01142 char *fname = NULL;
01143 #endif
01144
01145 wpa_s->ctrl_sock = -1;
01146
01147 if (wpa_s->conf->ctrl_interface == NULL)
01148 return 0;
01149
01150 #ifdef CONFIG_CTRL_IFACE_UDP
01151 s = socket(PF_INET, SOCK_DGRAM, 0);
01152 if (s < 0) {
01153 perror("socket(PF_INET)");
01154 goto fail;
01155 }
01156
01157 memset(&addr, 0, sizeof(addr));
01158 addr.sin_family = AF_INET;
01159 addr.sin_addr.s_addr = htonl((127 << 24) | 1);
01160 addr.sin_port = htons(WPA_CTRL_IFACE_PORT);
01161 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
01162 perror("bind(AF_INET)");
01163 goto fail;
01164 }
01165 #else
01166 if (mkdir(wpa_s->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {
01167 if (errno == EEXIST) {
01168 wpa_printf(MSG_DEBUG, "Using existing control "
01169 "interface directory.");
01170 } else {
01171 perror("mkdir[ctrl_interface]");
01172 goto fail;
01173 }
01174 }
01175
01176 if (wpa_s->conf->ctrl_interface_gid_set &&
01177 chown(wpa_s->conf->ctrl_interface, 0,
01178 wpa_s->conf->ctrl_interface_gid) < 0) {
01179 perror("chown[ctrl_interface]");
01180 return -1;
01181 }
01182
01183 if (strlen(wpa_s->conf->ctrl_interface) + 1 + strlen(wpa_s->ifname) >=
01184 sizeof(addr.sun_path))
01185 goto fail;
01186
01187 s = socket(PF_UNIX, SOCK_DGRAM, 0);
01188 if (s < 0) {
01189 perror("socket(PF_UNIX)");
01190 goto fail;
01191 }
01192
01193 memset(&addr, 0, sizeof(addr));
01194 addr.sun_family = AF_UNIX;
01195 fname = wpa_supplicant_ctrl_iface_path(wpa_s);
01196 if (fname == NULL)
01197 goto fail;
01198 strncpy(addr.sun_path, fname, sizeof(addr.sun_path));
01199 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
01200 perror("bind(PF_UNIX)");
01201 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
01202 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
01203 " allow connections - assuming it was left"
01204 "over from forced program termination");
01205 if (unlink(fname) < 0) {
01206 perror("unlink[ctrl_iface]");
01207 wpa_printf(MSG_ERROR, "Could not unlink "
01208 "existing ctrl_iface socket '%s'",
01209 fname);
01210 goto fail;
01211 }
01212 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
01213 0) {
01214 perror("bind(PF_UNIX)");
01215 goto fail;
01216 }
01217 wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
01218 "ctrl_iface socket '%s'", fname);
01219 } else {
01220 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
01221 "be in use - cannot override it");
01222 wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
01223 "not used anymore", fname);
01224 free(fname);
01225 fname = NULL;
01226 goto fail;
01227 }
01228 }
01229
01230 if (wpa_s->conf->ctrl_interface_gid_set &&
01231 chown(fname, 0, wpa_s->conf->ctrl_interface_gid) < 0) {
01232 perror("chown[ctrl_interface/ifname]");
01233 goto fail;
01234 }
01235
01236 if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
01237 perror("chmod[ctrl_interface/ifname]");
01238 goto fail;
01239 }
01240 free(fname);
01241 #endif
01242
01243 wpa_s->ctrl_sock = s;
01244 eloop_register_read_sock(s, wpa_supplicant_ctrl_iface_receive, wpa_s,
01245 NULL);
01246
01247 return 0;
01248
01249 fail:
01250 if (s >= 0)
01251 close(s);
01252 #ifndef CONFIG_CTRL_IFACE_UDP
01253 if (fname) {
01254 unlink(fname);
01255 free(fname);
01256 }
01257 #endif
01258 return -1;
01259 }
01260
01261
01270 void wpa_supplicant_ctrl_iface_deinit(struct wpa_supplicant *wpa_s)
01271 {
01272 struct wpa_ctrl_dst *dst, *prev;
01273
01274 if (wpa_s->ctrl_sock > -1) {
01275 #ifndef CONFIG_CTRL_IFACE_UDP
01276 char *fname;
01277 #endif
01278 eloop_unregister_read_sock(wpa_s->ctrl_sock);
01279 if (wpa_s->ctrl_dst) {
01280
01281
01282
01283
01284
01285 wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
01286 "monitors to receive messages");
01287 sleep(1);
01288 }
01289 close(wpa_s->ctrl_sock);
01290 wpa_s->ctrl_sock = -1;
01291 #ifndef CONFIG_CTRL_IFACE_UDP
01292 fname = wpa_supplicant_ctrl_iface_path(wpa_s);
01293 if (fname)
01294 unlink(fname);
01295 free(fname);
01296
01297 if (rmdir(wpa_s->conf->ctrl_interface) < 0) {
01298 if (errno == ENOTEMPTY) {
01299 wpa_printf(MSG_DEBUG, "Control interface "
01300 "directory not empty - leaving it "
01301 "behind");
01302 } else {
01303 perror("rmdir[ctrl_interface]");
01304 }
01305 }
01306 #endif
01307 }
01308
01309 dst = wpa_s->ctrl_dst;
01310 while (dst) {
01311 prev = dst;
01312 dst = dst->next;
01313 free(prev);
01314 }
01315 }
01316
01317
01328 void wpa_supplicant_ctrl_iface_send(struct wpa_supplicant *wpa_s, int level,
01329 char *buf, size_t len)
01330 {
01331 struct wpa_ctrl_dst *dst, *next;
01332 char levelstr[10];
01333 int idx;
01334 #ifdef CONFIG_CTRL_IFACE_UDP
01335 char *sbuf;
01336 int llen;
01337
01338 dst = wpa_s->ctrl_dst;
01339 if (wpa_s->ctrl_sock < 0 || dst == NULL)
01340 return;
01341
01342 snprintf(levelstr, sizeof(levelstr), "<%d>", level);
01343
01344 llen = strlen(levelstr);
01345 sbuf = malloc(llen + len);
01346 if (sbuf == NULL)
01347 return;
01348
01349 memcpy(sbuf, levelstr, llen);
01350 memcpy(sbuf + llen, buf, len);
01351
01352 idx = 0;
01353 while (dst) {
01354 next = dst->next;
01355 if (level >= dst->debug_level) {
01356 wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
01357 inet_ntoa(dst->addr.sin_addr),
01358 ntohs(dst->addr.sin_port));
01359 if (sendto(wpa_s->ctrl_sock, sbuf, llen + len, 0,
01360 (struct sockaddr *) &dst->addr,
01361 sizeof(dst->addr)) < 0) {
01362 perror("sendto(CTRL_IFACE monitor)");
01363 dst->errors++;
01364 if (dst->errors > 10) {
01365 wpa_supplicant_ctrl_iface_detach(
01366 wpa_s, &dst->addr,
01367 dst->addrlen);
01368 }
01369 } else
01370 dst->errors = 0;
01371 }
01372 idx++;
01373 dst = next;
01374 }
01375 free(sbuf);
01376 #else
01377 struct msghdr msg;
01378 struct iovec io[2];
01379
01380 dst = wpa_s->ctrl_dst;
01381 if (wpa_s->ctrl_sock < 0 || dst == NULL)
01382 return;
01383
01384 snprintf(levelstr, sizeof(levelstr), "<%d>", level);
01385 io[0].iov_base = levelstr;
01386 io[0].iov_len = strlen(levelstr);
01387 io[1].iov_base = buf;
01388 io[1].iov_len = len;
01389 memset(&msg, 0, sizeof(msg));
01390 msg.msg_iov = io;
01391 msg.msg_iovlen = 2;
01392
01393 idx = 0;
01394 while (dst) {
01395 next = dst->next;
01396 if (level >= dst->debug_level) {
01397 wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor send",
01398 (u8 *) dst->addr.sun_path, dst->addrlen -
01399 sizeof(dst->addr.sun_family));
01400 msg.msg_name = &dst->addr;
01401 msg.msg_namelen = dst->addrlen;
01402 if (sendmsg(wpa_s->ctrl_sock, &msg, 0) < 0) {
01403 perror("sendmsg(CTRL_IFACE monitor)");
01404 dst->errors++;
01405 if (dst->errors > 10) {
01406 wpa_supplicant_ctrl_iface_detach(
01407 wpa_s, &dst->addr,
01408 dst->addrlen);
01409 }
01410 } else
01411 dst->errors = 0;
01412 }
01413 idx++;
01414 dst = next;
01415 }
01416 #endif
01417 }
01418
01419
01430 void wpa_supplicant_ctrl_iface_wait(struct wpa_supplicant *wpa_s)
01431 {
01432 fd_set rfds;
01433
01434 if (wpa_s->ctrl_sock < 0)
01435 return;
01436
01437 wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor",
01438 wpa_s->ifname);
01439
01440 FD_ZERO(&rfds);
01441 FD_SET(wpa_s->ctrl_sock, &rfds);
01442 select(wpa_s->ctrl_sock + 1, &rfds, NULL, NULL, NULL);
01443 }
01444
01445
01446 static int wpa_supplicant_global_iface_add(struct wpa_global *global,
01447 char *cmd)
01448 {
01449 struct wpa_interface iface;
01450 char *pos;
01451
01452
01453
01454
01455 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);
01456
01457 memset(&iface, 0, sizeof(iface));
01458
01459 do {
01460 iface.ifname = pos = cmd;
01461 pos = strchr(pos, '\t');
01462 if (pos)
01463 *pos++ = '\0';
01464 if (iface.ifname[0] == '\0')
01465 return -1;
01466 if (pos == NULL)
01467 break;
01468
01469 iface.confname = pos;
01470 pos = strchr(pos, '\t');
01471 if (pos)
01472 *pos++ = '\0';
01473 if (iface.confname[0] == '\0')
01474 iface.confname = NULL;
01475 if (pos == NULL)
01476 break;
01477
01478 iface.driver = pos;
01479 pos = strchr(pos, '\t');
01480 if (pos)
01481 *pos++ = '\0';
01482 if (iface.driver[0] == '\0')
01483 iface.driver = NULL;
01484 if (pos == NULL)
01485 break;
01486
01487 iface.ctrl_interface = pos;
01488 pos = strchr(pos, '\t');
01489 if (pos)
01490 *pos++ = '\0';
01491 if (iface.ctrl_interface[0] == '\0')
01492 iface.ctrl_interface = NULL;
01493 if (pos == NULL)
01494 break;
01495
01496 iface.driver_param = pos;
01497 pos = strchr(pos, '\t');
01498 if (pos)
01499 *pos++ = '\0';
01500 if (iface.driver_param[0] == '\0')
01501 iface.driver_param = NULL;
01502 if (pos == NULL)
01503 break;
01504 } while (0);
01505
01506 if (wpa_supplicant_get_iface(global, iface.ifname))
01507 return -1;
01508
01509 return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
01510 }
01511
01512
01513 static int wpa_supplicant_global_iface_remove(struct wpa_global *global,
01514 char *cmd)
01515 {
01516 struct wpa_supplicant *wpa_s;
01517
01518 wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_REMOVE '%s'", cmd);
01519
01520 wpa_s = wpa_supplicant_get_iface(global, cmd);
01521 if (wpa_s == NULL)
01522 return -1;
01523 return wpa_supplicant_remove_iface(global, wpa_s);
01524 }
01525
01526
01527 static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
01528 void *sock_ctx)
01529 {
01530 struct wpa_global *global = eloop_ctx;
01531 char buf[256];
01532 int res;
01533 CTRL_IFACE_SOCK from;
01534 socklen_t fromlen = sizeof(from);
01535 char *reply;
01536 const int reply_size = 2048;
01537 int reply_len;
01538
01539 res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
01540 (struct sockaddr *) &from, &fromlen);
01541 if (res < 0) {
01542 perror("recvfrom(ctrl_iface)");
01543 return;
01544 }
01545 buf[res] = '\0';
01546 wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface", (u8 *) buf, res);
01547
01548 reply = malloc(reply_size);
01549 if (reply == NULL) {
01550 sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
01551 fromlen);
01552 return;
01553 }
01554
01555 memcpy(reply, "OK\n", 3);
01556 reply_len = 3;
01557
01558 if (strcmp(buf, "PING") == 0) {
01559 memcpy(reply, "PONG\n", 5);
01560 reply_len = 5;
01561 } else if (strncmp(buf, "INTERFACE_ADD ", 14) == 0) {
01562 if (wpa_supplicant_global_iface_add(global, buf + 14))
01563 reply_len = -1;
01564 } else if (strncmp(buf, "INTERFACE_REMOVE ", 17) == 0) {
01565 if (wpa_supplicant_global_iface_remove(global, buf + 17))
01566 reply_len = -1;
01567 } else {
01568 memcpy(reply, "UNKNOWN COMMAND\n", 16);
01569 reply_len = 16;
01570 }
01571
01572 if (reply_len < 0) {
01573 memcpy(reply, "FAIL\n", 5);
01574 reply_len = 5;
01575 }
01576 sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
01577 free(reply);
01578 }
01579
01580
01590 int wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
01591 {
01592 CTRL_IFACE_SOCK addr;
01593 int s = -1;
01594
01595 global->ctrl_sock = -1;
01596
01597 if (global->params.ctrl_interface == NULL)
01598 return 0;
01599
01600 wpa_printf(MSG_DEBUG, "Global control interface '%s'",
01601 global->params.ctrl_interface);
01602
01603 #ifdef CONFIG_CTRL_IFACE_UDP
01604 s = socket(PF_INET, SOCK_DGRAM, 0);
01605 if (s < 0) {
01606 perror("socket(PF_INET)");
01607 goto fail;
01608 }
01609
01610 memset(&addr, 0, sizeof(addr));
01611 addr.sin_family = AF_INET;
01612 addr.sin_addr.s_addr = htonl((127 << 24) | 1);
01613 addr.sin_port = htons(WPA_GLOBAL_CTRL_IFACE_PORT);
01614 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
01615 perror("bind(AF_INET)");
01616 goto fail;
01617 }
01618 #else
01619 s = socket(PF_UNIX, SOCK_DGRAM, 0);
01620 if (s < 0) {
01621 perror("socket(PF_UNIX)");
01622 goto fail;
01623 }
01624
01625 memset(&addr, 0, sizeof(addr));
01626 addr.sun_family = AF_UNIX;
01627 strncpy(addr.sun_path, global->params.ctrl_interface,
01628 sizeof(addr.sun_path));
01629 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
01630 perror("bind(PF_UNIX)");
01631 if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
01632 wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
01633 " allow connections - assuming it was left"
01634 "over from forced program termination");
01635 if (unlink(global->params.ctrl_interface) < 0) {
01636 perror("unlink[ctrl_iface]");
01637 wpa_printf(MSG_ERROR, "Could not unlink "
01638 "existing ctrl_iface socket '%s'",
01639 global->params.ctrl_interface);
01640 goto fail;
01641 }
01642 if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
01643 0) {
01644 perror("bind(PF_UNIX)");
01645 goto fail;
01646 }
01647 wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
01648 "ctrl_iface socket '%s'",
01649 global->params.ctrl_interface);
01650 } else {
01651 wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
01652 "be in use - cannot override it");
01653 wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
01654 "not used anymore",
01655 global->params.ctrl_interface);
01656 goto fail;
01657 }
01658 }
01659 #endif
01660
01661 global->ctrl_sock = s;
01662 eloop_register_read_sock(s, wpa_supplicant_global_ctrl_iface_receive,
01663 global, NULL);
01664
01665 return 0;
01666
01667 fail:
01668 if (s >= 0)
01669 close(s);
01670 return -1;
01671 }
01672
01673
01682 void wpa_supplicant_global_ctrl_iface_deinit(struct wpa_global *global)
01683 {
01684 if (global->ctrl_sock < 0)
01685 return;
01686
01687 eloop_unregister_read_sock(global->ctrl_sock);
01688 close(global->ctrl_sock);
01689 global->ctrl_sock = -1;
01690
01691 #ifndef CONFIG_CTRL_IFACE_UDP
01692 if (global->params.ctrl_interface)
01693 unlink(global->params.ctrl_interface);
01694 #endif
01695 }
01696