libnftnl  1.0.6
jansson.c
1 /*
2  * (C) 2013 by Álvaro Neira Ayuso <alvaroneay@gmail.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published
6  * by the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  */
9 
10 #include <internal.h>
11 #include <stdlib.h>
12 #include <limits.h>
13 #include <stdint.h>
14 #include <stdbool.h>
15 #include <arpa/inet.h>
16 #include <errno.h>
17 #include <string.h>
18 #include "expr_ops.h"
19 #include <libnftnl/set.h>
20 
21 #include <libnftnl/expr.h>
22 #include <linux/netfilter/nf_tables.h>
23 
24 #ifdef JSON_PARSING
25 
26 static int nftnl_jansson_load_int_node(json_t *root, const char *node_name,
27  json_int_t *val, struct nftnl_parse_err *err)
28 {
29  json_t *node;
30 
31  node = json_object_get(root, node_name);
32  if (node == NULL) {
33  err->error = NFTNL_PARSE_EMISSINGNODE;
34  err->node_name = node_name;
35  errno = EINVAL;
36  return -1;
37  }
38 
39  if (!json_is_integer(node)) {
40  err->error = NFTNL_PARSE_EBADTYPE;
41  err->node_name = node_name;
42  errno = ERANGE;
43  return -1;
44  }
45  *val = json_integer_value(node);
46 
47  return 0;
48 }
49 
50 const char *nftnl_jansson_parse_str(json_t *root, const char *node_name,
51  struct nftnl_parse_err *err)
52 {
53  json_t *node;
54  const char *val;
55 
56  node = json_object_get(root, node_name);
57  if (node == NULL) {
58  err->error = NFTNL_PARSE_EMISSINGNODE;
59  err->node_name = node_name;
60  errno = EINVAL;
61  return NULL;
62  }
63 
64  val = json_string_value(node);
65  if (val == NULL) {
66  err->error = NFTNL_PARSE_EBADTYPE;
67  err->node_name = node_name;
68  }
69 
70  return val;
71 }
72 
73 int nftnl_jansson_parse_val(json_t *root, const char *node_name, int type,
74  void *out, struct nftnl_parse_err *err)
75 {
76  json_int_t val;
77 
78  if (nftnl_jansson_load_int_node(root, node_name, &val, err) == -1)
79  return -1;
80 
81  if (nftnl_get_value(type, &val, out) == -1)
82  return -1;
83 
84  return 0;
85 }
86 
87 bool nftnl_jansson_node_exist(json_t *root, const char *node_name)
88 {
89  return json_object_get(root, node_name) != NULL;
90 }
91 
92 json_t *nftnl_jansson_create_root(const void *json, json_error_t *error,
93  struct nftnl_parse_err *err, enum nftnl_parse_input input)
94 {
95  json_t *root;
96 
97  switch (input) {
98  case NFTNL_PARSE_BUFFER:
99  root = json_loadb(json, strlen(json), 0, error);
100  break;
101  case NFTNL_PARSE_FILE:
102  root = json_loadf((FILE *)json, 0, error);
103  break;
104  default:
105  goto err;
106  }
107 
108  if (root == NULL) {
109  err->error = NFTNL_PARSE_EBADINPUT;
110  err->line = error->line;
111  err->column = error->column;
112  err->node_name = error->source;
113  goto err;
114  }
115 
116  return root;
117 err:
118  errno = EINVAL;
119  return NULL;
120 }
121 
122 json_t *nftnl_jansson_get_node(json_t *root, const char *node_name,
123  struct nftnl_parse_err *err)
124 {
125  json_t *node;
126 
127  node = json_object_get(root, node_name);
128  if (node == NULL) {
129  err->error = NFTNL_PARSE_EMISSINGNODE;
130  err->node_name = node_name;
131  errno = EINVAL;
132  return NULL;
133  }
134 
135  return node;
136 }
137 
138 void nftnl_jansson_free_root(json_t *root)
139 {
140  json_decref(root);
141 }
142 
143 int nftnl_jansson_parse_family(json_t *root, void *out, struct nftnl_parse_err *err)
144 {
145  const char *str;
146  int family;
147 
148  str = nftnl_jansson_parse_str(root, "family", err);
149  if (str == NULL)
150  return -1;
151 
152  family = nftnl_str2family(str);
153  if (family < 0) {
154  err->node_name = "family";
155  errno = EINVAL;
156  return -1;
157  }
158 
159  memcpy(out, &family, sizeof(family));
160  return 0;
161 }
162 
163 int nftnl_jansson_parse_reg(json_t *root, const char *node_name, int type,
164  void *out, struct nftnl_parse_err *err)
165 {
166  if (nftnl_jansson_parse_val(root, node_name, type, out, err) < 0)
167  return -1;
168 
169  if (*((uint32_t *)out) > NFT_REG_MAX){
170  errno = ERANGE;
171  return -1;
172  }
173 
174  return 0;
175 }
176 
177 int nftnl_jansson_str2num(json_t *root, const char *node_name, int base,
178  void *out, enum nftnl_type type, struct nftnl_parse_err *err)
179 {
180  const char *str;
181 
182  str = nftnl_jansson_parse_str(root, node_name, err);
183  if (str == NULL)
184  return -1;
185 
186  return nftnl_strtoi(str, base, out, type);
187 }
188 
189 struct nftnl_expr *nftnl_jansson_expr_parse(json_t *root,
190  struct nftnl_parse_err *err,
191  struct nftnl_set_list *set_list)
192 {
193  struct nftnl_expr *e;
194  const char *type;
195  uint32_t set_id;
196  int ret;
197 
198  type = nftnl_jansson_parse_str(root, "type", err);
199  if (type == NULL)
200  return NULL;
201 
202  e = nftnl_expr_alloc(type);
203  if (e == NULL) {
204  err->node_name = "type";
205  return NULL;
206  }
207 
208  ret = e->ops->json_parse(e, root, err);
209 
210  if (set_list != NULL &&
211  strcmp(type, "lookup") == 0 &&
212  nftnl_set_lookup_id(e, set_list, &set_id))
213  nftnl_expr_set_u32(e, NFTNL_EXPR_LOOKUP_SET_ID, set_id);
214 
215  return ret < 0 ? NULL : e;
216 }
217 
218 int nftnl_jansson_data_reg_parse(json_t *root, const char *node_name,
219  union nftnl_data_reg *data_reg,
220  struct nftnl_parse_err *err)
221 {
222  json_t *data;
223  int ret;
224 
225  /* It is necessary for the compatibility with cmpdata label. */
226  data = json_object_get(root, node_name);
227  if (data == NULL)
228  data = root;
229 
230  data = json_object_get(data, "reg");
231  if (data == NULL) {
232  err->error = NFTNL_PARSE_EMISSINGNODE;
233  err->node_name = "reg";
234  errno = EINVAL;
235  return -1;
236  }
237 
238  ret = nftnl_data_reg_json_parse(data_reg, data, err);
239  if (ret == DATA_NONE) {
240  errno = EINVAL;
241  return -1;
242  }
243 
244  return ret;
245 }
246 
247 int nftnl_jansson_set_elem_parse(struct nftnl_set_elem *e, json_t *root,
248  struct nftnl_parse_err *err)
249 {
250  int set_elem_data;
251  uint32_t flags;
252 
253  if (nftnl_jansson_parse_val(root, "flags", NFTNL_TYPE_U32, &flags, err) == 0)
254  nftnl_set_elem_set_u32(e, NFTNL_SET_ELEM_FLAGS, flags);
255 
256  if (nftnl_jansson_data_reg_parse(root, "key", &e->key, err) == DATA_VALUE)
257  e->flags |= (1 << NFTNL_SET_ELEM_KEY);
258 
259  if (nftnl_jansson_node_exist(root, "data")) {
260  set_elem_data = nftnl_jansson_data_reg_parse(root, "data",
261  &e->data, err);
262  switch (set_elem_data) {
263  case DATA_VALUE:
264  e->flags |= (1 << NFTNL_SET_ELEM_DATA);
265  break;
266  case DATA_VERDICT:
267  e->flags |= (1 << NFTNL_SET_ELEM_VERDICT);
268  if (e->data.chain != NULL)
269  e->flags |= (1 << NFTNL_SET_ELEM_CHAIN);
270  break;
271  case DATA_NONE:
272  default:
273  return -1;
274  }
275  }
276 
277  return 0;
278 }
279 #endif