[PATCH] wpa_supplicant: Add support for setting of a regulatory domain

Luis R. Rodriguez lrodriguez at atheros.com
Mon Dec 8 20:07:49 EST 2008


This adds support for setting of a regulatory domain to wpa_supplicant
drivers. It also adds regulatory domain setting for the nl80211 driver.
We expect an ISO / IEC 3166 alpha2 in the wpa configuration file as a
global.

---
 src/drivers/driver.h              |   11 +++++++++++
 src/drivers/driver_nl80211.c      |   35 +++++++++++++++++++++++++++++++++++
 wpa_supplicant/config.h           |    7 +++++++
 wpa_supplicant/config_file.c      |   17 +++++++++++++++++
 wpa_supplicant/wpa_supplicant.c   |    6 ++++++
 wpa_supplicant/wpa_supplicant_i.h |    8 ++++++++
 6 files changed, 84 insertions(+), 0 deletions(-)

diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 5357598..b0080b6 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -840,6 +840,17 @@ struct wpa_driver_ops {
 	int (*set_bssid)(void *priv, const u8 *bssid);
 
 	/**
+	 * set_country - Set country
+	 * @priv: Private driver interface data
+	 * @alpha2: country to which to switch to
+	 * Returns: 0 on success, -1 on failure
+	 *
+	 * This function is for drivers which support some form
+	 * of setting a regulatory domain.
+	 */
+	int (*set_country)(void *priv, const char *alpha2);
+
+	/**
 	 * send_mlme - Send management frame from MLME
 	 * @priv: Private driver interface data
 	 * @data: IEEE 802.11 management frame with IEEE 802.11 header
diff --git a/src/drivers/driver_nl80211.c b/src/drivers/driver_nl80211.c
index 59ef1d7..b17f6f3 100644
--- a/src/drivers/driver_nl80211.c
+++ b/src/drivers/driver_nl80211.c
@@ -957,6 +957,40 @@ static int wpa_driver_nl80211_set_ifflags(struct wpa_driver_nl80211_data *drv,
 	return wpa_driver_nl80211_set_ifflags_ifname(drv, drv->ifname, flags);
 }
 
+/**
+ * wpa_driver_nl80211_set_country - ask nl80211 to set the regulatory domain
+ * @drv: driver_nl80211 private data
+ * This asks nl80211 to set the regulatory domain for given
+ * country ISO / IEC alpha2.
+ * Returns: 0 on success, -1 on failure
+ */
+static int wpa_driver_nl80211_set_country(struct wpa_driver_nl80211_data *drv,
+	const char *alpha2_arg)
+{
+	char alpha2[3];
+	struct nl_msg *msg;
+
+	if (!alpha2_arg[0] || !alpha2_arg[1])
+		goto nla_put_failure;
+
+	msg = nlmsg_alloc();
+	if (!msg)
+		goto nla_put_failure;
+
+	alpha2[0] = alpha2_arg[0];
+	alpha2[1] = alpha2_arg[1];
+	alpha2[2] = '\0';
+
+	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
+		    0, NL80211_CMD_REQ_SET_REG, 0);
+
+	NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);
+	if (send_and_recv_msgs(drv, msg, NULL, NULL))
+		return -EINVAL;
+	return 0;
+nla_put_failure:
+	return -EINVAL;
+}
 
 #ifdef CONFIG_CLIENT_MLME
 
@@ -2858,6 +2892,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
 	.flush_pmkid = wpa_driver_nl80211_flush_pmkid,
 	.get_capa = wpa_driver_nl80211_get_capa,
 	.set_operstate = wpa_driver_nl80211_set_operstate,
+	.set_country = wpa_driver_nl80211_set_country,
 #ifdef CONFIG_CLIENT_MLME
 	.get_hw_feature_data = wpa_driver_nl80211_get_hw_feature_data,
 	.set_channel = wpa_driver_nl80211_set_channel,
diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h
index b05576d..cfde781 100644
--- a/wpa_supplicant/config.h
+++ b/wpa_supplicant/config.h
@@ -43,6 +43,13 @@ struct wpa_config {
 	struct wpa_ssid *ssid;
 
 	/**
+	 * alpha2 - Country code
+	 *
+	 * This is the ISO / IEC alpha2 country code for which we are operating in
+	 */
+	char alpha2[2];
+
+	/**
 	 * pssid - Per-priority network lists (in priority order)
 	 */
 	struct wpa_ssid **pssid;
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index acc9ee5..5a32681 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -269,6 +269,19 @@ static int wpa_config_process_blob(struct wpa_config *config, FILE *f,
 }
 #endif /* CONFIG_NO_CONFIG_BLOBS */
 
+static int wpa_config_process_country(struct wpa_config *config,
+					   char *pos)
+{
+	if (!pos[0] || !pos[1]) {
+		wpa_printf(MSG_DEBUG, "Invalid country set");
+		return -EINVAL;
+	}
+	config->alpha2[0] = pos[0];
+	config->alpha2[1] = pos[1];
+	wpa_printf(MSG_DEBUG, "Trying country='%c%c'",
+		config->alpha2[0], config->alpha2[1]);
+	return 0;
+}
 
 #ifdef CONFIG_CTRL_IFACE
 static int wpa_config_process_ctrl_interface(struct wpa_config *config,
@@ -447,6 +460,10 @@ static int wpa_config_process_uuid(struct wpa_config *config, int line,
 static int wpa_config_process_global(struct wpa_config *config, char *pos,
 				     int line)
 {
+	if (os_strncmp(pos, "country=", 8) == 0) {
+		return wpa_config_process_country(config, pos + 8);
+	}
+
 #ifdef CONFIG_CTRL_IFACE
 	if (os_strncmp(pos, "ctrl_interface=", 15) == 0)
 		return wpa_config_process_ctrl_interface(config, pos + 15);
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 00d20c9..eb1a33e 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -1790,6 +1790,12 @@ static int wpa_supplicant_init_iface2(struct wpa_supplicant *wpa_s)
 	if (wpa_supplicant_driver_init(wpa_s) < 0)
 		return -1;
 
+	if (wpa_drv_set_country(wpa_s, wpa_s->conf->alpha2))
+		wpa_printf(MSG_DEBUG, "Failed to set country");
+	else
+		wpa_printf(MSG_DEBUG, "Set country=%c%c",
+			wpa_s->conf->alpha2[0], wpa_s->conf->alpha2[1]);
+
 	wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr);
 
 	if (wpas_wps_init(wpa_s))
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index ab7aa94..d493ea5 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -676,6 +676,14 @@ static inline int wpa_drv_set_bssid(struct wpa_supplicant *wpa_s,
 	return -1;
 }
 
+static inline int wpa_drv_set_country(struct wpa_supplicant *wpa_s,
+				    const char *alpha2)
+{
+	if (wpa_s->driver->set_country)
+		return wpa_s->driver->set_country(wpa_s->drv_priv, alpha2);
+	return -1;
+}
+
 static inline int wpa_drv_send_mlme(struct wpa_supplicant *wpa_s,
 				    const u8 *data, size_t data_len)
 {
-- 
1.5.6.rc2.15.g457bb.dirty



More information about the HostAP mailing list