p2p_dbg(p2p, "Invitation Request retry limit reached");
if (p2p->cfg->invitation_result)
p2p->cfg->invitation_result(
- p2p->cfg->cb_ctx, -1, NULL, NULL,
+ p2p->cfg->cb_ctx, -1, NULL, 0, NULL,
+ NULL,
p2p->invite_peer->info.p2p_device_addr,
0, 0, NULL, NULL, 0);
}
}
+int p2p_get_dik_id(struct p2p_data *p2p, const u8 *peer)
+{
+ struct p2p_device *dev;
+
+ dev = p2p_get_device(p2p, peer);
+ if (!dev)
+ return 0;
+
+ return dev->info.dik_id;
+}
+
+
#ifdef CONFIG_PASN
int p2p_config_sae_password(struct p2p_data *p2p, const char *pw)
* used
* @p2p2: Whether invitation request was wrapped in PASN authentication
* received from a P2P2 device
+ * @new_ssid: Pointer to hold new SSID
+ * @new_ssid_len: Length of new SSID buffer in octets
* Returns: Status code (P2P_SC_*)
*
* This optional callback can be used to implement persistent reconnect
size_t ssid_len, int *go, u8 *group_bssid,
int *force_freq, int persistent_group,
const struct p2p_channels *channels,
- int dev_pw_id, bool p2p2);
+ int dev_pw_id, bool p2p2, const u8 **new_ssid,
+ size_t *new_ssid_len);
/**
* invitation_received - Callback on Invitation Request RX
* invitation_result - Callback on Invitation result
* @ctx: Callback context from cb_ctx
* @status: Negotiation result (Status Code)
+ * @new_ssid: New SSID received in invitation response
+ * @new_ssid_len: Length of new SSID received
* @bssid: P2P Group BSSID or %NULL if not received
* @channels: Available operating channels for the group
* @addr: Peer address
* (P2P_SC_SUCCESS) indicating success or -1 to indicate a timeout or a
* local failure in transmitting the Invitation Request.
*/
- void (*invitation_result)(void *ctx, int status, const u8 *bssid,
+ void (*invitation_result)(void *ctx, int status, const u8 *new_ssid,
+ size_t new_ssid_len, const u8 *bssid,
const struct p2p_channels *channels,
const u8 *addr, int freq, int peer_oper_freq,
const u8 *pmkid, const u8 *pmk,
struct wpabuf * p2p_usd_elems(struct p2p_data *p2p);
void p2p_process_usd_elems(struct p2p_data *p2p, const u8 *ies, u16 ies_len,
const u8 *peer_addr, unsigned int freq);
+int p2p_get_dik_id(struct p2p_data *p2p, const u8 *peer);
void p2p_set_pairing_setup(struct p2p_data *p2p, int pairing_setup);
void p2p_set_pairing_cache(struct p2p_data *p2p, int pairing_cache);
int inv_freq;
int inv_peer_oper_freq;
u8 inv_bssid[ETH_ALEN];
+ u8 inv_ssid[SSID_MAX_LEN];
+ size_t inv_ssid_len;
bool inv_all_channels;
};
u8 dialog_token, u8 status,
const u8 *group_bssid,
u8 reg_class, u8 channel,
- struct p2p_channels *channels)
+ struct p2p_channels *channels,
+ const u8 *ssid,
+ size_t ssid_len)
{
struct wpabuf *buf;
u8 *len;
reg_class, channel);
if (group_bssid)
p2p_buf_add_group_bssid(buf, group_bssid);
+
+ if (ssid_len && ssid) {
+ const u8 *dev_addr;
+
+ if (p2p->inv_role == P2P_INVITE_ROLE_CLIENT)
+ dev_addr = peer->info.p2p_device_addr;
+ else
+ dev_addr = p2p->cfg->dev_addr;
+
+ p2p_buf_add_group_id(buf, dev_addr, ssid, ssid_len);
+ }
+
if (channels) {
bool is_6ghz_capab;
u8 group_bssid[ETH_ALEN], *bssid;
int op_freq = 0;
u8 reg_class = 0, channel = 0;
+ const u8 *new_ssid;
+ size_t new_ssid_len = 0;
struct p2p_channels all_channels, intersection, *channels = NULL;
int persistent;
msg.group_id + ETH_ALEN, msg.group_id_len - ETH_ALEN,
&go, group_bssid, &op_freq, persistent, &intersection,
msg.dev_password_id_present ? msg.dev_password_id : -1,
- p2p2);
+ p2p2, &new_ssid, &new_ssid_len);
}
if (go) {
else
bssid = NULL;
resp = p2p_build_invitation_resp(p2p, dev, msg.dialog_token, status,
- bssid, reg_class, channel, channels);
+ bssid, reg_class, channel, channels,
+ new_ssid, new_ssid_len);
/*
* Store copy of invitation data to be used when processing TX status
p2p->inv_group_bssid_ptr = p2p->inv_group_bssid;
} else
p2p->inv_group_bssid_ptr = NULL;
- if (msg.group_id) {
+
+ if (p2p2 && new_ssid_len) {
+ os_memcpy(p2p->inv_ssid, new_ssid, new_ssid_len);
+ p2p->inv_ssid_len = new_ssid_len;
+ os_memcpy(p2p->inv_go_dev_addr, p2p->cfg->dev_addr, ETH_ALEN);
+ } else if (msg.group_id) {
if (msg.group_id_len - ETH_ALEN <= SSID_MAX_LEN) {
os_memcpy(p2p->inv_ssid, msg.group_id + ETH_ALEN,
msg.group_id_len - ETH_ALEN);
if (msg.group_bssid)
os_memcpy(dev->inv_bssid, msg.group_bssid,
ETH_ALEN);
+ if (msg.group_id) {
+ dev->inv_ssid_len = msg.group_id_len - ETH_ALEN;
+ os_memcpy(dev->inv_ssid,
+ msg.group_id + ETH_ALEN,
+ dev->inv_ssid_len);
+ }
goto out;
}
p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status,
+ NULL, 0,
msg.group_bssid, channels, sa,
freq, peer_oper_freq, NULL, NULL,
0);
p2p_dbg(p2p, "Invitation connect: msg status %d", dev->inv_status);
if (p2p->cfg->invitation_result)
p2p->cfg->invitation_result(p2p->cfg->cb_ctx, dev->inv_status,
+ dev->inv_ssid, dev->inv_ssid_len,
dev->inv_bssid, inv_channels,
dev->info.p2p_device_addr,
dev->inv_freq,
p2p_clear_timeout(p2p);
p2p_set_state(p2p, P2P_IDLE);
+ os_memset(dev->inv_ssid, 0, sizeof(dev->inv_ssid));
+ dev->inv_ssid_len = 0;
p2p->invite_peer = NULL;
}
#endif /* CONFIG_PASN */
}
+#ifdef CONFIG_P2P
+/**
+ * wpa_config_get_network_with_dik_id - Get configured network based on ID of
+ * device identity block
+ * @config: Configuration data from wpa_config_read()
+ * @dik_id: DIK ID to search for
+ * Returns: Network configuration or %NULL if not found
+ */
+struct wpa_ssid * wpa_config_get_network_with_dik_id(struct wpa_config *config,
+ int dik_id)
+{
+ struct wpa_ssid *ssid;
+
+ for (ssid = config->ssid; ssid; ssid = ssid->next) {
+ if (ssid->disabled != 2)
+ continue;
+
+ if (ssid->go_dik_id == dik_id)
+ return ssid;
+
+ if (int_array_includes(ssid->p2p2_client_list, dik_id))
+ return ssid;
+ }
+
+ return NULL;
+}
+#endif /* CONFIG_P2P */
+
+
/**
* wpa_config_add_network - Add a new network with empty configuration
* @config: Configuration data from wpa_config_read()
void (*func)(void *, struct wpa_ssid *),
void *arg);
struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id);
+struct wpa_ssid * wpa_config_get_network_with_dik_id(struct wpa_config *config,
+ int dik_id);
struct wpa_ssid * wpa_config_add_network(struct wpa_config *config);
int wpa_config_remove_network(struct wpa_config *config, int id);
void wpa_config_set_network_defaults(struct wpa_ssid *ssid);
size_t ssid_len, int *go, u8 *group_bssid,
int *force_freq, int persistent_group,
const struct p2p_channels *channels,
- int dev_pw_id, bool p2p2)
+ int dev_pw_id, bool p2p2, const u8 **new_ssid,
+ size_t *new_ssid_len)
{
struct wpa_supplicant *wpa_s = ctx;
struct wpa_ssid *s;
break;
}
- if (!s) {
+ if (p2p2) {
+ int dik_id;
+ u8 go_ssid[SSID_MAX_LEN];
+
+ dik_id = p2p_get_dik_id(wpa_s->global->p2p, sa);
+ s = wpa_config_get_network_with_dik_id(wpa_s->conf, dik_id);
+ if (!s) {
+ wpa_printf(MSG_DEBUG, "P2P2: Invitation from " MACSTR
+ " requested reinvocation of an unknown group",
+ MAC2STR(sa));
+ return P2P_SC_FAIL_UNKNOWN_GROUP;
+ }
+ os_free(s->ssid);
+ if (s->mode == WPAS_MODE_P2P_GO) {
+ p2p_build_ssid(wpa_s->global->p2p, go_ssid,
+ &s->ssid_len);
+ s->ssid = os_memdup(go_ssid, s->ssid_len);
+ if (!s->ssid) {
+ s->ssid_len = 0;
+ return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
+ }
+ wpa_printf(MSG_DEBUG,
+ "P2P: New random SSID for the group: %s",
+ wpa_ssid_txt(s->ssid, s->ssid_len));
+ *new_ssid = s->ssid;
+ *new_ssid_len = s->ssid_len;
+ } else {
+ s->ssid_len = ssid_len;
+ s->ssid = os_memdup(ssid, ssid_len);
+ if (!s->ssid) {
+ s->ssid_len = 0;
+ return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE;
+ }
+ }
+ } else if (!s) {
wpa_printf(MSG_DEBUG, "P2P: Invitation from " MACSTR
" requested reinvocation of an unknown group",
MAC2STR(sa));
}
-static void wpas_invitation_result(void *ctx, int status, const u8 *bssid,
+static void wpas_invitation_result(void *ctx, int status, const u8 *new_ssid,
+ size_t new_ssid_len, const u8 *bssid,
const struct p2p_channels *channels,
const u8 *peer, int neg_freq,
int peer_oper_freq, const u8 *pmkid,
return;
}
+ if (new_ssid && new_ssid_len) {
+ os_free(ssid->ssid);
+ ssid->ssid = os_memdup(new_ssid, new_ssid_len);
+ if (!ssid->ssid) {
+ ssid->ssid_len = 0;
+ return;
+ }
+ ssid->ssid_len = new_ssid_len;
+ }
+
/*
* The peer could have missed our ctrl::ack frame for Invitation
* Response and continue retransmitting the frame. To reduce the
else
os_memset(wpa_s->p2p_auth_invite, 0, ETH_ALEN);
+ if (wpa_s->global->p2p && p2p2 && !ssid && peer_addr) {
+ int dik_id;
+
+ dik_id = p2p_get_dik_id(wpa_s->global->p2p, peer_addr);
+ ssid = wpa_config_get_network_with_dik_id(wpa_s->conf, dik_id);
+ if (!ssid) {
+ wpa_printf(MSG_DEBUG,
+ "P2P: Could not find SSID for P2P2 peer "
+ MACSTR, MAC2STR(peer_addr));
+ return -1;
+ }
+ }
+
wpa_s->p2p_persistent_go_freq = freq;
wpa_s->p2p_go_ht40 = !!ht40;
wpa_s->p2p_go_vht = !!vht;