Deleted Added
full compact
jls.c (194364) jls.c (194869)
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>
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

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

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/cdefs.h>
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>
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

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

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/cdefs.h>
30__FBSDID("$FreeBSD: head/usr.sbin/jls/jls.c 194364 2009-06-17 14:32:08Z jamie $");
30__FBSDID("$FreeBSD: head/usr.sbin/jls/jls.c 194869 2009-06-24 18:18:35Z jamie $");
31
32#include <sys/param.h>
33#include <sys/jail.h>
34#include <sys/socket.h>
35#include <sys/sysctl.h>
31
32#include <sys/param.h>
33#include <sys/jail.h>
34#include <sys/socket.h>
35#include <sys/sysctl.h>
36#include <sys/uio.h>
37
38#include <arpa/inet.h>
39#include <netinet/in.h>
40
41#include <err.h>
42#include <errno.h>
36
37#include <arpa/inet.h>
38#include <netinet/in.h>
39
40#include <err.h>
41#include <errno.h>
42#include <jail.h>
43#include <limits.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <unistd.h>
48
43#include <limits.h>
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <unistd.h>
48
49#define SJPARAM "security.jail.param"
50#define ARRAY_SLOP 5
49#define JP_USER 0x01000000
50#define JP_OPT 0x02000000
51
51
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
52#define PRINT_DEFAULT 0x01
53#define PRINT_HEADER 0x02
54#define PRINT_NAMEVAL 0x04
55#define PRINT_QUOTED 0x08
56#define PRINT_SKIP 0x10
57#define PRINT_VERBOSE 0x20
58
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;
59static struct jailparam *params;
60static int *param_noparent;
85static int nparams;
61static int nparams;
86static char errmsg[256];
87
62
88static int add_param(const char *name, void *value, unsigned flags);
89static int get_param(const char *name, struct param *param);
63static int add_param(const char *name, void *value, size_t valuelen,
64 struct jailparam *source, unsigned flags);
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);
65static int sort_param(const void *a, const void *b);
66static char *noname(const char *name);
67static char *nononame(const char *name);
68static int print_jail(int pflags, int jflags);
94static void quoted_print(char *str, int len);
69static void quoted_print(char *str);
95
96int
97main(int argc, char **argv)
98{
99 char *dot, *ep, *jname, *nname;
100 int c, i, jflags, jid, lastjid, pflags, spc;
101
102 jname = NULL;

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

131 break;
132 default:
133 errx(1, "usage: jls [-dhnqv] [-j jail] [param ...]");
134 }
135
136 /* Add the parameters to print. */
137 if (optind == argc) {
138 if (pflags & PRINT_VERBOSE) {
70
71int
72main(int argc, char **argv)
73{
74 char *dot, *ep, *jname, *nname;
75 int c, i, jflags, jid, lastjid, pflags, spc;
76
77 jname = NULL;

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

106 break;
107 default:
108 errx(1, "usage: jls [-dhnqv] [-j jail] [param ...]");
109 }
110
111 /* Add the parameters to print. */
112 if (optind == argc) {
113 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.id", NULL, PARAM_USER);
145 add_param("ip4.addr", NULL, PARAM_USER);
146 add_param("ip6.addr", NULL, PARAM_USER | PARAM_OPT);
114 add_param("jid", NULL, (size_t)0, NULL, JP_USER);
115 add_param("host.hostname", NULL, (size_t)0, NULL,
116 JP_USER);
117 add_param("path", NULL, (size_t)0, NULL, JP_USER);
118 add_param("name", NULL, (size_t)0, NULL, JP_USER);
119 add_param("dying", NULL, (size_t)0, NULL, JP_USER);
120 add_param("cpuset.id", NULL, (size_t)0, NULL, JP_USER);
121 add_param("ip4.addr", NULL, (size_t)0, NULL, JP_USER);
122 add_param("ip6.addr", NULL, (size_t)0, NULL,
123 JP_USER | JP_OPT);
147 } else {
148 pflags = (pflags &
149 ~(PRINT_NAMEVAL | PRINT_SKIP | PRINT_VERBOSE)) |
150 PRINT_DEFAULT;
124 } else {
125 pflags = (pflags &
126 ~(PRINT_NAMEVAL | PRINT_SKIP | PRINT_VERBOSE)) |
127 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);
128 add_param("jid", NULL, (size_t)0, NULL, JP_USER);
129 add_param("ip4.addr", NULL, (size_t)0, NULL, JP_USER);
130 add_param("host.hostname", NULL, (size_t)0, NULL,
131 JP_USER);
132 add_param("path", NULL, (size_t)0, NULL, JP_USER);
155 }
156 } else
157 while (optind < argc)
133 }
134 } else
135 while (optind < argc)
158 add_param(argv[optind++], NULL, PARAM_USER);
136 add_param(argv[optind++], NULL, (size_t)0, NULL,
137 JP_USER);
159
160 if (pflags & PRINT_SKIP) {
161 /* Check for parameters with boolean parents. */
162 for (i = 0; i < nparams; i++) {
138
139 if (pflags & PRINT_SKIP) {
140 /* Check for parameters with boolean parents. */
141 for (i = 0; i < nparams; i++) {
163 if ((params[i].flags & PARAM_USER) &&
164 (dot = strchr(params[i].name, '.'))) {
142 if ((params[i].jp_flags & JP_USER) &&
143 (dot = strchr(params[i].jp_name, '.'))) {
165 *dot = 0;
144 *dot = 0;
166 nname = noname(params[i].name);
145 nname = noname(params[i].jp_name);
167 *dot = '.';
146 *dot = '.';
168 params[i].noparent =
169 add_param(nname, NULL, PARAM_OPT);
147 param_noparent[i] =
148 add_param(nname, NULL, (size_t)0, NULL,
149 JP_OPT);
170 free(nname);
171 }
172 }
173 }
174
150 free(nname);
151 }
152 }
153 }
154
175 /* Add the index key and errmsg parameters. */
155 /* Add the index key parameters. */
176 if (jid != 0)
156 if (jid != 0)
177 add_param("jid", &jid, PARAM_KEY);
157 add_param("jid", &jid, sizeof(jid), NULL, 0);
178 else if (jname != NULL)
158 else if (jname != NULL)
179 add_param("name", jname, PARAM_KEY);
159 add_param("name", jname, strlen(jname), NULL, 0);
180 else
160 else
181 add_param("lastjid", &lastjid, PARAM_KEY);
182 add_param("errmsg", errmsg, PARAM_KEY);
161 add_param("lastjid", &lastjid, sizeof(lastjid), NULL, 0);
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++)
162
163 /* Print a header line if requested. */
164 if (pflags & PRINT_VERBOSE)
165 printf(" JID Hostname Path\n"
166 " Name State\n"
167 " CPUSetID\n"
168 " IP Address(es)\n");
169 else if (pflags & PRINT_DEFAULT)
170 printf(" JID IP Address "
171 "Hostname Path\n");
172 else if (pflags & PRINT_HEADER) {
173 for (i = spc = 0; i < nparams; i++)
195 if (params[i].flags & PARAM_USER) {
174 if (params[i].jp_flags & JP_USER) {
196 if (spc)
197 putchar(' ');
198 else
199 spc = 1;
175 if (spc)
176 putchar(' ');
177 else
178 spc = 1;
200 fputs(params[i].name, stdout);
179 fputs(params[i].jp_name, stdout);
201 }
202 putchar('\n');
203 }
204
205 /* Fetch the jail(s) and print the paramters. */
206 if (jid != 0 || jname != NULL) {
180 }
181 putchar('\n');
182 }
183
184 /* Fetch the jail(s) and print the paramters. */
185 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 }
186 if (print_jail(pflags, jflags) < 0)
187 errx(1, "%s", jail_errmsg);
212 } else {
213 for (lastjid = 0;
214 (lastjid = print_jail(pflags, jflags)) >= 0; )
215 ;
188 } else {
189 for (lastjid = 0;
190 (lastjid = print_jail(pflags, jflags)) >= 0; )
191 ;
216 if (errno != 0 && errno != ENOENT) {
217 if (errmsg[0])
218 errx(1, "%s", errmsg);
219 err(1, "jail_get");
220 }
192 if (errno != 0 && errno != ENOENT)
193 errx(1, "%s", jail_errmsg);
221 }
222
223 return (0);
224}
225
226static int
194 }
195
196 return (0);
197}
198
199static int
227add_param(const char *name, void *value, unsigned flags)
200add_param(const char *name, void *value, size_t valuelen,
201 struct jailparam *source, unsigned flags)
228{
202{
229 struct param *param;
230 char *nname;
231 size_t mlen1, mlen2, buflen;
232 int mib1[CTL_MAXNAME], mib2[CTL_MAXNAME - 2];
203 struct jailparam *param, *tparams;
233 int i, tnparams;
204 int i, tnparams;
234 char buf[MAXPATHLEN];
235
236 static int paramlistsize;
237
238 /* The pseudo-parameter "all" scans the list of available parameters. */
239 if (!strcmp(name, "all")) {
205
206 static int paramlistsize;
207
208 /* The pseudo-parameter "all" scans the list of available parameters. */
209 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 }
283
284 qsort(params + tnparams, (size_t)(nparams - tnparams),
285 sizeof(struct param), sort_param);
210 tnparams = jailparam_all(&tparams);
211 if (tnparams < 0)
212 errx(1, "%s", jail_errmsg);
213 qsort(tparams, (size_t)tnparams, sizeof(struct jailparam),
214 sort_param);
215 for (i = 0; i < tnparams; i++)
216 add_param(tparams[i].jp_name, NULL, (size_t)0,
217 tparams + i, flags);
218 free(tparams);
286 return -1;
287 }
288
289 /* Check for repeat parameters. */
290 for (i = 0; i < nparams; i++)
219 return -1;
220 }
221
222 /* Check for repeat parameters. */
223 for (i = 0; i < nparams; i++)
291 if (!strcmp(name, params[i].name)) {
292 params[i].value = value;
293 params[i].flags |= flags;
224 if (!strcmp(name, params[i].jp_name)) {
225 if (value != NULL && jailparam_import_raw(params + i,
226 value, valuelen) < 0)
227 errx(1, "%s", jail_errmsg);
228 params[i].jp_flags |= flags;
229 if (source != NULL)
230 jailparam_free(source, 1);
294 return i;
295 }
296
297 /* Make sure there is room for the new param record. */
298 if (!nparams) {
299 paramlistsize = 32;
300 params = malloc(paramlistsize * sizeof(*params));
231 return i;
232 }
233
234 /* Make sure there is room for the new param record. */
235 if (!nparams) {
236 paramlistsize = 32;
237 params = malloc(paramlistsize * sizeof(*params));
301 if (params == NULL)
238 param_noparent =
239 malloc(paramlistsize * sizeof(*param_noparent));
240 if (params == NULL || param_noparent == NULL)
302 err(1, "malloc");
303 } else if (nparams >= paramlistsize) {
304 paramlistsize *= 2;
305 params = realloc(params, paramlistsize * sizeof(*params));
241 err(1, "malloc");
242 } else if (nparams >= paramlistsize) {
243 paramlistsize *= 2;
244 params = realloc(params, paramlistsize * sizeof(*params));
306 if (params == NULL)
245 param_noparent = realloc(param_noparent,
246 paramlistsize * sizeof(*param_noparent));
247 if (params == NULL || param_noparent == NULL)
307 err(1, "realloc");
308 }
309
310 /* Look up the parameter. */
248 err(1, "realloc");
249 }
250
251 /* Look up the parameter. */
252 param_noparent[nparams] = -1;
311 param = params + nparams++;
253 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;
254 if (source != NULL) {
255 *param = *source;
256 param->jp_flags |= flags;
257 return param - params;
323 }
258 }
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) {
259 if (jailparam_init(param, name) < 0)
260 errx(1, "%s", jail_errmsg);
261 param->jp_flags = flags;
262 if ((value != NULL ? jailparam_import_raw(param, value, valuelen)
263 : jailparam_import(param, value)) < 0) {
264 if (flags & JP_OPT) {
342 nparams--;
265 nparams--;
343 return -1;
266 return (-1);
344 }
267 }
345 errx(1, "unknown parameter: %s", name);
268 errx(1, "%s", jail_errmsg);
346 }
269 }
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 }
361
362 got_type:
363 param->value = value;
364 return param - params;
365}
366
367static int
270 return param - params;
271}
272
273static 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;
397 }
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);
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;
426 }
427 return (0);
428}
429
430static int
431sort_param(const void *a, const void *b)
432{
274sort_param(const void *a, const void *b)
275{
433 const struct param *parama, *paramb;
276 const struct jailparam *parama, *paramb;
434 char *ap, *bp;
435
436 /* Put top-level parameters first. */
437 parama = a;
438 paramb = b;
277 char *ap, *bp;
278
279 /* Put top-level parameters first. */
280 parama = a;
281 paramb = b;
439 ap = strchr(parama->name, '.');
440 bp = strchr(paramb->name, '.');
282 ap = strchr(parama->jp_name, '.');
283 bp = strchr(paramb->jp_name, '.');
441 if (ap && !bp)
442 return (1);
443 if (bp && !ap)
444 return (-1);
284 if (ap && !bp)
285 return (1);
286 if (bp && !ap)
287 return (-1);
445 return (strcmp(parama->name, paramb->name));
288 return (strcmp(parama->jp_name, paramb->jp_name));
446}
447
448static char *
449noname(const char *name)
450{
451 char *nname, *p;
452
453 nname = malloc(strlen(name) + 3);

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

478 strcpy(nname, name + 2);
479 return nname;
480}
481
482static int
483print_jail(int pflags, int jflags)
484{
485 char *nname;
289}
290
291static char *
292noname(const char *name)
293{
294 char *nname, *p;
295
296 nname = malloc(strlen(name) + 3);

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

321 strcpy(nname, name + 2);
322 return nname;
323}
324
325static int
326print_jail(int pflags, int jflags)
327{
328 char *nname;
486 int i, ai, jid, count, sanity, spc;
329 char **param_values;
330 int i, ai, jid, count, spc;
487 char ipbuf[INET6_ADDRSTRLEN];
488
331 char ipbuf[INET6_ADDRSTRLEN];
332
489 static struct iovec2 *iov, *aiov;
490 static int narray, nkey;
491
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++;
510 }
511 }
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 }
521 }
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);
529 }
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 }
579 }
580 }
333 jid = jailparam_get(params, nparams, jflags);
334 if (jid < 0)
335 return jid;
581 if (pflags & PRINT_VERBOSE) {
582 printf("%6d %-29.29s %.74s\n"
583 "%6s %-29.29s %.74s\n"
584 "%6s %-6d\n",
336 if (pflags & PRINT_VERBOSE) {
337 printf("%6d %-29.29s %.74s\n"
338 "%6s %-29.29s %.74s\n"
339 "%6s %-6d\n",
585 *(int *)iov[0].value.iov_base,
586 (char *)iov[1].value.iov_base,
587 (char *)iov[2].value.iov_base,
340 *(int *)params[0].jp_value,
341 (char *)params[1].jp_value,
342 (char *)params[2].jp_value,
588 "",
343 "",
589 (char *)iov[3].value.iov_base,
590 *(int *)iov[4].value.iov_base ? "DYING" : "ACTIVE",
344 (char *)params[3].jp_value,
345 *(int *)params[4].jp_value ? "DYING" : "ACTIVE",
591 "",
346 "",
592 *(int *)iov[5].value.iov_base);
593 count = iov[6].value.iov_len / sizeof(struct in_addr);
347 *(int *)params[5].jp_value);
348 count = params[6].jp_valuelen / sizeof(struct in_addr);
594 for (ai = 0; ai < count; ai++)
595 if (inet_ntop(AF_INET,
349 for (ai = 0; ai < count; ai++)
350 if (inet_ntop(AF_INET,
596 &((struct in_addr *)iov[6].value.iov_base)[ai],
351 &((struct in_addr *)params[6].jp_value)[ai],
597 ipbuf, sizeof(ipbuf)) == NULL)
598 err(1, "inet_ntop");
599 else
600 printf("%6s %-15.15s\n", "", ipbuf);
352 ipbuf, sizeof(ipbuf)) == NULL)
353 err(1, "inet_ntop");
354 else
355 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);
356 if (!strcmp(params[7].jp_name, "ip6.addr")) {
357 count = params[7].jp_valuelen / sizeof(struct in6_addr);
603 for (ai = 0; ai < count; ai++)
358 for (ai = 0; ai < count; ai++)
604 if (inet_ntop(AF_INET6, &((struct in_addr *)
605 iov[7].value.iov_base)[ai],
359 if (inet_ntop(AF_INET6,
360 &((struct in_addr *)params[7].jp_value)[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",
361 ipbuf, sizeof(ipbuf)) == NULL)
362 err(1, "inet_ntop");
363 else
364 printf("%6s %-15.15s\n", "", ipbuf);
365 }
366 } else if (pflags & PRINT_DEFAULT)
367 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);
368 *(int *)params[0].jp_value,
369 params[1].jp_valuelen == 0 ? "-"
370 : inet_ntoa(*(struct in_addr *)params[1].jp_value),
371 (char *)params[2].jp_value,
372 (char *)params[3].jp_value);
618 else {
373 else {
374 param_values = alloca(nparams * sizeof(*param_values));
375 for (i = 0; i < nparams; i++) {
376 if (!(params[i].jp_flags & JP_USER))
377 continue;
378 param_values[i] = jailparam_export(params + i);
379 if (param_values[i] == NULL)
380 errx(1, "%s", jail_errmsg);
381 }
619 for (i = spc = 0; i < nparams; i++) {
382 for (i = spc = 0; i < nparams; i++) {
620 if (!(params[i].flags & PARAM_USER))
383 if (!(params[i].jp_flags & JP_USER))
621 continue;
622 if ((pflags & PRINT_SKIP) &&
384 continue;
385 if ((pflags & PRINT_SKIP) &&
623 ((!(params[i].flags & PARAM_WR)) ||
624 (params[i].noparent >= 0 &&
625 *(int *)iov[params[i].noparent].value.iov_base)))
386 ((!(params[i].jp_ctltype &
387 (CTLFLAG_WR | CTLFLAG_TUN))) ||
388 (param_noparent[i] >= 0 &&
389 *(int *)params[param_noparent[i]].jp_value)))
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 */
390 continue;
391 if (spc)
392 putchar(' ');
393 else
394 spc = 1;
395 if (pflags & PRINT_NAMEVAL) {
396 /*
397 * Generally "name=value", but for booleans
398 * either "name" or "noname".
399 */
636 switch (params[i].type) {
637 case CTLTYPE_BOOL:
638 if (*(int *)iov[i].value.iov_base)
639 printf("%s", params[i].name);
400 if (params[i].jp_flags &
401 (JP_BOOL | JP_NOBOOL)) {
402 if (*(int *)params[i].jp_value)
403 printf("%s", params[i].jp_name);
640 else {
404 else {
641 nname = noname(params[i].name);
405 nname = (params[i].jp_flags &
406 JP_NOBOOL) ?
407 nononame(params[i].jp_name)
408 : noname(params[i].jp_name);
642 printf("%s", nname);
643 free(nname);
644 }
409 printf("%s", nname);
410 free(nname);
411 }
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);
412 continue;
658 }
413 }
414 printf("%s=", params[i].jp_name);
659 }
415 }
660 count = params[i].flags & PARAM_ARRAY
661 ? iov[i].value.iov_len / params[i].size : 1;
662 if (count == 0) {
416 if (params[i].jp_valuelen == 0) {
663 if (pflags & PRINT_QUOTED)
664 printf("\"\"");
665 else if (!(pflags & PRINT_NAMEVAL))
666 putchar('-');
417 if (pflags & PRINT_QUOTED)
418 printf("\"\"");
419 else if (!(pflags & PRINT_NAMEVAL))
420 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 }
421 } else
422 quoted_print(param_values[i]);
724 }
725 putchar('\n');
423 }
424 putchar('\n');
425 for (i = 0; i < nparams; i++)
426 if (params[i].jp_flags & JP_USER)
427 free(param_values[i]);
726 }
727 for (i = 0; i < nparams; i++)
428 }
429 for (i = 0; i < nparams; i++)
728 if (params[i].value == NULL)
729 free(iov[i].value.iov_base);
430 if (!(params[i].jp_flags & JP_RAWVALUE)) {
431 free(params[i].jp_value);
432 params[i].jp_value = NULL;
433 }
730 return (jid);
731}
732
733static void
434 return (jid);
435}
436
437static void
734quoted_print(char *str, int len)
438quoted_print(char *str)
735{
736 int c, qc;
737 char *p = str;
439{
440 int c, qc;
441 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);
442
443 /* An empty string needs quoting. */
444 if (!*p) {
445 fputs("\"\"", stdout);
446 return;
447 }
448
449 /*
450 * The value will be surrounded by quotes if it contains spaces
451 * or quotes.
452 */
453 qc = strchr(p, '\'') ? '"'
454 : strchr(p, '"') ? '\''
455 : strchr(p, ' ') || strchr(p, '\t') ? '"'
456 : 0;
457 if (qc)
458 putchar(qc);
756 while (p < ep && (c = *p++)) {
459 while ((c = *p++)) {
757 if (c == '\\' || c == qc)
758 putchar('\\');
759 putchar(c);
760 }
761 if (qc)
762 putchar(qc);
763}
460 if (c == '\\' || c == qc)
461 putchar('\\');
462 putchar(c);
463 }
464 if (qc)
465 putchar(qc);
466}