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