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