diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 0bb937e0d..b4860a08b 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -384,6 +384,12 @@ struct hostapd_bss_config { #define P2P_MANAGE BIT(3) #define P2P_ALLOW_CROSS_CONNECTION BIT(4) int p2p; +#ifdef CONFIG_P2P + u8 ip_addr_go[4]; + u8 ip_addr_mask[4]; + u8 ip_addr_start[4]; + u8 ip_addr_end[4]; +#endif /* CONFIG_P2P */ int disassoc_low_ack; int skip_inactivity_poll; diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c index 670b83447..24e764d66 100644 --- a/src/ap/sta_info.c +++ b/src/ap/sta_info.c @@ -908,6 +908,7 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, char buf[100]; #ifdef CONFIG_P2P u8 addr[ETH_ALEN]; + u8 ip_addr_buf[4]; #endif /* CONFIG_P2P */ if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED)) @@ -929,12 +930,25 @@ void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr)); if (authorized) { - wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s", buf); + char ip_addr[100]; + ip_addr[0] = '\0'; +#ifdef CONFIG_P2P + if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) { + os_snprintf(ip_addr, sizeof(ip_addr), + " ip_addr=%u.%u.%u.%u", + ip_addr_buf[0], ip_addr_buf[1], + ip_addr_buf[2], ip_addr_buf[3]); + } +#endif /* CONFIG_P2P */ + + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s", + buf, ip_addr); if (hapd->msg_ctx_parent && hapd->msg_ctx_parent != hapd->msg_ctx) wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, - AP_STA_CONNECTED "%s", buf); + AP_STA_CONNECTED "%s%s", + buf, ip_addr); sta->flags |= WLAN_STA_AUTHORIZED; } else { diff --git a/src/ap/wpa_auth.c b/src/ap/wpa_auth.c index 5993edf71..707a63f0c 100644 --- a/src/ap/wpa_auth.c +++ b/src/ap/wpa_auth.c @@ -11,6 +11,7 @@ #include "utils/common.h" #include "utils/eloop.h" #include "utils/state_machine.h" +#include "utils/bitfield.h" #include "common/ieee802_11_defs.h" #include "crypto/aes_wrap.h" #include "crypto/crypto.h" @@ -424,6 +425,17 @@ struct wpa_authenticator * wpa_init(const u8 *addr, wpa_rekey_gtk, wpa_auth, NULL); } +#ifdef CONFIG_P2P + if (WPA_GET_BE32(conf->ip_addr_start)) { + int count = WPA_GET_BE32(conf->ip_addr_end) - + WPA_GET_BE32(conf->ip_addr_start) + 1; + if (count > 1000) + count = 1000; + if (count > 0) + wpa_auth->ip_pool = bitfield_alloc(count); + } +#endif /* CONFIG_P2P */ + return wpa_auth; } @@ -466,6 +478,11 @@ void wpa_deinit(struct wpa_authenticator *wpa_auth) wpa_auth->ft_pmk_cache = NULL; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_P2P + bitfield_free(wpa_auth->ip_pool); +#endif /* CONFIG_P2P */ + + os_free(wpa_auth->wpa_ie); group = wpa_auth->group; @@ -583,6 +600,19 @@ void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm) static void wpa_free_sta_sm(struct wpa_state_machine *sm) { +#ifdef CONFIG_P2P + if (WPA_GET_BE32(sm->ip_addr)) { + u32 start; + wpa_printf(MSG_DEBUG, "P2P: Free assigned IP " + "address %u.%u.%u.%u from " MACSTR, + sm->ip_addr[0], sm->ip_addr[1], + sm->ip_addr[2], sm->ip_addr[3], + MAC2STR(sm->addr)); + start = WPA_GET_BE32(sm->wpa_auth->conf.ip_addr_start); + bitfield_clear(sm->wpa_auth->ip_pool, + WPA_GET_BE32(sm->ip_addr) - start); + } +#endif /* CONFIG_P2P */ if (sm->GUpdateStationKeys) { sm->group->GKeyDoneStations--; sm->GUpdateStationKeys = FALSE; @@ -1000,6 +1030,26 @@ continue_processing: return; } #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_P2P + if (kde.ip_addr_req && kde.ip_addr_req[0] && + wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) { + int idx; + wpa_printf(MSG_DEBUG, "P2P: IP address requested in " + "EAPOL-Key exchange"); + idx = bitfield_get_first_zero(wpa_auth->ip_pool); + if (idx >= 0) { + u32 start = WPA_GET_BE32(wpa_auth->conf. + ip_addr_start); + bitfield_set(wpa_auth->ip_pool, idx); + WPA_PUT_BE32(sm->ip_addr, start + idx); + wpa_printf(MSG_DEBUG, "P2P: Assigned IP " + "address %u.%u.%u.%u to " MACSTR, + sm->ip_addr[0], sm->ip_addr[1], + sm->ip_addr[2], sm->ip_addr[3], + MAC2STR(sm->addr)); + } + } +#endif /* CONFIG_P2P */ break; case PAIRWISE_4: if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || @@ -1995,6 +2045,10 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) kde_len += 300; /* FTIE + 2 * TIE */ } #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_P2P + if (WPA_GET_BE32(sm->ip_addr) > 0) + kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4; +#endif /* CONFIG_P2P */ kde = os_malloc(kde_len); if (kde == NULL) return; @@ -2056,6 +2110,16 @@ SM_STATE(WPA_PTK, PTKINITNEGOTIATING) pos += 4; } #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_P2P + if (WPA_GET_BE32(sm->ip_addr) > 0) { + u8 addr[3 * 4]; + os_memcpy(addr, sm->ip_addr, 4); + os_memcpy(addr + 4, sm->wpa_auth->conf.ip_addr_mask, 4); + os_memcpy(addr + 8, sm->wpa_auth->conf.ip_addr_go, 4); + pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC, + addr, sizeof(addr), NULL, 0); + } +#endif /* CONFIG_P2P */ wpa_send_eapol(sm->wpa_auth, sm, (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC | @@ -3103,3 +3167,14 @@ int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm) return 0; return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE; } + + +#ifdef CONFIG_P2P +int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr) +{ + if (sm == NULL || WPA_GET_BE32(sm->ip_addr) == 0) + return -1; + os_memcpy(addr, sm->ip_addr, 4); + return 0; +} +#endif /* CONFIG_P2P */ diff --git a/src/ap/wpa_auth.h b/src/ap/wpa_auth.h index da45ae40e..bc3dec45a 100644 --- a/src/ap/wpa_auth.h +++ b/src/ap/wpa_auth.h @@ -163,6 +163,12 @@ struct wpa_auth_config { #ifdef CONFIG_TESTING_OPTIONS double corrupt_gtk_rekey_mic_probability; #endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_P2P + u8 ip_addr_go[4]; + u8 ip_addr_mask[4]; + u8 ip_addr_start[4]; + u8 ip_addr_end[4]; +#endif /* CONFIG_P2P */ }; typedef enum { @@ -297,4 +303,6 @@ int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos); int wpa_auth_uses_sae(struct wpa_state_machine *sm); int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm); +int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr); + #endif /* WPA_AUTH_H */ diff --git a/src/ap/wpa_auth_glue.c b/src/ap/wpa_auth_glue.c index 4c1d62576..5af149503 100644 --- a/src/ap/wpa_auth_glue.c +++ b/src/ap/wpa_auth_glue.c @@ -78,6 +78,12 @@ static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, wconf->corrupt_gtk_rekey_mic_probability = iconf->corrupt_gtk_rekey_mic_probability; #endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_P2P + os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4); + os_memcpy(wconf->ip_addr_mask, conf->ip_addr_mask, 4); + os_memcpy(wconf->ip_addr_start, conf->ip_addr_start, 4); + os_memcpy(wconf->ip_addr_end, conf->ip_addr_end, 4); +#endif /* CONFIG_P2P */ } diff --git a/src/ap/wpa_auth_i.h b/src/ap/wpa_auth_i.h index 9736874f1..fcd5878e7 100644 --- a/src/ap/wpa_auth_i.h +++ b/src/ap/wpa_auth_i.h @@ -121,6 +121,10 @@ struct wpa_state_machine { #endif /* CONFIG_IEEE80211R */ int pending_1_of_4_timeout; + +#ifdef CONFIG_P2P + u8 ip_addr[4]; +#endif /* CONFIG_P2P */ }; @@ -185,6 +189,10 @@ struct wpa_authenticator { struct rsn_pmksa_cache *pmksa; struct wpa_ft_pmk_cache *ft_pmk_cache; + +#ifdef CONFIG_P2P + struct bitfield *ip_pool; +#endif /* CONFIG_P2P */ }; diff --git a/src/ap/wpa_auth_ie.c b/src/ap/wpa_auth_ie.c index cdfcca198..274f4d621 100644 --- a/src/ap/wpa_auth_ie.c +++ b/src/ap/wpa_auth_ie.c @@ -708,6 +708,25 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, } #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_P2P + if (pos[1] >= RSN_SELECTOR_LEN + 1 && + RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_REQ) { + ie->ip_addr_req = pos + 2 + RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: IP Address Request in EAPOL-Key", + ie->ip_addr_req, pos[1] - RSN_SELECTOR_LEN); + return 0; + } + + if (pos[1] >= RSN_SELECTOR_LEN + 3 * 4 && + RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_ALLOC) { + ie->ip_addr_alloc = pos + 2 + RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, + "WPA: IP Address Allocation in EAPOL-Key", + ie->ip_addr_alloc, pos[1] - RSN_SELECTOR_LEN); + return 0; + } +#endif /* CONFIG_P2P */ + return 0; } diff --git a/src/ap/wpa_auth_ie.h b/src/ap/wpa_auth_ie.h index 499913951..f94588252 100644 --- a/src/ap/wpa_auth_ie.h +++ b/src/ap/wpa_auth_ie.h @@ -39,6 +39,10 @@ struct wpa_eapol_ie_parse { const u8 *ftie; size_t ftie_len; #endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_P2P + const u8 *ip_addr_req; + const u8 *ip_addr_alloc; +#endif /* CONFIG_P2P */ }; int wpa_parse_kde_ies(const u8 *buf, size_t len, diff --git a/src/common/ieee802_11_defs.h b/src/common/ieee802_11_defs.h index 67ce9ac24..6f7f7779d 100644 --- a/src/common/ieee802_11_defs.h +++ b/src/common/ieee802_11_defs.h @@ -948,6 +948,7 @@ enum p2p_attr_id { #define P2P_GROUP_CAPAB_CROSS_CONN BIT(4) #define P2P_GROUP_CAPAB_PERSISTENT_RECONN BIT(5) #define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6) +#define P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION BIT(7) /* Invitation Flags */ #define P2P_INVITATION_FLAGS_TYPE BIT(0) diff --git a/src/common/wpa_common.h b/src/common/wpa_common.h index 62505f1b8..dcc035c7d 100644 --- a/src/common/wpa_common.h +++ b/src/common/wpa_common.h @@ -109,6 +109,9 @@ RSN_SELECTOR(0x00, 0x0f, 0xac, 13) #define RSN_KEY_DATA_MULTIBAND_GTK RSN_SELECTOR(0x00, 0x0f, 0xac, 11) #define RSN_KEY_DATA_MULTIBAND_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 12) +#define WFA_KEY_DATA_IP_ADDR_REQ RSN_SELECTOR(0x50, 0x6f, 0x9a, 4) +#define WFA_KEY_DATA_IP_ADDR_ALLOC RSN_SELECTOR(0x50, 0x6f, 0x9a, 5) + #define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1) #define RSN_SELECTOR_PUT(a, val) WPA_PUT_BE32((u8 *) (a), (val)) diff --git a/src/p2p/p2p_group.c b/src/p2p/p2p_group.c index 3154acc3e..395ca089a 100644 --- a/src/p2p/p2p_group.c +++ b/src/p2p/p2p_group.c @@ -154,6 +154,7 @@ static void p2p_group_add_common_ies(struct p2p_group *group, group_capab |= P2P_GROUP_CAPAB_CROSS_CONN; if (group->num_members >= group->cfg->max_clients) group_capab |= P2P_GROUP_CAPAB_GROUP_LIMIT; + group_capab |= P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION; p2p_buf_add_capability(ie, dev_capab, group_capab); } diff --git a/src/rsn_supp/wpa.c b/src/rsn_supp/wpa.c index a294730df..4474c3b11 100644 --- a/src/rsn_supp/wpa.c +++ b/src/rsn_supp/wpa.c @@ -379,6 +379,8 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, struct wpa_ptk *ptk; u8 buf[8]; int res; + u8 *kde, *kde_buf = NULL; + size_t kde_len; if (wpa_sm_get_network_ctx(sm) == NULL) { wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No SSID info " @@ -435,15 +437,39 @@ static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, os_memcpy(ptk->u.auth.rx_mic_key, buf, 8); sm->tptk_set = 1; + kde = sm->assoc_wpa_ie; + kde_len = sm->assoc_wpa_ie_len; + +#ifdef CONFIG_P2P + if (sm->p2p) { + kde_buf = os_malloc(kde_len + 2 + RSN_SELECTOR_LEN + 1); + if (kde_buf) { + u8 *pos; + wpa_printf(MSG_DEBUG, "P2P: Add IP Address Request KDE " + "into EAPOL-Key 2/4"); + os_memcpy(kde_buf, kde, kde_len); + kde = kde_buf; + pos = kde + kde_len; + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = RSN_SELECTOR_LEN + 1; + RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_IP_ADDR_REQ); + pos += RSN_SELECTOR_LEN; + *pos++ = 0x01; + kde_len = pos - kde; + } + } +#endif /* CONFIG_P2P */ + if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce, - sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, - ptk)) + kde, kde_len, ptk)) goto failed; + os_free(kde_buf); os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN); return; failed: + os_free(kde_buf); wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); } @@ -1090,6 +1116,14 @@ static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, goto failed; } +#ifdef CONFIG_P2P + if (ie.ip_addr_alloc) { + os_memcpy(sm->p2p_ip_addr, ie.ip_addr_alloc, 3 * 4); + wpa_hexdump(MSG_DEBUG, "P2P: IP address info", + sm->p2p_ip_addr, sizeof(sm->p2p_ip_addr)); + } +#endif /* CONFIG_P2P */ + if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, NULL, 0, &sm->ptk)) { goto failed; @@ -2086,6 +2120,10 @@ void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) #ifdef CONFIG_TDLS wpa_tdls_assoc(sm); #endif /* CONFIG_TDLS */ + +#ifdef CONFIG_P2P + os_memset(sm->p2p_ip_addr, 0, sizeof(sm->p2p_ip_addr)); +#endif /* CONFIG_P2P */ } @@ -2209,6 +2247,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) } else sm->ssid_len = 0; sm->wpa_ptk_rekey = config->wpa_ptk_rekey; + sm->p2p = config->p2p; } else { sm->network_ctx = NULL; sm->peerkey_enabled = 0; @@ -2218,6 +2257,7 @@ void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) sm->eap_conf_ctx = NULL; sm->ssid_len = 0; sm->wpa_ptk_rekey = 0; + sm->p2p = 0; } } @@ -2731,3 +2771,16 @@ int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr, return 1; } #endif /* CONFIG_PEERKEY */ + + +#ifdef CONFIG_P2P + +int wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf) +{ + if (sm == NULL || WPA_GET_BE32(sm->p2p_ip_addr) == 0) + return -1; + os_memcpy(buf, sm->p2p_ip_addr, 3 * 4); + return 0; +} + +#endif /* CONFIG_P2P */ diff --git a/src/rsn_supp/wpa.h b/src/rsn_supp/wpa.h index 9884ce12d..20b3f6211 100644 --- a/src/rsn_supp/wpa.h +++ b/src/rsn_supp/wpa.h @@ -95,6 +95,7 @@ struct rsn_supp_config { const u8 *ssid; size_t ssid_len; int wpa_ptk_rekey; + int p2p; }; #ifndef CONFIG_NO_WPA @@ -145,6 +146,8 @@ void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr); void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx); +int wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf); + #else /* CONFIG_NO_WPA */ static inline struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx) diff --git a/src/rsn_supp/wpa_i.h b/src/rsn_supp/wpa_i.h index cad6c8d96..75cfb479e 100644 --- a/src/rsn_supp/wpa_i.h +++ b/src/rsn_supp/wpa_i.h @@ -58,6 +58,7 @@ struct wpa_sm { u8 ssid[32]; size_t ssid_len; int wpa_ptk_rekey; + int p2p; u8 own_addr[ETH_ALEN]; const char *ifname; @@ -122,6 +123,10 @@ struct wpa_sm { u8 *assoc_resp_ies; /* MDIE and FTIE from (Re)Association Response */ size_t assoc_resp_ies_len; #endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_P2P + u8 p2p_ip_addr[3 * 4]; +#endif /* CONFIG_P2P */ }; diff --git a/src/rsn_supp/wpa_ie.c b/src/rsn_supp/wpa_ie.c index ab8d104dd..e58bdc477 100644 --- a/src/rsn_supp/wpa_ie.c +++ b/src/rsn_supp/wpa_ie.c @@ -345,6 +345,25 @@ static int wpa_parse_generic(const u8 *pos, const u8 *end, } #endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_P2P + if (pos[1] >= RSN_SELECTOR_LEN + 1 && + RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_REQ) { + ie->ip_addr_req = pos + 2 + RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: IP Address Request in EAPOL-Key", + ie->ip_addr_req, pos[1] - RSN_SELECTOR_LEN); + return 0; + } + + if (pos[1] >= RSN_SELECTOR_LEN + 3 * 4 && + RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_ALLOC) { + ie->ip_addr_alloc = pos + 2 + RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, + "WPA: IP Address Allocation in EAPOL-Key", + ie->ip_addr_alloc, pos[1] - RSN_SELECTOR_LEN); + return 0; + } +#endif /* CONFIG_P2P */ + return 0; } diff --git a/src/rsn_supp/wpa_ie.h b/src/rsn_supp/wpa_ie.h index 0375767d6..82b6fa3fb 100644 --- a/src/rsn_supp/wpa_ie.h +++ b/src/rsn_supp/wpa_ie.h @@ -59,6 +59,10 @@ struct wpa_eapol_ie_parse { size_t supp_oper_classes_len; u8 qosinfo; u16 aid; +#ifdef CONFIG_P2P + const u8 *ip_addr_req; + const u8 *ip_addr_alloc; +#endif /* CONFIG_P2P */ }; int wpa_supplicant_parse_ies(const u8 *buf, size_t len, diff --git a/wpa_supplicant/Android.mk b/wpa_supplicant/Android.mk index a030a0bbf..9b0746072 100644 --- a/wpa_supplicant/Android.mk +++ b/wpa_supplicant/Android.mk @@ -255,6 +255,7 @@ OBJS += src/p2p/p2p_invitation.c OBJS += src/p2p/p2p_dev_disc.c OBJS += src/p2p/p2p_group.c OBJS += src/ap/p2p_hostapd.c +OBJS += src/utils/bitfield.c L_CFLAGS += -DCONFIG_P2P NEED_GAS=y NEED_OFFCHANNEL=y diff --git a/wpa_supplicant/Makefile b/wpa_supplicant/Makefile index 2c709c330..d1e11a3ee 100644 --- a/wpa_supplicant/Makefile +++ b/wpa_supplicant/Makefile @@ -257,6 +257,7 @@ OBJS += ../src/p2p/p2p_invitation.o OBJS += ../src/p2p/p2p_dev_disc.o OBJS += ../src/p2p/p2p_group.o OBJS += ../src/ap/p2p_hostapd.o +OBJS += ../src/utils/bitfield.o CFLAGS += -DCONFIG_P2P NEED_GAS=y NEED_OFFCHANNEL=y diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c index 9a09e3ea5..ce3efcbad 100644 --- a/wpa_supplicant/ap.c +++ b/wpa_supplicant/ap.c @@ -182,6 +182,16 @@ static int wpa_supplicant_conf_ap(struct wpa_supplicant *wpa_s, bss->isolate = !wpa_s->conf->p2p_intra_bss; bss->force_per_enrollee_psk = wpa_s->global->p2p_per_sta_psk; + + if (ssid->p2p_group) { + os_memcpy(bss->ip_addr_go, wpa_s->parent->conf->ip_addr_go, 4); + os_memcpy(bss->ip_addr_mask, wpa_s->parent->conf->ip_addr_mask, + 4); + os_memcpy(bss->ip_addr_start, + wpa_s->parent->conf->ip_addr_start, 4); + os_memcpy(bss->ip_addr_end, wpa_s->parent->conf->ip_addr_end, + 4); + } #endif /* CONFIG_P2P */ if (ssid->ssid_len == 0) { diff --git a/wpa_supplicant/config.c b/wpa_supplicant/config.c index 884acf6c8..b43a72a68 100644 --- a/wpa_supplicant/config.c +++ b/wpa_supplicant/config.c @@ -10,6 +10,7 @@ #include "common.h" #include "utils/uuid.h" +#include "utils/ip_addr.h" #include "crypto/sha1.h" #include "rsn_supp/wpa.h" #include "eap_peer/eap.h" @@ -2971,6 +2972,29 @@ static int wpa_config_process_freq_list(const struct global_parse_data *data, } +#ifdef CONFIG_P2P +static int wpa_global_config_parse_ipv4(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *pos) +{ + u32 *dst; + struct hostapd_ip_addr addr; + + if (hostapd_parse_ip_addr(pos, &addr) < 0) + return -1; + if (addr.af != AF_INET) + return -1; + + dst = (u32 *) (((u8 *) config) + (long) data->param1); + os_memcpy(dst, &addr.u.v4.s_addr, 4); + wpa_printf(MSG_DEBUG, "%s = 0x%x", data->name, + WPA_GET_BE32((u8 *) dst)); + + return 0; +} +#endif /* CONFIG_P2P */ + + static int wpa_config_process_country(const struct global_parse_data *data, struct wpa_config *config, int line, const char *pos) @@ -3275,6 +3299,7 @@ static int wpa_config_process_no_ctrl_interface( #define STR(f) _STR(f), NULL, NULL #define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max #define BIN(f) #f, wpa_global_config_parse_bin, OFFSET(f), NULL, NULL +#define IPV4(f) #f, wpa_global_config_parse_ipv4, OFFSET(f), NULL, NULL static const struct global_parse_data global_fields[] = { #ifdef CONFIG_CTRL_IFACE @@ -3333,6 +3358,10 @@ static const struct global_parse_data global_fields[] = { { INT(p2p_disabled), 0 }, { INT(p2p_no_group_iface), 0 }, { INT_RANGE(p2p_ignore_shared_freq, 0, 1), 0 }, + { IPV4(ip_addr_go), 0 }, + { IPV4(ip_addr_mask), 0 }, + { IPV4(ip_addr_start), 0 }, + { IPV4(ip_addr_end), 0 }, #endif /* CONFIG_P2P */ { FUNC(country), CFG_CHANGED_COUNTRY }, { INT(bss_max_count), 0 }, @@ -3379,6 +3408,7 @@ static const struct global_parse_data global_fields[] = { #undef STR #undef STR_RANGE #undef BIN +#undef IPV4 #define NUM_GLOBAL_FIELDS ARRAY_SIZE(global_fields) diff --git a/wpa_supplicant/config.h b/wpa_supplicant/config.h index a98a5aa53..e7bdaa5a2 100644 --- a/wpa_supplicant/config.h +++ b/wpa_supplicant/config.h @@ -948,6 +948,11 @@ struct wpa_config { * specified TDLS peers. */ int tdls_external_control; + + u8 ip_addr_go[4]; + u8 ip_addr_mask[4]; + u8 ip_addr_start[4]; + u8 ip_addr_end[4]; }; diff --git a/wpa_supplicant/examples/p2p-action.sh b/wpa_supplicant/examples/p2p-action.sh index 8759f5401..c44ea7e35 100755 --- a/wpa_supplicant/examples/p2p-action.sh +++ b/wpa_supplicant/examples/p2p-action.sh @@ -41,6 +41,19 @@ if [ "$CMD" = "P2P-GROUP-STARTED" ]; then kill_daemon dhclient /var/run/dhclient-$GIFNAME.pid rm /var/run/dhclient.leases-$GIFNAME kill_daemon dnsmasq /var/run/dnsmasq.pid-$GIFNAME + ipaddr=`echo "$*" | sed 's/.* ip_addr=\([^ ]*\).*/\1/'` + ipmask=`echo "$*" | sed 's/.* ip_mask=\([^ ]*\).*/\1/'` + goipaddr=`echo "$*" | sed 's/.* go_ip_addr=\([^ ]*\).*/\1/'` + if echo "$ipaddr$ipmask$goipaddr" | grep -q ' '; then + ipaddr="" + ipmask="" + goipaddr="" + fi + if [ -n "$ipaddr" ]; then + sudo ifconfig $GIFNAME "$ipaddr" netmask "$ipmask" + sudo ip ro re default via "$goipaddr" + exit 0 + fi dhclient -pf /var/run/dhclient-$GIFNAME.pid \ -lf /var/run/dhclient.leases-$GIFNAME \ -nw \ diff --git a/wpa_supplicant/p2p_supplicant.c b/wpa_supplicant/p2p_supplicant.c index 26d53c266..4375d9bbc 100644 --- a/wpa_supplicant/p2p_supplicant.c +++ b/wpa_supplicant/p2p_supplicant.c @@ -5783,6 +5783,8 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s) int network_id = -1; int persistent; int freq; + u8 ip[3 * 4]; + char ip_addr[100]; if (ssid == NULL || ssid->mode != WPAS_MODE_P2P_GROUP_FORMATION) { eloop_cancel_timeout(wpas_p2p_group_formation_timeout, @@ -5807,23 +5809,33 @@ void wpas_p2p_completed(struct wpa_supplicant *wpa_s) freq = wpa_s->current_bss ? wpa_s->current_bss->freq : (int) wpa_s->assoc_freq; + + ip_addr[0] = '\0'; + if (wpa_sm_get_p2p_ip_addr(wpa_s->wpa, ip) == 0) { + os_snprintf(ip_addr, sizeof(ip_addr), " ip_addr=%u.%u.%u.%u " + "ip_mask=%u.%u.%u.%u go_ip_addr=%u.%u.%u.%u", + ip[0], ip[1], ip[2], ip[3], + ip[4], ip[5], ip[6], ip[7], + ip[8], ip[9], ip[10], ip[11]); + } + if (ssid->passphrase == NULL && ssid->psk_set) { char psk[65]; wpa_snprintf_hex(psk, sizeof(psk), ssid->psk, 32); wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED "%s client ssid=\"%s\" freq=%d psk=%s " - "go_dev_addr=" MACSTR "%s", + "go_dev_addr=" MACSTR "%s%s", wpa_s->ifname, ssid_txt, freq, psk, MAC2STR(go_dev_addr), - persistent ? " [PERSISTENT]" : ""); + persistent ? " [PERSISTENT]" : "", ip_addr); } else { wpa_msg_global(wpa_s->parent, MSG_INFO, P2P_EVENT_GROUP_STARTED "%s client ssid=\"%s\" freq=%d " - "passphrase=\"%s\" go_dev_addr=" MACSTR "%s", + "passphrase=\"%s\" go_dev_addr=" MACSTR "%s%s", wpa_s->ifname, ssid_txt, freq, ssid->passphrase ? ssid->passphrase : "", MAC2STR(go_dev_addr), - persistent ? " [PERSISTENT]" : ""); + persistent ? " [PERSISTENT]" : "", ip_addr); } if (persistent) diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index 1bb1a2ce2..35f56936e 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -1565,6 +1565,8 @@ static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) "disallows" : "allows"); } } + + os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info)); #endif /* CONFIG_P2P */ #ifdef CONFIG_HS20 diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h index 46f895666..6390ca280 100644 --- a/wpa_supplicant/wpa_supplicant_i.h +++ b/wpa_supplicant/wpa_supplicant_i.h @@ -730,6 +730,7 @@ struct wpa_supplicant { struct wpabuf *p2p_oob_dev_pw; /* OOB Device Password for group * formation */ u8 p2p_peer_oob_pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN]; + u8 p2p_ip_addr_info[3 * 4]; #endif /* CONFIG_P2P */ struct wpa_ssid *bgscan_ssid; diff --git a/wpa_supplicant/wpas_glue.c b/wpa_supplicant/wpas_glue.c index ad0895be5..0dca0e629 100644 --- a/wpa_supplicant/wpas_glue.c +++ b/wpa_supplicant/wpas_glue.c @@ -948,6 +948,21 @@ void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, conf.ssid = ssid->ssid; conf.ssid_len = ssid->ssid_len; conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey; +#ifdef CONFIG_P2P + if (ssid->p2p_group && wpa_s->current_bss) { + struct wpabuf *p2p; + p2p = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss, + P2P_IE_VENDOR_TYPE); + if (p2p) { + u8 group_capab; + group_capab = p2p_get_group_capab(p2p); + if (group_capab & + P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION) + conf.p2p = 1; + wpabuf_free(p2p); + } + } +#endif /* CONFIG_P2P */ } wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL); }