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