Merged in edrikk/tomato-arm-ddwrt-kong-cherrypicks (pull request #13)
[tomato.git] / release / src-rt-6.x.4708 / router / rc / network.c
blobbb0c88da5bd9ac5eba736b35e97339a9eb5bd711
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 if ((s = nvram_get("lan1_ipaddr")) && (*s) && (strcmp(s,"") != 0))
105 fprintf(f, "%s %s-lan1\n", s, nvram_safe_get("lan_hostname"));
106 if ((s = nvram_get("lan2_ipaddr")) && (*s) && (strcmp(s,"") != 0))
107 fprintf(f, "%s %s-lan2\n", s, nvram_safe_get("lan_hostname"));
108 if ((s = nvram_get("lan3_ipaddr")) && (*s) && (strcmp(s,"") != 0))
109 fprintf(f, "%s %s-lan3\n", s, nvram_safe_get("lan_hostname"));
110 #ifdef TCONFIG_IPV6
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"));
116 #endif
117 fclose(f);
121 void set_host_domain_name(void)
123 const char *s;
125 s = nvram_safe_get("wan_hostname");
126 sethostname(s, strlen(s));
127 set_lan_hostname(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)
136 int r;
137 char wl[24];
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");
146 if (r == 0) {
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("mitigation", 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);
167 return r;
170 // -----------------------------------------------------------------------------
172 #ifdef TCONFIG_EMF
173 static void emf_mfdb_update(char *lan_ifname, char *lan_port_ifname, bool add)
175 char word[256], *next;
176 char *mgrp, *ifname;
178 /* Add/Delete MFDB entries corresponding to new interface */
179 foreach (word, nvram_safe_get("emf_entry"), next) {
180 ifname = word;
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;
195 char *ifname;
197 /* Add/Delete UFFP entries corresponding to new interface */
198 foreach (word, nvram_safe_get("emf_uffp_entry"), next) {
199 ifname = word;
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;
213 char *ifname;
215 /* Add/Delete RTPORT entries corresponding to new interface */
216 foreach (word, nvram_safe_get("emf_rtport_entry"), next) {
217 ifname = word;
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)
230 /* Start EMF */
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);
249 #endif
251 // -----------------------------------------------------------------------------
253 /* Set initial QoS mode for all et interfaces that are up. */
254 void set_et_qos_mode(int sfd)
256 int i, qos;
257 caddr_t ifrdata;
258 struct ifreq ifr;
259 struct ethtool_drvinfo info;
261 qos = (strcmp(nvram_safe_get("wl_wme"), "off") != 0);
262 for (i = 1; i <= DEV_NUMIFS; i++) {
263 ifr.ifr_ifindex = 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;
267 /* get flags */
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 #ifndef BCMARM
278 if (!strncmp(info.driver, "et", 2) ||
279 !strncmp(info.driver, "bcm57", 5)) {
280 ifr.ifr_data = (caddr_t)&qos;
281 ioctl(sfd, SIOCSETCQOS, &ifr);
283 #endif
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");
585 if (get_model() == MODEL_WS880) {
586 if (nvram_match("wl0_radio", "1") || nvram_match("wl1_radio", "1"))
587 led(LED_WLAN, LED_ON);
588 else
589 led(LED_WLAN, LED_OFF);
593 #ifdef CONFIG_BCMWL5
594 static int disabled_wl(int idx, int unit, int subunit, void *param)
596 char *ifname;
598 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
600 // skip disabled wl vifs
601 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
602 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
603 return 1;
604 return 0;
606 #endif
608 void start_wl(void)
610 char *lan_ifname, *lan_ifnames, *ifname, *p;
611 int unit, subunit;
612 int is_client = 0;
614 char tmp[32];
615 char br;
617 #ifdef CONFIG_BCMWL5
618 // HACK: When a virtual SSID is disabled, it requires two initialisation
619 if (foreach_wif(1, NULL, disabled_wl))
621 stop_wireless();
622 start_wireless();
623 return;
625 #endif
627 for(br=0 ; br<4 ; br++) {
628 char bridge[2] = "0";
629 if (br!=0)
630 bridge[0]+=br;
631 else
632 strcpy(bridge, "");
634 strcpy(tmp,"lan");
635 strcat(tmp,bridge);
636 strcat(tmp, "_ifname");
637 lan_ifname = nvram_safe_get(tmp);
638 if (strncmp(lan_ifname, "br", 2) == 0) {
639 strcpy(tmp,"lan");
640 strcat(tmp,bridge);
641 strcat(tmp, "_ifnames");
642 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
643 p = lan_ifnames;
644 while ((ifname = strsep(&p, " ")) != NULL) {
645 while (*ifname == ' ') ++ifname;
646 if (*ifname == 0) continue;
648 unit = -1; subunit = -1;
650 // ignore disabled wl vifs
651 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
652 char nv[40];
653 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
654 if (!nvram_get_int(nv))
655 continue;
656 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
657 continue;
659 // get the instance number of the wl i/f
660 else if (wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit)))
661 continue;
663 is_client |= wl_client(unit, subunit) && nvram_get_int(wl_nvname("radio", unit, 0));
665 #ifdef CONFIG_BCMWL5
666 eval("wlconf", ifname, "start"); /* start wl iface */
667 // Enable LED if wireless interface is enabled, and turn on blink (traffic "control" of LED) if enabled
668 if (nvram_get_int(wl_nvname("radio", unit, 0))) {
669 if (unit == 0) {
670 led(LED_WLAN, LED_ON);
671 if (nvram_get_int("blink_wl"))
672 eval("blink", ifname, "wlan", "20", "8192");
674 else{
675 led(LED_5G, LED_ON);
676 if (nvram_get_int("blink_wl"))
677 eval("blink", ifname, "5g", "20", "8192");
680 #endif // CONFIG_BCMWL5
682 free(lan_ifnames);
685 #ifdef CONFIG_BCMWL5
686 else if (strcmp(lan_ifname, "")) {
687 /* specific non-bridged lan iface */
688 eval("wlconf", lan_ifname, "start");
690 #endif // CONFIG_BCMWL5
693 killall("wldist", SIGTERM);
694 eval("wldist");
696 if (is_client)
697 xstart("radio", "join");
699 if (get_model() == MODEL_WS880) {
700 if (nvram_match("wl0_radio", "1") || nvram_match("wl1_radio", "1"))
701 led(LED_WLAN, LED_ON);
702 else
703 led(LED_WLAN, LED_OFF);
707 #ifdef TCONFIG_IPV6
708 void enable_ipv6(int enable)
710 DIR *dir;
711 struct dirent *dirent;
712 char s[256];
714 if ((dir = opendir("/proc/sys/net/ipv6/conf")) != NULL) {
715 while ((dirent = readdir(dir)) != NULL) {
716 if (strcmp("vlan1", dirent->d_name) &&
717 strcmp("eth0", dirent->d_name) &&
718 strcmp("all", dirent->d_name) &&
719 strcmp("eth1", dirent->d_name))
722 sprintf(s, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", dirent->d_name);
723 f_write_string(s, enable ? "0" : "1", 0, 0);
726 closedir(dir);
730 void accept_ra(const char *ifname)
732 char s[256];
734 sprintf(s, "/proc/sys/net/ipv6/conf/%s/accept_ra", ifname);
735 f_write_string(s, "2", 0, 0);
737 sprintf(s, "/proc/sys/net/ipv6/conf/%s/forwarding", ifname);
738 f_write_string(s, "2", 0, 0);
740 #endif
742 void start_lan(void)
744 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
746 char *lan_ifname;
747 struct ifreq ifr;
748 char *lan_ifnames, *ifname, *p;
749 int sfd;
750 uint32 ip;
751 int unit, subunit, sta;
752 int hwaddrset;
753 char eabuf[32];
754 char tmp[32];
755 char tmp2[32];
756 char br;
757 int vlan0tag;
758 int vid;
759 int vid_map;
760 char *iftmp;
761 char nv[64];
763 #ifdef CONFIG_BCMWL5
764 foreach_wif(0, NULL, set_wlmac);
765 #else
766 foreach_wif(1, NULL, set_wlmac);
767 #endif
768 check_afterburner();
769 #ifdef TCONFIG_IPV6
770 enable_ipv6(ipv6_enabled()); //tell Kernel to disable/enable IPv6 for most interfaces
771 #endif
772 vlan0tag = nvram_get_int("vlan0tag");
774 if ((sfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) return;
775 for(br=0 ; br<4 ; br++) {
776 char bridge[2] = "0";
777 if (br!=0)
778 bridge[0]+=br;
779 else
780 strcpy(bridge, "");
782 strcpy(tmp,"lan");
783 strcat(tmp,bridge);
784 strcat(tmp, "_ifname");
785 lan_ifname = strdup(nvram_safe_get(tmp));
787 if (strncmp(lan_ifname, "br", 2) == 0) {
788 _dprintf("%s: setting up the bridge %s\n", __FUNCTION__, lan_ifname);
790 eval("brctl", "addbr", lan_ifname);
791 eval("brctl", "setfd", lan_ifname, "0");
792 strcpy(tmp,"lan");
793 strcat(tmp,bridge);
794 strcat(tmp, "_stp");
795 eval("brctl", "stp", lan_ifname, nvram_safe_get(tmp));
797 #ifdef TCONFIG_EMF
798 if (nvram_get_int("emf_enable")) {
799 eval("emf", "add", "bridge", lan_ifname);
800 eval("igs", "add", "bridge", lan_ifname);
802 #endif
804 strcpy(tmp,"lan");
805 strcat(tmp,bridge);
806 strcat(tmp, "_ipaddr");
807 inet_aton(nvram_safe_get(tmp), (struct in_addr *)&ip);
809 hwaddrset = 0;
810 sta = 0;
812 strcpy(tmp,"lan");
813 strcat(tmp,bridge);
814 strcat(tmp, "_ifnames");
815 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
816 p = lan_ifnames;
817 while ((iftmp = strsep(&p, " ")) != NULL) {
818 while (*iftmp == ' ') ++iftmp;
819 if (*iftmp == 0) continue;
820 ifname = iftmp;
822 unit = -1; subunit = -1;
824 // ignore disabled wl vifs
825 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
827 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
828 if (!nvram_get_int(nv))
829 continue;
830 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
831 continue;
832 #ifdef CONFIG_BCMWL5
833 set_wlmac(0, unit, subunit, NULL);
834 #endif
836 else
837 wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit));
839 // vlan ID mapping
840 if (strncmp(ifname, "vlan", 4) == 0) {
841 if (sscanf(ifname, "vlan%d", &vid) == 1) {
842 snprintf(tmp, sizeof(tmp), "vlan%dvid", vid);
843 vid_map = nvram_get_int(tmp);
844 if ((vid_map < 1) || (vid_map > 4094)) vid_map = vlan0tag | vid;
845 snprintf(tmp, sizeof(tmp), "vlan%d", vid_map);
846 ifname = tmp;
850 // bring up interface
851 if (ifconfig(ifname, IFUP|IFF_ALLMULTI, NULL, NULL) != 0) continue;
853 // set the logical bridge address to that of the first interface
854 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
855 if ((!hwaddrset) ||
856 (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0 &&
857 memcmp(ifr.ifr_hwaddr.sa_data, "\0\0\0\0\0\0", ETHER_ADDR_LEN) == 0)) {
858 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
859 if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) {
860 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
861 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
862 _dprintf("%s: setting MAC of %s bridge to %s\n", __FUNCTION__,
863 ifr.ifr_name, ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
864 ioctl(sfd, SIOCSIFHWADDR, &ifr);
865 hwaddrset = 1;
869 if (wlconf(ifname, unit, subunit) == 0) {
870 const char *mode = nvram_safe_get(wl_nvname("mode", unit, subunit));
872 if (strcmp(mode, "wet") == 0) {
873 // Enable host DHCP relay
874 if (nvram_get_int("dhcp_relay")) {
875 wl_iovar_set(ifname, "wet_host_mac", ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
876 wl_iovar_setint(ifname, "wet_host_ipv4", ip);
880 sta |= (strcmp(mode, "sta") == 0);
881 if ((strcmp(mode, "ap") != 0) && (strcmp(mode, "wet") != 0)) continue;
883 eval("brctl", "addif", lan_ifname, ifname);
884 #ifdef TCONFIG_EMF
885 if (nvram_get_int("emf_enable"))
886 eval("emf", "add", "iface", lan_ifname, ifname);
887 #endif
890 if ((nvram_get_int("wan_islan")) && (br==0) &&
891 ((get_wan_proto() == WP_DISABLED) || (sta))) {
892 ifname = nvram_get("wan_ifnameX");
893 if (ifconfig(ifname, IFUP, NULL, NULL) == 0)
894 eval("brctl", "addif", lan_ifname, ifname);
897 free(lan_ifnames);
900 // --- this shouldn't happen ---
901 else if (*lan_ifname) {
902 ifconfig(lan_ifname, IFUP, NULL, NULL);
903 wlconf(lan_ifname, -1, -1);
905 else {
906 close(sfd);
907 free(lan_ifname);
908 return;
911 // Get current LAN hardware address
912 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
913 strcpy(tmp,"lan");
914 strcat(tmp,bridge);
915 strcat(tmp, "_hwaddr");
916 // if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set("lan_hwaddr", ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
917 if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set(tmp, ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
919 // Set initial QoS mode for LAN ports
920 set_et_qos_mode(sfd);
922 close(sfd);
924 // bring up and configure LAN interface
925 strcpy(tmp,"lan");
926 strcat(tmp,bridge);
927 strcat(tmp, "_ipaddr");
928 strcpy(tmp2,"lan");
929 strcat(tmp2,bridge);
930 strcat(tmp2, "_netmask");
931 ifconfig(lan_ifname, IFUP, nvram_safe_get(tmp), nvram_safe_get(tmp2));
933 config_loopback();
934 do_static_routes(1);
936 if(br==0)
937 set_lan_hostname(nvram_safe_get("wan_hostname"));
939 if ((get_wan_proto() == WP_DISABLED) && (br==0)) {
940 char *gateway = nvram_safe_get("lan_gateway") ;
941 if ((*gateway) && (strcmp(gateway, "0.0.0.0") != 0)) {
942 int tries = 5;
943 while ((route_add(lan_ifname, 0, "0.0.0.0", gateway, "0.0.0.0") != 0) && (tries-- > 0)) sleep(1);
944 _dprintf("%s: add gateway=%s tries=%d\n", __FUNCTION__, gateway, tries);
948 #ifdef TCONFIG_IPV6
949 start_ipv6();
950 #endif
952 #ifdef TCONFIG_EMF
953 if (nvram_get_int("emf_enable")) start_emf(lan_ifname);
954 #endif
956 free(lan_ifname);
958 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
961 void stop_lan(void)
963 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
965 char *lan_ifname;
966 char *lan_ifnames, *p, *ifname;
967 char tmp[32];
968 char br;
969 int vlan0tag, vid, vid_map;
970 char *iftmp;
972 vlan0tag = nvram_get_int("vlan0tag");
974 for(br=0 ; br<4 ; br++) {
975 char bridge[2] = "0";
976 if (br!=0)
977 bridge[0]+=br;
978 else
979 strcpy(bridge, "");
981 strcpy(tmp,"lan");
982 strcat(tmp,bridge);
983 strcat(tmp, "_ifname");
984 lan_ifname = nvram_safe_get(tmp);
985 ifconfig(lan_ifname, 0, NULL, NULL);
987 #ifdef TCONFIG_IPV6
988 stop_ipv6();
989 #endif
991 if (strncmp(lan_ifname, "br", 2) == 0) {
992 #ifdef TCONFIG_EMF
993 stop_emf(lan_ifname);
994 #endif
995 strcpy(tmp,"lan");
996 strcat(tmp,bridge);
997 strcat(tmp, "_ifnames");
998 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
999 p = lan_ifnames;
1000 while ((iftmp = strsep(&p, " ")) != NULL) {
1001 while (*iftmp == ' ') ++iftmp;
1002 if (*iftmp == 0) continue;
1003 ifname = iftmp;
1004 // vlan ID mapping
1005 if (strncmp(ifname, "vlan", 4) == 0) {
1006 if (sscanf(ifname, "vlan%d", &vid) == 1) {
1007 snprintf(tmp, sizeof(tmp), "vlan%dvid", vid);
1008 vid_map = nvram_get_int(tmp);
1009 if ((vid_map < 1) || (vid_map > 4094)) vid_map = vlan0tag | vid;
1010 snprintf(tmp, sizeof(tmp), "vlan%d", vid_map);
1011 ifname = tmp;
1014 eval("wlconf", ifname, "down");
1015 ifconfig(ifname, 0, NULL, NULL);
1016 eval("brctl", "delif", lan_ifname, ifname);
1018 free(lan_ifnames);
1020 eval("brctl", "delbr", lan_ifname);
1022 else if (*lan_ifname) {
1023 eval("wlconf", lan_ifname, "down");
1026 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
1029 static int is_sta(int idx, int unit, int subunit, void *param)
1031 return (nvram_match(wl_nvname("mode", unit, subunit), "sta") && (nvram_match(wl_nvname("bss_enabled", unit, subunit), "1")));
1034 void do_static_routes(int add)
1036 char *buf;
1037 char *p, *q;
1038 char *dest, *mask, *gateway, *metric, *ifname;
1039 int r;
1041 if ((buf = strdup(nvram_safe_get(add ? "routes_static" : "routes_static_saved"))) == NULL) return;
1042 if (add) nvram_set("routes_static_saved", buf);
1043 else nvram_unset("routes_static_saved");
1044 p = buf;
1045 while ((q = strsep(&p, ">")) != NULL) {
1046 if (vstrsep(q, "<", &dest, &gateway, &mask, &metric, &ifname) != 5) continue;
1047 ifname = nvram_safe_get(((strcmp(ifname,"LAN")==0) ? "lan_ifname" :
1048 ((strcmp(ifname,"LAN1")==0) ? "lan1_ifname" :
1049 ((strcmp(ifname,"LAN2")==0) ? "lan2_ifname" :
1050 ((strcmp(ifname,"LAN3")==0) ? "lan3_ifname" :
1051 ((*ifname == 'W') ? "wan_iface" : "wan_ifname"))))));
1052 if (add) {
1053 for (r = 3; r >= 0; --r) {
1054 if (route_add(ifname, atoi(metric), dest, gateway, mask) == 0) break;
1055 sleep(1);
1058 else {
1059 route_del(ifname, atoi(metric), dest, gateway, mask);
1062 free(buf);
1064 char *modem_ipaddr;
1065 if ( (nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "dhcp") || nvram_match("wan_proto", "static") )
1066 && (modem_ipaddr = nvram_safe_get("modem_ipaddr")) && *modem_ipaddr && !nvram_match("modem_ipaddr","0.0.0.0")
1067 && (!foreach_wif(1, NULL, is_sta)) ) {
1068 char ip[16];
1069 char *end = rindex(modem_ipaddr,'.')+1;
1070 unsigned char c = atoi(end);
1071 char *iface = nvram_safe_get("wan_ifname");
1073 sprintf(ip, "%.*s%hhu", end-modem_ipaddr, modem_ipaddr, (unsigned char)(c^1^((c&2)^((c&1)<<1))) );
1074 eval("ip", "addr", add ?"add":"del", ip, "peer", modem_ipaddr, "dev", iface);
1079 void hotplug_net(void)
1081 char *interface, *action;
1082 char *lan_ifname;
1084 if (((interface = getenv("INTERFACE")) == NULL) || ((action = getenv("ACTION")) == NULL)) return;
1086 _dprintf("hotplug net INTERFACE=%s ACTION=%s\n", interface, action);
1088 if ((strncmp(interface, "wds", 3) == 0) &&
1089 (strcmp(action, "register") == 0 || strcmp(action, "add") == 0)) {
1090 ifconfig(interface, IFUP, NULL, NULL);
1091 lan_ifname = nvram_safe_get("lan_ifname");
1092 #ifdef TCONFIG_EMF
1093 if (nvram_get_int("emf_enable")) {
1094 eval("emf", "add", "iface", lan_ifname, interface);
1095 emf_mfdb_update(lan_ifname, interface, 1);
1096 emf_uffp_update(lan_ifname, interface, 1);
1097 emf_rtport_update(lan_ifname, interface, 1);
1099 #endif
1100 if (strncmp(lan_ifname, "br", 2) == 0) {
1101 eval("brctl", "addif", lan_ifname, interface);
1102 notify_nas(interface);
1108 static int is_same_addr(struct ether_addr *addr1, struct ether_addr *addr2)
1110 int i;
1111 for (i = 0; i < 6; i++) {
1112 if (addr1->octet[i] != addr2->octet[i])
1113 return 0;
1115 return 1;
1118 #define WL_MAX_ASSOC 128
1119 static int check_wl_client(char *ifname, int unit, int subunit)
1121 struct ether_addr bssid;
1122 wl_bss_info_t *bi;
1123 char buf[WLC_IOCTL_MAXLEN];
1124 struct maclist *mlist;
1125 int mlsize, i;
1126 int associated, authorized;
1128 *(uint32 *)buf = WLC_IOCTL_MAXLEN;
1129 if (wl_ioctl(ifname, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN) < 0 ||
1130 wl_ioctl(ifname, WLC_GET_BSS_INFO, buf, WLC_IOCTL_MAXLEN) < 0)
1131 return 0;
1133 bi = (wl_bss_info_t *)(buf + 4);
1134 if ((bi->SSID_len == 0) ||
1135 (bi->BSSID.octet[0] + bi->BSSID.octet[1] + bi->BSSID.octet[2] +
1136 bi->BSSID.octet[3] + bi->BSSID.octet[4] + bi->BSSID.octet[5] == 0))
1137 return 0;
1139 associated = 0;
1140 authorized = strstr(nvram_safe_get(wl_nvname("akm", unit, subunit)), "psk") == 0;
1142 mlsize = sizeof(struct maclist) + (WL_MAX_ASSOC * sizeof(struct ether_addr));
1143 if ((mlist = malloc(mlsize)) != NULL) {
1144 mlist->count = WL_MAX_ASSOC;
1145 if (wl_ioctl(ifname, WLC_GET_ASSOCLIST, mlist, mlsize) == 0) {
1146 for (i = 0; i < mlist->count; ++i) {
1147 if (is_same_addr(&mlist->ea[i], &bi->BSSID)) {
1148 associated = 1;
1149 break;
1154 if (associated && !authorized) {
1155 memset(mlist, 0, mlsize);
1156 mlist->count = WL_MAX_ASSOC;
1157 strcpy((char*)mlist, "autho_sta_list");
1158 if (wl_ioctl(ifname, WLC_GET_VAR, mlist, mlsize) == 0) {
1159 for (i = 0; i < mlist->count; ++i) {
1160 if (is_same_addr(&mlist->ea[i], &bi->BSSID)) {
1161 authorized = 1;
1162 break;
1167 free(mlist);
1170 return (associated && authorized);
1173 #define STACHECK_CONNECT 30
1174 #define STACHECK_DISCONNECT 5
1176 static int radio_join(int idx, int unit, int subunit, void *param)
1178 int i;
1179 char s[32], f[64];
1180 char *ifname;
1182 int *unit_filter = param;
1183 if (*unit_filter >= 0 && *unit_filter != unit) return 0;
1185 if (!nvram_get_int(wl_nvname("radio", unit, 0)) || !wl_client(unit, subunit)) return 0;
1187 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
1189 // skip disabled wl vifs
1190 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
1191 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
1192 return 0;
1194 sprintf(f, "/var/run/radio.%d.%d.pid", unit, subunit < 0 ? 0 : subunit);
1195 if (f_read_string(f, s, sizeof(s)) > 0) {
1196 if ((i = atoi(s)) > 1) {
1197 kill(i, SIGTERM);
1198 sleep(1);
1202 if (fork() == 0) {
1203 sprintf(s, "%d", getpid());
1204 f_write(f, s, sizeof(s), 0, 0644);
1206 int stacheck_connect = nvram_get_int("sta_chkint");
1207 if (stacheck_connect <= 0)
1208 stacheck_connect = STACHECK_CONNECT;
1209 int stacheck;
1211 while (get_radio(unit) && wl_client(unit, subunit)) {
1213 if (check_wl_client(ifname, unit, subunit)) {
1214 stacheck = stacheck_connect;
1216 else {
1217 eval("wl", "-i", ifname, "disassoc");
1218 #ifdef CONFIG_BCMWL5
1219 char *amode, *sec = nvram_safe_get(wl_nvname("akm", unit, subunit));
1221 if (strstr(sec, "psk2")) amode = "wpa2psk";
1222 else if (strstr(sec, "psk")) amode = "wpapsk";
1223 else if (strstr(sec, "wpa2")) amode = "wpa2";
1224 else if (strstr(sec, "wpa")) amode = "wpa";
1225 else if (nvram_get_int(wl_nvname("auth", unit, subunit))) amode = "shared";
1226 else amode = "open";
1228 eval("wl", "-i", ifname, "join", nvram_safe_get(wl_nvname("ssid", unit, subunit)),
1229 "imode", "bss", "amode", amode);
1230 #else
1231 eval("wl", "-i", ifname, "join", nvram_safe_get(wl_nvname("ssid", unit, subunit)));
1232 #endif
1233 stacheck = STACHECK_DISCONNECT;
1235 sleep(stacheck);
1237 unlink(f);
1240 return 1;
1243 enum {
1244 RADIO_OFF = 0,
1245 RADIO_ON = 1,
1246 RADIO_TOGGLE = 2
1249 static int radio_toggle(int idx, int unit, int subunit, void *param)
1251 if (!nvram_get_int(wl_nvname("radio", unit, 0))) return 0;
1253 int *op = param;
1255 if (*op == RADIO_TOGGLE) {
1256 *op = get_radio(unit) ? RADIO_OFF : RADIO_ON;
1259 set_radio(*op, unit);
1260 return *op;
1263 int radio_main(int argc, char *argv[])
1265 int op = RADIO_OFF;
1266 int unit;
1268 if (argc < 2) {
1269 HELP:
1270 usage_exit(argv[0], "on|off|toggle|join [N]\n");
1272 unit = (argc == 3) ? atoi(argv[2]) : -1;
1274 if (strcmp(argv[1], "toggle") == 0)
1275 op = RADIO_TOGGLE;
1276 else if (strcmp(argv[1], "off") == 0)
1277 op = RADIO_OFF;
1278 else if (strcmp(argv[1], "on") == 0)
1279 op = RADIO_ON;
1280 else if (strcmp(argv[1], "join") == 0)
1281 goto JOIN;
1282 else
1283 goto HELP;
1285 if (unit >= 0)
1286 op = radio_toggle(0, unit, 0, &op);
1287 else
1288 op = foreach_wif(0, &op, radio_toggle);
1290 if (!op) {
1291 led(LED_DIAG, 0);
1292 return 0;
1294 JOIN:
1295 foreach_wif(1, &unit, radio_join);
1296 return 0;
1300 int wdist_main(int argc, char *argv[])
1302 int n;
1303 rw_reg_t r;
1304 int v;
1306 if (argc != 2) {
1307 r.byteoff = 0x684;
1308 r.size = 2;
1309 if (wl_ioctl(nvram_safe_get("wl_ifname"), 101, &r, sizeof(r)) == 0) {
1310 v = r.val - 510;
1311 if (v <= 9) v = 0;
1312 else v = (v - (9 + 1)) * 150;
1313 printf("Current: %d-%dm (0x%02x)\n\n", v + (v ? 1 : 0), v + 150, r.val);
1315 usage_exit(argv[0], "<meters>");
1317 if ((n = atoi(argv[1])) <= 0) setup_wldistance();
1318 else set_wldistance(n);
1319 return 0;
1323 static int get_wldist(int idx, int unit, int subunit, void *param)
1325 int n;
1327 char *p = nvram_safe_get(wl_nvname("distance", unit, 0));
1328 if ((*p == 0) || ((n = atoi(p)) < 0)) return 0;
1330 return (9 + (n / 150) + ((n % 150) ? 1 : 0));
1333 static int wldist(int idx, int unit, int subunit, void *param)
1335 rw_reg_t r;
1336 uint32 s;
1337 char *p;
1338 int n;
1340 n = get_wldist(idx, unit, subunit, param);
1341 if (n > 0) {
1342 s = 0x10 | (n << 16);
1343 p = nvram_safe_get(wl_nvname("ifname", unit, 0));
1344 wl_ioctl(p, 197, &s, sizeof(s));
1346 r.byteoff = 0x684;
1347 r.val = n + 510;
1348 r.size = 2;
1349 wl_ioctl(p, 102, &r, sizeof(r));
1351 return 0;
1354 // ref: wificonf.c
1355 int wldist_main(int argc, char *argv[])
1357 if (fork() == 0) {
1358 if (foreach_wif(0, NULL, get_wldist) == 0) return 0;
1360 while (1) {
1361 foreach_wif(0, NULL, wldist);
1362 sleep(2);
1366 return 0;