diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h index 5b727685b..c6f620573 100644 --- a/src/ap/hostapd.h +++ b/src/ap/hostapd.h @@ -149,7 +149,7 @@ struct hostapd_data { void *wps_event_cb_ctx; void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr, - int authorized); + int authorized, const u8 *p2p_dev_addr); void *sta_authorized_cb_ctx; void (*setup_complete_cb)(void *ctx); diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index d9c348e0d..27ab25856 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -824,7 +824,7 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, if (hapd->sta_authorized_cb) hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx, - sta->addr, authorized); + sta->addr, authorized, dev_addr); } diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 2d147d1a4..1386d0c02 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -328,9 +328,9 @@ static void ap_wps_event_cb(void *ctx, enum wps_event event, static void ap_sta_authorized_cb(void *ctx, const u8 *mac_addr, - int authorized) + int authorized, const u8 *p2p_dev_addr) { - wpas_notify_sta_authorized(ctx, mac_addr, authorized); + wpas_notify_sta_authorized(ctx, mac_addr, authorized, p2p_dev_addr); } diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index b446a3f44..0fd1f3e0d 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -1351,6 +1351,90 @@ static char * wpa_config_write_wep_key3(const struct parse_data *data, #endif /* NO_CONFIG_WRITE */ +#ifdef CONFIG_P2P + +static int wpa_config_parse_p2p_client_list(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + const char *pos; + u8 *buf, *n, addr[ETH_ALEN]; + size_t count; + + buf = NULL; + count = 0; + + pos = value; + while (pos && *pos) { + while (*pos == ' ') + pos++; + + if (hwaddr_aton(pos, addr)) { + wpa_printf(MSG_ERROR, "Line %d: Invalid " + "p2p_client_list address '%s'.", + line, value); + /* continue anyway */ + } else { + n = os_realloc(buf, (count + 1) * ETH_ALEN); + if (n == NULL) { + os_free(buf); + return -1; + } + buf = n; + os_memcpy(buf + count * ETH_ALEN, addr, ETH_ALEN); + count++; + wpa_hexdump(MSG_MSGDUMP, "p2p_client_list", + addr, ETH_ALEN); + } + + pos = os_strchr(pos, ' '); + } + + os_free(ssid->p2p_client_list); + ssid->p2p_client_list = buf; + ssid->num_p2p_clients = count; + + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_p2p_client_list(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + char *value, *end, *pos; + int res; + size_t i; + + if (ssid->p2p_client_list == NULL || ssid->num_p2p_clients == 0) + return NULL; + + value = os_malloc(20 * ssid->num_p2p_clients); + if (value == NULL) + return NULL; + pos = value; + end = value + 20 * ssid->num_p2p_clients; + + for (i = 0; i < ssid->num_p2p_clients; i++) { + res = os_snprintf(pos, end - pos, MACSTR " ", + MAC2STR(ssid->p2p_client_list + + i * ETH_ALEN)); + if (res < 0 || res >= end - pos) { + os_free(value); + return NULL; + } + pos += res; + } + + if (pos > value) + pos[-1] = '\0'; + + return value; +} +#endif /* NO_CONFIG_WRITE */ + +#endif /* CONFIG_P2P */ + /* Helper macros for network block parser */ #ifdef OFFSET @@ -1511,6 +1595,9 @@ static const struct parse_data ssid_fields[] = { { INT_RANGE(frequency, 0, 10000) }, { INT(wpa_ptk_rekey) }, { STR(bgscan) }, +#ifdef CONFIG_P2P + { FUNC(p2p_client_list) }, +#endif /* CONFIG_P2P */ }; #undef OFFSET @@ -1677,6 +1764,7 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid) os_free(ssid->scan_freq); os_free(ssid->freq_list); os_free(ssid->bgscan); + os_free(ssid->p2p_client_list); os_free(ssid); } diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c index 8ea03abe3..f3a729137 100644 --- a/wpa_supplicant/config_file.c +++ b/wpa_supplicant/config_file.c @@ -493,6 +493,18 @@ static void write_wep_key(FILE *f, int idx, struct wpa_ssid *ssid) } +#ifdef CONFIG_P2P +static void write_p2p_client_list(FILE *f, struct wpa_ssid *ssid) +{ + char *value = wpa_config_get(ssid, "p2p_client_list"); + if (value == NULL) + return; + fprintf(f, "\tp2p_client_list=%s\n", value); + os_free(value); +} +#endif /* CONFIG_P2P */ + + static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) { int i; @@ -567,6 +579,9 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid) INT(ieee80211w); #endif /* CONFIG_IEEE80211W */ STR(id_str); +#ifdef CONFIG_P2P + write_p2p_client_list(f, ssid); +#endif /* CONFIG_P2P */ #undef STR #undef INT diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h index 8419f43d9..8a47c0b9d 100644 --- a/wpa_supplicant/config_ssid.h +++ b/wpa_supplicant/config_ssid.h @@ -386,6 +386,20 @@ struct wpa_ssid { */ int *freq_list; + /** + * p2p_client_list - List of P2P Clients in a persistent group (GO) + * + * This is a list of P2P Clients (P2P Device Address) that have joined + * the persistent group. This is maintained on the GO for persistent + * group entries (disabled == 2). + */ + u8 *p2p_client_list; + + /** + * num_p2p_clients - Number of entries in p2p_client_list + */ + size_t num_p2p_clients; + /** * p2p_group - Network generated as a P2P group (used internally) */ diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c index 71778ae44..6e9b5a9f4 100644 --- a/wpa_supplicant/notify.c +++ b/wpa_supplicant/notify.c @@ -525,9 +525,12 @@ void wpas_notify_p2p_wps_failed(struct wpa_supplicant *wpa_s, static void wpas_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s, - const u8 *sta) + const u8 *sta, + const u8 *p2p_dev_addr) { #ifdef CONFIG_P2P + wpas_p2p_notify_ap_sta_authorized(wpa_s, p2p_dev_addr); + /* * Register a group member object corresponding to this peer and * emit a PeerJoined signal. This will check if it really is a @@ -564,10 +567,11 @@ static void wpas_notify_ap_sta_deauthorized(struct wpa_supplicant *wpa_s, void wpas_notify_sta_authorized(struct wpa_supplicant *wpa_s, - const u8 *mac_addr, int authorized) + const u8 *mac_addr, int authorized, + const u8 *p2p_dev_addr) { if (authorized) - wpas_notify_ap_sta_authorized(wpa_s, mac_addr); + wpas_notify_ap_sta_authorized(wpa_s, mac_addr, p2p_dev_addr); else wpas_notify_ap_sta_deauthorized(wpa_s, mac_addr); } diff --git a/wpa_supplicant/notify.h b/wpa_supplicant/notify.h index 7d4a11e71..236a31ee8 100644 --- a/wpa_supplicant/notify.h +++ b/wpa_supplicant/notify.h @@ -86,7 +86,8 @@ void wpas_notify_suspend(struct wpa_global *global); void wpas_notify_resume(struct wpa_global *global); void wpas_notify_sta_authorized(struct wpa_supplicant *wpa_s, - const u8 *mac_addr, int authorized); + const u8 *mac_addr, int authorized, + const u8 *p2p_dev_addr); void wpas_notify_p2p_device_found(struct wpa_supplicant *wpa_s, const u8 *dev_addr, int new_device); void wpas_notify_p2p_device_lost(struct wpa_supplicant *wpa_s, diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 367fce144..5cb9db613 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -465,6 +465,52 @@ static int wpas_p2p_store_persistent_group(struct wpa_supplicant *wpa_s, } +static void wpas_p2p_add_persistent_group_client(struct wpa_supplicant *wpa_s, + const u8 *addr) +{ + struct wpa_ssid *ssid, *s; + u8 *n; + size_t i; + + ssid = wpa_s->current_ssid; + if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GO || + !ssid->p2p_persistent_group) + return; + + for (s = wpa_s->parent->conf->ssid; s; s = s->next) { + if (s->disabled != 2 || s->mode != WPAS_MODE_P2P_GO) + continue; + + if (s->ssid_len == ssid->ssid_len && + os_memcmp(s->ssid, ssid->ssid, s->ssid_len) == 0) + break; + } + + if (s == NULL) + return; + + for (i = 0; s->p2p_client_list && i < s->num_p2p_clients; i++) { + if (os_memcmp(s->p2p_client_list + i * ETH_ALEN, addr, + ETH_ALEN) == 0) + return; /* already in list */ + } + + n = os_realloc(s->p2p_client_list, + (s->num_p2p_clients + 1) * ETH_ALEN); + if (n == NULL) + return; + os_memcpy(n + s->num_p2p_clients * ETH_ALEN, addr, ETH_ALEN); + s->p2p_client_list = n; + s->num_p2p_clients++; + +#ifndef CONFIG_NO_CONFIG_WRITE + if (wpa_s->parent->conf->update_config && + wpa_config_write(wpa_s->parent->confname, wpa_s->parent->conf)) + wpa_printf(MSG_DEBUG, "P2P: Failed to update configuration"); +#endif /* CONFIG_NO_CONFIG_WRITE */ +} + + static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s, int success) { @@ -4266,12 +4312,31 @@ struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s, const u8 *addr) { struct wpa_ssid *s; + size_t i; for (s = wpa_s->conf->ssid; s; s = s->next) { - if (s->disabled == 2 && - os_memcmp(s->bssid, addr, ETH_ALEN) == 0) - return s; + if (s->disabled != 2) + continue; + if (os_memcmp(s->bssid, addr, ETH_ALEN) == 0) + return s; /* peer is GO in the persistent group */ + if (s->mode != WPAS_MODE_P2P_GO || s->p2p_client_list == NULL) + continue; + for (i = 0; i < s->num_p2p_clients; i++) { + if (os_memcmp(s->p2p_client_list + i * ETH_ALEN, + addr, ETH_ALEN) == 0) + return s; /* peer is P2P client in persistent + * group */ + } } return NULL; } + + +void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s, + const u8 *addr) +{ + if (addr == NULL) + return; + wpas_p2p_add_persistent_group_client(wpa_s, addr); +} diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h index 0a450b6c7..3150f0499 100644 --- a/wpa_supplicant/p2p_supplicant.h +++ b/wpa_supplicant/p2p_supplicant.h @@ -133,5 +133,7 @@ void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s, const u8 *addr); +void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s, + const u8 *addr); #endif /* P2P_SUPPLICANT_H */