aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/nl80211.h35
-rw-r--r--include/net/cfg80211.h24
-rw-r--r--net/mac80211/cfg.c4
-rw-r--r--net/wireless/nl80211.c44
4 files changed, 101 insertions, 6 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 63695060db9f..a9f0b93324a2 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -164,6 +164,9 @@ enum nl80211_commands {
164 * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands, 164 * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands,
165 * consisting of a nested array. 165 * consisting of a nested array.
166 * 166 *
167 * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of
168 * &enum nl80211_mntr_flags.
169 *
167 * @NL80211_ATTR_MAX: highest attribute number currently defined 170 * @NL80211_ATTR_MAX: highest attribute number currently defined
168 * @__NL80211_ATTR_AFTER_LAST: internal use 171 * @__NL80211_ATTR_AFTER_LAST: internal use
169 */ 172 */
@@ -200,6 +203,8 @@ enum nl80211_attrs {
200 203
201 NL80211_ATTR_WIPHY_BANDS, 204 NL80211_ATTR_WIPHY_BANDS,
202 205
206 NL80211_ATTR_MNTR_FLAGS,
207
203 /* add attributes here, update the policy in nl80211.c */ 208 /* add attributes here, update the policy in nl80211.c */
204 209
205 __NL80211_ATTR_AFTER_LAST, 210 __NL80211_ATTR_AFTER_LAST,
@@ -344,4 +349,34 @@ enum nl80211_bitrate_attr {
344 NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1 349 NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1
345}; 350};
346 351
352/**
353 * enum nl80211_mntr_flags - monitor configuration flags
354 *
355 * Monitor configuration flags.
356 *
357 * @__NL80211_MNTR_FLAG_INVALID: reserved
358 *
359 * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS
360 * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP
361 * @NL80211_MNTR_FLAG_CONTROL: pass control frames
362 * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering
363 * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing.
364 * overrides all other flags.
365 *
366 * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use
367 * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag
368 */
369enum nl80211_mntr_flags {
370 __NL80211_MNTR_FLAG_INVALID,
371 NL80211_MNTR_FLAG_FCSFAIL,
372 NL80211_MNTR_FLAG_PLCPFAIL,
373 NL80211_MNTR_FLAG_CONTROL,
374 NL80211_MNTR_FLAG_OTHER_BSS,
375 NL80211_MNTR_FLAG_COOK_FRAMES,
376
377 /* keep last */
378 __NL80211_MNTR_FLAG_AFTER_LAST,
379 NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1
380};
381
347#endif /* __LINUX_NL80211_H */ 382#endif /* __LINUX_NL80211_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index bcc480b8892a..ab4caf63954f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -163,6 +163,26 @@ struct station_stats {
163 u32 tx_bytes; 163 u32 tx_bytes;
164}; 164};
165 165
166/**
167 * enum monitor_flags - monitor flags
168 *
169 * Monitor interface configuration flags. Note that these must be the bits
170 * according to the nl80211 flags.
171 *
172 * @MONITOR_FLAG_FCSFAIL: pass frames with bad FCS
173 * @MONITOR_FLAG_PLCPFAIL: pass frames with bad PLCP
174 * @MONITOR_FLAG_CONTROL: pass control frames
175 * @MONITOR_FLAG_OTHER_BSS: disable BSSID filtering
176 * @MONITOR_FLAG_COOK_FRAMES: report frames after processing
177 */
178enum monitor_flags {
179 MONITOR_FLAG_FCSFAIL = 1<<NL80211_MNTR_FLAG_FCSFAIL,
180 MONITOR_FLAG_PLCPFAIL = 1<<NL80211_MNTR_FLAG_PLCPFAIL,
181 MONITOR_FLAG_CONTROL = 1<<NL80211_MNTR_FLAG_CONTROL,
182 MONITOR_FLAG_OTHER_BSS = 1<<NL80211_MNTR_FLAG_OTHER_BSS,
183 MONITOR_FLAG_COOK_FRAMES = 1<<NL80211_MNTR_FLAG_COOK_FRAMES,
184};
185
166/* from net/wireless.h */ 186/* from net/wireless.h */
167struct wiphy; 187struct wiphy;
168 188
@@ -213,10 +233,10 @@ struct wiphy;
213 */ 233 */
214struct cfg80211_ops { 234struct cfg80211_ops {
215 int (*add_virtual_intf)(struct wiphy *wiphy, char *name, 235 int (*add_virtual_intf)(struct wiphy *wiphy, char *name,
216 enum nl80211_iftype type); 236 enum nl80211_iftype type, u32 *flags);
217 int (*del_virtual_intf)(struct wiphy *wiphy, int ifindex); 237 int (*del_virtual_intf)(struct wiphy *wiphy, int ifindex);
218 int (*change_virtual_intf)(struct wiphy *wiphy, int ifindex, 238 int (*change_virtual_intf)(struct wiphy *wiphy, int ifindex,
219 enum nl80211_iftype type); 239 enum nl80211_iftype type, u32 *flags);
220 240
221 int (*add_key)(struct wiphy *wiphy, struct net_device *netdev, 241 int (*add_key)(struct wiphy *wiphy, struct net_device *netdev,
222 u8 key_index, u8 *mac_addr, 242 u8 key_index, u8 *mac_addr,
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: