Skip to content

Commit

Permalink
mac80211: iterate the virtual monitor interface
Browse files Browse the repository at this point in the history
If the virtual monitor interface is requested
by the driver, it should also be iterated over
when the driver wants to iterate all active
interfaces.

To allow that protect it with the iflist_mtx.

Change-Id: I58ac5de2f4ce93d12c5a98ecd2859f60158d5d69
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Johannes Berg committed Jul 12, 2012
1 parent 8e95ea4 commit 685fb72
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 10 deletions.
29 changes: 19 additions & 10 deletions net/mac80211/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -334,17 +334,21 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)
int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;
int ret;
int ret = 0;

if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
return 0;

mutex_lock(&local->iflist_mtx);

if (local->monitor_sdata)
return 0;
goto out_unlock;

sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL);
if (!sdata)
return -ENOMEM;
if (!sdata) {
ret = -ENOMEM;
goto out_unlock;
}

/* set up data */
sdata->local = local;
Expand All @@ -358,18 +362,19 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local)
if (WARN_ON(ret)) {
/* ok .. stupid driver, it asked for this! */
kfree(sdata);
return ret;
goto out_unlock;
}

ret = ieee80211_check_queues(sdata);
if (ret) {
kfree(sdata);
return ret;
goto out_unlock;
}

rcu_assign_pointer(local->monitor_sdata, sdata);

return 0;
out_unlock:
mutex_unlock(&local->iflist_mtx);
return ret;
}

void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
Expand All @@ -379,17 +384,21 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))
return;

sdata = rtnl_dereference(local->monitor_sdata);
mutex_lock(&local->iflist_mtx);

sdata = rcu_dereference_protected(local->monitor_sdata,
lockdep_is_held(&local->iflist_mtx));
if (!sdata)
return;
goto out_unlock;

rcu_assign_pointer(local->monitor_sdata, NULL);
synchronize_net();

drv_remove_interface(local, sdata);

kfree(sdata);
out_unlock:
mutex_unlock(&local->iflist_mtx);
}

/*
Expand Down
9 changes: 9 additions & 0 deletions net/mac80211/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,11 @@ void ieee80211_iterate_active_interfaces(
&sdata->vif);
}

sdata = rcu_dereference_protected(local->monitor_sdata,
lockdep_is_held(&local->iflist_mtx));
if (sdata)
iterator(data, sdata->vif.addr, &sdata->vif);

mutex_unlock(&local->iflist_mtx);
}
EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);
Expand Down Expand Up @@ -557,6 +562,10 @@ void ieee80211_iterate_active_interfaces_atomic(
&sdata->vif);
}

sdata = rcu_dereference(local->monitor_sdata);
if (sdata)
iterator(data, sdata->vif.addr, &sdata->vif);

rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
Expand Down

0 comments on commit 685fb72

Please sign in to comment.