static void hostapd_wps_ap_pin_timeout(void *eloop_data, void *user_ctx);
+struct wps_for_each_data {
+ int (*func)(struct hostapd_data *h, void *ctx);
+ void *ctx;
+};
+
+
+static int wps_for_each(struct hostapd_iface *iface, void *ctx)
+{
+ struct wps_for_each_data *data = ctx;
+ size_t j;
+
+ if (iface == NULL)
+ return 0;
+ for (j = 0; j < iface->num_bss; j++) {
+ struct hostapd_data *hapd = iface->bss[j];
+ int ret = data->func(hapd, data->ctx);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+
+static int hostapd_wps_for_each(struct hostapd_data *hapd,
+ int (*func)(struct hostapd_data *h, void *ctx),
+ void *ctx)
+{
+ struct hostapd_iface *iface = hapd->iface;
+ struct wps_for_each_data data;
+ data.func = func;
+ data.ctx = ctx;
+ if (iface->for_each_interface == NULL)
+ return wps_for_each(iface, &data);
+ return iface->for_each_interface(iface->interfaces, wps_for_each,
+ &data);
+}
+
+
static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *psk,
size_t psk_len)
{
}
-static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
+static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
{
- struct hostapd_data *hapd = ctx;
+ const struct wps_credential *cred = ctx;
FILE *oconf, *nconf;
size_t len, i;
char *tmp_fname;
int multi_bss;
int wpa;
+ if (hapd->wps == NULL)
+ return 0;
+
wpa_hexdump_key(MSG_DEBUG, "WPS: Received Credential attribute",
cred->cred_attr, cred->cred_attr_len);
eloop_register_timeout(0, 100000, wps_reload_config, hapd->iface,
NULL);
- /* TODO: dualband AP may need to update multiple configuration files */
-
wpa_printf(MSG_DEBUG, "WPS: AP configuration updated");
return 0;
}
+static int hostapd_wps_cred_cb(void *ctx, const struct wps_credential *cred)
+{
+ struct hostapd_data *hapd = ctx;
+ return hostapd_wps_for_each(hapd, hapd_wps_cred_cb, (void *) cred);
+}
+
+
static void hostapd_wps_reenable_ap_pin(void *eloop_data, void *user_ctx)
{
struct hostapd_data *hapd = eloop_data;
}
-static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
- struct wps_event_pwd_auth_fail *data)
+static int wps_pwd_auth_fail(struct hostapd_data *hapd, void *ctx)
{
- if (!data->enrollee || hapd->conf->ap_pin == NULL)
- return;
+ struct wps_event_pwd_auth_fail *data = ctx;
+
+ if (!data->enrollee || hapd->conf->ap_pin == NULL || hapd->wps == NULL)
+ return 0;
/*
* Registrar failed to prove its knowledge of the AP PIN. Lock AP setup
wpa_printf(MSG_DEBUG, "WPS: AP PIN authentication failure number %u",
hapd->ap_pin_failures);
if (hapd->ap_pin_failures < 3)
- return;
+ return 0;
wpa_msg(hapd->msg_ctx, MSG_INFO, WPS_EVENT_AP_SETUP_LOCKED);
hapd->wps->ap_setup_locked = 1;
NULL);
}
- /* TODO: dualband AP may need to update other interfaces */
+ return 0;
+}
+
+
+static void hostapd_pwd_auth_fail(struct hostapd_data *hapd,
+ struct wps_event_pwd_auth_fail *data)
+{
+ hostapd_wps_for_each(hapd, wps_pwd_auth_fail, data);
+}
+
+
+static void hostapd_wps_event_fail(struct hostapd_data *hapd,
+ struct wps_event_fail *fail)
+{
+ wpa_msg(hapd->msg_ctx, MSG_INFO,
+ WPS_EVENT_FAIL "msg=%d config_error=%d",
+ fail->msg, fail->config_error);
}
{
struct hostapd_data *hapd = ctx;
- if (event == WPS_EV_PWD_AUTH_FAIL)
+ switch (event) {
+ case WPS_EV_M2D:
+ break;
+ case WPS_EV_FAIL:
+ hostapd_wps_event_fail(hapd, &data->fail);
+ break;
+ case WPS_EV_SUCCESS:
+ break;
+ case WPS_EV_PWD_AUTH_FAIL:
hostapd_pwd_auth_fail(hapd, &data->pwd_auth_fail);
+ break;
+ case WPS_EV_PBC_OVERLAP:
+ break;
+ case WPS_EV_PBC_TIMEOUT:
+ break;
+ case WPS_EV_ER_AP_ADD:
+ break;
+ case WPS_EV_ER_AP_REMOVE:
+ break;
+ case WPS_EV_ER_ENROLLEE_ADD:
+ break;
+ case WPS_EV_ER_ENROLLEE_REMOVE:
+ break;
+ case WPS_EV_ER_AP_SETTINGS:
+ break;
+ }
+ if (hapd->wps_event_cb)
+ hapd->wps_event_cb(hapd->wps_event_cb_ctx, event, data);
}
}
+static int count_interface_cb(struct hostapd_iface *iface, void *ctx)
+{
+ int *count= ctx;
+ (*count)++;
+ return 0;
+}
+
+
+static int interface_count(struct hostapd_iface *iface)
+{
+ int count = 0;
+ if (iface->for_each_interface == NULL)
+ return 0;
+ iface->for_each_interface(iface->interfaces, count_interface_cb,
+ &count);
+ return count;
+}
+
+
int hostapd_init_wps(struct hostapd_data *hapd,
struct hostapd_bss_config *conf)
{
os_strdup(hapd->conf->serial_number) : NULL;
wps->config_methods =
wps_config_methods_str2bin(hapd->conf->config_methods);
+#ifdef CONFIG_WPS2
+ if ((wps->config_methods &
+ (WPS_CONFIG_DISPLAY | WPS_CONFIG_VIRT_DISPLAY |
+ WPS_CONFIG_PHY_DISPLAY)) == WPS_CONFIG_DISPLAY) {
+ wpa_printf(MSG_INFO, "WPS: Converting display to "
+ "virtual_display for WPS 2.0 compliance");
+ wps->config_methods |= WPS_CONFIG_VIRT_DISPLAY;
+ }
+ if ((wps->config_methods &
+ (WPS_CONFIG_PUSHBUTTON | WPS_CONFIG_VIRT_PUSHBUTTON |
+ WPS_CONFIG_PHY_PUSHBUTTON)) == WPS_CONFIG_PUSHBUTTON) {
+ wpa_printf(MSG_INFO, "WPS: Converting push_button to "
+ "virtual_push_button for WPS 2.0 compliance");
+ wps->config_methods |= WPS_CONFIG_VIRT_PUSHBUTTON;
+ }
+#endif /* CONFIG_WPS2 */
if (hapd->conf->device_type &&
wps_dev_type_str2bin(hapd->conf->device_type,
wps->dev.pri_dev_type) < 0) {
conf->skip_cred_build;
if (conf->ssid.security_policy == SECURITY_STATIC_WEP)
cfg.static_wep_only = 1;
+ cfg.dualband = interface_count(hapd->iface) > 1;
+ if (cfg.dualband)
+ wpa_printf(MSG_DEBUG, "WPS: Dualband AP");
wps->registrar = wps_registrar_init(wps, &cfg);
if (wps->registrar == NULL) {
- printf("Failed to initialize WPS Registrar\n");
+ wpa_printf(MSG_ERROR, "Failed to initialize WPS Registrar");
os_free(wps->network_key);
os_free(wps);
return -1;
{
if (hapd->wps == NULL)
return;
+
+#ifdef CONFIG_WPS_UPNP
+ hapd->wps->friendly_name = hapd->conf->friendly_name;
+ hapd->wps->manufacturer_url = hapd->conf->manufacturer_url;
+ hapd->wps->model_description = hapd->conf->model_description;
+ hapd->wps->model_url = hapd->conf->model_url;
+ hapd->wps->upc = hapd->conf->upc;
+#endif /* CONFIG_WPS_UPNP */
+
if (hapd->conf->wps_state)
wps_registrar_update_ie(hapd->wps->registrar);
else
}
+struct wps_add_pin_data {
+ const u8 *addr;
+ const u8 *uuid;
+ const u8 *pin;
+ size_t pin_len;
+ int timeout;
+ int added;
+};
+
+
+static int wps_add_pin(struct hostapd_data *hapd, void *ctx)
+{
+ struct wps_add_pin_data *data = ctx;
+ int ret;
+
+ if (hapd->wps == NULL)
+ return 0;
+ ret = wps_registrar_add_pin(hapd->wps->registrar, data->addr,
+ data->uuid, data->pin, data->pin_len,
+ data->timeout);
+ if (ret == 0)
+ data->added++;
+ return ret;
+}
+
+
int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr,
const char *uuid, const char *pin, int timeout)
{
u8 u[UUID_LEN];
- int any = 0;
+ struct wps_add_pin_data data;
+
+ data.addr = addr;
+ data.uuid = u;
+ data.pin = (const u8 *) pin;
+ data.pin_len = os_strlen(pin);
+ data.timeout = timeout;
+ data.added = 0;
- if (hapd->wps == NULL)
- return -1;
if (os_strcmp(uuid, "any") == 0)
- any = 1;
- else if (uuid_str2bin(uuid, u))
+ data.uuid = NULL;
+ else {
+ if (uuid_str2bin(uuid, u))
+ return -1;
+ data.uuid = u;
+ }
+ if (hostapd_wps_for_each(hapd, wps_add_pin, &data) < 0)
return -1;
- return wps_registrar_add_pin(hapd->wps->registrar, addr,
- any ? NULL : u,
- (const u8 *) pin, os_strlen(pin),
- timeout);
+ return data.added ? 0 : -1;
}
-int hostapd_wps_button_pushed(struct hostapd_data *hapd)
+static int wps_button_pushed(struct hostapd_data *hapd, void *ctx)
{
if (hapd->wps == NULL)
- return -1;
+ return 0;
return wps_registrar_button_pushed(hapd->wps->registrar);
}
+int hostapd_wps_button_pushed(struct hostapd_data *hapd)
+{
+ return hostapd_wps_for_each(hapd, wps_button_pushed, NULL);
+}
+
+
#ifdef CONFIG_WPS_OOB
int hostapd_wps_start_oob(struct hostapd_data *hapd, char *device_type,
char *path, char *method, char *name)
wps_ie = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
if (wps_ie == NULL)
return 0;
- if (wps_validate_probe_req(wps_ie) < 0) {
+ if (wps_validate_probe_req(wps_ie, addr) < 0) {
wpabuf_free(wps_ie);
return 0;
}
}
-void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd)
+static int wps_ap_pin_disable(struct hostapd_data *hapd, void *ctx)
{
- wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN");
os_free(hapd->conf->ap_pin);
hapd->conf->ap_pin = NULL;
#ifdef CONFIG_WPS_UPNP
upnp_wps_set_ap_pin(hapd->wps_upnp, NULL);
#endif /* CONFIG_WPS_UPNP */
eloop_cancel_timeout(hostapd_wps_ap_pin_timeout, hapd, NULL);
+ return 0;
}
-const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout)
+void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd)
{
- unsigned int pin;
+ wpa_printf(MSG_DEBUG, "WPS: Disabling AP PIN");
+ hostapd_wps_for_each(hapd, wps_ap_pin_disable, NULL);
+}
+
+
+struct wps_ap_pin_data {
char pin_txt[9];
+ int timeout;
+};
- pin = wps_generate_pin();
- os_snprintf(pin_txt, sizeof(pin_txt), "%u", pin);
+
+static int wps_ap_pin_set(struct hostapd_data *hapd, void *ctx)
+{
+ struct wps_ap_pin_data *data = ctx;
os_free(hapd->conf->ap_pin);
- hapd->conf->ap_pin = os_strdup(pin_txt);
+ hapd->conf->ap_pin = os_strdup(data->pin_txt);
#ifdef CONFIG_WPS_UPNP
- upnp_wps_set_ap_pin(hapd->wps_upnp, pin_txt);
+ upnp_wps_set_ap_pin(hapd->wps_upnp, data->pin_txt);
#endif /* CONFIG_WPS_UPNP */
- hostapd_wps_ap_pin_enable(hapd, timeout);
+ hostapd_wps_ap_pin_enable(hapd, data->timeout);
+ return 0;
+}
+
+
+const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout)
+{
+ unsigned int pin;
+ struct wps_ap_pin_data data;
+
+ pin = wps_generate_pin();
+ os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%u", pin);
+ data.timeout = timeout;
+ hostapd_wps_for_each(hapd, wps_ap_pin_set, &data);
return hapd->conf->ap_pin;
}
int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin,
int timeout)
{
- os_free(hapd->conf->ap_pin);
- hapd->conf->ap_pin = os_strdup(pin);
- if (hapd->conf->ap_pin == NULL)
+ struct wps_ap_pin_data data;
+ int ret;
+
+ ret = os_snprintf(data.pin_txt, sizeof(data.pin_txt), "%s", pin);
+ if (ret < 0 || ret >= (int) sizeof(data.pin_txt))
return -1;
-#ifdef CONFIG_WPS_UPNP
- upnp_wps_set_ap_pin(hapd->wps_upnp, hapd->conf->ap_pin);
-#endif /* CONFIG_WPS_UPNP */
- hostapd_wps_ap_pin_enable(hapd, timeout);
- return 0;
+ data.timeout = timeout;
+ return hostapd_wps_for_each(hapd, wps_ap_pin_set, &data);
}