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 Jul 29, 2024
1 parent 9dd084c commit c214bad
Show file tree
Hide file tree
Showing 5 changed files with 305 additions and 0 deletions.
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,19 @@ 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
The `xtable` [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 run `lua luaxtable.lua <ext_name> <ext_revision> <protocol_name>` to generate the userspace library for the xtable extension.
2. Modify the generate `libxt_<ext_name>.lua` callback placeholders.
3. Make sure to align the protocol, revision, name, family, size, userspace size and family of the userspace extension with the kernel extension. To make changes to these properties, modify `libxt_<ext_name>.c`.
4. Run `make` to build the extension and `make install` (as root) to install the userspace plugin to the system.
Now load the extension normally using `iptables`.
# Examples
### spyglass
Expand Down
21 changes: 21 additions & 0 deletions usr/lib/xtable/Makefile.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
CFLAGS = -O2 -Wall -I../../../lib
XTABLES_SO_DIR = $(shell pkg-config xtables --variable xtlibdir)
LUA_FLAGS = -llua -lm

all:
make libxt_<EXT_NAME>.so;

install:
sudo cp libxt_<EXT_NAME>.so ${XTABLES_SO_DIR}

uninstall:
sudo rm -f ${XTABLES_SO_DIR}/libxt_<EXT_NAME>.so

clean:
rm -f libxt_<EXT_NAME>.so libxt_<EXT_NAME>.o

lib%.so: lib%.o
gcc -shared -fPIC -o $@ $^ ${LUA_FLAGS};

lib%.o: lib%.c
gcc ${CFLAGS} ${LUA_FLAGS} -D_INIT=lib$*_init -fPIC -c -o $@ $<;
169 changes: 169 additions & 0 deletions usr/lib/xtable/luaxtable.c.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
#include "luaxtable.h"

#include <lauxlib.h>
#include <lua.h>
#include <lualib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <xtables.h>

static lua_State *L = NULL;

// Function to initialize Lua state
static int init_lua(void)
{
L = luaL_newstate();
if (L == NULL) {
fprintf(stderr, "Failed to create Lua state\n");
return 0;
}
luaL_openlibs(L);
return 1;
}

// Function to load Lua script
static int load_lua_script(const char *filename)
{
if (luaL_dofile(L, filename) != LUA_OK) {
fprintf(stderr, "Failed to load Lua script: %s\n", lua_tostring(L, -1));
return 0;
}
return 1;
}

// Helper function to call Lua functions
static int call_lua_function(const char *func_name, int nargs, int nresults)
{
int base = lua_gettop(L) - nargs;
if (lua_getglobal(L, func_name) != LUA_TFUNCTION) {
fprintf(stderr, "Failed to find Lua function %s\n", func_name);
return 0;
}
lua_insert(L, base + 1); /* func */
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));
return 0;
}
return 1;
}

static void <EXT_NAME>_mt_help(void)
{
call_lua_function("<EXT_NAME>_mt_help", 0, 0);
}

static void <EXT_NAME>_mt_init(struct xt_entry_match *match)
{
call_lua_function("<EXT_NAME>_mt_init", 0, 0);
}

static int <EXT_NAME>_mt_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
call_lua_function("<EXT_NAME>_mt_parse", 0, 1);
return lua_toboolean(L, -1);
}

static void <EXT_NAME>_mt_check(unsigned int flags)
{
call_lua_function("<EXT_NAME>_mt_check", 0, 0);
}

static void <EXT_NAME>_mt_print(const void *entry, const struct xt_entry_match *match,
int numeric)
{
call_lua_function("<EXT_NAME>_mt_print", 0, 0);
}

static void <EXT_NAME>_mt_save(const void *entry, const struct xt_entry_match *match)
{
call_lua_function("<EXT_NAME>_mt_save", 0, 0);
}

static void <EXT_NAME>_tg_help(void)
{
call_lua_function("<EXT_NAME>_tg_help", 0, 0);
}

static void <EXT_NAME>_tg_init(struct xt_entry_target *target)
{
call_lua_function("<EXT_NAME>_tg_init", 0, 0);
}

static int <EXT_NAME>_tg_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_target **target)
{
call_lua_function("<EXT_NAME>_tg_parse", 0, 1);
return lua_toboolean(L, -1);
}

static void <EXT_NAME>_tg_check(unsigned int flags)
{
call_lua_function("<EXT_NAME>_tg_check", 0, 0);
}

static void <EXT_NAME>_tg_print(const void *entry, const struct xt_entry_target *target,
int numeric)
{
call_lua_function("<EXT_NAME>_tg_print", 0, 0);
}

static void <EXT_NAME>_tg_save(const void *entry, const struct xt_entry_target *target)
{
call_lua_function("<EXT_NAME>_tg_save", 0, 0);
}

