Accumulative patch from commit 1075b2957169d8f9d6dddd7679339c751dc9515b
1075b29 P2P: Report group formation failure on error to start GO mode
b62b29e Do not block on ctrl_iface monitor events
eb7ddbf WPS: Stop SSDP service before freeing the pending entries
98cbc0a Remove forgotten Xcode defines
0b9d3b2 Interworking: Relax 3GPP info PLMN matching for MNC
c7a67a7 WPS: Disconnect when removing existing WPS network block
fe65847 EAP-EKE: Add server implementation
7e7610d EAP-EKE: Add peer implementation
489202d EAP-SAKE: Use configured server identity
a607b42 EAP-PSK: Use configured server identity
15b042b EAP-MSCHAPv2: Use configured server identity
162865b EAP-IKEv2 server: Use configured server identity
8f89d82 EAP-GPSK server: Use configured server identity
67fe933 Add server identity configuration for EAP server
06aeff5 dbus: Register the AutoScan method call at the right place
78f79fe P2P: Do not add ctrl interface for P2P_DEVICE (p2p-dev-*)
1c42b42 P2P: Fix TDLS and l2_packet init without P2P Device interface
9e6a321 Fix non-P2P build after the P2P_DEVICE changes
d53d259 Fix build with older OpenSSL versions
54d4ba4 nl80211: Silence a compiler warning with older gcc versions
2e5ba4b P2P: Derive group interface name bit more sensibly
c68f620 P2P: Create P2P Device interface if supported
851b0c5 nl80211: Do not indicate P2P_DEVICE support by default
bb4028f P2P: Ignore p2p_no_group_iface when driver advertizes P2P_DEVICE support
7940c79 nl80211: Use wdev id when cancelling wait for frame using P2P_DEVICE
f608081 nl80211: Verify P2P GO/client address with all interface addresses
5fbcb45 nl80211: Fix determining phy name for P2P Device
27ce1d6 nl80211: Fix nl80211_get_wiphy_index() for P2P Device
080585c Add support for OCSP stapling to validate server certificate
72950ed P2P: Remove a call to wpas_p2p_deinit_global()
ab7a1ad nl80211: Fix P2P group interface creating using P2P Device
fa93de4 nl80211: Use wdev_id in nl80211_create_iface_once()
fdc554b nl80211: Use wdev id to obtain P2P Device scan results
597b94f nl80211: Add .get_mac_addr() callback for P2P Device
8e12685 nl80211: Rework setting interface mode
91724d6 nl80211: Introduce i802_set_iface_flags()
eb4582f nl80211: Remove P2P Device interface upon .deinit()
f632e48 nl80211: Fix P2P Device interface initialization
e472e1b nl80211: Handle creation of P2P Device interface
01517c8 nl80211: Allow Android P2P functionality
6bae92e nl80211: Add support for P2P Device in add interface
d6dcfcd nl80211: Add a handler to create_interface
d3aaef8 nl80211: Hold wdev identification for P2P Device
7aad838 nl80211: Identify if nl80211 is capable of P2P Device abstraction
6a71413 nl80211: Rename is_p2p_interface
8393e1a nl80211: Print interface name on set_key()
80ebfd9 VLAN: Avoid access to non-existing interfaces
4345fe9 bridge: Track inter-BSS usage
459eee9 bridge: Use safe default bridge interface
2aaeedf bridge: Give bridge name in per-bss configuration
8a901d7 D-Bus: Emit signal when a station is authorized or deauthorized
9578329 Add AVG_RSSI report in signal_poll
2cc8d8f Add bandwidth and center freq info to signal_poll
1e0e943 Remove 802.11b rates only in case of P2P group operation
2090a0b nl80211: Add prints for kernel events
8743676 TDLS: Validate ext_supp_rates in copy_supp_rates
85b4eac P2P: Do not reply to 802.11b-only Probe Request frames as GO
ec7b97a Interworking: Add support for using eap_proxy offload
4331263 Fix session timeout after ANQP dummy STA entry with SME-in-driver
56cb4e1 wpadebug: Add option to ignore SSL errors
aa20e1a Remove CONFIG_NO_WPA2 build parameter
5d5c4ee Remove compiler warnings with CONFIG_NO_SCAN_PROCESSING
9aaa695 Remove compiler warnings if TDLS is enabled without WPA2
84ae1d4 Fix WNM build without WPA2
c33d5eb Fix build without WPA2 or EAP
1aef400 IBSS RSN: Implement disconnect() callback using sta_deauth()
Change-Id: I4593be5b1478f6532da917423b1d2afa95fb8020
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
diff --git a/src/ap/vlan_init.c b/src/ap/vlan_init.c
index 6390e8b..70affda 100644
--- a/src/ap/vlan_init.c
+++ b/src/ap/vlan_init.c
@@ -480,6 +480,123 @@
#endif /* CONFIG_VLAN_NETLINK */
+/**
+ * Increase the usage counter for given parent/ifname combination.
+ * If create is set, then this iface is added to the global list.
+ * Returns
+ * -1 on error
+ * 0 if iface is not in list
+ * 1 if iface is in list (was there or has been added)
+ */
+static int hapd_get_dynamic_iface(const char *parent, const char *ifname,
+ int create, struct hostapd_data *hapd)
+{
+ size_t i;
+ struct hostapd_dynamic_iface *j = NULL, **tmp;
+ struct hapd_interfaces *hapd_global = hapd->iface->interfaces;
+
+ if (!parent)
+ parent = "";
+
+ for (i = 0; i < hapd_global->count_dynamic; i++) {
+ j = hapd_global->dynamic_iface[i];
+ if (os_strncmp(j->iface, ifname, sizeof(j->iface)) == 0 &&
+ os_strncmp(j->parent, parent, sizeof(j->parent)) == 0)
+ break;
+ }
+ if (i < hapd_global->count_dynamic) {
+ j->usage++;
+ return 1;
+ }
+
+ /* new entry required */
+ if (!create)
+ return 0;
+
+ j = os_zalloc(sizeof(*j));
+ if (!j)
+ return -1;
+ os_strlcpy(j->iface, ifname, sizeof(j->iface));
+ os_strlcpy(j->parent, parent, sizeof(j->parent));
+
+ tmp = os_realloc_array(hapd_global->dynamic_iface, i + 1,
+ sizeof(*hapd_global->dynamic_iface));
+ if (!tmp) {
+ wpa_printf(MSG_ERROR, "VLAN: Failed to allocate memory in %s",
+ __func__);
+ return -1;
+ }
+ hapd_global->count_dynamic++;
+ hapd_global->dynamic_iface = tmp;
+ hapd_global->dynamic_iface[i] = j;
+
+ return 1;
+}
+
+
+/**
+ * Decrease the usage counter for given ifname.
+ * Returns
+ * -1 on error or if iface was not found
+ * 0 if iface was found and is still present
+ * 1 if iface was removed from global list
+ */
+static int hapd_put_dynamic_iface(const char *parent, const char *ifname,
+ struct hostapd_data *hapd)
+{
+ size_t i;
+ struct hostapd_dynamic_iface *j = NULL, **tmp;
+ struct hapd_interfaces *hapd_glob = hapd->iface->interfaces;
+
+ if (!parent)
+ parent = "";
+
+ for (i = 0; i < hapd_glob->count_dynamic; i++) {
+ j = hapd_glob->dynamic_iface[i];
+ if (os_strncmp(j->iface, ifname, sizeof(j->iface)) == 0 &&
+ os_strncmp(j->parent, parent, sizeof(j->parent)) == 0)
+ break;
+ }
+
+ if (i == hapd_glob->count_dynamic) {
+ /*
+ * Interface not in global list. This can happen if alloc in
+ * _get_ failed.
+ */
+ return -1;
+ }
+
+ if (j->usage > 0) {
+ j->usage--;
+ return 0;
+ }
+
+ os_free(j);
+ for (; i < hapd_glob->count_dynamic - 1; i++)
+ hapd_glob->dynamic_iface[i] = hapd_glob->dynamic_iface[i + 1];
+ hapd_glob->dynamic_iface[hapd_glob->count_dynamic - 1] = NULL;
+ hapd_glob->count_dynamic--;
+
+ if (hapd_glob->count_dynamic == 0) {
+ os_free(hapd_glob->dynamic_iface);
+ hapd_glob->dynamic_iface = NULL;
+ return 1;
+ }
+
+ tmp = os_realloc_array(hapd_glob->dynamic_iface,
+ hapd_glob->count_dynamic,
+ sizeof(*hapd_glob->dynamic_iface));
+ if (!tmp) {
+ wpa_printf(MSG_ERROR, "VLAN: Failed to release memory in %s",
+ __func__);
+ return -1;
+ }
+ hapd_glob->dynamic_iface = tmp;
+
+ return 1;
+}
+
+
static void vlan_newlink(char *ifname, struct hostapd_data *hapd)
{
char vlan_ifname[IFNAMSIZ];
@@ -487,16 +604,29 @@
struct hostapd_vlan *vlan = hapd->conf->vlan;
char *tagged_interface = hapd->conf->ssid.vlan_tagged_interface;
int vlan_naming = hapd->conf->ssid.vlan_naming;
+ int ret;
wpa_printf(MSG_DEBUG, "VLAN: vlan_newlink(%s)", ifname);
while (vlan) {
if (os_strcmp(ifname, vlan->ifname) == 0) {
- os_snprintf(br_name, sizeof(br_name), "brvlan%d",
- vlan->vlan_id);
+ if (hapd->conf->vlan_bridge[0]) {
+ os_snprintf(br_name, sizeof(br_name), "%s%d",
+ hapd->conf->vlan_bridge,
+ vlan->vlan_id);
+ } else if (tagged_interface) {
+ os_snprintf(br_name, sizeof(br_name),
+ "br%s.%d", tagged_interface,
+ vlan->vlan_id);
+ } else {
+ os_snprintf(br_name, sizeof(br_name),
+ "brvlan%d", vlan->vlan_id);
+ }
- if (!br_addbr(br_name))
+ 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);
@@ -514,17 +644,24 @@
"vlan%d", vlan->vlan_id);
ifconfig_up(tagged_interface);
- if (!vlan_add(tagged_interface, vlan->vlan_id,
- vlan_ifname))
+ ret = vlan_add(tagged_interface, vlan->vlan_id,
+ vlan_ifname);
+ if (hapd_get_dynamic_iface(NULL, vlan_ifname,
+ ret == 0, hapd))
vlan->clean |= DVLAN_CLEAN_VLAN;
- if (!br_addif(br_name, vlan_ifname))
+ 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);
}
- if (!br_addif(br_name, ifname))
+ ret = br_addif(br_name, ifname);
+ if (hapd_get_dynamic_iface(br_name, ifname, ret == 0,
+ hapd))
vlan->clean |= DVLAN_CLEAN_WLAN_PORT;
ifconfig_up(ifname);
@@ -550,10 +687,21 @@
while (vlan) {
if (os_strcmp(ifname, vlan->ifname) == 0) {
- os_snprintf(br_name, sizeof(br_name), "brvlan%d",
- vlan->vlan_id);
+ if (hapd->conf->vlan_bridge[0]) {
+ os_snprintf(br_name, sizeof(br_name), "%s%d",
+ hapd->conf->vlan_bridge,
+ vlan->vlan_id);
+ } else if (tagged_interface) {
+ os_snprintf(br_name, sizeof(br_name),
+ "br%s.%d", tagged_interface,
+ vlan->vlan_id);
+ } else {
+ os_snprintf(br_name, sizeof(br_name),
+ "brvlan%d", vlan->vlan_id);
+ }
- if (vlan->clean & DVLAN_CLEAN_WLAN_PORT)
+ 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) {
@@ -567,15 +715,20 @@
os_snprintf(vlan_ifname,
sizeof(vlan_ifname),
"vlan%d", vlan->vlan_id);
- if (vlan->clean & DVLAN_CLEAN_VLAN_PORT)
+ 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)
+ if ((vlan->clean & DVLAN_CLEAN_VLAN) &&
+ hapd_put_dynamic_iface(NULL, vlan_ifname,
+ hapd))
vlan_rem(vlan_ifname);
}
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);