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