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
;
166 if ((sfd
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0) return;
168 lan_ifname
= strdup(nvram_safe_get("lan_ifname"));
169 if (strncmp(lan_ifname
, "br", 2) == 0) {
170 eval("brctl", "addbr", lan_ifname
);
171 eval("brctl", "setfd", lan_ifname
, "0");
172 eval("brctl", "stp", lan_ifname
, nvram_safe_get("lan_stp"));
174 if ((lan_ifnames
= strdup(nvram_safe_get("lan_ifnames"))) != NULL
) {
176 while ((ifname
= strsep(&p
, " ")) != NULL
) {
177 while (*ifname
== ' ') ++ifname
;
178 if (*ifname
== 0) break;
180 // bring up interface
181 if (ifconfig(ifname
, IFUP
, NULL
, NULL
) != 0) continue;
183 // set the logical bridge address to that of the first interface
184 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
185 if ((ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) && (memcmp(ifr
.ifr_hwaddr
.sa_data
, "\0\0\0\0\0\0", ETHER_ADDR_LEN
) == 0)) {
186 strlcpy(ifr
.ifr_name
, ifname
, IFNAMSIZ
);
187 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) {
188 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
189 ifr
.ifr_hwaddr
.sa_family
= ARPHRD_ETHER
;
190 ioctl(sfd
, SIOCSIFHWADDR
, &ifr
);
194 if (wlconf(ifname
) == 0) {
195 const char *mode
= nvram_get("wl0_mode");
196 if ((mode
) && ((strcmp(mode
, "ap") != 0) && (strcmp(mode
, "wet") != 0))) continue;
198 eval("brctl", "addif", lan_ifname
, ifname
);
201 if ((nvram_get_int("wan_islan")) &&
202 ((get_wan_proto() == WP_DISABLED
) || (nvram_match("wl_mode", "sta")))) {
203 ifname
= nvram_get("wan_ifnameX");
204 if (ifconfig(ifname
, IFUP
, NULL
, NULL
) == 0)
205 eval("brctl", "addif", lan_ifname
, ifname
);
211 // --- this shouldn't happen ---
212 else if (*lan_ifname
) {
213 ifconfig(lan_ifname
, IFUP
, NULL
, NULL
);
223 // Get current LAN hardware address
225 strlcpy(ifr
.ifr_name
, lan_ifname
, IFNAMSIZ
);
226 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
) == 0) nvram_set("lan_hwaddr", ether_etoa(ifr
.ifr_hwaddr
.sa_data
, eabuf
));
231 struct ethtool_drvinfo info
;
233 qos
= (strcmp(nvram_safe_get("wl_wme"), "on")) ? 0 : 1;
234 for (i
= 1; i
<= DEV_NUMIFS
; i
++) {
236 if (ioctl(sfd
, SIOCGIFNAME
, &ifr
)) continue;
237 if (ioctl(sfd
, SIOCGIFHWADDR
, &ifr
)) continue;
238 if (ifr
.ifr_hwaddr
.sa_family
!= ARPHRD_ETHER
) continue;
240 if (ioctl(sfd
, SIOCGIFFLAGS
, &ifr
)) continue;
241 /* if up(wan not up yet at this point) */
242 if (ifr
.ifr_flags
& IFF_UP
) {
243 ifrdata
= ifr
.ifr_data
;
244 memset(&info
, 0, sizeof(info
));
245 info
.cmd
= ETHTOOL_GDRVINFO
;
246 ifr
.ifr_data
= (caddr_t
)&info
;
247 if (ioctl(sfd
, SIOCETHTOOL
, &ifr
) >= 0) {
248 /* currently only need to set QoS to et devices */
249 if (!strncmp(info
.driver
, "et", 2)) {
250 ifr
.ifr_data
= (caddr_t
)&qos
;
251 ioctl(sfd
, SIOCSETCQOS
, &ifr
);
254 ifr
.ifr_data
= ifrdata
;
260 // bring up and configure LAN interface
261 ifconfig(lan_ifname
, IFUP
, nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_netmask"));
266 if (nvram_match("wan_proto", "disabled")) {
267 char *gateway
= nvram_safe_get("lan_gateway") ;
268 if ((*gateway
) && (strcmp(gateway
, "0.0.0.0") != 0)) {
270 while ((route_add(lan_ifname
, 0, "0.0.0.0", gateway
, "0.0.0.0") != 0) && (tries
-- > 0)) sleep(1);
271 _dprintf("%s: add gateway=%s tries=%d\n", __FUNCTION__
, gateway
, tries
);
277 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
282 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
285 char *lan_ifnames
, *p
, *ifname
;
287 lan_ifname
= nvram_safe_get("lan_ifname");
288 ifconfig(lan_ifname
, 0, NULL
, NULL
);
290 if (strncmp(lan_ifname
, "br", 2) == 0) {
291 if ((lan_ifnames
= strdup(nvram_safe_get("lan_ifnames"))) != NULL
) {
293 while ((ifname
= strsep(&p
, " ")) != NULL
) {
294 while (*ifname
== ' ') ++ifname
;
295 if (*ifname
== 0) break;
296 eval("wlconf", ifname
, "down");
297 ifconfig(ifname
, 0, NULL
, NULL
);
298 eval("brctl", "delif", lan_ifname
, ifname
);
303 else if (*lan_ifname
) {
304 eval("wlconf", lan_ifname
, "down");
307 _dprintf("%s %d\n", __FUNCTION__
, __LINE__
);
311 void do_static_routes(int add
)
315 char *dest
, *mask
, *gateway
, *metric
, *ifname
;
318 if ((buf
= strdup(nvram_safe_get(add
? "routes_static" : "routes_static_saved"))) == NULL
) return;
319 if (add
) nvram_set("routes_static_saved", buf
);
320 else nvram_unset("routes_static_saved");
322 while ((q
= strsep(&p
, ">")) != NULL
) {
323 if (vstrsep(q
, "<", &dest
, &gateway
, &mask
, &metric
, &ifname
) != 5) continue;
324 ifname
= nvram_safe_get((*ifname
== 'L') ? "lan_ifname" : "wan_ifname");
326 for (r
= 3; r
>= 0; --r
) {
327 if (route_add(ifname
, atoi(metric
) + 1, dest
, gateway
, mask
) == 0) break;
332 route_del(ifname
, atoi(metric
) + 1, dest
, gateway
, mask
);
338 void hotplug_net(void)
340 char *interface
, *action
;
343 if (((interface
= getenv("INTERFACE")) == NULL
) || ((action
= getenv("ACTION")) == NULL
)) return;
345 _dprintf("hotplug net INTERFACE=%s ACTION=%s\n", interface
, action
);
347 if ((nvram_match("wds_enable", "1")) && (strncmp(interface
, "wds", 3) == 0) && (strcmp(action
, "register") == 0)) {
348 ifconfig(interface
, IFUP
, NULL
, NULL
);
349 lan_ifname
= nvram_safe_get("lan_ifname");
350 if (strncmp(lan_ifname
, "br", 2) == 0) {
351 eval("brctl", "addif", lan_ifname
, interface
);
352 notify_nas(interface
);
357 int radio_main(int argc
, char *argv
[])
361 usage_exit(argv
[0], "on|off|toggle|join\n");
364 if (!nvram_match("wl_radio", "1")) {
368 if (strcmp(argv
[1], "toggle") == 0) {
369 argv
[1] = get_radio() ? "off" : "on";
372 if (strcmp(argv
[1], "off") == 0) {
377 else if (strcmp(argv
[1], "on") == 0) {
380 else if (strcmp(argv
[1], "join") != 0) {
390 if (f_read_string("/var/run/radio.pid", s
, sizeof(s
)) > 0) {
391 if ((i
= atoi(s
)) > 1) {
398 sprintf(s
, "%d", getpid());
399 f_write("/var/run/radio.pid", s
, sizeof(s
), 0, 0644);
402 if (!get_radio()) break;
404 eval("wl", "join", nvram_safe_get("wl_ssid"));
405 for (i
= 6; i
> 0; --i
) {
407 if ((wl_ioctl(nvram_safe_get("wl_ifname"), WLC_GET_SSID
, &ssid
, sizeof(ssid
)) == 0) &&
408 (ssid
.SSID_len
> 0)) break;
414 unlink("/var/run/radio.pid");
422 int wdist_main(int argc, char *argv[])
431 if (wl_ioctl(nvram_safe_get("wl_ifname"), 101, &r, sizeof(r)) == 0) {
434 else v = (v - (9 + 1)) * 150;
435 printf("Current: %d-%dm (0x%02x)\n\n", v + (v ? 1 : 0), v + 150, r.val);
437 usage_exit(argv[0], "<meters>");
439 if ((n = atoi(argv[1])) <= 0) setup_wldistance();
440 else set_wldistance(n);
447 int wldist_main(int argc
, char *argv
[])
455 p
= nvram_safe_get("wl_distance");
456 if ((*p
== 0) || ((n
= atoi(p
)) < 0)) return 0;
457 n
= 9 + (n
/ 150) + ((n
% 150) ? 1 : 0);
460 s
= 0x10 | (n
<< 16);
461 p
= nvram_safe_get("wl_ifname");
462 wl_ioctl(p
, 197, &s
, sizeof(s
));
467 wl_ioctl(p
, 102, &r
, sizeof(r
));