Example #1
0
int hostapd_vlan_valid(struct hostapd_vlan *vlan,
		       struct vlan_description *vlan_desc)
{
	struct hostapd_vlan *v = vlan;
	int i;

	if (!vlan_desc->notempty || vlan_desc->untagged < 0 ||
	    vlan_desc->untagged > MAX_VLAN_ID)
		return 0;
	for (i = 0; i < MAX_NUM_TAGGED_VLAN; i++) {
		if (vlan_desc->tagged[i] < 0 ||
		    vlan_desc->tagged[i] > MAX_VLAN_ID)
			return 0;
	}
	if (!vlan_desc->untagged && !vlan_desc->tagged[0])
		return 0;

	while (v) {
		if (!vlan_compare(&v->vlan_desc, vlan_desc) ||
		    v->vlan_id == VLAN_ID_WILDCARD)
			return 1;
		v = v->next;
	}
	return 0;
}
Example #2
0
int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta,
                    struct vlan_description *vlan_desc)
{
    struct hostapd_vlan *vlan = NULL, *wildcard_vlan = NULL;
    int old_vlan_id, vlan_id = 0, ret = 0;

    if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED)
        vlan_desc = NULL;

    /* Check if there is something to do */
    if (hapd->conf->ssid.per_sta_vif && !sta->vlan_id) {
        /* This sta is lacking its own vif */
    } else if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED &&
               !hapd->conf->ssid.per_sta_vif && sta->vlan_id) {
        /* sta->vlan_id needs to be reset */
    } else if (!vlan_compare(vlan_desc, sta->vlan_desc)) {
        return 0; /* nothing to change */
    }

    /* Now the real VLAN changed or the STA just needs its own vif */
    if (hapd->conf->ssid.per_sta_vif) {
        /* Assign a new vif, always */
        /* find a free vlan_id sufficiently big */
        vlan_id = ap_sta_get_free_vlan_id(hapd);
        /* Get wildcard VLAN */
        for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
            if (vlan->vlan_id == VLAN_ID_WILDCARD)
                break;
        }
        if (!vlan) {
            hostapd_logger(hapd, sta->addr,
                           HOSTAPD_MODULE_IEEE80211,
                           HOSTAPD_LEVEL_DEBUG,
                           "per_sta_vif missing wildcard");
            vlan_id = 0;
            ret = -1;
            goto done;
        }
    } else if (vlan_desc && vlan_desc->notempty) {
        for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) {
            if (!vlan_compare(&vlan->vlan_desc, vlan_desc))
                break;
            if (vlan->vlan_id == VLAN_ID_WILDCARD)
                wildcard_vlan = vlan;
        }
        if (vlan) {
            vlan_id = vlan->vlan_id;
        } else if (wildcard_vlan) {
            vlan = wildcard_vlan;
            vlan_id = vlan_desc->untagged;
            if (vlan_desc->tagged[0]) {
                /* Tagged VLAN configuration */
                vlan_id = ap_sta_get_free_vlan_id(hapd);
            }
        } else {
            hostapd_logger(hapd, sta->addr,
                           HOSTAPD_MODULE_IEEE80211,
                           HOSTAPD_LEVEL_DEBUG,
                           "missing vlan and wildcard for vlan=%d%s",
                           vlan_desc->untagged,
                           vlan_desc->tagged[0] ? "+" : "");
            vlan_id = 0;
            ret = -1;
            goto done;
        }
    }

    if (vlan && vlan->vlan_id == VLAN_ID_WILDCARD) {
        vlan = vlan_add_dynamic(hapd, vlan, vlan_id, vlan_desc);
        if (vlan == NULL) {
            hostapd_logger(hapd, sta->addr,
                           HOSTAPD_MODULE_IEEE80211,
                           HOSTAPD_LEVEL_DEBUG,
                           "could not add dynamic VLAN interface for vlan=%d%s",
                           vlan_desc ? vlan_desc->untagged : -1,
                           (vlan_desc && vlan_desc->tagged[0]) ?
                           "+" : "");
            vlan_id = 0;
            ret = -1;
            goto done;
        }

        hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211,
                       HOSTAPD_LEVEL_DEBUG,
                       "added new dynamic VLAN interface '%s'",
                       vlan->ifname);
    } else if (vlan && vlan->dynamic_vlan > 0) {
        vlan->dynamic_vlan++;
        hostapd_logger(hapd, sta->addr,
                       HOSTAPD_MODULE_IEEE80211,
                       HOSTAPD_LEVEL_DEBUG,
                       "updated existing dynamic VLAN interface '%s'",
                       vlan->ifname);
    }
done:
    old_vlan_id = sta->vlan_id;
    sta->vlan_id = vlan_id;
    sta->vlan_desc = vlan ? &vlan->vlan_desc : NULL;

    if (vlan_id != old_vlan_id && old_vlan_id)
        vlan_remove_dynamic(hapd, old_vlan_id);

    return ret;
}