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.
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
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <arpa/inet.h>
25 #ifndef __always_inline
26 #define __always_inline inline
28 #include <asm/bitops.h>
30 #include <linux/netfilter_ipv4/ip_set_ipmap.h>
35 #define OPT_CREATE_FROM 0x01U
36 #define OPT_CREATE_TO 0x02U
37 #define OPT_CREATE_NETWORK 0x04U
38 #define OPT_CREATE_NETMASK 0x08U
40 #define OPT_ADDDEL_IP 0x01U
42 /* Initialize the create. */
43 void create_init(void *data)
45 struct ip_set_req_ipmap_create *mydata =
46 (struct ip_set_req_ipmap_create *) data;
49 mydata->netmask = 0xFFFFFFFF;
52 /* Function which parses command options; returns true if it ate an option */
53 int create_parse(int c, char *argv[], void *data, unsigned *flags)
55 struct ip_set_req_ipmap_create *mydata =
56 (struct ip_set_req_ipmap_create *) data;
63 parse_ip(optarg, &mydata->from);
65 *flags |= OPT_CREATE_FROM;
67 DP("--from %x (%s)", mydata->from,
68 ip_tostring_numeric(mydata->from));
73 parse_ip(optarg, &mydata->to);
75 *flags |= OPT_CREATE_TO;
77 DP("--to %x (%s)", mydata->to,
78 ip_tostring_numeric(mydata->to));
83 parse_ipandmask(optarg, &mydata->from, &mydata->to);
85 /* Make to the last of from + mask */
87 mydata->to = mydata->from | ~(mydata->to);
89 mydata->from = 0x00000000;
90 mydata->to = 0xFFFFFFFF;
92 *flags |= OPT_CREATE_NETWORK;
94 DP("--network from %x (%s)",
95 mydata->from, ip_tostring_numeric(mydata->from));
96 DP("--network to %x (%s)",
97 mydata->to, ip_tostring_numeric(mydata->to));
102 if (string_to_number(optarg, 0, 32, &bits))
103 exit_error(PARAMETER_PROBLEM,
104 "Invalid netmask `%s' specified", optarg);
107 mydata->netmask = 0xFFFFFFFF << (32 - bits);
109 *flags |= OPT_CREATE_NETMASK;
111 DP("--netmask %x", mydata->netmask);
122 #define ERRSTRLEN 256
124 /* Final check; exit if not ok. */
125 void create_final(void *data, unsigned int flags)
127 struct ip_set_req_ipmap_create *mydata =
128 (struct ip_set_req_ipmap_create *) data;
130 char errstr[ERRSTRLEN];
133 exit_error(PARAMETER_PROBLEM,
134 "Need to specify --from and --to, or --network\n");
136 if (flags & OPT_CREATE_NETWORK) {
138 if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
139 exit_error(PARAMETER_PROBLEM,
140 "Can't specify --from or --to with --network\n");
143 if ((flags & OPT_CREATE_FROM) == 0
144 || (flags & OPT_CREATE_TO) == 0)
145 exit_error(PARAMETER_PROBLEM,
146 "Need to specify both --from and --to\n");
149 DP("from : %x to: %x diff: %x",
150 mydata->from, mydata->to,
151 mydata->to - mydata->from);
153 if (mydata->from > mydata->to)
154 exit_error(PARAMETER_PROBLEM,
155 "From can't be lower than to.\n");
157 if (flags & OPT_CREATE_NETMASK) {
158 unsigned int mask_bits, netmask_bits;
161 if ((mydata->from & mydata->netmask) != mydata->from)
162 exit_error(PARAMETER_PROBLEM,
163 "%s is not a network address according to netmask %d\n",
164 ip_tostring_numeric(mydata->from),
165 mask_to_bits(mydata->netmask));
167 mask = range_to_mask(mydata->from, mydata->to, &mask_bits);
169 && (mydata->from || mydata->to != 0xFFFFFFFF)) {
170 strncpy(errstr, ip_tostring_numeric(mydata->from),
172 errstr[ERRSTRLEN-1] = '\0';
173 exit_error(PARAMETER_PROBLEM,
174 "%s-%s is not a full network (%x)\n",
176 ip_tostring_numeric(mydata->to), mask);
178 netmask_bits = mask_to_bits(mydata->netmask);
180 if (netmask_bits <= mask_bits) {
181 strncpy(errstr, ip_tostring_numeric(mydata->from),
183 errstr[ERRSTRLEN-1] = '\0';
184 exit_error(PARAMETER_PROBLEM,
185 "%d netmask specifies larger or equal netblock than %s-%s (%d)\n",
188 ip_tostring_numeric(mydata->to),
191 range = (1<<(netmask_bits - mask_bits)) - 1;
193 range = mydata->to - mydata->from;
195 if (range > MAX_RANGE)
196 exit_error(PARAMETER_PROBLEM,
197 "Range to large. Max is %d IPs in range\n",
201 /* Create commandline options */
202 static struct option create_opts[] = {
205 {"network", 1, 0, '3'},
206 {"netmask", 1, 0, '4'},
210 /* Add, del, test parser */
211 ip_set_ip_t adt_parser(unsigned cmd, const char *optarg, void *data)
213 struct ip_set_req_ipmap *mydata =
214 (struct ip_set_req_ipmap *) data;
216 DP("ipmap: %p %p", optarg, data);
218 parse_ip(optarg, &mydata->ip);
219 DP("%s", ip_tostring_numeric(mydata->ip));
228 void initheader(struct set *set, const void *data)
230 struct ip_set_req_ipmap_create *header =
231 (struct ip_set_req_ipmap_create *) data;
232 struct ip_set_ipmap *map =
233 (struct ip_set_ipmap *) set->settype->header;
235 memset(map, 0, sizeof(struct ip_set_ipmap));
236 map->first_ip = header->from;
237 map->last_ip = header->to;
238 map->netmask = header->netmask;
240 if (map->netmask == 0xFFFFFFFF) {
242 map->sizeid = map->last_ip - map->first_ip + 1;
244 unsigned int mask_bits, netmask_bits;
247 mask = range_to_mask(header->from, header->to, &mask_bits);
248 netmask_bits = mask_to_bits(header->netmask);
250 DP("bits: %i %i", mask_bits, netmask_bits);
251 map->hosts = 2 << (32 - netmask_bits - 1);
252 map->sizeid = 2 << (netmask_bits - mask_bits - 1);
255 DP("%i %i", map->hosts, map->sizeid );
258 void printheader(struct set *set, unsigned options)
260 struct ip_set_ipmap *mysetdata =
261 (struct ip_set_ipmap *) set->settype->header;
263 printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
264 printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
265 if (mysetdata->netmask == 0xFFFFFFFF)
268 printf(" netmask: %d\n", mask_to_bits(mysetdata->netmask));
271 void printips_sorted(struct set *set, void *data, size_t len, unsigned options)
273 struct ip_set_ipmap *mysetdata =
274 (struct ip_set_ipmap *) set->settype->header;
277 for (id = 0; id < mysetdata->sizeid; id++)
278 if (test_bit(id, data))
280 ip_tostring(mysetdata->first_ip
281 + id * mysetdata->hosts,
285 void saveheader(struct set *set, unsigned options)
287 struct ip_set_ipmap *mysetdata =
288 (struct ip_set_ipmap *) set->settype->header;
290 printf("-N %s %s --from %s",
291 set->name, set->settype->typename,
292 ip_tostring(mysetdata->first_ip, options));
294 ip_tostring(mysetdata->last_ip, options));
295 if (mysetdata->netmask == 0xFFFFFFFF)
298 printf(" --netmask %d\n",
299 mask_to_bits(mysetdata->netmask));
302 void saveips(struct set *set, void *data, size_t len, unsigned options)
304 struct ip_set_ipmap *mysetdata =
305 (struct ip_set_ipmap *) set->settype->header;
309 for (id = 0; id < mysetdata->sizeid; id++)
310 if (test_bit(id, data))
313 ip_tostring(mysetdata->first_ip
314 + id * mysetdata->hosts,
321 ("-N set ipmap --from IP --to IP [--netmask CIDR-netmask]\n"
322 "-N set ipmap --network IP/mask [--netmask CIDR-netmask]\n"
328 static struct settype settype_ipmap = {
329 .typename = SETTYPE_NAME,
330 .protocol_version = IP_SET_PROTOCOL_VERSION,
333 .create_size = sizeof(struct ip_set_req_ipmap_create),
334 .create_init = &create_init,
335 .create_parse = &create_parse,
336 .create_final = &create_final,
337 .create_opts = create_opts,
340 .adt_size = sizeof(struct ip_set_req_ipmap),
341 .adt_parser = &adt_parser,
344 .header_size = sizeof(struct ip_set_ipmap),
345 .initheader = &initheader,
346 .printheader = &printheader,
347 .printips = &printips_sorted, /* We only have sorted version */
348 .printips_sorted = &printips_sorted,
349 .saveheader = &saveheader,
353 .bindip_tostring = &binding_ip_tostring,
354 .bindip_parse = &parse_ip,
361 settype_register(&settype_ipmap);