blob: 78bf7c10a0181cd856a96955ff72249fc004e769 [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
25static void
26set_help(void)
27{
28 printf("set match options:\n"
29 " [!] --match-set name flags\n"
30 " 'name' is the set name from to match,\n"
31 " 'flags' are the comma separated list of\n"
32 " 'src' and 'dst' specifications.\n");
33}
34
35static const struct option set_opts[] = {
Jan Engelhardt32b8e612010-07-23 21:16:14 +020036 {.name = "match-set", .has_arg = true, .val = '1'},
37 {.name = "set", .has_arg = true, .val = '2'},
38 XT_GETOPT_TABLEEND,
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +020039};
40
41static void
42set_check(unsigned int flags)
43{
44 if (!flags)
45 xtables_error(PARAMETER_PROBLEM,
46 "You must specify `--match-set' with proper arguments");
47}
48
49static int
50set_parse_v0(int c, char **argv, int invert, unsigned int *flags,
51 const void *entry, struct xt_entry_match **match)
52{
53 struct xt_set_info_match_v0 *myinfo =
54 (struct xt_set_info_match_v0 *) (*match)->data;
55 struct xt_set_info_v0 *info = &myinfo->match_set;
56
57 switch (c) {
58 case '2':
59 fprintf(stderr,
60 "--set option deprecated, please use --match-set\n");
61 case '1': /* --match-set <set> <flag>[,<flag> */
62 if (info->u.flags[0])
63 xtables_error(PARAMETER_PROBLEM,
64 "--match-set can be specified only once");
65
66 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
67 if (invert)
68 info->u.flags[0] |= IPSET_MATCH_INV;
69
70 if (!argv[optind]
71 || argv[optind][0] == '-'
72 || argv[optind][0] == '!')
73 xtables_error(PARAMETER_PROBLEM,
74 "--match-set requires two args.");
75
76 if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
77 xtables_error(PARAMETER_PROBLEM,
78 "setname `%s' too long, max %d characters.",
79 optarg, IPSET_MAXNAMELEN - 1);
80
81 get_set_byname(optarg, (struct xt_set_info *)info);
82 parse_dirs_v0(argv[optind], info);
83 DEBUGP("parse: set index %u\n", info->index);
84 optind++;
85
86 *flags = 1;
87 break;
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +020088 }
89
90 return 1;
91}
92
93static void
94print_match_v0(const char *prefix, const struct xt_set_info_v0 *info)
95{
96 int i;
97 char setname[IPSET_MAXNAMELEN];
98
99 get_set_byid(setname, info->index);
Jan Engelhardt73866352010-12-18 02:04:59 +0100100 printf("%s %s %s",
101 (info->u.flags[0] & IPSET_MATCH_INV) ? " !" : "",
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200102 prefix,
103 setname);
104 for (i = 0; i < IPSET_DIM_MAX; i++) {
105 if (!info->u.flags[i])
106 break;
107 printf("%s%s",
108 i == 0 ? " " : ",",
109 info->u.flags[i] & IPSET_SRC ? "src" : "dst");
110 }
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200111}
112
113/* Prints out the matchinfo. */
114static void
115set_print_v0(const void *ip, const struct xt_entry_match *match, int numeric)
116{
117 const struct xt_set_info_match_v0 *info = (const void *)match->data;
118
119 print_match_v0("match-set", &info->match_set);
120}
121
122static void
123set_save_v0(const void *ip, const struct xt_entry_match *match)
124{
125 const struct xt_set_info_match_v0 *info = (const void *)match->data;
126
127 print_match_v0("--match-set", &info->match_set);
128}
129
130static int
131set_parse(int c, char **argv, int invert, unsigned int *flags,
132 const void *entry, struct xt_entry_match **match)
133{
134 struct xt_set_info_match *myinfo =
135 (struct xt_set_info_match *) (*match)->data;
136 struct xt_set_info *info = &myinfo->match_set;
137
138 switch (c) {
139 case '2':
140 fprintf(stderr,
141 "--set option deprecated, please use --match-set\n");
142 case '1': /* --match-set <set> <flag>[,<flag> */
143 if (info->dim)
144 xtables_error(PARAMETER_PROBLEM,
145 "--match-set can be specified only once");
146
147 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
148 if (invert)
149 info->flags |= IPSET_INV_MATCH;
150
151 if (!argv[optind]
152 || argv[optind][0] == '-'
153 || argv[optind][0] == '!')
154 xtables_error(PARAMETER_PROBLEM,
155 "--match-set requires two args.");
156
157 if (strlen(optarg) > IPSET_MAXNAMELEN - 1)
158 xtables_error(PARAMETER_PROBLEM,
159 "setname `%s' too long, max %d characters.",
160 optarg, IPSET_MAXNAMELEN - 1);
161
162 get_set_byname(optarg, info);
163 parse_dirs(argv[optind], info);
164 DEBUGP("parse: set index %u\n", info->index);
165 optind++;
166
167 *flags = 1;
168 break;
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200169 }
170
171 return 1;
172}
173
174static void
175print_match(const char *prefix, const struct xt_set_info *info)
176{
177 int i;
178 char setname[IPSET_MAXNAMELEN];
179
180 get_set_byid(setname, info->index);
Jan Engelhardt73866352010-12-18 02:04:59 +0100181 printf("%s %s %s",
182 (info->flags & IPSET_INV_MATCH) ? " !" : "",
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200183 prefix,
184 setname);
185 for (i = 1; i <= info->dim; i++) {
186 printf("%s%s",
187 i == 1 ? " " : ",",
188 info->flags & (1 << i) ? "src" : "dst");
189 }
Jozsef Kadlecsikd40f1622010-06-16 12:45:33 +0200190}
191
192/* Prints out the matchinfo. */
193static void
194set_print(const void *ip, const struct xt_entry_match *match, int numeric)
195{
196 const struct xt_set_info_match *info = (const void *)match->data;
197
198 print_match("match-set", &info->match_set);
199}
200
201static void
202set_save(const void *ip, const struct xt_entry_match *match)
203{
204 const struct xt_set_info_match *info = (const void *)match->data;
205
206 print_match("--match-set", &info->match_set);
207}
208
209static struct xtables_match set_mt_reg[] = {
210 {
211 .name = "set",
212 .revision = 0,
213 .version = XTABLES_VERSION,
214 .family = NFPROTO_IPV4,
215 .size = XT_ALIGN(sizeof(struct xt_set_info_match_v0)),
216 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match_v0)),
217 .help = set_help,
218 .parse = set_parse_v0,
219 .final_check = set_check,
220 .print = set_print_v0,
221 .save = set_save_v0,
222 .extra_opts = set_opts,
223 },
224 {
225 .name = "set",
226 .revision = 1,
227 .version = XTABLES_VERSION,
228 .family = NFPROTO_UNSPEC,
229 .size = XT_ALIGN(sizeof(struct xt_set_info_match)),
230 .userspacesize = XT_ALIGN(sizeof(struct xt_set_info_match)),
231 .help = set_help,
232 .parse = set_parse,
233 .final_check = set_check,
234 .print = set_print,
235 .save = set_save,
236 .extra_opts = set_opts,
237 },
238};
239
240void _init(void)
241{
242 xtables_register_matches(set_mt_reg, ARRAY_SIZE(set_mt_reg));
243}