17 #include <arpa/inet.h>
19 #include <libmnl/libmnl.h>
20 #include <linux/netfilter/nf_tables.h>
21 #include <libnftnl/rule.h>
22 #include <libnftnl/expr.h>
25 enum nft_registers sreg;
26 enum nft_registers dreg;
32 nftnl_expr_lookup_set(
struct nftnl_expr *e, uint16_t type,
33 const void *data, uint32_t data_len)
38 case NFTNL_EXPR_LOOKUP_SREG:
39 lookup->sreg = *((uint32_t *)data);
41 case NFTNL_EXPR_LOOKUP_DREG:
42 lookup->dreg = *((uint32_t *)data);
44 case NFTNL_EXPR_LOOKUP_SET:
45 lookup->set_name = strdup((
const char *)data);
47 case NFTNL_EXPR_LOOKUP_SET_ID:
48 lookup->set_id = *((uint32_t *)data);
57 nftnl_expr_lookup_get(
const struct nftnl_expr *e, uint16_t type,
63 case NFTNL_EXPR_LOOKUP_SREG:
64 *data_len =
sizeof(lookup->sreg);
66 case NFTNL_EXPR_LOOKUP_DREG:
67 *data_len =
sizeof(lookup->dreg);
69 case NFTNL_EXPR_LOOKUP_SET:
70 return lookup->set_name;
71 case NFTNL_EXPR_LOOKUP_SET_ID:
72 return &lookup->set_id;
77 static int nftnl_expr_lookup_cb(
const struct nlattr *attr,
void *data)
79 const struct nlattr **tb = data;
80 int type = mnl_attr_get_type(attr);
82 if (mnl_attr_type_valid(attr, NFTA_LOOKUP_MAX) < 0)
86 case NFTA_LOOKUP_SREG:
87 case NFTA_LOOKUP_DREG:
88 case NFTA_LOOKUP_SET_ID:
89 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
93 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
103 nftnl_expr_lookup_build(
struct nlmsghdr *nlh,
const struct nftnl_expr *e)
107 if (e->flags & (1 << NFTNL_EXPR_LOOKUP_SREG))
108 mnl_attr_put_u32(nlh, NFTA_LOOKUP_SREG, htonl(lookup->sreg));
109 if (e->flags & (1 << NFTNL_EXPR_LOOKUP_DREG))
110 mnl_attr_put_u32(nlh, NFTA_LOOKUP_DREG, htonl(lookup->dreg));
111 if (e->flags & (1 << NFTNL_EXPR_LOOKUP_SET))
112 mnl_attr_put_strz(nlh, NFTA_LOOKUP_SET, lookup->set_name);
113 if (e->flags & (1 << NFTNL_EXPR_LOOKUP_SET_ID)) {
114 mnl_attr_put_u32(nlh, NFTA_LOOKUP_SET_ID,
115 htonl(lookup->set_id));
120 nftnl_expr_lookup_parse(
struct nftnl_expr *e,
struct nlattr *attr)
123 struct nlattr *tb[NFTA_LOOKUP_MAX+1] = {};
126 if (mnl_attr_parse_nested(attr, nftnl_expr_lookup_cb, tb) < 0)
129 if (tb[NFTA_LOOKUP_SREG]) {
130 lookup->sreg = ntohl(mnl_attr_get_u32(tb[NFTA_LOOKUP_SREG]));
131 e->flags |= (1 << NFTNL_EXPR_LOOKUP_SREG);
133 if (tb[NFTA_LOOKUP_DREG]) {
134 lookup->dreg = ntohl(mnl_attr_get_u32(tb[NFTA_LOOKUP_DREG]));
135 e->flags |= (1 << NFTNL_EXPR_LOOKUP_DREG);
137 if (tb[NFTA_LOOKUP_SET]) {
139 strdup(mnl_attr_get_str(tb[NFTA_LOOKUP_SET]));
140 e->flags |= (1 << NFTNL_EXPR_LOOKUP_SET);
142 if (tb[NFTA_LOOKUP_SET_ID]) {
144 ntohl(mnl_attr_get_u32(tb[NFTA_LOOKUP_SET_ID]));
145 e->flags |= (1 << NFTNL_EXPR_LOOKUP_SET_ID);
152 nftnl_expr_lookup_json_parse(
struct nftnl_expr *e, json_t *root,
153 struct nftnl_parse_err *err)
156 const char *set_name;
159 set_name = nftnl_jansson_parse_str(root,
"set", err);
160 if (set_name != NULL)
161 nftnl_expr_set_str(e, NFTNL_EXPR_LOOKUP_SET, set_name);
163 if (nftnl_jansson_parse_reg(root,
"sreg", NFTNL_TYPE_U32, &sreg, err) == 0)
164 nftnl_expr_set_u32(e, NFTNL_EXPR_LOOKUP_SREG, sreg);
166 if (nftnl_jansson_parse_reg(root,
"dreg", NFTNL_TYPE_U32, &dreg, err) == 0)
167 nftnl_expr_set_u32(e, NFTNL_EXPR_LOOKUP_DREG, dreg);
177 nftnl_expr_lookup_xml_parse(
struct nftnl_expr *e, mxml_node_t *tree,
178 struct nftnl_parse_err *err)
181 const char *set_name;
184 set_name = nftnl_mxml_str_parse(tree,
"set", MXML_DESCEND_FIRST,
185 NFTNL_XML_MAND, err);
186 if (set_name != NULL)
187 nftnl_expr_set_str(e, NFTNL_EXPR_LOOKUP_SET, set_name);
189 if (nftnl_mxml_reg_parse(tree,
"sreg", &sreg, MXML_DESCEND, NFTNL_XML_MAND,
191 nftnl_expr_set_u32(e, NFTNL_EXPR_LOOKUP_SREG, sreg);
193 if (nftnl_mxml_reg_parse(tree,
"dreg", &dreg, MXML_DESCEND, NFTNL_XML_OPT,
195 nftnl_expr_set_u32(e, NFTNL_EXPR_LOOKUP_DREG, dreg);
205 nftnl_expr_lookup_export(
char *buf,
size_t size,
206 const struct nftnl_expr *e,
int type)
209 NFTNL_BUF_INIT(b, buf, size);
211 if (e->flags & (1 << NFTNL_EXPR_LOOKUP_SET))
212 nftnl_buf_str(&b, type, l->set_name, SET);
213 if (e->flags & (1 << NFTNL_EXPR_LOOKUP_SREG))
214 nftnl_buf_u32(&b, type, l->sreg, SREG);
215 if (e->flags & (1 << NFTNL_EXPR_LOOKUP_DREG))
216 nftnl_buf_u32(&b, type, l->dreg, DREG);
218 return nftnl_buf_done(&b);
222 nftnl_expr_lookup_snprintf_default(
char *buf,
size_t size,
223 const struct nftnl_expr *e)
225 int len = size, offset = 0, ret;
228 ret = snprintf(buf, len,
"reg %u set %s ", l->sreg, l->set_name);
229 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
232 if (e->flags & (1 << NFTNL_EXPR_LOOKUP_DREG)) {
233 ret = snprintf(buf+offset, len,
"dreg %u ", l->dreg);
234 SNPRINTF_BUFFER_SIZE(ret, size, len, offset);
241 nftnl_expr_lookup_snprintf(
char *buf,
size_t size, uint32_t type,
242 uint32_t flags,
const struct nftnl_expr *e)
246 case NFTNL_OUTPUT_DEFAULT:
247 return nftnl_expr_lookup_snprintf_default(buf, size, e);
248 case NFTNL_OUTPUT_XML:
249 case NFTNL_OUTPUT_JSON:
250 return nftnl_expr_lookup_export(buf, size, e, type);
257 static void nftnl_expr_lookup_free(
const struct nftnl_expr *e)
261 xfree(lookup->set_name);
264 struct expr_ops expr_ops_lookup = {
267 .max_attr = NFTA_LOOKUP_MAX,
268 .free = nftnl_expr_lookup_free,
269 .set = nftnl_expr_lookup_set,
270 .get = nftnl_expr_lookup_get,
271 .parse = nftnl_expr_lookup_parse,
272 .build = nftnl_expr_lookup_build,
273 .snprintf = nftnl_expr_lookup_snprintf,
274 .xml_parse = nftnl_expr_lookup_xml_parse,
275 .json_parse = nftnl_expr_lookup_json_parse,