Merge branch 'VLAN-MultiSSID' into Toastman-VLAN
[tomato.git] / release / src / router / rc / network.c
blobfe9744bd29a65f07830afde0e41ec7ba0b831a68
1 /*
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
22 All Rights Reserved.
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.
32 wificonf, OpenWRT
33 Copyright (C) 2005 Felix Fietkau <nbd@vd-s.ath.cx>
38 Modified for Tomato Firmware
39 Portions, Copyright (C) 2006-2009 Jonathan Zarate
43 #include <rc.h>
45 #ifndef UU_INT
46 typedef u_int64_t u64;
47 typedef u_int32_t u32;
48 typedef u_int16_t u16;
49 typedef u_int8_t u8;
50 #endif
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>
58 #include <dirent.h>
60 #include <wlutils.h>
61 #include <bcmparams.h>
62 #include <wlioctl.h>
64 #ifndef WL_BSS_INFO_VERSION
65 #error WL_BSS_INFO_VERSION
66 #endif
67 #if WL_BSS_INFO_VERSION >= 108
68 #include <etioctl.h>
69 #else
70 #include <etsockio.h>
71 #endif
73 static void set_lan_hostname(const char *wan_hostname)
75 const char *s;
76 FILE *f;
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) {
83 char hostname[16];
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"))) {
89 fputs(hostname, f);
90 fclose(f);
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"));
100 #ifdef TCONFIG_IPV6
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"));
106 #endif
107 fclose(f);
111 void set_host_domain_name(void)
113 const char *s;
115 s = nvram_safe_get("wan_hostname");
116 sethostname(s, strlen(s));
117 set_lan_hostname(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)
126 int r;
127 char wl[24];
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");
136 if (r == 0) {
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);
157 return r;
160 // -----------------------------------------------------------------------------
162 #ifdef TCONFIG_EMF
163 static void emf_mfdb_update(char *lan_ifname, char *lan_port_ifname, bool add)
165 char word[256], *next;
166 char *mgrp, *ifname;
168 /* Add/Delete MFDB entries corresponding to new interface */
169 foreach (word, nvram_safe_get("emf_entry"), next) {
170 ifname = word;
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;
185 char *ifname;
187 /* Add/Delete UFFP entries corresponding to new interface */
188 foreach (word, nvram_safe_get("emf_uffp_entry"), next) {
189 ifname = word;
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;
203 char *ifname;
205 /* Add/Delete RTPORT entries corresponding to new interface */
206 foreach (word, nvram_safe_get("emf_rtport_entry"), next) {
207 ifname = word;
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)
220 /* Start EMF */
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);
239 #endif
241 // -----------------------------------------------------------------------------
243 /* Set initial QoS mode for all et interfaces that are up. */
244 void set_et_qos_mode(int sfd)
246 int i, qos;
247 caddr_t ifrdata;
248 struct ifreq ifr;
249 struct ethtool_drvinfo info;
251 qos = (strcmp(nvram_safe_get("wl_wme"), "off") != 0);
252 for (i = 1; i <= DEV_NUMIFS; i++) {
253 ifr.ifr_ifindex = 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;
257 /* get flags */
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)
280 char *p;
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
286 p = "0x0318";
288 else if (strcmp(p, "0x0188") == 0) { // G 2.0
289 p = "0x0388";
291 else if (strcmp(p, "0x2558") == 0) { // G 4.0, GL 1.0, 1.1
292 p = "0x2758";
294 else {
295 return;
298 nvram_set("boardflags", p);
300 if (!nvram_match("debug_abrst", "0")) {
301 modprobe_r("wl");
302 modprobe("wl");
306 /* safe?
308 unsigned long bf;
309 char s[64];
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);
319 static int set_wlmac(int idx, int unit, int subunit, void *param)
321 char *ifname;
323 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
325 // skip disabled wl vifs
326 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
327 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
328 return 0;
330 // set_mac(ifname, wl_nvname("macaddr", unit, subunit),
331 set_mac(ifname, wl_nvname("hwaddr", unit, subunit), // AB multiSSID
332 2 + unit + ((subunit > 0) ? ((unit + 1) * 0x10 + subunit) : 0));
334 return 1;
337 void start_wl(void)
339 char *lan_ifname, *lan_ifnames, *ifname, *p;
340 int unit, subunit;
341 int is_client = 0;
343 char tmp[32];
344 char br;
346 foreach_wif(1, NULL, set_wlmac);
348 for(br=0 ; br<4 ; br++) {
349 char bridge[2] = "0";
350 if (br!=0)
351 bridge[0]+=br;
352 else
353 strcpy(bridge, "");
355 strcpy(tmp,"lan");
356 strcat(tmp,bridge);
357 strcat(tmp, "_ifname");
358 lan_ifname = nvram_safe_get(tmp);
359 // lan_ifname = nvram_safe_get("lan_ifname");
360 if (strncmp(lan_ifname, "br", 2) == 0) {
361 strcpy(tmp,"lan");
362 strcat(tmp,bridge);
363 strcat(tmp, "_ifnames");
364 // if ((lan_ifnames = strdup(nvram_safe_get("lan_ifnames"))) != NULL) {
365 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
366 p = lan_ifnames;
367 while ((ifname = strsep(&p, " ")) != NULL) {
368 while (*ifname == ' ') ++ifname;
369 if (*ifname == 0) break;
371 unit = -1; subunit = -1;
373 // ignore disabled wl vifs
374 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
375 char nv[40];
376 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
377 if (!nvram_get_int(nv))
378 continue;
379 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
380 continue;
382 // get the instance number of the wl i/f
383 else if (wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit)))
384 continue;
386 is_client |= wl_client(unit, subunit) && nvram_get_int(wl_nvname("radio", unit, 0));
388 #ifdef CONFIG_BCMWL5
389 eval("wlconf", ifname, "start"); /* start wl iface */
390 #endif // CONFIG_BCMWL5
392 free(lan_ifnames);
395 #ifdef CONFIG_BCMWL5
396 else if (strcmp(lan_ifname, "")) {
397 /* specific non-bridged lan iface */
398 eval("wlconf", lan_ifname, "start");
400 #endif // CONFIG_BCMWL5
403 killall("wldist", SIGTERM);
404 eval("wldist");
406 if (is_client)
407 xstart("radio", "join");
410 #ifdef TCONFIG_IPV6
411 void enable_ipv6(int enable)
413 DIR *dir;
414 struct dirent *dirent;
415 char s[256];
417 if ((dir = opendir("/proc/sys/net/ipv6/conf")) != NULL) {
418 while ((dirent = readdir(dir)) != NULL) {
419 sprintf(s, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", dirent->d_name);
420 f_write_string(s, enable ? "0" : "1", 0, 0);
422 closedir(dir);
426 void accept_ra(const char *ifname)
428 char s[256];
430 sprintf(s, "/proc/sys/net/ipv6/conf/%s/accept_ra", ifname);
431 f_write_string(s, "2", 0, 0);
433 sprintf(s, "/proc/sys/net/ipv6/conf/%s/forwarding", ifname);
434 f_write_string(s, "2", 0, 0);
436 #endif
438 void start_lan(void)
440 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
442 char *lan_ifname;
443 struct ifreq ifr;
444 char *lan_ifnames, *ifname, *p;
445 int sfd;
446 uint32 ip;
447 int unit, subunit, sta;
448 int hwaddrset;
449 char eabuf[32];
450 char tmp[32];
451 char tmp2[32];
452 char br;
454 foreach_wif(1, NULL, set_wlmac);
455 check_afterburner();
456 #ifdef TCONFIG_IPV6
457 enable_ipv6(ipv6_enabled());
458 #endif
460 if ((sfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) return;
461 for(br=0 ; br<4 ; br++) {
462 char bridge[2] = "0";
463 if (br!=0)
464 bridge[0]+=br;
465 else
466 strcpy(bridge, "");
468 // lan_ifname = strdup(nvram_safe_get("lan_ifname"));
469 strcpy(tmp,"lan");
470 strcat(tmp,bridge);
471 strcat(tmp, "_ifname");
472 lan_ifname = strdup(nvram_safe_get(tmp));
474 if (strncmp(lan_ifname, "br", 2) == 0) {
475 _dprintf("%s: setting up the bridge %s\n", __FUNCTION__, lan_ifname);
477 eval("brctl", "addbr", lan_ifname);
478 eval("brctl", "setfd", lan_ifname, "0");
479 strcpy(tmp,"lan");
480 strcat(tmp,bridge);
481 strcat(tmp, "_stp");
482 eval("brctl", "stp", lan_ifname, nvram_safe_get(tmp));
484 #ifdef TCONFIG_EMF
485 if (nvram_get_int("emf_enable")) {
486 eval("emf", "add", "bridge", lan_ifname);
487 eval("igs", "add", "bridge", lan_ifname);
489 #endif
491 strcpy(tmp,"lan");
492 strcat(tmp,bridge);
493 strcat(tmp, "_ipaddr");
494 inet_aton(nvram_safe_get(tmp), (struct in_addr *)&ip);
496 hwaddrset = 0;
497 sta = 0;
499 strcpy(tmp,"lan");
500 strcat(tmp,bridge);
501 strcat(tmp, "_ifnames");
502 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
503 p = lan_ifnames;
504 while ((ifname = strsep(&p, " ")) != NULL) {
505 while (*ifname == ' ') ++ifname;
506 if (*ifname == 0) break;
508 unit = -1; subunit = -1;
510 // ignore disabled wl vifs
511 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
512 char nv[64];
514 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
515 if (!nvram_get_int(nv))
516 continue;
517 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
518 continue;
520 else
521 wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit));
523 // bring up interface
524 if (ifconfig(ifname, IFUP|IFF_ALLMULTI, NULL, NULL) != 0) continue;
526 // set the logical bridge address to that of the first interface
527 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
528 if ((!hwaddrset) ||
529 (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0 &&
530 memcmp(ifr.ifr_hwaddr.sa_data, "\0\0\0\0\0\0", ETHER_ADDR_LEN) == 0)) {
531 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
532 if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) {
533 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
534 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
535 _dprintf("%s: setting MAC of %s bridge to %s\n", __FUNCTION__,
536 ifr.ifr_name, ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
537 ioctl(sfd, SIOCSIFHWADDR, &ifr);
538 hwaddrset = 1;
542 if (wlconf(ifname, unit, subunit) == 0) {
543 const char *mode = nvram_safe_get(wl_nvname("mode", unit, subunit));
545 if (strcmp(mode, "wet") == 0) {
546 // Enable host DHCP relay
547 if (nvram_get_int("dhcp_relay")) {
548 wl_iovar_set(ifname, "wet_host_mac", ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
549 wl_iovar_setint(ifname, "wet_host_ipv4", ip);
553 sta |= (strcmp(mode, "sta") == 0);
554 if ((strcmp(mode, "ap") != 0) && (strcmp(mode, "wet") != 0)) continue;
556 eval("brctl", "addif", lan_ifname, ifname);
557 #ifdef TCONFIG_EMF
558 if (nvram_get_int("emf_enable"))
559 eval("emf", "add", "iface", lan_ifname, ifname);
560 #endif
563 if ((nvram_get_int("wan_islan")) && (br==0) &&
564 ((get_wan_proto() == WP_DISABLED) || (sta))) {
565 ifname = nvram_get("wan_ifnameX");
566 if (ifconfig(ifname, IFUP, NULL, NULL) == 0)
567 eval("brctl", "addif", lan_ifname, ifname);
570 free(lan_ifnames);
573 // --- this shouldn't happen ---
574 else if (*lan_ifname) {
575 ifconfig(lan_ifname, IFUP, NULL, NULL);
576 wlconf(lan_ifname, -1, -1);
578 else {
579 close(sfd);
580 free(lan_ifname);
581 return;
584 // Get current LAN hardware address
585 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
586 strcpy(tmp,"lan");
587 strcat(tmp,bridge);
588 strcat(tmp, "_hwaddr");
589 // if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set("lan_hwaddr", ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
590 if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set(tmp, ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
592 // Set initial QoS mode for LAN ports
593 set_et_qos_mode(sfd);
595 close(sfd);
597 // bring up and configure LAN interface
598 strcpy(tmp,"lan");
599 strcat(tmp,bridge);
600 strcat(tmp, "_ipaddr");
601 strcpy(tmp2,"lan");
602 strcat(tmp2,bridge);
603 strcat(tmp2, "_netmask");
604 ifconfig(lan_ifname, IFUP, nvram_safe_get(tmp), nvram_safe_get(tmp2));
606 config_loopback();
607 do_static_routes(1);
609 if(br==0)
610 set_lan_hostname(nvram_safe_get("wan_hostname"));
612 if ((get_wan_proto() == WP_DISABLED) && (br==0)) {
613 char *gateway = nvram_safe_get("lan_gateway") ;
614 if ((*gateway) && (strcmp(gateway, "0.0.0.0") != 0)) {
615 int tries = 5;
616 while ((route_add(lan_ifname, 0, "0.0.0.0", gateway, "0.0.0.0") != 0) && (tries-- > 0)) sleep(1);
617 _dprintf("%s: add gateway=%s tries=%d\n", __FUNCTION__, gateway, tries);
621 #ifdef TCONFIG_IPV6
622 start_ipv6();
623 #endif
625 #ifdef TCONFIG_EMF
626 if (nvram_get_int("emf_enable")) start_emf(lan_ifname);
627 #endif
629 free(lan_ifname);
631 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
634 void stop_lan(void)
636 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
638 char *lan_ifname;
639 char *lan_ifnames, *p, *ifname;
640 char tmp[32];
641 char br;
643 for(br=0 ; br<4 ; br++) {
644 char bridge[2] = "0";
645 if (br!=0)
646 bridge[0]+=br;
647 else
648 strcpy(bridge, "");
650 strcpy(tmp,"lan");
651 strcat(tmp,bridge);
652 strcat(tmp, "_ifname");
653 lan_ifname = nvram_safe_get(tmp);
654 ifconfig(lan_ifname, 0, NULL, NULL);
656 #ifdef TCONFIG_IPV6
657 stop_ipv6();
658 #endif
660 if (strncmp(lan_ifname, "br", 2) == 0) {
661 #ifdef TCONFIG_EMF
662 stop_emf(lan_ifname);
663 #endif
664 strcpy(tmp,"lan");
665 strcat(tmp,bridge);
666 strcat(tmp, "_ifnames");
667 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
668 p = lan_ifnames;
669 while ((ifname = strsep(&p, " ")) != NULL) {
670 while (*ifname == ' ') ++ifname;
671 if (*ifname == 0) break;
672 eval("wlconf", ifname, "down");
673 ifconfig(ifname, 0, NULL, NULL);
674 eval("brctl", "delif", lan_ifname, ifname);
676 free(lan_ifnames);
678 eval("brctl", "delbr", lan_ifname);
680 else if (*lan_ifname) {
681 eval("wlconf", lan_ifname, "down");
684 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
688 void do_static_routes(int add)
690 char *buf;
691 char *p, *q;
692 char *dest, *mask, *gateway, *metric, *ifname;
693 int r;
695 if ((buf = strdup(nvram_safe_get(add ? "routes_static" : "routes_static_saved"))) == NULL) return;
696 if (add) nvram_set("routes_static_saved", buf);
697 else nvram_unset("routes_static_saved");
698 p = buf;
699 while ((q = strsep(&p, ">")) != NULL) {
700 if (vstrsep(q, "<", &dest, &gateway, &mask, &metric, &ifname) != 5) continue;
701 // ifname = nvram_safe_get((*ifname == 'L') ? "lan_ifname" :
702 // ((*ifname == 'W') ? "wan_iface" : "wan_ifname"));
703 ifname = nvram_safe_get(((strcmp(ifname,"LAN")==0) ? "lan_ifname" :
704 ((strcmp(ifname,"LAN1")==0) ? "lan1_ifname" :
705 ((strcmp(ifname,"LAN2")==0) ? "lan2_ifname" :
706 ((strcmp(ifname,"LAN3")==0) ? "lan3_ifname" :
707 ((*ifname == 'W') ? "wan_iface" : "wan_ifname"))))));
708 if (add) {
709 for (r = 3; r >= 0; --r) {
710 if (route_add(ifname, atoi(metric), dest, gateway, mask) == 0) break;
711 sleep(1);
714 else {
715 route_del(ifname, atoi(metric), dest, gateway, mask);
718 free(buf);
721 void hotplug_net(void)
723 char *interface, *action;
724 char *lan_ifname;
726 if (((interface = getenv("INTERFACE")) == NULL) || ((action = getenv("ACTION")) == NULL)) return;
728 _dprintf("hotplug net INTERFACE=%s ACTION=%s\n", interface, action);
730 if ((strncmp(interface, "wds", 3) == 0) &&
731 (strcmp(action, "register") == 0 || strcmp(action, "add") == 0)) {
732 ifconfig(interface, IFUP, NULL, NULL);
733 lan_ifname = nvram_safe_get("lan_ifname");
734 #ifdef TCONFIG_EMF
735 if (nvram_get_int("emf_enable")) {
736 eval("emf", "add", "iface", lan_ifname, interface);
737 emf_mfdb_update(lan_ifname, interface, 1);
738 emf_uffp_update(lan_ifname, interface, 1);
739 emf_rtport_update(lan_ifname, interface, 1);
741 #endif
742 if (strncmp(lan_ifname, "br", 2) == 0) {
743 eval("brctl", "addif", lan_ifname, interface);
744 notify_nas(interface);
750 static int is_same_addr(struct ether_addr *addr1, struct ether_addr *addr2)
752 int i;
753 for (i = 0; i < 6; i++) {
754 if (addr1->octet[i] != addr2->octet[i])
755 return 0;
757 return 1;
760 #define WL_MAX_ASSOC 128
761 static int check_wl_client(char *ifname, int unit, int subunit)
763 struct ether_addr bssid;
764 wl_bss_info_t *bi;
765 char buf[WLC_IOCTL_MAXLEN];
766 struct maclist *mlist;
767 int mlsize, i;
768 int associated, authorized;
770 *(uint32 *)buf = WLC_IOCTL_MAXLEN;
771 if (wl_ioctl(ifname, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN) < 0 ||
772 wl_ioctl(ifname, WLC_GET_BSS_INFO, buf, WLC_IOCTL_MAXLEN) < 0)
773 return 0;
775 bi = (wl_bss_info_t *)(buf + 4);
776 if ((bi->SSID_len == 0) ||
777 (bi->BSSID.octet[0] + bi->BSSID.octet[1] + bi->BSSID.octet[2] +
778 bi->BSSID.octet[3] + bi->BSSID.octet[4] + bi->BSSID.octet[5] == 0))
779 return 0;
781 associated = 0;
782 authorized = strstr(nvram_safe_get(wl_nvname("akm", unit, subunit)), "psk") == 0;
784 mlsize = sizeof(struct maclist) + (WL_MAX_ASSOC * sizeof(struct ether_addr));
785 if ((mlist = malloc(mlsize)) != NULL) {
786 mlist->count = WL_MAX_ASSOC;
787 if (wl_ioctl(ifname, WLC_GET_ASSOCLIST, mlist, mlsize) == 0) {
788 for (i = 0; i < mlist->count; ++i) {
789 if (is_same_addr(&mlist->ea[i], &bi->BSSID)) {
790 associated = 1;
791 break;
796 if (associated && !authorized) {
797 memset(mlist, 0, mlsize);
798 mlist->count = WL_MAX_ASSOC;
799 strcpy((char*)mlist, "autho_sta_list");
800 if (wl_ioctl(ifname, WLC_GET_VAR, mlist, mlsize) == 0) {
801 for (i = 0; i < mlist->count; ++i) {
802 if (is_same_addr(&mlist->ea[i], &bi->BSSID)) {
803 authorized = 1;
804 break;
809 free(mlist);
812 return (associated && authorized);
815 #define STACHECK_CONNECT 30
816 #define STACHECK_DISCONNECT 5
818 static int radio_join(int idx, int unit, int subunit, void *param)
820 int i;
821 char s[32], f[64];
822 char *ifname;
824 int *unit_filter = param;
825 if (*unit_filter >= 0 && *unit_filter != unit) return 0;
827 if (!nvram_get_int(wl_nvname("radio", unit, 0)) || !wl_client(unit, subunit)) return 0;
829 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
831 // skip disabled wl vifs
832 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
833 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
834 return 0;
836 sprintf(f, "/var/run/radio.%d.%d.pid", unit, subunit < 0 ? 0 : subunit);
837 if (f_read_string(f, s, sizeof(s)) > 0) {
838 if ((i = atoi(s)) > 1) {
839 kill(i, SIGTERM);
840 sleep(1);
844 if (fork() == 0) {
845 sprintf(s, "%d", getpid());
846 f_write(f, s, sizeof(s), 0, 0644);
848 int stacheck_connect = nvram_get_int("sta_chkint");
849 if (stacheck_connect <= 0)
850 stacheck_connect = STACHECK_CONNECT;
851 int stacheck;
853 while (get_radio(unit) && wl_client(unit, subunit)) {
855 if (check_wl_client(ifname, unit, subunit)) {
856 stacheck = stacheck_connect;
858 else {
859 eval("wl", "-i", ifname, "disassoc");
860 #ifdef CONFIG_BCMWL5
861 char *amode, *sec = nvram_safe_get(wl_nvname("akm", unit, subunit));
863 if (strstr(sec, "psk2")) amode = "wpa2psk";
864 else if (strstr(sec, "psk")) amode = "wpapsk";
865 else if (strstr(sec, "wpa2")) amode = "wpa2";
866 else if (strstr(sec, "wpa")) amode = "wpa";
867 else if (nvram_get_int(wl_nvname("auth", unit, subunit))) amode = "shared";
868 else amode = "open";
870 eval("wl", "-i", ifname, "join", nvram_safe_get(wl_nvname("ssid", unit, subunit)),
871 "imode", "bss", "amode", amode);
872 #else
873 eval("wl", "-i", ifname, "join", nvram_safe_get(wl_nvname("ssid", unit, subunit)));
874 #endif
875 stacheck = STACHECK_DISCONNECT;
877 sleep(stacheck);
879 unlink(f);
882 return 1;
885 enum {
886 RADIO_OFF = 0,
887 RADIO_ON = 1,
888 RADIO_TOGGLE = 2
891 static int radio_toggle(int idx, int unit, int subunit, void *param)
893 if (!nvram_get_int(wl_nvname("radio", unit, 0))) return 0;
895 int *op = param;
897 if (*op == RADIO_TOGGLE) {
898 *op = get_radio(unit) ? RADIO_OFF : RADIO_ON;
901 set_radio(*op, unit);
902 return *op;
905 int radio_main(int argc, char *argv[])
907 int op = RADIO_OFF;
908 int unit;
910 if (argc < 2) {
911 HELP:
912 usage_exit(argv[0], "on|off|toggle|join [N]\n");
914 unit = (argc == 3) ? atoi(argv[2]) : -1;
916 if (strcmp(argv[1], "toggle") == 0)
917 op = RADIO_TOGGLE;
918 else if (strcmp(argv[1], "off") == 0)
919 op = RADIO_OFF;
920 else if (strcmp(argv[1], "on") == 0)
921 op = RADIO_ON;
922 else if (strcmp(argv[1], "join") == 0)
923 goto JOIN;
924 else
925 goto HELP;
927 if (unit >= 0)
928 op = radio_toggle(0, unit, 0, &op);
929 else
930 op = foreach_wif(0, &op, radio_toggle);
932 if (!op) {
933 led(LED_DIAG, 0);
934 return 0;
936 JOIN:
937 foreach_wif(1, &unit, radio_join);
938 return 0;
942 int wdist_main(int argc, char *argv[])
944 int n;
945 rw_reg_t r;
946 int v;
948 if (argc != 2) {
949 r.byteoff = 0x684;
950 r.size = 2;
951 if (wl_ioctl(nvram_safe_get("wl_ifname"), 101, &r, sizeof(r)) == 0) {
952 v = r.val - 510;
953 if (v <= 9) v = 0;
954 else v = (v - (9 + 1)) * 150;
955 printf("Current: %d-%dm (0x%02x)\n\n", v + (v ? 1 : 0), v + 150, r.val);
957 usage_exit(argv[0], "<meters>");
959 if ((n = atoi(argv[1])) <= 0) setup_wldistance();
960 else set_wldistance(n);
961 return 0;
965 static int get_wldist(int idx, int unit, int subunit, void *param)
967 int n;
969 char *p = nvram_safe_get(wl_nvname("distance", unit, 0));
970 if ((*p == 0) || ((n = atoi(p)) < 0)) return 0;
972 return (9 + (n / 150) + ((n % 150) ? 1 : 0));
975 static int wldist(int idx, int unit, int subunit, void *param)
977 rw_reg_t r;
978 uint32 s;
979 char *p;
980 int n;
982 n = get_wldist(idx, unit, subunit, param);
983 if (n > 0) {
984 s = 0x10 | (n << 16);
985 p = nvram_safe_get(wl_nvname("ifname", unit, 0));
986 wl_ioctl(p, 197, &s, sizeof(s));
988 r.byteoff = 0x684;
989 r.val = n + 510;
990 r.size = 2;
991 wl_ioctl(p, 102, &r, sizeof(r));
993 return 0;
996 // ref: wificonf.c
997 int wldist_main(int argc, char *argv[])
999 if (fork() == 0) {
1000 if (foreach_wif(0, NULL, get_wldist) == 0) return 0;
1002 while (1) {
1003 foreach_wif(0, NULL, wldist);
1004 sleep(2);
1008 return 0;