libnftnl  1.1.8
set.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 <inttypes.h>
19 #include <netinet/in.h>
20 #include <limits.h>
21 #include <errno.h>
22 
23 #include <libmnl/libmnl.h>
24 #include <linux/netfilter/nfnetlink.h>
25 #include <linux/netfilter/nf_tables.h>
26 
27 #include <libnftnl/set.h>
28 #include <libnftnl/expr.h>
29 
30 EXPORT_SYMBOL(nftnl_set_alloc);
31 struct nftnl_set *nftnl_set_alloc(void)
32 {
33  struct nftnl_set *s;
34 
35  s = calloc(1, sizeof(struct nftnl_set));
36  if (s == NULL)
37  return NULL;
38 
39  INIT_LIST_HEAD(&s->element_list);
40  return s;
41 }
42 
43 EXPORT_SYMBOL(nftnl_set_free);
44 void nftnl_set_free(const struct nftnl_set *s)
45 {
46  struct nftnl_set_elem *elem, *tmp;
47 
48  if (s->flags & (1 << NFTNL_SET_TABLE))
49  xfree(s->table);
50  if (s->flags & (1 << NFTNL_SET_NAME))
51  xfree(s->name);
52  if (s->flags & (1 << NFTNL_SET_USERDATA))
53  xfree(s->user.data);
54  if (s->flags & (1 << NFTNL_SET_EXPR))
55  nftnl_expr_free(s->expr);
56 
57  list_for_each_entry_safe(elem, tmp, &s->element_list, head) {
58  list_del(&elem->head);
59  nftnl_set_elem_free(elem);
60  }
61  xfree(s);
62 }
63 
64 EXPORT_SYMBOL(nftnl_set_is_set);
65 bool nftnl_set_is_set(const struct nftnl_set *s, uint16_t attr)
66 {
67  return s->flags & (1 << attr);
68 }
69 
70 EXPORT_SYMBOL(nftnl_set_unset);
71 void nftnl_set_unset(struct nftnl_set *s, uint16_t attr)
72 {
73  if (!(s->flags & (1 << attr)))
74  return;
75 
76  switch (attr) {
77  case NFTNL_SET_TABLE:
78  xfree(s->table);
79  break;
80  case NFTNL_SET_NAME:
81  xfree(s->name);
82  break;
83  case NFTNL_SET_HANDLE:
84  case NFTNL_SET_FLAGS:
85  case NFTNL_SET_KEY_TYPE:
86  case NFTNL_SET_KEY_LEN:
87  case NFTNL_SET_DATA_TYPE:
88  case NFTNL_SET_DATA_LEN:
89  case NFTNL_SET_OBJ_TYPE:
90  case NFTNL_SET_FAMILY:
91  case NFTNL_SET_ID:
92  case NFTNL_SET_POLICY:
93  case NFTNL_SET_DESC_SIZE:
94  case NFTNL_SET_DESC_CONCAT:
95  case NFTNL_SET_TIMEOUT:
96  case NFTNL_SET_GC_INTERVAL:
97  break;
98  case NFTNL_SET_USERDATA:
99  xfree(s->user.data);
100  break;
101  case NFTNL_SET_EXPR:
102  nftnl_expr_free(s->expr);
103  break;
104  default:
105  return;
106  }
107 
108  s->flags &= ~(1 << attr);
109 }
110 
111 static uint32_t nftnl_set_validate[NFTNL_SET_MAX + 1] = {
112  [NFTNL_SET_HANDLE] = sizeof(uint64_t),
113  [NFTNL_SET_FLAGS] = sizeof(uint32_t),
114  [NFTNL_SET_KEY_TYPE] = sizeof(uint32_t),
115  [NFTNL_SET_KEY_LEN] = sizeof(uint32_t),
116  [NFTNL_SET_DATA_TYPE] = sizeof(uint32_t),
117  [NFTNL_SET_DATA_LEN] = sizeof(uint32_t),
118  [NFTNL_SET_OBJ_TYPE] = sizeof(uint32_t),
119  [NFTNL_SET_FAMILY] = sizeof(uint32_t),
120  [NFTNL_SET_POLICY] = sizeof(uint32_t),
121  [NFTNL_SET_DESC_SIZE] = sizeof(uint32_t),
122  [NFTNL_SET_TIMEOUT] = sizeof(uint64_t),
123  [NFTNL_SET_GC_INTERVAL] = sizeof(uint32_t),
124 };
125 
126 EXPORT_SYMBOL(nftnl_set_set_data);
127 int nftnl_set_set_data(struct nftnl_set *s, uint16_t attr, const void *data,
128  uint32_t data_len)
129 {
130  nftnl_assert_attr_exists(attr, NFTNL_SET_MAX);
131  nftnl_assert_validate(data, nftnl_set_validate, attr, data_len);
132 
133  switch(attr) {
134  case NFTNL_SET_TABLE:
135  if (s->flags & (1 << NFTNL_SET_TABLE))
136  xfree(s->table);
137 
138  s->table = strdup(data);
139  if (!s->table)
140  return -1;
141  break;
142  case NFTNL_SET_NAME:
143  if (s->flags & (1 << NFTNL_SET_NAME))
144  xfree(s->name);
145 
146  s->name = strdup(data);
147  if (!s->name)
148  return -1;
149  break;
150  case NFTNL_SET_HANDLE:
151  memcpy(&s->handle, data, sizeof(s->handle));
152  break;
153  case NFTNL_SET_FLAGS:
154  memcpy(&s->set_flags, data, sizeof(s->set_flags));
155  break;
156  case NFTNL_SET_KEY_TYPE:
157  memcpy(&s->key_type, data, sizeof(s->key_type));
158  break;
159  case NFTNL_SET_KEY_LEN:
160  memcpy(&s->key_len, data, sizeof(s->key_len));
161  break;
162  case NFTNL_SET_DATA_TYPE:
163  memcpy(&s->data_type, data, sizeof(s->data_type));
164  break;
165  case NFTNL_SET_DATA_LEN:
166  memcpy(&s->data_len, data, sizeof(s->data_len));
167  break;
168  case NFTNL_SET_OBJ_TYPE:
169  memcpy(&s->obj_type, data, sizeof(s->obj_type));
170  break;
171  case NFTNL_SET_FAMILY:
172  memcpy(&s->family, data, sizeof(s->family));
173  break;
174  case NFTNL_SET_ID:
175  memcpy(&s->id, data, sizeof(s->id));
176  break;
177  case NFTNL_SET_POLICY:
178  memcpy(&s->policy, data, sizeof(s->policy));
179  break;
180  case NFTNL_SET_DESC_SIZE:
181  memcpy(&s->desc.size, data, sizeof(s->desc.size));
182  break;
183  case NFTNL_SET_DESC_CONCAT:
184  memcpy(&s->desc.field_len, data, data_len);
185  while (s->desc.field_len[++s->desc.field_count]);
186  break;
187  case NFTNL_SET_TIMEOUT:
188  memcpy(&s->timeout, data, sizeof(s->timeout));
189  break;
190  case NFTNL_SET_GC_INTERVAL:
191  memcpy(&s->gc_interval, data, sizeof(s->gc_interval));
192  break;
193  case NFTNL_SET_USERDATA:
194  if (s->flags & (1 << NFTNL_SET_USERDATA))
195  xfree(s->user.data);
196 
197  s->user.data = malloc(data_len);
198  if (!s->user.data)
199  return -1;
200  memcpy(s->user.data, data, data_len);
201  s->user.len = data_len;
202  break;
203  case NFTNL_SET_EXPR:
204  if (s->flags & (1 << NFTNL_SET_EXPR))
205  nftnl_expr_free(s->expr);
206 
207  s->expr = (void *)data;
208  break;
209  }
210  s->flags |= (1 << attr);
211  return 0;
212 }
213 
214 int nftnl_set_set(struct nftnl_set *s, uint16_t attr, const void *data) __visible;
215 int nftnl_set_set(struct nftnl_set *s, uint16_t attr, const void *data)
216 {
217  return nftnl_set_set_data(s, attr, data, nftnl_set_validate[attr]);
218 }
219 
220 EXPORT_SYMBOL(nftnl_set_set_u32);
221 void nftnl_set_set_u32(struct nftnl_set *s, uint16_t attr, uint32_t val)
222 {
223  nftnl_set_set_data(s, attr, &val, sizeof(uint32_t));
224 }
225 
226 EXPORT_SYMBOL(nftnl_set_set_u64);
227 void nftnl_set_set_u64(struct nftnl_set *s, uint16_t attr, uint64_t val)
228 {
229  nftnl_set_set_data(s, attr, &val, sizeof(uint64_t));
230 }
231 
232 EXPORT_SYMBOL(nftnl_set_set_str);
233 int nftnl_set_set_str(struct nftnl_set *s, uint16_t attr, const char *str)
234 {
235  return nftnl_set_set_data(s, attr, str, strlen(str) + 1);
236 }
237 
238 EXPORT_SYMBOL(nftnl_set_get_data);
239 const void *nftnl_set_get_data(const struct nftnl_set *s, uint16_t attr,
240  uint32_t *data_len)
241 {
242  if (!(s->flags & (1 << attr)))
243  return NULL;
244 
245  switch(attr) {
246  case NFTNL_SET_TABLE:
247  *data_len = strlen(s->table) + 1;
248  return s->table;
249  case NFTNL_SET_NAME:
250  *data_len = strlen(s->name) + 1;
251  return s->name;
252  case NFTNL_SET_HANDLE:
253  *data_len = sizeof(uint64_t);
254  return &s->handle;
255  case NFTNL_SET_FLAGS:
256  *data_len = sizeof(uint32_t);
257  return &s->set_flags;
258  case NFTNL_SET_KEY_TYPE:
259  *data_len = sizeof(uint32_t);
260  return &s->key_type;
261  case NFTNL_SET_KEY_LEN:
262  *data_len = sizeof(uint32_t);
263  return &s->key_len;
264  case NFTNL_SET_DATA_TYPE:
265  *data_len = sizeof(uint32_t);
266  return &s->data_type;
267  case NFTNL_SET_DATA_LEN:
268  *data_len = sizeof(uint32_t);
269  return &s->data_len;
270  case NFTNL_SET_OBJ_TYPE:
271  *data_len = sizeof(uint32_t);
272  return &s->obj_type;
273  case NFTNL_SET_FAMILY:
274  *data_len = sizeof(uint32_t);
275  return &s->family;
276  case NFTNL_SET_ID:
277  *data_len = sizeof(uint32_t);
278  return &s->id;
279  case NFTNL_SET_POLICY:
280  *data_len = sizeof(uint32_t);
281  return &s->policy;
282  case NFTNL_SET_DESC_SIZE:
283  *data_len = sizeof(uint32_t);
284  return &s->desc.size;
285  case NFTNL_SET_DESC_CONCAT:
286  *data_len = s->desc.field_count;
287  return s->desc.field_len;
288  case NFTNL_SET_TIMEOUT:
289  *data_len = sizeof(uint64_t);
290  return &s->timeout;
291  case NFTNL_SET_GC_INTERVAL:
292  *data_len = sizeof(uint32_t);
293  return &s->gc_interval;
294  case NFTNL_SET_USERDATA:
295  *data_len = s->user.len;
296  return s->user.data;
297  case NFTNL_SET_EXPR:
298  return s->expr;
299  }
300  return NULL;
301 }
302 
303 EXPORT_SYMBOL(nftnl_set_get);
304 const void *nftnl_set_get(const struct nftnl_set *s, uint16_t attr)
305 {
306  uint32_t data_len;
307  return nftnl_set_get_data(s, attr, &data_len);
308 }
309 
310 EXPORT_SYMBOL(nftnl_set_get_str);
311 const char *nftnl_set_get_str(const struct nftnl_set *s, uint16_t attr)
312 {
313  return nftnl_set_get(s, attr);
314 }
315 
316 EXPORT_SYMBOL(nftnl_set_get_u32);
317 uint32_t nftnl_set_get_u32(const struct nftnl_set *s, uint16_t attr)
318 {
319  uint32_t data_len;
320  const uint32_t *val = nftnl_set_get_data(s, attr, &data_len);
321 
322  nftnl_assert(val, attr, data_len == sizeof(uint32_t));
323 
324  return val ? *val : 0;
325 }
326 
327 EXPORT_SYMBOL(nftnl_set_get_u64);
328 uint64_t nftnl_set_get_u64(const struct nftnl_set *s, uint16_t attr)
329 {
330  uint32_t data_len;
331  const uint64_t *val = nftnl_set_get_data(s, attr, &data_len);
332 
333  nftnl_assert(val, attr, data_len == sizeof(uint64_t));
334 
335  return val ? *val : 0;
336 }
337 
338 struct nftnl_set *nftnl_set_clone(const struct nftnl_set *set)
339 {
340  struct nftnl_set *newset;
341  struct nftnl_set_elem *elem, *newelem;
342 
343  newset = nftnl_set_alloc();
344  if (newset == NULL)
345  return NULL;
346 
347  memcpy(newset, set, sizeof(*set));
348 
349  if (set->flags & (1 << NFTNL_SET_TABLE)) {
350  newset->table = strdup(set->table);
351  if (!newset->table)
352  goto err;
353  }
354  if (set->flags & (1 << NFTNL_SET_NAME)) {
355  newset->name = strdup(set->name);
356  if (!newset->name)
357  goto err;
358  }
359 
360  INIT_LIST_HEAD(&newset->element_list);
361  list_for_each_entry(elem, &set->element_list, head) {
362  newelem = nftnl_set_elem_clone(elem);
363  if (newelem == NULL)
364  goto err;
365 
366  list_add_tail(&newelem->head, &newset->element_list);
367  }
368 
369  return newset;
370 err:
371  nftnl_set_free(newset);
372  return NULL;
373 }
374 
375 static void nftnl_set_nlmsg_build_desc_size_payload(struct nlmsghdr *nlh,
376  struct nftnl_set *s)
377 {
378  mnl_attr_put_u32(nlh, NFTA_SET_DESC_SIZE, htonl(s->desc.size));
379 }
380 
381 static void nftnl_set_nlmsg_build_desc_concat_payload(struct nlmsghdr *nlh,
382  struct nftnl_set *s)
383 {
384  struct nlattr *nest;
385  int i;
386 
387  nest = mnl_attr_nest_start(nlh, NFTA_SET_DESC_CONCAT);
388  for (i = 0; i < NFT_REG32_COUNT && i < s->desc.field_count; i++) {
389  struct nlattr *nest_elem;
390 
391  nest_elem = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
392  mnl_attr_put_u32(nlh, NFTA_SET_FIELD_LEN,
393  htonl(s->desc.field_len[i]));
394  mnl_attr_nest_end(nlh, nest_elem);
395  }
396  mnl_attr_nest_end(nlh, nest);
397 }
398 
399 static void
400 nftnl_set_nlmsg_build_desc_payload(struct nlmsghdr *nlh, struct nftnl_set *s)
401 {
402  struct nlattr *nest;
403 
404  nest = mnl_attr_nest_start(nlh, NFTA_SET_DESC);
405 
406  if (s->flags & (1 << NFTNL_SET_DESC_SIZE))
407  nftnl_set_nlmsg_build_desc_size_payload(nlh, s);
408  if (s->flags & (1 << NFTNL_SET_DESC_CONCAT))
409  nftnl_set_nlmsg_build_desc_concat_payload(nlh, s);
410 
411  mnl_attr_nest_end(nlh, nest);
412 }
413 
414 EXPORT_SYMBOL(nftnl_set_nlmsg_build_payload);
415 void nftnl_set_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_set *s)
416 {
417  if (s->flags & (1 << NFTNL_SET_TABLE))
418  mnl_attr_put_strz(nlh, NFTA_SET_TABLE, s->table);
419  if (s->flags & (1 << NFTNL_SET_NAME))
420  mnl_attr_put_strz(nlh, NFTA_SET_NAME, s->name);
421  if (s->flags & (1 << NFTNL_SET_HANDLE))
422  mnl_attr_put_u64(nlh, NFTA_SET_HANDLE, htobe64(s->handle));
423  if (s->flags & (1 << NFTNL_SET_FLAGS))
424  mnl_attr_put_u32(nlh, NFTA_SET_FLAGS, htonl(s->set_flags));
425  if (s->flags & (1 << NFTNL_SET_KEY_TYPE))
426  mnl_attr_put_u32(nlh, NFTA_SET_KEY_TYPE, htonl(s->key_type));
427  if (s->flags & (1 << NFTNL_SET_KEY_LEN))
428  mnl_attr_put_u32(nlh, NFTA_SET_KEY_LEN, htonl(s->key_len));
429  /* These are only used to map matching -> action (1:1) */
430  if (s->flags & (1 << NFTNL_SET_DATA_TYPE))
431  mnl_attr_put_u32(nlh, NFTA_SET_DATA_TYPE, htonl(s->data_type));
432  if (s->flags & (1 << NFTNL_SET_DATA_LEN))
433  mnl_attr_put_u32(nlh, NFTA_SET_DATA_LEN, htonl(s->data_len));
434  if (s->flags & (1 << NFTNL_SET_OBJ_TYPE))
435  mnl_attr_put_u32(nlh, NFTA_SET_OBJ_TYPE, htonl(s->obj_type));
436  if (s->flags & (1 << NFTNL_SET_ID))
437  mnl_attr_put_u32(nlh, NFTA_SET_ID, htonl(s->id));
438  if (s->flags & (1 << NFTNL_SET_POLICY))
439  mnl_attr_put_u32(nlh, NFTA_SET_POLICY, htonl(s->policy));
440  if (s->flags & (1 << NFTNL_SET_DESC_SIZE | 1 << NFTNL_SET_DESC_CONCAT))
441  nftnl_set_nlmsg_build_desc_payload(nlh, s);
442  if (s->flags & (1 << NFTNL_SET_TIMEOUT))
443  mnl_attr_put_u64(nlh, NFTA_SET_TIMEOUT, htobe64(s->timeout));
444  if (s->flags & (1 << NFTNL_SET_GC_INTERVAL))
445  mnl_attr_put_u32(nlh, NFTA_SET_GC_INTERVAL, htonl(s->gc_interval));
446  if (s->flags & (1 << NFTNL_SET_USERDATA))
447  mnl_attr_put(nlh, NFTA_SET_USERDATA, s->user.len, s->user.data);
448  if (s->flags & (1 << NFTNL_SET_EXPR)) {
449  struct nlattr *nest1;
450 
451  nest1 = mnl_attr_nest_start(nlh, NFTA_SET_EXPR);
452  nftnl_expr_build_payload(nlh, s->expr);
453  mnl_attr_nest_end(nlh, nest1);
454  }
455 }
456 
457 
458 static int nftnl_set_parse_attr_cb(const struct nlattr *attr, void *data)
459 {
460  const struct nlattr **tb = data;
461  int type = mnl_attr_get_type(attr);
462 
463  if (mnl_attr_type_valid(attr, NFTA_SET_MAX) < 0)
464  return MNL_CB_OK;
465 
466  switch(type) {
467  case NFTA_SET_TABLE:
468  case NFTA_SET_NAME:
469  if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
470  abi_breakage();
471  break;
472  case NFTA_SET_HANDLE:
473  if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
474  abi_breakage();
475  break;
476  case NFTA_SET_FLAGS:
477  case NFTA_SET_KEY_TYPE:
478  case NFTA_SET_KEY_LEN:
479  case NFTA_SET_DATA_TYPE:
480  case NFTA_SET_DATA_LEN:
481  case NFTA_SET_ID:
482  case NFTA_SET_POLICY:
483  case NFTA_SET_GC_INTERVAL:
484  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
485  abi_breakage();
486  break;
487  case NFTA_SET_USERDATA:
488  if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
489  abi_breakage();
490  break;
491  case NFTA_SET_TIMEOUT:
492  if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
493  abi_breakage();
494  break;
495  case NFTA_SET_DESC:
496  if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
497  abi_breakage();
498  break;
499  }
500 
501  tb[type] = attr;
502  return MNL_CB_OK;
503 }
504 
505 static int
506 nftnl_set_desc_concat_field_parse_attr_cb(const struct nlattr *attr, void *data)
507 {
508  int type = mnl_attr_get_type(attr);
509  struct nftnl_set *s = data;
510 
511  if (type != NFTA_SET_FIELD_LEN)
512  return MNL_CB_OK;
513 
514  if (mnl_attr_validate(attr, MNL_TYPE_U32))
515  return MNL_CB_ERROR;
516 
517  s->desc.field_len[s->desc.field_count] = ntohl(mnl_attr_get_u32(attr));
518  s->desc.field_count++;
519 
520  return MNL_CB_OK;
521 }
522 
523 static int
524 nftnl_set_desc_concat_parse_attr_cb(const struct nlattr *attr, void *data)
525 {
526  int type = mnl_attr_get_type(attr);
527  struct nftnl_set *s = data;
528 
529  if (type != NFTA_LIST_ELEM)
530  return MNL_CB_OK;
531 
532  return mnl_attr_parse_nested(attr,
533  nftnl_set_desc_concat_field_parse_attr_cb,
534  s);
535 }
536 
537 static int nftnl_set_desc_parse_attr_cb(const struct nlattr *attr, void *data)
538 {
539  int type = mnl_attr_get_type(attr), err;
540  struct nftnl_set *s = data;
541 
542  if (mnl_attr_type_valid(attr, NFTA_SET_DESC_MAX) < 0)
543  return MNL_CB_OK;
544 
545  switch (type) {
546  case NFTA_SET_DESC_SIZE:
547  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
548  abi_breakage();
549  break;
550  }
551 
552  s->desc.size = ntohl(mnl_attr_get_u32(attr));
553  s->flags |= (1 << NFTNL_SET_DESC_SIZE);
554  break;
555  case NFTA_SET_DESC_CONCAT:
556  err = mnl_attr_parse_nested(attr,
557  nftnl_set_desc_concat_parse_attr_cb,
558  s);
559  if (err != MNL_CB_OK)
560  abi_breakage();
561 
562  s->flags |= (1 << NFTNL_SET_DESC_CONCAT);
563  break;
564  default:
565  break;
566  }
567 
568  return MNL_CB_OK;
569 }
570 
571 static int nftnl_set_desc_parse(struct nftnl_set *s, const struct nlattr *attr)
572 {
573  return mnl_attr_parse_nested(attr, nftnl_set_desc_parse_attr_cb, s);
574 }
575 
576 EXPORT_SYMBOL(nftnl_set_nlmsg_parse);
577 int nftnl_set_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_set *s)
578 {
579  struct nlattr *tb[NFTA_SET_MAX+1] = {};
580  struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
581  int ret;
582 
583  if (mnl_attr_parse(nlh, sizeof(*nfg), nftnl_set_parse_attr_cb, tb) < 0)
584  return -1;
585 
586  if (tb[NFTA_SET_TABLE]) {
587  if (s->flags & (1 << NFTNL_SET_TABLE))
588  xfree(s->table);
589  s->table = strdup(mnl_attr_get_str(tb[NFTA_SET_TABLE]));
590  if (!s->table)
591  return -1;
592  s->flags |= (1 << NFTNL_SET_TABLE);
593  }
594  if (tb[NFTA_SET_NAME]) {
595  if (s->flags & (1 << NFTNL_SET_NAME))
596  xfree(s->name);
597  s->name = strdup(mnl_attr_get_str(tb[NFTA_SET_NAME]));
598  if (!s->name)
599  return -1;
600  s->flags |= (1 << NFTNL_SET_NAME);
601  }
602  if (tb[NFTA_SET_HANDLE]) {
603  s->handle = be64toh(mnl_attr_get_u64(tb[NFTA_SET_HANDLE]));
604  s->flags |= (1 << NFTNL_SET_HANDLE);
605  }
606  if (tb[NFTA_SET_FLAGS]) {
607  s->set_flags = ntohl(mnl_attr_get_u32(tb[NFTA_SET_FLAGS]));
608  s->flags |= (1 << NFTNL_SET_FLAGS);
609  }
610  if (tb[NFTA_SET_KEY_TYPE]) {
611  s->key_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_KEY_TYPE]));
612  s->flags |= (1 << NFTNL_SET_KEY_TYPE);
613  }
614  if (tb[NFTA_SET_KEY_LEN]) {
615  s->key_len = ntohl(mnl_attr_get_u32(tb[NFTA_SET_KEY_LEN]));
616  s->flags |= (1 << NFTNL_SET_KEY_LEN);
617  }
618  if (tb[NFTA_SET_DATA_TYPE]) {
619  s->data_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_DATA_TYPE]));
620  s->flags |= (1 << NFTNL_SET_DATA_TYPE);
621  }
622  if (tb[NFTA_SET_DATA_LEN]) {
623  s->data_len = ntohl(mnl_attr_get_u32(tb[NFTA_SET_DATA_LEN]));
624  s->flags |= (1 << NFTNL_SET_DATA_LEN);
625  }
626  if (tb[NFTA_SET_OBJ_TYPE]) {
627  s->obj_type = ntohl(mnl_attr_get_u32(tb[NFTA_SET_OBJ_TYPE]));
628  s->flags |= (1 << NFTNL_SET_OBJ_TYPE);
629  }
630  if (tb[NFTA_SET_ID]) {
631  s->id = ntohl(mnl_attr_get_u32(tb[NFTA_SET_ID]));
632  s->flags |= (1 << NFTNL_SET_ID);
633  }
634  if (tb[NFTA_SET_POLICY]) {
635  s->policy = ntohl(mnl_attr_get_u32(tb[NFTA_SET_POLICY]));
636  s->flags |= (1 << NFTNL_SET_POLICY);
637  }
638  if (tb[NFTA_SET_TIMEOUT]) {
639  s->timeout = be64toh(mnl_attr_get_u64(tb[NFTA_SET_TIMEOUT]));
640  s->flags |= (1 << NFTNL_SET_TIMEOUT);
641  }
642  if (tb[NFTA_SET_GC_INTERVAL]) {
643  s->gc_interval = ntohl(mnl_attr_get_u32(tb[NFTA_SET_GC_INTERVAL]));
644  s->flags |= (1 << NFTNL_SET_GC_INTERVAL);
645  }
646  if (tb[NFTA_SET_USERDATA]) {
647  ret = nftnl_set_set_data(s, NFTNL_SET_USERDATA,
648  mnl_attr_get_payload(tb[NFTA_SET_USERDATA]),
649  mnl_attr_get_payload_len(tb[NFTA_SET_USERDATA]));
650  if (ret < 0)
651  return ret;
652  }
653  if (tb[NFTA_SET_DESC]) {
654  ret = nftnl_set_desc_parse(s, tb[NFTA_SET_DESC]);
655  if (ret < 0)
656  return ret;
657  }
658  if (tb[NFTA_SET_EXPR]) {
659  s->expr = nftnl_expr_parse(tb[NFTA_SET_EXPR]);
660  if (!s->expr)
661  return -1;
662 
663  s->flags |= (1 << NFTNL_SET_EXPR);
664  }
665 
666  s->family = nfg->nfgen_family;
667  s->flags |= (1 << NFTNL_SET_FAMILY);
668 
669  return 0;
670 }
671 
672 static int nftnl_set_do_parse(struct nftnl_set *s, enum nftnl_parse_type type,
673  const void *data, struct nftnl_parse_err *err,
674  enum nftnl_parse_input input)
675 {
676  int ret;
677  struct nftnl_parse_err perr = {};
678 
679  switch (type) {
680  case NFTNL_PARSE_JSON:
681  case NFTNL_PARSE_XML:
682  default:
683  ret = -1;
684  errno = EOPNOTSUPP;
685  break;
686  }
687 
688  if (err != NULL)
689  *err = perr;
690 
691  return ret;
692 }
693 
694 EXPORT_SYMBOL(nftnl_set_parse);
695 int nftnl_set_parse(struct nftnl_set *s, enum nftnl_parse_type type,
696  const char *data, struct nftnl_parse_err *err)
697 {
698  return nftnl_set_do_parse(s, type, data, err, NFTNL_PARSE_BUFFER);
699 }
700 
701 EXPORT_SYMBOL(nftnl_set_parse_file);
702 int nftnl_set_parse_file(struct nftnl_set *s, enum nftnl_parse_type type,
703  FILE *fp, struct nftnl_parse_err *err)
704 {
705  return nftnl_set_do_parse(s, type, fp, err, NFTNL_PARSE_FILE);
706 }
707 
708 static int nftnl_set_snprintf_default(char *buf, size_t size,
709  const struct nftnl_set *s,
710  uint32_t type, uint32_t flags)
711 {
712  int ret;
713  int remain = size, offset = 0;
714  struct nftnl_set_elem *elem;
715 
716  ret = snprintf(buf, remain, "%s %s %x",
717  s->name, s->table, s->set_flags);
718  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
719 
720  if (s->flags & (1 << NFTNL_SET_TIMEOUT)) {
721  ret = snprintf(buf + offset, remain, " timeout %"PRIu64"ms",
722  s->timeout);
723  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
724  }
725 
726  if (s->flags & (1 << NFTNL_SET_GC_INTERVAL)) {
727  ret = snprintf(buf + offset, remain, " gc_interval %ums",
728  s->gc_interval);
729  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
730  }
731 
732  if (s->flags & (1 << NFTNL_SET_POLICY)) {
733  ret = snprintf(buf + offset, remain, " policy %u", s->policy);
734  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
735  }
736 
737  if (s->flags & (1 << NFTNL_SET_DESC_SIZE)) {
738  ret = snprintf(buf + offset, remain, " size %u", s->desc.size);
739  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
740  }
741 
742  /* Empty set? Skip printinf of elements */
743  if (list_empty(&s->element_list))
744  return offset;
745 
746  ret = snprintf(buf + offset, remain, "\n");
747  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
748 
749  list_for_each_entry(elem, &s->element_list, head) {
750  ret = snprintf(buf + offset, remain, "\t");
751  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
752 
753  ret = nftnl_set_elem_snprintf(buf + offset, remain, elem, type,
754  flags);
755  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
756  }
757 
758  return offset;
759 }
760 
761 static int nftnl_set_cmd_snprintf(char *buf, size_t size,
762  const struct nftnl_set *s, uint32_t cmd,
763  uint32_t type, uint32_t flags)
764 {
765  int ret, remain = size, offset = 0;
766  uint32_t inner_flags = flags;
767 
768  if (type == NFTNL_OUTPUT_XML)
769  return 0;
770 
771  /* prevent set_elems to print as events */
772  inner_flags &= ~NFTNL_OF_EVENT_ANY;
773 
774  switch(type) {
775  case NFTNL_OUTPUT_DEFAULT:
776  ret = nftnl_set_snprintf_default(buf + offset, remain, s, type,
777  inner_flags);
778  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
779  break;
780  default:
781  return -1;
782  }
783 
784  return offset;
785 }
786 
787 EXPORT_SYMBOL(nftnl_set_snprintf);
788 int nftnl_set_snprintf(char *buf, size_t size, const struct nftnl_set *s,
789  uint32_t type, uint32_t flags)
790 {
791  if (size)
792  buf[0] = '\0';
793 
794  return nftnl_set_cmd_snprintf(buf, size, s, nftnl_flag2cmd(flags), type,
795  flags);
796 }
797 
798 static int nftnl_set_do_snprintf(char *buf, size_t size, const void *s,
799  uint32_t cmd, uint32_t type, uint32_t flags)
800 {
801  return nftnl_set_snprintf(buf, size, s, type, flags);
802 }
803 
804 EXPORT_SYMBOL(nftnl_set_fprintf);
805 int nftnl_set_fprintf(FILE *fp, const struct nftnl_set *s, uint32_t type,
806  uint32_t flags)
807 {
808  return nftnl_fprintf(fp, s, NFTNL_CMD_UNSPEC, type, flags,
809  nftnl_set_do_snprintf);
810 }
811 
812 EXPORT_SYMBOL(nftnl_set_elem_add);
813 void nftnl_set_elem_add(struct nftnl_set *s, struct nftnl_set_elem *elem)
814 {
815  list_add_tail(&elem->head, &s->element_list);
816 }
817 
818 #define SET_NAME_HSIZE 512
819 
821  struct list_head list;
822  struct hlist_head name_hash[SET_NAME_HSIZE];
823 };
824 
825 EXPORT_SYMBOL(nftnl_set_list_alloc);
826 struct nftnl_set_list *nftnl_set_list_alloc(void)
827 {
828  struct nftnl_set_list *list;
829  int i;
830 
831  list = calloc(1, sizeof(struct nftnl_set_list));
832  if (list == NULL)
833  return NULL;
834 
835  INIT_LIST_HEAD(&list->list);
836  for (i = 0; i < SET_NAME_HSIZE; i++)
837  INIT_HLIST_HEAD(&list->name_hash[i]);
838 
839  return list;
840 }
841 
842 EXPORT_SYMBOL(nftnl_set_list_free);
843 void nftnl_set_list_free(struct nftnl_set_list *list)
844 {
845  struct nftnl_set *s, *tmp;
846 
847  list_for_each_entry_safe(s, tmp, &list->list, head) {
848  list_del(&s->head);
849  hlist_del(&s->hnode);
850  nftnl_set_free(s);
851  }
852  xfree(list);
853 }
854 
855 EXPORT_SYMBOL(nftnl_set_list_is_empty);
856 int nftnl_set_list_is_empty(const struct nftnl_set_list *list)
857 {
858  return list_empty(&list->list);
859 }
860 
861 static uint32_t djb_hash(const char *key)
862 {
863  uint32_t i, hash = 5381;
864 
865  for (i = 0; i < strlen(key); i++)
866  hash = ((hash << 5) + hash) + key[i];
867 
868  return hash;
869 }
870 
871 EXPORT_SYMBOL(nftnl_set_list_add);
872 void nftnl_set_list_add(struct nftnl_set *s, struct nftnl_set_list *list)
873 {
874  int key = djb_hash(s->name) % SET_NAME_HSIZE;
875 
876  hlist_add_head(&s->hnode, &list->name_hash[key]);
877  list_add(&s->head, &list->list);
878 }
879 
880 EXPORT_SYMBOL(nftnl_set_list_add_tail);
881 void nftnl_set_list_add_tail(struct nftnl_set *s, struct nftnl_set_list *list)
882 {
883  int key = djb_hash(s->name) % SET_NAME_HSIZE;
884 
885  hlist_add_head(&s->hnode, &list->name_hash[key]);
886  list_add_tail(&s->head, &list->list);
887 }
888 
889 EXPORT_SYMBOL(nftnl_set_list_del);
890 void nftnl_set_list_del(struct nftnl_set *s)
891 {
892  list_del(&s->head);
893  hlist_del(&s->hnode);
894 }
895 
896 EXPORT_SYMBOL(nftnl_set_list_foreach);
897 int nftnl_set_list_foreach(struct nftnl_set_list *set_list,
898  int (*cb)(struct nftnl_set *t, void *data), void *data)
899 {
900  struct nftnl_set *cur, *tmp;
901  int ret;
902 
903  list_for_each_entry_safe(cur, tmp, &set_list->list, head) {
904  ret = cb(cur, data);
905  if (ret < 0)
906  return ret;
907  }
908  return 0;
909 }
910 
912  const struct nftnl_set_list *list;
913  struct nftnl_set *cur;
914 };
915 
916 EXPORT_SYMBOL(nftnl_set_list_iter_create);
917 struct nftnl_set_list_iter *
918 nftnl_set_list_iter_create(const struct nftnl_set_list *l)
919 {
920  struct nftnl_set_list_iter *iter;
921 
922  iter = calloc(1, sizeof(struct nftnl_set_list_iter));
923  if (iter == NULL)
924  return NULL;
925 
926  iter->list = l;
927  if (nftnl_set_list_is_empty(l))
928  iter->cur = NULL;
929  else
930  iter->cur = list_entry(l->list.next, struct nftnl_set, head);
931 
932  return iter;
933 }
934 
935 EXPORT_SYMBOL(nftnl_set_list_iter_cur);
936 struct nftnl_set *
937 nftnl_set_list_iter_cur(const struct nftnl_set_list_iter *iter)
938 {
939  return iter->cur;
940 }
941 
942 EXPORT_SYMBOL(nftnl_set_list_iter_next);
943 struct nftnl_set *nftnl_set_list_iter_next(struct nftnl_set_list_iter *iter)
944 {
945  struct nftnl_set *s = iter->cur;
946 
947  if (s == NULL)
948  return NULL;
949 
950  /* get next rule, if any */
951  iter->cur = list_entry(iter->cur->head.next, struct nftnl_set, head);
952  if (&iter->cur->head == iter->list->list.next)
953  return NULL;
954 
955  return s;
956 }
957 
958 EXPORT_SYMBOL(nftnl_set_list_iter_destroy);
959 void nftnl_set_list_iter_destroy(const struct nftnl_set_list_iter *iter)
960 {
961  xfree(iter);
962 }
963 
964 EXPORT_SYMBOL(nftnl_set_list_lookup_byname);
965 struct nftnl_set *
966 nftnl_set_list_lookup_byname(struct nftnl_set_list *set_list, const char *set)
967 {
968  int key = djb_hash(set) % SET_NAME_HSIZE;
969  struct hlist_node *n;
970  struct nftnl_set *s;
971 
972  hlist_for_each_entry(s, n, &set_list->name_hash[key], hnode) {
973  if (!strcmp(set, s->name))
974  return s;
975  }
976  return NULL;
977 }
978 
979 int nftnl_set_lookup_id(struct nftnl_expr *e,
980  struct nftnl_set_list *set_list, uint32_t *set_id)
981 {
982  const char *set_name;
983  struct nftnl_set *s;
984 
985  set_name = nftnl_expr_get_str(e, NFTNL_EXPR_LOOKUP_SET);
986  if (set_name == NULL)
987  return 0;
988 
989  s = nftnl_set_list_lookup_byname(set_list, set_name);
990  if (s == NULL)
991  return 0;
992 
993  *set_id = nftnl_set_get_u32(s, NFTNL_SET_ID);
994  return 1;
995 }
nftnl_set_list_iter
Definition: set.c:911
nftnl_set_list
Definition: set.c:820