summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2013-05-14 19:49:13 +0200
committerPablo Neira Ayuso <pablo@netfilter.org>2013-05-19 21:42:36 +0200
commit99fc209e6a465ccb6ea96ef81116e8d931e2261c (patch)
tree7625c994bc04527af9099d06e84aed610801df5b /src
parent75b53c4a45518102ed8c1515fdf4b84a4293edf8 (diff)
cli: complete basic functionality of the interactive mode
This patch adds missing code to get basic interactive mode operative via `nft -i', including parsing, evaluation, command execution via netlink and error reporting. Autocomplete is not yet implemented. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'src')
-rw-r--r--src/cli.c12
-rw-r--r--src/main.c71
-rw-r--r--src/rule.c25
3 files changed, 66 insertions, 42 deletions
diff --git a/src/cli.c b/src/cli.c
index e302dfa8..a5a891e2 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -32,6 +32,7 @@
static const struct input_descriptor indesc_cli = {
.type = INDESC_CLI,
+ .name = "<cli>",
};
static struct parser_state *state;
@@ -86,6 +87,7 @@ static void cli_complete(char *line)
{
const HIST_ENTRY *hist;
const char *c;
+ LIST_HEAD(msgs);
line = cli_append_multiline(line);
if (line == NULL)
@@ -102,10 +104,10 @@ static void cli_complete(char *line)
if (hist == NULL || strcmp(hist->line, line))
add_history(line);
+ parser_init(state, &msgs);
scanner_push_buffer(scanner, &indesc_cli, line);
- nft_parse(scanner, state);
-
- erec_print_list(stdout, state->msgs);
+ nft_run(scanner, state, &msgs);
+ erec_print_list(stdout, &msgs);
xfree(line);
}
@@ -140,7 +142,7 @@ void __fmtstring(1, 0) cli_display(const char *fmt, va_list ap)
rl_forced_update_display();
}
-int cli_init(void *_scanner, struct parser_state *_state)
+int cli_init(struct parser_state *_state)
{
const char *home;
@@ -159,8 +161,8 @@ int cli_init(void *_scanner, struct parser_state *_state)
read_history(histfile);
history_set_pos(history_length);
- scanner = _scanner;
state = _state;
+ scanner = scanner_init(state);
while (!eof)
rl_callback_read_char();
diff --git a/src/main.c b/src/main.c
index ab2ceab9..283ec289 100644
--- a/src/main.c
+++ b/src/main.c
@@ -141,17 +141,48 @@ static const struct input_descriptor indesc_cmdline = {
.name = "<cmdline>",
};
+int nft_run(void *scanner, struct parser_state *state, struct list_head *msgs)
+{
+ struct eval_ctx ctx;
+ int ret;
+
+ ret = nft_parse(scanner, state);
+ if (ret != 0)
+ return -1;
+
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.msgs = msgs;
+ if (evaluate(&ctx, &state->cmds) < 0)
+ return -1;
+
+ {
+ struct netlink_ctx ctx;
+ struct cmd *cmd, *next;
+
+ list_for_each_entry_safe(cmd, next, &state->cmds, list) {
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.msgs = msgs;
+ init_list_head(&ctx.list);
+ ret = do_command(&ctx, cmd);
+ list_del(&cmd->list);
+ cmd_free(cmd);
+ if (ret < 0)
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
int main(int argc, char * const *argv)
{
struct parser_state state;
- struct eval_ctx ctx;
void *scanner;
LIST_HEAD(msgs);
char *buf = NULL, *filename = NULL;
unsigned int len;
bool interactive = false;
int i, val;
- int ret;
while (1) {
val = getopt_long(argc, argv, OPTSTRING, options, NULL);
@@ -218,9 +249,6 @@ int main(int argc, char * const *argv)
}
}
- parser_init(&state, &msgs);
- scanner = scanner_init(&state);
-
if (optind != argc) {
for (len = 0, i = optind; i < argc; i++)
len += strlen(argv[i]) + strlen(" ");
@@ -231,44 +259,25 @@ int main(int argc, char * const *argv)
if (i + 1 < argc)
strcat(buf, " ");
}
-
+ parser_init(&state, &msgs);
+ scanner = scanner_init(&state);
scanner_push_buffer(scanner, &indesc_cmdline, buf);
} else if (filename != NULL) {
+ parser_init(&state, &msgs);
+ scanner = scanner_init(&state);
if (scanner_read_file(scanner, filename, &internal_location) < 0)
goto out;
} else if (interactive) {
- cli_init(scanner, &state);
+ cli_init(&state);
+ return 0;
} else {
fprintf(stderr, "%s: no command specified\n", argv[0]);
exit(NFT_EXIT_FAILURE);
}
- ret = nft_parse(scanner, &state);
- if (ret != 0)
- goto out;
-
- memset(&ctx, 0, sizeof(ctx));
- ctx.msgs = &msgs;
- if (evaluate(&ctx, &state.cmds) < 0)
- goto out;
-
- {
- struct netlink_ctx ctx;
- struct cmd *cmd, *next;
-
- list_for_each_entry_safe(cmd, next, &state.cmds, list) {
- memset(&ctx, 0, sizeof(ctx));
- ctx.msgs = &msgs;
- init_list_head(&ctx.list);
- if (do_command(&ctx, cmd) < 0)
- goto out;
- list_del(&cmd->list);
- cmd_free(cmd);
- }
- }
+ nft_run(scanner, &state, &msgs);
out:
scanner_destroy(scanner);
- scope_release(&state.top_scope);
erec_print_list(stdout, &msgs);
xfree(buf);
diff --git a/src/rule.c b/src/rule.c
index 89c3607c..9d9eaee3 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -142,7 +142,6 @@ void rule_print(const struct rule *rule)
struct scope *scope_init(struct scope *scope, const struct scope *parent)
{
scope->parent = parent;
- init_list_head(&scope->symbols);
return scope;
}
@@ -189,6 +188,7 @@ struct chain *chain_alloc(const char *name)
chain = xzalloc(sizeof(*chain));
init_list_head(&chain->rules);
+ init_list_head(&chain->scope.symbols);
if (name != NULL)
chain->handle.chain = xstrdup(name);
return chain;
@@ -240,6 +240,7 @@ struct table *table_alloc(void)
table = xzalloc(sizeof(*table));
init_list_head(&table->chains);
init_list_head(&table->sets);
+ init_list_head(&table->scope.symbols);
return table;
}
@@ -472,14 +473,20 @@ static int do_list_sets(struct netlink_ctx *ctx, const struct location *loc,
static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
{
- struct table *table;
- struct chain *chain;
+ struct table *table = NULL;
+ struct chain *chain, *nchain;
struct rule *rule, *nrule;
struct set *set, *nset;
- table = table_alloc();
- handle_merge(&table->handle, &cmd->handle);
- table_add_hash(table);
+ /* No need to allocate the table object when listing all tables */
+ if (cmd->handle.table != NULL) {
+ table = table_lookup(&cmd->handle);
+ if (table == NULL) {
+ table = table_alloc();
+ handle_merge(&table->handle, &cmd->handle);
+ table_add_hash(table);
+ }
+ }
switch (cmd->obj) {
case CMD_OBJ_TABLE:
@@ -546,6 +553,12 @@ static int do_command_list(struct netlink_ctx *ctx, struct cmd *cmd)
}
table_print(table);
+
+ list_for_each_entry_safe(chain, nchain, &table->chains, list) {
+ list_del(&chain->list);
+ chain_free(chain);
+ }
+
return 0;
}