1 /* Shared library add-on to iptables to add IP range matching support. */
10 #include <linux/netfilter.h>
11 #include <linux/netfilter_ipv6/ip6_tables.h>
12 #include <linux/netfilter/xt_iprange.h>
19 /* Function which prints out usage message. */
24 "iprange match v%s options:\n"
25 "[!] --src-range ip6-ip6 Match source IPv6 in the specified range\n"
26 "[!] --dst-range ip6-ip6 Match destination IPv6 in the specified range\n"
31 static struct option opts
[] = {
32 { "src-range", 1, 0, '1' },
33 { "dst-range", 1, 0, '2' },
37 static struct in6_addr
*numeric_to_ip6addr(const char *num
)
39 static struct in6_addr ap
;
42 if ((err
= inet_pton(AF_INET6
, num
, &ap
)) == 1)
47 static const char *ip6addr_to_numeric(const struct in6_addr
*addrp
)
49 /* 0000:0000:0000:0000:0000:000.000.000.000
50 * 0000:0000:0000:0000:0000:0000:0000:0000 */
51 static char buf
[50+1];
52 return inet_ntop(AF_INET6
, addrp
, buf
, sizeof(buf
));
55 /* Function which parses command options; returns true if it
58 parse(int c
, char **argv
, int invert
, unsigned int *flags
,
59 const struct ip6t_entry
*entry
,
60 unsigned int *nfcache
,
61 struct ip6t_entry_match
**match
)
63 struct xt_iprange_mtinfo
*info
= (void *)(*match
)->data
;
64 const struct in6_addr
*ia
;
68 case '1': /* --src-range */
69 end
= strchr(optarg
, '-');
71 exit_error(PARAMETER_PROBLEM
, "iprange match: Bad IP range `%s'\n", optarg
);
73 ia
= numeric_to_ip6addr(optarg
);
75 exit_error(PARAMETER_PROBLEM
, "iprange match: Bad IP address `%s'\n", optarg
);
76 memcpy(&info
->src_min
.in
, ia
, sizeof(*ia
));
77 ia
= numeric_to_ip6addr(end
+ 1);
79 exit_error(PARAMETER_PROBLEM
, "iprange match: Bad IP address `%s'\n", end
+ 1);
80 memcpy(&info
->src_max
.in
, ia
, sizeof(*ia
));
81 info
->flags
|= IPRANGE_SRC
;
83 info
->flags
|= IPRANGE_SRC_INV
;
87 case '2': /* --dst-range */
88 end
= strchr(optarg
, '-');
90 exit_error(PARAMETER_PROBLEM
, "iprange match: Bad IP range `%s'\n", optarg
);
92 ia
= numeric_to_ip6addr(optarg
);
94 exit_error(PARAMETER_PROBLEM
, "iprange match: Bad IP address `%s'\n", optarg
);
95 memcpy(&info
->dst_min
.in
, ia
, sizeof(*ia
));
96 ia
= numeric_to_ip6addr(end
+ 1);
98 exit_error(PARAMETER_PROBLEM
, "iprange match: Bad IP address `%s'\n", end
+ 1);
99 memcpy(&info
->dst_max
.in
, ia
, sizeof(*ia
));
100 info
->flags
|= IPRANGE_DST
;
102 info
->flags
|= IPRANGE_DST_INV
;
109 /* Final check; must have specified --src-range or --dst-range. */
111 final_check(unsigned int flags
)
114 exit_error(PARAMETER_PROBLEM
,
115 "iprange match: You must specify `--src-range' or `--dst-range'");
118 /* Prints out the info. */
120 print(const struct ip6t_ip6
*ip
,
121 const struct ip6t_entry_match
*match
,
124 const struct xt_iprange_mtinfo
*info
= (const void *)match
->data
;
126 if (info
->flags
& IPRANGE_SRC
) {
127 printf("source IP range ");
128 if (info
->flags
& IPRANGE_SRC_INV
)
131 * ipaddr_to_numeric() uses a static buffer, so cannot
132 * combine the printf() calls.
134 printf("%s", ip6addr_to_numeric(&info
->src_min
.in6
));
135 printf("-%s ", ip6addr_to_numeric(&info
->src_max
.in6
));
137 if (info
->flags
& IPRANGE_DST
) {
138 printf("destination IP range ");
139 if (info
->flags
& IPRANGE_DST_INV
)
141 printf("%s", ip6addr_to_numeric(&info
->dst_min
.in6
));
142 printf("-%s ", ip6addr_to_numeric(&info
->dst_max
.in6
));
146 /* Saves the union ipt_info in parsable form to stdout. */
148 save(const struct ip6t_ip6
*ip
, const struct ip6t_entry_match
*match
)
151 const struct xt_iprange_mtinfo
*info
= (const void *)match
->data
;
153 if (info
->flags
& IPRANGE_SRC
) {
154 if (info
->flags
& IPRANGE_SRC_INV
)
156 printf("--src-range %s", ip6addr_to_numeric(&info
->src_min
.in6
));
157 printf("-%s ", ip6addr_to_numeric(&info
->src_max
.in6
));
159 if (info
->flags
& IPRANGE_DST
) {
160 if (info
->flags
& IPRANGE_DST_INV
)
162 printf("--dst-range %s", ip6addr_to_numeric(&info
->dst_min
.in6
));
163 printf("-%s ", ip6addr_to_numeric(&info
->dst_max
.in6
));
168 static struct ip6tables_match iprange
= {
172 .version
= IPTABLES_VERSION
,
173 .size
= IP6T_ALIGN(sizeof(struct xt_iprange_mtinfo
)),
174 .userspacesize
= IP6T_ALIGN(sizeof(struct xt_iprange_mtinfo
)),
177 .final_check
= &final_check
,
185 register_match6(&iprange
);