list_add_tail(&erec->list, queue);
}
-extern void erec_print(FILE *f, const struct error_record *erec);
-extern void erec_print_list(FILE *f, struct list_head *list);
+extern void erec_print(FILE *f, const struct error_record *erec,
+ unsigned int debug_mask);
+extern void erec_print_list(FILE *f, struct list_head *list,
+ unsigned int debug_mask);
struct eval_ctx;
extern struct expr *set_expr_alloc(const struct location *loc,
const struct set *set);
extern int set_to_intervals(struct list_head *msgs, struct set *set,
- struct expr *init, bool add);
+ struct expr *init, bool add,
+ unsigned int debug_mask);
extern void interval_map_decompose(struct expr *set);
extern struct expr *mapping_expr_alloc(const struct location *loc,
struct mnl_ctx {
struct mnl_socket *nf_sock;
unsigned int seqnum;
+ unsigned int debug_mask;
};
struct mnl_socket *netlink_open_sock(void);
struct nftnl_ruleset *mnl_nft_ruleset_dump(struct mnl_socket *nf_sock,
uint32_t family, uint32_t seqnum);
-int mnl_nft_event_listener(struct mnl_socket *nf_sock,
+int mnl_nft_event_listener(struct mnl_ctx *ctx,
int (*cb)(const struct nlmsghdr *nlh, void *data),
void *cb_data);
struct rule *rule;
struct stmt *stmt;
struct expr *registers[1 + NFT_REG32_15 - NFT_REG32_00 + 1];
+ unsigned int debug_mask;
};
struct rule_pp_ctx {
* @data: pointer to pass data to callback
* @seqnum: sequence number
* @octx: output context
+ * @debug_mask: display debugging information
* @cache: cache context
*/
struct netlink_ctx {
uint32_t seqnum;
struct nftnl_batch *batch;
bool batch_supported;
+ unsigned int debug_mask;
struct output_ctx *octx;
struct nft_cache *cache;
};
extern int netlink_delete_obj(struct netlink_ctx *ctx, const struct handle *h,
struct location *loc, uint32_t type);
-extern void netlink_dump_chain(const struct nftnl_chain *nlc);
-extern void netlink_dump_rule(const struct nftnl_rule *nlr);
-extern void netlink_dump_expr(const struct nftnl_expr *nle);
-extern void netlink_dump_set(const struct nftnl_set *nls);
-extern void netlink_dump_obj(struct nftnl_obj *nlo);
+extern void netlink_dump_chain(const struct nftnl_chain *nlc,
+ unsigned int debug_mask);
+extern void netlink_dump_rule(const struct nftnl_rule *nlr,
+ unsigned int debug_mask);
+extern void netlink_dump_expr(const struct nftnl_expr *nle,
+ unsigned int debug_mask);
+extern void netlink_dump_set(const struct nftnl_set *nls,
+ unsigned int debug_mask);
+extern void netlink_dump_obj(struct nftnl_obj *nlo, unsigned int debug_mask);
extern int netlink_batch_send(struct netlink_ctx *ctx, struct list_head *err_list);
uint32_t format;
struct netlink_ctx *ctx;
const struct location *loc;
+ unsigned int debug_mask;
bool cache_needed;
struct nft_cache *cache;
};
const char *include_paths[INCLUDE_PATHS_MAX];
unsigned int num_include_paths;
unsigned int parser_max_errors;
+ unsigned int debug_mask;
struct output_ctx output;
bool check;
struct nft_cache cache;
};
-extern unsigned int debug_level;
-
enum nftables_exit_codes {
NFT_EXIT_SUCCESS = 0,
NFT_EXIT_FAILURE = 1,
struct mnl_socket;
extern void parser_init(struct mnl_socket *nf_sock, struct nft_cache *cache,
- struct parser_state *state, struct list_head *msgs);
+ struct parser_state *state, struct list_head *msgs,
+ unsigned int debug_level);
extern int nft_parse(struct nft_ctx *ctx, void *, struct parser_state *state);
extern void *scanner_init(struct parser_state *state);
/**
* struct proto_ctx - protocol context
*
+ * debug_mask: display debugging information
* @family: hook family
* @location: location of the relational expression defining the context
* @desc: protocol description for this layer
* through a dependency.
*/
struct proto_ctx {
+ unsigned int debug_mask;
unsigned int family;
struct {
struct location location;
} protocol[PROTO_BASE_MAX + 1];
};
-extern void proto_ctx_init(struct proto_ctx *ctx, unsigned int family);
+extern void proto_ctx_init(struct proto_ctx *ctx, unsigned int family,
+ unsigned int debug_mask);
extern void proto_ctx_update(struct proto_ctx *ctx, enum proto_bases base,
const struct location *loc,
const struct proto_desc *desc);
* @set: current set
* @stmt: current statement
* @cache: cache context
+ * @debug_mask: debugging bitmask
* @ectx: expression context
* @pctx: payload context
*/
struct set *set;
struct stmt *stmt;
struct nft_cache *cache;
+ unsigned int debug_mask;
struct expr_ctx ectx;
struct proto_ctx pctx;
};
extern int do_command(struct netlink_ctx *ctx, struct cmd *cmd);
extern int cache_update(struct mnl_socket *nf_sock, struct nft_cache *cache,
- enum cmd_ops cmd, struct list_head *msgs);
+ enum cmd_ops cmd, struct list_head *msgs, bool debug);
extern void cache_flush(struct list_head *table_list);
extern void cache_release(struct nft_cache *cache);
xfree(line);
line = s;
- parser_init(cli_nf_sock, &cli_nft->cache, state, &msgs);
+ parser_init(cli_nf_sock, &cli_nft->cache, state, &msgs,
+ cli_nft->debug_mask);
scanner_push_buffer(scanner, &indesc_cli, line);
nft_run(cli_nft, cli_nf_sock, scanner, state, &msgs);
- erec_print_list(stdout, &msgs);
+ erec_print_list(stdout, &msgs, cli_nft->debug_mask);
xfree(line);
cache_release(&cli_nft->cache);
iface_cache_release();
return erec;
}
-void erec_print(FILE *f, const struct error_record *erec)
+void erec_print(FILE *f, const struct error_record *erec,
+ unsigned int debug_mask)
{
const struct location *loc = erec->locations, *iloc;
const struct input_descriptor *indesc = loc->indesc, *tmp;
fprintf(f, "%s\n", erec->msg);
for (l = 0; l < (int)erec->num_locations; l++) {
loc = &erec->locations[l];
- netlink_dump_expr(loc->nle);
+ netlink_dump_expr(loc->nle, debug_mask);
}
fprintf(f, "\n");
} else {
fprintf(f, "\n");
}
-void erec_print_list(FILE *f, struct list_head *list)
+void erec_print_list(FILE *f, struct list_head *list, unsigned int debug_mask)
{
struct error_record *erec, *next;
list_for_each_entry_safe(erec, next, list, list) {
list_del(&erec->list);
- erec_print(f, erec);
+ erec_print(f, erec, debug_mask);
erec_destroy(erec);
}
}
break;
case SYMBOL_SET:
ret = cache_update(ctx->nf_sock, ctx->cache, ctx->cmd->op,
- ctx->msgs);
+ ctx->msgs, ctx->debug_mask & DEBUG_NETLINK);
if (ret < 0)
return ret;
static int expr_evaluate(struct eval_ctx *ctx, struct expr **expr)
{
- if (debug_level & DEBUG_EVALUATION) {
+ if (ctx->debug_mask & DEBUG_EVALUATION) {
struct error_record *erec;
erec = erec_create(EREC_INFORMATIONAL, &(*expr)->location,
"Evaluate %s", (*expr)->ops->name);
- erec_print(stdout, erec);
+ erec_print(stdout, erec, ctx->debug_mask);
expr_print(*expr, &octx_debug_dummy);
printf("\n\n");
}
int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt)
{
- if (debug_level & DEBUG_EVALUATION) {
+ if (ctx->debug_mask & DEBUG_EVALUATION) {
struct error_record *erec;
erec = erec_create(EREC_INFORMATIONAL, &stmt->location,
"Evaluate %s", stmt->ops->name);
- erec_print(stdout, erec); stmt_print(stmt, &octx_debug_dummy);
+ erec_print(stdout, erec, ctx->debug_mask);
+ stmt_print(stmt, &octx_debug_dummy);
printf("\n\n");
}
struct stmt *stmt, *tstmt = NULL;
struct error_record *erec;
- proto_ctx_init(&ctx->pctx, rule->handle.family);
+ proto_ctx_init(&ctx->pctx, rule->handle.family, ctx->debug_mask);
memset(&ctx->ectx, 0, sizeof(ctx->ectx));
ctx->rule = rule;
switch (cmd->obj) {
case CMD_OBJ_SETELEM:
ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op,
- ctx->msgs);
+ ctx->msgs, ctx->debug_mask & DEBUG_NETLINK);
if (ret < 0)
return ret;
return setelem_evaluate(ctx, &cmd->expr);
case CMD_OBJ_SET:
ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op,
- ctx->msgs);
+ ctx->msgs, ctx->debug_mask & DEBUG_NETLINK);
if (ret < 0)
return ret;
return rule_evaluate(ctx, cmd->rule);
case CMD_OBJ_CHAIN:
ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op,
- ctx->msgs);
+ ctx->msgs, ctx->debug_mask & DEBUG_NETLINK);
if (ret < 0)
return ret;
switch (cmd->obj) {
case CMD_OBJ_SETELEM:
ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op,
- ctx->msgs);
+ ctx->msgs, ctx->debug_mask & DEBUG_NETLINK);
if (ret < 0)
return ret;
struct set *set;
int ret;
- ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs,
+ ctx->debug_mask & DEBUG_NETLINK);
if (ret < 0)
return ret;
{
int ret;
- ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs,
+ ctx->debug_mask & DEBUG_NETLINK);
if (ret < 0)
return ret;
struct set *set;
int ret;
- ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs,
+ ctx->debug_mask & DEBUG_NETLINK);
if (ret < 0)
return ret;
switch (cmd->obj) {
case CMD_OBJ_CHAIN:
ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op,
- ctx->msgs);
+ ctx->msgs, ctx->debug_mask & DEBUG_NETLINK);
if (ret < 0)
return ret;
uint32_t event;
int ret;
- ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs,
+ ctx->debug_mask & DEBUG_NETLINK);
if (ret < 0)
return ret;
static int cmd_evaluate_export(struct eval_ctx *ctx, struct cmd *cmd)
{
- return cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs);
+ return cache_update(ctx->nf_sock, ctx->cache, cmd->op, ctx->msgs,
+ ctx->debug_mask & DEBUG_NETLINK);
}
static const char *cmd_op_name[] = {
int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd)
{
- if (debug_level & DEBUG_EVALUATION) {
+ if (ctx->debug_mask & DEBUG_EVALUATION) {
struct error_record *erec;
erec = erec_create(EREC_INFORMATIONAL, &cmd->location,
"Evaluate %s", cmd_op_to_name(cmd->op));
- erec_print(stdout, erec); printf("\n\n");
+ erec_print(stdout, erec, ctx->debug_mask);
+ printf("\n\n");
}
ctx->cmd = cmd;
#include <cli.h>
static struct nft_ctx nft;
-unsigned int debug_level;
enum opt_vals {
OPT_HELP = 'h',
ctx.octx = &nft->output;
ctx.nf_sock = nf_sock;
ctx.cache = &nft->cache;
+ ctx.debug_mask = nft->debug_mask;
init_list_head(&ctx.list);
ret = do_command(&ctx, cmd);
if (ret < 0)
for (i = 0; i < array_size(debug_param); i++) {
if (strcmp(debug_param[i].name, optarg))
continue;
- debug_level |= debug_param[i].level;
+ nft.debug_mask |= debug_param[i].level;
break;
}
strcat(buf, " ");
}
strcat(buf, "\n");
- parser_init(nf_sock, &nft.cache, &state, &msgs);
+ parser_init(nf_sock, &nft.cache, &state, &msgs, nft.debug_mask);
scanner = scanner_init(&state);
scanner_push_buffer(scanner, &indesc_cmdline, buf);
} else if (filename != NULL) {
- rc = cache_update(nf_sock, &nft.cache, CMD_INVALID, &msgs);
+ rc = cache_update(nf_sock, &nft.cache, CMD_INVALID, &msgs,
+ nft.debug_mask);
if (rc < 0)
return rc;
- parser_init(nf_sock, &nft.cache, &state, &msgs);
+ parser_init(nf_sock, &nft.cache, &state, &msgs, nft.debug_mask);
scanner = scanner_init(&state);
if (scanner_read_file(scanner, filename, &internal_location) < 0)
goto out;
rc = NFT_EXIT_FAILURE;
out:
scanner_destroy(scanner);
- erec_print_list(stderr, &msgs);
+ erec_print_list(stderr, &msgs, nft.debug_mask);
xfree(buf);
cache_release(&nft.cache);
iface_cache_release();
{
uint32_t portid = mnl_socket_get_portid(ctx->nf_sock);
- if (debug_level & DEBUG_MNL)
+ if (ctx->debug_mask & DEBUG_MNL)
mnl_nlmsg_fprintf(stdout, data, len, sizeof(struct nfgenmsg));
if (mnl_socket_sendto(ctx->nf_sock, data, len) < 0)
nftnl_batch_iovec(ctx->batch, iov, iov_len);
for (i = 0; i < iov_len; i++) {
- if (debug_level & DEBUG_MNL) {
+ if (ctx->debug_mask & DEBUG_MNL) {
mnl_nlmsg_fprintf(stdout,
iov[i].iov_base, iov[i].iov_len,
sizeof(struct nfgenmsg));
*/
#define NFTABLES_NLEVENT_BUFSIZ (1 << 24)
-int mnl_nft_event_listener(struct mnl_socket *nf_sock,
+int mnl_nft_event_listener(struct mnl_ctx *ctx,
int (*cb)(const struct nlmsghdr *nlh, void *data),
void *cb_data)
{
* message loss due to ENOBUFS.
*/
unsigned int bufsiz = NFTABLES_NLEVENT_BUFSIZ;
- int fd = mnl_socket_get_fd(nf_sock);
+ int fd = mnl_socket_get_fd(ctx->nf_sock);
char buf[NFT_NLMSG_MAXSIZE];
fd_set readfds;
int ret;
return -1;
if (FD_ISSET(fd, &readfds)) {
- ret = mnl_socket_recvfrom(nf_sock, buf, sizeof(buf));
+ ret = mnl_socket_recvfrom(ctx->nf_sock, buf, sizeof(buf));
if (ret < 0) {
if (errno == ENOBUFS) {
printf("# ERROR: We lost some netlink events!\n");
}
}
- if (debug_level & DEBUG_MNL) {
+ if (ctx->debug_mask & DEBUG_MNL) {
mnl_nlmsg_fprintf(stdout, buf, sizeof(buf),
sizeof(struct nfgenmsg));
}
if (ctx->octx->echo) {
err = cache_update(ctx->nf_sock, ctx->cache,
- CMD_INVALID, ctx->msgs);
+ CMD_INVALID, ctx->msgs,
+ ctx->debug_mask & DEBUG_NETLINK);
if (err < 0)
return err;
return err;
}
-void netlink_dump_rule(const struct nftnl_rule *nlr)
+void netlink_dump_rule(const struct nftnl_rule *nlr, unsigned int debug_mask)
{
char buf[4096];
- if (!(debug_level & DEBUG_NETLINK))
+ if (!(debug_mask & DEBUG_NETLINK))
return;
nftnl_rule_snprintf(buf, sizeof(buf), nlr, 0, 0);
fprintf(stdout, "%s\n", buf);
}
-void netlink_dump_expr(const struct nftnl_expr *nle)
+void netlink_dump_expr(const struct nftnl_expr *nle, unsigned int debug_mask)
{
char buf[4096];
- if (!(debug_level & DEBUG_NETLINK))
+ if (!(debug_mask & DEBUG_NETLINK))
return;
nftnl_expr_snprintf(buf, sizeof(buf), nle, 0, 0);
(h->chain && strcmp(chain, h->chain) != 0))
return 0;
- netlink_dump_rule(nlr);
+ netlink_dump_rule(nlr, ctx->debug_mask);
rule = netlink_delinearize_rule(ctx, nlr);
list_add_tail(&rule->list, &ctx->list);
return netlink_del_rule_batch(ctx, h, loc);
}
-void netlink_dump_chain(const struct nftnl_chain *nlc)
+void netlink_dump_chain(const struct nftnl_chain *nlc, unsigned int debug_mask)
{
char buf[4096];
- if (!(debug_level & DEBUG_NETLINK))
+ if (!(debug_mask & DEBUG_NETLINK))
return;
nftnl_chain_snprintf(buf, sizeof(buf), nlc, 0, 0);
chain->policy);
}
- netlink_dump_chain(nlc);
+ netlink_dump_chain(nlc, ctx->debug_mask);
err = mnl_nft_chain_add(ctx->nf_sock, nlc, flags, ctx->seqnum);
nftnl_chain_free(nlc);
chain->dev);
}
- netlink_dump_chain(nlc);
+ netlink_dump_chain(nlc, ctx->debug_mask);
err = mnl_nft_chain_batch_add(nlc, ctx->batch, flags, ctx->seqnum);
nftnl_chain_free(nlc);
nlc = alloc_nftnl_chain(h);
nftnl_chain_set_str(nlc, NFTNL_CHAIN_NAME, name);
- netlink_dump_chain(nlc);
+ netlink_dump_chain(nlc, ctx->debug_mask);
err = mnl_nft_chain_add(ctx->nf_sock, nlc, 0, ctx->seqnum);
nftnl_chain_free(nlc);
nlc = alloc_nftnl_chain(h);
nftnl_chain_set_str(nlc, NFTNL_CHAIN_NAME, name);
- netlink_dump_chain(nlc);
+ netlink_dump_chain(nlc, ctx->debug_mask);
err = mnl_nft_chain_batch_add(nlc, ctx->batch, 0, ctx->seqnum);
nftnl_chain_free(nlc);
int err;
nlc = alloc_nftnl_chain(h);
- netlink_dump_chain(nlc);
+ netlink_dump_chain(nlc, ctx->debug_mask);
err = mnl_nft_chain_delete(ctx->nf_sock, nlc, 0, ctx->seqnum);
nftnl_chain_free(nlc);
int err;
nlc = alloc_nftnl_chain(h);
- netlink_dump_chain(nlc);
+ netlink_dump_chain(nlc, ctx->debug_mask);
err = mnl_nft_chain_batch_del(nlc, ctx->batch, 0, ctx->seqnum);
nftnl_chain_free(nlc);
}
}
-void netlink_dump_set(const struct nftnl_set *nls)
+void netlink_dump_set(const struct nftnl_set *nls, unsigned int debug_mask)
{
char buf[4096];
- if (!(debug_level & DEBUG_NETLINK))
+ if (!(debug_mask & DEBUG_NETLINK))
return;
nftnl_set_snprintf(buf, sizeof(buf), nls, 0, 0);
nftnl_set_set_u32(nls, NFTNL_SET_DATA_LEN,
set->datalen / BITS_PER_BYTE);
}
- netlink_dump_set(nls);
+ netlink_dump_set(nls, ctx->debug_mask);
err = mnl_nft_set_add(ctx->nf_sock, nls, NLM_F_ECHO | flags,
ctx->seqnum);
nftnl_udata_buf_len(udbuf));
nftnl_udata_buf_free(udbuf);
- netlink_dump_set(nls);
+ netlink_dump_set(nls, ctx->debug_mask);
err = mnl_nft_set_batch_add(nls, ctx->batch, flags, ctx->seqnum);
if (err < 0)
nls = alloc_nftnl_set(h);
alloc_setelem_cache(expr, nls);
- netlink_dump_set(nls);
+ netlink_dump_set(nls, ctx->debug_mask);
err = mnl_nft_setelem_batch_add(nls, ctx->batch, flags, ctx->seqnum);
nftnl_set_free(nls);
nls = alloc_nftnl_set(h);
alloc_setelem_cache(expr, nls);
- netlink_dump_set(nls);
+ netlink_dump_set(nls, ctx->debug_mask);
err = mnl_nft_setelem_add(ctx->nf_sock, nls, flags, ctx->seqnum);
nftnl_set_free(nls);
nls = alloc_nftnl_set(h);
if (expr)
alloc_setelem_cache(expr, nls);
- netlink_dump_set(nls);
+ netlink_dump_set(nls, ctx->debug_mask);
err = mnl_nft_setelem_batch_del(nls, ctx->batch, 0, ctx->seqnum);
nftnl_set_free(nls);
nls = alloc_nftnl_set(h);
alloc_setelem_cache(expr, nls);
- netlink_dump_set(nls);
+ netlink_dump_set(nls, ctx->debug_mask);
err = mnl_nft_setelem_delete(ctx->nf_sock, nls, 0, ctx->seqnum);
nftnl_set_free(nls);
int err;
nls = alloc_nftnl_set(h);
- netlink_dump_set(nls);
+ netlink_dump_set(nls, ctx->debug_mask);
err = mnl_nft_setelem_batch_flush(nls, ctx->batch, 0, ctx->seqnum);
nftnl_set_free(nls);
return err;
}
-void netlink_dump_obj(struct nftnl_obj *nln)
+void netlink_dump_obj(struct nftnl_obj *nln, unsigned int debug_mask)
{
char buf[4096];
- if (!(debug_level & DEBUG_NETLINK))
+ if (!(debug_mask & DEBUG_NETLINK))
return;
nftnl_obj_snprintf(buf, sizeof(buf), nln, 0, 0);
int err;
nlo = alloc_nftnl_obj(h, obj);
- netlink_dump_obj(nlo);
+ netlink_dump_obj(nlo, ctx->debug_mask);
err = mnl_nft_obj_batch_add(nlo, ctx->batch, flags, ctx->seqnum);
if (err < 0)
int err;
nlo = __alloc_nftnl_obj(h, type);
- netlink_dump_obj(nlo);
+ netlink_dump_obj(nlo, ctx->debug_mask);
err = mnl_nft_obj_batch_del(nlo, ctx->batch, 0, ctx->seqnum);
if (err < 0)
meta_expr_alloc(&netlink_location,
NFT_META_OIF), octx);
- proto_ctx_init(&ctx, nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY));
+ proto_ctx_init(&ctx, nftnl_trace_get_u32(nlt, NFTNL_TRACE_FAMILY), 0);
ll_desc = ctx.protocol[PROTO_BASE_LL_HDR].desc;
if ((ll_desc == &proto_inet || ll_desc == &proto_netdev) &&
nftnl_trace_is_set(nlt, NFTNL_TRACE_NFPROTO)) {
return nftnl_msg_types[type];
}
-static void netlink_events_debug(uint16_t type)
+static void netlink_events_debug(uint16_t type, unsigned int debug_mask)
{
- if (!(debug_level & DEBUG_NETLINK))
+ if (!(debug_mask & DEBUG_NETLINK))
return;
printf("netlink event: %s\n", nftnl_msgtype2str(type));
uint16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type);
struct netlink_mon_handler *monh = (struct netlink_mon_handler *)data;
- netlink_events_debug(type);
+ netlink_events_debug(type, monh->debug_mask);
netlink_events_cache_update(monh, nlh, type);
if (!(monh->monitor_flags & (1 << type)))
.monitor_flags = 0xffffffff,
.cache_needed = true,
.cache = ctx->cache,
+ .debug_mask = ctx->debug_mask,
};
if (!echo_monh.ctx->octx->echo)
}
int netlink_monitor(struct netlink_mon_handler *monhandler,
- struct mnl_socket *nf_sock)
+ struct mnl_socket *nf_sock)
{
+ struct mnl_ctx ctx = {
+ .nf_sock = nf_sock,
+ .debug_mask = monhandler->debug_mask,
+ };
int group;
if (monhandler->monitor_flags & (1 << NFT_MSG_TRACE)) {
strerror(errno));
}
- return mnl_nft_event_listener(nf_sock, netlink_events_cb, monhandler);
+ return mnl_nft_event_listener(&ctx, netlink_events_cb, monhandler);
}
bool netlink_batch_supported(struct mnl_socket *nf_sock, uint32_t *seqnum)
struct stmt *stmt, *next;
memset(&rctx, 0, sizeof(rctx));
- proto_ctx_init(&rctx.pctx, rule->handle.family);
+ proto_ctx_init(&rctx.pctx, rule->handle.family, ctx->debug_mask);
list_for_each_entry_safe(stmt, next, &rule->stmts, list) {
enum stmt_types type = stmt->ops->type;
memset(&_ctx, 0, sizeof(_ctx));
_ctx.msgs = ctx->msgs;
+ _ctx.debug_mask = ctx->debug_mask;
memset(&h, 0, sizeof(h));
h.family = nftnl_rule_get_u32(nlr, NFTNL_RULE_FAMILY);
nftnl_udata_buf_free(udata);
}
- netlink_dump_rule(nlr);
+ netlink_dump_rule(nlr, ctx->debug_mask);
}
#include "parser_bison.h"
void parser_init(struct mnl_socket *nf_sock, struct nft_cache *cache,
- struct parser_state *state, struct list_head *msgs)
+ struct parser_state *state, struct list_head *msgs,
+ unsigned int debug_mask)
{
memset(state, 0, sizeof(*state));
init_list_head(&state->cmds);
state->ectx.cache = cache;
state->ectx.msgs = msgs;
state->ectx.nf_sock = nf_sock;
+ state->ectx.debug_mask = debug_mask;
}
static void yyerror(struct location *loc, struct nft_ctx *nft, void *scanner,
%initial-action {
location_init(scanner, state, &yylloc);
- if (debug_level & DEBUG_SCANNER)
+ if (nft->debug_mask & DEBUG_SCANNER)
nft_set_debug(1, scanner);
- if (debug_level & DEBUG_PARSER)
+ if (nft->debug_mask & DEBUG_PARSER)
yydebug = 1;
}
[NFPROTO_ARP] = HOOK_PROTO_DESC(PROTO_BASE_NETWORK_HDR, &proto_arp),
};
-static void proto_ctx_debug(const struct proto_ctx *ctx, enum proto_bases base)
+static void proto_ctx_debug(const struct proto_ctx *ctx, enum proto_bases base,
+ unsigned int debug_mask)
{
unsigned int i;
- if (!(debug_level & DEBUG_PROTO_CTX))
+ if (!(debug_mask & DEBUG_NETLINK))
return;
pr_debug("update %s protocol context:\n", proto_base_names[base]);
*
* @ctx: protocol context
* @family: hook family
+ * @debug_mask: display debugging information
*/
-void proto_ctx_init(struct proto_ctx *ctx, unsigned int family)
+void proto_ctx_init(struct proto_ctx *ctx, unsigned int family,
+ unsigned int debug_mask)
{
const struct hook_proto_desc *h = &hook_proto_desc[family];
memset(ctx, 0, sizeof(*ctx));
ctx->family = family;
ctx->protocol[h->base].desc = h->desc;
+ ctx->debug_mask = debug_mask;
- proto_ctx_debug(ctx, h->base);
+ proto_ctx_debug(ctx, h->base, debug_mask);
}
/**
ctx->protocol[base].location = *loc;
ctx->protocol[base].desc = desc;
- proto_ctx_debug(ctx, base);
+ proto_ctx_debug(ctx, base, ctx->debug_mask);
}
#define HDR_TEMPLATE(__name, __dtype, __type, __member) \
}
static int cache_init(struct mnl_socket *nf_sock, struct nft_cache *cache,
- enum cmd_ops cmd, struct list_head *msgs)
+ enum cmd_ops cmd, struct list_head *msgs,
+ unsigned int debug_mask)
{
struct handle handle = {
.family = NFPROTO_UNSPEC,
ctx.cache = cache;
ctx.msgs = msgs;
ctx.seqnum = cache->seqnum++;
+ ctx.debug_mask = debug_mask;
ret = cache_init_tables(&ctx, &handle, cache);
if (ret < 0)
}
int cache_update(struct mnl_socket *nf_sock, struct nft_cache *cache,
- enum cmd_ops cmd, struct list_head *msgs)
+ enum cmd_ops cmd, struct list_head *msgs, bool debug)
{
int ret;
return 0;
replay:
netlink_genid_get(nf_sock, cache->seqnum++);
- ret = cache_init(nf_sock, cache, cmd, msgs);
+ ret = cache_init(nf_sock, cache, cmd, msgs, debug);
if (ret < 0) {
cache_release(cache);
if (errno == EINTR) {
set = set_lookup(table, h->set);
if (set->flags & NFT_SET_INTERVAL &&
- set_to_intervals(ctx->msgs, set, init, true) < 0)
+ set_to_intervals(ctx->msgs, set, init, true, ctx->debug_mask) < 0)
return -1;
return __do_add_setelems(ctx, h, set, init, flags);
{
if (set->init != NULL) {
if (set->flags & NFT_SET_INTERVAL &&
- set_to_intervals(ctx->msgs, set, set->init, true) < 0)
+ set_to_intervals(ctx->msgs, set, set->init, true,
+ ctx->debug_mask) < 0)
return -1;
}
if (netlink_add_set(ctx, h, set, flags) < 0)
if (ctx->octx->echo) {
int ret;
- ret = cache_update(ctx->nf_sock, ctx->cache,
- cmd->obj, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, ctx->cache, cmd->obj,
+ ctx->msgs, ctx->debug_mask);
if (ret < 0)
return ret;
if (ctx->octx->echo) {
int ret;
- ret = cache_update(ctx->nf_sock, ctx->cache,
- cmd->obj, ctx->msgs);
+ ret = cache_update(ctx->nf_sock, ctx->cache, cmd->obj,
+ ctx->msgs, ctx->debug_mask);
if (ret < 0)
return ret;
set = set_lookup(table, h->set);
if (set->flags & NFT_SET_INTERVAL &&
- set_to_intervals(ctx->msgs, set, expr, false) < 0)
+ set_to_intervals(ctx->msgs, set, expr, false, ctx->debug_mask) < 0)
return -1;
if (netlink_delete_setelems(ctx, h, expr) < 0)
* @type: the datatype of the dimension
* @dwidth: width of the dimension
* @byteorder: byteorder of elements
+ * @debug_mask: display debugging information
*/
struct seg_tree {
struct rb_root root;
const struct datatype *datatype;
unsigned int datalen;
enum byteorder byteorder;
+ unsigned int debug_mask;
};
enum elementary_interval_flags {
static struct output_ctx debug_octx = {};
static void seg_tree_init(struct seg_tree *tree, const struct set *set,
- struct expr *init)
+ struct expr *init, unsigned int debug_mask)
{
struct expr *first;
tree->datatype = set->datatype;
tree->datalen = set->datalen;
tree->byteorder = first->byteorder;
+ tree->debug_mask = debug_mask;
}
static struct elementary_interval *ei_alloc(const mpz_t left, const mpz_t right,
rb_insert_color(&new->rb_node, &tree->root);
}
-static bool segtree_debug(void)
+static bool segtree_debug(unsigned int debug_mask)
{
- if (debug_level & DEBUG_SEGTREE)
+ if (debug_mask & DEBUG_SEGTREE)
return true;
return false;
lei = ei_lookup(tree, new->left);
rei = ei_lookup(tree, new->right);
- if (segtree_debug())
+ if (segtree_debug(tree->debug_mask))
pr_gmp_debug("insert: [%Zx %Zx]\n", new->left, new->right);
if (lei != NULL && rei != NULL && lei == rei) {
*
* [lei_left, new_left) and (new_right, rei_right]
*/
- if (segtree_debug())
+ if (segtree_debug(tree->debug_mask))
pr_gmp_debug("split [%Zx %Zx]\n", lei->left, lei->right);
ei_remove(tree, lei);
*
* [lei_left, new_left)[new_left, new_right]
*/
- if (segtree_debug()) {
+ if (segtree_debug(tree->debug_mask)) {
pr_gmp_debug("adjust left [%Zx %Zx]\n",
lei->left, lei->right);
}
*
* [new_left, new_right](new_right, rei_right]
*/
- if (segtree_debug()) {
+ if (segtree_debug(tree->debug_mask)) {
pr_gmp_debug("adjust right [%Zx %Zx]\n",
rei->left, rei->right);
}
* Convert the tree of open intervals to half-closed map expressions.
*/
rb_for_each_entry_safe(ei, node, next, &tree->root, rb_node) {
- if (segtree_debug())
+ if (segtree_debug(tree->debug_mask))
pr_gmp_debug("iter: [%Zx %Zx]\n", ei->left, ei->right);
if (prev == NULL) {
}
int set_to_intervals(struct list_head *errs, struct set *set,
- struct expr *init, bool add)
+ struct expr *init, bool add, unsigned int debug_mask)
{
struct elementary_interval *ei, *next;
struct seg_tree tree;
LIST_HEAD(list);
- seg_tree_init(&tree, set, init);
+ seg_tree_init(&tree, set, init, debug_mask);
if (set_to_segtree(errs, set, init, &tree, add) < 0)
return -1;
segtree_linearize(&list, set, init, &tree, add);
init->size = 0;
list_for_each_entry_safe(ei, next, &list, list) {
- if (segtree_debug()) {
+ if (segtree_debug(tree.debug_mask)) {
pr_gmp_debug("list: [%.*Zx %.*Zx]\n",
2 * tree.keylen / BITS_PER_BYTE, ei->left,
2 * tree.keylen / BITS_PER_BYTE, ei->right);
ei_destroy(ei);
}
- if (segtree_debug()) {
+ if (segtree_debug(tree.debug_mask)) {
expr_print(init, &debug_octx);
pr_gmp_debug("\n");
}