1999-01-15 16:49:17 +00:00
/*
1999-03-17 14:29:39 +00:00
* BIRD Internet Routing Daemon - - Filters
1999-01-15 16:49:17 +00:00
*
1999-03-17 14:29:39 +00:00
* ( c ) 1999 Pavel Machek < pavel @ ucw . cz >
1999-01-15 16:49:17 +00:00
*
* Can be freely distributed and used under the terms of the GNU GPL .
*/
# ifndef _BIRD_FILT_H_
# define _BIRD_FILT_H_
# include "lib/resource.h"
1999-04-07 12:11:08 +00:00
# include "lib/ip.h"
2008-10-26 21:45:09 +00:00
# include "nest/route.h"
2000-04-17 11:20:00 +00:00
# include "nest/attrs.h"
1999-01-15 16:49:17 +00:00
2018-12-27 13:26:11 +00:00
/* IP prefix range structure */
2018-12-20 14:25:04 +00:00
struct f_prefix {
2018-12-27 13:26:11 +00:00
net_addr net ; /* The matching prefix must match this net */
u8 lo , hi ; /* And its length must fit between lo and hi */
2018-12-20 14:25:04 +00:00
} ;
2018-12-27 13:26:11 +00:00
/* Type numbers must be in 0..0xff range */
# define T_MASK 0xff
/* Internal types */
enum f_type {
/* Do not use type of zero, that way we'll see errors easier. */
T_VOID = 1 ,
/* User visible types, which fit in int */
T_INT = 0x10 ,
T_BOOL = 0x11 ,
T_PAIR = 0x12 , /* Notice that pair is stored as integer: first << 16 | second */
T_QUAD = 0x13 ,
/* Put enumerational types in 0x30..0x3f range */
T_ENUM_LO = 0x30 ,
T_ENUM_HI = 0x3f ,
T_ENUM_RTS = 0x30 ,
T_ENUM_BGP_ORIGIN = 0x31 ,
T_ENUM_SCOPE = 0x32 ,
T_ENUM_RTC = 0x33 ,
T_ENUM_RTD = 0x34 ,
T_ENUM_ROA = 0x35 ,
T_ENUM_NETTYPE = 0x36 ,
T_ENUM_RA_PREFERENCE = 0x37 ,
/* new enums go here */
T_ENUM_EMPTY = 0x3f , /* Special hack for atomic_aggr */
# define T_ENUM T_ENUM_LO ... T_ENUM_HI
/* Bigger ones */
T_IP = 0x20 ,
T_NET = 0x21 ,
T_STRING = 0x22 ,
T_PATH_MASK = 0x23 , /* mask for BGP path */
T_PATH = 0x24 , /* BGP path */
T_CLIST = 0x25 , /* Community list */
T_EC = 0x26 , /* Extended community value, u64 */
T_ECLIST = 0x27 , /* Extended community list */
T_LC = 0x28 , /* Large community value, lcomm */
T_LCLIST = 0x29 , /* Large community list */
T_RD = 0x2a , /* Route distinguisher for VPN addresses */
T_PATH_MASK_ITEM = 0x2b , /* Path mask item for path mask constructors */
T_SET = 0x80 ,
T_PREFIX_SET = 0x81 ,
} PACKED ;
/* Filter value; size of this affects filter memory consumption */
2018-12-20 14:25:04 +00:00
struct f_val {
2018-12-27 13:26:11 +00:00
enum f_type type ; /* T_* */
2018-12-20 14:25:04 +00:00
union {
uint i ;
u64 ec ;
lcomm lc ;
ip_addr ip ;
const net_addr * net ;
char * s ;
2018-12-27 13:26:11 +00:00
const struct f_tree * t ;
const struct f_trie * ti ;
const struct adata * ad ;
const struct f_path_mask * path_mask ;
struct f_path_mask_item pmi ;
2018-12-20 14:25:04 +00:00
} val ;
} ;
2018-12-27 13:26:11 +00:00
/* Dynamic attribute definition (eattrs) */
2018-12-20 14:25:04 +00:00
struct f_dynamic_attr {
2018-12-27 13:26:11 +00:00
u8 type ; /* EA type (EAF_*) */
u8 bit ; /* For bitfield accessors */
enum f_type f_type ; /* Filter type */
uint ea_code ; /* EA code */
2018-12-20 14:25:04 +00:00
} ;
2018-12-27 13:26:11 +00:00
enum f_sa_code {
SA_FROM = 1 ,
SA_GW ,
SA_NET ,
SA_PROTO ,
SA_SOURCE ,
SA_SCOPE ,
SA_DEST ,
SA_IFNAME ,
SA_IFINDEX ,
} PACKED ;
/* Static attribute definition (members of struct rta) */
2018-12-20 14:25:04 +00:00
struct f_static_attr {
2018-12-27 13:26:11 +00:00
enum f_type f_type ; /* Filter type */
enum f_sa_code sa_code ; /* Static attribute id */
int readonly : 1 ; /* Don't allow writing */
2018-12-20 14:25:04 +00:00
} ;
2018-12-27 13:26:11 +00:00
/* Filter instruction words */
2017-10-19 10:39:44 +00:00
# define FI__TWOCHAR(a,b) ((a<<8) | b)
# define FI__LIST \
2018-12-20 15:25:54 +00:00
F ( FI_NOP , 0 , ' 0 ' ) \
2017-10-19 10:39:44 +00:00
F ( FI_ADD , 0 , ' + ' ) \
F ( FI_SUBTRACT , 0 , ' - ' ) \
F ( FI_MULTIPLY , 0 , ' * ' ) \
F ( FI_DIVIDE , 0 , ' / ' ) \
F ( FI_AND , 0 , ' & ' ) \
F ( FI_OR , 0 , ' | ' ) \
F ( FI_PAIR_CONSTRUCT , ' m ' , ' p ' ) \
F ( FI_EC_CONSTRUCT , ' m ' , ' c ' ) \
F ( FI_LC_CONSTRUCT , ' m ' , ' l ' ) \
2018-02-28 15:57:50 +00:00
F ( FI_PATHMASK_CONSTRUCT , ' m ' , ' P ' ) \
2017-10-19 10:39:44 +00:00
F ( FI_NEQ , ' ! ' , ' = ' ) \
F ( FI_EQ , ' = ' , ' = ' ) \
F ( FI_LT , 0 , ' < ' ) \
F ( FI_LTE , ' < ' , ' = ' ) \
F ( FI_NOT , 0 , ' ! ' ) \
F ( FI_MATCH , 0 , ' ~ ' ) \
F ( FI_NOT_MATCH , ' ! ' , ' ~ ' ) \
F ( FI_DEFINED , ' d ' , ' e ' ) \
2018-03-13 15:51:04 +00:00
F ( FI_TYPE , 0 , ' T ' ) \
F ( FI_IS_V4 , ' I ' , ' i ' ) \
2017-10-19 10:39:44 +00:00
F ( FI_SET , 0 , ' s ' ) \
F ( FI_CONSTANT , 0 , ' c ' ) \
F ( FI_VARIABLE , 0 , ' V ' ) \
F ( FI_CONSTANT_INDIRECT , 0 , ' C ' ) \
F ( FI_PRINT , 0 , ' p ' ) \
F ( FI_CONDITION , 0 , ' ? ' ) \
F ( FI_PRINT_AND_DIE , ' p ' , ' , ' ) \
F ( FI_RTA_GET , 0 , ' a ' ) \
F ( FI_RTA_SET , ' a ' , ' S ' ) \
F ( FI_EA_GET , ' e ' , ' a ' ) \
F ( FI_EA_SET , ' e ' , ' S ' ) \
F ( FI_PREF_GET , 0 , ' P ' ) \
F ( FI_PREF_SET , ' P ' , ' S ' ) \
F ( FI_LENGTH , 0 , ' L ' ) \
2018-03-13 15:51:04 +00:00
F ( FI_ROA_MAXLEN , ' R ' , ' M ' ) \
F ( FI_ROA_ASN , ' R ' , ' A ' ) \
2018-05-16 09:19:29 +00:00
F ( FI_SADR_SRC , ' n ' , ' s ' ) \
2017-10-19 10:39:44 +00:00
F ( FI_IP , ' c ' , ' p ' ) \
2018-03-13 15:51:04 +00:00
F ( FI_ROUTE_DISTINGUISHER , ' R ' , ' D ' ) \
2017-10-19 10:39:44 +00:00
F ( FI_AS_PATH_FIRST , ' a ' , ' f ' ) \
F ( FI_AS_PATH_LAST , ' a ' , ' l ' ) \
F ( FI_AS_PATH_LAST_NAG , ' a ' , ' L ' ) \
F ( FI_RETURN , 0 , ' r ' ) \
F ( FI_CALL , ' c ' , ' a ' ) \
2018-12-27 13:26:11 +00:00
F ( FI_DROP_RESULT , ' d ' , ' r ' ) \
2017-10-19 10:39:44 +00:00
F ( FI_CLEAR_LOCAL_VARS , ' c ' , ' V ' ) \
F ( FI_SWITCH , ' S ' , ' W ' ) \
F ( FI_IP_MASK , ' i ' , ' M ' ) \
F ( FI_PATH_PREPEND , ' A ' , ' p ' ) \
2018-12-27 13:26:11 +00:00
F ( FI_CLIST_ADD , ' C ' , ' a ' ) \
F ( FI_CLIST_DEL , ' C ' , ' d ' ) \
F ( FI_CLIST_FILTER , ' C ' , ' f ' ) \
F ( FI_ROA_CHECK_IMPLICIT , ' R ' , ' i ' ) \
F ( FI_ROA_CHECK_EXPLICIT , ' R ' , ' e ' ) \
2018-03-13 15:51:04 +00:00
F ( FI_FORMAT , 0 , ' F ' ) \
F ( FI_ASSERT , ' a ' , ' s ' )
2017-10-19 10:39:44 +00:00
2018-12-27 13:26:11 +00:00
/* The enum itself */
2017-10-19 10:39:44 +00:00
enum f_instruction_code {
# define F(c,a,b) \
2018-04-30 10:39:32 +00:00
c ,
2017-10-19 10:39:44 +00:00
FI__LIST
# undef F
2018-04-30 10:49:22 +00:00
FI__MAX ,
2017-10-19 10:39:44 +00:00
} PACKED ;
2018-12-27 13:26:11 +00:00
/* Convert the instruction back to the enum name */
2018-04-30 14:06:53 +00:00
const char * f_instruction_name ( enum f_instruction_code fi ) ;
2018-12-27 13:26:11 +00:00
enum f_instruction_flags {
FIF_PRINTED = 1 , /* FI_PRINT_AND_DIE: message put in buffer */
} ;
union f_inst_attr {
uint i ;
void * p ;
struct rtable_config * rtc ;
} ;
/* Instruction structure for config */
struct f_inst {
struct f_inst * next ; /* Next instruction to be executed */
enum f_instruction_code fi_code ; /* The instruction itself */
2016-11-09 15:36:34 +00:00
u16 aux ; /* Extension to instruction code, T_*, EA_*, EAF_* */
1999-04-10 09:45:08 +00:00
union {
2018-12-27 13:26:11 +00:00
union f_inst_attr a [ 3 ] ; /* The three arguments */
2018-12-20 14:25:04 +00:00
struct f_val val ; /* The value if FI_CONSTANT */
2018-12-27 13:26:11 +00:00
struct {
union f_inst_attr sa_a [ 1 ] ;
struct f_static_attr sa ; /* Static attribute def for FI_RTA_* */
} ;
struct {
union f_inst_attr da_a [ 1 ] ;
struct f_dynamic_attr da ; /* Dynamic attribute def for FI_EA_* */
} ;
2018-12-20 14:25:04 +00:00
} ;
2000-05-16 18:50:51 +00:00
int lineno ;
1999-01-15 16:49:17 +00:00
} ;
2018-12-27 13:26:11 +00:00
/* Possible return values of filter execution */
enum filter_return {
F_NOP = 0 ,
F_NONL ,
F_RETURN ,
F_ACCEPT , /* Need to preserve ordering: accepts < rejects! */
F_REJECT ,
F_ERROR ,
F_QUITBIRD ,
} ;
/* Filter structures for execution */
struct f_line ;
1999-04-10 09:45:08 +00:00
2018-12-27 13:26:11 +00:00
/* The single instruction item */
struct f_line_item {
enum f_instruction_code fi_code ; /* What to do */
enum f_instruction_flags flags ; /* Flags, instruction-specific */
uint lineno ; /* Where */
union {
struct {
const struct f_val * vp ;
const struct symbol * sym ;
} ;
const struct f_line * lines [ 2 ] ;
enum filter_return fret ;
struct f_static_attr sa ;
struct f_dynamic_attr da ;
enum ec_subtype ecs ;
const char * s ;
const struct f_tree * tree ;
const struct rtable_config * rtc ;
uint count ;
} ; /* Additional instruction data */
} ;
/* Line of instructions to be unconditionally executed one after another */
struct f_line {
uint len ; /* Line length */
struct f_line_item items [ 0 ] ; /* The items themselves */
} ;
/* The filter encapsulating structure to be pointed-to from outside */
1999-03-17 14:29:39 +00:00
struct filter {
char * name ;
2018-12-27 13:26:11 +00:00
struct f_line * root ;
} ;
/* Convert the f_inst infix tree to the f_line structures */
struct f_line * f_postfixify_concat ( struct f_inst * root , . . . ) ;
static inline struct f_line * f_postfixify ( struct f_inst * root )
{ return f_postfixify_concat ( root , NULL ) ; }
# define F_VAL_STACK_MAX 4096
/* Value stack for execution */
struct f_val_stack {
uint cnt ; /* Current stack size; 0 for empty */
struct f_val val [ F_VAL_STACK_MAX ] ; /* The stack itself */
} ;
# define F_EXEC_STACK_MAX 4096
/* Exception bits */
enum f_exception {
FE_RETURN = 0x1 ,
} ;
/* Instruction stack for execution */
struct f_exec_stack {
struct {
const struct f_line * line ; /* The line that is being executed */
uint pos ; /* Instruction index in the line */
uint ventry ; /* Value stack depth on entry */
enum f_exception emask ; /* Exception mask */
} item [ F_EXEC_STACK_MAX ] ;
uint cnt ; /* Current stack size; 0 for empty */
1999-03-17 14:29:39 +00:00
} ;
2017-10-19 10:39:44 +00:00
struct f_inst * f_new_inst ( enum f_instruction_code fi_code ) ;
struct f_inst * f_new_inst_da ( enum f_instruction_code fi_code , struct f_dynamic_attr da ) ;
struct f_inst * f_new_inst_sa ( enum f_instruction_code fi_code , struct f_static_attr sa ) ;
2018-12-27 13:26:11 +00:00
static inline struct f_dynamic_attr f_new_dynamic_attr ( u8 type , u8 bit , enum f_type f_type , uint code ) /* Type as core knows it, type as filters know it, and code of dynamic attribute */
{ return ( struct f_dynamic_attr ) { . type = type , . bit = bit , . f_type = f_type , . ea_code = code } ; } /* f_type currently unused; will be handy for static type checking */
2017-10-19 10:39:44 +00:00
static inline struct f_static_attr f_new_static_attr ( int f_type , int code , int readonly )
{ return ( struct f_static_attr ) { . f_type = f_type , . sa_code = code , . readonly = readonly } ; }
1999-04-12 19:58:18 +00:00
struct f_tree * f_new_tree ( void ) ;
2018-12-27 13:26:11 +00:00
struct f_inst * f_generate_complex ( enum f_instruction_code fi_code , struct f_dynamic_attr da , struct f_inst * argument ) ;
2016-01-20 14:38:37 +00:00
struct f_inst * f_generate_roa_check ( struct rtable_config * table , struct f_inst * prefix , struct f_inst * asn ) ;
2012-03-18 16:32:30 +00:00
1999-04-12 19:58:18 +00:00
struct f_tree * build_tree ( struct f_tree * ) ;
2018-12-27 13:26:11 +00:00
const struct f_tree * find_tree ( const struct f_tree * t , const struct f_val * val ) ;
int same_tree ( const struct f_tree * t1 , const struct f_tree * t2 ) ;
void tree_format ( const struct f_tree * t , buffer * buf ) ;
1999-03-02 19:49:28 +00:00
2015-02-21 13:05:20 +00:00
struct f_trie * f_new_trie ( linpool * lp , uint node_size ) ;
2015-12-21 16:17:21 +00:00
void * trie_add_prefix ( struct f_trie * t , const net_addr * n , uint l , uint h ) ;
2018-12-27 13:26:11 +00:00
int trie_match_net ( const struct f_trie * t , const net_addr * n ) ;
int trie_same ( const struct f_trie * t1 , const struct f_trie * t2 ) ;
void trie_format ( const struct f_trie * t , buffer * buf ) ;
2009-03-31 10:55:57 +00:00
1999-08-03 19:31:11 +00:00
struct ea_list ;
struct rte ;
2018-12-27 13:26:11 +00:00
enum filter_return f_run ( const struct filter * filter , struct rte * * rte , struct linpool * tmp_pool , int flags ) ;
enum filter_return f_eval_rte ( const struct f_line * expr , struct rte * * rte , struct linpool * tmp_pool ) ;
enum filter_return f_eval ( const struct f_line * expr , struct linpool * tmp_pool , struct f_val * pres ) ;
uint f_eval_int ( const struct f_line * expr ) ;
2009-08-27 17:01:04 +00:00
1999-04-05 20:10:31 +00:00
char * filter_name ( struct filter * filter ) ;
2000-01-16 17:49:32 +00:00
int filter_same ( struct filter * new , struct filter * old ) ;
1999-03-17 14:29:39 +00:00
2018-12-27 13:26:11 +00:00
int f_same ( const struct f_line * f1 , const struct f_line * f2 ) ;
int val_compare ( const struct f_val * v1 , const struct f_val * v2 ) ;
2000-01-31 17:44:22 +00:00
2018-12-27 13:26:11 +00:00
void val_format ( const struct f_val * v , buffer * buf ) ;
1999-04-07 12:11:08 +00:00
2018-12-27 13:26:11 +00:00
extern const struct f_val f_const_empty_path , f_const_empty_clist , f_const_empty_eclist , f_const_empty_lclist ;
2013-10-05 18:12:28 +00:00
1999-04-05 20:10:31 +00:00
# define FILTER_ACCEPT NULL
# define FILTER_REJECT ((void *) 1)
2018-01-16 03:14:49 +00:00
# define FILTER_UNDEF ((void *) 2) /* Used in BGP */
1999-04-05 20:10:31 +00:00
2013-09-26 20:08:21 +00:00
1999-04-12 19:58:18 +00:00
struct f_tree {
struct f_tree * left , * right ;
struct f_val from , to ;
void * data ;
} ;
2009-03-31 10:55:57 +00:00
struct f_trie_node
{
ip_addr addr , mask , accept ;
2016-11-08 18:27:58 +00:00
uint plen ;
2009-03-31 10:55:57 +00:00
struct f_trie_node * c [ 2 ] ;
} ;
struct f_trie
{
2010-07-27 15:17:11 +00:00
linpool * lp ;
2009-03-31 10:55:57 +00:00
int zero ;
2015-02-21 13:05:20 +00:00
uint node_size ;
struct f_trie_node root [ 0 ] ; /* Root trie node follows */
2009-03-31 10:55:57 +00:00
} ;
1999-10-12 06:27:42 +00:00
# define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val));
2018-01-16 15:20:01 +00:00
# define FF_SILENT 2 /* Silent filter execution */
2000-03-29 09:02:00 +00:00
2018-11-21 19:37:11 +00:00
/* Custom route attributes */
struct custom_attribute {
resource r ;
struct f_dynamic_attr * fda ;
const char * name ;
} ;
struct custom_attribute * ca_lookup ( pool * p , const char * name , int ea_type ) ;
2016-11-09 15:36:34 +00:00
/* Bird Tests */
struct f_bt_test_suite {
node n ; /* Node in config->tests */
2018-12-27 13:26:11 +00:00
struct f_line * fn ; /* Root of function */
2016-11-09 15:36:34 +00:00
const char * fn_name ; /* Name of test */
const char * dsc ; /* Description */
} ;
/* Hook for call bt_assert() function in configuration */
2018-12-27 13:26:11 +00:00
extern void ( * bt_assert_hook ) ( int result , const struct f_line_item * assert ) ;
2016-11-09 15:36:34 +00:00
1999-01-15 16:49:17 +00:00
# endif