1 /*
2 * Copyright (C) 2021 HiSilicon (Shanghai) Technologies CO., LIMITED.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19 /* ****************************************************************************
20 头文件包含
21 **************************************************************************** */
22 #include "oal_ext_if.h"
23 #include "wlan_types.h"
24 #include "mac_vap.h"
25 #include "mac_device.h"
26 #include "mac_data.h"
27
28 #ifdef __cplusplus
29 #if __cplusplus
30 extern "C" {
31 #endif
32 #endif
33
34 /* ****************************************************************************
35 函数实现
36 **************************************************************************** */
37 /* ****************************************************************************
38 功能描述 : 从带mac头的80211帧中获取以太类型
39 修改历史 :
40 1.日 期 : 2015年7月6日
41 作 者 : HiSilicon
42 修改内容 : 新生成函数
43 **************************************************************************** */
mac_get_data_type_from_80211(const oal_netbuf_stru * netbuf,hi_u16 us_mac_hdr_len)44 hi_u8 mac_get_data_type_from_80211(const oal_netbuf_stru *netbuf, hi_u16 us_mac_hdr_len)
45 {
46 mac_llc_snap_stru *snap = HI_NULL;
47
48 if (netbuf == HI_NULL) {
49 return MAC_DATA_BUTT;
50 }
51 snap = (mac_llc_snap_stru *)(oal_netbuf_data(netbuf) + us_mac_hdr_len);
52 return mac_get_data_type_from_8023((hi_u8 *)snap, MAC_NETBUFF_PAYLOAD_SNAP);
53 }
54
55 /* ****************************************************************************
56 功能描述 : 判断该帧是否为4 次握手的EAPOL KEY 单播密钥协商帧
57 输入参数 : mac_eapol_header_stru *pst_eapol_header
58 返 回 值 : hi_u8
59 修改历史 :
60 1.日 期 : 2015年8月13日
61 作 者 : HiSilicon
62 修改内容 : 新生成函数
63 **************************************************************************** */
mac_is_eapol_key_ptk(mac_eapol_header_stru * eapol_header)64 hi_u8 mac_is_eapol_key_ptk(mac_eapol_header_stru *eapol_header)
65 {
66 mac_eapol_key_stru *key = HI_NULL;
67
68 if (IEEE802_1X_TYPE_EAPOL_KEY == eapol_header->type) {
69 if ((hi_u16)(oal_net2host_short(eapol_header->us_length)) >= (hi_u16)sizeof(mac_eapol_key_stru)) {
70 key = (mac_eapol_key_stru *)(eapol_header + 1);
71 if (key->auc_key_info[1] & WPA_KEY_INFO_KEY_TYPE) {
72 return HI_TRUE;
73 }
74 }
75 }
76 return HI_FALSE;
77 }
78
79 /* ****************************************************************************
80 功能描述 : 判断是否是dhcp帧 port
81 修改历史 :
82 1.日 期 : 2014年6月27日
83 作 者 : HiSilicon
84 **************************************************************************** */
mac_is_dhcp_port(mac_ip_header_stru * ip_hdr)85 WIFI_ROM_TEXT hi_u8 mac_is_dhcp_port(mac_ip_header_stru *ip_hdr)
86 {
87 udp_hdr_stru *udp_hdr = HI_NULL;
88 if ((ip_hdr->protocol == MAC_UDP_PROTOCAL) && ((oal_net2host_short(ip_hdr->us_frag_off) & 0x1FFF) == 0)) {
89 udp_hdr = (udp_hdr_stru *)(ip_hdr + 1);
90
91 if (oal_net2host_short(udp_hdr->us_des_port) == 67 || /* 67 端口为dhcp端口 */
92 oal_net2host_short(udp_hdr->us_des_port) == 68) { /* 68 端口也为dhcp端口 */
93 return HI_TRUE;
94 }
95 }
96 return HI_FALSE;
97 }
98
mac_dhcp_get_type(hi_u8 * pos,const hi_u8 * packet_end,hi_u8 type)99 WIFI_ROM_TEXT hi_u8 *mac_dhcp_get_type(hi_u8 *pos, const hi_u8 *packet_end, hi_u8 type)
100 {
101 hi_u8 *opt = HI_NULL;
102 if (pos == HI_NULL) {
103 oam_warning_log0(0, OAM_SF_PWR, "{mac_dhcp_get_type::pos is null.}");
104 return HI_NULL;
105 }
106
107 if (packet_end == HI_NULL) {
108 oam_warning_log0(0, OAM_SF_PWR, "{mac_dhcp_get_type::packet_end is null.}");
109 return HI_NULL;
110 }
111
112 /* 获取 DHCP 类型 */
113 while ((pos < packet_end) && (*pos != 0xFF)) {
114 opt = pos++;
115
116 /* Padding */
117 if (*opt == 0) {
118 continue;
119 }
120 pos += *pos + 1;
121 if (pos >= packet_end) {
122 break;
123 }
124 /* Message Type */
125 if ((type == *opt) && (opt[1] != 0)) {
126 return opt;
127 }
128 }
129
130 return HI_NULL;
131 }
132
133 /* ****************************************************************************
134 功能描述 : 判断是否是nd帧
135 修改历史 :
136 1.日 期 : 2014年8月7日
137 作 者 : HiSilicon
138 修改内容 : 新生成函数
139 **************************************************************************** */
mac_is_nd(oal_ipv6hdr_stru * ipv6hdr)140 WIFI_ROM_TEXT hi_u8 mac_is_nd(oal_ipv6hdr_stru *ipv6hdr)
141 {
142 oal_icmp6hdr_stru *icmp6hdr = HI_NULL;
143
144 if (ipv6hdr->nexthdr == OAL_IPPROTO_ICMPV6) {
145 icmp6hdr = (oal_icmp6hdr_stru *)(ipv6hdr + 1);
146 if ((icmp6hdr->icmp6_type == MAC_ND_RSOL) || (icmp6hdr->icmp6_type == MAC_ND_RADVT) ||
147 (icmp6hdr->icmp6_type == MAC_ND_NSOL) || (icmp6hdr->icmp6_type == MAC_ND_NADVT) ||
148 (icmp6hdr->icmp6_type == MAC_ND_RMES)) {
149 return HI_TRUE;
150 }
151 }
152 return HI_FALSE;
153 }
154
mac_get_ipv4_data_type(mac_ip_header_stru * ip)155 WIFI_ROM_TEXT static hi_u8 mac_get_ipv4_data_type(mac_ip_header_stru *ip)
156 {
157 udp_hdr_stru *udp_hdr = HI_NULL;
158 dhcp_message_stru *dhcp_message = HI_NULL;
159 hi_u8 *tmp = HI_NULL;
160 hi_u8 datatype = MAC_DATA_BUTT;
161
162 if (mac_is_dhcp_port(ip)) {
163 udp_hdr = (udp_hdr_stru *)(ip + 1);
164 dhcp_message = (dhcp_message_stru *)(udp_hdr + 1);
165 tmp = mac_dhcp_get_type(dhcp_message->options, dhcp_message->options + sizeof(dhcp_message->options),
166 DHCP_OPT_MESSAGETYPE);
167 if (tmp == HI_NULL) {
168 datatype = MAC_DATA_BUTT;
169 } else {
170 if (*(tmp + 2) == DHCP_DISCOVER) { /* 偏移2 byte,获取DHCP type */
171 datatype = MAC_DATA_DHCP_DISCOVER;
172 } else if (*(tmp + 2) == DHCP_OFFER) { /* 偏移2 byte,获取DHCP type */
173 datatype = MAC_DATA_DHCP_OFFER;
174 } else if (*(tmp + 2) == DHCP_REQUEST) { /* 偏移2 byte,获取DHCP type */
175 datatype = MAC_DATA_DHCP_REQ;
176 } else if (*(tmp + 2) == DHCP_ACK) { /* 偏移2 byte,获取DHCP type */
177 datatype = MAC_DATA_DHCP_ACK;
178 } else {
179 datatype = MAC_DATA_BUTT;
180 }
181 }
182 }
183 return datatype;
184 }
185
186 /* ****************************************************************************
187 功能描述 : 判断是否是DHCP6帧
188 修改历史 :
189 1.日 期 : 2014年8月7日
190 作 者 : HiSilicon
191 修改内容 : 新生成函数
192 **************************************************************************** */
mac_is_dhcp6(oal_ipv6hdr_stru * ipv6hdr)193 WIFI_ROM_TEXT hi_u8 mac_is_dhcp6(oal_ipv6hdr_stru *ipv6hdr)
194 {
195 udp_hdr_stru *udp_hdr = HI_NULL;
196
197 if (ipv6hdr->nexthdr == MAC_UDP_PROTOCAL) {
198 udp_hdr = (udp_hdr_stru *)(ipv6hdr + 1);
199 if (udp_hdr->us_des_port == oal_host2net_short(MAC_IPV6_UDP_DES_PORT) ||
200 udp_hdr->us_des_port == oal_host2net_short(MAC_IPV6_UDP_SRC_PORT)) {
201 return HI_TRUE;
202 }
203 }
204 return HI_FALSE;
205 }
206
mac_get_ipv6_data_type(oal_ipv6hdr_stru * ipv6)207 WIFI_ROM_TEXT static hi_u8 mac_get_ipv6_data_type(oal_ipv6hdr_stru *ipv6)
208 {
209 hi_u8 datatype = MAC_DATA_BUTT;
210
211 if (mac_is_nd(ipv6)) {
212 datatype = MAC_DATA_ND;
213 } else if (mac_is_dhcp6(ipv6)) {
214 datatype = MAC_DATA_DHCPV6;
215 #ifdef _PRE_WLAN_FEATURE_MESH_ROM
216 } else if (mac_is_rpl(ipv6)) {
217 datatype = MAC_DATA_RPL;
218 #endif
219 }
220
221 return datatype;
222 }
223 /* ****************************************************************************
224 功能描述 : 根据数据帧(802.3)的类型,判断帧类型
225 输入参数 : puc_frame_hdr: 为去除80211头的数据帧,可为以太头或snap头
226 uc_hdr_type: 指针指向数据类型,用来计算获取data_type时刻的偏移
227 1.日 期 : 2015年1月20日
228 作 者 : HiSilicon
229 修改内容 : 新生成函数
230 **************************************************************************** */
mac_get_data_type_from_8023(const hi_u8 * puc_frame_hdr,mac_netbuff_payload_type hdr_type)231 WIFI_ROM_TEXT hi_u8 mac_get_data_type_from_8023(const hi_u8 *puc_frame_hdr, mac_netbuff_payload_type hdr_type)
232 {
233 const hi_u8 *puc_frame_body = HI_NULL;
234 hi_u16 ether_type;
235 hi_u8 datatype = MAC_DATA_BUTT;
236
237 if (puc_frame_hdr == HI_NULL) {
238 return datatype;
239 }
240 /* 偏移一个以太网头,取ip头 */
241 if (hdr_type == MAC_NETBUFF_PAYLOAD_ETH) {
242 ether_type = oal_net2host_short(((mac_ether_header_stru *)puc_frame_hdr)->us_ether_type);
243 puc_frame_body = puc_frame_hdr + (hi_u16)sizeof(mac_ether_header_stru);
244 } else if (hdr_type == MAC_NETBUFF_PAYLOAD_SNAP) {
245 ether_type = oal_net2host_short(((mac_llc_snap_stru *)puc_frame_hdr)->us_ether_type);
246 puc_frame_body = puc_frame_hdr + (hi_u16)sizeof(mac_llc_snap_stru);
247 } else {
248 return datatype;
249 }
250
251 switch (ether_type) {
252 case ETHER_TYPE_IP:
253 datatype = mac_get_ipv4_data_type((mac_ip_header_stru *)puc_frame_body);
254 break;
255 case ETHER_TYPE_IPV6:
256 datatype = mac_get_ipv6_data_type((oal_ipv6hdr_stru *)puc_frame_body);
257 break;
258 case ETHER_TYPE_PAE:
259 datatype = MAC_DATA_EAPOL;
260 break;
261 /* TDLS帧处理,建链保护,入高优先级TID队列 */
262 case ETHER_TYPE_TDLS:
263 datatype = MAC_DATA_TDLS;
264 break;
265 /* PPPOE帧处理,建链保护(发现阶段, 会话阶段),入高优先级TID队列 */
266 case ETHER_TYPE_PPP_DISC:
267 case ETHER_TYPE_PPP_SES:
268 datatype = MAC_DATA_PPPOE;
269 break;
270 case ETHER_TYPE_WAI:
271 datatype = MAC_DATA_WAPI;
272 break;
273 case ETHER_TYPE_VLAN:
274 datatype = MAC_DATA_VLAN;
275 break;
276 case ETHER_TYPE_ARP:
277 /* 如果是ARP帧,则进入VO队列发送 */
278 datatype = mac_get_arp_type_by_arphdr((oal_eth_arphdr_stru *)puc_frame_body);
279 break;
280 /* _PRE_WLAN_FEATURE_MESH + */
281 case ETHER_TYPE_6LO:
282 datatype = MAC_DATA_6LO;
283 break;
284 default:
285 break;
286 }
287
288 return datatype;
289 }
290
291 /* 代码ROM段结束位置 新增ROM代码请放在SECTION中 */
292 #undef __WIFI_ROM_SECTION__
293
294 #ifdef __cplusplus
295 #if __cplusplus
296 }
297 #endif
298 #endif
299