1*a71a9546SAutomerger Merge Worker /* Copyright (C) 2000-2002 Joakim Axelsson <[email protected]>
2*a71a9546SAutomerger Merge Worker * Patrick Schaaf <[email protected]>
3*a71a9546SAutomerger Merge Worker * Martin Josefsson <[email protected]>
4*a71a9546SAutomerger Merge Worker * Copyright (C) 2003-2010 Jozsef Kadlecsik <[email protected]>
5*a71a9546SAutomerger Merge Worker *
6*a71a9546SAutomerger Merge Worker * This program is free software; you can redistribute it and/or modify
7*a71a9546SAutomerger Merge Worker * it under the terms of the GNU General Public License version 2 as
8*a71a9546SAutomerger Merge Worker * published by the Free Software Foundation.
9*a71a9546SAutomerger Merge Worker */
10*a71a9546SAutomerger Merge Worker
11*a71a9546SAutomerger Merge Worker /* Shared library add-on to iptables to add IP set mangling target. */
12*a71a9546SAutomerger Merge Worker #include <stdbool.h>
13*a71a9546SAutomerger Merge Worker #include <stdio.h>
14*a71a9546SAutomerger Merge Worker #include <netdb.h>
15*a71a9546SAutomerger Merge Worker #include <string.h>
16*a71a9546SAutomerger Merge Worker #include <stdlib.h>
17*a71a9546SAutomerger Merge Worker #include <getopt.h>
18*a71a9546SAutomerger Merge Worker #include <ctype.h>
19*a71a9546SAutomerger Merge Worker
20*a71a9546SAutomerger Merge Worker #include <xtables.h>
21*a71a9546SAutomerger Merge Worker #include <linux/netfilter/xt_set.h>
22*a71a9546SAutomerger Merge Worker #include "libxt_set.h"
23*a71a9546SAutomerger Merge Worker
24*a71a9546SAutomerger Merge Worker /* Revision 0 */
25*a71a9546SAutomerger Merge Worker
26*a71a9546SAutomerger Merge Worker static void
set_target_help_v0(void)27*a71a9546SAutomerger Merge Worker set_target_help_v0(void)
28*a71a9546SAutomerger Merge Worker {
29*a71a9546SAutomerger Merge Worker printf("SET target options:\n"
30*a71a9546SAutomerger Merge Worker " --add-set name flags\n"
31*a71a9546SAutomerger Merge Worker " --del-set name flags\n"
32*a71a9546SAutomerger Merge Worker " add/del src/dst IP/port from/to named sets,\n"
33*a71a9546SAutomerger Merge Worker " where flags are the comma separated list of\n"
34*a71a9546SAutomerger Merge Worker " 'src' and 'dst' specifications.\n");
35*a71a9546SAutomerger Merge Worker }
36*a71a9546SAutomerger Merge Worker
37*a71a9546SAutomerger Merge Worker static const struct option set_target_opts_v0[] = {
38*a71a9546SAutomerger Merge Worker {.name = "add-set", .has_arg = true, .val = '1'},
39*a71a9546SAutomerger Merge Worker {.name = "del-set", .has_arg = true, .val = '2'},
40*a71a9546SAutomerger Merge Worker XT_GETOPT_TABLEEND,
41*a71a9546SAutomerger Merge Worker };
42*a71a9546SAutomerger Merge Worker
43*a71a9546SAutomerger Merge Worker static void
set_target_check_v0(unsigned int flags)44*a71a9546SAutomerger Merge Worker set_target_check_v0(unsigned int flags)
45*a71a9546SAutomerger Merge Worker {
46*a71a9546SAutomerger Merge Worker if (!flags)
47*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
48*a71a9546SAutomerger Merge Worker "You must specify either `--add-set' or `--del-set'");
49*a71a9546SAutomerger Merge Worker }
50*a71a9546SAutomerger Merge Worker
51*a71a9546SAutomerger Merge Worker static void
set_target_init_v0(struct xt_entry_target * target)52*a71a9546SAutomerger Merge Worker set_target_init_v0(struct xt_entry_target *target)
53*a71a9546SAutomerger Merge Worker {
54*a71a9546SAutomerger Merge Worker struct xt_set_info_target_v0 *info =
55*a71a9546SAutomerger Merge Worker (struct xt_set_info_target_v0 *) target->data;
56*a71a9546SAutomerger Merge Worker
57*a71a9546SAutomerger Merge Worker info->add_set.index =
58*a71a9546SAutomerger Merge Worker info->del_set.index = IPSET_INVALID_ID;
59*a71a9546SAutomerger Merge Worker
60*a71a9546SAutomerger Merge Worker }
61*a71a9546SAutomerger Merge Worker
62*a71a9546SAutomerger Merge Worker static void
parse_target_v0(char ** argv,int invert,unsigned int * flags,struct xt_set_info_v0 * info,const char * what)63*a71a9546SAutomerger Merge Worker parse_target_v0(char **argv, int invert, unsigned int *flags,
64*a71a9546SAutomerger Merge Worker struct xt_set_info_v0 *info, const char *what)
65*a71a9546SAutomerger Merge Worker {
66*a71a9546SAutomerger Merge Worker if (info->u.flags[0])
67*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
68*a71a9546SAutomerger Merge Worker "--%s can be specified only once", what);
69*a71a9546SAutomerger Merge Worker
70*a71a9546SAutomerger Merge Worker if (!argv[optind]
71*a71a9546SAutomerger Merge Worker || argv[optind][0] == '-' || argv[optind][0] == '!')
72*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
73*a71a9546SAutomerger Merge Worker "--%s requires two args.", what);
74*a71a9546SAutomerger Merge Worker
75*a71a9546SAutomerger Merge Worker if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
76*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
77*a71a9546SAutomerger Merge Worker "setname `%s' too long, max %d characters.",
78*a71a9546SAutomerger Merge Worker optarg, IPSET_MAXNAMELEN - 1);
79*a71a9546SAutomerger Merge Worker
80*a71a9546SAutomerger Merge Worker get_set_byname(optarg, (struct xt_set_info *)info);
81*a71a9546SAutomerger Merge Worker parse_dirs_v0(argv[optind], info);
82*a71a9546SAutomerger Merge Worker optind++;
83*a71a9546SAutomerger Merge Worker
84*a71a9546SAutomerger Merge Worker *flags = 1;
85*a71a9546SAutomerger Merge Worker }
86*a71a9546SAutomerger Merge Worker
87*a71a9546SAutomerger Merge Worker static int
set_target_parse_v0(int c,char ** argv,int invert,unsigned int * flags,const void * entry,struct xt_entry_target ** target)88*a71a9546SAutomerger Merge Worker set_target_parse_v0(int c, char **argv, int invert, unsigned int *flags,
89*a71a9546SAutomerger Merge Worker const void *entry, struct xt_entry_target **target)
90*a71a9546SAutomerger Merge Worker {
91*a71a9546SAutomerger Merge Worker struct xt_set_info_target_v0 *myinfo =
92*a71a9546SAutomerger Merge Worker (struct xt_set_info_target_v0 *) (*target)->data;
93*a71a9546SAutomerger Merge Worker
94*a71a9546SAutomerger Merge Worker switch (c) {
95*a71a9546SAutomerger Merge Worker case '1': /* --add-set <set> <flags> */
96*a71a9546SAutomerger Merge Worker parse_target_v0(argv, invert, flags,
97*a71a9546SAutomerger Merge Worker &myinfo->add_set, "add-set");
98*a71a9546SAutomerger Merge Worker break;
99*a71a9546SAutomerger Merge Worker case '2': /* --del-set <set>[:<flags>] <flags> */
100*a71a9546SAutomerger Merge Worker parse_target_v0(argv, invert, flags,
101*a71a9546SAutomerger Merge Worker &myinfo->del_set, "del-set");
102*a71a9546SAutomerger Merge Worker break;
103*a71a9546SAutomerger Merge Worker }
104*a71a9546SAutomerger Merge Worker return 1;
105*a71a9546SAutomerger Merge Worker }
106*a71a9546SAutomerger Merge Worker
107*a71a9546SAutomerger Merge Worker static void
print_target_v0(const char * prefix,const struct xt_set_info_v0 * info)108*a71a9546SAutomerger Merge Worker print_target_v0(const char *prefix, const struct xt_set_info_v0 *info)
109*a71a9546SAutomerger Merge Worker {
110*a71a9546SAutomerger Merge Worker int i;
111*a71a9546SAutomerger Merge Worker char setname[IPSET_MAXNAMELEN];
112*a71a9546SAutomerger Merge Worker
113*a71a9546SAutomerger Merge Worker if (info->index == IPSET_INVALID_ID)
114*a71a9546SAutomerger Merge Worker return;
115*a71a9546SAutomerger Merge Worker get_set_byid(setname, info->index);
116*a71a9546SAutomerger Merge Worker printf(" %s %s", prefix, setname);
117*a71a9546SAutomerger Merge Worker for (i = 0; i < IPSET_DIM_MAX; i++) {
118*a71a9546SAutomerger Merge Worker if (!info->u.flags[i])
119*a71a9546SAutomerger Merge Worker break;
120*a71a9546SAutomerger Merge Worker printf("%s%s",
121*a71a9546SAutomerger Merge Worker i == 0 ? " " : ",",
122*a71a9546SAutomerger Merge Worker info->u.flags[i] & IPSET_SRC ? "src" : "dst");
123*a71a9546SAutomerger Merge Worker }
124*a71a9546SAutomerger Merge Worker }
125*a71a9546SAutomerger Merge Worker
126*a71a9546SAutomerger Merge Worker static void
set_target_print_v0(const void * ip,const struct xt_entry_target * target,int numeric)127*a71a9546SAutomerger Merge Worker set_target_print_v0(const void *ip, const struct xt_entry_target *target,
128*a71a9546SAutomerger Merge Worker int numeric)
129*a71a9546SAutomerger Merge Worker {
130*a71a9546SAutomerger Merge Worker const struct xt_set_info_target_v0 *info = (const void *)target->data;
131*a71a9546SAutomerger Merge Worker
132*a71a9546SAutomerger Merge Worker print_target_v0("add-set", &info->add_set);
133*a71a9546SAutomerger Merge Worker print_target_v0("del-set", &info->del_set);
134*a71a9546SAutomerger Merge Worker }
135*a71a9546SAutomerger Merge Worker
136*a71a9546SAutomerger Merge Worker static void
set_target_save_v0(const void * ip,const struct xt_entry_target * target)137*a71a9546SAutomerger Merge Worker set_target_save_v0(const void *ip, const struct xt_entry_target *target)
138*a71a9546SAutomerger Merge Worker {
139*a71a9546SAutomerger Merge Worker const struct xt_set_info_target_v0 *info = (const void *)target->data;
140*a71a9546SAutomerger Merge Worker
141*a71a9546SAutomerger Merge Worker print_target_v0("--add-set", &info->add_set);
142*a71a9546SAutomerger Merge Worker print_target_v0("--del-set", &info->del_set);
143*a71a9546SAutomerger Merge Worker }
144*a71a9546SAutomerger Merge Worker
145*a71a9546SAutomerger Merge Worker /* Revision 1 */
146*a71a9546SAutomerger Merge Worker static void
set_target_init_v1(struct xt_entry_target * target)147*a71a9546SAutomerger Merge Worker set_target_init_v1(struct xt_entry_target *target)
148*a71a9546SAutomerger Merge Worker {
149*a71a9546SAutomerger Merge Worker struct xt_set_info_target_v1 *info =
150*a71a9546SAutomerger Merge Worker (struct xt_set_info_target_v1 *) target->data;
151*a71a9546SAutomerger Merge Worker
152*a71a9546SAutomerger Merge Worker info->add_set.index =
153*a71a9546SAutomerger Merge Worker info->del_set.index = IPSET_INVALID_ID;
154*a71a9546SAutomerger Merge Worker
155*a71a9546SAutomerger Merge Worker }
156*a71a9546SAutomerger Merge Worker
157*a71a9546SAutomerger Merge Worker #define SET_TARGET_ADD 0x1
158*a71a9546SAutomerger Merge Worker #define SET_TARGET_DEL 0x2
159*a71a9546SAutomerger Merge Worker #define SET_TARGET_EXIST 0x4
160*a71a9546SAutomerger Merge Worker #define SET_TARGET_TIMEOUT 0x8
161*a71a9546SAutomerger Merge Worker #define SET_TARGET_MAP 0x10
162*a71a9546SAutomerger Merge Worker #define SET_TARGET_MAP_MARK 0x20
163*a71a9546SAutomerger Merge Worker #define SET_TARGET_MAP_PRIO 0x40
164*a71a9546SAutomerger Merge Worker #define SET_TARGET_MAP_QUEUE 0x80
165*a71a9546SAutomerger Merge Worker
166*a71a9546SAutomerger Merge Worker static void
parse_target(char ** argv,int invert,struct xt_set_info * info,const char * what)167*a71a9546SAutomerger Merge Worker parse_target(char **argv, int invert, struct xt_set_info *info,
168*a71a9546SAutomerger Merge Worker const char *what)
169*a71a9546SAutomerger Merge Worker {
170*a71a9546SAutomerger Merge Worker if (info->dim)
171*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
172*a71a9546SAutomerger Merge Worker "--%s can be specified only once", what);
173*a71a9546SAutomerger Merge Worker if (!argv[optind]
174*a71a9546SAutomerger Merge Worker || argv[optind][0] == '-' || argv[optind][0] == '!')
175*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
176*a71a9546SAutomerger Merge Worker "--%s requires two args.", what);
177*a71a9546SAutomerger Merge Worker
178*a71a9546SAutomerger Merge Worker if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
179*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
180*a71a9546SAutomerger Merge Worker "setname `%s' too long, max %d characters.",
181*a71a9546SAutomerger Merge Worker optarg, IPSET_MAXNAMELEN - 1);
182*a71a9546SAutomerger Merge Worker
183*a71a9546SAutomerger Merge Worker get_set_byname(optarg, info);
184*a71a9546SAutomerger Merge Worker parse_dirs(argv[optind], info);
185*a71a9546SAutomerger Merge Worker optind++;
186*a71a9546SAutomerger Merge Worker }
187*a71a9546SAutomerger Merge Worker
188*a71a9546SAutomerger Merge Worker static int
set_target_parse_v1(int c,char ** argv,int invert,unsigned int * flags,const void * entry,struct xt_entry_target ** target)189*a71a9546SAutomerger Merge Worker set_target_parse_v1(int c, char **argv, int invert, unsigned int *flags,
190*a71a9546SAutomerger Merge Worker const void *entry, struct xt_entry_target **target)
191*a71a9546SAutomerger Merge Worker {
192*a71a9546SAutomerger Merge Worker struct xt_set_info_target_v1 *myinfo =
193*a71a9546SAutomerger Merge Worker (struct xt_set_info_target_v1 *) (*target)->data;
194*a71a9546SAutomerger Merge Worker
195*a71a9546SAutomerger Merge Worker switch (c) {
196*a71a9546SAutomerger Merge Worker case '1': /* --add-set <set> <flags> */
197*a71a9546SAutomerger Merge Worker parse_target(argv, invert, &myinfo->add_set, "add-set");
198*a71a9546SAutomerger Merge Worker *flags |= SET_TARGET_ADD;
199*a71a9546SAutomerger Merge Worker break;
200*a71a9546SAutomerger Merge Worker case '2': /* --del-set <set>[:<flags>] <flags> */
201*a71a9546SAutomerger Merge Worker parse_target(argv, invert, &myinfo->del_set, "del-set");
202*a71a9546SAutomerger Merge Worker *flags |= SET_TARGET_DEL;
203*a71a9546SAutomerger Merge Worker break;
204*a71a9546SAutomerger Merge Worker }
205*a71a9546SAutomerger Merge Worker return 1;
206*a71a9546SAutomerger Merge Worker }
207*a71a9546SAutomerger Merge Worker
208*a71a9546SAutomerger Merge Worker static void
print_target(const char * prefix,const struct xt_set_info * info)209*a71a9546SAutomerger Merge Worker print_target(const char *prefix, const struct xt_set_info *info)
210*a71a9546SAutomerger Merge Worker {
211*a71a9546SAutomerger Merge Worker int i;
212*a71a9546SAutomerger Merge Worker char setname[IPSET_MAXNAMELEN];
213*a71a9546SAutomerger Merge Worker
214*a71a9546SAutomerger Merge Worker if (info->index == IPSET_INVALID_ID)
215*a71a9546SAutomerger Merge Worker return;
216*a71a9546SAutomerger Merge Worker get_set_byid(setname, info->index);
217*a71a9546SAutomerger Merge Worker printf(" %s %s", prefix, setname);
218*a71a9546SAutomerger Merge Worker for (i = 1; i <= info->dim; i++) {
219*a71a9546SAutomerger Merge Worker printf("%s%s",
220*a71a9546SAutomerger Merge Worker i == 1 ? " " : ",",
221*a71a9546SAutomerger Merge Worker info->flags & (1 << i) ? "src" : "dst");
222*a71a9546SAutomerger Merge Worker }
223*a71a9546SAutomerger Merge Worker }
224*a71a9546SAutomerger Merge Worker
225*a71a9546SAutomerger Merge Worker static void
set_target_print_v1(const void * ip,const struct xt_entry_target * target,int numeric)226*a71a9546SAutomerger Merge Worker set_target_print_v1(const void *ip, const struct xt_entry_target *target,
227*a71a9546SAutomerger Merge Worker int numeric)
228*a71a9546SAutomerger Merge Worker {
229*a71a9546SAutomerger Merge Worker const struct xt_set_info_target_v1 *info = (const void *)target->data;
230*a71a9546SAutomerger Merge Worker
231*a71a9546SAutomerger Merge Worker print_target("add-set", &info->add_set);
232*a71a9546SAutomerger Merge Worker print_target("del-set", &info->del_set);
233*a71a9546SAutomerger Merge Worker }
234*a71a9546SAutomerger Merge Worker
235*a71a9546SAutomerger Merge Worker static void
set_target_save_v1(const void * ip,const struct xt_entry_target * target)236*a71a9546SAutomerger Merge Worker set_target_save_v1(const void *ip, const struct xt_entry_target *target)
237*a71a9546SAutomerger Merge Worker {
238*a71a9546SAutomerger Merge Worker const struct xt_set_info_target_v1 *info = (const void *)target->data;
239*a71a9546SAutomerger Merge Worker
240*a71a9546SAutomerger Merge Worker print_target("--add-set", &info->add_set);
241*a71a9546SAutomerger Merge Worker print_target("--del-set", &info->del_set);
242*a71a9546SAutomerger Merge Worker }
243*a71a9546SAutomerger Merge Worker
244*a71a9546SAutomerger Merge Worker /* Revision 2 */
245*a71a9546SAutomerger Merge Worker
246*a71a9546SAutomerger Merge Worker static void
set_target_help_v2(void)247*a71a9546SAutomerger Merge Worker set_target_help_v2(void)
248*a71a9546SAutomerger Merge Worker {
249*a71a9546SAutomerger Merge Worker printf("SET target options:\n"
250*a71a9546SAutomerger Merge Worker " --add-set name flags [--exist] [--timeout n]\n"
251*a71a9546SAutomerger Merge Worker " --del-set name flags\n"
252*a71a9546SAutomerger Merge Worker " add/del src/dst IP/port from/to named sets,\n"
253*a71a9546SAutomerger Merge Worker " where flags are the comma separated list of\n"
254*a71a9546SAutomerger Merge Worker " 'src' and 'dst' specifications.\n");
255*a71a9546SAutomerger Merge Worker }
256*a71a9546SAutomerger Merge Worker
257*a71a9546SAutomerger Merge Worker static const struct option set_target_opts_v2[] = {
258*a71a9546SAutomerger Merge Worker {.name = "add-set", .has_arg = true, .val = '1'},
259*a71a9546SAutomerger Merge Worker {.name = "del-set", .has_arg = true, .val = '2'},
260*a71a9546SAutomerger Merge Worker {.name = "exist", .has_arg = false, .val = '3'},
261*a71a9546SAutomerger Merge Worker {.name = "timeout", .has_arg = true, .val = '4'},
262*a71a9546SAutomerger Merge Worker XT_GETOPT_TABLEEND,
263*a71a9546SAutomerger Merge Worker };
264*a71a9546SAutomerger Merge Worker
265*a71a9546SAutomerger Merge Worker static void
set_target_check_v2(unsigned int flags)266*a71a9546SAutomerger Merge Worker set_target_check_v2(unsigned int flags)
267*a71a9546SAutomerger Merge Worker {
268*a71a9546SAutomerger Merge Worker if (!(flags & (SET_TARGET_ADD|SET_TARGET_DEL)))
269*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
270*a71a9546SAutomerger Merge Worker "You must specify either `--add-set' or `--del-set'");
271*a71a9546SAutomerger Merge Worker if (!(flags & SET_TARGET_ADD)) {
272*a71a9546SAutomerger Merge Worker if (flags & SET_TARGET_EXIST)
273*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
274*a71a9546SAutomerger Merge Worker "Flag `--exist' can be used with `--add-set' only");
275*a71a9546SAutomerger Merge Worker if (flags & SET_TARGET_TIMEOUT)
276*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
277*a71a9546SAutomerger Merge Worker "Option `--timeout' can be used with `--add-set' only");
278*a71a9546SAutomerger Merge Worker }
279*a71a9546SAutomerger Merge Worker }
280*a71a9546SAutomerger Merge Worker
281*a71a9546SAutomerger Merge Worker
282*a71a9546SAutomerger Merge Worker static void
set_target_init_v2(struct xt_entry_target * target)283*a71a9546SAutomerger Merge Worker set_target_init_v2(struct xt_entry_target *target)
284*a71a9546SAutomerger Merge Worker {
285*a71a9546SAutomerger Merge Worker struct xt_set_info_target_v2 *info =
286*a71a9546SAutomerger Merge Worker (struct xt_set_info_target_v2 *) target->data;
287*a71a9546SAutomerger Merge Worker
288*a71a9546SAutomerger Merge Worker info->add_set.index =
289*a71a9546SAutomerger Merge Worker info->del_set.index = IPSET_INVALID_ID;
290*a71a9546SAutomerger Merge Worker info->timeout = UINT32_MAX;
291*a71a9546SAutomerger Merge Worker }
292*a71a9546SAutomerger Merge Worker
293*a71a9546SAutomerger Merge Worker static int
set_target_parse_v2(int c,char ** argv,int invert,unsigned int * flags,const void * entry,struct xt_entry_target ** target)294*a71a9546SAutomerger Merge Worker set_target_parse_v2(int c, char **argv, int invert, unsigned int *flags,
295*a71a9546SAutomerger Merge Worker const void *entry, struct xt_entry_target **target)
296*a71a9546SAutomerger Merge Worker {
297*a71a9546SAutomerger Merge Worker struct xt_set_info_target_v2 *myinfo =
298*a71a9546SAutomerger Merge Worker (struct xt_set_info_target_v2 *) (*target)->data;
299*a71a9546SAutomerger Merge Worker unsigned int timeout;
300*a71a9546SAutomerger Merge Worker
301*a71a9546SAutomerger Merge Worker switch (c) {
302*a71a9546SAutomerger Merge Worker case '1': /* --add-set <set> <flags> */
303*a71a9546SAutomerger Merge Worker parse_target(argv, invert, &myinfo->add_set, "add-set");
304*a71a9546SAutomerger Merge Worker *flags |= SET_TARGET_ADD;
305*a71a9546SAutomerger Merge Worker break;
306*a71a9546SAutomerger Merge Worker case '2': /* --del-set <set>[:<flags>] <flags> */
307*a71a9546SAutomerger Merge Worker parse_target(argv, invert, &myinfo->del_set, "del-set");
308*a71a9546SAutomerger Merge Worker *flags |= SET_TARGET_DEL;
309*a71a9546SAutomerger Merge Worker break;
310*a71a9546SAutomerger Merge Worker case '3':
311*a71a9546SAutomerger Merge Worker myinfo->flags |= IPSET_FLAG_EXIST;
312*a71a9546SAutomerger Merge Worker *flags |= SET_TARGET_EXIST;
313*a71a9546SAutomerger Merge Worker break;
314*a71a9546SAutomerger Merge Worker case '4':
315*a71a9546SAutomerger Merge Worker if (!xtables_strtoui(optarg, NULL, &timeout, 0, UINT32_MAX - 1))
316*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
317*a71a9546SAutomerger Merge Worker "Invalid value for option --timeout "
318*a71a9546SAutomerger Merge Worker "or out of range 0-%u", UINT32_MAX - 1);
319*a71a9546SAutomerger Merge Worker myinfo->timeout = timeout;
320*a71a9546SAutomerger Merge Worker *flags |= SET_TARGET_TIMEOUT;
321*a71a9546SAutomerger Merge Worker break;
322*a71a9546SAutomerger Merge Worker }
323*a71a9546SAutomerger Merge Worker return 1;
324*a71a9546SAutomerger Merge Worker }
325*a71a9546SAutomerger Merge Worker
326*a71a9546SAutomerger Merge Worker static void
set_target_print_v2(const void * ip,const struct xt_entry_target * target,int numeric)327*a71a9546SAutomerger Merge Worker set_target_print_v2(const void *ip, const struct xt_entry_target *target,
328*a71a9546SAutomerger Merge Worker int numeric)
329*a71a9546SAutomerger Merge Worker {
330*a71a9546SAutomerger Merge Worker const struct xt_set_info_target_v2 *info = (const void *)target->data;
331*a71a9546SAutomerger Merge Worker
332*a71a9546SAutomerger Merge Worker print_target("add-set", &info->add_set);
333*a71a9546SAutomerger Merge Worker if (info->flags & IPSET_FLAG_EXIST)
334*a71a9546SAutomerger Merge Worker printf(" exist");
335*a71a9546SAutomerger Merge Worker if (info->timeout != UINT32_MAX)
336*a71a9546SAutomerger Merge Worker printf(" timeout %u", info->timeout);
337*a71a9546SAutomerger Merge Worker print_target("del-set", &info->del_set);
338*a71a9546SAutomerger Merge Worker }
339*a71a9546SAutomerger Merge Worker
340*a71a9546SAutomerger Merge Worker static void
set_target_save_v2(const void * ip,const struct xt_entry_target * target)341*a71a9546SAutomerger Merge Worker set_target_save_v2(const void *ip, const struct xt_entry_target *target)
342*a71a9546SAutomerger Merge Worker {
343*a71a9546SAutomerger Merge Worker const struct xt_set_info_target_v2 *info = (const void *)target->data;
344*a71a9546SAutomerger Merge Worker
345*a71a9546SAutomerger Merge Worker print_target("--add-set", &info->add_set);
346*a71a9546SAutomerger Merge Worker if (info->flags & IPSET_FLAG_EXIST)
347*a71a9546SAutomerger Merge Worker printf(" --exist");
348*a71a9546SAutomerger Merge Worker if (info->timeout != UINT32_MAX)
349*a71a9546SAutomerger Merge Worker printf(" --timeout %u", info->timeout);
350*a71a9546SAutomerger Merge Worker print_target("--del-set", &info->del_set);
351*a71a9546SAutomerger Merge Worker }
352*a71a9546SAutomerger Merge Worker
353*a71a9546SAutomerger Merge Worker
354*a71a9546SAutomerger Merge Worker /* Revision 3 */
355*a71a9546SAutomerger Merge Worker
356*a71a9546SAutomerger Merge Worker static void
set_target_help_v3(void)357*a71a9546SAutomerger Merge Worker set_target_help_v3(void)
358*a71a9546SAutomerger Merge Worker {
359*a71a9546SAutomerger Merge Worker printf("SET target options:\n"
360*a71a9546SAutomerger Merge Worker " --add-set name flags [--exist] [--timeout n]\n"
361*a71a9546SAutomerger Merge Worker " --del-set name flags\n"
362*a71a9546SAutomerger Merge Worker " --map-set name flags"
363*a71a9546SAutomerger Merge Worker " [--map-mark] [--map-prio] [--map-queue]\n"
364*a71a9546SAutomerger Merge Worker " add/del src/dst IP/port from/to named sets,\n"
365*a71a9546SAutomerger Merge Worker " where flags are the comma separated list of\n"
366*a71a9546SAutomerger Merge Worker " 'src' and 'dst' specifications.\n");
367*a71a9546SAutomerger Merge Worker }
368*a71a9546SAutomerger Merge Worker
369*a71a9546SAutomerger Merge Worker static const struct option set_target_opts_v3[] = {
370*a71a9546SAutomerger Merge Worker {.name = "add-set", .has_arg = true, .val = '1'},
371*a71a9546SAutomerger Merge Worker {.name = "del-set", .has_arg = true, .val = '2'},
372*a71a9546SAutomerger Merge Worker {.name = "exist", .has_arg = false, .val = '3'},
373*a71a9546SAutomerger Merge Worker {.name = "timeout", .has_arg = true, .val = '4'},
374*a71a9546SAutomerger Merge Worker {.name = "map-set", .has_arg = true, .val = '5'},
375*a71a9546SAutomerger Merge Worker {.name = "map-mark", .has_arg = false, .val = '6'},
376*a71a9546SAutomerger Merge Worker {.name = "map-prio", .has_arg = false, .val = '7'},
377*a71a9546SAutomerger Merge Worker {.name = "map-queue", .has_arg = false, .val = '8'},
378*a71a9546SAutomerger Merge Worker XT_GETOPT_TABLEEND,
379*a71a9546SAutomerger Merge Worker };
380*a71a9546SAutomerger Merge Worker
381*a71a9546SAutomerger Merge Worker static void
set_target_check_v3(unsigned int flags)382*a71a9546SAutomerger Merge Worker set_target_check_v3(unsigned int flags)
383*a71a9546SAutomerger Merge Worker {
384*a71a9546SAutomerger Merge Worker if (!(flags & (SET_TARGET_ADD|SET_TARGET_DEL|SET_TARGET_MAP)))
385*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
386*a71a9546SAutomerger Merge Worker "You must specify either `--add-set' or "
387*a71a9546SAutomerger Merge Worker "`--del-set' or `--map-set'");
388*a71a9546SAutomerger Merge Worker if (!(flags & SET_TARGET_ADD)) {
389*a71a9546SAutomerger Merge Worker if (flags & SET_TARGET_EXIST)
390*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
391*a71a9546SAutomerger Merge Worker "Flag `--exist' can be used with `--add-set' only");
392*a71a9546SAutomerger Merge Worker if (flags & SET_TARGET_TIMEOUT)
393*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
394*a71a9546SAutomerger Merge Worker "Option `--timeout' can be used with `--add-set' only");
395*a71a9546SAutomerger Merge Worker }
396*a71a9546SAutomerger Merge Worker if (!(flags & SET_TARGET_MAP)) {
397*a71a9546SAutomerger Merge Worker if (flags & SET_TARGET_MAP_MARK)
398*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
399*a71a9546SAutomerger Merge Worker "Flag `--map-mark' can be used with `--map-set' only");
400*a71a9546SAutomerger Merge Worker if (flags & SET_TARGET_MAP_PRIO)
401*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
402*a71a9546SAutomerger Merge Worker "Flag `--map-prio' can be used with `--map-set' only");
403*a71a9546SAutomerger Merge Worker if (flags & SET_TARGET_MAP_QUEUE)
404*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
405*a71a9546SAutomerger Merge Worker "Flag `--map-queue' can be used with `--map-set' only");
406*a71a9546SAutomerger Merge Worker }
407*a71a9546SAutomerger Merge Worker if ((flags & SET_TARGET_MAP) && !(flags & (SET_TARGET_MAP_MARK |
408*a71a9546SAutomerger Merge Worker SET_TARGET_MAP_PRIO |
409*a71a9546SAutomerger Merge Worker SET_TARGET_MAP_QUEUE)))
410*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
411*a71a9546SAutomerger Merge Worker "You must specify flags `--map-mark' or "
412*a71a9546SAutomerger Merge Worker "'--map-prio` or `--map-queue'");
413*a71a9546SAutomerger Merge Worker }
414*a71a9546SAutomerger Merge Worker
415*a71a9546SAutomerger Merge Worker static void
set_target_init_v3(struct xt_entry_target * target)416*a71a9546SAutomerger Merge Worker set_target_init_v3(struct xt_entry_target *target)
417*a71a9546SAutomerger Merge Worker {
418*a71a9546SAutomerger Merge Worker struct xt_set_info_target_v3 *info =
419*a71a9546SAutomerger Merge Worker (struct xt_set_info_target_v3 *) target->data;
420*a71a9546SAutomerger Merge Worker
421*a71a9546SAutomerger Merge Worker info->add_set.index =
422*a71a9546SAutomerger Merge Worker info->del_set.index =
423*a71a9546SAutomerger Merge Worker info->map_set.index = IPSET_INVALID_ID;
424*a71a9546SAutomerger Merge Worker info->timeout = UINT32_MAX;
425*a71a9546SAutomerger Merge Worker }
426*a71a9546SAutomerger Merge Worker
427*a71a9546SAutomerger Merge Worker static int
set_target_parse_v3(int c,char ** argv,int invert,unsigned int * flags,const void * entry,struct xt_entry_target ** target)428*a71a9546SAutomerger Merge Worker set_target_parse_v3(int c, char **argv, int invert, unsigned int *flags,
429*a71a9546SAutomerger Merge Worker const void *entry, struct xt_entry_target **target)
430*a71a9546SAutomerger Merge Worker {
431*a71a9546SAutomerger Merge Worker struct xt_set_info_target_v3 *myinfo =
432*a71a9546SAutomerger Merge Worker (struct xt_set_info_target_v3 *) (*target)->data;
433*a71a9546SAutomerger Merge Worker unsigned int timeout;
434*a71a9546SAutomerger Merge Worker
435*a71a9546SAutomerger Merge Worker switch (c) {
436*a71a9546SAutomerger Merge Worker case '1': /* --add-set <set> <flags> */
437*a71a9546SAutomerger Merge Worker parse_target(argv, invert, &myinfo->add_set, "add-set");
438*a71a9546SAutomerger Merge Worker *flags |= SET_TARGET_ADD;
439*a71a9546SAutomerger Merge Worker break;
440*a71a9546SAutomerger Merge Worker case '2': /* --del-set <set>[:<flags>] <flags> */
441*a71a9546SAutomerger Merge Worker parse_target(argv, invert, &myinfo->del_set, "del-set");
442*a71a9546SAutomerger Merge Worker *flags |= SET_TARGET_DEL;
443*a71a9546SAutomerger Merge Worker break;
444*a71a9546SAutomerger Merge Worker case '3':
445*a71a9546SAutomerger Merge Worker myinfo->flags |= IPSET_FLAG_EXIST;
446*a71a9546SAutomerger Merge Worker *flags |= SET_TARGET_EXIST;
447*a71a9546SAutomerger Merge Worker break;
448*a71a9546SAutomerger Merge Worker case '4':
449*a71a9546SAutomerger Merge Worker if (!xtables_strtoui(optarg, NULL, &timeout, 0, UINT32_MAX - 1))
450*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM,
451*a71a9546SAutomerger Merge Worker "Invalid value for option --timeout "
452*a71a9546SAutomerger Merge Worker "or out of range 0-%u", UINT32_MAX - 1);
453*a71a9546SAutomerger Merge Worker myinfo->timeout = timeout;
454*a71a9546SAutomerger Merge Worker *flags |= SET_TARGET_TIMEOUT;
455*a71a9546SAutomerger Merge Worker break;
456*a71a9546SAutomerger Merge Worker case '5': /* --map-set <set> <flags> */
457*a71a9546SAutomerger Merge Worker parse_target(argv, invert, &myinfo->map_set, "map-set");
458*a71a9546SAutomerger Merge Worker *flags |= SET_TARGET_MAP;
459*a71a9546SAutomerger Merge Worker break;
460*a71a9546SAutomerger Merge Worker case '6':
461*a71a9546SAutomerger Merge Worker myinfo->flags |= IPSET_FLAG_MAP_SKBMARK;
462*a71a9546SAutomerger Merge Worker *flags |= SET_TARGET_MAP_MARK;
463*a71a9546SAutomerger Merge Worker break;
464*a71a9546SAutomerger Merge Worker case '7':
465*a71a9546SAutomerger Merge Worker myinfo->flags |= IPSET_FLAG_MAP_SKBPRIO;
466*a71a9546SAutomerger Merge Worker *flags |= SET_TARGET_MAP_PRIO;
467*a71a9546SAutomerger Merge Worker break;
468*a71a9546SAutomerger Merge Worker case '8':
469*a71a9546SAutomerger Merge Worker myinfo->flags |= IPSET_FLAG_MAP_SKBQUEUE;
470*a71a9546SAutomerger Merge Worker *flags |= SET_TARGET_MAP_QUEUE;
471*a71a9546SAutomerger Merge Worker break;
472*a71a9546SAutomerger Merge Worker }
473*a71a9546SAutomerger Merge Worker return 1;
474*a71a9546SAutomerger Merge Worker }
475*a71a9546SAutomerger Merge Worker
476*a71a9546SAutomerger Merge Worker static void
set_target_print_v3(const void * ip,const struct xt_entry_target * target,int numeric)477*a71a9546SAutomerger Merge Worker set_target_print_v3(const void *ip, const struct xt_entry_target *target,
478*a71a9546SAutomerger Merge Worker int numeric)
479*a71a9546SAutomerger Merge Worker {
480*a71a9546SAutomerger Merge Worker const struct xt_set_info_target_v3 *info = (const void *)target->data;
481*a71a9546SAutomerger Merge Worker
482*a71a9546SAutomerger Merge Worker print_target("add-set", &info->add_set);
483*a71a9546SAutomerger Merge Worker if (info->flags & IPSET_FLAG_EXIST)
484*a71a9546SAutomerger Merge Worker printf(" exist");
485*a71a9546SAutomerger Merge Worker if (info->timeout != UINT32_MAX)
486*a71a9546SAutomerger Merge Worker printf(" timeout %u", info->timeout);
487*a71a9546SAutomerger Merge Worker print_target("del-set", &info->del_set);
488*a71a9546SAutomerger Merge Worker print_target("map-set", &info->map_set);
489*a71a9546SAutomerger Merge Worker if (info->flags & IPSET_FLAG_MAP_SKBMARK)
490*a71a9546SAutomerger Merge Worker printf(" map-mark");
491*a71a9546SAutomerger Merge Worker if (info->flags & IPSET_FLAG_MAP_SKBPRIO)
492*a71a9546SAutomerger Merge Worker printf(" map-prio");
493*a71a9546SAutomerger Merge Worker if (info->flags & IPSET_FLAG_MAP_SKBQUEUE)
494*a71a9546SAutomerger Merge Worker printf(" map-queue");
495*a71a9546SAutomerger Merge Worker }
496*a71a9546SAutomerger Merge Worker
497*a71a9546SAutomerger Merge Worker static void
set_target_save_v3(const void * ip,const struct xt_entry_target * target)498*a71a9546SAutomerger Merge Worker set_target_save_v3(const void *ip, const struct xt_entry_target *target)
499*a71a9546SAutomerger Merge Worker {
500*a71a9546SAutomerger Merge Worker const struct xt_set_info_target_v3 *info = (const void *)target->data;
501*a71a9546SAutomerger Merge Worker
502*a71a9546SAutomerger Merge Worker print_target("--add-set", &info->add_set);
503*a71a9546SAutomerger Merge Worker if (info->flags & IPSET_FLAG_EXIST)
504*a71a9546SAutomerger Merge Worker printf(" --exist");
505*a71a9546SAutomerger Merge Worker if (info->timeout != UINT32_MAX)
506*a71a9546SAutomerger Merge Worker printf(" --timeout %u", info->timeout);
507*a71a9546SAutomerger Merge Worker print_target("--del-set", &info->del_set);
508*a71a9546SAutomerger Merge Worker print_target("--map-set", &info->map_set);
509*a71a9546SAutomerger Merge Worker if (info->flags & IPSET_FLAG_MAP_SKBMARK)
510*a71a9546SAutomerger Merge Worker printf(" --map-mark");
511*a71a9546SAutomerger Merge Worker if (info->flags & IPSET_FLAG_MAP_SKBPRIO)
512*a71a9546SAutomerger Merge Worker printf(" --map-prio");
513*a71a9546SAutomerger Merge Worker if (info->flags & IPSET_FLAG_MAP_SKBQUEUE)
514*a71a9546SAutomerger Merge Worker printf(" --map-queue");
515*a71a9546SAutomerger Merge Worker }
516*a71a9546SAutomerger Merge Worker
517*a71a9546SAutomerger Merge Worker static struct xtables_target set_tg_reg[] = {
518*a71a9546SAutomerger Merge Worker {
519*a71a9546SAutomerger Merge Worker .name = "SET",
520*a71a9546SAutomerger Merge Worker .revision = 0,
521*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
522*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV4,
523*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_set_info_target_v0)),
524*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_target_v0)),
525*a71a9546SAutomerger Merge Worker .help = set_target_help_v0,
526*a71a9546SAutomerger Merge Worker .init = set_target_init_v0,
527*a71a9546SAutomerger Merge Worker .parse = set_target_parse_v0,
528*a71a9546SAutomerger Merge Worker .final_check = set_target_check_v0,
529*a71a9546SAutomerger Merge Worker .print = set_target_print_v0,
530*a71a9546SAutomerger Merge Worker .save = set_target_save_v0,
531*a71a9546SAutomerger Merge Worker .extra_opts = set_target_opts_v0,
532*a71a9546SAutomerger Merge Worker },
533*a71a9546SAutomerger Merge Worker {
534*a71a9546SAutomerger Merge Worker .name = "SET",
535*a71a9546SAutomerger Merge Worker .revision = 1,
536*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
537*a71a9546SAutomerger Merge Worker .family = NFPROTO_UNSPEC,
538*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_set_info_target_v1)),
539*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_target_v1)),
540*a71a9546SAutomerger Merge Worker .help = set_target_help_v0,
541*a71a9546SAutomerger Merge Worker .init = set_target_init_v1,
542*a71a9546SAutomerger Merge Worker .parse = set_target_parse_v1,
543*a71a9546SAutomerger Merge Worker .final_check = set_target_check_v0,
544*a71a9546SAutomerger Merge Worker .print = set_target_print_v1,
545*a71a9546SAutomerger Merge Worker .save = set_target_save_v1,
546*a71a9546SAutomerger Merge Worker .extra_opts = set_target_opts_v0,
547*a71a9546SAutomerger Merge Worker },
548*a71a9546SAutomerger Merge Worker {
549*a71a9546SAutomerger Merge Worker .name = "SET",
550*a71a9546SAutomerger Merge Worker .revision = 2,
551*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
552*a71a9546SAutomerger Merge Worker .family = NFPROTO_UNSPEC,
553*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_set_info_target_v2)),
554*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_target_v2)),
555*a71a9546SAutomerger Merge Worker .help = set_target_help_v2,
556*a71a9546SAutomerger Merge Worker .init = set_target_init_v2,
557*a71a9546SAutomerger Merge Worker .parse = set_target_parse_v2,
558*a71a9546SAutomerger Merge Worker .final_check = set_target_check_v2,
559*a71a9546SAutomerger Merge Worker .print = set_target_print_v2,
560*a71a9546SAutomerger Merge Worker .save = set_target_save_v2,
561*a71a9546SAutomerger Merge Worker .extra_opts = set_target_opts_v2,
562*a71a9546SAutomerger Merge Worker },
563*a71a9546SAutomerger Merge Worker {
564*a71a9546SAutomerger Merge Worker .name = "SET",
565*a71a9546SAutomerger Merge Worker .revision = 3,
566*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
567*a71a9546SAutomerger Merge Worker .family = NFPROTO_UNSPEC,
568*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_set_info_target_v3)),
569*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_target_v3)),
570*a71a9546SAutomerger Merge Worker .help = set_target_help_v3,
571*a71a9546SAutomerger Merge Worker .init = set_target_init_v3,
572*a71a9546SAutomerger Merge Worker .parse = set_target_parse_v3,
573*a71a9546SAutomerger Merge Worker .final_check = set_target_check_v3,
574*a71a9546SAutomerger Merge Worker .print = set_target_print_v3,
575*a71a9546SAutomerger Merge Worker .save = set_target_save_v3,
576*a71a9546SAutomerger Merge Worker .extra_opts = set_target_opts_v3,
577*a71a9546SAutomerger Merge Worker },
578*a71a9546SAutomerger Merge Worker };
579*a71a9546SAutomerger Merge Worker
_init(void)580*a71a9546SAutomerger Merge Worker void _init(void)
581*a71a9546SAutomerger Merge Worker {
582*a71a9546SAutomerger Merge Worker xtables_register_targets(set_tg_reg, ARRAY_SIZE(set_tg_reg));
583*a71a9546SAutomerger Merge Worker }
584