P2PS: Callback to send P2PS provisioning events
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
This commit is contained in:
parent
9a58e521ac
commit
5fefce2747
3 changed files with 270 additions and 0 deletions
|
@ -178,6 +178,9 @@ extern "C" {
|
||||||
#define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT "
|
#define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT "
|
||||||
#define P2P_EVENT_REMOVE_AND_REFORM_GROUP "P2P-REMOVE-AND-REFORM-GROUP "
|
#define P2P_EVENT_REMOVE_AND_REFORM_GROUP "P2P-REMOVE-AND-REFORM-GROUP "
|
||||||
|
|
||||||
|
#define P2P_EVENT_P2PS_PROVISION_START "P2PS-PROV-START "
|
||||||
|
#define P2P_EVENT_P2PS_PROVISION_DONE "P2PS-PROV-DONE "
|
||||||
|
|
||||||
#define INTERWORKING_AP "INTERWORKING-AP "
|
#define INTERWORKING_AP "INTERWORKING-AP "
|
||||||
#define INTERWORKING_BLACKLISTED "INTERWORKING-BLACKLISTED "
|
#define INTERWORKING_BLACKLISTED "INTERWORKING-BLACKLISTED "
|
||||||
#define INTERWORKING_NO_MATCH "INTERWORKING-NO-MATCH "
|
#define INTERWORKING_NO_MATCH "INTERWORKING-NO-MATCH "
|
||||||
|
|
|
@ -981,6 +981,20 @@ struct p2p_config {
|
||||||
int (*remove_stale_groups)(void *ctx, const u8 *peer, const u8 *go,
|
int (*remove_stale_groups)(void *ctx, const u8 *peer, const u8 *go,
|
||||||
const u8 *ssid, size_t ssid_len);
|
const u8 *ssid, size_t ssid_len);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* p2ps_prov_complete - P2PS provisioning complete
|
||||||
|
*
|
||||||
|
* When P2PS provisioning completes (successfully or not) we must
|
||||||
|
* transmit all of the results to the upper layers.
|
||||||
|
*/
|
||||||
|
void (*p2ps_prov_complete)(void *ctx, u8 status, const u8 *dev,
|
||||||
|
const u8 *adv_mac, const u8 *ses_mac,
|
||||||
|
const u8 *grp_mac, u32 adv_id, u32 ses_id,
|
||||||
|
u8 conncap, int passwd_id,
|
||||||
|
const u8 *persist_ssid,
|
||||||
|
size_t persist_ssid_size, int response_done,
|
||||||
|
int prov_start, const char *session_info);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* prov_disc_resp_cb - Callback for indicating completion of PD Response
|
* prov_disc_resp_cb - Callback for indicating completion of PD Response
|
||||||
* @ctx: Callback context from cb_ctx
|
* @ctx: Callback context from cb_ctx
|
||||||
|
|
|
@ -477,6 +477,30 @@ static int wpas_p2p_disconnect_safely(struct wpa_supplicant *wpa_s,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Determine total number of clients in active groups where we are the GO */
|
||||||
|
static unsigned int p2p_group_go_member_count(struct wpa_supplicant *wpa_s)
|
||||||
|
{
|
||||||
|
unsigned int count = 0;
|
||||||
|
struct wpa_ssid *s;
|
||||||
|
|
||||||
|
for (wpa_s = wpa_s->global->ifaces; wpa_s; wpa_s = wpa_s->next) {
|
||||||
|
for (s = wpa_s->conf->ssid; s; s = s->next) {
|
||||||
|
wpa_printf(MSG_DEBUG,
|
||||||
|
"P2P: sup:%p ssid:%p disabled:%d p2p:%d mode:%d",
|
||||||
|
wpa_s, s, s->disabled, s->p2p_group,
|
||||||
|
s->mode);
|
||||||
|
if (!s->disabled && s->p2p_group &&
|
||||||
|
s->mode == WPAS_MODE_P2P_GO) {
|
||||||
|
count += p2p_get_group_num_members(
|
||||||
|
wpa_s->p2p_group);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Find an interface for a P2P group where we are the GO */
|
/* Find an interface for a P2P group where we are the GO */
|
||||||
static struct wpa_supplicant *
|
static struct wpa_supplicant *
|
||||||
wpas_p2p_get_go_group(struct wpa_supplicant *wpa_s)
|
wpas_p2p_get_go_group(struct wpa_supplicant *wpa_s)
|
||||||
|
@ -4729,6 +4753,234 @@ static int wpas_remove_stale_groups(void *ctx, const u8 *peer, const u8 *go,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void wpas_p2ps_prov_complete(void *ctx, u8 status, const u8 *dev,
|
||||||
|
const u8 *adv_mac, const u8 *ses_mac,
|
||||||
|
const u8 *grp_mac, u32 adv_id, u32 ses_id,
|
||||||
|
u8 conncap, int passwd_id,
|
||||||
|
const u8 *persist_ssid,
|
||||||
|
size_t persist_ssid_size, int response_done,
|
||||||
|
int prov_start, const char *session_info)
|
||||||
|
{
|
||||||
|
struct wpa_supplicant *wpa_s = ctx;
|
||||||
|
u8 mac[ETH_ALEN];
|
||||||
|
struct wpa_ssid *persistent_go, *stale, *s;
|
||||||
|
int save_config = 0;
|
||||||
|
struct wpa_supplicant *go_wpa_s;
|
||||||
|
|
||||||
|
if (!dev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
os_memset(mac, 0, ETH_ALEN);
|
||||||
|
if (!adv_mac)
|
||||||
|
adv_mac = mac;
|
||||||
|
if (!ses_mac)
|
||||||
|
ses_mac = mac;
|
||||||
|
if (!grp_mac)
|
||||||
|
grp_mac = mac;
|
||||||
|
|
||||||
|
if (prov_start) {
|
||||||
|
if (session_info == NULL) {
|
||||||
|
wpa_msg_global(wpa_s, MSG_INFO,
|
||||||
|
P2P_EVENT_P2PS_PROVISION_START MACSTR
|
||||||
|
" adv_id=%x conncap=%x"
|
||||||
|
" adv_mac=" MACSTR
|
||||||
|
" session=%x mac=" MACSTR
|
||||||
|
" dev_passwd_id=%d",
|
||||||
|
MAC2STR(dev), adv_id, conncap,
|
||||||
|
MAC2STR(adv_mac),
|
||||||
|
ses_id, MAC2STR(ses_mac),
|
||||||
|
passwd_id);
|
||||||
|
} else {
|
||||||
|
wpa_msg_global(wpa_s, MSG_INFO,
|
||||||
|
P2P_EVENT_P2PS_PROVISION_START MACSTR
|
||||||
|
" adv_id=%x conncap=%x"
|
||||||
|
" adv_mac=" MACSTR
|
||||||
|
" session=%x mac=" MACSTR
|
||||||
|
" dev_passwd_id=%d info='%s'",
|
||||||
|
MAC2STR(dev), adv_id, conncap,
|
||||||
|
MAC2STR(adv_mac),
|
||||||
|
ses_id, MAC2STR(ses_mac),
|
||||||
|
passwd_id, session_info);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
go_wpa_s = wpas_p2p_get_go_group(wpa_s);
|
||||||
|
persistent_go = wpas_p2p_get_persistent_go(wpa_s);
|
||||||
|
|
||||||
|
if (status && status != P2P_SC_SUCCESS_DEFERRED) {
|
||||||
|
if (go_wpa_s && !p2p_group_go_member_count(wpa_s))
|
||||||
|
wpas_p2p_group_remove(wpa_s, go_wpa_s->ifname);
|
||||||
|
|
||||||
|
if (persistent_go && !persistent_go->num_p2p_clients) {
|
||||||
|
/* remove empty persistent GO */
|
||||||
|
wpa_config_remove_network(wpa_s->conf,
|
||||||
|
persistent_go->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_msg_global(wpa_s, MSG_INFO,
|
||||||
|
P2P_EVENT_P2PS_PROVISION_DONE MACSTR
|
||||||
|
" status=%d"
|
||||||
|
" adv_id=%x adv_mac=" MACSTR
|
||||||
|
" session=%x mac=" MACSTR,
|
||||||
|
MAC2STR(dev), status,
|
||||||
|
adv_id, MAC2STR(adv_mac),
|
||||||
|
ses_id, MAC2STR(ses_mac));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clean up stale persistent groups with this device */
|
||||||
|
s = wpas_p2p_get_persistent(wpa_s, dev, persist_ssid,
|
||||||
|
persist_ssid_size);
|
||||||
|
for (;;) {
|
||||||
|
stale = wpas_p2p_get_persistent(wpa_s, dev, NULL, 0);
|
||||||
|
if (!stale)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (s && s->ssid_len == stale->ssid_len &&
|
||||||
|
os_memcmp(stale->bssid, s->bssid, ETH_ALEN) == 0 &&
|
||||||
|
os_memcmp(stale->ssid, s->ssid, s->ssid_len) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Remove stale persistent group */
|
||||||
|
if (stale->mode != WPAS_MODE_P2P_GO ||
|
||||||
|
stale->num_p2p_clients <= 1) {
|
||||||
|
wpa_config_remove_network(wpa_s->conf, stale->id);
|
||||||
|
} else {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < stale->num_p2p_clients; i++) {
|
||||||
|
if (os_memcmp(stale->p2p_client_list +
|
||||||
|
i * ETH_ALEN,
|
||||||
|
dev, ETH_ALEN) == 0) {
|
||||||
|
os_memmove(stale->p2p_client_list +
|
||||||
|
i * ETH_ALEN,
|
||||||
|
stale->p2p_client_list +
|
||||||
|
(i + 1) * ETH_ALEN,
|
||||||
|
(stale->num_p2p_clients -
|
||||||
|
i - 1) * ETH_ALEN);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stale->num_p2p_clients--;
|
||||||
|
}
|
||||||
|
save_config = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (save_config)
|
||||||
|
p2p_config_write(wpa_s);
|
||||||
|
|
||||||
|
if (s) {
|
||||||
|
if (go_wpa_s && !p2p_group_go_member_count(wpa_s))
|
||||||
|
wpas_p2p_group_remove(wpa_s, go_wpa_s->ifname);
|
||||||
|
|
||||||
|
if (persistent_go && s != persistent_go &&
|
||||||
|
!persistent_go->num_p2p_clients) {
|
||||||
|
/* remove empty persistent GO */
|
||||||
|
wpa_config_remove_network(wpa_s->conf,
|
||||||
|
persistent_go->id);
|
||||||
|
/* Save config */
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_msg_global(wpa_s, MSG_INFO,
|
||||||
|
P2P_EVENT_P2PS_PROVISION_DONE MACSTR
|
||||||
|
" status=%d"
|
||||||
|
" adv_id=%x adv_mac=" MACSTR
|
||||||
|
" session=%x mac=" MACSTR
|
||||||
|
" persist=%d",
|
||||||
|
MAC2STR(dev), status,
|
||||||
|
adv_id, MAC2STR(adv_mac),
|
||||||
|
ses_id, MAC2STR(ses_mac), s->id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conncap == P2PS_SETUP_GROUP_OWNER) {
|
||||||
|
const char *go_ifname = NULL;
|
||||||
|
if (!go_wpa_s) {
|
||||||
|
wpa_s->global->pending_p2ps_group = 1;
|
||||||
|
|
||||||
|
if (wpa_s->conf->p2p_no_group_iface)
|
||||||
|
go_ifname = wpa_s->ifname;
|
||||||
|
else if (wpa_s->pending_interface_name[0])
|
||||||
|
go_ifname = wpa_s->pending_interface_name;
|
||||||
|
|
||||||
|
if (!go_ifname) {
|
||||||
|
wpas_p2ps_prov_complete(
|
||||||
|
wpa_s, P2P_SC_FAIL_UNKNOWN_GROUP,
|
||||||
|
dev, adv_mac, ses_mac,
|
||||||
|
NULL, adv_id, ses_id, 0, 0,
|
||||||
|
NULL, 0, 0, 0, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If PD Resp complete, start up the GO */
|
||||||
|
if (response_done && persistent_go) {
|
||||||
|
wpas_p2p_group_add_persistent(
|
||||||
|
wpa_s, persistent_go,
|
||||||
|
0, 0, 0, 0, 0, NULL,
|
||||||
|
persistent_go->mode ==
|
||||||
|
WPAS_MODE_P2P_GO ?
|
||||||
|
P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE :
|
||||||
|
0);
|
||||||
|
} else if (response_done) {
|
||||||
|
wpas_p2p_group_add(wpa_s, 1, 0, 0, 0);
|
||||||
|
}
|
||||||
|
} else if (passwd_id == DEV_PW_P2PS_DEFAULT) {
|
||||||
|
go_ifname = go_wpa_s->ifname;
|
||||||
|
|
||||||
|
wpa_dbg(go_wpa_s, MSG_DEBUG,
|
||||||
|
"P2P: Setting PIN-1 For " MACSTR, MAC2STR(dev));
|
||||||
|
wpa_supplicant_ap_wps_pin(go_wpa_s, dev, "12345670",
|
||||||
|
NULL, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
wpa_msg_global(wpa_s, MSG_INFO,
|
||||||
|
P2P_EVENT_P2PS_PROVISION_DONE MACSTR
|
||||||
|
" status=%d conncap=%x"
|
||||||
|
" adv_id=%x adv_mac=" MACSTR
|
||||||
|
" session=%x mac=" MACSTR
|
||||||
|
" dev_passwd_id=%d go=%s",
|
||||||
|
MAC2STR(dev), status, conncap,
|
||||||
|
adv_id, MAC2STR(adv_mac),
|
||||||
|
ses_id, MAC2STR(ses_mac),
|
||||||
|
passwd_id, go_ifname);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (go_wpa_s && !p2p_group_go_member_count(wpa_s))
|
||||||
|
wpas_p2p_group_remove(wpa_s, go_wpa_s->ifname);
|
||||||
|
|
||||||
|
if (persistent_go && !persistent_go->num_p2p_clients) {
|
||||||
|
/* remove empty persistent GO */
|
||||||
|
wpa_config_remove_network(wpa_s->conf, persistent_go->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conncap == P2PS_SETUP_CLIENT) {
|
||||||
|
wpa_msg_global(wpa_s, MSG_INFO,
|
||||||
|
P2P_EVENT_P2PS_PROVISION_DONE MACSTR
|
||||||
|
" status=%d conncap=%x"
|
||||||
|
" adv_id=%x adv_mac=" MACSTR
|
||||||
|
" session=%x mac=" MACSTR
|
||||||
|
" dev_passwd_id=%d join=" MACSTR,
|
||||||
|
MAC2STR(dev), status, conncap,
|
||||||
|
adv_id, MAC2STR(adv_mac),
|
||||||
|
ses_id, MAC2STR(ses_mac),
|
||||||
|
passwd_id, MAC2STR(grp_mac));
|
||||||
|
} else {
|
||||||
|
wpa_msg_global(wpa_s, MSG_INFO,
|
||||||
|
P2P_EVENT_P2PS_PROVISION_DONE MACSTR
|
||||||
|
" status=%d conncap=%x"
|
||||||
|
" adv_id=%x adv_mac=" MACSTR
|
||||||
|
" session=%x mac=" MACSTR
|
||||||
|
" dev_passwd_id=%d",
|
||||||
|
MAC2STR(dev), status, conncap,
|
||||||
|
adv_id, MAC2STR(adv_mac),
|
||||||
|
ses_id, MAC2STR(ses_mac),
|
||||||
|
passwd_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int _wpas_p2p_in_progress(void *ctx)
|
static int _wpas_p2p_in_progress(void *ctx)
|
||||||
{
|
{
|
||||||
struct wpa_supplicant *wpa_s = ctx;
|
struct wpa_supplicant *wpa_s = ctx;
|
||||||
|
@ -4813,6 +5065,7 @@ int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s)
|
||||||
p2p.get_persistent_group = wpas_get_persistent_group;
|
p2p.get_persistent_group = wpas_get_persistent_group;
|
||||||
p2p.get_go_info = wpas_get_go_info;
|
p2p.get_go_info = wpas_get_go_info;
|
||||||
p2p.remove_stale_groups = wpas_remove_stale_groups;
|
p2p.remove_stale_groups = wpas_remove_stale_groups;
|
||||||
|
p2p.p2ps_prov_complete = wpas_p2ps_prov_complete;
|
||||||
p2p.prov_disc_resp_cb = wpas_prov_disc_resp_cb;
|
p2p.prov_disc_resp_cb = wpas_prov_disc_resp_cb;
|
||||||
|
|
||||||
os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
|
os_memcpy(wpa_s->global->p2p_dev_addr, wpa_s->own_addr, ETH_ALEN);
|
||||||
|
|
Loading…
Reference in a new issue