Update regulatory change to all virtual interface for the phy

wpas_p2p_setup_channels function uses the per interface information
(wpa_s->hw.modes) for setting up the available channel list for P2P
operation, but if a separate P2P interface is used (e.g., p2p0 on
Android), the wpa_s instance for that interface may not get an updated
channel list. This can result in some operations, like "P2P_SET
disallow_freq", using old channel list information (e.g., world roaming
information with passive-scan/no-ibss flags) which was initialized
during the start-up. This could result in P2P functionality using
conflicting or obsolete channel information.

To resolve this issue, update channel list information on regulatory
change events to all of the virtual interfaces sharing the same phy for
which the event is received.

Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
Vinay Krishna Eranna 2013-10-29 23:03:23 +02:00 committed by Jouni Malinen
parent 709f18d501
commit 731ca6364e

View file

@ -2632,6 +2632,52 @@ static void wpas_event_deauth(struct wpa_supplicant *wpa_s,
} }
static void wpa_supplicant_update_channel_list(struct wpa_supplicant *wpa_s)
{
const char *rn, *rn2;
struct wpa_supplicant *ifs;
if (wpa_s->drv_priv == NULL)
return; /* Ignore event during drv initialization */
free_hw_features(wpa_s);
wpa_s->hw.modes = wpa_drv_get_hw_feature_data(
wpa_s, &wpa_s->hw.num_modes, &wpa_s->hw.flags);
#ifdef CONFIG_P2P
wpas_p2p_update_channel_list(wpa_s);
#endif /* CONFIG_P2P */
/*
* Check other interfaces to see if they have the same radio-name. If
* so, they get updated with this same hw mode info.
*/
if (!wpa_s->driver->get_radio_name)
return;
rn = wpa_s->driver->get_radio_name(wpa_s->drv_priv);
if (rn == NULL || rn[0] == '\0')
return;
wpa_dbg(wpa_s, MSG_DEBUG, "Checking for other virtual interfaces "
"sharing same radio (%s) in event_channel_list_change", rn);
for (ifs = wpa_s->global->ifaces; ifs; ifs = ifs->next) {
if (ifs == wpa_s || !ifs->driver->get_radio_name)
continue;
rn2 = ifs->driver->get_radio_name(ifs->drv_priv);
if (rn2 && os_strcmp(rn, rn2) == 0) {
wpa_printf(MSG_DEBUG, "%s: Updating hw mode",
ifs->ifname);
free_hw_features(ifs);
ifs->hw.modes = wpa_drv_get_hw_feature_data(
ifs, &ifs->hw.num_modes, &ifs->hw.flags);
}
}
}
void wpa_supplicant_event(void *ctx, enum wpa_event_type event, void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
union wpa_event_data *data) union wpa_event_data *data)
{ {
@ -3118,16 +3164,7 @@ void wpa_supplicant_event(void *ctx, enum wpa_event_type event,
wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED); wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED);
break; break;
case EVENT_CHANNEL_LIST_CHANGED: case EVENT_CHANNEL_LIST_CHANGED:
if (wpa_s->drv_priv == NULL) wpa_supplicant_update_channel_list(wpa_s);
break; /* Ignore event during drv initialization */
free_hw_features(wpa_s);
wpa_s->hw.modes = wpa_drv_get_hw_feature_data(
wpa_s, &wpa_s->hw.num_modes, &wpa_s->hw.flags);
#ifdef CONFIG_P2P
wpas_p2p_update_channel_list(wpa_s);
#endif /* CONFIG_P2P */
break; break;
case EVENT_INTERFACE_UNAVAILABLE: case EVENT_INTERFACE_UNAVAILABLE:
#ifdef CONFIG_P2P #ifdef CONFIG_P2P