/**
 * hostapd_validate_bssid_configuration - Validate BSSID configuration
 * @iface: Pointer to interface data
 * Returns: 0 on success, -1 on failure
 *
 * This function is used to validate that the configured BSSIDs are valid.
 */
static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface)
{
	u8 mask[ETH_ALEN] = { 0 };
	struct hostapd_data *hapd = iface->bss[0];
	unsigned int i = iface->conf->num_bss, bits = 0, j;
	int auto_addr = 0;

	if (hostapd_drv_none(hapd))
		return 0;

	/* Generate BSSID mask that is large enough to cover the BSSIDs. */

	/* Determine the bits necessary to cover the number of BSSIDs. */
	for (i--; i; i >>= 1)
		bits++;

	/* Determine the bits necessary to any configured BSSIDs,
	   if they are higher than the number of BSSIDs. */
	for (j = 0; j < iface->conf->num_bss; j++) {
		if (hostapd_mac_comp_empty(iface->conf->bss[j].bssid) == 0) {
			if (j)
				auto_addr++;
			continue;
		}

		for (i = 0; i < ETH_ALEN; i++) {
			mask[i] |=
				iface->conf->bss[j].bssid[i] ^
				hapd->own_addr[i];
		}
	}

	if (!auto_addr)
		goto skip_mask_ext;

	for (i = 0; i < ETH_ALEN && mask[i] == 0; i++)
		;
	j = 0;
	if (i < ETH_ALEN) {
		j = (5 - i) * 8;

		while (mask[i] != 0) {
			mask[i] >>= 1;
			j++;
		}
	}
Ejemplo n.º 2
0
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 && hostapd_mac_comp_empty(bss->bssid) != 0) {
		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_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_printf(MSG_INFO, "WPS: WPA/TKIP configuration without "
			   "WPA2/CCMP 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 */

	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);
}