[PATCH] nl80211: Allow configuring allowable legacy rate mask.

greearb at candelatech.com greearb at candelatech.com
Tue Sep 15 20:04:45 EDT 2015


From: Ben Greear <greearb at candelatech.com>

With this, we should be able to disable un-wanted rates
early in the association process, before 'iw' could
have a chance to make any settings.

Signed-off-by: Ben Greear <greearb at candelatech.com>
---
 src/drivers/driver.h                 |  10 ++
 src/drivers/driver_nl80211.c         | 216 +++++++++++++++++++++++++----------
 src/drivers/driver_nl80211.h         |   5 +-
 src/drivers/driver_nl80211_monitor.c |   4 +-
 wpa_supplicant/driver_i.h            |   7 ++
 wpa_supplicant/wpa_supplicant.c      |   8 ++
 wpa_supplicant/wpa_supplicant.conf   |   5 +
 7 files changed, 192 insertions(+), 63 deletions(-)

diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 3cdab5a..d5fbf2c 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -1425,6 +1425,9 @@ struct wpa_init_params {
 	char **bridge;
 	size_t num_bridge;
 
+	/* legacy rate mask, 12 bits for legacy rates, (1<<31) to enable use of this mask */
+	unsigned int legacy_rates;
+
 	u8 *own_addr; /* buffer for writing own MAC address */
 };
 
@@ -3012,6 +3015,13 @@ struct wpa_driver_ops {
 	int (*stop_sched_scan)(void *priv);
 
 	/**
+	 * Set the legacy rates.  User would have previously configured the
+	 * ratemask through other means.  This just tells the kernel to apply
+	 * it.
+	 */
+	int (*set_legacy_rates)(void *priv);
+
+	/**
 	 * poll_client - Probe (null data or such) the given station
 	 * @priv: Private driver interface data
 	 * @own_addr: MAC address of sending interface
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 075a20e..3fbf0f4 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -186,8 +186,10 @@ static int have_ifidx(struct wpa_driver_nl80211_data *drv, int ifidx);
 
 static int nl80211_set_channel(struct i802_bss *bss,
 			       struct hostapd_freq_params *freq, int set_chan);
-static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
-				     int ifindex, int disabled);
+static int nl80211_set_legacy_rates(struct i802_bss *bss,
+				    struct wpa_driver_nl80211_data *drv,
+				    int ifindex, int b_disabled,
+				    unsigned int cfg_legacy_mask);
 
 static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv,
 			      int reset_mode);
@@ -2295,8 +2297,8 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
 {
 	struct wpa_driver_nl80211_data *drv = bss->drv;
 
-	wpa_printf(MSG_INFO, "nl80211: deinit ifname=%s disabled_11b_rates=%d",
-		   bss->ifname, drv->disabled_11b_rates);
+	wpa_printf(MSG_INFO, "nl80211: deinit ifname=%s",
+		   bss->ifname);
 
 	bss->in_deinit = 1;
 	if (drv->data_tx_status)
@@ -2340,8 +2342,7 @@ static void wpa_driver_nl80211_deinit(struct i802_bss *bss)
 	if (drv->if_indices != drv->default_if_indices)
 		os_free(drv->if_indices);
 
-	if (drv->disabled_11b_rates)
-		nl80211_disable_11b_rates(drv, drv->ifindex, 0);
+	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, 0xFFF);
 
 	netlink_send_oper_ifla(drv->global->netlink, drv->ifindex, 0,
 			       IF_OPER_UP);
@@ -2864,25 +2865,6 @@ static void nl80211_copy_auth_params(struct wpa_driver_nl80211_data *drv,
 }
 
 
-static void nl80211_unmask_11b_rates(struct i802_bss *bss)
-{
-	struct wpa_driver_nl80211_data *drv = bss->drv;
-
-	if (is_p2p_net_interface(drv->nlmode) || !drv->disabled_11b_rates)
-		return;
-
-	/*
-	 * Looks like we failed to unmask 11b rates previously. This could
-	 * happen, e.g., if the interface was down at the point in time when a
-	 * P2P group was terminated.
-	 */
-	wpa_printf(MSG_DEBUG,
-		   "nl80211: Interface %s mode is for non-P2P, but 11b rates were disabled - re-enable them",
-		   bss->ifname);
-	nl80211_disable_11b_rates(drv, drv->ifindex, 0);
-}
-
-
 static int wpa_driver_nl80211_authenticate(
 	struct i802_bss *bss, struct wpa_driver_auth_params *params)
 {
@@ -2894,7 +2876,7 @@ static int wpa_driver_nl80211_authenticate(
 	int count = 0;
 	int is_retry;
 
-	nl80211_unmask_11b_rates(bss);
+	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->legacy_rates);
 
 	is_retry = drv->retry_auth;
 	drv->retry_auth = 0;
@@ -4076,7 +4058,7 @@ static int nl80211_create_iface_once(struct wpa_driver_nl80211_data *drv,
 }
 
 
-int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
+int nl80211_create_iface(struct i802_bss *bss, struct wpa_driver_nl80211_data *drv,
 			 const char *ifname, enum nl80211_iftype iftype,
 			 const u8 *addr, int wds,
 			 int (*handler)(struct nl_msg *, void *),
@@ -4118,7 +4100,7 @@ int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Interface %s created for P2P - disable 11b rates",
 			   ifname);
-		nl80211_disable_11b_rates(drv, ret, 1);
+		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 1, bss->legacy_rates);
 	}
 
 	return ret;
