* [libnftables PATCH 0/5] XML works
@ 2013-04-10 16:39 Arturo Borrero
2013-04-10 16:39 ` [libnftables PATCH 1/5] src: rule: small fix XML output Arturo Borrero
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Arturo Borrero @ 2013-04-10 16:39 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
The following series implements:
* small XML format fixes in printing.
* a workaround for target/match binary data.
* delete all \n and \t in XML printing.
* print expr flags in XML (the <expr_flags> node)
* [RFC] XML-to-object parsing.
Note that for XML parsing i've used libmxml (http://minixml.org/)
Also, please consider the XML parsing code a RFC.
---
Arturo Borrero (5):
src: rule: small fix XML output
src: expr: XML printing for binary data in targer and match
src: xml printing: delete text format
src: expr: print flags in XML
src: support for XML parsing
Make_global.am | 2
configure.ac | 1
include/libnftables/chain.h | 1
include/libnftables/rule.h | 1
include/libnftables/table.h | 1
src/chain.c | 206 ++++++++++++++++++++++++++++++++++--
src/expr/bitwise.c | 151 ++++++++++++++++++++++++--
src/expr/cmp.c | 139 +++++++++++++++++++++++-
src/expr/counter.c | 87 +++++++++++++++
src/expr/data_reg.c | 249 +++++++++++++++++++++++++++++++++++++++++++
src/expr/immediate.c | 118 ++++++++++++++++++++
src/expr/lookup.c | 107 +++++++++++++++++-
src/expr/match.c | 146 ++++++++++++++++++++++++-
src/expr/meta.c | 84 ++++++++++++++-
src/expr/nat.c | 159 +++++++++++++++++++++++++++
src/expr/payload.c | 118 ++++++++++++++++++++
src/expr/target.c | 148 +++++++++++++++++++++++++-
src/expr_ops.h | 1
src/libnftables.map | 3 +
src/rule.c | 189 ++++++++++++++++++++++++++++++++-
src/table.c | 102 ++++++++++++++++--
21 files changed, 1937 insertions(+), 76 deletions(-)
--
Signature
^ permalink raw reply [flat|nested] 8+ messages in thread
* [libnftables PATCH 1/5] src: rule: small fix XML output
2013-04-10 16:39 [libnftables PATCH 0/5] XML works Arturo Borrero
@ 2013-04-10 16:39 ` Arturo Borrero
2013-04-18 23:32 ` Pablo Neira Ayuso
2013-04-10 16:40 ` [libnftables PATCH 2/5] src: expr: XML printing for binary data in targer and match Arturo Borrero
` (3 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Arturo Borrero @ 2013-04-10 16:39 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
This patch aplies two fixes:
* snprintf XML output offset for rule.
* add XML <flags> node, missing in previous patches.
The <flags> node will be used for parsing a rule in XML.
Signed-off-by: Arturo Borrero González <arturo.borrero.glez@gmail.com>
---
src/rule.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/rule.c b/src/rule.c
index e419b0a..c463c69 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -451,9 +451,10 @@ static int nft_rule_snprintf_xml(char *buf, size_t size, struct nft_rule *r,
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
ret = snprintf(buf+offset, len, "<rule_flags>%u</rule_flags>"
+ "<flags>%u</flags>"
"<compat_flags>%u</compat_flags>"
"<compat_proto>%u</compat_proto>",
- r->rule_flags,
+ r->rule_flags, r->flags,
r->compat.flags, r->compat.proto);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
@@ -469,7 +470,7 @@ static int nft_rule_snprintf_xml(char *buf, size_t size, struct nft_rule *r,
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
}
- ret = snprintf(buf+offset-1, len, "\n</rule>\n ");
+ ret = snprintf(buf+offset, len, "\n</rule>\n ");
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
return ret;
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [libnftables PATCH 2/5] src: expr: XML printing for binary data in targer and match
2013-04-10 16:39 [libnftables PATCH 0/5] XML works Arturo Borrero
2013-04-10 16:39 ` [libnftables PATCH 1/5] src: rule: small fix XML output Arturo Borrero
@ 2013-04-10 16:40 ` Arturo Borrero
2013-04-10 16:40 ` [libnftables PATCH 3/5] src: xml printing: delete text format Arturo Borrero
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Arturo Borrero @ 2013-04-10 16:40 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
This is a try for expr/match and expr/target to be more XML friendly.
Signed-off-by: Arturo Borrero González <arturo.borrero.glez@gmail.com>
---
src/expr/match.c | 6 +++---
src/expr/target.c | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/expr/match.c b/src/expr/match.c
index f83a8ea..d1f5963 100644
--- a/src/expr/match.c
+++ b/src/expr/match.c
@@ -193,12 +193,12 @@ int nft_rule_expr_match_snprintf_xml(char *buf, size_t len,
int offset = 0;
uint8_t *data = (uint8_t *)mt->data;
- ret = snprintf(buf, len, "\t\t<name>%s</name> <rev>%u</rev> <info>0x",
- mt->name, mt->rev);
+ ret = snprintf(buf, len, "\t\t<name>%s</name> <rev>%u</rev> <info><len>%u</len>",
+ mt->name, mt->rev, mt->data_len);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
for (i=0; i < mt->data_len; i++) {
- ret = snprintf(buf+offset, len, "%x", data[i] & 0xff);
+ ret = snprintf(buf+offset, len, "<data%d>0x%.2x</data%d>",i, data[i] & 0xff, i);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
}
diff --git a/src/expr/target.c b/src/expr/target.c
index 86c9bc8..aae58ce 100644
--- a/src/expr/target.c
+++ b/src/expr/target.c
@@ -193,12 +193,12 @@ int nft_rule_exp_target_snprintf_xml(char *buf, size_t len,
int offset = 0;
uint8_t *data = (uint8_t *)tg->data;
- ret = snprintf(buf, len, "\t\t<name>%s</name> <rev>%u</rev> <info>0x",
- tg->name, tg->rev);
+ ret = snprintf(buf, len, "\t\t<name>%s</name> <rev>%u</rev> <info><len>%u</len>",
+ tg->name, tg->rev, tg->data_len);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
for (i=0; i < tg->data_len; i++) {
- ret = snprintf(buf+offset, len, "%x", data[i] & 0xff);
+ ret = snprintf(buf+offset, len, "<data%d>0x%.2x</data%d>",i, data[i] & 0xff, i);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
}
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [libnftables PATCH 3/5] src: xml printing: delete text format
2013-04-10 16:39 [libnftables PATCH 0/5] XML works Arturo Borrero
2013-04-10 16:39 ` [libnftables PATCH 1/5] src: rule: small fix XML output Arturo Borrero
2013-04-10 16:40 ` [libnftables PATCH 2/5] src: expr: XML printing for binary data in targer and match Arturo Borrero
@ 2013-04-10 16:40 ` Arturo Borrero
2013-04-19 0:00 ` Pablo Neira Ayuso
2013-04-10 16:40 ` [libnftables PATCH 4/5] src: expr: print flags in XML Arturo Borrero
2013-04-10 16:40 ` [libnftables PATCH 5/5] src: support for XML parsing Arturo Borrero
4 siblings, 1 reply; 8+ messages in thread
From: Arturo Borrero @ 2013-04-10 16:40 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
Delete all \n and \t from XML output.
Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
src/chain.c | 24 ++++++++++++------------
src/expr/bitwise.c | 8 ++++----
src/expr/cmp.c | 4 ++--
src/expr/counter.c | 2 +-
src/expr/immediate.c | 4 ++--
src/expr/lookup.c | 2 +-
src/expr/match.c | 2 +-
src/expr/meta.c | 4 ++--
src/expr/nat.c | 8 ++++----
src/expr/payload.c | 4 ++--
src/expr/target.c | 2 +-
src/rule.c | 8 ++++----
src/table.c | 14 +++++++-------
13 files changed, 43 insertions(+), 43 deletions(-)
diff --git a/src/chain.c b/src/chain.c
index 9d77179..4c111b6 100644
--- a/src/chain.c
+++ b/src/chain.c
@@ -450,18 +450,18 @@ static int nft_chain_snprintf_xml(char *buf, size_t size, struct nft_chain *c)
{
return snprintf(buf, size,
"<chain name=\"%s\" handle=\"%lu\""
- " bytes=\"%lu\" packets=\"%lu\" >\n"
- "\t<properties>\n"
- "\t\t<flags>%d</flags>\n"
- "\t\t<type>%s</type>\n"
- "\t\t<table>%s</table>\n"
- "\t\t<prio>%d</prio>\n"
- "\t\t<use>%d</use>\n"
- "\t\t<hooknum>%d</hooknum>\n"
- "\t\t<policy>%d</policy>\n"
- "\t\t<family>%d</family>\n"
- "\t</properties>\n"
- "</chain>\n",
+ " bytes=\"%lu\" packets=\"%lu\" >"
+ "<properties>"
+ "<flags>%d</flags>"
+ "<type>%s</type>"
+ "<table>%s</table>"
+ "<prio>%d</prio>"
+ "<use>%d</use>"
+ "<hooknum>%d</hooknum>"
+ "<policy>%d</policy>"
+ "<family>%d</family>"
+ "</properties>"
+ "</chain>",
c->name, c->handle, c->bytes, c->packets,
c->flags, c->type, c->table, c->prio,
c->use, c->hooknum, c->policy, c->family);
diff --git a/src/expr/bitwise.c b/src/expr/bitwise.c
index 052144e..ddcf6a7 100644
--- a/src/expr/bitwise.c
+++ b/src/expr/bitwise.c
@@ -201,8 +201,8 @@ nft_rule_expr_bitwise_snprintf_xml(char *buf, size_t size,
{
int len = size, offset = 0, ret;
- ret = snprintf(buf, len, "\t\t<sreg>%u</sreg> "
- "<dreg>%u</dreg> ",
+ ret = snprintf(buf, len, "<sreg>%u</sreg>"
+ "<dreg>%u</dreg>",
bitwise->sreg, bitwise->dreg);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
@@ -213,14 +213,14 @@ nft_rule_expr_bitwise_snprintf_xml(char *buf, size_t size,
NFT_RULE_O_XML, 0, DATA_VALUE);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
- ret = snprintf(buf+offset, len, "</mask> <xor>");
+ ret = snprintf(buf+offset, len, "</mask><xor>");
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
ret = nft_data_reg_snprintf(buf+offset, len, &bitwise->xor,
NFT_RULE_O_XML, 0, DATA_VALUE);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
- ret = snprintf(buf+offset, len, "</xor> ");
+ ret = snprintf(buf+offset, len, "</xor>");
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
return offset;
diff --git a/src/expr/cmp.c b/src/expr/cmp.c
index 6b5a3a2..3de849a 100644
--- a/src/expr/cmp.c
+++ b/src/expr/cmp.c
@@ -171,7 +171,7 @@ nft_rule_expr_cmp_snprintf_xml(char *buf, size_t size, struct nft_expr_cmp *cmp)
{
int len = size, offset = 0, ret;
- ret = snprintf(buf, len, "\t\t<sreg>%u</sreg> <op>%s</op> <cmpdata>",
+ ret = snprintf(buf, len, "<sreg>%u</sreg><op>%s</op><cmpdata>",
cmp->sreg, expr_cmp_str[cmp->op]);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
@@ -179,7 +179,7 @@ nft_rule_expr_cmp_snprintf_xml(char *buf, size_t size, struct nft_expr_cmp *cmp)
NFT_RULE_O_XML, 0, DATA_VALUE);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
- ret = snprintf(buf+offset, len, "</cmpdata> ");
+ ret = snprintf(buf+offset, len, "</cmpdata>");
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
return offset;
diff --git a/src/expr/counter.c b/src/expr/counter.c
index d2da9bf..550d56d 100644
--- a/src/expr/counter.c
+++ b/src/expr/counter.c
@@ -133,7 +133,7 @@ nft_rule_expr_counter_snprintf(char *buf, size_t len, uint32_t type,
switch(type) {
case NFT_RULE_O_XML:
- return snprintf(buf, len, "\t\t<pkts>%lu</pkts> <bytes>%lu</bytes> ",
+ return snprintf(buf, len, "<pkts>%lu</pkts><bytes>%lu</bytes>",
ctr->pkts, ctr->bytes);
case NFT_RULE_O_DEFAULT:
return snprintf(buf, len, "pkts=%lu bytes=%lu ",
diff --git a/src/expr/immediate.c b/src/expr/immediate.c
index 082db76..10f7793 100644
--- a/src/expr/immediate.c
+++ b/src/expr/immediate.c
@@ -202,8 +202,8 @@ nft_rule_expr_immediate_snprintf_xml(char *buf, size_t len,
int size = len, offset = 0, ret;
struct nft_expr_immediate *imm = (struct nft_expr_immediate *)e->data;
- ret = snprintf(buf, len, "\t\t<dreg>%u</dreg>"
- "\n\t\t<immediatedata>", imm->dreg);
+ ret = snprintf(buf, len, "<dreg>%u</dreg>"
+ "<immediatedata>", imm->dreg);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
diff --git a/src/expr/lookup.c b/src/expr/lookup.c
index 550c850..003554b 100644
--- a/src/expr/lookup.c
+++ b/src/expr/lookup.c
@@ -156,7 +156,7 @@ nft_rule_expr_lookup_snprintf_xml(char *buf, size_t size,
{
int len = size, offset = 0, ret;
- ret = snprintf(buf, len, "<set>%s</set><sreg>%u</sreg><dreg>%u</dreg>\n",
+ ret = snprintf(buf, len, "<set>%s</set><sreg>%u</sreg><dreg>%u</dreg>",
l->set_name, l->sreg, l->dreg);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
diff --git a/src/expr/match.c b/src/expr/match.c
index d1f5963..d3bfe76 100644
--- a/src/expr/match.c
+++ b/src/expr/match.c
@@ -193,7 +193,7 @@ int nft_rule_expr_match_snprintf_xml(char *buf, size_t len,
int offset = 0;
uint8_t *data = (uint8_t *)mt->data;
- ret = snprintf(buf, len, "\t\t<name>%s</name> <rev>%u</rev> <info><len>%u</len>",
+ ret = snprintf(buf, len, "<name>%s</name><rev>%u</rev><info><len>%u</len>",
mt->name, mt->rev, mt->data_len);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
diff --git a/src/expr/meta.c b/src/expr/meta.c
index 2095545..bfc1aa6 100644
--- a/src/expr/meta.c
+++ b/src/expr/meta.c
@@ -133,8 +133,8 @@ nft_rule_expr_meta_snprintf(char *buf, size_t len, uint32_t type,
switch(type) {
case NFT_RULE_O_XML:
- return snprintf(buf, len, "\t\t<dreg>%u</dreg>"
- " <key>%u</key> ",
+ return snprintf(buf, len, "<dreg>%u</dreg>"
+ "<key>%u</key>",
meta->dreg, meta->key);
case NFT_RULE_O_DEFAULT:
return snprintf(buf, len, "dreg=%u key=%u ",
diff --git a/src/expr/nat.c b/src/expr/nat.c
index 68217bd..56212a7 100644
--- a/src/expr/nat.c
+++ b/src/expr/nat.c
@@ -211,17 +211,17 @@ nft_rule_expr_nat_snprintf_xml(char *buf, size_t size,
switch (nat->type) {
case NFT_NAT_SNAT:
ret = snprintf(buf, len,
- "\t\t<type>NFT_NAT_SNAT</type> ");
+ "<type>NFT_NAT_SNAT</type>");
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
break;
case NFT_NAT_DNAT:
ret = snprintf(buf, len,
- "\t\t<type>NFT_NAT_DNAT</type> ");
+ "<type>NFT_NAT_DNAT</type>");
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
break;
}
- ret = snprintf(buf, len, "<family>%s</family> ",
+ ret = snprintf(buf, len, "<family>%s</family>",
nat->family == AF_INET ? "AF_INET" : "AF_INET6");
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
@@ -234,7 +234,7 @@ nft_rule_expr_nat_snprintf_xml(char *buf, size_t size,
if (e->flags & (1 << NFT_EXPR_NAT_REG_PROTO_MIN)) {
ret = snprintf(buf, len, "<sreg_proto_min>%u</sreg_proto_min>"
- " <sreg_proto_max>%u</sreg_proto_max> ",
+ "<sreg_proto_max>%u</sreg_proto_max>",
nat->sreg_proto_min, nat->sreg_proto_max);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
}
diff --git a/src/expr/payload.c b/src/expr/payload.c
index 33fcef1..091078b 100644
--- a/src/expr/payload.c
+++ b/src/expr/payload.c
@@ -172,8 +172,8 @@ nft_rule_expr_payload_snprintf(char *buf, size_t len, uint32_t type,
switch(type) {
case NFT_RULE_O_XML:
- return snprintf(buf, len, "\t\t<dreg>%u</dreg>"
- "<base>%u</base> <offset>%u</offset>"
+ return snprintf(buf, len, "<dreg>%u</dreg>"
+ "<base>%u</base><offset>%u</offset>"
"<len>%u</len>",
payload->dreg, payload->base,
payload->offset, payload->len);
diff --git a/src/expr/target.c b/src/expr/target.c
index aae58ce..b6cfd04 100644
--- a/src/expr/target.c
+++ b/src/expr/target.c
@@ -193,7 +193,7 @@ int nft_rule_exp_target_snprintf_xml(char *buf, size_t len,
int offset = 0;
uint8_t *data = (uint8_t *)tg->data;
- ret = snprintf(buf, len, "\t\t<name>%s</name> <rev>%u</rev> <info><len>%u</len>",
+ ret = snprintf(buf, len, "<name>%s</name><rev>%u</rev><info><len>%u</len>",
tg->name, tg->rev, tg->data_len);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
diff --git a/src/rule.c b/src/rule.c
index c463c69..6178e57 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -445,7 +445,7 @@ static int nft_rule_snprintf_xml(char *buf, size_t size, struct nft_rule *r,
ret = snprintf(buf, size,
"<rule family=\"%u\" table=\"%s\" "
- "chain=\"%s\" handle=\"%llu\">\n ",
+ "chain=\"%s\" handle=\"%llu\">",
r->family, r->table, r->chain,
(unsigned long long)r->handle);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
@@ -460,17 +460,17 @@ static int nft_rule_snprintf_xml(char *buf, size_t size, struct nft_rule *r,
list_for_each_entry(expr, &r->expr_list, head) {
ret = snprintf(buf+offset, len,
- "\n\t<expr type=\"%s\">\n", expr->ops->name);
+ "<expr type=\"%s\">", expr->ops->name);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
ret = expr->ops->snprintf(buf+offset, len, type, flags, expr);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
- ret = snprintf(buf+offset, len, "\n\t</expr>");
+ ret = snprintf(buf+offset, len, "</expr>");
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
}
- ret = snprintf(buf+offset, len, "\n</rule>\n ");
+ ret = snprintf(buf+offset, len, "</rule>");
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
return ret;
diff --git a/src/table.c b/src/table.c
index f109cdd..b47d623 100644
--- a/src/table.c
+++ b/src/table.c
@@ -185,13 +185,13 @@ EXPORT_SYMBOL(nft_table_nlmsg_parse);
static int nft_table_snprintf_xml(char *buf, size_t size, struct nft_table *t)
{
return snprintf(buf, size,
- "<table name=\"%s\" >\n"
- "\t<properties>\n"
- "\t\t<family>%u</family>\n"
- "\t\t<flags>%d</flags>\n"
- "\t\t<table_flags>%d</table_flags>\n"
- "\t</properties>\n"
- "</table>\n" ,
+ "<table name=\"%s\" >"
+ "<properties>"
+ "<family>%u</family>"
+ "<flags>%d</flags>"
+ "<table_flags>%d</table_flags>"
+ "</properties>"
+ "</table>" ,
t->name, t->family, t->flags, t->table_flags);
}
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [libnftables PATCH 4/5] src: expr: print flags in XML
2013-04-10 16:39 [libnftables PATCH 0/5] XML works Arturo Borrero
` (2 preceding siblings ...)
2013-04-10 16:40 ` [libnftables PATCH 3/5] src: xml printing: delete text format Arturo Borrero
@ 2013-04-10 16:40 ` Arturo Borrero
2013-04-10 16:40 ` [libnftables PATCH 5/5] src: support for XML parsing Arturo Borrero
4 siblings, 0 replies; 8+ messages in thread
From: Arturo Borrero @ 2013-04-10 16:40 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
This patch adds the <expr_flags> XML node to expressions printing.
Using this new node, a exact copy of the expr is exported, so is possible to know what attributes were originally set in the expr.
Signed-off-by: Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
---
src/expr/bitwise.c | 17 ++++++++++-------
src/expr/cmp.c | 15 ++++++++++-----
src/expr/counter.c | 6 ++++--
src/expr/immediate.c | 4 ++++
src/expr/lookup.c | 17 +++++++++--------
src/expr/match.c | 8 ++++++--
src/expr/meta.c | 5 +++--
src/expr/nat.c | 4 ++++
src/expr/payload.c | 5 +++--
src/expr/target.c | 9 +++++++--
10 files changed, 60 insertions(+), 30 deletions(-)
diff --git a/src/expr/bitwise.c b/src/expr/bitwise.c
index ddcf6a7..4376fa0 100644
--- a/src/expr/bitwise.c
+++ b/src/expr/bitwise.c
@@ -197,8 +197,9 @@ nft_rule_expr_bitwise_parse(struct nft_rule_expr *e, struct nlattr *attr)
static int
nft_rule_expr_bitwise_snprintf_xml(char *buf, size_t size,
- struct nft_expr_bitwise *bitwise)
+ struct nft_rule_expr *e)
{
+ struct nft_expr_bitwise *bitwise = (struct nft_expr_bitwise *)e->data;
int len = size, offset = 0, ret;
ret = snprintf(buf, len, "<sreg>%u</sreg>"
@@ -223,13 +224,18 @@ nft_rule_expr_bitwise_snprintf_xml(char *buf, size_t size,
ret = snprintf(buf+offset, len, "</xor>");
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ ret = snprintf(buf+offset, len, "<expr_flags>%u</expr_flags>",
+ e->flags);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
return offset;
}
static int
nft_rule_expr_bitwise_snprintf_default(char *buf, size_t size,
- struct nft_expr_bitwise *bitwise)
+ struct nft_rule_expr *e)
{
+ struct nft_expr_bitwise *bitwise = (struct nft_expr_bitwise *)e->data;
int len = size, offset = 0, ret;
ret = snprintf(buf, len, "sreg=%u dreg=%u ",
@@ -257,14 +263,11 @@ static int
nft_rule_expr_bitwise_snprintf(char *buf, size_t size, uint32_t type,
uint32_t flags, struct nft_rule_expr *e)
{
- struct nft_expr_bitwise *bitwise = (struct nft_expr_bitwise *)e->data;
-
switch(type) {
case NFT_RULE_O_XML:
- return nft_rule_expr_bitwise_snprintf_xml(buf, size, bitwise);
+ return nft_rule_expr_bitwise_snprintf_xml(buf, size, e);
case NFT_RULE_O_DEFAULT:
- return nft_rule_expr_bitwise_snprintf_default(buf, size,
- bitwise);
+ return nft_rule_expr_bitwise_snprintf_default(buf, size, e);
default:
break;
}
diff --git a/src/expr/cmp.c b/src/expr/cmp.c
index 3de849a..e1e76a6 100644
--- a/src/expr/cmp.c
+++ b/src/expr/cmp.c
@@ -167,8 +167,9 @@ static char *expr_cmp_str[] = {
};
static int
-nft_rule_expr_cmp_snprintf_xml(char *buf, size_t size, struct nft_expr_cmp *cmp)
+nft_rule_expr_cmp_snprintf_xml(char *buf, size_t size, struct nft_rule_expr *e)
{
+ struct nft_expr_cmp *cmp = (struct nft_expr_cmp *)e->data;
int len = size, offset = 0, ret;
ret = snprintf(buf, len, "<sreg>%u</sreg><op>%s</op><cmpdata>",
@@ -182,13 +183,18 @@ nft_rule_expr_cmp_snprintf_xml(char *buf, size_t size, struct nft_expr_cmp *cmp)
ret = snprintf(buf+offset, len, "</cmpdata>");
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ ret = snprintf(buf+offset, len, "<expr_flags>%u</expr_flags>",
+ e->flags);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
return offset;
}
static int
nft_rule_expr_cmp_snprintf_default(char *buf, size_t size,
- struct nft_expr_cmp *cmp)
+ struct nft_rule_expr *e)
{
+ struct nft_expr_cmp *cmp = (struct nft_expr_cmp *)e->data;
int len = size, offset = 0, ret;
ret = snprintf(buf, len, "sreg=%u op=%s data=",
@@ -206,12 +212,11 @@ static int
nft_rule_expr_cmp_snprintf(char *buf, size_t size, uint32_t type,
uint32_t flags, struct nft_rule_expr *e)
{
- struct nft_expr_cmp *cmp = (struct nft_expr_cmp *)e->data;
switch(type) {
case NFT_RULE_O_XML:
- return nft_rule_expr_cmp_snprintf_xml(buf, size, cmp);
+ return nft_rule_expr_cmp_snprintf_xml(buf, size, e);
case NFT_RULE_O_DEFAULT:
- return nft_rule_expr_cmp_snprintf_default(buf, size, cmp);
+ return nft_rule_expr_cmp_snprintf_default(buf, size, e);
default:
break;
}
diff --git a/src/expr/counter.c b/src/expr/counter.c
index 550d56d..ec6f637 100644
--- a/src/expr/counter.c
+++ b/src/expr/counter.c
@@ -133,8 +133,10 @@ nft_rule_expr_counter_snprintf(char *buf, size_t len, uint32_t type,
switch(type) {
case NFT_RULE_O_XML:
- return snprintf(buf, len, "<pkts>%lu</pkts><bytes>%lu</bytes>",
- ctr->pkts, ctr->bytes);
+ return snprintf(buf, len, "<pkts>%lu</pkts>"
+ "<bytes>%lu</bytes>"
+ "<expr_flags>%u</expr_flags>",
+ ctr->pkts, ctr->bytes, e->flags);
case NFT_RULE_O_DEFAULT:
return snprintf(buf, len, "pkts=%lu bytes=%lu ",
ctr->pkts, ctr->bytes);
diff --git a/src/expr/immediate.c b/src/expr/immediate.c
index 10f7793..d59f109 100644
--- a/src/expr/immediate.c
+++ b/src/expr/immediate.c
@@ -226,6 +226,10 @@ nft_rule_expr_immediate_snprintf_xml(char *buf, size_t len,
ret = snprintf(buf+offset, len, "</immediatedata>");
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ ret = snprintf(buf+offset, len, "<expr_flags>%u</expr_flags>",
+ e->flags);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
return offset;
}
diff --git a/src/expr/lookup.c b/src/expr/lookup.c
index 003554b..2abe82e 100644
--- a/src/expr/lookup.c
+++ b/src/expr/lookup.c
@@ -152,12 +152,14 @@ nft_rule_expr_lookup_parse(struct nft_rule_expr *e, struct nlattr *attr)
static int
nft_rule_expr_lookup_snprintf_xml(char *buf, size_t size,
- struct nft_expr_lookup *l)
+ struct nft_rule_expr *e)
{
+ struct nft_expr_lookup *l = (struct nft_expr_lookup *)e->data;
int len = size, offset = 0, ret;
- ret = snprintf(buf, len, "<set>%s</set><sreg>%u</sreg><dreg>%u</dreg>",
- l->set_name, l->sreg, l->dreg);
+ ret = snprintf(buf, len, "<set>%s</set><sreg>%u</sreg><dreg>%u</dreg>"
+ "<expr_flags>%u</expr_flags>",
+ l->set_name, l->sreg, l->dreg, e->flags);
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
return offset;
@@ -165,8 +167,9 @@ nft_rule_expr_lookup_snprintf_xml(char *buf, size_t size,
static int
nft_rule_expr_lookup_snprintf_default(char *buf, size_t size,
- struct nft_expr_lookup *l)
+ struct nft_rule_expr *e)
{
+ struct nft_expr_lookup *l = (struct nft_expr_lookup *)e->data;
int len = size, offset = 0, ret;
ret = snprintf(buf, len, "set=%s sreg=%u dreg=%u\n",
@@ -180,13 +183,11 @@ static int
nft_rule_expr_lookup_snprintf(char *buf, size_t size, uint32_t type,
uint32_t flags, struct nft_rule_expr *e)
{
- struct nft_expr_lookup *lookup = (struct nft_expr_lookup *)e->data;
-
switch(type) {
case NFT_RULE_O_XML:
- return nft_rule_expr_lookup_snprintf_xml(buf, size, lookup);
+ return nft_rule_expr_lookup_snprintf_xml(buf, size, e);
case NFT_RULE_O_DEFAULT:
- return nft_rule_expr_lookup_snprintf_default(buf, size, lookup);
+ return nft_rule_expr_lookup_snprintf_default(buf, size, e);
default:
break;
}
diff --git a/src/expr/match.c b/src/expr/match.c
index d3bfe76..9a2696e 100644
--- a/src/expr/match.c
+++ b/src/expr/match.c
@@ -186,8 +186,9 @@ static int nft_rule_expr_match_parse(struct nft_rule_expr *e, struct nlattr *att
static
int nft_rule_expr_match_snprintf_xml(char *buf, size_t len,
- struct nft_expr_match *mt)
+ struct nft_rule_expr *e)
{
+ struct nft_expr_match *mt = (struct nft_expr_match *)e->data;
int ret, size=len;
int i;
int offset = 0;
@@ -205,6 +206,9 @@ int nft_rule_expr_match_snprintf_xml(char *buf, size_t len,
ret = snprintf(buf+offset, len, "</info>" );
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ ret = snprintf(buf+offset, len, "<expr_flags>%u</expr_flags>", e->flags);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
return offset;
}
@@ -217,7 +221,7 @@ nft_rule_expr_match_snprintf(char *buf, size_t len, uint32_t type,
switch(type) {
case NFT_RULE_O_XML:
- return nft_rule_expr_match_snprintf_xml(buf, len, match);
+ return nft_rule_expr_match_snprintf_xml(buf, len, e);
case NFT_RULE_O_DEFAULT:
return snprintf(buf, len, "name=%s rev=%u ",
match->name, match->rev);
diff --git a/src/expr/meta.c b/src/expr/meta.c
index bfc1aa6..e342a6d 100644
--- a/src/expr/meta.c
+++ b/src/expr/meta.c
@@ -134,8 +134,9 @@ nft_rule_expr_meta_snprintf(char *buf, size_t len, uint32_t type,
switch(type) {
case NFT_RULE_O_XML:
return snprintf(buf, len, "<dreg>%u</dreg>"
- "<key>%u</key>",
- meta->dreg, meta->key);
+ "<key>%u</key>"
+ "<expr_flags>%u</expr_flags>",
+ meta->dreg, meta->key, e->flags);
case NFT_RULE_O_DEFAULT:
return snprintf(buf, len, "dreg=%u key=%u ",
meta->dreg, meta->key);
diff --git a/src/expr/nat.c b/src/expr/nat.c
index 56212a7..382862a 100644
--- a/src/expr/nat.c
+++ b/src/expr/nat.c
@@ -239,6 +239,10 @@ nft_rule_expr_nat_snprintf_xml(char *buf, size_t size,
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
}
+ ret = snprintf(buf, len, "<expr_flags>%u</expr_flags>",
+ e->flags);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
return offset;
}
diff --git a/src/expr/payload.c b/src/expr/payload.c
index 091078b..b72be96 100644
--- a/src/expr/payload.c
+++ b/src/expr/payload.c
@@ -174,9 +174,10 @@ nft_rule_expr_payload_snprintf(char *buf, size_t len, uint32_t type,
case NFT_RULE_O_XML:
return snprintf(buf, len, "<dreg>%u</dreg>"
"<base>%u</base><offset>%u</offset>"
- "<len>%u</len>",
+ "<len>%u</len>"
+ "<expr_flags>%u</expr_flags>",
payload->dreg, payload->base,
- payload->offset, payload->len);
+ payload->offset, payload->len, e->flags);
case NFT_RULE_O_DEFAULT:
return snprintf(buf, len, "dreg=%u base=%u offset=%u len=%u ",
diff --git a/src/expr/target.c b/src/expr/target.c
index b6cfd04..5ceecce 100644
--- a/src/expr/target.c
+++ b/src/expr/target.c
@@ -186,8 +186,9 @@ static int nft_rule_expr_target_parse(struct nft_rule_expr *e, struct nlattr *at
static
int nft_rule_exp_target_snprintf_xml(char *buf, size_t len,
- struct nft_expr_target *tg)
+ struct nft_rule_expr *e)
{
+ struct nft_expr_target *tg = (struct nft_expr_target *)e->data;
int ret, size=len;
int i;
int offset = 0;
@@ -205,6 +206,10 @@ int nft_rule_exp_target_snprintf_xml(char *buf, size_t len,
ret = snprintf(buf+offset, len, "</info>" );
SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+ ret = snprintf(buf+offset, len, "<expr_flags>%u</expr_flags>",
+ e->flags);
+ SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
+
return offset;
}
@@ -216,7 +221,7 @@ nft_rule_expr_target_snprintf(char *buf, size_t len, uint32_t type,
switch(type) {
case NFT_RULE_O_XML:
- return nft_rule_exp_target_snprintf_xml(buf, len, target);
+ return nft_rule_exp_target_snprintf_xml(buf, len, e);
case NFT_RULE_O_DEFAULT:
return snprintf(buf, len, "name=%s rev=%u ",
target->name, target->rev);
^ permalink raw reply related [flat|nested] 8+ messages in thread
* [libnftables PATCH 5/5] src: support for XML parsing
2013-04-10 16:39 [libnftables PATCH 0/5] XML works Arturo Borrero
` (3 preceding siblings ...)
2013-04-10 16:40 ` [libnftables PATCH 4/5] src: expr: print flags in XML Arturo Borrero
@ 2013-04-10 16:40 ` Arturo Borrero
4 siblings, 0 replies; 8+ messages in thread
From: Arturo Borrero @ 2013-04-10 16:40 UTC (permalink / raw)
To: netfilter-devel; +Cc: pablo
This patch adds capabilities for parsing a XML table/chain/rule
Some points to note:
* the XML data is case sensitive (so <chain>asd</chain> != <chain>ASD</chain> != <CHAIN>asd</CHAIN>)
* All XML nodes in each object must be present for the XML to be valid.
(following the format as printed by already included snprintf functions)
* The API functions will receive a XML and return an object (aka table|chain|rule)
* If error, -1 is returned. 0 if not. (you know, easily check if the parsing went OK).
Nice things you could achieve with this patch and all XML-related stuff in libnftables:
* Export the current ruleset (or just one object) in XML format.
* Edit a ruleset in XML.
* Validate a XML ruleset, or each object.
* Import to kernel a XML ruleset, or each object.
* Possibly (using third party apps), do some XML-to-Json and Json-to-XML conversions.
* Build even nicer stuff on top of it.
NOTE: expr/target and expr/match are working, but somewhat provisional.
Actually a binary format, hard to deal within XML (at least for me).
Some code examples/test cases will be added to libnftables in a future patch.
Signed-off-by: Arturo Borrero González <arturo.borrero.glez@gmail.com>
---
Make_global.am | 2
configure.ac | 1
include/libnftables/chain.h | 1
include/libnftables/rule.h | 1
include/libnftables/table.h | 1
src/chain.c | 182 +++++++++++++++++++++++++++++++
src/expr/bitwise.c | 126 ++++++++++++++++++++++
src/expr/cmp.c | 120 +++++++++++++++++++++
src/expr/counter.c | 81 ++++++++++++++
src/expr/data_reg.c | 249 +++++++++++++++++++++++++++++++++++++++++++
src/expr/immediate.c | 110 +++++++++++++++++++
src/expr/lookup.c | 90 ++++++++++++++++
src/expr/match.c | 132 +++++++++++++++++++++++
src/expr/meta.c | 77 +++++++++++++
src/expr/nat.c | 147 +++++++++++++++++++++++++
src/expr/payload.c | 109 +++++++++++++++++++
src/expr/target.c | 133 +++++++++++++++++++++++
src/expr_ops.h | 1
src/libnftables.map | 3 +
src/rule.c | 178 +++++++++++++++++++++++++++++++
src/table.c | 88 +++++++++++++++
21 files changed, 1831 insertions(+), 1 deletion(-)
diff --git a/Make_global.am b/Make_global.am
index 1654f10..8205938 100644
--- a/Make_global.am
+++ b/Make_global.am
@@ -20,5 +20,5 @@
#
LIBVERSION=0:0:0
-AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_srcdir}/include ${LIBMNL_CFLAGS}
+AM_CPPFLAGS = ${regular_CPPFLAGS} -I${top_srcdir}/include ${LIBMNL_CFLAGS} ${LIBMXML_CFLAGS}
AM_CFLAGS = ${regular_CFLAGS} ${GCC_FVISIBILITY_HIDDEN}
diff --git a/configure.ac b/configure.ac
index 01c170a..523133f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -14,6 +14,7 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
dnl Dependencies
PKG_CHECK_MODULES([LIBMNL], [libmnl >= 1.0.0])
+PKG_CHECK_MODULES([LIBMXML], [mxml >= 2.6])
AC_PROG_CC
AM_PROG_CC_C_O
diff --git a/include/libnftables/chain.h b/include/libnftables/chain.h
index a7f6a50..af51191 100644
--- a/include/libnftables/chain.h
+++ b/include/libnftables/chain.h
@@ -44,6 +44,7 @@ enum {
NFT_CHAIN_O_XML,
};
+int nft_chain_xml_parse(struct nft_chain *c, char *xml);
int nft_chain_snprintf(char *buf, size_t size, struct nft_chain *t, uint32_t type, uint32_t flags);
struct nlmsghdr *nft_chain_nlmsg_build_hdr(char *buf, uint16_t cmd, uint16_t family, uint16_t type, uint32_t seq);
diff --git a/include/libnftables/rule.h b/include/libnftables/rule.h
index 50222c5..6eb7efc 100644
--- a/include/libnftables/rule.h
+++ b/include/libnftables/rule.h
@@ -43,6 +43,7 @@ enum {
NFT_RULE_O_XML,
};
+int nft_rule_xml_parse(struct nft_rule *r, char *xml);
int nft_rule_snprintf(char *buf, size_t size, struct nft_rule *t, uint32_t type, uint32_t flags);
struct nlmsghdr *nft_rule_nlmsg_build_hdr(char *buf, uint16_t cmd, uint16_t family, uint16_t type, uint32_t seq);
diff --git a/include/libnftables/table.h b/include/libnftables/table.h
index f367bb8..376749e 100644
--- a/include/libnftables/table.h
+++ b/include/libnftables/table.h
@@ -31,6 +31,7 @@ enum {
NFT_TABLE_O_XML,
};
+int nft_table_xml_parse(struct nft_table *t, char *xml);
int nft_table_snprintf(char *buf, size_t size, struct nft_table *t, uint32_t type, uint32_t flags);
struct nlmsghdr *nft_table_nlmsg_build_hdr(char *buf, uint16_t cmd, uint16_t family, uint16_t type, uint32_t seq);
diff --git a/src/chain.c b/src/chain.c
index 4c111b6..b1126f5 100644
--- a/src/chain.c
+++ b/src/chain.c
@@ -20,6 +20,7 @@
#include <libmnl/libmnl.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nf_tables.h>
+#include <mxml.h>
#include <libnftables/chain.h>
@@ -446,6 +447,187 @@ int nft_chain_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_chain *c)
}
EXPORT_SYMBOL(nft_chain_nlmsg_parse);
+int nft_chain_xml_parse(struct nft_chain *c, char *xml)
+{
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ char *endptr = NULL;
+ unsigned long long int utmp;
+ long int tmp;
+
+ /* Load the tree */
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ /* Get and set <chain name="xxx" ... >*/
+ if (mxmlElementGetAttr(tree, "name") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ strncpy(c->name, mxmlElementGetAttr(tree, "name"),
+ NFT_CHAIN_MAXNAMELEN);
+
+ /* Get and set <chain handle="x" ... >*/
+ if (mxmlElementGetAttr(tree, "handle") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /*
+ * checking here (and followings):
+ * dest type overflow,
+ * strtoul overflow,
+ * bad string
+ */
+ errno = 0;
+ utmp = strtoull(mxmlElementGetAttr(tree, "handle"), &endptr, 10);
+ if (utmp > UINT64_MAX || utmp < 0 || errno != 0
+ || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ c->handle = (uint64_t)utmp;
+
+ /* Get and set <chain bytes="x" ... >*/
+ if (mxmlElementGetAttr(tree, "bytes") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ utmp = strtoull(mxmlElementGetAttr(tree, "bytes"), &endptr, 10);
+ if (utmp > UINT64_MAX || utmp < 0 || errno != 0
+ || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ c->bytes = (uint64_t)utmp;
+
+ /* Get and set <chain packets="x" ... > */
+ if (mxmlElementGetAttr(tree, "packets") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ utmp = strtoull(mxmlElementGetAttr(tree, "packets"), &endptr, 10);
+ if (utmp > UINT64_MAX || utmp < 0 || errno != 0
+ || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ c->packets = (uint64_t)utmp;
+
+
+ /* Ignore <properties> node */
+ node = mxmlFindElement(tree, tree, "properties", NULL, NULL,
+ MXML_DESCEND_FIRST);
+
+ /* Get and set <type> */
+ node = mxmlFindElement(tree, tree, "type", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (c->type)
+ free(c->type);
+
+ c->type = strdup(node->child->value.opaque);
+
+ /* Get and set <table> */
+ node = mxmlFindElement(tree, tree, "table", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ if (c->table)
+ free(c->table);
+
+ c->table = strdup(node->child->value.opaque);
+
+ /* Get and set <prio> */
+ node = mxmlFindElement(tree, tree, "prio", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ tmp = strtol(node->child->value.opaque, &endptr, 10);
+ if (tmp > INT32_MAX || tmp < INT32_MIN || errno != 0
+ || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ memcpy(&c->prio, &tmp, sizeof(c->prio));
+
+ /* Ignore <use> (cannot be set)*/
+ node = mxmlFindElement(tree, tree, "use", NULL, NULL, MXML_DESCEND);
+
+ /* Get and set <hooknum> */
+ node = mxmlFindElement(tree, tree, "hooknum", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ utmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (utmp > UINT32_MAX || utmp < 0 || errno != 0
+ || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ memcpy(&c->hooknum, &utmp, sizeof(c->hooknum));
+
+ /* Get and set <policy> */
+ node = mxmlFindElement(tree, tree, "policy", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ utmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (utmp > UINT32_MAX || utmp < 0 || errno != 0
+ || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ c->policy = (uint32_t)utmp;
+
+ /* Get and set <family> */
+ node = mxmlFindElement(tree, tree, "family", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ utmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (utmp > UINT8_MAX || utmp < 0 || errno != 0
+ || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ c->family = (uint32_t)utmp;
+
+ /* Get and set <flags> */
+ node = mxmlFindElement(tree, tree, "flags", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ utmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (utmp > UINT32_MAX || utmp < 0 || errno != 0
+ || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ c->flags = (uint32_t)utmp;
+
+ mxmlDelete(tree);
+ return 0;
+}
+EXPORT_SYMBOL(nft_chain_xml_parse);
+
static int nft_chain_snprintf_xml(char *buf, size_t size, struct nft_chain *c)
{
return snprintf(buf, size,
diff --git a/src/expr/bitwise.c b/src/expr/bitwise.c
index 4376fa0..ef68042 100644
--- a/src/expr/bitwise.c
+++ b/src/expr/bitwise.c
@@ -22,6 +22,8 @@
#include "data_reg.h"
#include "expr_ops.h"
+#include <mxml.h>
+
struct nft_expr_bitwise {
enum nft_registers sreg;
enum nft_registers dreg;
@@ -195,6 +197,129 @@ nft_rule_expr_bitwise_parse(struct nft_rule_expr *e, struct nlattr *attr)
return ret;
}
+static int nft_rule_expr_bitwise_xml_parse(struct nft_rule_expr *e, char *xml)
+{
+ struct nft_expr_bitwise *bitwise = (struct nft_expr_bitwise *)e->data;
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ mxml_node_t *save = NULL;
+ unsigned long int tmp;
+ union nft_data_reg data_regtmp;
+ char *endptr;
+
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ if (mxmlElementGetAttr(tree, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp("bitwise", mxmlElementGetAttr(tree, "type")) != 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+
+ /* get and set <sreg> */
+ node = mxmlFindElement(tree, tree, "sreg", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /*
+ * Checking here (and followins)
+ * dst type overflow
+ * strtol overflow
+ * bad number string
+ */
+ errno = 0;
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ bitwise->sreg = (uint32_t)tmp;
+
+ /* get and set <dreg> */
+ node = mxmlFindElement(tree, tree, "dreg", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ bitwise->dreg = (uint32_t)tmp;
+
+ /* Get and set <mask> */
+ node = mxmlFindElement(tree, tree, "mask", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* hack for mxmSaveAllocString to print just the current node */
+ save = node->next;
+ node->next = NULL;
+ if (nft_data_reg_xml_parse(&data_regtmp,
+ mxmlSaveAllocString(node, MXML_NO_CALLBACK)) < 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ node->next = save;
+
+ memcpy(&bitwise->mask.val, data_regtmp.val, data_regtmp.len);
+ bitwise->mask.len = data_regtmp.len;
+
+
+ /* Get and set <xor> */
+ node = mxmlFindElement(tree, tree, "xor", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* hack for mxmSaveAllocString to print just the current node */
+ save = node->next;
+ node->next = NULL;
+ if (nft_data_reg_xml_parse(&data_regtmp,
+ mxmlSaveAllocString(node, MXML_NO_CALLBACK)) < 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ memcpy(&bitwise->xor.val, data_regtmp.val, data_regtmp.len);
+ bitwise->xor.len = data_regtmp.len;
+
+ /* get and set <expr_flags> */
+ node = mxmlFindElement(tree, tree, "expr_flags",
+ NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ e->flags = (uint32_t)tmp;
+
+ mxmlDelete(tree);
+ return 0;
+}
+
static int
nft_rule_expr_bitwise_snprintf_xml(char *buf, size_t size,
struct nft_rule_expr *e)
@@ -283,4 +408,5 @@ struct expr_ops expr_ops_bitwise = {
.parse = nft_rule_expr_bitwise_parse,
.build = nft_rule_expr_bitwise_build,
.snprintf = nft_rule_expr_bitwise_snprintf,
+ .xml_parse = nft_rule_expr_bitwise_xml_parse,
};
diff --git a/src/expr/cmp.c b/src/expr/cmp.c
index e1e76a6..c91d90d 100644
--- a/src/expr/cmp.c
+++ b/src/expr/cmp.c
@@ -23,6 +23,8 @@
#include "expr_ops.h"
#include "data_reg.h"
+#include <mxml.h>
+
struct nft_expr_cmp {
union nft_data_reg data;
uint8_t sreg; /* enum nft_registers */
@@ -166,6 +168,123 @@ static char *expr_cmp_str[] = {
[NFT_CMP_GTE] = "gte",
};
+static int nft_rule_expr_cmp_xml_parse(struct nft_rule_expr *e, char *xml)
+{
+ struct nft_expr_cmp *cmp = (struct nft_expr_cmp *)e->data;
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ mxml_node_t *save = NULL;
+ union nft_data_reg data_regtmp;
+ unsigned int tmp;
+ char *endptr;
+
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ if (mxmlElementGetAttr(tree, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ if (strcmp("cmp", mxmlElementGetAttr(tree, "type")) != 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Get and set <sreg> */
+ node = mxmlFindElement(tree, tree, "sreg", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /*
+ * Checking here (and followings)
+ * dst data type overflow
+ * strtol overflow
+ * bad number string
+ */
+
+ errno = 0;
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT8_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ cmp->sreg = (uint8_t)tmp;
+
+ /* Get and set <op> */
+ node = mxmlFindElement(tree, tree, "op", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp(node->child->value.opaque, "eq") == 0) {
+ cmp->op = NFT_CMP_EQ;
+ } else if (strcmp(node->child->value.opaque, "neq") == 0) {
+ cmp->op = NFT_CMP_NEQ;
+ } else if (strcmp(node->child->value.opaque, "lt") == 0) {
+ cmp->op = NFT_CMP_LT;
+ } else if (strcmp(node->child->value.opaque, "lte") == 0) {
+ cmp->op = NFT_CMP_LTE;
+ } else if (strcmp(node->child->value.opaque, "gt") == 0) {
+ cmp->op = NFT_CMP_GT;
+ } else if (strcmp(node->child->value.opaque, "gte") == 0) {
+ cmp->op = NFT_CMP_GTE;
+ } else {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ e->flags |= (1 << NFT_EXPR_CMP_OP);
+
+ /* Get and set <cmpdata> */
+ node = mxmlFindElement(tree, tree, "cmpdata", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* hack for mxmSaveAllocString to print just the current node */
+ save = node->next;
+ node->next = NULL;
+
+ if (nft_data_reg_xml_parse(&data_regtmp,
+ mxmlSaveAllocString(node, MXML_NO_CALLBACK)) < 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ node->next = save;
+
+ memcpy(&cmp->data.val, data_regtmp.val, data_regtmp.len);
+ cmp->data.len = data_regtmp.len;
+
+ /* Get and set <expr_flags> */
+ node = mxmlFindElement(tree, tree, "expr_flags", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ e->flags = (uint32_t)tmp;
+
+ mxmlDelete(tree);
+ return 0;
+}
+
+
static int
nft_rule_expr_cmp_snprintf_xml(char *buf, size_t size, struct nft_rule_expr *e)
{
@@ -232,4 +351,5 @@ struct expr_ops expr_ops_cmp = {
.parse = nft_rule_expr_cmp_parse,
.build = nft_rule_expr_cmp_build,
.snprintf = nft_rule_expr_cmp_snprintf,
+ .xml_parse = nft_rule_expr_cmp_xml_parse,
};
diff --git a/src/expr/counter.c b/src/expr/counter.c
index ec6f637..9b39cc2 100644
--- a/src/expr/counter.c
+++ b/src/expr/counter.c
@@ -21,6 +21,8 @@
#include <libnftables/rule.h>
#include "expr_ops.h"
+#include <mxml.h>
+
struct nft_expr_counter {
uint64_t pkts;
uint64_t bytes;
@@ -125,6 +127,84 @@ nft_rule_expr_counter_parse(struct nft_rule_expr *e, struct nlattr *attr)
return 0;
}
+
+static
+int nft_rule_expr_counter_xml_parse(struct nft_rule_expr *e, char *xml)
+{
+ struct nft_expr_counter *ctr = (struct nft_expr_counter *)e->data;
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ char *endptr;
+ unsigned long long int tmp;
+
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ if (mxmlElementGetAttr(tree, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp("counter", mxmlElementGetAttr(tree, "type")) != 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* get and set <pkts> */
+ node = mxmlFindElement(tree, tree, "pkts", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ errno = 0;
+ tmp = strtoull(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT64_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ ctr->pkts = (uint64_t)tmp;
+
+ /* get and set <bytes> */
+ node = mxmlFindElement(tree, tree, "bytes", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoull(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT64_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ ctr->bytes = (uint64_t)tmp;
+
+ /* get and set <expr_flags> */
+ node = mxmlFindElement(tree, tree, "expr_flags", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoull(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ e->flags = (uint32_t)tmp;
+
+ mxmlDelete(tree);
+ return 0;
+}
+
+
static int
nft_rule_expr_counter_snprintf(char *buf, size_t len, uint32_t type,
uint32_t flags, struct nft_rule_expr *e)
@@ -155,4 +235,5 @@ struct expr_ops expr_ops_counter = {
.parse = nft_rule_expr_counter_parse,
.build = nft_rule_expr_counter_build,
.snprintf = nft_rule_expr_counter_snprintf,
+ .xml_parse = nft_rule_expr_counter_xml_parse,
};
diff --git a/src/expr/data_reg.c b/src/expr/data_reg.c
index d7010ad..3f66452 100644
--- a/src/expr/data_reg.c
+++ b/src/expr/data_reg.c
@@ -12,6 +12,7 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
+#include <limits.h>
#include <arpa/inet.h>
#include <libmnl/libmnl.h>
@@ -23,6 +24,253 @@
#include "data_reg.h"
#include "internal.h"
+#include <mxml.h>
+
+static int nft_data_reg_verdict_xml_parse(union nft_data_reg *reg, char *xml)
+{
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ char *endptr;
+ long int tmp;
+
+ /*
+ * <data_reg type="verdict" >
+ <verdict>int</verdict>
+ * </data_reg>
+ */
+
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ node = mxmlFindElement(tree, tree, "data_reg", NULL, NULL,
+ MXML_DESCEND_FIRST);
+
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Get and validate <data_reg type="verdict" >*/
+ if (mxmlElementGetAttr(tree, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp(mxmlElementGetAttr(tree, "type"), "verdict") != 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Get and set <verdict> */
+ node = mxmlFindElement(tree, tree, "verdict", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ errno = 0;
+ tmp = strtol(node->child->value.opaque, &endptr, 10);
+ if (tmp > INT_MAX || tmp < INT_MIN || errno != 0
+ || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ reg->verdict = tmp;
+
+ mxmlDelete(tree);
+ return 0;
+}
+
+static int nft_data_reg_chain_xml_parse(union nft_data_reg *reg, char *xml)
+{
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+
+ /*
+ * <data_reg type="chain" >
+ <chain>string</chain>
+ * </data_reg>
+ */
+
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ node = mxmlFindElement(tree, tree, "data_reg", NULL, NULL,
+ MXML_DESCEND_FIRST);
+
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Get and validate <data_reg type="chain" >*/
+ if (mxmlElementGetAttr(tree, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp(mxmlElementGetAttr(tree, "type"), "chain") != 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Get and set <chain> */
+ node = mxmlFindElement(tree, tree, "chain", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* no max len value to validate? */
+ if (strlen(node->child->value.opaque) < 1) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (reg->chain)
+ free(reg->chain);
+
+ reg->chain = strdup(node->child->value.opaque);
+
+ mxmlDelete(tree);
+ return 0;
+}
+
+static int nft_data_reg_value_xml_parse(union nft_data_reg *reg, char *xml)
+{
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ int i, len;
+ long int tmp;
+ unsigned long int utmp;
+ char *endptr;
+ char node_name[6];
+
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ node = mxmlFindElement(tree, tree, "data_reg", NULL, NULL,
+ MXML_DESCEND_FIRST);
+
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /*
+ * <data_reg type="value">
+ * <len>4</len>
+ * <data0>0xc09a002a</data0>
+ * <data1>0x2700cac1</data1>
+ * <data2>0x00000000</data2>
+ * <data3>0x08000000</data3>
+ * </data_reg>
+ */
+
+ /* Get and validate <data_reg type="value" ... >*/
+ if (mxmlElementGetAttr(node, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp(mxmlElementGetAttr(node, "type"), "value") != 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Get <len> */
+ node = mxmlFindElement(tree, tree, "len", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /*
+ * Checking here (and followings):
+ * dest type overflow
+ * strtol overflow
+ * bad string
+ */
+
+ errno = 0;
+ tmp = strtol(node->child->value.opaque, &endptr, 10);
+ if (tmp > INT_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ /* maybe also (len < 1 || len > 4) */
+ len = tmp;
+
+ /* Get and set <dataN> */
+ for (i = 0; i < len; i++) {
+ sprintf(node_name, "data%d", i);
+
+ node = mxmlFindElement(tree, tree, node_name, NULL,
+ NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ utmp = strtoul(node->child->value.opaque, &endptr, 16);
+ if (utmp > UINT32_MAX || utmp < 0 || errno != 0
+ || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ reg->val[i] = tmp;
+ }
+
+ reg->len = sizeof(reg->val);
+
+ mxmlDelete(tree);
+ return 0;
+}
+
+int nft_data_reg_xml_parse(union nft_data_reg *reg, char *xml)
+{
+ mxml_node_t *node = NULL;
+ mxml_node_t *tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+
+ if (tree == NULL)
+ return -1;
+
+ node = mxmlFindElement(tree, tree, "data_reg", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Get <data_reg type="xxx" ... >*/
+ if (mxmlElementGetAttr(node, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Select what type of parsing is needed */
+ if (strcmp(mxmlElementGetAttr(node, "type"), "value") == 0) {
+ mxmlDelete(tree);
+ return nft_data_reg_value_xml_parse(reg, xml);
+ } else if (strcmp(mxmlElementGetAttr(node, "type"), "verdict") == 0) {
+ mxmlDelete(tree);
+ return nft_data_reg_verdict_xml_parse(reg, xml);
+ } else if (strcmp(mxmlElementGetAttr(node, "type"), "chain") == 0) {
+ mxmlDelete(tree);
+ return nft_data_reg_chain_xml_parse(reg, xml);
+ }
+
+ mxmlDelete(tree);
+ return -1;
+}
+
+
+
static
int nft_data_reg_value_snprintf_xml(char *buf, size_t size,
union nft_data_reg *reg, uint32_t flags)
@@ -251,3 +499,4 @@ int nft_parse_data(union nft_data_reg *data, struct nlattr *attr, int *type)
return ret;
}
+
diff --git a/src/expr/immediate.c b/src/expr/immediate.c
index d59f109..8fb1df8 100644
--- a/src/expr/immediate.c
+++ b/src/expr/immediate.c
@@ -22,6 +22,8 @@
#include "expr_ops.h"
#include "data_reg.h"
+#include <mxml.h>
+
struct nft_expr_immediate {
union nft_data_reg data;
enum nft_registers dreg;
@@ -195,6 +197,113 @@ nft_rule_expr_immediate_parse(struct nft_rule_expr *e, struct nlattr *attr)
return ret;
}
+static
+int nft_rule_expr_immediate_xml_parse(struct nft_rule_expr *e, char *xml)
+{
+ struct nft_expr_immediate *imm = (struct nft_expr_immediate *)e->data;
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ mxml_node_t *save = NULL;
+ union nft_data_reg data_regtmp;
+ uint32_t tmp;
+ char *endptr;
+
+ /* load the tree */
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ if (mxmlElementGetAttr(tree, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp("immediate", mxmlElementGetAttr(tree, "type")) != 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Get and set <dreg> */
+ node = mxmlFindElement(tree, tree, "dreg", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ errno = 0;
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ imm->dreg = (uint32_t)tmp;
+
+ /* Get and set <immdata> */
+ node = mxmlFindElement(tree, tree, "immdata", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* hack for mxmSaveAllocString to print just the current node */
+ save = node->next;
+ node->next = NULL;
+
+ if (nft_data_reg_xml_parse(&data_regtmp,
+ mxmlSaveAllocString(node, MXML_NO_CALLBACK)) < 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ node->next = save;
+
+ /* data_reg type switch */
+ node = mxmlFindElement(tree, tree, "data_reg", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (mxmlElementGetAttr(node, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp(mxmlElementGetAttr(node, "type"), "value") == 0) {
+ memcpy(&imm->data.val, data_regtmp.val, data_regtmp.len);
+ imm->data.len = data_regtmp.len;
+ } else if (strcmp(mxmlElementGetAttr(node, "type"), "verdict") == 0) {
+ imm->data.verdict = data_regtmp.verdict;
+ } else if (strcmp(mxmlElementGetAttr(node, "type"), "chain") == 0) {
+ if (imm->data.chain)
+ free(imm->data.chain);
+
+ imm->data.chain = strdup(data_regtmp.chain);
+ }
+
+ /* Get and set <expr_flags> */
+ node = mxmlFindElement(tree, tree, "expr_flags", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ e->flags = (uint32_t)tmp;
+
+ mxmlDelete(tree);
+ return 0;
+}
+
static int
nft_rule_expr_immediate_snprintf_xml(char *buf, size_t len,
struct nft_rule_expr *e, uint32_t flags)
@@ -286,4 +395,5 @@ struct expr_ops expr_ops_immediate = {
.parse = nft_rule_expr_immediate_parse,
.build = nft_rule_expr_immediate_build,
.snprintf = nft_rule_expr_immediate_snprintf,
+ .xml_parse = nft_rule_expr_immediate_xml_parse,
};
diff --git a/src/expr/lookup.c b/src/expr/lookup.c
index 2abe82e..2a81465 100644
--- a/src/expr/lookup.c
+++ b/src/expr/lookup.c
@@ -22,6 +22,8 @@
#include "data_reg.h"
#include "expr_ops.h"
+#include <mxml.h>
+
#ifndef IFNAMSIZ
#define IFNAMSIZ 16
#endif
@@ -150,6 +152,93 @@ nft_rule_expr_lookup_parse(struct nft_rule_expr *e, struct nlattr *attr)
return ret;
}
+static int nft_rule_expr_lookup_xml_parse(struct nft_rule_expr *e, char *xml)
+{
+ struct nft_expr_lookup *lookup = (struct nft_expr_lookup *)e->data;
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ unsigned long int tmp;
+ char *endptr;
+
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ if (mxmlElementGetAttr(tree, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp("lookup", mxmlElementGetAttr(tree, "type")) != 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* get and set <set> */
+ node = mxmlFindElement(tree, tree, "set", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ memcpy(lookup->set_name, node->child->value.opaque, IFNAMSIZ);
+ lookup->set_name[IFNAMSIZ-1] = '\0';
+
+ /* get and set <sreg> */
+ node = mxmlFindElement(tree, tree, "sreg", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ errno = 0;
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ lookup->sreg = (uint32_t)tmp;
+
+ /* get and set <dreg> */
+ node = mxmlFindElement(tree, tree, "dreg", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ lookup->dreg = (uint32_t)tmp;
+
+ /* get and set <expr_flags> */
+ node = mxmlFindElement(tree, tree, "expr_flags", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ e->flags = (uint32_t)tmp;
+
+ mxmlDelete(tree);
+ return 0;
+}
+
static int
nft_rule_expr_lookup_snprintf_xml(char *buf, size_t size,
struct nft_rule_expr *e)
@@ -203,4 +292,5 @@ struct expr_ops expr_ops_lookup = {
.parse = nft_rule_expr_lookup_parse,
.build = nft_rule_expr_lookup_build,
.snprintf = nft_rule_expr_lookup_snprintf,
+ .xml_parse = nft_rule_expr_lookup_xml_parse,
};
diff --git a/src/expr/match.c b/src/expr/match.c
index 9a2696e..8b67df7 100644
--- a/src/expr/match.c
+++ b/src/expr/match.c
@@ -25,6 +25,8 @@
#include <libnftables/expr.h>
#include <libnftables/rule.h>
+#include <mxml.h>
+
#include "expr_ops.h"
struct nft_expr_match {
@@ -184,6 +186,135 @@ static int nft_rule_expr_match_parse(struct nft_rule_expr *e, struct nlattr *att
return 0;
}
+static int nft_rule_expr_match_xml_parse(struct nft_rule_expr *e, char *xml)
+{
+ struct nft_expr_match *mt = (struct nft_expr_match *)e->data;
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ uint8_t *info;
+ int i;
+ char node_name[6];
+ unsigned long int tmp;
+ uint32_t len;
+ char *endptr;
+
+ /* load the tree */
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ if (mxmlElementGetAttr(tree, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp("match", mxmlElementGetAttr(tree, "type")) != 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* get and set <name> */
+ node = mxmlFindElement(tree, tree, "name", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ memcpy(mt->name, node->child->value.opaque, XT_EXTENSION_MAXNAMELEN);
+ mt->name[XT_EXTENSION_MAXNAMELEN-1] = '\0';
+
+ /* get and set <rev> */
+ node = mxmlFindElement(tree, tree, "rev", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ errno = 0;
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ mt->rev = (uint32_t)tmp;
+
+ /* Get and set <info> */
+ node = mxmlFindElement(tree, tree, "info", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ node = mxmlFindElement(tree, tree, "len", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ len = (uint32_t)tmp;
+
+ /* parsing the binary data in multiple <dataN>0xff</dataN> */
+ info = (uint8_t *)malloc(len);
+ for (i = 0; i < len; i++) {
+ sprintf(node_name, "data%d", i);
+
+ node = mxmlFindElement(tree, tree, node_name,
+ NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ free(info);
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 16);
+ if (tmp > UINT8_MAX || tmp < 0 || errno != 0
+ || strlen(endptr) > 0) {
+ free(info);
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ info[i] = (uint8_t)tmp;
+ }
+
+ if (mt->data)
+ free(mt->data);
+
+ mt->data = info;
+ free(info);
+ mt->data_len = len;
+
+ /* get and set <expr_flags> */
+ node = mxmlFindElement(tree, tree, "expr_flags",
+ NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ errno = 0;
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ e->flags = (uint32_t)tmp;
+
+ mxmlDelete(tree);
+ return 0;
+}
+
+
static
int nft_rule_expr_match_snprintf_xml(char *buf, size_t len,
struct nft_rule_expr *e)
@@ -240,4 +371,5 @@ struct expr_ops expr_ops_match = {
.parse = nft_rule_expr_match_parse,
.build = nft_rule_expr_match_build,
.snprintf = nft_rule_expr_match_snprintf,
+ .xml_parse = nft_rule_expr_match_xml_parse,
};
diff --git a/src/expr/meta.c b/src/expr/meta.c
index e342a6d..20dcb07 100644
--- a/src/expr/meta.c
+++ b/src/expr/meta.c
@@ -21,6 +21,9 @@
#include <libnftables/rule.h>
#include "expr_ops.h"
+#include <mxml.h>
+
+
struct nft_expr_meta {
uint8_t key; /* enum nft_meta_keys */
uint8_t dreg; /* enum nft_registers */
@@ -125,6 +128,79 @@ nft_rule_expr_meta_parse(struct nft_rule_expr *e, struct nlattr *attr)
return 0;
}
+static int nft_rule_expr_meta_xml_parse(struct nft_rule_expr *e, char *xml)
+{
+ struct nft_expr_meta *meta = (struct nft_expr_meta *)e->data;
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ unsigned long int tmp;
+ char *endptr;
+
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ if (mxmlElementGetAttr(tree, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp("meta", mxmlElementGetAttr(tree, "type")) != 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Get and set <dreg> */
+ node = mxmlFindElement(tree, tree, "dreg", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ errno = 0;
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT8_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ meta->dreg = (uint8_t)tmp;
+
+ /* Get and set <key> */
+ node = mxmlFindElement(tree, tree, "key", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT8_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ meta->key = (uint8_t)tmp;
+
+ /* Get and set <expr_flags> */
+ node = mxmlFindElement(tree, tree, "expr_flags", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ e->flags = (uint32_t)tmp;
+
+ mxmlDelete(tree);
+ return 0;
+}
+
static int
nft_rule_expr_meta_snprintf(char *buf, size_t len, uint32_t type,
uint32_t flags, struct nft_rule_expr *e)
@@ -155,4 +231,5 @@ struct expr_ops expr_ops_meta = {
.parse = nft_rule_expr_meta_parse,
.build = nft_rule_expr_meta_build,
.snprintf = nft_rule_expr_meta_snprintf,
+ .xml_parse = nft_rule_expr_meta_xml_parse,
};
diff --git a/src/expr/nat.c b/src/expr/nat.c
index 382862a..b1b43cc 100644
--- a/src/expr/nat.c
+++ b/src/expr/nat.c
@@ -14,6 +14,7 @@
#include <stdio.h>
#include <stdint.h>
+#include <limits.h>
#include <arpa/inet.h>
#include <libmnl/libmnl.h>
#include <linux/netfilter/nf_tables.h>
@@ -21,6 +22,8 @@
#include <libnftables/rule.h>
#include "expr_ops.h"
+#include <mxml.h>
+
struct nft_expr_nat {
enum nft_registers sreg_addr_min;
enum nft_registers sreg_addr_max;
@@ -201,6 +204,149 @@ nft_rule_expr_nat_build(struct nlmsghdr *nlh, struct nft_rule_expr *e)
htonl(nat->sreg_proto_max));
}
+
+static int nft_rule_expr_nat_xml_parse(struct nft_rule_expr *e, char *xml)
+{
+ struct nft_expr_nat *nat = (struct nft_expr_nat *)e->data;
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ unsigned long int tmp;
+ char *endptr;
+
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ if (mxmlElementGetAttr(tree, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp("nat", mxmlElementGetAttr(tree, "type")) != 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Get and set <type> */
+ node = mxmlFindElement(tree, tree, "type", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp(node->child->value.opaque, "NFT_NAT_SNAT") == 0) {
+ nat->type = NFT_NAT_SNAT;
+ } else if (strcmp(node->child->value.opaque, "NFT_NAT_DNAT") == 0) {
+ nat->type = NFT_NAT_DNAT;
+ } else {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Get and set <family> */
+ node = mxmlFindElement(tree, tree, "family", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp(node->child->value.opaque, "AF_INET") == 0) {
+ nat->family = AF_INET;
+ } else if (strcmp(node->child->value.opaque, "AF_INET6") == 0) {
+ nat->family = AF_INET6;
+ } else {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Get and set <sreg_addr_min_v4> */
+ node = mxmlFindElement(tree, tree, "sreg_addr_min_v4", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ errno = 0;
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) < 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ nat->sreg_addr_min = (uint32_t)tmp;
+
+ /* Get and set <sreg_addr_max_v4> */
+ node = mxmlFindElement(tree, tree, "sreg_addr_max_v4", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) < 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ nat->sreg_addr_max = (uint32_t)tmp;
+
+ /* Get and set <sreg_proto_min> */
+ node = mxmlFindElement(tree, tree, "sreg_proto_min", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) < 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ nat->sreg_proto_min = (uint32_t)tmp;
+
+ /* Get and set <sreg_proto_max> */
+ node = mxmlFindElement(tree, tree, "sreg_proto_max", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) < 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ nat->sreg_proto_max = (uint32_t)tmp;
+
+ /* Get and set <expr_flags> */
+ node = mxmlFindElement(tree, tree, "expr_flags", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) < 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ e->flags = (uint32_t)tmp;
+
+ mxmlDelete(tree);
+ return 0;
+}
+
+
static int
nft_rule_expr_nat_snprintf_xml(char *buf, size_t size,
struct nft_rule_expr *e)
@@ -309,4 +455,5 @@ struct expr_ops expr_ops_nat = {
.parse = nft_rule_expr_nat_parse,
.build = nft_rule_expr_nat_build,
.snprintf = nft_rule_expr_nat_snprintf,
+ .xml_parse = nft_rule_expr_nat_xml_parse,
};
diff --git a/src/expr/payload.c b/src/expr/payload.c
index b72be96..271ad36 100644
--- a/src/expr/payload.c
+++ b/src/expr/payload.c
@@ -13,6 +13,7 @@
#include <stdio.h>
#include <stdint.h>
+#include <limits.h>
#include <arpa/inet.h>
#include <libmnl/libmnl.h>
@@ -24,6 +25,8 @@
#include "expr_ops.h"
+#include <mxml.h>
+
struct nft_expr_payload {
enum nft_registers dreg;
enum nft_payload_bases base;
@@ -164,6 +167,111 @@ nft_rule_expr_payload_parse(struct nft_rule_expr *e, struct nlattr *attr)
return 0;
}
+static int nft_rule_expr_payload_xml_parse(struct nft_rule_expr *e, char *xml)
+{
+ struct nft_expr_payload *payload = (struct nft_expr_payload *)e->data;
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ unsigned long int tmp;
+ char *endptr;
+
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ if (mxmlElementGetAttr(tree, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp("payload", mxmlElementGetAttr(tree, "type")) != 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Get and set <dreg> */
+ node = mxmlFindElement(tree, tree, "dreg", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ errno = 0;
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ payload->dreg = (uint32_t)tmp;
+
+ /* Get and set <base> */
+ node = mxmlFindElement(tree, tree, "base", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ payload->base = (uint32_t)tmp;
+
+ /* Get and set <offset> */
+ node = mxmlFindElement(tree, tree, "offset", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ payload->offset = (unsigned int)tmp;
+
+ /* Get and set <len> */
+ node = mxmlFindElement(tree, tree, "len", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ payload->len = (unsigned int)tmp;
+
+ /* Get and set <expr_flags> */
+ node = mxmlFindElement(tree, tree, "expr_flags",
+ NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ e->flags = (uint32_t)tmp;
+
+ mxmlDelete(tree);
+ return 0;
+}
+
static int
nft_rule_expr_payload_snprintf(char *buf, size_t len, uint32_t type,
uint32_t flags, struct nft_rule_expr *e)
@@ -198,4 +306,5 @@ struct expr_ops expr_ops_payload = {
.parse = nft_rule_expr_payload_parse,
.build = nft_rule_expr_payload_build,
.snprintf = nft_rule_expr_payload_snprintf,
+ .xml_parse = nft_rule_expr_payload_xml_parse,
};
diff --git a/src/expr/target.c b/src/expr/target.c
index 5ceecce..ddc8513 100644
--- a/src/expr/target.c
+++ b/src/expr/target.c
@@ -27,6 +27,8 @@
#include "expr_ops.h"
+#include <mxml.h>
+
struct nft_expr_target {
char name[XT_EXTENSION_MAXNAMELEN];
uint32_t rev;
@@ -184,6 +186,136 @@ static int nft_rule_expr_target_parse(struct nft_rule_expr *e, struct nlattr *at
return 0;
}
+static int nft_rule_expr_target_xml_parse(struct nft_rule_expr *e, char *xml)
+{
+ struct nft_expr_target *tg = (struct nft_expr_target *)e->data;
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ unsigned long int tmp;
+ uint8_t *info;
+ int i;
+ char *endptr;
+ char node_name[6];
+ uint32_t len;
+
+ /* load the tree */
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ if (mxmlElementGetAttr(tree, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (strcmp("target", mxmlElementGetAttr(tree, "type")) != 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* Get and set <name> */
+ node = mxmlFindElement(tree, tree, "name", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ memcpy(tg->name, node->child->value.opaque, XT_EXTENSION_MAXNAMELEN);
+ tg->name[XT_EXTENSION_MAXNAMELEN-1] = '\0';
+
+ /* Get and set <rev> */
+ node = mxmlFindElement(tree, tree, "rev", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ errno = 0;
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tg->rev = (uint32_t)tmp;
+
+ /* Get and set <info> */
+ node = mxmlFindElement(tree, tree, "info", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ node = mxmlFindElement(tree, tree, "len", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ len = (uint32_t)tmp;
+
+ /* parsing the binary data in multiple <dataN>0xff</dataN> */
+ info = (uint8_t *)malloc(len);
+ for (i = 0; i < len; i++) {
+ sprintf(node_name, "data%d", i);
+
+ node = mxmlFindElement(tree, tree, node_name,
+ NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ free(info);
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 16);
+ if (tmp > UINT8_MAX || tmp < 0 || errno != 0
+ || strlen(endptr) > 0) {
+ free(info);
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ info[i] = (uint8_t)tmp;
+ }
+
+ if (tg->data)
+ free(tg->data);
+
+ tg->data = info;
+ free(info);
+ tg->data_len = len;
+
+ /* Get and set <expr_flags> */
+ node = mxmlFindElement(tree, tree, "expr_flags", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ e->flags = (uint32_t)tmp;
+
+
+ mxmlDelete(tree);
+ return 0;
+}
+
static
int nft_rule_exp_target_snprintf_xml(char *buf, size_t len,
struct nft_rule_expr *e)
@@ -240,4 +372,5 @@ struct expr_ops expr_ops_target = {
.parse = nft_rule_expr_target_parse,
.build = nft_rule_expr_target_build,
.snprintf = nft_rule_expr_target_snprintf,
+ .xml_parse = nft_rule_expr_target_xml_parse,
};
diff --git a/src/expr_ops.h b/src/expr_ops.h
index d6e4ec9..ff4c648 100644
--- a/src/expr_ops.h
+++ b/src/expr_ops.h
@@ -17,6 +17,7 @@ struct expr_ops {
int (*parse)(struct nft_rule_expr *e, struct nlattr *attr);
void (*build)(struct nlmsghdr *nlh, struct nft_rule_expr *e);
int (*snprintf)(char *buf, size_t len, uint32_t type, uint32_t flags, struct nft_rule_expr *e);
+ int (*xml_parse)(struct nft_rule_expr *e, char *xml);
};
struct expr_ops *nft_expr_ops_lookup(const char *name);
diff --git a/src/libnftables.map b/src/libnftables.map
index 957e3b6..5913976 100644
--- a/src/libnftables.map
+++ b/src/libnftables.map
@@ -6,6 +6,7 @@ global:
nft_table_attr_get;
nft_table_attr_set_u32;
nft_table_attr_get_u32;
+ nft_table_xml_parse;
nft_table_snprintf;
nft_table_nlmsg_build_hdr;
nft_table_nlmsg_build_payload;
@@ -28,6 +29,7 @@ global:
nft_chain_attr_get_s32;
nft_chain_attr_get_u64;
nft_chain_attr_get_str;
+ nft_chain_xml_parse;
nft_chain_snprintf;
nft_chain_nlmsg_build_hdr;
nft_chain_nlmsg_build_payload;
@@ -51,6 +53,7 @@ global:
nft_rule_attr_get_u32;
nft_rule_attr_get_u64;
nft_rule_attr_get_str;
+ nft_rule_xml_parse;
nft_rule_snprintf;
nft_rule_nlmsg_build_hdr;
nft_rule_nlmsg_build_payload;
diff --git a/src/rule.c b/src/rule.c
index 6178e57..73d6401 100644
--- a/src/rule.c
+++ b/src/rule.c
@@ -27,6 +27,8 @@
#include "linux_list.h"
#include "expr_ops.h"
+#include "mxml.h"
+
struct nft_rule {
struct list_head head;
@@ -437,6 +439,182 @@ int nft_rule_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_rule *r)
}
EXPORT_SYMBOL(nft_rule_nlmsg_parse);
+int nft_rule_xml_parse(struct nft_rule *r, char *xml)
+{
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ mxml_node_t *save = NULL;
+ struct nft_rule_expr *e;
+ struct expr_ops *ops;
+ char *endptr;
+ unsigned long long int tmp;
+
+ /* Load the tree */
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ /* get and set <rule ... family=X ... > */
+ if (mxmlElementGetAttr(tree, "family") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /*
+ * Checking here (and followings):
+ * dest type overflow
+ * strtol overflow
+ * badformed number string
+ */
+ errno = 0;
+ tmp = strtoull(mxmlElementGetAttr(tree, "family"), &endptr, 10);
+ if (tmp > UINT8_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ r->family = (uint8_t)tmp;
+
+ /* get and set <rule ... table=X ...> */
+ if (mxmlElementGetAttr(tree, "table") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (r->table)
+ free(r->table);
+
+ r->table = strdup(mxmlElementGetAttr(tree, "table"));
+
+ /* get and set <rule ... chain=X ...> */
+ if (mxmlElementGetAttr(tree, "chain") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (r->chain)
+ free(r->chain);
+
+ r->chain = strdup(mxmlElementGetAttr(tree, "chain"));
+
+ /* get and set <rule ... handle=X ...> */
+ if (mxmlElementGetAttr(tree, "handle") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ tmp = strtoull(mxmlElementGetAttr(tree, "handle"), &endptr, 10);
+ if (tmp > UINT64_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ r->handle = (uint64_t)tmp;
+
+ /* get and set <rule_flags> */
+ node = mxmlFindElement(tree, tree, "rule_flags", NULL, NULL,
+ MXML_DESCEND_FIRST);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ tmp = strtoull(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ r->rule_flags = (uint32_t)tmp;
+
+ /* get and set <compat_proto> */
+ node = mxmlFindElement(tree, tree, "compat_proto", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ tmp = strtoull(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ r->compat.proto = (uint32_t)tmp;
+
+ /* get and set <compat_flags> */
+ node = mxmlFindElement(tree, tree, "compat_flags", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+ tmp = strtoull(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ r->compat.flags = (uint32_t)tmp;
+
+ /* get and set <flags> */
+ node = mxmlFindElement(tree, tree, "flags", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ r->flags = (uint32_t)tmp;
+
+ /* Iterating over <expr> */
+ for (node = mxmlFindElement(tree, tree, "expr", "type",
+ NULL, MXML_DESCEND);
+ node != NULL;
+ node = mxmlFindElement(node, tree, "expr", "type",
+ NULL, MXML_DESCEND)) {
+
+ if (mxmlElementGetAttr(node, "type") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ ops = nft_expr_ops_lookup(mxmlElementGetAttr(node, "type"));
+ if (ops == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ e = nft_rule_expr_alloc(mxmlElementGetAttr(node, "type"));
+ if (e == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /* This is a hack for mxml to print just the current node */
+ save = node->next;
+ node->next = NULL;
+
+ if (ops->xml_parse(e, mxmlSaveAllocString(node,
+ MXML_NO_CALLBACK)) != 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ nft_rule_add_expr(r, e);
+
+ node->next = save;
+ save = NULL;
+ }
+
+ mxmlDelete(tree);
+ return 0;
+}
+EXPORT_SYMBOL(nft_rule_xml_parse);
+
static int nft_rule_snprintf_xml(char *buf, size_t size, struct nft_rule *r,
uint32_t type, uint32_t flags)
{
diff --git a/src/table.c b/src/table.c
index b47d623..759f9a8 100644
--- a/src/table.c
+++ b/src/table.c
@@ -13,6 +13,7 @@
#include <time.h>
#include <endian.h>
#include <stdint.h>
+#include <limits.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
@@ -21,6 +22,8 @@
#include <linux/netfilter/nfnetlink.h>
#include <linux/netfilter/nf_tables.h>
+#include <mxml.h>
+
#include <libnftables/table.h>
struct nft_table {
@@ -182,6 +185,91 @@ int nft_table_nlmsg_parse(const struct nlmsghdr *nlh, struct nft_table *t)
}
EXPORT_SYMBOL(nft_table_nlmsg_parse);
+int nft_table_xml_parse(struct nft_table *t, char *xml)
+{
+ mxml_node_t *tree = NULL;
+ mxml_node_t *node = NULL;
+ char *endptr;
+ unsigned long int tmp;
+
+ /* Load the tree */
+ tree = mxmlLoadString(NULL, xml, MXML_OPAQUE_CALLBACK);
+ if (tree == NULL)
+ return -1;
+
+ /* Get and set the name of the table */
+ if (mxmlElementGetAttr(tree, "name") == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ if (t->name)
+ free(t->name);
+
+ t->name = strdup(mxmlElementGetAttr(tree, "name"));
+
+ /* Ignore <properties> node */
+ node = mxmlFindElement(tree, tree, "properties", NULL, NULL,
+ MXML_DESCEND_FIRST);
+
+ /* Get the and set <family> node */
+ node = mxmlFindElement(tree, tree, "family", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ /*
+ * checking here (and followings):
+ * dest type overflow,
+ * strtoul overflow,
+ * bad string
+ */
+ errno = 0;
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT8_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ t->family = (uint32_t)tmp;
+
+ /* Get and set <table_flags> */
+ node = mxmlFindElement(tree, tree, "table_flags", NULL, NULL,
+ MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ t->table_flags = (uint32_t)tmp;
+
+ /* Get and st <flags> */
+ node = mxmlFindElement(tree, tree, "flags", NULL, NULL, MXML_DESCEND);
+ if (node == NULL) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ tmp = strtoul(node->child->value.opaque, &endptr, 10);
+ if (tmp > UINT32_MAX || tmp < 0 || errno != 0 || strlen(endptr) > 0) {
+ mxmlDelete(tree);
+ return -1;
+ }
+
+ t->flags = (uint32_t)tmp;
+
+ mxmlDelete(tree);
+ return 0;
+}
+EXPORT_SYMBOL(nft_table_xml_parse);
+
static int nft_table_snprintf_xml(char *buf, size_t size, struct nft_table *t)
{
return snprintf(buf, size,
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [libnftables PATCH 1/5] src: rule: small fix XML output
2013-04-10 16:39 ` [libnftables PATCH 1/5] src: rule: small fix XML output Arturo Borrero
@ 2013-04-18 23:32 ` Pablo Neira Ayuso
0 siblings, 0 replies; 8+ messages in thread
From: Pablo Neira Ayuso @ 2013-04-18 23:32 UTC (permalink / raw)
To: Arturo Borrero; +Cc: netfilter-devel
Hi Arturo,
On Wed, Apr 10, 2013 at 06:39:57PM +0200, Arturo Borrero wrote:
> This patch aplies two fixes:
> * snprintf XML output offset for rule.
> * add XML <flags> node, missing in previous patches.
>
> The <flags> node will be used for parsing a rule in XML.
>
> Signed-off-by: Arturo Borrero González <arturo.borrero.glez@gmail.com>
> ---
> src/rule.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/src/rule.c b/src/rule.c
> index e419b0a..c463c69 100644
> --- a/src/rule.c
> +++ b/src/rule.c
> @@ -451,9 +451,10 @@ static int nft_rule_snprintf_xml(char *buf, size_t size, struct nft_rule *r,
> SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
>
> ret = snprintf(buf+offset, len, "<rule_flags>%u</rule_flags>"
> + "<flags>%u</flags>"
> "<compat_flags>%u</compat_flags>"
> "<compat_proto>%u</compat_proto>",
> - r->rule_flags,
> + r->rule_flags, r->flags,
You should not rely on the r->flags in the XML parser. Same thing for
table, chain and expressions. Those flags are internal to the library
object representation and I would prefer if they still remain like
that.
I have applied this chunk below as bugfix.
> r->compat.flags, r->compat.proto);
> SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
>
> @@ -469,7 +470,7 @@ static int nft_rule_snprintf_xml(char *buf, size_t size, struct nft_rule *r,
> SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
>
> }
> - ret = snprintf(buf+offset-1, len, "\n</rule>\n ");
> + ret = snprintf(buf+offset, len, "\n</rule>\n ");
> SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
>
> return ret;
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [libnftables PATCH 3/5] src: xml printing: delete text format
2013-04-10 16:40 ` [libnftables PATCH 3/5] src: xml printing: delete text format Arturo Borrero
@ 2013-04-19 0:00 ` Pablo Neira Ayuso
0 siblings, 0 replies; 8+ messages in thread
From: Pablo Neira Ayuso @ 2013-04-19 0:00 UTC (permalink / raw)
To: Arturo Borrero; +Cc: netfilter-devel
On Wed, Apr 10, 2013 at 06:40:07PM +0200, Arturo Borrero wrote:
> Delete all \n and \t from XML output.
I have also applied this cleanup. Thanks.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2013-04-19 0:00 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-10 16:39 [libnftables PATCH 0/5] XML works Arturo Borrero
2013-04-10 16:39 ` [libnftables PATCH 1/5] src: rule: small fix XML output Arturo Borrero
2013-04-18 23:32 ` Pablo Neira Ayuso
2013-04-10 16:40 ` [libnftables PATCH 2/5] src: expr: XML printing for binary data in targer and match Arturo Borrero
2013-04-10 16:40 ` [libnftables PATCH 3/5] src: xml printing: delete text format Arturo Borrero
2013-04-19 0:00 ` Pablo Neira Ayuso
2013-04-10 16:40 ` [libnftables PATCH 4/5] src: expr: print flags in XML Arturo Borrero
2013-04-10 16:40 ` [libnftables PATCH 5/5] src: support for XML parsing Arturo Borrero
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.