diff --git a/src/makefile b/src/makefile index 522d378..1b84429 100755 --- a/src/makefile +++ b/src/makefile @@ -173,7 +173,7 @@ SOCKET_macosx=usocket.o SO_linux=so O_linux=o CC_linux=gcc -DEF_linux=-DLUASOCKET_$(DEBUG) +DEF_linux=-DLUASOCKET_$(DEBUG) -D_GNU_SOURCE CFLAGS_linux=$(LUAINC:%=-I%) $(DEF) -Wall -Wshadow -Wextra \ -Wimplicit -O2 -ggdb3 -fpic LDFLAGS_linux=-O -shared -fpic -o diff --git a/src/options.c b/src/options.c index 06ab58d..f0d8f47 100644 --- a/src/options.c +++ b/src/options.c @@ -234,6 +234,35 @@ int opt_get_ip6_multicast_loop(lua_State *L, p_socket ps) return opt_getboolean(L, ps, IPPROTO_IPV6, IPV6_MULTICAST_LOOP); } +// ------------------------------------------------------- +#ifndef _WIN32 +int opt_set_passcred(lua_State *L, p_socket ps) +{ + return opt_setboolean(L, ps, SOL_SOCKET, SO_PASSCRED); +} + +int opt_get_passcred(lua_State *L, p_socket ps) +{ + return opt_getboolean(L, ps, SOL_SOCKET, SO_PASSCRED); +} + +int opt_get_peercred(lua_State *L, p_socket ps) +{ + struct ucred cred; + int len = sizeof(cred); + int err = opt_get(L, ps, SOL_SOCKET, SO_PEERCRED, (char *) &cred, &len); + if (err < 0) + return err; + lua_newtable(L); + lua_pushinteger(L, (long) cred.pid); + lua_setfield(L, -2, "pid"); + lua_pushinteger(L, (long) cred.uid); + lua_setfield(L, -2, "uid"); + lua_pushinteger(L, (long) cred.gid); + lua_setfield(L, -2, "gid"); + return 1; +} +#endif // ------------------------------------------------------- int opt_set_linger(lua_State *L, p_socket ps) { diff --git a/src/options.h b/src/options.h index 41f7337..bf181d7 100644 --- a/src/options.h +++ b/src/options.h @@ -93,6 +93,12 @@ int opt_set_ip6_drop_membersip(lua_State *L, p_socket ps); int opt_set_ip6_v6only(lua_State *L, p_socket ps); int opt_get_ip6_v6only(lua_State *L, p_socket ps); +#ifndef _WIN32 +int opt_set_passcred(lua_State *L, p_socket ps); +int opt_get_passcred(lua_State *L, p_socket ps); +int opt_get_peercred(lua_State *L, p_socket ps); +#endif + int opt_get_error(lua_State *L, p_socket ps); #ifndef _WIN32 diff --git a/src/unixstream.c b/src/unixstream.c index 02aced9..3fa2fc2 100644 --- a/src/unixstream.c +++ b/src/unixstream.c @@ -25,6 +25,7 @@ static int meth_receive(lua_State *L); static int meth_accept(lua_State *L); static int meth_close(lua_State *L); static int meth_setoption(lua_State *L); +static int meth_getoption(lua_State *L); static int meth_settimeout(lua_State *L); static int meth_getfd(lua_State *L); static int meth_setfd(lua_State *L); @@ -33,8 +34,8 @@ static int meth_getstats(lua_State *L); static int meth_setstats(lua_State *L); static int meth_getsockname(lua_State *L); -static const char *unixstream_tryconnect(p_unix un, const char *path); -static const char *unixstream_trybind(p_unix un, const char *path); +static const char *unixstream_tryconnect(p_unix un, const char *path, size_t pathlen); +static const char *unixstream_trybind(p_unix un, const char *path, size_t pathlen); /* unixstream object methods */ static luaL_Reg unixstream_methods[] = { @@ -58,6 +59,9 @@ static luaL_Reg unixstream_methods[] = { {"getsockname", meth_getsockname}, {"settimeout", meth_settimeout}, {"shutdown", meth_shutdown}, +#ifndef _WIN32 + {"getoption", meth_getoption}, +#endif {NULL, NULL} }; @@ -66,6 +70,9 @@ static t_opt optset[] = { {"keepalive", opt_set_keepalive}, {"reuseaddr", opt_set_reuseaddr}, {"linger", opt_set_linger}, +#ifndef _WIN32 + {"passcred", opt_set_passcred}, +#endif {NULL, NULL} }; @@ -75,6 +82,14 @@ static luaL_Reg func[] = { {NULL, NULL} }; +#ifndef _WIN32 + +static t_opt optget[] = { + {"passcred", opt_get_passcred}, + {"peercred", opt_get_peercred}, + {NULL, NULL} +}; +#endif /*-------------------------------------------------------------------------*\ * Initializes module \*-------------------------------------------------------------------------*/ @@ -128,6 +143,11 @@ static int meth_setoption(lua_State *L) { return opt_meth_setoption(L, optset, &un->sock); } +static int meth_getoption(lua_State *L) { + p_unix un = (p_unix) auxiliar_checkgroup(L, "unixstream{any}", 1); + return opt_meth_getoption(L, optget, &un->sock); +} + /*-------------------------------------------------------------------------*\ * Select support methods \*-------------------------------------------------------------------------*/ @@ -181,13 +201,12 @@ static int meth_accept(lua_State *L) { /*-------------------------------------------------------------------------*\ * Binds an object to an address \*-------------------------------------------------------------------------*/ -static const char *unixstream_trybind(p_unix un, const char *path) { +static const char *unixstream_trybind(p_unix un, const char *path, size_t pathlen) { struct sockaddr_un local; - size_t len = strlen(path); int err; - if (len >= sizeof(local.sun_path)) return "path too long"; + if (pathlen >= sizeof(local.sun_path)) return "path too long"; memset(&local, 0, sizeof(local)); - strcpy(local.sun_path, path); + memcpy(local.sun_path, path, pathlen); local.sun_family = AF_UNIX; #ifdef UNIX_HAS_SUN_LEN local.sun_len = sizeof(local.sun_family) + sizeof(local.sun_len) @@ -196,7 +215,7 @@ static const char *unixstream_trybind(p_unix un, const char *path) { #else err = socket_bind(&un->sock, (SA *) &local, - sizeof(local.sun_family) + len); + sizeof(local.sun_family) + pathlen); #endif if (err != IO_DONE) socket_destroy(&un->sock); return socket_strerror(err); @@ -204,8 +223,9 @@ static const char *unixstream_trybind(p_unix un, const char *path) { static int meth_bind(lua_State *L) { p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1); - const char *path = luaL_checkstring(L, 2); - const char *err = unixstream_trybind(un, path); + size_t len = 0; + const char *path = luaL_checklstring(L, 2, &len); + const char *err = unixstream_trybind(un, path, len); if (err) { lua_pushnil(L); lua_pushstring(L, err); @@ -234,23 +254,22 @@ static int meth_getsockname(lua_State *L) /*-------------------------------------------------------------------------*\ * Turns a master unixstream object into a client object. \*-------------------------------------------------------------------------*/ -static const char *unixstream_tryconnect(p_unix un, const char *path) +static const char *unixstream_tryconnect(p_unix un, const char *path, size_t pathlen) { struct sockaddr_un remote; int err; - size_t len = strlen(path); - if (len >= sizeof(remote.sun_path)) return "path too long"; + if (pathlen >= sizeof(remote.sun_path)) return "path too long"; memset(&remote, 0, sizeof(remote)); - strcpy(remote.sun_path, path); + memcpy(remote.sun_path, path, pathlen); remote.sun_family = AF_UNIX; timeout_markstart(&un->tm); #ifdef UNIX_HAS_SUN_LEN remote.sun_len = sizeof(remote.sun_family) + sizeof(remote.sun_len) - + len + 1; + + pathlen + 1; err = socket_connect(&un->sock, (SA *) &remote, remote.sun_len, &un->tm); #else err = socket_connect(&un->sock, (SA *) &remote, - sizeof(remote.sun_family) + len, &un->tm); + sizeof(remote.sun_family) + pathlen, &un->tm); #endif if (err != IO_DONE) socket_destroy(&un->sock); return socket_strerror(err); @@ -259,8 +278,10 @@ static const char *unixstream_tryconnect(p_unix un, const char *path) static int meth_connect(lua_State *L) { p_unix un = (p_unix) auxiliar_checkclass(L, "unixstream{master}", 1); - const char *path = luaL_checkstring(L, 2); - const char *err = unixstream_tryconnect(un, path); + size_t len = 0; + + const char *path = luaL_checklstring(L, 2, &len); + const char *err = unixstream_tryconnect(un, path, len); if (err) { lua_pushnil(L); lua_pushstring(L, err);