EXPERIMENTAL VLAN/VID mapping GUI
[tomato.git] / release / src / router / rc / network.c
blob49eb96f14d5691b789a3a2265d7ff2bb9b3af3ec
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 #define sin_addr(s) (((struct sockaddr_in *)(s))->sin_addr)
75 static void set_lan_hostname(const char *wan_hostname)
77 const char *s;
78 FILE *f;
80 nvram_set("lan_hostname", wan_hostname);
81 if ((wan_hostname == NULL) || (*wan_hostname == 0)) {
82 /* derive from et0 mac address */
83 s = nvram_get("et0macaddr");
84 if (s && strlen(s) >= 17) {
85 char hostname[16];
86 sprintf(hostname, "RT-%c%c%c%c%c%c%c%c%c%c%c%c",
87 s[0], s[1], s[3], s[4], s[6], s[7],
88 s[9], s[10], s[12], s[13], s[15], s[16]);
90 if ((f = fopen("/proc/sys/kernel/hostname", "w"))) {
91 fputs(hostname, f);
92 fclose(f);
94 nvram_set("lan_hostname", hostname);
98 if ((f = fopen("/etc/hosts", "w"))) {
99 fprintf(f, "127.0.0.1 localhost\n");
100 if ((s = nvram_get("lan_ipaddr")) && (*s))
101 fprintf(f, "%s %s %s-lan\n", s, nvram_safe_get("lan_hostname"), nvram_safe_get("lan_hostname"));
102 #ifdef TCONFIG_VLAN
103 if ((s = nvram_get("lan1_ipaddr")) && (*s) && (strcmp(s,"") != 0))
104 fprintf(f, "%s %s-lan1\n", s, nvram_safe_get("lan_hostname"));
105 if ((s = nvram_get("lan2_ipaddr")) && (*s) && (strcmp(s,"") != 0))
106 fprintf(f, "%s %s-lan2\n", s, nvram_safe_get("lan_hostname"));
107 if ((s = nvram_get("lan3_ipaddr")) && (*s) && (strcmp(s,"") != 0))
108 fprintf(f, "%s %s-lan3\n", s, nvram_safe_get("lan_hostname"));
109 #endif
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("interfmode", 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 if (!strncmp(info.driver, "et", 2) ||
278 !strncmp(info.driver, "bcm57", 5)) {
279 ifr.ifr_data = (caddr_t)&qos;
280 ioctl(sfd, SIOCSETCQOS, &ifr);
283 ifr.ifr_data = ifrdata;
288 static void check_afterburner(void)
290 char *p;
292 if (nvram_match("wl_afterburner", "off")) return;
293 if ((p = nvram_get("boardflags")) == NULL) return;
295 if (strcmp(p, "0x0118") == 0) { // G 2.2, 3.0, 3.1
296 p = "0x0318";
298 else if (strcmp(p, "0x0188") == 0) { // G 2.0
299 p = "0x0388";
301 else if (strcmp(p, "0x2558") == 0) { // G 4.0, GL 1.0, 1.1
302 p = "0x2758";
304 else {
305 return;
308 nvram_set("boardflags", p);
310 if (!nvram_match("debug_abrst", "0")) {
311 modprobe_r("wl");
312 modprobe("wl");
316 /* safe?
318 unsigned long bf;
319 char s[64];
321 bf = strtoul(p, &p, 0);
322 if ((*p == 0) && ((bf & BFL_AFTERBURNER) == 0)) {
323 sprintf(s, "0x%04lX", bf | BFL_AFTERBURNER);
324 nvram_set("boardflags", s);
329 void start_wl(void)
331 char *lan_ifname, *lan_ifnames, *ifname, *p;
332 int unit, subunit;
333 int is_client = 0;
335 char tmp[32];
336 char br;
338 for(br=0 ; br<4 ; br++) {
339 char bridge[2] = "0";
340 if (br!=0)
341 bridge[0]+=br;
342 else
343 strcpy(bridge, "");
345 strcpy(tmp,"lan");
346 strcat(tmp,bridge);
347 strcat(tmp, "_ifname");
348 lan_ifname = nvram_safe_get(tmp);
349 // lan_ifname = nvram_safe_get("lan_ifname");
350 if (strncmp(lan_ifname, "br", 2) == 0) {
351 strcpy(tmp,"lan");
352 strcat(tmp,bridge);
353 strcat(tmp, "_ifnames");
354 // if ((lan_ifnames = strdup(nvram_safe_get("lan_ifnames"))) != NULL) {
355 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
356 p = lan_ifnames;
357 while ((ifname = strsep(&p, " ")) != NULL) {
358 while (*ifname == ' ') ++ifname;
359 if (*ifname == 0) break;
361 unit = -1; subunit = -1;
363 // ignore disabled wl vifs
364 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
365 char nv[40];
366 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
367 if (!nvram_get_int(nv))
368 continue;
369 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
370 continue;
372 // get the instance number of the wl i/f
373 else if (wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit)))
374 continue;
376 is_client |= wl_client(unit, subunit) && nvram_get_int(wl_nvname("radio", unit, 0));
378 #ifdef CONFIG_BCMWL5
379 eval("wlconf", ifname, "start"); /* start wl iface */
380 #endif // CONFIG_BCMWL5
382 free(lan_ifnames);
385 #ifdef CONFIG_BCMWL5
386 else if (strcmp(lan_ifname, "")) {
387 /* specific non-bridged lan iface */
388 eval("wlconf", lan_ifname, "start");
390 #endif // CONFIG_BCMWL5
393 killall("wldist", SIGTERM);
394 eval("wldist");
396 if (is_client)
397 xstart("radio", "join");
400 static int set_wlmac(int idx, int unit, int subunit, void *param)
402 char *ifname;
404 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
406 // skip disabled wl vifs
407 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
408 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
409 return 0;
411 set_mac(ifname, wl_nvname("macaddr", unit, subunit),
412 2 + unit + ((subunit > 0) ? ((unit + 1) * 0x10 + subunit) : 0));
414 return 1;
417 #ifdef TCONFIG_IPV6
418 void enable_ipv6(int enable)
420 DIR *dir;
421 struct dirent *dirent;
422 char s[256];
424 if ((dir = opendir("/proc/sys/net/ipv6/conf")) != NULL) {
425 while ((dirent = readdir(dir)) != NULL) {
426 sprintf(s, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", dirent->d_name);
427 f_write_string(s, enable ? "0" : "1", 0, 0);
429 closedir(dir);
433 void accept_ra(const char *ifname)
435 char s[256];
437 sprintf(s, "/proc/sys/net/ipv6/conf/%s/accept_ra", ifname);
438 f_write_string(s, "2", 0, 0);
440 sprintf(s, "/proc/sys/net/ipv6/conf/%s/forwarding", ifname);
441 f_write_string(s, "2", 0, 0);
443 #endif
445 void start_lan(void)
447 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
449 char *lan_ifname;
450 struct ifreq ifr;
451 char *lan_ifnames, *ifname, *p;
452 int sfd;
453 uint32 ip;
454 int unit, subunit, sta;
455 int hwaddrset;
456 char eabuf[32];
457 char tmp[32];
458 char tmp2[32];
459 char br;
460 int vlan0tag;
461 int vid;
462 int vid_map;
463 char *iftmp;
464 char nv[64];
466 foreach_wif(1, NULL, set_wlmac);
467 check_afterburner();
468 #ifdef TCONFIG_IPV6
469 enable_ipv6(ipv6_enabled());
470 #endif
471 vlan0tag = nvram_get_int("vlan0tag");
473 if ((sfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) return;
474 for(br=0 ; br<4 ; br++) {
475 char bridge[2] = "0";
476 if (br!=0)
477 bridge[0]+=br;
478 else
479 strcpy(bridge, "");
481 // lan_ifname = strdup(nvram_safe_get("lan_ifname"));
482 strcpy(tmp,"lan");
483 strcat(tmp,bridge);
484 strcat(tmp, "_ifname");
485 lan_ifname = strdup(nvram_safe_get(tmp));
487 if (strncmp(lan_ifname, "br", 2) == 0) {
488 _dprintf("%s: setting up the bridge %s\n", __FUNCTION__, lan_ifname);
490 eval("brctl", "addbr", lan_ifname);
491 eval("brctl", "setfd", lan_ifname, "0");
492 strcpy(tmp,"lan");
493 strcat(tmp,bridge);
494 strcat(tmp, "_stp");
495 eval("brctl", "stp", lan_ifname, nvram_safe_get(tmp));
497 #ifdef TCONFIG_EMF
498 if (nvram_get_int("emf_enable")) {
499 eval("emf", "add", "bridge", lan_ifname);
500 eval("igs", "add", "bridge", lan_ifname);
502 #endif
504 strcpy(tmp,"lan");
505 strcat(tmp,bridge);
506 strcat(tmp, "_ipaddr");
507 inet_aton(nvram_safe_get(tmp), (struct in_addr *)&ip);
509 hwaddrset = 0;
510 sta = 0;
512 strcpy(tmp,"lan");
513 strcat(tmp,bridge);
514 strcat(tmp, "_ifnames");
515 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
516 p = lan_ifnames;
517 while ((iftmp = strsep(&p, " ")) != NULL) {
518 while (*iftmp == ' ') ++iftmp;
519 if (*iftmp == 0) break;
520 ifname = iftmp;
522 unit = -1; subunit = -1;
524 // ignore disabled wl vifs
525 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.')) {
527 snprintf(nv, sizeof(nv) - 1, "%s_bss_enabled", ifname);
528 if (!nvram_get_int(nv))
529 continue;
530 if (get_ifname_unit(ifname, &unit, &subunit) < 0)
531 continue;
533 else
534 wl_ioctl(ifname, WLC_GET_INSTANCE, &unit, sizeof(unit));
536 // vlan ID mapping
537 if (strncmp(ifname, "vlan", 4) == 0) {
538 if (sscanf(ifname, "vlan%d", &vid) == 1) {
539 snprintf(tmp, sizeof(tmp), "vlan%dvid", vid);
540 vid_map = nvram_get_int(tmp);
541 if ((vid_map < 1) || (vid_map > 4094)) vid_map = vlan0tag | vid;
542 snprintf(tmp, sizeof(tmp), "vlan%d", vid_map);
543 ifname = tmp;
547 // bring up interface
548 if (ifconfig(ifname, IFUP|IFF_ALLMULTI, NULL, NULL) != 0) continue;
550 // set the logical bridge address to that of the first interface
551 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
552 if ((!hwaddrset) ||
553 (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0 &&
554 memcmp(ifr.ifr_hwaddr.sa_data, "\0\0\0\0\0\0", ETHER_ADDR_LEN) == 0)) {
555 strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
556 if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) {
557 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
558 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
559 _dprintf("%s: setting MAC of %s bridge to %s\n", __FUNCTION__,
560 ifr.ifr_name, ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
561 ioctl(sfd, SIOCSIFHWADDR, &ifr);
562 hwaddrset = 1;
566 if (wlconf(ifname, unit, subunit) == 0) {
567 const char *mode = nvram_safe_get(wl_nvname("mode", unit, subunit));
569 if (strcmp(mode, "wet") == 0) {
570 // Enable host DHCP relay
571 if (nvram_get_int("dhcp_relay")) {
572 wl_iovar_set(ifname, "wet_host_mac", ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
573 wl_iovar_setint(ifname, "wet_host_ipv4", ip);
577 sta |= (strcmp(mode, "sta") == 0);
578 if ((strcmp(mode, "ap") != 0) && (strcmp(mode, "wet") != 0)) continue;
580 eval("brctl", "addif", lan_ifname, ifname);
581 #ifdef TCONFIG_EMF
582 if (nvram_get_int("emf_enable"))
583 eval("emf", "add", "iface", lan_ifname, ifname);
584 #endif
587 if ((nvram_get_int("wan_islan")) && (br==0) &&
588 ((get_wan_proto() == WP_DISABLED) || (sta))) {
589 ifname = nvram_get("wan_ifnameX");
590 if (ifconfig(ifname, IFUP, NULL, NULL) == 0)
591 eval("brctl", "addif", lan_ifname, ifname);
594 free(lan_ifnames);
597 // --- this shouldn't happen ---
598 else if (*lan_ifname) {
599 ifconfig(lan_ifname, IFUP, NULL, NULL);
600 wlconf(lan_ifname, -1, -1);
602 else {
603 close(sfd);
604 free(lan_ifname);
605 return;
608 // Get current LAN hardware address
609 strlcpy(ifr.ifr_name, lan_ifname, IFNAMSIZ);
610 strcpy(tmp,"lan");
611 strcat(tmp,bridge);
612 strcat(tmp, "_hwaddr");
613 // if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set("lan_hwaddr", ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
614 if (ioctl(sfd, SIOCGIFHWADDR, &ifr) == 0) nvram_set(tmp, ether_etoa(ifr.ifr_hwaddr.sa_data, eabuf));
616 // Set initial QoS mode for LAN ports
617 set_et_qos_mode(sfd);
619 close(sfd);
621 // bring up and configure LAN interface
622 strcpy(tmp,"lan");
623 strcat(tmp,bridge);
624 strcat(tmp, "_ipaddr");
625 strcpy(tmp2,"lan");
626 strcat(tmp2,bridge);
627 strcat(tmp2, "_netmask");
628 ifconfig(lan_ifname, IFUP, nvram_safe_get(tmp), nvram_safe_get(tmp2));
630 config_loopback();
631 do_static_routes(1);
633 if(br==0)
634 set_lan_hostname(nvram_safe_get("wan_hostname"));
636 if ((get_wan_proto() == WP_DISABLED) && (br==0)) {
637 char *gateway = nvram_safe_get("lan_gateway") ;
638 if ((*gateway) && (strcmp(gateway, "0.0.0.0") != 0)) {
639 int tries = 5;
640 while ((route_add(lan_ifname, 0, "0.0.0.0", gateway, "0.0.0.0") != 0) && (tries-- > 0)) sleep(1);
641 _dprintf("%s: add gateway=%s tries=%d\n", __FUNCTION__, gateway, tries);
645 #ifdef TCONFIG_IPV6
646 start_ipv6();
647 #endif
649 #ifdef TCONFIG_EMF
650 if (nvram_get_int("emf_enable")) start_emf(lan_ifname);
651 #endif
653 free(lan_ifname);
655 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
658 void stop_lan(void)
660 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
662 char *lan_ifname;
663 char *lan_ifnames, *p, *ifname;
664 char tmp[32];
665 char br;
666 int vlan0tag, vid, vid_map;
667 char *iftmp;
669 vlan0tag = nvram_get_int("vlan0tag");
671 for(br=0 ; br<4 ; br++) {
672 char bridge[2] = "0";
673 if (br!=0)
674 bridge[0]+=br;
675 else
676 strcpy(bridge, "");
678 strcpy(tmp,"lan");
679 strcat(tmp,bridge);
680 strcat(tmp, "_ifname");
681 lan_ifname = nvram_safe_get(tmp);
682 ifconfig(lan_ifname, 0, NULL, NULL);
684 #ifdef TCONFIG_IPV6
685 stop_ipv6();
686 #endif
688 if (strncmp(lan_ifname, "br", 2) == 0) {
689 #ifdef TCONFIG_EMF
690 stop_emf(lan_ifname);
691 #endif
692 strcpy(tmp,"lan");
693 strcat(tmp,bridge);
694 strcat(tmp, "_ifnames");
695 if ((lan_ifnames = strdup(nvram_safe_get(tmp))) != NULL) {
696 p = lan_ifnames;
697 while ((iftmp = strsep(&p, " ")) != NULL) {
698 while (*iftmp == ' ') ++iftmp;
699 if (*iftmp == 0) break;
700 ifname = iftmp;
701 // vlan ID mapping
702 if (strncmp(ifname, "vlan", 4) == 0) {
703 if (sscanf(ifname, "vlan%d", &vid) == 1) {
704 snprintf(tmp, sizeof(tmp), "vlan%dvid", vid);
705 vid_map = nvram_get_int(tmp);
706 if ((vid_map < 1) || (vid_map > 4094)) vid_map = vlan0tag | vid;
707 snprintf(tmp, sizeof(tmp), "vlan%d", vid_map);
708 ifname = tmp;
711 eval("wlconf", ifname, "down");
712 ifconfig(ifname, 0, NULL, NULL);
713 eval("brctl", "delif", lan_ifname, ifname);
715 free(lan_ifnames);
717 eval("brctl", "delbr", lan_ifname);
719 else if (*lan_ifname) {
720 eval("wlconf", lan_ifname, "down");
723 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
727 void do_static_routes(int add)
729 char *buf;
730 char *p, *q;
731 char *dest, *mask, *gateway, *metric, *ifname;
732 int r;
734 if ((buf = strdup(nvram_safe_get(add ? "routes_static" : "routes_static_saved"))) == NULL) return;
735 if (add) nvram_set("routes_static_saved", buf);
736 else nvram_unset("routes_static_saved");
737 p = buf;
738 while ((q = strsep(&p, ">")) != NULL) {
739 if (vstrsep(q, "<", &dest, &gateway, &mask, &metric, &ifname) != 5) continue;
740 #ifdef TCONFIG_VLAN
741 ifname = nvram_safe_get(((strcmp(ifname,"LAN")==0) ? "lan_ifname" :
742 ((strcmp(ifname,"LAN1")==0) ? "lan1_ifname" :
743 ((strcmp(ifname,"LAN2")==0) ? "lan2_ifname" :
744 ((strcmp(ifname,"LAN3")==0) ? "lan3_ifname" :
745 ((*ifname == 'W') ? "wan_iface" : "wan_ifname"))))));
746 #else
747 ifname = nvram_safe_get((*ifname == 'L') ? "lan_ifname" :
748 ((*ifname == 'W') ? "wan_iface" : "wan_ifname"));
749 #endif
750 if (add) {
751 for (r = 3; r >= 0; --r) {
752 if (route_add(ifname, atoi(metric) + 1, dest, gateway, mask) == 0) break;
753 sleep(1);
756 else {
757 route_del(ifname, atoi(metric) + 1, dest, gateway, mask);
760 free(buf);
763 void hotplug_net(void)
765 char *interface, *action;
766 char *lan_ifname;
768 if (((interface = getenv("INTERFACE")) == NULL) || ((action = getenv("ACTION")) == NULL)) return;
770 _dprintf("hotplug net INTERFACE=%s ACTION=%s\n", interface, action);
772 if ((strncmp(interface, "wds", 3) == 0) &&
773 (strcmp(action, "register") == 0 || strcmp(action, "add") == 0)) {
774 ifconfig(interface, IFUP, NULL, NULL);
775 lan_ifname = nvram_safe_get("lan_ifname");
776 #ifdef TCONFIG_EMF
777 if (nvram_get_int("emf_enable")) {
778 eval("emf", "add", "iface", lan_ifname, interface);
779 emf_mfdb_update(lan_ifname, interface, 1);
780 emf_uffp_update(lan_ifname, interface, 1);
781 emf_rtport_update(lan_ifname, interface, 1);
783 #endif
784 if (strncmp(lan_ifname, "br", 2) == 0) {
785 eval("brctl", "addif", lan_ifname, interface);
786 notify_nas(interface);
792 static int is_same_addr(struct ether_addr *addr1, struct ether_addr *addr2)
794 int i;
795 for (i = 0; i < 6; i++) {
796 if (addr1->octet[i] != addr2->octet[i])
797 return 0;
799 return 1;
802 #define WL_MAX_ASSOC 128
803 static int check_wl_client(char *ifname, int unit, int subunit)
805 struct ether_addr bssid;
806 wl_bss_info_t *bi;
807 char buf[WLC_IOCTL_MAXLEN];
808 struct maclist *mlist;
809 int mlsize, i;
810 int associated, authorized;
812 *(uint32 *)buf = WLC_IOCTL_MAXLEN;
813 if (wl_ioctl(ifname, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN) < 0 ||
814 wl_ioctl(ifname, WLC_GET_BSS_INFO, buf, WLC_IOCTL_MAXLEN) < 0)
815 return 0;
817 bi = (wl_bss_info_t *)(buf + 4);
818 if ((bi->SSID_len == 0) ||
819 (bi->BSSID.octet[0] + bi->BSSID.octet[1] + bi->BSSID.octet[2] +
820 bi->BSSID.octet[3] + bi->BSSID.octet[4] + bi->BSSID.octet[5] == 0))
821 return 0;
823 associated = 0;
824 authorized = strstr(nvram_safe_get(wl_nvname("akm", unit, subunit)), "psk") == 0;
826 mlsize = sizeof(struct maclist) + (WL_MAX_ASSOC * sizeof(struct ether_addr));
827 if ((mlist = malloc(mlsize)) != NULL) {
828 mlist->count = WL_MAX_ASSOC;
829 if (wl_ioctl(ifname, WLC_GET_ASSOCLIST, mlist, mlsize) == 0) {
830 for (i = 0; i < mlist->count; ++i) {
831 if (is_same_addr(&mlist->ea[i], &bi->BSSID)) {
832 associated = 1;
833 break;
838 if (associated && !authorized) {
839 memset(mlist, 0, mlsize);
840 mlist->count = WL_MAX_ASSOC;
841 strcpy((char*)mlist, "autho_sta_list");
842 if (wl_ioctl(ifname, WLC_GET_VAR, mlist, mlsize) == 0) {
843 for (i = 0; i < mlist->count; ++i) {
844 if (is_same_addr(&mlist->ea[i], &bi->BSSID)) {
845 authorized = 1;
846 break;
851 free(mlist);
854 return (associated && authorized);
857 #define STACHECK_CONNECT 30
858 #define STACHECK_DISCONNECT 5
860 static int radio_join(int idx, int unit, int subunit, void *param)
862 int i;
863 char s[32], f[64];
864 char *ifname;
866 int *unit_filter = param;
867 if (*unit_filter >= 0 && *unit_filter != unit) return 0;
869 if (!nvram_get_int(wl_nvname("radio", unit, 0)) || !wl_client(unit, subunit)) return 0;
871 ifname = nvram_safe_get(wl_nvname("ifname", unit, subunit));
873 // skip disabled wl vifs
874 if (strncmp(ifname, "wl", 2) == 0 && strchr(ifname, '.') &&
875 !nvram_get_int(wl_nvname("bss_enabled", unit, subunit)))
876 return 0;
878 sprintf(f, "/var/run/radio.%d.%d.pid", unit, subunit < 0 ? 0 : subunit);
879 if (f_read_string(f, s, sizeof(s)) > 0) {
880 if ((i = atoi(s)) > 1) {
881 kill(i, SIGTERM);
882 sleep(1);
886 if (fork() == 0) {
887 sprintf(s, "%d", getpid());
888 f_write(f, s, sizeof(s), 0, 0644);
890 int stacheck_connect = nvram_get_int("sta_chkint");
891 if (stacheck_connect <= 0)
892 stacheck_connect = STACHECK_CONNECT;
893 int stacheck;
895 while (get_radio(unit) && wl_client(unit, subunit)) {
897 if (check_wl_client(ifname, unit, subunit)) {
898 stacheck = stacheck_connect;
900 else {
901 eval("wl", "-i", ifname, "disassoc");
902 #ifdef CONFIG_BCMWL5
903 char *amode, *sec = nvram_safe_get(wl_nvname("akm", unit, subunit));
905 if (strstr(sec, "psk2")) amode = "wpa2psk";
906 else if (strstr(sec, "psk")) amode = "wpapsk";
907 else if (strstr(sec, "wpa2")) amode = "wpa2";
908 else if (strstr(sec, "wpa")) amode = "wpa";
909 else if (nvram_get_int(wl_nvname("auth", unit, subunit))) amode = "shared";
910 else amode = "open";
912 eval("wl", "-i", ifname, "join", nvram_safe_get(wl_nvname("ssid", unit, subunit)),
913 "imode", "bss", "amode", amode);
914 #else
915 eval("wl", "-i", ifname, "join", nvram_safe_get(wl_nvname("ssid", unit, subunit)));
916 #endif
917 stacheck = STACHECK_DISCONNECT;
919 sleep(stacheck);
921 unlink(f);
924 return 1;
927 enum {
928 RADIO_OFF = 0,
929 RADIO_ON = 1,
930 RADIO_TOGGLE = 2
933 static int radio_toggle(int idx, int unit, int subunit, void *param)
935 if (!nvram_get_int(wl_nvname("radio", unit, 0))) return 0;
937 int *op = param;
939 if (*op == RADIO_TOGGLE) {
940 *op = get_radio(unit) ? RADIO_OFF : RADIO_ON;
943 set_radio(*op, unit);
944 return *op;
947 int radio_main(int argc, char *argv[])
949 int op = RADIO_OFF;
950 int unit;
952 if (argc < 2) {
953 HELP:
954 usage_exit(argv[0], "on|off|toggle|join [N]\n");
956 unit = (argc == 3) ? atoi(argv[2]) : -1;
958 if (strcmp(argv[1], "toggle") == 0)
959 op = RADIO_TOGGLE;
960 else if (strcmp(argv[1], "off") == 0)
961 op = RADIO_OFF;
962 else if (strcmp(argv[1], "on") == 0)
963 op = RADIO_ON;
964 else if (strcmp(argv[1], "join") == 0)
965 goto JOIN;
966 else
967 goto HELP;
969 if (unit >= 0)
970 op = radio_toggle(0, unit, 0, &op);
971 else
972 op = foreach_wif(0, &op, radio_toggle);
974 if (!op) {
975 led(LED_DIAG, 0);
976 return 0;
978 JOIN:
979 foreach_wif(1, &unit, radio_join);
980 return 0;
984 int wdist_main(int argc, char *argv[])
986 int n;
987 rw_reg_t r;
988 int v;
990 if (argc != 2) {
991 r.byteoff = 0x684;
992 r.size = 2;
993 if (wl_ioctl(nvram_safe_get("wl_ifname"), 101, &r, sizeof(r)) == 0) {
994 v = r.val - 510;
995 if (v <= 9) v = 0;
996 else v = (v - (9 + 1)) * 150;
997 printf("Current: %d-%dm (0x%02x)\n\n", v + (v ? 1 : 0), v + 150, r.val);
999 usage_exit(argv[0], "<meters>");
1001 if ((n = atoi(argv[1])) <= 0) setup_wldistance();
1002 else set_wldistance(n);
1003 return 0;
1007 static int get_wldist(int idx, int unit, int subunit, void *param)
1009 int n;
1011 char *p = nvram_safe_get(wl_nvname("distance", unit, 0));
1012 if ((*p == 0) || ((n = atoi(p)) < 0)) return 0;
1014 return (9 + (n / 150) + ((n % 150) ? 1 : 0));
1017 static int wldist(int idx, int unit, int subunit, void *param)
1019 rw_reg_t r;
1020 uint32 s;
1021 char *p;
1022 int n;
1024 n = get_wldist(idx, unit, subunit, param);
1025 if (n > 0) {
1026 s = 0x10 | (n << 16);
1027 p = nvram_safe_get(wl_nvname("ifname", unit, 0));
1028 wl_ioctl(p, 197, &s, sizeof(s));
1030 r.byteoff = 0x684;
1031 r.val = n + 510;
1032 r.size = 2;
1033 wl_ioctl(p, 102, &r, sizeof(r));
1035 return 0;
1038 // ref: wificonf.c
1039 int wldist_main(int argc, char *argv[])
1041 if (fork() == 0) {
1042 if (foreach_wif(0, NULL, get_wldist) == 0) return 0;
1044 while (1) {
1045 foreach_wif(0, NULL, wldist);
1046 sleep(2);
1050 return 0;