Commit 1f22cf13 authored by David S. Miller's avatar David S. Miller
Browse files

Merge tag 'mac80211-for-net-2021-07-23' of...

Merge tag 'mac80211-for-net-2021-07-23' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211

Couple of fixes:
 * fix aggregation on mesh
 * fix late enabling of 4-addr mode
 * leave monitor SKBs with some headroom
 * limit band information for old applications
 * fix virt-wifi WARN_ON
 * fix memory leak in cfg80211 BSS list maintenance
parents 15bbf8bb f9a5c358
Loading
Loading
Loading
Loading
+32 −20
Original line number Diff line number Diff line
@@ -136,6 +136,29 @@ static struct ieee80211_supported_band band_5ghz = {
/* Assigned at module init. Guaranteed locally-administered and unicast. */
static u8 fake_router_bssid[ETH_ALEN] __ro_after_init = {};

static void virt_wifi_inform_bss(struct wiphy *wiphy)
{
	u64 tsf = div_u64(ktime_get_boottime_ns(), 1000);
	struct cfg80211_bss *informed_bss;
	static const struct {
		u8 tag;
		u8 len;
		u8 ssid[8];
	} __packed ssid = {
		.tag = WLAN_EID_SSID,
		.len = 8,
		.ssid = "VirtWifi",
	};

	informed_bss = cfg80211_inform_bss(wiphy, &channel_5ghz,
					   CFG80211_BSS_FTYPE_PRESP,
					   fake_router_bssid, tsf,
					   WLAN_CAPABILITY_ESS, 0,
					   (void *)&ssid, sizeof(ssid),
					   DBM_TO_MBM(-50), GFP_KERNEL);
	cfg80211_put_bss(wiphy, informed_bss);
}

/* Called with the rtnl lock held. */
static int virt_wifi_scan(struct wiphy *wiphy,
			  struct cfg80211_scan_request *request)
@@ -156,28 +179,13 @@ static int virt_wifi_scan(struct wiphy *wiphy,
/* Acquires and releases the rdev BSS lock. */
static void virt_wifi_scan_result(struct work_struct *work)
{
	struct {
		u8 tag;
		u8 len;
		u8 ssid[8];
	} __packed ssid = {
		.tag = WLAN_EID_SSID, .len = 8, .ssid = "VirtWifi",
	};
	struct cfg80211_bss *informed_bss;
	struct virt_wifi_wiphy_priv *priv =
		container_of(work, struct virt_wifi_wiphy_priv,
			     scan_result.work);
	struct wiphy *wiphy = priv_to_wiphy(priv);
	struct cfg80211_scan_info scan_info = { .aborted = false };
	u64 tsf = div_u64(ktime_get_boottime_ns(), 1000);

	informed_bss = cfg80211_inform_bss(wiphy, &channel_5ghz,
					   CFG80211_BSS_FTYPE_PRESP,
					   fake_router_bssid, tsf,
					   WLAN_CAPABILITY_ESS, 0,
					   (void *)&ssid, sizeof(ssid),
					   DBM_TO_MBM(-50), GFP_KERNEL);
	cfg80211_put_bss(wiphy, informed_bss);
	virt_wifi_inform_bss(wiphy);

	/* Schedules work which acquires and releases the rtnl lock. */
	cfg80211_scan_done(priv->scan_request, &scan_info);
@@ -225,10 +233,12 @@ static int virt_wifi_connect(struct wiphy *wiphy, struct net_device *netdev,
	if (!could_schedule)
		return -EBUSY;

	if (sme->bssid)
	if (sme->bssid) {
		ether_addr_copy(priv->connect_requested_bss, sme->bssid);
	else
	} else {
		virt_wifi_inform_bss(wiphy);
		eth_zero_addr(priv->connect_requested_bss);
	}

	wiphy_debug(wiphy, "connect\n");

@@ -241,11 +251,13 @@ static void virt_wifi_connect_complete(struct work_struct *work)
	struct virt_wifi_netdev_priv *priv =
		container_of(work, struct virt_wifi_netdev_priv, connect.work);
	u8 *requested_bss = priv->connect_requested_bss;
	bool has_addr = !is_zero_ether_addr(requested_bss);
	bool right_addr = ether_addr_equal(requested_bss, fake_router_bssid);
	u16 status = WLAN_STATUS_SUCCESS;

	if (!priv->is_up || (has_addr && !right_addr))
	if (is_zero_ether_addr(requested_bss))
		requested_bss = NULL;

	if (!priv->is_up || (requested_bss && !right_addr))
		status = WLAN_STATUS_UNSPECIFIED_FAILURE;
	else
		priv->is_connected = true;
+19 −0
Original line number Diff line number Diff line
@@ -152,6 +152,8 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
				  struct vif_params *params)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_local *local = sdata->local;
	struct sta_info *sta;
	int ret;

	ret = ieee80211_if_change_type(sdata, type);
@@ -162,7 +164,24 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
		RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
		ieee80211_check_fast_rx_iface(sdata);
	} else if (type == NL80211_IFTYPE_STATION && params->use_4addr >= 0) {
		struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

		if (params->use_4addr == ifmgd->use_4addr)
			return 0;

		sdata->u.mgd.use_4addr = params->use_4addr;
		if (!ifmgd->associated)
			return 0;

		mutex_lock(&local->sta_mtx);
		sta = sta_info_get(sdata, ifmgd->bssid);
		if (sta)
			drv_sta_set_4addr(local, sdata, &sta->sta,
					  params->use_4addr);
		mutex_unlock(&local->sta_mtx);

		if (params->use_4addr)
			ieee80211_send_4addr_nullfunc(local, sdata);
	}

	if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
+2 −0
Original line number Diff line number Diff line
@@ -2201,6 +2201,8 @@ void ieee80211_dynamic_ps_timer(struct timer_list *t);
void ieee80211_send_nullfunc(struct ieee80211_local *local,
			     struct ieee80211_sub_if_data *sdata,
			     bool powersave);
void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
				   struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
			     struct ieee80211_hdr *hdr, bool ack, u16 tx_time);

+2 −2
Original line number Diff line number Diff line
@@ -1095,7 +1095,7 @@ void ieee80211_send_nullfunc(struct ieee80211_local *local,
	ieee80211_tx_skb(sdata, skb);
}

static void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
				   struct ieee80211_sub_if_data *sdata)
{
	struct sk_buff *skb;
+2 −1
Original line number Diff line number Diff line
@@ -730,7 +730,8 @@ ieee80211_make_monitor_skb(struct ieee80211_local *local,
		 * Need to make a copy and possibly remove radiotap header
		 * and FCS from the original.
		 */
		skb = skb_copy_expand(*origskb, needed_headroom, 0, GFP_ATOMIC);
		skb = skb_copy_expand(*origskb, needed_headroom + NET_SKB_PAD,
				      0, GFP_ATOMIC);

		if (!skb)
			return NULL;
Loading