mac80211: add nl80211/cfg80211 handling of the new mesh root mode option.
[linux-2.6-block.git] / net / mac80211 / cfg.c
index 5608f6c68413d2169dfc44d3d081a2c9235c938b..7f18c8fa188034fa26f8253ea35aea6d856af112 100644 (file)
@@ -36,6 +36,24 @@ static bool nl80211_type_check(enum nl80211_iftype type)
        }
 }
 
+static bool nl80211_params_check(enum nl80211_iftype type,
+                                struct vif_params *params)
+{
+       if (!nl80211_type_check(type))
+               return false;
+
+       if (params->use_4addr > 0) {
+               switch(type) {
+               case NL80211_IFTYPE_AP_VLAN:
+               case NL80211_IFTYPE_STATION:
+                       break;
+               default:
+                       return false;
+               }
+       }
+       return true;
+}
+
 static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
                               enum nl80211_iftype type, u32 *flags,
                               struct vif_params *params)
@@ -45,7 +63,7 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
        struct ieee80211_sub_if_data *sdata;
        int err;
 
-       if (!nl80211_type_check(type))
+       if (!nl80211_params_check(type, params))
                return -EINVAL;
 
        err = ieee80211_if_add(local, name, &dev, type, params);
@@ -72,7 +90,10 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
        struct ieee80211_sub_if_data *sdata;
        int ret;
 
-       if (!nl80211_type_check(type))
+       if (netif_running(dev))
+               return -EBUSY;
+
+       if (!nl80211_params_check(type, params))
                return -EINVAL;
 
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
@@ -81,14 +102,14 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
        if (ret)
                return ret;
 
-       if (netif_running(sdata->dev))
-               return -EBUSY;
-
        if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
                ieee80211_sdata_set_mesh_id(sdata,
                                            params->mesh_id_len,
                                            params->mesh_id);
 
+       if (params->use_4addr >= 0)
+               sdata->use_4addr = !!params->use_4addr;
+
        if (sdata->vif.type != NL80211_IFTYPE_MONITOR || !flags)
                return 0;
 
@@ -738,13 +759,6 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
 
        err = sta_info_insert(sta);
        if (err) {
-               /* STA has been freed */
-               if (err == -EEXIST && layer2_update) {
-                       /* Need to update layer 2 devices on reassociation */
-                       sta = sta_info_get(local, mac);
-                       if (sta)
-                               ieee80211_send_layer2_update(sta);
-               }
                rcu_read_unlock();
                return err;
        }
@@ -813,6 +827,13 @@ static int ieee80211_change_station(struct wiphy *wiphy,
                        return -EINVAL;
                }
 
+               if (vlansdata->use_4addr) {
+                       if (vlansdata->u.vlan.sta)
+                               return -EBUSY;
+
+                       rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
+               }
+
                sta->sdata = vlansdata;
                ieee80211_send_layer2_update(sta);
        }
@@ -914,7 +935,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
        pinfo->generation = mesh_paths_generation;
 
        pinfo->filled = MPATH_INFO_FRAME_QLEN |
-                       MPATH_INFO_DSN |
+                       MPATH_INFO_SN |
                        MPATH_INFO_METRIC |
                        MPATH_INFO_EXPTIME |
                        MPATH_INFO_DISCOVERY_TIMEOUT |
@@ -922,7 +943,7 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
                        MPATH_INFO_FLAGS;
 
        pinfo->frame_qlen = mpath->frame_queue.qlen;
-       pinfo->dsn = mpath->dsn;
+       pinfo->sn = mpath->sn;
        pinfo->metric = mpath->metric;
        if (time_before(jiffies, mpath->exp_time))
                pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies);
@@ -934,8 +955,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
                pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
        if (mpath->flags & MESH_PATH_RESOLVING)
                pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
-       if (mpath->flags & MESH_PATH_DSN_VALID)
-               pinfo->flags |= NL80211_MPATH_FLAG_DSN_VALID;
+       if (mpath->flags & MESH_PATH_SN_VALID)
+               pinfo->flags |= NL80211_MPATH_FLAG_SN_VALID;
        if (mpath->flags & MESH_PATH_FIXED)
                pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
        if (mpath->flags & MESH_PATH_RESOLVING)
@@ -1008,7 +1029,10 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy,
 {
        struct mesh_config *conf;
        struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_if_mesh *ifmsh;
+
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       ifmsh = &sdata->u.mesh;
 
        /* Set the config options which we are interested in setting */
        conf = &(sdata->u.mesh.mshcfg);
@@ -1043,6 +1067,10 @@ static int ieee80211_set_mesh_params(struct wiphy *wiphy,
                           mask))
                conf->dot11MeshHWMPnetDiameterTraversalTime =
                        nconf->dot11MeshHWMPnetDiameterTraversalTime;
+       if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ROOTMODE, mask)) {
+               conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode;
+               ieee80211_mesh_root_setup(ifmsh);
+       }
        return 0;
 }