+// SPDX-License-Identifier: GPL-2.0-or-later
/* Scripting foo
* Copyright (C) 2020 NVIDIA Corporation
* Quentin Young
- *
- * 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.
- *
- * 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 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>
DEFINE_MTYPE_STATIC(LIB, SCRIPT, "Scripting");
+/*
+ * Script name hash utilities
+ */
+
+struct frrscript_names_head frrscript_names_hash;
+
+/*
+ * Wrapper for frrscript_names_add
+ * Use this to register hook calls when a daemon starts up
+ */
+int frrscript_names_add_function_name(const char *function_name)
+{
+ struct frrscript_names_entry *insert =
+ XCALLOC(MTYPE_SCRIPT, sizeof(*insert));
+ strlcpy(insert->function_name, function_name,
+ sizeof(insert->function_name));
+
+ if (frrscript_names_add(&frrscript_names_hash, insert)) {
+ zlog_warn(
+ "Failed to add hook call function name to script_names");
+ return 1;
+ }
+ return 0;
+}
+
+void frrscript_names_destroy(void)
+{
+ struct frrscript_names_entry *ne;
+
+ while ((ne = frrscript_names_pop(&frrscript_names_hash)))
+ XFREE(MTYPE_SCRIPT, ne);
+}
+
+/*
+ * Given a function_name, set its script_name. function_names and script_names
+ * are one-to-one. Each set will wipe the previous script_name.
+ * Return 0 if set was successful, else 1.
+ *
+ * script_name is the base name of the file, without .lua.
+ */
+int frrscript_names_set_script_name(const char *function_name,
+ const char *script_name)
+{
+ struct frrscript_names_entry lookup;
+
+ strlcpy(lookup.function_name, function_name,
+ sizeof(lookup.function_name));
+ struct frrscript_names_entry *snhe =
+ frrscript_names_find(&frrscript_names_hash, &lookup);
+ if (!snhe)
+ return 1;
+ strlcpy(snhe->script_name, script_name, sizeof(snhe->script_name));
+ return 0;
+}
+
+/*
+ * Given a function_name, get its script_name.
+ * Return NULL if function_name not found.
+ *
+ * script_name is the base name of the file, without .lua.
+ */
+char *frrscript_names_get_script_name(const char *function_name)
+{
+ struct frrscript_names_entry lookup;
+
+ strlcpy(lookup.function_name, function_name,
+ sizeof(lookup.function_name));
+ struct frrscript_names_entry *snhe =
+ frrscript_names_find(&frrscript_names_hash, &lookup);
+ if (!snhe)
+ return NULL;
+
+ if (snhe->script_name[0] == '\0')
+ return NULL;
+
+ return snhe->script_name;
+}
+
+uint32_t frrscript_names_hash_key(const struct frrscript_names_entry *snhe)
+{
+ return string_hash_make(snhe->function_name);
+}
+
+int frrscript_names_hash_cmp(const struct frrscript_names_entry *snhe1,
+ const struct frrscript_names_entry *snhe2)
+{
+ return strncmp(snhe1->function_name, snhe2->function_name,
+ sizeof(snhe1->function_name));
+}
+
/* Codecs */
struct frrscript_codec frrscript_codecs_lib[] = {
return e;
}
-#if 0
-static void codec_free(struct codec *c)
+static void codec_free(void *data)
{
- XFREE(MTYPE_TMP, c->typename);
- XFREE(MTYPE_TMP, c);
+ struct frrscript_codec *c = data;
+ char *constworkaroundandihateit = (char *)c->typename;
+
+ XFREE(MTYPE_SCRIPT, constworkaroundandihateit);
+ XFREE(MTYPE_SCRIPT, c);
}
-#endif
/* Lua function hash utils */
void *lua_function_alloc(void *arg)
{
struct lua_function_state *tmp = arg;
-
struct lua_function_state *lfs =
XCALLOC(MTYPE_SCRIPT, sizeof(struct lua_function_state));
+
lfs->name = tmp->name;
lfs->L = tmp->L;
return lfs;
}
-static void lua_function_free(struct hash_bucket *b, void *data)
+static void lua_function_free(void *data)
{
- struct lua_function_state *lfs = (struct lua_function_state *)b->data;
+ struct lua_function_state *lfs = data;
+
lua_close(lfs->L);
XFREE(MTYPE_SCRIPT, lfs);
}
assert(!"Type codec double-registered.");
}
- assert(hash_get(codec_hash, &c, codec_alloc));
+ (void)hash_get(codec_hash, &c, codec_alloc);
}
void frrscript_register_type_codecs(struct frrscript_codec *codecs)
}
if (luaL_dofile(L, script_name) != 0) {
- zlog_err("frrscript: failed loading script '%s.lua': error: %s",
+ zlog_err("frrscript: failed loading script '%s': error: %s",
script_name, lua_tostring(L, -1));
goto fail;
}
/* To check the Lua function, we get it from the global table */
lua_getglobal(L, function_name);
if (lua_isfunction(L, lua_gettop(L)) == 0) {
- zlog_err("frrscript: loaded script '%s.lua' but %s not found",
+ zlog_err("frrscript: loaded script '%s' but %s not found",
script_name, function_name);
goto fail;
}
if (load_cb && (*load_cb)(fs) != 0) {
zlog_err(
- "frrscript: '%s.lua': %s: loaded but callback returned non-zero exit code",
+ "frrscript: '%s': %s: loaded but callback returned non-zero exit code",
script_name, function_name);
goto fail;
}
/* Add the Lua function state to frrscript */
struct lua_function_state key = {.name = function_name, .L = L};
- hash_get(fs->lua_function_hash, &key, lua_function_alloc);
+ (void)hash_get(fs->lua_function_hash, &key, lua_function_alloc);
return 0;
fail:
void frrscript_delete(struct frrscript *fs)
{
- hash_iterate(fs->lua_function_hash, lua_function_free, NULL);
+ hash_clean(fs->lua_function_hash, lua_function_free);
+ hash_free(fs->lua_function_hash);
XFREE(MTYPE_SCRIPT, fs->name);
XFREE(MTYPE_SCRIPT, fs);
}
frrscript_register_type_codecs(frrscript_codecs_lib);
}
+void frrscript_fini(void)
+{
+ hash_clean(codec_hash, codec_free);
+ hash_free(codec_hash);
+
+ frrscript_names_destroy();
+}
#endif /* HAVE_SCRIPTING */