15 #include <arpa/inet.h>
17 #include <linux/netfilter/nf_tables.h>
18 #include <linux/netfilter/nf_log.h>
21 #include <libmnl/libmnl.h>
22 #include <libnftnl/expr.h>
23 #include <libnftnl/rule.h>
34 static int nftnl_expr_log_set(
struct nftnl_expr *e, uint16_t type,
35 const void *data, uint32_t data_len)
40 case NFTNL_EXPR_LOG_PREFIX:
41 if (log->flags & (1 << NFTNL_EXPR_LOG_PREFIX))
44 log->prefix = strdup(data);
48 case NFTNL_EXPR_LOG_GROUP:
49 log->group = *((uint16_t *)data);
51 case NFTNL_EXPR_LOG_SNAPLEN:
52 log->snaplen = *((uint32_t *)data);
54 case NFTNL_EXPR_LOG_QTHRESHOLD:
55 log->qthreshold = *((uint16_t *)data);
57 case NFTNL_EXPR_LOG_LEVEL:
58 log->level = *((uint32_t *)data);
60 case NFTNL_EXPR_LOG_FLAGS:
61 log->flags = *((uint32_t *)data);
70 nftnl_expr_log_get(
const struct nftnl_expr *e, uint16_t type,
76 case NFTNL_EXPR_LOG_PREFIX:
77 *data_len = strlen(log->prefix)+1;
79 case NFTNL_EXPR_LOG_GROUP:
80 *data_len =
sizeof(log->group);
82 case NFTNL_EXPR_LOG_SNAPLEN:
83 *data_len =
sizeof(log->snaplen);
85 case NFTNL_EXPR_LOG_QTHRESHOLD:
86 *data_len =
sizeof(log->qthreshold);
87 return &log->qthreshold;
88 case NFTNL_EXPR_LOG_LEVEL:
89 *data_len =
sizeof(log->level);
91 case NFTNL_EXPR_LOG_FLAGS:
92 *data_len =
sizeof(log->flags);
98 static int nftnl_expr_log_cb(
const struct nlattr *attr,
void *data)
100 const struct nlattr **tb = data;
101 int type = mnl_attr_get_type(attr);
103 if (mnl_attr_type_valid(attr, NFTA_LOG_MAX) < 0)
107 case NFTA_LOG_PREFIX:
108 if (mnl_attr_validate(attr, MNL_TYPE_STRING) < 0)
112 case NFTA_LOG_QTHRESHOLD:
113 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0)
116 case NFTA_LOG_SNAPLEN:
119 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
129 nftnl_expr_log_build(
struct nlmsghdr *nlh,
const struct nftnl_expr *e)
133 if (e->flags & (1 << NFTNL_EXPR_LOG_PREFIX))
134 mnl_attr_put_strz(nlh, NFTA_LOG_PREFIX, log->prefix);
135 if (e->flags & (1 << NFTNL_EXPR_LOG_GROUP))
136 mnl_attr_put_u16(nlh, NFTA_LOG_GROUP, htons(log->group));
137 if (e->flags & (1 << NFTNL_EXPR_LOG_SNAPLEN))
138 mnl_attr_put_u32(nlh, NFTA_LOG_SNAPLEN, htonl(log->snaplen));
139 if (e->flags & (1 << NFTNL_EXPR_LOG_QTHRESHOLD))
140 mnl_attr_put_u16(nlh, NFTA_LOG_QTHRESHOLD, htons(log->qthreshold));
141 if (e->flags & (1 << NFTNL_EXPR_LOG_LEVEL))
142 mnl_attr_put_u32(nlh, NFTA_LOG_LEVEL, htonl(log->level));
143 if (e->flags & (1 << NFTNL_EXPR_LOG_FLAGS))
144 mnl_attr_put_u32(nlh, NFTA_LOG_FLAGS, htonl(log->flags));
148 nftnl_expr_log_parse(
struct nftnl_expr *e,
struct nlattr *attr)
151 struct nlattr *tb[NFTA_LOG_MAX+1] = {};
153 if (mnl_attr_parse_nested(attr, nftnl_expr_log_cb, tb) < 0)
156 if (tb[NFTA_LOG_PREFIX]) {
160 log->prefix = strdup(mnl_attr_get_str(tb[NFTA_LOG_PREFIX]));
163 e->flags |= (1 << NFTNL_EXPR_LOG_PREFIX);
165 if (tb[NFTA_LOG_GROUP]) {
166 log->group = ntohs(mnl_attr_get_u16(tb[NFTA_LOG_GROUP]));
167 e->flags |= (1 << NFTNL_EXPR_LOG_GROUP);
169 if (tb[NFTA_LOG_SNAPLEN]) {
170 log->snaplen = ntohl(mnl_attr_get_u32(tb[NFTA_LOG_SNAPLEN]));
171 e->flags |= (1 << NFTNL_EXPR_LOG_SNAPLEN);
173 if (tb[NFTA_LOG_QTHRESHOLD]) {
174 log->qthreshold = ntohs(mnl_attr_get_u16(tb[NFTA_LOG_QTHRESHOLD]));
175 e->flags |= (1 << NFTNL_EXPR_LOG_QTHRESHOLD);
177 if (tb[NFTA_LOG_LEVEL]) {
178 log->level = ntohl(mnl_attr_get_u32(tb[NFTA_LOG_LEVEL]));
179 e->flags |= (1 << NFTNL_EXPR_LOG_LEVEL);
181 if (tb[NFTA_LOG_FLAGS]) {
182 log->flags = ntohl(mnl_attr_get_u32(tb[NFTA_LOG_FLAGS]));
183 e->flags |= (1 << NFTNL_EXPR_LOG_FLAGS);
189 static int nftnl_expr_log_json_parse(
struct nftnl_expr *e, json_t *root,
190 struct nftnl_parse_err *err)
194 uint32_t snaplen, level, flags;
195 uint16_t group, qthreshold;
197 prefix = nftnl_jansson_parse_str(root,
"prefix", err);
199 nftnl_expr_set_str(e, NFTNL_EXPR_LOG_PREFIX, prefix);
201 if (nftnl_jansson_parse_val(root,
"group", NFTNL_TYPE_U16, &group,
203 nftnl_expr_set_u16(e, NFTNL_EXPR_LOG_GROUP, group);
205 if (nftnl_jansson_parse_val(root,
"snaplen", NFTNL_TYPE_U32, &snaplen,
207 nftnl_expr_set_u32(e, NFTNL_EXPR_LOG_SNAPLEN, snaplen);
209 if (nftnl_jansson_parse_val(root,
"qthreshold", NFTNL_TYPE_U16,
210 &qthreshold, err) == 0)
211 nftnl_expr_set_u16(e, NFTNL_EXPR_LOG_QTHRESHOLD, qthreshold);
213 if (nftnl_jansson_parse_val(root,
"level", NFTNL_TYPE_U32, &level,
215 nftnl_expr_set_u32(e, NFTNL_EXPR_LOG_LEVEL, level);
217 if (nftnl_jansson_parse_val(root,
"flags", NFTNL_TYPE_U32, &flags,
219 nftnl_expr_set_u32(e, NFTNL_EXPR_LOG_FLAGS, flags);
228 static int nftnl_expr_log_snprintf_default(
char *buf,
size_t size,
229 const struct nftnl_expr *e)
232 int ret, offset = 0, remain = size;
234 if (e->flags & (1 << NFTNL_EXPR_LOG_PREFIX)) {
235 ret = snprintf(buf, remain,
"prefix %s ", log->prefix);
236 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
239 if (e->flags & (1 << NFTNL_EXPR_LOG_GROUP)) {
240 ret = snprintf(buf + offset, remain,
241 "group %u snaplen %u qthreshold %u ",
242 log->group, log->snaplen, log->qthreshold);
243 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
245 if (e->flags & (1 << NFTNL_EXPR_LOG_LEVEL)) {
246 ret = snprintf(buf + offset, remain,
"level %u ",
248 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
250 if (e->flags & (1 << NFTNL_EXPR_LOG_FLAGS)) {
251 if (log->flags & NF_LOG_TCPSEQ) {
252 ret = snprintf(buf + offset, remain,
"tcpseq ");
253 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
255 if (log->flags & NF_LOG_TCPOPT) {
256 ret = snprintf(buf + offset, remain,
"tcpopt ");
257 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
259 if (log->flags & NF_LOG_IPOPT) {
260 ret = snprintf(buf + offset, remain,
"ipopt ");
261 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
263 if (log->flags & NF_LOG_UID) {
264 ret = snprintf(buf + offset, remain,
"uid ");
265 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
267 if (log->flags & NF_LOG_MACDECODE) {
268 ret = snprintf(buf + offset, remain,
270 SNPRINTF_BUFFER_SIZE(ret, remain, offset);
278 static int nftnl_expr_log_export(
char *buf,
size_t size,
279 const struct nftnl_expr *e,
int type)
282 NFTNL_BUF_INIT(b, buf, size);
284 if (e->flags & (1 << NFTNL_EXPR_LOG_PREFIX))
285 nftnl_buf_str(&b, type, log->prefix, PREFIX);
286 if (e->flags & (1 << NFTNL_EXPR_LOG_GROUP))
287 nftnl_buf_u32(&b, type, log->group, GROUP);
288 if (e->flags & (1 << NFTNL_EXPR_LOG_SNAPLEN))
289 nftnl_buf_u32(&b, type, log->snaplen, SNAPLEN);
290 if (e->flags & (1 << NFTNL_EXPR_LOG_QTHRESHOLD))
291 nftnl_buf_u32(&b, type, log->qthreshold, QTHRESH);
292 if (e->flags & (1 << NFTNL_EXPR_LOG_LEVEL))
293 nftnl_buf_u32(&b, type, log->level, LEVEL);
294 if (e->flags & (1 << NFTNL_EXPR_LOG_FLAGS))
295 nftnl_buf_u32(&b, type, log->flags, FLAGS);
297 return nftnl_buf_done(&b);
301 nftnl_expr_log_snprintf(
char *buf,
size_t len, uint32_t type,
302 uint32_t flags,
const struct nftnl_expr *e)
305 case NFTNL_OUTPUT_DEFAULT:
306 return nftnl_expr_log_snprintf_default(buf, len, e);
307 case NFTNL_OUTPUT_XML:
308 case NFTNL_OUTPUT_JSON:
309 return nftnl_expr_log_export(buf, len, e, type);
316 static void nftnl_expr_log_free(
const struct nftnl_expr *e)
323 static bool nftnl_expr_log_cmp(
const struct nftnl_expr *e1,
324 const struct nftnl_expr *e2)
330 if (e1->flags & (1 << NFTNL_EXPR_LOG_SNAPLEN))
331 eq &= (l1->snaplen == l2->snaplen);
332 if (e1->flags & (1 << NFTNL_EXPR_LOG_GROUP))
333 eq &= (l1->group == l2->group);
334 if (e1->flags & (1 << NFTNL_EXPR_LOG_QTHRESHOLD))
335 eq &= (l1->qthreshold == l2->qthreshold);
336 if (e1->flags & (1 << NFTNL_EXPR_LOG_LEVEL))
337 eq &= (l1->level == l2->level);
338 if (e1->flags & (1 << NFTNL_EXPR_LOG_FLAGS))
339 eq &= (l1->flags == l2->flags);
340 if (e1->flags & (1 << NFTNL_EXPR_LOG_PREFIX))
341 eq &= !strcmp(l1->prefix, l2->prefix);
346 struct expr_ops expr_ops_log = {
349 .max_attr = NFTA_LOG_MAX,
350 .free = nftnl_expr_log_free,
351 .cmp = nftnl_expr_log_cmp,
352 .set = nftnl_expr_log_set,
353 .get = nftnl_expr_log_get,
354 .parse = nftnl_expr_log_parse,
355 .build = nftnl_expr_log_build,
356 .snprintf = nftnl_expr_log_snprintf,
357 .json_parse = nftnl_expr_log_json_parse,