blob: 1e1a111f11fb496f2721e24b375099b6d228cf89 [file] [log] [blame]
Jan Engelhardt32b8e612010-07-23 21:16:14 +02001#include <stdbool.h>
Stephen Frost93c7e5a2001-11-08 22:35:03 +00002#include <stdio.h>
Stephen Frost93c7e5a2001-11-08 22:35:03 +00003#include <string.h>
Jan Engelhardtaf1660f2008-10-22 18:53:39 +02004#include <xtables.h>
5#include <linux/netfilter/xt_recent.h>
Harald Welte122e7c02003-03-30 20:26:42 +00006
Jan Engelhardt51a746e2011-05-04 12:30:15 +02007enum {
8 O_SET = 0,
9 O_RCHECK,
10 O_UPDATE,
11 O_REMOVE,
12 O_SECONDS,
13 O_HITCOUNT,
14 O_RTTL,
15 O_NAME,
16 O_RSOURCE,
17 O_RDEST,
18 F_SET = 1 << O_SET,
19 F_RCHECK = 1 << O_RCHECK,
20 F_UPDATE = 1 << O_UPDATE,
21 F_REMOVE = 1 << O_REMOVE,
22 F_ANY_OP = F_SET | F_RCHECK | F_UPDATE | F_REMOVE,
Stephen Frost27e1fa82003-04-14 13:33:15 +000023};
24
Jan Engelhardt51a746e2011-05-04 12:30:15 +020025#define s struct xt_recent_mtinfo
26static const struct xt_option_entry recent_opts[] = {
27 {.name = "set", .id = O_SET, .type = XTTYPE_NONE,
28 .excl = F_ANY_OP, .flags = XTOPT_INVERT},
29 {.name = "rcheck", .id = O_RCHECK, .type = XTTYPE_NONE,
30 .excl = F_ANY_OP, .flags = XTOPT_INVERT},
31 {.name = "update", .id = O_UPDATE, .type = XTTYPE_NONE,
32 .excl = F_ANY_OP, .flags = XTOPT_INVERT},
33 {.name = "remove", .id = O_REMOVE, .type = XTTYPE_NONE,
34 .excl = F_ANY_OP, .flags = XTOPT_INVERT},
35 {.name = "seconds", .id = O_SECONDS, .type = XTTYPE_UINT32,
36 .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds)},
37 {.name = "hitcount", .id = O_HITCOUNT, .type = XTTYPE_UINT32,
38 .flags = XTOPT_PUT, XTOPT_POINTER(s, hit_count)},
39 {.name = "rttl", .id = O_RTTL, .type = XTTYPE_NONE,
40 .excl = F_SET | F_REMOVE},
41 {.name = "name", .id = O_NAME, .type = XTTYPE_STRING,
42 .flags = XTOPT_PUT, XTOPT_POINTER(s, name)},
43 {.name = "rsource", .id = O_RSOURCE, .type = XTTYPE_NONE},
44 {.name = "rdest", .id = O_RDEST, .type = XTTYPE_NONE},
45 XTOPT_TABLEEND,
46};
47#undef s
48
Jan Engelhardt59d16402007-10-04 16:28:39 +000049static void recent_help(void)
Stephen Frost93c7e5a2001-11-08 22:35:03 +000050{
51 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020052"recent match options:\n"
Stephen Frost93c7e5a2001-11-08 22:35:03 +000053"[!] --set Add source address to list, always matches.\n"
54"[!] --rcheck Match if source address in list.\n"
55"[!] --update Match if source address in list, also update last-seen time.\n"
56"[!] --remove Match if source address in list, also removes that address from list.\n"
57" --seconds seconds For check and update commands above.\n"
58" Specifies that the match will only occur if source address last seen within\n"
59" the last 'seconds' seconds.\n"
60" --hitcount hits For check and update commands above.\n"
61" Specifies that the match will only occur if source address seen hits times.\n"
Fabrice MARIEae31bb62002-06-14 07:38:16 +000062" May be used in conjunction with the seconds option.\n"
Stephen Frost4fce44c2002-02-04 11:58:22 +000063" --rttl For check and update commands above.\n"
64" Specifies that the match will only occur if the source address and the TTL\n"
65" match between this packet and the one which was set.\n"
66" Useful if you have problems with people spoofing their source address in order\n"
67" to DoS you via this module.\n"
Stephen Frost7fdbc952002-06-21 17:26:33 +000068" --name name Name of the recent list to be used. DEFAULT used if none given.\n"
Stephen Frost27e1fa82003-04-14 13:33:15 +000069" --rsource Match/Save the source address of each packet in the recent list table (default).\n"
70" --rdest Match/Save the destination address of each packet in the recent list table.\n"
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020071"xt_recent by: Stephen Frost <sfrost@snowman.net>. http://snowman.net/projects/ipt_recent/\n");
Stephen Frost93c7e5a2001-11-08 22:35:03 +000072}
Jan Engelhardtddac6c52008-09-01 14:22:19 +020073
Jan Engelhardt59d16402007-10-04 16:28:39 +000074static void recent_init(struct xt_entry_match *match)
Stephen Frost93c7e5a2001-11-08 22:35:03 +000075{
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020076 struct xt_recent_mtinfo *info = (void *)(match)->data;
Stephen Frost7fdbc952002-06-21 17:26:33 +000077
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020078 strncpy(info->name,"DEFAULT", XT_RECENT_NAME_LEN);
79 /* even though XT_RECENT_NAME_LEN is currently defined as 200,
Karsten Desler073df8f2004-01-31 15:33:55 +000080 * better be safe, than sorry */
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020081 info->name[XT_RECENT_NAME_LEN-1] = '\0';
82 info->side = XT_RECENT_SOURCE;
Stephen Frost93c7e5a2001-11-08 22:35:03 +000083}
84
Jan Engelhardt51a746e2011-05-04 12:30:15 +020085static void recent_parse(struct xt_option_call *cb)
Stephen Frost93c7e5a2001-11-08 22:35:03 +000086{
Jan Engelhardt51a746e2011-05-04 12:30:15 +020087 struct xt_recent_mtinfo *info = cb->data;
Jan Engelhardtaf1660f2008-10-22 18:53:39 +020088
Jan Engelhardt51a746e2011-05-04 12:30:15 +020089 xtables_option_parse(cb);
90 switch (cb->entry->id) {
91 case O_SET:
92 info->check_set |= XT_RECENT_SET;
93 if (cb->invert)
94 info->invert = true;
95 break;
96 case O_RCHECK:
97 info->check_set |= XT_RECENT_CHECK;
98 if (cb->invert)
99 info->invert = true;
100 break;
101 case O_UPDATE:
102 info->check_set |= XT_RECENT_UPDATE;
103 if (cb->invert)
104 info->invert = true;
105 break;
106 case O_REMOVE:
107 info->check_set |= XT_RECENT_REMOVE;
108 if (cb->invert)
109 info->invert = true;
110 break;
111 case O_RTTL:
112 info->check_set |= XT_RECENT_TTL;
113 break;
114 case O_RSOURCE:
115 info->side = XT_RECENT_SOURCE;
116 break;
117 case O_RDEST:
118 info->side = XT_RECENT_DEST;
119 break;
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000120 }
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000121}
122
Jan Engelhardt51a746e2011-05-04 12:30:15 +0200123static void recent_check(struct xt_fcheck_call *cb)
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000124{
Jan Engelhardt51a746e2011-05-04 12:30:15 +0200125 if (!(cb->xflags & F_ANY_OP))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100126 xtables_error(PARAMETER_PROBLEM,
Stephen Frostd5903952003-03-03 07:24:27 +0000127 "recent: you must specify one of `--set', `--rcheck' "
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000128 "`--update' or `--remove'");
129}
130
Jan Engelhardt59d16402007-10-04 16:28:39 +0000131static void recent_print(const void *ip, const struct xt_entry_match *match,
132 int numeric)
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000133{
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200134 const struct xt_recent_mtinfo *info = (const void *)match->data;
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000135
Sven Strickroth0c1b7762003-06-01 10:11:43 +0000136 if (info->invert)
Jan Engelhardt73866352010-12-18 02:04:59 +0100137 printf(" !");
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000138
Jan Engelhardt73866352010-12-18 02:04:59 +0100139 printf(" recent:");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200140 if (info->check_set & XT_RECENT_SET)
Jan Engelhardt73866352010-12-18 02:04:59 +0100141 printf(" SET");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200142 if (info->check_set & XT_RECENT_CHECK)
Jan Engelhardt73866352010-12-18 02:04:59 +0100143 printf(" CHECK");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200144 if (info->check_set & XT_RECENT_UPDATE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100145 printf(" UPDATE");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200146 if (info->check_set & XT_RECENT_REMOVE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100147 printf(" REMOVE");
148 if(info->seconds) printf(" seconds: %d", info->seconds);
149 if(info->hit_count) printf(" hit_count: %d", info->hit_count);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200150 if (info->check_set & XT_RECENT_TTL)
Jan Engelhardt73866352010-12-18 02:04:59 +0100151 printf(" TTL-Match");
152 if(info->name) printf(" name: %s", info->name);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200153 if (info->side == XT_RECENT_SOURCE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100154 printf(" side: source");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200155 if (info->side == XT_RECENT_DEST)
Jan Engelhardt73866352010-12-18 02:04:59 +0100156 printf(" side: dest");
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000157}
158
Jan Engelhardt59d16402007-10-04 16:28:39 +0000159static void recent_save(const void *ip, const struct xt_entry_match *match)
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000160{
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200161 const struct xt_recent_mtinfo *info = (const void *)match->data;
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000162
Sven Strickroth0c1b7762003-06-01 10:11:43 +0000163 if (info->invert)
Jan Engelhardt73866352010-12-18 02:04:59 +0100164 printf(" !");
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000165
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200166 if (info->check_set & XT_RECENT_SET)
Jan Engelhardt73866352010-12-18 02:04:59 +0100167 printf(" --set");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200168 if (info->check_set & XT_RECENT_CHECK)
Jan Engelhardt73866352010-12-18 02:04:59 +0100169 printf(" --rcheck");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200170 if (info->check_set & XT_RECENT_UPDATE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100171 printf(" --update");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200172 if (info->check_set & XT_RECENT_REMOVE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100173 printf(" --remove");
174 if(info->seconds) printf(" --seconds %d", info->seconds);
175 if(info->hit_count) printf(" --hitcount %d", info->hit_count);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200176 if (info->check_set & XT_RECENT_TTL)
Jan Engelhardt73866352010-12-18 02:04:59 +0100177 printf(" --rttl");
178 if(info->name) printf(" --name %s",info->name);
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200179 if (info->side == XT_RECENT_SOURCE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100180 printf(" --rsource");
Jan Engelhardtaf1660f2008-10-22 18:53:39 +0200181 if (info->side == XT_RECENT_DEST)
Jan Engelhardt73866352010-12-18 02:04:59 +0100182 printf(" --rdest");
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000183}
184
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200185static struct xtables_match recent_mt_reg = {
Jan Engelhardte1df2212011-02-15 12:02:51 +0100186 .name = "recent",
187 .version = XTABLES_VERSION,
188 .family = NFPROTO_UNSPEC,
189 .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
190 .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
191 .help = recent_help,
192 .init = recent_init,
Jan Engelhardt51a746e2011-05-04 12:30:15 +0200193 .x6_parse = recent_parse,
194 .x6_fcheck = recent_check,
Jan Engelhardte1df2212011-02-15 12:02:51 +0100195 .print = recent_print,
196 .save = recent_save,
Jan Engelhardt51a746e2011-05-04 12:30:15 +0200197 .x6_options = recent_opts,
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000198};
199
200void _init(void)
201{
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +0200202 xtables_register_match(&recent_mt_reg);
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000203}