summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lua/common.c97
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;
}