4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / helpers.c C
#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;
}