K2.6 patches and update.
[tomato.git] / release / src / router / iptables / extensions / libip6t_recent.c
blob2486b3c131695377cb66fb78759c6bad424e6f67
1 /* Shared library add-on to iptables to add recent matching support. */
2 #include <stdio.h>
3 #include <netdb.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <getopt.h>
8 #include <ip6tables.h>
9 #include <linux/netfilter_ipv6/ip6_tables.h>
10 #include <linux/netfilter/xt_recent.h>
12 #ifndef XTABLES_VERSION
13 #define XTABLES_VERSION IPTABLES_VERSION
14 #endif
16 #ifdef IPT_LIB_DIR
17 #define xtables_target ip6tables_target
18 #define xtables_register_target register_target6
19 #endif
21 /* Need these in order to not fail when compiling against an older kernel. */
22 #ifndef RECENT_NAME
23 #define RECENT_NAME "ip6t_recent"
24 #endif /* RECENT_NAME */
26 #ifndef RECENT_VER
27 #define RECENT_VER "unknown"
28 #endif /* RECENT_VER */
30 /* Options for this module */
31 static struct option opts[] = {
32 { .name = "set", .has_arg = 0, .flag = 0, .val = 201 },
33 { .name = "rcheck", .has_arg = 0, .flag = 0, .val = 202 },
34 { .name = "update", .has_arg = 0, .flag = 0, .val = 203 },
35 { .name = "seconds", .has_arg = 1, .flag = 0, .val = 204 },
36 { .name = "hitcount", .has_arg = 1, .flag = 0, .val = 205 },
37 { .name = "remove", .has_arg = 0, .flag = 0, .val = 206 },
38 { .name = "rttl", .has_arg = 0, .flag = 0, .val = 207 },
39 { .name = "name", .has_arg = 1, .flag = 0, .val = 208 },
40 { .name = "rsource", .has_arg = 0, .flag = 0, .val = 209 },
41 { .name = "rdest", .has_arg = 0, .flag = 0, .val = 210 },
42 { .name = 0, .has_arg = 0, .flag = 0, .val = 0 }
45 /* Function which prints out usage message. */
46 static void
47 help(void)
49 printf(
50 "recent v%s options:\n"
51 "[!] --set Add source address to list, always matches.\n"
52 "[!] --rcheck Match if source address in list.\n"
53 "[!] --update Match if source address in list, also update last-seen time.\n"
54 "[!] --remove Match if source address in list, also removes that address from list.\n"
55 " --seconds seconds For check and update commands above.\n"
56 " Specifies that the match will only occur if source address last seen within\n"
57 " the last 'seconds' seconds.\n"
58 " --hitcount hits For check and update commands above.\n"
59 " Specifies that the match will only occur if source address seen hits times.\n"
60 " May be used in conjunction with the seconds option.\n"
61 " --rttl For check and update commands above.\n"
62 " Specifies that the match will only occur if the source address and the TTL\n"
63 " match between this packet and the one which was set.\n"
64 " Useful if you have problems with people spoofing their source address in order\n"
65 " to DoS you via this module.\n"
66 " --name name Name of the recent list to be used. DEFAULT used if none given.\n"
67 " --rsource Match/Save the source address of each packet in the recent list table (default).\n"
68 " --rdest Match/Save the destination address of each packet in the recent list table.\n"
69 RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>. http://snowman.net/projects/ipt_recent/\n"
71 IPTABLES_VERSION);
75 /* Initialize the match. */
76 static void
77 init(struct ip6t_entry_match *match, unsigned int *nfcache)
79 struct xt_recent_mtinfo *info = (struct xt_recent_mtinfo *)(match)->data;
82 strncpy(info->name,"DEFAULT",XT_RECENT_NAME_LEN);
83 /* eventhough XT_RECENT_NAME_LEN is currently defined as 200,
84 * better be safe, than sorry */
85 info->name[XT_RECENT_NAME_LEN-1] = '\0';
86 info->side = XT_RECENT_SOURCE;
89 /* Function which parses command options; returns true if it
90 ate an option */
91 static int
92 parse(int c, char **argv, int invert, unsigned int *flags,
93 const struct ip6t_entry *entry,
94 unsigned int *nfcache,
95 struct ip6t_entry_match **match)
97 struct xt_recent_mtinfo *info = (struct xt_recent_mtinfo *)(*match)->data;
98 switch (c) {
99 case 201:
100 if (*flags) exit_error(PARAMETER_PROBLEM,
101 "recent: only one of `--set', `--rcheck' "
102 "`--update' or `--remove' may be set");
103 check_inverse(optarg, &invert, &optind, 0);
104 info->check_set |= XT_RECENT_SET;
105 if (invert) info->invert = 1;
106 *flags = 1;
107 break;
109 case 202:
110 if (*flags) exit_error(PARAMETER_PROBLEM,
111 "recent: only one of `--set', `--rcheck' "
112 "`--update' or `--remove' may be set");
113 check_inverse(optarg, &invert, &optind, 0);
114 info->check_set |= XT_RECENT_CHECK;
115 if(invert) info->invert = 1;
116 *flags = 1;
117 break;
119 case 203:
120 if (*flags) exit_error(PARAMETER_PROBLEM,
121 "recent: only one of `--set', `--rcheck' "
122 "`--update' or `--remove' may be set");
123 check_inverse(optarg, &invert, &optind, 0);
124 info->check_set |= XT_RECENT_UPDATE;
125 if (invert) info->invert = 1;
126 *flags = 1;
127 break;
129 case 206:
130 if (*flags) exit_error(PARAMETER_PROBLEM,
131 "recent: only one of `--set', `--rcheck' "
132 "`--update' or `--remove' may be set");
133 check_inverse(optarg, &invert, &optind, 0);
134 info->check_set |= XT_RECENT_REMOVE;
135 if (invert) info->invert = 1;
136 *flags = 1;
137 break;
139 case 204:
140 info->seconds = atoi(optarg);
141 break;
143 case 205:
144 info->hit_count = atoi(optarg);
145 break;
147 case 207:
148 info->check_set |= XT_RECENT_TTL;
149 break;
151 case 208:
152 strncpy(info->name,optarg,XT_RECENT_NAME_LEN);
153 info->name[XT_RECENT_NAME_LEN-1] = '\0';
154 break;
156 case 209:
157 info->side = XT_RECENT_SOURCE;
158 break;
160 case 210:
161 info->side = XT_RECENT_DEST;
162 break;
164 default:
165 return 0;
168 return 1;
171 /* Final check; must have specified a specific option. */
172 static void
173 final_check(unsigned int flags)
175 if (!flags)
176 exit_error(PARAMETER_PROBLEM,
177 "recent: you must specify one of `--set', `--rcheck' "
178 "`--update' or `--remove'");
181 /* Prints out the matchinfo. */
182 static void
183 print(const struct ip6t_ip6 *ip,
184 const struct ip6t_entry_match *match,
185 int numeric)
187 struct xt_recent_mtinfo *info = (struct xt_recent_mtinfo *)match->data;
189 if (info->invert)
190 fputc('!', stdout);
192 printf("recent: ");
193 if(info->check_set & XT_RECENT_SET) printf("SET ");
194 if(info->check_set & XT_RECENT_CHECK) printf("CHECK ");
195 if(info->check_set & XT_RECENT_UPDATE) printf("UPDATE ");
196 if(info->check_set & XT_RECENT_REMOVE) printf("REMOVE ");
197 if(info->seconds) printf("seconds: %d ",info->seconds);
198 if(info->hit_count) printf("hit_count: %d ",info->hit_count);
199 if(info->check_set & XT_RECENT_TTL) printf("TTL-Match ");
200 if(info->name) printf("name: %s ",info->name);
201 if(info->side == XT_RECENT_SOURCE) printf("side: source ");
202 if(info->side == XT_RECENT_DEST) printf("side: dest");
205 /* Saves the union ip6t_matchinfo in parsable form to stdout. */
206 static void
207 save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
209 struct xt_recent_mtinfo *info = (struct xt_recent_mtinfo *)match->data;
211 if (info->invert)
212 printf("! ");
214 if(info->check_set & XT_RECENT_SET) printf("--set ");
215 if(info->check_set & XT_RECENT_CHECK) printf("--rcheck ");
216 if(info->check_set & XT_RECENT_UPDATE) printf("--update ");
217 if(info->check_set & XT_RECENT_REMOVE) printf("--remove ");
218 if(info->seconds) printf("--seconds %d ",info->seconds);
219 if(info->hit_count) printf("--hitcount %d ",info->hit_count);
220 if(info->check_set & XT_RECENT_TTL) printf("--rttl ");
221 if(info->name) printf("--name %s ",info->name);
222 if(info->side == XT_RECENT_SOURCE) printf("--rsource ");
223 if(info->side == XT_RECENT_DEST) printf("--rdest ");
226 /* Structure for iptables to use to communicate with module */
227 static struct ip6tables_match recent = {
228 .next = NULL,
229 .name = "recent",
230 .version = XTABLES_VERSION,
231 .size = IP6T_ALIGN(sizeof(struct xt_recent_mtinfo)),
232 .userspacesize = IP6T_ALIGN(sizeof(struct xt_recent_mtinfo)),
233 .help = &help,
234 .init = &init,
235 .parse = &parse,
236 .final_check = &final_check,
237 .print = &print,
238 .save = &save,
239 .extra_opts = opts,
242 void _init(void)
244 register_match6(&recent);