aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/nl80211.h34
-rw-r--r--include/net/cfg80211.h34
-rw-r--r--net/wireless/nl80211.c105
3 files changed, 173 insertions, 0 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index d2f276de9abe..45db17f81aa3 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -160,6 +160,11 @@
160 * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, 160 * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons,
161 * partial scan results may be available 161 * partial scan results may be available
162 * 162 *
163 * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation
164 * or noise level
165 * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to
166 * NL80211_CMD_GET_SURVEY and on the "scan" multicast group)
167 *
163 * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain 168 * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain
164 * has been changed and provides details of the request information 169 * has been changed and provides details of the request information
165 * that caused the change such as who initiated the regulatory request 170 * that caused the change such as who initiated the regulatory request
@@ -341,6 +346,9 @@ enum nl80211_commands {
341 346
342 NL80211_CMD_SET_WIPHY_NETNS, 347 NL80211_CMD_SET_WIPHY_NETNS,
343 348
349 NL80211_CMD_GET_SURVEY,
350 NL80211_CMD_NEW_SURVEY_RESULTS,
351
344 /* add new commands above here */ 352 /* add new commands above here */
345 353
346 /* used to define NL80211_CMD_MAX below */ 354 /* used to define NL80211_CMD_MAX below */
@@ -586,6 +594,10 @@ enum nl80211_commands {
586 * 594 *
587 * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface 595 * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface
588 * 596 *
597 * @NL80211_ATTR_SURVEY_INFO: survey information about a channel, part of
598 * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute
599 * containing info as possible, see &enum survey_info.
600 *
589 * @NL80211_ATTR_MAX: highest attribute number currently defined 601 * @NL80211_ATTR_MAX: highest attribute number currently defined
590 * @__NL80211_ATTR_AFTER_LAST: internal use 602 * @__NL80211_ATTR_AFTER_LAST: internal use
591 */ 603 */
@@ -718,6 +730,8 @@ enum nl80211_attrs {
718 730
719 NL80211_ATTR_4ADDR, 731 NL80211_ATTR_4ADDR,
720 732
733 NL80211_ATTR_SURVEY_INFO,
734
721 /* add attributes here, update the policy in nl80211.c */ 735 /* add attributes here, update the policy in nl80211.c */
722 736
723 __NL80211_ATTR_AFTER_LAST, 737 __NL80211_ATTR_AFTER_LAST,
@@ -1121,6 +1135,26 @@ enum nl80211_reg_rule_flags {
1121}; 1135};
1122 1136
1123/** 1137/**
1138 * enum nl80211_survey_info - survey information
1139 *
1140 * These attribute types are used with %NL80211_ATTR_SURVEY_INFO
1141 * when getting information about a survey.
1142 *
1143 * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved
1144 * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel
1145 * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm)
1146 */
1147enum nl80211_survey_info {
1148 __NL80211_SURVEY_INFO_INVALID,
1149 NL80211_SURVEY_INFO_FREQUENCY,
1150 NL80211_SURVEY_INFO_NOISE,
1151
1152 /* keep last */
1153 __NL80211_SURVEY_INFO_AFTER_LAST,
1154 NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1
1155};
1156
1157/**
1124 * enum nl80211_mntr_flags - monitor configuration flags 1158 * enum nl80211_mntr_flags - monitor configuration flags
1125 * 1159 *
1126 * Monitor configuration flags. 1160 * Monitor configuration flags.
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 0e4c51fc63e5..21710fc17eaf 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -235,6 +235,35 @@ struct key_params {
235}; 235};
236 236
237/** 237/**
238 * enum survey_info_flags - survey information flags
239 *
240 * Used by the driver to indicate which info in &struct survey_info
241 * it has filled in during the get_survey().
242 */
243enum survey_info_flags {
244 SURVEY_INFO_NOISE_DBM = 1<<0,
245};
246
247/**
248 * struct survey_info - channel survey response
249 *
250 * Used by dump_survey() to report back per-channel survey information.
251 *
252 * @channel: the channel this survey record reports, mandatory
253 * @filled: bitflag of flags from &enum survey_info_flags
254 * @noise: channel noise in dBm. This and all following fields are
255 * optional
256 *
257 * This structure can later be expanded with things like
258 * channel duty cycle etc.
259 */
260struct survey_info {
261 struct ieee80211_channel *channel;
262 u32 filled;
263 s8 noise;
264};
265
266/**
238 * struct beacon_parameters - beacon parameters 267 * struct beacon_parameters - beacon parameters
239 * 268 *
240 * Used to configure the beacon for an interface. 269 * Used to configure the beacon for an interface.
@@ -944,6 +973,8 @@ struct cfg80211_bitrate_mask {
944 * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting 973 * @rfkill_poll: polls the hw rfkill line, use cfg80211 reporting
945 * functions to adjust rfkill hw state 974 * functions to adjust rfkill hw state
946 * 975 *
976 * @dump_survey: get site survey information.
977 *
947 * @testmode_cmd: run a test mode command 978 * @testmode_cmd: run a test mode command
948 */ 979 */
949struct cfg80211_ops { 980struct cfg80211_ops {
@@ -1063,6 +1094,9 @@ struct cfg80211_ops {
1063 const u8 *peer, 1094 const u8 *peer,
1064 const struct cfg80211_bitrate_mask *mask); 1095 const struct cfg80211_bitrate_mask *mask);
1065 1096
1097 int (*dump_survey)(struct wiphy *wiphy, struct net_device *netdev,
1098 int idx, struct survey_info *info);
1099
1066 /* some temporary stuff to finish wext */ 1100 /* some temporary stuff to finish wext */
1067 int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, 1101 int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
1068 bool enabled, int timeout); 1102 bool enabled, int timeout);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 4dc139cdba5c..5c8b3bfada4b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3245,6 +3245,106 @@ static int nl80211_dump_scan(struct sk_buff *skb,
3245 return err; 3245 return err;
3246} 3246}
3247 3247
3248static int nl80211_send_survey(struct sk_buff *msg, u32 pid, u32 seq,
3249 int flags, struct net_device *dev,
3250 struct survey_info *survey)
3251{
3252 void *hdr;
3253 struct nlattr *infoattr;
3254
3255 /* Survey without a channel doesn't make sense */
3256 if (!survey->channel)
3257 return -EINVAL;
3258
3259 hdr = nl80211hdr_put(msg, pid, seq, flags,
3260 NL80211_CMD_NEW_SURVEY_RESULTS);
3261 if (!hdr)
3262 return -ENOMEM;
3263
3264 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, dev->ifindex);
3265
3266 infoattr = nla_nest_start(msg, NL80211_ATTR_SURVEY_INFO);
3267 if (!infoattr)
3268 goto nla_put_failure;
3269
3270 NLA_PUT_U32(msg, NL80211_SURVEY_INFO_FREQUENCY,
3271 survey->channel->center_freq);
3272 if (survey->filled & SURVEY_INFO_NOISE_DBM)
3273 NLA_PUT_U8(msg, NL80211_SURVEY_INFO_NOISE,
3274 survey->noise);
3275
3276 nla_nest_end(msg, infoattr);
3277
3278 return genlmsg_end(msg, hdr);
3279
3280 nla_put_failure:
3281 genlmsg_cancel(msg, hdr);
3282 return -EMSGSIZE;
3283}
3284
3285static int nl80211_dump_survey(struct sk_buff *skb,
3286 struct netlink_callback *cb)
3287{
3288 struct survey_info survey;
3289 struct cfg80211_registered_device *dev;
3290 struct net_device *netdev;
3291 int ifidx = cb->args[0];
3292 int survey_idx = cb->args[1];
3293 int res;
3294
3295 if (!ifidx)
3296 ifidx = nl80211_get_ifidx(cb);
3297 if (ifidx < 0)
3298 return ifidx;
3299 cb->args[0] = ifidx;
3300
3301 rtnl_lock();
3302
3303 netdev = __dev_get_by_index(sock_net(skb->sk), ifidx);
3304 if (!netdev) {
3305 res = -ENODEV;
3306 goto out_rtnl;
3307 }
3308
3309 dev = cfg80211_get_dev_from_ifindex(sock_net(skb->sk), ifidx);
3310 if (IS_ERR(dev)) {
3311 res = PTR_ERR(dev);
3312 goto out_rtnl;
3313 }
3314
3315 if (!dev->ops->dump_survey) {
3316 res = -EOPNOTSUPP;
3317 goto out_err;
3318 }
3319
3320 while (1) {
3321 res = dev->ops->dump_survey(&dev->wiphy, netdev, survey_idx,
3322 &survey);
3323 if (res == -ENOENT)
3324 break;
3325 if (res)
3326 goto out_err;
3327
3328 if (nl80211_send_survey(skb,
3329 NETLINK_CB(cb->skb).pid,
3330 cb->nlh->nlmsg_seq, NLM_F_MULTI,
3331 netdev,
3332 &survey) < 0)
3333 goto out;
3334 survey_idx++;
3335 }
3336
3337 out:
3338 cb->args[1] = survey_idx;
3339 res = skb->len;
3340 out_err:
3341 cfg80211_unlock_rdev(dev);
3342 out_rtnl:
3343 rtnl_unlock();
3344
3345 return res;
3346}
3347
3248static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type) 3348static bool nl80211_valid_auth_type(enum nl80211_auth_type auth_type)
3249{ 3349{
3250 return auth_type <= NL80211_AUTHTYPE_MAX; 3350 return auth_type <= NL80211_AUTHTYPE_MAX;
@@ -4322,6 +4422,11 @@ static struct genl_ops nl80211_ops[] = {
4322 .policy = nl80211_policy, 4422 .policy = nl80211_policy,
4323 .flags = GENL_ADMIN_PERM, 4423 .flags = GENL_ADMIN_PERM,
4324 }, 4424 },
4425 {
4426 .cmd = NL80211_CMD_GET_SURVEY,
4427 .policy = nl80211_policy,
4428 .dumpit = nl80211_dump_survey,
4429 },
4325}; 4430};
4326static struct genl_multicast_group nl80211_mlme_mcgrp = { 4431static struct genl_multicast_group nl80211_mlme_mcgrp = {
4327 .name = "mlme", 4432 .name = "mlme",