Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

netfilter: xt_time: add support to ignore day transition

Currently, if you want to do something like:
"match Monday, starting 23:00, for two hours"
You need two rules, one for Mon 23:00 to 0:00 and one for Tue 0:00-1:00.

The rule: --weekdays Mo --timestart 23:00 --timestop 01:00

looks correct, but it will first match on monday from midnight to 1 a.m.
and then again for another hour from 23:00 onwards.

This permits userspace to explicitly ignore the day transition and
match for a single, continuous time period instead.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

authored by

Florian Westphal and committed by
Pablo Neira Ayuso
54eb3df3 3e0304a5

+28 -1
+5
include/linux/netfilter/xt_time.h
··· 17 17 /* Match against local time (instead of UTC) */ 18 18 XT_TIME_LOCAL_TZ = 1 << 0, 19 19 20 + /* treat timestart > timestop (e.g. 23:00-01:00) as single period */ 21 + XT_TIME_CONTIGUOUS = 1 << 1, 22 + 20 23 /* Shortcuts */ 21 24 XT_TIME_ALL_MONTHDAYS = 0xFFFFFFFE, 22 25 XT_TIME_ALL_WEEKDAYS = 0xFE, 23 26 XT_TIME_MIN_DAYTIME = 0, 24 27 XT_TIME_MAX_DAYTIME = 24 * 60 * 60 - 1, 25 28 }; 29 + 30 + #define XT_TIME_ALL_FLAGS (XT_TIME_LOCAL_TZ|XT_TIME_CONTIGUOUS) 26 31 27 32 #endif /* _XT_TIME_H */
+23 -1
net/netfilter/xt_time.c
··· 42 42 */ 43 43 enum { 44 44 DSE_FIRST = 2039, 45 + SECONDS_PER_DAY = 86400, 45 46 }; 46 47 static const u_int16_t days_since_epoch[] = { 47 48 /* 2039 - 2030 */ ··· 79 78 unsigned int v, w; 80 79 81 80 /* Each day has 86400s, so finding the hour/minute is actually easy. */ 82 - v = time % 86400; 81 + v = time % SECONDS_PER_DAY; 83 82 r->second = v % 60; 84 83 w = v / 60; 85 84 r->minute = w % 60; ··· 200 199 if (packet_time < info->daytime_start && 201 200 packet_time > info->daytime_stop) 202 201 return false; 202 + 203 + /** if user asked to ignore 'next day', then e.g. 204 + * '1 PM Wed, August 1st' should be treated 205 + * like 'Tue 1 PM July 31st'. 206 + * 207 + * This also causes 208 + * 'Monday, "23:00 to 01:00", to match for 2 hours, starting 209 + * Monday 23:00 to Tuesday 01:00. 210 + */ 211 + if ((info->flags & XT_TIME_CONTIGUOUS) && 212 + packet_time <= info->daytime_stop) 213 + stamp -= SECONDS_PER_DAY; 203 214 } 204 215 205 216 localtime_2(&current_time, stamp); ··· 239 226 "stop time greater than 23:59:59\n"); 240 227 return -EDOM; 241 228 } 229 + 230 + if (info->flags & ~XT_TIME_ALL_FLAGS) { 231 + pr_info("unknown flags 0x%x\n", info->flags & ~XT_TIME_ALL_FLAGS); 232 + return -EINVAL; 233 + } 234 + 235 + if ((info->flags & XT_TIME_CONTIGUOUS) && 236 + info->daytime_start < info->daytime_stop) 237 + return -EINVAL; 242 238 243 239 return 0; 244 240 }