README.md
Rendering markdown...
#include "./helpers.h"
batch batch_init(size_t size) {
void *buf = malloc(size);
batch b = mnl_nlmsg_batch_start(buf, size);
nftnl_batch_begin(mnl_nlmsg_batch_current(b), seq++);
mnl_nlmsg_batch_next(b);
rseq = seq;
return b;
}
void batch_end(batch b) {
nftnl_batch_end(mnl_nlmsg_batch_current(b), seq);
mnl_nlmsg_batch_next(b);
}
ssize_t batch_send(batch b, sock s) { return mnl_socket_sendto(s, mnl_nlmsg_batch_head(b), mnl_nlmsg_batch_size(b)); }
void batch_free(batch b) {
void *buf = mnl_nlmsg_batch_head(b);
mnl_nlmsg_batch_stop(b);
free(buf);
}
int batch_send_and_run_callbacks(batch b, sock s, void *cb) {
batch_end(b);
if (batch_send(b, s) == -1) {
ERROR("batch_send");
return -1;
}
batch_free(b);
if (run_callbacks(s, cb, NULL) < 0) {
ERROR("run_callbacks");
return -1;
}
return 0;
}
table make_table(const char *name, uint32_t family, const void *udata, uint32_t udlen) {
table t = nftnl_table_alloc();
if (t == NULL) {
ERROR("Couldn't allocate a table");
exit(EXIT_FAILURE);
}
nftnl_table_set_str(t, NFTNL_TABLE_NAME, name);
if (udata != NULL && udlen > 0)
nftnl_table_set_data(t, NFTNL_TABLE_USERDATA, udata, udlen);
return t;
}
void batch_new_table(batch b, table t, uint32_t family) {
nlmsghdr hdr = nftnl_nlmsg_build_hdr((char *)mnl_nlmsg_batch_current(b), NFT_MSG_NEWTABLE, family, NLM_F_ACK | NLM_F_CREATE | NLM_F_APPEND, seq++);
nftnl_table_nlmsg_build_payload(hdr, t);
mnl_nlmsg_batch_next(b);
}
chain make_chain(const char *table, const char *name, uint32_t flags, uint32_t hooknum, uint32_t prio, char *type) {
chain c = nftnl_chain_alloc();
if (c == NULL) {
ERROR("Couldn't allocate a chain");
exit(EXIT_FAILURE);
}
nftnl_chain_set_str(c, NFTNL_CHAIN_TABLE, table);
nftnl_chain_set_str(c, NFTNL_CHAIN_NAME, name);
nftnl_chain_set_u32(c, NFTNL_CHAIN_FLAGS, flags);
if (type)
nftnl_chain_set_str(c, NFTNL_CHAIN_TYPE, type);
if (hooknum != -1) {
nftnl_chain_set_u32(c, NFTNL_CHAIN_HOOKNUM, hooknum);
nftnl_chain_set_u32(c, NFTNL_CHAIN_PRIO, prio);
}
return c;
}
void batch_new_chain(batch b, chain c, uint32_t family) {
nlmsghdr hdr = nftnl_nlmsg_build_hdr((char *)mnl_nlmsg_batch_current(b), NFT_MSG_NEWCHAIN, family, NLM_F_ACK | NLM_F_CREATE | NLM_F_APPEND, seq++);
nftnl_chain_nlmsg_build_payload(hdr, c);
mnl_nlmsg_batch_next(b);
}
rule make_rule(const char *table, const char *chain, expr *exprs, size_t num_exprs, const void *udata, uint32_t udlen, uint64_t handle) {
rule r = nftnl_rule_alloc();
if (r == NULL) {
ERROR("Couldn't allocate a rule");
return NULL;
}
nftnl_rule_set_str(r, NFTNL_RULE_TABLE, table);
nftnl_rule_set_str(r, NFTNL_RULE_CHAIN, chain);
for (int i = 0; i < num_exprs; ++i)
nftnl_rule_add_expr(r, exprs[i]);
if (udlen)
nftnl_rule_set_data(r, NFTNL_RULE_USERDATA, udata, udlen);
if (handle)
nftnl_rule_set_u64(r, NFTNL_RULE_HANDLE, handle);
return r;
}
void batch_new_rule(batch b, rule r, uint32_t family) {
nlmsghdr hdr = nftnl_nlmsg_build_hdr((char *)mnl_nlmsg_batch_current(b), NFT_MSG_NEWRULE, family, NLM_F_ACK | NLM_F_CREATE | NLM_F_APPEND, seq++);
nftnl_rule_nlmsg_build_payload(hdr, r);
mnl_nlmsg_batch_next(b);
}
void batch_del_rule(batch b, rule r, uint32_t family) {
nlmsghdr hdr = nftnl_nlmsg_build_hdr((char *)mnl_nlmsg_batch_current(b), NFT_MSG_DELRULE, family, NLM_F_ACK, seq++);
nftnl_rule_nlmsg_build_payload(hdr, r);
mnl_nlmsg_batch_next(b);
}
expr make_notrack_expr() { return nftnl_expr_alloc("notrack"); }
expr make_ct_set_zone_expr(uint32_t sreg) {
expr e = nftnl_expr_alloc("ct");
if (e == NULL)
return NULL;
nftnl_expr_set_u32(e, NFTNL_EXPR_CT_KEY, NFT_CT_ZONE);
nftnl_expr_set_u32(e, NFTNL_EXPR_CT_SREG, sreg);
return e;
}
expr make_queue_expr(uint16_t num, uint16_t total, uint16_t flags) {
expr e = nftnl_expr_alloc("queue");
if (e == NULL)
return NULL;
nftnl_expr_set_u16(e, NFTNL_EXPR_QUEUE_NUM, num);
if (total)
nftnl_expr_set_u16(e, NFTNL_EXPR_QUEUE_TOTAL, total);
if (flags)
nftnl_expr_set_u16(e, NFTNL_EXPR_QUEUE_FLAGS, flags);
return e;
}
expr make_cmp_expr(uint32_t sreg, uint32_t cmp_op, uint8_t data) {
expr e = nftnl_expr_alloc("cmp");
if (e == NULL)
return NULL;
nftnl_expr_set_u32(e, NFTNL_EXPR_CMP_SREG, sreg);
nftnl_expr_set_u32(e, NFTNL_EXPR_CMP_OP, cmp_op);
nftnl_expr_set_u8(e, NFTNL_EXPR_CMP_DATA, data);
return e;
}
expr make_log_expr(char *prefix) {
expr e = nftnl_expr_alloc("log");
if (e == NULL)
return NULL;
if (prefix) {
nftnl_expr_set_str(e, NFTNL_EXPR_LOG_PREFIX, prefix);
}
nftnl_expr_set_u32(e, NFTNL_EXPR_LOG_LEVEL, NFT_LOGLEVEL_AUDIT);
return e;
}
expr make_payload_expr(uint32_t base, uint32_t offset, uint32_t len, uint32_t dreg) {
expr e = nftnl_expr_alloc("payload");
if (e == NULL)
return NULL;
nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_BASE, base);
nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_OFFSET, offset);
nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_LEN, len);
nftnl_expr_set_u32(e, NFTNL_EXPR_PAYLOAD_DREG, dreg);
return e;
}
int run_callbacks(sock s, mnl_cb_t cb, void *data) {
char buf[MNL_SOCKET_BUFFER_SIZE];
int ret = 0;
while (rseq < seq) {
ret = mnl_socket_recvfrom(s, buf, sizeof(buf));
if (ret <= 0)
break;
ret = mnl_cb_run(buf, ret, rseq, mnl_socket_get_portid(s), cb, data);
if (ret < 0)
break;
rseq += ret == 0;
}
return ret;
}
nlmsghdr dump_rule(rule r, char *buf, uint32_t family) {
nlmsghdr hdr = nftnl_nlmsg_build_hdr(buf, NFT_MSG_GETRULE, family, NLM_F_ACK, seq++);
nftnl_rule_nlmsg_build_payload(hdr, r);
return hdr;
}