From b841cf2fa6886de7749477ad71e3f8b6dc3f8bb9 Mon Sep 17 00:00:00 2001 From: Ahmad Kholaif Date: Thu, 23 Jul 2015 17:39:45 -0700 Subject: [PATCH] P2P: Add preferred frequency list extension to GO Neg Req When sending a GO Negotiation Request, advertise the preferred frequency list in a new vendor specific IE. This can be used to extend the standard P2P behavior where a single preferred channel can be advertised by allowing a priority list of channels to be indicated. Signed-off-by: Jouni Malinen --- src/p2p/p2p_build.c | 39 +++++++++++++++++++++++++++++++++++++++ src/p2p/p2p_go_neg.c | 3 +++ src/p2p/p2p_i.h | 2 ++ 3 files changed, 44 insertions(+) diff --git a/src/p2p/p2p_build.c b/src/p2p/p2p_build.c index c733543c4..793d28ba7 100644 --- a/src/p2p/p2p_build.c +++ b/src/p2p/p2p_build.c @@ -10,6 +10,7 @@ #include "common.h" #include "common/ieee802_11_defs.h" +#include "common/qca-vendor.h" #include "wps/wps_i.h" #include "p2p_i.h" @@ -109,6 +110,44 @@ void p2p_buf_add_operating_channel(struct wpabuf *buf, const char *country, } +void p2p_buf_add_pref_channel_list(struct wpabuf *buf, + const u32 *preferred_freq_list, + unsigned int size) +{ + unsigned int i, count = 0; + u8 op_class, op_channel; + + if (!size) + return; + + /* + * First, determine the number of P2P supported channels in the + * pref_freq_list returned from driver. This is needed for calculations + * of the vendor IE size. + */ + for (i = 0; i < size; i++) { + if (p2p_freq_to_channel(preferred_freq_list[i], &op_class, + &op_channel) == 0) + count++; + } + + wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); + wpabuf_put_u8(buf, 4 + count * sizeof(u16)); + wpabuf_put_be24(buf, OUI_QCA); + wpabuf_put_u8(buf, QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST); + for (i = 0; i < size; i++) { + if (p2p_freq_to_channel(preferred_freq_list[i], &op_class, + &op_channel) < 0) { + wpa_printf(MSG_DEBUG, "Unsupported frequency %u MHz", + preferred_freq_list[i]); + continue; + } + wpabuf_put_u8(buf, op_class); + wpabuf_put_u8(buf, op_channel); + } +} + + void p2p_buf_add_channel_list(struct wpabuf *buf, const char *country, struct p2p_channels *chan) { diff --git a/src/p2p/p2p_go_neg.c b/src/p2p/p2p_go_neg.c index 19f1daaf2..d47763ac5 100644 --- a/src/p2p/p2p_go_neg.c +++ b/src/p2p/p2p_go_neg.c @@ -185,6 +185,9 @@ static struct wpabuf * p2p_build_go_neg_req(struct p2p_data *p2p, p2p->op_reg_class, p2p->op_channel); p2p_buf_update_ie_hdr(buf, len); + p2p_buf_add_pref_channel_list(buf, p2p->pref_freq_list, + p2p->num_pref_freq); + /* WPS IE with Device Password ID attribute */ pw_id = p2p_wps_method_pw_id(peer->wps_method); if (peer->oob_pw_id) diff --git a/src/p2p/p2p_i.h b/src/p2p/p2p_i.h index 3d6bc7054..5921792da 100644 --- a/src/p2p/p2p_i.h +++ b/src/p2p/p2p_i.h @@ -769,6 +769,8 @@ void p2p_buf_add_persistent_group_info(struct wpabuf *buf, const u8 *dev_addr, const u8 *ssid, size_t ssid_len); int p2p_build_wps_ie(struct p2p_data *p2p, struct wpabuf *buf, int pw_id, int all_attr); +void p2p_buf_add_pref_channel_list(struct wpabuf *buf, + const u32 *preferred_freq_list, u32 size); /* p2p_sd.c */ struct p2p_sd_query * p2p_pending_sd_req(struct p2p_data *p2p,