/*
* WPA Supplicant / Control interface (shared code for all backends)
- * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
#include "config.h"
#include "eapol_supp/eapol_supp_sm.h"
#include "wpa_supplicant_i.h"
+#include "driver_i.h"
#include "ctrl_iface.h"
#include "l2_packet/l2_packet.h"
#include "preauth.h"
#include "ieee802_11_defs.h"
#include "wps_supplicant.h"
#include "wps/wps.h"
+#include "ibss_rsn.h"
+#include "ap.h"
+#include "notify.h"
+
+extern struct wpa_driver_ops *wpa_drivers[];
static int wpa_supplicant_global_iface_list(struct wpa_global *global,
char *buf, int len);
static int wpa_supplicant_ctrl_iface_wps_pbc(struct wpa_supplicant *wpa_s,
char *cmd)
{
- u8 bssid[ETH_ALEN];
+ u8 bssid[ETH_ALEN], *_bssid = bssid;
if (cmd == NULL || os_strcmp(cmd, "any") == 0)
- return wpas_wps_start_pbc(wpa_s, NULL);
-
- if (hwaddr_aton(cmd, bssid)) {
+ _bssid = NULL;
+ else if (hwaddr_aton(cmd, bssid)) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE WPS_PBC: invalid BSSID '%s'",
cmd);
return -1;
}
- return wpas_wps_start_pbc(wpa_s, bssid);
+#ifdef CONFIG_AP
+ if (wpa_s->ap_iface)
+ return wpa_supplicant_ap_wps_pbc(wpa_s, _bssid);
+#endif /* CONFIG_AP */
+
+ return wpas_wps_start_pbc(wpa_s, _bssid);
}
return -1;
}
+#ifdef CONFIG_AP
+ if (wpa_s->ap_iface)
+ return wpa_supplicant_ap_wps_pin(wpa_s, _bssid, pin,
+ buf, buflen);
+#endif /* CONFIG_AP */
+
if (pin) {
ret = wpas_wps_start_pin(wpa_s, _bssid, pin);
if (ret < 0)
}
+#ifdef CONFIG_WPS_OOB
+static int wpa_supplicant_ctrl_iface_wps_oob(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ char *path, *method, *name;
+
+ path = os_strchr(cmd, ' ');
+ if (path == NULL)
+ return -1;
+ *path++ = '\0';
+
+ method = os_strchr(path, ' ');
+ if (method == NULL)
+ return -1;
+ *method++ = '\0';
+
+ name = os_strchr(method, ' ');
+ if (name != NULL)
+ *name++ = '\0';
+
+ return wpas_wps_start_oob(wpa_s, cmd, path, method, name);
+}
+#endif /* CONFIG_WPS_OOB */
+
+
static int wpa_supplicant_ctrl_iface_wps_reg(struct wpa_supplicant *wpa_s,
char *cmd)
{
u8 bssid[ETH_ALEN], *_bssid = bssid;
char *pin;
+ char *new_ssid;
+ char *new_auth;
+ char *new_encr;
+ char *new_key;
+ struct wps_new_ap_settings ap;
pin = os_strchr(cmd, ' ');
if (pin == NULL)
return -1;
}
- return wpas_wps_start_reg(wpa_s, _bssid, pin);
+ new_ssid = os_strchr(pin, ' ');
+ if (new_ssid == NULL)
+ return wpas_wps_start_reg(wpa_s, _bssid, pin, NULL);
+ *new_ssid++ = '\0';
+
+ new_auth = os_strchr(new_ssid, ' ');
+ if (new_auth == NULL)
+ return -1;
+ *new_auth++ = '\0';
+
+ new_encr = os_strchr(new_auth, ' ');
+ if (new_encr == NULL)
+ return -1;
+ *new_encr++ = '\0';
+
+ new_key = os_strchr(new_encr, ' ');
+ if (new_key == NULL)
+ return -1;
+ *new_key++ = '\0';
+
+ os_memset(&ap, 0, sizeof(ap));
+ ap.ssid_hex = new_ssid;
+ ap.auth = new_auth;
+ ap.encr = new_encr;
+ ap.key_hex = new_key;
+ return wpas_wps_start_reg(wpa_s, _bssid, pin, &ap);
+}
+
+
+#ifdef CONFIG_WPS_ER
+static int wpa_supplicant_ctrl_iface_wps_er_pin(struct wpa_supplicant *wpa_s,
+ char *cmd)
+{
+ char *uuid = cmd, *pin;
+ pin = os_strchr(uuid, ' ');
+ if (pin == NULL)
+ return -1;
+ *pin++ = '\0';
+ return wpas_wps_er_add_pin(wpa_s, uuid, pin);
}
+#endif /* CONFIG_WPS_ER */
+
#endif /* CONFIG_WPS */
+#ifdef CONFIG_IBSS_RSN
+static int wpa_supplicant_ctrl_iface_ibss_rsn(
+ struct wpa_supplicant *wpa_s, char *addr)
+{
+ u8 peer[ETH_ALEN];
+
+ if (hwaddr_aton(addr, peer)) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN: invalid "
+ "address '%s'", peer);
+ return -1;
+ }
+
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE IBSS_RSN " MACSTR,
+ MAC2STR(peer));
+
+ return ibss_rsn_start(wpa_s->ibss_rsn, peer);
+}
+#endif /* CONFIG_IBSS_RSN */
+
+
static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
char *rsp)
{
}
}
+#ifdef CONFIG_AP
+ if (wpa_s->ap_iface) {
+ pos += ap_ctrl_iface_wpa_get_status(wpa_s, pos,
+ end - pos,
+ verbose);
+ } else
+#endif /* CONFIG_AP */
pos += wpa_sm_get_status(wpa_s->wpa, pos, end - pos, verbose);
}
ret = os_snprintf(pos, end - pos, "wpa_state=%s\n",
/* cmd: "<network id>" or "any" */
if (os_strcmp(cmd, "any") == 0) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK any");
- ssid = wpa_s->conf->ssid;
- while (ssid) {
- ssid->disabled = 0;
- ssid = ssid->next;
- }
- wpa_s->reassociate = 1;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- return 0;
- }
-
- id = atoi(cmd);
- wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
+ ssid = NULL;
+ } else {
+ id = atoi(cmd);
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: SELECT_NETWORK id=%d", id);
- ssid = wpa_config_get_network(wpa_s->conf, id);
- if (ssid == NULL) {
- wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
- "id=%d", id);
- return -1;
+ ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (ssid == NULL) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
+ "network id=%d", id);
+ return -1;
+ }
}
- if (ssid != wpa_s->current_ssid && wpa_s->current_ssid)
- wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
-
- /* Mark all other networks disabled and trigger reassociation */
- ssid = wpa_s->conf->ssid;
- while (ssid) {
- ssid->disabled = id != ssid->id;
- ssid = ssid->next;
- }
- wpa_s->reassociate = 1;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
+ wpa_supplicant_select_network(wpa_s, ssid);
return 0;
}
/* cmd: "<network id>" or "all" */
if (os_strcmp(cmd, "all") == 0) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK all");
- ssid = wpa_s->conf->ssid;
- while (ssid) {
- if (ssid == wpa_s->current_ssid && ssid->disabled)
- wpa_s->reassociate = 1;
- ssid->disabled = 0;
- ssid = ssid->next;
- }
- if (wpa_s->reassociate)
- wpa_supplicant_req_scan(wpa_s, 0, 0);
- return 0;
- }
-
- id = atoi(cmd);
- wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
-
- ssid = wpa_config_get_network(wpa_s->conf, id);
- if (ssid == NULL) {
- wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
- "id=%d", id);
- return -1;
- }
+ ssid = NULL;
+ } else {
+ id = atoi(cmd);
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: ENABLE_NETWORK id=%d", id);
- if (wpa_s->current_ssid == NULL && ssid->disabled) {
- /*
- * Try to reassociate since there is no current configuration
- * and a new network was made available. */
- wpa_s->reassociate = 1;
- wpa_supplicant_req_scan(wpa_s, 0, 0);
+ ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (ssid == NULL) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
+ "network id=%d", id);
+ return -1;
+ }
}
- ssid->disabled = 0;
+ wpa_supplicant_enable_network(wpa_s, ssid);
return 0;
}
/* cmd: "<network id>" or "all" */
if (os_strcmp(cmd, "all") == 0) {
wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK all");
- ssid = wpa_s->conf->ssid;
- while (ssid) {
- ssid->disabled = 1;
- ssid = ssid->next;
- }
- if (wpa_s->current_ssid)
- wpa_supplicant_disassociate(wpa_s,
- WLAN_REASON_DEAUTH_LEAVING);
- return 0;
- }
-
- id = atoi(cmd);
- wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
+ ssid = NULL;
+ } else {
+ id = atoi(cmd);
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: DISABLE_NETWORK id=%d", id);
- ssid = wpa_config_get_network(wpa_s->conf, id);
- if (ssid == NULL) {
- wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
- "id=%d", id);
- return -1;
+ ssid = wpa_config_get_network(wpa_s->conf, id);
+ if (ssid == NULL) {
+ wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find "
+ "network id=%d", id);
+ return -1;
+ }
}
-
- if (ssid == wpa_s->current_ssid)
- wpa_supplicant_disassociate(wpa_s, WLAN_REASON_DEAUTH_LEAVING);
- ssid->disabled = 1;
+ wpa_supplicant_disable_network(wpa_s, ssid);
return 0;
}
ssid = wpa_config_add_network(wpa_s->conf);
if (ssid == NULL)
return -1;
+
+ wpas_notify_network_added(wpa_s, ssid);
+
ssid->disabled = 1;
wpa_config_set_network_defaults(ssid);
wpa_printf(MSG_DEBUG, "CTRL_IFACE: REMOVE_NETWORK all");
ssid = wpa_s->conf->ssid;
while (ssid) {
+ struct wpa_ssid *remove_ssid = ssid;
id = ssid->id;
ssid = ssid->next;
+ wpas_notify_network_removed(wpa_s, remove_ssid);
wpa_config_remove_network(wpa_s->conf, id);
}
if (wpa_s->current_ssid) {
return pos - buf;
pos += ret;
+#ifdef CONFIG_WPS
+ ie = (const u8 *) (bss + 1);
+ ret = wpas_wps_scan_result_text(ie, bss->ie_len, pos, end);
+ if (ret < 0 || ret >= end - pos)
+ return pos - buf;
+ pos += ret;
+#endif /* CONFIG_WPS */
+
return pos - buf;
}
struct wpa_supplicant *wpa_s, char *cmd)
{
int ap_scan = atoi(cmd);
-
- if (ap_scan < 0 || ap_scan > 2)
- return -1;
- wpa_s->conf->ap_scan = ap_scan;
- return 0;
+ return wpa_supplicant_set_ap_scan(wpa_s, ap_scan);
}
reply_len = wpa_supplicant_ctrl_iface_status(
wpa_s, buf + 6, reply, reply_size);
} else if (os_strcmp(buf, "PMKSA") == 0) {
- reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size);
+ reply_len = wpa_sm_pmksa_cache_list(wpa_s->wpa, reply,
+ reply_size);
} else if (os_strncmp(buf, "SET ", 4) == 0) {
if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))
reply_len = -1;
reply_len = wpa_supplicant_ctrl_iface_wps_pin(wpa_s, buf + 8,
reply,
reply_size);
+#ifdef CONFIG_WPS_OOB
+ } else if (os_strncmp(buf, "WPS_OOB ", 8) == 0) {
+ if (wpa_supplicant_ctrl_iface_wps_oob(wpa_s, buf + 8))
+ reply_len = -1;
+#endif /* CONFIG_WPS_OOB */
} else if (os_strncmp(buf, "WPS_REG ", 8) == 0) {
if (wpa_supplicant_ctrl_iface_wps_reg(wpa_s, buf + 8))
reply_len = -1;
+#ifdef CONFIG_WPS_ER
+ } else if (os_strcmp(buf, "WPS_ER_START") == 0) {
+ if (wpas_wps_er_start(wpa_s))
+ reply_len = -1;
+ } else if (os_strcmp(buf, "WPS_ER_STOP") == 0) {
+ if (wpas_wps_er_stop(wpa_s))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "WPS_ER_PIN ", 11) == 0) {
+ if (wpa_supplicant_ctrl_iface_wps_er_pin(wpa_s, buf + 11))
+ reply_len = -1;
+ } else if (os_strncmp(buf, "WPS_ER_PBC ", 11) == 0) {
+ if (wpas_wps_er_pbc(wpa_s, buf + 11))
+ reply_len = -1;
+#endif /* CONFIG_WPS_ER */
#endif /* CONFIG_WPS */
+#ifdef CONFIG_IBSS_RSN
+ } else if (os_strncmp(buf, "IBSS_RSN ", 9) == 0) {
+ if (wpa_supplicant_ctrl_iface_ibss_rsn(wpa_s, buf + 9))
+ reply_len = -1;
+#endif /* CONFIG_IBSS_RSN */
} 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, "BSS ", 4) == 0) {
reply_len = wpa_supplicant_ctrl_iface_bss(
wpa_s, buf + 4, reply, reply_size);
+#ifdef CONFIG_AP
+ } else if (os_strcmp(buf, "STA-FIRST") == 0) {
+ reply_len = ap_ctrl_iface_sta_first(wpa_s, reply, reply_size);
+ } else if (os_strncmp(buf, "STA ", 4) == 0) {
+ reply_len = ap_ctrl_iface_sta(wpa_s, buf + 4, reply,
+ reply_size);
+ } else if (os_strncmp(buf, "STA-NEXT ", 9) == 0) {
+ reply_len = ap_ctrl_iface_sta_next(wpa_s, buf + 9, reply,
+ reply_size);
+#endif /* CONFIG_AP */
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
reply_len = 16;
struct wpa_interface_info *iface = NULL, *last = NULL, *tmp;
char *pos, *end;
- for (i = 0; wpa_supplicant_drivers[i]; i++) {
- struct wpa_driver_ops *drv = wpa_supplicant_drivers[i];
+ for (i = 0; wpa_drivers[i]; i++) {
+ struct wpa_driver_ops *drv = wpa_drivers[i];
if (drv->get_interfaces == NULL)
continue;
tmp = drv->get_interfaces(global->drv_priv);