4 Copyright (C) 2006-2009 Jonathan Zarate
5 Portions rebuild by victek@tomato.raf, 2013. String chain restriction
15 static inline 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);
56 static int radio_on(int idx
, int unit
, int subunit
, void *param
)
58 return nvram_match(wl_nvname("radio", unit
, 0), "1");
61 int rcheck_main(int argc
, char *argv
[])
76 unsigned long long activated
;
87 if (!nvram_contains_word("log_events", "acre")) {
88 setlogmask(LOG_MASK(LOG_EMERG
)); // can't set to 0
91 simple_lock("restrictions");
95 if (!nvram_match("rrules_timewarn", "1")) {
96 nvram_set("rrules_timewarn", "1");
97 syslog(LOG_INFO
, "Time not yet set. Only \"all day, everyday\" restrictions will be activated.");
99 now_mins
= now_dow
= 0;
102 tms
= localtime(&now
);
103 now_dow
= 1 << tms
->tm_wday
;
104 now_mins
= (tms
->tm_hour
* 60) + tms
->tm_min
;
111 activated
= strtoull(nvram_safe_get("rrules_activated"), NULL
, 16);
113 radio
= foreach_wif(0, NULL
, radio_on
) ? -1 : -2;
114 for (nrule
= 0; nrule
< MAX_NRULES
; ++nrule
) {
115 sprintf(buf
, "rrule%d", nrule
);
116 if ((p
= nvram_get(buf
)) == NULL
) continue;
117 if (sscanf(p
, "%d|%d|%d|%d|%c", &n
, &sched_begin
, &sched_end
, &sched_dow
, &comp
) != 5) continue;
118 if (n
== 0) continue;
123 if ((sched_begin
>= 0) || (sched_end
>= 0) || (sched_dow
!= 0x7F)) continue;
127 insch
= in_sched(now_mins
, now_dow
, sched_begin
, sched_end
, sched_dow
);
131 if ((insch
) && (comp
!= '~'))
136 if ((insch
) == ((activated
& n
) != 0)) {
140 syslog(LOG_INFO
, "%sctivating rule %d", insch
? "A" : "Dea", nrule
);
143 if ((radio
!= 0) && (radio
!= -2)) radio
= !insch
;
146 sprintf(buf
, "r%s%02d", (comp
!= '|') ? "dev" : "res", nrule
);
148 r
= eval("iptables", "-D", "restrict", "-j", buf
);
150 // ignore error above (if any)
152 r
= eval("iptables", "-A", "restrict", "-j", buf
);
156 r6
= eval("ip6tables", "-D", "restrict", "-j", buf
);
157 if (ipv6_enabled()) {
159 // ignore error above (if any)
161 r6
= eval("ip6tables", "-A", "restrict", "-j", buf
);
168 syslog(LOG_ERR
, "Iptables: %sactivating chain \"%s\" failed. Retrying in 15 minutes.",
169 insch
? "" : "de", buf
);
174 if (insch
) activated
|= n
;
175 else activated
&= ~n
;
178 sprintf(buf
, "%llx", activated
);
179 nvram_set("rrules_activated", buf
);
182 if ((argc
!= 2) || (strcmp(argv
[1], "--cron") != 0)) {
183 system("cru a rcheck '*/15 * * * * rcheck --cron'");
187 unsched_restrictions();
191 nvram_set("rrules_radio", radio
? "0" : "1");
193 // changed for dual radio support
194 _dprintf("%s: radio = %d\n", __FUNCTION__
, radio
);
195 eval("radio", radio
? "on" : "off");
197 if (get_radio() != radio
) {
198 _dprintf("%s: radio = %d\n", __FUNCTION__
, radio
);
199 eval("radio", radio
? "on" : "off");
202 _dprintf("%s: no radio change = %d\n", __FUNCTION__
, radio
);
208 allow_fastnat("restrictions", (ipt_active
== 0));
209 try_enabling_fastnat();
211 simple_unlock("restrictions");
215 void ipt_restrictions(void)
220 char *comps
, *matches
, *http
;
234 char *addr_type
, *addr
;
245 nvram_unset("rrules_timewarn");
246 nvram_set("rrules_radio", "-1");
247 unsched_restrictions();
249 for (nrule
= 0; nrule
< MAX_NRULES
; ++nrule
) {
250 sprintf(buf
, "rrule%d", nrule
);
251 if ((p
= nvram_get(buf
)) == NULL
) continue;
252 if (strlen(p
) >= sizeof(buf
)) continue;
255 if ((vstrsep(buf
, "|",
257 &p
, &p
, &p
, // time (ignored)
261 &p
// http file match
262 ) != 8) || (*q
!= '1')) continue;
265 if (comps
[0] == '~') {
266 // a wireless disable rule, skip
273 ip46t_write(":restrict - [0:0]\n");
276 ip6t_write("-A FORWARD -o %s -j restrict\n",
279 for (n
= 0; n
< wanfaces
.count
; ++n
) {
280 if (*(wanfaces
.iface
[n
].name
)) {
281 ipt_write("-A FORWARD -o %s -j restrict\n",
282 wanfaces
.iface
[n
].name
);
287 sprintf(reschain
, "rres%02d", nrule
);
288 ip46t_write(":%s - [0:0]\n", reschain
);
294 proto<dir<port<ipp2p<layer7[<addr_type<addr]
301 if proto == -1,tcp,udp:
307 port # if proto == -1,tcp,udp
320 while ((q
= strsep(&matches
, ">")) != NULL
) {
321 n
= vstrsep(q
, "<", &pproto
, &dir
, &pport
, &ipp2p
, &layer7
, &addr_type
, &addr
);
323 // fixup for backward compatibility
326 else if (n
!= 7) continue;
328 if ((*dir
!= 'a') && (*dir
!= 's') && (*dir
!= 'd') && (*dir
!= 'x')) continue;
331 if (!ipt_ipp2p(ipp2p
, app
)) {
332 if (ipt_layer7(layer7
, app
) == -1) continue;
335 v4v6_ok
= ((*app
) ? 0 : IPT_V6
) | IPT_V4
;
340 // dest ip/domain address
341 if ((*addr_type
== '1') || (*addr_type
== '2')) {
342 v4v6_ok
= ipt_addr(iptaddr
, sizeof(iptaddr
), addr
, (*addr_type
== '1') ? "dst" : "src", v4v6_ok
, (v4v6_ok
== IPT_V4
), "restrictions", NULL
);
353 proto
= atoi(pproto
);
355 // shortcut if any proto+any port
356 ip46t_flagged_write(v4v6_ok
, "-A %s %s %s -j %s\n", reschain
, iptaddr
, app
, chain_out_drop
);
359 else if ((proto
== 6) || (proto
== 17) || (proto
== -1)) {
360 if ((*dir
!= 'a') && (*pport
)) {
361 if ((*dir
== 'x') || (strchr(pport
, ','))) {
362 // use multiport for multiple ports or src-or-dst type matches
363 snprintf(ports
, sizeof(ports
), "-m multiport --%sports %s", (*dir
== 'x') ? "" : dir
, pport
);
366 // else, use built-in
367 snprintf(ports
, sizeof(ports
), "--%sport %s", dir
, pport
);
374 ip46t_flagged_write(v4v6_ok
, "-A %s -p tcp %s %s %s -j %s\n", reschain
, ports
, iptaddr
, app
, chain_out_drop
);
376 ip46t_flagged_write(v4v6_ok
, "-A %s -p udp %s %s %s -j %s\n", reschain
, ports
, iptaddr
, app
, chain_out_drop
);
379 ip46t_flagged_write(v4v6_ok
, "-A %s -p %d %s %s -j %s\n", reschain
, proto
, iptaddr
, app
, chain_out_drop
);
383 // Build chain to perform string matching
384 sprintf(strchain
, "rstr%02d", nrule
);
385 ip46t_write(":%s - [0:0]\n", strchain
);
387 // Multiport match for ports 53,80,443 goto strchain
388 ip46t_write("-A %s -p tcp -m multiport --dports 53,80,443 -j %s\n", reschain
, strchain
);
389 ip46t_write("-A %s -p udp --dport 53 -j %s\n", reschain
, strchain
);
393 if ((*p
== '\t') || (*p
== '\r') || (*p
== '\n') || (*p
== '"')) *p
= ' ';
396 while ((n
= strlen(http
)) > 0) {
399 while ((p
> http
) && (*p
!= ' ')) --p
;
408 // Trim trailing whitespace from http
409 char *p2
= http
+ strlen(http
) - 1;
415 // Split the string delimited by whitespace. Each substring should be a new iptables entry.
417 p2
= strtok(http
, delim
);
420 ip46t_write("-I %s 1 -p tcp -m string --string \"%s\" --algo bm --from 1 --to 600 -j %s\n", strchain
, p2
, chain_out_reject
);
421 ip46t_write("-I %s 1 -p udp -m string --string \"%s\" --algo bm --from 1 --to 600 -j REJECT\n", strchain
, p2
);
422 p2
= strtok(NULL
, delim
);
427 if (p
== NULL
) break;
434 if (http_file
& 1) strcat(app
, ".ocx$ .cab$ ");
435 if (http_file
& 2) strcpy(app
, ".swf$ ");
436 if (http_file
& 4) strcat(app
, ".class$ .jar$");
438 ip46t_write("-A %s -p tcp -m multiport --dports %s -m web --path \"%s\" -j %s\n",
439 reschain
, nvram_safe_get("rrulewp"), app
, chain_out_reject
);
446 ip46t_write("-F %s\n", reschain
); // https://github.com/ReliefLabs/EasyTomato/
447 ip46t_write("-X %s\n", reschain
); // chain not needed
448 sprintf(nextchain
, "-j %s", chain_out_drop
);
451 sprintf(nextchain
, "-g %s", reschain
);
455 sprintf(devchain
, "rdev%02d", nrule
);
456 ip46t_write(":%s - [0:0]\n", devchain
);
457 while ((q
= strsep(&comps
, ">")) != NULL
) {
458 if (*q
== 0) continue;
464 v4v6_ok
= IPT_V6
| IPT_V4
;
468 if (sscanf(q
, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
469 iptaddr
, iptaddr
, iptaddr
, iptaddr
, iptaddr
, iptaddr
) == 6) {
470 snprintf(iptaddr
, sizeof(iptaddr
), "-m mac --mac-source %s", q
);
473 v4v6_ok
= ipt_addr(iptaddr
, sizeof(iptaddr
), q
, "src", v4v6_ok
, (v4v6_ok
== IPT_V4
), "restrictions", "filtering");
477 ip46t_flagged_write(v4v6_ok
,
478 "-A %s %s %s\n", devchain
, iptaddr
, ex
? "-j RETURN" : nextchain
);
482 ip46t_write("-A %s %s\n", devchain
, nextchain
);
486 ip46t_write("-A %s -j %s\n", reschain
, chain_out_drop
);
490 nvram_set("rrules_activated", "0");