1 /* Shared library add-on to iptables to add addrtype matching support
3 * This program is released under the terms of GNU GPL */
11 #include <linux/netfilter_ipv4/ip_tables.h>
12 #include <linux/netfilter_ipv4/ipt_addrtype.h>
14 /* from linux/rtnetlink.h, must match order of enumeration */
15 static const char *const rtn_names[] = {
31 static void addrtype_help_types(void)
35 for (i = 0; rtn_names[i]; i++)
36 printf(" %s\n", rtn_names[i]);
39 static void addrtype_help_v0(void)
42 "Address type match options:\n"
43 " [!] --src-type type[,...] Match source address type\n"
44 " [!] --dst-type type[,...] Match destination address type\n"
47 addrtype_help_types();
50 static void addrtype_help_v1(void)
53 "Address type match options:\n"
54 " [!] --src-type type[,...] Match source address type\n"
55 " [!] --dst-type type[,...] Match destination address type\n"
56 " --limit-iface-in Match only on the packet's incoming device\n"
57 " --limit-iface-out Match only on the packet's incoming device\n"
60 addrtype_help_types();
64 parse_type(const char *name, size_t len, u_int16_t *mask)
68 for (i = 0; rtn_names[i]; i++)
69 if (strncasecmp(name, rtn_names[i], len) == 0) {
70 /* build up bitmask for kernel module */
78 static void parse_types(const char *arg, u_int16_t *mask)
82 while ((comma = strchr(arg, ',')) != NULL) {
83 if (comma == arg || !parse_type(arg, comma-arg, mask))
84 exit_error(PARAMETER_PROBLEM,
85 "addrtype: bad type `%s'", arg);
89 if (strlen(arg) == 0 || !parse_type(arg, strlen(arg), mask))
90 exit_error(PARAMETER_PROBLEM, "addrtype: bad type `%s'", arg);
93 #define IPT_ADDRTYPE_OPT_SRCTYPE 0x1
94 #define IPT_ADDRTYPE_OPT_DSTTYPE 0x2
95 #define IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN 0x4
96 #define IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT 0x8
99 addrtype_parse_v0(int c, char **argv, int invert, unsigned int *flags,
100 const void *entry, struct xt_entry_match **match)
102 struct ipt_addrtype_info *info =
103 (struct ipt_addrtype_info *) (*match)->data;
107 if (*flags&IPT_ADDRTYPE_OPT_SRCTYPE)
108 exit_error(PARAMETER_PROBLEM,
109 "addrtype: can't specify src-type twice");
110 check_inverse(optarg, &invert, &optind, 0);
111 parse_types(argv[optind-1], &info->source);
113 info->invert_source = 1;
114 *flags |= IPT_ADDRTYPE_OPT_SRCTYPE;
117 if (*flags&IPT_ADDRTYPE_OPT_DSTTYPE)
118 exit_error(PARAMETER_PROBLEM,
119 "addrtype: can't specify dst-type twice");
120 check_inverse(optarg, &invert, &optind, 0);
121 parse_types(argv[optind-1], &info->dest);
123 info->invert_dest = 1;
124 *flags |= IPT_ADDRTYPE_OPT_DSTTYPE;
134 addrtype_parse_v1(int c, char **argv, int invert, unsigned int *flags,
135 const void *entry, struct xt_entry_match **match)
137 struct ipt_addrtype_info_v1 *info =
138 (struct ipt_addrtype_info_v1 *) (*match)->data;
142 if (*flags & IPT_ADDRTYPE_OPT_SRCTYPE)
143 exit_error(PARAMETER_PROBLEM,
144 "addrtype: can't specify src-type twice");
145 check_inverse(optarg, &invert, &optind, 0);
146 parse_types(argv[optind-1], &info->source);
148 info->flags |= IPT_ADDRTYPE_INVERT_SOURCE;
149 *flags |= IPT_ADDRTYPE_OPT_SRCTYPE;
152 if (*flags & IPT_ADDRTYPE_OPT_DSTTYPE)
153 exit_error(PARAMETER_PROBLEM,
154 "addrtype: can't specify dst-type twice");
155 check_inverse(optarg, &invert, &optind, 0);
156 parse_types(argv[optind-1], &info->dest);
158 info->flags |= IPT_ADDRTYPE_INVERT_DEST;
159 *flags |= IPT_ADDRTYPE_OPT_DSTTYPE;
162 if (*flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN)
163 exit_error(PARAMETER_PROBLEM,
164 "addrtype: can't specify limit-iface-in twice");
165 info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_IN;
166 *flags |= IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN;
169 if (*flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT)
170 exit_error(PARAMETER_PROBLEM,
171 "addrtype: can't specify limit-iface-out twice");
172 info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_OUT;
173 *flags |= IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT;
182 static void addrtype_check_v0(unsigned int flags)
184 if (!(flags & (IPT_ADDRTYPE_OPT_SRCTYPE|IPT_ADDRTYPE_OPT_DSTTYPE)))
185 exit_error(PARAMETER_PROBLEM,
186 "addrtype: you must specify --src-type or --dst-type");
189 static void addrtype_check_v1(unsigned int flags)
191 if (!(flags & (IPT_ADDRTYPE_OPT_SRCTYPE|IPT_ADDRTYPE_OPT_DSTTYPE)))
192 exit_error(PARAMETER_PROBLEM,
193 "addrtype: you must specify --src-type or --dst-type");
194 if (flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN &&
195 flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT)
196 exit_error(PARAMETER_PROBLEM,
197 "addrtype: you can't specify both --limit-iface-in "
198 "and --limit-iface-out");
201 static void print_types(u_int16_t mask)
203 const char *sep = "";
206 for (i = 0; rtn_names[i]; i++)
207 if (mask & (1 << i)) {
208 printf("%s%s", sep, rtn_names[i]);
215 static void addrtype_print_v0(const void *ip, const struct xt_entry_match *match,
218 const struct ipt_addrtype_info *info =
219 (struct ipt_addrtype_info *) match->data;
221 printf("ADDRTYPE match ");
224 if (info->invert_source)
226 print_types(info->source);
230 if (info->invert_dest)
232 print_types(info->dest);
236 static void addrtype_print_v1(const void *ip, const struct xt_entry_match *match,
239 const struct ipt_addrtype_info_v1 *info =
240 (struct ipt_addrtype_info_v1 *) match->data;
242 printf("ADDRTYPE match ");
245 if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE)
247 print_types(info->source);
251 if (info->flags & IPT_ADDRTYPE_INVERT_DEST)
253 print_types(info->dest);
255 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) {
258 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) {
259 printf("limit-out ");
263 static void addrtype_save_v0(const void *ip, const struct xt_entry_match *match)
265 const struct ipt_addrtype_info *info =
266 (struct ipt_addrtype_info *) match->data;
269 printf("--src-type ");
270 if (info->invert_source)
272 print_types(info->source);
275 printf("--dst-type ");
276 if (info->invert_dest)
278 print_types(info->dest);
282 static void addrtype_save_v1(const void *ip, const struct xt_entry_match *match)
284 const struct ipt_addrtype_info_v1 *info =
285 (struct ipt_addrtype_info_v1 *) match->data;
288 printf("--src-type ");
289 if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE)
291 print_types(info->source);
294 printf("--dst-type ");
295 if (info->flags & IPT_ADDRTYPE_INVERT_DEST)
297 print_types(info->dest);
299 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) {
300 printf("--limit-iface-in ");
302 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) {
303 printf("--limit-iface-out ");
307 static const struct option addrtype_opts[] = {
308 { "src-type", 1, NULL, '1' },
309 { "dst-type", 1, NULL, '2' },
313 static const struct option addrtype_opts_v0[] = {
314 { "src-type", 1, NULL, '1' },
315 { "dst-type", 1, NULL, '2' },
319 static const struct option addrtype_opts_v1[] = {
320 { "src-type", 1, NULL, '1' },
321 { "dst-type", 1, NULL, '2' },
322 { "limit-iface-in", 0, NULL, '3' },
323 { "limit-iface-out", 0, NULL, '4' },
327 static struct xtables_match addrtype_mt_reg_v0 = {
329 .version = XTABLES_VERSION,
331 .size = XT_ALIGN(sizeof(struct ipt_addrtype_info)),
332 .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info)),
333 .help = addrtype_help_v0,
334 .parse = addrtype_parse_v0,
335 .final_check = addrtype_check_v0,
336 .print = addrtype_print_v0,
337 .save = addrtype_save_v0,
338 .extra_opts = addrtype_opts_v0,
341 static struct xtables_match addrtype_mt_reg_v1 = {
343 .version = XTABLES_VERSION,
345 .size = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)),
346 .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)),
347 .help = addrtype_help_v1,
348 .parse = addrtype_parse_v1,
349 .final_check = addrtype_check_v1,
350 .print = addrtype_print_v1,
351 .save = addrtype_save_v1,
352 .extra_opts = addrtype_opts_v1,
359 xtables_register_match(&addrtype_mt_reg_v0);
360 xtables_register_match(&addrtype_mt_reg_v1);