Merge branch 'tomato-ND-usbmod-base' into tomato-ND-USBmod
[tomato.git] / release / src / router / rc / misc.c
blobb1c7b33a28734ed7fc1d7013a3b4f85c11b8a529
1 /*
3 Tomato Firmware
4 Copyright (C) 2006-2009 Jonathan Zarate
6 */
8 #include "rc.h"
10 #include <stdarg.h>
11 #include <sys/ioctl.h>
12 #include <net/if_arp.h>
14 #include <bcmdevs.h>
15 #include <wlutils.h>
16 #include <dirent.h>
17 #include <sys/wait.h>
20 void usage_exit(const char *cmd, const char *help)
22 fprintf(stderr, "Usage: %s %s\n", cmd, help);
23 exit(1);
26 int modprobe(const char *mod)
28 #if 1
29 return eval("modprobe", "-s", (char *)mod);
30 #else
31 int r = eval("modprobe", "-s", (char *)mod);
32 cprintf("modprobe %s = %d\n", mod, r);
33 return r;
34 #endif
37 int modprobe_r(const char *mod)
39 #if 1
40 return eval("modprobe", "-r", (char *)mod);
41 #else
42 int r = eval("modprobe", "-r", (char *)mod);
43 cprintf("modprobe -r %s = %d\n", mod, r);
44 return r;
45 #endif
48 int _xstart(const char *cmd, ...)
50 va_list ap;
51 char *argv[16];
52 int argc;
53 int pid;
55 argv[0] = (char *)cmd;
56 argc = 1;
57 va_start(ap, cmd);
58 while ((argv[argc++] = va_arg(ap, char *)) != NULL) {
61 va_end(ap);
63 return _eval(argv, NULL, 0, &pid);
66 int endswith (char *str, char *cmp)
68 int cmp_len, str_len, i;
70 cmp_len = strlen (cmp);
71 str_len = strlen (str);
72 if (cmp_len > str_len)
73 return (0);
74 for (i = 0; i < cmp_len; i++) {
75 if (str[(str_len - 1) - i] != cmp[(cmp_len - 1) - i])
76 return (0);
78 return (1);
82 static void execute_with_maxwait(char *const argv[], int wtime)
84 pid_t pid;
86 if (_eval(argv, NULL, 0, &pid) != 0)
87 pid = -1;
88 else {
89 while (wtime-- > 0) {
90 waitpid(pid, NULL, WNOHANG); /* Reap the zombie if it has terminated. */
91 if (kill(pid, 0) != 0) break;
92 sleep(1);
94 //printf("killdon: errno: %d pid %d\n", errno, pid);
98 void run_userfile (char *folder, char *extension, const char *arg1, int wtime)
100 struct dirent *entry;
101 DIR *directory;
102 unsigned char buf[128];
103 char *argv[3];
105 //printf("run_userfile: check %s for *%s\n", folder, extension);
106 directory = opendir (folder);
107 if (directory == NULL)
108 return;
110 while ((entry = readdir (directory)) != NULL) {
111 if (endswith (entry->d_name, extension)) {
112 sprintf (buf, "%s/%s", folder, entry->d_name);
113 argv[0] = buf;
114 argv[1] = (char *)arg1;
115 argv[2] = NULL;
116 execute_with_maxwait(argv, wtime);
119 closedir (directory);
123 /* Run user-supplied script(s), with 1 argument.
124 * Return when the script(s) have finished,
125 * or after wtime seconds, even if they aren't finished.
127 * Extract NAME from nvram variable named as "script_NAME".
129 * The sole exception to the nvram item naming rule is sesx.
130 * That one is "sesx_script" rather than "script_sesx", due
131 * to historical accident.
133 * The other exception is time-scheduled commands.
134 * These have names that start with "sch_".
135 * No directories are searched for corresponding user scripts.
137 * Execute in this order:
138 * nvram item: nv (run as a /bin/sh script)
139 * All files with a suffix of ".NAME" in these directories:
140 * /etc/config/
141 * /jffs/etc/config/
142 * /opt/etc/config/
143 * /mmc/etc/config/
144 * /tmp/config/
147 At this time, the names/events are:
148 sesx SES/AOSS Button custom script.
149 brau "bridge/auto" button pushed.
150 fire When firewall service has been started or re-started.
151 shut At system shutdown, just before wan/lan/usb/etc. are stopped.
152 init At system startup, just before wan/lan/usb/etc. are started.
153 The root filesystem and /jffs are mounted, but not any USB devices.
154 usbmount After an auto-mounted USB drive is mounted.
155 usbumount Before an auto-mounted USB drive is unmounted.
156 usbhotplug When any USB device is attached or removed.
157 wanup After WAN has come up.
160 void run_nvscript(const char *nv, const char *arg1, int wtime)
162 FILE *f;
163 char *script;
164 char s[256];
165 char *argv[3];
166 int check_dirs = 1;
168 script = nvram_get(nv);
169 if ((script) && (*script != 0)) {
170 sprintf(s, "/tmp/%s.sh", nv);
171 if ((f = fopen(s, "w")) != NULL) {
172 fputs("#!/bin/sh\n", f);
173 fputs(script, f);
174 fputs("\n", f);
175 fclose(f);
176 chmod(s, 0700);
178 chdir("/tmp");
180 argv[0] = s;
181 argv[1] = (char *)arg1;
182 argv[2] = NULL;
184 //printf("Running: '%s %s'\n", argv[0], argv[1]? argv[1]: "");
185 execute_with_maxwait(argv, wtime);
186 chdir("/");
190 sprintf(s, ".%s", nv);
191 if (strncmp("sch_c", nv, 5) == 0) {
192 check_dirs = 0;
194 else if (strncmp("sesx_", nv, 5) == 0) {
195 s[5] = 0;
197 else if (strncmp("script_", nv, 7) == 0) {
198 strcpy(&s[1], &nv[7]);
201 if (nvram_match("userfiles_disable", "1")) {
202 // backdoor to disable user scripts execution
203 check_dirs = 0;
206 if ((check_dirs) && strcmp(s, ".")) {
207 //printf("checking for user scripts: '%s'\n", s);
208 run_userfile("/etc/config", s, arg1, wtime);
209 run_userfile("/jffs/etc/config", s, arg1, wtime);
210 run_userfile("/opt/etc/config", s, arg1, wtime);
211 run_userfile("/mmc/etc/config", s, arg1, wtime);
212 run_userfile("/tmp/config", s, arg1, wtime);
216 static void write_ct_timeout(const char *type, const char *name, unsigned int val)
218 unsigned char buf[128];
219 char v[16];
221 sprintf(buf, "/proc/sys/net/ipv4/netfilter/ip_conntrack_%s_timeout%s%s",
222 type, (name && name[0]) ? "_" : "", name ? name : "");
223 sprintf(v, "%u", val);
225 f_write_string(buf, v, 0, 0);
228 #ifndef write_tcp_timeout
229 #define write_tcp_timeout(name, val) write_ct_timeout("tcp", name, val)
230 #endif
232 #ifndef write_udp_timeout
233 #define write_udp_timeout(name, val) write_ct_timeout("udp", name, val)
234 #endif
236 static unsigned int read_ct_timeout(const char *type, const char *name)
238 unsigned char buf[128];
239 unsigned int val = 0;
240 char v[16];
242 sprintf(buf, "/proc/sys/net/ipv4/netfilter/ip_conntrack_%s_timeout%s%s",
243 type, (name && name[0]) ? "_" : "", name ? name : "");
244 if (f_read_string(buf, v, sizeof(v)) > 0)
245 val = atoi(v);
247 return val;
250 #ifndef read_tcp_timeout
251 #define read_tcp_timeout(name) read_ct_timeout("tcp", name)
252 #endif
254 #ifndef read_udp_timeout
255 #define read_udp_timeout(name) read_ct_timeout("udp", name)
256 #endif
258 void setup_conntrack(void)
260 unsigned int v[10];
261 const char *p;
262 char buf[70];
263 int i;
265 p = nvram_safe_get("ct_tcp_timeout");
266 if (sscanf(p, "%u%u%u%u%u%u%u%u%u%u",
267 &v[0], &v[1], &v[2], &v[3], &v[4], &v[5], &v[6], &v[7], &v[8], &v[9]) == 10) { // lightly verify
268 write_tcp_timeout("established", v[1]);
269 write_tcp_timeout("syn_sent", v[2]);
270 write_tcp_timeout("syn_recv", v[3]);
271 write_tcp_timeout("fin_wait", v[4]);
272 write_tcp_timeout("time_wait", v[5]);
273 write_tcp_timeout("close", v[6]);
274 write_tcp_timeout("close_wait", v[7]);
275 write_tcp_timeout("last_ack", v[8]);
277 else {
278 v[1] = read_tcp_timeout("established");
279 v[2] = read_tcp_timeout("syn_sent");
280 v[3] = read_tcp_timeout("syn_recv");
281 v[4] = read_tcp_timeout("fin_wait");
282 v[5] = read_tcp_timeout("time_wait");
283 v[6] = read_tcp_timeout("close");
284 v[7] = read_tcp_timeout("close_wait");
285 v[8] = read_tcp_timeout("last_ack");
286 sprintf(buf, "0 %u %u %u %u %u %u %u %u 0",
287 v[1], v[2], v[3], v[4], v[5], v[6], v[7], v[8]);
288 nvram_set("ct_tcp_timeout", buf);
291 p = nvram_safe_get("ct_udp_timeout");
292 if (sscanf(p, "%u%u", &v[0], &v[1]) == 2) {
293 write_udp_timeout(NULL, v[0]);
294 write_udp_timeout("stream", v[1]);
296 else {
297 v[0] = read_udp_timeout(NULL);
298 v[1] = read_udp_timeout("stream");
299 sprintf(buf, "%u %u", v[0], v[1]);
300 nvram_set("ct_udp_timeout", buf);
303 p = nvram_safe_get("ct_timeout");
304 if (sscanf(p, "%u%u", &v[0], &v[1]) == 2) {
305 write_ct_timeout("generic", NULL, v[0]);
306 write_ct_timeout("icmp", NULL, v[1]);
308 else {
309 v[0] = read_ct_timeout("generic", NULL);
310 v[1] = read_ct_timeout("icmp", NULL);
311 sprintf(buf, "%u %u", v[0], v[1]);
312 nvram_set("ct_timeout", buf);
315 p = nvram_safe_get("ct_max");
316 i = atoi(p);
317 if ((i >= 128) && (i <= 10240)) {
318 f_write_string("/proc/sys/net/ipv4/ip_conntrack_max", p, 0, 0);
321 if (!nvram_match("nf_pptp", "0")) {
322 modprobe("ip_conntrack_proto_gre");
323 modprobe("ip_nat_proto_gre");
324 modprobe("ip_conntrack_pptp");
325 modprobe("ip_nat_pptp");
327 else {
328 modprobe_r("ip_nat_pptp");
329 modprobe_r("ip_conntrack_pptp");
330 modprobe_r("ip_nat_proto_gre");
331 modprobe_r("ip_conntrack_proto_gre");
334 if (!nvram_match("nf_h323", "0")) {
335 modprobe("ip_conntrack_h323");
336 modprobe("ip_nat_h323");
338 else {
339 modprobe_r("ip_nat_h323");
340 modprobe_r("ip_conntrack_h323");
343 if (!nvram_match("nf_rtsp", "0")) {
344 modprobe("ip_conntrack_rtsp");
345 modprobe("ip_nat_rtsp");
347 else {
348 modprobe_r("ip_nat_rtsp");
349 modprobe_r("ip_conntrack_rtsp");
352 // !!TB - FTP Server
353 #ifdef TCONFIG_FTP
354 i = nvram_get_int("ftp_port");
355 if (nvram_match("ftp_enable", "1") && (i > 0) && (i != 21))
357 char ports[32];
359 sprintf(ports, "ports=21,%d", i);
360 eval("modprobe", "-s", "ip_conntrack_ftp", ports);
361 eval("modprobe", "-s", "ip_nat_ftp", ports);
363 else
364 #endif
365 if (!nvram_match("nf_ftp", "0")
366 #ifdef TCONFIG_FTP
367 || nvram_match("ftp_enable", "1") // !!TB - FTP Server
368 #endif
370 modprobe("ip_conntrack_ftp");
371 modprobe("ip_nat_ftp");
373 else {
374 modprobe_r("ip_nat_ftp");
375 modprobe_r("ip_conntrack_ftp");
380 void set_mac(const char *ifname, const char *nvname, int plus)
382 int sfd;
383 struct ifreq ifr;
384 int up;
385 int j;
387 if ((sfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
388 _dprintf("%s: %s %d\n", ifname, __FUNCTION__, __LINE__);
389 return;
392 strcpy(ifr.ifr_name, ifname);
394 up = 0;
395 if (ioctl(sfd, SIOCGIFFLAGS, &ifr) == 0) {
396 if ((up = ifr.ifr_flags & IFF_UP) != 0) {
397 ifr.ifr_flags &= ~IFF_UP;
398 if (ioctl(sfd, SIOCSIFFLAGS, &ifr) != 0) {
399 _dprintf("%s: %s %d\n", ifname, __FUNCTION__, __LINE__);
403 else {
404 _dprintf("%s: %s %d\n", ifname, __FUNCTION__, __LINE__);
407 if (!ether_atoe(nvram_safe_get(nvname), (unsigned char *)&ifr.ifr_hwaddr.sa_data)) {
408 if (!ether_atoe(nvram_safe_get("et0macaddr"), (unsigned char *)&ifr.ifr_hwaddr.sa_data)) {
410 // goofy et0macaddr, make something up
411 nvram_set("et0macaddr", "00:01:23:45:67:89");
412 ifr.ifr_hwaddr.sa_data[0] = 0;
413 ifr.ifr_hwaddr.sa_data[1] = 0x01;
414 ifr.ifr_hwaddr.sa_data[2] = 0x23;
415 ifr.ifr_hwaddr.sa_data[3] = 0x45;
416 ifr.ifr_hwaddr.sa_data[4] = 0x67;
417 ifr.ifr_hwaddr.sa_data[5] = 0x89;
420 while (plus-- > 0) {
421 for (j = 5; j >= 3; --j) {
422 ifr.ifr_hwaddr.sa_data[j]++;
423 if (ifr.ifr_hwaddr.sa_data[j] != 0) break; // continue if rolled over
428 ifr.ifr_hwaddr.sa_family = ARPHRD_ETHER;
429 if (ioctl(sfd, SIOCSIFHWADDR, &ifr) == -1) {
430 _dprintf("Error setting %s address\n", ifname);
433 if (up) {
434 if (ioctl(sfd, SIOCGIFFLAGS, &ifr) == 0) {
435 ifr.ifr_flags |= IFF_UP|IFF_RUNNING;
436 if (ioctl(sfd, SIOCSIFFLAGS, &ifr) == -1) {
437 _dprintf("%s: %s %d\n", ifname, __FUNCTION__, __LINE__);
440 else {
441 _dprintf("%s: %s %d\n", ifname, __FUNCTION__, __LINE__);
445 close(sfd);
449 const char *default_wanif(void)
451 return ((strtoul(nvram_safe_get("boardflags"), NULL, 0) & BFL_ENETVLAN) ||
452 (check_hw_type() == HW_BCM4712)) ? "vlan1" : "eth1";
457 const char *default_wlif(void)
459 switch (check_hw_type()) {
460 case HW_BCM4702:
461 case HW_BCM4704_BCM5325F:
462 case HW_BCM4704_BCM5325F_EWC:
463 return "eth2";
465 return "eth1";
470 int _vstrsep(char *buf, const char *sep, ...)
472 va_list ap;
473 char **p;
474 int n;
476 n = 0;
477 va_start(ap, sep);
478 while ((p = va_arg(ap, char **)) != NULL) {
479 if ((*p = strsep(&buf, sep)) == NULL) break;
480 ++n;
482 va_end(ap);
483 return n;
486 void simple_unlock(const char *name)
488 char fn[256];
490 snprintf(fn, sizeof(fn), "/var/lock/%s.lock", name);
491 f_write(fn, NULL, 0, 0, 0600);
494 void simple_lock(const char *name)
496 int n;
497 char fn[256];
499 n = 5 + (getpid() % 10);
500 snprintf(fn, sizeof(fn), "/var/lock/%s.lock", name);
501 while (unlink(fn) != 0) {
502 if (--n == 0) {
503 syslog(LOG_DEBUG, "Breaking %s", fn);
504 break;
506 sleep(1);
510 void killall_tk(const char *name)
512 int n;
514 if (killall(name, SIGTERM) == 0) {
515 n = 5;
516 while ((killall(name, 0) == 0) && (n-- > 0)) {
517 _dprintf("%s: waiting name=%s n=%d\n", __FUNCTION__, name, n);
518 sleep(1);
520 if (n < 0) {
521 n = 5;
522 while ((killall(name, SIGKILL) == 0) && (n-- > 0)) {
523 _dprintf("%s: SIGKILL name=%s n=%d\n", __FUNCTION__, name, n);
524 sleep(2);
530 long fappend(FILE *out, const char *fname)
532 FILE *in;
533 char buf[1024];
534 int n;
535 long r;
537 if ((in = fopen(fname, "r")) == NULL) return -1;
538 r = 0;
539 while ((n = fread(buf, 1, sizeof(buf), in)) > 0) {
540 if (fwrite(buf, 1, n, out) != n) {
541 r = -1;
542 break;
544 else {
545 r += n;
548 fclose(in);
549 return r;