4 Copyright (C) 2006-2009 Jonathan Zarate
11 #include <sys/ioctl.h>
12 #include <net/if_arp.h>
20 void usage_exit(const char *cmd
, const char *help
)
22 fprintf(stderr
, "Usage: %s %s\n", cmd
, help
);
26 #if 0 // replaced by #define in rc.h
27 int modprobe(const char *mod
)
30 return eval("modprobe", "-s", (char *)mod
);
32 int r
= eval("modprobe", "-s", (char *)mod
);
33 cprintf("modprobe %s = %d\n", mod
, r
);
39 int modprobe_r(const char *mod
)
42 return eval("modprobe", "-r", (char *)mod
);
44 int r
= eval("modprobe", "-r", (char *)mod
);
45 cprintf("modprobe -r %s = %d\n", mod
, r
);
52 #define ct_modprobe(mod, args...) ({ \
53 modprobe("nf_conntrack_"mod, ## args); \
54 modprobe("nf_nat_"mod); \
57 #define ct_modprobe(mod, args...) ({ \
58 modprobe("ip_conntrack_"mod, ## args); \
59 modprobe("ip_nat_"mod, ## args); \
66 #define ct_modprobe_r(mod) ({ \
67 modprobe_r("nf_nat_"mod); \
68 modprobe_r("nf_conntrack_"mod); \
71 #define ct_modprobe_r(mod) ({ \
72 modprobe_r("ip_nat_"mod); \
73 modprobe_r("ip_conntrack_"mod); \
78 int _xstart(const char *cmd
, ...)
85 argv
[0] = (char *)cmd
;
88 while ((argv
[argc
++] = va_arg(ap
, char *)) != NULL
) {
93 return _eval(argv
, NULL
, 0, &pid
);
96 int endswith (const char *str
, char *cmp
)
98 int cmp_len
, str_len
, i
;
100 cmp_len
= strlen (cmp
);
101 str_len
= strlen (str
);
102 if (cmp_len
> str_len
)
104 for (i
= 0; i
< cmp_len
; i
++) {
105 if (str
[(str_len
- 1) - i
] != cmp
[(cmp_len
- 1) - i
])
112 static void execute_with_maxwait(char *const argv
[], int wtime
)
116 if (_eval(argv
, NULL
, 0, &pid
) != 0)
119 while (wtime
-- > 0) {
120 waitpid(pid
, NULL
, WNOHANG
); /* Reap the zombie if it has terminated. */
121 if (kill(pid
, 0) != 0) break;
124 //printf("killdon: errno: %d pid %d\n", errno, pid);
128 /* This is a bit ugly. Why didn't they allow another parameter to filter???? */
129 static char *filter_extension
;
130 static int endswith_filter(const struct dirent
*entry
)
132 return endswith(entry
->d_name
, filter_extension
);
135 void run_userfile(char *folder
, char *extension
, const char *arg1
, int wtime
)
137 unsigned char buf
[128];
139 struct dirent
**namelist
;
142 /* Do them in sorted order. */
143 filter_extension
= extension
;
144 n
= scandir(folder
, &namelist
, endswith_filter
, alphasort
);
148 for (i
= 0; i
< n
; ++i
) {
149 sprintf (buf
, "%s/%s", folder
, namelist
[i
]->d_name
);
151 argv
[1] = (char *)arg1
;
153 execute_with_maxwait(argv
, wtime
);
161 /* Run user-supplied script(s), with 1 argument.
162 * Return when the script(s) have finished,
163 * or after wtime seconds, even if they aren't finished.
165 * Extract NAME from nvram variable named as "script_NAME".
167 * The sole exception to the nvram item naming rule is sesx.
168 * That one is "sesx_script" rather than "script_sesx", due
169 * to historical accident.
171 * The other exception is time-scheduled commands.
172 * These have names that start with "sch_".
173 * No directories are searched for corresponding user scripts.
175 * Execute in this order:
176 * nvram item: nv (run as a /bin/sh script)
177 * All files with a suffix of ".NAME" in these directories:
185 At this time, the names/events are:
186 (Unless otherwise noted, there are no parameters. Otherwise, one parameter).
187 sesx SES/AOSS Button custom script. Param: ??
188 brau "bridge/auto" button pushed. Param: mode (bridge/auto/etc)
189 fire When firewall service has been started or re-started.
190 shut At system shutdown, just before wan/lan/usb/etc. are stopped.
191 init At system startup, just before wan/lan/usb/etc. are started.
192 The root filesystem and /jffs are mounted, but not any USB devices.
193 usbmount After an auto-mounted USB drive is mounted.
194 usbumount Before an auto-mounted USB drive is unmounted.
195 usbhotplug When any USB device is attached or removed.
196 wanup After WAN has come up.
197 autostop When a USB partition gets un-mounted. Param: the mount-point (directory).
198 If unmounted from the GUI, the directory is still mounted and accessible.
199 If the USB drive was unplugged, it is still mounted but not accessible.
201 User scripts -- no directories are searched. One parameter.
202 autorun When a USB disk partition gets auto-mounted. Param: the mount-point (directory).
203 But not if the partition was already mounted.
204 Only the files in that directory will be run.
206 void run_nvscript(const char *nv
, const char *arg1
, int wtime
)
214 script
= nvram_get(nv
);
215 if ((script
) && (*script
!= 0)) {
216 sprintf(s
, "/tmp/%s.sh", nv
);
217 if ((f
= fopen(s
, "w")) != NULL
) {
218 fputs("#!/bin/sh\n", f
);
227 argv
[1] = (char *)arg1
;
230 //printf("Running: '%s %s'\n", argv[0], argv[1]? argv[1]: "");
231 execute_with_maxwait(argv
, wtime
);
236 sprintf(s
, ".%s", nv
);
237 if (strncmp("sch_c", nv
, 5) == 0) {
240 else if (strncmp("sesx_", nv
, 5) == 0) {
243 else if (strncmp("script_", nv
, 7) == 0) {
244 strcpy(&s
[1], &nv
[7]);
247 if (nvram_match("userfiles_disable", "1")) {
248 // backdoor to disable user scripts execution
252 if ((check_dirs
) && strcmp(s
, ".")) {
253 //printf("checking for user scripts: '%s'\n", s);
254 run_userfile("/etc/config", s
, arg1
, wtime
);
255 run_userfile("/jffs/etc/config", s
, arg1
, wtime
);
256 run_userfile("/opt/etc/config", s
, arg1
, wtime
);
257 run_userfile("/mmc/etc/config", s
, arg1
, wtime
);
258 run_userfile("/tmp/config", s
, arg1
, wtime
);
262 static void write_ct_timeout(const char *type
, const char *name
, unsigned int val
)
264 unsigned char buf
[128];
267 sprintf(buf
, "/proc/sys/net/ipv4/netfilter/ip_conntrack_%s_timeout%s%s",
268 type
, (name
&& name
[0]) ? "_" : "", name
? name
: "");
269 sprintf(v
, "%u", val
);
271 f_write_string(buf
, v
, 0, 0);
274 #ifndef write_tcp_timeout
275 #define write_tcp_timeout(name, val) write_ct_timeout("tcp", name, val)
278 #ifndef write_udp_timeout
279 #define write_udp_timeout(name, val) write_ct_timeout("udp", name, val)
282 static unsigned int read_ct_timeout(const char *type
, const char *name
)
284 unsigned char buf
[128];
285 unsigned int val
= 0;
288 sprintf(buf
, "/proc/sys/net/ipv4/netfilter/ip_conntrack_%s_timeout%s%s",
289 type
, (name
&& name
[0]) ? "_" : "", name
? name
: "");
290 if (f_read_string(buf
, v
, sizeof(v
)) > 0)
296 #ifndef read_tcp_timeout
297 #define read_tcp_timeout(name) read_ct_timeout("tcp", name)
300 #ifndef read_udp_timeout
301 #define read_udp_timeout(name) read_ct_timeout("udp", name)
304 void setup_conntrack(void)
311 p
= nvram_safe_get("ct_tcp_timeout");
312 if (sscanf(p
, "%u%u%u%u%u%u%u%u%u%u",
313 &v
[0], &v
[1], &v
[2], &v
[3], &v
[4], &v
[5], &v
[6], &v
[7], &v
[8], &v
[9]) == 10) { // lightly verify
314 write_tcp_timeout("established", v
[1]);
315 write_tcp_timeout("syn_sent", v
[2]);
316 write_tcp_timeout("syn_recv", v
[3]);
317 write_tcp_timeout("fin_wait", v
[4]);
318 write_tcp_timeout("time_wait", v
[5]);
319 write_tcp_timeout("close", v
[6]);
320 write_tcp_timeout("close_wait", v
[7]);
321 write_tcp_timeout("last_ack", v
[8]);
324 v
[1] = read_tcp_timeout("established");
325 v
[2] = read_tcp_timeout("syn_sent");
326 v
[3] = read_tcp_timeout("syn_recv");
327 v
[4] = read_tcp_timeout("fin_wait");
328 v
[5] = read_tcp_timeout("time_wait");
329 v
[6] = read_tcp_timeout("close");
330 v
[7] = read_tcp_timeout("close_wait");
331 v
[8] = read_tcp_timeout("last_ack");
332 sprintf(buf
, "0 %u %u %u %u %u %u %u %u 0",
333 v
[1], v
[2], v
[3], v
[4], v
[5], v
[6], v
[7], v
[8]);
334 nvram_set("ct_tcp_timeout", buf
);
337 p
= nvram_safe_get("ct_udp_timeout");
338 if (sscanf(p
, "%u%u", &v
[0], &v
[1]) == 2) {
339 write_udp_timeout(NULL
, v
[0]);
340 write_udp_timeout("stream", v
[1]);
343 v
[0] = read_udp_timeout(NULL
);
344 v
[1] = read_udp_timeout("stream");
345 sprintf(buf
, "%u %u", v
[0], v
[1]);
346 nvram_set("ct_udp_timeout", buf
);
349 p
= nvram_safe_get("ct_timeout");
350 if (sscanf(p
, "%u%u", &v
[0], &v
[1]) == 2) {
351 write_ct_timeout("generic", NULL
, v
[0]);
352 write_ct_timeout("icmp", NULL
, v
[1]);
355 v
[0] = read_ct_timeout("generic", NULL
);
356 v
[1] = read_ct_timeout("icmp", NULL
);
357 sprintf(buf
, "%u %u", v
[0], v
[1]);
358 nvram_set("ct_timeout", buf
);
362 p
= nvram_safe_get("ct_hashsize");
365 f_write_string("/sys/module/nf_conntrack/parameters/hashsize", p
, 0, 0);
367 else if (f_read_string("/sys/module/nf_conntrack/parameters/hashsize", buf
, sizeof(buf
)) > 0) {
368 if (atoi(buf
) > 0) nvram_set("ct_hashsize", buf
);
372 p
= nvram_safe_get("ct_max");
375 f_write_string("/proc/sys/net/ipv4/netfilter/ip_conntrack_max", p
, 0, 0);
377 else if (f_read_string("/proc/sys/net/ipv4/netfilter/ip_conntrack_max", buf
, sizeof(buf
)) > 0) {
378 if (atoi(buf
) > 0) nvram_set("ct_max", buf
);
381 if (!nvram_match("nf_pptp", "0")) {
382 ct_modprobe("proto_gre");
386 ct_modprobe_r("pptp");
387 ct_modprobe_r("proto_gre");
390 if (!nvram_match("nf_h323", "0")) {
394 ct_modprobe_r("h323");
398 if (!nvram_match("nf_sip", "0")) {
402 ct_modprobe_r("sip");
406 if (!nvram_match("nf_rtsp", "0")) {
410 ct_modprobe_r("rtsp");
415 i
= nvram_get_int("ftp_port");
416 if (nvram_match("ftp_enable", "1") && (i
> 0) && (i
!= 21))
420 sprintf(ports
, "ports=21,%d", i
);
421 ct_modprobe("ftp", ports
);
425 if (!nvram_match("nf_ftp", "0")
427 || nvram_match("ftp_enable", "1") // !!TB - FTP Server
433 ct_modprobe_r("ftp");
438 void set_mac(const char *ifname
, const char *nvname
, int plus
)
445 if ((sfd
= socket(AF_INET
, SOCK_RAW
, IPPROTO_RAW
)) < 0) {
446 _dprintf("%s: %s %d\n", ifname
, __FUNCTION__
, __LINE__
);
450 strcpy(ifr
.ifr_name
, ifname
);
453 if (ioctl(sfd
, SIOCGIFFLAGS
, &ifr
) == 0) {
454 if ((up
= ifr
.ifr_flags
& IFF_UP
) != 0) {
455 ifr
.ifr_flags
&= ~IFF_UP
;
456 if (ioctl(sfd
, SIOCSIFFLAGS
, &ifr
) != 0) {
457 _dprintf("%s: %s %d\n", ifname
, __FUNCTION__
, __LINE__
);
462 _dprintf("%s: %s %d\n", ifname
, __FUNCTION__
, __LINE__
);
465 if (!ether_atoe(nvram_safe_get(nvname
), (unsigned char *)&ifr
.ifr_hwaddr
.sa_data
)) {
466 if (!ether_atoe(nvram_safe_get("et0macaddr"), (unsigned char *)&ifr
.ifr_hwaddr
.sa_data
)) {
468 // goofy et0macaddr, make something up
469 nvram_set("et0macaddr", "00:01:23:45:67:89");
470 ifr
.ifr_hwaddr
.sa_data
[0] = 0;
471 ifr
.ifr_hwaddr
.sa_data
[1] = 0x01;
472 ifr
.ifr_hwaddr
.sa_data
[2] = 0x23;
473 ifr
.ifr_hwaddr
.sa_data
[3] = 0x45;
474 ifr
.ifr_hwaddr
.sa_data
[4] = 0x67;
475 ifr
.ifr_hwaddr
.sa_data
[5] = 0x89;
479 for (j
= 5; j
>= 3; --j
) {
480 ifr
.ifr_hwaddr
.sa_data
[j
]++;
481 if (ifr
.ifr_hwaddr
.sa_data
[j
] != 0) break; // continue if rolled over
486 ifr
.ifr_hwaddr
.sa_family
= ARPHRD_ETHER
;
487 if (ioctl(sfd
, SIOCSIFHWADDR
, &ifr
) == -1) {
488 _dprintf("Error setting %s address\n", ifname
);
492 if (ioctl(sfd
, SIOCGIFFLAGS
, &ifr
) == 0) {
493 ifr
.ifr_flags
|= IFF_UP
|IFF_RUNNING
;
494 if (ioctl(sfd
, SIOCSIFFLAGS
, &ifr
) == -1) {
495 _dprintf("%s: %s %d\n", ifname
, __FUNCTION__
, __LINE__
);
499 _dprintf("%s: %s %d\n", ifname
, __FUNCTION__
, __LINE__
);
507 const char *default_wanif(void)
509 return ((strtoul(nvram_safe_get("boardflags"), NULL, 0) & BFL_ENETVLAN) ||
510 (check_hw_type() == HW_BCM4712)) ? "vlan1" : "eth1";
515 const char *default_wlif(void)
517 switch (check_hw_type()) {
519 case HW_BCM4704_BCM5325F:
520 case HW_BCM4704_BCM5325F_EWC:
528 int _vstrsep(char *buf
, const char *sep
, ...)
536 while ((p
= va_arg(ap
, char **)) != NULL
) {
537 if ((*p
= strsep(&buf
, sep
)) == NULL
) break;
544 void simple_unlock(const char *name
)
548 snprintf(fn
, sizeof(fn
), "/var/lock/%s.lock", name
);
549 f_write(fn
, NULL
, 0, 0, 0600);
552 void simple_lock(const char *name
)
557 n
= 5 + (getpid() % 10);
558 snprintf(fn
, sizeof(fn
), "/var/lock/%s.lock", name
);
559 while (unlink(fn
) != 0) {
561 syslog(LOG_DEBUG
, "Breaking %s", fn
);
568 void killall_tk(const char *name
)
572 if (killall(name
, SIGTERM
) == 0) {
574 while ((killall(name
, 0) == 0) && (n
-- > 0)) {
575 _dprintf("%s: waiting name=%s n=%d\n", __FUNCTION__
, name
, n
);
580 while ((killall(name
, SIGKILL
) == 0) && (n
-- > 0)) {
581 _dprintf("%s: SIGKILL name=%s n=%d\n", __FUNCTION__
, name
, n
);
588 long fappend(FILE *out
, const char *fname
)
595 if ((in
= fopen(fname
, "r")) == NULL
) return -1;
597 while ((n
= fread(buf
, 1, sizeof(buf
), in
)) > 0) {
598 if (fwrite(buf
, 1, n
, out
) != n
) {