blob: 8c4a1a33c4794ea98e4455a3e30a5366984ac452 [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",
27NETFILTER_VERSION);
28
29}
30
31static struct option opts[] = {
32 { "set", 0, 0, 201 },
33 { "rcheck", 0, 0, 202 },
34 { "update", 0, 0, 203 },
35 { "seconds", 1, 0, 204 },
36 { "hitcount", 1, 0, 205 },
37 { "remove",0, 0, 206 },
38 {0}
39};
40
41/* Initialize the match. */
42static void
43init(struct ipt_entry_match *m, unsigned int *nfcache)
44{
45 *nfcache |= NFC_UNKNOWN;
46}
47
48/* Function which parses command options; returns true if it
49 ate an option */
50static int
51parse(int c, char **argv, int invert, unsigned int *flags,
52 const struct ipt_entry *entry,
53 unsigned int *nfcache,
54 struct ipt_entry_match **match)
55{
56 struct ipt_recent_info *info = (struct ipt_recent_info *)(*match)->data;
57
58 switch (c) {
59 case 201:
60 if (*flags) exit_error(PARAMETER_PROBLEM,
61 "recent: only one of `--set', `--check' "
62 "`--update' or `--remove' may be set");
63 if (check_inverse(optarg, &invert)) optind++;
64 info->check_set |= IPT_RECENT_SET;
65 if (invert) info->invert = 1;
66 *flags = 1;
67 break;
68
69 case 202:
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_CHECK;
75 if(invert) info->invert = 1;
76 *flags = 1;
77 break;
78
79 case 203:
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_UPDATE;
85 if (invert) info->invert = 1;
86 *flags = 1;
87 break;
88
89 case 206:
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_REMOVE;
95 if (invert) info->invert = 1;
96 *flags = 1;
97 break;
98
99 case 204:
100 info->seconds = atoi(optarg);
101 break;
102
103 case 205:
104 info->hit_count = atoi(optarg);
105 break;
106
107 default:
108 return 0;
109 }
110 return 1;
111}
112
113/* Final check; must have specified a specific option. */
114static void
115final_check(unsigned int flags)
116{
117 if (!flags)
118 exit_error(PARAMETER_PROBLEM,
119 "recent: you must specify one of `--set', `--check' "
120 "`--update' or `--remove'");
121}
122
123/* Prints out the matchinfo. */
124static void
125print(const struct ipt_ip *ip,
126 const struct ipt_entry_match *match,
127 int numeric)
128{
129 struct ipt_recent_info *info = (struct ipt_recent_info *)match->data;
130
131 if (info->invert) fputc('!', stdout);
132
133 printf("recent: ");
134 if(info->check_set & IPT_RECENT_SET) printf("SET ");
135 if(info->check_set & IPT_RECENT_CHECK) printf("CHECK ");
136 if(info->check_set & IPT_RECENT_UPDATE) printf("UPDATE ");
137 if(info->check_set & IPT_RECENT_REMOVE) printf("REMOVE ");
138 if(info->seconds) printf("seconds: %d",info->seconds);
139 if(info->hit_count) printf("hit_count: %d",info->hit_count);
140}
141
142/* Saves the union ipt_matchinfo in parsable form to stdout. */
143static void
144save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
145{
146 struct ipt_recent_info *info = (struct ipt_recent_info *)match;
147
148 if (info->invert) fputc('!', stdout);
149
150 printf("recent: ");
151 if(info->check_set & IPT_RECENT_SET) printf("SET ");
152 if(info->check_set & IPT_RECENT_CHECK) printf("CHECK ");
153 if(info->check_set & IPT_RECENT_UPDATE) printf("UPDATE ");
154 if(info->check_set & IPT_RECENT_REMOVE) printf("REMOVE ");
155 if(info->seconds) printf("seconds: ");
156 if(info->hit_count) printf("hit_count: ");
157}
158
159static
160struct iptables_match recent
161= { NULL,
162 "recent",
163 NETFILTER_VERSION,
164 IPT_ALIGN(sizeof(struct ipt_recent_info)),
165 IPT_ALIGN(sizeof(struct ipt_recent_info)),
166 &help,
167 &init,
168 &parse,
169 &final_check,
170 &print,
171 &save,
172 opts
173};
174
175void _init(void)
176{
177 register_match(&recent);
178}