summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in6
-rw-r--r--aclocal.m4480
-rw-r--r--configure.ac6
-rw-r--r--filter/filter.c9
-rw-r--r--filter/filter.h3
-rw-r--r--lua/Makefile4
-rw-r--r--lua/filter.c25
-rw-r--r--nest/config.Y10
8 files changed, 539 insertions, 4 deletions
diff --git a/Makefile.in b/Makefile.in
index 0ecd6811..b858e898 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -7,12 +7,12 @@ MAKEFLAGS += -r
# Variable definitions
CPPFLAGS=-I$(objdir) -I$(srcdir) @CPPFLAGS@
-CFLAGS=$(CPPFLAGS) @CFLAGS@
+CFLAGS=$(CPPFLAGS) @CFLAGS@ @LUA_INCLUDE@
LDFLAGS=@LDFLAGS@
M4FLAGS=@M4FLAGS@
BISONFLAGS=@BISONFLAGS@
LIBS=@LIBS@
-DAEMON_LIBS=@DAEMON_LIBS@
+DAEMON_LIBS=@DAEMON_LIBS@ @LUA_LIB@
CLIENT_LIBS=@CLIENT_LIBS@
CC=@CC@
M4=@M4@
@@ -74,7 +74,7 @@ cli: $(client)
$(daemon): LIBS += $(DAEMON_LIBS)
# Include directories
-dirs := client conf doc filter lib nest test $(addprefix proto/,$(protocols)) @sysdep_dirs@
+dirs := client conf doc filter lib lua nest test $(addprefix proto/,$(protocols)) @sysdep_dirs@
conf-y-targets := $(addprefix $(objdir)/conf/,cf-parse.y keywords.h commands.h)
cf-local = $(conf-y-targets): $(s)config.Y
diff --git a/aclocal.m4 b/aclocal.m4
index c401d447..7fc7f67e 100644
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -196,3 +196,483 @@ AC_DEFUN([BIRD_CHECK_BISON_VERSION],
;;
esac
])
+
+dnl =========================================================================
+dnl AX_PROG_LUA([MINIMUM-VERSION], [TOO-BIG-VERSION],
+dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl =========================================================================
+AC_DEFUN([AX_PROG_LUA],
+[
+ dnl Check for required tools.
+ AC_REQUIRE([AC_PROG_GREP])
+ AC_REQUIRE([AC_PROG_SED])
+
+ dnl Make LUA a precious variable.
+ AC_ARG_VAR([LUA], [The Lua interpreter, e.g. /usr/bin/lua5.1])
+
+ dnl Find a Lua interpreter.
+ m4_define_default([_AX_LUA_INTERPRETER_LIST],
+ [lua lua5.3 lua53 lua5.2 lua52 lua5.1 lua51 lua50])
+
+ m4_if([$1], [],
+ [ dnl No version check is needed. Find any Lua interpreter.
+ AS_IF([test "x$LUA" = 'x'],
+ [AC_PATH_PROGS([LUA], [_AX_LUA_INTERPRETER_LIST], [:])])
+ ax_display_LUA='lua'
+
+ AS_IF([test "x$LUA" != 'x:'],
+ [ dnl At least check if this is a Lua interpreter.
+ AC_MSG_CHECKING([if $LUA is a Lua interpreter])
+ _AX_LUA_CHK_IS_INTRP([$LUA],
+ [AC_MSG_RESULT([yes])],
+ [ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([not a Lua interpreter])
+ ])
+ ])
+ ],
+ [ dnl A version check is needed.
+ AS_IF([test "x$LUA" != 'x'],
+ [ dnl Check if this is a Lua interpreter.
+ AC_MSG_CHECKING([if $LUA is a Lua interpreter])
+ _AX_LUA_CHK_IS_INTRP([$LUA],
+ [AC_MSG_RESULT([yes])],
+ [ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([not a Lua interpreter])
+ ])
+ dnl Check the version.
+ m4_if([$2], [],
+ [_ax_check_text="whether $LUA version >= $1"],
+ [_ax_check_text="whether $LUA version >= $1, < $2"])
+ AC_MSG_CHECKING([$_ax_check_text])
+ _AX_LUA_CHK_VER([$LUA], [$1], [$2],
+ [AC_MSG_RESULT([yes])],
+ [ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([version is out of range for specified LUA])])
+ ax_display_LUA=$LUA
+ ],
+ [ dnl Try each interpreter until we find one that satisfies VERSION.
+ m4_if([$2], [],
+ [_ax_check_text="for a Lua interpreter with version >= $1"],
+ [_ax_check_text="for a Lua interpreter with version >= $1, < $2"])
+ AC_CACHE_CHECK([$_ax_check_text],
+ [ax_cv_pathless_LUA],
+ [ for ax_cv_pathless_LUA in _AX_LUA_INTERPRETER_LIST none; do
+ test "x$ax_cv_pathless_LUA" = 'xnone' && break
+ _AX_LUA_CHK_IS_INTRP([$ax_cv_pathless_LUA], [], [continue])
+ _AX_LUA_CHK_VER([$ax_cv_pathless_LUA], [$1], [$2], [break])
+ done
+ ])
+ dnl Set $LUA to the absolute path of $ax_cv_pathless_LUA.
+ AS_IF([test "x$ax_cv_pathless_LUA" = 'xnone'],
+ [LUA=':'],
+ [AC_PATH_PROG([LUA], [$ax_cv_pathless_LUA])])
+ ax_display_LUA=$ax_cv_pathless_LUA
+ ])
+ ])
+
+ AS_IF([test "x$LUA" = 'x:'],
+ [ dnl Run any user-specified action, or abort.
+ m4_default([$4], [AC_MSG_ERROR([cannot find suitable Lua interpreter])])
+ ],
+ [ dnl Query Lua for its version number.
+ AC_CACHE_CHECK([for $ax_display_LUA version],
+ [ax_cv_lua_version],
+ [ dnl Get the interpreter version in X.Y format. This should work for
+ dnl interpreters version 5.0 and beyond.
+ ax_cv_lua_version=[`$LUA -e '
+ -- return a version number in X.Y format
+ local _, _, ver = string.find(_VERSION, "^Lua (%d+%.%d+)")
+ print(ver)'`]
+ ])
+ AS_IF([test "x$ax_cv_lua_version" = 'x'],
+ [AC_MSG_ERROR([invalid Lua version number])])
+ AC_SUBST([LUA_VERSION], [$ax_cv_lua_version])
+ AC_SUBST([LUA_SHORT_VERSION], [`echo "$LUA_VERSION" | $SED 's|\.||'`])
+
+ dnl The following check is not supported:
+ dnl At times (like when building shared libraries) you may want to know
+ dnl which OS platform Lua thinks this is.
+ AC_CACHE_CHECK([for $ax_display_LUA platform],
+ [ax_cv_lua_platform],
+ [ax_cv_lua_platform=[`$LUA -e 'print("unknown")'`]])
+ AC_SUBST([LUA_PLATFORM], [$ax_cv_lua_platform])
+
+ dnl Use the values of $prefix and $exec_prefix for the corresponding
+ dnl values of LUA_PREFIX and LUA_EXEC_PREFIX. These are made distinct
+ dnl variables so they can be overridden if need be. However, the general
+ dnl consensus is that you shouldn't need this ability.
+ AC_SUBST([LUA_PREFIX], ['${prefix}'])
+ AC_SUBST([LUA_EXEC_PREFIX], ['${exec_prefix}'])
+
+ dnl Lua provides no way to query the script directory, and instead
+ dnl provides LUA_PATH. However, we should be able to make a safe educated
+ dnl guess. If the built-in search path contains a directory which is
+ dnl prefixed by $prefix, then we can store scripts there. The first
+ dnl matching path will be used.
+ AC_CACHE_CHECK([for $ax_display_LUA script directory],
+ [ax_cv_lua_luadir],
+ [ AS_IF([test "x$prefix" = 'xNONE'],
+ [ax_lua_prefix=$ac_default_prefix],
+ [ax_lua_prefix=$prefix])
+
+ dnl Initialize to the default path.
+ ax_cv_lua_luadir="$LUA_PREFIX/share/lua/$LUA_VERSION"
+
+ dnl Try to find a path with the prefix.
+ _AX_LUA_FND_PRFX_PTH([$LUA], [$ax_lua_prefix], [script])
+ AS_IF([test "x$ax_lua_prefixed_path" != 'x'],
+ [ dnl Fix the prefix.
+ _ax_strip_prefix=`echo "$ax_lua_prefix" | $SED 's|.|.|g'`
+ ax_cv_lua_luadir=`echo "$ax_lua_prefixed_path" | \
+ $SED "s|^$_ax_strip_prefix|$LUA_PREFIX|"`
+ ])
+ ])
+ AC_SUBST([luadir], [$ax_cv_lua_luadir])
+ AC_SUBST([pkgluadir], [\${luadir}/$PACKAGE])
+
+ dnl Lua provides no way to query the module directory, and instead
+ dnl provides LUA_PATH. However, we should be able to make a safe educated
+ dnl guess. If the built-in search path contains a directory which is
+ dnl prefixed by $exec_prefix, then we can store modules there. The first
+ dnl matching path will be used.
+ AC_CACHE_CHECK([for $ax_display_LUA module directory],
+ [ax_cv_lua_luaexecdir],
+ [ AS_IF([test "x$exec_prefix" = 'xNONE'],
+ [ax_lua_exec_prefix=$ax_lua_prefix],
+ [ax_lua_exec_prefix=$exec_prefix])
+
+ dnl Initialize to the default path.
+ ax_cv_lua_luaexecdir="$LUA_EXEC_PREFIX/lib/lua/$LUA_VERSION"
+
+ dnl Try to find a path with the prefix.
+ _AX_LUA_FND_PRFX_PTH([$LUA],
+ [$ax_lua_exec_prefix], [module])
+ AS_IF([test "x$ax_lua_prefixed_path" != 'x'],
+ [ dnl Fix the prefix.
+ _ax_strip_prefix=`echo "$ax_lua_exec_prefix" | $SED 's|.|.|g'`
+ ax_cv_lua_luaexecdir=`echo "$ax_lua_prefixed_path" | \
+ $SED "s|^$_ax_strip_prefix|$LUA_EXEC_PREFIX|"`
+ ])
+ ])
+ AC_SUBST([luaexecdir], [$ax_cv_lua_luaexecdir])
+ AC_SUBST([pkgluaexecdir], [\${luaexecdir}/$PACKAGE])
+
+ dnl Run any user specified action.
+ $3
+ ])
+])
+
+dnl AX_WITH_LUA is now the same thing as AX_PROG_LUA.
+AC_DEFUN([AX_WITH_LUA],
+[
+ AC_MSG_WARN([[$0 is deprecated, please use AX_PROG_LUA instead]])
+ AX_PROG_LUA
+])
+
+
+dnl =========================================================================
+dnl _AX_LUA_CHK_IS_INTRP(PROG, [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+dnl =========================================================================
+AC_DEFUN([_AX_LUA_CHK_IS_INTRP],
+[
+ dnl A minimal Lua factorial to prove this is an interpreter. This should work
+ dnl for Lua interpreters version 5.0 and beyond.
+ _ax_lua_factorial=[`$1 2>/dev/null -e '
+ -- a simple factorial
+ function fact (n)
+ if n == 0 then
+ return 1
+ else
+ return n * fact(n-1)
+ end
+ end
+ print("fact(5) is " .. fact(5))'`]
+ AS_IF([test "$_ax_lua_factorial" = 'fact(5) is 120'],
+ [$2], [$3])
+])
+
+
+dnl =========================================================================
+dnl _AX_LUA_CHK_VER(PROG, MINIMUM-VERSION, [TOO-BIG-VERSION],
+dnl [ACTION-IF-TRUE], [ACTION-IF-FALSE])
+dnl =========================================================================
+AC_DEFUN([_AX_LUA_CHK_VER],
+[
+ dnl Check that the Lua version is within the bounds. Only the major and minor
+ dnl version numbers are considered. This should work for Lua interpreters
+ dnl version 5.0 and beyond.
+ _ax_lua_good_version=[`$1 -e '
+ -- a script to compare versions
+ function verstr2num(verstr)
+ local _, _, majorver, minorver = string.find(verstr, "^(%d+)%.(%d+)")
+ if majorver and minorver then
+ return tonumber(majorver) * 100 + tonumber(minorver)
+ end
+ end
+ local minver = verstr2num("$2")
+ local _, _, trimver = string.find(_VERSION, "^Lua (.*)")
+ local ver = verstr2num(trimver)
+ local maxver = verstr2num("$3") or 1e9
+ if minver <= ver and ver < maxver then
+ print("yes")
+ else
+ print("no")
+ end'`]
+ AS_IF([test "x$_ax_lua_good_version" = "xyes"],
+ [$4], [$5])
+])
+
+
+dnl =========================================================================
+dnl _AX_LUA_FND_PRFX_PTH(PROG, PREFIX, SCRIPT-OR-MODULE-DIR)
+dnl =========================================================================
+AC_DEFUN([_AX_LUA_FND_PRFX_PTH],
+[
+ dnl Get the script or module directory by querying the Lua interpreter,
+ dnl filtering on the given prefix, and selecting the shallowest path. If no
+ dnl path is found matching the prefix, the result will be an empty string.
+ dnl The third argument determines the type of search, it can be 'script' or
+ dnl 'module'. Supplying 'script' will perform the search with package.path
+ dnl and LUA_PATH, and supplying 'module' will search with package.cpath and
+ dnl LUA_CPATH. This is done for compatibility with Lua 5.0.
+
+ ax_lua_prefixed_path=[`$1 -e '
+ -- get the path based on search type
+ local searchtype = "$3"
+ local paths = ""
+ if searchtype == "script" then
+ paths = (package and package.path) or LUA_PATH
+ elseif searchtype == "module" then
+ paths = (package and package.cpath) or LUA_CPATH
+ end
+ -- search for the prefix
+ local prefix = "'$2'"
+ local minpath = ""
+ local mindepth = 1e9
+ string.gsub(paths, "(@<:@^;@:>@+)",
+ function (path)
+ path = string.gsub(path, "%?.*$", "")
+ path = string.gsub(path, "/@<:@^/@:>@*$", "")
+ if string.find(path, prefix) then
+ local depth = string.len(string.gsub(path, "@<:@^/@:>@", ""))
+ if depth < mindepth then
+ minpath = path
+ mindepth = depth
+ end
+ end
+ end)
+ print(minpath)'`]
+])
+
+
+dnl =========================================================================
+dnl AX_LUA_HEADERS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl =========================================================================
+AC_DEFUN([AX_LUA_HEADERS],
+[
+ dnl Check for LUA_VERSION.
+ AC_MSG_CHECKING([if LUA_VERSION is defined])
+ AS_IF([test "x$LUA_VERSION" != 'x'],
+ [AC_MSG_RESULT([yes])],
+ [ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([cannot check Lua headers without knowing LUA_VERSION])
+ ])
+
+ dnl Make LUA_INCLUDE a precious variable.
+ AC_ARG_VAR([LUA_INCLUDE], [The Lua includes, e.g. -I/usr/include/lua5.1])
+
+ dnl Some default directories to search.
+ LUA_SHORT_VERSION=`echo "$LUA_VERSION" | $SED 's|\.||'`
+ m4_define_default([_AX_LUA_INCLUDE_LIST],
+ [ /usr/include/lua$LUA_VERSION \
+ /usr/include/lua-$LUA_VERSION \
+ /usr/include/lua/$LUA_VERSION \
+ /usr/include/lua$LUA_SHORT_VERSION \
+ /usr/local/include/lua$LUA_VERSION \
+ /usr/local/include/lua-$LUA_VERSION \
+ /usr/local/include/lua/$LUA_VERSION \
+ /usr/local/include/lua$LUA_SHORT_VERSION \
+ ])
+
+ dnl Try to find the headers.
+ _ax_lua_saved_cppflags=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
+ AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h])
+ CPPFLAGS=$_ax_lua_saved_cppflags
+
+ dnl Try some other directories if LUA_INCLUDE was not set.
+ AS_IF([test "x$LUA_INCLUDE" = 'x' &&
+ test "x$ac_cv_header_lua_h" != 'xyes'],
+ [ dnl Try some common include paths.
+ for _ax_include_path in _AX_LUA_INCLUDE_LIST; do
+ test ! -d "$_ax_include_path" && continue
+
+ AC_MSG_CHECKING([for Lua headers in])
+ AC_MSG_RESULT([$_ax_include_path])
+
+ AS_UNSET([ac_cv_header_lua_h])
+ AS_UNSET([ac_cv_header_lualib_h])
+ AS_UNSET([ac_cv_header_lauxlib_h])
+ AS_UNSET([ac_cv_header_luaconf_h])
+
+ _ax_lua_saved_cppflags=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS -I$_ax_include_path"
+ AC_CHECK_HEADERS([lua.h lualib.h lauxlib.h luaconf.h])
+ CPPFLAGS=$_ax_lua_saved_cppflags
+
+ AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
+ [ LUA_INCLUDE="-I$_ax_include_path"
+ break
+ ])
+ done
+ ])
+
+ AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
+ [ dnl Make a program to print LUA_VERSION defined in the header.
+ dnl TODO It would be really nice if we could do this without compiling a
+ dnl program, then it would work when cross compiling. But I'm not sure how
+ dnl to do this reliably. For now, assume versions match when cross compiling.
+
+ AS_IF([test "x$cross_compiling" != 'xyes'],
+ [ AC_CACHE_CHECK([for Lua header version],
+ [ax_cv_lua_header_version],
+ [ _ax_lua_saved_cppflags=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
+ AC_RUN_IFELSE(
+ [ AC_LANG_SOURCE([[
+#include <lua.h>
+#include <stdlib.h>
+#include <stdio.h>
+int main(int argc, char ** argv)
+{
+ if(argc > 1) printf("%s", LUA_VERSION);
+ exit(EXIT_SUCCESS);
+}
+]])
+ ],
+ [ ax_cv_lua_header_version=`./conftest$EXEEXT p | \
+ $SED -n "s|^Lua \(@<:@0-9@:>@\{1,\}\.@<:@0-9@:>@\{1,\}\).\{0,\}|\1|p"`
+ ],
+ [ax_cv_lua_header_version='unknown'])
+ CPPFLAGS=$_ax_lua_saved_cppflags
+ ])
+
+ dnl Compare this to the previously found LUA_VERSION.
+ AC_MSG_CHECKING([if Lua header version matches $LUA_VERSION])
+ AS_IF([test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"],
+ [ AC_MSG_RESULT([yes])
+ ax_header_version_match='yes'
+ ],
+ [ AC_MSG_RESULT([no])
+ ax_header_version_match='no'
+ ])
+ ],
+ [ AC_MSG_WARN([cross compiling so assuming header version number matches])
+ ax_header_version_match='yes'
+ ])
+ ])
+
+ dnl Was LUA_INCLUDE specified?
+ AS_IF([test "x$ax_header_version_match" != 'xyes' &&
+ test "x$LUA_INCLUDE" != 'x'],
+ [AC_MSG_ERROR([cannot find headers for specified LUA_INCLUDE])])
+
+ dnl Test the final result and run user code.
+ AS_IF([test "x$ax_header_version_match" = 'xyes'], [$1],
+ [m4_default([$2], [AC_MSG_ERROR([cannot find Lua includes])])])
+])
+
+dnl AX_LUA_HEADERS_VERSION no longer exists, use AX_LUA_HEADERS.
+AC_DEFUN([AX_LUA_HEADERS_VERSION],
+[
+ AC_MSG_WARN([[$0 is deprecated, please use AX_LUA_HEADERS instead]])
+])
+
+
+dnl =========================================================================
+dnl AX_LUA_LIBS([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl =========================================================================
+AC_DEFUN([AX_LUA_LIBS],
+[
+ dnl TODO Should this macro also check various -L flags?
+
+ dnl Check for LUA_VERSION.
+ AC_MSG_CHECKING([if LUA_VERSION is defined])
+ AS_IF([test "x$LUA_VERSION" != 'x'],
+ [AC_MSG_RESULT([yes])],
+ [ AC_MSG_RESULT([no])
+ AC_MSG_ERROR([cannot check Lua libs without knowing LUA_VERSION])
+ ])
+
+ dnl Make LUA_LIB a precious variable.
+ AC_ARG_VAR([LUA_LIB], [The Lua library, e.g. -llua5.1])
+
+ AS_IF([test "x$LUA_LIB" != 'x'],
+ [ dnl Check that LUA_LIBS works.
+ _ax_lua_saved_libs=$LIBS
+ LIBS="$LIBS $LUA_LIB"
+ AC_SEARCH_LIBS([lua_load], [],
+ [_ax_found_lua_libs='yes'],
+ [_ax_found_lua_libs='no'])
+ LIBS=$_ax_lua_saved_libs
+
+ dnl Check the result.
+ AS_IF([test "x$_ax_found_lua_libs" != 'xyes'],
+ [AC_MSG_ERROR([cannot find libs for specified LUA_LIB])])
+ ],
+ [ dnl First search for extra libs.
+ _ax_lua_extra_libs=''
+
+ _ax_lua_saved_libs=$LIBS
+ LIBS="$LIBS $LUA_LIB"
+ AC_SEARCH_LIBS([exp], [m])
+ AC_SEARCH_LIBS([dlopen], [dl])
+ LIBS=$_ax_lua_saved_libs
+
+ AS_IF([test "x$ac_cv_search_exp" != 'xno' &&
+ test "x$ac_cv_search_exp" != 'xnone required'],
+ [_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_exp"])
+
+ AS_IF([test "x$ac_cv_search_dlopen" != 'xno' &&
+ test "x$ac_cv_search_dlopen" != 'xnone required'],
+ [_ax_lua_extra_libs="$_ax_lua_extra_libs $ac_cv_search_dlopen"])
+
+ dnl Try to find the Lua libs.
+ _ax_lua_saved_libs=$LIBS
+ LIBS="$LIBS $LUA_LIB"
+ AC_SEARCH_LIBS([lua_load],
+ [ lua$LUA_VERSION \
+ lua$LUA_SHORT_VERSION \
+ lua-$LUA_VERSION \
+ lua-$LUA_SHORT_VERSION \
+ lua \
+ ],
+ [_ax_found_lua_libs='yes'],
+ [_ax_found_lua_libs='no'],
+ [$_ax_lua_extra_libs])
+ LIBS=$_ax_lua_saved_libs
+
+ AS_IF([test "x$ac_cv_search_lua_load" != 'xno' &&
+ test "x$ac_cv_search_lua_load" != 'xnone required'],
+ [LUA_LIB="$ac_cv_search_lua_load $_ax_lua_extra_libs"])
+ ])
+
+ dnl Test the result and run user code.
+ AS_IF([test "x$_ax_found_lua_libs" = 'xyes'], [$1],
+ [m4_default([$2], [AC_MSG_ERROR([cannot find Lua libs])])])
+])
+
+
+dnl =========================================================================
+dnl AX_LUA_READLINE([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+dnl =========================================================================
+AC_DEFUN([AX_LUA_READLINE],
+[
+ AX_LIB_READLINE
+ AS_IF([test "x$ac_cv_header_readline_readline_h" != 'x' &&
+ test "x$ac_cv_header_readline_history_h" != 'x'],
+ [ LUA_LIBS_CFLAGS="-DLUA_USE_READLINE $LUA_LIBS_CFLAGS"
+ $1
+ ],
+ [$2])
+])
diff --git a/configure.ac b/configure.ac
index da1a8f44..7d538bdd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -340,6 +340,12 @@ elif test "$bird_cv_lib_log" != yes ; then
LIBS="$LIBS $bird_cv_lib_log"
fi
+AX_PROG_LUA(5.3)
+AX_LUA_HEADERS
+AX_LUA_LIBS
+AC_SUBST(LUA_INCLUDE)
+AC_SUBST(LUA_LIBS)
+
if test "$enable_debug" = yes ; then
AC_DEFINE([DEBUGGING], [1], [Define to 1 if debugging is enabled])
LDFLAGS="$LDFLAGS -rdynamic"
diff --git a/filter/filter.c b/filter/filter.c
index 37cf16a3..7f3979f3 100644
--- a/filter/filter.c
+++ b/filter/filter.c
@@ -1575,6 +1575,15 @@ interpret(struct f_inst *what)
CALL(bt_assert_hook, res.val.i, what);
break;
+ case P('L','C'): /* Lua include */
+ ONEARG;
+ if (v1.type != T_STRING)
+ runtime("Lua code should be a string argument");
+
+ res.type = T_RETURN;
+ res.val.i = filter_lua_chunk(v1.val.s, f_rte, f_old_rta, f_tmp_attrs, f_pool);
+ break;
+
default:
bug( "Unknown instruction %d (%c)", what->fi_code, what->fi_code & 0xff);
}}
diff --git a/filter/filter.h b/filter/filter.h
index a8c33287..a4eb2913 100644
--- a/filter/filter.h
+++ b/filter/filter.h
@@ -307,4 +307,7 @@ struct f_bt_test_suite {
/* Hook for call bt_assert() function in configuration */
extern void (*bt_assert_hook)(int result, struct f_inst *assert);
+/* Lua */
+int filter_lua_chunk(const char *chunk, struct rte **e, struct rta *a, struct ea_list **ea, struct linpool *lp);
+
#endif
diff --git a/lua/Makefile b/lua/Makefile
new file mode 100644
index 00000000..493b9475
--- /dev/null
+++ b/lua/Makefile
@@ -0,0 +1,4 @@
+src := filter.c
+obj := $(src-o-files)
+$(all-daemon)
+#$(cf-local)
diff --git a/lua/filter.c b/lua/filter.c
new file mode 100644
index 00000000..c40a5207
--- /dev/null
+++ b/lua/filter.c
@@ -0,0 +1,25 @@
+#include "nest/bird.h"
+#include "filter/filter.h"
+
+#include <lua.h>
+#include <lualib.h>
+#include <lauxlib.h>
+
+int filter_lua_chunk(const char *chunk, struct rte **e, struct rta *a, struct ea_list **ea, struct linpool *lp) {
+ lua_State *L = luaL_newstate();
+ luaL_openlibs(L);
+ int le = luaL_dostring(L, chunk);
+ int out;
+ if (le) {
+ log(L_WARN "bad lua: %s", lua_tostring(L, -1));
+ out = F_ERROR;
+ } else if (lua_isnumber(L, -1)) {
+ out = lua_tonumber(L, -1);
+ } else {
+ log(L_WARN "lua return value is not a number: %s", lua_tostring(L, -1));
+ out = F_ERROR;
+ }
+
+ lua_close(L);
+ return out;
+}
diff --git a/nest/config.Y b/nest/config.Y
index aef5ed46..f87ed2df 100644
--- a/nest/config.Y
+++ b/nest/config.Y
@@ -65,7 +65,7 @@ proto_postconfig(void)
CF_DECLS
CF_KEYWORDS(ROUTER, ID, PROTOCOL, TEMPLATE, PREFERENCE, DISABLED, DEBUG, ALL, OFF, DIRECT)
-CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, NONE, VRF, TABLE, STATES, ROUTES, FILTERS)
+CF_KEYWORDS(INTERFACE, IMPORT, EXPORT, FILTER, LUA, NONE, VRF, TABLE, STATES, ROUTES, FILTERS)
CF_KEYWORDS(IPV4, IPV6, VPN4, VPN6, ROA4, ROA6, FLOW4, FLOW6, SADR, MPLS)
CF_KEYWORDS(RECEIVE, LIMIT, ACTION, WARN, BLOCK, RESTART, DISABLE, KEEP, FILTERED)
CF_KEYWORDS(PASSWORD, FROM, PASSIVE, TO, ID, EVENTS, PACKETS, PROTOCOLS, INTERFACES)
@@ -263,6 +263,14 @@ rtable:
imexport:
FILTER filter { $$ = $2; }
+ | LUA constant {
+ $$ = cfg_alloc(sizeof(struct filter));
+ $$->name = NULL;
+ $$->root = f_new_inst();
+ $$->root->code = P('L','C');
+ $$->root->a1.p = $2;
+ $$->root->next = NULL;
+ }
| where_filter
| ALL { $$ = FILTER_ACCEPT; }
| NONE { $$ = FILTER_REJECT; }