{nl,cfg,mac}80211: Add support of setting non-forwarding entity in Mesh
[linux-2.6-block.git] / net / wireless / nl80211.c
index b3d3cf8931cb9a3c055df2e497943ec2500cfc51..c42173f947efa149c40eae716cd32c3b25981ca2 100644 (file)
@@ -427,10 +427,9 @@ static int nl80211_parse_key_new(struct nlattr *key, struct key_parse *k)
 
        if (tb[NL80211_KEY_DEFAULT_TYPES]) {
                struct nlattr *kdt[NUM_NL80211_KEY_DEFAULT_TYPES];
-               int err = nla_parse_nested(kdt,
-                                          NUM_NL80211_KEY_DEFAULT_TYPES - 1,
-                                          tb[NL80211_KEY_DEFAULT_TYPES],
-                                          nl80211_key_default_policy);
+               err = nla_parse_nested(kdt, NUM_NL80211_KEY_DEFAULT_TYPES - 1,
+                                      tb[NL80211_KEY_DEFAULT_TYPES],
+                                      nl80211_key_default_policy);
                if (err)
                        return err;
 
@@ -2250,6 +2249,7 @@ static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = {
 };
 
 static int parse_station_flags(struct genl_info *info,
+                              enum nl80211_iftype iftype,
                               struct station_parameters *params)
 {
        struct nlattr *flags[NL80211_STA_FLAG_MAX + 1];
@@ -2283,8 +2283,33 @@ static int parse_station_flags(struct genl_info *info,
                             nla, sta_flags_policy))
                return -EINVAL;
 
-       params->sta_flags_mask = (1 << __NL80211_STA_FLAG_AFTER_LAST) - 1;
-       params->sta_flags_mask &= ~1;
+       /*
+        * Only allow certain flags for interface types so that
+        * other attributes are silently ignored. Remember that
+        * this is backward compatibility code with old userspace
+        * and shouldn't be hit in other cases anyway.
+        */
+       switch (iftype) {
+       case NL80211_IFTYPE_AP:
+       case NL80211_IFTYPE_AP_VLAN:
+       case NL80211_IFTYPE_P2P_GO:
+               params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
+                                        BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) |
+                                        BIT(NL80211_STA_FLAG_WME) |
+                                        BIT(NL80211_STA_FLAG_MFP);
+               break;
+       case NL80211_IFTYPE_P2P_CLIENT:
+       case NL80211_IFTYPE_STATION:
+               params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHORIZED) |
+                                        BIT(NL80211_STA_FLAG_TDLS_PEER);
+               break;
+       case NL80211_IFTYPE_MESH_POINT:
+               params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) |
+                                        BIT(NL80211_STA_FLAG_MFP) |
+                                        BIT(NL80211_STA_FLAG_AUTHORIZED);
+       default:
+               return -EINVAL;
+       }
 
        for (flag = 1; flag <= NL80211_STA_FLAG_MAX; flag++)
                if (flags[flag])
@@ -2585,7 +2610,7 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
        if (!rdev->ops->change_station)
                return -EOPNOTSUPP;
 
-       if (parse_station_flags(info, &params))
+       if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
                return -EINVAL;
 
        if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION])
@@ -2731,7 +2756,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
        if (!rdev->ops->add_station)
                return -EOPNOTSUPP;
 
-       if (parse_station_flags(info, &params))
+       if (parse_station_flags(info, dev->ieee80211_ptr->iftype, &params))
                return -EINVAL;
 
        switch (dev->ieee80211_ptr->iftype) {
@@ -3233,6 +3258,8 @@ static int nl80211_get_mesh_config(struct sk_buff *skb,
                        cur_params.dot11MeshHWMPRannInterval);
        NLA_PUT_U8(msg, NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
                        cur_params.dot11MeshGateAnnouncementProtocol);
+       NLA_PUT_U8(msg, NL80211_MESHCONF_FORWARDING,
+                       cur_params.dot11MeshForwarding);
        nla_nest_end(msg, pinfoattr);
        genlmsg_end(msg, hdr);
        return genlmsg_reply(msg, info);
@@ -3264,6 +3291,7 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
        [NL80211_MESHCONF_HWMP_ROOTMODE] = { .type = NLA_U8 },
        [NL80211_MESHCONF_HWMP_RANN_INTERVAL] = { .type = NLA_U16 },
        [NL80211_MESHCONF_GATE_ANNOUNCEMENTS] = { .type = NLA_U8 },
+       [NL80211_MESHCONF_FORWARDING] = { .type = NLA_U8 },
 };
 
 static const struct nla_policy
@@ -3353,6 +3381,8 @@ do {\
                        dot11MeshGateAnnouncementProtocol, mask,
                        NL80211_MESHCONF_GATE_ANNOUNCEMENTS,
                        nla_get_u8);
+       FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding,
+                       mask, NL80211_MESHCONF_FORWARDING, nla_get_u8);
        if (mask_out)
                *mask_out = mask;
 
@@ -4755,7 +4785,6 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
                        nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]);
                struct ieee80211_supported_band *sband =
                        wiphy->bands[ibss.channel->band];
-               int err;
 
                err = ieee80211_get_ratemask(sband, rates, n_rates,
                                             &ibss.basic_rates);