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/sockios.h>
53 #include <linux/ethtool.h>
54 #include <sys/ioctl.h>
55 #include <net/if_arp.h>
58 #include <bcmparams.h>
61 #ifndef WL_BSS_INFO_VERSION
62 #error WL_BSS_INFO_VERSION
64 #if WL_BSS_INFO_VERSION == 108
70 #define IFUP (IFF_UP | IFF_RUNNING | IFF_BROADCAST | IFF_MULTICAST)
71 #define sin_addr(s) (((struct sockaddr_in *)(s))->sin_addr)
73 void set_host_domain_name(void)
77 s
= nvram_safe_get("wan_hostname");
78 sethostname(s
, strlen(s
));
79 s
= nvram_get("wan_domain");
80 if ((s
== NULL
) || (*s
== 0)) s
= nvram_safe_get("wan_get_domain");
81 setdomainname(s
, strlen(s
));
84 static int wlconf(char *ifname
)
88 r
= eval("wlconf", ifname
, "up");
90 // set_mac(ifname, "mac_wl", 2);
92 nvram_set("rrules_radio", "-1");
94 eval("wl", "antdiv", nvram_safe_get("wl_antdiv"));
95 eval("wl", "txant", nvram_safe_get("wl_txant"));
96 eval("wl", "txpwr1", "-o", "-m", nvram_safe_get("wl_txpwr"));
98 killall("wldist", SIGTERM
);
102 if (nvram_match("wl_mode", "wet")) {
103 ifconfig(ifname
, IFUP
|IFF_ALLMULTI
, NULL
, NULL
);
105 if (nvram_match("wl_radio", "1")) {
106 xstart("radio", "join");
113 static void check_afterburner(void)
117 if (nvram_match("wl_afterburner", "off")) return;
118 if ((p
= nvram_get("boardflags")) == NULL
) return;
120 if (strcmp(p
, "0x0118") == 0) { // G 2.2, 3.0, 3.1
123 else if (strcmp(p
, "0x0188") == 0) { // G 2.0
126 else if (strcmp(p
, "0x2558") == 0) { // G 4.0, GL 1.0, 1.1
133 nvram_set("boardflags", p
);
135 if (!nvram_match("debug_abrst", "0")) {
146 bf = strtoul(p, &p, 0);
147 if ((*p == 0) && ((bf & BFL_AFTERBURNER) == 0)) {
148 sprintf(s, "0x%04lX", bf | BFL_AFTERBURNER);
149 nvram_set("boardflags", s);
157 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
161 char *lan_ifnames
, *ifname
, *p
;
164 set_mac(nvram_safe_get("wl_ifname"), "mac_wl", 2);
167 if ((sfd
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0) return;
169 lan_ifname
= strdup(nvram_safe_get("lan_ifname"));
170 if (strncmp(lan_ifname
, "br", 2) == 0) {
171 eval("brctl", "addbr", lan_ifname
);
172 eval("brctl", "setfd", lan_ifname
, "0");
173 eval("brctl", "stp", lan_ifname
, nvram_safe_get("lan_stp"));
175 if ((lan_ifnames
= strdup(nvram_safe_get("lan_ifnames"))) != NULL
) {
177 while ((ifname
= strsep(&p
, " ")) != NULL
) {
178 while (*ifname
== ' ') ++ifname
;
179 if (*ifname
== 0) break;
181 // bring up interface
182 if (ifconfig(ifname
, IFUP
, NULL
, NULL
) != 0) continue;
184 // set the logical bridge address to that of the first interface
185 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
186 if ((ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) && (memcmp(ifr
.ifr_hwaddr
.sa_data
, "\0\0\0\0\0\0", ETHER_ADDR_LEN
) == 0)) {
187 strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
188 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) {
189 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
190 ifr
.ifr_hwaddr
.sa_family
= ARPHRD_ETHER
;
191 ioctl(sfd
, SIOCSIFHWADDR
, &ifr
);
195 if (wlconf(ifname
) == 0) {
196 const char *mode
= nvram_get("wl0_mode");
197 if ((mode
) && ((strcmp(mode
, "ap") != 0) && (strcmp(mode
, "wet") != 0))) continue;
199 eval("brctl", "addif", lan_ifname
, ifname
);
202 if ((nvram_get_int("wan_islan")) &&
203 ((get_wan_proto() == WP_DISABLED
) || (nvram_match("wl_mode", "sta")))) {
204 ifname
= nvram_get("wan_ifnameX");
205 if (ifconfig(ifname
, IFUP
, NULL
, NULL
) == 0)
206 eval("brctl", "addif", lan_ifname
, ifname
);
212 // --- this shouldn't happen ---
213 else if (*lan_ifname
) {
214 ifconfig(lan_ifname
, IFUP
, NULL
, NULL
);
224 // Get current LAN hardware address
226 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
227 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) nvram_set("lan_hwaddr", ether_etoa(ifr
.ifr_hwaddr
.sa_data
, eabuf
));
232 struct ethtool_drvinfo info
;
234 qos
= (strcmp(nvram_safe_get("wl_wme"), "on")) ? 0 : 1;
235 for (i
= 1; i
<= DEV_NUMIFS
; i
++) {
237 if (ioctl(sfd
, SIOCGIFNAME
, &ifr
)) continue;
238 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
)) continue;
239 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) continue;
241 if (ioctl(sfd
, SIOCGIFFLAGS
, &ifr
)) continue;
242 /* if up(wan not up yet at this point) */
243 if (ifr
.ifr_flags
& IFF_UP
) {
244 ifrdata
= ifr
.ifr_data
;
245 memset(&info
, 0, sizeof(info
));
246 info
.cmd
= ETHTOOL_GDRVINFO
;
247 ifr
.ifr_data
= (caddr_t
)&info
;
248 if (ioctl(sfd
, SIOCETHTOOL
, &ifr
) >= 0) {
249 /* currently only need to set QoS to et devices */
250 if (!strncmp(info
.driver
, "et", 2)) {
251 ifr
.ifr_data
= (caddr_t
)&qos
;
252 ioctl(sfd
, SIOCSETCQOS
, &ifr
);
255 ifr
.ifr_data
= ifrdata
;
261 // bring up and configure LAN interface
262 ifconfig(lan_ifname
, IFUP
, nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_netmask"));
267 if (nvram_match("wan_proto", "disabled")) {
268 char *gateway
= nvram_safe_get("lan_gateway") ;
269 if ((*gateway
) && (strcmp(gateway
, "0.0.0.0") != 0)) {
271 while ((route_add(lan_ifname
, 0, "0.0.0.0", gateway
, "0.0.0.0") != 0) && (tries
-- > 0)) sleep(1);
272 _dprintf("%s: add gateway=%s tries=%d\n", __FUNCTION__
, gateway
, tries
);
278 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
283 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
286 char *lan_ifnames
, *p
, *ifname
;
288 lan_ifname
= nvram_safe_get("lan_ifname");
289 ifconfig(lan_ifname
, 0, NULL
, NULL
);
291 if (strncmp(lan_ifname
, "br", 2) == 0) {
292 if ((lan_ifnames
= strdup(nvram_safe_get("lan_ifnames"))) != NULL
) {
294 while ((ifname
= strsep(&p
, " ")) != NULL
) {
295 while (*ifname
== ' ') ++ifname
;
296 if (*ifname
== 0) break;
297 eval("wlconf", ifname
, "down");
298 ifconfig(ifname
, 0, NULL
, NULL
);
299 eval("brctl", "delif", lan_ifname
, ifname
);
304 else if (*lan_ifname
) {
305 eval("wlconf", lan_ifname
, "down");
308 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
312 void do_static_routes(int add
)
316 char *dest
, *mask
, *gateway
, *metric
, *ifname
;
319 if ((buf
= strdup(nvram_safe_get(add
? "routes_static" : "routes_static_saved"))) == NULL
) return;
320 if (add
) nvram_set("routes_static_saved", buf
);
321 else nvram_unset("routes_static_saved");
323 while ((q
= strsep(&p
, ">")) != NULL
) {
324 if (vstrsep(q
, "<", &dest
, &gateway
, &mask
, &metric
, &ifname
) != 5) continue;
325 ifname
= nvram_safe_get((*ifname
== 'L') ? "lan_ifname" : "wan_ifname");
327 for (r
= 3; r
>= 0; --r
) {
328 if (route_add(ifname
, atoi(metric
) + 1, dest
, gateway
, mask
) == 0) break;
333 route_del(ifname
, atoi(metric
) + 1, dest
, gateway
, mask
);
339 void hotplug_net(void)
341 char *interface
, *action
;
344 if (((interface
= getenv("INTERFACE")) == NULL
) || ((action
= getenv("ACTION")) == NULL
)) return;
346 _dprintf("hotplug net INTERFACE=%s ACTION=%s\n", interface
, action
);
348 if ((nvram_match("wds_enable", "1")) && (strncmp(interface
, "wds", 3) == 0) && (strcmp(action
, "register") == 0)) {
349 ifconfig(interface
, IFUP
, NULL
, NULL
);
350 lan_ifname
= nvram_safe_get("lan_ifname");
351 if (strncmp(lan_ifname
, "br", 2) == 0) {
352 eval("brctl", "addif", lan_ifname
, interface
);
353 notify_nas(interface
);
358 int radio_main(int argc
, char *argv
[])
362 usage_exit(argv
[0], "on|off|toggle|join\n");
365 if (!nvram_match("wl_radio", "1")) {
369 if (strcmp(argv
[1], "toggle") == 0) {
370 argv
[1] = get_radio() ? "off" : "on";
373 if (strcmp(argv
[1], "off") == 0) {
378 else if (strcmp(argv
[1], "on") == 0) {
381 else if (strcmp(argv
[1], "join") != 0) {
391 if (f_read_string("/var/run/radio.pid", s
, sizeof(s
)) > 0) {
392 if ((i
= atoi(s
)) > 1) {
399 sprintf(s
, "%d", getpid());
400 f_write("/var/run/radio.pid", s
, sizeof(s
), 0, 0644);
403 if (!get_radio()) break;
405 eval("wl", "join", nvram_safe_get("wl_ssid"));
406 for (i
= 6; i
> 0; --i
) {
408 if ((wl_ioctl(nvram_safe_get("wl_ifname"), WLC_GET_SSID
, &ssid
, sizeof(ssid
)) == 0) &&
409 (ssid
.SSID_len
> 0)) break;
415 unlink("/var/run/radio.pid");
423 int wdist_main(int argc, char *argv[])
432 if (wl_ioctl(nvram_safe_get("wl_ifname"), 101, &r, sizeof(r)) == 0) {
435 else v = (v - (9 + 1)) * 150;
436 printf("Current: %d-%dm (0x%02x)\n\n", v + (v ? 1 : 0), v + 150, r.val);
438 usage_exit(argv[0], "<meters>");
440 if ((n = atoi(argv[1])) <= 0) setup_wldistance();
441 else set_wldistance(n);
448 int wldist_main(int argc
, char *argv
[])
456 p
= nvram_safe_get("wl_distance");
457 if ((*p
== 0) || ((n
= atoi(p
)) < 0)) return 0;
458 n
= 9 + (n
/ 150) + ((n
% 150) ? 1 : 0);
461 s
= 0x10 | (n
<< 16);
462 p
= nvram_safe_get("wl_ifname");
463 wl_ioctl(p
, 197, &s
, sizeof(s
));
468 wl_ioctl(p
, 102, &r
, sizeof(r
));