#include "bss.h"
#include "scan.h"
#include "ctrl_iface.h"
+#include "interworking.h"
+#include "blacklist.h"
+#include "wpas_glue.h"
extern struct wpa_driver_ops *wpa_drivers[];
char *buf, int len);
+static int pno_start(struct wpa_supplicant *wpa_s)
+{
+ int ret;
+ size_t i, num_ssid;
+ struct wpa_ssid *ssid;
+ struct wpa_driver_scan_params params;
+
+ if (wpa_s->pno)
+ return 0;
+
+ os_memset(¶ms, 0, sizeof(params));
+
+ num_ssid = 0;
+ ssid = wpa_s->conf->ssid;
+ while (ssid) {
+ if (!ssid->disabled)
+ num_ssid++;
+ ssid = ssid->next;
+ }
+ if (num_ssid > WPAS_MAX_SCAN_SSIDS) {
+ wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from "
+ "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid);
+ num_ssid = WPAS_MAX_SCAN_SSIDS;
+ }
+
+ if (num_ssid == 0) {
+ wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs");
+ return -1;
+ }
+
+ params.filter_ssids = os_malloc(sizeof(struct wpa_driver_scan_filter) *
+ num_ssid);
+ if (params.filter_ssids == NULL)
+ return -1;
+ i = 0;
+ ssid = wpa_s->conf->ssid;
+ while (ssid) {
+ if (!ssid->disabled) {
+ params.ssids[i].ssid = ssid->ssid;
+ params.ssids[i].ssid_len = ssid->ssid_len;
+ params.num_ssids++;
+ os_memcpy(params.filter_ssids[i].ssid, ssid->ssid,
+ ssid->ssid_len);
+ params.filter_ssids[i].ssid_len = ssid->ssid_len;
+ params.num_filter_ssids++;
+ i++;
+ if (i == num_ssid)
+ break;
+ }
+ ssid = ssid->next;
+ }
+
+ ret = wpa_drv_sched_scan(wpa_s, ¶ms, 10 * 1000);
+ os_free(params.filter_ssids);
+ if (ret == 0)
+ wpa_s->pno = 1;
+ return ret;
+}
+
+
+static int pno_stop(struct wpa_supplicant *wpa_s)
+{
+ if (wpa_s->pno) {
+ wpa_s->pno = 0;
+ return wpa_drv_stop_sched_scan(wpa_s);
+ }
+ return 0;
+}
+
+
static int wpa_supplicant_ctrl_iface_set(struct wpa_supplicant *wpa_s,
char *cmd)
{
ret = -1;
wpa_tdls_enable(wpa_s->wpa, !disabled);
#endif /* CONFIG_TDLS */
+ } else if (os_strcasecmp(cmd, "pno") == 0) {
+ if (atoi(value))
+ ret = pno_start(wpa_s);
+ else
+ ret = pno_stop(wpa_s);
} else {
value[-1] = '=';
ret = wpa_config_process_global(wpa_s->conf, cmd, -1);
static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s,
char *cmd, char *buf, size_t buflen)
{
- int res;
+ int res = -1;
wpa_printf(MSG_DEBUG, "CTRL_IFACE GET '%s'", cmd);
if (os_strcmp(cmd, "version") == 0) {
res = os_snprintf(buf, buflen, "%s", VERSION_STR);
- if (res < 0 || (unsigned int) res >= buflen)
- return -1;
- return res;
+ } else if (os_strcasecmp(cmd, "country") == 0) {
+ if (wpa_s->conf->country[0] && wpa_s->conf->country[1])
+ res = os_snprintf(buf, buflen, "%c%c",
+ wpa_s->conf->country[0],
+ wpa_s->conf->country[1]);
}
- return -1;
+ if (res < 0 || (unsigned int) res >= buflen)
+ return -1;
+ return res;
}
struct wpa_supplicant *wpa_s, char *addr)
{
u8 peer[ETH_ALEN];
+ int ret;
if (hwaddr_aton(addr, peer)) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER: invalid "
wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_DISCOVER " MACSTR,
MAC2STR(peer));
- return wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
+ if (wpa_tdls_is_external_setup(wpa_s->wpa))
+ ret = wpa_tdls_send_discovery_request(wpa_s->wpa, peer);
+ else
+ ret = wpa_drv_tdls_oper(wpa_s, TDLS_DISCOVERY_REQ, peer);
+
+ return ret;
}
MAC2STR(peer));
ret = wpa_tdls_reneg(wpa_s->wpa, peer);
- if (ret)
- ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
+ if (ret) {
+ if (wpa_tdls_is_external_setup(wpa_s->wpa))
+ ret = wpa_tdls_start(wpa_s->wpa, peer);
+ else
+ ret = wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, peer);
+ }
+
return ret;
}
wpa_printf(MSG_DEBUG, "CTRL_IFACE TDLS_TEARDOWN " MACSTR,
MAC2STR(peer));
- return wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, peer);
+ return wpa_tdls_teardown_link(wpa_s->wpa, peer,
+ WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED);
}
#endif /* CONFIG_TDLS */
char *cmd)
{
u8 bssid[ETH_ALEN], *_bssid = bssid;
- u8 p2p_dev_addr[ETH_ALEN], *_p2p_dev_addr = NULL;
+#ifdef CONFIG_P2P
+ u8 p2p_dev_addr[ETH_ALEN];
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_AP
+ u8 *_p2p_dev_addr = NULL;
+#endif /* CONFIG_AP */
if (cmd == NULL || os_strcmp(cmd, "any") == 0) {
_bssid = NULL;
if (os_strcmp(cmd, "any") == 0)
_bssid = NULL;
- else if (hwaddr_aton(cmd, bssid)) {
+ else if (os_strcmp(cmd, "get") == 0) {
+ ret = wps_generate_pin();
+ goto done;
+ } else if (hwaddr_aton(cmd, bssid)) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PIN: invalid BSSID '%s'",
cmd);
return -1;
if (ret < 0)
return -1;
+done:
/* Return the generated PIN */
ret = os_snprintf(buf, buflen, "%08d", ret);
if (ret < 0 || (size_t) ret >= buflen)
#endif /* CONFIG_IBSS_RSN */
-static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
- char *rsp)
+int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid,
+ const char *field,
+ const char *value)
{
-#ifdef IEEE8021X_EAPOL
- char *pos, *id_pos;
- int id;
- struct wpa_ssid *ssid;
- struct eap_peer_config *eap;
+ struct eap_peer_config *eap = &ssid->eap;
- pos = os_strchr(rsp, '-');
- if (pos == NULL)
- return -1;
- *pos++ = '\0';
- id_pos = pos;
- pos = os_strchr(pos, ':');
- if (pos == NULL)
- return -1;
- *pos++ = '\0';
- id = atoi(id_pos);
- wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
- wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
- (u8 *) pos, os_strlen(pos));
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: response handle field=%s", field);
+ wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: response value",
+ (const u8 *) value, os_strlen(value));
- ssid = wpa_config_get_network(wpa_s->conf, id);
- if (ssid == NULL) {
- wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
- "to update", id);
- return -1;
- }
- eap = &ssid->eap;
-
- if (os_strcmp(rsp, "IDENTITY") == 0) {
+ switch (wpa_supplicant_ctrl_req_from_string(field)) {
+ case WPA_CTRL_REQ_EAP_IDENTITY:
os_free(eap->identity);
- eap->identity = (u8 *) os_strdup(pos);
- eap->identity_len = os_strlen(pos);
+ eap->identity = (u8 *) os_strdup(value);
+ eap->identity_len = os_strlen(value);
eap->pending_req_identity = 0;
if (ssid == wpa_s->current_ssid)
wpa_s->reassociate = 1;
- } else if (os_strcmp(rsp, "PASSWORD") == 0) {
+ break;
+ case WPA_CTRL_REQ_EAP_PASSWORD:
os_free(eap->password);
- eap->password = (u8 *) os_strdup(pos);
- eap->password_len = os_strlen(pos);
+ eap->password = (u8 *) os_strdup(value);
+ eap->password_len = os_strlen(value);
eap->pending_req_password = 0;
if (ssid == wpa_s->current_ssid)
wpa_s->reassociate = 1;
- } else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) {
+ break;
+ case WPA_CTRL_REQ_EAP_NEW_PASSWORD:
os_free(eap->new_password);
- eap->new_password = (u8 *) os_strdup(pos);
- eap->new_password_len = os_strlen(pos);
+ eap->new_password = (u8 *) os_strdup(value);
+ eap->new_password_len = os_strlen(value);
eap->pending_req_new_password = 0;
if (ssid == wpa_s->current_ssid)
wpa_s->reassociate = 1;
- } else if (os_strcmp(rsp, "PIN") == 0) {
+ break;
+ case WPA_CTRL_REQ_EAP_PIN:
os_free(eap->pin);
- eap->pin = os_strdup(pos);
+ eap->pin = os_strdup(value);
eap->pending_req_pin = 0;
if (ssid == wpa_s->current_ssid)
wpa_s->reassociate = 1;
- } else if (os_strcmp(rsp, "OTP") == 0) {
+ break;
+ case WPA_CTRL_REQ_EAP_OTP:
os_free(eap->otp);
- eap->otp = (u8 *) os_strdup(pos);
- eap->otp_len = os_strlen(pos);
+ eap->otp = (u8 *) os_strdup(value);
+ eap->otp_len = os_strlen(value);
os_free(eap->pending_req_otp);
eap->pending_req_otp = NULL;
eap->pending_req_otp_len = 0;
- } else if (os_strcmp(rsp, "PASSPHRASE") == 0) {
+ break;
+ case WPA_CTRL_REQ_EAP_PASSPHRASE:
os_free(eap->private_key_passwd);
- eap->private_key_passwd = (u8 *) os_strdup(pos);
+ eap->private_key_passwd = (u8 *) os_strdup(value);
eap->pending_req_passphrase = 0;
if (ssid == wpa_s->current_ssid)
wpa_s->reassociate = 1;
- } else {
- wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
+ break;
+ default:
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", field);
return -1;
}
return 0;
+}
+
+
+static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
+ char *rsp)
+{
+#ifdef IEEE8021X_EAPOL
+ char *pos, *id_pos;
+ int id;
+ struct wpa_ssid *ssid;
+
+ pos = os_strchr(rsp, '-');
+ if (pos == NULL)
+ return -1;
+ *pos++ = '\0';
+ id_pos = pos;
+ pos = os_strchr(pos, ':');
+ if (pos == NULL)
+ return -1;
+ *pos++ = '\0';
+ id = atoi(id_pos);
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
+ wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
+ (u8 *) pos, os_strlen(pos));
+
+ ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (ssid == NULL) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
+ "to update", id);
+ return -1;
+ }
+
+ return wpa_supplicant_ctrl_iface_ctrl_rsp_handle(wpa_s, ssid, rsp,
+ pos);
#else /* IEEE8021X_EAPOL */
wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
return -1;
char *buf, size_t buflen)
{
char *pos, *end, tmp[30];
- int res, verbose, ret;
+ int res, verbose, wps, ret;
verbose = os_strcmp(params, "-VERBOSE") == 0;
+ wps = os_strcmp(params, "-WPS") == 0;
pos = buf;
end = buf + buflen;
if (wpa_s->wpa_state >= WPA_ASSOCIATED) {
return pos - buf;
pos += ret;
+ if (wps && ssid->passphrase &&
+ wpa_key_mgmt_wpa_psk(ssid->key_mgmt) &&
+ (ssid->mode == WPAS_MODE_AP ||
+ ssid->mode == WPAS_MODE_P2P_GO)) {
+ ret = os_snprintf(pos, end - pos,
+ "passphrase=%s\n",
+ ssid->passphrase);
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+ }
if (ssid->id_str) {
ret = os_snprintf(pos, end - pos,
"id_str=%s\n",
}
+static int wpa_supplicant_ctrl_iface_blacklist(struct wpa_supplicant *wpa_s,
+ char *cmd, char *buf,
+ size_t buflen)
+{
+ u8 bssid[ETH_ALEN];
+ struct wpa_blacklist *e;
+ char *pos, *end;
+ int ret;
+
+ /* cmd: "BLACKLIST [<BSSID>]" */
+ if (*cmd == '\0') {
+ pos = buf;
+ end = buf + buflen;
+ e = wpa_s->blacklist;
+ while (e) {
+ ret = os_snprintf(pos, end - pos, MACSTR "\n",
+ MAC2STR(e->bssid));
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+ e = e->next;
+ }
+ return pos - buf;
+ }
+
+ cmd++;
+ if (os_strncmp(cmd, "clear", 5) == 0) {
+ wpa_blacklist_clear(wpa_s);
+ os_memcpy(buf, "OK\n", 3);
+ return 3;
+ }
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: BLACKLIST bssid='%s'", cmd);
+ if (hwaddr_aton(cmd, bssid)) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: invalid BSSID '%s'", cmd);
+ return -1;
+ }
+
+ /*
+ * Add the BSSID twice, so its count will be 2, causing it to be
+ * skipped when processing scan results.
+ */
+ ret = wpa_blacklist_add(wpa_s, bssid);
+ if (ret != 0)
+ return -1;
+ ret = wpa_blacklist_add(wpa_s, bssid);
+ if (ret != 0)
+ return -1;
+ os_memcpy(buf, "OK\n", 3);
+ return 3;
+}
+
+
+extern int wpa_debug_level;
+extern int wpa_debug_timestamp;
+
+static const char * debug_level_str(int level)
+{
+ switch (level) {
+ case MSG_EXCESSIVE:
+ return "EXCESSIVE";
+ case MSG_MSGDUMP:
+ return "MSGDUMP";
+ case MSG_DEBUG:
+ return "DEBUG";
+ case MSG_INFO:
+ return "INFO";
+ case MSG_WARNING:
+ return "WARNING";
+ case MSG_ERROR:
+ return "ERROR";
+ default:
+ return "?";
+ }
+}
+
+
+static int str_to_debug_level(const char *s)
+{
+ if (os_strcasecmp(s, "EXCESSIVE") == 0)
+ return MSG_EXCESSIVE;
+ if (os_strcasecmp(s, "MSGDUMP") == 0)
+ return MSG_MSGDUMP;
+ if (os_strcasecmp(s, "DEBUG") == 0)
+ return MSG_DEBUG;
+ if (os_strcasecmp(s, "INFO") == 0)
+ return MSG_INFO;
+ if (os_strcasecmp(s, "WARNING") == 0)
+ return MSG_WARNING;
+ if (os_strcasecmp(s, "ERROR") == 0)
+ return MSG_ERROR;
+ return -1;
+}
+
+
+static int wpa_supplicant_ctrl_iface_log_level(struct wpa_supplicant *wpa_s,
+ char *cmd, char *buf,
+ size_t buflen)
+{
+ char *pos, *end, *stamp;
+ int ret;
+
+ if (cmd == NULL) {
+ return -1;
+ }
+
+ /* cmd: "LOG_LEVEL [<level>]" */
+ if (*cmd == '\0') {
+ pos = buf;
+ end = buf + buflen;
+ ret = os_snprintf(pos, end - pos, "Current level: %s\n"
+ "Timestamp: %d\n",
+ debug_level_str(wpa_debug_level),
+ wpa_debug_timestamp);
+ if (ret < 0 || ret >= end - pos)
+ ret = 0;
+
+ return ret;
+ }
+
+ while (*cmd == ' ')
+ cmd++;
+
+ stamp = os_strchr(cmd, ' ');
+ if (stamp) {
+ *stamp++ = '\0';
+ while (*stamp == ' ') {
+ stamp++;
+ }
+ }
+
+ if (cmd && os_strlen(cmd)) {
+ int level = str_to_debug_level(cmd);
+ if (level < 0)
+ return -1;
+ wpa_debug_level = level;
+ }
+
+ if (stamp && os_strlen(stamp))
+ wpa_debug_timestamp = atoi(stamp);
+
+ os_memcpy(buf, "OK\n", 3);
+ return 3;
+}
+
+
static int wpa_supplicant_ctrl_iface_list_networks(
struct wpa_supplicant *wpa_s, char *buf, size_t buflen)
{
wpas_notify_network_removed(wpa_s, remove_ssid);
wpa_config_remove_network(wpa_s->conf, id);
}
+ eapol_sm_invalidate_cached_session(wpa_s->eapol);
if (wpa_s->current_ssid) {
- eapol_sm_invalidate_cached_session(wpa_s->eapol);
+ wpa_sm_set_config(wpa_s->wpa, NULL);
+ eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
wpa_supplicant_disassociate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING);
}
wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK id=%d", id);
ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (ssid)
+ wpas_notify_network_removed(wpa_s, ssid);
if (ssid == NULL ||
wpa_config_remove_network(wpa_s->conf, id) < 0) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
return -1;
}
- if (ssid == wpa_s->current_ssid) {
+ if (ssid == wpa_s->current_ssid || wpa_s->current_ssid == NULL) {
/*
- * Invalidate the EAP session cache if the current network is
- * removed.
+ * Invalidate the EAP session cache if the current or
+ * previously used network is removed.
*/
eapol_sm_invalidate_cached_session(wpa_s->eapol);
+ }
+
+ if (ssid == wpa_s->current_ssid) {
+ wpa_sm_set_config(wpa_s->wpa, NULL);
+ eapol_sm_notify_config(wpa_s->eapol, NULL, NULL);
wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
}
return -1;
}
- if (wpa_s->current_ssid == ssid) {
+ wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid);
+
+ if (wpa_s->current_ssid == ssid || wpa_s->current_ssid == NULL) {
/*
* Invalidate the EAP session cache if anything in the current
- * configuration changes.
+ * or previously used configuration changes.
*/
eapol_sm_invalidate_cached_session(wpa_s->eapol);
}
}
+#ifdef CONFIG_INTERWORKING
+static char * anqp_add_hex(char *pos, char *end, const char *title,
+ struct wpabuf *data)
+{
+ char *start = pos;
+ size_t i;
+ int ret;
+ const u8 *d;
+
+ if (data == NULL)
+ return start;
+
+ ret = os_snprintf(pos, end - pos, "%s=", title);
+ if (ret < 0 || ret >= end - pos)
+ return start;
+ pos += ret;
+
+ d = wpabuf_head_u8(data);
+ for (i = 0; i < wpabuf_len(data); i++) {
+ ret = os_snprintf(pos, end - pos, "%02x", *d++);
+ if (ret < 0 || ret >= end - pos)
+ return start;
+ pos += ret;
+ }
+
+ ret = os_snprintf(pos, end - pos, "\n");
+ if (ret < 0 || ret >= end - pos)
+ return start;
+ pos += ret;
+
+ return pos;
+}
+#endif /* CONFIG_INTERWORKING */
+
+
static int wpa_supplicant_ctrl_iface_bss(struct wpa_supplicant *wpa_s,
const char *cmd, char *buf,
size_t buflen)
return pos - buf;
pos += ret;
}
- if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) {
- ret = os_snprintf(pos, end - pos, "[P2P]");
- 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 (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE)) {
+ ret = os_snprintf(pos, end - pos, "[P2P]");
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+ }
ret = os_snprintf(pos, end - pos, "\n");
if (ret < 0 || ret >= end - pos)
pos += ret;
#endif /* CONFIG_P2P */
+#ifdef CONFIG_INTERWORKING
+ pos = anqp_add_hex(pos, end, "anqp_venue_name", bss->anqp_venue_name);
+ pos = anqp_add_hex(pos, end, "anqp_network_auth_type",
+ bss->anqp_network_auth_type);
+ pos = anqp_add_hex(pos, end, "anqp_roaming_consortium",
+ bss->anqp_roaming_consortium);
+ pos = anqp_add_hex(pos, end, "anqp_ip_addr_type_availability",
+ bss->anqp_ip_addr_type_availability);
+ pos = anqp_add_hex(pos, end, "anqp_nai_realm", bss->anqp_nai_realm);
+ pos = anqp_add_hex(pos, end, "anqp_3gpp", bss->anqp_3gpp);
+ pos = anqp_add_hex(pos, end, "anqp_domain_name",
+ bss->anqp_domain_name);
+#endif /* CONFIG_INTERWORKING */
+
return pos - buf;
}
wps_method = WPS_PIN_KEYPAD;
if (pos) {
*pos++ = '\0';
- if (os_strncmp(pos, "label", 5) == 0)
- wps_method = WPS_PIN_LABEL;
- else if (os_strncmp(pos, "display", 7) == 0)
+ if (os_strncmp(pos, "display", 7) == 0)
wps_method = WPS_PIN_DISPLAY;
}
}
u8 addr[ETH_ALEN];
char *pos;
- /* <addr> <config method> */
+ /* <addr> <config method> [join] */
if (hwaddr_aton(cmd, addr))
return -1;
return -1;
pos++;
- return wpas_p2p_prov_disc(wpa_s, addr, pos);
+ return wpas_p2p_prov_disc(wpa_s, addr, pos,
+ os_strstr(pos, "join") != NULL);
}
if (*pos != ' ')
return -1;
pos++;
- ref = (unsigned long) wpas_p2p_sd_request_upnp(wpa_s, dst,
- version, pos);
+ ref = wpas_p2p_sd_request_upnp(wpa_s, dst, version, pos);
} else {
len = os_strlen(pos);
if (len & 1)
return -1;
}
- ref = (unsigned long) wpas_p2p_sd_request(wpa_s, dst, tlvs);
+ ref = wpas_p2p_sd_request(wpa_s, dst, tlvs);
wpabuf_free(tlvs);
}
+ if (ref == 0)
+ return -1;
res = os_snprintf(buf, buflen, "%llx", (long long unsigned) ref);
if (res < 0 || (unsigned) res >= buflen)
return -1;
if (sscanf(cmd, "%llx", &val) != 1)
return -1;
req = val;
- return wpas_p2p_sd_cancel_request(wpa_s, (void *) (unsigned long) req);
+ return wpas_p2p_sd_cancel_request(wpa_s, req);
}
#endif /* CONFIG_P2P */
+#ifdef CONFIG_INTERWORKING
+static int ctrl_interworking_connect(struct wpa_supplicant *wpa_s, char *dst)
+{
+ u8 bssid[ETH_ALEN];
+ struct wpa_bss *bss;
+
+ if (hwaddr_aton(dst, bssid)) {
+ wpa_printf(MSG_DEBUG, "Invalid BSSID '%s'", dst);
+ return -1;
+ }
+
+ bss = wpa_bss_get_bssid(wpa_s, bssid);
+ if (bss == NULL) {
+ wpa_printf(MSG_DEBUG, "Could not find BSS " MACSTR,
+ MAC2STR(bssid));
+ return -1;
+ }
+
+ return interworking_connect(wpa_s, bss);
+}
+
+
+static int get_anqp(struct wpa_supplicant *wpa_s, char *dst)
+{
+ u8 dst_addr[ETH_ALEN];
+ int used;
+ char *pos;
+#define MAX_ANQP_INFO_ID 100
+ u16 id[MAX_ANQP_INFO_ID];
+ size_t num_id = 0;
+
+ used = hwaddr_aton2(dst, dst_addr);
+ if (used < 0)
+ return -1;
+ pos = dst + used;
+ while (num_id < MAX_ANQP_INFO_ID) {
+ id[num_id] = atoi(pos);
+ if (id[num_id])
+ num_id++;
+ pos = os_strchr(pos + 1, ',');
+ if (pos == NULL)
+ break;
+ pos++;
+ }
+
+ if (num_id == 0)
+ return -1;
+
+ return anqp_send_req(wpa_s, dst_addr, id, num_id);
+}
+#endif /* CONFIG_INTERWORKING */
+
+
static int wpa_supplicant_ctrl_iface_sta_autoconnect(
struct wpa_supplicant *wpa_s, char *cmd)
{
} else if (os_strcmp(buf, "LOGOFF") == 0) {
eapol_sm_notify_logoff(wpa_s->eapol, TRUE);
} else if (os_strcmp(buf, "REASSOCIATE") == 0) {
+ wpa_s->normal_scans = 0;
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
reply_len = -1;
else {
wpa_supplicant_req_scan(wpa_s, 0, 0);
}
} else if (os_strcmp(buf, "RECONNECT") == 0) {
+ wpa_s->normal_scans = 0;
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
reply_len = -1;
else if (wpa_s->disconnected) {
if (p2p_ctrl_ext_listen(wpa_s, "") < 0)
reply_len = -1;
#endif /* CONFIG_P2P */
+#ifdef CONFIG_INTERWORKING
+ } else if (os_strcmp(buf, "FETCH_ANQP") == 0) {
+ if (interworking_fetch_anqp(wpa_s) < 0)
+ reply_len = -1;
+ } else if (os_strcmp(buf, "STOP_FETCH_ANQP") == 0) {
+ interworking_stop_fetch_anqp(wpa_s);
+ } else if (os_strncmp(buf, "INTERWORKING_SELECT", 19) == 0) {
+ if (interworking_select(wpa_s, os_strstr(buf + 19, "auto") !=
+ NULL) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "INTERWORKING_CONNECT ", 21) == 0) {
+ if (ctrl_interworking_connect(wpa_s, buf + 21) < 0)
+ reply_len = -1;
+ } else if (os_strncmp(buf, "ANQP_GET ", 9) == 0) {
+ if (get_anqp(wpa_s, buf + 9) < 0)
+ reply_len = -1;
+#endif /* CONFIG_INTERWORKING */
} else if (os_strncmp(buf, WPA_CTRL_RSP, os_strlen(WPA_CTRL_RSP)) == 0)
{
if (wpa_supplicant_ctrl_iface_ctrl_rsp(
} else if (os_strncmp(buf, "BSSID ", 6) == 0) {
if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))
reply_len = -1;
+ } else if (os_strncmp(buf, "BLACKLIST", 9) == 0) {
+ reply_len = wpa_supplicant_ctrl_iface_blacklist(
+ wpa_s, buf + 9, reply, reply_size);
+ } else if (os_strncmp(buf, "LOG_LEVEL", 9) == 0) {
+ reply_len = wpa_supplicant_ctrl_iface_log_level(
+ wpa_s, buf + 9, reply, reply_size);
} else if (os_strcmp(buf, "LIST_NETWORKS") == 0) {
reply_len = wpa_supplicant_ctrl_iface_list_networks(
wpa_s, reply, reply_size);
} else if (os_strcmp(buf, "DISCONNECT") == 0) {
wpa_s->reassociate = 0;
wpa_s->disconnected = 1;
+ wpa_supplicant_cancel_sched_scan(wpa_s);
wpa_supplicant_deauthenticate(wpa_s,
WLAN_REASON_DEAUTH_LEAVING);
} else if (os_strcmp(buf, "SCAN") == 0) {
+ wpa_s->normal_scans = 0;
if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED)
reply_len = -1;
else {
} else if (os_strncmp(buf, "SIGNAL_POLL", 11) == 0) {
reply_len = wpa_supplicant_signal_poll(wpa_s, reply,
reply_size);
+ } else if (os_strcmp(buf, "REAUTHENTICATE") == 0) {
+ eapol_sm_request_reauth(wpa_s->eapol);
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
char *reply;
const int reply_size = 2048;
int reply_len;
+ int level = MSG_DEBUG;
- wpa_hexdump_ascii(MSG_DEBUG, "RX global ctrl_iface",
+ if (os_strcmp(buf, "PING") == 0)
+ level = MSG_EXCESSIVE;
+ wpa_hexdump_ascii(level, "RX global ctrl_iface",
(const u8 *) buf, os_strlen(buf));
reply = os_malloc(reply_size);