Skip to content

Commit

Permalink
add userspace library skeleton
Browse files Browse the repository at this point in the history
Signed-off-by: Mohammad Shehar Yaar Tausif <[email protected]>
  • Loading branch information
sheharyaar committed Aug 1, 2024
1 parent 9dd084c commit 38965fc
Show file tree
Hide file tree
Showing 3 changed files with 222 additions and 0 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,18 @@ netfilter hooks to Lua.
* `"LOCAL_OUT"`: `NF_INET_LOCAL_OUT`. The packet is generated by the local system.
* `"POST_ROUTING"`: `NF_INET_POST_ROUTING`. The packet is about to be sent out.
### xtable userspace library (libxtable)
The `libxtable` [userspace library](usr/lib/xtable) provides support for generating userspace code for [xtable extensions](https://inai.de/projects/xtables-addons/). The user can modify the generated lua code to implement the userspace handlers for the corresponding xtable extension.
To generate the library, the following steps are required:
1. Go to `usr/lib/xtable` and create a `libxt_<ext_name>.lua` file.
2. Register your callbacks for the xtable extension by importing the library (`libxtable`) in the created file.
3. Run `LUAXTABLE_MODULE=<ext_name> make` to build the extension and `LUAXTABLE_MODULE=<ext_name> make install` (as root) to install the userspace plugin to the system.
Now load the extension normally using `iptables`.
# Examples
### spyglass
Expand Down
27 changes: 27 additions & 0 deletions usr/lib/xtable/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# SPDX-FileCopyrightText: (c) 2024 Mohammad Shehar Yaar Tausif <[email protected]>
# SPDX-License-Identifier: MIT OR GPL-2.0-only

LUAXTABLE_MODULE ?= test

CFLAGS = -DLUAXTABLE_MODULE=\"${LUAXTABLE_MODULE}\" -O2 -Wall -I../../../lib
XTABLES_SO_DIR = $(shell pkg-config xtables --variable xtlibdir)
LUA_FLAGS = -llua -lm

all:
make libxt_${LUAXTABLE_MODULE}.so

install:
sudo cp libxt_${LUAXTABLE_MODULE}.so ${XTABLES_SO_DIR}

uninstall:
sudo rm -f ${XTABLES_SO_DIR}/libxt_${LUAXTABLE_MODULE}.so

clean:
rm -f libxt_*.so libxt_*.o

lib%.so: lib%.o
gcc -shared -fPIC -o libxt_${LUAXTABLE_MODULE}.so libxt_${LUAXTABLE_MODULE}.o ${LUA_FLAGS};

lib%.o: libxtable.c
gcc ${CFLAGS} ${LUA_FLAGS} -D_INIT=lib$*_init -fPIC -c -o libxt_${LUAXTABLE_MODULE}.o $<;

183 changes: 183 additions & 0 deletions usr/lib/xtable/libxtable.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
/*
* SPDX-FileCopyrightText: (c) 2024 Mohammad Shehar Yaar Tausif <[email protected]>
* SPDX-License-Identifier: MIT OR GPL-2.0-only
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>

#include <xtables.h>

#include "luaxtable.h"

#ifndef LUAXTABLE_MODULE
#error "LUAXTABLE_MODULE is not defined"
#endif

static lua_State *L = NULL;
const char *libxtable_match_key = "libxtable_match";
const char *libxtable_target_key = "libxtable_target";

int luaopen_libxtable(lua_State *L);

static inline int libxtable_run(lua_State *L, const char *func_name, const char *key, int nargs, int nresults)
{
int ret = 0;
int base = lua_gettop(L) - nargs;
lua_rawgetp(L, LUA_REGISTRYINDEX, key);

if (lua_getfield(L, -1, func_name) != LUA_TFUNCTION) {
fprintf(stderr, "Function %s not found\n", func_name);
goto restore;
}

lua_insert(L, base + 1); /* func */
lua_pop(L, 1); /* table */

if (lua_pcall(L, nargs, nresults, 0) != LUA_OK) {
fprintf(stderr, "Failed to call Lua function %s: %s\n", func_name,
lua_tostring(L, -1));
goto restore;
}

if (nresults == 1)
ret = lua_toboolean(L, -1);

restore:
lua_settop(L, base);
return ret;
}

