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 /* #include <asm/bitops.h> */
27 #include <linux/netfilter_ipv4/ip_set_ipmap.h>
32 #define OPT_CREATE_FROM 0x01U
33 #define OPT_CREATE_TO 0x02U
34 #define OPT_CREATE_NETWORK 0x04U
35 #define OPT_CREATE_NETMASK 0x08U
37 #define OPT_ADDDEL_IP 0x01U
39 /* Initialize the create. */
40 void create_init(void *data)
42 struct ip_set_req_ipmap_create *mydata =
43 (struct ip_set_req_ipmap_create *) data;
46 mydata->netmask = 0xFFFFFFFF;
49 /* Function which parses command options; returns true if it ate an option */
50 int create_parse(int c, char *argv[], void *data, unsigned *flags)
52 struct ip_set_req_ipmap_create *mydata =
53 (struct ip_set_req_ipmap_create *) data;
60 parse_ip(optarg, &mydata->from);
62 *flags |= OPT_CREATE_FROM;
64 DP("--from %x (%s)", mydata->from,
65 ip_tostring_numeric(mydata->from));
70 parse_ip(optarg, &mydata->to);
72 *flags |= OPT_CREATE_TO;
74 DP("--to %x (%s)", mydata->to,
75 ip_tostring_numeric(mydata->to));
80 parse_ipandmask(optarg, &mydata->from, &mydata->to);
82 /* Make to the last of from + mask */
84 mydata->to = mydata->from | ~(mydata->to);
86 mydata->from = 0x00000000;
87 mydata->to = 0xFFFFFFFF;
89 *flags |= OPT_CREATE_NETWORK;
91 DP("--network from %x (%s)",
92 mydata->from, ip_tostring_numeric(mydata->from));
93 DP("--network to %x (%s)",
94 mydata->to, ip_tostring_numeric(mydata->to));
99 if (string_to_number(optarg, 0, 32, &bits))
100 exit_error(PARAMETER_PROBLEM,
101 "Invalid netmask `%s' specified", optarg);
104 mydata->netmask = 0xFFFFFFFF << (32 - bits);
106 *flags |= OPT_CREATE_NETMASK;
108 DP("--netmask %x", mydata->netmask);
119 #define ERRSTRLEN 256
121 /* Final check; exit if not ok. */
122 void create_final(void *data, unsigned int flags)
124 struct ip_set_req_ipmap_create *mydata =
125 (struct ip_set_req_ipmap_create *) data;
127 char errstr[ERRSTRLEN];
130 exit_error(PARAMETER_PROBLEM,
131 "Need to specify --from and --to, or --network\n");
133 if (flags & OPT_CREATE_NETWORK) {
135 if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
136 exit_error(PARAMETER_PROBLEM,
137 "Can't specify --from or --to with --network\n");
140 if ((flags & OPT_CREATE_FROM) == 0
141 || (flags & OPT_CREATE_TO) == 0)
142 exit_error(PARAMETER_PROBLEM,
143 "Need to specify both --from and --to\n");
146 DP("from : %x to: %x diff: %x",
147 mydata->from, mydata->to,
148 mydata->to - mydata->from);
150 if (mydata->from > mydata->to)
151 exit_error(PARAMETER_PROBLEM,
152 "From can't be lower than to.\n");
154 if (flags & OPT_CREATE_NETMASK) {
155 unsigned int mask_bits, netmask_bits;
158 if ((mydata->from & mydata->netmask) != mydata->from)
159 exit_error(PARAMETER_PROBLEM,
160 "%s is not a network address according to netmask %d\n",
161 ip_tostring_numeric(mydata->from),
162 mask_to_bits(mydata->netmask));
164 mask = range_to_mask(mydata->from, mydata->to, &mask_bits);
166 && (mydata->from || mydata->to != 0xFFFFFFFF)) {
167 strncpy(errstr, ip_tostring_numeric(mydata->from),
169 errstr[ERRSTRLEN-1] = '\0';
170 exit_error(PARAMETER_PROBLEM,
171 "%s-%s is not a full network (%x)\n",
173 ip_tostring_numeric(mydata->to), mask);
175 netmask_bits = mask_to_bits(mydata->netmask);
177 if (netmask_bits <= mask_bits) {
178 strncpy(errstr, ip_tostring_numeric(mydata->from),
180 errstr[ERRSTRLEN-1] = '\0';
181 exit_error(PARAMETER_PROBLEM,
182 "%d netmask specifies larger or equal netblock than %s-%s (%d)\n",
185 ip_tostring_numeric(mydata->to),
188 range = (1<<(netmask_bits - mask_bits)) - 1;
190 range = mydata->to - mydata->from;
192 if (range > MAX_RANGE)
193 exit_error(PARAMETER_PROBLEM,
194 "Range too large. Max is %d IPs in range\n",
198 /* Create commandline options */
199 static struct option create_opts[] = {
202 {"network", 1, 0, '3'},
203 {"netmask", 1, 0, '4'},
207 /* Add, del, test parser */
208 ip_set_ip_t adt_parser(unsigned cmd, const char *optarg, void *data)
210 struct ip_set_req_ipmap *mydata =
211 (struct ip_set_req_ipmap *) data;
213 DP("ipmap: %p %p", optarg, data);
215 parse_ip(optarg, &mydata->ip);
216 DP("%s", ip_tostring_numeric(mydata->ip));
225 void initheader(struct set *set, const void *data)
227 struct ip_set_req_ipmap_create *header =
228 (struct ip_set_req_ipmap_create *) data;
229 struct ip_set_ipmap *map =
230 (struct ip_set_ipmap *) set->settype->header;
232 memset(map, 0, sizeof(struct ip_set_ipmap));
233 map->first_ip = header->from;
234 map->last_ip = header->to;
235 map->netmask = header->netmask;
237 if (map->netmask == 0xFFFFFFFF) {
239 map->sizeid = map->last_ip - map->first_ip + 1;
241 unsigned int mask_bits, netmask_bits;
244 mask = range_to_mask(header->from, header->to, &mask_bits);
245 netmask_bits = mask_to_bits(header->netmask);
247 DP("bits: %i %i", mask_bits, netmask_bits);
248 map->hosts = 2 << (32 - netmask_bits - 1);
249 map->sizeid = 2 << (netmask_bits - mask_bits - 1);
252 DP("%i %i", map->hosts, map->sizeid );
255 void printheader(struct set *set, unsigned options)
257 struct ip_set_ipmap *mysetdata =
258 (struct ip_set_ipmap *) set->settype->header;
260 printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
261 printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
262 if (mysetdata->netmask == 0xFFFFFFFF)
265 printf(" netmask: %d\n", mask_to_bits(mysetdata->netmask));
268 void printips_sorted(struct set *set, void *data, size_t len, unsigned options)
270 struct ip_set_ipmap *mysetdata =
271 (struct ip_set_ipmap *) set->settype->header;
274 for (id = 0; id < mysetdata->sizeid; id++)
275 if (test_bit(id, data))
277 ip_tostring(mysetdata->first_ip
278 + id * mysetdata->hosts,
282 void saveheader(struct set *set, unsigned options)
284 struct ip_set_ipmap *mysetdata =
285 (struct ip_set_ipmap *) set->settype->header;
287 printf("-N %s %s --from %s",
288 set->name, set->settype->typename,
289 ip_tostring(mysetdata->first_ip, options));
291 ip_tostring(mysetdata->last_ip, options));
292 if (mysetdata->netmask == 0xFFFFFFFF)
295 printf(" --netmask %d\n",
296 mask_to_bits(mysetdata->netmask));
299 void saveips(struct set *set, void *data, size_t len, unsigned options)
301 struct ip_set_ipmap *mysetdata =
302 (struct ip_set_ipmap *) set->settype->header;
306 for (id = 0; id < mysetdata->sizeid; id++)
307 if (test_bit(id, data))
310 ip_tostring(mysetdata->first_ip
311 + id * mysetdata->hosts,
318 ("-N set ipmap --from IP --to IP [--netmask CIDR-netmask]\n"
319 "-N set ipmap --network IP/mask [--netmask CIDR-netmask]\n"
325 static struct settype settype_ipmap = {
326 .typename = SETTYPE_NAME,
327 .protocol_version = IP_SET_PROTOCOL_VERSION,
330 .create_size = sizeof(struct ip_set_req_ipmap_create),
331 .create_init = &create_init,
332 .create_parse = &create_parse,
333 .create_final = &create_final,
334 .create_opts = create_opts,
337 .adt_size = sizeof(struct ip_set_req_ipmap),
338 .adt_parser = &adt_parser,
341 .header_size = sizeof(struct ip_set_ipmap),
342 .initheader = &initheader,
343 .printheader = &printheader,
344 .printips = &printips_sorted, /* We only have sorted version */
345 .printips_sorted = &printips_sorted,
346 .saveheader = &saveheader,
350 .bindip_tostring = &binding_ip_tostring,
351 .bindip_parse = &parse_ip,
358 settype_register(&settype_ipmap);