1 /* Shared library add-on to iptables to add recent matching support. */
9 #include <linux/netfilter_ipv4/ipt_recent.h>
11 /* Need these in order to not fail when compiling against an older kernel. */
13 #define RECENT_NAME "ipt_recent"
14 #endif /* RECENT_NAME */
17 #define RECENT_VER "unknown"
18 #endif /* RECENT_VER */
20 #ifndef IPT_RECENT_NAME_LEN
21 #define IPT_RECENT_NAME_LEN 200
22 #endif /* IPT_RECENT_NAME_LEN */
24 /* Options for this module */
25 static const struct option recent_opts[] = {
26 { .name = "set", .has_arg = 0, .val = 201 },
27 { .name = "rcheck", .has_arg = 0, .val = 202 },
28 { .name = "update", .has_arg = 0, .val = 203 },
29 { .name = "seconds", .has_arg = 1, .val = 204 },
30 { .name = "hitcount", .has_arg = 1, .val = 205 },
31 { .name = "remove", .has_arg = 0, .val = 206 },
32 { .name = "rttl", .has_arg = 0, .val = 207 },
33 { .name = "name", .has_arg = 1, .val = 208 },
34 { .name = "rsource", .has_arg = 0, .val = 209 },
35 { .name = "rdest", .has_arg = 0, .val = 210 },
39 /* Function which prints out usage message. */
40 static void recent_help(void)
43 "recent match options:\n"
44 "[!] --set Add source address to list, always matches.\n"
45 "[!] --rcheck Match if source address in list.\n"
46 "[!] --update Match if source address in list, also update last-seen time.\n"
47 "[!] --remove Match if source address in list, also removes that address from list.\n"
48 " --seconds seconds For check and update commands above.\n"
49 " Specifies that the match will only occur if source address last seen within\n"
50 " the last 'seconds' seconds.\n"
51 " --hitcount hits For check and update commands above.\n"
52 " Specifies that the match will only occur if source address seen hits times.\n"
53 " May be used in conjunction with the seconds option.\n"
54 " --rttl For check and update commands above.\n"
55 " Specifies that the match will only occur if the source address and the TTL\n"
56 " match between this packet and the one which was set.\n"
57 " Useful if you have problems with people spoofing their source address in order\n"
58 " to DoS you via this module.\n"
59 " --name name Name of the recent list to be used. DEFAULT used if none given.\n"
60 " --rsource Match/Save the source address of each packet in the recent list table (default).\n"
61 " --rdest Match/Save the destination address of each packet in the recent list table.\n"
62 RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>. http://snowman.net/projects/ipt_recent/\n");
65 /* Initialize the match. */
66 static void recent_init(struct xt_entry_match *match)
68 struct ipt_recent_info *info = (struct ipt_recent_info *)(match)->data;
71 strncpy(info->name,"DEFAULT",IPT_RECENT_NAME_LEN);
72 /* eventhough IPT_RECENT_NAME_LEN is currently defined as 200,
73 * better be safe, than sorry */
74 info->name[IPT_RECENT_NAME_LEN-1] = '\0';
75 info->side = IPT_RECENT_SOURCE;
78 /* Function which parses command options; returns true if it
80 static int recent_parse(int c, char **argv, int invert, unsigned int *flags,
81 const void *entry, struct xt_entry_match **match)
83 struct ipt_recent_info *info = (struct ipt_recent_info *)(*match)->data;
86 if (*flags) exit_error(PARAMETER_PROBLEM,
87 "recent: only one of `--set', `--rcheck' "
88 "`--update' or `--remove' may be set");
89 check_inverse(optarg, &invert, &optind, 0);
90 info->check_set |= IPT_RECENT_SET;
91 if (invert) info->invert = 1;
96 if (*flags) exit_error(PARAMETER_PROBLEM,
97 "recent: only one of `--set', `--rcheck' "
98 "`--update' or `--remove' may be set");
99 check_inverse(optarg, &invert, &optind, 0);
100 info->check_set |= IPT_RECENT_CHECK;
101 if(invert) info->invert = 1;
106 if (*flags) exit_error(PARAMETER_PROBLEM,
107 "recent: only one of `--set', `--rcheck' "
108 "`--update' or `--remove' may be set");
109 check_inverse(optarg, &invert, &optind, 0);
110 info->check_set |= IPT_RECENT_UPDATE;
111 if (invert) info->invert = 1;
116 if (*flags) exit_error(PARAMETER_PROBLEM,
117 "recent: only one of `--set', `--rcheck' "
118 "`--update' or `--remove' may be set");
119 check_inverse(optarg, &invert, &optind, 0);
120 info->check_set |= IPT_RECENT_REMOVE;
121 if (invert) info->invert = 1;
126 info->seconds = atoi(optarg);
130 info->hit_count = atoi(optarg);
134 info->check_set |= IPT_RECENT_TTL;
138 strncpy(info->name,optarg,IPT_RECENT_NAME_LEN);
139 info->name[IPT_RECENT_NAME_LEN-1] = '\0';
143 info->side = IPT_RECENT_SOURCE;
147 info->side = IPT_RECENT_DEST;
157 /* Final check; must have specified a specific option. */
158 static void recent_check(unsigned int flags)
162 exit_error(PARAMETER_PROBLEM,
163 "recent: you must specify one of `--set', `--rcheck' "
164 "`--update' or `--remove'");
167 /* Prints out the matchinfo. */
168 static void recent_print(const void *ip, const struct xt_entry_match *match,
171 struct ipt_recent_info *info = (struct ipt_recent_info *)match->data;
177 if(info->check_set & IPT_RECENT_SET) printf("SET ");
178 if(info->check_set & IPT_RECENT_CHECK) printf("CHECK ");
179 if(info->check_set & IPT_RECENT_UPDATE) printf("UPDATE ");
180 if(info->check_set & IPT_RECENT_REMOVE) printf("REMOVE ");
181 if(info->seconds) printf("seconds: %d ",info->seconds);
182 if(info->hit_count) printf("hit_count: %d ",info->hit_count);
183 if(info->check_set & IPT_RECENT_TTL) printf("TTL-Match ");
184 if(info->name) printf("name: %s ",info->name);
185 if(info->side == IPT_RECENT_SOURCE) printf("side: source ");
186 if(info->side == IPT_RECENT_DEST) printf("side: dest");
189 /* Saves the union ipt_matchinfo in parsable form to stdout. */
190 static void recent_save(const void *ip, const struct xt_entry_match *match)
192 struct ipt_recent_info *info = (struct ipt_recent_info *)match->data;
197 if(info->check_set & IPT_RECENT_SET) printf("--set ");
198 if(info->check_set & IPT_RECENT_CHECK) printf("--rcheck ");
199 if(info->check_set & IPT_RECENT_UPDATE) printf("--update ");
200 if(info->check_set & IPT_RECENT_REMOVE) printf("--remove ");
201 if(info->seconds) printf("--seconds %d ",info->seconds);
202 if(info->hit_count) printf("--hitcount %d ",info->hit_count);
203 if(info->check_set & IPT_RECENT_TTL) printf("--rttl ");
204 if(info->name) printf("--name %s ",info->name);
205 if(info->side == IPT_RECENT_SOURCE) printf("--rsource ");
206 if(info->side == IPT_RECENT_DEST) printf("--rdest ");
209 /* Structure for iptables to use to communicate with module */
210 static struct xtables_match recent_mt_reg = {
212 .version = XTABLES_VERSION,
214 .size = XT_ALIGN(sizeof(struct ipt_recent_info)),
215 .userspacesize = XT_ALIGN(sizeof(struct ipt_recent_info)),
218 .parse = recent_parse,
219 .final_check = recent_check,
220 .print = recent_print,
222 .extra_opts = recent_opts,
227 xtables_register_match(&recent_mt_reg);