libnftnl  1.2.9
obj/counter.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * (C) 2012-2016 by Pablo Neira Ayuso <pablo@netfilter.org>
4  */
5 
6 #include <stdio.h>
7 #include <stdint.h>
8 #include <arpa/inet.h>
9 #include <errno.h>
10 #include <inttypes.h>
11 
12 #include <linux/netfilter/nf_tables.h>
13 
14 #include <libmnl/libmnl.h>
15 #include <libnftnl/object.h>
16 
17 #include "internal.h"
18 #include "obj.h"
19 
20 static int
21 nftnl_obj_counter_set(struct nftnl_obj *e, uint16_t type,
22  const void *data, uint32_t data_len)
23 {
24  struct nftnl_obj_counter *ctr = nftnl_obj_data(e);
25 
26  switch(type) {
27  case NFTNL_OBJ_CTR_BYTES:
28  memcpy(&ctr->bytes, data, data_len);
29  break;
30  case NFTNL_OBJ_CTR_PKTS:
31  memcpy(&ctr->pkts, data, data_len);
32  break;
33  }
34  return 0;
35 }
36 
37 static const void *
38 nftnl_obj_counter_get(const struct nftnl_obj *e, uint16_t type,
39  uint32_t *data_len)
40 {
41  struct nftnl_obj_counter *ctr = nftnl_obj_data(e);
42 
43  switch(type) {
44  case NFTNL_OBJ_CTR_BYTES:
45  *data_len = sizeof(ctr->bytes);
46  return &ctr->bytes;
47  case NFTNL_OBJ_CTR_PKTS:
48  *data_len = sizeof(ctr->pkts);
49  return &ctr->pkts;
50  }
51  return NULL;
52 }
53 
54 static int nftnl_obj_counter_cb(const struct nlattr *attr, void *data)
55 {
56  const struct nlattr **tb = data;
57  int type = mnl_attr_get_type(attr);
58 
59  if (mnl_attr_type_valid(attr, NFTA_COUNTER_MAX) < 0)
60  return MNL_CB_OK;
61 
62  switch(type) {
63  case NFTA_COUNTER_BYTES:
64  case NFTA_COUNTER_PACKETS:
65  if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
66  abi_breakage();
67  break;
68  }
69 
70  tb[type] = attr;
71  return MNL_CB_OK;
72 }
73 
74 static void
75 nftnl_obj_counter_build(struct nlmsghdr *nlh, const struct nftnl_obj *e)
76 {
77  struct nftnl_obj_counter *ctr = nftnl_obj_data(e);
78 
79  if (e->flags & (1 << NFTNL_OBJ_CTR_BYTES))
80  mnl_attr_put_u64(nlh, NFTA_COUNTER_BYTES, htobe64(ctr->bytes));
81  if (e->flags & (1 << NFTNL_OBJ_CTR_PKTS))
82  mnl_attr_put_u64(nlh, NFTA_COUNTER_PACKETS, htobe64(ctr->pkts));
83 }
84 
85 static int
86 nftnl_obj_counter_parse(struct nftnl_obj *e, struct nlattr *attr)
87 {
88  struct nftnl_obj_counter *ctr = nftnl_obj_data(e);
89  struct nlattr *tb[NFTA_COUNTER_MAX+1] = {};
90 
91  if (mnl_attr_parse_nested(attr, nftnl_obj_counter_cb, tb) < 0)
92  return -1;
93 
94  if (tb[NFTA_COUNTER_BYTES]) {
95  ctr->bytes = be64toh(mnl_attr_get_u64(tb[NFTA_COUNTER_BYTES]));
96  e->flags |= (1 << NFTNL_OBJ_CTR_BYTES);
97  }
98  if (tb[NFTA_COUNTER_PACKETS]) {
99  ctr->pkts = be64toh(mnl_attr_get_u64(tb[NFTA_COUNTER_PACKETS]));
100  e->flags |= (1 << NFTNL_OBJ_CTR_PKTS);
101  }
102 
103  return 0;
104 }
105 
106 static int nftnl_obj_counter_snprintf(char *buf, size_t len, uint32_t flags,
107  const struct nftnl_obj *e)
108 {
109  struct nftnl_obj_counter *ctr = nftnl_obj_data(e);
110 
111  return snprintf(buf, len, "pkts %"PRIu64" bytes %"PRIu64" ",
112  ctr->pkts, ctr->bytes);
113 }
114 
115 static struct attr_policy obj_ctr_attr_policy[__NFTNL_OBJ_CTR_MAX] = {
116  [NFTNL_OBJ_CTR_BYTES] = { .maxlen = sizeof(uint64_t) },
117  [NFTNL_OBJ_CTR_PKTS] = { .maxlen = sizeof(uint64_t) },
118 };
119 
120 struct obj_ops obj_ops_counter = {
121  .name = "counter",
122  .type = NFT_OBJECT_COUNTER,
123  .alloc_len = sizeof(struct nftnl_obj_counter),
124  .nftnl_max_attr = __NFTNL_OBJ_CTR_MAX - 1,
125  .attr_policy = obj_ctr_attr_policy,
126  .set = nftnl_obj_counter_set,
127  .get = nftnl_obj_counter_get,
128  .parse = nftnl_obj_counter_parse,
129  .build = nftnl_obj_counter_build,
130  .output = nftnl_obj_counter_snprintf,
131 };