diff options
-rw-r--r-- | include/linux/nl80211.h | 35 | ||||
-rw-r--r-- | include/net/cfg80211.h | 24 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 4 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 44 |
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 | */ | ||
369 | enum 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 | */ | ||
178 | enum 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 */ |
167 | struct wiphy; | 187 | struct wiphy; |
168 | 188 | ||
@@ -213,10 +233,10 @@ struct wiphy; | |||
213 | */ | 233 | */ |
214 | struct cfg80211_ops { | 234 | struct 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 | ||
36 | static int ieee80211_add_iface(struct wiphy *wiphy, char *name, | 36 | static 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 | ||
71 | static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex, | 71 | static 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 | ||
340 | static 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 | |||
348 | static 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 | |||
339 | static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | 369 | static 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: |