summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/ct.h29
-rw-r--r--include/datatype.h156
-rw-r--r--include/erec.h64
-rw-r--r--include/expression.h323
-rw-r--r--include/exthdr.h84
-rw-r--r--include/gmputil.h42
-rw-r--r--include/headers.h119
-rw-r--r--include/linux/netfilter.h59
-rw-r--r--include/linux/netfilter/nf_conntrack_common.h152
-rw-r--r--include/linux/netfilter/nf_conntrack_tuple_common.h13
-rw-r--r--include/linux/netfilter/nf_tables.h337
-rw-r--r--include/linux/netfilter_arp.h19
-rw-r--r--include/linux/netfilter_bridge.h27
-rw-r--r--include/linux/netfilter_decnet.h72
-rw-r--r--include/linux/netfilter_ipv4.h75
-rw-r--r--include/linux/netfilter_ipv6.h72
-rw-r--r--include/list.h625
-rw-r--r--include/meta.h29
-rw-r--r--include/netlink.h60
-rw-r--r--include/nftables.h96
-rw-r--r--include/parser.h36
-rw-r--r--include/payload.h289
-rw-r--r--include/rbtree.h98
-rw-r--r--include/rule.h174
-rw-r--r--include/statement.h140
-rw-r--r--include/utils.h69
26 files changed, 3259 insertions, 0 deletions
diff --git a/include/ct.h b/include/ct.h
new file mode 100644
index 00000000..946bc297
--- /dev/null
+++ b/include/ct.h
@@ -0,0 +1,29 @@
+#ifndef _CT_H
+#define _CT_H
+
+/**
+ * struct ct_template
+ *
+ * @token: parser token for the expression
+ * @dtype: data type of the expression
+ * @len: length of the expression
+ * @byteorder: byteorder
+ */
+struct ct_template {
+ const char *token;
+ const struct datatype *dtype;
+ enum byteorder byteorder;
+ unsigned int len;
+};
+
+#define CT_TEMPLATE(__token, __dtype, __byteorder, __len) { \
+ .token = (__token), \
+ .dtype = (__dtype), \
+ .byteorder = (__byteorder), \
+ .len = (__len), \
+}
+
+extern struct expr *ct_expr_alloc(const struct location *loc,
+ enum nft_ct_keys key);
+
+#endif /* _CT_H */
diff --git a/include/datatype.h b/include/datatype.h
new file mode 100644
index 00000000..c6aeeeda
--- /dev/null
+++ b/include/datatype.h
@@ -0,0 +1,156 @@
+#ifndef _DATATYPE_H
+#define _DATATYPE_H
+
+/**
+ * enum datatypes
+ *
+ * @TYPE_INVALID: uninitialized
+ * @TYPE_VERDICT: nftables verdict
+ * @TYPE_BITMASK: bitmask
+ * @TYPE_INTEGER: integer
+ * @TYPE_STRING: string
+ * @TYPE_LLADDR: link layer address (integer subtype)
+ * @TYPE_IPADDR: IPv4 address (integer subtype)
+ * @TYPE_IP6ADDR: IPv6 address (integer subtype)
+ * @TYPE_ETHERTYPE: EtherType (integer subtype)
+ * @TYPE_ARPOP: ARP operation (integer subtype)
+ * @TYPE_INET_PROTOCOL: internet protocol (integer subtype)
+ * @TYPE_INET_SERVICE: internet service (integer subtype)
+ * @TYPE_ICMP_TYPE: ICMP type codes (integer subtype)
+ * @TYPE_TCP_FLAG: TCP flag (bitmask subtype)
+ * @TYPE_MH_TYPE: Mobility Header type (integer subtype)
+ * @TYPE_TIME: relative time
+ * @TYPE_MARK: packet mark (integer subtype)
+ * @TYPE_IFINDEX: interface index (integer subtype)
+ * @TYPE_ARPHRD: interface type (integer subtype)
+ * @TYPE_REALM: routing realm (integer subtype)
+ * @TYPE_TC_HANDLE: TC handle (integer subtype)
+ * @TYPE_UID: user ID (integer subtype)
+ * @TYPE_GID: group ID (integer subtype)
+ * @TYPE_CT_STATE: conntrack state (bitmask subtype)
+ * @TYPE_CT_DIR: conntrack direction
+ * @TYPE_CT_STATUS: conntrack status (bitmask subtype)
+ */
+enum datatypes {
+ TYPE_INVALID,
+ TYPE_VERDICT,
+ TYPE_BITMASK,
+ TYPE_INTEGER,
+ TYPE_STRING,
+ TYPE_LLADDR,
+ TYPE_IPADDR,
+ TYPE_IP6ADDR,
+ TYPE_ETHERTYPE,
+ TYPE_ARPOP,
+ TYPE_INET_PROTOCOL,
+ TYPE_INET_SERVICE,
+ TYPE_ICMP_TYPE,
+ TYPE_TCP_FLAG,
+ TYPE_MH_TYPE,
+ TYPE_TIME,
+ TYPE_MARK,
+ TYPE_IFINDEX,
+ TYPE_ARPHRD,
+ TYPE_REALM,
+ TYPE_TC_HANDLE,
+ TYPE_UID,
+ TYPE_GID,
+ TYPE_CT_STATE,
+ TYPE_CT_DIR,
+ TYPE_CT_STATUS,
+};
+
+/**
+ * enum byteorder
+ *
+ * @BYTEORDER_INVALID: uninitialized/unknown
+ * @BYTEORDER_HOST_ENDIAN: host endian
+ * @BYTEORDER_BIG_ENDIAN: big endian
+ */
+enum byteorder {
+ BYTEORDER_INVALID,
+ BYTEORDER_HOST_ENDIAN,
+ BYTEORDER_BIG_ENDIAN,
+};
+
+struct expr;
+
+/**
+ * struct datatype
+ *
+ * @type: numeric identifier
+ * @name: type name for diagnostics
+ * @basetype: basetype for subtypes, determines type compatibilty
+ * @basefmt: format string for basetype
+ * @print: function to print a constant of this type
+ * @parse: function to parse a symbol and return an expression
+ * @sym_tbl: symbol table for this type
+ */
+struct datatype {
+ enum datatypes type;
+ const char *name;
+ const struct datatype *basetype;
+ const char *basefmt;
+ void (*print)(const struct expr *expr);
+ struct error_record *(*parse)(const struct expr *sym,
+ struct expr **res);
+ const struct symbol_table *sym_tbl;
+};
+
+extern struct error_record *symbol_parse(const struct expr *sym,
+ struct expr **res);
+extern void datatype_print(const struct expr *expr);
+
+/**
+ * struct symbolic_constant - symbol <-> constant mapping
+ *
+ * @identifier: symbol
+ * @value: symbolic value
+ */
+struct symbolic_constant {
+ const char *identifier;
+ uint64_t value;
+};
+
+#define SYMBOL(id, v) { .identifier = (id), .value = (v) }
+#define SYMBOL_LIST_END (struct symbolic_constant) { }
+
+/**
+ * struct symbol_table - type construction from symbolic values
+ *
+ * @byteorder: byteorder of symbol values
+ * @size: size of symbol values
+ * @symbols: the symbols
+ */
+struct symbol_table {
+ enum byteorder byteorder;
+ unsigned int size;
+ struct symbolic_constant symbols[];
+};
+
+extern struct error_record *symbolic_constant_parse(const struct expr *sym,
+ const struct symbol_table *tbl,
+ struct expr **res);
+extern void symbolic_constant_print(const struct symbol_table *tbl,
+ const struct expr *expr);
+extern void symbol_table_print(const struct symbol_table *tbl);
+
+extern struct symbol_table *rt_symbol_table_init(const char *filename);
+extern void rt_symbol_table_free(struct symbol_table *tbl);
+
+extern const struct datatype invalid_type;
+extern const struct datatype verdict_type;
+extern const struct datatype bitmask_type;
+extern const struct datatype integer_type;
+extern const struct datatype string_type;
+extern const struct datatype lladdr_type;
+extern const struct datatype ipaddr_type;
+extern const struct datatype ip6addr_type;
+extern const struct datatype ethertype_type;
+extern const struct datatype arphrd_type;
+extern const struct datatype inet_protocol_type;
+extern const struct datatype inet_service_type;
+extern const struct datatype mark_type;
+extern const struct datatype time_type;
+
+#endif /* _DATATYPE_H */
diff --git a/include/erec.h b/include/erec.h
new file mode 100644
index 00000000..51f39588
--- /dev/null
+++ b/include/erec.h
@@ -0,0 +1,64 @@
+#ifndef _EREC_H
+#define _EREC_H
+
+#include <nftables.h>
+#include <utils.h>
+
+/**
+ * enum error_record_types
+ *
+ * @EREC_INFORMATIONAL: informational message
+ * @EREC_WARNING: warning message
+ * @EREC_ERROR: error message
+ */
+enum error_record_types {
+ EREC_INFORMATIONAL,
+ EREC_WARNING,
+ EREC_ERROR,
+};
+
+#define EREC_MSGBUFSIZE 1024
+#define EREC_LOCATIONS_MAX 3
+
+/**
+ * struct error_record
+ *
+ * @list: message queue node
+ * @type: error record type
+ * @num_locations: number of locations
+ * @locations: location(s) of error
+ * @msg: message
+ */
+struct error_record {
+ struct list_head list;
+ enum error_record_types type;
+ unsigned int num_locations;
+ struct location locations[EREC_LOCATIONS_MAX];
+ char *msg;
+};
+
+extern struct error_record *erec_vcreate(enum error_record_types type,
+ const struct location *loc,
+ const char *fmt, va_list ap)
+ __gmp_fmtstring(3, 0);
+extern struct error_record *erec_create(enum error_record_types type,
+ const struct location *loc,
+ const char *fmt, ...) __gmp_fmtstring(3, 4);
+extern void erec_add_location(struct error_record *erec,
+ const struct location *loc);
+
+#define error(loc, fmt, args...) \
+ erec_create(EREC_ERROR, (loc), (fmt), ## args)
+#define warning(loc, fmt, args...) \
+ erec_create(EREC_WARNING, (loc), (fmt), ## args)
+
+static inline void erec_queue(struct error_record *erec,
+ struct list_head *queue)
+{
+ list_add_tail(&erec->list, queue);
+}
+
+extern void erec_print(FILE *f, const struct error_record *erec);
+extern void erec_print_list(FILE *f, struct list_head *list);
+
+#endif /* _EREC_H */
diff --git a/include/expression.h b/include/expression.h
new file mode 100644
index 00000000..72585469
--- /dev/null
+++ b/include/expression.h
@@ -0,0 +1,323 @@
+#ifndef _EXPRESSION_H
+#define _EXPRESSION_H
+
+#include <stdbool.h>
+#include <gmp.h>
+#include <linux/netfilter/nf_tables.h>
+
+#include <nftables.h>
+#include <datatype.h>
+#include <utils.h>
+#include <list.h>
+
+/**
+ * enum expr_types
+ *
+ * @EXPR_INVALID: uninitialized type, should not happen
+ * @EXPR_VERDICT: nftables verdict expression
+ * @EXPR_SYMBOL: unparsed symbol
+ * @EXPR_VALUE: literal numeric or string expression
+ * @EXPR_PREFIX: prefixed expression
+ * @EXPR_RANGE: literal range
+ * @EXPR_PAYLOAD: payload expression
+ * @EXPR_EXTHDR: exthdr expression
+ * @EXPR_META: meta expression
+ * @EXPR_CT: conntrack expression
+ * @EXPR_CONCAT: concatenation
+ * @EXPR_LIST: list of expressions
+ * @EXPR_SET: literal set
+ * @EXPR_MAPPING: a single mapping (key => value)
+ * @EXPR_MAP: map operation (expr map { EXPR_MAPPING, ... })
+ * @EXPR_UNARY: byteorder conversion, generated during evaluation
+ * @EXPR_BINOP: binary operations (bitwise, shifts)
+ * @EXPR_RELATIONAL: equality and relational expressions
+ */
+enum expr_types {
+ EXPR_INVALID,
+ EXPR_VERDICT,
+ EXPR_SYMBOL,
+ EXPR_VALUE,
+ EXPR_PREFIX,
+ EXPR_RANGE,
+ EXPR_PAYLOAD,
+ EXPR_EXTHDR,
+ EXPR_META,
+ EXPR_CT,
+ EXPR_CONCAT,
+ EXPR_LIST,
+ EXPR_SET,
+ EXPR_MAPPING,
+ EXPR_MAP,
+ EXPR_UNARY,
+ EXPR_BINOP,
+ EXPR_RELATIONAL,
+};
+
+enum ops {
+ OP_INVALID,
+ /* Unary operations */
+ OP_HTON,
+ OP_NTOH,
+ /* Binary operations */
+ OP_LSHIFT,
+ OP_RSHIFT,
+ OP_AND,
+ OP_XOR,
+ OP_OR,
+ /* Relational operations */
+ OP_EQ,
+ OP_NEQ,
+ OP_LT,
+ OP_GT,
+ OP_LTE,
+ OP_GTE,
+ /* Range comparison */
+ OP_RANGE,
+ /* Flag comparison */
+ OP_FLAGCMP,
+ /* Set lookup */
+ OP_LOOKUP,
+};
+
+extern const char *expr_op_symbols[];
+
+/**
+ * struct expr_ctx - type context for symbol parsing during evaluation
+ *
+ * @dtype: expected datatype
+ * @len: expected len
+ */
+struct expr_ctx {
+ const struct datatype *dtype;
+ unsigned int len;
+};
+
+static inline void expr_set_context(struct expr_ctx *ctx,
+ const struct datatype *dtype,
+ unsigned int len)
+{
+ ctx->dtype = dtype;
+ ctx->len = len;
+}
+
+/**
+ * struct expr_ops
+ *
+ * @type: expression type
+ * @name: expression name for diagnostics
+ * @destroy: destructor, must release inner expressions
+ * @set_type: function to promote type and byteorder of inner types
+ * @print: function to print the expression
+ */
+struct expr_ops {
+ enum expr_types type;
+ const char *name;
+ void (*destroy)(struct expr *expr);
+ void (*set_type)(const struct expr *expr,
+ const struct datatype *dtype,
+ enum byteorder byteorder);
+ void (*print)(const struct expr *expr);
+};
+
+/**
+ * enum expr_flags
+ *
+ * @EXPR_F_PRIMARY: primary expression
+ * @EXPR_F_CONSTANT: constant expression
+ * @EXPR_F_SINGLETON: singleton (implies primary and constant)
+ * @EXPR_F_INTERVAL_END: set member ends an open interval
+ * @SET_F_INTERVAL: set includes ranges and/or prefix expressions
+ */
+enum expr_flags {
+ EXPR_F_PRIMARY = 0x1,
+ EXPR_F_CONSTANT = 0x2,
+ EXPR_F_SINGLETON = 0x4,
+ EXPR_F_INTERVAL_END = 0x8,
+ SET_F_INTERVAL = 0x10,
+};
+
+#include <payload.h>
+#include <exthdr.h>
+#include <meta.h>
+#include <ct.h>
+
+/**
+ * struct expr
+ *
+ * @list: list node
+ * @location: location from parser
+ * @refcnt: reference count
+ * @flags: mask of enum expr_flags
+ * @dtype: data type of expression
+ * @byteorder: byteorder of expression
+ * @len: length of expression
+ * @ops: expression ops
+ * @op: operation for unary, binary and relational expressions
+ * @union: type specific data
+ */
+struct expr {
+ struct list_head list;
+ struct location location;
+
+ unsigned int refcnt;
+ unsigned int flags;
+
+ const struct datatype *dtype;
+ enum byteorder byteorder;
+ unsigned int len;
+
+ const struct expr_ops *ops;
+ enum ops op;
+ union {
+ struct {
+ /* EXPR_SYMBOL */
+ const struct datatype *sym_type;
+ const char *identifier;
+ };
+ struct {
+ /* EXPR_VERDICT */
+ int verdict;
+ const char *chain;
+ };
+ struct {
+ /* EXPR_VALUE */
+ mpz_t value;
+ };
+ struct {
+ /* EXPR_PREFIX */
+ struct expr *expr;
+ unsigned int prefix_len;
+ };
+ struct {
+ /* EXPR_CONCAT, EXPR_LIST, EXPR_SET */
+ struct list_head expressions;
+ unsigned int size;
+ };
+ struct {
+ /* EXPR_UNARY */
+ struct expr *arg;
+ };
+ struct {
+ /* EXPR_RANGE, EXPR_BINOP, EXPR_MAPPING, EXPR_RELATIONAL */
+ struct expr *left;
+ struct expr *right;
+ };
+ struct {
+ /* EXPR_MAP */
+ struct expr *expr;
+ struct expr *mappings;
+ };
+
+ struct {
+ /* EXPR_PAYLOAD */
+ const struct payload_desc *desc;
+ const struct payload_template *tmpl;
+ enum payload_bases base;
+ unsigned int offset;
+ unsigned int flags;
+ } payload;
+ struct {
+ /* EXPR_EXTHDR */
+ const struct exthdr_desc *desc;
+ const struct payload_template *tmpl;
+ } exthdr;
+ struct {
+ /* EXPR_META */
+ enum nft_meta_keys key;
+ } meta;
+ struct {
+ /* EXPR_CT */
+ enum nft_ct_keys key;
+ } ct;
+ };
+};
+
+extern struct expr *expr_alloc(const struct location *loc,
+ const struct expr_ops *ops,
+ const struct datatype *dtype,
+ enum byteorder byteorder, unsigned int len);
+extern struct expr *expr_get(struct expr *expr);
+extern void expr_free(struct expr *expr);
+extern void expr_print(const struct expr *expr);
+extern void expr_describe(const struct expr *expr);
+
+extern const struct datatype *expr_basetype(const struct expr *expr);
+extern void expr_set_type(struct expr *expr, const struct datatype *dtype,
+ enum byteorder byteorder);
+
+struct eval_ctx;
+extern int expr_binary_error(struct eval_ctx *ctx,
+ const struct expr *e1, const struct expr *e2,
+ const char *fmt, ...) __gmp_fmtstring(4, 5);
+
+#define expr_error(ctx, expr, fmt, args...) \
+ expr_binary_error(ctx, expr, NULL, fmt, ## args)
+
+static inline bool expr_is_primary(const struct expr *expr)
+{
+ return expr->flags & EXPR_F_PRIMARY ? true : false;
+}
+
+static inline bool expr_is_constant(const struct expr *expr)
+{
+ return expr->flags & EXPR_F_CONSTANT ? true : false;
+}
+
+static inline bool expr_is_singleton(const struct expr *expr)
+{
+ return expr->flags & EXPR_F_SINGLETON ? true : false;
+}
+
+extern struct expr *unary_expr_alloc(const struct location *loc,
+ enum ops op, struct expr *arg);
+
+extern struct expr *binop_expr_alloc(const struct location *loc, enum ops op,
+ struct expr *left, struct expr *right);
+
+extern struct expr *relational_expr_alloc(const struct location *loc, enum ops op,
+ struct expr *left, struct expr *right);
+
+extern struct expr *verdict_expr_alloc(const struct location *loc,
+ int verdict, const char *chain);
+
+extern struct expr *symbol_expr_alloc(const struct location *loc,
+ const char *identifier);
+
+static inline void symbol_expr_set_type(struct expr *expr,
+ const struct datatype *dtype)
+{
+ if (expr->ops->type == EXPR_SYMBOL)
+ expr->sym_type = dtype;
+}
+
+extern struct expr *constant_expr_alloc(const struct location *loc,
+ const struct datatype *dtype,
+ enum byteorder byteorder,
+ unsigned int len, const void *data);
+extern struct expr *constant_expr_join(const struct expr *e1,
+ const struct expr *e2);
+extern struct expr *constant_expr_splice(struct expr *expr, unsigned int len);
+
+extern struct expr *prefix_expr_alloc(const struct location *loc,
+ struct expr *expr,
+ unsigned int prefix_len);
+
+extern struct expr *range_expr_alloc(const struct location *loc,
+ struct expr *low, struct expr *high);
+
+extern void compound_expr_add(struct expr *compound, struct expr *expr);
+extern void compound_expr_remove(struct expr *compound, struct expr *expr);
+
+extern struct expr *concat_expr_alloc(const struct location *loc);
+
+extern struct expr *list_expr_alloc(const struct location *loc);
+
+extern struct expr *set_expr_alloc(const struct location *loc);
+extern void set_to_intervals(struct expr *set);
+
+extern struct expr *mapping_expr_alloc(const struct location *loc,
+ struct expr *from, struct expr *to);
+extern struct expr *map_expr_alloc(const struct location *loc,
+ struct expr *arg, struct expr *list);
+
+#endif /* _EXPRESSION_H */
diff --git a/include/exthdr.h b/include/exthdr.h
new file mode 100644
index 00000000..8ef0b395
--- /dev/null
+++ b/include/exthdr.h
@@ -0,0 +1,84 @@
+#ifndef _EXTHDR_H
+#define _EXTHDR_H
+
+/**
+ * struct exthdr_desc - extension header description
+ *
+ * @name: extension header name
+ * @type: extension header protocol value
+ * @templates: header templates
+ */
+struct exthdr_desc {
+ const char *name;
+ uint8_t type;
+ struct payload_template templates[10];
+};
+
+extern struct expr *exthdr_expr_alloc(const struct location *loc,
+ const struct exthdr_desc *desc,
+ uint8_t type);
+
+extern void exthdr_init_raw(struct expr *expr, uint8_t type,
+ unsigned int offset, unsigned int len);
+
+
+enum hbh_hdr_fields {
+ HBHHDR_INVALID,
+ HBHHDR_NEXTHDR,
+ HBHHDR_HDRLENGTH,
+};
+
+enum rt_hdr_fields {
+ RTHDR_INVALID,
+ RTHDR_NEXTHDR,
+ RTHDR_HDRLENGTH,
+ RTHDR_TYPE,
+ RTHDR_SEG_LEFT,
+};
+
+enum rt0_hdr_fields {
+ RT0HDR_INVALID,
+ RT0HDR_RESERVED,
+ RT0HDR_ADDR_1,
+};
+
+enum rt2_hdr_fields {
+ RT2HDR_INVALID,
+ RT2HDR_RESERVED,
+ RT2HDR_ADDR,
+};
+
+enum frag_hdr_fields {
+ FRAGHDR_INVALID,
+ FRAGHDR_NEXTHDR,
+ FRAGHDR_RESERVED,
+ FRAGHDR_FRAG_OFF,
+ FRAGHDR_RESERVED2,
+ FRAGHDR_MFRAGS,
+ FRAGHDR_ID,
+};
+
+enum dst_hdr_fields {
+ DSTHDR_INVALID,
+ DSTHDR_NEXTHDR,
+ DSTHDR_HDRLENGTH,
+};
+
+enum mh_hdr_fields {
+ MHHDR_INVALID,
+ MHHDR_NEXTHDR,
+ MHHDR_HDRLENGTH,
+ MHHDR_TYPE,
+ MHHDR_RESERVED,
+ MHHDR_CHECKSUM,
+};
+
+extern const struct exthdr_desc exthdr_hbh;
+extern const struct exthdr_desc exthdr_rt;
+extern const struct exthdr_desc exthdr_rt0;
+extern const struct exthdr_desc exthdr_rt2;
+extern const struct exthdr_desc exthdr_frag;
+extern const struct exthdr_desc exthdr_dst;
+extern const struct exthdr_desc exthdr_mh;
+
+#endif /* _EXTHDR_H */
diff --git a/include/gmputil.h b/include/gmputil.h
new file mode 100644
index 00000000..41a6c270
--- /dev/null
+++ b/include/gmputil.h
@@ -0,0 +1,42 @@
+#ifndef _GMPUTIL_H
+#define _GMPUTIL_H
+
+#include <gmp.h>
+
+enum mpz_word_order {
+ MPZ_MSWF = 1,
+ MPZ_LSWF = -1,
+};
+
+enum mpz_byte_order {
+ MPZ_BIG_ENDIAN = 1,
+ MPZ_HOST_ENDIAN = 0,
+ MPZ_LITTLE_ENDIAN = -1,
+};
+
+extern void mpz_bitmask(mpz_t rop, unsigned int width);
+extern void mpz_init_bitmask(mpz_t rop, unsigned int width);
+extern void mpz_prefixmask(mpz_t rop, unsigned int width, unsigned int prefix_len);
+
+extern void mpz_lshift_ui(mpz_t rop, unsigned int n);
+extern void mpz_rshift_ui(mpz_t rop, unsigned int n);
+
+extern uint64_t mpz_get_uint64(const mpz_t op);
+extern uint32_t mpz_get_uint32(const mpz_t op);
+extern uint16_t mpz_get_uint16(const mpz_t op);
+extern uint8_t mpz_get_uint8(const mpz_t op);
+
+extern uint64_t mpz_get_be64(const mpz_t op);
+extern uint32_t mpz_get_be32(const mpz_t op);
+extern uint16_t mpz_get_be16(const mpz_t op);
+
+enum byteorder;
+extern void *mpz_export_data(void *data, const mpz_t op,
+ enum byteorder byteorder,
+ unsigned int len);
+extern void mpz_import_data(mpz_t rop, const void *data,
+ enum byteorder byteorder,
+ unsigned int len);
+extern void mpz_switch_byteorder(mpz_t rop, unsigned int len);
+
+#endif /* _GMPUTIL_H */
diff --git a/include/headers.h b/include/headers.h
new file mode 100644
index 00000000..be20cec0
--- /dev/null
+++ b/include/headers.h
@@ -0,0 +1,119 @@
+#ifndef _HEADERS_H
+#define _HEADERS_H
+
+#ifndef IPPROTO_UDPLITE
+# define IPPROTO_UDPLITE 136
+#endif
+
+enum tcp_hdr_flags {
+ TCP_FLAG_FIN = 0x01,
+ TCP_FLAG_SYN = 0x02,
+ TCP_FLAG_RST = 0x04,
+ TCP_FLAG_PSH = 0x08,
+ TCP_FLAG_ACK = 0x10,
+ TCP_FLAG_URG = 0x20,
+ TCP_FLAG_ECN = 0x40,
+ TCP_FLAG_CWR = 0x80,
+};
+
+struct ip_auth_hdr {
+ uint8_t nexthdr;
+ uint8_t hdrlen;
+ uint16_t reserved;
+ uint32_t spi;
+ uint32_t seq_no;
+};
+
+struct ip_esp_hdr {
+ uint32_t spi;
+ uint32_t seq_no;
+};
+
+struct ip_comp_hdr {
+ uint8_t nexthdr;
+ uint8_t flags;
+ uint16_t cpi;
+};
+
+#ifndef IPPROTO_DCCP
+# define IPPROTO_DCCP 33
+#endif
+
+struct dccp_hdr {
+ uint16_t dccph_sport,
+ dccph_dport;
+ uint8_t dccph_doff;
+ uint8_t dccph_ccval:4,
+ dccph_cscov:4;
+ uint16_t dccph_checksum;
+ uint8_t dccph_reserved:3,
+ dccph_type:4,
+ dccph_x:1;
+ uint8_t dccph_seq2;
+ uint16_t dccph_seq;
+};
+
+#ifndef IPPROTO_SCTP
+# define IPPROTO_SCTP 132
+#endif
+
+struct sctphdr {
+ uint16_t source;
+ uint16_t dest;
+ uint32_t vtag;
+ uint32_t checksum;
+};
+
+struct ipv6hdr {
+ uint8_t version:4,
+ priority:4;
+ uint8_t flow_lbl[3];
+
+ uint16_t payload_len;
+ uint8_t nexthdr;
+ uint8_t hop_limit;
+
+ struct in6_addr saddr;
+ struct in6_addr daddr;
+};
+
+struct vlan_hdr {
+ uint16_t vlan_id:12,
+ vlan_cfi:1,
+ vlan_pcp:3;
+ uint16_t vlan_type;
+};
+
+#ifndef IPPROTO_MH
+# define IPPROTO_MH 135
+#endif
+
+struct ip6_mh {
+ uint8_t ip6mh_proto;
+ uint8_t ip6mh_hdrlen;
+ uint8_t ip6mh_type;
+ uint8_t ip6mh_reserved;
+ uint16_t ip6mh_cksum;
+ /* Followed by type specific messages */
+ uint8_t data[0];
+};
+
+/* RFC 3775 */
+#define IP6_MH_TYPE_BRR 0 /* Binding Refresh Request */
+#define IP6_MH_TYPE_HOTI 1 /* HOTI Message */
+#define IP6_MH_TYPE_COTI 2 /* COTI Message */
+#define IP6_MH_TYPE_HOT 3 /* HOT Message */
+#define IP6_MH_TYPE_COT 4 /* COT Message */
+#define IP6_MH_TYPE_BU 5 /* Binding Update */
+#define IP6_MH_TYPE_BACK 6 /* Binding ACK */
+#define IP6_MH_TYPE_BERROR 7 /* Binding Error */
+/* RFC 4068 */
+#define IP6_MH_TYPE_FBU 8 /* Fast Binding Update */
+#define IP6_MH_TYPE_FBACK 9 /* Fast Binding ACK */
+#define IP6_MH_TYPE_FNA 10 /* Fast Binding Advertisement */
+/* RFC 5096 */
+#define IP6_MH_TYPE_EMH 11 /* Experimental Mobility Header */
+/* RFC 5142 */
+#define IP6_MH_TYPE_HASM 12 /* Home Agent Switch Message */
+
+#endif /* _HEADERS_H */
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
new file mode 100644
index 00000000..2eb00b6c
--- /dev/null
+++ b/include/linux/netfilter.h
@@ -0,0 +1,59 @@
+#ifndef __LINUX_NETFILTER_H
+#define __LINUX_NETFILTER_H
+
+#include <linux/types.h>
+
+
+/* Responses from hook functions. */
+#define NF_DROP 0
+#define NF_ACCEPT 1
+#define NF_STOLEN 2
+#define NF_QUEUE 3
+#define NF_REPEAT 4
+#define NF_STOP 5
+#define NF_MAX_VERDICT NF_STOP
+
+/* we overload the higher bits for encoding auxiliary data such as the queue
+ * number. Not nice, but better than additional function arguments. */
+#define NF_VERDICT_MASK 0x0000ffff
+#define NF_VERDICT_BITS 16
+
+#define NF_VERDICT_QMASK 0xffff0000
+#define NF_VERDICT_QBITS 16
+
+#define NF_QUEUE_NR(x) ((((x) << NF_VERDICT_BITS) & NF_VERDICT_QMASK) | NF_QUEUE)
+
+/* only for userspace compatibility */
+/* Generic cache responses from hook functions.
+ <= 0x2000 is used for protocol-flags. */
+#define NFC_UNKNOWN 0x4000
+#define NFC_ALTERED 0x8000
+
+enum nf_inet_hooks {
+ NF_INET_PRE_ROUTING,
+ NF_INET_LOCAL_IN,
+ NF_INET_FORWARD,
+ NF_INET_LOCAL_OUT,
+ NF_INET_POST_ROUTING,
+ NF_INET_NUMHOOKS
+};
+
+enum {
+ NFPROTO_UNSPEC = 0,
+ NFPROTO_IPV4 = 2,
+ NFPROTO_ARP = 3,
+ NFPROTO_BRIDGE = 7,
+ NFPROTO_IPV6 = 10,
+ NFPROTO_DECNET = 12,
+ NFPROTO_NUMPROTO,
+};
+
+union nf_inet_addr {
+ __u32 all[4];
+ __be32 ip;
+ __be32 ip6[4];
+ struct in_addr in;
+ struct in6_addr in6;
+};
+
+#endif /*__LINUX_NETFILTER_H*/
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h
new file mode 100644
index 00000000..27a18952
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_common.h
@@ -0,0 +1,152 @@
+#ifndef _NF_CONNTRACK_COMMON_H
+#define _NF_CONNTRACK_COMMON_H
+/* Connection state tracking for netfilter. This is separated from,
+ but required by, the NAT layer; it can also be used by an iptables
+ extension. */
+enum ip_conntrack_info
+{
+ /* Part of an established connection (either direction). */
+ IP_CT_ESTABLISHED,
+
+ /* Like NEW, but related to an existing connection, or ICMP error
+ (in either direction). */
+ IP_CT_RELATED,
+
+ /* Started a new connection to track (only
+ IP_CT_DIR_ORIGINAL); may be a retransmission. */
+ IP_CT_NEW,
+
+ /* >= this indicates reply direction */
+ IP_CT_IS_REPLY,
+
+ /* Number of distinct IP_CT types (no NEW in reply dirn). */
+ IP_CT_NUMBER = IP_CT_IS_REPLY * 2 - 1
+};
+
+#define NF_CT_STATE_INVALID_BIT (1 << 0)
+#define NF_CT_STATE_BIT(ctinfo) (1 << ((ctinfo) % IP_CT_IS_REPLY + 1))
+#define NF_CT_STATE_UNTRACKED_BIT (1 << (IP_CT_NUMBER + 1))
+
+/* Bitset representing status of connection. */
+enum ip_conntrack_status {
+ /* It's an expected connection: bit 0 set. This bit never changed */
+ IPS_EXPECTED_BIT = 0,
+ IPS_EXPECTED = (1 << IPS_EXPECTED_BIT),
+
+ /* We've seen packets both ways: bit 1 set. Can be set, not unset. */
+ IPS_SEEN_REPLY_BIT = 1,
+ IPS_SEEN_REPLY = (1 << IPS_SEEN_REPLY_BIT),
+
+ /* Conntrack should never be early-expired. */
+ IPS_ASSURED_BIT = 2,
+ IPS_ASSURED = (1 << IPS_ASSURED_BIT),
+
+ /* Connection is confirmed: originating packet has left box */
+ IPS_CONFIRMED_BIT = 3,
+ IPS_CONFIRMED = (1 << IPS_CONFIRMED_BIT),
+
+ /* Connection needs src nat in orig dir. This bit never changed. */
+ IPS_SRC_NAT_BIT = 4,
+ IPS_SRC_NAT = (1 << IPS_SRC_NAT_BIT),
+
+ /* Connection needs dst nat in orig dir. This bit never changed. */
+ IPS_DST_NAT_BIT = 5,
+ IPS_DST_NAT = (1 << IPS_DST_NAT_BIT),
+
+ /* Both together. */
+ IPS_NAT_MASK = (IPS_DST_NAT | IPS_SRC_NAT),
+
+ /* Connection needs TCP sequence adjusted. */
+ IPS_SEQ_ADJUST_BIT = 6,
+ IPS_SEQ_ADJUST = (1 << IPS_SEQ_ADJUST_BIT),
+
+ /* NAT initialization bits. */
+ IPS_SRC_NAT_DONE_BIT = 7,
+ IPS_SRC_NAT_DONE = (1 << IPS_SRC_NAT_DONE_BIT),
+
+ IPS_DST_NAT_DONE_BIT = 8,
+ IPS_DST_NAT_DONE = (1 << IPS_DST_NAT_DONE_BIT),
+
+ /* Both together */
+ IPS_NAT_DONE_MASK = (IPS_DST_NAT_DONE | IPS_SRC_NAT_DONE),
+
+ /* Connection is dying (removed from lists), can not be unset. */
+ IPS_DYING_BIT = 9,
+ IPS_DYING = (1 << IPS_DYING_BIT),
+
+ /* Connection has fixed timeout. */
+ IPS_FIXED_TIMEOUT_BIT = 10,
+ IPS_FIXED_TIMEOUT = (1 << IPS_FIXED_TIMEOUT_BIT),
+};
+
+/* Connection tracking event bits */
+enum ip_conntrack_events
+{
+ /* New conntrack */
+ IPCT_NEW_BIT = 0,
+ IPCT_NEW = (1 << IPCT_NEW_BIT),
+
+ /* Expected connection */
+ IPCT_RELATED_BIT = 1,
+ IPCT_RELATED = (1 << IPCT_RELATED_BIT),
+
+ /* Destroyed conntrack */
+ IPCT_DESTROY_BIT = 2,
+ IPCT_DESTROY = (1 << IPCT_DESTROY_BIT),
+
+ /* Timer has been refreshed */
+ IPCT_REFRESH_BIT = 3,
+ IPCT_REFRESH = (1 << IPCT_REFRESH_BIT),
+
+ /* Status has changed */
+ IPCT_STATUS_BIT = 4,
+ IPCT_STATUS = (1 << IPCT_STATUS_BIT),
+
+ /* Update of protocol info */
+ IPCT_PROTOINFO_BIT = 5,
+ IPCT_PROTOINFO = (1 << IPCT_PROTOINFO_BIT),
+
+ /* Volatile protocol info */
+ IPCT_PROTOINFO_VOLATILE_BIT = 6,
+ IPCT_PROTOINFO_VOLATILE = (1 << IPCT_PROTOINFO_VOLATILE_BIT),
+
+ /* New helper for conntrack */
+ IPCT_HELPER_BIT = 7,
+ IPCT_HELPER = (1 << IPCT_HELPER_BIT),
+
+ /* Update of helper info */
+ IPCT_HELPINFO_BIT = 8,
+ IPCT_HELPINFO = (1 << IPCT_HELPINFO_BIT),
+
+ /* Volatile helper info */
+ IPCT_HELPINFO_VOLATILE_BIT = 9,
+ IPCT_HELPINFO_VOLATILE = (1 << IPCT_HELPINFO_VOLATILE_BIT),
+
+ /* NAT info */
+ IPCT_NATINFO_BIT = 10,
+ IPCT_NATINFO = (1 << IPCT_NATINFO_BIT),
+
+ /* Counter highest bit has been set, unused */
+ IPCT_COUNTER_FILLING_BIT = 11,
+ IPCT_COUNTER_FILLING = (1 << IPCT_COUNTER_FILLING_BIT),
+
+ /* Mark is set */
+ IPCT_MARK_BIT = 12,
+ IPCT_MARK = (1 << IPCT_MARK_BIT),
+
+ /* NAT sequence adjustment */
+ IPCT_NATSEQADJ_BIT = 13,
+ IPCT_NATSEQADJ = (1 << IPCT_NATSEQADJ_BIT),
+
+ /* Secmark is set */
+ IPCT_SECMARK_BIT = 14,
+ IPCT_SECMARK = (1 << IPCT_SECMARK_BIT),
+};
+
+enum ip_conntrack_expect_events {
+ IPEXP_NEW_BIT = 0,
+ IPEXP_NEW = (1 << IPEXP_NEW_BIT),
+};
+
+
+#endif /* _NF_CONNTRACK_COMMON_H */
diff --git a/include/linux/netfilter/nf_conntrack_tuple_common.h b/include/linux/netfilter/nf_conntrack_tuple_common.h
new file mode 100644
index 00000000..8e145f0d
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_tuple_common.h
@@ -0,0 +1,13 @@
+#ifndef _NF_CONNTRACK_TUPLE_COMMON_H
+#define _NF_CONNTRACK_TUPLE_COMMON_H
+
+enum ip_conntrack_dir
+{
+ IP_CT_DIR_ORIGINAL,
+ IP_CT_DIR_REPLY,
+ IP_CT_DIR_MAX
+};
+
+#define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL)
+
+#endif /* _NF_CONNTRACK_TUPLE_COMMON_H */
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
new file mode 100644
index 00000000..b4d518e3
--- /dev/null
+++ b/include/linux/netfilter/nf_tables.h
@@ -0,0 +1,337 @@
+#ifndef _LINUX_NF_TABLES_H
+#define _LINUX_NF_TABLES_H
+
+enum nft_registers {
+ NFT_REG_VERDICT,
+ NFT_REG_1,
+ NFT_REG_2,
+ NFT_REG_3,
+ NFT_REG_4,
+ __NFT_REG_MAX
+};
+#define NFT_REG_MAX (__NFT_REG_MAX - 1)
+
+enum nft_verdicts {
+ NFT_CONTINUE = -1,
+ NFT_BREAK = -2,
+ NFT_JUMP = -3,
+ NFT_GOTO = -4,
+ NFT_RETURN = -5,
+};
+
+enum nf_tables_msg_types {
+ NFT_MSG_NEWTABLE,
+ NFT_MSG_GETTABLE,
+ NFT_MSG_DELTABLE,
+ NFT_MSG_NEWCHAIN,
+ NFT_MSG_GETCHAIN,
+ NFT_MSG_DELCHAIN,
+ NFT_MSG_NEWRULE,
+ NFT_MSG_GETRULE,
+ NFT_MSG_DELRULE,
+ NFT_MSG_MAX,
+};
+
+enum nft_list_attributes {
+ NFTA_LIST_UNPEC,
+ NFTA_LIST_ELEM,
+ __NFTA_LIST_MAX
+};
+#define NFTA_LIST_MAX (__NFTA_LIST_MAX - 1)
+
+enum nft_hook_attributes {
+ NFTA_HOOK_UNSPEC,
+ NFTA_HOOK_HOOKNUM,
+ NFTA_HOOK_PRIORITY,
+ __NFTA_HOOK_MAX
+};
+#define NFTA_HOOK_MAX (__NFTA_HOOK_MAX - 1)
+
+enum nft_table_attributes {
+ NFTA_TABLE_UNSPEC,
+ NFTA_TABLE_NAME,
+ __NFTA_TABLE_MAX
+};
+#define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1)
+
+enum nft_chain_attributes {
+ NFTA_CHAIN_UNSPEC,
+ NFTA_CHAIN_TABLE,
+ NFTA_CHAIN_NAME,
+ NFTA_CHAIN_HOOK,
+ __NFTA_CHAIN_MAX
+};
+#define NFTA_CHAIN_MAX (__NFTA_CHAIN_MAX - 1)
+
+enum nft_rule_attributes {
+ NFTA_RULE_UNSPEC,
+ NFTA_RULE_TABLE,
+ NFTA_RULE_CHAIN,
+ NFTA_RULE_HANDLE,
+ NFTA_RULE_EXPRESSIONS,
+ __NFTA_RULE_MAX
+};
+#define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1)
+
+enum nft_data_attributes {
+ NFTA_DATA_UNSPEC,
+ NFTA_DATA_VALUE,
+ NFTA_DATA_VERDICT,
+ __NFTA_DATA_MAX
+};
+#define NFTA_DATA_MAX (__NFTA_DATA_MAX - 1)
+
+enum nft_verdict_attributes {
+ NFTA_VERDICT_UNSPEC,
+ NFTA_VERDICT_CODE,
+ NFTA_VERDICT_CHAIN,
+ __NFTA_VERDICT_MAX
+};
+#define NFTA_VERDICT_MAX (__NFTA_VERDICT_MAX - 1)
+
+enum nft_expr_attributes {
+ NFTA_EXPR_UNSPEC,
+ NFTA_EXPR_NAME,
+ NFTA_EXPR_DATA,
+ __NFTA_EXPR_MAX
+};
+#define NFTA_EXPR_MAX (__NFTA_EXPR_MAX - 1)
+
+enum nft_immediate_attributes {
+ NFTA_IMMEDIATE_UNSPEC,
+ NFTA_IMMEDIATE_DREG,
+ NFTA_IMMEDIATE_DATA,
+ __NFTA_IMMEDIATE_MAX
+};
+#define NFTA_IMMEDIATE_MAX (__NFTA_IMMEDIATE_MAX - 1)
+
+enum nft_bitwise_attributes {
+ NFTA_BITWISE_UNSPEC,
+ NFTA_BITWISE_SREG,
+ NFTA_BITWISE_DREG,
+ NFTA_BITWISE_LEN,
+ NFTA_BITWISE_MASK,
+ NFTA_BITWISE_XOR,
+ __NFTA_BITWISE_MAX
+};
+#define NFTA_BITWISE_MAX (__NFTA_BITWISE_MAX - 1)
+
+enum nft_byteorder_ops {
+ NFT_BYTEORDER_NTOH,
+ NFT_BYTEORDER_HTON,
+};
+
+enum nft_byteorder_attributes {
+ NFTA_BYTEORDER_UNSPEC,
+ NFTA_BYTEORDER_SREG,
+ NFTA_BYTEORDER_DREG,
+ NFTA_BYTEORDER_OP,
+ NFTA_BYTEORDER_LEN,
+ NFTA_BYTEORDER_SIZE,
+ __NFTA_BYTEORDER_MAX
+};
+#define NFTA_BYTEORDER_MAX (__NFTA_BYTEORDER_MAX - 1)
+
+enum nft_cmp_ops {
+ NFT_CMP_EQ,
+ NFT_CMP_NEQ,
+ NFT_CMP_LT,
+ NFT_CMP_LTE,
+ NFT_CMP_GT,
+ NFT_CMP_GTE,
+};
+
+enum nft_cmp_attributes {
+ NFTA_CMP_UNSPEC,
+ NFTA_CMP_SREG,
+ NFTA_CMP_OP,
+ NFTA_CMP_DATA,
+ __NFTA_CMP_MAX
+};
+#define NFTA_CMP_MAX (__NFTA_CMP_MAX - 1)
+
+enum nft_set_elem_flags {
+ NFT_SE_INTERVAL_END = 0x1,
+};
+
+enum nft_set_elem_attributes {
+ NFTA_SE_UNSPEC,
+ NFTA_SE_KEY,
+ NFTA_SE_DATA,
+ NFTA_SE_FLAGS,
+ __NFTA_SE_MAX
+};
+#define NFTA_SE_MAX (__NFTA_SE_MAX - 1)
+
+enum nft_set_flags {
+ NFT_SET_INTERVAL = 0x1,
+ NFT_SET_MAP = 0x2,
+};
+
+enum nft_set_attributes {
+ NFTA_SET_UNSPEC,
+ NFTA_SET_FLAGS,
+ NFTA_SET_SREG,
+ NFTA_SET_DREG,
+ NFTA_SET_KLEN,
+ NFTA_SET_ELEMENTS,
+ __NFTA_SET_MAX
+};
+#define NFTA_SET_MAX (__NFTA_SET_MAX - 1)
+
+enum nft_hash_flags {
+ NFT_HASH_MAP = 0x1,
+};
+
+enum nft_hash_elem_attributes {
+ NFTA_HE_UNSPEC,
+ NFTA_HE_KEY,
+ NFTA_HE_DATA,
+ __NFTA_HE_MAX
+};
+#define NFTA_HE_MAX (__NFTA_HE_MAX - 1)
+
+enum nft_hash_attributes {
+ NFTA_HASH_UNSPEC,
+ NFTA_HASH_FLAGS,
+ NFTA_HASH_SREG,
+ NFTA_HASH_DREG,
+ NFTA_HASH_KLEN,
+ NFTA_HASH_ELEMENTS,
+ __NFTA_HASH_MAX
+};
+#define NFTA_HASH_MAX (__NFTA_HASH_MAX - 1)
+
+enum nft_payload_bases {
+ NFT_PAYLOAD_LL_HEADER,
+ NFT_PAYLOAD_NETWORK_HEADER,
+ NFT_PAYLOAD_TRANSPORT_HEADER,
+};
+
+enum nft_payload_attributes {
+ NFTA_PAYLOAD_UNSPEC,
+ NFTA_PAYLOAD_DREG,
+ NFTA_PAYLOAD_BASE,
+ NFTA_PAYLOAD_OFFSET,
+ NFTA_PAYLOAD_LEN,
+ __NFTA_PAYLOAD_MAX
+};
+#define NFTA_PAYLOAD_MAX (__NFTA_PAYLOAD_MAX - 1)
+
+enum nft_exthdr_attributes {
+ NFTA_EXTHDR_UNSPEC,
+ NFTA_EXTHDR_DREG,
+ NFTA_EXTHDR_TYPE,
+ NFTA_EXTHDR_OFFSET,
+ NFTA_EXTHDR_LEN,
+ __NFTA_EXTHDR_MAX
+};
+#define NFTA_EXTHDR_MAX (__NFTA_EXTHDR_MAX - 1)
+
+enum nft_meta_keys {
+ NFT_META_LEN,
+ NFT_META_PROTOCOL,
+ NFT_META_PRIORITY,
+ NFT_META_MARK,
+ NFT_META_IIF,
+ NFT_META_OIF,
+ NFT_META_IIFNAME,
+ NFT_META_OIFNAME,
+ NFT_META_IIFTYPE,
+ NFT_META_OIFTYPE,
+ NFT_META_SKUID,
+ NFT_META_SKGID,
+ NFT_META_NFTRACE,
+ NFT_META_RTCLASSID,
+ NFT_META_SECMARK,
+};
+
+enum nft_meta_attributes {
+ NFTA_META_UNSPEC,
+ NFTA_META_DREG,
+ NFTA_META_KEY,
+ __NFTA_META_MAX
+};
+#define NFTA_META_MAX (__NFTA_META_MAX - 1)
+
+enum nft_ct_keys {
+ NFT_CT_STATE,
+ NFT_CT_DIRECTION,
+ NFT_CT_STATUS,
+ NFT_CT_MARK,
+ NFT_CT_SECMARK,
+ NFT_CT_EXPIRATION,
+ NFT_CT_HELPER,
+ NFT_CT_L3PROTO,
+ NFT_CT_SADDR,
+ NFT_CT_DADDR,
+ NFT_CT_PROTOCOL,
+ NFT_CT_PROTO_SRC,
+ NFT_CT_PROTO_DST,
+};
+
+enum nft_ct_attributes {
+ NFTA_CT_UNSPEC,
+ NFTA_CT_DREG,
+ NFTA_CT_KEY,
+ NFTA_CT_DIRECTION,
+ __NFTA_CT_MAX
+};
+#define NFTA_CT_MAX (__NFTA_CT_MAX - 1)
+
+enum nft_limit_attributes {
+ NFTA_LIMIT_UNSPEC,
+ NFTA_LIMIT_RATE,
+ NFTA_LIMIT_DEPTH,
+ __NFTA_LIMIT_MAX
+};
+#define NFTA_LIMIT_MAX (__NFTA_LIMIT_MAX - 1)
+
+enum nft_counter_attributes {
+ NFTA_COUNTER_UNSPEC,
+ NFTA_COUNTER_BYTES,
+ NFTA_COUNTER_PACKETS,
+ __NFTA_COUNTER_MAX
+};
+#define NFTA_COUNTER_MAX (__NFTA_COUNTER_MAX - 1)
+
+enum nft_log_attributes {
+ NFTA_LOG_UNSPEC,
+ NFTA_LOG_GROUP,
+ NFTA_LOG_PREFIX,
+ NFTA_LOG_SNAPLEN,
+ NFTA_LOG_QTHRESHOLD,
+ __NFTA_LOG_MAX
+};
+#define NFTA_LOG_MAX (__NFTA_LOG_MAX - 1)
+
+enum nft_reject_types {
+ NFT_REJECT_ICMP_UNREACH,
+ NFT_REJECT_TCP_RST,
+};
+
+enum nft_reject_attributes {
+ NFTA_REJECT_UNSPEC,
+ NFTA_REJECT_TYPE,
+ NFTA_REJECT_ICMP_CODE,
+ __NFTA_REJECT_MAX
+};
+#define NFTA_REJECT_MAX (__NFTA_REJECT_MAX - 1)
+
+enum nft_nat_types {
+ NFT_NAT_SNAT,
+ NFT_NAT_DNAT,
+};
+
+enum nft_nat_attributes {
+ NFTA_NAT_UNSPEC,
+ NFTA_NAT_TYPE,
+ NFTA_NAT_ADDR_MIN,
+ NFTA_NAT_ADDR_MAX,
+ NFTA_NAT_PROTO_MIN,
+ NFTA_NAT_PROTO_MAX,
+ __NFTA_NAT_MAX
+};
+#define NFTA_NAT_MAX (__NFTA_NAT_MAX - 1)
+
+#endif /* _LINUX_NF_TABLES_H */
diff --git a/include/linux/netfilter_arp.h b/include/linux/netfilter_arp.h
new file mode 100644
index 00000000..92bc6ddc
--- /dev/null
+++ b/include/linux/netfilter_arp.h
@@ -0,0 +1,19 @@
+#ifndef __LINUX_ARP_NETFILTER_H
+#define __LINUX_ARP_NETFILTER_H
+
+/* ARP-specific defines for netfilter.
+ * (C)2002 Rusty Russell IBM -- This code is GPL.
+ */
+
+#include <linux/netfilter.h>
+
+/* There is no PF_ARP. */
+#define NF_ARP 0
+
+/* ARP Hooks */
+#define NF_ARP_IN 0
+#define NF_ARP_OUT 1
+#define NF_ARP_FORWARD 2
+#define NF_ARP_NUMHOOKS 3
+
+#endif /* __LINUX_ARP_NETFILTER_H */
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
new file mode 100644
index 00000000..5094ecca
--- /dev/null
+++ b/include/linux/netfilter_bridge.h
@@ -0,0 +1,27 @@
+#ifndef __LINUX_BRIDGE_NETFILTER_H
+#define __LINUX_BRIDGE_NETFILTER_H
+
+/* bridge-specific defines for netfilter.
+ */
+
+#include <linux/netfilter.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/if_pppox.h>
+
+/* Bridge Hooks */
+/* After promisc drops, checksum checks. */
+#define NF_BR_PRE_ROUTING 0
+/* If the packet is destined for this box. */
+#define NF_BR_LOCAL_IN 1
+/* If the packet is destined for another interface. */
+#define NF_BR_FORWARD 2
+/* Packets coming from a local process. */
+#define NF_BR_LOCAL_OUT 3
+/* Packets about to hit the wire. */
+#define NF_BR_POST_ROUTING 4
+/* Not really a hook, but used for the ebtables broute table */
+#define NF_BR_BROUTING 5
+#define NF_BR_NUMHOOKS 6
+
+#endif
diff --git a/include/linux/netfilter_decnet.h b/include/linux/netfilter_decnet.h
new file mode 100644
index 00000000..ca70c6cd
--- /dev/null
+++ b/include/linux/netfilter_decnet.h
@@ -0,0 +1,72 @@
+#ifndef __LINUX_DECNET_NETFILTER_H
+#define __LINUX_DECNET_NETFILTER_H
+
+/* DECnet-specific defines for netfilter.
+ * This file (C) Steve Whitehouse 1999 derived from the
+ * ipv4 netfilter header file which is
+ * (C)1998 Rusty Russell -- This code is GPL.
+ */
+
+#include <linux/netfilter.h>
+
+/* only for userspace compatibility */
+/* IP Cache bits. */
+/* Src IP address. */
+#define NFC_DN_SRC 0x0001
+/* Dest IP address. */
+#define NFC_DN_DST 0x0002
+/* Input device. */
+#define NFC_DN_IF_IN 0x0004
+/* Output device. */
+#define NFC_DN_IF_OUT 0x0008
+
+/* DECnet Hooks */
+/* After promisc drops, checksum checks. */
+#define NF_DN_PRE_ROUTING 0
+/* If the packet is destined for this box. */
+#define NF_DN_LOCAL_IN 1
+/* If the packet is destined for another interface. */
+#define NF_DN_FORWARD 2
+/* Packets coming from a local process. */
+#define NF_DN_LOCAL_OUT 3
+/* Packets about to hit the wire. */
+#define NF_DN_POST_ROUTING 4
+/* Input Hello Packets */
+#define NF_DN_HELLO 5
+/* Input Routing Packets */
+#define NF_DN_ROUTE 6
+#define NF_DN_NUMHOOKS 7
+
+enum nf_dn_hook_priorities {
+ NF_DN_PRI_FIRST = INT_MIN,
+ NF_DN_PRI_CONNTRACK = -200,
+ NF_DN_PRI_MANGLE = -150,
+ NF_DN_PRI_NAT_DST = -100,
+ NF_DN_PRI_FILTER = 0,
+ NF_DN_PRI_NAT_SRC = 100,
+ NF_DN_PRI_DNRTMSG = 200,
+ NF_DN_PRI_LAST = INT_MAX,
+};
+
+struct nf_dn_rtmsg {
+ int nfdn_ifindex;
+};
+
+#define NFDN_RTMSG(r) ((unsigned char *)(r) + NLMSG_ALIGN(sizeof(struct nf_dn_rtmsg)))
+
+/* backwards compatibility for userspace */
+#define DNRMG_L1_GROUP 0x01
+#define DNRMG_L2_GROUP 0x02
+
+enum {
+ DNRNG_NLGRP_NONE,
+#define DNRNG_NLGRP_NONE DNRNG_NLGRP_NONE
+ DNRNG_NLGRP_L1,
+#define DNRNG_NLGRP_L1 DNRNG_NLGRP_L1
+ DNRNG_NLGRP_L2,
+#define DNRNG_NLGRP_L2 DNRNG_NLGRP_L2
+ __DNRNG_NLGRP_MAX
+};
+#define DNRNG_NLGRP_MAX (__DNRNG_NLGRP_MAX - 1)
+
+#endif /*__LINUX_DECNET_NETFILTER_H*/
diff --git a/include/linux/netfilter_ipv4.h b/include/linux/netfilter_ipv4.h
new file mode 100644
index 00000000..4d7ba3e4
--- /dev/null
+++ b/include/linux/netfilter_ipv4.h
@@ -0,0 +1,75 @@
+#ifndef __LINUX_IP_NETFILTER_H
+#define __LINUX_IP_NETFILTER_H
+
+/* IPv4-specific defines for netfilter.
+ * (C)1998 Rusty Russell -- This code is GPL.
+ */
+
+#include <linux/netfilter.h>
+
+/* only for userspace compatibility */
+/* IP Cache bits. */
+/* Src IP address. */
+#define NFC_IP_SRC 0x0001
+/* Dest IP address. */
+#define NFC_IP_DST 0x0002
+/* Input device. */
+#define NFC_IP_IF_IN 0x0004
+/* Output device. */
+#define NFC_IP_IF_OUT 0x0008
+/* TOS. */
+#define NFC_IP_TOS 0x0010
+/* Protocol. */
+#define NFC_IP_PROTO 0x0020
+/* IP options. */
+#define NFC_IP_OPTIONS 0x0040
+/* Frag & flags. */
+#define NFC_IP_FRAG 0x0080
+
+/* Per-protocol information: only matters if proto match. */
+/* TCP flags. */
+#define NFC_IP_TCPFLAGS 0x0100
+/* Source port. */
+#define NFC_IP_SRC_PT 0x0200
+/* Dest port. */
+#define NFC_IP_DST_PT 0x0400
+/* Something else about the proto */
+#define NFC_IP_PROTO_UNKNOWN 0x2000
+
+/* IP Hooks */
+/* After promisc drops, checksum checks. */
+#define NF_IP_PRE_ROUTING 0
+/* If the packet is destined for this box. */
+#define NF_IP_LOCAL_IN 1
+/* If the packet is destined for another interface. */
+#define NF_IP_FORWARD 2
+/* Packets coming from a local process. */
+#define NF_IP_LOCAL_OUT 3
+/* Packets about to hit the wire. */
+#define NF_IP_POST_ROUTING 4
+#define NF_IP_NUMHOOKS 5
+
+enum nf_ip_hook_priorities {
+ NF_IP_PRI_FIRST = INT_MIN,
+ NF_IP_PRI_CONNTRACK_DEFRAG = -400,
+ NF_IP_PRI_RAW = -300,
+ NF_IP_PRI_SELINUX_FIRST = -225,
+ NF_IP_PRI_CONNTRACK = -200,
+ NF_IP_PRI_MANGLE = -150,
+ NF_IP_PRI_NAT_DST = -100,
+ NF_IP_PRI_FILTER = 0,
+ NF_IP_PRI_SECURITY = 50,
+ NF_IP_PRI_NAT_SRC = 100,
+ NF_IP_PRI_SELINUX_LAST = 225,
+ NF_IP_PRI_CONNTRACK_CONFIRM = INT_MAX,
+ NF_IP_PRI_LAST = INT_MAX,
+};
+
+/* Arguments for setsockopt SOL_IP: */
+/* 2.0 firewalling went from 64 through 71 (and +256, +512, etc). */
+/* 2.2 firewalling (+ masq) went from 64 through 76 */
+/* 2.4 firewalling went 64 through 67. */
+#define SO_ORIGINAL_DST 80
+
+
+#endif /*__LINUX_IP_NETFILTER_H*/
diff --git a/include/linux/netfilter_ipv6.h b/include/linux/netfilter_ipv6.h
new file mode 100644
index 00000000..7430b392
--- /dev/null
+++ b/include/linux/netfilter_ipv6.h
@@ -0,0 +1,72 @@
+#ifndef __LINUX_IP6_NETFILTER_H
+#define __LINUX_IP6_NETFILTER_H
+
+/* IPv6-specific defines for netfilter.
+ * (C)1998 Rusty Russell -- This code is GPL.
+ * (C)1999 David Jeffery
+ * this header was blatantly ripped from netfilter_ipv4.h
+ * it's amazing what adding a bunch of 6s can do =8^)
+ */
+
+#include <linux/netfilter.h>
+
+/* only for userspace compatibility */
+/* IP Cache bits. */
+/* Src IP address. */
+#define NFC_IP6_SRC 0x0001
+/* Dest IP address. */
+#define NFC_IP6_DST 0x0002
+/* Input device. */
+#define NFC_IP6_IF_IN 0x0004
+/* Output device. */
+#define NFC_IP6_IF_OUT 0x0008
+/* TOS. */
+#define NFC_IP6_TOS 0x0010
+/* Protocol. */
+#define NFC_IP6_PROTO 0x0020
+/* IP options. */
+#define NFC_IP6_OPTIONS 0x0040
+/* Frag & flags. */
+#define NFC_IP6_FRAG 0x0080
+
+
+/* Per-protocol information: only matters if proto match. */
+/* TCP flags. */
+#define NFC_IP6_TCPFLAGS 0x0100
+/* Source port. */
+#define NFC_IP6_SRC_PT 0x0200
+/* Dest port. */
+#define NFC_IP6_DST_PT 0x0400
+/* Something else about the proto */
+#define NFC_IP6_PROTO_UNKNOWN 0x2000
+
+/* IP6 Hooks */
+/* After promisc drops, checksum checks. */
+#define NF_IP6_PRE_ROUTING 0
+/* If the packet is destined for this box. */
+#define NF_IP6_LOCAL_IN 1
+/* If the packet is destined for another interface. */
+#define NF_IP6_FORWARD 2
+/* Packets coming from a local process. */
+#define NF_IP6_LOCAL_OUT 3
+/* Packets about to hit the wire. */
+#define NF_IP6_POST_ROUTING 4
+#define NF_IP6_NUMHOOKS 5
+
+
+enum nf_ip6_hook_priorities {
+ NF_IP6_PRI_FIRST = INT_MIN,
+ NF_IP6_PRI_CONNTRACK_DEFRAG = -400,
+ NF_IP6_PRI_SELINUX_FIRST = -225,
+ NF_IP6_PRI_CONNTRACK = -200,
+ NF_IP6_PRI_MANGLE = -150,
+ NF_IP6_PRI_NAT_DST = -100,
+ NF_IP6_PRI_FILTER = 0,
+ NF_IP6_PRI_SECURITY = 50,
+ NF_IP6_PRI_NAT_SRC = 100,
+ NF_IP6_PRI_SELINUX_LAST = 225,
+ NF_IP6_PRI_LAST = INT_MAX,
+};
+
+
+#endif /*__LINUX_IP6_NETFILTER_H*/
diff --git a/include/list.h b/include/list.h
new file mode 100644
index 00000000..75d29212
--- /dev/null
+++ b/include/list.h
@@ -0,0 +1,625 @@
+#ifndef _LINUX_LIST_H
+#define _LINUX_LIST_H
+
+#include <stddef.h>
+
+#define prefetch(x) ((void)0)
+
+#define LIST_POISON1 ((void *)0x12345678)
+#define LIST_POISON2 ((void *)0x87654321)
+
+/*
+ * Simple doubly linked list implementation.
+ *
+ * Some of the internal functions ("__xxx") are useful when
+ * manipulating whole lists rather than single entries, as
+ * sometimes we already know the next/prev entries and we can
+ * generate better code by using them directly rather than
+ * using the generic single-entry routines.
+ */
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_HEAD_INIT(name) { &(name), &(name) }
+
+#define LIST_HEAD(name) \
+ struct list_head name = LIST_HEAD_INIT(name)
+
+static inline void init_list_head(struct list_head *list)
+{
+ list->next = list;
+ list->prev = list;
+}
+
+/*
+ * Insert a new entry between two known consecutive entries.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+/**
+ * list_add - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it after
+ *
+ * Insert a new entry after the specified head.
+ * This is good for implementing stacks.
+ */
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+
+/**
+ * list_add_tail - add a new entry
+ * @new: new entry to be added
+ * @head: list head to add it before
+ *
+ * Insert a new entry before the specified head.
+ * This is useful for implementing queues.
+ */
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+/*
+ * Delete a list entry by making the prev/next entries
+ * point to each other.
+ *
+ * This is only for internal list manipulation where we know
+ * the prev/next entries already!
+ */
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+/**
+ * list_del - deletes entry from list.
+ * @entry: the element to delete from the list.
+ * Note: list_empty() on entry does not return true after this, the entry is
+ * in an undefined state.
+ */
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = LIST_POISON1;
+ entry->prev = LIST_POISON2;
+}
+
+/**
+ * list_replace - replace old entry by new one
+ * @old : the element to be replaced
+ * @new : the new element to insert
+ *
+ * If @old was empty, it will be overwritten.
+ */
+static inline void list_replace(struct list_head *old,
+ struct list_head *new)
+{
+ new->next = old->next;
+ new->next->prev = new;
+ new->prev = old->prev;
+ new->prev->next = new;
+}
+
+static inline void list_replace_init(struct list_head *old,
+ struct list_head *new)
+{
+ list_replace(old, new);
+ init_list_head(old);
+}
+
+/**
+ * list_del_init - deletes entry from list and reinitialize it.
+ * @entry: the element to delete from the list.
+ */
+static inline void list_del_init(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ init_list_head(entry);
+}
+
+/**
+ * list_move - delete from one list and add as another's head
+ * @list: the entry to move
+ * @head: the head that will precede our entry
+ */
+static inline void list_move(struct list_head *list, struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add(list, head);
+}
+
+/**
+ * list_move_tail - delete from one list and add as another's tail
+ * @list: the entry to move
+ * @head: the head that will follow our entry
+ */
+static inline void list_move_tail(struct list_head *list,
+ struct list_head *head)
+{
+ __list_del(list->prev, list->next);
+ list_add_tail(list, head);
+}
+
+/**
+ * list_is_last - tests whether @list is the last entry in list @head
+ * @list: the entry to test
+ * @head: the head of the list
+ */
+static inline int list_is_last(const struct list_head *list,
+ const struct list_head *head)
+{
+ return list->next == head;
+}
+
+/**
+ * list_empty - tests whether a list is empty
+ * @head: the list to test.
+ */
+static inline int list_empty(const struct list_head *head)
+{
+ return head->next == head;
+}
+
+/**
+ * list_empty_careful - tests whether a list is empty and not being modified
+ * @head: the list to test
+ *
+ * Description:
+ * tests whether a list is empty _and_ checks that no other CPU might be
+ * in the process of modifying either member (next or prev)
+ *
+ * NOTE: using list_empty_careful() without synchronization
+ * can only be safe if the only activity that can happen
+ * to the list entry is list_del_init(). Eg. it cannot be used
+ * if another CPU could re-list_add() it.
+ */
+static inline int list_empty_careful(const struct list_head *head)
+{
+ struct list_head *next = head->next;
+ return (next == head) && (next == head->prev);
+}
+
+/**
+ * list_is_singular - tests whether a list has just one entry.
+ * @head: the list to test.
+ */
+static inline int list_is_singular(const struct list_head *head)
+{
+ return !list_empty(head) && (head->next == head->prev);
+}
+
+static inline void __list_cut_position(struct list_head *list,
+ struct list_head *head, struct list_head *entry)
+{
+ struct list_head *new_first = entry->next;
+ list->next = head->next;
+ list->next->prev = list;
+ list->prev = entry;
+ entry->next = list;
+ head->next = new_first;
+ new_first->prev = head;
+}
+
+/**
+ * list_cut_position - cut a list into two
+ * @list: a new list to add all removed entries
+ * @head: a list with entries
+ * @entry: an entry within head, could be the head itself
+ * and if so we won't cut the list
+ *
+ * This helper moves the initial part of @head, up to and
+ * including @entry, from @head to @list. You should
+ * pass on @entry an element you know is on @head. @list
+ * should be an empty list or a list you do not care about
+ * losing its data.
+ *
+ */
+static inline void list_cut_position(struct list_head *list,
+ struct list_head *head, struct list_head *entry)
+{
+ if (list_empty(head))
+ return;
+ if (list_is_singular(head) &&
+ (head->next != entry && head != entry))
+ return;
+ if (entry == head)
+ init_list_head(list);
+ else
+ __list_cut_position(list, head, entry);
+}
+
+static inline void __list_splice(const struct list_head *list,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+
+ first->prev = prev;
+ prev->next = first;
+
+ last->next = next;
+ next->prev = last;
+}
+
+/**
+ * list_splice - join two lists, this is designed for stacks
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice(const struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head, head->next);
+}
+
+/**
+ * list_splice_tail - join two lists, each list being a queue
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ */
+static inline void list_splice_tail(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list))
+ __list_splice(list, head->prev, head);
+}
+
+/**
+ * list_splice_init - join two lists and reinitialise the emptied list.
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head, head->next);
+ init_list_head(list);
+ }
+}
+
+/**
+ * list_splice_tail_init - join two lists and reinitialise the emptied list
+ * @list: the new list to add.
+ * @head: the place to add it in the first list.
+ *
+ * Each of the lists is a queue.
+ * The list at @list is reinitialised
+ */
+static inline void list_splice_tail_init(struct list_head *list,
+ struct list_head *head)
+{
+ if (!list_empty(list)) {
+ __list_splice(list, head->prev, head);
+ init_list_head(list);
+ }
+}
+
+/**
+ * list_entry - get the struct for this entry
+ * @ptr: the &struct list_head pointer.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_entry(ptr, type, member) \
+ container_of(ptr, type, member)
+
+/**
+ * list_first_entry - get the first element from a list
+ * @ptr: the list head to take the element from.
+ * @type: the type of the struct this is embedded in.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Note, that list is expected to be not empty.
+ */
+#define list_first_entry(ptr, type, member) \
+ list_entry((ptr)->next, type, member)
+
+
+/**
+ * list_for_each_entry - iterate over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_reverse - iterate backwards over list of given type.
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_reverse(pos, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member); \
+ prefetch(pos->member.prev), &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
+ * @pos: the type * to use as a start point
+ * @head: the head of the list
+ * @member: the name of the list_struct within the struct.
+ *
+ * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
+ */
+#define list_prepare_entry(pos, head, member) \
+ ((pos) ? : list_entry(head, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue - continue iteration over list of given type
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Continue to iterate over list of given type, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue(pos, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member); \
+ prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_continue_reverse - iterate backwards from the given point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Start to iterate over list of given type backwards, continuing after
+ * the current position.
+ */
+#define list_for_each_entry_continue_reverse(pos, head, member) \
+ for (pos = list_entry(pos->member.prev, typeof(*pos), member); \
+ prefetch(pos->member.prev), &pos->member != (head); \
+ pos = list_entry(pos->member.prev, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_from - iterate over list of given type from the current point
+ * @pos: the type * to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing from current position.
+ */
+#define list_for_each_entry_from(pos, head, member) \
+ for (; prefetch(pos->member.next), &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+/**
+ * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ */
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_continue
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type, continuing after current point,
+ * safe against removal of list entry.
+ */
+#define list_for_each_entry_safe_continue(pos, n, head, member) \
+ for (pos = list_entry(pos->member.next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_from
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate over list of given type from current point, safe against
+ * removal of list entry.
+ */
+#define list_for_each_entry_safe_from(pos, n, head, member) \
+ for (n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+/**
+ * list_for_each_entry_safe_reverse
+ * @pos: the type * to use as a loop cursor.
+ * @n: another type * to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the list_struct within the struct.
+ *
+ * Iterate backwards over list of given type, safe against removal
+ * of list entry.
+ */
+#define list_for_each_entry_safe_reverse(pos, n, head, member) \
+ for (pos = list_entry((head)->prev, typeof(*pos), member), \
+ n = list_entry(pos->member.prev, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.prev, typeof(*n), member))
+
+/*
+ * Double linked lists with a single pointer list head.
+ * Mostly useful for hash tables where the two pointer list head is
+ * too wasteful.
+ * You lose the ability to access the tail in O(1).
+ */
+
+struct hlist_head {
+ struct hlist_node *first;
+};
+
+struct hlist_node {
+ struct hlist_node *next, **pprev;
+};
+
+#define HLIST_HEAD_INIT { .first = NULL }
+#define HLIST_HEAD(name) struct hlist_head name = { .first = NULL }
+
+#define init_hlist_head(ptr) ((ptr)->first = NULL)
+
+static inline void init_hlist_node(struct hlist_node *h)
+{
+ h->next = NULL;
+ h->pprev = NULL;
+}
+
+static inline int hlist_unhashed(const struct hlist_node *h)
+{
+ return !h->pprev;
+}
+
+static inline int hlist_empty(const struct hlist_head *h)
+{
+ return !h->first;
+}
+
+static inline void __hlist_del(struct hlist_node *n)
+{
+ struct hlist_node *next = n->next;
+ struct hlist_node **pprev = n->pprev;
+ *pprev = next;
+ if (next)
+ next->pprev = pprev;
+}
+
+static inline void hlist_del(struct hlist_node *n)
+{
+ __hlist_del(n);
+ n->next = LIST_POISON1;
+ n->pprev = LIST_POISON2;
+}
+
+static inline void hlist_del_init(struct hlist_node *n)
+{
+ if (!hlist_unhashed(n)) {
+ __hlist_del(n);
+ init_hlist_node(n);
+ }
+}
+
+static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h)
+{
+ struct hlist_node *first = h->first;
+ n->next = first;
+ if (first)
+ first->pprev = &n->next;
+ h->first = n;
+ n->pprev = &h->first;
+}
+
+/* next must be != NULL */
+static inline void hlist_add_before(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ n->pprev = next->pprev;
+ n->next = next;
+ next->pprev = &n->next;
+ *(n->pprev) = n;
+}
+
+static inline void hlist_add_after(struct hlist_node *n,
+ struct hlist_node *next)
+{
+ next->next = n->next;
+ n->next = next;
+ next->pprev = &n->next;
+
+ if(next->next)
+ next->next->pprev = &next->next;
+}
+
+#define hlist_entry(ptr, type, member) container_of(ptr,type,member)
+
+#define hlist_for_each(pos, head) \
+ for (pos = (head)->first; pos && ({ prefetch(pos->next); 1; }); \
+ pos = pos->next)
+
+#define hlist_for_each_safe(pos, n, head) \
+ for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \
+ pos = n)
+
+/**
+ * hlist_for_each_entry - iterate over list of given type
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry(tpos, pos, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_continue(tpos, pos, member) \
+ for (pos = (pos)->next; \
+ pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_from - iterate over a hlist continuing from current point
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_from(tpos, pos, member) \
+ for (; pos && ({ prefetch(pos->next); 1;}) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = pos->next)
+
+/**
+ * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
+ * @tpos: the type * to use as a loop cursor.
+ * @pos: the &struct hlist_node to use as a loop cursor.
+ * @n: another &struct hlist_node to use as temporary storage
+ * @head: the head for your list.
+ * @member: the name of the hlist_node within the struct.
+ */
+#define hlist_for_each_entry_safe(tpos, pos, n, head, member) \
+ for (pos = (head)->first; \
+ pos && ({ n = pos->next; 1; }) && \
+ ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1;}); \
+ pos = n)
+
+#endif
diff --git a/include/meta.h b/include/meta.h
new file mode 100644
index 00000000..75b1f1eb
--- /dev/null
+++ b/include/meta.h
@@ -0,0 +1,29 @@
+#ifndef _META_H
+#define _META_H
+
+/**
+ * struct meta_template - template for meta expressions and statements
+ *
+ * @token: parser token for the expression
+ * @dtype: data type of the expression
+ * @len: length of the expression
+ * @byteorder: byteorder
+ */
+struct meta_template {
+ const char *token;
+ const struct datatype *dtype;
+ enum byteorder byteorder;
+ unsigned int len;
+};
+
+#define META_TEMPLATE(__token, __dtype, __len, __byteorder) { \
+ .token = (__token), \
+ .dtype = (__dtype), \
+ .len = (__len), \
+ .byteorder = (__byteorder), \
+}
+
+extern struct expr *meta_expr_alloc(const struct location *loc,
+ enum nft_meta_keys key);
+
+#endif /* _META_H */
diff --git a/include/netlink.h b/include/netlink.h
new file mode 100644
index 00000000..4849ff51
--- /dev/null
+++ b/include/netlink.h
@@ -0,0 +1,60 @@
+#ifndef _NETLINK_H
+#define _NETLINK_H
+
+#include <netlink/netfilter/netfilter.h>
+#include <netlink/netfilter/nft_table.h>
+#include <netlink/netfilter/nft_chain.h>
+#include <netlink/netfilter/nft_rule.h>
+#include <netlink/netfilter/nft_expr.h>
+#include <netlink/netfilter/nft_data.h>
+#include <netlink/object.h>
+
+#include <rule.h>
+
+/**
+ * struct netlink_ctx
+ *
+ * @msgs: message queue
+ * @list: list of parsed rules/chains/tables
+ */
+struct netlink_ctx {
+ struct list_head *msgs;
+ struct list_head list;
+};
+
+extern void netlink_dump_object(struct nl_object *obj);
+
+extern struct nfnl_nft_table *alloc_nft_table(const struct handle *h);
+extern struct nfnl_nft_chain *alloc_nft_chain(const struct handle *h);
+extern struct nfnl_nft_rule *alloc_nft_rule(const struct handle *h);
+extern struct nfnl_nft_expr *alloc_nft_expr(int (*init)(struct nfnl_nft_expr *));
+extern struct nfnl_nft_data *alloc_nft_data(const void *data, unsigned int len);
+
+extern int netlink_linearize_rule(struct netlink_ctx *ctx,
+ struct nfnl_nft_rule *nlr,
+ const struct rule *rule);
+extern struct rule *netlink_delinearize_rule(struct netlink_ctx *ctx,
+ const struct nl_object *obj);
+
+extern int netlink_add_rule(struct netlink_ctx *ctx, const struct handle *h,
+ const struct rule *rule);
+extern int netlink_delete_rule(struct netlink_ctx *ctx, const struct handle *h);
+extern int netlink_get_rule(struct netlink_ctx *ctx, const struct handle *h);
+
+extern int netlink_add_chain(struct netlink_ctx *ctx, const struct handle *h,
+ const struct chain *chain);
+extern int netlink_delete_chain(struct netlink_ctx *ctx, const struct handle *h);
+extern int netlink_list_chains(struct netlink_ctx *ctx, const struct handle *h);
+extern int netlink_get_chain(struct netlink_ctx *ctx, const struct handle *h);
+extern int netlink_list_chain(struct netlink_ctx *ctx, const struct handle *h);
+extern int netlink_flush_chain(struct netlink_ctx *ctx, const struct handle *h);
+
+extern int netlink_add_table(struct netlink_ctx *ctx, const struct handle *h,
+ const struct table *table);
+extern int netlink_delete_table(struct netlink_ctx *ctx, const struct handle *h);
+extern int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h);
+extern int netlink_get_table(struct netlink_ctx *ctx, const struct handle *h);
+extern int netlink_list_table(struct netlink_ctx *ctx, const struct handle *h);
+extern int netlink_flush_table(struct netlink_ctx *ctx, const struct handle *h);
+
+#endif /* _NETLINK_H */
diff --git a/include/nftables.h b/include/nftables.h
new file mode 100644
index 00000000..7e4a2fc8
--- /dev/null
+++ b/include/nftables.h
@@ -0,0 +1,96 @@
+#ifndef _NFTABLES_H
+#define _NFTABLES_H
+
+#include <stdbool.h>
+#include <stdarg.h>
+#include <utils.h>
+
+enum numeric_level {
+ NUMERIC_NONE,
+ NUMERIC_ADDR,
+ NUMERIC_ALL,
+};
+
+#define INCLUDE_PATHS_MAX 16
+
+extern unsigned int numeric_output;
+extern const char *include_paths[INCLUDE_PATHS_MAX];
+
+struct parser_state;
+extern int cli_init(void *scanner, struct parser_state *state);
+extern void cli_exit(void);
+extern void cli_display(const char *fmt, va_list ap) __fmtstring(1, 0);
+
+enum nftables_exit_codes {
+ NFT_EXIT_SUCCESS = 0,
+ NFT_EXIT_FAILURE = 1,
+ NFT_EXIT_NOMEM = 2,
+};
+
+struct input_descriptor;
+struct location {
+ const struct input_descriptor *indesc;
+ union {
+ struct {
+ off_t token_offset;
+ off_t line_offset;
+
+ unsigned int first_line;
+ unsigned int last_line;
+ unsigned int first_column;
+ unsigned int last_column;
+ };
+ struct {
+ struct nl_object *nl_obj;
+ };
+ };
+};
+
+extern const struct location internal_location;
+
+/**
+ * enum input_descriptor_types
+ *
+ * @INDESC_INVALID: invalid
+ * @INDESC_INTERNAL: dummy type for internally generated messages
+ * @INDESC_BUFFER: buffer (command line arguments)
+ * @INDESC_FILE: file
+ * @INDESC_CLI: command line interface
+ * @INDESC_NETLINK: received from netlink
+ */
+enum input_descriptor_types {
+ INDESC_INVALID,
+ INDESC_INTERNAL,
+ INDESC_BUFFER,
+ INDESC_FILE,
+ INDESC_CLI,
+ INDESC_NETLINK,
+};
+
+/**
+ * struct input_descriptor
+ *
+ * @location: location, used for include statements
+ * @type: input descriptor type
+ * @name: name describing the input
+ * @union: buffer or file descriptor, depending on type
+ * @lineno: current line number in the input
+ * @column: current column in the input
+ * @token_offset: offset of the current token to the beginning
+ * @line_offset: offset of the current line to the beginning
+ */
+struct input_descriptor {
+ struct location location;
+ enum input_descriptor_types type;
+ const char *name;
+ union {
+ const char *data;
+ int fd;
+ };
+ unsigned int lineno;
+ unsigned int column;
+ off_t token_offset;
+ off_t line_offset;
+};
+
+#endif /* _NFTABLES_H */
diff --git a/include/parser.h b/include/parser.h
new file mode 100644
index 00000000..2a4c73b4
--- /dev/null
+++ b/include/parser.h
@@ -0,0 +1,36 @@
+#ifndef _PARSER_H
+#define _PARSER_H
+
+#include <list.h>
+
+#define MAX_INCLUDE_DEPTH 16
+#define TABSIZE 8
+
+#define YYLTYPE struct location
+#define YYLTYPE_IS_TRIVIAL 0
+#define YYENABLE_NLS 0
+
+struct parser_state {
+ struct input_descriptor *indesc;
+ struct input_descriptor indescs[MAX_INCLUDE_DEPTH];
+ unsigned int indesc_idx;
+
+ struct list_head *msgs;
+ struct list_head cmds;
+};
+
+extern void parser_init(struct parser_state *state, struct list_head *msgs);
+extern int nft_parse(void *, struct parser_state *state);
+
+extern void *scanner_init(struct parser_state *state);
+extern void scanner_destroy(struct parser_state *state);
+
+extern int scanner_read_file(void *scanner, const char *filename,
+ const struct location *loc);
+extern int scanner_include_file(void *scanner, const char *filename,
+ const struct location *loc);
+extern void scanner_push_buffer(void *scanner,
+ const struct input_descriptor *indesc,
+ const char *buffer);
+
+#endif /* _PARSER_H */
diff --git a/include/payload.h b/include/payload.h
new file mode 100644
index 00000000..ff9b1381
--- /dev/null
+++ b/include/payload.h
@@ -0,0 +1,289 @@
+#ifndef _PAYLOAD_H
+#define _PAYLOAD_H
+
+#include <nftables.h>
+
+/**
+ * enum payload_bases
+ *
+ * @PAYLOAD_BASE_INVALID: uninitialised, does not happen
+ * @PAYLOAD_BASE_LL_HDR: link layer header
+ * @PAYLOAD_BASE_NETWORK_HDR: network layer header
+ * @PAYLOAD_BASE_TRANSPORT_HDR: transport layer header
+ */
+enum payload_bases {
+ PAYLOAD_BASE_INVALID,
+ PAYLOAD_BASE_LL_HDR,
+ PAYLOAD_BASE_NETWORK_HDR,
+ PAYLOAD_BASE_TRANSPORT_HDR,
+ __PAYLOAD_BASE_MAX
+};
+#define PAYLOAD_BASE_MAX (__PAYLOAD_BASE_MAX - 1)
+
+/**
+ * enum payload_expr_flags
+ *
+ * @PAYLOAD_PROTOCOL_EXPR: payload expression contains upper layer protocol
+ */
+enum payload_expr_flags {
+ PAYLOAD_PROTOCOL_EXPR = 0x1,
+};
+
+/**
+ * struct payload_template - template for a payload header expression
+ *
+ * @token: parser token describing the header field
+ * @dtype: data type of the expression
+ * @offset: offset from base
+ * @len: length of header field
+ */
+struct payload_template {
+ const char *token;
+ const struct datatype *dtype;
+ uint16_t offset;
+ uint16_t len;
+};
+
+#define PAYLOAD_TEMPLATE(__token, __dtype, __offset, __len) \
+ { \
+ .token = (__token), \
+ .dtype = (__dtype), \
+ .offset = (__offset), \
+ .len = (__len), \
+ }
+
+#define PAYLOAD_PROTO_MAX 16
+#define PAYLOAD_TEMPLATE_MAX 20
+
+/**
+ * struct payload_desc - payload protocol description
+ *
+ * @name: protocol name
+ * @base: header base
+ * @protocol_key: key of template containing upper layer protocol description
+ * @protocols: link to upper layer protocol description indexed by protocol value
+ * @templates: header templates
+ */
+struct payload_desc {
+ const char *name;
+ enum payload_bases base;
+ unsigned int protocol_key;
+ struct {
+ unsigned int num;
+ const struct payload_desc *desc;
+ } protocols[PAYLOAD_PROTO_MAX];
+ struct payload_template templates[PAYLOAD_TEMPLATE_MAX];
+};
+
+#define PAYLOAD_PROTO(__num, __desc) { .num = (__num), .desc = (__desc), }
+
+/**
+ * struct payload_hook_desc - description of constraints imposed by hook family
+ *
+ * @base: protocol base of packets
+ * @desc: protocol description of packets
+ */
+struct payload_hook_desc {
+ enum payload_bases base;
+ const struct payload_desc *desc;
+};
+
+#define PAYLOAD_HOOK(__base, __desc) { .base = (__base), .desc = (__desc), }
+
+/**
+ * struct dev_payload_desc - description of device LL protocol
+ *
+ * @desc: protocol description
+ * @type: arphrd value
+ */
+struct dev_payload_desc {
+ const struct payload_desc *desc;
+ uint16_t type;
+};
+
+#define DEV_PAYLOAD_DESC(__type, __desc) { .type = (__type), .desc = (__desc), }
+
+/**
+ * struct payload_ctx - payload expression protocol context
+ *
+ * @family: hook family
+ * @location: location of expression defining the context
+ * @desc: payload description for this layer
+ *
+ * The location of the context is the location of the relational expression
+ * defining it, either directly through a protocol match or indirectly
+ * through a dependency.
+ */
+struct payload_ctx {
+ unsigned int family;
+ struct {
+ struct location location;
+ const struct payload_desc *desc;
+ } protocol[PAYLOAD_BASE_MAX + 1];
+};
+
+extern struct expr *payload_expr_alloc(const struct location *loc,
+ const struct payload_desc *desc,
+ unsigned int type);
+extern void payload_init_raw(struct expr *expr, enum payload_bases base,
+ unsigned int offset, unsigned int len);
+
+extern void payload_ctx_init(struct payload_ctx *ctx, unsigned int family);
+extern void payload_ctx_update_meta(struct payload_ctx *ctx,
+ const struct expr *expr);
+extern void payload_ctx_update(struct payload_ctx *ctx,
+ const struct expr *expr);
+
+struct eval_ctx;
+extern int payload_gen_dependency(struct eval_ctx *ctx, const struct expr *expr,
+ struct expr **res);
+
+extern bool payload_is_adjacent(const struct expr *e1, const struct expr *e2);
+extern struct expr *payload_expr_join(const struct expr *e1,
+ const struct expr *e2);
+
+extern void payload_expr_expand(struct list_head *list, struct expr *expr,
+ const struct payload_ctx *ctx);
+extern void payload_expr_complete(struct expr *expr,
+ const struct payload_ctx *ctx);
+
+enum eth_hdr_fields {
+ ETHHDR_INVALID,
+ ETHHDR_DADDR,
+ ETHHDR_SADDR,
+ ETHHDR_TYPE,
+};
+
+enum vlan_hdr_fields {
+ VLANHDR_INVALID,
+ VLANHDR_VID,
+ VLANHDR_CFI,
+ VLANHDR_PCP,
+ VLANHDR_TYPE,
+};
+
+enum arp_hdr_fields {
+ ARPHDR_INVALID,
+ ARPHDR_HRD,
+ ARPHDR_PRO,
+ ARPHDR_HLN,
+ ARPHDR_PLN,
+ ARPHDR_OP,
+};
+
+enum ip_hdr_fields {
+ IPHDR_INVALID,
+ IPHDR_VERSION,
+ IPHDR_HDRLENGTH,
+ IPHDR_TOS,
+ IPHDR_LENGTH,
+ IPHDR_ID,
+ IPHDR_FRAG_OFF,
+ IPHDR_TTL,
+ IPHDR_PROTOCOL,
+ IPHDR_CHECKSUM,
+ IPHDR_SADDR,
+ IPHDR_DADDR,
+};
+
+enum icmp_hdr_fields {
+ ICMPHDR_INVALID,
+ ICMPHDR_TYPE,
+ ICMPHDR_CODE,
+ ICMPHDR_CHECKSUM,
+ ICMPHDR_ID,
+ ICMPHDR_SEQ,
+ ICMPHDR_GATEWAY,
+ ICMPHDR_MTU,
+};
+
+enum ip6_hdr_fields {
+ IP6HDR_INVALID,
+ IP6HDR_VERSION,
+ IP6HDR_PRIORITY,
+ IP6HDR_FLOWLABEL,
+ IP6HDR_LENGTH,
+ IP6HDR_NEXTHDR,
+ IP6HDR_HOPLIMIT,
+ IP6HDR_SADDR,
+ IP6HDR_DADDR,
+};
+
+enum ah_hdr_fields {
+ AHHDR_INVALID,
+ AHHDR_NEXTHDR,
+ AHHDR_HDRLENGTH,
+ AHHDR_RESERVED,
+ AHHDR_SPI,
+ AHHDR_SEQUENCE,
+};
+
+enum esp_hdr_fields {
+ ESPHDR_INVALID,
+ ESPHDR_SPI,
+ ESPHDR_SEQUENCE,
+};
+
+enum comp_hdr_fields {
+ COMPHDR_INVALID,
+ COMPHDR_NEXTHDR,
+ COMPHDR_FLAGS,
+ COMPHDR_CPI,
+};
+
+enum udp_hdr_fields {
+ UDPHDR_INVALID,
+ UDPHDR_SPORT,
+ UDPHDR_DPORT,
+ UDPHDR_LENGTH,
+ UDPHDR_CSUMCOV = UDPHDR_LENGTH,
+ UDPHDR_CHECKSUM,
+};
+
+enum tcp_hdr_fields {
+ TCPHDR_INVALID,
+ TCPHDR_SPORT,
+ TCPHDR_DPORT,
+ TCPHDR_SEQ,
+ TCPHDR_ACKSEQ,
+ TCPHDR_DOFF,
+ TCPHDR_RESERVED,
+ TCPHDR_FLAGS,
+ TCPHDR_WINDOW,
+ TCPHDR_CHECKSUM,
+ TCPHDR_URGPTR,
+};
+
+enum dccp_hdr_fields {
+ DCCPHDR_INVALID,
+ DCCPHDR_SPORT,
+ DCCPHDR_DPORT,
+};
+
+enum sctp_hdr_fields {
+ SCTPHDR_INVALID,
+ SCTPHDR_SPORT,
+ SCTPHDR_DPORT,
+ SCTPHDR_VTAG,
+ SCTPHDR_CHECKSUM,
+};
+
+extern const struct payload_desc payload_icmp;
+extern const struct payload_desc payload_ah;
+extern const struct payload_desc payload_esp;
+extern const struct payload_desc payload_comp;
+extern const struct payload_desc payload_udp;
+extern const struct payload_desc payload_udplite;
+extern const struct payload_desc payload_tcp;
+extern const struct payload_desc payload_dccp;
+extern const struct payload_desc payload_sctp;
+
+extern const struct payload_desc payload_ip;
+extern const struct payload_desc payload_ip6;
+
+extern const struct payload_desc payload_arp;
+
+extern const struct payload_desc payload_vlan;
+extern const struct payload_desc payload_eth;
+
+#endif /* _PAYLOAD_H */
diff --git a/include/rbtree.h b/include/rbtree.h
new file mode 100644
index 00000000..26b6b44a
--- /dev/null
+++ b/include/rbtree.h
@@ -0,0 +1,98 @@
+/*
+ * Red Black Trees
+ * (C) 1999 Andrea Arcangeli <andrea@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef _RBTREE_H
+#define _RBTREE_H
+
+#include <stddef.h>
+
+struct rb_node
+{
+ unsigned long rb_parent_color;
+#define RB_RED 0
+#define RB_BLACK 1
+ struct rb_node *rb_right;
+ struct rb_node *rb_left;
+};
+
+struct rb_root
+{
+ struct rb_node *rb_node;
+};
+
+#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
+#define rb_color(r) ((r)->rb_parent_color & 1)
+#define rb_is_red(r) (!rb_color(r))
+#define rb_is_black(r) rb_color(r)
+#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
+#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
+
+static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
+{
+ rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
+}
+static inline void rb_set_color(struct rb_node *rb, int color)
+{
+ rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
+}
+
+#define RB_ROOT (struct rb_root) { NULL, }
+#define rb_entry(ptr, type, member) container_of(ptr, type, member)
+
+#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
+#define RB_EMPTY_NODE(node) (rb_parent(node) == node)
+#define RB_CLEAR_NODE(node) (rb_set_parent(node, node))
+
+extern void rb_insert_color(struct rb_node *, struct rb_root *);
+extern void rb_erase(struct rb_node *, struct rb_root *);
+
+/* Find logical next and previous nodes in a tree */
+extern struct rb_node *rb_next(struct rb_node *);
+extern struct rb_node *rb_prev(struct rb_node *);
+extern struct rb_node *rb_first(struct rb_root *);
+extern struct rb_node *rb_last(struct rb_root *);
+
+/* Fast replacement of a single node without remove/rebalance/add/rebalance */
+extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
+ struct rb_root *root);
+
+static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
+ struct rb_node ** rb_link)
+{
+ node->rb_parent_color = (unsigned long )parent;
+ node->rb_left = node->rb_right = NULL;
+
+ *rb_link = node;
+}
+
+#define rb_for_each_entry(pos, root, member) \
+ for ((pos) = (root)->rb_node ? \
+ rb_entry(rb_first(root), typeof(*pos), member) : NULL; \
+ (pos) != NULL; \
+ (pos) = rb_entry(rb_next(&(pos)->member), typeof(*pos), member))
+
+#define rb_for_each_entry_safe(pos, node, next, root, member) \
+ for ((node) = rb_first(root); \
+ (pos) = (node) ? rb_entry((node), typeof(*pos), member) : NULL, \
+ (next) = (node) ? rb_next(node) : NULL, \
+ (pos) != NULL; \
+ (node) = (next))
+
+#endif /* _RBTREE_H */
diff --git a/include/rule.h b/include/rule.h
new file mode 100644
index 00000000..e4ad9f58
--- /dev/null
+++ b/include/rule.h
@@ -0,0 +1,174 @@
+#ifndef _RULE_H
+#define _RULE_H
+
+#include <stdint.h>
+#include <nftables.h>
+#include <list.h>
+
+/**
+ * struct handle - handle for tables, chains and rules
+ *
+ * @family: protocol family
+ * @table: table name
+ * @chain: chain name (chains and rules only)
+ * @handle: rule handle (rules only)
+ */
+struct handle {
+ int family;
+ const char *table;
+ const char *chain;
+ uint32_t handle;
+};
+
+extern void handle_merge(struct handle *dst, const struct handle *src);
+extern void handle_free(struct handle *h);
+
+/**
+ * struct table - nftables table
+ *
+ * @list: list node
+ * @handle: table handle
+ * @chains: chains contained in the table
+ */
+struct table {
+ struct list_head list;
+ struct handle handle;
+ struct list_head chains;
+};
+
+extern struct table *table_alloc(void);
+extern void table_free(struct table *table);
+extern void table_add_hash(struct table *table);
+extern struct table *table_lookup(const struct handle *h);
+
+/**
+ * struct chain - nftables chain
+ *
+ * @list: list node in table list
+ * @handle: chain handle
+ * @hooknum: hook number (base chains)
+ * @priority: hook priority (base chains)
+ * @rules: rules contained in the chain
+ */
+struct chain {
+ struct list_head list;
+ struct handle handle;
+ unsigned int hooknum;
+ unsigned int priority;
+ struct list_head rules;
+};
+
+extern struct chain *chain_alloc(const char *name);
+extern void chain_free(struct chain *chain);
+extern void chain_add_hash(struct chain *chain, struct table *table);
+extern struct chain *chain_lookup(const struct table *table,
+ const struct handle *h);
+
+/**
+ * struct rule - nftables rule
+ *
+ * @list: list node in chain list
+ * @handle: rule handle
+ * @location: location the rule was defined at
+ * @stmt: list of statements
+ * @num_stmts: number of statements in stmts list
+ */
+struct rule {
+ struct list_head list;
+ struct handle handle;
+ struct location location;
+ struct list_head stmts;
+ unsigned int num_stmts;
+};
+
+extern struct rule *rule_alloc(const struct location *loc,
+ const struct handle *h);
+extern void rule_free(struct rule *rule);
+extern void rule_print(const struct rule *rule);
+
+/**
+ * enum cmd_ops - command operations
+ *
+ * @CMD_INVALID: invalid
+ * @CMD_ADD: add object
+ * @CMD_DELETE: delete object
+ * @CMD_LIST: list container
+ * @CMD_FLUSH: flush container
+ */
+enum cmd_ops {
+ CMD_INVALID,
+ CMD_ADD,
+ CMD_DELETE,
+ CMD_LIST,
+ CMD_FLUSH,
+};
+
+/**
+ * enum cmd_obj - command objects
+ *
+ * @CMD_OBJ_INVALID: invalid
+ * @CMD_OBJ_RULE: rule
+ * @CMD_OBJ_CHAIN: chain
+ * @CMD_OBJ_TABLE: table
+ */
+enum cmd_obj {
+ CMD_OBJ_INVALID,
+ CMD_OBJ_RULE,
+ CMD_OBJ_CHAIN,
+ CMD_OBJ_TABLE,
+};
+
+/**
+ * struct cmd - command statement
+ *
+ * @list: list node
+ * @location: location of the statement
+ * @op: operation
+ * @obj: object type to perform operation on
+ * @handle: handle for operations working without full objects
+ * @union: object
+ */
+struct cmd {
+ struct list_head list;
+ struct location location;
+ enum cmd_ops op;
+ enum cmd_obj obj;
+ struct handle handle;
+ union {
+ void *data;
+ struct rule *rule;
+ struct chain *chain;
+ struct table *table;
+ };
+};
+
+extern struct cmd *cmd_alloc(enum cmd_ops op, enum cmd_obj obj,
+ const struct handle *h, void *data);
+extern void cmd_free(struct cmd *cmd);
+
+#include <payload.h>
+#include <expression.h>
+
+/**
+ * struct eval_ctx - evaluation context
+ *
+ * @msgs: message queue
+ * @stmt: current statement
+ * @ectx: expression context
+ * @pctx: payload context
+ */
+struct eval_ctx {
+ struct list_head *msgs;
+ struct stmt *stmt;
+ struct expr_ctx ectx;
+ struct payload_ctx pctx;
+};
+
+extern int evaluate(struct eval_ctx *ctx, struct list_head *commands);
+
+extern struct error_record *rule_postprocess(struct rule *rule);
+
+struct netlink_ctx;
+extern int do_command(struct netlink_ctx *ctx, struct cmd *cmd);
+
+#endif /* RULE_H */
diff --git a/include/statement.h b/include/statement.h
new file mode 100644
index 00000000..6e5cfbdb
--- /dev/null
+++ b/include/statement.h
@@ -0,0 +1,140 @@
+#ifndef _STATEMENT_H
+#define _STATEMENT_H
+
+#include <list.h>
+#include <expression.h>
+
+extern struct stmt *expr_stmt_alloc(const struct location *loc,
+ struct expr *expr);
+
+extern struct stmt *verdict_stmt_alloc(const struct location *loc,
+ struct expr *expr);
+
+struct counter_stmt {
+ uint64_t packets;
+ uint64_t bytes;
+};
+
+extern struct stmt *counter_stmt_alloc(const struct location *loc);
+
+#include <meta.h>
+struct meta_stmt {
+ enum nft_meta_keys key;
+ const struct meta_template *tmpl;
+ struct expr *expr;
+};
+
+extern struct stmt *meta_stmt_alloc(const struct location *loc,
+ enum nft_meta_keys key,
+ struct expr *expr);
+
+struct log_stmt {
+ const char *prefix;
+ unsigned int group;
+ unsigned int snaplen;
+ unsigned int qthreshold;
+};
+
+extern struct stmt *log_stmt_alloc(const struct location *loc);
+
+
+struct limit_stmt {
+ uint64_t rate;
+ uint64_t unit;
+ uint64_t depth;
+};
+
+extern struct stmt *limit_stmt_alloc(const struct location *loc);
+
+struct reject_stmt {
+ enum nft_reject_types type;
+};
+
+extern struct stmt *reject_stmt_alloc(const struct location *loc);
+
+struct nat_stmt {
+ enum nft_nat_types type;
+ struct expr *addr;
+ struct expr *proto;
+};
+
+extern struct stmt *nat_stmt_alloc(const struct location *loc);
+
+/**
+ * enum stmt_types - statement types
+ *
+ * @STMT_INVALID: uninitialised
+ * @STMT_EXPRESSION: expression statement (relational)
+ * @STMT_VERDICT: verdict statement
+ * @STMT_COUNTER: counters
+ * @STMT_META: meta statement
+ * @STMT_LIMIT: limit statement
+ * @STMT_LOG: log statement
+ * @STMT_REJECT: REJECT statement
+ * @STMT_NAT: NAT statement
+ */
+enum stmt_types {
+ STMT_INVALID,
+ STMT_EXPRESSION,
+ STMT_VERDICT,
+ STMT_COUNTER,
+ STMT_META,
+ STMT_LIMIT,
+ STMT_LOG,
+ STMT_REJECT,
+ STMT_NAT,
+};
+
+/**
+ * struct stmt_ops
+ *
+ * @type: statement type
+ * @name: name
+ * @destroy: destructor
+ * @print: function to print statement
+ */
+struct stmt;
+struct stmt_ops {
+ enum stmt_types type;
+ const char *name;
+ void (*destroy)(struct stmt *stmt);
+ void (*print)(const struct stmt *stmt);
+};
+
+enum stmt_flags {
+ STMT_F_TERMINAL = 0x1,
+};
+
+/**
+ * struct stmt
+ *
+ * @list: rule list node
+ * @ops: statement ops
+ * @location: location where the statement was defined
+ * @flags: statement flags
+ * @union: type specific data
+ */
+struct stmt {
+ struct list_head list;
+ const struct stmt_ops *ops;
+ struct location location;
+ enum stmt_flags flags;
+
+ union {
+ struct expr *expr;
+ struct counter_stmt counter;
+ struct meta_stmt meta;
+ struct log_stmt log;
+ struct limit_stmt limit;
+ struct reject_stmt reject;
+ struct nat_stmt nat;
+ };
+};
+
+extern struct stmt *stmt_alloc(const struct location *loc,
+ const struct stmt_ops *ops);
+extern void stmt_free(struct stmt *stmt);
+extern void stmt_list_free(struct list_head *list);
+extern void stmt_print(const struct stmt *stmt);
+
+#endif /* _STATEMENT_H */
diff --git a/include/utils.h b/include/utils.h
new file mode 100644
index 00000000..beb63868
--- /dev/null
+++ b/include/utils.h
@@ -0,0 +1,69 @@
+#ifndef _UTILS_H
+#define _UTILS_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <assert.h>
+#include <list.h>
+#include <gmp.h>
+
+#define BITS_PER_BYTE 8
+
+#ifdef DEBUG
+#define pr_debug(fmt, arg...) gmp_printf(fmt, ##arg)
+#else
+#define pr_debug(fmt, arg...) ({ if (false) gmp_printf(fmt, ##arg); 0; })
+#endif
+
+#define __fmtstring(x, y) __attribute__((format(printf, x, y)))
+#if 0
+#define __gmp_fmtstring(x, y) __fmtstring(x, y)
+#else
+#define __gmp_fmtstring(x, y)
+#endif
+
+#define __init __attribute__((constructor))
+#define __exit __attribute__((destructor))
+#define __must_check __attribute__((warn_unused_result))
+#define __noreturn __attribute__((__noreturn__))
+
+#define BUG() assert(0)
+
+#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
+#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1)
+
+#define __must_be_array(a) \
+ BUILD_BUG_ON_ZERO(__builtin_types_compatible_p(typeof(a), typeof(&a[0])))
+
+#define container_of(ptr, type, member) ({ \
+ typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+
+#define field_sizeof(t, f) (sizeof(((t *)NULL)->f))
+#define array_size(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr))
+#define div_round_up(n, d) (((n) + (d) - 1) / (d))
+
+#define min(x, y) ({ \
+ typeof(x) _min1 = (x); \
+ typeof(y) _min2 = (y); \
+ (void) (&_min1 == &_min2); \
+ _min1 < _min2 ? _min1 : _min2; })
+
+#define max(x, y) ({ \
+ typeof(x) _max1 = (x); \
+ typeof(y) _max2 = (y); \
+ (void) (&_max1 == &_max2); \
+ _max1 > _max2 ? _max1 : _max2; })
+
+extern void memory_allocation_error(void) __noreturn;
+
+extern void xfree(const void *ptr);
+extern void *xmalloc(size_t size);
+extern void *xrealloc(void *ptr, size_t size);
+extern void *xzalloc(size_t size);
+extern char *xstrdup(const char *s);
+
+#endif /* _UTILS_H */