blob: 4f862e824f5a486ec29ba72616819b3db18e58ff [file] [log] [blame]
developerf4a48782022-08-02 18:22:33 +08001From 4592e371528abdf4804c116760059b0a0fb4dbc6 Mon Sep 17 00:00:00 2001
2From: "Allen.Ye" <allen.ye@mediatek.com>
3Date: Tue, 2 Aug 2022 17:23:06 +0800
4Subject: [PATCH] HAL: refactor NeighboringWiFiDiagnosticResult2 scan part and
5 add scan filter function
6
7---
8 source/wifi/wifi_hal.c | 289 ++++++++++++++++++++++++++++++++++++-----
9 1 file changed, 259 insertions(+), 30 deletions(-)
10
11diff --git a/source/wifi/wifi_hal.c b/source/wifi/wifi_hal.c
12index e49f22f..44f167b 100644
13--- a/source/wifi/wifi_hal.c
14+++ b/source/wifi/wifi_hal.c
15@@ -73,6 +73,8 @@ Licensed under the ISC license
16 //#define ACL_PREFIX "/tmp/wifi_acl_list" //RDKB convention
17 #define SOCK_PREFIX "/var/run/hostapd/wifi"
18 #define VAP_STATUS_FILE "/tmp/vap-status"
19+#define ESSID_FILE "/tmp/essid"
20+
21 #ifdef MTK_IMPL
22 #define DRIVER_2GHZ "mt7915e"
23 #define DRIVER_5GHZ "mt7915e"
24@@ -3037,47 +3039,243 @@ INT wifi_applySSIDSettings(INT ssidIndex)
25 return ret;
26 }
27
28+struct channels_noise {
29+ int channel;
30+ int noise;
31+};
32+
33+// Return noise array for each channel
34+int get_noise(int radioIndex, struct channels_noise *channels_noise_arr, int channels_num)
35+{
36+ FILE *f = NULL;
37+ char cmd[128] = {0};
38+ char *line = NULL;
39+ size_t len = 0;
40+ ssize_t read = 0;
41+ int tmp = 0, arr_index = -1;
42+
43+ sprintf(cmd, "iw dev %s%d survey dump | grep 'frequency\\|noise' | awk '{print $2}'", AP_PREFIX, radioIndex);
44+
45+ if ((f = popen(cmd, "r")) == NULL) {
46+ wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
47+ return RETURN_ERR;
48+ }
49+
50+ while((read = getline(&line, &len, f)) != -1) {
51+ sscanf(line, "%d", &tmp);
52+ if (tmp > 0) { // channel frequency, the first line must be frequency
53+ arr_index++;
54+ channels_noise_arr[arr_index].channel = ieee80211_frequency_to_channel(tmp);
55+ } else { // noise
56+ channels_noise_arr[arr_index].noise = tmp;
57+ }
58+ }
59+ free(line);
60+ pclose(f);
61+ return RETURN_OK;
62+}
63+
64 //Start the wifi scan and get the result into output buffer for RDKB to parser. The result will be used to manage endpoint list
65 //HAL funciton should allocate an data structure array, and return to caller with "neighbor_ap_array"
66 INT wifi_getNeighboringWiFiDiagnosticResult2(INT radioIndex, wifi_neighbor_ap2_t **neighbor_ap_array, UINT *output_array_size) //Tr181
67 {
68- INT status = RETURN_ERR;
69- UINT index;
70- wifi_neighbor_ap2_t *pt=NULL;
71- char cmd[128]={0};
72- char buf[8192]={0};
73+ int index = -1;
74+ wifi_neighbor_ap2_t *scan_array = NULL;
75+ char cmd[256]={0};
76+ char buf[128]={0};
77+ char file_name[32] = {0};
78+ char filter_SSID[32] = {0};
79+ int freq=0;
80+ FILE *f = NULL;
81+ size_t len=0;
82+ ssize_t read = 0;
83+ char *line =NULL;
84+ // int noise_arr[channels_num] = {0};
85+ int channels_num = 0;
86+ int vht_channel_width = 0;
87+ bool get_nosie_ret = false;
88+ bool filter_enable = false;
89+ bool filter_BSS = false; // The flag determine whether the BSS information need to be filterd.
90
91 WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
92- sprintf(cmd, "iwlist %s%d scan",AP_PREFIX,(radioIndex==0)?0:1); //suppose ap0 mapping to radio0
93+
94+ snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, radioIndex);
95+ f = fopen(file_name, "r");
96+ if (f != NULL) {
97+ fgets(filter_SSID, sizeof(file_name), f);
98+ if (strlen(filter_SSID) != 0)
99+ filter_enable = true;
100+ fclose(f);
101+ }
102+
103+ snprintf(cmd, sizeof(cmd), "iw phy phy%d channels | grep * | grep -v disable | wc -l", radioIndex);
104 _syscmd(cmd, buf, sizeof(buf));
105+ channels_num = atoi(buf);
106
107+ struct channels_noise *channels_noise_arr = calloc(channels_num, sizeof(struct channels_noise));
108+ get_nosie_ret = get_noise(radioIndex, channels_noise_arr, channels_num);
109+
110+ sprintf(cmd, "iw dev %s%d scan | grep '%s%d\\|SSID\\|freq\\|beacon interval\\|capabilities\\|signal\\|Supported rates\\|DTIM\\| \
111+ // WPA\\|RSN\\|Group cipher\\|HT operation\\|secondary channel offset\\|channel width\\|HE160' | grep -v -e '*.*BSS'", AP_PREFIX, radioIndex, AP_PREFIX, radioIndex);
112+ fprintf(stderr, "cmd: %s\n", cmd);
113+ if ((f = popen(cmd, "r")) == NULL) {
114+ wifi_dbg_printf("%s: popen %s error\n", __func__, cmd);
115+ return RETURN_ERR;
116+ }
117
118- *output_array_size=2;
119- //zqiu: HAL alloc the array and return to caller. Caller response to free it.
120- *neighbor_ap_array=(wifi_neighbor_ap2_t *)calloc(sizeof(wifi_neighbor_ap2_t), *output_array_size);
121- for (index = 0, pt=*neighbor_ap_array; index < *output_array_size; index++, pt++) {
122- strcpy(pt->ap_SSID,"");
123- strcpy(pt->ap_BSSID,"");
124- strcpy(pt->ap_Mode,"");
125- pt->ap_Channel=1;
126- pt->ap_SignalStrength=0;
127- strcpy(pt->ap_SecurityModeEnabled,"");
128- strcpy(pt->ap_EncryptionMode,"");
129- strcpy(pt->ap_OperatingFrequencyBand,"");
130- strcpy(pt->ap_SupportedStandards,"");
131- strcpy(pt->ap_OperatingStandards,"");
132- strcpy(pt->ap_OperatingChannelBandwidth,"");
133- pt->ap_BeaconPeriod=1;
134- pt->ap_Noise=0;
135- strcpy(pt->ap_BasicDataTransferRates,"");
136- strcpy(pt->ap_SupportedDataTransferRates,"");
137- pt->ap_DTIMPeriod=1;
138- pt->ap_ChannelUtilization=0;
139+ while ((read = getline(&line, &len, f)) != -1) {
140+ if(strstr(line, "BSS") != NULL) { // new neighbor info
141+ // The SSID field is not in the first field. So, we should store whole BSS informations and the filter flag.
142+ // And we will determine whether we need the previous BSS infomation when parsing the next BSS field or end of while loop.
143+ // If we don't want the BSS info, we don't realloc more space, and just clean the previous BSS.
144+
145+ if (!filter_BSS) {
146+ index++;
147+ wifi_neighbor_ap2_t *tmp;
148+ tmp = realloc(scan_array, sizeof(wifi_neighbor_ap2_t)*(index+1));
149+ if (tmp == NULL) { // no more memory to use
150+ index--;
151+ wifi_dbg_printf("%s: realloc failed\n", __func__);
152+ break;
153+ }
154+ scan_array = tmp;
155+ }
156+ memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
157+
158+ filter_BSS = false;
159+ sscanf(line, "BSS %17s", scan_array[index].ap_BSSID);
160+ strncpy(scan_array[index].ap_Mode, "Infrastructure", strlen("Infrastructure"));
161+ strncpy(scan_array[index].ap_SecurityModeEnabled, "None", strlen("None"));
162+ strncpy(scan_array[index].ap_EncryptionMode, "None", strlen("None"));
163+ } else if (strstr(line, "freq") != NULL) {
164+ sscanf(line," freq: %d", &freq);
165+ scan_array[index].ap_Channel = ieee80211_frequency_to_channel(freq);
166+
167+ if (freq >= 2412 && freq <= 2484) {
168+ strncpy(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz"));
169+ strncpy(scan_array[index].ap_SupportedStandards, "b,g", strlen("b,g"));
170+ strncpy(scan_array[index].ap_OperatingStandards, "g", strlen("g"));
171+ }
172+ else if (freq >= 5160 && freq <= 5805) {
173+ strncpy(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz"));
174+ strncpy(scan_array[index].ap_SupportedStandards, "a", strlen("a"));
175+ strncpy(scan_array[index].ap_OperatingStandards, "a", strlen("a"));
176+ }
177+
178+ scan_array[index].ap_Noise = 0;
179+ if (get_nosie_ret) {
180+ for (int i = 0; i < channels_num; i++) {
181+ if (scan_array[index].ap_Channel == channels_noise_arr[i].channel) {
182+ scan_array[index].ap_Noise = channels_noise_arr[i].noise;
183+ break;
184+ }
185+ }
186+ }
187+ } else if (strstr(line, "beacon interval") != NULL) {
188+ sscanf(line," beacon interval: %d TUs", &(scan_array[index].ap_BeaconPeriod));
189+ } else if (strstr(line, "signal") != NULL) {
190+ sscanf(line," signal: %d", &(scan_array[index].ap_SignalStrength));
191+ } else if (strstr(line,"SSID") != NULL) {
192+ sscanf(line," SSID: %s", scan_array[index].ap_SSID);
193+ if (filter_enable && strcmp(scan_array[index].ap_SSID, filter_SSID) != 0) {
194+ filter_BSS = true;
195+ }
196+ } else if (strstr(line, "Supported rates") != NULL) {
197+ char SRate[64] = {0}, *tmp = NULL;
198+ memset(buf, 0, sizeof(buf));
199+ strcpy(SRate, line);
200+ tmp = strtok(SRate, ":");
201+ tmp = strtok(NULL, ":");
202+ strcpy(buf, tmp);
203+ memset(SRate, 0, sizeof(SRate));
204+
205+ tmp = strtok(buf, " \n");
206+ while (tmp != NULL) {
207+ strcat(SRate, tmp);
208+ if (SRate[strlen(SRate) - 1] == '*') {
209+ SRate[strlen(SRate) - 1] = '\0';
210+ }
211+ strcat(SRate, ",");
212+
213+ tmp = strtok(NULL, " \n");
214+ }
215+ SRate[strlen(SRate) - 1] = '\0';
216+ strcpy(scan_array[index].ap_SupportedDataTransferRates, SRate);
217+ } else if (strstr(line, "DTIM") != NULL) {
218+ sscanf(line,"DTIM Period %d", scan_array[index].ap_DTIMPeriod, buf);
219+ } else if (strstr(line, "VHT capabilities") != NULL) {
220+ strcat(scan_array[index].ap_SupportedStandards, ",ac");
221+ strcpy(scan_array[index].ap_OperatingStandards, "ac");
222+ } else if (strstr(line, "HT capabilities") != NULL) {
223+ strcat(scan_array[index].ap_SupportedStandards, ",n");
224+ strcpy(scan_array[index].ap_OperatingStandards, "n");
225+ } else if (strstr(line, "VHT operation") != NULL) {
226+ read = getline(&line, &len, f);
227+ sscanf(line," * channel width: %d", &vht_channel_width);
228+ if(vht_channel_width == 1) {
229+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT80");
230+ } else {
231+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11AC_VHT40");
232+ }
233+ if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
234+ continue;
235+ } else if (strstr(line, "HT operation") != NULL) {
236+ read = getline(&line, &len, f);
237+ sscanf(line," * secondary channel offset: %s", &buf);
238+ if (!strcmp(buf, "above")) {
239+ //40Mhz +
240+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40PLUS", radioIndex%1 ? "A": "G");
241+ }
242+ else if (!strcmp(buf, "below")) {
243+ //40Mhz -
244+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT40MINUS", radioIndex%1 ? "A": "G");
245+ } else {
246+ //20Mhz
247+ snprintf(scan_array[index].ap_OperatingChannelBandwidth, sizeof(scan_array[index].ap_OperatingChannelBandwidth), "11N%s_HT20", radioIndex%1 ? "A": "G");
248+ }
249+ if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
250+ continue;
251+ } else if (strstr(line, "HE capabilities") != NULL) {
252+ strncat(scan_array[index].ap_SupportedStandards, ",ax", strlen(",ax"));
253+ strncpy(scan_array[index].ap_OperatingStandards, "ax", strlen("ax"));
254+ } else if (strstr(line, "HE PHY Capabilities") != NULL) {
255+ if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "2.4GHz", strlen("2.4GHz")) == 0) {
256+ if (strstr(line, "HE40/2.4GHz") != NULL)
257+ strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE40PLUS", strlen("11AXHE40PLUS"));
258+ else
259+ strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE20", strlen("11AXHE20"));
260+
261+ } else if (strncmp(scan_array[index].ap_OperatingFrequencyBand, "5GHz", strlen("5GHz")) == 0) {
262+ strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE80", strlen("11AXHE80")); // AP must always support
263+ read = getline(&line, &len, f);
264+ if (strstr(line, "HE160/5GHz") != NULL)
265+ strncpy(scan_array[index].ap_OperatingChannelBandwidth, "11AXHE160", strlen("11AXHE160"));
266+ }
267+ if (strstr(line, "BSS") != NULL) // prevent to get the next neighbor information
268+ continue;
269+ } else if (strstr(line, "WPA") != NULL) {
270+ strcpy(scan_array[index].ap_SecurityModeEnabled, "WPA");
271+ } else if (strstr(line, "RSN") != NULL) {
272+ strcpy(scan_array[index].ap_SecurityModeEnabled, "RSN");
273+ } else if (strstr(line, "Group cipher") != NULL) {
274+ sscanf(line, " * Group cipher: %s", scan_array[index].ap_EncryptionMode);
275+ if (strncmp(scan_array[index].ap_EncryptionMode, "CCMP", strlen("CCMP")) == 0) {
276+ strcpy(scan_array[index].ap_EncryptionMode, "AES");
277+ }
278+ }
279 }
280
281- status = RETURN_OK;
282+ if (!filter_BSS) {
283+ *output_array_size = index + 1;
284+ } else {
285+ memset(&(scan_array[index]), 0, sizeof(wifi_neighbor_ap2_t));
286+ *output_array_size = index;
287+ }
288+ *neighbor_ap_array = scan_array;
289+ free(line);
290+ pclose(f);
291 WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
292- return status;
293+ return RETURN_OK;
294 }
295
296 //>> Deprecated: used for old RDKB code.
297@@ -7635,7 +7833,38 @@ INT wifi_setApCsaDeauth(INT apIndex, INT mode)
298
299 INT wifi_setApScanFilter(INT apIndex, INT mode, CHAR *essid)
300 {
301- // TODO Implement me!
302+ char file_name[128] = {0};
303+ char buf[128] = {0};
304+ FILE *f = NULL;
305+
306+ WIFI_ENTRY_EXIT_DEBUG("Inside %s:%d\n",__func__, __LINE__);
307+
308+ if (essid == NULL || strlen(essid) == 0 || apIndex == -1) {
309+ for (int index = 0; index < NUMBER_OF_RADIOS; index++) {
310+ snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, index);
311+ f = fopen(file_name, "w");
312+ if (f == NULL)
313+ return RETURN_ERR;
314+ // For mode == 0 is to disable filter, just don't write to the file.
315+ if (mode)
316+ fprintf(f, "%s", essid);
317+
318+ fclose(f);
319+ }
320+ } else { // special case, need to set AP's SSID as filter for each radio.
321+ snprintf(file_name, sizeof(file_name), "%s%d.txt", ESSID_FILE, apIndex);
322+ f = fopen(file_name, "w");
323+ if (f == NULL)
324+ return RETURN_ERR;
325+
326+ // For mode == 0 is to disable filter, just don't write to the file.
327+ if (mode)
328+ fprintf(f, "%s", essid);
329+
330+ fclose(f);
331+ }
332+
333+ WIFI_ENTRY_EXIT_DEBUG("Exiting %s:%d\n",__func__, __LINE__);
334 return RETURN_OK;
335 }
336
337--
3382.18.0
339