mac80211: add support for "active" monitor interfaces which allow userspace tools to connect to APs via injection
Signed-off-by: Felix Fietkau <nbd@openwrt.org> git-svn-id: svn://svn.openwrt.org/openwrt/trunk@36743 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
cf58fd647b
commit
fbe37f1e87
|
@ -740,7 +740,15 @@
|
||||||
struct rate_info txrate;
|
struct rate_info txrate;
|
||||||
struct rate_info rxrate;
|
struct rate_info rxrate;
|
||||||
u32 rx_packets;
|
u32 rx_packets;
|
||||||
@@ -4027,6 +4041,17 @@ bool cfg80211_reg_can_beacon(struct wiph
|
@@ -954,6 +968,7 @@ enum monitor_flags {
|
||||||
|
MONITOR_FLAG_CONTROL = 1<<NL80211_MNTR_FLAG_CONTROL,
|
||||||
|
MONITOR_FLAG_OTHER_BSS = 1<<NL80211_MNTR_FLAG_OTHER_BSS,
|
||||||
|
MONITOR_FLAG_COOK_FRAMES = 1<<NL80211_MNTR_FLAG_COOK_FRAMES,
|
||||||
|
+ MONITOR_FLAG_ACTIVE = 1<<NL80211_MNTR_FLAG_ACTIVE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
@@ -4027,6 +4042,17 @@ bool cfg80211_reg_can_beacon(struct wiph
|
||||||
void cfg80211_ch_switch_notify(struct net_device *dev,
|
void cfg80211_ch_switch_notify(struct net_device *dev,
|
||||||
struct cfg80211_chan_def *chandef);
|
struct cfg80211_chan_def *chandef);
|
||||||
|
|
||||||
|
@ -1024,7 +1032,31 @@
|
||||||
|
|
||||||
--- a/net/mac80211/cfg.c
|
--- a/net/mac80211/cfg.c
|
||||||
+++ b/net/mac80211/cfg.c
|
+++ b/net/mac80211/cfg.c
|
||||||
@@ -444,7 +444,7 @@ static void sta_set_sinfo(struct sta_inf
|
@@ -73,16 +73,19 @@ static int ieee80211_change_iface(struct
|
||||||
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
|
||||||
|
if (ieee80211_sdata_running(sdata)) {
|
||||||
|
+ u32 mask = MONITOR_FLAG_COOK_FRAMES |
|
||||||
|
+ MONITOR_FLAG_ACTIVE;
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
- * Prohibit MONITOR_FLAG_COOK_FRAMES to be
|
||||||
|
- * changed while the interface is up.
|
||||||
|
+ * Prohibit MONITOR_FLAG_COOK_FRAMES and
|
||||||
|
+ * MONITOR_FLAG_ACTIVE to be changed while the
|
||||||
|
+ * interface is up.
|
||||||
|
* Else we would need to add a lot of cruft
|
||||||
|
* to update everything:
|
||||||
|
* cooked_mntrs, monitor and all fif_* counters
|
||||||
|
* reconfigure hardware
|
||||||
|
*/
|
||||||
|
- if ((*flags & MONITOR_FLAG_COOK_FRAMES) !=
|
||||||
|
- (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES))
|
||||||
|
+ if ((*flags & mask) != (sdata->u.mntr_flags & mask))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
ieee80211_adjust_monitor_flags(sdata, -1);
|
||||||
|
@@ -444,7 +447,7 @@ static void sta_set_sinfo(struct sta_inf
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct timespec uptime;
|
struct timespec uptime;
|
||||||
u64 packets = 0;
|
u64 packets = 0;
|
||||||
|
@ -1033,7 +1065,7 @@
|
||||||
|
|
||||||
sinfo->generation = sdata->local->sta_generation;
|
sinfo->generation = sdata->local->sta_generation;
|
||||||
|
|
||||||
@@ -488,6 +488,17 @@ static void sta_set_sinfo(struct sta_inf
|
@@ -488,6 +491,17 @@ static void sta_set_sinfo(struct sta_inf
|
||||||
sinfo->signal = (s8)sta->last_signal;
|
sinfo->signal = (s8)sta->last_signal;
|
||||||
sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
|
sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal);
|
||||||
}
|
}
|
||||||
|
@ -1051,7 +1083,7 @@
|
||||||
|
|
||||||
sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
|
sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate);
|
||||||
sta_set_rate_info_rx(sta, &sinfo->rxrate);
|
sta_set_rate_info_rx(sta, &sinfo->rxrate);
|
||||||
@@ -1052,6 +1063,7 @@ static int ieee80211_stop_ap(struct wiph
|
@@ -1052,6 +1066,7 @@ static int ieee80211_stop_ap(struct wiph
|
||||||
ieee80211_free_keys(sdata);
|
ieee80211_free_keys(sdata);
|
||||||
|
|
||||||
sdata->vif.bss_conf.enable_beacon = false;
|
sdata->vif.bss_conf.enable_beacon = false;
|
||||||
|
@ -1059,7 +1091,7 @@
|
||||||
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
|
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
|
||||||
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
|
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
|
||||||
|
|
||||||
@@ -2416,9 +2428,22 @@ static int ieee80211_set_bitrate_mask(st
|
@@ -2416,9 +2431,22 @@ static int ieee80211_set_bitrate_mask(st
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
|
for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
|
||||||
|
@ -1296,7 +1328,51 @@
|
||||||
u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
|
u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
|
||||||
--- a/net/mac80211/iface.c
|
--- a/net/mac80211/iface.c
|
||||||
+++ b/net/mac80211/iface.c
|
+++ b/net/mac80211/iface.c
|
||||||
@@ -450,7 +450,6 @@ int ieee80211_do_open(struct wireless_de
|
@@ -159,7 +159,8 @@ static int ieee80211_change_mtu(struct n
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr)
|
||||||
|
+static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr,
|
||||||
|
+ bool check_dup)
|
||||||
|
{
|
||||||
|
struct ieee80211_sub_if_data *sdata;
|
||||||
|
u64 new, mask, tmp;
|
||||||
|
@@ -179,10 +180,13 @@ static int ieee80211_verify_mac(struct i
|
||||||
|
((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) |
|
||||||
|
((u64)m[4] << 1*8) | ((u64)m[5] << 0*8);
|
||||||
|
|
||||||
|
+ if (!check_dup)
|
||||||
|
+ return ret;
|
||||||
|
|
||||||
|
mutex_lock(&local->iflist_mtx);
|
||||||
|
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||||
|
- if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
|
||||||
|
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
|
||||||
|
+ !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
m = sdata->vif.addr;
|
||||||
|
@@ -204,12 +208,17 @@ static int ieee80211_change_mac(struct n
|
||||||
|
{
|
||||||
|
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
|
||||||
|
struct sockaddr *sa = addr;
|
||||||
|
+ bool check_dup = true;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (ieee80211_sdata_running(sdata))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
- ret = ieee80211_verify_mac(sdata->local, sa->sa_data);
|
||||||
|
+ if (sdata->vif.type == NL80211_IFTYPE_MONITOR &&
|
||||||
|
+ !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
|
||||||
|
+ check_dup = false;
|
||||||
|
+
|
||||||
|
+ ret = ieee80211_verify_mac(sdata->local, sa->sa_data, check_dup);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
@@ -450,7 +459,6 @@ int ieee80211_do_open(struct wireless_de
|
||||||
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
||||||
struct net_device *dev = wdev->netdev;
|
struct net_device *dev = wdev->netdev;
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
|
@ -1304,7 +1380,7 @@
|
||||||
u32 changed = 0;
|
u32 changed = 0;
|
||||||
int res;
|
int res;
|
||||||
u32 hw_reconf_flags = 0;
|
u32 hw_reconf_flags = 0;
|
||||||
@@ -474,6 +473,9 @@ int ieee80211_do_open(struct wireless_de
|
@@ -474,6 +482,9 @@ int ieee80211_do_open(struct wireless_de
|
||||||
master->control_port_protocol;
|
master->control_port_protocol;
|
||||||
sdata->control_port_no_encrypt =
|
sdata->control_port_no_encrypt =
|
||||||
master->control_port_no_encrypt;
|
master->control_port_no_encrypt;
|
||||||
|
@ -1314,7 +1390,20 @@
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NL80211_IFTYPE_AP:
|
case NL80211_IFTYPE_AP:
|
||||||
@@ -609,30 +611,8 @@ int ieee80211_do_open(struct wireless_de
|
@@ -538,7 +549,11 @@ int ieee80211_do_open(struct wireless_de
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (local->monitors == 0 && local->open_count == 0) {
|
||||||
|
+ if (sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE) {
|
||||||
|
+ res = drv_add_interface(local, sdata);
|
||||||
|
+ if (res)
|
||||||
|
+ goto err_stop;
|
||||||
|
+ } else if (local->monitors == 0 && local->open_count == 0) {
|
||||||
|
res = ieee80211_add_virtual_monitor(local);
|
||||||
|
if (res)
|
||||||
|
goto err_stop;
|
||||||
|
@@ -609,30 +624,8 @@ int ieee80211_do_open(struct wireless_de
|
||||||
|
|
||||||
set_bit(SDATA_STATE_RUNNING, &sdata->state);
|
set_bit(SDATA_STATE_RUNNING, &sdata->state);
|
||||||
|
|
||||||
|
@ -1346,7 +1435,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set_multicast_list will be invoked by the networking core
|
* set_multicast_list will be invoked by the networking core
|
||||||
@@ -653,7 +633,11 @@ int ieee80211_do_open(struct wireless_de
|
@@ -653,7 +646,11 @@ int ieee80211_do_open(struct wireless_de
|
||||||
|
|
||||||
ieee80211_recalc_ps(local, -1);
|
ieee80211_recalc_ps(local, -1);
|
||||||
|
|
||||||
|
@ -1359,7 +1448,29 @@
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
int n_acs = IEEE80211_NUM_ACS;
|
int n_acs = IEEE80211_NUM_ACS;
|
||||||
int ac;
|
int ac;
|
||||||
@@ -1092,6 +1076,74 @@ static void ieee80211_if_setup(struct ne
|
@@ -916,7 +913,11 @@ static void ieee80211_do_stop(struct iee
|
||||||
|
mutex_lock(&local->mtx);
|
||||||
|
ieee80211_recalc_idle(local);
|
||||||
|
mutex_unlock(&local->mtx);
|
||||||
|
- break;
|
||||||
|
+
|
||||||
|
+ if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
|
||||||
|
+ break;
|
||||||
|
+
|
||||||
|
+ /* fall through */
|
||||||
|
default:
|
||||||
|
if (going_down)
|
||||||
|
drv_remove_interface(local, sdata);
|
||||||
|
@@ -1075,7 +1076,7 @@ static const struct net_device_ops ieee8
|
||||||
|
.ndo_start_xmit = ieee80211_monitor_start_xmit,
|
||||||
|
.ndo_set_rx_mode = ieee80211_set_multicast_list,
|
||||||
|
.ndo_change_mtu = ieee80211_change_mtu,
|
||||||
|
- .ndo_set_mac_address = eth_mac_addr,
|
||||||
|
+ .ndo_set_mac_address = ieee80211_change_mac,
|
||||||
|
.ndo_select_queue = ieee80211_monitor_select_queue,
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -1092,6 +1093,74 @@ static void ieee80211_if_setup(struct ne
|
||||||
dev->destructor = free_netdev;
|
dev->destructor = free_netdev;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1434,7 +1545,7 @@
|
||||||
static void ieee80211_iface_work(struct work_struct *work)
|
static void ieee80211_iface_work(struct work_struct *work)
|
||||||
{
|
{
|
||||||
struct ieee80211_sub_if_data *sdata =
|
struct ieee80211_sub_if_data *sdata =
|
||||||
@@ -1196,6 +1248,9 @@ static void ieee80211_iface_work(struct
|
@@ -1196,6 +1265,9 @@ static void ieee80211_iface_work(struct
|
||||||
break;
|
break;
|
||||||
ieee80211_mesh_rx_queued_mgmt(sdata, skb);
|
ieee80211_mesh_rx_queued_mgmt(sdata, skb);
|
||||||
break;
|
break;
|
||||||
|
@ -1444,7 +1555,7 @@
|
||||||
default:
|
default:
|
||||||
WARN(1, "frame for unexpected interface type");
|
WARN(1, "frame for unexpected interface type");
|
||||||
break;
|
break;
|
||||||
@@ -1718,6 +1773,15 @@ void ieee80211_remove_interfaces(struct
|
@@ -1718,6 +1790,15 @@ void ieee80211_remove_interfaces(struct
|
||||||
|
|
||||||
ASSERT_RTNL();
|
ASSERT_RTNL();
|
||||||
|
|
||||||
|
@ -3608,7 +3719,27 @@
|
||||||
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -660,7 +661,7 @@ void ieee80211_queue_delayed_work(struct
|
@@ -559,6 +560,9 @@ void ieee80211_iterate_active_interfaces
|
||||||
|
list_for_each_entry(sdata, &local->interfaces, list) {
|
||||||
|
switch (sdata->vif.type) {
|
||||||
|
case NL80211_IFTYPE_MONITOR:
|
||||||
|
+ if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
|
||||||
|
+ continue;
|
||||||
|
+ break;
|
||||||
|
case NL80211_IFTYPE_AP_VLAN:
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
@@ -597,6 +601,9 @@ void ieee80211_iterate_active_interfaces
|
||||||
|
list_for_each_entry_rcu(sdata, &local->interfaces, list) {
|
||||||
|
switch (sdata->vif.type) {
|
||||||
|
case NL80211_IFTYPE_MONITOR:
|
||||||
|
+ if (!(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))
|
||||||
|
+ continue;
|
||||||
|
+ break;
|
||||||
|
case NL80211_IFTYPE_AP_VLAN:
|
||||||
|
continue;
|
||||||
|
default:
|
||||||
|
@@ -660,7 +667,7 @@ void ieee80211_queue_delayed_work(struct
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(ieee80211_queue_delayed_work);
|
EXPORT_SYMBOL(ieee80211_queue_delayed_work);
|
||||||
|
|
||||||
|
@ -3617,7 +3748,7 @@
|
||||||
struct ieee802_11_elems *elems,
|
struct ieee802_11_elems *elems,
|
||||||
u64 filter, u32 crc)
|
u64 filter, u32 crc)
|
||||||
{
|
{
|
||||||
@@ -668,6 +669,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start
|
@@ -668,6 +675,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start
|
||||||
u8 *pos = start;
|
u8 *pos = start;
|
||||||
bool calc_crc = filter != 0;
|
bool calc_crc = filter != 0;
|
||||||
DECLARE_BITMAP(seen_elems, 256);
|
DECLARE_BITMAP(seen_elems, 256);
|
||||||
|
@ -3625,7 +3756,7 @@
|
||||||
|
|
||||||
bitmap_zero(seen_elems, 256);
|
bitmap_zero(seen_elems, 256);
|
||||||
memset(elems, 0, sizeof(*elems));
|
memset(elems, 0, sizeof(*elems));
|
||||||
@@ -715,6 +717,12 @@ u32 ieee802_11_parse_elems_crc(u8 *start
|
@@ -715,6 +723,12 @@ u32 ieee802_11_parse_elems_crc(u8 *start
|
||||||
case WLAN_EID_COUNTRY:
|
case WLAN_EID_COUNTRY:
|
||||||
case WLAN_EID_PWR_CONSTRAINT:
|
case WLAN_EID_PWR_CONSTRAINT:
|
||||||
case WLAN_EID_TIMEOUT_INTERVAL:
|
case WLAN_EID_TIMEOUT_INTERVAL:
|
||||||
|
@ -3638,7 +3769,7 @@
|
||||||
if (test_bit(id, seen_elems)) {
|
if (test_bit(id, seen_elems)) {
|
||||||
elems->parse_error = true;
|
elems->parse_error = true;
|
||||||
left -= elen;
|
left -= elen;
|
||||||
@@ -862,6 +870,48 @@ u32 ieee802_11_parse_elems_crc(u8 *start
|
@@ -862,6 +876,48 @@ u32 ieee802_11_parse_elems_crc(u8 *start
|
||||||
}
|
}
|
||||||
elems->ch_switch_ie = (void *)pos;
|
elems->ch_switch_ie = (void *)pos;
|
||||||
break;
|
break;
|
||||||
|
@ -3749,6 +3880,31 @@
|
||||||
|
|
||||||
/* keep last */
|
/* keep last */
|
||||||
__NL80211_STA_INFO_AFTER_LAST,
|
__NL80211_STA_INFO_AFTER_LAST,
|
||||||
|
@@ -2395,6 +2401,8 @@ enum nl80211_survey_info {
|
||||||
|
* @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering
|
||||||
|
* @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing.
|
||||||
|
* overrides all other flags.
|
||||||
|
+ * @NL80211_MNTR_FLAG_ACTIVE: use the configured MAC address
|
||||||
|
+ * and ACK incoming unicast packets.
|
||||||
|
*
|
||||||
|
* @__NL80211_MNTR_FLAG_AFTER_LAST: internal use
|
||||||
|
* @NL80211_MNTR_FLAG_MAX: highest possible monitor flag
|
||||||
|
@@ -2406,6 +2414,7 @@ enum nl80211_mntr_flags {
|
||||||
|
NL80211_MNTR_FLAG_CONTROL,
|
||||||
|
NL80211_MNTR_FLAG_OTHER_BSS,
|
||||||
|
NL80211_MNTR_FLAG_COOK_FRAMES,
|
||||||
|
+ NL80211_MNTR_FLAG_ACTIVE,
|
||||||
|
|
||||||
|
/* keep last */
|
||||||
|
__NL80211_MNTR_FLAG_AFTER_LAST,
|
||||||
|
@@ -3557,6 +3566,7 @@ enum nl80211_feature_flags {
|
||||||
|
NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14,
|
||||||
|
NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 15,
|
||||||
|
NL80211_FEATURE_USERSPACE_MPM = 1 << 16,
|
||||||
|
+ NL80211_FEATURE_ACTIVE_MONITOR = 1 << 17,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
--- a/net/mac80211/sta_info.c
|
--- a/net/mac80211/sta_info.c
|
||||||
+++ b/net/mac80211/sta_info.c
|
+++ b/net/mac80211/sta_info.c
|
||||||
@@ -358,6 +358,8 @@ struct sta_info *sta_info_alloc(struct i
|
@@ -358,6 +358,8 @@ struct sta_info *sta_info_alloc(struct i
|
||||||
|
@ -3762,7 +3918,38 @@
|
||||||
kfree(sta);
|
kfree(sta);
|
||||||
--- a/net/wireless/nl80211.c
|
--- a/net/wireless/nl80211.c
|
||||||
+++ b/net/wireless/nl80211.c
|
+++ b/net/wireless/nl80211.c
|
||||||
@@ -3367,6 +3367,32 @@ static bool nl80211_put_sta_rate(struct
|
@@ -2270,6 +2270,7 @@ static const struct nla_policy mntr_flag
|
||||||
|
[NL80211_MNTR_FLAG_CONTROL] = { .type = NLA_FLAG },
|
||||||
|
[NL80211_MNTR_FLAG_OTHER_BSS] = { .type = NLA_FLAG },
|
||||||
|
[NL80211_MNTR_FLAG_COOK_FRAMES] = { .type = NLA_FLAG },
|
||||||
|
+ [NL80211_MNTR_FLAG_ACTIVE] = { .type = NLA_FLAG },
|
||||||
|
};
|
||||||
|
|
||||||
|
static int parse_monitor_flags(struct nlattr *nla, u32 *mntrflags)
|
||||||
|
@@ -2381,6 +2382,10 @@ static int nl80211_set_interface(struct
|
||||||
|
change = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if ((*flags & NL80211_MNTR_FLAG_ACTIVE) &&
|
||||||
|
+ !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
|
||||||
|
+ return -EOPNOTSUPP;
|
||||||
|
+
|
||||||
|
if (change)
|
||||||
|
err = cfg80211_change_iface(rdev, dev, ntype, flags, ¶ms);
|
||||||
|
else
|
||||||
|
@@ -2438,6 +2443,11 @@ static int nl80211_new_interface(struct
|
||||||
|
err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ?
|
||||||
|
info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL,
|
||||||
|
&flags);
|
||||||
|
+
|
||||||
|
+ if (!err && (flags & NL80211_MNTR_FLAG_ACTIVE) &&
|
||||||
|
+ !(rdev->wiphy.features & NL80211_FEATURE_ACTIVE_MONITOR))
|
||||||
|
+ return -EOPNOTSUPP;
|
||||||
|
+
|
||||||
|
wdev = rdev_add_virtual_intf(rdev,
|
||||||
|
nla_data(info->attrs[NL80211_ATTR_IFNAME]),
|
||||||
|
type, err ? NULL : &flags, ¶ms);
|
||||||
|
@@ -3367,6 +3377,32 @@ static bool nl80211_put_sta_rate(struct
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3795,7 +3982,7 @@
|
||||||
static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq,
|
||||||
int flags,
|
int flags,
|
||||||
struct cfg80211_registered_device *rdev,
|
struct cfg80211_registered_device *rdev,
|
||||||
@@ -3402,7 +3428,7 @@ static int nl80211_send_station(struct s
|
@@ -3402,7 +3438,7 @@ static int nl80211_send_station(struct s
|
||||||
(u32)sinfo->rx_bytes))
|
(u32)sinfo->rx_bytes))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
if ((sinfo->filled & (STATION_INFO_TX_BYTES |
|
if ((sinfo->filled & (STATION_INFO_TX_BYTES |
|
||||||
|
@ -3804,7 +3991,7 @@
|
||||||
nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
|
nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES,
|
||||||
(u32)sinfo->tx_bytes))
|
(u32)sinfo->tx_bytes))
|
||||||
goto nla_put_failure;
|
goto nla_put_failure;
|
||||||
@@ -3438,6 +3464,18 @@ static int nl80211_send_station(struct s
|
@@ -3438,6 +3474,18 @@ static int nl80211_send_station(struct s
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3835,6 +4022,15 @@
|
||||||
|
|
||||||
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
|
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT)
|
||||||
hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
|
hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
|
||||||
|
@@ -776,6 +777,8 @@ void ath9k_set_hw_capab(struct ath_softc
|
||||||
|
if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt)
|
||||||
|
hw->flags |= IEEE80211_HW_MFP_CAPABLE;
|
||||||
|
|
||||||
|
+ hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
|
||||||
|
+
|
||||||
|
hw->wiphy->interface_modes =
|
||||||
|
BIT(NL80211_IFTYPE_P2P_GO) |
|
||||||
|
BIT(NL80211_IFTYPE_P2P_CLIENT) |
|
||||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||||
@@ -125,24 +125,6 @@ static void ath_tx_queue_tid(struct ath_
|
@@ -125,24 +125,6 @@ static void ath_tx_queue_tid(struct ath_
|
||||||
|
@ -4362,3 +4558,15 @@
|
||||||
REG_WRITE(ah, AR_DMISC(q),
|
REG_WRITE(ah, AR_DMISC(q),
|
||||||
AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1);
|
AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1);
|
||||||
else
|
else
|
||||||
|
--- a/net/mac80211/driver-ops.h
|
||||||
|
+++ b/net/mac80211/driver-ops.h
|
||||||
|
@@ -146,7 +146,8 @@ static inline int drv_add_interface(stru
|
||||||
|
|
||||||
|
if (WARN_ON(sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
|
||||||
|
(sdata->vif.type == NL80211_IFTYPE_MONITOR &&
|
||||||
|
- !(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))))
|
||||||
|
+ !(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF) &&
|
||||||
|
+ !(sdata->u.mntr_flags & MONITOR_FLAG_ACTIVE))))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
trace_drv_add_interface(local, sdata);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
--- a/net/mac80211/cfg.c
|
--- a/net/mac80211/cfg.c
|
||||||
+++ b/net/mac80211/cfg.c
|
+++ b/net/mac80211/cfg.c
|
||||||
@@ -2078,7 +2078,7 @@ static int ieee80211_scan(struct wiphy *
|
@@ -2081,7 +2081,7 @@ static int ieee80211_scan(struct wiphy *
|
||||||
* the frames sent while scanning on other channel will be
|
* the frames sent while scanning on other channel will be
|
||||||
* lost)
|
* lost)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||||
@@ -986,23 +986,23 @@ static int __init ath9k_init(void)
|
@@ -988,23 +988,23 @@ static int __init ath9k_init(void)
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
u8 uapsd_queues;
|
u8 uapsd_queues;
|
||||||
--- a/net/mac80211/cfg.c
|
--- a/net/mac80211/cfg.c
|
||||||
+++ b/net/mac80211/cfg.c
|
+++ b/net/mac80211/cfg.c
|
||||||
@@ -2259,7 +2259,9 @@ static int ieee80211_get_tx_power(struct
|
@@ -2262,7 +2262,9 @@ static int ieee80211_get_tx_power(struct
|
||||||
struct ieee80211_local *local = wiphy_priv(wiphy);
|
struct ieee80211_local *local = wiphy_priv(wiphy);
|
||||||
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
u32 tx_ant, rx_ant;
|
u32 tx_ant, rx_ant;
|
||||||
--- a/net/mac80211/cfg.c
|
--- a/net/mac80211/cfg.c
|
||||||
+++ b/net/mac80211/cfg.c
|
+++ b/net/mac80211/cfg.c
|
||||||
@@ -2269,6 +2269,19 @@ static int ieee80211_get_tx_power(struct
|
@@ -2272,6 +2272,19 @@ static int ieee80211_get_tx_power(struct
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +92,7 @@
|
||||||
static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
|
static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
|
||||||
const u8 *addr)
|
const u8 *addr)
|
||||||
{
|
{
|
||||||
@@ -3459,6 +3472,7 @@ struct cfg80211_ops mac80211_config_ops
|
@@ -3462,6 +3475,7 @@ struct cfg80211_ops mac80211_config_ops
|
||||||
.set_wiphy_params = ieee80211_set_wiphy_params,
|
.set_wiphy_params = ieee80211_set_wiphy_params,
|
||||||
.set_tx_power = ieee80211_set_tx_power,
|
.set_tx_power = ieee80211_set_tx_power,
|
||||||
.get_tx_power = ieee80211_get_tx_power,
|
.get_tx_power = ieee80211_get_tx_power,
|
||||||
|
@ -102,7 +102,7 @@
|
||||||
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
|
CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
|
||||||
--- a/include/net/cfg80211.h
|
--- a/include/net/cfg80211.h
|
||||||
+++ b/include/net/cfg80211.h
|
+++ b/include/net/cfg80211.h
|
||||||
@@ -1921,6 +1921,7 @@ struct cfg80211_update_ft_ies_params {
|
@@ -1922,6 +1922,7 @@ struct cfg80211_update_ft_ies_params {
|
||||||
* (as advertised by the nl80211 feature flag.)
|
* (as advertised by the nl80211 feature flag.)
|
||||||
* @get_tx_power: store the current TX power into the dbm variable;
|
* @get_tx_power: store the current TX power into the dbm variable;
|
||||||
* return 0 if successful
|
* return 0 if successful
|
||||||
|
@ -110,7 +110,7 @@
|
||||||
*
|
*
|
||||||
* @set_wds_peer: set the WDS peer for a WDS interface
|
* @set_wds_peer: set the WDS peer for a WDS interface
|
||||||
*
|
*
|
||||||
@@ -2134,6 +2135,7 @@ struct cfg80211_ops {
|
@@ -2135,6 +2136,7 @@ struct cfg80211_ops {
|
||||||
enum nl80211_tx_power_setting type, int mbm);
|
enum nl80211_tx_power_setting type, int mbm);
|
||||||
int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
|
int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||||
int *dbm);
|
int *dbm);
|
||||||
|
|
|
@ -162,7 +162,7 @@
|
||||||
void ath_fill_led_pin(struct ath_softc *sc)
|
void ath_fill_led_pin(struct ath_softc *sc)
|
||||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||||
@@ -891,7 +891,7 @@ int ath9k_init_device(u16 devid, struct
|
@@ -893,7 +893,7 @@ int ath9k_init_device(u16 devid, struct
|
||||||
|
|
||||||
#ifdef CONFIG_MAC80211_LEDS
|
#ifdef CONFIG_MAC80211_LEDS
|
||||||
/* must be initialized before ieee80211_register_hw */
|
/* must be initialized before ieee80211_register_hw */
|
||||||
|
|
|
@ -30,3 +30,11 @@
|
||||||
|
|
||||||
/* keep last */
|
/* keep last */
|
||||||
__NL80211_STA_INFO_AFTER_LAST,
|
__NL80211_STA_INFO_AFTER_LAST,
|
||||||
|
@@ -2424,6 +2429,7 @@ enum nl80211_mntr_flags {
|
||||||
|
NL80211_MNTR_FLAG_CONTROL,
|
||||||
|
NL80211_MNTR_FLAG_OTHER_BSS,
|
||||||
|
NL80211_MNTR_FLAG_COOK_FRAMES,
|
||||||
|
+ NL80211_MNTR_FLAG_ACTIVE,
|
||||||
|
|
||||||
|
/* keep last */
|
||||||
|
__NL80211_MNTR_FLAG_AFTER_LAST,
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
--- a/interface.c
|
||||||
|
+++ b/interface.c
|
||||||
|
@@ -16,7 +16,8 @@
|
||||||
|
"fcsfail: show frames with FCS errors\n"\
|
||||||
|
"control: show control frames\n"\
|
||||||
|
"otherbss: show frames from other BSSes\n"\
|
||||||
|
- "cook: use cooked mode"
|
||||||
|
+ "cook: use cooked mode\n"\
|
||||||
|
+ "active: use active mode (ACK incoming unicast packets)"
|
||||||
|
|
||||||
|
SECTION(interface);
|
||||||
|
|
||||||
|
@@ -27,6 +28,7 @@ static char *mntr_flags[NL80211_MNTR_FLA
|
||||||
|
"control",
|
||||||
|
"otherbss",
|
||||||
|
"cook",
|
||||||
|
+ "active",
|
||||||
|
};
|
||||||
|
|
||||||
|
static int parse_mntr_flags(int *_argc, char ***_argv,
|
Loading…
Reference in New Issue