mac80211: Disallow concurrent IBSS/STA mode interfaces
authorJohannes Berg <johannes@sipsolutions.net>
Thu, 21 Feb 2008 00:10:07 +0000 (01:10 +0100)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 29 Feb 2008 20:41:36 +0000 (15:41 -0500)
Disallow having more than one IBSS interface up at any time
because of beacon distribution issues, and for now also disallow
having more than one IBSS/STA interface up at the same time
because we use the master interface's BSS struct which would
be completely corrupted when we have more than one up.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
net/mac80211/ieee80211.c

index f82ebdd..2133c9f 100644 (file)
@@ -183,8 +183,52 @@ static int ieee80211_open(struct net_device *dev)
        list_for_each_entry(nsdata, &local->interfaces, list) {
                struct net_device *ndev = nsdata->dev;
 
-               if (ndev != dev && ndev != local->mdev && netif_running(ndev) &&
-                   compare_ether_addr(dev->dev_addr, ndev->dev_addr) == 0) {
+               if (ndev != dev && ndev != local->mdev && netif_running(ndev)) {
+                       /*
+                        * Allow only a single IBSS interface to be up at any
+                        * time. This is restricted because beacon distribution
+                        * cannot work properly if both are in the same IBSS.
+                        *
+                        * To remove this restriction we'd have to disallow them
+                        * from setting the same SSID on different IBSS interfaces
+                        * belonging to the same hardware. Then, however, we're
+                        * faced with having to adopt two different TSF timers...
+                        */
+                       if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
+                           nsdata->vif.type == IEEE80211_IF_TYPE_IBSS)
+                               return -EBUSY;
+
+                       /*
+                        * Disallow multiple IBSS/STA mode interfaces.
+                        *
+                        * This is a technical restriction, it is possible although
+                        * most likely not IEEE 802.11 compliant to have multiple
+                        * STAs with just a single hardware (the TSF timer will not
+                        * be adjusted properly.)
+                        *
+                        * However, because mac80211 uses the master device's BSS
+                        * information for each STA/IBSS interface, doing this will
+                        * currently corrupt that BSS information completely, unless,
+                        * a not very useful case, both STAs are associated to the
+                        * same BSS.
+                        *
+                        * To remove this restriction, the BSS information needs to
+                        * be embedded in the STA/IBSS mode sdata instead of using
+                        * the master device's BSS structure.
+                        */
+                       if ((sdata->vif.type == IEEE80211_IF_TYPE_STA ||
+                            sdata->vif.type == IEEE80211_IF_TYPE_IBSS) &&
+                           (nsdata->vif.type == IEEE80211_IF_TYPE_STA ||
+                            nsdata->vif.type == IEEE80211_IF_TYPE_IBSS))
+                               return -EBUSY;
+
+                       /*
+                        * The remaining checks are only performed for interfaces
+                        * with the same MAC address.
+                        */
+                       if (compare_ether_addr(dev->dev_addr, ndev->dev_addr))
+                               continue;
+
                        /*
                         * check whether it may have the same address
                         */
@@ -196,8 +240,7 @@ static int ieee80211_open(struct net_device *dev)
                         * can only add VLANs to enabled APs
                         */
                        if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN &&
-                           nsdata->vif.type == IEEE80211_IF_TYPE_AP &&
-                           netif_running(nsdata->dev))
+                           nsdata->vif.type == IEEE80211_IF_TYPE_AP)
                                sdata->u.vlan.ap = nsdata;
                }
        }