summaryrefslogtreecommitdiffstats
path: root/lib/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/session.c')
-rw-r--r--lib/session.c125
1 files changed, 114 insertions, 11 deletions
diff --git a/lib/session.c b/lib/session.c
index 1ca26ff..f822288 100644
--- a/lib/session.c
+++ b/lib/session.c
@@ -462,6 +462,10 @@ static const struct ipset_attr_policy create_attrs[] = {
.type = MNL_TYPE_U32,
.opt = IPSET_OPT_MEMSIZE,
},
+ [IPSET_ATTR_BITMASK] = {
+ .type = MNL_TYPE_NESTED,
+ .opt = IPSET_OPT_BITMASK,
+ },
};
static const struct ipset_attr_policy adt_attrs[] = {
@@ -856,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 */
@@ -890,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;
@@ -898,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]);
@@ -925,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;
}
@@ -932,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");
@@ -968,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]) {
@@ -1003,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;
}
@@ -1038,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");
+ break;
+ }
+ safe_snprintf(session, " \"%s\" : ", arg->name[0]);
+ safe_dprintf(session, arg->print, arg->opt);
+ safe_snprintf(session, ",\n");
+ break;
default:
break;
}
@@ -1075,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;
}
@@ -1210,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;
}
@@ -1223,6 +1306,7 @@ callback_list(struct ipset_session *session, struct nlattr *nla[],
enum ipset_cmd cmd)
{
struct ipset_data *data = session->data;
+ static bool firstipset = true;
if (setjmp(printf_failure)) {
session->saved_setname[0] = '\0';
@@ -1241,7 +1325,13 @@ 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));
- else
+ else if (session->mode == IPSET_LIST_JSON) {
+ if (!firstipset)
+ safe_snprintf(session, ",\n");
+ firstipset = false;
+ safe_snprintf(session, " { \"name\" : \"%s\" }",
+ ipset_data_setname(data));
+ } else
safe_snprintf(session, "%s\n",
ipset_data_setname(data));
return call_outfn(session) ? MNL_CB_ERROR : MNL_CB_OK;
@@ -1721,6 +1811,10 @@ rawdata2attr(struct ipset_session *session, struct nlmsghdr *nlh,
if (attr->type == MNL_TYPE_NESTED) {
/* IP addresses */
struct nlattr *nested;
+
+ if (type == IPSET_ATTR_BITMASK)
+ family = ipset_data_family(session->data);
+
int atype = family == NFPROTO_IPV4 ? IPSET_ATTR_IPADDR_IPV4
: IPSET_ATTR_IPADDR_IPV6;
@@ -2187,18 +2281,27 @@ ipset_cmd(struct ipset_session *session, enum ipset_cmd cmd, uint32_t lineno)
session->cmd = cmd;
session->lineno = lineno;
- /* Set default output mode */
- if (cmd == IPSET_CMD_LIST) {
- if (session->mode == IPSET_LIST_NONE)
- session->mode = IPSET_LIST_PLAIN;
- } else if (cmd == IPSET_CMD_SAVE) {
+ if (cmd == IPSET_CMD_LIST || cmd == IPSET_CMD_SAVE) {
+ /* Set default output mode */
if (session->mode == IPSET_LIST_NONE)
- session->mode = IPSET_LIST_SAVE;
+ session->mode = cmd == IPSET_CMD_LIST ?
+ IPSET_LIST_PLAIN : IPSET_LIST_SAVE;
+ /* Reset just in case there are multiple modes in a session */
+ ipset_envopt_unset(session, IPSET_ENV_QUOTED);
+ switch (session->mode) {
+ case IPSET_LIST_XML:
+ /* Start the root element in XML mode */
+ safe_snprintf(session, "<ipsets>\n");
+ break;
+ case IPSET_LIST_JSON:
+ /* Start the root element in json mode */
+ ipset_envopt_set(session, IPSET_ENV_QUOTED);
+ safe_snprintf(session, "[\n");
+ break;
+ default:
+ break;
+ }
}
- /* Start the root element in XML mode */
- if ((cmd == IPSET_CMD_LIST || cmd == IPSET_CMD_SAVE) &&
- session->mode == IPSET_LIST_XML)
- safe_snprintf(session, "<ipsets>\n");
D("next: build_msg");
/* Build new message or append buffered commands */