summaryrefslogtreecommitdiffstats
path: root/lib/session.c
diff options
context:
space:
mode:
authorThomas Oberhammer <toberhammer@open-systems.com>2023-09-18 23:24:59 +0200
committerJozsef Kadlecsik <kadlec@netfilter.org>2023-09-18 23:40:45 +0200
commit2885607ffeb4d24773ada1b9b3452d238c8989d3 (patch)
treede916e0ba1412a53b16661914b074c8ee9db7481 /lib/session.c
parentc63afc87e554f3742b7c2cd9c401cefb632bb38a (diff)
Add json output to list command
Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org>
Diffstat (limited to 'lib/session.c')
-rw-r--r--lib/session.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/lib/session.c b/lib/session.c
index cdc59e0..a10238d 100644
--- a/lib/session.c
+++ b/lib/session.c
@@ -860,6 +860,7 @@ list_adt(struct ipset_session *session, struct nlattr *nla[])
const struct ipset_arg *arg;
size_t offset = 0;
int i, found = 0;
+ static char last_setname[IPSET_MAXNAMELEN] = "";
D("enter");
/* Check and load type, family */
@@ -894,6 +895,13 @@ list_adt(struct ipset_session *session, struct nlattr *nla[])
case IPSET_LIST_XML:
safe_snprintf(session, "<member><elem>");
break;
+ case IPSET_LIST_JSON:
+ /* print separator if a member for this set was printed before */
+ if (STREQ(ipset_data_setname(data), last_setname))
+ safe_snprintf(session, ",");
+ strcpy(last_setname, ipset_data_setname(data));
+ safe_snprintf(session, "\n {\n \"elem\" : \"");
+ break;
case IPSET_LIST_PLAIN:
default:
break;
@@ -902,6 +910,8 @@ list_adt(struct ipset_session *session, struct nlattr *nla[])
safe_dprintf(session, ipset_print_elem, IPSET_OPT_ELEM);
if (session->mode == IPSET_LIST_XML)
safe_snprintf(session, "</elem>");
+ if (session->mode == IPSET_LIST_JSON)
+ safe_snprintf(session, "\"");
for (i = 0; type->cmd[IPSET_ADD].args[i] != IPSET_ARG_NONE; i++) {
arg = ipset_keyword(type->cmd[IPSET_ADD].args[i]);
@@ -929,6 +939,15 @@ list_adt(struct ipset_session *session, struct nlattr *nla[])
safe_dprintf(session, arg->print, arg->opt);
safe_snprintf(session, "</%s>", arg->name[0]);
break;
+ case IPSET_LIST_JSON:
+ if (arg->has_arg == IPSET_NO_ARG) {
+ safe_snprintf(session,
+ ",\n \"%s\" : true", arg->name[0]);
+ break;
+ }
+ safe_snprintf(session, ",\n \"%s\" : ", arg->name[0]);
+ safe_dprintf(session, arg->print, arg->opt);
+ break;
default:
break;
}
@@ -936,6 +955,8 @@ list_adt(struct ipset_session *session, struct nlattr *nla[])
if (session->mode == IPSET_LIST_XML)
safe_snprintf(session, "</member>\n");
+ else if (session->mode == IPSET_LIST_JSON)
+ safe_snprintf(session, "\n }");
else
safe_snprintf(session, "\n");
@@ -972,6 +993,7 @@ list_create(struct ipset_session *session, struct nlattr *nla[])
const struct ipset_arg *arg;
uint8_t family;
int i;
+ static bool firstipset = true;
for (i = IPSET_ATTR_UNSPEC + 1; i <= IPSET_ATTR_CREATE_MAX; i++)
if (nla[i]) {
@@ -1007,6 +1029,19 @@ list_create(struct ipset_session *session, struct nlattr *nla[])
ipset_data_setname(data),
type->name, type->revision);
break;
+ case IPSET_LIST_JSON:
+ if (!firstipset)
+ safe_snprintf(session, ",\n");
+ firstipset = false;
+ safe_snprintf(session,
+ " \{\n"
+ " \"name\" : \"%s\",\n"
+ " \"type\" : \"%s\",\n"
+ " \"revision\" : %u,\n"
+ " \"header\" : \{\n",
+ ipset_data_setname(data),
+ type->name, type->revision);
+ break;
default:
break;
}
@@ -1042,6 +1077,22 @@ list_create(struct ipset_session *session, struct nlattr *nla[])
safe_dprintf(session, arg->print, arg->opt);
safe_snprintf(session, "</%s>", arg->name[0]);
break;
+ case IPSET_LIST_JSON:
+ if (arg->has_arg == IPSET_NO_ARG) {
+ safe_snprintf(session,
+ " \"%s\" : true,\n", arg->name[0]);
+ break;
+ }
+ if (arg->opt == IPSET_OPT_FAMILY) {
+ safe_snprintf(session, " \"%s\" : \"", arg->name[0]);
+ safe_dprintf(session, arg->print, arg->opt);
+ safe_snprintf(session, "\",\n", arg->name[0]);
+ break;
+ }
+ safe_snprintf(session, " \"%s\" : ", arg->name[0]);
+ safe_dprintf(session, arg->print, arg->opt);
+ safe_snprintf(session, ",\n", arg->name[0]);
+ break;
default:
break;
}
@@ -1079,6 +1130,21 @@ list_create(struct ipset_session *session, struct nlattr *nla[])
"</header>\n" :
"</header>\n<members>\n");
break;
+ case IPSET_LIST_JSON:
+ safe_snprintf(session, " \"memsize\" : ");
+ safe_dprintf(session, ipset_print_number, IPSET_OPT_MEMSIZE);
+ safe_snprintf(session, ",\n \"references\" : ");
+ safe_dprintf(session, ipset_print_number, IPSET_OPT_REFERENCES);
+ if (ipset_data_test(data, IPSET_OPT_ELEMENTS)) {
+ safe_snprintf(session, ",\n \"numentries\" : ");
+ safe_dprintf(session, ipset_print_number, IPSET_OPT_ELEMENTS);
+ }
+ safe_snprintf(session, "\n");
+ safe_snprintf(session,
+ session->envopts & IPSET_ENV_LIST_HEADER ?
+ " },\n" :
+ " },\n \"members\" : [");
+ break;
default:
break;
}
@@ -1214,11 +1280,24 @@ print_set_done(struct ipset_session *session, bool callback_done)
if (session->saved_setname[0] != '\0')
safe_snprintf(session, "</members>\n</ipset>\n");
break;
+ case IPSET_LIST_JSON:
+ if (session->envopts & IPSET_ENV_LIST_SETNAME)
+ break;
+ if (session->envopts & IPSET_ENV_LIST_HEADER) {
+ if (session->saved_setname[0] != '\0')
+ safe_snprintf(session, " }");
+ break;
+ }
+ if (session->saved_setname[0] != '\0')
+ safe_snprintf(session, "\n ]\n }");
+ break;
default:
break;
}
if (callback_done && session->mode == IPSET_LIST_XML)
safe_snprintf(session, "</ipsets>\n");
+ if (callback_done && session->mode == IPSET_LIST_JSON)
+ safe_snprintf(session, "\n]\n");
return call_outfn(session) ? MNL_CB_ERROR : MNL_CB_STOP;
}
@@ -1245,6 +1324,9 @@ callback_list(struct ipset_session *session, struct nlattr *nla[],
if (session->mode == IPSET_LIST_XML)
safe_snprintf(session, "<ipset name=\"%s\"/>\n",
ipset_data_setname(data));
+ if (session->mode == IPSET_LIST_JSON)
+ safe_snprintf(session, "\"name\" : \"%s\"\n",
+ ipset_data_setname(data));
else
safe_snprintf(session, "%s\n",
ipset_data_setname(data));
@@ -2208,6 +2290,11 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
session->mode == IPSET_LIST_XML)
safe_snprintf(session, "<ipsets>\n");
+ /* Start the root element in json mode */
+ if ((cmd == IPSET_CMD_LIST || cmd == IPSET_CMD_SAVE) &&
+ session->mode == IPSET_LIST_JSON)
+ safe_snprintf(session, "[\n");
+
D("next: build_msg");
/* Build new message or append buffered commands */
ret = build_msg(session, aggregate);