16 #include <arpa/inet.h>
18 #include <linux/netfilter/nf_tables.h>
21 #include <libmnl/libmnl.h>
22 #include <libnftnl/expr.h>
23 #include <libnftnl/rule.h>
29 enum nft_limit_type type;
34 nftnl_expr_limit_set(
struct nftnl_expr *e, uint16_t type,
35 const void *data, uint32_t data_len)
40 case NFTNL_EXPR_LIMIT_RATE:
41 memcpy(&limit->rate, data, data_len);
43 case NFTNL_EXPR_LIMIT_UNIT:
44 memcpy(&limit->unit, data, data_len);
46 case NFTNL_EXPR_LIMIT_BURST:
47 memcpy(&limit->burst, data, data_len);
49 case NFTNL_EXPR_LIMIT_TYPE:
50 memcpy(&limit->type, data, data_len);
52 case NFTNL_EXPR_LIMIT_FLAGS:
53 memcpy(&limit->flags, data, data_len);
60 nftnl_expr_limit_get(
const struct nftnl_expr *e, uint16_t type,
66 case NFTNL_EXPR_LIMIT_RATE:
67 *data_len =
sizeof(uint64_t);
69 case NFTNL_EXPR_LIMIT_UNIT:
70 *data_len =
sizeof(uint64_t);
72 case NFTNL_EXPR_LIMIT_BURST:
73 *data_len =
sizeof(uint32_t);
75 case NFTNL_EXPR_LIMIT_TYPE:
76 *data_len =
sizeof(uint32_t);
78 case NFTNL_EXPR_LIMIT_FLAGS:
79 *data_len =
sizeof(uint32_t);
85 static int nftnl_expr_limit_cb(
const struct nlattr *attr,
void *data)
87 const struct nlattr **tb = data;
88 int type = mnl_attr_get_type(attr);
90 if (mnl_attr_type_valid(attr, NFTA_LIMIT_MAX) < 0)
96 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
99 case NFTA_LIMIT_BURST:
100 case NFTA_LIMIT_TYPE:
101 case NFTA_LIMIT_FLAGS:
102 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
112 nftnl_expr_limit_build(
struct nlmsghdr *nlh,
const struct nftnl_expr *e)
116 if (e->flags & (1 << NFTNL_EXPR_LIMIT_RATE))
117 mnl_attr_put_u64(nlh, NFTA_LIMIT_RATE, htobe64(limit->rate));
118 if (e->flags & (1 << NFTNL_EXPR_LIMIT_UNIT))
119 mnl_attr_put_u64(nlh, NFTA_LIMIT_UNIT, htobe64(limit->unit));
120 if (e->flags & (1 << NFTNL_EXPR_LIMIT_BURST))
121 mnl_attr_put_u32(nlh, NFTA_LIMIT_BURST, htonl(limit->burst));
122 if (e->flags & (1 << NFTNL_EXPR_LIMIT_TYPE))
123 mnl_attr_put_u32(nlh, NFTA_LIMIT_TYPE, htonl(limit->type));
124 if (e->flags & (1 << NFTNL_EXPR_LIMIT_FLAGS))
125 mnl_attr_put_u32(nlh, NFTA_LIMIT_FLAGS, htonl(limit->flags));
129 nftnl_expr_limit_parse(
struct nftnl_expr *e,
struct nlattr *attr)
132 struct nlattr *tb[NFTA_LIMIT_MAX+1] = {};
134 if (mnl_attr_parse_nested(attr, nftnl_expr_limit_cb, tb) < 0)
137 if (tb[NFTA_LIMIT_RATE]) {
138 limit->rate = be64toh(mnl_attr_get_u64(tb[NFTA_LIMIT_RATE]));
139 e->flags |= (1 << NFTNL_EXPR_LIMIT_RATE);
141 if (tb[NFTA_LIMIT_UNIT]) {
142 limit->unit = be64toh(mnl_attr_get_u64(tb[NFTA_LIMIT_UNIT]));
143 e->flags |= (1 << NFTNL_EXPR_LIMIT_UNIT);
145 if (tb[NFTA_LIMIT_BURST]) {
146 limit->burst = ntohl(mnl_attr_get_u32(tb[NFTA_LIMIT_BURST]));
147 e->flags |= (1 << NFTNL_EXPR_LIMIT_BURST);
149 if (tb[NFTA_LIMIT_TYPE]) {
150 limit->type = ntohl(mnl_attr_get_u32(tb[NFTA_LIMIT_TYPE]));
151 e->flags |= (1 << NFTNL_EXPR_LIMIT_TYPE);
153 if (tb[NFTA_LIMIT_FLAGS]) {
154 limit->flags = ntohl(mnl_attr_get_u32(tb[NFTA_LIMIT_FLAGS]));
155 e->flags |= (1 << NFTNL_EXPR_LIMIT_FLAGS);
161 static const char *get_time(uint64_t seconds, uint64_t *val)
163 static const struct {
175 for (i = 1; i < array_size(units); i++) {
176 if (seconds % units[i].size)
178 seconds /= units[i].size;
182 return units[i - 1].name;
185 static const char *limit_to_type(
enum nft_limit_type type)
191 case NFT_LIMIT_PKT_BYTES:
197 nftnl_expr_limit_snprintf(
char *buf,
size_t len,
198 uint32_t flags,
const struct nftnl_expr *e)
201 unsigned int offset = 0;
202 const char *time_unit;
206 ret = snprintf(buf, len,
"rate %"PRIu64
"/", limit->rate);
207 SNPRINTF_BUFFER_SIZE(ret, len, offset);
209 time_unit = get_time(limit->unit, &time_val);
211 ret = snprintf(buf + offset, len,
"%"PRIu64
" ", time_val);
212 SNPRINTF_BUFFER_SIZE(ret, len, offset);
215 ret = snprintf(buf + offset, len,
"%s burst %u type %s flags 0x%x ",
216 time_unit, limit->burst, limit_to_type(limit->type),
218 SNPRINTF_BUFFER_SIZE(ret, len, offset);
223 static struct attr_policy limit_attr_policy[__NFTNL_EXPR_LIMIT_MAX] = {
224 [NFTNL_EXPR_LIMIT_RATE] = { .maxlen =
sizeof(uint64_t) },
225 [NFTNL_EXPR_LIMIT_UNIT] = { .maxlen =
sizeof(uint64_t) },
226 [NFTNL_EXPR_LIMIT_BURST] = { .maxlen =
sizeof(uint32_t) },
227 [NFTNL_EXPR_LIMIT_TYPE] = { .maxlen =
sizeof(uint32_t) },
228 [NFTNL_EXPR_LIMIT_FLAGS] = { .maxlen =
sizeof(uint32_t) },
231 struct expr_ops expr_ops_limit = {
234 .nftnl_max_attr = __NFTNL_EXPR_LIMIT_MAX - 1,
235 .attr_policy = limit_attr_policy,
236 .set = nftnl_expr_limit_set,
237 .get = nftnl_expr_limit_get,
238 .parse = nftnl_expr_limit_parse,
239 .build = nftnl_expr_limit_build,
240 .output = nftnl_expr_limit_snprintf,