3 Copyright 2003, CyberTAN Inc. All Rights Reserved
5 This is UNPUBLISHED PROPRIETARY SOURCE CODE of CyberTAN Inc.
6 the contents of this file may not be disclosed to third parties,
7 copied or duplicated in any form without the prior written
8 permission of CyberTAN Inc.
10 This software should be used as a reference only, and it not
11 intended for production use!
13 THIS SOFTWARE IS OFFERED "AS IS", AND CYBERTAN GRANTS NO WARRANTIES OF ANY
14 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. CYBERTAN
15 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
16 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE
21 Copyright 2005, Broadcom Corporation
24 THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
25 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
26 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
27 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
33 Copyright (C) 2005 Felix Fietkau <nbd@vd-s.ath.cx>
38 Modified for Tomato Firmware
39 Portions, Copyright (C) 2006-2009 Jonathan Zarate
46 typedef u_int64_t u64
;
47 typedef u_int32_t u32
;
48 typedef u_int16_t u16
;
52 #include <linux/types.h>
53 #include <linux/sockios.h>
54 #include <linux/ethtool.h>
55 #include <sys/ioctl.h>
56 #include <net/if_arp.h>
57 #include <arpa/inet.h>
61 #include <bcmparams.h>
64 #ifndef WL_BSS_INFO_VERSION
65 #error WL_BSS_INFO_VERSION
67 #if WL_BSS_INFO_VERSION >= 108
73 static void set_lan_hostname(const char *wan_hostname
)
78 nvram_set("lan_hostname", wan_hostname
);
79 if ((wan_hostname
== NULL
) || (*wan_hostname
== 0)) {
80 /* derive from et0 mac address */
81 s
= nvram_get("et0macaddr");
82 if (s
&& strlen(s
) >= 17) {
84 sprintf(hostname
, "RT-%c%c%c%c%c%c%c%c%c%c%c%c",
85 s
[0], s
[1], s
[3], s
[4], s
[6], s
[7],
86 s
[9], s
[10], s
[12], s
[13], s
[15], s
[16]);
88 if ((f
= fopen("/proc/sys/kernel/hostname", "w"))) {
92 nvram_set("lan_hostname", hostname
);
96 if ((f
= fopen("/etc/hosts", "w"))) {
97 fprintf(f
, "127.0.0.1 localhost\n");
98 if ((s
= nvram_get("lan_ipaddr")) && (*s
))
99 fprintf(f
, "%s %s\n", s
, nvram_safe_get("lan_hostname"));
101 if (ipv6_enabled()) {
102 fprintf(f
, "::1 localhost\n");
103 s
= ipv6_router_address(NULL
);
104 if (*s
) fprintf(f
, "%s %s\n", s
, nvram_safe_get("lan_hostname"));
111 void set_host_domain_name(void)
115 s
= nvram_safe_get("wan_hostname");
116 sethostname(s
, strlen(s
));
119 s
= nvram_get("wan_domain");
120 if ((s
== NULL
) || (*s
== 0)) s
= nvram_safe_get("wan_get_domain");
121 setdomainname(s
, strlen(s
));
124 static int wlconf(char *ifname
, int unit
, int subunit
)
129 if (/* !wl_probe(ifname) && */ unit
>= 0) {
130 // validate nvram settings for wireless i/f
131 snprintf(wl
, sizeof(wl
), "--wl%d", unit
);
132 eval("nvram", "validate", wl
);
135 r
= eval("wlconf", ifname
, "up");
137 if (unit
>= 0 && subunit
<= 0) {
138 // setup primary wl interface
139 nvram_set("rrules_radio", "-1");
141 eval("wl", "-i", ifname
, "antdiv", nvram_safe_get(wl_nvname("antdiv", unit
, 0)));
142 eval("wl", "-i", ifname
, "txant", nvram_safe_get(wl_nvname("txant", unit
, 0)));
143 eval("wl", "-i", ifname
, "txpwr1", "-o", "-m", nvram_get_int(wl_nvname("txpwr", unit
, 0)) ? nvram_safe_get(wl_nvname("txpwr", unit
, 0)) : "-1");
144 eval("wl", "-i", ifname
, "interference", nvram_safe_get(wl_nvname("mitigation", unit
, 0)));
147 if (wl_client(unit
, subunit
)) {
148 if (nvram_match(wl_nvname("mode", unit
, subunit
), "wet")) {
149 ifconfig(ifname
, IFUP
|IFF_ALLMULTI
, NULL
, NULL
);
151 if (nvram_get_int(wl_nvname("radio", unit
, 0))) {
152 snprintf(wl
, sizeof(wl
), "%d", unit
);
153 xstart("radio", "join", wl
);
160 // -----------------------------------------------------------------------------
163 static void emf_mfdb_update(char *lan_ifname
, char *lan_port_ifname
, bool add
)
165 char word
[256], *next
;
168 /* Add/Delete MFDB entries corresponding to new interface */
169 foreach (word
, nvram_safe_get("emf_entry"), next
) {
171 mgrp
= strsep(&ifname
, ":");
173 if ((mgrp
== NULL
) || (ifname
== NULL
)) continue;
175 /* Add/Delete MFDB entry using the group addr and interface */
176 if (lan_port_ifname
== NULL
|| strcmp(lan_port_ifname
, ifname
) == 0) {
177 eval("emf", ((add
) ? "add" : "del"), "mfdb", lan_ifname
, mgrp
, ifname
);
182 static void emf_uffp_update(char *lan_ifname
, char *lan_port_ifname
, bool add
)
184 char word
[256], *next
;
187 /* Add/Delete UFFP entries corresponding to new interface */
188 foreach (word
, nvram_safe_get("emf_uffp_entry"), next
) {
191 if (ifname
== NULL
) continue;
193 /* Add/Delete UFFP entry for the interface */
194 if (lan_port_ifname
== NULL
|| strcmp(lan_port_ifname
, ifname
) == 0) {
195 eval("emf", ((add
) ? "add" : "del"), "uffp", lan_ifname
, ifname
);
200 static void emf_rtport_update(char *lan_ifname
, char *lan_port_ifname
, bool add
)
202 char word
[256], *next
;
205 /* Add/Delete RTPORT entries corresponding to new interface */
206 foreach (word
, nvram_safe_get("emf_rtport_entry"), next
) {
209 if (ifname
== NULL
) continue;
211 /* Add/Delete RTPORT entry for the interface */
212 if (lan_port_ifname
== NULL
|| strcmp(lan_port_ifname
, ifname
) == 0) {
213 eval("emf", ((add
) ? "add" : "del"), "rtport", lan_ifname
, ifname
);
218 static void start_emf(char *lan_ifname
)
221 eval("emf", "start", lan_ifname
);
223 /* Add the static MFDB entries */
224 emf_mfdb_update(lan_ifname
, NULL
, 1);
226 /* Add the UFFP entries */
227 emf_uffp_update(lan_ifname
, NULL
, 1);
229 /* Add the RTPORT entries */
230 emf_rtport_update(lan_ifname
, NULL
, 1);
233 static void stop_emf(char *lan_ifname
)
235 eval("emf", "stop", lan_ifname
);
236 eval("igs", "del", "bridge", lan_ifname
);
237 eval("emf", "del", "bridge", lan_ifname
);
241 // -----------------------------------------------------------------------------
243 /* Set initial QoS mode for all et interfaces that are up. */
244 void set_et_qos_mode(int sfd
)
249 struct ethtool_drvinfo info
;
251 qos
= (strcmp(nvram_safe_get("wl_wme"), "off") != 0);
252 for (i
= 1; i
<= DEV_NUMIFS
; i
++) {
254 if (ioctl(sfd
, SIOCGIFNAME
, &ifr
)) continue;
255 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
)) continue;
256 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) continue;
258 if (ioctl(sfd
, SIOCGIFFLAGS
, &ifr
)) continue;
259 /* if up (wan may not be up yet at this point) */
260 if (ifr
.ifr_flags
& IFF_UP
) {
261 ifrdata
= ifr
.ifr_data
;
262 memset(&info
, 0, sizeof(info
));
263 info
.cmd
= ETHTOOL_GDRVINFO
;
264 ifr
.ifr_data
= (caddr_t
)&info
;
265 if (ioctl(sfd
, SIOCETHTOOL
, &ifr
) >= 0) {
266 /* Set QoS for et & bcm57xx devices */
267 if (!strncmp(info
.driver
, "et", 2) ||
268 !strncmp(info
.driver
, "bcm57", 5)) {
269 ifr
.ifr_data
= (caddr_t
)&qos
;
270 ioctl(sfd
, SIOCSETCQOS
, &ifr
);
273 ifr
.ifr_data
= ifrdata
;
278 static void check_afterburner(void)
282 if (nvram_match("wl_afterburner", "off")) return;
283 if ((p
= nvram_get("boardflags")) == NULL
) return;
285 if (strcmp(p
, "0x0118") == 0) { // G 2.2, 3.0, 3.1
288 else if (strcmp(p
, "0x0188") == 0) { // G 2.0
291 else if (strcmp(p
, "0x2558") == 0) { // G 4.0, GL 1.0, 1.1
298 nvram_set("boardflags", p
);
300 if (!nvram_match("debug_abrst", "0")) {
311 bf = strtoul(p, &p, 0);
312 if ((*p == 0) && ((bf & BFL_AFTERBURNER) == 0)) {
313 sprintf(s, "0x%04lX", bf | BFL_AFTERBURNER);
314 nvram_set("boardflags", s);
321 char *lan_ifname
, *lan_ifnames
, *ifname
, *p
;
325 lan_ifname
= nvram_safe_get("lan_ifname");
326 if (strncmp(lan_ifname
, "br", 2) == 0) {
327 if ((lan_ifnames
= strdup(nvram_safe_get("lan_ifnames"))) != NULL
) {
329 while ((ifname
= strsep(&p
, " ")) != NULL
) {
330 while (*ifname
== ' ') ++ifname
;
331 if (*ifname
== 0) break;
333 unit
= -1; subunit
= -1;
335 // ignore disabled wl vifs
336 if (strncmp(ifname
, "wl", 2) == 0 && strchr(ifname
, '.')) {
338 snprintf(nv
, sizeof(nv
) - 1, "%s_bss_enabled", ifname
);
339 if (!nvram_get_int(nv
))
341 if (get_ifname_unit(ifname
, &unit
, &subunit
) < 0)
344 // get the instance number of the wl i/f
345 else if (wl_ioctl(ifname
, WLC_GET_INSTANCE
, &unit
, sizeof(unit
)))
348 is_client
|= wl_client(unit
, subunit
) && nvram_get_int(wl_nvname("radio", unit
, 0));
351 eval("wlconf", ifname
, "start"); /* start wl iface */
352 #endif // CONFIG_BCMWL5
358 else if (strcmp(lan_ifname
, "")) {
359 /* specific non-bridged lan iface */
360 eval("wlconf", lan_ifname
, "start");
362 #endif // CONFIG_BCMWL5
364 killall("wldist", SIGTERM
);
368 xstart("radio", "join");
371 static int set_wlmac(int idx
, int unit
, int subunit
, void *param
)
375 ifname
= nvram_safe_get(wl_nvname("ifname", unit
, subunit
));
377 // skip disabled wl vifs
378 if (strncmp(ifname
, "wl", 2) == 0 && strchr(ifname
, '.') &&
379 !nvram_get_int(wl_nvname("bss_enabled", unit
, subunit
)))
382 set_mac(ifname
, wl_nvname("macaddr", unit
, subunit
),
383 2 + unit
+ ((subunit
> 0) ? ((unit
+ 1) * 0x10 + subunit
) : 0));
389 void enable_ipv6(int enable
)
392 struct dirent
*dirent
;
395 if ((dir
= opendir("/proc/sys/net/ipv6/conf")) != NULL
) {
396 while ((dirent
= readdir(dir
)) != NULL
) {
397 sprintf(s
, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", dirent
->d_name
);
398 f_write_string(s
, enable
? "0" : "1", 0, 0);
404 void accept_ra(const char *ifname
)
408 sprintf(s
, "/proc/sys/net/ipv6/conf/%s/accept_ra", ifname
);
409 f_write_string(s
, "2", 0, 0);
411 sprintf(s
, "/proc/sys/net/ipv6/conf/%s/forwarding", ifname
);
412 f_write_string(s
, "2", 0, 0);
418 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
422 char *lan_ifnames
, *ifname
, *p
;
425 int unit
, subunit
, sta
;
429 foreach_wif(1, NULL
, set_wlmac
);
432 enable_ipv6(ipv6_enabled());
435 if ((sfd
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0) return;
437 lan_ifname
= strdup(nvram_safe_get("lan_ifname"));
438 if (strncmp(lan_ifname
, "br", 2) == 0) {
439 _dprintf("%s: setting up the bridge %s\n", __FUNCTION__
, lan_ifname
);
441 eval("brctl", "addbr", lan_ifname
);
442 eval("brctl", "setfd", lan_ifname
, "0");
443 eval("brctl", "stp", lan_ifname
, nvram_safe_get("lan_stp"));
446 if (nvram_get_int("emf_enable")) {
447 eval("emf", "add", "bridge", lan_ifname
);
448 eval("igs", "add", "bridge", lan_ifname
);
452 inet_aton(nvram_safe_get("lan_ipaddr"), (struct in_addr
*)&ip
);
456 if ((lan_ifnames
= strdup(nvram_safe_get("lan_ifnames"))) != NULL
) {
458 while ((ifname
= strsep(&p
, " ")) != NULL
) {
459 while (*ifname
== ' ') ++ifname
;
460 if (*ifname
== 0) break;
462 unit
= -1; subunit
= -1;
464 // ignore disabled wl vifs
465 if (strncmp(ifname
, "wl", 2) == 0 && strchr(ifname
, '.')) {
468 snprintf(nv
, sizeof(nv
) - 1, "%s_bss_enabled", ifname
);
469 if (!nvram_get_int(nv
))
471 if (get_ifname_unit(ifname
, &unit
, &subunit
) < 0)
475 wl_ioctl(ifname
, WLC_GET_INSTANCE
, &unit
, sizeof(unit
));
477 // bring up interface
478 if (ifconfig(ifname
, IFUP
|IFF_ALLMULTI
, NULL
, NULL
) != 0) continue;
480 // set the logical bridge address to that of the first interface
481 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
483 (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0 &&
484 memcmp(ifr
.ifr_hwaddr
.sa_data
, "\0\0\0\0\0\0", ETHER_ADDR_LEN
) == 0)) {
485 strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
486 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) {
487 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
488 ifr
.ifr_hwaddr
.sa_family
= ARPHRD_ETHER
;
489 _dprintf("%s: setting MAC of %s bridge to %s\n", __FUNCTION__
,
490 ifr
.ifr_name
, ether_etoa(ifr
.ifr_hwaddr
.sa_data
, eabuf
));
491 ioctl(sfd
, SIOCSIFHWADDR
, &ifr
);
496 if (wlconf(ifname
, unit
, subunit
) == 0) {
497 const char *mode
= nvram_safe_get(wl_nvname("mode", unit
, subunit
));
499 if (strcmp(mode
, "wet") == 0) {
500 // Enable host DHCP relay
501 if (nvram_get_int("dhcp_relay")) {
502 wl_iovar_set(ifname
, "wet_host_mac", ifr
.ifr_hwaddr
.sa_data
, ETHER_ADDR_LEN
);
503 wl_iovar_setint(ifname
, "wet_host_ipv4", ip
);
507 sta
|= (strcmp(mode
, "sta") == 0);
508 if ((strcmp(mode
, "ap") != 0) && (strcmp(mode
, "wet") != 0)) continue;
510 eval("brctl", "addif", lan_ifname
, ifname
);
512 if (nvram_get_int("emf_enable"))
513 eval("emf", "add", "iface", lan_ifname
, ifname
);
517 if ((nvram_get_int("wan_islan")) &&
518 ((get_wan_proto() == WP_DISABLED
) || (sta
))) {
519 ifname
= nvram_get("wan_ifnameX");
520 if (ifconfig(ifname
, IFUP
, NULL
, NULL
) == 0)
521 eval("brctl", "addif", lan_ifname
, ifname
);
527 // --- this shouldn't happen ---
528 else if (*lan_ifname
) {
529 ifconfig(lan_ifname
, IFUP
, NULL
, NULL
);
530 wlconf(lan_ifname
, -1, -1);
538 // Get current LAN hardware address
539 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
540 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) nvram_set("lan_hwaddr", ether_etoa(ifr
.ifr_hwaddr
.sa_data
, eabuf
));
542 // Set initial QoS mode for LAN ports
543 set_et_qos_mode(sfd
);
547 // bring up and configure LAN interface
548 ifconfig(lan_ifname
, IFUP
, nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_netmask"));
553 set_lan_hostname(nvram_safe_get("wan_hostname"));
555 if (get_wan_proto() == WP_DISABLED
) {
556 char *gateway
= nvram_safe_get("lan_gateway") ;
557 if ((*gateway
) && (strcmp(gateway
, "0.0.0.0") != 0)) {
559 while ((route_add(lan_ifname
, 0, "0.0.0.0", gateway
, "0.0.0.0") != 0) && (tries
-- > 0)) sleep(1);
560 _dprintf("%s: add gateway=%s tries=%d\n", __FUNCTION__
, gateway
, tries
);
569 if (nvram_get_int("emf_enable")) start_emf(lan_ifname
);
574 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
579 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
582 char *lan_ifnames
, *p
, *ifname
;
584 lan_ifname
= nvram_safe_get("lan_ifname");
585 ifconfig(lan_ifname
, 0, NULL
, NULL
);
591 if (strncmp(lan_ifname
, "br", 2) == 0) {
593 stop_emf(lan_ifname
);
595 if ((lan_ifnames
= strdup(nvram_safe_get("lan_ifnames"))) != NULL
) {
597 while ((ifname
= strsep(&p
, " ")) != NULL
) {
598 while (*ifname
== ' ') ++ifname
;
599 if (*ifname
== 0) break;
600 eval("wlconf", ifname
, "down");
601 ifconfig(ifname
, 0, NULL
, NULL
);
602 eval("brctl", "delif", lan_ifname
, ifname
);
606 eval("brctl", "delbr", lan_ifname
);
608 else if (*lan_ifname
) {
609 eval("wlconf", lan_ifname
, "down");
612 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
616 void do_static_routes(int add
)
620 char *dest
, *mask
, *gateway
, *metric
, *ifname
;
623 if ((buf
= strdup(nvram_safe_get(add
? "routes_static" : "routes_static_saved"))) == NULL
) return;
624 if (add
) nvram_set("routes_static_saved", buf
);
625 else nvram_unset("routes_static_saved");
627 while ((q
= strsep(&p
, ">")) != NULL
) {
628 if (vstrsep(q
, "<", &dest
, &gateway
, &mask
, &metric
, &ifname
) != 5) continue;
629 ifname
= nvram_safe_get((*ifname
== 'L') ? "lan_ifname" :
630 ((*ifname
== 'W') ? "wan_iface" : "wan_ifname"));
632 for (r
= 3; r
>= 0; --r
) {
633 if (route_add(ifname
, atoi(metric
), dest
, gateway
, mask
) == 0) break;
638 route_del(ifname
, atoi(metric
), dest
, gateway
, mask
);
644 void hotplug_net(void)
646 char *interface
, *action
;
649 if (((interface
= getenv("INTERFACE")) == NULL
) || ((action
= getenv("ACTION")) == NULL
)) return;
651 _dprintf("hotplug net INTERFACE=%s ACTION=%s\n", interface
, action
);
653 if ((strncmp(interface
, "wds", 3) == 0) &&
654 (strcmp(action
, "register") == 0 || strcmp(action
, "add") == 0)) {
655 ifconfig(interface
, IFUP
, NULL
, NULL
);
656 lan_ifname
= nvram_safe_get("lan_ifname");
658 if (nvram_get_int("emf_enable")) {
659 eval("emf", "add", "iface", lan_ifname
, interface
);
660 emf_mfdb_update(lan_ifname
, interface
, 1);
661 emf_uffp_update(lan_ifname
, interface
, 1);
662 emf_rtport_update(lan_ifname
, interface
, 1);
665 if (strncmp(lan_ifname
, "br", 2) == 0) {
666 eval("brctl", "addif", lan_ifname
, interface
);
667 notify_nas(interface
);
673 static int is_same_addr(struct ether_addr
*addr1
, struct ether_addr
*addr2
)
676 for (i
= 0; i
< 6; i
++) {
677 if (addr1
->octet
[i
] != addr2
->octet
[i
])
683 #define WL_MAX_ASSOC 128
684 static int check_wl_client(char *ifname
, int unit
, int subunit
)
686 struct ether_addr bssid
;
688 char buf
[WLC_IOCTL_MAXLEN
];
689 struct maclist
*mlist
;
691 int associated
, authorized
;
693 *(uint32
*)buf
= WLC_IOCTL_MAXLEN
;
694 if (wl_ioctl(ifname
, WLC_GET_BSSID
, &bssid
, ETHER_ADDR_LEN
) < 0 ||
695 wl_ioctl(ifname
, WLC_GET_BSS_INFO
, buf
, WLC_IOCTL_MAXLEN
) < 0)
698 bi
= (wl_bss_info_t
*)(buf
+ 4);
699 if ((bi
->SSID_len
== 0) ||
700 (bi
->BSSID
.octet
[0] + bi
->BSSID
.octet
[1] + bi
->BSSID
.octet
[2] +
701 bi
->BSSID
.octet
[3] + bi
->BSSID
.octet
[4] + bi
->BSSID
.octet
[5] == 0))
705 authorized
= strstr(nvram_safe_get(wl_nvname("akm", unit
, subunit
)), "psk") == 0;
707 mlsize
= sizeof(struct maclist
) + (WL_MAX_ASSOC
* sizeof(struct ether_addr
));
708 if ((mlist
= malloc(mlsize
)) != NULL
) {
709 mlist
->count
= WL_MAX_ASSOC
;
710 if (wl_ioctl(ifname
, WLC_GET_ASSOCLIST
, mlist
, mlsize
) == 0) {
711 for (i
= 0; i
< mlist
->count
; ++i
) {
712 if (is_same_addr(&mlist
->ea
[i
], &bi
->BSSID
)) {
719 if (associated
&& !authorized
) {
720 memset(mlist
, 0, mlsize
);
721 mlist
->count
= WL_MAX_ASSOC
;
722 strcpy((char*)mlist
, "autho_sta_list");
723 if (wl_ioctl(ifname
, WLC_GET_VAR
, mlist
, mlsize
) == 0) {
724 for (i
= 0; i
< mlist
->count
; ++i
) {
725 if (is_same_addr(&mlist
->ea
[i
], &bi
->BSSID
)) {
735 return (associated
&& authorized
);
738 #define STACHECK_CONNECT 30
739 #define STACHECK_DISCONNECT 5
741 static int radio_join(int idx
, int unit
, int subunit
, void *param
)
747 int *unit_filter
= param
;
748 if (*unit_filter
>= 0 && *unit_filter
!= unit
) return 0;
750 if (!nvram_get_int(wl_nvname("radio", unit
, 0)) || !wl_client(unit
, subunit
)) return 0;
752 ifname
= nvram_safe_get(wl_nvname("ifname", unit
, subunit
));
754 // skip disabled wl vifs
755 if (strncmp(ifname
, "wl", 2) == 0 && strchr(ifname
, '.') &&
756 !nvram_get_int(wl_nvname("bss_enabled", unit
, subunit
)))
759 sprintf(f
, "/var/run/radio.%d.%d.pid", unit
, subunit
< 0 ? 0 : subunit
);
760 if (f_read_string(f
, s
, sizeof(s
)) > 0) {
761 if ((i
= atoi(s
)) > 1) {
768 sprintf(s
, "%d", getpid());
769 f_write(f
, s
, sizeof(s
), 0, 0644);
771 int stacheck_connect
= nvram_get_int("sta_chkint");
772 if (stacheck_connect
<= 0)
773 stacheck_connect
= STACHECK_CONNECT
;
776 while (get_radio(unit
) && wl_client(unit
, subunit
)) {
778 if (check_wl_client(ifname
, unit
, subunit
)) {
779 stacheck
= stacheck_connect
;
782 eval("wl", "-i", ifname
, "disassoc");
784 char *amode
, *sec
= nvram_safe_get(wl_nvname("akm", unit
, subunit
));
786 if (strstr(sec
, "psk2")) amode
= "wpa2psk";
787 else if (strstr(sec
, "psk")) amode
= "wpapsk";
788 else if (strstr(sec
, "wpa2")) amode
= "wpa2";
789 else if (strstr(sec
, "wpa")) amode
= "wpa";
790 else if (nvram_get_int(wl_nvname("auth", unit
, subunit
))) amode
= "shared";
793 eval("wl", "-i", ifname
, "join", nvram_safe_get(wl_nvname("ssid", unit
, subunit
)),
794 "imode", "bss", "amode", amode
);
796 eval("wl", "-i", ifname
, "join", nvram_safe_get(wl_nvname("ssid", unit
, subunit
)));
798 stacheck
= STACHECK_DISCONNECT
;
814 static int radio_toggle(int idx
, int unit
, int subunit
, void *param
)
816 if (!nvram_get_int(wl_nvname("radio", unit
, 0))) return 0;
820 if (*op
== RADIO_TOGGLE
) {
821 *op
= get_radio(unit
) ? RADIO_OFF
: RADIO_ON
;
824 set_radio(*op
, unit
);
828 int radio_main(int argc
, char *argv
[])
835 usage_exit(argv
[0], "on|off|toggle|join [N]\n");
837 unit
= (argc
== 3) ? atoi(argv
[2]) : -1;
839 if (strcmp(argv
[1], "toggle") == 0)
841 else if (strcmp(argv
[1], "off") == 0)
843 else if (strcmp(argv
[1], "on") == 0)
845 else if (strcmp(argv
[1], "join") == 0)
851 op
= radio_toggle(0, unit
, 0, &op
);
853 op
= foreach_wif(0, &op
, radio_toggle
);
860 foreach_wif(1, &unit
, radio_join
);
865 int wdist_main(int argc, char *argv[])
874 if (wl_ioctl(nvram_safe_get("wl_ifname"), 101, &r, sizeof(r)) == 0) {
877 else v = (v - (9 + 1)) * 150;
878 printf("Current: %d-%dm (0x%02x)\n\n", v + (v ? 1 : 0), v + 150, r.val);
880 usage_exit(argv[0], "<meters>");
882 if ((n = atoi(argv[1])) <= 0) setup_wldistance();
883 else set_wldistance(n);
888 static int get_wldist(int idx
, int unit
, int subunit
, void *param
)
892 char *p
= nvram_safe_get(wl_nvname("distance", unit
, 0));
893 if ((*p
== 0) || ((n
= atoi(p
)) < 0)) return 0;
895 return (9 + (n
/ 150) + ((n
% 150) ? 1 : 0));
898 static int wldist(int idx
, int unit
, int subunit
, void *param
)
905 n
= get_wldist(idx
, unit
, subunit
, param
);
907 s
= 0x10 | (n
<< 16);
908 p
= nvram_safe_get(wl_nvname("ifname", unit
, 0));
909 wl_ioctl(p
, 197, &s
, sizeof(s
));
914 wl_ioctl(p
, 102, &r
, sizeof(r
));
920 int wldist_main(int argc
, char *argv
[])
923 if (foreach_wif(0, NULL
, get_wldist
) == 0) return 0;
926 foreach_wif(0, NULL
, wldist
);