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