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
20 #include <stdio.h> /* *printf */
21 #include <string.h> /* mem* */
25 #include <linux/netfilter_ipv4/ip_set_ipmap.h>
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. */
38 ipmap_create_init(void *data
)
40 struct ip_set_req_ipmap_create
*mydata
= data
;
43 mydata
->netmask
= 0xFFFFFFFF;
46 /* Function which parses command options; returns true if it ate an option */
48 ipmap_create_parse(int c
, char *argv
[] UNUSED
, void *data
, unsigned *flags
)
50 struct ip_set_req_ipmap_create
*mydata
= data
;
57 parse_ip(optarg
, &mydata
->from
);
59 *flags
|= OPT_CREATE_FROM
;
61 DP("--from %x (%s)", mydata
->from
,
62 ip_tostring_numeric(mydata
->from
));
67 parse_ip(optarg
, &mydata
->to
);
69 *flags
|= OPT_CREATE_TO
;
71 DP("--to %x (%s)", mydata
->to
,
72 ip_tostring_numeric(mydata
->to
));
77 parse_ipandmask(optarg
, &mydata
->from
, &mydata
->to
);
79 /* Make to the last of from + mask */
81 mydata
->to
= mydata
->from
| ~(mydata
->to
);
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
));
96 if (string_to_number(optarg
, 0, 32, &bits
))
97 exit_error(PARAMETER_PROBLEM
,
98 "Invalid netmask `%s' specified", optarg
);
101 mydata
->netmask
= 0xFFFFFFFF << (32 - bits
);
103 *flags
|= OPT_CREATE_NETMASK
;
105 DP("--netmask %x", mydata
->netmask
);
116 /* Final check; exit if not ok. */
118 ipmap_create_final(void *data
, unsigned int flags
)
120 struct ip_set_req_ipmap_create
*mydata
= data
;
124 exit_error(PARAMETER_PROBLEM
,
125 "Need to specify --from and --to, or --network\n");
127 if (flags
& OPT_CREATE_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");
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
;
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
);
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;
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",
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'},
189 /* Add, del, test parser */
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
));
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) {
220 map
->sizeid
= map
->last_ip
- map
->first_ip
+ 1;
222 unsigned int mask_bits
, netmask_bits
;
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
);
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)
246 printf(" netmask: %d\n", mask_to_bits(mysetdata
->netmask
));
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
;
256 for (id
= 0; id
< mysetdata
->sizeid
; id
++)
257 if (test_bit(id
, data
))
259 ip_tostring(mysetdata
->first_ip
260 + id
* mysetdata
->hosts
,
265 ipmap_printips_sorted(struct set
*set
, void *data
,
266 u_int32_t len
, unsigned options
,
273 return __ipmap_printips_sorted(set
, data
, len
, options
);
275 while (offset
< len
) {
276 DP("offset: %zu, len %u\n", offset
, len
);
278 printf("%s\n", ip_tostring(*ip
, options
));
279 offset
+= IPSET_ALIGN(sizeof(ip_set_ip_t
));
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
));
292 ip_tostring(mysetdata
->last_ip
, options
));
293 if (mysetdata
->netmask
== 0xFFFFFFFF)
296 printf(" --netmask %d\n",
297 mask_to_bits(mysetdata
->netmask
));
301 __ipmap_saveips(struct set
*set
, void *data
, u_int32_t len UNUSED
,
304 struct ip_set_ipmap
*mysetdata
= set
->settype
->header
;
308 for (id
= 0; id
< mysetdata
->sizeid
; id
++)
309 if (test_bit(id
, data
))
312 ip_tostring(mysetdata
->first_ip
313 + id
* mysetdata
->hosts
,
318 ipmap_saveips(struct set
*set
, void *data
, u_int32_t len
,
319 unsigned options
, char dont_align
)
325 return __ipmap_saveips(set
, data
, len
, options
);
327 while (offset
< len
) {
329 printf("-A %s %s\n", set
->name
, ip_tostring(*ip
, options
));
330 offset
+= IPSET_ALIGN(sizeof(ip_set_ip_t
));
338 ("-N set ipmap --from IP --to IP [--netmask CIDR-netmask]\n"
339 "-N set ipmap --network IP/mask [--netmask CIDR-netmask]\n"
345 static struct settype settype_ipmap
= {
346 .typename
= SETTYPE_NAME
,
347 .protocol_version
= IP_SET_PROTOCOL_VERSION
,
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
,
357 .adt_size
= sizeof(struct ip_set_req_ipmap
),
358 .adt_parser
= ipmap_adt_parser
,
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
,
374 settype_register(&settype_ipmap
);