X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=hostapd%2Fctrl_iface.c;h=1886b7783fe6943bd7dc0e8e3d1e7bf0d7d99f97;hb=403b96fe4f31e4bf2ca7f2715da179bc7b025085;hp=e03e66fa11410a1adb63ce0fa4133a3f09027c2c;hpb=31fcea931d916fd3dec2522822f87a7148b45a99;p=libeap.git diff --git a/hostapd/ctrl_iface.c b/hostapd/ctrl_iface.c index e03e66f..1886b77 100644 --- a/hostapd/ctrl_iface.c +++ b/hostapd/ctrl_iface.c @@ -34,6 +34,8 @@ #include "ap/accounting.h" #include "ap/wps_hostapd.h" #include "ap/ctrl_iface_ap.h" +#include "wps/wps_defs.h" +#include "wps/wps.h" #include "ctrl_iface.h" @@ -155,6 +157,59 @@ static int hostapd_ctrl_iface_new_sta(struct hostapd_data *hapd, } +#ifdef CONFIG_P2P_MANAGER +static int p2p_manager_disconnect(struct hostapd_data *hapd, u16 stype, + u8 minor_reason_code, const u8 *addr) +{ + struct ieee80211_mgmt *mgmt; + int ret; + u8 *pos; + + if (hapd->driver->send_frame == NULL) + return -1; + + mgmt = os_zalloc(sizeof(*mgmt) + 100); + if (mgmt == NULL) + return -1; + + wpa_printf(MSG_DEBUG, "P2P: Disconnect STA " MACSTR " with minor " + "reason code %u (stype=%u)", + MAC2STR(addr), minor_reason_code, stype); + + mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, stype); + os_memcpy(mgmt->da, addr, ETH_ALEN); + os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); + if (stype == WLAN_FC_STYPE_DEAUTH) { + mgmt->u.deauth.reason_code = + host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); + pos = (u8 *) (&mgmt->u.deauth.reason_code + 1); + } else { + mgmt->u.disassoc.reason_code = + host_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); + pos = (u8 *) (&mgmt->u.disassoc.reason_code + 1); + } + + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = 4 + 3 + 1; + WPA_PUT_BE24(pos, OUI_WFA); + pos += 3; + *pos++ = P2P_OUI_TYPE; + + *pos++ = P2P_ATTR_MINOR_REASON_CODE; + WPA_PUT_LE16(pos, 1); + pos += 2; + *pos++ = minor_reason_code; + + ret = hapd->driver->send_frame(hapd->drv_priv, (u8 *) mgmt, + pos - (u8 *) mgmt, 1); + os_free(mgmt); + + return ret < 0 ? -1 : 0; +} +#endif /* CONFIG_P2P_MANAGER */ + + static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd, const char *txtaddr) { @@ -191,6 +246,14 @@ static int hostapd_ctrl_iface_deauthenticate(struct hostapd_data *hapd, return 0; } +#ifdef CONFIG_P2P_MANAGER + pos = os_strstr(txtaddr, " p2p="); + if (pos) { + return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DEAUTH, + atoi(pos + 5), addr); + } +#endif /* CONFIG_P2P_MANAGER */ + hapd->drv.sta_deauth(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); sta = ap_get_sta(hapd, addr); if (sta) @@ -237,6 +300,14 @@ static int hostapd_ctrl_iface_disassociate(struct hostapd_data *hapd, return 0; } +#ifdef CONFIG_P2P_MANAGER + pos = os_strstr(txtaddr, " p2p="); + if (pos) { + return p2p_manager_disconnect(hapd, WLAN_FC_STYPE_DISASSOC, + atoi(pos + 5), addr); + } +#endif /* CONFIG_P2P_MANAGER */ + hapd->drv.sta_disassoc(hapd, addr, WLAN_REASON_PREV_AUTH_NOT_VALID); sta = ap_get_sta(hapd, addr); if (sta) @@ -299,6 +370,51 @@ static int hostapd_ctrl_iface_wps_pin(struct hostapd_data *hapd, char *txt) } +static int hostapd_ctrl_iface_wps_check_pin( + struct hostapd_data *hapd, char *cmd, char *buf, size_t buflen) +{ + char pin[9]; + size_t len; + char *pos; + int ret; + + wpa_hexdump_ascii_key(MSG_DEBUG, "WPS_CHECK_PIN", + (u8 *) cmd, os_strlen(cmd)); + for (pos = cmd, len = 0; *pos != '\0'; pos++) { + if (*pos < '0' || *pos > '9') + continue; + pin[len++] = *pos; + if (len == 9) { + wpa_printf(MSG_DEBUG, "WPS: Too long PIN"); + return -1; + } + } + if (len != 4 && len != 8) { + wpa_printf(MSG_DEBUG, "WPS: Invalid PIN length %d", (int) len); + return -1; + } + pin[len] = '\0'; + + if (len == 8) { + unsigned int pin_val; + pin_val = atoi(pin); + if (!wps_pin_valid(pin_val)) { + wpa_printf(MSG_DEBUG, "WPS: Invalid checksum digit"); + ret = os_snprintf(buf, buflen, "FAIL-CHECKSUM\n"); + if (ret < 0 || (size_t) ret >= buflen) + return -1; + return ret; + } + } + + ret = os_snprintf(buf, buflen, "%s", pin); + if (ret < 0 || (size_t) ret >= buflen) + return -1; + + return ret; +} + + #ifdef CONFIG_WPS_OOB static int hostapd_ctrl_iface_wps_oob(struct hostapd_data *hapd, char *txt) { @@ -377,6 +493,212 @@ static int hostapd_ctrl_iface_wps_ap_pin(struct hostapd_data *hapd, char *txt, #endif /* CONFIG_WPS */ +static int hostapd_ctrl_iface_get_config(struct hostapd_data *hapd, + char *buf, size_t buflen) +{ + int ret; + char *pos, *end; + + pos = buf; + end = buf + buflen; + + ret = os_snprintf(pos, end - pos, "bssid=" MACSTR "\n" + "ssid=%s\n", + MAC2STR(hapd->own_addr), + hapd->conf->ssid.ssid); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + +#ifdef CONFIG_WPS + ret = os_snprintf(pos, end - pos, "wps_state=%s\n", + hapd->conf->wps_state == 0 ? "disabled" : + (hapd->conf->wps_state == 1 ? "not configured" : + "configured")); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + + if (hapd->conf->wps_state && + hapd->conf->ssid.wpa_passphrase) { + ret = os_snprintf(pos, end - pos, "passphrase=%s\n", + hapd->conf->ssid.wpa_passphrase); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } + + if (hapd->conf->wps_state && hapd->conf->ssid.wpa_psk && + hapd->conf->ssid.wpa_psk->group) { + char hex[PMK_LEN * 2 + 1]; + wpa_snprintf_hex(hex, sizeof(hex), + hapd->conf->ssid.wpa_psk->psk, PMK_LEN); + ret = os_snprintf(pos, end - pos, "psk=%s\n", hex); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_WPS */ + + if (hapd->conf->wpa && hapd->conf->wpa_key_mgmt) { + ret = os_snprintf(pos, end - pos, "key_mgmt="); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + + if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { + ret = os_snprintf(pos, end - pos, "WPA-PSK "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } + if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { + ret = os_snprintf(pos, end - pos, "WPA-EAP "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } +#ifdef CONFIG_IEEE80211R + if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { + ret = os_snprintf(pos, end - pos, "FT-PSK "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } + if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { + ret = os_snprintf(pos, end - pos, "FT-EAP "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { + ret = os_snprintf(pos, end - pos, "WPA-PSK-SHA256 "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } + if (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { + ret = os_snprintf(pos, end - pos, "WPA-EAP-SHA256 "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } +#endif /* CONFIG_IEEE80211W */ + + ret = os_snprintf(pos, end - pos, "\n"); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } + + if (hapd->conf->wpa_group == WPA_CIPHER_CCMP) { + ret = os_snprintf(pos, end - pos, "group_cipher=CCMP\n"); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } else if (hapd->conf->wpa_group == WPA_CIPHER_TKIP) { + ret = os_snprintf(pos, end - pos, "group_cipher=TKIP\n"); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } + + if ((hapd->conf->wpa & WPA_PROTO_RSN) && hapd->conf->rsn_pairwise) { + ret = os_snprintf(pos, end - pos, "rsn_pairwise_cipher="); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + + if (hapd->conf->rsn_pairwise & WPA_CIPHER_CCMP) { + ret = os_snprintf(pos, end - pos, "CCMP "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } + if (hapd->conf->rsn_pairwise & WPA_CIPHER_TKIP) { + ret = os_snprintf(pos, end - pos, "TKIP "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } + + ret = os_snprintf(pos, end - pos, "\n"); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } + + if ((hapd->conf->wpa & WPA_PROTO_WPA) && hapd->conf->wpa_pairwise) { + ret = os_snprintf(pos, end - pos, "wpa_pairwise_cipher="); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + + if (hapd->conf->wpa_pairwise & WPA_CIPHER_CCMP) { + ret = os_snprintf(pos, end - pos, "CCMP "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } + if (hapd->conf->wpa_pairwise & WPA_CIPHER_TKIP) { + ret = os_snprintf(pos, end - pos, "TKIP "); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } + + ret = os_snprintf(pos, end - pos, "\n"); + if (ret < 0 || ret >= end - pos) + return pos - buf; + pos += ret; + } + + return pos - buf; +} + + +static int hostapd_ctrl_iface_set(struct hostapd_data *wpa_s, char *cmd) +{ + char *value; + int ret = 0; + + value = os_strchr(cmd, ' '); + if (value == NULL) + return -1; + *value++ = '\0'; + + wpa_printf(MSG_DEBUG, "CTRL_IFACE SET '%s'='%s'", cmd, value); + if (0) { +#ifdef CONFIG_WPS_TESTING + } else if (os_strcasecmp(cmd, "wps_version_number") == 0) { + long int val; + val = strtol(value, NULL, 0); + if (val < 0 || val > 0xff) { + ret = -1; + wpa_printf(MSG_DEBUG, "WPS: Invalid " + "wps_version_number %ld", val); + } else { + wps_version_number = val; + wpa_printf(MSG_DEBUG, "WPS: Testing - force WPS " + "version %u.%u", + (wps_version_number & 0xf0) >> 4, + wps_version_number & 0x0f); + } + } else if (os_strcasecmp(cmd, "wps_testing_dummy_cred") == 0) { + wps_testing_dummy_cred = atoi(value); + wpa_printf(MSG_DEBUG, "WPS: Testing - dummy_cred=%d", + wps_testing_dummy_cred); +#endif /* CONFIG_WPS_TESTING */ + } else { + ret = -1; + } + + return ret; +} + + static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, void *sock_ctx) { @@ -479,6 +801,9 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, } else if (os_strncmp(buf, "WPS_PIN ", 8) == 0) { if (hostapd_ctrl_iface_wps_pin(hapd, buf + 8)) reply_len = -1; + } else if (os_strncmp(buf, "WPS_CHECK_PIN ", 14) == 0) { + reply_len = hostapd_ctrl_iface_wps_check_pin( + hapd, buf + 14, reply, reply_size); } else if (os_strcmp(buf, "WPS_PBC") == 0) { if (hostapd_wps_button_pushed(hapd)) reply_len = -1; @@ -491,6 +816,12 @@ static void hostapd_ctrl_iface_receive(int sock, void *eloop_ctx, reply_len = hostapd_ctrl_iface_wps_ap_pin(hapd, buf + 11, reply, reply_size); #endif /* CONFIG_WPS */ + } else if (os_strcmp(buf, "GET_CONFIG") == 0) { + reply_len = hostapd_ctrl_iface_get_config(hapd, reply, + reply_size); + } else if (os_strncmp(buf, "SET ", 4) == 0) { + if (hostapd_ctrl_iface_set(hapd, buf + 4)) + reply_len = -1; } else { os_memcpy(reply, "UNKNOWN COMMAND\n", 16); reply_len = 16;