• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
27 static void
set_help_v0(void)28 set_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 
37 static 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 
43 static void
set_check_v0(unsigned int flags)44 set_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 
51 static int
set_parse_v0(int c,char ** argv,int invert,unsigned int * flags,const void * entry,struct xt_entry_match ** match)52 set_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 
95 static void
print_match_v0(const char * prefix,const struct xt_set_info_v0 * info)96 print_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. */
116 static void
set_print_v0(const void * ip,const struct xt_entry_match * match,int numeric)117 set_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 
124 static void
set_save_v0(const void * ip,const struct xt_entry_match * match)125 set_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 
138 static int
set_parse_v1(int c,char ** argv,int invert,unsigned int * flags,const void * entry,struct xt_entry_match ** match)139 set_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 
182 static void
print_match(const char * prefix,const struct xt_set_info * info)183 print_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. */
201 static void
set_print_v1(const void * ip,const struct xt_entry_match * match,int numeric)202 set_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 
209 static void
set_save_v1(const void * ip,const struct xt_entry_match * match)210 set_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 
217 static 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 
_init(void)248 void _init(void)
249 {
250 	xtables_register_matches(set_mt_reg, ARRAY_SIZE(set_mt_reg));
251 }
252