4 Copyright (C) 2006-2009 Jonathan Zarate
15 static void unsched_restrictions(void)
17 system("cru d rcheck");
20 void sched_restrictions(void)
25 static int in_sched(int now_mins
, int now_dow
, int sched_begin
, int sched_end
, int sched_dow
)
28 if ((sched_begin
< 0) || (sched_end
< 0)) {
29 return (sched_dow
& now_dow
) != 0;
33 if (sched_begin
< sched_end
) {
34 return (((sched_dow
& now_dow
) != 0) && (now_mins
>= sched_begin
) && (now_mins
< sched_end
));
37 // 15:00 - 01:00 = 15:00 Sun to 01:00 Mon
38 // 12:00 - 12:00 = 12:00 Sun to 12:00 Mon
40 if ((now_dow
& sched_dow
) != 0) {
41 if (now_mins
>= sched_begin
) return 1;
45 if (now_dow
== 1) now_dow
= (1 << 6);
48 if ((now_dow
& sched_dow
) != 0) {
49 if (now_mins
< sched_end
) return 1;
52 // printf("now_mins=%d sched_end=%d now_dow=%d sched_dow=%d\n", now_mins, sched_end, now_dow, sched_dow);
57 int rcheck_main(int argc
, char *argv
[])
72 unsigned long long activated
;
77 if (!nvram_contains_word("log_events", "acre")) {
78 setlogmask(LOG_MASK(LOG_EMERG
)); // can't set to 0
81 simple_lock("restrictions");
85 if (!nvram_match("rrules_timewarn", "1")) {
86 nvram_set("rrules_timewarn", "1");
87 syslog(LOG_INFO
, "Time not yet set. Only \"all day, everyday\" restrictions will be activated.");
89 now_mins
= now_dow
= 0;
92 tms
= localtime(&now
);
93 now_dow
= 1 << tms
->tm_wday
;
94 now_mins
= (tms
->tm_hour
* 60) + tms
->tm_min
;
97 activated
= strtoull(nvram_safe_get("rrules_activated"), NULL
, 16);
99 radio
= nvram_match("wl_radio", "1") ? -1 : -2;
100 for (nrule
= 0; nrule
< MAX_NRULES
; ++nrule
) {
101 sprintf(buf
, "rrule%d", nrule
);
102 if ((p
= nvram_get(buf
)) == NULL
) continue;
103 if (sscanf(p
, "%d|%d|%d|%d|%c", &n
, &sched_begin
, &sched_end
, &sched_dow
, &comp
) != 5) continue;
104 if (n
== 0) continue;
109 if ((sched_begin
>= 0) || (sched_end
>= 0) || (sched_dow
!= 0x7F)) continue;
113 insch
= in_sched(now_mins
, now_dow
, sched_begin
, sched_end
, sched_dow
);
117 if ((insch
) == ((activated
& n
) != 0)) {
121 syslog(LOG_INFO
, "%sctivating rule %d", insch
? "A" : "Dea", nrule
);
124 if ((radio
!= 0) && (radio
!= -2)) radio
= !insch
;
127 sprintf(buf
, "r%s%02d", (comp
!= '|') ? "dev" : "res", nrule
);
129 r
= eval("iptables", "-D", "restrict", "-j", buf
);
131 // ignore error above (if any)
133 r
= eval("iptables", "-A", "restrict", "-j", buf
);
137 syslog(LOG_ERR
, "Iptables command failed. Retrying in 15 minutes.");
141 if (eval("iptables", insch ? "-A" : "-D", "restrict", "-j", buf) != 0) {
142 syslog(LOG_ERR, "iptables command failed");
148 if (insch
) activated
|= n
;
149 else activated
&= ~n
;
152 sprintf(buf
, "%llx", activated
);
153 nvram_set("rrules_activated", buf
);
156 if ((argc
!= 2) || (strcmp(argv
[1], "--cron") != 0)) {
157 system("cru a rcheck '*/15 * * * * rcheck --cron'");
161 unsched_restrictions();
165 nvram_set("rrules_radio", radio
? "0" : "1");
166 if (get_radio() != radio
) {
167 _dprintf("%s: radio = %d\n", __FUNCTION__
, radio
);
168 eval("radio", radio
? "on" : "off");
171 _dprintf("%s: no radio change = %d\n", __FUNCTION__
, radio
);
175 simple_unlock("restrictions");
179 void ipt_restrictions(void)
184 char *comps
, *matches
, *http
;
205 nvram_unset("rrules_timewarn");
206 nvram_set("rrules_radio", "-1");
207 unsched_restrictions();
209 for (nrule
= 0; nrule
< MAX_NRULES
; ++nrule
) {
210 sprintf(buf
, "rrule%d", nrule
);
211 if ((p
= nvram_get(buf
)) == NULL
) continue;
212 if (strlen(p
) >= sizeof(buf
)) continue;
215 if ((vstrsep(buf
, "|",
217 &p
, &p
, &p
, // time (ignored)
221 &p
// http file match
222 ) != 8) || (*q
!= '1')) continue;
225 if (comps
[0] == '~') {
226 // a wireless disable rule, skip
232 ipt_write(":restrict - [0:0]\n"
233 "-A FORWARD -o %s -j restrict\n", wanface
);
236 sprintf(reschain
, "rres%02d", nrule
);
237 ipt_write(":%s - [0:0]\n", reschain
);
243 proto<dir<port<ipp2p<layer7
259 while ((q
= strsep(&matches
, ">")) != NULL
) {
260 if (vstrsep(q
, "<", &pproto
, &dir
, &pport
, &ipp2p
, &layer7
) != 5) continue;
262 if ((*dir
!= 'a') && (*dir
!= 's') && (*dir
!= 'd') && (*dir
!= 'x')) continue;
263 if ((*dir
!= 'a') && (*pport
)) {
264 if ((*dir
== 'x') || (strchr(pport
, ','))) {
265 // use mport for multiple ports or src-or-dst type matches
266 snprintf(ports
, sizeof(ports
), "-m mport --%sports %s", (*dir
== 'x') ? "" : dir
, pport
);
269 // else, use built-in
270 snprintf(ports
, sizeof(ports
), "--%sport %s", dir
, pport
);
277 if (!ipt_ipp2p(ipp2p
, app
)) {
278 if (ipt_layer7(layer7
, app
) == -1) continue;
283 proto
= atoi(pproto
);
284 if ((*dir
== 'a') && (proto
== -1)) {
285 // shortcut if tcp+udp+any port
286 ipt_write("-A %s %s -j %s\n", reschain
, app
, chain_out_drop
);
291 ipt_write("-A %s -p %sp %s %s -j %s\n", reschain
, "tc", ports
, app
, chain_out_drop
);
293 ipt_write("-A %s -p %sp %s %s -j %s\n", reschain
, "ud", ports
, app
, chain_out_drop
);
300 if ((*p
== '\t') || (*p
== '\r') || (*p
== '\n') || (*p
== '"')) *p
= ' ';
303 while ((n
= strlen(http
)) > 0) {
306 while ((p
> http
) && (*p
!= ' ')) --p
;
314 ipt_write("-A %s -p tcp -m web --hore \"%s\" -j %s\n", reschain
, http
, chain_out_reject
);
317 if (p
== NULL
) break;
324 if (http_file
& 1) strcat(app
, ".ocx$ .cab$ ");
325 if (http_file
& 2) strcpy(app
, ".swf$ ");
326 if (http_file
& 4) strcat(app
, ".class$ .jar$");
328 ipt_write("-A %s -p tcp -m mport --dports %s -m web --path \"%s\" -j %s\n",
329 reschain
, nvram_safe_get("rrulewp"), app
, chain_out_reject
);
336 ipt_write("-X %s\n", reschain
); // chain not needed
337 sprintf(nextchain
, "-j %s", chain_out_drop
);
340 sprintf(nextchain
, "-g %s", reschain
);
344 sprintf(devchain
, "rdev%02d", nrule
);
345 ipt_write(":%s - [0:0]\n", devchain
);
346 while ((q
= strsep(&comps
, ">")) != NULL
) {
347 if (*q
== 0) continue;
352 if (strchr(q
, ':')) {
353 p
= "-m mac --mac-source";
355 else if (strchr(q
, '-')) {
356 p
= "-m iprange --src-range";
361 ipt_write("-A %s %s %s %s\n", devchain
, p
, q
, ex
? "-j RETURN" : nextchain
);
365 ipt_write("-A %s %s\n", devchain
, nextchain
);
369 ipt_write("-A %s -j %s\n", reschain
, chain_out_drop
);
373 nvram_set("rrules_activated", "0");
375 if (need_web
) modprobe("ipt_web");