From f9c00188ca6f553b3e8043ac98455d516cf2ca02 Mon Sep 17 00:00:00 2001 From: Michael Braun Date: Thu, 21 Jan 2016 14:51:58 +0100 Subject: [PATCH] VLAN: Factor out per-vid code in newlink/dellink To prepare for adding tagged VLAN support in vlan_init.c, vlan_newlink() and vlan_dellink() are split into multiple functions. This reduces indention and eases adding tagged VLANs as well. Signed-off-by: Michael Braun --- src/ap/vlan_init.c | 279 +++++++++++++++++++++++++-------------------- 1 file changed, 153 insertions(+), 126 deletions(-) diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c index 4d93a706a..70110ef7a 100644 --- a/src/ap/vlan_init.c +++ b/src/ap/vlan_init.c @@ -623,155 +623,182 @@ static int vlan_set_name_type(unsigned int name_type) #endif /* CONFIG_VLAN_NETLINK */ -static void vlan_newlink(char *ifname, struct hostapd_data *hapd) +static void vlan_newlink_tagged(int vlan_naming, const char *tagged_interface, + const char *br_name, int vid, + struct hostapd_data *hapd) { char vlan_ifname[IFNAMSIZ]; - char br_name[IFNAMSIZ]; - struct hostapd_vlan *vlan = hapd->conf->vlan; + int clean; + + if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE) + os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s.%d", + tagged_interface, vid); + else + os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d", vid); + + clean = 0; + ifconfig_up(tagged_interface); + if (!vlan_add(tagged_interface, vid, vlan_ifname)) + clean |= DVLAN_CLEAN_VLAN; + + if (!br_addif(br_name, vlan_ifname)) + clean |= DVLAN_CLEAN_VLAN_PORT; + + dyn_iface_get(hapd, vlan_ifname, clean); + + ifconfig_up(vlan_ifname); +} + + +static void vlan_bridge_name(char *br_name, struct hostapd_data *hapd, int vid) +{ char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; - int vlan_naming = hapd->conf->ssid.vlan_naming; - int clean, untagged; - wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname); - - while (vlan) { - untagged = vlan->vlan_desc.untagged; - if (os_strcmp(ifname, vlan->ifname) == 0 && !vlan->configured) { - vlan->configured = 1; - - if (hapd->conf->vlan_bridge[0]) { - os_snprintf(br_name, sizeof(br_name), "%s%d", - hapd->conf->vlan_bridge, - untagged); - } else if (tagged_interface) { - os_snprintf(br_name, sizeof(br_name), - "br%s.%d", tagged_interface, - untagged); - } else { - os_snprintf(br_name, sizeof(br_name), - "brvlan%d", untagged); - } - - dyn_iface_get(hapd, br_name, - br_addbr(br_name) ? 0 : 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, - untagged); - else - os_snprintf(vlan_ifname, - sizeof(vlan_ifname), - "vlan%d", untagged); - - clean = 0; - ifconfig_up(tagged_interface); - if (!vlan_add(tagged_interface, untagged, - vlan_ifname)) - clean |= DVLAN_CLEAN_VLAN; - - if (!br_addif(br_name, vlan_ifname)) - clean |= DVLAN_CLEAN_VLAN_PORT; - - dyn_iface_get(hapd, vlan_ifname, clean); - - ifconfig_up(vlan_ifname); - } - - if (!br_addif(br_name, ifname)) - vlan->clean |= DVLAN_CLEAN_WLAN_PORT; - - ifconfig_up(ifname); - - break; - } - vlan = vlan->next; + if (hapd->conf->vlan_bridge[0]) { + os_snprintf(br_name, IFNAMSIZ, "%s%d", + hapd->conf->vlan_bridge, vid); + } else if (tagged_interface) { + os_snprintf(br_name, IFNAMSIZ, "br%s.%d", + tagged_interface, vid); + } else { + os_snprintf(br_name, IFNAMSIZ, "brvlan%d", vid); } } -static void vlan_dellink(char *ifname, struct hostapd_data *hapd) +static void vlan_get_bridge(const char *br_name, struct hostapd_data *hapd, + int vid) { - 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 clean, untagged; + + dyn_iface_get(hapd, br_name, br_addbr(br_name) ? 0 : DVLAN_CLEAN_BR); + + ifconfig_up(br_name); + + if (tagged_interface) + vlan_newlink_tagged(vlan_naming, tagged_interface, br_name, + vid, hapd); +} + + +static void vlan_newlink(const char *ifname, struct hostapd_data *hapd) +{ + char br_name[IFNAMSIZ]; + struct hostapd_vlan *vlan; + int untagged; + + wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname); + + for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) { + if (vlan->configured || + os_strcmp(ifname, vlan->ifname) != 0) + continue; + break; + } + if (!vlan) + return; + + vlan->configured = 1; + + untagged = vlan->vlan_desc.untagged; + + if (untagged > 0 && untagged <= MAX_VLAN_ID) { + vlan_bridge_name(br_name, hapd, untagged); + + vlan_get_bridge(br_name, hapd, untagged); + + if (!br_addif(br_name, ifname)) + vlan->clean |= DVLAN_CLEAN_WLAN_PORT; + } + + ifconfig_up(ifname); +} + + +static void vlan_dellink_tagged(int vlan_naming, const char *tagged_interface, + const char *br_name, int vid, + struct hostapd_data *hapd) +{ + char vlan_ifname[IFNAMSIZ]; + int clean; + + if (vlan_naming == DYNAMIC_VLAN_NAMING_WITH_DEVICE) + os_snprintf(vlan_ifname, sizeof(vlan_ifname), "%s.%d", + tagged_interface, vid); + else + os_snprintf(vlan_ifname, sizeof(vlan_ifname), "vlan%d", vid); + + clean = dyn_iface_put(hapd, vlan_ifname); + + if (clean & DVLAN_CLEAN_VLAN_PORT) + br_delif(br_name, vlan_ifname); + + if (clean & DVLAN_CLEAN_VLAN) { + ifconfig_down(vlan_ifname); + vlan_rem(vlan_ifname); + } +} + + +static void vlan_put_bridge(const char *br_name, struct hostapd_data *hapd, + int vid) +{ + int clean; + char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface; + int vlan_naming = hapd->conf->ssid.vlan_naming; + + if (tagged_interface) + vlan_dellink_tagged(vlan_naming, tagged_interface, br_name, + vid, hapd); + + clean = dyn_iface_put(hapd, br_name); + if ((clean & DVLAN_CLEAN_BR) && br_getnumports(br_name) == 0) { + ifconfig_down(br_name); + br_delbr(br_name); + } +} + + +static void vlan_dellink(const char *ifname, struct hostapd_data *hapd) +{ + struct hostapd_vlan *first, *prev, *vlan = hapd->conf->vlan; wpa_printf(MSG_DEBUG, "VLAN: vlan_dellink(%s)", ifname); first = prev = vlan; while (vlan) { - untagged = vlan->vlan_desc.untagged; - if (os_strcmp(ifname, vlan->ifname) == 0 && - vlan->configured) { - if (hapd->conf->vlan_bridge[0]) { - os_snprintf(br_name, sizeof(br_name), "%s%d", - hapd->conf->vlan_bridge, - untagged); - } else if (tagged_interface) { - os_snprintf(br_name, sizeof(br_name), - "br%s.%d", tagged_interface, - untagged); - } else { - os_snprintf(br_name, sizeof(br_name), - "brvlan%d", untagged); - } + if (os_strcmp(ifname, vlan->ifname) != 0) { + prev = vlan; + vlan = vlan->next; + continue; + } + break; + } + if (!vlan) + return; + + if (vlan->configured) { + int untagged = vlan->vlan_desc.untagged; + char br_name[IFNAMSIZ]; + + if (untagged > 0 && untagged <= MAX_VLAN_ID) { + vlan_bridge_name(br_name, hapd, untagged); if (vlan->clean & DVLAN_CLEAN_WLAN_PORT) 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, - untagged); - else - os_snprintf(vlan_ifname, - sizeof(vlan_ifname), - "vlan%d", untagged); - - clean = dyn_iface_put(hapd, vlan_ifname); - - if (clean & DVLAN_CLEAN_VLAN_PORT) - br_delif(br_name, vlan_ifname); - - if (clean & DVLAN_CLEAN_VLAN) { - ifconfig_down(vlan_ifname); - vlan_rem(vlan_ifname); - } - } - - clean = dyn_iface_put(hapd, br_name); - if ((clean & DVLAN_CLEAN_BR) && - br_getnumports(br_name) == 0) { - ifconfig_down(br_name); - br_delbr(br_name); - } + vlan_put_bridge(br_name, hapd, untagged); } - - if (os_strcmp(ifname, vlan->ifname) == 0) { - if (vlan == first) { - hapd->conf->vlan = vlan->next; - } else { - prev->next = vlan->next; - } - os_free(vlan); - - break; - } - prev = vlan; - vlan = vlan->next; } + + if (vlan == first) + hapd->conf->vlan = vlan->next; + else + prev->next = vlan->next; + + os_free(vlan); }