summaryrefslogtreecommitdiffstats
path: root/src/lib.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib.h')
-rw-r--r--src/lib.h1899
1 files changed, 1899 insertions, 0 deletions
diff --git a/src/lib.h b/src/lib.h
new file mode 100644
index 0000000..a5d4362
--- /dev/null
+++ b/src/lib.h
@@ -0,0 +1,1899 @@
+#ifndef _LIB_H
+#define _LIB_H
+
+#include <libmnl/libmnl.h>
+#include <stdlib.h>
+#include "linux_list.h"
+
+#define ARRAY_MAX 4096
+
+struct array {
+ void *data[ARRAY_MAX];
+ int num;
+};
+
+struct array_u8 {
+ uint8_t data[ARRAY_MAX];
+ int num;
+};
+
+struct array_u32 {
+ uint32_t data[ARRAY_MAX];
+ int num;
+};
+
+enum test_batch_type {
+ ADD_TABLE = 0,
+ SET_TABLE,
+ DEL_TABLE,
+ ADD_BASECHAIN,
+ DEL_BASECHAIN,
+ ADD_CHAIN,
+ DEL_CHAIN,
+ ADD_SET,
+ SET_SET,
+ FLUSH_SET,
+ ADD_SETELEM,
+ DEL_SETELEM,
+ DEL_SET,
+ ADD_FLOWTABLE,
+ DEL_FLOWTABLE,
+ ADD_RULE,
+ DEL_RULE,
+ ADD_OBJECT,
+ DEL_OBJECT,
+};
+
+struct test_batch_cmd {
+ struct list_head list;
+ enum test_batch_type type;
+ int lineno;
+ void *obj;
+};
+
+struct test_batch {
+ struct list_head cmd;
+ uint32_t lineno;
+ char buf[1 << 21];
+ struct mnl_socket *nl;
+ struct mnl_nlmsg_batch *batch;
+ struct {
+ int family;
+ const char *table;
+ struct rule *rule;
+ struct list_head *expr_list; /* for inner */
+ struct set *set;
+ } ctx;
+};
+
+void setup_batch(struct test_batch *batch);
+
+struct table {
+ const char *name;
+ uint32_t *nfproto;
+ uint32_t *flags;
+ uint64_t *handle;
+ const char *userdata;
+
+ /* storage */
+ uint32_t _nfproto;
+ uint32_t _flags;
+ uint64_t _handle;
+};
+
+static inline struct table *table_init(void)
+{
+ struct table *table = calloc(1, sizeof(*table));
+
+ table->nfproto = &table->_nfproto;
+ table->flags = &table->_flags;
+ table->handle = &table->_handle;
+
+ return table;
+}
+
+void free_table(struct table *table);
+
+void set_table(struct test_batch *batch, struct table *table);
+void add_table(struct test_batch *batch, struct table *table);
+void del_table(struct test_batch *batch, struct table *table);
+
+struct chain {
+ const char *table;
+ const char *name;
+ const char *type;
+ const char *dev;
+ struct array *dev_array;
+ const char *userdata;
+
+ uint32_t *family;
+ uint32_t *flags;
+ uint32_t *chain_id;
+ uint32_t *hooknum;
+ uint64_t *handle;
+ uint32_t *policy;
+ uint64_t *bytes;
+ uint64_t *pkts;
+ uint32_t *prio;
+
+ /* storage */
+ uint32_t _family;
+ uint32_t _flags;
+ uint32_t _chain_id;
+ uint32_t _hooknum;
+ uint64_t _handle;
+ uint32_t _policy;
+ uint64_t _bytes;
+ uint64_t _pkts;
+ uint32_t _prio;
+};
+
+static inline struct chain *chain_init(void)
+{
+ struct chain *c = calloc(1, sizeof(*c));
+
+ c->family = &c->_family;
+ c->flags = &c->_flags;
+ c->chain_id = &c->_chain_id;
+ c->hooknum = &c->_hooknum;
+ c->handle = &c->_handle;
+ c->policy = &c->_policy;
+ c->bytes = &c->_bytes;
+ c->pkts = &c->_pkts;
+ c->prio = &c->_prio;
+
+ return c;
+}
+
+void free_chain(struct chain *chain);
+
+void add_chain(struct test_batch *batch, struct chain *chain);
+void del_chain(struct test_batch *batch, struct chain *chain);
+void add_basechain(struct test_batch *batch, struct chain *chain);
+void del_basechain(struct test_batch *batch, struct chain *chain);
+
+struct set {
+ const char *table;
+ const char *name;
+ struct list_head expr_list;
+
+ uint32_t *family;
+ uint32_t *flags;
+ uint32_t *key_len;
+ uint32_t *key_type;
+ uint32_t *data_len;
+ uint32_t *data_type;
+ uint32_t *policy;
+ struct array_u8 *field_array;
+ uint32_t *size;
+ uint32_t *set_id;
+ uint64_t *timeout;
+ uint32_t *gc_interval;
+ const char *userdata;
+ uint32_t *obj_type;
+ uint64_t *handle;
+
+ /* storage */
+ uint32_t _family;
+ uint32_t _flags;
+ uint32_t _key_len;
+ uint32_t _key_type;
+ uint32_t _data_len;
+ uint32_t _data_type;
+ uint32_t _policy;
+ uint32_t _size;
+ uint32_t _set_id;
+ uint64_t _timeout;
+ uint32_t _gc_interval;
+ uint32_t _obj_type;
+ uint64_t _handle;
+};
+
+static inline struct set *set_init(void)
+{
+ struct set *set = calloc(1, sizeof(*set));
+
+ INIT_LIST_HEAD(&set->expr_list);
+
+ set->family = &set->_family;
+ set->flags = &set->_flags;
+ set->key_len = &set->_key_len;
+ set->key_type = &set->_key_type;
+ set->data_len = &set->_data_len;
+ set->data_type = &set->_data_type;
+ set->policy = &set->_policy;
+ set->size = &set->_size;
+ set->set_id = &set->_set_id;
+ set->timeout = &set->_timeout;
+ set->gc_interval = &set->_gc_interval;
+ set->obj_type = &set->_obj_type;
+ set->handle = &set->_handle;
+
+ return set;
+}
+
+void add_set(struct test_batch *batch, struct set *set);
+void del_set(struct test_batch *batch, struct set *set);
+void flush_set(struct test_batch *batch, struct set *set);
+void set_set(struct test_batch *batch, struct set *set);
+void free_set(struct set *set);
+
+struct elem {
+ const char *table;
+ const char *set;
+ uint32_t set_id;
+
+ const char *chain;
+ const char *objname;
+ uint8_t *userdata;
+
+ struct list_head expr_list;
+
+ uint32_t *family;
+ uint8_t *key;
+ int key_len;
+ uint8_t *key_end;
+ int key_end_len;
+ uint8_t *data;
+ int data_len;
+ uint32_t *flags;
+ uint32_t *verdict;
+ uint64_t *timeout;
+ uint64_t *expiration;
+
+ /* storage */
+ uint32_t _family;
+ uint8_t _key[16];
+ uint8_t _key_end[16];
+ uint8_t _data[64];
+ uint32_t _flags;
+ uint32_t _verdict;
+ uint64_t _timeout;
+ uint64_t _expiration;
+};
+
+static inline struct elem *elem_init(void)
+{
+ struct elem *elem = calloc(1, sizeof(*elem));
+
+ INIT_LIST_HEAD(&elem->expr_list);
+
+ elem->family = &elem->_family;
+ elem->key = elem->_key;
+ elem->key_end = elem->_key_end;
+ elem->data = elem->_data;
+ elem->flags = &elem->_flags;
+ elem->verdict = &elem->_verdict;
+ elem->timeout = &elem->_timeout;
+ elem->expiration = &elem->_expiration;
+
+ return elem;
+}
+
+void free_elem(struct elem *elem);
+
+void add_elem(struct test_batch *batch, struct elem *elem);
+void del_elem(struct test_batch *batch, struct elem *elem);
+
+struct flowtable {
+ const char *table;
+ const char *name;
+ struct array *dev_array;
+
+ uint32_t *family;
+ uint32_t *hooknum;
+ uint32_t *prio;
+ uint64_t *handle;
+
+ /* storage */
+ uint32_t _family;
+ uint32_t _hooknum;
+ uint32_t _prio;
+ uint64_t _handle;
+};
+
+static inline struct flowtable *flowtable_init(void)
+{
+ struct flowtable *f = calloc(1, sizeof(*f));
+
+ f->family = &f->_family;
+ f->hooknum = &f->_hooknum;
+ f->handle = &f->_handle;
+ f->prio = &f->_prio;
+
+ return f;
+}
+
+void add_flowtable(struct test_batch *batch, struct flowtable *flowtable);
+void del_flowtable(struct test_batch *batch, struct flowtable *flowtable);
+void free_flowtable(struct flowtable *flowtable);
+
+struct rule {
+ const char *table;
+ const char *chain;
+ uint32_t *family;
+ uint32_t *rule_id;
+ uint32_t *pos_id;
+ uint64_t *handle;
+ uint64_t *pos;
+ const char *userdata;
+
+ /* set up when parsing match/target. */
+ struct {
+ uint32_t *l4proto;
+ uint32_t *flags;
+ } compat;
+
+ struct list_head expr_list;
+
+ /* storage */
+ uint32_t _family;
+ uint32_t _rule_id;
+ uint32_t _pos_id;
+ uint64_t _handle;
+ uint64_t _pos;
+};
+
+static inline struct rule *rule_init(void)
+{
+ struct rule *rule = calloc(1, sizeof(*rule));
+
+ rule->family = &rule->_family;
+ rule->rule_id = &rule->_rule_id;
+ rule->pos_id = &rule->_pos_id;
+ rule->handle = &rule->_handle;
+ rule->pos = &rule->_pos;
+
+ INIT_LIST_HEAD(&rule->expr_list);
+
+ return rule;
+}
+
+void free_rule(struct rule *rule);
+
+void add_rule(struct test_batch *batch, struct rule *rule);
+void del_rule(struct test_batch *batch, struct rule *rule);
+
+enum expr_type {
+ INVALID = 0,
+ BITWISE,
+ BYTEORDER,
+ CMP,
+ COUNTER,
+ CONNLIMIT,
+ CT,
+ DUP,
+ DYNSET,
+ EXTHDR,
+ FIB,
+ FWD,
+ HASH,
+ INNER,
+ IMMEDIATE,
+ LAST,
+ LIMIT,
+ LOG,
+ LOOKUP,
+ MASQ,
+ MATCH,
+ META,
+ NAT,
+ NUMGEN,
+ OBJREF,
+ OSF,
+ PAYLOAD,
+ QUEUE,
+ QUOTA,
+ RANGE,
+ REDIR,
+ REJECT,
+ RT,
+ SOCKET,
+ SYNPROXY,
+ TARGET,
+ TPROXY,
+ TUNNEL,
+ XFRM,
+};
+
+struct expr {
+ struct list_head list;
+ enum expr_type type;
+};
+
+int add_expr(struct test_batch *batch, struct expr *expr);
+
+struct bitwise {
+ struct expr expr;
+
+ uint32_t *sreg;
+ uint32_t *dreg;
+ uint32_t *op;
+ uint32_t *len;
+ uint8_t *mask;
+ int mask_len;
+ uint8_t *xor;
+ int xor_len;
+ uint8_t *data;
+ int data_len;
+
+ uint32_t _sreg;
+ uint32_t _dreg;
+ uint32_t _op;
+ uint32_t _len;
+ uint8_t _mask[16];
+ uint8_t _xor[16];
+ uint8_t _data[16];
+};
+
+static inline struct bitwise *bitwise_init(void)
+{
+ struct bitwise *bitwise = calloc(1, sizeof(*bitwise));
+
+ bitwise->expr.type = BITWISE;
+
+ bitwise->sreg = &bitwise->_sreg;
+ bitwise->dreg = &bitwise->_dreg;
+ bitwise->op = &bitwise->_op;
+ bitwise->len = &bitwise->_len;
+ bitwise->mask = bitwise->_mask;
+ bitwise->xor = bitwise->_xor;
+ bitwise->data = bitwise->_data;
+
+ return bitwise;
+}
+
+static inline void free_bitwise(struct bitwise *bitwise)
+{
+ free(bitwise);
+}
+
+struct byteorder {
+ struct expr expr;
+
+ uint32_t *sreg;
+ uint32_t *dreg;
+ uint32_t *op;
+ uint32_t *len;
+ uint32_t *size;
+
+ uint32_t _sreg;
+ uint32_t _dreg;
+ uint32_t _op;
+ uint32_t _len;
+ uint32_t _size;
+};
+
+static inline struct byteorder *byteorder_init(void)
+{
+ struct byteorder *byteorder = calloc(1, sizeof(*byteorder));
+
+ byteorder->expr.type = BYTEORDER;
+
+ byteorder->sreg = &byteorder->_sreg;
+ byteorder->dreg = &byteorder->_dreg;
+ byteorder->op = &byteorder->_op;
+ byteorder->len = &byteorder->_len;
+ byteorder->size = &byteorder->_size;
+
+ return byteorder;
+}
+
+static inline void free_byteorder(struct byteorder *byteorder)
+{
+ free(byteorder);
+}
+
+struct cmp {
+ struct expr expr;
+
+ uint32_t *sreg;
+ uint32_t *op;
+ uint8_t *data;
+ int data_len;
+
+ uint32_t _sreg;
+ uint32_t _op;
+ uint8_t _data[16];
+};
+
+static inline struct cmp *cmp_init(void)
+{
+ struct cmp *cmp = calloc(1, sizeof(*cmp));
+
+ cmp->expr.type = CMP;
+
+ cmp->sreg = &cmp->_sreg;
+ cmp->op = &cmp->_op;
+ cmp->data = cmp->_data;
+
+ return cmp;
+}
+
+static inline void free_cmp(struct cmp *cmp)
+{
+ free(cmp);
+}
+
+struct connlimit {
+ struct expr expr;
+
+ uint32_t *count;
+ uint32_t *flags;
+
+ uint32_t _count;
+ uint32_t _flags;
+};
+
+static inline struct connlimit *connlimit_init(void)
+{
+ struct connlimit *connlimit = calloc(1, sizeof(*connlimit));
+
+ connlimit->expr.type = CONNLIMIT;
+
+ connlimit->count = &connlimit->_count;
+ connlimit->flags = &connlimit->_flags;
+
+ return connlimit;
+}
+
+static inline void free_connlimit(struct connlimit *connlimit)
+{
+ free(connlimit);
+}
+
+struct counter {
+ struct expr expr;
+
+ uint64_t *pkts;
+ uint64_t *bytes;
+
+ /* storage */
+ uint64_t _pkts;
+ uint64_t _bytes;
+};
+
+static inline struct counter *counter_init(void)
+{
+ struct counter *counter = calloc(1, sizeof(*counter));
+
+ counter->expr.type = COUNTER;
+
+ counter->pkts = &counter->_pkts;
+ counter->bytes = &counter->_bytes;
+
+ return counter;
+}
+
+static inline void free_counter(struct counter *counter)
+{
+ free(counter);
+}
+
+struct ct {
+ struct expr expr;
+
+ uint32_t *sreg;
+ uint32_t *dreg;
+ uint32_t *key;
+ uint8_t *dir;
+
+ uint32_t _sreg;
+ uint32_t _dreg;
+ uint32_t _key;
+ uint8_t _dir;
+};
+
+static inline struct ct *ct_init(void)
+{
+ struct ct *ct = calloc(1, sizeof(*ct));
+
+ ct->expr.type = CT;
+
+ ct->sreg = &ct->_sreg;
+ ct->dreg = &ct->_dreg;
+ ct->key = &ct->_key;
+ ct->dir = &ct->_dir;
+
+ return ct;
+}
+
+static inline void free_ct(struct ct *ct)
+{
+ free(ct);
+}
+
+struct dup {
+ struct expr expr;
+
+ uint32_t *sreg_addr;
+ uint32_t *sreg_dev;
+
+ uint32_t _sreg_addr;
+ uint32_t _sreg_dev;
+};
+
+static inline struct dup *dup_init(void)
+{
+ struct dup *dup = calloc(1, sizeof(*dup));
+
+ dup->expr.type = DUP;
+
+ dup->sreg_addr = &dup->_sreg_addr;
+ dup->sreg_dev = &dup->_sreg_dev;
+
+ return dup;
+}
+
+static inline void free_dup(struct dup *dup)
+{
+ free(dup);
+}
+
+struct dynset {
+ struct expr expr;
+
+ const char *set;
+ struct list_head expr_list;
+
+ uint32_t *set_id;
+ uint32_t *op;
+ uint32_t *sreg_key;
+ uint32_t *sreg_data;
+ uint64_t *timeout;
+ uint32_t *flags;
+ /* exprs */
+
+ /* storage */
+ uint32_t _set_id;
+ uint32_t _op;
+ uint32_t _sreg_key;
+ uint32_t _sreg_data;
+ uint64_t _timeout;
+ uint32_t _flags;
+};
+
+static inline struct dynset *dynset_init(void)
+{
+ struct dynset *dynset = calloc(1, sizeof(*dynset));
+
+ dynset->expr.type = DYNSET;
+
+ INIT_LIST_HEAD(&dynset->expr_list);
+
+ dynset->set_id = &dynset->_set_id;
+ dynset->op = &dynset->_op;
+ dynset->sreg_key= &dynset->_sreg_key;
+ dynset->sreg_data = &dynset->_sreg_data;
+ dynset->timeout = &dynset->_timeout;
+ dynset->flags = &dynset->_flags;
+
+ return dynset;
+}
+
+static inline void free_dynset(struct dynset *dynset)
+{
+ free((void *)dynset->set);
+ free(dynset);
+}
+
+struct exthdr {
+ struct expr expr;
+
+ uint32_t *sreg;
+ uint32_t *dreg;
+ uint32_t *offset;
+ uint32_t *len;
+ uint32_t *type;
+ uint32_t *op;
+ uint32_t *flags;
+
+ uint32_t _sreg;
+ uint32_t _dreg;
+ uint32_t _offset;
+ uint32_t _len;
+ uint32_t _type;
+ uint32_t _op;
+ uint32_t _flags;
+};
+
+static inline struct exthdr *exthdr_init(void)
+{
+ struct exthdr *exthdr = calloc(1, sizeof(*exthdr));
+
+ exthdr->expr.type = EXTHDR;
+
+ exthdr->sreg = &exthdr->_sreg;
+ exthdr->dreg = &exthdr->_dreg;
+ exthdr->offset = &exthdr->_offset;
+ exthdr->len = &exthdr->_len;
+ exthdr->type = &exthdr->_type;
+ exthdr->op = &exthdr->_op;
+ exthdr->flags = &exthdr->_flags;
+
+ return exthdr;
+}
+
+static inline void free_exthdr(struct exthdr *exthdr)
+{
+ free(exthdr);
+}
+
+struct fib {
+ struct expr expr;
+
+ uint32_t *flags;
+ uint32_t *result;
+ uint32_t *dreg;
+
+ /* storage */
+ uint32_t _flags;
+ uint32_t _result;
+ uint32_t _dreg;
+};
+
+static inline struct fib *fib_init(void)
+{
+ struct fib *fib = calloc(1, sizeof(*fib));
+
+ fib->expr.type = FIB;
+
+ fib->flags = &fib->_flags;
+ fib->result = &fib->_result;
+ fib->dreg = &fib->_dreg;
+
+ return fib;
+}
+
+static inline void free_fib(struct fib *fib)
+{
+ free(fib);
+}
+
+struct fwd {
+ struct expr expr;
+
+ uint32_t *sreg_addr;
+ uint32_t *sreg_dev;
+ uint32_t *nfproto;
+
+ uint32_t _sreg_addr;
+ uint32_t _sreg_dev;
+ uint32_t _nfproto;
+};
+
+static inline struct fwd *fwd_init(void)
+{
+ struct fwd *fwd = calloc(1, sizeof(*fwd));
+
+ fwd->expr.type = FWD;
+
+ fwd->sreg_addr = &fwd->_sreg_addr;
+ fwd->sreg_dev = &fwd->_sreg_dev;
+ fwd->nfproto = &fwd->_nfproto;
+
+ return fwd;
+}
+
+static inline void free_fwd(struct fwd *fwd)
+{
+ free(fwd);
+}
+
+struct hash {
+ struct expr expr;
+
+ uint32_t *type;
+ uint32_t *sreg;
+ uint32_t *dreg;
+ uint32_t *len;
+ uint32_t *modulus;
+ uint32_t *seed;
+ uint32_t *offset;
+
+ uint32_t _type;
+ uint32_t _sreg;
+ uint32_t _dreg;
+ uint32_t _len;
+ uint32_t _modulus;
+ uint32_t _seed;
+ uint32_t _offset;
+};
+
+static inline struct hash *hash_init(void)
+{
+ struct hash *hash = calloc(1, sizeof(*hash));
+
+ hash->expr.type = HASH;
+
+ hash->type = &hash->_type;
+ hash->sreg = &hash->_sreg;
+ hash->dreg = &hash->_dreg;
+ hash->len = &hash->_len;
+ hash->modulus = &hash->_modulus;
+ hash->seed = &hash->_seed;
+ hash->offset = &hash->_offset;
+
+ return hash;
+}
+
+static inline void free_hash(struct hash *hash)
+{
+ free(hash);
+}
+
+struct inner {
+ struct expr expr;
+
+ uint32_t _num;
+ uint32_t _type;
+ uint32_t _flags;
+ uint32_t _hdrsize;
+
+ uint32_t *num;
+ uint32_t *type;
+ uint32_t *flags;
+ uint32_t *hdrsize;
+
+ struct list_head expr_list;
+};
+
+static inline struct inner *inner_init(void)
+{
+ struct inner *inner = calloc(1, sizeof(*inner));
+
+ inner->expr.type = INNER;
+
+ inner->num = &inner->_num;
+ inner->type = &inner->_type;
+ inner->flags = &inner->_flags;
+ inner->hdrsize = &inner->_hdrsize;
+
+ INIT_LIST_HEAD(&inner->expr_list);
+
+ return inner;
+}
+
+void free_expr_list(struct list_head *expr_list);
+
+static inline void free_inner(struct inner *inner)
+{
+ free_expr_list(&inner->expr_list);
+ free(inner);
+}
+
+struct immediate {
+ struct expr expr;
+
+ const char *chain;
+
+ uint32_t *dreg;
+ uint32_t *chain_id;
+ uint32_t *verdict;
+ uint8_t *data;
+ int data_len;
+
+ uint32_t _dreg;
+ uint32_t _chain_id;
+ uint32_t _verdict;
+ uint8_t _data[16];
+};
+
+static inline struct immediate *immediate_init(void)
+{
+ struct immediate *imm = calloc(1, sizeof(*imm));
+
+ imm->expr.type = IMMEDIATE;
+
+ imm->dreg = &imm->_dreg;
+ imm->chain_id = &imm->_chain_id;
+ imm->verdict = &imm->_verdict;
+ imm->data = imm->_data;
+
+ return imm;
+}
+
+static inline void free_immediate(struct immediate *immediate)
+{
+ free((void *)immediate->chain);
+ free(immediate);
+}
+
+struct last {
+ struct expr expr;
+
+ uint64_t *msecs;
+ uint32_t *set;
+
+ /* storage */
+ uint64_t _msecs;
+ uint32_t _set;
+};
+
+static inline struct last *last_init(void)
+{
+ struct last *last = calloc(1, sizeof(*last));
+
+ last->expr.type = LAST;
+
+ last->msecs = &last->_msecs;
+ last->set = &last->_set;
+
+ return last;
+}
+
+static inline void free_last(struct last *last)
+{
+ free(last);
+}
+
+struct limit {
+ struct expr expr;
+
+ uint64_t *rate;
+ uint64_t *unit;
+ uint32_t *burst;
+ uint32_t *type;
+ uint32_t *flags;
+
+ /* storage */
+ uint64_t _rate;
+ uint64_t _unit;
+ uint32_t _burst;
+ uint32_t _type;
+ uint32_t _flags;
+};
+
+static inline struct limit *limit_init(void)
+{
+ struct limit *limit = calloc(1, sizeof(*limit));
+
+ limit->expr.type = LIMIT;
+
+ limit->rate = &limit->_rate;
+ limit->unit = &limit->_unit;
+ limit->burst = &limit->_burst;
+ limit->type = &limit->_type;
+ limit->flags = &limit->_flags;
+
+ return limit;
+}
+
+static inline void free_limit(struct limit *limit)
+{
+ free(limit);
+}
+
+struct log {
+ struct expr expr;
+
+ const char *prefix;
+
+ uint32_t *snaplen;
+ uint16_t *group;
+ uint16_t *qthreshold;
+ uint32_t *level;
+ uint32_t *flags;
+
+ /* storage */
+ uint32_t _snaplen;
+ uint16_t _group;
+ uint16_t _qthreshold;
+ uint32_t _level;
+ uint32_t _flags;
+};
+
+static inline struct log *log_init(void)
+{
+ struct log *log = calloc(1, sizeof(*log));
+
+ log->expr.type = LOG;
+
+ log->snaplen = &log->_snaplen;
+ log->group = &log->_group;
+ log->qthreshold = &log->_qthreshold;
+ log->level = &log->_level;
+ log->flags = &log->_flags;
+
+ return log;
+}
+
+static inline void free_log(struct log *log)
+{
+ free((void *)log->prefix);
+ free(log);
+}
+
+struct lookup {
+ struct expr expr;
+
+ const char *set;
+ uint32_t *set_id;
+ uint32_t *sreg;
+ uint32_t *dreg;
+ uint32_t *flags;
+
+ /* storage */
+ uint32_t _set_id;
+ uint32_t _sreg;
+ uint32_t _dreg;
+};
+
+static inline struct lookup *lookup_init(void)
+{
+ struct lookup *lookup = calloc(1, sizeof(*lookup));
+
+ lookup->expr.type = LOOKUP;
+
+ lookup->set_id = &lookup->_set_id;
+ lookup->sreg = &lookup->_sreg;
+ lookup->dreg = &lookup->_dreg;
+ lookup->flags = NULL; // TODO
+
+ return lookup;
+}
+
+static inline void free_lookup(struct lookup *lookup)
+{
+ free((void *)lookup->set);
+ free(lookup);
+}
+
+struct masq {
+ struct expr expr;
+
+ uint32_t *sreg_proto_min;
+ uint32_t *sreg_proto_max;
+ uint32_t *flags;
+
+ uint32_t _sreg_proto_min;
+ uint32_t _sreg_proto_max;
+ uint32_t _flags;
+};
+
+static inline struct masq *masq_init(void)
+{
+ struct masq *masq = calloc(1, sizeof(*masq));
+
+ masq->expr.type = MASQ;
+
+ masq->sreg_proto_min = &masq->_sreg_proto_min;
+ masq->sreg_proto_max = &masq->_sreg_proto_max;
+ masq->flags = &masq->_flags;
+
+ return masq;
+}
+
+static inline void free_masq(struct masq *masq)
+{
+ free(masq);
+}
+
+struct match {
+ struct expr expr;
+
+ const char *name;
+
+ uint32_t *rev;
+ uint8_t *data;
+ int data_len;
+ uint32_t *l4proto;
+ uint32_t *flags;
+
+ /* storage */
+ uint32_t _rev;
+ uint8_t _data[65536];
+ uint32_t _l4proto;
+ uint32_t _flags;
+};
+
+static inline struct match *match_init(void)
+{
+ struct match *match = calloc(1, sizeof(*match));
+
+ match->expr.type = MATCH;
+
+ match->rev = &match->_rev;
+ match->data = match->_data;
+ match->l4proto = &match->_l4proto;
+ match->flags = &match->_flags;
+
+ return match;
+}
+
+static inline void free_match(struct match *match)
+{
+ free((void *)match->name);
+ free(match);
+}
+
+struct meta {
+ struct expr expr;
+
+ uint32_t *sreg;
+ uint32_t *dreg;
+ uint32_t *key;
+
+ uint32_t _sreg;
+ uint32_t _dreg;
+ uint32_t _key;
+};
+
+static inline struct meta *meta_init(void)
+{
+ struct meta *meta = calloc(1, sizeof(*meta));
+
+ meta->expr.type = META;
+
+ meta->sreg = &meta->_sreg;
+ meta->dreg = &meta->_dreg;
+ meta->key = &meta->_key;
+
+ return meta;
+}
+
+static inline void free_meta(struct meta *meta)
+{
+ free(meta);
+}
+
+struct nat {
+ struct expr expr;
+
+ uint32_t *sreg_addr_min;
+ uint32_t *sreg_addr_max;
+ uint32_t *sreg_proto_min;
+ uint32_t *sreg_proto_max;
+ uint32_t *nfproto;
+ uint32_t *type;
+ uint32_t *flags;
+
+ uint32_t _sreg_addr_min;
+ uint32_t _sreg_addr_max;
+ uint32_t _sreg_proto_min;
+ uint32_t _sreg_proto_max;
+ uint32_t _nfproto;
+ uint32_t _type;
+ uint32_t _flags;
+};
+
+static inline struct nat *nat_init(void)
+{
+ struct nat *nat = calloc(1, sizeof(*nat));
+
+ nat->expr.type = NAT;
+
+ nat->sreg_addr_min = &nat->_sreg_addr_min;
+ nat->sreg_addr_max = &nat->_sreg_addr_max;
+ nat->sreg_proto_min = &nat->_sreg_proto_min;
+ nat->sreg_proto_max = &nat->_sreg_proto_max;
+ nat->nfproto = &nat->_nfproto;
+ nat->type = &nat->_type;
+ nat->flags = &nat->_flags;
+
+ return nat;
+}
+
+static inline void free_nat(struct nat *nat)
+{
+ free(nat);
+}
+
+struct numgen {
+ struct expr expr;
+
+ uint32_t *dreg;
+ uint32_t *modulus;
+ uint32_t *type;
+ uint32_t *offset;
+
+ uint32_t _dreg;
+ uint32_t _modulus;
+ uint32_t _type;
+ uint32_t _offset;
+};
+
+static inline struct numgen *numgen_init(void)
+{
+ struct numgen *numgen = calloc(1, sizeof(*numgen));
+
+ numgen->expr.type = NUMGEN;
+
+ numgen->dreg = &numgen->_dreg;
+ numgen->modulus = &numgen->_modulus;
+ numgen->type = &numgen->_type;
+ numgen->offset = &numgen->_offset;
+
+ return numgen;
+}
+
+static inline void free_numgen(struct numgen *numgen)
+{
+ free(numgen);
+}
+
+struct objref {
+ struct expr expr;
+
+ const char *set_name;
+ const char *name;
+
+ uint32_t *type;
+ uint32_t *sreg;
+ uint32_t *set_id;
+
+ uint32_t _type;
+ uint32_t _sreg;
+ uint32_t _set_id;
+};
+
+static inline struct objref *objref_init(void)
+{
+ struct objref *objref = calloc(1, sizeof(*objref));
+
+ objref->expr.type = OBJREF;
+
+ objref->type = &objref->_type;
+ objref->sreg = &objref->_sreg;
+ objref->set_id = &objref->_set_id;
+
+ return objref;
+}
+
+static inline void free_objref(struct objref *objref)
+{
+ free((void *)objref->set_name);
+ free((void *)objref->name);
+ free(objref);
+}
+
+struct osf {
+ struct expr expr;
+
+ uint32_t *dreg;
+ uint32_t *ttl;
+ uint32_t *flags;
+
+ uint32_t _dreg;
+ uint32_t _ttl;
+ uint32_t _flags;
+};
+
+static inline struct osf *osf_init(void)
+{
+ struct osf *osf = calloc(1, sizeof(*osf));
+
+ osf->expr.type = OSF;
+
+ osf->dreg = &osf->_dreg;
+ osf->ttl = &osf->_ttl;
+ osf->flags = &osf->_flags;
+
+ return osf;
+}
+
+static inline void free_osf(struct osf *osf)
+{
+ free(osf);
+}
+
+struct payload {
+ struct expr expr;
+
+ uint32_t *sreg;
+ uint32_t *dreg;
+ uint32_t *offset;
+ uint32_t *base;
+ uint32_t *len;
+ uint32_t *csum_type;
+ uint32_t *csum_offset;
+ uint32_t *csum_flags;
+
+ /* storage */
+ uint32_t _sreg;
+ uint32_t _dreg;
+ uint32_t _offset;
+ uint32_t _base;
+ uint32_t _len;
+ uint32_t _csum_type;
+ uint32_t _csum_offset;
+ uint32_t _csum_flags;
+};
+
+static inline struct payload *payload_init(void)
+{
+ struct payload *payload = calloc(1, sizeof(*payload));
+
+ payload->expr.type = PAYLOAD;
+
+ payload->sreg = &payload->_sreg;
+ payload->dreg = &payload->_dreg;
+ payload->offset = &payload->_offset;
+ payload->base = &payload->_base;
+ payload->len = &payload->_len;
+ payload->csum_type = &payload->_csum_type;
+ payload->csum_offset = &payload->_csum_offset;
+ payload->csum_flags = &payload->_csum_flags;
+
+ return payload;
+}
+
+static inline void free_payload(struct payload *payload)
+{
+ free(payload);
+}
+
+struct queue {
+ struct expr expr;
+
+ uint32_t *sreg_qnum;
+ uint16_t *queue_num;
+ uint16_t *queue_total;
+ uint16_t *flags;
+
+ uint32_t _sreg_qnum;
+ uint16_t _queue_num;
+ uint16_t _queue_total;
+ uint16_t _flags;
+};
+
+static inline struct queue *queue_init(void)
+{
+ struct queue *queue = calloc(1, sizeof(*queue));
+
+ queue->expr.type = QUEUE;
+
+ queue->sreg_qnum = &queue->_sreg_qnum;
+ queue->queue_num = &queue->_queue_num;
+ queue->queue_total = &queue->_queue_total;
+ queue->flags = &queue->_flags;
+
+ return queue;
+}
+
+static inline void free_queue(struct queue *queue)
+{
+ free(queue);
+}
+
+struct quota {
+ struct expr expr;
+
+ uint64_t *bytes;
+ uint64_t *consumed;
+ uint32_t *flags;
+
+ /* storage */
+ uint64_t _bytes;
+ uint64_t _consumed;
+ uint32_t _flags;
+};
+
+static inline struct quota *quota_init(void)
+{
+ struct quota *quota = calloc(1, sizeof(*quota));
+
+ quota->expr.type = QUOTA;
+
+ quota->bytes = &quota->_bytes;
+ quota->consumed = &quota->_consumed;
+ quota->flags = &quota->_flags;
+
+ return quota;
+}
+
+static inline void free_quota(struct quota *quota)
+{
+ free(quota);
+}
+
+struct range {
+ struct expr expr;
+
+ uint32_t *sreg;
+ uint32_t *op;
+ uint8_t *data_from;
+ int data_from_len;
+ uint8_t *data_to;
+ int data_to_len;
+
+ uint32_t _sreg;
+ uint32_t _op;
+ uint8_t _data_from[16];
+ uint8_t _data_to[16];
+};
+
+static inline struct range *range_init(void)
+{
+ struct range *range = calloc(1, sizeof(*range));
+
+ range->expr.type = RANGE;
+
+ range->sreg = &range->_sreg;
+ range->op = &range->_op;
+ range->data_from = range->_data_from;
+ range->data_to = range->_data_to;
+
+ return range;
+}
+
+static inline void free_range(struct range *range)
+{
+ free(range);
+}
+
+struct redir {
+ struct expr expr;
+
+ uint32_t *sreg_proto_min;
+ uint32_t *sreg_proto_max;
+ uint32_t *flags;
+
+ uint32_t _sreg_proto_min;
+ uint32_t _sreg_proto_max;
+ uint32_t _flags;
+};
+
+static inline struct redir *redir_init(void)
+{
+ struct redir *redir = calloc(1, sizeof(*redir));
+
+ redir->expr.type = REDIR;
+
+ redir->sreg_proto_min = &redir->_sreg_proto_min;
+ redir->sreg_proto_max = &redir->_sreg_proto_max;
+ redir->flags = &redir->_flags;
+
+ return redir;
+}
+
+static inline void free_redir(struct redir *redir)
+{
+ free(redir);
+}
+
+struct reject {
+ struct expr expr;
+
+ uint32_t *type;
+ uint8_t *icmp_code;
+
+ /* storage */
+ uint32_t _type;
+ uint8_t _icmp_code;
+};
+
+static inline struct reject *reject_init(void)
+{
+ struct reject *reject = calloc(1, sizeof(*reject));
+
+ reject->expr.type = REJECT;
+
+ reject->type = &reject->_type;
+ reject->icmp_code = &reject->_icmp_code;
+
+ return reject;
+}
+
+static inline void free_reject(struct reject *reject)
+{
+ free(reject);
+}
+
+struct rt {
+ struct expr expr;
+
+ uint32_t *dreg;
+ uint32_t *key;
+
+ uint32_t _dreg;
+ uint32_t _key;
+};
+
+static inline struct rt *rt_init(void)
+{
+ struct rt *rt = calloc(1, sizeof(*rt));
+
+ rt->expr.type = RT;
+
+ rt->dreg = &rt->_dreg;
+ rt->key = &rt->_key;
+
+ return rt;
+}
+
+static inline void free_rt(struct rt *rt)
+{
+ free(rt);
+}
+
+struct socket {
+ struct expr expr;
+
+ uint32_t *dreg;
+ uint32_t *key;
+ uint32_t *level;
+
+ uint32_t _dreg;
+ uint32_t _key;
+ uint32_t _level;
+};
+
+static inline struct socket *socket_init(void)
+{
+ struct socket *socket = calloc(1, sizeof(*socket));
+
+ socket->expr.type = SOCKET;
+
+ socket->dreg = &socket->_dreg;
+ socket->key = &socket->_key;
+ socket->level = &socket->_level;
+
+ return socket;
+}
+
+static inline void free_socket(struct socket *socket)
+{
+ free(socket);
+}
+
+struct synproxy {
+ struct expr expr;
+
+ uint16_t *mss;
+ uint8_t *wscale;
+ uint32_t *flags;
+
+ /* storage */
+ uint16_t _mss;
+ uint8_t _wscale;
+ uint32_t _flags;
+};
+
+static inline struct synproxy *synproxy_init(void)
+{
+ struct synproxy *synproxy = calloc(1, sizeof(*synproxy));
+
+ synproxy->expr.type = SYNPROXY;
+
+ synproxy->mss = &synproxy->_mss;
+ synproxy->wscale = &synproxy->_wscale;
+ synproxy->flags = &synproxy->_flags;
+
+ return synproxy;
+}
+
+static inline void free_synproxy(struct synproxy *synproxy)
+{
+ free(synproxy);
+}
+
+struct target {
+ struct expr expr;
+
+ const char *name;
+
+ uint32_t *rev;
+ uint8_t *data;
+ int data_len;
+ uint32_t *l4proto;
+ uint32_t *flags;
+
+ /* storage */
+ uint32_t _rev;
+ uint8_t _data[65536];
+ uint32_t _l4proto;
+ uint32_t _flags;
+};
+
+static inline struct target *target_init(void)
+{
+ struct target *target = calloc(1, sizeof(*target));
+
+ target->expr.type = TARGET;
+
+ target->rev = &target->_rev;
+ target->data = target->_data;
+ target->l4proto = &target->_l4proto;
+ target->flags = &target->_flags;
+
+ return target;
+}
+
+static void free_target(struct target *target)
+{
+ free((void *)target->name);
+ free(target);
+}
+
+struct tproxy {
+ struct expr expr;
+
+ uint32_t *nfproto;
+ uint32_t *sreg_addr;
+ uint32_t *sreg_port;
+
+ uint32_t _nfproto;
+ uint32_t _sreg_addr;
+ uint32_t _sreg_port;
+};
+
+static inline struct tproxy *tproxy_init(void)
+{
+ struct tproxy *tproxy = calloc(1, sizeof(*tproxy));
+
+ tproxy->expr.type = TPROXY;
+
+ tproxy->nfproto = &tproxy->_nfproto;
+ tproxy->sreg_addr = &tproxy->_sreg_addr;
+ tproxy->sreg_port = &tproxy->_sreg_port;
+
+ return tproxy;
+}
+
+static inline void free_tproxy(struct tproxy *tproxy)
+{
+ free(tproxy);
+}
+
+struct tunnel {
+ struct expr expr;
+
+ uint32_t *dreg;
+ uint32_t *key;
+// uint32_t *mode;
+
+ uint32_t _dreg;
+ uint32_t _key;
+//XXX uint32_t _mode;
+};
+
+static inline struct tunnel *tunnel_init(void)
+{
+ struct tunnel *tunnel = calloc(1, sizeof(*tunnel));
+
+ tunnel->expr.type = TUNNEL;
+
+ tunnel->dreg = &tunnel->_dreg;
+ tunnel->key = &tunnel->_key;
+//XXX tunnel->mode = &tunnel->_mode;
+
+ return tunnel;
+}
+
+static inline void free_tunnel(struct tunnel *tunnel)
+{
+ free(tunnel);
+}
+
+struct xfrm {
+ struct expr expr;
+
+ uint32_t *dreg;
+ uint32_t *key;
+ uint32_t *spnum;
+ uint8_t *dir;
+
+ uint32_t _dreg;
+ uint32_t _key;
+ uint32_t _spnum;
+ uint8_t _dir;
+};
+
+static inline struct xfrm *xfrm_init(void)
+{
+ struct xfrm *xfrm = calloc(1, sizeof(*xfrm));
+
+ xfrm->expr.type = XFRM;
+
+ xfrm->dreg = &xfrm->_dreg;
+ xfrm->key = &xfrm->_key;
+ xfrm->spnum = &xfrm->_spnum;
+ xfrm->dir = &xfrm->_dir;
+
+ return xfrm;
+}
+
+static inline void free_xfrm(struct xfrm *xfrm)
+{
+ free(xfrm);
+}
+
+struct ct_helper {
+ const char *name;
+ uint8_t *l4proto;
+ uint16_t *l3proto;
+
+ /* storage */
+ uint8_t _l4proto;
+ uint16_t _l3proto;
+};
+
+static inline struct ct_helper *ct_helper_init(void)
+{
+ struct ct_helper *ct_helper = calloc(1, sizeof(*ct_helper));
+
+ ct_helper->l4proto = &ct_helper->_l4proto;
+ ct_helper->l3proto = &ct_helper->_l3proto;
+
+ return ct_helper;
+}
+
+struct ct_timeout {
+ const char *name;
+ uint8_t *l4proto;
+ uint16_t *l3proto;
+ struct array_u32 *timeout_array;
+
+ /* storage */
+ uint8_t _l4proto;
+ uint16_t _l3proto;
+};
+
+static inline struct ct_timeout *ct_timeout_init(void)
+{
+ struct ct_timeout *ct_timeout = calloc(1, sizeof(*ct_timeout));
+
+ ct_timeout->l4proto = &ct_timeout->_l4proto;
+ ct_timeout->l3proto = &ct_timeout->_l3proto;
+
+ return ct_timeout;
+}
+
+struct ct_expect {
+ const char *name;
+ uint8_t *l4proto;
+ uint16_t *l3proto;
+ uint16_t *dport;
+ uint32_t *timeout;
+ uint8_t *size;
+
+ /* storage */
+ uint8_t _l4proto;
+ uint16_t _l3proto;
+ uint16_t _dport;
+ uint32_t _timeout;
+ uint8_t _size;
+};
+
+static inline struct ct_expect *ct_expect_init(void)
+{
+ struct ct_expect *ct_expect = calloc(1, sizeof(*ct_expect));
+
+ ct_expect->l4proto = &ct_expect->_l4proto;
+ ct_expect->l3proto = &ct_expect->_l3proto;
+ ct_expect->dport = &ct_expect->_dport;
+ ct_expect->timeout = &ct_expect->_timeout;
+ ct_expect->size = &ct_expect->_size;
+
+ return ct_expect;
+}
+
+struct tunnel_tmpl {
+ uint32_t *id;
+ uint32_t *flags;
+ uint16_t *sport;
+ uint16_t *dport;
+ uint8_t *tos;
+ uint8_t *ttl;
+ uint32_t *src_v4;
+ uint8_t *src_v6;
+ uint32_t *dst_v4;
+ uint8_t *dst_v6;
+ uint32_t *flowlabel;
+
+ /* storage */
+ uint32_t _id;
+ uint32_t _flags;
+ uint16_t _sport;
+ uint16_t _dport;
+ uint8_t _tos;
+ uint8_t _ttl;
+ uint32_t _src_v4;
+ uint8_t _src_v6[16];
+ uint32_t _dst_v4;
+ uint8_t _dst_v6[16];
+ uint32_t _flowlabel;
+};
+
+static inline struct tunnel_tmpl *tunnel_tmpl_init(void)
+{
+ struct tunnel_tmpl *tunnel = calloc(1, sizeof(*tunnel));
+
+ tunnel->id = &tunnel->_id;
+ tunnel->flags = &tunnel->_flags;
+ tunnel->sport = &tunnel->_sport;
+ tunnel->dport = &tunnel->_dport;
+ tunnel->tos = &tunnel->_tos;
+ tunnel->ttl = &tunnel->_ttl;
+ tunnel->src_v4 = &tunnel->_src_v4;
+ tunnel->src_v6 = tunnel->_src_v6;
+ tunnel->dst_v4 = &tunnel->_dst_v4;
+ tunnel->dst_v6 = tunnel->_dst_v6;
+ tunnel->flowlabel = &tunnel->_flowlabel;
+
+ return tunnel;
+}
+
+struct secmark {
+ char *ctx;
+};
+
+static inline struct secmark *secmark_init(void)
+{
+ struct secmark *secmark = calloc(1, sizeof(*secmark));
+
+ return secmark;
+}
+
+struct obj {
+ const char *table;
+ const char *name;
+ uint64_t *handle;
+ const char *userdata;
+ uint32_t *type;
+ uint32_t *family;
+
+ union {
+ struct counter *counter;
+ struct quota *quota;
+ struct ct_helper *ct_helper;
+ struct limit *limit;
+ struct connlimit *connlimit;
+ struct tunnel_tmpl *tun;
+ struct ct_timeout *ct_timeout;
+ struct ct_expect *ct_expect;
+ struct secmark *secmark;
+ struct synproxy *synproxy;
+ } u;
+
+ /* storage */
+ uint32_t _type;
+ uint32_t _family;
+ uint64_t _handle;
+};
+
+static inline struct obj *obj_init(void)
+{
+ struct obj *obj = calloc(1, sizeof(*obj));
+
+ obj->type = &obj->_type;
+ obj->family = &obj->_family;
+ obj->handle = &obj->_handle;
+
+ return obj;
+}
+
+void add_obj(struct test_batch *batch, struct obj *obj);
+void del_obj(struct test_batch *batch, struct obj *obj);
+void free_obj(struct obj *obj);
+
+int batch_commit(struct test_batch *batch);
+int batch_abort(struct test_batch *batch);
+
+static inline bool batch_empty(struct test_batch *batch)
+{
+ return list_empty(&batch->cmd);
+}
+
+void batch_reset(struct test_batch *batch);
+void batch_stop(struct test_batch *batch);
+
+int flush_ruleset(struct mnl_socket *nl);
+
+struct array *array_alloc(void);
+bool array_add(struct array *array, void *data);
+void array_free(struct array *array);
+
+struct array_u8 *array_u8_alloc(void);
+bool array_u8_add(struct array_u8 *array, const char *data);
+void array_u8_free(struct array_u8 *array);
+
+struct array_u32 *array_u32_alloc(void);
+bool array_u32_add(struct array_u32 *array, const char *value);
+void array_u32_free(struct array_u32 *array);
+
+bool kernel_is_tainted(void);
+int list_hooks(struct mnl_socket *nl);
+
+#endif