|
Packit |
c5a612 |
#define _GNU_SOURCE
|
|
Packit |
c5a612 |
#include <string.h>
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
#include <expression.h>
|
|
Packit |
c5a612 |
#include <list.h>
|
|
Packit |
c5a612 |
#include <netlink.h>
|
|
Packit |
c5a612 |
#include <rule.h>
|
|
Packit |
c5a612 |
#include <rt.h>
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
#include <netdb.h>
|
|
Packit |
c5a612 |
#include <netinet/icmp6.h>
|
|
Packit |
c5a612 |
#include <netinet/in.h>
|
|
Packit |
c5a612 |
#include <netinet/ip.h>
|
|
Packit |
c5a612 |
#include <netinet/ip_icmp.h>
|
|
Packit |
c5a612 |
#include <linux/netfilter.h>
|
|
Packit |
c5a612 |
#include <linux/netfilter/nf_log.h>
|
|
Packit |
c5a612 |
#include <linux/netfilter/nf_nat.h>
|
|
Packit |
c5a612 |
#include <linux/netfilter/nf_tables.h>
|
|
Packit |
c5a612 |
#include <linux/netfilter/nf_synproxy.h>
|
|
Packit |
c5a612 |
#include <linux/xfrm.h>
|
|
Packit |
c5a612 |
#include <pwd.h>
|
|
Packit |
c5a612 |
#include <grp.h>
|
|
Packit |
c5a612 |
#include <jansson.h>
|
|
Packit |
c5a612 |
#include <syslog.h>
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
#ifdef DEBUG
|
|
Packit |
c5a612 |
#define __json_pack json_pack
|
|
Packit |
c5a612 |
#define json_pack(...) ({ \
|
|
Packit |
c5a612 |
json_t *__out = __json_pack(__VA_ARGS__); \
|
|
Packit |
c5a612 |
assert(__out); \
|
|
Packit |
c5a612 |
__out; \
|
|
Packit |
c5a612 |
})
|
|
Packit |
c5a612 |
#endif
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *expr_print_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const struct expr_ops *ops;
|
|
Packit |
c5a612 |
char buf[1024];
|
|
Packit |
c5a612 |
FILE *fp;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
ops = expr_ops(expr);
|
|
Packit |
c5a612 |
if (ops->json)
|
|
Packit |
c5a612 |
return ops->json(expr, octx);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
printf("warning: expr ops %s have no json callback\n", expr_name(expr));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
fp = octx->output_fp;
|
|
Packit |
c5a612 |
octx->output_fp = fmemopen(buf, 1024, "w");
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
ops->print(expr, octx);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
fclose(octx->output_fp);
|
|
Packit |
c5a612 |
octx->output_fp = fp;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("s", buf);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *set_dtype_json(const struct expr *key)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
char *namedup = xstrdup(key->dtype->name), *tok;
|
|
Packit |
c5a612 |
json_t *root = NULL;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
tok = strtok(namedup, " .");
|
|
Packit |
c5a612 |
while (tok) {
|
|
Packit |
c5a612 |
json_t *jtok = json_string(xstrdup(tok));
|
|
Packit |
c5a612 |
if (!root)
|
|
Packit |
c5a612 |
root = jtok;
|
|
Packit |
c5a612 |
else if (json_is_string(root))
|
|
Packit |
c5a612 |
root = json_pack("[o, o]", root, jtok);
|
|
Packit |
c5a612 |
else
|
|
Packit |
c5a612 |
json_array_append_new(root, jtok);
|
|
Packit |
c5a612 |
tok = strtok(NULL, " .");
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
xfree(namedup);
|
|
Packit |
c5a612 |
return root;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *set_print_json(struct output_ctx *octx, const struct set *set)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root, *tmp;
|
|
Packit |
c5a612 |
const char *type, *datatype_ext = NULL;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (set_is_datamap(set->flags)) {
|
|
Packit |
c5a612 |
type = "map";
|
|
Packit |
c5a612 |
datatype_ext = set->datatype->name;
|
|
Packit |
c5a612 |
} else if (set_is_objmap(set->flags)) {
|
|
Packit |
c5a612 |
type = "map";
|
|
Packit |
c5a612 |
datatype_ext = obj_type_name(set->objtype);
|
|
Packit |
c5a612 |
} else if (set_is_meter(set->flags)) {
|
|
Packit |
c5a612 |
type = "meter";
|
|
Packit |
c5a612 |
} else {
|
|
Packit |
c5a612 |
type = "set";
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:s, s:s, s:s, s:o, s:I}",
|
|
Packit |
c5a612 |
"family", family2str(set->handle.family),
|
|
Packit |
c5a612 |
"name", set->handle.set.name,
|
|
Packit |
c5a612 |
"table", set->handle.table.name,
|
|
Packit |
c5a612 |
"type", set_dtype_json(set->key),
|
|
Packit |
c5a612 |
"handle", set->handle.handle.id);
|
|
Packit |
c5a612 |
if (datatype_ext)
|
|
Packit |
c5a612 |
json_object_set_new(root, "map", json_string(datatype_ext));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (!(set->flags & (NFT_SET_CONSTANT))) {
|
|
Packit |
c5a612 |
if (set->policy != NFT_SET_POL_PERFORMANCE) {
|
|
Packit |
c5a612 |
tmp = json_pack("s", set_policy2str(set->policy));
|
|
Packit |
c5a612 |
json_object_set_new(root, "policy", tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
if (set->desc.size) {
|
|
Packit |
c5a612 |
tmp = json_pack("i", set->desc.size);
|
|
Packit |
c5a612 |
json_object_set_new(root, "size", tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
tmp = json_array();
|
|
Packit |
c5a612 |
if (set->flags & NFT_SET_CONSTANT)
|
|
Packit |
c5a612 |
json_array_append_new(tmp, json_pack("s", "constant"));
|
|
Packit |
c5a612 |
if (set->flags & NFT_SET_INTERVAL)
|
|
Packit |
c5a612 |
json_array_append_new(tmp, json_pack("s", "interval"));
|
|
Packit |
c5a612 |
if (set->flags & NFT_SET_TIMEOUT)
|
|
Packit |
c5a612 |
json_array_append_new(tmp, json_pack("s", "timeout"));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (json_array_size(tmp) > 0) {
|
|
Packit |
c5a612 |
json_object_set_new(root, "flags", tmp);
|
|
Packit |
c5a612 |
} else {
|
|
Packit |
c5a612 |
if (json_array_size(tmp))
|
|
Packit |
c5a612 |
json_object_set(root, "flags", json_array_get(tmp, 0));
|
|
Packit |
c5a612 |
json_decref(tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (set->timeout) {
|
|
Packit |
c5a612 |
tmp = json_integer(set->timeout / 1000);
|
|
Packit |
c5a612 |
json_object_set_new(root, "timeout", tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
if (set->gc_int) {
|
|
Packit |
c5a612 |
tmp = json_pack("i", set->gc_int / 1000);
|
|
Packit |
c5a612 |
json_object_set_new(root, "gc-interval", tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (set->init && set->init->size > 0) {
|
|
Packit |
c5a612 |
json_t *array = json_array();
|
|
Packit |
c5a612 |
const struct expr *i;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(i, &set->init->expressions, list)
|
|
Packit |
c5a612 |
json_array_append_new(array, expr_print_json(i, octx));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_object_set_new(root, "elem", array);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", type, root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
/* XXX: Merge with set_print_json()? */
|
|
Packit |
c5a612 |
static json_t *element_print_json(struct output_ctx *octx,
|
|
Packit |
c5a612 |
const struct set *set)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root = expr_print_json(set->init, octx);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s: {s:s, s:s, s:s, s:o}}", "element",
|
|
Packit |
c5a612 |
"family", family2str(set->handle.family),
|
|
Packit |
c5a612 |
"table", set->handle.table.name,
|
|
Packit |
c5a612 |
"name", set->handle.set.name,
|
|
Packit |
c5a612 |
"elem", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *stmt_print_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
char buf[1024];
|
|
Packit |
c5a612 |
FILE *fp;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
/* XXX: Can't be supported at this point:
|
|
Packit |
c5a612 |
* xt_stmt_xlate() ignores output_fp.
|
|
Packit |
c5a612 |
*/
|
|
Packit |
c5a612 |
if (stmt->ops->type == STMT_XT)
|
|
Packit |
c5a612 |
return json_pack("{s:n}", "xt");
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->ops->json)
|
|
Packit |
c5a612 |
return stmt->ops->json(stmt, octx);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
printf("warning: stmt ops %s have no json callback\n",
|
|
Packit |
c5a612 |
stmt->ops->name);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
fp = octx->output_fp;
|
|
Packit |
c5a612 |
octx->output_fp = fmemopen(buf, 1024, "w");
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
stmt->ops->print(stmt, octx);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
fclose(octx->output_fp);
|
|
Packit |
c5a612 |
octx->output_fp = fp;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("s", buf);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *rule_print_json(struct output_ctx *octx,
|
|
Packit |
c5a612 |
const struct rule *rule)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const struct stmt *stmt;
|
|
Packit |
c5a612 |
json_t *root, *tmp;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:s, s:s, s:s, s:I}",
|
|
Packit |
c5a612 |
"family", family2str(rule->handle.family),
|
|
Packit |
c5a612 |
"table", rule->handle.table.name,
|
|
Packit |
c5a612 |
"chain", rule->handle.chain.name,
|
|
Packit |
c5a612 |
"handle", rule->handle.handle.id);
|
|
Packit |
c5a612 |
if (rule->comment)
|
|
Packit |
c5a612 |
json_object_set_new(root, "comment",
|
|
Packit |
c5a612 |
json_string(rule->comment));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
tmp = json_array();
|
|
Packit |
c5a612 |
list_for_each_entry(stmt, &rule->stmts, list)
|
|
Packit |
c5a612 |
json_array_append_new(tmp, stmt_print_json(stmt, octx));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (json_array_size(tmp))
|
|
Packit |
c5a612 |
json_object_set_new(root, "expr", tmp);
|
|
Packit |
c5a612 |
else {
|
|
Packit |
c5a612 |
fprintf(stderr, "rule without statements?!\n");
|
|
Packit |
c5a612 |
json_decref(tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "rule", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *chain_print_json(const struct chain *chain)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
int priority, policy, n = 0;
|
|
Packit |
c5a612 |
struct expr *dev, *expr;
|
|
Packit |
c5a612 |
json_t *root, *tmp;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:s, s:s, s:s, s:I}",
|
|
Packit |
c5a612 |
"family", family2str(chain->handle.family),
|
|
Packit |
c5a612 |
"table", chain->handle.table.name,
|
|
Packit |
c5a612 |
"name", chain->handle.chain.name,
|
|
Packit |
c5a612 |
"handle", chain->handle.handle.id);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (chain->flags & CHAIN_F_BASECHAIN) {
|
|
Packit |
c5a612 |
mpz_export_data(&priority, chain->priority.expr->value,
|
|
Packit |
c5a612 |
BYTEORDER_HOST_ENDIAN, sizeof(int));
|
|
Packit |
c5a612 |
mpz_export_data(&policy, chain->policy->value,
|
|
Packit |
c5a612 |
BYTEORDER_HOST_ENDIAN, sizeof(int));
|
|
Packit |
c5a612 |
tmp = json_pack("{s:s, s:s, s:i, s:s}",
|
|
Packit |
c5a612 |
"type", chain->type,
|
|
Packit |
c5a612 |
"hook", hooknum2str(chain->handle.family,
|
|
Packit |
c5a612 |
chain->hooknum),
|
|
Packit |
c5a612 |
"prio", priority,
|
|
Packit |
c5a612 |
"policy", chain_policy2str(policy));
|
|
Packit |
c5a612 |
if (chain->dev_expr) {
|
|
Packit |
c5a612 |
list_for_each_entry(expr, &chain->dev_expr->expressions, list) {
|
|
Packit |
c5a612 |
dev = expr;
|
|
Packit |
c5a612 |
n++;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (n == 1) {
|
|
Packit |
c5a612 |
json_object_set_new(tmp, "dev",
|
|
Packit |
c5a612 |
json_string(dev->identifier));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
json_object_update(root, tmp);
|
|
Packit |
c5a612 |
json_decref(tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "chain", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *proto_name_json(uint8_t proto)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const struct protoent *p = getprotobynumber(proto);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (p)
|
|
Packit |
c5a612 |
return json_string(p->p_name);
|
|
Packit |
c5a612 |
return json_integer(proto);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *timeout_policy_json(uint8_t l4, const uint32_t *timeout)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root = NULL;
|
|
Packit |
c5a612 |
unsigned int i;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
for (i = 0; i < timeout_protocol[l4].array_size; i++) {
|
|
Packit |
c5a612 |
if (timeout[i] == timeout_protocol[l4].dflt_timeout[i])
|
|
Packit |
c5a612 |
continue;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (!root)
|
|
Packit |
c5a612 |
root = json_object();
|
|
Packit |
c5a612 |
json_object_set_new(root, timeout_protocol[l4].state_to_name[i],
|
|
Packit |
c5a612 |
json_integer(timeout[i]));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
return root ? : json_null();
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *obj_print_json(const struct obj *obj)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const char *rate_unit = NULL, *burst_unit = NULL;
|
|
Packit |
c5a612 |
const char *type = obj_type_name(obj->type);
|
|
Packit |
c5a612 |
json_t *root, *tmp, *flags;
|
|
Packit |
c5a612 |
uint64_t rate, burst;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:s, s:s, s:s, s:I}",
|
|
Packit |
c5a612 |
"family", family2str(obj->handle.family),
|
|
Packit |
c5a612 |
"name", obj->handle.obj.name,
|
|
Packit |
c5a612 |
"table", obj->handle.table.name,
|
|
Packit |
c5a612 |
"handle", obj->handle.handle.id);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
switch (obj->type) {
|
|
Packit |
c5a612 |
case NFT_OBJECT_COUNTER:
|
|
Packit |
c5a612 |
tmp = json_pack("{s:I, s:I}",
|
|
Packit |
c5a612 |
"packets", obj->counter.packets,
|
|
Packit |
c5a612 |
"bytes", obj->counter.bytes);
|
|
Packit |
c5a612 |
json_object_update(root, tmp);
|
|
Packit |
c5a612 |
json_decref(tmp);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFT_OBJECT_QUOTA:
|
|
Packit |
c5a612 |
tmp = json_pack("{s:I, s:I, s:b}",
|
|
Packit |
c5a612 |
"bytes", obj->quota.bytes,
|
|
Packit |
c5a612 |
"used", obj->quota.used,
|
|
Packit |
c5a612 |
"inv", obj->quota.flags & NFT_QUOTA_F_INV);
|
|
Packit |
c5a612 |
json_object_update(root, tmp);
|
|
Packit |
c5a612 |
json_decref(tmp);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFT_OBJECT_SECMARK:
|
|
Packit |
c5a612 |
tmp = json_pack("{s:s}",
|
|
Packit |
c5a612 |
"context", obj->secmark.ctx);
|
|
Packit |
c5a612 |
json_object_update(root, tmp);
|
|
Packit |
c5a612 |
json_decref(tmp);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFT_OBJECT_CT_HELPER:
|
|
Packit |
c5a612 |
tmp = json_pack("{s:s, s:o, s:s}",
|
|
Packit |
c5a612 |
"type", obj->ct_helper.name, "protocol",
|
|
Packit |
c5a612 |
proto_name_json(obj->ct_helper.l4proto),
|
|
Packit |
c5a612 |
"l3proto", family2str(obj->ct_helper.l3proto));
|
|
Packit |
c5a612 |
json_object_update(root, tmp);
|
|
Packit |
c5a612 |
json_decref(tmp);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFT_OBJECT_CT_TIMEOUT:
|
|
Packit |
c5a612 |
tmp = timeout_policy_json(obj->ct_timeout.l4proto,
|
|
Packit |
c5a612 |
obj->ct_timeout.timeout);
|
|
Packit |
c5a612 |
tmp = json_pack("{s:o, s:s, s:o}",
|
|
Packit |
c5a612 |
"protocol",
|
|
Packit |
c5a612 |
proto_name_json(obj->ct_timeout.l4proto),
|
|
Packit |
c5a612 |
"l3proto", family2str(obj->ct_timeout.l3proto),
|
|
Packit |
c5a612 |
"policy", tmp);
|
|
Packit |
c5a612 |
json_object_update(root, tmp);
|
|
Packit |
c5a612 |
json_decref(tmp);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFT_OBJECT_CT_EXPECT:
|
|
Packit |
c5a612 |
tmp = json_pack("{s:o, s:I, s:I, s:I, s:s}",
|
|
Packit |
c5a612 |
"protocol",
|
|
Packit |
c5a612 |
proto_name_json(obj->ct_expect.l4proto),
|
|
Packit |
c5a612 |
"dport", obj->ct_expect.dport,
|
|
Packit |
c5a612 |
"timeout", obj->ct_expect.timeout,
|
|
Packit |
c5a612 |
"size", obj->ct_expect.size,
|
|
Packit |
c5a612 |
"l3proto", family2str(obj->ct_expect.l3proto));
|
|
Packit |
c5a612 |
json_object_update(root, tmp);
|
|
Packit |
c5a612 |
json_decref(tmp);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFT_OBJECT_LIMIT:
|
|
Packit |
c5a612 |
rate = obj->limit.rate;
|
|
Packit |
c5a612 |
burst = obj->limit.burst;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (obj->limit.type == NFT_LIMIT_PKT_BYTES) {
|
|
Packit |
c5a612 |
rate_unit = get_rate(obj->limit.rate, &rate;;
|
|
Packit |
c5a612 |
burst_unit = get_rate(obj->limit.burst, &burst);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
tmp = json_pack("{s:I, s:s}",
|
|
Packit |
c5a612 |
"rate", rate,
|
|
Packit |
c5a612 |
"per", get_unit(obj->limit.unit));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (obj->limit.flags & NFT_LIMIT_F_INV)
|
|
Packit |
c5a612 |
json_object_set_new(tmp, "inv", json_true());
|
|
Packit |
c5a612 |
if (rate_unit)
|
|
Packit |
c5a612 |
json_object_set_new(tmp, "rate_unit",
|
|
Packit |
c5a612 |
json_string(rate_unit));
|
|
Packit |
c5a612 |
if (burst) {
|
|
Packit |
c5a612 |
json_object_set_new(tmp, "burst", json_integer(burst));
|
|
Packit |
c5a612 |
if (burst_unit)
|
|
Packit |
c5a612 |
json_object_set_new(tmp, "burst_unit",
|
|
Packit |
c5a612 |
json_string(burst_unit));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_object_update(root, tmp);
|
|
Packit |
c5a612 |
json_decref(tmp);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFT_OBJECT_SYNPROXY:
|
|
Packit |
c5a612 |
flags = json_array();
|
|
Packit |
c5a612 |
tmp = json_pack("{s:i, s:i}",
|
|
Packit |
c5a612 |
"mss", obj->synproxy.mss,
|
|
Packit |
c5a612 |
"wscale", obj->synproxy.wscale);
|
|
Packit |
c5a612 |
if (obj->synproxy.flags & NF_SYNPROXY_OPT_TIMESTAMP)
|
|
Packit |
c5a612 |
json_array_append_new(flags, json_string("timestamp"));
|
|
Packit |
c5a612 |
if (obj->synproxy.flags & NF_SYNPROXY_OPT_SACK_PERM)
|
|
Packit |
c5a612 |
json_array_append_new(flags, json_string("sack-perm"));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (json_array_size(flags) > 0)
|
|
Packit |
c5a612 |
json_object_set_new(tmp, "flags", flags);
|
|
Packit |
c5a612 |
else
|
|
Packit |
c5a612 |
json_decref(flags);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_object_update(root, tmp);
|
|
Packit |
c5a612 |
json_decref(tmp);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", type, root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *flowtable_print_json(const struct flowtable *ftable)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root, *devs = NULL;
|
|
Packit |
c5a612 |
int i, priority;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
mpz_export_data(&priority, ftable->priority.expr->value,
|
|
Packit |
c5a612 |
BYTEORDER_HOST_ENDIAN, sizeof(int));
|
|
Packit |
c5a612 |
root = json_pack("{s:s, s:s, s:s, s:I, s:s, s:i}",
|
|
Packit |
c5a612 |
"family", family2str(ftable->handle.family),
|
|
Packit |
c5a612 |
"name", ftable->handle.flowtable.name,
|
|
Packit |
c5a612 |
"table", ftable->handle.table.name,
|
|
Packit |
c5a612 |
"handle", ftable->handle.handle.id,
|
|
Packit |
c5a612 |
"hook", hooknum2str(NFPROTO_NETDEV, ftable->hooknum),
|
|
Packit |
c5a612 |
"prio", priority);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
for (i = 0; i < ftable->dev_array_len; i++) {
|
|
Packit |
c5a612 |
const char *dev = ftable->dev_array[i];
|
|
Packit |
c5a612 |
if (!devs)
|
|
Packit |
c5a612 |
devs = json_string(dev);
|
|
Packit |
c5a612 |
else if (json_is_string(devs))
|
|
Packit |
c5a612 |
devs = json_pack("[o, s]", devs, dev);
|
|
Packit |
c5a612 |
else
|
|
Packit |
c5a612 |
json_array_append_new(devs, json_string(dev));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
if (devs)
|
|
Packit |
c5a612 |
json_object_set_new(root, "dev", devs);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "flowtable", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *table_flags_json(const struct table *table)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
uint32_t flags = table->flags;
|
|
Packit |
c5a612 |
json_t *root = json_array(), *tmp;
|
|
Packit |
c5a612 |
int i = 0;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
while (flags) {
|
|
Packit |
c5a612 |
if (flags & 0x1) {
|
|
Packit |
c5a612 |
tmp = json_string(table_flags_name[i]);
|
|
Packit |
c5a612 |
json_array_append_new(root, tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
flags >>= 1;
|
|
Packit |
c5a612 |
i++;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
switch (json_array_size(root)) {
|
|
Packit |
c5a612 |
case 0:
|
|
Packit |
c5a612 |
json_decref(root);
|
|
Packit |
c5a612 |
return NULL;
|
|
Packit |
c5a612 |
case 1:
|
|
Packit |
c5a612 |
json_unpack(root, "[o]", &tmp);
|
|
Packit |
c5a612 |
json_decref(root);
|
|
Packit |
c5a612 |
root = tmp;
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
return root;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *table_print_json(const struct table *table)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root, *tmp;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:s, s:s, s:I}",
|
|
Packit |
c5a612 |
"family", family2str(table->handle.family),
|
|
Packit |
c5a612 |
"name", table->handle.table.name,
|
|
Packit |
c5a612 |
"handle", table->handle.handle.id);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
tmp = table_flags_json(table);
|
|
Packit |
c5a612 |
if (tmp)
|
|
Packit |
c5a612 |
json_object_set_new(root, "flags", tmp);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "table", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *binop_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return json_pack("{s:[o, o]}", expr_op_symbols[expr->op],
|
|
Packit |
c5a612 |
expr_print_json(expr->left, octx),
|
|
Packit |
c5a612 |
expr_print_json(expr->right, octx));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *relational_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return json_pack("{s:{s:s, s:o, s:o}}", "match",
|
|
Packit |
c5a612 |
"op", expr_op_symbols[expr->op] ? : "in",
|
|
Packit |
c5a612 |
"left", expr_print_json(expr->left, octx),
|
|
Packit |
c5a612 |
"right", expr_print_json(expr->right, octx));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *range_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
unsigned int flags = octx->flags;
|
|
Packit |
c5a612 |
json_t *root;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
octx->flags &= ~NFT_CTX_OUTPUT_SERVICE;
|
|
Packit |
c5a612 |
octx->flags |= NFT_CTX_OUTPUT_NUMERIC_PROTO;
|
|
Packit |
c5a612 |
root = json_pack("{s:[o, o]}", "range",
|
|
Packit |
c5a612 |
expr_print_json(expr->left, octx),
|
|
Packit |
c5a612 |
expr_print_json(expr->right, octx));
|
|
Packit |
c5a612 |
octx->flags = flags;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return root;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *meta_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return json_pack("{s:{s:s}}", "meta",
|
|
Packit |
c5a612 |
"key", meta_templates[expr->meta.key].token);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *payload_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (payload_is_known(expr))
|
|
Packit |
c5a612 |
root = json_pack("{s:s, s:s}",
|
|
Packit |
c5a612 |
"protocol", expr->payload.desc->name,
|
|
Packit |
c5a612 |
"field", expr->payload.tmpl->token);
|
|
Packit |
c5a612 |
else
|
|
Packit |
c5a612 |
root = json_pack("{s:s, s:i, s:i}",
|
|
Packit |
c5a612 |
"base", proto_base_tokens[expr->payload.base],
|
|
Packit |
c5a612 |
"offset", expr->payload.offset,
|
|
Packit |
c5a612 |
"len", expr->len);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "payload", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *ct_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const char *dirstr = ct_dir2str(expr->ct.direction);
|
|
Packit |
c5a612 |
enum nft_ct_keys key = expr->ct.key;
|
|
Packit |
c5a612 |
json_t *root;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:s}", "key", ct_templates[key].token);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (expr->ct.direction < 0)
|
|
Packit |
c5a612 |
goto out;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (dirstr)
|
|
Packit |
c5a612 |
json_object_set_new(root, "dir", json_string(dirstr));
|
|
Packit |
c5a612 |
out:
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "ct", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *concat_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *array = json_array();
|
|
Packit |
c5a612 |
const struct expr *i;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(i, &expr->expressions, list)
|
|
Packit |
c5a612 |
json_array_append_new(array, expr_print_json(i, octx));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "concat", array);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *set_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *array = json_array();
|
|
Packit |
c5a612 |
const struct expr *i;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(i, &expr->expressions, list)
|
|
Packit |
c5a612 |
json_array_append_new(array, expr_print_json(i, octx));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "set", array);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *set_ref_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
if (set_is_anonymous(expr->set->flags)) {
|
|
Packit |
c5a612 |
return expr_print_json(expr->set->init, octx);
|
|
Packit |
c5a612 |
} else {
|
|
Packit |
c5a612 |
return json_pack("s+", "@", expr->set->handle.set.name);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *set_elem_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root = expr_print_json(expr->key, octx);
|
|
Packit |
c5a612 |
json_t *tmp;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (!root)
|
|
Packit |
c5a612 |
return NULL;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
/* these element attributes require formal set elem syntax */
|
|
Packit |
c5a612 |
if (expr->timeout || expr->expiration || expr->comment) {
|
|
Packit |
c5a612 |
root = json_pack("{s:o}", "val", root);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (expr->timeout) {
|
|
Packit |
c5a612 |
tmp = json_integer(expr->timeout / 1000);
|
|
Packit |
c5a612 |
json_object_set_new(root, "timeout", tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
if (expr->expiration) {
|
|
Packit |
c5a612 |
tmp = json_integer(expr->expiration / 1000);
|
|
Packit |
c5a612 |
json_object_set_new(root, "expires", tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
if (expr->comment) {
|
|
Packit |
c5a612 |
tmp = json_string(expr->comment);
|
|
Packit |
c5a612 |
json_object_set_new(root, "comment", tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "elem", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return root;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *prefix_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root = expr_print_json(expr->prefix, octx);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:{s:o, s:i}}", "prefix",
|
|
Packit |
c5a612 |
"addr", root,
|
|
Packit |
c5a612 |
"len", expr->prefix_len);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *list_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *array = json_array();
|
|
Packit |
c5a612 |
const struct expr *i;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(i, &expr->expressions, list)
|
|
Packit |
c5a612 |
json_array_append_new(array, expr_print_json(i, octx));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
//return json_pack("{s:s, s:o}", "type", "list", "val", array);
|
|
Packit |
c5a612 |
return array;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *unary_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return expr_print_json(expr->arg, octx);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *mapping_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return json_pack("[o, o]",
|
|
Packit |
c5a612 |
expr_print_json(expr->left, octx),
|
|
Packit |
c5a612 |
expr_print_json(expr->right, octx));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *map_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const char *type = "map";
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (expr->mappings->etype == EXPR_SET_REF &&
|
|
Packit |
c5a612 |
expr->mappings->set->datatype->type == TYPE_VERDICT)
|
|
Packit |
c5a612 |
type = "vmap";
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:{s:o, s:o}}", type,
|
|
Packit |
c5a612 |
"key", expr_print_json(expr->map, octx),
|
|
Packit |
c5a612 |
"data", expr_print_json(expr->mappings, octx));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *exthdr_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const char *desc = expr->exthdr.desc ?
|
|
Packit |
c5a612 |
expr->exthdr.desc->name :
|
|
Packit |
c5a612 |
"unknown-exthdr";
|
|
Packit |
c5a612 |
const char *field = expr->exthdr.tmpl->token;
|
|
Packit |
c5a612 |
json_t *root;
|
|
Packit |
c5a612 |
bool is_exists = expr->exthdr.flags & NFT_EXTHDR_F_PRESENT;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (expr->exthdr.op == NFT_EXTHDR_OP_TCPOPT) {
|
|
Packit |
c5a612 |
unsigned int offset = expr->exthdr.offset / 64;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (offset) {
|
|
Packit |
c5a612 |
const char *offstrs[] = { "0", "1", "2", "3" };
|
|
Packit |
c5a612 |
const char *offstr = "";
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (offset < 4)
|
|
Packit |
c5a612 |
offstr = offstrs[offset];
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:s+}", "name", desc, offstr);
|
|
Packit |
c5a612 |
} else {
|
|
Packit |
c5a612 |
root = json_pack("{s:s}", "name", desc);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (!is_exists)
|
|
Packit |
c5a612 |
json_object_set_new(root, "field", json_string(field));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "tcp option", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
if (expr->exthdr.op == NFT_EXTHDR_OP_IPV4) {
|
|
Packit |
c5a612 |
root = json_pack("{s:s}", "name", desc);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (!is_exists)
|
|
Packit |
c5a612 |
json_object_set_new(root, "field", json_string(field));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "ip option", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:s}",
|
|
Packit |
c5a612 |
"name", desc);
|
|
Packit |
c5a612 |
if (!is_exists)
|
|
Packit |
c5a612 |
json_object_set_new(root, "field", json_string(field));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "exthdr", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *verdict_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const struct {
|
|
Packit |
c5a612 |
int verdict;
|
|
Packit |
c5a612 |
const char *name;
|
|
Packit |
c5a612 |
bool chain;
|
|
Packit |
c5a612 |
} verdict_tbl[] = {
|
|
Packit |
c5a612 |
{ NFT_CONTINUE, "continue", false },
|
|
Packit |
c5a612 |
{ NFT_BREAK, "break", false },
|
|
Packit |
c5a612 |
{ NFT_JUMP, "jump", true },
|
|
Packit |
c5a612 |
{ NFT_GOTO, "goto", true },
|
|
Packit |
c5a612 |
{ NFT_RETURN, "return", false },
|
|
Packit |
c5a612 |
{ NF_ACCEPT, "accept", false },
|
|
Packit |
c5a612 |
{ NF_DROP, "drop", false },
|
|
Packit |
c5a612 |
{ NF_QUEUE, "queue", false },
|
|
Packit |
c5a612 |
};
|
|
Packit |
c5a612 |
const char *name = NULL;
|
|
Packit |
c5a612 |
json_t *chain = NULL;
|
|
Packit |
c5a612 |
unsigned int i;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
for (i = 0; i < array_size(verdict_tbl); i++) {
|
|
Packit |
c5a612 |
if (expr->verdict == verdict_tbl[i].verdict) {
|
|
Packit |
c5a612 |
name = verdict_tbl[i].name;
|
|
Packit |
c5a612 |
if (verdict_tbl[i].chain && expr->chain)
|
|
Packit |
c5a612 |
chain = expr_print_json(expr->chain, octx);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
if (!name) {
|
|
Packit |
c5a612 |
BUG("Unknown verdict %d.", expr->verdict);
|
|
Packit |
c5a612 |
return NULL;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
if (chain)
|
|
Packit |
c5a612 |
return json_pack("{s:{s:o}}", name, "target", chain);
|
|
Packit |
c5a612 |
else
|
|
Packit |
c5a612 |
return json_pack("{s:n}", name);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *rt_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const char *key = rt_templates[expr->rt.key].token;
|
|
Packit |
c5a612 |
json_t *root = json_pack("{s:s}", "key", key);
|
|
Packit |
c5a612 |
const char *family = NULL;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
switch (expr->rt.key) {
|
|
Packit |
c5a612 |
case NFT_RT_NEXTHOP4:
|
|
Packit |
c5a612 |
family = "ip";
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFT_RT_NEXTHOP6:
|
|
Packit |
c5a612 |
family = "ip6";
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
default:
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (family)
|
|
Packit |
c5a612 |
json_object_set_new(root, "family", json_string(family));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "rt", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *numgen_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const char *mode;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
switch (expr->numgen.type) {
|
|
Packit |
c5a612 |
case NFT_NG_INCREMENTAL:
|
|
Packit |
c5a612 |
mode = "inc";
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFT_NG_RANDOM:
|
|
Packit |
c5a612 |
mode = "random";
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
default:
|
|
Packit |
c5a612 |
mode = "unknown";
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:{s:s, s:i, s:i}}", "numgen",
|
|
Packit |
c5a612 |
"mode", mode,
|
|
Packit |
c5a612 |
"mod", expr->numgen.mod,
|
|
Packit |
c5a612 |
"offset", expr->numgen.offset);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *hash_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const char *type;
|
|
Packit |
c5a612 |
json_t *root, *jexpr = NULL;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
switch (expr->hash.type) {
|
|
Packit |
c5a612 |
case NFT_HASH_SYM:
|
|
Packit |
c5a612 |
type = "symhash";
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFT_HASH_JENKINS:
|
|
Packit |
c5a612 |
default:
|
|
Packit |
c5a612 |
type = "jhash";
|
|
Packit |
c5a612 |
jexpr = expr_print_json(expr->hash.expr, octx);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:i}", "mod", expr->hash.mod);
|
|
Packit |
c5a612 |
if (expr->hash.seed_set)
|
|
Packit |
c5a612 |
json_object_set_new(root, "seed",
|
|
Packit |
c5a612 |
json_integer(expr->hash.seed));
|
|
Packit |
c5a612 |
if (expr->hash.offset)
|
|
Packit |
c5a612 |
json_object_set_new(root, "offset",
|
|
Packit |
c5a612 |
json_integer(expr->hash.offset));
|
|
Packit |
c5a612 |
if (jexpr)
|
|
Packit |
c5a612 |
json_object_set_new(root, "expr", jexpr);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", type, root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *fib_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const char *fib_flags[] = { "saddr", "daddr", "mark", "iif", "oif" };
|
|
Packit |
c5a612 |
unsigned int flags = expr->fib.flags & ~NFTA_FIB_F_PRESENT;
|
|
Packit |
c5a612 |
json_t *root;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:s}", "result", fib_result_str(expr->fib.result));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (flags) {
|
|
Packit |
c5a612 |
json_t *tmp = json_array();
|
|
Packit |
c5a612 |
unsigned int i;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
for (i = 0; i < array_size(fib_flags); i++) {
|
|
Packit |
c5a612 |
if (flags & (1 << i)) {
|
|
Packit |
c5a612 |
json_array_append_new(tmp, json_string(fib_flags[i]));
|
|
Packit |
c5a612 |
flags &= ~(1 << i);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
if (flags)
|
|
Packit |
c5a612 |
json_array_append_new(tmp, json_integer(flags));
|
|
Packit |
c5a612 |
json_object_set_new(root, "flags", tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "fib", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *symbolic_constant_json(const struct symbol_table *tbl,
|
|
Packit |
c5a612 |
const struct expr *expr,
|
|
Packit |
c5a612 |
struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
unsigned int len = div_round_up(expr->len, BITS_PER_BYTE);
|
|
Packit |
c5a612 |
const struct symbolic_constant *s;
|
|
Packit |
c5a612 |
uint64_t val = 0;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
/* Export the data in the correct byteorder for comparison */
|
|
Packit |
c5a612 |
assert(expr->len / BITS_PER_BYTE <= sizeof(val));
|
|
Packit |
c5a612 |
mpz_export_data(constant_data_ptr(val, expr->len), expr->value,
|
|
Packit |
c5a612 |
expr->byteorder, len);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
for (s = tbl->symbols; s->identifier != NULL; s++) {
|
|
Packit |
c5a612 |
if (val == s->value)
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
if (!s->identifier)
|
|
Packit |
c5a612 |
return expr_basetype(expr)->json(expr, octx);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (nft_output_numeric_symbol(octx))
|
|
Packit |
c5a612 |
return json_integer(val);
|
|
Packit |
c5a612 |
else
|
|
Packit |
c5a612 |
return json_string(s->identifier);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *datatype_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const struct datatype *dtype = expr->dtype;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
do {
|
|
Packit |
c5a612 |
if (dtype->json)
|
|
Packit |
c5a612 |
return dtype->json(expr, octx);
|
|
Packit |
c5a612 |
if (dtype->sym_tbl)
|
|
Packit |
c5a612 |
return symbolic_constant_json(dtype->sym_tbl,
|
|
Packit |
c5a612 |
expr, octx);
|
|
Packit |
c5a612 |
if (dtype->print) {
|
|
Packit |
c5a612 |
char buf[1024];
|
|
Packit |
c5a612 |
FILE *ofp = octx->output_fp;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
octx->output_fp = fmemopen(buf, 1024, "w");
|
|
Packit |
c5a612 |
dtype->print(expr, octx);
|
|
Packit |
c5a612 |
fclose(octx->output_fp);
|
|
Packit |
c5a612 |
octx->output_fp = ofp;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (buf[0] == '"') {
|
|
Packit |
c5a612 |
memmove(buf, buf + 1, strlen(buf));
|
|
Packit |
c5a612 |
*strchrnul(buf, '"') = '\0';
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_string(buf);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
} while ((dtype = dtype->basetype));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
BUG("datatype %s has no print method or symbol table\n",
|
|
Packit |
c5a612 |
expr->dtype->name);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *constant_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return datatype_json(expr, octx);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *socket_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return json_pack("{s:{s:s}}", "socket", "key",
|
|
Packit |
c5a612 |
socket_templates[expr->socket.key].token);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *osf_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (expr->osf.flags & NFT_OSF_F_VERSION)
|
|
Packit |
c5a612 |
root = json_pack("{s:s}", "key", "version");
|
|
Packit |
c5a612 |
else
|
|
Packit |
c5a612 |
root = json_pack("{s:s}", "key", "name");
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
switch (expr->osf.ttl) {
|
|
Packit |
c5a612 |
case 1:
|
|
Packit |
c5a612 |
json_object_set_new(root, "ttl", json_string("loose"));
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case 2:
|
|
Packit |
c5a612 |
json_object_set_new(root, "ttl", json_string("skip"));
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "osf", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *xfrm_expr_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const char *name = xfrm_templates[expr->xfrm.key].token;
|
|
Packit |
c5a612 |
const char *family = NULL;
|
|
Packit |
c5a612 |
const char *dirstr;
|
|
Packit |
c5a612 |
json_t *root;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
switch (expr->xfrm.direction) {
|
|
Packit |
c5a612 |
case XFRM_POLICY_IN:
|
|
Packit |
c5a612 |
dirstr = "in";
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case XFRM_POLICY_OUT:
|
|
Packit |
c5a612 |
dirstr = "out";
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
default:
|
|
Packit |
c5a612 |
return NULL;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
switch (expr->xfrm.key) {
|
|
Packit |
c5a612 |
case NFT_XFRM_KEY_UNSPEC:
|
|
Packit |
c5a612 |
case NFT_XFRM_KEY_SPI:
|
|
Packit |
c5a612 |
case NFT_XFRM_KEY_REQID:
|
|
Packit |
c5a612 |
case __NFT_XFRM_KEY_MAX:
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFT_XFRM_KEY_DADDR_IP4:
|
|
Packit |
c5a612 |
case NFT_XFRM_KEY_SADDR_IP4:
|
|
Packit |
c5a612 |
family = "ip";
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFT_XFRM_KEY_DADDR_IP6:
|
|
Packit |
c5a612 |
case NFT_XFRM_KEY_SADDR_IP6:
|
|
Packit |
c5a612 |
family = "ip6";
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:s}", "key", name);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (family)
|
|
Packit |
c5a612 |
json_object_set_new(root, "family", json_string(family));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_object_set_new(root, "dir", json_string(dirstr));
|
|
Packit |
c5a612 |
json_object_set_new(root, "spnum", json_integer(expr->xfrm.spnum));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "ipsec", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *integer_type_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
char buf[1024] = "0x";
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (mpz_fits_ulong_p(expr->value))
|
|
Packit |
c5a612 |
return json_integer(mpz_get_ui(expr->value));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
mpz_get_str(buf + 2, 16, expr->value);
|
|
Packit |
c5a612 |
return json_string(buf);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *string_type_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
unsigned int len = div_round_up(expr->len, BITS_PER_BYTE);
|
|
Packit |
c5a612 |
char data[len+1];
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
mpz_export_data(data, expr->value, BYTEORDER_HOST_ENDIAN, len);
|
|
Packit |
c5a612 |
data[len] = '\0';
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_string(data);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *boolean_type_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
unsigned int len = div_round_up(expr->len, BITS_PER_BYTE);
|
|
Packit |
c5a612 |
uint64_t val = 0;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
/* Export the data in the correct byteorder for comparison */
|
|
Packit |
c5a612 |
assert(expr->len / BITS_PER_BYTE <= sizeof(val));
|
|
Packit |
c5a612 |
mpz_export_data(constant_data_ptr(val, expr->len), expr->value,
|
|
Packit |
c5a612 |
expr->byteorder, len);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_boolean((int)val);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *inet_protocol_type_json(const struct expr *expr,
|
|
Packit |
c5a612 |
struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
struct protoent *p;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (!nft_output_numeric_proto(octx)) {
|
|
Packit |
c5a612 |
p = getprotobynumber(mpz_get_uint8(expr->value));
|
|
Packit |
c5a612 |
if (p != NULL)
|
|
Packit |
c5a612 |
return json_string(p->p_name);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
return integer_type_json(expr, octx);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *inet_service_type_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
struct sockaddr_in sin = {
|
|
Packit |
c5a612 |
.sin_family = AF_INET,
|
|
Packit |
c5a612 |
.sin_port = mpz_get_be16(expr->value),
|
|
Packit |
c5a612 |
};
|
|
Packit |
c5a612 |
char buf[NI_MAXSERV];
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (!nft_output_service(octx) ||
|
|
Packit |
c5a612 |
getnameinfo((struct sockaddr *)&sin, sizeof(sin),
|
|
Packit |
c5a612 |
NULL, 0, buf, sizeof(buf), 0))
|
|
Packit |
c5a612 |
return json_integer(ntohs(sin.sin_port));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (htons(atoi(buf)) == sin.sin_port ||
|
|
Packit |
c5a612 |
getnameinfo((struct sockaddr *)&sin, sizeof(sin),
|
|
Packit |
c5a612 |
NULL, 0, buf, sizeof(buf), NI_DGRAM))
|
|
Packit |
c5a612 |
return json_integer(ntohs(sin.sin_port));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_string(buf);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *mark_type_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return symbolic_constant_json(octx->tbl.mark, expr, octx);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *devgroup_type_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return symbolic_constant_json(octx->tbl.devgroup, expr, octx);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *ct_label_type_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
unsigned long bit = mpz_scan1(expr->value, 0);
|
|
Packit |
c5a612 |
const char *labelstr = ct_label2str(octx->tbl.ct_label, bit);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (labelstr)
|
|
Packit |
c5a612 |
return json_string(labelstr);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
/* can happen when connlabel.conf is altered after rules were added */
|
|
Packit |
c5a612 |
return json_integer(bit);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *time_type_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return json_integer(mpz_get_uint64(expr->value) / MSEC_PER_SEC);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *uid_type_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
uint32_t uid = mpz_get_uint32(expr->value);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (nft_output_guid(octx)) {
|
|
Packit |
c5a612 |
struct passwd *pw = getpwuid(uid);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (pw)
|
|
Packit |
c5a612 |
return json_string(pw->pw_name);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
return json_integer(uid);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *gid_type_json(const struct expr *expr, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
uint32_t gid = mpz_get_uint32(expr->value);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (nft_output_guid(octx)) {
|
|
Packit |
c5a612 |
struct group *gr = getgrgid(gid);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (gr)
|
|
Packit |
c5a612 |
return json_string(gr->gr_name);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
return json_integer(gid);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *expr_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return expr_print_json(stmt->expr, octx);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *payload_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return json_pack("{s: {s:o, s:o}}", "mangle",
|
|
Packit |
c5a612 |
"key", expr_print_json(stmt->payload.expr, octx),
|
|
Packit |
c5a612 |
"value", expr_print_json(stmt->payload.val, octx));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *exthdr_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return json_pack("{s: {s:o, s:o}}", "mangle",
|
|
Packit |
c5a612 |
"key", expr_print_json(stmt->exthdr.expr, octx),
|
|
Packit |
c5a612 |
"value", expr_print_json(stmt->exthdr.val, octx));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *quota_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const char *data_unit;
|
|
Packit |
c5a612 |
uint64_t bytes;
|
|
Packit |
c5a612 |
json_t *root;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
data_unit = get_rate(stmt->quota.bytes, &bytes);
|
|
Packit |
c5a612 |
root = json_pack("{s:I, s:s}",
|
|
Packit |
c5a612 |
"val", bytes,
|
|
Packit |
c5a612 |
"val_unit", data_unit);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->quota.flags & NFT_QUOTA_F_INV)
|
|
Packit |
c5a612 |
json_object_set_new(root, "inv", json_true());
|
|
Packit |
c5a612 |
if (!nft_output_stateless(octx) && stmt->quota.used) {
|
|
Packit |
c5a612 |
data_unit = get_rate(stmt->quota.used, &bytes);
|
|
Packit |
c5a612 |
json_object_set_new(root, "used", json_integer(bytes));
|
|
Packit |
c5a612 |
json_object_set_new(root, "used_unit", json_string(data_unit));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "quota", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *ct_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
struct expr expr = {
|
|
Packit |
c5a612 |
.ct = {
|
|
Packit |
c5a612 |
.key = stmt->ct.key,
|
|
Packit |
c5a612 |
.direction = stmt->ct.direction,
|
|
Packit |
c5a612 |
.nfproto = 0,
|
|
Packit |
c5a612 |
},
|
|
Packit |
c5a612 |
};
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:{s:o, s:o}}", "mangle",
|
|
Packit |
c5a612 |
"key", ct_expr_json(&expr, octx),
|
|
Packit |
c5a612 |
"value", expr_print_json(stmt->ct.expr, octx));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *limit_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const char *rate_unit = NULL, *burst_unit = NULL;
|
|
Packit |
c5a612 |
bool inv = stmt->limit.flags & NFT_LIMIT_F_INV;
|
|
Packit |
c5a612 |
uint64_t burst = stmt->limit.burst;
|
|
Packit |
c5a612 |
uint64_t rate = stmt->limit.rate;
|
|
Packit |
c5a612 |
json_t *root;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->limit.type == NFT_LIMIT_PKT_BYTES) {
|
|
Packit |
c5a612 |
rate_unit = get_rate(stmt->limit.rate, &rate;;
|
|
Packit |
c5a612 |
burst_unit = get_rate(stmt->limit.burst, &burst);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:I, s:s}",
|
|
Packit |
c5a612 |
"rate", rate,
|
|
Packit |
c5a612 |
"per", get_unit(stmt->limit.unit));
|
|
Packit |
c5a612 |
if (inv)
|
|
Packit |
c5a612 |
json_object_set_new(root, "inv", json_boolean(inv));
|
|
Packit |
c5a612 |
if (rate_unit)
|
|
Packit |
c5a612 |
json_object_set_new(root, "rate_unit", json_string(rate_unit));
|
|
Packit |
c5a612 |
if (burst && burst != 5) {
|
|
Packit |
c5a612 |
json_object_set_new(root, "burst", json_integer(burst));
|
|
Packit |
c5a612 |
if (burst_unit)
|
|
Packit |
c5a612 |
json_object_set_new(root, "burst_unit",
|
|
Packit |
c5a612 |
json_string(burst_unit));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "limit", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *fwd_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root, *tmp;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:o}", "dev", expr_print_json(stmt->fwd.dev, octx));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->fwd.addr) {
|
|
Packit |
c5a612 |
tmp = json_string(family2str(stmt->fwd.family));
|
|
Packit |
c5a612 |
json_object_set_new(root, "family", tmp);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
tmp = expr_print_json(stmt->fwd.addr, octx);
|
|
Packit |
c5a612 |
json_object_set_new(root, "addr", tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "fwd", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *notrack_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return json_pack("{s:n}", "notrack");
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *dup_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->dup.to) {
|
|
Packit |
c5a612 |
root = json_pack("{s:o}", "addr", expr_print_json(stmt->dup.to, octx));
|
|
Packit |
c5a612 |
if (stmt->dup.dev)
|
|
Packit |
c5a612 |
json_object_set_new(root, "dev",
|
|
Packit |
c5a612 |
expr_print_json(stmt->dup.dev, octx));
|
|
Packit |
c5a612 |
} else {
|
|
Packit |
c5a612 |
root = json_null();
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "dup", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *meta_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:{s:s}}", "meta",
|
|
Packit |
c5a612 |
"key", meta_templates[stmt->meta.key].token);
|
|
Packit |
c5a612 |
root = json_pack("{s:o, s:o}",
|
|
Packit |
c5a612 |
"key", root,
|
|
Packit |
c5a612 |
"value", expr_print_json(stmt->meta.expr, octx));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "mangle", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *log_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root = json_object(), *flags;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->log.flags & STMT_LOG_PREFIX)
|
|
Packit |
c5a612 |
json_object_set_new(root, "prefix",
|
|
Packit |
c5a612 |
json_string(stmt->log.prefix));
|
|
Packit |
c5a612 |
if (stmt->log.flags & STMT_LOG_GROUP)
|
|
Packit |
c5a612 |
json_object_set_new(root, "group",
|
|
Packit |
c5a612 |
json_integer(stmt->log.group));
|
|
Packit |
c5a612 |
if (stmt->log.flags & STMT_LOG_SNAPLEN)
|
|
Packit |
c5a612 |
json_object_set_new(root, "snaplen",
|
|
Packit |
c5a612 |
json_integer(stmt->log.snaplen));
|
|
Packit |
c5a612 |
if (stmt->log.flags & STMT_LOG_QTHRESHOLD)
|
|
Packit |
c5a612 |
json_object_set_new(root, "queue-threshold",
|
|
Packit |
c5a612 |
json_integer(stmt->log.qthreshold));
|
|
Packit |
c5a612 |
if ((stmt->log.flags & STMT_LOG_LEVEL) &&
|
|
Packit |
c5a612 |
stmt->log.level != LOG_WARNING)
|
|
Packit |
c5a612 |
json_object_set_new(root, "level",
|
|
Packit |
c5a612 |
json_string(log_level(stmt->log.level)));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
flags = json_array();
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if ((stmt->log.logflags & NF_LOG_MASK) == NF_LOG_MASK) {
|
|
Packit |
c5a612 |
json_array_append_new(flags, json_string("all"));
|
|
Packit |
c5a612 |
} else {
|
|
Packit |
c5a612 |
if (stmt->log.logflags & NF_LOG_TCPSEQ)
|
|
Packit |
c5a612 |
json_array_append_new(flags,
|
|
Packit |
c5a612 |
json_string("tcp sequence"));
|
|
Packit |
c5a612 |
if (stmt->log.logflags & NF_LOG_TCPOPT)
|
|
Packit |
c5a612 |
json_array_append_new(flags,
|
|
Packit |
c5a612 |
json_string("tcp options"));
|
|
Packit |
c5a612 |
if (stmt->log.logflags & NF_LOG_IPOPT)
|
|
Packit |
c5a612 |
json_array_append_new(flags, json_string("ip options"));
|
|
Packit |
c5a612 |
if (stmt->log.logflags & NF_LOG_UID)
|
|
Packit |
c5a612 |
json_array_append_new(flags, json_string("skuid"));
|
|
Packit |
c5a612 |
if (stmt->log.logflags & NF_LOG_MACDECODE)
|
|
Packit |
c5a612 |
json_array_append_new(flags, json_string("ether"));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
if (json_array_size(flags) > 1) {
|
|
Packit |
c5a612 |
json_object_set_new(root, "flags", flags);
|
|
Packit |
c5a612 |
} else {
|
|
Packit |
c5a612 |
if (json_array_size(flags))
|
|
Packit |
c5a612 |
json_object_set(root, "flags",
|
|
Packit |
c5a612 |
json_array_get(flags, 0));
|
|
Packit |
c5a612 |
json_decref(flags);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (!json_object_size(root)) {
|
|
Packit |
c5a612 |
json_decref(root);
|
|
Packit |
c5a612 |
root = json_null();
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "log", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *nat_flags_json(int flags)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *array = json_array();
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (flags & NF_NAT_RANGE_PROTO_RANDOM)
|
|
Packit |
c5a612 |
json_array_append_new(array, json_string("random"));
|
|
Packit |
c5a612 |
if (flags & NF_NAT_RANGE_PROTO_RANDOM_FULLY)
|
|
Packit |
c5a612 |
json_array_append_new(array, json_string("fully-random"));
|
|
Packit |
c5a612 |
if (flags & NF_NAT_RANGE_PERSISTENT)
|
|
Packit |
c5a612 |
json_array_append_new(array, json_string("persistent"));
|
|
Packit |
c5a612 |
return array;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *nat_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root = json_object();
|
|
Packit |
c5a612 |
json_t *array = nat_flags_json(stmt->nat.flags);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
switch (stmt->nat.family) {
|
|
Packit |
c5a612 |
case NFPROTO_IPV4:
|
|
Packit |
c5a612 |
case NFPROTO_IPV6:
|
|
Packit |
c5a612 |
json_object_set_new(root, "family",
|
|
Packit |
c5a612 |
json_string(family2str(stmt->nat.family)));
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->nat.addr)
|
|
Packit |
c5a612 |
json_object_set_new(root, "addr",
|
|
Packit |
c5a612 |
expr_print_json(stmt->nat.addr, octx));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->nat.proto)
|
|
Packit |
c5a612 |
json_object_set_new(root, "port",
|
|
Packit |
c5a612 |
expr_print_json(stmt->nat.proto, octx));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (json_array_size(array) > 1) {
|
|
Packit |
c5a612 |
json_object_set_new(root, "flags", array);
|
|
Packit |
c5a612 |
} else {
|
|
Packit |
c5a612 |
if (json_array_size(array))
|
|
Packit |
c5a612 |
json_object_set(root, "flags",
|
|
Packit |
c5a612 |
json_array_get(array, 0));
|
|
Packit |
c5a612 |
json_decref(array);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (!json_object_size(root)) {
|
|
Packit |
c5a612 |
json_decref(root);
|
|
Packit |
c5a612 |
root = json_null();
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", nat_etype2str(stmt->nat.type), root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *reject_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root, *jexpr = NULL;
|
|
Packit |
c5a612 |
const char *type = NULL;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
switch (stmt->reject.type) {
|
|
Packit |
c5a612 |
case NFT_REJECT_TCP_RST:
|
|
Packit |
c5a612 |
type = "tcp reset";
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFT_REJECT_ICMPX_UNREACH:
|
|
Packit |
c5a612 |
if (stmt->reject.icmp_code == NFT_REJECT_ICMPX_PORT_UNREACH)
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
type = "icmpx";
|
|
Packit |
c5a612 |
jexpr = expr_print_json(stmt->reject.expr, octx);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFT_REJECT_ICMP_UNREACH:
|
|
Packit |
c5a612 |
switch (stmt->reject.family) {
|
|
Packit |
c5a612 |
case NFPROTO_IPV4:
|
|
Packit |
c5a612 |
if (!stmt->reject.verbose_print &&
|
|
Packit |
c5a612 |
stmt->reject.icmp_code == ICMP_PORT_UNREACH)
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
type = "icmp";
|
|
Packit |
c5a612 |
jexpr = expr_print_json(stmt->reject.expr, octx);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case NFPROTO_IPV6:
|
|
Packit |
c5a612 |
if (!stmt->reject.verbose_print &&
|
|
Packit |
c5a612 |
stmt->reject.icmp_code == ICMP6_DST_UNREACH_NOPORT)
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
type = "icmpv6";
|
|
Packit |
c5a612 |
jexpr = expr_print_json(stmt->reject.expr, octx);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (!type && !jexpr)
|
|
Packit |
c5a612 |
return json_pack("{s:n}", "reject");
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_object();
|
|
Packit |
c5a612 |
if (type)
|
|
Packit |
c5a612 |
json_object_set_new(root, "type", json_string(type));
|
|
Packit |
c5a612 |
if (jexpr)
|
|
Packit |
c5a612 |
json_object_set_new(root, "expr", jexpr);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "reject", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *counter_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
if (nft_output_stateless(octx))
|
|
Packit |
c5a612 |
return json_pack("{s:n}", "counter");
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:{s:I, s:I}}", "counter",
|
|
Packit |
c5a612 |
"packets", stmt->counter.packets,
|
|
Packit |
c5a612 |
"bytes", stmt->counter.bytes);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *set_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return json_pack("{s:{s:s, s:o, s:s+}}", "set",
|
|
Packit |
c5a612 |
"op", set_stmt_op_names[stmt->set.op],
|
|
Packit |
c5a612 |
"elem", expr_print_json(stmt->set.key, octx),
|
|
Packit |
c5a612 |
"set", "@", stmt->set.set->set->handle.set.name);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *objref_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
const char *name;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->objref.type > NFT_OBJECT_MAX)
|
|
Packit |
c5a612 |
name = "unknown";
|
|
Packit |
c5a612 |
else
|
|
Packit |
c5a612 |
name = objref_type_name(stmt->objref.type);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", name, expr_print_json(stmt->objref.expr, octx));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *meter_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
unsigned int flags = octx->flags;
|
|
Packit |
c5a612 |
json_t *root, *tmp;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
octx->flags |= NFT_CTX_OUTPUT_STATELESS;
|
|
Packit |
c5a612 |
tmp = stmt_print_json(stmt->meter.stmt, octx);
|
|
Packit |
c5a612 |
octx->flags = flags;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:o, s:o, s:i}",
|
|
Packit |
c5a612 |
"key", expr_print_json(stmt->meter.key, octx),
|
|
Packit |
c5a612 |
"stmt", tmp,
|
|
Packit |
c5a612 |
"size", stmt->meter.size);
|
|
Packit |
c5a612 |
if (stmt->meter.set) {
|
|
Packit |
c5a612 |
tmp = json_string(stmt->meter.set->set->handle.set.name);
|
|
Packit |
c5a612 |
json_object_set_new(root, "name", tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "meter", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *queue_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root, *flags;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_object();
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->queue.queue)
|
|
Packit |
c5a612 |
json_object_set_new(root, "num",
|
|
Packit |
c5a612 |
expr_print_json(stmt->queue.queue, octx));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
flags = json_array();
|
|
Packit |
c5a612 |
if (stmt->queue.flags & NFT_QUEUE_FLAG_BYPASS)
|
|
Packit |
c5a612 |
json_array_append_new(flags, json_string("bypass"));
|
|
Packit |
c5a612 |
if (stmt->queue.flags & NFT_QUEUE_FLAG_CPU_FANOUT)
|
|
Packit |
c5a612 |
json_array_append_new(flags, json_string("fanout"));
|
|
Packit |
c5a612 |
if (json_array_size(flags) > 1) {
|
|
Packit |
c5a612 |
json_object_set_new(root, "flags", flags);
|
|
Packit |
c5a612 |
} else {
|
|
Packit |
c5a612 |
if (json_array_size(flags))
|
|
Packit |
c5a612 |
json_object_set(root, "flags",
|
|
Packit |
c5a612 |
json_array_get(flags, 0));
|
|
Packit |
c5a612 |
json_decref(flags);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (!json_object_size(root)) {
|
|
Packit |
c5a612 |
json_decref(root);
|
|
Packit |
c5a612 |
root = json_null();
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "queue", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *verdict_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return expr_print_json(stmt->expr, octx);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *connlimit_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root = json_pack("{s:i}", "val", stmt->connlimit.count);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->connlimit.flags & NFT_CONNLIMIT_F_INV)
|
|
Packit |
c5a612 |
json_object_set_new(root, "inv", json_true());
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "ct count", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *tproxy_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *tmp, *root = json_object();
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->tproxy.table_family == NFPROTO_INET &&
|
|
Packit |
c5a612 |
stmt->tproxy.family != NFPROTO_UNSPEC) {
|
|
Packit |
c5a612 |
tmp = json_string(family2str(stmt->tproxy.family));
|
|
Packit |
c5a612 |
json_object_set_new(root, "family", tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->tproxy.addr) {
|
|
Packit |
c5a612 |
tmp = expr_print_json(stmt->tproxy.addr, octx);
|
|
Packit |
c5a612 |
json_object_set_new(root, "addr", tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->tproxy.port) {
|
|
Packit |
c5a612 |
tmp = expr_print_json(stmt->tproxy.port, octx);
|
|
Packit |
c5a612 |
json_object_set_new(root, "port", tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "tproxy", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_t *synproxy_stmt_json(const struct stmt *stmt, struct output_ctx *octx)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root = json_object(), *flags = json_array();
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (stmt->synproxy.flags & NF_SYNPROXY_OPT_MSS)
|
|
Packit |
c5a612 |
json_object_set_new(root, "mss",
|
|
Packit |
c5a612 |
json_integer(stmt->synproxy.mss));
|
|
Packit |
c5a612 |
if (stmt->synproxy.flags & NF_SYNPROXY_OPT_WSCALE)
|
|
Packit |
c5a612 |
json_object_set_new(root, "wscale",
|
|
Packit |
c5a612 |
json_integer(stmt->synproxy.wscale));
|
|
Packit |
c5a612 |
if (stmt->synproxy.flags & NF_SYNPROXY_OPT_TIMESTAMP)
|
|
Packit |
c5a612 |
json_array_append_new(flags, json_string("timestamp"));
|
|
Packit |
c5a612 |
if (stmt->synproxy.flags & NF_SYNPROXY_OPT_SACK_PERM)
|
|
Packit |
c5a612 |
json_array_append_new(flags, json_string("sack-perm"));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (json_array_size(flags) > 0)
|
|
Packit |
c5a612 |
json_object_set_new(root, "flags", flags);
|
|
Packit |
c5a612 |
else
|
|
Packit |
c5a612 |
json_decref(flags);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (!json_object_size(root)) {
|
|
Packit |
c5a612 |
json_decref(root);
|
|
Packit |
c5a612 |
root = json_null();
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("{s:o}", "synproxy", root);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *table_print_json_full(struct netlink_ctx *ctx,
|
|
Packit |
c5a612 |
struct table *table)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root = json_array(), *tmp;
|
|
Packit |
c5a612 |
struct flowtable *flowtable;
|
|
Packit |
c5a612 |
struct chain *chain;
|
|
Packit |
c5a612 |
struct rule *rule;
|
|
Packit |
c5a612 |
struct obj *obj;
|
|
Packit |
c5a612 |
struct set *set;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
tmp = table_print_json(table);
|
|
Packit |
c5a612 |
json_array_append_new(root, tmp);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(obj, &table->objs, list) {
|
|
Packit |
c5a612 |
tmp = obj_print_json(obj);
|
|
Packit |
c5a612 |
json_array_append_new(root, tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
list_for_each_entry(set, &table->sets, list) {
|
|
Packit |
c5a612 |
if (set_is_anonymous(set->flags))
|
|
Packit |
c5a612 |
continue;
|
|
Packit |
c5a612 |
tmp = set_print_json(&ctx->nft->output, set);
|
|
Packit |
c5a612 |
json_array_append_new(root, tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
list_for_each_entry(flowtable, &table->flowtables, list) {
|
|
Packit |
c5a612 |
tmp = flowtable_print_json(flowtable);
|
|
Packit |
c5a612 |
json_array_append_new(root, tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
list_for_each_entry(chain, &table->chains, list) {
|
|
Packit |
c5a612 |
tmp = chain_print_json(chain);
|
|
Packit |
c5a612 |
json_array_append_new(root, tmp);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(rule, &chain->rules, list) {
|
|
Packit |
c5a612 |
tmp = rule_print_json(&ctx->nft->output, rule);
|
|
Packit |
c5a612 |
json_array_append_new(root, tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return root;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *do_list_ruleset_json(struct netlink_ctx *ctx, struct cmd *cmd)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
unsigned int family = cmd->handle.family;
|
|
Packit |
c5a612 |
json_t *root = json_array();
|
|
Packit |
c5a612 |
struct table *table;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(table, &ctx->nft->cache.list, list) {
|
|
Packit |
c5a612 |
if (family != NFPROTO_UNSPEC &&
|
|
Packit |
c5a612 |
table->handle.family != family)
|
|
Packit |
c5a612 |
continue;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_array_extend(root, table_print_json_full(ctx, table));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return root;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *do_list_tables_json(struct netlink_ctx *ctx, struct cmd *cmd)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
unsigned int family = cmd->handle.family;
|
|
Packit |
c5a612 |
json_t *root = json_array();
|
|
Packit |
c5a612 |
struct table *table;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(table, &ctx->nft->cache.list, list) {
|
|
Packit |
c5a612 |
if (family != NFPROTO_UNSPEC &&
|
|
Packit |
c5a612 |
table->handle.family != family)
|
|
Packit |
c5a612 |
continue;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_array_append_new(root, table_print_json(table));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return root;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *do_list_table_json(struct netlink_ctx *ctx,
|
|
Packit |
c5a612 |
struct cmd *cmd, struct table *table)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return table_print_json_full(ctx, table);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *do_list_chain_json(struct netlink_ctx *ctx,
|
|
Packit |
c5a612 |
struct cmd *cmd, struct table *table)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root = json_array();
|
|
Packit |
c5a612 |
struct chain *chain;
|
|
Packit |
c5a612 |
struct rule *rule;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(chain, &table->chains, list) {
|
|
Packit |
c5a612 |
if (chain->handle.family != cmd->handle.family ||
|
|
Packit |
c5a612 |
strcmp(cmd->handle.chain.name, chain->handle.chain.name))
|
|
Packit |
c5a612 |
continue;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_array_append_new(root, chain_print_json(chain));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(rule, &chain->rules, list) {
|
|
Packit |
c5a612 |
json_t *tmp = rule_print_json(&ctx->nft->output, rule);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_array_append_new(root, tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return root;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *do_list_chains_json(struct netlink_ctx *ctx, struct cmd *cmd)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root = json_array();
|
|
Packit |
c5a612 |
struct table *table;
|
|
Packit |
c5a612 |
struct chain *chain;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(table, &ctx->nft->cache.list, list) {
|
|
Packit |
c5a612 |
if (cmd->handle.family != NFPROTO_UNSPEC &&
|
|
Packit |
c5a612 |
cmd->handle.family != table->handle.family)
|
|
Packit |
c5a612 |
continue;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(chain, &table->chains, list) {
|
|
Packit |
c5a612 |
json_t *tmp = chain_print_json(chain);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_array_append_new(root, tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return root;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *do_list_set_json(struct netlink_ctx *ctx,
|
|
Packit |
c5a612 |
struct cmd *cmd, struct table *table)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
struct set *set = set_lookup(table, cmd->handle.set.name);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (set == NULL)
|
|
Packit |
c5a612 |
return json_null();
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return json_pack("[o]", set_print_json(&ctx->nft->output, set));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *do_list_sets_json(struct netlink_ctx *ctx, struct cmd *cmd)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
struct output_ctx *octx = &ctx->nft->output;
|
|
Packit |
c5a612 |
json_t *root = json_array();
|
|
Packit |
c5a612 |
struct table *table;
|
|
Packit |
c5a612 |
struct set *set;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(table, &ctx->nft->cache.list, list) {
|
|
Packit |
c5a612 |
if (cmd->handle.family != NFPROTO_UNSPEC &&
|
|
Packit |
c5a612 |
cmd->handle.family != table->handle.family)
|
|
Packit |
c5a612 |
continue;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(set, &table->sets, list) {
|
|
Packit |
c5a612 |
if (cmd->obj == CMD_OBJ_SETS &&
|
|
Packit |
c5a612 |
!set_is_literal(set->flags))
|
|
Packit |
c5a612 |
continue;
|
|
Packit |
c5a612 |
if (cmd->obj == CMD_OBJ_METERS &&
|
|
Packit |
c5a612 |
!set_is_meter(set->flags))
|
|
Packit |
c5a612 |
continue;
|
|
Packit |
c5a612 |
if (cmd->obj == CMD_OBJ_MAPS &&
|
|
Packit |
c5a612 |
!map_is_literal(set->flags))
|
|
Packit |
c5a612 |
continue;
|
|
Packit |
c5a612 |
json_array_append_new(root, set_print_json(octx, set));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return root;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *do_list_obj_json(struct netlink_ctx *ctx,
|
|
Packit |
c5a612 |
struct cmd *cmd, uint32_t type)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root = json_array();
|
|
Packit |
c5a612 |
struct table *table;
|
|
Packit |
c5a612 |
struct obj *obj;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(table, &ctx->nft->cache.list, list) {
|
|
Packit |
c5a612 |
if (cmd->handle.family != NFPROTO_UNSPEC &&
|
|
Packit |
c5a612 |
cmd->handle.family != table->handle.family)
|
|
Packit |
c5a612 |
continue;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (cmd->handle.table.name &&
|
|
Packit |
c5a612 |
strcmp(cmd->handle.table.name, table->handle.table.name))
|
|
Packit |
c5a612 |
continue;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(obj, &table->objs, list) {
|
|
Packit |
c5a612 |
if (obj->type != type ||
|
|
Packit |
c5a612 |
(cmd->handle.obj.name &&
|
|
Packit |
c5a612 |
strcmp(cmd->handle.obj.name, obj->handle.obj.name)))
|
|
Packit |
c5a612 |
continue;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_array_append_new(root, obj_print_json(obj));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return root;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *do_list_flowtable_json(struct netlink_ctx *ctx,
|
|
Packit |
c5a612 |
struct cmd *cmd, struct table *table)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root = json_array();
|
|
Packit |
c5a612 |
struct flowtable *ft;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
ft = flowtable_lookup(table, cmd->handle.flowtable.name);
|
|
Packit |
c5a612 |
if (ft == NULL)
|
|
Packit |
c5a612 |
return json_null();
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_array_append_new(root, flowtable_print_json(ft));
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return root;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *do_list_flowtables_json(struct netlink_ctx *ctx, struct cmd *cmd)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
json_t *root = json_array(), *tmp;
|
|
Packit |
c5a612 |
struct flowtable *flowtable;
|
|
Packit |
c5a612 |
struct table *table;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(table, &ctx->nft->cache.list, list) {
|
|
Packit |
c5a612 |
if (cmd->handle.family != NFPROTO_UNSPEC &&
|
|
Packit |
c5a612 |
cmd->handle.family != table->handle.family)
|
|
Packit |
c5a612 |
continue;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
list_for_each_entry(flowtable, &table->flowtables, list) {
|
|
Packit |
c5a612 |
tmp = flowtable_print_json(flowtable);
|
|
Packit |
c5a612 |
json_array_append_new(root, tmp);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
return root;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static json_t *generate_json_metainfo(void)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
return json_pack("{s: {s:s, s:s, s:i}}", "metainfo",
|
|
Packit |
c5a612 |
"version", PACKAGE_VERSION,
|
|
Packit |
c5a612 |
"release_name", RELEASE_NAME,
|
|
Packit |
c5a612 |
"json_schema_version", JSON_SCHEMA_VERSION);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
int do_command_list_json(struct netlink_ctx *ctx, struct cmd *cmd)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
struct table *table = NULL;
|
|
Packit |
c5a612 |
json_t *root;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (cmd->handle.table.name)
|
|
Packit |
c5a612 |
table = table_lookup(&cmd->handle, &ctx->nft->cache);
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
switch (cmd->obj) {
|
|
Packit |
c5a612 |
case CMD_OBJ_TABLE:
|
|
Packit |
c5a612 |
if (!cmd->handle.table.name) {
|
|
Packit |
c5a612 |
root = do_list_tables_json(ctx, cmd);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
root = do_list_table_json(ctx, cmd, table);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_CHAIN:
|
|
Packit |
c5a612 |
root = do_list_chain_json(ctx, cmd, table);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_CHAINS:
|
|
Packit |
c5a612 |
root = do_list_chains_json(ctx, cmd);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_SETS:
|
|
Packit |
c5a612 |
root = do_list_sets_json(ctx, cmd);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_SET:
|
|
Packit |
c5a612 |
root = do_list_set_json(ctx, cmd, table);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_RULESET:
|
|
Packit |
c5a612 |
root = do_list_ruleset_json(ctx, cmd);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_METERS:
|
|
Packit |
c5a612 |
root = do_list_sets_json(ctx, cmd);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_METER:
|
|
Packit |
c5a612 |
root = do_list_set_json(ctx, cmd, table);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_MAPS:
|
|
Packit |
c5a612 |
root = do_list_sets_json(ctx, cmd);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_MAP:
|
|
Packit |
c5a612 |
root = do_list_set_json(ctx, cmd, table);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_COUNTER:
|
|
Packit |
c5a612 |
case CMD_OBJ_COUNTERS:
|
|
Packit |
c5a612 |
root = do_list_obj_json(ctx, cmd, NFT_OBJECT_COUNTER);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_QUOTA:
|
|
Packit |
c5a612 |
case CMD_OBJ_QUOTAS:
|
|
Packit |
c5a612 |
root = do_list_obj_json(ctx, cmd, NFT_OBJECT_QUOTA);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_CT_HELPER:
|
|
Packit |
c5a612 |
case CMD_OBJ_CT_HELPERS:
|
|
Packit |
c5a612 |
root = do_list_obj_json(ctx, cmd, NFT_OBJECT_CT_HELPER);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_LIMIT:
|
|
Packit |
c5a612 |
case CMD_OBJ_LIMITS:
|
|
Packit |
c5a612 |
root = do_list_obj_json(ctx, cmd, NFT_OBJECT_LIMIT);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_SECMARK:
|
|
Packit |
c5a612 |
case CMD_OBJ_SECMARKS:
|
|
Packit |
c5a612 |
root = do_list_obj_json(ctx, cmd, NFT_OBJECT_SECMARK);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_FLOWTABLE:
|
|
Packit |
c5a612 |
root = do_list_flowtable_json(ctx, cmd, table);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
case CMD_OBJ_FLOWTABLES:
|
|
Packit |
c5a612 |
root = do_list_flowtables_json(ctx, cmd);
|
|
Packit |
c5a612 |
break;
|
|
Packit |
c5a612 |
default:
|
|
Packit |
c5a612 |
BUG("invalid command object type %u\n", cmd->obj);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
if (!json_is_array(root)) {
|
|
Packit |
c5a612 |
json_t *tmp = json_array();
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_array_append_new(tmp, root);
|
|
Packit |
c5a612 |
root = tmp;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
json_array_insert_new(root, 0, generate_json_metainfo());
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
root = json_pack("{s:o}", "nftables", root);
|
|
Packit |
c5a612 |
json_dumpf(root, ctx->nft->output.output_fp, 0);
|
|
Packit |
c5a612 |
json_decref(root);
|
|
Packit |
c5a612 |
fprintf(ctx->nft->output.output_fp, "\n");
|
|
Packit |
c5a612 |
fflush(ctx->nft->output.output_fp);
|
|
Packit |
c5a612 |
return 0;
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
static void monitor_print_json(struct netlink_mon_handler *monh,
|
|
Packit |
c5a612 |
const char *cmd, json_t *obj)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
obj = json_pack("{s:o}", cmd, obj);
|
|
Packit |
c5a612 |
json_dumpf(obj, monh->ctx->nft->output.output_fp, 0);
|
|
Packit |
c5a612 |
json_decref(obj);
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
void monitor_print_table_json(struct netlink_mon_handler *monh,
|
|
Packit |
c5a612 |
const char *cmd, struct table *t)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
monitor_print_json(monh, cmd, table_print_json(t));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
void monitor_print_chain_json(struct netlink_mon_handler *monh,
|
|
Packit |
c5a612 |
const char *cmd, struct chain *c)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
monitor_print_json(monh, cmd, chain_print_json(c));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
void monitor_print_set_json(struct netlink_mon_handler *monh,
|
|
Packit |
c5a612 |
const char *cmd, struct set *s)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
struct output_ctx *octx = &monh->ctx->nft->output;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
monitor_print_json(monh, cmd, set_print_json(octx, s));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
void monitor_print_element_json(struct netlink_mon_handler *monh,
|
|
Packit |
c5a612 |
const char *cmd, struct set *s)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
struct output_ctx *octx = &monh->ctx->nft->output;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
monitor_print_json(monh, cmd, element_print_json(octx, s));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
void monitor_print_obj_json(struct netlink_mon_handler *monh,
|
|
Packit |
c5a612 |
const char *cmd, struct obj *o)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
monitor_print_json(monh, cmd, obj_print_json(o));
|
|
Packit |
c5a612 |
}
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
void monitor_print_rule_json(struct netlink_mon_handler *monh,
|
|
Packit |
c5a612 |
const char *cmd, struct rule *r)
|
|
Packit |
c5a612 |
{
|
|
Packit |
c5a612 |
struct output_ctx *octx = &monh->ctx->nft->output;
|
|
Packit |
c5a612 |
|
|
Packit |
c5a612 |
monitor_print_json(monh, cmd, rule_print_json(octx, r));
|
|
Packit |
c5a612 |
}
|