aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c602
1 files changed, 583 insertions, 19 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 31b807af323..ab9d8f14e15 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -7,13 +7,13 @@
7#include <linux/if.h> 7#include <linux/if.h>
8#include <linux/module.h> 8#include <linux/module.h>
9#include <linux/err.h> 9#include <linux/err.h>
10#include <linux/mutex.h>
11#include <linux/list.h> 10#include <linux/list.h>
12#include <linux/if_ether.h> 11#include <linux/if_ether.h>
13#include <linux/ieee80211.h> 12#include <linux/ieee80211.h>
14#include <linux/nl80211.h> 13#include <linux/nl80211.h>
15#include <linux/rtnetlink.h> 14#include <linux/rtnetlink.h>
16#include <linux/netlink.h> 15#include <linux/netlink.h>
16#include <linux/etherdevice.h>
17#include <net/genetlink.h> 17#include <net/genetlink.h>
18#include <net/cfg80211.h> 18#include <net/cfg80211.h>
19#include "core.h" 19#include "core.h"
@@ -105,6 +105,12 @@ 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 },
112 [NL80211_ATTR_SCAN_FREQUENCIES] = { .type = NLA_NESTED },
113 [NL80211_ATTR_SCAN_SSIDS] = { .type = NLA_NESTED },
108}; 114};
109 115
110/* message building helper */ 116/* message building helper */
@@ -135,8 +141,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
135 if (!hdr) 141 if (!hdr)
136 return -1; 142 return -1;
137 143
138 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->idx); 144 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, dev->wiphy_idx);
139 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy)); 145 NLA_PUT_STRING(msg, NL80211_ATTR_WIPHY_NAME, wiphy_name(&dev->wiphy));
146 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_SCAN_SSIDS,
147 dev->wiphy.max_scan_ssids);
140 148
141 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); 149 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
142 if (!nl_modes) 150 if (!nl_modes)
@@ -247,7 +255,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
247 int start = cb->args[0]; 255 int start = cb->args[0];
248 struct cfg80211_registered_device *dev; 256 struct cfg80211_registered_device *dev;
249 257
250 mutex_lock(&cfg80211_drv_mutex); 258 mutex_lock(&cfg80211_mutex);
251 list_for_each_entry(dev, &cfg80211_drv_list, list) { 259 list_for_each_entry(dev, &cfg80211_drv_list, list) {
252 if (++idx <= start) 260 if (++idx <= start)
253 continue; 261 continue;
@@ -258,7 +266,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
258 break; 266 break;
259 } 267 }
260 } 268 }
261 mutex_unlock(&cfg80211_drv_mutex); 269 mutex_unlock(&cfg80211_mutex);
262 270
263 cb->args[0] = idx; 271 cb->args[0] = idx;
264 272
@@ -461,7 +469,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
461 struct cfg80211_registered_device *dev; 469 struct cfg80211_registered_device *dev;
462 struct wireless_dev *wdev; 470 struct wireless_dev *wdev;
463 471
464 mutex_lock(&cfg80211_drv_mutex); 472 mutex_lock(&cfg80211_mutex);
465 list_for_each_entry(dev, &cfg80211_drv_list, list) { 473 list_for_each_entry(dev, &cfg80211_drv_list, list) {
466 if (wp_idx < wp_start) { 474 if (wp_idx < wp_start) {
467 wp_idx++; 475 wp_idx++;
@@ -488,7 +496,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
488 wp_idx++; 496 wp_idx++;
489 } 497 }
490 out: 498 out:
491 mutex_unlock(&cfg80211_drv_mutex); 499 mutex_unlock(&cfg80211_mutex);
492 500
493 cb->args[0] = wp_idx; 501 cb->args[0] = wp_idx;
494 cb->args[1] = if_idx; 502 cb->args[1] = if_idx;
@@ -738,7 +746,7 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info)
738 if (info->attrs[NL80211_ATTR_KEY_IDX]) 746 if (info->attrs[NL80211_ATTR_KEY_IDX])
739 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); 747 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
740 748
741 if (key_idx > 3) 749 if (key_idx > 5)
742 return -EINVAL; 750 return -EINVAL;
743 751
744 if (info->attrs[NL80211_ATTR_MAC]) 752 if (info->attrs[NL80211_ATTR_MAC])
@@ -804,30 +812,41 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
804 int err; 812 int err;
805 struct net_device *dev; 813 struct net_device *dev;
806 u8 key_idx; 814 u8 key_idx;
815 int (*func)(struct wiphy *wiphy, struct net_device *netdev,
816 u8 key_index);
807 817
808 if (!info->attrs[NL80211_ATTR_KEY_IDX]) 818 if (!info->attrs[NL80211_ATTR_KEY_IDX])
809 return -EINVAL; 819 return -EINVAL;
810 820
811 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); 821 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
812 822
813 if (key_idx > 3) 823 if (info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) {
824 if (key_idx < 4 || key_idx > 5)
825 return -EINVAL;
826 } else if (key_idx > 3)
814 return -EINVAL; 827 return -EINVAL;
815 828
816 /* currently only support setting default key */ 829 /* currently only support setting default key */
817 if (!info->attrs[NL80211_ATTR_KEY_DEFAULT]) 830 if (!info->attrs[NL80211_ATTR_KEY_DEFAULT] &&
831 !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT])
818 return -EINVAL; 832 return -EINVAL;
819 833
820 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); 834 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
821 if (err) 835 if (err)
822 return err; 836 return err;
823 837
824 if (!drv->ops->set_default_key) { 838 if (info->attrs[NL80211_ATTR_KEY_DEFAULT])
839 func = drv->ops->set_default_key;
840 else
841 func = drv->ops->set_default_mgmt_key;
842
843 if (!func) {
825 err = -EOPNOTSUPP; 844 err = -EOPNOTSUPP;
826 goto out; 845 goto out;
827 } 846 }
828 847
829 rtnl_lock(); 848 rtnl_lock();
830 err = drv->ops->set_default_key(&drv->wiphy, dev, key_idx); 849 err = func(&drv->wiphy, dev, key_idx);
831 rtnl_unlock(); 850 rtnl_unlock();
832 851
833 out: 852 out:
@@ -863,7 +882,7 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
863 if (info->attrs[NL80211_ATTR_MAC]) 882 if (info->attrs[NL80211_ATTR_MAC])
864 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); 883 mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
865 884
866 if (key_idx > 3) 885 if (key_idx > 5)
867 return -EINVAL; 886 return -EINVAL;
868 887
869 /* 888 /*
@@ -894,6 +913,10 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info)
894 if (params.key_len != 13) 913 if (params.key_len != 13)
895 return -EINVAL; 914 return -EINVAL;
896 break; 915 break;
916 case WLAN_CIPHER_SUITE_AES_CMAC:
917 if (params.key_len != 16)
918 return -EINVAL;
919 break;
897 default: 920 default:
898 return -EINVAL; 921 return -EINVAL;
899 } 922 }
@@ -928,7 +951,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
928 if (info->attrs[NL80211_ATTR_KEY_IDX]) 951 if (info->attrs[NL80211_ATTR_KEY_IDX])
929 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]); 952 key_idx = nla_get_u8(info->attrs[NL80211_ATTR_KEY_IDX]);
930 953
931 if (key_idx > 3) 954 if (key_idx > 5)
932 return -EINVAL; 955 return -EINVAL;
933 956
934 if (info->attrs[NL80211_ATTR_MAC]) 957 if (info->attrs[NL80211_ATTR_MAC])
@@ -1182,6 +1205,12 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
1182 1205
1183 nla_nest_end(msg, txrate); 1206 nla_nest_end(msg, txrate);
1184 } 1207 }
1208 if (sinfo->filled & STATION_INFO_RX_PACKETS)
1209 NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS,
1210 sinfo->rx_packets);
1211 if (sinfo->filled & STATION_INFO_TX_PACKETS)
1212 NLA_PUT_U32(msg, NL80211_STA_INFO_TX_PACKETS,
1213 sinfo->tx_packets);
1185 nla_nest_end(msg, sinfoattr); 1214 nla_nest_end(msg, sinfoattr);
1186 1215
1187 return genlmsg_end(msg, hdr); 1216 return genlmsg_end(msg, hdr);
@@ -1876,6 +1905,19 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
1876 int r; 1905 int r;
1877 char *data = NULL; 1906 char *data = NULL;
1878 1907
1908 /*
1909 * You should only get this when cfg80211 hasn't yet initialized
1910 * completely when built-in to the kernel right between the time
1911 * window between nl80211_init() and regulatory_init(), if that is
1912 * even possible.
1913 */
1914 mutex_lock(&cfg80211_mutex);
1915 if (unlikely(!cfg80211_regdomain)) {
1916 mutex_unlock(&cfg80211_mutex);
1917 return -EINPROGRESS;
1918 }
1919 mutex_unlock(&cfg80211_mutex);
1920
1879 if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) 1921 if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
1880 return -EINVAL; 1922 return -EINVAL;
1881 1923
@@ -1886,9 +1928,9 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
1886 if (is_world_regdom(data)) 1928 if (is_world_regdom(data))
1887 return -EINVAL; 1929 return -EINVAL;
1888#endif 1930#endif
1889 mutex_lock(&cfg80211_drv_mutex); 1931
1890 r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, 0, ENVIRON_ANY); 1932 r = regulatory_hint_user(data);
1891 mutex_unlock(&cfg80211_drv_mutex); 1933
1892 return r; 1934 return r;
1893} 1935}
1894 1936
@@ -2080,6 +2122,81 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2080 2122
2081#undef FILL_IN_MESH_PARAM_IF_SET 2123#undef FILL_IN_MESH_PARAM_IF_SET
2082 2124
2125static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
2126{
2127 struct sk_buff *msg;
2128 void *hdr = NULL;
2129 struct nlattr *nl_reg_rules;
2130 unsigned int i;
2131 int err = -EINVAL;
2132
2133 mutex_lock(&cfg80211_mutex);
2134
2135 if (!cfg80211_regdomain)
2136 goto out;
2137
2138 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
2139 if (!msg) {
2140 err = -ENOBUFS;
2141 goto out;
2142 }
2143
2144 hdr = nl80211hdr_put(msg, info->snd_pid, info->snd_seq, 0,
2145 NL80211_CMD_GET_REG);
2146 if (!hdr)
2147 goto nla_put_failure;
2148
2149 NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2,
2150 cfg80211_regdomain->alpha2);
2151
2152 nl_reg_rules = nla_nest_start(msg, NL80211_ATTR_REG_RULES);
2153 if (!nl_reg_rules)
2154 goto nla_put_failure;
2155
2156 for (i = 0; i < cfg80211_regdomain->n_reg_rules; i++) {
2157 struct nlattr *nl_reg_rule;
2158 const struct ieee80211_reg_rule *reg_rule;
2159 const struct ieee80211_freq_range *freq_range;
2160 const struct ieee80211_power_rule *power_rule;
2161
2162 reg_rule = &cfg80211_regdomain->reg_rules[i];
2163 freq_range = &reg_rule->freq_range;
2164 power_rule = &reg_rule->power_rule;
2165
2166 nl_reg_rule = nla_nest_start(msg, i);
2167 if (!nl_reg_rule)
2168 goto nla_put_failure;
2169
2170 NLA_PUT_U32(msg, NL80211_ATTR_REG_RULE_FLAGS,
2171 reg_rule->flags);
2172 NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_START,
2173 freq_range->start_freq_khz);
2174 NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_END,
2175 freq_range->end_freq_khz);
2176 NLA_PUT_U32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW,
2177 freq_range->max_bandwidth_khz);
2178 NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN,
2179 power_rule->max_antenna_gain);
2180 NLA_PUT_U32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP,
2181 power_rule->max_eirp);
2182
2183 nla_nest_end(msg, nl_reg_rule);
2184 }
2185
2186 nla_nest_end(msg, nl_reg_rules);
2187
2188 genlmsg_end(msg, hdr);
2189 err = genlmsg_unicast(msg, info->snd_pid);
2190 goto out;
2191
2192nla_put_failure:
2193 genlmsg_cancel(msg, hdr);
2194 err = -EMSGSIZE;
2195out:
2196 mutex_unlock(&cfg80211_mutex);
2197 return err;
2198}
2199
2083static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) 2200static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
2084{ 2201{
2085 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1]; 2202 struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
@@ -2135,9 +2252,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
2135 2252
2136 BUG_ON(rule_idx != num_rules); 2253 BUG_ON(rule_idx != num_rules);
2137 2254
2138 mutex_lock(&cfg80211_drv_mutex); 2255 mutex_lock(&cfg80211_mutex);
2139 r = set_regdom(rd); 2256 r = set_regdom(rd);
2140 mutex_unlock(&cfg80211_drv_mutex); 2257 mutex_unlock(&cfg80211_mutex);
2141 return r; 2258 return r;
2142 2259
2143 bad_reg: 2260 bad_reg:
@@ -2145,6 +2262,302 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
2145 return -EINVAL; 2262 return -EINVAL;
2146} 2263}
2147 2264
2265static int nl80211_set_mgmt_extra_ie(struct sk_buff *skb,
2266 struct genl_info *info)
2267{
2268 struct cfg80211_registered_device *drv;
2269 int err;
2270 struct net_device *dev;
2271 struct mgmt_extra_ie_params params;
2272
2273 memset(&params, 0, sizeof(params));
2274
2275 if (!info->attrs[NL80211_ATTR_MGMT_SUBTYPE])
2276 return -EINVAL;
2277 params.subtype = nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
2278 if (params.subtype > 15)
2279 return -EINVAL; /* FC Subtype field is 4 bits (0..15) */
2280
2281 if (info->attrs[NL80211_ATTR_IE]) {
2282 params.ies = nla_data(info->attrs[NL80211_ATTR_IE]);
2283 params.ies_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2284 }
2285
2286 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2287 if (err)
2288 return err;
2289
2290 if (drv->ops->set_mgmt_extra_ie) {
2291 rtnl_lock();
2292 err = drv->ops->set_mgmt_extra_ie(&drv->wiphy, dev, &params);
2293 rtnl_unlock();
2294 } else
2295 err = -EOPNOTSUPP;
2296
2297 cfg80211_put_dev(drv);
2298 dev_put(dev);
2299 return err;
2300}
2301
2302static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2303{
2304 struct cfg80211_registered_device *drv;
2305 struct net_device *dev;
2306 struct cfg80211_scan_request *request;
2307 struct cfg80211_ssid *ssid;
2308 struct ieee80211_channel *channel;
2309 struct nlattr *attr;
2310 struct wiphy *wiphy;
2311 int err, tmp, n_ssids = 0, n_channels = 0, i;
2312 enum ieee80211_band band;
2313 size_t ie_len;
2314
2315 err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev);
2316 if (err)
2317 return err;
2318
2319 wiphy = &drv->wiphy;
2320
2321 if (!drv->ops->scan) {
2322 err = -EOPNOTSUPP;
2323 goto out;
2324 }
2325
2326 rtnl_lock();
2327
2328 if (drv->scan_req) {
2329 err = -EBUSY;
2330 goto out_unlock;
2331 }
2332
2333 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
2334 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp)
2335 n_channels++;
2336 if (!n_channels) {
2337 err = -EINVAL;
2338 goto out_unlock;
2339 }
2340 } else {
2341 for (band = 0; band < IEEE80211_NUM_BANDS; band++)
2342 if (wiphy->bands[band])
2343 n_channels += wiphy->bands[band]->n_channels;
2344 }
2345
2346 if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
2347 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp)
2348 n_ssids++;
2349
2350 if (n_ssids > wiphy->max_scan_ssids) {
2351 err = -EINVAL;
2352 goto out_unlock;
2353 }
2354
2355 if (info->attrs[NL80211_ATTR_IE])
2356 ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2357 else
2358 ie_len = 0;
2359
2360 request = kzalloc(sizeof(*request)
2361 + sizeof(*ssid) * n_ssids
2362 + sizeof(channel) * n_channels
2363 + ie_len, GFP_KERNEL);
2364 if (!request) {
2365 err = -ENOMEM;
2366 goto out_unlock;
2367 }
2368
2369 request->channels = (void *)((char *)request + sizeof(*request));
2370 request->n_channels = n_channels;
2371 if (n_ssids)
2372 request->ssids = (void *)(request->channels + n_channels);
2373 request->n_ssids = n_ssids;
2374 if (ie_len) {
2375 if (request->ssids)
2376 request->ie = (void *)(request->ssids + n_ssids);
2377 else
2378 request->ie = (void *)(request->channels + n_channels);
2379 }
2380
2381 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
2382 /* user specified, bail out if channel not found */
2383 request->n_channels = n_channels;
2384 i = 0;
2385 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) {
2386 request->channels[i] = ieee80211_get_channel(wiphy, nla_get_u32(attr));
2387 if (!request->channels[i]) {
2388 err = -EINVAL;
2389 goto out_free;
2390 }
2391 i++;
2392 }
2393 } else {
2394 /* all channels */
2395 i = 0;
2396 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
2397 int j;
2398 if (!wiphy->bands[band])
2399 continue;
2400 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
2401 request->channels[i] = &wiphy->bands[band]->channels[j];
2402 i++;
2403 }
2404 }
2405 }
2406
2407 i = 0;
2408 if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {
2409 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
2410 if (request->ssids[i].ssid_len > IEEE80211_MAX_SSID_LEN) {
2411 err = -EINVAL;
2412 goto out_free;
2413 }
2414 memcpy(request->ssids[i].ssid, nla_data(attr), nla_len(attr));
2415 request->ssids[i].ssid_len = nla_len(attr);
2416 i++;
2417 }
2418 }
2419
2420 if (info->attrs[NL80211_ATTR_IE]) {
2421 request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
2422 memcpy(request->ie, nla_data(info->attrs[NL80211_ATTR_IE]),
2423 request->ie_len);
2424 }
2425
2426 request->ifidx = dev->ifindex;
2427 request->wiphy = &drv->wiphy;
2428
2429 drv->scan_req = request;
2430 err = drv->ops->scan(&drv->wiphy, dev, request);
2431
2432 out_free:
2433 if (err) {
2434 drv->scan_req = NULL;
2435 kfree(request);
2436 }
2437 out_unlock:
2438 rtnl_unlock();
2439 out:
2440 cfg80211_put_dev(drv);
2441 dev_put(dev);
2442 return err;
2443}
2444
2445static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
2446 struct cfg80211_registered_device *rdev,
2447 struct net_device *dev,
2448 struct cfg80211_bss *res)
2449{
2450 void *hdr;
2451 struct nlattr *bss;
2452
2453 hdr = nl80211hdr_put(msg, pid, seq, flags,
2454 NL80211_CMD_NEW_SCAN_RESULTS);
2455 if (!hdr)
2456 return -1;
2457
2458 NLA_PUT_U32(msg, NL80211_ATTR_SCAN_GENERATION,
2459 rdev->bss_generation);
2460 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
2461
2462 bss = nla_nest_start(msg, NL80211_ATTR_BSS);
2463 if (!bss)
2464 goto nla_put_failure;
2465 if (!is_zero_ether_addr(res->bssid))
2466 NLA_PUT(msg, NL80211_BSS_BSSID, ETH_ALEN, res->bssid);
2467 if (res->information_elements && res->len_information_elements)
2468 NLA_PUT(msg, NL80211_BSS_INFORMATION_ELEMENTS,
2469 res->len_information_elements,
2470 res->information_elements);
2471 if (res->tsf)
2472 NLA_PUT_U64(msg, NL80211_BSS_TSF, res->tsf);
2473 if (res->beacon_interval)
2474 NLA_PUT_U16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval);
2475 NLA_PUT_U16(msg, NL80211_BSS_CAPABILITY, res->capability);
2476 NLA_PUT_U32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq);
2477
2478 switch (rdev->wiphy.signal_type) {
2479 case CFG80211_SIGNAL_TYPE_MBM:
2480 NLA_PUT_U32(msg, NL80211_BSS_SIGNAL_MBM, res->signal);
2481 break;
2482 case CFG80211_SIGNAL_TYPE_UNSPEC:
2483 NLA_PUT_U8(msg, NL80211_BSS_SIGNAL_UNSPEC, res->signal);
2484 break;
2485 default:
2486 break;
2487 }
2488
2489 nla_nest_end(msg, bss);
2490
2491 return genlmsg_end(msg, hdr);
2492
2493 nla_put_failure:
2494 genlmsg_cancel(msg, hdr);
2495 return -EMSGSIZE;
2496}
2497
2498static int nl80211_dump_scan(struct sk_buff *skb,
2499 struct netlink_callback *cb)
2500{
2501 struct cfg80211_registered_device *dev;
2502 struct net_device *netdev;
2503 struct cfg80211_internal_bss *scan;
2504 int ifidx = cb->args[0];
2505 int start = cb->args[1], idx = 0;
2506 int err;
2507
2508 if (!ifidx) {
2509 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
2510 nl80211_fam.attrbuf, nl80211_fam.maxattr,
2511 nl80211_policy);
2512 if (err)
2513 return err;
2514
2515 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
2516 return -EINVAL;
2517
2518 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
2519 if (!ifidx)
2520 return -EINVAL;
2521 cb->args[0] = ifidx;
2522 }
2523
2524 netdev = dev_get_by_index(&init_net, ifidx);
2525 if (!netdev)
2526 return -ENODEV;
2527
2528 dev = cfg80211_get_dev_from_ifindex(ifidx);
2529 if (IS_ERR(dev)) {
2530 err = PTR_ERR(dev);
2531 goto out_put_netdev;
2532 }
2533
2534 spin_lock_bh(&dev->bss_lock);
2535 cfg80211_bss_expire(dev);
2536
2537 list_for_each_entry(scan, &dev->bss_list, list) {
2538 if (++idx <= start)
2539 continue;
2540 if (nl80211_send_bss(skb,
2541 NETLINK_CB(cb->skb).pid,
2542 cb->nlh->nlmsg_seq, NLM_F_MULTI,
2543 dev, netdev, &scan->pub) < 0) {
2544 idx--;
2545 goto out;
2546 }
2547 }
2548
2549 out:
2550 spin_unlock_bh(&dev->bss_lock);
2551
2552 cb->args[1] = idx;
2553 err = skb->len;
2554 cfg80211_put_dev(dev);
2555 out_put_netdev:
2556 dev_put(netdev);
2557
2558 return err;
2559}
2560
2148static struct genl_ops nl80211_ops[] = { 2561static struct genl_ops nl80211_ops[] = {
2149 { 2562 {
2150 .cmd = NL80211_CMD_GET_WIPHY, 2563 .cmd = NL80211_CMD_GET_WIPHY,
@@ -2231,7 +2644,6 @@ static struct genl_ops nl80211_ops[] = {
2231 .doit = nl80211_get_station, 2644 .doit = nl80211_get_station,
2232 .dumpit = nl80211_dump_station, 2645 .dumpit = nl80211_dump_station,
2233 .policy = nl80211_policy, 2646 .policy = nl80211_policy,
2234 .flags = GENL_ADMIN_PERM,
2235 }, 2647 },
2236 { 2648 {
2237 .cmd = NL80211_CMD_SET_STATION, 2649 .cmd = NL80211_CMD_SET_STATION,
@@ -2283,6 +2695,12 @@ static struct genl_ops nl80211_ops[] = {
2283 .flags = GENL_ADMIN_PERM, 2695 .flags = GENL_ADMIN_PERM,
2284 }, 2696 },
2285 { 2697 {
2698 .cmd = NL80211_CMD_GET_REG,
2699 .doit = nl80211_get_reg,
2700 .policy = nl80211_policy,
2701 /* can be retrieved by unprivileged users */
2702 },
2703 {
2286 .cmd = NL80211_CMD_SET_REG, 2704 .cmd = NL80211_CMD_SET_REG,
2287 .doit = nl80211_set_reg, 2705 .doit = nl80211_set_reg,
2288 .policy = nl80211_policy, 2706 .policy = nl80211_policy,
@@ -2306,12 +2724,35 @@ static struct genl_ops nl80211_ops[] = {
2306 .policy = nl80211_policy, 2724 .policy = nl80211_policy,
2307 .flags = GENL_ADMIN_PERM, 2725 .flags = GENL_ADMIN_PERM,
2308 }, 2726 },
2727 {
2728 .cmd = NL80211_CMD_SET_MGMT_EXTRA_IE,
2729 .doit = nl80211_set_mgmt_extra_ie,
2730 .policy = nl80211_policy,
2731 .flags = GENL_ADMIN_PERM,
2732 },
2733 {
2734 .cmd = NL80211_CMD_TRIGGER_SCAN,
2735 .doit = nl80211_trigger_scan,
2736 .policy = nl80211_policy,
2737 .flags = GENL_ADMIN_PERM,
2738 },
2739 {
2740 .cmd = NL80211_CMD_GET_SCAN,
2741 .policy = nl80211_policy,
2742 .dumpit = nl80211_dump_scan,
2743 },
2309}; 2744};
2310 2745
2311/* multicast groups */ 2746/* multicast groups */
2312static struct genl_multicast_group nl80211_config_mcgrp = { 2747static struct genl_multicast_group nl80211_config_mcgrp = {
2313 .name = "config", 2748 .name = "config",
2314}; 2749};
2750static struct genl_multicast_group nl80211_scan_mcgrp = {
2751 .name = "scan",
2752};
2753static struct genl_multicast_group nl80211_regulatory_mcgrp = {
2754 .name = "regulatory",
2755};
2315 2756
2316/* notification functions */ 2757/* notification functions */
2317 2758
@@ -2331,6 +2772,121 @@ void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
2331 genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL); 2772 genlmsg_multicast(msg, 0, nl80211_config_mcgrp.id, GFP_KERNEL);
2332} 2773}
2333 2774
2775static int nl80211_send_scan_donemsg(struct sk_buff *msg,
2776 struct cfg80211_registered_device *rdev,
2777 struct net_device *netdev,
2778 u32 pid, u32 seq, int flags,
2779 u32 cmd)
2780{
2781 void *hdr;
2782
2783 hdr = nl80211hdr_put(msg, pid, seq, flags, cmd);
2784 if (!hdr)
2785 return -1;
2786
2787 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx);
2788 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex);
2789
2790 /* XXX: we should probably bounce back the request? */
2791
2792 return genlmsg_end(msg, hdr);
2793
2794 nla_put_failure:
2795 genlmsg_cancel(msg, hdr);
2796 return -EMSGSIZE;
2797}
2798
2799void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
2800 struct net_device *netdev)
2801{
2802 struct sk_buff *msg;
2803
2804 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
2805 if (!msg)
2806 return;
2807
2808 if (nl80211_send_scan_donemsg(msg, rdev, netdev, 0, 0, 0,
2809 NL80211_CMD_NEW_SCAN_RESULTS) < 0) {
2810 nlmsg_free(msg);
2811 return;
2812 }
2813
2814 genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL);
2815}
2816
2817void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
2818 struct net_device *netdev)
2819{
2820 struct sk_buff *msg;
2821
2822 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
2823 if (!msg)
2824 return;
2825
2826 if (nl80211_send_scan_donemsg(msg, rdev, netdev, 0, 0, 0,
2827 NL80211_CMD_SCAN_ABORTED) < 0) {
2828 nlmsg_free(msg);
2829 return;
2830 }
2831
2832 genlmsg_multicast(msg, 0, nl80211_scan_mcgrp.id, GFP_KERNEL);
2833}
2834
2835/*
2836 * This can happen on global regulatory changes or device specific settings
2837 * based on custom world regulatory domains.
2838 */
2839void nl80211_send_reg_change_event(struct regulatory_request *request)
2840{
2841 struct sk_buff *msg;
2842 void *hdr;
2843
2844 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
2845 if (!msg)
2846 return;
2847
2848 hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_REG_CHANGE);
2849 if (!hdr) {
2850 nlmsg_free(msg);
2851 return;
2852 }
2853
2854 /* Userspace can always count this one always being set */
2855 NLA_PUT_U8(msg, NL80211_ATTR_REG_INITIATOR, request->initiator);
2856
2857 if (request->alpha2[0] == '0' && request->alpha2[1] == '0')
2858 NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
2859 NL80211_REGDOM_TYPE_WORLD);
2860 else if (request->alpha2[0] == '9' && request->alpha2[1] == '9')
2861 NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
2862 NL80211_REGDOM_TYPE_CUSTOM_WORLD);
2863 else if ((request->alpha2[0] == '9' && request->alpha2[1] == '8') ||
2864 request->intersect)
2865 NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
2866 NL80211_REGDOM_TYPE_INTERSECTION);
2867 else {
2868 NLA_PUT_U8(msg, NL80211_ATTR_REG_TYPE,
2869 NL80211_REGDOM_TYPE_COUNTRY);
2870 NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, request->alpha2);
2871 }
2872
2873 if (wiphy_idx_valid(request->wiphy_idx))
2874 NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, request->wiphy_idx);
2875
2876 if (genlmsg_end(msg, hdr) < 0) {
2877 nlmsg_free(msg);
2878 return;
2879 }
2880
2881 genlmsg_multicast(msg, 0, nl80211_regulatory_mcgrp.id, GFP_KERNEL);
2882
2883 return;
2884
2885nla_put_failure:
2886 genlmsg_cancel(msg, hdr);
2887 nlmsg_free(msg);
2888}
2889
2334/* initialisation/exit functions */ 2890/* initialisation/exit functions */
2335 2891
2336int nl80211_init(void) 2892int nl80211_init(void)
@@ -2351,6 +2907,14 @@ int nl80211_init(void)
2351 if (err) 2907 if (err)
2352 goto err_out; 2908 goto err_out;
2353 2909
2910 err = genl_register_mc_group(&nl80211_fam, &nl80211_scan_mcgrp);
2911 if (err)
2912 goto err_out;
2913
2914 err = genl_register_mc_group(&nl80211_fam, &nl80211_regulatory_mcgrp);
2915 if (err)
2916 goto err_out;
2917
2354 return 0; 2918 return 0;
2355 err_out: 2919 err_out:
2356 genl_unregister_family(&nl80211_fam); 2920 genl_unregister_family(&nl80211_fam);