mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-11-09 20:58:44 +00:00
Lua filtering able to reject and accept
This commit is contained in:
parent
76a7182321
commit
c30c4bd37f
@ -413,7 +413,7 @@ CF_KEYWORDS(FUNCTION, PRINT, PRINTN, UNSET, RETURN,
|
||||
%nonassoc ELSE
|
||||
|
||||
%type <x> term block cmds cmds_int cmd function_body constant constructor print_one print_list var_list var_listn dynamic_attr static_attr function_call symbol bgp_path_expr
|
||||
%type <f> filter filter_body where_filter
|
||||
%type <f> filter filter_body where_filter lua_call
|
||||
%type <i> type break_command ec_kind
|
||||
%type <i32> cnum
|
||||
%type <e> pair_item ec_item lc_item set_item switch_item set_items switch_items switch_body
|
||||
@ -1058,6 +1058,16 @@ cmd:
|
||||
| BT_ASSERT '(' get_cf_position term get_cf_position ')' ';' { $$ = assert_done($4, $3 + 1, $5 - 1); }
|
||||
;
|
||||
|
||||
lua_call:
|
||||
LUA constant {
|
||||
$$ = cfg_alloc(sizeof(struct filter));
|
||||
$$->name = NULL;
|
||||
$$->root = f_new_inst();
|
||||
$$->root->code = P('L','C');
|
||||
$$->root->a1.p = $2;
|
||||
$$->root->next = NULL;
|
||||
}
|
||||
|
||||
get_cf_position:
|
||||
{
|
||||
$$ = cf_text;
|
||||
|
@ -1580,8 +1580,7 @@ interpret(struct f_inst *what)
|
||||
if (v1.type != T_STRING)
|
||||
runtime("Lua code should be a string argument");
|
||||
|
||||
res.type = T_RETURN;
|
||||
res.val.i = filter_lua_chunk(v1.val.s, f_rte, f_old_rta, f_tmp_attrs, f_pool);
|
||||
res = filter_lua_chunk(v1.val.s, f_rte, f_old_rta, f_tmp_attrs, f_pool);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -206,6 +206,8 @@ struct f_trie
|
||||
};
|
||||
|
||||
#define NEW_F_VAL struct f_val * val; val = cfg_alloc(sizeof(struct f_val));
|
||||
#define F_VAL(_type, where, value) ((struct f_val) { .type = (_type), .val.where = (value) })
|
||||
#define F_VAL_VOID ((struct f_val) { .type = T_VOID })
|
||||
|
||||
#define FF_FORCE_TMPATTR 1 /* Force all attributes to be temporary */
|
||||
|
||||
@ -221,6 +223,6 @@ struct f_bt_test_suite {
|
||||
extern void (*bt_assert_hook)(int result, struct f_inst *assert);
|
||||
|
||||
/* Lua */
|
||||
int filter_lua_chunk(const char *chunk, struct rte **e, struct rta *a, struct ea_list **ea, struct linpool *lp);
|
||||
struct f_val filter_lua_chunk(const char *chunk, struct rte **e, struct rta *a, struct ea_list **ea, struct linpool *lp);
|
||||
|
||||
#endif
|
||||
|
47
lua/common.c
47
lua/common.c
@ -64,6 +64,12 @@ static int luaB_trace(lua_State *L) {
|
||||
#define lua_settablecfunction(L, idx, val) lua_sett(L, idx, val, cfunction)
|
||||
#define lua_settableinteger(L, idx, val) lua_sett(L, idx, val, integer)
|
||||
#define lua_settableip4(L, idx, val) lua_sett(L, idx, val, ip4)
|
||||
#define lua_settablelightuserdata(L, idx, val) lua_sett(L, idx, val, lightuserdata)
|
||||
|
||||
#define lua_setglobalcfunction(L, n, val) do { \
|
||||
lua_pushcfunction(L, val); \
|
||||
lua_setglobal(L, n); \
|
||||
} while (0)
|
||||
|
||||
static int luaB_generic_concat(lua_State *L) {
|
||||
int n = lua_gettop(L);
|
||||
@ -125,7 +131,34 @@ static void lua_puship4(lua_State *L, ip4_addr a) {
|
||||
lua_setmetatable(L, -2);
|
||||
}
|
||||
|
||||
void luaB_push_bird(lua_State *L) {
|
||||
static lua_bird_state *luaB_getinternalstate(lua_State *L) {
|
||||
lua_getglobal(L, "bird");
|
||||
lua_pushstring(L, "_internal_state");
|
||||
lua_gettable(L, -2);
|
||||
if (!lua_isuserdata(L, -1))
|
||||
luaL_error(L, "fatal: bird internal state not found, type %d", lua_type(L, -1));
|
||||
|
||||
lua_bird_state *lbs = lua_touserdata(L, -1);
|
||||
lua_pop(L, 2); /* Pop the user data and then the table. The string is consumed by gettable(). */
|
||||
return lbs;
|
||||
}
|
||||
|
||||
static int luaB_global_exception(lua_State *L, int value) {
|
||||
int n = lua_gettop(L);
|
||||
if (n > 1)
|
||||
log(L_WARN "Called exception with too many arguments.");
|
||||
|
||||
lua_bird_state *lbs = luaB_getinternalstate(L);
|
||||
lbs->exception = value;
|
||||
|
||||
lua_error(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int luaB_accept(lua_State *L) { return luaB_global_exception(L, F_ACCEPT); }
|
||||
static inline int luaB_reject(lua_State *L) { return luaB_global_exception(L, F_REJECT); }
|
||||
|
||||
lua_bird_state *luaB_init(lua_State *L, struct linpool *lp) {
|
||||
lua_newtable(L);
|
||||
|
||||
lua_settablecfunction(L, "err", luaB_err);
|
||||
@ -133,9 +166,21 @@ void luaB_push_bird(lua_State *L) {
|
||||
lua_settablecfunction(L, "info", luaB_info);
|
||||
lua_settablecfunction(L, "trace", luaB_trace);
|
||||
|
||||
lua_bird_state *lbs = lp_allocz(lp, sizeof(lua_bird_state));
|
||||
|
||||
lua_settablelightuserdata(L, "_internal_state", lbs);
|
||||
|
||||
lua_settableip4(L, "router_id", config->router_id);
|
||||
|
||||
lua_setglobal(L, "bird");
|
||||
|
||||
lua_pushcfunction(L, luaB_accept);
|
||||
lua_setglobal(L, "accept");
|
||||
|
||||
lua_pushcfunction(L, luaB_reject);
|
||||
lua_setglobal(L, "reject");
|
||||
|
||||
return lbs;
|
||||
}
|
||||
|
||||
void luaB_push_route(lua_State *L, struct rte *e) {
|
||||
|
22
lua/filter.c
22
lua/filter.c
@ -6,21 +6,25 @@
|
||||
#include <lualib.h>
|
||||
#include <lauxlib.h>
|
||||
|
||||
int filter_lua_chunk(const char *chunk, struct rte **e, struct rta *a, struct ea_list **ea, struct linpool *lp) {
|
||||
/* Docs: http://pgl.yoyo.org/luai/i/luaL_dostring */
|
||||
|
||||
struct f_val filter_lua_chunk(const char *chunk, struct rte **e, struct rta *a, struct ea_list **ea, struct linpool *lp) {
|
||||
lua_State *L = luaL_newstate();
|
||||
luaL_openlibs(L);
|
||||
luaB_push_bird(L);
|
||||
lua_bird_state *lbs = luaB_init(L, lp);
|
||||
luaB_push_route(L, *e);
|
||||
int le = luaL_dostring(L, chunk);
|
||||
int out;
|
||||
if (le) {
|
||||
log(L_WARN "bad lua: %s", lua_tostring(L, -1));
|
||||
out = F_ERROR;
|
||||
struct f_val out = F_VAL_VOID;
|
||||
if (le && lbs->exception) {
|
||||
out = F_VAL(T_RETURN, i, lbs->exception);
|
||||
} else if (le) {
|
||||
log(L_ERR "bad lua: %s", lua_tostring(L, -1));
|
||||
out = F_VAL(T_RETURN, i, F_ERROR);
|
||||
} else if (lua_isnumber(L, -1)) {
|
||||
out = lua_tonumber(L, -1);
|
||||
out = F_VAL(T_INT, i, lua_tonumber(L, -1));
|
||||
} else {
|
||||
log(L_WARN "lua return value is not a number: %s", lua_tostring(L, -1));
|
||||
out = F_ERROR;
|
||||
log(L_WARN "lua return value is not a number (unimplemented): %s", lua_tostring(L, -1));
|
||||
out = F_VAL(T_RETURN, i, F_ERROR);
|
||||
}
|
||||
|
||||
lua_close(L);
|
||||
|
@ -2,5 +2,10 @@
|
||||
|
||||
#include <lua.h>
|
||||
|
||||
void luaB_push_bird(lua_State *L);
|
||||
typedef struct lua_bird_state {
|
||||
int exception;
|
||||
} lua_bird_state;
|
||||
|
||||
lua_bird_state *luaB_init(lua_State *L, struct linpool *lp);
|
||||
void luaB_push_route(lua_State *L, rte *e);
|
||||
|
||||
|
@ -262,14 +262,7 @@ rtable:
|
||||
|
||||
imexport:
|
||||
FILTER filter { $$ = $2; }
|
||||
| LUA constant {
|
||||
$$ = cfg_alloc(sizeof(struct filter));
|
||||
$$->name = NULL;
|
||||
$$->root = f_new_inst();
|
||||
$$->root->code = P('L','C');
|
||||
$$->root->a1.p = $2;
|
||||
$$->root->next = NULL;
|
||||
}
|
||||
| lua_call
|
||||
| where_filter
|
||||
| ALL { $$ = FILTER_ACCEPT; }
|
||||
| NONE { $$ = FILTER_REJECT; }
|
||||
|
Loading…
Reference in New Issue
Block a user