summaryrefslogtreecommitdiff
path: root/lib/frrlua.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/frrlua.c')
-rw-r--r--lib/frrlua.c387
1 files changed, 312 insertions, 75 deletions
diff --git a/lib/frrlua.c b/lib/frrlua.c
index 9f9cf8c1f6..d8aaa3aa3c 100644
--- a/lib/frrlua.c
+++ b/lib/frrlua.c
@@ -2,128 +2,365 @@
* This file defines the lua interface into
* FRRouting.
*
- * Copyright (C) 2016 Cumulus Networks, Inc.
- * Donald Sharp
+ * Copyright (C) 2016-2019 Cumulus Networks, Inc.
+ * Donald Sharp, Quentin Young
*
- * This file is part of FRRouting (FRR).
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
*
- * FRR is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2, or (at your option) any later version.
- *
- * FRR is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
*
* You should have received a copy of the GNU General Public License along
- * with FRR; see the file COPYING. If not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <zebra.h>
-#if defined(HAVE_LUA)
+#ifdef HAVE_SCRIPTING
+
#include "prefix.h"
#include "frrlua.h"
#include "log.h"
+#include "buffer.h"
+
+/* Lua stuff */
-static int lua_zlog_debug(lua_State *L)
+/*
+ * FRR convenience functions.
+ *
+ * This section has convenience functions used to make interacting with the Lua
+ * stack easier.
+ */
+
+int frrlua_table_get_integer(lua_State *L, const char *key)
{
- int debug_lua = 1;
- const char *string = lua_tostring(L, 1);
+ int result;
- if (debug_lua)
- zlog_debug("%s", string);
+ lua_pushstring(L, key);
+ lua_gettable(L, -2);
- return 0;
+ result = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+
+ return result;
}
-const char *get_string(lua_State *L, const char *key)
+/*
+ * Encoders.
+ *
+ * This section has functions that convert internal FRR datatypes into Lua
+ * datatypes.
+ */
+
+void lua_pushprefix(lua_State *L, const struct prefix *prefix)
{
- const char *str;
+ char buffer[PREFIX_STRLEN];
- lua_pushstring(L, key);
- lua_gettable(L, -2);
+ lua_newtable(L);
+ lua_pushstring(L, prefix2str(prefix, buffer, PREFIX_STRLEN));
+ lua_setfield(L, -2, "network");
+ lua_pushinteger(L, prefix->prefixlen);
+ lua_setfield(L, -2, "length");
+ lua_pushinteger(L, prefix->family);
+ lua_setfield(L, -2, "family");
+}
- str = (const char *)lua_tostring(L, -1);
+void *lua_toprefix(lua_State *L, int idx)
+{
+ struct prefix *p = XCALLOC(MTYPE_TMP, sizeof(struct prefix));
+
+ lua_getfield(L, idx, "network");
+ (void)str2prefix(lua_tostring(L, -1), p);
lua_pop(L, 1);
- return str;
+ return p;
}
-int get_integer(lua_State *L, const char *key)
+void lua_pushinterface(lua_State *L, const struct interface *ifp)
{
- int result;
+ lua_newtable(L);
+ lua_pushstring(L, ifp->name);
+ lua_setfield(L, -2, "name");
+ lua_pushinteger(L, ifp->ifindex);
+ lua_setfield(L, -2, "ifindex");
+ lua_pushinteger(L, ifp->status);
+ lua_setfield(L, -2, "status");
+ lua_pushinteger(L, ifp->flags);
+ lua_setfield(L, -2, "flags");
+ lua_pushinteger(L, ifp->metric);
+ lua_setfield(L, -2, "metric");
+ lua_pushinteger(L, ifp->speed);
+ lua_setfield(L, -2, "speed");
+ lua_pushinteger(L, ifp->mtu);
+ lua_setfield(L, -2, "mtu");
+ lua_pushinteger(L, ifp->mtu6);
+ lua_setfield(L, -2, "mtu6");
+ lua_pushinteger(L, ifp->bandwidth);
+ lua_setfield(L, -2, "bandwidth");
+ lua_pushinteger(L, ifp->link_ifindex);
+ lua_setfield(L, -2, "link_ifindex");
+ lua_pushinteger(L, ifp->ll_type);
+ lua_setfield(L, -2, "linklayer_type");
+}
- lua_pushstring(L, key);
- lua_gettable(L, -2);
+void *lua_tointerface(lua_State *L, int idx)
+{
+ struct interface *ifp = XCALLOC(MTYPE_TMP, sizeof(struct interface));
- result = lua_tointeger(L, -1);
+ lua_getfield(L, idx, "name");
+ strlcpy(ifp->name, lua_tostring(L, -1), sizeof(ifp->name));
+ lua_pop(L, 1);
+ lua_getfield(L, idx, "ifindex");
+ ifp->ifindex = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+ lua_getfield(L, idx, "status");
+ ifp->status = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+ lua_getfield(L, idx, "flags");
+ ifp->flags = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+ lua_getfield(L, idx, "metric");
+ ifp->metric = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+ lua_getfield(L, idx, "speed");
+ ifp->speed = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+ lua_getfield(L, idx, "mtu");
+ ifp->mtu = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+ lua_getfield(L, idx, "mtu6");
+ ifp->mtu6 = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+ lua_getfield(L, idx, "bandwidth");
+ ifp->bandwidth = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+ lua_getfield(L, idx, "link_ifindex");
+ ifp->link_ifindex = lua_tointeger(L, -1);
+ lua_pop(L, 1);
+ lua_getfield(L, idx, "linklayer_type");
+ ifp->ll_type = lua_tointeger(L, -1);
lua_pop(L, 1);
- return result;
+ return ifp;
}
-static void *lua_alloc(void *ud, void *ptr, size_t osize,
- size_t nsize)
+void lua_pushinaddr(lua_State *L, const struct in_addr *addr)
{
- (void)ud; (void)osize; /* not used */
- if (nsize == 0) {
- free(ptr);
- return NULL;
- } else
- return realloc(ptr, nsize);
+ char buf[INET_ADDRSTRLEN];
+ inet_ntop(AF_INET, addr, buf, sizeof(buf));
+
+ lua_newtable(L);
+ lua_pushinteger(L, addr->s_addr);
+ lua_setfield(L, -2, "value");
+ lua_pushstring(L, buf);
+ lua_setfield(L, -2, "string");
}
-lua_State *lua_initialize(const char *file)
+void *lua_toinaddr(lua_State *L, int idx)
{
- int status;
- lua_State *L = lua_newstate(lua_alloc, NULL);
+ struct in_addr *inaddr = XCALLOC(MTYPE_TMP, sizeof(struct in_addr));
- zlog_debug("Newstate: %p", L);
- luaL_openlibs(L);
- zlog_debug("Opened lib");
- status = luaL_loadfile(L, file);
- if (status) {
- zlog_debug("Failure to open %s %d", file, status);
- lua_close(L);
- return NULL;
- }
+ lua_getfield(L, idx, "value");
+ inaddr->s_addr = lua_tointeger(L, -1);
+ lua_pop(L, 1);
- lua_pcall(L, 0, LUA_MULTRET, 0);
- zlog_debug("Setting global function");
- lua_pushcfunction(L, lua_zlog_debug);
- lua_setglobal(L, "zlog_debug");
+ return inaddr;
+}
+
+
+void lua_pushin6addr(lua_State *L, const struct in6_addr *addr)
+{
+ char buf[INET6_ADDRSTRLEN];
+ inet_ntop(AF_INET6, addr, buf, sizeof(buf));
+
+ lua_newtable(L);
+ lua_pushlstring(L, (const char *)addr->s6_addr, 16);
+ lua_setfield(L, -2, "value");
+ lua_pushstring(L, buf);
+ lua_setfield(L, -2, "string");
+}
+
+void *lua_toin6addr(lua_State *L, int idx)
+{
+ struct in6_addr *in6addr = XCALLOC(MTYPE_TMP, sizeof(struct in6_addr));
+
+ lua_getfield(L, idx, "string");
+ inet_pton(AF_INET6, lua_tostring(L, -1), in6addr);
+ lua_pop(L, 1);
- return L;
+ return in6addr;
}
-void lua_setup_prefix_table(lua_State *L, const struct prefix *prefix)
+void lua_pushsockunion(lua_State *L, const union sockunion *su)
{
- char buffer[100];
+ char buf[SU_ADDRSTRLEN];
+ sockunion2str(su, buf, sizeof(buf));
lua_newtable(L);
- lua_pushstring(L, prefix2str(prefix, buffer, 100));
- lua_setfield(L, -2, "route");
- lua_pushinteger(L, prefix->family);
- lua_setfield(L, -2, "family");
- lua_setglobal(L, "prefix");
+ lua_pushlstring(L, (const char *)sockunion_get_addr(su),
+ sockunion_get_addrlen(su));
+ lua_setfield(L, -2, "value");
+ lua_pushstring(L, buf);
+ lua_setfield(L, -2, "string");
}
-enum lua_rm_status lua_run_rm_rule(lua_State *L, const char *rule)
+void *lua_tosockunion(lua_State *L, int idx)
{
- int status;
+ union sockunion *su = XCALLOC(MTYPE_TMP, sizeof(union sockunion));
+
+ lua_getfield(L, idx, "string");
+ str2sockunion(lua_tostring(L, -1), su);
+
+ return su;
+}
- lua_getglobal(L, rule);
- status = lua_pcall(L, 0, 1, 0);
- if (status) {
- zlog_debug("Executing Failure with function: %s: %d",
- rule, status);
- return LUA_RM_FAILURE;
+void lua_pushtimet(lua_State *L, const time_t *time)
+{
+ lua_pushinteger(L, *time);
+}
+
+void *lua_totimet(lua_State *L, int idx)
+{
+ time_t *t = XCALLOC(MTYPE_TMP, sizeof(time_t));
+
+ *t = lua_tointeger(L, idx);
+
+ return t;
+}
+
+void lua_pushintegerp(lua_State *L, const long long *num)
+{
+ lua_pushinteger(L, *num);
+}
+
+void *lua_tointegerp(lua_State *L, int idx)
+{
+ int isnum;
+ long long *num = XCALLOC(MTYPE_TMP, sizeof(long long));
+
+ *num = lua_tonumberx(L, idx, &isnum);
+ assert(isnum);
+
+ return num;
+}
+
+void *lua_tostringp(lua_State *L, int idx)
+{
+ char *string = XSTRDUP(MTYPE_TMP, lua_tostring(L, idx));
+
+ return string;
+}
+
+/*
+ * Logging.
+ *
+ * Lua-compatible wrappers for FRR logging functions.
+ */
+static const char *frrlua_log_thunk(lua_State *L)
+{
+ int nargs;
+
+ nargs = lua_gettop(L);
+ assert(nargs == 1);
+
+ return lua_tostring(L, 1);
+}
+
+static int frrlua_log_debug(lua_State *L)
+{
+ zlog_debug("%s", frrlua_log_thunk(L));
+ return 0;
+}
+
+static int frrlua_log_info(lua_State *L)
+{
+ zlog_info("%s", frrlua_log_thunk(L));
+ return 0;
+}
+
+static int frrlua_log_notice(lua_State *L)
+{
+ zlog_notice("%s", frrlua_log_thunk(L));
+ return 0;
+}
+
+static int frrlua_log_warn(lua_State *L)
+{
+ zlog_warn("%s", frrlua_log_thunk(L));
+ return 0;
+}
+
+static int frrlua_log_error(lua_State *L)
+{
+ zlog_err("%s", frrlua_log_thunk(L));
+ return 0;
+}
+
+static const luaL_Reg log_funcs[] = {
+ {"debug", frrlua_log_debug},
+ {"info", frrlua_log_info},
+ {"notice", frrlua_log_notice},
+ {"warn", frrlua_log_warn},
+ {"error", frrlua_log_error},
+ {},
+};
+
+void frrlua_export_logging(lua_State *L)
+{
+ lua_newtable(L);
+ luaL_setfuncs(L, log_funcs, 0);
+ lua_setglobal(L, "log");
+}
+
+/*
+ * Debugging.
+ */
+
+char *frrlua_stackdump(lua_State *L)
+{
+ int top = lua_gettop(L);
+
+ char tmpbuf[64];
+ struct buffer *buf = buffer_new(4098);
+
+ for (int i = 1; i <= top; i++) {
+ int t = lua_type(L, i);
+
+ switch (t) {
+ case LUA_TSTRING: /* strings */
+ snprintf(tmpbuf, sizeof(tmpbuf), "\"%s\"\n",
+ lua_tostring(L, i));
+ buffer_putstr(buf, tmpbuf);
+ break;
+ case LUA_TBOOLEAN: /* booleans */
+ snprintf(tmpbuf, sizeof(tmpbuf), "%s\n",
+ lua_toboolean(L, i) ? "true" : "false");
+ buffer_putstr(buf, tmpbuf);
+ break;
+ case LUA_TNUMBER: /* numbers */
+ snprintf(tmpbuf, sizeof(tmpbuf), "%g\n",
+ lua_tonumber(L, i));
+ buffer_putstr(buf, tmpbuf);
+ break;
+ default: /* other values */
+ snprintf(tmpbuf, sizeof(tmpbuf), "%s\n",
+ lua_typename(L, t));
+ buffer_putstr(buf, tmpbuf);
+ break;
+ }
}
- status = lua_tonumber(L, -1);
- return status;
+ char *result = XSTRDUP(MTYPE_TMP, buffer_getstr(buf));
+
+ buffer_free(buf);
+
+ return result;
}
-#endif
+
+#endif /* HAVE_SCRIPTING */