libxt_set.c revision e39f367d905670e39e6f08d2b73c715a6d0b4bfb
1/* Copyright (C) 2000-2002 Joakim Axelsson <gozem@linux.nu>
2 *                         Patrick Schaaf <bof@bof.de>
3 *                         Martin Josefsson <gandalf@wlug.westbo.se>
4 * Copyright (C) 2003-2010 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11/* Shared library add-on to iptables to add IP set matching. */
12#include <stdbool.h>
13#include <stdio.h>
14#include <netdb.h>
15#include <string.h>
16#include <stdlib.h>
17#include <getopt.h>
18#include <ctype.h>
19#include <errno.h>
20
21#include <xtables.h>
22#include <linux/netfilter/xt_set.h>
23#include "libxt_set.h"
24
25/* Revision 0 */
26
27static void
28set_help_v0(void)
29{
30	printf("set match options:\n"
31	       " [!] --match-set name flags\n"
32	       "		 'name' is the set name from to match,\n"
33	       "		 'flags' are the comma separated list of\n"
34	       "		 'src' and 'dst' specifications.\n");
35}
36
37static const struct option set_opts_v0[] = {
38	{.name = "match-set", .has_arg = true, .val = '1'},
39	{.name = "set",       .has_arg = true, .val = '2'},
40	XT_GETOPT_TABLEEND,
41};
42
43static void
44set_check_v0(unsigned int flags)
45{
46	if (!flags)
47		xtables_error(PARAMETER_PROBLEM,
48			"You must specify `--match-set' with proper arguments");
49}
50
51static int
52set_parse_v0(int c, char **argv, int invert, unsigned int *flags,
53	     const void *entry, struct xt_entry_match **match)
54{
55	struct xt_set_info_match_v0 *myinfo =
56		(struct xt_set_info_match_v0 *) (*match)->data;
57	struct xt_set_info_v0 *info = &myinfo->match_set;
58
59	switch (c) {
60	case '2':
61		fprintf(stderr,
62			"--set option deprecated, please use --match-set\n");
63	case '1':		/* --match-set <set> <flag>[,<flag> */
64		if (info->u.flags[0])
65			xtables_error(PARAMETER_PROBLEM,
66				      "--match-set can be specified only once");
67
68		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
69		if (invert)
70			info->u.flags[0] |= IPSET_MATCH_INV;
71
72		if (!argv[optind]
73		    || argv[optind][0] == '-'
74		    || argv[optind][0] == '!')
75			xtables_error(PARAMETER_PROBLEM,
76				      "--match-set requires two args.");
77
78		if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
79			xtables_error(PARAMETER_PROBLEM,
80				      "setname `%s' too long, max %d characters.",
81				      optarg, IPSET_MAXNAMELEN - 1);
82
83		get_set_byname(optarg, (struct xt_set_info *)info);
84		parse_dirs_v0(argv[optind], info);
85		DEBUGP("parse: set index %u\n", info->index);
86		optind++;
87
88		*flags = 1;
89		break;
90	}
91
92	return 1;
93}
94
95static void
96print_match_v0(const char *prefix, const struct xt_set_info_v0 *info)
97{
98	int i;
99	char setname[IPSET_MAXNAMELEN];
100
101	get_set_byid(setname, info->index);
102	printf("%s %s %s",
103	       (info->u.flags[0] & IPSET_MATCH_INV) ? " !" : "",
104	       prefix,
105	       setname);
106	for (i = 0; i < IPSET_DIM_MAX; i++) {
107		if (!info->u.flags[i])
108			break;
109		printf("%s%s",
110		       i == 0 ? " " : ",",
111		       info->u.flags[i] & IPSET_SRC ? "src" : "dst");
112	}
113}
114
115/* Prints out the matchinfo. */
116static void
117set_print_v0(const void *ip, const struct xt_entry_match *match, int numeric)
118{
119	const struct xt_set_info_match_v0 *info = (const void *)match->data;
120
121	print_match_v0("match-set", &info->match_set);
122}
123
124static void
125set_save_v0(const void *ip, const struct xt_entry_match *match)
126{
127	const struct xt_set_info_match_v0 *info = (const void *)match->data;
128
129	print_match_v0("--match-set", &info->match_set);
130}
131
132/* Revision 1 */
133
134#define set_help_v1	set_help_v0
135#define set_opts_v1	set_opts_v0
136#define set_check_v1	set_check_v0
137
138static int
139set_parse_v1(int c, char **argv, int invert, unsigned int *flags,
140	     const void *entry, struct xt_entry_match **match)
141{
142	struct xt_set_info_match_v1 *myinfo =
143		(struct xt_set_info_match_v1 *) (*match)->data;
144	struct xt_set_info *info = &myinfo->match_set;
145
146	switch (c) {
147	case '2':
148		fprintf(stderr,
149			"--set option deprecated, please use --match-set\n");
150	case '1':		/* --match-set <set> <flag>[,<flag> */
151		if (info->dim)
152			xtables_error(PARAMETER_PROBLEM,
153				      "--match-set can be specified only once");
154
155		xtables_check_inverse(optarg, &invert, &optind, 0, argv);
156		if (invert)
157			info->flags |= IPSET_INV_MATCH;
158
159		if (!argv[optind]
160		    || argv[optind][0] == '-'
161		    || argv[optind][0] == '!')
162			xtables_error(PARAMETER_PROBLEM,
163				      "--match-set requires two args.");
164
165		if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
166			xtables_error(PARAMETER_PROBLEM,
167				      "setname `%s' too long, max %d characters.",
168				      optarg, IPSET_MAXNAMELEN - 1);
169
170		get_set_byname(optarg, info);
171		parse_dirs(argv[optind], info);
172		DEBUGP("parse: set index %u\n", info->index);
173		optind++;
174
175		*flags = 1;
176		break;
177	}
178
179	return 1;
180}
181
182static void
183print_match(const char *prefix, const struct xt_set_info *info)
184{
185	int i;
186	char setname[IPSET_MAXNAMELEN];
187
188	get_set_byid(setname, info->index);
189	printf("%s %s %s",
190	       (info->flags & IPSET_INV_MATCH) ? " !" : "",
191	       prefix,
192	       setname);
193	for (i = 1; i <= info->dim; i++) {
194		printf("%s%s",
195		       i == 1 ? " " : ",",
196		       info->flags & (1 << i) ? "src" : "dst");
197	}
198}
199
200/* Prints out the matchinfo. */
201static void
202set_print_v1(const void *ip, const struct xt_entry_match *match, int numeric)
203{
204	const struct xt_set_info_match_v1 *info = (const void *)match->data;
205
206	print_match("match-set", &info->match_set);
207}
208
209static void
210set_save_v1(const void *ip, const struct xt_entry_match *match)
211{
212	const struct xt_set_info_match_v1 *info = (const void *)match->data;
213
214	print_match("--match-set", &info->match_set);
215}
216
217static struct xtables_match set_mt_reg[] = {
218	{
219		.name		= "set",
220		.revision	= 0,
221		.version	= XTABLES_VERSION,
222		.family		= NFPROTO_IPV4,
223		.size		= XT_ALIGN(sizeof(struct xt_set_info_match_v0)),
224		.userspacesize	= XT_ALIGN(sizeof(struct xt_set_info_match_v0)),
225		.help		= set_help_v0,
226		.parse		= set_parse_v0,
227		.final_check	= set_check_v0,
228		.print		= set_print_v0,
229		.save		= set_save_v0,
230		.extra_opts	= set_opts_v0,
231	},
232	{
233		.name		= "set",
234		.revision	= 1,
235		.version	= XTABLES_VERSION,
236		.family		= NFPROTO_UNSPEC,
237		.size		= XT_ALIGN(sizeof(struct xt_set_info_match_v1)),
238		.userspacesize	= XT_ALIGN(sizeof(struct xt_set_info_match_v1)),
239		.help		= set_help_v1,
240		.parse		= set_parse_v1,
241		.final_check	= set_check_v1,
242		.print		= set_print_v1,
243		.save		= set_save_v1,
244		.extra_opts	= set_opts_v1,
245	},
246};
247
248void _init(void)
249{
250	xtables_register_matches(set_mt_reg, ARRAY_SIZE(set_mt_reg));
251}
252