aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2011-05-20 12:05:54 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-06-01 15:12:28 -0400
commit71063f0e8939b5b6ea5121faed47987e094ef018 (patch)
tree97936964a23ef6d26819c0267ea246cd0301ed9e /net/wireless
parent2e5ef4599addb1046086b63743f41822858a23b7 (diff)
nl80211: add testmode dump support
This adds dump support to testmode. The testmode dump support in nl80211 requires using two of the six cb->args, the rest can be used by the driver to figure out where the dump position is at or to store other data across invocations. Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/nl80211.c88
1 files changed, 88 insertions, 0 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 88a565f130a5..6d0d44b19ee6 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4361,6 +4361,93 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
4361 return err; 4361 return err;
4362} 4362}
4363 4363
4364static int nl80211_testmode_dump(struct sk_buff *skb,
4365 struct netlink_callback *cb)
4366{
4367 struct cfg80211_registered_device *dev;
4368 int err;
4369 long phy_idx;
4370 void *data = NULL;
4371 int data_len = 0;
4372
4373 if (cb->args[0]) {
4374 /*
4375 * 0 is a valid index, but not valid for args[0],
4376 * so we need to offset by 1.
4377 */
4378 phy_idx = cb->args[0] - 1;
4379 } else {
4380 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
4381 nl80211_fam.attrbuf, nl80211_fam.maxattr,
4382 nl80211_policy);
4383 if (err)
4384 return err;
4385 if (!nl80211_fam.attrbuf[NL80211_ATTR_WIPHY])
4386 return -EINVAL;
4387 phy_idx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]);
4388 if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
4389 cb->args[1] =
4390 (long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA];
4391 }
4392
4393 if (cb->args[1]) {
4394 data = nla_data((void *)cb->args[1]);
4395 data_len = nla_len((void *)cb->args[1]);
4396 }
4397
4398 mutex_lock(&cfg80211_mutex);
4399 dev = cfg80211_rdev_by_wiphy_idx(phy_idx);
4400 if (!dev) {
4401 mutex_unlock(&cfg80211_mutex);
4402 return -ENOENT;
4403 }
4404 cfg80211_lock_rdev(dev);
4405 mutex_unlock(&cfg80211_mutex);
4406
4407 if (!dev->ops->testmode_dump) {
4408 err = -EOPNOTSUPP;
4409 goto out_err;
4410 }
4411
4412 while (1) {
4413 void *hdr = nl80211hdr_put(skb, NETLINK_CB(cb->skb).pid,
4414 cb->nlh->nlmsg_seq, NLM_F_MULTI,
4415 NL80211_CMD_TESTMODE);
4416 struct nlattr *tmdata;
4417
4418 if (nla_put_u32(skb, NL80211_ATTR_WIPHY, dev->wiphy_idx) < 0) {
4419 genlmsg_cancel(skb, hdr);
4420 break;
4421 }
4422
4423 tmdata = nla_nest_start(skb, NL80211_ATTR_TESTDATA);
4424 if (!tmdata) {
4425 genlmsg_cancel(skb, hdr);
4426 break;
4427 }
4428 err = dev->ops->testmode_dump(&dev->wiphy, skb, cb,
4429 data, data_len);
4430 nla_nest_end(skb, tmdata);
4431
4432 if (err == -ENOBUFS || err == -ENOENT) {
4433 genlmsg_cancel(skb, hdr);
4434 break;
4435 } else if (err) {
4436 genlmsg_cancel(skb, hdr);
4437 goto out_err;
4438 }
4439
4440 genlmsg_end(skb, hdr);
4441 }
4442
4443 err = skb->len;
4444 /* see above */
4445 cb->args[0] = phy_idx + 1;
4446 out_err:
4447 cfg80211_unlock_rdev(dev);
4448 return err;
4449}
4450
4364static struct sk_buff * 4451static struct sk_buff *
4365__cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev, 4452__cfg80211_testmode_alloc_skb(struct cfg80211_registered_device *rdev,
4366 int approxlen, u32 pid, u32 seq, gfp_t gfp) 4453 int approxlen, u32 pid, u32 seq, gfp_t gfp)
@@ -5658,6 +5745,7 @@ static struct genl_ops nl80211_ops[] = {
5658 { 5745 {
5659 .cmd = NL80211_CMD_TESTMODE, 5746 .cmd = NL80211_CMD_TESTMODE,
5660 .doit = nl80211_testmode_do, 5747 .doit = nl80211_testmode_do,
5748 .dumpit = nl80211_testmode_dump,
5661 .policy = nl80211_policy, 5749 .policy = nl80211_policy,
5662 .flags = GENL_ADMIN_PERM, 5750 .flags = GENL_ADMIN_PERM,
5663 .internal_flags = NL80211_FLAG_NEED_WIPHY | 5751 .internal_flags = NL80211_FLAG_NEED_WIPHY |