liminix/pkgs/nellie/nellie.c
2024-04-14 22:45:29 +01:00

90 lines
1.8 KiB
C

#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <linux/netlink.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int l_close_socket(lua_State *L) {
lua_getfield(L, 1, "fileno");
int fd = (int) lua_tointeger(L, -1);
close(fd);
return 0;
}
static int l_read_from_socket(lua_State *L) {
int length = 32;
if(lua_isnumber(L, 2))
length = lua_tointeger(L, 2);
lua_getfield(L, 1, "fileno");
int fd = (int) lua_tointeger(L, -1);
char *buf = (char *) malloc(length);
int bytes = recv(fd, buf, length, 0);
if(bytes > 0) {
lua_pushlstring(L, buf, bytes);
free(buf);
return 1;
} else {
free(buf);
return 0;
}
}
static int l_open_socket(lua_State *L) {
int netlink_fd = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT);
struct sockaddr_nl sa;
memset(&sa, 0, sizeof(sa));
sa.nl_family = AF_NETLINK;
sa.nl_pid = getpid();
if(lua_isnumber(L, 1)) {
sa.nl_groups = lua_tointeger(L, 1);
lua_pop(L, 1);
}
else {
sa.nl_groups = 4; /* group 4 is rebroadcasts from mdevd */
}
if(bind(netlink_fd, (struct sockaddr *) &sa, sizeof(sa))==0) {
lua_newtable(L);
lua_pushliteral(L, "fileno");
lua_pushinteger(L, netlink_fd);
lua_settable(L, 1);
lua_pushliteral(L, "read");
lua_pushcfunction(L, l_read_from_socket);
lua_settable(L, 1);
lua_pushliteral(L, "close");
lua_pushcfunction(L, l_close_socket);
lua_settable(L, 1);
return 1;
} else {
return 0;
}
}
static const struct luaL_Reg funcs [] = {
{"open", l_open_socket},
{NULL, NULL} /* sentinel */
};
/* "luaopen_" prefix is magic and tells lua to run this function
* when it dlopens the library
*/
int luaopen_nellie (lua_State *L) {
luaL_newlib(L, funcs);
return 1;
}