summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/command.c6
-rw-r--r--lib/compiler.h23
-rw-r--r--lib/frrlua.c100
-rw-r--r--lib/frrlua.h21
-rw-r--r--lib/frrscript.c18
-rw-r--r--lib/frrscript.h76
-rw-r--r--lib/sockunion.c3
-rw-r--r--lib/sockunion.h1
8 files changed, 199 insertions, 49 deletions
diff --git a/lib/command.c b/lib/command.c
index 560d4a09f8..9dac60599c 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -2428,14 +2428,16 @@ DEFUN(script,
struct prefix p;
(void)str2prefix("1.2.3.4/24", &p);
-
struct frrscript *fs = frrscript_load(argv[1]->arg, NULL);
if (fs == NULL) {
vty_out(vty, "Script '/etc/frr/scripts/%s.lua' not found\n",
argv[1]->arg);
} else {
- int ret = frrscript_call(fs, NULL);
+ int ret = frrscript_call(fs, ("p", &p));
+ char buf[40];
+ prefix2str(&p, buf, sizeof(buf));
+ vty_out(vty, "p: %s\n", buf);
vty_out(vty, "Script result: %d\n", ret);
}
diff --git a/lib/compiler.h b/lib/compiler.h
index 970ed297fc..bf443906eb 100644
--- a/lib/compiler.h
+++ b/lib/compiler.h
@@ -173,6 +173,29 @@ extern "C" {
#define MACRO_REPEAT(NAME, ...) \
MACRO_VARIANT(_MACRO_REPEAT, ##__VA_ARGS__)(NAME, ##__VA_ARGS__)
+/* per-arglist repeat macro, use like this:
+ * #define foo(...) MAP_LISTS(F, ##__VA_ARGS__)
+ * where F is a n-ary function where n is the number of args in each arglist.
+ * e.g.: MAP_LISTS(f, (a, b), (c, d))
+ * expands to: f(a, b); f(c, d)
+ */
+
+#define ESC(...) __VA_ARGS__
+#define MAP_LISTS(M, ...) \
+ _CONCAT(_MAP_LISTS_, PP_NARG(__VA_ARGS__))(M, ##__VA_ARGS__)
+#define _MAP_LISTS_0(M)
+#define _MAP_LISTS_1(M, _1) ESC(M _1)
+#define _MAP_LISTS_2(M, _1, _2) ESC(M _1; M _2)
+#define _MAP_LISTS_3(M, _1, _2, _3) ESC(M _1; M _2; M _3)
+#define _MAP_LISTS_4(M, _1, _2, _3, _4) ESC(M _1; M _2; M _3; M _4)
+#define _MAP_LISTS_5(M, _1, _2, _3, _4, _5) ESC(M _1; M _2; M _3; M _4; M _5)
+#define _MAP_LISTS_6(M, _1, _2, _3, _4, _5, _6) \
+ ESC(M _1; M _2; M _3; M _4; M _5; M _6)
+#define _MAP_LISTS_7(M, _1, _2, _3, _4, _5, _6, _7) \
+ ESC(M _1; M _2; M _3; M _4; M _5; M _6; M _7)
+#define _MAP_LISTS_8(M, _1, _2, _3, _4, _5, _6, _7, _8) \
+ ESC(M _1; M _2; M _3; M _4; M _5; M _6; M _7; M _8)
+
/*
* for warnings on macros, put in the macro content like this:
* #define MACRO BLA CPP_WARN("MACRO has been deprecated")
diff --git a/lib/frrlua.c b/lib/frrlua.c
index d8aaa3aa3c..e97e48121c 100644
--- a/lib/frrlua.c
+++ b/lib/frrlua.c
@@ -52,10 +52,9 @@ int frrlua_table_get_integer(lua_State *L, const char *key)
}
/*
- * Encoders.
- *
* This section has functions that convert internal FRR datatypes into Lua
- * datatypes.
+ * datatypes: one encoder function and two decoder functions for each type.
+ *
*/
void lua_pushprefix(lua_State *L, const struct prefix *prefix)
@@ -71,14 +70,19 @@ void lua_pushprefix(lua_State *L, const struct prefix *prefix)
lua_setfield(L, -2, "family");
}
-void *lua_toprefix(lua_State *L, int idx)
+void lua_decode_prefix(lua_State *L, int idx, struct prefix *prefix)
{
- struct prefix *p = XCALLOC(MTYPE_TMP, sizeof(struct prefix));
-
lua_getfield(L, idx, "network");
- (void)str2prefix(lua_tostring(L, -1), p);
+ (void)str2prefix(lua_tostring(L, -1), prefix);
lua_pop(L, 1);
+ /* pop the table */
+ lua_pop(L, 1);
+}
+void *lua_toprefix(lua_State *L, int idx)
+{
+ struct prefix *p = XCALLOC(MTYPE_TMP, sizeof(struct prefix));
+ lua_decode_prefix(L, idx, p);
return p;
}
@@ -109,10 +113,8 @@ void lua_pushinterface(lua_State *L, const struct interface *ifp)
lua_setfield(L, -2, "linklayer_type");
}
-void *lua_tointerface(lua_State *L, int idx)
+void lua_decode_interface(lua_State *L, int idx, struct interface *ifp)
{
- struct interface *ifp = XCALLOC(MTYPE_TMP, sizeof(struct interface));
-
lua_getfield(L, idx, "name");
strlcpy(ifp->name, lua_tostring(L, -1), sizeof(ifp->name));
lua_pop(L, 1);
@@ -146,13 +148,21 @@ void *lua_tointerface(lua_State *L, int idx)
lua_getfield(L, idx, "linklayer_type");
ifp->ll_type = lua_tointeger(L, -1);
lua_pop(L, 1);
+ /* pop the table */
+ lua_pop(L, 1);
+}
+void *lua_tointerface(lua_State *L, int idx)
+{
+ struct interface *ifp = XCALLOC(MTYPE_TMP, sizeof(struct interface));
+ lua_decode_interface(L, idx, ifp);
return ifp;
}
void lua_pushinaddr(lua_State *L, const struct in_addr *addr)
{
char buf[INET_ADDRSTRLEN];
+
inet_ntop(AF_INET, addr, buf, sizeof(buf));
lua_newtable(L);
@@ -162,14 +172,19 @@ void lua_pushinaddr(lua_State *L, const struct in_addr *addr)
lua_setfield(L, -2, "string");
}
-void *lua_toinaddr(lua_State *L, int idx)
+void lua_decode_inaddr(lua_State *L, int idx, struct in_addr *inaddr)
{
- struct in_addr *inaddr = XCALLOC(MTYPE_TMP, sizeof(struct in_addr));
-
lua_getfield(L, idx, "value");
inaddr->s_addr = lua_tointeger(L, -1);
lua_pop(L, 1);
+ /* pop the table */
+ lua_pop(L, 1);
+}
+void *lua_toinaddr(lua_State *L, int idx)
+{
+ struct in_addr *inaddr = XCALLOC(MTYPE_TMP, sizeof(struct in_addr));
+ lua_decode_inaddr(L, idx, inaddr);
return inaddr;
}
@@ -177,6 +192,7 @@ void *lua_toinaddr(lua_State *L, int idx)
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);
@@ -186,20 +202,26 @@ void lua_pushin6addr(lua_State *L, const struct in6_addr *addr)
lua_setfield(L, -2, "string");
}
-void *lua_toin6addr(lua_State *L, int idx)
+void lua_decode_in6addr(lua_State *L, int idx, struct in6_addr *in6addr)
{
- 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);
+ /* pop the table */
+ lua_pop(L, 1);
+}
+void *lua_toin6addr(lua_State *L, int idx)
+{
+ struct in6_addr *in6addr = XCALLOC(MTYPE_TMP, sizeof(struct in6_addr));
+ lua_decode_in6addr(L, idx, in6addr);
return in6addr;
}
void lua_pushsockunion(lua_State *L, const union sockunion *su)
{
char buf[SU_ADDRSTRLEN];
+
sockunion2str(su, buf, sizeof(buf));
lua_newtable(L);
@@ -210,13 +232,20 @@ void lua_pushsockunion(lua_State *L, const union sockunion *su)
lua_setfield(L, -2, "string");
}
-void *lua_tosockunion(lua_State *L, int idx)
+void lua_decode_sockunion(lua_State *L, int idx, union sockunion *su)
{
- union sockunion *su = XCALLOC(MTYPE_TMP, sizeof(union sockunion));
-
lua_getfield(L, idx, "string");
str2sockunion(lua_tostring(L, -1), su);
+ lua_pop(L, 1);
+ /* pop the table */
+ lua_pop(L, 1);
+}
+
+void *lua_tosockunion(lua_State *L, int idx)
+{
+ union sockunion *su = XCALLOC(MTYPE_TMP, sizeof(union sockunion));
+ lua_decode_sockunion(L, idx, su);
return su;
}
@@ -225,12 +254,17 @@ void lua_pushtimet(lua_State *L, const time_t *time)
lua_pushinteger(L, *time);
}
+void lua_decode_timet(lua_State *L, int idx, time_t *t)
+{
+ *t = lua_tointeger(L, idx);
+ lua_pop(L, 1);
+}
+
void *lua_totimet(lua_State *L, int idx)
{
time_t *t = XCALLOC(MTYPE_TMP, sizeof(time_t));
- *t = lua_tointeger(L, idx);
-
+ lua_decode_timet(L, idx, t);
return t;
}
@@ -239,17 +273,28 @@ void lua_pushintegerp(lua_State *L, const long long *num)
lua_pushinteger(L, *num);
}
-void *lua_tointegerp(lua_State *L, int idx)
+void lua_decode_integerp(lua_State *L, int idx, long long *num)
{
int isnum;
- long long *num = XCALLOC(MTYPE_TMP, sizeof(long long));
-
*num = lua_tonumberx(L, idx, &isnum);
+ lua_pop(L, 1);
assert(isnum);
+}
+
+void *lua_tointegerp(lua_State *L, int idx)
+{
+ long long *num = XCALLOC(MTYPE_TMP, sizeof(long long));
+ lua_decode_integerp(L, idx, num);
return num;
}
+void lua_decode_stringp(lua_State *L, int idx, char *str)
+{
+ strlcpy(str, lua_tostring(L, idx), strlen(str) + 1);
+ lua_pop(L, 1);
+}
+
void *lua_tostringp(lua_State *L, int idx)
{
char *string = XSTRDUP(MTYPE_TMP, lua_tostring(L, idx));
@@ -258,6 +303,13 @@ void *lua_tostringp(lua_State *L, int idx)
}
/*
+ * Decoder for const values, since we cannot modify them.
+ */
+void lua_decode_noop(lua_State *L, int idx, const void *ptr)
+{
+}
+
+/*
* Logging.
*
* Lua-compatible wrappers for FRR logging functions.
diff --git a/lib/frrlua.h b/lib/frrlua.h
index 6fb30938b0..c4de82740c 100644
--- a/lib/frrlua.h
+++ b/lib/frrlua.h
@@ -50,6 +50,8 @@ static inline void lua_pushstring_wrapper(lua_State *L, const char *str)
*/
void lua_pushprefix(lua_State *L, const struct prefix *prefix);
+void lua_decode_prefix(lua_State *L, int idx, struct prefix *prefix);
+
/*
* Converts the Lua value at idx to a prefix.
*
@@ -63,6 +65,8 @@ void *lua_toprefix(lua_State *L, int idx);
*/
void lua_pushinterface(lua_State *L, const struct interface *ifp);
+void lua_decode_interface(lua_State *L, int idx, struct interface *ifp);
+
/*
* Converts the Lua value at idx to an interface.
*
@@ -77,6 +81,8 @@ void *lua_tointerface(lua_State *L, int idx);
*/
void lua_pushinaddr(lua_State *L, const struct in_addr *addr);
+void lua_decode_inaddr(lua_State *L, int idx, struct in_addr *addr);
+
/*
* Converts the Lua value at idx to an in_addr.
*
@@ -90,6 +96,8 @@ void *lua_toinaddr(lua_State *L, int idx);
*/
void lua_pushin6addr(lua_State *L, const struct in6_addr *addr);
+void lua_decode_in6addr(lua_State *L, int idx, struct in6_addr *addr);
+
/*
* Converts the Lua value at idx to an in6_addr.
*
@@ -103,6 +111,8 @@ void *lua_toin6addr(lua_State *L, int idx);
*/
void lua_pushtimet(lua_State *L, const time_t *time);
+void lua_decode_timet(lua_State *L, int idx, time_t *time);
+
/*
* Converts the Lua value at idx to a time_t.
*
@@ -116,6 +126,8 @@ void *lua_totimet(lua_State *L, int idx);
*/
void lua_pushsockunion(lua_State *L, const union sockunion *su);
+void lua_decode_sockunion(lua_State *L, int idx, union sockunion *su);
+
/*
* Converts the Lua value at idx to a sockunion.
*
@@ -129,6 +141,8 @@ void *lua_tosockunion(lua_State *L, int idx);
*/
void lua_pushintegerp(lua_State *L, const long long *num);
+void lua_decode_integerp(lua_State *L, int idx, long long *num);
+
/*
* Converts the Lua value at idx to an int.
*
@@ -137,6 +151,8 @@ void lua_pushintegerp(lua_State *L, const long long *num);
*/
void *lua_tointegerp(lua_State *L, int idx);
+void lua_decode_stringp(lua_State *L, int idx, char *str);
+
/*
* Pop string.
*
@@ -146,6 +162,11 @@ void *lua_tointegerp(lua_State *L, int idx);
void *lua_tostringp(lua_State *L, int idx);
/*
+ * No-op decocder
+ */
+void lua_decode_noop(lua_State *L, int idx, const void *ptr);
+
+/*
* Retrieve an integer from table on the top of the stack.
*
* key
diff --git a/lib/frrscript.c b/lib/frrscript.c
index 10d400886d..1a9f3639dd 100644
--- a/lib/frrscript.c
+++ b/lib/frrscript.c
@@ -104,24 +104,8 @@ static void codec_free(struct codec *c)
/* Generic script APIs */
-int frrscript_call(struct frrscript *fs, struct frrscript_env *env)
+int _frrscript_call(struct frrscript *fs)
{
- struct frrscript_codec c = {};
- const void *arg;
- const char *bindname;
-
- /* Encode script arguments */
- for (int i = 0; env && env[i].val != NULL; i++) {
- bindname = env[i].name;
- c.typename = env[i].typename;
- arg = env[i].val;
-
- struct frrscript_codec *codec = hash_lookup(codec_hash, &c);
- assert(codec && "No encoder for type");
- codec->encoder(fs->L, arg);
-
- lua_setglobal(fs->L, bindname);
- }
int ret = lua_pcall(fs->L, 0, 0, 0);
diff --git a/lib/frrscript.h b/lib/frrscript.h
index f4057f531b..8612c602f3 100644
--- a/lib/frrscript.h
+++ b/lib/frrscript.h
@@ -25,6 +25,7 @@
#include <lua.h>
#include "frrlua.h"
+#include "../bgpd/bgp_script.h"
#ifdef __cplusplus
extern "C" {
@@ -96,6 +97,56 @@ void frrscript_register_type_codecs(struct frrscript_codec *codecs);
*/
void frrscript_init(const char *scriptdir);
+#define ENCODE_ARGS(name, value) \
+ do { \
+ ENCODE_ARGS_WITH_STATE(L, value); \
+ lua_setglobal(L, name); \
+ } while (0)
+
+#define DECODE_ARGS(name, value) \
+ do { \
+ lua_getglobal(L, name); \
+ DECODE_ARGS_WITH_STATE(L, value); \
+ } while (0)
+
+/*
+ * Maps the type of value to its encoder/decoder.
+ * Add new mappings here.
+ *
+ * L
+ * Lua state
+ * scriptdir
+ * Directory in which to look for scripts
+ */
+#define ENCODE_ARGS_WITH_STATE(L, value) \
+ _Generic((value), \
+long long * : lua_pushintegerp, \
+struct prefix * : lua_pushprefix, \
+struct interface * : lua_pushinterface, \
+struct in_addr * : lua_pushinaddr, \
+struct in6_addr * : lua_pushin6addr, \
+union sockunion * : lua_pushsockunion, \
+time_t * : lua_pushtimet, \
+char * : lua_pushstring_wrapper, \
+struct attr * : lua_pushattr, \
+struct peer * : lua_pushpeer, \
+const struct prefix * : lua_pushprefix \
+)(L, value)
+
+#define DECODE_ARGS_WITH_STATE(L, value) \
+ _Generic((value), \
+long long * : lua_decode_integerp, \
+struct prefix * : lua_decode_prefix, \
+struct interface * : lua_decode_interface, \
+struct in_addr * : lua_decode_inaddr, \
+struct in6_addr * : lua_decode_in6addr, \
+union sockunion * : lua_decode_sockunion, \
+time_t * : lua_decode_timet, \
+char * : lua_decode_stringp, \
+struct attr * : lua_decode_attr, \
+struct peer * : lua_decode_noop, \
+const struct prefix * : lua_decode_noop \
+)(L, -1, value)
/*
* Call script.
@@ -103,14 +154,31 @@ void frrscript_init(const char *scriptdir);
* fs
* The script to call; this is obtained from frrscript_load().
*
- * env
- * The script's environment. Specify this as an array of frrscript_env.
- *
* Returns:
* 0 if the script ran successfully, nonzero otherwise.
*/
-int frrscript_call(struct frrscript *fs, struct frrscript_env *env);
+int _frrscript_call(struct frrscript *fs);
+/*
+ * Wrapper for call script. Maps values passed in to their encoder
+ * and decoder types.
+ *
+ * fs
+ * The script to call; this is obtained from frrscript_load().
+ *
+ * Returns:
+ * 0 if the script ran successfully, nonzero otherwise.
+ */
+#define frrscript_call(fs, ...) \
+ ({ \
+ lua_State *L = fs->L; \
+ MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \
+ int ret = _frrscript_call(fs); \
+ if (ret == 0) { \
+ MAP_LISTS(DECODE_ARGS, ##__VA_ARGS__); \
+ } \
+ ret; \
+ })
/*
* Get result from finished script.
diff --git a/lib/sockunion.c b/lib/sockunion.c
index e6340a1743..c7af458e9e 100644
--- a/lib/sockunion.c
+++ b/lib/sockunion.c
@@ -606,8 +606,7 @@ static void __attribute__((unused)) sockunion_print(const union sockunion *su)
}
}
-static int in6addr_cmp(const struct in6_addr *addr1,
- const struct in6_addr *addr2)
+int in6addr_cmp(const struct in6_addr *addr1, const struct in6_addr *addr2)
{
unsigned int i;
const uint8_t *p1, *p2;
diff --git a/lib/sockunion.h b/lib/sockunion.h
index 2cc80bb70f..9e6719ccf9 100644
--- a/lib/sockunion.h
+++ b/lib/sockunion.h
@@ -73,6 +73,7 @@ enum connect_result { connect_error, connect_success, connect_in_progress };
/* Prototypes. */
extern int str2sockunion(const char *, union sockunion *);
extern const char *sockunion2str(const union sockunion *, char *, size_t);
+int in6addr_cmp(const struct in6_addr *addr1, const struct in6_addr *addr2);
extern int sockunion_cmp(const union sockunion *, const union sockunion *);
extern int sockunion_same(const union sockunion *, const union sockunion *);
extern unsigned int sockunion_hash(const union sockunion *);