1
/* Copyright 2008 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
18
#include <limits.h> /* UINT_MAX */
19
#include <stdio.h> /* *printf */
20
#include <string.h> /* mem*, str* */
24
#include "ip_set_ipportiphash.h"
26
#define OPT_CREATE_HASHSIZE 0x01U
27
#define OPT_CREATE_PROBES 0x02U
28
#define OPT_CREATE_RESIZE 0x04U
29
#define OPT_CREATE_NETWORK 0x08U
30
#define OPT_CREATE_FROM 0x10U
31
#define OPT_CREATE_TO 0x20U
33
/* Initialize the create. */
35
ipportiphash_create_init(void *data)
37
struct ip_set_req_ipportiphash_create *mydata = data;
41
/* Default create parameters */
42
mydata->hashsize = IP_NF_SET_HASHSIZE;
47
/* Function which parses command options; returns true if it ate an option */
49
ipportiphash_create_parse(int c, char *argv[] UNUSED, void *data,
52
struct ip_set_req_ipportiphash_create *mydata = data;
60
if (string_to_number(optarg, 1, UINT_MAX - 1, &mydata->hashsize))
61
exit_error(PARAMETER_PROBLEM, "Invalid hashsize `%s' specified", optarg);
63
*flags |= OPT_CREATE_HASHSIZE;
65
DP("--hashsize %u", mydata->hashsize);
71
if (string_to_number(optarg, 1, 65535, &value))
72
exit_error(PARAMETER_PROBLEM, "Invalid probes `%s' specified", optarg);
74
mydata->probes = value;
75
*flags |= OPT_CREATE_PROBES;
77
DP("--probes %u", mydata->probes);
83
if (string_to_number(optarg, 0, 65535, &value))
84
exit_error(PARAMETER_PROBLEM, "Invalid resize `%s' specified", optarg);
86
mydata->resize = value;
87
*flags |= OPT_CREATE_RESIZE;
89
DP("--resize %u", mydata->resize);
94
parse_ip(optarg, &mydata->from);
96
*flags |= OPT_CREATE_FROM;
98
DP("--from %x (%s)", mydata->from,
99
ip_tostring_numeric(mydata->from));
104
parse_ip(optarg, &mydata->to);
106
*flags |= OPT_CREATE_TO;
108
DP("--to %x (%s)", mydata->to,
109
ip_tostring_numeric(mydata->to));
114
parse_ipandmask(optarg, &mydata->from, &mydata->to);
116
/* Make to the last of from + mask */
118
mydata->to = mydata->from | ~(mydata->to);
120
mydata->from = 0x00000000;
121
mydata->to = 0xFFFFFFFF;
123
*flags |= OPT_CREATE_NETWORK;
125
DP("--network from %x (%s)",
126
mydata->from, ip_tostring_numeric(mydata->from));
127
DP("--network to %x (%s)",
128
mydata->to, ip_tostring_numeric(mydata->to));
139
/* Final check; exit if not ok. */
141
ipportiphash_create_final(void *data, unsigned int flags)
143
struct ip_set_req_ipportiphash_create *mydata = data;
146
DP("hashsize %u probes %u resize %u",
147
mydata->hashsize, mydata->probes, mydata->resize);
150
if (flags & OPT_CREATE_NETWORK) {
152
if ((flags & OPT_CREATE_FROM) || (flags & OPT_CREATE_TO))
153
exit_error(PARAMETER_PROBLEM,
154
"Can't specify --from or --to with --network\n");
155
} else if (flags & (OPT_CREATE_FROM | OPT_CREATE_TO)) {
157
if (!(flags & OPT_CREATE_FROM) || !(flags & OPT_CREATE_TO))
158
exit_error(PARAMETER_PROBLEM,
159
"Need to specify both --from and --to\n");
161
exit_error(PARAMETER_PROBLEM,
162
"Need to specify --from and --to, or --network\n");
166
DP("from : %x to: %x diff: %x",
167
mydata->from, mydata->to,
168
mydata->to - mydata->from);
170
if (mydata->from > mydata->to)
171
exit_error(PARAMETER_PROBLEM,
172
"From can't be higher than to.\n");
174
if (mydata->to - mydata->from > 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 = "hashsize", .has_arg = required_argument, .val = '1'},
183
{.name = "probes", .has_arg = required_argument, .val = '2'},
184
{.name = "resize", .has_arg = required_argument, .val = '3'},
185
{.name = "from", .has_arg = required_argument, .val = '4'},
186
{.name = "to", .has_arg = required_argument, .val = '5'},
187
{.name = "network", .has_arg = required_argument, .val = '6'},
191
/* Add, del, test parser */
193
ipportiphash_adt_parser(int cmd UNUSED, const char *arg, void *data)
195
struct ip_set_req_ipportiphash *mydata = data;
196
char *saved = ipset_strdup(arg);
197
char *ptr, *tmp = saved;
199
DP("ipportiphash: %p %p", arg, data);
201
if (((ptr = strchr(tmp, ':')) || (ptr = strchr(tmp, '%'))) && ++warn_once == 1)
202
fprintf(stderr, "Warning: please use ',' separator token between ip,port,ip.\n"
203
"Next release won't support old separator tokens.\n");
205
ptr = strsep(&tmp, ":%,");
206
parse_ip(ptr, &mydata->ip);
209
exit_error(PARAMETER_PROBLEM,
210
"IP address, port and IP address must be specified: ip,port,ip");
212
ptr = strsep(&tmp, ":%,");
213
parse_port(ptr, &mydata->port);
215
parse_ip(tmp, &mydata->ip1);
217
exit_error(PARAMETER_PROBLEM,
218
"IP address, port and IP address must be specified: ip,port,ip");
219
if (!(mydata->ip || mydata->port || mydata->ip1))
220
exit_error(PARAMETER_PROBLEM,
221
"Zero valued IP address, port and IP address `%s' specified", arg);
231
ipportiphash_initheader(struct set *set, const void *data)
233
const struct ip_set_req_ipportiphash_create *header = data;
234
struct ip_set_ipportiphash *map = set->settype->header;
236
memset(map, 0, sizeof(struct ip_set_ipportiphash));
237
map->hashsize = header->hashsize;
238
map->probes = header->probes;
239
map->resize = header->resize;
240
map->first_ip = header->from;
241
map->last_ip = header->to;
245
ipportiphash_printheader(struct set *set, unsigned options)
247
struct ip_set_ipportiphash *mysetdata = set->settype->header;
249
printf(" from: %s", ip_tostring(mysetdata->first_ip, options));
250
printf(" to: %s", ip_tostring(mysetdata->last_ip, options));
251
printf(" hashsize: %u", mysetdata->hashsize);
252
printf(" probes: %u", mysetdata->probes);
253
printf(" resize: %u\n", mysetdata->resize);
257
ipportiphash_printips(struct set *set, void *data, u_int32_t len,
258
unsigned options, char dont_align)
260
struct ip_set_ipportiphash *mysetdata = set->settype->header;
262
struct ipportip *ipptr;
266
while (offset < len) {
267
ipptr = data + offset;
268
ip = (ipptr->ip>>16) + mysetdata->first_ip;
269
port = (uint16_t) ipptr->ip;
271
ip_tostring(ip, options),
272
port_tostring(port, options));
274
ip_tostring(ipptr->ip1, options));
275
offset += IPSET_VALIGN(sizeof(struct ipportip), dont_align);
280
ipportiphash_saveheader(struct set *set, unsigned options)
282
struct ip_set_ipportiphash *mysetdata = set->settype->header;
284
printf("-N %s %s --from %s",
285
set->name, set->settype->typename,
286
ip_tostring(mysetdata->first_ip, options));
288
ip_tostring(mysetdata->last_ip, options));
289
printf(" --hashsize %u --probes %u --resize %u\n",
290
mysetdata->hashsize, mysetdata->probes, mysetdata->resize);
293
/* Print save for an IP */
295
ipportiphash_saveips(struct set *set, void *data, u_int32_t len,
296
unsigned options, char dont_align)
298
struct ip_set_ipportiphash *mysetdata = set->settype->header;
300
struct ipportip *ipptr;
304
while (offset < len) {
305
ipptr = data + offset;
306
ip = (ipptr->ip>>16) + mysetdata->first_ip;
307
port = (uint16_t) ipptr->ip;
308
printf("-A %s %s,%s,", set->name,
309
ip_tostring(ip, options),
310
port_tostring(port, options));
312
ip_tostring(ipptr->ip1, options));
313
offset += IPSET_VALIGN(sizeof(struct ipportip), dont_align);
318
ipportiphash_usage(void)
321
("-N set ipportiphash --from IP --to IP\n"
322
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
323
"-N set ipportiphash --network IP/mask\n"
324
" [--hashsize hashsize] [--probes probes ] [--resize resize]\n"
325
"-A set IP,port,IP\n"
326
"-D set IP,port,IP\n"
327
"-T set IP,port,IP\n");
330
static struct settype settype_ipportiphash = {
331
.typename = SETTYPE_NAME,
332
.protocol_version = IP_SET_PROTOCOL_VERSION,
335
.create_size = sizeof(struct ip_set_req_ipportiphash_create),
336
.create_init = ipportiphash_create_init,
337
.create_parse = ipportiphash_create_parse,
338
.create_final = ipportiphash_create_final,
339
.create_opts = create_opts,
342
.adt_size = sizeof(struct ip_set_req_ipportiphash),
343
.adt_parser = ipportiphash_adt_parser,
346
.header_size = sizeof(struct ip_set_ipportiphash),
347
.initheader = ipportiphash_initheader,
348
.printheader = ipportiphash_printheader,
349
.printips = ipportiphash_printips,
350
.printips_sorted = ipportiphash_printips,
351
.saveheader = ipportiphash_saveheader,
352
.saveips = ipportiphash_saveips,
354
.usage = ipportiphash_usage,
357
CONSTRUCTOR(ipportiphash)
359
settype_register(&settype_ipportiphash);