Tomato 1.24
[tomato.git] / release / src / router / rc / network.c
blob674467f91e41d3bb98a9e96274f6e58b2f7b0b36
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/sockios.h>
53 #include <linux/ethtool.h>
54 #include <sys/ioctl.h>
55 #include <net/if_arp.h>
57 #include <wlutils.h>
58 #include <bcmparams.h>
59 #include <wlioctl.h>
61 #ifndef WL_BSS_INFO_VERSION
62 #error WL_BSS_INFO_VERSION
63 #endif
64 #if WL_BSS_INFO_VERSION == 108
65 #include <etioctl.h>
66 #else
67 #include <etsockio.h>
68 #endif
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)
75 const char *s;
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)
86 int r;
88 r = eval("wlconf", ifname, "up");
89 if (r == 0) {
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);
99 eval("wldist");
101 if (wl_client()) {
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");
110 return r;
113 static void check_afterburner(void)
115 char *p;
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
121 p = "0x0318";
123 else if (strcmp(p, "0x0188") == 0) { // G 2.0
124 p = "0x0388";
126 else if (strcmp(p, "0x2558") == 0) { // G 4.0, GL 1.0, 1.1
127 p = "0x2758";
129 else {
130 return;
133 nvram_set("boardflags", p);
135 if (!nvram_match("debug_abrst", "0")) {
136 modprobe_r("wl");
137 modprobe("wl");
141 /* safe?
143 unsigned long bf;
144 char s[64];
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);
155 void start_lan(void)
157 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
159 char *lan_ifname;
160 struct ifreq ifr;
161 char *lan_ifnames, *ifname, *p;
162 int sfd;
164 check_afterburner();
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) {
175 p = lan_ifnames;
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);
208 free(lan_ifnames);
211 // --- this shouldn't happen ---
212 else if (*lan_ifname) {
213 ifconfig(lan_ifname, IFUP, NULL, NULL);
214 wlconf(lan_ifname);
216 else {
217 close(sfd);
218 free(lan_ifname);
219 return;
223 // Get current LAN hardware address
224 char eabuf[32];
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));
229 int i, qos;
230 caddr_t ifrdata;
231 struct ethtool_drvinfo info;
233 qos = (strcmp(nvram_safe_get("wl_wme"), "on")) ? 0 : 1;
234 for (i = 1; i <= DEV_NUMIFS; i++) {
235 ifr.ifr_ifindex = 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;
239 /* get flags */
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;
258 close(sfd);
260 // bring up and configure LAN interface
261 ifconfig(lan_ifname, IFUP, nvram_safe_get("lan_ipaddr"), nvram_safe_get("lan_netmask"));
263 config_loopback();
264 do_static_routes(1);
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)) {
269 int tries = 5;
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);
275 free(lan_ifname);
277 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
280 void stop_lan(void)
282 _dprintf("%s %d\n", __FUNCTION__, __LINE__);
284 char *lan_ifname;
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) {
292 p = lan_ifnames;
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);
300 free(lan_ifnames);
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)
313 char *buf;
314 char *p, *q;
315 char *dest, *mask, *gateway, *metric, *ifname;
316 int r;
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");
321 p = buf;
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");
325 if (add) {
326 for (r = 3; r >= 0; --r) {
327 if (route_add(ifname, atoi(metric) + 1, dest, gateway, mask) == 0) break;
328 sleep(1);
331 else {
332 route_del(ifname, atoi(metric) + 1, dest, gateway, mask);
335 free(buf);
338 void hotplug_net(void)
340 char *interface, *action;
341 char *lan_ifname;
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[])
359 if (argc != 2) {
360 HELP:
361 usage_exit(argv[0], "on|off|toggle|join\n");
364 if (!nvram_match("wl_radio", "1")) {
365 return 1;
368 if (strcmp(argv[1], "toggle") == 0) {
369 argv[1] = get_radio() ? "off" : "on";
372 if (strcmp(argv[1], "off") == 0) {
373 set_radio(0);
374 led(LED_DIAG, 0);
375 return 0;
377 else if (strcmp(argv[1], "on") == 0) {
378 set_radio(1);
380 else if (strcmp(argv[1], "join") != 0) {
381 goto HELP;
385 if (wl_client()) {
386 int i;
387 wlc_ssid_t ssid;
388 char s[32];
390 if (f_read_string("/var/run/radio.pid", s, sizeof(s)) > 0) {
391 if ((i = atoi(s)) > 1) {
392 kill(i, SIGTERM);
393 sleep(1);
397 if (fork() == 0) {
398 sprintf(s, "%d", getpid());
399 f_write("/var/run/radio.pid", s, sizeof(s), 0, 0644);
401 while (1) {
402 if (!get_radio()) break;
404 eval("wl", "join", nvram_safe_get("wl_ssid"));
405 for (i = 6; i > 0; --i) {
406 sleep(1);
407 if ((wl_ioctl(nvram_safe_get("wl_ifname"), WLC_GET_SSID, &ssid, sizeof(ssid)) == 0) &&
408 (ssid.SSID_len > 0)) break;
410 if (i > 0) break;
411 sleep(5);
414 unlink("/var/run/radio.pid");
418 return 0;
422 int wdist_main(int argc, char *argv[])
424 int n;
425 rw_reg_t r;
426 int v;
428 if (argc != 2) {
429 r.byteoff = 0x684;
430 r.size = 2;
431 if (wl_ioctl(nvram_safe_get("wl_ifname"), 101, &r, sizeof(r)) == 0) {
432 v = r.val - 510;
433 if (v <= 9) v = 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);
441 return 0;
446 // ref: wificonf.c
447 int wldist_main(int argc, char *argv[])
449 rw_reg_t r;
450 uint32 s;
451 char *p;
452 int n;
454 if (fork() == 0) {
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);
459 while (1) {
460 s = 0x10 | (n << 16);
461 p = nvram_safe_get("wl_ifname");
462 wl_ioctl(p, 197, &s, sizeof(s));
464 r.byteoff = 0x684;
465 r.val = n + 510;
466 r.size = 2;
467 wl_ioctl(p, 102, &r, sizeof(r));
469 sleep(2);
473 return 0;