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.c406
1 files changed, 349 insertions, 57 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index ca3c92a0a14f..a6028433e3a0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -138,6 +138,9 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
138 [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 }, 138 [NL80211_ATTR_CIPHER_SUITE_GROUP] = { .type = NLA_U32 },
139 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, 139 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
140 [NL80211_ATTR_PID] = { .type = NLA_U32 }, 140 [NL80211_ATTR_PID] = { .type = NLA_U32 },
141 [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
142 [NL80211_ATTR_PMKID] = { .type = NLA_BINARY,
143 .len = WLAN_PMKID_LEN },
141}; 144};
142 145
143/* policy for the attributes */ 146/* policy for the attributes */
@@ -151,6 +154,26 @@ nl80211_key_policy[NL80211_KEY_MAX + 1] __read_mostly = {
151 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG }, 154 [NL80211_KEY_DEFAULT_MGMT] = { .type = NLA_FLAG },
152}; 155};
153 156
157/* ifidx get helper */
158static int nl80211_get_ifidx(struct netlink_callback *cb)
159{
160 int res;
161
162 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
163 nl80211_fam.attrbuf, nl80211_fam.maxattr,
164 nl80211_policy);
165 if (res)
166 return res;
167
168 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
169 return -EINVAL;
170
171 res = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
172 if (!res)
173 return -EINVAL;
174 return res;
175}
176
154/* IE validation */ 177/* IE validation */
155static bool is_valid_ie_attr(const struct nlattr *attr) 178static bool is_valid_ie_attr(const struct nlattr *attr)
156{ 179{
@@ -429,6 +452,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
429 sizeof(u32) * dev->wiphy.n_cipher_suites, 452 sizeof(u32) * dev->wiphy.n_cipher_suites,
430 dev->wiphy.cipher_suites); 453 dev->wiphy.cipher_suites);
431 454
455 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
456 dev->wiphy.max_num_pmkids);
457
432 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); 458 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
433 if (!nl_modes) 459 if (!nl_modes)
434 goto nla_put_failure; 460 goto nla_put_failure;
@@ -540,7 +566,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
540 CMD(deauth, DEAUTHENTICATE); 566 CMD(deauth, DEAUTHENTICATE);
541 CMD(disassoc, DISASSOCIATE); 567 CMD(disassoc, DISASSOCIATE);
542 CMD(join_ibss, JOIN_IBSS); 568 CMD(join_ibss, JOIN_IBSS);
543 if (dev->wiphy.netnsok) { 569 CMD(set_pmksa, SET_PMKSA);
570 CMD(del_pmksa, DEL_PMKSA);
571 CMD(flush_pmksa, FLUSH_PMKSA);
572 if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
544 i++; 573 i++;
545 NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); 574 NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
546 } 575 }
@@ -947,6 +976,32 @@ static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
947 return 0; 976 return 0;
948} 977}
949 978
979static int nl80211_valid_4addr(struct cfg80211_registered_device *rdev,
980 struct net_device *netdev, u8 use_4addr,
981 enum nl80211_iftype iftype)
982{
983 if (!use_4addr) {
984 if (netdev && netdev->br_port)
985 return -EBUSY;
986 return 0;
987 }
988
989 switch (iftype) {
990 case NL80211_IFTYPE_AP_VLAN:
991 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_AP)
992 return 0;
993 break;
994 case NL80211_IFTYPE_STATION:
995 if (rdev->wiphy.flags & WIPHY_FLAG_4ADDR_STATION)
996 return 0;
997 break;
998 default:
999 break;
1000 }
1001
1002 return -EOPNOTSUPP;
1003}
1004
950static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) 1005static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
951{ 1006{
952 struct cfg80211_registered_device *rdev; 1007 struct cfg80211_registered_device *rdev;
@@ -987,6 +1042,16 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
987 change = true; 1042 change = true;
988 } 1043 }
989 1044
1045 if (info->attrs[NL80211_ATTR_4ADDR]) {
1046 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
1047 change = true;
1048 err = nl80211_valid_4addr(rdev, dev, params.use_4addr, ntype);
1049 if (err)
1050 goto unlock;
1051 } else {
1052 params.use_4addr = -1;
1053 }
1054
990 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) { 1055 if (info->attrs[NL80211_ATTR_MNTR_FLAGS]) {
991 if (ntype != NL80211_IFTYPE_MONITOR) { 1056 if (ntype != NL80211_IFTYPE_MONITOR) {
992 err = -EINVAL; 1057 err = -EINVAL;
@@ -1006,6 +1071,9 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
1006 else 1071 else
1007 err = 0; 1072 err = 0;
1008 1073
1074 if (!err && params.use_4addr != -1)
1075 dev->ieee80211_ptr->use_4addr = params.use_4addr;
1076
1009 unlock: 1077 unlock:
1010 dev_put(dev); 1078 dev_put(dev);
1011 cfg80211_unlock_rdev(rdev); 1079 cfg80211_unlock_rdev(rdev);
@@ -1053,6 +1121,13 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
1053 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); 1121 params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
1054 } 1122 }
1055 1123
1124 if (info->attrs[NL80211_ATTR_4ADDR]) {
1125 params.use_4addr = !!nla_get_u8(info->attrs[NL80211_ATTR_4ADDR]);
1126 err = nl80211_valid_4addr(rdev, NULL, params.use_4addr, type);
1127 if (err)
1128 goto unlock;
1129 }
1130
1056 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? 1131 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
1057 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, 1132 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
1058 &flags); 1133 &flags);
@@ -1264,7 +1339,7 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info)
1264 if (!err) 1339 if (!err)
1265 err = func(&rdev->wiphy, dev, key.idx); 1340 err = func(&rdev->wiphy, dev, key.idx);
1266 1341
1267#ifdef CONFIG_WIRELESS_EXT 1342#ifdef CONFIG_CFG80211_WEXT
1268 if (!err) { 1343 if (!err) {
1269 if (func == rdev->ops->set_default_key) 1344 if (func == rdev->ops->set_default_key)
1270 dev->ieee80211_ptr->wext.default_key = key.idx; 1345 dev->ieee80211_ptr->wext.default_key = key.idx;
@@ -1365,7 +1440,7 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info)
1365 if (!err) 1440 if (!err)
1366 err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr); 1441 err = rdev->ops->del_key(&rdev->wiphy, dev, key.idx, mac_addr);
1367 1442
1368#ifdef CONFIG_WIRELESS_EXT 1443#ifdef CONFIG_CFG80211_WEXT
1369 if (!err) { 1444 if (!err) {
1370 if (key.idx == dev->ieee80211_ptr->wext.default_key) 1445 if (key.idx == dev->ieee80211_ptr->wext.default_key)
1371 dev->ieee80211_ptr->wext.default_key = -1; 1446 dev->ieee80211_ptr->wext.default_key = -1;
@@ -1682,20 +1757,10 @@ static int nl80211_dump_station(struct sk_buff *skb,
1682 int sta_idx = cb->args[1]; 1757 int sta_idx = cb->args[1];
1683 int err; 1758 int err;
1684 1759
1685 if (!ifidx) { 1760 if (!ifidx)
1686 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, 1761 ifidx = nl80211_get_ifidx(cb);
1687 nl80211_fam.attrbuf, nl80211_fam.maxattr, 1762 if (ifidx < 0)
1688 nl80211_policy); 1763 return ifidx;
1689 if (err)
1690 return err;
1691
1692 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
1693 return -EINVAL;
1694
1695 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
1696 if (!ifidx)
1697 return -EINVAL;
1698 }
1699 1764
1700 rtnl_lock(); 1765 rtnl_lock();
1701 1766
@@ -1800,7 +1865,7 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info)
1800} 1865}
1801 1866
1802/* 1867/*
1803 * Get vlan interface making sure it is on the right wiphy. 1868 * Get vlan interface making sure it is running and on the right wiphy.
1804 */ 1869 */
1805static int get_vlan(struct genl_info *info, 1870static int get_vlan(struct genl_info *info,
1806 struct cfg80211_registered_device *rdev, 1871 struct cfg80211_registered_device *rdev,
@@ -1818,6 +1883,8 @@ static int get_vlan(struct genl_info *info,
1818 return -EINVAL; 1883 return -EINVAL;
1819 if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy) 1884 if ((*vlan)->ieee80211_ptr->wiphy != &rdev->wiphy)
1820 return -EINVAL; 1885 return -EINVAL;
1886 if (!netif_running(*vlan))
1887 return -ENETDOWN;
1821 } 1888 }
1822 return 0; 1889 return 0;
1823} 1890}
@@ -2105,9 +2172,9 @@ static int nl80211_send_mpath(struct sk_buff *msg, u32 pid, u32 seq,
2105 if (pinfo->filled & MPATH_INFO_FRAME_QLEN) 2172 if (pinfo->filled & MPATH_INFO_FRAME_QLEN)
2106 NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN, 2173 NLA_PUT_U32(msg, NL80211_MPATH_INFO_FRAME_QLEN,
2107 pinfo->frame_qlen); 2174 pinfo->frame_qlen);
2108 if (pinfo->filled & MPATH_INFO_DSN) 2175 if (pinfo->filled & MPATH_INFO_SN)
2109 NLA_PUT_U32(msg, NL80211_MPATH_INFO_DSN, 2176 NLA_PUT_U32(msg, NL80211_MPATH_INFO_SN,
2110 pinfo->dsn); 2177 pinfo->sn);
2111 if (pinfo->filled & MPATH_INFO_METRIC) 2178 if (pinfo->filled & MPATH_INFO_METRIC)
2112 NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC, 2179 NLA_PUT_U32(msg, NL80211_MPATH_INFO_METRIC,
2113 pinfo->metric); 2180 pinfo->metric);
@@ -2145,20 +2212,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
2145 int path_idx = cb->args[1]; 2212 int path_idx = cb->args[1];
2146 int err; 2213 int err;
2147 2214
2148 if (!ifidx) { 2215 if (!ifidx)
2149 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, 2216 ifidx = nl80211_get_ifidx(cb);
2150 nl80211_fam.attrbuf, nl80211_fam.maxattr, 2217 if (ifidx < 0)
2151 nl80211_policy); 2218 return ifidx;
2152 if (err)
2153 return err;
2154
2155 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
2156 return -EINVAL;
2157
2158 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
2159 if (!ifidx)
2160 return -EINVAL;
2161 }
2162 2219
2163 rtnl_lock(); 2220 rtnl_lock();
2164 2221
@@ -2605,6 +2662,8 @@ static int nl80211_get_mesh_params(struct sk_buff *skb,
2605 cur_params.dot11MeshHWMPpreqMinInterval); 2662 cur_params.dot11MeshHWMPpreqMinInterval);
2606 NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, 2663 NLA_PUT_U16(msg, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
2607 cur_params.dot11MeshHWMPnetDiameterTraversalTime); 2664 cur_params.dot11MeshHWMPnetDiameterTraversalTime);
2665 NLA_PUT_U8(msg, NL80211_MESHCONF_HWMP_ROOTMODE,
2666 cur_params.dot11MeshHWMPRootMode);
2608 nla_nest_end(msg, pinfoattr); 2667 nla_nest_end(msg, pinfoattr);
2609 genlmsg_end(msg, hdr); 2668 genlmsg_end(msg, hdr);
2610 err = genlmsg_reply(msg, info); 2669 err = genlmsg_reply(msg, info);
@@ -2715,6 +2774,10 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info)
2715 dot11MeshHWMPnetDiameterTraversalTime, 2774 dot11MeshHWMPnetDiameterTraversalTime,
2716 mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, 2775 mask, NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
2717 nla_get_u16); 2776 nla_get_u16);
2777 FILL_IN_MESH_PARAM_IF_SET(tb, cfg,
2778 dot11MeshHWMPRootMode, mask,
2779 NL80211_MESHCONF_HWMP_ROOTMODE,
2780 nla_get_u8);
2718 2781
2719 /* Apply changes */ 2782 /* Apply changes */
2720 err = rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask); 2783 err = rdev->ops->set_mesh_params(&rdev->wiphy, dev, &cfg, mask);
@@ -2988,7 +3051,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2988 goto out; 3051 goto out;
2989 } 3052 }
2990 3053
2991 request->n_channels = n_channels;
2992 if (n_ssids) 3054 if (n_ssids)
2993 request->ssids = (void *)&request->channels[n_channels]; 3055 request->ssids = (void *)&request->channels[n_channels];
2994 request->n_ssids = n_ssids; 3056 request->n_ssids = n_ssids;
@@ -2999,32 +3061,53 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
2999 request->ie = (void *)(request->channels + n_channels); 3061 request->ie = (void *)(request->channels + n_channels);
3000 } 3062 }
3001 3063
3064 i = 0;
3002 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { 3065 if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
3003 /* user specified, bail out if channel not found */ 3066 /* user specified, bail out if channel not found */
3004 request->n_channels = n_channels;
3005 i = 0;
3006 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) { 3067 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_FREQUENCIES], tmp) {
3007 request->channels[i] = ieee80211_get_channel(wiphy, nla_get_u32(attr)); 3068 struct ieee80211_channel *chan;
3008 if (!request->channels[i]) { 3069
3070 chan = ieee80211_get_channel(wiphy, nla_get_u32(attr));
3071
3072 if (!chan) {
3009 err = -EINVAL; 3073 err = -EINVAL;
3010 goto out_free; 3074 goto out_free;
3011 } 3075 }
3076
3077 /* ignore disabled channels */
3078 if (chan->flags & IEEE80211_CHAN_DISABLED)
3079 continue;
3080
3081 request->channels[i] = chan;
3012 i++; 3082 i++;
3013 } 3083 }
3014 } else { 3084 } else {
3015 /* all channels */ 3085 /* all channels */
3016 i = 0;
3017 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 3086 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
3018 int j; 3087 int j;
3019 if (!wiphy->bands[band]) 3088 if (!wiphy->bands[band])
3020 continue; 3089 continue;
3021 for (j = 0; j < wiphy->bands[band]->n_channels; j++) { 3090 for (j = 0; j < wiphy->bands[band]->n_channels; j++) {
3022 request->channels[i] = &wiphy->bands[band]->channels[j]; 3091 struct ieee80211_channel *chan;
3092
3093 chan = &wiphy->bands[band]->channels[j];
3094
3095 if (chan->flags & IEEE80211_CHAN_DISABLED)
3096 continue;
3097
3098 request->channels[i] = chan;
3023 i++; 3099 i++;
3024 } 3100 }
3025 } 3101 }
3026 } 3102 }
3027 3103
3104 if (!i) {
3105 err = -EINVAL;
3106 goto out_free;
3107 }
3108
3109 request->n_channels = i;
3110
3028 i = 0; 3111 i = 0;
3029 if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) { 3112 if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {
3030 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) { 3113 nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS], tmp) {
@@ -3105,6 +3188,8 @@ static int nl80211_send_bss(struct sk_buff *msg, u32 pid, u32 seq, int flags,
3105 NLA_PUT_U16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval); 3188 NLA_PUT_U16(msg, NL80211_BSS_BEACON_INTERVAL, res->beacon_interval);
3106 NLA_PUT_U16(msg, NL80211_BSS_CAPABILITY, res->capability); 3189 NLA_PUT_U16(msg, NL80211_BSS_CAPABILITY, res->capability);
3107 NLA_PUT_U32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq); 3190 NLA_PUT_U32(msg, NL80211_BSS_FREQUENCY, res->channel->center_freq);
3191 NLA_PUT_U32(msg, NL80211_BSS_SEEN_MS_AGO,
3192 jiffies_to_msecs(jiffies - intbss->ts));
3108 3193
3109 switch (rdev->wiphy.signal_type) { 3194 switch (rdev->wiphy.signal_type) {
3110 case CFG80211_SIGNAL_TYPE_MBM: 3195 case CFG80211_SIGNAL_TYPE_MBM:
@@ -3159,21 +3244,11 @@ static int nl80211_dump_scan(struct sk_buff *skb,
3159 int start = cb->args[1], idx = 0; 3244 int start = cb->args[1], idx = 0;
3160 int err; 3245 int err;
3161 3246
3162 if (!ifidx) { 3247 if (!ifidx)
3163 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, 3248 ifidx = nl80211_get_ifidx(cb);
3164 nl80211_fam.attrbuf, nl80211_fam.maxattr, 3249 if (ifidx < 0)
3165 nl80211_policy); 3250 return ifidx;
3166 if (err) 3251 cb->args[0] = ifidx;
3167 return err;
3168
3169 if (!nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX])
3170 return -EINVAL;
3171
3172 ifidx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_IFINDEX]);
3173 if (!ifidx)
3174 return -EINVAL;
3175 cb->args[0] = ifidx;
3176 }
3177 3252
3178 dev = dev_get_by_index(sock_net(skb->sk), ifidx); 3253 dev = dev_get_by_index(sock_net(skb->sk), ifidx);
3179 if (!dev) 3254 if (!dev)
@@ -3216,6 +3291,106 @@ static int nl80211_dump_scan(struct sk_buff *skb,
3216 return err; 3291 return err;
3217} 3292}
3218 3293
3294static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq,
3295 int flags, struct net_device *dev,
3296 struct survey_info *survey)
3297{
3298 void *hdr;
3299 struct nlattr *infoattr;
3300
3301 /* Survey without a channel doesn't make sense */
3302 if (!survey->channel)
3303 return -EINVAL;
3304
3305 hdr = nl80211hdr_put(msg, pid, seq, flags,
3306 NL80211_CMD_NEW_SURVEY_RESULTS);
3307 if (!hdr)
3308 return -ENOMEM;
3309
3310 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
3311
3312 infoattr = nla_nest_start(msg, NL80211_ATTR_SURVEY_INFO);
3313 if (!infoattr)
3314 goto nla_put_failure;
3315
3316 NLA_PUT_U32(msg, NL80211_SURVEY_INFO_FREQUENCY,
3317 survey->channel->center_freq);
3318 if (survey->filled & SURVEY_INFO_NOISE_DBM)
3319 NLA_PUT_U8(msg, NL80211_SURVEY_INFO_NOISE,
3320 survey->noise);
3321
3322 nla_nest_end(msg, infoattr);
3323
3324 return genlmsg_end(msg, hdr);
3325
3326 nla_put_failure:
3327 genlmsg_cancel(msg, hdr);
3328 return -EMSGSIZE;
3329}
3330
3331static int nl80211_dump_survey(struct sk_buff *skb,
3332 struct netlink_callback *cb)
3333{
3334 struct survey_info survey;
3335 struct cfg80211_registered_device *dev;
3336 struct net_device *netdev;
3337 int ifidx = cb->args[0];
3338 int survey_idx = cb->args[1];
3339 int res;
3340
3341 if (!ifidx)
3342 ifidx = nl80211_get_ifidx(cb);
3343 if (ifidx < 0)
3344 return ifidx;
3345 cb->args[0] = ifidx;
3346
3347 rtnl_lock();
3348
3349 netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
3350 if (!netdev) {
3351 res = -ENODEV;
3352 goto out_rtnl;
3353 }
3354
3355 dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
3356 if (IS_ERR(dev)) {
3357 res = PTR_ERR(dev);
3358 goto out_rtnl;
3359 }
3360
3361 if (!dev->ops->dump_survey) {
3362 res = -EOPNOTSUPP;
3363 goto out_err;
3364 }
3365
3366 while (1) {
3367 res = dev->ops->dump_survey(&dev->wiphy, netdev, survey_idx,
3368 &survey);
3369 if (res == -ENOENT)
3370 break;
3371 if (res)
3372 goto out_err;
3373
3374 if (nl80211_send_survey(skb,
3375 NETLINK_CB(cb->skb).pid,
3376 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3377 netdev,
3378 &survey) < 0)
3379 goto out;
3380 survey_idx++;
3381 }
3382
3383 out:
3384 cb->args[1] = survey_idx;
3385 res = skb->len;
3386 out_err:
3387 cfg80211_unlock_rdev(dev);
3388 out_rtnl:
3389 rtnl_unlock();
3390
3391 return res;
3392}
3393
3219static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type) 3394static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type)
3220{ 3395{
3221 return auth_type <= NL80211_AUTHTYPE_MAX; 3396 return auth_type <= NL80211_AUTHTYPE_MAX;
@@ -4054,6 +4229,99 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
4054 return err; 4229 return err;
4055} 4230}
4056 4231
4232static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
4233{
4234 struct cfg80211_registered_device *rdev;
4235 int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
4236 struct cfg80211_pmksa *pmksa) = NULL;
4237 int err;
4238 struct net_device *dev;
4239 struct cfg80211_pmksa pmksa;
4240
4241 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
4242
4243 if (!info->attrs[NL80211_ATTR_MAC])
4244 return -EINVAL;
4245
4246 if (!info->attrs[NL80211_ATTR_PMKID])
4247 return -EINVAL;
4248
4249 rtnl_lock();
4250
4251 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4252 if (err)
4253 goto out_rtnl;
4254
4255 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
4256 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
4257
4258 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
4259 err = -EOPNOTSUPP;
4260 goto out;
4261 }
4262
4263 switch (info->genlhdr->cmd) {
4264 case NL80211_CMD_SET_PMKSA:
4265 rdev_ops = rdev->ops->set_pmksa;
4266 break;
4267 case NL80211_CMD_DEL_PMKSA:
4268 rdev_ops = rdev->ops->del_pmksa;
4269 break;
4270 default:
4271 WARN_ON(1);
4272 break;
4273 }
4274
4275 if (!rdev_ops) {
4276 err = -EOPNOTSUPP;
4277 goto out;
4278 }
4279
4280 err = rdev_ops(&rdev->wiphy, dev, &pmksa);
4281
4282 out:
4283 cfg80211_unlock_rdev(rdev);
4284 dev_put(dev);
4285 out_rtnl:
4286 rtnl_unlock();
4287
4288 return err;
4289}
4290
4291static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
4292{
4293 struct cfg80211_registered_device *rdev;
4294 int err;
4295 struct net_device *dev;
4296
4297 rtnl_lock();
4298
4299 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4300 if (err)
4301 goto out_rtnl;
4302
4303 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
4304 err = -EOPNOTSUPP;
4305 goto out;
4306 }
4307
4308 if (!rdev->ops->flush_pmksa) {
4309 err = -EOPNOTSUPP;
4310 goto out;
4311 }
4312
4313 err = rdev->ops->flush_pmksa(&rdev->wiphy, dev);
4314
4315 out:
4316 cfg80211_unlock_rdev(rdev);
4317 dev_put(dev);
4318 out_rtnl:
4319 rtnl_unlock();
4320
4321 return err;
4322
4323}
4324
4057static struct genl_ops nl80211_ops[] = { 4325static struct genl_ops nl80211_ops[] = {
4058 { 4326 {
4059 .cmd = NL80211_CMD_GET_WIPHY, 4327 .cmd = NL80211_CMD_GET_WIPHY,
@@ -4293,6 +4561,30 @@ static struct genl_ops nl80211_ops[] = {
4293 .policy = nl80211_policy, 4561 .policy = nl80211_policy,
4294 .flags = GENL_ADMIN_PERM, 4562 .flags = GENL_ADMIN_PERM,
4295 }, 4563 },
4564 {
4565 .cmd = NL80211_CMD_GET_SURVEY,
4566 .policy = nl80211_policy,
4567 .dumpit = nl80211_dump_survey,
4568 },
4569 {
4570 .cmd = NL80211_CMD_SET_PMKSA,
4571 .doit = nl80211_setdel_pmksa,
4572 .policy = nl80211_policy,
4573 .flags = GENL_ADMIN_PERM,
4574 },
4575 {
4576 .cmd = NL80211_CMD_DEL_PMKSA,
4577 .doit = nl80211_setdel_pmksa,
4578 .policy = nl80211_policy,
4579 .flags = GENL_ADMIN_PERM,
4580 },
4581 {
4582 .cmd = NL80211_CMD_FLUSH_PMKSA,
4583 .doit = nl80211_flush_pmksa,
4584 .policy = nl80211_policy,
4585 .flags = GENL_ADMIN_PERM,
4586 },
4587
4296}; 4588};
4297static struct genl_multicast_group nl80211_mlme_mcgrp = { 4589static struct genl_multicast_group nl80211_mlme_mcgrp = {
4298 .name = "mlme", 4590 .name = "mlme",