blob: 48cc8140b82d95b79fa1ecf972653262f879837b [file] [log] [blame]
Stephen Frost93c7e5a2001-11-08 22:35:03 +00001/* 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. */
12static void
13help(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",
Stephen Frost4fce44c2002-02-04 11:58:22 +000027" --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",
Stephen Frost93c7e5a2001-11-08 22:35:03 +000033NETFILTER_VERSION);
34
35}
36
37static struct option opts[] = {
38 { "set", 0, 0, 201 },
39 { "rcheck", 0, 0, 202 },
40 { "update", 0, 0, 203 },
41 { "seconds", 1, 0, 204 },
42 { "hitcount", 1, 0, 205 },
43 { "remove",0, 0, 206 },
Stephen Frost4fce44c2002-02-04 11:58:22 +000044 { "rttl",0, 0, 207},
45 { "name", 1, 0, 208},
Stephen Frost93c7e5a2001-11-08 22:35:03 +000046 {0}
47};
48
49/* Initialize the match. */
50static void
51init(struct ipt_entry_match *m, unsigned int *nfcache)
52{
53 *nfcache |= NFC_UNKNOWN;
54}
55
56/* Function which parses command options; returns true if it
57 ate an option */
58static int
59parse(int c, char **argv, int invert, unsigned int *flags,
60 const struct ipt_entry *entry,
61 unsigned int *nfcache,
62 struct ipt_entry_match **match)
63{
64 struct ipt_recent_info *info = (struct ipt_recent_info *)(*match)->data;
65
Stephen Frost4fce44c2002-02-04 11:58:22 +000066 info->name[0] = '\0';
67
Stephen Frost93c7e5a2001-11-08 22:35:03 +000068 switch (c) {
69 case 201:
70 if (*flags) exit_error(PARAMETER_PROBLEM,
71 "recent: only one of `--set', `--check' "
72 "`--update' or `--remove' may be set");
73 if (check_inverse(optarg, &invert)) optind++;
74 info->check_set |= IPT_RECENT_SET;
75 if (invert) info->invert = 1;
76 *flags = 1;
77 break;
78
79 case 202:
80 if (*flags) exit_error(PARAMETER_PROBLEM,
81 "recent: only one of `--set', `--check' "
82 "`--update' or `--remove' may be set");
83 if (check_inverse(optarg, &invert)) optind++;
84 info->check_set |= IPT_RECENT_CHECK;
85 if(invert) info->invert = 1;
86 *flags = 1;
87 break;
88
89 case 203:
90 if (*flags) exit_error(PARAMETER_PROBLEM,
91 "recent: only one of `--set', `--check' "
92 "`--update' or `--remove' may be set");
93 if (check_inverse(optarg, &invert)) optind++;
94 info->check_set |= IPT_RECENT_UPDATE;
95 if (invert) info->invert = 1;
96 *flags = 1;
97 break;
98
99 case 206:
100 if (*flags) exit_error(PARAMETER_PROBLEM,
101 "recent: only one of `--set', `--check' "
102 "`--update' or `--remove' may be set");
103 if (check_inverse(optarg, &invert)) optind++;
104 info->check_set |= IPT_RECENT_REMOVE;
105 if (invert) info->invert = 1;
106 *flags = 1;
107 break;
108
109 case 204:
110 info->seconds = atoi(optarg);
111 break;
112
113 case 205:
114 info->hit_count = atoi(optarg);
115 break;
116
Stephen Frost4fce44c2002-02-04 11:58:22 +0000117 case 207:
118 info->check_set |= IPT_RECENT_TTL;
119 break;
120
121 case 208:
122 strncpy(info->name,optarg,200);
123 break;
124
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000125 default:
126 return 0;
127 }
Stephen Frost4fce44c2002-02-04 11:58:22 +0000128
129 if(!info->name[0]) strncpy(info->name,"DEFAULT",200);
130
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000131 return 1;
132}
133
134/* Final check; must have specified a specific option. */
135static void
136final_check(unsigned int flags)
137{
138 if (!flags)
139 exit_error(PARAMETER_PROBLEM,
140 "recent: you must specify one of `--set', `--check' "
141 "`--update' or `--remove'");
142}
143
144/* Prints out the matchinfo. */
145static void
146print(const struct ipt_ip *ip,
147 const struct ipt_entry_match *match,
148 int numeric)
149{
150 struct ipt_recent_info *info = (struct ipt_recent_info *)match->data;
151
152 if (info->invert) fputc('!', stdout);
153
154 printf("recent: ");
155 if(info->check_set & IPT_RECENT_SET) printf("SET ");
156 if(info->check_set & IPT_RECENT_CHECK) printf("CHECK ");
157 if(info->check_set & IPT_RECENT_UPDATE) printf("UPDATE ");
158 if(info->check_set & IPT_RECENT_REMOVE) printf("REMOVE ");
Stephen Frost4fce44c2002-02-04 11:58:22 +0000159 if(info->seconds) printf("seconds: %d ",info->seconds);
160 if(info->hit_count) printf("hit_count: %d ",info->hit_count);
161 if(info->check_set & IPT_RECENT_TTL) printf("TTL-Match ");
162 if(info->name) printf("name: %s",info->name);
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000163}
164
165/* Saves the union ipt_matchinfo in parsable form to stdout. */
166static void
167save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
168{
169 struct ipt_recent_info *info = (struct ipt_recent_info *)match;
170
171 if (info->invert) fputc('!', stdout);
172
173 printf("recent: ");
174 if(info->check_set & IPT_RECENT_SET) printf("SET ");
175 if(info->check_set & IPT_RECENT_CHECK) printf("CHECK ");
176 if(info->check_set & IPT_RECENT_UPDATE) printf("UPDATE ");
177 if(info->check_set & IPT_RECENT_REMOVE) printf("REMOVE ");
Stephen Frost4fce44c2002-02-04 11:58:22 +0000178 if(info->seconds) printf("seconds: %d ",info->seconds);
179 if(info->hit_count) printf("hit_count: %d ",info->hit_count);
180 if(info->check_set & IPT_RECENT_TTL) printf("TTL-Match ");
181 if(info->name) printf("name: %s",info->name);
Stephen Frost93c7e5a2001-11-08 22:35:03 +0000182}
183
184static
185struct iptables_match recent
186= { NULL,
187 "recent",
188 NETFILTER_VERSION,
189 IPT_ALIGN(sizeof(struct ipt_recent_info)),
190 IPT_ALIGN(sizeof(struct ipt_recent_info)),
191 &help,
192 &init,
193 &parse,
194 &final_check,
195 &print,
196 &save,
197 opts
198};
199
200void _init(void)
201{
202 register_match(&recent);
203}