ctrl_iface.c

Go to the documentation of this file.
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 /* CONFIG_NATIVE_WINDOWS */
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 /* CONFIG_CTRL_IFACE_UDP */
00048 #define CTRL_IFACE_SOCK struct sockaddr_un
00049 #endif /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
00150         wpa_hexdump(MSG_DEBUG, "CTRL_IFACE monitor attached",
00151                     (u8 *) from->sun_path, fromlen - sizeof(from->sun_family));
00152 #endif /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
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         /* cmd: "<network id> <BSSID>" */
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         /* cmd: "<network id>" or "any" */
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         /* Mark all other networks disabled and trigger reassociation */
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         /* cmd: "<network id>" */
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                  * Try to reassociate since there is no current configuration
00607                  * and a new network was made available. */
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         /* cmd: "<network id>" */
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         /* cmd: "<network id>" */
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         /* cmd: "<network id> <variable name> <value>" */
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         /* cmd: "<network id> <variable name>" */
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                 /* Windows/WinPcap uses interface names that are not suitable
01114                  * as a file name - convert invalid chars to underscores */
01115                 char *pos = buf;
01116                 while (*pos) {
01117                         if (*pos == '\\')
01118                                 *pos = '_';
01119                         pos++;
01120                 }
01121         }
01122 #endif /* __CYGWIN__ */
01123         return buf;
01124 }
01125 #endif /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
01278                 eloop_unregister_read_sock(wpa_s->ctrl_sock);
01279                 if (wpa_s->ctrl_dst) {
01280                         /*
01281                          * Wait a second before closing the control socket if
01282                          * there are any attached monitors in order to allow
01283                          * them to receive any pending messages.
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 /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
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          * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
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 /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
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 /* CONFIG_CTRL_IFACE_UDP */
01695 }
01696 

Generated on Sat May 6 21:13:31 2006 for wpa_supplicant by  doxygen 1.4.2