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>
31 #include <linux/netfilter_ipv4/ip_set_nethash.h>
32 #include <linux/netfilter_ipv4/ip_set_jhash.h>
38 #define OPT_CREATE_HASHSIZE 0x01U
39 #define OPT_CREATE_PROBES 0x02U
40 #define OPT_CREATE_RESIZE 0x04U
42 /* Initialize the create. */
43 void create_init(void *data)
45 struct ip_set_req_nethash_create *mydata =
46 (struct ip_set_req_nethash_create *) data;
50 /* Default create parameters */
51 mydata->hashsize = 1024;
56 /* Function which parses command options; returns true if it ate an option */
57 int create_parse(int c, char *argv[], void *data, unsigned *flags)
59 struct ip_set_req_nethash_create *mydata =
60 (struct ip_set_req_nethash_create *) data;
68 if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
69 exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
71 *flags |= OPT_CREATE_HASHSIZE;
73 DP("--hashsize %u", mydata->hashsize);
79 if (string_to_number(optarg, 1, 65535, &value))
80 exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
82 mydata->probes = value;
83 *flags |= OPT_CREATE_PROBES;
85 DP("--probes %u", mydata->probes);
91 if (string_to_number(optarg, 0, 65535, &value))
92 exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
94 mydata->resize = value;
95 *flags |= OPT_CREATE_RESIZE;
97 DP("--resize %u", mydata->resize);
108 /* Final check; exit if not ok. */
109 void create_final(void *data, unsigned int flags)
112 struct ip_set_req_nethash_create *mydata =
113 (struct ip_set_req_nethash_create *) data;
115 DP("hashsize %u probes %u resize %u",
116 mydata->hashsize, mydata->probes, mydata->resize);
120 /* Create commandline options */
121 static struct option create_opts[] = {
122 {"hashsize", 1, 0, '1'},
123 {"probes", 1, 0, '2'},
124 {"resize", 1, 0, '3'},
128 /* Add, del, test parser */
129 ip_set_ip_t adt_parser(unsigned cmd, const char *optarg, void *data)
131 struct ip_set_req_nethash *mydata =
132 (struct ip_set_req_nethash *) data;
133 char *saved = ipset_strdup(optarg);
134 char *ptr, *tmp = saved;
137 ptr = strsep(&tmp, "/");
143 exit_error(PARAMETER_PROBLEM,
144 "Missing cidr from `%s'", optarg);
146 if (string_to_number(tmp, 1, 31, &cidr))
147 exit_error(PARAMETER_PROBLEM,
148 "Out of range cidr `%s' specified", optarg);
151 parse_ip(ptr, &mydata->ip);
153 exit_error(PARAMETER_PROBLEM,
154 "Zero valued IP address `%s' specified", ptr);
164 void initheader(struct set *set, const void *data)
166 struct ip_set_req_nethash_create *header =
167 (struct ip_set_req_nethash_create *) data;
168 struct ip_set_nethash *map =
169 (struct ip_set_nethash *) set->settype->header;
171 memset(map, 0, sizeof(struct ip_set_nethash));
172 map->hashsize = header->hashsize;
173 map->probes = header->probes;
174 map->resize = header->resize;
178 mask_to_bits(ip_set_ip_t mask)
180 unsigned int bits = 32;
181 ip_set_ip_t maskaddr;
183 if (mask == 0xFFFFFFFF)
186 maskaddr = 0xFFFFFFFE;
187 while (--bits >= 0 && maskaddr != mask)
193 void printheader(struct set *set, unsigned options)
195 struct ip_set_nethash *mysetdata =
196 (struct ip_set_nethash *) set->settype->header;
198 printf(" hashsize: %u", mysetdata->hashsize);
199 printf(" probes: %u", mysetdata->probes);
200 printf(" resize: %u\n", mysetdata->resize);
205 static char * unpack_ip_tostring(ip_set_ip_t ip, unsigned options)
211 for (i = 3; i >= 0; i--)
212 if (((unsigned char *)&ip)[i] != 0) {
217 a = ((unsigned char *)&ip)[j];
221 } else if (a <= 192) {
224 } else if (a <= 224) {
227 } else if (a <= 240) {
230 } else if (a <= 248) {
233 } else if (a <= 252) {
236 } else if (a <= 254) {
242 ((unsigned char *)&ip)[j] = a;
245 sprintf(buf, "%u.%u.%u.%u/%u",
246 ((unsigned char *)&ip)[0],
247 ((unsigned char *)&ip)[1],
248 ((unsigned char *)&ip)[2],
249 ((unsigned char *)&ip)[3],
252 DP("%s %s", ip_tostring(ntohl(ip), options), buf);
256 void printips(struct set *set, void *data, size_t len, unsigned options)
261 while (offset < len) {
264 printf("%s\n", unpack_ip_tostring(*ip, options));
265 offset += sizeof(ip_set_ip_t);
269 void saveheader(struct set *set, unsigned options)
271 struct ip_set_nethash *mysetdata =
272 (struct ip_set_nethash *) set->settype->header;
274 printf("-N %s %s --hashsize %u --probes %u --resize %u\n",
275 set->name, set->settype->typename,
276 mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
279 /* Print save for an IP */
280 void saveips(struct set *set, void *data, size_t len, unsigned options)
285 while (offset < len) {
288 printf("-A %s %s\n", set->name,
289 unpack_ip_tostring(*ip, options));
290 offset += sizeof(ip_set_ip_t);
294 static char * net_tostring(struct set *set, ip_set_ip_t ip, unsigned options)
296 return unpack_ip_tostring(ip, options);
299 static void parse_net(const char *str, ip_set_ip_t *ip)
301 char *saved = strdup(str);
302 char *ptr, *tmp = saved;
305 ptr = strsep(&tmp, "/");
308 exit_error(PARAMETER_PROBLEM,
309 "Missing cidr from `%s'", str);
311 if (string_to_number(tmp, 1, 31, &cidr))
312 exit_error(PARAMETER_PROBLEM,
313 "Out of range cidr `%s' specified", str);
318 *ip = pack(*ip, cidr);
324 ("-N set nethash [--hashsize hashsize] [--probes probes ]\n"
325 " [--resize resize]\n"
331 static struct settype settype_nethash = {
332 .typename = SETTYPE_NAME,
333 .protocol_version = IP_SET_PROTOCOL_VERSION,
336 .create_size = sizeof(struct ip_set_req_nethash_create),
337 .create_init = &create_init,
338 .create_parse = &create_parse,
339 .create_final = &create_final,
340 .create_opts = create_opts,
343 .adt_size = sizeof(struct ip_set_req_nethash),
344 .adt_parser = &adt_parser,
347 .header_size = sizeof(struct ip_set_nethash),
348 .initheader = &initheader,
349 .printheader = &printheader,
350 .printips = &printips, /* We only have the unsorted version */
351 .printips_sorted = &printips,
352 .saveheader = &saveheader,
356 .bindip_tostring = &net_tostring,
357 .bindip_parse = &parse_net,
362 void __attribute__ ((constructor)) my_init(void)
364 settype_register(&settype_nethash);