[PATCH] wpa_supplicant: Add support for setting of a regulatory domain
Luis R. Rodriguez
lrodriguez
Mon Dec 8 17:07:49 PST 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