blob: 3dec626b0d4c20627a2db592a6c4d06b1c50572f [file] [log] [blame]
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +00001/* Shared library add-on to iptables to add addrtype matching support
2 *
3 * This program is released under the terms of GNU GPL */
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +00004#include <stdio.h>
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +00005#include <string.h>
Jan Engelhardt5d9678a2008-11-20 10:15:35 +01006#include <xtables.h>
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +00007#include <linux/netfilter_ipv4/ipt_addrtype.h>
8
Jan Engelhardt94c5d622011-03-01 20:02:35 +01009enum {
10 O_SRC_TYPE = 0,
11 O_DST_TYPE,
12 O_LIMIT_IFACE_IN,
13 O_LIMIT_IFACE_OUT,
14 F_SRC_TYPE = 1 << O_SRC_TYPE,
15 F_DST_TYPE = 1 << O_DST_TYPE,
16 F_LIMIT_IFACE_IN = 1 << O_LIMIT_IFACE_IN,
17 F_LIMIT_IFACE_OUT = 1 << O_LIMIT_IFACE_OUT,
18};
19
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +000020/* from linux/rtnetlink.h, must match order of enumeration */
Jan Engelhardt661f1122007-07-30 14:46:51 +000021static const char *const rtn_names[] = {
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +000022 "UNSPEC",
23 "UNICAST",
24 "LOCAL",
25 "BROADCAST",
26 "ANYCAST",
27 "MULTICAST",
28 "BLACKHOLE",
29 "UNREACHABLE",
30 "PROHIBIT",
31 "THROW",
32 "NAT",
33 "XRESOLVE",
34 NULL
35};
36
László Attila Tóth14d5ebe2007-10-04 05:01:35 +000037static void addrtype_help_types(void)
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +000038{
39 int i;
40
41 for (i = 0; rtn_names[i]; i++)
42 printf(" %s\n", rtn_names[i]);
43}
44
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +020045static void addrtype_help_v0(void)
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +000046{
47 printf(
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020048"Address type match options:\n"
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +000049" [!] --src-type type[,...] Match source address type\n"
50" [!] --dst-type type[,...] Match destination address type\n"
51"\n"
Jan Engelhardt8b7c64d2008-04-15 11:48:25 +020052"Valid types: \n");
László Attila Tóth14d5ebe2007-10-04 05:01:35 +000053 addrtype_help_types();
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +000054}
55
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +020056static void addrtype_help_v1(void)
57{
58 printf(
59"Address type match options:\n"
60" [!] --src-type type[,...] Match source address type\n"
61" [!] --dst-type type[,...] Match destination address type\n"
62" --limit-iface-in Match only on the packet's incoming device\n"
63" --limit-iface-out Match only on the packet's incoming device\n"
64"\n"
65"Valid types: \n");
66 addrtype_help_types();
67}
68
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +000069static int
Jan Engelhardt7ac40522011-01-07 12:34:04 +010070parse_type(const char *name, size_t len, uint16_t *mask)
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +000071{
72 int i;
73
74 for (i = 0; rtn_names[i]; i++)
Jan Engelhardtdbb77542008-02-11 00:33:30 +010075 if (strncasecmp(name, rtn_names[i], len) == 0) {
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +000076 /* build up bitmask for kernel module */
77 *mask |= (1 << i);
78 return 1;
79 }
80
81 return 0;
82}
83
Jan Engelhardt7ac40522011-01-07 12:34:04 +010084static void parse_types(const char *arg, uint16_t *mask)
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +000085{
86 const char *comma;
87
88 while ((comma = strchr(arg, ',')) != NULL) {
Jan Engelhardt59d16402007-10-04 16:28:39 +000089 if (comma == arg || !parse_type(arg, comma-arg, mask))
Jan Engelhardt1829ed42009-02-21 03:29:44 +010090 xtables_error(PARAMETER_PROBLEM,
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +000091 "addrtype: bad type `%s'", arg);
92 arg = comma + 1;
93 }
94
Jan Engelhardt59d16402007-10-04 16:28:39 +000095 if (strlen(arg) == 0 || !parse_type(arg, strlen(arg), mask))
Jan Engelhardt1829ed42009-02-21 03:29:44 +010096 xtables_error(PARAMETER_PROBLEM, "addrtype: bad type \"%s\"", arg);
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +000097}
98
Jan Engelhardt94c5d622011-03-01 20:02:35 +010099static void addrtype_parse_v0(struct xt_option_call *cb)
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000100{
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100101 struct ipt_addrtype_info *info = cb->data;
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000102
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100103 xtables_option_parse(cb);
104 switch (cb->entry->id) {
105 case O_SRC_TYPE:
106 parse_types(cb->arg, &info->source);
107 if (cb->invert)
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000108 info->invert_source = 1;
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000109 break;
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100110 case O_DST_TYPE:
111 parse_types(cb->arg, &info->dest);
112 if (cb->invert)
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000113 info->invert_dest = 1;
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000114 break;
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000115 }
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000116}
117
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100118static void addrtype_parse_v1(struct xt_option_call *cb)
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200119{
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100120 struct ipt_addrtype_info_v1 *info = cb->data;
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200121
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100122 xtables_option_parse(cb);
123 switch (cb->entry->id) {
124 case O_SRC_TYPE:
125 parse_types(cb->arg, &info->source);
126 if (cb->invert)
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200127 info->flags |= IPT_ADDRTYPE_INVERT_SOURCE;
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200128 break;
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100129 case O_DST_TYPE:
130 parse_types(cb->arg, &info->dest);
131 if (cb->invert)
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200132 info->flags |= IPT_ADDRTYPE_INVERT_DEST;
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200133 break;
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100134 case O_LIMIT_IFACE_IN:
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200135 info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_IN;
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200136 break;
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100137 case O_LIMIT_IFACE_OUT:
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200138 info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_OUT;
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200139 break;
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200140 }
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200141}
142
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100143static void addrtype_check(struct xt_fcheck_call *cb)
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000144{
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100145 if (!(cb->xflags & (F_SRC_TYPE | F_DST_TYPE)))
Jan Engelhardt1829ed42009-02-21 03:29:44 +0100146 xtables_error(PARAMETER_PROBLEM,
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000147 "addrtype: you must specify --src-type or --dst-type");
148}
149
Jan Engelhardt7ac40522011-01-07 12:34:04 +0100150static void print_types(uint16_t mask)
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000151{
152 const char *sep = "";
153 int i;
154
155 for (i = 0; rtn_names[i]; i++)
156 if (mask & (1 << i)) {
157 printf("%s%s", sep, rtn_names[i]);
158 sep = ",";
159 }
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000160}
161
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200162static void addrtype_print_v0(const void *ip, const struct xt_entry_match *match,
163 int numeric)
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000164{
165 const struct ipt_addrtype_info *info =
166 (struct ipt_addrtype_info *) match->data;
167
Jan Engelhardt73866352010-12-18 02:04:59 +0100168 printf(" ADDRTYPE match");
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000169 if (info->source) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100170 printf(" src-type ");
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000171 if (info->invert_source)
172 printf("!");
Jan Engelhardt59d16402007-10-04 16:28:39 +0000173 print_types(info->source);
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000174 }
175 if (info->dest) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100176 printf(" dst-type");
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000177 if (info->invert_dest)
178 printf("!");
Jan Engelhardt59d16402007-10-04 16:28:39 +0000179 print_types(info->dest);
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000180 }
181}
182
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200183static void addrtype_print_v1(const void *ip, const struct xt_entry_match *match,
184 int numeric)
185{
186 const struct ipt_addrtype_info_v1 *info =
187 (struct ipt_addrtype_info_v1 *) match->data;
188
Jan Engelhardt73866352010-12-18 02:04:59 +0100189 printf(" ADDRTYPE match");
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200190 if (info->source) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100191 printf(" src-type ");
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200192 if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE)
193 printf("!");
194 print_types(info->source);
195 }
196 if (info->dest) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100197 printf(" dst-type ");
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200198 if (info->flags & IPT_ADDRTYPE_INVERT_DEST)
199 printf("!");
200 print_types(info->dest);
201 }
202 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100203 printf(" limit-in");
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200204 }
205 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100206 printf(" limit-out");
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200207 }
208}
209
210static void addrtype_save_v0(const void *ip, const struct xt_entry_match *match)
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000211{
212 const struct ipt_addrtype_info *info =
213 (struct ipt_addrtype_info *) match->data;
214
215 if (info->source) {
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000216 if (info->invert_source)
Jan Engelhardt73866352010-12-18 02:04:59 +0100217 printf(" !");
218 printf(" --src-type ");
Jan Engelhardt59d16402007-10-04 16:28:39 +0000219 print_types(info->source);
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000220 }
221 if (info->dest) {
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000222 if (info->invert_dest)
Jan Engelhardt73866352010-12-18 02:04:59 +0100223 printf(" !");
224 printf(" --dst-type ");
Jan Engelhardt59d16402007-10-04 16:28:39 +0000225 print_types(info->dest);
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000226 }
227}
228
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200229static void addrtype_save_v1(const void *ip, const struct xt_entry_match *match)
230{
231 const struct ipt_addrtype_info_v1 *info =
232 (struct ipt_addrtype_info_v1 *) match->data;
233
234 if (info->source) {
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200235 if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE)
Jan Engelhardt73866352010-12-18 02:04:59 +0100236 printf(" !");
237 printf(" --src-type ");
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200238 print_types(info->source);
239 }
240 if (info->dest) {
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200241 if (info->flags & IPT_ADDRTYPE_INVERT_DEST)
Jan Engelhardt73866352010-12-18 02:04:59 +0100242 printf(" !");
243 printf(" --dst-type ");
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200244 print_types(info->dest);
245 }
246 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100247 printf(" --limit-iface-in");
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200248 }
249 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) {
Jan Engelhardt73866352010-12-18 02:04:59 +0100250 printf(" --limit-iface-out");
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200251 }
252}
253
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100254static const struct xt_option_entry addrtype_opts_v0[] = {
255 {.name = "src-type", .id = O_SRC_TYPE, .type = XTTYPE_STRING,
256 .flags = XTOPT_INVERT},
257 {.name = "dst-type", .id = O_DST_TYPE, .type = XTTYPE_STRING,
258 .flags = XTOPT_INVERT},
259 XTOPT_TABLEEND,
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000260};
261
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100262static const struct xt_option_entry addrtype_opts_v1[] = {
263 {.name = "src-type", .id = O_SRC_TYPE, .type = XTTYPE_STRING,
264 .flags = XTOPT_INVERT},
265 {.name = "dst-type", .id = O_DST_TYPE, .type = XTTYPE_STRING,
266 .flags = XTOPT_INVERT},
267 {.name = "limit-iface-in", .id = O_LIMIT_IFACE_IN,
268 .type = XTTYPE_NONE, .excl = F_LIMIT_IFACE_OUT},
269 {.name = "limit-iface-out", .id = O_LIMIT_IFACE_OUT,
270 .type = XTTYPE_NONE, .excl = F_LIMIT_IFACE_IN},
271 XTOPT_TABLEEND,
Laszlo Attila Toth4dfd25a2008-06-06 14:17:53 +0200272};
273
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200274static struct xtables_match addrtype_mt_reg[] = {
275 {
276 .name = "addrtype",
277 .version = XTABLES_VERSION,
278 .family = NFPROTO_IPV4,
279 .size = XT_ALIGN(sizeof(struct ipt_addrtype_info)),
280 .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info)),
281 .help = addrtype_help_v0,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200282 .print = addrtype_print_v0,
283 .save = addrtype_save_v0,
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100284 .x6_parse = addrtype_parse_v0,
285 .x6_fcheck = addrtype_check,
286 .x6_options = addrtype_opts_v0,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200287 },
288 {
289 .name = "addrtype",
290 .revision = 1,
291 .version = XTABLES_VERSION,
292 .family = NFPROTO_IPV4,
293 .size = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)),
294 .userspacesize = XT_ALIGN(sizeof(struct ipt_addrtype_info_v1)),
295 .help = addrtype_help_v1,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200296 .print = addrtype_print_v1,
297 .save = addrtype_save_v1,
Jan Engelhardt94c5d622011-03-01 20:02:35 +0100298 .x6_parse = addrtype_parse_v1,
299 .x6_fcheck = addrtype_check,
300 .x6_options = addrtype_opts_v1,
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200301 },
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000302};
303
304
305void _init(void)
306{
Jan Engelhardtf2a77522009-06-25 20:12:12 +0200307 xtables_register_matches(addrtype_mt_reg, ARRAY_SIZE(addrtype_mt_reg));
Patrick McHardy6e0e0ed2003-05-07 16:51:40 +0000308}