1*a71a9546SAutomerger Merge Worker #include <stdbool.h>
2*a71a9546SAutomerger Merge Worker #include <stdio.h>
3*a71a9546SAutomerger Merge Worker #include <string.h>
4*a71a9546SAutomerger Merge Worker #include <xtables.h>
5*a71a9546SAutomerger Merge Worker #include <linux/netfilter/xt_recent.h>
6*a71a9546SAutomerger Merge Worker
7*a71a9546SAutomerger Merge Worker enum {
8*a71a9546SAutomerger Merge Worker O_SET = 0,
9*a71a9546SAutomerger Merge Worker O_RCHECK,
10*a71a9546SAutomerger Merge Worker O_UPDATE,
11*a71a9546SAutomerger Merge Worker O_REMOVE,
12*a71a9546SAutomerger Merge Worker O_SECONDS,
13*a71a9546SAutomerger Merge Worker O_REAP,
14*a71a9546SAutomerger Merge Worker O_HITCOUNT,
15*a71a9546SAutomerger Merge Worker O_RTTL,
16*a71a9546SAutomerger Merge Worker O_NAME,
17*a71a9546SAutomerger Merge Worker O_RSOURCE,
18*a71a9546SAutomerger Merge Worker O_RDEST,
19*a71a9546SAutomerger Merge Worker O_MASK,
20*a71a9546SAutomerger Merge Worker F_SET = 1 << O_SET,
21*a71a9546SAutomerger Merge Worker F_RCHECK = 1 << O_RCHECK,
22*a71a9546SAutomerger Merge Worker F_UPDATE = 1 << O_UPDATE,
23*a71a9546SAutomerger Merge Worker F_REMOVE = 1 << O_REMOVE,
24*a71a9546SAutomerger Merge Worker F_SECONDS = 1 << O_SECONDS,
25*a71a9546SAutomerger Merge Worker F_ANY_OP = F_SET | F_RCHECK | F_UPDATE | F_REMOVE,
26*a71a9546SAutomerger Merge Worker };
27*a71a9546SAutomerger Merge Worker
28*a71a9546SAutomerger Merge Worker #define s struct xt_recent_mtinfo
29*a71a9546SAutomerger Merge Worker static const struct xt_option_entry recent_opts_v0[] = {
30*a71a9546SAutomerger Merge Worker {.name = "set", .id = O_SET, .type = XTTYPE_NONE,
31*a71a9546SAutomerger Merge Worker .excl = F_ANY_OP, .flags = XTOPT_INVERT},
32*a71a9546SAutomerger Merge Worker {.name = "rcheck", .id = O_RCHECK, .type = XTTYPE_NONE,
33*a71a9546SAutomerger Merge Worker .excl = F_ANY_OP, .flags = XTOPT_INVERT},
34*a71a9546SAutomerger Merge Worker {.name = "update", .id = O_UPDATE, .type = XTTYPE_NONE,
35*a71a9546SAutomerger Merge Worker .excl = F_ANY_OP, .flags = XTOPT_INVERT},
36*a71a9546SAutomerger Merge Worker {.name = "remove", .id = O_REMOVE, .type = XTTYPE_NONE,
37*a71a9546SAutomerger Merge Worker .excl = F_ANY_OP, .flags = XTOPT_INVERT},
38*a71a9546SAutomerger Merge Worker {.name = "seconds", .id = O_SECONDS, .type = XTTYPE_UINT32,
39*a71a9546SAutomerger Merge Worker .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds), .min = 1},
40*a71a9546SAutomerger Merge Worker {.name = "reap", .id = O_REAP, .type = XTTYPE_NONE,
41*a71a9546SAutomerger Merge Worker .also = F_SECONDS },
42*a71a9546SAutomerger Merge Worker {.name = "hitcount", .id = O_HITCOUNT, .type = XTTYPE_UINT32,
43*a71a9546SAutomerger Merge Worker .flags = XTOPT_PUT, XTOPT_POINTER(s, hit_count)},
44*a71a9546SAutomerger Merge Worker {.name = "rttl", .id = O_RTTL, .type = XTTYPE_NONE,
45*a71a9546SAutomerger Merge Worker .excl = F_SET | F_REMOVE},
46*a71a9546SAutomerger Merge Worker {.name = "name", .id = O_NAME, .type = XTTYPE_STRING,
47*a71a9546SAutomerger Merge Worker .flags = XTOPT_PUT, XTOPT_POINTER(s, name)},
48*a71a9546SAutomerger Merge Worker {.name = "rsource", .id = O_RSOURCE, .type = XTTYPE_NONE},
49*a71a9546SAutomerger Merge Worker {.name = "rdest", .id = O_RDEST, .type = XTTYPE_NONE},
50*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND,
51*a71a9546SAutomerger Merge Worker };
52*a71a9546SAutomerger Merge Worker #undef s
53*a71a9546SAutomerger Merge Worker
54*a71a9546SAutomerger Merge Worker #define s struct xt_recent_mtinfo_v1
55*a71a9546SAutomerger Merge Worker static const struct xt_option_entry recent_opts_v1[] = {
56*a71a9546SAutomerger Merge Worker {.name = "set", .id = O_SET, .type = XTTYPE_NONE,
57*a71a9546SAutomerger Merge Worker .excl = F_ANY_OP, .flags = XTOPT_INVERT},
58*a71a9546SAutomerger Merge Worker {.name = "rcheck", .id = O_RCHECK, .type = XTTYPE_NONE,
59*a71a9546SAutomerger Merge Worker .excl = F_ANY_OP, .flags = XTOPT_INVERT},
60*a71a9546SAutomerger Merge Worker {.name = "update", .id = O_UPDATE, .type = XTTYPE_NONE,
61*a71a9546SAutomerger Merge Worker .excl = F_ANY_OP, .flags = XTOPT_INVERT},
62*a71a9546SAutomerger Merge Worker {.name = "remove", .id = O_REMOVE, .type = XTTYPE_NONE,
63*a71a9546SAutomerger Merge Worker .excl = F_ANY_OP, .flags = XTOPT_INVERT},
64*a71a9546SAutomerger Merge Worker {.name = "seconds", .id = O_SECONDS, .type = XTTYPE_UINT32,
65*a71a9546SAutomerger Merge Worker .flags = XTOPT_PUT, XTOPT_POINTER(s, seconds), .min = 1},
66*a71a9546SAutomerger Merge Worker {.name = "reap", .id = O_REAP, .type = XTTYPE_NONE,
67*a71a9546SAutomerger Merge Worker .also = F_SECONDS },
68*a71a9546SAutomerger Merge Worker {.name = "hitcount", .id = O_HITCOUNT, .type = XTTYPE_UINT32,
69*a71a9546SAutomerger Merge Worker .flags = XTOPT_PUT, XTOPT_POINTER(s, hit_count)},
70*a71a9546SAutomerger Merge Worker {.name = "rttl", .id = O_RTTL, .type = XTTYPE_NONE,
71*a71a9546SAutomerger Merge Worker .excl = F_SET | F_REMOVE},
72*a71a9546SAutomerger Merge Worker {.name = "name", .id = O_NAME, .type = XTTYPE_STRING,
73*a71a9546SAutomerger Merge Worker .flags = XTOPT_PUT, XTOPT_POINTER(s, name)},
74*a71a9546SAutomerger Merge Worker {.name = "rsource", .id = O_RSOURCE, .type = XTTYPE_NONE},
75*a71a9546SAutomerger Merge Worker {.name = "rdest", .id = O_RDEST, .type = XTTYPE_NONE},
76*a71a9546SAutomerger Merge Worker {.name = "mask", .id = O_MASK, .type = XTTYPE_HOST,
77*a71a9546SAutomerger Merge Worker .flags = XTOPT_PUT, XTOPT_POINTER(s, mask)},
78*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND,
79*a71a9546SAutomerger Merge Worker };
80*a71a9546SAutomerger Merge Worker #undef s
81*a71a9546SAutomerger Merge Worker
recent_help(void)82*a71a9546SAutomerger Merge Worker static void recent_help(void)
83*a71a9546SAutomerger Merge Worker {
84*a71a9546SAutomerger Merge Worker printf(
85*a71a9546SAutomerger Merge Worker "recent match options:\n"
86*a71a9546SAutomerger Merge Worker "[!] --set Add source address to list, always matches.\n"
87*a71a9546SAutomerger Merge Worker "[!] --rcheck Match if source address in list.\n"
88*a71a9546SAutomerger Merge Worker "[!] --update Match if source address in list, also update last-seen time.\n"
89*a71a9546SAutomerger Merge Worker "[!] --remove Match if source address in list, also removes that address from list.\n"
90*a71a9546SAutomerger Merge Worker " --seconds seconds For check and update commands above.\n"
91*a71a9546SAutomerger Merge Worker " Specifies that the match will only occur if source address last seen within\n"
92*a71a9546SAutomerger Merge Worker " the last 'seconds' seconds.\n"
93*a71a9546SAutomerger Merge Worker " --reap Purge entries older then 'seconds'.\n"
94*a71a9546SAutomerger Merge Worker " Can only be used in conjunction with the seconds option.\n"
95*a71a9546SAutomerger Merge Worker " --hitcount hits For check and update commands above.\n"
96*a71a9546SAutomerger Merge Worker " Specifies that the match will only occur if source address seen hits times.\n"
97*a71a9546SAutomerger Merge Worker " May be used in conjunction with the seconds option.\n"
98*a71a9546SAutomerger Merge Worker " --rttl For check and update commands above.\n"
99*a71a9546SAutomerger Merge Worker " Specifies that the match will only occur if the source address and the TTL\n"
100*a71a9546SAutomerger Merge Worker " match between this packet and the one which was set.\n"
101*a71a9546SAutomerger Merge Worker " Useful if you have problems with people spoofing their source address in order\n"
102*a71a9546SAutomerger Merge Worker " to DoS you via this module.\n"
103*a71a9546SAutomerger Merge Worker " --name name Name of the recent list to be used. DEFAULT used if none given.\n"
104*a71a9546SAutomerger Merge Worker " --rsource Match/Save the source address of each packet in the recent list table (default).\n"
105*a71a9546SAutomerger Merge Worker " --rdest Match/Save the destination address of each packet in the recent list table.\n"
106*a71a9546SAutomerger Merge Worker " --mask netmask Netmask that will be applied to this recent list.\n"
107*a71a9546SAutomerger Merge Worker "xt_recent by: Stephen Frost <[email protected]>.\n");
108*a71a9546SAutomerger Merge Worker }
109*a71a9546SAutomerger Merge Worker
110*a71a9546SAutomerger Merge Worker enum {
111*a71a9546SAutomerger Merge Worker XT_RECENT_REV_0 = 0,
112*a71a9546SAutomerger Merge Worker XT_RECENT_REV_1,
113*a71a9546SAutomerger Merge Worker };
114*a71a9546SAutomerger Merge Worker
recent_init(struct xt_entry_match * match,unsigned int rev)115*a71a9546SAutomerger Merge Worker static void recent_init(struct xt_entry_match *match, unsigned int rev)
116*a71a9546SAutomerger Merge Worker {
117*a71a9546SAutomerger Merge Worker struct xt_recent_mtinfo *info = (struct xt_recent_mtinfo *)match->data;
118*a71a9546SAutomerger Merge Worker struct xt_recent_mtinfo_v1 *info_v1 =
119*a71a9546SAutomerger Merge Worker (struct xt_recent_mtinfo_v1 *)match->data;
120*a71a9546SAutomerger Merge Worker
121*a71a9546SAutomerger Merge Worker strncpy(info->name,"DEFAULT", XT_RECENT_NAME_LEN);
122*a71a9546SAutomerger Merge Worker /* even though XT_RECENT_NAME_LEN is currently defined as 200,
123*a71a9546SAutomerger Merge Worker * better be safe, than sorry */
124*a71a9546SAutomerger Merge Worker info->name[XT_RECENT_NAME_LEN-1] = '\0';
125*a71a9546SAutomerger Merge Worker info->side = XT_RECENT_SOURCE;
126*a71a9546SAutomerger Merge Worker if (rev == XT_RECENT_REV_1)
127*a71a9546SAutomerger Merge Worker memset(&info_v1->mask, 0xFF, sizeof(info_v1->mask));
128*a71a9546SAutomerger Merge Worker }
129*a71a9546SAutomerger Merge Worker
recent_parse(struct xt_option_call * cb)130*a71a9546SAutomerger Merge Worker static void recent_parse(struct xt_option_call *cb)
131*a71a9546SAutomerger Merge Worker {
132*a71a9546SAutomerger Merge Worker struct xt_recent_mtinfo *info = cb->data;
133*a71a9546SAutomerger Merge Worker
134*a71a9546SAutomerger Merge Worker xtables_option_parse(cb);
135*a71a9546SAutomerger Merge Worker switch (cb->entry->id) {
136*a71a9546SAutomerger Merge Worker case O_SET:
137*a71a9546SAutomerger Merge Worker info->check_set |= XT_RECENT_SET;
138*a71a9546SAutomerger Merge Worker if (cb->invert)
139*a71a9546SAutomerger Merge Worker info->invert = true;
140*a71a9546SAutomerger Merge Worker break;
141*a71a9546SAutomerger Merge Worker case O_RCHECK:
142*a71a9546SAutomerger Merge Worker info->check_set |= XT_RECENT_CHECK;
143*a71a9546SAutomerger Merge Worker if (cb->invert)
144*a71a9546SAutomerger Merge Worker info->invert = true;
145*a71a9546SAutomerger Merge Worker break;
146*a71a9546SAutomerger Merge Worker case O_UPDATE:
147*a71a9546SAutomerger Merge Worker info->check_set |= XT_RECENT_UPDATE;
148*a71a9546SAutomerger Merge Worker if (cb->invert)
149*a71a9546SAutomerger Merge Worker info->invert = true;
150*a71a9546SAutomerger Merge Worker break;
151*a71a9546SAutomerger Merge Worker case O_REMOVE:
152*a71a9546SAutomerger Merge Worker info->check_set |= XT_RECENT_REMOVE;
153*a71a9546SAutomerger Merge Worker if (cb->invert)
154*a71a9546SAutomerger Merge Worker info->invert = true;
155*a71a9546SAutomerger Merge Worker break;
156*a71a9546SAutomerger Merge Worker case O_RTTL:
157*a71a9546SAutomerger Merge Worker info->check_set |= XT_RECENT_TTL;
158*a71a9546SAutomerger Merge Worker break;
159*a71a9546SAutomerger Merge Worker case O_RSOURCE:
160*a71a9546SAutomerger Merge Worker info->side = XT_RECENT_SOURCE;
161*a71a9546SAutomerger Merge Worker break;
162*a71a9546SAutomerger Merge Worker case O_RDEST:
163*a71a9546SAutomerger Merge Worker info->side = XT_RECENT_DEST;
164*a71a9546SAutomerger Merge Worker break;
165*a71a9546SAutomerger Merge Worker case O_REAP:
166*a71a9546SAutomerger Merge Worker info->check_set |= XT_RECENT_REAP;
167*a71a9546SAutomerger Merge Worker break;
168*a71a9546SAutomerger Merge Worker }
169*a71a9546SAutomerger Merge Worker }
170*a71a9546SAutomerger Merge Worker
recent_check(struct xt_fcheck_call * cb)171*a71a9546SAutomerger Merge Worker static void recent_check(struct xt_fcheck_call *cb)
172*a71a9546SAutomerger Merge Worker {
173*a71a9546SAutomerger Merge Worker if (!(cb->xflags & F_ANY_OP))
174*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
175*a71a9546SAutomerger Merge Worker "recent: you must specify one of `--set', `--rcheck' "
176*a71a9546SAutomerger Merge Worker "`--update' or `--remove'");
177*a71a9546SAutomerger Merge Worker }
178*a71a9546SAutomerger Merge Worker
recent_print(const void * ip,const struct xt_entry_match * match,unsigned int family)179*a71a9546SAutomerger Merge Worker static void recent_print(const void *ip, const struct xt_entry_match *match,
180*a71a9546SAutomerger Merge Worker unsigned int family)
181*a71a9546SAutomerger Merge Worker {
182*a71a9546SAutomerger Merge Worker const struct xt_recent_mtinfo_v1 *info = (const void *)match->data;
183*a71a9546SAutomerger Merge Worker
184*a71a9546SAutomerger Merge Worker if (info->invert)
185*a71a9546SAutomerger Merge Worker printf(" !");
186*a71a9546SAutomerger Merge Worker
187*a71a9546SAutomerger Merge Worker printf(" recent:");
188*a71a9546SAutomerger Merge Worker if (info->check_set & XT_RECENT_SET)
189*a71a9546SAutomerger Merge Worker printf(" SET");
190*a71a9546SAutomerger Merge Worker if (info->check_set & XT_RECENT_CHECK)
191*a71a9546SAutomerger Merge Worker printf(" CHECK");
192*a71a9546SAutomerger Merge Worker if (info->check_set & XT_RECENT_UPDATE)
193*a71a9546SAutomerger Merge Worker printf(" UPDATE");
194*a71a9546SAutomerger Merge Worker if (info->check_set & XT_RECENT_REMOVE)
195*a71a9546SAutomerger Merge Worker printf(" REMOVE");
196*a71a9546SAutomerger Merge Worker if(info->seconds) printf(" seconds: %d", info->seconds);
197*a71a9546SAutomerger Merge Worker if (info->check_set & XT_RECENT_REAP)
198*a71a9546SAutomerger Merge Worker printf(" reap");
199*a71a9546SAutomerger Merge Worker if(info->hit_count) printf(" hit_count: %d", info->hit_count);
200*a71a9546SAutomerger Merge Worker if (info->check_set & XT_RECENT_TTL)
201*a71a9546SAutomerger Merge Worker printf(" TTL-Match");
202*a71a9546SAutomerger Merge Worker printf(" name: %s", info->name);
203*a71a9546SAutomerger Merge Worker if (info->side == XT_RECENT_SOURCE)
204*a71a9546SAutomerger Merge Worker printf(" side: source");
205*a71a9546SAutomerger Merge Worker if (info->side == XT_RECENT_DEST)
206*a71a9546SAutomerger Merge Worker printf(" side: dest");
207*a71a9546SAutomerger Merge Worker
208*a71a9546SAutomerger Merge Worker switch(family) {
209*a71a9546SAutomerger Merge Worker case NFPROTO_IPV4:
210*a71a9546SAutomerger Merge Worker printf(" mask: %s",
211*a71a9546SAutomerger Merge Worker xtables_ipaddr_to_numeric(&info->mask.in));
212*a71a9546SAutomerger Merge Worker break;
213*a71a9546SAutomerger Merge Worker case NFPROTO_IPV6:
214*a71a9546SAutomerger Merge Worker printf(" mask: %s",
215*a71a9546SAutomerger Merge Worker xtables_ip6addr_to_numeric(&info->mask.in6));
216*a71a9546SAutomerger Merge Worker break;
217*a71a9546SAutomerger Merge Worker }
218*a71a9546SAutomerger Merge Worker }
219*a71a9546SAutomerger Merge Worker
recent_save(const void * ip,const struct xt_entry_match * match,unsigned int family)220*a71a9546SAutomerger Merge Worker static void recent_save(const void *ip, const struct xt_entry_match *match,
221*a71a9546SAutomerger Merge Worker unsigned int family)
222*a71a9546SAutomerger Merge Worker {
223*a71a9546SAutomerger Merge Worker const struct xt_recent_mtinfo_v1 *info = (const void *)match->data;
224*a71a9546SAutomerger Merge Worker
225*a71a9546SAutomerger Merge Worker if (info->invert)
226*a71a9546SAutomerger Merge Worker printf(" !");
227*a71a9546SAutomerger Merge Worker
228*a71a9546SAutomerger Merge Worker if (info->check_set & XT_RECENT_SET)
229*a71a9546SAutomerger Merge Worker printf(" --set");
230*a71a9546SAutomerger Merge Worker if (info->check_set & XT_RECENT_CHECK)
231*a71a9546SAutomerger Merge Worker printf(" --rcheck");
232*a71a9546SAutomerger Merge Worker if (info->check_set & XT_RECENT_UPDATE)
233*a71a9546SAutomerger Merge Worker printf(" --update");
234*a71a9546SAutomerger Merge Worker if (info->check_set & XT_RECENT_REMOVE)
235*a71a9546SAutomerger Merge Worker printf(" --remove");
236*a71a9546SAutomerger Merge Worker if(info->seconds) printf(" --seconds %d", info->seconds);
237*a71a9546SAutomerger Merge Worker if (info->check_set & XT_RECENT_REAP)
238*a71a9546SAutomerger Merge Worker printf(" --reap");
239*a71a9546SAutomerger Merge Worker if(info->hit_count) printf(" --hitcount %d", info->hit_count);
240*a71a9546SAutomerger Merge Worker if (info->check_set & XT_RECENT_TTL)
241*a71a9546SAutomerger Merge Worker printf(" --rttl");
242*a71a9546SAutomerger Merge Worker printf(" --name %s",info->name);
243*a71a9546SAutomerger Merge Worker
244*a71a9546SAutomerger Merge Worker switch(family) {
245*a71a9546SAutomerger Merge Worker case NFPROTO_IPV4:
246*a71a9546SAutomerger Merge Worker printf(" --mask %s",
247*a71a9546SAutomerger Merge Worker xtables_ipaddr_to_numeric(&info->mask.in));
248*a71a9546SAutomerger Merge Worker break;
249*a71a9546SAutomerger Merge Worker case NFPROTO_IPV6:
250*a71a9546SAutomerger Merge Worker printf(" --mask %s",
251*a71a9546SAutomerger Merge Worker xtables_ip6addr_to_numeric(&info->mask.in6));
252*a71a9546SAutomerger Merge Worker break;
253*a71a9546SAutomerger Merge Worker }
254*a71a9546SAutomerger Merge Worker
255*a71a9546SAutomerger Merge Worker if (info->side == XT_RECENT_SOURCE)
256*a71a9546SAutomerger Merge Worker printf(" --rsource");
257*a71a9546SAutomerger Merge Worker if (info->side == XT_RECENT_DEST)
258*a71a9546SAutomerger Merge Worker printf(" --rdest");
259*a71a9546SAutomerger Merge Worker }
260*a71a9546SAutomerger Merge Worker
recent_init_v0(struct xt_entry_match * match)261*a71a9546SAutomerger Merge Worker static void recent_init_v0(struct xt_entry_match *match)
262*a71a9546SAutomerger Merge Worker {
263*a71a9546SAutomerger Merge Worker recent_init(match, XT_RECENT_REV_0);
264*a71a9546SAutomerger Merge Worker }
265*a71a9546SAutomerger Merge Worker
recent_init_v1(struct xt_entry_match * match)266*a71a9546SAutomerger Merge Worker static void recent_init_v1(struct xt_entry_match *match)
267*a71a9546SAutomerger Merge Worker {
268*a71a9546SAutomerger Merge Worker recent_init(match, XT_RECENT_REV_1);
269*a71a9546SAutomerger Merge Worker }
270*a71a9546SAutomerger Merge Worker
recent_save_v0(const void * ip,const struct xt_entry_match * match)271*a71a9546SAutomerger Merge Worker static void recent_save_v0(const void *ip, const struct xt_entry_match *match)
272*a71a9546SAutomerger Merge Worker {
273*a71a9546SAutomerger Merge Worker recent_save(ip, match, NFPROTO_UNSPEC);
274*a71a9546SAutomerger Merge Worker }
275*a71a9546SAutomerger Merge Worker
recent_save_v4(const void * ip,const struct xt_entry_match * match)276*a71a9546SAutomerger Merge Worker static void recent_save_v4(const void *ip, const struct xt_entry_match *match)
277*a71a9546SAutomerger Merge Worker {
278*a71a9546SAutomerger Merge Worker recent_save(ip, match, NFPROTO_IPV4);
279*a71a9546SAutomerger Merge Worker }
280*a71a9546SAutomerger Merge Worker
recent_save_v6(const void * ip,const struct xt_entry_match * match)281*a71a9546SAutomerger Merge Worker static void recent_save_v6(const void *ip, const struct xt_entry_match *match)
282*a71a9546SAutomerger Merge Worker {
283*a71a9546SAutomerger Merge Worker recent_save(ip, match, NFPROTO_IPV6);
284*a71a9546SAutomerger Merge Worker }
285*a71a9546SAutomerger Merge Worker
recent_print_v0(const void * ip,const struct xt_entry_match * match,int numeric)286*a71a9546SAutomerger Merge Worker static void recent_print_v0(const void *ip, const struct xt_entry_match *match,
287*a71a9546SAutomerger Merge Worker int numeric)
288*a71a9546SAutomerger Merge Worker {
289*a71a9546SAutomerger Merge Worker recent_print(ip, match, NFPROTO_UNSPEC);
290*a71a9546SAutomerger Merge Worker }
291*a71a9546SAutomerger Merge Worker
recent_print_v4(const void * ip,const struct xt_entry_match * match,int numeric)292*a71a9546SAutomerger Merge Worker static void recent_print_v4(const void *ip, const struct xt_entry_match *match,
293*a71a9546SAutomerger Merge Worker int numeric)
294*a71a9546SAutomerger Merge Worker {
295*a71a9546SAutomerger Merge Worker recent_print(ip, match, NFPROTO_IPV4);
296*a71a9546SAutomerger Merge Worker }
297*a71a9546SAutomerger Merge Worker
recent_print_v6(const void * ip,const struct xt_entry_match * match,int numeric)298*a71a9546SAutomerger Merge Worker static void recent_print_v6(const void *ip, const struct xt_entry_match *match,
299*a71a9546SAutomerger Merge Worker int numeric)
300*a71a9546SAutomerger Merge Worker {
301*a71a9546SAutomerger Merge Worker recent_print(ip, match, NFPROTO_IPV6);
302*a71a9546SAutomerger Merge Worker }
303*a71a9546SAutomerger Merge Worker
304*a71a9546SAutomerger Merge Worker static struct xtables_match recent_mt_reg[] = {
305*a71a9546SAutomerger Merge Worker {
306*a71a9546SAutomerger Merge Worker .name = "recent",
307*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
308*a71a9546SAutomerger Merge Worker .revision = 0,
309*a71a9546SAutomerger Merge Worker .family = NFPROTO_UNSPEC,
310*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
311*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo)),
312*a71a9546SAutomerger Merge Worker .help = recent_help,
313*a71a9546SAutomerger Merge Worker .init = recent_init_v0,
314*a71a9546SAutomerger Merge Worker .x6_parse = recent_parse,
315*a71a9546SAutomerger Merge Worker .x6_fcheck = recent_check,
316*a71a9546SAutomerger Merge Worker .print = recent_print_v0,
317*a71a9546SAutomerger Merge Worker .save = recent_save_v0,
318*a71a9546SAutomerger Merge Worker .x6_options = recent_opts_v0,
319*a71a9546SAutomerger Merge Worker },
320*a71a9546SAutomerger Merge Worker {
321*a71a9546SAutomerger Merge Worker .name = "recent",
322*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
323*a71a9546SAutomerger Merge Worker .revision = 1,
324*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV4,
325*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo_v1)),
326*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo_v1)),
327*a71a9546SAutomerger Merge Worker .help = recent_help,
328*a71a9546SAutomerger Merge Worker .init = recent_init_v1,
329*a71a9546SAutomerger Merge Worker .x6_parse = recent_parse,
330*a71a9546SAutomerger Merge Worker .x6_fcheck = recent_check,
331*a71a9546SAutomerger Merge Worker .print = recent_print_v4,
332*a71a9546SAutomerger Merge Worker .save = recent_save_v4,
333*a71a9546SAutomerger Merge Worker .x6_options = recent_opts_v1,
334*a71a9546SAutomerger Merge Worker },
335*a71a9546SAutomerger Merge Worker {
336*a71a9546SAutomerger Merge Worker .name = "recent",
337*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
338*a71a9546SAutomerger Merge Worker .revision = 1,
339*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV6,
340*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_recent_mtinfo_v1)),
341*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_recent_mtinfo_v1)),
342*a71a9546SAutomerger Merge Worker .help = recent_help,
343*a71a9546SAutomerger Merge Worker .init = recent_init_v1,
344*a71a9546SAutomerger Merge Worker .x6_parse = recent_parse,
345*a71a9546SAutomerger Merge Worker .x6_fcheck = recent_check,
346*a71a9546SAutomerger Merge Worker .print = recent_print_v6,
347*a71a9546SAutomerger Merge Worker .save = recent_save_v6,
348*a71a9546SAutomerger Merge Worker .x6_options = recent_opts_v1,
349*a71a9546SAutomerger Merge Worker },
350*a71a9546SAutomerger Merge Worker };
351*a71a9546SAutomerger Merge Worker
_init(void)352*a71a9546SAutomerger Merge Worker void _init(void)
353*a71a9546SAutomerger Merge Worker {
354*a71a9546SAutomerger Merge Worker xtables_register_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg));
355*a71a9546SAutomerger Merge Worker }
356