* [nft PATCH 0/16] introduce libnftables
@ 2017-08-16 20:42 Eric Leblond
2017-08-16 20:42 ` [nft PATH 01/16] libnftables: introduce library Eric Leblond
` (16 more replies)
0 siblings, 17 replies; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:42 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel
Hello,
This patchset adds a basi high level libnftables to nftables code.
It is currently supporting running a command from a buffer or from
a file as well as batch support allowing to chain commands and commit
them at once.
The API is mostly using existing structures such as nft_ctx that are
updated to contain enough information. It also adds a structure
dedicated to batch.
A simple program running a command is the following:
nft_global_init();
nft = nft_context_new();
nft_context_set_print_func(nft, my_print, buf);
rc = nft_run_command_from_buffer(nft, CMD, sizeof(CMD));
if (rc != NFT_EXIT_SUCCESS) {
nft_get_error(nft, err_buf, sizeof(err_buf));
printf("%s\n", err_buf);
return -1;
}
nft_context_free(nft);
nft_global_deinit();
Transaction support is similar with:
nft = nft_context_new();
batch = nft_batch_start(nft);
if (nft_batch_add(nft, batch, ADD1, strlen(ADD1)) !=0) {
printf("FAIL add 1\n");
goto out;
}
if (nft_batch_add(nft, batch, ADD2, strlen(ADD2)) !=0) {
printf("FAIL add 2\n");
goto out;
}
if (nft_batch_commit(nft, batch) != 0) {
goto out;
}
out:
nft_batch_free(batch);
nft_context_free(nft);
nft_global_deinit();
The library provides a way to get standard output via nft_context_set_print_func
and error handling is done via nft_get_error that get error message in a buffer.
This is early stage code as it does not feature things like set handling but IMO
it can already be used as a starting point to build more things.
BR,
--
Eric
^ permalink raw reply [flat|nested] 37+ messages in thread
* [nft PATH 01/16] libnftables: introduce library
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
@ 2017-08-16 20:42 ` Eric Leblond
2017-08-17 8:57 ` Phil Sutter
2017-08-16 20:42 ` [nft PATH 02/16] libnftables: add context new and free Eric Leblond
` (15 subsequent siblings)
16 siblings, 1 reply; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:42 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
Add global init and deinit functions.
Signed-off-by: Eric Leblond <eric@regit.org>
---
configure.ac | 4 ++++
include/Makefile.am | 2 +-
include/nftables/Makefile.am | 2 ++
include/nftables/nftables.h | 20 +++++++++++++++++
src/Makefile.am | 26 +++++++++++++---------
src/libnftables.c | 53 ++++++++++++++++++++++++++++++++++++++++++++
src/main.c | 27 +++-------------------
7 files changed, 99 insertions(+), 35 deletions(-)
create mode 100644 include/nftables/Makefile.am
create mode 100644 include/nftables/nftables.h
create mode 100644 src/libnftables.c
diff --git a/configure.ac b/configure.ac
index bef6c0b..91273ce 100644
--- a/configure.ac
+++ b/configure.ac
@@ -56,6 +56,9 @@ then
exit 1
fi
+AM_PROG_AR
+AM_PROG_LIBTOOL
+
AC_CHECK_PROG(DOCBOOK2X_MAN, [docbook2x-man], [docbook2x-man], [no])
AC_CHECK_PROG(DOCBOOK2MAN, [docbook2man], [docbook2man], [no])
AC_CHECK_PROG(DB2X_DOCBOOK2MAN, [db2x_docbook2man], [db2x_docbook2man], [no])
@@ -146,6 +149,7 @@ AC_CONFIG_FILES([ \
include/linux/netfilter_bridge/Makefile \
include/linux/netfilter_ipv4/Makefile \
include/linux/netfilter_ipv6/Makefile \
+ include/nftables/Makefile \
doc/Makefile \
files/Makefile \
files/nftables/Makefile \
diff --git a/include/Makefile.am b/include/Makefile.am
index 5dd73d8..caa6961 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = linux
+SUBDIRS = linux nftables
noinst_HEADERS = cli.h \
datatype.h \
diff --git a/include/nftables/Makefile.am b/include/nftables/Makefile.am
new file mode 100644
index 0000000..a14b188
--- /dev/null
+++ b/include/nftables/Makefile.am
@@ -0,0 +1,2 @@
+pkginclude_HEADERS = nftables.h
+
diff --git a/include/nftables/nftables.h b/include/nftables/nftables.h
new file mode 100644
index 0000000..4ba16f0
--- /dev/null
+++ b/include/nftables/nftables.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2017 Eric Leblond <eric@regit.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef LIB_NFTABLES_H
+#define LIB_NFTABLES_H
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+void nft_global_init(void);
+void nft_global_deinit(void);
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 99eef7b..a340d39 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -27,8 +27,9 @@ parser_bison.o scanner.o: AM_CFLAGS += -Wno-missing-prototypes -Wno-missing-decl
BUILT_SOURCES = parser_bison.h
-nft_SOURCES = main.c \
- rule.c \
+lib_LTLIBRARIES = libnftables.la
+
+libnftables_la_SOURCES = rule.c \
statement.c \
datatype.c \
expression.c \
@@ -54,23 +55,28 @@ nft_SOURCES = main.c \
iface.c \
services.c \
mergesort.c \
+ libnftables.c \
scanner.l \
tcpopt.c \
parser_bison.y
-if BUILD_CLI
-nft_SOURCES += cli.c
-endif
-
if BUILD_MINIGMP
mini-gmp.o: AM_CFLAGS += -Wno-sign-compare
-nft_SOURCES += mini-gmp.c
+libnftables_la_SOURCES += mini-gmp.c
endif
-nft_LDADD = ${LIBMNL_LIBS} ${LIBNFTNL_LIBS}
+nft_SOURCES = main.c
+
+if BUILD_CLI
+nft_SOURCES += cli.c
+endif
+
+libnftables_la_LIBADD = ${LIBMNL_LIBS} ${LIBNFTNL_LIBS}
if BUILD_XTABLES
-nft_SOURCES += xt.c
-nft_LDADD += ${XTABLES_LIBS}
+libnftables_la_SOURCES += xt.c
+libnftables_la_LIBADD += ${XTABLES_LIBS}
endif
+
+nft_LDADD = libnftables.la
diff --git a/src/libnftables.c b/src/libnftables.c
new file mode 100644
index 0000000..215179a
--- /dev/null
+++ b/src/libnftables.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017 Eric Leblond <eric@regit.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <nftables/nftables.h>
+#include <string.h>
+#include <errno.h>
+#include <nftables.h>
+#include <parser.h>
+#include <iface.h>
+#include <netlink.h>
+#include <erec.h>
+#include <libmnl/libmnl.h>
+#include <mnl.h>
+
+#include <unistd.h>
+#include <fcntl.h>
+
+
+unsigned int max_errors = 10;
+unsigned int numeric_output;
+unsigned int ip2name_output;
+unsigned int handle_output;
+#ifdef DEBUG
+unsigned int debug_level;
+#endif
+
+void nft_global_init(void)
+{
+ mark_table_init();
+ realm_table_rt_init();
+ devgroup_table_init();
+ realm_table_meta_init();
+ ct_label_table_init();
+ gmp_init();
+#ifdef HAVE_LIBXTABLES
+ xt_init();
+#endif
+}
+
+void nft_global_deinit(void)
+{
+ ct_label_table_exit();
+ realm_table_rt_exit();
+ devgroup_table_exit();
+ realm_table_meta_exit();
+ mark_table_exit();
+}
diff --git a/src/main.c b/src/main.c
index 8883959..dde3104 100644
--- a/src/main.c
+++ b/src/main.c
@@ -18,6 +18,7 @@
#include <fcntl.h>
#include <sys/types.h>
+#include <nftables/nftables.h>
#include <nftables.h>
#include <utils.h>
#include <parser.h>
@@ -272,28 +273,6 @@ err1:
return ret;
}
-void nft_init(void)
-{
- mark_table_init();
- realm_table_rt_init();
- devgroup_table_init();
- realm_table_meta_init();
- ct_label_table_init();
- gmp_init();
-#ifdef HAVE_LIBXTABLES
- xt_init();
-#endif
-}
-
-void nft_exit(void)
-{
- ct_label_table_exit();
- realm_table_rt_exit();
- devgroup_table_exit();
- realm_table_meta_exit();
- mark_table_exit();
-}
-
int main(int argc, char * const *argv)
{
struct parser_state state;
@@ -309,7 +288,7 @@ int main(int argc, char * const *argv)
memset(&cache, 0, sizeof(cache));
init_list_head(&cache.list);
- nft_init();
+ nft_global_init();
nf_sock = netlink_open_sock();
while (1) {
val = getopt_long(argc, argv, OPTSTRING, options, NULL);
@@ -440,7 +419,7 @@ out:
cache_release(&cache);
iface_cache_release();
netlink_close_sock(nf_sock);
- nft_exit();
+ nft_global_deinit();
return rc;
}
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 02/16] libnftables: add context new and free
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
2017-08-16 20:42 ` [nft PATH 01/16] libnftables: introduce library Eric Leblond
@ 2017-08-16 20:42 ` Eric Leblond
2017-08-17 9:04 ` Phil Sutter
2017-08-16 20:42 ` [nft PATH 03/16] libnftables: add nft_run_command_from_buffer Eric Leblond
` (14 subsequent siblings)
16 siblings, 1 reply; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:42 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/nftables.h | 1 +
include/nftables/nftables.h | 3 +++
src/libnftables.c | 20 ++++++++++++++++++++
src/main.c | 27 +++++++++++++--------------
4 files changed, 37 insertions(+), 14 deletions(-)
diff --git a/include/nftables.h b/include/nftables.h
index a457aba..717af37 100644
--- a/include/nftables.h
+++ b/include/nftables.h
@@ -35,6 +35,7 @@ struct output_ctx {
struct nft_ctx {
struct output_ctx output;
bool check;
+ struct mnl_socket *nf_sock;
};
struct nft_cache {
diff --git a/include/nftables/nftables.h b/include/nftables/nftables.h
index 4ba16f0..cfa60fe 100644
--- a/include/nftables/nftables.h
+++ b/include/nftables/nftables.h
@@ -17,4 +17,7 @@
void nft_global_init(void);
void nft_global_deinit(void);
+struct nft_ctx *nft_context_new(void);
+void nft_context_free(struct nft_ctx *nft);
+
#endif
diff --git a/src/libnftables.c b/src/libnftables.c
index 215179a..da1b231 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -51,3 +51,23 @@ void nft_global_deinit(void)
realm_table_meta_exit();
mark_table_exit();
}
+
+struct nft_ctx *nft_context_new(void)
+{
+ struct nft_ctx *ctx = NULL;
+ ctx = malloc(sizeof(struct nft_ctx));
+ if (ctx == NULL)
+ return NULL;
+ ctx->nf_sock = netlink_open_sock();
+
+ return ctx;
+}
+
+
+void nft_context_free(struct nft_ctx *nft)
+{
+ if (nft == NULL)
+ return;
+ netlink_close_sock(nft->nf_sock);
+ xfree(nft);
+}
diff --git a/src/main.c b/src/main.c
index dde3104..23af38e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -29,7 +29,6 @@
#include <iface.h>
#include <cli.h>
-static struct nft_ctx nft;
unsigned int max_errors = 10;
#ifdef DEBUG
unsigned int debug_level;
@@ -283,13 +282,13 @@ int main(int argc, char * const *argv)
unsigned int len;
bool interactive = false;
int i, val, rc = NFT_EXIT_SUCCESS;
- struct mnl_socket *nf_sock;
+ struct nft_ctx *nft;
memset(&cache, 0, sizeof(cache));
init_list_head(&cache.list);
nft_global_init();
- nf_sock = netlink_open_sock();
+ nft = nft_context_new();
while (1) {
val = getopt_long(argc, argv, OPTSTRING, options, NULL);
if (val == -1)
@@ -304,7 +303,7 @@ int main(int argc, char * const *argv)
PACKAGE_NAME, PACKAGE_VERSION, RELEASE_NAME);
exit(NFT_EXIT_SUCCESS);
case OPT_CHECK:
- nft.check = true;
+ nft->check = true;
break;
case OPT_FILE:
filename = optarg;
@@ -322,7 +321,7 @@ int main(int argc, char * const *argv)
include_paths[num_include_paths++] = optarg;
break;
case OPT_NUMERIC:
- if (++nft.output.numeric > NUMERIC_ALL) {
+ if (++nft->output.numeric > NUMERIC_ALL) {
fprintf(stderr, "Too many numeric options "
"used, max. %u\n",
NUMERIC_ALL);
@@ -330,10 +329,10 @@ int main(int argc, char * const *argv)
}
break;
case OPT_STATELESS:
- nft.output.stateless++;
+ nft->output.stateless++;
break;
case OPT_IP2NAME:
- nft.output.ip2name++;
+ nft->output.ip2name++;
break;
#ifdef DEBUG
case OPT_DEBUG:
@@ -365,7 +364,7 @@ int main(int argc, char * const *argv)
break;
#endif
case OPT_HANDLE_OUTPUT:
- nft.output.handle++;
+ nft->output.handle++;
break;
case OPT_ECHO:
nft.output.echo++;
@@ -386,20 +385,20 @@ int main(int argc, char * const *argv)
strcat(buf, " ");
}
strcat(buf, "\n");
- parser_init(nf_sock, &cache, &state, &msgs);
+ parser_init(nft->nf_sock, &cache, &state, &msgs);
scanner = scanner_init(&state);
scanner_push_buffer(scanner, &indesc_cmdline, buf);
} else if (filename != NULL) {
- rc = cache_update(nf_sock, &cache, CMD_INVALID, &msgs);
+ rc = cache_update(nft->nf_sock, &cache, CMD_INVALID, &msgs);
if (rc < 0)
return rc;
- parser_init(nf_sock, &cache, &state, &msgs);
+ parser_init(nft->nf_sock, &cache, &state, &msgs);
scanner = scanner_init(&state);
if (scanner_read_file(scanner, filename, &internal_location) < 0)
goto out;
} else if (interactive) {
- if (cli_init(&nft, nf_sock, &cache, &state) < 0) {
+ if (cli_init(nft, nft->nf_sock, &cache, &state) < 0) {
fprintf(stderr, "%s: interactive CLI not supported in this build\n",
argv[0]);
exit(NFT_EXIT_FAILURE);
@@ -410,7 +409,7 @@ int main(int argc, char * const *argv)
exit(NFT_EXIT_FAILURE);
}
- if (nft_run(&nft, nf_sock, &cache, scanner, &state, &msgs) != 0)
+ if (nft_run(nft, nft->nf_sock, &cache, scanner, &state, &msgs) != 0)
rc = NFT_EXIT_FAILURE;
out:
scanner_destroy(scanner);
@@ -418,7 +417,7 @@ out:
xfree(buf);
cache_release(&cache);
iface_cache_release();
- netlink_close_sock(nf_sock);
+ nft_context_free(nft);
nft_global_deinit();
return rc;
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 03/16] libnftables: add nft_run_command_from_buffer
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
2017-08-16 20:42 ` [nft PATH 01/16] libnftables: introduce library Eric Leblond
2017-08-16 20:42 ` [nft PATH 02/16] libnftables: add context new and free Eric Leblond
@ 2017-08-16 20:42 ` Eric Leblond
2017-08-17 9:21 ` Phil Sutter
2017-08-16 20:42 ` [nft PATH 04/16] libnftables: add nft_run_command_from_filename Eric Leblond
` (13 subsequent siblings)
16 siblings, 1 reply; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:42 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/nftables/nftables.h | 3 +++
src/libnftables.c | 26 +++++++++++++++++++++++++-
src/main.c | 21 +++++++++------------
3 files changed, 37 insertions(+), 13 deletions(-)
diff --git a/include/nftables/nftables.h b/include/nftables/nftables.h
index cfa60fe..63150ba 100644
--- a/include/nftables/nftables.h
+++ b/include/nftables/nftables.h
@@ -20,4 +20,7 @@ void nft_global_deinit(void);
struct nft_ctx *nft_context_new(void);
void nft_context_free(struct nft_ctx *nft);
+int nft_run_command_from_buffer(struct nft_ctx *nft, struct nft_cache *cache,
+ char *buf, size_t buflen);
+
#endif
diff --git a/src/libnftables.c b/src/libnftables.c
index da1b231..9248741 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -7,7 +7,6 @@
*
*/
-#include <nftables/nftables.h>
#include <string.h>
#include <errno.h>
#include <nftables.h>
@@ -18,6 +17,8 @@
#include <libmnl/libmnl.h>
#include <mnl.h>
+#include <nftables/nftables.h>
+
#include <unistd.h>
#include <fcntl.h>
@@ -71,3 +72,26 @@ void nft_context_free(struct nft_ctx *nft)
netlink_close_sock(nft->nf_sock);
xfree(nft);
}
+
+static const struct input_descriptor indesc_cmdline = {
+ .type = INDESC_BUFFER,
+ .name = "<cmdline>",
+};
+
+int nft_run_command_from_buffer(struct nft_ctx *nft, struct nft_cache *cache,
+ char *buf, size_t buflen)
+{
+ int rc = NFT_EXIT_SUCCESS;
+ struct parser_state state;
+ LIST_HEAD(msgs);
+ void *scanner;
+
+ parser_init(nft->nf_sock, cache, &state, &msgs);
+ scanner = scanner_init(&state);
+ scanner_push_buffer(scanner, &indesc_cmdline, buf);
+
+ if (nft_run(nft, nft->nf_sock, cache, scanner, &state, &msgs) != 0)
+ rc = NFT_EXIT_FAILURE;
+
+ return rc;
+}
diff --git a/src/main.c b/src/main.c
index 23af38e..f863dec 100644
--- a/src/main.c
+++ b/src/main.c
@@ -18,8 +18,8 @@
#include <fcntl.h>
#include <sys/types.h>
-#include <nftables/nftables.h>
#include <nftables.h>
+#include <nftables/nftables.h>
#include <utils.h>
#include <parser.h>
#include <rule.h>
@@ -182,11 +182,6 @@ static const struct {
};
#endif
-static const struct input_descriptor indesc_cmdline = {
- .type = INDESC_BUFFER,
- .name = "<cmdline>",
-};
-
static int nft_netlink(struct nft_ctx *nft, struct nft_cache *cache,
struct parser_state *state, struct list_head *msgs,
struct mnl_socket *nf_sock)
@@ -367,7 +362,7 @@ int main(int argc, char * const *argv)
nft->output.handle++;
break;
case OPT_ECHO:
- nft.output.echo++;
+ nft->output.echo++;
break;
case OPT_INVALID:
exit(NFT_EXIT_FAILURE);
@@ -385,9 +380,10 @@ int main(int argc, char * const *argv)
strcat(buf, " ");
}
strcat(buf, "\n");
- parser_init(nft->nf_sock, &cache, &state, &msgs);
- scanner = scanner_init(&state);
- scanner_push_buffer(scanner, &indesc_cmdline, buf);
+ rc = nft_run_command_from_buffer(nft, &cache, buf, len + 2);
+ if (rc < 0)
+ return rc;
+ goto libout;
} else if (filename != NULL) {
rc = cache_update(nft->nf_sock, &cache, CMD_INVALID, &msgs);
if (rc < 0)
@@ -397,6 +393,8 @@ int main(int argc, char * const *argv)
scanner = scanner_init(&state);
if (scanner_read_file(scanner, filename, &internal_location) < 0)
goto out;
+ if (nft_run(nft, nft->nf_sock, &cache, scanner, &state, &msgs) != 0)
+ rc = NFT_EXIT_FAILURE;
} else if (interactive) {
if (cli_init(nft, nft->nf_sock, &cache, &state) < 0) {
fprintf(stderr, "%s: interactive CLI not supported in this build\n",
@@ -409,11 +407,10 @@ int main(int argc, char * const *argv)
exit(NFT_EXIT_FAILURE);
}
- if (nft_run(nft, nft->nf_sock, &cache, scanner, &state, &msgs) != 0)
- rc = NFT_EXIT_FAILURE;
out:
scanner_destroy(scanner);
erec_print_list(stderr, &msgs);
+libout:
xfree(buf);
cache_release(&cache);
iface_cache_release();
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 04/16] libnftables: add nft_run_command_from_filename
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
` (2 preceding siblings ...)
2017-08-16 20:42 ` [nft PATH 03/16] libnftables: add nft_run_command_from_buffer Eric Leblond
@ 2017-08-16 20:42 ` Eric Leblond
2017-08-16 20:42 ` [nft PATH 05/16] libnftables: put nft_run in library Eric Leblond
` (12 subsequent siblings)
16 siblings, 0 replies; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:42 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
Add new function to read nftables command from a file
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/nftables/nftables.h | 2 ++
src/libnftables.c | 25 +++++++++++++++++++++++++
src/main.c | 16 +++-------------
3 files changed, 30 insertions(+), 13 deletions(-)
diff --git a/include/nftables/nftables.h b/include/nftables/nftables.h
index 63150ba..980c6ec 100644
--- a/include/nftables/nftables.h
+++ b/include/nftables/nftables.h
@@ -22,5 +22,7 @@ void nft_context_free(struct nft_ctx *nft);
int nft_run_command_from_buffer(struct nft_ctx *nft, struct nft_cache *cache,
char *buf, size_t buflen);
+int nft_run_command_from_filename(struct nft_ctx *nft, struct nft_cache *cache,
+ const char *filename);
#endif
diff --git a/src/libnftables.c b/src/libnftables.c
index 9248741..8c92fbf 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -93,5 +93,30 @@ int nft_run_command_from_buffer(struct nft_ctx *nft, struct nft_cache *cache,
if (nft_run(nft, nft->nf_sock, cache, scanner, &state, &msgs) != 0)
rc = NFT_EXIT_FAILURE;
+ scanner_destroy(scanner);
+ erec_print_list(stderr, &msgs);
+ return rc;
+}
+
+int nft_run_command_from_filename(struct nft_ctx *nft, struct nft_cache *cache,
+ const char *filename)
+{
+ int rc = NFT_EXIT_SUCCESS;
+ struct parser_state state;
+ LIST_HEAD(msgs);
+ void *scanner;
+
+ rc = cache_update(nft->nf_sock, cache, CMD_INVALID, &msgs);
+ if (rc < 0)
+ return rc;
+ parser_init(nft->nf_sock, cache, &state, &msgs);
+ scanner = scanner_init(&state);
+ if (scanner_read_file(scanner, filename, &internal_location) < 0)
+ return NFT_EXIT_FAILURE;
+ if (nft_run(nft, nft->nf_sock, cache, scanner, &state, &msgs) != 0)
+ rc = NFT_EXIT_FAILURE;
+
+ scanner_destroy(scanner);
+ erec_print_list(stderr, &msgs);
return rc;
}
diff --git a/src/main.c b/src/main.c
index f863dec..658988d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -271,7 +271,6 @@ int main(int argc, char * const *argv)
{
struct parser_state state;
struct nft_cache cache;
- void *scanner;
LIST_HEAD(msgs);
char *buf = NULL, *filename = NULL;
unsigned int len;
@@ -383,18 +382,12 @@ int main(int argc, char * const *argv)
rc = nft_run_command_from_buffer(nft, &cache, buf, len + 2);
if (rc < 0)
return rc;
- goto libout;
+ goto out;
} else if (filename != NULL) {
- rc = cache_update(nft->nf_sock, &cache, CMD_INVALID, &msgs);
+ rc = nft_run_command_from_filename(nft, &cache, filename);
if (rc < 0)
return rc;
-
- parser_init(nft->nf_sock, &cache, &state, &msgs);
- scanner = scanner_init(&state);
- if (scanner_read_file(scanner, filename, &internal_location) < 0)
- goto out;
- if (nft_run(nft, nft->nf_sock, &cache, scanner, &state, &msgs) != 0)
- rc = NFT_EXIT_FAILURE;
+ goto out;
} else if (interactive) {
if (cli_init(nft, nft->nf_sock, &cache, &state) < 0) {
fprintf(stderr, "%s: interactive CLI not supported in this build\n",
@@ -408,9 +401,6 @@ int main(int argc, char * const *argv)
}
out:
- scanner_destroy(scanner);
- erec_print_list(stderr, &msgs);
-libout:
xfree(buf);
cache_release(&cache);
iface_cache_release();
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 05/16] libnftables: put nft_run in library
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
` (3 preceding siblings ...)
2017-08-16 20:42 ` [nft PATH 04/16] libnftables: add nft_run_command_from_filename Eric Leblond
@ 2017-08-16 20:42 ` Eric Leblond
2017-08-16 20:43 ` [nft PATH 06/16] libnftables: add missing variable to library Eric Leblond
` (11 subsequent siblings)
16 siblings, 0 replies; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:42 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/nftables.h | 4 --
include/nftables_common.h | 18 ++++++++
src/Makefile.am | 1 +
src/cli.c | 1 +
src/libnftables.c | 2 +
src/main.c | 85 -------------------------------------
src/nftables_common.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 126 insertions(+), 89 deletions(-)
create mode 100644 include/nftables_common.h
create mode 100644 src/nftables_common.c
diff --git a/include/nftables.h b/include/nftables.h
index 717af37..c2bb7d8 100644
--- a/include/nftables.h
+++ b/include/nftables.h
@@ -124,10 +124,6 @@ struct input_descriptor {
struct parser_state;
struct mnl_socket;
-int nft_run(struct nft_ctx *nft, struct mnl_socket *nf_sock,
- struct nft_cache *cache, void *scanner, struct parser_state *state,
- struct list_head *msgs);
-
void ct_label_table_init(void);
void mark_table_init(void);
void gmp_init(void);
diff --git a/include/nftables_common.h b/include/nftables_common.h
new file mode 100644
index 0000000..c3f54a5
--- /dev/null
+++ b/include/nftables_common.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2017 Eric Leblond <eric@regit.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+
+#ifndef NFTABLES_NFTABLES_COMMON_H
+#define NFTABLES_NFTABLES_COMMON_H
+
+int nft_run(struct nft_ctx *nft, struct mnl_socket *nf_sock,
+ struct nft_cache *cache, void *scanner, struct parser_state *state,
+ struct list_head *msgs);
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index a340d39..cddd3a2 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -58,6 +58,7 @@ libnftables_la_SOURCES = rule.c \
libnftables.c \
scanner.l \
tcpopt.c \
+ nftables_common.c \
parser_bison.y
if BUILD_MINIGMP
diff --git a/src/cli.c b/src/cli.c
index a50fc58..7501b29 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -30,6 +30,7 @@
#include <utils.h>
#include <iface.h>
#include <cli.h>
+#include <nftables_common.h>
#include <libmnl/libmnl.h>
diff --git a/src/libnftables.c b/src/libnftables.c
index 8c92fbf..6599248 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -16,6 +16,8 @@
#include <erec.h>
#include <libmnl/libmnl.h>
#include <mnl.h>
+#include <netlink.h>
+#include <nftables_common.h>
#include <nftables/nftables.h>
diff --git a/src/main.c b/src/main.c
index 658988d..9b4e450 100644
--- a/src/main.c
+++ b/src/main.c
@@ -182,91 +182,6 @@ static const struct {
};
#endif
-static int nft_netlink(struct nft_ctx *nft, struct nft_cache *cache,
- struct parser_state *state, struct list_head *msgs,
- struct mnl_socket *nf_sock)
-{
- uint32_t batch_seqnum, seqnum = 0;
- struct nftnl_batch *batch;
- struct netlink_ctx ctx;
- struct cmd *cmd;
- struct mnl_err *err, *tmp;
- LIST_HEAD(err_list);
- bool batch_supported = netlink_batch_supported(nf_sock, &seqnum);
- int ret = 0;
-
- batch = mnl_batch_init();
-
- batch_seqnum = mnl_batch_begin(batch, mnl_seqnum_alloc(&seqnum));
- list_for_each_entry(cmd, &state->cmds, list) {
- memset(&ctx, 0, sizeof(ctx));
- ctx.msgs = msgs;
- ctx.seqnum = cmd->seqnum = mnl_seqnum_alloc(&seqnum);
- ctx.batch = batch;
- ctx.batch_supported = batch_supported;
- ctx.octx = &nft->output;
- ctx.nf_sock = nf_sock;
- ctx.cache = cache;
- init_list_head(&ctx.list);
- ret = do_command(&ctx, cmd);
- if (ret < 0)
- goto out;
- }
- if (!nft->check)
- mnl_batch_end(batch, mnl_seqnum_alloc(&seqnum));
-
- if (!mnl_batch_ready(batch))
- goto out;
-
- ret = netlink_batch_send(&ctx, &err_list);
-
- list_for_each_entry_safe(err, tmp, &err_list, head) {
- list_for_each_entry(cmd, &state->cmds, list) {
- if (err->seqnum == cmd->seqnum ||
- err->seqnum == batch_seqnum) {
- netlink_io_error(&ctx, &cmd->location,
- "Could not process rule: %s",
- strerror(err->err));
- ret = -1;
- errno = err->err;
- if (err->seqnum == cmd->seqnum) {
- mnl_err_list_free(err);
- break;
- }
- }
- }
- }
-out:
- mnl_batch_reset(batch);
- return ret;
-}
-
-int nft_run(struct nft_ctx *nft, struct mnl_socket *nf_sock,
- struct nft_cache *cache, void *scanner, struct parser_state *state,
- struct list_head *msgs)
-{
- struct cmd *cmd, *next;
- int ret;
-
- ret = nft_parse(scanner, state);
- if (ret != 0 || state->nerrs > 0) {
- ret = -1;
- goto err1;
- }
-
- list_for_each_entry(cmd, &state->cmds, list)
- nft_cmd_expand(cmd);
-
- ret = nft_netlink(nft, cache, state, msgs, nf_sock);
-err1:
- list_for_each_entry_safe(cmd, next, &state->cmds, list) {
- list_del(&cmd->list);
- cmd_free(cmd);
- }
-
- return ret;
-}
-
int main(int argc, char * const *argv)
{
struct parser_state state;
diff --git a/src/nftables_common.c b/src/nftables_common.c
new file mode 100644
index 0000000..4ae9f3e
--- /dev/null
+++ b/src/nftables_common.c
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2017 Eric Leblond <eric@regit.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <string.h>
+#include <errno.h>
+
+#include <nftables.h>
+#include <nftables_common.h>
+#include <netlink.h>
+#include <parser.h>
+#include <mnl.h>
+
+static int nft_netlink(struct nft_ctx *nft, struct nft_cache *cache,
+ struct parser_state *state, struct list_head *msgs,
+ struct mnl_socket *nf_sock)
+{
+ uint32_t batch_seqnum, seqnum = 0;
+ struct nftnl_batch *batch;
+ struct netlink_ctx ctx;
+ struct cmd *cmd;
+ struct mnl_err *err, *tmp;
+ LIST_HEAD(err_list);
+ bool batch_supported = netlink_batch_supported(nf_sock, &seqnum);
+ int ret = 0;
+
+ batch = mnl_batch_init();
+
+ batch_seqnum = mnl_batch_begin(batch, mnl_seqnum_alloc(&seqnum));
+ list_for_each_entry(cmd, &state->cmds, list) {
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.msgs = msgs;
+ ctx.seqnum = cmd->seqnum = mnl_seqnum_alloc(&seqnum);
+ ctx.batch = batch;
+ ctx.batch_supported = batch_supported;
+ ctx.octx = &nft->output;
+ ctx.nf_sock = nf_sock;
+ ctx.cache = cache;
+ init_list_head(&ctx.list);
+ ret = do_command(&ctx, cmd);
+ if (ret < 0)
+ goto out;
+ }
+ if (!nft->check)
+ mnl_batch_end(batch, mnl_seqnum_alloc(&seqnum));
+
+ if (!mnl_batch_ready(batch))
+ goto out;
+
+ ret = netlink_batch_send(&ctx, &err_list);
+
+ list_for_each_entry_safe(err, tmp, &err_list, head) {
+ list_for_each_entry(cmd, &state->cmds, list) {
+ if (err->seqnum == cmd->seqnum ||
+ err->seqnum == batch_seqnum) {
+ netlink_io_error(&ctx, &cmd->location,
+ "Could not process rule: %s",
+ strerror(err->err));
+ ret = -1;
+ errno = err->err;
+ if (err->seqnum == cmd->seqnum) {
+ mnl_err_list_free(err);
+ break;
+ }
+ }
+ }
+ }
+out:
+ mnl_batch_reset(batch);
+ return ret;
+}
+
+int nft_run(struct nft_ctx *nft, struct mnl_socket *nf_sock,
+ struct nft_cache *cache, void *scanner, struct parser_state *state,
+ struct list_head *msgs)
+{
+ struct cmd *cmd, *next;
+ int ret;
+
+ ret = nft_parse(scanner, state);
+ if (ret != 0 || state->nerrs > 0) {
+ ret = -1;
+ goto err1;
+ }
+
+ list_for_each_entry(cmd, &state->cmds, list)
+ nft_cmd_expand(cmd);
+
+ ret = nft_netlink(nft, cache, state, msgs, nf_sock);
+err1:
+ list_for_each_entry_safe(cmd, next, &state->cmds, list) {
+ list_del(&cmd->list);
+ cmd_free(cmd);
+ }
+
+ return ret;
+}
+
+
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 06/16] libnftables: add missing variable to library
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
` (4 preceding siblings ...)
2017-08-16 20:42 ` [nft PATH 05/16] libnftables: put nft_run in library Eric Leblond
@ 2017-08-16 20:43 ` Eric Leblond
2017-08-17 9:35 ` Phil Sutter
2017-08-16 20:43 ` [nft PATH 07/16] libnftables: add NFT_EXIT_* " Eric Leblond
` (10 subsequent siblings)
16 siblings, 1 reply; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:43 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
Signed-off-by: Eric Leblond <eric@regit.org>
---
src/libnftables.c | 2 ++
src/main.c | 1 -
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/libnftables.c b/src/libnftables.c
index 6599248..6d4aceb 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -33,6 +33,8 @@ unsigned int handle_output;
unsigned int debug_level;
#endif
+const char *include_paths[INCLUDE_PATHS_MAX] = { DEFAULT_INCLUDE_PATH };
+
void nft_global_init(void)
{
mark_table_init();
diff --git a/src/main.c b/src/main.c
index 9b4e450..20fea87 100644
--- a/src/main.c
+++ b/src/main.c
@@ -34,7 +34,6 @@ unsigned int max_errors = 10;
unsigned int debug_level;
#endif
-const char *include_paths[INCLUDE_PATHS_MAX] = { DEFAULT_INCLUDE_PATH };
static unsigned int num_include_paths = 1;
enum opt_vals {
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 07/16] libnftables: add NFT_EXIT_* to library
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
` (5 preceding siblings ...)
2017-08-16 20:43 ` [nft PATH 06/16] libnftables: add missing variable to library Eric Leblond
@ 2017-08-16 20:43 ` Eric Leblond
2017-08-16 20:43 ` [nft PATH 08/16] libnftables: add a nft_cache to nft_ctx Eric Leblond
` (9 subsequent siblings)
16 siblings, 0 replies; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:43 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
So it can be used by client to check function return.
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/nftables.h | 7 -------
include/nftables/nftables.h | 7 +++++++
src/netlink.c | 1 +
src/utils.c | 1 +
4 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/include/nftables.h b/include/nftables.h
index c2bb7d8..aad204e 100644
--- a/include/nftables.h
+++ b/include/nftables.h
@@ -48,13 +48,6 @@ extern unsigned int max_errors;
extern unsigned int debug_level;
extern const char *include_paths[INCLUDE_PATHS_MAX];
-enum nftables_exit_codes {
- NFT_EXIT_SUCCESS = 0,
- NFT_EXIT_FAILURE = 1,
- NFT_EXIT_NOMEM = 2,
- NFT_EXIT_NONL = 3,
-};
-
struct input_descriptor;
struct location {
const struct input_descriptor *indesc;
diff --git a/include/nftables/nftables.h b/include/nftables/nftables.h
index 980c6ec..20a062c 100644
--- a/include/nftables/nftables.h
+++ b/include/nftables/nftables.h
@@ -14,6 +14,13 @@
#include <stdint.h>
#include <stdbool.h>
+enum nftables_exit_codes {
+ NFT_EXIT_SUCCESS = 0,
+ NFT_EXIT_FAILURE = 1,
+ NFT_EXIT_NOMEM = 2,
+ NFT_EXIT_NONL = 3,
+};
+
void nft_global_init(void);
void nft_global_deinit(void);
diff --git a/src/netlink.c b/src/netlink.c
index 7311149..ea5d9b1 100644
--- a/src/netlink.c
+++ b/src/netlink.c
@@ -30,6 +30,7 @@
#include <linux/netfilter.h>
#include <nftables.h>
+#include <nftables/nftables.h>
#include <netlink.h>
#include <mnl.h>
#include <expression.h>
diff --git a/src/utils.c b/src/utils.c
index 47f5b79..aace563 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -16,6 +16,7 @@
#include <string.h>
#include <nftables.h>
+#include <nftables/nftables.h>
#include <utils.h>
void __noreturn __memory_allocation_error(const char *filename, uint32_t line)
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 08/16] libnftables: add a nft_cache to nft_ctx
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
` (6 preceding siblings ...)
2017-08-16 20:43 ` [nft PATH 07/16] libnftables: add NFT_EXIT_* " Eric Leblond
@ 2017-08-16 20:43 ` Eric Leblond
2017-08-17 9:43 ` Phil Sutter
2017-08-16 20:43 ` [nft PATH 09/16] libnftables: move iface_cache_release to deinit Eric Leblond
` (8 subsequent siblings)
16 siblings, 1 reply; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:43 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
Hide this structure from the user, this allows simplify the simple
functions by just providing easy and meaningfull arguments.
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/cli.h | 2 +-
include/nftables.h | 13 +++++++------
include/nftables/nftables.h | 5 ++---
src/cli.c | 10 ++++++++--
src/libnftables.c | 19 +++++++++++--------
src/main.c | 11 +++--------
6 files changed, 32 insertions(+), 28 deletions(-)
diff --git a/include/cli.h b/include/cli.h
index e577400..899c8a6 100644
--- a/include/cli.h
+++ b/include/cli.h
@@ -6,7 +6,7 @@
struct parser_state;
#ifdef HAVE_LIBREADLINE
extern int cli_init(struct nft_ctx *nft, struct mnl_socket *nf_sock,
- struct nft_cache *cache, struct parser_state *state);
+ struct parser_state *state);
#else
static inline int cli_init(struct nft_ctx *nft, struct mnl_socket *nf_sock,
struct nft_cache *cache, struct parser_state *state)
diff --git a/include/nftables.h b/include/nftables.h
index aad204e..348fbb0 100644
--- a/include/nftables.h
+++ b/include/nftables.h
@@ -32,18 +32,19 @@ struct output_ctx {
unsigned int echo;
};
-struct nft_ctx {
- struct output_ctx output;
- bool check;
- struct mnl_socket *nf_sock;
-};
-
struct nft_cache {
bool initialized;
struct list_head list;
uint32_t seqnum;
};
+struct nft_ctx {
+ struct output_ctx output;
+ bool check;
+ struct mnl_socket *nf_sock;
+ struct nft_cache cache;
+};
+
extern unsigned int max_errors;
extern unsigned int debug_level;
extern const char *include_paths[INCLUDE_PATHS_MAX];
diff --git a/include/nftables/nftables.h b/include/nftables/nftables.h
index 20a062c..b902cbd 100644
--- a/include/nftables/nftables.h
+++ b/include/nftables/nftables.h
@@ -27,9 +27,8 @@ void nft_global_deinit(void);
struct nft_ctx *nft_context_new(void);
void nft_context_free(struct nft_ctx *nft);
-int nft_run_command_from_buffer(struct nft_ctx *nft, struct nft_cache *cache,
+int nft_run_command_from_buffer(struct nft_ctx *nft,
char *buf, size_t buflen);
-int nft_run_command_from_filename(struct nft_ctx *nft, struct nft_cache *cache,
- const char *filename);
+int nft_run_command_from_filename(struct nft_ctx *nft, const char *filename);
#endif
diff --git a/src/cli.c b/src/cli.c
index 7501b29..fd5c7b7 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -177,13 +177,17 @@ void __fmtstring(1, 0) cli_display(const char *fmt, va_list ap)
}
int cli_init(struct nft_ctx *nft, struct mnl_socket *nf_sock,
- struct nft_cache *cache, struct parser_state *_state)
+ struct parser_state *_state)
{
const char *home;
+ struct nft_cache cache;
+
+ memset(&cache, 0, sizeof(cache));
+ init_list_head(&cache.list);
cli_nf_sock = nf_sock;
cli_nft = *nft;
- cli_cache = cache;
+ cli_cache = &cache;
rl_readline_name = "nft";
rl_instream = stdin;
rl_outstream = stdout;
@@ -204,6 +208,8 @@ int cli_init(struct nft_ctx *nft, struct mnl_socket *nf_sock,
while (!eof)
rl_callback_read_char();
+
+ cache_release(&cache);
return 0;
}
diff --git a/src/libnftables.c b/src/libnftables.c
index 6d4aceb..864156c 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -63,7 +63,10 @@ struct nft_ctx *nft_context_new(void)
ctx = malloc(sizeof(struct nft_ctx));
if (ctx == NULL)
return NULL;
+
+ memset(ctx, 0, sizeof(*ctx));
ctx->nf_sock = netlink_open_sock();
+ init_list_head(&ctx->cache.list);
return ctx;
}
@@ -74,6 +77,7 @@ void nft_context_free(struct nft_ctx *nft)
if (nft == NULL)
return;
netlink_close_sock(nft->nf_sock);
+ cache_release(&nft->cache);
xfree(nft);
}
@@ -82,7 +86,7 @@ static const struct input_descriptor indesc_cmdline = {
.name = "<cmdline>",
};
-int nft_run_command_from_buffer(struct nft_ctx *nft, struct nft_cache *cache,
+int nft_run_command_from_buffer(struct nft_ctx *nft,
char *buf, size_t buflen)
{
int rc = NFT_EXIT_SUCCESS;
@@ -90,11 +94,11 @@ int nft_run_command_from_buffer(struct nft_ctx *nft, struct nft_cache *cache,
LIST_HEAD(msgs);
void *scanner;
- parser_init(nft->nf_sock, cache, &state, &msgs);
+ parser_init(nft->nf_sock, &nft->cache, &state, &msgs);
scanner = scanner_init(&state);
scanner_push_buffer(scanner, &indesc_cmdline, buf);
- if (nft_run(nft, nft->nf_sock, cache, scanner, &state, &msgs) != 0)
+ if (nft_run(nft, nft->nf_sock, &nft->cache, scanner, &state, &msgs) != 0)
rc = NFT_EXIT_FAILURE;
scanner_destroy(scanner);
@@ -102,22 +106,21 @@ int nft_run_command_from_buffer(struct nft_ctx *nft, struct nft_cache *cache,
return rc;
}
-int nft_run_command_from_filename(struct nft_ctx *nft, struct nft_cache *cache,
- const char *filename)
+int nft_run_command_from_filename(struct nft_ctx *nft, const char *filename)
{
int rc = NFT_EXIT_SUCCESS;
struct parser_state state;
LIST_HEAD(msgs);
void *scanner;
- rc = cache_update(nft->nf_sock, cache, CMD_INVALID, &msgs);
+ rc = cache_update(nft->nf_sock, &nft->cache, CMD_INVALID, &msgs);
if (rc < 0)
return rc;
- parser_init(nft->nf_sock, cache, &state, &msgs);
+ parser_init(nft->nf_sock, &nft->cache, &state, &msgs);
scanner = scanner_init(&state);
if (scanner_read_file(scanner, filename, &internal_location) < 0)
return NFT_EXIT_FAILURE;
- if (nft_run(nft, nft->nf_sock, cache, scanner, &state, &msgs) != 0)
+ if (nft_run(nft, nft->nf_sock, &nft->cache, scanner, &state, &msgs) != 0)
rc = NFT_EXIT_FAILURE;
scanner_destroy(scanner);
diff --git a/src/main.c b/src/main.c
index 20fea87..64b8c58 100644
--- a/src/main.c
+++ b/src/main.c
@@ -184,7 +184,6 @@ static const struct {
int main(int argc, char * const *argv)
{
struct parser_state state;
- struct nft_cache cache;
LIST_HEAD(msgs);
char *buf = NULL, *filename = NULL;
unsigned int len;
@@ -192,9 +191,6 @@ int main(int argc, char * const *argv)
int i, val, rc = NFT_EXIT_SUCCESS;
struct nft_ctx *nft;
- memset(&cache, 0, sizeof(cache));
- init_list_head(&cache.list);
-
nft_global_init();
nft = nft_context_new();
while (1) {
@@ -293,17 +289,17 @@ int main(int argc, char * const *argv)
strcat(buf, " ");
}
strcat(buf, "\n");
- rc = nft_run_command_from_buffer(nft, &cache, buf, len + 2);
+ rc = nft_run_command_from_buffer(nft, buf, len + 2);
if (rc < 0)
return rc;
goto out;
} else if (filename != NULL) {
- rc = nft_run_command_from_filename(nft, &cache, filename);
+ rc = nft_run_command_from_filename(nft, filename);
if (rc < 0)
return rc;
goto out;
} else if (interactive) {
- if (cli_init(nft, nft->nf_sock, &cache, &state) < 0) {
+ if (cli_init(nft, nft->nf_sock, &state) < 0) {
fprintf(stderr, "%s: interactive CLI not supported in this build\n",
argv[0]);
exit(NFT_EXIT_FAILURE);
@@ -316,7 +312,6 @@ int main(int argc, char * const *argv)
out:
xfree(buf);
- cache_release(&cache);
iface_cache_release();
nft_context_free(nft);
nft_global_deinit();
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 09/16] libnftables: move iface_cache_release to deinit
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
` (7 preceding siblings ...)
2017-08-16 20:43 ` [nft PATH 08/16] libnftables: add a nft_cache to nft_ctx Eric Leblond
@ 2017-08-16 20:43 ` Eric Leblond
2017-08-16 20:43 ` [nft PATH 10/16] libnftables: get rid of printf Eric Leblond
` (7 subsequent siblings)
16 siblings, 0 replies; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:43 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
Signed-off-by: Eric Leblond <eric@regit.org>
---
src/libnftables.c | 1 +
src/main.c | 1 -
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/libnftables.c b/src/libnftables.c
index 864156c..72e6efa 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -50,6 +50,7 @@ void nft_global_init(void)
void nft_global_deinit(void)
{
+ iface_cache_release();
ct_label_table_exit();
realm_table_rt_exit();
devgroup_table_exit();
diff --git a/src/main.c b/src/main.c
index 64b8c58..a6305cc 100644
--- a/src/main.c
+++ b/src/main.c
@@ -312,7 +312,6 @@ int main(int argc, char * const *argv)
out:
xfree(buf);
- iface_cache_release();
nft_context_free(nft);
nft_global_deinit();
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 10/16] libnftables: get rid of printf
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
` (8 preceding siblings ...)
2017-08-16 20:43 ` [nft PATH 09/16] libnftables: move iface_cache_release to deinit Eric Leblond
@ 2017-08-16 20:43 ` Eric Leblond
2017-08-17 10:01 ` Phil Sutter
2017-08-16 20:43 ` [nft PATH 11/16] libnftables: add nft_context_set_print Eric Leblond
` (6 subsequent siblings)
16 siblings, 1 reply; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:43 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
Use a custom print function that user will be able to set instead of
using a direct call to printf.
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/datatype.h | 5 +-
include/expression.h | 2 +-
include/nftables.h | 2 +
src/ct.c | 20 +++----
src/datatype.c | 61 +++++++++++---------
src/expression.c | 70 +++++++++++------------
src/exthdr.c | 8 +--
src/fib.c | 23 ++++----
src/hash.c | 10 ++--
src/libnftables.c | 14 +++++
src/meta.c | 26 ++++-----
src/numgen.c | 4 +-
src/payload.c | 4 +-
src/rule.c | 159 ++++++++++++++++++++++++++-------------------------
src/statement.c | 122 +++++++++++++++++++--------------------
15 files changed, 279 insertions(+), 251 deletions(-)
diff --git a/include/datatype.h b/include/datatype.h
index 2e34591..e9f6079 100644
--- a/include/datatype.h
+++ b/include/datatype.h
@@ -209,7 +209,8 @@ extern void symbolic_constant_print(const struct symbol_table *tbl,
struct output_ctx *octx);
extern void symbol_table_print(const struct symbol_table *tbl,
const struct datatype *dtype,
- enum byteorder byteorder);
+ enum byteorder byteorder,
+ struct output_ctx *octx);
extern struct symbol_table *rt_symbol_table_init(const char *filename);
extern void rt_symbol_table_free(struct symbol_table *tbl);
@@ -261,7 +262,7 @@ extern const struct datatype *
set_datatype_alloc(const struct datatype *orig_dtype, unsigned int byteorder);
extern void set_datatype_destroy(const struct datatype *dtype);
-extern void time_print(uint64_t seconds);
+extern void time_print(uint64_t seconds, struct output_ctx *octx);
extern struct error_record *time_parse(const struct location *loc,
const char *c, uint64_t *res);
diff --git a/include/expression.h b/include/expression.h
index 828dbae..d82642d 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -334,7 +334,7 @@ extern struct expr *expr_get(struct expr *expr);
extern void expr_free(struct expr *expr);
extern void expr_print(const struct expr *expr, struct output_ctx *octx);
extern bool expr_cmp(const struct expr *e1, const struct expr *e2);
-extern void expr_describe(const struct expr *expr);
+extern void expr_describe(const struct expr *expr, struct output_ctx *octx);
extern const struct datatype *expr_basetype(const struct expr *expr);
extern void expr_set_type(struct expr *expr, const struct datatype *dtype,
diff --git a/include/nftables.h b/include/nftables.h
index 348fbb0..ddff5d8 100644
--- a/include/nftables.h
+++ b/include/nftables.h
@@ -30,6 +30,8 @@ struct output_ctx {
unsigned int ip2name;
unsigned int handle;
unsigned int echo;
+ void *ctx;
+ int (*print)(void *ctx, const char *format, ...);
};
struct nft_cache {
diff --git a/src/ct.c b/src/ct.c
index d64f467..4367b21 100644
--- a/src/ct.c
+++ b/src/ct.c
@@ -141,11 +141,11 @@ static void ct_label_type_print(const struct expr *expr,
for (s = ct_label_tbl->symbols; s->identifier != NULL; s++) {
if (bit != s->value)
continue;
- printf("\"%s\"", s->identifier);
+ octx->print(octx->ctx, "\"%s\"", s->identifier);
return;
}
/* can happen when connlabel.conf is altered after rules were added */
- printf("%ld\n", (long)mpz_scan1(expr->value, 0));
+ octx->print(octx->ctx, "%ld\n", (long)mpz_scan1(expr->value, 0));
}
static struct error_record *ct_label_type_parse(const struct expr *sym,
@@ -269,27 +269,27 @@ static const struct ct_template ct_templates[] = {
BYTEORDER_HOST_ENDIAN, 32),
};
-static void ct_print(enum nft_ct_keys key, int8_t dir)
+static void ct_print(enum nft_ct_keys key, int8_t dir, struct output_ctx *octx)
{
const struct symbolic_constant *s;
- printf("ct ");
+ octx->print(octx->ctx, "ct ");
if (dir < 0)
goto done;
for (s = ct_dir_tbl.symbols; s->identifier != NULL; s++) {
if (dir == (int)s->value) {
- printf("%s ", s->identifier);
+ octx->print(octx->ctx, "%s ", s->identifier);
break;
}
}
done:
- printf("%s", ct_templates[key].token);
+ octx->print(octx->ctx, "%s", ct_templates[key].token);
}
static void ct_expr_print(const struct expr *expr, struct output_ctx *octx)
{
- ct_print(expr->ct.key, expr->ct.direction);
+ ct_print(expr->ct.key, expr->ct.direction, octx);
}
static bool ct_expr_cmp(const struct expr *e1, const struct expr *e2)
@@ -445,8 +445,8 @@ void ct_expr_update_type(struct proto_ctx *ctx, struct expr *expr)
static void ct_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
- ct_print(stmt->ct.key, stmt->ct.direction);
- printf(" set ");
+ ct_print(stmt->ct.key, stmt->ct.direction, octx);
+ octx->print(octx->ctx, " set ");
expr_print(stmt->ct.expr, octx);
}
@@ -472,7 +472,7 @@ struct stmt *ct_stmt_alloc(const struct location *loc, enum nft_ct_keys key,
static void notrack_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
- printf("notrack");
+ octx->print(octx->ctx, "notrack");
}
static const struct stmt_ops notrack_stmt_ops = {
diff --git a/src/datatype.c b/src/datatype.c
index 5bd0c7b..1f500e2 100644
--- a/src/datatype.c
+++ b/src/datatype.c
@@ -192,15 +192,15 @@ void symbolic_constant_print(const struct symbol_table *tbl,
return expr_basetype(expr)->print(expr, octx);
if (quotes)
- printf("\"");
+ octx->print(octx->ctx, "\"");
if (octx->numeric > NUMERIC_ALL)
- printf("%"PRIu64"", val);
+ octx->print(octx->ctx, "%"PRIu64"", val);
else
- printf("%s", s->identifier);
+ octx->print(octx->ctx, "%s", s->identifier);
if (quotes)
- printf("\"");
+ octx->print(octx->ctx, "\"");
}
static void switch_byteorder(void *data, unsigned int len)
@@ -215,7 +215,8 @@ static void switch_byteorder(void *data, unsigned int len)
void symbol_table_print(const struct symbol_table *tbl,
const struct datatype *dtype,
- enum byteorder byteorder)
+ enum byteorder byteorder,
+ struct output_ctx *octx)
{
const struct symbolic_constant *s;
unsigned int len = dtype->size / BITS_PER_BYTE;
@@ -228,16 +229,18 @@ void symbol_table_print(const struct symbol_table *tbl,
switch_byteorder(&value, len);
if (tbl->base == BASE_DECIMAL)
- printf("\t%-30s\t%20"PRIu64"\n", s->identifier, value);
+ octx->print(octx->ctx, "\t%-30s\t%20"PRIu64"\n", s->identifier, value);
else
- printf("\t%-30s\t0x%.*" PRIx64 "\n",
+ octx->print(octx->ctx, "\t%-30s\t0x%.*" PRIx64 "\n",
s->identifier, 2 * len, value);
}
}
static void invalid_type_print(const struct expr *expr, struct output_ctx *octx)
{
- gmp_printf("0x%Zx [invalid type]", expr->value);
+ char buf[512];
+ gmp_snprintf(buf, sizeof(buf), "0x%Zx [invalid type]", expr->value);
+ octx->print(octx->ctx, "%s", buf);
}
const struct datatype invalid_type = {
@@ -251,30 +254,30 @@ static void verdict_type_print(const struct expr *expr, struct output_ctx *octx)
{
switch (expr->verdict) {
case NFT_CONTINUE:
- printf("continue");
+ octx->print(octx->ctx, "continue");
break;
case NFT_BREAK:
- printf("break");
+ octx->print(octx->ctx, "break");
break;
case NFT_JUMP:
- printf("jump %s", expr->chain);
+ octx->print(octx->ctx, "jump %s", expr->chain);
break;
case NFT_GOTO:
- printf("goto %s", expr->chain);
+ octx->print(octx->ctx, "goto %s", expr->chain);
break;
case NFT_RETURN:
- printf("return");
+ octx->print(octx->ctx, "return");
break;
default:
switch (expr->verdict & NF_VERDICT_MASK) {
case NF_ACCEPT:
- printf("accept");
+ octx->print(octx->ctx, "accept");
break;
case NF_DROP:
- printf("drop");
+ octx->print(octx->ctx, "drop");
break;
case NF_QUEUE:
- printf("queue");
+ octx->print(octx->ctx, "queue");
break;
default:
BUG("invalid verdict value %u\n", expr->verdict);
@@ -319,6 +322,7 @@ static void integer_type_print(const struct expr *expr, struct output_ctx *octx)
{
const struct datatype *dtype = expr->dtype;
const char *fmt = "%Zu";
+ char buf[256];
do {
if (dtype->basefmt != NULL) {
@@ -327,7 +331,8 @@ static void integer_type_print(const struct expr *expr, struct output_ctx *octx)
}
} while ((dtype = dtype->basetype));
- gmp_printf(fmt, expr->value);
+ gmp_snprintf(buf, sizeof(buf),fmt, expr->value);
+ octx->print(octx->ctx, "%s", buf);
}
static struct error_record *integer_type_parse(const struct expr *sym,
@@ -364,7 +369,7 @@ static void string_type_print(const struct expr *expr, struct output_ctx *octx)
mpz_export_data(data, expr->value, BYTEORDER_HOST_ENDIAN, len);
data[len] = '\0';
- printf("\"%s\"", data);
+ octx->print(octx->ctx, "\"%s\"", data);
}
static struct error_record *string_type_parse(const struct expr *sym,
@@ -396,7 +401,7 @@ static void lladdr_type_print(const struct expr *expr, struct output_ctx *octx)
mpz_export_data(data, expr->value, BYTEORDER_BIG_ENDIAN, len);
for (i = 0; i < len; i++) {
- printf("%s%.2x", delim, data[i]);
+ octx->print(octx->ctx, "%s%.2x", delim, data[i]);
delim = ":";
}
}
@@ -449,7 +454,7 @@ static void ipaddr_type_print(const struct expr *expr, struct output_ctx *octx)
getnameinfo((struct sockaddr *)&sin, sizeof(sin), buf,
sizeof(buf), NULL, 0, NI_NUMERICHOST);
}
- printf("%s", buf);
+ octx->print(octx->ctx, "%s", buf);
}
static struct error_record *ipaddr_type_parse(const struct expr *sym,
@@ -507,7 +512,7 @@ static void ip6addr_type_print(const struct expr *expr, struct output_ctx *octx)
getnameinfo((struct sockaddr *)&sin6, sizeof(sin6), buf,
sizeof(buf), NULL, 0, NI_NUMERICHOST);
}
- printf("%s", buf);
+ octx->print(octx->ctx, "%s", buf);
}
static struct error_record *ip6addr_type_parse(const struct expr *sym,
@@ -557,7 +562,7 @@ static void inet_protocol_type_print(const struct expr *expr,
if (octx->numeric < NUMERIC_ALL) {
p = getprotobynumber(mpz_get_uint8(expr->value));
if (p != NULL) {
- printf("%s", p->p_name);
+ octx->print(octx->ctx, "%s", p->p_name);
return;
}
}
@@ -821,7 +826,7 @@ const struct datatype icmpx_code_type = {
.sym_tbl = &icmpx_code_tbl,
};
-void time_print(uint64_t seconds)
+void time_print(uint64_t seconds, struct output_ctx *octx)
{
uint64_t days, hours, minutes;
@@ -835,13 +840,13 @@ void time_print(uint64_t seconds)
seconds %= 60;
if (days > 0)
- printf("%"PRIu64"d", days);
+ octx->print(octx->ctx, "%"PRIu64"d", days);
if (hours > 0)
- printf("%"PRIu64"h", hours);
+ octx->print(octx->ctx, "%"PRIu64"h", hours);
if (minutes > 0)
- printf("%"PRIu64"m", minutes);
+ octx->print(octx->ctx, "%"PRIu64"m", minutes);
if (seconds > 0)
- printf("%"PRIu64"s", seconds);
+ octx->print(octx->ctx, "%"PRIu64"s", seconds);
}
enum {
@@ -933,7 +938,7 @@ struct error_record *time_parse(const struct location *loc, const char *str,
static void time_type_print(const struct expr *expr, struct output_ctx *octx)
{
- time_print(mpz_get_uint64(expr->value) / MSEC_PER_SEC);
+ time_print(mpz_get_uint64(expr->value) / MSEC_PER_SEC, octx);
}
static struct error_record *time_type_parse(const struct expr *sym,
diff --git a/src/expression.c b/src/expression.c
index d41ada3..6d70739 100644
--- a/src/expression.c
+++ b/src/expression.c
@@ -86,41 +86,41 @@ bool expr_cmp(const struct expr *e1, const struct expr *e2)
return e1->ops->cmp(e1, e2);
}
-void expr_describe(const struct expr *expr)
+void expr_describe(const struct expr *expr, struct output_ctx *octx)
{
const struct datatype *dtype = expr->dtype;
const char *delim = "";
- printf("%s expression, datatype %s (%s)",
+ octx->print(octx->ctx, "%s expression, datatype %s (%s)",
expr->ops->name, dtype->name, dtype->desc);
if (dtype->basetype != NULL) {
- printf(" (basetype ");
+ octx->print(octx->ctx, " (basetype ");
for (dtype = dtype->basetype; dtype != NULL;
dtype = dtype->basetype) {
- printf("%s%s", delim, dtype->desc);
+ octx->print(octx->ctx, "%s%s", delim, dtype->desc);
delim = ", ";
}
- printf(")");
+ octx->print(octx->ctx, ")");
}
if (expr_basetype(expr)->type == TYPE_STRING) {
if (expr->len)
- printf(", %u characters", expr->len / BITS_PER_BYTE);
+ octx->print(octx->ctx, ", %u characters", expr->len / BITS_PER_BYTE);
else
- printf(", dynamic length");
+ octx->print(octx->ctx, ", dynamic length");
} else
- printf(", %u bits", expr->len);
+ octx->print(octx->ctx, ", %u bits", expr->len);
- printf("\n");
+ octx->print(octx->ctx, "\n");
if (expr->dtype->sym_tbl != NULL) {
- printf("\npre-defined symbolic constants ");
+ octx->print(octx->ctx, "\npre-defined symbolic constants ");
if (expr->dtype->sym_tbl->base == BASE_DECIMAL)
- printf("(in decimal):\n");
+ octx->print(octx->ctx, "(in decimal):\n");
else
- printf("(in hexadecimal):\n");
+ octx->print(octx->ctx, "(in hexadecimal):\n");
symbol_table_print(expr->dtype->sym_tbl, expr->dtype,
- expr->byteorder);
+ expr->byteorder, octx);
}
}
@@ -215,7 +215,7 @@ struct expr *verdict_expr_alloc(const struct location *loc,
static void symbol_expr_print(const struct expr *expr, struct output_ctx *octx)
{
- printf("%s%s", expr->scope != NULL ? "$" : "", expr->identifier);
+ octx->print(octx->ctx, "%s%s", expr->scope != NULL ? "$" : "", expr->identifier);
}
static void symbol_expr_clone(struct expr *new, const struct expr *expr)
@@ -398,7 +398,7 @@ struct expr *bitmask_expr_to_binops(struct expr *expr)
static void prefix_expr_print(const struct expr *expr, struct output_ctx *octx)
{
expr_print(expr->prefix, octx);
- printf("/%u", expr->prefix_len);
+ octx->print(octx->ctx, "/%u", expr->prefix_len);
}
static void prefix_expr_set_type(const struct expr *expr,
@@ -513,10 +513,10 @@ static void binop_arg_print(const struct expr *op, const struct expr *arg,
prec = 1;
if (prec)
- printf("(");
+ octx->print(octx->ctx, "(");
expr_print(arg, octx);
if (prec)
- printf(")");
+ octx->print(octx->ctx, ")");
}
static bool must_print_eq_op(const struct expr *expr)
@@ -534,9 +534,9 @@ static void binop_expr_print(const struct expr *expr, struct output_ctx *octx)
if (expr_op_symbols[expr->op] &&
(expr->op != OP_EQ || must_print_eq_op(expr)))
- printf(" %s ", expr_op_symbols[expr->op]);
+ octx->print(octx->ctx, " %s ", expr_op_symbols[expr->op]);
else
- printf(" ");
+ octx->print(octx->ctx, " ");
binop_arg_print(expr, expr->right, octx);
}
@@ -602,7 +602,7 @@ static void range_expr_print(const struct expr *expr, struct output_ctx *octx)
{
octx->numeric += NUMERIC_ALL + 1;
expr_print(expr->left, octx);
- printf("-");
+ octx->print(octx->ctx, "-");
expr_print(expr->right, octx);
octx->numeric -= NUMERIC_ALL + 1;
}
@@ -682,7 +682,7 @@ static void compound_expr_print(const struct expr *expr, const char *delim,
const char *d = "";
list_for_each_entry(i, &expr->expressions, list) {
- printf("%s", d);
+ octx->print(octx->ctx, "%s", d);
expr_print(i, octx);
d = delim;
}
@@ -793,16 +793,16 @@ static void set_expr_print(const struct expr *expr, struct output_ctx *octx)
const char *d = "";
int count = 0;
- printf("{ ");
+ octx->print(octx->ctx, "{ ");
list_for_each_entry(i, &expr->expressions, list) {
- printf("%s", d);
+ octx->print(octx->ctx, "%s", d);
expr_print(i, octx);
count++;
d = calculate_delim(expr, &count);
}
- printf(" }");
+ octx->print(octx->ctx, " }");
}
static void set_expr_set_type(const struct expr *expr,
@@ -840,7 +840,7 @@ struct expr *set_expr_alloc(const struct location *loc, const struct set *set)
static void mapping_expr_print(const struct expr *expr, struct output_ctx *octx)
{
expr_print(expr->left, octx);
- printf(" : ");
+ octx->print(octx->ctx, " : ");
expr_print(expr->right, octx);
}
@@ -889,9 +889,9 @@ static void map_expr_print(const struct expr *expr, struct output_ctx *octx)
expr_print(expr->map, octx);
if (expr->mappings->ops->type == EXPR_SET_REF &&
expr->mappings->set->datatype->type == TYPE_VERDICT)
- printf(" vmap ");
+ octx->print(octx->ctx, " vmap ");
else
- printf(" map ");
+ octx->print(octx->ctx, " map ");
expr_print(expr->mappings, octx);
}
@@ -930,11 +930,11 @@ static void set_ref_expr_print(const struct expr *expr, struct output_ctx *octx)
{
if (expr->set->flags & NFT_SET_ANONYMOUS) {
if (expr->set->flags & NFT_SET_EVAL)
- printf("table %s", expr->set->handle.set);
+ octx->print(octx->ctx, "table %s", expr->set->handle.set);
else
expr_print(expr->set->init, octx);
} else {
- printf("@%s", expr->set->handle.set);
+ octx->print(octx->ctx, "@%s", expr->set->handle.set);
}
}
@@ -971,18 +971,18 @@ static void set_elem_expr_print(const struct expr *expr,
{
expr_print(expr->key, octx);
if (expr->timeout) {
- printf(" timeout ");
- time_print(expr->timeout / 1000);
+ octx->print(octx->ctx, " timeout ");
+ time_print(expr->timeout / 1000, octx);
}
if (!octx->stateless && expr->expiration) {
- printf(" expires ");
- time_print(expr->expiration / 1000);
+ octx->print(octx->ctx, " expires ");
+ time_print(expr->expiration / 1000, octx);
}
if (expr->comment)
- printf(" comment \"%s\"", expr->comment);
+ octx->print(octx->ctx, " comment \"%s\"", expr->comment);
if (expr->stmt) {
- printf(" : ");
+ octx->print(octx->ctx, " : ");
stmt_print(expr->stmt, octx);
}
}
diff --git a/src/exthdr.c b/src/exthdr.c
index a412025..21ceedd 100644
--- a/src/exthdr.c
+++ b/src/exthdr.c
@@ -33,19 +33,19 @@ static void exthdr_expr_print(const struct expr *expr, struct output_ctx *octx)
char buf[9] = {0};
if (expr->exthdr.flags & NFT_EXTHDR_F_PRESENT) {
- printf("tcp option %s", expr->exthdr.desc->name);
+ octx->print(octx->ctx, "tcp option %s", expr->exthdr.desc->name);
return;
}
if (offset)
snprintf(buf, sizeof buf, "%d", offset);
- printf("tcp option %s%s %s", expr->exthdr.desc->name, buf,
+ octx->print(octx->ctx, "tcp option %s%s %s", expr->exthdr.desc->name, buf,
expr->exthdr.tmpl->token);
} else {
if (expr->exthdr.flags & NFT_EXTHDR_F_PRESENT)
- printf("exthdr %s", expr->exthdr.desc->name);
+ octx->print(octx->ctx, "exthdr %s", expr->exthdr.desc->name);
else {
- printf("%s %s", expr->exthdr.desc ? expr->exthdr.desc->name : "unknown-exthdr",
+ octx->print(octx->ctx, "%s %s", expr->exthdr.desc ? expr->exthdr.desc->name : "unknown-exthdr",
expr->exthdr.tmpl->token);
}
}
diff --git a/src/fib.c b/src/fib.c
index b3488af..202b6b1 100644
--- a/src/fib.c
+++ b/src/fib.c
@@ -60,32 +60,33 @@ static const char *fib_result_str(enum nft_fib_result result)
return "unknown";
}
-static void __fib_expr_print_f(unsigned int *flags, unsigned int f, const char *s)
+static void __fib_expr_print_f(unsigned int *flags, unsigned int f,
+ const char *s, struct output_ctx *octx)
{
if ((*flags & f) == 0)
return;
- printf("%s", s);
+ octx->print(octx->ctx, "%s", s);
*flags &= ~f;
if (*flags)
- printf(" . ");
+ octx->print(octx->ctx, " . ");
}
static void fib_expr_print(const struct expr *expr, struct output_ctx *octx)
{
unsigned int flags = expr->fib.flags & ~NFTA_FIB_F_PRESENT;
- printf("fib ");
- __fib_expr_print_f(&flags, NFTA_FIB_F_SADDR, "saddr");
- __fib_expr_print_f(&flags, NFTA_FIB_F_DADDR, "daddr");
- __fib_expr_print_f(&flags, NFTA_FIB_F_MARK, "mark");
- __fib_expr_print_f(&flags, NFTA_FIB_F_IIF, "iif");
- __fib_expr_print_f(&flags, NFTA_FIB_F_OIF, "oif");
+ octx->print(octx->ctx, "fib ");
+ __fib_expr_print_f(&flags, NFTA_FIB_F_SADDR, "saddr", octx);
+ __fib_expr_print_f(&flags, NFTA_FIB_F_DADDR, "daddr", octx);
+ __fib_expr_print_f(&flags, NFTA_FIB_F_MARK, "mark", octx);
+ __fib_expr_print_f(&flags, NFTA_FIB_F_IIF, "iif", octx);
+ __fib_expr_print_f(&flags, NFTA_FIB_F_OIF, "oif", octx);
if (flags)
- printf("0x%x", flags);
+ octx->print(octx->ctx, "0x%x", flags);
- printf(" %s", fib_result_str(expr->fib.result));
+ octx->print(octx->ctx, " %s", fib_result_str(expr->fib.result));
}
static bool fib_expr_cmp(const struct expr *e1, const struct expr *e2)
diff --git a/src/hash.c b/src/hash.c
index 1a4bfb3..c42d360 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -19,19 +19,19 @@ static void hash_expr_print(const struct expr *expr, struct output_ctx *octx)
{
switch (expr->hash.type) {
case NFT_HASH_SYM:
- printf("symhash");
+ octx->print(octx->ctx, "symhash");
break;
case NFT_HASH_JENKINS:
default:
- printf("jhash ");
+ octx->print(octx->ctx, "jhash ");
expr_print(expr->hash.expr, octx);
}
- printf(" mod %u", expr->hash.mod);
+ octx->print(octx->ctx, " mod %u", expr->hash.mod);
if (expr->hash.seed_set)
- printf(" seed 0x%x", expr->hash.seed);
+ octx->print(octx->ctx, " seed 0x%x", expr->hash.seed);
if (expr->hash.offset)
- printf(" offset %u", expr->hash.offset);
+ octx->print(octx->ctx, " offset %u", expr->hash.offset);
}
static bool hash_expr_cmp(const struct expr *e1, const struct expr *e2)
diff --git a/src/libnftables.c b/src/libnftables.c
index 72e6efa..356e9c4 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -58,6 +58,17 @@ void nft_global_deinit(void)
mark_table_exit();
}
+__attribute__((format(printf, 2, 0)))
+static int nft_print(void *ctx, const char *fmt, ...)
+{
+ va_list arg;
+ va_start(arg, fmt);
+ vfprintf(stdout, fmt, arg);
+ va_end(arg);
+
+ return 0;
+}
+
struct nft_ctx *nft_context_new(void)
{
struct nft_ctx *ctx = NULL;
@@ -67,8 +78,11 @@ struct nft_ctx *nft_context_new(void)
memset(ctx, 0, sizeof(*ctx));
ctx->nf_sock = netlink_open_sock();
+
init_list_head(&ctx->cache.list);
+ ctx->output.ctx = ctx;
+ ctx->output.print = nft_print;
return ctx;
}
diff --git a/src/meta.c b/src/meta.c
index 9c80893..9994d57 100644
--- a/src/meta.c
+++ b/src/meta.c
@@ -54,13 +54,13 @@ static void tchandle_type_print(const struct expr *expr,
switch(handle) {
case TC_H_ROOT:
- printf("root");
+ octx->print(octx->ctx, "root");
break;
case TC_H_UNSPEC:
- printf("none");
+ octx->print(octx->ctx, "none");
break;
default:
- printf("%0x:%0x", TC_H_MAJ(handle) >> 16, TC_H_MIN(handle));
+ octx->print(octx->ctx, "%0x:%0x", TC_H_MAJ(handle) >> 16, TC_H_MIN(handle));
break;
}
}
@@ -134,9 +134,9 @@ static void ifindex_type_print(const struct expr *expr, struct output_ctx *octx)
ifindex = mpz_get_uint32(expr->value);
if (nft_if_indextoname(ifindex, name))
- printf("\"%s\"", name);
+ octx->print(octx->ctx, "\"%s\"", name);
else
- printf("%d", ifindex);
+ octx->print(octx->ctx, "%d", ifindex);
}
static struct error_record *ifindex_type_parse(const struct expr *sym,
@@ -209,9 +209,9 @@ static void uid_type_print(const struct expr *expr, struct output_ctx *octx)
pw = getpwuid(uid);
if (pw != NULL)
- printf("\"%s\"", pw->pw_name);
+ octx->print(octx->ctx, "\"%s\"", pw->pw_name);
else
- printf("%d", uid);
+ octx->print(octx->ctx, "%d", uid);
return;
}
expr_basetype(expr)->print(expr, octx);
@@ -261,9 +261,9 @@ static void gid_type_print(const struct expr *expr, struct output_ctx *octx)
gr = getgrgid(gid);
if (gr != NULL)
- printf("\"%s\"", gr->gr_name);
+ octx->print(octx->ctx, "\"%s\"", gr->gr_name);
else
- printf("%u", gid);
+ octx->print(octx->ctx, "%u", gid);
return;
}
expr_basetype(expr)->print(expr, octx);
@@ -446,9 +446,9 @@ static bool meta_key_is_qualified(enum nft_meta_keys key)
static void meta_expr_print(const struct expr *expr, struct output_ctx *octx)
{
if (meta_key_is_qualified(expr->meta.key))
- printf("meta %s", meta_templates[expr->meta.key].token);
+ octx->print(octx->ctx, "meta %s", meta_templates[expr->meta.key].token);
else
- printf("%s", meta_templates[expr->meta.key].token);
+ octx->print(octx->ctx, "%s", meta_templates[expr->meta.key].token);
}
static bool meta_expr_cmp(const struct expr *e1, const struct expr *e2)
@@ -573,9 +573,9 @@ struct expr *meta_expr_alloc(const struct location *loc, enum nft_meta_keys key)
static void meta_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
if (meta_key_is_qualified(stmt->meta.key))
- printf("meta %s set ", meta_templates[stmt->meta.key].token);
+ octx->print(octx->ctx, "meta %s set ", meta_templates[stmt->meta.key].token);
else
- printf("%s set ", meta_templates[stmt->meta.key].token);
+ octx->print(octx->ctx, "%s set ", meta_templates[stmt->meta.key].token);
expr_print(stmt->meta.expr, octx);
}
diff --git a/src/numgen.c b/src/numgen.c
index 19a4a9c..e6938ce 100644
--- a/src/numgen.c
+++ b/src/numgen.c
@@ -30,10 +30,10 @@ static const char *numgen_type_str(enum nft_ng_types type)
static void numgen_expr_print(const struct expr *expr, struct output_ctx *octx)
{
- printf("numgen %s mod %u", numgen_type_str(expr->numgen.type),
+ octx->print(octx->ctx, "numgen %s mod %u", numgen_type_str(expr->numgen.type),
expr->numgen.mod);
if (expr->numgen.offset)
- printf(" offset %u", expr->numgen.offset);
+ octx->print(octx->ctx, " offset %u", expr->numgen.offset);
}
static bool numgen_expr_cmp(const struct expr *e1, const struct expr *e2)
diff --git a/src/payload.c b/src/payload.c
index 7f94ff7..fd6cb3a 100644
--- a/src/payload.c
+++ b/src/payload.c
@@ -46,9 +46,9 @@ static void payload_expr_print(const struct expr *expr, struct output_ctx *octx)
desc = expr->payload.desc;
tmpl = expr->payload.tmpl;
if (payload_is_known(expr))
- printf("%s %s", desc->name, tmpl->token);
+ octx->print(octx->ctx, "%s %s", desc->name, tmpl->token);
else
- printf("payload @%s,%u,%u",
+ octx->print(octx->ctx, "payload @%s,%u,%u",
proto_base_tokens[expr->payload.base],
expr->payload.offset, expr->len);
}
diff --git a/src/rule.c b/src/rule.c
index ef12bec..364dd13 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -271,7 +271,8 @@ static const char *set_policy2str(uint32_t policy)
}
static void set_print_declaration(const struct set *set,
- struct print_fmt_options *opts)
+ struct print_fmt_options *opts,
+ struct output_ctx *octx)
{
const char *delim = "";
const char *type;
@@ -284,33 +285,33 @@ static void set_print_declaration(const struct set *set,
else
type = "set";
- printf("%s%s", opts->tab, type);
+ octx->print(octx->ctx, "%s%s", opts->tab, type);
if (opts->family != NULL)
- printf(" %s", opts->family);
+ octx->print(octx->ctx, " %s", opts->family);
if (opts->table != NULL)
- printf(" %s", opts->table);
+ octx->print(octx->ctx, " %s", opts->table);
- printf(" %s {%s", set->handle.set, opts->nl);
+ octx->print(octx->ctx, " %s {%s", set->handle.set, opts->nl);
- printf("%s%stype %s", opts->tab, opts->tab, set->keytype->name);
+ octx->print(octx->ctx, "%s%stype %s", opts->tab, opts->tab, set->keytype->name);
if (set->flags & NFT_SET_MAP)
- printf(" : %s", set->datatype->name);
+ octx->print(octx->ctx, " : %s", set->datatype->name);
else if (set->flags & NFT_SET_OBJECT)
- printf(" : %s", obj_type_name(set->objtype));
+ octx->print(octx->ctx, " : %s", obj_type_name(set->objtype));
- printf("%s", opts->stmt_separator);
+ octx->print(octx->ctx, "%s", opts->stmt_separator);
if (!(set->flags & (NFT_SET_CONSTANT))) {
if (set->policy != NFT_SET_POL_PERFORMANCE) {
- printf("%s%spolicy %s%s", opts->tab, opts->tab,
+ octx->print(octx->ctx, "%s%spolicy %s%s", opts->tab, opts->tab,
set_policy2str(set->policy),
opts->stmt_separator);
}
if (set->desc.size > 0) {
- printf("%s%ssize %u%s", opts->tab, opts->tab,
+ octx->print(octx->ctx, "%s%ssize %u%s", opts->tab, opts->tab,
set->desc.size, opts->stmt_separator);
}
}
@@ -321,45 +322,45 @@ static void set_print_declaration(const struct set *set,
flags &= ~NFT_SET_TIMEOUT;
if (flags & (NFT_SET_CONSTANT | NFT_SET_INTERVAL | NFT_SET_TIMEOUT)) {
- printf("%s%sflags ", opts->tab, opts->tab);
+ octx->print(octx->ctx, "%s%sflags ", opts->tab, opts->tab);
if (set->flags & NFT_SET_CONSTANT) {
- printf("%sconstant", delim);
+ octx->print(octx->ctx, "%sconstant", delim);
delim = ",";
}
if (set->flags & NFT_SET_INTERVAL) {
- printf("%sinterval", delim);
+ octx->print(octx->ctx, "%sinterval", delim);
delim = ",";
}
if (set->flags & NFT_SET_TIMEOUT) {
- printf("%stimeout", delim);
+ octx->print(octx->ctx, "%stimeout", delim);
delim = ",";
}
- printf("%s", opts->stmt_separator);
+ octx->print(octx->ctx, "%s", opts->stmt_separator);
}
if (set->timeout) {
- printf("%s%stimeout ", opts->tab, opts->tab);
- time_print(set->timeout / 1000);
- printf("%s", opts->stmt_separator);
+ octx->print(octx->ctx, "%s%stimeout ", opts->tab, opts->tab);
+ time_print(set->timeout / 1000, octx);
+ octx->print(octx->ctx, "%s", opts->stmt_separator);
}
if (set->gc_int) {
- printf("%s%sgc-interval ", opts->tab, opts->tab);
- time_print(set->gc_int / 1000);
- printf("%s", opts->stmt_separator);
+ octx->print(octx->ctx, "%s%sgc-interval ", opts->tab, opts->tab);
+ time_print(set->gc_int / 1000, octx);
+ octx->print(octx->ctx, "%s", opts->stmt_separator);
}
}
static void do_set_print(const struct set *set, struct print_fmt_options *opts,
struct output_ctx *octx)
{
- set_print_declaration(set, opts);
+ set_print_declaration(set, opts, octx);
if (set->init != NULL && set->init->size > 0) {
- printf("%s%selements = ", opts->tab, opts->tab);
+ octx->print(octx->ctx, "%s%selements = ", opts->tab, opts->tab);
expr_print(set->init, octx);
- printf("%s", opts->nl);
+ octx->print(octx->ctx, "%s", opts->nl);
}
- printf("%s}%s", opts->tab, opts->nl);
+ octx->print(octx->ctx, "%s}%s", opts->tab, opts->nl);
}
void set_print(const struct set *s, struct output_ctx *octx)
@@ -424,14 +425,14 @@ void rule_print(const struct rule *rule, struct output_ctx *octx)
list_for_each_entry(stmt, &rule->stmts, list) {
stmt->ops->print(stmt, octx);
if (!list_is_last(&stmt->list, &rule->stmts))
- printf(" ");
+ octx->print(octx->ctx, " ");
}
if (rule->comment)
- printf(" comment \"%s\"", rule->comment);
+ octx->print(octx->ctx, " comment \"%s\"", rule->comment);
if (octx->handle > 0)
- printf(" # handle %" PRIu64, rule->handle.handle.id);
+ octx->print(octx->ctx, " # handle %" PRIu64, rule->handle.handle.id);
}
struct rule *rule_lookup(const struct chain *chain, uint64_t handle)
@@ -661,18 +662,19 @@ static const char *chain_policy2str(uint32_t policy)
return "unknown";
}
-static void chain_print_declaration(const struct chain *chain)
+static void chain_print_declaration(const struct chain *chain,
+ struct output_ctx *octx)
{
- printf("\tchain %s {\n", chain->handle.chain);
+ octx->print(octx->ctx, "\tchain %s {\n", chain->handle.chain);
if (chain->flags & CHAIN_F_BASECHAIN) {
if (chain->dev != NULL) {
- printf("\t\ttype %s hook %s device %s priority %d; policy %s;\n",
+ octx->print(octx->ctx, "\t\ttype %s hook %s device %s priority %d; policy %s;\n",
chain->type,
hooknum2str(chain->handle.family, chain->hooknum),
chain->dev, chain->priority,
chain_policy2str(chain->policy));
} else {
- printf("\t\ttype %s hook %s priority %d; policy %s;\n",
+ octx->print(octx->ctx, "\t\ttype %s hook %s priority %d; policy %s;\n",
chain->type,
hooknum2str(chain->handle.family, chain->hooknum),
chain->priority, chain_policy2str(chain->policy));
@@ -684,14 +686,14 @@ static void chain_print(const struct chain *chain, struct output_ctx *octx)
{
struct rule *rule;
- chain_print_declaration(chain);
+ chain_print_declaration(chain, octx);
list_for_each_entry(rule, &chain->rules, list) {
- printf("\t\t");
+ octx->print(octx->ctx, "\t\t");
rule_print(rule, octx);
- printf("\n");
+ octx->print(octx->ctx, "\n");
}
- printf("\t}\n");
+ octx->print(octx->ctx, "\t}\n");
}
void chain_print_plain(const struct chain *chain)
@@ -796,27 +798,27 @@ static void table_print(const struct table *table, struct output_ctx *octx)
const char *delim = "";
const char *family = family2str(table->handle.family);
- printf("table %s %s {\n", family, table->handle.table);
+ octx->print(octx->ctx, "table %s %s {\n", family, table->handle.table);
table_print_options(table, &delim);
list_for_each_entry(obj, &table->objs, list) {
- printf("%s", delim);
+ octx->print(octx->ctx, "%s", delim);
obj_print(obj, octx);
delim = "\n";
}
list_for_each_entry(set, &table->sets, list) {
if (set->flags & NFT_SET_ANONYMOUS)
continue;
- printf("%s", delim);
+ octx->print(octx->ctx, "%s", delim);
set_print(set, octx);
delim = "\n";
}
list_for_each_entry(chain, &table->chains, list) {
- printf("%s", delim);
+ octx->print(octx->ctx, "%s", delim);
chain_print(chain, octx);
delim = "\n";
}
- printf("}\n");
+ octx->print(octx->ctx, "}\n");
}
struct cmd *cmd_alloc(enum cmd_ops op, enum cmd_obj obj,
@@ -1176,7 +1178,7 @@ static int do_list_sets(struct netlink_ctx *ctx, struct cmd *cmd)
cmd->handle.family != table->handle.family)
continue;
- printf("table %s %s {\n",
+ ctx->octx->print(ctx->octx->ctx, "table %s %s {\n",
family2str(table->handle.family),
table->handle.table);
@@ -1191,11 +1193,12 @@ static int do_list_sets(struct netlink_ctx *ctx, struct cmd *cmd)
if (cmd->obj == CMD_OBJ_MAPS &&
!(set->flags & NFT_SET_MAP))
continue;
- set_print_declaration(set, &opts);
- printf("%s}%s", opts.tab, opts.nl);
+ set_print_declaration(set, &opts, ctx->octx);
+ ctx->octx->print(ctx->octx->ctx, "%s}%s",
+ opts.tab, opts.nl);
}
- printf("}\n");
+ ctx->octx->print(ctx->octx->ctx, "}\n");
}
return 0;
}
@@ -1260,40 +1263,40 @@ static void obj_print_data(const struct obj *obj,
{
switch (obj->type) {
case NFT_OBJECT_COUNTER:
- printf(" %s {%s%s%s", obj->handle.obj,
+ octx->print(octx->ctx, " %s {%s%s%s", obj->handle.obj,
opts->nl, opts->tab, opts->tab);
if (octx->stateless) {
- printf("packets 0 bytes 0");
+ octx->print(octx->ctx, "packets 0 bytes 0");
break;
}
- printf("packets %"PRIu64" bytes %"PRIu64"",
+ octx->print(octx->ctx, "packets %"PRIu64" bytes %"PRIu64"",
obj->counter.packets, obj->counter.bytes);
break;
case NFT_OBJECT_QUOTA: {
const char *data_unit;
uint64_t bytes;
- printf(" %s {%s%s%s", obj->handle.obj,
+ octx->print(octx->ctx, " %s {%s%s%s", obj->handle.obj,
opts->nl, opts->tab, opts->tab);
data_unit = get_rate(obj->quota.bytes, &bytes);
- printf("%s%"PRIu64" %s",
+ octx->print(octx->ctx, "%s%"PRIu64" %s",
obj->quota.flags & NFT_QUOTA_F_INV ? "over " : "",
bytes, data_unit);
if (!octx->stateless && obj->quota.used) {
data_unit = get_rate(obj->quota.used, &bytes);
- printf(" used %"PRIu64" %s", bytes, data_unit);
+ octx->print(octx->ctx, " used %"PRIu64" %s", bytes, data_unit);
}
}
break;
case NFT_OBJECT_CT_HELPER: {
- printf("ct helper %s {\n", obj->handle.obj);
- printf("\t\ttype \"%s\" protocol ", obj->ct_helper.name);
+ octx->print(octx->ctx, "ct helper %s {\n", obj->handle.obj);
+ octx->print(octx->ctx, "\t\ttype \"%s\" protocol ", obj->ct_helper.name);
print_proto_name_proto(obj->ct_helper.l4proto);
- printf("\t\tl3proto %s", family2str(obj->ct_helper.l3proto));
+ octx->print(octx->ctx, "\t\tl3proto %s", family2str(obj->ct_helper.l3proto));
break;
}
default:
- printf("unknown {%s", opts->nl);
+ octx->print(octx->ctx, "unknown {%s", opts->nl);
break;
}
}
@@ -1328,17 +1331,17 @@ static void obj_print_declaration(const struct obj *obj,
struct print_fmt_options *opts,
struct output_ctx *octx)
{
- printf("%s%s", opts->tab, obj_type_name(obj->type));
+ octx->print(octx->ctx, "%s%s", opts->tab, obj_type_name(obj->type));
if (opts->family != NULL)
- printf(" %s", opts->family);
+ octx->print(octx->ctx, " %s", opts->family);
if (opts->table != NULL)
- printf(" %s", opts->table);
+ octx->print(octx->ctx, " %s", opts->table);
obj_print_data(obj, opts, octx);
- printf("%s%s}%s", opts->nl, opts->tab, opts->nl);
+ octx->print(octx->ctx, "%s%s}%s", opts->nl, opts->tab, opts->nl);
}
void obj_print(const struct obj *obj, struct output_ctx *octx)
@@ -1379,13 +1382,13 @@ static int do_list_obj(struct netlink_ctx *ctx, struct cmd *cmd, uint32_t type)
cmd->handle.family != table->handle.family)
continue;
- printf("table %s %s {\n",
+ ctx->octx->print(ctx->octx->ctx, "table %s %s {\n",
family2str(table->handle.family),
table->handle.table);
if (cmd->handle.table != NULL &&
strcmp(cmd->handle.table, table->handle.table)) {
- printf("}\n");
+ ctx->octx->print(ctx->octx->ctx, "}\n");
continue;
}
@@ -1398,7 +1401,7 @@ static int do_list_obj(struct netlink_ctx *ctx, struct cmd *cmd, uint32_t type)
obj_print_declaration(obj, &opts, ctx->octx);
}
- printf("}\n");
+ ctx->octx->print(ctx->octx->ctx, "}\n");
}
return 0;
}
@@ -1434,7 +1437,7 @@ static int do_list_tables(struct netlink_ctx *ctx, struct cmd *cmd)
cmd->handle.family != table->handle.family)
continue;
- printf("table %s %s\n",
+ ctx->octx->print(ctx->octx->ctx, "table %s %s\n",
family2str(table->handle.family),
table->handle.table);
}
@@ -1442,9 +1445,10 @@ static int do_list_tables(struct netlink_ctx *ctx, struct cmd *cmd)
return 0;
}
-static void table_print_declaration(struct table *table)
+static void table_print_declaration(struct table *table,
+ struct output_ctx *octx)
{
- printf("table %s %s {\n",
+ octx->print(octx->ctx, "table %s %s {\n",
family2str(table->handle.family),
table->handle.table);
}
@@ -1454,7 +1458,7 @@ static int do_list_chain(struct netlink_ctx *ctx, struct cmd *cmd,
{
struct chain *chain;
- table_print_declaration(table);
+ table_print_declaration(table, ctx->octx);
list_for_each_entry(chain, &table->chains, list) {
if (chain->handle.family != cmd->handle.family ||
@@ -1464,7 +1468,7 @@ static int do_list_chain(struct netlink_ctx *ctx, struct cmd *cmd,
chain_print(chain, ctx->octx);
}
- printf("}\n");
+ ctx->octx->print(ctx->octx->ctx, "}\n");
return 0;
}
@@ -1479,13 +1483,13 @@ static int do_list_chains(struct netlink_ctx *ctx, struct cmd *cmd)
cmd->handle.family != table->handle.family)
continue;
- table_print_declaration(table);
+ table_print_declaration(table, ctx->octx);
list_for_each_entry(chain, &table->chains, list) {
- chain_print_declaration(chain);
- printf("\t}\n");
+ chain_print_declaration(chain, ctx->octx);
+ ctx->octx->print(ctx->octx->ctx, "\t}\n");
}
- printf("}\n");
+ ctx->octx->print(ctx->octx->ctx, "}\n");
}
return 0;
@@ -1500,9 +1504,9 @@ static int do_list_set(struct netlink_ctx *ctx, struct cmd *cmd,
if (set == NULL)
return -1;
- table_print_declaration(table);
+ table_print_declaration(table, ctx->octx);
set_print(set, ctx->octx);
- printf("}\n");
+ ctx->octx->print(ctx->octx->ctx, "}\n");
return 0;
}
@@ -1689,9 +1693,10 @@ static int do_command_monitor(struct netlink_ctx *ctx, struct cmd *cmd)
return netlink_monitor(&monhandler, ctx->nf_sock);
}
-static int do_command_describe(struct netlink_ctx *ctx, struct cmd *cmd)
+static int do_command_describe(struct netlink_ctx *ctx, struct cmd *cmd,
+ struct output_ctx *octx)
{
- expr_describe(cmd->expr);
+ expr_describe(cmd->expr, octx);
return 0;
}
@@ -1737,7 +1742,7 @@ int do_command(struct netlink_ctx *ctx, struct cmd *cmd)
case CMD_MONITOR:
return do_command_monitor(ctx, cmd);
case CMD_DESCRIBE:
- return do_command_describe(ctx, cmd);
+ return do_command_describe(ctx, cmd, ctx->octx);
default:
BUG("invalid command object type %u\n", cmd->obj);
}
diff --git a/src/statement.c b/src/statement.c
index 0ce875e..bb9b862 100644
--- a/src/statement.c
+++ b/src/statement.c
@@ -109,20 +109,20 @@ struct stmt *verdict_stmt_alloc(const struct location *loc, struct expr *expr)
static void flow_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
- printf("flow ");
+ octx->print(octx->ctx, "flow ");
if (stmt->flow.set) {
expr_print(stmt->flow.set, octx);
- printf(" ");
+ octx->print(octx->ctx, " ");
}
- printf("{ ");
+ octx->print(octx->ctx, "{ ");
expr_print(stmt->flow.key, octx);
- printf(" ");
+ octx->print(octx->ctx, " ");
octx->stateless++;
stmt_print(stmt->flow.stmt, octx);
octx->stateless--;
- printf("} ");
+ octx->print(octx->ctx, "} ");
}
@@ -147,12 +147,12 @@ struct stmt *flow_stmt_alloc(const struct location *loc)
static void counter_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
- printf("counter");
+ octx->print(octx->ctx, "counter");
if (octx->stateless)
return;
- printf(" packets %" PRIu64 " bytes %" PRIu64,
+ octx->print(octx->ctx, " packets %" PRIu64 " bytes %" PRIu64,
stmt->counter.packets, stmt->counter.bytes);
}
@@ -189,10 +189,10 @@ static void objref_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
switch (stmt->objref.type) {
case NFT_OBJECT_CT_HELPER:
- printf("ct helper set ");
+ octx->print(octx->ctx, "ct helper set ");
break;
default:
- printf("%s name ", objref_type_name(stmt->objref.type));
+ octx->print(octx->ctx, "%s name ", objref_type_name(stmt->objref.type));
break;
}
expr_print(stmt->objref.expr, octx);
@@ -233,39 +233,39 @@ static const char *log_level(uint32_t level)
static void log_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
- printf("log");
+ octx->print(octx->ctx, "log");
if (stmt->log.flags & STMT_LOG_PREFIX)
- printf(" prefix \"%s\"", stmt->log.prefix);
+ octx->print(octx->ctx, " prefix \"%s\"", stmt->log.prefix);
if (stmt->log.flags & STMT_LOG_GROUP)
- printf(" group %u", stmt->log.group);
+ octx->print(octx->ctx, " group %u", stmt->log.group);
if (stmt->log.flags & STMT_LOG_SNAPLEN)
- printf(" snaplen %u", stmt->log.snaplen);
+ octx->print(octx->ctx, " snaplen %u", stmt->log.snaplen);
if (stmt->log.flags & STMT_LOG_QTHRESHOLD)
- printf(" queue-threshold %u", stmt->log.qthreshold);
+ octx->print(octx->ctx, " queue-threshold %u", stmt->log.qthreshold);
if ((stmt->log.flags & STMT_LOG_LEVEL) &&
stmt->log.level != LOG_WARNING)
- printf(" level %s", log_level(stmt->log.level));
+ octx->print(octx->ctx, " level %s", log_level(stmt->log.level));
if ((stmt->log.logflags & NF_LOG_MASK) == NF_LOG_MASK) {
- printf(" flags all");
+ octx->print(octx->ctx, " flags all");
} else {
if (stmt->log.logflags & (NF_LOG_TCPSEQ | NF_LOG_TCPOPT)) {
const char *delim = " ";
- printf(" flags tcp");
+ octx->print(octx->ctx, " flags tcp");
if (stmt->log.logflags & NF_LOG_TCPSEQ) {
- printf(" sequence");
+ octx->print(octx->ctx, " sequence");
delim = ",";
}
if (stmt->log.logflags & NF_LOG_TCPOPT)
- printf("%soptions", delim);
+ octx->print(octx->ctx, "%soptions", delim);
}
if (stmt->log.logflags & NF_LOG_IPOPT)
- printf(" flags ip options");
+ octx->print(octx->ctx, " flags ip options");
if (stmt->log.logflags & NF_LOG_UID)
- printf(" flags skuid");
+ octx->print(octx->ctx, " flags skuid");
if (stmt->log.logflags & NF_LOG_MACDECODE)
- printf(" flags ether");
+ octx->print(octx->ctx, " flags ether");
}
}
@@ -328,23 +328,23 @@ static void limit_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
switch (stmt->limit.type) {
case NFT_LIMIT_PKTS:
- printf("limit rate %s%" PRIu64 "/%s",
+ octx->print(octx->ctx, "limit rate %s%" PRIu64 "/%s",
inv ? "over " : "", stmt->limit.rate,
get_unit(stmt->limit.unit));
if (stmt->limit.burst > 0)
- printf(" burst %u packets", stmt->limit.burst);
+ octx->print(octx->ctx, " burst %u packets", stmt->limit.burst);
break;
case NFT_LIMIT_PKT_BYTES:
data_unit = get_rate(stmt->limit.rate, &rate);
- printf("limit rate %s%" PRIu64 " %s/%s",
+ octx->print(octx->ctx, "limit rate %s%" PRIu64 " %s/%s",
inv ? "over " : "", rate, data_unit,
get_unit(stmt->limit.unit));
if (stmt->limit.burst > 0) {
uint64_t burst;
data_unit = get_rate(stmt->limit.burst, &burst);
- printf(" burst %"PRIu64" %s", burst, data_unit);
+ octx->print(octx->ctx, " burst %"PRIu64" %s", burst, data_unit);
}
break;
}
@@ -369,17 +369,17 @@ static void queue_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
const char *delim = " ";
- printf("queue");
+ octx->print(octx->ctx, "queue");
if (stmt->queue.queue != NULL) {
- printf(" num ");
+ octx->print(octx->ctx, " num ");
expr_print(stmt->queue.queue, octx);
}
if (stmt->queue.flags & NFT_QUEUE_FLAG_BYPASS) {
- printf("%sbypass", delim);
+ octx->print(octx->ctx, "%sbypass", delim);
delim = ",";
}
if (stmt->queue.flags & NFT_QUEUE_FLAG_CPU_FANOUT)
- printf("%sfanout", delim);
+ octx->print(octx->ctx, "%sfanout", delim);
}
@@ -401,12 +401,12 @@ static void quota_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
uint64_t bytes, used;
data_unit = get_rate(stmt->quota.bytes, &bytes);
- printf("quota %s%"PRIu64" %s",
+ octx->print(octx->ctx, "quota %s%"PRIu64" %s",
inv ? "over " : "", bytes, data_unit);
if (!octx->stateless && stmt->quota.used) {
data_unit = get_rate(stmt->quota.used, &used);
- printf(" used %"PRIu64" %s", used, data_unit);
+ octx->print(octx->ctx, " used %"PRIu64" %s", used, data_unit);
}
}
@@ -427,15 +427,15 @@ struct stmt *quota_stmt_alloc(const struct location *loc)
static void reject_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
- printf("reject");
+ octx->print(octx->ctx, "reject");
switch (stmt->reject.type) {
case NFT_REJECT_TCP_RST:
- printf(" with tcp reset");
+ octx->print(octx->ctx, " with tcp reset");
break;
case NFT_REJECT_ICMPX_UNREACH:
if (stmt->reject.icmp_code == NFT_REJECT_ICMPX_PORT_UNREACH)
break;
- printf(" with icmpx type ");
+ octx->print(octx->ctx, " with icmpx type ");
expr_print(stmt->reject.expr, octx);
break;
case NFT_REJECT_ICMP_UNREACH:
@@ -443,13 +443,13 @@ static void reject_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
case NFPROTO_IPV4:
if (stmt->reject.icmp_code == ICMP_PORT_UNREACH)
break;
- printf(" with icmp type ");
+ octx->print(octx->ctx, " with icmp type ");
expr_print(stmt->reject.expr, octx);
break;
case NFPROTO_IPV6:
if (stmt->reject.icmp_code == ICMP6_DST_UNREACH_NOPORT)
break;
- printf(" with icmpv6 type ");
+ octx->print(octx->ctx, " with icmpv6 type ");
expr_print(stmt->reject.expr, octx);
break;
}
@@ -468,7 +468,7 @@ struct stmt *reject_stmt_alloc(const struct location *loc)
return stmt_alloc(loc, &reject_stmt_ops);
}
-static void print_nf_nat_flags(uint32_t flags)
+static void print_nf_nat_flags(uint32_t flags, struct output_ctx *octx)
{
const char *delim = " ";
@@ -476,17 +476,17 @@ static void print_nf_nat_flags(uint32_t flags)
return;
if (flags & NF_NAT_RANGE_PROTO_RANDOM) {
- printf("%srandom", delim);
+ octx->print(octx->ctx, "%srandom", delim);
delim = ",";
}
if (flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY) {
- printf("%sfully-random", delim);
+ octx->print(octx->ctx, "%sfully-random", delim);
delim = ",";
}
if (flags & NF_NAT_RANGE_PERSISTENT)
- printf("%spersistent", delim);
+ octx->print(octx->ctx, "%spersistent", delim);
}
static void nat_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
@@ -496,21 +496,21 @@ static void nat_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
[NFT_NAT_DNAT] = "dnat",
};
- printf("%s to ", nat_types[stmt->nat.type]);
+ octx->print(octx->ctx, "%s to ", nat_types[stmt->nat.type]);
if (stmt->nat.addr) {
if (stmt->nat.proto) {
if (stmt->nat.addr->ops->type == EXPR_VALUE &&
stmt->nat.addr->dtype->type == TYPE_IP6ADDR) {
- printf("[");
+ octx->print(octx->ctx, "[");
expr_print(stmt->nat.addr, octx);
- printf("]");
+ octx->print(octx->ctx, "]");
} else if (stmt->nat.addr->ops->type == EXPR_RANGE &&
stmt->nat.addr->left->dtype->type == TYPE_IP6ADDR) {
- printf("[");
+ octx->print(octx->ctx, "[");
expr_print(stmt->nat.addr->left, octx);
- printf("]-[");
+ octx->print(octx->ctx, "]-[");
expr_print(stmt->nat.addr->right, octx);
- printf("]");
+ octx->print(octx->ctx, "]");
} else {
expr_print(stmt->nat.addr, octx);
}
@@ -520,11 +520,11 @@ static void nat_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
}
if (stmt->nat.proto) {
- printf(":");
+ octx->print(octx->ctx, ":");
expr_print(stmt->nat.proto, octx);
}
- print_nf_nat_flags(stmt->nat.flags);
+ print_nf_nat_flags(stmt->nat.flags, octx);
}
static void nat_stmt_destroy(struct stmt *stmt)
@@ -547,14 +547,14 @@ struct stmt *nat_stmt_alloc(const struct location *loc)
static void masq_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
- printf("masquerade");
+ octx->print(octx->ctx, "masquerade");
if (stmt->masq.proto) {
- printf(" to :");
+ octx->print(octx->ctx, " to :");
expr_print(stmt->masq.proto, octx);
}
- print_nf_nat_flags(stmt->masq.flags);
+ print_nf_nat_flags(stmt->masq.flags, octx);
}
static void masq_stmt_destroy(struct stmt *stmt)
@@ -576,14 +576,14 @@ struct stmt *masq_stmt_alloc(const struct location *loc)
static void redir_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
- printf("redirect");
+ octx->print(octx->ctx, "redirect");
if (stmt->redir.proto) {
- printf(" to :");
+ octx->print(octx->ctx, " to :");
expr_print(stmt->redir.proto, octx);
}
- print_nf_nat_flags(stmt->redir.flags);
+ print_nf_nat_flags(stmt->redir.flags, octx);
}
static void redir_stmt_destroy(struct stmt *stmt)
@@ -610,9 +610,9 @@ static const char * const set_stmt_op_names[] = {
static void set_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
- printf("set %s ", set_stmt_op_names[stmt->set.op]);
+ octx->print(octx->ctx, "set %s ", set_stmt_op_names[stmt->set.op]);
expr_print(stmt->set.key, octx);
- printf(" ");
+ octx->print(octx->ctx, " ");
expr_print(stmt->set.set, octx);
}
@@ -636,13 +636,13 @@ struct stmt *set_stmt_alloc(const struct location *loc)
static void dup_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
- printf("dup");
+ octx->print(octx->ctx, "dup");
if (stmt->dup.to != NULL) {
- printf(" to ");
+ octx->print(octx->ctx, " to ");
expr_print(stmt->dup.to, octx);
if (stmt->dup.dev != NULL) {
- printf(" device ");
+ octx->print(octx->ctx, " device ");
expr_print(stmt->dup.dev, octx);
}
}
@@ -668,7 +668,7 @@ struct stmt *dup_stmt_alloc(const struct location *loc)
static void fwd_stmt_print(const struct stmt *stmt, struct output_ctx *octx)
{
- printf("fwd to ");
+ octx->print(octx->ctx, "fwd to ");
expr_print(stmt->fwd.to, octx);
}
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 11/16] libnftables: add nft_context_set_print
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
` (9 preceding siblings ...)
2017-08-16 20:43 ` [nft PATH 10/16] libnftables: get rid of printf Eric Leblond
@ 2017-08-16 20:43 ` Eric Leblond
2017-08-16 20:43 ` [nft PATH 12/16] libnftables: transaction support Eric Leblond
` (5 subsequent siblings)
16 siblings, 0 replies; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:43 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
This function allows user to set his own printing function. It is
still dependant of the format used by nft but at least it can be
redirected easily.
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/nftables/nftables.h | 3 +++
src/libnftables.c | 9 +++++++++
2 files changed, 12 insertions(+)
diff --git a/include/nftables/nftables.h b/include/nftables/nftables.h
index b902cbd..935d0db 100644
--- a/include/nftables/nftables.h
+++ b/include/nftables/nftables.h
@@ -26,6 +26,9 @@ void nft_global_deinit(void);
struct nft_ctx *nft_context_new(void);
void nft_context_free(struct nft_ctx *nft);
+void nft_context_set_print_func(struct nft_ctx *nft,
+ int (*print)(void *ctx, const char *fmt, ...),
+ void *ctx);
int nft_run_command_from_buffer(struct nft_ctx *nft,
char *buf, size_t buflen);
diff --git a/src/libnftables.c b/src/libnftables.c
index 356e9c4..494ff57 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -86,6 +86,15 @@ struct nft_ctx *nft_context_new(void)
return ctx;
}
+void nft_context_set_print_func(struct nft_ctx *nft,
+ int (*print)(void *ctx, const char *fmt, ...),
+ void *ctx)
+{
+ if (nft) {
+ nft->output.print = print;
+ nft->output.ctx = ctx;
+ }
+}
void nft_context_free(struct nft_ctx *nft)
{
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 12/16] libnftables: transaction support
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
` (10 preceding siblings ...)
2017-08-16 20:43 ` [nft PATH 11/16] libnftables: add nft_context_set_print Eric Leblond
@ 2017-08-16 20:43 ` Eric Leblond
2017-08-17 10:11 ` Phil Sutter
2017-08-16 20:43 ` [nft PATH 13/16] libnftables: set max_errors to 1 in library Eric Leblond
` (4 subsequent siblings)
16 siblings, 1 reply; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:43 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
Add batch support for libnftables. This patch
provides a set of function to handle batch command.
The cinematic is the following:
* nft_batch_start to allocate the batch structure
* multiple call to nft_batch_add
* nft_batch_commit to do the commit to kernel
* nft_batch_free to free the batch
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/netlink.h | 5 +++
include/nftables/nftables.h | 7 ++++
src/libnftables.c | 89 +++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 101 insertions(+)
diff --git a/include/netlink.h b/include/netlink.h
index 0e1d26b..b7f87c0 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -54,6 +54,11 @@ struct netlink_ctx {
struct nft_cache *cache;
};
+struct nft_batch {
+ struct netlink_ctx nl_ctx;
+ struct nftnl_batch *batch;
+};
+
extern struct nftnl_table *alloc_nftnl_table(const struct handle *h);
extern struct nftnl_chain *alloc_nftnl_chain(const struct handle *h);
extern struct nftnl_rule *alloc_nftnl_rule(const struct handle *h);
diff --git a/include/nftables/nftables.h b/include/nftables/nftables.h
index 935d0db..2ddb38a 100644
--- a/include/nftables/nftables.h
+++ b/include/nftables/nftables.h
@@ -34,4 +34,11 @@ int nft_run_command_from_buffer(struct nft_ctx *nft,
char *buf, size_t buflen);
int nft_run_command_from_filename(struct nft_ctx *nft, const char *filename);
+
+struct nft_batch *nft_batch_start(struct nft_ctx *ctx);
+int nft_batch_add(struct nft_ctx *ctx, struct nft_batch *batch,
+ const char * buf, size_t buflen);
+int nft_batch_commit(struct nft_ctx *ctx, struct nft_batch *batch);
+void nft_batch_free(struct nft_batch *batch);
+
#endif
diff --git a/src/libnftables.c b/src/libnftables.c
index 494ff57..08050e5 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -151,3 +151,92 @@ int nft_run_command_from_filename(struct nft_ctx *nft, const char *filename)
erec_print_list(stderr, &msgs);
return rc;
}
+
+struct nft_batch *nft_batch_start(struct nft_ctx *nft)
+{
+ struct nft_batch *batch = malloc(sizeof(*batch));
+ if (batch == NULL)
+ return NULL;
+
+ batch->batch = mnl_batch_init();
+ mnl_batch_begin(batch->batch, mnl_seqnum_alloc(&nft->cache.seqnum));
+
+ return batch;
+}
+
+int nft_batch_add(struct nft_ctx *nft, struct nft_batch *batch,
+ const char * buf, size_t buflen)
+{
+ int rc = NFT_EXIT_SUCCESS;
+ int ret = 0;
+ struct parser_state state;
+ LIST_HEAD(msgs);
+ void *scanner;
+ struct cmd *cmd, *next;
+ struct netlink_ctx *ctx = &batch->nl_ctx;
+ uint32_t seqnum;
+ bool batch_supported = netlink_batch_supported(nft->nf_sock, &seqnum);
+
+ parser_init(nft->nf_sock, &nft->cache, &state, &msgs);
+ scanner = scanner_init(&state);
+ scanner_push_buffer(scanner, &indesc_cmdline, buf);
+
+ ret = nft_parse(scanner, &state);
+ if (ret != 0 || state.nerrs > 0) {
+ rc = -1;
+ goto err1;
+ }
+
+ list_for_each_entry(cmd, &state.cmds, list) {
+ nft_cmd_expand(cmd);
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->msgs = &msgs;
+ ctx->seqnum = cmd->seqnum = mnl_seqnum_alloc(&seqnum);
+ ctx->batch = batch->batch;
+ ctx->batch_supported = batch_supported;
+ ctx->octx = &nft->output;
+ ctx->nf_sock = nft->nf_sock;
+ ctx->cache = &nft->cache;
+ init_list_head(&ctx->list);
+ ret = do_command(ctx, cmd);
+ if (ret < 0)
+ return -1;
+ }
+
+ list_for_each_entry_safe(cmd, next, &state.cmds, list) {
+ list_del(&cmd->list);
+ cmd_free(cmd);
+ }
+err1:
+ scanner_destroy(scanner);
+ erec_print_list(stderr, &msgs);
+ return rc;
+}
+
+int nft_batch_commit(struct nft_ctx *nft, struct nft_batch *batch)
+{
+ int ret = 0;
+
+ mnl_batch_end(batch->batch, mnl_seqnum_alloc(&nft->cache.seqnum));
+ LIST_HEAD(err_list);
+
+ if (!mnl_batch_ready(batch->batch))
+ goto out;
+
+ batch->nl_ctx.batch = batch->batch;
+ if (!mnl_batch_ready(batch->batch))
+ goto out;
+
+ ret = netlink_batch_send(&batch->nl_ctx, &err_list);
+out:
+ return ret;
+
+}
+
+void nft_batch_free(struct nft_batch *batch)
+{
+ if (batch == NULL)
+ return;
+ mnl_batch_reset(batch->batch);
+ xfree(batch);
+}
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 13/16] libnftables: set max_errors to 1 in library
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
` (11 preceding siblings ...)
2017-08-16 20:43 ` [nft PATH 12/16] libnftables: transaction support Eric Leblond
@ 2017-08-16 20:43 ` Eric Leblond
2017-08-16 20:43 ` [nft PATH 14/16] erec: add function to free list Eric Leblond
` (3 subsequent siblings)
16 siblings, 0 replies; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:43 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
As memory handling is defficient if we don't do so, we can't really
use a non 1 value for the parameter in the library due to memory
leak.
Also this is not a real issue as programmatically a user of the
library should only encounter one error at a time.
This patch also introduces a function that can be used to modify
the max_errors parameter. It is used in main to keep the existing
behavior.
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/nftables/nftables.h | 1 +
src/libnftables.c | 8 +++++++-
src/main.c | 1 +
3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/include/nftables/nftables.h b/include/nftables/nftables.h
index 2ddb38a..f419884 100644
--- a/include/nftables/nftables.h
+++ b/include/nftables/nftables.h
@@ -22,6 +22,7 @@ enum nftables_exit_codes {
};
void nft_global_init(void);
+int nft_global_set_max_errors(unsigned int errors);
void nft_global_deinit(void);
struct nft_ctx *nft_context_new(void);
diff --git a/src/libnftables.c b/src/libnftables.c
index 08050e5..c50c068 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -25,7 +25,7 @@
#include <fcntl.h>
-unsigned int max_errors = 10;
+unsigned int max_errors = 1;
unsigned int numeric_output;
unsigned int ip2name_output;
unsigned int handle_output;
@@ -58,6 +58,12 @@ void nft_global_deinit(void)
mark_table_exit();
}
+int nft_global_set_max_errors(unsigned int errors)
+{
+ max_errors = errors;
+ return 0;
+}
+
__attribute__((format(printf, 2, 0)))
static int nft_print(void *ctx, const char *fmt, ...)
{
diff --git a/src/main.c b/src/main.c
index a6305cc..bb08c31 100644
--- a/src/main.c
+++ b/src/main.c
@@ -192,6 +192,7 @@ int main(int argc, char * const *argv)
struct nft_ctx *nft;
nft_global_init();
+ nft_global_set_max_errors(10);
nft = nft_context_new();
while (1) {
val = getopt_long(argc, argv, OPTSTRING, options, NULL);
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 14/16] erec: add function to free list
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
` (12 preceding siblings ...)
2017-08-16 20:43 ` [nft PATH 13/16] libnftables: set max_errors to 1 in library Eric Leblond
@ 2017-08-16 20:43 ` Eric Leblond
2017-08-16 20:43 ` [nft PATH 15/16] libnftables: add error handling Eric Leblond
` (2 subsequent siblings)
16 siblings, 0 replies; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:43 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/erec.h | 1 +
src/erec.c | 10 ++++++++++
2 files changed, 11 insertions(+)
diff --git a/include/erec.h b/include/erec.h
index 36e0efa..befc274 100644
--- a/include/erec.h
+++ b/include/erec.h
@@ -60,6 +60,7 @@ static inline void erec_queue(struct error_record *erec,
extern void erec_print(FILE *f, const struct error_record *erec);
extern void erec_print_list(FILE *f, struct list_head *list);
+void erec_free_list(struct list_head *list);
struct eval_ctx;
diff --git a/src/erec.c b/src/erec.c
index 439add9..f454d34 100644
--- a/src/erec.c
+++ b/src/erec.c
@@ -213,6 +213,16 @@ void erec_print_list(FILE *f, struct list_head *list)
}
}
+void erec_free_list(struct list_head *list)
+{
+ struct error_record *erec, *next;
+
+ list_for_each_entry_safe(erec, next, list, list) {
+ list_del(&erec->list);
+ erec_destroy(erec);
+ }
+}
+
int __fmtstring(4, 5) __stmt_binary_error(struct eval_ctx *ctx,
const struct location *l1,
const struct location *l2,
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 15/16] libnftables: add error handling
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
` (13 preceding siblings ...)
2017-08-16 20:43 ` [nft PATH 14/16] erec: add function to free list Eric Leblond
@ 2017-08-16 20:43 ` Eric Leblond
2017-08-17 10:32 ` Phil Sutter
2017-08-16 20:43 ` [nft PATH 16/16] libnftables: basic doxygen documentation Eric Leblond
2017-08-17 8:32 ` [nft PATCH 0/16] introduce libnftables Arturo Borrero Gonzalez
16 siblings, 1 reply; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:43 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
It had a nft_get_error to be able to fetch existing errors and get
them into a buffer that can be later used by the application.
Signed-off-by: Eric Leblond <eric@regit.org>
---
include/nftables.h | 1 +
include/nftables/nftables.h | 1 +
src/libnftables.c | 29 ++++++++++++++++++-----------
3 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/include/nftables.h b/include/nftables.h
index ddff5d8..9d119b1 100644
--- a/include/nftables.h
+++ b/include/nftables.h
@@ -30,6 +30,7 @@ struct output_ctx {
unsigned int ip2name;
unsigned int handle;
unsigned int echo;
+ struct list_head msgs;
void *ctx;
int (*print)(void *ctx, const char *format, ...);
};
diff --git a/include/nftables/nftables.h b/include/nftables/nftables.h
index f419884..c72ec6b 100644
--- a/include/nftables/nftables.h
+++ b/include/nftables/nftables.h
@@ -30,6 +30,7 @@ void nft_context_free(struct nft_ctx *nft);
void nft_context_set_print_func(struct nft_ctx *nft,
int (*print)(void *ctx, const char *fmt, ...),
void *ctx);
+int nft_get_error(struct nft_ctx *nft, char *err_buf, size_t err_buf_len);
int nft_run_command_from_buffer(struct nft_ctx *nft,
char *buf, size_t buflen);
diff --git a/src/libnftables.c b/src/libnftables.c
index c50c068..a42e8f1 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -86,6 +86,7 @@ struct nft_ctx *nft_context_new(void)
ctx->nf_sock = netlink_open_sock();
init_list_head(&ctx->cache.list);
+ init_list_head(&ctx->output.msgs);
ctx->output.ctx = ctx;
ctx->output.print = nft_print;
@@ -108,6 +109,7 @@ void nft_context_free(struct nft_ctx *nft)
return;
netlink_close_sock(nft->nf_sock);
cache_release(&nft->cache);
+ erec_free_list(&nft->output.msgs);
xfree(nft);
}
@@ -116,23 +118,30 @@ static const struct input_descriptor indesc_cmdline = {
.name = "<cmdline>",
};
+int nft_get_error(struct nft_ctx *nft, char *err_buf, size_t err_buf_len)
+{
+ FILE *errfile = fmemopen(err_buf, err_buf_len, "w");
+ erec_print_list(errfile, &nft->output.msgs);
+ fclose(errfile);
+ return 0;
+}
+
int nft_run_command_from_buffer(struct nft_ctx *nft,
char *buf, size_t buflen)
{
int rc = NFT_EXIT_SUCCESS;
struct parser_state state;
- LIST_HEAD(msgs);
void *scanner;
- parser_init(nft->nf_sock, &nft->cache, &state, &msgs);
+ parser_init(nft->nf_sock, &nft->cache, &state, &nft->output.msgs);
scanner = scanner_init(&state);
scanner_push_buffer(scanner, &indesc_cmdline, buf);
- if (nft_run(nft, nft->nf_sock, &nft->cache, scanner, &state, &msgs) != 0)
+ if (nft_run(nft, nft->nf_sock, &nft->cache, scanner,
+ &state, &nft->output.msgs) != 0)
rc = NFT_EXIT_FAILURE;
scanner_destroy(scanner);
- erec_print_list(stderr, &msgs);
return rc;
}
@@ -146,15 +155,15 @@ int nft_run_command_from_filename(struct nft_ctx *nft, const char *filename)
rc = cache_update(nft->nf_sock, &nft->cache, CMD_INVALID, &msgs);
if (rc < 0)
return rc;
- parser_init(nft->nf_sock, &nft->cache, &state, &msgs);
+ parser_init(nft->nf_sock, &nft->cache, &state, &nft->output.msgs);
scanner = scanner_init(&state);
if (scanner_read_file(scanner, filename, &internal_location) < 0)
return NFT_EXIT_FAILURE;
- if (nft_run(nft, nft->nf_sock, &nft->cache, scanner, &state, &msgs) != 0)
+ if (nft_run(nft, nft->nf_sock, &nft->cache, scanner,
+ &state, &nft->output.msgs) != 0)
rc = NFT_EXIT_FAILURE;
scanner_destroy(scanner);
- erec_print_list(stderr, &msgs);
return rc;
}
@@ -176,14 +185,13 @@ int nft_batch_add(struct nft_ctx *nft, struct nft_batch *batch,
int rc = NFT_EXIT_SUCCESS;
int ret = 0;
struct parser_state state;
- LIST_HEAD(msgs);
void *scanner;
struct cmd *cmd, *next;
struct netlink_ctx *ctx = &batch->nl_ctx;
uint32_t seqnum;
bool batch_supported = netlink_batch_supported(nft->nf_sock, &seqnum);
- parser_init(nft->nf_sock, &nft->cache, &state, &msgs);
+ parser_init(nft->nf_sock, &nft->cache, &state, &nft->output.msgs);
scanner = scanner_init(&state);
scanner_push_buffer(scanner, &indesc_cmdline, buf);
@@ -196,7 +204,7 @@ int nft_batch_add(struct nft_ctx *nft, struct nft_batch *batch,
list_for_each_entry(cmd, &state.cmds, list) {
nft_cmd_expand(cmd);
memset(ctx, 0, sizeof(*ctx));
- ctx->msgs = &msgs;
+ ctx->msgs = &nft->output.msgs;
ctx->seqnum = cmd->seqnum = mnl_seqnum_alloc(&seqnum);
ctx->batch = batch->batch;
ctx->batch_supported = batch_supported;
@@ -215,7 +223,6 @@ int nft_batch_add(struct nft_ctx *nft, struct nft_batch *batch,
}
err1:
scanner_destroy(scanner);
- erec_print_list(stderr, &msgs);
return rc;
}
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* [nft PATH 16/16] libnftables: basic doxygen documentation
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
` (14 preceding siblings ...)
2017-08-16 20:43 ` [nft PATH 15/16] libnftables: add error handling Eric Leblond
@ 2017-08-16 20:43 ` Eric Leblond
2017-08-17 8:32 ` [nft PATCH 0/16] introduce libnftables Arturo Borrero Gonzalez
16 siblings, 0 replies; 37+ messages in thread
From: Eric Leblond @ 2017-08-16 20:43 UTC (permalink / raw)
To: pablo; +Cc: netfilter-devel, Eric Leblond
Signed-off-by: Eric Leblond <eric@regit.org>
---
src/libnftables.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/src/libnftables.c b/src/libnftables.c
index a42e8f1..a9e54c4 100644
--- a/src/libnftables.c
+++ b/src/libnftables.c
@@ -35,6 +35,12 @@ unsigned int debug_level;
const char *include_paths[INCLUDE_PATHS_MAX] = { DEFAULT_INCLUDE_PATH };
+/**
+ * Init cache structure.
+ *
+ * This needs to be called once by process to do the initialization
+ * phase of some structures.
+ */
void nft_global_init(void)
{
mark_table_init();
@@ -48,6 +54,11 @@ void nft_global_init(void)
#endif
}
+/**
+ * Deinit global structures
+ *
+ * To be call one before exiting the nftables tasks
+ */
void nft_global_deinit(void)
{
iface_cache_release();
@@ -58,6 +69,12 @@ void nft_global_deinit(void)
mark_table_exit();
}
+/**
+ * Set number of consecutive errors to handle
+ *
+ * This can be useful if you send complex command to nftables
+ * and want to debug it but it causes memory leak.
+ */
int nft_global_set_max_errors(unsigned int errors)
{
max_errors = errors;
@@ -75,6 +92,10 @@ static int nft_print(void *ctx, const char *fmt, ...)
return 0;
}
+/**
+ * Allocate a nftables context
+ *
+ */
struct nft_ctx *nft_context_new(void)
{
struct nft_ctx *ctx = NULL;
@@ -93,6 +114,12 @@ struct nft_ctx *nft_context_new(void)
return ctx;
}
+/**
+ * Set print function for your application
+ *
+ * Command such as `list ruleset` can trigger an output. This function
+ * allows you to define which function should be used.
+ */
void nft_context_set_print_func(struct nft_ctx *nft,
int (*print)(void *ctx, const char *fmt, ...),
void *ctx)
@@ -103,6 +130,9 @@ void nft_context_set_print_func(struct nft_ctx *nft,
}
}
+/**
+ * Free a nftables context
+ */
void nft_context_free(struct nft_ctx *nft)
{
if (nft == NULL)
@@ -118,6 +148,9 @@ static const struct input_descriptor indesc_cmdline = {
.name = "<cmdline>",
};
+/**
+ * Get current errors and write them in provided buffer
+ */
int nft_get_error(struct nft_ctx *nft, char *err_buf, size_t err_buf_len)
{
FILE *errfile = fmemopen(err_buf, err_buf_len, "w");
@@ -126,6 +159,9 @@ int nft_get_error(struct nft_ctx *nft, char *err_buf, size_t err_buf_len)
return 0;
}
+/**
+ * Run nftables command contained in provided buffer
+ */
int nft_run_command_from_buffer(struct nft_ctx *nft,
char *buf, size_t buflen)
{
@@ -145,6 +181,9 @@ int nft_run_command_from_buffer(struct nft_ctx *nft,
return rc;
}
+/**
+ * Run all nftables commands contained in a file
+ */
int nft_run_command_from_filename(struct nft_ctx *nft, const char *filename)
{
int rc = NFT_EXIT_SUCCESS;
@@ -167,6 +206,9 @@ int nft_run_command_from_filename(struct nft_ctx *nft, const char *filename)
return rc;
}
+/**
+ * Start a batch
+ */
struct nft_batch *nft_batch_start(struct nft_ctx *nft)
{
struct nft_batch *batch = malloc(sizeof(*batch));
@@ -179,6 +221,9 @@ struct nft_batch *nft_batch_start(struct nft_ctx *nft)
return batch;
}
+/**
+ * Add a command to a already created batch
+ */
int nft_batch_add(struct nft_ctx *nft, struct nft_batch *batch,
const char * buf, size_t buflen)
{
@@ -226,6 +271,9 @@ err1:
return rc;
}
+/**
+ * Commit a batch to the kernel
+ */
int nft_batch_commit(struct nft_ctx *nft, struct nft_batch *batch)
{
int ret = 0;
@@ -246,6 +294,9 @@ out:
}
+/**
+ * Free ressources allocated to a batch
+ */
void nft_batch_free(struct nft_batch *batch)
{
if (batch == NULL)
--
2.14.1
^ permalink raw reply related [flat|nested] 37+ messages in thread
* Re: [nft PATCH 0/16] introduce libnftables
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
` (15 preceding siblings ...)
2017-08-16 20:43 ` [nft PATH 16/16] libnftables: basic doxygen documentation Eric Leblond
@ 2017-08-17 8:32 ` Arturo Borrero Gonzalez
2017-08-17 8:58 ` Eric Leblond
2017-08-17 10:47 ` Phil Sutter
16 siblings, 2 replies; 37+ messages in thread
From: Arturo Borrero Gonzalez @ 2017-08-17 8:32 UTC (permalink / raw)
To: Eric Leblond; +Cc: Pablo Neira Ayuso, Netfilter Development Mailing list
On 16 August 2017 at 22:42, Eric Leblond <eric@regit.org> wrote:
>
> Hello,
>
> This patchset adds a basi high level libnftables to nftables code.
> It is currently supporting running a command from a buffer or from
> a file as well as batch support allowing to chain commands and commit
> them at once.
>
> The API is mostly using existing structures such as nft_ctx that are
> updated to contain enough information. It also adds a structure
> dedicated to batch.
>
Great work Eric, thanks!
Some comments below.
> A simple program running a command is the following:
>
> nft_global_init();
> nft = nft_context_new();
> nft_context_set_print_func(nft, my_print, buf);
^^^
A minor thing: Did you evaluate merging these two? Setting the print
function directly when allocating a new context.
> rc = nft_run_command_from_buffer(nft, CMD, sizeof(CMD));
> if (rc != NFT_EXIT_SUCCESS) {
> nft_get_error(nft, err_buf, sizeof(err_buf));
> printf("%s\n", err_buf);
> return -1;
> }
> nft_context_free(nft);
> nft_global_deinit();
>
> Transaction support is similar with:
>
> nft = nft_context_new();
> batch = nft_batch_start(nft);
> if (nft_batch_add(nft, batch, ADD1, strlen(ADD1)) !=0) {
> printf("FAIL add 1\n");
> goto out;
> }
> if (nft_batch_add(nft, batch, ADD2, strlen(ADD2)) !=0) {
> printf("FAIL add 2\n");
> goto out;
> }
> if (nft_batch_commit(nft, batch) != 0) {
^^^
error handling here is like in the other case? i.e. running nft_get_error() ?
> goto out;
> }
>
> out:
> nft_batch_free(batch);
> nft_context_free(nft);
> nft_global_deinit();
>
> The library provides a way to get standard output via nft_context_set_print_func
> and error handling is done via nft_get_error that get error message in a buffer.
>
> This is early stage code as it does not feature things like set handling but IMO
> it can already be used as a starting point to build more things.
>
Any special challenge with sets?
On a side note, I remember in NFWS 2017 we discussed the possibility
of libnftables being a separate source project, i.e a standalone
repository.
Now that I see your patches, what I see is that libnftables is mostly
all the code, while nft itself is very little code.
Still, with my Debian hat, I think that different repositories is good to have.
One more comment: perhaps is good idea to release nftables v0.8 before
introducing this code into the repository. We may end not releasing
nftables in quite a long time.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 01/16] libnftables: introduce library
2017-08-16 20:42 ` [nft PATH 01/16] libnftables: introduce library Eric Leblond
@ 2017-08-17 8:57 ` Phil Sutter
2017-08-17 17:09 ` Eric Leblond
0 siblings, 1 reply; 37+ messages in thread
From: Phil Sutter @ 2017-08-17 8:57 UTC (permalink / raw)
To: Eric Leblond; +Cc: pablo, netfilter-devel
On Wed, Aug 16, 2017 at 10:42:55PM +0200, Eric Leblond wrote:
[...]
> diff --git a/src/libnftables.c b/src/libnftables.c
> new file mode 100644
> index 0000000..215179a
> --- /dev/null
> +++ b/src/libnftables.c
> @@ -0,0 +1,53 @@
> +/*
> + * Copyright (c) 2017 Eric Leblond <eric@regit.org>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + */
> +
> +#include <nftables/nftables.h>
> +#include <string.h>
> +#include <errno.h>
> +#include <nftables.h>
> +#include <parser.h>
> +#include <iface.h>
> +#include <netlink.h>
> +#include <erec.h>
> +#include <libmnl/libmnl.h>
> +#include <mnl.h>
> +
> +#include <unistd.h>
> +#include <fcntl.h>
> +
> +
> +unsigned int max_errors = 10;
> +unsigned int numeric_output;
> +unsigned int ip2name_output;
> +unsigned int handle_output;
> +#ifdef DEBUG
> +unsigned int debug_level;
> +#endif
I guess these global variables have to die. I tried static linking (for
quick testing without installing) which didn't work because max_errors
is then redefined here. (There is a stale one in main.c which you
probably just forgot to remove.)
Maybe max_errors could become part of struct nft_ctx? Alternatively I
would make it static and add a getter to be used from parser_bison.y.
The remaining ones apart from debug_level are leftovers, they live in
struct output_ctx now.
I am not sure where debug_level really belongs to. One one hand, it has
something to do with printing, so struct output_ctx. On the other,
nft_ctx would have to be made reachable from all places where debug
output happens.
Maybe the whole debugging infrastructure (i.e. debug data dumpers and
printers) should be exported to the application?
> +
> +void nft_global_init(void)
> +{
> + mark_table_init();
> + realm_table_rt_init();
> + devgroup_table_init();
> + realm_table_meta_init();
> + ct_label_table_init();
> + gmp_init();
> +#ifdef HAVE_LIBXTABLES
> + xt_init();
> +#endif
> +}
> +
> +void nft_global_deinit(void)
> +{
> + ct_label_table_exit();
> + realm_table_rt_exit();
> + devgroup_table_exit();
> + realm_table_meta_exit();
> + mark_table_exit();
> +}
How about calling these from nft_context_new() and nft_context_free()?
Cheers, Phil
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATCH 0/16] introduce libnftables
2017-08-17 8:32 ` [nft PATCH 0/16] introduce libnftables Arturo Borrero Gonzalez
@ 2017-08-17 8:58 ` Eric Leblond
2017-08-17 10:35 ` Florian Westphal
2017-08-17 10:47 ` Phil Sutter
1 sibling, 1 reply; 37+ messages in thread
From: Eric Leblond @ 2017-08-17 8:58 UTC (permalink / raw)
To: Arturo Borrero Gonzalez
Cc: Pablo Neira Ayuso, Netfilter Development Mailing list
Hi,
On Thu, 2017-08-17 at 10:32 +0200, Arturo Borrero Gonzalez wrote:
> On 16 August 2017 at 22:42, Eric Leblond <eric@regit.org> wrote:
> >
> > Hello,
> >
> > This patchset adds a basi high level libnftables to nftables code.
> > It is currently supporting running a command from a buffer or from
> > a file as well as batch support allowing to chain commands and
> > commit
> > them at once.
> >
> > The API is mostly using existing structures such as nft_ctx that
> > are
> > updated to contain enough information. It also adds a structure
> > dedicated to batch.
> >
>
> Great work Eric, thanks!
>
> Some comments below.
>
> > A simple program running a command is the following:
> >
> > nft_global_init();
> > nft = nft_context_new();
> > nft_context_set_print_func(nft, my_print, buf);
>
> ^^^
> A minor thing: Did you evaluate merging these two? Setting the print
> function directly when allocating a new context.
Nope but could make sense.
>
>
> > rc = nft_run_command_from_buffer(nft, CMD, sizeof(CMD));
> > if (rc != NFT_EXIT_SUCCESS) {
> > nft_get_error(nft, err_buf, sizeof(err_buf));
> > printf("%s\n", err_buf);
> > return -1;
> > }
> > nft_context_free(nft);
> > nft_global_deinit();
> >
> > Transaction support is similar with:
> >
> > nft = nft_context_new();
> > batch = nft_batch_start(nft);
> > if (nft_batch_add(nft, batch, ADD1, strlen(ADD1)) !=0) {
> > printf("FAIL add 1\n");
> > goto out;
> > }
> > if (nft_batch_add(nft, batch, ADD2, strlen(ADD2)) !=0) {
> > printf("FAIL add 2\n");
> > goto out;
> > }
> > if (nft_batch_commit(nft, batch) != 0) {
>
> ^^^
> error handling here is like in the other case? i.e. running
> nft_get_error() ?
Yes exactly. It is supposed to do so but it seems I wrote the commit
function wrong. I'm gonna send an updated patchset.
>
> > goto out;
> > }
> >
> > out:
> > nft_batch_free(batch);
> > nft_context_free(nft);
> > nft_global_deinit();
> >
> > The library provides a way to get standard output via
> > nft_context_set_print_func
> > and error handling is done via nft_get_error that get error message
> > in a buffer.
> >
> > This is early stage code as it does not feature things like set
> > handling but IMO
> > it can already be used as a starting point to build more things.
> >
>
> Any special challenge with sets?
This is in the list of things that are yet to be developed.
> On a side note, I remember in NFWS 2017 we discussed the possibility
> of libnftables being a separate source project, i.e a standalone
> repository.
> Now that I see your patches, what I see is that libnftables is mostly
> all the code, while nft itself is very little code.
> Still, with my Debian hat, I think that different repositories is
> good to have.
I don't like the cascade idea with nftables -> libnftables -> libnftnl
-> libmnl that this will induce. Also this means some potential
breakage in versionning.
> One more comment: perhaps is good idea to release nftables v0.8
> before
> introducing this code into the repository. We may end not releasing
> nftables in quite a long time.
Fully agree on that, this was a point I forgot to mention in my initial
mail.
++
--
Eric Leblond <eric@regit.org>
Blog: https://home.regit.org/
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 02/16] libnftables: add context new and free
2017-08-16 20:42 ` [nft PATH 02/16] libnftables: add context new and free Eric Leblond
@ 2017-08-17 9:04 ` Phil Sutter
0 siblings, 0 replies; 37+ messages in thread
From: Phil Sutter @ 2017-08-17 9:04 UTC (permalink / raw)
To: Eric Leblond; +Cc: pablo, netfilter-devel
On Wed, Aug 16, 2017 at 10:42:56PM +0200, Eric Leblond wrote:
[...]
> diff --git a/src/libnftables.c b/src/libnftables.c
> index 215179a..da1b231 100644
> --- a/src/libnftables.c
> +++ b/src/libnftables.c
> @@ -51,3 +51,23 @@ void nft_global_deinit(void)
> realm_table_meta_exit();
> mark_table_exit();
> }
> +
> +struct nft_ctx *nft_context_new(void)
> +{
> + struct nft_ctx *ctx = NULL;
> + ctx = malloc(sizeof(struct nft_ctx));
Use calloc() here to avoid having garbage in 'output' and 'check'
fields.
> + if (ctx == NULL)
> + return NULL;
> + ctx->nf_sock = netlink_open_sock();
> +
> + return ctx;
> +}
Cheers, Phil
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 03/16] libnftables: add nft_run_command_from_buffer
2017-08-16 20:42 ` [nft PATH 03/16] libnftables: add nft_run_command_from_buffer Eric Leblond
@ 2017-08-17 9:21 ` Phil Sutter
0 siblings, 0 replies; 37+ messages in thread
From: Phil Sutter @ 2017-08-17 9:21 UTC (permalink / raw)
To: Eric Leblond; +Cc: pablo, netfilter-devel
On Wed, Aug 16, 2017 at 10:42:57PM +0200, Eric Leblond wrote:
[...]
> diff --git a/src/libnftables.c b/src/libnftables.c
> index da1b231..9248741 100644
> --- a/src/libnftables.c
> +++ b/src/libnftables.c
> @@ -7,7 +7,6 @@
> *
> */
>
> -#include <nftables/nftables.h>
> #include <string.h>
> #include <errno.h>
> #include <nftables.h>
> @@ -18,6 +17,8 @@
> #include <libmnl/libmnl.h>
> #include <mnl.h>
>
> +#include <nftables/nftables.h>
> +
> #include <unistd.h>
> #include <fcntl.h>
Wat? :)
BTW, someone once told me "headers shouldn't include other headers",
though I sometimes doubt that was the whole truth. What do you think, is
"oh, you included our lib's header too early" a bug in the library or
the application?
[...]
> diff --git a/src/main.c b/src/main.c
> index 23af38e..f863dec 100644
[...]
> @@ -367,7 +362,7 @@ int main(int argc, char * const *argv)
> nft->output.handle++;
> break;
> case OPT_ECHO:
> - nft.output.echo++;
> + nft->output.echo++;
Rebase scars. :)
Cheers, Phil
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 06/16] libnftables: add missing variable to library
2017-08-16 20:43 ` [nft PATH 06/16] libnftables: add missing variable to library Eric Leblond
@ 2017-08-17 9:35 ` Phil Sutter
2017-08-19 11:02 ` Eric Leblond
0 siblings, 1 reply; 37+ messages in thread
From: Phil Sutter @ 2017-08-17 9:35 UTC (permalink / raw)
To: Eric Leblond; +Cc: pablo, netfilter-devel
On Wed, Aug 16, 2017 at 10:43:00PM +0200, Eric Leblond wrote:
> Signed-off-by: Eric Leblond <eric@regit.org>
> ---
> src/libnftables.c | 2 ++
> src/main.c | 1 -
> 2 files changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/src/libnftables.c b/src/libnftables.c
> index 6599248..6d4aceb 100644
> --- a/src/libnftables.c
> +++ b/src/libnftables.c
> @@ -33,6 +33,8 @@ unsigned int handle_output;
> unsigned int debug_level;
> #endif
>
> +const char *include_paths[INCLUDE_PATHS_MAX] = { DEFAULT_INCLUDE_PATH };
> +
I guess this belongs into nft_ctx as well.
Cheers, Phil
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 08/16] libnftables: add a nft_cache to nft_ctx
2017-08-16 20:43 ` [nft PATH 08/16] libnftables: add a nft_cache to nft_ctx Eric Leblond
@ 2017-08-17 9:43 ` Phil Sutter
0 siblings, 0 replies; 37+ messages in thread
From: Phil Sutter @ 2017-08-17 9:43 UTC (permalink / raw)
To: Eric Leblond; +Cc: pablo, netfilter-devel
On Wed, Aug 16, 2017 at 10:43:02PM +0200, Eric Leblond wrote:
[...]
> diff --git a/include/cli.h b/include/cli.h
> index e577400..899c8a6 100644
> --- a/include/cli.h
> +++ b/include/cli.h
> @@ -6,7 +6,7 @@
> struct parser_state;
> #ifdef HAVE_LIBREADLINE
> extern int cli_init(struct nft_ctx *nft, struct mnl_socket *nf_sock,
> - struct nft_cache *cache, struct parser_state *state);
> + struct parser_state *state);
One could get rid of nf_sock parameter as well since that resides in
nft_ctx, too.
[...]
> diff --git a/src/cli.c b/src/cli.c
> index 7501b29..fd5c7b7 100644
> --- a/src/cli.c
> +++ b/src/cli.c
> @@ -177,13 +177,17 @@ void __fmtstring(1, 0) cli_display(const char *fmt, va_list ap)
> }
>
> int cli_init(struct nft_ctx *nft, struct mnl_socket *nf_sock,
> - struct nft_cache *cache, struct parser_state *_state)
> + struct parser_state *_state)
> {
> const char *home;
> + struct nft_cache cache;
> +
> + memset(&cache, 0, sizeof(cache));
> + init_list_head(&cache.list);
Is this a leftover, or do you intentionally use a new cache instance
instead of nft->cache?
Cheers, Phil
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 10/16] libnftables: get rid of printf
2017-08-16 20:43 ` [nft PATH 10/16] libnftables: get rid of printf Eric Leblond
@ 2017-08-17 10:01 ` Phil Sutter
2017-08-19 8:59 ` Eric Leblond
0 siblings, 1 reply; 37+ messages in thread
From: Phil Sutter @ 2017-08-17 10:01 UTC (permalink / raw)
To: Eric Leblond; +Cc: pablo, netfilter-devel
On Wed, Aug 16, 2017 at 10:43:04PM +0200, Eric Leblond wrote:
[...]
> diff --git a/include/nftables.h b/include/nftables.h
> index 348fbb0..ddff5d8 100644
> --- a/include/nftables.h
> +++ b/include/nftables.h
> @@ -30,6 +30,8 @@ struct output_ctx {
> unsigned int ip2name;
> unsigned int handle;
> unsigned int echo;
> + void *ctx;
> + int (*print)(void *ctx, const char *format, ...);
> };
My compiler says:
| libnftables.c: In function 'nft_context_new':
| libnftables.c:113:20: warning: assignment left-hand side might be a candidate for a format attribute [-Wsuggest-attribute=format]
| ctx->output.print = nft_print;
| ^
Not really a warning IMO, though.
Abstracting the topic a bit, maybe all these foo_print() callbacks
should die eventually and be replaced by formatters for different output
types, similar to nftnl_foo_snprintf() functions. Maybe the whole output
formatting actually even belongs to the application and libnftables has
to provide a way to extract object information. Not sure how much
knowlege the application should (need to) have about internal data
structures like e.g., struct table or struct expr.
Cheers, Phil
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 12/16] libnftables: transaction support
2017-08-16 20:43 ` [nft PATH 12/16] libnftables: transaction support Eric Leblond
@ 2017-08-17 10:11 ` Phil Sutter
0 siblings, 0 replies; 37+ messages in thread
From: Phil Sutter @ 2017-08-17 10:11 UTC (permalink / raw)
To: Eric Leblond; +Cc: pablo, netfilter-devel
On Wed, Aug 16, 2017 at 10:43:06PM +0200, Eric Leblond wrote:
[...]
> diff --git a/src/libnftables.c b/src/libnftables.c
> index 494ff57..08050e5 100644
> --- a/src/libnftables.c
> +++ b/src/libnftables.c
> @@ -151,3 +151,92 @@ int nft_run_command_from_filename(struct nft_ctx *nft, const char *filename)
> erec_print_list(stderr, &msgs);
> return rc;
> }
> +
> +struct nft_batch *nft_batch_start(struct nft_ctx *nft)
> +{
> + struct nft_batch *batch = malloc(sizeof(*batch));
> + if (batch == NULL)
> + return NULL;
> +
> + batch->batch = mnl_batch_init();
> + mnl_batch_begin(batch->batch, mnl_seqnum_alloc(&nft->cache.seqnum));
> +
> + return batch;
> +}
Don't you need to initialize batch->nl_ctx here as well?
> +int nft_batch_add(struct nft_ctx *nft, struct nft_batch *batch,
> + const char * buf, size_t buflen)
> +{
> + int rc = NFT_EXIT_SUCCESS;
> + int ret = 0;
> + struct parser_state state;
> + LIST_HEAD(msgs);
> + void *scanner;
> + struct cmd *cmd, *next;
> + struct netlink_ctx *ctx = &batch->nl_ctx;
> + uint32_t seqnum;
> + bool batch_supported = netlink_batch_supported(nft->nf_sock, &seqnum);
That should be an error condition in nft_batch_start(). If it turns out
to be false, later calls to do_command() will execute instead of adding
to batch buffer.
> + parser_init(nft->nf_sock, &nft->cache, &state, &msgs);
> + scanner = scanner_init(&state);
> + scanner_push_buffer(scanner, &indesc_cmdline, buf);
> +
> + ret = nft_parse(scanner, &state);
> + if (ret != 0 || state.nerrs > 0) {
> + rc = -1;
> + goto err1;
> + }
> +
> + list_for_each_entry(cmd, &state.cmds, list) {
> + nft_cmd_expand(cmd);
> + memset(ctx, 0, sizeof(*ctx));
> + ctx->msgs = &msgs;
> + ctx->seqnum = cmd->seqnum = mnl_seqnum_alloc(&seqnum);
> + ctx->batch = batch->batch;
> + ctx->batch_supported = batch_supported;
> + ctx->octx = &nft->output;
> + ctx->nf_sock = nft->nf_sock;
> + ctx->cache = &nft->cache;
> + init_list_head(&ctx->list);
> + ret = do_command(ctx, cmd);
> + if (ret < 0)
> + return -1;
> + }
> +
> + list_for_each_entry_safe(cmd, next, &state.cmds, list) {
> + list_del(&cmd->list);
> + cmd_free(cmd);
> + }
> +err1:
> + scanner_destroy(scanner);
> + erec_print_list(stderr, &msgs);
> + return rc;
> +}
> +
> +int nft_batch_commit(struct nft_ctx *nft, struct nft_batch *batch)
> +{
> + int ret = 0;
> +
> + mnl_batch_end(batch->batch, mnl_seqnum_alloc(&nft->cache.seqnum));
> + LIST_HEAD(err_list);
> +
> + if (!mnl_batch_ready(batch->batch))
> + goto out;
That's an error, no? (In the old code it was a regular exit point in
case batch support wasn't supported.)
Cheers, Phil
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 15/16] libnftables: add error handling
2017-08-16 20:43 ` [nft PATH 15/16] libnftables: add error handling Eric Leblond
@ 2017-08-17 10:32 ` Phil Sutter
2017-08-19 9:04 ` Eric Leblond
0 siblings, 1 reply; 37+ messages in thread
From: Phil Sutter @ 2017-08-17 10:32 UTC (permalink / raw)
To: Eric Leblond; +Cc: pablo, netfilter-devel
On Wed, Aug 16, 2017 at 10:43:09PM +0200, Eric Leblond wrote:
[...]
> diff --git a/src/libnftables.c b/src/libnftables.c
> index c50c068..a42e8f1 100644
> --- a/src/libnftables.c
> +++ b/src/libnftables.c
> @@ -86,6 +86,7 @@ struct nft_ctx *nft_context_new(void)
> ctx->nf_sock = netlink_open_sock();
>
> init_list_head(&ctx->cache.list);
> + init_list_head(&ctx->output.msgs);
>
> ctx->output.ctx = ctx;
> ctx->output.print = nft_print;
> @@ -108,6 +109,7 @@ void nft_context_free(struct nft_ctx *nft)
> return;
> netlink_close_sock(nft->nf_sock);
> cache_release(&nft->cache);
> + erec_free_list(&nft->output.msgs);
> xfree(nft);
> }
>
> @@ -116,23 +118,30 @@ static const struct input_descriptor indesc_cmdline = {
> .name = "<cmdline>",
> };
>
> +int nft_get_error(struct nft_ctx *nft, char *err_buf, size_t err_buf_len)
> +{
> + FILE *errfile = fmemopen(err_buf, err_buf_len, "w");
> + erec_print_list(errfile, &nft->output.msgs);
> + fclose(errfile);
> + return 0;
> +}
> +
> int nft_run_command_from_buffer(struct nft_ctx *nft,
> char *buf, size_t buflen)
> {
> int rc = NFT_EXIT_SUCCESS;
> struct parser_state state;
> - LIST_HEAD(msgs);
> void *scanner;
>
> - parser_init(nft->nf_sock, &nft->cache, &state, &msgs);
> + parser_init(nft->nf_sock, &nft->cache, &state, &nft->output.msgs);
Change signature to take struct nft_ctx as first parameter and get rid
of everything but struct parser_state?
> scanner = scanner_init(&state);
> scanner_push_buffer(scanner, &indesc_cmdline, buf);
>
> - if (nft_run(nft, nft->nf_sock, &nft->cache, scanner, &state, &msgs) != 0)
> + if (nft_run(nft, nft->nf_sock, &nft->cache, scanner,
> + &state, &nft->output.msgs) != 0)
Just use nft->output.msg directly in nft_run() and drop the parameter?
Cheers, Phil
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATCH 0/16] introduce libnftables
2017-08-17 8:58 ` Eric Leblond
@ 2017-08-17 10:35 ` Florian Westphal
0 siblings, 0 replies; 37+ messages in thread
From: Florian Westphal @ 2017-08-17 10:35 UTC (permalink / raw)
To: Eric Leblond
Cc: Arturo Borrero Gonzalez, Pablo Neira Ayuso,
Netfilter Development Mailing list
Eric Leblond <eric@regit.org> wrote:
Thanks a lot for working on this Eric!
> On Thu, 2017-08-17 at 10:32 +0200, Arturo Borrero Gonzalez wrote:
> > On 16 August 2017 at 22:42, Eric Leblond <eric@regit.org> wrote:
> > >
> > > Hello,
> > >
> > > This patchset adds a basi high level libnftables to nftables code.
> > > It is currently supporting running a command from a buffer or from
> > > a file as well as batch support allowing to chain commands and
> > > commit
> > > them at once.
> > >
> > > The API is mostly using existing structures such as nft_ctx that
> > > are
> > > updated to contain enough information. It also adds a structure
> > > dedicated to batch.
> > >
> >
> > Great work Eric, thanks!
> >
> > Some comments below.
> >
> > > A simple program running a command is the following:
> > >
> > > nft_global_init();
> > > nft = nft_context_new();
> > > nft_context_set_print_func(nft, my_print, buf);
> >
> > ^^^
> > A minor thing: Did you evaluate merging these two? Setting the print
> > function directly when allocating a new context.
>
> Nope but could make sense.
I'd recommend to keep it like this, else we can run into
problems when we need a new func.
If it stays this way we can simply add
nft_context_set_foo_func() instead of breaking nft_context_new() abi
or adding nft_context_new2() (ugh...).
> > On a side note, I remember in NFWS 2017 we discussed the possibility
> > of libnftables being a separate source project, i.e a standalone
> > repository.
> > Now that I see your patches, what I see is that libnftables is mostly
> > all the code, while nft itself is very little code.
> > Still, with my Debian hat, I think that different repositories is
> > good to have.
>
> I don't like the cascade idea with nftables -> libnftables -> libnftnl
> -> libmnl that this will induce. Also this means some potential
> breakage in versionning.
I would also like to keep it in same repo, else i fear we will
quickly have copy&paste programming...
We can always split later if we think that nft and libnft have matured
in a way that they are distinct after all.
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATCH 0/16] introduce libnftables
2017-08-17 8:32 ` [nft PATCH 0/16] introduce libnftables Arturo Borrero Gonzalez
2017-08-17 8:58 ` Eric Leblond
@ 2017-08-17 10:47 ` Phil Sutter
1 sibling, 0 replies; 37+ messages in thread
From: Phil Sutter @ 2017-08-17 10:47 UTC (permalink / raw)
To: Arturo Borrero Gonzalez
Cc: Eric Leblond, Pablo Neira Ayuso,
Netfilter Development Mailing list
On Thu, Aug 17, 2017 at 10:32:42AM +0200, Arturo Borrero Gonzalez wrote:
> On 16 August 2017 at 22:42, Eric Leblond <eric@regit.org> wrote:
> >
> > Hello,
> >
> > This patchset adds a basi high level libnftables to nftables code.
> > It is currently supporting running a command from a buffer or from
> > a file as well as batch support allowing to chain commands and commit
> > them at once.
> >
> > The API is mostly using existing structures such as nft_ctx that are
> > updated to contain enough information. It also adds a structure
> > dedicated to batch.
> >
>
> Great work Eric, thanks!
+1! Thanks for pushing this forward.
I noticed a few compiler warnings:
| libnftables.c: In function 'nft_batch_commit':
| ../include/list.h:28:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
| struct list_head name = LIST_HEAD_INIT(name)
| ^
| libnftables.c:282:2: note: in expansion of macro 'LIST_HEAD'
| LIST_HEAD(err_list);
| ^~~~~~~~~
I don't quite understand why that happens, the code removed from
nft_netlink() looks identical. Maybe some compiler flags missing? Or is
it just me?
In addition, I see this one:
| parser_bison.y: In function 'nft_parse':
| parser_bison.y:122:3: warning: implicit declaration of function 'nft_set_debug' [-Wimplicit-function-declaration]
| nft_set_debug(1, scanner);
| ^~~~~~~~~~~~~
| parser_bison.c:64:25: warning: implicit declaration of function 'nft_lex' [-Wimplicit-function-declaration]
| #define yylex nft_lex
| ^
| parser_bison.c:4400:16: note: in expansion of macro 'yylex'
| yychar = yylex (&yylval, &yylloc, scanner);
| ^~~~~
Not sure why that happens, though.
Cheers, Phil
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 01/16] libnftables: introduce library
2017-08-17 8:57 ` Phil Sutter
@ 2017-08-17 17:09 ` Eric Leblond
2017-08-17 17:13 ` Phil Sutter
0 siblings, 1 reply; 37+ messages in thread
From: Eric Leblond @ 2017-08-17 17:09 UTC (permalink / raw)
To: Phil Sutter; +Cc: pablo, netfilter-devel
Hi,
On Thu, 2017-08-17 at 10:57 +0200, Phil Sutter wrote:
> On Wed, Aug 16, 2017 at 10:42:55PM +0200, Eric Leblond wrote:
> [...]
> > diff --git a/src/libnftables.c b/src/libnftables.c
> > new file mode 100644
> > index 0000000..215179a
> > --- /dev/null
> > +++ b/src/libnftables.c
> > @@ -0,0 +1,53 @@
> > +/*
> > + * Copyright (c) 2017 Eric Leblond <eric@regit.org>
> > + *
> > + * This program is free software; you can redistribute it and/or
> > modify
> > + * it under the terms of the GNU General Public License version 2
> > as
> > + * published by the Free Software Foundation.
> > + *
> > + */
> > +
> > +#include <nftables/nftables.h>
> > +#include <string.h>
> > +#include <errno.h>
> > +#include <nftables.h>
> > +#include <parser.h>
> > +#include <iface.h>
> > +#include <netlink.h>
> > +#include <erec.h>
> > +#include <libmnl/libmnl.h>
> > +#include <mnl.h>
> > +
> > +#include <unistd.h>
> > +#include <fcntl.h>
> > +
> > +
> > +unsigned int max_errors = 10;
> > +unsigned int numeric_output;
> > +unsigned int ip2name_output;
> > +unsigned int handle_output;
> > +#ifdef DEBUG
> > +unsigned int debug_level;
> > +#endif
>
> I guess these global variables have to die. I tried static linking
> (for
> quick testing without installing) which didn't work because
> max_errors
> is then redefined here. (There is a stale one in main.c which you
> probably just forgot to remove.)
>
> Maybe max_errors could become part of struct nft_ctx? Alternatively I
> would make it static and add a getter to be used from parser_bison.y.
I'm gonna remove the all but max_errors and see how I could addmax_errors somewhere.
> The remaining ones apart from debug_level are leftovers, they live in
> struct output_ctx now.
Indeed. Good catch.
> I am not sure where debug_level really belongs to. One one hand, it
> has
> something to do with printing, so struct output_ctx. On the other,
> nft_ctx would have to be made reachable from all places where debug
> output happens.
>
> Maybe the whole debugging infrastructure (i.e. debug data dumpers and
> printers) should be exported to the application?
>
> > +
> > +void nft_global_init(void)
> > +{
> > + mark_table_init();
> > + realm_table_rt_init();
> > + devgroup_table_init();
> > + realm_table_meta_init();
> > + ct_label_table_init();
> > + gmp_init();
> > +#ifdef HAVE_LIBXTABLES
> > + xt_init();
> > +#endif
> > +}
> > +
> > +void nft_global_deinit(void)
> > +{
> > + ct_label_table_exit();
> > + realm_table_rt_exit();
> > + devgroup_table_exit();
> > + realm_table_meta_exit();
> > + mark_table_exit();
> > +}
>
> How about calling these from nft_context_new() and
> nft_context_free()?
I want to be able to have multiple context for a single process. Hence
I defined a global init and deinit. But maybe it does not really make
sense and could be attached to each context or init could be done at
first usage.
++
--
Eric Leblond <eric@regit.org>
Blog: https://home.regit.org/
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 01/16] libnftables: introduce library
2017-08-17 17:09 ` Eric Leblond
@ 2017-08-17 17:13 ` Phil Sutter
2017-08-19 8:43 ` Eric Leblond
0 siblings, 1 reply; 37+ messages in thread
From: Phil Sutter @ 2017-08-17 17:13 UTC (permalink / raw)
To: Eric Leblond; +Cc: pablo, netfilter-devel
Hey,
On Thu, Aug 17, 2017 at 07:09:02PM +0200, Eric Leblond wrote:
> On Thu, 2017-08-17 at 10:57 +0200, Phil Sutter wrote:
> > On Wed, Aug 16, 2017 at 10:42:55PM +0200, Eric Leblond wrote:
[...]
> > > +void nft_global_init(void)
> > > +{
> > > + mark_table_init();
> > > + realm_table_rt_init();
> > > + devgroup_table_init();
> > > + realm_table_meta_init();
> > > + ct_label_table_init();
> > > + gmp_init();
> > > +#ifdef HAVE_LIBXTABLES
> > > + xt_init();
> > > +#endif
> > > +}
> > > +
> > > +void nft_global_deinit(void)
> > > +{
> > > + ct_label_table_exit();
> > > + realm_table_rt_exit();
> > > + devgroup_table_exit();
> > > + realm_table_meta_exit();
> > > + mark_table_exit();
> > > +}
> >
> > How about calling these from nft_context_new() and
> > nft_context_free()?
>
> I want to be able to have multiple context for a single process. Hence
> I defined a global init and deinit. But maybe it does not really make
> sense and could be attached to each context or init could be done at
> first usage.
My idea was to implement simple reference counting to see whether the
library was already initialized and whether it is safe to deinit. Of
course this needs some serialization for thread-safety.
Or maybe the deinit can be ignored completely and nft_global_init() just
has to check whether data is already initialized or not.
Cheers, Phil
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 01/16] libnftables: introduce library
2017-08-17 17:13 ` Phil Sutter
@ 2017-08-19 8:43 ` Eric Leblond
2017-08-19 19:07 ` Jan Engelhardt
0 siblings, 1 reply; 37+ messages in thread
From: Eric Leblond @ 2017-08-19 8:43 UTC (permalink / raw)
To: Phil Sutter; +Cc: pablo, netfilter-devel
Hi,
On Thu, 2017-08-17 at 19:13 +0200, Phil Sutter wrote:
> Hey,
>
> On Thu, Aug 17, 2017 at 07:09:02PM +0200, Eric Leblond wrote:
> > On Thu, 2017-08-17 at 10:57 +0200, Phil Sutter wrote:
> > > On Wed, Aug 16, 2017 at 10:42:55PM +0200, Eric Leblond wrote:
>
> [...]
> > > > +void nft_global_init(void)
> > > > +{
> > > > + mark_table_init();
> > > > + realm_table_rt_init();
> > > > + devgroup_table_init();
> > > > + realm_table_meta_init();
> > > > + ct_label_table_init();
> > > > + gmp_init();
> > > > +#ifdef HAVE_LIBXTABLES
> > > > + xt_init();
> > > > +#endif
> > > > +}
> > > > +
> > > > +void nft_global_deinit(void)
> > > > +{
> > > > + ct_label_table_exit();
> > > > + realm_table_rt_exit();
> > > > + devgroup_table_exit();
> > > > + realm_table_meta_exit();
> > > > + mark_table_exit();
> > > > +}
> > >
> > > How about calling these from nft_context_new() and
> > > nft_context_free()?
> >
> > I want to be able to have multiple context for a single process.
> > Hence
> > I defined a global init and deinit. But maybe it does not really
> > make
> > sense and could be attached to each context or init could be done
> > at
> > first usage.
>
> My idea was to implement simple reference counting to see whether the
> library was already initialized and whether it is safe to deinit. Of
> course this needs some serialization for thread-safety.
>
> Or maybe the deinit can be ignored completely and nft_global_init()
> just
> has to check whether data is already initialized or not.
I have used numerous libraries providing a global init or deinit. For
now we could easily skip it with your approach or another but I prefer
we have it existing so it is available later in case of needs.
++
--
Eric Leblond <eric@regit.org>
Blog: https://home.regit.org/
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 10/16] libnftables: get rid of printf
2017-08-17 10:01 ` Phil Sutter
@ 2017-08-19 8:59 ` Eric Leblond
0 siblings, 0 replies; 37+ messages in thread
From: Eric Leblond @ 2017-08-19 8:59 UTC (permalink / raw)
To: Phil Sutter; +Cc: pablo, netfilter-devel
Hi,
On Thu, 2017-08-17 at 12:01 +0200, Phil Sutter wrote:
> On Wed, Aug 16, 2017 at 10:43:04PM +0200, Eric Leblond wrote:
> [...]
> > diff --git a/include/nftables.h b/include/nftables.h
> > index 348fbb0..ddff5d8 100644
> > --- a/include/nftables.h
> > +++ b/include/nftables.h
> > @@ -30,6 +30,8 @@ struct output_ctx {
> > unsigned int ip2name;
> > unsigned int handle;
> > unsigned int echo;
> > + void *ctx;
> > + int (*print)(void *ctx, const char *format, ...);
> > };
>
> My compiler says:
>
> > libnftables.c: In function 'nft_context_new':
> > libnftables.c:113:20: warning: assignment left-hand side might be a
> > candidate for a format attribute [-Wsuggest-attribute=format]
> > ctx->output.print = nft_print;
> > ^
>
> Not really a warning IMO, though.
>
> Abstracting the topic a bit, maybe all these foo_print() callbacks
> should die eventually and be replaced by formatters for different
> output
> types, similar to nftnl_foo_snprintf() functions. Maybe the whole
> output
> formatting actually even belongs to the application and libnftables
> has
> to provide a way to extract object information. Not sure how much
> knowlege the application should (need to) have about internal data
> structures like e.g., struct table or struct expr.
Agree, this was a first approach. Not sending structured data is
problem in a modern library.
We have already dumping of object in JSON or XML. It maybe could be
used as communication method to send structured data to the user
applications. Don't know if it is a lazy way but maybe it could be
enough.
++
--
Eric Leblond <eric@regit.org>
Blog: https://home.regit.org/
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 15/16] libnftables: add error handling
2017-08-17 10:32 ` Phil Sutter
@ 2017-08-19 9:04 ` Eric Leblond
0 siblings, 0 replies; 37+ messages in thread
From: Eric Leblond @ 2017-08-19 9:04 UTC (permalink / raw)
To: Phil Sutter; +Cc: pablo, netfilter-devel
Hi,
On Thu, 2017-08-17 at 12:32 +0200, Phil Sutter wrote:
> On Wed, Aug 16, 2017 at 10:43:09PM +0200, Eric Leblond wrote:
> [...]
> > diff --git a/src/libnftables.c b/src/libnftables.c
> > index c50c068..a42e8f1 100644
> > --- a/src/libnftables.c
> > +++ b/src/libnftables.c
> > @@ -86,6 +86,7 @@ struct nft_ctx *nft_context_new(void)
> > ctx->nf_sock = netlink_open_sock();
> >
> > init_list_head(&ctx->cache.list);
> > + init_list_head(&ctx->output.msgs);
> >
> > ctx->output.ctx = ctx;
> > ctx->output.print = nft_print;
> > @@ -108,6 +109,7 @@ void nft_context_free(struct nft_ctx *nft)
..
> > struct parser_state state;
> > - LIST_HEAD(msgs);
> > void *scanner;
> >
> > - parser_init(nft->nf_sock, &nft->cache, &state, &msgs);
> > + parser_init(nft->nf_sock, &nft->cache, &state, &nft-
> > >output.msgs);
>
> Change signature to take struct nft_ctx as first parameter and get
> rid
> of everything but struct parser_state?
Fully agree with proposal.
>
> > scanner = scanner_init(&state);
> > scanner_push_buffer(scanner, &indesc_cmdline, buf);
> >
> > - if (nft_run(nft, nft->nf_sock, &nft->cache, scanner,
> > &state, &msgs) != 0)
> > + if (nft_run(nft, nft->nf_sock, &nft->cache, scanner,
> > + &state, &nft->output.msgs) != 0)
>
> Just use nft->output.msg directly in nft_run() and drop the
> parameter?
Yes, I think we can go and simplify a few functions prototype. I did
not do it cause of lack of time but also because I wanted to have
everybody agree on the data model before doing this changes.
++
--
Eric Leblond <eric@regit.org>
Blog: https://home.regit.org/
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 06/16] libnftables: add missing variable to library
2017-08-17 9:35 ` Phil Sutter
@ 2017-08-19 11:02 ` Eric Leblond
0 siblings, 0 replies; 37+ messages in thread
From: Eric Leblond @ 2017-08-19 11:02 UTC (permalink / raw)
To: Phil Sutter; +Cc: pablo, netfilter-devel
Hi,
On Thu, 2017-08-17 at 11:35 +0200, Phil Sutter wrote:
> On Wed, Aug 16, 2017 at 10:43:00PM +0200, Eric Leblond wrote:
> > Signed-off-by: Eric Leblond <eric@regit.org>
> > ---
> > src/libnftables.c | 2 ++
> > src/main.c | 1 -
> > 2 files changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/src/libnftables.c b/src/libnftables.c
> > index 6599248..6d4aceb 100644
> > --- a/src/libnftables.c
> > +++ b/src/libnftables.c
> > @@ -33,6 +33,8 @@ unsigned int handle_output;
> > unsigned int debug_level;
> > #endif
> >
> > +const char *include_paths[INCLUDE_PATHS_MAX] = {
> > DEFAULT_INCLUDE_PATH };
> > +
>
> I guess this belongs into nft_ctx as well.
Yes, it could be done later.
++
--
Eric Leblond <eric@regit.org>
Blog: https://home.regit.org/
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 01/16] libnftables: introduce library
2017-08-19 8:43 ` Eric Leblond
@ 2017-08-19 19:07 ` Jan Engelhardt
2017-08-21 8:19 ` Pablo Neira Ayuso
0 siblings, 1 reply; 37+ messages in thread
From: Jan Engelhardt @ 2017-08-19 19:07 UTC (permalink / raw)
To: Eric Leblond; +Cc: Phil Sutter, pablo, netfilter-devel
On Saturday 2017-08-19 10:43, Eric Leblond wrote:
>>> Hence I defined a global init and deinit. But maybe it does not
>>> really make sense and could be attached to each context or init
>>> could be done at first usage.
>>
>> My idea was to implement simple reference counting to see whether
>> the library was already initialized and whether it is safe to
>> deinit. Of course this needs some serialization for thread-safety.
>>
>> Or maybe the deinit can be ignored completely and
>> nft_global_init() just has to check whether data is already
>> initialized or not.
>
>I have used numerous libraries providing a global init or deinit.
>For now we could easily skip it with your approach or another but I
>prefer we have it existing so it is available later in case of
>needs.
If a global init - more correctly, a singleton init - is needed,
can't it just implicitly be called from make_me_a_new_context()?
^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: [nft PATH 01/16] libnftables: introduce library
2017-08-19 19:07 ` Jan Engelhardt
@ 2017-08-21 8:19 ` Pablo Neira Ayuso
0 siblings, 0 replies; 37+ messages in thread
From: Pablo Neira Ayuso @ 2017-08-21 8:19 UTC (permalink / raw)
To: Jan Engelhardt; +Cc: Eric Leblond, Phil Sutter, netfilter-devel
On Sat, Aug 19, 2017 at 09:07:55PM +0200, Jan Engelhardt wrote:
>
> On Saturday 2017-08-19 10:43, Eric Leblond wrote:
>
> >>> Hence I defined a global init and deinit. But maybe it does not
> >>> really make sense and could be attached to each context or init
> >>> could be done at first usage.
> >>
> >> My idea was to implement simple reference counting to see whether
> >> the library was already initialized and whether it is safe to
> >> deinit. Of course this needs some serialization for thread-safety.
> >>
> >> Or maybe the deinit can be ignored completely and
> >> nft_global_init() just has to check whether data is already
> >> initialized or not.
> >
> >I have used numerous libraries providing a global init or deinit.
> >For now we could easily skip it with your approach or another but I
> >prefer we have it existing so it is available later in case of
> >needs.
>
> If a global init - more correctly, a singleton init - is needed,
> can't it just implicitly be called from make_me_a_new_context()?
I would advocate for placing the nft_global_init() and deinit() code
into the ctx object too.
Those _init() and _deinit() are indeed initializing context
information, such as iproute/ct label maps.
So they are context after all.
^ permalink raw reply [flat|nested] 37+ messages in thread
end of thread, other threads:[~2017-08-21 8:19 UTC | newest]
Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-08-16 20:42 [nft PATCH 0/16] introduce libnftables Eric Leblond
2017-08-16 20:42 ` [nft PATH 01/16] libnftables: introduce library Eric Leblond
2017-08-17 8:57 ` Phil Sutter
2017-08-17 17:09 ` Eric Leblond
2017-08-17 17:13 ` Phil Sutter
2017-08-19 8:43 ` Eric Leblond
2017-08-19 19:07 ` Jan Engelhardt
2017-08-21 8:19 ` Pablo Neira Ayuso
2017-08-16 20:42 ` [nft PATH 02/16] libnftables: add context new and free Eric Leblond
2017-08-17 9:04 ` Phil Sutter
2017-08-16 20:42 ` [nft PATH 03/16] libnftables: add nft_run_command_from_buffer Eric Leblond
2017-08-17 9:21 ` Phil Sutter
2017-08-16 20:42 ` [nft PATH 04/16] libnftables: add nft_run_command_from_filename Eric Leblond
2017-08-16 20:42 ` [nft PATH 05/16] libnftables: put nft_run in library Eric Leblond
2017-08-16 20:43 ` [nft PATH 06/16] libnftables: add missing variable to library Eric Leblond
2017-08-17 9:35 ` Phil Sutter
2017-08-19 11:02 ` Eric Leblond
2017-08-16 20:43 ` [nft PATH 07/16] libnftables: add NFT_EXIT_* " Eric Leblond
2017-08-16 20:43 ` [nft PATH 08/16] libnftables: add a nft_cache to nft_ctx Eric Leblond
2017-08-17 9:43 ` Phil Sutter
2017-08-16 20:43 ` [nft PATH 09/16] libnftables: move iface_cache_release to deinit Eric Leblond
2017-08-16 20:43 ` [nft PATH 10/16] libnftables: get rid of printf Eric Leblond
2017-08-17 10:01 ` Phil Sutter
2017-08-19 8:59 ` Eric Leblond
2017-08-16 20:43 ` [nft PATH 11/16] libnftables: add nft_context_set_print Eric Leblond
2017-08-16 20:43 ` [nft PATH 12/16] libnftables: transaction support Eric Leblond
2017-08-17 10:11 ` Phil Sutter
2017-08-16 20:43 ` [nft PATH 13/16] libnftables: set max_errors to 1 in library Eric Leblond
2017-08-16 20:43 ` [nft PATH 14/16] erec: add function to free list Eric Leblond
2017-08-16 20:43 ` [nft PATH 15/16] libnftables: add error handling Eric Leblond
2017-08-17 10:32 ` Phil Sutter
2017-08-19 9:04 ` Eric Leblond
2017-08-16 20:43 ` [nft PATH 16/16] libnftables: basic doxygen documentation Eric Leblond
2017-08-17 8:32 ` [nft PATCH 0/16] introduce libnftables Arturo Borrero Gonzalez
2017-08-17 8:58 ` Eric Leblond
2017-08-17 10:35 ` Florian Westphal
2017-08-17 10:47 ` Phil Sutter
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).