13 #include <arpa/inet.h>
15 #include <linux/netfilter/nf_tables.h>
18 #include <libmnl/libmnl.h>
19 #include <libnftnl/expr.h>
20 #include <libnftnl/rule.h>
23 #define NFT_RT_MAX (NFT_RT_TCPMSS + 1)
28 enum nft_registers dreg;
32 nftnl_expr_rt_set(
struct nftnl_expr *e, uint16_t type,
33 const void *data, uint32_t data_len)
38 case NFTNL_EXPR_RT_KEY:
39 rt->key = *((uint32_t *)data);
41 case NFTNL_EXPR_RT_DREG:
42 rt->dreg = *((uint32_t *)data);
51 nftnl_expr_rt_get(
const struct nftnl_expr *e, uint16_t type,
57 case NFTNL_EXPR_RT_KEY:
58 *data_len =
sizeof(rt->key);
60 case NFTNL_EXPR_RT_DREG:
61 *data_len =
sizeof(rt->dreg);
67 static int nftnl_expr_rt_cb(
const struct nlattr *attr,
void *data)
69 const struct nlattr **tb = data;
70 int type = mnl_attr_get_type(attr);
72 if (mnl_attr_type_valid(attr, NFTA_RT_MAX) < 0)
78 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
88 nftnl_expr_rt_build(
struct nlmsghdr *nlh,
const struct nftnl_expr *e)
92 if (e->flags & (1 << NFTNL_EXPR_RT_KEY))
93 mnl_attr_put_u32(nlh, NFTA_RT_KEY, htonl(rt->key));
94 if (e->flags & (1 << NFTNL_EXPR_RT_DREG))
95 mnl_attr_put_u32(nlh, NFTA_RT_DREG, htonl(rt->dreg));
99 nftnl_expr_rt_parse(
struct nftnl_expr *e,
struct nlattr *attr)
102 struct nlattr *tb[NFTA_RT_MAX+1] = {};
104 if (mnl_attr_parse_nested(attr, nftnl_expr_rt_cb, tb) < 0)
107 if (tb[NFTA_RT_KEY]) {
108 rt->key = ntohl(mnl_attr_get_u32(tb[NFTA_RT_KEY]));
109 e->flags |= (1 << NFTNL_EXPR_RT_KEY);
111 if (tb[NFTA_RT_DREG]) {
112 rt->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_RT_DREG]));
113 e->flags |= (1 << NFTNL_EXPR_RT_DREG);
119 static const char *rt_key2str_array[NFT_RT_MAX] = {
120 [NFT_RT_CLASSID] =
"classid",
121 [NFT_RT_NEXTHOP4] =
"nexthop4",
122 [NFT_RT_NEXTHOP6] =
"nexthop6",
123 [NFT_RT_TCPMSS] =
"tcpmss",
126 static const char *rt_key2str(uint8_t key)
128 if (key < NFT_RT_MAX)
129 return rt_key2str_array[key];
134 static inline int str2rt_key(
const char *str)
138 for (i = 0; i < NFT_RT_MAX; i++) {
139 if (strcmp(str, rt_key2str_array[i]) == 0)
147 static int nftnl_expr_rt_json_parse(
struct nftnl_expr *e, json_t *root,
148 struct nftnl_parse_err *err)
155 val_str = nftnl_jansson_parse_str(root,
"key", err);
156 if (val_str != NULL) {
157 val32 = str2rt_key(val_str);
159 nftnl_expr_set_u32(e, NFTNL_EXPR_RT_KEY, val32);
162 if (nftnl_jansson_node_exist(root,
"dreg")) {
163 if (nftnl_jansson_parse_reg(root,
"dreg", NFTNL_TYPE_U32, ®,
165 nftnl_expr_set_u32(e, NFTNL_EXPR_RT_DREG, reg);
176 nftnl_expr_rt_snprintf_default(
char *buf,
size_t len,
177 const struct nftnl_expr *e)
181 if (e->flags & (1 << NFTNL_EXPR_RT_DREG)) {
182 return snprintf(buf, len,
"load %s => reg %u ",
183 rt_key2str(rt->key), rt->dreg);
188 static int nftnl_expr_rt_export(
char *buf,
size_t size,
189 const struct nftnl_expr *e,
int type)
192 NFTNL_BUF_INIT(b, buf, size);
194 if (e->flags & (1 << NFTNL_EXPR_RT_DREG))
195 nftnl_buf_u32(&b, type, rt->dreg, DREG);
196 if (e->flags & (1 << NFTNL_EXPR_RT_KEY))
197 nftnl_buf_str(&b, type, rt_key2str(rt->key), KEY);
199 return nftnl_buf_done(&b);
203 nftnl_expr_rt_snprintf(
char *buf,
size_t len, uint32_t type,
204 uint32_t flags,
const struct nftnl_expr *e)
207 case NFTNL_OUTPUT_DEFAULT:
208 return nftnl_expr_rt_snprintf_default(buf, len, e);
209 case NFTNL_OUTPUT_XML:
210 case NFTNL_OUTPUT_JSON:
211 return nftnl_expr_rt_export(buf, len, e, type);
218 static bool nftnl_expr_rt_cmp(
const struct nftnl_expr *e1,
219 const struct nftnl_expr *e2)
225 if (e1->flags & (1 << NFTNL_EXPR_RT_KEY))
226 eq &= (r1->key == r2->key);
227 if (e1->flags & (1 << NFTNL_EXPR_RT_DREG))
228 eq &= (r1->dreg == r2->dreg);
233 struct expr_ops expr_ops_rt = {
236 .max_attr = NFTA_RT_MAX,
237 .cmp = nftnl_expr_rt_cmp,
238 .set = nftnl_expr_rt_set,
239 .get = nftnl_expr_rt_get,
240 .parse = nftnl_expr_rt_parse,
241 .build = nftnl_expr_rt_build,
242 .snprintf = nftnl_expr_rt_snprintf,
243 .json_parse = nftnl_expr_rt_json_parse,