diff options
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r-- | net/wireless/nl80211.c | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 123d3b160fad..09a5d0f1d6dc 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -105,6 +105,10 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
105 | 105 | ||
106 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, | 106 | [NL80211_ATTR_HT_CAPABILITY] = { .type = NLA_BINARY, |
107 | .len = NL80211_HT_CAPABILITY_LEN }, | 107 | .len = NL80211_HT_CAPABILITY_LEN }, |
108 | |||
109 | [NL80211_ATTR_MGMT_SUBTYPE] = { .type = NLA_U8 }, | ||
110 | [NL80211_ATTR_IE] = { .type = NLA_BINARY, | ||
111 | .len = IEEE80211_MAX_DATA_LEN }, | ||
108 | }; | 112 | }; |
109 | 113 | ||
110 | /* message building helper */ | 114 | /* message building helper */ |
@@ -2149,6 +2153,43 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
2149 | return -EINVAL; | 2153 | return -EINVAL; |
2150 | } | 2154 | } |
2151 | 2155 | ||
2156 | static int nl80211_set_mgmt_extra_ie(struct sk_buff *skb, | ||
2157 | struct genl_info *info) | ||
2158 | { | ||
2159 | struct cfg80211_registered_device *drv; | ||
2160 | int err; | ||
2161 | struct net_device *dev; | ||
2162 | struct mgmt_extra_ie_params params; | ||
2163 | |||
2164 | memset(¶ms, 0, sizeof(params)); | ||
2165 | |||
2166 | if (!info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) | ||
2167 | return -EINVAL; | ||
2168 | params.subtype = nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]); | ||
2169 | if (params.subtype > 15) | ||
2170 | return -EINVAL; /* FC Subtype field is 4 bits (0..15) */ | ||
2171 | |||
2172 | if (info->attrs[NL80211_ATTR_IE]) { | ||
2173 | params.ies = nla_data(info->attrs[NL80211_ATTR_IE]); | ||
2174 | params.ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); | ||
2175 | } | ||
2176 | |||
2177 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | ||
2178 | if (err) | ||
2179 | return err; | ||
2180 | |||
2181 | if (drv->ops->set_mgmt_extra_ie) { | ||
2182 | rtnl_lock(); | ||
2183 | err = drv->ops->set_mgmt_extra_ie(&drv->wiphy, dev, ¶ms); | ||
2184 | rtnl_unlock(); | ||
2185 | } else | ||
2186 | err = -EOPNOTSUPP; | ||
2187 | |||
2188 | cfg80211_put_dev(drv); | ||
2189 | dev_put(dev); | ||
2190 | return err; | ||
2191 | } | ||
2192 | |||
2152 | static struct genl_ops nl80211_ops[] = { | 2193 | static struct genl_ops nl80211_ops[] = { |
2153 | { | 2194 | { |
2154 | .cmd = NL80211_CMD_GET_WIPHY, | 2195 | .cmd = NL80211_CMD_GET_WIPHY, |
@@ -2310,6 +2351,12 @@ static struct genl_ops nl80211_ops[] = { | |||
2310 | .policy = nl80211_policy, | 2351 | .policy = nl80211_policy, |
2311 | .flags = GENL_ADMIN_PERM, | 2352 | .flags = GENL_ADMIN_PERM, |
2312 | }, | 2353 | }, |
2354 | { | ||
2355 | .cmd = NL80211_CMD_SET_MGMT_EXTRA_IE, | ||
2356 | .doit = nl80211_set_mgmt_extra_ie, | ||
2357 | .policy = nl80211_policy, | ||
2358 | .flags = GENL_ADMIN_PERM, | ||
2359 | }, | ||
2313 | }; | 2360 | }; |
2314 | 2361 | ||
2315 | /* multicast groups */ | 2362 | /* multicast groups */ |