blob: e4a7f4d4b6bb07b923cb7d48269ee6b158811d2f [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;
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000141 }
Stephen Frost4fce44c2002-02-04 11:58:22 +0000142
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000143 return 1;
144}
145
Jan Engelhardt59d16402007-10-04 16:28:39 +0000146static void recent_check(unsigned int flags)
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000147{
Jan Engelhardt3c5d15c2008-08-04 12:52:27 +0200148 if (!(flags & RECENT_CMDS))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100149 xtables_error(PARAMETER_PROBLEM,
Stephen Frostd5903952003-03-03 07:24:27 +0000150 "recent: you must specify one of `--set', `--rcheck' "
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000151 "`--update' or `--remove'");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200152 if ((flags & XT_RECENT_TTL) &&
153 (flags & (XT_RECENT_SET | XT_RECENT_REMOVE)))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100154 xtables_error(PARAMETER_PROBLEM,
Jan Engelhardt3c5d15c2008-08-04 12:52:27 +0200155 "recent: --rttl may only be used with --rcheck or "
156 "--update");
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000157}
158
Jan Engelhardt59d16402007-10-04 16:28:39 +0000159static void recent_print(const void *ip, const struct xt_entry_match *match,
160 int numeric)
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000161{
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200162 const struct xt_recent_mtinfo *info = (const void *)match->data;
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000163
Sven Strickroth0c1b7762003-06-01 10:11:43 +0000164 if (info->invert)
Jan Engelhardt73866352010-12-18 02:04:59 +0100165 printf(" !");
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000166
Jan Engelhardt73866352010-12-18 02:04:59 +0100167 printf(" recent:");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200168 if (info->check_set & XT_RECENT_SET)
Jan Engelhardt73866352010-12-18 02:04:59 +0100169 printf(" SET");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200170 if (info->check_set & XT_RECENT_CHECK)
Jan Engelhardt73866352010-12-18 02:04:59 +0100171 printf(" CHECK");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200172 if (info->check_set & XT_RECENT_UPDATE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100173 printf(" UPDATE");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200174 if (info->check_set & XT_RECENT_REMOVE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100175 printf(" REMOVE");
176 if(info->seconds) printf(" seconds: %d", info->seconds);
177 if(info->hit_count) printf(" hit_count: %d", info->hit_count);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200178 if (info->check_set & XT_RECENT_TTL)
Jan Engelhardt73866352010-12-18 02:04:59 +0100179 printf(" TTL-Match");
180 if(info->name) printf(" name: %s", info->name);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200181 if (info->side == XT_RECENT_SOURCE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100182 printf(" side: source");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200183 if (info->side == XT_RECENT_DEST)
Jan Engelhardt73866352010-12-18 02:04:59 +0100184 printf(" side: dest");
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000185}
186
Jan Engelhardt59d16402007-10-04 16:28:39 +0000187static void recent_save(const void *ip, const struct xt_entry_match *match)
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000188{
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200189 const struct xt_recent_mtinfo *info = (const void *)match->data;
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000190
Sven Strickroth0c1b7762003-06-01 10:11:43 +0000191 if (info->invert)
Jan Engelhardt73866352010-12-18 02:04:59 +0100192 printf(" !");
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000193
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200194 if (info->check_set & XT_RECENT_SET)
Jan Engelhardt73866352010-12-18 02:04:59 +0100195 printf(" --set");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200196 if (info->check_set & XT_RECENT_CHECK)
Jan Engelhardt73866352010-12-18 02:04:59 +0100197 printf(" --rcheck");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200198 if (info->check_set & XT_RECENT_UPDATE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100199 printf(" --update");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200200 if (info->check_set & XT_RECENT_REMOVE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100201 printf(" --remove");
202 if(info->seconds) printf(" --seconds %d", info->seconds);
203 if(info->hit_count) printf(" --hitcount %d", info->hit_count);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200204 if (info->check_set & XT_RECENT_TTL)
Jan Engelhardt73866352010-12-18 02:04:59 +0100205 printf(" --rttl");
206 if(info->name) printf(" --name %s",info->name);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200207 if (info->side == XT_RECENT_SOURCE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100208 printf(" --rsource");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200209 if (info->side == XT_RECENT_DEST)
Jan Engelhardt73866352010-12-18 02:04:59 +0100210 printf(" --rdest");
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000211}
212
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200213static struct xtables_match recent_mt_reg = {
Stephen Frost27e1fa82003-04-14 13:33:15 +0000214 .name = "recent",
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200215 .version = XTABLES_VERSION,
Jan Engelhardtc5e85732009-06-12 20:55:44 +0200216 .family = NFPROTO_UNSPEC,
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200217 .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
218 .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
Jan Engelhardt59d16402007-10-04 16:28:39 +0000219 .help = recent_help,
220 .init = recent_init,
221 .parse = recent_parse,
222 .final_check = recent_check,
223 .print = recent_print,
224 .save = recent_save,
225 .extra_opts = recent_opts,
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000226};
227
228void _init(void)
229{
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200230 xtables_register_match(&recent_mt_reg);
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000231}