1 /* Copyright 2004 Jozsef Kadlecsik (kadlec@blackhole.kfki.hu)
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include <sys/socket.h>
25 #include <sys/types.h>
26 #include <netinet/in.h>
27 #include <arpa/inet.h>
28 #include <asm/types.h>
30 #include <linux/netfilter_ipv4/ip_set_nethash.h>
31 #include <linux/netfilter_ipv4/ip_set_jhash.h>
37 #define OPT_CREATE_HASHSIZE 0x01U
38 #define OPT_CREATE_PROBES 0x02U
39 #define OPT_CREATE_RESIZE 0x04U
41 /* Initialize the create. */
42 void create_init(void *data)
44 struct ip_set_req_nethash_create *mydata =
45 (struct ip_set_req_nethash_create *) data;
49 /* Default create parameters */
50 mydata->hashsize = 1024;
55 /* Function which parses command options; returns true if it ate an option */
56 int create_parse(int c, char *argv[], void *data, unsigned *flags)
58 struct ip_set_req_nethash_create *mydata =
59 (struct ip_set_req_nethash_create *) data;
67 if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
68 exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
70 *flags |= OPT_CREATE_HASHSIZE;
72 DP("--hashsize %u", mydata->hashsize);
78 if (string_to_number(optarg, 1, 65535, &value))
79 exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
81 mydata->probes = value;
82 *flags |= OPT_CREATE_PROBES;
84 DP("--probes %u", mydata->probes);
90 if (string_to_number(optarg, 0, 65535, &value))
91 exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
93 mydata->resize = value;
94 *flags |= OPT_CREATE_RESIZE;
96 DP("--resize %u", mydata->resize);
107 /* Final check; exit if not ok. */
108 void create_final(void *data, unsigned int flags)
111 struct ip_set_req_nethash_create *mydata =
112 (struct ip_set_req_nethash_create *) data;
114 DP("hashsize %u probes %u resize %u",
115 mydata->hashsize, mydata->probes, mydata->resize);
119 /* Create commandline options */
120 static struct option create_opts[] = {
121 {"hashsize", 1, 0, '1'},
122 {"probes", 1, 0, '2'},
123 {"resize", 1, 0, '3'},
127 /* Add, del, test parser */
128 ip_set_ip_t adt_parser(unsigned cmd, const char *optarg, void *data)
130 struct ip_set_req_nethash *mydata =
131 (struct ip_set_req_nethash *) data;
132 char *saved = ipset_strdup(optarg);
133 char *ptr, *tmp = saved;
136 ptr = strsep(&tmp, "/");
142 exit_error(PARAMETER_PROBLEM,
143 "Missing cidr from `%s'", optarg);
145 if (string_to_number(tmp, 1, 31, &cidr))
146 exit_error(PARAMETER_PROBLEM,
147 "Out of range cidr `%s' specified", optarg);
150 parse_ip(ptr, &mydata->ip);
152 exit_error(PARAMETER_PROBLEM,
153 "Zero valued IP address `%s' specified", ptr);
163 void initheader(struct set *set, const void *data)
165 struct ip_set_req_nethash_create *header =
166 (struct ip_set_req_nethash_create *) data;
167 struct ip_set_nethash *map =
168 (struct ip_set_nethash *) set->settype->header;
170 memset(map, 0, sizeof(struct ip_set_nethash));
171 map->hashsize = header->hashsize;
172 map->probes = header->probes;
173 map->resize = header->resize;
177 mask_to_bits(ip_set_ip_t mask)
179 unsigned int bits = 32;
180 ip_set_ip_t maskaddr;
182 if (mask == 0xFFFFFFFF)
185 maskaddr = 0xFFFFFFFE;
186 while (--bits >= 0 && maskaddr != mask)
192 void printheader(struct set *set, unsigned options)
194 struct ip_set_nethash *mysetdata =
195 (struct ip_set_nethash *) set->settype->header;
197 printf(" hashsize: %u", mysetdata->hashsize);
198 printf(" probes: %u", mysetdata->probes);
199 printf(" resize: %u\n", mysetdata->resize);
204 static char * unpack_ip_tostring(ip_set_ip_t ip, unsigned options)
210 for (i = 3; i >= 0; i--)
211 if (((unsigned char *)&ip)[i] != 0) {
216 a = ((unsigned char *)&ip)[j];
220 } else if (a <= 192) {
223 } else if (a <= 224) {
226 } else if (a <= 240) {
229 } else if (a <= 248) {
232 } else if (a <= 252) {
235 } else if (a <= 254) {
241 ((unsigned char *)&ip)[j] = a;
244 sprintf(buf, "%u.%u.%u.%u/%u",
245 ((unsigned char *)&ip)[0],
246 ((unsigned char *)&ip)[1],
247 ((unsigned char *)&ip)[2],
248 ((unsigned char *)&ip)[3],
251 DP("%s %s", ip_tostring(ntohl(ip), options), buf);
255 void printips(struct set *set, void *data, size_t len, unsigned options)
260 while (offset < len) {
263 printf("%s\n", unpack_ip_tostring(*ip, options));
264 offset += sizeof(ip_set_ip_t);
268 void saveheader(struct set *set, unsigned options)
270 struct ip_set_nethash *mysetdata =
271 (struct ip_set_nethash *) set->settype->header;
273 printf("-N %s %s --hashsize %u --probes %u --resize %u\n",
274 set->name, set->settype->typename,
275 mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
278 /* Print save for an IP */
279 void saveips(struct set *set, void *data, size_t len, unsigned options)
284 while (offset < len) {
287 printf("-A %s %s\n", set->name,
288 unpack_ip_tostring(*ip, options));
289 offset += sizeof(ip_set_ip_t);
293 static char * net_tostring(struct set *set, ip_set_ip_t ip, unsigned options)
295 return unpack_ip_tostring(ip, options);
298 static void parse_net(const char *str, ip_set_ip_t *ip)
300 char *saved = strdup(str);
301 char *ptr, *tmp = saved;
304 ptr = strsep(&tmp, "/");
307 exit_error(PARAMETER_PROBLEM,
308 "Missing cidr from `%s'", str);
310 if (string_to_number(tmp, 1, 31, &cidr))
311 exit_error(PARAMETER_PROBLEM,
312 "Out of range cidr `%s' specified", str);
317 *ip = pack(*ip, cidr);
323 ("-N set nethash [--hashsize hashsize] [--probes probes ]\n"
324 " [--resize resize]\n"
330 static struct settype settype_nethash = {
331 .typename = SETTYPE_NAME,
332 .protocol_version = IP_SET_PROTOCOL_VERSION,
335 .create_size = sizeof(struct ip_set_req_nethash_create),
336 .create_init = &create_init,
337 .create_parse = &create_parse,
338 .create_final = &create_final,
339 .create_opts = create_opts,
342 .adt_size = sizeof(struct ip_set_req_nethash),
343 .adt_parser = &adt_parser,
346 .header_size = sizeof(struct ip_set_nethash),
347 .initheader = &initheader,
348 .printheader = &printheader,
349 .printips = &printips, /* We only have the unsorted version */
350 .printips_sorted = &printips,
351 .saveheader = &saveheader,
355 .bindip_tostring = &net_tostring,
356 .bindip_parse = &parse_net,
363 settype_register(&settype_nethash);