]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add a wpa_supplicant ctrl_iface event for regdom changes
authorJouni Malinen <j@w1.fi>
Sun, 13 Apr 2014 13:32:38 +0000 (16:32 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 13 Apr 2014 13:32:38 +0000 (16:32 +0300)
CTRL-EVENT-REGDOM-CHANGE event provides an external notification of
regulatory domain (and any driver channel list) changes.

Signed-off-by: Jouni Malinen <j@w1.fi>
src/common/wpa_ctrl.h
src/drivers/driver.h
src/drivers/driver_nl80211.c
wpa_supplicant/events.c

index 5ef75e8354de424473a2c2465712fb3850a8aec6..534bc997c19c9820b5c857d425e4d699da93bc4b 100644 (file)
@@ -66,6 +66,8 @@ extern "C" {
 #define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED "
 /** Change in the signal level was reported by the driver */
 #define WPA_EVENT_SIGNAL_CHANGE "CTRL-EVENT-SIGNAL-CHANGE "
+/** Regulatory domain channel */
+#define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE "
 
 /** RSN IBSS 4-way handshakes completed with specified peer */
 #define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED "
index 02ade12590c1fc6e6394826dd8e60b6c34b72590..13bf7183dcc1a2ff9720c8114fee36f53fe40bfd 100644 (file)
@@ -50,6 +50,14 @@ enum reg_change_initiator {
        REGDOM_BEACON_HINT,
 };
 
+enum reg_type {
+       REGDOM_TYPE_UNKNOWN,
+       REGDOM_TYPE_COUNTRY,
+       REGDOM_TYPE_WORLD,
+       REGDOM_TYPE_CUSTOM_WORLD,
+       REGDOM_TYPE_INTERSECTION,
+};
+
 /**
  * struct hostapd_channel_data - Channel information
  */
@@ -3851,9 +3859,13 @@ union wpa_event_data {
        /**
         * channel_list_changed - Data for EVENT_CHANNEL_LIST_CHANGED
         * @initiator: Initiator of the regulatory change
+        * @type: Regulatory change type
+        * @alpha2: Country code (or "" if not available)
         */
        struct channel_list_changed {
                enum reg_change_initiator initiator;
+               enum reg_type type;
+               char alpha2[3];
        } channel_list_changed;
 
        /**
index 5b5ceb0511af60d56010b63f91cf88377aad064e..9a75f960b140b9c1d563939eb82df164830676b5 100644 (file)
@@ -2889,6 +2889,69 @@ static void nl80211_vendor_event(struct wpa_driver_nl80211_data *drv,
 }
 
 
+static void nl80211_reg_change_event(struct wpa_driver_nl80211_data *drv,
+                                    struct nlattr *tb[])
+{
+       union wpa_event_data data;
+       enum nl80211_reg_initiator init;
+
+       wpa_printf(MSG_DEBUG, "nl80211: Regulatory domain change");
+
+       if (tb[NL80211_ATTR_REG_INITIATOR] == NULL)
+               return;
+
+       os_memset(&data, 0, sizeof(data));
+       init = nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR]);
+       wpa_printf(MSG_DEBUG, " * initiator=%d", init);
+       switch (init) {
+       case NL80211_REGDOM_SET_BY_CORE:
+               data.channel_list_changed.initiator = REGDOM_SET_BY_CORE;
+               break;
+       case NL80211_REGDOM_SET_BY_USER:
+               data.channel_list_changed.initiator = REGDOM_SET_BY_USER;
+               break;
+       case NL80211_REGDOM_SET_BY_DRIVER:
+               data.channel_list_changed.initiator = REGDOM_SET_BY_DRIVER;
+               break;
+       case NL80211_REGDOM_SET_BY_COUNTRY_IE:
+               data.channel_list_changed.initiator = REGDOM_SET_BY_COUNTRY_IE;
+               break;
+       }
+
+       if (tb[NL80211_ATTR_REG_TYPE]) {
+               enum nl80211_reg_type type;
+               type = nla_get_u8(tb[NL80211_ATTR_REG_TYPE]);
+               wpa_printf(MSG_DEBUG, " * type=%d", type);
+               switch (type) {
+               case NL80211_REGDOM_TYPE_COUNTRY:
+                       data.channel_list_changed.type = REGDOM_TYPE_COUNTRY;
+                       break;
+               case NL80211_REGDOM_TYPE_WORLD:
+                       data.channel_list_changed.type = REGDOM_TYPE_WORLD;
+                       break;
+               case NL80211_REGDOM_TYPE_CUSTOM_WORLD:
+                       data.channel_list_changed.type =
+                               REGDOM_TYPE_CUSTOM_WORLD;
+                       break;
+               case NL80211_REGDOM_TYPE_INTERSECTION:
+                       data.channel_list_changed.type =
+                               REGDOM_TYPE_INTERSECTION;
+                       break;
+               }
+       }
+
+       if (tb[NL80211_ATTR_REG_ALPHA2]) {
+               os_strlcpy(data.channel_list_changed.alpha2,
+                          nla_get_string(tb[NL80211_ATTR_REG_ALPHA2]),
+                          sizeof(data.channel_list_changed.alpha2));
+               wpa_printf(MSG_DEBUG, " * alpha2=%s",
+                          data.channel_list_changed.alpha2);
+       }
+
+       wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED, &data);
+}
+
+
 static void do_process_drv_event(struct i802_bss *bss, int cmd,
                                 struct nlattr **tb)
 {
@@ -3008,34 +3071,7 @@ static void do_process_drv_event(struct i802_bss *bss, int cmd,
                nl80211_cqm_event(drv, tb);
                break;
        case NL80211_CMD_REG_CHANGE:
-               wpa_printf(MSG_DEBUG, "nl80211: Regulatory domain change");
-               if (tb[NL80211_ATTR_REG_INITIATOR] == NULL)
-                       break;
-               os_memset(&data, 0, sizeof(data));
-               switch (nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR])) {
-               case NL80211_REGDOM_SET_BY_CORE:
-                       data.channel_list_changed.initiator =
-                               REGDOM_SET_BY_CORE;
-                       break;
-               case NL80211_REGDOM_SET_BY_USER:
-                       data.channel_list_changed.initiator =
-                               REGDOM_SET_BY_USER;
-                       break;
-               case NL80211_REGDOM_SET_BY_DRIVER:
-                       data.channel_list_changed.initiator =
-                               REGDOM_SET_BY_DRIVER;
-                       break;
-               case NL80211_REGDOM_SET_BY_COUNTRY_IE:
-                       data.channel_list_changed.initiator =
-                               REGDOM_SET_BY_COUNTRY_IE;
-                       break;
-               default:
-                       wpa_printf(MSG_DEBUG, "nl80211: Unknown reg change initiator %d received",
-                                  nla_get_u8(tb[NL80211_ATTR_REG_INITIATOR]));
-                       break;
-               }
-               wpa_supplicant_event(drv->ctx, EVENT_CHANNEL_LIST_CHANGED,
-                                    &data);
+               nl80211_reg_change_event(drv, tb);
                break;
        case NL80211_CMD_REG_BEACON_HINT:
                wpa_printf(MSG_DEBUG, "nl80211: Regulatory beacon hint");
index adcdf01dfc60cc33b5f96043dabdcb7c43f88584..cad0938c56af444a4faa1c20c404ee9f89fa5ba8 100644 (file)
@@ -2720,10 +2720,52 @@ static void wpas_event_deauth(struct wpa_supplicant *wpa_s,
 }
 
 
-static void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s)
+static const char * reg_init_str(enum reg_change_initiator init)
+{
+       switch (init) {
+       case REGDOM_SET_BY_CORE:
+               return "CORE";
+       case REGDOM_SET_BY_USER:
+               return "USER";
+       case REGDOM_SET_BY_DRIVER:
+               return "DRIVER";
+       case REGDOM_SET_BY_COUNTRY_IE:
+               return "COUNTRY_IE";
+       case REGDOM_BEACON_HINT:
+               return "BEACON_HINT";
+       }
+       return "?";
+}
+
+
+static const char * reg_type_str(enum reg_type type)
+{
+       switch (type) {
+       case REGDOM_TYPE_UNKNOWN:
+               return "UNKNOWN";
+       case REGDOM_TYPE_COUNTRY:
+               return "COUNTRY";
+       case REGDOM_TYPE_WORLD:
+               return "WORLD";
+       case REGDOM_TYPE_CUSTOM_WORLD:
+               return "CUSTOM_WORLD";
+       case REGDOM_TYPE_INTERSECTION:
+               return "INTERSECTION";
+       }
+       return "?";
+}
+
+
+static void wpa_supplicant_update_channel_list(
+       struct wpa_supplicant *wpa_s, struct channel_list_changed *info)
 {
        struct wpa_supplicant *ifs;
 
+       wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REGDOM_CHANGE "init=%s type=%s%s%s",
+               reg_init_str(info->type), reg_type_str(info->type),
+               info->alpha2[0] ? " alpha2=" : "",
+               info->alpha2[0] ? info->alpha2 : "");
+
        if (wpa_s->drv_priv == NULL)
                return; /* Ignore event during drv initialization */
 
@@ -3326,7 +3368,8 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
                wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED);
                break;
        case EVENT_CHANNEL_LIST_CHANGED:
-               wpa_supplicant_update_channel_list(wpa_s);
+               wpa_supplicant_update_channel_list(
+                       wpa_s, &data->channel_list_changed);
                break;
        case EVENT_INTERFACE_UNAVAILABLE:
 #ifdef CONFIG_P2P