mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 14:53:58 -04:00
wifi: cfg80211: add support for NAN data interface
This new interface type represents a NAN data interface (NDI). It is used for data communication with NAN peers. Note that the existing NL80211_IFTYPE_NAN interface, which is the NAN Management Interface (NMI), is used for management communication. An NDI interface is started when a new NAN data path is about to be established, and is stopped after the NAN data path is terminated. - An NDI interface can only be started if the NMI is running, and NAN is started. - Before the NMI is stopped, the NDI interfaces will be stopped. Add the new interface type, handle add/remove operations for it, and makes sure of the conditions above. Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20260219114327.0d681335c2e2.I92973483e927820ae2297853c141842fdb262747@changeid Link: https://patch.msgid.link/20260318123926.206536-4-miriam.rachel.korenblit@intel.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
committed by
Johannes Berg
parent
763a5a580f
commit
0e8ec738a7
@@ -3980,6 +3980,27 @@ struct cfg80211_qos_map {
|
||||
struct cfg80211_dscp_range up[8];
|
||||
};
|
||||
|
||||
/**
|
||||
* DOC: Neighbor Awareness Networking (NAN)
|
||||
*
|
||||
* NAN uses two interface types:
|
||||
*
|
||||
* - %NL80211_IFTYPE_NAN: a non-netdev interface. This has two roles: (1) holds
|
||||
* the configuration of all NAN activities (DE parameters, synchronisation
|
||||
* parameters, local schedule, etc.), and (2) uses as the NAN Management
|
||||
* Interface (NMI), which is used for NAN management communication.
|
||||
*
|
||||
* - %NL80211_IFTYPE_NAN_DATA: The NAN Data Interface (NDI), used for data
|
||||
* communication with NAN peers.
|
||||
*
|
||||
* An NDI interface can only be started (IFF_UP) if the NMI one is running and
|
||||
* NAN is started. Before NAN is stopped, all associated NDI interfaces
|
||||
* must be stopped first.
|
||||
*
|
||||
* The local schedule specifies which channels the device is available on and
|
||||
* when. Must be cancelled before NAN is stopped.
|
||||
*/
|
||||
|
||||
/**
|
||||
* struct cfg80211_nan_band_config - NAN band specific configuration
|
||||
*
|
||||
|
||||
@@ -3749,6 +3749,9 @@ enum nl80211_attrs {
|
||||
* @NL80211_IFTYPE_OCB: Outside Context of a BSS
|
||||
* This mode corresponds to the MIB variable dot11OCBActivated=true
|
||||
* @NL80211_IFTYPE_NAN: NAN device interface type (not a netdev)
|
||||
* @NL80211_IFTYPE_NAN_DATA: NAN data interface type (netdev); NAN data
|
||||
* interfaces can only be brought up (IFF_UP) when a NAN interface
|
||||
* already exists and NAN has been started (using %NL80211_CMD_START_NAN).
|
||||
* @NL80211_IFTYPE_MAX: highest interface type number currently defined
|
||||
* @NUM_NL80211_IFTYPES: number of defined interface types
|
||||
*
|
||||
@@ -3770,6 +3773,7 @@ enum nl80211_iftype {
|
||||
NL80211_IFTYPE_P2P_DEVICE,
|
||||
NL80211_IFTYPE_OCB,
|
||||
NL80211_IFTYPE_NAN,
|
||||
NL80211_IFTYPE_NAN_DATA,
|
||||
|
||||
/* keep last */
|
||||
NUM_NL80211_IFTYPES,
|
||||
|
||||
@@ -718,6 +718,7 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
case NL80211_IFTYPE_OCB:
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
/* shouldn't happen */
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
|
||||
@@ -495,6 +495,7 @@ ieee80211_get_width_of_link(struct ieee80211_link_data *link)
|
||||
case NUM_NL80211_IFTYPES:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
WARN_ON_ONCE(1);
|
||||
break;
|
||||
}
|
||||
@@ -1458,6 +1459,7 @@ ieee80211_link_chanctx_reservation_complete(struct ieee80211_link_data *link)
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
case NL80211_IFTYPE_NAN:
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
case NUM_NL80211_IFTYPES:
|
||||
WARN_ON(1);
|
||||
break;
|
||||
|
||||
@@ -1368,6 +1368,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
case NL80211_IFTYPE_OCB:
|
||||
case NL80211_IFTYPE_NAN:
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
/* no special treatment */
|
||||
break;
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
@@ -1945,6 +1946,8 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
sdata->vif.bss_conf.bssid = sdata->vif.addr;
|
||||
break;
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
break;
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
case NL80211_IFTYPE_WDS:
|
||||
case NUM_NL80211_IFTYPES:
|
||||
|
||||
@@ -4607,6 +4607,8 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
|
||||
(ieee80211_is_public_action(hdr, skb->len) ||
|
||||
(ieee80211_is_auth(hdr->frame_control) &&
|
||||
ether_addr_equal(sdata->vif.addr, hdr->addr1)));
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2118,6 +2118,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
return res;
|
||||
}
|
||||
break;
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
|
||||
@@ -816,6 +816,7 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
break;
|
||||
case NL80211_IFTYPE_WDS:
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
@@ -939,6 +940,7 @@ bool cfg80211_beaconing_iface_active(struct wireless_dev *wdev)
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
/* Can NAN type be considered as beaconing interface? */
|
||||
case NL80211_IFTYPE_NAN:
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
break;
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
case NL80211_IFTYPE_WDS:
|
||||
|
||||
@@ -329,16 +329,21 @@ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
/*
|
||||
* Some netdev interfaces need to be closed before some non-netdev
|
||||
* ones, i.e. NAN_DATA interfaces need to be closed before the NAN
|
||||
* interface
|
||||
*/
|
||||
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
|
||||
if (wdev->netdev) {
|
||||
dev_close(wdev->netdev);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* otherwise, check iftype */
|
||||
|
||||
guard(wiphy)(wiphy);
|
||||
guard(wiphy)(wiphy);
|
||||
|
||||
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
|
||||
switch (wdev->iftype) {
|
||||
case NL80211_IFTYPE_P2P_DEVICE:
|
||||
cfg80211_stop_p2p_device(rdev, wdev);
|
||||
@@ -396,6 +401,8 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
|
||||
|
||||
list_for_each_entry_safe(wdev, tmp, &rdev->wiphy.wdev_list, list) {
|
||||
if (wdev->nl_owner_dead) {
|
||||
cfg80211_close_dependents(rdev, wdev);
|
||||
|
||||
if (wdev->netdev)
|
||||
dev_close(wdev->netdev);
|
||||
|
||||
@@ -406,6 +413,21 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
|
||||
}
|
||||
}
|
||||
|
||||
void cfg80211_close_dependents(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev)
|
||||
{
|
||||
ASSERT_RTNL();
|
||||
|
||||
if (wdev->iftype != NL80211_IFTYPE_NAN)
|
||||
return;
|
||||
|
||||
/* Close all NAN DATA interfaces */
|
||||
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
|
||||
if (wdev->iftype == NL80211_IFTYPE_NAN_DATA)
|
||||
dev_close(wdev->netdev);
|
||||
}
|
||||
}
|
||||
|
||||
static void cfg80211_destroy_iface_wk(struct work_struct *work)
|
||||
{
|
||||
struct cfg80211_registered_device *rdev;
|
||||
@@ -1419,9 +1441,8 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
|
||||
rdev->num_running_monitor_ifaces += num;
|
||||
}
|
||||
|
||||
void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev,
|
||||
int link_id)
|
||||
void cfg80211_leave_locked(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev, int link_id)
|
||||
{
|
||||
struct net_device *dev = wdev->netdev;
|
||||
struct cfg80211_sched_scan_request *pos, *tmp;
|
||||
@@ -1472,6 +1493,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
||||
break;
|
||||
case NL80211_IFTYPE_AP_VLAN:
|
||||
case NL80211_IFTYPE_MONITOR:
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
/* nothing to do */
|
||||
break;
|
||||
case NL80211_IFTYPE_UNSPECIFIED:
|
||||
@@ -1482,6 +1504,19 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
||||
}
|
||||
}
|
||||
|
||||
void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev, int link_id)
|
||||
{
|
||||
ASSERT_RTNL();
|
||||
|
||||
/* NAN_DATA interfaces must be closed before stopping NAN */
|
||||
cfg80211_close_dependents(rdev, wdev);
|
||||
|
||||
guard(wiphy)(&rdev->wiphy);
|
||||
|
||||
cfg80211_leave_locked(rdev, wdev, link_id);
|
||||
}
|
||||
|
||||
void cfg80211_stop_link(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
int link_id, gfp_t gfp)
|
||||
{
|
||||
@@ -1497,6 +1532,9 @@ void cfg80211_stop_link(struct wiphy *wiphy, struct wireless_dev *wdev,
|
||||
|
||||
trace_cfg80211_stop_link(wiphy, wdev, link_id);
|
||||
|
||||
if (wdev->iftype == NL80211_IFTYPE_NAN)
|
||||
return;
|
||||
|
||||
ev = kzalloc_obj(*ev, gfp);
|
||||
if (!ev)
|
||||
return;
|
||||
@@ -1647,10 +1685,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
||||
}
|
||||
break;
|
||||
case NETDEV_GOING_DOWN:
|
||||
scoped_guard(wiphy, &rdev->wiphy) {
|
||||
cfg80211_leave(rdev, wdev, -1);
|
||||
cfg80211_leave(rdev, wdev, -1);
|
||||
scoped_guard(wiphy, &rdev->wiphy)
|
||||
cfg80211_remove_links(wdev);
|
||||
}
|
||||
/* since we just did cfg80211_leave() nothing to do there */
|
||||
cancel_work_sync(&wdev->disconnect_wk);
|
||||
cancel_work_sync(&wdev->pmsr_free_wk);
|
||||
@@ -1731,6 +1768,23 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
|
||||
|
||||
if (rfkill_blocked(rdev->wiphy.rfkill))
|
||||
return notifier_from_errno(-ERFKILL);
|
||||
|
||||
/* NAN_DATA interfaces require a running NAN interface */
|
||||
if (wdev->iftype == NL80211_IFTYPE_NAN_DATA) {
|
||||
struct wireless_dev *iter;
|
||||
bool nan_started = false;
|
||||
|
||||
list_for_each_entry(iter, &rdev->wiphy.wdev_list, list) {
|
||||
if (iter->iftype == NL80211_IFTYPE_NAN &&
|
||||
wdev_running(iter)) {
|
||||
nan_started = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nan_started)
|
||||
return notifier_from_errno(-ENOLINK);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return NOTIFY_DONE;
|
||||
|
||||
@@ -318,6 +318,9 @@ void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy,
|
||||
|
||||
void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev);
|
||||
|
||||
void cfg80211_close_dependents(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev);
|
||||
|
||||
/* free object */
|
||||
void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
|
||||
|
||||
@@ -541,6 +544,9 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
|
||||
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
|
||||
enum nl80211_iftype iftype, int num);
|
||||
|
||||
void cfg80211_leave_locked(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev, int link_id);
|
||||
|
||||
void cfg80211_leave(struct cfg80211_registered_device *rdev,
|
||||
struct wireless_dev *wdev,
|
||||
int link_id);
|
||||
|
||||
@@ -1764,6 +1764,7 @@ static int nl80211_key_allowed(struct wireless_dev *wdev)
|
||||
return 0;
|
||||
return -ENOLINK;
|
||||
case NL80211_IFTYPE_NAN:
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
if (wiphy_ext_feature_isset(wdev->wiphy,
|
||||
NL80211_EXT_FEATURE_SECURE_NAN))
|
||||
return 0;
|
||||
@@ -4921,6 +4922,8 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
|
||||
else
|
||||
dev_close(wdev->netdev);
|
||||
|
||||
cfg80211_close_dependents(rdev, wdev);
|
||||
|
||||
mutex_lock(&rdev->wiphy.mtx);
|
||||
|
||||
return cfg80211_remove_virtual_intf(rdev, wdev);
|
||||
@@ -15964,6 +15967,10 @@ static int nl80211_stop_nan(struct sk_buff *skb, struct genl_info *info)
|
||||
if (wdev->iftype != NL80211_IFTYPE_NAN)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
cfg80211_close_dependents(rdev, wdev);
|
||||
|
||||
guard(wiphy)(&rdev->wiphy);
|
||||
|
||||
cfg80211_stop_nan(rdev, wdev);
|
||||
|
||||
return 0;
|
||||
@@ -18356,7 +18363,11 @@ nl80211_epcs_cfg(struct sk_buff *skb, struct genl_info *info)
|
||||
NL80211_FLAG_NEED_RTNL) \
|
||||
SELECTOR(__sel, WIPHY_CLEAR, \
|
||||
NL80211_FLAG_NEED_WIPHY | \
|
||||
NL80211_FLAG_CLEAR_SKB)
|
||||
NL80211_FLAG_CLEAR_SKB) \
|
||||
SELECTOR(__sel, WDEV_UP_RTNL_NOMTX, \
|
||||
NL80211_FLAG_NEED_WDEV_UP | \
|
||||
NL80211_FLAG_NO_WIPHY_MTX | \
|
||||
NL80211_FLAG_NEED_RTNL)
|
||||
|
||||
enum nl80211_internal_flags_selector {
|
||||
#define SELECTOR(_, name, value) NL80211_IFL_SEL_##name,
|
||||
@@ -19193,6 +19204,7 @@ static const struct genl_small_ops nl80211_small_ops[] = {
|
||||
.doit = nl80211_stop_nan,
|
||||
.flags = GENL_ADMIN_PERM,
|
||||
.internal_flags = IFLAGS(NL80211_FLAG_NEED_WDEV_UP |
|
||||
NL80211_FLAG_NO_WIPHY_MTX |
|
||||
NL80211_FLAG_NEED_RTNL),
|
||||
},
|
||||
{
|
||||
|
||||
@@ -2409,6 +2409,9 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||
continue;
|
||||
chandef = wdev->u.ocb.chandef;
|
||||
break;
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
/* NAN channels are checked in NL80211_IFTYPE_NAN interface */
|
||||
break;
|
||||
default:
|
||||
/* others not implemented for now */
|
||||
WARN_ON_ONCE(1);
|
||||
@@ -2445,11 +2448,14 @@ static void reg_leave_invalid_chans(struct wiphy *wiphy)
|
||||
struct wireless_dev *wdev;
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
|
||||
guard(wiphy)(wiphy);
|
||||
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
|
||||
bool valid;
|
||||
|
||||
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
|
||||
if (!reg_wdev_chan_valid(wiphy, wdev))
|
||||
scoped_guard(wiphy, wiphy)
|
||||
valid = reg_wdev_chan_valid(wiphy, wdev);
|
||||
if (!valid)
|
||||
cfg80211_leave(rdev, wdev, -1);
|
||||
}
|
||||
}
|
||||
|
||||
static void reg_check_chans_work(struct work_struct *work)
|
||||
|
||||
@@ -102,25 +102,26 @@ static int wiphy_suspend(struct device *dev)
|
||||
if (!rdev->wiphy.registered)
|
||||
goto out_unlock_rtnl;
|
||||
|
||||
wiphy_lock(&rdev->wiphy);
|
||||
if (rdev->wiphy.wowlan_config) {
|
||||
cfg80211_process_wiphy_works(rdev, NULL);
|
||||
if (rdev->ops->suspend)
|
||||
ret = rdev_suspend(rdev, rdev->wiphy.wowlan_config);
|
||||
if (ret <= 0)
|
||||
goto out_unlock_wiphy;
|
||||
scoped_guard(wiphy, &rdev->wiphy) {
|
||||
cfg80211_process_wiphy_works(rdev, NULL);
|
||||
if (rdev->ops->suspend)
|
||||
ret = rdev_suspend(rdev,
|
||||
rdev->wiphy.wowlan_config);
|
||||
if (ret <= 0)
|
||||
goto out_unlock_rtnl;
|
||||
}
|
||||
}
|
||||
|
||||
/* Driver refused to configure wowlan (ret = 1) or no wowlan */
|
||||
|
||||
cfg80211_leave_all(rdev);
|
||||
cfg80211_process_rdev_events(rdev);
|
||||
cfg80211_process_wiphy_works(rdev, NULL);
|
||||
if (rdev->ops->suspend)
|
||||
ret = rdev_suspend(rdev, NULL);
|
||||
|
||||
out_unlock_wiphy:
|
||||
wiphy_unlock(&rdev->wiphy);
|
||||
scoped_guard(wiphy, &rdev->wiphy) {
|
||||
cfg80211_process_rdev_events(rdev);
|
||||
cfg80211_process_wiphy_works(rdev, NULL);
|
||||
if (rdev->ops->suspend)
|
||||
ret = rdev_suspend(rdev, NULL);
|
||||
}
|
||||
out_unlock_rtnl:
|
||||
if (ret == 0)
|
||||
rdev->suspended = true;
|
||||
|
||||
@@ -1144,8 +1144,15 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
|
||||
ev->ij.channel);
|
||||
break;
|
||||
case EVENT_STOPPED:
|
||||
cfg80211_leave(wiphy_to_rdev(wdev->wiphy), wdev,
|
||||
ev->link_id);
|
||||
/*
|
||||
* for NAN interfaces cfg80211_leave must be called but
|
||||
* locking here doesn't allow this.
|
||||
*/
|
||||
if (WARN_ON(wdev->iftype == NL80211_IFTYPE_NAN))
|
||||
break;
|
||||
|
||||
cfg80211_leave_locked(wiphy_to_rdev(wdev->wiphy), wdev,
|
||||
ev->link_id);
|
||||
break;
|
||||
case EVENT_PORT_AUTHORIZED:
|
||||
__cfg80211_port_authorized(wdev, ev->pa.peer_addr,
|
||||
@@ -1184,6 +1191,13 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||||
if (otype == NL80211_IFTYPE_AP_VLAN)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/*
|
||||
* for NAN interfaces cfg80211_leave must be called for leaving,
|
||||
* but locking here doesn't allow this.
|
||||
*/
|
||||
if (otype == NL80211_IFTYPE_NAN)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
/* cannot change into P2P device or NAN */
|
||||
if (ntype == NL80211_IFTYPE_P2P_DEVICE ||
|
||||
ntype == NL80211_IFTYPE_NAN)
|
||||
@@ -1204,7 +1218,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||||
dev->ieee80211_ptr->use_4addr = false;
|
||||
rdev_set_qos_map(rdev, dev, NULL);
|
||||
|
||||
cfg80211_leave(rdev, dev->ieee80211_ptr, -1);
|
||||
cfg80211_leave_locked(rdev, dev->ieee80211_ptr, -1);
|
||||
|
||||
cfg80211_process_rdev_events(rdev);
|
||||
cfg80211_mlme_purge_registrations(dev->ieee80211_ptr);
|
||||
@@ -1232,6 +1246,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
|
||||
case NL80211_IFTYPE_OCB:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
case NL80211_IFTYPE_NAN_DATA:
|
||||
dev->priv_flags |= IFF_DONT_BRIDGE;
|
||||
break;
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
|
||||
Reference in New Issue
Block a user