diff options
Diffstat (limited to 'src/p2p/p2p.c')
-rw-r--r--[-rwxr-xr-x] | src/p2p/p2p.c | 111 |
1 files changed, 89 insertions, 22 deletions
diff --git a/src/p2p/p2p.c b/src/p2p/p2p.c index 8c768f6..d5884f2 100755..100644 --- a/src/p2p/p2p.c +++ b/src/p2p/p2p.c @@ -2,14 +2,8 @@ * Wi-Fi Direct - P2P module * Copyright (c) 2009-2010, Atheros Communications * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Alternatively, this software may be distributed under the terms of BSD - * license. - * - * See README and COPYING for more details. + * This software may be distributed under the terms of the BSD license. + * See README for more details. */ #include "includes.h" @@ -17,10 +11,8 @@ #include "common.h" #include "eloop.h" #include "common/ieee802_11_defs.h" -#ifdef ANDROID_P2P -#include "common/wpa_ctrl.h" -#endif #include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" #include "wps/wps_i.h" #include "p2p_i.h" #include "p2p.h" @@ -58,11 +50,38 @@ static void p2p_expire_peers(struct p2p_data *p2p) { struct p2p_device *dev, *n; struct os_time now; + size_t i; os_get_time(&now); dl_list_for_each_safe(dev, n, &p2p->devices, struct p2p_device, list) { if (dev->last_seen.sec + P2P_PEER_EXPIRATION_AGE >= now.sec) continue; + + if (p2p->cfg->go_connected && + p2p->cfg->go_connected(p2p->cfg->cb_ctx, + dev->info.p2p_device_addr)) { + /* + * We are connected as a client to a group in which the + * peer is the GO, so do not expire the peer entry. + */ + os_get_time(&dev->last_seen); + continue; + } + + for (i = 0; i < p2p->num_groups; i++) { + if (p2p_group_is_client_connected( + p2p->groups[i], dev->info.p2p_device_addr)) + break; + } + if (i < p2p->num_groups) { + /* + * The peer is connected as a client in a group where + * we are the GO, so do not expire the peer entry. + */ + os_get_time(&dev->last_seen); + continue; + } + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Expiring old peer " "entry " MACSTR, MAC2STR(dev->info.p2p_device_addr)); dl_list_del(&dev->list); @@ -798,8 +817,8 @@ static void p2p_search(struct p2p_data *p2p) } if (p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, type, freq, - p2p->num_req_dev_types, p2p->req_dev_types) < 0) - { + p2p->num_req_dev_types, p2p->req_dev_types, + p2p->find_dev_id)) { wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Scan request failed"); p2p_continue_find(p2p); @@ -898,7 +917,8 @@ static void p2p_free_req_dev_types(struct p2p_data *p2p) int p2p_find(struct p2p_data *p2p, unsigned int timeout, enum p2p_discovery_type type, - unsigned int num_req_dev_types, const u8 *req_dev_types) + unsigned int num_req_dev_types, const u8 *req_dev_types, + const u8 *dev_id) { int res; @@ -920,6 +940,12 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, p2p->num_req_dev_types = num_req_dev_types; } + if (dev_id) { + os_memcpy(p2p->find_dev_id_buf, dev_id, ETH_ALEN); + p2p->find_dev_id = p2p->find_dev_id_buf; + } else + p2p->find_dev_id = NULL; + p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING; p2p_clear_timeout(p2p); p2p->cfg->stop_listen(p2p->cfg->cb_ctx); @@ -936,12 +962,12 @@ int p2p_find(struct p2p_data *p2p, unsigned int timeout, case P2P_FIND_PROGRESSIVE: res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_FULL, 0, p2p->num_req_dev_types, - p2p->req_dev_types); + p2p->req_dev_types, dev_id); break; case P2P_FIND_ONLY_SOCIAL: res = p2p->cfg->p2p_scan(p2p->cfg->cb_ctx, P2P_SCAN_SOCIAL, 0, p2p->num_req_dev_types, - p2p->req_dev_types); + p2p->req_dev_types, dev_id); break; default: return -1; @@ -978,7 +1004,8 @@ int p2p_other_scan_completed(struct p2p_data *p2p) wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Starting pending P2P find " "now that previous scan was completed"); if (p2p_find(p2p, p2p->last_p2p_find_timeout, p2p->find_type, - p2p->num_req_dev_types, p2p->req_dev_types) < 0) + p2p->num_req_dev_types, p2p->req_dev_types, + p2p->find_dev_id) < 0) return 0; return 1; } @@ -989,11 +1016,9 @@ void p2p_stop_find_for_freq(struct p2p_data *p2p, int freq) wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: Stopping find"); eloop_cancel_timeout(p2p_find_timeout, p2p, NULL); p2p_clear_timeout(p2p); + if (p2p->state == P2P_SEARCH) + wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, P2P_EVENT_FIND_STOPPED); p2p_set_state(p2p, P2P_IDLE); -#ifdef ANDROID_P2P - wpa_msg(p2p->cfg->msg_ctx, MSG_INFO, P2P_EVENT_FIND_STOPPED); -#endif - p2p_free_req_dev_types(p2p); p2p->start_after_scan = P2P_AFTER_SCAN_NOTHING; p2p->go_neg_peer = NULL; @@ -2065,6 +2090,32 @@ int p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, char *end) } +int p2p_parse_dev_addr(const u8 *ies, size_t ies_len, u8 *dev_addr) +{ + struct wpabuf *p2p_ie; + struct p2p_message msg; + + p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, + P2P_IE_VENDOR_TYPE); + if (p2p_ie == NULL) + return -1; + os_memset(&msg, 0, sizeof(msg)); + if (p2p_parse_p2p_ie(p2p_ie, &msg)) { + wpabuf_free(p2p_ie); + return -1; + } + + if (msg.p2p_device_addr == NULL) { + wpabuf_free(p2p_ie); + return -1; + } + + os_memcpy(dev_addr, msg.p2p_device_addr, ETH_ALEN); + wpabuf_free(p2p_ie); + return 0; +} + + static void p2p_clear_go_neg(struct p2p_data *p2p) { p2p->go_neg_peer = NULL; @@ -2540,10 +2591,12 @@ void p2p_scan_res_handled(struct p2p_data *p2p) } -void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies) +void p2p_scan_ie(struct p2p_data *p2p, struct wpabuf *ies, const u8 *dev_id) { u8 *len = p2p_buf_add_ie_hdr(ies); p2p_buf_add_capability(ies, p2p->dev_capab, 0); + if (dev_id) + p2p_buf_add_device_id(ies, dev_id); if (p2p->cfg->reg_class && p2p->cfg->channel) p2p_buf_add_listen_channel(ies, p2p->cfg->country, p2p->cfg->reg_class, @@ -2792,6 +2845,20 @@ int p2p_listen_end(struct p2p_data *p2p, unsigned int freq) p2p_connect_send(p2p, p2p->go_neg_peer); return 1; } else if (p2p->state == P2P_SEARCH) { + if (p2p->p2p_scan_running) { + /* + * Search is already in progress. This can happen if + * an Action frame RX is reported immediately after + * the end of a remain-on-channel operation and the + * response frame to that is sent using an offchannel + * operation while in p2p_find. Avoid an attempt to + * restart a scan here. + */ + wpa_msg(p2p->cfg->msg_ctx, MSG_DEBUG, "P2P: p2p_scan " + "already in progress - do not try to start a " + "new one"); + return 1; + } p2p_search(p2p); return 1; } |