libnftnl  1.0.2
mxml.c
1 /*
2  * (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
3  * (C) 2013 by Arturo Borrero Gonzalez <arturo.borrero.glez@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published
7  * by the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This code has been sponsored by Sophos Astaro <http://www.sophos.com>
11  */
12 #include "internal.h"
13 #include "expr_ops.h"
14 #include <stdint.h>
15 #include <limits.h>
16 
17 #include <linux/netfilter/nf_tables.h>
18 #include <libnftnl/table.h>
19 #include <libnftnl/chain.h>
20 #include <libnftnl/rule.h>
21 #include <libnftnl/expr.h>
22 #include <libnftnl/set.h>
23 
24 #ifdef XML_PARSING
25 mxml_node_t *nft_mxml_build_tree(const void *data, const char *treename,
26  struct nft_parse_err *err, enum nft_parse_input input)
27 {
28  mxml_node_t *tree;
29 
30  switch (input) {
31  case NFT_PARSE_BUFFER:
32  tree = mxmlLoadString(NULL, data, MXML_OPAQUE_CALLBACK);
33  break;
34  case NFT_PARSE_FILE:
35  tree = mxmlLoadFile(NULL, (FILE *)data, MXML_OPAQUE_CALLBACK);
36  break;
37  default:
38  goto err;
39  }
40 
41  if (tree == NULL) {
42  err->error = NFT_PARSE_EBADINPUT;
43  goto err;
44  }
45 
46  if (strcmp(tree->value.opaque, treename) == 0)
47  return tree;
48 
49  err->error = NFT_PARSE_EMISSINGNODE;
50  err->node_name = treename;
51 
52  mxmlDelete(tree);
53 err:
54  err->line = 0;
55  err->column = 0;
56  errno = EINVAL;
57  return NULL;
58 }
59 
60 struct nft_rule_expr *nft_mxml_expr_parse(mxml_node_t *node,
61  struct nft_parse_err *err)
62 {
63  mxml_node_t *tree;
64  struct nft_rule_expr *e;
65  const char *expr_name;
66  char *xml_text;
67  int ret;
68 
69  expr_name = mxmlElementGetAttr(node, "type");
70  if (expr_name == NULL) {
71  err->node_name = "type";
72  err->error = NFT_PARSE_EMISSINGNODE;
73  goto err;
74  }
75 
76  e = nft_rule_expr_alloc(expr_name);
77  if (e == NULL)
78  goto err;
79 
80  xml_text = mxmlSaveAllocString(node, MXML_NO_CALLBACK);
81  if (xml_text == NULL)
82  goto err_expr;
83 
84  tree = mxmlLoadString(NULL, xml_text, MXML_OPAQUE_CALLBACK);
85  xfree(xml_text);
86 
87  if (tree == NULL)
88  goto err_expr;
89 
90  ret = e->ops->xml_parse(e, tree, err);
91  mxmlDelete(tree);
92 
93  return ret < 0 ? NULL : e;
94 err_expr:
95  nft_rule_expr_free(e);
96 err:
97  mxmlDelete(tree);
98  errno = EINVAL;
99  return NULL;
100 }
101 
102 int nft_mxml_reg_parse(mxml_node_t *tree, const char *reg_name, uint32_t *reg,
103  uint32_t mxmlflags, uint32_t flags,
104  struct nft_parse_err *err)
105 {
106  mxml_node_t *node;
107 
108  node = mxmlFindElement(tree, tree, reg_name, NULL, NULL, mxmlflags);
109  if (node == NULL) {
110  if (!(flags & NFT_XML_OPT)) {
111  err->error = NFT_PARSE_EMISSINGNODE;
112  errno = EINVAL;
113  goto err;
114  }
115  return -1;
116  }
117 
118  if (nft_strtoi(node->child->value.opaque, BASE_DEC, reg,
119  NFT_TYPE_U32) != 0) {
120  err->error = NFT_PARSE_EBADTYPE;
121  goto err;
122  }
123 
124  if (*reg > NFT_REG_MAX) {
125  errno = ERANGE;
126  goto err;
127  }
128 
129  return 0;
130 err:
131  err->node_name = reg_name;
132  return -1;
133 }
134 
135 int nft_mxml_data_reg_parse(mxml_node_t *tree, const char *node_name,
136  union nft_data_reg *data_reg, uint16_t flags,
137  struct nft_parse_err *err)
138 {
139  mxml_node_t *node;
140 
141  node = mxmlFindElement(tree, tree, node_name, NULL, NULL,
142  MXML_DESCEND_FIRST);
143 
144  /* It is necessary for the compatibility with cmpdata label. */
145  if (node == NULL || node->child == NULL)
146  node = tree;
147 
148  return nft_data_reg_xml_parse(data_reg, node, err);
149 }
150 
151 int
152 nft_mxml_num_parse(mxml_node_t *tree, const char *node_name,
153  uint32_t mxml_flags, int base, void *number,
154  enum nft_type type, uint16_t flags,
155  struct nft_parse_err *err)
156 {
157  mxml_node_t *node = NULL;
158  int ret;
159 
160  node = mxmlFindElement(tree, tree, node_name, NULL, NULL, mxml_flags);
161  if (node == NULL || node->child == NULL) {
162  if (!(flags & NFT_XML_OPT)) {
163  errno = EINVAL;
164  err->node_name = node_name;
165  err->error = NFT_PARSE_EMISSINGNODE;
166  }
167  return -1;
168  }
169 
170  ret = nft_strtoi(node->child->value.opaque, base, number, type);
171 
172  if (ret != 0) {
173  err->error = NFT_PARSE_EBADTYPE;
174  err->node_name = node_name;
175  }
176  return ret;
177 }
178 
179 const char *nft_mxml_str_parse(mxml_node_t *tree, const char *node_name,
180  uint32_t mxml_flags, uint16_t flags,
181  struct nft_parse_err *err)
182 {
183  mxml_node_t *node;
184  const char *ret;
185 
186  node = mxmlFindElement(tree, tree, node_name, NULL, NULL, mxml_flags);
187  if (node == NULL || node->child == NULL) {
188  if (!(flags & NFT_XML_OPT)) {
189  errno = EINVAL;
190  err->node_name = node_name;
191  err->error = NFT_PARSE_EMISSINGNODE;
192  }
193  return NULL;
194  }
195 
196  ret = node->child->value.opaque;
197  if (ret == NULL) {
198  err->node_name = node_name;
199  err->error = NFT_PARSE_EBADTYPE;
200  }
201  return ret;
202 }
203 
204 int nft_mxml_family_parse(mxml_node_t *tree, const char *node_name,
205  uint32_t mxml_flags, uint16_t flags,
206  struct nft_parse_err *err)
207 {
208  const char *family_str;
209  int family;
210 
211  family_str = nft_mxml_str_parse(tree, node_name, mxml_flags,
212  flags, err);
213  if (family_str == NULL)
214  return -1;
215 
216  family = nft_str2family(family_str);
217  if (family < 0) {
218  err->node_name = node_name;
219  errno = EAFNOSUPPORT;
220  }
221 
222  return family;
223 }
224 #endif