p2p_invitation.c revision 252726
118334Speter/* 290075Sobrien * Wi-Fi Direct - P2P Invitation procedure 390075Sobrien * Copyright (c) 2010, Atheros Communications 418334Speter * 518334Speter * This software may be distributed under the terms of the BSD license. 618334Speter * See README for more details. 790075Sobrien */ 818334Speter 990075Sobrien#include "includes.h" 1090075Sobrien 1190075Sobrien#include "common.h" 1290075Sobrien#include "common/ieee802_11_defs.h" 1318334Speter#include "p2p_i.h" 1490075Sobrien#include "p2p.h" 1590075Sobrien 1690075Sobrien 1790075Sobrienstatic struct wpabuf * p2p_build_invitation_req(struct p2p_data *p2p, 1818334Speter struct p2p_device *peer, 1918334Speter const u8 *go_dev_addr) 2090075Sobrien{ 2190075Sobrien struct wpabuf *buf; 2290075Sobrien u8 *len; 2318334Speter const u8 *dev_addr; 2418334Speter size_t extra = 0; 2518334Speter 2618334Speter#ifdef CONFIG_WIFI_DISPLAY 2718334Speter struct wpabuf *wfd_ie = p2p->wfd_ie_invitation; 2818334Speter if (wfd_ie && p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO) { 2918334Speter size_t i; 3018334Speter for (i = 0; i < p2p->num_groups; i++) { 3118334Speter struct p2p_group *g = p2p->groups[i]; 3218334Speter struct wpabuf *ie; 3318334Speter if (os_memcmp(p2p_group_get_interface_addr(g), 3418334Speter p2p->inv_bssid, ETH_ALEN) != 0) 3518334Speter continue; 3618334Speter ie = p2p_group_get_wfd_ie(g); 3718334Speter if (ie) { 3818334Speter wfd_ie = ie; 3918334Speter break; 4018334Speter } 4118334Speter } 4218334Speter } 4318334Speter if (wfd_ie) 4418334Speter extra = wpabuf_len(wfd_ie); 4518334Speter#endif /* CONFIG_WIFI_DISPLAY */ 4618334Speter 4718334Speter buf = wpabuf_alloc(1000 + extra); 4818334Speter if (buf == NULL) 4918334Speter return NULL; 5018334Speter 5118334Speter peer->dialog_token++; 5218334Speter if (peer->dialog_token == 0) 5318334Speter peer->dialog_token = 1; 5418334Speter p2p_buf_add_public_action_hdr(buf, P2P_INVITATION_REQ, 5518334Speter peer->dialog_token); 5618334Speter 5718334Speter len = p2p_buf_add_ie_hdr(buf); 5818334Speter if (p2p->inv_role == P2P_INVITE_ROLE_ACTIVE_GO || !p2p->inv_persistent) 5990075Sobrien p2p_buf_add_config_timeout(buf, 0, 0); 6018334Speter else 6118334Speter p2p_buf_add_config_timeout(buf, p2p->go_timeout, 6218334Speter p2p->client_timeout); 6318334Speter p2p_buf_add_invitation_flags(buf, p2p->inv_persistent ? 6418334Speter P2P_INVITATION_FLAGS_TYPE : 0); 6552284Sobrien p2p_buf_add_operating_channel(buf, p2p->cfg->country, 6652284Sobrien p2p->op_reg_class, p2p->op_channel); 6752284Sobrien if (p2p->inv_bssid_set) 6852284Sobrien p2p_buf_add_group_bssid(buf, p2p->inv_bssid); 6918334Speter p2p_buf_add_channel_list(buf, p2p->cfg->country, &p2p->channels); 7018334Speter if (go_dev_addr) 7118334Speter dev_addr = go_dev_addr; 7218334Speter else if (p2p->inv_role == P2P_INVITE_ROLE_CLIENT) 7318334Speter dev_addr = peer->info.p2p_device_addr; 7418334Speter else 7518334Speter dev_addr = p2p->cfg->dev_addr; 7618334Speter p2p_buf_add_group_id(buf, dev_addr, p2p->inv_ssid, p2p->inv_ssid_len); 7718334Speter p2p_buf_add_device_info(buf, p2p, peer); 7818334Speter p2p_buf_update_ie_hdr(buf, len); 7918334Speter 8018334Speter#ifdef CONFIG_WIFI_DISPLAY 8118334Speter if (wfd_ie) 8218334Speter wpabuf_put_buf(buf, wfd_ie); 8318334Speter#endif /* CONFIG_WIFI_DISPLAY */ 8418334Speter 8518334Speter return buf; 8618334Speter} 8718334Speter 8818334Speter 8918334Speterstatic struct wpabuf * p2p_build_invitation_resp(struct p2p_data *p2p, 9018334Speter struct p2p_device *peer, 9118334Speter u8 dialog_token, u8 status, 9218334Speter const u8 *group_bssid, 9318334Speter u8 reg_class, u8 channel, 9418334Speter struct p2p_channels *channels) 9518334Speter{ 9618334Speter struct wpabuf *buf; 9718334Speter u8 *len; 9818334Speter size_t extra = 0; 9918334Speter 10018334Speter#ifdef CONFIG_WIFI_DISPLAY 10118334Speter struct wpabuf *wfd_ie = p2p->wfd_ie_invitation; 10218334Speter if (wfd_ie && group_bssid) { 10318334Speter size_t i; 10418334Speter for (i = 0; i < p2p->num_groups; i++) { 10518334Speter struct p2p_group *g = p2p->groups[i]; 10618334Speter struct wpabuf *ie; 10718334Speter if (os_memcmp(p2p_group_get_interface_addr(g), 10818334Speter group_bssid, ETH_ALEN) != 0) 10918334Speter continue; 11018334Speter ie = p2p_group_get_wfd_ie(g); 11118334Speter if (ie) { 11218334Speter wfd_ie = ie; 11318334Speter break; 11418334Speter } 11518334Speter } 11618334Speter } 11718334Speter if (wfd_ie) 11818334Speter extra = wpabuf_len(wfd_ie); 11918334Speter#endif /* CONFIG_WIFI_DISPLAY */ 12018334Speter 12190075Sobrien buf = wpabuf_alloc(1000 + extra); 12218334Speter if (buf == NULL) 12318334Speter return NULL; 12450397Sobrien 12552284Sobrien p2p_buf_add_public_action_hdr(buf, P2P_INVITATION_RESP, 12618334Speter dialog_token); 12790075Sobrien 12850397Sobrien len = p2p_buf_add_ie_hdr(buf); 12990075Sobrien p2p_buf_add_status(buf, status); 13018334Speter p2p_buf_add_config_timeout(buf, 0, 0); /* FIX */ 13118334Speter if (reg_class && channel) 13218334Speter p2p_buf_add_operating_channel(buf, p2p->cfg->country, 13318334Speter reg_class, channel); 13418334Speter if (group_bssid) 13518334Speter p2p_buf_add_group_bssid(buf, group_bssid); 13618334Speter if (channels) 13718334Speter p2p_buf_add_channel_list(buf, p2p->cfg->country, channels); 13818334Speter p2p_buf_update_ie_hdr(buf, len); 13918334Speter 14052284Sobrien#ifdef CONFIG_WIFI_DISPLAY 14190075Sobrien if (wfd_ie) 14290075Sobrien wpabuf_put_buf(buf, wfd_ie); 14318334Speter#endif /* CONFIG_WIFI_DISPLAY */ 14418334Speter 14518334Speter return buf; 14618334Speter} 14718334Speter 14818334Speter 14918334Spetervoid p2p_process_invitation_req(struct p2p_data *p2p, const u8 *sa, 15018334Speter const u8 *data, size_t len, int rx_freq) 15118334Speter{ 15218334Speter struct p2p_device *dev; 15318334Speter struct p2p_message msg; 15418334Speter struct wpabuf *resp = NULL; 15518334Speter u8 status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE; 15618334Speter int freq; 15718334Speter int go = 0; 15818334Speter u8 group_bssid[ETH_ALEN], *bssid; 15918334Speter int op_freq = 0; 16018334Speter u8 reg_class = 0, channel = 0; 16118334Speter struct p2p_channels intersection, *channels = NULL; 16218334Speter int persistent; 16318334Speter 16418334Speter os_memset(group_bssid, 0, sizeof(group_bssid)); 16518334Speter 16618334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 16718334Speter "P2P: Received Invitation Request from " MACSTR " (freq=%d)", 16818334Speter MAC2STR(sa), rx_freq); 16918334Speter 17018334Speter if (p2p_parse(data, len, &msg)) 17118334Speter return; 17218334Speter 17318334Speter dev = p2p_get_device(p2p, sa); 17418334Speter if (dev == NULL || (dev->flags & P2P_DEV_PROBE_REQ_ONLY)) { 17518334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 17618334Speter "P2P: Invitation Request from unknown peer " 17718334Speter MACSTR, MAC2STR(sa)); 17818334Speter 17918334Speter if (p2p_add_device(p2p, sa, rx_freq, 0, 0, data + 1, len - 1, 18018334Speter 0)) { 18190075Sobrien wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 18290075Sobrien "P2P: Invitation Request add device failed " 18352284Sobrien MACSTR, MAC2STR(sa)); 18490075Sobrien status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE; 18590075Sobrien goto fail; 18690075Sobrien } 18790075Sobrien 18890075Sobrien dev = p2p_get_device(p2p, sa); 18990075Sobrien if (dev == NULL) { 19090075Sobrien wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 19190075Sobrien "P2P: Reject Invitation Request from unknown " 19290075Sobrien "peer " MACSTR, MAC2STR(sa)); 19390075Sobrien status = P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE; 19490075Sobrien goto fail; 19590075Sobrien } 19690075Sobrien } 19790075Sobrien 19890075Sobrien if (!msg.group_id || !msg.channel_list) { 19990075Sobrien wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 20090075Sobrien "P2P: Mandatory attribute missing in Invitation " 20190075Sobrien "Request from " MACSTR, MAC2STR(sa)); 20290075Sobrien status = P2P_SC_FAIL_INVALID_PARAMS; 20390075Sobrien goto fail; 20418334Speter } 20518334Speter 20618334Speter if (msg.invitation_flags) 20718334Speter persistent = *msg.invitation_flags & P2P_INVITATION_FLAGS_TYPE; 20890075Sobrien else { 20918334Speter /* Invitation Flags is a mandatory attribute starting from P2P 21018334Speter * spec 1.06. As a backwards compatibility mechanism, assume 21118334Speter * the request was for a persistent group if the attribute is 21218334Speter * missing. 21390075Sobrien */ 21490075Sobrien wpa_printf(MSG_DEBUG, "P2P: Mandatory Invitation Flags " 21590075Sobrien "attribute missing from Invitation Request"); 21690075Sobrien persistent = 1; 21790075Sobrien } 21890075Sobrien 21990075Sobrien if (p2p_peer_channels_check(p2p, &p2p->cfg->channels, dev, 22090075Sobrien msg.channel_list, msg.channel_list_len) < 22190075Sobrien 0) { 22290075Sobrien wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 22352284Sobrien "P2P: No common channels found"); 22490075Sobrien status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 22590075Sobrien goto fail; 22690075Sobrien } 22790075Sobrien 22890075Sobrien if (p2p->cfg->invitation_process) { 22918334Speter status = p2p->cfg->invitation_process( 23018334Speter p2p->cfg->cb_ctx, sa, msg.group_bssid, msg.group_id, 23118334Speter msg.group_id + ETH_ALEN, msg.group_id_len - ETH_ALEN, 23218334Speter &go, group_bssid, &op_freq, persistent); 23318334Speter } 23418334Speter 23518334Speter if (op_freq) { 23618334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Invitation " 23718334Speter "processing forced frequency %d MHz", op_freq); 23818334Speter if (p2p_freq_to_channel(p2p->cfg->country, op_freq, 23918334Speter ®_class, &channel) < 0) { 24018334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 24118334Speter "P2P: Unknown forced freq %d MHz from " 24218334Speter "invitation_process()", op_freq); 24318334Speter status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 24418334Speter goto fail; 24518334Speter } 24618334Speter 24718334Speter p2p_channels_intersect(&p2p->cfg->channels, &dev->channels, 24818334Speter &intersection); 24918334Speter if (!p2p_channels_includes(&intersection, reg_class, channel)) 25018334Speter { 25118334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 25218334Speter "P2P: forced freq %d MHz not in the supported " 25318334Speter "channels interaction", op_freq); 25418334Speter status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 25518334Speter goto fail; 25618334Speter } 25718334Speter 25818334Speter if (status == P2P_SC_SUCCESS) 25918334Speter channels = &intersection; 26018334Speter } else { 26118334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 26218334Speter "P2P: No forced channel from invitation processing - " 26318334Speter "figure out best one to use"); 26418334Speter 26518334Speter p2p_channels_intersect(&p2p->cfg->channels, &dev->channels, 26618334Speter &intersection); 26718334Speter /* Default to own configuration as a starting point */ 26818334Speter p2p->op_reg_class = p2p->cfg->op_reg_class; 26918334Speter p2p->op_channel = p2p->cfg->op_channel; 27018334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Own default " 27118334Speter "op_class %d channel %d", 27218334Speter p2p->op_reg_class, p2p->op_channel); 27318334Speter 27418334Speter /* Use peer preference if specified and compatible */ 27518334Speter if (msg.operating_channel) { 27618334Speter int req_freq; 27718334Speter req_freq = p2p_channel_to_freq( 27818334Speter (const char *) msg.operating_channel, 27918334Speter msg.operating_channel[3], 28018334Speter msg.operating_channel[4]); 28118334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Peer " 28218334Speter "operating channel preference: %d MHz", 28318334Speter req_freq); 28418334Speter if (req_freq > 0 && 28518334Speter p2p_channels_includes(&intersection, 28618334Speter msg.operating_channel[3], 28718334Speter msg.operating_channel[4])) { 28818334Speter p2p->op_reg_class = msg.operating_channel[3]; 28918334Speter p2p->op_channel = msg.operating_channel[4]; 29018334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 29118334Speter "P2P: Use peer preference op_class %d " 29218334Speter "channel %d", 29318334Speter p2p->op_reg_class, p2p->op_channel); 29450397Sobrien } else { 29518334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 29618334Speter "P2P: Cannot use peer channel " 29718334Speter "preference"); 29818334Speter } 29918334Speter } 30018334Speter 30118334Speter if (!p2p_channels_includes(&intersection, p2p->op_reg_class, 30218334Speter p2p->op_channel)) { 30318334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 30490075Sobrien "P2P: Initially selected channel (op_class %d " 30590075Sobrien "channel %d) not in channel intersection - try " 30618334Speter "to reselect", 30718334Speter p2p->op_reg_class, p2p->op_channel); 30818334Speter p2p_reselect_channel(p2p, &intersection); 30918334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 31018334Speter "P2P: Re-selection result: op_class %d " 31118334Speter "channel %d", 31218334Speter p2p->op_reg_class, p2p->op_channel); 31318334Speter if (!p2p_channels_includes(&intersection, 31418334Speter p2p->op_reg_class, 31518334Speter p2p->op_channel)) { 31650397Sobrien wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 31718334Speter "P2P: Peer does not support selected " 31818334Speter "operating channel (reg_class=%u " 31918334Speter "channel=%u)", 32018334Speter p2p->op_reg_class, p2p->op_channel); 32118334Speter status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 32290075Sobrien goto fail; 32390075Sobrien } 32418334Speter } 32518334Speter 32618334Speter op_freq = p2p_channel_to_freq(p2p->cfg->country, 32718334Speter p2p->op_reg_class, 32818334Speter p2p->op_channel); 32918334Speter if (op_freq < 0) { 33018334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 33118334Speter "P2P: Unknown operational channel " 33218334Speter "(country=%c%c reg_class=%u channel=%u)", 33318334Speter p2p->cfg->country[0], p2p->cfg->country[1], 33418334Speter p2p->op_reg_class, p2p->op_channel); 33518334Speter status = P2P_SC_FAIL_NO_COMMON_CHANNELS; 33618334Speter goto fail; 33718334Speter } 33818334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Selected operating " 33918334Speter "channel - %d MHz", op_freq); 34018334Speter 34118334Speter if (status == P2P_SC_SUCCESS) { 34218334Speter reg_class = p2p->op_reg_class; 34318334Speter channel = p2p->op_channel; 34418334Speter channels = &intersection; 34518334Speter } 34618334Speter } 34718334Speter 34818334Speterfail: 34918334Speter if (go && status == P2P_SC_SUCCESS && !is_zero_ether_addr(group_bssid)) 35018334Speter bssid = group_bssid; 35118334Speter else 35218334Speter bssid = NULL; 35318334Speter resp = p2p_build_invitation_resp(p2p, dev, msg.dialog_token, status, 35418334Speter bssid, reg_class, channel, channels); 35518334Speter 35690075Sobrien if (resp == NULL) 35718334Speter goto out; 35818334Speter 35918334Speter if (rx_freq > 0) 36018334Speter freq = rx_freq; 36118334Speter else 36218334Speter freq = p2p_channel_to_freq(p2p->cfg->country, 36318334Speter p2p->cfg->reg_class, 36418334Speter p2p->cfg->channel); 36518334Speter if (freq < 0) { 36618334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 36750397Sobrien "P2P: Unknown regulatory class/channel"); 36818334Speter goto out; 36918334Speter } 37018334Speter 37118334Speter /* 37218334Speter * Store copy of invitation data to be used when processing TX status 37318334Speter * callback for the Acton frame. 37418334Speter */ 37518334Speter os_memcpy(p2p->inv_sa, sa, ETH_ALEN); 37618334Speter if (msg.group_bssid) { 37718334Speter os_memcpy(p2p->inv_group_bssid, msg.group_bssid, ETH_ALEN); 37818334Speter p2p->inv_group_bssid_ptr = p2p->inv_group_bssid; 37918334Speter } else 38090075Sobrien p2p->inv_group_bssid_ptr = NULL; 38190075Sobrien if (msg.group_id_len - ETH_ALEN <= 32) { 38290075Sobrien os_memcpy(p2p->inv_ssid, msg.group_id + ETH_ALEN, 38390075Sobrien msg.group_id_len - ETH_ALEN); 38490075Sobrien p2p->inv_ssid_len = msg.group_id_len - ETH_ALEN; 38590075Sobrien } 38690075Sobrien os_memcpy(p2p->inv_go_dev_addr, msg.group_id, ETH_ALEN); 38718334Speter p2p->inv_status = status; 38890075Sobrien p2p->inv_op_freq = op_freq; 38990075Sobrien 39090075Sobrien p2p->pending_action_state = P2P_PENDING_INVITATION_RESPONSE; 39190075Sobrien if (p2p_send_action(p2p, freq, sa, p2p->cfg->dev_addr, 39290075Sobrien p2p->cfg->dev_addr, 39390075Sobrien wpabuf_head(resp), wpabuf_len(resp), 200) < 0) { 39490075Sobrien wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 39590075Sobrien "P2P: Failed to send Action frame"); 39618334Speter } 39790075Sobrien 39890075Sobrienout: 39990075Sobrien wpabuf_free(resp); 40090075Sobrien p2p_parse_free(&msg); 40190075Sobrien} 40290075Sobrien 40390075Sobrien 40490075Sobrienvoid p2p_process_invitation_resp(struct p2p_data *p2p, const u8 *sa, 40590075Sobrien const u8 *data, size_t len) 40690075Sobrien{ 40790075Sobrien struct p2p_device *dev; 40890075Sobrien struct p2p_message msg; 40990075Sobrien 41090075Sobrien wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 41190075Sobrien "P2P: Received Invitation Response from " MACSTR, 41218334Speter MAC2STR(sa)); 41390075Sobrien 41418334Speter dev = p2p_get_device(p2p, sa); 41518334Speter if (dev == NULL) { 41618334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 41718334Speter "P2P: Ignore Invitation Response from unknown peer " 41818334Speter MACSTR, MAC2STR(sa)); 41918334Speter return; 42018334Speter } 42118334Speter 42218334Speter if (dev != p2p->invite_peer) { 42318334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 42418334Speter "P2P: Ignore unexpected Invitation Response from peer " 42518334Speter MACSTR, MAC2STR(sa)); 42618334Speter return; 42718334Speter } 42818334Speter 42918334Speter if (p2p_parse(data, len, &msg)) 43018334Speter return; 43118334Speter 43218334Speter if (!msg.status) { 43318334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 43450397Sobrien "P2P: Mandatory Status attribute missing in " 43518334Speter "Invitation Response from " MACSTR, MAC2STR(sa)); 43618334Speter p2p_parse_free(&msg); 43718334Speter return; 43818334Speter } 43990075Sobrien 44090075Sobrien if (p2p->cfg->invitation_result) 44118334Speter p2p->cfg->invitation_result(p2p->cfg->cb_ctx, *msg.status, 44218334Speter msg.group_bssid); 44350397Sobrien 44418334Speter p2p_parse_free(&msg); 44550397Sobrien 44618334Speter p2p_clear_timeout(p2p); 44718334Speter p2p_set_state(p2p, P2P_IDLE); 44818334Speter p2p->invite_peer = NULL; 44918334Speter} 45050397Sobrien 45118334Speter 45218334Speterint p2p_invite_send(struct p2p_data *p2p, struct p2p_device *dev, 45318334Speter const u8 *go_dev_addr) 45490075Sobrien{ 45518334Speter struct wpabuf *req; 45618334Speter int freq; 45718334Speter 45890075Sobrien freq = dev->listen_freq > 0 ? dev->listen_freq : dev->oper_freq; 45918334Speter if (freq <= 0) { 46018334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 46118334Speter "P2P: No Listen/Operating frequency known for the " 46218334Speter "peer " MACSTR " to send Invitation Request", 46318334Speter MAC2STR(dev->info.p2p_device_addr)); 46418334Speter return -1; 46518334Speter } 46618334Speter 46750397Sobrien req = p2p_build_invitation_req(p2p, dev, go_dev_addr); 46850397Sobrien if (req == NULL) 46950397Sobrien return -1; 47050397Sobrien if (p2p->state != P2P_IDLE) 47150397Sobrien p2p_stop_listen_for_freq(p2p, freq); 47250397Sobrien wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 47350397Sobrien "P2P: Sending Invitation Request"); 47450397Sobrien p2p_set_state(p2p, P2P_INVITE); 47550397Sobrien p2p->pending_action_state = P2P_PENDING_INVITATION_REQUEST; 47650397Sobrien p2p->invite_peer = dev; 47750397Sobrien dev->invitation_reqs++; 47818334Speter if (p2p_send_action(p2p, freq, dev->info.p2p_device_addr, 47918334Speter p2p->cfg->dev_addr, dev->info.p2p_device_addr, 48018334Speter wpabuf_head(req), wpabuf_len(req), 200) < 0) { 48118334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 48218334Speter "P2P: Failed to send Action frame"); 48318334Speter /* Use P2P find to recover and retry */ 48418334Speter p2p_set_timeout(p2p, 0, 0); 48518334Speter } 48618334Speter 48718334Speter wpabuf_free(req); 48818334Speter 48918334Speter return 0; 49018334Speter} 49118334Speter 49290075Sobrien 49318334Spetervoid p2p_invitation_req_cb(struct p2p_data *p2p, int success) 49418334Speter{ 49518334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 49618334Speter "P2P: Invitation Request TX callback: success=%d", success); 49718334Speter 49818334Speter if (p2p->invite_peer == NULL) { 49918334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 50018334Speter "P2P: No pending Invite"); 50190075Sobrien return; 50290075Sobrien } 50390075Sobrien 50490075Sobrien /* 50590075Sobrien * Use P2P find, if needed, to find the other device from its listen 50690075Sobrien * channel. 50790075Sobrien */ 50890075Sobrien p2p_set_state(p2p, P2P_INVITE); 50990075Sobrien p2p_set_timeout(p2p, 0, 100000); 51090075Sobrien} 51190075Sobrien 51290075Sobrien 51390075Sobrienvoid p2p_invitation_resp_cb(struct p2p_data *p2p, int success) 51496263Sobrien{ 51596263Sobrien wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 51690075Sobrien "P2P: Invitation Response TX callback: success=%d", success); 51790075Sobrien p2p->cfg->send_action_done(p2p->cfg->cb_ctx); 51890075Sobrien 51990075Sobrien if (success && p2p->cfg->invitation_received) { 52090075Sobrien p2p->cfg->invitation_received(p2p->cfg->cb_ctx, 52190075Sobrien p2p->inv_sa, 52218334Speter p2p->inv_group_bssid_ptr, 52318334Speter p2p->inv_ssid, p2p->inv_ssid_len, 52418334Speter p2p->inv_go_dev_addr, 52518334Speter p2p->inv_status, 52618334Speter p2p->inv_op_freq); 52718334Speter } 52818334Speter} 52918334Speter 53018334Speter 53118334Speterint p2p_invite(struct p2p_data *p2p, const u8 *peer, enum p2p_invite_role role, 53218334Speter const u8 *bssid, const u8 *ssid, size_t ssid_len, 53318334Speter unsigned int force_freq, const u8 *go_dev_addr, 53418334Speter int persistent_group) 53518334Speter{ 53618334Speter struct p2p_device *dev; 53718334Speter 53818334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 53990075Sobrien "P2P: Request to invite peer " MACSTR " role=%d persistent=%d " 54018334Speter "force_freq=%u", 54118334Speter MAC2STR(peer), role, persistent_group, force_freq); 54218334Speter if (bssid) 54318334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 54418334Speter "P2P: Invitation for BSSID " MACSTR, MAC2STR(bssid)); 54518334Speter if (go_dev_addr) { 54618334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 54718334Speter "P2P: Invitation for GO Device Address " MACSTR, 54818334Speter MAC2STR(go_dev_addr)); 54918334Speter os_memcpy(p2p->invite_go_dev_addr_buf, go_dev_addr, ETH_ALEN); 55018334Speter p2p->invite_go_dev_addr = p2p->invite_go_dev_addr_buf; 55118334Speter } else 55218334Speter p2p->invite_go_dev_addr = NULL; 55318334Speter wpa_hexdump_ascii(MSG_DEBUG, "P2P: Invitation for SSID", 55418334Speter ssid, ssid_len); 55518334Speter 55618334Speter dev = p2p_get_device(p2p, peer); 55718334Speter if (dev == NULL || (dev->listen_freq <= 0 && dev->oper_freq <= 0)) { 55818334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 55950397Sobrien "P2P: Cannot invite unknown P2P Device " MACSTR, 56018334Speter MAC2STR(peer)); 56118334Speter return -1; 56218334Speter } 56318334Speter 56452284Sobrien if (dev->flags & P2P_DEV_GROUP_CLIENT_ONLY) { 56550397Sobrien if (!(dev->info.dev_capab & 56618334Speter P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY)) { 56718334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 56818334Speter "P2P: Cannot invite a P2P Device " MACSTR 56918334Speter " that is in a group and is not discoverable", 57018334Speter MAC2STR(peer)); 57118334Speter } 57218334Speter /* TODO: use device discoverability request through GO */ 57390075Sobrien } 57418334Speter 57552284Sobrien dev->invitation_reqs = 0; 57652284Sobrien 57718334Speter if (force_freq) { 57852284Sobrien if (p2p_freq_to_channel(p2p->cfg->country, force_freq, 57918334Speter &p2p->op_reg_class, &p2p->op_channel) < 58018334Speter 0) { 58118334Speter wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, 58218334Speter "P2P: Unsupported frequency %u MHz", 58318334Speter force_freq); 58418334Speter return -1; 58518334Speter } 58618334Speter p2p->channels.reg_classes = 1; 58718334Speter p2p->channels.reg_class[0].channels = 1; 58818334Speter p2p->channels.reg_class[0].reg_class = p2p->op_reg_class; 58918334Speter p2p->channels.reg_class[0].channel[0] = p2p->op_channel; 59018334Speter } else { 59118334Speter p2p->op_reg_class = p2p->cfg->op_reg_class; 59218334Speter p2p->op_channel = p2p->cfg->op_channel; 59318334Speter os_memcpy(&p2p->channels, &p2p->cfg->channels, 59418334Speter sizeof(struct p2p_channels)); 59518334Speter } 59618334Speter 59718334Speter if (p2p->state != P2P_IDLE) 59818334Speter p2p_stop_find(p2p); 59918334Speter 60018334Speter p2p->inv_role = role; 60118334Speter p2p->inv_bssid_set = bssid != NULL; 60218334Speter if (bssid) 60318334Speter os_memcpy(p2p->inv_bssid, bssid, ETH_ALEN); 60418334Speter os_memcpy(p2p->inv_ssid, ssid, ssid_len); 60518334Speter p2p->inv_ssid_len = ssid_len; 60618334Speter p2p->inv_persistent = persistent_group; 60718334Speter return p2p_invite_send(p2p, dev, go_dev_addr); 60818334Speter} 60990075Sobrien