diff options
-rw-r--r-- | lua/common.c | 97 |
1 files changed, 96 insertions, 1 deletions
diff --git a/lua/common.c b/lua/common.c index e1d3e98b..230bd272 100644 --- a/lua/common.c +++ b/lua/common.c @@ -5,6 +5,7 @@ #include "conf/conf.h" #include "filter/filter.h" #include "lua.h" +#include "sysdep/linux/wireguard.h" #include <lua.h> #include <lualib.h> @@ -12,6 +13,9 @@ static linpool *lua_lp; +static void lua_pushwgdevice(lua_State *L, wg_device *dev); +static void lua_pushwgpeer(lua_State *L, wg_peer *peer); + static int luaB_err(lua_State *L) { int n = lua_gettop(L); if (n != 1) @@ -60,7 +64,67 @@ static int luaB_trace(lua_State *L) { return 0; } -#define lua_sett(L, idx, val, what) do { \ +static int luaB_wg_get_device(lua_State *L) { + int n = lua_gettop(L); + if (n != 1) { + log(L_WARN "get_device needs exactly 1 argument"); + return 0; + } + + const char *device_name = lua_tolstring(L, 1, NULL); + log(L_WARN "WG: device name %s", device_name); + lua_pop(L, 1); + + wg_device *dev = NULL; + + if (wg_get_device(&dev, device_name) < 0) { + return luaL_error(L, "Wireguard error opening %s", device_name); + } + + log(L_WARN "WG: device %p", dev); + lua_pushwgdevice(L, dev); + return 1; +} + +static int luaB_wg_device_first_peer(lua_State *L) { + int n = lua_gettop(L); + if (n != 1) { + log(L_WARN "first_peer needs exactly 0 argument"); + return 0; + } + + lua_pushliteral(L, "_internal"); + lua_gettable(L, 1); + if (!lua_isuserdata(L, -1)) + luaL_error(L, "fatal: bird internal state not found, type %d", lua_type(L, -1)); + + wg_device *dev = lua_touserdata(L, -1); + lua_pop(L, 1); + lua_pushwgpeer(L, dev->first_peer); + + return 1; +} + +static int luaB_wg_peer_next_peer(lua_State *L) { + int n = lua_gettop(L); + if (n != 1) { + log(L_WARN "next_peer needs exactly 0 argument"); + return 0; + } + + lua_pushliteral(L, "_internal"); + lua_gettable(L, 1); + if (!lua_isuserdata(L, -1)) + luaL_error(L, "fatal: bird internal state not found, type %d", lua_type(L, -1)); + + wg_peer *peer = lua_touserdata(L, -1); + lua_pop(L, 1); + lua_pushwgpeer(L, peer->next_peer); + + return 1; +} + +#define lua_sett(L, idx, val, what) do { \ lua_pushstring(L, idx); \ lua_push##what(L, val); \ lua_settable(L, -3); \ @@ -73,6 +137,7 @@ static int luaB_trace(lua_State *L) { #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_settableeattr(L, idx, val) lua_sett(L, idx, val, eattr) +#define lua_settablewgdevice(L, idx, val) lua_sett(L, idx, val, wgdevice) #define lua_settablevalue(L, idx, val) lua_sett(L, idx, val, value) #define lua_setglobalcfunction(L, n, val) do { \ @@ -208,6 +273,32 @@ static void lua_pushipaddr(lua_State *L, ip_addr *addr) { lua_setmetatable(L, -2); } +static void lua_pushwgdevice(lua_State *L, wg_device *dev) { + lua_newtable(L); + lua_settablelightuserdata(L, "_internal", dev); + lua_settablecfunction(L, "first_peer", luaB_wg_device_first_peer); + + lua_newtable(L); + lua_settablevalue(L, "__index", -2-1); + lua_setmetatable(L, -2); +} + +static void lua_pushwgpeer(lua_State *L, wg_peer *peer) { + lua_newtable(L); + lua_settablelightuserdata(L, "_internal", peer); + lua_settablecfunction(L, "next_peer", luaB_wg_peer_next_peer); + + wg_key_b64_string b64; + wg_key_to_base64(b64, peer->public_key); + lua_pushliteral(L, "public_key"); + lua_pushlstring(L, b64, strlen(b64)); + lua_settable(L, -3); + + lua_newtable(L); + lua_settablevalue(L, "__index", -2-1); + lua_setmetatable(L, -2); +} + static void lua_pusheattr(lua_State *L, eattr *ea) { /* if (ea->type == EAF_TYPE_IP_ADDRESS) { */ /* lua_settableinteger(L, "data", 17); */ @@ -276,6 +367,10 @@ lua_bird_state *luaB_init(lua_State *L, struct linpool *lp) { lua_pushcfunction(L, luaB_reject); lua_setglobal(L, "reject"); + lua_newtable(L); + lua_settablecfunction(L, "get_device", luaB_wg_get_device); + lua_setglobal(L, "wireguard"); + return lbs; } |