Netgear R6400 support
[tomato.git] / release / src-rt-6.x.4708 / router / rc / network.c
blobe0fc86924946573019ff8166af12a8c87cb055ec
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_R6400) || (get_model() == MODEL_R7000)) {
586 if (nvram_match("wl0_radio", "1"))
587 led(LED_WLAN, LED_ON);
588 if (nvram_match("wl1_radio", "1"))
589 led(LED_5G, LED_ON);
590 if (nvram_match("wl0_radio", "0"))
591 led(LED_WLAN, LED_OFF);
592 if (nvram_match("wl1_radio", "0"))
593 led(LED_5G, LED_OFF);
596 if (get_model() == MODEL_WS880) {
597 if (nvram_match("wl0_radio", "1") || nvram_match("wl1_radio", "1"))
598 led(LED_WLAN, LED_ON);
599 else
600 led(LED_WLAN, LED_OFF);
604 #ifdef CONFIG_BCMWL5
605 static int disabled_wl(int idx, int unit, int subunit, void *param)
607 char *ifname;
609 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
611 // skip disabled wl vifs
612 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
613 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
614 return 1;
615 return 0;
617 #endif
619 void start_wl(void)
621 char *lan_ifname, *lan_ifnames, *ifname, *p;
622 int unit, subunit;
623 int is_client = 0;
625 char tmp[32];
626 char br;
628 #ifdef CONFIG_BCMWL5
629 // HACK: When a virtual SSID is disabled, it requires two initialisation
630 if (foreach_wif(1, NULL, disabled_wl))
632 stop_wireless();
633 start_wireless();
634 return;
636 #endif
638 for(br=0 ; br<4 ; br++) {
639 char bridge[2] = "0";
640 if (br!=0)
641 bridge[0]+=br;
642 else
643 strcpy(bridge, "");
645 strcpy(tmp,"lan");
646 strcat(tmp,bridge);
647 strcat(tmp, "_ifname");
648 lan_ifname = nvram_safe_get(tmp);
649 if (strncmp(lan_ifname, "br", 2) == 0) {
650 strcpy(tmp,"lan");
651 strcat(tmp,bridge);
652 strcat(tmp, "_ifnames");
653 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
654 p = lan_ifnames;
655 while ((ifname = strsep(&p, " ")) != NULL) {
656 while (*ifname == ' ') ++ifname;
657 if (*ifname == 0) continue;
659 unit = -1; subunit = -1;
661 // ignore disabled wl vifs
662 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
663 char nv[40];
664 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
665 if (!nvram_get_int(nv))
666 continue;
667 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
668 continue;
670 // get the instance number of the wl i/f
671 else if (wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit)))
672 continue;
674 is_client |= wl_client(unit, subunit) && nvram_get_int(wl_nvname("radio", unit, 0));
676 #ifdef CONFIG_BCMWL5
677 eval("wlconf", ifname, "start"); /* start wl iface */
678 // Enable LED if wireless interface is enabled, and turn on blink (traffic "control" of LED) if enabled
679 if (nvram_get_int(wl_nvname("radio", unit, 0))) {
680 if (unit == 0) {
681 led(LED_WLAN, LED_ON);
682 killall("blink", SIGKILL);
683 if (nvram_get_int("blink_wl"))
684 eval("blink", ifname, "wlan", "20", "8192");
686 else{
687 led(LED_5G, LED_ON);
688 if (nvram_get_int("blink_wl"))
689 eval("blink", ifname, "5g", "20", "8192");
692 #endif // CONFIG_BCMWL5
694 free(lan_ifnames);
697 #ifdef CONFIG_BCMWL5
698 else if (strcmp(lan_ifname, "")) {
699 /* specific non-bridged lan iface */
700 eval("wlconf", lan_ifname, "start");
702 #endif // CONFIG_BCMWL5
705 killall("wldist", SIGTERM);
706 eval("wldist");
708 if (is_client)
709 xstart("radio", "join");
711 if ((get_model() == MODEL_R6400) || get_model() == MODEL_R7000) {
712 if (nvram_match("wl0_radio", "1"))
713 led(LED_WLAN, LED_ON);
714 if (nvram_match("wl1_radio", "1"))
715 led(LED_5G, LED_ON);
716 if (nvram_match("wl0_radio", "0"))
717 led(LED_WLAN, LED_OFF);
718 if (nvram_match("wl1_radio", "0"))
719 led(LED_5G, LED_OFF);
722 if (get_model() == MODEL_WS880) {
723 if (nvram_match("wl0_radio", "1") || nvram_match("wl1_radio", "1"))
724 led(LED_WLAN, LED_ON);
725 else
726 led(LED_WLAN, LED_OFF);
730 #ifdef TCONFIG_IPV6
731 void enable_ipv6(int enable)
733 DIR *dir;
734 struct dirent *dirent;
735 char s[256];
737 if ((dir = opendir("/proc/sys/net/ipv6/conf")) != NULL) {
738 while ((dirent = readdir(dir)) != NULL) {
739 if (strcmp("vlan1", dirent->d_name) &&
740 strcmp("eth0", dirent->d_name) &&
741 strcmp("all", dirent->d_name) &&
742 strcmp("eth1", dirent->d_name))
745 sprintf(s, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", dirent->d_name);
746 f_write_string(s, enable ? "0" : "1", 0, 0);
749 closedir(dir);
753 void accept_ra(const char *ifname)
755 char s[256];
757 sprintf(s, "/proc/sys/net/ipv6/conf/%s/accept_ra", ifname);
758 f_write_string(s, "2", 0, 0);
760 sprintf(s, "/proc/sys/net/ipv6/conf/%s/forwarding", ifname);
761 f_write_string(s, "2", 0, 0);
763 #endif
765 void start_lan(void)
767 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
769 char *lan_ifname;
770 struct ifreq ifr;
771 char *lan_ifnames, *ifname, *p;
772 int sfd;
773 uint32 ip;
774 int unit, subunit, sta;
775 int hwaddrset;
776 char eabuf[32];
777 char tmp[32];
778 char tmp2[32];
779 char br;
780 int vlan0tag;
781 int vid;
782 int vid_map;
783 char *iftmp;
784 char nv[64];
786 #ifdef CONFIG_BCMWL5
787 foreach_wif(0, NULL, set_wlmac);
788 #else
789 foreach_wif(1, NULL, set_wlmac);
790 #endif
791 check_afterburner();
792 #ifdef TCONFIG_IPV6
793 enable_ipv6(ipv6_enabled()); //tell Kernel to disable/enable IPv6 for most interfaces
794 #endif
795 vlan0tag = nvram_get_int("vlan0tag");
797 if ((sfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) return;
798 for(br=0 ; br<4 ; br++) {
799 char bridge[2] = "0";
800 if (br!=0)
801 bridge[0]+=br;
802 else
803 strcpy(bridge, "");
805 strcpy(tmp,"lan");
806 strcat(tmp,bridge);
807 strcat(tmp, "_ifname");
808 lan_ifname = strdup(nvram_safe_get(tmp));
810 if (strncmp(lan_ifname, "br", 2) == 0) {
811 _dprintf("%s: setting up the bridge %s\n", __FUNCTION__, lan_ifname);
813 eval("brctl", "addbr", lan_ifname);
814 eval("brctl", "setfd", lan_ifname, "0");
815 strcpy(tmp,"lan");
816 strcat(tmp,bridge);
817 strcat(tmp, "_stp");
818 eval("brctl", "stp", lan_ifname, nvram_safe_get(tmp));
820 #ifdef TCONFIG_EMF
821 if (nvram_get_int("emf_enable")) {
822 eval("emf", "add", "bridge", lan_ifname);
823 eval("igs", "add", "bridge", lan_ifname);
825 #endif
827 strcpy(tmp,"lan");
828 strcat(tmp,bridge);
829 strcat(tmp, "_ipaddr");
830 inet_aton(nvram_safe_get(tmp), (struct in_addr *)&ip);
832 hwaddrset = 0;
833 sta = 0;
835 strcpy(tmp,"lan");
836 strcat(tmp,bridge);
837 strcat(tmp, "_ifnames");
838 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
839 p = lan_ifnames;
840 while ((iftmp = strsep(&p, " ")) != NULL) {
841 while (*iftmp == ' ') ++iftmp;
842 if (*iftmp == 0) continue;
843 ifname = iftmp;
845 unit = -1; subunit = -1;
847 // ignore disabled wl vifs
848 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
850 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
851 if (!nvram_get_int(nv))
852 continue;
853 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
854 continue;
855 #ifdef CONFIG_BCMWL5
856 set_wlmac(0, unit, subunit, NULL);
857 #endif
859 else
860 wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit));
862 // vlan ID mapping
863 if (strncmp(ifname, "vlan", 4) == 0) {
864 if (sscanf(ifname, "vlan%d", &vid) == 1) {
865 snprintf(tmp, sizeof(tmp), "vlan%dvid", vid);
866 vid_map = nvram_get_int(tmp);
867 if ((vid_map < 1) || (vid_map > 4094)) vid_map = vlan0tag | vid;
868 snprintf(tmp, sizeof(tmp), "vlan%d", vid_map);
869 ifname = tmp;
873 // bring up interface
874 if (ifconfig(ifname, IFUP|IFF_ALLMULTI, NULL, NULL) != 0) continue;
876 // set the logical bridge address to that of the first interface
877 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
878 if ((!hwaddrset) ||
879 (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0 &&
880 memcmp(ifr.ifr_hwaddr.sa_data, "\0\0\0\0\0\0", ETHER_ADDR_LEN) == 0)) {
881 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
882 if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) {
883 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
884 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
885 _dprintf("%s: setting MAC of %s bridge to %s\n", __FUNCTION__,
886 ifr.ifr_name, ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
887 ioctl(sfd, SIOCSIFHWADDR, &ifr);
888 hwaddrset = 1;
892 if (wlconf(ifname, unit, subunit) == 0) {
893 const char *mode = nvram_safe_get(wl_nvname("mode", unit, subunit));
895 if (strcmp(mode, "wet") == 0) {
896 // Enable host DHCP relay
897 if (nvram_get_int("dhcp_relay")) {
898 wl_iovar_set(ifname, "wet_host_mac", ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
899 wl_iovar_setint(ifname, "wet_host_ipv4", ip);
903 sta |= (strcmp(mode, "sta") == 0);
904 if ((strcmp(mode, "ap") != 0) && (strcmp(mode, "wet") != 0)) continue;
906 eval("brctl", "addif", lan_ifname, ifname);
907 #ifdef TCONFIG_EMF
908 if (nvram_get_int("emf_enable"))
909 eval("emf", "add", "iface", lan_ifname, ifname);
910 #endif
913 if ((nvram_get_int("wan_islan")) && (br==0) &&
914 ((get_wan_proto() == WP_DISABLED) || (sta))) {
915 ifname = nvram_get("wan_ifnameX");
916 if (ifconfig(ifname, IFUP, NULL, NULL) == 0)
917 eval("brctl", "addif", lan_ifname, ifname);
920 free(lan_ifnames);
923 // --- this shouldn't happen ---
924 else if (*lan_ifname) {
925 ifconfig(lan_ifname, IFUP, NULL, NULL);
926 wlconf(lan_ifname, -1, -1);
928 else {
929 close(sfd);
930 free(lan_ifname);
931 return;
934 // Get current LAN hardware address
935 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
936 strcpy(tmp,"lan");
937 strcat(tmp,bridge);
938 strcat(tmp, "_hwaddr");
939 // if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set("lan_hwaddr", ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
940 if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set(tmp, ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
942 // Set initial QoS mode for LAN ports
943 set_et_qos_mode(sfd);
945 close(sfd);
947 // bring up and configure LAN interface
948 strcpy(tmp,"lan");
949 strcat(tmp,bridge);
950 strcat(tmp, "_ipaddr");
951 strcpy(tmp2,"lan");
952 strcat(tmp2,bridge);
953 strcat(tmp2, "_netmask");
954 ifconfig(lan_ifname, IFUP, nvram_safe_get(tmp), nvram_safe_get(tmp2));
956 config_loopback();
957 do_static_routes(1);
959 if(br==0)
960 set_lan_hostname(nvram_safe_get("wan_hostname"));
962 if ((get_wan_proto() == WP_DISABLED) && (br==0)) {
963 char *gateway = nvram_safe_get("lan_gateway") ;
964 if ((*gateway) && (strcmp(gateway, "0.0.0.0") != 0)) {
965 int tries = 5;
966 while ((route_add(lan_ifname, 0, "0.0.0.0", gateway, "0.0.0.0") != 0) && (tries-- > 0)) sleep(1);
967 _dprintf("%s: add gateway=%s tries=%d\n", __FUNCTION__, gateway, tries);
971 #ifdef TCONFIG_IPV6
972 start_ipv6();
973 #endif
975 #ifdef TCONFIG_EMF
976 if (nvram_get_int("emf_enable")) start_emf(lan_ifname);
977 #endif
979 free(lan_ifname);
981 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
984 void stop_lan(void)
986 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
988 char *lan_ifname;
989 char *lan_ifnames, *p, *ifname;
990 char tmp[32];
991 char br;
992 int vlan0tag, vid, vid_map;
993 char *iftmp;
995 vlan0tag = nvram_get_int("vlan0tag");
997 for(br=0 ; br<4 ; br++) {
998 char bridge[2] = "0";
999 if (br!=0)
1000 bridge[0]+=br;
1001 else
1002 strcpy(bridge, "");
1004 strcpy(tmp,"lan");
1005 strcat(tmp,bridge);
1006 strcat(tmp, "_ifname");
1007 lan_ifname = nvram_safe_get(tmp);
1008 ifconfig(lan_ifname, 0, NULL, NULL);
1010 #ifdef TCONFIG_IPV6
1011 stop_ipv6();
1012 #endif
1014 if (strncmp(lan_ifname, "br", 2) == 0) {
1015 #ifdef TCONFIG_EMF
1016 stop_emf(lan_ifname);
1017 #endif
1018 strcpy(tmp,"lan");
1019 strcat(tmp,bridge);
1020 strcat(tmp, "_ifnames");
1021 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
1022 p = lan_ifnames;
1023 while ((iftmp = strsep(&p, " ")) != NULL) {
1024 while (*iftmp == ' ') ++iftmp;
1025 if (*iftmp == 0) continue;
1026 ifname = iftmp;
1027 // vlan ID mapping
1028 if (strncmp(ifname, "vlan", 4) == 0) {
1029 if (sscanf(ifname, "vlan%d", &vid) == 1) {
1030 snprintf(tmp, sizeof(tmp), "vlan%dvid", vid);
1031 vid_map = nvram_get_int(tmp);
1032 if ((vid_map < 1) || (vid_map > 4094)) vid_map = vlan0tag | vid;
1033 snprintf(tmp, sizeof(tmp), "vlan%d", vid_map);
1034 ifname = tmp;
1037 eval("wlconf", ifname, "down");
1038 ifconfig(ifname, 0, NULL, NULL);
1039 eval("brctl", "delif", lan_ifname, ifname);
1041 free(lan_ifnames);
1043 eval("brctl", "delbr", lan_ifname);
1045 else if (*lan_ifname) {
1046 eval("wlconf", lan_ifname, "down");
1049 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
1052 static int is_sta(int idx, int unit, int subunit, void *param)
1054 return (nvram_match(wl_nvname("mode", unit, subunit), "sta") && (nvram_match(wl_nvname("bss_enabled", unit, subunit), "1")));
1057 void do_static_routes(int add)
1059 char *buf;
1060 char *p, *q;
1061 char *dest, *mask, *gateway, *metric, *ifname;
1062 int r;
1064 if ((buf = strdup(nvram_safe_get(add ? "routes_static" : "routes_static_saved"))) == NULL) return;
1065 if (add) nvram_set("routes_static_saved", buf);
1066 else nvram_unset("routes_static_saved");
1067 p = buf;
1068 while ((q = strsep(&p, ">")) != NULL) {
1069 if (vstrsep(q, "<", &dest, &gateway, &mask, &metric, &ifname) != 5) continue;
1070 ifname = nvram_safe_get(((strcmp(ifname,"LAN")==0) ? "lan_ifname" :
1071 ((strcmp(ifname,"LAN1")==0) ? "lan1_ifname" :
1072 ((strcmp(ifname,"LAN2")==0) ? "lan2_ifname" :
1073 ((strcmp(ifname,"LAN3")==0) ? "lan3_ifname" :
1074 ((*ifname == 'W') ? "wan_iface" : "wan_ifname"))))));
1075 if (add) {
1076 for (r = 3; r >= 0; --r) {
1077 if (route_add(ifname, atoi(metric), dest, gateway, mask) == 0) break;
1078 sleep(1);
1081 else {
1082 route_del(ifname, atoi(metric), dest, gateway, mask);
1085 free(buf);
1087 char *modem_ipaddr;
1088 if ( (nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "dhcp") || nvram_match("wan_proto", "static") )
1089 && (modem_ipaddr = nvram_safe_get("modem_ipaddr")) && *modem_ipaddr && !nvram_match("modem_ipaddr","0.0.0.0")
1090 && (!foreach_wif(1, NULL, is_sta)) ) {
1091 char ip[16];
1092 char *end = rindex(modem_ipaddr,'.')+1;
1093 unsigned char c = atoi(end);
1094 char *iface = nvram_safe_get("wan_ifname");
1096 sprintf(ip, "%.*s%hhu", end-modem_ipaddr, modem_ipaddr, (unsigned char)(c^1^((c&2)^((c&1)<<1))) );
1097 eval("ip", "addr", add ?"add":"del", ip, "peer", modem_ipaddr, "dev", iface);
1102 void hotplug_net(void)
1104 char *interface, *action;
1105 char *lan_ifname;
1107 if (((interface = getenv("INTERFACE")) == NULL) || ((action = getenv("ACTION")) == NULL)) return;
1109 _dprintf("hotplug net INTERFACE=%s ACTION=%s\n", interface, action);
1111 if ((strncmp(interface, "wds", 3) == 0) &&
1112 (strcmp(action, "register") == 0 || strcmp(action, "add") == 0)) {
1113 ifconfig(interface, IFUP, NULL, NULL);
1114 lan_ifname = nvram_safe_get("lan_ifname");
1115 #ifdef TCONFIG_EMF
1116 if (nvram_get_int("emf_enable")) {
1117 eval("emf", "add", "iface", lan_ifname, interface);
1118 emf_mfdb_update(lan_ifname, interface, 1);
1119 emf_uffp_update(lan_ifname, interface, 1);
1120 emf_rtport_update(lan_ifname, interface, 1);
1122 #endif
1123 if (strncmp(lan_ifname, "br", 2) == 0) {
1124 eval("brctl", "addif", lan_ifname, interface);
1125 notify_nas(interface);
1131 static int is_same_addr(struct ether_addr *addr1, struct ether_addr *addr2)
1133 int i;
1134 for (i = 0; i < 6; i++) {
1135 if (addr1->octet[i] != addr2->octet[i])
1136 return 0;
1138 return 1;
1141 #define WL_MAX_ASSOC 128
1142 static int check_wl_client(char *ifname, int unit, int subunit)
1144 struct ether_addr bssid;
1145 wl_bss_info_t *bi;
1146 char buf[WLC_IOCTL_MAXLEN];
1147 struct maclist *mlist;
1148 int mlsize, i;
1149 int associated, authorized;
1151 *(uint32 *)buf = WLC_IOCTL_MAXLEN;
1152 if (wl_ioctl(ifname, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN) < 0 ||
1153 wl_ioctl(ifname, WLC_GET_BSS_INFO, buf, WLC_IOCTL_MAXLEN) < 0)
1154 return 0;
1156 bi = (wl_bss_info_t *)(buf + 4);
1157 if ((bi->SSID_len == 0) ||
1158 (bi->BSSID.octet[0] + bi->BSSID.octet[1] + bi->BSSID.octet[2] +
1159 bi->BSSID.octet[3] + bi->BSSID.octet[4] + bi->BSSID.octet[5] == 0))
1160 return 0;
1162 associated = 0;
1163 authorized = strstr(nvram_safe_get(wl_nvname("akm", unit, subunit)), "psk") == 0;
1165 mlsize = sizeof(struct maclist) + (WL_MAX_ASSOC * sizeof(struct ether_addr));
1166 if ((mlist = malloc(mlsize)) != NULL) {
1167 mlist->count = WL_MAX_ASSOC;
1168 if (wl_ioctl(ifname, WLC_GET_ASSOCLIST, mlist, mlsize) == 0) {
1169 for (i = 0; i < mlist->count; ++i) {
1170 if (is_same_addr(&mlist->ea[i], &bi->BSSID)) {
1171 associated = 1;
1172 break;
1177 if (associated && !authorized) {
1178 memset(mlist, 0, mlsize);
1179 mlist->count = WL_MAX_ASSOC;
1180 strcpy((char*)mlist, "autho_sta_list");
1181 if (wl_ioctl(ifname, WLC_GET_VAR, mlist, mlsize) == 0) {
1182 for (i = 0; i < mlist->count; ++i) {
1183 if (is_same_addr(&mlist->ea[i], &bi->BSSID)) {
1184 authorized = 1;
1185 break;
1190 free(mlist);
1193 return (associated && authorized);
1196 #define STACHECK_CONNECT 30
1197 #define STACHECK_DISCONNECT 5
1199 static int radio_join(int idx, int unit, int subunit, void *param)
1201 int i;
1202 char s[32], f[64];
1203 char *ifname;
1205 int *unit_filter = param;
1206 if (*unit_filter >= 0 && *unit_filter != unit) return 0;
1208 if (!nvram_get_int(wl_nvname("radio", unit, 0)) || !wl_client(unit, subunit)) return 0;
1210 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
1212 // skip disabled wl vifs
1213 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
1214 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
1215 return 0;
1217 sprintf(f, "/var/run/radio.%d.%d.pid", unit, subunit < 0 ? 0 : subunit);
1218 if (f_read_string(f, s, sizeof(s)) > 0) {
1219 if ((i = atoi(s)) > 1) {
1220 kill(i, SIGTERM);
1221 sleep(1);
1225 if (fork() == 0) {
1226 sprintf(s, "%d", getpid());
1227 f_write(f, s, sizeof(s), 0, 0644);
1229 int stacheck_connect = nvram_get_int("sta_chkint");
1230 if (stacheck_connect <= 0)
1231 stacheck_connect = STACHECK_CONNECT;
1232 int stacheck;
1234 while (get_radio(unit) && wl_client(unit, subunit)) {
1236 if (check_wl_client(ifname, unit, subunit)) {
1237 stacheck = stacheck_connect;
1239 else {
1240 eval("wl", "-i", ifname, "disassoc");
1241 #ifdef CONFIG_BCMWL5
1242 char *amode, *sec = nvram_safe_get(wl_nvname("akm", unit, subunit));
1244 if (strstr(sec, "psk2")) amode = "wpa2psk";
1245 else if (strstr(sec, "psk")) amode = "wpapsk";
1246 else if (strstr(sec, "wpa2")) amode = "wpa2";
1247 else if (strstr(sec, "wpa")) amode = "wpa";
1248 else if (nvram_get_int(wl_nvname("auth", unit, subunit))) amode = "shared";
1249 else amode = "open";
1251 eval("wl", "-i", ifname, "join", nvram_safe_get(wl_nvname("ssid", unit, subunit)),
1252 "imode", "bss", "amode", amode);
1253 #else
1254 eval("wl", "-i", ifname, "join", nvram_safe_get(wl_nvname("ssid", unit, subunit)));
1255 #endif
1256 stacheck = STACHECK_DISCONNECT;
1258 sleep(stacheck);
1260 unlink(f);
1263 return 1;
1266 enum {
1267 RADIO_OFF = 0,
1268 RADIO_ON = 1,
1269 RADIO_TOGGLE = 2
1272 static int radio_toggle(int idx, int unit, int subunit, void *param)
1274 if (!nvram_get_int(wl_nvname("radio", unit, 0))) return 0;
1276 int *op = param;
1278 if (*op == RADIO_TOGGLE) {
1279 *op = get_radio(unit) ? RADIO_OFF : RADIO_ON;
1282 set_radio(*op, unit);
1283 return *op;
1286 int radio_main(int argc, char *argv[])
1288 int op = RADIO_OFF;
1289 int unit;
1291 if (argc < 2) {
1292 HELP:
1293 usage_exit(argv[0], "on|off|toggle|join [N]\n");
1295 unit = (argc == 3) ? atoi(argv[2]) : -1;
1297 if (strcmp(argv[1], "toggle") == 0)
1298 op = RADIO_TOGGLE;
1299 else if (strcmp(argv[1], "off") == 0)
1300 op = RADIO_OFF;
1301 else if (strcmp(argv[1], "on") == 0)
1302 op = RADIO_ON;
1303 else if (strcmp(argv[1], "join") == 0)
1304 goto JOIN;
1305 else
1306 goto HELP;
1308 if (unit >= 0)
1309 op = radio_toggle(0, unit, 0, &op);
1310 else
1311 op = foreach_wif(0, &op, radio_toggle);
1313 if (!op) {
1314 led(LED_DIAG, 0);
1315 return 0;
1317 JOIN:
1318 foreach_wif(1, &unit, radio_join);
1319 return 0;
1323 int wdist_main(int argc, char *argv[])
1325 int n;
1326 rw_reg_t r;
1327 int v;
1329 if (argc != 2) {
1330 r.byteoff = 0x684;
1331 r.size = 2;
1332 if (wl_ioctl(nvram_safe_get("wl_ifname"), 101, &r, sizeof(r)) == 0) {
1333 v = r.val - 510;
1334 if (v <= 9) v = 0;
1335 else v = (v - (9 + 1)) * 150;
1336 printf("Current: %d-%dm (0x%02x)\n\n", v + (v ? 1 : 0), v + 150, r.val);
1338 usage_exit(argv[0], "<meters>");
1340 if ((n = atoi(argv[1])) <= 0) setup_wldistance();
1341 else set_wldistance(n);
1342 return 0;
1346 static int get_wldist(int idx, int unit, int subunit, void *param)
1348 int n;
1350 char *p = nvram_safe_get(wl_nvname("distance", unit, 0));
1351 if ((*p == 0) || ((n = atoi(p)) < 0)) return 0;
1353 return (9 + (n / 150) + ((n % 150) ? 1 : 0));
1356 static int wldist(int idx, int unit, int subunit, void *param)
1358 rw_reg_t r;
1359 uint32 s;
1360 char *p;
1361 int n;
1363 n = get_wldist(idx, unit, subunit, param);
1364 if (n > 0) {
1365 s = 0x10 | (n << 16);
1366 p = nvram_safe_get(wl_nvname("ifname", unit, 0));
1367 wl_ioctl(p, 197, &s, sizeof(s));
1369 r.byteoff = 0x684;
1370 r.val = n + 510;
1371 r.size = 2;
1372 wl_ioctl(p, 102, &r, sizeof(r));
1374 return 0;
1377 // ref: wificonf.c
1378 int wldist_main(int argc, char *argv[])
1380 if (fork() == 0) {
1381 if (foreach_wif(0, NULL, get_wldist) == 0) return 0;
1383 while (1) {
1384 foreach_wif(0, NULL, wldist);
1385 sleep(2);
1389 return 0;