diff --git a/lib/flua/libjail/jail.3lua b/lib/flua/libjail/jail.3lua index aa1e0ec49616..a0cb7ae1381e 100644 --- a/lib/flua/libjail/jail.3lua +++ b/lib/flua/libjail/jail.3lua @@ -1,257 +1,279 @@ .\" .\" SPDX-License-Identifier: BSD-2-Clause-FreeBSD .\" .\" Copyright (c) 2020, Ryan Moeller .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" .\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" $FreeBSD$ .\" .Dd October 24, 2020 .Dt JAIL 3lua .Os .Sh NAME +.Nm attach , .Nm getid , .Nm getname , .Nm list , .Nm allparams , .Nm getparams , +.Nm remove , .Nm setparams , .Nm CREATE , .Nm UPDATE , .Nm ATTACH , .Nm DYING .Nd Lua binding to .Xr jail 3 .Sh SYNOPSIS .Bd -literal local jail = require('jail') .Ed .Pp .Bl -tag -width XXXX -compact +.It Dv ok, err = jail.attach(jid|name) .It Dv jid, err = jail.getid(name) .It Dv name, err = jail.getname(jid) .It Dv params, err = jail.allparams() .It Dv iter, jail_obj = jail.list([params]) .It Dv jid, res = jail.getparams(jid|name, params [, flags ] ) +.It Dv ok, err = jail.remove(jid|name) .It Dv jid, err = jail.setparams(jid|name, params, flags ) .It Dv jail.CREATE .It Dv jail.UPDATE .It Dv jail.ATTACH .It Dv jail.DYING .El .Sh DESCRIPTION The .Nm jail module is a binding to the .Xr jail 3 library. It provides a string-oriented interface for the .Xr jail_get 2 and .Xr jail_set 2 system calls. .Bl -tag -width XXXX +.It Dv ok, err = jail.attach(jid|name) +Attach to the given jail, identified by an integer +.Fa jid +or the +.Fa name . .It Dv jid, err = jail.getid(name) Get the jail identifier .Pq jid as an integer. .Fa name is the name of a jail or a jid in the form of a string. .It Dv name, err = jail.getname(jid) Get the name of a jail as a string for the given .Fa jid .Pq an integer . .It Dv iter, jail_obj = jail.list([params]) Returns an iterator over running jails on the system. .Dv params is a list of parameters to fetch for each jail as we iterate. .Dv jid and .Dv name will always be returned, and may be omitted from .Dv params . Additionally, .Dv params may be omitted or an empty table, but not nil. .Pp See .Sx EXAMPLES . .It Dv params, err = jail.allparams() Get a list of all supported parameter names .Pq as strings . See .Xr jail 8 for descriptions of the core jail parameters. .It Dv jid, res = jail.getparams(jid|name, params [, flags ] ) Get a table of the requested parameters for the given jail. .Nm jid|name can either be the jid as an integer or the jid or name as a string. .Nm params is a list of parameter names. .Nm flags is an optional integer representing the flag bits to apply for the operation. See the list of flags below. Only the .Dv DYING flag is valid to set. +.It Dv ok, err = jail.remove(jid|name) +Remove the given jail, identified by an integer +.Fa jid +or the +.Fa name . .It Dv jid, err = jail.setparams(jid|name, params [, flags ] ) Set parameters for a given jail. This is used to create, update, attach to, or destroy a jail. .Nm jid|name can either be the jid as an integer or the jid or name as a string. .Nm params is a table of parameters to apply to the jail, where each key in the table is a parameter name as a string and each value is a string that will be converted to the internal value type by .Xr jailparam_import 3 . .Nm flags is an optional integer representing the flag bits to apply for the operation. See the list of flags below. .El .Pp The .Nm flags arguments are an integer bitwise-or combination of one or more of the following flags: .Bl -tag -width XXXX .It Dv jail.CREATE Used with .Fn setparams to create a new jail. The jail must not already exist, unless combined with .Dv UPDATE . .It Dv jail.UPDATE Used with .Fn setparams to modify an existing jail. The jail must already exist, unless combined with .Dv CREATE . .It Dv jail.ATTACH Used with .Fn setparams in combination with .Dv CREATE or .Dv UPDATE to attach the current process to a jail. .It Dv jail.DYING Allow operating on a jail that is in the process of being removed. .El .Sh RETURN VALUES The .Fn getid and .Fn setparams functions return a jail identifier integer on success, or .Dv nil and an error message string if an error occurred. .Pp The .Fn getname function returns a jail name string on success, or .Dv nil and an error message string if an error occurred. .Pp The .Fn allparams function returns a list of parameter name strings on success, or .Dv nil and an error message string if an error occurred. .Pp The .Fn getparams function returns a jail identifier integer and a table of jail parameters with parameter name strings as keys and strings for values on success, or .Dv nil and an error message string if an error occurred. .Pp The .Fn list function returns an iterator over the list of running jails. +.Pp +The +.Fn attach +and +.Fn remove +functions return true on success, or +.Dv nil +and an error message string if an error occurred. .Sh EXAMPLES Set the hostname of jail .Dq foo to .Dq foo.bar : .Bd -literal -offset indent local jail = require('jail') jid, err = jail.setparams("foo", {["host.hostname"]="foo.bar"}, jail.UPDATE) if not jid then error(err) end .Ed .Pp Retrieve the hostname of jail .Dq foo : .Bd -literal -offset indent local jail = require('jail') jid, res = jail.getparams("foo", {"host.hostname"}) if not jid then error(res) end print(res["host.hostname"]) .Ed .Pp Iterate over jails on the system: .Bd -literal -offset indent local jail = require('jail') -- Recommended: just loop over it for jparams in jail.list() do print(jparams["jid"] .. " = " .. jparams["name"]) end -- Request path and hostname, too for jparams in jail.list({"path", "host.hostname"}) do print(jparams["host.hostname"] .. " mounted at " .. jparams["path"]) end -- Raw iteration protocol local iter, jail_obj = jail.list() -- Request the first params local jparams = jail_obj:next() while jparams do print(jparams["jid"] .. " = " .. jparams["name"]) -- Subsequent calls may return nil jparams = jail_obj:next() end .Ed .Sh SEE ALSO .Xr jail 2 , .Xr jail 3 , .Xr jail 8 .Sh HISTORY The .Nm jail Lua module for flua first appeared in .Fx 13.0 . .Sh AUTHORS .An Ryan Moeller , with inspiration from .Nx gpio(3lua), by .An Mark Balmer . diff --git a/lib/flua/libjail/lua_jail.c b/lib/flua/libjail/lua_jail.c index 7bb0e13cceea..025694bf1181 100644 --- a/lib/flua/libjail/lua_jail.c +++ b/lib/flua/libjail/lua_jail.c @@ -1,641 +1,715 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2020, Ryan Moeller * Copyright (c) 2020, Kyle Evans * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #define JAIL_METATABLE "jail iterator metatable" /* * Taken from RhodiumToad's lspawn implementation, let static analyzers make * better decisions about the behavior after we raise an error. */ #if defined(LUA_VERSION_NUM) && defined(LUA_API) LUA_API int (lua_error) (lua_State *L) __dead2; #endif #if defined(LUA_ERRFILE) && defined(LUALIB_API) LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg) __dead2; LUALIB_API int (luaL_typeerror) (lua_State *L, int arg, const char *tname) __dead2; LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...) __dead2; #endif int luaopen_jail(lua_State *); typedef bool (*getparam_filter)(const char *, void *); static void getparam_table(lua_State *L, int paramindex, struct jailparam *params, size_t paramoff, size_t *params_countp, getparam_filter keyfilt, void *udata); struct l_jail_iter { struct jailparam *params; size_t params_count; int jid; }; static bool l_jail_filter(const char *param_name, void *data __unused) { /* * Allowing lastjid will mess up our iteration over all jails on the * system, as this is a special paramter that indicates where the search * starts from. We'll always add jid and name, so just silently remove * these. */ return (strcmp(param_name, "lastjid") != 0 && strcmp(param_name, "jid") != 0 && strcmp(param_name, "name") != 0); } static int l_jail_iter_next(lua_State *L) { struct l_jail_iter *iter, **iterp; struct jailparam *jp; int serrno; iterp = (struct l_jail_iter **)luaL_checkudata(L, 1, JAIL_METATABLE); iter = *iterp; luaL_argcheck(L, iter != NULL, 1, "closed jail iterator"); jp = iter->params; /* Populate lastjid; we must keep it in params[0] for our sake. */ if (jailparam_import_raw(&jp[0], &iter->jid, sizeof(iter->jid))) { jailparam_free(jp, iter->params_count); free(jp); free(iter); *iterp = NULL; return (luaL_error(L, "jailparam_import_raw: %s", jail_errmsg)); } /* The list of requested params was populated back in l_list(). */ iter->jid = jailparam_get(jp, iter->params_count, 0); if (iter->jid == -1) { /* * We probably got an ENOENT to signify the end of the jail * listing, but just in case we didn't; stash it off and start * cleaning up. We'll handle non-ENOENT errors later. */ serrno = errno; jailparam_free(jp, iter->params_count); free(iter->params); free(iter); *iterp = NULL; if (serrno != ENOENT) return (luaL_error(L, "jailparam_get: %s", strerror(serrno))); return (0); } /* * Finally, we'll fill in the return table with whatever parameters the * user requested, in addition to the ones we forced with exception to * lastjid. */ lua_newtable(L); for (size_t i = 0; i < iter->params_count; ++i) { char *value; jp = &iter->params[i]; if (strcmp(jp->jp_name, "lastjid") == 0) continue; value = jailparam_export(jp); lua_pushstring(L, value); lua_setfield(L, -2, jp->jp_name); free(value); } return (1); } static int l_jail_iter_close(lua_State *L) { struct l_jail_iter *iter, **iterp; /* * Since we're using this as the __gc method as well, there's a good * chance that it's already been cleaned up by iterating to the end of * the list. */ iterp = (struct l_jail_iter **)lua_touserdata(L, 1); iter = *iterp; if (iter == NULL) return (0); jailparam_free(iter->params, iter->params_count); free(iter->params); free(iter); *iterp = NULL; return (0); } static int l_list(lua_State *L) { struct l_jail_iter *iter; int nargs; nargs = lua_gettop(L); if (nargs >= 1) luaL_checktype(L, 1, LUA_TTABLE); iter = malloc(sizeof(*iter)); if (iter == NULL) return (luaL_error(L, "malloc: %s", strerror(errno))); /* * lastjid, jid, name + length of the table. This may be too much if * we have duplicated one of those fixed parameters. */ iter->params_count = 3 + (nargs != 0 ? lua_rawlen(L, 1) : 0); iter->params = malloc(iter->params_count * sizeof(*iter->params)); if (iter->params == NULL) { free(iter); return (luaL_error(L, "malloc params: %s", strerror(errno))); } /* The :next() method will populate lastjid before jail_getparam(). */ if (jailparam_init(&iter->params[0], "lastjid") == -1) { free(iter->params); free(iter); return (luaL_error(L, "jailparam_init: %s", jail_errmsg)); } /* These two will get populated by jail_getparam(). */ if (jailparam_init(&iter->params[1], "jid") == -1) { jailparam_free(iter->params, 1); free(iter->params); free(iter); return (luaL_error(L, "jailparam_init: %s", jail_errmsg)); } if (jailparam_init(&iter->params[2], "name") == -1) { jailparam_free(iter->params, 2); free(iter->params); free(iter); return (luaL_error(L, "jailparam_init: %s", jail_errmsg)); } /* * We only need to process additional arguments if we were given any. * That is, we don't descend into getparam_table if we're passed nothing * or an empty table. */ iter->jid = 0; if (iter->params_count != 3) getparam_table(L, 1, iter->params, 2, &iter->params_count, l_jail_filter, NULL); /* * Part of the iterator magic. We give it an iterator function with a * metatable defining next() and close() that can be used for manual * iteration. iter->jid is how we track which jail we last iterated, to * be supplied as "lastjid". */ lua_pushcfunction(L, l_jail_iter_next); *(struct l_jail_iter **)lua_newuserdata(L, sizeof(struct l_jail_iter **)) = iter; luaL_getmetatable(L, JAIL_METATABLE); lua_setmetatable(L, -2); return (2); } static void register_jail_metatable(lua_State *L) { luaL_newmetatable(L, JAIL_METATABLE); lua_newtable(L); lua_pushcfunction(L, l_jail_iter_next); lua_setfield(L, -2, "next"); lua_pushcfunction(L, l_jail_iter_close); lua_setfield(L, -2, "close"); lua_setfield(L, -2, "__index"); lua_pushcfunction(L, l_jail_iter_close); lua_setfield(L, -2, "__gc"); lua_pop(L, 1); } static int l_getid(lua_State *L) { const char *name; int jid; name = luaL_checkstring(L, 1); jid = jail_getid(name); if (jid == -1) { lua_pushnil(L); lua_pushstring(L, jail_errmsg); return (2); } lua_pushinteger(L, jid); return (1); } static int l_getname(lua_State *L) { char *name; int jid; jid = luaL_checkinteger(L, 1); name = jail_getname(jid); if (name == NULL) { lua_pushnil(L); lua_pushstring(L, jail_errmsg); return (2); } lua_pushstring(L, name); free(name); return (1); } static int l_allparams(lua_State *L) { struct jailparam *params; int params_count; params_count = jailparam_all(¶ms); if (params_count == -1) { lua_pushnil(L); lua_pushstring(L, jail_errmsg); return (2); } lua_newtable(L); for (int i = 0; i < params_count; ++i) { lua_pushstring(L, params[i].jp_name); lua_rawseti(L, -2, i + 1); } jailparam_free(params, params_count); free(params); return (1); } static void getparam_table(lua_State *L, int paramindex, struct jailparam *params, size_t params_off, size_t *params_countp, getparam_filter keyfilt, void *udata) { size_t params_count; int skipped; params_count = *params_countp; skipped = 0; for (size_t i = 1 + params_off; i < params_count; ++i) { const char *param_name; lua_rawgeti(L, -1, i - params_off); param_name = lua_tostring(L, -1); if (param_name == NULL) { jailparam_free(params, i - skipped); free(params); luaL_argerror(L, paramindex, "param names must be strings"); } lua_pop(L, 1); if (keyfilt != NULL && !keyfilt(param_name, udata)) { ++skipped; continue; } if (jailparam_init(¶ms[i - skipped], param_name) == -1) { jailparam_free(params, i - skipped); free(params); luaL_error(L, "jailparam_init: %s", jail_errmsg); } } *params_countp -= skipped; } struct getparams_filter_args { int filter_type; }; static bool l_getparams_filter(const char *param_name, void *udata) { struct getparams_filter_args *gpa; gpa = udata; /* Skip name or jid, whichever was given. */ if (gpa->filter_type == LUA_TSTRING) { if (strcmp(param_name, "name") == 0) return (false); } else /* type == LUA_TNUMBER */ { if (strcmp(param_name, "jid") == 0) return (false); } return (true); } static int l_getparams(lua_State *L) { const char *name; struct jailparam *params; size_t params_count; struct getparams_filter_args gpa; int flags, jid, type; type = lua_type(L, 1); luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1, "expected a jail name (string) or id (integer)"); luaL_checktype(L, 2, LUA_TTABLE); params_count = 1 + lua_rawlen(L, 2); flags = luaL_optinteger(L, 3, 0); params = malloc(params_count * sizeof(struct jailparam)); if (params == NULL) return (luaL_error(L, "malloc: %s", strerror(errno))); /* * Set the jail name or id param as determined by the first arg. */ if (type == LUA_TSTRING) { if (jailparam_init(¶ms[0], "name") == -1) { free(params); return (luaL_error(L, "jailparam_init: %s", jail_errmsg)); } name = lua_tostring(L, 1); if (jailparam_import(¶ms[0], name) == -1) { jailparam_free(params, 1); free(params); return (luaL_error(L, "jailparam_import: %s", jail_errmsg)); } } else /* type == LUA_TNUMBER */ { if (jailparam_init(¶ms[0], "jid") == -1) { free(params); return (luaL_error(L, "jailparam_init: %s", jail_errmsg)); } jid = lua_tointeger(L, 1); if (jailparam_import_raw(¶ms[0], &jid, sizeof(jid)) == -1) { jailparam_free(params, 1); free(params); return (luaL_error(L, "jailparam_import_raw: %s", jail_errmsg)); } } /* * Set the remaining param names being requested. */ gpa.filter_type = type; getparam_table(L, 2, params, 0, ¶ms_count, l_getparams_filter, &gpa); /* * Get the values and convert to a table. */ jid = jailparam_get(params, params_count, flags); if (jid == -1) { jailparam_free(params, params_count); free(params); lua_pushnil(L); lua_pushstring(L, jail_errmsg); return (2); } lua_pushinteger(L, jid); lua_newtable(L); for (size_t i = 0; i < params_count; ++i) { char *value; value = jailparam_export(¶ms[i]); lua_pushstring(L, value); free(value); lua_setfield(L, -2, params[i].jp_name); } jailparam_free(params, params_count); free(params); return (2); } static int l_setparams(lua_State *L) { const char *name; struct jailparam *params; size_t params_count; int flags, jid, type; type = lua_type(L, 1); luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1, "expected a jail name (string) or id (integer)"); luaL_checktype(L, 2, LUA_TTABLE); lua_pushnil(L); for (params_count = 1; lua_next(L, 2) != 0; ++params_count) lua_pop(L, 1); flags = luaL_optinteger(L, 3, 0); params = malloc(params_count * sizeof(struct jailparam)); if (params == NULL) return (luaL_error(L, "malloc: %s", strerror(errno))); /* * Set the jail name or id param as determined by the first arg. */ if (type == LUA_TSTRING) { if (jailparam_init(¶ms[0], "name") == -1) { free(params); return (luaL_error(L, "jailparam_init: %s", jail_errmsg)); } name = lua_tostring(L, 1); if (jailparam_import(¶ms[0], name) == -1) { jailparam_free(params, 1); free(params); return (luaL_error(L, "jailparam_import: %s", jail_errmsg)); } } else /* type == LUA_TNUMBER */ { if (jailparam_init(¶ms[0], "jid") == -1) { free(params); return (luaL_error(L, "jailparam_init: %s", jail_errmsg)); } jid = lua_tointeger(L, 1); if (jailparam_import_raw(¶ms[0], &jid, sizeof(jid)) == -1) { jailparam_free(params, 1); free(params); return (luaL_error(L, "jailparam_import_raw: %s", jail_errmsg)); } } /* * Set the rest of the provided params. */ lua_pushnil(L); for (size_t i = 1; i < params_count && lua_next(L, 2) != 0; ++i) { const char *value; name = lua_tostring(L, -2); if (name == NULL) { jailparam_free(params, i); free(params); return (luaL_argerror(L, 2, "param names must be strings")); } if (jailparam_init(¶ms[i], name) == -1) { jailparam_free(params, i); free(params); return (luaL_error(L, "jailparam_init: %s", jail_errmsg)); } value = lua_tostring(L, -1); if (value == NULL) { jailparam_free(params, i + 1); free(params); return (luaL_argerror(L, 2, "param values must be strings")); } if (jailparam_import(¶ms[i], value) == -1) { jailparam_free(params, i + 1); free(params); return (luaL_error(L, "jailparam_import: %s", jail_errmsg)); } lua_pop(L, 1); } /* * Attempt to set the params. */ jid = jailparam_set(params, params_count, flags); if (jid == -1) { jailparam_free(params, params_count); free(params); lua_pushnil(L); lua_pushstring(L, jail_errmsg); return (2); } lua_pushinteger(L, jid); jailparam_free(params, params_count); free(params); return (1); } +static int +l_attach(lua_State *L) +{ + int jid, type; + + type = lua_type(L, 1); + luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1, + "expected a jail name (string) or id (integer)"); + + if (lua_isstring(L, 1)) { + /* Resolve it to a jid. */ + jid = jail_getid(lua_tostring(L, 1)); + if (jid == -1) { + lua_pushnil(L); + lua_pushstring(L, jail_errmsg); + return (2); + } + } else { + jid = lua_tointeger(L, 1); + } + + if (jail_attach(jid) == -1) { + lua_pushnil(L); + lua_pushstring(L, strerror(errno)); + return (2); + } + + lua_pushboolean(L, 1); + return (1); +} + +static int +l_remove(lua_State *L) +{ + int jid, type; + + type = lua_type(L, 1); + luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1, + "expected a jail name (string) or id (integer)"); + + if (lua_isstring(L, 1)) { + /* Resolve it to a jid. */ + jid = jail_getid(lua_tostring(L, 1)); + if (jid == -1) { + lua_pushnil(L); + lua_pushstring(L, jail_errmsg); + return (2); + } + } else { + jid = lua_tointeger(L, 1); + } + + if (jail_remove(jid) == -1) { + lua_pushnil(L); + lua_pushstring(L, strerror(errno)); + return (2); + } + + lua_pushboolean(L, 1); + return (1); +} + static const struct luaL_Reg l_jail[] = { /** Get id of a jail by name. * @param name jail name (string) * @return jail id (integer) * or nil, error (string) on error */ {"getid", l_getid}, /** Get name of a jail by id. * @param jid jail id (integer) * @return jail name (string) * or nil, error (string) on error */ {"getname", l_getname}, /** Get a list of all known jail parameters. * @return list of jail parameter names (table of strings) * or nil, error (string) on error */ {"allparams", l_allparams}, /** Get the listed params for a given jail. * @param jail jail name (string) or id (integer) * @param params list of parameter names (table of strings) * @param flags optional flags (integer) * @return jid (integer), params (table of [string] = string) * or nil, error (string) on error */ {"getparams", l_getparams}, /** Set params for a given jail. * @param jail jail name (string) or id (integer) * @param params params and values (table of [string] = string) * @param flags optional flags (integer) * @return jid (integer) * or nil, error (string) on error */ {"setparams", l_setparams}, /** Get a list of jail parameters for running jails on the system. * @param params optional list of parameter names (table of * strings) * @return iterator (function), jail_obj (object) with next and * close methods */ {"list", l_list}, + /** Attach to a running jail. + * @param jail jail name (string) or id (integer) + * @return true (boolean) + * or nil, error (string) on error + */ + {"attach", l_attach}, + /** Remove a running jail. + * @param jail jail name (string) or id (integer) + * @return true (boolean) + * or nil, error (string) on error + */ + {"remove", l_remove}, {NULL, NULL} }; int luaopen_jail(lua_State *L) { lua_newtable(L); luaL_setfuncs(L, l_jail, 0); lua_pushinteger(L, JAIL_CREATE); lua_setfield(L, -2, "CREATE"); lua_pushinteger(L, JAIL_UPDATE); lua_setfield(L, -2, "UPDATE"); lua_pushinteger(L, JAIL_ATTACH); lua_setfield(L, -2, "ATTACH"); lua_pushinteger(L, JAIL_DYING); lua_setfield(L, -2, "DYING"); register_jail_metatable(L); return (1); }