diff --git a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h index 9c08e3648f33..a196ac51faff 100644 --- a/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h +++ b/umac/cmn_services/cmn_defs/inc/wlan_cmn_ieee80211.h @@ -25,6 +25,10 @@ #include #include +#define IEEE80211_CCMP_HEADERLEN 8 +#define IEEE80211_CCMP_MICLEN 8 +#define IEEE80211_FC1_WEP 0x40 + #define WLAN_SEQ_SEQ_SHIFT 4 #define P2P_WFA_OUI {0x50, 0x6f, 0x9a} diff --git a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c index 59981c830c2c..d82a136eeb15 100644 --- a/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c +++ b/umac/cmn_services/mgmt_txrx/dispatcher/src/wlan_mgmt_txrx_tgt_api.c @@ -869,17 +869,24 @@ QDF_STATUS tgt_mgmt_txrx_rx_frame_handler( /* mpdu_data_ptr is pointer to action header */ mpdu_data_ptr = (uint8_t *)qdf_nbuf_data(buf) + sizeof(struct ieee80211_frame); + if ((wh->i_fc[1] & IEEE80211_FC1_WEP) && + (mgmt_subtype == MGMT_SUBTYPE_ACTION) && + !qdf_is_macaddr_group((struct qdf_mac_addr *)wh->i_addr1) && + !qdf_is_macaddr_broadcast((struct qdf_mac_addr *)wh->i_addr1)) + mpdu_data_ptr += IEEE80211_CCMP_HEADERLEN; + frm_type = mgmt_txrx_get_frm_type(mgmt_subtype, mpdu_data_ptr); if (frm_type == MGMT_FRM_UNSPECIFIED) { - mgmt_txrx_err("Unspecified mgmt frame type"); + mgmt_txrx_err("Unspecified mgmt frame type fc: %x %x", + wh->i_fc[0], wh->i_fc[1]); qdf_nbuf_free(buf); status = QDF_STATUS_E_FAILURE; goto dec_peer_ref_cnt; } - mgmt_txrx_info("Rcvd mgmt frame, mgmt txrx frm type: %u" - "seq. no.: %u, peer: %pK", - frm_type, *(uint16_t *)wh->i_seq, peer); + mgmt_txrx_info("Rcvd mgmt frame, mgmt txrx frm type: %u seq. no.: %u, peer: %pK fc: %x %x", + frm_type, *(uint16_t *)wh->i_seq, peer, wh->i_fc[0], + wh->i_fc[1]); mgmt_txrx_psoc_ctx = (struct mgmt_txrx_priv_psoc_context *) wlan_objmgr_psoc_get_comp_private_obj(psoc, diff --git a/umac/p2p/core/src/wlan_p2p_main.h b/umac/p2p/core/src/wlan_p2p_main.h index c1b60d05b13f..17e6bedc0786 100644 --- a/umac/p2p/core/src/wlan_p2p_main.h +++ b/umac/p2p/core/src/wlan_p2p_main.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -166,6 +166,7 @@ enum p2p_connection_status { * data to HDD * @cancel_roc_done: Cancel roc done event * @roc_runtime_lock: Runtime lock for roc request + * @p2p_cb: Callbacks to protocol stack * @connection_status:Global P2P connection status */ struct p2p_soc_priv_obj { @@ -177,6 +178,7 @@ struct p2p_soc_priv_obj { struct p2p_start_param *start_param; qdf_event_t cancel_roc_done; qdf_runtime_lock_t roc_runtime_lock; + struct p2p_protocol_callbacks p2p_cb; #ifdef WLAN_FEATURE_P2P_DEBUG enum p2p_connection_status connection_status; #endif diff --git a/umac/p2p/core/src/wlan_p2p_off_chan_tx.c b/umac/p2p/core/src/wlan_p2p_off_chan_tx.c index 7510af8977e3..62ef353e7b76 100644 --- a/umac/p2p/core/src/wlan_p2p_off_chan_tx.c +++ b/umac/p2p/core/src/wlan_p2p_off_chan_tx.c @@ -494,21 +494,6 @@ static QDF_STATUS p2p_populate_mac_header( return QDF_STATUS_SUCCESS; } -/** - * p2p_set_protected_bit() - set protected bit - * @tx_ctx: tx context - * @frame: pointer to frame - * - * This function sets protected bit of this mgmt frame - * - * Return: QDF_STATUS_SUCCESS - in case of success - */ -static QDF_STATUS p2p_set_protected_bit( - struct tx_action_context *tx_ctx, void *frame) -{ - return QDF_STATUS_E_INVAL; -} - /** * p2p_get_frame_type_str() - parse frame type to string * @frame_info: frame information @@ -799,7 +784,7 @@ static QDF_STATUS p2p_rx_update_connection_status( * Return: QDF_STATUS_SUCCESS - in case of success */ static QDF_STATUS p2p_packet_alloc(uint16_t size, void **data, - void **ppPacket) + qdf_nbuf_t *ppPacket) { QDF_STATUS status = QDF_STATUS_E_FAILURE; qdf_nbuf_t nbuf; @@ -882,7 +867,7 @@ static QDF_STATUS p2p_send_tx_conf(struct tx_action_context *tx_ctx, * Return: QDF_STATUS_SUCCESS - in case of success */ static QDF_STATUS p2p_mgmt_tx(struct tx_action_context *tx_ctx, - uint32_t buf_len, void *packet, uint8_t *frame) + uint32_t buf_len, qdf_nbuf_t packet, uint8_t *frame) { QDF_STATUS status; mgmt_tx_download_comp_cb tx_comp_cb; @@ -935,7 +920,7 @@ static QDF_STATUS p2p_mgmt_tx(struct tx_action_context *tx_ctx, tx_ctx->nbuf = packet; status = wlan_mgmt_txrx_mgmt_frame_tx(peer, tx_ctx->p2p_soc_obj, - (qdf_nbuf_t)packet, tx_comp_cb, tx_ota_comp_cb, + packet, tx_comp_cb, tx_ota_comp_cb, WLAN_UMAC_COMP_P2P, &mgmt_param); wlan_objmgr_peer_release_ref(peer, WLAN_P2P_ID); @@ -1352,6 +1337,120 @@ static QDF_STATUS p2p_disable_tx_timer(struct tx_action_context *tx_ctx) return status; } +/** + * is_rmf_mgmt_action_frame() - check RMF action frame by category + * @action_category: action frame actegory + * + * This function check the frame is robust mgmt action frame or not + * + * Return: true - if category is robust mgmt type + */ +static bool is_rmf_mgmt_action_frame(uint8_t action_category) +{ + switch (action_category) { + case ACTION_CATEGORY_SPECTRUM_MGMT: + case ACTION_CATEGORY_QOS: + case ACTION_CATEGORY_DLS: + case ACTION_CATEGORY_BACK: + case ACTION_CATEGORY_RRM: + case ACTION_FAST_BSS_TRNST: + case ACTION_CATEGORY_SA_QUERY: + case ACTION_CATEGORY_PROTECTED_DUAL_OF_PUBLIC_ACTION: + case ACTION_CATEGORY_WNM: + case ACTION_CATEGORY_MESH_ACTION: + case ACTION_CATEGORY_MULTIHOP_ACTION: + case ACTION_CATEGORY_DMG: + case ACTION_CATEGORY_FST: + case ACTION_CATEGORY_VENDOR_SPECIFIC_PROTECTED: + return true; + default: + break; + } + return false; +} + +/** + * p2p_populate_rmf_field() - populate unicast rmf frame + * @tx_ctx: tx_action_context + * @size: input size of frame, and output new size + * @ppbuf: input frame ptr, and output new frame + * @ppkt: input pkt, output new pkt. + * + * This function allocates new pkt for rmf frame. The + * new frame has extra space for ccmp field. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +static QDF_STATUS p2p_populate_rmf_field(struct tx_action_context *tx_ctx, + uint32_t *size, uint8_t **ppbuf, qdf_nbuf_t *ppkt) +{ + struct wlan_frame_hdr *wh, *rmf_wh; + struct action_frm_hdr *action_hdr; + QDF_STATUS status = QDF_STATUS_SUCCESS; + qdf_nbuf_t pkt = NULL; + uint8_t *frame; + uint32_t frame_len; + struct p2p_soc_priv_obj *p2p_soc_obj; + + p2p_soc_obj = tx_ctx->p2p_soc_obj; + + if (tx_ctx->frame_info.sub_type != P2P_MGMT_ACTION || + !p2p_soc_obj->p2p_cb.is_mgmt_protected) + return QDF_STATUS_SUCCESS; + if (*size < (sizeof(struct wlan_frame_hdr) + + sizeof(struct action_frm_hdr))) { + return QDF_STATUS_E_INVAL; + } + + wh = (struct wlan_frame_hdr *)(*ppbuf); + action_hdr = (struct action_frm_hdr *)(*ppbuf + sizeof(*wh)); + + if (!is_rmf_mgmt_action_frame(action_hdr->action_category)) { + p2p_debug("non rmf act frame 0x%x cat %x", + tx_ctx->frame_info.sub_type, + action_hdr->action_category); + return QDF_STATUS_SUCCESS; + } + + if (!p2p_soc_obj->p2p_cb.is_mgmt_protected( + tx_ctx->vdev_id, wh->i_addr1)) { + p2p_debug("non rmf connection vdev %d "QDF_MAC_ADDR_STR, + tx_ctx->vdev_id, QDF_MAC_ADDR_ARRAY(wh->i_addr1)); + return QDF_STATUS_SUCCESS; + } + if (!qdf_is_macaddr_group((struct qdf_mac_addr *)wh->i_addr1) && + !qdf_is_macaddr_broadcast((struct qdf_mac_addr *)wh->i_addr1)) { + + frame_len = *size + IEEE80211_CCMP_HEADERLEN + + IEEE80211_CCMP_MICLEN; + status = p2p_packet_alloc((uint16_t)frame_len, (void **)&frame, + &pkt); + if (status != QDF_STATUS_SUCCESS) { + p2p_err("Failed to allocate %d bytes for rmf frame.", + frame_len); + return QDF_STATUS_E_NOMEM; + } + + qdf_mem_copy(frame, wh, sizeof(*wh)); + qdf_mem_copy(frame + sizeof(*wh) + IEEE80211_CCMP_HEADERLEN, + *ppbuf + sizeof(*wh), + *size - sizeof(*wh)); + rmf_wh = (struct wlan_frame_hdr *)frame; + (rmf_wh)->i_fc[1] |= IEEE80211_FC1_WEP; + p2p_debug("set protection 0x%x cat %d "QDF_MAC_ADDR_STR, + tx_ctx->frame_info.sub_type, + action_hdr->action_category, + QDF_MAC_ADDR_ARRAY(wh->i_addr1)); + + qdf_nbuf_free(*ppkt); + *ppbuf = frame; + *ppkt = pkt; + *size = frame_len; + } + + return status; +} + /** * p2p_execute_tx_action_frame() - execute tx action frame * @tx_ctx: tx context @@ -1364,7 +1463,7 @@ static QDF_STATUS p2p_execute_tx_action_frame( struct tx_action_context *tx_ctx) { uint8_t *frame; - void *packet; + qdf_nbuf_t packet; QDF_STATUS status; uint8_t noa_len = 0; uint8_t noa_stream[P2P_NOA_STREAM_ARR_SIZE]; @@ -1411,7 +1510,7 @@ static QDF_STATUS p2p_execute_tx_action_frame( /* Ok-- try to allocate some memory: */ status = p2p_packet_alloc((uint16_t) buf_len, (void **)&frame, - (void **)&packet); + &packet); if (status != QDF_STATUS_SUCCESS) { p2p_err("Failed to allocate %d bytes for a Probe Request.", buf_len); @@ -1439,7 +1538,12 @@ static QDF_STATUS p2p_execute_tx_action_frame( qdf_mem_copy(frame, tx_ctx->buf, buf_len); } - p2p_set_protected_bit(tx_ctx, frame); + status = p2p_populate_rmf_field(tx_ctx, &buf_len, &frame, &packet); + if (status != QDF_STATUS_SUCCESS) { + p2p_err("failed to populate rmf frame"); + qdf_nbuf_free(packet); + return status; + } status = p2p_mgmt_tx(tx_ctx, buf_len, packet, frame); if (status == QDF_STATUS_SUCCESS) { if (tx_ctx->no_ack) { diff --git a/umac/p2p/core/src/wlan_p2p_off_chan_tx.h b/umac/p2p/core/src/wlan_p2p_off_chan_tx.h index 87465875f0fc..41bdc806d527 100644 --- a/umac/p2p/core/src/wlan_p2p_off_chan_tx.h +++ b/umac/p2p/core/src/wlan_p2p_off_chan_tx.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -173,7 +173,7 @@ struct tx_action_context { uint32_t duration; qdf_mc_timer_t tx_timer; struct p2p_frame_info frame_info; - void *nbuf; + qdf_nbuf_t nbuf; }; /** diff --git a/umac/p2p/dispatcher/inc/wlan_p2p_public_struct.h b/umac/p2p/dispatcher/inc/wlan_p2p_public_struct.h index febd25f75f24..4f156c633d7c 100644 --- a/umac/p2p/dispatcher/inc/wlan_p2p_public_struct.h +++ b/umac/p2p/dispatcher/inc/wlan_p2p_public_struct.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -215,4 +215,12 @@ struct p2p_noa_info { struct noa_descriptor noa_desc[P2P_MAX_NOA_DESC]; }; +/** + * struct p2p_protocol_callbacks - callback to non-converged driver + * @is_mgmt_protected: func to get 11w mgmt protection status + */ +struct p2p_protocol_callbacks { + bool (*is_mgmt_protected)(uint32_t vdev_id, const uint8_t *peer_addr); +}; + #endif /* _WLAN_P2P_PUBLIC_STRUCT_H_ */ diff --git a/umac/p2p/dispatcher/inc/wlan_p2p_ucfg_api.h b/umac/p2p/dispatcher/inc/wlan_p2p_ucfg_api.h index 708a4bf7e338..7ef8974a7993 100644 --- a/umac/p2p/dispatcher/inc/wlan_p2p_ucfg_api.h +++ b/umac/p2p/dispatcher/inc/wlan_p2p_ucfg_api.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -297,6 +297,19 @@ void p2p_peer_authorized(struct wlan_objmgr_vdev *vdev, uint8_t *mac_addr); QDF_STATUS ucfg_p2p_set_noa(struct wlan_objmgr_psoc *soc, uint32_t vdev_id, bool disable_noa); +/** + * ucfg_p2p_register_callbacks() - register p2p callbacks + * @soc: soc context + * @cb_obj: p2p_protocol_callbacks struct + * + * This function registers lim callbacks to p2p components to provide + * protocol information. + * + * Return: QDF_STATUS_SUCCESS - in case of success + */ +QDF_STATUS ucfg_p2p_register_callbacks(struct wlan_objmgr_psoc *soc, + struct p2p_protocol_callbacks *cb_obj); + /** * ucfg_p2p_status_scan() - Show P2P connection status when scanning * @vdev: vdev context diff --git a/umac/p2p/dispatcher/src/wlan_p2p_ucfg_api.c b/umac/p2p/dispatcher/src/wlan_p2p_ucfg_api.c index 4415b3cbefc2..8e2ea051aa72 100644 --- a/umac/p2p/dispatcher/src/wlan_p2p_ucfg_api.c +++ b/umac/p2p/dispatcher/src/wlan_p2p_ucfg_api.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. * * Permission to use, copy, modify, and/or distribute this software for * any purpose with or without fee is hereby granted, provided that the @@ -23,8 +23,8 @@ #include #include #include -#include "wlan_p2p_ucfg_api.h" #include "wlan_p2p_public_struct.h" +#include "wlan_p2p_ucfg_api.h" #include "../../core/src/wlan_p2p_main.h" #include "../../core/src/wlan_p2p_roc.h" #include "../../core/src/wlan_p2p_off_chan_tx.h" @@ -423,6 +423,28 @@ QDF_STATUS ucfg_p2p_set_noa(struct wlan_objmgr_psoc *soc, return status; } +QDF_STATUS ucfg_p2p_register_callbacks(struct wlan_objmgr_psoc *soc, + struct p2p_protocol_callbacks *cb_obj) +{ + struct p2p_soc_priv_obj *p2p_soc_obj; + + if (!soc || !cb_obj) { + p2p_err("psoc %pM cb_obj %pM context passed is NULL", soc, + cb_obj); + return QDF_STATUS_E_INVAL; + } + + p2p_soc_obj = wlan_objmgr_psoc_get_comp_private_obj(soc, + WLAN_UMAC_COMP_P2P); + if (!p2p_soc_obj) { + p2p_err("p2p soc private object is NULL"); + return QDF_STATUS_E_FAILURE; + } + p2p_soc_obj->p2p_cb = *cb_obj; + + return QDF_STATUS_SUCCESS; +} + QDF_STATUS ucfg_p2p_status_scan(struct wlan_objmgr_vdev *vdev) { if (!vdev) {