summaryrefslogtreecommitdiffstats
path: root/usr.sbin/jls
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/jls')
-rw-r--r--usr.sbin/jls/Makefile2
-rw-r--r--usr.sbin/jls/jls.834
-rw-r--r--usr.sbin/jls/jls.c202
3 files changed, 212 insertions, 26 deletions
diff --git a/usr.sbin/jls/Makefile b/usr.sbin/jls/Makefile
index 3968946..01294bd 100644
--- a/usr.sbin/jls/Makefile
+++ b/usr.sbin/jls/Makefile
@@ -4,4 +4,6 @@ PROG= jls
MAN= jls.8
WARNS?= 6
+CFLAGS+= -DSUPPORT_OLD_XPRISON
+
.include <bsd.prog.mk>
diff --git a/usr.sbin/jls/jls.8 b/usr.sbin/jls/jls.8
index 4dc68c7..aff9848 100644
--- a/usr.sbin/jls/jls.8
+++ b/usr.sbin/jls/jls.8
@@ -25,20 +25,44 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 8, 2003
+.Dd November 29, 2008
.Dt JLS 8
.Os
.Sh NAME
.Nm jls
-.Nd "list active jails"
+.Nd "list jails"
.Sh SYNOPSIS
.Nm
+.Op Fl av
.Sh DESCRIPTION
The
.Nm
-utility lists all active jails.
-Each jail is represented by one row which contains the following columns:
-jail identifier (JID), IP address, hostname, and path.
+utility lists all jails.
+By default only active jails are listed.
+.Pp
+The options are as follows:
+.Bl -tag -width ".Fl a"
+.It Fl a
+Show jails in all states, not only active ones.
+.It Fl v
+Show more verbose information.
+This also lists cpusets, jail state, multi-IP, etc. instead of the
+classic single-IP jail output.
+.El
+.Pp
+Each jail is represented by rows which, depending on
+.Fl v ,
+contain the following columns:
+.Bl -item -offset indent -compact
+.It
+jail identifier (JID), hostname and path
+.It
+jail state and name
+.It
+jail cpuset
+.It
+followed by one IP adddress per line.
+.El
.Sh SEE ALSO
.Xr jail 2 ,
.Xr jail 8 ,
diff --git a/usr.sbin/jls/jls.c b/usr.sbin/jls/jls.c
index 23a3946..4488c31 100644
--- a/usr.sbin/jls/jls.c
+++ b/usr.sbin/jls/jls.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 2008 Bjoern A. Zeeb <bz@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,57 +28,216 @@
*/
#include <sys/param.h>
+#include <sys/types.h>
#include <sys/jail.h>
#include <sys/sysctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
#include <arpa/inet.h>
#include <err.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#define FLAG_A 0x00001
+#define FLAG_V 0x00002
+
+#ifdef SUPPORT_OLD_XPRISON
+static
+char *print_xprison_v1(void *p, char *end)
+{
+ struct xprison_v1 *xp;
+ struct in_addr in;
+
+ if ((char *)p + sizeof(struct xprison_v1) > end)
+ errx(1, "Invalid length for jail");
+
+ xp = (struct xprison_v1 *)p;
+ printf("%6d %-29.29s %.74s\n",
+ xp->pr_id, xp->pr_host, xp->pr_path);
+
+ /* We are not printing an empty line here for state and name. */
+ /* We are not printing an empty line here for cpusetid. */
+
+ /* IPv4 address. */
+ in.s_addr = htonl(xp->pr_ip);
+ printf("%6s %-15.15s\n", "", inet_ntoa(in));
+
+ return ((char *)(xp + 1));
+}
+#endif
+
+static
+char *print_xprison_v3(void *p, char *end, unsigned flags)
+{
+ struct xprison *xp;
+ struct in_addr *iap, in;
+ struct in6_addr *ia6p;
+ char buf[INET6_ADDRSTRLEN];
+ const char *state;
+ char *q;
+ uint32_t i;
+
+ if ((char *)p + sizeof(struct xprison) > end)
+ errx(1, "Invalid length for jail");
+ xp = (struct xprison *)p;
+
+ if (xp->pr_state < 0 || xp->pr_state > (int)
+ ((sizeof(prison_states) / sizeof(struct prison_state))))
+ state = "(bogus)";
+ else
+ state = prison_states[xp->pr_state].state_name;
+
+ /* See if we should print non-ACTIVE jails. No? */
+ if ((flags & FLAG_A) == 0 && strcmp(state, "ALIVE")) {
+ q = (char *)(xp + 1);
+ q += (xp->pr_ip4s * sizeof(struct in_addr));
+ if (q > end)
+ errx(1, "Invalid length for jail");
+ q += (xp->pr_ip6s * sizeof(struct in6_addr));
+ if (q > end)
+ errx(1, "Invalid length for jail");
+ return (q);
+ }
+
+ printf("%6d %-29.29s %.74s\n",
+ xp->pr_id, xp->pr_host, xp->pr_path);
+
+ /* Jail state and name. */
+ if (flags & FLAG_V)
+ printf("%6s %-29.29s %.74s\n",
+ "", (xp->pr_name != NULL) ? xp->pr_name : "", state);
+
+ /* cpusetid. */
+ if (flags & FLAG_V)
+ printf("%6s %-6d\n",
+ "", xp->pr_cpusetid);
+
+ q = (char *)(xp + 1);
+ /* IPv4 addresses. */
+ iap = (struct in_addr *)(void *)q;
+ q += (xp->pr_ip4s * sizeof(struct in_addr));
+ if (q > end)
+ errx(1, "Invalid length for jail");
+ for (i = 0; i < xp->pr_ip4s; i++) {
+ if (i == 0 || flags & FLAG_V) {
+ in.s_addr = iap[i].s_addr;
+ printf("%6s %-15.15s\n", "", inet_ntoa(in));
+ }
+ }
+ /* IPv6 addresses. */
+ ia6p = (struct in6_addr *)(void *)q;
+ q += (xp->pr_ip6s * sizeof(struct in6_addr));
+ if (q > end)
+ errx(1, "Invalid length for jail");
+ for (i = 0; i < xp->pr_ip6s; i++) {
+ if (flags & FLAG_V) {
+ inet_ntop(AF_INET6, &ia6p[i], buf, sizeof(buf));
+ printf("%6s %s\n", "", buf);
+ }
+ }
+
+ return (q);
+}
+
+static void
+usage(void)
+{
+
+ (void)fprintf(stderr, "usage: jls [-av]\n");
+ exit(1);
+}
int
-main(void)
+main(int argc, char *argv[])
{
- struct xprison *sxp, *xp;
- struct in_addr in;
- size_t i, len;
+ int ch, version;
+ unsigned flags;
+ size_t i, j, len;
+ void *p, *q;
+
+ flags = 0;
+ while ((ch = getopt(argc, argv, "av")) != -1) {
+ switch (ch) {
+ case 'a':
+ flags |= FLAG_A;
+ break;
+ case 'v':
+ flags |= FLAG_V;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
if (sysctlbyname("security.jail.list", NULL, &len, NULL, 0) == -1)
err(1, "sysctlbyname(): security.jail.list");
+ j = len;
for (i = 0; i < 4; i++) {
if (len <= 0)
exit(0);
- sxp = xp = malloc(len);
- if (sxp == NULL)
+ p = q = malloc(len);
+ if (p == NULL)
err(1, "malloc()");
- if (sysctlbyname("security.jail.list", xp, &len, NULL, 0) == -1) {
+ if (sysctlbyname("security.jail.list", q, &len, NULL, 0) == -1) {
if (errno == ENOMEM) {
- free(sxp);
- sxp = NULL;
+ free(p);
+ p = NULL;
+ len += j;
continue;
}
err(1, "sysctlbyname(): security.jail.list");
}
break;
}
- if (sxp == NULL)
+ if (p == NULL)
err(1, "sysctlbyname(): security.jail.list");
- if (len < sizeof(*xp) || len % sizeof(*xp) ||
- xp->pr_version != XPRISON_VERSION)
- errx(1, "Kernel and userland out of sync");
-
- printf(" JID IP Address Hostname Path\n");
- for (i = 0; i < len / sizeof(*xp); i++) {
- in.s_addr = ntohl(xp->pr_ip);
- printf("%6d %-15.15s %-29.29s %.74s\n",
- xp->pr_id, inet_ntoa(in), xp->pr_host, xp->pr_path);
- xp++;
+ if (len < sizeof(int))
+ errx(1, "This is no prison. Kernel and userland out of sync?");
+ version = *(int *)p;
+ if (version > XPRISON_VERSION)
+ errx(1, "Sci-Fi prison. Kernel/userland out of sync?");
+
+ printf(" JID Hostname Path\n");
+ if (flags & FLAG_V) {
+ printf(" Name State\n");
+ printf(" CPUSetID\n");
+ }
+ printf(" IP Address(es)\n");
+ for (; q != NULL && (char *)q + sizeof(int) < (char *)p + len;) {
+ version = *(int *)q;
+ if (version > XPRISON_VERSION)
+ errx(1, "Sci-Fi prison. Kernel/userland out of sync?");
+ switch (version) {
+#ifdef SUPPORT_OLD_XPRISON
+ case 1:
+ q = print_xprison_v1(q, (char *)p + len);
+ break;
+ case 2:
+ errx(1, "Version 2 was used by multi-IPv4 jail "
+ "implementations that never made it into the "
+ "official kernel.");
+ /* NOTREACHED */
+ break;
+#endif
+ case 3:
+ q = print_xprison_v3(q, (char *)p + len, flags);
+ break;
+ default:
+ errx(1, "Prison unknown. Kernel/userland out of sync?");
+ /* NOTREACHED */
+ break;
+ }
}
- free(sxp);
+
+ free(p);
exit(0);
}
OpenPOWER on IntegriCloud