blob: 41faeb6128a6aaa23ef09232c3984a2d3134903f [file] [log] [blame]
Stephen Frost93c7e5a2001-11-08 22:35:03 +00001/* Shared library add-on to iptables to add recent matching support. */
Jan Engelhardt32b8e612010-07-23 21:16:14 +02002#include <stdbool.h>
Stephen Frost93c7e5a2001-11-08 22:35:03 +00003#include <stdio.h>
4#include <netdb.h>
5#include <string.h>
6#include <stdlib.h>
7#include <getopt.h>
8
Jan Engelhardtaf1660f2008-10-22 18:53:39 +02009#include <xtables.h>
10#include <linux/netfilter/xt_recent.h>
Harald Welte122e7c02003-03-30 20:26:42 +000011
Jan Engelhardt59d16402007-10-04 16:28:39 +000012static const struct option recent_opts[] = {
Jan Engelhardt32b8e612010-07-23 21:16:14 +020013 {.name = "set", .has_arg = false, .val = 201},
14 {.name = "rcheck", .has_arg = false, .val = 202},
15 {.name = "update", .has_arg = false, .val = 203},
16 {.name = "seconds", .has_arg = true, .val = 204},
17 {.name = "hitcount", .has_arg = true, .val = 205},
18 {.name = "remove", .has_arg = false, .val = 206},
19 {.name = "rttl", .has_arg = false, .val = 207},
20 {.name = "name", .has_arg = true, .val = 208},
21 {.name = "rsource", .has_arg = false, .val = 209},
22 {.name = "rdest", .has_arg = false, .val = 210},
23 XT_GETOPT_TABLEEND,
Stephen Frost27e1fa82003-04-14 13:33:15 +000024};
25
Jan Engelhardt59d16402007-10-04 16:28:39 +000026static void recent_help(void)
Stephen Frost93c7e5a2001-11-08 22:35:03 +000027{
28 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020029"recent match options:\n"
Stephen Frost93c7e5a2001-11-08 22:35:03 +000030"[!] --set Add source address to list, always matches.\n"
31"[!] --rcheck Match if source address in list.\n"
32"[!] --update Match if source address in list, also update last-seen time.\n"
33"[!] --remove Match if source address in list, also removes that address from list.\n"
34" --seconds seconds For check and update commands above.\n"
35" Specifies that the match will only occur if source address last seen within\n"
36" the last 'seconds' seconds.\n"
37" --hitcount hits For check and update commands above.\n"
38" Specifies that the match will only occur if source address seen hits times.\n"
Fabrice MARIEae31bb62002-06-14 07:38:16 +000039" May be used in conjunction with the seconds option.\n"
Stephen Frost4fce44c2002-02-04 11:58:22 +000040" --rttl For check and update commands above.\n"
41" Specifies that the match will only occur if the source address and the TTL\n"
42" match between this packet and the one which was set.\n"
43" Useful if you have problems with people spoofing their source address in order\n"
44" to DoS you via this module.\n"
Stephen Frost7fdbc952002-06-21 17:26:33 +000045" --name name Name of the recent list to be used. DEFAULT used if none given.\n"
Stephen Frost27e1fa82003-04-14 13:33:15 +000046" --rsource Match/Save the source address of each packet in the recent list table (default).\n"
47" --rdest Match/Save the destination address of each packet in the recent list table.\n"
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020048"xt_recent by: Stephen Frost <sfrost@snowman.net>. http://snowman.net/projects/ipt_recent/\n");
Stephen Frost93c7e5a2001-11-08 22:35:03 +000049}
Jan Engelhardtddac6c52008-09-01 14:22:19 +020050
Jan Engelhardt59d16402007-10-04 16:28:39 +000051static void recent_init(struct xt_entry_match *match)
Stephen Frost93c7e5a2001-11-08 22:35:03 +000052{
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020053 struct xt_recent_mtinfo *info = (void *)(match)->data;
Stephen Frost7fdbc952002-06-21 17:26:33 +000054
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020055 strncpy(info->name,"DEFAULT", XT_RECENT_NAME_LEN);
56 /* even though XT_RECENT_NAME_LEN is currently defined as 200,
Karsten Desler073df8f2004-01-31 15:33:55 +000057 * better be safe, than sorry */
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020058 info->name[XT_RECENT_NAME_LEN-1] = '\0';
59 info->side = XT_RECENT_SOURCE;
Stephen Frost93c7e5a2001-11-08 22:35:03 +000060}
61
Jan Engelhardt3c5d15c2008-08-04 12:52:27 +020062#define RECENT_CMDS \
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020063 (XT_RECENT_SET | XT_RECENT_CHECK | \
64 XT_RECENT_UPDATE | XT_RECENT_REMOVE)
Jan Engelhardt3c5d15c2008-08-04 12:52:27 +020065
Jan Engelhardt59d16402007-10-04 16:28:39 +000066static int recent_parse(int c, char **argv, int invert, unsigned int *flags,
67 const void *entry, struct xt_entry_match **match)
Stephen Frost93c7e5a2001-11-08 22:35:03 +000068{
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020069 struct xt_recent_mtinfo *info = (void *)(*match)->data;
70
Stephen Frost93c7e5a2001-11-08 22:35:03 +000071 switch (c) {
72 case 201:
Jan Engelhardt3c5d15c2008-08-04 12:52:27 +020073 if (*flags & RECENT_CMDS)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010074 xtables_error(PARAMETER_PROBLEM,
Stephen Frostd5903952003-03-03 07:24:27 +000075 "recent: only one of `--set', `--rcheck' "
Stephen Frost93c7e5a2001-11-08 22:35:03 +000076 "`--update' or `--remove' may be set");
Jan Engelhardtbf971282009-11-03 19:55:11 +010077 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020078 info->check_set |= XT_RECENT_SET;
Stephen Frost93c7e5a2001-11-08 22:35:03 +000079 if (invert) info->invert = 1;
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020080 *flags |= XT_RECENT_SET;
Stephen Frost93c7e5a2001-11-08 22:35:03 +000081 break;
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020082
Stephen Frost93c7e5a2001-11-08 22:35:03 +000083 case 202:
Jan Engelhardt3c5d15c2008-08-04 12:52:27 +020084 if (*flags & RECENT_CMDS)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010085 xtables_error(PARAMETER_PROBLEM,
Stephen Frostd5903952003-03-03 07:24:27 +000086 "recent: only one of `--set', `--rcheck' "
Stephen Frost93c7e5a2001-11-08 22:35:03 +000087 "`--update' or `--remove' may be set");
Jan Engelhardtbf971282009-11-03 19:55:11 +010088 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020089 info->check_set |= XT_RECENT_CHECK;
Stephen Frost93c7e5a2001-11-08 22:35:03 +000090 if(invert) info->invert = 1;
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020091 *flags |= XT_RECENT_CHECK;
Stephen Frost93c7e5a2001-11-08 22:35:03 +000092 break;
93
94 case 203:
Jan Engelhardt3c5d15c2008-08-04 12:52:27 +020095 if (*flags & RECENT_CMDS)
Jan Engelhardt1829ed42009-02-21 03:29:44 +010096 xtables_error(PARAMETER_PROBLEM,
Stephen Frostd5903952003-03-03 07:24:27 +000097 "recent: only one of `--set', `--rcheck' "
Stephen Frost93c7e5a2001-11-08 22:35:03 +000098 "`--update' or `--remove' may be set");
Jan Engelhardtbf971282009-11-03 19:55:11 +010099 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200100 info->check_set |= XT_RECENT_UPDATE;
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000101 if (invert) info->invert = 1;
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200102 *flags |= XT_RECENT_UPDATE;
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000103 break;
104
Jan Engelhardt6ce22ff2010-01-19 18:13:23 +0100105 case 204:
106 info->seconds = atoi(optarg);
107 break;
108
109 case 205:
110 info->hit_count = atoi(optarg);
111 break;
112
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000113 case 206:
Jan Engelhardt3c5d15c2008-08-04 12:52:27 +0200114 if (*flags & RECENT_CMDS)
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100115 xtables_error(PARAMETER_PROBLEM,
Stephen Frostd5903952003-03-03 07:24:27 +0000116 "recent: only one of `--set', `--rcheck' "
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000117 "`--update' or `--remove' may be set");
Jan Engelhardtbf971282009-11-03 19:55:11 +0100118 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200119 info->check_set |= XT_RECENT_REMOVE;
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000120 if (invert) info->invert = 1;
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200121 *flags |= XT_RECENT_REMOVE;
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000122 break;
123
Stephen Frost4fce44c2002-02-04 11:58:22 +0000124 case 207:
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200125 info->check_set |= XT_RECENT_TTL;
126 *flags |= XT_RECENT_TTL;
Stephen Frost4fce44c2002-02-04 11:58:22 +0000127 break;
128
129 case 208:
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200130 strncpy(info->name,optarg, XT_RECENT_NAME_LEN);
131 info->name[XT_RECENT_NAME_LEN-1] = '\0';
Stephen Frost4fce44c2002-02-04 11:58:22 +0000132 break;
133
Stephen Frost7fdbc952002-06-21 17:26:33 +0000134 case 209:
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200135 info->side = XT_RECENT_SOURCE;
Stephen Frost7fdbc952002-06-21 17:26:33 +0000136 break;
137
138 case 210:
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200139 info->side = XT_RECENT_DEST;
Stephen Frost7fdbc952002-06-21 17:26:33 +0000140 break;
141
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000142 default:
143 return 0;
144 }
Stephen Frost4fce44c2002-02-04 11:58:22 +0000145
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000146 return 1;
147}
148
Jan Engelhardt59d16402007-10-04 16:28:39 +0000149static void recent_check(unsigned int flags)
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000150{
Jan Engelhardt3c5d15c2008-08-04 12:52:27 +0200151 if (!(flags & RECENT_CMDS))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100152 xtables_error(PARAMETER_PROBLEM,
Stephen Frostd5903952003-03-03 07:24:27 +0000153 "recent: you must specify one of `--set', `--rcheck' "
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000154 "`--update' or `--remove'");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200155 if ((flags & XT_RECENT_TTL) &&
156 (flags & (XT_RECENT_SET | XT_RECENT_REMOVE)))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100157 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardt3c5d15c2008-08-04 12:52:27 +0200158 "recent: --rttl may only be used with --rcheck or "
159 "--update");
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000160}
161
Jan Engelhardt59d16402007-10-04 16:28:39 +0000162static void recent_print(const void *ip, const struct xt_entry_match *match,
163 int numeric)
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000164{
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200165 const struct xt_recent_mtinfo *info = (const void *)match->data;
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000166
Sven Strickroth0c1b7762003-06-01 10:11:43 +0000167 if (info->invert)
168 fputc('!', stdout);
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000169
170 printf("recent: ");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200171 if (info->check_set & XT_RECENT_SET)
172 printf("SET ");
173 if (info->check_set & XT_RECENT_CHECK)
174 printf("CHECK ");
175 if (info->check_set & XT_RECENT_UPDATE)
176 printf("UPDATE ");
177 if (info->check_set & XT_RECENT_REMOVE)
178 printf("REMOVE ");
Stephen Frost4fce44c2002-02-04 11:58:22 +0000179 if(info->seconds) printf("seconds: %d ",info->seconds);
180 if(info->hit_count) printf("hit_count: %d ",info->hit_count);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200181 if (info->check_set & XT_RECENT_TTL)
182 printf("TTL-Match ");
Stephen Frost7fdbc952002-06-21 17:26:33 +0000183 if(info->name) printf("name: %s ",info->name);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200184 if (info->side == XT_RECENT_SOURCE)
185 printf("side: source ");
186 if (info->side == XT_RECENT_DEST)
Jan Engelhardt204a2532010-03-17 20:20:02 +0100187 printf("side: dest ");
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000188}
189
Jan Engelhardt59d16402007-10-04 16:28:39 +0000190static void recent_save(const void *ip, const struct xt_entry_match *match)
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000191{
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200192 const struct xt_recent_mtinfo *info = (const void *)match->data;
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000193
Sven Strickroth0c1b7762003-06-01 10:11:43 +0000194 if (info->invert)
195 printf("! ");
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000196
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200197 if (info->check_set & XT_RECENT_SET)
198 printf("--set ");
199 if (info->check_set & XT_RECENT_CHECK)
200 printf("--rcheck ");
201 if (info->check_set & XT_RECENT_UPDATE)
202 printf("--update ");
203 if (info->check_set & XT_RECENT_REMOVE)
204 printf("--remove ");
Stephen Frostd5903952003-03-03 07:24:27 +0000205 if(info->seconds) printf("--seconds %d ",info->seconds);
206 if(info->hit_count) printf("--hitcount %d ",info->hit_count);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200207 if (info->check_set & XT_RECENT_TTL)
208 printf("--rttl ");
Stephen Frostd5903952003-03-03 07:24:27 +0000209 if(info->name) printf("--name %s ",info->name);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200210 if (info->side == XT_RECENT_SOURCE)
211 printf("--rsource ");
212 if (info->side == XT_RECENT_DEST)
213 printf("--rdest ");
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000214}
215
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200216static struct xtables_match recent_mt_reg = {
Stephen Frost27e1fa82003-04-14 13:33:15 +0000217 .name = "recent",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200218 .version = XTABLES_VERSION,
Jan Engelhardtc5e85732009-06-12 20:55:44 +0200219 .family = NFPROTO_UNSPEC,
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200220 .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
221 .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
Jan Engelhardt59d16402007-10-04 16:28:39 +0000222 .help = recent_help,
223 .init = recent_init,
224 .parse = recent_parse,
225 .final_check = recent_check,
226 .print = recent_print,
227 .save = recent_save,
228 .extra_opts = recent_opts,
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000229};
230
231void _init(void)
232{
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200233 xtables_register_match(&recent_mt_reg);
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000234}