Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / iptables / extensions / libipt_recent.c
blob0b0ed2d18e8cf5e589fd45483e887f88b8575200
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 <iptables.h>
9 #include <linux/netfilter_ipv4/ipt_recent.h>
11 /* Need these in order to not fail when compiling against an older kernel. */
12 #ifndef RECENT_NAME
13 #define RECENT_NAME "ipt_recent"
14 #endif /* RECENT_NAME */
16 #ifndef RECENT_VER
17 #define RECENT_VER "unknown"
18 #endif /* RECENT_VER */
20 #ifndef IPT_RECENT_NAME_LEN
21 #define IPT_RECENT_NAME_LEN 200
22 #endif /* IPT_RECENT_NAME_LEN */
24 /* Options for this module */
25 static struct option opts[] = {
26 { .name = "set", .has_arg = 0, .flag = 0, .val = 201 },
27 { .name = "rcheck", .has_arg = 0, .flag = 0, .val = 202 },
28 { .name = "update", .has_arg = 0, .flag = 0, .val = 203 },
29 { .name = "seconds", .has_arg = 1, .flag = 0, .val = 204 },
30 { .name = "hitcount", .has_arg = 1, .flag = 0, .val = 205 },
31 { .name = "remove", .has_arg = 0, .flag = 0, .val = 206 },
32 { .name = "rttl", .has_arg = 0, .flag = 0, .val = 207 },
33 { .name = "name", .has_arg = 1, .flag = 0, .val = 208 },
34 { .name = "rsource", .has_arg = 0, .flag = 0, .val = 209 },
35 { .name = "rdest", .has_arg = 0, .flag = 0, .val = 210 },
36 { .name = 0, .has_arg = 0, .flag = 0, .val = 0 }
39 /* Function which prints out usage message. */
40 static void
41 help(void)
43 printf(
44 "recent v%s options:\n"
45 "[!] --set Add source address to list, always matches.\n"
46 "[!] --rcheck Match if source address in list.\n"
47 "[!] --update Match if source address in list, also update last-seen time.\n"
48 "[!] --remove Match if source address in list, also removes that address from list.\n"
49 " --seconds seconds For check and update commands above.\n"
50 " Specifies that the match will only occur if source address last seen within\n"
51 " the last 'seconds' seconds.\n"
52 " --hitcount hits For check and update commands above.\n"
53 " Specifies that the match will only occur if source address seen hits times.\n"
54 " May be used in conjunction with the seconds option.\n"
55 " --rttl For check and update commands above.\n"
56 " Specifies that the match will only occur if the source address and the TTL\n"
57 " match between this packet and the one which was set.\n"
58 " Useful if you have problems with people spoofing their source address in order\n"
59 " to DoS you via this module.\n"
60 " --name name Name of the recent list to be used. DEFAULT used if none given.\n"
61 " --rsource Match/Save the source address of each packet in the recent list table (default).\n"
62 " --rdest Match/Save the destination address of each packet in the recent list table.\n"
63 RECENT_NAME " " RECENT_VER ": Stephen Frost <sfrost@snowman.net>. http://snowman.net/projects/ipt_recent/\n"
65 IPTABLES_VERSION);
69 /* Initialize the match. */
70 static void
71 init(struct ipt_entry_match *match, unsigned int *nfcache)
73 struct ipt_recent_info *info = (struct ipt_recent_info *)(match)->data;
76 strncpy(info->name,"DEFAULT",IPT_RECENT_NAME_LEN);
77 /* eventhough IPT_RECENT_NAME_LEN is currently defined as 200,
78 * better be safe, than sorry */
79 info->name[IPT_RECENT_NAME_LEN-1] = '\0';
80 info->side = IPT_RECENT_SOURCE;
83 /* Function which parses command options; returns true if it
84 ate an option */
85 static int
86 parse(int c, char **argv, int invert, unsigned int *flags,
87 const struct ipt_entry *entry,
88 unsigned int *nfcache,
89 struct ipt_entry_match **match)
91 struct ipt_recent_info *info = (struct ipt_recent_info *)(*match)->data;
92 switch (c) {
93 case 201:
94 if (*flags) exit_error(PARAMETER_PROBLEM,
95 "recent: only one of `--set', `--rcheck' "
96 "`--update' or `--remove' may be set");
97 check_inverse(optarg, &invert, &optind, 0);
98 info->check_set |= IPT_RECENT_SET;
99 if (invert) info->invert = 1;
100 *flags = 1;
101 break;
103 case 202:
104 if (*flags) exit_error(PARAMETER_PROBLEM,
105 "recent: only one of `--set', `--rcheck' "
106 "`--update' or `--remove' may be set");
107 check_inverse(optarg, &invert, &optind, 0);
108 info->check_set |= IPT_RECENT_CHECK;
109 if(invert) info->invert = 1;
110 *flags = 1;
111 break;
113 case 203:
114 if (*flags) exit_error(PARAMETER_PROBLEM,
115 "recent: only one of `--set', `--rcheck' "
116 "`--update' or `--remove' may be set");
117 check_inverse(optarg, &invert, &optind, 0);
118 info->check_set |= IPT_RECENT_UPDATE;
119 if (invert) info->invert = 1;
120 *flags = 1;
121 break;
123 case 206:
124 if (*flags) exit_error(PARAMETER_PROBLEM,
125 "recent: only one of `--set', `--rcheck' "
126 "`--update' or `--remove' may be set");
127 check_inverse(optarg, &invert, &optind, 0);
128 info->check_set |= IPT_RECENT_REMOVE;
129 if (invert) info->invert = 1;
130 *flags = 1;
131 break;
133 case 204:
134 info->seconds = atoi(optarg);
135 break;
137 case 205:
138 info->hit_count = atoi(optarg);
139 break;
141 case 207:
142 info->check_set |= IPT_RECENT_TTL;
143 break;
145 case 208:
146 strncpy(info->name,optarg,IPT_RECENT_NAME_LEN);
147 info->name[IPT_RECENT_NAME_LEN-1] = '\0';
148 break;
150 case 209:
151 info->side = IPT_RECENT_SOURCE;
152 break;
154 case 210:
155 info->side = IPT_RECENT_DEST;
156 break;
158 default:
159 return 0;
162 return 1;
165 /* Final check; must have specified a specific option. */
166 static void
167 final_check(unsigned int flags)
170 if (!flags)
171 exit_error(PARAMETER_PROBLEM,
172 "recent: you must specify one of `--set', `--rcheck' "
173 "`--update' or `--remove'");
176 /* Prints out the matchinfo. */
177 static void
178 print(const struct ipt_ip *ip,
179 const struct ipt_entry_match *match,
180 int numeric)
182 struct ipt_recent_info *info = (struct ipt_recent_info *)match->data;
184 if (info->invert)
185 fputc('!', stdout);
187 printf("recent: ");
188 if(info->check_set & IPT_RECENT_SET) printf("SET ");
189 if(info->check_set & IPT_RECENT_CHECK) printf("CHECK ");
190 if(info->check_set & IPT_RECENT_UPDATE) printf("UPDATE ");
191 if(info->check_set & IPT_RECENT_REMOVE) printf("REMOVE ");
192 if(info->seconds) printf("seconds: %d ",info->seconds);
193 if(info->hit_count) printf("hit_count: %d ",info->hit_count);
194 if(info->check_set & IPT_RECENT_TTL) printf("TTL-Match ");
195 if(info->name) printf("name: %s ",info->name);
196 if(info->side == IPT_RECENT_SOURCE) printf("side: source ");
197 if(info->side == IPT_RECENT_DEST) printf("side: dest");
200 /* Saves the union ipt_matchinfo in parsable form to stdout. */
201 static void
202 save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
204 struct ipt_recent_info *info = (struct ipt_recent_info *)match->data;
206 if (info->invert)
207 printf("! ");
209 if(info->check_set & IPT_RECENT_SET) printf("--set ");
210 if(info->check_set & IPT_RECENT_CHECK) printf("--rcheck ");
211 if(info->check_set & IPT_RECENT_UPDATE) printf("--update ");
212 if(info->check_set & IPT_RECENT_REMOVE) printf("--remove ");
213 if(info->seconds) printf("--seconds %d ",info->seconds);
214 if(info->hit_count) printf("--hitcount %d ",info->hit_count);
215 if(info->check_set & IPT_RECENT_TTL) printf("--rttl ");
216 if(info->name) printf("--name %s ",info->name);
217 if(info->side == IPT_RECENT_SOURCE) printf("--rsource ");
218 if(info->side == IPT_RECENT_DEST) printf("--rdest ");
221 /* Structure for iptables to use to communicate with module */
222 static struct iptables_match recent = {
223 .next = NULL,
224 .name = "recent",
225 .version = IPTABLES_VERSION,
226 .size = IPT_ALIGN(sizeof(struct ipt_recent_info)),
227 .userspacesize = IPT_ALIGN(sizeof(struct ipt_recent_info)),
228 .help = &help,
229 .init = &init,
230 .parse = &parse,
231 .final_check = &final_check,
232 .print = &print,
233 .save = &save,
234 .extra_opts = opts
237 void _init(void)
239 register_match(&recent);