libnftnl  1.0.5
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 
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 *nftnl_mxml_build_tree(const void *data, const char *treename,
26  struct nftnl_parse_err *err, enum nftnl_parse_input input)
27 {
28  mxml_node_t *tree;
29 
30  switch (input) {
31  case NFTNL_PARSE_BUFFER:
32  tree = mxmlLoadString(NULL, data, MXML_OPAQUE_CALLBACK);
33  break;
34  case NFTNL_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 = NFTNL_PARSE_EBADINPUT;
43  goto err;
44  }
45 
46  if (tree->value.opaque != NULL &&
47  strcmp(tree->value.opaque, treename) == 0)
48  return tree;
49 
50  err->error = NFTNL_PARSE_EMISSINGNODE;
51  err->node_name = treename;
52 
53  mxmlDelete(tree);
54 err:
55  err->line = 0;
56  err->column = 0;
57  errno = EINVAL;
58  return NULL;
59 }
60 
61 struct nftnl_expr *nftnl_mxml_expr_parse(mxml_node_t *node,
62  struct nftnl_parse_err *err,
63  struct nftnl_set_list *set_list)
64 {
65  mxml_node_t *tree;
66  struct nftnl_expr *e;
67  const char *expr_name;
68  char *xml_text;
69  uint32_t set_id;
70  int ret;
71 
72  expr_name = mxmlElementGetAttr(node, "type");
73  if (expr_name == NULL) {
74  err->node_name = "type";
75  err->error = NFTNL_PARSE_EMISSINGNODE;
76  goto err;
77  }
78 
79  e = nftnl_expr_alloc(expr_name);
80  if (e == NULL)
81  goto err;
82 
83  xml_text = mxmlSaveAllocString(node, MXML_NO_CALLBACK);
84  if (xml_text == NULL)
85  goto err_expr;
86 
87  tree = mxmlLoadString(NULL, xml_text, MXML_OPAQUE_CALLBACK);
88  xfree(xml_text);
89 
90  if (tree == NULL)
91  goto err_expr;
92 
93  ret = e->ops->xml_parse(e, tree, err);
94  mxmlDelete(tree);
95 
96  if (set_list != NULL &&
97  strcmp(expr_name, "lookup") == 0 &&
98  nftnl_set_lookup_id(e, set_list, &set_id))
99  nftnl_expr_set_u32(e, NFTNL_EXPR_LOOKUP_SET_ID, set_id);
100 
101  return ret < 0 ? NULL : e;
102 err_expr:
103  nftnl_expr_free(e);
104 err:
105  mxmlDelete(tree);
106  errno = EINVAL;
107  return NULL;
108 }
109 
110 int nftnl_mxml_reg_parse(mxml_node_t *tree, const char *reg_name, uint32_t *reg,
111  uint32_t mxmlflags, uint32_t flags,
112  struct nftnl_parse_err *err)
113 {
114  mxml_node_t *node;
115 
116  node = mxmlFindElement(tree, tree, reg_name, NULL, NULL, mxmlflags);
117  if (node == NULL) {
118  if (!(flags & NFTNL_XML_OPT)) {
119  err->error = NFTNL_PARSE_EMISSINGNODE;
120  errno = EINVAL;
121  goto err;
122  }
123  return -1;
124  }
125 
126  if (nftnl_strtoi(node->child->value.opaque, BASE_DEC, reg,
127  NFTNL_TYPE_U32) != 0) {
128  err->error = NFTNL_PARSE_EBADTYPE;
129  goto err;
130  }
131 
132  if (*reg > NFT_REG_MAX) {
133  errno = ERANGE;
134  goto err;
135  }
136 
137  return 0;
138 err:
139  err->node_name = reg_name;
140  return -1;
141 }
142 
143 int nftnl_mxml_data_reg_parse(mxml_node_t *tree, const char *node_name,
144  union nftnl_data_reg *data_reg, uint16_t flags,
145  struct nftnl_parse_err *err)
146 {
147  mxml_node_t *node;
148 
149  node = mxmlFindElement(tree, tree, node_name, NULL, NULL,
150  MXML_DESCEND_FIRST);
151 
152  /* It is necessary for the compatibility with cmpdata label. */
153  if (node == NULL || node->child == NULL)
154  node = tree;
155 
156  return nftnl_data_reg_xml_parse(data_reg, node, err);
157 }
158 
159 int
160 nftnl_mxml_num_parse(mxml_node_t *tree, const char *node_name,
161  uint32_t mxml_flags, int base, void *number,
162  enum nftnl_type type, uint16_t flags,
163  struct nftnl_parse_err *err)
164 {
165  mxml_node_t *node = NULL;
166  int ret;
167 
168  node = mxmlFindElement(tree, tree, node_name, NULL, NULL, mxml_flags);
169  if (node == NULL || node->child == NULL) {
170  if (!(flags & NFTNL_XML_OPT)) {
171  errno = EINVAL;
172  err->node_name = node_name;
173  err->error = NFTNL_PARSE_EMISSINGNODE;
174  }
175  return -1;
176  }
177 
178  ret = nftnl_strtoi(node->child->value.opaque, base, number, type);
179 
180  if (ret != 0) {
181  err->error = NFTNL_PARSE_EBADTYPE;
182  err->node_name = node_name;
183  }
184  return ret;
185 }
186 
187 const char *nftnl_mxml_str_parse(mxml_node_t *tree, const char *node_name,
188  uint32_t mxml_flags, uint16_t flags,
189  struct nftnl_parse_err *err)
190 {
191  mxml_node_t *node;
192  const char *ret;
193 
194  node = mxmlFindElement(tree, tree, node_name, NULL, NULL, mxml_flags);
195  if (node == NULL || node->child == NULL) {
196  if (!(flags & NFTNL_XML_OPT)) {
197  errno = EINVAL;
198  err->node_name = node_name;
199  err->error = NFTNL_PARSE_EMISSINGNODE;
200  }
201  return NULL;
202  }
203 
204  ret = node->child->value.opaque;
205  if (ret == NULL) {
206  err->node_name = node_name;
207  err->error = NFTNL_PARSE_EBADTYPE;
208  }
209  return ret;
210 }
211 
212 int nftnl_mxml_family_parse(mxml_node_t *tree, const char *node_name,
213  uint32_t mxml_flags, uint16_t flags,
214  struct nftnl_parse_err *err)
215 {
216  const char *family_str;
217  int family;
218 
219  family_str = nftnl_mxml_str_parse(tree, node_name, mxml_flags,
220  flags, err);
221  if (family_str == NULL)
222  return -1;
223 
224  family = nftnl_str2family(family_str);
225  if (family < 0) {
226  err->node_name = node_name;
227  errno = EAFNOSUPPORT;
228  }
229 
230  return family;
231 }
232 #endif