diff options
Diffstat (limited to 'include')
45 files changed, 1158 insertions, 335 deletions
diff --git a/include/Makefile.am b/include/Makefile.am deleted file mode 100644 index 42f24f35..00000000 --- a/include/Makefile.am +++ /dev/null @@ -1,39 +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 \ - 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 86a7eff7..8ca4a9a7 100644 --- a/include/cache.h +++ b/include/cache.h @@ -1,6 +1,10 @@ #ifndef _NFT_CACHE_H_ #define _NFT_CACHE_H_ +#include <list.h> + +struct handle; + enum cache_level_bits { NFT_CACHE_TABLE_BIT = (1 << 0), NFT_CACHE_CHAIN_BIT = (1 << 1), @@ -30,8 +34,122 @@ 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; + +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); + +static inline uint32_t djb_hash(const char *key) +{ + uint32_t i, hash = 5381; + + for (i = 0; i < strlen(key); i++) + hash = ((hash << 5) + hash) + key[i]; + + return hash; +} + +struct nft_cache_filter *nft_cache_filter_init(void); +void nft_cache_filter_fini(struct nft_cache_filter *filter); + +struct table; +struct chain; + +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); + +struct cache { + struct list_head *ht; + struct list_head list; +}; + +struct cache_item { + struct list_head hlist; + struct list_head list; +}; + +void cache_init(struct cache *cache); +void cache_free(struct cache *cache); +void cache_add(struct cache_item *item, struct cache *cache, uint32_t hash); +void cache_del(struct cache_item *item); + +void table_cache_add(struct table *table, struct nft_cache *cache); +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, + uint32_t obj_type); + +struct flowtable; +void ft_cache_add(struct flowtable *ft, struct table *table); +void ft_cache_del(struct flowtable *ft); +struct flowtable *ft_cache_find(const struct table *table, const char *name); + +struct nft_cache { + uint32_t genid; + struct cache table_cache; + uint32_t seqnum; + 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 d8251775..f0a0d47a 100644 --- a/include/cli.h +++ b/include/cli.h @@ -2,9 +2,8 @@ #define _NFT_CLI_H_ #include <nftables/libnftables.h> -#include <config.h> -#if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBLINENOISE) +#if defined(HAVE_LIBREADLINE) || defined(HAVE_LIBEDIT) || defined(HAVE_LIBLINENOISE) extern int cli_init(struct nft_ctx *nft); #else static inline 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 04b4892b..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) @@ -48,6 +48,7 @@ * @TYPE_TIME_DATA Date type (integer subtype) * @TYPE_TIME_HOUR Hour type (integer subtype) * @TYPE_TIME_DAY Day type (integer subtype) + * @TYPE_CGROUPV2 cgroups v2 (integer subtype) */ enum datatypes { TYPE_INVALID, @@ -96,6 +97,7 @@ enum datatypes { TYPE_TIME_DATE, TYPE_TIME_HOUR, TYPE_TIME_DAY, + TYPE_CGROUPV2, __TYPE_MAX }; #define TYPE_MAX (__TYPE_MAX - 1) @@ -164,18 +166,23 @@ 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; }; 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, @@ -245,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; @@ -270,6 +281,12 @@ extern const struct datatype time_type; extern const struct datatype boolean_type; 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); @@ -292,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, @@ -305,4 +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 8135a516..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, @@ -71,8 +78,11 @@ enum expr_types { EXPR_RT, EXPR_FIB, EXPR_XFRM, + EXPR_SET_ELEM_CATCHALL, + EXPR_FLAGCMP, + + EXPR_MAX = EXPR_FLAGCMP }; -#define EXPR_MAX EXPR_XFRM enum ops { OP_INVALID, @@ -93,6 +103,7 @@ enum ops { OP_GT, OP_LTE, OP_GTE, + OP_NEG, __OP_MAX }; #define OP_MAX (__OP_MAX - 1) @@ -113,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, @@ -128,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, @@ -167,14 +184,16 @@ struct expr_ops { bool (*cmp)(const struct expr *e1, const struct expr *e2); void (*pctx_update)(struct proto_ctx *ctx, - const struct expr *expr); + const struct location *loc, + const struct expr *left, + const struct expr *right); int (*build_udata)(struct nftnl_udata_buf *udbuf, const struct expr *expr); struct expr * (*parse_udata)(const struct nftnl_udata *ud); }; 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 @@ -185,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, @@ -193,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> @@ -233,6 +255,7 @@ struct expr { enum expr_types etype:8; enum ops op:8; unsigned int len; + struct cmd *cmd; union { struct { @@ -249,6 +272,7 @@ struct expr { /* EXPR_VERDICT */ int verdict; struct expr *chain; + uint32_t chain_id; }; struct { /* EXPR_VALUE */ @@ -277,7 +301,7 @@ struct expr { uint64_t timeout; uint64_t expiration; const char *comment; - struct stmt *stmt; + struct list_head stmt_list; uint32_t elem_flags; }; struct { @@ -299,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; @@ -308,7 +333,8 @@ struct expr { /* EXPR_EXTHDR */ const struct exthdr_desc *desc; const struct proto_hdr_template *tmpl; - unsigned int offset; + uint16_t offset; + uint8_t raw_type; enum nft_exthdr_op op; unsigned int flags; } exthdr; @@ -316,10 +342,12 @@ struct expr { /* EXPR_META */ enum nft_meta_keys key; enum proto_bases base; + const struct proto_desc *inner_desc; } meta; struct { /* SOCKET */ enum nft_socket_keys key; + uint32_t level; } socket; struct { /* EXPR_RT */ @@ -363,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; }; }; @@ -381,6 +415,8 @@ 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); +void expr_to_string(const struct expr *expr, char *string); + struct eval_ctx; extern int expr_binary_error(struct list_head *msgs, const struct expr *e1, const struct expr *e2, @@ -459,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); @@ -466,17 +503,13 @@ 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); extern struct expr *get_set_intervals(const struct set *set, const struct expr *init); struct table; -extern int get_set_decompose(struct table *table, struct set *set); +extern int get_set_decompose(struct set *cache_set, struct set *set); extern struct expr *mapping_expr_alloc(const struct location *loc, struct expr *from, struct expr *to); @@ -489,7 +522,14 @@ extern struct expr *set_ref_expr_alloc(const struct location *loc, extern struct expr *set_elem_expr_alloc(const struct location *loc, struct expr *key); +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 c9a3c211..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, @@ -30,7 +31,6 @@ struct exthdr_desc { const char *name; enum exthdr_desc_id id; uint8_t type; - int proto_key; struct proto_hdr_template templates[10]; }; 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 20d6c2a4..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); @@ -111,6 +118,7 @@ void monitor_print_rule_json(struct netlink_mon_handler *monh, int json_events_cb(const struct nlmsghdr *nlh, struct netlink_mon_handler *monh); +void json_alloc_echo(struct nft_ctx *ctx); void json_print_echo(struct nft_ctx *ctx); #else /* ! HAVE_LIBJANSSON */ @@ -126,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) @@ -143,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) @@ -164,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) @@ -177,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) @@ -185,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 @@ -251,6 +266,11 @@ static inline int json_events_cb(const struct nlmsghdr *nlh, return -1; } +static inline void json_alloc_echo(struct nft_ctx *ctx) +{ + /* empty */ +} + static inline void json_print_echo(struct nft_ctx *ctx) { /* empty */ 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 18075f95..9e078880 100644 --- a/include/linux/netfilter.h +++ b/include/linux/netfilter.h @@ -48,11 +48,13 @@ enum nf_inet_hooks { NF_INET_FORWARD, NF_INET_LOCAL_OUT, NF_INET_POST_ROUTING, + NF_INET_INGRESS, NF_INET_NUMHOOKS }; 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_log.h b/include/linux/netfilter/nf_log.h index 8be21e02..2ae00932 100644 --- a/include/linux/netfilter/nf_log.h +++ b/include/linux/netfilter/nf_log.h @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ #ifndef _NETFILTER_NF_LOG_H #define _NETFILTER_NF_LOG_H @@ -9,4 +10,6 @@ #define NF_LOG_MACDECODE 0x20 /* Decode MAC header */ #define NF_LOG_MASK 0x2f +#define NF_LOG_PREFIXLEN 128 + #endif /* _NETFILTER_NF_LOG_H */ diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h index 4565456c..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, }; @@ -133,7 +151,7 @@ enum nf_tables_msg_types { * @NFTA_LIST_ELEM: list element (NLA_NESTED) */ enum nft_list_attributes { - NFTA_LIST_UNPEC, + NFTA_LIST_UNSPEC, NFTA_LIST_ELEM, __NFTA_LIST_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 @@ -172,6 +193,8 @@ enum nft_table_flags { * @NFTA_TABLE_NAME: name of the table (NLA_STRING) * @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, @@ -180,10 +203,21 @@ enum nft_table_attributes { NFTA_TABLE_USE, NFTA_TABLE_HANDLE, NFTA_TABLE_PAD, + NFTA_TABLE_USERDATA, + NFTA_TABLE_OWNER, __NFTA_TABLE_MAX }; #define NFTA_TABLE_MAX (__NFTA_TABLE_MAX - 1) +enum nft_chain_flags { + NFT_CHAIN_BASE = (1 << 0), + NFT_CHAIN_HW_OFFLOAD = (1 << 1), + NFT_CHAIN_BINDING = (1 << 2), +}; +#define NFT_CHAIN_FLAGS (NFT_CHAIN_BASE | \ + NFT_CHAIN_HW_OFFLOAD | \ + NFT_CHAIN_BINDING) + /** * enum nft_chain_attributes - nf_tables chain netlink attributes * @@ -196,6 +230,8 @@ enum nft_table_attributes { * @NFTA_CHAIN_TYPE: type name of the string (NLA_NUL_STRING) * @NFTA_CHAIN_COUNTERS: counter specification of the chain (NLA_NESTED: nft_counter_attributes) * @NFTA_CHAIN_FLAGS: chain flags + * @NFTA_CHAIN_ID: uniquely identifies a chain in a transaction (NLA_U32) + * @NFTA_CHAIN_USERDATA: user data (NLA_BINARY) */ enum nft_chain_attributes { NFTA_CHAIN_UNSPEC, @@ -209,6 +245,8 @@ enum nft_chain_attributes { NFTA_CHAIN_COUNTERS, NFTA_CHAIN_PAD, NFTA_CHAIN_FLAGS, + NFTA_CHAIN_ID, + NFTA_CHAIN_USERDATA, __NFTA_CHAIN_MAX }; #define NFTA_CHAIN_MAX (__NFTA_CHAIN_MAX - 1) @@ -238,6 +276,7 @@ enum nft_rule_attributes { NFTA_RULE_PAD, NFTA_RULE_ID, NFTA_RULE_POSITION_ID, + NFTA_RULE_CHAIN_ID, __NFTA_RULE_MAX }; #define NFTA_RULE_MAX (__NFTA_RULE_MAX - 1) @@ -277,6 +316,7 @@ enum nft_rule_compat_attributes { * @NFT_SET_EVAL: set can be updated from the evaluation path * @NFT_SET_OBJECT: set contains stateful objects * @NFT_SET_CONCAT: set contains a concatenation + * @NFT_SET_EXPR: set contains expressions */ enum nft_set_flags { NFT_SET_ANONYMOUS = 0x1, @@ -287,6 +327,7 @@ enum nft_set_flags { NFT_SET_EVAL = 0x20, NFT_SET_OBJECT = 0x40, NFT_SET_CONCAT = 0x80, + NFT_SET_EXPR = 0x100, }; /** @@ -345,6 +386,7 @@ enum nft_set_field_attributes { * @NFTA_SET_OBJ_TYPE: stateful object type (NLA_U32: NFT_OBJECT_*) * @NFTA_SET_HANDLE: set handle (NLA_U64) * @NFTA_SET_EXPR: set expression (NLA_NESTED: nft_expr_attributes) + * @NFTA_SET_EXPRESSIONS: list of expressions (NLA_NESTED: nft_list_attributes) */ enum nft_set_attributes { NFTA_SET_UNSPEC, @@ -365,6 +407,7 @@ enum nft_set_attributes { NFTA_SET_OBJ_TYPE, NFTA_SET_HANDLE, NFTA_SET_EXPR, + NFTA_SET_EXPRESSIONS, __NFTA_SET_MAX }; #define NFTA_SET_MAX (__NFTA_SET_MAX - 1) @@ -373,9 +416,11 @@ enum nft_set_attributes { * enum nft_set_elem_flags - nf_tables set element flags * * @NFT_SET_ELEM_INTERVAL_END: element ends the previous interval + * @NFT_SET_ELEM_CATCHALL: special catch-all element */ enum nft_set_elem_flags { NFT_SET_ELEM_INTERVAL_END = 0x1, + NFT_SET_ELEM_CATCHALL = 0x2, }; /** @@ -390,6 +435,7 @@ enum nft_set_elem_flags { * @NFTA_SET_ELEM_EXPR: expression (NLA_NESTED: nft_expr_attributes) * @NFTA_SET_ELEM_OBJREF: stateful object reference (NLA_STRING) * @NFTA_SET_ELEM_KEY_END: closing key value (NLA_NESTED: nft_data) + * @NFTA_SET_ELEM_EXPRESSIONS: list of expressions (NLA_NESTED: nft_list_attributes) */ enum nft_set_elem_attributes { NFTA_SET_ELEM_UNSPEC, @@ -403,6 +449,7 @@ enum nft_set_elem_attributes { NFTA_SET_ELEM_PAD, NFTA_SET_ELEM_OBJREF, NFTA_SET_ELEM_KEY_END, + NFTA_SET_ELEM_EXPRESSIONS, __NFTA_SET_ELEM_MAX }; #define NFTA_SET_ELEM_MAX (__NFTA_SET_ELEM_MAX - 1) @@ -468,11 +515,13 @@ enum nft_data_attributes { * * @NFTA_VERDICT_CODE: nf_tables verdict (NLA_U32: enum nft_verdicts) * @NFTA_VERDICT_CHAIN: jump target chain name (NLA_STRING) + * @NFTA_VERDICT_CHAIN_ID: jump target chain ID (NLA_U32) */ enum nft_verdict_attributes { NFTA_VERDICT_UNSPEC, NFTA_VERDICT_CODE, NFTA_VERDICT_CHAIN, + NFTA_VERDICT_CHAIN_ID, __NFTA_VERDICT_MAX }; #define NFTA_VERDICT_MAX (__NFTA_VERDICT_MAX - 1) @@ -684,6 +733,7 @@ enum nft_dynset_ops { enum nft_dynset_flags { NFT_DYNSET_F_INV = (1 << 0), + NFT_DYNSET_F_EXPR = (1 << 1), }; /** @@ -697,6 +747,7 @@ enum nft_dynset_flags { * @NFTA_DYNSET_TIMEOUT: timeout value for the new element (NLA_U64) * @NFTA_DYNSET_EXPR: expression (NLA_NESTED: nft_expr_attributes) * @NFTA_DYNSET_FLAGS: flags (NLA_U32) + * @NFTA_DYNSET_EXPRESSIONS: list of expressions (NLA_NESTED: nft_list_attributes) */ enum nft_dynset_attributes { NFTA_DYNSET_UNSPEC, @@ -709,6 +760,7 @@ enum nft_dynset_attributes { NFTA_DYNSET_EXPR, NFTA_DYNSET_PAD, NFTA_DYNSET_FLAGS, + NFTA_DYNSET_EXPRESSIONS, __NFTA_DYNSET_MAX, }; #define NFTA_DYNSET_MAX (__NFTA_DYNSET_MAX - 1) @@ -719,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, }; /** @@ -731,16 +786,44 @@ enum nft_payload_bases { * * @NFT_PAYLOAD_CSUM_NONE: no checksumming * @NFT_PAYLOAD_CSUM_INET: internet checksum (RFC 791) + * @NFT_PAYLOAD_CSUM_SCTP: CRC-32c, for use in SCTP header (RFC 3309) */ enum nft_payload_csum_types { NFT_PAYLOAD_CSUM_NONE, NFT_PAYLOAD_CSUM_INET, + NFT_PAYLOAD_CSUM_SCTP, }; 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 * @@ -777,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) @@ -848,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, @@ -858,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, @@ -885,6 +974,8 @@ enum nft_meta_keys { NFT_META_TIME_HOUR, NFT_META_SDIF, NFT_META_SDIFNAME, + NFT_META_BRI_BROUTE, + __NFT_META_IIFTYPE, }; /** @@ -980,11 +1071,13 @@ 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, NFTA_SOCKET_KEY, NFTA_SOCKET_DREG, + NFTA_SOCKET_LEVEL, __NFTA_SOCKET_MAX }; #define NFTA_SOCKET_MAX (__NFTA_SOCKET_MAX - 1) @@ -994,10 +1087,14 @@ 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, NFT_SOCKET_MARK, + NFT_SOCKET_WILDCARD, + NFT_SOCKET_CGROUPV2, __NFT_SOCKET_MAX }; #define NFT_SOCKET_MAX (__NFT_SOCKET_MAX - 1) @@ -1152,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) @@ -1541,6 +1653,7 @@ enum nft_ct_expectation_attributes { * @NFTA_OBJ_DATA: stateful object data (NLA_NESTED) * @NFTA_OBJ_USE: number of references to this expression (NLA_U32) * @NFTA_OBJ_HANDLE: object handle (NLA_U64) + * @NFTA_OBJ_USERDATA: user data (NLA_BINARY) */ enum nft_object_attributes { NFTA_OBJ_UNSPEC, @@ -1551,6 +1664,7 @@ enum nft_object_attributes { NFTA_OBJ_USE, NFTA_OBJ_HANDLE, NFTA_OBJ_PAD, + NFTA_OBJ_USERDATA, __NFTA_OBJ_MAX }; #define NFTA_OBJ_MAX (__NFTA_OBJ_MAX - 1) 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/list.h b/include/list.h index 9c4da817..857921e3 100644 --- a/include/list.h +++ b/include/list.h @@ -348,6 +348,13 @@ static inline void list_splice_tail_init(struct list_head *list, #define list_first_entry(ptr, type, member) \ list_entry((ptr)->next, type, member) +/** + * list_next_entry - get the next element in list + * @pos: the type * to cursor + * @member: the name of the list_head within the struct. + */ +#define list_next_entry(pos, member) \ + list_entry((pos)->member.next, typeof(*(pos)), member) /** * list_for_each_entry - iterate over list of given type 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 74b1b56f..cd5a2053 100644 --- a/include/mnl.h +++ b/include/mnl.h @@ -7,7 +7,6 @@ #include <libmnl/libmnl.h> struct mnl_socket *nft_mnl_socket_open(void); -struct mnl_socket *nft_mnl_socket_reopen(struct mnl_socket *nf_sock); uint32_t mnl_seqnum_alloc(uint32_t *seqnum); uint32_t mnl_genid_get(struct netlink_ctx *ctx); @@ -34,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); @@ -44,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, @@ -77,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 0a5fde3c..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,8 +101,9 @@ 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; }; @@ -121,10 +142,10 @@ 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, - struct nftnl_rule *nlr, - const struct rule *rule); + const struct rule *rule, + struct netlink_linearize_ctx *lctx); extern struct rule *netlink_delinearize_rule(struct netlink_ctx *ctx, struct nftnl_rule *r); @@ -132,11 +153,11 @@ 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); -extern int netlink_list_sets(struct netlink_ctx *ctx, const struct handle *h); extern struct set *netlink_delinearize_set(struct netlink_ctx *ctx, const struct nftnl_set *nls); @@ -145,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 table *table, - struct set *set, struct expr *init); + const struct location *loc, struct set *cache_set, + 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); @@ -161,6 +183,11 @@ extern struct obj *netlink_delinearize_obj(struct netlink_ctx *ctx, extern int netlink_list_flowtables(struct netlink_ctx *ctx, const struct handle *h); +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); @@ -177,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); @@ -211,4 +238,27 @@ int netlink_events_trace_cb(const struct nlmsghdr *nlh, int type, enum nft_data_types dtype_map_to_kernel(const struct datatype *dtype); +void netlink_linearize_init(struct netlink_linearize_ctx *lctx, + struct nftnl_rule *nlr); +void netlink_linearize_fini(struct netlink_linearize_ctx *lctx); + +struct netlink_linearize_ctx { + struct nftnl_rule *nlr; + unsigned int reg_low; + struct list_head *expr_loc_htable; +}; + +#define NFT_EXPR_LOC_HSIZE 128 + +struct nft_expr_loc { + struct list_head hlist; + const struct nftnl_expr *nle; + const struct location *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 3556728d..4b7c3359 100644 --- a/include/nftables.h +++ b/include/nftables.h @@ -1,10 +1,10 @@ #ifndef NFTABLES_NFTABLES_H #define NFTABLES_NFTABLES_H -#include <stdbool.h> #include <stdarg.h> #include <limits.h> #include <utils.h> +#include <cache.h> #include <nftables/libnftables.h> struct cookie { @@ -22,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 { @@ -95,33 +109,41 @@ static inline bool nft_output_terse(const struct output_ctx *octx) return octx->flags & NFT_CTX_OUTPUT_TERSE; } -struct nft_cache { - uint32_t genid; - struct list_head list; - uint32_t seqnum; - uint32_t flags; -}; - 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 { @@ -169,6 +191,7 @@ enum input_descriptor_types { INDESC_FILE, INDESC_CLI, INDESC_NETLINK, + INDESC_STDIN, }; /** @@ -201,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); @@ -213,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/owner.h b/include/owner.h new file mode 100644 index 00000000..85d821cc --- /dev/null +++ b/include/owner.h @@ -0,0 +1,6 @@ +#ifndef _NFT_OWNER_H_ +#define _NFT_OWNER_H_ + +char *get_progname(uint32_t portid); + +#endif diff --git a/include/parser.h b/include/parser.h index 636d1c88..f79a22f3 100644 --- a/include/parser.h +++ b/include/parser.h @@ -11,7 +11,7 @@ #define YYLTYPE_IS_TRIVIAL 0 #define YYENABLE_NLS 0 -#define SCOPE_NEST_MAX 3 +#define SCOPE_NEST_MAX 4 struct parser_state { struct input_descriptor *indesc; @@ -22,8 +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; @@ -45,4 +110,6 @@ extern void scanner_push_buffer(void *scanner, const struct input_descriptor *indesc, const char *buffer); +extern void scanner_pop_start_cond(void *scanner, enum startcond_type sc); + #endif /* NFTABLES_PARSER_H */ diff --git a/include/payload.h b/include/payload.h index a914d239..08e45f7f 100644 --- a/include/payload.h +++ b/include/payload.h @@ -15,6 +15,11 @@ 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); extern int exthdr_gen_dependency(struct eval_ctx *ctx, const struct expr *expr, const struct proto_desc *dependency, enum proto_bases pb, struct stmt **res); @@ -22,14 +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 - * @pdep: last dependency match + * @icmp_type: extra info for icmp(6) decoding * @prev: previous statement + * @pdeps: last dependency match per protocol layer */ struct payload_dep_ctx { - enum proto_bases pbase; - 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); @@ -42,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, @@ -61,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 1771ba8e..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) @@ -25,6 +26,19 @@ enum proto_bases { extern const char *proto_base_names[]; extern const char *proto_base_tokens[]; +enum icmp_hdr_field_type { + PROTO_ICMP_ANY = 0, + PROTO_ICMP_ECHO, /* echo and reply */ + PROTO_ICMP_MTU, /* destination unreachable */ + PROTO_ICMP_ADDRESS, /* redirect */ + PROTO_ICMP6_MTU, + PROTO_ICMP6_PPTR, + PROTO_ICMP6_ECHO, + PROTO_ICMP6_MGMQ, + PROTO_ICMP6_ADDRESS, /* neighbor solicit/advert, redirect and MLD */ + PROTO_ICMP6_REDIRECT, +}; + /** * struct proto_hdr_template - protocol header field description * @@ -33,14 +47,16 @@ extern const char *proto_base_tokens[]; * @offset: offset of the header field from base * @len: length of header field * @meta_key: special case: meta expression key + * @icmp_dep: special case: icmp header dependency */ struct proto_hdr_template { const char *token; const struct datatype *dtype; uint16_t offset; uint16_t len; - enum byteorder byteorder; - enum nft_meta_keys meta_key; + enum byteorder byteorder:8; + enum nft_meta_keys meta_key:8; + enum icmp_hdr_field_type icmp_dep:8; }; #define PROTO_HDR_TEMPLATE(__token, __dtype, __byteorder, __offset, __len)\ @@ -82,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) @@ -101,10 +121,11 @@ enum proto_desc_id { */ struct proto_desc { const char *name; - enum proto_desc_id id; - enum proto_bases base; - unsigned int checksum_key; - unsigned int protocol_key; + enum proto_desc_id id:8; + enum proto_bases base:8; + enum nft_payload_csum_types checksum_type:8; + uint16_t checksum_key; + uint16_t protocol_key; unsigned int length; struct { unsigned int num; @@ -116,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), } @@ -152,6 +177,8 @@ struct dev_proto_desc { extern int proto_dev_type(const struct proto_desc *desc, uint16_t *res); extern const struct proto_desc *proto_dev_desc(uint16_t type); +#define PROTO_CTX_NUM_PROTOS 16 + /** * struct proto_ctx - protocol context * @@ -167,23 +194,41 @@ extern const struct proto_desc *proto_dev_desc(uint16_t type); */ struct proto_ctx { unsigned int debug_mask; - unsigned int family; + uint8_t family; + bool inner; + union { + struct { + uint8_t type; + } icmp; + } th_dep; 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); +bool proto_ctx_is_ambiguous(struct proto_ctx *ctx, enum proto_bases bases); +const struct proto_desc *proto_ctx_find_conflict(struct proto_ctx *ctx, + enum proto_bases base, + const struct proto_desc *desc); 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); @@ -197,6 +242,7 @@ enum eth_hdr_fields { enum vlan_hdr_fields { VLANHDR_INVALID, VLANHDR_PCP, + VLANHDR_DEI, VLANHDR_CFI, VLANHDR_VID, VLANHDR_TYPE, @@ -210,8 +256,8 @@ enum arp_hdr_fields { ARPHDR_PLN, ARPHDR_OP, ARPHDR_SADDR_ETHER, - ARPHDR_DADDR_ETHER, ARPHDR_SADDR_IP, + ARPHDR_DADDR_ETHER, ARPHDR_DADDR_IP, }; @@ -230,6 +276,7 @@ enum ip_hdr_fields { IPHDR_SADDR, IPHDR_DADDR, }; +#define IPHDR_MAX IPHDR_DADDR enum icmp_hdr_fields { ICMPHDR_INVALID, @@ -260,6 +307,8 @@ enum icmp6_hdr_fields { ICMP6HDR_ID, ICMP6HDR_SEQ, ICMP6HDR_MAXDELAY, + ICMP6HDR_TADDR, + ICMP6HDR_DADDR, }; enum ip6_hdr_fields { @@ -343,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; @@ -380,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 cfb76b8a..5b3e12b5 100644 --- a/include/rule.h +++ b/include/rule.h @@ -1,12 +1,12 @@ #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 <cache.h> /** * struct handle_spec - handle ID @@ -79,6 +79,7 @@ struct handle { struct position_spec position; struct position_spec index; uint32_t set_id; + uint32_t chain_id; uint32_t rule_id; uint32_t position_id; }; @@ -128,10 +129,13 @@ 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 1 +#define TABLE_FLAGS_MAX 3 -extern const char *table_flags_name[TABLE_FLAGS_MAX]; +const char *table_flag_name(uint32_t flag); +unsigned int parse_table_flag(const char *name); /** * struct table - nftables table @@ -148,23 +152,29 @@ extern const char *table_flags_name[TABLE_FLAGS_MAX]; */ struct table { struct list_head list; + struct cache_item cache; struct handle handle; struct location location; struct scope scope; + struct cache chain_cache; + struct cache set_cache; + struct cache obj_cache; + struct cache ft_cache; struct list_head chains; struct list_head sets; struct list_head objs; struct list_head flowtables; + struct list_head chain_bindings; enum table_flags flags; unsigned int refcnt; + uint32_t owner; + const char *comment; + bool has_xt_stmts; }; extern struct table *table_alloc(void); extern struct table *table_get(struct table *table); extern void table_free(struct table *table); -extern void table_add_hash(struct table *table, struct nft_cache *cache); -extern struct table *table_lookup(const struct handle *h, - const struct nft_cache *cache); extern struct table *table_lookup_fuzzy(const struct handle *h, const struct nft_cache *cache); @@ -176,6 +186,15 @@ extern struct table *table_lookup_fuzzy(const struct handle *h, enum chain_flags { CHAIN_F_BASECHAIN = 0x1, CHAIN_F_HW_OFFLOAD = 0x2, + CHAIN_F_BINDING = 0x4, +}; + +/** + * enum flowtable_flags - flowtable flags + * + */ +enum flowtable_flags { + FLOWTABLE_F_HW_OFFLOAD = 0x1, /* NF_FLOWTABLE_HW_OFFLOAD in linux nf_flow_table.h */ }; /** @@ -195,6 +214,11 @@ struct hook_spec { unsigned int num; }; +struct chain_type_spec { + struct location loc; + const char *str; +}; + /** * struct chain - nftables chain * @@ -213,16 +237,18 @@ struct hook_spec { */ struct chain { struct list_head list; + struct cache_item cache; struct handle handle; struct location location; unsigned int refcnt; uint32_t flags; + const char *comment; struct { struct location loc; 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; @@ -235,21 +261,23 @@ 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 void chain_add_hash(struct chain *chain, struct table *table); -extern struct chain *chain_lookup(const struct table *table, - const struct handle *h); extern struct chain *chain_lookup_fuzzy(const struct handle *h, const struct nft_cache *cache, const struct table **table); +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, struct output_ctx *octx); +extern void chain_rules_print(const struct chain *chain, + struct output_ctx *octx, const char *indent); /** * struct rule - nftables rule @@ -284,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 * @@ -298,16 +325,20 @@ 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 */ struct set { struct list_head list; + struct cache_item cache; struct handle handle; struct location location; unsigned int refcnt; @@ -317,13 +348,16 @@ 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; - struct stmt *stmt; + struct list_head stmt_list; bool root; bool automerge; bool key_typeof_valid; + bool errors; + const char *comment; struct { uint32_t size; uint8_t field_len[NFT_REG32_COUNT]; @@ -335,8 +369,6 @@ extern struct set *set_alloc(const struct location *loc); extern struct set *set_get(struct set *set); extern void set_free(struct set *set); extern struct set *set_clone(const struct set *set); -extern void set_add_hash(struct set *set, struct table *table); -extern struct set *set_lookup(const struct table *table, const char *name); extern struct set *set_lookup_global(uint32_t family, const char *table, const char *name, struct nft_cache *cache); extern struct set *set_lookup_fuzzy(const char *set_name, @@ -381,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; @@ -462,10 +499,12 @@ struct secmark { */ struct obj { struct list_head list; + struct cache_item cache; struct location location; struct handle handle; uint32_t type; unsigned int refcnt; + const char *comment; union { struct counter counter; struct quota quota; @@ -481,19 +520,17 @@ struct obj { struct obj *obj_alloc(const struct location *loc); extern struct obj *obj_get(struct obj *obj); void obj_free(struct obj *obj); -void obj_add_hash(struct obj *obj, struct table *table); -struct obj *obj_lookup(const struct table *table, const char *name, - uint32_t type); struct obj *obj_lookup_fuzzy(const char *obj_name, const struct nft_cache *cache, const struct table **t); 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; + struct cache_item cache; struct handle handle; struct scope scope; struct location location; @@ -509,8 +546,6 @@ struct flowtable { extern struct flowtable *flowtable_alloc(const struct location *loc); extern struct flowtable *flowtable_get(struct flowtable *flowtable); extern void flowtable_free(struct flowtable *flowtable); -extern void flowtable_add_hash(struct flowtable *flowtable, struct table *table); -extern struct flowtable *flowtable_lookup(const struct table *table, const char *name); extern struct flowtable *flowtable_lookup_fuzzy(const char *ft_name, const struct nft_cache *cache, const struct table **table); @@ -535,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, @@ -552,6 +588,7 @@ enum cmd_ops { CMD_EXPORT, CMD_MONITOR, CMD_DESCRIBE, + CMD_DESTROY, }; /** @@ -592,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, @@ -614,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 { @@ -651,7 +692,12 @@ struct monitor { struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event); void monitor_free(struct monitor *m); -#define NFT_NLATTR_LOC_MAX 8 +#define NFT_NLATTR_LOC_MAX 32 + +struct nlerr_loc { + uint16_t offset; + const struct location *location; +}; /** * struct cmd - command statement @@ -672,10 +718,15 @@ struct cmd { enum cmd_obj obj; struct handle handle; uint32_t seqnum; + struct list_head collapse_list; union { void *data; struct expr *expr; struct set *set; + struct { + struct expr *expr; /* same offset as cmd->expr */ + struct set *set; + } elem; struct rule *rule; struct chain *chain; struct table *table; @@ -684,25 +735,20 @@ struct cmd { struct markup *markup; struct obj *object; }; - struct { - uint16_t offset; - 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, struct location *loc); - #include <payload.h> #include <expression.h> @@ -716,10 +762,13 @@ void cmd_add_loc(struct cmd *cmd, uint16_t offset, 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; @@ -729,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); @@ -740,19 +792,13 @@ extern struct error_record *rule_postprocess(struct rule *rule); struct netlink_ctx; extern int do_command(struct netlink_ctx *ctx, struct cmd *cmd); -extern unsigned int cache_evaluate(struct nft_ctx *nft, struct list_head *cmds); -extern int cache_update(struct nft_ctx *ctx, enum cmd_ops cmd, - struct list_head *msgs); -extern bool cache_needs_update(struct nft_cache *cache); -extern void cache_release(struct nft_cache *cache); - struct timeout_protocol { uint32_t array_size; const char *const *state_to_name; 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/socket.h b/include/socket.h index fbfddd11..79938ccf 100644 --- a/include/socket.h +++ b/include/socket.h @@ -19,6 +19,6 @@ struct socket_template { extern const struct socket_template socket_templates[]; extern struct expr *socket_expr_alloc(const struct location *loc, - enum nft_socket_keys key); + enum nft_socket_keys key, uint32_t level); #endif /* NFTABLES_SOCKET_H */ diff --git a/include/statement.h b/include/statement.h index 7d96b394..662f99dd 100644 --- a/include/statement.h +++ b/include/statement.h @@ -11,6 +11,14 @@ extern struct stmt *expr_stmt_alloc(const struct location *loc, extern struct stmt *verdict_stmt_alloc(const struct location *loc, struct expr *expr); +struct chain_stmt { + struct chain *chain; + struct expr *expr; +}; + +struct stmt *chain_stmt_alloc(const struct location *loc, struct chain *chain, + enum nft_verdicts verdict); + struct flow_stmt { const char *table_name; }; @@ -39,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; @@ -75,7 +90,7 @@ enum { }; struct log_stmt { - const char *prefix; + struct expr *prefix; unsigned int snaplen; uint16_t group; uint16_t qthreshold; @@ -137,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; @@ -151,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; @@ -193,7 +215,7 @@ uint32_t fwd_stmt_type(const char *type); struct set_stmt { struct expr *set; struct expr *key; - struct stmt *stmt; + struct list_head stmt_list; enum nft_dynset_ops op; }; @@ -205,7 +227,7 @@ struct map_stmt { struct expr *set; struct expr *key; struct expr *data; - struct stmt *stmt; + struct list_head stmt_list; enum nft_dynset_ops op; }; @@ -240,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; @@ -249,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); @@ -287,6 +308,9 @@ extern struct stmt *xt_stmt_alloc(const struct location *loc); * @STMT_CONNLIMIT: connection limit statement * @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, @@ -315,6 +339,9 @@ enum stmt_types { STMT_CONNLIMIT, STMT_MAP, STMT_SYNPROXY, + STMT_CHAIN, + STMT_OPTSTRIP, + STMT_LAST, }; /** @@ -364,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; @@ -380,12 +409,14 @@ struct stmt { struct flow_stmt flow; struct map_stmt map; struct synproxy_stmt synproxy; + struct chain_stmt chain; }; }; 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 ffdbcb02..3a0b8424 100644 --- a/include/tcpopt.h +++ b/include/tcpopt.h @@ -6,44 +6,80 @@ #include <statement.h> extern struct expr *tcpopt_expr_alloc(const struct location *loc, - uint8_t type, uint8_t field); + unsigned int kind, unsigned int field); 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); - -enum tcpopt_hdr_types { - TCPOPTHDR_INVALID, - TCPOPTHDR_EOL, - TCPOPTHDR_NOOP, - TCPOPTHDR_MAXSEG, - TCPOPTHDR_WINDOW, - TCPOPTHDR_SACK_PERMITTED, - TCPOPTHDR_SACK0, - TCPOPTHDR_SACK1, - TCPOPTHDR_SACK2, - TCPOPTHDR_SACK3, - TCPOPTHDR_TIMESTAMP, - TCPOPTHDR_ECHO, - TCPOPTHDR_ECHO_REPLY, - __TCPOPTHDR_MAX +extern bool tcpopt_find_template(struct expr *expr, unsigned int offset, + unsigned int len); + +/* TCP option numbers used on wire */ +enum tcpopt_kind { + TCPOPT_KIND_EOL = 0, + TCPOPT_KIND_NOP = 1, + TCPOPT_KIND_MAXSEG = 2, + TCPOPT_KIND_WINDOW = 3, + TCPOPT_KIND_SACK_PERMITTED = 4, + 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 */ + TCPOPT_KIND_SACK1 = 256, + TCPOPT_KIND_SACK2 = 257, + TCPOPT_KIND_SACK3 = 258, +}; + +/* Internal identifiers */ +enum tcpopt_common { + TCPOPT_COMMON_KIND, + TCPOPT_COMMON_LENGTH, +}; + +enum tcpopt_maxseg { + TCPOPT_MAXSEG_KIND, + TCPOPT_MAXSEG_LENGTH, + TCPOPT_MAXSEG_SIZE, +}; + +enum tcpopt_timestamp { + TCPOPT_TS_KIND, + TCPOPT_TS_LENGTH, + TCPOPT_TS_TSVAL, + TCPOPT_TS_TSECR, +}; + +enum tcpopt_windowscale { + TCPOPT_WINDOW_KIND, + TCPOPT_WINDOW_LENGTH, + TCPOPT_WINDOW_COUNT, +}; + +enum tcpopt_hdr_field_sack { + TCPOPT_SACK_KIND, + TCPOPT_SACK_LENGTH, + TCPOPT_SACK_LEFT, + TCPOPT_SACK_RIGHT, + TCPOPT_SACK_LEFT1, + TCPOPT_SACK_RIGHT1, + TCPOPT_SACK_LEFT2, + TCPOPT_SACK_RIGHT2, + TCPOPT_SACK_LEFT3, + TCPOPT_SACK_RIGHT3, }; -enum tcpopt_hdr_fields { - TCPOPTHDR_FIELD_INVALID, - TCPOPTHDR_FIELD_KIND, - TCPOPTHDR_FIELD_LENGTH, - TCPOPTHDR_FIELD_SIZE, - TCPOPTHDR_FIELD_COUNT, - TCPOPTHDR_FIELD_LEFT, - TCPOPTHDR_FIELD_RIGHT, - TCPOPTHDR_FIELD_TSVAL, - TCPOPTHDR_FIELD_TSECR, +enum tcpopt_hdr_mptcp_common { + TCPOPT_MPTCP_KIND, + TCPOPT_MPTCP_LENGTH, + TCPOPT_MPTCP_SUBTYPE, }; -extern const struct exthdr_desc *tcpopthdr_protocols[__TCPOPTHDR_MAX]; +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 */ |