#ifndef NFTABLES_RULE_H #define NFTABLES_RULE_H #include #include #include #include #include /* For NFTNL_CTTIMEOUT_ARRAY_MAX. */ #include #include #include /** * struct handle_spec - handle ID * * @location: location this handle was defined at * @id: handle ID value */ struct handle_spec { struct location location; uint64_t id; }; /** * struct position_spec - position ID * * @location: location this position was defined at * @id: position ID value */ struct position_spec { struct location location; uint64_t id; }; struct table_spec { struct location location; const char *name; }; struct chain_spec { struct location location; const char *name; }; struct set_spec { struct location location; const char *name; }; struct flowtable_spec { struct location location; const char *name; }; struct obj_spec { struct location location; const char *name; }; /** * struct handle - handle for tables, chains, rules and sets * * @family: protocol family * @table: table name * @chain: chain name (chains and rules only) * @set: set name (sets only) * @obj: stateful object name (stateful object only) * @flowtable: flow table name (flow table only) * @handle: rule handle (rules only) * @position: rule position (rules only) * @set_id: set ID (sets only) */ struct handle { uint32_t family; struct table_spec table; struct chain_spec chain; struct set_spec set; struct obj_spec obj; struct flowtable_spec flowtable; struct handle_spec 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; }; extern void handle_merge(struct handle *dst, const struct handle *src); extern void handle_free(struct handle *h); /** * struct scope * * @parent: pointer to parent scope * @symbols: symbols bound in the scope */ struct scope { const struct scope *parent; struct list_head symbols; }; extern struct scope *scope_alloc(void); extern struct scope *scope_init(struct scope *scope, const struct scope *parent); extern void scope_release(const struct scope *scope); extern void scope_free(struct scope *scope); /** * struct symbol * * @list: scope symbol list node * @identifier: identifier * @expr: initializer * @refcnt: reference counter */ struct symbol { struct list_head list; const char *identifier; struct expr *expr; int refcnt; }; extern void symbol_bind(struct scope *scope, const char *identifier, struct expr *expr); extern int symbol_unbind(const struct scope *scope, const char *identifier); extern struct symbol *symbol_lookup(const struct scope *scope, const char *identifier); struct symbol *symbol_lookup_fuzzy(const struct scope *scope, const char *identifier); struct symbol *symbol_get(const struct scope *scope, const char *identifier); enum table_flags { TABLE_F_DORMANT = (1 << 0), TABLE_F_OWNER = (1 << 1), }; #define TABLE_FLAGS_MAX 2 const char *table_flag_name(uint32_t flag); /** * struct table - nftables table * * @list: list node * @handle: table handle * @location: location the table was defined at * @chains: chains contained in the table * @sets: sets contained in the table * @objs: stateful objects contained in the table * @flowtables: flow tables contained in the table * @flags: table flags * @refcnt: table reference counter */ 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; }; extern struct table *table_alloc(void); extern struct table *table_get(struct table *table); extern void table_free(struct table *table); extern struct table *table_lookup_fuzzy(const struct handle *h, const struct nft_cache *cache); /** * enum chain_flags - chain flags * * @CHAIN_F_BASECHAIN: chain is a base chain */ 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 */ }; /** * struct prio_spec - extendend priority specification for mixed * textual/numerical parsing. * * @expr: expr of the standard priority value */ struct prio_spec { struct location loc; struct expr *expr; }; struct hook_spec { struct location loc; const char *name; unsigned int num; }; struct chain_type_spec { struct location loc; const char *str; }; /** * struct chain - nftables chain * * @list: list node in table list * @handle: chain handle * @location: location the chain was defined at * @refcnt: reference counter * @flags: chain flags * @hookstr: unified and human readable hook name (base chains) * @hooknum: hook number (base chains) * @priority: hook priority (base chains) * @policy: default chain policy (base chains) * @type: chain type * @dev: device (if any) * @rules: rules contained in the chain */ 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; struct chain_type_spec type; const char **dev_array; struct expr *dev_expr; int dev_array_len; }; struct scope scope; struct list_head rules; }; #define STD_PRIO_BUFSIZE 100 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_get(struct chain *chain); extern void chain_free(struct chain *chain); 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); 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 * * @list: list node in chain list * @handle: rule handle * @location: location the rule was defined at * @stmt: list of statements * @num_stmts: number of statements in stmts list * @comment: comment * @refcnt: rule reference counter */ struct rule { struct list_head list; struct handle handle; struct location location; struct list_head stmts; unsigned int num_stmts; const char *comment; unsigned int refcnt; }; extern struct rule *rule_alloc(const struct location *loc, const struct handle *h); extern struct rule *rule_get(struct rule *rule); extern void rule_free(struct rule *rule); extern void rule_print(const struct rule *rule, struct output_ctx *octx); extern struct rule *rule_lookup(const struct chain *chain, uint64_t handle); extern struct rule *rule_lookup_by_index(const struct chain *chain, uint64_t index); 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 * * @list: table set list node * @handle: set handle * @location: location the set was defined/declared at * @refcnt: reference count * @flags: bitmask of set flags * @gc_int: garbage collection interval * @timeout: default timeout value * @key: key expression (data type, length)) * @data: mapping data expression * @objtype: mapping object type * @init: initializer * @rg_cache: cached range element (left) * @policy: set mechanism policy * @automerge: merge adjacents and overlapping elements, if possible * @comment: comment * @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; uint32_t flags; uint32_t gc_int; uint64_t timeout; struct expr *key; struct expr *data; uint32_t objtype; struct expr *init; struct expr *rg_cache; uint32_t policy; struct list_head stmt_list; bool root; bool automerge; bool key_typeof_valid; const char *comment; struct { uint32_t size; uint8_t field_len[NFT_REG32_COUNT]; uint8_t field_count; } desc; }; 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 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, const struct nft_cache *cache, const struct table **table); extern const char *set_policy2str(uint32_t policy); extern void set_print(const struct set *set, struct output_ctx *octx); extern void set_print_plain(const struct set *s, struct output_ctx *octx); static inline bool set_is_datamap(uint32_t set_flags) { return set_flags & NFT_SET_MAP; } static inline bool set_is_objmap(uint32_t set_flags) { return set_flags & NFT_SET_OBJECT; } static inline bool set_is_map(uint32_t set_flags) { return set_is_datamap(set_flags) || set_is_objmap(set_flags); } static inline bool set_is_anonymous(uint32_t set_flags) { return set_flags & NFT_SET_ANONYMOUS; } static inline bool set_is_literal(uint32_t set_flags) { return !(set_is_anonymous(set_flags) || set_is_map(set_flags)); } static inline bool map_is_literal(uint32_t set_flags) { return !(set_is_anonymous(set_flags) || !set_is_map(set_flags)); } 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_interval(uint32_t set_flags) { return set_flags & NFT_SET_INTERVAL; } static inline bool set_is_non_concat_range(struct set *s) { return (s->flags & NFT_SET_INTERVAL) && s->desc.field_count <= 1; } #include struct counter { uint64_t packets; uint64_t bytes; }; struct quota { uint64_t bytes; uint64_t used; uint32_t flags; }; struct ct_helper { char name[16]; uint16_t l3proto; uint8_t l4proto; }; struct timeout_state { struct list_head head; struct location location; uint8_t timeout_index; const char *timeout_str; unsigned int timeout_value; }; struct ct_timeout { uint16_t l3proto; uint8_t l4proto; uint32_t timeout[NFTNL_CTTIMEOUT_ARRAY_MAX]; struct list_head timeout_list; }; struct ct_expect { uint16_t l3proto; uint8_t l4proto; uint16_t dport; uint32_t timeout; uint8_t size; }; struct limit { uint64_t rate; uint64_t unit; uint32_t burst; uint32_t type; uint32_t flags; }; struct synproxy { uint16_t mss; uint8_t wscale; uint32_t flags; }; struct secmark { char ctx[NFT_SECMARK_CTX_MAXLEN]; }; /** * struct obj - nftables stateful object statement * * @list: table set list node * @location: location the stateful object was defined/declared at * @handle: counter handle * @type: type of stateful object * @refcnt: object reference counter */ 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; struct ct_helper ct_helper; struct limit limit; struct ct_timeout ct_timeout; struct secmark secmark; struct ct_expect ct_expect; struct synproxy synproxy; }; }; struct obj *obj_alloc(const struct location *loc); extern struct obj *obj_get(struct obj *obj); void obj_free(struct obj *obj); 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); struct flowtable { struct list_head list; struct cache_item cache; struct handle handle; struct scope scope; struct location location; struct hook_spec hook; struct prio_spec priority; const char **dev_array; struct expr *dev_expr; int dev_array_len; uint32_t flags; unsigned int refcnt; }; 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 struct flowtable *flowtable_lookup_fuzzy(const char *ft_name, const struct nft_cache *cache, const struct table **table); void flowtable_print(const struct flowtable *n, struct output_ctx *octx); /** * enum cmd_ops - command operations * * @CMD_INVALID: invalid * @CMD_ADD: add object (non-exclusive) * @CMD_REPLACE, replace object * @CMD_CREATE: create object (exclusive) * @CMD_INSERT: insert object * @CMD_DELETE: delete object * @CMD_GET: get object * @CMD_LIST: list container * @CMD_RESET: reset container * @CMD_FLUSH: flush container * @CMD_RENAME: rename object * @CMD_IMPORT: import a ruleset in a given format * @CMD_EXPORT: export the ruleset in a given format * @CMD_MONITOR: event listener * @CMD_DESCRIBE: describe an expression */ enum cmd_ops { CMD_INVALID, CMD_ADD, CMD_REPLACE, CMD_CREATE, CMD_INSERT, CMD_DELETE, CMD_GET, CMD_LIST, CMD_RESET, CMD_FLUSH, CMD_RENAME, CMD_IMPORT, CMD_EXPORT, CMD_MONITOR, CMD_DESCRIBE, }; /** * enum cmd_obj - command objects * * @CMD_OBJ_INVALID: invalid * @CMD_OBJ_ELEMENTS: set element(s) * @CMD_OBJ_SET: set * @CMD_OBJ_SETS: multiple sets * @CMD_OBJ_SETELEMS: set elements * @CMD_OBJ_RULE: rule * @CMD_OBJ_CHAIN: chain * @CMD_OBJ_CHAINS: multiple chains * @CMD_OBJ_TABLE: table * @CMD_OBJ_FLOWTABLE: flowtable * @CMD_OBJ_FLOWTABLES: flowtables * @CMD_OBJ_RULESET: ruleset * @CMD_OBJ_EXPR: expression * @CMD_OBJ_MONITOR: monitor * @CMD_OBJ_MARKUP: import/export * @CMD_OBJ_METER: meter * @CMD_OBJ_METERS: meters * @CMD_OBJ_COUNTER: counter * @CMD_OBJ_COUNTERS: multiple counters * @CMD_OBJ_QUOTA: quota * @CMD_OBJ_QUOTAS: multiple quotas * @CMD_OBJ_LIMIT: limit * @CMD_OBJ_LIMITS: multiple limits * @CMD_OBJ_SECMARK: secmark * @CMD_OBJ_SECMARKS: multiple secmarks * @CMD_OBJ_SYNPROXY: synproxy * @CMD_OBJ_SYNPROXYS: multiple synproxys */ enum cmd_obj { CMD_OBJ_INVALID, CMD_OBJ_ELEMENTS, CMD_OBJ_SET, CMD_OBJ_SETELEMS, CMD_OBJ_SETS, CMD_OBJ_RULE, CMD_OBJ_CHAIN, CMD_OBJ_CHAINS, CMD_OBJ_TABLE, CMD_OBJ_RULESET, CMD_OBJ_EXPR, CMD_OBJ_MONITOR, CMD_OBJ_MARKUP, CMD_OBJ_METER, CMD_OBJ_METERS, CMD_OBJ_MAP, CMD_OBJ_MAPS, CMD_OBJ_COUNTER, CMD_OBJ_COUNTERS, CMD_OBJ_QUOTA, CMD_OBJ_QUOTAS, CMD_OBJ_CT_HELPER, CMD_OBJ_CT_HELPERS, CMD_OBJ_LIMIT, CMD_OBJ_LIMITS, CMD_OBJ_FLOWTABLE, CMD_OBJ_FLOWTABLES, CMD_OBJ_CT_TIMEOUT, CMD_OBJ_SECMARK, CMD_OBJ_SECMARKS, CMD_OBJ_CT_EXPECT, CMD_OBJ_SYNPROXY, CMD_OBJ_SYNPROXYS, }; struct markup { uint32_t format; }; struct markup *markup_alloc(uint32_t format); void markup_free(struct markup *m); enum { CMD_MONITOR_OBJ_ANY, CMD_MONITOR_OBJ_TABLES, CMD_MONITOR_OBJ_CHAINS, CMD_MONITOR_OBJ_RULES, CMD_MONITOR_OBJ_SETS, CMD_MONITOR_OBJ_ELEMS, CMD_MONITOR_OBJ_RULESET, CMD_MONITOR_OBJ_TRACE, CMD_MONITOR_OBJ_MAX }; struct monitor { struct location location; uint32_t format; uint32_t flags; uint32_t type; const char *event; }; struct monitor *monitor_alloc(uint32_t format, uint32_t type, const char *event); void monitor_free(struct monitor *m); #define NFT_NLATTR_LOC_MAX 32 /** * struct cmd - command statement * * @list: list node * @location: location of the statement * @op: operation * @obj: object type to perform operation on * @handle: handle for operations working without full objects * @seqnum: sequence number to match netlink errors * @union: object * @arg: argument data */ struct cmd { struct list_head list; struct location location; enum cmd_ops op; enum cmd_obj obj; struct handle handle; uint32_t seqnum; 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; struct flowtable *flowtable; struct monitor *monitor; struct markup *markup; struct obj *object; }; struct { uint16_t offset; const struct location *location; } attr[NFT_NLATTR_LOC_MAX]; int 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 #include /** * struct eval_ctx - evaluation context * * @nft: nftables context * @msgs: message queue * @cmd: current command * @table: current table * @rule: current rule * @set: current set * @stmt: current statement * @cache: cache context * @debug_mask: debugging bitmask * @ectx: expression context * @pctx: payload context */ struct eval_ctx { struct nft_ctx *nft; struct list_head *msgs; struct cmd *cmd; struct table *table; struct rule *rule; struct set *set; struct stmt *stmt; struct expr_ctx ectx; struct proto_ctx pctx; }; extern int cmd_evaluate(struct eval_ctx *ctx, struct cmd *cmd); extern struct error_record *rule_postprocess(struct rule *rule); struct netlink_ctx; extern int do_command(struct netlink_ctx *ctx, struct cmd *cmd); 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 int timeout_str2num(uint16_t l4proto, struct timeout_state *ts); #endif /* NFTABLES_RULE_H */