1/* Shared library add-on to iptables to add TIME matching support. */ 2#include <stdio.h> 3#include <netdb.h> 4#include <string.h> 5#include <stdlib.h> 6#include <getopt.h> 7 8#include <iptables.h> 9#include <linux/netfilter_ipv4/ipt_time.h> 10#include <time.h> 11 12/* Function which prints out usage message. */ 13static void 14help(void) 15{ 16 printf( 17"TIME v%s options:\n" 18" --timestart value --timestop value --days listofdays\n" 19" timestart value : HH:MM:SS\n" 20" timestop value : HH:MM:SS\n" 21" listofdays value: a list of days to apply -> ie. Mon,Tue,Wed,Thu,Fri. Case sensitive\n", 22IPTABLES_VERSION); 23} 24 25static struct option opts[] = { 26 { "timestart", 1, 0, '1' }, 27 { "timestop", 1, 0, '2' }, 28 { "days", 1, 0, '3'}, 29 {0} 30}; 31 32/* Initialize the match. */ 33static void 34init(struct ipt_entry_match *m, unsigned int *nfcache) 35{ 36 /* caching not yet implemented */ 37 *nfcache |= NFC_UNKNOWN; 38} 39 40static int 41parse_time(const char *time) 42{ 43 int hours, minutes, seconds; 44 45 if (sscanf(time, "%d:%d:%d", &hours, &minutes, &seconds) == 3) 46 return (hours * 60 * 60 + minutes * 60 + seconds); 47 48 /* If we are here, there was a problem ..*/ 49 exit_error(PARAMETER_PROBLEM, 50 "invalid time `%s' specified, should be HH:MM:SS format", time); 51} 52 53static const char *days[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; 54 55static int 56parse_days(const char *string) 57{ 58 char *comma; 59 int i, mask = 0; 60 61 do { 62 for (i = 0; i < 7; i++) 63 if (!strncasecmp(string, days[i], 3)) 64 mask |= 1 << i; 65 comma = strchr(string, ','); 66 string = comma + 1; 67 } while (comma); 68 69 return mask; 70} 71 72#define IPT_TIME_START 0x01 73#define IPT_TIME_STOP 0x02 74#define IPT_TIME_DAYS 0x04 75 76 77/* Function which parses command options; returns true if it 78 ate an option */ 79static int 80parse(int c, char **argv, int invert, unsigned int *flags, 81 const struct ipt_entry *entry, 82 unsigned int *nfcache, 83 struct ipt_entry_match **match) 84{ 85 struct ipt_time_info *timeinfo = (struct ipt_time_info *)(*match)->data; 86 87 switch (c) 88 { 89 /* timestart */ 90 case '1': 91 if (invert) 92 exit_error(PARAMETER_PROBLEM, 93 "unexpected '!' with --timestart"); 94 if (*flags & IPT_TIME_START) 95 exit_error(PARAMETER_PROBLEM, 96 "Can't specify --timestart twice"); 97 timeinfo->time_start = parse_time(optarg); 98 *flags |= IPT_TIME_START; 99 break; 100 /* timestop */ 101 case '2': 102 if (invert) 103 exit_error(PARAMETER_PROBLEM, 104 "unexpected '!' with --timestop"); 105 if (*flags & IPT_TIME_STOP) 106 exit_error(PARAMETER_PROBLEM, 107 "Can't specify --timestop twice"); 108 timeinfo->time_stop = parse_time(optarg); 109 *flags |= IPT_TIME_STOP; 110 break; 111 112 /* days */ 113 case '3': 114 if (invert) 115 exit_error(PARAMETER_PROBLEM, 116 "unexpected '!' with --days"); 117 if (*flags & IPT_TIME_DAYS) 118 exit_error(PARAMETER_PROBLEM, 119 "Can't specify --days twice"); 120 timeinfo->days_match = parse_days(optarg); 121 *flags |= IPT_TIME_DAYS; 122 break; 123 default: 124 return 0; 125 } 126 return 1; 127} 128 129/* Final check; must have specified --timestart --timestop --days. */ 130static void 131final_check(unsigned int flags) 132{ 133 if (flags != (IPT_TIME_START | IPT_TIME_STOP | IPT_TIME_DAYS)) 134 exit_error(PARAMETER_PROBLEM, 135 "TIME match: You must specify `--timestart --timestop and --days'"); 136} 137 138static void 139print_days(const struct ipt_time_info *time) 140{ 141 int i; 142 char *sep = ""; 143 144 for (i = 0; i < 7; i++) { 145 if (time->days_match & (1 << i)) { 146 printf("%s%s", sep, days[i]); 147 sep = ","; 148 } 149 } 150} 151 152/* Prints out the matchinfo. */ 153static void 154print(const struct ipt_ip *ip, 155 const struct ipt_entry_match *match, 156 int numeric) 157{ 158 struct ipt_time_info *time = ((struct ipt_time_info *)match->data); 159 160 printf(" TIME from %02d:%02d:%02d to %02d:%02d:%02d on ", 161 time->time_start / (60 * 60), (time->time_start / 60) % 60, time->time_start % 60, 162 time->time_stop / (60 * 60), (time->time_stop / 60) % 60, time->time_stop % 60); 163 print_days(time); 164 printf(" "); 165} 166 167/* Saves the data in parsable form to stdout. */ 168static void 169save(const struct ipt_ip *ip, const struct ipt_entry_match *match) 170{ 171 struct ipt_time_info *time = ((struct ipt_time_info *)match->data); 172 173 printf(" --timestart %02d:%02d:%02d --timestop %02d:%02d:%02d --days ", 174 time->time_start / (60 * 60), (time->time_start / 60) % 60, time->time_start % 60, 175 time->time_stop / (60 * 60), (time->time_stop / 60) % 60, time->time_stop % 60); 176 print_days(time); 177 printf(" "); 178} 179 180static 181struct iptables_match timestruct 182= { NULL, 183 "time", 184 IPTABLES_VERSION, 185 IPT_ALIGN(sizeof(struct ipt_time_info)), 186 IPT_ALIGN(sizeof(struct ipt_time_info)), 187 &help, 188 &init, 189 &parse, 190 &final_check, 191 &print, 192 &save, 193 opts 194}; 195 196void _init(void) 197{ 198 register_match(×truct); 199} 200