4 Copyright (C) 2006-2009 Jonathan Zarate
14 static inline void unsched_restrictions(void)
16 eval("cru", "d", "rcheck");
19 inline void sched_restrictions(void)
24 static int in_sched(int now_mins
, int now_dow
, int sched_begin
, int sched_end
, int sched_dow
)
27 if ((sched_begin
< 0) || (sched_end
< 0)) {
28 return (sched_dow
& now_dow
) != 0;
32 if (sched_begin
< sched_end
) {
33 return (((sched_dow
& now_dow
) != 0) && (now_mins
>= sched_begin
) && (now_mins
< sched_end
));
36 // 15:00 - 01:00 = 15:00 Sun to 01:00 Mon
37 // 12:00 - 12:00 = 12:00 Sun to 12:00 Mon
39 if ((now_dow
& sched_dow
) != 0) {
40 if (now_mins
>= sched_begin
) return 1;
44 if (now_dow
== 1) now_dow
= (1 << 6);
47 if ((now_dow
& sched_dow
) != 0) {
48 if (now_mins
< sched_end
) return 1;
51 // printf("now_mins=%d sched_end=%d now_dow=%d sched_dow=%d\n", now_mins, sched_end, now_dow, sched_dow);
55 static int radio_on(int idx
, int unit
, int subunit
, void *param
)
57 return nvram_match(wl_nvname("radio", unit
, 0), "1");
60 int rcheck_main(int argc
, char *argv
[])
75 unsigned long long activated
;
86 if (!nvram_contains_word("log_events", "acre")) {
87 setlogmask(LOG_MASK(LOG_EMERG
)); // can't set to 0
90 simple_lock("restrictions");
94 if (!nvram_match("rrules_timewarn", "1")) {
95 nvram_set("rrules_timewarn", "1");
96 syslog(LOG_INFO
, "Time not yet set. Only \"all day, everyday\" restrictions will be activated.");
98 now_mins
= now_dow
= 0;
101 tms
= localtime(&now
);
102 now_dow
= 1 << tms
->tm_wday
;
103 now_mins
= (tms
->tm_hour
* 60) + tms
->tm_min
;
110 activated
= strtoull(nvram_safe_get("rrules_activated"), NULL
, 16);
112 radio
= foreach_wif(0, NULL
, radio_on
) ? -1 : -2;
113 for (nrule
= 0; nrule
< MAX_NRULES
; ++nrule
) {
114 sprintf(buf
, "rrule%d", nrule
);
115 if ((p
= nvram_get(buf
)) == NULL
) continue;
116 if (sscanf(p
, "%d|%d|%d|%d|%c", &n
, &sched_begin
, &sched_end
, &sched_dow
, &comp
) != 5) continue;
117 if (n
== 0) continue;
122 if ((sched_begin
>= 0) || (sched_end
>= 0) || (sched_dow
!= 0x7F)) continue;
126 insch
= in_sched(now_mins
, now_dow
, sched_begin
, sched_end
, sched_dow
);
130 if ((insch
) && (comp
!= '~'))
135 if ((insch
) == ((activated
& n
) != 0)) {
139 syslog(LOG_INFO
, "%sctivating rule %d", insch
? "A" : "Dea", nrule
);
142 if ((radio
!= 0) && (radio
!= -2)) radio
= !insch
;
145 sprintf(buf
, "r%s%02d", (comp
!= '|') ? "dev" : "res", nrule
);
147 r
= eval("iptables", "-D", "restrict", "-j", buf
);
149 // ignore error above (if any)
151 r
= eval("iptables", "-A", "restrict", "-j", buf
);
155 r6
= eval("ip6tables", "-D", "restrict", "-j", buf
);
156 if (ipv6_enabled()) {
158 // ignore error above (if any)
160 r6
= eval("ip6tables", "-A", "restrict", "-j", buf
);
167 syslog(LOG_ERR
, "Iptables: %sactivating chain \"%s\" failed. Retrying in 15 minutes.",
168 insch
? "" : "de", buf
);
173 if (insch
) activated
|= n
;
174 else activated
&= ~n
;
177 sprintf(buf
, "%llx", activated
);
178 nvram_set("rrules_activated", buf
);
181 if ((argc
!= 2) || (strcmp(argv
[1], "--cron") != 0)) {
182 eval("cru", "a", "rcheck", "*/15 * * * * rcheck --cron");
186 unsched_restrictions();
190 nvram_set("rrules_radio", radio
? "0" : "1");
192 // changed for dual radio support
193 _dprintf("%s: radio = %d\n", __FUNCTION__
, radio
);
194 eval("radio", radio
? "on" : "off");
196 if (get_radio() != radio
) {
197 _dprintf("%s: radio = %d\n", __FUNCTION__
, radio
);
198 eval("radio", radio
? "on" : "off");
201 _dprintf("%s: no radio change = %d\n", __FUNCTION__
, radio
);
207 allow_fastnat("restrictions", (ipt_active
== 0));
208 try_enabling_fastnat();
210 simple_unlock("restrictions");
214 void ipt_restrictions(void)
219 char *comps
, *matches
, *http
;
232 char *addr_type
, *addr
;
243 nvram_unset("rrules_timewarn");
244 nvram_set("rrules_radio", "-1");
245 unsched_restrictions();
247 for (nrule
= 0; nrule
< MAX_NRULES
; ++nrule
) {
248 sprintf(buf
, "rrule%d", nrule
);
249 if ((p
= nvram_get(buf
)) == NULL
) continue;
250 if (strlen(p
) >= sizeof(buf
)) continue;
253 if ((vstrsep(buf
, "|",
255 &p
, &p
, &p
, // time (ignored)
259 &p
// http file match
260 ) != 8) || (*q
!= '1')) continue;
263 if (comps
[0] == '~') {
264 // a wireless disable rule, skip
271 ip46t_write(":restrict - [0:0]\n");
274 ip6t_write("-A FORWARD -o %s -j restrict\n",
277 for (n
= 0; n
< wanfaces
.count
; ++n
) {
278 if (*(wanfaces
.iface
[n
].name
)) {
279 ipt_write("-A FORWARD -o %s -j restrict\n",
280 wanfaces
.iface
[n
].name
);
283 // Only mess with DNS requests that are coming in on INPUT
284 ip46t_write("-I INPUT 1 ! -i lo -p udp --dport 53 -j restrict\n");
287 sprintf(reschain
, "rres%02d", nrule
);
288 ip46t_write(":%s - [0:0]\n", reschain
);
292 while ((q
= strsep(&matches
, ">")) != NULL
) {
293 n
= vstrsep(q
, "<", &pproto
, &dir
, &pport
, &ipp2p
, &layer7
, &addr_type
, &addr
);
295 // fixup for backward compatibility
298 else if (n
!= 7) continue;
300 if ((*dir
!= 'a') && (*dir
!= 's') && (*dir
!= 'd') && (*dir
!= 'x')) continue;
303 if (!ipt_ipp2p(ipp2p
, app
)) {
304 if (ipt_layer7(layer7
, app
) == -1) continue;
307 v4v6_ok
= ((*app
) ? 0 : IPT_V6
) | IPT_V4
;
312 // dest ip/domain address
313 if ((*addr_type
== '1') || (*addr_type
== '2')) {
314 v4v6_ok
= ipt_addr(iptaddr
, sizeof(iptaddr
), addr
, (*addr_type
== '1') ? "dst" : "src", v4v6_ok
, (v4v6_ok
== IPT_V4
), "restrictions", NULL
);
325 proto
= atoi(pproto
);
327 // shortcut if any proto+any port
328 ip46t_flagged_write(v4v6_ok
, "-A %s %s %s -j %s\n", reschain
, iptaddr
, app
, chain_out_drop
);
331 else if ((proto
== 6) || (proto
== 17) || (proto
== -1)) {
332 if ((*dir
!= 'a') && (*pport
)) {
333 if ((*dir
== 'x') || (strchr(pport
, ','))) {
334 // use multiport for multiple ports or src-or-dst type matches
335 snprintf(ports
, sizeof(ports
), "-m multiport --%sports %s", (*dir
== 'x') ? "" : dir
, pport
);
338 // else, use built-in
339 snprintf(ports
, sizeof(ports
), "--%sport %s", dir
, pport
);
346 ip46t_flagged_write(v4v6_ok
, "-A %s -p tcp %s %s %s -j %s\n", reschain
, ports
, iptaddr
, app
, chain_out_drop
);
348 ip46t_flagged_write(v4v6_ok
, "-A %s -p udp %s %s %s -j %s\n", reschain
, ports
, iptaddr
, app
, chain_out_drop
);
351 ip46t_flagged_write(v4v6_ok
, "-A %s -p %d %s %s -j %s\n", reschain
, proto
, iptaddr
, app
, chain_out_drop
);
359 if ((*p
== '\t') || (*p
== '\r') || (*p
== '\n') || (*p
== '"')) *p
= ' ';
362 while ((n
= strlen(http
)) > 0) {
365 while ((p
> http
) && (*p
!= ' ')) --p
;
373 ip46t_write("-A %s -p tcp -m web --hore \"%s\" -j %s\n", reschain
, http
, chain_out_reject
);
376 if (p
== NULL
) break;
383 if (http_file
& 1) strcat(app
, ".ocx$ .cab$ ");
384 if (http_file
& 2) strcpy(app
, ".swf$ ");
385 if (http_file
& 4) strcat(app
, ".class$ .jar$");
387 ip46t_write("-A %s -p tcp -m multiport --dports %s -m web --path \"%s\" -j %s\n",
388 reschain
, nvram_safe_get("rrulewp"), app
, chain_out_reject
);
395 ip46t_write("-X %s\n", reschain
); // chain not needed
396 sprintf(nextchain
, "-j %s", chain_out_drop
);
399 sprintf(nextchain
, "-g %s", reschain
);
403 sprintf(devchain
, "rdev%02d", nrule
);
404 ip46t_write(":%s - [0:0]\n", devchain
);
405 while ((q
= strsep(&comps
, ">")) != NULL
) {
406 if (*q
== 0) continue;
412 v4v6_ok
= IPT_V6
| IPT_V4
;
416 if (sscanf(q
, "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx",
417 iptaddr
, iptaddr
, iptaddr
, iptaddr
, iptaddr
, iptaddr
) == 6) {
418 snprintf(iptaddr
, sizeof(iptaddr
), "-m mac --mac-source %s", q
);
421 v4v6_ok
= ipt_addr(iptaddr
, sizeof(iptaddr
), q
, "src", v4v6_ok
, (v4v6_ok
== IPT_V4
), "restrictions", "filtering");
425 ip46t_flagged_write(v4v6_ok
,
426 "-A %s %s %s\n", devchain
, iptaddr
, ex
? "-j RETURN" : nextchain
);
430 ip46t_write("-A %s %s\n", devchain
, nextchain
);
434 ip46t_write("-A %s -j %s\n", reschain
, chain_out_drop
);
438 nvram_set("rrules_activated", "0");