static int hostapd_config_check_bss(struct hostapd_bss_config *bss, struct hostapd_config *conf, int full_config) { if (full_config && bss->ieee802_1x && !bss->eap_server && !bss->radius->auth_servers) { wpa_printf(MSG_ERROR, "Invalid IEEE 802.1X configuration (no " "EAP authenticator configured)."); return -1; } if (bss->wpa) { int wep, i; wep = bss->default_wep_key_len > 0 || bss->individual_wep_key_len > 0; for (i = 0; i < NUM_WEP_KEYS; i++) { if (bss->ssid.wep.keys_set) { wep = 1; break; } } if (wep) { wpa_printf(MSG_ERROR, "WEP configuration in a WPA network is not supported"); return -1; } } if (full_config && bss->wpa && bss->wpa_psk_radius != PSK_RADIUS_IGNORED && bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH) { wpa_printf(MSG_ERROR, "WPA-PSK using RADIUS enabled, but no " "RADIUS checking (macaddr_acl=2) enabled."); return -1; } if (full_config && bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) && bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL && bss->ssid.wpa_psk_file == NULL && (bss->wpa_psk_radius != PSK_RADIUS_REQUIRED || bss->macaddr_acl != USE_EXTERNAL_RADIUS_AUTH)) { wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase " "is not configured."); return -1; } if (full_config && !is_zero_ether_addr(bss->bssid)) { size_t i; for (i = 0; i < conf->num_bss; i++) { if (conf->bss[i] != bss && (hostapd_mac_comp(conf->bss[i]->bssid, bss->bssid) == 0)) { wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR " on interface '%s' and '%s'.", MAC2STR(bss->bssid), conf->bss[i]->iface, bss->iface); return -1; } } } #ifdef CONFIG_IEEE80211R if (full_config && wpa_key_mgmt_ft(bss->wpa_key_mgmt) && (bss->nas_identifier == NULL || os_strlen(bss->nas_identifier) < 1 || os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) { wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires " "nas_identifier to be configured as a 1..48 octet " "string"); return -1; } #endif /* CONFIG_IEEE80211R */ #ifdef CONFIG_IEEE80211N if (full_config && conf->ieee80211n && conf->hw_mode == HOSTAPD_MODE_IEEE80211B) { bss->disable_11n = 1; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not " "allowed, disabling HT capabilities"); } if (full_config && conf->ieee80211n && bss->ssid.security_policy == SECURITY_STATIC_WEP) { bss->disable_11n = 1; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not " "allowed, disabling HT capabilities"); } if (full_config && conf->ieee80211n && bss->wpa && !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) { bss->disable_11n = 1; wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 " "requires CCMP/GCMP to be enabled, disabling HT " "capabilities"); } #endif /* CONFIG_IEEE80211N */ #ifdef CONFIG_IEEE80211AC if (full_config && conf->ieee80211ac && bss->ssid.security_policy == SECURITY_STATIC_WEP) { bss->disable_11ac = 1; wpa_printf(MSG_ERROR, "VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities"); } #endif /* CONFIG_IEEE80211AC */ #ifdef CONFIG_WPS if (full_config && bss->wps_state && bss->ignore_broadcast_ssid) { wpa_printf(MSG_INFO, "WPS: ignore_broadcast_ssid " "configuration forced WPS to be disabled"); bss->wps_state = 0; } if (full_config && bss->wps_state && bss->ssid.wep.keys_set && bss->wpa == 0) { wpa_printf(MSG_INFO, "WPS: WEP configuration forced WPS to be " "disabled"); bss->wps_state = 0; } if (full_config && bss->wps_state && bss->wpa && (!(bss->wpa & 2) || !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)))) { wpa_printf(MSG_INFO, "WPS: WPA/TKIP configuration without " "WPA2/CCMP/GCMP forced WPS to be disabled"); bss->wps_state = 0; } #endif /* CONFIG_WPS */ #ifdef CONFIG_HS20 if (full_config && bss->hs20 && (!(bss->wpa & 2) || !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256)))) { wpa_printf(MSG_ERROR, "HS 2.0: WPA2-Enterprise/CCMP " "configuration is required for Hotspot 2.0 " "functionality"); return -1; } #endif /* CONFIG_HS20 */ #ifdef CONFIG_MBO if (full_config && bss->mbo_enabled && (bss->wpa & 2) && bss->ieee80211w == NO_MGMT_FRAME_PROTECTION) { wpa_printf(MSG_ERROR, "MBO: PMF needs to be enabled whenever using WPA2 with MBO"); return -1; } #endif /* CONFIG_MBO */ return 0; }
/** * config_reload2 - Part 2 of configuration reloading * @hapd_iface: */ static void config_reload2(struct hostapd_iface *hapd_iface, int status) { struct hostapd_config_change *change = hapd_iface->change; struct hostapd_data *hapd = change->hapd; struct hostapd_config *newconf = change->newconf; struct hostapd_config *oldconf = change->oldconf; int beacon_changed = change->beacon_changed; struct hostapd_data **new_hapd = change->new_hapd; struct hostapd_data **old_hapd = change->old_hapd; int num_old_hapd = change->num_old_hapd; size_t i, j, max_bss, same_bssid; struct hostapd_bss_config *newbss, *oldbss; u8 *prev_addr; hostapd_iface_cb cb; free(change); hapd_iface->change = NULL; if (status) { printf("Failed to setup new interface config\n"); cb = hapd_iface->config_reload_cb; hapd_iface->config_reload_cb = NULL; /* Invalid configuration - cleanup and terminate hostapd */ hapd_iface->bss = old_hapd; hapd_iface->num_bss = num_old_hapd; hapd_iface->conf = hapd->iconf = oldconf; hapd->conf = &oldconf->bss[0]; hostapd_config_free(newconf); free(new_hapd); cb(hapd_iface, -2); return; } /* * If any BSSes have been removed, added, or had their BSSIDs changed, * completely remove and reinitialize such BSSes and all the BSSes * following them since their BSSID might have changed. */ max_bss = oldconf->num_bss; if (max_bss > newconf->num_bss) max_bss = newconf->num_bss; for (i = 0; i < max_bss; i++) { if (strcmp(oldconf->bss[i].iface, newconf->bss[i].iface) != 0 || hostapd_mac_comp(oldconf->bss[i].bssid, newconf->bss[i].bssid) != 0) break; } same_bssid = i; for (i = 0; i < oldconf->num_bss; i++) { oldbss = &oldconf->bss[i]; newbss = NULL; for (j = 0; j < newconf->num_bss; j++) { if (strcmp(oldbss->iface, newconf->bss[j].iface) == 0) { newbss = &newconf->bss[j]; break; } } if (newbss && i < same_bssid) { hapd = hapd_iface->bss[j] = old_hapd[i]; hapd->iconf = newconf; hapd->conf = newbss; hostapd_reconfig_bss(hapd, newbss, oldbss, oldconf, beacon_changed); } else { hapd = old_hapd[i]; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Removing BSS (ifname %s)\n", hapd->conf->iface); hostapd_free_stas(hapd); /* Send broadcast deauthentication for this BSS, but do * not clear all STAs from the driver since other BSSes * may have STA entries. The driver will remove all STA * entries for this BSS anyway when the interface is * being removed. */ #if 0 hostapd_deauth_all_stas(hapd); hostapd_cleanup(hapd); #endif free(hapd); } } prev_addr = hapd_iface->bss[0]->own_addr; hapd = hapd_iface->bss[0]; for (j = 0; j < newconf->num_bss; j++) { if (hapd_iface->bss[j] != NULL) { prev_addr = hapd_iface->bss[j]->own_addr; continue; } newbss = &newconf->bss[j]; HOSTAPD_DEBUG(HOSTAPD_DEBUG_MINIMAL, "Reconfiguration: adding " "new BSS (ifname=%s)\n", newbss->iface); #if 0 hapd = hapd_iface->bss[j] = hostapd_alloc_bss_data(hapd_iface, newconf, newbss); #endif if (hapd == NULL) { printf("Failed to initialize new BSS\n"); /* FIX: This one is somewhat hard to recover * from.. Would need to remove this BSS from * conf and BSS list. */ exit(1); } hapd->driver = hapd_iface->bss[0]->driver; hapd->iface = hapd_iface; hapd->iconf = newconf; hapd->conf = newbss; memcpy(hapd->own_addr, prev_addr, ETH_ALEN); if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) prev_addr = hapd->own_addr; #if 0 if (hostapd_setup_bss(hapd, j == 0)) { printf("Failed to setup new BSS\n"); /* FIX */ exit(1); } #endif } free(old_hapd); hostapd_config_free(oldconf); cb = hapd_iface->config_reload_cb; hapd_iface->config_reload_cb = NULL; cb(hapd_iface, 0); }