X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=wpa_supplicant%2Fp2p_supplicant.c;h=b1fdc2837ff06779db8556ae7fd7907de0c6e2ae;hb=8f4791749302bb3a89b2baef19fc5e6075ec3845;hp=cfe5fff5edde7d8b6ecef426b2776667c4adbd38;hpb=ba307f8528b1242c931a57feb21cd30286126916;p=mech_eap.git diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index cfe5fff..b1fdc28 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -351,6 +351,7 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, int social_channels_freq[] = { 2412, 2437, 2462, 60480 }; size_t ielen; u8 *n, i; + unsigned int bands; if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return -1; @@ -380,28 +381,6 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, if (wps_ie == NULL) goto fail; - ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); - ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen); - if (ies == NULL) { - wpabuf_free(wps_ie); - goto fail; - } - wpabuf_put_buf(ies, wps_ie); - wpabuf_free(wps_ie); - - p2p_scan_ie(wpa_s->global->p2p, ies, dev_id); - - params->p2p_probe = 1; - n = os_malloc(wpabuf_len(ies)); - if (n == NULL) { - wpabuf_free(ies); - goto fail; - } - os_memcpy(n, wpabuf_head(ies), wpabuf_len(ies)); - params->extra_ies = n; - params->extra_ies_len = wpabuf_len(ies); - wpabuf_free(ies); - switch (type) { case P2P_SCAN_SOCIAL: params->freqs = os_calloc(ARRAY_SIZE(social_channels_freq) + 1, @@ -442,6 +421,29 @@ static int wpas_p2p_scan(void *ctx, enum p2p_scan_type type, int freq, break; } + ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); + ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen); + if (ies == NULL) { + wpabuf_free(wps_ie); + goto fail; + } + wpabuf_put_buf(ies, wps_ie); + wpabuf_free(wps_ie); + + bands = wpas_get_bands(wpa_s, params->freqs); + p2p_scan_ie(wpa_s->global->p2p, ies, dev_id, bands); + + params->p2p_probe = 1; + n = os_malloc(wpabuf_len(ies)); + if (n == NULL) { + wpabuf_free(ies); + goto fail; + } + os_memcpy(n, wpabuf_head(ies), wpabuf_len(ies)); + params->extra_ies = n; + params->extra_ies_len = wpabuf_len(ies); + wpabuf_free(ies); + radio_remove_works(wpa_s, "p2p-scan", 0); if (radio_add_work(wpa_s, 0, "p2p-scan", 0, wpas_p2p_trigger_scan_cb, params) < 0) @@ -800,6 +802,8 @@ grp_owner: s = wpas_p2p_get_persistent_go(wpa_s); if (!s && !go_wpa_s && p2p_no_group_iface) { p2p_set_intended_addr(wpa_s->global->p2p, + wpa_s->p2p_mgmt ? + wpa_s->parent->own_addr : wpa_s->own_addr); } else if (!s && !go_wpa_s) { if (wpas_p2p_add_group_interface(wpa_s, @@ -949,6 +953,12 @@ static int wpas_p2p_group_delete(struct wpa_supplicant *wpa_s, return 1; } + /* + * The primary interface was used for P2P group operations, so + * need to reset its p2pdev. + */ + wpa_s->p2pdev = wpa_s->parent; + if (!wpa_s->p2p_go_group_formation_completed) { wpa_s->global->p2p_group_formation = NULL; wpa_s->p2p_in_provisioning = 0; @@ -1066,7 +1076,7 @@ static int wpas_p2p_persistent_group(struct wpa_supplicant *wpa_s, "go_dev_addr=" MACSTR, MAC2STR(bssid), group_capab, MAC2STR(go_dev_addr)); - return group_capab & P2P_GROUP_CAPAB_PERSISTENT_GROUP; + return !!(group_capab & P2P_GROUP_CAPAB_PERSISTENT_GROUP); } @@ -1124,7 +1134,8 @@ static int wpas_p2p_store_persistent_group(struct wpa_supplicant *wpa_s, s->auth_alg = WPA_AUTH_ALG_OPEN; s->key_mgmt = WPA_KEY_MGMT_PSK; s->proto = WPA_PROTO_RSN; - s->pairwise_cipher = WPA_CIPHER_CCMP; + s->pbss = ssid->pbss; + s->pairwise_cipher = ssid->pbss ? WPA_CIPHER_GCMP : WPA_CIPHER_CCMP; s->export_keys = 1; if (ssid->passphrase) { os_free(s->passphrase); @@ -1290,7 +1301,6 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s, int client; int persistent; u8 go_dev_addr[ETH_ALEN]; - int network_id = -1; /* * This callback is likely called for the main interface. Update wpa_s @@ -1365,16 +1375,15 @@ static void wpas_group_formation_completed(struct wpa_supplicant *wpa_s, } if (persistent) - network_id = wpas_p2p_store_persistent_group(wpa_s->p2pdev, - ssid, go_dev_addr); + wpas_p2p_store_persistent_group(wpa_s->p2pdev, + 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) { - wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 0); + wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 0); os_get_reltime(&wpa_s->global->p2p_go_wait_client); } } @@ -1739,7 +1748,6 @@ static void p2p_go_configured(void *ctx, void *data) struct wpa_supplicant *wpa_s = ctx; struct p2p_go_neg_results *params = data; struct wpa_ssid *ssid; - int network_id = -1; wpa_s->ap_configured_cb = NULL; wpa_s->ap_configured_cb_ctx = NULL; @@ -1786,14 +1794,14 @@ static void p2p_go_configured(void *ctx, void *data) os_get_reltime(&wpa_s->global->p2p_go_wait_client); if (params->persistent_group) { - network_id = wpas_p2p_store_persistent_group( + wpas_p2p_store_persistent_group( wpa_s->p2pdev, 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); + + wpas_notify_p2p_group_started(wpa_s, ssid, + params->persistent_group, 0); wpas_p2p_cross_connect_setup(wpa_s); wpas_p2p_set_group_idle_timeout(wpa_s); @@ -1873,7 +1881,7 @@ static void wpas_start_wps_go(struct wpa_supplicant *wpa_s, wpa_config_set_network_defaults(ssid); ssid->temporary = 1; ssid->p2p_group = 1; - ssid->p2p_persistent_group = params->persistent_group; + ssid->p2p_persistent_group = !!params->persistent_group; ssid->mode = group_formation ? WPAS_MODE_P2P_GROUP_FORMATION : WPAS_MODE_P2P_GO; ssid->frequency = params->freq; @@ -1940,7 +1948,12 @@ static void wpas_p2p_clone_config(struct wpa_supplicant *dst, d = dst->conf; s = src->conf; -#define C(n) if (s->n) d->n = os_strdup(s->n) +#define C(n) \ +do { \ + if (s->n && !d->n) \ + d->n = os_strdup(s->n); \ +} while (0) + C(device_name); C(manufacturer); C(model_name); @@ -1968,7 +1981,10 @@ static void wpas_p2p_clone_config(struct wpa_supplicant *dst, d->disable_scan_offload = s->disable_scan_offload; d->passive_scan = s->passive_scan; - if (s->wps_nfc_dh_privkey && s->wps_nfc_dh_pubkey) { + if (s->wps_nfc_dh_privkey && s->wps_nfc_dh_pubkey && + !d->wps_nfc_pw_from_config) { + wpabuf_free(d->wps_nfc_dh_privkey); + wpabuf_free(d->wps_nfc_dh_pubkey); d->wps_nfc_dh_privkey = wpabuf_dup(s->wps_nfc_dh_privkey); d->wps_nfc_dh_pubkey = wpabuf_dup(s->wps_nfc_dh_pubkey); } @@ -2159,6 +2175,7 @@ void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s) static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) { struct wpa_supplicant *wpa_s = ctx; + struct wpa_supplicant *group_wpa_s; if (wpa_s->off_channel_freq || wpa_s->roc_waiting_drv_freq) { wpa_drv_cancel_remain_on_channel(wpa_s); @@ -2211,7 +2228,7 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) } if (wpa_s->create_p2p_iface) { - struct wpa_supplicant *group_wpa_s = + group_wpa_s = wpas_p2p_init_group_interface(wpa_s, res->role_go); if (group_wpa_s == NULL) { wpas_p2p_remove_pending_group_interface(wpa_s); @@ -2220,31 +2237,27 @@ static void wpas_go_neg_completed(void *ctx, struct p2p_go_neg_results *res) wpas_p2p_group_formation_failed(wpa_s, 1); return; } - if (group_wpa_s != wpa_s) { - os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin, - sizeof(group_wpa_s->p2p_pin)); - group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method; - } os_memset(wpa_s->pending_interface_addr, 0, ETH_ALEN); wpa_s->pending_interface_name[0] = '\0'; - group_wpa_s->p2p_in_provisioning = 1; - - if (res->role_go) { - wpas_start_wps_go(group_wpa_s, res, 1); - } else { - os_get_reltime(&group_wpa_s->scan_min_time); - wpas_start_wps_enrollee(group_wpa_s, res); - } } else { - wpa_s->p2p_in_provisioning = 1; - wpa_s->global->p2p_group_formation = wpa_s; + group_wpa_s = wpa_s->parent; + wpa_s->global->p2p_group_formation = group_wpa_s; + if (group_wpa_s != wpa_s) + wpas_p2p_clone_config(group_wpa_s, wpa_s); + } - if (res->role_go) { - wpas_start_wps_go(wpa_s, res, 1); - } else { - os_get_reltime(&wpa_s->scan_min_time); - wpas_start_wps_enrollee(ctx, res); - } + group_wpa_s->p2p_in_provisioning = 1; + group_wpa_s->p2pdev = wpa_s; + if (group_wpa_s != wpa_s) { + os_memcpy(group_wpa_s->p2p_pin, wpa_s->p2p_pin, + sizeof(group_wpa_s->p2p_pin)); + group_wpa_s->p2p_wps_method = wpa_s->p2p_wps_method; + } + if (res->role_go) { + wpas_start_wps_go(group_wpa_s, res, 1); + } else { + os_get_reltime(&group_wpa_s->scan_min_time); + wpas_start_wps_enrollee(group_wpa_s, res); } wpa_s->p2p_long_listen = 0; @@ -2365,6 +2378,10 @@ static void wpas_dev_lost(void *ctx, const u8 *dev_addr) static void wpas_find_stopped(void *ctx) { struct wpa_supplicant *wpa_s = ctx; + + if (wpa_s->p2p_scan_work && wpas_abort_ongoing_scan(wpa_s) < 0) + wpa_printf(MSG_DEBUG, "P2P: Abort ongoing scan failed"); + wpa_msg_global(wpa_s, MSG_INFO, P2P_EVENT_FIND_STOPPED); wpas_notify_p2p_find_stopped(wpa_s); } @@ -2903,7 +2920,11 @@ static u8 wpas_invitation_process(void *ctx, const u8 *sa, const u8 *bssid, "invitation"); return P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE; } - os_memcpy(group_bssid, wpa_s->own_addr, ETH_ALEN); + if (wpa_s->p2p_mgmt) + os_memcpy(group_bssid, wpa_s->parent->own_addr, + ETH_ALEN); + else + os_memcpy(group_bssid, wpa_s->own_addr, ETH_ALEN); } else if (s->mode == WPAS_MODE_P2P_GO) { *go = 1; if (wpas_p2p_add_group_interface(wpa_s, WPA_IF_P2P_GO) < 0) @@ -2985,12 +3006,31 @@ static void wpas_invitation_received(void *ctx, const u8 *sa, const u8 *bssid, MAC2STR(sa), op_freq, wpa_ssid_txt(ssid, ssid_len)); if (s) { int go = s->mode == WPAS_MODE_P2P_GO; + if (go) { + wpa_msg_global(wpa_s, MSG_INFO, + P2P_EVENT_INVITATION_ACCEPTED + "sa=" MACSTR + " persistent=%d freq=%d", + MAC2STR(sa), s->id, op_freq); + } else { + wpa_msg_global(wpa_s, MSG_INFO, + P2P_EVENT_INVITATION_ACCEPTED + "sa=" MACSTR + " persistent=%d", + MAC2STR(sa), s->id); + } wpas_p2p_group_add_persistent( wpa_s, s, go, 0, op_freq, 0, 0, 0, 0, NULL, go ? P2P_MAX_INITIAL_CONN_WAIT_GO_REINVOKE : 0, 1); } else if (bssid) { wpa_s->user_initiated_pd = 0; + wpa_msg_global(wpa_s, MSG_INFO, + P2P_EVENT_INVITATION_ACCEPTED + "sa=" MACSTR " go_dev_addr=" MACSTR + " bssid=" MACSTR " unknown-network", + MAC2STR(sa), MAC2STR(go_dev_addr), + MAC2STR(bssid)); wpas_p2p_join(wpa_s, bssid, go_dev_addr, wpa_s->p2p_wps_method, 0, op_freq, ssid, ssid_len); @@ -3329,7 +3369,7 @@ static int wpas_p2p_get_center_80mhz(struct wpa_supplicant *wpa_s, u8 channel) { u8 center_channels[] = { 42, 58, 106, 122, 138, 155 }; - unsigned int i; + size_t i; if (mode->mode != HOSTAPD_MODE_IEEE80211A) return 0; @@ -3733,6 +3773,7 @@ int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s, return -1; } + p2pdev_wpa_s->p2pdev = p2pdev_wpa_s; wpa_s->pending_interface_name[0] = '\0'; return 0; } @@ -4514,8 +4555,7 @@ static void wpas_p2p_deinit_global(struct wpa_global *global) static int wpas_p2p_create_iface(struct wpa_supplicant *wpa_s) { - if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) && - wpa_s->conf->p2p_no_group_iface) + if (wpa_s->conf->p2p_no_group_iface) return 0; /* separate interface disabled per configuration */ if (wpa_s->drv_flags & (WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE | @@ -4904,6 +4944,7 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq, struct wpabuf *wps_ie, *ies; size_t ielen; int freqs[2] = { 0, 0 }; + unsigned int bands; os_memset(¶ms, 0, sizeof(params)); @@ -4929,22 +4970,6 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq, return; } - ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); - ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen); - if (ies == NULL) { - wpabuf_free(wps_ie); - wpas_p2p_scan_res_join(wpa_s, NULL); - return; - } - wpabuf_put_buf(ies, wps_ie); - wpabuf_free(wps_ie); - - p2p_scan_ie(wpa_s->global->p2p, ies, NULL); - - params.p2p_probe = 1; - params.extra_ies = wpabuf_head(ies); - params.extra_ies_len = wpabuf_len(ies); - if (!freq) { int oper_freq; /* @@ -4961,6 +4986,23 @@ static void wpas_p2p_join_scan_req(struct wpa_supplicant *wpa_s, int freq, params.freqs = freqs; } + ielen = p2p_scan_ie_buf_len(wpa_s->global->p2p); + ies = wpabuf_alloc(wpabuf_len(wps_ie) + ielen); + if (ies == NULL) { + wpabuf_free(wps_ie); + wpas_p2p_scan_res_join(wpa_s, NULL); + return; + } + wpabuf_put_buf(ies, wps_ie); + wpabuf_free(wps_ie); + + bands = wpas_get_bands(wpa_s, freqs); + p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands); + + params.p2p_probe = 1; + params.extra_ies = wpabuf_head(ies); + params.extra_ies_len = wpabuf_len(ies); + /* * Run a scan to update BSS table and start Provision Discovery once * the new scan results become available. @@ -5338,6 +5380,9 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, wpa_s->p2p_pin[sizeof(wpa_s->p2p_pin) - 1] = '\0'; wpa_printf(MSG_DEBUG, "P2P: Randomly generated PIN: %s", wpa_s->p2p_pin); + } else if (wps_method == WPS_P2PS) { + /* Force the P2Ps default PIN to be used */ + os_strlcpy(wpa_s->p2p_pin, "12345670", sizeof(wpa_s->p2p_pin)); } else wpa_s->p2p_pin[0] = '\0'; @@ -5397,7 +5442,10 @@ int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, if_addr = wpa_s->pending_interface_addr; } else { - if_addr = wpa_s->own_addr; + if (wpa_s->p2p_mgmt) + if_addr = wpa_s->parent->own_addr; + else + if_addr = wpa_s->own_addr; os_memset(wpa_s->go_dev_addr, 0, ETH_ALEN); } @@ -5734,6 +5782,7 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, unsigned int cand; unsigned int num, i; int ignore_no_freqs = 0; + int unused_channels = wpas_p2p_num_unused_channels(wpa_s) > 0; os_memset(params, 0, sizeof(*params)); params->role_go = 1; @@ -5790,8 +5839,7 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, } } - if (!ignore_no_freqs && - wpas_p2p_num_unused_channels(wpa_s) <= 0) { + if (!ignore_no_freqs && !unused_channels) { wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on freq (%d MHz) as all the channels are in use", freq); @@ -5806,12 +5854,13 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, } /* consider using one of the shared frequencies */ - if (num) { + if (num && + (!wpa_s->conf->p2p_ignore_shared_freq || !unused_channels)) { cand = wpas_p2p_pick_best_used_freq(wpa_s, freqs, num); if (wpas_p2p_supported_freq_go(wpa_s, channels, cand)) { wpa_printf(MSG_DEBUG, "P2P: Use shared freq (%d MHz) for GO", - freq); + cand); params->freq = cand; goto success; } @@ -5822,15 +5871,14 @@ static int wpas_p2p_init_go_params(struct wpa_supplicant *wpa_s, freqs[i].freq)) { wpa_printf(MSG_DEBUG, "P2P: Use shared freq (%d MHz) for GO", - freq); + freqs[i].freq); params->freq = freqs[i].freq; goto success; } } } - if (!ignore_no_freqs && - wpas_p2p_num_unused_channels(wpa_s) <= 0) { + if (!ignore_no_freqs && !unused_channels) { wpa_printf(MSG_DEBUG, "P2P: Cannot force GO on any of the channels we are already using"); goto fail; @@ -5943,9 +5991,20 @@ wpas_p2p_get_group_iface(struct wpa_supplicant *wpa_s, int addr_allocated, struct wpa_supplicant *group_wpa_s; if (!wpas_p2p_create_iface(wpa_s)) { - wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Use same interface for group " - "operations"); + if (wpa_s->p2p_mgmt) { + /* + * We may be called on the p2p_dev interface which + * cannot be used for group operations, so always use + * the primary interface. + */ + wpa_s->parent->p2pdev = wpa_s; + wpa_s = wpa_s->parent; + } + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P: Use primary interface for group operations"); wpa_s->p2p_first_connection_timeout = 0; + if (wpa_s != wpa_s->p2pdev) + wpas_p2p_clone_config(wpa_s, wpa_s->p2pdev); return wpa_s; } @@ -6059,8 +6118,10 @@ static int wpas_start_p2p_client(struct wpa_supplicant *wpa_s, wpa_config_set_network_defaults(ssid); ssid->temporary = 1; ssid->proto = WPA_PROTO_RSN; - ssid->pairwise_cipher = WPA_CIPHER_CCMP; - ssid->group_cipher = WPA_CIPHER_CCMP; + ssid->pbss = params->pbss; + ssid->pairwise_cipher = params->pbss ? WPA_CIPHER_GCMP : + WPA_CIPHER_CCMP; + ssid->group_cipher = params->pbss ? WPA_CIPHER_GCMP : WPA_CIPHER_CCMP; ssid->key_mgmt = WPA_KEY_MGMT_PSK; ssid->ssid = os_malloc(params->ssid_len); if (ssid->ssid == NULL) { @@ -6257,7 +6318,8 @@ struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s, struct p2p_group *group; struct p2p_group_config *cfg; - if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) + if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL || + !ssid->p2p_group) return NULL; cfg = os_zalloc(sizeof(*cfg)); @@ -6280,6 +6342,8 @@ struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s, cfg->cb_ctx = wpa_s; cfg->ie_update = wpas_p2p_ie_update; cfg->idle_update = wpas_p2p_idle_update; + cfg->ip_addr_alloc = WPA_GET_BE32(wpa_s->p2pdev->conf->ip_addr_start) + != 0; group = p2p_group_init(wpa_s->global->p2p, cfg); if (group == NULL) @@ -6568,6 +6632,12 @@ int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout) if (wpa_s->global->p2p_disabled || wpa_s->global->p2p == NULL) return -1; + if (wpa_s->p2p_lo_started) { + wpa_printf(MSG_DEBUG, + "P2P: Cannot start P2P listen, it is offloaded"); + return -1; + } + wpa_supplicant_cancel_sched_scan(wpa_s); wpas_p2p_clear_pending_action_tx(wpa_s); @@ -6641,7 +6711,7 @@ int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, const u8 *addr, return 0; switch (p2p_probe_req_rx(wpa_s->global->p2p, addr, dst, bssid, - ie, ie_len, rx_freq)) { + ie, ie_len, rx_freq, wpa_s->p2p_lo_started)) { case P2P_PREQ_NOT_P2P: wpas_notify_preq(wpa_s, addr, dst, bssid, ie, ie_len, ssi_signal); @@ -6673,12 +6743,15 @@ void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, const u8 *da, void wpas_p2p_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ies) { + unsigned int bands; + if (wpa_s->global->p2p_disabled) return; if (wpa_s->global->p2p == NULL) return; - p2p_scan_ie(wpa_s->global->p2p, ies, NULL); + bands = wpas_get_bands(wpa_s, NULL); + p2p_scan_ie(wpa_s->global->p2p, ies, NULL, bands); } @@ -6745,7 +6818,9 @@ int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr, return -1; } bssid = wpa_s->pending_interface_addr; - } else + } else if (wpa_s->p2p_mgmt) + bssid = wpa_s->parent->own_addr; + else bssid = wpa_s->own_addr; } else { role = P2P_INVITE_ROLE_CLIENT; @@ -6869,7 +6944,6 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s) { struct wpa_ssid *ssid = wpa_s->current_ssid; u8 go_dev_addr[ETH_ALEN]; - int network_id = -1; int persistent; int freq; u8 ip[3 * 4]; @@ -6928,11 +7002,10 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s) ip_addr); if (persistent) - network_id = wpas_p2p_store_persistent_group(wpa_s->p2pdev, - ssid, go_dev_addr); - if (network_id < 0) - network_id = ssid->id; - wpas_notify_p2p_group_started(wpa_s, ssid, network_id, 1); + wpas_p2p_store_persistent_group(wpa_s->p2pdev, + ssid, go_dev_addr); + + wpas_notify_p2p_group_started(wpa_s, ssid, persistent, 1); } @@ -8313,17 +8386,17 @@ static int wpas_p2p_nfc_auth_join(struct wpa_supplicant *wpa_s, return -1; } - if (wpa_s->parent->p2p_oob_dev_pw_id != + if (wpa_s->p2pdev->p2p_oob_dev_pw_id != DEV_PW_NFC_CONNECTION_HANDOVER && - !wpa_s->parent->p2p_oob_dev_pw) { + !wpa_s->p2pdev->p2p_oob_dev_pw) { wpa_printf(MSG_DEBUG, "P2P: No NFC Dev Pw known"); return -1; } res = wpas_ap_wps_add_nfc_pw( - wpa_s, wpa_s->parent->p2p_oob_dev_pw_id, - wpa_s->parent->p2p_oob_dev_pw, - wpa_s->parent->p2p_peer_oob_pk_hash_known ? - wpa_s->parent->p2p_peer_oob_pubkey_hash : NULL); + wpa_s, wpa_s->p2pdev->p2p_oob_dev_pw_id, + wpa_s->p2pdev->p2p_oob_dev_pw, + wpa_s->p2pdev->p2p_peer_oob_pk_hash_known ? + wpa_s->p2pdev->p2p_peer_oob_pubkey_hash : NULL); if (res) return res; @@ -8341,16 +8414,16 @@ static int wpas_p2p_nfc_auth_join(struct wpa_supplicant *wpa_s, wpa_s->global->p2p_invite_group = wpa_s; persistent = ssid->p2p_persistent_group && - wpas_p2p_get_persistent(wpa_s->parent, + wpas_p2p_get_persistent(wpa_s->p2pdev, params->peer->p2p_device_addr, ssid->ssid, ssid->ssid_len); - wpa_s->parent->pending_invite_ssid_id = -1; + wpa_s->p2pdev->pending_invite_ssid_id = -1; return p2p_invite(wpa_s->global->p2p, params->peer->p2p_device_addr, P2P_INVITE_ROLE_ACTIVE_GO, wpa_s->own_addr, ssid->ssid, ssid->ssid_len, ssid->frequency, wpa_s->global->p2p_dev_addr, persistent, 0, - wpa_s->parent->p2p_oob_dev_pw_id); + wpa_s->p2pdev->p2p_oob_dev_pw_id); } @@ -8671,7 +8744,9 @@ int wpas_p2p_nfc_tag_enabled(struct wpa_supplicant *wpa_s, int enabled) } if_addr = wpa_s->pending_interface_addr; - } else + } else if (wpa_s->p2p_mgmt) + if_addr = wpa_s->parent->own_addr; + else if_addr = wpa_s->own_addr; wpa_s->p2p_nfc_tag_enabled = enabled; @@ -9137,3 +9212,86 @@ void wpas_p2p_ap_deinit(struct wpa_supplicant *wpa_s) wpa_s->ap_iface->bss[0]->p2p_group = NULL; wpas_p2p_group_deinit(wpa_s); } + + +int wpas_p2p_lo_start(struct wpa_supplicant *wpa_s, unsigned int freq, + unsigned int period, unsigned int interval, + unsigned int count) +{ + struct p2p_data *p2p = wpa_s->global->p2p; + u8 *device_types; + size_t dev_types_len; + struct wpabuf *buf; + int ret; + + if (wpa_s->p2p_lo_started) { + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P Listen offload is already started"); + return 0; + } + + if (wpa_s->global->p2p == NULL || + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_LISTEN_OFFLOAD)) { + wpa_printf(MSG_DEBUG, "P2P: Listen offload not supported"); + return -1; + } + + if (!p2p_supported_freq(wpa_s->global->p2p, freq)) { + wpa_printf(MSG_ERROR, "P2P: Input channel not supported: %u", + freq); + return -1; + } + + /* Get device type */ + dev_types_len = (wpa_s->conf->num_sec_device_types + 1) * + WPS_DEV_TYPE_LEN; + device_types = os_malloc(dev_types_len); + if (!device_types) + return -1; + os_memcpy(device_types, wpa_s->conf->device_type, WPS_DEV_TYPE_LEN); + os_memcpy(&device_types[WPS_DEV_TYPE_LEN], wpa_s->conf->sec_device_type, + wpa_s->conf->num_sec_device_types * WPS_DEV_TYPE_LEN); + + /* Get Probe Response IE(s) */ + buf = p2p_build_probe_resp_template(p2p, freq); + if (!buf) { + os_free(device_types); + return -1; + } + + ret = wpa_drv_p2p_lo_start(wpa_s, freq, period, interval, count, + device_types, dev_types_len, + wpabuf_mhead_u8(buf), wpabuf_len(buf)); + if (ret < 0) + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P: Failed to start P2P listen offload"); + + os_free(device_types); + wpabuf_free(buf); + + if (ret == 0) { + wpa_s->p2p_lo_started = 1; + + /* Stop current P2P listen if any */ + wpas_stop_listen(wpa_s); + } + + return ret; +} + + +int wpas_p2p_lo_stop(struct wpa_supplicant *wpa_s) +{ + int ret; + + if (!wpa_s->p2p_lo_started) + return 0; + + ret = wpa_drv_p2p_lo_stop(wpa_s); + if (ret < 0) + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P: Failed to stop P2P listen offload"); + + wpa_s->p2p_lo_started = 0; + return ret; +}