aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/ap/hostapd.h5
-rw-r--r--src/ap/wps_hostapd.c5
-rw-r--r--wpa_supplicant/ap.c15
-rw-r--r--wpa_supplicant/config.c63
-rw-r--r--wpa_supplicant/config_file.c17
-rw-r--r--wpa_supplicant/config_ssid.h15
-rw-r--r--wpa_supplicant/config_winreg.c1
-rw-r--r--wpa_supplicant/p2p_supplicant.c152
-rw-r--r--wpa_supplicant/p2p_supplicant.h3
-rw-r--r--wpa_supplicant/wpa_supplicant.c1
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h2
11 files changed, 277 insertions, 2 deletions
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index cae4756..dbf1b52 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -204,6 +204,11 @@ struct hostapd_data {
void (*setup_complete_cb)(void *ctx);
void *setup_complete_cb_ctx;
+ void (*new_psk_cb)(void *ctx, const u8 *mac_addr,
+ const u8 *p2p_dev_addr, const u8 *psk,
+ size_t psk_len);
+ void *new_psk_cb_ctx;
+
#ifdef CONFIG_P2P
struct p2p_data *p2p;
struct p2p_group *p2p_group;
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 85eae35..eb300f1 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -125,6 +125,11 @@ static int hostapd_wps_new_psk_cb(void *ctx, const u8 *mac_addr,
os_memcpy(p->p2p_dev_addr, p2p_dev_addr, ETH_ALEN);
os_memcpy(p->psk, psk, PMK_LEN);
+ if (hapd->new_psk_cb) {
+ hapd->new_psk_cb(hapd->new_psk_cb_ctx, mac_addr, p2p_dev_addr,
+ psk, psk_len);
+ }
+
p->next = ssid->wpa_psk;
ssid->wpa_psk = p;
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index 99c6d8a..c2fb215 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -367,6 +367,19 @@ static void ap_sta_authorized_cb(void *ctx, const u8 *mac_addr,
}
+#ifdef CONFIG_P2P
+static void ap_new_psk_cb(void *ctx, const u8 *mac_addr, const u8 *p2p_dev_addr,
+ const u8 *psk, size_t psk_len)
+{
+
+ struct wpa_supplicant *wpa_s = ctx;
+ if (wpa_s->ap_iface == NULL || wpa_s->current_ssid == NULL)
+ return;
+ wpas_p2p_new_psk_cb(wpa_s, mac_addr, p2p_dev_addr, psk, psk_len);
+}
+#endif /* CONFIG_P2P */
+
+
static int ap_vendor_action_rx(void *ctx, const u8 *buf, size_t len, int freq)
{
#ifdef CONFIG_P2P
@@ -571,6 +584,8 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
hapd_iface->bss[i]->sta_authorized_cb = ap_sta_authorized_cb;
hapd_iface->bss[i]->sta_authorized_cb_ctx = wpa_s;
#ifdef CONFIG_P2P
+ hapd_iface->bss[i]->new_psk_cb = ap_new_psk_cb;
+ hapd_iface->bss[i]->new_psk_cb_ctx = wpa_s;
hapd_iface->bss[i]->p2p = wpa_s->global->p2p;
hapd_iface->bss[i]->p2p_group = wpas_p2p_group_init(wpa_s,
ssid);
diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c
index a35be51..d666c91 100644
--- a/wpa_supplicant/config.c
+++ b/wpa_supplicant/config.c
@@ -1372,6 +1372,60 @@ static char * wpa_config_write_p2p_client_list(const struct parse_data *data,
}
#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 */
@@ -1539,6 +1593,7 @@ static const struct parse_data ssid_fields[] = {
{ 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) },
@@ -1731,6 +1786,8 @@ static void eap_peer_config_free(struct eap_peer_config *eap)
*/
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);
@@ -1745,6 +1802,11 @@ void wpa_config_free_ssid(struct wpa_ssid *ssid)
#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);
}
@@ -1908,6 +1970,7 @@ struct wpa_ssid * wpa_config_add_network(struct wpa_config *config)
if (ssid == NULL)
return NULL;
ssid->id = id;
+ dl_list_init(&ssid->psk_list);
if (last)
last->next = ssid;
else
diff --git a/wpa_supplicant/config_file.c b/wpa_supplicant/config_file.c
index d03de0b..a2791eb 100644
--- a/wpa_supplicant/config_file.c
+++ b/wpa_supplicant/config_file.c
@@ -158,6 +158,7 @@ static struct wpa_ssid * wpa_config_read_network(FILE *f, int *line, int id)
ssid = os_zalloc(sizeof(*ssid));
if (ssid == NULL)
return NULL;
+ dl_list_init(&ssid->psk_list);
ssid->id = id;
wpa_config_set_network_defaults(ssid);
@@ -604,6 +605,7 @@ 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");
@@ -612,6 +614,20 @@ static void write_p2p_client_list(FILE *f, struct wpa_ssid *ssid)
fprintf(f, "\tp2p_client_list=%s\n", value);
os_free(value);
}
+
+
+static void write_psk_list(FILE *f, struct wpa_ssid *ssid)
+{
+ struct psk_list_entry *psk;
+ char hex[32 * 2 + 1];
+
+ dl_list_for_each(psk, &ssid->psk_list, struct psk_list_entry, list) {
+ wpa_snprintf_hex(hex, sizeof(hex), psk->psk, sizeof(psk->psk));
+ fprintf(f, "\tpsk_list=%s" MACSTR "-%s\n",
+ psk->p2p ? "P2P-" : "", MAC2STR(psk->addr), hex);
+ }
+}
+
#endif /* CONFIG_P2P */
@@ -696,6 +712,7 @@ static void wpa_config_write_network(FILE *f, struct wpa_ssid *ssid)
STR(id_str);
#ifdef CONFIG_P2P
write_p2p_client_list(f, ssid);
+ write_psk_list(f, ssid);
#endif /* CONFIG_P2P */
INT(dtim_period);
INT(beacon_int);
diff --git a/wpa_supplicant/config_ssid.h b/wpa_supplicant/config_ssid.h
index 1340dce..3a44272 100644
--- a/wpa_supplicant/config_ssid.h
+++ b/wpa_supplicant/config_ssid.h
@@ -1,6 +1,6 @@
/*
* WPA Supplicant / Network configuration structures
- * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2003-2013, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
@@ -10,6 +10,7 @@
#define CONFIG_SSID_H
#include "common/defs.h"
+#include "utils/list.h"
#include "eap_peer/eap_config.h"
#define MAX_SSID_LEN 32
@@ -33,6 +34,13 @@
#define DEFAULT_AMPDU_FACTOR -1 /* no change */
#define DEFAULT_AMPDU_DENSITY -1 /* no change */
+struct psk_list_entry {
+ struct dl_list list;
+ u8 addr[ETH_ALEN];
+ u8 psk[32];
+ u8 p2p;
+};
+
/**
* struct wpa_ssid - Network configuration data
*
@@ -456,6 +464,11 @@ struct wpa_ssid {
#endif /* P2P_MAX_STORED_CLIENTS */
/**
+ * psk_list - Per-client PSKs (struct psk_list_entry)
+ */
+ struct dl_list psk_list;
+
+ /**
* p2p_group - Network generated as a P2P group (used internally)
*/
int p2p_group;
diff --git a/wpa_supplicant/config_winreg.c b/wpa_supplicant/config_winreg.c
index 3cf3a91..1b5e237 100644
--- a/wpa_supplicant/config_winreg.c
+++ b/wpa_supplicant/config_winreg.c
@@ -302,6 +302,7 @@ static struct wpa_ssid * wpa_config_read_network(HKEY hk, const TCHAR *netw,
RegCloseKey(nhk);
return NULL;
}
+ dl_list_init(&ssid->psk_list);
ssid->id = id;
wpa_config_set_network_defaults(ssid);
diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c
index f8c8b0a..962236b 100644
--- a/wpa_supplicant/p2p_supplicant.c
+++ b/wpa_supplicant/p2p_supplicant.c
@@ -600,6 +600,11 @@ static int wpas_p2p_store_persistent_group(struct wpa_supplicant *wpa_s,
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 &&
@@ -775,6 +780,10 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s,
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) {
@@ -879,6 +888,44 @@ static void wpas_start_wps_enrollee(struct wpa_supplicant *wpa_s,
}
+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;
@@ -918,10 +965,12 @@ static void p2p_go_configured(void *ctx, void *data)
" [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);
@@ -3970,6 +4019,9 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr,
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;
@@ -4424,6 +4476,9 @@ int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group,
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);
@@ -4515,6 +4570,9 @@ int wpas_p2p_group_add_persistent(struct wpa_supplicant *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);
@@ -5843,6 +5901,11 @@ struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *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)
@@ -5966,3 +6029,90 @@ void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s)
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 */
+}
diff --git a/wpa_supplicant/p2p_supplicant.h b/wpa_supplicant/p2p_supplicant.h
index e7ddb85..f72d563 100644
--- a/wpa_supplicant/p2p_supplicant.h
+++ b/wpa_supplicant/p2p_supplicant.h
@@ -152,6 +152,9 @@ int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s);
int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s,
struct hostapd_hw_modes *mode, u8 channel);
unsigned int wpas_p2p_search_delay(struct wpa_supplicant *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);
#ifdef CONFIG_P2P
void wpas_p2p_continue_after_scan(struct wpa_supplicant *wpa_s);
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 7bfbc0e..c274f3c 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -3480,6 +3480,7 @@ void wpa_supplicant_deinit(struct wpa_global *global)
os_free(global->params.override_ctrl_interface);
os_free(global->p2p_disallow_freq);
+ os_free(global->add_psk);
os_free(global);
wpa_debug_close_syslog();
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index f808f49..ac22c31 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -272,6 +272,8 @@ struct wpa_global {
#define MAX_WFD_SUBELEMS 10
struct wpabuf *wfd_subelem[MAX_WFD_SUBELEMS];
#endif /* CONFIG_WIFI_DISPLAY */
+
+ struct psk_list_entry *add_psk; /* From group formation */
};