diff --git a/src/ap/ap_drv_ops.c b/src/ap/ap_drv_ops.c index c1861cb8b..ecf60e247 100644 --- a/src/ap/ap_drv_ops.c +++ b/src/ap/ap_drv_ops.c @@ -596,13 +596,13 @@ int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, struct hostapd_hw_modes * hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, - u16 *flags) + u16 *flags, u8 *dfs_domain) { if (hapd->driver == NULL || hapd->driver->get_hw_feature_data == NULL) return NULL; return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes, - flags); + flags, dfs_domain); } diff --git a/src/ap/ap_drv_ops.h b/src/ap/ap_drv_ops.h index aa82eb3a7..b598015a9 100644 --- a/src/ap/ap_drv_ops.h +++ b/src/ap/ap_drv_ops.h @@ -72,7 +72,7 @@ int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, int cw_min, int cw_max, int burst_time); struct hostapd_hw_modes * hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, - u16 *flags); + u16 *flags, u8 *dfs_domain); int hostapd_driver_commit(struct hostapd_data *hapd); int hostapd_drv_none(struct hostapd_data *hapd); int hostapd_driver_scan(struct hostapd_data *hapd, diff --git a/src/ap/hw_features.c b/src/ap/hw_features.c index c677d30f4..da7c3f637 100644 --- a/src/ap/hw_features.c +++ b/src/ap/hw_features.c @@ -78,10 +78,12 @@ int hostapd_get_hw_features(struct hostapd_iface *iface) int i, j; u16 num_modes, flags; struct hostapd_hw_modes *modes; + u8 dfs_domain; if (hostapd_drv_none(hapd)) return -1; - modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags); + modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags, + &dfs_domain); if (modes == NULL) { hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_DEBUG, diff --git a/src/drivers/driver.h b/src/drivers/driver.h index 8103c28e4..9587d063e 100644 --- a/src/drivers/driver.h +++ b/src/drivers/driver.h @@ -65,6 +65,10 @@ /* Filter unicast IP packets encrypted using the GTK */ #define WPA_DATA_FRAME_FILTER_FLAG_GTK BIT(2) +#define HOSTAPD_DFS_REGION_FCC 1 +#define HOSTAPD_DFS_REGION_ETSI 2 +#define HOSTAPD_DFS_REGION_JP 3 + /** * enum reg_change_initiator - Regulatory change initiator */ @@ -2368,12 +2372,13 @@ struct wpa_driver_ops { * @priv: Private driver interface data * @num_modes: Variable for returning the number of returned modes * flags: Variable for returning hardware feature flags + * @dfs: Variable for returning DFS region (HOSTAPD_DFS_REGION_*) * Returns: Pointer to allocated hardware data on success or %NULL on * failure. Caller is responsible for freeing this. */ struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv, u16 *num_modes, - u16 *flags); + u16 *flags, u8 *dfs); /** * send_mlme - Send management frame from MLME diff --git a/src/drivers/driver_hostap.c b/src/drivers/driver_hostap.c index c657ce918..597da335e 100644 --- a/src/drivers/driver_hostap.c +++ b/src/drivers/driver_hostap.c @@ -1088,7 +1088,7 @@ static int hostap_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv, u16 *num_modes, - u16 *flags) + u16 *flags, u8 *dfs) { struct hostapd_hw_modes *mode; int i, clen, rlen; @@ -1103,6 +1103,7 @@ static struct hostapd_hw_modes * hostap_get_hw_feature_data(void *priv, *num_modes = 1; *flags = 0; + *dfs = 0; mode->mode = HOSTAPD_MODE_IEEE80211B; mode->num_channels = 14; diff --git a/src/drivers/driver_nl80211.h b/src/drivers/driver_nl80211.h index 7e1f52c25..3eaccaa9b 100644 --- a/src/drivers/driver_nl80211.h +++ b/src/drivers/driver_nl80211.h @@ -260,7 +260,8 @@ int nl80211_send_monitor(struct wpa_driver_nl80211_data *drv, int wpa_driver_nl80211_capa(struct wpa_driver_nl80211_data *drv); struct hostapd_hw_modes * -nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags); +nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags, + u8 *dfs_domain); int process_global_event(struct nl_msg *msg, void *arg); int process_bss_event(struct nl_msg *msg, void *arg); diff --git a/src/drivers/driver_nl80211_capa.c b/src/drivers/driver_nl80211_capa.c index ea7bac1d6..9aa4e14e6 100644 --- a/src/drivers/driver_nl80211_capa.c +++ b/src/drivers/driver_nl80211_capa.c @@ -1209,6 +1209,7 @@ struct phy_info_arg { struct hostapd_hw_modes *modes; int last_mode, last_chan_idx; int failed; + u8 dfs_domain; }; static void phy_info_ht_capa(struct hostapd_hw_modes *mode, struct nlattr *capa, @@ -1737,6 +1738,20 @@ static void nl80211_reg_rule_vht(struct nlattr *tb[], } +static void nl80211_set_dfs_domain(enum nl80211_dfs_regions region, + u8 *dfs_domain) +{ + if (region == NL80211_DFS_FCC) + *dfs_domain = HOSTAPD_DFS_REGION_FCC; + else if (region == NL80211_DFS_ETSI) + *dfs_domain = HOSTAPD_DFS_REGION_ETSI; + else if (region == NL80211_DFS_JP) + *dfs_domain = HOSTAPD_DFS_REGION_JP; + else + *dfs_domain = 0; +} + + static const char * dfs_domain_name(enum nl80211_dfs_regions region) { switch (region) { @@ -1783,6 +1798,7 @@ static int nl80211_get_reg(struct nl_msg *msg, void *arg) if (tb_msg[NL80211_ATTR_DFS_REGION]) { enum nl80211_dfs_regions dfs_domain; dfs_domain = nla_get_u8(tb_msg[NL80211_ATTR_DFS_REGION]); + nl80211_set_dfs_domain(dfs_domain, &results->dfs_domain); wpa_printf(MSG_DEBUG, "nl80211: Regulatory information - country=%s (%s)", (char *) nla_data(tb_msg[NL80211_ATTR_REG_ALPHA2]), dfs_domain_name(dfs_domain)); @@ -1859,7 +1875,8 @@ static int nl80211_set_regulatory_flags(struct wpa_driver_nl80211_data *drv, struct hostapd_hw_modes * -nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) +nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags, + u8 *dfs_domain) { u32 feat; struct i802_bss *bss = priv; @@ -1871,10 +1888,12 @@ nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) .modes = NULL, .last_mode = -1, .failed = 0, + .dfs_domain = 0, }; *num_modes = 0; *flags = 0; + *dfs_domain = 0; feat = get_nl80211_protocol_features(drv); if (feat & NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP) @@ -1898,6 +1917,9 @@ nl80211_get_hw_feature_data(void *priv, u16 *num_modes, u16 *flags) *num_modes = 0; return NULL; } + + *dfs_domain = result.dfs_domain; + return wpa_driver_nl80211_postprocess_modes(result.modes, num_modes); } diff --git a/wpa_supplicant/driver_i.h b/wpa_supplicant/driver_i.h index 39b08ac09..fa2296b73 100644 --- a/wpa_supplicant/driver_i.h +++ b/wpa_supplicant/driver_i.h @@ -275,11 +275,12 @@ static inline int wpa_drv_mlme_setprotection(struct wpa_supplicant *wpa_s, static inline struct hostapd_hw_modes * wpa_drv_get_hw_feature_data(struct wpa_supplicant *wpa_s, u16 *num_modes, - u16 *flags) + u16 *flags, u8 *dfs_domain) { if (wpa_s->driver->get_hw_feature_data) return wpa_s->driver->get_hw_feature_data(wpa_s->drv_priv, - num_modes, flags); + num_modes, flags, + dfs_domain); return NULL; } diff --git a/wpa_supplicant/events.c b/wpa_supplicant/events.c index e6f6b000e..3a2ec64e6 100644 --- a/wpa_supplicant/events.c +++ b/wpa_supplicant/events.c @@ -3428,6 +3428,7 @@ static void wpa_supplicant_update_channel_list( struct wpa_supplicant *wpa_s, struct channel_list_changed *info) { struct wpa_supplicant *ifs; + u8 dfs_domain; /* * To allow backwards compatibility with higher level layers that @@ -3452,7 +3453,7 @@ static void wpa_supplicant_update_channel_list( ifs->ifname); free_hw_features(ifs); ifs->hw.modes = wpa_drv_get_hw_feature_data( - ifs, &ifs->hw.num_modes, &ifs->hw.flags); + ifs, &ifs->hw.num_modes, &ifs->hw.flags, &dfs_domain); /* Restart PNO/sched_scan with updated channel list */ if (ifs->pno) { diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index b4680eae9..b72e0df38 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -4939,6 +4939,7 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, { struct wpa_driver_capa capa; int capa_res; + u8 dfs_domain; wpa_printf(MSG_DEBUG, "Initializing interface '%s' conf '%s' driver " "'%s' ctrl_interface '%s' bridge '%s'", iface->ifname, @@ -5066,7 +5067,8 @@ static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s, &wpa_s->hw.num_modes, - &wpa_s->hw.flags); + &wpa_s->hw.flags, + &dfs_domain); if (wpa_s->hw.modes) { u16 i;