blob: da722c738ddf8a1cb45b6495bcca2a7f1859149f [file] [log] [blame]
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +02001/* 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. */
Jan Engelhardt32b8e612010-07-23 21:16:14 +020012#include <stdbool.h>
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +020013#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
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +020025/* Revision 0 */
26
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +020027static void
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +020028set_help_v0(void)
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +020029{
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
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +020037static const struct option set_opts_v0[] = {
Jan Engelhardt32b8e612010-07-23 21:16:14 +020038 {.name = "match-set", .has_arg = true, .val = '1'},
39 {.name = "set", .has_arg = true, .val = '2'},
40 XT_GETOPT_TABLEEND,
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +020041};
42
43static void
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +020044set_check_v0(unsigned int flags)
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +020045{
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;
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +020090 }
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);
Jan Engelhardt73866352010-12-18 02:04:59 +0100102 printf("%s %s %s",
103 (info->u.flags[0] & IPSET_MATCH_INV) ? " !" : "",
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200104 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 }
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200113}
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
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +0200132/* 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
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200138static int
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +0200139set_parse_v1(int c, char **argv, int invert, unsigned int *flags,
140 const void *entry, struct xt_entry_match **match)
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200141{
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +0200142 struct xt_set_info_match_v1 *myinfo =
143 (struct xt_set_info_match_v1 *) (*match)->data;
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200144 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;
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200177 }
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);
Jan Engelhardt73866352010-12-18 02:04:59 +0100189 printf("%s %s %s",
190 (info->flags & IPSET_INV_MATCH) ? " !" : "",
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200191 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 }
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200198}
199
200/* Prints out the matchinfo. */
201static void
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +0200202set_print_v1(const void *ip, const struct xt_entry_match *match, int numeric)
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200203{
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +0200204 const struct xt_set_info_match_v1 *info = (const void *)match->data;
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200205
206 print_match("match-set", &info->match_set);
207}
208
209static void
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +0200210set_save_v1(const void *ip, const struct xt_entry_match *match)
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200211{
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +0200212 const struct xt_set_info_match_v1 *info = (const void *)match->data;
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200213
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)),
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +0200225 .help = set_help_v0,
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200226 .parse = set_parse_v0,
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +0200227 .final_check = set_check_v0,
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200228 .print = set_print_v0,
229 .save = set_save_v0,
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +0200230 .extra_opts = set_opts_v0,
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200231 },
232 {
233 .name = "set",
234 .revision = 1,
235 .version = XTABLES_VERSION,
236 .family = NFPROTO_UNSPEC,
Jozsef Kadlecsike39f3672011-04-17 11:38:18 +0200237 .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,
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200245 },
246};
247
248void _init(void)
249{
250 xtables_register_matches(set_mt_reg, ARRAY_SIZE(set_mt_reg));
251}