#ifndef NFTABLES_EXPRESSION_H
#define NFTABLES_EXPRESSION_H
#include <stdbool.h>
#include <gmputil.h>
#include <linux/netfilter/nf_tables.h>
#include <nftables.h>
#include <datatype.h>
#include <utils.h>
#include <list.h>
#include <json.h>
/**
* enum expr_types
*
* @EXPR_INVALID: uninitialized type, should not happen
* @EXPR_VERDICT: nftables verdict expression
* @EXPR_SYMBOL: unparsed symbol
* @EXPR_VARIABLE: variable
* @EXPR_VALUE: literal numeric or string expression
* @EXPR_PREFIX: prefixed expression
* @EXPR_RANGE: literal range
* @EXPR_PAYLOAD: payload expression
* @EXPR_EXTHDR: exthdr expression
* @EXPR_META: meta expression
* @EXPR_SOCKET: socket expression
* @EXPR_OSF: osf expression
* @EXPR_CT: conntrack expression
* @EXPR_CONCAT: concatenation
* @EXPR_LIST: list of expressions
* @EXPR_SET: literal set
* @EXPR_SET_REF: set reference
* @EXPR_SET_ELEM: set element
* @EXPR_MAPPING: a single mapping (key : value)
* @EXPR_MAP: map operation (expr map { EXPR_MAPPING, ... })
* @EXPR_UNARY: byteorder conversion, generated during evaluation
* @EXPR_BINOP: binary operations (bitwise, shifts)
* @EXPR_RELATIONAL: equality and relational expressions
* @EXPR_NUMGEN: number generation expression
* @EXPR_HASH: hash expression
* @EXPR_RT: routing expression
*/
enum expr_types {
EXPR_INVALID,
EXPR_VERDICT,
EXPR_SYMBOL,
EXPR_VARIABLE,
EXPR_VALUE,
EXPR_PREFIX,
EXPR_RANGE,
EXPR_PAYLOAD,
EXPR_EXTHDR,
EXPR_META,
EXPR_SOCKET,
EXPR_OSF,
EXPR_CT,
EXPR_CONCAT,
EXPR_LIST,
EXPR_SET,
EXPR_SET_REF,
EXPR_SET_ELEM,
EXPR_MAPPING,
EXPR_MAP,
EXPR_UNARY,
EXPR_BINOP,
EXPR_RELATIONAL,
EXPR_NUMGEN,
EXPR_HASH,
EXPR_RT,
EXPR_FIB,
EXPR_XFRM,
};
enum ops {
OP_INVALID,
OP_IMPLICIT,
/* Unary operations */
OP_HTON,
OP_NTOH,
/* Binary operations */
OP_LSHIFT,
OP_RSHIFT,
OP_AND,
OP_XOR,
OP_OR,
/* Relational operations */
OP_EQ,
OP_NEQ,
OP_LT,
OP_GT,
OP_LTE,
OP_GTE,
__OP_MAX
};
#define OP_MAX (__OP_MAX - 1)
extern const char *expr_op_symbols[];
enum symbol_types {
SYMBOL_VALUE,
SYMBOL_SET,
};
/**
* struct expr_ctx - type context for symbol parsing during evaluation
*
* @dtype: expected datatype
* @byteorder: expected byteorder
* @len: expected len
* @maxval: expected maximum value
*/
struct expr_ctx {
const struct datatype *dtype;
enum byteorder byteorder;
unsigned int len;
unsigned int maxval;
};
static inline void __expr_set_context(struct expr_ctx *ctx,
const struct datatype *dtype,
enum byteorder byteorder,
unsigned int len, unsigned int maxval)
{
ctx->dtype = dtype;
ctx->byteorder = byteorder;
ctx->len = len;
ctx->maxval = maxval;
}
static inline void expr_set_context(struct expr_ctx *ctx,
const struct datatype *dtype,
unsigned int len)
{
__expr_set_context(ctx, dtype,
dtype ? dtype->byteorder : BYTEORDER_INVALID,
len, 0);
}
/**
* struct expr_ops
*
* @type: expression type
* @name: expression name for diagnostics
* @clone: function to clone type specific data
* @destroy: destructor, must release inner expressions
* @set_type: function to promote type and byteorder of inner types
* @print: function to print the expression
* @cmp: function to compare two expressions of the same types
* @pctx_update:update protocol context
*/
struct proto_ctx;
struct expr_ops {
enum expr_types type;
const char *name;
void (*clone)(struct expr *new, const struct expr *expr);
void (*destroy)(struct expr *expr);
void (*set_type)(const struct expr *expr,
const struct datatype *dtype,
enum byteorder byteorder);
void (*print)(const struct expr *expr,
struct output_ctx *octx);
json_t *(*json)(const struct expr *expr,
struct output_ctx *octx);
bool (*cmp)(const struct expr *e1,
const struct expr *e2);
void (*pctx_update)(struct proto_ctx *ctx,
const struct expr *expr);
};
const struct expr_ops *expr_ops(const struct expr *e);
/**
* enum expr_flags
*
* @EXPR_F_CONSTANT: constant expression
* @EXPR_F_SINGLETON: singleton (implies primary and constant)
* @EXPR_F_PROTOCOL: expressions describes upper layer protocol
* @EXPR_F_INTERVAL_END: set member ends an open interval
* @EXPR_F_BOOLEAN: expression is boolean (set by relational expr on LHS)
*/
enum expr_flags {
EXPR_F_CONSTANT = 0x1,
EXPR_F_SINGLETON = 0x2,
EXPR_F_PROTOCOL = 0x4,
EXPR_F_INTERVAL_END = 0x8,
EXPR_F_BOOLEAN = 0x10,
};
#include <payload.h>
#include <exthdr.h>
#include <fib.h>
#include <numgen.h>
#include <meta.h>
#include <rt.h>
#include <hash.h>
#include <ct.h>
#include <socket.h>
#include <osf.h>
#include <xfrm.h>
/**
* struct expr
*
* @list: list node
* @location: location from parser
* @refcnt: reference count
* @flags: mask of enum expr_flags
* @dtype: data type of expression
* @byteorder: byteorder of expression
* @etype: expression type
* @op: operation for unary, binary and relational expressions
* @len: length of expression
* @union: type specific data
*/
struct expr {
struct list_head list;
struct location location;
unsigned int refcnt;
unsigned int flags;
const struct datatype *dtype;
enum byteorder byteorder:8;
enum expr_types etype:8;
enum ops op:8;
unsigned int len;
union {
struct {
/* EXPR_SYMBOL */
const struct scope *scope;
const char *identifier;
enum symbol_types symtype;
};
struct {
/* EXPR_VARIABLE */
struct symbol *sym;
};
struct {
/* EXPR_VERDICT */
int verdict;
struct expr *chain;
};
struct {
/* EXPR_VALUE */
mpz_t value;
};
struct {
/* EXPR_PREFIX */
struct expr *prefix;
unsigned int prefix_len;
};
struct {
/* EXPR_CONCAT, EXPR_LIST, EXPR_SET */
struct list_head expressions;
unsigned int size;
uint32_t set_flags;
};
struct {
/* EXPR_SET_REF */
struct set *set;
};
struct {
/* EXPR_SET_ELEM */
struct expr *key;
uint64_t timeout;
uint64_t expiration;
const char *comment;
struct stmt *stmt;
uint32_t elem_flags;
};
struct {
/* EXPR_UNARY */
struct expr *arg;
};
struct {
/* EXPR_RANGE, EXPR_BINOP, EXPR_MAPPING, EXPR_RELATIONAL */
struct expr *left;
struct expr *right;
};
struct {
/* EXPR_MAP */
struct expr *map;
struct expr *mappings;
};
struct {
/* EXPR_PAYLOAD */
const struct proto_desc *desc;
const struct proto_hdr_template *tmpl;
enum proto_bases base;
unsigned int offset;
bool is_raw;
} payload;
struct {
/* EXPR_EXTHDR */
const struct exthdr_desc *desc;
const struct proto_hdr_template *tmpl;
unsigned int offset;
enum nft_exthdr_op op;
unsigned int flags;
} exthdr;
struct {
/* EXPR_META */
enum nft_meta_keys key;
enum proto_bases base;
} meta;
struct {
/* SOCKET */
enum nft_socket_keys key;
} socket;
struct {
/* EXPR_RT */
enum nft_rt_keys key;
} rt;
struct {
/* EXPR_CT */
enum nft_ct_keys key;
enum proto_bases base;
int8_t direction;
uint8_t nfproto;
} ct;
struct {
/* EXPR_NUMGEN */
enum nft_ng_types type;
uint32_t mod;
uint32_t offset;
} numgen;
struct {
/* EXPR_HASH */
struct expr *expr;
uint32_t mod;
bool seed_set;
uint32_t seed;
uint32_t offset;
enum nft_hash_types type;
} hash;
struct {
/* EXPR_FIB */
uint32_t flags;
uint32_t result;
} fib;
struct {
/* EXPR_XFRM */
enum nft_xfrm_keys key;
uint8_t direction;
uint8_t spnum;
} xfrm;
struct {
/* EXPR_OSF */
uint8_t ttl;
uint32_t flags;
} osf;
};
};
extern struct expr *expr_alloc(const struct location *loc,
enum expr_types etype,
const struct datatype *dtype,
enum byteorder byteorder, unsigned int len);
extern struct expr *expr_clone(const struct expr *expr);
extern struct expr *expr_get(struct expr *expr);
extern void expr_free(struct expr *expr);
extern void expr_print(const struct expr *expr, struct output_ctx *octx);
extern bool expr_cmp(const struct expr *e1, const struct expr *e2);
extern void expr_describe(const struct expr *expr, struct output_ctx *octx);
extern const struct datatype *expr_basetype(const struct expr *expr);
extern void expr_set_type(struct expr *expr, const struct datatype *dtype,
enum byteorder byteorder);
struct eval_ctx;
extern int expr_binary_error(struct list_head *msgs,
const struct expr *e1, const struct expr *e2,
const char *fmt, ...) __gmp_fmtstring(4, 5);
#define expr_error(msgs, expr, fmt, args...) \
expr_binary_error(msgs, expr, NULL, fmt, ## args)
static inline bool expr_is_constant(const struct expr *expr)
{
return expr->flags & EXPR_F_CONSTANT ? true : false;
}
static inline bool expr_is_singleton(const struct expr *expr)
{
return expr->flags & EXPR_F_SINGLETON ? true : false;
}
extern struct expr *unary_expr_alloc(const struct location *loc,
enum ops op, struct expr *arg);
extern struct expr *binop_expr_alloc(const struct location *loc, enum ops op,
struct expr *left, struct expr *right);
extern bool must_print_eq_op(const struct expr *expr);
extern struct expr *relational_expr_alloc(const struct location *loc, enum ops op,
struct expr *left, struct expr *right);
extern void relational_expr_pctx_update(struct proto_ctx *ctx,
const struct expr *expr);
extern struct expr *verdict_expr_alloc(const struct location *loc,
int verdict, struct expr *chain);
extern struct expr *symbol_expr_alloc(const struct location *loc,
enum symbol_types type, struct scope *scope,
const char *identifier);
const char *expr_name(const struct expr *e);
static inline void symbol_expr_set_type(struct expr *expr,
const struct datatype *dtype)
{
if (expr->etype == EXPR_SYMBOL)
datatype_set(expr, dtype);
}
struct expr *variable_expr_alloc(const struct location *loc,
struct scope *scope, struct symbol *sym);
extern struct expr *constant_expr_alloc(const struct location *loc,
const struct datatype *dtype,
enum byteorder byteorder,
unsigned int len, const void *data);
extern struct expr *constant_expr_join(const struct expr *e1,
const struct expr *e2);
extern struct expr *constant_expr_splice(struct expr *expr, unsigned int len);
extern struct expr *flag_expr_alloc(const struct location *loc,
const struct datatype *dtype,
enum byteorder byteorder,
unsigned int len, unsigned long n);
extern struct expr *bitmask_expr_to_binops(struct expr *expr);
extern struct expr *prefix_expr_alloc(const struct location *loc,
struct expr *expr,
unsigned int prefix_len);
extern struct expr *range_expr_alloc(const struct location *loc,
struct expr *low, struct expr *high);
extern struct expr *compound_expr_alloc(const struct location *loc,
enum expr_types etypes);
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 struct expr *concat_expr_alloc(const struct location *loc);
extern struct expr *list_expr_alloc(const struct location *loc);
extern struct expr *set_expr_alloc(const struct location *loc,
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 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 struct expr *mapping_expr_alloc(const struct location *loc,
struct expr *from, struct expr *to);
extern struct expr *map_expr_alloc(const struct location *loc,
struct expr *arg, struct expr *list);
extern struct expr *set_ref_expr_alloc(const struct location *loc,
struct set *set);
extern struct expr *set_elem_expr_alloc(const struct location *loc,
struct expr *key);
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);
#endif /* NFTABLES_EXPRESSION_H */