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/ipt_addrtype.h>
13 /* from linux/rtnetlink.h, must match order of enumeration */
14 static const char *const rtn_names[] = {
30 static void addrtype_help_types(void)
34 for (i = 0; rtn_names[i]; i++)
35 printf(" %s\n", rtn_names[i]);
38 static void addrtype_help_v0(void)
41 "Address type match options:\n"
42 " [!] --src-type type[,...] Match source address type\n"
43 " [!] --dst-type type[,...] Match destination address type\n"
46 addrtype_help_types();
49 static void addrtype_help_v1(void)
52 "Address type match options:\n"
53 " [!] --src-type type[,...] Match source address type\n"
54 " [!] --dst-type type[,...] Match destination address type\n"
55 " --limit-iface-in Match only on the packet's incoming device\n"
56 " --limit-iface-out Match only on the packet's incoming device\n"
59 addrtype_help_types();
63 parse_type(const char *name, size_t len, u_int16_t *mask)
67 for (i = 0; rtn_names[i]; i++)
68 if (strncasecmp(name, rtn_names[i], len) == 0) {
69 /* build up bitmask for kernel module */
77 static void parse_types(const char *arg, u_int16_t *mask)
81 while ((comma = strchr(arg, ',')) != NULL) {
82 if (comma == arg || !parse_type(arg, comma-arg, mask))
83 xtables_error(PARAMETER_PROBLEM,
84 "addrtype: bad type `%s'", arg);
88 if (strlen(arg) == 0 || !parse_type(arg, strlen(arg), mask))
89 xtables_error(PARAMETER_PROBLEM, "addrtype: bad type \"%s\"", arg);
92 #define IPT_ADDRTYPE_OPT_SRCTYPE 0x1
93 #define IPT_ADDRTYPE_OPT_DSTTYPE 0x2
94 #define IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN 0x4
95 #define IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT 0x8
98 addrtype_parse_v0(int c, char **argv, int invert, unsigned int *flags,
99 const void *entry, struct xt_entry_match **match)
101 struct ipt_addrtype_info *info =
102 (struct ipt_addrtype_info *) (*match)->data;
106 if (*flags&IPT_ADDRTYPE_OPT_SRCTYPE)
107 xtables_error(PARAMETER_PROBLEM,
108 "addrtype: can't specify src-type twice");
109 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
110 parse_types(optarg, &info->source);
112 info->invert_source = 1;
113 *flags |= IPT_ADDRTYPE_OPT_SRCTYPE;
116 if (*flags&IPT_ADDRTYPE_OPT_DSTTYPE)
117 xtables_error(PARAMETER_PROBLEM,
118 "addrtype: can't specify dst-type twice");
119 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
120 parse_types(optarg, &info->dest);
122 info->invert_dest = 1;
123 *flags |= IPT_ADDRTYPE_OPT_DSTTYPE;
133 addrtype_parse_v1(int c, char **argv, int invert, unsigned int *flags,
134 const void *entry, struct xt_entry_match **match)
136 struct ipt_addrtype_info_v1 *info =
137 (struct ipt_addrtype_info_v1 *) (*match)->data;
141 if (*flags & IPT_ADDRTYPE_OPT_SRCTYPE)
142 xtables_error(PARAMETER_PROBLEM,
143 "addrtype: can't specify src-type twice");
144 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
145 parse_types(optarg, &info->source);
147 info->flags |= IPT_ADDRTYPE_INVERT_SOURCE;
148 *flags |= IPT_ADDRTYPE_OPT_SRCTYPE;
151 if (*flags & IPT_ADDRTYPE_OPT_DSTTYPE)
152 xtables_error(PARAMETER_PROBLEM,
153 "addrtype: can't specify dst-type twice");
154 xtables_check_inverse(optarg, &invert, &optind, 0, argv);
155 parse_types(optarg, &info->dest);
157 info->flags |= IPT_ADDRTYPE_INVERT_DEST;
158 *flags |= IPT_ADDRTYPE_OPT_DSTTYPE;
161 if (*flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN)
162 xtables_error(PARAMETER_PROBLEM,
163 "addrtype: can't specify limit-iface-in twice");
164 info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_IN;
165 *flags |= IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN;
168 if (*flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT)
169 xtables_error(PARAMETER_PROBLEM,
170 "addrtype: can't specify limit-iface-out twice");
171 info->flags |= IPT_ADDRTYPE_LIMIT_IFACE_OUT;
172 *flags |= IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT;
181 static void addrtype_check_v0(unsigned int flags)
183 if (!(flags & (IPT_ADDRTYPE_OPT_SRCTYPE|IPT_ADDRTYPE_OPT_DSTTYPE)))
184 xtables_error(PARAMETER_PROBLEM,
185 "addrtype: you must specify --src-type or --dst-type");
188 static void addrtype_check_v1(unsigned int flags)
190 if (!(flags & (IPT_ADDRTYPE_OPT_SRCTYPE|IPT_ADDRTYPE_OPT_DSTTYPE)))
191 xtables_error(PARAMETER_PROBLEM,
192 "addrtype: you must specify --src-type or --dst-type");
193 if (flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_IN &&
194 flags & IPT_ADDRTYPE_OPT_LIMIT_IFACE_OUT)
195 xtables_error(PARAMETER_PROBLEM,
196 "addrtype: you can't specify both --limit-iface-in "
197 "and --limit-iface-out");
200 static void print_types(u_int16_t mask)
202 const char *sep = "";
205 for (i = 0; rtn_names[i]; i++)
206 if (mask & (1 << i)) {
207 printf("%s%s", sep, rtn_names[i]);
214 static void addrtype_print_v0(const void *ip, const struct xt_entry_match *match,
217 const struct ipt_addrtype_info *info =
218 (struct ipt_addrtype_info *) match->data;
220 printf("ADDRTYPE match ");
223 if (info->invert_source)
225 print_types(info->source);
229 if (info->invert_dest)
231 print_types(info->dest);
235 static void addrtype_print_v1(const void *ip, const struct xt_entry_match *match,
238 const struct ipt_addrtype_info_v1 *info =
239 (struct ipt_addrtype_info_v1 *) match->data;
241 printf("ADDRTYPE match ");
244 if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE)
246 print_types(info->source);
250 if (info->flags & IPT_ADDRTYPE_INVERT_DEST)
252 print_types(info->dest);
254 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) {
257 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) {
258 printf("limit-out ");
262 static void addrtype_save_v0(const void *ip, const struct xt_entry_match *match)
264 const struct ipt_addrtype_info *info =
265 (struct ipt_addrtype_info *) match->data;
268 if (info->invert_source)
270 printf("--src-type ");
271 print_types(info->source);
274 if (info->invert_dest)
276 printf("--dst-type ");
277 print_types(info->dest);
281 static void addrtype_save_v1(const void *ip, const struct xt_entry_match *match)
283 const struct ipt_addrtype_info_v1 *info =
284 (struct ipt_addrtype_info_v1 *) match->data;
287 if (info->flags & IPT_ADDRTYPE_INVERT_SOURCE)
289 printf("--src-type ");
290 print_types(info->source);
293 if (info->flags & IPT_ADDRTYPE_INVERT_DEST)
295 printf("--dst-type ");
296 print_types(info->dest);
298 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_IN) {
299 printf("--limit-iface-in ");
301 if (info->flags & IPT_ADDRTYPE_LIMIT_IFACE_OUT) {
302 printf("--limit-iface-out ");
306 static const struct option addrtype_opts[] = {
307 { "src-type", 1, NULL, '1' },
308 { "dst-type", 1, NULL, '2' },
312 static const struct option addrtype_opts_v0[] = {
313 { "src-type", 1, NULL, '1' },
314 { "dst-type", 1, NULL, '2' },
318 static const struct option addrtype_opts_v1[] = {
319 { "src-type", 1, NULL, '1' },
320 { "dst-type", 1, NULL, '2' },
321 { "limit-iface-in", 0, NULL, '3' },
322 { "limit-iface-out", 0, NULL, '4' },
326 static struct xtables_match addrtype_mt_reg[] = {
329 .version = XTABLES_VERSION,
330 .family = NFPROTO_IPV4,
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,
343 .version = XTABLES_VERSION,
344 .family = NFPROTO_IPV4,
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_matches(addrtype_mt_reg, ARRAY_SIZE(addrtype_mt_reg));