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
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.
33 Copyright (C) 2005 Felix Fietkau <nbd@vd-s.ath.cx>
38 Modified for Tomato Firmware
39 Portions, Copyright (C) 2006-2009 Jonathan Zarate
46 typedef u_int64_t u64
;
47 typedef u_int32_t u32
;
48 typedef u_int16_t u16
;
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>
59 #include <bcmparams.h>
62 #ifndef WL_BSS_INFO_VERSION
63 #error WL_BSS_INFO_VERSION
65 #if WL_BSS_INFO_VERSION == 108
71 #define IFUP (IFF_UP | IFF_RUNNING | IFF_BROADCAST | IFF_MULTICAST)
72 #define sin_addr(s) (((struct sockaddr_in *)(s))->sin_addr)
74 #ifdef TCONFIG_SAMBASRV
75 //!!TB - hostname is required for Samba to work
76 void set_lan_hostname(const char *wan_hostname
)
81 nvram_set("lan_hostname", wan_hostname
);
82 if ((wan_hostname
== NULL
) || (*wan_hostname
== 0)) {
83 /* derive from et0 mac address */
84 s
= nvram_get("et0macaddr");
85 if (s
&& strlen(s
) >= 17) {
87 sprintf(hostname
, "RT-%c%c%c%c%c%c%c%c%c%c%c%c",
88 s
[0], s
[1], s
[3], s
[4], s
[6], s
[7],
89 s
[9], s
[10], s
[12], s
[13], s
[15], s
[16]);
91 if ((f
= fopen("/proc/sys/kernel/hostname", "w"))) {
95 nvram_set("lan_hostname", hostname
);
99 if ((f
= fopen("/etc/hosts", "w"))) {
100 fprintf(f
, "127.0.0.1 localhost\n");
101 fprintf(f
, "%s %s\n",
102 nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_hostname"));
108 void set_host_domain_name(void)
112 s
= nvram_safe_get("wan_hostname");
113 sethostname(s
, strlen(s
));
115 #ifdef TCONFIG_SAMBASRV
116 //!!TB - hostname is required for Samba to work
120 s
= nvram_get("wan_domain");
121 if ((s
== NULL
) || (*s
== 0)) s
= nvram_safe_get("wan_get_domain");
122 setdomainname(s
, strlen(s
));
125 static int wlconf(char *ifname
)
129 r
= eval("wlconf", ifname
, "up");
131 // set_mac(ifname, "mac_wl", 2);
133 nvram_set("rrules_radio", "-1");
135 eval("wl", "antdiv", nvram_safe_get("wl_antdiv"));
136 eval("wl", "txant", nvram_safe_get("wl_txant"));
137 eval("wl", "txpwr1", "-o", "-m", nvram_get_int("wl_txpwr") ? nvram_safe_get("wl_txpwr") : "-1");
139 killall("wldist", SIGTERM
);
143 if (nvram_match("wl_mode", "wet")) {
144 ifconfig(ifname
, IFUP
|IFF_ALLMULTI
, NULL
, NULL
);
146 if (nvram_match("wl_radio", "1")) {
147 xstart("radio", "join");
155 /* Set initial QoS mode for all et interfaces that are up. */
156 void set_et_qos_mode(int sfd
)
161 struct ethtool_drvinfo info
;
163 qos
= (strcmp(nvram_safe_get("wl_wme"), "off") != 0);
164 for (i
= 1; i
<= DEV_NUMIFS
; i
++) {
166 if (ioctl(sfd
, SIOCGIFNAME
, &ifr
)) continue;
167 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
)) continue;
168 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) continue;
170 if (ioctl(sfd
, SIOCGIFFLAGS
, &ifr
)) continue;
171 /* if up (wan may not be up yet at this point) */
172 if (ifr
.ifr_flags
& IFF_UP
) {
173 ifrdata
= ifr
.ifr_data
;
174 memset(&info
, 0, sizeof(info
));
175 info
.cmd
= ETHTOOL_GDRVINFO
;
176 ifr
.ifr_data
= (caddr_t
)&info
;
177 if (ioctl(sfd
, SIOCETHTOOL
, &ifr
) >= 0) {
178 /* Set QoS for et & bcm57xx devices */
179 if (!strncmp(info
.driver
, "et", 2) ||
180 !strncmp(info
.driver
, "bcm57", 5)) {
181 ifr
.ifr_data
= (caddr_t
)&qos
;
182 ioctl(sfd
, SIOCSETCQOS
, &ifr
);
185 ifr
.ifr_data
= ifrdata
;
190 static void check_afterburner(void)
194 if (nvram_match("wl_afterburner", "off")) return;
195 if ((p
= nvram_get("boardflags")) == NULL
) return;
197 if (strcmp(p
, "0x0118") == 0) { // G 2.2, 3.0, 3.1
200 else if (strcmp(p
, "0x0188") == 0) { // G 2.0
203 else if (strcmp(p
, "0x2558") == 0) { // G 4.0, GL 1.0, 1.1
210 nvram_set("boardflags", p
);
212 if (!nvram_match("debug_abrst", "0")) {
223 bf = strtoul(p, &p, 0);
224 if ((*p == 0) && ((bf & BFL_AFTERBURNER) == 0)) {
225 sprintf(s, "0x%04lX", bf | BFL_AFTERBURNER);
226 nvram_set("boardflags", s);
234 char *lan_ifname
, *lan_ifnames
, *ifname
, *p
;
236 lan_ifname
= nvram_safe_get("lan_ifname");
237 if (strncmp(lan_ifname
, "br", 2) == 0) {
238 if ((lan_ifnames
= strdup(nvram_safe_get("lan_ifnames"))) != NULL
) {
240 while ((ifname
= strsep(&p
, " ")) != NULL
) {
241 while (*ifname
== ' ') ++ifname
;
242 if (*ifname
== 0) break;
244 /* Ignore disabled wl vifs */
245 if (strncmp(ifname
, "wl", 2) == 0) {
247 snprintf(nv
, sizeof(nv
) - 1, "%s_bss_enabled", ifname
);
248 if (!nvram_get_int(nv
))
252 eval("wlconf", ifname
, "start"); /* start wl iface */
257 else if (strcmp(lan_ifname
, "")) {
258 /* specific non-bridged lan iface */
259 eval("wlconf", lan_ifname
, "start");
262 if (wl_client() && nvram_match("wl_radio", "1"))
263 xstart("radio", "join");
265 #endif // CONFIG_BCMWL5
269 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
273 char *lan_ifnames
, *ifname
, *p
;
276 set_mac(nvram_safe_get("wl_ifname"), "mac_wl", 2);
279 if ((sfd
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0) return;
281 lan_ifname
= strdup(nvram_safe_get("lan_ifname"));
282 if (strncmp(lan_ifname
, "br", 2) == 0) {
283 eval("brctl", "addbr", lan_ifname
);
284 eval("brctl", "setfd", lan_ifname
, "0");
285 eval("brctl", "stp", lan_ifname
, nvram_safe_get("lan_stp"));
287 if ((lan_ifnames
= strdup(nvram_safe_get("lan_ifnames"))) != NULL
) {
289 while ((ifname
= strsep(&p
, " ")) != NULL
) {
290 while (*ifname
== ' ') ++ifname
;
291 if (*ifname
== 0) break;
293 // bring up interface
294 if (ifconfig(ifname
, IFUP
, NULL
, NULL
) != 0) continue;
296 // set the logical bridge address to that of the first interface
297 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
298 if ((ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) && (memcmp(ifr
.ifr_hwaddr
.sa_data
, "\0\0\0\0\0\0", ETHER_ADDR_LEN
) == 0)) {
299 strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
300 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) {
301 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
302 ifr
.ifr_hwaddr
.sa_family
= ARPHRD_ETHER
;
303 ioctl(sfd
, SIOCSIFHWADDR
, &ifr
);
307 if (wlconf(ifname
) == 0) {
308 const char *mode
= nvram_get("wl0_mode");
309 if ((mode
) && ((strcmp(mode
, "ap") != 0) && (strcmp(mode
, "wet") != 0))) continue;
311 eval("brctl", "addif", lan_ifname
, ifname
);
314 if ((nvram_get_int("wan_islan")) &&
315 ((get_wan_proto() == WP_DISABLED
) || (nvram_match("wl_mode", "sta")))) {
316 ifname
= nvram_get("wan_ifnameX");
317 if (ifconfig(ifname
, IFUP
, NULL
, NULL
) == 0)
318 eval("brctl", "addif", lan_ifname
, ifname
);
324 // --- this shouldn't happen ---
325 else if (*lan_ifname
) {
326 ifconfig(lan_ifname
, IFUP
, NULL
, NULL
);
336 // Get current LAN hardware address
338 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
339 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) nvram_set("lan_hwaddr", ether_etoa(ifr
.ifr_hwaddr
.sa_data
, eabuf
));
341 // Set initial QoS mode for LAN ports
342 set_et_qos_mode(sfd
);
346 // bring up and configure LAN interface
347 ifconfig(lan_ifname
, IFUP
, nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_netmask"));
352 #ifdef TCONFIG_SAMBASRV
353 //!!TB - hostname is required for Samba to work
354 set_lan_hostname(nvram_safe_get("wan_hostname"));
357 if (nvram_match("wan_proto", "disabled")) {
358 char *gateway
= nvram_safe_get("lan_gateway") ;
359 if ((*gateway
) && (strcmp(gateway
, "0.0.0.0") != 0)) {
361 while ((route_add(lan_ifname
, 0, "0.0.0.0", gateway
, "0.0.0.0") != 0) && (tries
-- > 0)) sleep(1);
362 _dprintf("%s: add gateway=%s tries=%d\n", __FUNCTION__
, gateway
, tries
);
368 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
373 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
376 char *lan_ifnames
, *p
, *ifname
;
378 lan_ifname
= nvram_safe_get("lan_ifname");
379 ifconfig(lan_ifname
, 0, NULL
, NULL
);
381 if (strncmp(lan_ifname
, "br", 2) == 0) {
382 if ((lan_ifnames
= strdup(nvram_safe_get("lan_ifnames"))) != NULL
) {
384 while ((ifname
= strsep(&p
, " ")) != NULL
) {
385 while (*ifname
== ' ') ++ifname
;
386 if (*ifname
== 0) break;
387 eval("wlconf", ifname
, "down");
388 ifconfig(ifname
, 0, NULL
, NULL
);
389 eval("brctl", "delif", lan_ifname
, ifname
);
393 eval("brctl", "delbr", lan_ifname
);
395 else if (*lan_ifname
) {
396 eval("wlconf", lan_ifname
, "down");
399 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
403 void do_static_routes(int add
)
407 char *dest
, *mask
, *gateway
, *metric
, *ifname
;
410 if ((buf
= strdup(nvram_safe_get(add
? "routes_static" : "routes_static_saved"))) == NULL
) return;
411 if (add
) nvram_set("routes_static_saved", buf
);
412 else nvram_unset("routes_static_saved");
414 while ((q
= strsep(&p
, ">")) != NULL
) {
415 if (vstrsep(q
, "<", &dest
, &gateway
, &mask
, &metric
, &ifname
) != 5) continue;
416 ifname
= nvram_safe_get((*ifname
== 'L') ? "lan_ifname" :
417 ((*ifname
== 'W') ? "wan_iface" : "wan_ifname"));
419 for (r
= 3; r
>= 0; --r
) {
420 if (route_add(ifname
, atoi(metric
) + 1, dest
, gateway
, mask
) == 0) break;
425 route_del(ifname
, atoi(metric
) + 1, dest
, gateway
, mask
);
431 void hotplug_net(void)
433 char *interface
, *action
;
436 if (((interface
= getenv("INTERFACE")) == NULL
) || ((action
= getenv("ACTION")) == NULL
)) return;
438 _dprintf("hotplug net INTERFACE=%s ACTION=%s\n", interface
, action
);
440 if ((nvram_match("wds_enable", "1")) && (strncmp(interface
, "wds", 3) == 0) &&
441 (strcmp(action
, "register") == 0 || strcmp(action
, "add") == 0)) {
442 ifconfig(interface
, IFUP
, NULL
, NULL
);
443 lan_ifname
= nvram_safe_get("lan_ifname");
444 if (strncmp(lan_ifname
, "br", 2) == 0) {
445 eval("brctl", "addif", lan_ifname
, interface
);
446 notify_nas(interface
);
452 static int is_same_addr(struct ether_addr
*addr1
, struct ether_addr
*addr2
)
455 for (i
= 0; i
< 6; i
++) {
456 if (addr1
->octet
[i
] != addr2
->octet
[i
])
462 #define WL_MAX_ASSOC 128
463 static int check_wl_client(char *ifname
)
465 struct ether_addr bssid
;
467 char buf
[WLC_IOCTL_MAXLEN
];
468 struct maclist
*mlist
;
470 int associated
, authorized
;
472 *(uint32
*)buf
= WLC_IOCTL_MAXLEN
;
473 if (wl_ioctl(ifname
, WLC_GET_BSSID
, &bssid
, ETHER_ADDR_LEN
) < 0 ||
474 wl_ioctl(ifname
, WLC_GET_BSS_INFO
, buf
, WLC_IOCTL_MAXLEN
) < 0)
477 bi
= (wl_bss_info_t
*)(buf
+ 4);
478 if ((bi
->SSID_len
== 0) ||
479 (bi
->BSSID
.octet
[0] + bi
->BSSID
.octet
[1] + bi
->BSSID
.octet
[2] +
480 bi
->BSSID
.octet
[3] + bi
->BSSID
.octet
[4] + bi
->BSSID
.octet
[5] == 0))
484 authorized
= strstr(nvram_safe_get("wl_akm"), "psk") == 0;
486 mlsize
= sizeof(struct maclist
) + (WL_MAX_ASSOC
* sizeof(struct ether_addr
));
487 if ((mlist
= malloc(mlsize
)) != NULL
) {
488 mlist
->count
= WL_MAX_ASSOC
;
489 if (wl_ioctl(ifname
, WLC_GET_ASSOCLIST
, mlist
, mlsize
) == 0) {
490 for (i
= 0; i
< mlist
->count
; ++i
) {
491 if (is_same_addr(&mlist
->ea
[i
], &bi
->BSSID
)) {
498 if (associated
&& !authorized
) {
499 memset(mlist
, 0, mlsize
);
500 mlist
->count
= WL_MAX_ASSOC
;
501 strcpy((char*)mlist
, "autho_sta_list");
502 if (wl_ioctl(ifname
, WLC_GET_VAR
, mlist
, mlsize
) == 0) {
503 for (i
= 0; i
< mlist
->count
; ++i
) {
504 if (is_same_addr(&mlist
->ea
[i
], &bi
->BSSID
)) {
514 return (associated
&& authorized
);
517 #define STACHECK_CONNECT 30
518 #define STACHECK_DISCONNECT 5
520 int radio_main(int argc
, char *argv
[])
524 usage_exit(argv
[0], "on|off|toggle|join\n");
527 if (!nvram_match("wl_radio", "1")) {
531 if (strcmp(argv
[1], "toggle") == 0) {
532 argv
[1] = get_radio() ? "off" : "on";
535 if (strcmp(argv
[1], "off") == 0) {
540 else if (strcmp(argv
[1], "on") == 0) {
543 else if (strcmp(argv
[1], "join") != 0) {
552 if (f_read_string("/var/run/radio.pid", s
, sizeof(s
)) > 0) {
553 if ((i
= atoi(s
)) > 1) {
560 sprintf(s
, "%d", getpid());
561 f_write("/var/run/radio.pid", s
, sizeof(s
), 0, 0644);
563 int stacheck_connect
= nvram_get_int("sta_chkint");
564 if (stacheck_connect
<= 0)
565 stacheck_connect
= STACHECK_CONNECT
;
568 while (get_radio() && wl_client()) {
570 if (check_wl_client(nvram_safe_get("wl_ifname"))) {
571 stacheck
= stacheck_connect
;
574 eval("wl", "disassoc");
576 char *amode
, *sec
= nvram_safe_get("security_mode2");
578 if (strstr(sec
, "personal")) {
579 if (strstr(sec
, "wpa2")) amode
= "wpa2psk";
580 else amode
= "wpapsk";
582 else if (strstr(sec
, "wpa2")) amode
= "wpa2";
583 else if (strstr(sec
, "wpa")) amode
= "wpa";
584 else if (nvram_get_int("wl_auth")) amode
= "shared";
587 eval("wl", "join", nvram_safe_get("wl_ssid"),
588 "imode", "bss", "amode", amode
);
590 eval("wl", "join", nvram_safe_get("wl_ssid"));
592 stacheck
= STACHECK_DISCONNECT
;
598 unlink("/var/run/radio.pid");
606 int wdist_main(int argc, char *argv[])
615 if (wl_ioctl(nvram_safe_get("wl_ifname"), 101, &r, sizeof(r)) == 0) {
618 else v = (v - (9 + 1)) * 150;
619 printf("Current: %d-%dm (0x%02x)\n\n", v + (v ? 1 : 0), v + 150, r.val);
621 usage_exit(argv[0], "<meters>");
623 if ((n = atoi(argv[1])) <= 0) setup_wldistance();
624 else set_wldistance(n);
631 int wldist_main(int argc
, char *argv
[])
639 p
= nvram_safe_get("wl_distance");
640 if ((*p
== 0) || ((n
= atoi(p
)) < 0)) return 0;
641 n
= 9 + (n
/ 150) + ((n
% 150) ? 1 : 0);
644 s
= 0x10 | (n
<< 16);
645 p
= nvram_safe_get("wl_ifname");
646 wl_ioctl(p
, 197, &s
, sizeof(s
));
651 wl_ioctl(p
, 102, &r
, sizeof(r
));