summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2018-10-18 17:27:49 +0200
committerJozsef Kadlecsik <kadlec@blackhole.kfki.hu>2018-10-18 17:27:49 +0200
commit55fdd96e331e920ee62bd816a572ac24f6dcd1ae (patch)
tree74e53ff7174e08b035b85f95977ff6919e315b01 /src
parenta27741493db0d824a51775e387cf3972a471f64e (diff)
Library reworked to support embedding ipset completely
The ipset library is rewritten/extended to support embedding ipset, so that sets can fully be managed without calling the ipset binary. The ipset binary relies completely on the new library. The libipset.3 manpage was written about the library functions and usage. Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/ipset.c889
2 files changed, 12 insertions, 879 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 810efb7..438fcec 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
include $(top_srcdir)/Make_global.am
sbin_PROGRAMS = ipset
-ipset_SOURCES = ipset.c ui.c
+ipset_SOURCES = ipset.c
ipset_LDADD = ../lib/libipset.la
if ENABLE_SETTYPE_MODULES
diff --git a/src/ipset.c b/src/ipset.c
index 14a351a..fcb2247 100644
--- a/src/ipset.c
+++ b/src/ipset.c
@@ -7,898 +7,31 @@
* published by the Free Software Foundation.
*/
#include <assert.h> /* assert */
-#include <ctype.h> /* isspace */
-#include <errno.h> /* errno */
-#include <stdarg.h> /* va_* */
-#include <stdbool.h> /* bool */
-#include <stdio.h> /* fprintf, fgets */
+#include <stdio.h> /* fprintf */
#include <stdlib.h> /* exit */
-#include <string.h> /* str* */
#include <config.h>
-
-#include <libipset/debug.h> /* D() */
-#include <libipset/data.h> /* enum ipset_data */
-#include <libipset/parse.h> /* ipset_parse_* */
-#include <libipset/session.h> /* ipset_session_* */
-#include <libipset/types.h> /* struct ipset_type */
-#include <libipset/ui.h> /* core options, commands */
-#include <libipset/utils.h> /* STREQ */
-
-static char program_name[] = PACKAGE;
-static char program_version[] = PACKAGE_VERSION;
-
-static struct ipset_session *session;
-static uint32_t restore_line;
-static bool interactive;
-static char cmdline[1024];
-static char *newargv[255];
-static int newargc;
-static FILE *fd = NULL;
-static const char *filename = NULL;
-
-enum exittype {
- NO_PROBLEM = 0,
- OTHER_PROBLEM,
- PARAMETER_PROBLEM,
- VERSION_PROBLEM,
- SESSION_PROBLEM,
-};
-
-static int __attribute__((format(printf, 2, 3)))
-exit_error(int status, const char *msg, ...)
-{
- bool quiet = !interactive &&
- session &&
- ipset_envopt_test(session, IPSET_ENV_QUIET);
-
- if (status && msg && !quiet) {
- va_list args;
-
- fprintf(stderr, "%s v%s: ", program_name, program_version);
- va_start(args, msg);
- vfprintf(stderr, msg, args);
- va_end(args);
- if (status != SESSION_PROBLEM)
- fprintf(stderr, "\n");
-
- if (status == PARAMETER_PROBLEM)
- fprintf(stderr,
- "Try `%s help' for more information.\n",
- program_name);
- }
- /* Ignore errors in interactive mode */
- if (status && interactive) {
- if (session)
- ipset_session_report_reset(session);
- return -1;
- }
-
- if (session)
- ipset_session_fini(session);
-
- D("status: %u", status);
- if (fd)
- fclose(fd);
- exit(status > VERSION_PROBLEM ? OTHER_PROBLEM : status);
- /* Unreached */
- return -1;
-}
-
-static int
-handle_error(void)
-{
- if (ipset_session_warning(session) &&
- !ipset_envopt_test(session, IPSET_ENV_QUIET))
- fprintf(stderr, "Warning: %s\n",
- ipset_session_warning(session));
- if (ipset_session_error(session))
- return exit_error(SESSION_PROBLEM, "%s",
- ipset_session_error(session));
-
- if (!interactive) {
- ipset_session_fini(session);
- if (fd)
- fclose(fd);
- exit(OTHER_PROBLEM);
- }
-
- ipset_session_report_reset(session);
- return -1;
-}
-
-static void
-help(void)
-{
- const struct ipset_commands *c;
- const struct ipset_envopts *opt = ipset_envopts;
-
- printf("%s v%s\n\n"
- "Usage: %s [options] COMMAND\n\nCommands:\n",
- program_name, program_version, program_name);
-
- for (c = ipset_commands; c->cmd; c++)
- printf("%s %s\n", c->name[0], c->help);
- printf("\nOptions:\n");
-
- while (opt->flag) {
- if (opt->help)
- printf("%s %s\n", opt->name[0], opt->help);
- opt++;
- }
-}
-
-int
-ipset_parse_file(struct ipset_session *s UNUSED,
- int opt UNUSED, const char *str)
-{
- if (filename != NULL)
- return exit_error(PARAMETER_PROBLEM,
- "-file option can be specified once");
- filename = str;
-
- return 0;
-}
-
-static
-int __attribute__ ((format (printf, 1, 2)))
-ipset_print_file(const char *fmt, ...)
-{
- int len;
- va_list args;
-
- assert(fd != NULL);
- va_start(args, fmt);
- len = vfprintf(fd, fmt, args);
- va_end(args);
-
- return len;
-}
-
-/* Build faked argv from parsed line */
-static void
-build_argv(char *buffer)
-{
- char *tmp, *arg;
- int i;
- bool quoted = false;
-
- /* Reset */
- for (i = 1; i < newargc; i++) {
- if (newargv[i])
- free(newargv[i]);
- newargv[i] = NULL;
- }
- newargc = 1;
-
- arg = calloc(strlen(buffer) + 1, sizeof(*buffer));
- for (tmp = buffer, i = 0; *tmp; tmp++) {
- if ((newargc + 1) == (int)(sizeof(newargv)/sizeof(char *))) {
- exit_error(PARAMETER_PROBLEM,
- "Line is too long to parse.");
- goto out;
- }
- switch (*tmp) {
- case '"':
- quoted = !quoted;
- if (*(tmp+1))
- continue;
- break;
- case ' ':
- case '\r':
- case '\n':
- case '\t':
- if (!quoted)
- break;
- arg[i++] = *tmp;
- continue;
- default:
- arg[i++] = *tmp;
- if (*(tmp+1))
- continue;
- break;
- }
- if (!*(tmp+1) && quoted) {
- exit_error(PARAMETER_PROBLEM, "Missing close quote!");
- goto out;
- }
- if (!*arg)
- continue;
- newargv[newargc] = calloc(strlen(arg) + 1, sizeof(*arg));
- ipset_strlcpy(newargv[newargc++], arg, strlen(arg) + 1);
- memset(arg, 0, strlen(arg) + 1);
- i = 0;
- }
-out:
- free(arg);
-}
-
-/* Main parser function, workhorse */
-int parse_commandline(int argc, char *argv[]);
-
-/*
- * Performs a restore from stdin
- */
-static int
-restore(char *argv0)
-{
- int ret = 0;
- char *c;
- FILE *rfd = stdin;
-
- /* Initialize newargv/newargc */
- newargc = 0;
- newargv[newargc] = calloc(strlen(argv0) + 1, sizeof(*argv0));
- ipset_strlcpy(newargv[newargc++], argv0, strlen(argv0) + 1);
- if (filename) {
- fd = fopen(filename, "r");
- if (!fd) {
- return exit_error(OTHER_PROBLEM,
- "Cannot open %s for reading: %s",
- filename, strerror(errno));
- }
- rfd = fd;
- }
-
- while (fgets(cmdline, sizeof(cmdline), rfd)) {
- restore_line++;
- c = cmdline;
- while (isspace(c[0]))
- c++;
- if (c[0] == '\0' || c[0] == '#')
- continue;
- else if (STREQ(c, "COMMIT\n") || STREQ(c, "COMMIT\r\n")) {
- ret = ipset_commit(session);
- if (ret < 0)
- handle_error();
- continue;
- }
- /* Build faked argv, argc */
- build_argv(c);
-
- /* Execute line */
- ret = parse_commandline(newargc, newargv);
- if (ret < 0)
- handle_error();
- }
- /* implicit "COMMIT" at EOF */
- ret = ipset_commit(session);
- if (ret < 0)
- handle_error();
-
- free(newargv[0]);
- return ret;
-}
-
-static bool do_parse(const struct ipset_arg *arg, bool family)
-{
- return !((family == true) ^ (arg->opt == IPSET_OPT_FAMILY));
-}
-
-static int
-call_parser(int *argc, char *argv[], const struct ipset_type *type,
- enum ipset_adt cmd, bool family)
-{
- const struct ipset_arg *arg;
- const char *optstr;
- const struct ipset_type *t = type;
- uint8_t revision = type->revision;
- int ret = 0, i = 1, j;
-
- /* Currently CREATE and ADT may have got additional arguments */
- if (type->cmd[cmd].args[0] == IPSET_ARG_NONE && *argc > 1)
- return exit_error(PARAMETER_PROBLEM, "Unknown argument: `%s'",
- argv[i]);
-
- while (*argc > i) {
- ret = -1;
- for (j = 0; type->cmd[cmd].args[j] != IPSET_ARG_NONE; j++) {
- arg = ipset_keyword(type->cmd[cmd].args[j]);
- D("argc: %u, %s vs %s", i, argv[i], arg->name[0]);
- if (!(ipset_match_option(argv[i], arg->name)))
- continue;
-
- optstr = argv[i];
- /* Matched option */
- D("match %s, argc %u, i %u, %s",
- arg->name[0], *argc, i + 1,
- do_parse(arg, family) ? "parse" : "skip");
- i++;
- ret = 0;
- switch (arg->has_arg) {
- case IPSET_MANDATORY_ARG:
- if (*argc - i < 1)
- return exit_error(PARAMETER_PROBLEM,
- "Missing mandatory argument "
- "of option `%s'",
- arg->name[0]);
- /* Fall through */
- case IPSET_OPTIONAL_ARG:
- if (*argc - i >= 1) {
- if (do_parse(arg, family)) {
- ret = ipset_call_parser(
- session, arg, argv[i]);
- if (ret < 0)
- return ret;
- }
- i++;
- break;
- }
- /* Fall through */
- default:
- if (do_parse(arg, family)) {
- ret = ipset_call_parser(
- session, arg, optstr);
- if (ret < 0)
- return ret;
- }
- }
- break;
- }
- if (ret < 0)
- goto err_unknown;
- }
- if (!family)
- *argc = 0;
- return ret;
-
-err_unknown:
- while ((type = ipset_type_higher_rev(t)) != t) {
- for (j = 0; type->cmd[cmd].args[j] != IPSET_ARG_NONE; j++) {
- arg = ipset_keyword(type->cmd[cmd].args[j]);
- D("argc: %u, %s vs %s", i, argv[i], arg->name[0]);
- if (ipset_match_option(argv[i], arg->name))
- return exit_error(PARAMETER_PROBLEM,
- "Argument `%s' is supported in the kernel module "
- "of the set type %s starting from the revision %u "
- "and you have installed revision %u only. "
- "Your kernel is behind your ipset utility.",
- argv[i], type->name,
- type->revision, revision);
- }
- t = type;
- }
- return exit_error(PARAMETER_PROBLEM, "Unknown argument: `%s'", argv[i]);
-}
-
-static enum ipset_adt
-cmd2cmd(int cmd)
-{
- switch (cmd) {
- case IPSET_CMD_ADD:
- return IPSET_ADD;
- case IPSET_CMD_DEL:
- return IPSET_DEL;
- case IPSET_CMD_TEST:
- return IPSET_TEST;
- case IPSET_CMD_CREATE:
- return IPSET_CREATE;
- default:
- return 0;
- }
-}
-
-static void
-check_mandatory(const struct ipset_type *type, enum ipset_cmd command)
-{
- enum ipset_adt cmd = cmd2cmd(command);
- uint64_t flags = ipset_data_flags(ipset_session_data(session));
- uint64_t mandatory = type->cmd[cmd].need;
- const struct ipset_arg *arg;
- int i;
-
- /* Range can be expressed by ip/cidr */
- if (flags & IPSET_FLAG(IPSET_OPT_CIDR))
- flags |= IPSET_FLAG(IPSET_OPT_IP_TO);
-
- mandatory &= ~flags;
- if (!mandatory)
- return;
- if (type->cmd[cmd].args[0] == IPSET_ARG_NONE) {
- exit_error(OTHER_PROBLEM,
- "There are missing mandatory flags "
- "but can't check them. "
- "It's a bug, please report the problem.");
- return;
- }
-
- for (i = 0; type->cmd[cmd].args[i] != IPSET_ARG_NONE; i++) {
- arg = ipset_keyword(type->cmd[cmd].args[i]);
- if (mandatory & IPSET_FLAG(arg->opt)) {
- exit_error(PARAMETER_PROBLEM,
- "Mandatory option `%s' is missing",
- arg->name[0]);
- return;
- }
- }
-}
-
-static const char *
-cmd2name(enum ipset_cmd cmd)
-{
- const struct ipset_commands *c;
-
- for (c = ipset_commands; c->cmd; c++)
- if (cmd == c->cmd)
- return c->name[0];
- return "unknown command";
-}
-
-static const char *
-session_family(void)
-{
- switch (ipset_data_family(ipset_session_data(session))) {
- case NFPROTO_IPV4:
- return "inet";
- case NFPROTO_IPV6:
- return "inet6";
- default:
- return "unspec";
- }
-}
-
-static void
-check_allowed(const struct ipset_type *type, enum ipset_cmd command)
-{
- uint64_t flags = ipset_data_flags(ipset_session_data(session));
- enum ipset_adt cmd = cmd2cmd(command);
- uint64_t allowed = type->cmd[cmd].full;
- uint64_t cmdflags = command == IPSET_CMD_CREATE
- ? IPSET_CREATE_FLAGS : IPSET_ADT_FLAGS;
- const struct ipset_arg *arg;
- enum ipset_opt i;
- int j;
-
- /* Range can be expressed by ip/cidr or from-to */
- if (allowed & IPSET_FLAG(IPSET_OPT_IP_TO))
- allowed |= IPSET_FLAG(IPSET_OPT_CIDR);
-
- for (i = IPSET_OPT_IP; i < IPSET_OPT_FLAGS; i++) {
- if (!(cmdflags & IPSET_FLAG(i)) ||
- (allowed & IPSET_FLAG(i)) ||
- !(flags & IPSET_FLAG(i)))
- continue;
- /* Not allowed element-expressions */
- switch (i) {
- case IPSET_OPT_CIDR:
- exit_error(OTHER_PROBLEM,
- "IP/CIDR range is not allowed in command %s "
- "with set type %s and family %s",
- cmd2name(command), type->name,
- session_family());
- return;
- case IPSET_OPT_IP_TO:
- exit_error(OTHER_PROBLEM,
- "FROM-TO IP range is not allowed in command %s "
- "with set type %s and family %s",
- cmd2name(command), type->name,
- session_family());
- return;
- case IPSET_OPT_PORT_TO:
- exit_error(OTHER_PROBLEM,
- "FROM-TO port range is not allowed in command %s "
- "with set type %s and family %s",
- cmd2name(command), type->name,
- session_family());
- return;
- default:
- break;
- }
- /* Other options */
- if (type->cmd[cmd].args[0] == IPSET_ARG_NONE) {
- exit_error(OTHER_PROBLEM,
- "There are not allowed options (%u) "
- "but option list is empty. "
- "It's a bug, please report the problem.", i);
- return;
- }
- for (j = 0; type->cmd[cmd].args[j] != IPSET_ARG_NONE; j++) {
- arg = ipset_keyword(type->cmd[cmd].args[j]);
- if (arg->opt != i)
- continue;
- exit_error(OTHER_PROBLEM,
- "%s parameter is not allowed in command %s "
- "with set type %s and family %s",
- arg->name[0],
- cmd2name(command), type->name,
- session_family());
- return;
- }
- exit_error(OTHER_PROBLEM,
- "There are not allowed options (%u) "
- "but can't resolve them. "
- "It's a bug, please report the problem.", i);
- return;
- }
-}
-
-static const struct ipset_type *
-type_find(const char *name)
-{
- const struct ipset_type *t = ipset_types();
-
- while (t) {
- if (ipset_match_typename(name, t))
- return t;
- t = t->next;
- }
- return NULL;
-}
-
-static enum ipset_adt cmd_help_order[] = {
- IPSET_CREATE,
- IPSET_ADD,
- IPSET_DEL,
- IPSET_TEST,
- IPSET_CADT_MAX,
-};
-
-static const char *cmd_prefix[] = {
- [IPSET_CREATE] = "create SETNAME",
- [IPSET_ADD] = "add SETNAME",
- [IPSET_DEL] = "del SETNAME",
- [IPSET_TEST] = "test SETNAME",
-};
-
-/* Workhorse */
-int
-parse_commandline(int argc, char *argv[])
-{
- int ret = 0;
- enum ipset_cmd cmd = IPSET_CMD_NONE;
- int i;
- char *arg0 = NULL, *arg1 = NULL, *c;
- const struct ipset_envopts *opt;
- const struct ipset_commands *command;
- const struct ipset_type *type;
-
- /* Set session lineno to report parser errors correctly */
- ipset_session_lineno(session, restore_line);
-
- /* Commandline parsing, somewhat similar to that of 'ip' */
-
- /* First: parse core options */
- for (opt = ipset_envopts; opt->flag; opt++) {
- for (i = 1; i < argc; ) {
- if (!ipset_match_envopt(argv[i], opt->name)) {
- i++;
- continue;
- }
- /* Shift off matched option */
- ipset_shift_argv(&argc, argv, i);
- switch (opt->has_arg) {
- case IPSET_MANDATORY_ARG:
- if (i + 1 > argc)
- return exit_error(PARAMETER_PROBLEM,
- "Missing mandatory argument "
- "to option %s",
- opt->name[0]);
- /* Fall through */
- case IPSET_OPTIONAL_ARG:
- if (i + 1 <= argc) {
- ret = opt->parse(session, opt->flag,
- argv[i]);
- if (ret < 0)
- return handle_error();
- ipset_shift_argv(&argc, argv, i);
- }
- break;
- case IPSET_NO_ARG:
- ret = opt->parse(session, opt->flag,
- opt->name[0]);
- if (ret < 0)
- return handle_error();
- break;
- default:
- break;
- }
- }
- }
-
- /* Second: parse command */
- for (command = ipset_commands;
- argc > 1 && command->cmd && cmd == IPSET_CMD_NONE;
- command++) {
- if (!ipset_match_cmd(argv[1], command->name))
- continue;
-
- if (restore_line != 0 &&
- (command->cmd == IPSET_CMD_RESTORE ||
- command->cmd == IPSET_CMD_VERSION ||
- command->cmd == IPSET_CMD_HELP))
- return exit_error(PARAMETER_PROBLEM,
- "Command `%s' is invalid "
- "in restore mode.",
- command->name[0]);
- if (interactive && command->cmd == IPSET_CMD_RESTORE) {
- printf("Restore command ignored "
- "in interactive mode\n");
- return 0;
- }
-
- /* Shift off matched command arg */
- ipset_shift_argv(&argc, argv, 1);
- cmd = command->cmd;
- switch (command->has_arg) {
- case IPSET_MANDATORY_ARG:
- case IPSET_MANDATORY_ARG2:
- if (argc < 2)
- return exit_error(PARAMETER_PROBLEM,
- "Missing mandatory argument "
- "to command %s",
- command->name[0]);
- /* Fall through */
- case IPSET_OPTIONAL_ARG:
- arg0 = argv[1];
- if (argc >= 2)
- /* Shift off first arg */
- ipset_shift_argv(&argc, argv, 1);
- break;
- default:
- break;
- }
- if (command->has_arg == IPSET_MANDATORY_ARG2) {
- if (argc < 2)
- return exit_error(PARAMETER_PROBLEM,
- "Missing second mandatory "
- "argument to command %s",
- command->name[0]);
- arg1 = argv[1];
- /* Shift off second arg */
- ipset_shift_argv(&argc, argv, 1);
- }
- break;
- }
-
- /* Third: catch interactive mode, handle help, version */
- switch (cmd) {
- case IPSET_CMD_NONE:
- if (interactive) {
- printf("No command specified\n");
- if (session)
- ipset_envopt_parse(session, 0, "reset");
- return 0;
- }
- if (argc > 1 && STREQ(argv[1], "-")) {
- interactive = true;
- printf("%s> ", program_name);
- /* Initialize newargv/newargc */
- newargv[newargc++] = program_name;
- while (fgets(cmdline, sizeof(cmdline), stdin)) {
- c = cmdline;
- while (isspace(c[0]))
- c++;
- if (c[0] == '\0' || c[0] == '#') {
- printf("%s> ", program_name);
- continue;
- }
- /* Build fake argv, argc */
- build_argv(c);
- /* Execute line: ignore soft errors */
- if (parse_commandline(newargc, newargv) < 0)
- handle_error();
- printf("%s> ", program_name);
- }
- return exit_error(NO_PROBLEM, NULL);
- }
- if (argc > 1)
- return exit_error(PARAMETER_PROBLEM,
- "No command specified: unknown argument %s",
- argv[1]);
- return exit_error(PARAMETER_PROBLEM, "No command specified.");
- case IPSET_CMD_VERSION:
- printf("%s v%s, protocol version: %u\n",
- program_name, program_version, IPSET_PROTOCOL);
- if (interactive)
- return 0;
- return exit_error(NO_PROBLEM, NULL);
- case IPSET_CMD_HELP:
- help();
-
- if (interactive ||
- !ipset_envopt_test(session, IPSET_ENV_QUIET)) {
- if (arg0) {
- const struct ipset_arg *arg;
- int k;
-
- /* Type-specific help, without kernel checking */
- type = type_find(arg0);
- if (!type)
- return exit_error(PARAMETER_PROBLEM,
- "Unknown settype: `%s'", arg0);
- printf("\n%s type specific options:\n\n", type->name);
- for (i = 0; cmd_help_order[i] != IPSET_CADT_MAX; i++) {
- cmd = cmd_help_order[i];
- printf("%s %s %s\n",
- cmd_prefix[cmd], type->name, type->cmd[cmd].help);
- for (k = 0; type->cmd[cmd].args[k] != IPSET_ARG_NONE; k++) {
- arg = ipset_keyword(type->cmd[cmd].args[k]);
- if (!arg->help || arg->help[0] == '\0')
- continue;
- printf(" %s\n", arg->help);
- }
- }
- printf("\n%s\n", type->usage);
- if (type->usagefn)
- type->usagefn();
- if (type->family == NFPROTO_UNSPEC)
- printf("\nType %s is family neutral.\n",
- type->name);
- else if (type->family == NFPROTO_IPSET_IPV46)
- printf("\nType %s supports inet "
- "and inet6.\n",
- type->name);
- else
- printf("\nType %s supports family "
- "%s only.\n",
- type->name,
- type->family == NFPROTO_IPV4
- ? "inet" : "inet6");
- } else {
- printf("\nSupported set types:\n");
- type = ipset_types();
- while (type) {
- printf(" %s\t%s%u\t%s\n",
- type->name,
- strlen(type->name) < 12 ? "\t" : "",
- type->revision,
- type->description);
- type = type->next;
- }
- }
- }
- if (interactive)
- return 0;
- return exit_error(NO_PROBLEM, NULL);
- case IPSET_CMD_QUIT:
- return exit_error(NO_PROBLEM, NULL);
- default:
- break;
- }
-
- /* Forth: parse command args and issue the command */
- switch (cmd) {
- case IPSET_CMD_CREATE:
- /* Args: setname typename [type specific options] */
- ret = ipset_parse_setname(session, IPSET_SETNAME, arg0);
- if (ret < 0)
- return handle_error();
-
- ret = ipset_parse_typename(session, IPSET_OPT_TYPENAME, arg1);
- if (ret < 0)
- return handle_error();
-
- type = ipset_type_get(session, cmd);
- if (type == NULL)
- return handle_error();
-
- /* Parse create options: first check INET family */
- ret = call_parser(&argc, argv, type, IPSET_CREATE, true);
- if (ret < 0)
- return handle_error();
- else if (ret)
- return ret;
-
- /* Parse create options: then check all options */
- ret = call_parser(&argc, argv, type, IPSET_CREATE, false);
- if (ret < 0)
- return handle_error();
- else if (ret)
- return ret;
-
- /* Check mandatory, then allowed options */
- check_mandatory(type, cmd);
- check_allowed(type, cmd);
-
- break;
- case IPSET_CMD_LIST:
- case IPSET_CMD_SAVE:
- if (filename != NULL) {
- fd = fopen(filename, "w");
- if (!fd)
- return exit_error(OTHER_PROBLEM,
- "Cannot open %s for writing: "
- "%s", filename,
- strerror(errno));
- ipset_session_outfn(session, ipset_print_file);
- }
- case IPSET_CMD_DESTROY:
- case IPSET_CMD_FLUSH:
- /* Args: [setname] */
- if (arg0) {
- ret = ipset_parse_setname(session,
- IPSET_SETNAME, arg0);
- if (ret < 0)
- return handle_error();
- }
- break;
-
- case IPSET_CMD_RENAME:
- case IPSET_CMD_SWAP:
- /* Args: from-setname to-setname */
- ret = ipset_parse_setname(session, IPSET_SETNAME, arg0);
- if (ret < 0)
- return handle_error();
- ret = ipset_parse_setname(session, IPSET_OPT_SETNAME2, arg1);
- if (ret < 0)
- return handle_error();
- break;
-
- case IPSET_CMD_RESTORE:
- /* Restore mode */
- if (argc > 1)
- return exit_error(PARAMETER_PROBLEM,
- "Unknown argument %s", argv[1]);
- return restore(argv[0]);
- case IPSET_CMD_ADD:
- case IPSET_CMD_DEL:
- case IPSET_CMD_TEST:
- D("ADT: setname %s", arg0);
- /* Args: setname ip [options] */
- ret = ipset_parse_setname(session, IPSET_SETNAME, arg0);
- if (ret < 0)
- return handle_error();
-
- type = ipset_type_get(session, cmd);
- if (type == NULL)
- return handle_error();
-
- ret = ipset_parse_elem(session, type->last_elem_optional, arg1);
- if (ret < 0)
- return handle_error();
-
- /* Parse additional ADT options */
- ret = call_parser(&argc, argv, type, cmd2cmd(cmd), false);
- if (ret < 0)
- return handle_error();
- else if (ret)
- return ret;
-
- /* Check mandatory, then allowed options */
- check_mandatory(type, cmd);
- check_allowed(type, cmd);
-
- break;
- default:
- break;
- }
-
- if (argc > 1)
- return exit_error(PARAMETER_PROBLEM,
- "Unknown argument %s", argv[1]);
- ret = ipset_cmd(session, cmd, restore_line);
- D("ret %d", ret);
- /* Special case for TEST and non-quiet mode */
- if (cmd == IPSET_CMD_TEST && ipset_session_warning(session)) {
- if (!ipset_envopt_test(session, IPSET_ENV_QUIET))
- fprintf(stderr, "%s", ipset_session_warning(session));
- ipset_session_report_reset(session);
- }
- if (ret < 0)
- handle_error();
-
- return ret;
-}
+#include <libipset/ipset.h> /* ipset library */
int
main(int argc, char *argv[])
{
+ struct ipset *ipset;
int ret;
/* Load set types */
ipset_load_types();
- /* Initialize session */
- session = ipset_session_init(printf);
- if (session == NULL)
- return exit_error(OTHER_PROBLEM,
- "Cannot initialize ipset session, aborting.");
+ /* Initialize ipset library */
+ ipset = ipset_init();
+ if (ipset == NULL) {
+ fprintf(stderr, "Cannot initialize ipset, aborting.");
+ exit(1);
+ }
- ret = parse_commandline(argc, argv);
+ ret = ipset_parse_argv(ipset, argc, argv);
- ipset_session_fini(session);
- if (fd)
- fclose(fd);
+ ipset_fini(ipset);
return ret;
}