Deleted Added
full compact
jls.c (186085) jls.c (192896)
1/*-
2 * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
3 * Copyright (c) 2008 Bjoern A. Zeeb <bz@FreeBSD.org>
1/*-
2 * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
3 * Copyright (c) 2008 Bjoern A. Zeeb <bz@FreeBSD.org>
4 * Copyright (c) 2009 James Gritton <jamie@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright

--- 6 unchanged lines hidden (view full) ---

18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
5 * All rights reserved.
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

--- 6 unchanged lines hidden (view full) ---

19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR 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.
26 *
27 * $FreeBSD: head/usr.sbin/jls/jls.c 186085 2008-12-14 16:56:47Z bz $
28 */
29
27 */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: head/usr.sbin/jls/jls.c 192896 2009-05-27 14:30:26Z jamie $");
31
30#include <sys/param.h>
32#include <sys/param.h>
31#include <sys/types.h>
32#include <sys/jail.h>
33#include <sys/jail.h>
34#include <sys/socket.h>
33#include <sys/sysctl.h>
35#include <sys/sysctl.h>
36#include <sys/uio.h>
34
37
35#include <sys/socket.h>
36#include <netinet/in.h>
37#include <arpa/inet.h>
38#include <arpa/inet.h>
39#include <netinet/in.h>
40
38#include <err.h>
39#include <errno.h>
40#include <limits.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <unistd.h>
45
41#include <err.h>
42#include <errno.h>
43#include <limits.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <unistd.h>
48
46#define FLAG_A 0x00001
47#define FLAG_V 0x00002
49#define SJPARAM "security.jail.param"
50#define ARRAY_SLOP 5
48
51
49#ifdef SUPPORT_OLD_XPRISON
50static
51char *print_xprison_v1(void *p, char *end, unsigned flags)
52#define CTLTYPE_BOOL (CTLTYPE + 1)
53#define CTLTYPE_NOBOOL (CTLTYPE + 2)
54#define CTLTYPE_IPADDR (CTLTYPE + 3)
55#define CTLTYPE_IP6ADDR (CTLTYPE + 4)
56
57#define PARAM_KEY 0x01
58#define PARAM_USER 0x02
59#define PARAM_ARRAY 0x04
60#define PARAM_OPT 0x08
61#define PARAM_WR 0x10
62
63#define PRINT_DEFAULT 0x01
64#define PRINT_HEADER 0x02
65#define PRINT_NAMEVAL 0x04
66#define PRINT_QUOTED 0x08
67#define PRINT_SKIP 0x10
68#define PRINT_VERBOSE 0x20
69
70struct param {
71 char *name;
72 void *value;
73 size_t size;
74 int type;
75 unsigned flags;
76 int noparent;
77};
78
79struct iovec2 {
80 struct iovec name;
81 struct iovec value;
82};
83
84static struct param *params;
85static int nparams;
86static char errmsg[256];
87
88static int add_param(const char *name, void *value, unsigned flags);
89static int get_param(const char *name, struct param *param);
90static int sort_param(const void *a, const void *b);
91static char *noname(const char *name);
92static char *nononame(const char *name);
93static int print_jail(int pflags, int jflags);
94static void quoted_print(char *str, int len);
95
96int
97main(int argc, char **argv)
52{
98{
53 struct xprison_v1 *xp;
54 struct in_addr in;
99 char *dot, *ep, *jname, *nname;
100 int c, i, jflags, jid, lastjid, pflags, spc;
55
101
56 if ((char *)p + sizeof(struct xprison_v1) > end)
57 errx(1, "Invalid length for jail");
102 jname = NULL;
103 pflags = jflags = jid = 0;
104 while ((c = getopt(argc, argv, "adj:hnqsv")) >= 0)
105 switch (c) {
106 case 'a':
107 case 'd':
108 jflags |= JAIL_DYING;
109 break;
110 case 'j':
111 jid = strtoul(optarg, &ep, 10);
112 if (!*optarg || *ep)
113 jname = optarg;
114 break;
115 case 'h':
116 pflags = (pflags & ~PRINT_SKIP) | PRINT_HEADER;
117 break;
118 case 'n':
119 pflags = (pflags & ~PRINT_VERBOSE) | PRINT_NAMEVAL;
120 break;
121 case 'q':
122 pflags |= PRINT_QUOTED;
123 break;
124 case 's':
125 pflags = (pflags & ~(PRINT_HEADER | PRINT_VERBOSE)) |
126 PRINT_NAMEVAL | PRINT_QUOTED | PRINT_SKIP;
127 break;
128 case 'v':
129 pflags = (pflags & ~(PRINT_NAMEVAL | PRINT_SKIP)) |
130 PRINT_VERBOSE;
131 break;
132 default:
133 errx(1, "usage: jls [-dhnqv] [-j jail] [param ...]");
134 }
58
135
59 xp = (struct xprison_v1 *)p;
60 if (flags & FLAG_V) {
61 printf("%6d %-29.29s %.74s\n",
62 xp->pr_id, xp->pr_host, xp->pr_path);
63 /* We are not printing an empty line here for state and name. */
64 /* We are not printing an empty line here for cpusetid. */
65 /* IPv4 address. */
66 in.s_addr = htonl(xp->pr_ip);
67 printf("%6s %-15.15s\n", "", inet_ntoa(in));
136 /* Add the parameters to print. */
137 if (optind == argc) {
138 if (pflags & PRINT_VERBOSE) {
139 add_param("jid", NULL, PARAM_USER);
140 add_param("host.hostname", NULL, PARAM_USER);
141 add_param("path", NULL, PARAM_USER);
142 add_param("name", NULL, PARAM_USER);
143 add_param("dying", NULL, PARAM_USER);
144 add_param("cpuset", NULL, PARAM_USER);
145 add_param("ip4.addr", NULL, PARAM_USER);
146 add_param("ip6.addr", NULL, PARAM_USER | PARAM_OPT);
147 } else {
148 pflags = (pflags &
149 ~(PRINT_NAMEVAL | PRINT_SKIP | PRINT_VERBOSE)) |
150 PRINT_DEFAULT;
151 add_param("jid", NULL, PARAM_USER);
152 add_param("ip4.addr", NULL, PARAM_USER);
153 add_param("host.hostname", NULL, PARAM_USER);
154 add_param("path", NULL, PARAM_USER);
155 }
156 } else
157 while (optind < argc)
158 add_param(argv[optind++], NULL, PARAM_USER);
159
160 if (pflags & PRINT_SKIP) {
161 /* Check for parameters with boolean parents. */
162 for (i = 0; i < nparams; i++) {
163 if ((params[i].flags & PARAM_USER) &&
164 (dot = strchr(params[i].name, '.'))) {
165 *dot = 0;
166 nname = noname(params[i].name);
167 *dot = '.';
168 params[i].noparent =
169 add_param(nname, NULL, PARAM_OPT);
170 free(nname);
171 }
172 }
173 }
174
175 /* Add the index key and errmsg parameters. */
176 if (jid != 0)
177 add_param("jid", &jid, PARAM_KEY);
178 else if (jname != NULL)
179 add_param("name", jname, PARAM_KEY);
180 else
181 add_param("lastjid", &lastjid, PARAM_KEY);
182 add_param("errmsg", errmsg, PARAM_KEY);
183
184 /* Print a header line if requested. */
185 if (pflags & PRINT_VERBOSE)
186 printf(" JID Hostname Path\n"
187 " Name State\n"
188 " CPUSetID\n"
189 " IP Address(es)\n");
190 else if (pflags & PRINT_DEFAULT)
191 printf(" JID IP Address "
192 "Hostname Path\n");
193 else if (pflags & PRINT_HEADER) {
194 for (i = spc = 0; i < nparams; i++)
195 if (params[i].flags & PARAM_USER) {
196 if (spc)
197 putchar(' ');
198 else
199 spc = 1;
200 fputs(params[i].name, stdout);
201 }
202 putchar('\n');
203 }
204
205 /* Fetch the jail(s) and print the paramters. */
206 if (jid != 0 || jname != NULL) {
207 if (print_jail(pflags, jflags) < 0) {
208 if (errmsg[0])
209 errx(1, "%s", errmsg);
210 err(1, "jail_get");
211 }
68 } else {
212 } else {
69 printf("%6d %-15.15s %-29.29s %.74s\n",
70 xp->pr_id, inet_ntoa(in), xp->pr_host, xp->pr_path);
213 for (lastjid = 0;
214 (lastjid = print_jail(pflags, jflags)) >= 0; )
215 ;
216 if (errno != 0 && errno != ENOENT) {
217 if (errmsg[0])
218 errx(1, "%s", errmsg);
219 err(1, "jail_get");
220 }
71 }
72
221 }
222
73 return ((char *)(xp + 1));
223 return (0);
74}
224}
75#endif
76
225
77static
78char *print_xprison_v3(void *p, char *end, unsigned flags)
226static int
227add_param(const char *name, void *value, unsigned flags)
79{
228{
80 struct xprison *xp;
81 struct in_addr *iap, in;
82 struct in6_addr *ia6p;
83 char buf[INET6_ADDRSTRLEN];
84 const char *state;
85 char *q;
86 uint32_t i;
229 struct param *param;
230 char *nname;
231 size_t mlen1, mlen2, buflen;
232 int mib1[CTL_MAXNAME], mib2[CTL_MAXNAME - 2];
233 int i, tnparams;
234 char buf[MAXPATHLEN];
87
235
88 if ((char *)p + sizeof(struct xprison) > end)
89 errx(1, "Invalid length for jail");
90 xp = (struct xprison *)p;
236 static int paramlistsize;
91
237
92 if (xp->pr_state < 0 || xp->pr_state >= (int)
93 ((sizeof(prison_states) / sizeof(struct prison_state))))
94 state = "(bogus)";
95 else
96 state = prison_states[xp->pr_state].state_name;
238 /* The pseudo-parameter "all" scans the list of available parameters. */
239 if (!strcmp(name, "all")) {
240 tnparams = nparams;
241 mib1[0] = 0;
242 mib1[1] = 2;
243 mlen1 = CTL_MAXNAME - 2;
244 if (sysctlnametomib(SJPARAM, mib1 + 2, &mlen1) < 0)
245 err(1, "sysctlnametomib(" SJPARAM ")");
246 for (;;) {
247 /* Get the next parameter. */
248 mlen2 = sizeof(mib2);
249 if (sysctl(mib1, mlen1 + 2, mib2, &mlen2, NULL, 0) < 0)
250 err(1, "sysctl(0.2)");
251 if (mib2[0] != mib1[2] || mib2[1] != mib1[3] ||
252 mib2[2] != mib1[4])
253 break;
254 /* Convert it to an ascii name. */
255 memcpy(mib1 + 2, mib2, mlen2);
256 mlen1 = mlen2 / sizeof(int);
257 mib1[1] = 1;
258 buflen = sizeof(buf);
259 if (sysctl(mib1, mlen1 + 2, buf, &buflen, NULL, 0) < 0)
260 err(1, "sysctl(0.1)");
261 add_param(buf + sizeof(SJPARAM), NULL, flags);
262 /*
263 * Convert nobool parameters to bool if their
264 * counterpart is a node, ortherwise discard them.
265 */
266 param = &params[nparams - 1];
267 if (param->type == CTLTYPE_NOBOOL) {
268 nname = nononame(param->name);
269 if (get_param(nname, param) >= 0 &&
270 param->type != CTLTYPE_NODE) {
271 free(nname);
272 nparams--;
273 } else {
274 free(param->name);
275 param->name = nname;
276 param->type = CTLTYPE_BOOL;
277 param->size = sizeof(int);
278 param->value = NULL;
279 }
280 }
281 mib1[1] = 2;
282 }
97
283
98 /* See if we should print non-ACTIVE jails. No? */
99 if ((flags & FLAG_A) == 0 && strcmp(state, "ALIVE")) {
100 q = (char *)(xp + 1);
101 q += (xp->pr_ip4s * sizeof(struct in_addr));
102 if (q > end)
103 errx(1, "Invalid length for jail");
104 q += (xp->pr_ip6s * sizeof(struct in6_addr));
105 if (q > end)
106 errx(1, "Invalid length for jail");
107 return (q);
284 qsort(params + tnparams, (size_t)(nparams - tnparams),
285 sizeof(struct param), sort_param);
286 return -1;
108 }
109
287 }
288
110 if (flags & FLAG_V)
111 printf("%6d %-29.29s %.74s\n",
112 xp->pr_id, xp->pr_host, xp->pr_path);
289 /* Check for repeat parameters. */
290 for (i = 0; i < nparams; i++)
291 if (!strcmp(name, params[i].name)) {
292 params[i].value = value;
293 params[i].flags |= flags;
294 return i;
295 }
113
296
114 /* Jail state and name. */
115 if (flags & FLAG_V)
116 printf("%6s %-29.29s %.74s\n",
117 "", (xp->pr_name[0] != '\0') ? xp->pr_name : "", state);
297 /* Make sure there is room for the new param record. */
298 if (!nparams) {
299 paramlistsize = 32;
300 params = malloc(paramlistsize * sizeof(*params));
301 if (params == NULL)
302 err(1, "malloc");
303 } else if (nparams >= paramlistsize) {
304 paramlistsize *= 2;
305 params = realloc(params, paramlistsize * sizeof(*params));
306 if (params == NULL)
307 err(1, "realloc");
308 }
118
309
119 /* cpusetid. */
120 if (flags & FLAG_V)
121 printf("%6s %-6d\n",
122 "", xp->pr_cpusetid);
310 /* Look up the parameter. */
311 param = params + nparams++;
312 memset(param, 0, sizeof *param);
313 param->name = strdup(name);
314 if (param->name == NULL)
315 err(1, "strdup");
316 param->flags = flags;
317 param->noparent = -1;
318 /* We have to know about pseudo-parameters without asking. */
319 if (!strcmp(param->name, "lastjid")) {
320 param->type = CTLTYPE_INT;
321 param->size = sizeof(int);
322 goto got_type;
323 }
324 if (!strcmp(param->name, "errmsg")) {
325 param->type = CTLTYPE_STRING;
326 param->size = sizeof(errmsg);
327 goto got_type;
328 }
329 if (get_param(name, param) < 0) {
330 if (errno != ENOENT)
331 err(1, "sysctl(0.3.%s)", name);
332 /* See if this the "no" part of an existing boolean. */
333 if ((nname = nononame(name))) {
334 i = get_param(nname, param);
335 free(nname);
336 if (i >= 0 && param->type == CTLTYPE_BOOL) {
337 param->type = CTLTYPE_NOBOOL;
338 goto got_type;
339 }
340 }
341 if (flags & PARAM_OPT) {
342 nparams--;
343 return -1;
344 }
345 errx(1, "unknown parameter: %s", name);
346 }
347 if (param->type == CTLTYPE_NODE) {
348 /*
349 * A node isn't normally a parameter, but may be a boolean
350 * if its "no" counterpart exists.
351 */
352 nname = noname(name);
353 i = get_param(nname, param);
354 free(nname);
355 if (i >= 0 && param->type == CTLTYPE_NOBOOL) {
356 param->type = CTLTYPE_BOOL;
357 goto got_type;
358 }
359 errx(1, "unknown parameter: %s", name);
360 }
123
361
124 q = (char *)(xp + 1);
125 /* IPv4 addresses. */
126 iap = (struct in_addr *)(void *)q;
127 q += (xp->pr_ip4s * sizeof(struct in_addr));
128 if (q > end)
129 errx(1, "Invalid length for jail");
130 in.s_addr = 0;
131 for (i = 0; i < xp->pr_ip4s; i++) {
132 if (i == 0 || flags & FLAG_V)
133 in.s_addr = iap[i].s_addr;
134 if (flags & FLAG_V)
135 printf("%6s %-15.15s\n", "", inet_ntoa(in));
362 got_type:
363 param->value = value;
364 return param - params;
365}
366
367static int
368get_param(const char *name, struct param *param)
369{
370 char *p;
371 size_t buflen, mlen;
372 int mib[CTL_MAXNAME];
373 struct {
374 int i;
375 char s[MAXPATHLEN];
376 } buf;
377
378 /* Look up the MIB. */
379 mib[0] = 0;
380 mib[1] = 3;
381 snprintf(buf.s, sizeof(buf.s), SJPARAM ".%s", name);
382 mlen = sizeof(mib) - 2 * sizeof(int);
383 if (sysctl(mib, 2, mib + 2, &mlen, buf.s, strlen(buf.s)) < 0)
384 return (-1);
385 /* Get the type and size. */
386 mib[1] = 4;
387 buflen = sizeof(buf);
388 if (sysctl(mib, (mlen / sizeof(int)) + 2, &buf, &buflen, NULL, 0) < 0)
389 err(1, "sysctl(0.4.%s)", name);
390 param->type = buf.i & CTLTYPE;
391 if (buf.i & (CTLFLAG_WR | CTLFLAG_TUN))
392 param->flags |= PARAM_WR;
393 p = strchr(buf.s, '\0');
394 if (p - 2 >= buf.s && !strcmp(p - 2, ",a")) {
395 p[-2] = 0;
396 param->flags |= PARAM_ARRAY;
136 }
397 }
137 /* IPv6 addresses. */
138 ia6p = (struct in6_addr *)(void *)q;
139 q += (xp->pr_ip6s * sizeof(struct in6_addr));
140 if (q > end)
141 errx(1, "Invalid length for jail");
142 for (i = 0; i < xp->pr_ip6s; i++) {
143 if (flags & FLAG_V) {
144 inet_ntop(AF_INET6, &ia6p[i], buf, sizeof(buf));
145 printf("%6s %s\n", "", buf);
398 switch (param->type) {
399 case CTLTYPE_INT:
400 /* An integer parameter might be a boolean. */
401 if (buf.s[0] == 'B')
402 param->type = buf.s[1] == 'N'
403 ? CTLTYPE_NOBOOL : CTLTYPE_BOOL;
404 case CTLTYPE_UINT:
405 param->size = sizeof(int);
406 break;
407 case CTLTYPE_LONG:
408 case CTLTYPE_ULONG:
409 param->size = sizeof(long);
410 break;
411 case CTLTYPE_STRUCT:
412 if (!strcmp(buf.s, "S,in_addr")) {
413 param->type = CTLTYPE_IPADDR;
414 param->size = sizeof(struct in_addr);
415 } else if (!strcmp(buf.s, "S,in6_addr")) {
416 param->type = CTLTYPE_IP6ADDR;
417 param->size = sizeof(struct in6_addr);
146 }
418 }
419 break;
420 case CTLTYPE_STRING:
421 buf.s[0] = 0;
422 sysctl(mib + 2, mlen / sizeof(int), buf.s, &buflen, NULL, 0);
423 param->size = strtoul(buf.s, NULL, 10);
424 if (param->size == 0)
425 param->size = BUFSIZ;
147 }
426 }
427 return (0);
428}
148
429
149 /* If requested print the old style single line version. */
150 if (!(flags & FLAG_V))
151 printf("%6d %-15.15s %-29.29s %.74s\n",
152 xp->pr_id, (in.s_addr) ? inet_ntoa(in) : "",
153 xp->pr_host, xp->pr_path);
430static int
431sort_param(const void *a, const void *b)
432{
433 const struct param *parama, *paramb;
434 char *ap, *bp;
154
435
155 return (q);
436 /* Put top-level parameters first. */
437 parama = a;
438 paramb = b;
439 ap = strchr(parama->name, '.');
440 bp = strchr(paramb->name, '.');
441 if (ap && !bp)
442 return (1);
443 if (bp && !ap)
444 return (-1);
445 return (strcmp(parama->name, paramb->name));
156}
157
446}
447
158static void
159usage(void)
448static char *
449noname(const char *name)
160{
450{
451 char *nname, *p;
161
452
162 (void)fprintf(stderr, "usage: jls [-av]\n");
163 exit(1);
453 nname = malloc(strlen(name) + 3);
454 if (nname == NULL)
455 err(1, "malloc");
456 p = strrchr(name, '.');
457 if (p != NULL)
458 sprintf(nname, "%.*s.no%s", (int)(p - name), name, p + 1);
459 else
460 sprintf(nname, "no%s", name);
461 return nname;
164}
165
462}
463
166int
167main(int argc, char *argv[])
168{
169 int ch, version;
170 unsigned flags;
171 size_t i, j, len;
172 void *p, *q;
464static char *
465nononame(const char *name)
466{
467 char *nname, *p;
173
468
174 flags = 0;
175 while ((ch = getopt(argc, argv, "av")) != -1) {
176 switch (ch) {
177 case 'a':
178 flags |= FLAG_A;
179 break;
180 case 'v':
181 flags |= FLAG_V;
182 break;
183 default:
184 usage();
185 }
186 }
187 argc -= optind;
188 argv += optind;
469 p = strrchr(name, '.');
470 if (strncmp(p ? p + 1 : name, "no", 2))
471 return NULL;
472 nname = malloc(strlen(name) - 1);
473 if (nname == NULL)
474 err(1, "malloc");
475 if (p != NULL)
476 sprintf(nname, "%.*s.%s", (int)(p - name), name, p + 3);
477 else
478 strcpy(nname, name + 2);
479 return nname;
480}
189
481
190 if (sysctlbyname("security.jail.list", NULL, &len, NULL, 0) == -1)
191 err(1, "sysctlbyname(): security.jail.list");
482static int
483print_jail(int pflags, int jflags)
484{
485 char *nname;
486 int i, ai, jid, count, sanity, spc;
487 char ipbuf[INET6_ADDRSTRLEN];
192
488
193 j = len;
194 for (i = 0; i < 4; i++) {
195 if (len <= 0)
196 exit(0);
197 p = q = malloc(len);
198 if (p == NULL)
199 err(1, "malloc()");
489 static struct iovec2 *iov, *aiov;
490 static int narray, nkey;
200
491
201 if (sysctlbyname("security.jail.list", q, &len, NULL, 0) == -1) {
202 if (errno == ENOMEM) {
203 free(p);
204 p = NULL;
205 len += j;
206 continue;
492 /* Set up the parameter list(s) the first time around. */
493 if (iov == NULL) {
494 iov = malloc(nparams * sizeof(struct iovec2));
495 if (iov == NULL)
496 err(1, "malloc");
497 for (i = narray = 0; i < nparams; i++) {
498 iov[i].name.iov_base = params[i].name;
499 iov[i].name.iov_len = strlen(params[i].name) + 1;
500 iov[i].value.iov_base = params[i].value;
501 iov[i].value.iov_len =
502 params[i].type == CTLTYPE_STRING &&
503 params[i].value != NULL &&
504 ((char *)params[i].value)[0] != '\0'
505 ? strlen(params[i].value) + 1 : params[i].size;
506 if (params[i].flags & (PARAM_KEY | PARAM_ARRAY)) {
507 narray++;
508 if (params[i].flags & PARAM_KEY)
509 nkey++;
207 }
510 }
208 err(1, "sysctlbyname(): security.jail.list");
209 }
511 }
210 break;
512 if (narray > nkey) {
513 aiov = malloc(narray * sizeof(struct iovec2));
514 if (aiov == NULL)
515 err(1, "malloc");
516 for (i = ai = 0; i < nparams; i++)
517 if (params[i].flags &
518 (PARAM_KEY | PARAM_ARRAY))
519 aiov[ai++] = iov[i];
520 }
211 }
521 }
212 if (p == NULL)
213 err(1, "sysctlbyname(): security.jail.list");
214 if (len < sizeof(int))
215 errx(1, "This is no prison. Kernel and userland out of sync?");
216 version = *(int *)p;
217 if (version > XPRISON_VERSION)
218 errx(1, "Sci-Fi prison. Kernel/userland out of sync?");
219
220 if (flags & FLAG_V) {
221 printf(" JID Hostname Path\n");
222 printf(" Name State\n");
223 printf(" CPUSetID\n");
224 printf(" IP Address(es)\n");
225 } else {
226 printf(" JID IP Address Hostname"
227 " Path\n");
522 /* If there are array parameters, find their sizes. */
523 if (aiov != NULL) {
524 for (ai = 0; ai < narray; ai++)
525 if (aiov[ai].value.iov_base == NULL)
526 aiov[ai].value.iov_len = 0;
527 if (jail_get((struct iovec *)aiov, 2 * narray, jflags) < 0)
528 return (-1);
228 }
529 }
229 for (; q != NULL && (char *)q + sizeof(int) < (char *)p + len;) {
230 version = *(int *)q;
231 if (version > XPRISON_VERSION)
232 errx(1, "Sci-Fi prison. Kernel/userland out of sync?");
233 switch (version) {
234#ifdef SUPPORT_OLD_XPRISON
235 case 1:
236 q = print_xprison_v1(q, (char *)p + len, flags);
237 break;
238 case 2:
239 errx(1, "Version 2 was used by multi-IPv4 jail "
240 "implementations that never made it into the "
241 "official kernel.");
242 /* NOTREACHED */
243 break;
244#endif
245 case 3:
246 q = print_xprison_v3(q, (char *)p + len, flags);
247 break;
248 default:
249 errx(1, "Prison unknown. Kernel/userland out of sync?");
250 /* NOTREACHED */
251 break;
530 /* Allocate storage for all parameters. */
531 for (i = ai = 0; i < nparams; i++) {
532 if (params[i].flags & (PARAM_KEY | PARAM_ARRAY)) {
533 if (params[i].flags & PARAM_ARRAY) {
534 iov[i].value.iov_len = aiov[ai].value.iov_len +
535 ARRAY_SLOP * params[i].size;
536 iov[i].value.iov_base =
537 malloc(iov[i].value.iov_len);
538 }
539 ai++;
540 } else
541 iov[i].value.iov_base = malloc(params[i].size);
542 if (iov[i].value.iov_base == NULL)
543 err(1, "malloc");
544 if (params[i].value == NULL)
545 memset(iov[i].value.iov_base, 0, iov[i].value.iov_len);
546 }
547 /*
548 * Get the actual prison. If there are array elements, retry a few
549 * times in case the size changed from under us.
550 */
551 if ((jid = jail_get((struct iovec *)iov, 2 * nparams, jflags)) < 0) {
552 if (errno != EINVAL || aiov == NULL || errmsg[0])
553 return (-1);
554 for (sanity = 0;; sanity++) {
555 if (sanity == 10)
556 return (-1);
557 for (ai = 0; ai < narray; ai++)
558 if (params[i].flags & PARAM_ARRAY)
559 aiov[ai].value.iov_len = 0;
560 if (jail_get((struct iovec *)iov, 2 * narray, jflags) <
561 0)
562 return (-1);
563 for (i = ai = 0; i < nparams; i++) {
564 if (!(params[i].flags &
565 (PARAM_KEY | PARAM_ARRAY)))
566 continue;
567 if (params[i].flags & PARAM_ARRAY) {
568 iov[i].value.iov_len =
569 aiov[ai].value.iov_len +
570 ARRAY_SLOP * params[i].size;
571 iov[i].value.iov_base =
572 realloc(iov[i].value.iov_base,
573 iov[i].value.iov_len);
574 if (iov[i].value.iov_base == NULL)
575 err(1, "malloc");
576 }
577 ai++;
578 }
252 }
253 }
579 }
580 }
581 if (pflags & PRINT_VERBOSE) {
582 printf("%6d %-29.29s %.74s\n"
583 "%6s %-29.29s %.74s\n"
584 "%6s %-6d\n",
585 *(int *)iov[0].value.iov_base,
586 (char *)iov[1].value.iov_base,
587 (char *)iov[2].value.iov_base,
588 "",
589 (char *)iov[3].value.iov_base,
590 *(int *)iov[4].value.iov_base ? "DYING" : "ACTIVE",
591 "",
592 *(int *)iov[5].value.iov_base);
593 count = iov[6].value.iov_len / sizeof(struct in_addr);
594 for (ai = 0; ai < count; ai++)
595 if (inet_ntop(AF_INET,
596 &((struct in_addr *)iov[6].value.iov_base)[ai],
597 ipbuf, sizeof(ipbuf)) == NULL)
598 err(1, "inet_ntop");
599 else
600 printf("%6s %-15.15s\n", "", ipbuf);
601 if (!strcmp(params[7].name, "ip6.addr")) {
602 count = iov[7].value.iov_len / sizeof(struct in6_addr);
603 for (ai = 0; ai < count; ai++)
604 if (inet_ntop(AF_INET6, &((struct in_addr *)
605 iov[7].value.iov_base)[ai],
606 ipbuf, sizeof(ipbuf)) == NULL)
607 err(1, "inet_ntop");
608 else
609 printf("%6s %-15.15s\n", "", ipbuf);
610 }
611 } else if (pflags & PRINT_DEFAULT)
612 printf("%6d %-15.15s %-29.29s %.74s\n",
613 *(int *)iov[0].value.iov_base,
614 iov[1].value.iov_len == 0 ? "-"
615 : inet_ntoa(*(struct in_addr *)iov[1].value.iov_base),
616 (char *)iov[2].value.iov_base,
617 (char *)iov[3].value.iov_base);
618 else {
619 for (i = spc = 0; i < nparams; i++) {
620 if (!(params[i].flags & PARAM_USER))
621 continue;
622 if ((pflags & PRINT_SKIP) &&
623 ((!(params[i].flags & PARAM_WR)) ||
624 (params[i].noparent >= 0 &&
625 *(int *)iov[params[i].noparent].value.iov_base)))
626 continue;
627 if (spc)
628 putchar(' ');
629 else
630 spc = 1;
631 if (pflags & PRINT_NAMEVAL) {
632 /*
633 * Generally "name=value", but for booleans
634 * either "name" or "noname".
635 */
636 switch (params[i].type) {
637 case CTLTYPE_BOOL:
638 if (*(int *)iov[i].value.iov_base)
639 printf("%s", params[i].name);
640 else {
641 nname = noname(params[i].name);
642 printf("%s", nname);
643 free(nname);
644 }
645 break;
646 case CTLTYPE_NOBOOL:
647 if (*(int *)iov[i].value.iov_base)
648 printf("%s", params[i].name);
649 else {
650 nname =
651 nononame(params[i].name);
652 printf("%s", nname);
653 free(nname);
654 }
655 break;
656 default:
657 printf("%s=", params[i].name);
658 }
659 }
660 count = params[i].flags & PARAM_ARRAY
661 ? iov[i].value.iov_len / params[i].size : 1;
662 if (count == 0) {
663 if (pflags & PRINT_QUOTED)
664 printf("\"\"");
665 else if (!(pflags & PRINT_NAMEVAL))
666 putchar('-');
667 }
668 for (ai = 0; ai < count; ai++) {
669 if (ai > 0)
670 putchar(',');
671 switch (params[i].type) {
672 case CTLTYPE_INT:
673 printf("%d", ((int *)
674 iov[i].value.iov_base)[ai]);
675 break;
676 case CTLTYPE_UINT:
677 printf("%u", ((int *)
678 iov[i].value.iov_base)[ai]);
679 break;
680 case CTLTYPE_IPADDR:
681 if (inet_ntop(AF_INET,
682 &((struct in_addr *)
683 iov[i].value.iov_base)[ai],
684 ipbuf, sizeof(ipbuf)) == NULL)
685 err(1, "inet_ntop");
686 else
687 printf("%s", ipbuf);
688 break;
689 case CTLTYPE_IP6ADDR:
690 if (inet_ntop(AF_INET6,
691 &((struct in6_addr *)
692 iov[i].value.iov_base)[ai],
693 ipbuf, sizeof(ipbuf)) == NULL)
694 err(1, "inet_ntop");
695 else
696 printf("%s", ipbuf);
697 break;
698 case CTLTYPE_LONG:
699 printf("%ld", ((long *)
700 iov[i].value.iov_base)[ai]);
701 case CTLTYPE_ULONG:
702 printf("%lu", ((long *)
703 iov[i].value.iov_base)[ai]);
704 break;
705 case CTLTYPE_STRING:
706 if (pflags & PRINT_QUOTED)
707 quoted_print((char *)
708 iov[i].value.iov_base,
709 params[i].size);
710 else
711 printf("%.*s",
712 (int)params[i].size,
713 (char *)
714 iov[i].value.iov_base);
715 break;
716 case CTLTYPE_BOOL:
717 case CTLTYPE_NOBOOL:
718 if (!(pflags & PRINT_NAMEVAL))
719 printf(((int *)
720 iov[i].value.iov_base)[ai]
721 ? "true" : "false");
722 }
723 }
724 }
725 putchar('\n');
726 }
727 for (i = 0; i < nparams; i++)
728 if (params[i].value == NULL)
729 free(iov[i].value.iov_base);
730 return (jid);
731}
254
732
255 free(p);
256 exit(0);
733static void
734quoted_print(char *str, int len)
735{
736 int c, qc;
737 char *p = str;
738 char *ep = str + len;
739
740 /* An empty string needs quoting. */
741 if (!*p) {
742 fputs("\"\"", stdout);
743 return;
744 }
745
746 /*
747 * The value will be surrounded by quotes if it contains spaces
748 * or quotes.
749 */
750 qc = strchr(p, '\'') ? '"'
751 : strchr(p, '"') ? '\''
752 : strchr(p, ' ') || strchr(p, '\t') ? '"'
753 : 0;
754 if (qc)
755 putchar(qc);
756 while (p < ep && (c = *p++)) {
757 if (c == '\\' || c == qc)
758 putchar('\\');
759 putchar(c);
760 }
761 if (qc)
762 putchar(qc);
257}
763}