Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / rc / network.c
blob0c9193e92b7dbac0e686f52c5828adcd4db189a5
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 void restart_wl(void);
74 void stop_lan_wl(void);
75 void start_lan_wl(void);
77 static void set_lan_hostname(const char *wan_hostname)
79 const char *s;
80 FILE *f;
82 nvram_set("lan_hostname", wan_hostname);
83 if ((wan_hostname == NULL) || (*wan_hostname == 0)) {
84 /* derive from et0 mac address */
85 s = nvram_get("et0macaddr");
86 if (s && strlen(s) >= 17) {
87 char hostname[16];
88 sprintf(hostname, "RT-%c%c%c%c%c%c%c%c%c%c%c%c",
89 s[0], s[1], s[3], s[4], s[6], s[7],
90 s[9], s[10], s[12], s[13], s[15], s[16]);
92 if ((f = fopen("/proc/sys/kernel/hostname", "w"))) {
93 fputs(hostname, f);
94 fclose(f);
96 nvram_set("lan_hostname", hostname);
100 if ((f = fopen("/etc/hosts", "w"))) {
101 fprintf(f, "127.0.0.1 localhost\n");
102 if ((s = nvram_get("lan_ipaddr")) && (*s))
103 fprintf(f, "%s %s %s-lan\n", s, nvram_safe_get("lan_hostname"), nvram_safe_get("lan_hostname"));
104 #ifdef TCONFIG_VLAN
105 if ((s = nvram_get("lan1_ipaddr")) && (*s) && (strcmp(s,"") != 0))
106 fprintf(f, "%s %s-lan1\n", s, nvram_safe_get("lan_hostname"));
107 if ((s = nvram_get("lan2_ipaddr")) && (*s) && (strcmp(s,"") != 0))
108 fprintf(f, "%s %s-lan2\n", s, nvram_safe_get("lan_hostname"));
109 if ((s = nvram_get("lan3_ipaddr")) && (*s) && (strcmp(s,"") != 0))
110 fprintf(f, "%s %s-lan3\n", s, nvram_safe_get("lan_hostname"));
111 #endif
112 #ifdef TCONFIG_IPV6
113 if (ipv6_enabled()) {
114 fprintf(f, "::1 localhost\n");
115 s = ipv6_router_address(NULL);
116 if (*s) fprintf(f, "%s %s\n", s, nvram_safe_get("lan_hostname"));
118 #endif
119 fclose(f);
123 void set_host_domain_name(void)
125 const char *s;
127 s = nvram_safe_get("wan_hostname");
128 sethostname(s, strlen(s));
129 set_lan_hostname(s);
131 s = nvram_get("wan_domain");
132 if ((s == NULL) || (*s == 0)) s = nvram_safe_get("wan_get_domain");
133 setdomainname(s, strlen(s));
136 static int wlconf(char *ifname, int unit, int subunit)
138 int r;
139 char wl[24];
141 if (/* !wl_probe(ifname) && */ unit >= 0) {
142 // validate nvram settings for wireless i/f
143 snprintf(wl, sizeof(wl), "--wl%d", unit);
144 eval("nvram", "validate", wl);
147 r = eval("wlconf", ifname, "up");
148 if (r == 0) {
149 if (unit >= 0 && subunit <= 0) {
150 // setup primary wl interface
151 nvram_set("rrules_radio", "-1");
153 eval("wl", "-i", ifname, "antdiv", nvram_safe_get(wl_nvname("antdiv", unit, 0)));
154 eval("wl", "-i", ifname, "txant", nvram_safe_get(wl_nvname("txant", unit, 0)));
155 eval("wl", "-i", ifname, "txpwr1", "-o", "-m", nvram_get_int(wl_nvname("txpwr", unit, 0)) ? nvram_safe_get(wl_nvname("txpwr", unit, 0)) : "-1");
156 eval("wl", "-i", ifname, "interference", nvram_safe_get(wl_nvname("mitigation", unit, 0)));
159 if (wl_client(unit, subunit)) {
160 if (nvram_match(wl_nvname("mode", unit, subunit), "wet")) {
161 ifconfig(ifname, IFUP|IFF_ALLMULTI, NULL, NULL);
163 if (nvram_get_int(wl_nvname("radio", unit, 0))) {
164 snprintf(wl, sizeof(wl), "%d", unit);
165 xstart("radio", "join", wl);
169 return r;
172 // -----------------------------------------------------------------------------
174 #ifdef TCONFIG_EMF
175 static void emf_mfdb_update(char *lan_ifname, char *lan_port_ifname, bool add)
177 char word[256], *next;
178 char *mgrp, *ifname;
180 /* Add/Delete MFDB entries corresponding to new interface */
181 foreach (word, nvram_safe_get("emf_entry"), next) {
182 ifname = word;
183 mgrp = strsep(&ifname, ":");
185 if ((mgrp == NULL) || (ifname == NULL)) continue;
187 /* Add/Delete MFDB entry using the group addr and interface */
188 if (lan_port_ifname == NULL || strcmp(lan_port_ifname, ifname) == 0) {
189 eval("emf", ((add) ? "add" : "del"), "mfdb", lan_ifname, mgrp, ifname);
194 static void emf_uffp_update(char *lan_ifname, char *lan_port_ifname, bool add)
196 char word[256], *next;
197 char *ifname;
199 /* Add/Delete UFFP entries corresponding to new interface */
200 foreach (word, nvram_safe_get("emf_uffp_entry"), next) {
201 ifname = word;
203 if (ifname == NULL) continue;
205 /* Add/Delete UFFP entry for the interface */
206 if (lan_port_ifname == NULL || strcmp(lan_port_ifname, ifname) == 0) {
207 eval("emf", ((add) ? "add" : "del"), "uffp", lan_ifname, ifname);
212 static void emf_rtport_update(char *lan_ifname, char *lan_port_ifname, bool add)
214 char word[256], *next;
215 char *ifname;
217 /* Add/Delete RTPORT entries corresponding to new interface */
218 foreach (word, nvram_safe_get("emf_rtport_entry"), next) {
219 ifname = word;
221 if (ifname == NULL) continue;
223 /* Add/Delete RTPORT entry for the interface */
224 if (lan_port_ifname == NULL || strcmp(lan_port_ifname, ifname) == 0) {
225 eval("emf", ((add) ? "add" : "del"), "rtport", lan_ifname, ifname);
230 static void start_emf(char *lan_ifname)
232 /* Start EMF */
233 eval("emf", "start", lan_ifname);
235 /* Add the static MFDB entries */
236 emf_mfdb_update(lan_ifname, NULL, 1);
238 /* Add the UFFP entries */
239 emf_uffp_update(lan_ifname, NULL, 1);
241 /* Add the RTPORT entries */
242 emf_rtport_update(lan_ifname, NULL, 1);
245 static void stop_emf(char *lan_ifname)
247 eval("emf", "stop", lan_ifname);
248 eval("igs", "del", "bridge", lan_ifname);
249 eval("emf", "del", "bridge", lan_ifname);
251 #endif
253 // -----------------------------------------------------------------------------
255 /* Set initial QoS mode for all et interfaces that are up. */
256 void set_et_qos_mode(int sfd)
258 int i, qos;
259 caddr_t ifrdata;
260 struct ifreq ifr;
261 struct ethtool_drvinfo info;
263 qos = (strcmp(nvram_safe_get("wl_wme"), "off") != 0);
264 for (i = 1; i <= DEV_NUMIFS; i++) {
265 ifr.ifr_ifindex = i;
266 if (ioctl(sfd, SIOCGIFNAME, &ifr)) continue;
267 if (ioctl(sfd, SIOCGIFHWADDR, &ifr)) continue;
268 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) continue;
269 /* get flags */
270 if (ioctl(sfd, SIOCGIFFLAGS, &ifr)) continue;
271 /* if up (wan may not be up yet at this point) */
272 if (ifr.ifr_flags & IFF_UP) {
273 ifrdata = ifr.ifr_data;
274 memset(&info, 0, sizeof(info));
275 info.cmd = ETHTOOL_GDRVINFO;
276 ifr.ifr_data = (caddr_t)&info;
277 if (ioctl(sfd, SIOCETHTOOL, &ifr) >= 0) {
278 /* Set QoS for et & bcm57xx devices */
279 if (!strncmp(info.driver, "et", 2) ||
280 !strncmp(info.driver, "bcm57", 5)) {
281 ifr.ifr_data = (caddr_t)&qos;
282 ioctl(sfd, SIOCSETCQOS, &ifr);
285 ifr.ifr_data = ifrdata;
290 static void check_afterburner(void)
292 char *p;
294 if (nvram_match("wl_afterburner", "off")) return;
295 if ((p = nvram_get("boardflags")) == NULL) return;
297 if (strcmp(p, "0x0118") == 0) { // G 2.2, 3.0, 3.1
298 p = "0x0318";
300 else if (strcmp(p, "0x0188") == 0) { // G 2.0
301 p = "0x0388";
303 else if (strcmp(p, "0x2558") == 0) { // G 4.0, GL 1.0, 1.1
304 p = "0x2758";
306 else {
307 return;
310 nvram_set("boardflags", p);
312 if (!nvram_match("debug_abrst", "0")) {
313 stop_wireless();
314 unload_wl();
315 load_wl();
316 start_wireless();
320 /* safe?
322 unsigned long bf;
323 char s[64];
325 bf = strtoul(p, &p, 0);
326 if ((*p == 0) && ((bf & BFL_AFTERBURNER) == 0)) {
327 sprintf(s, "0x%04lX", bf | BFL_AFTERBURNER);
328 nvram_set("boardflags", s);
333 void unload_wl(void)
335 modprobe_r("wl");
338 void load_wl(void)
340 modprobe("wl");
343 static int set_wlmac(int idx, int unit, int subunit, void *param)
345 char *ifname;
347 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
349 // skip disabled wl vifs
350 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
351 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
352 return 0;
354 if (strcmp(nvram_safe_get(wl_nvname("hwaddr", unit, subunit)), "") == 0) {
355 // set_mac(ifname, wl_nvname("macaddr", unit, subunit),
356 set_mac(ifname, wl_nvname("hwaddr", unit, subunit), // AB multiSSID
357 2 + unit + ((subunit > 0) ? ((unit + 1) * 0x10 + subunit) : 0));
358 } else {
359 set_mac(ifname, wl_nvname("hwaddr", unit, subunit), 0);
361 return 1;
364 void stop_lan_wl(void)
366 char *p, *ifname;
367 char *wl_ifnames;
368 char *lan_ifname;
369 #ifdef CONFIG_BCMWL5
370 int unit, subunit;
371 #endif
373 eval("ebtables", "-F");
375 char tmp[32];
376 char br;
378 for(br=0 ; br<4 ; br++) {
379 char bridge[2] = "0";
380 if (br!=0)
381 bridge[0]+=br;
382 else
383 strcpy(bridge, "");
385 strcpy(tmp,"lan");
386 strcat(tmp,bridge);
387 strcat(tmp, "_ifname");
388 lan_ifname = nvram_safe_get(tmp);
390 strcpy(tmp,"lan");
391 strcat(tmp,bridge);
392 strcat(tmp, "_ifnames");
393 if ((wl_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
394 p = wl_ifnames;
395 while ((ifname = strsep(&p, " ")) != NULL) {
396 while (*ifname == ' ') ++ifname;
397 if (*ifname == 0) continue;
398 #ifdef CONFIG_BCMWL5
399 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
400 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
401 continue;
403 else if (wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit)))
404 continue;
406 eval("wlconf", ifname, "down");
407 #endif
408 eval("brctl", "delif", lan_ifname, ifname);
409 ifconfig(ifname, 0, NULL, NULL);
411 free(wl_ifnames);
416 void start_lan_wl(void)
418 char *lan_ifname;
419 #ifdef CONFIG_BCMWL5
420 struct ifreq ifr;
421 #endif
422 char *wl_ifnames, *ifname, *p;
423 uint32 ip;
424 int unit, subunit, sta;
426 char tmp[32];
427 char br;
429 #ifdef CONFIG_BCMWL5
430 foreach_wif(0, NULL, set_wlmac);
431 #else
432 foreach_wif(1, NULL, set_wlmac);
433 #endif
435 for(br=0 ; br<4 ; br++) {
436 char bridge[2] = "0";
437 if (br!=0)
438 bridge[0]+=br;
439 else
440 strcpy(bridge, "");
442 strcpy(tmp,"lan");
443 strcat(tmp,bridge);
444 strcat(tmp, "_ifname");
445 lan_ifname = nvram_safe_get(tmp);
447 if (strncmp(lan_ifname, "br", 2) == 0) {
448 strcpy(tmp,"lan");
449 strcat(tmp,bridge);
450 strcat(tmp, "_ipaddr");
451 inet_aton(nvram_safe_get(tmp), (struct in_addr *)&ip);
453 strcpy(tmp,"lan");
454 strcat(tmp,bridge);
455 strcat(tmp, "_ifnames");
457 sta = 0;
459 if ((wl_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
460 p = wl_ifnames;
461 while ((ifname = strsep(&p, " ")) != NULL) {
462 while (*ifname == ' ') ++ifname;
463 if (*ifname == 0) continue;
465 unit = -1; subunit = -1;
467 // ignore disabled wl vifs
468 #ifdef CONFIG_BCMWL5
469 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
470 #endif
471 char nv[40];
472 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
473 if (!nvram_get_int(nv))
474 continue;
475 #ifdef CONFIG_BCMWL5
476 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
477 continue;
478 set_wlmac(0, unit, subunit, NULL);
480 else
481 wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit));
482 #endif
484 // bring up interface
485 if (ifconfig(ifname, IFUP, NULL, NULL) != 0) continue;
487 #ifdef CONFIG_BCMWL5
488 if (wlconf(ifname, unit, subunit) == 0) {
489 const char *mode = nvram_safe_get(wl_nvname("mode", unit, subunit));
491 if (strcmp(mode, "wet") == 0) {
492 // Enable host DHCP relay
493 if (nvram_get_int("dhcp_relay")) {
494 wl_iovar_set(ifname, "wet_host_mac", ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
495 wl_iovar_setint(ifname, "wet_host_ipv4", ip);
499 sta |= (strcmp(mode, "sta") == 0);
500 if ((strcmp(mode, "ap") != 0) && (strcmp(mode, "wet") != 0)) continue;
502 #endif
503 eval("brctl", "addif", lan_ifname, ifname);
505 free(wl_ifnames);
511 void stop_wireless()
513 #ifdef CONFIG_BCMWL5
514 stop_nas();
515 #endif
516 stop_lan_wl();
519 void start_wireless()
521 start_lan_wl();
523 #ifdef CONFIG_BCMWL5
524 start_nas();
525 #endif
526 restart_wl();
529 void restart_wl(void)
531 char *lan_ifnames, *ifname, *p;
532 int unit, subunit;
533 int is_client = 0;
535 char tmp[32];
536 char br;
538 for(br=0 ; br<4 ; br++) {
539 char bridge[2] = "0";
540 if (br!=0)
541 bridge[0]+=br;
542 else
543 strcpy(bridge, "");
545 strcpy(tmp,"lan");
546 strcat(tmp,bridge);
547 strcat(tmp, "_ifnames");
548 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
549 p = lan_ifnames;
550 while ((ifname = strsep(&p, " ")) != NULL) {
551 while (*ifname == ' ') ++ifname;
552 if (*ifname == 0) continue;
554 unit = -1; subunit = -1;
556 // ignore disabled wl vifs
557 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
558 char nv[40];
559 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
560 if (!nvram_get_int(nv))
561 continue;
562 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
563 continue;
565 // get the instance number of the wl i/f
566 else if (wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit)))
567 continue;
569 is_client |= wl_client(unit, subunit) && nvram_get_int(wl_nvname("radio", unit, 0));
571 #ifdef CONFIG_BCMWL5
572 eval("wlconf", ifname, "start"); /* start wl iface */
573 #endif // CONFIG_BCMWL5
575 free(lan_ifnames);
579 killall("wldist", SIGTERM);
580 eval("wldist");
582 if (is_client)
583 xstart("radio", "join");
586 #ifdef CONFIG_BCMWL5
587 static int disabled_wl(int idx, int unit, int subunit, void *param)
589 char *ifname;
591 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
593 // skip disabled wl vifs
594 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
595 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
596 return 1;
597 return 0;
599 #endif
601 void start_wl(void)
603 char *lan_ifname, *lan_ifnames, *ifname, *p;
604 int unit, subunit;
605 int is_client = 0;
607 char tmp[32];
608 char br;
610 #ifdef CONFIG_BCMWL5
611 // HACK: When a virtual SSID is disabled, it requires two initialisation
612 if (foreach_wif(1, NULL, disabled_wl))
614 stop_wireless();
615 start_wireless();
616 return;
618 #endif
620 for(br=0 ; br<4 ; br++) {
621 char bridge[2] = "0";
622 if (br!=0)
623 bridge[0]+=br;
624 else
625 strcpy(bridge, "");
627 strcpy(tmp,"lan");
628 strcat(tmp,bridge);
629 strcat(tmp, "_ifname");
630 lan_ifname = nvram_safe_get(tmp);
631 if (strncmp(lan_ifname, "br", 2) == 0) {
632 strcpy(tmp,"lan");
633 strcat(tmp,bridge);
634 strcat(tmp, "_ifnames");
635 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
636 p = lan_ifnames;
637 while ((ifname = strsep(&p, " ")) != NULL) {
638 while (*ifname == ' ') ++ifname;
639 if (*ifname == 0) continue;
641 unit = -1; subunit = -1;
643 // ignore disabled wl vifs
644 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
645 char nv[40];
646 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
647 if (!nvram_get_int(nv))
648 continue;
649 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
650 continue;
652 // get the instance number of the wl i/f
653 else if (wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit)))
654 continue;
656 is_client |= wl_client(unit, subunit) && nvram_get_int(wl_nvname("radio", unit, 0));
658 #ifdef CONFIG_BCMWL5
659 eval("wlconf", ifname, "start"); /* start wl iface */
660 #endif // CONFIG_BCMWL5
662 free(lan_ifnames);
665 #ifdef CONFIG_BCMWL5
666 else if (strcmp(lan_ifname, "")) {
667 /* specific non-bridged lan iface */
668 eval("wlconf", lan_ifname, "start");
670 #endif // CONFIG_BCMWL5
673 killall("wldist", SIGTERM);
674 eval("wldist");
676 if (is_client)
677 xstart("radio", "join");
680 #ifdef TCONFIG_IPV6
681 void enable_ipv6(int enable)
683 DIR *dir;
684 struct dirent *dirent;
685 char s[256];
687 if ((dir = opendir("/proc/sys/net/ipv6/conf")) != NULL) {
688 while ((dirent = readdir(dir)) != NULL) {
689 if (strcmp("vlan1", dirent->d_name) &&
690 strcmp("eth0", dirent->d_name) &&
691 strcmp("all", dirent->d_name) &&
692 strcmp("eth1", dirent->d_name))
695 sprintf(s, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", dirent->d_name);
696 f_write_string(s, enable ? "0" : "1", 0, 0);
699 closedir(dir);
703 void accept_ra(const char *ifname)
705 char s[256];
707 sprintf(s, "/proc/sys/net/ipv6/conf/%s/accept_ra", ifname);
708 f_write_string(s, "2", 0, 0);
710 sprintf(s, "/proc/sys/net/ipv6/conf/%s/forwarding", ifname);
711 f_write_string(s, "2", 0, 0);
713 #endif
715 void start_lan(void)
717 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
719 char *lan_ifname;
720 struct ifreq ifr;
721 char *lan_ifnames, *ifname, *p;
722 int sfd;
723 uint32 ip;
724 int unit, subunit, sta;
725 int hwaddrset;
726 char eabuf[32];
727 char tmp[32];
728 char tmp2[32];
729 char br;
730 int vlan0tag;
731 int vid;
732 int vid_map;
733 char *iftmp;
734 char nv[64];
736 #ifdef CONFIG_BCMWL5
737 foreach_wif(0, NULL, set_wlmac);
738 #else
739 foreach_wif(1, NULL, set_wlmac);
740 #endif
741 check_afterburner();
742 #ifdef TCONFIG_IPV6
743 enable_ipv6(ipv6_enabled()); //tell Kernel to disable/enable IPv6 for most interfaces
744 #endif
745 vlan0tag = nvram_get_int("vlan0tag");
747 if ((sfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) return;
748 for(br=0 ; br<4 ; br++) {
749 char bridge[2] = "0";
750 if (br!=0)
751 bridge[0]+=br;
752 else
753 strcpy(bridge, "");
755 strcpy(tmp,"lan");
756 strcat(tmp,bridge);
757 strcat(tmp, "_ifname");
758 lan_ifname = strdup(nvram_safe_get(tmp));
760 if (strncmp(lan_ifname, "br", 2) == 0) {
761 _dprintf("%s: setting up the bridge %s\n", __FUNCTION__, lan_ifname);
763 eval("brctl", "addbr", lan_ifname);
764 eval("brctl", "setfd", lan_ifname, "0");
765 strcpy(tmp,"lan");
766 strcat(tmp,bridge);
767 strcat(tmp, "_stp");
768 eval("brctl", "stp", lan_ifname, nvram_safe_get(tmp));
770 #ifdef TCONFIG_EMF
771 if (nvram_get_int("emf_enable")) {
772 eval("emf", "add", "bridge", lan_ifname);
773 eval("igs", "add", "bridge", lan_ifname);
775 #endif
777 strcpy(tmp,"lan");
778 strcat(tmp,bridge);
779 strcat(tmp, "_ipaddr");
780 inet_aton(nvram_safe_get(tmp), (struct in_addr *)&ip);
782 hwaddrset = 0;
783 sta = 0;
785 strcpy(tmp,"lan");
786 strcat(tmp,bridge);
787 strcat(tmp, "_ifnames");
788 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
789 p = lan_ifnames;
790 while ((iftmp = strsep(&p, " ")) != NULL) {
791 while (*iftmp == ' ') ++iftmp;
792 if (*iftmp == 0) continue;
793 ifname = iftmp;
795 unit = -1; subunit = -1;
797 // ignore disabled wl vifs
798 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
800 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
801 if (!nvram_get_int(nv))
802 continue;
803 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
804 continue;
805 #ifdef CONFIG_BCMWL5
806 set_wlmac(0, unit, subunit, NULL);
807 #endif
809 else
810 wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit));
812 // vlan ID mapping
813 if (strncmp(ifname, "vlan", 4) == 0) {
814 if (sscanf(ifname, "vlan%d", &vid) == 1) {
815 snprintf(tmp, sizeof(tmp), "vlan%dvid", vid);
816 vid_map = nvram_get_int(tmp);
817 if ((vid_map < 1) || (vid_map > 4094)) vid_map = vlan0tag | vid;
818 snprintf(tmp, sizeof(tmp), "vlan%d", vid_map);
819 ifname = tmp;
823 // bring up interface
824 if (ifconfig(ifname, IFUP|IFF_ALLMULTI, NULL, NULL) != 0) continue;
826 // set the logical bridge address to that of the first interface
827 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
828 if ((!hwaddrset) ||
829 (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0 &&
830 memcmp(ifr.ifr_hwaddr.sa_data, "\0\0\0\0\0\0", ETHER_ADDR_LEN) == 0)) {
831 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
832 if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) {
833 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
834 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
835 _dprintf("%s: setting MAC of %s bridge to %s\n", __FUNCTION__,
836 ifr.ifr_name, ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
837 ioctl(sfd, SIOCSIFHWADDR, &ifr);
838 hwaddrset = 1;
842 if (wlconf(ifname, unit, subunit) == 0) {
843 const char *mode = nvram_safe_get(wl_nvname("mode", unit, subunit));
845 if (strcmp(mode, "wet") == 0) {
846 // Enable host DHCP relay
847 if (nvram_get_int("dhcp_relay")) {
848 wl_iovar_set(ifname, "wet_host_mac", ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
849 wl_iovar_setint(ifname, "wet_host_ipv4", ip);
853 sta |= (strcmp(mode, "sta") == 0);
854 if ((strcmp(mode, "ap") != 0) && (strcmp(mode, "wet") != 0)) continue;
856 eval("brctl", "addif", lan_ifname, ifname);
857 #ifdef TCONFIG_EMF
858 if (nvram_get_int("emf_enable"))
859 eval("emf", "add", "iface", lan_ifname, ifname);
860 #endif
863 if ((nvram_get_int("wan_islan")) && (br==0) &&
864 ((get_wan_proto() == WP_DISABLED) || (get_wan_proto() == WP_PPP3G) || (sta))) {
865 ifname = nvram_get("wan_ifnameX");
866 if (ifconfig(ifname, IFUP, NULL, NULL) == 0)
867 eval("brctl", "addif", lan_ifname, ifname);
870 free(lan_ifnames);
873 // --- this shouldn't happen ---
874 else if (*lan_ifname) {
875 ifconfig(lan_ifname, IFUP, NULL, NULL);
876 wlconf(lan_ifname, -1, -1);
878 else {
879 close(sfd);
880 free(lan_ifname);
881 return;
884 // Get current LAN hardware address
885 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
886 strcpy(tmp,"lan");
887 strcat(tmp,bridge);
888 strcat(tmp, "_hwaddr");
889 // if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set("lan_hwaddr", ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
890 if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set(tmp, ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
892 // Set initial QoS mode for LAN ports
893 set_et_qos_mode(sfd);
895 close(sfd);
897 // bring up and configure LAN interface
898 strcpy(tmp,"lan");
899 strcat(tmp,bridge);
900 strcat(tmp, "_ipaddr");
901 strcpy(tmp2,"lan");
902 strcat(tmp2,bridge);
903 strcat(tmp2, "_netmask");
904 ifconfig(lan_ifname, IFUP, nvram_safe_get(tmp), nvram_safe_get(tmp2));
906 config_loopback();
907 do_static_routes(1);
909 if(br==0)
910 set_lan_hostname(nvram_safe_get("wan_hostname"));
912 if ((get_wan_proto() == WP_DISABLED) && (br==0)) {
913 char *gateway = nvram_safe_get("lan_gateway") ;
914 if ((*gateway) && (strcmp(gateway, "0.0.0.0") != 0)) {
915 int tries = 5;
916 while ((route_add(lan_ifname, 0, "0.0.0.0", gateway, "0.0.0.0") != 0) && (tries-- > 0)) sleep(1);
917 _dprintf("%s: add gateway=%s tries=%d\n", __FUNCTION__, gateway, tries);
921 #ifdef TCONFIG_IPV6
922 start_ipv6();
923 #endif
925 #ifdef TCONFIG_EMF
926 if (nvram_get_int("emf_enable")) start_emf(lan_ifname);
927 #endif
929 free(lan_ifname);
931 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
934 void stop_lan(void)
936 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
938 char *lan_ifname;
939 char *lan_ifnames, *p, *ifname;
940 char tmp[32];
941 char br;
942 int vlan0tag, vid, vid_map;
943 char *iftmp;
945 vlan0tag = nvram_get_int("vlan0tag");
947 for(br=0 ; br<4 ; br++) {
948 char bridge[2] = "0";
949 if (br!=0)
950 bridge[0]+=br;
951 else
952 strcpy(bridge, "");
954 strcpy(tmp,"lan");
955 strcat(tmp,bridge);
956 strcat(tmp, "_ifname");
957 lan_ifname = nvram_safe_get(tmp);
958 ifconfig(lan_ifname, 0, NULL, NULL);
960 #ifdef TCONFIG_IPV6
961 stop_ipv6();
962 #endif
964 if (strncmp(lan_ifname, "br", 2) == 0) {
965 #ifdef TCONFIG_EMF
966 stop_emf(lan_ifname);
967 #endif
968 strcpy(tmp,"lan");
969 strcat(tmp,bridge);
970 strcat(tmp, "_ifnames");
971 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
972 p = lan_ifnames;
973 while ((iftmp = strsep(&p, " ")) != NULL) {
974 while (*iftmp == ' ') ++iftmp;
975 if (*iftmp == 0) continue;
976 ifname = iftmp;
977 // vlan ID mapping
978 if (strncmp(ifname, "vlan", 4) == 0) {
979 if (sscanf(ifname, "vlan%d", &vid) == 1) {
980 snprintf(tmp, sizeof(tmp), "vlan%dvid", vid);
981 vid_map = nvram_get_int(tmp);
982 if ((vid_map < 1) || (vid_map > 4094)) vid_map = vlan0tag | vid;
983 snprintf(tmp, sizeof(tmp), "vlan%d", vid_map);
984 ifname = tmp;
987 eval("wlconf", ifname, "down");
988 ifconfig(ifname, 0, NULL, NULL);
989 eval("brctl", "delif", lan_ifname, ifname);
991 free(lan_ifnames);
993 eval("brctl", "delbr", lan_ifname);
995 else if (*lan_ifname) {
996 eval("wlconf", lan_ifname, "down");
999 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
1002 static int is_sta(int idx, int unit, int subunit, void *param)
1004 return (nvram_match(wl_nvname("mode", unit, subunit), "sta") && (nvram_match(wl_nvname("bss_enabled", unit, subunit), "1")));
1007 void do_static_routes(int add)
1009 char *buf;
1010 char *p, *q;
1011 char *dest, *mask, *gateway, *metric, *ifname;
1012 int r;
1014 if ((buf = strdup(nvram_safe_get(add ? "routes_static" : "routes_static_saved"))) == NULL) return;
1015 if (add) nvram_set("routes_static_saved", buf);
1016 else nvram_unset("routes_static_saved");
1017 p = buf;
1018 while ((q = strsep(&p, ">")) != NULL) {
1019 if (vstrsep(q, "<", &dest, &gateway, &mask, &metric, &ifname) != 5) continue;
1020 #ifdef TCONFIG_VLAN
1021 ifname = nvram_safe_get(((strcmp(ifname,"LAN")==0) ? "lan_ifname" :
1022 ((strcmp(ifname,"LAN1")==0) ? "lan1_ifname" :
1023 ((strcmp(ifname,"LAN2")==0) ? "lan2_ifname" :
1024 ((strcmp(ifname,"LAN3")==0) ? "lan3_ifname" :
1025 ((*ifname == 'W') ? "wan_iface" : "wan_ifname"))))));
1026 #else
1027 ifname = nvram_safe_get((*ifname == 'L') ? "lan_ifname" :
1028 ((*ifname == 'W') ? "wan_iface" : "wan_ifname"));
1029 #endif
1030 if (add) {
1031 for (r = 3; r >= 0; --r) {
1032 if (route_add(ifname, atoi(metric), dest, gateway, mask) == 0) break;
1033 sleep(1);
1036 else {
1037 route_del(ifname, atoi(metric), dest, gateway, mask);
1040 free(buf);
1042 char *modem_ipaddr;
1043 if ( (nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "dhcp") || nvram_match("wan_proto", "static") )
1044 && (modem_ipaddr = nvram_safe_get("modem_ipaddr")) && *modem_ipaddr && !nvram_match("modem_ipaddr","0.0.0.0")
1045 && (!foreach_wif(1, NULL, is_sta)) ) {
1046 char ip[16];
1047 char *end = rindex(modem_ipaddr,'.')+1;
1048 unsigned char c = atoi(end);
1049 char *iface = nvram_safe_get("wan_ifname");
1051 sprintf(ip, "%.*s%hhu", end-modem_ipaddr, modem_ipaddr, (unsigned char)(c^1^((c&2)^((c&1)<<1))) );
1052 eval("ip", "addr", add ?"add":"del", ip, "peer", modem_ipaddr, "dev", iface);
1058 void hotplug_net(void)
1060 char *interface, *action;
1061 char *lan_ifname;
1063 if (((interface = getenv("INTERFACE")) == NULL) || ((action = getenv("ACTION")) == NULL)) return;
1065 _dprintf("hotplug net INTERFACE=%s ACTION=%s\n", interface, action);
1067 if ((strncmp(interface, "wds", 3) == 0) &&
1068 (strcmp(action, "register") == 0 || strcmp(action, "add") == 0)) {
1069 ifconfig(interface, IFUP, NULL, NULL);
1070 lan_ifname = nvram_safe_get("lan_ifname");
1071 #ifdef TCONFIG_EMF
1072 if (nvram_get_int("emf_enable")) {
1073 eval("emf", "add", "iface", lan_ifname, interface);
1074 emf_mfdb_update(lan_ifname, interface, 1);
1075 emf_uffp_update(lan_ifname, interface, 1);
1076 emf_rtport_update(lan_ifname, interface, 1);
1078 #endif
1079 if (strncmp(lan_ifname, "br", 2) == 0) {
1080 eval("brctl", "addif", lan_ifname, interface);
1081 notify_nas(interface);
1087 static int is_same_addr(struct ether_addr *addr1, struct ether_addr *addr2)
1089 int i;
1090 for (i = 0; i < 6; i++) {
1091 if (addr1->octet[i] != addr2->octet[i])
1092 return 0;
1094 return 1;
1097 #define WL_MAX_ASSOC 128
1098 static int check_wl_client(char *ifname, int unit, int subunit)
1100 struct ether_addr bssid;
1101 wl_bss_info_t *bi;
1102 char buf[WLC_IOCTL_MAXLEN];
1103 struct maclist *mlist;
1104 int mlsize, i;
1105 int associated, authorized;
1107 *(uint32 *)buf = WLC_IOCTL_MAXLEN;
1108 if (wl_ioctl(ifname, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN) < 0 ||
1109 wl_ioctl(ifname, WLC_GET_BSS_INFO, buf, WLC_IOCTL_MAXLEN) < 0)
1110 return 0;
1112 bi = (wl_bss_info_t *)(buf + 4);
1113 if ((bi->SSID_len == 0) ||
1114 (bi->BSSID.octet[0] + bi->BSSID.octet[1] + bi->BSSID.octet[2] +
1115 bi->BSSID.octet[3] + bi->BSSID.octet[4] + bi->BSSID.octet[5] == 0))
1116 return 0;
1118 associated = 0;
1119 authorized = strstr(nvram_safe_get(wl_nvname("akm", unit, subunit)), "psk") == 0;
1121 mlsize = sizeof(struct maclist) + (WL_MAX_ASSOC * sizeof(struct ether_addr));
1122 if ((mlist = malloc(mlsize)) != NULL) {
1123 mlist->count = WL_MAX_ASSOC;
1124 if (wl_ioctl(ifname, WLC_GET_ASSOCLIST, mlist, mlsize) == 0) {
1125 for (i = 0; i < mlist->count; ++i) {
1126 if (is_same_addr(&mlist->ea[i], &bi->BSSID)) {
1127 associated = 1;
1128 break;
1133 if (associated && !authorized) {
1134 memset(mlist, 0, mlsize);
1135 mlist->count = WL_MAX_ASSOC;
1136 strcpy((char*)mlist, "autho_sta_list");
1137 if (wl_ioctl(ifname, WLC_GET_VAR, mlist, mlsize) == 0) {
1138 for (i = 0; i < mlist->count; ++i) {
1139 if (is_same_addr(&mlist->ea[i], &bi->BSSID)) {
1140 authorized = 1;
1141 break;
1146 free(mlist);
1149 return (associated && authorized);
1152 #define STACHECK_CONNECT 30
1153 #define STACHECK_DISCONNECT 5
1155 static int radio_join(int idx, int unit, int subunit, void *param)
1157 int i;
1158 char s[32], f[64];
1159 char *ifname;
1161 int *unit_filter = param;
1162 if (*unit_filter >= 0 && *unit_filter != unit) return 0;
1164 if (!nvram_get_int(wl_nvname("radio", unit, 0)) || !wl_client(unit, subunit)) return 0;
1166 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
1168 // skip disabled wl vifs
1169 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
1170 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
1171 return 0;
1173 sprintf(f, "/var/run/radio.%d.%d.pid", unit, subunit < 0 ? 0 : subunit);
1174 if (f_read_string(f, s, sizeof(s)) > 0) {
1175 if ((i = atoi(s)) > 1) {
1176 kill(i, SIGTERM);
1177 sleep(1);
1181 if (fork() == 0) {
1182 sprintf(s, "%d", getpid());
1183 f_write(f, s, sizeof(s), 0, 0644);
1185 int stacheck_connect = nvram_get_int("sta_chkint");
1186 if (stacheck_connect <= 0)
1187 stacheck_connect = STACHECK_CONNECT;
1188 int stacheck;
1190 while (get_radio(unit) && wl_client(unit, subunit)) {
1192 if (check_wl_client(ifname, unit, subunit)) {
1193 stacheck = stacheck_connect;
1195 else {
1196 eval("wl", "-i", ifname, "disassoc");
1197 #ifdef CONFIG_BCMWL5
1198 char *amode, *sec = nvram_safe_get(wl_nvname("akm", unit, subunit));
1200 if (strstr(sec, "psk2")) amode = "wpa2psk";
1201 else if (strstr(sec, "psk")) amode = "wpapsk";
1202 else if (strstr(sec, "wpa2")) amode = "wpa2";
1203 else if (strstr(sec, "wpa")) amode = "wpa";
1204 else if (nvram_get_int(wl_nvname("auth", unit, subunit))) amode = "shared";
1205 else amode = "open";
1207 eval("wl", "-i", ifname, "join", nvram_safe_get(wl_nvname("ssid", unit, subunit)),
1208 "imode", "bss", "amode", amode);
1209 #else
1210 eval("wl", "-i", ifname, "join", nvram_safe_get(wl_nvname("ssid", unit, subunit)));
1211 #endif
1212 stacheck = STACHECK_DISCONNECT;
1214 sleep(stacheck);
1216 unlink(f);
1219 return 1;
1222 enum {
1223 RADIO_OFF = 0,
1224 RADIO_ON = 1,
1225 RADIO_TOGGLE = 2
1228 static int radio_toggle(int idx, int unit, int subunit, void *param)
1230 if (!nvram_get_int(wl_nvname("radio", unit, 0))) return 0;
1232 int *op = param;
1234 if (*op == RADIO_TOGGLE) {
1235 *op = get_radio(unit) ? RADIO_OFF : RADIO_ON;
1238 set_radio(*op, unit);
1239 return *op;
1242 int radio_main(int argc, char *argv[])
1244 int op = RADIO_OFF;
1245 int unit;
1247 if (argc < 2) {
1248 HELP:
1249 usage_exit(argv[0], "on|off|toggle|join [N]\n");
1251 unit = (argc == 3) ? atoi(argv[2]) : -1;
1253 if (strcmp(argv[1], "toggle") == 0)
1254 op = RADIO_TOGGLE;
1255 else if (strcmp(argv[1], "off") == 0)
1256 op = RADIO_OFF;
1257 else if (strcmp(argv[1], "on") == 0)
1258 op = RADIO_ON;
1259 else if (strcmp(argv[1], "join") == 0)
1260 goto JOIN;
1261 else
1262 goto HELP;
1264 if (unit >= 0)
1265 op = radio_toggle(0, unit, 0, &op);
1266 else
1267 op = foreach_wif(0, &op, radio_toggle);
1269 if (!op) {
1270 led(LED_DIAG, 0);
1271 return 0;
1273 JOIN:
1274 foreach_wif(1, &unit, radio_join);
1275 return 0;
1279 int wdist_main(int argc, char *argv[])
1281 int n;
1282 rw_reg_t r;
1283 int v;
1285 if (argc != 2) {
1286 r.byteoff = 0x684;
1287 r.size = 2;
1288 if (wl_ioctl(nvram_safe_get("wl_ifname"), 101, &r, sizeof(r)) == 0) {
1289 v = r.val - 510;
1290 if (v <= 9) v = 0;
1291 else v = (v - (9 + 1)) * 150;
1292 printf("Current: %d-%dm (0x%02x)\n\n", v + (v ? 1 : 0), v + 150, r.val);
1294 usage_exit(argv[0], "<meters>");
1296 if ((n = atoi(argv[1])) <= 0) setup_wldistance();
1297 else set_wldistance(n);
1298 return 0;
1302 static int get_wldist(int idx, int unit, int subunit, void *param)
1304 int n;
1306 char *p = nvram_safe_get(wl_nvname("distance", unit, 0));
1307 if ((*p == 0) || ((n = atoi(p)) < 0)) return 0;
1309 return (9 + (n / 150) + ((n % 150) ? 1 : 0));
1312 static int wldist(int idx, int unit, int subunit, void *param)
1314 rw_reg_t r;
1315 uint32 s;
1316 char *p;
1317 int n;
1319 n = get_wldist(idx, unit, subunit, param);
1320 if (n > 0) {
1321 s = 0x10 | (n << 16);
1322 p = nvram_safe_get(wl_nvname("ifname", unit, 0));
1323 wl_ioctl(p, 197, &s, sizeof(s));
1325 r.byteoff = 0x684;
1326 r.val = n + 510;
1327 r.size = 2;
1328 wl_ioctl(p, 102, &r, sizeof(r));
1330 return 0;
1333 // ref: wificonf.c
1334 int wldist_main(int argc, char *argv[])
1336 if (fork() == 0) {
1337 if (foreach_wif(0, NULL, get_wldist) == 0) return 0;
1339 while (1) {
1340 foreach_wif(0, NULL, wldist);
1341 sleep(2);
1345 return 0;