summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/Makefile.am40
-rw-r--r--include/cache.h56
-rw-r--r--include/cli.h3
-rw-r--r--include/cmd.h6
-rw-r--r--include/ct.h2
-rw-r--r--include/datatype.h23
-rw-r--r--include/dccpopt.h41
-rw-r--r--include/erec.h5
-rw-r--r--include/expression.h43
-rw-r--r--include/exthdr.h1
-rw-r--r--include/gmputil.h4
-rw-r--r--include/headers.h2
-rw-r--r--include/intervals.h11
-rw-r--r--include/ipopt.h2
-rw-r--r--include/json.h14
-rw-r--r--include/linux/Makefile.am12
-rw-r--r--include/linux/netfilter.h1
-rw-r--r--include/linux/netfilter/Makefile.am9
-rw-r--r--include/linux/netfilter/nf_tables.h79
-rw-r--r--include/linux/netfilter/nfnetlink.h3
-rw-r--r--include/linux/netfilter/nfnetlink_hook.h82
-rw-r--r--include/linux/netfilter_arp/Makefile.am1
-rw-r--r--include/linux/netfilter_bridge/Makefile.am1
-rw-r--r--include/linux/netfilter_ipv4/Makefile.am1
-rw-r--r--include/linux/netfilter_ipv6/Makefile.am1
-rw-r--r--include/meta.h2
-rw-r--r--include/mnl.h33
-rw-r--r--include/netlink.h44
-rw-r--r--include/nft.h18
-rw-r--r--include/nftables.h36
-rw-r--r--include/nftables/Makefile.am1
-rw-r--r--include/nftables/libnftables.h22
-rw-r--r--include/parser.h40
-rw-r--r--include/payload.h19
-rw-r--r--include/proto.h67
-rw-r--r--include/rbtree.h98
-rw-r--r--include/rule.h64
-rw-r--r--include/sctp_chunk.h87
-rw-r--r--include/statement.h34
-rw-r--r--include/tcpopt.h13
-rw-r--r--include/utils.h43
41 files changed, 799 insertions, 265 deletions
diff --git a/include/Makefile.am b/include/Makefile.am
deleted file mode 100644
index b1339814..00000000
--- a/include/Makefile.am
+++ /dev/null
@@ -1,40 +0,0 @@
-SUBDIRS = linux \
- nftables
-
-noinst_HEADERS = cli.h \
- cache.h \
- cmd.h \
- datatype.h \
- expression.h \
- fib.h \
- hash.h \
- ipopt.h \
- json.h \
- mini-gmp.h \
- gmputil.h \
- iface.h \
- mnl.h \
- nftables.h \
- payload.h \
- rbtree.h \
- tcpopt.h \
- statement.h \
- ct.h \
- erec.h \
- exthdr.h \
- headers.h \
- list.h \
- meta.h \
- misspell.h \
- numgen.h \
- netlink.h \
- osf.h \
- owner.h \
- parser.h \
- proto.h \
- socket.h \
- rule.h \
- rt.h \
- utils.h \
- xfrm.h \
- xt.h
diff --git a/include/cache.h b/include/cache.h
index ad907843..8ca4a9a7 100644
--- a/include/cache.h
+++ b/include/cache.h
@@ -1,7 +1,9 @@
#ifndef _NFT_CACHE_H_
#define _NFT_CACHE_H_
-#include <string.h>
+#include <list.h>
+
+struct handle;
enum cache_level_bits {
NFT_CACHE_TABLE_BIT = (1 << 0),
@@ -32,17 +34,47 @@ enum cache_level_flags {
NFT_CACHE_CHAIN_BIT |
NFT_CACHE_RULE_BIT,
NFT_CACHE_FULL = __NFT_CACHE_MAX_BIT - 1,
+ NFT_CACHE_TERSE = (1 << 27),
+ NFT_CACHE_SETELEM_MAYBE = (1 << 28),
NFT_CACHE_REFRESH = (1 << 29),
NFT_CACHE_UPDATE = (1 << 30),
NFT_CACHE_FLUSHED = (1 << 31),
};
+struct nft_filter_obj {
+ struct list_head list;
+ uint32_t family;
+ const char *table;
+ const char *set;
+};
+
+#define NFT_CACHE_HSIZE 8192
+
+struct nft_cache_filter {
+ struct {
+ uint32_t family;
+ const char *table;
+ const char *chain;
+ const char *set;
+ const char *ft;
+ uint64_t rule_handle;
+ } list;
+
+ struct {
+ struct list_head head;
+ } obj[NFT_CACHE_HSIZE];
+};
+
struct nft_cache;
+struct nft_ctx;
enum cmd_ops;
-unsigned int nft_cache_evaluate(struct nft_ctx *nft, struct list_head *cmds);
-int nft_cache_update(struct nft_ctx *ctx, enum cmd_ops cmd,
- struct list_head *msgs);
+int nft_cache_evaluate(struct nft_ctx *nft, struct list_head *cmds,
+ struct list_head *msgs, struct nft_cache_filter *filter,
+ unsigned int *flags);
+int nft_cache_update(struct nft_ctx *ctx, unsigned int flags,
+ struct list_head *msgs,
+ const struct nft_cache_filter *filter);
bool nft_cache_needs_update(struct nft_cache *cache);
void nft_cache_release(struct nft_cache *cache);
@@ -56,7 +88,8 @@ static inline uint32_t djb_hash(const char *key)
return hash;
}
-#define NFT_CACHE_HSIZE 8192
+struct nft_cache_filter *nft_cache_filter_init(void);
+void nft_cache_filter_fini(struct nft_cache_filter *filter);
struct table;
struct chain;
@@ -65,6 +98,8 @@ void chain_cache_add(struct chain *chain, struct table *table);
void chain_cache_del(struct chain *chain);
struct chain *chain_cache_find(const struct table *table, const char *name);
+struct set;
+
void set_cache_add(struct set *set, struct table *table);
void set_cache_del(struct set *set);
struct set *set_cache_find(const struct table *table, const char *name);
@@ -89,6 +124,8 @@ void table_cache_del(struct table *table);
struct table *table_cache_find(const struct cache *cache, const char *name,
uint32_t family);
+struct obj;
+
void obj_cache_add(struct obj *obj, struct table *table);
void obj_cache_del(struct obj *obj);
struct obj *obj_cache_find(const struct table *table, const char *name,
@@ -106,4 +143,13 @@ struct nft_cache {
uint32_t flags;
};
+struct netlink_ctx;
+
+void nft_chain_cache_update(struct netlink_ctx *ctx, struct table *table,
+ const char *chain);
+
+int rule_cache_dump(struct netlink_ctx *ctx, const struct handle *h,
+ const struct nft_cache_filter *filter,
+ bool dump, bool reset);
+
#endif /* _NFT_CACHE_H_ */
diff --git a/include/cli.h b/include/cli.h
index 609ed2ed..f0a0d47a 100644
--- a/include/cli.h
+++ b/include/cli.h
@@ -2,7 +2,6 @@
#define _NFT_CLI_H_
#include <nftables/libnftables.h>
-#include <config.h>
#if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDIT) || defined(HAVE_LIBLINENOISE)
extern int cli_init(struct nft_ctx *nft);
@@ -12,6 +11,6 @@ static inline int cli_init(struct nft_ctx *nft)
return -1;
}
#endif
-extern void cli_exit(void);
+extern void cli_exit(int rc);
#endif
diff --git a/include/cmd.h b/include/cmd.h
index 27fa6087..92a4152b 100644
--- a/include/cmd.h
+++ b/include/cmd.h
@@ -1,7 +1,13 @@
#ifndef _NFT_CMD_H_
#define _NFT_CMD_H_
+void cmd_add_loc(struct cmd *cmd, uint16_t offset, const struct location *loc);
void nft_cmd_error(struct netlink_ctx *ctx, struct cmd *cmd,
struct mnl_err *err);
+void nft_cmd_expand(struct cmd *cmd);
+void nft_cmd_post_expand(struct cmd *cmd);
+bool nft_cmd_collapse(struct list_head *cmds);
+void nft_cmd_uncollapse(struct list_head *cmds);
+
#endif
diff --git a/include/ct.h b/include/ct.h
index efb2d418..0a705fd0 100644
--- a/include/ct.h
+++ b/include/ct.h
@@ -39,5 +39,7 @@ extern const char *ct_label2str(const struct symbol_table *tbl,
extern const struct datatype ct_dir_type;
extern const struct datatype ct_state_type;
extern const struct datatype ct_status_type;
+extern const struct datatype ct_label_type;
+extern const struct datatype ct_event_type;
#endif /* NFTABLES_CT_H */
diff --git a/include/datatype.h b/include/datatype.h
index 448be57f..d4b4737c 100644
--- a/include/datatype.h
+++ b/include/datatype.h
@@ -22,7 +22,7 @@
* @TYPE_INET_SERVICE: internet service (integer subtype)
* @TYPE_ICMP_TYPE: ICMP type codes (integer subtype)
* @TYPE_TCP_FLAG: TCP flag (bitmask subtype)
- * @TCPE_DCCP_PKTTYPE: DCCP packet type (integer subtype)
+ * @TYPE_DCCP_PKTTYPE: DCCP packet type (integer subtype)
* @TYPE_MH_TYPE: Mobility Header type (integer subtype)
* @TYPE_TIME: relative time
* @TYPE_MARK: packet mark (integer subtype)
@@ -166,6 +166,7 @@ struct datatype {
struct error_record *(*parse)(struct parse_ctx *ctx,
const struct expr *sym,
struct expr **res);
+ struct error_record *(*err)(const struct expr *sym);
void (*describe)(struct output_ctx *octx);
const struct symbol_table *sym_tbl;
unsigned int refcnt;
@@ -173,12 +174,15 @@ struct datatype {
extern const struct datatype *datatype_lookup(enum datatypes type);
extern const struct datatype *datatype_lookup_byname(const char *name);
-extern struct datatype *datatype_get(const struct datatype *dtype);
+extern const struct datatype *datatype_get(const struct datatype *dtype);
extern void datatype_set(struct expr *expr, const struct datatype *dtype);
+extern void __datatype_set(struct expr *expr, const struct datatype *dtype);
extern void datatype_free(const struct datatype *dtype);
+struct datatype *datatype_clone(const struct datatype *orig_dtype);
struct parse_ctx {
struct symbol_tables *tbl;
+ const struct input_ctx *input;
};
extern struct error_record *symbol_parse(struct parse_ctx *ctx,
@@ -248,12 +252,16 @@ 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(const struct symbol_table *tbl);
+extern void rt_symbol_table_describe(struct output_ctx *octx, const char *name,
+ const struct symbol_table *tbl,
+ const struct datatype *type);
extern const struct datatype invalid_type;
extern const struct datatype verdict_type;
extern const struct datatype nfproto_type;
extern const struct datatype bitmask_type;
extern const struct datatype integer_type;
+extern const struct datatype xinteger_type;
extern const struct datatype string_type;
extern const struct datatype lladdr_type;
extern const struct datatype ipaddr_type;
@@ -275,6 +283,11 @@ extern const struct datatype priority_type;
extern const struct datatype policy_type;
extern const struct datatype cgroupv2_type;
+/* private datatypes for reject statement. */
+extern const struct datatype reject_icmp_code_type;
+extern const struct datatype reject_icmpv6_code_type;
+extern const struct datatype reject_icmpx_code_type;
+
void inet_service_type_print(const struct expr *expr, struct output_ctx *octx);
extern const struct datatype *concat_type_alloc(uint32_t type);
@@ -296,7 +309,7 @@ concat_subtype_lookup(uint32_t type, unsigned int n)
}
extern const struct datatype *
-set_datatype_alloc(const struct datatype *orig_dtype, unsigned int byteorder);
+set_datatype_alloc(const struct datatype *orig_dtype, enum byteorder byteorder);
extern void time_print(uint64_t msec, struct output_ctx *octx);
extern struct error_record *time_parse(const struct location *loc,
@@ -309,6 +322,10 @@ extern struct error_record *rate_parse(const struct location *loc,
extern struct error_record *data_unit_parse(const struct location *loc,
const char *str, uint64_t *rate);
+struct limit_rate {
+ uint64_t rate, unit;
+};
+
extern void expr_chain_export(const struct expr *e, char *chain);
#endif /* NFTABLES_DATATYPE_H */
diff --git a/include/dccpopt.h b/include/dccpopt.h
new file mode 100644
index 00000000..3617fc1a
--- /dev/null
+++ b/include/dccpopt.h
@@ -0,0 +1,41 @@
+#ifndef NFTABLES_DCCPOPT_H
+#define NFTABLES_DCCPOPT_H
+
+#include <nftables.h>
+
+#define DCCPOPT_TYPE_MIN 0
+#define DCCPOPT_TYPE_MAX UINT8_MAX
+
+enum dccpopt_fields {
+ DCCPOPT_FIELD_INVALID,
+ DCCPOPT_FIELD_TYPE,
+};
+
+enum dccpopt_types {
+ DCCPOPT_PADDING = 0,
+ DCCPOPT_MANDATORY = 1,
+ DCCPOPT_SLOW_RECEIVER = 2,
+ DCCPOPT_RESERVED_SHORT = 3,
+ DCCPOPT_CHANGE_L = 32,
+ DCCPOPT_CONFIRM_L = 33,
+ DCCPOPT_CHANGE_R = 34,
+ DCCPOPT_CONFIRM_R = 35,
+ DCCPOPT_INIT_COOKIE = 36,
+ DCCPOPT_NDP_COUNT = 37,
+ DCCPOPT_ACK_VECTOR_NONCE_0 = 38,
+ DCCPOPT_ACK_VECTOR_NONCE_1 = 39,
+ DCCPOPT_DATA_DROPPED = 40,
+ DCCPOPT_TIMESTAMP = 41,
+ DCCPOPT_TIMESTAMP_ECHO = 42,
+ DCCPOPT_ELAPSED_TIME = 43,
+ DCCPOPT_DATA_CHECKSUM = 44,
+ DCCPOPT_RESERVED_LONG = 45,
+ DCCPOPT_CCID_SPECIFIC = 128,
+};
+
+const struct exthdr_desc *dccpopt_find_desc(uint8_t type);
+struct expr *dccpopt_expr_alloc(const struct location *loc, uint8_t type);
+void dccpopt_init_raw(struct expr *expr, uint8_t type, unsigned int offset,
+ unsigned int len);
+
+#endif /* NFTABLES_DCCPOPT_H */
diff --git a/include/erec.h b/include/erec.h
index 79a16290..c17f5def 100644
--- a/include/erec.h
+++ b/include/erec.h
@@ -76,4 +76,9 @@ extern int __fmtstring(4, 5) __stmt_binary_error(struct eval_ctx *ctx,
#define stmt_binary_error(ctx, s1, s2, fmt, args...) \
__stmt_binary_error(ctx, &(s1)->location, &(s2)->location, fmt, ## args)
+void print_location(FILE *f, const struct input_descriptor *indesc,
+ const struct location *loc);
+const char *line_location(const struct input_descriptor *indesc,
+ const struct location *loc, char *buf, size_t bufsiz);
+
#endif /* NFTABLES_EREC_H */
diff --git a/include/expression.h b/include/expression.h
index be703d75..01b45b7c 100644
--- a/include/expression.h
+++ b/include/expression.h
@@ -1,7 +1,6 @@
#ifndef NFTABLES_EXPRESSION_H
#define NFTABLES_EXPRESSION_H
-#include <stdbool.h>
#include <gmputil.h>
#include <linux/netfilter/nf_tables.h>
@@ -12,6 +11,10 @@
#include <json.h>
#include <libnftnl/udata.h>
+#define NFT_MAX_EXPR_LEN_BYTES (NFT_REG32_COUNT * sizeof(uint32_t))
+#define NFT_MAX_EXPR_LEN_BITS (NFT_MAX_EXPR_LEN_BYTES * BITS_PER_BYTE)
+#define NFT_MAX_EXPR_RECURSION 16
+
/**
* enum expr_types
*
@@ -41,6 +44,10 @@
* @EXPR_NUMGEN: number generation expression
* @EXPR_HASH: hash expression
* @EXPR_RT: routing expression
+ * @EXPR_FIB forward information base expression
+ * @EXPR_XFRM XFRM (ipsec) expression
+ * @EXPR_SET_ELEM_CATCHALL catchall element expression
+ * @EXPR_FLAGCMP flagcmp expression
*/
enum expr_types {
EXPR_INVALID,
@@ -72,8 +79,10 @@ enum expr_types {
EXPR_FIB,
EXPR_XFRM,
EXPR_SET_ELEM_CATCHALL,
+ EXPR_FLAGCMP,
+
+ EXPR_MAX = EXPR_FLAGCMP
};
-#define EXPR_MAX EXPR_XFRM
enum ops {
OP_INVALID,
@@ -115,10 +124,15 @@ enum symbol_types {
* @maxval: expected maximum value
*/
struct expr_ctx {
+ /* expr_ctx does not own the reference to dtype. The caller must ensure
+ * the valid lifetime.
+ */
const struct datatype *dtype;
+
enum byteorder byteorder;
unsigned int len;
unsigned int maxval;
+ const struct expr *key;
};
static inline void __expr_set_context(struct expr_ctx *ctx,
@@ -130,6 +144,7 @@ static inline void __expr_set_context(struct expr_ctx *ctx,
ctx->byteorder = byteorder;
ctx->len = len;
ctx->maxval = maxval;
+ ctx->key = NULL;
}
static inline void expr_set_context(struct expr_ctx *ctx,
@@ -178,7 +193,7 @@ struct expr_ops {
};
const struct expr_ops *expr_ops(const struct expr *e);
-const struct expr_ops *expr_ops_by_type(enum expr_types etype);
+const struct expr_ops *expr_ops_by_type_u32(uint32_t value);
/**
* enum expr_flags
@@ -189,6 +204,7 @@ const struct expr_ops *expr_ops_by_type(enum expr_types etype);
* @EXPR_F_INTERVAL_END: set member ends an open interval
* @EXPR_F_BOOLEAN: expression is boolean (set by relational expr on LHS)
* @EXPR_F_INTERVAL: expression describes a interval
+ * @EXPR_F_KERNEL: expression resides in the kernel
*/
enum expr_flags {
EXPR_F_CONSTANT = 0x1,
@@ -197,6 +213,8 @@ enum expr_flags {
EXPR_F_INTERVAL_END = 0x8,
EXPR_F_BOOLEAN = 0x10,
EXPR_F_INTERVAL = 0x20,
+ EXPR_F_KERNEL = 0x40,
+ EXPR_F_REMOVE = 0x80,
};
#include <payload.h>
@@ -237,6 +255,7 @@ struct expr {
enum expr_types etype:8;
enum ops op:8;
unsigned int len;
+ struct cmd *cmd;
union {
struct {
@@ -304,6 +323,7 @@ struct expr {
/* EXPR_PAYLOAD */
const struct proto_desc *desc;
const struct proto_hdr_template *tmpl;
+ const struct proto_desc *inner_desc;
enum proto_bases base;
unsigned int offset;
bool is_raw;
@@ -322,6 +342,7 @@ struct expr {
/* EXPR_META */
enum nft_meta_keys key;
enum proto_bases base;
+ const struct proto_desc *inner_desc;
} meta;
struct {
/* SOCKET */
@@ -370,6 +391,12 @@ struct expr {
uint8_t ttl;
uint32_t flags;
} osf;
+ struct {
+ /* EXPR_FLAGCMP */
+ struct expr *expr;
+ struct expr *mask;
+ struct expr *value;
+ } flagcmp;
};
};
@@ -468,6 +495,7 @@ extern struct expr *compound_expr_alloc(const struct location *loc,
extern void compound_expr_add(struct expr *compound, struct expr *expr);
extern void compound_expr_remove(struct expr *compound, struct expr *expr);
extern void list_expr_sort(struct list_head *head);
+extern void list_splice_sorted(struct list_head *list, struct list_head *head);
extern struct expr *concat_expr_alloc(const struct location *loc);
@@ -475,10 +503,6 @@ extern struct expr *list_expr_alloc(const struct location *loc);
extern struct expr *set_expr_alloc(const struct location *loc,
const struct set *set);
-extern int set_to_intervals(struct list_head *msgs, struct set *set,
- struct expr *init, bool add,
- unsigned int debug_mask, bool merge,
- struct output_ctx *octx);
extern void concat_range_aggregate(struct expr *set);
extern void interval_map_decompose(struct expr *set);
@@ -500,7 +524,12 @@ extern struct expr *set_elem_expr_alloc(const struct location *loc,
struct expr *set_elem_catchall_expr_alloc(const struct location *loc);
+struct expr *flagcmp_expr_alloc(const struct location *loc, enum ops op,
+ struct expr *expr, struct expr *mask,
+ struct expr *value);
+
extern void range_expr_value_low(mpz_t rop, const struct expr *expr);
extern void range_expr_value_high(mpz_t rop, const struct expr *expr);
+void range_expr_swap_values(struct expr *range);
#endif /* NFTABLES_EXPRESSION_H */
diff --git a/include/exthdr.h b/include/exthdr.h
index 1bc756f9..084daba5 100644
--- a/include/exthdr.h
+++ b/include/exthdr.h
@@ -4,6 +4,7 @@
#include <proto.h>
#include <tcpopt.h>
#include <ipopt.h>
+#include <dccpopt.h>
enum exthdr_desc_id {
EXTHDR_DESC_UNKNOWN = 0,
diff --git a/include/gmputil.h b/include/gmputil.h
index 0cb85a7d..d1f4dcd2 100644
--- a/include/gmputil.h
+++ b/include/gmputil.h
@@ -1,8 +1,6 @@
#ifndef NFTABLES_GMPUTIL_H
#define NFTABLES_GMPUTIL_H
-#include <config.h>
-
#ifdef HAVE_LIBGMP
#include <gmp.h>
#else
@@ -79,4 +77,6 @@ extern void __mpz_switch_byteorder(mpz_t rop, unsigned int len);
__mpz_switch_byteorder(rop, len); \
}
+void nft_gmp_free(void *ptr);
+
#endif /* NFTABLES_GMPUTIL_H */
diff --git a/include/headers.h b/include/headers.h
index 759f93bf..13324c72 100644
--- a/include/headers.h
+++ b/include/headers.h
@@ -1,6 +1,8 @@
#ifndef NFTABLES_HEADERS_H
#define NFTABLES_HEADERS_H
+#include <netinet/in.h>
+
#ifndef IPPROTO_UDPLITE
# define IPPROTO_UDPLITE 136
#endif
diff --git a/include/intervals.h b/include/intervals.h
new file mode 100644
index 00000000..ef0fb53e
--- /dev/null
+++ b/include/intervals.h
@@ -0,0 +1,11 @@
+#ifndef NFTABLES_INTERVALS_H
+#define NFTABLES_INTERVALS_H
+
+int set_automerge(struct list_head *msgs, struct cmd *cmd, struct set *set,
+ struct expr *init, unsigned int debug_mask);
+int set_delete(struct list_head *msgs, struct cmd *cmd, struct set *set,
+ struct expr *init, unsigned int debug_mask);
+int set_overlap(struct list_head *msgs, struct set *set, struct expr *init);
+int set_to_intervals(const struct set *set, struct expr *init, bool add);
+
+#endif
diff --git a/include/ipopt.h b/include/ipopt.h
index d8d48066..03420dc6 100644
--- a/include/ipopt.h
+++ b/include/ipopt.h
@@ -6,7 +6,7 @@
#include <statement.h>
extern struct expr *ipopt_expr_alloc(const struct location *loc,
- uint8_t type, uint8_t field, uint8_t ptr);
+ uint8_t type, uint8_t field);
extern void ipopt_init_raw(struct expr *expr, uint8_t type,
unsigned int offset, unsigned int len,
diff --git a/include/json.h b/include/json.h
index 41142208..39be8928 100644
--- a/include/json.h
+++ b/include/json.h
@@ -28,6 +28,7 @@ struct list_head;
json_t *binop_expr_json(const struct expr *expr, struct output_ctx *octx);
json_t *relational_expr_json(const struct expr *expr, struct output_ctx *octx);
+json_t *flagcmp_expr_json(const struct expr *expr, struct output_ctx *octx);
json_t *range_expr_json(const struct expr *expr, struct output_ctx *octx);
json_t *meta_expr_json(const struct expr *expr, struct output_ctx *octx);
json_t *payload_expr_json(const struct expr *expr, struct output_ctx *octx);
@@ -36,6 +37,7 @@ json_t *concat_expr_json(const struct expr *expr, struct output_ctx *octx);
json_t *set_expr_json(const struct expr *expr, struct output_ctx *octx);
json_t *set_ref_expr_json(const struct expr *expr, struct output_ctx *octx);
json_t *set_elem_expr_json(const struct expr *expr, struct output_ctx *octx);
+json_t *set_elem_catchall_expr_json(const struct expr *expr, struct output_ctx *octx);
json_t *prefix_expr_json(const struct expr *expr, struct output_ctx *octx);
json_t *list_expr_json(const struct expr *expr, struct output_ctx *octx);
json_t *unary_expr_json(const struct expr *expr, struct output_ctx *octx);
@@ -67,10 +69,12 @@ json_t *uid_type_json(const struct expr *expr, struct output_ctx *octx);
json_t *gid_type_json(const struct expr *expr, struct output_ctx *octx);
json_t *expr_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
+json_t *flow_offload_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *payload_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *exthdr_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *quota_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *ct_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
+json_t *last_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *limit_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *fwd_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *notrack_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
@@ -80,6 +84,7 @@ json_t *nat_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *reject_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *counter_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *set_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
+json_t *map_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *log_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *objref_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *meter_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
@@ -88,6 +93,8 @@ json_t *verdict_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *connlimit_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *tproxy_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
json_t *synproxy_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
+json_t *optstrip_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
+json_t *xt_stmt_json(const struct stmt *stmt, struct output_ctx *octx);
int do_command_list_json(struct netlink_ctx *ctx, struct cmd *cmd);
@@ -127,6 +134,7 @@ static inline json_t *name##_json(arg1_t arg1, arg2_t arg2) { return NULL; }
JSON_PRINT_STUB(name##_stmt, const struct stmt *, struct output_ctx *)
EXPR_PRINT_STUB(binop_expr)
+EXPR_PRINT_STUB(flagcmp_expr)
EXPR_PRINT_STUB(relational_expr)
EXPR_PRINT_STUB(range_expr)
EXPR_PRINT_STUB(meta_expr)
@@ -144,6 +152,7 @@ EXPR_PRINT_STUB(map_expr)
EXPR_PRINT_STUB(exthdr_expr)
EXPR_PRINT_STUB(verdict_expr)
EXPR_PRINT_STUB(rt_expr)
+EXPR_PRINT_STUB(set_elem_catchall_expr)
EXPR_PRINT_STUB(numgen_expr)
EXPR_PRINT_STUB(hash_expr)
EXPR_PRINT_STUB(fib_expr)
@@ -165,10 +174,12 @@ EXPR_PRINT_STUB(uid_type)
EXPR_PRINT_STUB(gid_type)
STMT_PRINT_STUB(expr)
+STMT_PRINT_STUB(flow_offload)
STMT_PRINT_STUB(payload)
STMT_PRINT_STUB(exthdr)
STMT_PRINT_STUB(quota)
STMT_PRINT_STUB(ct)
+STMT_PRINT_STUB(last)
STMT_PRINT_STUB(limit)
STMT_PRINT_STUB(fwd)
STMT_PRINT_STUB(notrack)
@@ -178,6 +189,7 @@ STMT_PRINT_STUB(nat)
STMT_PRINT_STUB(reject)
STMT_PRINT_STUB(counter)
STMT_PRINT_STUB(set)
+STMT_PRINT_STUB(map)
STMT_PRINT_STUB(log)
STMT_PRINT_STUB(objref)
STMT_PRINT_STUB(meter)
@@ -186,6 +198,8 @@ STMT_PRINT_STUB(verdict)
STMT_PRINT_STUB(connlimit)
STMT_PRINT_STUB(tproxy)
STMT_PRINT_STUB(synproxy)
+STMT_PRINT_STUB(optstrip)
+STMT_PRINT_STUB(xt)
#undef STMT_PRINT_STUB
#undef EXPR_PRINT_STUB
diff --git a/include/linux/Makefile.am b/include/linux/Makefile.am
deleted file mode 100644
index eb9fc4e4..00000000
--- a/include/linux/Makefile.am
+++ /dev/null
@@ -1,12 +0,0 @@
-SUBDIRS = netfilter \
- netfilter_arp \
- netfilter_bridge \
- netfilter_ipv4 \
- netfilter_ipv6
-
-noinst_HEADERS = netfilter_arp.h \
- netfilter_bridge.h \
- netfilter_decnet.h \
- netfilter.h \
- netfilter_ipv4.h \
- netfilter_ipv6.h
diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h
index feb6287c..9e078880 100644
--- a/include/linux/netfilter.h
+++ b/include/linux/netfilter.h
@@ -54,6 +54,7 @@ enum nf_inet_hooks {
enum nf_dev_hooks {
NF_NETDEV_INGRESS,
+ NF_NETDEV_EGRESS,
NF_NETDEV_NUMHOOKS
};
diff --git a/include/linux/netfilter/Makefile.am b/include/linux/netfilter/Makefile.am
deleted file mode 100644
index 04c9ab80..00000000
--- a/include/linux/netfilter/Makefile.am
+++ /dev/null
@@ -1,9 +0,0 @@
-noinst_HEADERS = nf_conntrack_common.h \
- nf_conntrack_tuple_common.h \
- nf_log.h \
- nf_nat.h \
- nf_tables.h \
- nf_tables_compat.h \
- nf_synproxy.h \
- nfnetlink_osf.h \
- nfnetlink.h
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
index 894a62cf..c62e6ac5 100644
--- a/include/linux/netfilter/nf_tables.h
+++ b/include/linux/netfilter/nf_tables.h
@@ -97,6 +97,15 @@ enum nft_verdicts {
* @NFT_MSG_NEWFLOWTABLE: add new flow table (enum nft_flowtable_attributes)
* @NFT_MSG_GETFLOWTABLE: get flow table (enum nft_flowtable_attributes)
* @NFT_MSG_DELFLOWTABLE: delete flow table (enum nft_flowtable_attributes)
+ * @NFT_MSG_GETRULE_RESET: get rules and reset stateful expressions (enum nft_obj_attributes)
+ * @NFT_MSG_DESTROYTABLE: destroy a table (enum nft_table_attributes)
+ * @NFT_MSG_DESTROYCHAIN: destroy a chain (enum nft_chain_attributes)
+ * @NFT_MSG_DESTROYRULE: destroy a rule (enum nft_rule_attributes)
+ * @NFT_MSG_DESTROYSET: destroy a set (enum nft_set_attributes)
+ * @NFT_MSG_DESTROYSETELEM: destroy a set element (enum nft_set_elem_attributes)
+ * @NFT_MSG_DESTROYOBJ: destroy a stateful object (enum nft_object_attributes)
+ * @NFT_MSG_DESTROYFLOWTABLE: destroy flow table (enum nft_flowtable_attributes)
+ * @NFT_MSG_GETSETELEM_RESET: get set elements and reset attached stateful expressio ns (enum nft_set_elem_attributes)
*/
enum nf_tables_msg_types {
NFT_MSG_NEWTABLE,
@@ -124,6 +133,15 @@ enum nf_tables_msg_types {
NFT_MSG_NEWFLOWTABLE,
NFT_MSG_GETFLOWTABLE,
NFT_MSG_DELFLOWTABLE,
+ NFT_MSG_GETRULE_RESET,
+ NFT_MSG_DESTROYTABLE,
+ NFT_MSG_DESTROYCHAIN,
+ NFT_MSG_DESTROYRULE,
+ NFT_MSG_DESTROYSET,
+ NFT_MSG_DESTROYSETELEM,
+ NFT_MSG_DESTROYOBJ,
+ NFT_MSG_DESTROYFLOWTABLE,
+ NFT_MSG_GETSETELEM_RESET,
NFT_MSG_MAX,
};
@@ -164,7 +182,10 @@ enum nft_hook_attributes {
*/
enum nft_table_flags {
NFT_TABLE_F_DORMANT = 0x1,
+ NFT_TABLE_F_OWNER = 0x2,
};
+#define NFT_TABLE_F_MASK (NFT_TABLE_F_DORMANT | \
+ NFT_TABLE_F_OWNER)
/**
* enum nft_table_attributes - nf_tables table netlink attributes
@@ -173,6 +194,7 @@ enum nft_table_flags {
* @NFTA_TABLE_FLAGS: bitmask of enum nft_table_flags (NLA_U32)
* @NFTA_TABLE_USE: number of chains in this table (NLA_U32)
* @NFTA_TABLE_USERDATA: user data (NLA_BINARY)
+ * @NFTA_TABLE_OWNER: owner of this table through netlink portID (NLA_U32)
*/
enum nft_table_attributes {
NFTA_TABLE_UNSPEC,
@@ -182,6 +204,7 @@ enum nft_table_attributes {
NFTA_TABLE_HANDLE,
NFTA_TABLE_PAD,
NFTA_TABLE_USERDATA,
+ NFTA_TABLE_OWNER,
__NFTA_TABLE_MAX
};
#define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1)
@@ -748,11 +771,14 @@ enum nft_dynset_attributes {
* @NFT_PAYLOAD_LL_HEADER: link layer header
* @NFT_PAYLOAD_NETWORK_HEADER: network header
* @NFT_PAYLOAD_TRANSPORT_HEADER: transport header
+ * @NFT_PAYLOAD_INNER_HEADER: inner header / payload
*/
enum nft_payload_bases {
NFT_PAYLOAD_LL_HEADER,
NFT_PAYLOAD_NETWORK_HEADER,
NFT_PAYLOAD_TRANSPORT_HEADER,
+ NFT_PAYLOAD_INNER_HEADER,
+ NFT_PAYLOAD_TUN_HEADER,
};
/**
@@ -772,6 +798,32 @@ enum nft_payload_csum_flags {
NFT_PAYLOAD_L4CSUM_PSEUDOHDR = (1 << 0),
};
+enum nft_inner_type {
+ NFT_INNER_UNSPEC = 0,
+ NFT_INNER_VXLAN,
+ NFT_INNER_GENEVE,
+};
+
+enum nft_inner_flags {
+ NFT_INNER_HDRSIZE = (1 << 0),
+ NFT_INNER_LL = (1 << 1),
+ NFT_INNER_NH = (1 << 2),
+ NFT_INNER_TH = (1 << 3),
+};
+#define NFT_INNER_MASK (NFT_INNER_HDRSIZE | NFT_INNER_LL | \
+ NFT_INNER_NH | NFT_INNER_TH)
+
+enum nft_inner_attributes {
+ NFTA_INNER_UNSPEC,
+ NFTA_INNER_NUM,
+ NFTA_INNER_TYPE,
+ NFTA_INNER_FLAGS,
+ NFTA_INNER_HDRSIZE,
+ NFTA_INNER_EXPR,
+ __NFTA_INNER_MAX
+};
+#define NFTA_INNER_MAX (__NFTA_INNER_MAX - 1)
+
/**
* enum nft_payload_attributes - nf_tables payload expression netlink attributes
*
@@ -808,11 +860,15 @@ enum nft_exthdr_flags {
* @NFT_EXTHDR_OP_IPV6: match against ipv6 extension headers
* @NFT_EXTHDR_OP_TCP: match against tcp options
* @NFT_EXTHDR_OP_IPV4: match against ipv4 options
+ * @NFT_EXTHDR_OP_SCTP: match against sctp chunks
+ * @NFT_EXTHDR_OP_DCCP: match against dccp options
*/
enum nft_exthdr_op {
NFT_EXTHDR_OP_IPV6,
NFT_EXTHDR_OP_TCPOPT,
NFT_EXTHDR_OP_IPV4,
+ NFT_EXTHDR_OP_SCTP,
+ NFT_EXTHDR_OP_DCCP,
__NFT_EXTHDR_OP_MAX
};
#define NFT_EXTHDR_OP_MAX (__NFT_EXTHDR_OP_MAX - 1)
@@ -879,6 +935,7 @@ enum nft_exthdr_attributes {
* @NFT_META_TIME_HOUR: hour of day (in seconds)
* @NFT_META_SDIF: slave device interface index
* @NFT_META_SDIFNAME: slave device interface name
+ * @NFT_META_BRI_BROUTE: packet br_netfilter_broute bit
*/
enum nft_meta_keys {
NFT_META_LEN,
@@ -889,7 +946,8 @@ enum nft_meta_keys {
NFT_META_OIF,
NFT_META_IIFNAME,
NFT_META_OIFNAME,
- NFT_META_IIFTYPE,
+ NFT_META_IFTYPE,
+#define NFT_META_IIFTYPE NFT_META_IFTYPE
NFT_META_OIFTYPE,
NFT_META_SKUID,
NFT_META_SKGID,
@@ -916,6 +974,8 @@ enum nft_meta_keys {
NFT_META_TIME_HOUR,
NFT_META_SDIF,
NFT_META_SDIFNAME,
+ NFT_META_BRI_BROUTE,
+ __NFT_META_IIFTYPE,
};
/**
@@ -1011,6 +1071,7 @@ enum nft_rt_attributes {
*
* @NFTA_SOCKET_KEY: socket key to match
* @NFTA_SOCKET_DREG: destination register
+ * @NFTA_SOCKET_LEVEL: cgroups2 ancestor level (only for cgroupsv2)
*/
enum nft_socket_attributes {
NFTA_SOCKET_UNSPEC,
@@ -1027,6 +1088,7 @@ enum nft_socket_attributes {
* @NFT_SOCKET_TRANSPARENT: Value of the IP(V6)_TRANSPARENT socket option
* @NFT_SOCKET_MARK: Value of the socket mark
* @NFT_SOCKET_WILDCARD: Whether the socket is zero-bound (e.g. 0.0.0.0 or ::0)
+ * @NFT_SOCKET_CGROUPV2: Match on cgroups version 2
*/
enum nft_socket_keys {
NFT_SOCKET_TRANSPARENT,
@@ -1187,6 +1249,21 @@ enum nft_counter_attributes {
#define NFTA_COUNTER_MAX (__NFTA_COUNTER_MAX - 1)
/**
+ * enum nft_last_attributes - nf_tables last expression netlink attributes
+ *
+ * @NFTA_LAST_SET: last update has been set, zero means never updated (NLA_U32)
+ * @NFTA_LAST_MSECS: milliseconds since last update (NLA_U64)
+ */
+enum nft_last_attributes {
+ NFTA_LAST_UNSPEC,
+ NFTA_LAST_SET,
+ NFTA_LAST_MSECS,
+ NFTA_LAST_PAD,
+ __NFTA_LAST_MAX
+};
+#define NFTA_LAST_MAX (__NFTA_LAST_MAX - 1)
+
+/**
* enum nft_log_attributes - nf_tables log expression netlink attributes
*
* @NFTA_LOG_GROUP: netlink group to send messages to (NLA_U32)
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h
index 454f78d0..49e2b2c5 100644
--- a/include/linux/netfilter/nfnetlink.h
+++ b/include/linux/netfilter/nfnetlink.h
@@ -59,7 +59,8 @@ struct nfgenmsg {
#define NFNL_SUBSYS_CTHELPER 9
#define NFNL_SUBSYS_NFTABLES 10
#define NFNL_SUBSYS_NFT_COMPAT 11
-#define NFNL_SUBSYS_COUNT 12
+#define NFNL_SUBSYS_HOOK 12
+#define NFNL_SUBSYS_COUNT 13
/* Reserved control nfnetlink messages */
#define NFNL_MSG_BATCH_BEGIN NLMSG_MIN_TYPE
diff --git a/include/linux/netfilter/nfnetlink_hook.h b/include/linux/netfilter/nfnetlink_hook.h
new file mode 100644
index 00000000..84a561a7
--- /dev/null
+++ b/include/linux/netfilter/nfnetlink_hook.h
@@ -0,0 +1,82 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef _NFNL_HOOK_H_
+#define _NFNL_HOOK_H_
+
+enum nfnl_hook_msg_types {
+ NFNL_MSG_HOOK_GET,
+ NFNL_MSG_HOOK_MAX,
+};
+
+/**
+ * enum nfnl_hook_attributes - netfilter hook netlink attributes
+ *
+ * @NFNLA_HOOK_HOOKNUM: netfilter hook number (NLA_U32)
+ * @NFNLA_HOOK_PRIORITY: netfilter hook priority (NLA_U32)
+ * @NFNLA_HOOK_DEV: netdevice name (NLA_STRING)
+ * @NFNLA_HOOK_FUNCTION_NAME: hook function name (NLA_STRING)
+ * @NFNLA_HOOK_MODULE_NAME: kernel module that registered this hook (NLA_STRING)
+ * @NFNLA_HOOK_CHAIN_INFO: basechain hook metadata (NLA_NESTED)
+ */
+enum nfnl_hook_attributes {
+ NFNLA_HOOK_UNSPEC,
+ NFNLA_HOOK_HOOKNUM,
+ NFNLA_HOOK_PRIORITY,
+ NFNLA_HOOK_DEV,
+ NFNLA_HOOK_FUNCTION_NAME,
+ NFNLA_HOOK_MODULE_NAME,
+ NFNLA_HOOK_CHAIN_INFO,
+ __NFNLA_HOOK_MAX
+};
+#define NFNLA_HOOK_MAX (__NFNLA_HOOK_MAX - 1)
+
+/**
+ * enum nfnl_hook_chain_info_attributes - chain description
+ *
+ * @NFNLA_HOOK_INFO_DESC: nft chain and table name (NLA_NESTED)
+ * @NFNLA_HOOK_INFO_TYPE: chain type (enum nfnl_hook_chaintype) (NLA_U32)
+ *
+ * NFNLA_HOOK_INFO_DESC depends on NFNLA_HOOK_INFO_TYPE value:
+ * NFNL_HOOK_TYPE_NFTABLES: enum nft_table_attributes
+ * NFNL_HOOK_TYPE_BPF: enum nfnl_hook_bpf_attributes
+ */
+enum nfnl_hook_chain_info_attributes {
+ NFNLA_HOOK_INFO_UNSPEC,
+ NFNLA_HOOK_INFO_DESC,
+ NFNLA_HOOK_INFO_TYPE,
+ __NFNLA_HOOK_INFO_MAX,
+};
+#define NFNLA_HOOK_INFO_MAX (__NFNLA_HOOK_INFO_MAX - 1)
+
+enum nfnl_hook_chain_desc_attributes {
+ NFNLA_CHAIN_UNSPEC,
+ NFNLA_CHAIN_TABLE,
+ NFNLA_CHAIN_FAMILY,
+ NFNLA_CHAIN_NAME,
+ __NFNLA_CHAIN_MAX,
+};
+#define NFNLA_CHAIN_MAX (__NFNLA_CHAIN_MAX - 1)
+
+/**
+ * enum nfnl_hook_chaintype - chain type
+ *
+ * @NFNL_HOOK_TYPE_NFTABLES: nf_tables base chain
+ * @NFNL_HOOK_TYPE_BPF: bpf program
+ */
+enum nfnl_hook_chaintype {
+ NFNL_HOOK_TYPE_NFTABLES = 0x1,
+ NFNL_HOOK_TYPE_BPF,
+};
+
+/**
+ * enum nfnl_hook_bpf_attributes - bpf prog description
+ *
+ * @NFNLA_HOOK_BPF_ID: bpf program id (NLA_U32)
+ */
+enum nfnl_hook_bpf_attributes {
+ NFNLA_HOOK_BPF_UNSPEC,
+ NFNLA_HOOK_BPF_ID,
+ __NFNLA_HOOK_BPF_MAX,
+};
+#define NFNLA_HOOK_BPF_MAX (__NFNLA_HOOK_BPF_MAX - 1)
+
+#endif /* _NFNL_HOOK_H */
diff --git a/include/linux/netfilter_arp/Makefile.am b/include/linux/netfilter_arp/Makefile.am
deleted file mode 100644
index 0a16c1ab..00000000
--- a/include/linux/netfilter_arp/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-noinst_HEADERS = arp_tables.h
diff --git a/include/linux/netfilter_bridge/Makefile.am b/include/linux/netfilter_bridge/Makefile.am
deleted file mode 100644
index d2e8b38b..00000000
--- a/include/linux/netfilter_bridge/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-noinst_HEADERS = ebtables.h
diff --git a/include/linux/netfilter_ipv4/Makefile.am b/include/linux/netfilter_ipv4/Makefile.am
deleted file mode 100644
index fec42533..00000000
--- a/include/linux/netfilter_ipv4/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-noinst_HEADERS = ip_tables.h
diff --git a/include/linux/netfilter_ipv6/Makefile.am b/include/linux/netfilter_ipv6/Makefile.am
deleted file mode 100644
index bec6c3f1..00000000
--- a/include/linux/netfilter_ipv6/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-noinst_HEADERS = ip6_tables.h
diff --git a/include/meta.h b/include/meta.h
index 1478902e..af2d772b 100644
--- a/include/meta.h
+++ b/include/meta.h
@@ -45,4 +45,6 @@ extern const struct datatype date_type;
extern const struct datatype hour_type;
extern const struct datatype day_type;
+bool lhs_is_meta_hour(const struct expr *meta);
+
#endif /* NFTABLES_META_H */
diff --git a/include/mnl.h b/include/mnl.h
index 979929c3..cd5a2053 100644
--- a/include/mnl.h
+++ b/include/mnl.h
@@ -33,8 +33,10 @@ int mnl_nft_rule_add(struct netlink_ctx *ctx, struct cmd *cmd,
int mnl_nft_rule_del(struct netlink_ctx *ctx, struct cmd *cmd);
int mnl_nft_rule_replace(struct netlink_ctx *ctx, struct cmd *cmd);
-struct nftnl_rule_list *mnl_nft_rule_dump(struct netlink_ctx *ctx,
- int family);
+struct nftnl_rule_list *mnl_nft_rule_dump(struct netlink_ctx *ctx, int family,
+ const char *table, const char *chain,
+ uint64_t rule_handle,
+ bool dump, bool reset);
int mnl_nft_chain_add(struct netlink_ctx *ctx, struct cmd *cmd,
unsigned int flags);
@@ -43,29 +45,34 @@ int mnl_nft_chain_rename(struct netlink_ctx *ctx, const struct cmd *cmd,
const struct chain *chain);
struct nftnl_chain_list *mnl_nft_chain_dump(struct netlink_ctx *ctx,
- int family);
+ int family, const char *table,
+ const char *chain);
int mnl_nft_table_add(struct netlink_ctx *ctx, struct cmd *cmd,
unsigned int flags);
int mnl_nft_table_del(struct netlink_ctx *ctx, struct cmd *cmd);
struct nftnl_table_list *mnl_nft_table_dump(struct netlink_ctx *ctx,
- int family);
+ int family, const char *table);
int mnl_nft_set_add(struct netlink_ctx *ctx, struct cmd *cmd,
unsigned int flags);
int mnl_nft_set_del(struct netlink_ctx *ctx, struct cmd *cmd);
struct nftnl_set_list *mnl_nft_set_dump(struct netlink_ctx *ctx, int family,
- const char *table);
+ const char *table, const char *set);
-int mnl_nft_setelem_add(struct netlink_ctx *ctx, const struct set *set,
- const struct expr *expr, unsigned int flags);
-int mnl_nft_setelem_del(struct netlink_ctx *ctx, const struct cmd *cmd);
+int mnl_nft_setelem_add(struct netlink_ctx *ctx, struct cmd *cmd,
+ const struct set *set, const struct expr *expr,
+ unsigned int flags);
+int mnl_nft_setelem_del(struct netlink_ctx *ctx, struct cmd *cmd,
+ const struct handle *h, const struct expr *init);
int mnl_nft_setelem_flush(struct netlink_ctx *ctx, const struct cmd *cmd);
-int mnl_nft_setelem_get(struct netlink_ctx *ctx, struct nftnl_set *nls);
+int mnl_nft_setelem_get(struct netlink_ctx *ctx, struct nftnl_set *nls,
+ bool reset);
struct nftnl_set *mnl_nft_setelem_get_one(struct netlink_ctx *ctx,
- struct nftnl_set *nls);
+ struct nftnl_set *nls,
+ bool reset);
struct nftnl_obj_list *mnl_nft_obj_dump(struct netlink_ctx *ctx, int family,
const char *table,
@@ -76,12 +83,16 @@ int mnl_nft_obj_add(struct netlink_ctx *ctx, struct cmd *cmd,
int mnl_nft_obj_del(struct netlink_ctx *ctx, struct cmd *cmd, int type);
struct nftnl_flowtable_list *
-mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family, const char *table);
+mnl_nft_flowtable_dump(struct netlink_ctx *ctx, int family,
+ const char *table, const char *ft);
int mnl_nft_flowtable_add(struct netlink_ctx *ctx, struct cmd *cmd,
unsigned int flags);
int mnl_nft_flowtable_del(struct netlink_ctx *ctx, struct cmd *cmd);
+int mnl_nft_dump_nf_hooks(struct netlink_ctx *ctx, int family, int hook,
+ const char *devname);
+
int mnl_nft_event_listener(struct mnl_socket *nf_sock, unsigned int debug_mask,
struct output_ctx *octx,
int (*cb)(const struct nlmsghdr *nlh, void *data),
diff --git a/include/netlink.h b/include/netlink.h
index a7c524ca..27a62462 100644
--- a/include/netlink.h
+++ b/include/netlink.h
@@ -39,12 +39,29 @@ struct netlink_parse_ctx {
struct stmt *stmt;
struct expr *registers[MAX_REGS + 1];
unsigned int debug_mask;
+ struct netlink_ctx *nlctx;
+ bool inner;
+ uint8_t inner_reg;
};
-struct rule_pp_ctx {
+
+#define RULE_PP_IN_CONCATENATION (1 << 0)
+#define RULE_PP_IN_SET_ELEM (1 << 1)
+
+#define RULE_PP_REMOVE_OP_AND (RULE_PP_IN_CONCATENATION | \
+ RULE_PP_IN_SET_ELEM)
+
+struct dl_proto_ctx {
struct proto_ctx pctx;
struct payload_dep_ctx pdctx;
+};
+
+struct rule_pp_ctx {
+ struct dl_proto_ctx _dl[2];
+ struct dl_proto_ctx *dl;
struct stmt *stmt;
+ unsigned int flags;
+ struct set *set;
};
extern const struct input_descriptor indesc_netlink;
@@ -68,10 +85,13 @@ struct netlink_ctx {
const void *data;
uint32_t seqnum;
struct nftnl_batch *batch;
+ int maybe_emsgsize;
};
extern struct nftnl_expr *alloc_nft_expr(const char *name);
extern void alloc_setelem_cache(const struct expr *set, struct nftnl_set *nls);
+struct nftnl_set_elem *alloc_nftnl_setelem(const struct expr *set,
+ const struct expr *expr);
extern struct nftnl_table *netlink_table_alloc(const struct nlmsghdr *nlh);
extern struct nftnl_chain *netlink_chain_alloc(const struct nlmsghdr *nlh);
@@ -81,7 +101,7 @@ extern struct nftnl_rule *netlink_rule_alloc(const struct nlmsghdr *nlh);
struct nft_data_linearize {
uint32_t len;
- uint32_t value[4];
+ uint32_t value[NFT_REG32_COUNT];
char chain[NFT_CHAIN_MAXNAMELEN];
uint32_t chain_id;
int verdict;
@@ -122,8 +142,6 @@ extern struct expr *netlink_alloc_data(const struct location *loc,
const struct nft_data_delinearize *nld,
enum nft_registers dreg);
-extern int netlink_list_rules(struct netlink_ctx *ctx, const struct handle *h);
-
struct netlink_linearize_ctx;
extern void netlink_linearize_rule(struct netlink_ctx *ctx,
const struct rule *rule,
@@ -135,7 +153,8 @@ extern int netlink_list_chains(struct netlink_ctx *ctx, const struct handle *h);
extern struct chain *netlink_delinearize_chain(struct netlink_ctx *ctx,
const struct nftnl_chain *nlc);
-extern int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h);
+extern int netlink_list_tables(struct netlink_ctx *ctx, const struct handle *h,
+ const struct nft_cache_filter *filter);
extern struct table *netlink_delinearize_table(struct netlink_ctx *ctx,
const struct nftnl_table *nlt);
@@ -147,10 +166,11 @@ extern struct stmt *netlink_parse_set_expr(const struct set *set,
const struct nftnl_expr *nle);
extern int netlink_list_setelems(struct netlink_ctx *ctx,
- const struct handle *h, struct set *set);
+ const struct handle *h, struct set *set,
+ bool reset);
extern int netlink_get_setelem(struct netlink_ctx *ctx, const struct handle *h,
const struct location *loc, struct set *cache_set,
- struct set *set, struct expr *init);
+ struct set *set, struct expr *init, bool reset);
extern int netlink_delinearize_setelem(struct nftnl_set_elem *nlse,
struct set *set,
struct nft_cache *cache);
@@ -166,6 +186,9 @@ extern int netlink_list_flowtables(struct netlink_ctx *ctx,
extern struct flowtable *netlink_delinearize_flowtable(struct netlink_ctx *ctx,
struct nftnl_flowtable *nlo);
+extern int netlink_reset_rules(struct netlink_ctx *ctx, const struct cmd *cmd,
+ bool dump);
+
extern void netlink_dump_chain(const struct nftnl_chain *nlc,
struct netlink_ctx *ctx);
extern void netlink_dump_rule(const struct nftnl_rule *nlr,
@@ -181,7 +204,7 @@ extern void netlink_dump_flowtable(struct nftnl_flowtable *flo, struct netlink_c
__netlink_abi_error(__FILE__, __LINE__, strerror(errno));
extern void __noreturn __netlink_abi_error(const char *file, int line, const char *reason);
extern int netlink_io_error(struct netlink_ctx *ctx,
- const struct location *loc, const char *fmt, ...);
+ const struct location *loc, const char *fmt, ...) __attribute__((format(printf, 3, 4)));
#define netlink_init_error() \
__netlink_init_error(__FILE__, __LINE__, strerror(errno));
extern void __noreturn __netlink_init_error(const char *file, int line, const char *reason);
@@ -215,9 +238,6 @@ int netlink_events_trace_cb(const struct nlmsghdr *nlh, int type,
enum nft_data_types dtype_map_to_kernel(const struct datatype *dtype);
-void expr_handler_init(void);
-void expr_handler_exit(void);
-
void netlink_linearize_init(struct netlink_linearize_ctx *lctx,
struct nftnl_rule *nlr);
void netlink_linearize_fini(struct netlink_linearize_ctx *lctx);
@@ -239,4 +259,6 @@ struct nft_expr_loc {
struct nft_expr_loc *nft_expr_loc_find(const struct nftnl_expr *nle,
struct netlink_linearize_ctx *ctx);
+struct dl_proto_ctx *dl_proto_ctx(struct rule_pp_ctx *ctx);
+
#endif /* NFTABLES_NETLINK_H */
diff --git a/include/nft.h b/include/nft.h
new file mode 100644
index 00000000..a2d62dbf
--- /dev/null
+++ b/include/nft.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef NFTABLES_NFT_H
+#define NFTABLES_NFT_H
+
+#include <config.h>
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Just free(), but casts to a (void*). This is for places where
+ * we have a const pointer that we know we want to free. We could just
+ * do the (void*) cast, but free_const() makes it clear that this is
+ * something we frequently need to do and it's intentional. */
+#define free_const(ptr) free((void *)(ptr))
+
+#endif /* NFTABLES_NFT_H */
diff --git a/include/nftables.h b/include/nftables.h
index f239fcf0..4b7c3359 100644
--- a/include/nftables.h
+++ b/include/nftables.h
@@ -1,7 +1,6 @@
#ifndef NFTABLES_NFTABLES_H
#define NFTABLES_NFTABLES_H
-#include <stdbool.h>
#include <stdarg.h>
#include <limits.h>
#include <utils.h>
@@ -23,6 +22,20 @@ struct symbol_tables {
const struct symbol_table *realm;
};
+struct input_ctx {
+ unsigned int flags;
+};
+
+static inline bool nft_input_no_dns(const struct input_ctx *ictx)
+{
+ return ictx->flags & NFT_CTX_INPUT_NO_DNS;
+}
+
+static inline bool nft_input_json(const struct input_ctx *ictx)
+{
+ return ictx->flags & NFT_CTX_INPUT_JSON;
+}
+
struct output_ctx {
unsigned int flags;
union {
@@ -100,23 +113,37 @@ struct mnl_socket;
struct parser_state;
struct scope;
+struct nft_vars {
+ const char *key;
+ const char *value;
+};
+
#define MAX_INCLUDE_DEPTH 16
struct nft_ctx {
struct mnl_socket *nf_sock;
char **include_paths;
unsigned int num_include_paths;
+ struct nft_vars *vars;
+ struct {
+ const char *buf;
+ struct list_head indesc_list;
+ } vars_ctx;
+ unsigned int num_vars;
unsigned int parser_max_errors;
unsigned int debug_mask;
+ struct input_ctx input;
struct output_ctx output;
bool check;
struct nft_cache cache;
uint32_t flags;
+ uint32_t optimize_flags;
struct parser_state *state;
void *scanner;
struct scope *top_scope;
void *json_root;
json_t *json_echo;
+ const char *stdin_buf;
};
enum nftables_exit_codes {
@@ -164,6 +191,7 @@ enum input_descriptor_types {
INDESC_FILE,
INDESC_CLI,
INDESC_NETLINK,
+ INDESC_STDIN,
};
/**
@@ -196,7 +224,6 @@ struct input_descriptor {
void ct_label_table_init(struct nft_ctx *ctx);
void mark_table_init(struct nft_ctx *ctx);
-void gmp_init(void);
void realm_table_rt_init(struct nft_ctx *ctx);
void devgroup_table_init(struct nft_ctx *ctx);
void xt_init(void);
@@ -208,8 +235,9 @@ void realm_table_rt_exit(struct nft_ctx *ctx);
int nft_print(struct output_ctx *octx, const char *fmt, ...)
__attribute__((format(printf, 2, 3)));
-int nft_gmp_print(struct output_ctx *octx, const char *fmt, ...)
- __attribute__((format(printf, 2, 0)));
+int nft_gmp_print(struct output_ctx *octx, const char *fmt, ...);
+
+int nft_optimize(struct nft_ctx *nft, struct list_head *cmds);
#define __NFT_OUTPUT_NOTSUPP UINT_MAX
diff --git a/include/nftables/Makefile.am b/include/nftables/Makefile.am
deleted file mode 100644
index 5cfb0c6c..00000000
--- a/include/nftables/Makefile.am
+++ /dev/null
@@ -1 +0,0 @@
-pkginclude_HEADERS = libnftables.h
diff --git a/include/nftables/libnftables.h b/include/nftables/libnftables.h
index 765b20dd..c1d48d76 100644
--- a/include/nftables/libnftables.h
+++ b/include/nftables/libnftables.h
@@ -9,7 +9,6 @@
#ifndef LIB_NFTABLES_H
#define LIB_NFTABLES_H
-#define _GNU_SOURCE
#include <stdint.h>
#include <stdio.h>
#include <stdbool.h>
@@ -41,6 +40,21 @@ void nft_ctx_free(struct nft_ctx *ctx);
bool nft_ctx_get_dry_run(struct nft_ctx *ctx);
void nft_ctx_set_dry_run(struct nft_ctx *ctx, bool dry);
+enum nft_optimize_flags {
+ NFT_OPTIMIZE_ENABLED = 0x1,
+};
+
+uint32_t nft_ctx_get_optimize(struct nft_ctx *ctx);
+void nft_ctx_set_optimize(struct nft_ctx *ctx, uint32_t flags);
+
+enum {
+ NFT_CTX_INPUT_NO_DNS = (1 << 0),
+ NFT_CTX_INPUT_JSON = (1 << 1),
+};
+
+unsigned int nft_ctx_input_get_flags(struct nft_ctx *ctx);
+unsigned int nft_ctx_input_set_flags(struct nft_ctx *ctx, unsigned int flags);
+
enum {
NFT_CTX_OUTPUT_REVERSEDNS = (1 << 0),
NFT_CTX_OUTPUT_SERVICE = (1 << 1),
@@ -55,7 +69,8 @@ enum {
NFT_CTX_OUTPUT_NUMERIC_TIME = (1 << 10),
NFT_CTX_OUTPUT_NUMERIC_ALL = (NFT_CTX_OUTPUT_NUMERIC_PROTO |
NFT_CTX_OUTPUT_NUMERIC_PRIO |
- NFT_CTX_OUTPUT_NUMERIC_SYMBOL),
+ NFT_CTX_OUTPUT_NUMERIC_SYMBOL |
+ NFT_CTX_OUTPUT_NUMERIC_TIME),
NFT_CTX_OUTPUT_TERSE = (1 << 11),
};
@@ -78,6 +93,9 @@ const char *nft_ctx_get_error_buffer(struct nft_ctx *ctx);
int nft_ctx_add_include_path(struct nft_ctx *ctx, const char *path);
void nft_ctx_clear_include_paths(struct nft_ctx *ctx);
+int nft_ctx_add_var(struct nft_ctx *ctx, const char *var);
+void nft_ctx_clear_vars(struct nft_ctx *ctx);
+
int nft_run_cmd_from_buffer(struct nft_ctx *nft, const char *buf);
int nft_run_cmd_from_filename(struct nft_ctx *nft, const char *filename);
diff --git a/include/parser.h b/include/parser.h
index d890ab22..f79a22f3 100644
--- a/include/parser.h
+++ b/include/parser.h
@@ -22,33 +22,73 @@ struct parser_state {
struct scope *scopes[SCOPE_NEST_MAX];
unsigned int scope;
+ bool scope_err;
unsigned int flex_state_pop;
unsigned int startcond_type;
struct list_head *cmds;
+ unsigned int *startcond_active;
};
enum startcond_type {
PARSER_SC_BEGIN,
PARSER_SC_ARP,
+ PARSER_SC_AT,
PARSER_SC_CT,
PARSER_SC_COUNTER,
PARSER_SC_ETH,
+ PARSER_SC_GRE,
+ PARSER_SC_ICMP,
+ PARSER_SC_IGMP,
PARSER_SC_IP,
PARSER_SC_IP6,
+ PARSER_SC_LAST,
PARSER_SC_LIMIT,
+ PARSER_SC_META,
+ PARSER_SC_POLICY,
PARSER_SC_QUOTA,
+ PARSER_SC_SCTP,
PARSER_SC_SECMARK,
+ PARSER_SC_TCP,
+ PARSER_SC_TYPE,
PARSER_SC_VLAN,
+ PARSER_SC_XT,
+ PARSER_SC_CMD_DESTROY,
+ PARSER_SC_CMD_EXPORT,
+ PARSER_SC_CMD_IMPORT,
+ PARSER_SC_CMD_LIST,
+ PARSER_SC_CMD_MONITOR,
+ PARSER_SC_CMD_RESET,
+ PARSER_SC_EXPR_AH,
+ PARSER_SC_EXPR_COMP,
+ PARSER_SC_EXPR_DCCP,
+ PARSER_SC_EXPR_DST,
+ PARSER_SC_EXPR_ESP,
PARSER_SC_EXPR_FIB,
+ PARSER_SC_EXPR_FRAG,
PARSER_SC_EXPR_HASH,
+ PARSER_SC_EXPR_HBH,
PARSER_SC_EXPR_IPSEC,
+ PARSER_SC_EXPR_MH,
PARSER_SC_EXPR_NUMGEN,
+ PARSER_SC_EXPR_OSF,
PARSER_SC_EXPR_QUEUE,
PARSER_SC_EXPR_RT,
+ PARSER_SC_EXPR_SCTP_CHUNK,
PARSER_SC_EXPR_SOCKET,
+ PARSER_SC_EXPR_TH,
+ PARSER_SC_EXPR_UDP,
+ PARSER_SC_EXPR_UDPLITE,
+ PARSER_SC_STMT_DUP,
+ PARSER_SC_STMT_FWD,
PARSER_SC_STMT_LOG,
+ PARSER_SC_STMT_NAT,
+ PARSER_SC_STMT_REJECT,
+ PARSER_SC_STMT_SYNPROXY,
+ PARSER_SC_STMT_TPROXY,
+
+ __SC_MAX
};
struct mnl_socket;
diff --git a/include/payload.h b/include/payload.h
index 8bc3fb9a..08e45f7f 100644
--- a/include/payload.h
+++ b/include/payload.h
@@ -15,6 +15,8 @@ struct eval_ctx;
struct stmt;
extern int payload_gen_dependency(struct eval_ctx *ctx, const struct expr *expr,
struct stmt **res);
+int payload_gen_inner_dependency(struct eval_ctx *ctx, const struct expr *expr,
+ struct stmt **res);
extern int payload_gen_icmp_dependency(struct eval_ctx *ctx,
const struct expr *expr,
struct stmt **res);
@@ -25,16 +27,14 @@ extern int exthdr_gen_dependency(struct eval_ctx *ctx, const struct expr *expr,
/**
* struct payload_dep_ctx - payload protocol dependency tracking
*
- * @pbase: protocol base of last dependency match
* @icmp_type: extra info for icmp(6) decoding
- * @pdep: last dependency match
* @prev: previous statement
+ * @pdeps: last dependency match per protocol layer
*/
struct payload_dep_ctx {
- enum proto_bases pbase:8;
- uint8_t icmp_type;
- struct stmt *pdep;
- struct stmt *prev;
+ uint8_t icmp_type;
+ struct stmt *prev;
+ struct stmt *pdeps[PROTO_BASE_MAX + 1];
};
extern bool payload_is_known(const struct expr *expr);
@@ -47,7 +47,10 @@ extern void payload_dependency_store(struct payload_dep_ctx *ctx,
enum proto_bases base);
extern bool payload_dependency_exists(const struct payload_dep_ctx *ctx,
enum proto_bases base);
-extern void payload_dependency_release(struct payload_dep_ctx *ctx);
+extern struct expr *payload_dependency_get(struct payload_dep_ctx *ctx,
+ enum proto_bases base);
+extern void payload_dependency_release(struct payload_dep_ctx *ctx,
+ enum proto_bases base);
extern void payload_dependency_kill(struct payload_dep_ctx *ctx,
struct expr *expr, unsigned int family);
extern void exthdr_dependency_kill(struct payload_dep_ctx *ctx,
@@ -66,4 +69,6 @@ extern void payload_expr_complete(struct expr *expr,
bool payload_expr_cmp(const struct expr *e1, const struct expr *e2);
+const struct proto_desc *find_proto_desc(const struct nftnl_udata *ud);
+
#endif /* NFTABLES_PAYLOAD_H */
diff --git a/include/proto.h b/include/proto.h
index b9217588..9c98a0b7 100644
--- a/include/proto.h
+++ b/include/proto.h
@@ -18,6 +18,7 @@ enum proto_bases {
PROTO_BASE_LL_HDR,
PROTO_BASE_NETWORK_HDR,
PROTO_BASE_TRANSPORT_HDR,
+ PROTO_BASE_INNER_HDR,
__PROTO_BASE_MAX
};
#define PROTO_BASE_MAX (__PROTO_BASE_MAX - 1)
@@ -34,6 +35,8 @@ enum icmp_hdr_field_type {
PROTO_ICMP6_PPTR,
PROTO_ICMP6_ECHO,
PROTO_ICMP6_MGMQ,
+ PROTO_ICMP6_ADDRESS, /* neighbor solicit/advert, redirect and MLD */
+ PROTO_ICMP6_REDIRECT,
};
/**
@@ -95,6 +98,10 @@ enum proto_desc_id {
PROTO_DESC_ARP,
PROTO_DESC_VLAN,
PROTO_DESC_ETHER,
+ PROTO_DESC_VXLAN,
+ PROTO_DESC_GENEVE,
+ PROTO_DESC_GRE,
+ PROTO_DESC_GRETAP,
__PROTO_DESC_MAX
};
#define PROTO_DESC_MAX (__PROTO_DESC_MAX - 1)
@@ -130,7 +137,11 @@ struct proto_desc {
uint32_t filter;
} format;
unsigned int pseudohdr[PROTO_HDRS_MAX];
-
+ struct {
+ uint32_t hdrsize;
+ uint32_t flags;
+ enum nft_inner_type type;
+ } inner;
};
#define PROTO_LINK(__num, __desc) { .num = (__num), .desc = (__desc), }
@@ -184,6 +195,7 @@ extern const struct proto_desc *proto_dev_desc(uint16_t type);
struct proto_ctx {
unsigned int debug_mask;
uint8_t family;
+ bool inner;
union {
struct {
uint8_t type;
@@ -192,17 +204,18 @@ struct proto_ctx {
struct {
struct location location;
const struct proto_desc *desc;
- unsigned int offset;
struct {
struct location location;
const struct proto_desc *desc;
} protos[PROTO_CTX_NUM_PROTOS];
unsigned int num_protos;
} protocol[PROTO_BASE_MAX + 1];
+ const struct proto_desc *stacked_ll[PROTO_CTX_NUM_PROTOS];
+ uint8_t stacked_ll_count;
};
extern void proto_ctx_init(struct proto_ctx *ctx, unsigned int family,
- unsigned int debug_mask);
+ unsigned int debug_mask, bool inner);
extern void proto_ctx_update(struct proto_ctx *ctx, enum proto_bases base,
const struct location *loc,
const struct proto_desc *desc);
@@ -214,6 +227,8 @@ extern const struct proto_desc *proto_find_upper(const struct proto_desc *base,
unsigned int num);
extern int proto_find_num(const struct proto_desc *base,
const struct proto_desc *desc);
+const struct proto_desc *proto_find_inner(uint32_t type, uint32_t hdrsize,
+ uint32_t flags);
extern const struct proto_desc *proto_find_desc(enum proto_desc_id desc_id);
@@ -227,6 +242,7 @@ enum eth_hdr_fields {
enum vlan_hdr_fields {
VLANHDR_INVALID,
VLANHDR_PCP,
+ VLANHDR_DEI,
VLANHDR_CFI,
VLANHDR_VID,
VLANHDR_TYPE,
@@ -260,6 +276,7 @@ enum ip_hdr_fields {
IPHDR_SADDR,
IPHDR_DADDR,
};
+#define IPHDR_MAX IPHDR_DADDR
enum icmp_hdr_fields {
ICMPHDR_INVALID,
@@ -290,6 +307,8 @@ enum icmp6_hdr_fields {
ICMP6HDR_ID,
ICMP6HDR_SEQ,
ICMP6HDR_MAXDELAY,
+ ICMP6HDR_TADDR,
+ ICMP6HDR_DADDR,
};
enum ip6_hdr_fields {
@@ -373,6 +392,45 @@ enum th_hdr_fields {
THDR_DPORT,
};
+struct vxlanhdr {
+ uint32_t vx_flags;
+ uint32_t vx_vni;
+};
+
+enum vxlan_hdr_fields {
+ VXLANHDR_INVALID,
+ VXLANHDR_VNI,
+ VXLANHDR_FLAGS,
+};
+
+struct gnvhdr {
+ uint16_t flags;
+ uint16_t type;
+ uint32_t vni;
+};
+enum geneve_hdr_fields {
+ GNVHDR_INVALID,
+ GNVHDR_VNI,
+ GNVHDR_TYPE,
+};
+
+struct grehdr {
+ uint16_t flags;
+ uint16_t protocol;
+};
+
+enum gre_hdr_fields {
+ GREHDR_INVALID,
+ GREHDR_VERSION,
+ GREHDR_FLAGS,
+ GREHDR_PROTOCOL,
+};
+
+extern const struct proto_desc proto_vxlan;
+extern const struct proto_desc proto_geneve;
+extern const struct proto_desc proto_gre;
+extern const struct proto_desc proto_gretap;
+
extern const struct proto_desc proto_icmp;
extern const struct proto_desc proto_igmp;
extern const struct proto_desc proto_ah;
@@ -410,4 +468,7 @@ extern const struct datatype icmp6_type_type;
extern const struct datatype dscp_type;
extern const struct datatype ecn_type;
+struct eval_ctx;
+struct proto_ctx *eval_proto_ctx(struct eval_ctx *ctx);
+
#endif /* NFTABLES_PROTO_H */
diff --git a/include/rbtree.h b/include/rbtree.h
deleted file mode 100644
index ac65283f..00000000
--- a/include/rbtree.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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 NFTABLES_RBTREE_H
-#define NFTABLES_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 /* NFTABLES_RBTREE_H */
diff --git a/include/rule.h b/include/rule.h
index fbd2c9a7..5b3e12b5 100644
--- a/include/rule.h
+++ b/include/rule.h
@@ -1,13 +1,11 @@
#ifndef NFTABLES_RULE_H
#define NFTABLES_RULE_H
-#include <stdint.h>
#include <nftables.h>
#include <list.h>
#include <netinet/in.h>
#include <libnftnl/object.h> /* For NFTNL_CTTIMEOUT_ARRAY_MAX. */
#include <linux/netfilter/nf_tables.h>
-#include <string.h>
#include <cache.h>
/**
@@ -132,10 +130,12 @@ struct symbol *symbol_get(const struct scope *scope, const char *identifier);
enum table_flags {
TABLE_F_DORMANT = (1 << 0),
TABLE_F_OWNER = (1 << 1),
+ TABLE_F_PERSIST = (1 << 2),
};
-#define TABLE_FLAGS_MAX 2
+#define TABLE_FLAGS_MAX 3
const char *table_flag_name(uint32_t flag);
+unsigned int parse_table_flag(const char *name);
/**
* struct table - nftables table
@@ -169,6 +169,7 @@ struct table {
unsigned int refcnt;
uint32_t owner;
const char *comment;
+ bool has_xt_stmts;
};
extern struct table *table_alloc(void);
@@ -213,6 +214,11 @@ struct hook_spec {
unsigned int num;
};
+struct chain_type_spec {
+ struct location loc;
+ const char *str;
+};
+
/**
* struct chain - nftables chain
*
@@ -242,7 +248,7 @@ struct chain {
struct prio_spec priority;
struct hook_spec hook;
struct expr *policy;
- const char *type;
+ struct chain_type_spec type;
const char **dev_array;
struct expr *dev_expr;
int dev_array_len;
@@ -255,7 +261,7 @@ struct chain {
extern int std_prio_lookup(const char *std_prio_name, int family, int hook);
extern const char *chain_type_name_lookup(const char *name);
extern const char *chain_hookname_lookup(const char *name);
-extern struct chain *chain_alloc(const char *name);
+extern struct chain *chain_alloc(void);
extern struct chain *chain_get(struct chain *chain);
extern void chain_free(struct chain *chain);
extern struct chain *chain_lookup_fuzzy(const struct handle *h,
@@ -265,6 +271,7 @@ extern struct chain *chain_binding_lookup(const struct table *table,
const char *chain_name);
extern const char *family2str(unsigned int family);
+#define __NF_ARP_INGRESS 255
extern const char *hooknum2str(unsigned int family, unsigned int hooknum);
extern const char *chain_policy2str(uint32_t policy);
extern void chain_print_plain(const struct chain *chain,
@@ -305,7 +312,6 @@ void rule_stmt_append(struct rule *rule, struct stmt *stmt);
void rule_stmt_insert_at(struct rule *rule, struct stmt *nstmt,
struct stmt *stmt);
-
/**
* struct set - nftables set
*
@@ -319,11 +325,13 @@ void rule_stmt_insert_at(struct rule *rule, struct stmt *nstmt,
* @key: key expression (data type, length))
* @data: mapping data expression
* @objtype: mapping object type
+ * @existing_set: reference to existing set in the kernel
* @init: initializer
* @rg_cache: cached range element (left)
* @policy: set mechanism policy
* @automerge: merge adjacents and overlapping elements, if possible
* @comment: comment
+ * @errors: expr evaluation errors seen
* @desc.size: count of set elements
* @desc.field_len: length of single concatenated fields, bytes
* @desc.field_count: count of concatenated fields
@@ -340,6 +348,7 @@ struct set {
struct expr *key;
struct expr *data;
uint32_t objtype;
+ struct set *existing_set;
struct expr *init;
struct expr *rg_cache;
uint32_t policy;
@@ -347,6 +356,7 @@ struct set {
bool root;
bool automerge;
bool key_typeof_valid;
+ bool errors;
const char *comment;
struct {
uint32_t size;
@@ -403,6 +413,11 @@ static inline bool set_is_meter(uint32_t set_flags)
return set_is_anonymous(set_flags) && (set_flags & NFT_SET_EVAL);
}
+static inline bool set_is_meter_compat(uint32_t set_flags)
+{
+ return set_flags & NFT_SET_EVAL;
+}
+
static inline bool set_is_interval(uint32_t set_flags)
{
return set_flags & NFT_SET_INTERVAL;
@@ -511,7 +526,7 @@ struct obj *obj_lookup_fuzzy(const char *obj_name,
void obj_print(const struct obj *n, struct output_ctx *octx);
void obj_print_plain(const struct obj *obj, struct output_ctx *octx);
const char *obj_type_name(uint32_t type);
-uint32_t obj_type_to_cmd(uint32_t type);
+enum cmd_obj obj_type_to_cmd(uint32_t type);
struct flowtable {
struct list_head list;
@@ -555,6 +570,7 @@ void flowtable_print(const struct flowtable *n, struct output_ctx *octx);
* @CMD_EXPORT: export the ruleset in a given format
* @CMD_MONITOR: event listener
* @CMD_DESCRIBE: describe an expression
+ * @CMD_DESTROY: destroy object
*/
enum cmd_ops {
CMD_INVALID,
@@ -572,6 +588,7 @@ enum cmd_ops {
CMD_EXPORT,
CMD_MONITOR,
CMD_DESCRIBE,
+ CMD_DESTROY,
};
/**
@@ -612,6 +629,7 @@ enum cmd_obj {
CMD_OBJ_SETELEMS,
CMD_OBJ_SETS,
CMD_OBJ_RULE,
+ CMD_OBJ_RULES,
CMD_OBJ_CHAIN,
CMD_OBJ_CHAINS,
CMD_OBJ_TABLE,
@@ -634,11 +652,14 @@ enum cmd_obj {
CMD_OBJ_FLOWTABLE,
CMD_OBJ_FLOWTABLES,
CMD_OBJ_CT_TIMEOUT,
+ CMD_OBJ_CT_TIMEOUTS,
CMD_OBJ_SECMARK,
CMD_OBJ_SECMARKS,
CMD_OBJ_CT_EXPECT,
+ CMD_OBJ_CT_EXPECTATIONS,
CMD_OBJ_SYNPROXY,
CMD_OBJ_SYNPROXYS,
+ CMD_OBJ_HOOKS,
};
struct markup {
@@ -673,6 +694,11 @@ void monitor_free(struct monitor *m);
#define NFT_NLATTR_LOC_MAX 32
+struct nlerr_loc {
+ uint16_t offset;
+ const struct location *location;
+};
+
/**
* struct cmd - command statement
*
@@ -692,6 +718,7 @@ struct cmd {
enum cmd_obj obj;
struct handle handle;
uint32_t seqnum;
+ struct list_head collapse_list;
union {
void *data;
struct expr *expr;
@@ -708,25 +735,20 @@ struct cmd {
struct markup *markup;
struct obj *object;
};
- struct {
- uint16_t offset;
- const struct location *location;
- } attr[NFT_NLATTR_LOC_MAX];
- int num_attrs;
+ struct nlerr_loc *attr;
+ uint32_t attr_array_len;
+ uint32_t num_attrs;
const void *arg;
};
extern struct cmd *cmd_alloc(enum cmd_ops op, enum cmd_obj obj,
const struct handle *h, const struct location *loc,
void *data);
-extern void nft_cmd_expand(struct cmd *cmd);
extern struct cmd *cmd_alloc_obj_ct(enum cmd_ops op, int type,
const struct handle *h,
const struct location *loc, struct obj *obj);
extern void cmd_free(struct cmd *cmd);
-void cmd_add_loc(struct cmd *cmd, uint16_t offset, const struct location *loc);
-
#include <payload.h>
#include <expression.h>
@@ -740,10 +762,13 @@ void cmd_add_loc(struct cmd *cmd, uint16_t offset, const struct location *loc);
* @rule: current rule
* @set: current set
* @stmt: current statement
+ * @stmt_len: current statement template length
+ * @recursion: expr evaluation recursion counter
* @cache: cache context
* @debug_mask: debugging bitmask
* @ectx: expression context
- * @pctx: payload context
+ * @_pctx: payload contexts
+ * @inner_desc: inner header description
*/
struct eval_ctx {
struct nft_ctx *nft;
@@ -753,8 +778,11 @@ struct eval_ctx {
struct rule *rule;
struct set *set;
struct stmt *stmt;
+ uint32_t stmt_len;
+ uint32_t recursion;
struct expr_ctx ectx;
- struct proto_ctx pctx;
+ struct proto_ctx _pctx[2];
+ const struct proto_desc *inner_desc;
};
extern int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd);
@@ -770,7 +798,7 @@ struct timeout_protocol {
uint32_t *dflt_timeout;
};
-extern struct timeout_protocol timeout_protocol[IPPROTO_MAX];
+extern struct timeout_protocol timeout_protocol[UINT8_MAX + 1];
extern int timeout_str2num(uint16_t l4proto, struct timeout_state *ts);
#endif /* NFTABLES_RULE_H */
diff --git a/include/sctp_chunk.h b/include/sctp_chunk.h
new file mode 100644
index 00000000..3819200f
--- /dev/null
+++ b/include/sctp_chunk.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright Red Hat
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 (or any
+ * later) as published by the Free Software Foundation.
+ */
+
+#ifndef NFTABLES_SCTP_CHUNK_H
+#define NFTABLES_SCTP_CHUNK_H
+
+/* SCTP chunk types used on wire */
+enum sctp_hdr_chunk_types {
+ SCTP_CHUNK_TYPE_DATA = 0,
+ SCTP_CHUNK_TYPE_INIT = 1,
+ SCTP_CHUNK_TYPE_INIT_ACK = 2,
+ SCTP_CHUNK_TYPE_SACK = 3,
+ SCTP_CHUNK_TYPE_HEARTBEAT = 4,
+ SCTP_CHUNK_TYPE_HEARTBEAT_ACK = 5,
+ SCTP_CHUNK_TYPE_ABORT = 6,
+ SCTP_CHUNK_TYPE_SHUTDOWN = 7,
+ SCTP_CHUNK_TYPE_SHUTDOWN_ACK = 8,
+ SCTP_CHUNK_TYPE_ERROR = 9,
+ SCTP_CHUNK_TYPE_COOKIE_ECHO = 10,
+ SCTP_CHUNK_TYPE_COOKIE_ACK = 11,
+ SCTP_CHUNK_TYPE_ECNE = 12,
+ SCTP_CHUNK_TYPE_CWR = 13,
+ SCTP_CHUNK_TYPE_SHUTDOWN_COMPLETE = 14,
+ SCTP_CHUNK_TYPE_ASCONF_ACK = 128,
+ SCTP_CHUNK_TYPE_FORWARD_TSN = 192,
+ SCTP_CHUNK_TYPE_ASCONF = 193,
+};
+
+enum sctp_hdr_chunk_common_fields {
+ SCTP_CHUNK_COMMON_TYPE,
+ SCTP_CHUNK_COMMON_FLAGS,
+ SCTP_CHUNK_COMMON_LENGTH,
+ __SCTP_CHUNK_COMMON_MAX,
+};
+
+#define SCTP_CHUNK_START_INDEX __SCTP_CHUNK_COMMON_MAX
+
+enum sctp_hdr_chunk_data_fields {
+ SCTP_CHUNK_DATA_TSN = SCTP_CHUNK_START_INDEX,
+ SCTP_CHUNK_DATA_STREAM,
+ SCTP_CHUNK_DATA_SSN,
+ SCTP_CHUNK_DATA_PPID,
+};
+
+enum sctp_hdr_chunk_init_fields {
+ SCTP_CHUNK_INIT_TAG = SCTP_CHUNK_START_INDEX,
+ SCTP_CHUNK_INIT_RWND,
+ SCTP_CHUNK_INIT_OSTREAMS,
+ SCTP_CHUNK_INIT_ISTREAMS,
+ SCTP_CHUNK_INIT_TSN,
+};
+
+enum sctp_hdr_chunk_sack_fields {
+ SCTP_CHUNK_SACK_CTSN_ACK = SCTP_CHUNK_START_INDEX,
+ SCTP_CHUNK_SACK_RWND,
+ SCTP_CHUNK_SACK_GACK_BLOCKS,
+ SCTP_CHUNK_SACK_DUP_TSNS,
+};
+
+enum sctp_hdr_chunk_shutdown_fields {
+ SCTP_CHUNK_SHUTDOWN_CTSN_ACK = SCTP_CHUNK_START_INDEX,
+};
+
+enum sctp_hdr_chunk_ecne_cwr_fields {
+ SCTP_CHUNK_ECNE_CWR_MIN_TSN = SCTP_CHUNK_START_INDEX,
+};
+
+enum sctp_hdr_chunk_asconf_fields {
+ SCTP_CHUNK_ASCONF_SEQNO = SCTP_CHUNK_START_INDEX,
+};
+
+enum sctp_hdr_chunk_fwd_tsn_fields {
+ SCTP_CHUNK_FORWARD_TSN_NCTSN = SCTP_CHUNK_START_INDEX,
+};
+
+struct expr *sctp_chunk_expr_alloc(const struct location *loc,
+ unsigned int type, unsigned int field);
+void sctp_chunk_init_raw(struct expr *expr, uint8_t type, unsigned int off,
+ unsigned int len, uint32_t flags);
+const struct exthdr_desc *sctp_chunk_protocol_find(const char *name);
+
+#endif /* NFTABLES_SCTP_CHUNK_H */
diff --git a/include/statement.h b/include/statement.h
index 7637a82e..662f99dd 100644
--- a/include/statement.h
+++ b/include/statement.h
@@ -47,6 +47,13 @@ struct counter_stmt {
extern struct stmt *counter_stmt_alloc(const struct location *loc);
+struct last_stmt {
+ uint64_t used;
+ uint32_t set;
+};
+
+extern struct stmt *last_stmt_alloc(const struct location *loc);
+
struct exthdr_stmt {
struct expr *expr;
struct expr *val;
@@ -145,6 +152,12 @@ struct nat_stmt {
extern struct stmt *nat_stmt_alloc(const struct location *loc,
enum nft_nat_etypes type);
+struct optstrip_stmt {
+ struct expr *expr;
+};
+
+extern struct stmt *optstrip_stmt_alloc(const struct location *loc, struct expr *e);
+
struct tproxy_stmt {
struct expr *addr;
struct expr *port;
@@ -159,7 +172,8 @@ struct queue_stmt {
uint16_t flags;
};
-extern struct stmt *queue_stmt_alloc(const struct location *loc);
+extern struct stmt *queue_stmt_alloc(const struct location *loc,
+ struct expr *e, uint16_t flags);
struct quota_stmt {
uint64_t bytes;
@@ -248,8 +262,8 @@ enum nft_xt_type {
NFT_XT_MATCH = 0,
NFT_XT_TARGET,
NFT_XT_WATCHER,
- NFT_XT_MAX
};
+#define NFT_XT_MAX (NFT_XT_WATCHER + 1)
struct xtables_match;
struct xtables_target;
@@ -257,12 +271,11 @@ struct xtables_target;
struct xt_stmt {
const char *name;
enum nft_xt_type type;
+ uint32_t rev;
+ uint32_t family;
+ size_t infolen;
+ void *info;
uint32_t proto;
- union {
- struct xtables_match *match;
- struct xtables_target *target;
- };
- void *entry;
};
extern struct stmt *xt_stmt_alloc(const struct location *loc);
@@ -296,6 +309,8 @@ extern struct stmt *xt_stmt_alloc(const struct location *loc);
* @STMT_MAP: map statement
* @STMT_SYNPROXY: synproxy statement
* @STMT_CHAIN: chain statement
+ * @STMT_OPTSTRIP: optstrip statement
+ * @STMT_LAST: last statement
*/
enum stmt_types {
STMT_INVALID,
@@ -325,6 +340,8 @@ enum stmt_types {
STMT_MAP,
STMT_SYNPROXY,
STMT_CHAIN,
+ STMT_OPTSTRIP,
+ STMT_LAST,
};
/**
@@ -374,11 +391,13 @@ struct stmt {
struct counter_stmt counter;
struct payload_stmt payload;
struct meta_stmt meta;
+ struct last_stmt last;
struct log_stmt log;
struct limit_stmt limit;
struct reject_stmt reject;
struct nat_stmt nat;
struct tproxy_stmt tproxy;
+ struct optstrip_stmt optstrip;
struct queue_stmt queue;
struct quota_stmt quota;
struct ct_stmt ct;
@@ -397,6 +416,7 @@ struct stmt {
extern struct stmt *stmt_alloc(const struct location *loc,
const struct stmt_ops *ops);
int stmt_evaluate(struct eval_ctx *ctx, struct stmt *stmt);
+int stmt_dependency_evaluate(struct eval_ctx *ctx, struct stmt *stmt);
extern void stmt_free(struct stmt *stmt);
extern void stmt_list_free(struct list_head *list);
extern void stmt_print(const struct stmt *stmt, struct output_ctx *octx);
diff --git a/include/tcpopt.h b/include/tcpopt.h
index 667c8a77..3a0b8424 100644
--- a/include/tcpopt.h
+++ b/include/tcpopt.h
@@ -12,8 +12,8 @@ extern void tcpopt_init_raw(struct expr *expr, uint8_t type,
unsigned int offset, unsigned int len,
uint32_t flags);
-extern bool tcpopt_find_template(struct expr *expr, const struct expr *mask,
- unsigned int *shift);
+extern bool tcpopt_find_template(struct expr *expr, unsigned int offset,
+ unsigned int len);
/* TCP option numbers used on wire */
enum tcpopt_kind {
@@ -25,6 +25,9 @@ enum tcpopt_kind {
TCPOPT_KIND_SACK = 5,
TCPOPT_KIND_TIMESTAMP = 8,
TCPOPT_KIND_ECHO = 8,
+ TCPOPT_KIND_MD5SIG = 19,
+ TCPOPT_KIND_MPTCP = 30,
+ TCPOPT_KIND_FASTOPEN = 34,
__TCPOPT_KIND_MAX,
/* extra oob info, internal to nft */
@@ -71,6 +74,12 @@ enum tcpopt_hdr_field_sack {
TCPOPT_SACK_RIGHT3,
};
+enum tcpopt_hdr_mptcp_common {
+ TCPOPT_MPTCP_KIND,
+ TCPOPT_MPTCP_LENGTH,
+ TCPOPT_MPTCP_SUBTYPE,
+};
+
extern const struct exthdr_desc *tcpopt_protocols[__TCPOPT_KIND_MAX];
#endif /* NFTABLES_TCPOPT_H */
diff --git a/include/utils.h b/include/utils.h
index f45f2513..e18fabec 100644
--- a/include/utils.h
+++ b/include/utils.h
@@ -2,8 +2,6 @@
#define NFTABLES_UTILS_H
#include <asm/byteorder.h>
-#include <stdint.h>
-#include <stdbool.h>
#include <stdarg.h>
#include <stdio.h>
#include <unistd.h>
@@ -11,7 +9,6 @@
#include <list.h>
#include <gmputil.h>
-#include "config.h"
#ifdef HAVE_VISIBILITY_HIDDEN
# define __visible __attribute__((visibility("default")))
# define EXPORT_SYMBOL(x) typeof(x) (x) __visible;
@@ -39,7 +36,7 @@
#define __must_check __attribute__((warn_unused_result))
#define __noreturn __attribute__((__noreturn__))
-#define BUG(fmt, arg...) ({ fprintf(stderr, "BUG: " fmt, ##arg); assert(0); })
+#define BUG(fmt, arg...) ({ fprintf(stderr, "BUG: " fmt, ##arg); assert(0); abort(); })
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)]))
#define BUILD_BUG_ON_ZERO(e) (sizeof(char[1 - 2 * !!(e)]) - 1)
@@ -75,15 +72,32 @@
#define max(_x, _y) ({ \
_x > _y ? _x : _y; })
-#define SNPRINTF_BUFFER_SIZE(ret, size, len, offset) \
- if (ret < 0) \
- abort(); \
- offset += ret; \
- assert(ret < len); \
- if (ret > len) \
- ret = len; \
- size += ret; \
- len -= ret;
+#define SNPRINTF_BUFFER_SIZE(ret, len, offset) \
+ ({ \
+ const int _ret = (ret); \
+ size_t *const _len = (len); \
+ size_t *const _offset = (offset); \
+ bool _not_truncated = true; \
+ size_t _ret2; \
+ \
+ assert(_ret >= 0); \
+ \
+ if ((size_t) _ret >= *_len) { \
+ /* Truncated.
+ *
+ * We will leave "len" at zero and increment
+ * "offset" to point one byte after the buffer
+ * (after the terminating NUL byte). */ \
+ _ret2 = *_len; \
+ _not_truncated = false; \
+ } else \
+ _ret2 = (size_t) _ret; \
+ \
+ *_offset += _ret2; \
+ *_len -= _ret2; \
+ \
+ _not_truncated; \
+ })
#define MSEC_PER_SEC 1000L
@@ -128,12 +142,13 @@ extern void __memory_allocation_error(const char *filename, uint32_t line) __nor
#define memory_allocation_error() \
__memory_allocation_error(__FILE__, __LINE__);
-extern void xfree(const void *ptr);
extern void *xmalloc(size_t size);
extern void *xmalloc_array(size_t nmemb, size_t size);
extern void *xrealloc(void *ptr, size_t size);
extern void *xzalloc(size_t size);
+extern void *xzalloc_array(size_t nmemb, size_t size);
extern char *xstrdup(const char *s);
extern void xstrunescape(const char *in, char *out);
+extern int round_pow_2(unsigned int value);
#endif /* NFTABLES_UTILS_H */