1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
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 */
15
16 #include "securec.h"
17 #include "wifi_hdi_util.h"
18 #include "wifi_common_def.h"
19
20 #ifndef UT_TEST
21 #include "wifi_log.h"
22 #else
23 #define static
24 #define LOGI(...)
25 #define LOGE(...)
26 #endif
27
28 #undef LOG_TAG
29 #define LOG_TAG "WifiHdiUtil"
30
31 #define FAIL_BUSY 2
32
33 #define COLUMN_INDEX_ZERO 0
34 #define COLUMN_INDEX_ONE 1
35 #define COLUMN_INDEX_TWO 2
36 #define COLUMN_INDEX_THREE 3
37 #define COLUMN_INDEX_FOUR 4
38 #define COLUMN_INDEX_FIVE 5
39
40 #define FAIL_PBC_OVERLAP_RETUEN 3
41 #define CMD_BUFFER_SIZE 1024
42 #define REPLY_BUF_LENGTH (4096 * 10)
43 #define REPLY_BUF_SMALL_LENGTH 64
44 #define CMD_FREQ_MAX_LEN 8
45 #define MAC_UINT_SIZE 6
46 #define MAC_STRING_SIZE 17
47 #define HILINK_OUI_HEAD_LEN 7
48 #define HILINK_HEAD_LEN 9
49 #define HILINK_OFFSET_LEN 2
50
51 const unsigned int HT_OPER_EID = 61;
52 const unsigned int VHT_OPER_EID = 192;
53 const unsigned int EXT_EXIST_EID = 255;
54 const unsigned int EXT_HE_OPER_EID = 36;
55 const unsigned int HE_OPER_BASIC_LEN = 6;
56 const unsigned int VHT_OPER_INFO_EXTST_MASK = 0x40;
57 const unsigned int GHZ_HE_INFO_EXIST_MASK_6 = 0x02;
58 const unsigned int GHZ_HE_WIDTH_MASK_6 = 0x03;
59 const unsigned int BSS_EXIST_MASK = 0x80;
60 const unsigned int VHT_OPER_INFO_BEGIN_INDEX = 6;
61 const unsigned int VHT_INFO_SIZE = 3;
62 const unsigned int HT_INFO_SIZE = 3;
63 const unsigned int UINT8_MASK = 0xFF;
64 const unsigned int UNSPECIFIED = -1;
65 const unsigned int MAX_INFO_ELEMS_SIZE = 256;
66 const unsigned int SUPP_RATES_SIZE = 8;
67 const unsigned int EXT_SUPP_RATES_SIZE = 4;
68 const unsigned int SUPPORTED_RATES_EID = 1;
69 const unsigned int ERP_EID = 42;
70 const unsigned int EXT_SUPPORTED_RATES_EID = 50;
71
72 const unsigned int BAND_5_GHZ = 2;
73 const unsigned int BAND_6_GHZ = 8;
74 const unsigned int CHAN_WIDTH_20MHZ = 0;
75 const unsigned int CHAN_WIDTH_40MHZ = 1;
76 const unsigned int CHAN_WIDTH_80MHZ = 2;
77 const unsigned int CHAN_WIDTH_160MHZ = 3;
78 const unsigned int CHAN_WIDTH_80MHZ_MHZ = 4;
79
80 #ifndef OHOS_ARCH_LITE
ConvertChanToFreqMhz(int channel,int band)81 static int ConvertChanToFreqMhz(int channel, int band)
82 {
83 int BAND_FIRST_CH_NUM_24 = 1;
84 int BAND_LAST_CH_NUM_24 = 14;
85 int BAND_START_FREQ_MHZ_24 = 2412;
86 int BAND_FIRST_CH_NUM_5 = 32;
87 int BAND_LAST_CH_NUM_5 = 173;
88 int BAND_START_FREQ_MHZ_5 = 5160;
89 int BAND_FIRST_CH_NUM_6 = 1;
90 int BAND_LAST_CH_NUM_6 = 233;
91 int BAND_START_FREQ_MHZ_6 = 5955;
92 int BAND_CLA_2_FREQ_136_CH_MHZ_6 = 5935;
93 int BAND_24_GHZ = 1;
94 int BAND_SPECIAL = 2484;
95 int CHANNEL_SPECIAL = 14;
96 int CHANNEL_TIMES = 5;
97 int CHANNEL_TYPE = 2;
98
99 if (band == BAND_24_GHZ) {
100 if (channel == CHANNEL_SPECIAL) {
101 return BAND_SPECIAL;
102 } else if (channel >= BAND_FIRST_CH_NUM_24 && channel <= BAND_LAST_CH_NUM_24) {
103 return ((channel - BAND_FIRST_CH_NUM_24) * CHANNEL_TIMES) + BAND_START_FREQ_MHZ_24;
104 } else {
105 return UNSPECIFIED;
106 }
107 }
108 if (band == BAND_5_GHZ) {
109 if (channel >= BAND_FIRST_CH_NUM_5 && channel <= BAND_LAST_CH_NUM_5) {
110 return ((channel - BAND_FIRST_CH_NUM_5) * CHANNEL_TIMES) + BAND_START_FREQ_MHZ_5;
111 } else {
112 return UNSPECIFIED;
113 }
114 }
115 if (band == BAND_6_GHZ) {
116 if (channel >= BAND_FIRST_CH_NUM_6 && channel <= BAND_LAST_CH_NUM_6) {
117 if (channel == CHANNEL_TYPE) {
118 return BAND_CLA_2_FREQ_136_CH_MHZ_6;
119 }
120 return ((channel - BAND_FIRST_CH_NUM_6) * CHANNEL_TIMES) + BAND_START_FREQ_MHZ_6;
121 } else {
122 return UNSPECIFIED;
123 }
124 }
125 return UNSPECIFIED;
126 }
127
GetHeChanWidth(int heChannelWidth,int centerSegFreq0,int centerSegFreq1)128 static int GetHeChanWidth(int heChannelWidth, int centerSegFreq0, int centerSegFreq1)
129 {
130 int CHANNEL_WIDTH = 2;
131 int SEG_FREQ_VALUE = 8;
132 if (heChannelWidth == 0) {
133 return CHAN_WIDTH_20MHZ;
134 } else if (heChannelWidth == 1) {
135 return CHAN_WIDTH_40MHZ;
136 } else if (heChannelWidth == CHANNEL_WIDTH) {
137 return CHAN_WIDTH_80MHZ;
138 } else if (abs(centerSegFreq1 - centerSegFreq0) == SEG_FREQ_VALUE) {
139 return CHAN_WIDTH_160MHZ;
140 } else {
141 return CHAN_WIDTH_80MHZ_MHZ;
142 }
143 }
144
GetHeCentFreq(int centerSegFreq)145 static int GetHeCentFreq(int centerSegFreq)
146 {
147 if (centerSegFreq == 0) {
148 return 0;
149 }
150 return ConvertChanToFreqMhz(centerSegFreq, BAND_6_GHZ);
151 }
152
GetHtChanWidth(int secondOffsetChannel)153 static int GetHtChanWidth(int secondOffsetChannel)
154 {
155 if (secondOffsetChannel != 0) {
156 return CHAN_WIDTH_40MHZ;
157 } else {
158 return CHAN_WIDTH_20MHZ;
159 }
160 }
161
GetHtCentFreq0(int primaryFrequency,int secondOffsetChannel)162 static int GetHtCentFreq0(int primaryFrequency, int secondOffsetChannel)
163 {
164 int freqValue = 10;
165 int offsetChannle = 3;
166 if (secondOffsetChannel != 0) {
167 if (secondOffsetChannel == 1) {
168 return primaryFrequency + freqValue;
169 } else if (secondOffsetChannel == offsetChannle) {
170 return primaryFrequency - freqValue;
171 } else {
172 LOGE("error on get centFreq0");
173 return 0;
174 }
175 } else {
176 return primaryFrequency;
177 }
178 }
179
GetVhtChanWidth(int channelType,int centerFrequencyIndex1,int centerFrequencyIndex2)180 static int GetVhtChanWidth(int channelType, int centerFrequencyIndex1, int centerFrequencyIndex2)
181 {
182 int FREQ_VALUE = 8;
183 if (channelType == 0) {
184 return UNSPECIFIED;
185 } else if (centerFrequencyIndex2 == 0) {
186 return CHAN_WIDTH_80MHZ;
187 } else if (abs(centerFrequencyIndex1 - centerFrequencyIndex2) == FREQ_VALUE) {
188 return CHAN_WIDTH_160MHZ;
189 } else {
190 return CHAN_WIDTH_80MHZ_MHZ;
191 }
192 }
193
GetVhtCentFreq(int channelType,int centerFrequencyIndex)194 static int GetVhtCentFreq(int channelType, int centerFrequencyIndex)
195 {
196 if (centerFrequencyIndex == 0 || channelType == 0) {
197 return 0;
198 } else {
199 return ConvertChanToFreqMhz(centerFrequencyIndex, BAND_5_GHZ);
200 }
201 }
202
HexStringToString(const char * str,char * out)203 static int HexStringToString(const char *str, char *out)
204 {
205 unsigned len = strlen(str);
206 if (((len & 1) != 0) || (len == 0)) {
207 return -1;
208 }
209 const int hexShiftNum = 4;
210 for (unsigned i = 0, j = 0; i < len - 1;) {
211 uint8_t high = IsValidHexCharAndConvert(str[i]);
212 uint8_t low = IsValidHexCharAndConvert(str[i + 1]);
213 if (high < 0 || low < 0) {
214 return -1;
215 }
216 char tmp = ((high << hexShiftNum) | (low & 0x0F));
217 out[j] = tmp;
218 ++j;
219 i += 2; //2:每次循环分别获取char的高四位和第四位
220 }
221 return 0;
222 }
223
GetChanWidthCenterFreqVht(ScanInfo * pcmd,ScanInfoElem * infoElem)224 static bool GetChanWidthCenterFreqVht(ScanInfo *pcmd, ScanInfoElem* infoElem)
225 {
226 if ((pcmd == NULL) || (infoElem == NULL)) {
227 LOGE("pcmd or infoElem is NULL.");
228 return false;
229 }
230 if ((infoElem->content == NULL) || ((unsigned int)infoElem->size < VHT_INFO_SIZE)) {
231 return false;
232 }
233 int channelType = infoElem->content[COLUMN_INDEX_ZERO] & UINT8_MASK;
234 int centerFrequencyIndex1 = infoElem->content[COLUMN_INDEX_ONE] & UINT8_MASK;
235 int centerFrequencyIndex2 = infoElem->content[COLUMN_INDEX_TWO] & UINT8_MASK;
236 pcmd->isVhtInfoExist = 1;
237 pcmd->channelWidth = GetVhtChanWidth(channelType, centerFrequencyIndex1, centerFrequencyIndex2);
238 if ((unsigned int)pcmd->channelWidth == UNSPECIFIED) {
239 return false;
240 }
241 pcmd->centerFrequency0 = GetVhtCentFreq(channelType, centerFrequencyIndex1);
242 pcmd->centerFrequency1 = GetVhtCentFreq(channelType, centerFrequencyIndex2);
243 return true;
244 }
245
GetChanWidthCenterFreqHe(ScanInfo * pcmd,ScanInfoElem * infoElem)246 static bool GetChanWidthCenterFreqHe(ScanInfo *pcmd, ScanInfoElem* infoElem)
247 {
248 if ((pcmd == NULL) || (infoElem == NULL)) {
249 LOGE("pcmd or iesNeedParse is NULL.");
250 return false;
251 }
252 if ((infoElem->content == NULL) || ((unsigned int)infoElem->size < (HE_OPER_BASIC_LEN + 1))) {
253 return false;
254 }
255 if (infoElem->content[0] != EXT_HE_OPER_EID) {
256 return false;
257 }
258 char* content = infoElem->content + 1;
259 bool isVhtInfoExist = (content[COLUMN_INDEX_ONE] & VHT_OPER_INFO_EXTST_MASK) != 0;
260 bool is6GhzInfoExist = (content[COLUMN_INDEX_TWO] & GHZ_HE_INFO_EXIST_MASK_6) != 0;
261 bool coHostedBssPresent = (content[COLUMN_INDEX_ONE] & BSS_EXIST_MASK) != 0;
262 int expectedLen = HE_OPER_BASIC_LEN + (isVhtInfoExist ? COLUMN_INDEX_THREE : 0)
263 + (coHostedBssPresent ? 1 : 0) + (is6GhzInfoExist ? COLUMN_INDEX_FIVE : 0);
264 pcmd->isHeInfoExist = 1;
265 if (infoElem->size < expectedLen) {
266 return false;
267 }
268 if (is6GhzInfoExist) {
269 int startIndx = VHT_OPER_INFO_BEGIN_INDEX + (isVhtInfoExist ? COLUMN_INDEX_THREE : 0)
270 + (coHostedBssPresent ? 1 : 0);
271 int heChannelWidth = content[startIndx + 1] & GHZ_HE_WIDTH_MASK_6;
272 int centerSegFreq0 = content[startIndx + COLUMN_INDEX_TWO] & UINT8_MASK;
273 int centerSegFreq1 = content[startIndx + COLUMN_INDEX_THREE] & UINT8_MASK;
274 pcmd->channelWidth = GetHeChanWidth(heChannelWidth, centerSegFreq0, centerSegFreq1);
275 pcmd->centerFrequency0 = GetHeCentFreq(centerSegFreq0);
276 pcmd->centerFrequency1 = GetHeCentFreq(centerSegFreq1);
277 return true;
278 }
279 if (isVhtInfoExist) {
280 struct ScanInfoElem vhtInformation = {0};
281 vhtInformation.id = VHT_OPER_EID;
282 vhtInformation.size = VHT_INFO_SIZE;
283 vhtInformation.content = content + VHT_OPER_INFO_BEGIN_INDEX;
284 return GetChanWidthCenterFreqVht(pcmd, &vhtInformation);
285 }
286 return false;
287 }
288
GetChanWidthCenterFreqHt(ScanInfo * pcmd,ScanInfoElem * infoElem)289 static bool GetChanWidthCenterFreqHt(ScanInfo *pcmd, ScanInfoElem* infoElem)
290 {
291 const int offsetBit = 0x3;
292 if ((pcmd == NULL) || (infoElem == NULL)) {
293 LOGE("pcmd or infoElem is NULL.");
294 return false;
295 }
296 if ((infoElem->content == NULL) || ((unsigned int)infoElem->size < HT_INFO_SIZE)) {
297 return false;
298 }
299 int secondOffsetChannel = infoElem->content[1] & (unsigned int)offsetBit;
300 pcmd->channelWidth = GetHtChanWidth(secondOffsetChannel);
301 pcmd->centerFrequency0 = GetHtCentFreq0(pcmd->freq, secondOffsetChannel);
302 pcmd->isHtInfoExist = 1;
303 return true;
304 }
305
GetChanMaxRates(ScanInfo * pcmd,ScanInfoElem * infoElem)306 static bool GetChanMaxRates(ScanInfo *pcmd, ScanInfoElem* infoElem)
307 {
308 if ((pcmd == NULL) || (infoElem == NULL)) {
309 LOGE("pcmd or infoElem is NULL.");
310 return false;
311 }
312 if ((infoElem->content == NULL) || ((unsigned int)infoElem->size < SUPP_RATES_SIZE)) {
313 return false;
314 }
315 int maxIndex = infoElem->size - 1;
316 int maxRates = infoElem->content[maxIndex] & UINT8_MASK;
317 pcmd->maxRates = maxRates;
318 return true;
319 }
320
GetChanExtMaxRates(ScanInfo * pcmd,ScanInfoElem * infoElem)321 static bool GetChanExtMaxRates(ScanInfo *pcmd, ScanInfoElem* infoElem)
322 {
323 if ((pcmd == NULL) || (infoElem == NULL)) {
324 LOGE("pcmd or infoElem is NULL.");
325 return false;
326 }
327 if ((infoElem->content == NULL) || ((unsigned int)infoElem->size < EXT_SUPP_RATES_SIZE)) {
328 return false;
329 }
330 int maxIndex = infoElem->size - 1;
331 int maxRates = infoElem->content[maxIndex] & UINT8_MASK;
332 pcmd->extMaxRates = maxRates;
333 return true;
334 }
335
GetChanWidthCenterFreq(ScanInfo * pcmd,struct NeedParseIe * iesNeedParse)336 static void GetChanWidthCenterFreq(ScanInfo *pcmd, struct NeedParseIe* iesNeedParse)
337 {
338 if ((pcmd == NULL) || (iesNeedParse == NULL)) {
339 LOGE("pcmd or iesNeedParse is NULL.");
340 return;
341 }
342
343 if ((iesNeedParse->ieExtern != NULL) && GetChanWidthCenterFreqHe(pcmd, iesNeedParse->ieExtern)) {
344 return;
345 }
346 if ((iesNeedParse->ieVhtOper != NULL) && GetChanWidthCenterFreqVht(pcmd, iesNeedParse->ieVhtOper)) {
347 return;
348 }
349 if ((iesNeedParse->ieHtOper != NULL) && GetChanWidthCenterFreqHt(pcmd, iesNeedParse->ieHtOper)) {
350 return;
351 }
352 if ((iesNeedParse->ieMaxRate != NULL) && GetChanMaxRates(pcmd, iesNeedParse->ieMaxRate)) {
353 LOGE("pcmd maxRates is %{public}d.", pcmd->maxRates);
354 return;
355 }
356 if ((iesNeedParse->ieExtMaxRate != NULL) && GetChanExtMaxRates(pcmd, iesNeedParse->ieExtMaxRate)) {
357 LOGE("pcmd extMaxRates is %{public}d.", pcmd->extMaxRates);
358 return;
359 }
360 if (iesNeedParse->ieErp != NULL) {
361 LOGE("pcmd isErpExist is true.");
362 pcmd->isErpExist = 1;
363 return;
364 }
365 LOGE("GetChanWidthCenterFreq fail.");
366 return;
367 }
368
RecordIeNeedParse(unsigned int id,ScanInfoElem * ie,struct NeedParseIe * iesNeedParse)369 static void RecordIeNeedParse(unsigned int id, ScanInfoElem* ie, struct NeedParseIe* iesNeedParse)
370 {
371 if (iesNeedParse == NULL) {
372 return;
373 }
374 switch (id) {
375 case EXT_EXIST_EID:
376 iesNeedParse->ieExtern = ie;
377 break;
378 case VHT_OPER_EID:
379 iesNeedParse->ieVhtOper = ie;
380 break;
381 case HT_OPER_EID:
382 iesNeedParse->ieHtOper = ie;
383 break;
384 case SUPPORTED_RATES_EID:
385 iesNeedParse->ieMaxRate = ie;
386 break;
387 case ERP_EID:
388 iesNeedParse->ieErp = ie;
389 break;
390 case EXT_SUPPORTED_RATES_EID:
391 iesNeedParse->ieExtMaxRate = ie;
392 break;
393 default:
394 break;
395 }
396 }
397
GetInfoElems(int length,int end,char * srcBuf,ScanInfo * pcmd)398 static void GetInfoElems(int length, int end, char *srcBuf, ScanInfo *pcmd)
399 {
400 if (pcmd == NULL) {
401 LOGE("%{public}s, pcmd is NULL", __func__);
402 return;
403 }
404 int len;
405 int start = end + 1;
406 int last = end + 1;
407 int lenValue = 2;
408 int lastLength = 3;
409 int remainingLength = length - start;
410 int infoElemsSize = 0;
411 struct NeedParseIe iesNeedParse = {NULL};
412 ScanInfoElem* infoElemsTemp = (ScanInfoElem *)calloc(MAX_INFO_ELEMS_SIZE, sizeof(ScanInfoElem));
413 if (infoElemsTemp == NULL) {
414 LOGE("failed to alloc memory");
415 return;
416 }
417 if (memset_s(infoElemsTemp, MAX_INFO_ELEMS_SIZE * sizeof(ScanInfoElem),
418 0x0, MAX_INFO_ELEMS_SIZE * sizeof(ScanInfoElem)) != EOK) {
419 LOGE("GetInfoElems memset_s is failed");
420 free(infoElemsTemp);
421 infoElemsTemp = NULL;
422 return;
423 }
424 while (remainingLength > 1 && start < length) {
425 if (srcBuf[start] == '[') {
426 ++start;
427 infoElemsTemp[infoElemsSize].id = (unsigned int)atoi(srcBuf + start);
428 }
429 if (srcBuf[start] != ' ') {
430 ++start;
431 }
432 if (srcBuf[last] != ']') {
433 ++last;
434 continue;
435 }
436 len = last - start - 1;
437 infoElemsTemp[infoElemsSize].size = len/lenValue;
438 if ((len / lenValue + 1) <= 0) {
439 LOGI("GetInfoElems len is error");
440 break;
441 }
442 infoElemsTemp[infoElemsSize].content = (char *)calloc(len/lenValue+1, sizeof(char));
443 if (infoElemsTemp[infoElemsSize].content == NULL) {
444 break;
445 }
446 ++start;
447 srcBuf[last] = '\0';
448 HexStringToString(srcBuf + start, infoElemsTemp[infoElemsSize].content);
449 if ((length - last) > lastLength) { // make sure there is no useless character
450 last = last + 1;
451 }
452 start = last;
453 remainingLength = length - last;
454 RecordIeNeedParse(infoElemsTemp[infoElemsSize].id, &infoElemsTemp[infoElemsSize], &iesNeedParse);
455 ++infoElemsSize;
456 }
457 GetChanWidthCenterFreq(pcmd, &iesNeedParse);
458
459 // clear old infoElems first
460 if (pcmd->infoElems != NULL) {
461 for (int i = 0; i < pcmd->ieSize; i++) {
462 if (pcmd->infoElems[i].content != NULL) {
463 free(pcmd->infoElems[i].content);
464 pcmd->infoElems[i].content = NULL;
465 }
466 }
467 free(pcmd->infoElems);
468 pcmd->infoElems = NULL;
469 }
470 pcmd->infoElems = infoElemsTemp;
471 pcmd->ieSize = infoElemsSize;
472 return;
473 }
474 #endif
475
HdiParseExtensionInfo(const uint8_t * pos,size_t elen,struct HdiElems * elems,int show_errors)476 static int HdiParseExtensionInfo(const uint8_t *pos, size_t elen,
477 struct HdiElems *elems,
478 int show_errors)
479 {
480 uint8_t ext_id;
481
482 if (elen < 1) {
483 if (show_errors) {
484 LOGI("short information HdiElem (Ext)");
485 }
486 return -1;
487 }
488
489 ext_id = *pos++;
490 elen--;
491
492 switch (ext_id) {
493 case HDI_EID_EXT_ASSOC_DELAY_INFO:
494 if (elen != 1) {
495 break;
496 }
497 elems->assocDelayInfo = pos;
498 break;
499 case HDI_EID_EXT_FILS_REQ_PARAMS:
500 if (elen < HDI_POS_THIRD) {
501 break;
502 }
503 elems->filsReqParams = pos;
504 elems->filsReqParamsLen = elen;
505 break;
506 case HDI_EID_EXT_FILS_KEY_CONFIRM:
507 elems->filsKeyConfirm = pos;
508 elems->filsKeyConfirmLen = elen;
509 break;
510 case HDI_EID_EXT_FILS_SESSION:
511 if (elen != HDI_FILS_SESSION_LEN) {
512 break;
513 }
514 elems->filsSession = pos;
515 break;
516 case HDI_EID_EXT_FILS_HLP_CONTAINER:
517 if (elen < HDI_POS_SECOND * ETH_ALEN) {
518 break;
519 }
520 elems->filsHlp = pos;
521 elems->filsHlpLen = elen;
522 break;
523 case HDI_EID_EXT_FILS_IP_ADDR_ASSIGN:
524 if (elen < 1) {
525 break;
526 }
527 elems->addrAssign = pos;
528 elems->filsIpAddrAssignLen = elen;
529 break;
530 case HDI_EID_EXT_KEY_DELIVERY:
531 if (elen < HDI_KEY_RSC_LEN) {
532 break;
533 }
534 elems->delivery = pos;
535 elems->keyDeliveryLen = elen;
536 break;
537 case HDI_EID_EXT_FILS_WRAPPED_DATA:
538 elems->wrappedData = pos;
539 elems->filWrappedDataLen = elen;
540 break;
541 case HDI_EID_EXT_FILS_PUBLIC_KEY:
542 if (elen < 1) {
543 break;
544 }
545 elems->filsPk = pos;
546 elems->filsPkLen = elen;
547 break;
548 case HDI_EID_EXT_FILS_NONCE:
549 if (elen != HDI_FILS_NONCE_LEN) {
550 break;
551 }
552 elems->filsNonce = pos;
553 break;
554 case HDI_EID_EXT_OWE_DH_PARAM:
555 if (elen < HDI_POS_SECOND) {
556 break;
557 }
558 elems->oweDh = pos;
559 elems->oweDhLen = elen;
560 break;
561 case HDI_EID_EXT_PASSWORD_IDENTIFIER:
562 elems->passwordId = pos;
563 elems->passwordIdLen = elen;
564 break;
565 case HDI_EID_EXT_HE_CAPABILITIES:
566 elems->heCapabilities = pos;
567 elems->heCapabilitiesLen = elen;
568 break;
569 case HDI_EID_EXT_HE_OPERATION:
570 elems->heOperation = pos;
571 elems->heOperationLen = elen;
572 break;
573 case HDI_EID_EXT_OCV_OCI:
574 elems->oci = pos;
575 elems->ociLen = elen;
576 break;
577 case HDI_EID_EXT_EHT_CAPABILITIES_80211BE:
578 elems->ehtCapabilities80211Be = pos;
579 elems->ehtCapabilities80211BeLen = elen;
580 break;
581 default:
582 return -1;
583 }
584 return 0;
585 }
586
HdiParseVendorSpec(const uint8_t * pos,size_t elen,struct HdiElems * elems,int show_errors)587 static int HdiParseVendorSpec(const uint8_t *pos, size_t elen,
588 struct HdiElems *elems,
589 int show_errors)
590 {
591 unsigned int oui;
592
593 /* first 3 bytes in vendor specific information HdiElem are the IEEE
594 * OUI of the vendor. The following byte is used a vendor specific
595 * sub-type. */
596 if (elen < HDI_POS_FOURTH) {
597 if (show_errors) {
598 LOGI("short vendor specific "
599 "information HdiElem ignored (len=%{public}lu)",
600 (unsigned long) elen);
601 }
602 return -1;
603 }
604
605 oui = HdiGetBe24(pos);
606 switch (oui) {
607 case HDI_OUI_MICROSOFT:
608 /* Microsoft/Wi-Fi information elements are further typed and
609 * subtyped */
610 switch (pos[HDI_POS_THIRD]) {
611 case 1:
612 /* Microsoft OUI (00:50:F2) with OUI Type 1:
613 * real WPA information HdiElem */
614 elems->hdiIe = pos;
615 elems->wpaIeLen = elen;
616 break;
617 case HDI_WMM_OUI_TYPE:
618 /* WMM information HdiElem */
619 if (elen < HDI_POS_FIVE) {
620 LOGI("short WMM information HdiElem ignored (len=%{public}lu)",
621 (unsigned long) elen);
622 return -1;
623 }
624 switch (pos[HDI_POS_FOURTH]) {
625 case HDI_WMM_OUI_SUBTYPE_INFORMATION:
626 case HDI_WMM_OUI_SUBTYPE_PARAMETER:
627 /*
628 * Share same pointer since only one of these
629 * is used and they start with same data.
630 * Length field can be used to distinguish the
631 * IEs.
632 */
633 elems->wmm = pos;
634 elems->wmmLen = elen;
635 break;
636 case HDI_WMM_OUI_SUBTYPE_ELEMENT:
637 elems->wmmTspec = pos;
638 elems->wmmTspecLen = elen;
639 break;
640 default:
641 return -1;
642 }
643 break;
644 case HDI_POS_FOURTH:
645 /* Wi-Fi Protected Setup (WPS) IE */
646 elems->wpsIe = pos;
647 elems->hdiIeLen = elen;
648 break;
649 default:
650 return -1;
651 }
652 break;
653
654 case HDI_OUI_WFA:
655 switch (pos[HDI_POS_THIRD]) {
656 case HDI_P2P_OUI_TYPE:
657 /* Wi-Fi Alliance - P2P IE */
658 elems->p2p = pos;
659 elems->p2pLen = elen;
660 break;
661 case HDI_WFD_TYPE:
662 /* Wi-Fi Alliance - WFD IE */
663 elems->wfd = pos;
664 elems->wfdLen = elen;
665 break;
666 case HDI_HS20_INDICATION_OUI_TYPE:
667 /* Hotspot 2.0 */
668 elems->hs20 = pos;
669 elems->hs20Len = elen;
670 break;
671 case HDI_HS20_OSEN_OUI_TYPE:
672 /* Hotspot 2.0 OSEN */
673 elems->osen = pos;
674 elems->osenLen = elen;
675 break;
676 case HDI_MBO_OUI_TYPE:
677 /* MBO-OCE */
678 elems->mbo = pos;
679 elems->mboLen = elen;
680 break;
681 case HDI_HS20_ROAMING_CONS_SEL_OUI_TYPE:
682 /* Hotspot 2.0 Roaming Consortium Selection */
683 elems->roamingConsSel = pos;
684 elems->roamingConsSelLen = elen;
685 break;
686 case HDI_AP_OUI_TYPE:
687 elems->multiAp = pos;
688 elems->multiApLen = elen;
689 break;
690 default:
691 return -1;
692 }
693 break;
694
695 case HDI_OUI_BROADCOM:
696 switch (pos[HDI_POS_THIRD]) {
697 case HDI_HT_CAPAB_OUI_TYPE:
698 elems->vendorHtCap = pos;
699 elems->vendorHtCapLen = elen;
700 break;
701 case HDI_VHT_TYPE:
702 if (elen > HDI_POS_FOURTH &&
703 (pos[HDI_POS_FOURTH] == HDI_VHT_SUBTYPE ||
704 pos[HDI_POS_FOURTH] == HDI_VHT_SUBTYPE2)) {
705 elems->vendorVht = pos;
706 elems->vendorVhtLen = elen;
707 } else {
708 return -1;
709 }
710 break;
711 default:
712 return -1;
713 }
714 break;
715
716 case HDI_OUI_QCA:
717 switch (pos[HDI_POS_THIRD]) {
718 case HDI_VENDOR_ELEM_P2P_PREF_CHAN_LIST:
719 elems->prefFreqList = pos;
720 elems->prefFreqListLen = elen;
721 break;
722 default:
723 LOGI("Unknown QCA information HdiElem ignored (type=%{public}d len=%{public}lu)",
724 pos[HDI_POS_THIRD], (unsigned long) elen);
725 return -1;
726 }
727 break;
728
729 default:
730 return -1;
731 }
732
733 return 0;
734 }
735
HdiCheckExtCap(const uint8_t * ie,unsigned int capab)736 static int HdiCheckExtCap(const uint8_t *ie, unsigned int capab)
737 {
738 if (!ie || ie[1] <= capab / HDI_POS_EIGHT) {
739 return 0;
740 }
741 return !!(ie[HDI_POS_SECOND + capab / HDI_POS_EIGHT] & HDI_BIT(capab % HDI_POS_EIGHT));
742 }
743
HdiCheckBssExtCap(const uint8_t * ies,size_t len,unsigned int capab)744 static int HdiCheckBssExtCap(const uint8_t *ies, size_t len, unsigned int capab)
745 {
746 return HdiCheckExtCap(HdiBssGetIe(ies, len, HDI_EID_EXT_CAPAB),
747 capab);
748 }
749
HdiGetRsnCapabLen(const uint8_t * rsnxe,size_t rsnxe_len,unsigned int capab)750 static bool HdiGetRsnCapabLen(const uint8_t *rsnxe, size_t rsnxe_len,
751 unsigned int capab)
752 {
753 const uint8_t *end;
754 size_t flen, i;
755 uint32_t capabs = 0;
756
757 if (!rsnxe || rsnxe_len == 0) {
758 return false;
759 }
760 end = rsnxe + rsnxe_len;
761 flen = (rsnxe[0] & 0x0f) + 1;
762 if (rsnxe + flen > end) {
763 return false;
764 }
765 if (flen > HDI_POS_FOURTH) {
766 flen = HDI_POS_FOURTH;
767 }
768 for (i = 0; i < flen; i++) {
769 capabs |= rsnxe[i] << (HDI_POS_EIGHT * i);
770 }
771
772 return capabs & HDI_BIT(capab);
773 }
774
HdiGetRsnCapab(const uint8_t * rsnxe,unsigned int capab)775 static bool HdiGetRsnCapab(const uint8_t *rsnxe, unsigned int capab)
776 {
777 return HdiGetRsnCapabLen(rsnxe ? rsnxe + HDI_POS_SECOND : NULL,
778 rsnxe ? rsnxe[1] : 0, capab);
779 }
780
HdiCheckIsDmg(const int freq)781 static inline int HdiCheckIsDmg(const int freq)
782 {
783 return freq > HDI_POS_DMG;
784 }
785
Get80211ElemsFromIE(const uint8_t * start,size_t len,struct HdiElems * elems,int show)786 int Get80211ElemsFromIE(const uint8_t *start, size_t len, struct HdiElems *elems,
787 int show)
788 {
789 const struct HdiElem *elem;
790 int unknown = 0;
791 bool found_ssid = false;
792
793 if (memset_s(elems, sizeof(*elems), 0, sizeof(*elems)) != EOK) {
794 LOGE("%{public}s, memset_s is failed", __func__);
795 return false;
796 }
797
798 if (!start) {
799 return 0;
800 }
801
802 HDI_CHECK_ELEMENT(elem, start, len) {
803 if (elem == NULL) {
804 LOGE("%{public}s, elem is NULL", __func__);
805 return false;
806 }
807 uint8_t id = elem->id, elen = elem->datalen;
808 const uint8_t *pos = elem->data;
809
810 switch (id) {
811 case HDI_EID_SSID:
812 if (elen > SSID_MAX_LEN || found_ssid) {
813 LOGI("Ignored too long SSID HdiElem (elen=%{public}u) or ssid found", elen);
814 break;
815 }
816 elems->ssid = pos;
817 elems->ssidLen = elen;
818 found_ssid = true;
819 break;
820 case HDI_EID_SUPP_RATES:
821 elems->suppRates = pos;
822 elems->ratesLen = elen;
823 break;
824 case HDI_EID_DS_PARAMS:
825 if (elen < 1) {
826 break;
827 }
828 elems->dsParams = pos;
829 break;
830 case HDI_EID_CF_PARAMS:
831 case HDI_EID_TIM:
832 break;
833 case HDI_EID_CHALLENGE:
834 elems->challenge = pos;
835 elems->challengeLen = elen;
836 break;
837 case HDI_EID_ERP_INFO:
838 if (elen < 1) {
839 break;
840 }
841 elems->erpInfo = pos;
842 break;
843 case HDI_EID_EXT_SUPP_RATES:
844 elems->extSuppRates = pos;
845 elems->suppRatesLlen = elen;
846 break;
847 case HDI_EID_VENDOR_SPECIFIC:
848 if (HdiParseVendorSpec(pos, elen, elems, show)) {
849 unknown++;
850 }
851 break;
852 case HDI_EID_RSN:
853 elems->rsnIe = pos;
854 elems->rsnIeLen = elen;
855 break;
856 case HDI_EID_PWR_CAPABILITY:
857 if (elen < HDI_POS_SECOND) {
858 break;
859 }
860 elems->powerCapab = pos;
861 elems->powerCapabLen = elen;
862 break;
863 case HDI_EID_SUPPORTED_CHANNELS:
864 elems->hdiChannels = pos;
865 elems->channelsLen = elen;
866 break;
867 case HDI_EID_MOBILITY_DOMAIN:
868 if (elen < sizeof(struct HdiMdie)) {
869 break;
870 }
871 elems->mdie = pos;
872 elems->mdieLen = elen;
873 break;
874 case HDI_EID_FAST_BSS_TRANSITION:
875 if (elen < sizeof(struct HdiFtie)) {
876 break;
877 }
878 elems->ftie = pos;
879 elems->ftieLen = elen;
880 break;
881 case HDI_EID_TIMEOUT_INTERVAL:
882 if (elen != HDI_POS_FIVE)
883 break;
884 elems->timeout = pos;
885 break;
886 case HDI_EID_HT_CAP:
887 if (elen < sizeof(struct HdiHtCapabilities)) {
888 break;
889 }
890 elems->htCapabilities = pos;
891 break;
892 case HDI_EID_HT_OPERATION:
893 if (elen < sizeof(struct HdiHtOperation)) {
894 break;
895 }
896 elems->htOperation = pos;
897 break;
898 case HDI_EID_MESH_CONFIG:
899 elems->meshCfg = pos;
900 elems->meshConfigLen = elen;
901 break;
902 case HDI_EID_MESH_ID:
903 elems->meshId = pos;
904 elems->meshIdLen = elen;
905 break;
906 case HDI_EID_PEER_MGMT:
907 elems->peerMgmt = pos;
908 elems->peerMgmtLen = elen;
909 break;
910 case HDI_EID_VHT_CAP:
911 if (elen < sizeof(struct HdiVhtCapabilities)) {
912 break;
913 }
914 elems->vhtCapabilities = pos;
915 break;
916 case HDI_EID_VHT_OPERATION:
917 if (elen < sizeof(struct HdiVhtOperation)) {
918 break;
919 }
920 elems->vhtOperation = pos;
921 break;
922 case HDI_EID_VHT_OPERATING_MODE_NOTIFICATION:
923 if (elen != 1) {
924 break;
925 }
926 elems->vhtOpmodeNotif = pos;
927 break;
928 case HDI_EID_LINK_ID:
929 if (elen < HDI_POS_ET) {
930 break;
931 }
932 elems->linkId = pos;
933 break;
934 case HDI_EID_INTERWORKING:
935 elems->interworking = pos;
936 elems->interworkingLen = elen;
937 break;
938 case HDI_EID_QOS_MAP_SET:
939 if (elen < HDI_POS_OT) {
940 break;
941 }
942 elems->mapSet = pos;
943 elems->qosMapSetLen = elen;
944 break;
945 case HDI_EID_EXT_CAPAB:
946 elems->extCapab = pos;
947 elems->extCapabLen = elen;
948 break;
949 case HDI_EID_BSS_MAX_IDLE_PERIOD:
950 if (elen < HDI_POS_THIRD) {
951 break;
952 }
953 elems->maxIdlePeriod = pos;
954 break;
955 case HDI_EID_SSID_LIST:
956 elems->ssidList = pos;
957 elems->ssidListLen = elen;
958 break;
959 case HDI_EID_AMPE:
960 elems->ampe = pos;
961 elems->ampeLen = elen;
962 break;
963 case HDI_EID_MIC:
964 elems->mic = pos;
965 elems->micLen = elen;
966 /* after mic everything is encrypted, so stop. */
967 goto done;
968 case HDI_EID_MULTI_BAND:
969 if (elems->hdiIes.nofIes >= HDI_MAX_IES_SUPPORTED) {
970 LOGI("IEEE 802.11 HdiElem parse ignored MB IE (id=%{public}d elen=%{public}d)",
971 id, elen);
972 break;
973 }
974
975 elems->hdiIes.ies[elems->hdiIes.nofIes].ie = pos;
976 elems->hdiIes.ies[elems->hdiIes.nofIes].ieLen = elen;
977 elems->hdiIes.nofIes++;
978 break;
979 case HDI_EID_SUPPORTED_OPERATING_CLASSES:
980 elems->opClasses = pos;
981 elems->suppOpClassesLen = elen;
982 break;
983 case HDI_EID_RRM_ENABLED_CAPABILITIES:
984 elems->rrmEnabled = pos;
985 elems->rrmEnabledLen = elen;
986 break;
987 case HDI_EID_CAG_NUMBER:
988 elems->cagNumber = pos;
989 elems->cagNumberLen = elen;
990 break;
991 case HDI_EID_AP_CSN:
992 if (elen < 1) {
993 break;
994 }
995 elems->apCsn = pos;
996 break;
997 case HDI_EID_FILS_INDICATION:
998 if (elen < HDI_POS_SECOND) {
999 break;
1000 }
1001 elems->filsIndic = pos;
1002 elems->filsIndicLen = elen;
1003 break;
1004 case HDI_EID_DILS:
1005 if (elen < HDI_POS_SECOND) {
1006 break;
1007 }
1008 elems->dils = pos;
1009 elems->dilsLen = elen;
1010 break;
1011 case HDI_EID_FRAGMENT:
1012 break;
1013 case HDI_EID_EXTENSION:
1014 if (HdiParseExtensionInfo(pos, elen, elems, show)) {
1015 unknown++;
1016 }
1017 break;
1018 default:
1019 unknown++;
1020 if (!show) {
1021 break;
1022 }
1023 break;
1024 }
1025 }
1026
1027 if (!HdiCheckCompleted(elem, start, len)) {
1028 if (show) {
1029 LOGI("IEEE 802.11 HdiElem parse failed @%{public}d",
1030 (int) (start + len - (const uint8_t *) elem));
1031 }
1032 return -1;
1033 }
1034
1035 done:
1036 return unknown ? 1 : 0;
1037 }
1038
1039 /* Format one result on one text line into a buffer. */
GetScanResultText(const struct WifiScanResultExt * scanResult,struct HdiElems * elems,char * buf,int bufLen)1040 int GetScanResultText(const struct WifiScanResultExt *scanResult,
1041 struct HdiElems *elems, char* buf, int bufLen)
1042 {
1043 char *pos, *end;
1044 int ret;
1045 const uint8_t *ie, *ie2, *osen_ie, *p2p, *mesh, *owe, *rsnxe;
1046 const uint8_t *infoEle;
1047
1048 mesh = HdiBssGetIe(scanResult->ie, scanResult->ieLen, HDI_EID_MESH_ID);
1049 p2p = HdiBssGetVendorIe(scanResult->ie, scanResult->ieLen, HDI_P2P_IE_VENDOR_TYPE);
1050 if (!p2p)
1051 p2p = HdiBssGetVendorBeacon(scanResult->ie, scanResult->ieLen,
1052 scanResult->beaconIeLen, HDI_P2P_IE_VENDOR_TYPE);
1053 if (p2p && elems->ssidLen == HDI_P2P_CARD_SSID_LEN &&
1054 memcmp(elems->ssid, HDI_P2P_CARD_SSID, HDI_P2P_CARD_SSID_LEN) == 0) {
1055 return 0;
1056 }
1057
1058 pos = buf;
1059 end = buf + bufLen - 1;
1060
1061 ret = HdiTxtPrintf(pos, end - pos, MACSTR "\t%d\t%d\t",
1062 MAC2STR(scanResult->bssid), scanResult->freq, scanResult->level);
1063 if (HdiCheckError(end - pos, ret)) {
1064 return -1;
1065 }
1066 pos += ret;
1067 pos = HdiGetWifiCategoryTxt(pos, end, elems);
1068 ie = HdiBssGetVendorIe(scanResult->ie, scanResult->ieLen, HDI_IE_VENDOR_TYPE);
1069 if (ie)
1070 pos = HdiGetIeTxt(pos, end, "WPA", ie, HDI_POS_SECOND + ie[1]);
1071 ie2 = HdiBssGetIe(scanResult->ie, scanResult->ieLen, HDI_EID_RSN);
1072 if (ie2) {
1073 pos = HdiGetIeTxt(pos, end, mesh ? "RSN" : "WPA2",
1074 ie2, HDI_POS_SECOND + ie2[1]);
1075 }
1076
1077 const uint8_t *wapi;
1078 wapi = HdiBssGetIe(scanResult->ie, scanResult->ieLen, HDI_EID_WAPI);
1079 if (wapi) {
1080 pos = HdiGetWapiTxt(pos, end, wapi);
1081 }
1082
1083 rsnxe = HdiBssGetIe(scanResult->ie, scanResult->ieLen, HDI_EID_RSNX);
1084 if (HdiGetRsnCapab(rsnxe, HDI_RSNX_CAPAB_SAE_H2E)) {
1085 ret = HdiTxtPrintf(pos, end - pos, "[SAE-H2E]");
1086 if (HdiCheckError(end - pos, ret)) {
1087 return -1;
1088 }
1089 pos += ret;
1090 }
1091 if (HdiGetRsnCapab(rsnxe, HDI_RSNX_CAPAB_SAE_PK)) {
1092 ret = HdiTxtPrintf(pos, end - pos, "[SAE-PK]");
1093 if (HdiCheckError(end - pos, ret)) {
1094 return -1;
1095 }
1096 pos += ret;
1097 }
1098 osen_ie = HdiBssGetVendorIe(scanResult->ie, scanResult->ieLen, HDI_OSEN_IE_VENDOR_TYPE);
1099 if (osen_ie) {
1100 pos = HdiGetIeTxt(pos, end, "OSEN", osen_ie, HDI_POS_SECOND + osen_ie[1]);
1101 }
1102 owe = HdiBssGetVendorIe(scanResult->ie, scanResult->ieLen, HDI_OWE_VENDOR_TYPE);
1103 if (owe) {
1104 ret = HdiTxtPrintf(pos, end - pos,
1105 ie2 ? "[OWE-TRANS]" : "[OWE-TRANS-OPEN]");
1106 if (HdiCheckError(end - pos, ret)) {
1107 return -1;
1108 }
1109 pos += ret;
1110 }
1111 if (!ie && !ie2 && !osen_ie && !wapi && (scanResult->caps & HDI_CAP_PRIVACY)) {
1112 ret = HdiTxtPrintf(pos, end - pos, "[WEP]");
1113 if (HdiCheckError(end - pos, ret)) {
1114 return -1;
1115 }
1116 pos += ret;
1117 }
1118 if (mesh) {
1119 ret = HdiTxtPrintf(pos, end - pos, "[MESH]");
1120 if (HdiCheckError(end - pos, ret)) {
1121 return -1;
1122 }
1123 pos += ret;
1124 }
1125 if (HdiCheckIsDmg(scanResult->freq)) {
1126 const char *s;
1127
1128 if (HdiBssGetIeExt(scanResult->ie, scanResult->ieLen, HDI_EID_EXT_EDMG_OPERATION)) {
1129 ret = HdiTxtPrintf(pos, end - pos, "[EDMG]");
1130 if (HdiCheckError(end - pos, ret)) {
1131 return -1;
1132 }
1133 pos += ret;
1134 }
1135
1136 ret = HdiTxtPrintf(pos, end - pos, "[DMG]");
1137 if (HdiCheckError(end - pos, ret)) {
1138 return -1;
1139 }
1140 pos += ret;
1141 switch (scanResult->caps & HDI_CAP_DMG_MASK) {
1142 case HDI_CAP_DMG_IBSS:
1143 s = "[IBSS]";
1144 break;
1145 case HDI_CAP_DMG_AP:
1146 s = "[ESS]";
1147 break;
1148 case HDI_CAP_DMG_PBSS:
1149 s = "[PBSS]";
1150 break;
1151 default:
1152 s = "";
1153 break;
1154 }
1155 ret = HdiTxtPrintf(pos, end - pos, "%s", s);
1156 if (HdiCheckError(end - pos, ret)) {
1157 return -1;
1158 }
1159 pos += ret;
1160 } else {
1161 if (scanResult->caps & HDI_CAP_IBSS) {
1162 ret = HdiTxtPrintf(pos, end - pos, "[IBSS]");
1163 if (HdiCheckError(end - pos, ret)) {
1164 return -1;
1165 }
1166 pos += ret;
1167 }
1168 if (scanResult->caps & HDI_CAP_ESS) {
1169 ret = HdiTxtPrintf(pos, end - pos, "[ESS]");
1170 if (HdiCheckError(end - pos, ret)) {
1171 return -1;
1172 }
1173 pos += ret;
1174 }
1175 }
1176 if (p2p) {
1177 ret = HdiTxtPrintf(pos, end - pos, "[P2P]");
1178 if (HdiCheckError(end - pos, ret)) {
1179 return -1;
1180 }
1181 pos += ret;
1182 }
1183
1184 if (HdiCheckBssExtCap(scanResult->ie, scanResult->ieLen, HDI_EXT_CAPAB_UTF_8_SSID)) {
1185 ret = HdiTxtPrintf(pos, end - pos, "[UTF-8]");
1186 if (HdiCheckError(end - pos, ret)) {
1187 return -1;
1188 }
1189 pos += ret;
1190 }
1191
1192 ret = HdiTxtPrintf(pos, end - pos, "\t%s\t", HdiSSid2Txt(elems->ssid, elems->ssidLen));
1193 if (HdiCheckError(end - pos, ret)) {
1194 return -1;
1195 }
1196 pos += ret;
1197
1198 for (int j = 0; j < HDI_EID_EXTENSION; j++) {
1199 if ((j != HDI_EID_VHT_OPERATION) && (j != HDI_EID_HT_OPERATION) &&
1200 (j != HDI_EID_SUPPORTED_CHANNELS) && (j != HDI_EID_COUNTRY)) {
1201 continue;
1202 }
1203 infoEle = HdiBssGetIe(scanResult->ie, scanResult->ieLen, j);
1204 if (infoEle && infoEle[1] > 0) {
1205 ret = HdiTxtPrintf(pos, end - pos, "[%d ", j);
1206 if (HdiCheckError(end - pos, ret)) {
1207 return -1;
1208 }
1209 pos += ret;
1210 for (uint8_t i = 0; i < infoEle[1]; i++) {
1211 ret = HdiTxtPrintf(pos, end - pos, "%02x", infoEle[i + HDI_POS_SECOND]);
1212 if (HdiCheckError(end - pos, ret)) {
1213 return -1;
1214 }
1215 pos += ret;
1216 }
1217 ret = HdiTxtPrintf(pos, end - pos, "]");
1218 if (HdiCheckError(end - pos, ret)) {
1219 return -1;
1220 }
1221 pos += ret;
1222 }
1223 }
1224
1225 infoEle = HdiBssGetIeExt(scanResult->ie, scanResult->ieLen, HDI_EID_EXT_HE_OPERATION);
1226 // infoEle format: First position: Tag number, second postion: Tag length, third postion: ext tag number.
1227 if (infoEle) {
1228 unsigned int len = infoEle[1];
1229 if (len > 1) {
1230 ret = HdiTxtPrintf(pos, end - pos, "[%d %02x",
1231 HDI_EID_EXTENSION, HDI_EID_EXT_HE_OPERATION);
1232 if (HdiCheckError(end - pos, ret)) {
1233 return -1;
1234 }
1235 pos += ret;
1236 for (size_t i = 0; i < len - 1; i++) { // because ext tag number used one postion, len need substract 1.
1237 ret = HdiTxtPrintf(pos, end - pos, "%02x", infoEle[i + HDI_POS_THIRD]);
1238 if (HdiCheckError(end - pos, ret)) {
1239 return -1;
1240 }
1241 pos += ret;
1242 }
1243 ret = HdiTxtPrintf(pos, end - pos, "]");
1244 if (HdiCheckError(end - pos, ret)) {
1245 return -1;
1246 }
1247 pos += ret;
1248 }
1249 }
1250
1251 ret = HdiTxtPrintf(pos, end - pos, "\n");
1252 if (HdiCheckError(end - pos, ret)) {
1253 return -1;
1254 }
1255 pos += ret;
1256
1257 return pos - buf;
1258 }
1259
DelScanInfoLine(ScanInfo * pcmd,char * srcBuf,int length)1260 int DelScanInfoLine(ScanInfo *pcmd, char *srcBuf, int length)
1261 {
1262 int columnIndex = 0;
1263 int start = 0;
1264 int end = 0;
1265 int fail = 0;
1266 while (end < length) {
1267 if (srcBuf[end] != '\t') {
1268 ++end;
1269 continue;
1270 }
1271 srcBuf[end] = '\0';
1272 if (columnIndex == COLUMN_INDEX_ZERO) {
1273 if (strcpy_s(pcmd->bssid, sizeof(pcmd->bssid), srcBuf + start) != EOK) {
1274 fail = 1;
1275 break;
1276 }
1277 } else if (columnIndex == COLUMN_INDEX_ONE) {
1278 pcmd->freq = atoi(srcBuf + start);
1279 } else if (columnIndex == COLUMN_INDEX_TWO) {
1280 pcmd->siglv = atoi(srcBuf + start);
1281 } else if (columnIndex == COLUMN_INDEX_THREE) {
1282 if (strcpy_s(pcmd->flags, sizeof(pcmd->flags), srcBuf + start) != EOK) {
1283 fail = 1;
1284 break;
1285 }
1286 #ifdef OHOS_ARCH_LITE // The wpa of arch lite don't return "informationElements".
1287 start = end + 1;
1288 if (strcpy_s(pcmd->ssid, sizeof(pcmd->ssid), srcBuf + start) != EOK) {
1289 fail = 1;
1290 break;
1291 }
1292 PrintfDecode((u8 *)pcmd->ssid, sizeof(pcmd->ssid), pcmd->ssid);
1293 start = length;
1294 break;
1295 #else
1296 } else if (columnIndex == COLUMN_INDEX_FOUR) {
1297 if (strcpy_s(pcmd->ssid, sizeof(pcmd->ssid), srcBuf + start) != EOK) {
1298 fail = 1;
1299 break;
1300 }
1301 PrintfDecode((u8 *)pcmd->ssid, sizeof(pcmd->ssid), pcmd->ssid);
1302 GetInfoElems(length, end, srcBuf, pcmd);
1303 start = length;
1304 break;
1305 #endif
1306 }
1307 ++columnIndex;
1308 ++end;
1309 start = end;
1310 }
1311 if (fail == 0 && start < length) {
1312 if (strcpy_s(pcmd->flags, sizeof(pcmd->flags), srcBuf + start) != EOK) {
1313 fail = 1;
1314 }
1315 }
1316 return fail;
1317 }
1318
ConvertMacArr2String(const unsigned char * srcMac,int srcMacSize,char * destMacStr,int strLen)1319 int ConvertMacArr2String(const unsigned char *srcMac, int srcMacSize, char *destMacStr, int strLen)
1320 {
1321 if (srcMac == NULL || destMacStr == NULL || srcMacSize != MAC_UINT_SIZE || strLen <= MAC_STRING_SIZE) {
1322 return -1;
1323 }
1324 const int srcMacPosZero = 0;
1325 const int srcMacPosOne = 1;
1326 const int srcMacPosTwo = 2;
1327 const int srcMacPosThree = 3;
1328 const int srcMacPosFour = 4;
1329 const int srcMacPosFive = 5;
1330 if (snprintf_s(destMacStr, strLen, strLen - 1, "%02x:%02x:%02x:%02x:%02x:%02x", srcMac[srcMacPosZero],
1331 srcMac[srcMacPosOne], srcMac[srcMacPosTwo], srcMac[srcMacPosThree], srcMac[srcMacPosFour],
1332 srcMac[srcMacPosFive]) < 0) {
1333 return -1;
1334 }
1335 return 0;
1336 }
1337
GetScanResultInfoElem(ScanInfo * scanInfo,const uint8_t * start,size_t len)1338 void GetScanResultInfoElem(ScanInfo *scanInfo, const uint8_t *start, size_t len)
1339 {
1340 if (scanInfo == NULL || start == NULL) {
1341 LOGE("scanInfo or start is NULL.");
1342 return;
1343 }
1344 const struct HdiElem *elem;
1345 int ieIndex = 0;
1346 bool found_ssid = false;
1347 ScanInfoElem* infoElemsTemp = (ScanInfoElem *)calloc(MAX_INFO_ELEMS_SIZE, sizeof(ScanInfoElem));
1348 if (infoElemsTemp == NULL) {
1349 LOGE("failed to alloc memory");
1350 return;
1351 }
1352 if (memset_s(infoElemsTemp, MAX_INFO_ELEMS_SIZE * sizeof(ScanInfoElem),
1353 0x0, MAX_INFO_ELEMS_SIZE * sizeof(ScanInfoElem)) != EOK) {
1354 LOGE("GetScanResultInfoElem memset_s is failed");
1355 free(infoElemsTemp);
1356 infoElemsTemp = NULL;
1357 return;
1358 }
1359 HDI_CHECK_ELEMENT(elem, start, len) {
1360 if ((unsigned int)ieIndex >= MAX_INFO_ELEMS_SIZE) {
1361 LOGE("ieIndex exceeds the upper limit.");
1362 break;
1363 }
1364 uint8_t id = elem->id, elen = elem->datalen;
1365 if (id == HDI_EID_SSID) {
1366 if (found_ssid) {
1367 continue;
1368 }
1369 found_ssid = true;
1370 }
1371 infoElemsTemp[ieIndex].id = id;
1372 infoElemsTemp[ieIndex].size = elen;
1373 infoElemsTemp[ieIndex].content = (char *)calloc(elen+1, sizeof(char));
1374 if (infoElemsTemp[ieIndex].content == NULL) {
1375 break;
1376 }
1377 if (memcpy_s(infoElemsTemp[ieIndex].content, elen+1, elem->data, elen) != EOK) {
1378 LOGE("memcpy content fail");
1379 free(infoElemsTemp[ieIndex].content);
1380 infoElemsTemp[ieIndex].content = NULL;
1381 free(infoElemsTemp);
1382 infoElemsTemp = NULL;
1383 return;
1384 }
1385 ieIndex++;
1386 }
1387 // clear old infoElems first
1388 if (scanInfo->infoElems != NULL) {
1389 for (int i = 0; i < scanInfo->ieSize; i++) {
1390 if (scanInfo->infoElems[i].content != NULL) {
1391 free(scanInfo->infoElems[i].content);
1392 scanInfo->infoElems[i].content = NULL;
1393 }
1394 }
1395 free(scanInfo->infoElems);
1396 scanInfo->infoElems = NULL;
1397 }
1398 scanInfo->infoElems = infoElemsTemp;
1399 scanInfo->ieSize = ieIndex;
1400 }
1401
CheckHiLinkSection(const uint8_t * bytes,uint8_t len)1402 static uint8_t CheckHiLinkSection(const uint8_t *bytes, uint8_t len)
1403 {
1404 int formatHiLink[] = { 0, 0xE0, 0XFC, 0X80, 0, 0, 0, 0X01, 0 };
1405 if (bytes == NULL || len < HILINK_HEAD_LEN) {
1406 return 0;
1407 }
1408
1409 for (int index = 0; index < HILINK_HEAD_LEN; index++) {
1410 int element = bytes[index];
1411 if (element != formatHiLink[index]) {
1412 return 0;
1413 }
1414 }
1415
1416 return 1;
1417 }
1418
CheckHiLinkOUISection(const uint8_t * bytes,uint8_t len)1419 static uint8_t CheckHiLinkOUISection(const uint8_t *bytes, uint8_t len)
1420 {
1421 int formatHiLinkOUI[] = { 0, 0xE0, 0XFC, 0X40, 0, 0, 0 };
1422 int okcLogo[] = { 0xF9 };
1423 if (bytes == NULL || len < HILINK_OUI_HEAD_LEN) {
1424 return 0;
1425 }
1426
1427 for (int index = 0; index < HILINK_OUI_HEAD_LEN; index++) {
1428 int element = bytes[index];
1429 if (element != formatHiLinkOUI[index]) {
1430 return 0;
1431 }
1432 }
1433 /* check hilink ninth data, if equal 0XF9, return eleventh data.else find next data */
1434 int index = HILINK_HEAD_LEN;
1435 while ((index < len) && (index >= 0)) {
1436 int element = bytes[index];
1437 if (element != okcLogo[0]) {
1438 if (index + 1 >= len) {
1439 return 0;
1440 }
1441 int tlvLength = bytes[index + 1];
1442 index = tlvLength + HILINK_OFFSET_LEN + index;
1443 } else {
1444 if (index + HILINK_OFFSET_LEN >= len) {
1445 return 0;
1446 }
1447 return bytes[index + HILINK_OFFSET_LEN];
1448 }
1449 }
1450
1451 return 0;
1452 }
1453
RouterSupportHiLinkByWifiInfo(const uint8_t * start,size_t len)1454 int RouterSupportHiLinkByWifiInfo(const uint8_t *start, size_t len)
1455 {
1456 const struct HdiElem *elem;
1457 uint8_t num = 0;
1458 uint8_t hiLinkSectionNum = 0;
1459 uint8_t hiLinkOUISectionNum = 0;
1460 if (!start) {
1461 return num;
1462 }
1463
1464 HDI_CHECK_ELEMENT(elem, start, len) {
1465 if (elem == NULL) {
1466 return num;
1467 }
1468 uint8_t id = elem->id, elen = elem->datalen;
1469 const uint8_t *pos = elem->data;
1470 if (id == HDI_EID_VENDOR_SPECIFIC) {
1471 hiLinkSectionNum |= CheckHiLinkSection(pos, elen);
1472 hiLinkOUISectionNum |= CheckHiLinkOUISection(pos, elen);
1473 }
1474 }
1475 return hiLinkOUISectionNum ? hiLinkOUISectionNum : hiLinkSectionNum;
1476 }
1477