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 limit->rate = *((uint64_t *)data);
43 case NFTNL_EXPR_LIMIT_UNIT:
44 limit->unit = *((uint64_t *)data);
46 case NFTNL_EXPR_LIMIT_BURST:
47 limit->burst = *((uint32_t *)data);
49 case NFTNL_EXPR_LIMIT_TYPE:
50 limit->type = *((uint32_t *)data);
52 case NFTNL_EXPR_LIMIT_FLAGS:
53 limit->flags = *((uint32_t *)data);
62 nftnl_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);
87 static 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)
114 nftnl_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));
131 nftnl_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);
163 static int nftnl_expr_limit_json_parse(
struct nftnl_expr *e, json_t *root,
164 struct nftnl_parse_err *err)
170 if (nftnl_jansson_parse_val(root,
"rate", NFTNL_TYPE_U64, &uval64, err) == 0)
171 nftnl_expr_set_u64(e, NFTNL_EXPR_LIMIT_RATE, uval64);
173 if (nftnl_jansson_parse_val(root,
"unit", NFTNL_TYPE_U64, &uval64, err) == 0)
174 nftnl_expr_set_u64(e, NFTNL_EXPR_LIMIT_UNIT, uval64);
175 if (nftnl_jansson_parse_val(root,
"burst", NFTNL_TYPE_U32, &uval32, err) == 0)
176 nftnl_expr_set_u32(e, NFTNL_EXPR_LIMIT_BURST, uval32);
177 if (nftnl_jansson_parse_val(root,
"type", NFTNL_TYPE_U32, &uval32, err) == 0)
178 nftnl_expr_set_u32(e, NFTNL_EXPR_LIMIT_TYPE, uval32);
179 if (nftnl_jansson_parse_val(root,
"flags", NFTNL_TYPE_U32, &uval32, err) == 0)
180 nftnl_expr_set_u32(e, NFTNL_EXPR_LIMIT_FLAGS, uval32);
189 static const char *get_unit(uint64_t u)
192 case 1:
return "second";
193 case 60:
return "minute";
194 case 60 * 60:
return "hour";
195 case 60 * 60 * 24:
return "day";
196 case 60 * 60 * 24 * 7:
return "week";
201 static int nftnl_expr_limit_export(
char *buf,
size_t size,
202 const struct nftnl_expr *e,
int type)
205 NFTNL_BUF_INIT(b, buf, size);
207 if (e->flags & (1 << NFTNL_EXPR_LIMIT_RATE))
208 nftnl_buf_u64(&b, type, limit->rate, RATE);
209 if (e->flags & (1 << NFTNL_EXPR_LIMIT_UNIT))
210 nftnl_buf_u64(&b, type, limit->unit, UNIT);
211 if (e->flags & (1 << NFTNL_EXPR_LIMIT_BURST))
212 nftnl_buf_u32(&b, type, limit->burst, BURST);
213 if (e->flags & (1 << NFTNL_EXPR_LIMIT_TYPE))
214 nftnl_buf_u32(&b, type, limit->type, TYPE);
215 if (e->flags & (1 << NFTNL_EXPR_LIMIT_FLAGS))
216 nftnl_buf_u32(&b, type, limit->flags, FLAGS);
218 return nftnl_buf_done(&b);
221 static const char *limit_to_type(
enum nft_limit_type type)
227 case NFT_LIMIT_PKT_BYTES:
232 static int nftnl_expr_limit_snprintf_default(
char *buf,
size_t len,
233 const struct nftnl_expr *e)
237 return snprintf(buf, len,
"rate %"PRIu64
"/%s burst %u type %s flags 0x%x ",
238 limit->rate, get_unit(limit->unit), limit->burst,
239 limit_to_type(limit->type), limit->flags);
243 nftnl_expr_limit_snprintf(
char *buf,
size_t len, uint32_t type,
244 uint32_t flags,
const struct nftnl_expr *e)
247 case NFTNL_OUTPUT_DEFAULT:
248 return nftnl_expr_limit_snprintf_default(buf, len, e);
249 case NFTNL_OUTPUT_XML:
250 case NFTNL_OUTPUT_JSON:
251 return nftnl_expr_limit_export(buf, len, e, type);
258 static bool nftnl_expr_limit_cmp(
const struct nftnl_expr *e1,
259 const struct nftnl_expr *e2)
265 if (e1->flags & (1 << NFTNL_EXPR_LIMIT_RATE))
266 eq &= (l1->rate == l2->rate);
267 if (e1->flags & (1 << NFTNL_EXPR_LIMIT_UNIT))
268 eq &= (l1->unit == l2->unit);
269 if (e1->flags & (1 << NFTNL_EXPR_LIMIT_BURST))
270 eq &= (l1->burst == l2->burst);
271 if (e1->flags & (1 << NFTNL_EXPR_LIMIT_TYPE))
272 eq &= (l1->type == l2->type);
273 if (e1->flags & (1 << NFTNL_EXPR_LIMIT_FLAGS))
274 eq &= (l1->flags == l2->flags);
279 struct expr_ops expr_ops_limit = {
282 .max_attr = NFTA_LIMIT_MAX,
283 .set = nftnl_expr_limit_set,
284 .cmp = nftnl_expr_limit_cmp,
285 .get = nftnl_expr_limit_get,
286 .parse = nftnl_expr_limit_parse,
287 .build = nftnl_expr_limit_build,
288 .snprintf = nftnl_expr_limit_snprintf,
289 .json_parse = nftnl_expr_limit_json_parse,