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