Merge commit 'origin/trunk@12184' into fedora
[iptables.git] / extensions / .#libipt_recent.c.1.6
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>
7
8 #include <iptables.h>
9 #include <linux/netfilter_ipv4/ipt_recent.h>
10
11 /* Function which prints out usage message. */
12 static void
13 help(void)
14 {
15         printf(
16 "recent v%s options:\n"
17 "[!] --set                       Add source address to list, always matches.\n"
18 "[!] --rcheck                    Match if source address in list.\n"
19 "[!] --update                    Match if source address in list, also update last-seen time.\n"
20 "[!] --remove                    Match if source address in list, also removes that address from list.\n"
21 "    --seconds seconds           For check and update commands above.\n"
22 "                                Specifies that the match will only occur if source address last seen within\n"
23 "                                the last 'seconds' seconds.\n"
24 "    --hitcount hits             For check and update commands above.\n"
25 "                                Specifies that the match will only occur if source address seen hits times.\n"
26 "                                May be used in conjunction with the seconds option.\n"
27 "    --rttl                      For check and update commands above.\n"
28 "                                Specifies that the match will only occur if the source address and the TTL\n"
29 "                                match between this packet and the one which was set.\n"
30 "                                Useful if you have problems with people spoofing their source address in order\n"
31 "                                to DoS you via this module.\n"
32 "    --name name                 Name of the recent list to be used.  DEFAULT used if none given.\n"
33 "    --rsource                   Save the source address of each packet in the recent list table (default).\n"
34 "    --rdest                     Save the destination address of each packet in the recent list table.\n"
35 ,
36 IPTABLES_VERSION);
37
38 }
39   
40 static struct option opts[] = {
41         { "set", 0, 0, 201 }, 
42         { "rcheck", 0, 0, 202 }, 
43         { "update", 0, 0, 203 },
44         { "seconds", 1, 0, 204 }, 
45         { "hitcount", 1, 0, 205 },
46         { "remove",0, 0, 206 },
47         { "rttl",0, 0, 207 },
48         { "name", 1, 0, 208 },
49         { "rsource", 0, 0, 209 },
50         { "rdest", 0, 0, 210 },
51         {0}
52 };
53
54 /* Initialize the match. */
55 static void
56 init(struct ipt_entry_match *match, unsigned int *nfcache)
57 {
58         struct ipt_recent_info *info = (struct ipt_recent_info *)(match)->data;
59
60         *nfcache |= NFC_UNKNOWN;
61
62         strncpy(info->name, "DEFAULT", 200);
63         info->side = IPT_RECENT_SOURCE;
64 }
65
66 /* Function which parses command options; returns true if it
67    ate an option */
68 static int
69 parse(int c, char **argv, int invert, unsigned int *flags,
70       const struct ipt_entry *entry,
71       unsigned int *nfcache,
72       struct ipt_entry_match **match)
73 {
74         struct ipt_recent_info *info = (struct ipt_recent_info *)(*match)->data;
75         switch (c) {
76                 case 201:
77                         if (*flags) 
78                                 exit_error(PARAMETER_PROBLEM,
79                                         "recent: only one of `--set', `--check' "
80                                         "`--update' or `--remove' may be set");
81                         check_inverse(optarg, &invert, &optind, 0);
82                         info->check_set |= IPT_RECENT_SET;
83                         if (invert) 
84                                 info->invert = 1;
85                         *flags = 1;
86                         break;
87                         
88                 case 202:
89                         if (*flags) 
90                                 exit_error(PARAMETER_PROBLEM,
91                                         "recent: only one of `--set', `--check' "
92                                         "`--update' or `--remove' may be set");
93                         check_inverse(optarg, &invert, &optind, 0);
94                         info->check_set |= IPT_RECENT_CHECK;
95                         if (invert)
96                                 info->invert = 1;
97                         *flags = 1;
98                         break;
99
100                 case 203:
101                         if (*flags)
102                                 exit_error(PARAMETER_PROBLEM,
103                                         "recent: only one of `--set', `--check' "
104                                         "`--update' or `--remove' may be set");
105                         check_inverse(optarg, &invert, &optind, 0);
106                         info->check_set |= IPT_RECENT_UPDATE;
107                         if (invert)
108                                 info->invert = 1;
109                         *flags = 1;
110                         break;
111
112                 case 206:
113                         if (*flags)
114                                 exit_error(PARAMETER_PROBLEM,
115                                         "recent: only one of `--set', `--check' "
116                                         "`--update' or `--remove' may be set");
117                         check_inverse(optarg, &invert, &optind, 0);
118                         info->check_set |= IPT_RECENT_REMOVE;
119                         if (invert)
120                                 info->invert = 1;
121                         *flags = 1;
122                         break;
123
124                 case 204:
125                         info->seconds = atoi(optarg);
126                         break;
127
128                 case 205:
129                         info->hit_count = atoi(optarg);
130                         break;
131
132                 case 207:
133                         info->check_set |= IPT_RECENT_TTL;
134                         break;
135
136                 case 208:
137                         strncpy(info->name, optarg, 200);
138                         break;
139
140                 case 209:
141                         info->side = IPT_RECENT_SOURCE;
142                         break;
143
144                 case 210:
145                         info->side = IPT_RECENT_DEST;
146                         break;
147
148                 default:
149                         return 0;
150         }
151
152         return 1;
153 }
154
155 /* Final check; must have specified a specific option. */
156 static void
157 final_check(unsigned int flags)
158 {
159
160         if (!flags)
161                 exit_error(PARAMETER_PROBLEM,
162                         "recent: you must specify one of `--set', `--check' "
163                         "`--update' or `--remove'");
164 }
165
166 /* Prints out the matchinfo. */
167 static void
168 print(const struct ipt_ip *ip,
169       const struct ipt_entry_match *match,
170       int numeric)
171 {
172         struct ipt_recent_info *info = (struct ipt_recent_info *)match->data;
173
174         if (info->invert) fputc('!', stdout);
175
176         printf("recent: ");
177         if(info->check_set & IPT_RECENT_SET) printf("SET ");
178         if(info->check_set & IPT_RECENT_CHECK) printf("CHECK ");
179         if(info->check_set & IPT_RECENT_UPDATE) printf("UPDATE ");
180         if(info->check_set & IPT_RECENT_REMOVE) printf("REMOVE ");
181         if(info->seconds) printf("seconds: %d ", info->seconds);
182         if(info->hit_count) printf("hit_count: %d ", info->hit_count);
183         if(info->check_set & IPT_RECENT_TTL) printf("TTL-Match ");
184         if(info->name) printf("name: %s ", info->name);
185         if(info->side == IPT_RECENT_SOURCE) printf("side: source ");
186         if(info->side == IPT_RECENT_DEST) printf("side: dest");
187 }
188
189 /* Saves the union ipt_matchinfo in parsable form to stdout. */
190 static void
191 save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
192 {
193         struct ipt_recent_info *info = (struct ipt_recent_info *)match;
194
195         if (info->invert) fputc('!', stdout);
196
197         printf("recent: ");
198         if(info->check_set & IPT_RECENT_SET) printf("SET ");
199         if(info->check_set & IPT_RECENT_CHECK) printf("CHECK ");
200         if(info->check_set & IPT_RECENT_UPDATE) printf("UPDATE ");
201         if(info->check_set & IPT_RECENT_REMOVE) printf("REMOVE ");
202         if(info->seconds) printf("seconds: %d ",info->seconds);
203         if(info->hit_count) printf("hit_count: %d ",info->hit_count);
204         if(info->check_set & IPT_RECENT_TTL) printf("TTL-Match ");
205         if(info->name) printf("name: %s ",info->name);
206         if(info->side == IPT_RECENT_SOURCE) printf("side: source ");
207         if(info->side == IPT_RECENT_DEST) printf("side: dest");
208 }
209
210 static
211 struct iptables_match recent
212 = { NULL,
213     "recent",
214     IPTABLES_VERSION,
215     IPT_ALIGN(sizeof(struct ipt_recent_info)),
216     IPT_ALIGN(sizeof(struct ipt_recent_info)),
217     &help,
218     &init,
219     &parse,
220     &final_check,
221     &print,
222     &save,
223     opts
224 };
225
226 void _init(void)
227 {
228         register_match(&recent);
229 }