• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdbool.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <xtables.h>
5 #include <linux/netfilter/xt_recent.h>
6 
7 enum {
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,
23 };
24 
25 #define s struct xt_recent_mtinfo
26 static 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 
recent_help(void)49 static void recent_help(void)
50 {
51 	printf(
52 "recent match options:\n"
53 "[!] --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"
62 "                                May be used in conjunction with the seconds option.\n"
63 "    --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"
68 "    --name name                 Name of the recent list to be used.  DEFAULT used if none given.\n"
69 "    --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"
71 "xt_recent by: Stephen Frost <sfrost@snowman.net>.  http://snowman.net/projects/ipt_recent/\n");
72 }
73 
recent_init(struct xt_entry_match * match)74 static void recent_init(struct xt_entry_match *match)
75 {
76 	struct xt_recent_mtinfo *info = (void *)(match)->data;
77 
78 	strncpy(info->name,"DEFAULT", XT_RECENT_NAME_LEN);
79 	/* even though XT_RECENT_NAME_LEN is currently defined as 200,
80 	 * better be safe, than sorry */
81 	info->name[XT_RECENT_NAME_LEN-1] = '\0';
82 	info->side = XT_RECENT_SOURCE;
83 }
84 
recent_parse(struct xt_option_call * cb)85 static void recent_parse(struct xt_option_call *cb)
86 {
87 	struct xt_recent_mtinfo *info = cb->data;
88 
89 	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;
120 	}
121 }
122 
recent_check(struct xt_fcheck_call * cb)123 static void recent_check(struct xt_fcheck_call *cb)
124 {
125 	if (!(cb->xflags & F_ANY_OP))
126 		xtables_error(PARAMETER_PROBLEM,
127 			"recent: you must specify one of `--set', `--rcheck' "
128 			"`--update' or `--remove'");
129 }
130 
recent_print(const void * ip,const struct xt_entry_match * match,int numeric)131 static void recent_print(const void *ip, const struct xt_entry_match *match,
132                          int numeric)
133 {
134 	const struct xt_recent_mtinfo *info = (const void *)match->data;
135 
136 	if (info->invert)
137 		printf(" !");
138 
139 	printf(" recent:");
140 	if (info->check_set & XT_RECENT_SET)
141 		printf(" SET");
142 	if (info->check_set & XT_RECENT_CHECK)
143 		printf(" CHECK");
144 	if (info->check_set & XT_RECENT_UPDATE)
145 		printf(" UPDATE");
146 	if (info->check_set & XT_RECENT_REMOVE)
147 		printf(" REMOVE");
148 	if(info->seconds) printf(" seconds: %d", info->seconds);
149 	if(info->hit_count) printf(" hit_count: %d", info->hit_count);
150 	if (info->check_set & XT_RECENT_TTL)
151 		printf(" TTL-Match");
152 	if(info->name) printf(" name: %s", info->name);
153 	if (info->side == XT_RECENT_SOURCE)
154 		printf(" side: source");
155 	if (info->side == XT_RECENT_DEST)
156 		printf(" side: dest");
157 }
158 
recent_save(const void * ip,const struct xt_entry_match * match)159 static void recent_save(const void *ip, const struct xt_entry_match *match)
160 {
161 	const struct xt_recent_mtinfo *info = (const void *)match->data;
162 
163 	if (info->invert)
164 		printf(" !");
165 
166 	if (info->check_set & XT_RECENT_SET)
167 		printf(" --set");
168 	if (info->check_set & XT_RECENT_CHECK)
169 		printf(" --rcheck");
170 	if (info->check_set & XT_RECENT_UPDATE)
171 		printf(" --update");
172 	if (info->check_set & XT_RECENT_REMOVE)
173 		printf(" --remove");
174 	if(info->seconds) printf(" --seconds %d", info->seconds);
175 	if(info->hit_count) printf(" --hitcount %d", info->hit_count);
176 	if (info->check_set & XT_RECENT_TTL)
177 		printf(" --rttl");
178 	if(info->name) printf(" --name %s",info->name);
179 	if (info->side == XT_RECENT_SOURCE)
180 		printf(" --rsource");
181 	if (info->side == XT_RECENT_DEST)
182 		printf(" --rdest");
183 }
184 
185 static struct xtables_match recent_mt_reg = {
186 	.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,
193 	.x6_parse      = recent_parse,
194 	.x6_fcheck     = recent_check,
195 	.print         = recent_print,
196 	.save          = recent_save,
197 	.x6_options    = recent_opts,
198 };
199 
_init(void)200 void _init(void)
201 {
202 	xtables_register_match(&recent_mt_reg);
203 }
204