• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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