OpenSSL 1.0.1 update
[tomato.git] / release / src / router / rc / network.c
blobae65776f845c3ddae9960824d614f0734f25b619
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 %s-lan\n", s, nvram_safe_get("lan_hostname"), nvram_safe_get("lan_hostname"));
100 #ifdef TCONFIG_VLAN
101 if ((s = nvram_get("lan1_ipaddr")) && (*s) && (strcmp(s,"") != 0))
102 fprintf(f, "%s %s-lan1\n", s, nvram_safe_get("lan_hostname"));
103 if ((s = nvram_get("lan2_ipaddr")) && (*s) && (strcmp(s,"") != 0))
104 fprintf(f, "%s %s-lan2\n", s, nvram_safe_get("lan_hostname"));
105 if ((s = nvram_get("lan3_ipaddr")) && (*s) && (strcmp(s,"") != 0))
106 fprintf(f, "%s %s-lan3\n", s, nvram_safe_get("lan_hostname"));
107 #endif
108 #ifdef TCONFIG_IPV6
109 if (ipv6_enabled()) {
110 fprintf(f, "::1 localhost\n");
111 s = ipv6_router_address(NULL);
112 if (*s) fprintf(f, "%s %s\n", s, nvram_safe_get("lan_hostname"));
114 #endif
115 fclose(f);
119 void set_host_domain_name(void)
121 const char *s;
123 s = nvram_safe_get("wan_hostname");
124 sethostname(s, strlen(s));
125 set_lan_hostname(s);
127 s = nvram_get("wan_domain");
128 if ((s == NULL) || (*s == 0)) s = nvram_safe_get("wan_get_domain");
129 setdomainname(s, strlen(s));
132 static int wlconf(char *ifname, int unit, int subunit)
134 int r;
135 char wl[24];
137 if (/* !wl_probe(ifname) && */ unit >= 0) {
138 // validate nvram settings for wireless i/f
139 snprintf(wl, sizeof(wl), "--wl%d", unit);
140 eval("nvram", "validate", wl);
143 r = eval("wlconf", ifname, "up");
144 if (r == 0) {
145 if (unit >= 0 && subunit <= 0) {
146 // setup primary wl interface
147 nvram_set("rrules_radio", "-1");
149 eval("wl", "-i", ifname, "antdiv", nvram_safe_get(wl_nvname("antdiv", unit, 0)));
150 eval("wl", "-i", ifname, "txant", nvram_safe_get(wl_nvname("txant", unit, 0)));
151 eval("wl", "-i", ifname, "txpwr1", "-o", "-m", nvram_get_int(wl_nvname("txpwr", unit, 0)) ? nvram_safe_get(wl_nvname("txpwr", unit, 0)) : "-1");
152 eval("wl", "-i", ifname, "interference", nvram_safe_get(wl_nvname("mitigation", unit, 0)));
155 if (wl_client(unit, subunit)) {
156 if (nvram_match(wl_nvname("mode", unit, subunit), "wet")) {
157 ifconfig(ifname, IFUP|IFF_ALLMULTI, NULL, NULL);
159 if (nvram_get_int(wl_nvname("radio", unit, 0))) {
160 snprintf(wl, sizeof(wl), "%d", unit);
161 xstart("radio", "join", wl);
165 return r;
168 // -----------------------------------------------------------------------------
170 #ifdef TCONFIG_EMF
171 static void emf_mfdb_update(char *lan_ifname, char *lan_port_ifname, bool add)
173 char word[256], *next;
174 char *mgrp, *ifname;
176 /* Add/Delete MFDB entries corresponding to new interface */
177 foreach (word, nvram_safe_get("emf_entry"), next) {
178 ifname = word;
179 mgrp = strsep(&ifname, ":");
181 if ((mgrp == NULL) || (ifname == NULL)) continue;
183 /* Add/Delete MFDB entry using the group addr and interface */
184 if (lan_port_ifname == NULL || strcmp(lan_port_ifname, ifname) == 0) {
185 eval("emf", ((add) ? "add" : "del"), "mfdb", lan_ifname, mgrp, ifname);
190 static void emf_uffp_update(char *lan_ifname, char *lan_port_ifname, bool add)
192 char word[256], *next;
193 char *ifname;
195 /* Add/Delete UFFP entries corresponding to new interface */
196 foreach (word, nvram_safe_get("emf_uffp_entry"), next) {
197 ifname = word;
199 if (ifname == NULL) continue;
201 /* Add/Delete UFFP entry for the interface */
202 if (lan_port_ifname == NULL || strcmp(lan_port_ifname, ifname) == 0) {
203 eval("emf", ((add) ? "add" : "del"), "uffp", lan_ifname, ifname);
208 static void emf_rtport_update(char *lan_ifname, char *lan_port_ifname, bool add)
210 char word[256], *next;
211 char *ifname;
213 /* Add/Delete RTPORT entries corresponding to new interface */
214 foreach (word, nvram_safe_get("emf_rtport_entry"), next) {
215 ifname = word;
217 if (ifname == NULL) continue;
219 /* Add/Delete RTPORT entry for the interface */
220 if (lan_port_ifname == NULL || strcmp(lan_port_ifname, ifname) == 0) {
221 eval("emf", ((add) ? "add" : "del"), "rtport", lan_ifname, ifname);
226 static void start_emf(char *lan_ifname)
228 /* Start EMF */
229 eval("emf", "start", lan_ifname);
231 /* Add the static MFDB entries */
232 emf_mfdb_update(lan_ifname, NULL, 1);
234 /* Add the UFFP entries */
235 emf_uffp_update(lan_ifname, NULL, 1);
237 /* Add the RTPORT entries */
238 emf_rtport_update(lan_ifname, NULL, 1);
241 static void stop_emf(char *lan_ifname)
243 eval("emf", "stop", lan_ifname);
244 eval("igs", "del", "bridge", lan_ifname);
245 eval("emf", "del", "bridge", lan_ifname);
247 #endif
249 // -----------------------------------------------------------------------------
251 /* Set initial QoS mode for all et interfaces that are up. */
252 void set_et_qos_mode(int sfd)
254 int i, qos;
255 caddr_t ifrdata;
256 struct ifreq ifr;
257 struct ethtool_drvinfo info;
259 qos = (strcmp(nvram_safe_get("wl_wme"), "off") != 0);
260 for (i = 1; i <= DEV_NUMIFS; i++) {
261 ifr.ifr_ifindex = i;
262 if (ioctl(sfd, SIOCGIFNAME, &ifr)) continue;
263 if (ioctl(sfd, SIOCGIFHWADDR, &ifr)) continue;
264 if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) continue;
265 /* get flags */
266 if (ioctl(sfd, SIOCGIFFLAGS, &ifr)) continue;
267 /* if up (wan may not be up yet at this point) */
268 if (ifr.ifr_flags & IFF_UP) {
269 ifrdata = ifr.ifr_data;
270 memset(&info, 0, sizeof(info));
271 info.cmd = ETHTOOL_GDRVINFO;
272 ifr.ifr_data = (caddr_t)&info;
273 if (ioctl(sfd, SIOCETHTOOL, &ifr) >= 0) {
274 /* Set QoS for et & bcm57xx devices */
275 if (!strncmp(info.driver, "et", 2) ||
276 !strncmp(info.driver, "bcm57", 5)) {
277 ifr.ifr_data = (caddr_t)&qos;
278 ioctl(sfd, SIOCSETCQOS, &ifr);
281 ifr.ifr_data = ifrdata;
286 static void check_afterburner(void)
288 char *p;
290 if (nvram_match("wl_afterburner", "off")) return;
291 if ((p = nvram_get("boardflags")) == NULL) return;
293 if (strcmp(p, "0x0118") == 0) { // G 2.2, 3.0, 3.1
294 p = "0x0318";
296 else if (strcmp(p, "0x0188") == 0) { // G 2.0
297 p = "0x0388";
299 else if (strcmp(p, "0x2558") == 0) { // G 4.0, GL 1.0, 1.1
300 p = "0x2758";
302 else {
303 return;
306 nvram_set("boardflags", p);
308 if (!nvram_match("debug_abrst", "0")) {
309 modprobe_r("wl");
310 modprobe("wl");
314 /* safe?
316 unsigned long bf;
317 char s[64];
319 bf = strtoul(p, &p, 0);
320 if ((*p == 0) && ((bf & BFL_AFTERBURNER) == 0)) {
321 sprintf(s, "0x%04lX", bf | BFL_AFTERBURNER);
322 nvram_set("boardflags", s);
327 static int set_wlmac(int idx, int unit, int subunit, void *param)
329 char *ifname;
331 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
333 // skip disabled wl vifs
334 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
335 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
336 return 0;
338 if (strcmp(nvram_safe_get(wl_nvname("hwaddr", unit, subunit)), "") == 0) {
339 // set_mac(ifname, wl_nvname("macaddr", unit, subunit),
340 set_mac(ifname, wl_nvname("hwaddr", unit, subunit), // AB multiSSID
341 2 + unit + ((subunit > 0) ? ((unit + 1) * 0x10 + subunit) : 0));
342 } else {
343 set_mac(ifname, wl_nvname("hwaddr", unit, subunit), 0);
345 return 1;
348 void start_wl(void)
350 char *lan_ifname, *lan_ifnames, *ifname, *p;
351 int unit, subunit;
352 int is_client = 0;
354 char tmp[32];
355 char br;
357 foreach_wif(1, NULL, set_wlmac);
359 for(br=0 ; br<4 ; br++) {
360 char bridge[2] = "0";
361 if (br!=0)
362 bridge[0]+=br;
363 else
364 strcpy(bridge, "");
366 strcpy(tmp,"lan");
367 strcat(tmp,bridge);
368 strcat(tmp, "_ifname");
369 lan_ifname = nvram_safe_get(tmp);
370 // lan_ifname = nvram_safe_get("lan_ifname");
371 if (strncmp(lan_ifname, "br", 2) == 0) {
372 strcpy(tmp,"lan");
373 strcat(tmp,bridge);
374 strcat(tmp, "_ifnames");
375 // if ((lan_ifnames = strdup(nvram_safe_get("lan_ifnames"))) != NULL) {
376 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
377 p = lan_ifnames;
378 while ((ifname = strsep(&p, " ")) != NULL) {
379 while (*ifname == ' ') ++ifname;
380 if (*ifname == 0) break;
382 unit = -1; subunit = -1;
384 // ignore disabled wl vifs
385 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
386 char nv[40];
387 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
388 if (!nvram_get_int(nv))
389 continue;
390 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
391 continue;
393 // get the instance number of the wl i/f
394 else if (wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit)))
395 continue;
397 is_client |= wl_client(unit, subunit) && nvram_get_int(wl_nvname("radio", unit, 0));
399 #ifdef CONFIG_BCMWL5
400 eval("wlconf", ifname, "start"); /* start wl iface */
401 #endif // CONFIG_BCMWL5
403 free(lan_ifnames);
406 #ifdef CONFIG_BCMWL5
407 else if (strcmp(lan_ifname, "")) {
408 /* specific non-bridged lan iface */
409 eval("wlconf", lan_ifname, "start");
411 #endif // CONFIG_BCMWL5
414 killall("wldist", SIGTERM);
415 eval("wldist");
417 if (is_client)
418 xstart("radio", "join");
421 #ifdef TCONFIG_IPV6
422 void enable_ipv6(int enable)
424 DIR *dir;
425 struct dirent *dirent;
426 char s[256];
428 if ((dir = opendir("/proc/sys/net/ipv6/conf")) != NULL) {
429 while ((dirent = readdir(dir)) != NULL) {
430 sprintf(s, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", dirent->d_name);
431 f_write_string(s, enable ? "0" : "1", 0, 0);
433 closedir(dir);
437 void accept_ra(const char *ifname)
439 char s[256];
441 sprintf(s, "/proc/sys/net/ipv6/conf/%s/accept_ra", ifname);
442 f_write_string(s, "2", 0, 0);
444 sprintf(s, "/proc/sys/net/ipv6/conf/%s/forwarding", ifname);
445 f_write_string(s, "2", 0, 0);
447 #endif
449 void start_lan(void)
451 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
453 char *lan_ifname;
454 struct ifreq ifr;
455 char *lan_ifnames, *ifname, *p;
456 int sfd;
457 uint32 ip;
458 int unit, subunit, sta;
459 int hwaddrset;
460 char eabuf[32];
461 char tmp[32];
462 char tmp2[32];
463 char br;
465 foreach_wif(1, NULL, set_wlmac);
466 check_afterburner();
467 #ifdef TCONFIG_IPV6
468 enable_ipv6(ipv6_enabled());
469 #endif
471 if ((sfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) return;
472 for(br=0 ; br<4 ; br++) {
473 char bridge[2] = "0";
474 if (br!=0)
475 bridge[0]+=br;
476 else
477 strcpy(bridge, "");
479 // lan_ifname = strdup(nvram_safe_get("lan_ifname"));
480 strcpy(tmp,"lan");
481 strcat(tmp,bridge);
482 strcat(tmp, "_ifname");
483 lan_ifname = strdup(nvram_safe_get(tmp));
485 if (strncmp(lan_ifname, "br", 2) == 0) {
486 _dprintf("%s: setting up the bridge %s\n", __FUNCTION__, lan_ifname);
488 eval("brctl", "addbr", lan_ifname);
489 eval("brctl", "setfd", lan_ifname, "0");
490 strcpy(tmp,"lan");
491 strcat(tmp,bridge);
492 strcat(tmp, "_stp");
493 eval("brctl", "stp", lan_ifname, nvram_safe_get(tmp));
495 #ifdef TCONFIG_EMF
496 if (nvram_get_int("emf_enable")) {
497 eval("emf", "add", "bridge", lan_ifname);
498 eval("igs", "add", "bridge", lan_ifname);
500 #endif
502 strcpy(tmp,"lan");
503 strcat(tmp,bridge);
504 strcat(tmp, "_ipaddr");
505 inet_aton(nvram_safe_get(tmp), (struct in_addr *)&ip);
507 hwaddrset = 0;
508 sta = 0;
510 strcpy(tmp,"lan");
511 strcat(tmp,bridge);
512 strcat(tmp, "_ifnames");
513 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
514 p = lan_ifnames;
515 while ((ifname = strsep(&p, " ")) != NULL) {
516 while (*ifname == ' ') ++ifname;
517 if (*ifname == 0) break;
519 unit = -1; subunit = -1;
521 // ignore disabled wl vifs
522 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
523 char nv[64];
525 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
526 if (!nvram_get_int(nv))
527 continue;
528 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
529 continue;
531 else
532 wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit));
534 // bring up interface
535 if (ifconfig(ifname, IFUP|IFF_ALLMULTI, NULL, NULL) != 0) continue;
537 // set the logical bridge address to that of the first interface
538 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
539 if ((!hwaddrset) ||
540 (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0 &&
541 memcmp(ifr.ifr_hwaddr.sa_data, "\0\0\0\0\0\0", ETHER_ADDR_LEN) == 0)) {
542 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
543 if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) {
544 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
545 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
546 _dprintf("%s: setting MAC of %s bridge to %s\n", __FUNCTION__,
547 ifr.ifr_name, ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
548 ioctl(sfd, SIOCSIFHWADDR, &ifr);
549 hwaddrset = 1;
553 if (wlconf(ifname, unit, subunit) == 0) {
554 const char *mode = nvram_safe_get(wl_nvname("mode", unit, subunit));
556 if (strcmp(mode, "wet") == 0) {
557 // Enable host DHCP relay
558 if (nvram_get_int("dhcp_relay")) {
559 wl_iovar_set(ifname, "wet_host_mac", ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
560 wl_iovar_setint(ifname, "wet_host_ipv4", ip);
564 sta |= (strcmp(mode, "sta") == 0);
565 if ((strcmp(mode, "ap") != 0) && (strcmp(mode, "wet") != 0)) continue;
567 eval("brctl", "addif", lan_ifname, ifname);
568 #ifdef TCONFIG_EMF
569 if (nvram_get_int("emf_enable"))
570 eval("emf", "add", "iface", lan_ifname, ifname);
571 #endif
574 if ((nvram_get_int("wan_islan")) && (br==0) &&
575 ((get_wan_proto() == WP_DISABLED) || (sta))) {
576 ifname = nvram_get("wan_ifnameX");
577 if (ifconfig(ifname, IFUP, NULL, NULL) == 0)
578 eval("brctl", "addif", lan_ifname, ifname);
581 free(lan_ifnames);
584 // --- this shouldn't happen ---
585 else if (*lan_ifname) {
586 ifconfig(lan_ifname, IFUP, NULL, NULL);
587 wlconf(lan_ifname, -1, -1);
589 else {
590 close(sfd);
591 free(lan_ifname);
592 return;
595 // Get current LAN hardware address
596 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
597 strcpy(tmp,"lan");
598 strcat(tmp,bridge);
599 strcat(tmp, "_hwaddr");
600 // if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set("lan_hwaddr", ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
601 if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set(tmp, ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
603 // Set initial QoS mode for LAN ports
604 set_et_qos_mode(sfd);
606 close(sfd);
608 // bring up and configure LAN interface
609 strcpy(tmp,"lan");
610 strcat(tmp,bridge);
611 strcat(tmp, "_ipaddr");
612 strcpy(tmp2,"lan");
613 strcat(tmp2,bridge);
614 strcat(tmp2, "_netmask");
615 ifconfig(lan_ifname, IFUP, nvram_safe_get(tmp), nvram_safe_get(tmp2));
617 config_loopback();
618 do_static_routes(1);
620 if(br==0)
621 set_lan_hostname(nvram_safe_get("wan_hostname"));
623 if ((get_wan_proto() == WP_DISABLED) && (br==0)) {
624 char *gateway = nvram_safe_get("lan_gateway") ;
625 if ((*gateway) && (strcmp(gateway, "0.0.0.0") != 0)) {
626 int tries = 5;
627 while ((route_add(lan_ifname, 0, "0.0.0.0", gateway, "0.0.0.0") != 0) && (tries-- > 0)) sleep(1);
628 _dprintf("%s: add gateway=%s tries=%d\n", __FUNCTION__, gateway, tries);
632 #ifdef TCONFIG_IPV6
633 start_ipv6();
634 #endif
636 #ifdef TCONFIG_EMF
637 if (nvram_get_int("emf_enable")) start_emf(lan_ifname);
638 #endif
640 free(lan_ifname);
642 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
645 void stop_lan(void)
647 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
649 char *lan_ifname;
650 char *lan_ifnames, *p, *ifname;
651 char tmp[32];
652 char br;
654 for(br=0 ; br<4 ; br++) {
655 char bridge[2] = "0";
656 if (br!=0)
657 bridge[0]+=br;
658 else
659 strcpy(bridge, "");
661 strcpy(tmp,"lan");
662 strcat(tmp,bridge);
663 strcat(tmp, "_ifname");
664 lan_ifname = nvram_safe_get(tmp);
665 ifconfig(lan_ifname, 0, NULL, NULL);
667 #ifdef TCONFIG_IPV6
668 stop_ipv6();
669 #endif
671 if (strncmp(lan_ifname, "br", 2) == 0) {
672 #ifdef TCONFIG_EMF
673 stop_emf(lan_ifname);
674 #endif
675 strcpy(tmp,"lan");
676 strcat(tmp,bridge);
677 strcat(tmp, "_ifnames");
678 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
679 p = lan_ifnames;
680 while ((ifname = strsep(&p, " ")) != NULL) {
681 while (*ifname == ' ') ++ifname;
682 if (*ifname == 0) break;
683 eval("wlconf", ifname, "down");
684 ifconfig(ifname, 0, NULL, NULL);
685 eval("brctl", "delif", lan_ifname, ifname);
687 free(lan_ifnames);
689 eval("brctl", "delbr", lan_ifname);
691 else if (*lan_ifname) {
692 eval("wlconf", lan_ifname, "down");
695 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
698 static int is_sta(int idx, int unit, int subunit, void *param)
700 return (nvram_match(wl_nvname("mode", unit, subunit), "sta") && (nvram_match(wl_nvname("bss_enabled", unit, subunit), "1")));
703 void do_static_routes(int add)
705 char *buf;
706 char *p, *q;
707 char *dest, *mask, *gateway, *metric, *ifname;
708 int r;
710 if ((buf = strdup(nvram_safe_get(add ? "routes_static" : "routes_static_saved"))) == NULL) return;
711 if (add) nvram_set("routes_static_saved", buf);
712 else nvram_unset("routes_static_saved");
713 p = buf;
714 while ((q = strsep(&p, ">")) != NULL) {
715 if (vstrsep(q, "<", &dest, &gateway, &mask, &metric, &ifname) != 5) continue;
716 #ifdef TCONFIG_VLAN
717 ifname = nvram_safe_get(((strcmp(ifname,"LAN")==0) ? "lan_ifname" :
718 ((strcmp(ifname,"LAN1")==0) ? "lan1_ifname" :
719 ((strcmp(ifname,"LAN2")==0) ? "lan2_ifname" :
720 ((strcmp(ifname,"LAN3")==0) ? "lan3_ifname" :
721 ((*ifname == 'W') ? "wan_iface" : "wan_ifname"))))));
722 #else
723 ifname = nvram_safe_get((*ifname == 'L') ? "lan_ifname" :
724 ((*ifname == 'W') ? "wan_iface" : "wan_ifname"));
725 #endif
726 if (add) {
727 for (r = 3; r >= 0; --r) {
728 if (route_add(ifname, atoi(metric), dest, gateway, mask) == 0) break;
729 sleep(1);
732 else {
733 route_del(ifname, atoi(metric), dest, gateway, mask);
736 free(buf);
738 char *modem_ipaddr;
739 if ( (nvram_match("wan_proto", "pppoe") || nvram_match("wan_proto", "dhcp") || nvram_match("wan_proto", "static") )
740 && (modem_ipaddr = nvram_safe_get("modem_ipaddr")) && *modem_ipaddr && !nvram_match("modem_ipaddr","0.0.0.0")
741 && (!foreach_wif(1, NULL, is_sta)) ) {
742 char ip[16];
743 char *end = rindex(modem_ipaddr,'.')+1;
744 unsigned char c = atoi(end);
745 char *iface = nvram_safe_get("wan_ifname");
747 sprintf(ip, "%.*s%hhu", end-modem_ipaddr, modem_ipaddr, (unsigned char)(c^1^((c&2)^((c&1)<<1))) );
748 eval("ip", "addr", add ?"add":"del", ip, "peer", modem_ipaddr, "dev", iface);
754 void hotplug_net(void)
756 char *interface, *action;
757 char *lan_ifname;
759 if (((interface = getenv("INTERFACE")) == NULL) || ((action = getenv("ACTION")) == NULL)) return;
761 _dprintf("hotplug net INTERFACE=%s ACTION=%s\n", interface, action);
763 if ((strncmp(interface, "wds", 3) == 0) &&
764 (strcmp(action, "register") == 0 || strcmp(action, "add") == 0)) {
765 ifconfig(interface, IFUP, NULL, NULL);
766 lan_ifname = nvram_safe_get("lan_ifname");
767 #ifdef TCONFIG_EMF
768 if (nvram_get_int("emf_enable")) {
769 eval("emf", "add", "iface", lan_ifname, interface);
770 emf_mfdb_update(lan_ifname, interface, 1);
771 emf_uffp_update(lan_ifname, interface, 1);
772 emf_rtport_update(lan_ifname, interface, 1);
774 #endif
775 if (strncmp(lan_ifname, "br", 2) == 0) {
776 eval("brctl", "addif", lan_ifname, interface);
777 notify_nas(interface);
783 static int is_same_addr(struct ether_addr *addr1, struct ether_addr *addr2)
785 int i;
786 for (i = 0; i < 6; i++) {
787 if (addr1->octet[i] != addr2->octet[i])
788 return 0;
790 return 1;
793 #define WL_MAX_ASSOC 128
794 static int check_wl_client(char *ifname, int unit, int subunit)
796 struct ether_addr bssid;
797 wl_bss_info_t *bi;
798 char buf[WLC_IOCTL_MAXLEN];
799 struct maclist *mlist;
800 int mlsize, i;
801 int associated, authorized;
803 *(uint32 *)buf = WLC_IOCTL_MAXLEN;
804 if (wl_ioctl(ifname, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN) < 0 ||
805 wl_ioctl(ifname, WLC_GET_BSS_INFO, buf, WLC_IOCTL_MAXLEN) < 0)
806 return 0;
808 bi = (wl_bss_info_t *)(buf + 4);
809 if ((bi->SSID_len == 0) ||
810 (bi->BSSID.octet[0] + bi->BSSID.octet[1] + bi->BSSID.octet[2] +
811 bi->BSSID.octet[3] + bi->BSSID.octet[4] + bi->BSSID.octet[5] == 0))
812 return 0;
814 associated = 0;
815 authorized = strstr(nvram_safe_get(wl_nvname("akm", unit, subunit)), "psk") == 0;
817 mlsize = sizeof(struct maclist) + (WL_MAX_ASSOC * sizeof(struct ether_addr));
818 if ((mlist = malloc(mlsize)) != NULL) {
819 mlist->count = WL_MAX_ASSOC;
820 if (wl_ioctl(ifname, WLC_GET_ASSOCLIST, mlist, mlsize) == 0) {
821 for (i = 0; i < mlist->count; ++i) {
822 if (is_same_addr(&mlist->ea[i], &bi->BSSID)) {
823 associated = 1;
824 break;
829 if (associated && !authorized) {
830 memset(mlist, 0, mlsize);
831 mlist->count = WL_MAX_ASSOC;
832 strcpy((char*)mlist, "autho_sta_list");
833 if (wl_ioctl(ifname, WLC_GET_VAR, mlist, mlsize) == 0) {
834 for (i = 0; i < mlist->count; ++i) {
835 if (is_same_addr(&mlist->ea[i], &bi->BSSID)) {
836 authorized = 1;
837 break;
842 free(mlist);
845 return (associated && authorized);
848 #define STACHECK_CONNECT 30
849 #define STACHECK_DISCONNECT 5
851 static int radio_join(int idx, int unit, int subunit, void *param)
853 int i;
854 char s[32], f[64];
855 char *ifname;
857 int *unit_filter = param;
858 if (*unit_filter >= 0 && *unit_filter != unit) return 0;
860 if (!nvram_get_int(wl_nvname("radio", unit, 0)) || !wl_client(unit, subunit)) return 0;
862 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
864 // skip disabled wl vifs
865 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
866 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
867 return 0;
869 sprintf(f, "/var/run/radio.%d.%d.pid", unit, subunit < 0 ? 0 : subunit);
870 if (f_read_string(f, s, sizeof(s)) > 0) {
871 if ((i = atoi(s)) > 1) {
872 kill(i, SIGTERM);
873 sleep(1);
877 if (fork() == 0) {
878 sprintf(s, "%d", getpid());
879 f_write(f, s, sizeof(s), 0, 0644);
881 int stacheck_connect = nvram_get_int("sta_chkint");
882 if (stacheck_connect <= 0)
883 stacheck_connect = STACHECK_CONNECT;
884 int stacheck;
886 while (get_radio(unit) && wl_client(unit, subunit)) {
888 if (check_wl_client(ifname, unit, subunit)) {
889 stacheck = stacheck_connect;
891 else {
892 eval("wl", "-i", ifname, "disassoc");
893 #ifdef CONFIG_BCMWL5
894 char *amode, *sec = nvram_safe_get(wl_nvname("akm", unit, subunit));
896 if (strstr(sec, "psk2")) amode = "wpa2psk";
897 else if (strstr(sec, "psk")) amode = "wpapsk";
898 else if (strstr(sec, "wpa2")) amode = "wpa2";
899 else if (strstr(sec, "wpa")) amode = "wpa";
900 else if (nvram_get_int(wl_nvname("auth", unit, subunit))) amode = "shared";
901 else amode = "open";
903 eval("wl", "-i", ifname, "join", nvram_safe_get(wl_nvname("ssid", unit, subunit)),
904 "imode", "bss", "amode", amode);
905 #else
906 eval("wl", "-i", ifname, "join", nvram_safe_get(wl_nvname("ssid", unit, subunit)));
907 #endif
908 stacheck = STACHECK_DISCONNECT;
910 sleep(stacheck);
912 unlink(f);
915 return 1;
918 enum {
919 RADIO_OFF = 0,
920 RADIO_ON = 1,
921 RADIO_TOGGLE = 2
924 static int radio_toggle(int idx, int unit, int subunit, void *param)
926 if (!nvram_get_int(wl_nvname("radio", unit, 0))) return 0;
928 int *op = param;
930 if (*op == RADIO_TOGGLE) {
931 *op = get_radio(unit) ? RADIO_OFF : RADIO_ON;
934 set_radio(*op, unit);
935 return *op;
938 int radio_main(int argc, char *argv[])
940 int op = RADIO_OFF;
941 int unit;
943 if (argc < 2) {
944 HELP:
945 usage_exit(argv[0], "on|off|toggle|join [N]\n");
947 unit = (argc == 3) ? atoi(argv[2]) : -1;
949 if (strcmp(argv[1], "toggle") == 0)
950 op = RADIO_TOGGLE;
951 else if (strcmp(argv[1], "off") == 0)
952 op = RADIO_OFF;
953 else if (strcmp(argv[1], "on") == 0)
954 op = RADIO_ON;
955 else if (strcmp(argv[1], "join") == 0)
956 goto JOIN;
957 else
958 goto HELP;
960 if (unit >= 0)
961 op = radio_toggle(0, unit, 0, &op);
962 else
963 op = foreach_wif(0, &op, radio_toggle);
965 if (!op) {
966 led(LED_DIAG, 0);
967 return 0;
969 JOIN:
970 foreach_wif(1, &unit, radio_join);
971 return 0;
975 int wdist_main(int argc, char *argv[])
977 int n;
978 rw_reg_t r;
979 int v;
981 if (argc != 2) {
982 r.byteoff = 0x684;
983 r.size = 2;
984 if (wl_ioctl(nvram_safe_get("wl_ifname"), 101, &r, sizeof(r)) == 0) {
985 v = r.val - 510;
986 if (v <= 9) v = 0;
987 else v = (v - (9 + 1)) * 150;
988 printf("Current: %d-%dm (0x%02x)\n\n", v + (v ? 1 : 0), v + 150, r.val);
990 usage_exit(argv[0], "<meters>");
992 if ((n = atoi(argv[1])) <= 0) setup_wldistance();
993 else set_wldistance(n);
994 return 0;
998 static int get_wldist(int idx, int unit, int subunit, void *param)
1000 int n;
1002 char *p = nvram_safe_get(wl_nvname("distance", unit, 0));
1003 if ((*p == 0) || ((n = atoi(p)) < 0)) return 0;
1005 return (9 + (n / 150) + ((n % 150) ? 1 : 0));
1008 static int wldist(int idx, int unit, int subunit, void *param)
1010 rw_reg_t r;
1011 uint32 s;
1012 char *p;
1013 int n;
1015 n = get_wldist(idx, unit, subunit, param);
1016 if (n > 0) {
1017 s = 0x10 | (n << 16);
1018 p = nvram_safe_get(wl_nvname("ifname", unit, 0));
1019 wl_ioctl(p, 197, &s, sizeof(s));
1021 r.byteoff = 0x684;
1022 r.val = n + 510;
1023 r.size = 2;
1024 wl_ioctl(p, 102, &r, sizeof(r));
1026 return 0;
1029 // ref: wificonf.c
1030 int wldist_main(int argc, char *argv[])
1032 if (fork() == 0) {
1033 if (foreach_wif(0, NULL, get_wldist) == 0) return 0;
1035 while (1) {
1036 foreach_wif(0, NULL, wldist);
1037 sleep(2);
1041 return 0;