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);
110 parse_types(argv
[optind
-1], &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);
120 parse_types(argv
[optind
-1], &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);
145 parse_types(argv
[optind
-1], &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);
155 parse_types(argv
[optind
-1], &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_v0
= {
328 .version
= XTABLES_VERSION
,
329 .family
= NFPROTO_IPV4
,
330 .size
= XT_ALIGN(sizeof(struct ipt_addrtype_info
)),
331 .userspacesize
= XT_ALIGN(sizeof(struct ipt_addrtype_info
)),
332 .help
= addrtype_help_v0
,
333 .parse
= addrtype_parse_v0
,
334 .final_check
= addrtype_check_v0
,
335 .print
= addrtype_print_v0
,
336 .save
= addrtype_save_v0
,
337 .extra_opts
= addrtype_opts_v0
,
340 static struct xtables_match addrtype_mt_reg_v1
= {
342 .version
= XTABLES_VERSION
,
343 .family
= NFPROTO_IPV4
,
344 .size
= XT_ALIGN(sizeof(struct ipt_addrtype_info_v1
)),
345 .userspacesize
= XT_ALIGN(sizeof(struct ipt_addrtype_info_v1
)),
346 .help
= addrtype_help_v1
,
347 .parse
= addrtype_parse_v1
,
348 .final_check
= addrtype_check_v1
,
349 .print
= addrtype_print_v1
,
350 .save
= addrtype_save_v1
,
351 .extra_opts
= addrtype_opts_v1
,
358 xtables_register_match(&addrtype_mt_reg_v0
);
359 xtables_register_match(&addrtype_mt_reg_v1
);