diff --git a/lunatik-3.6.2/.editorconfig b/lunatik-3.6.2/.editorconfig new file mode 100644 index 0000000..4d6f5ef --- /dev/null +++ b/lunatik-3.6.2/.editorconfig @@ -0,0 +1,7 @@ +root = true + +[*] +indent_style = tab +indent_size = tab +trim_trailing_whitespace = true +insert_final_newline = true diff --git a/lunatik-3.6.2/.github/workflows/doc.yml b/lunatik-3.6.2/.github/workflows/doc.yml new file mode 100644 index 0000000..a92dad5 --- /dev/null +++ b/lunatik-3.6.2/.github/workflows/doc.yml @@ -0,0 +1,33 @@ +# Based on https://gist.github.com/domenic/ec8b0fc8ab45f39403dd +name: Build Docs +on: + pull_request: + branches: + - master + push: + branches: + - master +jobs: + build: + name: Build docs + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup Lua + uses: leafo/gh-actions-lua@v8 + with: + luaVersion: 5.4 + - name: Setup Lua Rocks + uses: leafo/gh-actions-luarocks@v4 + - name: Setup dependencies + run: luarocks install ldoc + - name: Build docs + run: make doc-site + - name: Deploy + if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} + uses: peaceiris/actions-gh-pages@v3 + with: + github_token: ${{ secrets.GITHUB_TOKEN }} + publish_dir: doc + diff --git a/lunatik-3.6.2/.pc/.quilt_patches b/lunatik-3.6.2/.pc/.quilt_patches new file mode 100644 index 0000000..6857a8d --- /dev/null +++ b/lunatik-3.6.2/.pc/.quilt_patches @@ -0,0 +1 @@ +debian/patches diff --git a/lunatik-3.6.2/.pc/.quilt_series b/lunatik-3.6.2/.pc/.quilt_series new file mode 100644 index 0000000..c206706 --- /dev/null +++ b/lunatik-3.6.2/.pc/.quilt_series @@ -0,0 +1 @@ +series diff --git a/lunatik-3.6.2/.pc/.version b/lunatik-3.6.2/.pc/.version new file mode 100644 index 0000000..0cfbf08 --- /dev/null +++ b/lunatik-3.6.2/.pc/.version @@ -0,0 +1 @@ +2 diff --git a/lunatik-3.6.2/.pc/applied-patches b/lunatik-3.6.2/.pc/applied-patches new file mode 100644 index 0000000..1511aa0 --- /dev/null +++ b/lunatik-3.6.2/.pc/applied-patches @@ -0,0 +1 @@ +fix-namespaced-symbols.patch diff --git a/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/.timestamp b/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/.timestamp new file mode 100644 index 0000000..e69de29 diff --git a/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luadata.c b/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luadata.c new file mode 100644 index 0000000..3ffa437 --- /dev/null +++ b/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luadata.c @@ -0,0 +1,419 @@ +/* +* SPDX-FileCopyrightText: (c) 2023-2024 Ring Zero Desenvolvimento de Software LTDA +* SPDX-License-Identifier: MIT OR GPL-2.0-only +*/ + +/*** +* Direct memory access and manipulation. +* This library allows creating `data` objects that represent blocks of memory. +* These objects can then be used to read and write various integer types +* (signed/unsigned, 8/16/32/64-bit) and raw byte strings at specific offsets. +* +* @module data +*/ + +/*** +* Represents a raw block of memory. +* This is a userdata object returned by `data.new()` or created internally +* by other Lunatik modules (e.g., for network packet buffers). +* @type data +*/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include + +#include +#include +#include + +#include + +#include "luadata.h" + +typedef struct luadata_s { + char *ptr; + size_t size; + uint8_t opt; +} luadata_t; + +#define LUADATA_NUMBER_SZ (sizeof(lua_Integer)) + +static int luadata_lnew(lua_State *L); + +LUNATIK_PRIVATECHECKER(luadata_check, luadata_t *); + +static inline void luadata_checkbounds(lua_State *L, int ix, size_t size, lua_Integer offset, lua_Integer length) +{ + int bounds = offset >= 0 && length > 0 && offset + length <= size; + luaL_argcheck(L, bounds, ix, "out of bounds"); +} + +#define luadata_checkwritable(L, data) luaL_argcheck((L), !((data)->opt & LUADATA_OPT_READONLY), 1, "read only") + +/*** +* Extracts a signed 8-bit integer from the data object. +* @function getint8 +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @treturn integer The signed 8-bit integer value at the specified offset. +* @raise Error if offset is out of bounds. +*/ +/*** +* Inserts a signed 8-bit integer into the data object. +* @function setint8 +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @tparam integer value The signed 8-bit integer value to write. +* @raise Error if offset is out of bounds or the data object is read-only. +*/ +#define LUADATA_NEWINT_GETTER(T) \ +static int luadata_get##T(lua_State *L) \ +{ \ + luadata_t *data = luadata_check(L, 1); \ + lua_Integer offset = luaL_checkinteger(L, 2); \ + luadata_checkbounds(L, 2, data->size, offset, sizeof(T##_t)); \ + lua_pushinteger(L, (lua_Integer)*(T##_t *)(data->ptr + offset)); \ + return 1; \ +} + +#define LUADATA_NEWINT_SETTER(T) \ +static int luadata_set##T(lua_State *L) \ +{ \ + luadata_t *data = luadata_check(L, 1); \ + lua_Integer offset = luaL_checkinteger(L, 2); \ + luadata_checkbounds(L, 2, data->size, offset, sizeof(T##_t)); \ + luadata_checkwritable(L, data); \ + *(T##_t *)(data->ptr + offset) = (T##_t)luaL_checkinteger(L, 3); \ + return 0; \ +} + +#define LUADATA_NEWINT(T) \ + LUADATA_NEWINT_GETTER(T); \ + LUADATA_NEWINT_SETTER(T); + +/*** +* Extracts an unsigned 8-bit integer from the data object. +* @function getuint8 +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @treturn integer The unsigned 8-bit integer value (0-255) at the specified offset. +* @raise Error if offset is out of bounds. +*/ +/*** +* Inserts an unsigned 8-bit integer into the data object. +* @function setuint8 +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @tparam integer value The unsigned 8-bit integer value (0-255) to write. +* @raise Error if offset is out of bounds or the data object is read-only. +*/ +LUADATA_NEWINT(int8); +LUADATA_NEWINT(uint8); +/*** +* Extracts a signed 16-bit integer from the data object. +* Assumes host byte order. For specific byte orders, use `linux.be16toh` etc. on the result. +* @function getint16 +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @treturn integer The signed 16-bit integer value at the specified offset. +* @raise Error if offset is out of bounds. +*/ +/*** +* Inserts a signed 16-bit integer into the data object. +* Assumes host byte order. For specific byte orders, use `linux.htobe16` etc. on the value before setting. +* @function setint16 +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @tparam integer value The signed 16-bit integer value to write. +* @raise Error if offset is out of bounds or the data object is read-only. +*/ +LUADATA_NEWINT(int16); +/*** +* Extracts an unsigned 16-bit integer from the data object. +* Assumes host byte order. +* @function getuint16 +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @treturn integer The unsigned 16-bit integer value at the specified offset. +* @raise Error if offset is out of bounds. +*/ +/*** +* Inserts an unsigned 16-bit integer into the data object. +* Assumes host byte order. +* @function setuint16 +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @tparam integer value The unsigned 16-bit integer value to write. +* @raise Error if offset is out of bounds or the data object is read-only. +*/ +LUADATA_NEWINT(uint16); +/*** +* Extracts a signed 32-bit integer from the data object. +* Assumes host byte order. +* @function getint32 +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @treturn integer The signed 32-bit integer value at the specified offset. +* @raise Error if offset is out of bounds. +*/ +/*** +* Inserts a signed 32-bit integer into the data object. +* Assumes host byte order. +* @function setint32 +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @tparam integer value The signed 32-bit integer value to write. +* @raise Error if offset is out of bounds or the data object is read-only. +*/ +LUADATA_NEWINT(int32); +/*** +* Extracts an unsigned 32-bit integer from the data object. +* Assumes host byte order. +* @function getuint32 +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @treturn integer The unsigned 32-bit integer value at the specified offset. +* @raise Error if offset is out of bounds. +*/ +/*** +* Inserts an unsigned 32-bit integer into the data object. +* Assumes host byte order. +* @function setuint32 +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @tparam integer value The unsigned 32-bit integer value to write. +* @raise Error if offset is out of bounds or the data object is read-only. +*/ +LUADATA_NEWINT(uint32); + +#ifdef __LP64__ +/*** +* Extracts a signed 64-bit integer from the data object. +* Assumes host byte order. +* @function getint64 +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @treturn integer The signed 64-bit integer value at the specified offset. +* @raise Error if offset is out of bounds. +*/ +/*** +* Inserts a signed 64-bit integer into the data object. +* Assumes host byte order. +* @function setint64 +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @tparam integer value The signed 64-bit integer value to write. +* @raise Error if offset is out of bounds or the data object is read-only. +*/ +LUADATA_NEWINT(int64); +#endif + +/*** +* Extracts a string from the data object. +* @function getstring +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @tparam[opt] integer length Number of bytes to read. If omitted, reads all bytes from `offset` to the end of the data block. +* @treturn string The string containing the bytes read from the data object. +* @raise Error if offset/length is out of bounds. +*/ +static int luadata_getstring(lua_State *L) +{ + luadata_t *data = luadata_check(L, 1); + lua_Integer offset = luaL_checkinteger(L, 2); + lua_Integer length = luaL_optinteger(L, 3, data->size - offset); + luadata_checkbounds(L, 2, data->size, offset, length); + + lua_pushlstring(L, data->ptr + offset, length); + return 1; +} + +/*** +* Inserts a string into the data object. +* @function setstring +* @tparam integer offset Byte offset from the start of the data block (0-indexed) where writing will begin. +* @tparam string s The string to write into the data object. +* @raise Error if the write operation (offset + length of string) goes out of bounds, or if the data object is read-only. +*/ +static int luadata_setstring(lua_State *L) +{ + size_t length; + luadata_t *data = luadata_check(L, 1); + lua_Integer offset = luaL_checkinteger(L, 2); + const char *str = luaL_checklstring(L, 3, &length); + luadata_checkbounds(L, 2, data->size, offset, length); + luadata_checkwritable(L, data); + + memcpy(data->ptr + offset, str, length); + return 0; +} + +/*** +* Returns the length of the data object in bytes. +* This is the Lua `__len` metamethod, allowing use of the `#` operator. +* @function __len +* @treturn integer The total size of the memory block in bytes. +*/ +static int luadata_length(lua_State *L) +{ + luadata_t *data = luadata_check(L, 1); + lua_pushinteger(L, (lua_Integer)data->size); + return 1; +} + +/*** +* Returns the content of the data object as a Lua string. +* This is the Lua `__tostring` metamethod. +* @function __tostring +* @treturn string A string representation of the entire data block. +*/ +static int luadata_tostring(lua_State *L) +{ + luadata_t *data = luadata_check(L, 1); + lua_pushlstring(L, data->ptr, data->size); + return 1; +} + +static void luadata_release(void *private) +{ + luadata_t *data = (luadata_t *)private; + if (data->opt & LUADATA_OPT_FREE) + lunatik_free(data->ptr); +} + +/*** +* Creates a new data object, allocating a fresh block of memory. +* @function new +* @tparam integer size The number of bytes to allocate for the data block. +* @treturn data A new, writable data object. +* @raise Error if memory allocation fails. +* @within data +*/ +static const luaL_Reg luadata_lib[] = { + {"new", luadata_lnew}, + {NULL, NULL} +}; + +static const luaL_Reg luadata_mt[] = { + {"__index", lunatik_monitorobject}, + {"__gc", lunatik_deleteobject}, + {"__len", luadata_length}, + {"__tostring", luadata_tostring}, +/*** +* Extracts an unsigned 8-bit integer (a byte) from the data object. +* Alias for `getuint8`. +* @function getbyte +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @treturn integer The byte value (0-255) at the specified offset. +* @raise Error if offset is out of bounds. +* @see getuint8 +*/ + {"getbyte", luadata_getuint8}, +/*** +* Inserts an unsigned 8-bit integer (a byte) into the data object. +* Alias for `setuint8`. +* @function setbyte +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @tparam integer value The byte value (0-255) to write. +* @raise Error if offset is out of bounds or the data object is read-only. +* @see setuint8 +*/ + {"setbyte", luadata_setuint8}, + {"getint8", luadata_getint8}, + {"setint8", luadata_setint8}, + {"getuint8", luadata_getuint8}, + {"setuint8", luadata_setuint8}, + {"getint16", luadata_getint16}, + {"setint16", luadata_setint16}, + {"getuint16", luadata_getuint16}, + {"setuint16", luadata_setuint16}, + {"getint32", luadata_getint32}, + {"setint32", luadata_setint32}, + {"getuint32", luadata_getuint32}, + {"setuint32", luadata_setuint32}, +#ifdef __LP64__ + {"getint64", luadata_getint64}, + {"setint64", luadata_setint64}, +/*** +* Extracts a Lua integer (platform-dependent: 64-bit on LP64, 32-bit otherwise) from the data object. +* Alias for `getint64` on LP64 systems, `getint32` otherwise. Assumes host byte order. +* @function getnumber +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @treturn integer The Lua integer value at the specified offset. +* @raise Error if offset is out of bounds. +*/ + {"getnumber", luadata_getint64}, +/*** +* Inserts a Lua integer (platform-dependent: 64-bit on LP64, 32-bit otherwise) into the data object. +* Alias for `setint64` on LP64 systems, `setint32` otherwise. Assumes host byte order. +* @function setnumber +* @tparam integer offset Byte offset from the start of the data block (0-indexed). +* @tparam integer value The Lua integer value to write. +* @raise Error if offset is out of bounds or the data object is read-only. +*/ + {"setnumber", luadata_setint64}, +#else + {"getnumber", luadata_getint32}, + {"setnumber", luadata_setint32}, +#endif + {"getstring", luadata_getstring}, + {"setstring", luadata_setstring}, + {NULL, NULL} +}; + +static const lunatik_class_t luadata_class = { + .name = "data", + .methods = luadata_mt, + .release = luadata_release, + .sleep = false, +}; + +static int luadata_lnew(lua_State *L) +{ + size_t size = (size_t)luaL_checkinteger(L, 1); + lunatik_object_t *object = lunatik_newobject(L, &luadata_class, sizeof(luadata_t)); + luadata_t *data = (luadata_t *)object->private; + + data->ptr = lunatik_checkalloc(L, size); + data->size = size; + data->opt = LUADATA_OPT_FREE; + return 1; /* object */ +} + +LUNATIK_NEWLIB(data, luadata_lib, &luadata_class, NULL); + +lunatik_object_t *luadata_new(void *ptr, size_t size, bool sleep, uint8_t opt) +{ + lunatik_object_t *object = lunatik_createobject(&luadata_class, sizeof(luadata_t), sleep); + + if (object != NULL) { + luadata_t *data = (luadata_t *)object->private; + data->ptr = ptr; + data->size = size; + data->opt = opt; + } + return object; +} +EXPORT_SYMBOL_NS(luadata_new, LUNATIK); + +int luadata_reset(lunatik_object_t *object, void *ptr, size_t size, uint8_t opt) +{ + luadata_t *data; + + lunatik_lock(object); + data = (luadata_t *)object->private; + + if (data->opt & LUADATA_OPT_FREE) { + lunatik_unlock(object); + return -1; + } + + data->ptr = ptr; + data->size = size; + data->opt = opt & LUADATA_OPT_KEEP ? data->opt : opt; + + lunatik_unlock(object); + return 0; +} +EXPORT_SYMBOL_NS(luadata_reset, LUNATIK); + +static int __init luadata_init(void) +{ + return 0; +} + +static void __exit luadata_exit(void) +{ +} + +module_init(luadata_init); +module_exit(luadata_exit); +MODULE_LICENSE("Dual MIT/GPL"); +MODULE_AUTHOR("Lourival Vieira Neto "); + diff --git a/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luanetfilter.c b/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luanetfilter.c new file mode 100644 index 0000000..21214f7 --- /dev/null +++ b/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luanetfilter.c @@ -0,0 +1,225 @@ +/* +* SPDX-FileCopyrightText: (c) 2024-2025 Mohammad Shehar Yaar Tausif +* SPDX-License-Identifier: MIT OR GPL-2.0-only +*/ +/*** +* Low-level Lua interface to the Linux Kernel Netfilter framework. +* This module allows registering Lua functions as Netfilter hooks to inspect +* and modify network packets. +* +* @module netfilter +*/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include + +#include +#include +#include + +#include "luanetfilter.h" +#include "luadata.h" + +MODULE_IMPORT_NS(LUNATIK); + +/*** +* Represents a registered Netfilter hook. +* This is a userdata object returned by `netfilter.register()`. It encapsulates +* the kernel `struct nf_hook_ops` and associated Lunatik runtime information +* necessary to invoke the Lua callback when a packet matches the hook criteria. +* @type netfilter_hook +*/ +typedef struct luanetfilter_s { + lunatik_object_t *runtime; + lunatik_object_t *skb; + u32 mark; + struct nf_hook_ops nfops; +} luanetfilter_t; + + +static void luanetfilter_release(void *private); + +static inline bool luanetfilter_pushcb(lua_State *L, luanetfilter_t *luanf) +{ + if (lunatik_getregistry(L, luanf) != LUA_TTABLE) { + pr_err("could not find ops table\n"); + return false; + } + + if (lua_getfield(L, -1, "hook") != LUA_TFUNCTION) { + pr_err("operation not defined"); + return false; + } + return true; +} + +static inline lunatik_object_t *luanetfilter_pushskb(lua_State *L, luanetfilter_t *luanf, struct sk_buff *skb) +{ + if (lunatik_getregistry(L, luanf->skb) != LUA_TUSERDATA) { + pr_err("could not find skb"); + return NULL; + } + + lunatik_object_t *data = (lunatik_object_t *)lunatik_toobject(L, -1); + if (unlikely(data == NULL || skb_linearize(skb) != 0)) { + pr_err("could not get skb\n"); + return NULL; + } + return data; +} + +static int luanetfilter_hook_cb(lua_State *L, luanetfilter_t *luanf, struct sk_buff *skb) +{ + lunatik_object_t *data; + + if (!luanetfilter_pushcb(L, luanf) || (data = luanetfilter_pushskb(L, luanf, skb)) == NULL) + return -1; + + if (skb_mac_header_was_set(skb)) + luadata_reset(data, skb_mac_header(skb), skb_headlen(skb) + skb_mac_header_len(skb), LUADATA_OPT_NONE); + else + luadata_reset(data, skb->data, skb_headlen(skb), LUADATA_OPT_NONE); + + if (lua_pcall(L, 1, 2, 0) != LUA_OK) { + pr_err("%s\n", lua_tostring(L, -1)); + return -1; + } + + if (!lua_isnil(L, -1)) + skb->mark = (u32)lua_tointeger(L, -1); + return lua_tointeger(L, -2); +} + +static inline unsigned int luanetfilter_docall(luanetfilter_t *luanf, struct sk_buff *skb) +{ + int ret; + int policy = NF_ACCEPT; + + if (unlikely(!luanf || !luanf->runtime)) { + pr_err("runtime not found\n"); + goto out; + } + + if (likely(luanf->mark != skb->mark)) + goto out; + + lunatik_run(luanf->runtime, luanetfilter_hook_cb, ret, luanf, skb); + return (ret < 0 || ret > NF_MAX_VERDICT) ? policy : ret; +out: + return policy; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)) +static unsigned int luanetfilter_hook(void *priv, struct sk_buff *skb, const struct nf_hook_state *state) +{ + luanetfilter_t *luanf = (luanetfilter_t *)priv; + return luanetfilter_docall(luanf, skb); +} +#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)) +static unsigned int luanetfilter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) +{ + luanetfilter_t *luanf = (luanetfilter_t *)ops->priv; + return luanetfilter_docall(luanf, skb); +} +#else +static unsigned int luanetfilter_hook(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) +{ + luanetfilter_t *luanf = (luanetfilter_t *)ops->priv; + return luanetfilter_docall(luanf, skb); +} +#endif + +static const luaL_Reg luanetfilter_mt[] = { + {"__gc", lunatik_deleteobject}, + {NULL, NULL} +}; + +static const lunatik_class_t luanetfilter_class = { + .name = "netfilter", + .methods = luanetfilter_mt, + .release = luanetfilter_release, + .sleep = false, +}; + +/*** +* Registers a Netfilter hook. +* The hook function will be called for packets matching the specified criteria. +* @function register +* @tparam table opts A table containing the options for the Netfilter hook. +* It should have the following fields: +* +* - `hook` (function): The Lua function to be called for each packet. +* It receives a `luadata` object representing the packet buffer (`skb`) +* and should return an integer verdict (e.g., `netfilter.action.ACCEPT`). +* - `pf` (integer): The protocol family (e.g., `netfilter.family.INET`). +* - `hooknum` (integer): The hook number within the protocol family (e.g., `netfilter.inet_hooks.LOCAL_OUT`). +* - `priority` (integer): The hook priority (e.g., `netfilter.ip_priority.FILTER`). +* - `mark` (integer, optional): Packet mark to match. If set, the hook is only called for packets with this mark. +* @treturn userdata A handle representing the registered hook. This handle can be garbage collected to unregister the hook. +*/ +static int luanetfilter_register(lua_State *L) +{ + luaL_checktype(L, 1, LUA_TTABLE); + lunatik_object_t *object = lunatik_newobject(L, &luanetfilter_class , sizeof(luanetfilter_t)); + luanetfilter_t *nf = (luanetfilter_t *)object->private; + luanetfilter_newbuffer(L, nf, skb); + nf->runtime = NULL; + + struct nf_hook_ops *nfops = &nf->nfops; +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 14, 0)) + nfops->hook_ops_type = NF_HOOK_OP_UNDEFINED; +#endif + nfops->hook = luanetfilter_hook; + nfops->dev = NULL; + nfops->priv = nf; + luanetfilter_setinteger(L, 1, nfops, pf); + luanetfilter_setinteger(L, 1, nfops, hooknum); + luanetfilter_setinteger(L, 1, nfops, priority); + luanetfilter_optinteger(L, 1, nf, mark, 0); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)) + if (nf_register_net_hook(&init_net, nfops) != 0) +#else + if (nf_register_hook(nfops) != 0) +#endif + luaL_error(L, "failed to register netfilter hook"); + lunatik_setruntime(L, netfilter, nf); + lunatik_getobject(nf->runtime); + lunatik_registerobject(L, 1, object); + return 1; +} + +static const luaL_Reg luanetfilter_lib[] = { + {"register", luanetfilter_register}, + {NULL, NULL}, +}; + +static void luanetfilter_release(void *private) +{ + luanetfilter_t *nf = (luanetfilter_t *)private; + if (!nf->runtime) + return; + + nf_unregister_net_hook(&init_net, &nf->nfops); + lunatik_putobject(nf->runtime); + nf->runtime = NULL; +} + +LUNATIK_NEWLIB(netfilter, luanetfilter_lib, &luanetfilter_class, luanetfilter_flags); + +static int __init luanetfilter_init(void) +{ + return 0; +} + +static void __exit luanetfilter_exit(void) +{ +} + +module_init(luanetfilter_init); +module_exit(luanetfilter_exit); +MODULE_LICENSE("Dual MIT/GPL"); +MODULE_AUTHOR("Mohammad Shehar Yaar Tausif "); + diff --git a/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luarcu.c b/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luarcu.c new file mode 100644 index 0000000..c64d5a4 --- /dev/null +++ b/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luarcu.c @@ -0,0 +1,450 @@ +/* +* SPDX-FileCopyrightText: (c) 2023-2025 Ring Zero Desenvolvimento de Software LTDA +* SPDX-License-Identifier: MIT OR GPL-2.0-only +*/ + +/*** +* Read-Copy-Update (RCU) synchronized hash table. +* This library provides a Lua-accessible hash table that uses RCU (Read-Copy-Update) +* for synchronization within the Linux kernel. RCU allows for very fast, lockless +* read operations, while write operations (updates and deletions) are synchronized +* to ensure data consistency. This makes it highly suitable for scenarios where +* read operations significantly outnumber write operations and high concurrency +* is required. +* +* Keys in the RCU table must be strings. Values must be Lunatik objects +* (i.e., userdata created by other Lunatik C modules like `data.new()`, +* `lunatik.runtime()`, etc.) or `nil` to delete an entry. +* +* A practical example of its usage can be found in `examples/shared.lua`, +* which implements an in-memory key-value store. +* +* @module rcu +*/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include "luarcu.h" + +#define LUARCU_MAXKEY (LUAL_BUFFERSIZE) + +typedef struct luarcu_entry_s { + lunatik_object_t *object; + struct hlist_node hlist; + struct rcu_head rcu; + char key[]; +} luarcu_entry_t; + +/*** +* Represents an RCU-synchronized hash table. +* This is a userdata object returned by `rcu.table()`. It behaves like a +* standard Lua table for get (`__index`) and set (`__newindex`) operations +* but uses RCU internally for synchronization. +* +* Keys must be strings. Values stored must be Lunatik objects (e.g., created +* via `data.new()`, `lunatik.runtime()`) or `nil` (to remove an entry). +* When a Lunatik object is retrieved, it's a new reference to that object. +* +* @type rcu_table +* @usage +* -- Assuming 'data' module is available for creating Lunatik objects +* -- and 'rcu' module is required. +* local rcu_store = rcu.table() +* local my_data = data.new(10) -- Create a Lunatik object +* my_data:setstring(0, "hello") +* +* -- Set a value +* rcu_store["my_key"] = my_data +* +* -- Get a value +* local retrieved_data = rcu_store["my_key"] +* if retrieved_data then +* print(retrieved_data:getstring(0)) -- Output: hello +* end +* +* -- Remove a value +* rcu_store["my_key"] = nil +* +* -- Iterate +* rcu_store:map(function(k, v_obj) +* print("Found key:", k, "Value object:", v_obj) +* end) +*/ + +typedef struct luarcu_table_s { + size_t size; + unsigned int seed; + struct hlist_head hlist[]; +} luarcu_table_t; + +#define luarcu_sizeoftable(size) (sizeof(luarcu_table_t) + sizeof(struct hlist_head) * (size)) + +#include +/* size is always a power of 2; thus `size - 1` turns on every valid bit */ +#define luarcu_mask(table) ((table)->size - 1) +#define luarcu_hash(table, key, keylen) (luaS_hash((key), (keylen), (table)->seed) & luarcu_mask(table)) +#define luarcu_seed() get_random_u32() + +#define luarcu_entry(ptr, pos) hlist_entry_safe(rcu_dereference_raw(ptr), typeof(*(pos)), hlist) +#define luarcu_foreach(table, bucket, n, pos) \ + for (bucket = 0, pos = NULL; pos == NULL && bucket < (table)->size; bucket++) \ + for (pos = luarcu_entry(hlist_first_rcu(&(table)->hlist[bucket]), pos); \ + pos && ({ n = luarcu_entry(hlist_next_rcu(&(pos)->hlist), pos); 1; }); \ + pos = n) + +#define luarcu_checkoptnil(L, i, checkopt, ...) \ + (lua_type((L), (i)) == LUA_TNIL ? NULL : checkopt((L), (i), ## __VA_ARGS__)) + +static int luarcu_table(lua_State *L); + +static inline luarcu_entry_t *luarcu_lookup(luarcu_table_t *table, unsigned int index, + const char *key, size_t keylen) +{ + luarcu_entry_t *entry; + + hlist_for_each_entry_rcu(entry, table->hlist + index, hlist) + if (strncmp(entry->key, key, keylen) == 0) + return entry; + return NULL; +} + +static luarcu_entry_t *luarcu_newentry(const char *key, size_t keylen, lunatik_object_t *object) +{ + luarcu_entry_t *entry; + + if (keylen >= LUARCU_MAXKEY || (entry = kmalloc(struct_size(entry, key, keylen + 1), GFP_ATOMIC)) == NULL) + return NULL; + + strncpy(entry->key, key, keylen); + entry->key[keylen] = '\0'; + entry->object = object; + lunatik_getobject(object); + return entry; +} + +static inline void luarcu_free(luarcu_entry_t *entry) +{ + lunatik_putobject(entry->object); + kfree_rcu(entry, rcu); +} + +LUNATIK_OBJECTCHECKER(luarcu_checktable, luarcu_table_t *); + +static int luarcu_cloneobject(lua_State *L) +{ + lunatik_object_t *object = (lunatik_object_t *)lua_touserdata(L, 1); + lunatik_cloneobject(L, object); + return 1; +} + +lunatik_object_t *luarcu_gettable(lunatik_object_t *table, const char *key, size_t keylen) +{ + luarcu_table_t *_table = (luarcu_table_t *)table->private; + unsigned int index = luarcu_hash(_table, key, keylen); + lunatik_object_t *value = NULL; + luarcu_entry_t *entry; + + rcu_read_lock(); + entry = luarcu_lookup(_table, index, key, keylen); + if (entry != NULL) { + /* entry might be released after rcu_read_unlock */ + value = entry->object; /* thus we need to store object pointer */ + lunatik_getobject(value); + } + rcu_read_unlock(); + return value; +} + +EXPORT_SYMBOL_NS(luarcu_gettable, LUNATIK); + +int luarcu_settable(lunatik_object_t *table, const char *key, size_t keylen, lunatik_object_t *object) +{ + int ret = 0; + luarcu_table_t *tab = (luarcu_table_t *)table->private; + luarcu_entry_t *old; + unsigned int index = luarcu_hash(tab, key, keylen); + + lunatik_lock(table); + rcu_read_lock(); + old = luarcu_lookup(tab, index, key, keylen); + rcu_read_unlock(); + if (object) { + luarcu_entry_t *new = luarcu_newentry(key, keylen, object); + if (new == NULL) { + ret = -ENOMEM; + goto unlock; + } + + if (!old) + hlist_add_head_rcu(&new->hlist, tab->hlist + index); + else { + hlist_replace_rcu(&old->hlist, &new->hlist); + luarcu_free(old); + } + } + else if (old) { + hlist_del_rcu(&old->hlist); + luarcu_free(old); + } +unlock: + lunatik_unlock(table); + return ret; +} +EXPORT_SYMBOL_NS(luarcu_settable, LUNATIK); + +/*** +* Retrieves a value (a Lunatik object) from the RCU table. +* This is the Lua `__index` metamethod, allowing table-like access `rcu_table[key]`. +* Read operations are RCU-protected and lockless. +* @function __index +* @tparam rcu_table self The RCU table instance. +* @tparam string key The key to look up in the table. +* @treturn lunatik_object The Lunatik object associated with the key, or `nil` if the key is not found. +* A new reference to the object is returned. +* @usage +* local my_object = my_rcu_table["some_key"] +* if my_object then +* -- Use my_object +* end +*/ +static int luarcu_index(lua_State *L) +{ + lunatik_object_t *table = lunatik_checkobject(L, 1); + size_t keylen; + const char *key = luaL_checklstring(L, 2, &keylen); + lunatik_object_t *value = luarcu_gettable(table, key, keylen); + + if (value == NULL) + lua_pushnil(L); + else { + lua_pushcfunction(L, luarcu_cloneobject); + lua_pushlightuserdata(L, value); + if (lua_pcall(L, 1, 1, 0) != LUA_OK) { + lunatik_putobject(value); + lua_error(L); + } + } + return 1; /* value */ +} + +/*** +* Sets or removes a value in the RCU table. +* This is the Lua `__newindex` metamethod, allowing table-like assignment `rcu_table[key] = value`. +* Write operations are synchronized. +* @function __newindex +* @tparam rcu_table self The RCU table instance. +* @tparam string key The key to set or update. +* @tparam lunatik_object|nil value The Lunatik object to associate with the key. +* If `nil`, the key-value pair is removed from the table. +* @raise Error if memory allocation fails during new entry creation. +* @usage +* local data_obj = data.new(5) -- Assuming 'data' module +* my_rcu_table["new_key"] = some_lunatik_object +* my_rcu_table["another_key"] = nil -- Removes 'another_key' +*/ +static int luarcu_newindex(lua_State *L) +{ + lunatik_object_t *table = lunatik_checkobject(L, 1); + size_t keylen; + const char *key = luaL_checklstring(L, 2, &keylen); + lunatik_object_t *object = luarcu_checkoptnil(L, 3, lunatik_checkobject); + + if (luarcu_settable(table, key, keylen, object) < 0) + luaL_error(L, "not enough memory"); + return 0; +} + +static void luarcu_release(void *private) +{ + luarcu_table_t *table = (luarcu_table_t *)private; + unsigned int bucket; + luarcu_entry_t *n, *entry; + + luarcu_foreach(table, bucket, n, entry) { + hlist_del_rcu(&entry->hlist); + luarcu_free(entry); + } +} + +static inline void luarcu_inittable(luarcu_table_t *table, size_t size) +{ + __hash_init(table->hlist, size); + table->size = size; + table->seed = luarcu_seed(); +} + +static int luarcu_map_handle(lua_State *L) +{ + const char *key = (const char *)lua_touserdata(L, 2); + lunatik_object_t *value = (lunatik_object_t *)lua_touserdata(L, 3); + + BUG_ON(!key || !value); + + lua_pop(L, 2); /* key, value */ + + lua_pushstring(L, key); + lunatik_pushobject(L, value); + lua_call(L, 2, 0); + + return 0; +} + +static inline int luarcu_map_call(lua_State *L, int cb, const char *key, lunatik_object_t *value) +{ + lua_pushcfunction(L, luarcu_map_handle); + lua_pushvalue(L, cb); + lua_pushlightuserdata(L, (void *)key); + lua_pushlightuserdata(L, value); + + return lua_pcall(L, 3, 0, 0); /* handle(cb, key, value) */ +} + +/*** +* Iterates over the RCU table and calls a callback for each key-value pair. +* The iteration is RCU-protected. The order of iteration is not guaranteed. +* For each entry, a new reference to the value (Lunatik object) is obtained +* before calling the callback and released after the callback returns. +* +* @function map +* @tparam rcu_table self The RCU table instance. +* @tparam function callback A Lua function that will be called for each entry in the table. +* The callback receives two arguments: +* +* 1. `key` (string): The key of the current entry. +* 2. `value` (lunatik_object): The Lunatik object associated with the key. +* +* @treturn nil +* @raise Error if the callback function raises an error during its execution. +* @usage +* -- Example: Iterating and printing content if values are 'data' objects +* my_rcu_table:map(function(k, v_obj) +* -- v_obj is the Lunatik object stored for the key. +* -- If it's a 'data' object (a common use case, see examples/shared.lua): +* print("Key:", k, "Content from data object:", v_obj:getstring(0)) +* end) +*/ +static int luarcu_map(lua_State *L) +{ + luarcu_table_t *table = luarcu_checktable(L, 1); + unsigned int bucket; + luarcu_entry_t *n, *entry; + + luaL_checktype(L, 2, LUA_TFUNCTION); /* cb */ + lua_remove(L, 1); /* table */ + + rcu_read_lock(); + luarcu_foreach(table, bucket, n, entry) { + char key[LUARCU_MAXKEY]; + + strncpy(key, entry->key, LUARCU_MAXKEY); + key[LUARCU_MAXKEY - 1] = '\0'; + lunatik_object_t *value = entry->object; + lunatik_getobject(value); + + rcu_read_unlock(); + int ret = luarcu_map_call(L, 1, key, value); + lunatik_putobject(value); + if (ret != LUA_OK) + lua_error(L); + rcu_read_lock(); + } + rcu_read_unlock(); + return 0; +} + +static const struct luaL_Reg luarcu_lib[] = { + {"table", luarcu_table}, + {"map", luarcu_map}, + {NULL, NULL} +}; + +static const struct luaL_Reg luarcu_mt[] = { + {"__newindex", luarcu_newindex}, + {"__index", luarcu_index}, + {"__gc", lunatik_deleteobject}, + {NULL, NULL} +}; + +static const lunatik_class_t luarcu_class = { + .name = "rcu", + .methods = luarcu_mt, + .release = luarcu_release, +}; + +lunatik_object_t *luarcu_newtable(size_t size, bool sleep) +{ + lunatik_object_t *object; + + size = roundup_pow_of_two(size); + if ((object = lunatik_createobject(&luarcu_class, luarcu_sizeoftable(size), sleep))!= NULL) + luarcu_inittable((luarcu_table_t *)object->private, size); + return object; +} +EXPORT_SYMBOL_NS(luarcu_newtable, LUNATIK); + +/*** +* Creates a new RCU-synchronized hash table. +* @function table +* @tparam[opt=1024] integer size Specifies the initial number of hash buckets (internal slots) for the table. +* This is **not** a hard limit on the number of entries the table can store. +* The provided `size` will be rounded up to the nearest power of two. +* Choosing an appropriate `size` involves a trade-off between memory usage and performance: +* +* - more buckets (larger `size`): Consumes more memory for the table structure itself, +* even if many buckets remain empty. However, it reduces the probability of hash collisions, +* which can significantly speed up operations (lookups, insertions, deletions), +* especially when storing a large number of entries. +* - fewer buckets (smaller `size`): Uses less memory for the table's internal array. +* However, if the number of entries is high relative to the number of buckets, +* it increases the chance of hash collisions. This means more entries might end up +* in the same bucket, forming longer linked lists that need to be traversed, +* thereby slowing down operations. +* +* **Guidance**: For optimal performance, aim for a `size` that is roughly in the order of, +* or somewhat larger than, the maximum number of entries you anticipate storing. This helps +* maintain a low average number of entries per bucket (a low "load factor," ideally close to 1). +* The table can hold more entries than its `size` (number of buckets), but performance +* will degrade as the load factor increases. The default is a general-purpose starting point +* suitable for many common use cases. +* @treturn rcu_table A new RCU table object, or raises an error if memory allocation fails. +* @usage +* local my_rcu_table = rcu.table() -- Default: 1024 buckets, good for moderate entries. +* local small_table = rcu.table(128) -- 128 buckets, for fewer expected entries. +* local large_table = rcu.table(8192) -- 8192 buckets, for many expected entries. +* @within rcu +*/ +static int luarcu_table(lua_State *L) +{ + size_t size = roundup_pow_of_two(luaL_optinteger(L, 1, LUARCU_DEFAULT_SIZE)); + lunatik_object_t *object = lunatik_newobject(L, &luarcu_class, luarcu_sizeoftable(size)); + + luarcu_inittable((luarcu_table_t *)object->private, size); + return 1; /* object */ +} + +LUNATIK_NEWLIB(rcu, luarcu_lib, &luarcu_class, NULL); + +static int __init luarcu_init(void) +{ + return 0; +} + +static void __exit luarcu_exit(void) +{ +} + +module_init(luarcu_init); +module_exit(luarcu_exit); +MODULE_LICENSE("Dual MIT/GPL"); +MODULE_AUTHOR("Lourival Vieira Neto "); + diff --git a/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luaxdp.c b/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luaxdp.c new file mode 100644 index 0000000..7558d7a --- /dev/null +++ b/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luaxdp.c @@ -0,0 +1,301 @@ +/* +* SPDX-FileCopyrightText: (c) 2024 Ring Zero Desenvolvimento de Software LTDA +* SPDX-License-Identifier: MIT OR GPL-2.0-only +*/ +/*** +* eXpress Data Path (XDP) integration. +* This library allows Lua scripts to interact with the kernel's XDP subsystem. +* It enables XDP/eBPF programs to call Lua functions for packet processing, +* providing a flexible way to implement custom packet handling logic in Lua +* at a very early stage in the network stack. +* +* The primary mechanism involves an XDP program calling the `bpf_luaxdp_run` +* kfunc, which in turn invokes a Lua callback function previously registered +* using `xdp.attach()`. +* @module xdp +*/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include + +#include +#include +#include + +#include + +#include "luarcu.h" +#include "luadata.h" + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)) +#include +#include +#include + +MODULE_IMPORT_NS(LUNATIK); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0)) +__bpf_kfunc_start_defs(); +#else +__diag_push(); +__diag_ignore_all("-Wmissing-prototypes", + "Global kfuncs as their definitions will be in BTF"); +#endif + +static lunatik_object_t *luaxdp_runtimes = NULL; + +static inline lunatik_object_t *luaxdp_pushdata(lua_State *L, int upvalue, void *ptr, size_t size) +{ + lunatik_object_t *data; + + lua_pushvalue(L, lua_upvalueindex(upvalue)); + data = (lunatik_object_t *)lunatik_toobject(L, -1); + luadata_reset(data, ptr, size, LUADATA_OPT_KEEP); + return data; +} + +static int luaxdp_callback(lua_State *L) +{ + lunatik_object_t *buffer, *argument; + struct xdp_buff *ctx = (struct xdp_buff *)lua_touserdata(L, 1); + void *arg = lua_touserdata(L, 2); + size_t arg__sz = (size_t)lua_tointeger(L, 3); + + lua_pushvalue(L, lua_upvalueindex(1)); /* callback */ + buffer = luaxdp_pushdata(L, 2, ctx->data, ctx->data_end - ctx->data); + argument = luaxdp_pushdata(L, 3, arg, arg__sz); + + if (lua_pcall(L, 2, 1, 0) != LUA_OK) { + luadata_clear(buffer); + luadata_clear(argument); + return lua_error(L); + } + + luadata_clear(buffer); + luadata_clear(argument); + return 1; +} + +static int luaxdp_handler(lua_State *L, struct xdp_buff *ctx, void *arg, size_t arg__sz) +{ + int action = -1; + int status; + + if (lunatik_getregistry(L, luaxdp_callback) != LUA_TFUNCTION) { + pr_err("couldn't find callback"); + goto out; + } + + lua_pushlightuserdata(L, ctx); + lua_pushlightuserdata(L, arg); + lua_pushinteger(L, (lua_Integer)arg__sz); + if ((status = lua_pcall(L, 3, 1, 0)) != LUA_OK) { + pr_err("%s\n", lua_tostring(L, -1)); + goto out; + } + + action = lua_tointeger(L, -1); +out: + return action; +} + +static inline int luaxdp_checkruntimes(void) +{ + const char *key = "runtimes"; + if (luaxdp_runtimes == NULL && + (luaxdp_runtimes = luarcu_gettable(lunatik_env, key, sizeof(key))) == NULL) + return -1; + return 0; +} + +__bpf_kfunc int bpf_luaxdp_run(char *key, size_t key__sz, struct xdp_md *xdp_ctx, void *arg, size_t arg__sz) +{ + lunatik_object_t *runtime; + struct xdp_buff *ctx = (struct xdp_buff *)xdp_ctx; + int action = -1; + size_t keylen = key__sz - 1; + + if (unlikely(luaxdp_checkruntimes() != 0)) { + pr_err("couldn't find _ENV.runtimes\n"); + goto out; + } + + key[keylen] = '\0'; + if ((runtime = luarcu_gettable(luaxdp_runtimes, key, keylen)) == NULL) { + pr_err("couldn't find runtime '%s'\n", key); + goto out; + } + + lunatik_run(runtime, luaxdp_handler, action, ctx, arg, arg__sz); + lunatik_putobject(runtime); +out: + return action; +} + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 7, 0)) +__bpf_kfunc_end_defs(); +#else +__diag_pop(); +#endif + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 9, 0)) +BTF_KFUNCS_START(bpf_luaxdp_set) +BTF_ID_FLAGS(func, bpf_luaxdp_run) +BTF_KFUNCS_END(bpf_luaxdp_set) +#else +BTF_SET8_START(bpf_luaxdp_set) +BTF_ID_FLAGS(func, bpf_luaxdp_run) +BTF_SET8_END(bpf_luaxdp_set) +#endif + +static const struct btf_kfunc_id_set bpf_luaxdp_kfunc_set = { + .owner = THIS_MODULE, + .set = &bpf_luaxdp_set, +}; + +/*** +* Table of XDP action verdicts. +* These constants define the possible return values from an XDP program (and thus +* from the Lua callback attached via `xdp.attach`) to indicate how the packet +* should be handled. +* (Constants from ``) +* @table action +* @tfield integer ABORTED Indicates an error; packet is dropped. (XDP_ABORTED) +* @tfield integer DROP Drop the packet silently. (XDP_DROP) +* @tfield integer PASS Pass the packet to the normal network stack. (XDP_PASS) +* @tfield integer TX Transmit the packet back out the same interface it arrived on. (XDP_TX) +* @tfield integer REDIRECT Redirect the packet to another interface or BPF map. (XDP_REDIRECT) +* @within xdp +*/ +#define luaxdp_setcallback(L, i) (lunatik_setregistry((L), (i), luaxdp_callback)) + +static inline void luaxdp_newdata(lua_State *L) +{ + lunatik_object_t *data = lunatik_checknull(L, luadata_new(NULL, 0, false, LUADATA_OPT_NONE)); + lunatik_cloneobject(L, data); +} + +/*** +* Unregisters the Lua callback function associated with the current Lunatik runtime. +* After calling this, `bpf_luaxdp_run` calls targeting this runtime will no longer +* invoke a Lua function (they will likely return an error or default action). +* @function detach +* @treturn nil +* @usage +* xdp.detach() +* @within xdp +*/ +static int luaxdp_detach(lua_State *L) +{ + lua_pushnil(L); + luaxdp_setcallback(L, 1); + return 0; +} + +/*** +* Registers a Lua callback function to be invoked by an XDP/eBPF program. +* When an XDP program calls the `bpf_luaxdp_run` kfunc, Lunatik will execute +* the registered Lua `callback` associated with the current Lunatik runtime. +* The runtime invoking this function must be non-sleepable. +* +* The `bpf_luaxdp_run` kfunc is called from an eBPF program with the following signature: +* `int bpf_luaxdp_run(char *key, size_t key_sz, struct xdp_md *xdp_ctx, void *arg, size_t arg_sz)` +* +* - `key`: A string identifying the Lunatik runtime (e.g., the script name like "examples/filter/sni"). +* This key is used to look up the runtime in Lunatik's internal table of active runtimes. +* - `key_sz`: Length of the key string (including the null terminator). +* - `xdp_ctx`: The XDP metadata context (`struct xdp_md *`). +* - `arg`: A pointer to arbitrary data passed from eBPF to Lua. +* - `arg_sz`: The size of the `arg` data. +* +* @function attach +* @tparam function callback The Lua function to be called. This function receives two arguments: +* +* 1. `buffer` (data): A `data` object representing the network packet buffer (`xdp_md`). +* The `data` object points to `xdp_ctx->data` and its size is `xdp_ctx->data_end - xdp_ctx->data`. +* 2. `argument` (data): A `data` object representing the `arg` passed from the eBPF program. +* Its size is `arg_sz`. +* +* The callback function should return an integer verdict, typically one of the values +* from the `xdp.action` table (e.g., `xdp.action.PASS`, `xdp.action.DROP`). +* @treturn nil +* @raise Error if the current runtime is sleepable or if internal setup fails. +* @usage +* -- Lua script (e.g., "my_xdp_handler.lua" which is run via `lunatik run my_xdp_handler.lua`) +* local xdp = require("xdp") +* +* local function my_packet_processor(packet_buffer, custom_arg) +* print("Packet received, size:", #packet_buffer) +* return xdp.action.PASS +* end +* xdp.attach(my_packet_processor) +* +* -- In eBPF C code, to call the above Lua function: +* -- char rt_key[] = "my_xdp_handler.lua"; // Key matches the script name +* -- int verdict = bpf_luaxdp_run(rt_key, sizeof(rt_key), ctx, NULL, 0); +* @see xdp.action +* @see data +* @within xdp +*/ +static int luaxdp_attach(lua_State *L) +{ + lunatik_checkruntime(L, false); + luaL_checktype(L, 1, LUA_TFUNCTION); /* callback */ + + luaxdp_newdata(L); /* buffer */ + luaxdp_newdata(L); /* argument */ + + lua_pushcclosure(L, luaxdp_callback, 3); + luaxdp_setcallback(L, -1); + return 0; +} +#endif + +static const luaL_Reg luaxdp_lib[] = { +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)) + {"attach", luaxdp_attach}, + {"detach", luaxdp_detach}, +#endif + {NULL, NULL} +}; + +static const lunatik_reg_t luaxdp_action[] = { + {"ABORTED", XDP_ABORTED}, + {"DROP", XDP_DROP}, + {"PASS", XDP_PASS}, + {"TX", XDP_TX}, + {"REDIRECT", XDP_REDIRECT}, + {NULL, 0} +}; + +static const lunatik_namespace_t luaxdp_flags[] = { + {"action", luaxdp_action}, + {NULL, NULL} +}; + +LUNATIK_NEWLIB(xdp, luaxdp_lib, NULL, luaxdp_flags); + +static int __init luaxdp_init(void) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)) + return register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, &bpf_luaxdp_kfunc_set); +#else + return 0; +#endif +} + +static void __exit luaxdp_exit(void) +{ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(6, 4, 0)) + if (luaxdp_runtimes != NULL) + lunatik_putobject(luaxdp_runtimes); +#endif +} + +module_init(luaxdp_init); +module_exit(luaxdp_exit); +MODULE_LICENSE("Dual MIT/GPL"); +MODULE_AUTHOR("Lourival Vieira Neto "); + diff --git a/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luaxtable.c b/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luaxtable.c new file mode 100644 index 0000000..1745f62 --- /dev/null +++ b/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/luaxtable.c @@ -0,0 +1,432 @@ +/* +* SPDX-FileCopyrightText: (c) 2024-2025 Mohammad Shehar Yaar Tausif +* SPDX-License-Identifier: MIT OR GPL-2.0-only +*/ +/*** +* Netfilter Xtables extensions. +* This library allows Lua scripts to define custom Netfilter match and target +* extensions for `iptables`. These extensions can then be used in `iptables` +* rules to implement complex packet filtering and manipulation logic in Lua. +* +* When an `iptables` rule using a Lua-defined extension is encountered, the +* corresponding Lua callback function (`match` or `target`) is executed in the +* kernel. +* +* @module xtable +*/ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +#include +#include +#include +#include + +#include +#include +#include + +#include "luadata.h" +#include "luarcu.h" +#include "luaxtable.h" +#include "luanetfilter.h" + +MODULE_IMPORT_NS(LUNATIK); + +typedef enum luaxtable_type_e { + LUAXTABLE_TMATCH, + LUAXTABLE_TTARGET, +} luaxtable_type_t; + +/*** +* Represents a registered Xtables match or target extension. +* This is a userdata object returned by `xtable.match()` or `xtable.target()`. +* It encapsulates the kernel structures (`struct xt_match` or `struct xt_target`) +* and the Lunatik runtime information necessary to invoke the Lua callbacks. +* The primary way to interact with this object from Lua is to let it be garbage +* collected, which will unregister the extension from the kernel. +* @type xtable_extension +*/ +typedef struct luaxtable_s { + lunatik_object_t *runtime; + lunatik_object_t *skb; + union { + struct xt_match match; + struct xt_target target; + }; + luaxtable_type_t type; +} luaxtable_t; + +static struct { + lunatik_object_t *target; + lunatik_object_t *match; + bool match_fallback; + unsigned int target_fallback; +} luaxtable_hooks = {NULL, NULL, false, XT_CONTINUE}; + +static int luaxtable_docall(lua_State *L, luaxtable_t *xtable, luaxtable_info_t *info, const char *op, int nargs, int nret) +{ + int base = lua_gettop(L) - nargs; + + if (lunatik_getregistry(L, xtable) != LUA_TTABLE) { + pr_err("%s: could not find ops table\n", op); + goto err; + } + + if (lua_getfield(L, -1, op) != LUA_TFUNCTION) { + pr_err("%s isn't defined\n", op); + goto err; + } + + lua_insert(L, base + 1); /* op */ + lua_pop(L, 1); /* table */ + lua_pushlstring(L, info->userargs, LUAXTABLE_USERDATA_SIZE); /* userargs */ + + if (lua_pcall(L, nargs + 1, nret, 0) != LUA_OK) { + pr_err("%s error: %s\n", op, lua_tostring(L, -1)); + goto err; + } + return 0; +err: + return -1; +} + +static inline lunatik_object_t *luaxtable_getskb(lua_State *L, luaxtable_t *xtable) +{ + if (lunatik_getregistry(L, xtable->skb) != LUA_TUSERDATA) + return NULL; + + return (lunatik_object_t *)lunatik_toobject(L, -1); +} + +static int luaxtable_pushparams(lua_State *L, const struct xt_action_param *par, luaxtable_t *xtable, struct sk_buff *skb, uint8_t opt) +{ + lunatik_object_t *data = luaxtable_getskb(L, xtable); + if (unlikely(data == NULL || skb_linearize(skb) != 0)) { + pr_err("could not get skb\n"); + return -1; + } + luadata_reset(data, skb->data, skb->len, opt); + + lua_newtable(L); + lua_pushboolean(L, par->hotdrop); + lua_setfield(L, -2, "hotdrop"); + lua_pushinteger(L, par->thoff); + lua_setfield(L, -2, "thoff"); + lua_pushinteger(L, par->fragoff); + lua_setfield(L, -2, "fragoff"); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 10, 0)) + lua_pushinteger(L, xt_hooknum(par)); +#else + lua_pushinteger(L, par->hooknum); +#endif + lua_setfield(L, -2, "hooknum"); + lua_pushvalue(L, -1); /* param table */ + lua_insert(L, lua_gettop(L) - 2); /* stack: (...), param, skb, param */ + return 0; +} + +#define luaxtable_call(L, op, xtable, skb, par, info, opt) \ + ((luaxtable_pushparams(L, par, xtable, skb, opt) == -1) || (luaxtable_docall(L, xtable, info, op, 2, 1) == -1)) + +static int luaxtable_domatch(lua_State *L, luaxtable_t *xtable, const struct sk_buff *skb, struct xt_action_param *par, int fallback) +{ + if (luaxtable_call(L, "match", xtable, (struct sk_buff *)skb, par, (luaxtable_info_t *)par->matchinfo, LUADATA_OPT_READONLY) != 0) + return fallback; + + int ret = lua_toboolean(L, -1); + lua_getfield(L, -2, "hotdrop"); + par->hotdrop = lua_toboolean(L, -1); + return ret; +} + +static int luaxtable_dotarget(lua_State *L, luaxtable_t *xtable, struct sk_buff *skb, const struct xt_action_param *par, int fallback) +{ + if (luaxtable_call(L, "target", xtable, skb, par, (luaxtable_info_t *)par->targinfo, LUADATA_OPT_NONE) != 0) + return fallback; + + int ret = lua_tointeger(L, -1); + return ret >= 0 && ret <= NF_MAX_VERDICT ? ret : fallback; +} + +#define LUAXTABLE_HOOK_CB(hook, huk, U, V, T) \ +static T luaxtable_##hook(U skb, V par) \ +{ \ + int ret; \ + const luaxtable_info_t *info = (const luaxtable_info_t *)par->huk##info; \ + luaxtable_t *xtable = info->data; \ + \ + lunatik_run(xtable->runtime, luaxtable_do##hook, ret, xtable, skb, par, luaxtable_hooks.hook##_fallback); \ + return ret; \ +} + +#define LUAXTABLE_CHECKER_CB(hook, hk, huk, HOOK) \ +static int luaxtable_##hook##_check(const struct xt_##hk##chk_param *par) \ +{ \ + int ret; \ + luaxtable_t *xtable; \ + lunatik_object_t *obj = luarcu_gettable(luaxtable_hooks.hook, par->hook->name, XT_EXTENSION_MAXNAMELEN); \ + if (obj == NULL) { \ + pr_err("could not find hook (%s)\n", par->hook->name); \ + return -EINVAL; \ + } \ + xtable = (luaxtable_t *)obj->private; \ + luaxtable_info_t *info = (luaxtable_info_t *)par->huk##info; \ + info->data = xtable; \ + \ + lunatik_run(xtable->runtime, luaxtable_docall, ret, xtable, info, "checkentry", 0, 1); \ + return ret != 0 ? -EINVAL : 0; \ +} + +#define LUAXTABLE_DESTROYER_CB(hook, hk, huk, HOOK) \ +static void luaxtable_##hook##_destroy(const struct xt_##hk##dtor_param *par) \ +{ \ + int ret; \ + luaxtable_info_t *info = (luaxtable_info_t *)par->huk##info; \ + luaxtable_t *xtable = (luaxtable_t *)info->data; \ + \ + lunatik_run(xtable->runtime, luaxtable_docall, ret, xtable, info, "destroy", 0, 0); \ +} + +LUAXTABLE_HOOK_CB(match, match, const struct sk_buff *, struct xt_action_param *, bool); +LUAXTABLE_HOOK_CB(target, targ, struct sk_buff *, const struct xt_action_param *, unsigned int); + +LUAXTABLE_CHECKER_CB(match, mt, match, LUAXTABLE_TMATCH); +LUAXTABLE_CHECKER_CB(target, tg, targ, LUAXTABLE_TTARGET); + +LUAXTABLE_DESTROYER_CB(match, mt, match, LUAXTABLE_TMATCH); +LUAXTABLE_DESTROYER_CB(target, tg, targ, LUAXTABLE_TTARGET); + +static void luaxtable_release(void *private); + +/*** +* Creates and registers a new Xtables match extension. +* The Lua functions provided in `opts` will be called by the kernel +* when `iptables` rules using this match are evaluated. +* @function match +* @tparam table opts A table containing the configuration for the match extension. +* It **must** include the following fields: +* +* - `name` (string): The unique name for this match extension (e.g., "myluamatch"). This name is used in `iptables -m `. +* - `revision` (integer): The revision number of this match extension. +* - `family` (netfilter.family): The protocol family this match applies to (e.g., `netfilter.family.INET`). +* - `proto` (socket.ipproto, optional, default: 0): The specific IP protocol this match applies to (e.g., `socket.ipproto.TCP`). Use 0 for any protocol. +* - `hooks` (integer): A bitmask indicating the Netfilter hooks where this match can be used (e.g., `1 << netfilter.inet_hooks.LOCAL_OUT`). Multiple hooks can be OR'd. Note: `netfilter.netdev_hooks` are not available for legacy Xtables. +* - `match` (function): The Lua function to be called to evaluate if a packet matches. +* Its signature is `function(skb, par, userargs) -> boolean`. +* +* - `skb` (data): A read-only `data` object representing the packet's socket buffer. +* - `par` (table): A read-only table containing parameters related to the packet and hook: +* - `hotdrop` (boolean): `true` if an earlier rule already marked the packet for unconditional drop. +* - `thoff` (integer): Offset to the transport header within the `skb`. +* - `fragoff` (integer): Fragment offset (0 if not a fragment or is the first fragment). +* - `hooknum` (integer): The Netfilter hook number (e.g., `NF_INET_LOCAL_OUT`). +* - `userargs` (string): A string containing any arguments passed to this match from the `iptables` rule command line. +* +* The function should return `true` if the packet matches, `false` otherwise. +* - `checkentry` (function): A Lua function called when an `iptables` rule using this match is added or modified. +* Its signature is `function(userargs)`. + +* - `userargs` (string): The arguments string from the `iptables` rule. + +* This function should validate the `userargs`. If validation fails, it should call `error()`. +* - `destroy` (function): A Lua function called when an `iptables` rule using this match is deleted. +* Its signature is `function(userargs)`. +* +* - `userargs` (string): The arguments string from the `iptables` rule. +* +* This function can be used for cleanup. +* @treturn xtable_extension A userdata object representing the registered match extension. +* This object should be kept referenced as long as the extension is needed; +* when it's garbage collected, the extension is unregistered. +* @raise Error if registration fails (e.g., name conflict, invalid parameters, memory allocation failure). +* @see netfilter.family +* @see socket.ipproto +* @see netfilter.inet_hooks +* @see netfilter.bridge_hooks +* @see netfilter.arp_hooks +* @usage +* local xtable = require("xtable") +* local nf = require("netfilter") +* +* local my_match_opts = { +* name = "myluamatch", +* revision = 0, +* family = nf.family.INET, +* hooks = (1 << nf.inet_hooks.PREROUTING) | (1 << nf.inet_hooks.INPUT), +* match = function(skb, par, userargs) +* print("Matching packet with userargs:", userargs) +* return skb:getuint8(9) == 6 -- Check if protocol is TCP +* end, +* checkentry = function(userargs) print("Checking:", userargs) end, +* destroy = function(userargs) print("Destroying:", userargs) end +* } +* local match_ext = xtable.match(my_match_opts) +* -- To use in iptables: iptables -A INPUT -m myluamatch --somearg "hello" -j ACCEPT +*/ + +/*** +* Creates and registers a new Xtables target extension. +* The Lua function provided in `opts` will be called by the kernel +* for packets that reach an `iptables` rule using this target. +* @function target +* @tparam table opts A table containing the configuration for the target extension. +* It **must** include the following fields: +* +* - `name` (string): The unique name for this target extension (e.g., "MYLUATARGET"). This name is used in `iptables -j `. +* - `revision` (integer): The revision number of this target extension. +* - `family` (netfilter.family): The protocol family this target applies to (e.g., `netfilter.family.INET`). +* - `proto` (socket.ipproto, optional, default: 0): The specific IP protocol this target applies to (e.g., `socket.ipproto.UDP`). Use 0 for any protocol. +* - `hooks` (integer): A bitmask indicating the Netfilter hooks where this target can be used. +* - `target` (function): The Lua function to be called to process a packet. +* Its signature is `function(skb, par, userargs) -> netfilter.action_verdict`. +* - `skb` (data): A read-write `data` object representing the packet's socket buffer. Modifications to this `skb` can alter the packet. +* - `par` (table): A read-only table containing parameters related to the packet and hook (same structure as for `xtable.match`). +* - `userargs` (string): A string containing any arguments passed to this target from the `iptables` rule command line. +* +* The function should return an integer verdict, typically one of the constants from the `netfilter.action` table (e.g., `netfilter.action.DROP`, `netfilter.action.ACCEPT`). +* - `checkentry` (function): A Lua function called when an `iptables` rule using this target is added or modified. Its signature is `function(userargs)`. (See `xtable.match` for details). +* - `destroy` (function): A Lua function called when an `iptable`s rule using this target is deleted. Its signature is `function(userargs)`. (See `xtable.match` for details). +* @treturn xtable_extension A userdata object representing the registered target extension. +* @raise Error if registration fails. +* @see netfilter.action +* @usage +* local my_target_opts = { +* name = "MYLUATARGET", +* revision = 0, +* family = nf.family.INET, +* hooks = (1 << nf.inet_hooks.FORWARD), +* target = function(skb, par, userargs) +* print("Targeting packet with userargs:", userargs) +* -- Example: Modify TTL (byte at offset 8 in IP header) +* -- skb:setuint8(8, skb:getuint8(8) - 1) +* return nf.action.ACCEPT +* end, +* checkentry = function(userargs) print("Checking target:", userargs) end, +* destroy = function(userargs) print("Destroying target:", userargs) end +* } +* local target_ext = xtable.target(my_target_opts) +* -- To use in iptables: iptables -A FORWARD -j MYLUATARGET --someoption "value" +*/ +static const luaL_Reg luaxtable_mt[] = { + {"__gc", lunatik_deleteobject}, + {NULL, NULL} +}; + +static const lunatik_class_t luaxtable_class = { + .name = "xtable", + .methods = luaxtable_mt, + .release = luaxtable_release, + .sleep = false, +}; + +static inline lunatik_object_t *luaxtable_new(lua_State *L, int idx, int hook) +{ + luaL_checktype(L, idx, LUA_TTABLE); + lunatik_object_t *object = lunatik_newobject(L, &luaxtable_class , sizeof(luaxtable_t)); + luaxtable_t *xtable = (luaxtable_t *)object->private; + + xtable->type = hook; + xtable->runtime = NULL; + luanetfilter_newbuffer(L, xtable, skb); + return object; +} + +static inline void luaxtable_register(lua_State *L, int idx, luaxtable_t *xtable, lunatik_object_t *object) +{ + lunatik_setruntime(L, xtable, xtable); + lunatik_getobject(xtable->runtime); + lunatik_registerobject(L, idx, object); +} + +#define LUAXTABLE_NEWHOOK(hook, HOOK) \ +static int luaxtable_new##hook(lua_State *L) \ +{ \ + lunatik_object_t *object = luaxtable_new(L, 1, HOOK); \ + luaxtable_t *xtable = (luaxtable_t *)object->private; \ + \ + struct xt_##hook *hook = &xtable->hook; \ + hook->me = THIS_MODULE; \ + \ + lunatik_setstring(L, 1, hook, name, XT_EXTENSION_MAXNAMELEN - 1); \ + luanetfilter_setinteger(L, 1, hook, revision); \ + luanetfilter_setinteger(L, 1, hook, family); \ + luanetfilter_setinteger(L, 1, hook, proto); \ + luanetfilter_setinteger(L, 1, hook, hooks); \ + lunatik_checkfield(L, 1, "checkentry", LUA_TFUNCTION); \ + lunatik_checkfield(L, 1, "destroy", LUA_TFUNCTION); \ + lunatik_checkfield(L, 1, #hook, LUA_TFUNCTION); \ + \ + hook->usersize = 0; \ + hook->hook##size = sizeof(luaxtable_info_t); \ + hook->hook = luaxtable_##hook; \ + hook->checkentry = luaxtable_##hook##_check; \ + hook->destroy = luaxtable_##hook##_destroy; \ + \ + if (luarcu_settable(luaxtable_hooks.hook, hook->name, XT_EXTENSION_MAXNAMELEN, object) != 0) \ + luaL_error(L, "unable to hook: %s\n", hook->name); \ + \ + if (xt_register_##hook(hook) != 0) \ + luaL_error(L, "unable to register " #hook); \ + \ + luaxtable_register(L, 1, xtable, object); \ + return 1; \ +} + +LUAXTABLE_NEWHOOK(match, LUAXTABLE_TMATCH); +LUAXTABLE_NEWHOOK(target, LUAXTABLE_TTARGET); + + +static const luaL_Reg luaxtable_lib[] = { + {"match", luaxtable_newmatch}, + {"target", luaxtable_newtarget}, + {NULL, NULL} +}; + +static void luaxtable_release(void *private) +{ + luaxtable_t *xtable = (luaxtable_t *)private; + if (!xtable->runtime) + return; + + switch (xtable->type) { + case LUAXTABLE_TMATCH: + xt_unregister_match(&xtable->match); + break; + case LUAXTABLE_TTARGET: + xt_unregister_target(&xtable->target); + break; + } + + lunatik_putobject(xtable->runtime); + xtable->runtime = NULL; +} + +LUNATIK_NEWLIB(xtable, luaxtable_lib, &luaxtable_class, luanetfilter_flags); + +#define luaxtable_inithook(hook) (luaxtable_hooks.hook = luarcu_newtable(LUARCU_DEFAULT_SIZE, false)) +#define luaxtable_puthook(hook) (lunatik_putobject(luaxtable_hooks.hook)) + +static int __init luaxtable_init(void) +{ + if (luaxtable_inithook(match) == NULL) + goto err; + if (luaxtable_inithook(target) == NULL) + goto put; + return 0; +put: + luaxtable_puthook(match); +err: + return -ENOMEM; +} + +static void __exit luaxtable_exit(void) +{ + luaxtable_puthook(match); + luaxtable_puthook(target); +} + +module_init(luaxtable_init); +module_exit(luaxtable_exit); +MODULE_LICENSE("Dual MIT/GPL"); +MODULE_AUTHOR("Mohammad Shehar Yaar Tausif "); + diff --git a/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/lunatik_aux.c b/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lib/lunatik_aux.c new file mode 100644 index 0000000..e69de29 diff --git a/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lunatik_run.c b/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lunatik_run.c new file mode 100644 index 0000000..ee70e40 --- /dev/null +++ b/lunatik-3.6.2/.pc/fix-namespaced-symbols.patch/lunatik_run.c @@ -0,0 +1,45 @@ +/* +* SPDX-FileCopyrightText: (c) 2023-2024 Ring Zero Desenvolvimento de Software LTDA +* SPDX-License-Identifier: MIT OR GPL-2.0-only +*/ + + +#include + +#include +#include +#include + +#include "lunatik.h" +#include "lib/luarcu.h" + +MODULE_IMPORT_NS(LUNATIK); + +static lunatik_object_t *runtime; + +static int __init lunatik_run_init(void) +{ + int ret = 0; + + if ((lunatik_env = luarcu_newtable(LUARCU_DEFAULT_SIZE, false)) == NULL) + return -ENOMEM; + + if ((ret = lunatik_runtime(&runtime, "driver", true)) < 0) { + pr_err("couldn't create driver runtime\n"); + lunatik_putobject(lunatik_env); + } + + return ret; +} + +static void __exit lunatik_run_exit(void) +{ + lunatik_putobject(lunatik_env); + lunatik_stop(runtime); +} + +module_init(lunatik_run_init); +module_exit(lunatik_run_exit); +MODULE_LICENSE("Dual MIT/GPL"); +MODULE_AUTHOR("Lourival Vieira Neto "); + diff --git a/lunatik-3.6.2/Kbuild b/lunatik-3.6.2/Kbuild new file mode 100644 index 0000000..9bbcc68 --- /dev/null +++ b/lunatik-3.6.2/Kbuild @@ -0,0 +1,50 @@ +ifeq ($(ARCH), x86) + ifdef CONFIG_X86_32 + KLIBC_ARCH := i386 + asflags-y += -D_REGPARM + else + KLIBC_ARCH := x86_64 + endif +else + KLIBC_ARCH := $(ARCH) +endif + +KLIBC_USR := /klibc/usr +KLIBC_INC := $(KLIBC_USR)/include/arch/$(KLIBC_ARCH) + +LUNATIK_FLAGS := -D_LUNATIK -D_KERNEL -I${PWD}$(KLIBC_INC) + +asflags-y += $(LUNATIK_FLAGS) +ccflags-y += $(LUNATIK_FLAGS) -DLUNATIK_RUNTIME=$(CONFIG_LUNATIK_RUNTIME) \ + -Wimplicit-fallthrough=0 -I$(src) -I${PWD} -I${PWD}/include -I${PWD}/lua + +obj-$(CONFIG_LUNATIK) += lunatik.o + +lunatik-objs += lua/lapi.o lua/lcode.o lua/lctype.o lua/ldebug.o lua/ldo.o \ + lua/ldump.o lua/lfunc.o lua/lgc.o lua/llex.o lua/lmem.o \ + lua/lobject.o lua/lopcodes.o lua/lparser.o lua/lstate.o \ + lua/lstring.o lua/ltable.o lua/ltm.o \ + lua/lundump.o lua/lvm.o lua/lzio.o lua/lauxlib.o lua/lbaselib.o \ + lua/lcorolib.o lua/ldblib.o lua/lstrlib.o \ + lua/ltablib.o lua/lutf8lib.o lua/lmathlib.o lua/linit.o \ + lua/loadlib.o $(KLIBC_USR)/klibc/arch/$(KLIBC_ARCH)/setjmp.o \ + lunatik_aux.o lunatik_obj.o lunatik_core.o + +obj-$(CONFIG_LUNATIK_RUN) += lunatik_run.o + +obj-$(CONFIG_LUNATIK_DEVICE) += lib/luadevice.o +obj-$(CONFIG_LUNATIK_LINUX) += lib/lualinux.o +obj-$(CONFIG_LUNATIK_NOTIFIER) += lib/luanotifier.o +obj-$(CONFIG_LUNATIK_SOCKET) += lib/luasocket.o +obj-$(CONFIG_LUNATIK_RCU) += lib/luarcu.o +obj-$(CONFIG_LUNATIK_THREAD) += lib/luathread.o +obj-$(CONFIG_LUNATIK_FIB) += lib/luafib.o +obj-$(CONFIG_LUNATIK_DATA) += lib/luadata.o +obj-$(CONFIG_LUNATIK_PROBE) += lib/luaprobe.o +obj-$(CONFIG_LUNATIK_SYSCALL) += lib/luasyscall.o +obj-$(CONFIG_LUNATIK_XDP) += lib/luaxdp.o +obj-$(CONFIG_LUNATIK_FIFO) += lib/luafifo.o +obj-$(CONFIG_LUNATIK_XTABLE) += lib/luaxtable.o +obj-$(CONFIG_LUNATIK_NETFILTER) += lib/luanetfilter.o +obj-$(CONFIG_LUNATIK_COMPLETION) += lib/luacompletion.o + diff --git a/lunatik-3.6.2/LICENSE-GPL b/lunatik-3.6.2/LICENSE-GPL new file mode 100644 index 0000000..d159169 --- /dev/null +++ b/lunatik-3.6.2/LICENSE-GPL @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/lunatik-3.6.2/LICENSE-MIT b/lunatik-3.6.2/LICENSE-MIT new file mode 100644 index 0000000..01f5fc8 --- /dev/null +++ b/lunatik-3.6.2/LICENSE-MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023-2025 Ring Zero Desenvolvimento de Software LTDA + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lunatik-3.6.2/Makefile b/lunatik-3.6.2/Makefile new file mode 100644 index 0000000..6c1eaa4 --- /dev/null +++ b/lunatik-3.6.2/Makefile @@ -0,0 +1,131 @@ +# SPDX-FileCopyrightText: (c) 2023-2025 Ring Zero Desenvolvimento de Software LTDA +# SPDX-License-Identifier: MIT OR GPL-2.0-only + +KERNEL_RELEASE ?= ${shell uname -r} +MODULES_PATH := /lib/modules +MODULES_RELEASE_PATH := ${MODULES_PATH}/${KERNEL_RELEASE} +MODULES_ORDER_LIST := lunatik/lunatik.ko kernel/zfs/zfs.ko # needed for Ubuntu +MODULES_ORDER_FILE := ${MODULES_RELEASE_PATH}/modules.order +BTF_INSTALL_PATH = ${MODULES_RELEASE_PATH}/build +MODULES_BUILD_PATH ?= ${BTF_INSTALL_PATH} +MODULES_INSTALL_PATH := ${MODULES_RELEASE_PATH}/kernel +SCRIPTS_INSTALL_PATH := ${MODULES_PATH}/lua + + +LUNATIK_INSTALL_PATH = /usr/local/sbin +LUNATIK_EBPF_INSTALL_PATH = /usr/local/lib/bpf/lunatik +MOONTASTIK_RELEASE ?= v0.1c +LUA_API = lua/lua.h lua/lauxlib.h lua/lualib.h +RM = rm -f +MKDIR = mkdir -p -m 0755 +INSTALL = install -o root -g root + +all: lunatik_sym.h + ${MAKE} -C ${MODULES_BUILD_PATH} M=${PWD} CONFIG_LUNATIK=m \ + CONFIG_LUNATIK_RUN=m CONFIG_LUNATIK_RUNTIME=y CONFIG_LUNATIK_DEVICE=m \ + CONFIG_LUNATIK_LINUX=m CONFIG_LUNATIK_NOTIFIER=m CONFIG_LUNATIK_SOCKET=m \ + CONFIG_LUNATIK_RCU=m CONFIG_LUNATIK_THREAD=m CONFIG_LUNATIK_FIB=m \ + CONFIG_LUNATIK_DATA=m CONFIG_LUNATIK_PROBE=m CONFIG_LUNATIK_SYSCALL=m \ + CONFIG_LUNATIK_XDP=m CONFIG_LUNATIK_FIFO=m CONFIG_LUNATIK_XTABLE=m \ + CONFIG_LUNATIK_NETFILTER=m CONFIG_LUNATIK_COMPLETION=m + +clean: + ${MAKE} -C ${MODULES_BUILD_PATH} M=${PWD} clean + ${MAKE} -C examples/filter clean + ${RM} lunatik_sym.h + +scripts_install: + ${MKDIR} ${SCRIPTS_INSTALL_PATH} ${SCRIPTS_INSTALL_PATH}/lunatik + ${MKDIR} ${SCRIPTS_INSTALL_PATH} ${SCRIPTS_INSTALL_PATH}/socket + ${MKDIR} ${SCRIPTS_INSTALL_PATH} ${SCRIPTS_INSTALL_PATH}/syscall + ${INSTALL} -m 0644 driver.lua ${SCRIPTS_INSTALL_PATH}/ + ${INSTALL} -m 0644 lib/mailbox.lua ${SCRIPTS_INSTALL_PATH}/ + ${INSTALL} -m 0644 lib/net.lua ${SCRIPTS_INSTALL_PATH}/ + ${INSTALL} -m 0644 lib/lunatik/*.lua ${SCRIPTS_INSTALL_PATH}/lunatik + ${INSTALL} -m 0644 lib/socket/*.lua ${SCRIPTS_INSTALL_PATH}/socket + ${INSTALL} -m 0644 lib/syscall/*.lua ${SCRIPTS_INSTALL_PATH}/syscall + ${INSTALL} -m 0755 bin/lunatik ${LUNATIK_INSTALL_PATH} + +scripts_uninstall: + ${RM} ${SCRIPTS_INSTALL_PATH}/driver.lua + ${RM} ${SCRIPTS_INSTALL_PATH}/runner.lua + ${RM} ${SCRIPTS_INSTALL_PATH}/mailbox.lua + ${RM} ${SCRIPTS_INSTALL_PATH}/net.lua + ${RM} -r ${SCRIPTS_INSTALL_PATH}/lunatik + ${RM} -r ${SCRIPTS_INSTALL_PATH}/socket + ${RM} -r ${SCRIPTS_INSTALL_PATH}/syscall + ${RM} ${LUNATIK_INSTALL_PATH}/lunatik + +.PHONY: ebpf +ebpf: + ${MAKE} -C examples/filter + +ebpf_install: + ${MKDIR} ${LUNATIK_EBPF_INSTALL_PATH} + ${INSTALL} -m 0644 examples/filter/https.o ${LUNATIK_EBPF_INSTALL_PATH}/ + +ebpf_uninstall: + ${RM} -r ${LUNATIK_EBPF_INSTALL_PATH} + +examples_install: + ${MKDIR} ${SCRIPTS_INSTALL_PATH}/examples + ${INSTALL} -m 0644 examples/*.lua ${SCRIPTS_INSTALL_PATH}/examples + ${MKDIR} ${SCRIPTS_INSTALL_PATH}/examples/echod + ${INSTALL} -m 0644 examples/echod/*.lua ${SCRIPTS_INSTALL_PATH}/examples/echod + ${MKDIR} ${SCRIPTS_INSTALL_PATH}/examples/filter + ${INSTALL} -m 0644 examples/filter/*.lua ${SCRIPTS_INSTALL_PATH}/examples/filter + ${MKDIR} ${SCRIPTS_INSTALL_PATH}/examples/dnsblock + ${INSTALL} -m 0644 examples/dnsblock/*.lua ${SCRIPTS_INSTALL_PATH}/examples/dnsblock + ${MKDIR} ${SCRIPTS_INSTALL_PATH}/examples/dnsdoctor + ${INSTALL} -m 0644 examples/dnsdoctor/*.lua ${SCRIPTS_INSTALL_PATH}/examples/dnsdoctor + +examples_uninstall: + ${RM} -r ${SCRIPTS_INSTALL_PATH}/examples + +tests_install: + ${MKDIR} ${SCRIPTS_INSTALL_PATH}/tests + ${MKDIR} ${SCRIPTS_INSTALL_PATH}/tests/rcumap_sync + ${INSTALL} -m 0644 tests/rcumap_sync/*.lua ${SCRIPTS_INSTALL_PATH}/tests/rcumap_sync + +tests_uninstall: + ${RM} -r ${SCRIPTS_INSTALL_PATH}/tests + +modules_install: + ${MKDIR} ${MODULES_INSTALL_PATH}/lunatik + ${INSTALL} -m 0644 *.ko lib/*.ko ${MODULES_INSTALL_PATH}/lunatik + +btf_install: + cp /sys/kernel/btf/vmlinux ${BTF_INSTALL_PATH} + +modules_uninstall: + ${RM} -r ${MODULES_INSTALL_PATH}/lunatik + +install: scripts_install modules_install + for mod in $(MODULES_ORDER_LIST); do \ + grep -qxF "$$mod" $(MODULES_ORDER_FILE) || echo "$$mod" >> $(MODULES_ORDER_FILE); \ + done + depmod -a + +uninstall: scripts_uninstall modules_uninstall + for mod in $(MODULES_ORDER_LIST); do \ + sed -i "\|^$$mod$$|d" $(MODULES_ORDER_FILE); \ + done + depmod -a + +lunatik_sym.h: $(LUA_API) gensymbols.sh + ${shell ./gensymbols.sh $(LUA_API) > lunatik_sym.h} + +moontastik_install_%: + [ $* ] || (echo "usage: make moontastik_install_TARGET" ; exit 1) + wget https://github.com/luainkernel/moontastik/releases/download/${MOONTASTIK_RELEASE}/moontastik_lua.zip -O moontastik_lua.zip + [ -d moontastik_lua ] && ${RM} -r moontastik_lua || true + unzip moontastik_lua.zip + cd moontastik_lua/"$*" && ./install.sh ; cd - + +moontastik_uninstall_%: + [ $* ] || (echo "usage: make moontastik_uninstall_TARGET" ; exit 1) + ${RM} -r ${SCRIPTS_INSTALL_PATH}/$* + +doc-site: + ldoc . + diff --git a/lunatik-3.6.2/README.md b/lunatik-3.6.2/README.md new file mode 100644 index 0000000..2dd1151 --- /dev/null +++ b/lunatik-3.6.2/README.md @@ -0,0 +1,1718 @@ +# Lunatik + +Lunatik is a framework for scripting the Linux kernel with [Lua](https://www.lua.org/). +It is composed by the Lua interpreter modified to run in the kernel; +a [device driver](driver.lua) (written in Lua =)) and a [command line tool](bin/lunatik) +to load and run scripts and manage runtime environments from the user space; +a [C API](#lunatik-c-api) to load and run scripts and manage runtime environments from the kernel; +and [Lua APIs](#lunatik-lua-apis) for binding kernel facilities to Lua scripts. + +Here is an example of a character device driver written in Lua using Lunatik +to generate random ASCII printable characters: +```Lua +-- /lib/modules/lua/passwd.lua +-- +-- implements /dev/passwd for generate passwords +-- usage: $ sudo lunatik run passwd +-- $ head -c /dev/passwd + +local device = require("device") +local linux = require("linux") + +local function nop() end -- do nothing + +local s = linux.stat +local driver = {name = "passwd", open = nop, release = nop, mode = s.IRUGO} + +function driver:read() -- read(2) callback + -- generate random ASCII printable characters + return string.char(linux.random(32, 126)) +end + +-- creates a new character device +device.new(driver) +``` + +## Setup + +Install dependencies (here for Debian/Ubuntu, to be adapted to one's distribution): + +```sh +sudo apt install git build-essential lua5.4 dwarves clang llvm libelf-dev linux-headers-$(uname -r) linux-tools-common linux-tools-$(uname -r) pkg-config libpcap-dev m4 +``` + +Install dependencies (here for Arch Linux): + +```sh +sudo pacman -S git lua clang llvm m4 libpcap pkg-config build2 linux-tools linux-headers +``` + +Compile and install `lunatik`: + +```sh +LUNATIK_DIR=~/lunatik # to be adapted +mkdir "${LUNATIK_DIR}" ; cd "${LUNATIK_DIR}" +git clone --depth 1 --recurse-submodules https://github.com/luainkernel/lunatik.git +cd lunatik +make +sudo make install +``` + +Once done, the `debian_kernel_postinst_lunatik.sh` script from tools/ may be copied into +`/etc/kernel/postinst.d/`: this ensures `lunatik` (and also the `xdp` needed libs) will get +compiled on kernel upgrade. + +### OpenWRT + +Install Lunatik from our [package feed](https://github.com/luainkernel/openwrt_feed/tree/openwrt-23.05). + +## Usage + +``` +sudo lunatik # execute Lunatik REPL +Lunatik 3.6 Copyright (C) 2023-2025 ring-0 Ltda. +> return 42 -- execute this line in the kernel +42 +``` + +### lunatik + +```Shell +usage: lunatik [load|unload|reload|status|list] [run|spawn|stop