New routers supported
[tomato.git] / release / src / router / ipset / ipset_ipmap.c
blob87b8e698198dd2be86cb96ea2b7732ba3ea3471a
1 /* Copyright 2000-2004 Joakim Axelsson (gozem@linux.nu)
2 * Patrick Schaaf (bof@bof.de)
3 * Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <stdio.h> /* *printf */
21 #include <string.h> /* mem* */
23 #include "ipset.h"
25 #include <linux/netfilter_ipv4/ip_set_ipmap.h>
27 #define BUFLEN 30;
29 #define OPT_CREATE_FROM 0x01U
30 #define OPT_CREATE_TO 0x02U
31 #define OPT_CREATE_NETWORK 0x04U
32 #define OPT_CREATE_NETMASK 0x08U
34 #define OPT_ADDDEL_IP 0x01U
36 /* Initialize the create. */
37 static void
38 ipmap_create_init(void *data)
40 struct ip_set_req_ipmap_create *mydata = data;
42 DP("create INIT");
43 mydata->netmask = 0xFFFFFFFF;
46 /* Function which parses command options; returns true if it ate an option */
47 static int
48 ipmap_create_parse(int c, char *argv[] UNUSED, void *data, unsigned *flags)
50 struct ip_set_req_ipmap_create *mydata = data;
51 unsigned int bits;
53 DP("create_parse");
55 switch (c) {
56 case '1':
57 parse_ip(optarg, &mydata->from);
59 *flags |= OPT_CREATE_FROM;
61 DP("--from %x (%s)", mydata->from,
62 ip_tostring_numeric(mydata->from));
64 break;
66 case '2':
67 parse_ip(optarg, &mydata->to);
69 *flags |= OPT_CREATE_TO;
71 DP("--to %x (%s)", mydata->to,
72 ip_tostring_numeric(mydata->to));
74 break;
76 case '3':
77 parse_ipandmask(optarg, &mydata->from, &mydata->to);
79 /* Make to the last of from + mask */
80 if (mydata->to)
81 mydata->to = mydata->from | ~(mydata->to);
82 else {
83 mydata->from = 0x00000000;
84 mydata->to = 0xFFFFFFFF;
86 *flags |= OPT_CREATE_NETWORK;
88 DP("--network from %x (%s)",
89 mydata->from, ip_tostring_numeric(mydata->from));
90 DP("--network to %x (%s)",
91 mydata->to, ip_tostring_numeric(mydata->to));
93 break;
95 case '4':
96 if (string_to_number(optarg, 0, 32, &bits))
97 exit_error(PARAMETER_PROBLEM,
98 "Invalid netmask `%s' specified", optarg);
100 if (bits != 0)
101 mydata->netmask = 0xFFFFFFFF << (32 - bits);
103 *flags |= OPT_CREATE_NETMASK;
105 DP("--netmask %x", mydata->netmask);
107 break;
109 default:
110 return 0;
113 return 1;
116 /* Final check; exit if not ok. */
117 static void
118 ipmap_create_final(void *data, unsigned int flags)
120 struct ip_set_req_ipmap_create *mydata = data;
121 ip_set_ip_t range;
123 if (flags == 0)
124 exit_error(PARAMETER_PROBLEM,
125 "Need to specify --from and --to, or --network\n");
127 if (flags & OPT_CREATE_NETWORK) {
128 /* --network */
129 if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
130 exit_error(PARAMETER_PROBLEM,
131 "Can't specify --from or --to with --network\n");
132 } else {
133 /* --from --to */
134 if ((flags & OPT_CREATE_FROM) == 0
135 || (flags & OPT_CREATE_TO) == 0)
136 exit_error(PARAMETER_PROBLEM,
137 "Need to specify both --from and --to\n");
140 DP("from : %x to: %x diff: %x",
141 mydata->from, mydata->to,
142 mydata->to - mydata->from);
144 if (mydata->from > mydata->to)
145 exit_error(PARAMETER_PROBLEM,
146 "From can't be lower than to.\n");
148 if (flags & OPT_CREATE_NETMASK) {
149 unsigned int mask_bits, netmask_bits;
150 ip_set_ip_t mask;
152 if ((mydata->from & mydata->netmask) != mydata->from)
153 exit_error(PARAMETER_PROBLEM,
154 "%s is not a network address according to netmask %d\n",
155 ip_tostring_numeric(mydata->from),
156 mask_to_bits(mydata->netmask));
158 mask = range_to_mask(mydata->from, mydata->to, &mask_bits);
159 if (!mask
160 && (mydata->from || mydata->to != 0xFFFFFFFF)) {
161 exit_error(PARAMETER_PROBLEM,
162 "You have to define a full network with --from"
163 " and --to if you specify the --network option\n");
165 netmask_bits = mask_to_bits(mydata->netmask);
166 if (netmask_bits <= mask_bits) {
167 exit_error(PARAMETER_PROBLEM,
168 "%d netmask specifies larger or equal netblock than the network itself\n");
170 range = (1<<(netmask_bits - mask_bits)) - 1;
171 } else {
172 range = mydata->to - mydata->from;
174 if (range > MAX_RANGE)
175 exit_error(PARAMETER_PROBLEM,
176 "Range too large. Max is %d IPs in range\n",
177 MAX_RANGE+1);
180 /* Create commandline options */
181 static const struct option create_opts[] = {
182 {.name = "from", .has_arg = required_argument, .val = '1'},
183 {.name = "to", .has_arg = required_argument, .val = '2'},
184 {.name = "network", .has_arg = required_argument, .val = '3'},
185 {.name = "netmask", .has_arg = required_argument, .val = '4'},
186 {NULL},
189 /* Add, del, test parser */
190 static ip_set_ip_t
191 ipmap_adt_parser(int cmd UNUSED, const char *arg, void *data)
193 struct ip_set_req_ipmap *mydata = data;
195 DP("ipmap: %p %p", arg, data);
197 parse_ip(arg, &mydata->ip);
198 DP("%s", ip_tostring_numeric(mydata->ip));
200 return 1;
204 * Print and save
207 static void
208 ipmap_initheader(struct set *set, const void *data)
210 const struct ip_set_req_ipmap_create *header = data;
211 struct ip_set_ipmap *map = set->settype->header;
213 memset(map, 0, sizeof(struct ip_set_ipmap));
214 map->first_ip = header->from;
215 map->last_ip = header->to;
216 map->netmask = header->netmask;
218 if (map->netmask == 0xFFFFFFFF) {
219 map->hosts = 1;
220 map->sizeid = map->last_ip - map->first_ip + 1;
221 } else {
222 unsigned int mask_bits, netmask_bits;
223 ip_set_ip_t mask;
225 mask = range_to_mask(header->from, header->to, &mask_bits);
226 netmask_bits = mask_to_bits(header->netmask);
228 DP("bits: %d %d", mask_bits, netmask_bits);
229 map->hosts = 2 << (32 - netmask_bits - 1);
230 map->sizeid = 2 << (netmask_bits - mask_bits - 1);
233 DP("%d %d", map->hosts, map->sizeid );
236 static void
237 ipmap_printheader(struct set *set, unsigned options)
239 struct ip_set_ipmap *mysetdata = set->settype->header;
241 printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
242 printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
243 if (mysetdata->netmask == 0xFFFFFFFF)
244 printf("\n");
245 else
246 printf(" netmask: %d\n", mask_to_bits(mysetdata->netmask));
249 static inline void
250 __ipmap_printips_sorted(struct set *set, void *data,
251 u_int32_t len UNUSED, unsigned options)
253 struct ip_set_ipmap *mysetdata = set->settype->header;
254 ip_set_ip_t id;
256 for (id = 0; id < mysetdata->sizeid; id++)
257 if (test_bit(id, data))
258 printf("%s\n",
259 ip_tostring(mysetdata->first_ip
260 + id * mysetdata->hosts,
261 options));
264 static void
265 ipmap_printips_sorted(struct set *set, void *data,
266 u_int32_t len, unsigned options,
267 char dont_align)
269 ip_set_ip_t *ip;
270 size_t offset = 0;
272 if (dont_align)
273 return __ipmap_printips_sorted(set, data, len, options);
275 while (offset < len) {
276 DP("offset: %zu, len %u\n", offset, len);
277 ip = data + offset;
278 printf("%s\n", ip_tostring(*ip, options));
279 offset += IPSET_ALIGN(sizeof(ip_set_ip_t));
283 static void
284 ipmap_saveheader(struct set *set, unsigned options)
286 struct ip_set_ipmap *mysetdata = set->settype->header;
288 printf("-N %s %s --from %s",
289 set->name, set->settype->typename,
290 ip_tostring(mysetdata->first_ip, options));
291 printf(" --to %s",
292 ip_tostring(mysetdata->last_ip, options));
293 if (mysetdata->netmask == 0xFFFFFFFF)
294 printf("\n");
295 else
296 printf(" --netmask %d\n",
297 mask_to_bits(mysetdata->netmask));
300 static inline void
301 __ipmap_saveips(struct set *set, void *data, u_int32_t len UNUSED,
302 unsigned options)
304 struct ip_set_ipmap *mysetdata = set->settype->header;
305 ip_set_ip_t id;
307 DP("%s", set->name);
308 for (id = 0; id < mysetdata->sizeid; id++)
309 if (test_bit(id, data))
310 printf("-A %s %s\n",
311 set->name,
312 ip_tostring(mysetdata->first_ip
313 + id * mysetdata->hosts,
314 options));
317 static void
318 ipmap_saveips(struct set *set, void *data, u_int32_t len,
319 unsigned options, char dont_align)
321 ip_set_ip_t *ip;
322 size_t offset = 0;
324 if (dont_align)
325 return __ipmap_saveips(set, data, len, options);
327 while (offset < len) {
328 ip = data + offset;
329 printf("-A %s %s\n", set->name, ip_tostring(*ip, options));
330 offset += IPSET_ALIGN(sizeof(ip_set_ip_t));
334 static void
335 ipmap_usage(void)
337 printf
338 ("-N set ipmap --from IP --to IP [--netmask CIDR-netmask]\n"
339 "-N set ipmap --network IP/mask [--netmask CIDR-netmask]\n"
340 "-A set IP\n"
341 "-D set IP\n"
342 "-T set IP\n");
345 static struct settype settype_ipmap = {
346 .typename = SETTYPE_NAME,
347 .protocol_version = IP_SET_PROTOCOL_VERSION,
349 /* Create */
350 .create_size = sizeof(struct ip_set_req_ipmap_create),
351 .create_init = ipmap_create_init,
352 .create_parse = ipmap_create_parse,
353 .create_final = ipmap_create_final,
354 .create_opts = create_opts,
356 /* Add/del/test */
357 .adt_size = sizeof(struct ip_set_req_ipmap),
358 .adt_parser = ipmap_adt_parser,
360 /* Printing */
361 .header_size = sizeof(struct ip_set_ipmap),
362 .initheader = ipmap_initheader,
363 .printheader = ipmap_printheader,
364 .printips = ipmap_printips_sorted,
365 .printips_sorted = ipmap_printips_sorted,
366 .saveheader = ipmap_saveheader,
367 .saveips = ipmap_saveips,
369 .usage = ipmap_usage,
372 CONSTRUCTOR(ipmap)
374 settype_register(&settype_ipmap);