@@ -4149,7 +4131,7 @@ static int nl80211_setup_ap(struct i802_bss *bss)
 			return -1;
 
 	if (!drv->device_ap_sme && drv->use_monitor &&
-	    nl80211_create_monitor_interface(drv) &&
+	    nl80211_create_monitor_interface(bss, drv) &&
 	    !drv->device_ap_sme)
 		return -1;
 
@@ -4810,7 +4792,7 @@ static int wpa_driver_nl80211_associate(
 	int ret = -1;
 	struct nl_msg *msg;
 
-	nl80211_unmask_11b_rates(bss);
+	nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->legacy_rates);
 
 	if (params->mode == IEEE80211_MODE_AP)
 		return wpa_driver_nl80211_ap(drv, params);
@@ -4989,12 +4971,12 @@ done:
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Interface %s mode change to P2P - disable 11b rates",
 			   bss->ifname);
-		nl80211_disable_11b_rates(drv, drv->ifindex, 1);
-	} else if (drv->disabled_11b_rates) {
+		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 1, bss->legacy_rates);
+	} else {
 		wpa_printf(MSG_DEBUG,
 			   "nl80211: Interface %s mode changed to non-P2P - re-enable 11b rates",
 			   bss->ifname);
-		nl80211_disable_11b_rates(drv, drv->ifindex, 0);
+		nl80211_set_legacy_rates(bss, drv, drv->ifindex, 0, bss->legacy_rates);
 	}
 
 	if (is_ap_interface(nlmode)) {
@@ -5595,7 +5577,7 @@ static int i802_set_wds_sta(void *priv, const u8 *addr, int aid, int val,
 		   " aid=%d val=%d name=%s", MAC2STR(addr), aid, val, name);
 	if (val) {
 		if (!if_nametoindex(name)) {
-			if (nl80211_create_iface(drv, name,
+			if (nl80211_create_iface(bss, drv, name,
 						 NL80211_IFTYPE_AP_VLAN,
 						 bss->addr, 1, NULL, NULL, 0) <
 			    0)
@@ -5917,7 +5899,7 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
 		struct wdev_info p2pdev_info;
 
 		os_memset(&p2pdev_info, 0, sizeof(p2pdev_info));
-		ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
+		ifidx = nl80211_create_iface(bss, drv, ifname, nlmode, addr,
 					     0, nl80211_wdev_handler,
 					     &p2pdev_info, use_existing);
 		if (!p2pdev_info.wdev_id_set || ifidx != 0) {
@@ -5934,7 +5916,7 @@ static int wpa_driver_nl80211_if_add(void *priv, enum wpa_driver_if_type type,
 			   ifname,
 			   (long long unsigned int) p2pdev_info.wdev_id);
 	} else {
-		ifidx = nl80211_create_iface(drv, ifname, nlmode, addr,
+		ifidx = nl80211_create_iface(bss, drv, ifname, nlmode, addr,
 					     0, NULL, NULL, use_existing);
 		if (use_existing && ifidx == -ENFILE) {
 			added = 0;
@@ -6373,17 +6355,19 @@ static int wpa_driver_nl80211_probe_req_report(struct i802_bss *bss, int report)
 }
 
 
-static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
-				     int ifindex, int disabled)
+static int nl80211_set_legacy_rates(struct i802_bss *bss,
+				    struct wpa_driver_nl80211_data *drv,
+				    int ifindex, int b_disabled,
+				    unsigned int legacy_rates)
 {
 	struct nl_msg *msg;
 	struct nlattr *bands, *band;
 	int ret;
 
 	wpa_printf(MSG_DEBUG,
-		   "nl80211: NL80211_CMD_SET_TX_BITRATE_MASK (ifindex=%d %s)",
-		   ifindex, disabled ? "NL80211_TXRATE_LEGACY=OFDM-only" :
-		   "no NL80211_TXRATE_LEGACY constraint");
+		   "nl80211: NL80211_CMD_SET_TX_BITRATE_MASK (ifindex=%d %s cfg-legacy-mask: 0x%x)",
+		   ifindex, b_disabled ? "NL80211_TXRATE_LEGACY=OFDM-only" :
+		   "no NL80211_TXRATE_LEGACY constraint", legacy_rates);
 
 	msg = nl80211_ifindex_msg(drv, ifindex, 0,
 				  NL80211_CMD_SET_TX_BITRATE_MASK);
@@ -6400,20 +6384,130 @@ static int nl80211_disable_11b_rates(struct wpa_driver_nl80211_data *drv,
 	 * rates. All 5 GHz rates are left enabled.
 	 */
 	band = nla_nest_start(msg, NL80211_BAND_2GHZ);
-	if (!band ||
-	    (disabled && nla_put(msg, NL80211_TXRATE_LEGACY, 8,
-				 "\x0c\x12\x18\x24\x30\x48\x60\x6c")))
+	if (!band)
 		goto fail;
+
+	if (legacy_rates & (1<<31) || b_disabled) {
+		unsigned char rates[12];
+		int i = 0;
+		if (legacy_rates & (1<<31)) {
+			/* Pay attention to the legacy mask */
+			if (!(b_disabled || ((legacy_rates & 0x1) == 0))) {
+				rates[i] = 2;
+				i++;
+			}
+			if (!(b_disabled || ((legacy_rates & 0x2) == 0))) {
+				rates[i] = 4;
+				i++;
+			}
+			if (!(b_disabled || ((legacy_rates & 0x4) == 0))) {
+				rates[i] = 11;
+				i++;
+			}
+			if (!(b_disabled || ((legacy_rates & 0x8) == 0))) {
+				rates[i] = 22;
+				i++;
+			}
+			if (legacy_rates & 0x10) { // 6Mbps
+				rates[i] = 12;
+				i++;
+			}
+			if (legacy_rates & 0x20) { // 9Mbps
+				rates[i] = 18;
+				i++;
+			}
+			if (legacy_rates & 0x40) { // 12Mbps
+				rates[i] = 24;
+				i++;
+			}
+			if (legacy_rates & 0x80) { // 18Mbps
+				rates[i] = 36;
+				i++;
+			}
+			if (legacy_rates & 0x100) { // 24Mbps
+				rates[i] = 48;
+				i++;
+			}
+			if (legacy_rates & 0x200) { // 36Mbps
+				rates[i] = 72;
+				i++;
+			}
+			if (legacy_rates & 0x400) { // 48Mbps
+				rates[i] = 96;
+				i++;
+			}
+			if (legacy_rates & 0x800) { // 54Mbps
+				rates[i] = 108;
+				i++;
+			}
+		}/* if user configured a legacy mask */
+		else if (b_disabled) {
+			i = 8;
+			/* Enable all /g rates */
+			memcpy(rates, "\x0c\x12\x18\x24\x30\x48\x60\x6c", i);
+		}
+		if (legacy_rates & (1<<31) || i) {
+			if (nla_put(msg, NL80211_TXRATE_LEGACY, i, rates))
+				goto fail;
+		}
+	}/* if we might need to disable some rates */
+
 	nla_nest_end(msg, band);
 
+	if (legacy_rates & (1<<31)) {
+		unsigned char rates[8];
+		int i = 0;
+
+		band = nla_nest_start(msg, NL80211_BAND_5GHZ);
+		if (!band)
+			goto fail;
+
+		if (legacy_rates & 0x10) { // 6Mbps
+			rates[i] = 12;
+			i++;
+		}
+		if (legacy_rates & 0x20) { // 9Mbps
+			rates[i] = 18;
+			i++;
+		}
+		if (legacy_rates & 0x40) { // 12Mbps
+			rates[i] = 24;
+			i++;
+		}
+		if (legacy_rates & 0x80) { // 18Mbps
+			rates[i] = 36;
+			i++;
+		}
+		if (legacy_rates & 0x100) { // 24Mbps
+			rates[i] = 48;
+			i++;
+		}
+		if (legacy_rates & 0x200) { // 36Mbps
+			rates[i] = 72;
+			i++;
+		}
+		if (legacy_rates & 0x400) { // 48Mbps
+			rates[i] = 96;
+			i++;
+		}
+		if (legacy_rates & 0x800) { // 54Mbps
+			rates[i] = 108;
+			i++;
+		}
+
+		if (nla_put(msg, NL80211_TXRATE_LEGACY, i, rates))
+			goto fail;
+
+		nla_nest_end(msg, band);
+	}
+
 	nla_nest_end(msg, bands);
 
 	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
 	if (ret) {
-		wpa_printf(MSG_DEBUG, "nl80211: Set TX rates failed: ret=%d "
+		wpa_printf(MSG_DEBUG, "nl80211: Set Legacy TX rates failed: ret=%d "
 			   "(%s)", ret, strerror(-ret));
-	} else
-		drv->disabled_11b_rates = disabled;
+	}
 
 	return ret;
 
@@ -6422,6 +6516,11 @@ fail:
 	return -1;
 }
 
+int wpa_driver_nl80211_set_legacy_rates(void *priv)
+{
+	struct i802_bss *bss = priv;
+	return nl80211_set_legacy_rates(bss, bss->drv, bss->drv->ifindex, 0, bss->legacy_rates);
+}
 
 static int wpa_driver_nl80211_deinit_ap(void *priv)
 {
@@ -6573,15 +6672,16 @@ static int nl80211_send_frame(void *priv, const u8 *data, size_t data_len,
 
 static int nl80211_set_param(void *priv, const char *param)
 {
+	char* tmp;
+	struct i802_bss *bss = priv;
+	struct wpa_driver_nl80211_data *drv = bss->drv;
+
 	wpa_printf(MSG_DEBUG, "nl80211: driver param='%s'", param);
 	if (param == NULL)
 		return 0;
 
 #ifdef CONFIG_P2P
 	if (os_strstr(param, "use_p2p_group_interface=1")) {
-		struct i802_bss *bss = priv;
-		struct wpa_driver_nl80211_data *drv = bss->drv;
-
 		wpa_printf(MSG_DEBUG, "nl80211: Use separate P2P group "
 			   "interface");
 		drv->capa.flags |= WPA_DRIVER_FLAGS_P2P_CONCURRENT;
@@ -6590,25 +6690,24 @@ static int nl80211_set_param(void *priv, const char *param)
 #endif /* CONFIG_P2P */
 
 	if (os_strstr(param, "use_monitor=1")) {
-		struct i802_bss *bss = priv;
-		struct wpa_driver_nl80211_data *drv = bss->drv;
 		drv->use_monitor = 1;
 	}
 
 	if (os_strstr(param, "force_connect_cmd=1")) {
-		struct i802_bss *bss = priv;
-		struct wpa_driver_nl80211_data *drv = bss->drv;
 		drv->capa.flags &= ~WPA_DRIVER_FLAGS_SME;
 		drv->force_connect_cmd = 1;
 	}
 
 	if (os_strstr(param, "no_offchannel_tx=1")) {
-		struct i802_bss *bss = priv;
-		struct wpa_driver_nl80211_data *drv = bss->drv;
 		drv->capa.flags &= ~WPA_DRIVER_FLAGS_OFFCHANNEL_TX;
 		drv->test_use_roc_tx = 1;
 	}
 
+	if ((tmp = os_strstr(param, "legacy_rates="))) {
+		bss->legacy_rates = atoi(tmp + strlen("legacy_rates="));
+		bss->legacy_rates |= (1<<31); /* so we know user actually configured something */
+	}
+
 	return 0;
 }
 
@@ -7456,7 +7555,7 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
 			  "monitor_refcount=%d\n"
 			  "last_mgmt_freq=%u\n"
 			  "eapol_tx_sock=%d\n"
-			  "%s%s%s%s%s%s%s%s%s%s%s%s%s",
+			  "%s%s%s%s%s%s%s%s%s%s%s%s",
 			  drv->phyname,
 			  MAC2STR(drv->perm_addr),
 			  drv->ifindex,
@@ -7477,8 +7576,6 @@ static int wpa_driver_nl80211_status(void *priv, char *buf, size_t buflen)
 			  "ignore_if_down_event=1\n" : "",
 			  drv->scan_complete_events ?
 			  "scan_complete_events=1\n" : "",
-			  drv->disabled_11b_rates ?
-			  "disabled_11b_rates=1\n" : "",
 			  drv->pending_remain_on_chan ?
 			  "pending_remain_on_chan=1\n" : "",
 			  drv->in_interface_list ? "in_interface_list=1\n" : "",
@@ -8731,6 +8828,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
 	.scan2 = driver_nl80211_scan2,
 	.sched_scan = wpa_driver_nl80211_sched_scan,
 	.stop_sched_scan = wpa_driver_nl80211_stop_sched_scan,
+	.set_legacy_rates = wpa_driver_nl80211_set_legacy_rates,
 	.get_scan_results2 = wpa_driver_nl80211_get_scan_results,
 	.deauthenticate = driver_nl80211_deauthenticate,
 	.authenticate = driver_nl80211_authenticate,
diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h
index 5c21e0f..bc64e5c 100644
--- a/src/drivers/driver_nl80211.h
+++ b/src/drivers/driver_nl80211.h
@@ -70,6 +70,7 @@ struct i802_bss {
 	int freq;
 	int bandwidth;
 	int if_dynamic;
+	unsigned int legacy_rates; /* 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54.  (1<<31) enables this mask */
 
 	void *ctx;
 	struct nl_handle *nl_preq, *nl_mgmt;
@@ -195,7 +196,7 @@ struct nl_msg * nl80211_bss_msg(struct i802_bss *bss, int flags, uint8_t cmd);
 int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv, struct nl_msg *msg,
 		       int (*valid_handler)(struct nl_msg *, void *),
 		       void *valid_data);
-int nl80211_create_iface(struct wpa_driver_nl80211_data *drv,
+int nl80211_create_iface(struct i802_bss *bss, struct wpa_driver_nl80211_data *drv,
 			 const char *ifname, enum nl80211_iftype iftype,
 			 const u8 *addr, int wds,
 			 int (*handler)(struct nl_msg *, void *),
@@ -220,7 +221,7 @@ int wpa_driver_nl80211_mlme(struct wpa_driver_nl80211_data *drv,
 			    const u8 *addr, int cmd, u16 reason_code,
 			    int local_state_change);
 
-int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv);
+int nl80211_create_monitor_interface(struct i802_bss *bss, struct wpa_driver_nl80211_data *drv);
 void nl80211_remove_monitor_interface(struct wpa_driver_nl80211_data *drv);
 int nl80211_send_monitor(struct wpa_driver_nl80211_data *drv,
 			 const void *data, size_t len,
diff --git a/src/drivers/driver_nl80211_monitor.c b/src/drivers/driver_nl80211_monitor.c
index 45385da..8e0b482 100644
--- a/src/drivers/driver_nl80211_monitor.c
+++ b/src/drivers/driver_nl80211_monitor.c
@@ -338,7 +338,7 @@ void nl80211_remove_monitor_interface(struct wpa_driver_nl80211_data *drv)
 }
 
 
-int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
+int nl80211_create_monitor_interface(struct i802_bss *bss, struct wpa_driver_nl80211_data *drv)
 {
 	char buf[IFNAMSIZ];
 	struct sockaddr_ll ll;
@@ -368,7 +368,7 @@ int nl80211_create_monitor_interface(struct wpa_driver_nl80211_data *drv)
 	buf[IFNAMSIZ - 1] = '\0';
 
 	drv->monitor_ifidx =
-		nl80211_create_iface(drv, buf, NL80211_IFTYPE_MONITOR, NULL,
+		nl80211_create_iface(bss, drv, buf, NL80211_IFTYPE_MONITOR, NULL,
 				     0, NULL, NULL, 0);
 
 	if (drv->monitor_ifidx == -EOPNOTSUPP) {
diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h
index 73768c7..a1853e5 100644
--- a/wpa_supplicant/driver_i.h
+++ b/wpa_supplicant/driver_i.h
@@ -116,6 +116,13 @@ static inline int wpa_drv_stop_sched_scan(struct wpa_supplicant *wpa_s)
 	return -1;
 }
 
+static inline int wpa_drv_set_legacy_rates(struct wpa_supplicant *wpa_s)
+{
+	if (wpa_s->driver->set_legacy_rates)
+		return wpa_s->driver->set_legacy_rates(wpa_s->drv_priv);
+	return -1;
+}
+
 static inline struct wpa_scan_results * wpa_drv_get_scan_results2(
 	struct wpa_supplicant *wpa_s)
 {
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 92b1137..09c9371 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -723,6 +723,12 @@ void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s,
 		wpa_s->normal_scans = 0;
 	}
 
+	/* If we are moving from DISCONNECTED to Scanning, then (re)set
+	 * the legacy ratemask, as it could have just been cleared as
+	 * the network device just bounced.
+	 */
+	wpa_drv_set_legacy_rates(wpa_s);
+
 	if (state == WPA_COMPLETED) {
 		wpas_connect_work_done(wpa_s);
 		/* Reinitialize normal_scan counter */
@@ -3375,6 +3381,8 @@ int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s)
 	wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver");
 	wpa_drv_flush_pmkid(wpa_s);
 
+	wpa_drv_set_legacy_rates(wpa_s);
+
 	wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
 	wpa_s->prev_scan_wildcard = 0;
 
diff --git a/wpa_supplicant/wpa_supplicant.conf b/wpa_supplicant/wpa_supplicant.conf
index c738b3f..41c55ef 100644
--- a/wpa_supplicant/wpa_supplicant.conf
+++ b/wpa_supplicant/wpa_supplicant.conf
@@ -182,6 +182,11 @@ fast_reauth=1
 # format is specific to the selected driver interface. This field is not used
 # in most cases.
 #driver_param="field=value"
+#
+# In particular, nl80211 supports: use_monitor=1, force_connect_cmd=1,
+#        no_offchannel_tx=1, legacy_rates=[number]
+# For legacy_rates, the number is a bitfield where rate 1Mbps is first bit,
+# and 54Mbps is 12th bit.
 
 # Country code
 # The ISO/IEC alpha2 country code for the country in which this device is
-- 
1.9.3



More information about the HostAP mailing list