static struct xtables_match <EXT_NAME>_mt_reg = {
.version = XTABLES_VERSION,
.name = "dnsblock",
.revision = 1,
.family = NFPROTO_UNSPEC,
.size = XT_ALIGN(sizeof(luaxtable_info_t)),
.userspacesize = 0,
.help = <EXT_NAME>_mt_help,
.init = <EXT_NAME>_mt_init,
.parse = <EXT_NAME>_mt_parse,
.final_check = <EXT_NAME>_mt_check,
.print = <EXT_NAME>_mt_print,
.save = <EXT_NAME>_mt_save,
};

static struct xtables_target <EXT_NAME>_tg_reg = {
.version = XTABLES_VERSION,
.size = XT_ALIGN(sizeof(luaxtable_info_t)),
.userspacesize = 0,
.name = "<EXT_NAME>",
.revision = <EXT_REV>,
.family = <EXT_FAMILY>,
.help = <EXT_NAME>_tg_help,
.init = <EXT_NAME>_tg_init,
.parse = <EXT_NAME>_tg_parse,
.final_check = <EXT_NAME>_tg_check,
.print = <EXT_NAME>_tg_print,
.save = <EXT_NAME>_tg_save,
};

static void __attribute__((constructor)) _init(void)
{
if (!init_lua()) {
fprintf(stderr, "Failed to initialize Lua\n");
return;
}

if (!load_lua_script("libxt_<EXT_NAME>.lua")) {
lua_close(L);
return;
}

xtables_register_match(&<EXT_NAME>_mt_reg);
xtables_register_target(&<EXT_NAME>_tg_reg);
}

static void __attribute__((destructor)) _fini(void)
{
if (L) {
lua_close(L);
}
}
65 changes: 65 additions & 0 deletions usr/lib/xtable/luaxtable.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
--
-- SPDX-FileCopyrightText: (c) 2024 Mohammad Shehar Yaar Tausif <[email protected]>
-- SPDX-License-Identifier: MIT OR GPL-2.0-only
--

local proto = {
["UNSPEC"] = "NFPROTO_UNSPEC",
["INET"] = "NFPROTO_INET",
["IPV4"] = "NFPROTO_IPV4",
["IPV6"] = "NFPROTO_IPV6",
["ARP"] = "NFPROTO_ARP",
["NETDEV"] = "NFPROTO_NETDEV",
["BRIDGE"] = "NFPROTO_BRIDGE",
}

local function write_file(filename, content)
local file = io.open(filename, "w")
if file == nil then
print("Failed to open file: "..filename)
return
end

file:write(content)
file:close()
end

local function read_file(filename)
local file = io.open(filename, "r")
if file == nil then
print("Failed to open file: "..filename)
return nil
end

local content = file:read("*a")
file:close()
return content
end

local function generate_module(ext_name, ext_rev, ext_family)
local luafile_tmpl = read_file("luaxtable.lua.tmpl") or ""
local makefile_tmpl = read_file("Makefile.tmpl") or ""
local cfile_tmpl = read_file("luaxtable.c.tmpl") or ""

local luafile = luafile_tmpl:gsub("<EXT_NAME>", ext_name)
local makefile = makefile_tmpl:gsub("<EXT_NAME>", ext_name)
local cfile = cfile_tmpl:gsub("<EXT_NAME>", ext_name)
cfile = cfile:gsub("<EXT_REV>", ext_rev or 1)
cfile = cfile:gsub("<EXT_FAMILY>", ext_family or "NFPROTO_UNSPEC")

write_file("libxt_"..ext_name..".c", cfile)
write_file("libxt_"..ext_name..".lua", luafile)
write_file("Makefile", makefile)
end

if #arg < 3 then
print("Usage: lua "..arg[0].." <module_name> <module_revision> <proto_family>")
return
end

if proto[arg[3]] == nil then
print("Invalid protocol family: "..arg[3])
return
end

generate_module(arg[1], arg[2], proto[arg[3]])
37 changes: 37 additions & 0 deletions usr/lib/xtable/luaxtable.lua.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
function <EXT_NAME>_mt_help()
end

function <EXT_NAME>_mt_init()
end

function <EXT_NAME>_mt_parse()
return true
end

function <EXT_NAME>_mt_check()
end

function <EXT_NAME>_mt_print()
end

function <EXT_NAME>_mt_save()
end

function <EXT_NAME>_tg_help()
end

function <EXT_NAME>_tg_init()
end

function <EXT_NAME>_tg_parse()
return true
end

function <EXT_NAME>_tg_check()
end

function <EXT_NAME>_tg_print()
end

function <EXT_NAME>_tg_save()
end

0 comments on commit c214bad

Please sign in to comment.