xref: /freebsd/libexec/flua/libjail/lua_jail.c (revision 151bd3516b541823b16793460d73916e63d2b9c1)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2020, Ryan Moeller <freqlabs@FreeBSD.org>
5  * Copyright (c) 2020, Kyle Evans <kevans@FreeBSD.org>
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/param.h>
30 #include <sys/jail.h>
31 #include <errno.h>
32 #include <jail.h>
33 #include <stdbool.h>
34 #include <stdlib.h>
35 #include <string.h>
36 
37 #include <lua.h>
38 #include <lauxlib.h>
39 #include <lualib.h>
40 
41 #include "bootstrap.h"
42 
43 #define	JAIL_METATABLE "jail iterator metatable"
44 
45 /*
46  * Taken from RhodiumToad's lspawn implementation, let static analyzers make
47  * better decisions about the behavior after we raise an error.
48  */
49 #if defined(LUA_VERSION_NUM) && defined(LUA_API)
50 LUA_API int   (lua_error) (lua_State *L) __dead2;
51 #endif
52 #if defined(LUA_ERRFILE) && defined(LUALIB_API)
53 LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg) __dead2;
54 LUALIB_API int (luaL_typeerror) (lua_State *L, int arg, const char *tname) __dead2;
55 LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...) __dead2;
56 #endif
57 
58 int luaopen_jail(lua_State *);
59 
60 typedef bool (*getparam_filter)(const char *, void *);
61 
62 static void getparam_table(lua_State *L, int paramindex,
63     struct jailparam *params, size_t paramoff, size_t *params_countp,
64     getparam_filter keyfilt, void *udata);
65 
66 struct l_jail_iter {
67 	struct jailparam	*params;
68 	size_t			params_count;
69 	int			jid;
70 };
71 
72 static bool
l_jail_filter(const char * param_name,void * data __unused)73 l_jail_filter(const char *param_name, void *data __unused)
74 {
75 
76 	/*
77 	 * Allowing lastjid will mess up our iteration over all jails on the
78 	 * system, as this is a special parameter that indicates where the search
79 	 * starts from.  We'll always add jid and name, so just silently remove
80 	 * these.
81 	 */
82 	return (strcmp(param_name, "lastjid") != 0 &&
83 	    strcmp(param_name, "jid") != 0 &&
84 	    strcmp(param_name, "name") != 0);
85 }
86 
87 static int
l_jail_iter_next(lua_State * L)88 l_jail_iter_next(lua_State *L)
89 {
90 	struct l_jail_iter *iter, **iterp;
91 	struct jailparam *jp;
92 	int serrno;
93 
94 	iterp = (struct l_jail_iter **)luaL_checkudata(L, 1, JAIL_METATABLE);
95 	iter = *iterp;
96 	luaL_argcheck(L, iter != NULL, 1, "closed jail iterator");
97 
98 	jp = iter->params;
99 	/* Populate lastjid; we must keep it in params[0] for our sake. */
100 	if (jailparam_import_raw(&jp[0], &iter->jid, sizeof(iter->jid))) {
101 		jailparam_free(jp, iter->params_count);
102 		free(jp);
103 		free(iter);
104 		*iterp = NULL;
105 		return (luaL_error(L, "jailparam_import_raw: %s", jail_errmsg));
106 	}
107 
108 	/* The list of requested params was populated back in l_list(). */
109 	iter->jid = jailparam_get(jp, iter->params_count, 0);
110 	if (iter->jid == -1) {
111 		/*
112 		 * We probably got an ENOENT to signify the end of the jail
113 		 * listing, but just in case we didn't; stash it off and start
114 		 * cleaning up.  We'll handle non-ENOENT errors later.
115 		 */
116 		serrno = errno;
117 		jailparam_free(jp, iter->params_count);
118 		free(iter->params);
119 		free(iter);
120 		*iterp = NULL;
121 		if (serrno != ENOENT)
122 			return (luaL_error(L, "jailparam_get: %s",
123 			    strerror(serrno)));
124 		return (0);
125 	}
126 
127 	/*
128 	 * Finally, we'll fill in the return table with whatever parameters the
129 	 * user requested, in addition to the ones we forced with exception to
130 	 * lastjid.
131 	 */
132 	lua_newtable(L);
133 	for (size_t i = 0; i < iter->params_count; ++i) {
134 		char *value;
135 
136 		jp = &iter->params[i];
137 		if (strcmp(jp->jp_name, "lastjid") == 0)
138 			continue;
139 		value = jailparam_export(jp);
140 		lua_pushstring(L, value);
141 		lua_setfield(L, -2, jp->jp_name);
142 		free(value);
143 	}
144 
145 	return (1);
146 }
147 
148 static int
l_jail_iter_close(lua_State * L)149 l_jail_iter_close(lua_State *L)
150 {
151 	struct l_jail_iter *iter, **iterp;
152 
153 	/*
154 	 * Since we're using this as the __gc method as well, there's a good
155 	 * chance that it's already been cleaned up by iterating to the end of
156 	 * the list.
157 	 */
158 	iterp = (struct l_jail_iter **)lua_touserdata(L, 1);
159 	iter = *iterp;
160 	if (iter == NULL)
161 		return (0);
162 
163 	jailparam_free(iter->params, iter->params_count);
164 	free(iter->params);
165 	free(iter);
166 	*iterp = NULL;
167 	return (0);
168 }
169 
170 static int
l_list(lua_State * L)171 l_list(lua_State *L)
172 {
173 	struct l_jail_iter *iter;
174 	int nargs;
175 
176 	nargs = lua_gettop(L);
177 	if (nargs >= 1)
178 		luaL_checktype(L, 1, LUA_TTABLE);
179 
180 	iter = malloc(sizeof(*iter));
181 	if (iter == NULL)
182 		return (luaL_error(L, "malloc: %s", strerror(errno)));
183 
184 	/*
185 	 * lastjid, jid, name + length of the table.  This may be too much if
186 	 * we have duplicated one of those fixed parameters.
187 	 */
188 	iter->params_count = 3 + (nargs != 0 ? lua_rawlen(L, 1) : 0);
189 	iter->params = malloc(iter->params_count * sizeof(*iter->params));
190 	if (iter->params == NULL) {
191 		free(iter);
192 		return (luaL_error(L, "malloc params: %s", strerror(errno)));
193 	}
194 
195 	/* The :next() method will populate lastjid before jail_getparam(). */
196 	if (jailparam_init(&iter->params[0], "lastjid") == -1) {
197 		free(iter->params);
198 		free(iter);
199 		return (luaL_error(L, "jailparam_init: %s", jail_errmsg));
200 	}
201 	/* These two will get populated by jail_getparam(). */
202 	if (jailparam_init(&iter->params[1], "jid") == -1) {
203 		jailparam_free(iter->params, 1);
204 		free(iter->params);
205 		free(iter);
206 		return (luaL_error(L, "jailparam_init: %s",
207 		    jail_errmsg));
208 	}
209 	if (jailparam_init(&iter->params[2], "name") == -1) {
210 		jailparam_free(iter->params, 2);
211 		free(iter->params);
212 		free(iter);
213 		return (luaL_error(L, "jailparam_init: %s",
214 		    jail_errmsg));
215 	}
216 
217 	/*
218 	 * We only need to process additional arguments if we were given any.
219 	 * That is, we don't descend into getparam_table if we're passed nothing
220 	 * or an empty table.
221 	 */
222 	iter->jid = 0;
223 	if (iter->params_count != 3)
224 		getparam_table(L, 1, iter->params, 2, &iter->params_count,
225 		    l_jail_filter, NULL);
226 
227 	/*
228 	 * Part of the iterator magic.  We give it an iterator function with a
229 	 * metatable defining next() and close() that can be used for manual
230 	 * iteration.  iter->jid is how we track which jail we last iterated, to
231 	 * be supplied as "lastjid".
232 	 */
233 	lua_pushcfunction(L, l_jail_iter_next);
234 	*(struct l_jail_iter **)lua_newuserdata(L,
235 	    sizeof(struct l_jail_iter **)) = iter;
236 	luaL_getmetatable(L, JAIL_METATABLE);
237 	lua_setmetatable(L, -2);
238 	return (2);
239 }
240 
241 static void
register_jail_metatable(lua_State * L)242 register_jail_metatable(lua_State *L)
243 {
244 	luaL_newmetatable(L, JAIL_METATABLE);
245 	lua_newtable(L);
246 	lua_pushcfunction(L, l_jail_iter_next);
247 	lua_setfield(L, -2, "next");
248 	lua_pushcfunction(L, l_jail_iter_close);
249 	lua_setfield(L, -2, "close");
250 
251 	lua_setfield(L, -2, "__index");
252 
253 	lua_pushcfunction(L, l_jail_iter_close);
254 	lua_setfield(L, -2, "__gc");
255 
256 	lua_pop(L, 1);
257 }
258 
259 static int
l_getid(lua_State * L)260 l_getid(lua_State *L)
261 {
262 	const char *name;
263 	int jid;
264 
265 	name = luaL_checkstring(L, 1);
266 	jid = jail_getid(name);
267 	if (jid == -1) {
268 		lua_pushnil(L);
269 		lua_pushstring(L, jail_errmsg);
270 		return (2);
271 	}
272 	lua_pushinteger(L, jid);
273 	return (1);
274 }
275 
276 static int
l_getname(lua_State * L)277 l_getname(lua_State *L)
278 {
279 	char *name;
280 	int jid;
281 
282 	jid = luaL_checkinteger(L, 1);
283 	name = jail_getname(jid);
284 	if (name == NULL) {
285 		lua_pushnil(L);
286 		lua_pushstring(L, jail_errmsg);
287 		return (2);
288 	}
289 	lua_pushstring(L, name);
290 	free(name);
291 	return (1);
292 }
293 
294 static int
l_allparams(lua_State * L)295 l_allparams(lua_State *L)
296 {
297 	struct jailparam *params;
298 	int params_count;
299 
300 	params_count = jailparam_all(&params);
301 	if (params_count == -1) {
302 		lua_pushnil(L);
303 		lua_pushstring(L, jail_errmsg);
304 		return (2);
305 	}
306 	lua_newtable(L);
307 	for (int i = 0; i < params_count; ++i) {
308 		lua_pushstring(L, params[i].jp_name);
309 		lua_rawseti(L, -2, i + 1);
310 	}
311 	jailparam_free(params, params_count);
312 	free(params);
313 	return (1);
314 }
315 
316 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)317 getparam_table(lua_State *L, int paramindex, struct jailparam *params,
318     size_t params_off, size_t *params_countp, getparam_filter keyfilt,
319     void *udata)
320 {
321 	size_t params_count;
322 	int skipped;
323 
324 	params_count = *params_countp;
325 	skipped = 0;
326 	for (size_t i = 1 + params_off; i < params_count; ++i) {
327 		const char *param_name;
328 
329 		lua_rawgeti(L, -1, i - params_off);
330 		param_name = lua_tostring(L, -1);
331 		if (param_name == NULL) {
332 			jailparam_free(params, i - skipped);
333 			free(params);
334 			luaL_argerror(L, paramindex,
335 			    "param names must be strings");
336 		}
337 		lua_pop(L, 1);
338 		if (keyfilt != NULL && !keyfilt(param_name, udata)) {
339 			++skipped;
340 			continue;
341 		}
342 		if (jailparam_init(&params[i - skipped], param_name) == -1) {
343 			jailparam_free(params, i - skipped);
344 			free(params);
345 			luaL_error(L, "jailparam_init: %s", jail_errmsg);
346 		}
347 	}
348 	*params_countp -= skipped;
349 }
350 
351 struct getparams_filter_args {
352 	int	filter_type;
353 };
354 
355 static bool
l_getparams_filter(const char * param_name,void * udata)356 l_getparams_filter(const char *param_name, void *udata)
357 {
358 	struct getparams_filter_args *gpa;
359 
360 	gpa = udata;
361 
362 	/* Skip name or jid, whichever was given. */
363 	if (gpa->filter_type == LUA_TSTRING) {
364 		if (strcmp(param_name, "name") == 0)
365 			return (false);
366 	} else /* type == LUA_TNUMBER */ {
367 		if (strcmp(param_name, "jid") == 0)
368 			return (false);
369 	}
370 
371 	return (true);
372 }
373 
374 static int
l_getparams(lua_State * L)375 l_getparams(lua_State *L)
376 {
377 	const char *name;
378 	struct jailparam *params;
379 	size_t params_count;
380 	struct getparams_filter_args gpa;
381 	int flags, jid, type;
382 
383 	type = lua_type(L, 1);
384 	luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1,
385 	    "expected a jail name (string) or id (integer)");
386 	luaL_checktype(L, 2, LUA_TTABLE);
387 	params_count = 1 + lua_rawlen(L, 2);
388 	flags = luaL_optinteger(L, 3, 0);
389 
390 	params = malloc(params_count * sizeof(struct jailparam));
391 	if (params == NULL)
392 		return (luaL_error(L, "malloc: %s", strerror(errno)));
393 
394 	/*
395 	 * Set the jail name or id param as determined by the first arg.
396 	 */
397 
398 	if (type == LUA_TSTRING) {
399 		if (jailparam_init(&params[0], "name") == -1) {
400 			free(params);
401 			return (luaL_error(L, "jailparam_init: %s",
402 			    jail_errmsg));
403 		}
404 		name = lua_tostring(L, 1);
405 		if (jailparam_import(&params[0], name) == -1) {
406 			jailparam_free(params, 1);
407 			free(params);
408 			return (luaL_error(L, "jailparam_import: %s",
409 			    jail_errmsg));
410 		}
411 	} else /* type == LUA_TNUMBER */ {
412 		if (jailparam_init(&params[0], "jid") == -1) {
413 			free(params);
414 			return (luaL_error(L, "jailparam_init: %s",
415 			    jail_errmsg));
416 		}
417 		jid = lua_tointeger(L, 1);
418 		if (jailparam_import_raw(&params[0], &jid, sizeof(jid)) == -1) {
419 			jailparam_free(params, 1);
420 			free(params);
421 			return (luaL_error(L, "jailparam_import_raw: %s",
422 			    jail_errmsg));
423 		}
424 	}
425 
426 	/*
427 	 * Set the remaining param names being requested.
428 	 */
429 	gpa.filter_type = type;
430 	getparam_table(L, 2, params, 0, &params_count, l_getparams_filter, &gpa);
431 
432 	/*
433 	 * Get the values and convert to a table.
434 	 */
435 
436 	jid = jailparam_get(params, params_count, flags);
437 	if (jid == -1) {
438 		jailparam_free(params, params_count);
439 		free(params);
440 		lua_pushnil(L);
441 		lua_pushstring(L, jail_errmsg);
442 		return (2);
443 	}
444 	lua_pushinteger(L, jid);
445 
446 	lua_newtable(L);
447 	for (size_t i = 0; i < params_count; ++i) {
448 		char *value;
449 
450 		if (params[i].jp_flags & JP_KEYVALUE &&
451 		    params[i].jp_valuelen == 0) {
452 			/* Communicate back a missing key. */
453 			lua_pushnil(L);
454 		} else {
455 			value = jailparam_export(&params[i]);
456 			lua_pushstring(L, value);
457 			free(value);
458 		}
459 
460 		lua_setfield(L, -2, params[i].jp_name);
461 	}
462 
463 	jailparam_free(params, params_count);
464 	free(params);
465 
466 	return (2);
467 }
468 
469 static int
l_setparams(lua_State * L)470 l_setparams(lua_State *L)
471 {
472 	const char *name;
473 	struct jailparam *params;
474 	size_t params_count;
475 	int flags, jid, type;
476 
477 	type = lua_type(L, 1);
478 	luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1,
479 	    "expected a jail name (string) or id (integer)");
480 	luaL_checktype(L, 2, LUA_TTABLE);
481 
482 	lua_pushnil(L);
483 	for (params_count = 1; lua_next(L, 2) != 0; ++params_count)
484 		lua_pop(L, 1);
485 
486 	flags = luaL_optinteger(L, 3, 0);
487 
488 	params = malloc(params_count * sizeof(struct jailparam));
489 	if (params == NULL)
490 		return (luaL_error(L, "malloc: %s", strerror(errno)));
491 
492 	/*
493 	 * Set the jail name or id param as determined by the first arg.
494 	 */
495 
496 	if (type == LUA_TSTRING) {
497 		if (jailparam_init(&params[0], "name") == -1) {
498 			free(params);
499 			return (luaL_error(L, "jailparam_init: %s",
500 			    jail_errmsg));
501 		}
502 		name = lua_tostring(L, 1);
503 		if (jailparam_import(&params[0], name) == -1) {
504 			jailparam_free(params, 1);
505 			free(params);
506 			return (luaL_error(L, "jailparam_import: %s",
507 			    jail_errmsg));
508 		}
509 	} else /* type == LUA_TNUMBER */ {
510 		if (jailparam_init(&params[0], "jid") == -1) {
511 			free(params);
512 			return (luaL_error(L, "jailparam_init: %s",
513 			    jail_errmsg));
514 		}
515 		jid = lua_tointeger(L, 1);
516 		if (jailparam_import_raw(&params[0], &jid, sizeof(jid)) == -1) {
517 			jailparam_free(params, 1);
518 			free(params);
519 			return (luaL_error(L, "jailparam_import_raw: %s",
520 			    jail_errmsg));
521 		}
522 	}
523 
524 	/*
525 	 * Set the rest of the provided params.
526 	 */
527 
528 	lua_pushnil(L);
529 	for (size_t i = 1; i < params_count && lua_next(L, 2) != 0; ++i) {
530 		const char *value;
531 
532 		name = lua_tostring(L, -2);
533 		if (name == NULL) {
534 			jailparam_free(params, i);
535 			free(params);
536 			return (luaL_argerror(L, 2,
537 			    "param names must be strings"));
538 		}
539 		if (jailparam_init(&params[i], name) == -1) {
540 			jailparam_free(params, i);
541 			free(params);
542 			return (luaL_error(L, "jailparam_init: %s",
543 			    jail_errmsg));
544 		}
545 
546 		value = lua_tostring(L, -1);
547 		/* Allow passing NULL for key removal. */
548 		if (value == NULL && !(params[i].jp_flags & JP_KEYVALUE)) {
549 			jailparam_free(params, i + 1);
550 			free(params);
551 			return (luaL_argerror(L, 2,
552 			    "param values must be strings"));
553 		}
554 		if (jailparam_import(&params[i], value) == -1) {
555 			jailparam_free(params, i + 1);
556 			free(params);
557 			return (luaL_error(L, "jailparam_import: %s",
558 			    jail_errmsg));
559 		}
560 
561 		lua_pop(L, 1);
562 	}
563 
564 	/*
565 	 * Attempt to set the params.
566 	 */
567 
568 	jid = jailparam_set(params, params_count, flags);
569 	if (jid == -1) {
570 		jailparam_free(params, params_count);
571 		free(params);
572 		lua_pushnil(L);
573 		lua_pushstring(L, jail_errmsg);
574 		return (2);
575 	}
576 	lua_pushinteger(L, jid);
577 
578 	jailparam_free(params, params_count);
579 	free(params);
580 	return (1);
581 }
582 
583 static int
l_attach(lua_State * L)584 l_attach(lua_State *L)
585 {
586 	int jid, type;
587 
588 	type = lua_type(L, 1);
589 	luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1,
590 	    "expected a jail name (string) or id (integer)");
591 
592 	if (lua_isstring(L, 1)) {
593 		/* Resolve it to a jid. */
594 		jid = jail_getid(lua_tostring(L, 1));
595 		if (jid == -1) {
596 			lua_pushnil(L);
597 			lua_pushstring(L, jail_errmsg);
598 			return (2);
599 		}
600 	} else {
601 		jid = lua_tointeger(L, 1);
602 	}
603 
604 	if (jail_attach(jid) == -1) {
605 		lua_pushnil(L);
606 		lua_pushstring(L, strerror(errno));
607 		return (2);
608 	}
609 
610 	lua_pushboolean(L, 1);
611 	return (1);
612 }
613 
614 static int
l_remove(lua_State * L)615 l_remove(lua_State *L)
616 {
617 	int jid, type;
618 
619 	type = lua_type(L, 1);
620 	luaL_argcheck(L, type == LUA_TSTRING || type == LUA_TNUMBER, 1,
621 	    "expected a jail name (string) or id (integer)");
622 
623 	if (lua_isstring(L, 1)) {
624 		/* Resolve it to a jid. */
625 		jid = jail_getid(lua_tostring(L, 1));
626 		if (jid == -1) {
627 			lua_pushnil(L);
628 			lua_pushstring(L, jail_errmsg);
629 			return (2);
630 		}
631 	} else {
632 		jid = lua_tointeger(L, 1);
633 	}
634 
635 	if (jail_remove(jid) == -1) {
636 		lua_pushnil(L);
637 		lua_pushstring(L, strerror(errno));
638 		return (2);
639 	}
640 
641 	lua_pushboolean(L, 1);
642 	return (1);
643 }
644 
645 static const struct luaL_Reg l_jail[] = {
646 	/** Get id of a jail by name.
647 	 * @param name	jail name (string)
648 	 * @return	jail id (integer)
649 	 *		or nil, error (string) on error
650 	 */
651 	{"getid", l_getid},
652 	/** Get name of a jail by id.
653 	 * @param jid	jail id (integer)
654 	 * @return	jail name (string)
655 	 *		or nil, error (string) on error
656 	 */
657 	{"getname", l_getname},
658 	/** Get a list of all known jail parameters.
659 	 * @return	list of jail parameter names (table of strings)
660 	 *		or nil, error (string) on error
661 	 */
662 	{"allparams", l_allparams},
663 	/** Get the listed params for a given jail.
664 	 * @param jail	jail name (string) or id (integer)
665 	 * @param params	list of parameter names (table of strings)
666 	 * @param flags	optional flags (integer)
667 	 * @return	jid (integer), params (table of [string] = string)
668 	 *		or nil, error (string) on error
669 	 */
670 	{"getparams", l_getparams},
671 	/** Set params for a given jail.
672 	 * @param jail	jail name (string) or id (integer)
673 	 * @param params	params and values (table of [string] = string)
674 	 * @param flags	optional flags (integer)
675 	 * @return	jid (integer)
676 	 *		or nil, error (string) on error
677 	 */
678 	{"setparams", l_setparams},
679 	/** Get a list of jail parameters for running jails on the system.
680 	 * @param params	optional list of parameter names (table of
681 	 *			strings)
682 	 * @return	iterator (function), jail_obj (object) with next and
683 	 *		close methods
684 	 */
685 	{"list", l_list},
686 	/** Attach to a running jail.
687 	 * @param jail	jail name (string) or id (integer)
688 	 * @return	true (boolean)
689 	 *		or nil, error (string) on error
690 	 */
691 	{"attach", l_attach},
692 	/** Remove a running jail.
693 	 * @param jail	jail name (string) or id (integer)
694 	 * @return	true (boolean)
695 	 *		or nil, error (string) on error
696 	 */
697 	{"remove", l_remove},
698 	{NULL, NULL}
699 };
700 
701 int
luaopen_jail(lua_State * L)702 luaopen_jail(lua_State *L)
703 {
704 	lua_newtable(L);
705 
706 	luaL_setfuncs(L, l_jail, 0);
707 
708 	lua_pushinteger(L, JAIL_CREATE);
709 	lua_setfield(L, -2, "CREATE");
710 	lua_pushinteger(L, JAIL_UPDATE);
711 	lua_setfield(L, -2, "UPDATE");
712 	lua_pushinteger(L, JAIL_ATTACH);
713 	lua_setfield(L, -2, "ATTACH");
714 	lua_pushinteger(L, JAIL_DYING);
715 	lua_setfield(L, -2, "DYING");
716 
717 	register_jail_metatable(L);
718 
719 	return (1);
720 }
721 
722 FLUA_MODULE(jail);
723