xref: /titanic_51/usr/src/cmd/cmd-inet/usr.sbin/ipsecutils/ikeadm.c (revision a31148363f598def767ac48c5d82e1572e44b935)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  *
21  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
22  * Use is subject to license terms.
23  */
24 
25 #include <unistd.h>
26 #include <stdio.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <sys/sysconf.h>
30 #include <string.h>
31 #include <strings.h>
32 #include <libintl.h>
33 #include <locale.h>
34 #include <ctype.h>
35 #include <time.h>
36 #include <sys/sysmacros.h>
37 #include <sys/stat.h>
38 #include <sys/mman.h>
39 #include <fcntl.h>
40 #include <sys/socket.h>
41 #include <netdb.h>
42 #include <errno.h>
43 #include <assert.h>
44 #include <netinet/in.h>
45 #include <arpa/inet.h>
46 #include <door.h>
47 #include <setjmp.h>
48 
49 #include <ipsec_util.h>
50 #include <ikedoor.h>
51 
52 static int	doorfd = -1;
53 
54 /*
55  * These are additional return values for the command line parsing
56  * function (parsecmd()).  They are specific to this utility, but
57  * need to share the same space as the IKE_SVC_* defs, without conflicts.
58  * So they're defined relative to the end of that range.
59  */
60 #define	IKEADM_HELP_GENERAL	IKE_SVC_MAX + 1
61 #define	IKEADM_HELP_GET		IKE_SVC_MAX + 2
62 #define	IKEADM_HELP_SET		IKE_SVC_MAX + 3
63 #define	IKEADM_HELP_ADD		IKE_SVC_MAX + 4
64 #define	IKEADM_HELP_DEL		IKE_SVC_MAX + 5
65 #define	IKEADM_HELP_DUMP	IKE_SVC_MAX + 6
66 #define	IKEADM_HELP_FLUSH	IKE_SVC_MAX + 7
67 #define	IKEADM_HELP_READ	IKE_SVC_MAX + 8
68 #define	IKEADM_HELP_WRITE	IKE_SVC_MAX + 9
69 #define	IKEADM_HELP_TOKEN	IKE_SVC_MAX + 10
70 #define	IKEADM_HELP_HELP	IKE_SVC_MAX + 11
71 #define	IKEADM_EXIT		IKE_SVC_MAX + 12
72 
73 /*
74  * Disable default TAB completion for now (until some brave soul tackles it).
75  */
76 /* ARGSUSED */
77 static
78 CPL_MATCH_FN(no_match)
79 {
80 	return (0);
81 }
82 
83 static void
84 command_complete(int s)
85 {
86 	if (interactive) {
87 		longjmp(env, 1);
88 	} else {
89 		exit(s);
90 	}
91 }
92 
93 static void
94 usage()
95 {
96 	if (!interactive) {
97 		(void) fprintf(stderr, gettext("Usage:\t"
98 		    "ikeadm [ -hnp ] cmd obj [cmd-specific options]\n"));
99 		(void) fprintf(stderr, gettext("      \tikeadm help\n"));
100 	} else {
101 		(void) fprintf(stderr,
102 		    gettext("\nType help for usage info\n"));
103 	}
104 
105 	command_complete(1);
106 }
107 
108 static void
109 print_help()
110 {
111 	(void) printf(gettext("Valid commands and objects:\n"));
112 	(void) printf(
113 	    "\tget   debug|priv|stats|p1|rule|preshared|defaults [%s]\n",
114 	    gettext("identifier"));
115 	(void) printf("\tset   priv %s\n", gettext("level"));
116 	(void) printf("\tset   debug %s [%s]\n",
117 	    gettext("level"), gettext("filename"));
118 	(void) printf("\tadd   rule|preshared {%s}|%s\n",
119 	    gettext("definition"), gettext("filename"));
120 	(void) printf("\tdel   p1|rule|preshared %s\n", gettext("identifier"));
121 	(void) printf("\tdump  p1|rule|preshared|certcache\n");
122 	(void) printf("\tflush p1|certcache\n");
123 	(void) printf("\tread  rule|preshared [%s]\n", gettext("filename"));
124 	(void) printf("\twrite rule|preshared %s\n", gettext("filename"));
125 	(void) printf("\ttoken <login|logout> %s\n",
126 	    gettext("<PKCS#11 Token Object>"));
127 	(void) printf(
128 	    "\thelp  [get|set|add|del|dump|flush|read|write|token|help]\n");
129 	(void) printf("\texit  %s\n", gettext("exit the program"));
130 	(void) printf("\tquit  %s\n", gettext("exit the program"));
131 
132 	command_complete(0);
133 }
134 
135 static void
136 print_get_help()
137 {
138 	(void) printf(
139 	    gettext("This command gets information from in.iked.\n\n"));
140 	(void) printf(gettext("Objects that may be retrieved include:\n"));
141 	(void) printf("\tdebug\t\t");
142 	(void) printf(gettext("the current debug level\n"));
143 	(void) printf("\tpriv\t\t");
144 	(void) printf(gettext("the current privilege level\n"));
145 	(void) printf("\tstats\t\t");
146 	(void) printf(gettext("current usage statistics\n"));
147 	(void) printf("\tp1\t\t");
148 	(void) printf(gettext("a phase 1 SA, identified by\n"));
149 	(void) printf(gettext("\t\t\t  local_ip remote_ip OR\n"));
150 	(void) printf(gettext("\t\t\t  init_cookie resp_cookie\n"));
151 	(void) printf("\trule\t\t");
152 	(void) printf(gettext("a phase 1 rule, identified by its label\n"));
153 	(void) printf("\tpreshared\t");
154 	(void) printf(gettext("a preshared key, identified by\n"));
155 	(void) printf(gettext("\t\t\t  local_ip remote_ip OR\n"));
156 	(void) printf(gettext("\t\t\t  local_id remote_id\n"));
157 	(void) printf("\n");
158 
159 	command_complete(0);
160 }
161 
162 static void
163 print_set_help()
164 {
165 	(void) printf(gettext("This command sets values in in.iked.\n\n"));
166 	(void) printf(gettext("Objects that may be set include:\n"));
167 	(void) printf("\tdebug\t\t");
168 	(void) printf(gettext("change the debug level\n"));
169 	(void) printf("\tpriv\t\t");
170 	(void) printf(
171 	    gettext("change the privilege level (may only be lowered)\n"));
172 	(void) printf("\n");
173 
174 	command_complete(0);
175 }
176 
177 static void
178 print_add_help()
179 {
180 	(void) printf(
181 	    gettext("This command adds items to in.iked's tables.\n\n"));
182 	(void) printf(gettext("Objects that may be set include:\n"));
183 	(void) printf("\trule\t\t");
184 	(void) printf(gettext("a phase 1 policy rule\n"));
185 	(void) printf("\tpreshared\t");
186 	(void) printf(gettext("a preshared key\n"));
187 	(void) printf(
188 	    gettext("\nObjects may be entered on the command-line, as a\n"));
189 	(void) printf(
190 	    gettext("series of keywords and tokens contained in curly\n"));
191 	(void) printf(
192 	    gettext("braces ('{', '}'); or the name of a file containing\n"));
193 	(void) printf(gettext("the object definition may be provided.\n\n"));
194 	(void) printf(
195 	    gettext("For security purposes, preshared keys may only be\n"));
196 	(void) printf(
197 	    gettext("entered on the command-line if ikeadm is running in\n"));
198 	(void) printf(gettext("interactive mode.\n"));
199 	(void) printf("\n");
200 
201 	command_complete(0);
202 }
203 
204 static void
205 print_del_help()
206 {
207 	(void) printf(
208 	    gettext("This command deletes an item from in.iked's tables.\n\n"));
209 	(void) printf(gettext("Objects that may be deleted include:\n"));
210 	(void) printf("\tp1\t\t");
211 	(void) printf(gettext("a phase 1 SA, identified by\n"));
212 	(void) printf(gettext("\t\t\t  local_ip remote_ip OR\n"));
213 	(void) printf(gettext("\t\t\t  init_cookie resp_cookie\n"));
214 	(void) printf("\trule\t\t");
215 	(void) printf(gettext("a phase 1 rule, identified by its label\n"));
216 	(void) printf("\tpreshared\t");
217 	(void) printf(gettext("a preshared key, identified by\n"));
218 	(void) printf(gettext("\t\t\t  local_ip remote_ip OR\n"));
219 	(void) printf(gettext("\t\t\t  local_id remote_id\n"));
220 	(void) printf("\n");
221 
222 	command_complete(0);
223 }
224 
225 static void
226 print_dump_help()
227 {
228 	(void) printf(
229 	    gettext("This command dumps one of in.iked's tables.\n\n"));
230 	(void) printf(gettext("Tables that may be dumped include:\n"));
231 	(void) printf("\tp1\t\t");
232 	(void) printf(gettext("all phase 1 SAs\n"));
233 	(void) printf("\trule\t\t");
234 	(void) printf(gettext("all phase 1 rules\n"));
235 	(void) printf("\tpreshared\t");
236 	(void) printf(gettext("all preshared keys\n"));
237 	(void) printf("\tcertcache\t");
238 	(void) printf(gettext("all cached certificates\n"));
239 	(void) printf("\n");
240 
241 	command_complete(0);
242 }
243 
244 static void
245 print_flush_help()
246 {
247 	(void) printf(
248 	    gettext("This command clears one of in.iked's tables.\n\n"));
249 	(void) printf(gettext("Tables that may be flushed include:\n"));
250 	(void) printf("\tp1\t\t");
251 	(void) printf(gettext("all phase 1 SAs\n"));
252 	(void) printf("\tcertcache\t");
253 	(void) printf(gettext("all cached certificates\n"));
254 	(void) printf("\n");
255 
256 	command_complete(0);
257 }
258 
259 static void
260 print_read_help()
261 {
262 	(void) printf(
263 	    gettext("This command reads a new configuration file into\n"));
264 	(void) printf(
265 	    gettext("in.iked, discarding the old configuration info.\n\n"));
266 	(void) printf(gettext("Sets of data that may be read include:\n"));
267 	(void) printf("\trule\t\t");
268 	(void) printf(gettext("all phase 1 rules\n"));
269 	(void) printf("\tpreshared\t");
270 	(void) printf(gettext("all preshared keys\n\n"));
271 	(void) printf(
272 	    gettext("A filename may be provided to specify a source file\n"));
273 	(void) printf(gettext("other than the default.\n"));
274 	(void) printf("\n");
275 
276 	command_complete(0);
277 }
278 
279 static void
280 print_write_help()
281 {
282 	(void) printf(
283 	    gettext("This command writes in.iked's current configuration\n"));
284 	(void) printf(gettext("out to a config file.\n\n"));
285 	(void) printf(gettext("Sets of data that may be written include:\n"));
286 	(void) printf("\trule\t\t");
287 	(void) printf(gettext("all phase 1 rules\n"));
288 	(void) printf("\tpreshared\t");
289 	(void) printf(gettext("all preshared keys\n\n"));
290 	(void) printf(
291 	    gettext("A filename must be provided to specify the file to\n"));
292 	(void) printf(gettext("which the information should be written.\n"));
293 	(void) printf("\n");
294 
295 	command_complete(0);
296 }
297 
298 static void
299 print_token_help()
300 {
301 	(void) printf(gettext(
302 	    "This command logs IKE into and out of PKCS#11 tokens.\n\n"));
303 	(void) printf(gettext("Commands include:\n"));
304 	(void) printf("\tlogin <PKCS#11 Token Object>\t");
305 	(void) printf(gettext("log into token\n"));
306 	(void) printf("\tlogout <PKCS#11 Token Object>\t");
307 	(void) printf(gettext("log out of token\n\n"));
308 	(void) printf(
309 	    gettext("The PKCS#11 Token Object name must be "
310 	    "enclosed in quotation marks.\n"));
311 	(void) printf("\n");
312 
313 	command_complete(0);
314 }
315 
316 static void
317 print_help_help()
318 {
319 	(void) printf(
320 	    gettext("This command provides information about commands.\n\n"));
321 	(void) printf(
322 	    gettext("The 'help' command alone provides a list of valid\n"));
323 	(void) printf(
324 	    gettext("commands, along with the valid objects for each.\n"));
325 	(void) printf(
326 	    gettext("'help' followed by a valid command name provides\n"));
327 	(void) printf(gettext("further information about that command.\n"));
328 	(void) printf("\n");
329 
330 	command_complete(0);
331 }
332 
333 /*PRINTFLIKE1*/
334 static void
335 message(char *fmt, ...)
336 {
337 	va_list	ap;
338 	char	msgbuf[BUFSIZ];
339 
340 	va_start(ap, fmt);
341 	(void) vsnprintf(msgbuf, BUFSIZ, fmt, ap);
342 	(void) fprintf(stderr, gettext("ikeadm: %s\n"), msgbuf);
343 	va_end(ap);
344 }
345 
346 static int
347 open_door(void)
348 {
349 	if (doorfd >= 0)
350 		(void) close(doorfd);
351 	doorfd = open(DOORNM, O_RDONLY);
352 	return (doorfd);
353 }
354 
355 static ike_service_t *
356 ikedoor_call(char *reqp, int size, door_desc_t *descp, int ndesc)
357 {
358 	door_arg_t	arg;
359 	int retries = 0;
360 
361 	arg.data_ptr = reqp;
362 	arg.data_size = size;
363 	arg.desc_ptr = descp;
364 	arg.desc_num = ndesc;
365 	arg.rbuf = (char *)NULL;
366 	arg.rsize = 0;
367 
368 retry:
369 	if (door_call(doorfd, &arg) < 0) {
370 		if ((errno == EBADF) && ((++retries < 2) &&
371 		    (open_door() >= 0)))
372 			goto retry;
373 		(void) fprintf(stderr,
374 		    gettext("Unable to communicate with in.iked\n"));
375 		Bail("door_call failed");
376 	}
377 
378 	if ((ndesc > 0) && (descp->d_attributes & DOOR_RELEASE) &&
379 	    ((errno == EBADF) || (errno == EFAULT))) {
380 		/* callers assume passed fds will be closed no matter what */
381 		(void) close(descp->d_data.d_desc.d_descriptor);
382 	}
383 
384 	/* LINTED E_BAD_PTR_CAST_ALIGN */
385 	return ((ike_service_t *)arg.rbuf);
386 }
387 
388 /*
389  * Parsing functions
390  */
391 
392 /* stolen from ipseckey.c, with a second tier added */
393 static int
394 parsecmd(char *cmdstr, char *objstr)
395 {
396 #define	MAXOBJS		11
397 	struct objtbl {
398 		char	*obj;
399 		int	token;
400 	};
401 	static struct cmdtbl {
402 		char		*cmd;
403 		int		null_obj_token;
404 		struct objtbl	objt[MAXOBJS];
405 	} table[] = {
406 		{"get", IKE_SVC_ERROR, {
407 				{"debug",	IKE_SVC_GET_DBG},
408 				{"priv",	IKE_SVC_GET_PRIV},
409 				{"stats",	IKE_SVC_GET_STATS},
410 				{"p1",		IKE_SVC_GET_P1},
411 				{"rule",	IKE_SVC_GET_RULE},
412 				{"preshared",	IKE_SVC_GET_PS},
413 				{"defaults",	IKE_SVC_GET_DEFS},
414 				{NULL,		IKE_SVC_ERROR}
415 			}
416 		},
417 		{"set", IKE_SVC_ERROR, {
418 				{"debug",	IKE_SVC_SET_DBG},
419 				{"priv",	IKE_SVC_SET_PRIV},
420 				{NULL,		IKE_SVC_ERROR}
421 			}
422 		},
423 		{"token", IKE_SVC_ERROR, {
424 				{"login",	IKE_SVC_SET_PIN},
425 				{"logout",	IKE_SVC_DEL_PIN},
426 				{NULL,		IKE_SVC_ERROR},
427 			}
428 		},
429 		{"add", IKE_SVC_ERROR, {
430 				{"rule",	IKE_SVC_NEW_RULE},
431 				{"preshared",	IKE_SVC_NEW_PS},
432 				{NULL,		IKE_SVC_ERROR}
433 			}
434 		},
435 		{"del", IKE_SVC_ERROR, {
436 				{"p1",		IKE_SVC_DEL_P1},
437 				{"rule",	IKE_SVC_DEL_RULE},
438 				{"preshared",	IKE_SVC_DEL_PS},
439 				{NULL,		IKE_SVC_ERROR}
440 			}
441 		},
442 		{"dump", IKE_SVC_ERROR, {
443 				{"p1",		IKE_SVC_DUMP_P1S},
444 				{"rule",	IKE_SVC_DUMP_RULES},
445 				{"preshared",	IKE_SVC_DUMP_PS},
446 				{"certcache",	IKE_SVC_DUMP_CERTCACHE},
447 				{NULL,		IKE_SVC_ERROR}
448 			}
449 		},
450 		{"flush", IKE_SVC_ERROR, {
451 				{"p1",		IKE_SVC_FLUSH_P1S},
452 				{"certcache",	IKE_SVC_FLUSH_CERTCACHE},
453 				{NULL,		IKE_SVC_ERROR}
454 			}
455 		},
456 		{"read", IKE_SVC_ERROR, {
457 				{"rule",	IKE_SVC_READ_RULES},
458 				{"preshared",	IKE_SVC_READ_PS},
459 				{NULL,		IKE_SVC_ERROR}
460 			}
461 		},
462 		{"write", IKE_SVC_ERROR, {
463 				{"rule",	IKE_SVC_WRITE_RULES},
464 				{"preshared",	IKE_SVC_WRITE_PS},
465 				{NULL,		IKE_SVC_ERROR}
466 			}
467 		},
468 		{"help", IKEADM_HELP_GENERAL, {
469 				{"get",		IKEADM_HELP_GET},
470 				{"set",		IKEADM_HELP_SET},
471 				{"add",		IKEADM_HELP_ADD},
472 				{"del",		IKEADM_HELP_DEL},
473 				{"dump",	IKEADM_HELP_DUMP},
474 				{"flush",	IKEADM_HELP_FLUSH},
475 				{"read",	IKEADM_HELP_READ},
476 				{"write",	IKEADM_HELP_WRITE},
477 				{"token",	IKEADM_HELP_TOKEN},
478 				{"help",	IKEADM_HELP_HELP},
479 				{NULL,		IKE_SVC_ERROR}
480 			}
481 		},
482 		{"exit", IKEADM_EXIT, {
483 				{NULL,		IKE_SVC_ERROR}
484 			}
485 		},
486 		{"quit", IKEADM_EXIT, {
487 				{NULL,		IKE_SVC_ERROR}
488 			}
489 		},
490 		{"dbg", IKE_SVC_ERROR, {
491 				{"rbdump",	IKE_SVC_DBG_RBDUMP},
492 				{NULL,		IKE_SVC_ERROR}
493 			}
494 		},
495 		{NULL,	IKE_SVC_ERROR, {
496 				{NULL,		IKE_SVC_ERROR}
497 			}
498 		}
499 	};
500 	struct cmdtbl	*ct = table;
501 	struct objtbl	*ot;
502 
503 	if (cmdstr == NULL) {
504 		return (IKE_SVC_ERROR);
505 	}
506 
507 	while (ct->cmd != NULL && strcmp(ct->cmd, cmdstr) != 0)
508 		ct++;
509 	ot = ct->objt;
510 
511 	if (ct->cmd == NULL) {
512 		message(gettext("Unrecognized command '%s'"), cmdstr);
513 		return (ot->token);
514 	}
515 
516 	if (objstr == NULL) {
517 		return (ct->null_obj_token);
518 	}
519 
520 	while (ot->obj != NULL && strcmp(ot->obj, objstr) != 0)
521 		ot++;
522 
523 	if (ot->obj == NULL)
524 		message(gettext("Unrecognized object '%s'"), objstr);
525 
526 	return (ot->token);
527 }
528 
529 /*
530  * Parsing functions:
531  * Parse command-line identification info.  All return -1 on failure,
532  * or the number of cmd-line args "consumed" on success (though argc
533  * and argv params are not actually modified).
534  */
535 
536 static int
537 parse_label(int argc, char **argv, char *label)
538 {
539 	if ((argc < 1) || (argv == NULL))
540 		return (-1);
541 
542 	if (strlcpy(label, argv[0], MAX_LABEL_LEN) >= MAX_LABEL_LEN)
543 		return (-1);
544 
545 	return (1);
546 }
547 
548 /*
549  * Parse a PKCS#11 token get the label.
550  */
551 static int
552 parse_token(int argc, char **argv, char *token_label)
553 {
554 	if ((argc < 1) || (argv == NULL))
555 		return (-1);
556 
557 	if (strlcpy(token_label, argv[0], PKCS11_TOKSIZE) >= PKCS11_TOKSIZE)
558 		return (-1);
559 
560 	return (0);
561 }
562 
563 /*
564  * Parse an address off the command line. In the hpp param, either
565  * return a hostent pointer (caller frees) or a pointer to a dummy_he_t
566  * (must also be freed by the caller; both cases are handled by the
567  * macro FREE_HE).  The new getipnodebyname() call does the Right Thing
568  * (TM), even with raw addresses (colon-separated IPv6 or dotted decimal
569  * IPv4).
570  * (mostly stolen from ipseckey.c, though some tweaks were made
571  * to better serve our purposes here.)
572  */
573 
574 typedef struct {
575 	struct hostent	he;
576 	char		*addtl[2];
577 } dummy_he_t;
578 
579 static int
580 parse_addr(int argc, char **argv, struct hostent **hpp)
581 {
582 	int		hp_errno;
583 	struct hostent	*hp = NULL;
584 	dummy_he_t	*dhp;
585 	char		*addr1;
586 
587 	if ((argc < 1) || (argv == NULL) || (argv[0] == NULL))
588 		return (-1);
589 
590 	if (!nflag) {
591 		/*
592 		 * Try name->address first.  Assume AF_INET6, and
593 		 * get IPV4s, plus IPv6s iff IPv6 is configured.
594 		 */
595 		hp = getipnodebyname(argv[0], AF_INET6, AI_DEFAULT | AI_ALL,
596 		    &hp_errno);
597 	} else {
598 		/*
599 		 * Try a normal address conversion only.  malloc a
600 		 * dummy_he_t to construct a fake hostent.  Caller
601 		 * will know to free this one using free_he().
602 		 */
603 		dhp = (dummy_he_t *)malloc(sizeof (dummy_he_t));
604 		addr1 = (char *)malloc(sizeof (struct in6_addr));
605 		if (inet_pton(AF_INET6, argv[0], addr1) == 1) {
606 			dhp->he.h_addr_list = dhp->addtl;
607 			dhp->addtl[0] = addr1;
608 			dhp->addtl[1] = NULL;
609 			hp = &dhp->he;
610 			dhp->he.h_addrtype = AF_INET6;
611 			dhp->he.h_length = sizeof (struct in6_addr);
612 		} else if (inet_pton(AF_INET, argv[0], addr1) == 1) {
613 			dhp->he.h_addr_list = dhp->addtl;
614 			dhp->addtl[0] = addr1;
615 			dhp->addtl[1] = NULL;
616 			hp = &dhp->he;
617 			dhp->he.h_addrtype = AF_INET;
618 			dhp->he.h_length = sizeof (struct in_addr);
619 		} else {
620 			hp = NULL;
621 		}
622 	}
623 
624 	*hpp = hp;
625 
626 	if (hp == NULL) {
627 		message(gettext("Unknown address %s."), argv[0]);
628 		return (-1);
629 	}
630 
631 	return (1);
632 }
633 
634 /*
635  * Free a dummy_he_t structure that was malloc'd in parse_addr().
636  * Unfortunately, callers of parse_addr don't want to know about
637  * dummy_he_t structs, so all they have is a pointer to the struct
638  * hostent; so that's what's passed in.  To manage this, we make
639  * the assumption that the struct hostent is the first field in
640  * the dummy_he_t, and therefore a pointer to it is a pointer to
641  * the dummy_he_t.
642  */
643 static void
644 free_he(struct hostent *hep)
645 {
646 	dummy_he_t	*p = (dummy_he_t *)hep;
647 
648 	assert(p != NULL);
649 
650 	if (p->addtl[0])
651 		free(p->addtl[0]);
652 	if (p->addtl[1])
653 		free(p->addtl[1]);
654 
655 	free(p);
656 }
657 
658 #define	FREE_HE(x) \
659 	if (nflag) \
660 		free_he(x); \
661 	else \
662 		freehostent(x)
663 
664 static void
665 headdr2sa(char *hea, struct sockaddr_storage *sa, int len)
666 {
667 	struct sockaddr_in	*sin;
668 	struct sockaddr_in6	*sin6;
669 
670 	if (len == sizeof (struct in6_addr)) {
671 		/* LINTED E_BAD_PTR_CAST_ALIGN */
672 		if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)hea)) {
673 			sin = (struct sockaddr_in *)sa;
674 			(void) memset(sin, 0, sizeof (*sin));
675 			/* LINTED E_BAD_PTR_CAST_ALIGN */
676 			IN6_V4MAPPED_TO_INADDR((struct in6_addr *)hea,
677 			    &sin->sin_addr);
678 			sin->sin_family = AF_INET;
679 		} else {
680 			sin6 = (struct sockaddr_in6 *)sa;
681 			(void) memset(sin6, 0, sizeof (*sin6));
682 			(void) memcpy(&sin6->sin6_addr, hea,
683 			    sizeof (struct in6_addr));
684 			sin6->sin6_family = AF_INET6;
685 		}
686 	} else {
687 		sin = (struct sockaddr_in *)sa;
688 		(void) memset(sin, 0, sizeof (*sin));
689 		(void) memcpy(&sin->sin_addr, hea, sizeof (struct in_addr));
690 		sin->sin_family = AF_INET;
691 	}
692 }
693 
694 /*
695  * The possible ident-type keywords that might be used on the command
696  * line.  This is a superset of the ones supported by ipseckey, those
697  * in the ike config file, and those in ike.preshared.
698  */
699 static keywdtab_t	idtypes[] = {
700 	/* ip, ipv4, and ipv6 are valid for preshared keys... */
701 	{SADB_IDENTTYPE_RESERVED,	"ip"},
702 	{SADB_IDENTTYPE_RESERVED,	"ipv4"},
703 	{SADB_IDENTTYPE_RESERVED,	"ipv6"},
704 	{SADB_IDENTTYPE_PREFIX,		"prefix"},
705 	{SADB_IDENTTYPE_PREFIX,		"ipv4-prefix"},
706 	{SADB_IDENTTYPE_PREFIX,		"ipv6-prefix"},
707 	{SADB_IDENTTYPE_PREFIX,		"subnet"},
708 	{SADB_IDENTTYPE_PREFIX,		"subnetv4"},
709 	{SADB_IDENTTYPE_PREFIX,		"subnetv6"},
710 	{SADB_IDENTTYPE_FQDN,		"fqdn"},
711 	{SADB_IDENTTYPE_FQDN,		"dns"},
712 	{SADB_IDENTTYPE_FQDN,		"domain"},
713 	{SADB_IDENTTYPE_FQDN,		"domainname"},
714 	{SADB_IDENTTYPE_USER_FQDN,	"user_fqdn"},
715 	{SADB_IDENTTYPE_USER_FQDN,	"mbox"},
716 	{SADB_IDENTTYPE_USER_FQDN,	"mailbox"},
717 	{SADB_X_IDENTTYPE_DN,		"dn"},
718 	{SADB_X_IDENTTYPE_DN,		"asn1dn"},
719 	{SADB_X_IDENTTYPE_GN,		"gn"},
720 	{SADB_X_IDENTTYPE_GN,		"asn1gn"},
721 	{SADB_X_IDENTTYPE_ADDR_RANGE,	"ipv4-range"},
722 	{SADB_X_IDENTTYPE_ADDR_RANGE,	"ipv6-range"},
723 	{SADB_X_IDENTTYPE_ADDR_RANGE,	"rangev4"},
724 	{SADB_X_IDENTTYPE_ADDR_RANGE,	"rangev6"},
725 	{SADB_X_IDENTTYPE_KEY_ID,	"keyid"},
726 	{NULL,	0}
727 };
728 
729 static int
730 parse_idtype(char *type, uint16_t *idnum)
731 {
732 	keywdtab_t	*idp;
733 
734 	if (type == NULL)
735 		return (-1);
736 
737 	for (idp = idtypes; idp->kw_str != NULL; idp++) {
738 		if (strcasecmp(idp->kw_str, type) == 0) {
739 			if (idnum != NULL)
740 				*idnum = idp->kw_tag;
741 			return (1);
742 		}
743 	}
744 
745 	return (-1);
746 }
747 
748 /*
749  * The sadb_ident_t is malloc'd, since its length varies;
750  * so the caller must free() it when done with the data.
751  */
752 static int
753 parse_ident(int argc, char **argv, sadb_ident_t **idpp)
754 {
755 	int		alloclen, consumed;
756 	sadb_ident_t	*idp;
757 	if ((argc < 2) || (argv == NULL) || (argv[0] == NULL) ||
758 	    (argv[1] == NULL))
759 		return (-1);
760 
761 	alloclen = sizeof (sadb_ident_t) + IKEDOORROUNDUP(strlen(argv[1]) + 1);
762 	*idpp = idp = (sadb_ident_t *)malloc(alloclen);
763 	if (idp == NULL)
764 		Bail("parsing identity");
765 
766 	if ((consumed = parse_idtype(argv[0], &idp->sadb_ident_type)) < 0) {
767 		message(gettext("unknown identity type %s."), argv[0]);
768 		return (-1);
769 	}
770 
771 	idp->sadb_ident_len = SADB_8TO64(alloclen);
772 	idp->sadb_ident_reserved = 0;
773 	idp->sadb_ident_id = 0;
774 
775 	/* now copy in identity param */
776 	(void) strlcpy((char *)(idp + 1), argv[1],
777 	    alloclen - (sizeof (sadb_ident_t)));
778 
779 	return (++consumed);
780 }
781 
782 static int
783 parse_cky(int argc, char **argv, uint64_t *ckyp)
784 {
785 	u_longlong_t	arg;
786 
787 	if ((argc < 1) || (argv[0] == NULL))
788 		return (-1);
789 
790 	errno = 0;
791 	arg = strtoull(argv[0], NULL, 0);
792 	if (errno != 0) {
793 		message(gettext("failed to parse cookie %s."), argv[0]);
794 		return (-1);
795 	}
796 
797 	*ckyp = (uint64_t)arg;
798 
799 	return (1);
800 }
801 
802 static int
803 parse_addr_pr(int argc, char **argv, struct hostent **h1pp,
804 	struct hostent **h2pp)
805 {
806 	int	rtn, consumed = 0;
807 
808 	if ((rtn = parse_addr(argc, argv, h1pp)) < 0) {
809 		return (-1);
810 	}
811 	consumed = rtn;
812 	argc -= rtn;
813 	argv += rtn;
814 
815 	if ((rtn = parse_addr(argc, argv, h2pp)) < 0) {
816 		FREE_HE(*h1pp);
817 		return (-1);
818 	}
819 	consumed += rtn;
820 
821 	return (consumed);
822 }
823 
824 /*
825  * The sadb_ident_ts are malloc'd, since their length varies;
826  * so the caller must free() them when done with the data.
827  */
828 static int
829 parse_ident_pr(int argc, char **argv, sadb_ident_t **id1pp,
830     sadb_ident_t **id2pp)
831 {
832 	int	rtn, consumed = 0;
833 
834 	if ((rtn = parse_ident(argc, argv, id1pp)) < 0) {
835 		return (-1);
836 	}
837 	consumed = rtn;
838 	argc -= rtn;
839 	argv += rtn;
840 
841 	(*id1pp)->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC;
842 
843 	if ((rtn = parse_ident(argc, argv, id2pp)) < 0) {
844 		free(*id1pp);
845 		return (-1);
846 	}
847 	consumed += rtn;
848 
849 	(*id2pp)->sadb_ident_exttype = SADB_EXT_IDENTITY_DST;
850 
851 	return (consumed);
852 }
853 
854 static int
855 parse_cky_pr(int argc, char **argv, ike_cky_pr_t *cpr)
856 {
857 	int	rtn, consumed = 0;
858 
859 	if ((rtn = parse_cky(argc, argv, &cpr->cky_i)) < 0) {
860 		return (-1);
861 	}
862 	consumed = rtn;
863 	argc -= rtn;
864 	argv += rtn;
865 
866 	if ((rtn = parse_cky(argc, argv, &cpr->cky_r)) < 0) {
867 		return (-1);
868 	}
869 	consumed += rtn;
870 
871 	return (consumed);
872 }
873 
874 /*
875  * Preshared key field types...used for parsing preshared keys that
876  * have been entered on the command line.  The code to parse preshared
877  * keys (parse_ps, parse_key, parse_psfldid, parse_ikmtype, ...) is
878  * mostly duplicated from in.iked's readps.c.
879  */
880 #define	PSFLD_LOCID	1
881 #define	PSFLD_LOCIDTYPE	2
882 #define	PSFLD_REMID	3
883 #define	PSFLD_REMIDTYPE	4
884 #define	PSFLD_MODE	5
885 #define	PSFLD_KEY	6
886 
887 static keywdtab_t	psfldtypes[] = {
888 	{PSFLD_LOCID,		"localid"},
889 	{PSFLD_LOCIDTYPE,	"localidtype"},
890 	{PSFLD_REMID,		"remoteid"},
891 	{PSFLD_REMIDTYPE,	"remoteidtype"},
892 	{PSFLD_MODE,		"ike_mode"},
893 	{PSFLD_KEY,		"key"},
894 	{NULL,	0}
895 };
896 
897 static int
898 parse_psfldid(char *type, uint16_t *idnum)
899 {
900 	keywdtab_t	*pfp;
901 
902 	if (type == NULL)
903 		return (-1);
904 
905 	for (pfp = psfldtypes; pfp->kw_str != NULL; pfp++) {
906 		if (strcasecmp(pfp->kw_str, type) == 0) {
907 			if (idnum != NULL)
908 				*idnum = pfp->kw_tag;
909 			return (1);
910 		}
911 	}
912 
913 	return (-1);
914 }
915 
916 static keywdtab_t	ikemodes[] = {
917 	{IKE_XCHG_IDENTITY_PROTECT,	"main"},
918 	{IKE_XCHG_AGGRESSIVE,		"aggressive"},
919 	{IKE_XCHG_IP_AND_AGGR,		"both"},
920 	{NULL,	0}
921 };
922 
923 static int
924 parse_ikmtype(char *mode, uint16_t *modenum)
925 {
926 	keywdtab_t	*ikmp;
927 
928 	if (mode == NULL)
929 		return (-1);
930 
931 	for (ikmp = ikemodes; ikmp->kw_str != NULL; ikmp++) {
932 		if (strcasecmp(ikmp->kw_str, mode) == 0) {
933 			if (modenum != NULL)
934 				*modenum = ikmp->kw_tag;
935 			return (1);
936 		}
937 	}
938 
939 	return (-1);
940 }
941 
942 #define	hd2num(hd) (((hd) >= '0' && (hd) <= '9') ? ((hd) - '0') : \
943 	(((hd) >= 'a' && (hd) <= 'f') ? ((hd) - 'a' + 10) : ((hd) - 'A' + 10)))
944 
945 static uint8_t *
946 parse_key(char *input, uint_t *keybuflen, uint_t *lbits)
947 {
948 	uint8_t	*keyp, *keybufp;
949 	uint_t	i, hexlen = 0, bits, alloclen;
950 
951 	for (i = 0; input[i] != '\0' && input[i] != '/'; i++)
952 		hexlen++;
953 
954 	if (input[i] == '\0') {
955 		bits = 0;
956 	} else {
957 		/* Have /nn. */
958 		input[i] = '\0';
959 		if (sscanf((input + i + 1), "%u", &bits) != 1)
960 			return (NULL);
961 
962 		/* hexlen is in nibbles */
963 		if (((bits + 3) >> 2) > hexlen)
964 			return (NULL);
965 
966 		/*
967 		 * Adjust hexlen down if user gave us too small of a bit
968 		 * count.
969 		 */
970 		if ((hexlen << 2) > bits + 3) {
971 			hexlen = (bits + 3) >> 2;
972 			input[hexlen] = '\0';
973 		}
974 	}
975 
976 	/*
977 	 * Allocate.  Remember, hexlen is in nibbles.
978 	 */
979 
980 	alloclen = (hexlen/2 + (hexlen & 0x1));
981 	keyp = malloc(alloclen);
982 
983 	if (keyp == NULL)
984 		return (NULL);
985 
986 	keybufp = keyp;
987 	*keybuflen = alloclen;
988 	if (bits == 0)
989 		*lbits = (hexlen + (hexlen & 0x1)) << 2;
990 	else
991 		*lbits = bits;
992 
993 	/*
994 	 * Read in nibbles.  Read in odd-numbered as shifted high.
995 	 * (e.g. 123 becomes 0x1230).
996 	 */
997 	for (i = 0; input[i] != '\0'; i += 2) {
998 		boolean_t second = (input[i + 1] != '\0');
999 
1000 		if (!isxdigit(input[i]) ||
1001 		    (!isxdigit(input[i + 1]) && second)) {
1002 			free(keyp);
1003 			return (NULL);
1004 		}
1005 		*keyp = (hd2num(input[i]) << 4);
1006 		if (second)
1007 			*keyp |= hd2num(input[i + 1]);
1008 		else
1009 			break; /* out of for loop. */
1010 		keyp++;
1011 	}
1012 
1013 	/* zero the remaining bits if we're a non-octet amount. */
1014 	if (bits & 0x7)
1015 		*((input[i] == '\0') ? keyp - 1 : keyp) &=
1016 		    0xff << (8 - (bits & 0x7));
1017 	return (keybufp);
1018 }
1019 
1020 /*
1021  * the ike_ps_t struct (plus trailing data) will be allocated here,
1022  * so it will need to be freed by the caller.
1023  */
1024 static int
1025 parse_ps(int argc, char **argv, ike_ps_t **presharedpp, int *len)
1026 {
1027 	uint_t		c = 0, locidlen, remidlen, keylen, keybits;
1028 	uint_t		a_locidtotal = 0, a_remidtotal = 0;
1029 	char		*locid, *remid;
1030 	uint8_t		*keyp = NULL;
1031 	uint16_t	fldid, locidtype, remidtype, mtype;
1032 	struct hostent	*loche = NULL, *remhe = NULL;
1033 	ike_ps_t	*psp = NULL;
1034 	sadb_ident_t	*sidp;
1035 	boolean_t	whacked = B_FALSE;
1036 
1037 	if ((argv[c] == NULL) || (argv[c][0] != '{'))
1038 		return (-1);
1039 	if (argv[c][1] != 0) {
1040 		/* no space between '{' and first token */
1041 		argv[c]++;
1042 	} else {
1043 		c++;
1044 	}
1045 	if ((argv[argc - 1][strlen(argv[argc - 1]) - 1] == '}') &&
1046 	    (argv[argc - 1][0] != '}')) {
1047 		/*
1048 		 * whack '}' without a space before it or parsers break.
1049 		 * Remember this trailing character for later
1050 		 */
1051 		argv[argc - 1][strlen(argv[argc - 1]) - 1] = '\0';
1052 		whacked = B_TRUE;
1053 	}
1054 
1055 	while ((c < argc) && (argv[c] != NULL) && (argv[c][0] != '}')) {
1056 		if ((argv[c + 1] == NULL) || (argv[c + 1][0] == '}'))
1057 			goto bail;
1058 		if (parse_psfldid(argv[c++], &fldid) < 0)
1059 			goto bail;
1060 		switch (fldid) {
1061 		case PSFLD_LOCID:
1062 			locid = argv[c++];
1063 			locidlen = strlen(locid) + 1;
1064 			break;
1065 		case PSFLD_LOCIDTYPE:
1066 			if (parse_idtype(argv[c++], &locidtype) < 0)
1067 				goto bail;
1068 			break;
1069 		case PSFLD_REMID:
1070 			remid = argv[c++];
1071 			remidlen = strlen(remid) + 1;
1072 			break;
1073 		case PSFLD_REMIDTYPE:
1074 			if (parse_idtype(argv[c++], &remidtype) < 0)
1075 				goto bail;
1076 			break;
1077 		case PSFLD_MODE:
1078 			if (parse_ikmtype(argv[c++], &mtype) < 0)
1079 				goto bail;
1080 			break;
1081 		case PSFLD_KEY:
1082 			keyp  = parse_key(argv[c++], &keylen, &keybits);
1083 			if (keyp == NULL)
1084 				goto bail;
1085 			break;
1086 		}
1087 	}
1088 
1089 	/* Make sure the line was terminated with '}' */
1090 	if (argv[c] == NULL) {
1091 		if (!whacked)
1092 			goto bail;
1093 	} else if (argv[c][0] != '}') {
1094 		goto bail;
1095 	}
1096 
1097 	/*
1098 	 * make sure we got all the required fields.  If no idtype, assume
1099 	 * ip addr; if that translation fails, we'll catch the error then.
1100 	 */
1101 	if (locid == NULL || remid == NULL || keyp == NULL || mtype == 0)
1102 		goto bail;
1103 
1104 	/* figure out the size buffer we need */
1105 	*len = sizeof (ike_ps_t);
1106 	if (locidtype != SADB_IDENTTYPE_RESERVED) {
1107 		a_locidtotal = IKEDOORROUNDUP(sizeof (sadb_ident_t) + locidlen);
1108 		*len += a_locidtotal;
1109 	}
1110 	if (remidtype != SADB_IDENTTYPE_RESERVED) {
1111 		a_remidtotal = IKEDOORROUNDUP(sizeof (sadb_ident_t) + remidlen);
1112 		*len += a_remidtotal;
1113 	}
1114 	*len += keylen;
1115 
1116 	psp = malloc(*len);
1117 	if (psp == NULL)
1118 		goto bail;
1119 	(void) memset(psp, 0, *len);
1120 
1121 	psp->ps_ike_mode = mtype;
1122 
1123 	psp->ps_localid_off = sizeof (ike_ps_t);
1124 	if (locidtype == SADB_IDENTTYPE_RESERVED) {
1125 		/*
1126 		 * this is an ip address, store in the sockaddr field;
1127 		 * we won't use an sadb_ident_t.
1128 		 */
1129 		psp->ps_localid_len = 0;
1130 		if (parse_addr(1, &locid, &loche) < 0)
1131 			goto bail;
1132 		if (loche->h_addr_list[1] != NULL) {
1133 			message(gettext("preshared key identifier cannot "
1134 			    "match multiple IP addresses"));
1135 			goto bail;
1136 		}
1137 		headdr2sa(loche->h_addr_list[0], &psp->ps_ipaddrs.loc_addr,
1138 		    loche->h_length);
1139 		FREE_HE(loche);
1140 	} else {
1141 		psp->ps_localid_len = sizeof (sadb_ident_t) + locidlen;
1142 		sidp = (sadb_ident_t *)((int)psp + psp->ps_localid_off);
1143 		sidp->sadb_ident_len = psp->ps_localid_len;
1144 		sidp->sadb_ident_type = locidtype;
1145 		(void) strlcpy((char *)(sidp + 1), locid, a_locidtotal);
1146 	}
1147 
1148 	psp->ps_remoteid_off = psp->ps_localid_off + a_locidtotal;
1149 	if (remidtype == SADB_IDENTTYPE_RESERVED) {
1150 		/*
1151 		 * this is an ip address, store in the sockaddr field;
1152 		 * we won't use an sadb_ident_t.
1153 		 */
1154 		psp->ps_remoteid_len = 0;
1155 		if (parse_addr(1, &remid, &remhe) < 0)
1156 			goto bail;
1157 		if (remhe->h_addr_list[1] != NULL) {
1158 			message(gettext("preshared key identifier cannot "
1159 			    "match multiple IP addresses"));
1160 			goto bail;
1161 		}
1162 		headdr2sa(remhe->h_addr_list[0], &psp->ps_ipaddrs.rem_addr,
1163 		    remhe->h_length);
1164 		FREE_HE(remhe);
1165 	} else {
1166 		/* make sure we have at least 16-bit alignment */
1167 		if (remidlen & 0x1)
1168 			remidlen++;
1169 		psp->ps_remoteid_len = sizeof (sadb_ident_t) + remidlen;
1170 		sidp = (sadb_ident_t *)((int)psp + psp->ps_remoteid_off);
1171 		sidp->sadb_ident_len = psp->ps_remoteid_len;
1172 		sidp->sadb_ident_type = remidtype;
1173 		(void) strlcpy((char *)(sidp + 1), remid, a_remidtotal);
1174 	}
1175 
1176 	psp->ps_key_off = psp->ps_remoteid_off + a_remidtotal;
1177 	psp->ps_key_len = keylen;
1178 	psp->ps_key_bits = keybits;
1179 	(void) memcpy((uint8_t *)((int)psp + psp->ps_key_off), keyp, keylen);
1180 
1181 	*presharedpp = psp;
1182 
1183 	return (c);
1184 
1185 bail:
1186 	if (loche != NULL)
1187 		FREE_HE(loche);
1188 	if (remhe != NULL)
1189 		FREE_HE(remhe);
1190 	if (keyp != NULL)
1191 		free(keyp);
1192 	if (psp != NULL)
1193 		free(psp);
1194 
1195 	*presharedpp = NULL;
1196 
1197 	return (-1);
1198 }
1199 
1200 /*
1201  * Printing functions
1202  *
1203  * A potential point of confusion here is that the ikeadm-specific string-
1204  * producing functions do not match the ipsec_util.c versions in style: the
1205  * ikeadm-specific functions return a string (and are named foostr), while
1206  * the ipsec_util.c functions actually print the string to the file named
1207  * in the second arg to the function (and are named dump_foo).
1208  *
1209  * Localization for ikeadm seems more straightforward when complete
1210  * phrases are translated rather than: a part of a phrase, a call to
1211  * dump_foo(), and more of the phrase.  It could also accommodate
1212  * non-English grammar more easily.
1213  */
1214 
1215 static char *
1216 errstr(int err)
1217 {
1218 	static char	rtn[MAXLINESIZE];
1219 
1220 	switch (err) {
1221 	case IKE_ERR_NO_OBJ:
1222 		return (gettext("No data returned"));
1223 	case IKE_ERR_NO_DESC:
1224 		return (gettext("No destination provided"));
1225 	case IKE_ERR_ID_INVALID:
1226 		return (gettext("Id info invalid"));
1227 	case IKE_ERR_LOC_INVALID:
1228 		return (gettext("Destination invalid"));
1229 	case IKE_ERR_CMD_INVALID:
1230 		return (gettext("Command invalid"));
1231 	case IKE_ERR_DATA_INVALID:
1232 		return (gettext("Supplied data invalid"));
1233 	case IKE_ERR_CMD_NOTSUP:
1234 		return (gettext("Unknown command"));
1235 	case IKE_ERR_REQ_INVALID:
1236 		return (gettext("Request invalid"));
1237 	case IKE_ERR_NO_PRIV:
1238 		return (gettext("Not allowed at current privilege level"));
1239 	case IKE_ERR_NO_AUTH:
1240 		return (gettext("User not authorized"));
1241 	case IKE_ERR_SYS_ERR:
1242 		return (gettext("System error"));
1243 	case IKE_ERR_DUP_IGNORED:
1244 		return (gettext("One or more duplicate entries ignored"));
1245 	case IKE_ERR_NO_TOKEN:
1246 		return (gettext(
1247 		    "token login failed or no objects on device"));
1248 	case IKE_ERR_IN_PROGRESS:
1249 		return (gettext(
1250 		    "Duplicate operation already in progress"));
1251 	case IKE_ERR_NO_MEM:
1252 		return (gettext(
1253 		    "Insufficient memory"));
1254 	default:
1255 		(void) snprintf(rtn, MAXLINESIZE,
1256 		    gettext("<unknown error %d>"), err);
1257 		return (rtn);
1258 	}
1259 }
1260 
1261 static char *
1262 dbgstr(int bit)
1263 {
1264 	static char	rtn[MAXLINESIZE];
1265 
1266 	switch (bit) {
1267 	case D_CERT:
1268 		return (gettext("Certificate management"));
1269 	case D_KEY:
1270 		return (gettext("Key management"));
1271 	case D_OP:
1272 		return (gettext("Operational"));
1273 	case D_P1:
1274 		return (gettext("Phase 1 SA creation"));
1275 	case D_P2:
1276 		return (gettext("Phase 2 SA creation"));
1277 	case D_PFKEY:
1278 		return (gettext("PF_KEY interface"));
1279 	case D_POL:
1280 		return (gettext("Policy management"));
1281 	case D_PROP:
1282 		return (gettext("Proposal construction"));
1283 	case D_DOOR:
1284 		return (gettext("Door interface"));
1285 	case D_CONFIG:
1286 		return (gettext("Config file processing"));
1287 	case D_LABEL:
1288 		return (gettext("MAC label processing"));
1289 	default:
1290 		(void) snprintf(rtn, MAXLINESIZE,
1291 		    gettext("<unknown flag 0x%x>"), bit);
1292 		return (rtn);
1293 	}
1294 }
1295 
1296 static char *
1297 privstr(int priv)
1298 {
1299 	static char	rtn[MAXLINESIZE];
1300 
1301 	switch (priv) {
1302 	case IKE_PRIV_MINIMUM:
1303 		return (gettext("base privileges"));
1304 	case IKE_PRIV_MODKEYS:
1305 		return (gettext("access to preshared key information"));
1306 	case IKE_PRIV_KEYMAT:
1307 		return (gettext("access to keying material"));
1308 	default:
1309 		(void) snprintf(rtn, MAXLINESIZE,
1310 		    gettext("<unknown level %d>"), priv);
1311 		return (rtn);
1312 	}
1313 }
1314 
1315 static char *
1316 xchgstr(int xchg)
1317 {
1318 	static char	rtn[MAXLINESIZE];
1319 
1320 	switch (xchg) {
1321 	case IKE_XCHG_NONE:
1322 		return (gettext("<unspecified>"));
1323 	case IKE_XCHG_BASE:
1324 		return (gettext("base"));
1325 	case IKE_XCHG_IDENTITY_PROTECT:
1326 		return (gettext("main mode (identity protect)"));
1327 	case IKE_XCHG_AUTH_ONLY:
1328 		return (gettext("authentication only"));
1329 	case IKE_XCHG_AGGRESSIVE:
1330 		return (gettext("aggressive mode"));
1331 	case IKE_XCHG_IP_AND_AGGR:
1332 		return (gettext("main and aggressive mode"));
1333 	case IKE_XCHG_ANY:
1334 		return (gettext("any mode"));
1335 	default:
1336 		(void) snprintf(rtn, MAXLINESIZE,
1337 		    gettext("<unknown %d>"), xchg);
1338 		return (rtn);
1339 	}
1340 }
1341 
1342 static char *
1343 statestr(int state)
1344 {
1345 	static char	rtn[MAXLINESIZE];
1346 
1347 	switch (state) {
1348 	case IKE_SA_STATE_INIT:
1349 		return (gettext("INITIALIZING"));
1350 	case IKE_SA_STATE_SENT_SA:
1351 		return (gettext("SENT FIRST MSG (SA)"));
1352 	case IKE_SA_STATE_SENT_KE:
1353 		return (gettext("SENT SECOND MSG (KE)"));
1354 	case IKE_SA_STATE_SENT_LAST:
1355 		return (gettext("SENT FINAL MSG"));
1356 	case IKE_SA_STATE_DONE:
1357 		return (gettext("ACTIVE"));
1358 	case IKE_SA_STATE_DELETED:
1359 		return (gettext("DELETED"));
1360 	case IKE_SA_STATE_INVALID:
1361 		return (gettext("<invalid>"));
1362 	default:
1363 		(void) snprintf(rtn, MAXLINESIZE,
1364 		    gettext("<unknown %d>"), state);
1365 		return (rtn);
1366 	}
1367 }
1368 
1369 static char *
1370 authmethstr(int meth)
1371 {
1372 	static char	rtn[MAXLINESIZE];
1373 
1374 	switch (meth) {
1375 	case IKE_AUTH_METH_PRE_SHARED_KEY:
1376 		return (gettext("pre-shared key"));
1377 	case IKE_AUTH_METH_DSS_SIG:
1378 		return (gettext("DSS signatures"));
1379 	case IKE_AUTH_METH_RSA_SIG:
1380 		return (gettext("RSA signatures"));
1381 	case IKE_AUTH_METH_RSA_ENCR:
1382 		return (gettext("RSA Encryption"));
1383 	case IKE_AUTH_METH_RSA_ENCR_REVISED:
1384 		return (gettext("Revised RSA Encryption"));
1385 	default:
1386 		(void) snprintf(rtn, MAXLINESIZE,
1387 		    gettext("<unknown %d>"), meth);
1388 		return (rtn);
1389 	}
1390 }
1391 
1392 static char *
1393 prfstr(int prf)
1394 {
1395 	static char	rtn[MAXLINESIZE];
1396 
1397 	switch (prf) {
1398 	case IKE_PRF_NONE:
1399 		return (gettext("<none/unavailable>"));
1400 	case IKE_PRF_HMAC_MD5:
1401 		return ("HMAC MD5");
1402 	case IKE_PRF_HMAC_SHA1:
1403 		return ("HMAC SHA1");
1404 	case IKE_PRF_HMAC_SHA256:
1405 		return ("HMAC SHA256");
1406 	case IKE_PRF_HMAC_SHA384:
1407 		return ("HMAC SHA384");
1408 	case IKE_PRF_HMAC_SHA512:
1409 		return ("HMAC SHA512");
1410 	default:
1411 		(void) snprintf(rtn, MAXLINESIZE,
1412 		    gettext("<unknown %d>"), prf);
1413 		return (rtn);
1414 	}
1415 }
1416 
1417 static char *
1418 dhstr(int grp)
1419 {
1420 	static char	rtn[MAXLINESIZE];
1421 
1422 	switch (grp) {
1423 	case 0:
1424 		return (gettext("<unavailable>"));
1425 	case IKE_GRP_DESC_MODP_768:
1426 		return (gettext("768-bit MODP (group 1)"));
1427 	case IKE_GRP_DESC_MODP_1024:
1428 		return (gettext("1024-bit MODP (group 2)"));
1429 	case IKE_GRP_DESC_EC2N_155:
1430 		return (gettext("EC2N group on GP[2^155]"));
1431 	case IKE_GRP_DESC_EC2N_185:
1432 		return (gettext("EC2N group on GP[2^185]"));
1433 	case IKE_GRP_DESC_MODP_1536:
1434 		return (gettext("1536-bit MODP (group 5)"));
1435 	case IKE_GRP_DESC_MODP_2048:
1436 		return (gettext("2048-bit MODP (group 14)"));
1437 	case IKE_GRP_DESC_MODP_3072:
1438 		return (gettext("3072-bit MODP (group 15)"));
1439 	case IKE_GRP_DESC_MODP_4096:
1440 		return (gettext("4096-bit MODP (group 16)"));
1441 	case IKE_GRP_DESC_MODP_6144:
1442 		return (gettext("6144-bit MODP (group 17)"));
1443 	case IKE_GRP_DESC_MODP_8192:
1444 		return (gettext("8192-bit MODP (group 18)"));
1445 	case IKE_GRP_DESC_ECP_256:
1446 		return (gettext("256-bit ECP (group 19)"));
1447 	case IKE_GRP_DESC_ECP_384:
1448 		return (gettext("384-bit ECP (group 20)"));
1449 	case IKE_GRP_DESC_ECP_521:
1450 		return (gettext("521-bit ECP (group 21)"));
1451 	case IKE_GRP_DESC_MODP_1024_160:
1452 		return (
1453 		    gettext("1024-bit MODP with 160-bit subprime (group 22)"));
1454 	case IKE_GRP_DESC_MODP_2048_224:
1455 		return (
1456 		    gettext("2048-bit MODP with 224-bit subprime (group 23)"));
1457 	case IKE_GRP_DESC_MODP_2048_256:
1458 		return (
1459 		    gettext("2048-bit MODP with 256-bit subprime (group 24)"));
1460 	case IKE_GRP_DESC_ECP_192:
1461 		return (gettext("192-bit ECP (group 25)"));
1462 	case IKE_GRP_DESC_ECP_224:
1463 		return (gettext("224-bit ECP (group 26)"));
1464 	default:
1465 		(void) snprintf(rtn, MAXLINESIZE, gettext("<unknown %d>"), grp);
1466 		return (rtn);
1467 	}
1468 }
1469 
1470 static void
1471 print_hdr(char *prefix, ike_p1_hdr_t *hdrp)
1472 {
1473 	char sbuf[TBUF_SIZE];
1474 	char tbuf[TBUF_SIZE];
1475 	time_t ltime = (time_t)hdrp->p1hdr_dpd_time;
1476 
1477 	(void) printf(
1478 	    gettext("%s Cookies: Initiator 0x%llx  Responder 0x%llx\n"),
1479 	    prefix, ntohll(hdrp->p1hdr_cookies.cky_i),
1480 	    ntohll(hdrp->p1hdr_cookies.cky_r));
1481 	(void) printf(gettext("%s The local host is the %s.\n"), prefix,
1482 	    hdrp->p1hdr_isinit ? gettext("initiator") : gettext("responder"));
1483 	(void) printf(gettext("%s ISAKMP version %d.%d; %s exchange\n"), prefix,
1484 	    hdrp->p1hdr_major, hdrp->p1hdr_minor, xchgstr(hdrp->p1hdr_xchg));
1485 	(void) printf(gettext("%s Current state is %s\n"), prefix,
1486 	    statestr(hdrp->p1hdr_state));
1487 	if (hdrp->p1hdr_support_dpd == B_FALSE) {
1488 		return;
1489 	}
1490 	(void) printf(gettext("%s Dead Peer Detection (RFC 3706)"
1491 	    " enabled"), prefix);
1492 	if (hdrp->p1hdr_dpd_state < DPD_IN_PROGRESS) {
1493 		(void) printf("\n");
1494 		return;
1495 	}
1496 	if (strftime(tbuf, TBUF_SIZE, NULL,
1497 	    localtime(&ltime)) == 0) {
1498 		(void) strlcpy(tbuf, gettext("<time conversion failed>"),
1499 		    TBUF_SIZE);
1500 	}
1501 	(void) printf(gettext("\n%s Dead Peer Detection handshake "), prefix);
1502 	switch (hdrp->p1hdr_dpd_state) {
1503 	case DPD_SUCCESSFUL:
1504 		(void) strlcpy(sbuf, gettext("was successful at "), TBUF_SIZE);
1505 		break;
1506 	case DPD_FAILURE:
1507 		(void) strlcpy(sbuf, gettext("failed at "), TBUF_SIZE);
1508 		break;
1509 	case DPD_IN_PROGRESS:
1510 		(void) strlcpy(sbuf, gettext("is in progress."), TBUF_SIZE);
1511 		break;
1512 	}
1513 	(void) printf("%s %s", sbuf,
1514 	    (hdrp->p1hdr_dpd_state == DPD_IN_PROGRESS) ? "" : tbuf);
1515 	(void) printf("\n");
1516 }
1517 
1518 static void
1519 print_lt_limits(char *prefix, ike_p1_xform_t *xfp)
1520 {
1521 	char byte_str[BYTE_STR_SIZE]; /* byte lifetime string representation */
1522 	char secs_str[SECS_STR_SIZE]; /* lifetime string representation */
1523 
1524 	(void) printf(gettext("%s Lifetime limits:\n"), prefix);
1525 	(void) printf(gettext("%s %u seconds%s; %u kbytes %sprotected\n"),
1526 	    prefix, xfp->p1xf_max_secs, secs2out(xfp->p1xf_max_secs,
1527 	    secs_str, sizeof (secs_str), SPC_BEGIN), xfp->p1xf_max_kbytes,
1528 	    bytecnt2out((uint64_t)xfp->p1xf_max_kbytes << 10, byte_str,
1529 	    sizeof (byte_str), SPC_END));
1530 	(void) printf(gettext("%s keying material for IPsec SAs can be "
1531 	    "provided %u times%s\n"), prefix, xfp->p1xf_max_keyuses,
1532 	    xfp->p1xf_max_keyuses == 0 ? " (no limit)" : "");
1533 }
1534 
1535 #define	LT_USAGE_LEN	16	/* 1 uint64 + 2 uint32s */
1536 static void
1537 print_lt_usage(char *prefix, ike_p1_stats_t *sp)
1538 {
1539 	time_t	scratch;
1540 	char	tbuf[TBUF_SIZE];
1541 	char	bytestr[BYTE_STR_SIZE]; /* byte lifetime representation */
1542 
1543 	(void) printf(gettext("%s Current usage:\n"), prefix);
1544 	scratch = (time_t)sp->p1stat_start;
1545 	if (strftime(tbuf, TBUF_SIZE, NULL, localtime(&scratch)) == 0)
1546 		(void) strlcpy(tbuf, gettext("<time conversion failed>"),
1547 		    TBUF_SIZE);
1548 	(void) printf(gettext("%s SA was created at %s\n"), prefix, tbuf);
1549 	(void) printf(gettext("%s %u kbytes %sprotected\n"),
1550 	    prefix, sp->p1stat_kbytes,
1551 	    bytecnt2out((uint64_t)sp->p1stat_kbytes << 10, bytestr,
1552 	    sizeof (bytestr), SPC_END));
1553 	(void) printf(gettext("%s keying material for IPsec SAs provided "
1554 	    "%u times\n"), prefix, sp->p1stat_keyuses);
1555 }
1556 
1557 static void
1558 print_xform(char *prefix, ike_p1_xform_t *xfp, boolean_t print_lifetimes)
1559 {
1560 	(void) printf(gettext("%s Authentication method: %s"), prefix,
1561 	    authmethstr(xfp->p1xf_auth_meth));
1562 	(void) printf(gettext("\n%s Encryption alg: "), prefix);
1563 	(void) dump_ealg(xfp->p1xf_encr_alg, stdout);
1564 	if (xfp->p1xf_encr_low_bits != 0) {
1565 		(void) printf(gettext("(%d..%d)"), xfp->p1xf_encr_low_bits,
1566 		    xfp->p1xf_encr_high_bits);
1567 	} else if ((xfp->p1xf_encr_low_bits == 0) &&
1568 	    (xfp->p1xf_encr_high_bits != 0)) {
1569 		/*
1570 		 * High bits is a placeholder for
1571 		 * negotiated algorithm strength
1572 		 */
1573 		(void) printf(gettext("(%d)"), xfp->p1xf_encr_high_bits);
1574 	}
1575 	(void) printf(gettext("; Authentication alg: "));
1576 	(void) dump_aalg(xfp->p1xf_auth_alg, stdout);
1577 	(void) printf("\n%s ", prefix);
1578 	if (xfp->p1xf_prf != 0)
1579 		(void) printf(gettext("PRF: %s ; "), prfstr(xfp->p1xf_prf));
1580 	(void) printf(gettext("Oakley Group: %s\n"),
1581 	    dhstr(xfp->p1xf_dh_group));
1582 	if (xfp->p1xf_pfs == 0) {
1583 		(void) printf(gettext("%s Phase 2 PFS is not used\n"), prefix);
1584 	} else {
1585 		(void) printf(gettext(
1586 		    "%s Phase 2 PFS is required (Oakley Group: %s)\n"),
1587 		    prefix, dhstr(xfp->p1xf_pfs));
1588 	}
1589 
1590 	if (print_lifetimes)
1591 		print_lt_limits(prefix, xfp);
1592 }
1593 
1594 static void
1595 print_lifetime(char *prefix, ike_p1_xform_t *xfp, ike_p1_stats_t *sp,
1596     int statlen)
1597 {
1598 	time_t	current, remain, exp;
1599 	char	tbuf[TBUF_SIZE];
1600 	char	byte_str[BYTE_STR_SIZE]; /* byte lifetime representation */
1601 	char	secs_str[SECS_STR_SIZE]; /* seconds lifetime representation */
1602 
1603 	current = time(NULL);
1604 
1605 	print_lt_limits(prefix, xfp);
1606 
1607 	/*
1608 	 * make sure the stats struct we've been passed is as big
1609 	 * as we expect it to be.  The usage stats are at the end,
1610 	 * so anything less than the size we expect won't work.
1611 	 */
1612 	if (statlen >= sizeof (ike_p1_stats_t)) {
1613 		print_lt_usage(prefix, sp);
1614 	} else {
1615 		return;
1616 	}
1617 
1618 	(void) printf(gettext("%s Expiration info:\n"), prefix);
1619 
1620 	if (xfp->p1xf_max_kbytes != 0)
1621 		(void) printf(gettext("%s %u more bytes %scan be "
1622 		    "protected.\n"),
1623 		    prefix, xfp->p1xf_max_kbytes - sp->p1stat_kbytes,
1624 		    bytecnt2out((uint64_t)(xfp->p1xf_max_kbytes -
1625 		    sp->p1stat_kbytes) << 10, byte_str, sizeof (byte_str),
1626 		    SPC_END));
1627 
1628 	if (xfp->p1xf_max_keyuses != 0)
1629 		(void) printf(gettext("%s Keying material can be provided "
1630 		    "%u more times.\n"), prefix,
1631 		    xfp->p1xf_max_keyuses - sp->p1stat_keyuses);
1632 
1633 	if (xfp->p1xf_max_secs != 0) {
1634 		exp = (time_t)sp->p1stat_start + (time_t)xfp->p1xf_max_secs;
1635 		remain = exp - current;
1636 		if (strftime(tbuf, TBUF_SIZE, NULL, localtime(&exp)) == 0)
1637 			(void) strlcpy(tbuf,
1638 			    gettext("<time conversion failed>"), TBUF_SIZE);
1639 		/*
1640 		 * The SA may have expired but still exist because libike
1641 		 * has not freed it yet.
1642 		 */
1643 		if (remain > 0) {
1644 			(void) printf(gettext(
1645 			    "%s SA expires in %lu seconds%s\n"),
1646 			    prefix, remain, secs2out(remain, secs_str,
1647 			    sizeof (secs_str), SPC_BEGIN));
1648 			(void) printf(gettext("%s Time of expiration: %s\n"),
1649 			    prefix, tbuf);
1650 		} else {
1651 			(void) printf(gettext("%s SA Expired at %s\n"),
1652 			    prefix, tbuf);
1653 		}
1654 	}
1655 }
1656 
1657 /* used to verify structure lengths... */
1658 #define	COUNTER_32BIT	4
1659 #define	COUNTER_PAIR	8
1660 
1661 static void
1662 print_p1stats(char *prefix, ike_p1_stats_t *sp, int statlen,
1663     boolean_t print_lifetimes)
1664 {
1665 	if (statlen < COUNTER_PAIR)
1666 		return;
1667 	(void) printf(gettext("%s %u Quick Mode SAs created; "), prefix,
1668 	    sp->p1stat_new_qm_sas);
1669 	(void) printf(gettext("%u Quick Mode SAs deleted\n"),
1670 	    sp->p1stat_del_qm_sas);
1671 	statlen -= COUNTER_PAIR;
1672 
1673 	if ((print_lifetimes) && (statlen >= LT_USAGE_LEN))
1674 		print_lt_usage(prefix, sp);
1675 }
1676 
1677 static void
1678 print_errs(char *prefix, ike_p1_errors_t *errp, int errlen)
1679 {
1680 	/*
1681 	 * Don't try to break this one up; it's either all or nothing!
1682 	 */
1683 	if (errlen < sizeof (ike_p1_errors_t))
1684 		return;
1685 
1686 	(void) printf(gettext("%s %u RX errors: "), prefix,
1687 	    errp->p1err_decrypt + errp->p1err_hash + errp->p1err_otherrx);
1688 	(void) printf(gettext("%u decryption, %u hash, %u other\n"),
1689 	    errp->p1err_decrypt, errp->p1err_hash, errp->p1err_otherrx);
1690 	(void) printf(gettext("%s %u TX errors\n"), prefix, errp->p1err_tx);
1691 }
1692 
1693 static void
1694 print_addr_range(char *prefix, ike_addr_pr_t *pr)
1695 {
1696 	boolean_t	range = B_TRUE;
1697 	struct sockaddr_storage	*beg, *end;
1698 	struct sockaddr_in	*bsin, *esin;
1699 	struct sockaddr_in6	*bsin6, *esin6;
1700 
1701 	beg = &pr->beg_iprange;
1702 	end = &pr->end_iprange;
1703 
1704 	if (beg->ss_family != end->ss_family) {
1705 		(void) printf(gettext("%s invalid address range\n"), prefix);
1706 		return;
1707 	}
1708 
1709 	switch (beg->ss_family) {
1710 	case AF_INET:
1711 		bsin = (struct sockaddr_in *)beg;
1712 		esin = (struct sockaddr_in *)end;
1713 		if ((uint32_t)bsin->sin_addr.s_addr ==
1714 		    (uint32_t)esin->sin_addr.s_addr)
1715 			range = B_FALSE;
1716 		break;
1717 	case AF_INET6:
1718 		bsin6 = (struct sockaddr_in6 *)beg;
1719 		esin6 = (struct sockaddr_in6 *)end;
1720 		if (IN6_ARE_ADDR_EQUAL(&bsin6->sin6_addr, &esin6->sin6_addr))
1721 			range = B_FALSE;
1722 		break;
1723 	default:
1724 		(void) printf(gettext("%s invalid address range\n"), prefix);
1725 		return;
1726 	}
1727 
1728 	(void) printf("%s ", prefix);
1729 	(void) dump_sockaddr((struct sockaddr *)beg, 0, B_TRUE, stdout, nflag);
1730 	if (range) {
1731 		(void) printf(" - ");
1732 		(void) dump_sockaddr((struct sockaddr *)end, 0, B_TRUE, stdout,
1733 		    nflag);
1734 	}
1735 	(void) printf("\n");
1736 
1737 }
1738 
1739 /*
1740  * used to tell printing function if info should be identified
1741  * as belonging to initiator, responder, or neither
1742  */
1743 #define	IS_INITIATOR	1
1744 #define	IS_RESPONDER	2
1745 #define	DONT_PRINT_INIT	3
1746 
1747 static void
1748 print_addr(char *prefix, struct sockaddr_storage *sa, int init_instr)
1749 {
1750 	(void) printf(gettext("%s Address"), prefix);
1751 
1752 	if (init_instr != DONT_PRINT_INIT)
1753 		(void) printf(" (%s):\n", (init_instr == IS_INITIATOR) ?
1754 		    gettext("Initiator") : gettext("Responder"));
1755 	else
1756 		(void) printf(":\n");
1757 
1758 	(void) printf("%s ", prefix);
1759 	(void) dump_sockaddr((struct sockaddr *)sa, 0, B_FALSE, stdout, nflag);
1760 }
1761 
1762 static void
1763 print_id(char *prefix, sadb_ident_t *idp, int init_instr)
1764 {
1765 	boolean_t	canprint;
1766 
1767 	switch (init_instr) {
1768 	case IS_INITIATOR:
1769 		(void) printf(gettext("%s Initiator identity, "), prefix);
1770 		break;
1771 	case IS_RESPONDER:
1772 		(void) printf(gettext("%s Responder identity, "), prefix);
1773 		break;
1774 	case DONT_PRINT_INIT:
1775 		(void) printf(gettext("%s Identity, "), prefix);
1776 		break;
1777 	default:
1778 		(void) printf(gettext("<invalid identity>\n"));
1779 		return;
1780 	}
1781 	(void) printf(gettext("uid=%d, type "), idp->sadb_ident_id);
1782 	canprint = dump_sadb_idtype(idp->sadb_ident_type, stdout, NULL);
1783 	if (canprint) {
1784 		(void) printf("\n%s %s\n", prefix, (char *)(idp + 1));
1785 	} else {
1786 		(void) printf(gettext("\n%s "), prefix);
1787 		print_asn1_name(stdout,
1788 		    (const unsigned char *)(idp + 1),
1789 		    SADB_64TO8(idp->sadb_ident_len) - sizeof (sadb_ident_t));
1790 	}
1791 }
1792 
1793 static void
1794 print_idspec(char *prefix, char *idp, int icnt, int ecnt)
1795 {
1796 	int	i;
1797 
1798 	(void) printf(gettext("%s Identity descriptors:\n"), prefix);
1799 
1800 	for (i = 0; i < icnt; i++) {
1801 		if (i == 0)
1802 			(void) printf(gettext("%s Includes:\n"), prefix);
1803 		(void) printf("%s    %s\n", prefix, idp);
1804 		idp += strlen(idp) + 1;
1805 	}
1806 
1807 	for (i = 0; i < ecnt; i++) {
1808 		if (i == 0)
1809 			(void) printf(gettext("%s Excludes:\n"), prefix);
1810 		(void) printf("%s    %s\n", prefix, idp);
1811 		idp += strlen(idp) + 1;
1812 	}
1813 }
1814 
1815 static void
1816 print_keys(char *prefix, ike_p1_key_t *keyp, int size)
1817 {
1818 	uint32_t	*curp;
1819 	ike_p1_key_t	*p;
1820 	int		ssize;
1821 
1822 	curp = (uint32_t *)keyp;
1823 
1824 	ssize = sizeof (ike_p1_key_t);
1825 
1826 	while ((intptr_t)curp - (intptr_t)keyp < size) {
1827 		size_t p1klen, len;
1828 
1829 		p = (ike_p1_key_t *)curp;
1830 		p1klen = p->p1key_len;
1831 		len = p1klen - ssize;
1832 
1833 		p1klen = roundup(p1klen, sizeof (ike_p1_key_t));
1834 		if (p1klen < ssize) {
1835 			(void) printf(gettext("Short key\n"));
1836 			break;
1837 		}
1838 
1839 		switch (p->p1key_type) {
1840 		case IKE_KEY_PRESHARED:
1841 			(void) printf(gettext("%s Pre-shared key (%d bytes): "),
1842 			    prefix, len);
1843 			break;
1844 		case IKE_KEY_SKEYID:
1845 			(void) printf(gettext("%s SKEYID (%d bytes): "),
1846 			    prefix, len);
1847 			break;
1848 		case IKE_KEY_SKEYID_D:
1849 			(void) printf(gettext("%s SKEYID_d (%d bytes): "),
1850 			    prefix, len);
1851 			break;
1852 		case IKE_KEY_SKEYID_A:
1853 			(void) printf(gettext("%s SKEYID_a (%d bytes): "),
1854 			    prefix, len);
1855 			break;
1856 		case IKE_KEY_SKEYID_E:
1857 			(void) printf(gettext("%s SKEYID_e (%d bytes): "),
1858 			    prefix, len);
1859 			break;
1860 		case IKE_KEY_ENCR:
1861 			(void) printf(gettext("%s Encryption key (%d bytes): "),
1862 			    prefix, len);
1863 			break;
1864 		case IKE_KEY_IV:
1865 			(void) printf(
1866 			    gettext("%s Initialization vector (%d bytes): "),
1867 			    prefix, len);
1868 			break;
1869 		default:
1870 			(void) printf(gettext("%s Unidentified key info %p %d"),
1871 			    prefix, p, p1klen);
1872 			goto badkey;
1873 		}
1874 		(void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 0,
1875 		    stdout, B_FALSE);
1876 badkey:
1877 		(void) printf("\n");
1878 		assert(IS_P2ALIGNED(p1klen, 8));
1879 		curp += (p1klen >> 2);
1880 	}
1881 }
1882 
1883 static void
1884 print_p1(ike_p1_sa_t *p1)
1885 {
1886 	ike_p1_stats_t	*sp;
1887 	ike_p1_errors_t	*ep;
1888 	ike_p1_key_t	*kp;
1889 	sadb_ident_t	*lidp, *ridp;
1890 	int		lstat, rstat;
1891 
1892 	(void) printf("\n");
1893 	print_hdr("IKESA:", &p1->p1sa_hdr);
1894 	print_xform("XFORM:", &p1->p1sa_xform, B_FALSE);
1895 
1896 	if (p1->p1sa_hdr.p1hdr_isinit) {
1897 		lstat = IS_INITIATOR;
1898 		rstat = IS_RESPONDER;
1899 	} else {
1900 		lstat = IS_RESPONDER;
1901 		rstat = IS_INITIATOR;
1902 	}
1903 	print_addr("LOCIP:", &p1->p1sa_ipaddrs.loc_addr, lstat);
1904 	print_addr("REMIP:", &p1->p1sa_ipaddrs.rem_addr, rstat);
1905 
1906 	/*
1907 	 * the stat len might be 0; but still make the call
1908 	 * to print_lifetime() to pick up the xform info
1909 	 */
1910 	sp = (ike_p1_stats_t *)((int)(p1) + p1->p1sa_stat_off);
1911 	print_lifetime("LIFTM:", &p1->p1sa_xform, sp, p1->p1sa_stat_len);
1912 
1913 	if (p1->p1sa_stat_len > 0) {
1914 		print_p1stats("STATS:", sp, p1->p1sa_stat_len, B_FALSE);
1915 	}
1916 
1917 	if (p1->p1sa_error_len > 0) {
1918 		ep = (ike_p1_errors_t *)((int)(p1) + p1->p1sa_error_off);
1919 		print_errs("ERRS: ", ep, p1->p1sa_error_len);
1920 	}
1921 
1922 	if (p1->p1sa_localid_len > 0) {
1923 		lidp = (sadb_ident_t *)((int)(p1) + p1->p1sa_localid_off);
1924 		print_id("LOCID:", lidp, lstat);
1925 	}
1926 
1927 	if (p1->p1sa_remoteid_len > 0) {
1928 		ridp = (sadb_ident_t *)((int)(p1) + p1->p1sa_remoteid_off);
1929 		print_id("REMID:", ridp, rstat);
1930 	}
1931 
1932 	if (p1->p1sa_key_len > 0) {
1933 		kp = (ike_p1_key_t *)((int)(p1) + p1->p1sa_key_off);
1934 		print_keys("KEY:  ", kp, p1->p1sa_key_len);
1935 	}
1936 }
1937 
1938 static void
1939 print_certcache(ike_certcache_t *c)
1940 {
1941 	(void) printf("\n");
1942 
1943 	(void) printf(gettext("CERTIFICATE CACHE ID: %d\n"), c->cache_id);
1944 	(void) printf(gettext("\tSubject Name: <%s>\n"),
1945 	    (c->subject != NULL) ? c->subject : gettext("Name unavailable"));
1946 	(void) printf(gettext("\t Issuer Name: <%s>\n"),
1947 	    (c->issuer != NULL) ? c->issuer : gettext("Name unavailable"));
1948 	if ((int)c->certclass == -1)
1949 		(void) printf(gettext("\t\t[trusted certificate]\n"));
1950 	switch (c->linkage) {
1951 	case CERT_OFF_WIRE:
1952 		(void) printf(gettext("\t\t[Public certificate only]\n"));
1953 		(void) printf(gettext(
1954 		    "\t\t[Obtained via certificate payload]\n"));
1955 		break;
1956 	case CERT_NO_PRIVKEY:
1957 		(void) printf(gettext("\t\t[Public certificate only]\n"));
1958 		break;
1959 	case CERT_PRIVKEY_LOCKED:
1960 		(void) printf(gettext(
1961 		    "\t\t[Private key linked but locked]\n"));
1962 		break;
1963 	case CERT_PRIVKEY_AVAIL:
1964 		(void) printf(gettext("\t\t[Private key available]\n"));
1965 		break;
1966 	}
1967 }
1968 
1969 static void
1970 print_ps(ike_ps_t *ps)
1971 {
1972 	sadb_ident_t	*lidp, *ridp;
1973 	uint8_t		*keyp;
1974 
1975 	(void) printf("\n");
1976 
1977 	(void) printf(gettext("PSKEY: For %s exchanges\n"),
1978 	    xchgstr(ps->ps_ike_mode));
1979 
1980 	if (ps->ps_key_len > 0) {
1981 		keyp = (uint8_t *)((int)(ps) + ps->ps_key_off);
1982 		(void) printf(gettext("PSKEY: Pre-shared key (%d bytes): "),
1983 		    ps->ps_key_len);
1984 		(void) dump_key(keyp, ps->ps_key_bits, 0, stdout, B_FALSE);
1985 		(void) printf("\n");
1986 	}
1987 
1988 	/*
1989 	 * We get *either* and address or an ident, never both.  So if
1990 	 * the ident is there, don't try printing an address.
1991 	 */
1992 	if (ps->ps_localid_len > 0) {
1993 		lidp = (sadb_ident_t *)
1994 		    ((int)(ps) + ps->ps_localid_off);
1995 		print_id("LOCID:", lidp, DONT_PRINT_INIT);
1996 	} else {
1997 		print_addr("LOCIP:", &ps->ps_ipaddrs.loc_addr, DONT_PRINT_INIT);
1998 	}
1999 
2000 	if (ps->ps_remoteid_len > 0) {
2001 		ridp = (sadb_ident_t *)
2002 		    ((int)(ps) + ps->ps_remoteid_off);
2003 		print_id("REMID:", ridp, DONT_PRINT_INIT);
2004 	} else {
2005 		print_addr("REMIP:", &ps->ps_ipaddrs.rem_addr, DONT_PRINT_INIT);
2006 	}
2007 }
2008 
2009 #define	PREFIXLEN	16
2010 
2011 static void
2012 print_rule(ike_rule_t *rp)
2013 {
2014 	char		prefix[PREFIXLEN];
2015 	int		i;
2016 	ike_p1_xform_t	*xfp;
2017 	ike_addr_pr_t	*lipp, *ripp;
2018 	char		*lidp, *ridp;
2019 	char byte_str[BYTE_STR_SIZE]; /* kbyte string representation */
2020 	char secs_str[SECS_STR_SIZE]; /* seconds string representation */
2021 
2022 	(void) printf("\n");
2023 	(void) printf(gettext("GLOBL: Label '%s', key manager cookie %u\n"),
2024 	    rp->rule_label, rp->rule_kmcookie);
2025 	(void) printf(gettext("GLOBL: local_idtype="));
2026 	(void) dump_sadb_idtype(rp->rule_local_idtype, stdout, NULL);
2027 	(void) printf(gettext(", ike_mode=%s\n"), xchgstr(rp->rule_ike_mode));
2028 	(void) printf(gettext(
2029 	    "GLOBL: p1_nonce_len=%u, p2_nonce_len=%u, p2_pfs=%s (group %u)\n"),
2030 	    rp->rule_p1_nonce_len, rp->rule_p2_nonce_len,
2031 	    (rp->rule_p2_pfs) ? gettext("true") : gettext("false"),
2032 	    rp->rule_p2_pfs);
2033 	(void) printf(
2034 	    gettext("GLOBL: p2_lifetime=%u seconds%s\n"),
2035 	    rp->rule_p2_lifetime_secs, secs2out(rp->rule_p2_lifetime_secs,
2036 	    secs_str, sizeof (secs_str), SPC_BEGIN));
2037 	(void) printf(
2038 	    gettext("GLOBL: p2_softlife=%u seconds%s\n"),
2039 	    rp->rule_p2_softlife_secs, secs2out(rp->rule_p2_softlife_secs,
2040 	    secs_str, sizeof (secs_str), SPC_BEGIN));
2041 	(void) printf(
2042 	    gettext("GLOBL: p2_idletime=%u seconds%s\n"),
2043 	    rp->rule_p2_idletime_secs, secs2out(rp->rule_p2_idletime_secs,
2044 	    secs_str, sizeof (secs_str), SPC_BEGIN));
2045 	/*
2046 	 * Perform explicit conversion before passing to bytecnt2out()
2047 	 * to avoid integer overflow.
2048 	 */
2049 	(void) printf(
2050 	    gettext("GLOBL: p2_lifetime_kb=%u kilobytes%s\n"),
2051 	    rp->rule_p2_lifetime_kb,
2052 	    bytecnt2out((uint64_t)(rp->rule_p2_lifetime_kb) << 10,
2053 	    byte_str, sizeof (byte_str), SPC_BEGIN));
2054 	(void) printf(
2055 	    gettext("GLOBL: p2_softlife_kb=%u kilobytes%s\n"),
2056 	    rp->rule_p2_softlife_kb,
2057 	    bytecnt2out(((uint64_t)(rp->rule_p2_softlife_kb)) << 10,
2058 	    byte_str, sizeof (byte_str), SPC_BEGIN));
2059 
2060 	if (rp->rule_locip_cnt > 0) {
2061 		(void) printf(gettext("LOCIP: IP address range(s):\n"));
2062 		lipp = (ike_addr_pr_t *)((int)rp + rp->rule_locip_off);
2063 		for (i = 0; i < rp->rule_locip_cnt; i++, lipp++) {
2064 			print_addr_range("LOCIP:", lipp);
2065 		}
2066 	}
2067 
2068 	if (rp->rule_remip_cnt > 0) {
2069 		(void) printf(gettext("REMIP: IP address range(s):\n"));
2070 		ripp = (ike_addr_pr_t *)((int)rp + rp->rule_remip_off);
2071 		for (i = 0; i < rp->rule_remip_cnt; i++, ripp++) {
2072 			print_addr_range("REMIP:", ripp);
2073 		}
2074 	}
2075 
2076 	if (rp->rule_locid_inclcnt + rp->rule_locid_exclcnt > 0) {
2077 		lidp = (char *)((int)rp + rp->rule_locid_off);
2078 		print_idspec("LOCID:", lidp, rp->rule_locid_inclcnt,
2079 		    rp->rule_locid_exclcnt);
2080 	}
2081 
2082 	if (rp->rule_remid_inclcnt + rp->rule_remid_exclcnt > 0) {
2083 		ridp = (char *)((int)rp + rp->rule_remid_off);
2084 		print_idspec("REMID:", ridp, rp->rule_remid_inclcnt,
2085 		    rp->rule_remid_exclcnt);
2086 	}
2087 
2088 	if (rp->rule_xform_cnt > 0) {
2089 		(void) printf(gettext("XFRMS: Available Transforms:\n"));
2090 		xfp = (ike_p1_xform_t *)((int)rp +  rp->rule_xform_off);
2091 		for (i = 0; i < rp->rule_xform_cnt; i++, xfp++) {
2092 			(void) snprintf(prefix, PREFIXLEN, "XF %2u:", i);
2093 			print_xform(prefix, xfp, B_TRUE);
2094 		}
2095 	}
2096 }
2097 
2098 #undef	PREFIXLEN
2099 
2100 #define	PRSACNTS(init, resp) \
2101 		(void) printf(gettext("initiator: %10u   responder: %10u\n"), \
2102 		    (init), (resp))
2103 
2104 static void
2105 print_stats(ike_stats_t *sp, int len)
2106 {
2107 	/*
2108 	 * before printing each line, make sure the structure we were
2109 	 * given is big enough to include the fields needed.
2110 	 */
2111 	if (len < COUNTER_PAIR)
2112 		return;
2113 	(void) printf(gettext("Phase 1 SA counts:\n"));
2114 	(void) printf(gettext("Current:   "));
2115 	PRSACNTS(sp->st_init_p1_current, sp->st_resp_p1_current);
2116 	len -= COUNTER_PAIR;
2117 
2118 	if (len < COUNTER_PAIR)
2119 		return;
2120 	(void) printf(gettext("Total:     "));
2121 	PRSACNTS(sp->st_init_p1_total, sp->st_resp_p1_total);
2122 	len -= COUNTER_PAIR;
2123 
2124 	if (len < COUNTER_PAIR)
2125 		return;
2126 	(void) printf(gettext("Attempted: "));
2127 	PRSACNTS(sp->st_init_p1_attempts, sp->st_resp_p1_attempts);
2128 	len -= COUNTER_PAIR;
2129 
2130 	if (len < (COUNTER_PAIR + COUNTER_32BIT))
2131 		return;
2132 	(void) printf(gettext("Failed:    "));
2133 	PRSACNTS(sp->st_init_p1_noresp + sp->st_init_p1_respfail,
2134 	    sp->st_resp_p1_fail);
2135 	(void) printf(
2136 	    gettext("           initiator fails include %u time-out(s)\n"),
2137 	    sp->st_init_p1_noresp);
2138 
2139 	if (len < PATH_MAX)
2140 		return;
2141 	if (*(sp->st_pkcs11_libname) != '\0')
2142 		(void) printf(gettext("PKCS#11 library linked in from %s\n"),
2143 		    sp->st_pkcs11_libname);
2144 }
2145 
2146 /* Print one line of 'get defaults' output (i.e. single value). */
2147 static void
2148 print_defaults(char *label, char *description, char *unit,
2149     uint_t current, uint_t def)
2150 {
2151 	(void) printf("%-18s%-10s%11u %-10s%-26s\n", label,
2152 	    (current != def) ? gettext("config") : gettext("default"),
2153 	    current, unit, description);
2154 }
2155 
2156 /*
2157  * Print out defaults used by in.iked, the argument is a buffer containing
2158  * two ike_defaults_t's, the first contains the hard coded defaults, the second
2159  * contains the actual values used. If these differ, then the defaults have been
2160  * changed via a config file entry. Note that "-" indicates this default
2161  * is not tunable via ike.config(4) or is system wide tunable.
2162  */
2163 static void
2164 do_print_defaults(ike_defaults_t *dp)
2165 {
2166 	ike_defaults_t *ddp;
2167 	ddp = (ike_defaults_t *)(dp + 1);
2168 
2169 	(void) printf(gettext("\nGlobal defaults. Some values can be"
2170 	    " over-ridden on a per rule basis.\n"));
2171 	(void) printf(gettext("\nSystem defaults are time delayed.\n\n"));
2172 
2173 	(void) printf("%-18s%-10s%-12s%-10s%-26s\n\n",
2174 	    gettext("Token:"), gettext("Source:"), gettext("Value:"),
2175 	    gettext("Unit:"), gettext("Description:"));
2176 
2177 	/* iked tunables */
2178 	print_defaults("p1_lifetime_secs", gettext("phase 1 lifetime"),
2179 	    gettext("seconds"), ddp->rule_p1_lifetime_secs,
2180 	    dp->rule_p1_lifetime_secs);
2181 
2182 	print_defaults("-", gettext("minimum phase 1 lifetime"),
2183 	    gettext("seconds"), ddp->rule_p1_minlife,
2184 	    dp->rule_p1_minlife);
2185 
2186 	print_defaults("p1_nonce_len", gettext("phase 1 nonce length"),
2187 	    gettext("bytes"), ddp->rule_p1_nonce_len,
2188 	    dp->rule_p1_nonce_len);
2189 
2190 	print_defaults("p2_lifetime_secs", gettext("phase 2 lifetime"),
2191 	    gettext("seconds"), ddp->rule_p2_lifetime_secs,
2192 	    dp->rule_p2_lifetime_secs);
2193 
2194 	print_defaults("p2_softlife_secs", gettext("phase 2 soft lifetime"),
2195 	    gettext("seconds"), ddp->rule_p2_softlife_secs,
2196 	    dp->rule_p2_softlife_secs);
2197 
2198 	print_defaults("p2_idletime_secs", gettext("phase 2 idle time"),
2199 	    gettext("seconds"), ddp->rule_p2_idletime_secs,
2200 	    dp->rule_p2_idletime_secs);
2201 
2202 	print_defaults("p2_lifetime_kb", gettext("phase 2 lifetime"),
2203 	    gettext("kilobytes"), ddp->rule_p2_lifetime_kb,
2204 	    dp->rule_p2_lifetime_kb);
2205 
2206 	print_defaults("p2_softlife_kb", gettext("phase 2 soft lifetime"),
2207 	    gettext("kilobytes"), ddp->rule_p2_softlife_kb,
2208 	    dp->rule_p2_softlife_kb);
2209 
2210 	/* system wide tunables */
2211 	print_defaults("-", gettext("system phase 2 lifetime"),
2212 	    gettext("seconds"), ddp->sys_p2_lifetime_secs,
2213 	    dp->sys_p2_lifetime_secs);
2214 
2215 	print_defaults("-", gettext("system phase 2 soft lifetime"),
2216 	    gettext("seconds"), ddp->sys_p2_softlife_secs,
2217 	    dp->sys_p2_softlife_secs);
2218 
2219 	print_defaults("-", gettext("system phase 2 idle time"),
2220 	    gettext("seconds"), ddp->sys_p2_idletime_secs,
2221 	    dp->sys_p2_idletime_secs);
2222 
2223 	print_defaults("-", gettext("system phase 2 lifetime"),
2224 	    gettext("bytes"), ddp->sys_p2_lifetime_bytes,
2225 	    dp->sys_p2_lifetime_bytes);
2226 
2227 	print_defaults("-", gettext("system phase 2 soft lifetime"),
2228 	    gettext("bytes"), ddp->sys_p2_softlife_bytes,
2229 	    dp->sys_p2_softlife_bytes);
2230 
2231 	/* minimum and maximum values */
2232 	print_defaults("-", gettext("minimum phase 2 hard lifetime"),
2233 	    gettext("seconds"), ddp->rule_p2_minlife_hard_secs,
2234 	    dp->rule_p2_minlife_hard_secs);
2235 
2236 	print_defaults("-", gettext("minimum phase 2 soft lifetime"),
2237 	    gettext("seconds"), ddp->rule_p2_minlife_soft_secs,
2238 	    dp->rule_p2_minlife_soft_secs);
2239 
2240 	print_defaults("-", gettext("minimum phase 2 idle lifetime"),
2241 	    gettext("seconds"), ddp->rule_p2_minlife_idle_secs,
2242 	    dp->rule_p2_minlife_idle_secs);
2243 
2244 	print_defaults("-", gettext("minimum phase 2 hard lifetime"),
2245 	    gettext("kilobytes"), ddp->rule_p2_minlife_hard_kb,
2246 	    dp->rule_p2_minlife_hard_kb);
2247 
2248 	print_defaults("-", gettext("minimum phase 2 soft lifetime"),
2249 	    gettext("kilobytes"), ddp->rule_p2_minlife_soft_kb,
2250 	    dp->rule_p2_minlife_soft_kb);
2251 
2252 	print_defaults("-", gettext("minimum phase 2 delta"),
2253 	    gettext("seconds"), ddp->rule_p2_mindiff_secs,
2254 	    dp->rule_p2_mindiff_secs);
2255 
2256 	print_defaults("-", gettext("minimum phase 2 delta"),
2257 	    gettext("kilobytes"), ddp->rule_p2_mindiff_kb,
2258 	    dp->rule_p2_mindiff_kb);
2259 
2260 	print_defaults("-", gettext("maximum phase 2 lifetime"),
2261 	    gettext("seconds"), ddp->rule_p2_maxlife_secs,
2262 	    dp->rule_p2_maxlife_secs);
2263 
2264 	print_defaults("-", gettext("conversion factor"),
2265 	    gettext("kbytes/s"), ddp->conversion_factor,
2266 	    dp->conversion_factor);
2267 
2268 	print_defaults("-", gettext("maximum phase 2 lifetime"),
2269 	    gettext("kilobytes"), ddp->rule_p2_maxlife_kb,
2270 	    dp->rule_p2_maxlife_kb);
2271 
2272 	/* other values */
2273 	print_defaults("p2_nonce_len", gettext("phase 2 nonce length"),
2274 	    gettext("bytes"), ddp->rule_p2_nonce_len,
2275 	    dp->rule_p2_nonce_len);
2276 
2277 	print_defaults("p2_pfs", gettext("phase 2 PFS"),
2278 	    " ", ddp->rule_p2_pfs, dp->rule_p2_pfs);
2279 
2280 	print_defaults("max_certs", gettext("max certificates"),
2281 	    " ", ddp->rule_max_certs, dp->rule_max_certs);
2282 
2283 	print_defaults("-", gettext("IKE port number"),
2284 	    " ", ddp->rule_ike_port, dp->rule_ike_port);
2285 
2286 	print_defaults("-", gettext("NAT-T port number"),
2287 	    " ", ddp->rule_natt_port, dp->rule_natt_port);
2288 }
2289 
2290 static void
2291 print_categories(int level)
2292 {
2293 	int	mask;
2294 
2295 	if (level == 0) {
2296 		(void) printf(gettext("No debug categories enabled.\n"));
2297 		return;
2298 	}
2299 
2300 	(void) printf(gettext("Debug categories enabled:"));
2301 	for (mask = 1; mask <= D_HIGHBIT; mask <<= 1) {
2302 		if (level & mask)
2303 			(void) printf("\n\t%s", dbgstr(mask));
2304 	}
2305 	(void) printf("\n");
2306 }
2307 
2308 /*PRINTFLIKE2*/
2309 static void
2310 ikeadm_err_exit(ike_err_t *err, char *fmt, ...)
2311 {
2312 	va_list	ap;
2313 	char	bailbuf[BUFSIZ];
2314 
2315 	va_start(ap, fmt);
2316 	(void) vsnprintf(bailbuf, BUFSIZ, fmt, ap);
2317 	va_end(ap);
2318 	if ((err != NULL) && (err->ike_err == IKE_ERR_SYS_ERR)) {
2319 		bail_msg("%s: %s", bailbuf, (err->ike_err_unix == 0) ?
2320 		    gettext("<unknown error>") : strerror(err->ike_err_unix));
2321 	} else {
2322 		bail_msg("%s: %s", bailbuf, (err == NULL) ?
2323 		    gettext("<unknown error>") : errstr(err->ike_err));
2324 	}
2325 }
2326 
2327 /*PRINTFLIKE2*/
2328 static void
2329 ikeadm_err_msg(ike_err_t *err, char *fmt, ...)
2330 {
2331 	va_list	ap;
2332 	char	mbuf[BUFSIZ];
2333 
2334 	va_start(ap, fmt);
2335 	(void) vsnprintf(mbuf, BUFSIZ, fmt, ap);
2336 	va_end(ap);
2337 	if ((err != NULL) && (err->ike_err == IKE_ERR_SYS_ERR)) {
2338 		message("%s: %s", mbuf, (err->ike_err_unix == 0) ?
2339 		    gettext("<unknown error>") :
2340 		    ((err->ike_err_unix == EEXIST) ?
2341 		    gettext("Duplicate entry") :
2342 		    strerror(err->ike_err_unix)));
2343 	} else {
2344 		message("%s: %s", mbuf, (err == NULL) ?
2345 		    gettext("<unknown error>") : errstr(err->ike_err));
2346 	}
2347 }
2348 
2349 
2350 /*
2351  * Command functions
2352  */
2353 
2354 /*
2355  * Exploit the fact that ike_dbg_t and ike_priv_t have identical
2356  * formats in the following two functions.
2357  */
2358 static void
2359 do_getvar(int cmd)
2360 {
2361 	ike_service_t	req, *rtn;
2362 	ike_dbg_t	*dreq;
2363 	char		*varname;
2364 
2365 	switch (cmd) {
2366 	case IKE_SVC_GET_DBG:
2367 		varname = gettext("debug");
2368 		break;
2369 	case IKE_SVC_GET_PRIV:
2370 		varname = gettext("privilege");
2371 		break;
2372 	default:
2373 		bail_msg(gettext("unrecognized get command (%d)"), cmd);
2374 	}
2375 
2376 	dreq = &req.svc_dbg;
2377 	dreq->cmd = cmd;
2378 	dreq->dbg_level = 0;
2379 
2380 	rtn = ikedoor_call((char *)&req, sizeof (ike_dbg_t), NULL, 0);
2381 
2382 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2383 		ikeadm_err_exit(&rtn->svc_err,
2384 		    gettext("error getting %s level"), varname);
2385 	}
2386 	dreq = &rtn->svc_dbg;
2387 	(void) printf(gettext("Current %s level is 0x%x"),
2388 	    varname, dreq->dbg_level);
2389 
2390 	if (cmd == IKE_SVC_GET_DBG) {
2391 		(void) printf("\n");
2392 		print_categories(dreq->dbg_level);
2393 	} else {
2394 		(void) printf(gettext(", %s enabled\n"),
2395 		    privstr(dreq->dbg_level));
2396 	}
2397 }
2398 
2399 /*
2400  * Log into a token and unlock all objects
2401  * referenced by PKCS#11 hint files.
2402  */
2403 static void
2404 do_setdel_pin(int cmd, int argc, char **argv)
2405 {
2406 	ike_service_t	req, *rtn;
2407 	ike_pin_t	*preq;
2408 	char		token_label[PKCS11_TOKSIZE];
2409 	char		*token_pin;
2410 	char		prompt[80];
2411 
2412 	if (argc < 1)
2413 		Bail(gettext("Must specify PKCS#11 token object."));
2414 
2415 	preq = &req.svc_pin;
2416 	preq->cmd = cmd;
2417 
2418 	switch (cmd) {
2419 	case IKE_SVC_SET_PIN:
2420 		if (parse_token(argc, argv, token_label) != 0)
2421 			Bail("Invalid syntax for \"token login\"");
2422 		(void) snprintf(prompt, sizeof (prompt),
2423 		    "Enter PIN for PKCS#11 token \'%s\': ", token_label);
2424 		token_pin =
2425 		    getpassphrase(prompt);
2426 		(void) strlcpy((char *)preq->token_pin, token_pin, MAX_PIN_LEN);
2427 		bzero(token_pin, strlen(token_pin));
2428 		break;
2429 	case IKE_SVC_DEL_PIN:
2430 		if (parse_token(argc, argv, token_label) != 0)
2431 			Bail("Invalid syntax for \"token logout\"");
2432 		break;
2433 	default:
2434 		bail_msg(gettext("unrecognized token command (%d)"), cmd);
2435 	}
2436 
2437 	(void) strlcpy(preq->pkcs11_token, token_label, PKCS11_TOKSIZE);
2438 
2439 	rtn = ikedoor_call((char *)&req, sizeof (ike_pin_t), NULL, 0);
2440 	if (cmd == IKE_SVC_SET_PIN)
2441 		bzero(preq->token_pin, sizeof (preq->token_pin));
2442 
2443 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2444 		ikeadm_err_exit(&rtn->svc_err,
2445 		    gettext("PKCS#11 operation"));
2446 	}
2447 	preq = &rtn->svc_pin;
2448 	message(gettext("PKCS#11 operation successful"));
2449 }
2450 
2451 static void
2452 do_setvar(int cmd, int argc, char **argv)
2453 {
2454 	ike_service_t	req, *rtn;
2455 	ike_dbg_t	*dreq;
2456 	door_desc_t	*descp = NULL, desc;
2457 	int		fd, ndesc = 0;
2458 	uint32_t	reqlevel;
2459 	char		*varname;
2460 
2461 	if (argc < 1)
2462 		Bail("unspecified level");
2463 	reqlevel = strtoul(argv[0], NULL, 0);
2464 
2465 	switch (cmd) {
2466 	case IKE_SVC_SET_DBG:
2467 		if (argc > 2)
2468 			Bail("Too many arguments to \"set debug\"");
2469 		varname = gettext("debug");
2470 		if (reqlevel == 0) {
2471 			/* check for a string... */
2472 			reqlevel = parsedbgopts(argv[0]);
2473 		}
2474 		if (reqlevel == D_INVALID)
2475 			bail_msg(gettext("Bad debug flag: %s"), argv[0]);
2476 		break;
2477 	case IKE_SVC_SET_PRIV:
2478 		if (argc > 1)
2479 			Bail("Too many arguments to \"set priv\"");
2480 
2481 		varname = gettext("privilege");
2482 		if (reqlevel == 0) {
2483 			/* check for a string... */
2484 			reqlevel = privstr2num(argv[0]);
2485 		}
2486 		if (reqlevel > IKE_PRIV_MAXIMUM)
2487 			bail_msg(gettext("Bad privilege flag: %s"), argv[0]);
2488 		break;
2489 	default:
2490 		bail_msg(gettext("unrecognized set command (%d)"), cmd);
2491 	}
2492 
2493 	dreq = &req.svc_dbg;
2494 	dreq->cmd = cmd;
2495 	dreq->dbg_level = reqlevel;
2496 
2497 	if ((argc == 2) && (cmd == IKE_SVC_SET_DBG)) {
2498 		fd = open(argv[1], O_RDWR | O_CREAT | O_APPEND,
2499 		    S_IRUSR | S_IWUSR);
2500 		if (fd < 0)
2501 			Bail("open debug file");
2502 		desc.d_data.d_desc.d_descriptor = fd;
2503 		desc.d_attributes = DOOR_DESCRIPTOR;
2504 		descp = &desc;
2505 		ndesc = 1;
2506 	}
2507 
2508 	rtn = ikedoor_call((char *)&req, sizeof (ike_dbg_t), descp, ndesc);
2509 
2510 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2511 		ikeadm_err_exit(&rtn->svc_err,
2512 		    gettext("error setting %s level"), varname);
2513 	}
2514 	dreq = &rtn->svc_dbg;
2515 	(void) printf(
2516 	    gettext("Successfully changed %s level from 0x%x to 0x%x\n"),
2517 	    varname, dreq->dbg_level, reqlevel);
2518 
2519 	if (cmd == IKE_SVC_SET_DBG) {
2520 		print_categories(reqlevel);
2521 	} else {
2522 		(void) printf(gettext("New privilege level 0x%x enables %s\n"),
2523 		    reqlevel, privstr(reqlevel));
2524 	}
2525 }
2526 
2527 static void
2528 do_getstats(int cmd)
2529 {
2530 	ike_service_t	*rtn;
2531 	ike_statreq_t	sreq, *sreqp;
2532 	ike_stats_t	*sp;
2533 
2534 	sreq.cmd = cmd;
2535 
2536 	rtn = ikedoor_call((char *)&sreq, sizeof (ike_statreq_t), NULL, 0);
2537 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2538 		ikeadm_err_exit(&rtn->svc_err, gettext("error getting stats"));
2539 	}
2540 
2541 	sreqp = &rtn->svc_stats;
2542 	sp = (ike_stats_t *)(sreqp + 1);
2543 	print_stats(sp, sreqp->stat_len);
2544 }
2545 
2546 static void
2547 do_getdefs(int cmd)
2548 {
2549 	ike_service_t	*rtn;
2550 	ike_defreq_t	dreq, *dreqp;
2551 	ike_defaults_t	*dp;
2552 
2553 	dreq.cmd = cmd;
2554 
2555 	rtn = ikedoor_call((char *)&dreq, sizeof (ike_defreq_t), NULL, 0);
2556 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2557 		ikeadm_err_exit(&rtn->svc_err,
2558 		    gettext("error getting defaults"));
2559 	}
2560 
2561 	dreqp = &rtn->svc_defaults;
2562 	dp = (ike_defaults_t *)(dreqp + 1);
2563 
2564 	/*
2565 	 * Before printing each line, make sure the structure we were
2566 	 * given is big enough to include the fields needed.
2567 	 * Silently bail out of there is a version mismatch.
2568 	 */
2569 	if (dreqp->stat_len < ((2 * sizeof (ike_defaults_t))
2570 	    + sizeof (ike_defreq_t)) || dreqp->version != DOORVER) {
2571 		return;
2572 	}
2573 	do_print_defaults(dp);
2574 }
2575 
2576 static void
2577 do_dump(int cmd)
2578 {
2579 	char		*name;
2580 	ike_service_t	req, *rtn;
2581 	ike_dump_t	*dreq, *dump;
2582 
2583 	switch (cmd) {
2584 	case IKE_SVC_DUMP_P1S:
2585 		name = gettext("phase 1 SA info");
2586 		break;
2587 	case IKE_SVC_DUMP_RULES:
2588 		name = gettext("policy rules");
2589 		break;
2590 	case IKE_SVC_DUMP_PS:
2591 		name = gettext("preshared keys");
2592 		break;
2593 	case IKE_SVC_DUMP_CERTCACHE:
2594 		name = gettext("certcache");
2595 		break;
2596 	default:
2597 		bail_msg(gettext("unrecognized dump command (%d)"), cmd);
2598 	}
2599 
2600 	dreq = &req.svc_dump;
2601 	dreq->cmd = cmd;
2602 	dreq->dump_len = 0;
2603 	dreq->dump_next = 0;
2604 	do {
2605 		rtn = ikedoor_call((char *)&req, sizeof (ike_dump_t),
2606 		    NULL, 0);
2607 		if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
2608 			if (rtn && (rtn->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
2609 				/* no entries to print */
2610 				break;
2611 			}
2612 			ikeadm_err_exit(&rtn->svc_err,
2613 			    gettext("error getting %s"), name);
2614 		}
2615 		dump = &rtn->svc_dump;
2616 
2617 		switch (cmd) {
2618 		case IKE_SVC_DUMP_P1S:
2619 			print_p1((ike_p1_sa_t *)(dump + 1));
2620 			break;
2621 		case IKE_SVC_DUMP_RULES:
2622 			print_rule((ike_rule_t *)(dump + 1));
2623 			break;
2624 		case IKE_SVC_DUMP_PS:
2625 			print_ps((ike_ps_t *)(dump + 1));
2626 			break;
2627 		case IKE_SVC_DUMP_CERTCACHE:
2628 			print_certcache((ike_certcache_t *)(dump + 1));
2629 			break;
2630 		}
2631 
2632 		dreq->dump_next = dump->dump_next;
2633 
2634 		(void) munmap((char *)rtn, dump->dump_len);
2635 
2636 	} while (dreq->dump_next);
2637 
2638 	(void) printf(gettext("\nCompleted dump of %s\n"), name);
2639 }
2640 
2641 static void
2642 do_getdel_doorcall(int cmd, int idlen, int idtype, char *idp, char *name)
2643 {
2644 	int		totallen;
2645 	char		*p;
2646 	ike_service_t	*reqp, *rtnp;
2647 	ike_get_t	*getp;
2648 	boolean_t	getcmd;
2649 
2650 	getcmd = ((cmd == IKE_SVC_GET_P1) || (cmd == IKE_SVC_GET_RULE) ||
2651 	    (cmd == IKE_SVC_GET_PS));
2652 
2653 	/*
2654 	 * WARNING: to avoid being redundant, this code takes advantage
2655 	 * of the fact that the ike_get_t and ike_del_t structures are
2656 	 * identical (only the field names differ, their function and
2657 	 * size are the same).  If for some reason those structures
2658 	 * change, this code will need to be re-written to accomodate
2659 	 * that difference.
2660 	 */
2661 	totallen = sizeof (ike_get_t) + idlen;
2662 	if ((reqp = (ike_service_t *)malloc(totallen)) == NULL)
2663 		Bail("malloc(id)");
2664 
2665 	getp = &reqp->svc_get;
2666 	getp->cmd = cmd;
2667 	getp->get_len = totallen;
2668 	getp->get_idtype = idtype;
2669 	p = (char *)(getp + 1);
2670 
2671 	(void) memcpy(p, idp, idlen);
2672 
2673 	rtnp = ikedoor_call((char *)reqp, totallen, NULL, 0);
2674 	if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
2675 		if (rtnp && (rtnp->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
2676 			message(gettext("Could not find requested %s."), name);
2677 		} else {
2678 			ikeadm_err_msg(&rtnp->svc_err, gettext("error %s %s"),
2679 			    (getcmd) ? gettext("getting") : gettext("deleting"),
2680 			    name);
2681 		}
2682 		free(reqp);
2683 		return;
2684 	}
2685 	getp = &rtnp->svc_get;
2686 
2687 	if (getcmd) {
2688 		switch (cmd) {
2689 		case IKE_SVC_GET_P1:
2690 			print_p1((ike_p1_sa_t *)(getp + 1));
2691 			break;
2692 		case IKE_SVC_GET_PS:
2693 			print_ps((ike_ps_t *)(getp + 1));
2694 			break;
2695 		case IKE_SVC_GET_RULE:
2696 			print_rule((ike_rule_t *)(getp + 1));
2697 			break;
2698 		}
2699 	} else {
2700 		message(gettext("Successfully deleted selected %s."), name);
2701 	}
2702 
2703 	(void) munmap((char *)rtnp, getp->get_len);
2704 	free(reqp);
2705 }
2706 
2707 static void
2708 do_getdel(int cmd, int argc, char **argv)
2709 {
2710 	int		idlen, idtype = 0, i, j;
2711 	int		bytelen1, bytelen2;
2712 	char		*name, *idp, *p, *p1, *p2;
2713 	ike_addr_pr_t	apr;
2714 	ike_cky_pr_t	cpr;
2715 	sadb_ident_t	*sid1p, *sid2p;
2716 	struct hostent	*he1p, *he2p;
2717 	char		label[MAX_LABEL_LEN];
2718 
2719 	if ((argc < 1) || (argv[0] == NULL)) {
2720 		Bail("not enough identification info");
2721 	}
2722 
2723 	switch (cmd) {
2724 	case IKE_SVC_GET_P1:
2725 	case IKE_SVC_DEL_P1:
2726 		name = gettext("phase 1 SA");
2727 		/*
2728 		 * The first token must either be an address (or hostname)
2729 		 * or a cookie.  We require cookies to be entered as hex
2730 		 * numbers, beginning with 0x; so if our token starts with
2731 		 * that, it's a cookie.
2732 		 */
2733 		if (strncmp(argv[0], "0x", 2) == 0) {
2734 			if (parse_cky_pr(argc, argv, &cpr) >= 0) {
2735 				idtype = IKE_ID_CKY_PAIR;
2736 				idlen = sizeof (ike_cky_pr_t);
2737 				idp = (char *)&cpr;
2738 			}
2739 		} else {
2740 			if (parse_addr_pr(argc, argv, &he1p, &he2p) >= 0) {
2741 				idtype = IKE_ID_ADDR_PAIR;
2742 				idlen = sizeof (ike_addr_pr_t);
2743 			}
2744 		}
2745 		break;
2746 
2747 	case IKE_SVC_GET_RULE:
2748 	case IKE_SVC_DEL_RULE:
2749 		name = gettext("policy rule");
2750 		if (parse_label(argc, argv, label) >= 0) {
2751 			idtype = IKE_ID_LABEL;
2752 			idlen = MAX_LABEL_LEN;
2753 			idp = label;
2754 		}
2755 		break;
2756 
2757 	case IKE_SVC_GET_PS:
2758 	case IKE_SVC_DEL_PS:
2759 		name = gettext("preshared key");
2760 		/*
2761 		 * The first token must either be an address or an ident
2762 		 * type.  Check for an ident type to determine which it is.
2763 		 */
2764 		if (parse_idtype(argv[0], NULL) >= 0) {
2765 			if (parse_ident_pr(argc, argv, &sid1p, &sid2p) >= 0) {
2766 				idtype = IKE_ID_IDENT_PAIR;
2767 				idlen = SADB_64TO8(sid1p->sadb_ident_len) +
2768 				    SADB_64TO8(sid2p->sadb_ident_len);
2769 			}
2770 		} else {
2771 			if (parse_addr_pr(argc, argv, &he1p, &he2p) >= 0) {
2772 				idtype = IKE_ID_ADDR_PAIR;
2773 				idlen = sizeof (ike_addr_pr_t);
2774 			}
2775 		}
2776 		break;
2777 
2778 	default:
2779 		bail_msg(gettext("unrecognized get/del command (%d)"), cmd);
2780 	}
2781 
2782 	switch (idtype) {
2783 	case IKE_ID_ADDR_PAIR:
2784 		/*
2785 		 * we might have exploding addrs here; do every possible
2786 		 * combination.
2787 		 */
2788 		i = 0;
2789 		j = 0;
2790 		while ((p1 = he1p->h_addr_list[i++]) != NULL) {
2791 			headdr2sa(p1, &apr.loc_addr, he1p->h_length);
2792 
2793 			while ((p2 = he2p->h_addr_list[j++]) != NULL) {
2794 				headdr2sa(p2, &apr.rem_addr, he2p->h_length);
2795 				do_getdel_doorcall(cmd, idlen, idtype,
2796 				    (char *)&apr, name);
2797 			}
2798 		}
2799 		FREE_HE(he1p);
2800 		FREE_HE(he2p);
2801 		break;
2802 
2803 	case IKE_ID_IDENT_PAIR:
2804 		bytelen1 = SADB_64TO8(sid1p->sadb_ident_len);
2805 		bytelen2 = SADB_64TO8(sid2p->sadb_ident_len);
2806 		if (idlen != bytelen1 + bytelen2)
2807 			Bail("ident syntax error");
2808 		idp = p = (char *)malloc(idlen);
2809 		if (p == NULL)
2810 			Bail("malloc(id)");
2811 		(void) memcpy(p, (char *)sid1p, bytelen1);
2812 		p += bytelen1;
2813 		(void) memcpy(p, (char *)sid2p, bytelen2);
2814 		do_getdel_doorcall(cmd, idlen, idtype, idp, name);
2815 		free(idp);
2816 		free(sid1p);
2817 		free(sid2p);
2818 		break;
2819 
2820 	case IKE_ID_CKY_PAIR:
2821 	case IKE_ID_LABEL:
2822 		do_getdel_doorcall(cmd, idlen, idtype, idp, name);
2823 		break;
2824 
2825 	case 0:
2826 	default:
2827 		bail_msg(gettext("invalid %s identification\n"), name);
2828 	}
2829 }
2830 
2831 /*
2832  * Copy source into target, inserting an escape character ('\') before
2833  * any quotes that appear.  Return true on success, false on failure.
2834  */
2835 static boolean_t
2836 escapequotes(char *target, char *source, int tlen)
2837 {
2838 	int	s, t, len = strlen(source) + 1;
2839 
2840 	if (tlen < len)
2841 		return (B_FALSE);
2842 
2843 	for (s = 0, t = 0; s < len && t < tlen; s++) {
2844 		if (source[s] == '\"')
2845 			target[t++] = '\\';
2846 		target[t++] = source[s];
2847 	}
2848 
2849 	if ((t == tlen) && (s < len))
2850 		return (B_FALSE);
2851 
2852 	return (B_TRUE);
2853 }
2854 
2855 /*
2856  * Return true if the arg following the given keyword should
2857  * be in quotes (i.e. is a string), false if not.
2858  */
2859 static boolean_t
2860 quotedfield(char *keywd)
2861 {
2862 	if ((strncmp(keywd, "label", strlen("label") + 1) == 0) ||
2863 	    (strncmp(keywd, "local_id", strlen("local_id") + 1) == 0) ||
2864 	    (strncmp(keywd, "remote_id", strlen("remote_id") + 1) == 0))
2865 		return (B_TRUE);
2866 
2867 	return (B_FALSE);
2868 }
2869 
2870 static void
2871 do_new(int cmd, int argc, char **argv)
2872 {
2873 	ike_service_t	*rtn;
2874 	ike_new_t	new, *newp = NULL;
2875 	door_desc_t	desc, *descp = NULL;
2876 	int		i, fd, ndesc = 0, buflen;
2877 	char		*name, tmpfilepath[32];
2878 	FILE		*tmpfile;
2879 
2880 	switch (cmd) {
2881 	case IKE_SVC_NEW_PS:
2882 		name = gettext("preshared key");
2883 		break;
2884 	case IKE_SVC_NEW_RULE:
2885 		name = gettext("policy rule");
2886 		break;
2887 	default:
2888 		bail_msg(gettext("unrecognized new command (%d)"), cmd);
2889 	}
2890 
2891 	if (argc == 1) {
2892 		/* We've been given a file to read from */
2893 		fd = open(argv[0], O_RDONLY);
2894 		if (fd < 0)
2895 			Bail("open source file");
2896 
2897 		desc.d_data.d_desc.d_descriptor = fd;
2898 		desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
2899 		descp = &desc;
2900 		ndesc = 1;
2901 
2902 		new.cmd = cmd;
2903 		new.new_len = 0;
2904 		newp = &new;
2905 		buflen = sizeof (ike_new_t);
2906 
2907 	} else if ((argc > 1) && (cmd == IKE_SVC_NEW_PS)) {
2908 		/*
2909 		 * This is an alternative to using the tmpfile method
2910 		 * for preshared keys.  It means we're duplicating the
2911 		 * parsing effort that happens in readps.c; but it
2912 		 * does avoid having the key sitting in a file.
2913 		 */
2914 		ike_ps_t	*psp;
2915 		int		pslen;
2916 
2917 		/*
2918 		 * must be in interactive mode; don't want keys in
2919 		 * the process args.
2920 		 */
2921 		if (!interactive)
2922 			Bail("Must be in interactive mode to add key info.");
2923 		if (parse_ps(argc, argv, &psp, &pslen) < 0) {
2924 			errno = 0;
2925 			Bail("invalid preshared key definition");
2926 		}
2927 		newp = malloc(sizeof (ike_new_t) + pslen);
2928 		if (newp == NULL)
2929 			Bail("alloc pskey");
2930 		newp->cmd = cmd;
2931 		newp->new_len = sizeof (ike_new_t) + pslen;
2932 		(void) memcpy((char *)(newp + 1), psp, pslen);
2933 		buflen = newp->new_len;
2934 		/* parse_ps allocated the ike_ps_t buffer; free it now */
2935 		free(psp);
2936 
2937 	} else if ((argc > 1) && (cmd == IKE_SVC_NEW_RULE)) {
2938 		/*
2939 		 * We've been given the item in argv.  However, parsing
2940 		 * rules can get more than a little messy, and in.iked
2941 		 * already has a great parser for this stuff!  So don't
2942 		 * fool around with trying to do the parsing here. Just
2943 		 * write it out to a tempfile, and send the fd to in.iked.
2944 		 *
2945 		 * We could conceivably do this for preshared keys,
2946 		 * rather than duplicating the parsing effort; but that
2947 		 * would mean the key would be written out to a file,
2948 		 * which isn't such a good idea.
2949 		 */
2950 		boolean_t	doquotes = B_FALSE;
2951 		int		rtn;
2952 
2953 		if ((argv[0][0] != '{') ||
2954 		    (argv[argc - 1][strlen(argv[argc - 1]) - 1] != '}'))
2955 			bail_msg(gettext("improperly formatted %s"), name);
2956 
2957 		/* attempt to use a fairly unpredictable file name... */
2958 		(void) sprintf(tmpfilepath, "/var/run/%x", (int)gethrtime());
2959 		fd = open(tmpfilepath, O_RDWR | O_CREAT | O_EXCL,
2960 		    S_IRUSR | S_IWUSR);
2961 		if (fd < 0)
2962 			Bail("cannot open tmpfile");
2963 
2964 		/* and make it inaccessible asap */
2965 		if (unlink(tmpfilepath) < 0) {
2966 			(void) close(fd);
2967 			Bail("tmpfile error");
2968 		}
2969 
2970 		tmpfile = fdopen(fd, "w");
2971 		if (tmpfile == NULL) {
2972 			(void) close(fd);
2973 			Bail("cannot write to tmpfile");
2974 		}
2975 
2976 		for (i = 0; i < argc; i++) {
2977 			/*
2978 			 * We have to do some gyrations with our string here,
2979 			 * to properly handle quotes.  There are two issues:
2980 			 * - some of the fields of a rule may have embedded
2981 			 *   whitespace, and thus must be quoted on the cmd
2982 			 *   line.  The shell removes the quotes, and gives
2983 			 *   us a single argv string; but we need to put the
2984 			 *   quotes back in when we write the string out to
2985 			 *   file.  The doquotes boolean is set when we
2986 			 *   process a keyword which will be followed by a
2987 			 *   string value (so the NEXT argv element will be
2988 			 *   quoted).
2989 			 * - there might be a quote character in a field,
2990 			 *   that was escaped on the cmdline.  The shell
2991 			 *   removes the escape char, and leaves the quote
2992 			 *   in the string it gives us.  We need to put the
2993 			 *   escape char back in before writing to file.
2994 			 */
2995 			char	field[MAXLINESIZE];
2996 			if (!escapequotes(field, argv[i], MAXLINESIZE))
2997 				Bail("write to tmpfile failed (arg too big)");
2998 			if (doquotes) {
2999 				rtn = fprintf(tmpfile, "\"%s\"\n", field);
3000 				doquotes = B_FALSE;
3001 			} else {
3002 				rtn = fprintf(tmpfile, "%s\n", field);
3003 			}
3004 			if (rtn < 0)
3005 				Bail("write to tmpfile failed");
3006 			/*
3007 			 * check if this is a keyword identifying
3008 			 * a field that needs to be quoted.
3009 			 */
3010 			doquotes = quotedfield(argv[i]);
3011 		}
3012 		if (fflush(tmpfile) == EOF)
3013 			Bail("write to tmpfile failed");
3014 		/* rewind so that the daemon will get the beginning */
3015 		rewind(tmpfile);
3016 
3017 		desc.d_data.d_desc.d_descriptor = fd;
3018 		desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
3019 		descp = &desc;
3020 		ndesc = 1;
3021 
3022 		new.cmd = cmd;
3023 		new.new_len = 0;
3024 		newp = &new;
3025 		buflen = sizeof (ike_new_t);
3026 
3027 	} else {
3028 		/* not enough information! */
3029 		bail_msg(gettext("missing %s description or file name"), name);
3030 	}
3031 
3032 	rtn = ikedoor_call((char *)newp, buflen, descp, ndesc);
3033 
3034 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
3035 		ikeadm_err_msg(&rtn->svc_err,
3036 		    gettext("error creating new %s"), name);
3037 	} else {
3038 		message(gettext("Successfully created new %s."), name);
3039 	}
3040 }
3041 
3042 static void
3043 do_flush(int cmd)
3044 {
3045 	ike_service_t	*rtnp;
3046 	ike_flush_t	flush;
3047 
3048 	if (cmd != IKE_SVC_FLUSH_P1S && cmd != IKE_SVC_FLUSH_CERTCACHE) {
3049 		bail_msg(gettext("unrecognized flush command (%d)."), cmd);
3050 	}
3051 
3052 	flush.cmd = cmd;
3053 
3054 	rtnp = ikedoor_call((char *)&flush, sizeof (ike_flush_t), NULL, 0);
3055 	if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
3056 		ikeadm_err_exit(&rtnp->svc_err, gettext("error doing flush"));
3057 	}
3058 	if (cmd == IKE_SVC_FLUSH_P1S)
3059 		message(gettext("Successfully flushed P1 SAs."));
3060 	else
3061 		message(gettext("Successfully flushed cert cache."));
3062 }
3063 
3064 static void
3065 do_rw(int cmd, int argc, char **argv)
3066 {
3067 	ike_service_t	*rtnp;
3068 	ike_rw_t	rw;
3069 	door_desc_t	desc, *descp = NULL;
3070 	int		oflag, omode, fd, ndesc = 0;
3071 	char		*op, *obj = NULL;
3072 	boolean_t	writing = B_FALSE;
3073 
3074 	switch (cmd) {
3075 	case IKE_SVC_READ_PS:
3076 		obj = gettext("preshared key");
3077 		/* FALLTHRU */
3078 	case IKE_SVC_READ_RULES:
3079 		if (obj == NULL)
3080 			obj = gettext("policy rule");
3081 		op = gettext("read");
3082 		oflag = O_RDONLY;
3083 		omode = 0;
3084 		break;
3085 
3086 	case IKE_SVC_WRITE_PS:
3087 		obj = gettext("preshared key");
3088 		/* FALLTHRU */
3089 	case IKE_SVC_WRITE_RULES:
3090 		if (obj == NULL)
3091 			obj = gettext("policy rule");
3092 		op = gettext("write");
3093 		oflag = O_RDWR | O_CREAT | O_EXCL;
3094 		omode = S_IRUSR | S_IWUSR;
3095 
3096 		/* for write commands, dest location must be specified */
3097 		if (argc < 1) {
3098 			bail_msg(gettext("destination location required "
3099 			    "to write %ss"), obj);
3100 		}
3101 		writing = B_TRUE;
3102 		break;
3103 
3104 	default:
3105 		bail_msg(gettext("unrecognized read/write command (%d)."), cmd);
3106 	}
3107 
3108 	rw.cmd = cmd;
3109 
3110 	if (argc >= 1) {
3111 		rw.rw_loc = IKE_RW_LOC_USER_SPEC;
3112 		fd = open(argv[0], oflag, omode);
3113 		if (fd < 0)
3114 			Bail("open user-specified file");
3115 
3116 		desc.d_data.d_desc.d_descriptor = fd;
3117 		desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
3118 		descp = &desc;
3119 		ndesc = 1;
3120 	} else {
3121 		rw.rw_loc = IKE_RW_LOC_DEFAULT;
3122 	}
3123 
3124 	rtnp = ikedoor_call((char *)&rw, sizeof (ike_rw_t), descp, ndesc);
3125 	if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
3126 		/*
3127 		 * Need to remove the target file in the
3128 		 * case of a failed write command.
3129 		 */
3130 		if (writing) {
3131 			/*
3132 			 * argv[0] must be valid if we're writing; we
3133 			 * exit before setting this boolean if not.
3134 			 */
3135 			(void) unlink(argv[0]);
3136 			(void) close(fd);
3137 
3138 			if ((rtnp != NULL) &&
3139 			    (rtnp->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
3140 				message(gettext("No %s information to write."),
3141 				    obj);
3142 				return;
3143 			}
3144 		}
3145 		ikeadm_err_exit(&rtnp->svc_err, gettext("error doing %s"), op);
3146 	}
3147 	message(gettext("Completed %s of %s configuration information."),
3148 	    op, obj);
3149 }
3150 
3151 static void
3152 do_rbdump()
3153 {
3154 	ike_cmd_t	req;
3155 	ike_service_t	*rtnp;
3156 
3157 	req.cmd = IKE_SVC_DBG_RBDUMP;
3158 
3159 	rtnp = ikedoor_call((char *)&req, sizeof (ike_cmd_t), NULL, 0);
3160 	if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
3161 		ikeadm_err_exit(&rtnp->svc_err, gettext("error doing flush"));
3162 	}
3163 	message(gettext("Successfully dumped rulebase; check iked dbg"));
3164 }
3165 
3166 #define	REQ_ARG_CNT	1
3167 
3168 /*ARGSUSED*/
3169 static void
3170 parseit(int argc, char **argv, char *notused, boolean_t notused_either)
3171 {
3172 	int	cmd, cmd_obj_args = 1;
3173 	char	*cmdstr, *objstr;
3174 
3175 	if (interactive) {
3176 		if (argc == 0)
3177 			return;
3178 	}
3179 
3180 	if (argc < REQ_ARG_CNT) {
3181 		usage();
3182 	}
3183 
3184 	cmdstr = argv[0];
3185 	if (argc > REQ_ARG_CNT) {
3186 		cmd_obj_args++;
3187 		objstr = argv[1];
3188 	} else {
3189 		objstr = NULL;
3190 	}
3191 	cmd = parsecmd(cmdstr, objstr);
3192 
3193 	/* skip over args specifying command/object */
3194 	argc -= cmd_obj_args;
3195 	argv += cmd_obj_args;
3196 
3197 	switch (cmd) {
3198 	case IKE_SVC_GET_DEFS:
3199 		if (argc != 0) {
3200 			print_get_help();
3201 			break;
3202 		}
3203 		do_getdefs(cmd);
3204 		break;
3205 	case IKE_SVC_GET_DBG:
3206 	case IKE_SVC_GET_PRIV:
3207 		if (argc != 0) {
3208 			print_get_help();
3209 			break;
3210 		}
3211 		do_getvar(cmd);
3212 		break;
3213 	case IKE_SVC_GET_STATS:
3214 		if (argc != 0) {
3215 			print_get_help();
3216 			break;
3217 		}
3218 		do_getstats(cmd);
3219 		break;
3220 	case IKE_SVC_SET_DBG:
3221 	case IKE_SVC_SET_PRIV:
3222 		do_setvar(cmd, argc, argv);
3223 		break;
3224 	case IKE_SVC_SET_PIN:
3225 	case IKE_SVC_DEL_PIN:
3226 		do_setdel_pin(cmd, argc, argv);
3227 		break;
3228 	case IKE_SVC_DUMP_P1S:
3229 	case IKE_SVC_DUMP_RULES:
3230 	case IKE_SVC_DUMP_PS:
3231 	case IKE_SVC_DUMP_CERTCACHE:
3232 		if (argc != NULL) {
3233 			print_dump_help();
3234 			break;
3235 		}
3236 		do_dump(cmd);
3237 		break;
3238 	case IKE_SVC_GET_P1:
3239 	case IKE_SVC_GET_RULE:
3240 	case IKE_SVC_GET_PS:
3241 	case IKE_SVC_DEL_P1:
3242 	case IKE_SVC_DEL_RULE:
3243 	case IKE_SVC_DEL_PS:
3244 		do_getdel(cmd, argc, argv);
3245 		break;
3246 	case IKE_SVC_NEW_RULE:
3247 	case IKE_SVC_NEW_PS:
3248 		do_new(cmd, argc, argv);
3249 		break;
3250 	case IKE_SVC_FLUSH_P1S:
3251 	case IKE_SVC_FLUSH_CERTCACHE:
3252 		if (argc != 0) {
3253 			print_flush_help();
3254 			break;
3255 		}
3256 		do_flush(cmd);
3257 		break;
3258 	case IKE_SVC_READ_RULES:
3259 	case IKE_SVC_READ_PS:
3260 	case IKE_SVC_WRITE_RULES:
3261 	case IKE_SVC_WRITE_PS:
3262 		do_rw(cmd, argc, argv);
3263 		break;
3264 	case IKEADM_HELP_GENERAL:
3265 		print_help();
3266 		break;
3267 	case IKEADM_HELP_GET:
3268 		print_get_help();
3269 		break;
3270 	case IKEADM_HELP_SET:
3271 		print_set_help();
3272 		break;
3273 	case IKEADM_HELP_ADD:
3274 		print_add_help();
3275 		break;
3276 	case IKEADM_HELP_DEL:
3277 		print_del_help();
3278 		break;
3279 	case IKEADM_HELP_DUMP:
3280 		print_dump_help();
3281 		break;
3282 	case IKEADM_HELP_FLUSH:
3283 		print_flush_help();
3284 		break;
3285 	case IKEADM_HELP_READ:
3286 		print_read_help();
3287 		break;
3288 	case IKEADM_HELP_WRITE:
3289 		print_write_help();
3290 		break;
3291 	case IKEADM_HELP_TOKEN:
3292 		print_token_help();
3293 		break;
3294 	case IKEADM_HELP_HELP:
3295 		print_help_help();
3296 		break;
3297 	case IKEADM_EXIT:
3298 		if (interactive)
3299 			exit(0);
3300 		break;
3301 	case IKE_SVC_DBG_RBDUMP:
3302 		do_rbdump();
3303 		break;
3304 	case IKE_SVC_ERROR:
3305 		usage();
3306 	default:
3307 		exit(0);
3308 	}
3309 }
3310 
3311 int
3312 main(int argc, char **argv)
3313 {
3314 	char	ch;
3315 
3316 	(void) setlocale(LC_ALL, "");
3317 #if !defined(TEXT_DOMAIN)
3318 #define	TEXT_DOMAIN "SYS_TEST"
3319 #endif
3320 	(void) textdomain(TEXT_DOMAIN);
3321 
3322 	while ((ch = getopt(argc, argv, "hpn")) != EOF) {
3323 		switch (ch) {
3324 		case 'h':
3325 			print_help();
3326 			return (0);
3327 		case 'p':
3328 			pflag = B_TRUE;
3329 			break;
3330 		case 'n':
3331 			nflag = B_TRUE;
3332 			break;
3333 		default:
3334 			usage();
3335 		}
3336 	}
3337 	argc -= optind;
3338 	argv += optind;
3339 
3340 	if (open_door() < 0) {
3341 		(void) fprintf(stderr,
3342 		    gettext("Unable to communicate with in.iked\n"));
3343 		Bail("open_door failed");
3344 	}
3345 
3346 	if (*argv == NULL) {
3347 		/* no cmd-line args, do interactive mode */
3348 		do_interactive(stdin, NULL, "ikeadm> ", NULL, parseit,
3349 		    no_match);
3350 	}
3351 
3352 	parseit(argc, argv, NULL, B_FALSE);
3353 
3354 	return (0);
3355 }
3356