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 int nftnl_expr_limit_xml_parse(
struct nftnl_expr *e,
191 struct nftnl_parse_err *err)
195 uint32_t burst, type, flags;
197 if (nftnl_mxml_num_parse(tree,
"rate", MXML_DESCEND_FIRST, BASE_DEC,
198 &rate, NFTNL_TYPE_U64, NFTNL_XML_MAND, err) == 0)
199 nftnl_expr_set_u64(e, NFTNL_EXPR_LIMIT_RATE, rate);
201 if (nftnl_mxml_num_parse(tree,
"unit", MXML_DESCEND_FIRST, BASE_DEC,
202 &unit, NFTNL_TYPE_U64, NFTNL_XML_MAND, err) == 0)
203 nftnl_expr_set_u64(e, NFTNL_EXPR_LIMIT_UNIT, unit);
204 if (nftnl_mxml_num_parse(tree,
"burst", MXML_DESCEND_FIRST, BASE_DEC,
205 &burst, NFTNL_TYPE_U32, NFTNL_XML_MAND, err) == 0)
206 nftnl_expr_set_u32(e, NFTNL_EXPR_LIMIT_BURST, burst);
207 if (nftnl_mxml_num_parse(tree,
"type", MXML_DESCEND_FIRST, BASE_DEC,
208 &type, NFTNL_TYPE_U32, NFTNL_XML_MAND, err) == 0)
209 nftnl_expr_set_u32(e, NFTNL_EXPR_LIMIT_TYPE, type);
210 if (nftnl_mxml_num_parse(tree,
"flags", MXML_DESCEND_FIRST, BASE_DEC,
211 &flags, NFTNL_TYPE_U32, NFTNL_XML_MAND, err) == 0)
212 nftnl_expr_set_u32(e, NFTNL_EXPR_LIMIT_FLAGS, flags);
221 static const char *get_unit(uint64_t u)
224 case 1:
return "second";
225 case 60:
return "minute";
226 case 60 * 60:
return "hour";
227 case 60 * 60 * 24:
return "day";
228 case 60 * 60 * 24 * 7:
return "week";
233 static int nftnl_expr_limit_export(
char *buf,
size_t size,
234 const struct nftnl_expr *e,
int type)
237 NFTNL_BUF_INIT(b, buf, size);
239 if (e->flags & (1 << NFTNL_EXPR_LIMIT_RATE))
240 nftnl_buf_u64(&b, type, limit->rate, RATE);
241 if (e->flags & (1 << NFTNL_EXPR_LIMIT_UNIT))
242 nftnl_buf_u64(&b, type, limit->unit, UNIT);
243 if (e->flags & (1 << NFTNL_EXPR_LIMIT_BURST))
244 nftnl_buf_u32(&b, type, limit->burst, BURST);
245 if (e->flags & (1 << NFTNL_EXPR_LIMIT_TYPE))
246 nftnl_buf_u32(&b, type, limit->type, TYPE);
247 if (e->flags & (1 << NFTNL_EXPR_LIMIT_FLAGS))
248 nftnl_buf_u32(&b, type, limit->flags, FLAGS);
250 return nftnl_buf_done(&b);
253 static const char *limit_to_type(
enum nft_limit_type type)
259 case NFT_LIMIT_PKT_BYTES:
265 static int nftnl_expr_limit_snprintf_default(
char *buf,
size_t len,
266 const struct nftnl_expr *e)
270 return snprintf(buf, len,
"rate %"PRIu64
"/%s burst %u type %s flags 0x%x ",
271 limit->rate, get_unit(limit->unit), limit->burst,
272 limit_to_type(limit->type), limit->flags);
276 nftnl_expr_limit_snprintf(
char *buf,
size_t len, uint32_t type,
277 uint32_t flags,
const struct nftnl_expr *e)
280 case NFTNL_OUTPUT_DEFAULT:
281 return nftnl_expr_limit_snprintf_default(buf, len, e);
282 case NFTNL_OUTPUT_XML:
283 case NFTNL_OUTPUT_JSON:
284 return nftnl_expr_limit_export(buf, len, e, type);
291 struct expr_ops expr_ops_limit = {
294 .max_attr = NFTA_LIMIT_MAX,
295 .set = nftnl_expr_limit_set,
296 .get = nftnl_expr_limit_get,
297 .parse = nftnl_expr_limit_parse,
298 .build = nftnl_expr_limit_build,
299 .snprintf = nftnl_expr_limit_snprintf,
300 .xml_parse = nftnl_expr_limit_xml_parse,
301 .json_parse = nftnl_expr_limit_json_parse,