Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / iptables / extensions / libip6t_iprange.c
blobca9fefe90e05f10bd4b57c6ee4ca6506f170711f
1 /* Shared library add-on to iptables to add IP range matching support. */
2 #include <stdio.h>
3 #include <netdb.h>
4 #include <string.h>
5 #include <stdlib.h>
6 #include <getopt.h>
7 #include <arpa/inet.h>
9 #include <ip6tables.h>
10 #include <linux/netfilter.h>
11 #include <linux/netfilter_ipv6/ip6_tables.h>
12 #include <linux/netfilter/xt_iprange.h>
14 enum {
15 F_SRCIP = 1 << 0,
16 F_DSTIP = 1 << 1,
19 /* Function which prints out usage message. */
20 static void
21 help(void)
23 printf(
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"
27 "\n",
28 IPTABLES_VERSION);
31 static struct option opts[] = {
32 { "src-range", 1, 0, '1' },
33 { "dst-range", 1, 0, '2' },
34 {0}
37 static struct in6_addr *numeric_to_ip6addr(const char *num)
39 static struct in6_addr ap;
40 int err;
42 if ((err = inet_pton(AF_INET6, num, &ap)) == 1)
43 return &ap;
44 return NULL;
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
56 ate an option */
57 static int
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;
65 char *end;
67 switch (c) {
68 case '1': /* --src-range */
69 end = strchr(optarg, '-');
70 if (end == NULL)
71 exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP range `%s'\n", optarg);
72 *end = '\0';
73 ia = numeric_to_ip6addr(optarg);
74 if (ia == NULL)
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);
78 if (ia == NULL)
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;
82 if (invert)
83 info->flags |= IPRANGE_SRC_INV;
84 *flags |= F_SRCIP;
85 return 1;
87 case '2': /* --dst-range */
88 end = strchr(optarg, '-');
89 if (end == NULL)
90 exit_error(PARAMETER_PROBLEM, "iprange match: Bad IP range `%s'\n", optarg);
91 *end = '\0';
92 ia = numeric_to_ip6addr(optarg);
93 if (ia == NULL)
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);
97 if (ia == NULL)
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;
101 if (invert)
102 info->flags |= IPRANGE_DST_INV;
103 *flags |= F_DSTIP;
104 return 1;
106 return 0;
109 /* Final check; must have specified --src-range or --dst-range. */
110 static void
111 final_check(unsigned int flags)
113 if (flags == 0)
114 exit_error(PARAMETER_PROBLEM,
115 "iprange match: You must specify `--src-range' or `--dst-range'");
118 /* Prints out the info. */
119 static void
120 print(const struct ip6t_ip6 *ip,
121 const struct ip6t_entry_match *match,
122 int numeric)
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)
129 printf("! ");
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)
140 printf("! ");
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. */
147 static void
148 save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
150 #ifdef IPTABLES_SAVE
151 const struct xt_iprange_mtinfo *info = (const void *)match->data;
153 if (info->flags & IPRANGE_SRC) {
154 if (info->flags & IPRANGE_SRC_INV)
155 printf("! ");
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)
161 printf("! ");
162 printf("--dst-range %s", ip6addr_to_numeric(&info->dst_min.in6));
163 printf("-%s ", ip6addr_to_numeric(&info->dst_max.in6));
165 #endif
168 static struct ip6tables_match iprange = {
169 .next = NULL,
170 .name = "iprange",
171 .revision = 1,
172 .version = IPTABLES_VERSION,
173 .size = IP6T_ALIGN(sizeof(struct xt_iprange_mtinfo)),
174 .userspacesize = IP6T_ALIGN(sizeof(struct xt_iprange_mtinfo)),
175 .help = &help,
176 .parse = &parse,
177 .final_check = &final_check,
178 .print = &print,
179 .save = &save,
180 .extra_opts = opts
183 void _init(void)
185 register_match6(&iprange);