libnftnl  1.0.6
set_elem.c
1 /*
2  * (C) 2012-2013 by Pablo Neira Ayuso <pablo@netfilter.org>
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  * This code has been sponsored by Sophos Astaro <http://www.sophos.com>
10  */
11 #include "internal.h"
12 
13 #include <time.h>
14 #include <endian.h>
15 #include <stdint.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <netinet/in.h>
19 #include <errno.h>
20 #include <ctype.h>
21 
22 #include <libmnl/libmnl.h>
23 #include <linux/netfilter/nfnetlink.h>
24 #include <linux/netfilter/nf_tables.h>
25 
26 #include <libnftnl/set.h>
27 #include <libnftnl/rule.h>
28 #include <libnftnl/expr.h>
29 
30 struct nftnl_set_elem *nftnl_set_elem_alloc(void)
31 {
32  struct nftnl_set_elem *s;
33 
34  s = calloc(1, sizeof(struct nftnl_set_elem));
35  if (s == NULL)
36  return NULL;
37 
38  return s;
39 }
40 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_alloc, nft_set_elem_alloc);
41 
42 void nftnl_set_elem_free(struct nftnl_set_elem *s)
43 {
44  if (s->flags & (1 << NFTNL_SET_ELEM_CHAIN)) {
45  if (s->data.chain) {
46  xfree(s->data.chain);
47  s->data.chain = NULL;
48  }
49  }
50 
51  if (s->flags & (1 << NFTNL_SET_ELEM_EXPR))
52  nftnl_expr_free(s->expr);
53 
54  if (s->flags & (1 << NFTNL_SET_ELEM_USERDATA))
55  xfree(s->user.data);
56 
57  xfree(s);
58 }
59 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_free, nft_set_elem_free);
60 
61 bool nftnl_set_elem_is_set(const struct nftnl_set_elem *s, uint16_t attr)
62 {
63  return s->flags & (1 << attr);
64 }
65 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_is_set, nft_set_elem_attr_is_set);
66 
67 void nftnl_set_elem_unset(struct nftnl_set_elem *s, uint16_t attr)
68 {
69  switch (attr) {
70  case NFTNL_SET_ELEM_CHAIN:
71  if (s->flags & (1 << NFTNL_SET_ELEM_CHAIN)) {
72  if (s->data.chain) {
73  xfree(s->data.chain);
74  s->data.chain = NULL;
75  }
76  }
77  break;
78  case NFTNL_SET_ELEM_FLAGS:
79  case NFTNL_SET_ELEM_KEY: /* NFTA_SET_ELEM_KEY */
80  case NFTNL_SET_ELEM_VERDICT: /* NFTA_SET_ELEM_DATA */
81  case NFTNL_SET_ELEM_DATA: /* NFTA_SET_ELEM_DATA */
82  case NFTNL_SET_ELEM_TIMEOUT: /* NFTA_SET_ELEM_TIMEOUT */
83  case NFTNL_SET_ELEM_EXPIRATION: /* NFTA_SET_ELEM_EXPIRATION */
84  case NFTNL_SET_ELEM_USERDATA: /* NFTA_SET_ELEM_USERDATA */
85  break;
86  case NFTNL_SET_ELEM_EXPR:
87  if (s->flags & (1 << NFTNL_SET_ELEM_EXPR)) {
88  nftnl_expr_free(s->expr);
89  s->expr = NULL;
90  }
91  break;
92  default:
93  return;
94  }
95 
96  s->flags &= ~(1 << attr);
97 }
98 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_unset, nft_set_elem_attr_unset);
99 
100 void nftnl_set_elem_set(struct nftnl_set_elem *s, uint16_t attr,
101  const void *data, uint32_t data_len)
102 {
103  switch(attr) {
104  case NFTNL_SET_ELEM_FLAGS:
105  s->set_elem_flags = *((uint32_t *)data);
106  break;
107  case NFTNL_SET_ELEM_KEY: /* NFTA_SET_ELEM_KEY */
108  memcpy(&s->key.val, data, data_len);
109  s->key.len = data_len;
110  break;
111  case NFTNL_SET_ELEM_VERDICT: /* NFTA_SET_ELEM_DATA */
112  s->data.verdict = *((uint32_t *)data);
113  break;
114  case NFTNL_SET_ELEM_CHAIN: /* NFTA_SET_ELEM_DATA */
115  if (s->data.chain)
116  xfree(s->data.chain);
117 
118  s->data.chain = strdup(data);
119  break;
120  case NFTNL_SET_ELEM_DATA: /* NFTA_SET_ELEM_DATA */
121  memcpy(s->data.val, data, data_len);
122  s->data.len = data_len;
123  break;
124  case NFTNL_SET_ELEM_TIMEOUT: /* NFTA_SET_ELEM_TIMEOUT */
125  s->timeout = *((uint64_t *)data);
126  break;
127  case NFTNL_SET_ELEM_USERDATA: /* NFTA_SET_ELEM_USERDATA */
128  if (s->user.data != NULL)
129  xfree(s->user.data);
130 
131  s->user.data = malloc(data_len);
132  if (!s->user.data)
133  return;
134  memcpy(s->user.data, data, data_len);
135  s->user.len = data_len;
136  break;
137  default:
138  return;
139  }
140  s->flags |= (1 << attr);
141 }
142 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_set, nft_set_elem_attr_set);
143 
144 void nftnl_set_elem_set_u32(struct nftnl_set_elem *s, uint16_t attr, uint32_t val)
145 {
146  nftnl_set_elem_set(s, attr, &val, sizeof(uint32_t));
147 }
148 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_set_u32, nft_set_elem_attr_set_u32);
149 
150 void nftnl_set_elem_set_u64(struct nftnl_set_elem *s, uint16_t attr, uint64_t val)
151 {
152  nftnl_set_elem_set(s, attr, &val, sizeof(uint64_t));
153 }
154 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_set_u64, nft_set_elem_attr_set_u64);
155 
156 void nftnl_set_elem_set_str(struct nftnl_set_elem *s, uint16_t attr, const char *str)
157 {
158  nftnl_set_elem_set(s, attr, str, strlen(str));
159 }
160 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_set_str, nft_set_elem_attr_set_str);
161 
162 const void *nftnl_set_elem_get(struct nftnl_set_elem *s, uint16_t attr, uint32_t *data_len)
163 {
164  if (!(s->flags & (1 << attr)))
165  return NULL;
166 
167  switch(attr) {
168  case NFTNL_SET_ELEM_FLAGS:
169  return &s->set_elem_flags;
170  case NFTNL_SET_ELEM_KEY: /* NFTA_SET_ELEM_KEY */
171  *data_len = s->key.len;
172  return &s->key.val;
173  case NFTNL_SET_ELEM_VERDICT: /* NFTA_SET_ELEM_DATA */
174  return &s->data.verdict;
175  case NFTNL_SET_ELEM_CHAIN: /* NFTA_SET_ELEM_DATA */
176  return s->data.chain;
177  case NFTNL_SET_ELEM_DATA: /* NFTA_SET_ELEM_DATA */
178  *data_len = s->data.len;
179  return &s->data.val;
180  case NFTNL_SET_ELEM_TIMEOUT: /* NFTA_SET_ELEM_TIMEOUT */
181  return &s->timeout;
182  case NFTNL_SET_ELEM_EXPIRATION: /* NFTA_SET_ELEM_EXPIRATION */
183  return &s->expiration;
184  case NFTNL_SET_ELEM_USERDATA:
185  *data_len = s->user.len;
186  return s->user.data;
187  case NFTNL_SET_ELEM_EXPR:
188  return s->expr;
189  }
190  return NULL;
191 }
192 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_get, nft_set_elem_attr_get);
193 
194 const char *nftnl_set_elem_get_str(struct nftnl_set_elem *s, uint16_t attr)
195 {
196  uint32_t size;
197 
198  return nftnl_set_elem_get(s, attr, &size);
199 }
200 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_get_str, nft_set_elem_attr_get_str);
201 
202 uint32_t nftnl_set_elem_get_u32(struct nftnl_set_elem *s, uint16_t attr)
203 {
204  uint32_t size;
205  uint32_t val = *((uint32_t *)nftnl_set_elem_get(s, attr, &size));
206  return val;
207 }
208 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_get_u32, nft_set_elem_attr_get_u32);
209 
210 uint64_t nftnl_set_elem_get_u64(struct nftnl_set_elem *s, uint16_t attr)
211 {
212  uint32_t size;
213  uint64_t val = *((uint64_t *)nftnl_set_elem_get(s, attr, &size));
214  return val;
215 }
216 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_get_u64, nft_set_elem_attr_get_u64);
217 
218 struct nftnl_set_elem *nftnl_set_elem_clone(struct nftnl_set_elem *elem)
219 {
220  struct nftnl_set_elem *newelem;
221 
222  newelem = nftnl_set_elem_alloc();
223  if (newelem == NULL)
224  return NULL;
225 
226  memcpy(newelem, elem, sizeof(*elem));
227 
228  if (elem->flags & (1 << NFTNL_SET_ELEM_CHAIN))
229  newelem->data.chain = strdup(elem->data.chain);
230 
231  return newelem;
232 }
233 
234 void nftnl_set_elem_nlmsg_build_payload(struct nlmsghdr *nlh,
235  struct nftnl_set_elem *e)
236 {
237  if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS))
238  mnl_attr_put_u32(nlh, NFTA_SET_ELEM_FLAGS, htonl(e->set_elem_flags));
239  if (e->flags & (1 << NFTNL_SET_ELEM_TIMEOUT))
240  mnl_attr_put_u64(nlh, NFTA_SET_ELEM_TIMEOUT, htobe64(e->timeout));
241  if (e->flags & (1 << NFTNL_SET_ELEM_KEY)) {
242  struct nlattr *nest1;
243 
244  nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_KEY);
245  mnl_attr_put(nlh, NFTA_DATA_VALUE, e->key.len, e->key.val);
246  mnl_attr_nest_end(nlh, nest1);
247  }
248  if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT)) {
249  struct nlattr *nest1, *nest2;
250 
251  nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
252  nest2 = mnl_attr_nest_start(nlh, NFTA_DATA_VERDICT);
253  mnl_attr_put_u32(nlh, NFTA_VERDICT_CODE, htonl(e->data.verdict));
254  if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
255  mnl_attr_put_strz(nlh, NFTA_VERDICT_CHAIN, e->data.chain);
256 
257  mnl_attr_nest_end(nlh, nest1);
258  mnl_attr_nest_end(nlh, nest2);
259  }
260  if (e->flags & (1 << NFTNL_SET_ELEM_DATA)) {
261  struct nlattr *nest1;
262 
263  nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_DATA);
264  mnl_attr_put(nlh, NFTA_DATA_VALUE, e->data.len, e->data.val);
265  mnl_attr_nest_end(nlh, nest1);
266  }
267  if (e->flags & (1 << NFTNL_SET_ELEM_USERDATA))
268  mnl_attr_put(nlh, NFTA_SET_ELEM_USERDATA, e->user.len, e->user.data);
269 }
270 
271 static void nftnl_set_elem_nlmsg_build_def(struct nlmsghdr *nlh,
272  struct nftnl_set *s)
273 {
274  if (s->flags & (1 << NFTNL_SET_NAME))
275  mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_SET, s->name);
276  if (s->flags & (1 << NFTNL_SET_ID))
277  mnl_attr_put_u32(nlh, NFTA_SET_ELEM_LIST_SET_ID, htonl(s->id));
278  if (s->flags & (1 << NFTNL_SET_TABLE))
279  mnl_attr_put_strz(nlh, NFTA_SET_ELEM_LIST_TABLE, s->table);
280 }
281 
282 static struct nlattr *nftnl_set_elem_build(struct nlmsghdr *nlh,
283  struct nftnl_set_elem *elem, int i)
284 {
285  struct nlattr *nest2;
286 
287  nest2 = mnl_attr_nest_start(nlh, i);
288  nftnl_set_elem_nlmsg_build_payload(nlh, elem);
289  mnl_attr_nest_end(nlh, nest2);
290 
291  return nest2;
292 }
293 
294 void nftnl_set_elems_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set *s)
295 {
296  struct nftnl_set_elem *elem;
297  struct nlattr *nest1;
298  int i = 0;
299 
300  nftnl_set_elem_nlmsg_build_def(nlh, s);
301 
302  nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
303  list_for_each_entry(elem, &s->element_list, head)
304  nftnl_set_elem_build(nlh, elem, ++i);
305 
306  mnl_attr_nest_end(nlh, nest1);
307 }
308 EXPORT_SYMBOL_ALIAS(nftnl_set_elems_nlmsg_build_payload, nft_set_elems_nlmsg_build_payload);
309 
310 static int nftnl_set_elem_parse_attr_cb(const struct nlattr *attr, void *data)
311 {
312  const struct nlattr **tb = data;
313  int type = mnl_attr_get_type(attr);
314 
315  if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
316  return MNL_CB_OK;
317 
318  switch(type) {
319  case NFTA_SET_ELEM_FLAGS:
320  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
321  abi_breakage();
322  break;
323  case NFTA_SET_ELEM_TIMEOUT:
324  case NFTA_SET_ELEM_EXPIRATION:
325  if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
326  abi_breakage();
327  break;
328  case NFTA_SET_ELEM_KEY:
329  case NFTA_SET_ELEM_DATA:
330  case NFTA_SET_ELEM_EXPR:
331  if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
332  abi_breakage();
333  break;
334  case NFTA_SET_ELEM_USERDATA:
335  if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
336  abi_breakage();
337  break;
338  }
339 
340  tb[type] = attr;
341  return MNL_CB_OK;
342 }
343 
344 static int nftnl_set_elems_parse2(struct nftnl_set *s, const struct nlattr *nest)
345 {
346  struct nlattr *tb[NFTA_SET_ELEM_MAX+1] = {};
347  struct nftnl_set_elem *e;
348  int ret = 0, type;
349 
350  e = nftnl_set_elem_alloc();
351  if (e == NULL)
352  return -1;
353 
354  if (mnl_attr_parse_nested(nest, nftnl_set_elem_parse_attr_cb, tb) < 0) {
355  nftnl_set_elem_free(e);
356  return -1;
357  }
358 
359  if (tb[NFTA_SET_ELEM_FLAGS]) {
360  e->set_elem_flags =
361  ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_FLAGS]));
362  e->flags |= (1 << NFTNL_SET_ELEM_FLAGS);
363  }
364  if (tb[NFTA_SET_ELEM_TIMEOUT]) {
365  e->timeout = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_TIMEOUT]));
366  e->flags |= (1 << NFTNL_SET_ELEM_TIMEOUT);
367  }
368  if (tb[NFTA_SET_ELEM_EXPIRATION]) {
369  e->expiration = be64toh(mnl_attr_get_u64(tb[NFTA_SET_ELEM_EXPIRATION]));
370  e->flags |= (1 << NFTNL_SET_ELEM_EXPIRATION);
371  }
372  if (tb[NFTA_SET_ELEM_KEY]) {
373  ret = nftnl_parse_data(&e->key, tb[NFTA_SET_ELEM_KEY], &type);
374  e->flags |= (1 << NFTNL_SET_ELEM_KEY);
375  }
376  if (tb[NFTA_SET_ELEM_DATA]) {
377  ret = nftnl_parse_data(&e->data, tb[NFTA_SET_ELEM_DATA], &type);
378  switch(type) {
379  case DATA_VERDICT:
380  e->flags |= (1 << NFTNL_SET_ELEM_VERDICT);
381  break;
382  case DATA_CHAIN:
383  e->flags |= (1 << NFTNL_SET_ELEM_VERDICT) |
384  (1 << NFTNL_SET_ELEM_CHAIN);
385  break;
386  case DATA_VALUE:
387  e->flags |= (1 << NFTNL_SET_ELEM_DATA);
388  break;
389  }
390  }
391  if (tb[NFTA_SET_ELEM_EXPR]) {
392  e->expr = nftnl_expr_parse(tb[NFTA_SET_ELEM_EXPR]);
393  if (e->expr == NULL)
394  goto err;
395  e->flags |= (1 << NFTNL_SET_ELEM_EXPR);
396  }
397  if (tb[NFTA_SET_ELEM_USERDATA]) {
398  const void *udata =
399  mnl_attr_get_payload(tb[NFTA_SET_ELEM_USERDATA]);
400 
401  if (e->user.data)
402  xfree(e->user.data);
403 
404  e->user.len = mnl_attr_get_payload_len(tb[NFTA_SET_ELEM_USERDATA]);
405  e->user.data = malloc(e->user.len);
406  if (e->user.data == NULL)
407  goto err;
408  memcpy(e->user.data, udata, e->user.len);
409  e->flags |= (1 << NFTNL_RULE_USERDATA);
410  }
411 
412  if (ret < 0) {
413 err:
414  nftnl_set_elem_free(e);
415  return -1;
416  }
417 
418  /* Add this new element to this set */
419  list_add_tail(&e->head, &s->element_list);
420 
421  return ret;
422 }
423 
424 static int
425 nftnl_set_elem_list_parse_attr_cb(const struct nlattr *attr, void *data)
426 {
427  const struct nlattr **tb = data;
428  int type = mnl_attr_get_type(attr);
429 
430  if (mnl_attr_type_valid(attr, NFTA_SET_ELEM_LIST_MAX) < 0)
431  return MNL_CB_OK;
432 
433  switch(type) {
434  case NFTA_SET_ELEM_LIST_TABLE:
435  case NFTA_SET_ELEM_LIST_SET:
436  if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
437  abi_breakage();
438  break;
439  case NFTA_SET_ELEM_LIST_ELEMENTS:
440  if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
441  abi_breakage();
442  break;
443  }
444 
445  tb[type] = attr;
446  return MNL_CB_OK;
447 }
448 
449 static int nftnl_set_elems_parse(struct nftnl_set *s, const struct nlattr *nest)
450 {
451  struct nlattr *attr;
452  int ret = 0;
453 
454  mnl_attr_for_each_nested(attr, nest) {
455  if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
456  return -1;
457 
458  ret = nftnl_set_elems_parse2(s, attr);
459  }
460  return ret;
461 }
462 
463 int nftnl_set_elems_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_set *s)
464 {
465  struct nlattr *tb[NFTA_SET_ELEM_LIST_MAX+1] = {};
466  struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
467  int ret = 0;
468 
469  if (mnl_attr_parse(nlh, sizeof(*nfg),
470  nftnl_set_elem_list_parse_attr_cb, tb) < 0)
471  return -1;
472 
473  if (tb[NFTA_SET_ELEM_LIST_TABLE]) {
474  xfree(s->table);
475  s->table =
476  strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_TABLE]));
477  s->flags |= (1 << NFTNL_SET_TABLE);
478  }
479  if (tb[NFTA_SET_ELEM_LIST_SET]) {
480  xfree(s->name);
481  s->name =
482  strdup(mnl_attr_get_str(tb[NFTA_SET_ELEM_LIST_SET]));
483  s->flags |= (1 << NFTNL_SET_NAME);
484  }
485  if (tb[NFTA_SET_ELEM_LIST_SET_ID]) {
486  s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ELEM_LIST_SET_ID]));
487  s->flags |= (1 << NFTNL_SET_ID);
488  }
489  if (tb[NFTA_SET_ELEM_LIST_ELEMENTS])
490  ret = nftnl_set_elems_parse(s, tb[NFTA_SET_ELEM_LIST_ELEMENTS]);
491 
492  s->family = nfg->nfgen_family;
493  s->flags |= (1 << NFTNL_SET_FAMILY);
494 
495  return ret;
496 }
497 EXPORT_SYMBOL_ALIAS(nftnl_set_elems_nlmsg_parse, nft_set_elems_nlmsg_parse);
498 
499 #ifdef XML_PARSING
500 int nftnl_mxml_set_elem_parse(mxml_node_t *tree, struct nftnl_set_elem *e,
501  struct nftnl_parse_err *err)
502 {
503  int set_elem_data;
504  uint32_t set_elem_flags;
505 
506  if (nftnl_mxml_num_parse(tree, "flags", MXML_DESCEND_FIRST, BASE_DEC,
507  &set_elem_flags, NFTNL_TYPE_U32, NFTNL_XML_MAND,
508  err) == 0)
509  nftnl_set_elem_set_u32(e, NFTNL_SET_ELEM_FLAGS, set_elem_flags);
510 
511  if (nftnl_mxml_data_reg_parse(tree, "key", &e->key,
512  NFTNL_XML_MAND, err) == DATA_VALUE)
513  e->flags |= (1 << NFTNL_SET_ELEM_KEY);
514 
515  /* <set_elem_data> is not mandatory */
516  set_elem_data = nftnl_mxml_data_reg_parse(tree, "data",
517  &e->data, NFTNL_XML_OPT, err);
518  switch (set_elem_data) {
519  case DATA_VALUE:
520  e->flags |= (1 << NFTNL_SET_ELEM_DATA);
521  break;
522  case DATA_VERDICT:
523  e->flags |= (1 << NFTNL_SET_ELEM_VERDICT);
524  if (e->data.chain != NULL)
525  e->flags |= (1 << NFTNL_SET_ELEM_CHAIN);
526 
527  break;
528  }
529 
530  return 0;
531 }
532 #endif
533 
534 static int nftnl_set_elem_xml_parse(struct nftnl_set_elem *e, const void *xml,
535  struct nftnl_parse_err *err,
536  enum nftnl_parse_input input)
537 {
538 #ifdef XML_PARSING
539  mxml_node_t *tree;
540  int ret;
541 
542  tree = nftnl_mxml_build_tree(xml, "set_elem", err, input);
543  if (tree == NULL)
544  return -1;
545 
546  ret = nftnl_mxml_set_elem_parse(tree, e, err);
547  mxmlDelete(tree);
548  return ret;
549 #else
550  errno = EOPNOTSUPP;
551  return -1;
552 #endif
553 }
554 
555 static int nftnl_set_elem_json_parse(struct nftnl_set_elem *e, const void *json,
556  struct nftnl_parse_err *err,
557  enum nftnl_parse_input input)
558 {
559 #ifdef JSON_PARSING
560  json_t *tree;
561  json_error_t error;
562 
563  tree = nftnl_jansson_create_root(json, &error, err, input);
564  if (tree == NULL)
565  return -1;
566 
567  return nftnl_jansson_set_elem_parse(e, tree, err);
568 #else
569  errno = EOPNOTSUPP;
570  return -1;
571 #endif
572 }
573 
574 static int
575 nftnl_set_elem_do_parse(struct nftnl_set_elem *e, enum nftnl_parse_type type,
576  const void *data, struct nftnl_parse_err *err,
577  enum nftnl_parse_input input)
578 {
579  int ret;
580 
581  switch (type) {
582  case NFTNL_PARSE_XML:
583  ret = nftnl_set_elem_xml_parse(e, data, err, input);
584  break;
585  case NFTNL_PARSE_JSON:
586  ret = nftnl_set_elem_json_parse(e, data, err, input);
587  break;
588  default:
589  errno = EOPNOTSUPP;
590  ret = -1;
591  break;
592  }
593 
594  return ret;
595 }
596 int nftnl_set_elem_parse(struct nftnl_set_elem *e, enum nftnl_parse_type type,
597  const char *data, struct nftnl_parse_err *err)
598 {
599  return nftnl_set_elem_do_parse(e, type, data, err, NFTNL_PARSE_BUFFER);
600 }
601 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_parse, nft_set_elem_parse);
602 
603 int nftnl_set_elem_parse_file(struct nftnl_set_elem *e, enum nftnl_parse_type type,
604  FILE *fp, struct nftnl_parse_err *err)
605 {
606  return nftnl_set_elem_do_parse(e, type, fp, err, NFTNL_PARSE_FILE);
607 }
608 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_parse_file, nft_set_elem_parse_file);
609 
610 static int nftnl_set_elem_snprintf_json(char *buf, size_t size,
611  const struct nftnl_set_elem *e,
612  uint32_t flags)
613 {
614  int ret, len = size, offset = 0, type = -1;
615 
616  if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS)) {
617  ret = snprintf(buf, len, "\"flags\":%u,", e->set_elem_flags);
618  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
619  }
620 
621  ret = snprintf(buf + offset, len, "\"key\":{");
622  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
623 
624  ret = nftnl_data_reg_snprintf(buf + offset, len, &e->key,
625  NFTNL_OUTPUT_JSON, flags, DATA_VALUE);
626  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
627 
628  ret = snprintf(buf + offset, len, "}");
629  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
630 
631  if (e->flags & (1 << NFTNL_SET_ELEM_DATA))
632  type = DATA_VALUE;
633  else if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
634  type = DATA_CHAIN;
635  else if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT))
636  type = DATA_VERDICT;
637 
638  if (type != -1) {
639  ret = snprintf(buf + offset, len, ",\"data\":{");
640  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
641 
642  ret = nftnl_data_reg_snprintf(buf + offset, len, &e->data,
643  NFTNL_OUTPUT_JSON, flags, type);
644  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
645 
646  ret = snprintf(buf + offset, len, "}");
647  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
648  }
649 
650  return offset;
651 }
652 
653 static int nftnl_set_elem_snprintf_default(char *buf, size_t size,
654  const struct nftnl_set_elem *e)
655 {
656  int ret, len = size, offset = 0, i;
657 
658  ret = snprintf(buf, len, "element ");
659  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
660 
661  for (i = 0; i < div_round_up(e->key.len, sizeof(uint32_t)); i++) {
662  ret = snprintf(buf+offset, len, "%.8x ", e->key.val[i]);
663  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
664  }
665 
666  ret = snprintf(buf+offset, len, " : ");
667  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
668 
669  for (i = 0; i < div_round_up(e->data.len, sizeof(uint32_t)); i++) {
670  ret = snprintf(buf+offset, len, "%.8x ", e->data.val[i]);
671  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
672  }
673 
674  ret = snprintf(buf+offset, len, "%u [end]", e->set_elem_flags);
675  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
676 
677  if (e->user.len) {
678  ret = snprintf(buf+offset, len, " userdata = {");
679  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
680 
681  for (i = 0; i < e->user.len; i++) {
682  char *c = e->user.data;
683 
684  ret = snprintf(buf+offset, len, "%c",
685  isalnum(c[i]) ? c[i] : 0);
686  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
687  }
688 
689  ret = snprintf(buf+offset, len, " }\n");
690  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
691  }
692 
693  return offset;
694 }
695 
696 static int nftnl_set_elem_snprintf_xml(char *buf, size_t size,
697  const struct nftnl_set_elem *e,
698  uint32_t flags)
699 {
700  int ret, len = size, offset = 0, type = DATA_NONE;
701 
702  ret = snprintf(buf, size, "<set_elem>");
703  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
704 
705  if (e->flags & (1 << NFTNL_SET_ELEM_FLAGS)) {
706  ret = snprintf(buf + offset, size, "<flags>%u</flags>",
707  e->set_elem_flags);
708  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
709  }
710 
711  if (e->flags & (1 << NFTNL_SET_ELEM_KEY)) {
712  ret = snprintf(buf + offset, len, "<key>");
713  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
714 
715  ret = nftnl_data_reg_snprintf(buf + offset, len, &e->key,
716  NFTNL_OUTPUT_XML, flags, DATA_VALUE);
717  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
718 
719  ret = snprintf(buf + offset, len, "</key>");
720  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
721  }
722 
723  if (e->flags & (1 << NFTNL_SET_ELEM_DATA))
724  type = DATA_VALUE;
725  else if (e->flags & (1 << NFTNL_SET_ELEM_CHAIN))
726  type = DATA_CHAIN;
727  else if (e->flags & (1 << NFTNL_SET_ELEM_VERDICT))
728  type = DATA_VERDICT;
729 
730  if (type != DATA_NONE) {
731  ret = snprintf(buf + offset, len, "<data>");
732  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
733 
734  ret = nftnl_data_reg_snprintf(buf + offset, len, &e->data,
735  NFTNL_OUTPUT_XML, flags, type);
736  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
737 
738  ret = snprintf(buf + offset, len, "</data>");
739  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
740  }
741 
742  ret = snprintf(buf + offset, len, "</set_elem>");
743  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
744 
745  return offset;
746 }
747 
748 static int nftnl_set_elem_cmd_snprintf(char *buf, size_t size,
749  const struct nftnl_set_elem *e,
750  uint32_t cmd, uint32_t type,
751  uint32_t flags)
752 {
753  int ret, len = size, offset = 0;
754 
755  ret = nftnl_cmd_header_snprintf(buf + offset, len, cmd, type, flags);
756  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
757 
758  switch(type) {
759  case NFTNL_OUTPUT_DEFAULT:
760  ret = nftnl_set_elem_snprintf_default(buf+offset, len, e);
761  break;
762  case NFTNL_OUTPUT_XML:
763  ret = nftnl_set_elem_snprintf_xml(buf+offset, len, e, flags);
764  break;
765  case NFTNL_OUTPUT_JSON:
766  ret = nftnl_set_elem_snprintf_json(buf+offset, len, e, flags);
767  break;
768  default:
769  return -1;
770  }
771 
772  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
773 
774  ret = nftnl_cmd_footer_snprintf(buf + offset, len, cmd, type, flags);
775  SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
776 
777  return offset;
778 }
779 
780 int nftnl_set_elem_snprintf(char *buf, size_t size,
781  const struct nftnl_set_elem *e,
782  uint32_t type, uint32_t flags)
783 {
784  return nftnl_set_elem_cmd_snprintf(buf, size, e, nftnl_flag2cmd(flags),
785  type, flags);
786 }
787 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_snprintf, nft_set_elem_snprintf);
788 
789 static int nftnl_set_elem_do_snprintf(char *buf, size_t size, const void *e,
790  uint32_t cmd, uint32_t type,
791  uint32_t flags)
792 {
793  return nftnl_set_elem_snprintf(buf, size, e, type, flags);
794 }
795 
796 int nftnl_set_elem_fprintf(FILE *fp, struct nftnl_set_elem *se, uint32_t type,
797  uint32_t flags)
798 {
799  return nftnl_fprintf(fp, se, NFTNL_CMD_UNSPEC, type, flags,
800  nftnl_set_elem_do_snprintf);
801 }
802 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_fprintf, nft_set_elem_fprintf);
803 
804 int nftnl_set_elem_foreach(struct nftnl_set *s,
805  int (*cb)(struct nftnl_set_elem *e, void *data),
806  void *data)
807 {
808  struct nftnl_set_elem *elem;
809  int ret;
810 
811  list_for_each_entry(elem, &s->element_list, head) {
812  ret = cb(elem, data);
813  if (ret < 0)
814  return ret;
815  }
816  return 0;
817 }
818 EXPORT_SYMBOL_ALIAS(nftnl_set_elem_foreach, nft_set_elem_foreach);
819 
821  struct nftnl_set *set;
822  struct list_head *list;
823  struct nftnl_set_elem *cur;
824 };
825 
826 struct nftnl_set_elems_iter *nftnl_set_elems_iter_create(struct nftnl_set *s)
827 {
828  struct nftnl_set_elems_iter *iter;
829 
830  iter = calloc(1, sizeof(struct nftnl_set_elems_iter));
831  if (iter == NULL)
832  return NULL;
833 
834  iter->set = s;
835  iter->list = &s->element_list;
836  if (list_empty(&s->element_list))
837  iter->cur = NULL;
838  else
839  iter->cur = list_entry(s->element_list.next,
840  struct nftnl_set_elem, head);
841 
842  return iter;
843 }
844 EXPORT_SYMBOL_ALIAS(nftnl_set_elems_iter_create, nft_set_elems_iter_create);
845 
846 struct nftnl_set_elem *nftnl_set_elems_iter_cur(struct nftnl_set_elems_iter *iter)
847 {
848  return iter->cur;
849 }
850 EXPORT_SYMBOL_ALIAS(nftnl_set_elems_iter_cur, nft_set_elems_iter_cur);
851 
852 struct nftnl_set_elem *nftnl_set_elems_iter_next(struct nftnl_set_elems_iter *iter)
853 {
854  struct nftnl_set_elem *s = iter->cur;
855 
856  if (s == NULL)
857  return NULL;
858 
859  iter->cur = list_entry(iter->cur->head.next, struct nftnl_set_elem, head);
860  if (&iter->cur->head == iter->list->next)
861  return NULL;
862 
863  return s;
864 }
865 EXPORT_SYMBOL_ALIAS(nftnl_set_elems_iter_next, nft_set_elems_iter_next);
866 
867 void nftnl_set_elems_iter_destroy(struct nftnl_set_elems_iter *iter)
868 {
869  xfree(iter);
870 }
871 EXPORT_SYMBOL_ALIAS(nftnl_set_elems_iter_destroy, nft_set_elems_iter_destroy);
872 
873 static bool nftnl_attr_nest_overflow(struct nlmsghdr *nlh,
874  const struct nlattr *from,
875  const struct nlattr *to)
876 {
877  int len = (void *)to + to->nla_len - (void *)from;
878 
879  /* The attribute length field is 16 bits long, thus the maximum payload
880  * that an attribute can convey is UINT16_MAX. In case of overflow,
881  * discard the last that did not fit into the attribute.
882  */
883  if (len > UINT16_MAX) {
884  nlh->nlmsg_len -= to->nla_len;
885  return true;
886  }
887  return false;
888 }
889 
890 int nftnl_set_elems_nlmsg_build_payload_iter(struct nlmsghdr *nlh,
891  struct nftnl_set_elems_iter *iter)
892 {
893  struct nftnl_set_elem *elem;
894  struct nlattr *nest1, *nest2;
895  int i = 0, ret = 0;
896 
897  nftnl_set_elem_nlmsg_build_def(nlh, iter->set);
898 
899  nest1 = mnl_attr_nest_start(nlh, NFTA_SET_ELEM_LIST_ELEMENTS);
900  elem = nftnl_set_elems_iter_next(iter);
901  while (elem != NULL) {
902  nest2 = nftnl_set_elem_build(nlh, elem, ++i);
903  if (nftnl_attr_nest_overflow(nlh, nest1, nest2)) {
904  /* Go back to previous not to miss this element */
905  iter->cur = list_entry(iter->cur->head.prev,
906  struct nftnl_set_elem, head);
907  ret = 1;
908  break;
909  }
910  elem = nftnl_set_elems_iter_next(iter);
911  }
912  mnl_attr_nest_end(nlh, nest1);
913 
914  return ret;
915 }
916 EXPORT_SYMBOL_ALIAS(nftnl_set_elems_nlmsg_build_payload_iter, nft_set_elems_nlmsg_build_payload_iter);