WPS AP: Add support for reconfiguration with in-memory config
This allows WPS to update AP configuration in the case no hostapd configuration file is used (i.e., dynamic configuration through the control interface). Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
parent
8970bae806
commit
ccdff94035
2 changed files with 135 additions and 11 deletions
|
@ -108,19 +108,10 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int hostapd_reload_config(struct hostapd_iface *iface)
|
static void hostapd_clear_old(struct hostapd_iface *iface)
|
||||||
{
|
{
|
||||||
struct hostapd_data *hapd = iface->bss[0];
|
|
||||||
struct hostapd_config *newconf, *oldconf;
|
|
||||||
size_t j;
|
size_t j;
|
||||||
|
|
||||||
if (iface->interfaces == NULL ||
|
|
||||||
iface->interfaces->config_read_cb == NULL)
|
|
||||||
return -1;
|
|
||||||
newconf = iface->interfaces->config_read_cb(iface->config_fname);
|
|
||||||
if (newconf == NULL)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Deauthenticate all stations since the new configuration may not
|
* Deauthenticate all stations since the new configuration may not
|
||||||
* allow them to use the BSS anymore.
|
* allow them to use the BSS anymore.
|
||||||
|
@ -136,6 +127,31 @@ int hostapd_reload_config(struct hostapd_iface *iface)
|
||||||
radius_client_flush(iface->bss[j]->radius, 0);
|
radius_client_flush(iface->bss[j]->radius, 0);
|
||||||
#endif /* CONFIG_NO_RADIUS */
|
#endif /* CONFIG_NO_RADIUS */
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int hostapd_reload_config(struct hostapd_iface *iface)
|
||||||
|
{
|
||||||
|
struct hostapd_data *hapd = iface->bss[0];
|
||||||
|
struct hostapd_config *newconf, *oldconf;
|
||||||
|
size_t j;
|
||||||
|
|
||||||
|
if (iface->config_fname == NULL) {
|
||||||
|
/* Only in-memory config in use - assume it has been updated */
|
||||||
|
hostapd_clear_old(iface);
|
||||||
|
for (j = 0; j < iface->num_bss; j++)
|
||||||
|
hostapd_reload_bss(iface->bss[j]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iface->interfaces == NULL ||
|
||||||
|
iface->interfaces->config_read_cb == NULL)
|
||||||
|
return -1;
|
||||||
|
newconf = iface->interfaces->config_read_cb(iface->config_fname);
|
||||||
|
if (newconf == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
hostapd_clear_old(iface);
|
||||||
|
|
||||||
oldconf = hapd->iconf;
|
oldconf = hapd->iconf;
|
||||||
iface->conf = newconf;
|
iface->conf = newconf;
|
||||||
|
|
|
@ -277,6 +277,114 @@ static void hapd_new_ap_event(struct hostapd_data *hapd, const u8 *attr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int hapd_wps_reconfig_in_memory(struct hostapd_data *hapd,
|
||||||
|
const struct wps_credential *cred)
|
||||||
|
{
|
||||||
|
struct hostapd_bss_config *bss = hapd->conf;
|
||||||
|
|
||||||
|
wpa_printf(MSG_DEBUG, "WPS: Updating in-memory configuration");
|
||||||
|
|
||||||
|
bss->wps_state = 2;
|
||||||
|
if (cred->ssid_len <= HOSTAPD_MAX_SSID_LEN) {
|
||||||
|
os_memcpy(bss->ssid.ssid, cred->ssid, cred->ssid_len);
|
||||||
|
bss->ssid.ssid_len = cred->ssid_len;
|
||||||
|
bss->ssid.ssid_set = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK)) &&
|
||||||
|
(cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK)))
|
||||||
|
bss->wpa = 3;
|
||||||
|
else if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK))
|
||||||
|
bss->wpa = 2;
|
||||||
|
else if (cred->auth_type & (WPS_AUTH_WPA | WPS_AUTH_WPAPSK))
|
||||||
|
bss->wpa = 1;
|
||||||
|
else
|
||||||
|
bss->wpa = 0;
|
||||||
|
|
||||||
|
if (bss->wpa) {
|
||||||
|
if (cred->auth_type & (WPS_AUTH_WPA2 | WPS_AUTH_WPA))
|
||||||
|
bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X;
|
||||||
|
if (cred->auth_type & (WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK))
|
||||||
|
bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK;
|
||||||
|
|
||||||
|
bss->wpa_pairwise = 0;
|
||||||
|
if (cred->encr_type & WPS_ENCR_AES)
|
||||||
|
bss->wpa_pairwise |= WPA_CIPHER_CCMP;
|
||||||
|
if (cred->encr_type & WPS_ENCR_TKIP)
|
||||||
|
bss->wpa_pairwise |= WPA_CIPHER_TKIP;
|
||||||
|
bss->rsn_pairwise = bss->wpa_pairwise;
|
||||||
|
bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa,
|
||||||
|
bss->wpa_pairwise,
|
||||||
|
bss->rsn_pairwise);
|
||||||
|
|
||||||
|
if (cred->key_len >= 8 && cred->key_len < 64) {
|
||||||
|
os_free(bss->ssid.wpa_passphrase);
|
||||||
|
bss->ssid.wpa_passphrase = os_zalloc(cred->key_len + 1);
|
||||||
|
if (bss->ssid.wpa_passphrase)
|
||||||
|
os_memcpy(bss->ssid.wpa_passphrase, cred->key,
|
||||||
|
cred->key_len);
|
||||||
|
os_free(bss->ssid.wpa_psk);
|
||||||
|
bss->ssid.wpa_psk = NULL;
|
||||||
|
} else if (cred->key_len == 64) {
|
||||||
|
os_free(bss->ssid.wpa_psk);
|
||||||
|
bss->ssid.wpa_psk =
|
||||||
|
os_zalloc(sizeof(struct hostapd_wpa_psk));
|
||||||
|
if (bss->ssid.wpa_psk &&
|
||||||
|
hexstr2bin((const char *) cred->key,
|
||||||
|
bss->ssid.wpa_psk->psk, PMK_LEN) == 0) {
|
||||||
|
bss->ssid.wpa_psk->group = 1;
|
||||||
|
os_free(bss->ssid.wpa_passphrase);
|
||||||
|
bss->ssid.wpa_passphrase = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bss->auth_algs = 1;
|
||||||
|
} else {
|
||||||
|
if ((cred->auth_type & WPS_AUTH_OPEN) &&
|
||||||
|
(cred->auth_type & WPS_AUTH_SHARED))
|
||||||
|
bss->auth_algs = 3;
|
||||||
|
else if (cred->auth_type & WPS_AUTH_SHARED)
|
||||||
|
bss->auth_algs = 2;
|
||||||
|
else
|
||||||
|
bss->auth_algs = 1;
|
||||||
|
if (cred->encr_type & WPS_ENCR_WEP && cred->key_idx > 0 &&
|
||||||
|
cred->key_idx <= 4) {
|
||||||
|
struct hostapd_wep_keys *wep = &bss->ssid.wep;
|
||||||
|
int idx = cred->key_idx;
|
||||||
|
if (idx)
|
||||||
|
idx--;
|
||||||
|
wep->idx = idx;
|
||||||
|
if (cred->key_len == 10 || cred->key_len == 26) {
|
||||||
|
os_free(wep->key[idx]);
|
||||||
|
wep->key[idx] = os_malloc(cred->key_len / 2);
|
||||||
|
if (wep->key[idx] == NULL ||
|
||||||
|
hexstr2bin((const char *) cred->key,
|
||||||
|
wep->key[idx],
|
||||||
|
cred->key_len / 2))
|
||||||
|
return -1;
|
||||||
|
wep->len[idx] = cred->key_len / 2;
|
||||||
|
} else {
|
||||||
|
os_free(wep->key[idx]);
|
||||||
|
wep->key[idx] = os_malloc(cred->key_len);
|
||||||
|
if (wep->key[idx] == NULL)
|
||||||
|
return -1;
|
||||||
|
os_memcpy(wep->key[idx], cred->key,
|
||||||
|
cred->key_len);
|
||||||
|
wep->len[idx] = cred->key_len;
|
||||||
|
}
|
||||||
|
wep->keys_set = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Schedule configuration reload after short period of time to allow
|
||||||
|
* EAP-WSC to be finished.
|
||||||
|
*/
|
||||||
|
eloop_register_timeout(0, 100000, wps_reload_config, hapd->iface,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
|
static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
|
||||||
{
|
{
|
||||||
const struct wps_credential *cred = ctx;
|
const struct wps_credential *cred = ctx;
|
||||||
|
@ -344,7 +452,7 @@ static int hapd_wps_cred_cb(struct hostapd_data *hapd, void *ctx)
|
||||||
hapd->wps->wps_state = WPS_STATE_CONFIGURED;
|
hapd->wps->wps_state = WPS_STATE_CONFIGURED;
|
||||||
|
|
||||||
if (hapd->iface->config_fname == NULL)
|
if (hapd->iface->config_fname == NULL)
|
||||||
return 0;
|
return hapd_wps_reconfig_in_memory(hapd, cred);
|
||||||
len = os_strlen(hapd->iface->config_fname) + 5;
|
len = os_strlen(hapd->iface->config_fname) + 5;
|
||||||
tmp_fname = os_malloc(len);
|
tmp_fname = os_malloc(len);
|
||||||
if (tmp_fname == NULL)
|
if (tmp_fname == NULL)
|
||||||
|
|
Loading…
Reference in a new issue