nl80211: Add a get_country hook
authorarron.wang <arron.wang@intel.com>
Fri, 8 Jun 2012 00:27:57 +0000 (08:27 +0800)
committerarron.wang <arron.wang@intel.com>
Fri, 8 Jun 2012 00:27:57 +0000 (08:27 +0800)
Get the current regulatory domain through nl80211.

src/drivers/driver.h
src/drivers/driver_nl80211.c
wpa_supplicant/driver_i.h

index bf18c34..1376594 100644 (file)
@@ -1324,6 +1324,14 @@ struct wpa_driver_ops {
         struct wpa_scan_results * (*get_scan_results2)(void *priv);
 
        /**
+        * get_country - get country
+        * @priv: Private driver interface data
+        * Returns: Allocated alpha2 null terminated string (caller is
+        * responsible for freeing the data structure), NULL on failure.
+        */
+       char * (*get_country)(void *priv);
+
+       /**
         * set_country - Set country
         * @priv: Private driver interface data
         * @alpha2: country to which to switch to
index e12e511..f3c9218 100644 (file)
@@ -1875,6 +1875,55 @@ static void wpa_driver_nl80211_event_receive(int sock, void *eloop_ctx,
 }
 
 
+static int nl80211_get_country(struct nl_msg *msg, void *arg)
+{
+       char **alpha2 = arg;
+       struct nlattr *tb_msg[NL80211_ATTR_MAX + 1];
+       struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
+
+       nla_parse(tb_msg, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
+                 genlmsg_attrlen(gnlh, 0), NULL);
+       if (!tb_msg[NL80211_ATTR_REG_ALPHA2] ||
+           !tb_msg[NL80211_ATTR_REG_RULES]) {
+               wpa_printf(MSG_DEBUG, "nl80211: No regulatory information "
+                          "available");
+               return NL_SKIP;
+       }
+
+       *alpha2 = os_strdup((char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]));
+
+       return NL_SKIP;
+}
+
+/**
+ * wpa_driver_nl80211_get_country - ask nl80211 to get the regulatory domain
+ * @priv: driver_nl80211 private data.
+ * Returns: An allocated alpha2 null terminated string, NULL on failure.
+ *
+ * This asks nl80211 to get the regulatory domain.
+ */
+static char *wpa_driver_nl80211_get_country(void *priv)
+{
+       struct i802_bss *bss = priv;
+       struct wpa_driver_nl80211_data *drv = bss->drv;
+       char *alpha2 = NULL;
+       struct nl_msg *msg;
+
+       msg = nlmsg_alloc();
+       if (!msg)
+               return NULL;
+
+       genlmsg_put(msg, 0, 0, genl_family_get_id(drv->global->nl80211), 0,
+                   0, NL80211_CMD_GET_REG, 0);
+
+       if (send_and_recv_msgs(drv, msg, nl80211_get_country, &alpha2))
+               return NULL;
+
+       wpa_printf(MSG_DEBUG, "nl80211: Country=%s", alpha2);
+
+       return alpha2;
+}
+
 /**
  * wpa_driver_nl80211_set_country - ask nl80211 to set the regulatory domain
  * @priv: driver_nl80211 private data
@@ -7706,6 +7755,7 @@ const struct wpa_driver_ops wpa_driver_nl80211_ops = {
        .get_capa = wpa_driver_nl80211_get_capa,
        .set_operstate = wpa_driver_nl80211_set_operstate,
        .set_supp_port = wpa_driver_nl80211_set_supp_port,
+       .get_country = wpa_driver_nl80211_get_country,
        .set_country = wpa_driver_nl80211_set_country,
        .set_ap = wpa_driver_nl80211_set_ap,
        .if_add = wpa_driver_nl80211_if_add,
index 9828aff..1bf42e3 100644 (file)
@@ -253,6 +253,13 @@ wpa_drv_get_hw_feature_data(struct wpa_supplicant *wpa_s, u16 *num_modes,
        return NULL;
 }
 
+static inline char *wpa_drv_get_country(struct wpa_supplicant *wpa_s)
+{
+       if (wpa_s->driver->get_country)
+               return wpa_s->driver->get_country(wpa_s->drv_priv);
+       return NULL;
+}
+
 static inline int wpa_drv_set_country(struct wpa_supplicant *wpa_s,
                                      const char *alpha2)
 {