}
#endif /* NO_CONFIG_WRITE */
+
+static int wpa_config_parse_psk_list(const struct parse_data *data,
+ struct wpa_ssid *ssid, int line,
+ const char *value)
+{
+ struct psk_list_entry *p;
+ const char *pos;
+
+ p = os_zalloc(sizeof(*p));
+ if (p == NULL)
+ return -1;
+
+ pos = value;
+ if (os_strncmp(pos, "P2P-", 4) == 0) {
+ p->p2p = 1;
+ pos += 4;
+ }
+
+ if (hwaddr_aton(pos, p->addr)) {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list address '%s'",
+ line, pos);
+ os_free(p);
+ return -1;
+ }
+ pos += 17;
+ if (*pos != '-') {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list '%s'",
+ line, pos);
+ os_free(p);
+ return -1;
+ }
+ pos++;
+
+ if (hexstr2bin(pos, p->psk, PMK_LEN) || pos[PMK_LEN * 2] != '\0') {
+ wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list PSK '%s'",
+ line, pos);
+ os_free(p);
+ return -1;
+ }
+
+ dl_list_add(&ssid->psk_list, &p->list);
+
+ return 0;
+}
+
+
+#ifndef NO_CONFIG_WRITE
+static char * wpa_config_write_psk_list(const struct parse_data *data,
+ struct wpa_ssid *ssid)
+{
+ return NULL;
+}
+#endif /* NO_CONFIG_WRITE */
+
#endif /* CONFIG_P2P */
/* Helper macros for network block parser */
{ INT_RANGE(ignore_broadcast_ssid, 0, 2) },
#ifdef CONFIG_P2P
{ FUNC(p2p_client_list) },
+ { FUNC(psk_list) },
#endif /* CONFIG_P2P */
#ifdef CONFIG_HT_OVERRIDES
{ INT_RANGE(disable_ht, 0, 1) },
*/
void wpa_config_free_ssid(struct wpa_ssid *ssid)
{
+ struct psk_list_entry *psk;
+
os_free(ssid->ssid);
os_free(ssid->passphrase);
os_free(ssid->ext_psk);
#ifdef CONFIG_HT_OVERRIDES
os_free(ssid->ht_mcs);
#endif /* CONFIG_HT_OVERRIDES */
+ while ((psk = dl_list_first(&ssid->psk_list, struct psk_list_entry,
+ list))) {
+ dl_list_del(&psk->list);
+ os_free(psk);
+ }
os_free(ssid);
}
if (ssid == NULL)
return NULL;
ssid->id = id;
+ dl_list_init(&ssid->psk_list);
if (last)
last->next = ssid;
else
s->ssid_len = ssid->ssid_len;
os_memcpy(s->ssid, ssid->ssid, s->ssid_len);
}
+ if (ssid->mode == WPAS_MODE_P2P_GO && wpa_s->global->add_psk) {
+ dl_list_add(&s->psk_list, &wpa_s->global->add_psk->list);
+ wpa_s->global->add_psk = NULL;
+ changed = 1;
+ }
#ifndef CONFIG_NO_CONFIG_WRITE
if (changed && wpa_s->conf->update_config &&
if (persistent)
network_id = wpas_p2p_store_persistent_group(wpa_s->parent,
ssid, go_dev_addr);
+ else {
+ os_free(wpa_s->global->add_psk);
+ wpa_s->global->add_psk = NULL;
+ }
if (network_id < 0 && ssid)
network_id = ssid->id;
if (!client) {
}
+static void wpas_p2p_add_psk_list(struct wpa_supplicant *wpa_s,
+ struct wpa_ssid *ssid)
+{
+ struct wpa_ssid *persistent;
+ struct psk_list_entry *psk;
+ struct hostapd_data *hapd;
+
+ if (!wpa_s->ap_iface)
+ return;
+
+ persistent = wpas_p2p_get_persistent(wpa_s->parent, NULL, ssid->ssid,
+ ssid->ssid_len);
+ if (persistent == NULL)
+ return;
+
+ hapd = wpa_s->ap_iface->bss[0];
+
+ dl_list_for_each(psk, &persistent->psk_list, struct psk_list_entry,
+ list) {
+ struct hostapd_wpa_psk *hpsk;
+
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Add persistent group PSK entry for "
+ MACSTR " psk=%d",
+ MAC2STR(psk->addr), psk->p2p);
+ hpsk = os_zalloc(sizeof(*hpsk));
+ if (hpsk == NULL)
+ break;
+ os_memcpy(hpsk->psk, psk->psk, PMK_LEN);
+ if (psk->p2p)
+ os_memcpy(hpsk->p2p_dev_addr, psk->addr, ETH_ALEN);
+ else
+ os_memcpy(hpsk->addr, psk->addr, ETH_ALEN);
+ hpsk->next = hapd->conf->ssid.wpa_psk;
+ hapd->conf->ssid.wpa_psk = hpsk;
+ }
+}
+
+
static void p2p_go_configured(void *ctx, void *data)
{
struct wpa_supplicant *wpa_s = ctx;
" [PERSISTENT]" : "");
}
- if (params->persistent_group)
+ if (params->persistent_group) {
network_id = wpas_p2p_store_persistent_group(
wpa_s->parent, ssid,
wpa_s->global->p2p_dev_addr);
+ wpas_p2p_add_psk_list(wpa_s, ssid);
+ }
if (network_id < 0)
network_id = ssid->id;
wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0);
return -1;
}
+ os_free(wpa_s->global->add_psk);
+ wpa_s->global->add_psk = NULL;
+
if (go_intent < 0)
go_intent = wpa_s->conf->p2p_go_intent;
if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL)
return -1;
+ os_free(wpa_s->global->add_psk);
+ wpa_s->global->add_psk = NULL;
+
/* Make sure we are not running find during connection establishment */
wpa_printf(MSG_DEBUG, "P2P: Stop any on-going P2P FIND");
wpas_p2p_stop_find_oper(wpa_s);
return 0;
}
+ os_free(wpa_s->global->add_psk);
+ wpa_s->global->add_psk = NULL;
+
/* Make sure we are not running find during connection establishment */
wpas_p2p_stop_find_oper(wpa_s);
(ssid_len != s->ssid_len ||
os_memcmp(ssid, s->ssid, ssid_len) != 0))
continue;
+ if (addr == NULL) {
+ if (s->mode == WPAS_MODE_P2P_GO)
+ return s;
+ 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)
wpas_p2p_search_delay(wpa_s));
}
}
+
+
+void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr,
+ const u8 *p2p_dev_addr,
+ const u8 *psk, size_t psk_len)
+{
+ struct wpa_ssid *ssid = wpa_s->current_ssid;
+ struct wpa_ssid *persistent;
+ struct psk_list_entry *p;
+
+ if (psk_len != sizeof(p->psk))
+ return;
+
+ if (p2p_dev_addr) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: New PSK for addr=" MACSTR
+ " p2p_dev_addr=" MACSTR,
+ MAC2STR(mac_addr), MAC2STR(p2p_dev_addr));
+ if (is_zero_ether_addr(p2p_dev_addr))
+ p2p_dev_addr = NULL;
+ } else {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: New PSK for addr=" MACSTR,
+ MAC2STR(mac_addr));
+ }
+
+ if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: new_psk_cb during group formation");
+ /* To be added to persistent group once created */
+ if (wpa_s->global->add_psk == NULL) {
+ wpa_s->global->add_psk = os_zalloc(sizeof(*p));
+ if (wpa_s->global->add_psk == NULL)
+ return;
+ }
+ p = wpa_s->global->add_psk;
+ if (p2p_dev_addr) {
+ p->p2p = 1;
+ os_memcpy(p->addr, p2p_dev_addr, ETH_ALEN);
+ } else {
+ p->p2p = 0;
+ os_memcpy(p->addr, mac_addr, ETH_ALEN);
+ }
+ os_memcpy(p->psk, psk, psk_len);
+ return;
+ }
+
+ if (ssid->mode != WPAS_MODE_P2P_GO || !ssid->p2p_persistent_group) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Ignore new_psk_cb on not-persistent GO");
+ return;
+ }
+
+ persistent = wpas_p2p_get_persistent(wpa_s->parent, NULL, ssid->ssid,
+ ssid->ssid_len);
+ if (!persistent) {
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Could not find persistent group information to store the new PSK");
+ return;
+ }
+
+ p = os_zalloc(sizeof(*p));
+ if (p == NULL)
+ return;
+ if (p2p_dev_addr) {
+ p->p2p = 1;
+ os_memcpy(p->addr, p2p_dev_addr, ETH_ALEN);
+ } else {
+ p->p2p = 0;
+ os_memcpy(p->addr, mac_addr, ETH_ALEN);
+ }
+ os_memcpy(p->psk, psk, psk_len);
+
+ if (dl_list_len(&persistent->psk_list) > P2P_MAX_STORED_CLIENTS) {
+ struct psk_list_entry *last;
+ last = dl_list_last(&persistent->psk_list,
+ struct psk_list_entry, list);
+ wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Remove oldest PSK entry for "
+ MACSTR " (p2p=%u) to make room for a new one",
+ MAC2STR(last->addr), last->p2p);
+ dl_list_del(&last->list);
+ os_free(last);
+ }
+
+ dl_list_add(&persistent->psk_list, &p->list);
+
+#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 */
+}