libnftnl  1.1.8
rule.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 <limits.h>
18 #include <string.h>
19 #include <netinet/in.h>
20 #include <errno.h>
21 #include <inttypes.h>
22 #include <ctype.h>
23 
24 #include <libmnl/libmnl.h>
25 #include <linux/netfilter/nfnetlink.h>
26 #include <linux/netfilter/nf_tables.h>
27 
28 #include <libnftnl/rule.h>
29 #include <libnftnl/set.h>
30 #include <libnftnl/expr.h>
31 
32 EXPORT_SYMBOL(nftnl_rule_alloc);
33 struct nftnl_rule *nftnl_rule_alloc(void)
34 {
35  struct nftnl_rule *r;
36 
37  r = calloc(1, sizeof(struct nftnl_rule));
38  if (r == NULL)
39  return NULL;
40 
41  INIT_LIST_HEAD(&r->expr_list);
42 
43  return r;
44 }
45 
46 EXPORT_SYMBOL(nftnl_rule_free);
47 void nftnl_rule_free(const struct nftnl_rule *r)
48 {
49  struct nftnl_expr *e, *tmp;
50 
51  list_for_each_entry_safe(e, tmp, &r->expr_list, head)
52  nftnl_expr_free(e);
53 
54  if (r->flags & (1 << (NFTNL_RULE_TABLE)))
55  xfree(r->table);
56  if (r->flags & (1 << (NFTNL_RULE_CHAIN)))
57  xfree(r->chain);
58  if (r->flags & (1 << (NFTNL_RULE_USERDATA)))
59  xfree(r->user.data);
60 
61  xfree(r);
62 }
63 
64 EXPORT_SYMBOL(nftnl_rule_is_set);
65 bool nftnl_rule_is_set(const struct nftnl_rule *r, uint16_t attr)
66 {
67  return r->flags & (1 << attr);
68 }
69 
70 EXPORT_SYMBOL(nftnl_rule_unset);
71 void nftnl_rule_unset(struct nftnl_rule *r, uint16_t attr)
72 {
73  if (!(r->flags & (1 << attr)))
74  return;
75 
76  switch (attr) {
77  case NFTNL_RULE_TABLE:
78  xfree(r->table);
79  break;
80  case NFTNL_RULE_CHAIN:
81  xfree(r->chain);
82  break;
83  case NFTNL_RULE_HANDLE:
84  case NFTNL_RULE_COMPAT_PROTO:
85  case NFTNL_RULE_COMPAT_FLAGS:
86  case NFTNL_RULE_POSITION:
87  case NFTNL_RULE_FAMILY:
88  case NFTNL_RULE_ID:
89  case NFTNL_RULE_POSITION_ID:
90  break;
91  case NFTNL_RULE_USERDATA:
92  xfree(r->user.data);
93  break;
94  }
95 
96  r->flags &= ~(1 << attr);
97 }
98 
99 static uint32_t nftnl_rule_validate[NFTNL_RULE_MAX + 1] = {
100  [NFTNL_RULE_HANDLE] = sizeof(uint64_t),
101  [NFTNL_RULE_COMPAT_PROTO] = sizeof(uint32_t),
102  [NFTNL_RULE_COMPAT_FLAGS] = sizeof(uint32_t),
103  [NFTNL_RULE_FAMILY] = sizeof(uint32_t),
104  [NFTNL_RULE_POSITION] = sizeof(uint64_t),
105  [NFTNL_RULE_ID] = sizeof(uint32_t),
106  [NFTNL_RULE_POSITION_ID] = sizeof(uint32_t),
107 };
108 
109 EXPORT_SYMBOL(nftnl_rule_set_data);
110 int nftnl_rule_set_data(struct nftnl_rule *r, uint16_t attr,
111  const void *data, uint32_t data_len)
112 {
113  nftnl_assert_attr_exists(attr, NFTNL_RULE_MAX);
114  nftnl_assert_validate(data, nftnl_rule_validate, attr, data_len);
115 
116  switch(attr) {
117  case NFTNL_RULE_TABLE:
118  if (r->flags & (1 << NFTNL_RULE_TABLE))
119  xfree(r->table);
120 
121  r->table = strdup(data);
122  if (!r->table)
123  return -1;
124  break;
125  case NFTNL_RULE_CHAIN:
126  if (r->flags & (1 << NFTNL_RULE_CHAIN))
127  xfree(r->chain);
128 
129  r->chain = strdup(data);
130  if (!r->chain)
131  return -1;
132  break;
133  case NFTNL_RULE_HANDLE:
134  memcpy(&r->handle, data, sizeof(r->handle));
135  break;
136  case NFTNL_RULE_COMPAT_PROTO:
137  memcpy(&r->compat.proto, data, sizeof(r->compat.proto));
138  break;
139  case NFTNL_RULE_COMPAT_FLAGS:
140  memcpy(&r->compat.flags, data, sizeof(r->compat.flags));
141  break;
142  case NFTNL_RULE_FAMILY:
143  memcpy(&r->family, data, sizeof(r->family));
144  break;
145  case NFTNL_RULE_POSITION:
146  memcpy(&r->position, data, sizeof(r->position));
147  break;
148  case NFTNL_RULE_USERDATA:
149  if (r->flags & (1 << NFTNL_RULE_USERDATA))
150  xfree(r->user.data);
151 
152  r->user.data = malloc(data_len);
153  if (!r->user.data)
154  return -1;
155 
156  memcpy(r->user.data, data, data_len);
157  r->user.len = data_len;
158  break;
159  case NFTNL_RULE_ID:
160  memcpy(&r->id, data, sizeof(r->id));
161  break;
162  case NFTNL_RULE_POSITION_ID:
163  memcpy(&r->position_id, data, sizeof(r->position_id));
164  break;
165  }
166  r->flags |= (1 << attr);
167  return 0;
168 }
169 
170 int nftnl_rule_set(struct nftnl_rule *r, uint16_t attr, const void *data) __visible;
171 int nftnl_rule_set(struct nftnl_rule *r, uint16_t attr, const void *data)
172 {
173  return nftnl_rule_set_data(r, attr, data, nftnl_rule_validate[attr]);
174 }
175 
176 EXPORT_SYMBOL(nftnl_rule_set_u32);
177 void nftnl_rule_set_u32(struct nftnl_rule *r, uint16_t attr, uint32_t val)
178 {
179  nftnl_rule_set_data(r, attr, &val, sizeof(uint32_t));
180 }
181 
182 EXPORT_SYMBOL(nftnl_rule_set_u64);
183 void nftnl_rule_set_u64(struct nftnl_rule *r, uint16_t attr, uint64_t val)
184 {
185  nftnl_rule_set_data(r, attr, &val, sizeof(uint64_t));
186 }
187 
188 EXPORT_SYMBOL(nftnl_rule_set_str);
189 int nftnl_rule_set_str(struct nftnl_rule *r, uint16_t attr, const char *str)
190 {
191  return nftnl_rule_set_data(r, attr, str, strlen(str) + 1);
192 }
193 
194 EXPORT_SYMBOL(nftnl_rule_get_data);
195 const void *nftnl_rule_get_data(const struct nftnl_rule *r, uint16_t attr,
196  uint32_t *data_len)
197 {
198  if (!(r->flags & (1 << attr)))
199  return NULL;
200 
201  switch(attr) {
202  case NFTNL_RULE_FAMILY:
203  *data_len = sizeof(uint32_t);
204  return &r->family;
205  case NFTNL_RULE_TABLE:
206  *data_len = strlen(r->table) + 1;
207  return r->table;
208  case NFTNL_RULE_CHAIN:
209  *data_len = strlen(r->chain) + 1;
210  return r->chain;
211  case NFTNL_RULE_HANDLE:
212  *data_len = sizeof(uint64_t);
213  return &r->handle;
214  case NFTNL_RULE_COMPAT_PROTO:
215  *data_len = sizeof(uint32_t);
216  return &r->compat.proto;
217  case NFTNL_RULE_COMPAT_FLAGS:
218  *data_len = sizeof(uint32_t);
219  return &r->compat.flags;
220  case NFTNL_RULE_POSITION:
221  *data_len = sizeof(uint64_t);
222  return &r->position;
223  case NFTNL_RULE_USERDATA:
224  *data_len = r->user.len;
225  return r->user.data;
226  case NFTNL_RULE_ID:
227  *data_len = sizeof(uint32_t);
228  return &r->id;
229  case NFTNL_RULE_POSITION_ID:
230  *data_len = sizeof(uint32_t);
231  return &r->position_id;
232  }
233  return NULL;
234 }
235 
236 EXPORT_SYMBOL(nftnl_rule_get);
237 const void *nftnl_rule_get(const struct nftnl_rule *r, uint16_t attr)
238 {
239  uint32_t data_len;
240  return nftnl_rule_get_data(r, attr, &data_len);
241 }
242 
243 EXPORT_SYMBOL(nftnl_rule_get_str);
244 const char *nftnl_rule_get_str(const struct nftnl_rule *r, uint16_t attr)
245 {
246  return nftnl_rule_get(r, attr);
247 }
248 
249 EXPORT_SYMBOL(nftnl_rule_get_u32);
250 uint32_t nftnl_rule_get_u32(const struct nftnl_rule *r, uint16_t attr)
251 {
252  uint32_t data_len;
253  const uint32_t *val = nftnl_rule_get_data(r, attr, &data_len);
254 
255  nftnl_assert(val, attr, data_len == sizeof(uint32_t));
256 
257  return val ? *val : 0;
258 }
259 
260 EXPORT_SYMBOL(nftnl_rule_get_u64);
261 uint64_t nftnl_rule_get_u64(const struct nftnl_rule *r, uint16_t attr)
262 {
263  uint32_t data_len;
264  const uint64_t *val = nftnl_rule_get_data(r, attr, &data_len);
265 
266  nftnl_assert(val, attr, data_len == sizeof(uint64_t));
267 
268  return val ? *val : 0;
269 }
270 
271 EXPORT_SYMBOL(nftnl_rule_get_u8);
272 uint8_t nftnl_rule_get_u8(const struct nftnl_rule *r, uint16_t attr)
273 {
274  uint32_t data_len;
275  const uint8_t *val = nftnl_rule_get_data(r, attr, &data_len);
276 
277  nftnl_assert(val, attr, data_len == sizeof(uint8_t));
278 
279  return val ? *val : 0;
280 }
281 
282 EXPORT_SYMBOL(nftnl_rule_nlmsg_build_payload);
283 void nftnl_rule_nlmsg_build_payload(struct nlmsghdr *nlh, struct nftnl_rule *r)
284 {
285  struct nftnl_expr *expr;
286  struct nlattr *nest, *nest2;
287 
288  if (r->flags & (1 << NFTNL_RULE_TABLE))
289  mnl_attr_put_strz(nlh, NFTA_RULE_TABLE, r->table);
290  if (r->flags & (1 << NFTNL_RULE_CHAIN))
291  mnl_attr_put_strz(nlh, NFTA_RULE_CHAIN, r->chain);
292  if (r->flags & (1 << NFTNL_RULE_HANDLE))
293  mnl_attr_put_u64(nlh, NFTA_RULE_HANDLE, htobe64(r->handle));
294  if (r->flags & (1 << NFTNL_RULE_POSITION))
295  mnl_attr_put_u64(nlh, NFTA_RULE_POSITION, htobe64(r->position));
296  if (r->flags & (1 << NFTNL_RULE_USERDATA)) {
297  mnl_attr_put(nlh, NFTA_RULE_USERDATA, r->user.len,
298  r->user.data);
299  }
300 
301  if (!list_empty(&r->expr_list)) {
302  nest = mnl_attr_nest_start(nlh, NFTA_RULE_EXPRESSIONS);
303  list_for_each_entry(expr, &r->expr_list, head) {
304  nest2 = mnl_attr_nest_start(nlh, NFTA_LIST_ELEM);
305  nftnl_expr_build_payload(nlh, expr);
306  mnl_attr_nest_end(nlh, nest2);
307  }
308  mnl_attr_nest_end(nlh, nest);
309  }
310 
311  if (r->flags & (1 << NFTNL_RULE_COMPAT_PROTO) &&
312  r->flags & (1 << NFTNL_RULE_COMPAT_FLAGS)) {
313 
314  nest = mnl_attr_nest_start(nlh, NFTA_RULE_COMPAT);
315  mnl_attr_put_u32(nlh, NFTA_RULE_COMPAT_PROTO,
316  htonl(r->compat.proto));
317  mnl_attr_put_u32(nlh, NFTA_RULE_COMPAT_FLAGS,
318  htonl(r->compat.flags));
319  mnl_attr_nest_end(nlh, nest);
320  }
321  if (r->flags & (1 << NFTNL_RULE_ID))
322  mnl_attr_put_u32(nlh, NFTA_RULE_ID, htonl(r->id));
323  if (r->flags & (1 << NFTNL_RULE_POSITION_ID))
324  mnl_attr_put_u32(nlh, NFTA_RULE_POSITION_ID, htonl(r->position_id));
325 }
326 
327 EXPORT_SYMBOL(nftnl_rule_add_expr);
328 void nftnl_rule_add_expr(struct nftnl_rule *r, struct nftnl_expr *expr)
329 {
330  list_add_tail(&expr->head, &r->expr_list);
331 }
332 
333 EXPORT_SYMBOL(nftnl_rule_del_expr);
334 void nftnl_rule_del_expr(struct nftnl_expr *expr)
335 {
336  list_del(&expr->head);
337 }
338 
339 static int nftnl_rule_parse_attr_cb(const struct nlattr *attr, void *data)
340 {
341  const struct nlattr **tb = data;
342  int type = mnl_attr_get_type(attr);
343 
344  if (mnl_attr_type_valid(attr, NFTA_RULE_MAX) < 0)
345  return MNL_CB_OK;
346 
347  switch(type) {
348  case NFTA_RULE_TABLE:
349  case NFTA_RULE_CHAIN:
350  if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
351  abi_breakage();
352  break;
353  case NFTA_RULE_HANDLE:
354  if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
355  abi_breakage();
356  break;
357  case NFTA_RULE_COMPAT:
358  if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0)
359  abi_breakage();
360  break;
361  case NFTA_RULE_POSITION:
362  if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
363  abi_breakage();
364  break;
365  case NFTA_RULE_USERDATA:
366  if (mnl_attr_validate(attr, MNL_TYPE_BINARY) < 0)
367  abi_breakage();
368  break;
369  case NFTA_RULE_ID:
370  case NFTA_RULE_POSITION_ID:
371  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
372  abi_breakage();
373  break;
374  }
375 
376  tb[type] = attr;
377  return MNL_CB_OK;
378 }
379 
380 static int nftnl_rule_parse_expr(struct nlattr *nest, struct nftnl_rule *r)
381 {
382  struct nftnl_expr *expr;
383  struct nlattr *attr;
384 
385  mnl_attr_for_each_nested(attr, nest) {
386  if (mnl_attr_get_type(attr) != NFTA_LIST_ELEM)
387  return -1;
388 
389  expr = nftnl_expr_parse(attr);
390  if (expr == NULL)
391  return -1;
392 
393  list_add_tail(&expr->head, &r->expr_list);
394  }
395  return 0;
396 }
397 
398 static int nftnl_rule_parse_compat_cb(const struct nlattr *attr, void *data)
399 {
400  const struct nlattr **tb = data;
401  int type = mnl_attr_get_type(attr);
402 
403  if (mnl_attr_type_valid(attr, NFTA_RULE_COMPAT_MAX) < 0)
404  return MNL_CB_OK;
405 
406  switch(type) {
407  case NFTA_RULE_COMPAT_PROTO:
408  case NFTA_RULE_COMPAT_FLAGS:
409  if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
410  abi_breakage();
411  break;
412  }
413 
414  tb[type] = attr;
415  return MNL_CB_OK;
416 }
417 
418 static int nftnl_rule_parse_compat(struct nlattr *nest, struct nftnl_rule *r)
419 {
420  struct nlattr *tb[NFTA_RULE_COMPAT_MAX+1] = {};
421 
422  if (mnl_attr_parse_nested(nest, nftnl_rule_parse_compat_cb, tb) < 0)
423  return -1;
424 
425  if (tb[NFTA_RULE_COMPAT_PROTO]) {
426  r->compat.proto =
427  ntohl(mnl_attr_get_u32(tb[NFTA_RULE_COMPAT_PROTO]));
428  r->flags |= (1 << NFTNL_RULE_COMPAT_PROTO);
429  }
430  if (tb[NFTA_RULE_COMPAT_FLAGS]) {
431  r->compat.flags =
432  ntohl(mnl_attr_get_u32(tb[NFTA_RULE_COMPAT_FLAGS]));
433  r->flags |= (1 << NFTNL_RULE_COMPAT_FLAGS);
434  }
435  return 0;
436 }
437 
438 EXPORT_SYMBOL(nftnl_rule_nlmsg_parse);
439 int nftnl_rule_nlmsg_parse(const struct nlmsghdr *nlh, struct nftnl_rule *r)
440 {
441  struct nlattr *tb[NFTA_RULE_MAX+1] = {};
442  struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
443  int ret;
444 
445  if (mnl_attr_parse(nlh, sizeof(*nfg), nftnl_rule_parse_attr_cb, tb) < 0)
446  return -1;
447 
448  if (tb[NFTA_RULE_TABLE]) {
449  if (r->flags & (1 << NFTNL_RULE_TABLE))
450  xfree(r->table);
451  r->table = strdup(mnl_attr_get_str(tb[NFTA_RULE_TABLE]));
452  if (!r->table)
453  return -1;
454  r->flags |= (1 << NFTNL_RULE_TABLE);
455  }
456  if (tb[NFTA_RULE_CHAIN]) {
457  if (r->flags & (1 << NFTNL_RULE_CHAIN))
458  xfree(r->chain);
459  r->chain = strdup(mnl_attr_get_str(tb[NFTA_RULE_CHAIN]));
460  if (!r->chain)
461  return -1;
462  r->flags |= (1 << NFTNL_RULE_CHAIN);
463  }
464  if (tb[NFTA_RULE_HANDLE]) {
465  r->handle = be64toh(mnl_attr_get_u64(tb[NFTA_RULE_HANDLE]));
466  r->flags |= (1 << NFTNL_RULE_HANDLE);
467  }
468  if (tb[NFTA_RULE_EXPRESSIONS]) {
469  ret = nftnl_rule_parse_expr(tb[NFTA_RULE_EXPRESSIONS], r);
470  if (ret < 0)
471  return ret;
472  }
473  if (tb[NFTA_RULE_COMPAT]) {
474  ret = nftnl_rule_parse_compat(tb[NFTA_RULE_COMPAT], r);
475  if (ret < 0)
476  return ret;
477  }
478  if (tb[NFTA_RULE_POSITION]) {
479  r->position = be64toh(mnl_attr_get_u64(tb[NFTA_RULE_POSITION]));
480  r->flags |= (1 << NFTNL_RULE_POSITION);
481  }
482  if (tb[NFTA_RULE_USERDATA]) {
483  const void *udata =
484  mnl_attr_get_payload(tb[NFTA_RULE_USERDATA]);
485 
486  if (r->flags & (1 << NFTNL_RULE_USERDATA))
487  xfree(r->user.data);
488 
489  r->user.len = mnl_attr_get_payload_len(tb[NFTA_RULE_USERDATA]);
490 
491  r->user.data = malloc(r->user.len);
492  if (r->user.data == NULL)
493  return -1;
494 
495  memcpy(r->user.data, udata, r->user.len);
496  r->flags |= (1 << NFTNL_RULE_USERDATA);
497  }
498  if (tb[NFTA_RULE_ID]) {
499  r->id = ntohl(mnl_attr_get_u32(tb[NFTA_RULE_ID]));
500  r->flags |= (1 << NFTNL_RULE_ID);
501  }
502  if (tb[NFTA_RULE_POSITION_ID]) {
503  r->position_id = ntohl(mnl_attr_get_u32(tb[NFTA_RULE_POSITION_ID]));
504  r->flags |= (1 << NFTNL_RULE_POSITION_ID);
505  }
506 
507  r->family = nfg->nfgen_family;
508  r->flags |= (1 << NFTNL_RULE_FAMILY);
509 
510  return 0;
511 }
512 
513 static int nftnl_rule_do_parse(struct nftnl_rule *r, enum nftnl_parse_type type,
514  const void *data, struct nftnl_parse_err *err,
515  enum nftnl_parse_input input)
516 {
517  int ret;
518  struct nftnl_parse_err perr = {};
519 
520  switch (type) {
521  case NFTNL_PARSE_JSON:
522  case NFTNL_PARSE_XML:
523  default:
524  ret = -1;
525  errno = EOPNOTSUPP;
526  break;
527  }
528  if (err != NULL)
529  *err = perr;
530 
531  return ret;
532 }
533 
534 EXPORT_SYMBOL(nftnl_rule_parse);
535 int nftnl_rule_parse(struct nftnl_rule *r, enum nftnl_parse_type type,
536  const char *data, struct nftnl_parse_err *err)
537 {
538  return nftnl_rule_do_parse(r, type, data, err, NFTNL_PARSE_BUFFER);
539 }
540 
541 EXPORT_SYMBOL(nftnl_rule_parse_file);
542 int nftnl_rule_parse_file(struct nftnl_rule *r, enum nftnl_parse_type type,
543  FILE *fp, struct nftnl_parse_err *err)
544 {
545  return nftnl_rule_do_parse(r, type, fp, err, NFTNL_PARSE_FILE);
546 }
547 
548 static int nftnl_rule_snprintf_default(char *buf, size_t size,
549  const struct nftnl_rule *r,
550  uint32_t type, uint32_t flags)
551 {
552  struct nftnl_expr *expr;
553  int ret, remain = size, offset = 0, i;
554 
555  if (r->flags & (1 << NFTNL_RULE_FAMILY)) {
556  ret = snprintf(buf + offset, remain, "%s ",
557  nftnl_family2str(r->family));
558  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
559  }
560 
561  if (r->flags & (1 << NFTNL_RULE_TABLE)) {
562  ret = snprintf(buf + offset, remain, "%s ",
563  r->table);
564  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
565  }
566 
567  if (r->flags & (1 << NFTNL_RULE_CHAIN)) {
568  ret = snprintf(buf + offset, remain, "%s ",
569  r->chain);
570  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
571  }
572  if (r->flags & (1 << NFTNL_RULE_HANDLE)) {
573  ret = snprintf(buf + offset, remain, "%llu ",
574  (unsigned long long)r->handle);
575  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
576  }
577 
578  if (r->flags & (1 << NFTNL_RULE_POSITION)) {
579  ret = snprintf(buf + offset, remain, "%llu ",
580  (unsigned long long)r->position);
581  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
582  }
583 
584  if (r->flags & (1 << NFTNL_RULE_ID)) {
585  ret = snprintf(buf + offset, remain, "%u ", r->id);
586  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
587  }
588 
589  if (r->flags & (1 << NFTNL_RULE_POSITION_ID)) {
590  ret = snprintf(buf + offset, remain, "%u ", r->position_id);
591  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
592  }
593 
594  ret = snprintf(buf + offset, remain, "\n");
595  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
596 
597  list_for_each_entry(expr, &r->expr_list, head) {
598  ret = snprintf(buf + offset, remain, " [ %s ", expr->ops->name);
599  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
600 
601  ret = nftnl_expr_snprintf(buf + offset, remain, expr,
602  type, flags);
603  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
604 
605  ret = snprintf(buf + offset, remain, "]\n");
606  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
607  }
608 
609  if (r->user.len) {
610  ret = snprintf(buf + offset, remain, " userdata = { ");
611  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
612 
613  for (i = 0; i < r->user.len; i++) {
614  char *c = r->user.data;
615 
616  ret = snprintf(buf + offset, remain, "%c",
617  isalnum(c[i]) ? c[i] : 0);
618  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
619  }
620 
621  ret = snprintf(buf + offset, remain, " }\n");
622  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
623 
624  }
625 
626  return offset;
627 }
628 
629 static int nftnl_rule_cmd_snprintf(char *buf, size_t size,
630  const struct nftnl_rule *r, uint32_t cmd,
631  uint32_t type, uint32_t flags)
632 {
633  int ret, remain = size, offset = 0;
634  uint32_t inner_flags = flags;
635 
636  inner_flags &= ~NFTNL_OF_EVENT_ANY;
637 
638  switch(type) {
639  case NFTNL_OUTPUT_DEFAULT:
640  ret = nftnl_rule_snprintf_default(buf + offset, remain, r, type,
641  inner_flags);
642  SNPRINTF_BUFFER_SIZE(ret, remain, offset);
643  break;
644  case NFTNL_OUTPUT_JSON:
645  case NFTNL_OUTPUT_XML:
646  default:
647  return -1;
648  }
649 
650  return offset;
651 }
652 
653 EXPORT_SYMBOL(nftnl_rule_snprintf);
654 int nftnl_rule_snprintf(char *buf, size_t size, const struct nftnl_rule *r,
655  uint32_t type, uint32_t flags)
656 {
657  if (size)
658  buf[0] = '\0';
659 
660  return nftnl_rule_cmd_snprintf(buf, size, r, nftnl_flag2cmd(flags), type,
661  flags);
662 }
663 
664 static int nftnl_rule_do_snprintf(char *buf, size_t size, const void *r,
665  uint32_t cmd, uint32_t type, uint32_t flags)
666 {
667  return nftnl_rule_snprintf(buf, size, r, type, flags);
668 }
669 
670 EXPORT_SYMBOL(nftnl_rule_fprintf);
671 int nftnl_rule_fprintf(FILE *fp, const struct nftnl_rule *r, uint32_t type,
672  uint32_t flags)
673 {
674  return nftnl_fprintf(fp, r, NFTNL_CMD_UNSPEC, type, flags,
675  nftnl_rule_do_snprintf);
676 }
677 
678 EXPORT_SYMBOL(nftnl_expr_foreach);
679 int nftnl_expr_foreach(struct nftnl_rule *r,
680  int (*cb)(struct nftnl_expr *e, void *data),
681  void *data)
682 {
683  struct nftnl_expr *cur, *tmp;
684  int ret;
685 
686  list_for_each_entry_safe(cur, tmp, &r->expr_list, head) {
687  ret = cb(cur, data);
688  if (ret < 0)
689  return ret;
690  }
691  return 0;
692 }
693 
695  const struct nftnl_rule *r;
696  struct nftnl_expr *cur;
697 };
698 
699 static void nftnl_expr_iter_init(const struct nftnl_rule *r,
700  struct nftnl_expr_iter *iter)
701 {
702  iter->r = r;
703  if (list_empty(&r->expr_list))
704  iter->cur = NULL;
705  else
706  iter->cur = list_entry(r->expr_list.next, struct nftnl_expr,
707  head);
708 }
709 
710 EXPORT_SYMBOL(nftnl_expr_iter_create);
711 struct nftnl_expr_iter *nftnl_expr_iter_create(const struct nftnl_rule *r)
712 {
713  struct nftnl_expr_iter *iter;
714 
715  iter = calloc(1, sizeof(struct nftnl_expr_iter));
716  if (iter == NULL)
717  return NULL;
718 
719  nftnl_expr_iter_init(r, iter);
720 
721  return iter;
722 }
723 
724 EXPORT_SYMBOL(nftnl_expr_iter_next);
725 struct nftnl_expr *nftnl_expr_iter_next(struct nftnl_expr_iter *iter)
726 {
727  struct nftnl_expr *expr = iter->cur;
728 
729  if (expr == NULL)
730  return NULL;
731 
732  /* get next expression, if any */
733  iter->cur = list_entry(iter->cur->head.next, struct nftnl_expr, head);
734  if (&iter->cur->head == iter->r->expr_list.next)
735  return NULL;
736 
737  return expr;
738 }
739 
740 EXPORT_SYMBOL(nftnl_expr_iter_destroy);
741 void nftnl_expr_iter_destroy(struct nftnl_expr_iter *iter)
742 {
743  xfree(iter);
744 }
745 
747  struct list_head list;
748 };
749 
750 EXPORT_SYMBOL(nftnl_rule_list_alloc);
751 struct nftnl_rule_list *nftnl_rule_list_alloc(void)
752 {
753  struct nftnl_rule_list *list;
754 
755  list = calloc(1, sizeof(struct nftnl_rule_list));
756  if (list == NULL)
757  return NULL;
758 
759  INIT_LIST_HEAD(&list->list);
760 
761  return list;
762 }
763 
764 EXPORT_SYMBOL(nftnl_rule_list_free);
765 void nftnl_rule_list_free(struct nftnl_rule_list *list)
766 {
767  struct nftnl_rule *r, *tmp;
768 
769  list_for_each_entry_safe(r, tmp, &list->list, head) {
770  list_del(&r->head);
771  nftnl_rule_free(r);
772  }
773  xfree(list);
774 }
775 
776 EXPORT_SYMBOL(nftnl_rule_list_is_empty);
777 int nftnl_rule_list_is_empty(const struct nftnl_rule_list *list)
778 {
779  return list_empty(&list->list);
780 }
781 
782 EXPORT_SYMBOL(nftnl_rule_list_add);
783 void nftnl_rule_list_add(struct nftnl_rule *r, struct nftnl_rule_list *list)
784 {
785  list_add(&r->head, &list->list);
786 }
787 
788 EXPORT_SYMBOL(nftnl_rule_list_insert_at);
789 void nftnl_rule_list_insert_at(struct nftnl_rule *r, struct nftnl_rule *pos)
790 {
791  list_add(&r->head, &pos->head);
792 }
793 
794 EXPORT_SYMBOL(nftnl_rule_list_add_tail);
795 void nftnl_rule_list_add_tail(struct nftnl_rule *r, struct nftnl_rule_list *list)
796 {
797  list_add_tail(&r->head, &list->list);
798 }
799 
800 EXPORT_SYMBOL(nftnl_rule_list_del);
801 void nftnl_rule_list_del(struct nftnl_rule *r)
802 {
803  list_del(&r->head);
804 }
805 
806 EXPORT_SYMBOL(nftnl_rule_list_foreach);
807 int nftnl_rule_list_foreach(struct nftnl_rule_list *rule_list,
808  int (*cb)(struct nftnl_rule *r, void *data),
809  void *data)
810 {
811  struct nftnl_rule *cur, *tmp;
812  int ret;
813 
814  list_for_each_entry_safe(cur, tmp, &rule_list->list, head) {
815  ret = cb(cur, data);
816  if (ret < 0)
817  return ret;
818  }
819  return 0;
820 }
821 
823  const struct nftnl_rule_list *list;
824  struct nftnl_rule *cur;
825 };
826 
827 EXPORT_SYMBOL(nftnl_rule_list_iter_create);
828 struct nftnl_rule_list_iter *
829 nftnl_rule_list_iter_create(const struct nftnl_rule_list *l)
830 {
831  struct nftnl_rule_list_iter *iter;
832 
833  iter = calloc(1, sizeof(struct nftnl_rule_list_iter));
834  if (iter == NULL)
835  return NULL;
836 
837  iter->list = l;
838  if (nftnl_rule_list_is_empty(l))
839  iter->cur = NULL;
840  else
841  iter->cur = list_entry(l->list.next, struct nftnl_rule, head);
842 
843  return iter;
844 }
845 
846 EXPORT_SYMBOL(nftnl_rule_list_iter_cur);
847 struct nftnl_rule *nftnl_rule_list_iter_cur(struct nftnl_rule_list_iter *iter)
848 {
849  return iter->cur;
850 }
851 
852 EXPORT_SYMBOL(nftnl_rule_list_iter_next);
853 struct nftnl_rule *nftnl_rule_list_iter_next(struct nftnl_rule_list_iter *iter)
854 {
855  struct nftnl_rule *r = iter->cur;
856 
857  if (r == NULL)
858  return NULL;
859 
860  /* get next rule, if any */
861  iter->cur = list_entry(iter->cur->head.next, struct nftnl_rule, head);
862  if (&iter->cur->head == iter->list->list.next)
863  return NULL;
864 
865  return r;
866 }
867 
868 EXPORT_SYMBOL(nftnl_rule_list_iter_destroy);
869 void nftnl_rule_list_iter_destroy(const struct nftnl_rule_list_iter *iter)
870 {
871  xfree(iter);
872 }
nftnl_rule_list_iter
Definition: rule.c:822
nftnl_expr_iter
Definition: rule.c:694
nftnl_rule_list
Definition: rule.c:746