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