Home | History | Annotate | Download | only in ipsecutils
      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 2009 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 	default:
   1446 		(void) snprintf(rtn, MAXLINESIZE, gettext("<unknown %d>"), grp);
   1447 		return (rtn);
   1448 	}
   1449 }
   1450 
   1451 static void
   1452 print_hdr(char *prefix, ike_p1_hdr_t *hdrp)
   1453 {
   1454 	char sbuf[TBUF_SIZE];
   1455 	char tbuf[TBUF_SIZE];
   1456 	time_t ltime = (time_t)hdrp->p1hdr_dpd_time;
   1457 
   1458 	(void) printf(
   1459 	    gettext("%s Cookies: Initiator 0x%llx  Responder 0x%llx\n"),
   1460 	    prefix, ntohll(hdrp->p1hdr_cookies.cky_i),
   1461 	    ntohll(hdrp->p1hdr_cookies.cky_r));
   1462 	(void) printf(gettext("%s The local host is the %s.\n"), prefix,
   1463 	    hdrp->p1hdr_isinit ? gettext("initiator") : gettext("responder"));
   1464 	(void) printf(gettext("%s ISAKMP version %d.%d; %s exchange\n"), prefix,
   1465 	    hdrp->p1hdr_major, hdrp->p1hdr_minor, xchgstr(hdrp->p1hdr_xchg));
   1466 	(void) printf(gettext("%s Current state is %s\n"), prefix,
   1467 	    statestr(hdrp->p1hdr_state));
   1468 	if (hdrp->p1hdr_support_dpd == B_FALSE) {
   1469 		return;
   1470 	}
   1471 	(void) printf(gettext("%s Dead Peer Detection (RFC 3706)"
   1472 	    " enabled"), prefix);
   1473 	if (hdrp->p1hdr_dpd_state < DPD_IN_PROGRESS) {
   1474 		(void) printf("\n");
   1475 		return;
   1476 	}
   1477 	if (strftime(tbuf, TBUF_SIZE, NULL,
   1478 	    localtime(&ltime)) == 0) {
   1479 		(void) strlcpy(tbuf, gettext("<time conversion failed>"),
   1480 		    TBUF_SIZE);
   1481 	}
   1482 	(void) printf(gettext("\n%s Dead Peer Detection handshake "), prefix);
   1483 	switch (hdrp->p1hdr_dpd_state) {
   1484 	case DPD_SUCCESSFUL:
   1485 		(void) strlcpy(sbuf, gettext("was successful at "), TBUF_SIZE);
   1486 		break;
   1487 	case DPD_FAILURE:
   1488 		(void) strlcpy(sbuf, gettext("failed at "), TBUF_SIZE);
   1489 		break;
   1490 	case DPD_IN_PROGRESS:
   1491 		(void) strlcpy(sbuf, gettext("is in progress."), TBUF_SIZE);
   1492 		break;
   1493 	}
   1494 	(void) printf("%s %s", sbuf,
   1495 	    (hdrp->p1hdr_dpd_state == DPD_IN_PROGRESS) ? "" : tbuf);
   1496 	(void) printf("\n");
   1497 }
   1498 
   1499 static void
   1500 print_lt_limits(char *prefix, ike_p1_xform_t *xfp)
   1501 {
   1502 	char byte_str[BYTE_STR_SIZE]; /* byte lifetime string representation */
   1503 	char secs_str[SECS_STR_SIZE]; /* lifetime string representation */
   1504 
   1505 	(void) printf(gettext("%s Lifetime limits:\n"), prefix);
   1506 	(void) printf(gettext("%s %u seconds%s; %u kbytes %sprotected\n"),
   1507 	    prefix, xfp->p1xf_max_secs, secs2out(xfp->p1xf_max_secs,
   1508 	    secs_str, sizeof (secs_str), SPC_BEGIN), xfp->p1xf_max_kbytes,
   1509 	    bytecnt2out((uint64_t)xfp->p1xf_max_kbytes << 10, byte_str,
   1510 	    sizeof (byte_str), SPC_END));
   1511 	(void) printf(gettext("%s keying material for IPsec SAs can be "
   1512 	    "provided %u times%s\n"), prefix, xfp->p1xf_max_keyuses,
   1513 	    xfp->p1xf_max_keyuses == 0 ? " (no limit)" : "");
   1514 }
   1515 
   1516 #define	LT_USAGE_LEN	16	/* 1 uint64 + 2 uint32s */
   1517 static void
   1518 print_lt_usage(char *prefix, ike_p1_stats_t *sp)
   1519 {
   1520 	time_t	scratch;
   1521 	char	tbuf[TBUF_SIZE];
   1522 	char	bytestr[BYTE_STR_SIZE]; /* byte lifetime representation */
   1523 
   1524 	(void) printf(gettext("%s Current usage:\n"), prefix);
   1525 	scratch = (time_t)sp->p1stat_start;
   1526 	if (strftime(tbuf, TBUF_SIZE, NULL, localtime(&scratch)) == 0)
   1527 		(void) strlcpy(tbuf, gettext("<time conversion failed>"),
   1528 		    TBUF_SIZE);
   1529 	(void) printf(gettext("%s SA was created at %s\n"), prefix, tbuf);
   1530 	(void) printf(gettext("%s %u kbytes %sprotected\n"),
   1531 	    prefix, sp->p1stat_kbytes,
   1532 	    bytecnt2out((uint64_t)sp->p1stat_kbytes << 10, bytestr,
   1533 	    sizeof (bytestr), SPC_END));
   1534 	(void) printf(gettext("%s keying material for IPsec SAs provided "
   1535 	    "%u times\n"), prefix, sp->p1stat_keyuses);
   1536 }
   1537 
   1538 static void
   1539 print_xform(char *prefix, ike_p1_xform_t *xfp, boolean_t print_lifetimes)
   1540 {
   1541 	(void) printf(gettext("%s Authentication method: %s"), prefix,
   1542 	    authmethstr(xfp->p1xf_auth_meth));
   1543 	(void) printf(gettext("\n%s Encryption alg: "), prefix);
   1544 	(void) dump_ealg(xfp->p1xf_encr_alg, stdout);
   1545 	if (xfp->p1xf_encr_low_bits != 0) {
   1546 		(void) printf(gettext("(%d..%d)"), xfp->p1xf_encr_low_bits,
   1547 		    xfp->p1xf_encr_high_bits);
   1548 	} else if ((xfp->p1xf_encr_low_bits == 0) &&
   1549 	    (xfp->p1xf_encr_high_bits != 0)) {
   1550 		/*
   1551 		 * High bits is a placeholder for
   1552 		 * negotiated algorithm strength
   1553 		 */
   1554 		(void) printf(gettext("(%d)"), xfp->p1xf_encr_high_bits);
   1555 	}
   1556 	(void) printf(gettext("; Authentication alg: "));
   1557 	(void) dump_aalg(xfp->p1xf_auth_alg, stdout);
   1558 	(void) printf("\n%s ", prefix);
   1559 	if (xfp->p1xf_prf != 0)
   1560 		(void) printf(gettext("PRF: %s ; "), prfstr(xfp->p1xf_prf));
   1561 	(void) printf(gettext("Oakley Group: %s\n"),
   1562 	    dhstr(xfp->p1xf_dh_group));
   1563 	if (xfp->p1xf_pfs == 0) {
   1564 		(void) printf(gettext("%s Phase 2 PFS is not used\n"), prefix);
   1565 	} else {
   1566 		(void) printf(gettext(
   1567 		    "%s Phase 2 PFS is required (Oakley Group: %s)\n"),
   1568 		    prefix, dhstr(xfp->p1xf_pfs));
   1569 	}
   1570 
   1571 	if (print_lifetimes)
   1572 		print_lt_limits(prefix, xfp);
   1573 }
   1574 
   1575 static void
   1576 print_lifetime(char *prefix, ike_p1_xform_t *xfp, ike_p1_stats_t *sp,
   1577     int statlen)
   1578 {
   1579 	time_t	current, remain, exp;
   1580 	char	tbuf[TBUF_SIZE];
   1581 	char	byte_str[BYTE_STR_SIZE]; /* byte lifetime representation */
   1582 	char	secs_str[SECS_STR_SIZE]; /* seconds lifetime representation */
   1583 
   1584 	current = time(NULL);
   1585 
   1586 	print_lt_limits(prefix, xfp);
   1587 
   1588 	/*
   1589 	 * make sure the stats struct we've been passed is as big
   1590 	 * as we expect it to be.  The usage stats are at the end,
   1591 	 * so anything less than the size we expect won't work.
   1592 	 */
   1593 	if (statlen >= sizeof (ike_p1_stats_t)) {
   1594 		print_lt_usage(prefix, sp);
   1595 	} else {
   1596 		return;
   1597 	}
   1598 
   1599 	(void) printf(gettext("%s Expiration info:\n"), prefix);
   1600 
   1601 	if (xfp->p1xf_max_kbytes != 0)
   1602 		(void) printf(gettext("%s %u more bytes %scan be "
   1603 		    "protected.\n"),
   1604 		    prefix, xfp->p1xf_max_kbytes - sp->p1stat_kbytes,
   1605 		    bytecnt2out((uint64_t)(xfp->p1xf_max_kbytes -
   1606 		    sp->p1stat_kbytes) << 10, byte_str, sizeof (byte_str),
   1607 		    SPC_END));
   1608 
   1609 	if (xfp->p1xf_max_keyuses != 0)
   1610 		(void) printf(gettext("%s Keying material can be provided "
   1611 		    "%u more times.\n"), prefix,
   1612 		    xfp->p1xf_max_keyuses - sp->p1stat_keyuses);
   1613 
   1614 	if (xfp->p1xf_max_secs != 0) {
   1615 		exp = (time_t)sp->p1stat_start + (time_t)xfp->p1xf_max_secs;
   1616 		remain = exp - current;
   1617 		if (strftime(tbuf, TBUF_SIZE, NULL, localtime(&exp)) == 0)
   1618 			(void) strlcpy(tbuf,
   1619 			    gettext("<time conversion failed>"), TBUF_SIZE);
   1620 		/*
   1621 		 * The SA may have expired but still exist because libike
   1622 		 * has not freed it yet.
   1623 		 */
   1624 		if (remain > 0) {
   1625 			(void) printf(gettext(
   1626 			    "%s SA expires in %lu seconds%s\n"),
   1627 			    prefix, remain, secs2out(remain, secs_str,
   1628 			    sizeof (secs_str), SPC_BEGIN));
   1629 			(void) printf(gettext("%s Time of expiration: %s\n"),
   1630 			    prefix, tbuf);
   1631 		} else {
   1632 			(void) printf(gettext("%s SA Expired at %s\n"),
   1633 			    prefix, tbuf);
   1634 		}
   1635 	}
   1636 }
   1637 
   1638 /* used to verify structure lengths... */
   1639 #define	COUNTER_32BIT	4
   1640 #define	COUNTER_PAIR	8
   1641 
   1642 static void
   1643 print_p1stats(char *prefix, ike_p1_stats_t *sp, int statlen,
   1644     boolean_t print_lifetimes)
   1645 {
   1646 	if (statlen < COUNTER_PAIR)
   1647 		return;
   1648 	(void) printf(gettext("%s %u Quick Mode SAs created; "), prefix,
   1649 	    sp->p1stat_new_qm_sas);
   1650 	(void) printf(gettext("%u Quick Mode SAs deleted\n"),
   1651 	    sp->p1stat_del_qm_sas);
   1652 	statlen -= COUNTER_PAIR;
   1653 
   1654 	if ((print_lifetimes) && (statlen >= LT_USAGE_LEN))
   1655 		print_lt_usage(prefix, sp);
   1656 }
   1657 
   1658 static void
   1659 print_errs(char *prefix, ike_p1_errors_t *errp, int errlen)
   1660 {
   1661 	/*
   1662 	 * Don't try to break this one up; it's either all or nothing!
   1663 	 */
   1664 	if (errlen < sizeof (ike_p1_errors_t))
   1665 		return;
   1666 
   1667 	(void) printf(gettext("%s %u RX errors: "), prefix,
   1668 	    errp->p1err_decrypt + errp->p1err_hash + errp->p1err_otherrx);
   1669 	(void) printf(gettext("%u decryption, %u hash, %u other\n"),
   1670 	    errp->p1err_decrypt, errp->p1err_hash, errp->p1err_otherrx);
   1671 	(void) printf(gettext("%s %u TX errors\n"), prefix, errp->p1err_tx);
   1672 }
   1673 
   1674 static void
   1675 print_addr_range(char *prefix, ike_addr_pr_t *pr)
   1676 {
   1677 	boolean_t	range = B_TRUE;
   1678 	struct sockaddr_storage	*beg, *end;
   1679 	struct sockaddr_in	*bsin, *esin;
   1680 	struct sockaddr_in6	*bsin6, *esin6;
   1681 
   1682 	beg = &pr->beg_iprange;
   1683 	end = &pr->end_iprange;
   1684 
   1685 	if (beg->ss_family != end->ss_family) {
   1686 		(void) printf(gettext("%s invalid address range\n"), prefix);
   1687 		return;
   1688 	}
   1689 
   1690 	switch (beg->ss_family) {
   1691 	case AF_INET:
   1692 		bsin = (struct sockaddr_in *)beg;
   1693 		esin = (struct sockaddr_in *)end;
   1694 		if ((uint32_t)bsin->sin_addr.s_addr ==
   1695 		    (uint32_t)esin->sin_addr.s_addr)
   1696 			range = B_FALSE;
   1697 		break;
   1698 	case AF_INET6:
   1699 		bsin6 = (struct sockaddr_in6 *)beg;
   1700 		esin6 = (struct sockaddr_in6 *)end;
   1701 		if (IN6_ARE_ADDR_EQUAL(&bsin6->sin6_addr, &esin6->sin6_addr))
   1702 			range = B_FALSE;
   1703 		break;
   1704 	default:
   1705 		(void) printf(gettext("%s invalid address range\n"), prefix);
   1706 		return;
   1707 	}
   1708 
   1709 	(void) printf("%s ", prefix);
   1710 	(void) dump_sockaddr((struct sockaddr *)beg, 0, B_TRUE, stdout, nflag);
   1711 	if (range) {
   1712 		(void) printf(" - ");
   1713 		(void) dump_sockaddr((struct sockaddr *)end, 0, B_TRUE, stdout,
   1714 		    nflag);
   1715 	}
   1716 	(void) printf("\n");
   1717 
   1718 }
   1719 
   1720 /*
   1721  * used to tell printing function if info should be identified
   1722  * as belonging to initiator, responder, or neither
   1723  */
   1724 #define	IS_INITIATOR	1
   1725 #define	IS_RESPONDER	2
   1726 #define	DONT_PRINT_INIT	3
   1727 
   1728 static void
   1729 print_addr(char *prefix, struct sockaddr_storage *sa, int init_instr)
   1730 {
   1731 	(void) printf(gettext("%s Address"), prefix);
   1732 
   1733 	if (init_instr != DONT_PRINT_INIT)
   1734 		(void) printf(" (%s):\n", (init_instr == IS_INITIATOR) ?
   1735 		    gettext("Initiator") : gettext("Responder"));
   1736 	else
   1737 		(void) printf(":\n");
   1738 
   1739 	(void) printf("%s ", prefix);
   1740 	(void) dump_sockaddr((struct sockaddr *)sa, 0, B_FALSE, stdout, nflag);
   1741 }
   1742 
   1743 static void
   1744 print_id(char *prefix, sadb_ident_t *idp, int init_instr)
   1745 {
   1746 	boolean_t	canprint;
   1747 
   1748 	switch (init_instr) {
   1749 	case IS_INITIATOR:
   1750 		(void) printf(gettext("%s Initiator identity, "), prefix);
   1751 		break;
   1752 	case IS_RESPONDER:
   1753 		(void) printf(gettext("%s Responder identity, "), prefix);
   1754 		break;
   1755 	case DONT_PRINT_INIT:
   1756 		(void) printf(gettext("%s Identity, "), prefix);
   1757 		break;
   1758 	default:
   1759 		(void) printf(gettext("<invalid identity>\n"));
   1760 		return;
   1761 	}
   1762 	(void) printf(gettext("uid=%d, type "), idp->sadb_ident_id);
   1763 	canprint = dump_sadb_idtype(idp->sadb_ident_type, stdout, NULL);
   1764 	if (canprint) {
   1765 		(void) printf("\n%s %s\n", prefix, (char *)(idp + 1));
   1766 	} else {
   1767 		(void) printf(gettext("\n%s "), prefix);
   1768 		print_asn1_name(stdout,
   1769 		    (const unsigned char *)(idp + 1),
   1770 		    SADB_64TO8(idp->sadb_ident_len) - sizeof (sadb_ident_t));
   1771 	}
   1772 }
   1773 
   1774 static void
   1775 print_idspec(char *prefix, char *idp, int icnt, int ecnt)
   1776 {
   1777 	int	i;
   1778 
   1779 	(void) printf(gettext("%s Identity descriptors:\n"), prefix);
   1780 
   1781 	for (i = 0; i < icnt; i++) {
   1782 		if (i == 0)
   1783 			(void) printf(gettext("%s Includes:\n"), prefix);
   1784 		(void) printf("%s    %s\n", prefix, idp);
   1785 		idp += strlen(idp) + 1;
   1786 	}
   1787 
   1788 	for (i = 0; i < ecnt; i++) {
   1789 		if (i == 0)
   1790 			(void) printf(gettext("%s Excludes:\n"), prefix);
   1791 		(void) printf("%s    %s\n", prefix, idp);
   1792 		idp += strlen(idp) + 1;
   1793 	}
   1794 }
   1795 
   1796 static void
   1797 print_keys(char *prefix, ike_p1_key_t *keyp, int size)
   1798 {
   1799 	uint32_t	*curp;
   1800 	ike_p1_key_t	*p;
   1801 	int		ssize;
   1802 
   1803 	curp = (uint32_t *)keyp;
   1804 
   1805 	ssize = sizeof (ike_p1_key_t);
   1806 
   1807 	while ((intptr_t)curp - (intptr_t)keyp < size) {
   1808 		size_t p1klen, len;
   1809 
   1810 		p = (ike_p1_key_t *)curp;
   1811 		p1klen = p->p1key_len;
   1812 		len = p1klen - ssize;
   1813 
   1814 		p1klen = roundup(p1klen, sizeof (ike_p1_key_t));
   1815 		if (p1klen < ssize) {
   1816 			(void) printf(gettext("Short key\n"));
   1817 			break;
   1818 		}
   1819 
   1820 		switch (p->p1key_type) {
   1821 		case IKE_KEY_PRESHARED:
   1822 			(void) printf(gettext("%s Pre-shared key (%d bytes): "),
   1823 			    prefix, len);
   1824 			break;
   1825 		case IKE_KEY_SKEYID:
   1826 			(void) printf(gettext("%s SKEYID (%d bytes): "),
   1827 			    prefix, len);
   1828 			break;
   1829 		case IKE_KEY_SKEYID_D:
   1830 			(void) printf(gettext("%s SKEYID_d (%d bytes): "),
   1831 			    prefix, len);
   1832 			break;
   1833 		case IKE_KEY_SKEYID_A:
   1834 			(void) printf(gettext("%s SKEYID_a (%d bytes): "),
   1835 			    prefix, len);
   1836 			break;
   1837 		case IKE_KEY_SKEYID_E:
   1838 			(void) printf(gettext("%s SKEYID_e (%d bytes): "),
   1839 			    prefix, len);
   1840 			break;
   1841 		case IKE_KEY_ENCR:
   1842 			(void) printf(gettext("%s Encryption key (%d bytes): "),
   1843 			    prefix, len);
   1844 			break;
   1845 		case IKE_KEY_IV:
   1846 			(void) printf(
   1847 			    gettext("%s Initialization vector (%d bytes): "),
   1848 			    prefix, len);
   1849 			break;
   1850 		default:
   1851 			(void) printf(gettext("%s Unidentified key info %p %d"),
   1852 			    prefix, p, p1klen);
   1853 			goto badkey;
   1854 		}
   1855 		(void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 0,
   1856 		    stdout, B_FALSE);
   1857 badkey:
   1858 		(void) printf("\n");
   1859 		assert(IS_P2ALIGNED(p1klen, 8));
   1860 		curp += (p1klen >> 2);
   1861 	}
   1862 }
   1863 
   1864 static void
   1865 print_p1(ike_p1_sa_t *p1)
   1866 {
   1867 	ike_p1_stats_t	*sp;
   1868 	ike_p1_errors_t	*ep;
   1869 	ike_p1_key_t	*kp;
   1870 	sadb_ident_t	*lidp, *ridp;
   1871 	int		lstat, rstat;
   1872 
   1873 	(void) printf("\n");
   1874 	print_hdr("IKESA:", &p1->p1sa_hdr);
   1875 	print_xform("XFORM:", &p1->p1sa_xform, B_FALSE);
   1876 
   1877 	if (p1->p1sa_hdr.p1hdr_isinit) {
   1878 		lstat = IS_INITIATOR;
   1879 		rstat = IS_RESPONDER;
   1880 	} else {
   1881 		lstat = IS_RESPONDER;
   1882 		rstat = IS_INITIATOR;
   1883 	}
   1884 	print_addr("LOCIP:", &p1->p1sa_ipaddrs.loc_addr, lstat);
   1885 	print_addr("REMIP:", &p1->p1sa_ipaddrs.rem_addr, rstat);
   1886 
   1887 	/*
   1888 	 * the stat len might be 0; but still make the call
   1889 	 * to print_lifetime() to pick up the xform info
   1890 	 */
   1891 	sp = (ike_p1_stats_t *)((int)(p1) + p1->p1sa_stat_off);
   1892 	print_lifetime("LIFTM:", &p1->p1sa_xform, sp, p1->p1sa_stat_len);
   1893 
   1894 	if (p1->p1sa_stat_len > 0) {
   1895 		print_p1stats("STATS:", sp, p1->p1sa_stat_len, B_FALSE);
   1896 	}
   1897 
   1898 	if (p1->p1sa_error_len > 0) {
   1899 		ep = (ike_p1_errors_t *)((int)(p1) + p1->p1sa_error_off);
   1900 		print_errs("ERRS: ", ep, p1->p1sa_error_len);
   1901 	}
   1902 
   1903 	if (p1->p1sa_localid_len > 0) {
   1904 		lidp = (sadb_ident_t *)((int)(p1) + p1->p1sa_localid_off);
   1905 		print_id("LOCID:", lidp, lstat);
   1906 	}
   1907 
   1908 	if (p1->p1sa_remoteid_len > 0) {
   1909 		ridp = (sadb_ident_t *)((int)(p1) + p1->p1sa_remoteid_off);
   1910 		print_id("REMID:", ridp, rstat);
   1911 	}
   1912 
   1913 	if (p1->p1sa_key_len > 0) {
   1914 		kp = (ike_p1_key_t *)((int)(p1) + p1->p1sa_key_off);
   1915 		print_keys("KEY:  ", kp, p1->p1sa_key_len);
   1916 	}
   1917 }
   1918 
   1919 static void
   1920 print_certcache(ike_certcache_t *c)
   1921 {
   1922 	(void) printf("\n");
   1923 
   1924 	(void) printf(gettext("CERTIFICATE CACHE ID: %d\n"), c->cache_id);
   1925 	(void) printf(gettext("\tSubject Name: <%s>\n"),
   1926 	    (c->subject != NULL) ? c->subject : gettext("Name unavailable"));
   1927 	(void) printf(gettext("\t Issuer Name: <%s>\n"),
   1928 	    (c->issuer != NULL) ? c->issuer : gettext("Name unavailable"));
   1929 	if ((int)c->certclass == -1)
   1930 		(void) printf(gettext("\t\t[trusted certificate]\n"));
   1931 	switch (c->linkage) {
   1932 	case CERT_OFF_WIRE:
   1933 		(void) printf(gettext("\t\t[Public certificate only]\n"));
   1934 		(void) printf(gettext(
   1935 		    "\t\t[Obtained via certificate payload]\n"));
   1936 		break;
   1937 	case CERT_NO_PRIVKEY:
   1938 		(void) printf(gettext("\t\t[Public certificate only]\n"));
   1939 		break;
   1940 	case CERT_PRIVKEY_LOCKED:
   1941 		(void) printf(gettext(
   1942 		    "\t\t[Private key linked but locked]\n"));
   1943 		break;
   1944 	case CERT_PRIVKEY_AVAIL:
   1945 		(void) printf(gettext("\t\t[Private key available]\n"));
   1946 		break;
   1947 	}
   1948 }
   1949 
   1950 static void
   1951 print_ps(ike_ps_t *ps)
   1952 {
   1953 	sadb_ident_t	*lidp, *ridp;
   1954 	uint8_t		*keyp;
   1955 
   1956 	(void) printf("\n");
   1957 
   1958 	(void) printf(gettext("PSKEY: For %s exchanges\n"),
   1959 	    xchgstr(ps->ps_ike_mode));
   1960 
   1961 	if (ps->ps_key_len > 0) {
   1962 		keyp = (uint8_t *)((int)(ps) + ps->ps_key_off);
   1963 		(void) printf(gettext("PSKEY: Pre-shared key (%d bytes): "),
   1964 		    ps->ps_key_len);
   1965 		(void) dump_key(keyp, ps->ps_key_bits, 0, stdout, B_FALSE);
   1966 		(void) printf("\n");
   1967 	}
   1968 
   1969 	/*
   1970 	 * We get *either* and address or an ident, never both.  So if
   1971 	 * the ident is there, don't try printing an address.
   1972 	 */
   1973 	if (ps->ps_localid_len > 0) {
   1974 		lidp = (sadb_ident_t *)
   1975 		    ((int)(ps) + ps->ps_localid_off);
   1976 		print_id("LOCID:", lidp, DONT_PRINT_INIT);
   1977 	} else {
   1978 		print_addr("LOCIP:", &ps->ps_ipaddrs.loc_addr, DONT_PRINT_INIT);
   1979 	}
   1980 
   1981 	if (ps->ps_remoteid_len > 0) {
   1982 		ridp = (sadb_ident_t *)
   1983 		    ((int)(ps) + ps->ps_remoteid_off);
   1984 		print_id("REMID:", ridp, DONT_PRINT_INIT);
   1985 	} else {
   1986 		print_addr("REMIP:", &ps->ps_ipaddrs.rem_addr, DONT_PRINT_INIT);
   1987 	}
   1988 }
   1989 
   1990 #define	PREFIXLEN	16
   1991 
   1992 static void
   1993 print_rule(ike_rule_t *rp)
   1994 {
   1995 	char		prefix[PREFIXLEN];
   1996 	int		i;
   1997 	ike_p1_xform_t	*xfp;
   1998 	ike_addr_pr_t	*lipp, *ripp;
   1999 	char		*lidp, *ridp;
   2000 	char byte_str[BYTE_STR_SIZE]; /* kbyte string representation */
   2001 	char secs_str[SECS_STR_SIZE]; /* seconds string representation */
   2002 
   2003 	(void) printf("\n");
   2004 	(void) printf(gettext("GLOBL: Label '%s', key manager cookie %u\n"),
   2005 	    rp->rule_label, rp->rule_kmcookie);
   2006 	(void) printf(gettext("GLOBL: local_idtype="));
   2007 	(void) dump_sadb_idtype(rp->rule_local_idtype, stdout, NULL);
   2008 	(void) printf(gettext(", ike_mode=%s\n"), xchgstr(rp->rule_ike_mode));
   2009 	(void) printf(gettext(
   2010 	    "GLOBL: p1_nonce_len=%u, p2_nonce_len=%u, p2_pfs=%s (group %u)\n"),
   2011 	    rp->rule_p1_nonce_len, rp->rule_p2_nonce_len,
   2012 	    (rp->rule_p2_pfs) ? gettext("true") : gettext("false"),
   2013 	    rp->rule_p2_pfs);
   2014 	(void) printf(
   2015 	    gettext("GLOBL: p2_lifetime=%u seconds%s\n"),
   2016 	    rp->rule_p2_lifetime_secs, secs2out(rp->rule_p2_lifetime_secs,
   2017 	    secs_str, sizeof (secs_str), SPC_BEGIN));
   2018 	(void) printf(
   2019 	    gettext("GLOBL: p2_softlife=%u seconds%s\n"),
   2020 	    rp->rule_p2_softlife_secs, secs2out(rp->rule_p2_softlife_secs,
   2021 	    secs_str, sizeof (secs_str), SPC_BEGIN));
   2022 	(void) printf(
   2023 	    gettext("GLOBL: p2_idletime=%u seconds%s\n"),
   2024 	    rp->rule_p2_idletime_secs, secs2out(rp->rule_p2_idletime_secs,
   2025 	    secs_str, sizeof (secs_str), SPC_BEGIN));
   2026 	/*
   2027 	 * Perform explicit conversion before passing to bytecnt2out()
   2028 	 * to avoid integer overflow.
   2029 	 */
   2030 	(void) printf(
   2031 	    gettext("GLOBL: p2_lifetime_kb=%u kilobytes%s\n"),
   2032 	    rp->rule_p2_lifetime_kb,
   2033 	    bytecnt2out((uint64_t)(rp->rule_p2_lifetime_kb) << 10,
   2034 	    byte_str, sizeof (byte_str), SPC_BEGIN));
   2035 	(void) printf(
   2036 	    gettext("GLOBL: p2_softlife_kb=%u kilobytes%s\n"),
   2037 	    rp->rule_p2_softlife_kb,
   2038 	    bytecnt2out(((uint64_t)(rp->rule_p2_softlife_kb)) << 10,
   2039 	    byte_str, sizeof (byte_str), SPC_BEGIN));
   2040 
   2041 	if (rp->rule_locip_cnt > 0) {
   2042 		(void) printf(gettext("LOCIP: IP address range(s):\n"));
   2043 		lipp = (ike_addr_pr_t *)((int)rp + rp->rule_locip_off);
   2044 		for (i = 0; i < rp->rule_locip_cnt; i++, lipp++) {
   2045 			print_addr_range("LOCIP:", lipp);
   2046 		}
   2047 	}
   2048 
   2049 	if (rp->rule_remip_cnt > 0) {
   2050 		(void) printf(gettext("REMIP: IP address range(s):\n"));
   2051 		ripp = (ike_addr_pr_t *)((int)rp + rp->rule_remip_off);
   2052 		for (i = 0; i < rp->rule_remip_cnt; i++, ripp++) {
   2053 			print_addr_range("REMIP:", ripp);
   2054 		}
   2055 	}
   2056 
   2057 	if (rp->rule_locid_inclcnt + rp->rule_locid_exclcnt > 0) {
   2058 		lidp = (char *)((int)rp + rp->rule_locid_off);
   2059 		print_idspec("LOCID:", lidp, rp->rule_locid_inclcnt,
   2060 		    rp->rule_locid_exclcnt);
   2061 	}
   2062 
   2063 	if (rp->rule_remid_inclcnt + rp->rule_remid_exclcnt > 0) {
   2064 		ridp = (char *)((int)rp + rp->rule_remid_off);
   2065 		print_idspec("REMID:", ridp, rp->rule_remid_inclcnt,
   2066 		    rp->rule_remid_exclcnt);
   2067 	}
   2068 
   2069 	if (rp->rule_xform_cnt > 0) {
   2070 		(void) printf(gettext("XFRMS: Available Transforms:\n"));
   2071 		xfp = (ike_p1_xform_t *)((int)rp +  rp->rule_xform_off);
   2072 		for (i = 0; i < rp->rule_xform_cnt; i++, xfp++) {
   2073 			(void) snprintf(prefix, PREFIXLEN, "XF %2u:", i);
   2074 			print_xform(prefix, xfp, B_TRUE);
   2075 		}
   2076 	}
   2077 }
   2078 
   2079 #undef	PREFIXLEN
   2080 
   2081 #define	PRSACNTS(init, resp) \
   2082 		(void) printf(gettext("initiator: %10u   responder: %10u\n"), \
   2083 		    (init), (resp))
   2084 
   2085 static void
   2086 print_stats(ike_stats_t *sp, int len)
   2087 {
   2088 	/*
   2089 	 * before printing each line, make sure the structure we were
   2090 	 * given is big enough to include the fields needed.
   2091 	 */
   2092 	if (len < COUNTER_PAIR)
   2093 		return;
   2094 	(void) printf(gettext("Phase 1 SA counts:\n"));
   2095 	(void) printf(gettext("Current:   "));
   2096 	PRSACNTS(sp->st_init_p1_current, sp->st_resp_p1_current);
   2097 	len -= COUNTER_PAIR;
   2098 
   2099 	if (len < COUNTER_PAIR)
   2100 		return;
   2101 	(void) printf(gettext("Total:     "));
   2102 	PRSACNTS(sp->st_init_p1_total, sp->st_resp_p1_total);
   2103 	len -= COUNTER_PAIR;
   2104 
   2105 	if (len < COUNTER_PAIR)
   2106 		return;
   2107 	(void) printf(gettext("Attempted: "));
   2108 	PRSACNTS(sp->st_init_p1_attempts, sp->st_resp_p1_attempts);
   2109 	len -= COUNTER_PAIR;
   2110 
   2111 	if (len < (COUNTER_PAIR + COUNTER_32BIT))
   2112 		return;
   2113 	(void) printf(gettext("Failed:    "));
   2114 	PRSACNTS(sp->st_init_p1_noresp + sp->st_init_p1_respfail,
   2115 	    sp->st_resp_p1_fail);
   2116 	(void) printf(
   2117 	    gettext("           initiator fails include %u time-out(s)\n"),
   2118 	    sp->st_init_p1_noresp);
   2119 
   2120 	if (len < PATH_MAX)
   2121 		return;
   2122 	if (*(sp->st_pkcs11_libname) != '\0')
   2123 		(void) printf(gettext("PKCS#11 library linked in from %s\n"),
   2124 		    sp->st_pkcs11_libname);
   2125 }
   2126 
   2127 /* Print one line of 'get defaults' output (i.e. single value). */
   2128 static void
   2129 print_defaults(char *label, char *description, char *unit,
   2130     uint_t current, uint_t def)
   2131 {
   2132 	(void) printf("%-18s%-10s%11u %-10s%-26s\n", label,
   2133 	    (current != def) ? gettext("config") : gettext("default"),
   2134 	    current, unit, description);
   2135 }
   2136 
   2137 /*
   2138  * Print out defaults used by in.iked, the argument is a buffer containing
   2139  * two ike_defaults_t's, the first contains the hard coded defaults, the second
   2140  * contains the actual values used. If these differ, then the defaults have been
   2141  * changed via a config file entry. Note that "-" indicates this default
   2142  * is not tunable via ike.config(4) or is system wide tunable.
   2143  */
   2144 static void
   2145 do_print_defaults(ike_defaults_t *dp)
   2146 {
   2147 	ike_defaults_t *ddp;
   2148 	ddp = (ike_defaults_t *)(dp + 1);
   2149 
   2150 	(void) printf(gettext("\nGlobal defaults. Some values can be"
   2151 	    " over-ridden on a per rule basis.\n"));
   2152 	(void) printf(gettext("\nSystem defaults are time delayed.\n\n"));
   2153 
   2154 	(void) printf("%-18s%-10s%-12s%-10s%-26s\n\n",
   2155 	    gettext("Token:"), gettext("Source:"), gettext("Value:"),
   2156 	    gettext("Unit:"), gettext("Description:"));
   2157 
   2158 	/* iked tunables */
   2159 	print_defaults("p1_lifetime_secs", gettext("phase 1 lifetime"),
   2160 	    gettext("seconds"), ddp->rule_p1_lifetime_secs,
   2161 	    dp->rule_p1_lifetime_secs);
   2162 
   2163 	print_defaults("-", gettext("minimum phase 1 lifetime"),
   2164 	    gettext("seconds"), ddp->rule_p1_minlife,
   2165 	    dp->rule_p1_minlife);
   2166 
   2167 	print_defaults("p1_nonce_len", gettext("phase 1 nonce length"),
   2168 	    gettext("bytes"), ddp->rule_p1_nonce_len,
   2169 	    dp->rule_p1_nonce_len);
   2170 
   2171 	print_defaults("p2_lifetime_secs", gettext("phase 2 lifetime"),
   2172 	    gettext("seconds"), ddp->rule_p2_lifetime_secs,
   2173 	    dp->rule_p2_lifetime_secs);
   2174 
   2175 	print_defaults("p2_softlife_secs", gettext("phase 2 soft lifetime"),
   2176 	    gettext("seconds"), ddp->rule_p2_softlife_secs,
   2177 	    dp->rule_p2_softlife_secs);
   2178 
   2179 	print_defaults("p2_idletime_secs", gettext("phase 2 idle time"),
   2180 	    gettext("seconds"), ddp->rule_p2_idletime_secs,
   2181 	    dp->rule_p2_idletime_secs);
   2182 
   2183 	print_defaults("p2_lifetime_kb", gettext("phase 2 lifetime"),
   2184 	    gettext("kilobytes"), ddp->rule_p2_lifetime_kb,
   2185 	    dp->rule_p2_lifetime_kb);
   2186 
   2187 	print_defaults("p2_softlife_kb", gettext("phase 2 soft lifetime"),
   2188 	    gettext("kilobytes"), ddp->rule_p2_softlife_kb,
   2189 	    dp->rule_p2_softlife_kb);
   2190 
   2191 	/* system wide tunables */
   2192 	print_defaults("-", gettext("system phase 2 lifetime"),
   2193 	    gettext("seconds"), ddp->sys_p2_lifetime_secs,
   2194 	    dp->sys_p2_lifetime_secs);
   2195 
   2196 	print_defaults("-", gettext("system phase 2 soft lifetime"),
   2197 	    gettext("seconds"), ddp->sys_p2_softlife_secs,
   2198 	    dp->sys_p2_softlife_secs);
   2199 
   2200 	print_defaults("-", gettext("system phase 2 idle time"),
   2201 	    gettext("seconds"), ddp->sys_p2_idletime_secs,
   2202 	    dp->sys_p2_idletime_secs);
   2203 
   2204 	print_defaults("-", gettext("system phase 2 lifetime"),
   2205 	    gettext("bytes"), ddp->sys_p2_lifetime_bytes,
   2206 	    dp->sys_p2_lifetime_bytes);
   2207 
   2208 	print_defaults("-", gettext("system phase 2 soft lifetime"),
   2209 	    gettext("bytes"), ddp->sys_p2_softlife_bytes,
   2210 	    dp->sys_p2_softlife_bytes);
   2211 
   2212 	/* minimum and maximum values */
   2213 	print_defaults("-", gettext("minimum phase 2 hard lifetime"),
   2214 	    gettext("seconds"), ddp->rule_p2_minlife_hard_secs,
   2215 	    dp->rule_p2_minlife_hard_secs);
   2216 
   2217 	print_defaults("-", gettext("minimum phase 2 soft lifetime"),
   2218 	    gettext("seconds"), ddp->rule_p2_minlife_soft_secs,
   2219 	    dp->rule_p2_minlife_soft_secs);
   2220 
   2221 	print_defaults("-", gettext("minimum phase 2 idle lifetime"),
   2222 	    gettext("seconds"), ddp->rule_p2_minlife_idle_secs,
   2223 	    dp->rule_p2_minlife_idle_secs);
   2224 
   2225 	print_defaults("-", gettext("minimum phase 2 hard lifetime"),
   2226 	    gettext("kilobytes"), ddp->rule_p2_minlife_hard_kb,
   2227 	    dp->rule_p2_minlife_hard_kb);
   2228 
   2229 	print_defaults("-", gettext("minimum phase 2 soft lifetime"),
   2230 	    gettext("kilobytes"), ddp->rule_p2_minlife_soft_kb,
   2231 	    dp->rule_p2_minlife_soft_kb);
   2232 
   2233 	print_defaults("-", gettext("minimum phase 2 delta"),
   2234 	    gettext("seconds"), ddp->rule_p2_mindiff_secs,
   2235 	    dp->rule_p2_mindiff_secs);
   2236 
   2237 	print_defaults("-", gettext("minimum phase 2 delta"),
   2238 	    gettext("kilobytes"), ddp->rule_p2_mindiff_kb,
   2239 	    dp->rule_p2_mindiff_kb);
   2240 
   2241 	print_defaults("-", gettext("maximum phase 2 lifetime"),
   2242 	    gettext("seconds"), ddp->rule_p2_maxlife_secs,
   2243 	    dp->rule_p2_maxlife_secs);
   2244 
   2245 	print_defaults("-", gettext("conversion factor"),
   2246 	    gettext("kbytes/s"), ddp->conversion_factor,
   2247 	    dp->conversion_factor);
   2248 
   2249 	print_defaults("-", gettext("maximum phase 2 lifetime"),
   2250 	    gettext("kilobytes"), ddp->rule_p2_maxlife_kb,
   2251 	    dp->rule_p2_maxlife_kb);
   2252 
   2253 	/* other values */
   2254 	print_defaults("p2_nonce_len", gettext("phase 2 nonce length"),
   2255 	    gettext("bytes"), ddp->rule_p2_nonce_len,
   2256 	    dp->rule_p2_nonce_len);
   2257 
   2258 	print_defaults("p2_pfs", gettext("phase 2 PFS"),
   2259 	    " ", ddp->rule_p2_pfs, dp->rule_p2_pfs);
   2260 
   2261 	print_defaults("max_certs", gettext("max certificates"),
   2262 	    " ", ddp->rule_max_certs, dp->rule_max_certs);
   2263 
   2264 	print_defaults("-", gettext("IKE port number"),
   2265 	    " ", ddp->rule_ike_port, dp->rule_ike_port);
   2266 
   2267 	print_defaults("-", gettext("NAT-T port number"),
   2268 	    " ", ddp->rule_natt_port, dp->rule_natt_port);
   2269 }
   2270 
   2271 static void
   2272 print_categories(int level)
   2273 {
   2274 	int	mask;
   2275 
   2276 	if (level == 0) {
   2277 		(void) printf(gettext("No debug categories enabled.\n"));
   2278 		return;
   2279 	}
   2280 
   2281 	(void) printf(gettext("Debug categories enabled:"));
   2282 	for (mask = 1; mask <= D_HIGHBIT; mask <<= 1) {
   2283 		if (level & mask)
   2284 			(void) printf("\n\t%s", dbgstr(mask));
   2285 	}
   2286 	(void) printf("\n");
   2287 }
   2288 
   2289 /*PRINTFLIKE2*/
   2290 static void
   2291 ikeadm_err_exit(ike_err_t *err, char *fmt, ...)
   2292 {
   2293 	va_list	ap;
   2294 	char	bailbuf[BUFSIZ];
   2295 
   2296 	va_start(ap, fmt);
   2297 	(void) vsnprintf(bailbuf, BUFSIZ, fmt, ap);
   2298 	va_end(ap);
   2299 	if ((err != NULL) && (err->ike_err == IKE_ERR_SYS_ERR)) {
   2300 		bail_msg("%s: %s", bailbuf, (err->ike_err_unix == 0) ?
   2301 		    gettext("<unknown error>") : strerror(err->ike_err_unix));
   2302 	} else {
   2303 		bail_msg("%s: %s", bailbuf, (err == NULL) ?
   2304 		    gettext("<unknown error>") : errstr(err->ike_err));
   2305 	}
   2306 }
   2307 
   2308 /*PRINTFLIKE2*/
   2309 static void
   2310 ikeadm_err_msg(ike_err_t *err, char *fmt, ...)
   2311 {
   2312 	va_list	ap;
   2313 	char	mbuf[BUFSIZ];
   2314 
   2315 	va_start(ap, fmt);
   2316 	(void) vsnprintf(mbuf, BUFSIZ, fmt, ap);
   2317 	va_end(ap);
   2318 	if ((err != NULL) && (err->ike_err == IKE_ERR_SYS_ERR)) {
   2319 		message("%s: %s", mbuf, (err->ike_err_unix == 0) ?
   2320 		    gettext("<unknown error>") :
   2321 		    ((err->ike_err_unix == EEXIST) ?
   2322 		    gettext("Duplicate entry") :
   2323 		    strerror(err->ike_err_unix)));
   2324 	} else {
   2325 		message("%s: %s", mbuf, (err == NULL) ?
   2326 		    gettext("<unknown error>") : errstr(err->ike_err));
   2327 	}
   2328 }
   2329 
   2330 
   2331 /*
   2332  * Command functions
   2333  */
   2334 
   2335 /*
   2336  * Exploit the fact that ike_dbg_t and ike_priv_t have identical
   2337  * formats in the following two functions.
   2338  */
   2339 static void
   2340 do_getvar(int cmd)
   2341 {
   2342 	ike_service_t	req, *rtn;
   2343 	ike_dbg_t	*dreq;
   2344 	char		*varname;
   2345 
   2346 	switch (cmd) {
   2347 	case IKE_SVC_GET_DBG:
   2348 		varname = gettext("debug");
   2349 		break;
   2350 	case IKE_SVC_GET_PRIV:
   2351 		varname = gettext("privilege");
   2352 		break;
   2353 	default:
   2354 		bail_msg(gettext("unrecognized get command (%d)"), cmd);
   2355 	}
   2356 
   2357 	dreq = &req.svc_dbg;
   2358 	dreq->cmd = cmd;
   2359 	dreq->dbg_level = 0;
   2360 
   2361 	rtn = ikedoor_call((char *)&req, sizeof (ike_dbg_t), NULL, 0);
   2362 
   2363 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
   2364 		ikeadm_err_exit(&rtn->svc_err,
   2365 		    gettext("error getting %s level"), varname);
   2366 	}
   2367 	dreq = &rtn->svc_dbg;
   2368 	(void) printf(gettext("Current %s level is 0x%x"),
   2369 	    varname, dreq->dbg_level);
   2370 
   2371 	if (cmd == IKE_SVC_GET_DBG) {
   2372 		(void) printf("\n");
   2373 		print_categories(dreq->dbg_level);
   2374 	} else {
   2375 		(void) printf(gettext(", %s enabled\n"),
   2376 		    privstr(dreq->dbg_level));
   2377 	}
   2378 }
   2379 
   2380 /*
   2381  * Log into a token and unlock all objects
   2382  * referenced by PKCS#11 hint files.
   2383  */
   2384 static void
   2385 do_setdel_pin(int cmd, int argc, char **argv)
   2386 {
   2387 	ike_service_t	req, *rtn;
   2388 	ike_pin_t	*preq;
   2389 	char		token_label[PKCS11_TOKSIZE];
   2390 	char		*token_pin;
   2391 	char		prompt[80];
   2392 
   2393 	if (argc < 1)
   2394 		Bail(gettext("Must specify PKCS#11 token object."));
   2395 
   2396 	preq = &req.svc_pin;
   2397 	preq->cmd = cmd;
   2398 
   2399 	switch (cmd) {
   2400 	case IKE_SVC_SET_PIN:
   2401 		if (parse_token(argc, argv, token_label) != 0)
   2402 			Bail("Invalid syntax for \"token login\"");
   2403 		(void) snprintf(prompt, sizeof (prompt),
   2404 		    "Enter PIN for PKCS#11 token \'%s\': ", token_label);
   2405 		token_pin =
   2406 		    getpassphrase(prompt);
   2407 		(void) strlcpy((char *)preq->token_pin, token_pin, MAX_PIN_LEN);
   2408 		bzero(token_pin, strlen(token_pin));
   2409 		break;
   2410 	case IKE_SVC_DEL_PIN:
   2411 		if (parse_token(argc, argv, token_label) != 0)
   2412 			Bail("Invalid syntax for \"token logout\"");
   2413 		break;
   2414 	default:
   2415 		bail_msg(gettext("unrecognized token command (%d)"), cmd);
   2416 	}
   2417 
   2418 	(void) strlcpy(preq->pkcs11_token, token_label, PKCS11_TOKSIZE);
   2419 
   2420 	rtn = ikedoor_call((char *)&req, sizeof (ike_pin_t), NULL, 0);
   2421 	if (cmd == IKE_SVC_SET_PIN)
   2422 		bzero(preq->token_pin, sizeof (preq->token_pin));
   2423 
   2424 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
   2425 		ikeadm_err_exit(&rtn->svc_err,
   2426 		    gettext("PKCS#11 operation"));
   2427 	}
   2428 	preq = &rtn->svc_pin;
   2429 	message(gettext("PKCS#11 operation successful"));
   2430 }
   2431 
   2432 static void
   2433 do_setvar(int cmd, int argc, char **argv)
   2434 {
   2435 	ike_service_t	req, *rtn;
   2436 	ike_dbg_t	*dreq;
   2437 	door_desc_t	*descp = NULL, desc;
   2438 	int		fd, ndesc = 0;
   2439 	uint32_t	reqlevel;
   2440 	char		*varname;
   2441 
   2442 	if (argc < 1)
   2443 		Bail("unspecified level");
   2444 	reqlevel = strtoul(argv[0], NULL, 0);
   2445 
   2446 	switch (cmd) {
   2447 	case IKE_SVC_SET_DBG:
   2448 		if (argc > 2)
   2449 			Bail("Too many arguments to \"set debug\"");
   2450 		varname = gettext("debug");
   2451 		if (reqlevel == 0) {
   2452 			/* check for a string... */
   2453 			reqlevel = parsedbgopts(argv[0]);
   2454 		}
   2455 		if (reqlevel == D_INVALID)
   2456 			bail_msg(gettext("Bad debug flag: %s"), argv[0]);
   2457 		break;
   2458 	case IKE_SVC_SET_PRIV:
   2459 		if (argc > 1)
   2460 			Bail("Too many arguments to \"set priv\"");
   2461 
   2462 		varname = gettext("privilege");
   2463 		if (reqlevel == 0) {
   2464 			/* check for a string... */
   2465 			reqlevel = privstr2num(argv[0]);
   2466 		}
   2467 		if (reqlevel > IKE_PRIV_MAXIMUM)
   2468 			bail_msg(gettext("Bad privilege flag: %s"), argv[0]);
   2469 		break;
   2470 	default:
   2471 		bail_msg(gettext("unrecognized set command (%d)"), cmd);
   2472 	}
   2473 
   2474 	dreq = &req.svc_dbg;
   2475 	dreq->cmd = cmd;
   2476 	dreq->dbg_level = reqlevel;
   2477 
   2478 	if ((argc == 2) && (cmd == IKE_SVC_SET_DBG)) {
   2479 		fd = open(argv[1], O_RDWR | O_CREAT | O_APPEND,
   2480 		    S_IRUSR | S_IWUSR);
   2481 		if (fd < 0)
   2482 			Bail("open debug file");
   2483 		desc.d_data.d_desc.d_descriptor = fd;
   2484 		desc.d_attributes = DOOR_DESCRIPTOR;
   2485 		descp = &desc;
   2486 		ndesc = 1;
   2487 	}
   2488 
   2489 	rtn = ikedoor_call((char *)&req, sizeof (ike_dbg_t), descp, ndesc);
   2490 
   2491 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
   2492 		ikeadm_err_exit(&rtn->svc_err,
   2493 		    gettext("error setting %s level"), varname);
   2494 	}
   2495 	dreq = &rtn->svc_dbg;
   2496 	(void) printf(
   2497 	    gettext("Successfully changed %s level from 0x%x to 0x%x\n"),
   2498 	    varname, dreq->dbg_level, reqlevel);
   2499 
   2500 	if (cmd == IKE_SVC_SET_DBG) {
   2501 		print_categories(reqlevel);
   2502 	} else {
   2503 		(void) printf(gettext("New privilege level 0x%x enables %s\n"),
   2504 		    reqlevel, privstr(reqlevel));
   2505 	}
   2506 }
   2507 
   2508 static void
   2509 do_getstats(int cmd)
   2510 {
   2511 	ike_service_t	*rtn;
   2512 	ike_statreq_t	sreq, *sreqp;
   2513 	ike_stats_t	*sp;
   2514 
   2515 	sreq.cmd = cmd;
   2516 
   2517 	rtn = ikedoor_call((char *)&sreq, sizeof (ike_statreq_t), NULL, 0);
   2518 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
   2519 		ikeadm_err_exit(&rtn->svc_err, gettext("error getting stats"));
   2520 	}
   2521 
   2522 	sreqp = &rtn->svc_stats;
   2523 	sp = (ike_stats_t *)(sreqp + 1);
   2524 	print_stats(sp, sreqp->stat_len);
   2525 }
   2526 
   2527 static void
   2528 do_getdefs(int cmd)
   2529 {
   2530 	ike_service_t	*rtn;
   2531 	ike_defreq_t	dreq, *dreqp;
   2532 	ike_defaults_t	*dp;
   2533 
   2534 	dreq.cmd = cmd;
   2535 
   2536 	rtn = ikedoor_call((char *)&dreq, sizeof (ike_defreq_t), NULL, 0);
   2537 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
   2538 		ikeadm_err_exit(&rtn->svc_err,
   2539 		    gettext("error getting defaults"));
   2540 	}
   2541 
   2542 	dreqp = &rtn->svc_defaults;
   2543 	dp = (ike_defaults_t *)(dreqp + 1);
   2544 
   2545 	/*
   2546 	 * Before printing each line, make sure the structure we were
   2547 	 * given is big enough to include the fields needed.
   2548 	 * Silently bail out of there is a version mismatch.
   2549 	 */
   2550 	if (dreqp->stat_len < ((2 * sizeof (ike_defaults_t))
   2551 	    + sizeof (ike_defreq_t)) || dreqp->version != DOORVER) {
   2552 		return;
   2553 	}
   2554 	do_print_defaults(dp);
   2555 }
   2556 
   2557 static void
   2558 do_dump(int cmd)
   2559 {
   2560 	char		*name;
   2561 	ike_service_t	req, *rtn;
   2562 	ike_dump_t	*dreq, *dump;
   2563 
   2564 	switch (cmd) {
   2565 	case IKE_SVC_DUMP_P1S:
   2566 		name = gettext("phase 1 SA info");
   2567 		break;
   2568 	case IKE_SVC_DUMP_RULES:
   2569 		name = gettext("policy rules");
   2570 		break;
   2571 	case IKE_SVC_DUMP_PS:
   2572 		name = gettext("preshared keys");
   2573 		break;
   2574 	case IKE_SVC_DUMP_CERTCACHE:
   2575 		name = gettext("certcache");
   2576 		break;
   2577 	default:
   2578 		bail_msg(gettext("unrecognized dump command (%d)"), cmd);
   2579 	}
   2580 
   2581 	dreq = &req.svc_dump;
   2582 	dreq->cmd = cmd;
   2583 	dreq->dump_len = 0;
   2584 	dreq->dump_next = 0;
   2585 	do {
   2586 		rtn = ikedoor_call((char *)&req, sizeof (ike_dump_t),
   2587 		    NULL, 0);
   2588 		if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
   2589 			if (rtn && (rtn->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
   2590 				/* no entries to print */
   2591 				break;
   2592 			}
   2593 			ikeadm_err_exit(&rtn->svc_err,
   2594 			    gettext("error getting %s"), name);
   2595 		}
   2596 		dump = &rtn->svc_dump;
   2597 
   2598 		switch (cmd) {
   2599 		case IKE_SVC_DUMP_P1S:
   2600 			print_p1((ike_p1_sa_t *)(dump + 1));
   2601 			break;
   2602 		case IKE_SVC_DUMP_RULES:
   2603 			print_rule((ike_rule_t *)(dump + 1));
   2604 			break;
   2605 		case IKE_SVC_DUMP_PS:
   2606 			print_ps((ike_ps_t *)(dump + 1));
   2607 			break;
   2608 		case IKE_SVC_DUMP_CERTCACHE:
   2609 			print_certcache((ike_certcache_t *)(dump + 1));
   2610 			break;
   2611 		}
   2612 
   2613 		dreq->dump_next = dump->dump_next;
   2614 
   2615 		(void) munmap((char *)rtn, dump->dump_len);
   2616 
   2617 	} while (dreq->dump_next);
   2618 
   2619 	(void) printf(gettext("\nCompleted dump of %s\n"), name);
   2620 }
   2621 
   2622 static void
   2623 do_getdel_doorcall(int cmd, int idlen, int idtype, char *idp, char *name)
   2624 {
   2625 	int		totallen;
   2626 	char		*p;
   2627 	ike_service_t	*reqp, *rtnp;
   2628 	ike_get_t	*getp;
   2629 	boolean_t	getcmd;
   2630 
   2631 	getcmd = ((cmd == IKE_SVC_GET_P1) || (cmd == IKE_SVC_GET_RULE) ||
   2632 	    (cmd == IKE_SVC_GET_PS));
   2633 
   2634 	/*
   2635 	 * WARNING: to avoid being redundant, this code takes advantage
   2636 	 * of the fact that the ike_get_t and ike_del_t structures are
   2637 	 * identical (only the field names differ, their function and
   2638 	 * size are the same).  If for some reason those structures
   2639 	 * change, this code will need to be re-written to accomodate
   2640 	 * that difference.
   2641 	 */
   2642 	totallen = sizeof (ike_get_t) + idlen;
   2643 	if ((reqp = (ike_service_t *)malloc(totallen)) == NULL)
   2644 		Bail("malloc(id)");
   2645 
   2646 	getp = &reqp->svc_get;
   2647 	getp->cmd = cmd;
   2648 	getp->get_len = totallen;
   2649 	getp->get_idtype = idtype;
   2650 	p = (char *)(getp + 1);
   2651 
   2652 	(void) memcpy(p, idp, idlen);
   2653 
   2654 	rtnp = ikedoor_call((char *)reqp, totallen, NULL, 0);
   2655 	if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
   2656 		if (rtnp && (rtnp->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
   2657 			message(gettext("Could not find requested %s."), name);
   2658 		} else {
   2659 			ikeadm_err_msg(&rtnp->svc_err, gettext("error %s %s"),
   2660 			    (getcmd) ? gettext("getting") : gettext("deleting"),
   2661 			    name);
   2662 		}
   2663 		free(reqp);
   2664 		return;
   2665 	}
   2666 	getp = &rtnp->svc_get;
   2667 
   2668 	if (getcmd) {
   2669 		switch (cmd) {
   2670 		case IKE_SVC_GET_P1:
   2671 			print_p1((ike_p1_sa_t *)(getp + 1));
   2672 			break;
   2673 		case IKE_SVC_GET_PS:
   2674 			print_ps((ike_ps_t *)(getp + 1));
   2675 			break;
   2676 		case IKE_SVC_GET_RULE:
   2677 			print_rule((ike_rule_t *)(getp + 1));
   2678 			break;
   2679 		}
   2680 	} else {
   2681 		message(gettext("Successfully deleted selected %s."), name);
   2682 	}
   2683 
   2684 	(void) munmap((char *)rtnp, getp->get_len);
   2685 	free(reqp);
   2686 }
   2687 
   2688 static void
   2689 do_getdel(int cmd, int argc, char **argv)
   2690 {
   2691 	int		idlen, idtype = 0, i, j;
   2692 	int		bytelen1, bytelen2;
   2693 	char		*name, *idp, *p, *p1, *p2;
   2694 	ike_addr_pr_t	apr;
   2695 	ike_cky_pr_t	cpr;
   2696 	sadb_ident_t	*sid1p, *sid2p;
   2697 	struct hostent	*he1p, *he2p;
   2698 	char		label[MAX_LABEL_LEN];
   2699 
   2700 	if ((argc < 1) || (argv[0] == NULL)) {
   2701 		Bail("not enough identification info");
   2702 	}
   2703 
   2704 	switch (cmd) {
   2705 	case IKE_SVC_GET_P1:
   2706 	case IKE_SVC_DEL_P1:
   2707 		name = gettext("phase 1 SA");
   2708 		/*
   2709 		 * The first token must either be an address (or hostname)
   2710 		 * or a cookie.  We require cookies to be entered as hex
   2711 		 * numbers, beginning with 0x; so if our token starts with
   2712 		 * that, it's a cookie.
   2713 		 */
   2714 		if (strncmp(argv[0], "0x", 2) == 0) {
   2715 			if (parse_cky_pr(argc, argv, &cpr) >= 0) {
   2716 				idtype = IKE_ID_CKY_PAIR;
   2717 				idlen = sizeof (ike_cky_pr_t);
   2718 				idp = (char *)&cpr;
   2719 			}
   2720 		} else {
   2721 			if (parse_addr_pr(argc, argv, &he1p, &he2p) >= 0) {
   2722 				idtype = IKE_ID_ADDR_PAIR;
   2723 				idlen = sizeof (ike_addr_pr_t);
   2724 			}
   2725 		}
   2726 		break;
   2727 
   2728 	case IKE_SVC_GET_RULE:
   2729 	case IKE_SVC_DEL_RULE:
   2730 		name = gettext("policy rule");
   2731 		if (parse_label(argc, argv, label) >= 0) {
   2732 			idtype = IKE_ID_LABEL;
   2733 			idlen = MAX_LABEL_LEN;
   2734 			idp = label;
   2735 		}
   2736 		break;
   2737 
   2738 	case IKE_SVC_GET_PS:
   2739 	case IKE_SVC_DEL_PS:
   2740 		name = gettext("preshared key");
   2741 		/*
   2742 		 * The first token must either be an address or an ident
   2743 		 * type.  Check for an ident type to determine which it is.
   2744 		 */
   2745 		if (parse_idtype(argv[0], NULL) >= 0) {
   2746 			if (parse_ident_pr(argc, argv, &sid1p, &sid2p) >= 0) {
   2747 				idtype = IKE_ID_IDENT_PAIR;
   2748 				idlen = SADB_64TO8(sid1p->sadb_ident_len) +
   2749 				    SADB_64TO8(sid2p->sadb_ident_len);
   2750 			}
   2751 		} else {
   2752 			if (parse_addr_pr(argc, argv, &he1p, &he2p) >= 0) {
   2753 				idtype = IKE_ID_ADDR_PAIR;
   2754 				idlen = sizeof (ike_addr_pr_t);
   2755 			}
   2756 		}
   2757 		break;
   2758 
   2759 	default:
   2760 		bail_msg(gettext("unrecognized get/del command (%d)"), cmd);
   2761 	}
   2762 
   2763 	switch (idtype) {
   2764 	case IKE_ID_ADDR_PAIR:
   2765 		/*
   2766 		 * we might have exploding addrs here; do every possible
   2767 		 * combination.
   2768 		 */
   2769 		i = 0;
   2770 		j = 0;
   2771 		while ((p1 = he1p->h_addr_list[i++]) != NULL) {
   2772 			headdr2sa(p1, &apr.loc_addr, he1p->h_length);
   2773 
   2774 			while ((p2 = he2p->h_addr_list[j++]) != NULL) {
   2775 				headdr2sa(p2, &apr.rem_addr, he2p->h_length);
   2776 				do_getdel_doorcall(cmd, idlen, idtype,
   2777 				    (char *)&apr, name);
   2778 			}
   2779 		}
   2780 		FREE_HE(he1p);
   2781 		FREE_HE(he2p);
   2782 		break;
   2783 
   2784 	case IKE_ID_IDENT_PAIR:
   2785 		bytelen1 = SADB_64TO8(sid1p->sadb_ident_len);
   2786 		bytelen2 = SADB_64TO8(sid2p->sadb_ident_len);
   2787 		if (idlen != bytelen1 + bytelen2)
   2788 			Bail("ident syntax error");
   2789 		idp = p = (char *)malloc(idlen);
   2790 		if (p == NULL)
   2791 			Bail("malloc(id)");
   2792 		(void) memcpy(p, (char *)sid1p, bytelen1);
   2793 		p += bytelen1;
   2794 		(void) memcpy(p, (char *)sid2p, bytelen2);
   2795 		do_getdel_doorcall(cmd, idlen, idtype, idp, name);
   2796 		free(idp);
   2797 		free(sid1p);
   2798 		free(sid2p);
   2799 		break;
   2800 
   2801 	case IKE_ID_CKY_PAIR:
   2802 	case IKE_ID_LABEL:
   2803 		do_getdel_doorcall(cmd, idlen, idtype, idp, name);
   2804 		break;
   2805 
   2806 	case 0:
   2807 	default:
   2808 		bail_msg(gettext("invalid %s identification\n"), name);
   2809 	}
   2810 }
   2811 
   2812 /*
   2813  * Copy source into target, inserting an escape character ('\') before
   2814  * any quotes that appear.  Return true on success, false on failure.
   2815  */
   2816 static boolean_t
   2817 escapequotes(char *target, char *source, int tlen)
   2818 {
   2819 	int	s, t, len = strlen(source) + 1;
   2820 
   2821 	if (tlen < len)
   2822 		return (B_FALSE);
   2823 
   2824 	for (s = 0, t = 0; s < len && t < tlen; s++) {
   2825 		if (source[s] == '\"')
   2826 			target[t++] = '\\';
   2827 		target[t++] = source[s];
   2828 	}
   2829 
   2830 	if ((t == tlen) && (s < len))
   2831 		return (B_FALSE);
   2832 
   2833 	return (B_TRUE);
   2834 }
   2835 
   2836 /*
   2837  * Return true if the arg following the given keyword should
   2838  * be in quotes (i.e. is a string), false if not.
   2839  */
   2840 static boolean_t
   2841 quotedfield(char *keywd)
   2842 {
   2843 	if ((strncmp(keywd, "label", strlen("label") + 1) == 0) ||
   2844 	    (strncmp(keywd, "local_id", strlen("local_id") + 1) == 0) ||
   2845 	    (strncmp(keywd, "remote_id", strlen("remote_id") + 1) == 0))
   2846 		return (B_TRUE);
   2847 
   2848 	return (B_FALSE);
   2849 }
   2850 
   2851 static void
   2852 do_new(int cmd, int argc, char **argv)
   2853 {
   2854 	ike_service_t	*rtn;
   2855 	ike_new_t	new, *newp = NULL;
   2856 	door_desc_t	desc, *descp = NULL;
   2857 	int		i, fd, ndesc = 0, buflen;
   2858 	char		*name, tmpfilepath[32];
   2859 	FILE		*tmpfile;
   2860 
   2861 	switch (cmd) {
   2862 	case IKE_SVC_NEW_PS:
   2863 		name = gettext("preshared key");
   2864 		break;
   2865 	case IKE_SVC_NEW_RULE:
   2866 		name = gettext("policy rule");
   2867 		break;
   2868 	default:
   2869 		bail_msg(gettext("unrecognized new command (%d)"), cmd);
   2870 	}
   2871 
   2872 	if (argc == 1) {
   2873 		/* We've been given a file to read from */
   2874 		fd = open(argv[0], O_RDONLY);
   2875 		if (fd < 0)
   2876 			Bail("open source file");
   2877 
   2878 		desc.d_data.d_desc.d_descriptor = fd;
   2879 		desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
   2880 		descp = &desc;
   2881 		ndesc = 1;
   2882 
   2883 		new.cmd = cmd;
   2884 		new.new_len = 0;
   2885 		newp = &new;
   2886 		buflen = sizeof (ike_new_t);
   2887 
   2888 	} else if ((argc > 1) && (cmd == IKE_SVC_NEW_PS)) {
   2889 		/*
   2890 		 * This is an alternative to using the tmpfile method
   2891 		 * for preshared keys.  It means we're duplicating the
   2892 		 * parsing effort that happens in readps.c; but it
   2893 		 * does avoid having the key sitting in a file.
   2894 		 */
   2895 		ike_ps_t	*psp;
   2896 		int		pslen;
   2897 
   2898 		/*
   2899 		 * must be in interactive mode; don't want keys in
   2900 		 * the process args.
   2901 		 */
   2902 		if (!interactive)
   2903 			Bail("Must be in interactive mode to add key info.");
   2904 		if (parse_ps(argc, argv, &psp, &pslen) < 0) {
   2905 			errno = 0;
   2906 			Bail("invalid preshared key definition");
   2907 		}
   2908 		newp = malloc(sizeof (ike_new_t) + pslen);
   2909 		if (newp == NULL)
   2910 			Bail("alloc pskey");
   2911 		newp->cmd = cmd;
   2912 		newp->new_len = sizeof (ike_new_t) + pslen;
   2913 		(void) memcpy((char *)(newp + 1), psp, pslen);
   2914 		buflen = newp->new_len;
   2915 		/* parse_ps allocated the ike_ps_t buffer; free it now */
   2916 		free(psp);
   2917 
   2918 	} else if ((argc > 1) && (cmd == IKE_SVC_NEW_RULE)) {
   2919 		/*
   2920 		 * We've been given the item in argv.  However, parsing
   2921 		 * rules can get more than a little messy, and in.iked
   2922 		 * already has a great parser for this stuff!  So don't
   2923 		 * fool around with trying to do the parsing here. Just
   2924 		 * write it out to a tempfile, and send the fd to in.iked.
   2925 		 *
   2926 		 * We could conceivably do this for preshared keys,
   2927 		 * rather than duplicating the parsing effort; but that
   2928 		 * would mean the key would be written out to a file,
   2929 		 * which isn't such a good idea.
   2930 		 */
   2931 		boolean_t	doquotes = B_FALSE;
   2932 		int		rtn;
   2933 
   2934 		if ((argv[0][0] != '{') ||
   2935 		    (argv[argc - 1][strlen(argv[argc - 1]) - 1] != '}'))
   2936 			bail_msg(gettext("improperly formatted %s"), name);
   2937 
   2938 		/* attempt to use a fairly unpredictable file name... */
   2939 		(void) sprintf(tmpfilepath, "/var/run/%x", (int)gethrtime());
   2940 		fd = open(tmpfilepath, O_RDWR | O_CREAT | O_EXCL,
   2941 		    S_IRUSR | S_IWUSR);
   2942 		if (fd < 0)
   2943 			Bail("cannot open tmpfile");
   2944 
   2945 		/* and make it inaccessible asap */
   2946 		if (unlink(tmpfilepath) < 0) {
   2947 			(void) close(fd);
   2948 			Bail("tmpfile error");
   2949 		}
   2950 
   2951 		tmpfile = fdopen(fd, "w");
   2952 		if (tmpfile == NULL) {
   2953 			(void) close(fd);
   2954 			Bail("cannot write to tmpfile");
   2955 		}
   2956 
   2957 		for (i = 0; i < argc; i++) {
   2958 			/*
   2959 			 * We have to do some gyrations with our string here,
   2960 			 * to properly handle quotes.  There are two issues:
   2961 			 * - some of the fields of a rule may have embedded
   2962 			 *   whitespace, and thus must be quoted on the cmd
   2963 			 *   line.  The shell removes the quotes, and gives
   2964 			 *   us a single argv string; but we need to put the
   2965 			 *   quotes back in when we write the string out to
   2966 			 *   file.  The doquotes boolean is set when we
   2967 			 *   process a keyword which will be followed by a
   2968 			 *   string value (so the NEXT argv element will be
   2969 			 *   quoted).
   2970 			 * - there might be a quote character in a field,
   2971 			 *   that was escaped on the cmdline.  The shell
   2972 			 *   removes the escape char, and leaves the quote
   2973 			 *   in the string it gives us.  We need to put the
   2974 			 *   escape char back in before writing to file.
   2975 			 */
   2976 			char	field[MAXLINESIZE];
   2977 			if (!escapequotes(field, argv[i], MAXLINESIZE))
   2978 				Bail("write to tmpfile failed (arg too big)");
   2979 			if (doquotes) {
   2980 				rtn = fprintf(tmpfile, "\"%s\"\n", field);
   2981 				doquotes = B_FALSE;
   2982 			} else {
   2983 				rtn = fprintf(tmpfile, "%s\n", field);
   2984 			}
   2985 			if (rtn < 0)
   2986 				Bail("write to tmpfile failed");
   2987 			/*
   2988 			 * check if this is a keyword identifying
   2989 			 * a field that needs to be quoted.
   2990 			 */
   2991 			doquotes = quotedfield(argv[i]);
   2992 		}
   2993 		if (fflush(tmpfile) == EOF)
   2994 			Bail("write to tmpfile failed");
   2995 		/* rewind so that the daemon will get the beginning */
   2996 		rewind(tmpfile);
   2997 
   2998 		desc.d_data.d_desc.d_descriptor = fd;
   2999 		desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
   3000 		descp = &desc;
   3001 		ndesc = 1;
   3002 
   3003 		new.cmd = cmd;
   3004 		new.new_len = 0;
   3005 		newp = &new;
   3006 		buflen = sizeof (ike_new_t);
   3007 
   3008 	} else {
   3009 		/* not enough information! */
   3010 		bail_msg(gettext("missing %s description or file name"), name);
   3011 	}
   3012 
   3013 	rtn = ikedoor_call((char *)newp, buflen, descp, ndesc);
   3014 
   3015 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
   3016 		ikeadm_err_msg(&rtn->svc_err,
   3017 		    gettext("error creating new %s"), name);
   3018 	} else {
   3019 		message(gettext("Successfully created new %s."), name);
   3020 	}
   3021 }
   3022 
   3023 static void
   3024 do_flush(int cmd)
   3025 {
   3026 	ike_service_t	*rtnp;
   3027 	ike_flush_t	flush;
   3028 
   3029 	if (cmd != IKE_SVC_FLUSH_P1S && cmd != IKE_SVC_FLUSH_CERTCACHE) {
   3030 		bail_msg(gettext("unrecognized flush command (%d)."), cmd);
   3031 	}
   3032 
   3033 	flush.cmd = cmd;
   3034 
   3035 	rtnp = ikedoor_call((char *)&flush, sizeof (ike_flush_t), NULL, 0);
   3036 	if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
   3037 		ikeadm_err_exit(&rtnp->svc_err, gettext("error doing flush"));
   3038 	}
   3039 	if (cmd == IKE_SVC_FLUSH_P1S)
   3040 		message(gettext("Successfully flushed P1 SAs."));
   3041 	else
   3042 		message(gettext("Successfully flushed cert cache."));
   3043 }
   3044 
   3045 static void
   3046 do_rw(int cmd, int argc, char **argv)
   3047 {
   3048 	ike_service_t	*rtnp;
   3049 	ike_rw_t	rw;
   3050 	door_desc_t	desc, *descp = NULL;
   3051 	int		oflag, omode, fd, ndesc = 0;
   3052 	char		*op, *obj = NULL;
   3053 	boolean_t	writing = B_FALSE;
   3054 
   3055 	switch (cmd) {
   3056 	case IKE_SVC_READ_PS:
   3057 		obj = gettext("preshared key");
   3058 		/* FALLTHRU */
   3059 	case IKE_SVC_READ_RULES:
   3060 		if (obj == NULL)
   3061 			obj = gettext("policy rule");
   3062 		op = gettext("read");
   3063 		oflag = O_RDONLY;
   3064 		omode = 0;
   3065 		break;
   3066 
   3067 	case IKE_SVC_WRITE_PS:
   3068 		obj = gettext("preshared key");
   3069 		/* FALLTHRU */
   3070 	case IKE_SVC_WRITE_RULES:
   3071 		if (obj == NULL)
   3072 			obj = gettext("policy rule");
   3073 		op = gettext("write");
   3074 		oflag = O_RDWR | O_CREAT | O_EXCL;
   3075 		omode = S_IRUSR | S_IWUSR;
   3076 
   3077 		/* for write commands, dest location must be specified */
   3078 		if (argc < 1) {
   3079 			bail_msg(gettext("destination location required "
   3080 			    "to write %ss"), obj);
   3081 		}
   3082 		writing = B_TRUE;
   3083 		break;
   3084 
   3085 	default:
   3086 		bail_msg(gettext("unrecognized read/write command (%d)."), cmd);
   3087 	}
   3088 
   3089 	rw.cmd = cmd;
   3090 
   3091 	if (argc >= 1) {
   3092 		rw.rw_loc = IKE_RW_LOC_USER_SPEC;
   3093 		fd = open(argv[0], oflag, omode);
   3094 		if (fd < 0)
   3095 			Bail("open user-specified file");
   3096 
   3097 		desc.d_data.d_desc.d_descriptor = fd;
   3098 		desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
   3099 		descp = &desc;
   3100 		ndesc = 1;
   3101 	} else {
   3102 		rw.rw_loc = IKE_RW_LOC_DEFAULT;
   3103 	}
   3104 
   3105 	rtnp = ikedoor_call((char *)&rw, sizeof (ike_rw_t), descp, ndesc);
   3106 	if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
   3107 		/*
   3108 		 * Need to remove the target file in the
   3109 		 * case of a failed write command.
   3110 		 */
   3111 		if (writing) {
   3112 			/*
   3113 			 * argv[0] must be valid if we're writing; we
   3114 			 * exit before setting this boolean if not.
   3115 			 */
   3116 			(void) unlink(argv[0]);
   3117 			(void) close(fd);
   3118 
   3119 			if ((rtnp != NULL) &&
   3120 			    (rtnp->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
   3121 				message(gettext("No %s information to write."),
   3122 				    obj);
   3123 				return;
   3124 			}
   3125 		}
   3126 		ikeadm_err_exit(&rtnp->svc_err, gettext("error doing %s"), op);
   3127 	}
   3128 	message(gettext("Completed %s of %s configuration information."),
   3129 	    op, obj);
   3130 }
   3131 
   3132 static void
   3133 do_rbdump()
   3134 {
   3135 	ike_cmd_t	req;
   3136 	ike_service_t	*rtnp;
   3137 
   3138 	req.cmd = IKE_SVC_DBG_RBDUMP;
   3139 
   3140 	rtnp = ikedoor_call((char *)&req, sizeof (ike_cmd_t), NULL, 0);
   3141 	if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
   3142 		ikeadm_err_exit(&rtnp->svc_err, gettext("error doing flush"));
   3143 	}
   3144 	message(gettext("Successfully dumped rulebase; check iked dbg"));
   3145 }
   3146 
   3147 #define	REQ_ARG_CNT	1
   3148 
   3149 /*ARGSUSED*/
   3150 static void
   3151 parseit(int argc, char **argv, char *notused, boolean_t notused_either)
   3152 {
   3153 	int	cmd, cmd_obj_args = 1;
   3154 	char	*cmdstr, *objstr;
   3155 
   3156 	if (interactive) {
   3157 		if (argc == 0)
   3158 			return;
   3159 	}
   3160 
   3161 	if (argc < REQ_ARG_CNT) {
   3162 		usage();
   3163 	}
   3164 
   3165 	cmdstr = argv[0];
   3166 	if (argc > REQ_ARG_CNT) {
   3167 		cmd_obj_args++;
   3168 		objstr = argv[1];
   3169 	} else {
   3170 		objstr = NULL;
   3171 	}
   3172 	cmd = parsecmd(cmdstr, objstr);
   3173 
   3174 	/* skip over args specifying command/object */
   3175 	argc -= cmd_obj_args;
   3176 	argv += cmd_obj_args;
   3177 
   3178 	switch (cmd) {
   3179 	case IKE_SVC_GET_DEFS:
   3180 		if (argc != 0) {
   3181 			print_get_help();
   3182 			break;
   3183 		}
   3184 		do_getdefs(cmd);
   3185 		break;
   3186 	case IKE_SVC_GET_DBG:
   3187 	case IKE_SVC_GET_PRIV:
   3188 		if (argc != 0) {
   3189 			print_get_help();
   3190 			break;
   3191 		}
   3192 		do_getvar(cmd);
   3193 		break;
   3194 	case IKE_SVC_GET_STATS:
   3195 		if (argc != 0) {
   3196 			print_get_help();
   3197 			break;
   3198 		}
   3199 		do_getstats(cmd);
   3200 		break;
   3201 	case IKE_SVC_SET_DBG:
   3202 	case IKE_SVC_SET_PRIV:
   3203 		do_setvar(cmd, argc, argv);
   3204 		break;
   3205 	case IKE_SVC_SET_PIN:
   3206 	case IKE_SVC_DEL_PIN:
   3207 		do_setdel_pin(cmd, argc, argv);
   3208 		break;
   3209 	case IKE_SVC_DUMP_P1S:
   3210 	case IKE_SVC_DUMP_RULES:
   3211 	case IKE_SVC_DUMP_PS:
   3212 	case IKE_SVC_DUMP_CERTCACHE:
   3213 		if (argc != NULL) {
   3214 			print_dump_help();
   3215 			break;
   3216 		}
   3217 		do_dump(cmd);
   3218 		break;
   3219 	case IKE_SVC_GET_P1:
   3220 	case IKE_SVC_GET_RULE:
   3221 	case IKE_SVC_GET_PS:
   3222 	case IKE_SVC_DEL_P1:
   3223 	case IKE_SVC_DEL_RULE:
   3224 	case IKE_SVC_DEL_PS:
   3225 		do_getdel(cmd, argc, argv);
   3226 		break;
   3227 	case IKE_SVC_NEW_RULE:
   3228 	case IKE_SVC_NEW_PS:
   3229 		do_new(cmd, argc, argv);
   3230 		break;
   3231 	case IKE_SVC_FLUSH_P1S:
   3232 	case IKE_SVC_FLUSH_CERTCACHE:
   3233 		if (argc != 0) {
   3234 			print_flush_help();
   3235 			break;
   3236 		}
   3237 		do_flush(cmd);
   3238 		break;
   3239 	case IKE_SVC_READ_RULES:
   3240 	case IKE_SVC_READ_PS:
   3241 	case IKE_SVC_WRITE_RULES:
   3242 	case IKE_SVC_WRITE_PS:
   3243 		do_rw(cmd, argc, argv);
   3244 		break;
   3245 	case IKEADM_HELP_GENERAL:
   3246 		print_help();
   3247 		break;
   3248 	case IKEADM_HELP_GET:
   3249 		print_get_help();
   3250 		break;
   3251 	case IKEADM_HELP_SET:
   3252 		print_set_help();
   3253 		break;
   3254 	case IKEADM_HELP_ADD:
   3255 		print_add_help();
   3256 		break;
   3257 	case IKEADM_HELP_DEL:
   3258 		print_del_help();
   3259 		break;
   3260 	case IKEADM_HELP_DUMP:
   3261 		print_dump_help();
   3262 		break;
   3263 	case IKEADM_HELP_FLUSH:
   3264 		print_flush_help();
   3265 		break;
   3266 	case IKEADM_HELP_READ:
   3267 		print_read_help();
   3268 		break;
   3269 	case IKEADM_HELP_WRITE:
   3270 		print_write_help();
   3271 		break;
   3272 	case IKEADM_HELP_TOKEN:
   3273 		print_token_help();
   3274 		break;
   3275 	case IKEADM_HELP_HELP:
   3276 		print_help_help();
   3277 		break;
   3278 	case IKEADM_EXIT:
   3279 		if (interactive)
   3280 			exit(0);
   3281 		break;
   3282 	case IKE_SVC_DBG_RBDUMP:
   3283 		do_rbdump();
   3284 		break;
   3285 	case IKE_SVC_ERROR:
   3286 		usage();
   3287 	default:
   3288 		exit(0);
   3289 	}
   3290 }
   3291 
   3292 int
   3293 main(int argc, char **argv)
   3294 {
   3295 	char	ch;
   3296 
   3297 	(void) setlocale(LC_ALL, "");
   3298 #if !defined(TEXT_DOMAIN)
   3299 #define	TEXT_DOMAIN "SYS_TEST"
   3300 #endif
   3301 	(void) textdomain(TEXT_DOMAIN);
   3302 
   3303 	while ((ch = getopt(argc, argv, "hpn")) != EOF) {
   3304 		switch (ch) {
   3305 		case 'h':
   3306 			print_help();
   3307 			return (0);
   3308 		case 'p':
   3309 			pflag = B_TRUE;
   3310 			break;
   3311 		case 'n':
   3312 			nflag = B_TRUE;
   3313 			break;
   3314 		default:
   3315 			usage();
   3316 		}
   3317 	}
   3318 	argc -= optind;
   3319 	argv += optind;
   3320 
   3321 	if (open_door() < 0) {
   3322 		(void) fprintf(stderr,
   3323 		    gettext("Unable to communicate with in.iked\n"));
   3324 		Bail("open_door failed");
   3325 	}
   3326 
   3327 	if (*argv == NULL) {
   3328 		/* no cmd-line args, do interactive mode */
   3329 		do_interactive(stdin, NULL, "ikeadm> ", NULL, parseit,
   3330 		    no_match);
   3331 	}
   3332 
   3333 	parseit(argc, argv, NULL, B_FALSE);
   3334 
   3335 	return (0);
   3336 }
   3337