2 Description: EBTables time extension module for userspace.
3 Authors: Song Wang <songw@broadcom.com>, ported from netfilter/iptables
4 The following is the original disclaimer.
6 Shared library add-on to iptables to add TIME matching support.
15 #include "../include/ebtables_u.h"
16 #include <linux/netfilter_bridge/ebt_time.h>
19 static int globaldays;
21 /* Function which prints out usage message. */
27 " --timestart value --timestop value --days listofdays\n"
28 " timestart value : HH:MM\n"
29 " timestop value : HH:MM\n"
30 " listofdays value: a list of days to apply -> ie. Mon,Tue,Wed,Thu,Fri. Case sensitive\n");
33 static struct option opts[] = {
34 { "timestart", 1, 0, '1' },
35 { "timestop", 1, 0, '2' },
40 /* Initialize the match. */
42 init(struct ebt_entry_match *m)
48 string_to_number(const char *s, unsigned int min, unsigned int max,
54 /* Handle hex, octal, etc. */
56 number = strtol(s, &end, 0);
57 if (*end == '\0' && end != s) {
58 /* we parsed a number, let's see if we want this */
59 if (errno != ERANGE && min <= number && number <= max) {
68 * param: part1, a pointer on a string 2 chars maximum long string, that will contain the hours.
69 * param: part2, a pointer on a string 2 chars maximum long string, that will contain the minutes.
70 * param: str_2_parse, the string to parse.
71 * return: 1 if ok, 0 if error.
74 split_time(char **part1, char **part2, const char *str_2_parse)
76 unsigned short int i,j=0;
77 char *rpart1 = *part1;
78 char *rpart2 = *part2;
79 unsigned char found_column = 0;
81 /* Check the length of the string */
82 if (strlen(str_2_parse) > 5)
84 /* parse the first part until the ':' */
87 if (str_2_parse[i] == ':')
90 rpart1[i] = str_2_parse[i];
95 /* parse the second part */
96 for (; i<strlen(str_2_parse); i++)
98 rpart2[i-j] = str_2_parse[i];
100 /* if we are here, format should be ok. */
105 parse_time_string(unsigned int *hour, unsigned int *minute, const char *time)
110 hours = (char *)malloc(3);
111 minutes = (char *)malloc(3);
112 bzero((void *)hours, 3);
113 bzero((void *)minutes, 3);
115 if (split_time(&hours, &minutes, time) == 1)
117 /* if the number starts with 0, replace it with a space else
118 this string_to_number will interpret it as octal !! */
119 if ((hours[0] == '0') && (hours[1] != '\0'))
121 if ((minutes[0] == '0') && (minutes[1] != '\0'))
124 if((string_to_number(hours, 0, 23, hour) == -1) ||
125 (string_to_number(minutes, 0, 59, minute) == -1)) {
126 *hour = *minute = (-1);
129 if ((*hour != (-1)) && (*minute != (-1))) {
135 /* If we are here, there was a problem ..*/
136 print_error("invalid time %s specified, should be HH:MM format", time);
139 /* return 1->ok, return 0->error */
141 parse_day(int *days, int from, int to, const char *string)
144 char *days_str[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
145 unsigned short int days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
148 dayread = (char *)malloc(4);
150 if ((to-from) != 3) {
154 for (i=from; i<to; i++)
155 dayread[i-from] = string[i];
157 if (strcmp(dayread, days_str[i]) == 0)
159 *days |= days_of_week[i];
163 /* if we are here, we didn't read a valid day */
169 parse_days_string(int *days, const char *daystring)
173 //char *err = "invalid days specified, should be Sun,Mon,Tue... format";
175 len = strlen(daystring);
177 print_error("invalid days specified, should be Sun,Mon,Tue... format");
180 if (parse_day(days, i, i+3, daystring) == 0)
181 print_error("invalid days specified, should be Sun,Mon,Tue... format");
186 #define EBT_TIME_START 0x01
187 #define EBT_TIME_STOP 0x02
188 #define EBT_TIME_DAYS 0x04
191 /* Function which parses command options; returns true if it
194 parse(int c, char **argv, int argc,
195 const struct ebt_u_entry *entry,
196 unsigned int *flags, struct ebt_entry_match **match)
198 struct ebt_time_info *timeinfo = (struct ebt_time_info *)(*match)->data;
201 switch (c) /* c is the return value of getopt_long */
205 if (*flags & EBT_TIME_START)
206 print_error("Can't specify --timestart twice");
207 parse_time_string(&hours, &minutes, optarg);
208 timeinfo->time_start = (hours * 60) + minutes;
209 *flags |= EBT_TIME_START;
213 if (*flags & EBT_TIME_STOP)
214 print_error("Can't specify --timestop twice");
215 parse_time_string(&hours, &minutes, optarg);
216 timeinfo->time_stop = (hours * 60) + minutes;
217 *flags |= EBT_TIME_STOP;
222 if (*flags & EBT_TIME_DAYS)
223 print_error("Can't specify --days twice");
224 parse_days_string(&globaldays, optarg);
225 timeinfo->days_match = globaldays;
226 *flags |= EBT_TIME_DAYS;
231 /* default value if not specified */
232 if (!(*flags & EBT_TIME_START))
233 timeinfo->time_start = 0;
234 if (!(*flags & EBT_TIME_STOP))
235 timeinfo->time_stop = 1439; /* 23*60+59 = 1439*/
236 if (!(*flags & EBT_TIME_DAYS))
237 timeinfo->days_match = 0;
242 /* Final check; must have specified --timestart --timestop --days. */
244 final_check(const struct ebt_u_entry *entry,
245 const struct ebt_entry_match *match, const char *name,
246 unsigned int hookmask, unsigned int time)
248 struct ebt_time_info *timeinfo = (struct ebt_time_info *)match->data;
251 printf("start=%d,stop=%d,days=%d\n",
252 timeinfo->time_start,timeinfo->time_stop,timeinfo->days_match);
254 if (timeinfo->time_stop < timeinfo->time_start)
255 print_error("stop time can't be smaller than start time");
260 print_days(int daynum)
262 char *days[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
263 unsigned short int days_of_week[7] = {64, 32, 16, 8, 4, 2, 1};
264 unsigned short int i, nbdays=0;
266 for (i=0; i<7; i++) {
267 if ((days_of_week[i] & daynum) == days_of_week[i])
270 printf(",%s", days[i]);
272 printf("%s", days[i]);
279 divide_time(int fulltime, int *hours, int *minutes)
281 *hours = fulltime / 60;
282 *minutes = fulltime % 60;
285 /* Prints out the matchinfo. */
287 print(const struct ebt_u_entry *entry,
288 const struct ebt_entry_match *match)
290 struct ebt_time_info *time = ((struct ebt_time_info *)match->data);
291 int hour_start, hour_stop, minute_start, minute_stop;
293 divide_time(time->time_start, &hour_start, &minute_start);
294 divide_time(time->time_stop, &hour_stop, &minute_stop);
295 printf(" TIME from %d:%d to %d:%d on ",
296 hour_start, minute_start,
297 hour_stop, minute_stop);
298 print_days(time->days_match);
303 /* Saves the data in parsable form to stdout. */
305 save(const struct ipt_ip *ip, const struct ebt_entry_match *match)
307 struct ebt_time_info *time = ((struct ebt_time_info *)match->data);
308 int hour_start, hour_stop, minute_start, minute_stop;
310 divide_time(time->time_start, &hour_start, &minute_start);
311 divide_time(time->time_stop, &hour_stop, &minute_stop);
312 printf(" --timestart %.2d:%.2d --timestop %.2d:%.2d --days ",
313 hour_start, minute_start,
314 hour_stop, minute_stop);
315 print_days(time->days_match);
321 compare(const struct ebt_entry_match *m1, const struct ebt_entry_match *m2)
323 struct ebt_time_info *timeinfo1 = (struct ebt_time_info *)m1->data;
324 struct ebt_time_info *timeinfo2 = (struct ebt_time_info *)m2->data;
326 if (timeinfo1->days_match != timeinfo2->days_match)
328 if (timeinfo1->time_start != timeinfo2->time_start)
330 if (timeinfo1->time_stop != timeinfo2->time_stop)
336 struct ebt_u_match time_match
338 sizeof(struct ebt_time_info),
348 static void _init(void) __attribute((constructor));
351 register_match(&time_match);