// stubs for xtables functions
#define LIBXTABLE_HELPER_CB(hook) \
static void libxtable_##hook##_help(void) \
{ \
libxtable_run(L, "help", libxtable_##hook##_key, 0, 0); \
}

#define LIBXTABLE_INITER_CB(hook) \
static void libxtable_##hook##_init(struct xt_entry_##hook *hook) \
{ \
libxtable_run(L, "init", libxtable_##hook##_key, 1, 0); \
}

#define LIBXTABLE_PARSER_CB(hook) \
static int libxtable_##hook##_parse(int c, char **argv, int invert, unsigned int *flags, \
const void *entry, struct xt_entry_##hook **hook) \
{ \
return libxtable_run(L, "parse", libxtable_##hook##_key, 0, 1); \
}

#define LIBXTABLE__FINALCHECKER_CB(hook) \
static void libxtable_##hook##_finalcheck(unsigned int flags) \
{ \
libxtable_run(L, "final_check", libxtable_##hook##_key, 0, 0); \
}

#define LIBXTABLE_PRINTER_CB(hook) \
static void libxtable_##hook##_print(const void *entry, const struct xt_entry_##hook *hook, int numeric) \
{ \
libxtable_run(L, "print", libxtable_##hook##_key, 0, 0); \
}

#define LIBXTABLE_SAVER_CB(hook) \
static void libxtable_##hook##_save(const void *entry, const struct xt_entry_##hook *hook) \
{ \
libxtable_run(L, "save", libxtable_##hook##_key, 0, 0); \
}

#define LIBXTABLE_NEWCB(hook) \
LIBXTABLE_HELPER_CB(hook) \
LIBXTABLE_INITER_CB(hook) \
LIBXTABLE_PARSER_CB(hook) \
LIBXTABLE__FINALCHECKER_CB(hook) \
LIBXTABLE_PRINTER_CB(hook) \
LIBXTABLE_SAVER_CB(hook)

LIBXTABLE_NEWCB(match);
LIBXTABLE_NEWCB(target);


#define LIBXTABLE_NEWREG(hook) \
static struct xtables_##hook libxtable_##hook##_reg = { \
.version = XTABLES_VERSION, \
.name = LUAXTABLE_MODULE, \
.size = XT_ALIGN(sizeof(luaxtable_info_t)), \
.userspacesize = 0, \
.help = libxtable_##hook##_help, \
.init = libxtable_##hook##_init, \
.parse = libxtable_##hook##_parse, \
.final_check = libxtable_##hook##_finalcheck, \
.print = libxtable_##hook##_print, \
.save = libxtable_##hook##_save \
}

LIBXTABLE_NEWREG(match);
LIBXTABLE_NEWREG(target);

static inline int libxtable_checkint(lua_State *L, int idx, const char *key)
{
if (lua_getfield(L, idx, key) != LUA_TNUMBER) {
fprintf(stderr, "invalid \'%s\' in match\n", key);
return 0;
}
int ret = lua_tointeger(L, -1);
lua_pop(L, 1);
return ret;
}

#define LIBXTABLE_LIB_CB(hook) \
static int libxtable_##hook##_lib(lua_State *L) \
{ \
luaL_checktype(L, 1, LUA_TTABLE); \
\
libxtable_##hook##_reg.revision = libxtable_checkint(L, 1, "revision"); \
libxtable_##hook##_reg.family = libxtable_checkint(L, 1, "family"); \
xtables_register_##hook(&libxtable_##hook##_reg); \
lua_pushvalue(L, 1); \
lua_rawsetp(L, LUA_REGISTRYINDEX, libxtable_##hook##_key); \
return 0; \
}

LIBXTABLE_LIB_CB(match);
LIBXTABLE_LIB_CB(target);

static const luaL_Reg libxtable_lib[] = {
{"match", libxtable_match_lib},
{"target", libxtable_target_lib},
{NULL, NULL}
};

int luaopen_libxtable(lua_State *L)
{
luaL_newlib(L, libxtable_lib);
return 1;
}

static int __attribute__((constructor)) _init(void)
{
if ((L = luaL_newstate()) == NULL) {
fprintf(stderr, "Failed to create Lua state\n");
return -1;
}
luaL_openlibs(L);
luaL_requiref(L, "libxtable", luaopen_libxtable, 1);

if (luaL_dofile(L, "libxt_"LUAXTABLE_MODULE".lua") != LUA_OK) {
fprintf(stderr, "Failed to load Lua script: %s\n", lua_tostring(L, -1));
return -1;
}

return 0;
}

static void __attribute__((destructor)) _fini(void)
{
if (L)
lua_close(L);
}

0 comments on commit 38965fc

Please sign in to comment.