1/*
2 * This program is free software; you can redistribute it and/or
3 * modify it under the terms of the GNU General Public License as
4 * published by the Free Software Foundation; either version 2 of
5 * the License, or (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
15 * MA 02111-1307 USA
16 */
17#include <stdio.h>
18#include <string.h>
19#include <bcmnvram.h>
20#include <net/if_arp.h>
21#include <shutils.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <dirent.h>
25#include <sys/ioctl.h>
26#include <sys/sysctl.h>
27#include <errno.h>
28#include <etioctl.h>
29#include <rc.h>
30typedef u_int64_t __u64;
31typedef u_int32_t __u32;
32typedef u_int16_t __u16;
33typedef u_int8_t __u8;
34#include <linux/sockios.h>
35#include <linux/ethtool.h>
36#include <ctype.h>
37#include <wlutils.h>
38#include <shared.h>
39#include <wlscan.h>
40
41#ifdef RTCONFIG_BCM_7114
42#include <bcmutils.h>
43#include <bcmendian.h>
44#include <security_ipc.h>
45#endif
46
47//This define only used for switch 53125
48#define SWITCH_PORT_0_UP	0x0001
49#define SWITCH_PORT_1_UP	0x0002
50#define SWITCH_PORT_2_UP	0x0004
51#define SWITCH_PORT_3_UP	0x0008
52#define SWITCH_PORT_4_UP	0x0010
53
54#define SWITCH_PORT_0_GIGA	0x0002
55#define SWITCH_PORT_1_GIGA	0x0008
56#define SWITCH_PORT_2_GIGA	0x0020
57#define SWITCH_PORT_3_GIGA	0x0080
58#define SWITCH_PORT_4_GIGA	0x0200
59//End
60
61//Defined for switch 5325
62//#define SWITCH_ACCESS_CMD		SIOCGETCROBORD
63#define SWITCH_ACCESS_PAGE		"0x1"
64#define SWITCH_ACCESS_REG_LINKSTATUS	"0x0"
65#define SWITCH_ACCESS_REG_LINKSPEED	"0x4"
66
67/* hardware-dependent */
68#define ETH_WAN_PORT "4"
69#define ETH_LAN1_PORT "3"
70#define ETH_LAN2_PORT "2"
71#define ETH_LAN3_PORT "1"
72#define ETH_LAN4_PORT "0"
73
74/* RT-N53 */
75/* WAN Port=4 */
76#define MASK_PHYPORT 0x0010
77
78#define ETH_WAN_PORT_UP 0x0010
79#define ETH_LAN1_PORT_UP 0x0001
80#define ETH_LAN2_PORT_UP 0x0002
81#define ETH_LAN3_PORT_UP 0x0004
82#define ETH_LAN4_PORT_UP 0x0008
83
84#define ETH_WAN_PORT_GIGA 0x0200
85#define ETH_LAN1_PORT_GIGA 0x0002
86#define ETH_LAN2_PORT_GIGA 0x0008
87#define ETH_LAN3_PORT_GIGA 0x0020
88#define ETH_LAN4_PORT_GIGA 0x0080
89
90#define ETH_PHY_REG_LAN_ADDR "0x1e"
91#define ETH_PHY_REG_LAN_DISCONN_VALUE "0x80a8"
92#define ETH_PHY_REG_LAN_CONN_VALUE "0x80a0"
93//End
94char cmd[32];
95
96#if defined(RTCONFIG_EXT_RTL8365MB) || defined(RTCONFIG_EXT_RTL8370MB)
97extern int ext_rtk_phyState(int v, char* BCMPorts);
98#endif
99
100int
101set40M_Channel_2G(char *channel)
102{
103#ifdef RTCONFIG_BCMWL6
104	char str[8];
105#endif
106
107	if (channel==NULL || !isValidChannel(1, channel))
108		return 0;
109
110#ifdef RTCONFIG_BCMWL6
111	if (atoi(channel) >= 5) sprintf(str, "%su", channel);
112	else sprintf(str, "%sl", channel);
113	nvram_set("wl0_chanspec", str);
114	nvram_set("wl0_bw_cap", "3");
115#else
116	nvram_set("wl0_channel", channel);
117	nvram_set("wl0_nbw_cap", "1");
118	nvram_set("wl0_nctrlsb", "lower");
119#endif
120	nvram_set("wl0_obss_coex", "0");
121	eval("wlconf", "eth1", "down");
122	eval("wlconf", "eth1", "up");
123	eval("wlconf", "eth1", "start");
124	puts("1");
125	return 1;
126}
127
128int
129set40M_Channel_5G(char *channel)
130{
131#ifdef RTCONFIG_BCMWL6
132	char str[8];
133	int ch = 0;
134#endif
135
136	if (channel==NULL || !isValidChannel(0, channel))
137		return 0;
138
139#ifdef RTCONFIG_BCMWL6
140	ch = atoi(channel);
141	sprintf(str, "0");
142	if (ch==40||ch==48||ch==56||ch==64||ch==104||ch==112||ch==120||ch==128||ch==136||ch==153||ch==161)
143		sprintf(str, "%su", channel);
144	else if (ch==36||ch==44||ch==52||ch==60||ch==100||ch==108||ch==116||ch==124||ch==132||ch==149||ch==157)
145		sprintf(str, "%sl", channel);
146	nvram_set("wl1_chanspec", str);
147	nvram_set("wl1_bw_cap", "3");
148#else
149	nvram_set("wl1_channel", channel);
150	nvram_set("wl1_nbw_cap", "1");
151	nvram_set("wl1_nctrlsb", "lower");
152#endif
153	eval("wlconf", "eth2", "down");
154	eval("wlconf", "eth2", "up");
155	eval("wlconf", "eth2", "start");
156	puts("1");
157	return 1;
158}
159
160int
161set80M_Channel_5G(char *channel)
162{
163#ifdef RTCONFIG_BCMWL6
164	char str[8];
165	int ch = 0;
166#endif
167
168	if (channel==NULL || !isValidChannel(0, channel))
169		return 0;
170
171#ifdef RTCONFIG_BCMWL6
172	ch = atoi(channel);
173	sprintf(str, "0");
174	if (ch==36||ch==40||ch==44||ch==48||ch==52||ch==56||ch==60||ch==64||
175		ch==100||ch==104||ch==108||ch==112||ch==149||ch==153||ch==157||ch==161)
176		sprintf(str, "%s/80", channel);
177	nvram_set("wl1_chanspec", str);
178	nvram_set("wl1_bw_cap", "7");
179#else
180	nvram_set("wl1_channel", channel);
181	nvram_set("wl1_nbw_cap", "1");
182	nvram_set("wl1_nctrlsb", "lower");
183#endif
184	eval("wlconf", "eth2", "down");
185	eval("wlconf", "eth2", "up");
186	eval("wlconf", "eth2", "start");
187	puts("1");
188	return 1;
189}
190
191int
192ResetDefault(void)
193{
194#ifndef RTCONFIG_BCMARM
195	eval("mtd-erase","-d","nvram");
196	puts("1");
197#else
198	int ret=0;
199	if (nvram_contains_word("rc_support", "nandflash"))	/* RT-AC56S,U/RT-AC68U/RT-N18U */
200#ifdef RTAC87U
201		ret = mtd_erase("nvram");
202#else
203		ret = eval("mtd-erase2", "nvram");
204#endif
205	else
206#if defined(RTAC1200G) || defined(RTAC1200GP)
207		ret = eval("mtd-erase2", "nvram");
208#else
209		ret = eval("mtd-erase","-d","nvram");
210#endif
211#ifdef RTAC87U
212	if (ret == 0) {
213		return 0;
214	} else {
215		return -1;
216	}
217#else
218	if (ret >= 0) {
219		sleep(3);
220		puts("1");
221	}
222	else
223		puts("0");
224#endif
225#endif
226	return 0;
227}
228
229int
230GetPhyStatus(int verbose)
231{
232	int ports[5];
233#if defined(RTCONFIG_EXT_RTL8365MB) || defined(RTCONFIG_EXT_RTL8370MB)
234	int ext = 0;
235#endif
236	int i, ret, lret=0, model, mask;
237	char out_buf[30];
238
239	model = get_model();
240	switch(model) {
241	case MODEL_RTN14UHP:
242		/* WAN L1 L2 L3 L4 */
243		ports[0]=4; ports[1]=0; ports[2]=1, ports[3]=2; ports[4]=3;
244		break;
245	case MODEL_RTN53:
246	case MODEL_RTN15U:
247	case MODEL_RTN12:
248	case MODEL_RTN12B1:
249	case MODEL_RTN12C1:
250	case MODEL_RTN12D1:
251	case MODEL_RTN12VP:
252	case MODEL_RTN12HP:
253	case MODEL_RTN12HP_B1:
254	case MODEL_APN12HP:
255	case MODEL_RTN10P:
256	case MODEL_RTN10D1:
257	case MODEL_RTN10PV2:
258		/* WAN L1 L2 L3 L4 */
259		ports[0]=4; ports[1]=3; ports[2]=2, ports[3]=1; ports[4]=0;
260		break;
261	case MODEL_RTN16:
262	case MODEL_RTN10U:
263		/* WAN L1 L2 L3 L4 */
264		ports[0]=0; ports[1]=4; ports[2]=3, ports[3]=2; ports[4]=1;
265		break;
266	case MODEL_RTAC88U:
267	case MODEL_RTAC3100:
268		/* WAN L1 L2 L3 L4 */
269		ports[0]=4; ports[1]=3; ports[2]=2; ports[3]=1; ports[4]=0;
270#if defined(RTCONFIG_EXT_RTL8365MB) || defined(RTCONFIG_EXT_RTL8370MB)
271		ext = 1;
272#endif
273		break;
274	case MODEL_RTAC56S:
275	case MODEL_RTAC56U:
276		/* WAN L1 L2 L3 L4 */
277		ports[0]=4; ports[1]=0; ports[2]=1; ports[3]=2; ports[4]=3;
278		break;
279
280	case MODEL_RTAC87U:
281		/* WAN L1 L2 L3 L4 */
282		ports[0]=0; ports[1]=5; ports[2]=3; ports[3]=2; ports[4]=1;
283		break;
284
285	case MODEL_DSLAC68U:
286	case MODEL_RPAC68U:
287	case MODEL_RTAC68U:
288	case MODEL_RTAC3200:
289	case MODEL_RTN18U:
290	case MODEL_RTAC53U:
291	case MODEL_RTN66U:
292	case MODEL_RTAC66U:
293	case MODEL_RTAC1200G:
294	case MODEL_RTAC1200GP:
295		/* WAN L1 L2 L3 L4 */
296		ports[0]=0; ports[1]=1; ports[2]=2; ports[3]=3; ports[4]=4;
297		break;
298	case MODEL_RTAC5300:
299		/* WAN L1 L2 L3 L4 */
300		ports[0]=0; ports[1]=1; ports[2]=2; ports[3]=3; ports[4]=4;
301#ifdef RTCONFIG_EXT_RTL8365MB
302		ext = 1;
303#endif
304		break;
305	case MODEL_RTAC5300R:
306		/* WAN L8 L4 TRUNK2 TRUNK1 */
307		ports[0]=0; ports[1]=4; ports[2]=3; ports[3]=2; ports[4]=1;
308#if defined(RTCONFIG_EXT_RTL8365MB) || defined(RTCONFIG_EXT_RTL8370MB)
309		ext = 1;
310#endif
311		break;
312	}
313
314#if defined(RTCONFIG_EXT_RTL8365MB) || defined(RTCONFIG_EXT_RTL8370MB)
315	char PStatus[5]="XXXXX";
316#endif
317
318	memset(out_buf, 0, 30);
319	for (i=0; i<5; i++) {
320		mask = 0;
321		mask |= 0x0001<<ports[i];
322		if (get_phy_status(mask)==0) {/*Disconnect*/
323			if (i==0)
324				sprintf(out_buf, "W0=X;");
325			else {
326#ifndef RTAC5300R
327				sprintf(out_buf, "%sL%d=X;", out_buf, i);
328#endif
329			}
330		}
331		else { /*Connect, keep check speed*/
332			mask = 0;
333			mask |= (0x0003<<(ports[i]*2));
334			ret=get_phy_speed(mask);
335			ret>>=(ports[i]*2);
336			if (i==0)
337				sprintf(out_buf, "W0=%s;", (ret & 2)? "G":"M");
338			else {
339#ifndef RTAC5300R
340				lret = 1;
341				sprintf(out_buf, "%sL%d=%s;", out_buf, i, (ret & 2)? "G":"M");
342#else
343				PStatus[i] = (ret & 2)? 'G':'M';
344				if (i < 3) lret = 1;
345#endif
346			}
347		}
348	}
349
350#ifdef RTCONFIG_QTN
351	if (model == MODEL_RTAC87U) {
352		ports[1] = GetPhyStatus_qtn();
353		if (ports[1] == 1000) {
354			out_buf[8] = 'G';
355		} else if (ports[1] == 100) {
356			out_buf[8] = 'M';
357		} else if (ports[1] == 10) {
358			out_buf[8] = 'M';
359		} else {
360			out_buf[8] = 'X';
361		}
362	}
363#endif
364	if (verbose)
365#if defined(RTCONFIG_EXT_RTL8365MB) || defined(RTCONFIG_EXT_RTL8370MB)
366		printf("%s", out_buf);
367#else
368		puts(out_buf);
369#endif
370
371#if defined(RTCONFIG_EXT_RTL8365MB) || defined(RTCONFIG_EXT_RTL8370MB)
372	if (ext)
373		lret |= ext_rtk_phyState(verbose, PStatus);
374#endif
375	return lret;
376}
377
378#ifdef RTCONFIG_LAN4WAN_LED
379int LanWanLedCtrl(void)
380{
381	int ports[5];
382	int i, ret, model, mask;
383	char out_buf[30];
384
385	model = get_model();
386	switch(model) {
387	case MODEL_RTN14UHP:
388		/* WAN L1 L2 L3 L4 */
389		ports[0]=4; ports[1]=0; ports[2]=1, ports[3]=2; ports[4]=3;
390		break;
391	}
392
393	memset(out_buf, 0, 30);
394	for (i=0; i<5; i++) {
395		mask = 0;
396		mask |= 0x0001<<ports[i];
397		if (get_phy_status(mask)==0) {/*Disconnect*/
398			if (i==0) {
399				led_control(LED_WAN, LED_OFF);
400			} else {
401				if (i == 1) led_control(LED_LAN1, LED_OFF);
402				if (i == 2) led_control(LED_LAN2, LED_OFF);
403				if (i == 3) led_control(LED_LAN3, LED_OFF);
404				if (i == 4) led_control(LED_LAN4, LED_OFF);
405			}
406		}
407		else { /*Connect, keep check speed*/
408			mask = 0;
409			mask |= (0x0003<<(ports[i]*2));
410			ret=get_phy_speed(mask);
411			ret>>=(ports[i]*2);
412			if (i==0) {
413				led_control(LED_WAN, LED_ON);
414			} else {
415				if (i == 1) led_control(LED_LAN1, LED_ON);
416				if (i == 2) led_control(LED_LAN2, LED_ON);
417				if (i == 3) led_control(LED_LAN3, LED_ON);
418				if (i == 4) led_control(LED_LAN4, LED_ON);
419			}
420		}
421	}
422	return 1;
423}
424#endif	/* LAN4WAN_LED*/
425
426int
427setAllLedOn(void)
428{
429	int model;
430
431	led_control(LED_POWER, LED_ON);
432
433	// generate nvram nvram according to system setting
434	model = get_model();
435	switch(model) {
436		case MODEL_RTN16:
437		case MODEL_RTN66U:
438		{
439			/* LAN, WAN Led On */
440			eval("et", "robowr", "0", "0x18", "0x01ff");
441			eval("et", "robowr", "0", "0x1a", "0x01e0");
442			eval("radio", "on"); /* wireless */
443			led_control(LED_USB, LED_ON);
444			break;
445		}
446		case MODEL_RTN18U:
447		{
448			led_control(LED_USB, LED_ON);
449			led_control(LED_USB3, LED_ON);
450			led_control(LED_POWER, LED_ON);
451			led_control(LED_WAN, LED_ON);
452			led_control(LED_LAN, LED_ON);
453			eval("wl", "-i", "eth1", "ledbh", "10", "7");
454			break;
455		}
456		case MODEL_DSLAC68U:
457		{
458			led_control(LED_USB3, LED_ON);
459			led_control(LED_WAN, LED_ON);
460			eval("et", "robowr", "0", "0x18", "0x01ff");	// lan/wan ethernet/giga led
461			eval("et", "robowr", "0", "0x1a", "0x01e0");
462			eval("wl", "ledbh", "10", "1");			// wl 2.4G
463			eval("wl", "-i", "eth2", "ledbh", "10", "1");	// wl 5G
464			/* 4360's fake 5g led */
465			led_control(LED_5G, LED_ON);
466			eval("adslate", "led", "on");
467			break;
468		}
469		case MODEL_RTAC87U:
470		{
471			eval("et", "robowr", "0", "0x18", "0x01ff");	// lan/wan ethernet/giga led
472			eval("et", "robowr", "0", "0x1a", "0x01e0");
473			eval("wl", "ledbh", "10", "1");			// wl 2.4G
474			led_control(LED_WPS, LED_ON);
475			led_control(LED_WAN, LED_ON);
476#ifdef RTCONFIG_QTN
477			setAllLedOn_qtn();
478#endif
479			break;
480		}
481		case MODEL_RPAC68U:
482			eval("et", "robowr", "0", "0x18", "0x01ff");	// lan/wan ethernet/giga led
483			eval("et", "robowr", "0", "0x1a", "0x01e0");
484
485			eval("wl", "ledbh", "0", "1");			// wl 2.4G
486			eval("wl", "ledbh", "9", "1");			// wl 2.4G
487			eval("wl", "ledbh", "10", "1");			// wl 2.4G
488			eval("wl", "-i", "eth2", "ledbh", "0", "1");	// wl 5G
489			eval("wl", "-i", "eth2", "ledbh", "9", "1");	// wl 5G
490			eval("wl", "-i", "eth2", "ledbh", "10", "1");	// wl 5G
491			break;
492		case MODEL_RTAC68U:
493		case MODEL_RTAC3200:
494		case MODEL_RTAC5300:
495		case MODEL_RTAC5300R:
496		case MODEL_RTAC88U:
497		case MODEL_RTAC3100:
498		{
499#if defined(RTAC68U) || defined(RTAC88U) || defined(RTAC3100) || defined(RTAC5300) || defined(RTAC5300R)
500			led_control(LED_USB, LED_ON);
501			led_control(LED_USB3, LED_ON);
502#endif
503#ifdef RTCONFIG_TURBO
504			led_control(LED_TURBO, LED_ON);
505#endif
506			eval("et", "-i", "eth0", "robowr", "0", "0x18", "0x01ff");	// lan/wan ethernet/giga led
507			eval("et", "-i", "eth0", "robowr", "0", "0x1a", "0x01e0");
508#if defined(RTAC3200)
509			eval("wl", "ledbh", "10", "1");			// wl 5G low
510			eval("wl", "-i", "eth2", "ledbh", "10", "1");	// wl 2.4G
511			eval("wl", "-i", "eth3", "ledbh", "10", "1");	// wl 5G high
512#elif defined(RTAC5300) || defined(RTAC5300R)
513			eval("wl", "ledbh", "9", "1");			// wl 5G low
514			eval("wl", "-i", "eth2", "ledbh", "9", "1");	// wl 2.4G
515			eval("wl", "-i", "eth3", "ledbh", "9", "1");	// wl 5G high
516#elif defined(RTAC88U) || defined(RTAC3100)
517			eval("wl", "ledbh", "9", "1");			// wl 2.4G
518			eval("wl", "-i", "eth2", "ledbh", "9", "1");	// wl 5G
519#else
520			eval("wl", "ledbh", "10", "1");			// wl 2.4G
521			eval("wl", "-i", "eth2", "ledbh", "10", "1");	// wl 5G
522#endif
523
524#if defined(RTAC3200)
525			led_control(LED_WPS, LED_ON);
526			led_control(LED_WAN, LED_ON);
527#elif defined (RTAC88U) || defined (RTAC3100) || defined (RTAC5300) || defined(RTAC5300R)
528			led_control(LED_WPS, LED_ON);
529			led_control(LED_WAN, LED_ON);
530			led_control(LED_LAN, LED_ON);
531#endif
532#ifdef RTAC68U
533			 /* 4360's fake 5g led */
534			led_control(LED_5G, LED_ON);
535			if (!strcmp(get_productid(), "RT-AC66U V2"))
536			led_control(LED_WAN, LED_ON);
537#endif
538			break;
539		}
540		case MODEL_RTAC56S:
541		case MODEL_RTAC56U:
542		{
543#ifdef RTCONFIG_LED_ALL
544			led_control(LED_ALL, LED_ON);
545#endif
546			led_control(LED_USB, LED_ON);
547			led_control(LED_USB3, LED_ON);
548			led_control(LED_WAN, LED_ON);
549			led_control(LED_LAN, LED_ON);
550			eval("et", "robowr", "0", "0x18", "0x01ff");	// lan/wan ethernet/giga led
551			eval("et", "robowr", "0", "0x1a", "0x01e0");
552			eval("wl", "ledbh", "3", "1");			// wl 2.4G
553			eval("wl", "-i", "eth2","ledbh", "10", "1");
554			/* 4352's fake 5g led */
555			led_control(LED_5G, LED_ON);
556			break;
557		}
558		case MODEL_RTAC66U:
559		{
560			/* LAN, WAN Led On */
561			eval("et", "robowr", "0", "0x18", "0x01ff");
562			eval("et", "robowr", "0", "0x1a", "0x01e0");
563			eval("radio", "on"); /* 2G led */
564			led_control(LED_5G, LED_ON);
565			led_control(LED_USB, LED_ON);
566			break;
567		}
568		case MODEL_RTN14UHP:
569		{
570			led_control(LED_POWER, LED_ON);
571			/* convert from shared, boardapi.c */
572			led_control(LED_WPS, LED_ON);
573			led_control(LED_USB, LED_ON);
574			eval("radio", "on"); /* 2G led */
575			if (nvram_contains_word("rc_support", "lanwan_led2")) {
576				led_control(LED_WAN, LED_ON);
577#ifdef RTCONFIG_LAN4WAN_LED
578				led_control(LED_LAN1, LED_ON);
579				led_control(LED_LAN2, LED_ON);
580				led_control(LED_LAN3, LED_ON);
581				led_control(LED_LAN4, LED_ON);
582#endif
583			} else {
584				eval("et", "robowr", "00", "0x12", "0xfd55");
585			}
586			break;
587		}
588		case MODEL_APN12HP:
589		{
590			led_control(LED_POWER, LED_ON);
591			/* convert from shared, boardapi.c */
592			nvram_set_int("led_2g_gpio", 4099);
593			led_control(LED_2G, LED_ON);
594			led_control(LED_WAN, LED_ON);
595			break;
596		}
597		case MODEL_RTN10P:
598		case MODEL_RTN10D1:
599		case MODEL_RTN10PV2:
600		{
601			led_control(LED_WPS, LED_ON);
602		}
603		case MODEL_RTN12B1:
604		case MODEL_RTN12C1:
605		case MODEL_RTN12D1:
606		case MODEL_RTN12VP:
607		case MODEL_RTN12HP:
608		case MODEL_RTN12HP_B1:
609		{
610			eval("et", "robowr", "00", "0x12", "0xfd55");
611			eval("radio", "on"); /* wireless */
612			break;
613		}
614		case MODEL_RTN10U:
615		{
616			led_control(LED_WPS, LED_ON);
617			led_control(LED_USB, LED_ON);
618			eval("et", "robowr", "00", "0x12", "0xfd55");
619			eval("radio", "on"); /* wireless */
620			break;
621		}
622		case MODEL_RTN15U:
623		{
624			//LAN, WAN Led On
625			led_control(LED_POWER, LED_ON);
626			led_control(LED_LAN, LED_ON);
627			led_control(LED_WAN, LED_ON);
628			led_control(LED_USB, LED_ON);
629			eval("radio", "on"); /* wireless */
630			break;
631		}
632		case MODEL_RTN53:
633		{
634			//LAN, WAN Led On
635			led_control(LED_LAN, LED_ON);
636			led_control(LED_WAN, LED_ON);
637			led_control(LED_2G, LED_ON);
638			led_control(LED_5G, LED_ON);
639			break;
640		}
641		case MODEL_RTAC53U:
642		{
643			led_control(LED_POWER, LED_ON);
644			led_control(LED_LAN, LED_ON);
645			led_control(LED_WAN, LED_ON);
646			led_control(LED_USB, LED_ON);
647			eval("wl", "-i", "eth1", "ledbh", "3", "1");	// wl 2.4G
648			eval("wl", "-i", "eth2", "ledbh", "9", "1");	// wl 5G
649			break;
650		}
651		case MODEL_RTAC1200G:
652		case MODEL_RTAC1200GP:
653		{
654			eval("et", "robowr", "0", "0x18", "0x01ff");	// lan/wan ethernet/giga led
655			eval("et", "robowr", "0", "0x1a", "0x01e0");
656			eval("wl", "-i", "eth1", "ledbh", "3", "1");	// wl 2.4G
657			eval("wl", "-i", "eth2", "ledbh", "11", "1");	// wl 5G
658			led_control(LED_WPS, LED_ON);
659			led_control(LED_USB, LED_ON);
660			break;
661		}
662	}
663
664	wan_red_led_control(LED_ON);
665
666	puts("1");
667	return 0;
668}
669
670int
671setWlOffLed(void)
672{
673	int model;
674	int wlon_unit = nvram_get_int("wlc_band");
675#ifdef PXYSTA_DUALBAND
676	int wlon_unit_ex = !nvram_match("dpsta_ifnames", "") ? nvram_get_int("wlc_band_ex") : -1 ;
677#else
678	int wlon_unit_ex = -1;
679#endif
680
681	model = get_model();
682	switch(model) {
683		case MODEL_RTAC56S:
684		case MODEL_RTAC56U:
685		{
686			if (wlon_unit != 0) {
687				eval("wl", "ledbh", "3", "0");			// wl 2.4G
688			} else {
689				eval("wl", "-i", "eth2", "ledbh", "10", "0");	// wl 5G
690				led_control(LED_5G, LED_OFF);
691			}
692			break;
693		}
694		case MODEL_RPAC68U:
695		case MODEL_RTAC68U:
696			if (wlon_unit != 0) {
697				eval("wl", "ledbh", "10", "0");			// wl 2.4G
698#ifdef RTCONFIG_LEDARRAY
699				eval("wl", "ledbh", "0", "0");			// wl 2.4G
700				eval("wl", "ledbh", "9", "0");			// wl 2.4G
701#endif
702			} else {
703				eval("wl", "-i", "eth2", "ledbh", "10", "0");	// wl 5G
704#ifdef RTCONFIG_LEDARRAY
705				eval("wl", "-i", "eth2", "ledbh", "0", "0");	// wl 5G
706				eval("wl", "-i", "eth2", "ledbh", "9", "0");	// wl 5G
707#endif
708#ifndef RTCONFIG_LEDARRAY
709				led_control(LED_5G, LED_OFF);
710#endif
711			}
712			break;
713
714		case MODEL_RTAC88U:
715		case MODEL_RTAC3100:
716			if (wlon_unit != 0) {
717				eval("wl", "ledbh", "9", "0");			// wl 2.4G
718			} else {
719				eval("wl", "-i", "eth2", "ledbh", "9", "0");	// wl 5G
720				led_control(LED_5G, LED_OFF);
721			}
722			break;
723
724		case MODEL_RTAC5300:
725		case MODEL_RTAC5300R:
726		{
727			if (wlon_unit != 0 && wlon_unit_ex != 0)
728				eval("wl", "-i", "eth1", "ledbh", "9", "0");	// wl 2.4G
729			if (wlon_unit != 1 && wlon_unit_ex != 1)
730				eval("wl", "-i", "eth2", "ledbh", "9", "0");	// wl 5G low
731			if (wlon_unit != 2 && wlon_unit_ex != 2)
732				eval("wl", "-i", "eth3", "ledbh", "9", "0");	// wl 5G high
733			break;
734		}
735		case MODEL_RTAC3200:
736		{
737			if (wlon_unit != 0 && wlon_unit_ex != 0)
738				eval("wl", "-i", "eth2", "ledbh", "10", "0");	// wl 2.4G
739			if (wlon_unit != 1 && wlon_unit_ex != 1)
740				eval("wl", "ledbh", "10", "0");			// wl 5G low
741			if (wlon_unit != 2 && wlon_unit_ex != 2)
742				eval("wl", "-i", "eth3", "ledbh", "10", "0");	// wl 5G high
743			break;
744		}
745		case MODEL_RTAC53U:
746		{
747			if (wlon_unit != 0) {
748				eval("wl", "-i", "eth1", "ledbh", "3", "0");	// wl 2.4G
749			} else {
750				eval("wl", "-i", "eth2", "ledbh", "9", "0");	// wl 5G
751			}
752			break;
753		}
754		case MODEL_RTAC1200G:
755		case MODEL_RTAC1200GP:
756		{
757			eval("wl", "ledbh", "10", "0"); // wl 2.4G
758			led_control(LED_5G, LED_OFF);
759			break;
760		}
761	}
762
763	return 0;
764}
765
766int
767setAllLedOff(void)
768{
769	int model;
770
771	led_control(LED_POWER, LED_OFF);
772
773	// generate nvram nvram according to system setting
774	model = get_model();
775	switch(model) {
776		case MODEL_RTN16:
777		case MODEL_RTN66U:
778		{
779			/* LAN, WAN Led Off */
780			eval("et", "robowr", "0", "0x18", "0x01e0");
781			eval("et", "robowr", "0", "0x1a", "0x01e0");
782			eval("radio", "off"); /* wireless */
783			led_control(LED_USB, LED_OFF);
784			break;
785		}
786		case MODEL_RTAC56S:
787		case MODEL_RTAC56U:
788		{
789#ifdef RTCONFIG_LED_ALL
790			led_control(LED_ALL, LED_OFF);
791#endif
792			eval("et", "robowr", "0", "0x18", "0x01e0");	// lan/wan ethernet/giga led
793			eval("et", "robowr", "0", "0x1a", "0x01e0");
794			eval("wl", "ledbh", "3", "0");			// wl 2.4G
795			eval("wl", "-i", "eth2", "ledbh", "10", "0");
796			/* 4352's fake 5g led */
797			led_control(LED_5G, LED_OFF);
798			break;
799		}
800		case MODEL_RTN18U:
801		{
802			led_control(LED_USB, LED_OFF);
803			led_control(LED_USB3, LED_OFF);
804			led_control(LED_POWER, LED_OFF);
805			led_control(LED_WAN, LED_OFF);
806			led_control(LED_LAN, LED_OFF);
807			led_control(LED_2G, LED_OFF);
808			eval("wl", "-i", "eth1", "ledbh", "10", "0");
809			break;
810		}
811		case MODEL_DSLAC68U:
812		{
813			char *ledcmd_argv[] = {"adslate", "led", "off", NULL};
814			led_control(LED_USB3, LED_OFF);
815			led_control(LED_WAN, LED_OFF);
816			eval("et", "robowr", "0", "0x18", "0x01e0");	// lan/wan ethernet/giga led
817			eval("et", "robowr", "0", "0x1a", "0x01e0");
818			eval("wl", "ledbh", "10", "0");			// wl 2.4G
819			eval("wl", "-i", "eth2", "ledbh", "10", "0");
820			/* 4360's fake 5g led */
821			led_control(LED_5G, LED_OFF);
822			_eval(ledcmd_argv, NULL, 5, NULL);
823			break;
824		}
825		case MODEL_RTAC87U:
826		{
827			eval("et", "robowr", "0", "0x18", "0x01e0");	// lan/wan ethernet/giga led
828			eval("et", "robowr", "0", "0x1a", "0x01e0");
829			eval("wl", "ledbh", "10", "0");			// wl 2.4G
830			led_control(LED_WPS, LED_OFF);
831			led_control(LED_WAN, LED_OFF);
832#ifdef RTCONFIG_QTN
833			setAllLedOff_qtn();
834#endif
835			break;
836		}
837		case MODEL_RPAC68U:
838			eval("et", "robowr", "0", "0x18", "0x01e0");	// lan/wan ethernet/giga led
839			eval("et", "robowr", "0", "0x1a", "0x01e0");
840
841			eval("wl", "ledbh", "10", "0");			// wl 2.4G
842			eval("wl", "ledbh", "0", "0");			// wl 2.4G
843			eval("wl", "ledbh", "9", "0");			// wl 2.4G
844			eval("wl", "-i", "eth2", "ledbh", "10", "0");	// wl 5G
845			eval("wl", "-i", "eth2", "ledbh", "0", "0");	// wl 5G
846			eval("wl", "-i", "eth2", "ledbh", "9", "0");	// wl 5G
847			break;
848		case MODEL_RTAC68U:
849		case MODEL_RTAC3200:
850		case MODEL_RTAC5300:
851		case MODEL_RTAC5300R:
852		case MODEL_RTAC88U:
853		case MODEL_RTAC3100:
854		{
855#if defined(RTAC68U) || defined(RTAC88U) || defined(RTAC3100) || defined(RTAC5300) || defined(RTAC5300R)
856			led_control(LED_USB, LED_OFF);
857			led_control(LED_USB3, LED_OFF);
858#endif
859#ifdef RTCONFIG_TURBO
860			led_control(LED_TURBO, LED_OFF);
861#endif
862			eval("et", "-i", "eth0", "robowr", "0", "0x18", "0x01e0");	// lan/wan ethernet/giga led
863			eval("et", "-i", "eth0", "robowr", "0", "0x1a", "0x01e0");
864#if defined(RTAC3200)
865			eval("wl", "ledbh", "10", "0");			// wl 5G low
866			eval("wl", "-i", "eth2", "ledbh", "10", "0");	// wl 2.4G
867			eval("wl", "-i", "eth3", "ledbh", "10", "0");	// wl 5G high
868#elif defined (RTAC5300) || defined(RTAC5300R)
869			eval("wl", "ledbh", "9", "0");			// wl 5G low
870			eval("wl", "-i", "eth2", "ledbh", "9", "0");	// wl 2.4G
871			eval("wl", "-i", "eth3", "ledbh", "9", "0");	// wl 5G high
872#elif defined (RTAC88U) || defined (RTAC3100)
873			eval("wl", "ledbh", "9", "0");			// wl 2.4G
874			eval("wl", "-i", "eth2", "ledbh", "9", "0");	// wl 5G
875#else
876			eval("wl", "ledbh", "10", "0");			// wl 2.4G
877			eval("wl", "-i", "eth2", "ledbh", "10", "0");	// wl 5G
878#endif
879
880#if defined(RTAC3200)
881			led_control(LED_WPS, LED_OFF);
882			led_control(LED_WAN, LED_OFF);
883#elif defined (RTAC88U) || defined (RTAC3100) || defined (RTAC5300) || defined(RTAC5300R)
884			led_control(LED_WPS, LED_OFF);
885			led_control(LED_WAN, LED_OFF);
886			led_control(LED_LAN, LED_OFF);
887#endif
888#ifdef RTAC68U
889			/* 4360's fake 5g led */
890			led_control(LED_5G, LED_OFF);
891			if (!strcmp(get_productid(), "RT-AC66U V2"))
892			led_control(LED_WAN, LED_OFF);
893#endif
894#ifdef RTCONFIG_FAKE_ETLAN_LED
895			led_control(LED_LAN, LED_OFF);
896#endif
897			break;
898		}
899		case MODEL_RTAC66U:
900		{
901			/* LAN, WAN Led Off */
902			eval("et", "robowr", "0", "0x18", "0x01e0");
903			eval("et", "robowr", "0", "0x1a", "0x01e0");
904			eval("radio", "off"); /* 2G led*/
905			led_control(LED_5G, LED_OFF);
906			led_control(LED_USB, LED_OFF);
907			break;
908		}
909		case MODEL_RTN14UHP:
910		{
911			led_control(LED_POWER, LED_OFF);
912			/* convert from shared, boardapi.c */
913			led_control(LED_WPS, LED_OFF);
914			led_control(LED_USB, LED_OFF);
915			eval("radio", "off"); /* 2G led */
916			if (nvram_contains_word("rc_support", "lanwan_led2")) {
917				led_control(LED_WAN, LED_OFF);
918#ifdef RTCONFIG_LAN4WAN_LED
919				led_control(LED_LAN1, LED_OFF);
920				led_control(LED_LAN2, LED_OFF);
921				led_control(LED_LAN3, LED_OFF);
922				led_control(LED_LAN4, LED_OFF);
923#endif
924			} else {
925				eval("et", "robowr", "00", "0x12", "0xf800");
926			}
927			break;
928		}
929		case MODEL_APN12HP:
930		{
931			led_control(LED_POWER, LED_OFF);
932			/* convert from shared, boardapi.c */
933			nvram_set_int("led_2g_gpio", 4099);
934			led_control(LED_2G, LED_OFF);
935			led_control(LED_WAN, LED_OFF);
936			break;
937		}
938		case MODEL_RTN10P:
939		case MODEL_RTN10D1:
940		case MODEL_RTN10PV2:
941		{
942			led_control(LED_WPS, LED_OFF);
943		}
944		case MODEL_RTN12B1:
945		case MODEL_RTN12C1:
946		case MODEL_RTN12D1:
947		case MODEL_RTN12VP:
948		case MODEL_RTN12HP:
949		case MODEL_RTN12HP_B1:
950		{
951			eval("et", "robowr", "00", "0x12", "0xf800");
952			eval("radio", "off"); /* wireless */
953			break;
954		}
955		case MODEL_RTN10U:
956		{
957			led_control(LED_WPS, LED_OFF);
958			led_control(LED_USB, LED_OFF);
959			eval("et", "robowr", "00", "0x12", "0xf800");
960			eval("radio", "off"); /* wireless */
961			break;
962		}
963		case MODEL_RTN15U:
964		{
965			//LAN, WAN Led Off
966			led_control(LED_POWER, LED_OFF);
967			led_control(LED_LAN, LED_OFF);
968			led_control(LED_WAN, LED_OFF);
969			led_control(LED_USB, LED_OFF);
970			eval("radio", "off"); /* wireless */
971			break;
972		}
973		case MODEL_RTN53:
974		{
975			//LAN, WAN Led Off
976			led_control(LED_LAN, LED_OFF);
977			led_control(LED_WAN, LED_OFF);
978			led_control(LED_2G, LED_OFF);
979			led_control(LED_5G, LED_OFF);
980			break;
981		}
982		case MODEL_RTAC53U:
983		{
984			led_control(LED_POWER, LED_OFF);
985			led_control(LED_LAN, LED_OFF);
986			led_control(LED_WAN, LED_OFF);
987			led_control(LED_USB, LED_OFF);
988			eval("wl", "-i", "eth1", "ledbh", "3", "0");	// wl 2.4G
989			eval("wl", "-i", "eth2", "ledbh", "9", "0");	// wl 5G
990			break;
991		}
992		case MODEL_RTAC1200G:
993		case MODEL_RTAC1200GP:
994		{
995			eval("et", "robowr", "0", "0x18", "0x01e0");	// lan/wan ethernet/giga led
996			eval("et", "robowr", "0", "0x1a", "0x01e0");
997			eval("wl", "-i", "eth1", "ledbh", "3", "0");	// wl 2.4G
998			eval("wl", "-i", "eth2", "ledbh", "11", "0");	// wl 5G
999			led_control(LED_WPS, LED_OFF);
1000			led_control(LED_USB, LED_OFF);
1001			break;
1002		}
1003	}
1004
1005	wan_red_led_control(LED_OFF);
1006
1007	puts("1");
1008	return 0;
1009}
1010
1011int
1012setATEModeLedOn(void) {
1013	int model;
1014
1015	led_control(LED_POWER, LED_ON);
1016	model = get_model();
1017
1018	switch(model) {
1019		case MODEL_RTN16:
1020		case MODEL_RTN66U:
1021		{
1022			/* LAN, WAN Led On */
1023			eval("et", "robowr", "0", "0x18", "0x01ff");
1024			eval("et", "robowr", "0", "0x1a", "0x01e0");
1025			led_control(LED_USB, LED_ON);
1026			break;
1027		}
1028		case MODEL_RTN18U:
1029		{
1030			led_control(LED_USB, LED_ON);
1031			led_control(LED_POWER, LED_ON);
1032			eval("et", "robowr", "0", "0x18", "0x01ff");	// lan/wan ethernet/giga led
1033			eval("et", "robowr", "0", "0x1a", "0x01e0");
1034			break;
1035		}
1036		case MODEL_DSLAC68U:
1037		{
1038			led_control(LED_USB3, LED_ON);
1039			led_control(LED_WAN, LED_ON);
1040			eval("et", "robowr", "0", "0x18", "0x01ff");	// lan/wan ethernet/giga led
1041			eval("et", "robowr", "0", "0x1a", "0x01e0");
1042			eval("adslate", "led", "on");
1043			break;
1044		}
1045		case MODEL_RTAC87U:
1046		{
1047			eval("et", "robowr", "0", "0x18", "0x01ff");	// lan/wan ethernet/giga led
1048			eval("et", "robowr", "0", "0x1a", "0x01e0");
1049			led_control(LED_WPS, LED_ON);
1050#ifdef RTCONFIG_QTN
1051			setAllLedOn_qtn();
1052#endif
1053			break;
1054		}
1055		case MODEL_RTAC68U:
1056		case MODEL_RTAC3200:
1057		{
1058			led_control(LED_WPS, LED_ON);
1059			led_control(LED_USB, LED_ON);
1060			led_control(LED_USB3, LED_ON);
1061#ifdef RTCONFIG_TURBO
1062			led_control(LED_TURBO, LED_ON);
1063#endif
1064			eval("et", "robowr", "0", "0x18", "0x01ff");	// lan/wan ethernet/giga led
1065			eval("et", "robowr", "0", "0x1a", "0x01e0");
1066			break;
1067		}
1068		//case MODEL_RPAC68U:
1069		case MODEL_RTAC88U:
1070		case MODEL_RTAC3100:
1071		case MODEL_RTAC5300:
1072		case MODEL_RTAC5300R:
1073		{
1074			led_control(LED_WPS, LED_ON);
1075			led_control(LED_WAN, LED_ON);
1076			led_control(LED_LAN, LED_ON);
1077			led_control(LED_USB, LED_ON);
1078			led_control(LED_USB3, LED_ON);
1079
1080			eval("et", "-i", "eth0", "robowr", "0", "0x18", "0x01ff");	// lan/wan ethernet/giga led
1081			eval("et", "-i", "eth0", "robowr", "0", "0x1a", "0x01e0");
1082#if defined(RTAC5300) || defined(RTAC5300R)
1083			eval("wl", "ledbh", "9", "1");			// wl 5G low
1084			eval("wl", "-i", "eth2", "ledbh", "9", "1");	// wl 2.4G
1085			eval("wl", "-i", "eth3", "ledbh", "9", "1");	// wl 5G high
1086#elif defined(RTAC88U) || defined(RTAC3100)
1087			eval("wl", "ledbh", "9", "1");			// wl 2.4G
1088			eval("wl", "-i", "eth2", "ledbh", "9", "1");	// wl 5G
1089#endif
1090			break;
1091		}
1092		case MODEL_RTAC56S:
1093		case MODEL_RTAC56U:
1094		{
1095#ifdef RTCONFIG_LED_ALL
1096			led_control(LED_ALL, LED_ON);
1097#endif
1098			led_control(LED_USB, LED_ON);
1099			led_control(LED_USB3, LED_ON);
1100			led_control(LED_WAN, LED_ON);
1101			led_control(LED_LAN, LED_ON);
1102			eval("et", "robowr", "0", "0x18", "0x01ff");	// lan/wan ethernet/giga led
1103			eval("et", "robowr", "0", "0x1a", "0x01e0");
1104			break;
1105		}
1106		case MODEL_RTAC66U:
1107		{
1108			/* LAN, WAN Led On */
1109			eval("et", "robowr", "0", "0x18", "0x01ff");
1110			eval("et", "robowr", "0", "0x1a", "0x01e0");
1111			led_control(LED_USB, LED_ON);
1112			break;
1113		}
1114		case MODEL_RTN10P:
1115		case MODEL_RTN10D1:
1116		case MODEL_RTN10PV2:
1117		{
1118			led_control(LED_WPS, LED_ON);
1119			break;
1120		}
1121		case MODEL_APN12HP:
1122		{
1123			led_control(LED_POWER, LED_ON);
1124			/* convert from shared, boardapi.c */
1125			led_control(LED_WAN, LED_ON);
1126			break;
1127		}
1128		case MODEL_RTN12B1:
1129		case MODEL_RTN12C1:
1130		case MODEL_RTN12D1:
1131		case MODEL_RTN12VP:
1132		case MODEL_RTN12HP:
1133		case MODEL_RTN12HP_B1:
1134		{
1135			eval("et", "robowr", "00", "0x12", "0xfd55");
1136			break;
1137		}
1138		case MODEL_RTN10U:
1139		{
1140			led_control(LED_WPS, LED_ON);
1141			led_control(LED_USB, LED_ON);
1142			eval("et", "robowr", "00", "0x12", "0xfd55");
1143			break;
1144		}
1145		case MODEL_RTN53:
1146		{
1147			/* LAN, WAN Led On */
1148			led_control(LED_LAN, LED_ON);
1149			led_control(LED_WAN, LED_ON);
1150			break;
1151		}
1152		case MODEL_RTAC53U:
1153		{
1154			led_control(LED_POWER, LED_ON);
1155			led_control(LED_LAN, LED_ON);
1156			led_control(LED_WAN, LED_ON);
1157			led_control(LED_USB, LED_ON);
1158			break;
1159		}
1160		case MODEL_RTAC1200G:
1161		case MODEL_RTAC1200GP:
1162		{
1163			eval("et", "robowr", "0", "0x18", "0x01ff");	// lan/wan ethernet/giga led
1164			eval("et", "robowr", "0", "0x1a", "0x01e0");
1165			led_control(LED_WPS, LED_ON);
1166			led_control(LED_USB, LED_ON);
1167			break;
1168		}
1169	}
1170
1171	return 0;
1172}
1173
1174#ifdef RTCONFIG_FANCTRL
1175int
1176setFanOn(void)
1177{
1178	led_control(FAN, FAN_ON);
1179	if (button_pressed(BTN_FAN))
1180		puts("1");
1181	else
1182		puts("ATE_ERROR");
1183}
1184
1185int
1186setFanOff(void)
1187{
1188	led_control(FAN, FAN_OFF);
1189	if (!button_pressed(BTN_FAN))
1190		puts("1");
1191	else
1192		puts("ATE_ERROR");
1193}
1194#endif
1195
1196int
1197setWiFi2G(const char *act)
1198{
1199	if (!strcmp(act, "on"))
1200		eval("wl", "radio", "on");
1201	else if (!strcmp(act, "off"))
1202		eval("wl", "radio", "off");
1203	else
1204		return 0;
1205
1206	puts(act);
1207	return 1;
1208}
1209
1210int
1211setWiFi5G(const char *act)
1212{
1213	if (!strcmp(act, "on"))
1214		eval("wl", "-i", "eth2", "radio", "on");
1215	else if (!strcmp(act, "off"))
1216		eval("wl", "-i", "eth2", "radio", "off");
1217	else
1218		return 0;
1219	puts(act);
1220	return 1;
1221}
1222
1223int
1224getWiFiStatus(const char *ifc)
1225{
1226	FILE *fp;
1227	char buf[128], *line;
1228	int ret = 1;
1229
1230	if (!strcmp(ifc, "2G"))
1231		sprintf(buf, "wl radio");
1232	else if (!strcmp(ifc, "5G"))
1233		sprintf(buf, "wl -i eth2 radio");
1234	else
1235		return 0;
1236
1237	fp = popen(buf, "r");
1238	if (fp == NULL) {
1239		perror("popen");
1240		return 0;
1241	}
1242
1243	line = fgets(buf, sizeof(buf), fp);
1244	if (line == NULL)
1245		ret = 0;
1246	else if (strstr(line, "0x0000"))
1247		puts("1");
1248	else if (strstr(line, "0x0001"))
1249		puts("0");
1250	else
1251		ret = 0;
1252
1253	return ret;
1254}
1255
1256/* The below macro handle endian mis-matches between wl utility and wl driver. */
1257static bool g_swap = FALSE;
1258#define htod32(i) (g_swap?bcmswap32(i):(uint32)(i))
1259#define dtoh32(i) (g_swap?bcmswap32(i):(uint32)(i))
1260#define	IW_MAX_FREQUENCIES	32
1261
1262int Get_channel_list(int unit)
1263{
1264	int i, retval = 0;
1265	int channels[MAXCHANNEL+1];
1266	wl_uint32_list_t *list = (wl_uint32_list_t *) channels;
1267	char tmp[256], prefix[] = "wlXXXXXXXXXX_";
1268	char *name;
1269	uint ch;
1270
1271	snprintf(prefix, sizeof(prefix), "wl%d_", unit);
1272	name = nvram_safe_get(strcat_r(prefix, "ifname", tmp));
1273	memset(tmp, 0x0, sizeof(tmp));
1274
1275	memset(channels, 0, sizeof(channels));
1276	list->count = htod32(MAXCHANNEL);
1277	if (wl_ioctl(name, WLC_GET_VALID_CHANNELS , channels, sizeof(channels)) < 0)
1278	{
1279		dbg("error doing WLC_GET_VALID_CHANNELS\n");
1280		sprintf(tmp, "%d", 0);
1281		goto ERROR;
1282	}
1283
1284	if (dtoh32(list->count) == 0)
1285	{
1286		sprintf(tmp, "%d", 0);
1287		goto ERROR;
1288	}
1289
1290	retval = 1;
1291	for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) {
1292		ch = dtoh32(list->element[i]);
1293
1294		if (i == 0)
1295			sprintf(tmp, "%d", ch);
1296		else
1297			sprintf(tmp,  "%s, %d", tmp, ch);
1298	}
1299ERROR:
1300	puts(tmp);
1301	return retval;
1302}
1303
1304int Get_ChannelList_2G(void)
1305{
1306#ifndef RTAC3200_INTF_ORDER
1307	return Get_channel_list(0);
1308#else
1309	return Get_channel_list(1);
1310#endif
1311}
1312
1313int Get_ChannelList_5G(void)
1314{
1315#ifndef RTAC3200_INTF_ORDER
1316	return Get_channel_list(1);
1317#else
1318	return Get_channel_list(0);
1319#endif
1320}
1321
1322#if defined(RTAC3200) || defined(RTAC5300) || defined(RTAC5300R)
1323int Get_ChannelList_5G_2(void)
1324{
1325	return Get_channel_list(2);
1326}
1327#endif
1328
1329static const unsigned char WPA_OUT_TYPE[] = { 0x00, 0x50, 0xf2, 1 };
1330
1331char *wlc_nvname(char *keyword)
1332{
1333	return(wl_nvname(keyword, nvram_get_int("wlc_band"), -1));
1334}
1335
1336int wpa_key_mgmt_to_bitfield(const unsigned char *s)
1337{
1338	if (memcmp(s, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X, WPA_SELECTOR_LEN) == 0)
1339		return WPA_KEY_MGMT_IEEE8021X_;
1340	if (memcmp(s, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X, WPA_SELECTOR_LEN) ==
1341	    0)
1342		return WPA_KEY_MGMT_PSK_;
1343	if (memcmp(s, WPA_AUTH_KEY_MGMT_NONE, WPA_SELECTOR_LEN) == 0)
1344		return WPA_KEY_MGMT_WPA_NONE_;
1345	return 0;
1346}
1347
1348int rsn_key_mgmt_to_bitfield(const unsigned char *s)
1349{
1350	if (memcmp(s, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X, RSN_SELECTOR_LEN) == 0)
1351		return WPA_KEY_MGMT_IEEE8021X2_;
1352	if (memcmp(s, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X, RSN_SELECTOR_LEN) ==
1353	    0)
1354		return WPA_KEY_MGMT_PSK2_;
1355	return 0;
1356}
1357
1358int wpa_selector_to_bitfield(const unsigned char *s)
1359{
1360	if (memcmp(s, WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN) == 0)
1361		return WPA_CIPHER_NONE_;
1362	if (memcmp(s, WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN) == 0)
1363		return WPA_CIPHER_WEP40_;
1364	if (memcmp(s, WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN) == 0)
1365		return WPA_CIPHER_TKIP_;
1366	if (memcmp(s, WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN) == 0)
1367		return WPA_CIPHER_CCMP_;
1368	if (memcmp(s, WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN) == 0)
1369		return WPA_CIPHER_WEP104_;
1370	return 0;
1371}
1372
1373int rsn_selector_to_bitfield(const unsigned char *s)
1374{
1375	if (memcmp(s, RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN) == 0)
1376		return WPA_CIPHER_NONE_;
1377	if (memcmp(s, RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN) == 0)
1378		return WPA_CIPHER_WEP40_;
1379	if (memcmp(s, RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN) == 0)
1380		return WPA_CIPHER_TKIP_;
1381	if (memcmp(s, RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN) == 0)
1382		return WPA_CIPHER_CCMP_;
1383	if (memcmp(s, RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN) == 0)
1384		return WPA_CIPHER_WEP104_;
1385	return 0;
1386}
1387
1388int wpa_parse_wpa_ie_wpa(const unsigned char *wpa_ie, size_t wpa_ie_len, struct wpa_ie_data *data)
1389{
1390	const struct wpa_ie_hdr *hdr;
1391	const unsigned char *pos;
1392	int left;
1393	int i, count;
1394
1395	data->proto = WPA_PROTO_WPA_;
1396	data->pairwise_cipher = WPA_CIPHER_TKIP_;
1397	data->group_cipher = WPA_CIPHER_TKIP_;
1398	data->key_mgmt = WPA_KEY_MGMT_IEEE8021X_;
1399	data->capabilities = 0;
1400	data->pmkid = NULL;
1401	data->num_pmkid = 0;
1402
1403	if (wpa_ie_len == 0) {
1404		/* No WPA IE - fail silently */
1405		return -1;
1406	}
1407
1408	if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) {
1409//		fprintf(stderr, "ie len too short %lu", (unsigned long) wpa_ie_len);
1410		return -1;
1411	}
1412
1413	hdr = (const struct wpa_ie_hdr *) wpa_ie;
1414
1415	if (hdr->elem_id != DOT11_MNG_WPA_ID ||
1416	    hdr->len != wpa_ie_len - 2 ||
1417	    memcmp(&hdr->oui, WPA_OUI_TYPE_ARR, WPA_SELECTOR_LEN) != 0 ||
1418	    WPA_GET_LE16(hdr->version) != WPA_VERSION_) {
1419//		fprintf(stderr, "malformed ie or unknown version");
1420		return -1;
1421	}
1422
1423	pos = (const unsigned char *) (hdr + 1);
1424	left = wpa_ie_len - sizeof(*hdr);
1425
1426	if (left >= WPA_SELECTOR_LEN) {
1427		data->group_cipher = wpa_selector_to_bitfield(pos);
1428		pos += WPA_SELECTOR_LEN;
1429		left -= WPA_SELECTOR_LEN;
1430	} else if (left > 0) {
1431//		fprintf(stderr, "ie length mismatch, %u too much", left);
1432		return -1;
1433	}
1434
1435	if (left >= 2) {
1436		data->pairwise_cipher = 0;
1437		count = WPA_GET_LE16(pos);
1438		pos += 2;
1439		left -= 2;
1440		if (count == 0 || left < count * WPA_SELECTOR_LEN) {
1441//			fprintf(stderr, "ie count botch (pairwise), "
1442//				   "count %u left %u", count, left);
1443			return -1;
1444		}
1445		for (i = 0; i < count; i++) {
1446			data->pairwise_cipher |= wpa_selector_to_bitfield(pos);
1447			pos += WPA_SELECTOR_LEN;
1448			left -= WPA_SELECTOR_LEN;
1449		}
1450	} else if (left == 1) {
1451//		fprintf(stderr, "ie too short (for key mgmt)");
1452		return -1;
1453	}
1454
1455	if (left >= 2) {
1456		data->key_mgmt = 0;
1457		count = WPA_GET_LE16(pos);
1458		pos += 2;
1459		left -= 2;
1460		if (count == 0 || left < count * WPA_SELECTOR_LEN) {
1461//			fprintf(stderr, "ie count botch (key mgmt), "
1462//				   "count %u left %u", count, left);
1463			return -1;
1464		}
1465		for (i = 0; i < count; i++) {
1466			data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos);
1467			pos += WPA_SELECTOR_LEN;
1468			left -= WPA_SELECTOR_LEN;
1469		}
1470	} else if (left == 1) {
1471//		fprintf(stderr, "ie too short (for capabilities)");
1472		return -1;
1473	}
1474
1475	if (left >= 2) {
1476		data->capabilities = WPA_GET_LE16(pos);
1477		pos += 2;
1478		left -= 2;
1479	}
1480
1481	if (left > 0) {
1482//		fprintf(stderr, "ie has %u trailing bytes", left);
1483		return -1;
1484	}
1485
1486	return 0;
1487}
1488
1489int wpa_parse_wpa_ie_rsn(const unsigned char *rsn_ie, size_t rsn_ie_len, struct wpa_ie_data *data)
1490{
1491	const struct rsn_ie_hdr *hdr;
1492	const unsigned char *pos;
1493	int left;
1494	int i, count;
1495
1496	data->proto = WPA_PROTO_RSN_;
1497	data->pairwise_cipher = WPA_CIPHER_CCMP_;
1498	data->group_cipher = WPA_CIPHER_CCMP_;
1499	data->key_mgmt = WPA_KEY_MGMT_IEEE8021X2_;
1500	data->capabilities = 0;
1501	data->pmkid = NULL;
1502	data->num_pmkid = 0;
1503
1504	if (rsn_ie_len == 0) {
1505		/* No RSN IE - fail silently */
1506		return -1;
1507	}
1508
1509	if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) {
1510//		fprintf(stderr, "ie len too short %lu", (unsigned long) rsn_ie_len);
1511		return -1;
1512	}
1513
1514	hdr = (const struct rsn_ie_hdr *) rsn_ie;
1515
1516	if (hdr->elem_id != DOT11_MNG_RSN_ID ||
1517	    hdr->len != rsn_ie_len - 2 ||
1518	    WPA_GET_LE16(hdr->version) != RSN_VERSION_) {
1519//		fprintf(stderr, "malformed ie or unknown version");
1520		return -1;
1521	}
1522
1523	pos = (const unsigned char *) (hdr + 1);
1524	left = rsn_ie_len - sizeof(*hdr);
1525
1526	if (left >= RSN_SELECTOR_LEN) {
1527		data->group_cipher = rsn_selector_to_bitfield(pos);
1528		pos += RSN_SELECTOR_LEN;
1529		left -= RSN_SELECTOR_LEN;
1530	} else if (left > 0) {
1531//		fprintf(stderr, "ie length mismatch, %u too much", left);
1532		return -1;
1533	}
1534
1535	if (left >= 2) {
1536		data->pairwise_cipher = 0;
1537		count = WPA_GET_LE16(pos);
1538		pos += 2;
1539		left -= 2;
1540		if (count == 0 || left < count * RSN_SELECTOR_LEN) {
1541//			fprintf(stderr, "ie count botch (pairwise), "
1542//				   "count %u left %u", count, left);
1543			return -1;
1544		}
1545		for (i = 0; i < count; i++) {
1546			data->pairwise_cipher |= rsn_selector_to_bitfield(pos);
1547			pos += RSN_SELECTOR_LEN;
1548			left -= RSN_SELECTOR_LEN;
1549		}
1550	} else if (left == 1) {
1551//		fprintf(stderr, "ie too short (for key mgmt)");
1552		return -1;
1553	}
1554
1555	if (left >= 2) {
1556		data->key_mgmt = 0;
1557		count = WPA_GET_LE16(pos);
1558		pos += 2;
1559		left -= 2;
1560		if (count == 0 || left < count * RSN_SELECTOR_LEN) {
1561//			fprintf(stderr, "ie count botch (key mgmt), "
1562//				   "count %u left %u", count, left);
1563			return -1;
1564		}
1565		for (i = 0; i < count; i++) {
1566			data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos);
1567			pos += RSN_SELECTOR_LEN;
1568			left -= RSN_SELECTOR_LEN;
1569		}
1570	} else if (left == 1) {
1571//		fprintf(stderr, "ie too short (for capabilities)");
1572		return -1;
1573	}
1574
1575	if (left >= 2) {
1576		data->capabilities = WPA_GET_LE16(pos);
1577		pos += 2;
1578		left -= 2;
1579	}
1580
1581	if (left >= 2) {
1582		data->num_pmkid = WPA_GET_LE16(pos);
1583		pos += 2;
1584		left -= 2;
1585		if (left < data->num_pmkid * PMKID_LEN) {
1586//			fprintf(stderr, "PMKID underflow "
1587//				   "(num_pmkid=%d left=%d)", data->num_pmkid, left);
1588			data->num_pmkid = 0;
1589		} else {
1590			data->pmkid = pos;
1591			pos += data->num_pmkid * PMKID_LEN;
1592			left -= data->num_pmkid * PMKID_LEN;
1593		}
1594	}
1595
1596	if (left > 0) {
1597//		fprintf(stderr, "ie has %u trailing bytes - ignored", left);
1598	}
1599
1600	return 0;
1601}
1602
1603int wpa_parse_wpa_ie(const unsigned char *wpa_ie, size_t wpa_ie_len,
1604		     struct wpa_ie_data *data)
1605{
1606	if (wpa_ie_len >= 1 && wpa_ie[0] == DOT11_MNG_RSN_ID)
1607		return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data);
1608	else
1609		return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data);
1610}
1611
1612static const char * wpa_key_mgmt_txt(int key_mgmt, int proto)
1613{
1614	switch (key_mgmt) {
1615	case WPA_KEY_MGMT_IEEE8021X_:
1616/*
1617		return proto == WPA_PROTO_RSN_ ?
1618			"WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP";
1619*/
1620		return "WPA-Enterprise";
1621	case WPA_KEY_MGMT_IEEE8021X2_:
1622		return "WPA2-Enterprise";
1623	case WPA_KEY_MGMT_PSK_:
1624/*
1625		return proto == WPA_PROTO_RSN_ ?
1626			"WPA2-PSK" : "WPA-PSK";
1627*/
1628		return "WPA-Personal";
1629	case WPA_KEY_MGMT_PSK2_:
1630		return "WPA2-Personal";
1631	case WPA_KEY_MGMT_NONE_:
1632		return "NONE";
1633	case WPA_KEY_MGMT_IEEE8021X_NO_WPA_:
1634//		return "IEEE 802.1X (no WPA)";
1635		return "IEEE 802.1X";
1636	default:
1637		return "Unknown";
1638	}
1639}
1640
1641static const char * wpa_cipher_txt(int cipher)
1642{
1643	switch (cipher) {
1644	case WPA_CIPHER_NONE_:
1645		return "NONE";
1646	case WPA_CIPHER_WEP40_:
1647		return "WEP-40";
1648	case WPA_CIPHER_WEP104_:
1649		return "WEP-104";
1650	case WPA_CIPHER_TKIP_:
1651		return "TKIP";
1652	case WPA_CIPHER_CCMP_:
1653//		return "CCMP";
1654		return "AES";
1655	case (WPA_CIPHER_TKIP_|WPA_CIPHER_CCMP_):
1656		return "TKIP+AES";
1657	default:
1658		return "Unknown";
1659	}
1660}
1661
1662static char scan_result[WLC_SCAN_RESULT_BUF_LEN];
1663
1664int wlcscan_core(char *ofile, char *wif)
1665{
1666	int ret, i, k, left, ht_extcha;
1667	int retval = 0, ap_count = 0, idx_same = -1, count = 0;
1668	unsigned char *bssidp;
1669	char *info_b;
1670	unsigned char rate;
1671	unsigned char bssid[6];
1672	char macstr[18];
1673	char ure_mac[18];
1674	char ssid_str[256];
1675	wl_scan_results_t *result;
1676	wl_bss_info_t *info;
1677	wl_bss_info_107_t *old_info;
1678	struct bss_ie_hdr *ie;
1679	NDIS_802_11_NETWORK_TYPE NetWorkType;
1680	struct maclist *authorized;
1681	int maclist_size;
1682	int max_sta_count = 128;
1683	int wl_authorized = 0;
1684	wl_scan_params_t *params;
1685	int params_size = WL_SCAN_PARAMS_FIXED_SIZE + NUMCHANS * sizeof(uint16);
1686	FILE *fp;
1687	int org_scan_time = 20, scan_time = 40;
1688	int wait_time = 3;
1689
1690	params = (wl_scan_params_t*)malloc(params_size);
1691	if (params == NULL)
1692		return retval;
1693
1694	memset(params, 0, params_size);
1695	params->bss_type = DOT11_BSSTYPE_INFRASTRUCTURE;
1696	memcpy(&params->bssid, &ether_bcast, ETHER_ADDR_LEN);
1697	params->scan_type = -1;
1698	params->nprobes = -1;
1699	params->active_time = -1;
1700	params->passive_time = -1;
1701	params->home_time = -1;
1702#if defined(RTAC88U) || defined(RTAC3100) || defined(RTAC5300) || defined(RTAC5300R)
1703	int band = WLC_BAND_ALL;
1704	wl_ioctl(wif, WLC_GET_BAND, &band, sizeof(band));
1705	if (band == WLC_BAND_5G)
1706	{
1707		if (wl_subband(wif, nvram_get_int("wlcscan_idx")+1) == 1)
1708		{
1709			params->channel_num = 4;
1710			params->channel_list[0] = 36;
1711			params->channel_list[1] = 40;
1712			params->channel_list[2] = 44;
1713			params->channel_list[3] = 48;
1714		}
1715		else if (wl_subband(wif, nvram_get_int("wlcscan_idx")+1) == 2)
1716		{
1717			params->channel_num = 4;
1718			params->channel_list[0] = 52;
1719			params->channel_list[1] = 56;
1720			params->channel_list[2] = 60;
1721			params->channel_list[3] = 64;
1722		}
1723		else if (wl_subband(wif, nvram_get_int("wlcscan_idx")+1) == 3)
1724		{
1725			if (wl_channel_valid(wif, 120))
1726			{
1727				params->channel_num = 11;
1728				params->channel_list[0] = 100;
1729				params->channel_list[1] = 104;
1730				params->channel_list[2] = 108;
1731				params->channel_list[3] = 112;
1732				params->channel_list[4] = 116;
1733				params->channel_list[5] = 120;
1734				params->channel_list[6] = 124;
1735				params->channel_list[7] = 128;
1736				params->channel_list[8] = 132;
1737				params->channel_list[9] = 136;
1738				params->channel_list[10] = 140;
1739			}
1740			else
1741			{
1742				params->channel_num = 8;
1743				params->channel_list[0] = 100;
1744				params->channel_list[1] = 104;
1745				params->channel_list[2] = 108;
1746				params->channel_list[3] = 112;
1747				params->channel_list[4] = 116;
1748				params->channel_list[5] = 132;
1749				params->channel_list[6] = 136;
1750				params->channel_list[7] = 140;
1751			}
1752		}
1753		else if (wl_subband(wif, nvram_get_int("wlcscan_idx")+1) == 4)
1754		{
1755			params->channel_num = 5;
1756			params->channel_list[0] = 165;
1757			params->channel_list[1] = 161;
1758			params->channel_list[2] = 157;
1759			params->channel_list[3] = 153;
1760			params->channel_list[4] = 149;
1761		}
1762		else
1763		{
1764			free(params);
1765			return retval;
1766		}
1767	}
1768	else
1769	{
1770		if (nvram_get_int("wlcscan_idx") == 0)
1771		{
1772			params->channel_num = 6;
1773			params->channel_list[0] = 1;
1774			params->channel_list[1] = 2;
1775			params->channel_list[2] = 3;
1776			params->channel_list[3] = 4;
1777			params->channel_list[4] = 5;
1778			params->channel_list[5] = 6;
1779		}
1780		else if (nvram_get_int("wlcscan_idx") == 1)
1781		{
1782			if (wl_channel_valid(wif, 13))
1783			{
1784				params->channel_num = 7;
1785				params->channel_list[0] = 7;
1786				params->channel_list[1] = 8;
1787				params->channel_list[2] = 9;
1788				params->channel_list[3] = 10;
1789				params->channel_list[4] = 11;
1790				params->channel_list[5] = 12;
1791				params->channel_list[6] = 13;
1792			}
1793			else
1794			{
1795				params->channel_num = 5;
1796				params->channel_list[0] = 7;
1797				params->channel_list[1] = 8;
1798				params->channel_list[2] = 9;
1799				params->channel_list[3] = 10;
1800				params->channel_list[4] = 11;
1801			}
1802		}
1803		else
1804		{
1805			free(params);
1806			return retval;
1807		}
1808	}
1809#else
1810	params->channel_num = 0;
1811#endif
1812
1813	/* extend scan channel time to get more AP probe resp */
1814	wl_ioctl(wif, WLC_GET_SCAN_CHANNEL_TIME, &org_scan_time, sizeof(org_scan_time));
1815	if (org_scan_time < scan_time)
1816		wl_ioctl(wif, WLC_SET_SCAN_CHANNEL_TIME, &scan_time, sizeof(scan_time));
1817
1818	while ((ret = wl_ioctl(wif, WLC_SCAN, params, params_size)) < 0 &&
1819				count++ < 2) {
1820		dbg("[rc] set scan command failed, retry %d\n", count);
1821		sleep(1);
1822	}
1823
1824	free(params);
1825
1826	/* restore original scan channel time */
1827	wl_ioctl(wif, WLC_SET_SCAN_CHANNEL_TIME, &org_scan_time, sizeof(org_scan_time));
1828
1829#if defined(RTAC88U) || defined(RTAC3100) || defined(RTAC5300) || defined(RTAC5300R)
1830	wait_time = 2;
1831#endif
1832	dbg("[rc] Please wait %d seconds ", wait_time);
1833	do {
1834		sleep(1);
1835		dbg(".");
1836	} while (--wait_time > 0);
1837	dbg("\n\n");
1838
1839	if (ret == 0) {
1840		result = (wl_scan_results_t *)scan_result;
1841		result->buflen = htod32(WLC_SCAN_RESULT_BUF_LEN);
1842
1843		while ((ret = wl_ioctl(wif, WLC_SCAN_RESULTS, result, WLC_SCAN_RESULT_BUF_LEN)) < 0 && count++ < 2)
1844		{
1845			dbg("[rc] set scan results command failed, retry %d\n", count);
1846			sleep(1);
1847		}
1848
1849		if (ret == 0)
1850		{
1851			info = &(result->bss_info[0]);
1852
1853			/* Convert version 107 to 109 */
1854			if (dtoh32(info->version) == LEGACY_WL_BSS_INFO_VERSION) {
1855				old_info = (wl_bss_info_107_t *)info;
1856				info->chanspec = CH20MHZ_CHSPEC(old_info->channel);
1857				info->ie_length = old_info->ie_length;
1858				info->ie_offset = sizeof(wl_bss_info_107_t);
1859			}
1860
1861			info_b = (char *) info;
1862
1863			for (i = 0; i < result->count; i++)
1864			{
1865				if (info->SSID_len > 32/* || info->SSID_len == 0*/)
1866					goto next_info;
1867				bssidp = (unsigned char *)&info->BSSID;
1868				sprintf(macstr, "%02X:%02X:%02X:%02X:%02X:%02X",
1869										(unsigned char)bssidp[0],
1870										(unsigned char)bssidp[1],
1871										(unsigned char)bssidp[2],
1872										(unsigned char)bssidp[3],
1873										(unsigned char)bssidp[4],
1874										(unsigned char)bssidp[5]);
1875
1876				idx_same = -1;
1877				for (k = 0; k < ap_count; k++) {
1878					/* deal with old version of Broadcom Multiple SSID
1879						(share the same BSSID) */
1880					if (strcmp(apinfos[k].BSSID, macstr) == 0 &&
1881						strcmp(apinfos[k].SSID, (const char *) info->SSID) == 0) {
1882						idx_same = k;
1883						break;
1884					}
1885				}
1886
1887				if (idx_same != -1)
1888				{
1889					if (info->RSSI >= -50)
1890						apinfos[idx_same].RSSI_Quality = 100;
1891					else if (info->RSSI >= -80)	// between -50 ~ -80dbm
1892						apinfos[idx_same].RSSI_Quality = (int)(24 + ((info->RSSI + 80) * 26)/10);
1893					else if (info->RSSI >= -90)	// between -80 ~ -90dbm
1894						apinfos[idx_same].RSSI_Quality = (int)(((info->RSSI + 90) * 26)/10);
1895					else					// < -84 dbm
1896						apinfos[idx_same].RSSI_Quality = 0;
1897				}
1898				else
1899				{
1900					strcpy(apinfos[ap_count].BSSID, macstr);
1901//					strcpy(apinfos[ap_count].SSID, info->SSID);
1902					memset(apinfos[ap_count].SSID, 0x0, 33);
1903					memcpy(apinfos[ap_count].SSID, info->SSID, info->SSID_len);
1904					apinfos[ap_count].channel = (uint8)(info->chanspec & WL_CHANSPEC_CHAN_MASK);
1905					if (info->ctl_ch == 0)
1906					{
1907						apinfos[ap_count].ctl_ch = apinfos[ap_count].channel;
1908					} else
1909					{
1910						apinfos[ap_count].ctl_ch = info->ctl_ch;
1911					}
1912
1913					if (info->RSSI >= -50)
1914						apinfos[ap_count].RSSI_Quality = 100;
1915					else if (info->RSSI >= -80)	// between -50 ~ -80dbm
1916						apinfos[ap_count].RSSI_Quality = (int)(24 + ((info->RSSI + 80) * 26)/10);
1917					else if (info->RSSI >= -90)	// between -80 ~ -90dbm
1918						apinfos[ap_count].RSSI_Quality = (int)(((info->RSSI + 90) * 26)/10);
1919					else					// < -84 dbm
1920						apinfos[ap_count].RSSI_Quality = 0;
1921
1922					if ((info->capability & 0x10) == 0x10)
1923						apinfos[ap_count].wep = 1;
1924					else
1925						apinfos[ap_count].wep = 0;
1926					apinfos[ap_count].wpa = 0;
1927
1928/*
1929					unsigned char *RATESET = &info->rateset;
1930					for (k = 0; k < 18; k++)
1931						dbg("%02x ", (unsigned char)RATESET[k]);
1932					dbg("\n");
1933*/
1934
1935					NetWorkType = Ndis802_11DS;
1936					if ((uint8)(info->chanspec & WL_CHANSPEC_CHAN_MASK) <= 14)
1937					{
1938						for (k = 0; k < info->rateset.count; k++)
1939						{
1940							rate = info->rateset.rates[k] & 0x7f;	// Mask out basic rate set bit
1941							if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22))
1942								continue;
1943							else
1944							{
1945								NetWorkType = Ndis802_11OFDM24;
1946								break;
1947							}
1948						}
1949					}
1950					else
1951						NetWorkType = Ndis802_11OFDM5;
1952
1953					if (info->n_cap)
1954					{
1955						if (NetWorkType == Ndis802_11OFDM5)
1956						{
1957#ifdef RTCONFIG_BCMWL6
1958							if (info->vht_cap)
1959								NetWorkType = Ndis802_11OFDM5_VHT;
1960							else
1961#endif
1962								NetWorkType = Ndis802_11OFDM5_N;
1963						}
1964						else
1965							NetWorkType = Ndis802_11OFDM24_N;
1966					}
1967
1968					apinfos[ap_count].NetworkType = NetWorkType;
1969
1970					ap_count++;
1971
1972					if (ap_count >= MAX_NUMBER_OF_APINFO)
1973						break;
1974				}
1975
1976				ie = (struct bss_ie_hdr *) ((unsigned char *) info + sizeof(*info));
1977				for (left = info->ie_length; left > 0; // look for RSN IE first
1978					left -= (ie->len + 2), ie = (struct bss_ie_hdr *) ((unsigned char *) ie + 2 + ie->len))
1979				{
1980					if (ie->elem_id != DOT11_MNG_RSN_ID)
1981						continue;
1982
1983					if (wpa_parse_wpa_ie(&ie->elem_id, ie->len + 2, &apinfos[ap_count - 1].wid) == 0)
1984					{
1985						apinfos[ap_count-1].wpa = 1;
1986						goto next_info;
1987					}
1988				}
1989
1990				ie = (struct bss_ie_hdr *) ((unsigned char *) info + sizeof(*info));
1991				for (left = info->ie_length; left > 0; // then look for WPA IE
1992					left -= (ie->len + 2), ie = (struct bss_ie_hdr *) ((unsigned char *) ie + 2 + ie->len))
1993				{
1994					if (ie->elem_id != DOT11_MNG_WPA_ID)
1995						continue;
1996
1997					if (wpa_parse_wpa_ie(&ie->elem_id, ie->len + 2, &apinfos[ap_count-1].wid) == 0)
1998					{
1999						apinfos[ap_count-1].wpa = 1;
2000						break;
2001					}
2002				}
2003
2004next_info:
2005				info = (wl_bss_info_t *) ((unsigned char *) info + info->length);
2006			}
2007		}
2008	}
2009
2010	/* Print scanning result to console */
2011	if (ap_count == 0) {
2012		dbg("[wlc] No AP found!\n");
2013	} else {
2014		printf("%-4s%4s%-33s%-18s%-9s%-16s%-9s%8s%3s%3s\n",
2015				"idx", "CH ", "SSID", "BSSID", "Enc", "Auth", "Siganl(%)", "W-Mode", "CC", "EC");
2016		for (k = 0; k < ap_count; k++)
2017		{
2018			printf("%2d. ", k + 1);
2019			printf("%3d ", apinfos[k].ctl_ch);
2020			printf("%-33s", apinfos[k].SSID);
2021			printf("%-18s", apinfos[k].BSSID);
2022
2023			if (apinfos[k].wpa == 1)
2024				printf("%-9s%-16s", wpa_cipher_txt(apinfos[k].wid.pairwise_cipher), wpa_key_mgmt_txt(apinfos[k].wid.key_mgmt, apinfos[k].wid.proto));
2025			else if (apinfos[k].wep == 1)
2026				printf("WEP      Unknown         ");
2027			else
2028				printf("NONE     Open System     ");
2029			printf("%9d ", apinfos[k].RSSI_Quality);
2030
2031			if (apinfos[k].NetworkType == Ndis802_11FH || apinfos[k].NetworkType == Ndis802_11DS)
2032				printf("%-7s", "11b");
2033			else if (apinfos[k].NetworkType == Ndis802_11OFDM5)
2034				printf("%-7s", "11a");
2035			else if (apinfos[k].NetworkType == Ndis802_11OFDM5_VHT)
2036				printf("%-7s", "11ac");
2037			else if (apinfos[k].NetworkType == Ndis802_11OFDM5_N)
2038				printf("%-7s", "11a/n");
2039			else if (apinfos[k].NetworkType == Ndis802_11OFDM24)
2040				printf("%-7s", "11b/g");
2041			else if (apinfos[k].NetworkType == Ndis802_11OFDM24_N)
2042				printf("%-7s", "11b/g/n");
2043			else
2044				printf("%-7s", "unknown");
2045
2046			printf("%3d", apinfos[k].ctl_ch);
2047
2048			if (	((apinfos[k].NetworkType == Ndis802_11OFDM5_VHT) ||
2049				 (apinfos[k].NetworkType == Ndis802_11OFDM5_N) ||
2050				 (apinfos[k].NetworkType == Ndis802_11OFDM24_N)) &&
2051					(apinfos[k].channel != apinfos[k].ctl_ch)) {
2052				if (apinfos[k].ctl_ch < apinfos[k].channel)
2053					ht_extcha = 1;
2054				else
2055					ht_extcha = 0;
2056
2057				printf("%3d", ht_extcha);
2058			}
2059
2060			printf("\n");
2061		}
2062	}
2063
2064	ret = wl_ioctl(wif, WLC_GET_BSSID, bssid, sizeof(bssid));
2065	memset(ure_mac, 0x0, 18);
2066	if (!ret) {
2067		if (!(!bssid[0] && !bssid[1] && !bssid[2] && !bssid[3] && !bssid[4] && !bssid[5])) {
2068			sprintf(ure_mac, "%02X:%02X:%02X:%02X:%02X:%02X",
2069										(unsigned char)bssid[0],
2070										(unsigned char)bssid[1],
2071										(unsigned char)bssid[2],
2072										(unsigned char)bssid[3],
2073										(unsigned char)bssid[4],
2074										(unsigned char)bssid[5]);
2075		}
2076	}
2077
2078	if (strstr(nvram_safe_get(wlc_nvname("akm")), "psk")) {
2079		maclist_size = sizeof(authorized->count) + max_sta_count * sizeof(struct ether_addr);
2080		authorized = malloc(maclist_size);
2081
2082		// query wl for authorized sta list
2083		strcpy((char*)authorized, "autho_sta_list");
2084		if (!wl_ioctl(wif, WLC_GET_VAR, authorized, maclist_size)) {
2085			if (authorized->count > 0) wl_authorized = 1;
2086		}
2087
2088		if (authorized) free(authorized);
2089	}
2090
2091	/* Print scanning result to web format */
2092	if (ap_count > 0) {
2093		/* write pid */
2094		if ((fp = fopen(ofile, "a")) == NULL) {
2095			printf("[wlcscan] Output %s error\n", ofile);
2096		} else {
2097#if defined(RTAC3200) || defined(RTAC5300) || defined(RTAC5300R)
2098			int unit = 0;
2099			char prefix[] = "wlXXXXXXXXXX_", tmp[100];
2100			wl_ioctl(wif, WLC_GET_INSTANCE, &unit, sizeof(unit));
2101			snprintf(prefix, sizeof(prefix), "wl%d_", unit);
2102#endif
2103			for (i = 0; i < ap_count; i++) {
2104#if defined(RTAC3200) || defined(RTAC5300) || defined(RTAC5300R)
2105				if (!strcmp(wif, "eth1") && (apinfos[i].ctl_ch > 48))
2106					continue;
2107				if (!strcmp(wif, "eth3")) {
2108					if (nvram_match(strcat_r(prefix, "country_code", tmp), "E0") ||
2109					    nvram_match(strcat_r(prefix, "country_code", tmp), "JP")) {
2110						if (apinfos[i].ctl_ch < 100)
2111							continue;
2112					} else {
2113						if (apinfos[i].ctl_ch < 149)
2114							continue;
2115					}
2116				}
2117#endif
2118				/*if (apinfos[i].ctl_ch < 0 ) {
2119					fprintf(fp, "\"ERR_BNAD\",");
2120				} else */if (apinfos[i].ctl_ch > 0 &&
2121							 apinfos[i].ctl_ch < 14) {
2122					fprintf(fp, "\"2G\",");
2123				} else if (apinfos[i].ctl_ch > 14 &&
2124							 apinfos[i].ctl_ch < 166) {
2125					fprintf(fp, "\"5G\",");
2126				} else {
2127					fprintf(fp, "\"ERR_BNAD\",");
2128				}
2129
2130				if (strlen(apinfos[i].SSID) == 0) {
2131					fprintf(fp, "\"\",");
2132				} else {
2133					memset(ssid_str, 0, sizeof(ssid_str));
2134					char_to_ascii(ssid_str, apinfos[i].SSID);
2135					fprintf(fp, "\"%s\",", ssid_str);
2136				}
2137
2138				fprintf(fp, "\"%d\",", apinfos[i].ctl_ch);
2139
2140				if (apinfos[i].wpa == 1) {
2141					if (apinfos[i].wid.key_mgmt == WPA_KEY_MGMT_IEEE8021X_)
2142						fprintf(fp, "\"%s\",", "WPA-Enterprise");
2143					else if (apinfos[i].wid.key_mgmt == WPA_KEY_MGMT_IEEE8021X2_)
2144						fprintf(fp, "\"%s\",", "WPA2-Enterprise");
2145					else if (apinfos[i].wid.key_mgmt == WPA_KEY_MGMT_PSK_)
2146						fprintf(fp, "\"%s\",", "WPA-Personal");
2147					else if (apinfos[i].wid.key_mgmt == WPA_KEY_MGMT_PSK2_)
2148						fprintf(fp, "\"%s\",", "WPA2-Personal");
2149					else if (apinfos[i].wid.key_mgmt == WPA_KEY_MGMT_NONE_)
2150						fprintf(fp, "\"%s\",", "NONE");
2151					else if (apinfos[i].wid.key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA_)
2152						fprintf(fp, "\"%s\",", "IEEE 802.1X");
2153					else
2154						fprintf(fp, "\"%s\",", "Unknown");
2155				} else if (apinfos[i].wep == 1) {
2156					fprintf(fp, "\"%s\",", "Unknown");
2157				} else {
2158					fprintf(fp, "\"%s\",", "Open System");
2159				}
2160
2161				if (apinfos[i].wpa == 1) {
2162					if (apinfos[i].wid.pairwise_cipher == WPA_CIPHER_NONE_)
2163						fprintf(fp, "\"%s\",", "NONE");
2164					else if (apinfos[i].wid.pairwise_cipher == WPA_CIPHER_WEP40_)
2165						fprintf(fp, "\"%s\",", "WEP");
2166					else if (apinfos[i].wid.pairwise_cipher == WPA_CIPHER_WEP104_)
2167						fprintf(fp, "\"%s\",", "WEP");
2168					else if (apinfos[i].wid.pairwise_cipher == WPA_CIPHER_TKIP_)
2169						fprintf(fp, "\"%s\",", "TKIP");
2170					else if (apinfos[i].wid.pairwise_cipher == WPA_CIPHER_CCMP_)
2171						fprintf(fp, "\"%s\",", "AES");
2172					else if (apinfos[i].wid.pairwise_cipher == (WPA_CIPHER_TKIP_|WPA_CIPHER_CCMP_))
2173						fprintf(fp, "\"%s\",", "TKIP+AES");
2174					else
2175						fprintf(fp, "\"%s\",", "Unknown");
2176				} else if (apinfos[i].wep == 1) {
2177					fprintf(fp, "\"%s\",", "WEP");
2178				} else {
2179					fprintf(fp, "\"%s\",", "NONE");
2180				}
2181
2182				fprintf(fp, "\"%d\",", apinfos[i].RSSI_Quality);
2183				fprintf(fp, "\"%s\",", apinfos[i].BSSID);
2184
2185				if (apinfos[i].NetworkType == Ndis802_11FH || apinfos[i].NetworkType == Ndis802_11DS)
2186					fprintf(fp, "\"%s\",", "b");
2187				else if (apinfos[i].NetworkType == Ndis802_11OFDM5)
2188					fprintf(fp, "\"%s\",", "a");
2189				else if (apinfos[i].NetworkType == Ndis802_11OFDM5_N)
2190					fprintf(fp, "\"%s\",", "an");
2191				else if (apinfos[i].NetworkType == Ndis802_11OFDM5_VHT)
2192					fprintf(fp, "\"%s\",", "ac");
2193				else if (apinfos[i].NetworkType == Ndis802_11OFDM24)
2194					fprintf(fp, "\"%s\",", "bg");
2195				else if (apinfos[i].NetworkType == Ndis802_11OFDM24_N)
2196					fprintf(fp, "\"%s\",", "bgn");
2197				else
2198					fprintf(fp, "\"%s\",", "");
2199
2200				if (strcmp(nvram_safe_get(wlc_nvname("ssid")), apinfos[i].SSID)) {
2201					if (strcmp(apinfos[i].SSID, ""))
2202						fprintf(fp, "\"%s\"", "0");				// none
2203					else if (!strcmp(ure_mac, apinfos[i].BSSID)) {
2204						// hidden AP (null SSID)
2205						if (strstr(nvram_safe_get(wlc_nvname("akm")), "psk")) {
2206							if (wl_authorized) {
2207								// in profile, connected
2208								fprintf(fp, "\"%s\"", "4");
2209							} else {
2210								// in profile, connecting
2211								fprintf(fp, "\"%s\"", "5");
2212							}
2213						} else {
2214							// in profile, connected
2215							fprintf(fp, "\"%s\"", "4");
2216						}
2217					} else {
2218						// hidden AP (null SSID)
2219						fprintf(fp, "\"%s\"", "0");				// none
2220					}
2221				} else if (!strcmp(nvram_safe_get(wlc_nvname("ssid")), apinfos[i].SSID)) {
2222					if (!strlen(ure_mac)) {
2223						// in profile, disconnected
2224						fprintf(fp, "\"%s\",", "1");
2225					} else if (!strcmp(ure_mac, apinfos[i].BSSID)) {
2226						if (strstr(nvram_safe_get(wlc_nvname("akm")), "psk")) {
2227							if (wl_authorized) {
2228								// in profile, connected
2229								fprintf(fp, "\"%s\"", "2");
2230							} else {
2231								// in profile, connecting
2232								fprintf(fp, "\"%s\"", "3");
2233							}
2234						} else {
2235							// in profile, connected
2236							fprintf(fp, "\"%s\"", "2");
2237						}
2238					} else {
2239						fprintf(fp, "\"%s\"", "0");				// impossible...
2240					}
2241				} else {
2242					// wl0_ssid is empty
2243					fprintf(fp, "\"%s\"", "0");
2244				}
2245
2246				if (i == ap_count - 1) {
2247					fprintf(fp, "\n");
2248				} else {
2249					fprintf(fp, "\n");
2250				}
2251			}	/* for */
2252			fclose(fp);
2253		}
2254	}	/* if */
2255
2256	return retval;
2257}
2258
2259#ifdef RTCONFIG_BCM_7114
2260
2261typedef struct escan_wksp_s {
2262	uint8 packet[4096];
2263	int event_fd;
2264} escan_wksp_t;
2265
2266static escan_wksp_t *d_info;
2267
2268/* open a UDP packet to event dispatcher for receiving/sending data */
2269static int
2270escan_open_eventfd()
2271{
2272	int reuse = 1;
2273	struct sockaddr_in sockaddr;
2274	int fd = -1;
2275
2276	d_info->event_fd = -1;
2277
2278	/* open loopback socket to communicate with event dispatcher */
2279	memset(&sockaddr, 0, sizeof(sockaddr));
2280	sockaddr.sin_family = AF_INET;
2281	sockaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
2282	sockaddr.sin_port = htons(EAPD_WKSP_DCS_UDP_SPORT);
2283
2284	if ((fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
2285		dbg("Unable to create loopback socket\n");
2286		goto exit;
2287	}
2288
2289	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&reuse, sizeof(reuse)) < 0) {
2290		dbg("Unable to setsockopt to loopback socket %d.\n", fd);
2291		goto exit;
2292	}
2293
2294	if (bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)) < 0) {
2295		dbg("Unable to bind to loopback socket %d\n", fd);
2296		goto exit;
2297	}
2298
2299	d_info->event_fd = fd;
2300
2301	return 0;
2302
2303	/* error handling */
2304exit:
2305	if (fd != -1) {
2306		close(fd);
2307	}
2308
2309	return errno;
2310}
2311
2312static bool escan_swap = FALSE;
2313#define htod16(i) (escan_swap?bcmswap16(i):(uint16)(i))
2314#define WL_EVENT_TIMEOUT 10
2315
2316struct escan_bss {
2317	struct escan_bss *next;
2318	wl_bss_info_t bss[1];
2319};
2320#define ESCAN_BSS_FIXED_SIZE 4
2321
2322/* listen to sockets and receive escan results */
2323static int
2324get_scan_escan(char *scan_buf, uint buf_len)
2325{
2326	fd_set fdset;
2327	int fd;
2328	struct timeval tv;
2329	uint8 *pkt;
2330	int len;
2331	int retval;
2332	wl_escan_result_t *escan_data;
2333	struct escan_bss *escan_bss_head = NULL;
2334	struct escan_bss *escan_bss_tail = NULL;
2335	struct escan_bss *result;
2336
2337	d_info = (escan_wksp_t*)malloc(sizeof(escan_wksp_t));
2338
2339	escan_open_eventfd();
2340
2341	if (d_info->event_fd == -1) {
2342		return -1;
2343	}
2344
2345	fd = d_info->event_fd;
2346
2347	FD_ZERO(&fdset);
2348	FD_SET(fd, &fdset);
2349
2350	pkt = d_info->packet;
2351	len = sizeof(d_info->packet);
2352
2353	tv.tv_sec = WL_EVENT_TIMEOUT;
2354	tv.tv_usec = 0;
2355
2356	/* listen to data availible on all sockets */
2357	while ((retval = select(fd+1, &fdset, NULL, NULL, &tv)) > 0) {
2358		bcm_event_t *pvt_data;
2359		uint32 evt_type;
2360		uint32 status;
2361
2362		if (recv(fd, pkt, len, 0) <= 0)
2363			continue;
2364
2365		pvt_data = (bcm_event_t *)(pkt + IFNAMSIZ);
2366		evt_type = ntoh32(pvt_data->event.event_type);
2367
2368		if (evt_type == WLC_E_ESCAN_RESULT) {
2369			escan_data = (wl_escan_result_t*)(pvt_data + 1);
2370			status = ntoh32(pvt_data->event.status);
2371
2372			if (status == WLC_E_STATUS_PARTIAL) {
2373				wl_bss_info_t *bi = &escan_data->bss_info[0];
2374				wl_bss_info_t *bss = NULL;
2375
2376				/* check if we've received info of same BSSID */
2377				for (result = escan_bss_head; result; result = result->next) {
2378					bss = result->bss;
2379
2380					if (!memcmp(bi->BSSID.octet, bss->BSSID.octet,
2381						ETHER_ADDR_LEN) &&
2382						CHSPEC_BAND(bi->chanspec) ==
2383						CHSPEC_BAND(bss->chanspec) &&
2384						bi->SSID_len == bss->SSID_len &&
2385						!memcmp(bi->SSID, bss->SSID, bi->SSID_len))
2386						break;
2387					}
2388
2389				if (!result) {
2390					/* New BSS. Allocate memory and save it */
2391					struct escan_bss *ebss = (struct escan_bss *)malloc(
2392						OFFSETOF(struct escan_bss, bss)	+ bi->length);
2393
2394					if (!ebss) {
2395						dbg("can't allocate memory for bss");
2396						goto exit;
2397					}
2398
2399					ebss->next = NULL;
2400					memcpy(&ebss->bss, bi, bi->length);
2401					if (escan_bss_tail) {
2402						escan_bss_tail->next = ebss;
2403					}
2404					else {
2405						escan_bss_head = ebss;
2406					}
2407					escan_bss_tail = ebss;
2408				}
2409				else if (bi->RSSI != WLC_RSSI_INVALID) {
2410					/* We've got this BSS. Update rssi if necessary */
2411					if (((bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) ==
2412						(bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL)) &&
2413					    ((bss->RSSI == WLC_RSSI_INVALID) ||
2414						(bss->RSSI < bi->RSSI))) {
2415						/* preserve max RSSI if the measurements are
2416						 * both on-channel or both off-channel
2417						 */
2418						bss->RSSI = bi->RSSI;
2419						bss->SNR = bi->SNR;
2420						bss->phy_noise = bi->phy_noise;
2421					} else if ((bi->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) &&
2422						(bss->flags & WL_BSS_FLAGS_RSSI_ONCHANNEL) == 0) {
2423						/* preserve the on-channel rssi measurement
2424						 * if the new measurement is off channel
2425						*/
2426						bss->RSSI = bi->RSSI;
2427						bss->SNR = bi->SNR;
2428						bss->phy_noise = bi->phy_noise;
2429						bss->flags |= WL_BSS_FLAGS_RSSI_ONCHANNEL;
2430					}
2431				}
2432			}
2433			else if (status == WLC_E_STATUS_SUCCESS) {
2434				/* Escan finished. Let's go dump the results. */
2435				break;
2436			}
2437			else {
2438				dbg("sync_id: %d, status:%d, misc. error/abort\n",
2439					escan_data->sync_id, status);
2440				goto exit;
2441			}
2442		}
2443	}
2444
2445	if (retval > 0) {
2446		wl_scan_results_t* s_result = (wl_scan_results_t*)scan_buf;
2447		wl_bss_info_t *bi = s_result->bss_info;
2448		wl_bss_info_t *bss;
2449
2450		s_result->count = 0;
2451		len = buf_len - WL_SCAN_RESULTS_FIXED_SIZE;
2452
2453		for (result = escan_bss_head; result; result = result->next) {
2454			bss = result->bss;
2455			if (buf_len < bss->length) {
2456				dbg("Memory not enough for scan results\n");
2457				break;
2458			}
2459			memcpy(bi, bss, bss->length);
2460			bi = (wl_bss_info_t*)((int8*)bi + bss->length);
2461			len -= bss->length;
2462			s_result->count++;
2463		}
2464	} else if (retval == 0) {
2465		dbg("Scan timeout!\n");
2466	} else {
2467		dbg("Receive scan results failed!\n");
2468	}
2469
2470exit:
2471	if (d_info) {
2472		if (d_info->event_fd != -1) {
2473			close(d_info->event_fd);
2474			d_info->event_fd = -1;
2475		}
2476
2477		free(d_info);
2478	}
2479
2480	/* free scan results */
2481	result = escan_bss_head;
2482	while (result) {
2483		struct escan_bss *tmp = result->next;
2484		free(result);
2485		result = tmp;
2486	}
2487
2488	return (retval > 0) ? BCME_OK : BCME_ERROR;
2489}
2490
2491int wlcscan_core_escan(char *ofile, char *wif)
2492{
2493	int ret, i, k, left, ht_extcha;
2494	int retval = 0, ap_count = 0, idx_same = -1, count = 0;
2495	unsigned char *bssidp;
2496	char *info_b;
2497	unsigned char rate;
2498	unsigned char bssid[6];
2499	char macstr[18];
2500	char ure_mac[18];
2501	char ssid_str[256];
2502	wl_scan_results_t *result;
2503	wl_bss_info_t *info;
2504	wl_bss_info_107_t *old_info;
2505	struct bss_ie_hdr *ie;
2506	NDIS_802_11_NETWORK_TYPE NetWorkType;
2507	struct maclist *authorized;
2508	int maclist_size;
2509	int max_sta_count = 128;
2510	int wl_authorized = 0;
2511	wl_escan_params_t *params = NULL;
2512	int params_size = WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_escan_params_t, params) + NUMCHANS * sizeof(uint16);
2513	FILE *fp;
2514	int org_scan_time = 20, scan_time = 40;
2515
2516	params = (wl_escan_params_t*)malloc(params_size);
2517	if (params == NULL)
2518		return retval;
2519
2520	memset(params, 0, params_size);
2521	params->params.bss_type = DOT11_BSSTYPE_INFRASTRUCTURE;
2522	memcpy(&params->params.bssid, &ether_bcast, ETHER_ADDR_LEN);
2523	params->params.scan_type = -1;
2524	params->params.nprobes = -1;
2525	params->params.active_time = -1;
2526	params->params.passive_time = -1;
2527	params->params.home_time = -1;
2528	params->params.channel_num = 0;
2529
2530	params->version = htod32(ESCAN_REQ_VERSION);
2531	params->action = htod16(WL_SCAN_ACTION_START);
2532
2533	srand((unsigned int)uptime());
2534	params->sync_id = htod16(rand() & 0xffff);
2535
2536	params_size += OFFSETOF(wl_escan_params_t, params);
2537
2538	/* extend scan channel time to get more AP probe resp */
2539	wl_ioctl(wif, WLC_GET_SCAN_CHANNEL_TIME, &org_scan_time, sizeof(org_scan_time));
2540	if (org_scan_time < scan_time)
2541		wl_ioctl(wif, WLC_SET_SCAN_CHANNEL_TIME, &scan_time, sizeof(scan_time));
2542
2543	while ((ret = wl_iovar_set(wif, "escan", params, params_size)) < 0 &&
2544				count++ < 2) {
2545		dbg("[rc] set escan command failed, retry %d\n", count);
2546		sleep(1);
2547	}
2548
2549	free(params);
2550
2551	/* restore original scan channel time */
2552	wl_ioctl(wif, WLC_SET_SCAN_CHANNEL_TIME, &org_scan_time, sizeof(org_scan_time));
2553
2554	if (ret == 0) {
2555		ret = get_scan_escan(scan_result, WLC_SCAN_RESULT_BUF_LEN);
2556
2557		if (ret == 0)
2558		{
2559			result = (wl_scan_results_t *)scan_result;
2560
2561			info = &(result->bss_info[0]);
2562
2563			/* Convert version 107 to 109 */
2564			if (dtoh32(info->version) == LEGACY_WL_BSS_INFO_VERSION) {
2565				old_info = (wl_bss_info_107_t *)info;
2566				info->chanspec = CH20MHZ_CHSPEC(old_info->channel);
2567				info->ie_length = old_info->ie_length;
2568				info->ie_offset = sizeof(wl_bss_info_107_t);
2569			}
2570
2571			info_b = (char *) info;
2572
2573			for (i = 0; i < result->count; i++)
2574			{
2575				if (info->SSID_len > 32/* || info->SSID_len == 0*/)
2576					goto next_info;
2577				bssidp = (unsigned char *)&info->BSSID;
2578				sprintf(macstr, "%02X:%02X:%02X:%02X:%02X:%02X",
2579										(unsigned char)bssidp[0],
2580										(unsigned char)bssidp[1],
2581										(unsigned char)bssidp[2],
2582										(unsigned char)bssidp[3],
2583										(unsigned char)bssidp[4],
2584										(unsigned char)bssidp[5]);
2585
2586				idx_same = -1;
2587				for (k = 0; k < ap_count; k++) {
2588					/* deal with old version of Broadcom Multiple SSID
2589						(share the same BSSID) */
2590					if (strcmp(apinfos[k].BSSID, macstr) == 0 &&
2591						strcmp(apinfos[k].SSID, (const char *) info->SSID) == 0) {
2592						idx_same = k;
2593						break;
2594					}
2595				}
2596
2597				if (idx_same != -1)
2598				{
2599					if (info->RSSI >= -50)
2600						apinfos[idx_same].RSSI_Quality = 100;
2601					else if (info->RSSI >= -80)	// between -50 ~ -80dbm
2602						apinfos[idx_same].RSSI_Quality = (int)(24 + ((info->RSSI + 80) * 26)/10);
2603					else if (info->RSSI >= -90)	// between -80 ~ -90dbm
2604						apinfos[idx_same].RSSI_Quality = (int)(((info->RSSI + 90) * 26)/10);
2605					else					// < -84 dbm
2606						apinfos[idx_same].RSSI_Quality = 0;
2607				}
2608				else
2609				{
2610					strcpy(apinfos[ap_count].BSSID, macstr);
2611//					strcpy(apinfos[ap_count].SSID, info->SSID);
2612					memset(apinfos[ap_count].SSID, 0x0, 33);
2613					memcpy(apinfos[ap_count].SSID, info->SSID, info->SSID_len);
2614					apinfos[ap_count].channel = (uint8)(info->chanspec & WL_CHANSPEC_CHAN_MASK);
2615					if (info->ctl_ch == 0)
2616					{
2617						apinfos[ap_count].ctl_ch = apinfos[ap_count].channel;
2618					} else
2619					{
2620						apinfos[ap_count].ctl_ch = info->ctl_ch;
2621					}
2622
2623					if (info->RSSI >= -50)
2624						apinfos[ap_count].RSSI_Quality = 100;
2625					else if (info->RSSI >= -80)	// between -50 ~ -80dbm
2626						apinfos[ap_count].RSSI_Quality = (int)(24 + ((info->RSSI + 80) * 26)/10);
2627					else if (info->RSSI >= -90)	// between -80 ~ -90dbm
2628						apinfos[ap_count].RSSI_Quality = (int)(((info->RSSI + 90) * 26)/10);
2629					else					// < -84 dbm
2630						apinfos[ap_count].RSSI_Quality = 0;
2631
2632					if ((info->capability & 0x10) == 0x10)
2633						apinfos[ap_count].wep = 1;
2634					else
2635						apinfos[ap_count].wep = 0;
2636					apinfos[ap_count].wpa = 0;
2637
2638/*
2639					unsigned char *RATESET = &info->rateset;
2640					for (k = 0; k < 18; k++)
2641						dbg("%02x ", (unsigned char)RATESET[k]);
2642					dbg("\n");
2643*/
2644
2645					NetWorkType = Ndis802_11DS;
2646					if ((uint8)(info->chanspec & WL_CHANSPEC_CHAN_MASK) <= 14)
2647					{
2648						for (k = 0; k < info->rateset.count; k++)
2649						{
2650							rate = info->rateset.rates[k] & 0x7f;	// Mask out basic rate set bit
2651							if ((rate == 2) || (rate == 4) || (rate == 11) || (rate == 22))
2652								continue;
2653							else
2654							{
2655								NetWorkType = Ndis802_11OFDM24;
2656								break;
2657							}
2658						}
2659					}
2660					else
2661						NetWorkType = Ndis802_11OFDM5;
2662
2663					if (info->n_cap)
2664					{
2665						if (NetWorkType == Ndis802_11OFDM5)
2666						{
2667#ifdef RTCONFIG_BCMWL6
2668							if (info->vht_cap)
2669								NetWorkType = Ndis802_11OFDM5_VHT;
2670							else
2671#endif
2672								NetWorkType = Ndis802_11OFDM5_N;
2673						}
2674						else
2675							NetWorkType = Ndis802_11OFDM24_N;
2676					}
2677
2678					apinfos[ap_count].NetworkType = NetWorkType;
2679
2680					ap_count++;
2681
2682					if (ap_count >= MAX_NUMBER_OF_APINFO)
2683						break;
2684				}
2685
2686				ie = (struct bss_ie_hdr *) ((unsigned char *) info + sizeof(*info));
2687				for (left = info->ie_length; left > 0; // look for RSN IE first
2688					left -= (ie->len + 2), ie = (struct bss_ie_hdr *) ((unsigned char *) ie + 2 + ie->len))
2689				{
2690					if (ie->elem_id != DOT11_MNG_RSN_ID)
2691						continue;
2692
2693					if (wpa_parse_wpa_ie(&ie->elem_id, ie->len + 2, &apinfos[ap_count - 1].wid) == 0)
2694					{
2695						apinfos[ap_count-1].wpa = 1;
2696						goto next_info;
2697					}
2698				}
2699
2700				ie = (struct bss_ie_hdr *) ((unsigned char *) info + sizeof(*info));
2701				for (left = info->ie_length; left > 0; // then look for WPA IE
2702					left -= (ie->len + 2), ie = (struct bss_ie_hdr *) ((unsigned char *) ie + 2 + ie->len))
2703				{
2704					if (ie->elem_id != DOT11_MNG_WPA_ID)
2705						continue;
2706
2707					if (wpa_parse_wpa_ie(&ie->elem_id, ie->len + 2, &apinfos[ap_count-1].wid) == 0)
2708					{
2709						apinfos[ap_count-1].wpa = 1;
2710						break;
2711					}
2712				}
2713
2714next_info:
2715				info = (wl_bss_info_t *) ((unsigned char *) info + info->length);
2716			}
2717		}
2718	}
2719
2720	/* Print scanning result to console */
2721	if (ap_count == 0) {
2722		dbg("[wlc] No AP found!\n");
2723	} else {
2724		printf("%-4s%4s%-33s%-18s%-9s%-16s%-9s%8s%3s%3s\n",
2725				"idx", "CH ", "SSID", "BSSID", "Enc", "Auth", "Siganl(%)", "W-Mode", "CC", "EC");
2726		for (k = 0; k < ap_count; k++)
2727		{
2728			printf("%2d. ", k + 1);
2729			printf("%3d ", apinfos[k].ctl_ch);
2730			printf("%-33s", apinfos[k].SSID);
2731			printf("%-18s", apinfos[k].BSSID);
2732
2733			if (apinfos[k].wpa == 1)
2734				printf("%-9s%-16s", wpa_cipher_txt(apinfos[k].wid.pairwise_cipher), wpa_key_mgmt_txt(apinfos[k].wid.key_mgmt, apinfos[k].wid.proto));
2735			else if (apinfos[k].wep == 1)
2736				printf("WEP      Unknown         ");
2737			else
2738				printf("NONE     Open System     ");
2739			printf("%9d ", apinfos[k].RSSI_Quality);
2740
2741			if (apinfos[k].NetworkType == Ndis802_11FH || apinfos[k].NetworkType == Ndis802_11DS)
2742				printf("%-7s", "11b");
2743			else if (apinfos[k].NetworkType == Ndis802_11OFDM5)
2744				printf("%-7s", "11a");
2745			else if (apinfos[k].NetworkType == Ndis802_11OFDM5_VHT)
2746				printf("%-7s", "11ac");
2747			else if (apinfos[k].NetworkType == Ndis802_11OFDM5_N)
2748				printf("%-7s", "11a/n");
2749			else if (apinfos[k].NetworkType == Ndis802_11OFDM24)
2750				printf("%-7s", "11b/g");
2751			else if (apinfos[k].NetworkType == Ndis802_11OFDM24_N)
2752				printf("%-7s", "11b/g/n");
2753			else
2754				printf("%-7s", "unknown");
2755
2756			printf("%3d", apinfos[k].ctl_ch);
2757
2758			if (	((apinfos[k].NetworkType == Ndis802_11OFDM5_VHT) ||
2759				 (apinfos[k].NetworkType == Ndis802_11OFDM5_N) ||
2760				 (apinfos[k].NetworkType == Ndis802_11OFDM24_N)) &&
2761					(apinfos[k].channel != apinfos[k].ctl_ch)) {
2762				if (apinfos[k].ctl_ch < apinfos[k].channel)
2763					ht_extcha = 1;
2764				else
2765					ht_extcha = 0;
2766
2767				printf("%3d", ht_extcha);
2768			}
2769
2770			printf("\n");
2771		}
2772	}
2773
2774	ret = wl_ioctl(wif, WLC_GET_BSSID, bssid, sizeof(bssid));
2775	memset(ure_mac, 0x0, 18);
2776	if (!ret) {
2777		if (!(!bssid[0] && !bssid[1] && !bssid[2] && !bssid[3] && !bssid[4] && !bssid[5])) {
2778			sprintf(ure_mac, "%02X:%02X:%02X:%02X:%02X:%02X",
2779										(unsigned char)bssid[0],
2780										(unsigned char)bssid[1],
2781										(unsigned char)bssid[2],
2782										(unsigned char)bssid[3],
2783										(unsigned char)bssid[4],
2784										(unsigned char)bssid[5]);
2785		}
2786	}
2787
2788	if (strstr(nvram_safe_get(wlc_nvname("akm")), "psk")) {
2789		maclist_size = sizeof(authorized->count) + max_sta_count * sizeof(struct ether_addr);
2790		authorized = malloc(maclist_size);
2791
2792		// query wl for authorized sta list
2793		strcpy((char*)authorized, "autho_sta_list");
2794		if (!wl_ioctl(wif, WLC_GET_VAR, authorized, maclist_size)) {
2795			if (authorized->count > 0) wl_authorized = 1;
2796		}
2797
2798		if (authorized) free(authorized);
2799	}
2800
2801	/* Print scanning result to web format */
2802	if (ap_count > 0) {
2803		/* write pid */
2804		if ((fp = fopen(ofile, "a")) == NULL) {
2805			printf("[wlcscan] Output %s error\n", ofile);
2806		} else {
2807			for (i = 0; i < ap_count; i++) {
2808				/*if (apinfos[i].ctl_ch < 0 ) {
2809					fprintf(fp, "\"ERR_BNAD\",");
2810				} else */if (apinfos[i].ctl_ch > 0 &&
2811							 apinfos[i].ctl_ch < 14) {
2812					fprintf(fp, "\"2G\",");
2813				} else if (apinfos[i].ctl_ch > 14 &&
2814							 apinfos[i].ctl_ch < 166) {
2815					fprintf(fp, "\"5G\",");
2816				} else {
2817					fprintf(fp, "\"ERR_BNAD\",");
2818				}
2819
2820				if (strlen(apinfos[i].SSID) == 0) {
2821					fprintf(fp, "\"\",");
2822				} else {
2823					memset(ssid_str, 0, sizeof(ssid_str));
2824					char_to_ascii(ssid_str, apinfos[i].SSID);
2825					fprintf(fp, "\"%s\",", ssid_str);
2826				}
2827
2828				fprintf(fp, "\"%d\",", apinfos[i].ctl_ch);
2829
2830				if (apinfos[i].wpa == 1) {
2831					if (apinfos[i].wid.key_mgmt == WPA_KEY_MGMT_IEEE8021X_)
2832						fprintf(fp, "\"%s\",", "WPA-Enterprise");
2833					else if (apinfos[i].wid.key_mgmt == WPA_KEY_MGMT_IEEE8021X2_)
2834						fprintf(fp, "\"%s\",", "WPA2-Enterprise");
2835					else if (apinfos[i].wid.key_mgmt == WPA_KEY_MGMT_PSK_)
2836						fprintf(fp, "\"%s\",", "WPA-Personal");
2837					else if (apinfos[i].wid.key_mgmt == WPA_KEY_MGMT_PSK2_)
2838						fprintf(fp, "\"%s\",", "WPA2-Personal");
2839					else if (apinfos[i].wid.key_mgmt == WPA_KEY_MGMT_NONE_)
2840						fprintf(fp, "\"%s\",", "NONE");
2841					else if (apinfos[i].wid.key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA_)
2842						fprintf(fp, "\"%s\",", "IEEE 802.1X");
2843					else
2844						fprintf(fp, "\"%s\",", "Unknown");
2845				} else if (apinfos[i].wep == 1) {
2846					fprintf(fp, "\"%s\",", "Unknown");
2847				} else {
2848					fprintf(fp, "\"%s\",", "Open System");
2849				}
2850
2851				if (apinfos[i].wpa == 1) {
2852					if (apinfos[i].wid.pairwise_cipher == WPA_CIPHER_NONE_)
2853						fprintf(fp, "\"%s\",", "NONE");
2854					else if (apinfos[i].wid.pairwise_cipher == WPA_CIPHER_WEP40_)
2855						fprintf(fp, "\"%s\",", "WEP");
2856					else if (apinfos[i].wid.pairwise_cipher == WPA_CIPHER_WEP104_)
2857						fprintf(fp, "\"%s\",", "WEP");
2858					else if (apinfos[i].wid.pairwise_cipher == WPA_CIPHER_TKIP_)
2859						fprintf(fp, "\"%s\",", "TKIP");
2860					else if (apinfos[i].wid.pairwise_cipher == WPA_CIPHER_CCMP_)
2861						fprintf(fp, "\"%s\",", "AES");
2862					else if (apinfos[i].wid.pairwise_cipher == (WPA_CIPHER_TKIP_|WPA_CIPHER_CCMP_))
2863						fprintf(fp, "\"%s\",", "TKIP+AES");
2864					else
2865						fprintf(fp, "\"%s\",", "Unknown");
2866				} else if (apinfos[i].wep == 1) {
2867					fprintf(fp, "\"%s\",", "WEP");
2868				} else {
2869					fprintf(fp, "\"%s\",", "NONE");
2870				}
2871
2872				fprintf(fp, "\"%d\",", apinfos[i].RSSI_Quality);
2873				fprintf(fp, "\"%s\",", apinfos[i].BSSID);
2874
2875				if (apinfos[i].NetworkType == Ndis802_11FH || apinfos[i].NetworkType == Ndis802_11DS)
2876					fprintf(fp, "\"%s\",", "b");
2877				else if (apinfos[i].NetworkType == Ndis802_11OFDM5)
2878					fprintf(fp, "\"%s\",", "a");
2879				else if (apinfos[i].NetworkType == Ndis802_11OFDM5_N)
2880					fprintf(fp, "\"%s\",", "an");
2881				else if (apinfos[i].NetworkType == Ndis802_11OFDM5_VHT)
2882					fprintf(fp, "\"%s\",", "ac");
2883				else if (apinfos[i].NetworkType == Ndis802_11OFDM24)
2884					fprintf(fp, "\"%s\",", "bg");
2885				else if (apinfos[i].NetworkType == Ndis802_11OFDM24_N)
2886					fprintf(fp, "\"%s\",", "bgn");
2887				else
2888					fprintf(fp, "\"%s\",", "");
2889
2890				if (strcmp(nvram_safe_get(wlc_nvname("ssid")), apinfos[i].SSID)) {
2891					if (strcmp(apinfos[i].SSID, ""))
2892						fprintf(fp, "\"%s\"", "0");				// none
2893					else if (!strcmp(ure_mac, apinfos[i].BSSID)) {
2894						// hidden AP (null SSID)
2895						if (strstr(nvram_safe_get(wlc_nvname("akm")), "psk")) {
2896							if (wl_authorized) {
2897								// in profile, connected
2898								fprintf(fp, "\"%s\"", "4");
2899							} else {
2900								// in profile, connecting
2901								fprintf(fp, "\"%s\"", "5");
2902							}
2903						} else {
2904							// in profile, connected
2905							fprintf(fp, "\"%s\"", "4");
2906						}
2907					} else {
2908						// hidden AP (null SSID)
2909						fprintf(fp, "\"%s\"", "0");				// none
2910					}
2911				} else if (!strcmp(nvram_safe_get(wlc_nvname("ssid")), apinfos[i].SSID)) {
2912					if (!strlen(ure_mac)) {
2913						// in profile, disconnected
2914						fprintf(fp, "\"%s\",", "1");
2915					} else if (!strcmp(ure_mac, apinfos[i].BSSID)) {
2916						if (strstr(nvram_safe_get(wlc_nvname("akm")), "psk")) {
2917							if (wl_authorized) {
2918								// in profile, connected
2919								fprintf(fp, "\"%s\"", "2");
2920							} else {
2921								// in profile, connecting
2922								fprintf(fp, "\"%s\"", "3");
2923							}
2924						} else {
2925							// in profile, connected
2926							fprintf(fp, "\"%s\"", "2");
2927						}
2928					} else {
2929						fprintf(fp, "\"%s\"", "0");				// impossible...
2930					}
2931				} else {
2932					// wl0_ssid is empty
2933					fprintf(fp, "\"%s\"", "0");
2934				}
2935
2936				if (i == ap_count - 1) {
2937					fprintf(fp, "\n");
2938				} else {
2939					fprintf(fp, "\n");
2940				}
2941			}	/* for */
2942			fclose(fp);
2943		}
2944	}	/* if */
2945
2946	return retval;
2947}
2948#endif
2949
2950#ifdef RTCONFIG_WIRELESSREPEATER
2951/*
2952 *  Return value:
2953 *  	2 = successfully connected to parent AP
2954 */
2955int get_wlc_status(char *wif)
2956{
2957	char ure_mac[18];
2958	unsigned char bssid[6];
2959	struct maclist *authorized;
2960	int maclist_size;
2961	int max_sta_count = 128;
2962	int wl_authorized = 0;
2963	int wl_associated = 0;
2964	int wl_psk = 0;
2965	wlc_ssid_t wst = {0, ""};
2966
2967	wl_psk = strstr(nvram_safe_get(wlc_nvname("akm")), "psk") ? 1 : 0;
2968
2969	if (wl_ioctl(wif, WLC_GET_SSID, &wst, sizeof(wst))) {
2970		dbg("[wlc] WLC_GET_SSID error\n");
2971		goto wl_ioctl_error;
2972	}
2973
2974	memset(ure_mac, 0x0, 18);
2975	if (!wl_ioctl(wif, WLC_GET_BSSID, bssid, sizeof(bssid))) {
2976		if (!(!bssid[0] && !bssid[1] && !bssid[2] &&
2977				!bssid[3] && !bssid[4] && !bssid[5])) {
2978			wl_associated = 1;
2979			sprintf(ure_mac, "%02X:%02X:%02X:%02X:%02X:%02X",
2980					(unsigned char)bssid[0],
2981					(unsigned char)bssid[1],
2982					(unsigned char)bssid[2],
2983					(unsigned char)bssid[3],
2984					(unsigned char)bssid[4],
2985					(unsigned char)bssid[5]);
2986		}
2987	} else {
2988		dbg("[wlc] WLC_GET_BSSID error\n");
2989		goto wl_ioctl_error;
2990	}
2991
2992	if (wl_psk) {
2993		maclist_size = sizeof(authorized->count) +
2994							max_sta_count * sizeof(struct ether_addr);
2995		authorized = malloc(maclist_size);
2996
2997		if (authorized) {
2998			// query wl for authorized sta list
2999			strcpy((char*)authorized, "autho_sta_list");
3000
3001			if (!wl_ioctl(wif, WLC_GET_VAR, authorized, maclist_size)) {
3002				if (authorized->count > 0) wl_authorized = 1;
3003				free(authorized);
3004			} else {
3005				free(authorized);
3006				dbg("[wlc] Authorized failed\n");
3007				goto wl_ioctl_error;
3008			}
3009		}
3010	}
3011
3012	if (!wl_associated) {
3013		dbg("[wlc] not wl_associated\n");
3014	}
3015
3016	dbg("[wlc] wl-associated [%d]\n", wl_associated);
3017	dbg("[wlc] %s\n", wst.SSID);
3018	dbg("[wlc] %s\n", nvram_safe_get(wlc_nvname("ssid")));
3019
3020	if (wl_associated &&
3021		!strncmp((const char *) wst.SSID, nvram_safe_get(wlc_nvname("ssid")), wst.SSID_len)) {
3022		if (wl_psk) {
3023			if (wl_authorized) {
3024				dbg("[wlc] wl_authorized\n");
3025				return 2;
3026			} else {
3027				dbg("[wlc] not wl_authorized\n");
3028				return 1;
3029			}
3030		} else {
3031			dbg("[wlc] wl_psk:[%d]\n", wl_psk);
3032			return 2;
3033		}
3034	} else {
3035		dbg("[wlc] Not associated\n");
3036		return 0;
3037	}
3038
3039wl_ioctl_error:
3040	return 0;
3041}
3042
3043// TODO: wlcconnect_main
3044//	wireless ap monitor to connect to ap
3045//	when wlc_list, then connect to it according to priority
3046int wlcconnect_core(void)
3047{
3048	int ret = 0;
3049	char word[256], *next;
3050	unsigned char SEND_NULLDATA[]={ 0x73, 0x65, 0x6e, 0x64,
3051					0x5f, 0x6e, 0x75, 0x6c,
3052					0x6c, 0x64, 0x61, 0x74,
3053					0x61, 0x00, 0xff, 0xff,
3054					0xff, 0xff, 0xff, 0xff};
3055	unsigned char bssid[6];
3056	int unit = 0;
3057
3058	/* return WLC connection status */
3059	foreach (word, nvram_safe_get("wl_ifnames"), next) {
3060		// only one client in a system
3061		if (is_ure(unit)) {
3062			//dbg("[rc] [%s] is URE mode\n", word);
3063			memset(bssid, 0xff, 6);
3064			if (!wl_ioctl(word, WLC_GET_BSSID, bssid, sizeof(bssid))) {
3065				memcpy(SEND_NULLDATA + 14, bssid, 6);
3066
3067				// wl send_nulldata xx:xx:xx:xx:xx:xx
3068				wl_ioctl(word, WLC_SET_VAR, SEND_NULLDATA,
3069					sizeof(SEND_NULLDATA));
3070			}
3071
3072			ret = get_wlc_status(word);
3073			dbg("[wlc][%s] get_wlc_status:[%d]\n", word, ret);
3074
3075			break;
3076		}
3077
3078		unit++;
3079	}
3080
3081	return ret;
3082}
3083
3084#endif
3085
3086#if 0
3087bool
3088wl_check_assoc_scb(char *ifname)
3089{
3090	bool connected = TRUE;
3091	int result = 0;
3092	int ret = 0;
3093
3094	ret = wl_iovar_getint(ifname, "scb_assoced", &result);
3095	if (ret) {
3096		dbg("failed to get scb_assoced\n");
3097		return connected;
3098	}
3099
3100	connected = dtoh32(result) ? TRUE : FALSE;
3101	return connected;
3102}
3103
3104int
3105wl_phy_rssi_ant(char *ifname)
3106{
3107	char buf[WLC_IOCTL_MAXLEN];
3108	int ret = 0;
3109	uint i;
3110	wl_rssi_ant_t *rssi_ant_p;
3111
3112	if (!ifname)
3113		return -1;
3114
3115	memset(buf, 0, WLC_IOCTL_MAXLEN);
3116	strcpy(buf, "phy_rssi_ant");
3117
3118	if ((ret = wl_ioctl(ifname, WLC_GET_VAR, &buf[0], WLC_IOCTL_MAXLEN)) < 0)
3119		return ret;
3120
3121	rssi_ant_p = (wl_rssi_ant_t *)buf;
3122	rssi_ant_p->version = dtoh32(rssi_ant_p->version);
3123	rssi_ant_p->count = dtoh32(rssi_ant_p->count);
3124
3125	if (rssi_ant_p->count == 0) {
3126		dbg("not supported on this chip\n");
3127	} else {
3128		if ((rssi_ant_p->rssi_ant[0]) &&
3129		    (rssi_ant_p->rssi_ant[1] < -100) &&
3130		    ((rssi_ant_p->count > 2)?(rssi_ant_p->rssi_ant[2] < -100) : 1))
3131		{
3132			for (i = 0; i < rssi_ant_p->count; i++)
3133				dbg("rssi[%d] %d  ", i, rssi_ant_p->rssi_ant[i]);
3134			dbg("\n");
3135		}
3136	}
3137
3138	return ret;
3139}
3140#endif
3141
3142#ifdef RTAC3200
3143extern struct nvram_tuple router_defaults[];
3144
3145void
3146bsd_defaults(void)
3147{
3148	char extendno_org[14];
3149	int ext_num;
3150	char ext_commit_str[8];
3151	struct nvram_tuple *t;
3152
3153	if (!strlen(nvram_safe_get("extendno_org")) ||
3154		nvram_match("extendno_org", nvram_safe_get("extendno")))
3155		return;
3156
3157	strcpy(extendno_org, nvram_safe_get("extendno_org"));
3158	if (!strlen(extendno_org) ||
3159		sscanf(extendno_org, "%d-g%s", &ext_num, ext_commit_str) != 2)
3160		return;
3161
3162//	if (strcmp(rt_serialno, "378") || (ext_num >= 4120))
3163//		return;
3164
3165	for (t = router_defaults; t->name; t++)
3166		if (strstr(t->name, "bsd"))
3167			nvram_set(t->name, t->value);
3168}
3169#endif
3170
3171#ifdef RTCONFIG_BCMWL6
3172int
3173wl_check_chanspec()
3174{
3175	wl_uint32_list_t *list;
3176	chanspec_t c, chansp_40m;
3177	int ret = 0, i, count;
3178	char data_buf[WLC_IOCTL_MAXLEN];
3179	char chanbuf[CHANSPEC_STR_LEN];
3180	char word[256], *next;
3181	char tmp[256], tmp2[256], prefix[] = "wlXXXXXXXXXX_";
3182	int unit = 0;
3183	int match;
3184	int match_ctrl_ch;
3185	int match_40m_ch;
3186
3187	foreach (word, nvram_safe_get("wl_ifnames"), next) {
3188		snprintf(prefix, sizeof(prefix), "wl%d_", unit++);
3189		c = 0;
3190		chansp_40m = 0;
3191		match = 0;
3192		match_ctrl_ch = 0;
3193		match_40m_ch = 0;
3194
3195		if (!nvram_get_int(strcat_r(prefix, "chanspec", tmp)))
3196			continue;
3197
3198		memset(data_buf, 0, WLC_IOCTL_MAXLEN);
3199		ret = wl_iovar_getbuf(word, "chanspecs", &c, sizeof(chanspec_t),
3200			data_buf, WLC_IOCTL_MAXLEN);
3201		if (ret < 0) {
3202			dbg("failed to get valid chanspec list\n");
3203			continue;
3204		}
3205
3206		list = (wl_uint32_list_t *)data_buf;
3207		count = dtoh32(list->count);
3208
3209		if (!count) {
3210			dbg("number of valid chanspec is 0\n");
3211			continue;
3212		} else
3213		for (i = 0; i < count; i++) {
3214			c = (chanspec_t)dtoh32(list->element[i]);
3215
3216			if (!match &&
3217			   (c == wf_chspec_aton(nvram_safe_get(strcat_r(prefix, "chanspec", tmp))))) {
3218				match = 1;
3219				break;
3220			}
3221
3222			if (wf_chspec_ctlchan(c) == wf_chspec_ctlchan(wf_chspec_aton(nvram_safe_get(strcat_r(prefix, "chanspec", tmp))))) {
3223				if (!match_ctrl_ch)
3224					match_ctrl_ch = 1;
3225
3226				if (!match_40m_ch && CHSPEC_IS40(c)) {
3227					match_40m_ch = 1;
3228					chansp_40m = c;
3229				}
3230			}
3231		}
3232
3233		if (!match) {
3234			dbg("chanspec %s is invalid\n", nvram_safe_get(strcat_r(prefix, "chanspec", tmp)));
3235
3236			if (match_40m_ch) {
3237				dbg("downgraded to 40M chanspec\n");
3238				nvram_set(strcat_r(prefix, "chanspec", tmp), wf_chspec_ntoa(chansp_40m, chanbuf));
3239			} else if (match_ctrl_ch) {
3240				dbg("downgraded to 20M chanspec\n");
3241				nvram_set_int(strcat_r(prefix, "chanspec", tmp), wf_chspec_ctlchan(wf_chspec_aton(nvram_safe_get(strcat_r(prefix, "chanspec", tmp2)))));
3242			} else {
3243				dbg("downgraded to auto chanspec\n");
3244				nvram_set_int(strcat_r(prefix, "chanspec", tmp), 0);
3245				nvram_set_int(strcat_r(prefix, "bw", tmp), 0);
3246			}
3247		}
3248	}
3249
3250	return ret;
3251}
3252
3253#define CHANNEL_5G_BAND_GROUP(c) \
3254	(((c) < 52) ? 1 : (((c) < 100) ? 2 : (((c) < 149) ? 3 : 4)))
3255
3256void
3257wl_check_5g_band_group()
3258{
3259	wl_uint32_list_t *list;
3260	chanspec_t c;
3261	int ret = 0, i, count;
3262	char data_buf[WLC_IOCTL_MAXLEN];
3263	char word[256], *next;
3264	char tmp[100], tmp2[100], prefix[] = "wlXXXXXXXXXX_";
3265	int unit = 0;
3266	unsigned int band5grp;
3267
3268	foreach (word, nvram_safe_get("wl_ifnames"), next) {
3269		snprintf(prefix, sizeof(prefix), "wl%d_", unit++);
3270		c = 0;
3271
3272		if (unit == 1) continue;
3273
3274		memset(data_buf, 0, WLC_IOCTL_MAXLEN);
3275		ret = wl_iovar_getbuf(word, "chanspecs", &c, sizeof(chanspec_t),
3276			data_buf, WLC_IOCTL_MAXLEN);
3277		if (ret < 0) {
3278			dbg("failed to get valid chanspec list\n");
3279			continue;
3280		}
3281
3282		list = (wl_uint32_list_t *)data_buf;
3283		count = dtoh32(list->count);
3284
3285		if (!count) {
3286			dbg("number of valid chanspec is 0\n");
3287			continue;
3288		} else
3289			for (i = 0, band5grp = 0; i < count; i++) {
3290				c = (chanspec_t)dtoh32(list->element[i]);
3291				band5grp |= 1 << (CHANNEL_5G_BAND_GROUP(wf_chspec_ctlchan(c)) - 1);
3292			}
3293
3294		sprintf(tmp2, "%x", band5grp);
3295		nvram_set(strcat_r(prefix, "band5grp", tmp), tmp2);
3296	}
3297}
3298#endif
3299
3300#if defined(RTAC88U) || defined(RTAC3100) || defined(RTAC5300) || defined(RTAC5300R)
3301int wl_channel_valid(char *wif, int channel)
3302{
3303	int channels[MAXCHANNEL+1];
3304	wl_uint32_list_t *list = (wl_uint32_list_t *) channels;
3305	int i;
3306
3307	memset(channels, 0, sizeof(channels));
3308	list->count = htod32(MAXCHANNEL);
3309	if (wl_ioctl(wif, WLC_GET_VALID_CHANNELS , channels, sizeof(channels)) < 0)
3310	{
3311		dbg("error doing WLC_GET_VALID_CHANNELS\n");
3312		return 0;
3313	}
3314
3315	if (dtoh32(list->count) == 0)
3316		return 0;
3317
3318	for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++)
3319		if (channel == dtoh32(list->element[i]))
3320			return 1;
3321
3322	return 0;
3323}
3324
3325int wl_subband(char *wif, int idx)
3326{
3327	int count = 0;
3328	int band;
3329
3330	wl_ioctl(wif, WLC_GET_BAND, &band, sizeof(band));
3331	if (band != WLC_BAND_5G)
3332		return -1;
3333
3334	if (wl_channel_valid(wif, 36))
3335	{
3336		if (++count == idx)
3337			return 1;
3338	}
3339
3340	if (wl_channel_valid(wif, 52))
3341	{
3342		if (++count == idx)
3343			return 2;
3344	}
3345
3346	if (wl_channel_valid(wif, 100))
3347	{
3348		if (++count == idx)
3349			return 3;
3350	}
3351
3352	if (wl_channel_valid(wif, 149))
3353	{
3354		if (++count == idx)
3355			return 4;
3356	}
3357
3358	return -1;
3359}
3360#endif
3361