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;
34nftnl_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,
sizeof(limit->rate));
43 case NFTNL_EXPR_LIMIT_UNIT:
44 memcpy(&limit->unit, data,
sizeof(limit->unit));
46 case NFTNL_EXPR_LIMIT_BURST:
47 memcpy(&limit->burst, data,
sizeof(limit->burst));
49 case NFTNL_EXPR_LIMIT_TYPE:
50 memcpy(&limit->type, data,
sizeof(limit->type));
52 case NFTNL_EXPR_LIMIT_FLAGS:
53 memcpy(&limit->flags, data,
sizeof(limit->flags));
62nftnl_expr_limit_get(
const struct nftnl_expr *e, uint16_t type,
68 case NFTNL_EXPR_LIMIT_RATE:
69 *data_len =
sizeof(uint64_t);
71 case NFTNL_EXPR_LIMIT_UNIT:
72 *data_len =
sizeof(uint64_t);
74 case NFTNL_EXPR_LIMIT_BURST:
75 *data_len =
sizeof(uint32_t);
77 case NFTNL_EXPR_LIMIT_TYPE:
78 *data_len =
sizeof(uint32_t);
80 case NFTNL_EXPR_LIMIT_FLAGS:
81 *data_len =
sizeof(uint32_t);
87static int nftnl_expr_limit_cb(
const struct nlattr *attr,
void *data)
89 const struct nlattr **tb = data;
90 int type = mnl_attr_get_type(attr);
92 if (mnl_attr_type_valid(attr, NFTA_LIMIT_MAX) < 0)
98 if (mnl_attr_validate(attr, MNL_TYPE_U64) < 0)
101 case NFTA_LIMIT_BURST:
102 case NFTA_LIMIT_TYPE:
103 case NFTA_LIMIT_FLAGS:
104 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
114nftnl_expr_limit_build(
struct nlmsghdr *nlh,
const struct nftnl_expr *e)
118 if (e->flags & (1 << NFTNL_EXPR_LIMIT_RATE))
119 mnl_attr_put_u64(nlh, NFTA_LIMIT_RATE, htobe64(limit->rate));
120 if (e->flags & (1 << NFTNL_EXPR_LIMIT_UNIT))
121 mnl_attr_put_u64(nlh, NFTA_LIMIT_UNIT, htobe64(limit->unit));
122 if (e->flags & (1 << NFTNL_EXPR_LIMIT_BURST))
123 mnl_attr_put_u32(nlh, NFTA_LIMIT_BURST, htonl(limit->burst));
124 if (e->flags & (1 << NFTNL_EXPR_LIMIT_TYPE))
125 mnl_attr_put_u32(nlh, NFTA_LIMIT_TYPE, htonl(limit->type));
126 if (e->flags & (1 << NFTNL_EXPR_LIMIT_FLAGS))
127 mnl_attr_put_u32(nlh, NFTA_LIMIT_FLAGS, htonl(limit->flags));
131nftnl_expr_limit_parse(
struct nftnl_expr *e,
struct nlattr *attr)
134 struct nlattr *tb[NFTA_LIMIT_MAX+1] = {};
136 if (mnl_attr_parse_nested(attr, nftnl_expr_limit_cb, tb) < 0)
139 if (tb[NFTA_LIMIT_RATE]) {
140 limit->rate = be64toh(mnl_attr_get_u64(tb[NFTA_LIMIT_RATE]));
141 e->flags |= (1 << NFTNL_EXPR_LIMIT_RATE);
143 if (tb[NFTA_LIMIT_UNIT]) {
144 limit->unit = be64toh(mnl_attr_get_u64(tb[NFTA_LIMIT_UNIT]));
145 e->flags |= (1 << NFTNL_EXPR_LIMIT_UNIT);
147 if (tb[NFTA_LIMIT_BURST]) {
148 limit->burst = ntohl(mnl_attr_get_u32(tb[NFTA_LIMIT_BURST]));
149 e->flags |= (1 << NFTNL_EXPR_LIMIT_BURST);
151 if (tb[NFTA_LIMIT_TYPE]) {
152 limit->type = ntohl(mnl_attr_get_u32(tb[NFTA_LIMIT_TYPE]));
153 e->flags |= (1 << NFTNL_EXPR_LIMIT_TYPE);
155 if (tb[NFTA_LIMIT_FLAGS]) {
156 limit->flags = ntohl(mnl_attr_get_u32(tb[NFTA_LIMIT_FLAGS]));
157 e->flags |= (1 << NFTNL_EXPR_LIMIT_FLAGS);
163static const char *get_unit(uint64_t u)
166 case 1:
return "second";
167 case 60:
return "minute";
168 case 60 * 60:
return "hour";
169 case 60 * 60 * 24:
return "day";
170 case 60 * 60 * 24 * 7:
return "week";
175static const char *limit_to_type(
enum nft_limit_type type)
181 case NFT_LIMIT_PKT_BYTES:
187nftnl_expr_limit_snprintf(
char *buf,
size_t len,
188 uint32_t flags,
const struct nftnl_expr *e)
192 return snprintf(buf, len,
"rate %"PRIu64
"/%s burst %u type %s flags 0x%x ",
193 limit->rate, get_unit(limit->unit), limit->burst,
194 limit_to_type(limit->type), limit->flags);
197struct expr_ops expr_ops_limit = {
200 .max_attr = NFTA_LIMIT_MAX,
201 .set = nftnl_expr_limit_set,
202 .get = nftnl_expr_limit_get,
203 .parse = nftnl_expr_limit_parse,
204 .build = nftnl_expr_limit_build,
205 .output = nftnl_expr_limit_snprintf,