fixes, fully translated tomato, with english dictionary and Polish translation
[tomato.git] / release / src / router / rc / network.c
blob5d6067a52d31a5f9341f182c7f5e3d0a68e3f561
1 /*
3 Copyright 2003, CyberTAN Inc. All Rights Reserved
5 This is UNPUBLISHED PROPRIETARY SOURCE CODE of CyberTAN Inc.
6 the contents of this file may not be disclosed to third parties,
7 copied or duplicated in any form without the prior written
8 permission of CyberTAN Inc.
10 This software should be used as a reference only, and it not
11 intended for production use!
13 THIS SOFTWARE IS OFFERED "AS IS", AND CYBERTAN GRANTS NO WARRANTIES OF ANY
14 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. CYBERTAN
15 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
16 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE
21 Copyright 2005, Broadcom Corporation
22 All Rights Reserved.
24 THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
25 KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
26 SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
27 FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
32 wificonf, OpenWRT
33 Copyright (C) 2005 Felix Fietkau <nbd@vd-s.ath.cx>
38 Modified for Tomato Firmware
39 Portions, Copyright (C) 2006-2009 Jonathan Zarate
43 #include <rc.h>
45 #ifndef UU_INT
46 typedef u_int64_t u64;
47 typedef u_int32_t u32;
48 typedef u_int16_t u16;
49 typedef u_int8_t u8;
50 #endif
52 #include <linux/types.h>
53 #include <linux/sockios.h>
54 #include <linux/ethtool.h>
55 #include <sys/ioctl.h>
56 #include <net/if_arp.h>
57 #include <arpa/inet.h>
58 #include <dirent.h>
60 #include <wlutils.h>
61 #include <bcmparams.h>
62 #include <wlioctl.h>
64 #ifndef WL_BSS_INFO_VERSION
65 #error WL_BSS_INFO_VERSION
66 #endif
67 #if WL_BSS_INFO_VERSION >= 108
68 #include <etioctl.h>
69 #else
70 #include <etsockio.h>
71 #endif
73 static void set_lan_hostname(const char *wan_hostname)
75 const char *s;
76 FILE *f;
78 nvram_set("lan_hostname", wan_hostname);
79 if ((wan_hostname == NULL) || (*wan_hostname == 0)) {
80 /* derive from et0 mac address */
81 s = nvram_get("et0macaddr");
82 if (s && strlen(s) >= 17) {
83 char hostname[16];
84 sprintf(hostname, "RT-%c%c%c%c%c%c%c%c%c%c%c%c",
85 s[0], s[1], s[3], s[4], s[6], s[7],
86 s[9], s[10], s[12], s[13], s[15], s[16]);
88 if ((f = fopen("/proc/sys/kernel/hostname", "w"))) {
89 fputs(hostname, f);
90 fclose(f);
92 nvram_set("lan_hostname", hostname);
96 if ((f = fopen("/etc/hosts", "w"))) {
97 fprintf(f, "127.0.0.1 localhost\n");
98 if ((s = nvram_get("lan_ipaddr")) && (*s))
99 fprintf(f, "%s %s\n", s, nvram_safe_get("lan_hostname"));
100 #ifdef TCONFIG_IPV6
101 if (ipv6_enabled()) {
102 fprintf(f, "::1 localhost\n");
103 s = ipv6_router_address(NULL);
104 if (*s) fprintf(f, "%s %s\n", s, nvram_safe_get("lan_hostname"));
106 #endif
107 fclose(f);
111 void set_host_domain_name(void)
113 const char *s;
115 s = nvram_safe_get("wan_hostname");
116 sethostname(s, strlen(s));
117 set_lan_hostname(s);
119 s = nvram_get("wan_domain");
120 if ((s == NULL) || (*s == 0)) s = nvram_safe_get("wan_get_domain");
121 setdomainname(s, strlen(s));
124 static int wlconf(char *ifname, int unit, int subunit)
126 int r;
127 char wl[24];
129 if (/* !wl_probe(ifname) && */ unit >= 0) {
130 // validate nvram settings for wireless i/f
131 snprintf(wl, sizeof(wl), "--wl%d", unit);
132 eval("nvram", "validate", wl);
135 r = eval("wlconf", ifname, "up");
136 if (r == 0) {
137 if (unit >= 0 && subunit <= 0) {
138 // setup primary wl interface
139 nvram_set("rrules_radio", "-1");
141 eval("wl", "-i", ifname, "antdiv", nvram_safe_get(wl_nvname("antdiv", unit, 0)));
142 eval("wl", "-i", ifname, "txant", nvram_safe_get(wl_nvname("txant", unit, 0)));
143 eval("wl", "-i", ifname, "txpwr1", "-o", "-m", nvram_get_int(wl_nvname("txpwr", unit, 0)) ? nvram_safe_get(wl_nvname("txpwr", unit, 0)) : "-1");
144 eval("wl", "-i", ifname, "interference", nvram_safe_get(wl_nvname("mitigation", unit, 0)));
147 if (wl_client(unit, subunit)) {
148 if (nvram_match(wl_nvname("mode", unit, subunit), "wet")) {
149 ifconfig(ifname, IFUP|IFF_ALLMULTI, NULL, NULL);
151 if (nvram_get_int(wl_nvname("radio", unit, 0))) {
152 snprintf(wl, sizeof(wl), "%d", unit);
153 xstart("radio", "join", wl);
157 return r;
160 // -----------------------------------------------------------------------------
162 #ifdef TCONFIG_EMF
163 static void emf_mfdb_update(char *lan_ifname, char *lan_port_ifname, bool add)
165 char word[256], *next;
166 char *mgrp, *ifname;
168 /* Add/Delete MFDB entries corresponding to new interface */
169 foreach (word, nvram_safe_get("emf_entry"), next) {
170 ifname = word;
171 mgrp = strsep(&ifname, ":");
173 if ((mgrp == NULL) || (ifname == NULL)) continue;
175 /* Add/Delete MFDB entry using the group addr and interface */
176 if (lan_port_ifname == NULL || strcmp(lan_port_ifname, ifname) == 0) {
177 eval("emf", ((add) ? "add" : "del"), "mfdb", lan_ifname, mgrp, ifname);
182 static void emf_uffp_update(char *lan_ifname, char *lan_port_ifname, bool add)
184 char word[256], *next;
185 char *ifname;
187 /* Add/Delete UFFP entries corresponding to new interface */
188 foreach (word, nvram_safe_get("emf_uffp_entry"), next) {
189 ifname = word;
191 if (ifname == NULL) continue;
193 /* Add/Delete UFFP entry for the interface */
194 if (lan_port_ifname == NULL || strcmp(lan_port_ifname, ifname) == 0) {
195 eval("emf", ((add) ? "add" : "del"), "uffp", lan_ifname, ifname);
200 static void emf_rtport_update(char *lan_ifname, char *lan_port_ifname, bool add)
202 char word[256], *next;
203 char *ifname;
205 /* Add/Delete RTPORT entries corresponding to new interface */
206 foreach (word, nvram_safe_get("emf_rtport_entry"), next) {
207 ifname = word;
209 if (ifname == NULL) continue;
211 /* Add/Delete RTPORT entry for the interface */
212 if (lan_port_ifname == NULL || strcmp(lan_port_ifname, ifname) == 0) {
213 eval("emf", ((add) ? "add" : "del"), "rtport", lan_ifname, ifname);
218 static void start_emf(char *lan_ifname)
220 /* Start EMF */
221 eval("emf", "start", lan_ifname);
223 /* Add the static MFDB entries */
224 emf_mfdb_update(lan_ifname, NULL, 1);
226 /* Add the UFFP entries */
227 emf_uffp_update(lan_ifname, NULL, 1);
229 /* Add the RTPORT entries */
230 emf_rtport_update(lan_ifname, NULL, 1);
233 static void stop_emf(char *lan_ifname)
235 eval("emf", "stop", lan_ifname);
236 eval("igs", "del", "bridge", lan_ifname);
237 eval("emf", "del", "bridge", lan_ifname);
239 #endif
241 // -----------------------------------------------------------------------------
243 /* Set initial QoS mode for all et interfaces that are up. */
244 void set_et_qos_mode(int sfd)
246 int i, qos;
247 caddr_t ifrdata;
248 struct ifreq ifr;
249 struct ethtool_drvinfo info;
251 qos = (strcmp(nvram_safe_get("wl_wme"), "off") != 0);
252 for (i = 1; i <= DEV_NUMIFS; i++) {
253 ifr.ifr_ifindex = i;
254 if (ioctl(sfd, SIOCGIFNAME, &ifr)) continue;
255 if (ioctl(sfd, SIOCGIFHWADDR, &ifr)) continue;
256 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) continue;
257 /* get flags */
258 if (ioctl(sfd, SIOCGIFFLAGS, &ifr)) continue;
259 /* if up (wan may not be up yet at this point) */
260 if (ifr.ifr_flags & IFF_UP) {
261 ifrdata = ifr.ifr_data;
262 memset(&info, 0, sizeof(info));
263 info.cmd = ETHTOOL_GDRVINFO;
264 ifr.ifr_data = (caddr_t)&info;
265 if (ioctl(sfd, SIOCETHTOOL, &ifr) >= 0) {
266 /* Set QoS for et & bcm57xx devices */
267 if (!strncmp(info.driver, "et", 2) ||
268 !strncmp(info.driver, "bcm57", 5)) {
269 ifr.ifr_data = (caddr_t)&qos;
270 ioctl(sfd, SIOCSETCQOS, &ifr);
273 ifr.ifr_data = ifrdata;
278 static void check_afterburner(void)
280 char *p;
282 if (nvram_match("wl_afterburner", "off")) return;
283 if ((p = nvram_get("boardflags")) == NULL) return;
285 if (strcmp(p, "0x0118") == 0) { // G 2.2, 3.0, 3.1
286 p = "0x0318";
288 else if (strcmp(p, "0x0188") == 0) { // G 2.0
289 p = "0x0388";
291 else if (strcmp(p, "0x2558") == 0) { // G 4.0, GL 1.0, 1.1
292 p = "0x2758";
294 else {
295 return;
298 nvram_set("boardflags", p);
300 if (!nvram_match("debug_abrst", "0")) {
301 modprobe_r("wl");
302 modprobe("wl");
306 /* safe?
308 unsigned long bf;
309 char s[64];
311 bf = strtoul(p, &p, 0);
312 if ((*p == 0) && ((bf & BFL_AFTERBURNER) == 0)) {
313 sprintf(s, "0x%04lX", bf | BFL_AFTERBURNER);
314 nvram_set("boardflags", s);
319 void start_wl(void)
321 char *lan_ifname, *lan_ifnames, *ifname, *p;
322 int unit, subunit;
323 int is_client = 0;
325 lan_ifname = nvram_safe_get("lan_ifname");
326 if (strncmp(lan_ifname, "br", 2) == 0) {
327 if ((lan_ifnames = strdup(nvram_safe_get("lan_ifnames"))) != NULL) {
328 p = lan_ifnames;
329 while ((ifname = strsep(&p, " ")) != NULL) {
330 while (*ifname == ' ') ++ifname;
331 if (*ifname == 0) break;
333 unit = -1; subunit = -1;
335 // ignore disabled wl vifs
336 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
337 char nv[40];
338 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
339 if (!nvram_get_int(nv))
340 continue;
341 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
342 continue;
344 // get the instance number of the wl i/f
345 else if (wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit)))
346 continue;
348 is_client |= wl_client(unit, subunit) && nvram_get_int(wl_nvname("radio", unit, 0));
350 #ifdef CONFIG_BCMWL5
351 eval("wlconf", ifname, "start"); /* start wl iface */
352 #endif // CONFIG_BCMWL5
354 free(lan_ifnames);
357 #ifdef CONFIG_BCMWL5
358 else if (strcmp(lan_ifname, "")) {
359 /* specific non-bridged lan iface */
360 eval("wlconf", lan_ifname, "start");
362 #endif // CONFIG_BCMWL5
364 killall("wldist", SIGTERM);
365 eval("wldist");
367 if (is_client)
368 xstart("radio", "join");
371 static int set_wlmac(int idx, int unit, int subunit, void *param)
373 char *ifname;
375 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
377 // skip disabled wl vifs
378 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
379 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
380 return 0;
382 set_mac(ifname, wl_nvname("macaddr", unit, subunit),
383 2 + unit + ((subunit > 0) ? ((unit + 1) * 0x10 + subunit) : 0));
385 return 1;
388 #ifdef TCONFIG_IPV6
389 void enable_ipv6(int enable)
391 DIR *dir;
392 struct dirent *dirent;
393 char s[256];
395 if ((dir = opendir("/proc/sys/net/ipv6/conf")) != NULL) {
396 while ((dirent = readdir(dir)) != NULL) {
397 sprintf(s, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", dirent->d_name);
398 f_write_string(s, enable ? "0" : "1", 0, 0);
400 closedir(dir);
404 void accept_ra(const char *ifname)
406 char s[256];
408 sprintf(s, "/proc/sys/net/ipv6/conf/%s/accept_ra", ifname);
409 f_write_string(s, "2", 0, 0);
411 sprintf(s, "/proc/sys/net/ipv6/conf/%s/forwarding", ifname);
412 f_write_string(s, "2", 0, 0);
414 #endif
416 void start_lan(void)
418 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
420 char *lan_ifname;
421 struct ifreq ifr;
422 char *lan_ifnames, *ifname, *p;
423 int sfd;
424 uint32 ip;
425 int unit, subunit, sta;
426 int hwaddrset;
427 char eabuf[32];
429 foreach_wif(1, NULL, set_wlmac);
430 check_afterburner();
431 #ifdef TCONFIG_IPV6
432 enable_ipv6(ipv6_enabled());
433 #endif
435 if ((sfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) return;
437 lan_ifname = strdup(nvram_safe_get("lan_ifname"));
438 if (strncmp(lan_ifname, "br", 2) == 0) {
439 _dprintf("%s: setting up the bridge %s\n", __FUNCTION__, lan_ifname);
441 eval("brctl", "addbr", lan_ifname);
442 eval("brctl", "setfd", lan_ifname, "0");
443 eval("brctl", "stp", lan_ifname, nvram_safe_get("lan_stp"));
445 #ifdef TCONFIG_EMF
446 if (nvram_get_int("emf_enable")) {
447 eval("emf", "add", "bridge", lan_ifname);
448 eval("igs", "add", "bridge", lan_ifname);
450 #endif
452 inet_aton(nvram_safe_get("lan_ipaddr"), (struct in_addr *)&ip);
454 hwaddrset = 0;
455 sta = 0;
456 if ((lan_ifnames = strdup(nvram_safe_get("lan_ifnames"))) != NULL) {
457 p = lan_ifnames;
458 while ((ifname = strsep(&p, " ")) != NULL) {
459 while (*ifname == ' ') ++ifname;
460 if (*ifname == 0) break;
462 unit = -1; subunit = -1;
464 // ignore disabled wl vifs
465 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
466 char nv[64];
468 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
469 if (!nvram_get_int(nv))
470 continue;
471 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
472 continue;
474 else
475 wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit));
477 // bring up interface
478 if (ifconfig(ifname, IFUP|IFF_ALLMULTI, NULL, NULL) != 0) continue;
480 // set the logical bridge address to that of the first interface
481 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
482 if ((!hwaddrset) ||
483 (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0 &&
484 memcmp(ifr.ifr_hwaddr.sa_data, "\0\0\0\0\0\0", ETHER_ADDR_LEN) == 0)) {
485 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
486 if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) {
487 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
488 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
489 _dprintf("%s: setting MAC of %s bridge to %s\n", __FUNCTION__,
490 ifr.ifr_name, ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
491 ioctl(sfd, SIOCSIFHWADDR, &ifr);
492 hwaddrset = 1;
496 if (wlconf(ifname, unit, subunit) == 0) {
497 const char *mode = nvram_safe_get(wl_nvname("mode", unit, subunit));
499 if (strcmp(mode, "wet") == 0) {
500 // Enable host DHCP relay
501 if (nvram_get_int("dhcp_relay")) {
502 wl_iovar_set(ifname, "wet_host_mac", ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
503 wl_iovar_setint(ifname, "wet_host_ipv4", ip);
507 sta |= (strcmp(mode, "sta") == 0);
508 if ((strcmp(mode, "ap") != 0) && (strcmp(mode, "wet") != 0)) continue;
510 eval("brctl", "addif", lan_ifname, ifname);
511 #ifdef TCONFIG_EMF
512 if (nvram_get_int("emf_enable"))
513 eval("emf", "add", "iface", lan_ifname, ifname);
514 #endif
517 if ((nvram_get_int("wan_islan")) &&
518 ((get_wan_proto() == WP_DISABLED) || (sta))) {
519 ifname = nvram_get("wan_ifnameX");
520 if (ifconfig(ifname, IFUP, NULL, NULL) == 0)
521 eval("brctl", "addif", lan_ifname, ifname);
524 free(lan_ifnames);
527 // --- this shouldn't happen ---
528 else if (*lan_ifname) {
529 ifconfig(lan_ifname, IFUP, NULL, NULL);
530 wlconf(lan_ifname, -1, -1);
532 else {
533 close(sfd);
534 free(lan_ifname);
535 return;
538 // Get current LAN hardware address
539 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
540 if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set("lan_hwaddr", ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
542 // Set initial QoS mode for LAN ports
543 set_et_qos_mode(sfd);
545 close(sfd);
547 // bring up and configure LAN interface
548 ifconfig(lan_ifname, IFUP, nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_netmask"));
550 config_loopback();
551 do_static_routes(1);
553 set_lan_hostname(nvram_safe_get("wan_hostname"));
555 if (get_wan_proto() == WP_DISABLED) {
556 char *gateway = nvram_safe_get("lan_gateway") ;
557 if ((*gateway) && (strcmp(gateway, "0.0.0.0") != 0)) {
558 int tries = 5;
559 while ((route_add(lan_ifname, 0, "0.0.0.0", gateway, "0.0.0.0") != 0) && (tries-- > 0)) sleep(1);
560 _dprintf("%s: add gateway=%s tries=%d\n", __FUNCTION__, gateway, tries);
564 #ifdef TCONFIG_IPV6
565 start_ipv6();
566 #endif
568 #ifdef TCONFIG_EMF
569 if (nvram_get_int("emf_enable")) start_emf(lan_ifname);
570 #endif
572 free(lan_ifname);
574 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
577 void stop_lan(void)
579 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
581 char *lan_ifname;
582 char *lan_ifnames, *p, *ifname;
584 lan_ifname = nvram_safe_get("lan_ifname");
585 ifconfig(lan_ifname, 0, NULL, NULL);
587 #ifdef TCONFIG_IPV6
588 stop_ipv6();
589 #endif
591 if (strncmp(lan_ifname, "br", 2) == 0) {
592 #ifdef TCONFIG_EMF
593 stop_emf(lan_ifname);
594 #endif
595 if ((lan_ifnames = strdup(nvram_safe_get("lan_ifnames"))) != NULL) {
596 p = lan_ifnames;
597 while ((ifname = strsep(&p, " ")) != NULL) {
598 while (*ifname == ' ') ++ifname;
599 if (*ifname == 0) break;
600 eval("wlconf", ifname, "down");
601 ifconfig(ifname, 0, NULL, NULL);
602 eval("brctl", "delif", lan_ifname, ifname);
604 free(lan_ifnames);
606 eval("brctl", "delbr", lan_ifname);
608 else if (*lan_ifname) {
609 eval("wlconf", lan_ifname, "down");
612 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
616 void do_static_routes(int add)
618 char *buf;
619 char *p, *q;
620 char *dest, *mask, *gateway, *metric, *ifname;
621 int r;
623 if ((buf = strdup(nvram_safe_get(add ? "routes_static" : "routes_static_saved"))) == NULL) return;
624 if (add) nvram_set("routes_static_saved", buf);
625 else nvram_unset("routes_static_saved");
626 p = buf;
627 while ((q = strsep(&p, ">")) != NULL) {
628 if (vstrsep(q, "<", &dest, &gateway, &mask, &metric, &ifname) != 5) continue;
629 ifname = nvram_safe_get((*ifname == 'L') ? "lan_ifname" :
630 ((*ifname == 'W') ? "wan_iface" : "wan_ifname"));
631 if (add) {
632 for (r = 3; r >= 0; --r) {
633 if (route_add(ifname, atoi(metric), dest, gateway, mask) == 0) break;
634 sleep(1);
637 else {
638 route_del(ifname, atoi(metric), dest, gateway, mask);
641 free(buf);
644 void hotplug_net(void)
646 char *interface, *action;
647 char *lan_ifname;
649 if (((interface = getenv("INTERFACE")) == NULL) || ((action = getenv("ACTION")) == NULL)) return;
651 _dprintf("hotplug net INTERFACE=%s ACTION=%s\n", interface, action);
653 if ((strncmp(interface, "wds", 3) == 0) &&
654 (strcmp(action, "register") == 0 || strcmp(action, "add") == 0)) {
655 ifconfig(interface, IFUP, NULL, NULL);
656 lan_ifname = nvram_safe_get("lan_ifname");
657 #ifdef TCONFIG_EMF
658 if (nvram_get_int("emf_enable")) {
659 eval("emf", "add", "iface", lan_ifname, interface);
660 emf_mfdb_update(lan_ifname, interface, 1);
661 emf_uffp_update(lan_ifname, interface, 1);
662 emf_rtport_update(lan_ifname, interface, 1);
664 #endif
665 if (strncmp(lan_ifname, "br", 2) == 0) {
666 eval("brctl", "addif", lan_ifname, interface);
667 notify_nas(interface);
673 static int is_same_addr(struct ether_addr *addr1, struct ether_addr *addr2)
675 int i;
676 for (i = 0; i < 6; i++) {
677 if (addr1->octet[i] != addr2->octet[i])
678 return 0;
680 return 1;
683 #define WL_MAX_ASSOC 128
684 static int check_wl_client(char *ifname, int unit, int subunit)
686 struct ether_addr bssid;
687 wl_bss_info_t *bi;
688 char buf[WLC_IOCTL_MAXLEN];
689 struct maclist *mlist;
690 int mlsize, i;
691 int associated, authorized;
693 *(uint32 *)buf = WLC_IOCTL_MAXLEN;
694 if (wl_ioctl(ifname, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN) < 0 ||
695 wl_ioctl(ifname, WLC_GET_BSS_INFO, buf, WLC_IOCTL_MAXLEN) < 0)
696 return 0;
698 bi = (wl_bss_info_t *)(buf + 4);
699 if ((bi->SSID_len == 0) ||
700 (bi->BSSID.octet[0] + bi->BSSID.octet[1] + bi->BSSID.octet[2] +
701 bi->BSSID.octet[3] + bi->BSSID.octet[4] + bi->BSSID.octet[5] == 0))
702 return 0;
704 associated = 0;
705 authorized = strstr(nvram_safe_get(wl_nvname("akm", unit, subunit)), "psk") == 0;
707 mlsize = sizeof(struct maclist) + (WL_MAX_ASSOC * sizeof(struct ether_addr));
708 if ((mlist = malloc(mlsize)) != NULL) {
709 mlist->count = WL_MAX_ASSOC;
710 if (wl_ioctl(ifname, WLC_GET_ASSOCLIST, mlist, mlsize) == 0) {
711 for (i = 0; i < mlist->count; ++i) {
712 if (is_same_addr(&mlist->ea[i], &bi->BSSID)) {
713 associated = 1;
714 break;
719 if (associated && !authorized) {
720 memset(mlist, 0, mlsize);
721 mlist->count = WL_MAX_ASSOC;
722 strcpy((char*)mlist, "autho_sta_list");
723 if (wl_ioctl(ifname, WLC_GET_VAR, mlist, mlsize) == 0) {
724 for (i = 0; i < mlist->count; ++i) {
725 if (is_same_addr(&mlist->ea[i], &bi->BSSID)) {
726 authorized = 1;
727 break;
732 free(mlist);
735 return (associated && authorized);
738 #define STACHECK_CONNECT 30
739 #define STACHECK_DISCONNECT 5
741 static int radio_join(int idx, int unit, int subunit, void *param)
743 int i;
744 char s[32], f[64];
745 char *ifname;
747 int *unit_filter = param;
748 if (*unit_filter >= 0 && *unit_filter != unit) return 0;
750 if (!nvram_get_int(wl_nvname("radio", unit, 0)) || !wl_client(unit, subunit)) return 0;
752 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
754 // skip disabled wl vifs
755 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
756 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
757 return 0;
759 sprintf(f, "/var/run/radio.%d.%d.pid", unit, subunit < 0 ? 0 : subunit);
760 if (f_read_string(f, s, sizeof(s)) > 0) {
761 if ((i = atoi(s)) > 1) {
762 kill(i, SIGTERM);
763 sleep(1);
767 if (fork() == 0) {
768 sprintf(s, "%d", getpid());
769 f_write(f, s, sizeof(s), 0, 0644);
771 int stacheck_connect = nvram_get_int("sta_chkint");
772 if (stacheck_connect <= 0)
773 stacheck_connect = STACHECK_CONNECT;
774 int stacheck;
776 while (get_radio(unit) && wl_client(unit, subunit)) {
778 if (check_wl_client(ifname, unit, subunit)) {
779 stacheck = stacheck_connect;
781 else {
782 eval("wl", "-i", ifname, "disassoc");
783 #ifdef CONFIG_BCMWL5
784 char *amode, *sec = nvram_safe_get(wl_nvname("akm", unit, subunit));
786 if (strstr(sec, "psk2")) amode = "wpa2psk";
787 else if (strstr(sec, "psk")) amode = "wpapsk";
788 else if (strstr(sec, "wpa2")) amode = "wpa2";
789 else if (strstr(sec, "wpa")) amode = "wpa";
790 else if (nvram_get_int(wl_nvname("auth", unit, subunit))) amode = "shared";
791 else amode = "open";
793 eval("wl", "-i", ifname, "join", nvram_safe_get(wl_nvname("ssid", unit, subunit)),
794 "imode", "bss", "amode", amode);
795 #else
796 eval("wl", "-i", ifname, "join", nvram_safe_get(wl_nvname("ssid", unit, subunit)));
797 #endif
798 stacheck = STACHECK_DISCONNECT;
800 sleep(stacheck);
802 unlink(f);
805 return 1;
808 enum {
809 RADIO_OFF = 0,
810 RADIO_ON = 1,
811 RADIO_TOGGLE = 2
814 static int radio_toggle(int idx, int unit, int subunit, void *param)
816 if (!nvram_get_int(wl_nvname("radio", unit, 0))) return 0;
818 int *op = param;
820 if (*op == RADIO_TOGGLE) {
821 *op = get_radio(unit) ? RADIO_OFF : RADIO_ON;
824 set_radio(*op, unit);
825 return *op;
828 int radio_main(int argc, char *argv[])
830 int op = RADIO_OFF;
831 int unit;
833 if (argc < 2) {
834 HELP:
835 usage_exit(argv[0], "on|off|toggle|join [N]\n");
837 unit = (argc == 3) ? atoi(argv[2]) : -1;
839 if (strcmp(argv[1], "toggle") == 0)
840 op = RADIO_TOGGLE;
841 else if (strcmp(argv[1], "off") == 0)
842 op = RADIO_OFF;
843 else if (strcmp(argv[1], "on") == 0)
844 op = RADIO_ON;
845 else if (strcmp(argv[1], "join") == 0)
846 goto JOIN;
847 else
848 goto HELP;
850 if (unit >= 0)
851 op = radio_toggle(0, unit, 0, &op);
852 else
853 op = foreach_wif(0, &op, radio_toggle);
855 if (!op) {
856 led(LED_DIAG, 0);
857 return 0;
859 JOIN:
860 foreach_wif(1, &unit, radio_join);
861 return 0;
865 int wdist_main(int argc, char *argv[])
867 int n;
868 rw_reg_t r;
869 int v;
871 if (argc != 2) {
872 r.byteoff = 0x684;
873 r.size = 2;
874 if (wl_ioctl(nvram_safe_get("wl_ifname"), 101, &r, sizeof(r)) == 0) {
875 v = r.val - 510;
876 if (v <= 9) v = 0;
877 else v = (v - (9 + 1)) * 150;
878 printf("Current: %d-%dm (0x%02x)\n\n", v + (v ? 1 : 0), v + 150, r.val);
880 usage_exit(argv[0], "<meters>");
882 if ((n = atoi(argv[1])) <= 0) setup_wldistance();
883 else set_wldistance(n);
884 return 0;
888 static int get_wldist(int idx, int unit, int subunit, void *param)
890 int n;
892 char *p = nvram_safe_get(wl_nvname("distance", unit, 0));
893 if ((*p == 0) || ((n = atoi(p)) < 0)) return 0;
895 return (9 + (n / 150) + ((n % 150) ? 1 : 0));
898 static int wldist(int idx, int unit, int subunit, void *param)
900 rw_reg_t r;
901 uint32 s;
902 char *p;
903 int n;
905 n = get_wldist(idx, unit, subunit, param);
906 if (n > 0) {
907 s = 0x10 | (n << 16);
908 p = nvram_safe_get(wl_nvname("ifname", unit, 0));
909 wl_ioctl(p, 197, &s, sizeof(s));
911 r.byteoff = 0x684;
912 r.val = n + 510;
913 r.size = 2;
914 wl_ioctl(p, 102, &r, sizeof(r));
916 return 0;
919 // ref: wificonf.c
920 int wldist_main(int argc, char *argv[])
922 if (fork() == 0) {
923 if (foreach_wif(0, NULL, get_wldist) == 0) return 0;
925 while (1) {
926 foreach_wif(0, NULL, wldist);
927 sleep(2);
931 return 0;