From patchwork Sat Jul 27 16:18:35 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: michael-dev X-Patchwork-Id: 262485 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 71B492C00F0 for ; Sun, 28 Jul 2013 02:20:03 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id 4C08017C142; Sat, 27 Jul 2013 12:20:01 -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 jzb0bacH8p8P; Sat, 27 Jul 2013 12:20:01 -0400 (EDT) Received: from maxx.shmoo.com (localhost [127.0.0.1]) by maxx.maxx.shmoo.com (Postfix) with ESMTP id D548F17C157; Sat, 27 Jul 2013 12:19:13 -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 79E5E17C157 for ; Sat, 27 Jul 2013 12:19:12 -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 4Kylsf19K8nX for ; Sat, 27 Jul 2013 12:19:07 -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 8A54417C142 for ; Sat, 27 Jul 2013 12:18:36 -0400 (EDT) Received: from localhost (localhost [127.0.0.1]) by mail.fem.tu-ilmenau.de (Postfix) with ESMTP id 20007656D for ; Sat, 27 Jul 2013 18:18:36 +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 PzE+i35v+m22; Sat, 27 Jul 2013 18:18:35 +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:35 +0200 (CEST) Received: from [10.42.51.234] (localhost [127.0.0.1]) by a234.fem.tu-ilmenau.de (Postfix) with ESMTP id 58C02BD0; Sat, 27 Jul 2013 18:18:35 +0200 (CEST) Subject: [PATCH v3 23/25] VLAN: ensure destroying interfaces goes reverse as creating To: hostap@lists.shmoo.com From: Michael Braun Date: Sat, 27 Jul 2013 18:18:35 +0200 Message-ID: <20130727161834.1152.87872.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 I currently see [kernel] unregister_netdevice: waiting for wl0_1.73 to become free. Usage count = 1 messages, thought wl0_1.73 is not in ip -f link a s or /sys/class/net . iw dev wl0_1 station dump hangs This patch tries to avoid this by not plugging the wl device out in the middle at first but using the reverse procedure of creating for destruction. Further, it fixes a race condition. Imagine 1. STA removal triggers dynamic interface removal 2. STA reconnects, finds VLAN still present but fails to set key (detecting the VLAN has been removed here would generate a NEWLINK messages after 3. but that would be pointless, due to 3. removing the vlan from hapd->conf->vlan, which is required for manual vlan interface removal) 3. DELLINK is processed, removes the VLAN although in use Signed-hostap: Michael Braun --- src/ap/ap_config.h | 3 +++ src/ap/vlan_init.c | 53 +++++++++++++++++++++++++++++++++++----------------- 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index deae005..d58a3d1 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -95,6 +95,9 @@ struct hostapd_vlan { * freed. */ int newlink_seen; + /* Make sure DELLINK processing does not affect newly created + * interfaces. */ + int ifidx; int dynamic_vlan; #ifdef CONFIG_FULL_DYNAMIC_VLAN diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c index 8bd538e..f004c35 100644 --- a/src/ap/vlan_init.c +++ b/src/ap/vlan_init.c @@ -653,14 +653,16 @@ static void vlan_newlink_vlan(const int vlan_id, char *ifname, int *clean, } -static void vlan_newlink(char *ifname, struct hostapd_data *hapd) +static void vlan_newlink(char *ifname, int ifidx, struct hostapd_data *hapd) { struct hostapd_vlan *vlan; char vlan_ifname[IFNAMSIZ+1]; int i, ret; for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) { - if (os_strcmp(ifname, vlan->ifname) != 0 || vlan->newlink_seen) + if (os_strcmp(ifname, vlan->ifname) != 0 || + vlan->newlink_seen || + (vlan->ifidx > 0 && ifidx > 0 && vlan->ifidx != ifidx)) continue; wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname); @@ -698,7 +700,7 @@ static void vlan_newlink(char *ifname, struct hostapd_data *hapd) } vlan->newlink_seen = 1; - + vlan->ifidx = ifidx; break; } } @@ -760,7 +762,7 @@ static void vlan_dellink_vlan(int vlan_id, char* ifname, int *clean, } -static void vlan_dellink(char *ifname, struct hostapd_data *hapd) +static void vlan_dellink(char *ifname, int ifidx, struct hostapd_data *hapd) { struct hostapd_vlan *first, *prev, *vlan; char vlan_ifname[IFNAMSIZ]; @@ -768,7 +770,8 @@ static void vlan_dellink(char *ifname, struct hostapd_data *hapd) for (first = prev = vlan = hapd->conf->vlan; vlan; prev = vlan, vlan = vlan->next) { - if (os_strcmp(ifname, vlan->ifname) != 0) + if (os_strcmp(ifname, vlan->ifname) != 0 || + (vlan->ifidx > 0 && ifidx > 0 && vlan->ifidx != ifidx)) continue; wpa_printf(MSG_DEBUG, "VLAN:%s: vlan_dellink(%s)", @@ -820,7 +823,7 @@ vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del, struct hostapd_data *hapd) { struct ifinfomsg *ifi; - int attrlen, nlmsg_len, rta_len; + int attrlen, nlmsg_len, rta_len, ifidx; struct rtattr *attr; if (len < sizeof(*ifi)) @@ -834,6 +837,7 @@ vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del, if (attrlen < 0) return; + ifidx = ifi->ifi_index; attr = (struct rtattr *) (((char *) ifi) + nlmsg_len); rta_len = RTA_ALIGN(sizeof(struct rtattr)); @@ -852,9 +856,9 @@ vlan_read_ifnames(struct nlmsghdr *h, size_t len, int del, os_memcpy(ifname, ((char *) attr) + rta_len, n); if (del) - vlan_dellink(ifname, hapd); + vlan_dellink(ifname, ifidx, hapd); else - vlan_newlink(ifname, hapd); + vlan_newlink(ifname, ifidx, hapd); } attr = RTA_NEXT(attr, attrlen); @@ -1030,21 +1034,29 @@ static void vlan_dynamic_remove(struct hostapd_data *hapd, struct hostapd_vlan *vlan) { struct hostapd_vlan *next; + char buf[IFNAMSIZ+1]; + vlan_t vlan_id = VLAN_NULL; while (vlan) { next = vlan->next; - if (vlan_untagged(&vlan->vlan_id) != VLAN_ID_WILDCARD && - hostapd_vlan_if_remove(hapd, vlan->ifname)) { - wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN " - "iface: %s: %s", - vlan->ifname, strerror(errno)); - } + vlan_alloc_copy(&vlan_id, &vlan->vlan_id); + os_strncpy(buf, vlan->ifname, sizeof(buf)); + #ifdef CONFIG_FULL_DYNAMIC_VLAN if (vlan->clean) - vlan_dellink(vlan->ifname, hapd); + vlan_dellink(buf, vlan->ifidx, hapd); #endif /* CONFIG_FULL_DYNAMIC_VLAN */ + if (vlan_untagged(&vlan_id) != VLAN_ID_WILDCARD && + hostapd_vlan_if_remove(hapd, buf)) { + wpa_printf(MSG_ERROR, "VLAN: Could not remove VLAN " + "iface: %s: %s", + buf, strerror(errno)); + } + + vlan_free(&vlan_id); + vlan = next; } } @@ -1160,6 +1172,8 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, os_free(n); return NULL; } + // if id_add returned the ifidx, it could be reused here + n->ifidx = if_nametoindex(n->ifname); /* insert into list */ if (!prev) { @@ -1181,6 +1195,7 @@ struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, int vlan_remove_dynamic(struct hostapd_data *hapd, vlan_t vlan_id) { struct hostapd_vlan *vlan; + char buf[IFNAMSIZ+1]; if (vlan_untagged(&vlan->vlan_id) == VLAN_ID_WILDCARD) return 1; @@ -1201,8 +1216,12 @@ int vlan_remove_dynamic(struct hostapd_data *hapd, vlan_t vlan_id) if (vlan == NULL) return 1; - if (vlan->dynamic_vlan == 0) - hostapd_vlan_if_remove(hapd, vlan->ifname); + if (vlan->dynamic_vlan == 0) { + os_strncpy(buf, vlan->ifname, sizeof(buf)); + vlan_dellink(buf, vlan->ifidx, hapd); + vlan = NULL; /* freed by vlan_dellink */ + hostapd_vlan_if_remove(hapd, buf); + } return 0; }