From patchwork Sat Jul 27 16:18:10 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: michael-dev X-Patchwork-Id: 262481 Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from maxx.maxx.shmoo.com (maxx.shmoo.com [205.134.188.171]) by ozlabs.org (Postfix) with ESMTP id EA24A2C00C0 for ; Sun, 28 Jul 2013 02:18:53 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id A3EAE17C171; Sat, 27 Jul 2013 12:18:51 -0400 (EDT) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id OwpdGVNaCDap; Sat, 27 Jul 2013 12:18:51 -0400 (EDT) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 4145C17C14D; Sat, 27 Jul 2013 12:18:30 -0400 (EDT) X-Original-To: mailman-post+hostap@maxx.shmoo.com Delivered-To: mailman-post+hostap@maxx.shmoo.com Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id B975C17C0C4 for ; Sat, 27 Jul 2013 12:18:28 -0400 (EDT) X-Virus-Scanned: amavisd-new at maxx.shmoo.com Received: from maxx.maxx.shmoo.com ([127.0.0.1]) by localhost (maxx.shmoo.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ji3xnlVZxe4x for ; Sat, 27 Jul 2013 12:18:23 -0400 (EDT) Received: from mail.fem.tu-ilmenau.de (mail.fem.tu-ilmenau.de [141.24.101.79]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id E9C5617C149 for ; Sat, 27 Jul 2013 12:18:11 -0400 (EDT) Received: from localhost (localhost [127.0.0.1]) by mail.fem.tu-ilmenau.de (Postfix) with ESMTP id 7FB4365C2 for ; Sat, 27 Jul 2013 18:18:11 +0200 (CEST) X-Virus-Scanned: amavisd-new at fem.tu-ilmenau.de Received: from mail.fem.tu-ilmenau.de ([127.0.0.1]) by localhost (mail.fem.tu-ilmenau.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Z0A4lP1hMfnD; Sat, 27 Jul 2013 18:18:10 +0200 (CEST) Received: from a234.fem.tu-ilmenau.de (unknown [10.42.51.234]) by mail.fem.tu-ilmenau.de (Postfix) with ESMTP; Sat, 27 Jul 2013 18:18:10 +0200 (CEST) Received: from [10.42.51.234] (localhost [127.0.0.1]) by a234.fem.tu-ilmenau.de (Postfix) with ESMTP id 627B7BD0; Sat, 27 Jul 2013 18:18:10 +0200 (CEST) Subject: [PATCH v3 19/25] VLAN: use untagged/tagged for interface configuration To: hostap@lists.shmoo.com From: Michael Braun Date: Sat, 27 Jul 2013 18:18:10 +0200 Message-ID: <20130727161809.1152.6242.stgit@ray-controller> In-Reply-To: <20130727160024.1152.46147.stgit@ray-controller> References: <20130727160024.1152.46147.stgit@ray-controller> User-Agent: StGit/0.16 MIME-Version: 1.0 Cc: projekt-wlan@fem.tu-ilmenau.de X-BeenThere: hostap@lists.shmoo.com X-Mailman-Version: 2.1.11 Precedence: list List-Id: HostAP Project List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: hostap-bounces@lists.shmoo.com Errors-To: hostap-bounces@lists.shmoo.com Signed-hostap: Michael Braun --- src/ap/ap_config.h | 6 + src/ap/vlan_init.c | 355 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 223 insertions(+), 138 deletions(-) diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index c450219..5c5b15a 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -84,6 +84,10 @@ struct hostapd_vlan { /* untagged = VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */ vlan_t vlan_id; char ifname[IFNAMSIZ + 1]; + /* VLANs created automatically for a WILDCARD entry use this id for id + * generation. The linked list is sorted by this id (ascending); + * non-dynamically generated entries get value zero */ + int artifical_id; int dynamic_vlan; #ifdef CONFIG_FULL_DYNAMIC_VLAN @@ -91,7 +95,7 @@ struct hostapd_vlan { #define DVLAN_CLEAN_VLAN 0x2 #define DVLAN_CLEAN_VLAN_PORT 0x4 #define DVLAN_CLEAN_WLAN_PORT 0x8 - int clean; + int *clean; #endif /* CONFIG_FULL_DYNAMIC_VLAN */ }; diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c index 3b024fa..12fc2a1 100644 --- a/src/ap/vlan_init.c +++ b/src/ap/vlan_init.c @@ -597,165 +597,212 @@ static int hapd_put_dynamic_iface(const char *parent, const char *ifname, } -static void vlan_newlink(char *ifname, struct hostapd_data *hapd) +static void vlan_newlink_vlan(const int vlan_id, char *ifname, int *clean, + struct hostapd_data *hapd) { - char vlan_ifname[IFNAMSIZ]; - char br_name[IFNAMSIZ]; - struct hostapd_vlan *vlan = hapd->conf->vlan; + char vlan_ifname[IFNAMSIZ+1]; + char br_name[IFNAMSIZ+1]; char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; int vlan_naming = hapd->conf->ssid.vlan_naming; int ret; + if (hapd->conf->vlan_bridge[0]) { + os_snprintf(br_name, sizeof(br_name), "%s%d", + hapd->conf->vlan_bridge, vlan_id); + } else if (tagged_interface) { + os_snprintf(br_name, sizeof(br_name), "br%s.%d", + tagged_interface, vlan_id); + } else { + os_snprintf(br_name, sizeof(br_name), "brvlan%d", vlan_id); + } + + ret = br_addbr(br_name); + if (hapd_get_dynamic_iface(NULL, br_name, (ret == 0), hapd)) + if (clean) + *clean |= DVLAN_CLEAN_BR; + ifconfig_up(br_name); + + if (tagged_interface) { + if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE) + os_snprintf(vlan_ifname, sizeof(vlan_ifname), + "%s.%d", tagged_interface, vlan_id); + else + os_snprintf(vlan_ifname, sizeof(vlan_ifname), + "vlan%d", vlan_id); + + ifconfig_up(tagged_interface); + ret = vlan_add(tagged_interface, vlan_id, vlan_ifname); + if (hapd_get_dynamic_iface(NULL, vlan_ifname, (ret == 0), hapd)) + if (clean) + *clean |= DVLAN_CLEAN_VLAN; + ifconfig_up(vlan_ifname); + + ret = br_addif(br_name, vlan_ifname); + if (hapd_get_dynamic_iface(br_name, vlan_ifname, (ret == 0), + hapd)) + if (clean) + *clean |= DVLAN_CLEAN_VLAN_PORT; + } + + ifconfig_up(ifname); + + ret = br_addif(br_name, ifname); + if (hapd_get_dynamic_iface(br_name, ifname, (ret == 0), hapd)) + if (clean) + *clean |= DVLAN_CLEAN_WLAN_PORT; +} + + +static void vlan_newlink(char *ifname, struct hostapd_data *hapd) +{ + struct hostapd_vlan *vlan; + char vlan_ifname[IFNAMSIZ+1]; + int i, ret; + wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname); - while (vlan) { - if (os_strcmp(ifname, vlan->ifname) == 0) { - - if (hapd->conf->vlan_bridge[0]) { - os_snprintf(br_name, sizeof(br_name), "%s%d", - hapd->conf->vlan_bridge, - vlan_untagged(&vlan->vlan_id)); - } else if (tagged_interface) { - os_snprintf(br_name, sizeof(br_name), - "br%s.%d", tagged_interface, - vlan_untagged(&vlan->vlan_id)); - } else { - os_snprintf(br_name, sizeof(br_name), - "brvlan%d", - vlan_untagged(&vlan->vlan_id)); - } + for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) { + if (os_strcmp(ifname, vlan->ifname) != 0) + continue; - ret = br_addbr(br_name); - if (hapd_get_dynamic_iface(NULL, br_name, ret == 0, - hapd)) - vlan->clean |= DVLAN_CLEAN_BR; - - ifconfig_up(br_name); - - if (tagged_interface) { - if (vlan_naming == - DYNAMIC_VLAN_NAMING_WITH_DEVICE) - os_snprintf(vlan_ifname, - sizeof(vlan_ifname), - "%s.%d", tagged_interface, - vlan_untagged( - &vlan->vlan_id)); - else - os_snprintf(vlan_ifname, - sizeof(vlan_ifname), - "vlan%d", - vlan_untagged( - &vlan->vlan_id)); - - ifconfig_up(tagged_interface); - ret = vlan_add(tagged_interface, - vlan_untagged(&vlan->vlan_id), - vlan_ifname); - if (hapd_get_dynamic_iface(NULL, vlan_ifname, - ret == 0, hapd)) - vlan->clean |= DVLAN_CLEAN_VLAN; - - ret = br_addif(br_name, vlan_ifname); - if (hapd_get_dynamic_iface(br_name, - vlan_ifname, - ret == 0, hapd)) - vlan->clean |= DVLAN_CLEAN_VLAN_PORT; - - ifconfig_up(vlan_ifname); - } + int untagged, num_tagged, *tagged; + num_tagged = vlan_tagged(&vlan->vlan_id, &tagged); + untagged = vlan_untagged(&vlan->vlan_id); - ret = br_addif(br_name, ifname); - if (hapd_get_dynamic_iface(br_name, ifname, ret == 0, - hapd)) - vlan->clean |= DVLAN_CLEAN_WLAN_PORT; + if (!vlan->clean) + vlan->clean = os_zalloc((num_tagged + 1) * + sizeof(*(vlan->clean))); + if (untagged > 0) { + vlan_newlink_vlan(untagged, ifname, vlan->clean, hapd); + } else { ifconfig_up(ifname); + } + for (i = 0; i < num_tagged; i++) { + const int tagged_vlan_id = tagged[i]; + // add tagged interface on wlan + ret = os_snprintf(vlan_ifname, sizeof(vlan_ifname), + "%s.%d", ifname, tagged_vlan_id); + if (ret >= sizeof(vlan_ifname) || ret < 0) { + wpa_printf(MSG_ERROR, "VLAN: length limit for " + "interfaces names reached."); + continue; + } + vlan_add(ifname, tagged_vlan_id, vlan_ifname); + // add this to bridge + int *clean = NULL; + if (vlan->clean) + clean = &(vlan->clean[i+1]); + vlan_newlink_vlan(tagged_vlan_id, vlan_ifname, clean, + hapd); + } + break; + } +} - break; + +static void vlan_dellink_vlan(int vlan_id, char* ifname, int *clean, + struct hostapd_data *hapd) +{ + char vlan_ifname[IFNAMSIZ+1]; + char br_name[IFNAMSIZ+1]; + char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; + int vlan_naming = hapd->conf->ssid.vlan_naming; + + if (hapd->conf->vlan_bridge[0]) { + os_snprintf(br_name, sizeof(br_name), "%s%d", + hapd->conf->vlan_bridge, vlan_id); + } else if (tagged_interface) { + os_snprintf(br_name, sizeof(br_name), "br%s.%d", + tagged_interface, vlan_id); + } else { + os_snprintf(br_name, sizeof(br_name), "brvlan%d", vlan_id); + } + + if (clean && (*clean & DVLAN_CLEAN_WLAN_PORT) && + hapd_put_dynamic_iface(br_name, ifname, hapd)) + br_delif(br_name, ifname); + + if (tagged_interface) { + if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE) + os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s.%d", + tagged_interface, vlan_id); + else + os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d", + vlan_id); + if (clean && (*clean & DVLAN_CLEAN_VLAN_PORT) && + hapd_put_dynamic_iface(br_name, vlan_ifname, hapd)) + br_delif(br_name, vlan_ifname); + + if (clean && (*clean & DVLAN_CLEAN_VLAN) && + hapd_put_dynamic_iface(NULL, vlan_ifname, hapd)) { + ifconfig_down(vlan_ifname); + vlan_rem(vlan_ifname); } - vlan = vlan->next; } + + if (clean && (*clean & DVLAN_CLEAN_BR) && + hapd_put_dynamic_iface(NULL, br_name, hapd) && + br_getnumports(br_name) == 0) { + ifconfig_down(br_name); + br_delbr(br_name); + } + + if (clean) + *clean = 0; } static void vlan_dellink(char *ifname, struct hostapd_data *hapd) { + struct hostapd_vlan *first, *prev, *vlan; char vlan_ifname[IFNAMSIZ]; - char br_name[IFNAMSIZ]; - struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan; - char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; - int vlan_naming = hapd->conf->ssid.vlan_naming; + int i, ret; wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname); - first = prev = vlan; - - while (vlan) { - if (os_strcmp(ifname, vlan->ifname) == 0) { - if (hapd->conf->vlan_bridge[0]) { - os_snprintf(br_name, sizeof(br_name), "%s%d", - hapd->conf->vlan_bridge, - vlan_untagged(&vlan->vlan_id)); - } else if (tagged_interface) { - os_snprintf(br_name, sizeof(br_name), "br%s.%d", - tagged_interface, - vlan_untagged(&vlan->vlan_id)); - } else { - os_snprintf(br_name, sizeof(br_name), - "brvlan%d", - vlan_untagged(&vlan->vlan_id)); - } + for (first = prev = vlan = hapd->conf->vlan; vlan; + prev = vlan, vlan = vlan->next) { + if (os_strcmp(ifname, vlan->ifname) != 0) + continue; - if ((vlan->clean & DVLAN_CLEAN_WLAN_PORT) && - hapd_put_dynamic_iface(br_name, vlan->ifname, hapd)) - br_delif(br_name, vlan->ifname); - - if (tagged_interface) { - if (vlan_naming == - DYNAMIC_VLAN_NAMING_WITH_DEVICE) - os_snprintf(vlan_ifname, - sizeof(vlan_ifname), - "%s.%d", tagged_interface, - vlan_untagged( - &vlan->vlan_id)); - else - os_snprintf(vlan_ifname, - sizeof(vlan_ifname), - "vlan%d", - vlan_untagged( - &vlan->vlan_id)); - if ((vlan->clean & DVLAN_CLEAN_VLAN_PORT) && - hapd_put_dynamic_iface(br_name, vlan_ifname, - hapd)) - br_delif(br_name, vlan_ifname); - ifconfig_down(vlan_ifname); - - if ((vlan->clean & DVLAN_CLEAN_VLAN) && - hapd_put_dynamic_iface(NULL, vlan_ifname, - hapd)) - vlan_rem(vlan_ifname); - } + int untagged = vlan_untagged(&vlan->vlan_id); + if (untagged > 0) { + vlan_dellink_vlan(untagged, ifname, vlan->clean, hapd); + } - if ((vlan->clean & DVLAN_CLEAN_BR) && - hapd_put_dynamic_iface(NULL, br_name, hapd) && - br_getnumports(br_name) == 0) { - ifconfig_down(br_name); - br_delbr(br_name); + int num_tagged, *tagged; + num_tagged = vlan_tagged(&vlan->vlan_id, &tagged); + for (i = 0; i < num_tagged; i++) { + const int tagged_vlan_id = tagged[i]; + // add tagged interface on wlan + ret = os_snprintf(vlan_ifname, sizeof(vlan_ifname), + "%s.%d", ifname, tagged_vlan_id); + if (ret >= sizeof(vlan_ifname) || ret < 0) { + wpa_printf(MSG_ERROR, "VLAN: length limit for " + "interfaces names reached."); + continue; } + int *clean = NULL; + if (vlan->clean) + clean = &(vlan->clean[i+1]); + vlan_dellink_vlan(tagged_vlan_id, vlan_ifname, clean, + hapd); + vlan_rem(vlan_ifname); + } + if (vlan == first) { + hapd->conf->vlan = vlan->next; + } else { + prev->next = vlan->next; + } - if (vlan == first) { - hapd->conf->vlan = vlan->next; - } else { - prev->next = vlan->next; - } + vlan_free(&vlan->vlan_id); + os_free(vlan->clean); + vlan->clean = NULL; - vlan_free(&vlan->vlan_id); - os_free(vlan); + os_free(vlan); - break; - } - prev = vlan; - vlan = vlan->next; + break; } } @@ -1040,12 +1087,14 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, struct hostapd_vlan *vlan, vlan_t vlan_id) { - struct hostapd_vlan *n; + struct hostapd_vlan *n, *i, *prev; char *ifname, *pos; - if (vlan == NULL || vlan_untagged(&vlan_id) <= 0 || - vlan_untagged(&vlan_id) > MAX_VLAN_ID || - vlan_untagged(&vlan->vlan_id) != VLAN_ID_WILDCARD) + if (vlan == NULL + || vlan_untagged(&vlan_id) <= 0 + || vlan_untagged(&vlan_id) > MAX_VLAN_ID + || !vlan_notempty(&vlan_id) + || vlan_untagged(&vlan->vlan_id) != VLAN_ID_WILDCARD) return NULL; wpa_printf(MSG_DEBUG, "VLAN: %s(vlan_id=%s ifname=%s)", @@ -1069,8 +1118,34 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, vlan_alloc_copy(&n->vlan_id, &vlan_id); n->dynamic_vlan = 1; + /* artifical id := untagged vlan id (if no tagged vlan id given) + * := MAX_VLAN_ID + seq (if tagged vlan is set) + */ + int artifical_id = vlan_untagged(&vlan_id); + int num_tagged, *tagged; + num_tagged = vlan_tagged(&vlan_id, &tagged); + if (num_tagged > 0) { + /* get free artifical id, start searching at 4096 */ + artifical_id = MAX_VLAN_ID + 2; + prev = NULL; + for (i = hapd->conf->vlan; + i && i->artifical_id <= artifical_id; + i = i->next) { + if ( artifical_id == i->artifical_id ) + artifical_id++; + prev = i; + } + } else { + prev = NULL; + for (i = hapd->conf->vlan; + i && i->artifical_id <= artifical_id; + i = i->next) { + prev = i; + } + } + n->artifical_id = artifical_id; os_snprintf(n->ifname, sizeof(n->ifname), "%s%d%s", ifname, - vlan_untagged(&vlan_id), pos); + artifical_id, pos); os_free(ifname); if (hostapd_vlan_if_add(hapd, n->ifname)) { @@ -1078,8 +1153,14 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, return NULL; } - n->next = hapd->conf->vlan; - hapd->conf->vlan = n; + /* insert into list */ + if (!prev) { + n->next = hapd->conf->vlan; + hapd->conf->vlan = n; + } else { + n->next = prev->next; + prev->next = n; + } #ifdef CONFIG_FULL_DYNAMIC_VLAN ifconfig_up(n->ifname);