1 /*
2 * Copyright (c) 2020 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 * Description: hook function for wifi promiscuous.
15 */
16
17 /* 混杂模式在linux上编译不过,先屏蔽,后续特性责任人做适配 */
18 #include "hmac_promisc.h"
19 #if defined(_PRE_OS_VERSION_LITEOS) && defined(_PRE_OS_VERSION) && (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
20 #include "soc_zdiag.h"
21 #include "hal_mac_reg.h"
22 #else
23 #include "mac_resource_ext.h"
24 #endif
25 #include "hmac_sta_pm.h"
26 #include "oam_ext_if.h"
27 #include "oal_net.h"
28 #include "mac_frame.h"
29 #include "mac_device_ext.h"
30 #include "dmac_ext_if_device.h"
31 #include "hmac_config.h"
32 #include "msg_psm_rom.h"
33 #include "hmac_mgmt_classifier.h"
34 #include "hmac_feature_interface.h"
35 #include "hmac_hook.h"
36
37 #ifdef __cplusplus
38 #if __cplusplus
39 extern "C" {
40 #endif
41 #endif
42
43 #undef THIS_FILE_ID
44 #define THIS_FILE_ID OAM_FILE_ID_OAM_PROMISC_C
45
46 #define WLAN_PROCMIS_ZDIAG_ID 0x7580
47 #define WLAN_PROMISC_MODE_NUM 4
48
49 static wlan_promisc_mode_stru g_promisc_st = {
50 .promis_count = {{{0}}}
51 };
52
53 static osal_u8 g_custom_en = 0;
54 static osal_u8 g_promisc_switch = 0;
55 static osal_u8 g_promisc_mode = 0;
56
57 /* 函数功能: 清零混杂模式帧计数 */
hmac_promisc_clear_counts(void)58 OAL_STATIC osal_void hmac_promisc_clear_counts(void)
59 {
60 memset_s(g_promisc_st.promis_count, sizeof(g_promisc_st.promis_count), 0, sizeof(g_promisc_st.promis_count));
61 }
62
63 #if defined(_PRE_OS_VERSION_LITEOS) && defined(_PRE_OS_VERSION) && (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
hmac_promis_send_custom_frame(hmac_vap_stru * hmac_vap,const oal_netbuf_stru * netbuf)64 OAL_STATIC osal_void hmac_promis_send_custom_frame(hmac_vap_stru *hmac_vap, const oal_netbuf_stru *netbuf)
65 {
66 const dmac_rx_ctl_stru *rx_ctl = OSAL_NULL;
67 const mac_rx_ctl_stru *rx_info = OSAL_NULL;
68
69 if (netbuf == OSAL_NULL) {
70 return;
71 }
72
73 if (g_custom_en == 0) {
74 return;
75 }
76
77 rx_ctl = (dmac_rx_ctl_stru *)oal_netbuf_cb_const(netbuf); /* 获取帧头信息 */
78 rx_info = (const mac_rx_ctl_stru *)(&(rx_ctl->rx_info));
79 hmac_rx_send_report_frame_msg(hmac_vap, rx_info, rx_ctl->rx_statistic.rssi_dbm, WLAN_MSG_H2W_UPLOAD_PROMIS);
80 return;
81 }
82 #endif
83
hmac_show_promisc_res_by_mode(osal_u8 bit_num,osal_u8 frame_type,osal_u8 subtype_num,osal_u8 frame_mode)84 OAL_STATIC osal_void hmac_show_promisc_res_by_mode(osal_u8 bit_num, osal_u8 frame_type,
85 osal_u8 subtype_num, osal_u8 frame_mode)
86 {
87 osal_u8 i;
88 osal_u8 promisc_mode = g_promisc_mode;
89 osal_u8 type = (frame_type == WLAN_MANAGEMENT) ? WLAN_FC0_TYPE_MGT : WLAN_FC0_TYPE_DATA;
90
91 if (((promisc_mode >> bit_num) & 0x1) != OSAL_FALSE) {
92 for (i = 0; i < subtype_num; i++) {
93 if (g_promisc_st.promis_count[frame_type][i][frame_mode] != 0) {
94 oam_warning_log3(0, 0, "type[%d], sub_type[%d], count[%d]\r\n",
95 type, i, g_promisc_st.promis_count[frame_type][i][frame_mode]);
96 }
97 }
98 }
99 }
100
hmac_show_80211_frame_promisc_statistic(osal_void)101 OAL_STATIC osal_void hmac_show_80211_frame_promisc_statistic(osal_void)
102 {
103 osal_u8 i;
104 wlan_promisc_query_stru promisc_query_module[WLAN_PROMISC_MODE_NUM] = {
105 {0, WLAN_DATA_BASICTYPE, WLAN_DATA_SUBTYPE_MGMT, 1}, /* bit0 多播、广播数据帧打开 */
106 {1, WLAN_DATA_BASICTYPE, WLAN_MGMT_SUBTYPE_BUTT, 0}, /* bit1 单播数据帧打开 */
107 {2, WLAN_MANAGEMENT, WLAN_MGMT_SUBTYPE_BUTT, 1}, /* bit2 多播、广播管理帧打开 */
108 {3, WLAN_MANAGEMENT, WLAN_MGMT_SUBTYPE_BUTT, 0}, /* bit3 单播管理帧打开 */
109 };
110
111 for (i = 0; i < osal_array_size(promisc_query_module); i++) {
112 hmac_show_promisc_res_by_mode(promisc_query_module[i].bit_num, promisc_query_module[i].frame_type,
113 promisc_query_module[i].subtype_num, promisc_query_module[i].frame_mode);
114 }
115 }
116
117 /* 函数功能: 混杂模式帧类型统计信息串口打印 */
hmac_80211_frame_promis_proc(hmac_vap_stru * hmac_vap,const mac_ieee80211_frame_stru * frame_hdr,const mac_rx_ctl_stru * rx_info,osal_s8 rssi)118 OAL_STATIC osal_void hmac_80211_frame_promis_proc(hmac_vap_stru *hmac_vap,
119 const mac_ieee80211_frame_stru *frame_hdr, const mac_rx_ctl_stru *rx_info, osal_s8 rssi)
120 {
121 osal_u8 is_multicast, type, sub_type, filter, frame_mode;
122
123 /* 混杂模式只处理RX方向的 802.11报文(包含beacon) */
124 is_multicast = (frame_hdr->frame_control.to_ds == 0) ?
125 ether_is_multicast(frame_hdr->address1) : ether_is_multicast(frame_hdr->address3);
126 frame_mode = (is_multicast == 0) ? 0 : 1; /* 0:表示单播,1:表示广播 */
127 type = frame_hdr->frame_control.type;
128 sub_type = frame_hdr->frame_control.sub_type;
129 filter = (osal_u8)g_promisc_mode;
130
131 if (type == WLAN_CONTROL) { /* 控制帧处理 */
132 return;
133 } else if (type == WLAN_MANAGEMENT) { /* 管理帧处理 */
134 g_promisc_st.promis_count[type][sub_type][frame_mode]++;
135 } else { /* 数据帧处理 */
136 g_promisc_st.promis_count[type][sub_type][frame_mode]++;
137 }
138
139 /* bit0 多播、广播数据帧没有打开 */
140 if (((filter & 0x1) == OSAL_FALSE) && ((type == WLAN_DATA_BASICTYPE) && (is_multicast != 0))) {
141 return;
142 }
143 /* bit1 单播数据帧没有打开 */
144 if ((((filter >> 1) & 0x1) == OSAL_FALSE) && ((type == WLAN_DATA_BASICTYPE) && (is_multicast == 0))) {
145 return;
146 }
147 /* bit2 多播、广播管理帧没有打开 */
148 if ((((filter >> 2) & 0x1) == OSAL_FALSE) && ((type == WLAN_MANAGEMENT) && (is_multicast != 0))) {
149 return;
150 }
151 /* bit3 单播管理帧没有打开 */
152 if ((((filter >> 3) & 0x1) == OSAL_FALSE) && ((type == WLAN_MANAGEMENT) && (is_multicast == 0))) {
153 return;
154 }
155
156 #if defined(_PRE_OS_VERSION_LITEOS) && defined(_PRE_OS_VERSION) && (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
157 hmac_rx_send_report_frame_msg(hmac_vap, rx_info, rssi, WLAN_MSG_H2W_UPLOAD_PROMIS);
158 #endif
159 }
160
hmac_80211_frame_promis_data2diag(const mac_ieee80211_frame_stru * wlan_frame,osal_u16 frame_len)161 OAL_STATIC osal_void hmac_80211_frame_promis_data2diag(const mac_ieee80211_frame_stru *wlan_frame, osal_u16 frame_len)
162 {
163 #if defined(_PRE_OS_VERSION_LITEOS) && defined(_PRE_OS_VERSION) && (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
164 #ifdef _PRE_WLAN_FEATURE_WS73
165 diag_option option = DIAG_OPTION_INIT_VAL;
166 #else
167 diag_option_t option = DIAG_OPTION_INIT_VAL;
168 #endif
169
170 oam_warning_log1(0, 0, "{dmac_80211_frame_promis_data2diag::frame_len[%d].}", frame_len);
171 #ifndef _PRE_LITEOS_SDK_
172 uapi_zdiag_report_packet(WLAN_PROCMIS_ZDIAG_ID, &option, (td_u8 *)wlan_frame, (td_u16)frame_len, TD_FALSE);
173 #endif
174 #endif
175 }
176
177 /*****************************************************************************
178 功能描述 : 混杂模式的处理
179 *****************************************************************************/
hmac_rx_frame_promis_proc(oal_netbuf_stru ** netbuf,hmac_vap_stru * hmac_vap)180 OAL_STATIC osal_u32 hmac_rx_frame_promis_proc(oal_netbuf_stru **netbuf, hmac_vap_stru *hmac_vap)
181 {
182 dmac_rx_ctl_stru *rx_ctl;
183 const mac_rx_ctl_stru *rx_info = OSAL_NULL;
184 const mac_ieee80211_frame_stru *frame_hdr;
185
186 if (g_promisc_switch == 0) {
187 return OAL_CONTINUE;
188 }
189
190 rx_ctl = (dmac_rx_ctl_stru *)oal_netbuf_cb_const(*netbuf); /* 获取帧头信息 */
191 rx_info = (const mac_rx_ctl_stru *)(&(rx_ctl->rx_info));
192 frame_hdr = (mac_ieee80211_frame_stru *)oal_netbuf_header(*netbuf);
193 hmac_80211_frame_promis_proc(hmac_vap, frame_hdr, rx_info, rx_ctl->rx_statistic.rssi_dbm);
194 hmac_80211_frame_promis_data2diag(frame_hdr, rx_ctl->rx_info.frame_len);
195
196 return OAL_CONTINUE;
197 }
198
199 /*****************************************************************************
200 功能描述 : 混杂模式的处理
201 *****************************************************************************/
hmac_promisc_set_monitor_hal_reg(osal_u8 promis_switch)202 OAL_STATIC osal_void hmac_promisc_set_monitor_hal_reg(osal_u8 promis_switch)
203 {
204 hal_rx_filter_set_rx_flt_en(promis_switch);
205 }
206
hmac_sta_rx_deauth_req_proc_for_promisc(hmac_vap_stru * hmac_vap,const osal_u8 * mac_hdr)207 OAL_STATIC osal_u32 hmac_sta_rx_deauth_req_proc_for_promisc(hmac_vap_stru *hmac_vap, const osal_u8 *mac_hdr)
208 {
209 osal_u8 *da = OSAL_NULL;
210 hmac_device_stru *hmac_device = OSAL_NULL;
211
212 mac_rx_get_da((mac_ieee80211_frame_stru *)mac_hdr, &da);
213
214 hmac_device = (hmac_device_stru *)hmac_res_get_mac_dev_etc(hmac_vap->device_id);
215 if (osal_unlikely(hmac_device == OSAL_NULL)) {
216 oam_warning_log1(0, OAM_SF_AUTH,
217 "vap_id[%d] {hmac_sta_rx_deauth_req_proc_for_promisc::hmac_device is null}", hmac_vap->vap_id);
218 return OAL_ERR_CODE_MAC_DEVICE_NULL;
219 }
220
221 /* 混杂模式下,判断关联之后如果收到了AP发给其他STA的去关联帧,丢弃 */
222 if ((g_promisc_switch != 0) &&
223 (memcmp(da, hmac_vap->mib_info->wlan_mib_sta_config.dot11_station_id, WLAN_MAC_ADDR_LEN) != 0)) {
224 oam_warning_log1(0, OAM_SF_AUTH,
225 "vap_id[%d] {hmac_sta_rx_deauth_req_proc_for_promisc::rx deauth for other STA}", hmac_vap->vap_id);
226 return OAL_FAIL;
227 }
228
229 return OAL_SUCC;
230 }
231
232 hmac_netbuf_hook_stru g_promisc_data_netbuf_hook = {
233 .hooknum = HMAC_FRAME_DATA_RX_EVENT_D2H,
234 .priority = HMAC_HOOK_PRI_MIDDLE,
235 .hook_func = hmac_rx_frame_promis_proc,
236 };
237
238 hmac_netbuf_hook_stru g_promisc_mgmt_netbuf_hook = {
239 .hooknum = HMAC_FRAME_MGMT_RX_EVENT_D2H,
240 .priority = HMAC_HOOK_PRI_MIDDLE,
241 .hook_func = hmac_rx_frame_promis_proc,
242 };
243
hmac_promis_feature_hook_register(osal_void)244 OAL_STATIC osal_void hmac_promis_feature_hook_register(osal_void)
245 {
246 /* 注册对外接口 */
247 (osal_void)hmac_register_netbuf_hook(&g_promisc_data_netbuf_hook);
248 (osal_void)hmac_register_netbuf_hook(&g_promisc_mgmt_netbuf_hook);
249 hmac_feature_hook_register(HMAC_FHOOK_PROMIS_RX_DEAUTH_REQ_PROC, hmac_sta_rx_deauth_req_proc_for_promisc);
250 #if defined(_PRE_OS_VERSION_LITEOS) && defined(_PRE_OS_VERSION) && (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
251 hmac_feature_hook_register(HMAC_FHOOK_PROMIS_SEND_CUSTOM_FRAME, hmac_promis_send_custom_frame);
252 #endif
253 return;
254 }
255
hmac_promis_feature_hook_unregister(osal_void)256 OAL_STATIC osal_void hmac_promis_feature_hook_unregister(osal_void)
257 {
258 /* 去注册对外接口 */
259 (osal_void)hmac_unregister_netbuf_hook(&g_promisc_data_netbuf_hook);
260 (osal_void)hmac_unregister_netbuf_hook(&g_promisc_mgmt_netbuf_hook);
261 hmac_feature_hook_unregister(HMAC_FHOOK_PROMIS_RX_DEAUTH_REQ_PROC);
262 #if defined(_PRE_OS_VERSION_LITEOS) && defined(_PRE_OS_VERSION) && (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION)
263 hmac_feature_hook_unregister(HMAC_FHOOK_PROMIS_SEND_CUSTOM_FRAME);
264 #endif
265 return;
266 }
267
268 /*****************************************************************************
269 功能描述 : 配置芯片是否接收其他BSS网络内发的包
270 修改历史 :
271 1.日 期 : 2016年3月14日
272 修改内容 : 新生成函数
273 *****************************************************************************/
hmac_config_set_monitor_switch(hmac_vap_stru * hmac_vap,frw_msg * msg)274 OAL_STATIC osal_s32 hmac_config_set_monitor_switch(hmac_vap_stru *hmac_vap, frw_msg *msg)
275 {
276 mac_cfg_ps_open_stru ps_open;
277 hal_to_dmac_device_stru *hal_device = hmac_vap->hal_device;
278 osal_u8 value = msg->data[0];
279 osal_u8 promisc_switch = msg->data[1];
280
281 if (osal_unlikely(hal_device == OSAL_NULL)) {
282 oam_error_log1(0, OAM_SF_CFG, "vap_id[%d] {hmac_config_set_monitor_switch::hal_dev null}", hmac_vap->vap_id);
283 return OAL_ERR_CODE_PTR_NULL;
284 }
285 if (promisc_switch == 2) { /* 2:混杂统计打印 */
286 hmac_show_80211_frame_promisc_statistic();
287 return OAL_SUCC;
288 }
289
290 g_custom_en = 0;
291 /* 有其他过滤方式时,custom_en:4 不生效 */
292 if ((((value >> 4) & 0x1) == OSAL_TRUE) && (promisc_switch == 0)) {
293 g_custom_en = 1;
294 }
295 g_promisc_switch = promisc_switch;
296 g_promisc_mode = value & 0xF;
297 oam_warning_log2(0, OAM_SF_CFG, "{hmac_config_set_monitor_switch::promisc_switch[%d], promisc_cfg[%d]",
298 g_promisc_switch, g_promisc_mode);
299
300 hal_device->promis_switch = promisc_switch;
301 if (promisc_switch == 1) {
302 /* 混杂开启时注册 */
303 wifi_printf("hmac_config_set_monitor_switch:: switch[%d] mode[%d]\r\n", promisc_switch, value);
304 hmac_promis_feature_hook_register();
305 } else {
306 /* 混杂关闭时注册 */
307 hmac_promis_feature_hook_unregister();
308 }
309 hmac_hal_device_sync(hal_device);
310 hmac_promisc_clear_counts(); /* 混杂模式统计数组清零 */
311 ps_open.pm_ctrl_type = MAC_STA_PM_CTRL_TYPE_MONITOR; /* monitor模式低功耗控制位 */
312
313 if (hal_device->promis_switch == 0) { /* 关闭报文上报 */
314 ps_open.pm_enable = MAC_STA_PM_SWITCH_ON; /* 开启低功耗 */
315 } else {
316 ps_open.pm_enable = MAC_STA_PM_SWITCH_OFF; /* 关闭低功耗 */
317 }
318 oam_warning_log2(0, OAM_SF_CFG, "Setting Promisc mode%d! Power Manager mode%d\r\n", g_promisc_mode,
319 ps_open.pm_enable);
320 if (hmac_vap->vap_mode == WLAN_VAP_MODE_BSS_STA) { /* 须先配置低功耗模式,再配置寄存器 */
321 hmac_set_sta_pm_on_cb(hmac_vap, &ps_open);
322 }
323
324 hmac_promisc_set_monitor_hal_reg(g_promisc_mode);
325
326 return OAL_SUCC;
327 }
328
hmac_promis_init(osal_void)329 osal_u32 hmac_promis_init(osal_void)
330 {
331 /* 消息注册 */
332 /* W2H */
333 frw_msg_hook_register(WLAN_MSG_W2H_CFG_MONITOR_EN, hmac_config_set_monitor_switch);
334 return OAL_SUCC;
335 }
336
hmac_promis_deinit(osal_void)337 osal_void hmac_promis_deinit(osal_void)
338 {
339 /* 消息去注册 */
340 frw_msg_hook_unregister(WLAN_MSG_W2H_CFG_MONITOR_EN);
341 return;
342 }
343
344 #ifdef __cplusplus
345 #if __cplusplus
346 }
347 #endif
348 #endif
349