1
/* Copyright 2007-2010 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 version 2 as
5
* published by the Free Software Foundation.
7
#include <assert.h> /* assert */
8
#include <ctype.h> /* tolower */
9
#include <string.h> /* memcmp, str* */
11
#include <libipset/linux_ip_set.h> /* IPSET_CMD_* */
12
#include <libipset/icmp.h> /* id_to_icmp */
13
#include <libipset/icmpv6.h> /* id_to_icmpv6 */
14
#include <libipset/types.h> /* IPSET_*_ARG */
15
#include <libipset/session.h> /* ipset_envopt_parse */
16
#include <libipset/parse.h> /* ipset_parse_family */
17
#include <libipset/print.h> /* ipset_print_family */
18
#include <libipset/utils.h> /* STREQ */
19
#include <libipset/ui.h> /* prototypes */
21
/* Commands and environment options */
23
const struct ipset_commands ipset_commands[] = {
24
/* Order is important */
26
{ /* c[reate], --create, n[ew], -N */
27
.cmd = IPSET_CMD_CREATE,
28
.name = { "create", "new" },
29
.has_arg = IPSET_MANDATORY_ARG2,
30
.help = "SETNAME TYPENAME [type-specific-options]\n"
33
{ /* a[dd], --add, -A */
35
.name = { "add", NULL },
36
.has_arg = IPSET_MANDATORY_ARG2,
37
.help = "SETNAME ENTRY\n"
38
" Add entry to the named set",
40
{ /* d[el], --del, -D */
42
.name = { "del", NULL },
43
.has_arg = IPSET_MANDATORY_ARG2,
44
.help = "SETNAME ENTRY\n"
45
" Delete entry from the named set",
47
{ /* t[est], --test, -T */
48
.cmd = IPSET_CMD_TEST,
49
.name = { "test", NULL },
50
.has_arg = IPSET_MANDATORY_ARG2,
51
.help = "SETNAME ENTRY\n"
52
" Test entry in the named set",
54
{ /* des[troy], --destroy, x, -X */
55
.cmd = IPSET_CMD_DESTROY,
56
.name = { "destroy", "x" },
57
.has_arg = IPSET_OPTIONAL_ARG,
59
" Destroy a named set or all sets",
61
{ /* l[ist], --list, -L */
62
.cmd = IPSET_CMD_LIST,
63
.name = { "list", NULL },
64
.has_arg = IPSET_OPTIONAL_ARG,
66
" List the entries of a named set or all sets",
68
{ /* s[save], --save, -S */
69
.cmd = IPSET_CMD_SAVE,
70
.name = { "save", NULL },
71
.has_arg = IPSET_OPTIONAL_ARG,
73
" Save the named set or all sets to stdout",
75
{ /* r[estore], --restore, -R */
76
.cmd = IPSET_CMD_RESTORE,
77
.name = { "restore", NULL },
78
.has_arg = IPSET_NO_ARG,
80
" Restore a saved state",
82
{ /* f[lush], --flush, -F */
83
.cmd = IPSET_CMD_FLUSH,
84
.name = { "flush", NULL },
85
.has_arg = IPSET_OPTIONAL_ARG,
87
" Flush a named set or all sets",
89
{ /* ren[ame], --rename, e, -E */
90
.cmd = IPSET_CMD_RENAME,
91
.name = { "rename", "e" },
92
.has_arg = IPSET_MANDATORY_ARG2,
93
.help = "FROM-SETNAME TO-SETNAME\n"
96
{ /* sw[ap], --swap, w, -W */
97
.cmd = IPSET_CMD_SWAP,
98
.name = { "swap", "w" },
99
.has_arg = IPSET_MANDATORY_ARG2,
100
.help = "FROM-SETNAME TO-SETNAME\n"
101
" Swap the contect of two existing sets",
103
{ /* h[elp, --help, -H */
104
.cmd = IPSET_CMD_HELP,
105
.name = { "help", NULL },
106
.has_arg = IPSET_OPTIONAL_ARG,
107
.help = "[TYPENAME]\n"
108
" Print help, and settype specific help",
110
{ /* v[ersion], --version, -V */
111
.cmd = IPSET_CMD_VERSION,
112
.name = { "version", NULL },
113
.has_arg = IPSET_NO_ARG,
115
" Print version information",
118
.cmd = IPSET_CMD_QUIT,
119
.name = { "quit", NULL },
120
.has_arg = IPSET_NO_ARG,
122
" Quit interactive mode",
127
/* Match a command: try to match as a prefix or letter-command */
129
ipset_match_cmd(const char *arg, const char * const name[])
134
assert(name && name[0]);
136
/* Ignore (two) leading dashes */
144
if (len > strlen(name[0]) || !len)
147
((strncmp(arg, name[0], len) == 0) ||
148
(name[1] != NULL && (strncmp(arg, name[1], len) == 0))))
152
else return tolower(arg[0]) == name[0][0] ||
153
(name[1] != NULL && tolower(arg[0]) == name[1][0]);
156
const struct ipset_envopts ipset_envopts[] = {
157
{ .name = { "-o", "-output" },
158
.has_arg = IPSET_MANDATORY_ARG, .flag = IPSET_OPT_MAX,
159
.parse = ipset_parse_output,
160
.help = "plain|save|xml\n"
161
" Specify output mode for listing sets.\n"
162
" Default value for \"list\" command is mode \"plain\"\n"
163
" and for \"save\" command is mode \"save\".",
165
{ .name = { "-s", "-sorted" },
166
.parse = ipset_envopt_parse,
167
.has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_SORTED,
169
" Print elements sorted (if supported by the set type).",
171
{ .name = { "-q", "-quiet" },
172
.parse = ipset_envopt_parse,
173
.has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_QUIET,
175
" Suppress any notice or warning message.",
177
{ .name = { "-r", "-resolve" },
178
.parse = ipset_envopt_parse,
179
.has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_RESOLVE,
181
" Try to resolve IP addresses in the output (slow!)",
183
{ .name = { "-!", "-exist" },
184
.parse = ipset_envopt_parse,
185
.has_arg = IPSET_NO_ARG, .flag = IPSET_ENV_EXIST,
187
" Ignore errors when creating already created sets,\n"
188
" when adding already existing elements\n"
189
" or when deleting non-existing elements.",
194
/* Strict option matching */
196
ipset_match_option(const char *arg, const char * const name[])
199
assert(name && name[0]);
201
/* Skip two leading dashes */
202
if (arg[0] == '-' && arg[1] == '-')
205
return STREQ(arg, name[0])
206
|| (name[1] != NULL && STREQ(arg, name[1]));
209
/* Strict envopt matching */
211
ipset_match_envopt(const char *arg, const char * const name[])
214
assert(name && name[0]);
216
/* Skip one leading dash */
217
if (arg[0] == '-' && arg[1] == '-')
220
return STREQ(arg, name[0])
221
|| (name[1] != NULL && STREQ(arg, name[1]));
225
* ipset_shift_argv - shift off an argument
226
* @arc: argument count
227
* @argv: array of argument strings
228
* @from: from where shift off an argument
230
* Shift off the argument at "from" from the array of
231
* arguments argv of size argc.
234
ipset_shift_argv(int *argc, char *argv[], int from)
238
assert(*argc >= from + 1);
240
for (i = from + 1; i <= *argc; i++) {
248
* ipset_port_usage - prints the usage for the port parameter
250
* Print the usage for the port parameter to stdout.
253
ipset_port_usage(void)
258
printf(" [PROTO:]PORT is a valid pattern of the following:\n"
259
" PORTNAME port name from /etc/services\n"
260
" PORTNUMBER port number identifier\n"
261
" tcp|udp:PORTNAME|PORTNUMBER\n"
262
" icmp:CODENAME supported ICMP codename\n"
263
" icmp:TYPE/CODE ICMP type/code value\n"
264
" icmpv6:CODENAME supported ICMPv6 codename\n"
265
" icmpv6:TYPE/CODE ICMPv6 type/code value\n"
266
" PROTO:0 all other protocols\n\n");
268
printf(" Supported ICMP codenames:\n");
270
while ((name = id_to_icmp(i++)) != NULL)
271
printf(" %s\n", name);
272
printf(" Supported ICMPv6 codenames:\n");
274
while ((name = id_to_icmpv6(i++)) != NULL)
275
printf(" %s\n", name);