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 #define sin_addr(s) (((struct sockaddr_in *)(s))->sin_addr)
75 static void set_lan_hostname(const char *wan_hostname
)
80 nvram_set("lan_hostname", wan_hostname
);
81 if ((wan_hostname
== NULL
) || (*wan_hostname
== 0)) {
82 /* derive from et0 mac address */
83 s
= nvram_get("et0macaddr");
84 if (s
&& strlen(s
) >= 17) {
86 sprintf(hostname
, "RT-%c%c%c%c%c%c%c%c%c%c%c%c",
87 s
[0], s
[1], s
[3], s
[4], s
[6], s
[7],
88 s
[9], s
[10], s
[12], s
[13], s
[15], s
[16]);
90 if ((f
= fopen("/proc/sys/kernel/hostname", "w"))) {
94 nvram_set("lan_hostname", hostname
);
98 if ((f
= fopen("/etc/hosts", "w"))) {
99 fprintf(f
, "127.0.0.1 localhost\n");
100 if ((s
= nvram_get("lan_ipaddr")) && (*s
))
101 fprintf(f
, "%s %s %s-lan\n", s
, nvram_safe_get("lan_hostname"), nvram_safe_get("lan_hostname"));
103 if ((s
= nvram_get("lan1_ipaddr")) && (*s
) && (strcmp(s
,"") != 0))
104 fprintf(f
, "%s %s-lan1\n", s
, nvram_safe_get("lan_hostname"));
105 if ((s
= nvram_get("lan2_ipaddr")) && (*s
) && (strcmp(s
,"") != 0))
106 fprintf(f
, "%s %s-lan2\n", s
, nvram_safe_get("lan_hostname"));
107 if ((s
= nvram_get("lan3_ipaddr")) && (*s
) && (strcmp(s
,"") != 0))
108 fprintf(f
, "%s %s-lan3\n", s
, nvram_safe_get("lan_hostname"));
111 if (ipv6_enabled()) {
112 fprintf(f
, "::1 localhost\n");
113 s
= ipv6_router_address(NULL
);
114 if (*s
) fprintf(f
, "%s %s\n", s
, nvram_safe_get("lan_hostname"));
121 void set_host_domain_name(void)
125 s
= nvram_safe_get("wan_hostname");
126 sethostname(s
, strlen(s
));
129 s
= nvram_get("wan_domain");
130 if ((s
== NULL
) || (*s
== 0)) s
= nvram_safe_get("wan_get_domain");
131 setdomainname(s
, strlen(s
));
134 static int wlconf(char *ifname
, int unit
, int subunit
)
139 if (/* !wl_probe(ifname) && */ unit
>= 0) {
140 // validate nvram settings for wireless i/f
141 snprintf(wl
, sizeof(wl
), "--wl%d", unit
);
142 eval("nvram", "validate", wl
);
145 r
= eval("wlconf", ifname
, "up");
147 if (unit
>= 0 && subunit
<= 0) {
148 // setup primary wl interface
149 nvram_set("rrules_radio", "-1");
151 eval("wl", "-i", ifname
, "antdiv", nvram_safe_get(wl_nvname("antdiv", unit
, 0)));
152 eval("wl", "-i", ifname
, "txant", nvram_safe_get(wl_nvname("txant", unit
, 0)));
153 eval("wl", "-i", ifname
, "txpwr1", "-o", "-m", nvram_get_int(wl_nvname("txpwr", unit
, 0)) ? nvram_safe_get(wl_nvname("txpwr", unit
, 0)) : "-1");
154 eval("wl", "-i", ifname
, "interference", nvram_safe_get(wl_nvname("interfmode", unit
, 0)));
157 if (wl_client(unit
, subunit
)) {
158 if (nvram_match(wl_nvname("mode", unit
, subunit
), "wet")) {
159 ifconfig(ifname
, IFUP
|IFF_ALLMULTI
, NULL
, NULL
);
161 if (nvram_get_int(wl_nvname("radio", unit
, 0))) {
162 snprintf(wl
, sizeof(wl
), "%d", unit
);
163 xstart("radio", "join", wl
);
170 // -----------------------------------------------------------------------------
173 static void emf_mfdb_update(char *lan_ifname
, char *lan_port_ifname
, bool add
)
175 char word
[256], *next
;
178 /* Add/Delete MFDB entries corresponding to new interface */
179 foreach (word
, nvram_safe_get("emf_entry"), next
) {
181 mgrp
= strsep(&ifname
, ":");
183 if ((mgrp
== NULL
) || (ifname
== NULL
)) continue;
185 /* Add/Delete MFDB entry using the group addr and interface */
186 if (lan_port_ifname
== NULL
|| strcmp(lan_port_ifname
, ifname
) == 0) {
187 eval("emf", ((add
) ? "add" : "del"), "mfdb", lan_ifname
, mgrp
, ifname
);
192 static void emf_uffp_update(char *lan_ifname
, char *lan_port_ifname
, bool add
)
194 char word
[256], *next
;
197 /* Add/Delete UFFP entries corresponding to new interface */
198 foreach (word
, nvram_safe_get("emf_uffp_entry"), next
) {
201 if (ifname
== NULL
) continue;
203 /* Add/Delete UFFP entry for the interface */
204 if (lan_port_ifname
== NULL
|| strcmp(lan_port_ifname
, ifname
) == 0) {
205 eval("emf", ((add
) ? "add" : "del"), "uffp", lan_ifname
, ifname
);
210 static void emf_rtport_update(char *lan_ifname
, char *lan_port_ifname
, bool add
)
212 char word
[256], *next
;
215 /* Add/Delete RTPORT entries corresponding to new interface */
216 foreach (word
, nvram_safe_get("emf_rtport_entry"), next
) {
219 if (ifname
== NULL
) continue;
221 /* Add/Delete RTPORT entry for the interface */
222 if (lan_port_ifname
== NULL
|| strcmp(lan_port_ifname
, ifname
) == 0) {
223 eval("emf", ((add
) ? "add" : "del"), "rtport", lan_ifname
, ifname
);
228 static void start_emf(char *lan_ifname
)
231 eval("emf", "start", lan_ifname
);
233 /* Add the static MFDB entries */
234 emf_mfdb_update(lan_ifname
, NULL
, 1);
236 /* Add the UFFP entries */
237 emf_uffp_update(lan_ifname
, NULL
, 1);
239 /* Add the RTPORT entries */
240 emf_rtport_update(lan_ifname
, NULL
, 1);
243 static void stop_emf(char *lan_ifname
)
245 eval("emf", "stop", lan_ifname
);
246 eval("igs", "del", "bridge", lan_ifname
);
247 eval("emf", "del", "bridge", lan_ifname
);
251 // -----------------------------------------------------------------------------
253 /* Set initial QoS mode for all et interfaces that are up. */
254 void set_et_qos_mode(int sfd
)
259 struct ethtool_drvinfo info
;
261 qos
= (strcmp(nvram_safe_get("wl_wme"), "off") != 0);
262 for (i
= 1; i
<= DEV_NUMIFS
; i
++) {
264 if (ioctl(sfd
, SIOCGIFNAME
, &ifr
)) continue;
265 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
)) continue;
266 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) continue;
268 if (ioctl(sfd
, SIOCGIFFLAGS
, &ifr
)) continue;
269 /* if up (wan may not be up yet at this point) */
270 if (ifr
.ifr_flags
& IFF_UP
) {
271 ifrdata
= ifr
.ifr_data
;
272 memset(&info
, 0, sizeof(info
));
273 info
.cmd
= ETHTOOL_GDRVINFO
;
274 ifr
.ifr_data
= (caddr_t
)&info
;
275 if (ioctl(sfd
, SIOCETHTOOL
, &ifr
) >= 0) {
276 /* Set QoS for et & bcm57xx devices */
277 if (!strncmp(info
.driver
, "et", 2) ||
278 !strncmp(info
.driver
, "bcm57", 5)) {
279 ifr
.ifr_data
= (caddr_t
)&qos
;
280 ioctl(sfd
, SIOCSETCQOS
, &ifr
);
283 ifr
.ifr_data
= ifrdata
;
288 static void check_afterburner(void)
292 if (nvram_match("wl_afterburner", "off")) return;
293 if ((p
= nvram_get("boardflags")) == NULL
) return;
295 if (strcmp(p
, "0x0118") == 0) { // G 2.2, 3.0, 3.1
298 else if (strcmp(p
, "0x0188") == 0) { // G 2.0
301 else if (strcmp(p
, "0x2558") == 0) { // G 4.0, GL 1.0, 1.1
308 nvram_set("boardflags", p
);
310 if (!nvram_match("debug_abrst", "0")) {
321 bf = strtoul(p, &p, 0);
322 if ((*p == 0) && ((bf & BFL_AFTERBURNER) == 0)) {
323 sprintf(s, "0x%04lX", bf | BFL_AFTERBURNER);
324 nvram_set("boardflags", s);
331 char *lan_ifname
, *lan_ifnames
, *ifname
, *p
;
338 for(br
=0 ; br
<4 ; br
++) {
339 char bridge
[2] = "0";
347 strcat(tmp
, "_ifname");
348 lan_ifname
= nvram_safe_get(tmp
);
349 // lan_ifname = nvram_safe_get("lan_ifname");
350 if (strncmp(lan_ifname
, "br", 2) == 0) {
353 strcat(tmp
, "_ifnames");
354 // if ((lan_ifnames = strdup(nvram_safe_get("lan_ifnames"))) != NULL) {
355 if ((lan_ifnames
= strdup(nvram_safe_get(tmp
))) != NULL
) {
357 while ((ifname
= strsep(&p
, " ")) != NULL
) {
358 while (*ifname
== ' ') ++ifname
;
359 if (*ifname
== 0) break;
361 unit
= -1; subunit
= -1;
363 // ignore disabled wl vifs
364 if (strncmp(ifname
, "wl", 2) == 0 && strchr(ifname
, '.')) {
366 snprintf(nv
, sizeof(nv
) - 1, "%s_bss_enabled", ifname
);
367 if (!nvram_get_int(nv
))
369 if (get_ifname_unit(ifname
, &unit
, &subunit
) < 0)
372 // get the instance number of the wl i/f
373 else if (wl_ioctl(ifname
, WLC_GET_INSTANCE
, &unit
, sizeof(unit
)))
376 is_client
|= wl_client(unit
, subunit
) && nvram_get_int(wl_nvname("radio", unit
, 0));
379 eval("wlconf", ifname
, "start"); /* start wl iface */
380 #endif // CONFIG_BCMWL5
386 else if (strcmp(lan_ifname
, "")) {
387 /* specific non-bridged lan iface */
388 eval("wlconf", lan_ifname
, "start");
390 #endif // CONFIG_BCMWL5
393 killall("wldist", SIGTERM
);
397 xstart("radio", "join");
400 static int set_wlmac(int idx
, int unit
, int subunit
, void *param
)
404 ifname
= nvram_safe_get(wl_nvname("ifname", unit
, subunit
));
406 // skip disabled wl vifs
407 if (strncmp(ifname
, "wl", 2) == 0 && strchr(ifname
, '.') &&
408 !nvram_get_int(wl_nvname("bss_enabled", unit
, subunit
)))
411 set_mac(ifname
, wl_nvname("macaddr", unit
, subunit
),
412 2 + unit
+ ((subunit
> 0) ? ((unit
+ 1) * 0x10 + subunit
) : 0));
418 void enable_ipv6(int enable
)
421 struct dirent
*dirent
;
424 if ((dir
= opendir("/proc/sys/net/ipv6/conf")) != NULL
) {
425 while ((dirent
= readdir(dir
)) != NULL
) {
426 sprintf(s
, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", dirent
->d_name
);
427 f_write_string(s
, enable
? "0" : "1", 0, 0);
433 void accept_ra(const char *ifname
)
437 sprintf(s
, "/proc/sys/net/ipv6/conf/%s/accept_ra", ifname
);
438 f_write_string(s
, "2", 0, 0);
440 sprintf(s
, "/proc/sys/net/ipv6/conf/%s/forwarding", ifname
);
441 f_write_string(s
, "2", 0, 0);
447 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
451 char *lan_ifnames
, *ifname
, *p
;
454 int unit
, subunit
, sta
;
466 foreach_wif(1, NULL
, set_wlmac
);
469 enable_ipv6(ipv6_enabled());
471 vlan0tag
= nvram_get_int("vlan0tag");
473 if ((sfd
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0) return;
474 for(br
=0 ; br
<4 ; br
++) {
475 char bridge
[2] = "0";
481 // lan_ifname = strdup(nvram_safe_get("lan_ifname"));
484 strcat(tmp
, "_ifname");
485 lan_ifname
= strdup(nvram_safe_get(tmp
));
487 if (strncmp(lan_ifname
, "br", 2) == 0) {
488 _dprintf("%s: setting up the bridge %s\n", __FUNCTION__
, lan_ifname
);
490 eval("brctl", "addbr", lan_ifname
);
491 eval("brctl", "setfd", lan_ifname
, "0");
495 eval("brctl", "stp", lan_ifname
, nvram_safe_get(tmp
));
498 if (nvram_get_int("emf_enable")) {
499 eval("emf", "add", "bridge", lan_ifname
);
500 eval("igs", "add", "bridge", lan_ifname
);
506 strcat(tmp
, "_ipaddr");
507 inet_aton(nvram_safe_get(tmp
), (struct in_addr
*)&ip
);
514 strcat(tmp
, "_ifnames");
515 if ((lan_ifnames
= strdup(nvram_safe_get(tmp
))) != NULL
) {
517 while ((iftmp
= strsep(&p
, " ")) != NULL
) {
518 while (*iftmp
== ' ') ++iftmp
;
519 if (*iftmp
== 0) break;
522 unit
= -1; subunit
= -1;
524 // ignore disabled wl vifs
525 if (strncmp(ifname
, "wl", 2) == 0 && strchr(ifname
, '.')) {
527 snprintf(nv
, sizeof(nv
) - 1, "%s_bss_enabled", ifname
);
528 if (!nvram_get_int(nv
))
530 if (get_ifname_unit(ifname
, &unit
, &subunit
) < 0)
534 wl_ioctl(ifname
, WLC_GET_INSTANCE
, &unit
, sizeof(unit
));
537 if (strncmp(ifname
, "vlan", 4) == 0) {
538 if (sscanf(ifname
, "vlan%d", &vid
) == 1) {
539 snprintf(tmp
, sizeof(tmp
), "vlan%dvid", vid
);
540 vid_map
= nvram_get_int(tmp
);
541 if ((vid_map
< 1) || (vid_map
> 4094)) vid_map
= vlan0tag
| vid
;
542 snprintf(tmp
, sizeof(tmp
), "vlan%d", vid_map
);
547 // bring up interface
548 if (ifconfig(ifname
, IFUP
|IFF_ALLMULTI
, NULL
, NULL
) != 0) continue;
550 // set the logical bridge address to that of the first interface
551 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
553 (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0 &&
554 memcmp(ifr
.ifr_hwaddr
.sa_data
, "\0\0\0\0\0\0", ETHER_ADDR_LEN
) == 0)) {
555 strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
556 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) {
557 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
558 ifr
.ifr_hwaddr
.sa_family
= ARPHRD_ETHER
;
559 _dprintf("%s: setting MAC of %s bridge to %s\n", __FUNCTION__
,
560 ifr
.ifr_name
, ether_etoa(ifr
.ifr_hwaddr
.sa_data
, eabuf
));
561 ioctl(sfd
, SIOCSIFHWADDR
, &ifr
);
566 if (wlconf(ifname
, unit
, subunit
) == 0) {
567 const char *mode
= nvram_safe_get(wl_nvname("mode", unit
, subunit
));
569 if (strcmp(mode
, "wet") == 0) {
570 // Enable host DHCP relay
571 if (nvram_get_int("dhcp_relay")) {
572 wl_iovar_set(ifname
, "wet_host_mac", ifr
.ifr_hwaddr
.sa_data
, ETHER_ADDR_LEN
);
573 wl_iovar_setint(ifname
, "wet_host_ipv4", ip
);
577 sta
|= (strcmp(mode
, "sta") == 0);
578 if ((strcmp(mode
, "ap") != 0) && (strcmp(mode
, "wet") != 0)) continue;
580 eval("brctl", "addif", lan_ifname
, ifname
);
582 if (nvram_get_int("emf_enable"))
583 eval("emf", "add", "iface", lan_ifname
, ifname
);
587 if ((nvram_get_int("wan_islan")) && (br
==0) &&
588 ((get_wan_proto() == WP_DISABLED
) || (sta
))) {
589 ifname
= nvram_get("wan_ifnameX");
590 if (ifconfig(ifname
, IFUP
, NULL
, NULL
) == 0)
591 eval("brctl", "addif", lan_ifname
, ifname
);
597 // --- this shouldn't happen ---
598 else if (*lan_ifname
) {
599 ifconfig(lan_ifname
, IFUP
, NULL
, NULL
);
600 wlconf(lan_ifname
, -1, -1);
608 // Get current LAN hardware address
609 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
612 strcat(tmp
, "_hwaddr");
613 // if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set("lan_hwaddr", ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
614 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) nvram_set(tmp
, ether_etoa(ifr
.ifr_hwaddr
.sa_data
, eabuf
));
616 // Set initial QoS mode for LAN ports
617 set_et_qos_mode(sfd
);
621 // bring up and configure LAN interface
624 strcat(tmp
, "_ipaddr");
627 strcat(tmp2
, "_netmask");
628 ifconfig(lan_ifname
, IFUP
, nvram_safe_get(tmp
), nvram_safe_get(tmp2
));
634 set_lan_hostname(nvram_safe_get("wan_hostname"));
636 if ((get_wan_proto() == WP_DISABLED
) && (br
==0)) {
637 char *gateway
= nvram_safe_get("lan_gateway") ;
638 if ((*gateway
) && (strcmp(gateway
, "0.0.0.0") != 0)) {
640 while ((route_add(lan_ifname
, 0, "0.0.0.0", gateway
, "0.0.0.0") != 0) && (tries
-- > 0)) sleep(1);
641 _dprintf("%s: add gateway=%s tries=%d\n", __FUNCTION__
, gateway
, tries
);
650 if (nvram_get_int("emf_enable")) start_emf(lan_ifname
);
655 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
660 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
663 char *lan_ifnames
, *p
, *ifname
;
666 int vlan0tag
, vid
, vid_map
;
669 vlan0tag
= nvram_get_int("vlan0tag");
671 for(br
=0 ; br
<4 ; br
++) {
672 char bridge
[2] = "0";
680 strcat(tmp
, "_ifname");
681 lan_ifname
= nvram_safe_get(tmp
);
682 ifconfig(lan_ifname
, 0, NULL
, NULL
);
688 if (strncmp(lan_ifname
, "br", 2) == 0) {
690 stop_emf(lan_ifname
);
694 strcat(tmp
, "_ifnames");
695 if ((lan_ifnames
= strdup(nvram_safe_get(tmp
))) != NULL
) {
697 while ((iftmp
= strsep(&p
, " ")) != NULL
) {
698 while (*iftmp
== ' ') ++iftmp
;
699 if (*iftmp
== 0) break;
702 if (strncmp(ifname
, "vlan", 4) == 0) {
703 if (sscanf(ifname
, "vlan%d", &vid
) == 1) {
704 snprintf(tmp
, sizeof(tmp
), "vlan%dvid", vid
);
705 vid_map
= nvram_get_int(tmp
);
706 if ((vid_map
< 1) || (vid_map
> 4094)) vid_map
= vlan0tag
| vid
;
707 snprintf(tmp
, sizeof(tmp
), "vlan%d", vid_map
);
711 eval("wlconf", ifname
, "down");
712 ifconfig(ifname
, 0, NULL
, NULL
);
713 eval("brctl", "delif", lan_ifname
, ifname
);
717 eval("brctl", "delbr", lan_ifname
);
719 else if (*lan_ifname
) {
720 eval("wlconf", lan_ifname
, "down");
723 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
727 void do_static_routes(int add
)
731 char *dest
, *mask
, *gateway
, *metric
, *ifname
;
734 if ((buf
= strdup(nvram_safe_get(add
? "routes_static" : "routes_static_saved"))) == NULL
) return;
735 if (add
) nvram_set("routes_static_saved", buf
);
736 else nvram_unset("routes_static_saved");
738 while ((q
= strsep(&p
, ">")) != NULL
) {
739 if (vstrsep(q
, "<", &dest
, &gateway
, &mask
, &metric
, &ifname
) != 5) continue;
741 ifname
= nvram_safe_get(((strcmp(ifname
,"LAN")==0) ? "lan_ifname" :
742 ((strcmp(ifname
,"LAN1")==0) ? "lan1_ifname" :
743 ((strcmp(ifname
,"LAN2")==0) ? "lan2_ifname" :
744 ((strcmp(ifname
,"LAN3")==0) ? "lan3_ifname" :
745 ((*ifname
== 'W') ? "wan_iface" : "wan_ifname"))))));
747 ifname
= nvram_safe_get((*ifname
== 'L') ? "lan_ifname" :
748 ((*ifname
== 'W') ? "wan_iface" : "wan_ifname"));
751 for (r
= 3; r
>= 0; --r
) {
752 if (route_add(ifname
, atoi(metric
) + 1, dest
, gateway
, mask
) == 0) break;
757 route_del(ifname
, atoi(metric
) + 1, dest
, gateway
, mask
);
763 void hotplug_net(void)
765 char *interface
, *action
;
768 if (((interface
= getenv("INTERFACE")) == NULL
) || ((action
= getenv("ACTION")) == NULL
)) return;
770 _dprintf("hotplug net INTERFACE=%s ACTION=%s\n", interface
, action
);
772 if ((strncmp(interface
, "wds", 3) == 0) &&
773 (strcmp(action
, "register") == 0 || strcmp(action
, "add") == 0)) {
774 ifconfig(interface
, IFUP
, NULL
, NULL
);
775 lan_ifname
= nvram_safe_get("lan_ifname");
777 if (nvram_get_int("emf_enable")) {
778 eval("emf", "add", "iface", lan_ifname
, interface
);
779 emf_mfdb_update(lan_ifname
, interface
, 1);
780 emf_uffp_update(lan_ifname
, interface
, 1);
781 emf_rtport_update(lan_ifname
, interface
, 1);
784 if (strncmp(lan_ifname
, "br", 2) == 0) {
785 eval("brctl", "addif", lan_ifname
, interface
);
786 notify_nas(interface
);
792 static int is_same_addr(struct ether_addr
*addr1
, struct ether_addr
*addr2
)
795 for (i
= 0; i
< 6; i
++) {
796 if (addr1
->octet
[i
] != addr2
->octet
[i
])
802 #define WL_MAX_ASSOC 128
803 static int check_wl_client(char *ifname
, int unit
, int subunit
)
805 struct ether_addr bssid
;
807 char buf
[WLC_IOCTL_MAXLEN
];
808 struct maclist
*mlist
;
810 int associated
, authorized
;
812 *(uint32
*)buf
= WLC_IOCTL_MAXLEN
;
813 if (wl_ioctl(ifname
, WLC_GET_BSSID
, &bssid
, ETHER_ADDR_LEN
) < 0 ||
814 wl_ioctl(ifname
, WLC_GET_BSS_INFO
, buf
, WLC_IOCTL_MAXLEN
) < 0)
817 bi
= (wl_bss_info_t
*)(buf
+ 4);
818 if ((bi
->SSID_len
== 0) ||
819 (bi
->BSSID
.octet
[0] + bi
->BSSID
.octet
[1] + bi
->BSSID
.octet
[2] +
820 bi
->BSSID
.octet
[3] + bi
->BSSID
.octet
[4] + bi
->BSSID
.octet
[5] == 0))
824 authorized
= strstr(nvram_safe_get(wl_nvname("akm", unit
, subunit
)), "psk") == 0;
826 mlsize
= sizeof(struct maclist
) + (WL_MAX_ASSOC
* sizeof(struct ether_addr
));
827 if ((mlist
= malloc(mlsize
)) != NULL
) {
828 mlist
->count
= WL_MAX_ASSOC
;
829 if (wl_ioctl(ifname
, WLC_GET_ASSOCLIST
, mlist
, mlsize
) == 0) {
830 for (i
= 0; i
< mlist
->count
; ++i
) {
831 if (is_same_addr(&mlist
->ea
[i
], &bi
->BSSID
)) {
838 if (associated
&& !authorized
) {
839 memset(mlist
, 0, mlsize
);
840 mlist
->count
= WL_MAX_ASSOC
;
841 strcpy((char*)mlist
, "autho_sta_list");
842 if (wl_ioctl(ifname
, WLC_GET_VAR
, mlist
, mlsize
) == 0) {
843 for (i
= 0; i
< mlist
->count
; ++i
) {
844 if (is_same_addr(&mlist
->ea
[i
], &bi
->BSSID
)) {
854 return (associated
&& authorized
);
857 #define STACHECK_CONNECT 30
858 #define STACHECK_DISCONNECT 5
860 static int radio_join(int idx
, int unit
, int subunit
, void *param
)
866 int *unit_filter
= param
;
867 if (*unit_filter
>= 0 && *unit_filter
!= unit
) return 0;
869 if (!nvram_get_int(wl_nvname("radio", unit
, 0)) || !wl_client(unit
, subunit
)) return 0;
871 ifname
= nvram_safe_get(wl_nvname("ifname", unit
, subunit
));
873 // skip disabled wl vifs
874 if (strncmp(ifname
, "wl", 2) == 0 && strchr(ifname
, '.') &&
875 !nvram_get_int(wl_nvname("bss_enabled", unit
, subunit
)))
878 sprintf(f
, "/var/run/radio.%d.%d.pid", unit
, subunit
< 0 ? 0 : subunit
);
879 if (f_read_string(f
, s
, sizeof(s
)) > 0) {
880 if ((i
= atoi(s
)) > 1) {
887 sprintf(s
, "%d", getpid());
888 f_write(f
, s
, sizeof(s
), 0, 0644);
890 int stacheck_connect
= nvram_get_int("sta_chkint");
891 if (stacheck_connect
<= 0)
892 stacheck_connect
= STACHECK_CONNECT
;
895 while (get_radio(unit
) && wl_client(unit
, subunit
)) {
897 if (check_wl_client(ifname
, unit
, subunit
)) {
898 stacheck
= stacheck_connect
;
901 eval("wl", "-i", ifname
, "disassoc");
903 char *amode
, *sec
= nvram_safe_get(wl_nvname("akm", unit
, subunit
));
905 if (strstr(sec
, "psk2")) amode
= "wpa2psk";
906 else if (strstr(sec
, "psk")) amode
= "wpapsk";
907 else if (strstr(sec
, "wpa2")) amode
= "wpa2";
908 else if (strstr(sec
, "wpa")) amode
= "wpa";
909 else if (nvram_get_int(wl_nvname("auth", unit
, subunit
))) amode
= "shared";
912 eval("wl", "-i", ifname
, "join", nvram_safe_get(wl_nvname("ssid", unit
, subunit
)),
913 "imode", "bss", "amode", amode
);
915 eval("wl", "-i", ifname
, "join", nvram_safe_get(wl_nvname("ssid", unit
, subunit
)));
917 stacheck
= STACHECK_DISCONNECT
;
933 static int radio_toggle(int idx
, int unit
, int subunit
, void *param
)
935 if (!nvram_get_int(wl_nvname("radio", unit
, 0))) return 0;
939 if (*op
== RADIO_TOGGLE
) {
940 *op
= get_radio(unit
) ? RADIO_OFF
: RADIO_ON
;
943 set_radio(*op
, unit
);
947 int radio_main(int argc
, char *argv
[])
954 usage_exit(argv
[0], "on|off|toggle|join [N]\n");
956 unit
= (argc
== 3) ? atoi(argv
[2]) : -1;
958 if (strcmp(argv
[1], "toggle") == 0)
960 else if (strcmp(argv
[1], "off") == 0)
962 else if (strcmp(argv
[1], "on") == 0)
964 else if (strcmp(argv
[1], "join") == 0)
970 op
= radio_toggle(0, unit
, 0, &op
);
972 op
= foreach_wif(0, &op
, radio_toggle
);
979 foreach_wif(1, &unit
, radio_join
);
984 int wdist_main(int argc, char *argv[])
993 if (wl_ioctl(nvram_safe_get("wl_ifname"), 101, &r, sizeof(r)) == 0) {
996 else v = (v - (9 + 1)) * 150;
997 printf("Current: %d-%dm (0x%02x)\n\n", v + (v ? 1 : 0), v + 150, r.val);
999 usage_exit(argv[0], "<meters>");
1001 if ((n = atoi(argv[1])) <= 0) setup_wldistance();
1002 else set_wldistance(n);
1007 static int get_wldist(int idx
, int unit
, int subunit
, void *param
)
1011 char *p
= nvram_safe_get(wl_nvname("distance", unit
, 0));
1012 if ((*p
== 0) || ((n
= atoi(p
)) < 0)) return 0;
1014 return (9 + (n
/ 150) + ((n
% 150) ? 1 : 0));
1017 static int wldist(int idx
, int unit
, int subunit
, void *param
)
1024 n
= get_wldist(idx
, unit
, subunit
, param
);
1026 s
= 0x10 | (n
<< 16);
1027 p
= nvram_safe_get(wl_nvname("ifname", unit
, 0));
1028 wl_ioctl(p
, 197, &s
, sizeof(s
));
1033 wl_ioctl(p
, 102, &r
, sizeof(r
));
1039 int wldist_main(int argc
, char *argv
[])
1042 if (foreach_wif(0, NULL
, get_wldist
) == 0) return 0;
1045 foreach_wif(0, NULL
, wldist
);