/* Shared library add-on to iptables to add TIME matching support. */ #include #include #include #include #include #include #include #include static int globaldays; /* Function which prints out usage message. */ static void help(void) { printf( "TIME v%s options:\n" " --timestart value --timestop value --days listofdays\n" " timestart value : HH:MM\n" " timestop value : HH:MM\n" " listofdays value: a list of days to apply -> ie. Mon,Tue,Wed,Thu,Fri. Case sensitive\n", IPTABLES_VERSION); } static struct option opts[] = { { "timestart", 1, 0, '1' }, { "timestop", 1, 0, '2' }, { "days", 1, 0, '3'}, {0} }; /* Initialize the match. */ static void init(struct ipt_entry_match *m, unsigned int *nfcache) { /* caching not yet implemented */ *nfcache |= NFC_UNKNOWN; globaldays = 0; } /** * param: part1, a pointer on a string 2 chars maximum long string, that will contain the hours. * param: part2, a pointer on a string 2 chars maximum long string, that will contain the minutes. * param: str_2_parse, the string to parse. * return: 1 if ok, 0 if error. */ static int split_time(char **part1, char **part2, const char *str_2_parse) { unsigned short int i,j=0; char *rpart1 = *part1; char *rpart2 = *part2; unsigned char found_column = 0; /* Check the length of the string */ if (strlen(str_2_parse) > 5) return 0; /* parse the first part until the ':' */ for (i=0; i<2; i++) { if (str_2_parse[i] == ':') found_column = 1; else rpart1[i] = str_2_parse[i]; } if (!found_column) i++; j=i; /* parse the second part */ for (; iok, return 0->error */ static int parse_day(int *days, int from, int to, const char *string) { char *dayread; char *days_str[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; unsigned short int days_of_week[7] = {64, 32, 16, 8, 4, 2, 1}; unsigned int i; dayread = (char *)malloc(4); bzero(dayread, 4); if ((to-from) != 3) { free(dayread); return 0; } for (i=from; idata; int hours, minutes; switch (c) { /* timestart */ case '1': if (invert) exit_error(PARAMETER_PROBLEM, "unexpected '!' with --timestart"); if (*flags & IPT_TIME_START) exit_error(PARAMETER_PROBLEM, "Can't specify --timestart twice"); parse_time_string(&hours, &minutes, optarg); timeinfo->time_start = (hours * 60) + minutes; *flags |= IPT_TIME_START; break; /* timestop */ case '2': if (invert) exit_error(PARAMETER_PROBLEM, "unexpected '!' with --timestop"); if (*flags & IPT_TIME_STOP) exit_error(PARAMETER_PROBLEM, "Can't specify --timestop twice"); parse_time_string(&hours, &minutes, optarg); timeinfo->time_stop = (hours * 60) + minutes; *flags |= IPT_TIME_STOP; break; /* days */ case '3': if (invert) exit_error(PARAMETER_PROBLEM, "unexpected '!' with --days"); if (*flags & IPT_TIME_DAYS) exit_error(PARAMETER_PROBLEM, "Can't specify --days twice"); parse_days_string(&globaldays, optarg); timeinfo->days_match = globaldays; *flags |= IPT_TIME_DAYS; break; default: return 0; } return 1; } /* Final check; must have specified --timestart --timestop --days. */ static void final_check(unsigned int flags) { if (flags != (IPT_TIME_START | IPT_TIME_STOP | IPT_TIME_DAYS)) exit_error(PARAMETER_PROBLEM, "TIME match: You must specify `--timestart --timestop and --days'"); } static void print_days(int daynum) { char *days[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; unsigned short int days_of_week[7] = {64, 32, 16, 8, 4, 2, 1}; unsigned short int i, nbdays=0; for (i=0; i<7; i++) { if ((days_of_week[i] & daynum) == days_of_week[i]) { if (nbdays>0) printf(",%s", days[i]); else printf("%s", days[i]); ++nbdays; } } } static void divide_time(int fulltime, int *hours, int *minutes) { *hours = fulltime / 60; *minutes = fulltime % 60; } /* Prints out the matchinfo. */ static void print(const struct ipt_ip *ip, const struct ipt_entry_match *match, int numeric) { struct ipt_time_info *time = ((struct ipt_time_info *)match->data); int hour_start, hour_stop, minute_start, minute_stop; divide_time(time->time_start, &hour_start, &minute_start); divide_time(time->time_stop, &hour_stop, &minute_stop); printf(" TIME from %d:%d to %d:%d on ", hour_start, minute_start, hour_stop, minute_stop); print_days(time->days_match); printf(" "); } /* Saves the data in parsable form to stdout. */ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match) { struct ipt_time_info *time = ((struct ipt_time_info *)match->data); int hour_start, hour_stop, minute_start, minute_stop; divide_time(time->time_start, &hour_start, &minute_start); divide_time(time->time_stop, &hour_stop, &minute_stop); printf(" --timestart %.2d:%.2d --timestop %.2d:%.2d --days ", hour_start, minute_start, hour_stop, minute_stop); print_days(time->days_match); printf(" "); } static struct iptables_match timestruct = { NULL, "time", IPTABLES_VERSION, IPT_ALIGN(sizeof(struct ipt_time_info)), IPT_ALIGN(sizeof(struct ipt_time_info)), &help, &init, &parse, &final_check, &print, &save, opts }; void _init(void) { register_match(×truct); }