aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorMichael Wu <flamingice@sourmilk.net>2008-01-31 13:48:22 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-02-29 15:37:02 -0500
commit66f7ac50ed7cc5c19a62bc97e8f6e7891004a03a (patch)
tree92c4756ae29b64aee4a76a043fd46bb02472cfd9 /net
parente4c26add8893e40e6e809b8c1ebc81e37762af2b (diff)
nl80211: Add monitor interface configuration flags
This allows precise control over what a monitor interface shows. Signed-off-by: Michael Wu <flamingice@sourmilk.net> Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/cfg.c4
-rw-r--r--net/wireless/nl80211.c44
2 files changed, 44 insertions, 4 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 15b8cf94f510..706418d477c2 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -34,7 +34,7 @@ nl80211_type_to_mac80211_type(enum nl80211_iftype type)
34} 34}
35 35
36static int ieee80211_add_iface(struct wiphy *wiphy, char *name, 36static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
37 enum nl80211_iftype type) 37 enum nl80211_iftype type, u32 *flags)
38{ 38{
39 struct ieee80211_local *local = wiphy_priv(wiphy); 39 struct ieee80211_local *local = wiphy_priv(wiphy);
40 enum ieee80211_if_types itype; 40 enum ieee80211_if_types itype;
@@ -69,7 +69,7 @@ static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
69} 69}
70 70
71static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, 71static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
72 enum nl80211_iftype type) 72 enum nl80211_iftype type, u32 *flags)
73{ 73{
74 struct ieee80211_local *local = wiphy_priv(wiphy); 74 struct ieee80211_local *local = wiphy_priv(wiphy);
75 struct net_device *dev; 75 struct net_device *dev;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b123f58d3909..5b3474798b8d 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -82,6 +82,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
82 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY, 82 [NL80211_ATTR_STA_SUPPORTED_RATES] = { .type = NLA_BINARY,
83 .len = NL80211_MAX_SUPP_RATES }, 83 .len = NL80211_MAX_SUPP_RATES },
84 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 }, 84 [NL80211_ATTR_STA_VLAN] = { .type = NLA_U32 },
85 [NL80211_ATTR_MNTR_FLAGS] = { .type = NLA_NESTED },
85}; 86};
86 87
87/* message building helper */ 88/* message building helper */
@@ -336,12 +337,42 @@ static int nl80211_get_interface(struct sk_buff *skb, struct genl_info *info)
336 return -ENOBUFS; 337 return -ENOBUFS;
337} 338}
338 339
340static const struct nla_policy mntr_flags_policy[NL80211_MNTR_FLAG_MAX + 1] = {
341 [NL80211_MNTR_FLAG_FCSFAIL] = { .type = NLA_FLAG },
342 [NL80211_MNTR_FLAG_PLCPFAIL] = { .type = NLA_FLAG },
343 [NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
344 [NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
345 [NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
346};
347
348static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
349{
350 struct nlattr *flags[NL80211_MNTR_FLAG_MAX + 1];
351 int flag;
352
353 *mntrflags = 0;
354
355 if (!nla)
356 return -EINVAL;
357
358 if (nla_parse_nested(flags, NL80211_MNTR_FLAG_MAX,
359 nla, mntr_flags_policy))
360 return -EINVAL;
361
362 for (flag = 1; flag <= NL80211_MNTR_FLAG_MAX; flag++)
363 if (flags[flag])
364 *mntrflags |= (1<<flag);
365
366 return 0;
367}
368
339static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) 369static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
340{ 370{
341 struct cfg80211_registered_device *drv; 371 struct cfg80211_registered_device *drv;
342 int err, ifindex; 372 int err, ifindex;
343 enum nl80211_iftype type; 373 enum nl80211_iftype type;
344 struct net_device *dev; 374 struct net_device *dev;
375 u32 flags;
345 376
346 if (info->attrs[NL80211_ATTR_IFTYPE]) { 377 if (info->attrs[NL80211_ATTR_IFTYPE]) {
347 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]); 378 type = nla_get_u32(info->attrs[NL80211_ATTR_IFTYPE]);
@@ -362,7 +393,11 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info)
362 } 393 }
363 394
364 rtnl_lock(); 395 rtnl_lock();
365 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, type); 396 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
397 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
398 &flags);
399 err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex,
400 type, err ? NULL : &flags);
366 rtnl_unlock(); 401 rtnl_unlock();
367 402
368 unlock: 403 unlock:
@@ -375,6 +410,7 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
375 struct cfg80211_registered_device *drv; 410 struct cfg80211_registered_device *drv;
376 int err; 411 int err;
377 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED; 412 enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
413 u32 flags;
378 414
379 if (!info->attrs[NL80211_ATTR_IFNAME]) 415 if (!info->attrs[NL80211_ATTR_IFNAME])
380 return -EINVAL; 416 return -EINVAL;
@@ -395,8 +431,12 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
395 } 431 }
396 432
397 rtnl_lock(); 433 rtnl_lock();
434 err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
435 info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
436 &flags);
398 err = drv->ops->add_virtual_intf(&drv->wiphy, 437 err = drv->ops->add_virtual_intf(&drv->wiphy,
399 nla_data(info->attrs[NL80211_ATTR_IFNAME]), type); 438 nla_data(info->attrs[NL80211_ATTR_IFNAME]),
439 type, err ? NULL : &flags);
400 rtnl_unlock(); 440 rtnl_unlock();
401 441
402 unlock: 442 unlock: