From db503f9a45f2a765ef63834a2c9416ccf59385af Mon Sep 17 00:00:00 2001 From: Joszef Kadlecsik Date: Wed, 5 May 2004 10:10:33 +0000 Subject: Fabrice's time match update + Tom Eastep's conntrack mach fix applied (JK) --- extensions/libipt_conntrack.c | 2 +- extensions/libipt_time.c | 313 ++++++++++++++++++++++++++++++++++++------ extensions/libipt_time.man | 18 ++- 3 files changed, 286 insertions(+), 47 deletions(-) (limited to 'extensions') diff --git a/extensions/libipt_conntrack.c b/extensions/libipt_conntrack.c index 63b38e98..48c2f1dc 100644 --- a/extensions/libipt_conntrack.c +++ b/extensions/libipt_conntrack.c @@ -504,7 +504,7 @@ print(const struct ipt_ip *ip, /* Saves the matchinfo in parsable form to stdout. */ static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match) { - matchinfo_print(ip, match, 0, "--"); + matchinfo_print(ip, match, 1, "--"); } static diff --git a/extensions/libipt_time.c b/extensions/libipt_time.c index b59fa990..8b6077a6 100644 --- a/extensions/libipt_time.c +++ b/extensions/libipt_time.c @@ -18,10 +18,26 @@ 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", +" [ --timestart value ] [ --timestop value] [ --days listofdays ] [ --datestart value ] [ --datestop value ]\n" +" timestart value : HH:MM (default 00:00)\n" +" timestop value : HH:MM (default 23:59)\n" +" listofdays value: a list of days to apply\n" +" from Mon,Tue,Wed,Thu,Fri,Sat,Sun\n" +" Coma speparated, no space, case sensitive.\n" +" Defaults to all days.\n" +" datestart value : YYYY[:MM[:DD[:hh[:mm[:ss]]]]]\n" +" If any of month, day, hour, minute or second is\n" +" not specified, then defaults to their smallest\n" +" 1900 <= YYYY < 2037\n" +" 1 <= MM <= 12\n" +" 1 <= DD <= 31\n" +" 0 <= hh <= 23\n" +" 0 <= mm <= 59\n" +" 0 <= ss <= 59\n" +" datestop value : YYYY[:MM[:DD[:hh[:mm[:ss]]]]]\n" +" If the whole option is ommited, default to never stop\n" +" If any of month, day, hour, minute or second is\n" +" not specified, then default to their smallest\n", IPTABLES_VERSION); } @@ -29,6 +45,8 @@ static struct option opts[] = { { "timestart", 1, 0, '1' }, { "timestop", 1, 0, '2' }, { "days", 1, 0, '3'}, + { "datestart", 1, 0, '4' }, + { "datestop", 1, 0, '5' }, {0} }; @@ -36,9 +54,18 @@ static struct option opts[] = { static void init(struct ipt_entry_match *m, unsigned int *nfcache) { + struct ipt_time_info *info = (struct ipt_time_info *)m->data; + globaldays = 0; /* caching not yet implemented */ *nfcache |= NFC_UNKNOWN; - globaldays = 0; + /* By default, we match on everyday */ + info->days_match = 127; + /* By default, we match on every hour:min of the day */ + info->time_start = 0; + info->time_stop = 1439; /* (23*60+59 = 1439 */ + /* By default, we don't have any date-begin or date-end boundaries */ + info->date_start = 0; + info->date_stop = LONG_MAX; } /** @@ -78,36 +105,45 @@ split_time(char **part1, char **part2, const char *str_2_parse) return 1; } +static int +parse_number(char *str, int num_min, int num_max, int *number) +{ + /* if the number starts with 0, replace it with a space else + string_to_number() will interpret it as octal !! */ + if (strlen(str) == 0) + return 0; + + if ((str[0] == '0') && (str[1] != '\0')) + str[0] = ' '; + + return string_to_number(str, num_min, num_max, number); +} + static void -parse_time_string(unsigned int *hour, unsigned int *minute, const char *time) +parse_time_string(int *hour, int *minute, const char *time) { char *hours; char *minutes; - hours = (char *)malloc(3); minutes = (char *)malloc(3); - bzero((void *)hours, 3); - bzero((void *)minutes, 3); + memset(hours, 0, 3); + memset(minutes, 0, 3); - if (split_time(&hours, &minutes, time) == 1) + if (split_time((char **)&hours, (char **)&minutes, time) == 1) { - /* if the number starts with 0, replace it with a space else - this string_to_number will interpret it as octal !! */ - if ((hours[0] == '0') && (hours[1] != '\0')) - hours[0] = ' '; - if ((minutes[0] == '0') && (minutes[1] != '\0')) - minutes[0] = ' '; - - if((string_to_number(hours, 0, 23, hour) == -1) || - (string_to_number(minutes, 0, 59, minute) == -1)) { - *hour = *minute = (-1); + *hour = 0; + *minute = 0; + if ((parse_number((char *)hours, 0, 23, hour) != -1) && + (parse_number((char *)minutes, 0, 59, minute) != -1)) + { + free(hours); + free(minutes); + return; } } - if ((*hour != (-1)) && (*minute != (-1))) { - free(hours); - free(minutes); - return; - } + + free(hours); + free(minutes); /* If we are here, there was a problem ..*/ exit_error(PARAMETER_PROBLEM, @@ -161,10 +197,139 @@ parse_days_string(int *days, const char *daystring) } } +static int +parse_date_field(const char *str_to_parse, int str_to_parse_s, int start_pos, + char *dest, int *next_pos) +{ + unsigned char found_value = 0; + unsigned char found_column = 0; + int i; + + for (i=0; i<2; i++) + { + if ((i+start_pos) >= str_to_parse_s) /* don't exit boundaries of the string.. */ + break; + if (str_to_parse[i+start_pos] == ':') + found_column = 1; + else + { + found_value = 1; + dest[i] = str_to_parse[i+start_pos]; + } + } + if (found_value == 0) + return 0; + *next_pos = i + start_pos; + if (found_column == 0) + ++(*next_pos); + return 1; +} + +static int +split_date(char *year, char *month, char *day, + char *hour, char *minute, char *second, + const char *str_to_parse) +{ + int i; + unsigned char found_column = 0; + int str_to_parse_s = strlen(str_to_parse); + + /* Check the length of the string */ + if ((str_to_parse_s > 19) || /* YYYY:MM:DD:HH:MM:SS */ + (str_to_parse_s < 4)) /* YYYY*/ + return 0; + + /* Clear the buffers */ + memset(year, 0, 4); + memset(month, 0, 2); + memset(day, 0, 2); + memset(hour, 0, 2); + memset(minute, 0, 2); + memset(second, 0, 2); + + /* parse the year YYYY */ + found_column = 0; + for (i=0; i<5; i++) + { + if (i >= str_to_parse_s) + break; + if (str_to_parse[i] == ':') + { + found_column = 1; + break; + } + else + year[i] = str_to_parse[i]; + } + if (found_column == 1) + ++i; + + /* parse the month if it exists */ + if (! parse_date_field(str_to_parse, str_to_parse_s, i, month, &i)) + return 1; + + if (! parse_date_field(str_to_parse, str_to_parse_s, i, day, &i)) + return 1; + + if (! parse_date_field(str_to_parse, str_to_parse_s, i, hour, &i)) + return 1; + + if (! parse_date_field(str_to_parse, str_to_parse_s, i, minute, &i)) + return 1; + + parse_date_field(str_to_parse, str_to_parse_s, i, second, &i); + + /* if we are here, format should be ok. */ + return 1; +} + +static time_t +parse_date_string(const char *str_to_parse) +{ + char year[5]; + char month[3]; + char day[3]; + char hour[3]; + char minute[3]; + char second[3]; + struct tm t; + time_t temp_time; + + memset(year, 0, 5); + memset(month, 0, 3); + memset(day, 0, 3); + memset(hour, 0, 3); + memset(minute, 0, 3); + memset(second, 0, 3); + + if (split_date(year, month, day, hour, minute, second, str_to_parse) == 1) + { + memset((void *)&t, 0, sizeof(struct tm)); + t.tm_isdst = -1; + t.tm_mday = 1; + if (!((parse_number(year, 1900, 2037, &(t.tm_year)) == -1) || + (parse_number(month, 1, 12, &(t.tm_mon)) == -1) || + (parse_number(day, 1, 31, &(t.tm_mday)) == -1) || + (parse_number(hour, 0, 9999, &(t.tm_hour)) == -1) || + (parse_number(minute, 0, 59, &(t.tm_min)) == -1) || + (parse_number(second, 0, 59, &(t.tm_sec)) == -1))) + { + t.tm_year -= 1900; + --(t.tm_mon); + temp_time = mktime(&t); + if (temp_time != -1) + return temp_time; + } + } + exit_error(PARAMETER_PROBLEM, + "invalid date `%s' specified, should be YYYY[:MM[:DD[:hh[:mm[:ss]]]]] format", str_to_parse); +} + #define IPT_TIME_START 0x01 #define IPT_TIME_STOP 0x02 #define IPT_TIME_DAYS 0x04 - +#define IPT_DATE_START 0x08 +#define IPT_DATE_STOP 0x10 /* Function which parses command options; returns true if it ate an option */ @@ -176,6 +341,7 @@ parse(int c, char **argv, int invert, unsigned int *flags, { struct ipt_time_info *timeinfo = (struct ipt_time_info *)(*match)->data; int hours, minutes; + time_t temp_date; switch (c) { @@ -216,19 +382,43 @@ parse(int c, char **argv, int invert, unsigned int *flags, timeinfo->days_match = globaldays; *flags |= IPT_TIME_DAYS; break; + + /* datestart */ + case '4': + if (invert) + exit_error(PARAMETER_PROBLEM, + "unexpected '!' with --datestart"); + if (*flags & IPT_DATE_START) + exit_error(PARAMETER_PROBLEM, + "Can't specify --datestart twice"); + temp_date = parse_date_string(optarg); + timeinfo->date_start = temp_date; + *flags |= IPT_DATE_START; + break; + + /* datestop*/ + case '5': + if (invert) + exit_error(PARAMETER_PROBLEM, + "unexpected '!' with --datestop"); + if (*flags & IPT_DATE_STOP) + exit_error(PARAMETER_PROBLEM, + "Can't specify --datestop twice"); + temp_date = parse_date_string(optarg); + timeinfo->date_stop = temp_date; + *flags |= IPT_DATE_STOP; + break; default: return 0; } return 1; } -/* Final check; must have specified --timestart --timestop --days. */ +/* Final check */ 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'"); + /* Nothing to do */ } @@ -249,6 +439,7 @@ print_days(int daynum) ++nbdays; } } + printf(" "); } static void @@ -258,6 +449,22 @@ divide_time(int fulltime, int *hours, int *minutes) *minutes = fulltime % 60; } +static void +print_date(time_t date, char *command) +{ + /* If it's default value, don't print..*/ + if (((date == 0) || (date == LONG_MAX)) && (command != NULL)) + return; + struct tm *t; + t = localtime(&date); + if (command != NULL) + printf("%s %d:%d:%d:%d:%d:%d ", command, (t->tm_year + 1900), (t->tm_mon + 1), + t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); + else + printf("%d-%d-%d %d:%d:%d ", (t->tm_year + 1900), (t->tm_mon + 1), + t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); +} + /* Prints out the matchinfo. */ static void print(const struct ipt_ip *ip, @@ -269,11 +476,26 @@ print(const struct ipt_ip *ip, 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(" "); + printf("TIME "); + if (time->time_start != 0) + printf("from %d:%d ", hour_start, minute_start); + if (time->time_stop != 1439) /* 23*60+59 = 1439 */ + printf("to %d:%d ", hour_stop, minute_stop); + printf("on "); + if (time->days_match == 127) + printf("all days "); + else + print_days(time->days_match); + if (time->date_start != 0) + { + printf("starting from "); + print_date(time->date_start, NULL); + } + if (time->date_stop != LONG_MAX) + { + printf("until date "); + print_date(time->date_stop, NULL); + } } /* Saves the data in parsable form to stdout. */ @@ -285,11 +507,22 @@ save(const struct ipt_ip *ip, const struct ipt_entry_match *match) 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(" "); + if (time->time_start != 0) + printf("--timestart %.2d:%.2d ", + hour_start, minute_start); + + if (time->time_stop != 1439) /* 23*60+59 = 1439 */ + printf("--timestop %.2d:%.2d ", + hour_stop, minute_stop); + + if (time->days_match != 127) + { + printf("--days "); + print_days(time->days_match); + printf(" "); + } + print_date(time->date_start, "--datestart"); + print_date(time->date_stop, "--datestop"); } /* have to use offsetof() instead of IPT_ALIGN(), since kerneltime must not diff --git a/extensions/libipt_time.man b/extensions/libipt_time.man index 0871ecfa..94b40531 100644 --- a/extensions/libipt_time.man +++ b/extensions/libipt_time.man @@ -1,10 +1,16 @@ -This matches if the current time is within a given range. +This matches if the packet arrival time/date is within a given range. All options are facultative. .TP -.BI "--timestart " "value" -Match only if it is after `value' (Format: HH:MM). +.BI " --timestart " "value" +Match only if it is after `value' (Inclusive, format: HH:MM ; default 00:00). .TP -.BI "--timestop " "value" -Match only if it is before `value' (Format: HH:MM). +.BI "--timestop " "value" +Match only if it is before `value' (Inclusive, format: HH:MM ; default 23:59). .TP .BI "--days " "listofdays" -Match only if today is one of the given days. (Format: Mon,Tue,Wed,Thu,Fri) +Match only if today is one of the given days. (format: Mon,Tue,Wed,Thu,Fri,Sat,Sun ; default everyday) +.TP +.BI "--datestart " "date" +Match only if it is after `date' (Inclusive, format: YYYY[:MM[:DD[:hh[:mm[:ss]]]]] ; h,m,s start from 0 ; default to 1970) +.TP +.BI "--datestop " "date" +Match only if it is before `date' (Inclusive, format: YYYY[:MM[:DD[:hh[:mm[:ss]]]]] ; h,m,s start from 0 ; default to 2037) -- cgit v1.2.3