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 %s-lan\n", s
, nvram_safe_get("lan_hostname"), nvram_safe_get("lan_hostname"));
101 if ((s
= nvram_get("lan1_ipaddr")) && (*s
) && (strcmp(s
,"") != 0))
102 fprintf(f
, "%s %s-lan1\n", s
, nvram_safe_get("lan_hostname"));
103 if ((s
= nvram_get("lan2_ipaddr")) && (*s
) && (strcmp(s
,"") != 0))
104 fprintf(f
, "%s %s-lan2\n", s
, nvram_safe_get("lan_hostname"));
105 if ((s
= nvram_get("lan3_ipaddr")) && (*s
) && (strcmp(s
,"") != 0))
106 fprintf(f
, "%s %s-lan3\n", s
, nvram_safe_get("lan_hostname"));
109 if (ipv6_enabled()) {
110 fprintf(f
, "::1 localhost\n");
111 s
= ipv6_router_address(NULL
);
112 if (*s
) fprintf(f
, "%s %s\n", s
, nvram_safe_get("lan_hostname"));
119 void set_host_domain_name(void)
123 s
= nvram_safe_get("wan_hostname");
124 sethostname(s
, strlen(s
));
127 s
= nvram_get("wan_domain");
128 if ((s
== NULL
) || (*s
== 0)) s
= nvram_safe_get("wan_get_domain");
129 setdomainname(s
, strlen(s
));
132 static int wlconf(char *ifname
, int unit
, int subunit
)
137 if (/* !wl_probe(ifname) && */ unit
>= 0) {
138 // validate nvram settings for wireless i/f
139 snprintf(wl
, sizeof(wl
), "--wl%d", unit
);
140 eval("nvram", "validate", wl
);
143 r
= eval("wlconf", ifname
, "up");
145 if (unit
>= 0 && subunit
<= 0) {
146 // setup primary wl interface
147 nvram_set("rrules_radio", "-1");
149 eval("wl", "-i", ifname
, "antdiv", nvram_safe_get(wl_nvname("antdiv", unit
, 0)));
150 eval("wl", "-i", ifname
, "txant", nvram_safe_get(wl_nvname("txant", unit
, 0)));
151 eval("wl", "-i", ifname
, "txpwr1", "-o", "-m", nvram_get_int(wl_nvname("txpwr", unit
, 0)) ? nvram_safe_get(wl_nvname("txpwr", unit
, 0)) : "-1");
152 eval("wl", "-i", ifname
, "interference", nvram_safe_get(wl_nvname("mitigation", unit
, 0)));
155 if (wl_client(unit
, subunit
)) {
156 if (nvram_match(wl_nvname("mode", unit
, subunit
), "wet")) {
157 ifconfig(ifname
, IFUP
|IFF_ALLMULTI
, NULL
, NULL
);
159 if (nvram_get_int(wl_nvname("radio", unit
, 0))) {
160 snprintf(wl
, sizeof(wl
), "%d", unit
);
161 xstart("radio", "join", wl
);
168 // -----------------------------------------------------------------------------
171 static void emf_mfdb_update(char *lan_ifname
, char *lan_port_ifname
, bool add
)
173 char word
[256], *next
;
176 /* Add/Delete MFDB entries corresponding to new interface */
177 foreach (word
, nvram_safe_get("emf_entry"), next
) {
179 mgrp
= strsep(&ifname
, ":");
181 if ((mgrp
== NULL
) || (ifname
== NULL
)) continue;
183 /* Add/Delete MFDB entry using the group addr and interface */
184 if (lan_port_ifname
== NULL
|| strcmp(lan_port_ifname
, ifname
) == 0) {
185 eval("emf", ((add
) ? "add" : "del"), "mfdb", lan_ifname
, mgrp
, ifname
);
190 static void emf_uffp_update(char *lan_ifname
, char *lan_port_ifname
, bool add
)
192 char word
[256], *next
;
195 /* Add/Delete UFFP entries corresponding to new interface */
196 foreach (word
, nvram_safe_get("emf_uffp_entry"), next
) {
199 if (ifname
== NULL
) continue;
201 /* Add/Delete UFFP entry for the interface */
202 if (lan_port_ifname
== NULL
|| strcmp(lan_port_ifname
, ifname
) == 0) {
203 eval("emf", ((add
) ? "add" : "del"), "uffp", lan_ifname
, ifname
);
208 static void emf_rtport_update(char *lan_ifname
, char *lan_port_ifname
, bool add
)
210 char word
[256], *next
;
213 /* Add/Delete RTPORT entries corresponding to new interface */
214 foreach (word
, nvram_safe_get("emf_rtport_entry"), next
) {
217 if (ifname
== NULL
) continue;
219 /* Add/Delete RTPORT entry for the interface */
220 if (lan_port_ifname
== NULL
|| strcmp(lan_port_ifname
, ifname
) == 0) {
221 eval("emf", ((add
) ? "add" : "del"), "rtport", lan_ifname
, ifname
);
226 static void start_emf(char *lan_ifname
)
229 eval("emf", "start", lan_ifname
);
231 /* Add the static MFDB entries */
232 emf_mfdb_update(lan_ifname
, NULL
, 1);
234 /* Add the UFFP entries */
235 emf_uffp_update(lan_ifname
, NULL
, 1);
237 /* Add the RTPORT entries */
238 emf_rtport_update(lan_ifname
, NULL
, 1);
241 static void stop_emf(char *lan_ifname
)
243 eval("emf", "stop", lan_ifname
);
244 eval("igs", "del", "bridge", lan_ifname
);
245 eval("emf", "del", "bridge", lan_ifname
);
249 // -----------------------------------------------------------------------------
251 /* Set initial QoS mode for all et interfaces that are up. */
252 void set_et_qos_mode(int sfd
)
257 struct ethtool_drvinfo info
;
259 qos
= (strcmp(nvram_safe_get("wl_wme"), "off") != 0);
260 for (i
= 1; i
<= DEV_NUMIFS
; i
++) {
262 if (ioctl(sfd
, SIOCGIFNAME
, &ifr
)) continue;
263 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
)) continue;
264 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) continue;
266 if (ioctl(sfd
, SIOCGIFFLAGS
, &ifr
)) continue;
267 /* if up (wan may not be up yet at this point) */
268 if (ifr
.ifr_flags
& IFF_UP
) {
269 ifrdata
= ifr
.ifr_data
;
270 memset(&info
, 0, sizeof(info
));
271 info
.cmd
= ETHTOOL_GDRVINFO
;
272 ifr
.ifr_data
= (caddr_t
)&info
;
273 if (ioctl(sfd
, SIOCETHTOOL
, &ifr
) >= 0) {
274 /* Set QoS for et & bcm57xx devices */
275 if (!strncmp(info
.driver
, "et", 2) ||
276 !strncmp(info
.driver
, "bcm57", 5)) {
277 ifr
.ifr_data
= (caddr_t
)&qos
;
278 ioctl(sfd
, SIOCSETCQOS
, &ifr
);
281 ifr
.ifr_data
= ifrdata
;
286 static void check_afterburner(void)
290 if (nvram_match("wl_afterburner", "off")) return;
291 if ((p
= nvram_get("boardflags")) == NULL
) return;
293 if (strcmp(p
, "0x0118") == 0) { // G 2.2, 3.0, 3.1
296 else if (strcmp(p
, "0x0188") == 0) { // G 2.0
299 else if (strcmp(p
, "0x2558") == 0) { // G 4.0, GL 1.0, 1.1
306 nvram_set("boardflags", p
);
308 if (!nvram_match("debug_abrst", "0")) {
319 bf = strtoul(p, &p, 0);
320 if ((*p == 0) && ((bf & BFL_AFTERBURNER) == 0)) {
321 sprintf(s, "0x%04lX", bf | BFL_AFTERBURNER);
322 nvram_set("boardflags", s);
327 static int set_wlmac(int idx
, int unit
, int subunit
, void *param
)
331 ifname
= nvram_safe_get(wl_nvname("ifname", unit
, subunit
));
333 // skip disabled wl vifs
334 if (strncmp(ifname
, "wl", 2) == 0 && strchr(ifname
, '.') &&
335 !nvram_get_int(wl_nvname("bss_enabled", unit
, subunit
)))
338 if (strcmp(nvram_safe_get(wl_nvname("hwaddr", unit
, subunit
)), "") == 0) {
339 // set_mac(ifname, wl_nvname("macaddr", unit, subunit),
340 set_mac(ifname
, wl_nvname("hwaddr", unit
, subunit
), // AB multiSSID
341 2 + unit
+ ((subunit
> 0) ? ((unit
+ 1) * 0x10 + subunit
) : 0));
343 set_mac(ifname
, wl_nvname("hwaddr", unit
, subunit
), 0);
350 char *lan_ifname
, *lan_ifnames
, *ifname
, *p
;
357 foreach_wif(1, NULL
, set_wlmac
);
359 for(br
=0 ; br
<4 ; br
++) {
360 char bridge
[2] = "0";
368 strcat(tmp
, "_ifname");
369 lan_ifname
= nvram_safe_get(tmp
);
370 // lan_ifname = nvram_safe_get("lan_ifname");
371 if (strncmp(lan_ifname
, "br", 2) == 0) {
374 strcat(tmp
, "_ifnames");
375 // if ((lan_ifnames = strdup(nvram_safe_get("lan_ifnames"))) != NULL) {
376 if ((lan_ifnames
= strdup(nvram_safe_get(tmp
))) != NULL
) {
378 while ((ifname
= strsep(&p
, " ")) != NULL
) {
379 while (*ifname
== ' ') ++ifname
;
380 if (*ifname
== 0) break;
382 unit
= -1; subunit
= -1;
384 // ignore disabled wl vifs
385 if (strncmp(ifname
, "wl", 2) == 0 && strchr(ifname
, '.')) {
387 snprintf(nv
, sizeof(nv
) - 1, "%s_bss_enabled", ifname
);
388 if (!nvram_get_int(nv
))
390 if (get_ifname_unit(ifname
, &unit
, &subunit
) < 0)
393 // get the instance number of the wl i/f
394 else if (wl_ioctl(ifname
, WLC_GET_INSTANCE
, &unit
, sizeof(unit
)))
397 is_client
|= wl_client(unit
, subunit
) && nvram_get_int(wl_nvname("radio", unit
, 0));
400 eval("wlconf", ifname
, "start"); /* start wl iface */
401 #endif // CONFIG_BCMWL5
407 else if (strcmp(lan_ifname
, "")) {
408 /* specific non-bridged lan iface */
409 eval("wlconf", lan_ifname
, "start");
411 #endif // CONFIG_BCMWL5
414 killall("wldist", SIGTERM
);
418 xstart("radio", "join");
422 void enable_ipv6(int enable
)
425 struct dirent
*dirent
;
428 if ((dir
= opendir("/proc/sys/net/ipv6/conf")) != NULL
) {
429 while ((dirent
= readdir(dir
)) != NULL
) {
430 sprintf(s
, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", dirent
->d_name
);
431 f_write_string(s
, enable
? "0" : "1", 0, 0);
437 void accept_ra(const char *ifname
)
441 sprintf(s
, "/proc/sys/net/ipv6/conf/%s/accept_ra", ifname
);
442 f_write_string(s
, "2", 0, 0);
444 sprintf(s
, "/proc/sys/net/ipv6/conf/%s/forwarding", ifname
);
445 f_write_string(s
, "2", 0, 0);
451 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
455 char *lan_ifnames
, *ifname
, *p
;
458 int unit
, subunit
, sta
;
465 foreach_wif(1, NULL
, set_wlmac
);
468 enable_ipv6(ipv6_enabled());
471 if ((sfd
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0) return;
472 for(br
=0 ; br
<4 ; br
++) {
473 char bridge
[2] = "0";
479 // lan_ifname = strdup(nvram_safe_get("lan_ifname"));
482 strcat(tmp
, "_ifname");
483 lan_ifname
= strdup(nvram_safe_get(tmp
));
485 if (strncmp(lan_ifname
, "br", 2) == 0) {
486 _dprintf("%s: setting up the bridge %s\n", __FUNCTION__
, lan_ifname
);
488 eval("brctl", "addbr", lan_ifname
);
489 eval("brctl", "setfd", lan_ifname
, "0");
493 eval("brctl", "stp", lan_ifname
, nvram_safe_get(tmp
));
496 if (nvram_get_int("emf_enable")) {
497 eval("emf", "add", "bridge", lan_ifname
);
498 eval("igs", "add", "bridge", lan_ifname
);
504 strcat(tmp
, "_ipaddr");
505 inet_aton(nvram_safe_get(tmp
), (struct in_addr
*)&ip
);
512 strcat(tmp
, "_ifnames");
513 if ((lan_ifnames
= strdup(nvram_safe_get(tmp
))) != NULL
) {
515 while ((ifname
= strsep(&p
, " ")) != NULL
) {
516 while (*ifname
== ' ') ++ifname
;
517 if (*ifname
== 0) break;
519 unit
= -1; subunit
= -1;
521 // ignore disabled wl vifs
522 if (strncmp(ifname
, "wl", 2) == 0 && strchr(ifname
, '.')) {
525 snprintf(nv
, sizeof(nv
) - 1, "%s_bss_enabled", ifname
);
526 if (!nvram_get_int(nv
))
528 if (get_ifname_unit(ifname
, &unit
, &subunit
) < 0)
532 wl_ioctl(ifname
, WLC_GET_INSTANCE
, &unit
, sizeof(unit
));
534 // bring up interface
535 if (ifconfig(ifname
, IFUP
|IFF_ALLMULTI
, NULL
, NULL
) != 0) continue;
537 // set the logical bridge address to that of the first interface
538 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
540 (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0 &&
541 memcmp(ifr
.ifr_hwaddr
.sa_data
, "\0\0\0\0\0\0", ETHER_ADDR_LEN
) == 0)) {
542 strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
543 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) {
544 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
545 ifr
.ifr_hwaddr
.sa_family
= ARPHRD_ETHER
;
546 _dprintf("%s: setting MAC of %s bridge to %s\n", __FUNCTION__
,
547 ifr
.ifr_name
, ether_etoa(ifr
.ifr_hwaddr
.sa_data
, eabuf
));
548 ioctl(sfd
, SIOCSIFHWADDR
, &ifr
);
553 if (wlconf(ifname
, unit
, subunit
) == 0) {
554 const char *mode
= nvram_safe_get(wl_nvname("mode", unit
, subunit
));
556 if (strcmp(mode
, "wet") == 0) {
557 // Enable host DHCP relay
558 if (nvram_get_int("dhcp_relay")) {
559 wl_iovar_set(ifname
, "wet_host_mac", ifr
.ifr_hwaddr
.sa_data
, ETHER_ADDR_LEN
);
560 wl_iovar_setint(ifname
, "wet_host_ipv4", ip
);
564 sta
|= (strcmp(mode
, "sta") == 0);
565 if ((strcmp(mode
, "ap") != 0) && (strcmp(mode
, "wet") != 0)) continue;
567 eval("brctl", "addif", lan_ifname
, ifname
);
569 if (nvram_get_int("emf_enable"))
570 eval("emf", "add", "iface", lan_ifname
, ifname
);
574 if ((nvram_get_int("wan_islan")) && (br
==0) &&
575 ((get_wan_proto() == WP_DISABLED
) || (sta
))) {
576 ifname
= nvram_get("wan_ifnameX");
577 if (ifconfig(ifname
, IFUP
, NULL
, NULL
) == 0)
578 eval("brctl", "addif", lan_ifname
, ifname
);
584 // --- this shouldn't happen ---
585 else if (*lan_ifname
) {
586 ifconfig(lan_ifname
, IFUP
, NULL
, NULL
);
587 wlconf(lan_ifname
, -1, -1);
595 // Get current LAN hardware address
596 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
599 strcat(tmp
, "_hwaddr");
600 // if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set("lan_hwaddr", ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
601 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) nvram_set(tmp
, ether_etoa(ifr
.ifr_hwaddr
.sa_data
, eabuf
));
603 // Set initial QoS mode for LAN ports
604 set_et_qos_mode(sfd
);
608 // bring up and configure LAN interface
611 strcat(tmp
, "_ipaddr");
614 strcat(tmp2
, "_netmask");
615 ifconfig(lan_ifname
, IFUP
, nvram_safe_get(tmp
), nvram_safe_get(tmp2
));
621 set_lan_hostname(nvram_safe_get("wan_hostname"));
623 if ((get_wan_proto() == WP_DISABLED
) && (br
==0)) {
624 char *gateway
= nvram_safe_get("lan_gateway") ;
625 if ((*gateway
) && (strcmp(gateway
, "0.0.0.0") != 0)) {
627 while ((route_add(lan_ifname
, 0, "0.0.0.0", gateway
, "0.0.0.0") != 0) && (tries
-- > 0)) sleep(1);
628 _dprintf("%s: add gateway=%s tries=%d\n", __FUNCTION__
, gateway
, tries
);
637 if (nvram_get_int("emf_enable")) start_emf(lan_ifname
);
642 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
647 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
650 char *lan_ifnames
, *p
, *ifname
;
654 for(br
=0 ; br
<4 ; br
++) {
655 char bridge
[2] = "0";
663 strcat(tmp
, "_ifname");
664 lan_ifname
= nvram_safe_get(tmp
);
665 ifconfig(lan_ifname
, 0, NULL
, NULL
);
671 if (strncmp(lan_ifname
, "br", 2) == 0) {
673 stop_emf(lan_ifname
);
677 strcat(tmp
, "_ifnames");
678 if ((lan_ifnames
= strdup(nvram_safe_get(tmp
))) != NULL
) {
680 while ((ifname
= strsep(&p
, " ")) != NULL
) {
681 while (*ifname
== ' ') ++ifname
;
682 if (*ifname
== 0) break;
683 eval("wlconf", ifname
, "down");
684 ifconfig(ifname
, 0, NULL
, NULL
);
685 eval("brctl", "delif", lan_ifname
, ifname
);
689 eval("brctl", "delbr", lan_ifname
);
691 else if (*lan_ifname
) {
692 eval("wlconf", lan_ifname
, "down");
695 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
698 static int is_sta(int idx
, int unit
, int subunit
, void *param
)
700 return (nvram_match(wl_nvname("mode", unit
, subunit
), "sta") && (nvram_match(wl_nvname("bss_enabled", unit
, subunit
), "1")));
703 void do_static_routes(int add
)
707 char *dest
, *mask
, *gateway
, *metric
, *ifname
;
710 if ((buf
= strdup(nvram_safe_get(add
? "routes_static" : "routes_static_saved"))) == NULL
) return;
711 if (add
) nvram_set("routes_static_saved", buf
);
712 else nvram_unset("routes_static_saved");
714 while ((q
= strsep(&p
, ">")) != NULL
) {
715 if (vstrsep(q
, "<", &dest
, &gateway
, &mask
, &metric
, &ifname
) != 5) continue;
717 ifname
= nvram_safe_get(((strcmp(ifname
,"LAN")==0) ? "lan_ifname" :
718 ((strcmp(ifname
,"LAN1")==0) ? "lan1_ifname" :
719 ((strcmp(ifname
,"LAN2")==0) ? "lan2_ifname" :
720 ((strcmp(ifname
,"LAN3")==0) ? "lan3_ifname" :
721 ((*ifname
== 'W') ? "wan_iface" : "wan_ifname"))))));
723 ifname
= nvram_safe_get((*ifname
== 'L') ? "lan_ifname" :
724 ((*ifname
== 'W') ? "wan_iface" : "wan_ifname"));
727 for (r
= 3; r
>= 0; --r
) {
728 if (route_add(ifname
, atoi(metric
), dest
, gateway
, mask
) == 0) break;
733 route_del(ifname
, atoi(metric
), dest
, gateway
, mask
);
739 if ( (nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "dhcp") || nvram_match("wan_proto", "static") )
740 && (modem_ipaddr
= nvram_safe_get("modem_ipaddr")) && *modem_ipaddr
&& !nvram_match("modem_ipaddr","0.0.0.0")
741 && (!foreach_wif(1, NULL
, is_sta
)) ) {
743 char *end
= rindex(modem_ipaddr
,'.')+1;
744 unsigned char c
= atoi(end
);
745 char *iface
= nvram_safe_get("wan_ifname");
747 sprintf(ip
, "%.*s%hhu", end
-modem_ipaddr
, modem_ipaddr
, (unsigned char)(c
^1^((c
&2)^((c
&1)<<1))) );
748 eval("ip", "addr", add
?"add":"del", ip
, "peer", modem_ipaddr
, "dev", iface
);
754 void hotplug_net(void)
756 char *interface
, *action
;
759 if (((interface
= getenv("INTERFACE")) == NULL
) || ((action
= getenv("ACTION")) == NULL
)) return;
761 _dprintf("hotplug net INTERFACE=%s ACTION=%s\n", interface
, action
);
763 if ((strncmp(interface
, "wds", 3) == 0) &&
764 (strcmp(action
, "register") == 0 || strcmp(action
, "add") == 0)) {
765 ifconfig(interface
, IFUP
, NULL
, NULL
);
766 lan_ifname
= nvram_safe_get("lan_ifname");
768 if (nvram_get_int("emf_enable")) {
769 eval("emf", "add", "iface", lan_ifname
, interface
);
770 emf_mfdb_update(lan_ifname
, interface
, 1);
771 emf_uffp_update(lan_ifname
, interface
, 1);
772 emf_rtport_update(lan_ifname
, interface
, 1);
775 if (strncmp(lan_ifname
, "br", 2) == 0) {
776 eval("brctl", "addif", lan_ifname
, interface
);
777 notify_nas(interface
);
783 static int is_same_addr(struct ether_addr
*addr1
, struct ether_addr
*addr2
)
786 for (i
= 0; i
< 6; i
++) {
787 if (addr1
->octet
[i
] != addr2
->octet
[i
])
793 #define WL_MAX_ASSOC 128
794 static int check_wl_client(char *ifname
, int unit
, int subunit
)
796 struct ether_addr bssid
;
798 char buf
[WLC_IOCTL_MAXLEN
];
799 struct maclist
*mlist
;
801 int associated
, authorized
;
803 *(uint32
*)buf
= WLC_IOCTL_MAXLEN
;
804 if (wl_ioctl(ifname
, WLC_GET_BSSID
, &bssid
, ETHER_ADDR_LEN
) < 0 ||
805 wl_ioctl(ifname
, WLC_GET_BSS_INFO
, buf
, WLC_IOCTL_MAXLEN
) < 0)
808 bi
= (wl_bss_info_t
*)(buf
+ 4);
809 if ((bi
->SSID_len
== 0) ||
810 (bi
->BSSID
.octet
[0] + bi
->BSSID
.octet
[1] + bi
->BSSID
.octet
[2] +
811 bi
->BSSID
.octet
[3] + bi
->BSSID
.octet
[4] + bi
->BSSID
.octet
[5] == 0))
815 authorized
= strstr(nvram_safe_get(wl_nvname("akm", unit
, subunit
)), "psk") == 0;
817 mlsize
= sizeof(struct maclist
) + (WL_MAX_ASSOC
* sizeof(struct ether_addr
));
818 if ((mlist
= malloc(mlsize
)) != NULL
) {
819 mlist
->count
= WL_MAX_ASSOC
;
820 if (wl_ioctl(ifname
, WLC_GET_ASSOCLIST
, mlist
, mlsize
) == 0) {
821 for (i
= 0; i
< mlist
->count
; ++i
) {
822 if (is_same_addr(&mlist
->ea
[i
], &bi
->BSSID
)) {
829 if (associated
&& !authorized
) {
830 memset(mlist
, 0, mlsize
);
831 mlist
->count
= WL_MAX_ASSOC
;
832 strcpy((char*)mlist
, "autho_sta_list");
833 if (wl_ioctl(ifname
, WLC_GET_VAR
, mlist
, mlsize
) == 0) {
834 for (i
= 0; i
< mlist
->count
; ++i
) {
835 if (is_same_addr(&mlist
->ea
[i
], &bi
->BSSID
)) {
845 return (associated
&& authorized
);
848 #define STACHECK_CONNECT 30
849 #define STACHECK_DISCONNECT 5
851 static int radio_join(int idx
, int unit
, int subunit
, void *param
)
857 int *unit_filter
= param
;
858 if (*unit_filter
>= 0 && *unit_filter
!= unit
) return 0;
860 if (!nvram_get_int(wl_nvname("radio", unit
, 0)) || !wl_client(unit
, subunit
)) return 0;
862 ifname
= nvram_safe_get(wl_nvname("ifname", unit
, subunit
));
864 // skip disabled wl vifs
865 if (strncmp(ifname
, "wl", 2) == 0 && strchr(ifname
, '.') &&
866 !nvram_get_int(wl_nvname("bss_enabled", unit
, subunit
)))
869 sprintf(f
, "/var/run/radio.%d.%d.pid", unit
, subunit
< 0 ? 0 : subunit
);
870 if (f_read_string(f
, s
, sizeof(s
)) > 0) {
871 if ((i
= atoi(s
)) > 1) {
878 sprintf(s
, "%d", getpid());
879 f_write(f
, s
, sizeof(s
), 0, 0644);
881 int stacheck_connect
= nvram_get_int("sta_chkint");
882 if (stacheck_connect
<= 0)
883 stacheck_connect
= STACHECK_CONNECT
;
886 while (get_radio(unit
) && wl_client(unit
, subunit
)) {
888 if (check_wl_client(ifname
, unit
, subunit
)) {
889 stacheck
= stacheck_connect
;
892 eval("wl", "-i", ifname
, "disassoc");
894 char *amode
, *sec
= nvram_safe_get(wl_nvname("akm", unit
, subunit
));
896 if (strstr(sec
, "psk2")) amode
= "wpa2psk";
897 else if (strstr(sec
, "psk")) amode
= "wpapsk";
898 else if (strstr(sec
, "wpa2")) amode
= "wpa2";
899 else if (strstr(sec
, "wpa")) amode
= "wpa";
900 else if (nvram_get_int(wl_nvname("auth", unit
, subunit
))) amode
= "shared";
903 eval("wl", "-i", ifname
, "join", nvram_safe_get(wl_nvname("ssid", unit
, subunit
)),
904 "imode", "bss", "amode", amode
);
906 eval("wl", "-i", ifname
, "join", nvram_safe_get(wl_nvname("ssid", unit
, subunit
)));
908 stacheck
= STACHECK_DISCONNECT
;
924 static int radio_toggle(int idx
, int unit
, int subunit
, void *param
)
926 if (!nvram_get_int(wl_nvname("radio", unit
, 0))) return 0;
930 if (*op
== RADIO_TOGGLE
) {
931 *op
= get_radio(unit
) ? RADIO_OFF
: RADIO_ON
;
934 set_radio(*op
, unit
);
938 int radio_main(int argc
, char *argv
[])
945 usage_exit(argv
[0], "on|off|toggle|join [N]\n");
947 unit
= (argc
== 3) ? atoi(argv
[2]) : -1;
949 if (strcmp(argv
[1], "toggle") == 0)
951 else if (strcmp(argv
[1], "off") == 0)
953 else if (strcmp(argv
[1], "on") == 0)
955 else if (strcmp(argv
[1], "join") == 0)
961 op
= radio_toggle(0, unit
, 0, &op
);
963 op
= foreach_wif(0, &op
, radio_toggle
);
970 foreach_wif(1, &unit
, radio_join
);
975 int wdist_main(int argc, char *argv[])
984 if (wl_ioctl(nvram_safe_get("wl_ifname"), 101, &r, sizeof(r)) == 0) {
987 else v = (v - (9 + 1)) * 150;
988 printf("Current: %d-%dm (0x%02x)\n\n", v + (v ? 1 : 0), v + 150, r.val);
990 usage_exit(argv[0], "<meters>");
992 if ((n = atoi(argv[1])) <= 0) setup_wldistance();
993 else set_wldistance(n);
998 static int get_wldist(int idx
, int unit
, int subunit
, void *param
)
1002 char *p
= nvram_safe_get(wl_nvname("distance", unit
, 0));
1003 if ((*p
== 0) || ((n
= atoi(p
)) < 0)) return 0;
1005 return (9 + (n
/ 150) + ((n
% 150) ? 1 : 0));
1008 static int wldist(int idx
, int unit
, int subunit
, void *param
)
1015 n
= get_wldist(idx
, unit
, subunit
, param
);
1017 s
= 0x10 | (n
<< 16);
1018 p
= nvram_safe_get(wl_nvname("ifname", unit
, 0));
1019 wl_ioctl(p
, 197, &s
, sizeof(s
));
1024 wl_ioctl(p
, 102, &r
, sizeof(r
));
1030 int wldist_main(int argc
, char *argv
[])
1033 if (foreach_wif(0, NULL
, get_wldist
) == 0) return 0;
1036 foreach_wif(0, NULL
, wldist
);