• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   文 件 名   : hmac_11r.c
15   生成日期   : 2023年3月2日
16  * 功能描述   : 11R
17  */
18 
19 /*****************************************************************************
20   1 头文件包含
21 *****************************************************************************/
22 #include "hmac_11r.h"
23 #include "wlan_types.h"
24 #include "oal_netbuf_data.h"
25 #include "mac_frame_common_rom.h"
26 #include "mac_frame.h"
27 #include "hmac_roam_if.h"
28 #include "hmac_roam_connect.h"
29 #include "diag_log_common.h"
30 #include "hmac_feature_dft.h"
31 #include "hmac_sme_sta.h"
32 #include "hmac_mgmt_bss_comm.h"
33 #include "hmac_mgmt_sta.h"
34 #include "hmac_chan_mgmt.h"
35 #include "hmac_feature_interface.h"
36 #include "frw_util_notifier.h"
37 #include "hmac_hook.h"
38 
39 #ifdef __cplusplus
40 #if __cplusplus
41 extern "C" {
42 #endif
43 #endif
44 
45 #undef THIS_FILE_ID
46 #define THIS_FILE_ID DIAG_FILE_ID_WIFI_HOST_HMAC_11R_C
47 
48 #undef THIS_MOD_ID
49 #define THIS_MOD_ID DIAG_MOD_ID_WIFI_HOST
50 
51 #ifdef _PRE_WLAN_FEATURE_11R
52 /*****************************************************************************
53   2 全局变量定义
54 *****************************************************************************/
55 hmac_11r_vap_info_stru *g_11r_vap_info[WLAN_VAP_MAX_NUM_PER_DEVICE_LIMIT] = {
56     OSAL_NULL, OSAL_NULL, OSAL_NULL, OSAL_NULL
57 };
58 
59 /*****************************************************************************
60   3 函数声明
61 *****************************************************************************/
62 
63 /*****************************************************************************
64   4 函数实现
65 *****************************************************************************/
hmac_11r_get_vap_info(const hmac_vap_stru * hmac_vap)66 OAL_STATIC hmac_11r_vap_info_stru *hmac_11r_get_vap_info(const hmac_vap_stru *hmac_vap)
67 {
68     if (hmac_vap_id_param_check(hmac_vap->vap_id) != OSAL_TRUE) {
69         return OSAL_NULL;
70     }
71 
72     return g_11r_vap_info[hmac_vap->vap_id];
73 }
74 
75 /*****************************************************************************
76 函 数 名  : hmac_11r_init_vap
77 功能描述  : 创建vap时,初始化11r vap结构体;
78 输入参数  : hmac_vap
79 输出参数  : 无
80 返 回 值  : 无
81  *****************************************************************************/
hmac_11r_add_vap(osal_void * notify_data)82 OAL_STATIC osal_bool hmac_11r_add_vap(osal_void *notify_data)
83 {
84     hmac_vap_stru *hmac_vap = (hmac_vap_stru *)notify_data;
85     osal_u8 vap_id;
86     osal_void *mem_ptr = OSAL_NULL;
87     mac_device_voe_custom_stru *mac_voe_custom_param = mac_get_pst_mac_voe_custom_param();
88 
89     if (hmac_vap_mode_param_check(hmac_vap) != OSAL_TRUE) {
90         return OSAL_FALSE;
91     }
92 
93     if (!is_legacy_sta(hmac_vap)) {
94         return OSAL_TRUE;
95     }
96 
97     vap_id = hmac_vap->vap_id;
98     if (g_11r_vap_info[vap_id] != OSAL_NULL) {
99         oam_warning_log1(0, OAM_SF_ANY, "vap_id[%d] hmac_11r_add_vap mem already malloc!", vap_id);
100         return OSAL_TRUE;
101     }
102 
103     mem_ptr = oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL, sizeof(hmac_11r_vap_info_stru), OAL_TRUE);
104     if (mem_ptr == OSAL_NULL) {
105         oam_error_log0(0, OAM_SF_ANY, "hmac_11r_add_vap mem alloc fail");
106         return OSAL_FALSE;
107     }
108 
109     (osal_void)memset_s(mem_ptr, sizeof(hmac_11r_vap_info_stru), 0, sizeof(hmac_11r_vap_info_stru));
110     /* 注册特性数据结构 */
111     g_11r_vap_info[vap_id] = (hmac_11r_vap_info_stru *)mem_ptr;
112     g_11r_vap_info[vap_id]->enable_11r = mac_voe_custom_param->en_11r;
113     g_11r_vap_info[vap_id]->enable_11r_over_ds = mac_voe_custom_param->en_11r_ds;
114 
115     return OAL_TRUE;
116 }
117 
hmac_11r_del_vap(osal_void * notify_data)118 OAL_STATIC osal_bool hmac_11r_del_vap(osal_void *notify_data)
119 {
120     osal_u8 vap_id_11r;
121     hmac_vap_stru *hmac_vap = (hmac_vap_stru *)notify_data;
122 
123     if (hmac_vap_mode_param_check(hmac_vap) != OSAL_TRUE) {
124         return OSAL_FALSE;
125     }
126 
127     if (!is_legacy_sta(hmac_vap)) {
128         return OSAL_TRUE;
129     }
130 
131     vap_id_11r = hmac_vap->vap_id;
132     if (g_11r_vap_info[vap_id_11r] != OSAL_NULL) {
133         oal_mem_free(g_11r_vap_info[vap_id_11r], OAL_TRUE);
134         g_11r_vap_info[vap_id_11r] = OSAL_NULL;
135     }
136 
137     return OAL_TRUE;
138 }
139 
140 /*
141  * 函 数 名  : hmac_roam_connect_ft_ds_change_to_air_etc
142  * 功能描述  : FT漫游由DS模式切换为Air方式重新连接
143  * 1.日    期  : 2022年3月14日
144  *   修改内容  : 新生成函数
145  */
hmac_roam_connect_ft_ds_change_to_air_etc(hmac_vap_stru * hmac_vap,osal_void * p_param)146 OAL_STATIC osal_u32 hmac_roam_connect_ft_ds_change_to_air_etc(hmac_vap_stru *hmac_vap, osal_void *p_param)
147 {
148     osal_u32 ul_ret;
149     hmac_roam_info_stru *roam_info = OAL_PTR_NULL;
150 
151     if (hmac_vap == OAL_PTR_NULL) {
152         oam_warning_log0(0, OAM_SF_ROAM, "{hmac_roam_connect_ft_ds_change_to_air_etc::vap null!}");
153         return OAL_ERR_CODE_PTR_NULL;
154     }
155 
156     if (p_param == OAL_PTR_NULL) {
157         oam_warning_log0(0, OAM_SF_ROAM, "{hmac_roam_connect_ft_ds_change_to_air_etc::param null!}");
158         return OAL_ERR_CODE_PTR_NULL;
159     }
160 
161     roam_info = hmac_get_roam_info(hmac_vap->vap_id);
162 
163     hmac_roam_main_clear(roam_info);
164     hmac_roam_main_del_timer(roam_info);
165     hmac_roam_main_change_state(roam_info, ROAM_MAIN_STATE_SCANING);
166 
167     ul_ret = hmac_roam_connect_to_bss(roam_info, p_param);
168     if (ul_ret != OAL_SUCC) {
169         return ul_ret;
170     }
171 
172     return OAL_SUCC;
173 }
174 
175 /*****************************************************************************
176  函 数 名  : hmac_roam_connect_notify_wpas
177  功能描述  : 将关联成功消息通知wpa_supplicant,以便开始4-way握手流程
178 *****************************************************************************/
hmac_roam_ft_notify_wpas(hmac_vap_stru * hmac_vap,osal_u8 * mac_hdr,osal_u16 msg_len)179 OAL_STATIC osal_u32 hmac_roam_ft_notify_wpas(hmac_vap_stru *hmac_vap, osal_u8 *mac_hdr,
180     osal_u16 msg_len)
181 {
182     osal_u8 *evt = OSAL_NULL;
183     osal_u32 len;
184 
185     hmac_roam_ft_stru *ft_event = OAL_PTR_NULL;
186     osal_u8 *target_bssid = OSAL_NULL;
187     osal_u16 ie_offset;
188     osal_s32 ret;
189     frw_msg msg_info = {0};
190 
191     if (mac_get_frame_type_and_subtype(mac_hdr) == (WLAN_FC0_SUBTYPE_AUTH | WLAN_FC0_TYPE_MGT)) {
192         ie_offset = OAL_AUTH_IE_OFFSET;
193         /*********************************************************/
194         /*              Management Frame Format                  */
195         /* ------------------------------------------------------*/
196         /* |Frame Control|Duration|DA|SA|BSSID|Sequence Control| */
197         /* ------------------------------------------------------*/
198         /* | 2           |2       |6 |6 |6    |2               | */
199         /* ------------------------------------------------------*/
200         /*********************************************************/
201         /* Auth的target ap bssid偏移量为mac_hdr结尾向前偏移8字节 */
202         target_bssid = mac_hdr + MAC_80211_FRAME_LEN - 8;
203     } else {
204         ie_offset = OAL_FT_ACTION_IE_OFFSET;
205         /* FT RESP ACTION帧的target ap bssid偏移量为mac_hdr结尾向后偏移8字节 */
206         target_bssid = mac_hdr + MAC_80211_FRAME_LEN + 8;
207     }
208     if (msg_len <= ie_offset) {
209         oam_error_log2(0, OAM_SF_ROAM, "hmac_roam_ft_notify_wpas::msg_len[%d] <= ie_offset[%d]",
210             msg_len, ie_offset);
211         return OAL_FAIL;
212     }
213     len = sizeof(hmac_roam_ft_stru) + msg_len - ie_offset;
214     evt = oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL, (osal_u16)len, OAL_TRUE);
215     if (evt == OSAL_NULL) {
216         return OAL_ERR_CODE_ALLOC_MEM_FAIL;
217     }
218     (osal_void)memset_s(evt, len, 0, len);
219     ft_event = (hmac_roam_ft_stru*)evt;
220     /* save target bssid */
221     oal_set_mac_addr(ft_event->bssid, target_bssid);
222     /* save ft ie */
223     ft_event->ft_ie_len = msg_len - ie_offset;
224     ret = memcpy_s(evt + sizeof(hmac_roam_ft_stru), msg_len - ie_offset, mac_hdr + ie_offset, msg_len - ie_offset);
225     if (ret != EOK) {
226         oal_mem_free(evt, OSAL_TRUE);
227         evt = OSAL_NULL;
228         return OAL_FAIL;
229     }
230 
231     msg_info.data = evt;
232     msg_info.data_len = (osal_u16)len;
233     ret = frw_asyn_host_post_msg(WLAN_MSG_H2W_FT_EVENT_STA, FRW_POST_PRI_LOW, hmac_vap->vap_id, &msg_info);
234     oal_mem_free(evt, OSAL_TRUE);
235     evt = OSAL_NULL;
236     if (ret != OAL_SUCC) {
237         oam_warning_log2(0, OAM_SF_ROAM, "{hmac_roam_ft_notify_wpas, post msg fail} msg[%d] ret[%d]",
238             WLAN_MSG_H2W_FT_EVENT_STA, ret);
239         return OAL_FAIL;
240     }
241     return OAL_SUCC;
242 }
243 
hmac_encap_ft_req(hmac_vap_stru * hmac_vap,osal_u8 * ft_buff,const hmac_roam_info_stru * roam_info,osal_u16 * ft_len)244 OAL_STATIC void hmac_encap_ft_req(hmac_vap_stru *hmac_vap, osal_u8 *ft_buff, const hmac_roam_info_stru *roam_info,
245     osal_u16 *ft_len)
246 {
247     osal_u8 *my_mac_addr = OSAL_NULL;
248     osal_u8 *current_bssid = OSAL_NULL;
249     osal_u16 app_ie_len;
250 
251     my_mac_addr = mac_mib_get_station_id(hmac_vap);
252     current_bssid = hmac_vap->bssid;
253     /*************************************************************************/
254     /*                        Management Frame Format                        */
255     /* --------------------------------------------------------------------  */
256     /* |Frame Control|Duration|DA|SA|BSSID|Sequence Control|Frame Body|FCS|  */
257     /* --------------------------------------------------------------------  */
258     /* | 2           |2       |6 |6 |6    |2               |0 - 2312  |4  |  */
259     /* --------------------------------------------------------------------  */
260     /*                                                                       */
261     /*************************************************************************/
262 
263     /*************************************************************************/
264     /*                Set the fields in the frame header                     */
265     /*************************************************************************/
266     /* All the fields of the Frame Control Field are set to zero. Only the   */
267     /* Type/Subtype field is set.                                            */
268     mac_hdr_set_frame_control(ft_buff, WLAN_FC0_SUBTYPE_ACTION);
269     /* Set DA  */
270     oal_set_mac_addr(((mac_ieee80211_frame_stru *)ft_buff)->address1, current_bssid);
271     /* Set SA  */
272     oal_set_mac_addr(((mac_ieee80211_frame_stru *)ft_buff)->address2, my_mac_addr);
273     /* Set SSID  */
274     oal_set_mac_addr(((mac_ieee80211_frame_stru *)ft_buff)->address3, current_bssid);
275     /* 设置分片序号为0 */
276     mac_hdr_set_fragment_number(ft_buff, 0);
277 
278     /*************************************************************************/
279     /*                Set the contents of the frame body                     */
280     /*************************************************************************/
281 
282     /*************************************************************************/
283     /*                  FT Request Frame - Frame Body                        */
284     /* --------------------------------------------------------------------- */
285     /* | Category | Action | STA Addr |Target AP Addr | FT Req frame body  | */
286     /* --------------------------------------------------------------------- */
287     /* |     1    |   1    |     6    |       6       |       varibal      | */
288     /* --------------------------------------------------------------------- */
289     /*                                                                       */
290     /*************************************************************************/
291     ft_buff += MAC_80211_FRAME_LEN;
292     *ft_len = MAC_80211_FRAME_LEN;
293 
294     ft_buff[0] = MAC_ACTION_CATEGORY_FAST_BSS_TRANSITION;
295     ft_buff[1] = MAC_FT_ACTION_REQUEST;
296     ft_buff += 2; /* 2表示Category+Action字段长度 */
297     *ft_len += 2; /* 2表示Category+Action字段长度 */
298 
299     oal_set_mac_addr(ft_buff, my_mac_addr);
300     ft_buff += OAL_MAC_ADDR_LEN;
301     *ft_len += OAL_MAC_ADDR_LEN;
302 
303     oal_set_mac_addr(ft_buff, roam_info->connect.bss_dscr->bssid);
304     ft_buff += OAL_MAC_ADDR_LEN;
305     *ft_len += OAL_MAC_ADDR_LEN;
306 
307     hmac_add_app_ie_etc((osal_void *)hmac_vap, ft_buff, &app_ie_len, OAL_APP_FT_IE);
308     ft_buff += app_ie_len;
309     *ft_len += app_ie_len;
310 }
311 
312 /*****************************************************************************
313  函 数 名  : hmac_roam_send_ft_req
314  功能描述  : 发送FT REQUEST帧
315  输出参数  : 无
316  返 回 值  : OAL_SUCC 或 失败错误码
317 *****************************************************************************/
hmac_roam_send_ft_req(hmac_roam_info_stru * roam_info,osal_void * param)318 OAL_STATIC osal_u32 hmac_roam_send_ft_req(hmac_roam_info_stru *roam_info, osal_void *param)
319 {
320     osal_u32              ret;
321     hmac_vap_stru          *hmac_vap;
322     hmac_user_stru         *hmac_user;
323     oal_netbuf_stru        *ft_frame;
324     osal_u8              *ft_buff;
325     mac_tx_ctl_stru        *tx_ctl;
326     osal_u16              ft_len;
327     hmac_11r_vap_info_stru *hmac_11r_vap_info = OSAL_NULL;
328 
329     unref_param(param);
330 
331     ret = hmac_roam_connect_check_state(roam_info, MAC_VAP_STATE_UP, ROAM_MAIN_STATE_CONNECTING,
332         ROAM_CONNECT_STATE_INIT);
333     if ((ret != OAL_SUCC)) {
334         oam_warning_log1(0, OAM_SF_ROAM, "{hmac_roam_send_ft_req::check_state fail[%d]!}", ret);
335         return ret;
336     }
337 
338     hmac_vap  = roam_info->hmac_vap;
339     hmac_user = roam_info->hmac_user;
340     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
341     if (hmac_11r_vap_info == OSAL_NULL || hmac_11r_vap_info->enable_11r != OAL_TRUE) {
342         return OAL_FAIL;
343     }
344 
345     ft_frame = OAL_MEM_NETBUF_ALLOC(OAL_NORMAL_NETBUF, WLAN_MEM_NETBUF_SIZE2, OAL_NETBUF_PRIORITY_MID);
346     if (ft_frame == OAL_PTR_NULL) {
347         oam_error_log1(0, OAM_SF_ROAM, "vap_id[%d] {hmac_roam_send_ft_req::malloc fail.}", hmac_vap->vap_id);
348         return OAL_ERR_CODE_PTR_NULL;
349     }
350 
351     ft_buff = (osal_u8 *)OAL_NETBUF_HEADER(ft_frame);
352     memset_s(oal_netbuf_cb(ft_frame), FT_NETBUF_CB_LENTH, 0, FT_NETBUF_CB_LENTH);
353     memset_s(ft_buff, MAC_80211_FRAME_LEN, 0, MAC_80211_FRAME_LEN);
354 
355     hmac_encap_ft_req(hmac_vap, ft_buff, roam_info, &ft_len);
356 
357     oal_netbuf_put(ft_frame, ft_len);
358 
359     /* 为填写发送描述符准备参数 */
360     tx_ctl = (mac_tx_ctl_stru *)oal_netbuf_cb(ft_frame);
361     mac_get_cb_mpdu_len(tx_ctl) = ft_len;
362     mac_get_cb_tx_user_idx(tx_ctl) = (osal_u8)hmac_user->assoc_id;
363     mac_get_cb_netbuf_num(tx_ctl) = 1;
364 
365     /* 抛事件让dmac将该帧发送 */
366     ret = hmac_tx_mgmt_send_event_etc(hmac_vap, ft_frame, ft_len);
367     if ((ret != OAL_SUCC)) {
368         oal_netbuf_free(ft_frame);
369         oam_error_log2(0, OAM_SF_ROAM,
370             "vap_id[%d] {hmac_roam_send_ft_req::hmac_tx_mgmt_send_event_etc failed[%d].}", hmac_vap->vap_id, ret);
371         return ret;
372     }
373 
374     hmac_roam_connect_change_state(roam_info, ROAM_CONNECT_STATE_WAIT_FT_COMP);
375 
376     /* 启动认证超时定时器 */
377     hmac_roam_connect_start_timer(roam_info, ROAM_AUTH_TIME_MAX);
378 
379     return OAL_SUCC;
380 }
381 /*****************************************************************************
382  函 数 名  : hmac_roam_process_ft_rsp
383  输出参数  : 无
384  返 回 值  : OAL_SUCC 或 失败错误码
385 *****************************************************************************/
hmac_roam_process_ft_rsp(hmac_roam_info_stru * roam_info,osal_void * p_param)386 OAL_STATIC osal_u32 hmac_roam_process_ft_rsp(hmac_roam_info_stru *roam_info, osal_void *p_param)
387 {
388     osal_u32                   ret;
389     hmac_vap_stru               *hmac_vap;
390     oal_netbuf_stru             *net_buffer;
391     mac_rx_ctl_stru            *pst_rx_ctrl;
392     osal_u8                   *mac_hdr;
393     osal_u16                   auth_status;
394     hmac_11r_vap_info_stru *hmac_11r_vap_info = OSAL_NULL;
395 
396     ret = hmac_roam_connect_check_state(roam_info, MAC_VAP_STATE_UP, ROAM_MAIN_STATE_CONNECTING,
397         ROAM_CONNECT_STATE_WAIT_FT_COMP);
398     if ((ret != OAL_SUCC)) {
399         oam_warning_log1(0, OAM_SF_ROAM, "{hmac_roam_process_ft_rsp::check_state fail[%d]}", ret);
400         return ret;
401     }
402 
403     hmac_vap = roam_info->hmac_vap;
404     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
405     if (hmac_11r_vap_info == OSAL_NULL || hmac_11r_vap_info->enable_11r != OAL_TRUE) {
406         return OAL_FAIL;
407     }
408 
409     net_buffer  = (oal_netbuf_stru *)p_param;
410     pst_rx_ctrl    = (mac_rx_ctl_stru *)oal_netbuf_cb(net_buffer);
411     mac_hdr    = (osal_u8 *)mac_get_rx_cb_mac_header_addr(pst_rx_ctrl);
412 
413     auth_status = mac_get_ft_status(mac_hdr);
414     if (auth_status != MAC_SUCCESSFUL_STATUSCODE) {
415         oam_warning_log1(0, OAM_SF_ROAM, "{hmac_roam_process_ft_rsp::status [%d], change to over air}", auth_status);
416         roam_info->connect.ft_force_air = OAL_TRUE;
417         roam_info->connect.ft_failed = OAL_TRUE;
418         ret = hmac_roam_connect_ft_ds_change_to_air_etc(hmac_vap, roam_info->connect.bss_dscr);
419         if (ret != OAL_SUCC) {
420             oam_warning_log1(0, OAM_SF_ROAM, "{hmac_roam_process_ft_rsp::over ds change to over air failed [%d]}", ret);
421             return hmac_roam_connect_fail(roam_info);
422         }
423         return OAL_SUCC;
424     }
425 
426     /* 上报FT成功消息给APP,以便APP下发新的FT_IE用于发送reassociation */
427     ret = hmac_roam_ft_notify_wpas(hmac_vap, mac_hdr, pst_rx_ctrl->frame_len);
428     if (ret != OAL_SUCC) {
429         oam_error_log1(0, OAM_SF_ROAM, "{hmac_roam_process_ft_rsp::hmac_roam_ft_notify_wpas failed [%d]}", ret);
430         return ret;
431     }
432 
433     hmac_roam_connect_change_state(roam_info, ROAM_CONNECT_STATE_WAIT_ASSOC_COMP);
434 
435     /* 启动关联超时定时器 */
436     hmac_roam_connect_start_timer(roam_info, ROAM_ASSOC_TIME_MAX);
437     return OAL_SUCC;
438 }
439 
hmac_roam_auth_seq2_11r_process(hmac_vap_stru * hmac_vap,hmac_roam_info_stru * roam_info,mac_rx_ctl_stru * rx_ctrl,osal_u8 * mac_hdr)440 OAL_STATIC osal_u32 hmac_roam_auth_seq2_11r_process(hmac_vap_stru *hmac_vap, hmac_roam_info_stru *roam_info,
441     mac_rx_ctl_stru *rx_ctrl, osal_u8 *mac_hdr)
442 {
443     osal_u32 ret;
444     hmac_11r_vap_info_stru *hmac_11r_vap_info = OSAL_NULL;
445 
446     if (hmac_vap == OSAL_NULL || roam_info == OSAL_NULL || rx_ctrl == OSAL_NULL || mac_hdr == OSAL_NULL) {
447         return OAL_ERR_CODE_PTR_NULL;
448     }
449 
450     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
451     if (hmac_11r_vap_info == OSAL_NULL) {
452         return OAL_ERR_CODE_PTR_NULL;
453     }
454 
455     if (hmac_11r_vap_info->enable_11r == OAL_TRUE) {
456         if (mac_get_auth_alg(mac_hdr) == WLAN_WITP_AUTH_FT) {
457             /* 上报FT成功消息给APP,以便APP下发新的FT_IE用于发送reassociation */
458             ret = hmac_roam_ft_notify_wpas(hmac_vap, mac_hdr, rx_ctrl->frame_len);
459             if ((ret != OAL_SUCC)) {
460                 oam_error_log2(0, OAM_SF_ROAM,
461                     "vap_id[%d] {hmac_roam_process_auth_seq2::hmac_roam_ft_notify_wpas failed[%d].}",
462                     hmac_vap->vap_id, ret);
463                 return ret;
464             }
465 
466             hmac_roam_connect_change_state(roam_info, ROAM_CONNECT_STATE_WAIT_ASSOC_COMP);
467             /* 启动关联超时定时器 */
468             hmac_roam_connect_start_timer(roam_info, ROAM_ASSOC_TIME_MAX);
469             return OAL_SUCC;
470         }
471     }
472 
473     return OAL_CONTINUE;
474 }
475 
476 /*****************************************************************************
477  函 数 名  : hmac_roam_ft_timeout
478  功能描述  : 处理认证超时,漫游期间最多3次auth
479  输出参数  : 无
480  返 回 值  : OAL_SUCC 或 失败错误码
481 *****************************************************************************/
hmac_roam_ft_timeout(hmac_roam_info_stru * roam_info,osal_void * p_param)482 OAL_STATIC osal_u32 hmac_roam_ft_timeout(hmac_roam_info_stru *roam_info, osal_void *p_param)
483 {
484     osal_u32 ret;
485     hmac_vap_stru *hmac_vap;
486     hmac_11r_vap_info_stru *hmac_11r_vap_info = OSAL_NULL;
487 
488     unref_param(p_param);
489     ret = hmac_roam_connect_check_state(roam_info, MAC_VAP_STATE_UP, ROAM_MAIN_STATE_CONNECTING,
490         ROAM_CONNECT_STATE_WAIT_FT_COMP);
491     if (ret != OAL_SUCC) {
492         oam_warning_log1(0, OAM_SF_ROAM, "{hmac_roam_ft_timeout::check_state fail[%d]!}", ret);
493         return ret;
494     }
495 
496     hmac_vap  = roam_info->hmac_vap;
497     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
498     if (hmac_11r_vap_info == OSAL_NULL) {
499         return OAL_ERR_CODE_PTR_NULL;
500     }
501 
502     if (hmac_11r_vap_info->enable_11r != OAL_TRUE) {
503         return OAL_SUCC;
504     }
505 
506     if (++roam_info->connect.ft_num >= MAX_AUTH_CNT) {
507         return hmac_roam_connect_fail(roam_info);
508     }
509 
510     hmac_roam_connect_change_state(roam_info, ROAM_CONNECT_STATE_INIT);
511 
512     oam_warning_log0(0, OAM_SF_ROAM, "{hmac_roam_ft_timeout::change to ft over the air!}");
513     roam_info->connect.ft_force_air = OAL_TRUE;
514     roam_info->connect.ft_failed = OAL_TRUE;
515     ret = hmac_roam_connect_ft_ds_change_to_air_etc(hmac_vap, roam_info->connect.bss_dscr);
516     if (ret != OAL_SUCC) {
517         oam_warning_log1(0, OAM_SF_ROAM,
518             "{hmac_roam_ft_timeout::hmac_roam_connect_ft_ds_change_to_air_etc failed[%d].}", ret);
519         return hmac_roam_connect_fail(roam_info);
520     }
521 
522     return ret;
523 }
524 
525 /*****************************************************************************
526  函 数 名  : hmac_roam_connect_ft_reassoc_etc
527  输出参数  : 无
528  返 回 值  : OAL_SUCC 或 失败错误码
529 *****************************************************************************/
hmac_roam_connect_ft_reassoc_etc(hmac_vap_stru * hmac_vap)530 OAL_STATIC osal_u32 hmac_roam_connect_ft_reassoc_etc(hmac_vap_stru *hmac_vap)
531 {
532     hmac_roam_info_stru                             *roam_info;
533     hmac_join_req_stru                               join_req;
534     osal_u32                                       ret;
535     mac_bss_dscr_stru                               *bss_dscr;
536     hmac_11r_vap_info_stru  *hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
537 
538     if (hmac_11r_vap_info == OSAL_NULL) {
539         return OAL_ERR_CODE_PTR_NULL;
540     }
541 
542     roam_info = hmac_get_roam_info(hmac_vap->vap_id);
543     bss_dscr = roam_info->connect.bss_dscr;
544 
545     if (roam_info->hmac_user == OAL_PTR_NULL) {
546         return OAL_ERR_CODE_PTR_NULL;
547     }
548 
549     oal_set_mac_addr(roam_info->hmac_user->user_mac_addr, bss_dscr->bssid);
550     if (memcpy_s(hmac_vap->supp_rates, bss_dscr->num_supp_rates, bss_dscr->supp_rates,
551         bss_dscr->num_supp_rates) != EOK) {
552         oam_warning_log0(0, OAM_SF_CFG, "{hmac_roam_connect_ft_reassoc_etc data::memcpy err.}");
553     }
554     mac_mib_set_SupportRateSetNums(hmac_vap, bss_dscr->num_supp_rates);
555 
556     if ((mac_mib_get_ft_over_ds(hmac_vap) == OAL_TRUE) && (hmac_11r_vap_info->enable_11r_over_ds == OAL_TRUE)) {
557         /* 配置join参数 */
558         hmac_prepare_join_req_etc(&join_req, bss_dscr);
559 
560         ret = hmac_sta_update_join_req_params_etc(hmac_vap, &join_req);
561         if (ret != OAL_SUCC) {
562             oam_error_log2(0, OAM_SF_SCAN,
563                 "vap_id[%d] {hmac_roam_connect_ft_reassoc_etc::hmac_sta_update_join_req_params_etc fail[%d].}",
564                 hmac_vap->vap_id, ret);
565             return ret;
566         }
567     }
568 
569     /* 发送关联请求 */
570     ret = hmac_roam_send_reassoc_req(roam_info);
571     if (ret != OAL_SUCC) {
572         oam_error_log2(0, OAM_SF_ROAM,
573             "vap_id[%d] {hmac_roam_connect_ft_reassoc_etc::hmac_roam_send_assoc_req failed[%d].}",
574             hmac_vap->vap_id, ret);
575         return ret;
576     }
577 
578     return OAL_SUCC;
579 }
580 
hmac_roam_reassoc_check(OAL_CONST hmac_vap_stru * hmac_vap)581 OAL_STATIC osal_u32 hmac_roam_reassoc_check(OAL_CONST hmac_vap_stru *hmac_vap)
582 {
583     hmac_roam_info_stru *roam_info = OAL_PTR_NULL;
584     osal_u8 vap_id;
585 
586     if (hmac_vap == OAL_PTR_NULL) {
587         oam_error_log0(0, OAM_SF_ROAM, "{hmac_roam_reassoc_etc::vap null!}");
588         return OAL_ERR_CODE_ROAM_INVALID_VAP;
589     }
590 
591     vap_id = hmac_vap->vap_id;
592     roam_info = hmac_get_roam_info(vap_id);
593     if (roam_info == OAL_PTR_NULL) {
594         oam_error_log1(0, OAM_SF_ROAM, "vap_id[%d] {hmac_roam_reassoc_etc::roam info null!}", vap_id);
595         return OAL_ERR_CODE_ROAM_INVALID_VAP;
596     }
597 
598     /* 漫游开关没有开时,不处理 */
599     if (roam_info->enable == 0) {
600         oam_error_log1(0, OAM_SF_ROAM, "vap_id[%d] {hmac_roam_reassoc_etc::roam disabled.}",
601                        hmac_vap->vap_id);
602         return OAL_ERR_CODE_ROAM_DISABLED;
603     }
604 
605     /* 主状态机为非CONNECTING状态,失败 */
606     if (roam_info->main_state != ROAM_MAIN_STATE_CONNECTING) {
607         oam_warning_log2(0, OAM_SF_ROAM,
608             "vap_id[%d] {hmac_roam_reassoc_etc::roam_en_main_state=[%d] not ROAM_MAIN_STATE_CONNECTING, return.}",
609             hmac_vap->vap_id,
610             roam_info->main_state);
611         return OAL_ERR_CODE_ROAM_STATE_UNEXPECT;
612     }
613 
614     /* CONNECT状态机为非WAIT_JOIN状态,失败 */
615     if (roam_info->connect.state != ROAM_CONNECT_STATE_WAIT_ASSOC_COMP) {
616         oam_error_log2(0, OAM_SF_ROAM,
617             "vap_id[%d] {hmac_roam_reassoc_etc::connect state[%d] error.}", hmac_vap->vap_id,
618             roam_info->connect.state);
619         return OAL_ERR_CODE_ROAM_STATE_UNEXPECT;
620     }
621     return OAL_SUCC;
622 }
623 
624 /*****************************************************************************
625  函 数 名  : hmac_roam_reassoc_etc
626  返 回 值  : OAL_SUCC 或 失败错误码
627 *****************************************************************************/
hmac_roam_reassoc_etc(hmac_vap_stru * hmac_vap)628 OAL_STATIC osal_u32 hmac_roam_reassoc_etc(hmac_vap_stru *hmac_vap)
629 {
630     hmac_roam_info_stru              *roam_info;
631     osal_u32                        ul_ret;
632     osal_u8                         vap_id;
633     mac_bss_dscr_stru                *bss_dscr;
634     hmac_11r_vap_info_stru  *hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
635 
636     if (hmac_11r_vap_info == OSAL_NULL) {
637         return OAL_ERR_CODE_PTR_NULL;
638     }
639 
640     ul_ret = hmac_roam_reassoc_check(hmac_vap);
641     if (ul_ret != OAL_SUCC) {
642         return ul_ret;
643     }
644 
645     vap_id = hmac_vap->vap_id;
646     roam_info = hmac_get_roam_info(vap_id);
647     if (mac_mib_get_ft_trainsistion(hmac_vap) == OSAL_TRUE) {
648         if ((mac_mib_get_ft_over_ds(hmac_vap) == OAL_TRUE) && (hmac_11r_vap_info->enable_11r_over_ds == OAL_TRUE)) {
649             /* over ds 首先pause user */
650             bss_dscr = roam_info->connect.bss_dscr;
651             if (bss_dscr == OAL_PTR_NULL) {
652                 oam_error_log1(0, OAM_SF_ROAM,
653                     "vap_id[%d] {hmac_roam_reassoc_etc::bss_dscr is null.}",
654                     hmac_vap->vap_id);
655                 return OAL_ERR_CODE_ROAM_NO_VALID_BSS;
656             }
657 
658             ul_ret = hmac_roam_pause_user_etc(hmac_vap);
659             if (ul_ret != OAL_SUCC) {
660                 oam_warning_log1(0, OAM_SF_ROAM,
661                     "{hmac_roam_reassoc_etc::hmac_roam_reassoc_etc fail[%ld]!}", ul_ret);
662                 return ul_ret;
663             }
664         }
665         oam_warning_log2(0, OAM_SF_ROAM,
666                          "vap_id[%d] {hmac_roam_reassoc_etc::ft_over_ds=[%d],to send reassoc!}", vap_id,
667                          mac_mib_get_ft_over_ds(hmac_vap));
668         ul_ret = hmac_roam_connect_ft_reassoc_etc(hmac_vap);
669         if (ul_ret != OAL_SUCC) {
670             oam_warning_log2(0, OAM_SF_ROAM,
671                 "vap_id[%d] {hmac_roam_reassoc_etc::hmac_roam_connect_process_ft FAIL[%d]!}", vap_id, ul_ret);
672             return ul_ret;
673         }
674     }
675 
676     return OAL_SUCC;
677 }
678 
679 /*****************************************************************************
680  功能描述 : 填充mdie
681 *****************************************************************************/
mac_set_md_ie_etc(hmac_vap_stru * hmac_vap,osal_u8 * buffer,osal_u8 * ie_len)682 OAL_STATIC osal_void mac_set_md_ie_etc(hmac_vap_stru *hmac_vap, osal_u8 *buffer, osal_u8 *ie_len)
683 {
684     hmac_11r_vap_info_stru *hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
685 
686     if (mac_mib_get_ft_trainsistion(hmac_vap) != OSAL_TRUE) {
687         *ie_len = 0;
688         return;
689     }
690 
691     /***************************************************************************
692                     ---------------------------------------------------
693                     |Element ID | Length | MDID| FT Capbility & Policy|
694                     ---------------------------------------------------
695            Octets:  |1          | 1      | 2   |  1                   |
696                     ---------------------------------------------------
697     ***************************************************************************/
698 
699     *buffer = MAC_EID_MOBILITY_DOMAIN;
700     *(buffer + 1) = 3;                                          /* IE内容长度3字节 */
701     *(buffer + 2) = mac_mib_get_ft_mdid(hmac_vap) & 0xFF;        /* IE第2字节 */
702     *(buffer + 3) = (mac_mib_get_ft_mdid(hmac_vap) >> 8) & 0xFF; /* IE第3字节. 右移8 bit */
703     *(buffer + 4) = 0;                                          /* IE第4字节 */
704 
705     /***************************************************************************
706                     ------------------------------------------
707                     |FT over DS| RRP Capability | Reserved   |
708                     ------------------------------------------
709              Bits:  |1         | 1              | 6          |
710                     ------------------------------------------
711     ***************************************************************************/
712     if (hmac_11r_vap_info->enable_11r_over_ds == OSAL_TRUE) {
713         *(buffer + 4) += 1;     /* buffer偏移4字节 */
714     }
715     if (mac_mib_get_ft_resource_req(hmac_vap) == OSAL_TRUE) {
716         *(buffer + 4) += 2;     /* buffer偏移4字节的内容设置为2 */
717     }
718     *ie_len = 5;    /* IE长度5字节 */
719 }
720 
mac_set_rde_ie_etc(osal_u8 * buffer,osal_u8 * ie_len)721 OAL_STATIC osal_void mac_set_rde_ie_etc(osal_u8 *buffer, osal_u8 *ie_len)
722 {
723     /*********************************************************************************************
724               -------------------------------------------------------------------
725               |Element ID | Length | RDE Identifier | Res Dscr Cnt| Status Code |
726               -------------------------------------------------------------------
727      Octets:  |1          | 1      | 1              |  1          |   2         |
728               -------------------------------------------------------------------
729     ***********************************************************************************************/
730     *buffer = MAC_EID_RDE;
731     *(buffer + 1) = 4;  /* IE内容长度4字节 */
732     *(buffer + 2) = 0;  /* IE第2字节 */
733     *(buffer + 3) = 1;  /* IE第3字节 */
734     *(buffer + 4) = 0;  /* IE第4字节 */
735 
736     *ie_len = 6;        /* IE长度6字节 */
737 }
738 
mac_set_tspec_ie_etc(osal_u8 * buffer,osal_u8 * ie_len,osal_u8 tid)739 OAL_STATIC osal_void mac_set_tspec_ie_etc(osal_u8 *buffer, osal_u8 *ie_len, osal_u8 tid)
740 {
741     osal_u8 len = 0;
742     mac_ts_info_stru *ts_info;
743 
744     /***********************************************************************************************
745               --------------------------------------------------------------------------------------
746               |Element ID|Length|TS Info|Nominal MSDU Size|Max MSDU Size|Min Serv Itvl|Max Serv Itvl|
747               ---------------------------------------------------------------------------------------
748      Octets:  |1         | 1(55)| 3     |  2              |   2         |4            |4            |
749               ---------------------------------------------------------------------------------------
750               | Inactivity Itvl | Suspension Itvl | Serv Start Time |Min Data Rate | Mean Data Rate |
751               ---------------------------------------------------------------------------------------
752      Octets:  |4                | 4               | 4               |4             |  4             |
753               ---------------------------------------------------------------------------------------
754               |Peak Data Rate|Burst Size|Delay Bound|Min PHY Rate|Surplus BW Allowance  |Medium Time|
755               ---------------------------------------------------------------------------------------
756      Octets:  |4             |4         | 4         | 4          |  2                   |2          |
757               ---------------------------------------------------------------------------------------
758 
759     ***********************************************************************************************/
760 
761     *buffer = MAC_EID_TSPEC;
762     *(buffer + 1) = 55; /* IE内容长度55字节 */
763     len += 2;           /* buffer偏移2字节 */
764 
765     memset_s(buffer + len, *(buffer + 1), 0, *(buffer + 1));
766 
767     ts_info = (mac_ts_info_stru *)(buffer + len); // TS Info
768     len += 3;           /* buffer偏移3字节 */
769 
770     ts_info->tsid = tid;
771     ts_info->direction = 3; // 3 for bidirection
772     ts_info->apsd = 1;
773     ts_info->user_prio = tid;
774 
775     *(osal_u16 *)(buffer + len) = 0x812c; // Nominal MSDU Size
776     len += 28;          /* buffer偏移28字节 */
777 
778     *(osal_u32 *)(buffer + len) = 0x0001D4C0; // Mean Data Rate
779     len += 16;          /* buffer偏移16字节 */
780 
781     *(osal_u16 *)(buffer + len) = 0x3000; // Surplus BW Allowance
782 
783     *ie_len = 57;       /* IE长度57字节 */
784 }
785 
hmac_11r_set_md_ie(hmac_vap_stru * hmac_vap,osal_u8 ** buffer,osal_u8 * ie_len)786 OAL_STATIC osal_void hmac_11r_set_md_ie(hmac_vap_stru *hmac_vap, osal_u8 **buffer, osal_u8 *ie_len)
787 {
788     wlan_wme_ac_type_enum_uint8 aci;
789     wlan_wme_ac_type_enum_uint8 target_ac;
790     osal_u8 tid;
791     hmac_11r_vap_info_stru *hmac_11r_vap_info = OSAL_NULL;
792 
793     if (hmac_vap == OSAL_NULL || buffer == OSAL_NULL || ie_len == OSAL_NULL) {
794         return;
795     }
796 
797     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
798     if (hmac_11r_vap_info == OSAL_NULL || hmac_11r_vap_info->enable_11r != OAL_TRUE) {
799         return;
800     }
801 
802     if (hmac_vap->reassoc_flag == OAL_FALSE) {
803         mac_set_md_ie_etc(hmac_vap, *buffer, ie_len);
804         *buffer += *ie_len;
805     } else {
806         /* Reasoc中包含RIC-Req */
807         for (aci = WLAN_WME_AC_BE; aci < WLAN_WME_AC_BUTT; aci++) {
808             if (mac_mib_get_qap_edca_table_mandatory(hmac_vap, aci) != 0) {
809                 target_ac = aci;
810                 tid = wlan_wme_ac_to_tid(target_ac);
811                 mac_set_rde_ie_etc(*buffer, ie_len);
812                 *buffer += *ie_len;
813 
814                 mac_set_tspec_ie_etc(*buffer, ie_len, tid);
815                 *buffer += *ie_len;
816             }
817         }
818     }
819 
820     return;
821 }
822 
823 /*****************************************************************************
824  功能描述 : 初始化Fast BSS Trisition信息
825 *****************************************************************************/
hmac_mib_init_ft_cfg_etc(hmac_vap_stru * hmac_vap,const osal_u8 * mde)826 OAL_STATIC osal_u32 hmac_mib_init_ft_cfg_etc(hmac_vap_stru *hmac_vap, const osal_u8 *mde)
827 {
828     if (hmac_vap == OAL_PTR_NULL) {
829         oam_error_log0(0, OAM_SF_WPA, "{hmac_mib_init_ft_cfg_etc::param null.}");
830         return OAL_ERR_CODE_PTR_NULL;
831     }
832 
833     if (hmac_vap->mib_info == OAL_PTR_NULL) {
834         oam_error_log0(0, OAM_SF_WPA, "{hmac_mib_init_ft_cfg_etc::pst_mib_info null.}");
835         return OAL_ERR_CODE_PTR_NULL;
836     }
837 
838     if (mac_mib_get_authentication_mode(hmac_vap) != WLAN_WITP_AUTH_FT) {
839         mac_mib_set_ft_trainsistion(hmac_vap, OSAL_FALSE);
840         return OAL_SUCC;
841     }
842 
843     if ((mde == OAL_PTR_NULL) || (mde[0] != MAC_EID_MOBILITY_DOMAIN) || (mde[1] != 3)) { /* MDIE长度不是3字节 */
844         mac_mib_set_ft_trainsistion(hmac_vap, OSAL_FALSE);
845         return OAL_SUCC;
846     }
847 
848     mac_mib_set_ft_trainsistion(hmac_vap, OSAL_TRUE);
849     mac_mib_set_ft_mdid(hmac_vap, (osal_u16)((mde[3] << 8) | mde[2]));        /* MDIE第3字节左移8 bit,或上MDIE第2字节 */
850     mac_mib_set_ft_over_ds(hmac_vap, ((mde[4] & BIT0) != 0) ? OSAL_TRUE : OSAL_FALSE);        /* MDIE第4字节 */
851     mac_mib_set_ft_resource_req(hmac_vap, ((mde[4] & BIT1) != 0) ? OSAL_TRUE : OSAL_FALSE);   /* MDIE第4字节 */
852 
853     return OAL_SUCC;
854 }
855 
856 /*****************************************************************************
857  功能描述 : 获取当前的md id
858 *****************************************************************************/
mac_mib_get_md_id_etc(hmac_vap_stru * hmac_vap,osal_u16 * mdid)859 OAL_STATIC osal_u32 mac_mib_get_md_id_etc(hmac_vap_stru *hmac_vap, osal_u16 *mdid)
860 {
861     if (hmac_vap == OAL_PTR_NULL) {
862         oam_error_log0(0, OAM_SF_WPA, "{hmac_mib_init_ft_cfg_etc::param null.}");
863         return OAL_ERR_CODE_PTR_NULL;
864     }
865 
866     if (hmac_vap->mib_info == OAL_PTR_NULL) {
867         oam_error_log0(0, OAM_SF_WPA, "{hmac_mib_init_ft_cfg_etc::pst_mib_info null.}");
868         return OAL_ERR_CODE_PTR_NULL;
869     }
870 
871     if (mac_mib_get_ft_trainsistion(hmac_vap) == OAL_FALSE) {
872         return OAL_FAIL;
873     }
874 
875     *mdid = mac_mib_get_ft_mdid(hmac_vap);
876     return OAL_SUCC;
877 }
878 
hmac_set_11r_md_ft_over_ds(hmac_vap_stru * hmac_vap,osal_u8 * ies,osal_u32 ie_len)879 OAL_STATIC osal_void hmac_set_11r_md_ft_over_ds(hmac_vap_stru *hmac_vap, osal_u8 *ies, osal_u32 ie_len)
880 {
881     osal_u8 *ie = OSAL_NULL;
882     hmac_11r_vap_info_stru *hmac_11r_vap_info = OSAL_NULL;
883 
884     if (hmac_vap == OSAL_NULL || !is_legacy_sta(hmac_vap)) {
885         return;
886     }
887 
888     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
889     if (hmac_11r_vap_info == OSAL_NULL || hmac_11r_vap_info->enable_11r != OSAL_TRUE) {
890         return;
891     }
892 
893     ie = mac_find_ie_etc(MAC_EID_MOBILITY_DOMAIN, ies, (osal_s32)ie_len);
894     if ((ie != OAL_PTR_NULL)) {
895         *(ie + FT_CAPABILITY_OFFSET) = 0;
896         if (hmac_11r_vap_info->enable_11r_over_ds == OSAL_TRUE) {
897             *(ie + FT_CAPABILITY_OFFSET) += 1; // 1表示Fast Bss Transition over ds能力
898         }
899         if (mac_mib_get_ft_resource_req(hmac_vap) == OSAL_TRUE) {
900             *(ie + FT_CAPABILITY_OFFSET) += 2; // 2表示Resource Request Protocol Capability能力
901         }
902     }
903 
904     return;
905 }
906 
907 /*****************************************************************************
908  函 数 名  : hmac_config_set_ft_ies_etc
909  功能描述  : 配置ft ies
910  输入参数  : hmac_vap_stru *hmac_vap
911              osal_u16 len
912              osal_u8 *param
913  输出参数  : 无
914 *****************************************************************************/
hmac_config_set_ft_ies_etc(hmac_vap_stru * hmac_vap,frw_msg * msg)915 OAL_STATIC osal_s32 hmac_config_set_ft_ies_etc(hmac_vap_stru *hmac_vap, frw_msg *msg)
916 {
917     mac_cfg80211_ft_ies_stru           *mac_ft_ies;
918     oal_app_ie_stru                     ft_ie;
919     osal_u32                          ul_ret;
920     osal_u16                          md_id;
921     hmac_11r_vap_info_stru *hmac_11r_vap_info = OSAL_NULL;
922 
923     if ((hmac_vap == OAL_PTR_NULL) || (msg->data == OAL_PTR_NULL)) {
924         oam_error_log0(0, OAM_SF_CFG, "{hmac_config_set_ft_ies_etc::param null.}");
925         return OAL_ERR_CODE_PTR_NULL;
926     }
927 
928     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
929     if (hmac_11r_vap_info == OSAL_NULL) {
930         return OAL_ERR_CODE_PTR_NULL;
931     }
932 
933     if (hmac_11r_vap_info->enable_11r != OAL_TRUE) {
934         return OAL_SUCC;
935     }
936 
937     mac_ft_ies = (mac_cfg80211_ft_ies_stru *)msg->data;
938     ul_ret = mac_mib_get_md_id_etc(hmac_vap, &md_id);
939     if (ul_ret != OAL_SUCC) {
940         oam_warning_log0(0, OAM_SF_CFG, "{hmac_config_set_ft_ies_etc::set_app_ie fail, not find ft ie.}");
941         return OAL_SUCC;
942     }
943 
944     if (md_id != mac_ft_ies->mdid) {
945         oam_error_log3(0, OAM_SF_CFG,
946                        "vap_id[%d] {hmac_config_set_ft_ies_etc::UNEXPECTED mdid[%d/%d].}",
947                        hmac_vap->vap_id, mac_ft_ies->mdid, md_id);
948         return OAL_FAIL;
949     }
950 
951     ft_ie.app_ie_type   = OAL_APP_FT_IE;
952     ft_ie.ie_len        = mac_ft_ies->len;
953     if (memcpy_s(ft_ie.ie, sizeof(ft_ie.ie), mac_ft_ies->ie, mac_ft_ies->len) != EOK) {
954         oam_error_log0(0, OAM_SF_ANY, "{hmac_config_set_ft_ies_etc::memcpy_s error}");
955     }
956 
957     hmac_set_11r_md_ft_over_ds(hmac_vap, ft_ie.ie, ft_ie.ie_len);
958 
959     ul_ret = hmac_config_set_app_ie_to_vap_etc(hmac_vap, &ft_ie, OAL_APP_FT_IE);
960     if (ul_ret != OAL_SUCC) {
961         oam_error_log2(0, OAM_SF_CFG, "vap_id[%d] {hmac_config_set_ft_ies_etc::set_app_ie FAIL[%d].}",
962                        hmac_vap->vap_id, ul_ret);
963         return (osal_s32)ul_ret;
964     }
965 
966     oam_warning_log2(0, OAM_SF_CFG, "vap_id[%d] {hmac_config_set_ft_ies_etc::set_app_ie OK LEN[%d].}",
967                      hmac_vap->vap_id, mac_ft_ies->len);
968 
969     hmac_roam_reassoc_etc(hmac_vap);
970 
971     return OAL_SUCC;
972 }
973 
hmac_11r_set_authentication_mode(hmac_vap_stru * hmac_vap,const mac_conn_security_stru * conn_sec)974 OAL_STATIC osal_void hmac_11r_set_authentication_mode(hmac_vap_stru *hmac_vap, const mac_conn_security_stru *conn_sec)
975 {
976     osal_u32 akm_suite;
977     osal_u8 akm_type;
978     hmac_11r_vap_info_stru *hmac_11r_vap_info = OSAL_NULL;
979 
980     if (hmac_vap == OSAL_NULL || conn_sec == OSAL_NULL) {
981         return;
982     }
983 
984     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
985     if (hmac_11r_vap_info == OSAL_NULL) {
986         return;
987     }
988 
989     if (hmac_11r_vap_info->enable_11r != OAL_TRUE) {
990         return;
991     }
992 
993     akm_suite = OAL_NTOH_32(conn_sec->crypto.akm_suite[0]);
994     akm_type  = akm_suite & 0xFF;
995     if ((akm_type == WLAN_AUTH_SUITE_FT_1X) || (akm_type == WLAN_AUTH_SUITE_FT_PSK) ||
996         (akm_type == WLAN_AUTH_SUITE_FT_SHA256)) {
997         mac_mib_set_authentication_mode(hmac_vap, WLAN_WITP_AUTH_FT);
998     }
999 
1000     return;
1001 }
1002 
hmac_11r_mib_init_cfg(hmac_vap_stru * hmac_vap,const mac_conn_security_stru * conn_sec,mac_bss_dscr_stru * bss_dscr)1003 OAL_STATIC osal_void hmac_11r_mib_init_cfg(hmac_vap_stru *hmac_vap, const mac_conn_security_stru *conn_sec,
1004     mac_bss_dscr_stru *bss_dscr)
1005 {
1006     osal_u8 *mde = OSAL_NULL;
1007     hmac_11r_vap_info_stru *hmac_11r_vap_info = OSAL_NULL;
1008 
1009     if (hmac_vap == OSAL_NULL || conn_sec == OSAL_NULL || bss_dscr == OSAL_NULL) {
1010         return;
1011     }
1012 
1013     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
1014     if (hmac_11r_vap_info == OSAL_NULL) {
1015         return;
1016     }
1017 
1018     if (hmac_11r_vap_info->enable_11r != OAL_TRUE) {
1019         return;
1020     }
1021 
1022     mac_mib_set_ft_trainsistion(hmac_vap, OSAL_FALSE);
1023     mde = mac_find_ie_etc(MAC_EID_MOBILITY_DOMAIN, bss_dscr->mgmt_buff + MAC_80211_FRAME_LEN + MAC_SSID_OFFSET,
1024         (osal_s32)(bss_dscr->mgmt_len - MAC_80211_FRAME_LEN - MAC_SSID_OFFSET));
1025     if (mde != OAL_PTR_NULL) {
1026         hmac_mib_init_ft_cfg_etc(hmac_vap, mde);
1027     }
1028 
1029     return;
1030 }
1031 
hmac_11r_encap_auth_req_ft_ie(hmac_vap_stru * hmac_vap,osal_u8 * mgmt_frame,osal_u16 * auth_req_len)1032 OAL_STATIC osal_void hmac_11r_encap_auth_req_ft_ie(hmac_vap_stru *hmac_vap, osal_u8 *mgmt_frame, osal_u16 *auth_req_len)
1033 {
1034     osal_u16 app_ie_len;
1035     hmac_11r_vap_info_stru *hmac_11r_vap_info = OSAL_NULL;
1036 
1037     if (hmac_vap == OSAL_NULL || mgmt_frame == OSAL_NULL || auth_req_len == OSAL_NULL) {
1038         return;
1039     }
1040 
1041     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
1042     if (hmac_11r_vap_info == OSAL_NULL) {
1043         return;
1044     }
1045 
1046     if (hmac_11r_vap_info->enable_11r == OAL_TRUE && (hmac_vap->vap_state == MAC_VAP_STATE_ROAMING) &&
1047         (mac_mib_get_ft_trainsistion(hmac_vap) == OAL_TRUE)) {
1048         /* FT System */
1049         mgmt_frame[MAC_80211_FRAME_LEN] = 0x02;
1050         mgmt_frame[MAC_80211_FRAME_LEN + 1] = 0x00;
1051         mgmt_frame += *auth_req_len;
1052 
1053         hmac_add_app_ie_etc((osal_void *)hmac_vap, mgmt_frame, &app_ie_len, OAL_APP_FT_IE);
1054         *auth_req_len += app_ie_len;
1055         mgmt_frame += app_ie_len;
1056     }
1057 
1058     return;
1059 }
1060 
hmac_11r_process_assoc_rsp(hmac_vap_stru * hmac_vap,hmac_roam_info_stru * roam_info)1061 OAL_STATIC osal_u32 hmac_11r_process_assoc_rsp(hmac_vap_stru *hmac_vap, hmac_roam_info_stru *roam_info)
1062 {
1063     osal_u32 ret;
1064     hmac_11r_vap_info_stru *hmac_11r_vap_info = OSAL_NULL;
1065 
1066     if (hmac_vap == OSAL_NULL || roam_info == OSAL_NULL) {
1067         return OAL_ERR_CODE_PTR_NULL;
1068     }
1069 
1070     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
1071     if (hmac_11r_vap_info == OSAL_NULL) {
1072         return OAL_ERR_CODE_PTR_NULL;
1073     }
1074 
1075     if (hmac_11r_vap_info->enable_11r != OAL_TRUE) {
1076         return OAL_CONTINUE;
1077     }
1078 
1079     /* 信道跟随检查 */
1080     ret = hmac_check_ap_channel_follow_sta(hmac_vap, &hmac_vap->channel);
1081     if (ret == OAL_SUCC) {
1082         oam_warning_log2(0, OAM_SF_ASSOC,
1083             "vap_id[%d] {hmac_11r_process_assoc_rsp:: ap channel change to %d}",
1084             hmac_vap->vap_id, hmac_vap->channel.chan_number);
1085     }
1086 
1087     if (mac_mib_get_privacyinvoked(hmac_vap) != OAL_TRUE) {
1088         return OAL_CONTINUE;
1089     }
1090 
1091     if (mac_mib_get_ft_trainsistion(hmac_vap) == OAL_TRUE) {
1092         /* FT情况下,漫游成功 */
1093         hmac_roam_connect_change_state(roam_info, ROAM_CONNECT_STATE_HANDSHAKING);
1094         hmac_roam_connect_succ(roam_info, OAL_PTR_NULL);
1095         return OAL_SUCC;
1096     }
1097 
1098     return OAL_CONTINUE;
1099 }
1100 
hmac_11r_roam_connect_start_etc(hmac_vap_stru * hmac_vap,hmac_roam_info_stru * roam_info,mac_bss_dscr_stru * bss_dscr)1101 OAL_STATIC osal_u32 hmac_11r_roam_connect_start_etc(hmac_vap_stru *hmac_vap, hmac_roam_info_stru *roam_info,
1102     mac_bss_dscr_stru *bss_dscr)
1103 {
1104     hmac_11r_vap_info_stru *hmac_11r_vap_info = OSAL_NULL;
1105 
1106     if (hmac_vap == OSAL_NULL || roam_info == OSAL_NULL || bss_dscr == OSAL_NULL) {
1107         return OAL_CONTINUE;
1108     }
1109 
1110     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
1111     if (hmac_11r_vap_info == OSAL_NULL) {
1112         return OAL_ERR_CODE_PTR_NULL;
1113     }
1114 
1115     if (hmac_11r_vap_info->enable_11r == OAL_TRUE) {
1116         if ((mac_mib_get_ft_trainsistion(hmac_vap) == OAL_TRUE) &&
1117             (mac_mib_get_ft_over_ds(hmac_vap) == OAL_TRUE) &&
1118             (hmac_11r_vap_info->enable_11r_over_ds == OAL_TRUE) &&
1119             (roam_info->connect.ft_force_air != OAL_TRUE)) {
1120             return hmac_roam_connect_fsm_action_etc(roam_info, ROAM_CONNECT_FSM_EVENT_FT_OVER_DS,
1121                 (osal_void *)bss_dscr);
1122         }
1123     }
1124 
1125     return OAL_CONTINUE;
1126 }
1127 
hmac_11r_roam_connect_to_bss(hmac_vap_stru * hmac_vap,const hmac_roam_info_stru * roam_info,oal_bool_enum_uint8 * need_to_stop_user)1128 OAL_STATIC osal_void hmac_11r_roam_connect_to_bss(hmac_vap_stru *hmac_vap, const hmac_roam_info_stru *roam_info,
1129     oal_bool_enum_uint8 *need_to_stop_user)
1130 {
1131     hmac_11r_vap_info_stru  *hmac_11r_vap_info = OSAL_NULL;
1132 
1133     if (hmac_vap == OSAL_NULL || roam_info == OSAL_NULL || need_to_stop_user == OSAL_NULL) {
1134         return;
1135     }
1136 
1137     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
1138     if (hmac_11r_vap_info == OSAL_NULL) {
1139         return;
1140     }
1141 
1142     if ((mac_mib_get_ft_trainsistion(hmac_vap) == OAL_TRUE) && (mac_mib_get_ft_over_ds(hmac_vap) == OAL_TRUE)) {
1143         oam_warning_log1(0, OAM_SF_ROAM, "{hmac_11r_roam_connect_to_bss::11r_over_ds = [%d]}",
1144             hmac_11r_vap_info->enable_11r_over_ds);
1145         /* modify仅第一次使用ds方式 */
1146         if ((hmac_11r_vap_info->enable_11r_over_ds == OAL_TRUE) && (roam_info->connect.ft_force_air != OAL_TRUE)) {
1147             *need_to_stop_user = OSAL_FALSE;
1148         }
1149     }
1150 
1151     return;
1152 }
1153 
hmac_11r_roam_change_app_ie(hmac_vap_stru * hmac_vap,app_ie_type_uint8 * app_ie_type)1154 OAL_STATIC osal_void hmac_11r_roam_change_app_ie(hmac_vap_stru *hmac_vap, app_ie_type_uint8 *app_ie_type)
1155 {
1156     hmac_11r_vap_info_stru *hmac_11r_vap_info = OSAL_NULL;
1157 
1158     if (hmac_vap == OSAL_NULL || app_ie_type == OSAL_NULL) {
1159         return;
1160     }
1161 
1162     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
1163     if (hmac_11r_vap_info == OSAL_NULL) {
1164         return;
1165     }
1166 
1167     if (hmac_11r_vap_info->enable_11r == OAL_TRUE) {
1168         if (mac_mib_get_ft_trainsistion(hmac_vap) == OAL_TRUE) {
1169             *app_ie_type = OAL_APP_FT_IE;
1170         }
1171     }
1172 
1173     return;
1174 }
1175 
hmac_11r_roam_connect_fsm_init(hmac_roam_fsm_func hmac_roam_connect_fsm_func[][ROAM_CONNECT_FSM_EVENT_TYPE_BUTT])1176 OAL_STATIC osal_void hmac_11r_roam_connect_fsm_init(
1177     hmac_roam_fsm_func hmac_roam_connect_fsm_func[][ROAM_CONNECT_FSM_EVENT_TYPE_BUTT])
1178 {
1179     if (hmac_roam_connect_fsm_func == OSAL_NULL) {
1180         return;
1181     }
1182 
1183     hmac_roam_connect_fsm_func[ROAM_CONNECT_STATE_INIT][ROAM_CONNECT_FSM_EVENT_FT_OVER_DS]           =
1184         hmac_roam_send_ft_req;
1185     hmac_roam_connect_fsm_func[ROAM_CONNECT_STATE_WAIT_FT_COMP][ROAM_CONNECT_FSM_EVENT_MGMT_RX]      =
1186         hmac_roam_process_ft_rsp;
1187     hmac_roam_connect_fsm_func[ROAM_CONNECT_STATE_WAIT_FT_COMP][ROAM_CONNECT_FSM_EVENT_TIMEOUT]      =
1188         hmac_roam_ft_timeout;
1189 }
1190 
hmac_get_11r_cap(hmac_vap_stru * hmac_vap,osal_s32 * cap_value)1191 OAL_STATIC osal_void hmac_get_11r_cap(hmac_vap_stru *hmac_vap, osal_s32 *cap_value)
1192 {
1193     osal_u8 vap_id;
1194     osal_u32 val = 0;
1195 
1196     if (hmac_vap == OSAL_NULL || cap_value == OSAL_NULL) {
1197         return;
1198     }
1199     val = (osal_u32)(*cap_value);
1200 
1201     if (!is_legacy_sta(hmac_vap)) {
1202         return;
1203     }
1204 
1205     vap_id = hmac_vap->vap_id;
1206     if (hmac_vap_id_param_check(vap_id) != OSAL_TRUE) {
1207         return;
1208     }
1209 
1210     if (g_11r_vap_info[vap_id] != OSAL_NULL && g_11r_vap_info[vap_id]->enable_11r == OAL_TRUE) {
1211         val |=  BIT(WAL_WIFI_FEATURE_SUPPORT_11R);
1212         *cap_value = (osal_s32)val;
1213     }
1214 
1215     return;
1216 }
1217 
hmac_sta_up_rx_action_ft_transition(oal_netbuf_stru ** netbuf,hmac_vap_stru * hmac_vap)1218 OAL_STATIC osal_u32 hmac_sta_up_rx_action_ft_transition(oal_netbuf_stru **netbuf, hmac_vap_stru *hmac_vap)
1219 {
1220     dmac_rx_ctl_stru *rx_ctl = OSAL_NULL;
1221     mac_ieee80211_frame_stru *frame_hdr = OSAL_NULL;
1222     osal_u8 *data = OSAL_NULL;
1223     hmac_roam_info_stru *roam_info = OSAL_NULL;
1224     hmac_11r_vap_info_stru *hmac_11r_vap_info = OSAL_NULL;
1225     osal_u32 ret;
1226 
1227     if (netbuf == OSAL_NULL || hmac_vap == OSAL_NULL) {
1228         return OAL_CONTINUE;
1229     }
1230 
1231     roam_info = hmac_get_roam_info(hmac_vap->vap_id);
1232     if (roam_info == OAL_PTR_NULL) {
1233         return OAL_CONTINUE;
1234     }
1235 
1236     /* 漫游开关没有开时,不处理管理帧接收 */
1237     if (roam_info->enable == 0) {
1238         return OAL_CONTINUE;
1239     }
1240 
1241     rx_ctl = (dmac_rx_ctl_stru *)oal_netbuf_cb(*netbuf); /* 获取帧头信息 */
1242     frame_hdr = (mac_ieee80211_frame_stru *)mac_get_rx_cb_mac_hdr(&(rx_ctl->rx_info));
1243     data = oal_netbuf_rx_data(*netbuf);
1244 
1245     if (!is_legacy_sta(hmac_vap)) {
1246         return OAL_CONTINUE;
1247     }
1248 
1249     hmac_11r_vap_info = hmac_11r_get_vap_info(hmac_vap);
1250     if (hmac_11r_vap_info == OSAL_NULL) {
1251         return OAL_CONTINUE;
1252     }
1253 
1254     if (hmac_11r_vap_info->enable_11r != OAL_TRUE) {
1255         return OAL_CONTINUE;
1256     }
1257 
1258     if (frame_hdr->frame_control.type != WLAN_MANAGEMENT || frame_hdr->frame_control.sub_type != WLAN_ACTION) {
1259         return OAL_CONTINUE;
1260     }
1261 
1262     if ((data[MAC_ACTION_OFFSET_CATEGORY]) != MAC_ACTION_CATEGORY_FAST_BSS_TRANSITION ||
1263         data[MAC_ACTION_OFFSET_ACTION] != MAC_FT_ACTION_RESPONSE) {
1264         return OAL_CONTINUE;
1265     }
1266 
1267     ret = hmac_roam_connect_fsm_action_etc(roam_info, ROAM_CONNECT_FSM_EVENT_MGMT_RX, (osal_void *)*netbuf);
1268     if (ret != OAL_CONTINUE) {
1269         oal_netbuf_free(*netbuf);
1270         return OAL_SUCC;
1271     }
1272 
1273     return OAL_CONTINUE;
1274 }
1275 
1276 hmac_netbuf_hook_stru g_11r_netbuf_hook = {
1277     .hooknum = HMAC_FRAME_MGMT_RX_EVENT_FEATURE,
1278     .priority = HMAC_HOOK_PRI_HIGHEST,
1279     .hook_func = hmac_sta_up_rx_action_ft_transition,
1280 };
1281 
hmac_11r_init(osal_void)1282 osal_u32 hmac_11r_init(osal_void)
1283 {
1284     osal_u32 ret;
1285 
1286     /* 注册监听 */
1287     frw_util_notifier_register(WLAN_UTIL_NOTIFIER_EVENT_ADD_VAP, hmac_11r_add_vap);
1288     frw_util_notifier_register(WLAN_UTIL_NOTIFIER_EVENT_DEL_VAP, hmac_11r_del_vap);
1289     /* 注册消息 */
1290     frw_msg_hook_register(WLAN_MSG_W2H_CFG_SET_FT_IES, hmac_config_set_ft_ies_etc);
1291     /* 注册对外接口 */
1292     hmac_feature_hook_register(HMAC_FHOOK_11R_SET_MD_IE, hmac_11r_set_md_ie);
1293     hmac_feature_hook_register(HMAC_FHOOK_11R_SET_AUTHENTICATION_MODE, hmac_11r_set_authentication_mode);
1294     hmac_feature_hook_register(HMAC_FHOOK_11R_MIB_INIT_CFG, hmac_11r_mib_init_cfg);
1295     hmac_feature_hook_register(HMAC_FHOOK_11R_ENCAP_AUTH_REQ_FT_IE, hmac_11r_encap_auth_req_ft_ie);
1296     hmac_feature_hook_register(HMAC_FHOOK_11R_AUTH_SEQ2_PROCESS, hmac_roam_auth_seq2_11r_process);
1297     hmac_feature_hook_register(HMAC_FHOOK_11R_PROCESS_ASSOC_RSP, hmac_11r_process_assoc_rsp);
1298     hmac_feature_hook_register(HMAC_FHOOK_11R_ROAM_CONNECT_START_ETC, hmac_11r_roam_connect_start_etc);
1299     hmac_feature_hook_register(HMAC_FHOOK_11R_ROAM_CONNECT_TO_BSS, hmac_11r_roam_connect_to_bss);
1300     hmac_feature_hook_register(HMAC_FHOOK_11R_ROAM_CHANGE_APP_IE, hmac_11r_roam_change_app_ie);
1301     hmac_feature_hook_register(HMAC_FHOOK_11R_ROAM_CONNECT_FSM_INIT, hmac_11r_roam_connect_fsm_init);
1302     hmac_feature_hook_register(HMAC_FHOOK_11R_GET_11R_CAP, hmac_get_11r_cap);
1303     hmac_feature_hook_register(HMAC_FHOOK_11R_SET_MD_FT_OVER_DS, hmac_set_11r_md_ft_over_ds);
1304     /* 注册转发Hook */
1305     ret = hmac_register_netbuf_hook(&g_11r_netbuf_hook);
1306     if (ret != OAL_SUCC) {
1307         oam_error_log0(0, OAM_SF_RX, "{hmac_11k_init:: MGMT RX IN register_netbuf_hooks error!");
1308         return ret;
1309     }
1310 
1311     return OAL_SUCC;
1312 }
1313 
hmac_11r_deinit(osal_void)1314 osal_void hmac_11r_deinit(osal_void)
1315 {
1316     /* 去注册监听 */
1317     frw_util_notifier_unregister(WLAN_UTIL_NOTIFIER_EVENT_ADD_VAP, hmac_11r_add_vap);
1318     frw_util_notifier_unregister(WLAN_UTIL_NOTIFIER_EVENT_DEL_VAP, hmac_11r_del_vap);
1319     /* 去注册消息 */
1320     frw_msg_hook_unregister(WLAN_MSG_W2H_CFG_SET_FT_IES);
1321     /* 去注册对外接口 */
1322     hmac_feature_hook_unregister(HMAC_FHOOK_11R_SET_MD_IE);
1323     hmac_feature_hook_unregister(HMAC_FHOOK_11R_SET_AUTHENTICATION_MODE);
1324     hmac_feature_hook_unregister(HMAC_FHOOK_11R_MIB_INIT_CFG);
1325     hmac_feature_hook_unregister(HMAC_FHOOK_11R_ENCAP_AUTH_REQ_FT_IE);
1326     hmac_feature_hook_unregister(HMAC_FHOOK_11R_AUTH_SEQ2_PROCESS);
1327     hmac_feature_hook_unregister(HMAC_FHOOK_11R_PROCESS_ASSOC_RSP);
1328     hmac_feature_hook_unregister(HMAC_FHOOK_11R_ROAM_CONNECT_START_ETC);
1329     hmac_feature_hook_unregister(HMAC_FHOOK_11R_ROAM_CONNECT_TO_BSS);
1330     hmac_feature_hook_unregister(HMAC_FHOOK_11R_ROAM_CHANGE_APP_IE);
1331     hmac_feature_hook_unregister(HMAC_FHOOK_11R_ROAM_CONNECT_FSM_INIT);
1332     hmac_feature_hook_unregister(HMAC_FHOOK_11R_GET_11R_CAP);
1333     hmac_feature_hook_unregister(HMAC_FHOOK_11R_SET_MD_FT_OVER_DS);
1334     /* 去注册转发Hook */
1335     hmac_unregister_netbuf_hook(&g_11r_netbuf_hook);
1336 
1337     return;
1338 }
1339 
1340 #endif
1341 
1342 #ifdef __cplusplus
1343 #if __cplusplus
1344 }
1345 #endif
1346 #endif
1347 
1348