xref: /onnv-gate/usr/src/cmd/cmd-inet/usr.sbin/ipsecutils/ikeadm.c (revision 12129:97467a5349d0)
14235Smarkfen /*
24235Smarkfen  * CDDL HEADER START
34235Smarkfen  *
44235Smarkfen  * The contents of this file are subject to the terms of the
54235Smarkfen  * Common Development and Distribution License (the "License").
64235Smarkfen  * You may not use this file except in compliance with the License.
74235Smarkfen  *
84235Smarkfen  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94235Smarkfen  * or http://www.opensolaris.org/os/licensing.
104235Smarkfen  * See the License for the specific language governing permissions
114235Smarkfen  * and limitations under the License.
124235Smarkfen  *
134235Smarkfen  * When distributing Covered Code, include this CDDL HEADER in each
144235Smarkfen  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154235Smarkfen  * If applicable, add the following below this CDDL HEADER, with the
164235Smarkfen  * fields enclosed by brackets "[]" replaced with your own identifying
174235Smarkfen  * information: Portions Copyright [yyyy] [name of copyright owner]
184235Smarkfen  *
194235Smarkfen  * CDDL HEADER END
204235Smarkfen  *
21*12129SVladimir.Kotal@Sun.COM  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
224235Smarkfen  */
234235Smarkfen 
244235Smarkfen #include <unistd.h>
254235Smarkfen #include <stdio.h>
264235Smarkfen #include <stdarg.h>
274235Smarkfen #include <stdlib.h>
284235Smarkfen #include <sys/sysconf.h>
294235Smarkfen #include <string.h>
304235Smarkfen #include <strings.h>
314235Smarkfen #include <libintl.h>
324235Smarkfen #include <locale.h>
334235Smarkfen #include <ctype.h>
344235Smarkfen #include <time.h>
354235Smarkfen #include <sys/sysmacros.h>
364235Smarkfen #include <sys/stat.h>
374235Smarkfen #include <sys/mman.h>
384235Smarkfen #include <fcntl.h>
394235Smarkfen #include <sys/socket.h>
404235Smarkfen #include <netdb.h>
414235Smarkfen #include <errno.h>
424235Smarkfen #include <assert.h>
434235Smarkfen #include <netinet/in.h>
444235Smarkfen #include <arpa/inet.h>
454235Smarkfen #include <door.h>
464235Smarkfen #include <setjmp.h>
474235Smarkfen 
484235Smarkfen #include <ipsec_util.h>
494235Smarkfen #include <ikedoor.h>
504235Smarkfen 
514235Smarkfen static int	doorfd = -1;
524235Smarkfen 
534235Smarkfen /*
544235Smarkfen  * These are additional return values for the command line parsing
554235Smarkfen  * function (parsecmd()).  They are specific to this utility, but
564235Smarkfen  * need to share the same space as the IKE_SVC_* defs, without conflicts.
574235Smarkfen  * So they're defined relative to the end of that range.
584235Smarkfen  */
594235Smarkfen #define	IKEADM_HELP_GENERAL	IKE_SVC_MAX + 1
604235Smarkfen #define	IKEADM_HELP_GET		IKE_SVC_MAX + 2
614235Smarkfen #define	IKEADM_HELP_SET		IKE_SVC_MAX + 3
624235Smarkfen #define	IKEADM_HELP_ADD		IKE_SVC_MAX + 4
634235Smarkfen #define	IKEADM_HELP_DEL		IKE_SVC_MAX + 5
644235Smarkfen #define	IKEADM_HELP_DUMP	IKE_SVC_MAX + 6
654235Smarkfen #define	IKEADM_HELP_FLUSH	IKE_SVC_MAX + 7
664235Smarkfen #define	IKEADM_HELP_READ	IKE_SVC_MAX + 8
674235Smarkfen #define	IKEADM_HELP_WRITE	IKE_SVC_MAX + 9
688596SPaul.Wernau@Sun.COM #define	IKEADM_HELP_TOKEN	IKE_SVC_MAX + 10
698596SPaul.Wernau@Sun.COM #define	IKEADM_HELP_HELP	IKE_SVC_MAX + 11
708596SPaul.Wernau@Sun.COM #define	IKEADM_EXIT		IKE_SVC_MAX + 12
714235Smarkfen 
729086SVladimir.Kotal@Sun.COM /*
739086SVladimir.Kotal@Sun.COM  * Disable default TAB completion for now (until some brave soul tackles it).
749086SVladimir.Kotal@Sun.COM  */
759086SVladimir.Kotal@Sun.COM /* ARGSUSED */
769086SVladimir.Kotal@Sun.COM static
779086SVladimir.Kotal@Sun.COM CPL_MATCH_FN(no_match)
789086SVladimir.Kotal@Sun.COM {
799086SVladimir.Kotal@Sun.COM 	return (0);
809086SVladimir.Kotal@Sun.COM }
819086SVladimir.Kotal@Sun.COM 
824235Smarkfen static void
834235Smarkfen command_complete(int s)
844235Smarkfen {
854235Smarkfen 	if (interactive) {
864235Smarkfen 		longjmp(env, 1);
874235Smarkfen 	} else {
884235Smarkfen 		exit(s);
894235Smarkfen 	}
904235Smarkfen }
914235Smarkfen 
924235Smarkfen static void
934235Smarkfen usage()
944235Smarkfen {
954235Smarkfen 	if (!interactive) {
964235Smarkfen 		(void) fprintf(stderr, gettext("Usage:\t"
974235Smarkfen 		    "ikeadm [ -hnp ] cmd obj [cmd-specific options]\n"));
984235Smarkfen 		(void) fprintf(stderr, gettext("      \tikeadm help\n"));
999086SVladimir.Kotal@Sun.COM 	} else {
1009086SVladimir.Kotal@Sun.COM 		(void) fprintf(stderr,
1019086SVladimir.Kotal@Sun.COM 		    gettext("\nType help for usage info\n"));
1024235Smarkfen 	}
1034235Smarkfen 
1044235Smarkfen 	command_complete(1);
1054235Smarkfen }
1064235Smarkfen 
1074235Smarkfen static void
1084235Smarkfen print_help()
1094235Smarkfen {
1104235Smarkfen 	(void) printf(gettext("Valid commands and objects:\n"));
1114235Smarkfen 	(void) printf(
1124235Smarkfen 	    "\tget   debug|priv|stats|p1|rule|preshared|defaults [%s]\n",
1134235Smarkfen 	    gettext("identifier"));
1144235Smarkfen 	(void) printf("\tset   priv %s\n", gettext("level"));
1154235Smarkfen 	(void) printf("\tset   debug %s [%s]\n",
1164235Smarkfen 	    gettext("level"), gettext("filename"));
1174235Smarkfen 	(void) printf("\tadd   rule|preshared {%s}|%s\n",
1184235Smarkfen 	    gettext("definition"), gettext("filename"));
1194235Smarkfen 	(void) printf("\tdel   p1|rule|preshared %s\n", gettext("identifier"));
120*12129SVladimir.Kotal@Sun.COM 	(void) printf("\tdump  p1|rule|preshared|certcache|groups|"
121*12129SVladimir.Kotal@Sun.COM 	    "encralgs|authalgs\n");
1228596SPaul.Wernau@Sun.COM 	(void) printf("\tflush p1|certcache\n");
1234235Smarkfen 	(void) printf("\tread  rule|preshared [%s]\n", gettext("filename"));
1244235Smarkfen 	(void) printf("\twrite rule|preshared %s\n", gettext("filename"));
1258596SPaul.Wernau@Sun.COM 	(void) printf("\ttoken <login|logout> %s\n",
1268596SPaul.Wernau@Sun.COM 	    gettext("<PKCS#11 Token Object>"));
1274235Smarkfen 	(void) printf(
1288596SPaul.Wernau@Sun.COM 	    "\thelp  [get|set|add|del|dump|flush|read|write|token|help]\n");
1294235Smarkfen 	(void) printf("\texit  %s\n", gettext("exit the program"));
1304235Smarkfen 	(void) printf("\tquit  %s\n", gettext("exit the program"));
1314235Smarkfen 
1324235Smarkfen 	command_complete(0);
1334235Smarkfen }
1344235Smarkfen 
1354235Smarkfen static void
1364235Smarkfen print_get_help()
1374235Smarkfen {
1384235Smarkfen 	(void) printf(
1394235Smarkfen 	    gettext("This command gets information from in.iked.\n\n"));
1404235Smarkfen 	(void) printf(gettext("Objects that may be retrieved include:\n"));
1414235Smarkfen 	(void) printf("\tdebug\t\t");
1424235Smarkfen 	(void) printf(gettext("the current debug level\n"));
1434235Smarkfen 	(void) printf("\tpriv\t\t");
1444235Smarkfen 	(void) printf(gettext("the current privilege level\n"));
1454235Smarkfen 	(void) printf("\tstats\t\t");
1464235Smarkfen 	(void) printf(gettext("current usage statistics\n"));
1474235Smarkfen 	(void) printf("\tp1\t\t");
1484235Smarkfen 	(void) printf(gettext("a phase 1 SA, identified by\n"));
1494235Smarkfen 	(void) printf(gettext("\t\t\t  local_ip remote_ip OR\n"));
1504235Smarkfen 	(void) printf(gettext("\t\t\t  init_cookie resp_cookie\n"));
1514235Smarkfen 	(void) printf("\trule\t\t");
1524235Smarkfen 	(void) printf(gettext("a phase 1 rule, identified by its label\n"));
1534235Smarkfen 	(void) printf("\tpreshared\t");
1544235Smarkfen 	(void) printf(gettext("a preshared key, identified by\n"));
1554235Smarkfen 	(void) printf(gettext("\t\t\t  local_ip remote_ip OR\n"));
1564235Smarkfen 	(void) printf(gettext("\t\t\t  local_id remote_id\n"));
1574235Smarkfen 	(void) printf("\n");
1584235Smarkfen 
1594235Smarkfen 	command_complete(0);
1604235Smarkfen }
1614235Smarkfen 
1624235Smarkfen static void
1634235Smarkfen print_set_help()
1644235Smarkfen {
1654235Smarkfen 	(void) printf(gettext("This command sets values in in.iked.\n\n"));
1664235Smarkfen 	(void) printf(gettext("Objects that may be set include:\n"));
1674235Smarkfen 	(void) printf("\tdebug\t\t");
1684235Smarkfen 	(void) printf(gettext("change the debug level\n"));
1694235Smarkfen 	(void) printf("\tpriv\t\t");
1704235Smarkfen 	(void) printf(
1714235Smarkfen 	    gettext("change the privilege level (may only be lowered)\n"));
1724235Smarkfen 	(void) printf("\n");
1734235Smarkfen 
1744235Smarkfen 	command_complete(0);
1754235Smarkfen }
1764235Smarkfen 
1774235Smarkfen static void
1784235Smarkfen print_add_help()
1794235Smarkfen {
1804235Smarkfen 	(void) printf(
1814235Smarkfen 	    gettext("This command adds items to in.iked's tables.\n\n"));
1824235Smarkfen 	(void) printf(gettext("Objects that may be set include:\n"));
1834235Smarkfen 	(void) printf("\trule\t\t");
1844235Smarkfen 	(void) printf(gettext("a phase 1 policy rule\n"));
1854235Smarkfen 	(void) printf("\tpreshared\t");
1864235Smarkfen 	(void) printf(gettext("a preshared key\n"));
1874235Smarkfen 	(void) printf(
1884235Smarkfen 	    gettext("\nObjects may be entered on the command-line, as a\n"));
1894235Smarkfen 	(void) printf(
1904235Smarkfen 	    gettext("series of keywords and tokens contained in curly\n"));
1914235Smarkfen 	(void) printf(
1924235Smarkfen 	    gettext("braces ('{', '}'); or the name of a file containing\n"));
1934235Smarkfen 	(void) printf(gettext("the object definition may be provided.\n\n"));
1944235Smarkfen 	(void) printf(
1954235Smarkfen 	    gettext("For security purposes, preshared keys may only be\n"));
1964235Smarkfen 	(void) printf(
1974235Smarkfen 	    gettext("entered on the command-line if ikeadm is running in\n"));
1984235Smarkfen 	(void) printf(gettext("interactive mode.\n"));
1994235Smarkfen 	(void) printf("\n");
2004235Smarkfen 
2014235Smarkfen 	command_complete(0);
2024235Smarkfen }
2034235Smarkfen 
2044235Smarkfen static void
2054235Smarkfen print_del_help()
2064235Smarkfen {
2074235Smarkfen 	(void) printf(
2084235Smarkfen 	    gettext("This command deletes an item from in.iked's tables.\n\n"));
2094235Smarkfen 	(void) printf(gettext("Objects that may be deleted include:\n"));
2104235Smarkfen 	(void) printf("\tp1\t\t");
2114235Smarkfen 	(void) printf(gettext("a phase 1 SA, identified by\n"));
2124235Smarkfen 	(void) printf(gettext("\t\t\t  local_ip remote_ip OR\n"));
2134235Smarkfen 	(void) printf(gettext("\t\t\t  init_cookie resp_cookie\n"));
2144235Smarkfen 	(void) printf("\trule\t\t");
2154235Smarkfen 	(void) printf(gettext("a phase 1 rule, identified by its label\n"));
2164235Smarkfen 	(void) printf("\tpreshared\t");
2174235Smarkfen 	(void) printf(gettext("a preshared key, identified by\n"));
2184235Smarkfen 	(void) printf(gettext("\t\t\t  local_ip remote_ip OR\n"));
2194235Smarkfen 	(void) printf(gettext("\t\t\t  local_id remote_id\n"));
2204235Smarkfen 	(void) printf("\n");
2214235Smarkfen 
2224235Smarkfen 	command_complete(0);
2234235Smarkfen }
2244235Smarkfen 
2254235Smarkfen static void
2264235Smarkfen print_dump_help()
2274235Smarkfen {
2284235Smarkfen 	(void) printf(
2294235Smarkfen 	    gettext("This command dumps one of in.iked's tables.\n\n"));
2304235Smarkfen 	(void) printf(gettext("Tables that may be dumped include:\n"));
2314235Smarkfen 	(void) printf("\tp1\t\t");
2324235Smarkfen 	(void) printf(gettext("all phase 1 SAs\n"));
2334235Smarkfen 	(void) printf("\trule\t\t");
2344235Smarkfen 	(void) printf(gettext("all phase 1 rules\n"));
2354235Smarkfen 	(void) printf("\tpreshared\t");
2364235Smarkfen 	(void) printf(gettext("all preshared keys\n"));
2378596SPaul.Wernau@Sun.COM 	(void) printf("\tcertcache\t");
2388596SPaul.Wernau@Sun.COM 	(void) printf(gettext("all cached certificates\n"));
239*12129SVladimir.Kotal@Sun.COM 	(void) printf("\tgroups\t\t");
240*12129SVladimir.Kotal@Sun.COM 	(void) printf(gettext("all implemented Diffie-Hellman groups\n"));
241*12129SVladimir.Kotal@Sun.COM 	(void) printf("\tencralgs\t");
242*12129SVladimir.Kotal@Sun.COM 	(void) printf(gettext("all encryption algorithms for IKE\n"));
243*12129SVladimir.Kotal@Sun.COM 	(void) printf("\tauthalgs\t");
244*12129SVladimir.Kotal@Sun.COM 	(void) printf(gettext("all authentication algorithms IKE\n"));
2454235Smarkfen 	(void) printf("\n");
2464235Smarkfen 
2474235Smarkfen 	command_complete(0);
2484235Smarkfen }
2494235Smarkfen 
2504235Smarkfen static void
2514235Smarkfen print_flush_help()
2524235Smarkfen {
2534235Smarkfen 	(void) printf(
2544235Smarkfen 	    gettext("This command clears one of in.iked's tables.\n\n"));
2554235Smarkfen 	(void) printf(gettext("Tables that may be flushed include:\n"));
2564235Smarkfen 	(void) printf("\tp1\t\t");
2574235Smarkfen 	(void) printf(gettext("all phase 1 SAs\n"));
2588596SPaul.Wernau@Sun.COM 	(void) printf("\tcertcache\t");
2598596SPaul.Wernau@Sun.COM 	(void) printf(gettext("all cached certificates\n"));
2604235Smarkfen 	(void) printf("\n");
2614235Smarkfen 
2624235Smarkfen 	command_complete(0);
2634235Smarkfen }
2644235Smarkfen 
2654235Smarkfen static void
2664235Smarkfen print_read_help()
2674235Smarkfen {
2684235Smarkfen 	(void) printf(
2694235Smarkfen 	    gettext("This command reads a new configuration file into\n"));
2704235Smarkfen 	(void) printf(
2714235Smarkfen 	    gettext("in.iked, discarding the old configuration info.\n\n"));
2724235Smarkfen 	(void) printf(gettext("Sets of data that may be read include:\n"));
2734235Smarkfen 	(void) printf("\trule\t\t");
2744235Smarkfen 	(void) printf(gettext("all phase 1 rules\n"));
2754235Smarkfen 	(void) printf("\tpreshared\t");
2764235Smarkfen 	(void) printf(gettext("all preshared keys\n\n"));
2774235Smarkfen 	(void) printf(
2784235Smarkfen 	    gettext("A filename may be provided to specify a source file\n"));
2794235Smarkfen 	(void) printf(gettext("other than the default.\n"));
2804235Smarkfen 	(void) printf("\n");
2814235Smarkfen 
2824235Smarkfen 	command_complete(0);
2834235Smarkfen }
2844235Smarkfen 
2854235Smarkfen static void
2864235Smarkfen print_write_help()
2874235Smarkfen {
2884235Smarkfen 	(void) printf(
2894235Smarkfen 	    gettext("This command writes in.iked's current configuration\n"));
2904235Smarkfen 	(void) printf(gettext("out to a config file.\n\n"));
2914235Smarkfen 	(void) printf(gettext("Sets of data that may be written include:\n"));
2924235Smarkfen 	(void) printf("\trule\t\t");
2934235Smarkfen 	(void) printf(gettext("all phase 1 rules\n"));
2944235Smarkfen 	(void) printf("\tpreshared\t");
2954235Smarkfen 	(void) printf(gettext("all preshared keys\n\n"));
2964235Smarkfen 	(void) printf(
2974235Smarkfen 	    gettext("A filename must be provided to specify the file to\n"));
2984235Smarkfen 	(void) printf(gettext("which the information should be written.\n"));
2994235Smarkfen 	(void) printf("\n");
3004235Smarkfen 
3014235Smarkfen 	command_complete(0);
3024235Smarkfen }
3034235Smarkfen 
3044235Smarkfen static void
3058596SPaul.Wernau@Sun.COM print_token_help()
3068596SPaul.Wernau@Sun.COM {
3078596SPaul.Wernau@Sun.COM 	(void) printf(gettext(
3088596SPaul.Wernau@Sun.COM 	    "This command logs IKE into and out of PKCS#11 tokens.\n\n"));
3098596SPaul.Wernau@Sun.COM 	(void) printf(gettext("Commands include:\n"));
3108596SPaul.Wernau@Sun.COM 	(void) printf("\tlogin <PKCS#11 Token Object>\t");
3118596SPaul.Wernau@Sun.COM 	(void) printf(gettext("log into token\n"));
3128596SPaul.Wernau@Sun.COM 	(void) printf("\tlogout <PKCS#11 Token Object>\t");
3138596SPaul.Wernau@Sun.COM 	(void) printf(gettext("log out of token\n\n"));
3148596SPaul.Wernau@Sun.COM 	(void) printf(
3158596SPaul.Wernau@Sun.COM 	    gettext("The PKCS#11 Token Object name must be "
3168596SPaul.Wernau@Sun.COM 	    "enclosed in quotation marks.\n"));
3178596SPaul.Wernau@Sun.COM 	(void) printf("\n");
3188596SPaul.Wernau@Sun.COM 
3198596SPaul.Wernau@Sun.COM 	command_complete(0);
3208596SPaul.Wernau@Sun.COM }
3218596SPaul.Wernau@Sun.COM 
3228596SPaul.Wernau@Sun.COM static void
3234235Smarkfen print_help_help()
3244235Smarkfen {
3254235Smarkfen 	(void) printf(
3264235Smarkfen 	    gettext("This command provides information about commands.\n\n"));
3274235Smarkfen 	(void) printf(
3284235Smarkfen 	    gettext("The 'help' command alone provides a list of valid\n"));
3294235Smarkfen 	(void) printf(
3304235Smarkfen 	    gettext("commands, along with the valid objects for each.\n"));
3314235Smarkfen 	(void) printf(
3324235Smarkfen 	    gettext("'help' followed by a valid command name provides\n"));
3334235Smarkfen 	(void) printf(gettext("further information about that command.\n"));
3344235Smarkfen 	(void) printf("\n");
3354235Smarkfen 
3364235Smarkfen 	command_complete(0);
3374235Smarkfen }
3384235Smarkfen 
3394235Smarkfen /*PRINTFLIKE1*/
3404235Smarkfen static void
3414235Smarkfen message(char *fmt, ...)
3424235Smarkfen {
3434235Smarkfen 	va_list	ap;
3444235Smarkfen 	char	msgbuf[BUFSIZ];
3454235Smarkfen 
3464235Smarkfen 	va_start(ap, fmt);
3474235Smarkfen 	(void) vsnprintf(msgbuf, BUFSIZ, fmt, ap);
3484235Smarkfen 	(void) fprintf(stderr, gettext("ikeadm: %s\n"), msgbuf);
3494235Smarkfen 	va_end(ap);
3504235Smarkfen }
3514235Smarkfen 
3524235Smarkfen static int
3534235Smarkfen open_door(void)
3544235Smarkfen {
3554235Smarkfen 	if (doorfd >= 0)
3564235Smarkfen 		(void) close(doorfd);
3578596SPaul.Wernau@Sun.COM 	doorfd = open(DOORNM, O_RDONLY);
3584235Smarkfen 	return (doorfd);
3594235Smarkfen }
3604235Smarkfen 
3614235Smarkfen static ike_service_t *
3624235Smarkfen ikedoor_call(char *reqp, int size, door_desc_t *descp, int ndesc)
3634235Smarkfen {
3644235Smarkfen 	door_arg_t	arg;
3654235Smarkfen 	int retries = 0;
3664235Smarkfen 
3674235Smarkfen 	arg.data_ptr = reqp;
3684235Smarkfen 	arg.data_size = size;
3694235Smarkfen 	arg.desc_ptr = descp;
3704235Smarkfen 	arg.desc_num = ndesc;
3714235Smarkfen 	arg.rbuf = (char *)NULL;
3724235Smarkfen 	arg.rsize = 0;
3734235Smarkfen 
3744235Smarkfen retry:
3754235Smarkfen 	if (door_call(doorfd, &arg) < 0) {
3764235Smarkfen 		if ((errno == EBADF) && ((++retries < 2) &&
3774235Smarkfen 		    (open_door() >= 0)))
3784235Smarkfen 			goto retry;
3794235Smarkfen 		(void) fprintf(stderr,
3804235Smarkfen 		    gettext("Unable to communicate with in.iked\n"));
3814235Smarkfen 		Bail("door_call failed");
3824235Smarkfen 	}
3834235Smarkfen 
3844235Smarkfen 	if ((ndesc > 0) && (descp->d_attributes & DOOR_RELEASE) &&
3854235Smarkfen 	    ((errno == EBADF) || (errno == EFAULT))) {
3864235Smarkfen 		/* callers assume passed fds will be closed no matter what */
3874235Smarkfen 		(void) close(descp->d_data.d_desc.d_descriptor);
3884235Smarkfen 	}
3894235Smarkfen 
3904235Smarkfen 	/* LINTED E_BAD_PTR_CAST_ALIGN */
3914235Smarkfen 	return ((ike_service_t *)arg.rbuf);
3924235Smarkfen }
3934235Smarkfen 
3944235Smarkfen /*
3954235Smarkfen  * Parsing functions
3964235Smarkfen  */
3974235Smarkfen 
3984235Smarkfen /* stolen from ipseckey.c, with a second tier added */
3994235Smarkfen static int
4004235Smarkfen parsecmd(char *cmdstr, char *objstr)
4014235Smarkfen {
4028596SPaul.Wernau@Sun.COM #define	MAXOBJS		11
4034235Smarkfen 	struct objtbl {
4044235Smarkfen 		char	*obj;
4054235Smarkfen 		int	token;
4064235Smarkfen 	};
4074235Smarkfen 	static struct cmdtbl {
4084235Smarkfen 		char		*cmd;
4094235Smarkfen 		int		null_obj_token;
4104235Smarkfen 		struct objtbl	objt[MAXOBJS];
4114235Smarkfen 	} table[] = {
4124235Smarkfen 		{"get", IKE_SVC_ERROR, {
4134235Smarkfen 				{"debug",	IKE_SVC_GET_DBG},
4144235Smarkfen 				{"priv",	IKE_SVC_GET_PRIV},
4154235Smarkfen 				{"stats",	IKE_SVC_GET_STATS},
4164235Smarkfen 				{"p1",		IKE_SVC_GET_P1},
4174235Smarkfen 				{"rule",	IKE_SVC_GET_RULE},
4184235Smarkfen 				{"preshared",	IKE_SVC_GET_PS},
4194235Smarkfen 				{"defaults",	IKE_SVC_GET_DEFS},
4207421SDaniel.Anderson@Sun.COM 				{NULL,		IKE_SVC_ERROR}
4214235Smarkfen 			}
4224235Smarkfen 		},
4234235Smarkfen 		{"set", IKE_SVC_ERROR, {
4244235Smarkfen 				{"debug",	IKE_SVC_SET_DBG},
4254235Smarkfen 				{"priv",	IKE_SVC_SET_PRIV},
4267421SDaniel.Anderson@Sun.COM 				{NULL,		IKE_SVC_ERROR}
4274235Smarkfen 			}
4284235Smarkfen 		},
4298596SPaul.Wernau@Sun.COM 		{"token", IKE_SVC_ERROR, {
4308596SPaul.Wernau@Sun.COM 				{"login",	IKE_SVC_SET_PIN},
4318596SPaul.Wernau@Sun.COM 				{"logout",	IKE_SVC_DEL_PIN},
4328596SPaul.Wernau@Sun.COM 				{NULL,		IKE_SVC_ERROR},
4338596SPaul.Wernau@Sun.COM 			}
4348596SPaul.Wernau@Sun.COM 		},
4354235Smarkfen 		{"add", IKE_SVC_ERROR, {
4364235Smarkfen 				{"rule",	IKE_SVC_NEW_RULE},
4374235Smarkfen 				{"preshared",	IKE_SVC_NEW_PS},
4387421SDaniel.Anderson@Sun.COM 				{NULL,		IKE_SVC_ERROR}
4394235Smarkfen 			}
4404235Smarkfen 		},
4414235Smarkfen 		{"del", IKE_SVC_ERROR, {
4424235Smarkfen 				{"p1",		IKE_SVC_DEL_P1},
4434235Smarkfen 				{"rule",	IKE_SVC_DEL_RULE},
4444235Smarkfen 				{"preshared",	IKE_SVC_DEL_PS},
4457421SDaniel.Anderson@Sun.COM 				{NULL,		IKE_SVC_ERROR}
4464235Smarkfen 			}
4474235Smarkfen 		},
4484235Smarkfen 		{"dump", IKE_SVC_ERROR, {
4494235Smarkfen 				{"p1",		IKE_SVC_DUMP_P1S},
4504235Smarkfen 				{"rule",	IKE_SVC_DUMP_RULES},
4514235Smarkfen 				{"preshared",	IKE_SVC_DUMP_PS},
4528596SPaul.Wernau@Sun.COM 				{"certcache",	IKE_SVC_DUMP_CERTCACHE},
453*12129SVladimir.Kotal@Sun.COM 				{"groups",	IKE_SVC_DUMP_GROUPS},
454*12129SVladimir.Kotal@Sun.COM 				{"encralgs",	IKE_SVC_DUMP_ENCRALGS},
455*12129SVladimir.Kotal@Sun.COM 				{"authalgs",	IKE_SVC_DUMP_AUTHALGS},
4567421SDaniel.Anderson@Sun.COM 				{NULL,		IKE_SVC_ERROR}
4574235Smarkfen 			}
4584235Smarkfen 		},
4594235Smarkfen 		{"flush", IKE_SVC_ERROR, {
4604235Smarkfen 				{"p1",		IKE_SVC_FLUSH_P1S},
4618596SPaul.Wernau@Sun.COM 				{"certcache",	IKE_SVC_FLUSH_CERTCACHE},
4627421SDaniel.Anderson@Sun.COM 				{NULL,		IKE_SVC_ERROR}
4634235Smarkfen 			}
4644235Smarkfen 		},
4654235Smarkfen 		{"read", IKE_SVC_ERROR, {
4664235Smarkfen 				{"rule",	IKE_SVC_READ_RULES},
4674235Smarkfen 				{"preshared",	IKE_SVC_READ_PS},
4687421SDaniel.Anderson@Sun.COM 				{NULL,		IKE_SVC_ERROR}
4694235Smarkfen 			}
4704235Smarkfen 		},
4714235Smarkfen 		{"write", IKE_SVC_ERROR, {
4724235Smarkfen 				{"rule",	IKE_SVC_WRITE_RULES},
4734235Smarkfen 				{"preshared",	IKE_SVC_WRITE_PS},
4747421SDaniel.Anderson@Sun.COM 				{NULL,		IKE_SVC_ERROR}
4754235Smarkfen 			}
4764235Smarkfen 		},
4774235Smarkfen 		{"help", IKEADM_HELP_GENERAL, {
4784235Smarkfen 				{"get",		IKEADM_HELP_GET},
4794235Smarkfen 				{"set",		IKEADM_HELP_SET},
4804235Smarkfen 				{"add",		IKEADM_HELP_ADD},
4814235Smarkfen 				{"del",		IKEADM_HELP_DEL},
4824235Smarkfen 				{"dump",	IKEADM_HELP_DUMP},
4834235Smarkfen 				{"flush",	IKEADM_HELP_FLUSH},
4844235Smarkfen 				{"read",	IKEADM_HELP_READ},
4854235Smarkfen 				{"write",	IKEADM_HELP_WRITE},
4868596SPaul.Wernau@Sun.COM 				{"token",	IKEADM_HELP_TOKEN},
4874235Smarkfen 				{"help",	IKEADM_HELP_HELP},
4887421SDaniel.Anderson@Sun.COM 				{NULL,		IKE_SVC_ERROR}
4894235Smarkfen 			}
4904235Smarkfen 		},
4914235Smarkfen 		{"exit", IKEADM_EXIT, {
4927421SDaniel.Anderson@Sun.COM 				{NULL,		IKE_SVC_ERROR}
4934235Smarkfen 			}
4944235Smarkfen 		},
4954235Smarkfen 		{"quit", IKEADM_EXIT, {
4967421SDaniel.Anderson@Sun.COM 				{NULL,		IKE_SVC_ERROR}
4974235Smarkfen 			}
4984235Smarkfen 		},
4994235Smarkfen 		{"dbg", IKE_SVC_ERROR, {
5004235Smarkfen 				{"rbdump",	IKE_SVC_DBG_RBDUMP},
5017421SDaniel.Anderson@Sun.COM 				{NULL,		IKE_SVC_ERROR}
5024235Smarkfen 			}
5034235Smarkfen 		},
5044235Smarkfen 		{NULL,	IKE_SVC_ERROR, {
5057421SDaniel.Anderson@Sun.COM 				{NULL,		IKE_SVC_ERROR}
5064235Smarkfen 			}
5077421SDaniel.Anderson@Sun.COM 		}
5084235Smarkfen 	};
5094235Smarkfen 	struct cmdtbl	*ct = table;
5104235Smarkfen 	struct objtbl	*ot;
5114235Smarkfen 
5124235Smarkfen 	if (cmdstr == NULL) {
5134235Smarkfen 		return (IKE_SVC_ERROR);
5144235Smarkfen 	}
5154235Smarkfen 
5164235Smarkfen 	while (ct->cmd != NULL && strcmp(ct->cmd, cmdstr) != 0)
5174235Smarkfen 		ct++;
5184235Smarkfen 	ot = ct->objt;
5194235Smarkfen 
5204235Smarkfen 	if (ct->cmd == NULL) {
5214235Smarkfen 		message(gettext("Unrecognized command '%s'"), cmdstr);
5224235Smarkfen 		return (ot->token);
5234235Smarkfen 	}
5244235Smarkfen 
5254235Smarkfen 	if (objstr == NULL) {
5264235Smarkfen 		return (ct->null_obj_token);
5274235Smarkfen 	}
5284235Smarkfen 
5294235Smarkfen 	while (ot->obj != NULL && strcmp(ot->obj, objstr) != 0)
5304235Smarkfen 		ot++;
5314235Smarkfen 
5324235Smarkfen 	if (ot->obj == NULL)
5334235Smarkfen 		message(gettext("Unrecognized object '%s'"), objstr);
5344235Smarkfen 
5354235Smarkfen 	return (ot->token);
5364235Smarkfen }
5374235Smarkfen 
5384235Smarkfen /*
5394235Smarkfen  * Parsing functions:
5404235Smarkfen  * Parse command-line identification info.  All return -1 on failure,
5414235Smarkfen  * or the number of cmd-line args "consumed" on success (though argc
5424235Smarkfen  * and argv params are not actually modified).
5434235Smarkfen  */
5444235Smarkfen 
5454235Smarkfen static int
5464235Smarkfen parse_label(int argc, char **argv, char *label)
5474235Smarkfen {
5484235Smarkfen 	if ((argc < 1) || (argv == NULL))
5494235Smarkfen 		return (-1);
5504235Smarkfen 
5514235Smarkfen 	if (strlcpy(label, argv[0], MAX_LABEL_LEN) >= MAX_LABEL_LEN)
5524235Smarkfen 		return (-1);
5534235Smarkfen 
5544235Smarkfen 	return (1);
5554235Smarkfen }
5564235Smarkfen 
5574235Smarkfen /*
5588596SPaul.Wernau@Sun.COM  * Parse a PKCS#11 token get the label.
5598596SPaul.Wernau@Sun.COM  */
5608596SPaul.Wernau@Sun.COM static int
5618596SPaul.Wernau@Sun.COM parse_token(int argc, char **argv, char *token_label)
5628596SPaul.Wernau@Sun.COM {
5638596SPaul.Wernau@Sun.COM 	if ((argc < 1) || (argv == NULL))
5648596SPaul.Wernau@Sun.COM 		return (-1);
5658596SPaul.Wernau@Sun.COM 
5668596SPaul.Wernau@Sun.COM 	if (strlcpy(token_label, argv[0], PKCS11_TOKSIZE) >= PKCS11_TOKSIZE)
5678596SPaul.Wernau@Sun.COM 		return (-1);
5688596SPaul.Wernau@Sun.COM 
5698596SPaul.Wernau@Sun.COM 	return (0);
5708596SPaul.Wernau@Sun.COM }
5718596SPaul.Wernau@Sun.COM 
5728596SPaul.Wernau@Sun.COM /*
5734235Smarkfen  * Parse an address off the command line. In the hpp param, either
5744235Smarkfen  * return a hostent pointer (caller frees) or a pointer to a dummy_he_t
5754235Smarkfen  * (must also be freed by the caller; both cases are handled by the
5764235Smarkfen  * macro FREE_HE).  The new getipnodebyname() call does the Right Thing
5774235Smarkfen  * (TM), even with raw addresses (colon-separated IPv6 or dotted decimal
5784235Smarkfen  * IPv4).
5794235Smarkfen  * (mostly stolen from ipseckey.c, though some tweaks were made
5804235Smarkfen  * to better serve our purposes here.)
5814235Smarkfen  */
5824235Smarkfen 
5834235Smarkfen typedef struct {
5844235Smarkfen 	struct hostent	he;
5854235Smarkfen 	char		*addtl[2];
5864235Smarkfen } dummy_he_t;
5874235Smarkfen 
5884235Smarkfen static int
5894235Smarkfen parse_addr(int argc, char **argv, struct hostent **hpp)
5904235Smarkfen {
5914235Smarkfen 	int		hp_errno;
5924235Smarkfen 	struct hostent	*hp = NULL;
5934235Smarkfen 	dummy_he_t	*dhp;
5944235Smarkfen 	char		*addr1;
5954235Smarkfen 
5964235Smarkfen 	if ((argc < 1) || (argv == NULL) || (argv[0] == NULL))
5974235Smarkfen 		return (-1);
5984235Smarkfen 
5994235Smarkfen 	if (!nflag) {
6004235Smarkfen 		/*
6014235Smarkfen 		 * Try name->address first.  Assume AF_INET6, and
6024235Smarkfen 		 * get IPV4s, plus IPv6s iff IPv6 is configured.
6034235Smarkfen 		 */
6044235Smarkfen 		hp = getipnodebyname(argv[0], AF_INET6, AI_DEFAULT | AI_ALL,
6054235Smarkfen 		    &hp_errno);
6064235Smarkfen 	} else {
6074235Smarkfen 		/*
6084235Smarkfen 		 * Try a normal address conversion only.  malloc a
6094235Smarkfen 		 * dummy_he_t to construct a fake hostent.  Caller
6104235Smarkfen 		 * will know to free this one using free_he().
6114235Smarkfen 		 */
6124235Smarkfen 		dhp = (dummy_he_t *)malloc(sizeof (dummy_he_t));
6134235Smarkfen 		addr1 = (char *)malloc(sizeof (struct in6_addr));
6144235Smarkfen 		if (inet_pton(AF_INET6, argv[0], addr1) == 1) {
6154235Smarkfen 			dhp->he.h_addr_list = dhp->addtl;
6164235Smarkfen 			dhp->addtl[0] = addr1;
6174235Smarkfen 			dhp->addtl[1] = NULL;
6184235Smarkfen 			hp = &dhp->he;
6194235Smarkfen 			dhp->he.h_addrtype = AF_INET6;
6204235Smarkfen 			dhp->he.h_length = sizeof (struct in6_addr);
6214235Smarkfen 		} else if (inet_pton(AF_INET, argv[0], addr1) == 1) {
6224235Smarkfen 			dhp->he.h_addr_list = dhp->addtl;
6234235Smarkfen 			dhp->addtl[0] = addr1;
6244235Smarkfen 			dhp->addtl[1] = NULL;
6254235Smarkfen 			hp = &dhp->he;
6264235Smarkfen 			dhp->he.h_addrtype = AF_INET;
6274235Smarkfen 			dhp->he.h_length = sizeof (struct in_addr);
6284235Smarkfen 		} else {
6294235Smarkfen 			hp = NULL;
6304235Smarkfen 		}
6314235Smarkfen 	}
6324235Smarkfen 
6334235Smarkfen 	*hpp = hp;
6344235Smarkfen 
6354235Smarkfen 	if (hp == NULL) {
6364235Smarkfen 		message(gettext("Unknown address %s."), argv[0]);
6374235Smarkfen 		return (-1);
6384235Smarkfen 	}
6394235Smarkfen 
6404235Smarkfen 	return (1);
6414235Smarkfen }
6424235Smarkfen 
6434235Smarkfen /*
6444235Smarkfen  * Free a dummy_he_t structure that was malloc'd in parse_addr().
6454235Smarkfen  * Unfortunately, callers of parse_addr don't want to know about
6464235Smarkfen  * dummy_he_t structs, so all they have is a pointer to the struct
6474235Smarkfen  * hostent; so that's what's passed in.  To manage this, we make
6484235Smarkfen  * the assumption that the struct hostent is the first field in
6494235Smarkfen  * the dummy_he_t, and therefore a pointer to it is a pointer to
6504235Smarkfen  * the dummy_he_t.
6514235Smarkfen  */
6524235Smarkfen static void
6534235Smarkfen free_he(struct hostent *hep)
6544235Smarkfen {
6554235Smarkfen 	dummy_he_t	*p = (dummy_he_t *)hep;
6564235Smarkfen 
6574235Smarkfen 	assert(p != NULL);
6584235Smarkfen 
6594235Smarkfen 	if (p->addtl[0])
6604235Smarkfen 		free(p->addtl[0]);
6614235Smarkfen 	if (p->addtl[1])
6624235Smarkfen 		free(p->addtl[1]);
6634235Smarkfen 
6644235Smarkfen 	free(p);
6654235Smarkfen }
6664235Smarkfen 
6674235Smarkfen #define	FREE_HE(x) \
6684235Smarkfen 	if (nflag) \
6694235Smarkfen 		free_he(x); \
6704235Smarkfen 	else \
6714235Smarkfen 		freehostent(x)
6724235Smarkfen 
6734235Smarkfen static void
6744235Smarkfen headdr2sa(char *hea, struct sockaddr_storage *sa, int len)
6754235Smarkfen {
6764235Smarkfen 	struct sockaddr_in	*sin;
6774235Smarkfen 	struct sockaddr_in6	*sin6;
6784235Smarkfen 
6794235Smarkfen 	if (len == sizeof (struct in6_addr)) {
6804235Smarkfen 		/* LINTED E_BAD_PTR_CAST_ALIGN */
6814235Smarkfen 		if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)hea)) {
6824235Smarkfen 			sin = (struct sockaddr_in *)sa;
6834235Smarkfen 			(void) memset(sin, 0, sizeof (*sin));
6844235Smarkfen 			/* LINTED E_BAD_PTR_CAST_ALIGN */
6854235Smarkfen 			IN6_V4MAPPED_TO_INADDR((struct in6_addr *)hea,
6864235Smarkfen 			    &sin->sin_addr);
6874235Smarkfen 			sin->sin_family = AF_INET;
6884235Smarkfen 		} else {
6894235Smarkfen 			sin6 = (struct sockaddr_in6 *)sa;
6904235Smarkfen 			(void) memset(sin6, 0, sizeof (*sin6));
6914235Smarkfen 			(void) memcpy(&sin6->sin6_addr, hea,
6924235Smarkfen 			    sizeof (struct in6_addr));
6934235Smarkfen 			sin6->sin6_family = AF_INET6;
6944235Smarkfen 		}
6954235Smarkfen 	} else {
6964235Smarkfen 		sin = (struct sockaddr_in *)sa;
6974235Smarkfen 		(void) memset(sin, 0, sizeof (*sin));
6984235Smarkfen 		(void) memcpy(&sin->sin_addr, hea, sizeof (struct in_addr));
6994235Smarkfen 		sin->sin_family = AF_INET;
7004235Smarkfen 	}
7014235Smarkfen }
7024235Smarkfen 
7034235Smarkfen /*
7044235Smarkfen  * The possible ident-type keywords that might be used on the command
7054235Smarkfen  * line.  This is a superset of the ones supported by ipseckey, those
7064235Smarkfen  * in the ike config file, and those in ike.preshared.
7074235Smarkfen  */
7084235Smarkfen static keywdtab_t	idtypes[] = {
7094235Smarkfen 	/* ip, ipv4, and ipv6 are valid for preshared keys... */
7104235Smarkfen 	{SADB_IDENTTYPE_RESERVED,	"ip"},
7114235Smarkfen 	{SADB_IDENTTYPE_RESERVED,	"ipv4"},
7124235Smarkfen 	{SADB_IDENTTYPE_RESERVED,	"ipv6"},
7134235Smarkfen 	{SADB_IDENTTYPE_PREFIX,		"prefix"},
7144235Smarkfen 	{SADB_IDENTTYPE_PREFIX,		"ipv4-prefix"},
7154235Smarkfen 	{SADB_IDENTTYPE_PREFIX,		"ipv6-prefix"},
7164235Smarkfen 	{SADB_IDENTTYPE_PREFIX,		"subnet"},
7174235Smarkfen 	{SADB_IDENTTYPE_PREFIX,		"subnetv4"},
7184235Smarkfen 	{SADB_IDENTTYPE_PREFIX,		"subnetv6"},
7194235Smarkfen 	{SADB_IDENTTYPE_FQDN,		"fqdn"},
7204235Smarkfen 	{SADB_IDENTTYPE_FQDN,		"dns"},
7214235Smarkfen 	{SADB_IDENTTYPE_FQDN,		"domain"},
7224235Smarkfen 	{SADB_IDENTTYPE_FQDN,		"domainname"},
7234235Smarkfen 	{SADB_IDENTTYPE_USER_FQDN,	"user_fqdn"},
7244235Smarkfen 	{SADB_IDENTTYPE_USER_FQDN,	"mbox"},
7254235Smarkfen 	{SADB_IDENTTYPE_USER_FQDN,	"mailbox"},
7264235Smarkfen 	{SADB_X_IDENTTYPE_DN,		"dn"},
7274235Smarkfen 	{SADB_X_IDENTTYPE_DN,		"asn1dn"},
7284235Smarkfen 	{SADB_X_IDENTTYPE_GN,		"gn"},
7294235Smarkfen 	{SADB_X_IDENTTYPE_GN,		"asn1gn"},
7304235Smarkfen 	{SADB_X_IDENTTYPE_ADDR_RANGE,	"ipv4-range"},
7314235Smarkfen 	{SADB_X_IDENTTYPE_ADDR_RANGE,	"ipv6-range"},
7324235Smarkfen 	{SADB_X_IDENTTYPE_ADDR_RANGE,	"rangev4"},
7334235Smarkfen 	{SADB_X_IDENTTYPE_ADDR_RANGE,	"rangev6"},
7344235Smarkfen 	{SADB_X_IDENTTYPE_KEY_ID,	"keyid"},
7354235Smarkfen 	{NULL,	0}
7364235Smarkfen };
7374235Smarkfen 
7384235Smarkfen static int
7394235Smarkfen parse_idtype(char *type, uint16_t *idnum)
7404235Smarkfen {
7414235Smarkfen 	keywdtab_t	*idp;
7424235Smarkfen 
7434235Smarkfen 	if (type == NULL)
7444235Smarkfen 		return (-1);
7454235Smarkfen 
7464235Smarkfen 	for (idp = idtypes; idp->kw_str != NULL; idp++) {
7474235Smarkfen 		if (strcasecmp(idp->kw_str, type) == 0) {
7484235Smarkfen 			if (idnum != NULL)
7494235Smarkfen 				*idnum = idp->kw_tag;
7504235Smarkfen 			return (1);
7514235Smarkfen 		}
7524235Smarkfen 	}
7534235Smarkfen 
7544235Smarkfen 	return (-1);
7554235Smarkfen }
7564235Smarkfen 
7574235Smarkfen /*
7584235Smarkfen  * The sadb_ident_t is malloc'd, since its length varies;
7594235Smarkfen  * so the caller must free() it when done with the data.
7604235Smarkfen  */
7614235Smarkfen static int
7624235Smarkfen parse_ident(int argc, char **argv, sadb_ident_t **idpp)
7634235Smarkfen {
7644235Smarkfen 	int		alloclen, consumed;
7654235Smarkfen 	sadb_ident_t	*idp;
7664235Smarkfen 	if ((argc < 2) || (argv == NULL) || (argv[0] == NULL) ||
7674235Smarkfen 	    (argv[1] == NULL))
7684235Smarkfen 		return (-1);
7694235Smarkfen 
7704235Smarkfen 	alloclen = sizeof (sadb_ident_t) + IKEDOORROUNDUP(strlen(argv[1]) + 1);
7714235Smarkfen 	*idpp = idp = (sadb_ident_t *)malloc(alloclen);
7724235Smarkfen 	if (idp == NULL)
7734235Smarkfen 		Bail("parsing identity");
7744235Smarkfen 
7754235Smarkfen 	if ((consumed = parse_idtype(argv[0], &idp->sadb_ident_type)) < 0) {
7764235Smarkfen 		message(gettext("unknown identity type %s."), argv[0]);
7774235Smarkfen 		return (-1);
7784235Smarkfen 	}
7794235Smarkfen 
7804235Smarkfen 	idp->sadb_ident_len = SADB_8TO64(alloclen);
7814235Smarkfen 	idp->sadb_ident_reserved = 0;
7824235Smarkfen 	idp->sadb_ident_id = 0;
7834235Smarkfen 
7844235Smarkfen 	/* now copy in identity param */
7854235Smarkfen 	(void) strlcpy((char *)(idp + 1), argv[1],
7864235Smarkfen 	    alloclen - (sizeof (sadb_ident_t)));
7874235Smarkfen 
7884235Smarkfen 	return (++consumed);
7894235Smarkfen }
7904235Smarkfen 
7914235Smarkfen static int
7924235Smarkfen parse_cky(int argc, char **argv, uint64_t *ckyp)
7934235Smarkfen {
7944235Smarkfen 	u_longlong_t	arg;
7954235Smarkfen 
7964235Smarkfen 	if ((argc < 1) || (argv[0] == NULL))
7974235Smarkfen 		return (-1);
7984235Smarkfen 
7994235Smarkfen 	errno = 0;
8004235Smarkfen 	arg = strtoull(argv[0], NULL, 0);
8014235Smarkfen 	if (errno != 0) {
8024235Smarkfen 		message(gettext("failed to parse cookie %s."), argv[0]);
8034235Smarkfen 		return (-1);
8044235Smarkfen 	}
8054235Smarkfen 
8064235Smarkfen 	*ckyp = (uint64_t)arg;
8074235Smarkfen 
8084235Smarkfen 	return (1);
8094235Smarkfen }
8104235Smarkfen 
8114235Smarkfen static int
8124235Smarkfen parse_addr_pr(int argc, char **argv, struct hostent **h1pp,
8134235Smarkfen 	struct hostent **h2pp)
8144235Smarkfen {
8154235Smarkfen 	int	rtn, consumed = 0;
8164235Smarkfen 
8174235Smarkfen 	if ((rtn = parse_addr(argc, argv, h1pp)) < 0) {
8184235Smarkfen 		return (-1);
8194235Smarkfen 	}
8204235Smarkfen 	consumed = rtn;
8214235Smarkfen 	argc -= rtn;
8224235Smarkfen 	argv += rtn;
8234235Smarkfen 
8244235Smarkfen 	if ((rtn = parse_addr(argc, argv, h2pp)) < 0) {
8254235Smarkfen 		FREE_HE(*h1pp);
8264235Smarkfen 		return (-1);
8274235Smarkfen 	}
8284235Smarkfen 	consumed += rtn;
8294235Smarkfen 
8304235Smarkfen 	return (consumed);
8314235Smarkfen }
8324235Smarkfen 
8334235Smarkfen /*
8344235Smarkfen  * The sadb_ident_ts are malloc'd, since their length varies;
8354235Smarkfen  * so the caller must free() them when done with the data.
8364235Smarkfen  */
8374235Smarkfen static int
8384235Smarkfen parse_ident_pr(int argc, char **argv, sadb_ident_t **id1pp,
8394235Smarkfen     sadb_ident_t **id2pp)
8404235Smarkfen {
8414235Smarkfen 	int	rtn, consumed = 0;
8424235Smarkfen 
8434235Smarkfen 	if ((rtn = parse_ident(argc, argv, id1pp)) < 0) {
8444235Smarkfen 		return (-1);
8454235Smarkfen 	}
8464235Smarkfen 	consumed = rtn;
8474235Smarkfen 	argc -= rtn;
8484235Smarkfen 	argv += rtn;
8494235Smarkfen 
8504235Smarkfen 	(*id1pp)->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC;
8514235Smarkfen 
8524235Smarkfen 	if ((rtn = parse_ident(argc, argv, id2pp)) < 0) {
8534235Smarkfen 		free(*id1pp);
8544235Smarkfen 		return (-1);
8554235Smarkfen 	}
8564235Smarkfen 	consumed += rtn;
8574235Smarkfen 
8584235Smarkfen 	(*id2pp)->sadb_ident_exttype = SADB_EXT_IDENTITY_DST;
8594235Smarkfen 
8604235Smarkfen 	return (consumed);
8614235Smarkfen }
8624235Smarkfen 
8634235Smarkfen static int
8644235Smarkfen parse_cky_pr(int argc, char **argv, ike_cky_pr_t *cpr)
8654235Smarkfen {
8664235Smarkfen 	int	rtn, consumed = 0;
8674235Smarkfen 
8684235Smarkfen 	if ((rtn = parse_cky(argc, argv, &cpr->cky_i)) < 0) {
8694235Smarkfen 		return (-1);
8704235Smarkfen 	}
8714235Smarkfen 	consumed = rtn;
8724235Smarkfen 	argc -= rtn;
8734235Smarkfen 	argv += rtn;
8744235Smarkfen 
8754235Smarkfen 	if ((rtn = parse_cky(argc, argv, &cpr->cky_r)) < 0) {
8764235Smarkfen 		return (-1);
8774235Smarkfen 	}
8784235Smarkfen 	consumed += rtn;
8794235Smarkfen 
8804235Smarkfen 	return (consumed);
8814235Smarkfen }
8824235Smarkfen 
8834235Smarkfen /*
8844235Smarkfen  * Preshared key field types...used for parsing preshared keys that
8854235Smarkfen  * have been entered on the command line.  The code to parse preshared
8864235Smarkfen  * keys (parse_ps, parse_key, parse_psfldid, parse_ikmtype, ...) is
8874235Smarkfen  * mostly duplicated from in.iked's readps.c.
8884235Smarkfen  */
8894235Smarkfen #define	PSFLD_LOCID	1
8904235Smarkfen #define	PSFLD_LOCIDTYPE	2
8914235Smarkfen #define	PSFLD_REMID	3
8924235Smarkfen #define	PSFLD_REMIDTYPE	4
8934235Smarkfen #define	PSFLD_MODE	5
8944235Smarkfen #define	PSFLD_KEY	6
8954235Smarkfen 
8964235Smarkfen static keywdtab_t	psfldtypes[] = {
8974235Smarkfen 	{PSFLD_LOCID,		"localid"},
8984235Smarkfen 	{PSFLD_LOCIDTYPE,	"localidtype"},
8994235Smarkfen 	{PSFLD_REMID,		"remoteid"},
9004235Smarkfen 	{PSFLD_REMIDTYPE,	"remoteidtype"},
9014235Smarkfen 	{PSFLD_MODE,		"ike_mode"},
9024235Smarkfen 	{PSFLD_KEY,		"key"},
9034235Smarkfen 	{NULL,	0}
9044235Smarkfen };
9054235Smarkfen 
9064235Smarkfen static int
9074235Smarkfen parse_psfldid(char *type, uint16_t *idnum)
9084235Smarkfen {
9094235Smarkfen 	keywdtab_t	*pfp;
9104235Smarkfen 
9114235Smarkfen 	if (type == NULL)
9124235Smarkfen 		return (-1);
9134235Smarkfen 
9144235Smarkfen 	for (pfp = psfldtypes; pfp->kw_str != NULL; pfp++) {
9154235Smarkfen 		if (strcasecmp(pfp->kw_str, type) == 0) {
9164235Smarkfen 			if (idnum != NULL)
9174235Smarkfen 				*idnum = pfp->kw_tag;
9184235Smarkfen 			return (1);
9194235Smarkfen 		}
9204235Smarkfen 	}
9214235Smarkfen 
9224235Smarkfen 	return (-1);
9234235Smarkfen }
9244235Smarkfen 
9254235Smarkfen static keywdtab_t	ikemodes[] = {
9264235Smarkfen 	{IKE_XCHG_IDENTITY_PROTECT,	"main"},
9274235Smarkfen 	{IKE_XCHG_AGGRESSIVE,		"aggressive"},
9284235Smarkfen 	{IKE_XCHG_IP_AND_AGGR,		"both"},
9294235Smarkfen 	{NULL,	0}
9304235Smarkfen };
9314235Smarkfen 
9324235Smarkfen static int
9334235Smarkfen parse_ikmtype(char *mode, uint16_t *modenum)
9344235Smarkfen {
9354235Smarkfen 	keywdtab_t	*ikmp;
9364235Smarkfen 
9374235Smarkfen 	if (mode == NULL)
9384235Smarkfen 		return (-1);
9394235Smarkfen 
9404235Smarkfen 	for (ikmp = ikemodes; ikmp->kw_str != NULL; ikmp++) {
9414235Smarkfen 		if (strcasecmp(ikmp->kw_str, mode) == 0) {
9424235Smarkfen 			if (modenum != NULL)
9434235Smarkfen 				*modenum = ikmp->kw_tag;
9444235Smarkfen 			return (1);
9454235Smarkfen 		}
9464235Smarkfen 	}
9474235Smarkfen 
9484235Smarkfen 	return (-1);
9494235Smarkfen }
9504235Smarkfen 
9514235Smarkfen #define	hd2num(hd) (((hd) >= '0' && (hd) <= '9') ? ((hd) - '0') : \
9524235Smarkfen 	(((hd) >= 'a' && (hd) <= 'f') ? ((hd) - 'a' + 10) : ((hd) - 'A' + 10)))
9534235Smarkfen 
9544235Smarkfen static uint8_t *
9554235Smarkfen parse_key(char *input, uint_t *keybuflen, uint_t *lbits)
9564235Smarkfen {
9574235Smarkfen 	uint8_t	*keyp, *keybufp;
9584235Smarkfen 	uint_t	i, hexlen = 0, bits, alloclen;
9594235Smarkfen 
9604235Smarkfen 	for (i = 0; input[i] != '\0' && input[i] != '/'; i++)
9614235Smarkfen 		hexlen++;
9624235Smarkfen 
9634235Smarkfen 	if (input[i] == '\0') {
9644235Smarkfen 		bits = 0;
9654235Smarkfen 	} else {
9664235Smarkfen 		/* Have /nn. */
9674235Smarkfen 		input[i] = '\0';
9684235Smarkfen 		if (sscanf((input + i + 1), "%u", &bits) != 1)
9694235Smarkfen 			return (NULL);
9704235Smarkfen 
9714235Smarkfen 		/* hexlen is in nibbles */
9724235Smarkfen 		if (((bits + 3) >> 2) > hexlen)
9734235Smarkfen 			return (NULL);
9744235Smarkfen 
9754235Smarkfen 		/*
9764235Smarkfen 		 * Adjust hexlen down if user gave us too small of a bit
9774235Smarkfen 		 * count.
9784235Smarkfen 		 */
9794235Smarkfen 		if ((hexlen << 2) > bits + 3) {
9804235Smarkfen 			hexlen = (bits + 3) >> 2;
9814235Smarkfen 			input[hexlen] = '\0';
9824235Smarkfen 		}
9834235Smarkfen 	}
9844235Smarkfen 
9854235Smarkfen 	/*
9864235Smarkfen 	 * Allocate.  Remember, hexlen is in nibbles.
9874235Smarkfen 	 */
9884235Smarkfen 
9894235Smarkfen 	alloclen = (hexlen/2 + (hexlen & 0x1));
9904235Smarkfen 	keyp = malloc(alloclen);
9914235Smarkfen 
9924235Smarkfen 	if (keyp == NULL)
9934235Smarkfen 		return (NULL);
9944235Smarkfen 
9954235Smarkfen 	keybufp = keyp;
9964235Smarkfen 	*keybuflen = alloclen;
9974235Smarkfen 	if (bits == 0)
9984235Smarkfen 		*lbits = (hexlen + (hexlen & 0x1)) << 2;
9994235Smarkfen 	else
10004235Smarkfen 		*lbits = bits;
10014235Smarkfen 
10024235Smarkfen 	/*
10034235Smarkfen 	 * Read in nibbles.  Read in odd-numbered as shifted high.
10044235Smarkfen 	 * (e.g. 123 becomes 0x1230).
10054235Smarkfen 	 */
10064235Smarkfen 	for (i = 0; input[i] != '\0'; i += 2) {
10074235Smarkfen 		boolean_t second = (input[i + 1] != '\0');
10084235Smarkfen 
10094235Smarkfen 		if (!isxdigit(input[i]) ||
10104235Smarkfen 		    (!isxdigit(input[i + 1]) && second)) {
10114235Smarkfen 			free(keyp);
10124235Smarkfen 			return (NULL);
10134235Smarkfen 		}
10144235Smarkfen 		*keyp = (hd2num(input[i]) << 4);
10154235Smarkfen 		if (second)
10164235Smarkfen 			*keyp |= hd2num(input[i + 1]);
10174235Smarkfen 		else
10184235Smarkfen 			break; /* out of for loop. */
10194235Smarkfen 		keyp++;
10204235Smarkfen 	}
10214235Smarkfen 
10224235Smarkfen 	/* zero the remaining bits if we're a non-octet amount. */
10234235Smarkfen 	if (bits & 0x7)
10244235Smarkfen 		*((input[i] == '\0') ? keyp - 1 : keyp) &=
10254235Smarkfen 		    0xff << (8 - (bits & 0x7));
10264235Smarkfen 	return (keybufp);
10274235Smarkfen }
10284235Smarkfen 
10294235Smarkfen /*
10304235Smarkfen  * the ike_ps_t struct (plus trailing data) will be allocated here,
10314235Smarkfen  * so it will need to be freed by the caller.
10324235Smarkfen  */
10334235Smarkfen static int
10344235Smarkfen parse_ps(int argc, char **argv, ike_ps_t **presharedpp, int *len)
10354235Smarkfen {
10364235Smarkfen 	uint_t		c = 0, locidlen, remidlen, keylen, keybits;
10374235Smarkfen 	uint_t		a_locidtotal = 0, a_remidtotal = 0;
10384235Smarkfen 	char		*locid, *remid;
10394235Smarkfen 	uint8_t		*keyp = NULL;
10404235Smarkfen 	uint16_t	fldid, locidtype, remidtype, mtype;
10414235Smarkfen 	struct hostent	*loche = NULL, *remhe = NULL;
10424235Smarkfen 	ike_ps_t	*psp = NULL;
10434235Smarkfen 	sadb_ident_t	*sidp;
10444235Smarkfen 	boolean_t	whacked = B_FALSE;
10454235Smarkfen 
10464235Smarkfen 	if ((argv[c] == NULL) || (argv[c][0] != '{'))
10474235Smarkfen 		return (-1);
10484235Smarkfen 	if (argv[c][1] != 0) {
10494235Smarkfen 		/* no space between '{' and first token */
10504235Smarkfen 		argv[c]++;
10514235Smarkfen 	} else {
10524235Smarkfen 		c++;
10534235Smarkfen 	}
10544235Smarkfen 	if ((argv[argc - 1][strlen(argv[argc - 1]) - 1] == '}') &&
10554235Smarkfen 	    (argv[argc - 1][0] != '}')) {
10564235Smarkfen 		/*
10574235Smarkfen 		 * whack '}' without a space before it or parsers break.
10584235Smarkfen 		 * Remember this trailing character for later
10594235Smarkfen 		 */
10604235Smarkfen 		argv[argc - 1][strlen(argv[argc - 1]) - 1] = '\0';
10614235Smarkfen 		whacked = B_TRUE;
10624235Smarkfen 	}
10634235Smarkfen 
10644235Smarkfen 	while ((c < argc) && (argv[c] != NULL) && (argv[c][0] != '}')) {
10654235Smarkfen 		if ((argv[c + 1] == NULL) || (argv[c + 1][0] == '}'))
10664235Smarkfen 			goto bail;
10674235Smarkfen 		if (parse_psfldid(argv[c++], &fldid) < 0)
10684235Smarkfen 			goto bail;
10694235Smarkfen 		switch (fldid) {
10704235Smarkfen 		case PSFLD_LOCID:
10714235Smarkfen 			locid = argv[c++];
10724235Smarkfen 			locidlen = strlen(locid) + 1;
10734235Smarkfen 			break;
10744235Smarkfen 		case PSFLD_LOCIDTYPE:
10754235Smarkfen 			if (parse_idtype(argv[c++], &locidtype) < 0)
10764235Smarkfen 				goto bail;
10774235Smarkfen 			break;
10784235Smarkfen 		case PSFLD_REMID:
10794235Smarkfen 			remid = argv[c++];
10804235Smarkfen 			remidlen = strlen(remid) + 1;
10814235Smarkfen 			break;
10824235Smarkfen 		case PSFLD_REMIDTYPE:
10834235Smarkfen 			if (parse_idtype(argv[c++], &remidtype) < 0)
10844235Smarkfen 				goto bail;
10854235Smarkfen 			break;
10864235Smarkfen 		case PSFLD_MODE:
10874235Smarkfen 			if (parse_ikmtype(argv[c++], &mtype) < 0)
10884235Smarkfen 				goto bail;
10894235Smarkfen 			break;
10904235Smarkfen 		case PSFLD_KEY:
10914235Smarkfen 			keyp  = parse_key(argv[c++], &keylen, &keybits);
10924235Smarkfen 			if (keyp == NULL)
10934235Smarkfen 				goto bail;
10944235Smarkfen 			break;
10954235Smarkfen 		}
10964235Smarkfen 	}
10974235Smarkfen 
10984235Smarkfen 	/* Make sure the line was terminated with '}' */
10994235Smarkfen 	if (argv[c] == NULL) {
11004235Smarkfen 		if (!whacked)
11014235Smarkfen 			goto bail;
11024235Smarkfen 	} else if (argv[c][0] != '}') {
11034235Smarkfen 		goto bail;
11044235Smarkfen 	}
11054235Smarkfen 
11064235Smarkfen 	/*
11074235Smarkfen 	 * make sure we got all the required fields.  If no idtype, assume
11084235Smarkfen 	 * ip addr; if that translation fails, we'll catch the error then.
11094235Smarkfen 	 */
11104235Smarkfen 	if (locid == NULL || remid == NULL || keyp == NULL || mtype == 0)
11114235Smarkfen 		goto bail;
11124235Smarkfen 
11134235Smarkfen 	/* figure out the size buffer we need */
11144235Smarkfen 	*len = sizeof (ike_ps_t);
11154235Smarkfen 	if (locidtype != SADB_IDENTTYPE_RESERVED) {
11164235Smarkfen 		a_locidtotal = IKEDOORROUNDUP(sizeof (sadb_ident_t) + locidlen);
11174235Smarkfen 		*len += a_locidtotal;
11184235Smarkfen 	}
11194235Smarkfen 	if (remidtype != SADB_IDENTTYPE_RESERVED) {
11204235Smarkfen 		a_remidtotal = IKEDOORROUNDUP(sizeof (sadb_ident_t) + remidlen);
11214235Smarkfen 		*len += a_remidtotal;
11224235Smarkfen 	}
11234235Smarkfen 	*len += keylen;
11244235Smarkfen 
11254235Smarkfen 	psp = malloc(*len);
11264235Smarkfen 	if (psp == NULL)
11274235Smarkfen 		goto bail;
11284235Smarkfen 	(void) memset(psp, 0, *len);
11294235Smarkfen 
11304235Smarkfen 	psp->ps_ike_mode = mtype;
11314235Smarkfen 
11324235Smarkfen 	psp->ps_localid_off = sizeof (ike_ps_t);
11334235Smarkfen 	if (locidtype == SADB_IDENTTYPE_RESERVED) {
11344235Smarkfen 		/*
11354235Smarkfen 		 * this is an ip address, store in the sockaddr field;
11364235Smarkfen 		 * we won't use an sadb_ident_t.
11374235Smarkfen 		 */
11384235Smarkfen 		psp->ps_localid_len = 0;
11394235Smarkfen 		if (parse_addr(1, &locid, &loche) < 0)
11404235Smarkfen 			goto bail;
11414235Smarkfen 		if (loche->h_addr_list[1] != NULL) {
11424235Smarkfen 			message(gettext("preshared key identifier cannot "
11434235Smarkfen 			    "match multiple IP addresses"));
11444235Smarkfen 			goto bail;
11454235Smarkfen 		}
11464235Smarkfen 		headdr2sa(loche->h_addr_list[0], &psp->ps_ipaddrs.loc_addr,
11474235Smarkfen 		    loche->h_length);
11484235Smarkfen 		FREE_HE(loche);
11494235Smarkfen 	} else {
11504235Smarkfen 		psp->ps_localid_len = sizeof (sadb_ident_t) + locidlen;
11514235Smarkfen 		sidp = (sadb_ident_t *)((int)psp + psp->ps_localid_off);
11524235Smarkfen 		sidp->sadb_ident_len = psp->ps_localid_len;
11534235Smarkfen 		sidp->sadb_ident_type = locidtype;
11544235Smarkfen 		(void) strlcpy((char *)(sidp + 1), locid, a_locidtotal);
11554235Smarkfen 	}
11564235Smarkfen 
11574235Smarkfen 	psp->ps_remoteid_off = psp->ps_localid_off + a_locidtotal;
11584235Smarkfen 	if (remidtype == SADB_IDENTTYPE_RESERVED) {
11594235Smarkfen 		/*
11604235Smarkfen 		 * this is an ip address, store in the sockaddr field;
11614235Smarkfen 		 * we won't use an sadb_ident_t.
11624235Smarkfen 		 */
11634235Smarkfen 		psp->ps_remoteid_len = 0;
11644235Smarkfen 		if (parse_addr(1, &remid, &remhe) < 0)
11654235Smarkfen 			goto bail;
11664235Smarkfen 		if (remhe->h_addr_list[1] != NULL) {
11674235Smarkfen 			message(gettext("preshared key identifier cannot "
11684235Smarkfen 			    "match multiple IP addresses"));
11694235Smarkfen 			goto bail;
11704235Smarkfen 		}
11714235Smarkfen 		headdr2sa(remhe->h_addr_list[0], &psp->ps_ipaddrs.rem_addr,
11724235Smarkfen 		    remhe->h_length);
11734235Smarkfen 		FREE_HE(remhe);
11744235Smarkfen 	} else {
11754235Smarkfen 		/* make sure we have at least 16-bit alignment */
11764235Smarkfen 		if (remidlen & 0x1)
11774235Smarkfen 			remidlen++;
11784235Smarkfen 		psp->ps_remoteid_len = sizeof (sadb_ident_t) + remidlen;
11794235Smarkfen 		sidp = (sadb_ident_t *)((int)psp + psp->ps_remoteid_off);
11804235Smarkfen 		sidp->sadb_ident_len = psp->ps_remoteid_len;
11814235Smarkfen 		sidp->sadb_ident_type = remidtype;
11824235Smarkfen 		(void) strlcpy((char *)(sidp + 1), remid, a_remidtotal);
11834235Smarkfen 	}
11844235Smarkfen 
11854235Smarkfen 	psp->ps_key_off = psp->ps_remoteid_off + a_remidtotal;
11864235Smarkfen 	psp->ps_key_len = keylen;
11874235Smarkfen 	psp->ps_key_bits = keybits;
11884235Smarkfen 	(void) memcpy((uint8_t *)((int)psp + psp->ps_key_off), keyp, keylen);
11894235Smarkfen 
11904235Smarkfen 	*presharedpp = psp;
11914235Smarkfen 
11924235Smarkfen 	return (c);
11934235Smarkfen 
11944235Smarkfen bail:
11954235Smarkfen 	if (loche != NULL)
11964235Smarkfen 		FREE_HE(loche);
11974235Smarkfen 	if (remhe != NULL)
11984235Smarkfen 		FREE_HE(remhe);
11994235Smarkfen 	if (keyp != NULL)
12004235Smarkfen 		free(keyp);
12014235Smarkfen 	if (psp != NULL)
12024235Smarkfen 		free(psp);
12034235Smarkfen 
12044235Smarkfen 	*presharedpp = NULL;
12054235Smarkfen 
12064235Smarkfen 	return (-1);
12074235Smarkfen }
12084235Smarkfen 
12094235Smarkfen /*
12104235Smarkfen  * Printing functions
12114235Smarkfen  *
12124235Smarkfen  * A potential point of confusion here is that the ikeadm-specific string-
12134235Smarkfen  * producing functions do not match the ipsec_util.c versions in style: the
12144235Smarkfen  * ikeadm-specific functions return a string (and are named foostr), while
12154235Smarkfen  * the ipsec_util.c functions actually print the string to the file named
12164235Smarkfen  * in the second arg to the function (and are named dump_foo).
12174235Smarkfen  *
12187421SDaniel.Anderson@Sun.COM  * Localization for ikeadm seems more straightforward when complete
12197421SDaniel.Anderson@Sun.COM  * phrases are translated rather than: a part of a phrase, a call to
12207421SDaniel.Anderson@Sun.COM  * dump_foo(), and more of the phrase.  It could also accommodate
12217421SDaniel.Anderson@Sun.COM  * non-English grammar more easily.
12224235Smarkfen  */
12234235Smarkfen 
12244235Smarkfen static char *
12254235Smarkfen errstr(int err)
12264235Smarkfen {
12274235Smarkfen 	static char	rtn[MAXLINESIZE];
12284235Smarkfen 
12294235Smarkfen 	switch (err) {
12304235Smarkfen 	case IKE_ERR_NO_OBJ:
12314235Smarkfen 		return (gettext("No data returned"));
12324235Smarkfen 	case IKE_ERR_NO_DESC:
12334235Smarkfen 		return (gettext("No destination provided"));
12344235Smarkfen 	case IKE_ERR_ID_INVALID:
12354235Smarkfen 		return (gettext("Id info invalid"));
12364235Smarkfen 	case IKE_ERR_LOC_INVALID:
12374235Smarkfen 		return (gettext("Destination invalid"));
12384235Smarkfen 	case IKE_ERR_CMD_INVALID:
12394235Smarkfen 		return (gettext("Command invalid"));
12404235Smarkfen 	case IKE_ERR_DATA_INVALID:
12414235Smarkfen 		return (gettext("Supplied data invalid"));
12424235Smarkfen 	case IKE_ERR_CMD_NOTSUP:
12434235Smarkfen 		return (gettext("Unknown command"));
12444235Smarkfen 	case IKE_ERR_REQ_INVALID:
12454235Smarkfen 		return (gettext("Request invalid"));
12464235Smarkfen 	case IKE_ERR_NO_PRIV:
12474235Smarkfen 		return (gettext("Not allowed at current privilege level"));
12488596SPaul.Wernau@Sun.COM 	case IKE_ERR_NO_AUTH:
12498596SPaul.Wernau@Sun.COM 		return (gettext("User not authorized"));
12504235Smarkfen 	case IKE_ERR_SYS_ERR:
12514235Smarkfen 		return (gettext("System error"));
12524235Smarkfen 	case IKE_ERR_DUP_IGNORED:
12534235Smarkfen 		return (gettext("One or more duplicate entries ignored"));
12548596SPaul.Wernau@Sun.COM 	case IKE_ERR_NO_TOKEN:
12558596SPaul.Wernau@Sun.COM 		return (gettext(
12568596SPaul.Wernau@Sun.COM 		    "token login failed or no objects on device"));
12578596SPaul.Wernau@Sun.COM 	case IKE_ERR_IN_PROGRESS:
12588596SPaul.Wernau@Sun.COM 		return (gettext(
12598596SPaul.Wernau@Sun.COM 		    "Duplicate operation already in progress"));
12608596SPaul.Wernau@Sun.COM 	case IKE_ERR_NO_MEM:
12618596SPaul.Wernau@Sun.COM 		return (gettext(
12628596SPaul.Wernau@Sun.COM 		    "Insufficient memory"));
12634235Smarkfen 	default:
12644235Smarkfen 		(void) snprintf(rtn, MAXLINESIZE,
12654235Smarkfen 		    gettext("<unknown error %d>"), err);
12664235Smarkfen 		return (rtn);
12674235Smarkfen 	}
12684235Smarkfen }
12694235Smarkfen 
12704235Smarkfen static char *
12714235Smarkfen dbgstr(int bit)
12724235Smarkfen {
12734235Smarkfen 	static char	rtn[MAXLINESIZE];
12744235Smarkfen 
12754235Smarkfen 	switch (bit) {
12764235Smarkfen 	case D_CERT:
12774235Smarkfen 		return (gettext("Certificate management"));
12784235Smarkfen 	case D_KEY:
12794235Smarkfen 		return (gettext("Key management"));
12804235Smarkfen 	case D_OP:
12814235Smarkfen 		return (gettext("Operational"));
12824235Smarkfen 	case D_P1:
12834235Smarkfen 		return (gettext("Phase 1 SA creation"));
12844235Smarkfen 	case D_P2:
12854235Smarkfen 		return (gettext("Phase 2 SA creation"));
12864235Smarkfen 	case D_PFKEY:
12874235Smarkfen 		return (gettext("PF_KEY interface"));
12884235Smarkfen 	case D_POL:
12894235Smarkfen 		return (gettext("Policy management"));
12904235Smarkfen 	case D_PROP:
12914235Smarkfen 		return (gettext("Proposal construction"));
12924235Smarkfen 	case D_DOOR:
12934235Smarkfen 		return (gettext("Door interface"));
12944235Smarkfen 	case D_CONFIG:
12954235Smarkfen 		return (gettext("Config file processing"));
129610934Ssommerfeld@sun.com 	case D_LABEL:
129710934Ssommerfeld@sun.com 		return (gettext("MAC label processing"));
12984235Smarkfen 	default:
12994235Smarkfen 		(void) snprintf(rtn, MAXLINESIZE,
13004235Smarkfen 		    gettext("<unknown flag 0x%x>"), bit);
13014235Smarkfen 		return (rtn);
13024235Smarkfen 	}
13034235Smarkfen }
13044235Smarkfen 
13054235Smarkfen static char *
13064235Smarkfen privstr(int priv)
13074235Smarkfen {
13084235Smarkfen 	static char	rtn[MAXLINESIZE];
13094235Smarkfen 
13104235Smarkfen 	switch (priv) {
13114235Smarkfen 	case IKE_PRIV_MINIMUM:
13124235Smarkfen 		return (gettext("base privileges"));
13134235Smarkfen 	case IKE_PRIV_MODKEYS:
13144235Smarkfen 		return (gettext("access to preshared key information"));
13154235Smarkfen 	case IKE_PRIV_KEYMAT:
13164235Smarkfen 		return (gettext("access to keying material"));
13174235Smarkfen 	default:
13184235Smarkfen 		(void) snprintf(rtn, MAXLINESIZE,
13194235Smarkfen 		    gettext("<unknown level %d>"), priv);
13204235Smarkfen 		return (rtn);
13214235Smarkfen 	}
13224235Smarkfen }
13234235Smarkfen 
13244235Smarkfen static char *
13254235Smarkfen xchgstr(int xchg)
13264235Smarkfen {
13274235Smarkfen 	static char	rtn[MAXLINESIZE];
13284235Smarkfen 
13294235Smarkfen 	switch (xchg) {
13304235Smarkfen 	case IKE_XCHG_NONE:
13314235Smarkfen 		return (gettext("<unspecified>"));
13324235Smarkfen 	case IKE_XCHG_BASE:
13334235Smarkfen 		return (gettext("base"));
13344235Smarkfen 	case IKE_XCHG_IDENTITY_PROTECT:
13354235Smarkfen 		return (gettext("main mode (identity protect)"));
13364235Smarkfen 	case IKE_XCHG_AUTH_ONLY:
13374235Smarkfen 		return (gettext("authentication only"));
13384235Smarkfen 	case IKE_XCHG_AGGRESSIVE:
13394235Smarkfen 		return (gettext("aggressive mode"));
13404235Smarkfen 	case IKE_XCHG_IP_AND_AGGR:
13414235Smarkfen 		return (gettext("main and aggressive mode"));
13424235Smarkfen 	case IKE_XCHG_ANY:
13434235Smarkfen 		return (gettext("any mode"));
13444235Smarkfen 	default:
13454235Smarkfen 		(void) snprintf(rtn, MAXLINESIZE,
13464235Smarkfen 		    gettext("<unknown %d>"), xchg);
13474235Smarkfen 		return (rtn);
13484235Smarkfen 	}
13494235Smarkfen }
13504235Smarkfen 
13514235Smarkfen static char *
13524235Smarkfen statestr(int state)
13534235Smarkfen {
13544235Smarkfen 	static char	rtn[MAXLINESIZE];
13554235Smarkfen 
13564235Smarkfen 	switch (state) {
13574235Smarkfen 	case IKE_SA_STATE_INIT:
13584235Smarkfen 		return (gettext("INITIALIZING"));
13594235Smarkfen 	case IKE_SA_STATE_SENT_SA:
13604235Smarkfen 		return (gettext("SENT FIRST MSG (SA)"));
13614235Smarkfen 	case IKE_SA_STATE_SENT_KE:
13624235Smarkfen 		return (gettext("SENT SECOND MSG (KE)"));
13634235Smarkfen 	case IKE_SA_STATE_SENT_LAST:
13644235Smarkfen 		return (gettext("SENT FINAL MSG"));
13654235Smarkfen 	case IKE_SA_STATE_DONE:
13664235Smarkfen 		return (gettext("ACTIVE"));
13674235Smarkfen 	case IKE_SA_STATE_DELETED:
13684235Smarkfen 		return (gettext("DELETED"));
13694235Smarkfen 	case IKE_SA_STATE_INVALID:
13704235Smarkfen 		return (gettext("<invalid>"));
13714235Smarkfen 	default:
13724235Smarkfen 		(void) snprintf(rtn, MAXLINESIZE,
13734235Smarkfen 		    gettext("<unknown %d>"), state);
13744235Smarkfen 		return (rtn);
13754235Smarkfen 	}
13764235Smarkfen }
13774235Smarkfen 
13784235Smarkfen static char *
13794235Smarkfen authmethstr(int meth)
13804235Smarkfen {
13814235Smarkfen 	static char	rtn[MAXLINESIZE];
13824235Smarkfen 
13834235Smarkfen 	switch (meth) {
13844235Smarkfen 	case IKE_AUTH_METH_PRE_SHARED_KEY:
13854235Smarkfen 		return (gettext("pre-shared key"));
13864235Smarkfen 	case IKE_AUTH_METH_DSS_SIG:
13874235Smarkfen 		return (gettext("DSS signatures"));
13884235Smarkfen 	case IKE_AUTH_METH_RSA_SIG:
13894235Smarkfen 		return (gettext("RSA signatures"));
13904235Smarkfen 	case IKE_AUTH_METH_RSA_ENCR:
13914235Smarkfen 		return (gettext("RSA Encryption"));
13924235Smarkfen 	case IKE_AUTH_METH_RSA_ENCR_REVISED:
13934235Smarkfen 		return (gettext("Revised RSA Encryption"));
13944235Smarkfen 	default:
13954235Smarkfen 		(void) snprintf(rtn, MAXLINESIZE,
13964235Smarkfen 		    gettext("<unknown %d>"), meth);
13974235Smarkfen 		return (rtn);
13984235Smarkfen 	}
13994235Smarkfen }
14004235Smarkfen 
14014235Smarkfen static char *
14024235Smarkfen prfstr(int prf)
14034235Smarkfen {
14044235Smarkfen 	static char	rtn[MAXLINESIZE];
14054235Smarkfen 
14064235Smarkfen 	switch (prf) {
14074235Smarkfen 	case IKE_PRF_NONE:
14086209Spwernau 		return (gettext("<none/unavailable>"));
14094235Smarkfen 	case IKE_PRF_HMAC_MD5:
14104235Smarkfen 		return ("HMAC MD5");
14114235Smarkfen 	case IKE_PRF_HMAC_SHA1:
14124235Smarkfen 		return ("HMAC SHA1");
14136126Sdanmcd 	case IKE_PRF_HMAC_SHA256:
14146126Sdanmcd 		return ("HMAC SHA256");
14156126Sdanmcd 	case IKE_PRF_HMAC_SHA384:
14166126Sdanmcd 		return ("HMAC SHA384");
14176126Sdanmcd 	case IKE_PRF_HMAC_SHA512:
14186126Sdanmcd 		return ("HMAC SHA512");
14194235Smarkfen 	default:
14204235Smarkfen 		(void) snprintf(rtn, MAXLINESIZE,
14214235Smarkfen 		    gettext("<unknown %d>"), prf);
14224235Smarkfen 		return (rtn);
14234235Smarkfen 	}
14244235Smarkfen }
14254235Smarkfen 
14264235Smarkfen static char *
14274235Smarkfen dhstr(int grp)
14284235Smarkfen {
14294235Smarkfen 	static char	rtn[MAXLINESIZE];
14304235Smarkfen 
14314235Smarkfen 	switch (grp) {
14324235Smarkfen 	case 0:
14334731Smarkfen 		return (gettext("<unavailable>"));
14344235Smarkfen 	case IKE_GRP_DESC_MODP_768:
14354731Smarkfen 		return (gettext("768-bit MODP (group 1)"));
14364235Smarkfen 	case IKE_GRP_DESC_MODP_1024:
14374731Smarkfen 		return (gettext("1024-bit MODP (group 2)"));
14384235Smarkfen 	case IKE_GRP_DESC_EC2N_155:
14394235Smarkfen 		return (gettext("EC2N group on GP[2^155]"));
14404235Smarkfen 	case IKE_GRP_DESC_EC2N_185:
14414235Smarkfen 		return (gettext("EC2N group on GP[2^185]"));
14424235Smarkfen 	case IKE_GRP_DESC_MODP_1536:
14434731Smarkfen 		return (gettext("1536-bit MODP (group 5)"));
14444731Smarkfen 	case IKE_GRP_DESC_MODP_2048:
14454731Smarkfen 		return (gettext("2048-bit MODP (group 14)"));
14464731Smarkfen 	case IKE_GRP_DESC_MODP_3072:
14474731Smarkfen 		return (gettext("3072-bit MODP (group 15)"));
14484731Smarkfen 	case IKE_GRP_DESC_MODP_4096:
14494731Smarkfen 		return (gettext("4096-bit MODP (group 16)"));
14504731Smarkfen 	case IKE_GRP_DESC_MODP_6144:
14514731Smarkfen 		return (gettext("6144-bit MODP (group 17)"));
14524731Smarkfen 	case IKE_GRP_DESC_MODP_8192:
14534731Smarkfen 		return (gettext("8192-bit MODP (group 18)"));
145411892Ssommerfeld@sun.com 	case IKE_GRP_DESC_ECP_256:
145511892Ssommerfeld@sun.com 		return (gettext("256-bit ECP (group 19)"));
145611892Ssommerfeld@sun.com 	case IKE_GRP_DESC_ECP_384:
145711892Ssommerfeld@sun.com 		return (gettext("384-bit ECP (group 20)"));
145811892Ssommerfeld@sun.com 	case IKE_GRP_DESC_ECP_521:
145911892Ssommerfeld@sun.com 		return (gettext("521-bit ECP (group 21)"));
146011892Ssommerfeld@sun.com 	case IKE_GRP_DESC_MODP_1024_160:
146111892Ssommerfeld@sun.com 		return (
146211892Ssommerfeld@sun.com 		    gettext("1024-bit MODP with 160-bit subprime (group 22)"));
146311892Ssommerfeld@sun.com 	case IKE_GRP_DESC_MODP_2048_224:
146411892Ssommerfeld@sun.com 		return (
146511892Ssommerfeld@sun.com 		    gettext("2048-bit MODP with 224-bit subprime (group 23)"));
146611892Ssommerfeld@sun.com 	case IKE_GRP_DESC_MODP_2048_256:
146711892Ssommerfeld@sun.com 		return (
146811892Ssommerfeld@sun.com 		    gettext("2048-bit MODP with 256-bit subprime (group 24)"));
146911892Ssommerfeld@sun.com 	case IKE_GRP_DESC_ECP_192:
147011892Ssommerfeld@sun.com 		return (gettext("192-bit ECP (group 25)"));
147111892Ssommerfeld@sun.com 	case IKE_GRP_DESC_ECP_224:
147211892Ssommerfeld@sun.com 		return (gettext("224-bit ECP (group 26)"));
14734235Smarkfen 	default:
14744235Smarkfen 		(void) snprintf(rtn, MAXLINESIZE, gettext("<unknown %d>"), grp);
14754235Smarkfen 		return (rtn);
14764235Smarkfen 	}
14774235Smarkfen }
14784235Smarkfen 
14794235Smarkfen static void
14804235Smarkfen print_hdr(char *prefix, ike_p1_hdr_t *hdrp)
14814235Smarkfen {
14827749SThejaswini.Singarajipura@Sun.COM 	char sbuf[TBUF_SIZE];
14837749SThejaswini.Singarajipura@Sun.COM 	char tbuf[TBUF_SIZE];
14849452Sdanmcd@sun.com 	time_t ltime = (time_t)hdrp->p1hdr_dpd_time;
14857749SThejaswini.Singarajipura@Sun.COM 
14864235Smarkfen 	(void) printf(
14874235Smarkfen 	    gettext("%s Cookies: Initiator 0x%llx  Responder 0x%llx\n"),
14887421SDaniel.Anderson@Sun.COM 	    prefix, ntohll(hdrp->p1hdr_cookies.cky_i),
14897421SDaniel.Anderson@Sun.COM 	    ntohll(hdrp->p1hdr_cookies.cky_r));
14904235Smarkfen 	(void) printf(gettext("%s The local host is the %s.\n"), prefix,
14914235Smarkfen 	    hdrp->p1hdr_isinit ? gettext("initiator") : gettext("responder"));
14924235Smarkfen 	(void) printf(gettext("%s ISAKMP version %d.%d; %s exchange\n"), prefix,
14934235Smarkfen 	    hdrp->p1hdr_major, hdrp->p1hdr_minor, xchgstr(hdrp->p1hdr_xchg));
14947749SThejaswini.Singarajipura@Sun.COM 	(void) printf(gettext("%s Current state is %s\n"), prefix,
14954235Smarkfen 	    statestr(hdrp->p1hdr_state));
14967749SThejaswini.Singarajipura@Sun.COM 	if (hdrp->p1hdr_support_dpd == B_FALSE) {
14977749SThejaswini.Singarajipura@Sun.COM 		return;
14987749SThejaswini.Singarajipura@Sun.COM 	}
14997749SThejaswini.Singarajipura@Sun.COM 	(void) printf(gettext("%s Dead Peer Detection (RFC 3706)"
15007749SThejaswini.Singarajipura@Sun.COM 	    " enabled"), prefix);
15017749SThejaswini.Singarajipura@Sun.COM 	if (hdrp->p1hdr_dpd_state < DPD_IN_PROGRESS) {
15027749SThejaswini.Singarajipura@Sun.COM 		(void) printf("\n");
15037749SThejaswini.Singarajipura@Sun.COM 		return;
15047749SThejaswini.Singarajipura@Sun.COM 	}
15057749SThejaswini.Singarajipura@Sun.COM 	if (strftime(tbuf, TBUF_SIZE, NULL,
15069452Sdanmcd@sun.com 	    localtime(&ltime)) == 0) {
15077749SThejaswini.Singarajipura@Sun.COM 		(void) strlcpy(tbuf, gettext("<time conversion failed>"),
15087749SThejaswini.Singarajipura@Sun.COM 		    TBUF_SIZE);
15097749SThejaswini.Singarajipura@Sun.COM 	}
15107749SThejaswini.Singarajipura@Sun.COM 	(void) printf(gettext("\n%s Dead Peer Detection handshake "), prefix);
15117749SThejaswini.Singarajipura@Sun.COM 	switch (hdrp->p1hdr_dpd_state) {
15127749SThejaswini.Singarajipura@Sun.COM 	case DPD_SUCCESSFUL:
15137749SThejaswini.Singarajipura@Sun.COM 		(void) strlcpy(sbuf, gettext("was successful at "), TBUF_SIZE);
15147749SThejaswini.Singarajipura@Sun.COM 		break;
15157749SThejaswini.Singarajipura@Sun.COM 	case DPD_FAILURE:
15167749SThejaswini.Singarajipura@Sun.COM 		(void) strlcpy(sbuf, gettext("failed at "), TBUF_SIZE);
15177749SThejaswini.Singarajipura@Sun.COM 		break;
15187749SThejaswini.Singarajipura@Sun.COM 	case DPD_IN_PROGRESS:
15197749SThejaswini.Singarajipura@Sun.COM 		(void) strlcpy(sbuf, gettext("is in progress."), TBUF_SIZE);
15207749SThejaswini.Singarajipura@Sun.COM 		break;
15217749SThejaswini.Singarajipura@Sun.COM 	}
15228185Sdanmcd@sun.com 	(void) printf("%s %s", sbuf,
15238185Sdanmcd@sun.com 	    (hdrp->p1hdr_dpd_state == DPD_IN_PROGRESS) ? "" : tbuf);
15244235Smarkfen 	(void) printf("\n");
15254235Smarkfen }
15264235Smarkfen 
15274235Smarkfen static void
15284235Smarkfen print_lt_limits(char *prefix, ike_p1_xform_t *xfp)
15294235Smarkfen {
153011379SVladimir.Kotal@Sun.COM 	char byte_str[BYTE_STR_SIZE]; /* byte lifetime string representation */
153111379SVladimir.Kotal@Sun.COM 	char secs_str[SECS_STR_SIZE]; /* lifetime string representation */
153211379SVladimir.Kotal@Sun.COM 
15334235Smarkfen 	(void) printf(gettext("%s Lifetime limits:\n"), prefix);
153411379SVladimir.Kotal@Sun.COM 	(void) printf(gettext("%s %u seconds%s; %u kbytes %sprotected\n"),
153511379SVladimir.Kotal@Sun.COM 	    prefix, xfp->p1xf_max_secs, secs2out(xfp->p1xf_max_secs,
153611379SVladimir.Kotal@Sun.COM 	    secs_str, sizeof (secs_str), SPC_BEGIN), xfp->p1xf_max_kbytes,
153711379SVladimir.Kotal@Sun.COM 	    bytecnt2out((uint64_t)xfp->p1xf_max_kbytes << 10, byte_str,
153811379SVladimir.Kotal@Sun.COM 	    sizeof (byte_str), SPC_END));
153911379SVladimir.Kotal@Sun.COM 	(void) printf(gettext("%s keying material for IPsec SAs can be "
154011379SVladimir.Kotal@Sun.COM 	    "provided %u times%s\n"), prefix, xfp->p1xf_max_keyuses,
154111379SVladimir.Kotal@Sun.COM 	    xfp->p1xf_max_keyuses == 0 ? " (no limit)" : "");
15424235Smarkfen }
15434235Smarkfen 
15444235Smarkfen #define	LT_USAGE_LEN	16	/* 1 uint64 + 2 uint32s */
15454235Smarkfen static void
15464235Smarkfen print_lt_usage(char *prefix, ike_p1_stats_t *sp)
15474235Smarkfen {
15484235Smarkfen 	time_t	scratch;
15494235Smarkfen 	char	tbuf[TBUF_SIZE];
155011379SVladimir.Kotal@Sun.COM 	char	bytestr[BYTE_STR_SIZE]; /* byte lifetime representation */
15514235Smarkfen 
15524235Smarkfen 	(void) printf(gettext("%s Current usage:\n"), prefix);
15534235Smarkfen 	scratch = (time_t)sp->p1stat_start;
15544235Smarkfen 	if (strftime(tbuf, TBUF_SIZE, NULL, localtime(&scratch)) == 0)
15554235Smarkfen 		(void) strlcpy(tbuf, gettext("<time conversion failed>"),
15564235Smarkfen 		    TBUF_SIZE);
15574235Smarkfen 	(void) printf(gettext("%s SA was created at %s\n"), prefix, tbuf);
155811379SVladimir.Kotal@Sun.COM 	(void) printf(gettext("%s %u kbytes %sprotected\n"),
155911379SVladimir.Kotal@Sun.COM 	    prefix, sp->p1stat_kbytes,
156011379SVladimir.Kotal@Sun.COM 	    bytecnt2out((uint64_t)sp->p1stat_kbytes << 10, bytestr,
156111379SVladimir.Kotal@Sun.COM 	    sizeof (bytestr), SPC_END));
156211379SVladimir.Kotal@Sun.COM 	(void) printf(gettext("%s keying material for IPsec SAs provided "
156311379SVladimir.Kotal@Sun.COM 	    "%u times\n"), prefix, sp->p1stat_keyuses);
15644235Smarkfen }
15654235Smarkfen 
15664235Smarkfen static void
15674235Smarkfen print_xform(char *prefix, ike_p1_xform_t *xfp, boolean_t print_lifetimes)
15684235Smarkfen {
15694235Smarkfen 	(void) printf(gettext("%s Authentication method: %s"), prefix,
15704235Smarkfen 	    authmethstr(xfp->p1xf_auth_meth));
15714235Smarkfen 	(void) printf(gettext("\n%s Encryption alg: "), prefix);
15724235Smarkfen 	(void) dump_ealg(xfp->p1xf_encr_alg, stdout);
15734235Smarkfen 	if (xfp->p1xf_encr_low_bits != 0) {
15744235Smarkfen 		(void) printf(gettext("(%d..%d)"), xfp->p1xf_encr_low_bits,
15754235Smarkfen 		    xfp->p1xf_encr_high_bits);
15766209Spwernau 	} else if ((xfp->p1xf_encr_low_bits == 0) &&
15776209Spwernau 	    (xfp->p1xf_encr_high_bits != 0)) {
15786209Spwernau 		/*
15796209Spwernau 		 * High bits is a placeholder for
15806209Spwernau 		 * negotiated algorithm strength
15816209Spwernau 		 */
15826209Spwernau 		(void) printf(gettext("(%d)"), xfp->p1xf_encr_high_bits);
15834235Smarkfen 	}
15844235Smarkfen 	(void) printf(gettext("; Authentication alg: "));
15854235Smarkfen 	(void) dump_aalg(xfp->p1xf_auth_alg, stdout);
15866209Spwernau 	(void) printf("\n%s ", prefix);
15876209Spwernau 	if (xfp->p1xf_prf != 0)
15886209Spwernau 		(void) printf(gettext("PRF: %s ; "), prfstr(xfp->p1xf_prf));
15896209Spwernau 	(void) printf(gettext("Oakley Group: %s\n"),
15904235Smarkfen 	    dhstr(xfp->p1xf_dh_group));
15914235Smarkfen 	if (xfp->p1xf_pfs == 0) {
15924235Smarkfen 		(void) printf(gettext("%s Phase 2 PFS is not used\n"), prefix);
15934235Smarkfen 	} else {
15944235Smarkfen 		(void) printf(gettext(
15954235Smarkfen 		    "%s Phase 2 PFS is required (Oakley Group: %s)\n"),
15964235Smarkfen 		    prefix, dhstr(xfp->p1xf_pfs));
15974235Smarkfen 	}
15984235Smarkfen 
15994235Smarkfen 	if (print_lifetimes)
16004235Smarkfen 		print_lt_limits(prefix, xfp);
16014235Smarkfen }
16024235Smarkfen 
16034235Smarkfen static void
16044235Smarkfen print_lifetime(char *prefix, ike_p1_xform_t *xfp, ike_p1_stats_t *sp,
16054235Smarkfen     int statlen)
16064235Smarkfen {
16074235Smarkfen 	time_t	current, remain, exp;
16084235Smarkfen 	char	tbuf[TBUF_SIZE];
160911379SVladimir.Kotal@Sun.COM 	char	byte_str[BYTE_STR_SIZE]; /* byte lifetime representation */
161011379SVladimir.Kotal@Sun.COM 	char	secs_str[SECS_STR_SIZE]; /* seconds lifetime representation */
16114235Smarkfen 
16124235Smarkfen 	current = time(NULL);
16134235Smarkfen 
16144235Smarkfen 	print_lt_limits(prefix, xfp);
16154235Smarkfen 
16164235Smarkfen 	/*
16174235Smarkfen 	 * make sure the stats struct we've been passed is as big
16184235Smarkfen 	 * as we expect it to be.  The usage stats are at the end,
16194235Smarkfen 	 * so anything less than the size we expect won't work.
16204235Smarkfen 	 */
16214235Smarkfen 	if (statlen >= sizeof (ike_p1_stats_t)) {
16224235Smarkfen 		print_lt_usage(prefix, sp);
16234235Smarkfen 	} else {
16244235Smarkfen 		return;
16254235Smarkfen 	}
16264235Smarkfen 
16274235Smarkfen 	(void) printf(gettext("%s Expiration info:\n"), prefix);
16284235Smarkfen 
16294235Smarkfen 	if (xfp->p1xf_max_kbytes != 0)
163011379SVladimir.Kotal@Sun.COM 		(void) printf(gettext("%s %u more bytes %scan be "
163111379SVladimir.Kotal@Sun.COM 		    "protected.\n"),
163211379SVladimir.Kotal@Sun.COM 		    prefix, xfp->p1xf_max_kbytes - sp->p1stat_kbytes,
163311379SVladimir.Kotal@Sun.COM 		    bytecnt2out((uint64_t)(xfp->p1xf_max_kbytes -
163411379SVladimir.Kotal@Sun.COM 		    sp->p1stat_kbytes) << 10, byte_str, sizeof (byte_str),
163511379SVladimir.Kotal@Sun.COM 		    SPC_END));
16364235Smarkfen 
16374235Smarkfen 	if (xfp->p1xf_max_keyuses != 0)
16384235Smarkfen 		(void) printf(gettext("%s Keying material can be provided "
16394235Smarkfen 		    "%u more times.\n"), prefix,
16404235Smarkfen 		    xfp->p1xf_max_keyuses - sp->p1stat_keyuses);
16414235Smarkfen 
16424235Smarkfen 	if (xfp->p1xf_max_secs != 0) {
16434235Smarkfen 		exp = (time_t)sp->p1stat_start + (time_t)xfp->p1xf_max_secs;
16444235Smarkfen 		remain = exp - current;
16454235Smarkfen 		if (strftime(tbuf, TBUF_SIZE, NULL, localtime(&exp)) == 0)
16464235Smarkfen 			(void) strlcpy(tbuf,
16474235Smarkfen 			    gettext("<time conversion failed>"), TBUF_SIZE);
16484235Smarkfen 		/*
16494235Smarkfen 		 * The SA may have expired but still exist because libike
16504235Smarkfen 		 * has not freed it yet.
16514235Smarkfen 		 */
165211379SVladimir.Kotal@Sun.COM 		if (remain > 0) {
16534235Smarkfen 			(void) printf(gettext(
165411379SVladimir.Kotal@Sun.COM 			    "%s SA expires in %lu seconds%s\n"),
165511379SVladimir.Kotal@Sun.COM 			    prefix, remain, secs2out(remain, secs_str,
165611379SVladimir.Kotal@Sun.COM 			    sizeof (secs_str), SPC_BEGIN));
165711379SVladimir.Kotal@Sun.COM 			(void) printf(gettext("%s Time of expiration: %s\n"),
165811379SVladimir.Kotal@Sun.COM 			    prefix, tbuf);
165911379SVladimir.Kotal@Sun.COM 		} else {
16604235Smarkfen 			(void) printf(gettext("%s SA Expired at %s\n"),
16614235Smarkfen 			    prefix, tbuf);
166211379SVladimir.Kotal@Sun.COM 		}
16634235Smarkfen 	}
16644235Smarkfen }
16654235Smarkfen 
16664235Smarkfen /* used to verify structure lengths... */
16674235Smarkfen #define	COUNTER_32BIT	4
16684235Smarkfen #define	COUNTER_PAIR	8
16694235Smarkfen 
16704235Smarkfen static void
16714235Smarkfen print_p1stats(char *prefix, ike_p1_stats_t *sp, int statlen,
16724235Smarkfen     boolean_t print_lifetimes)
16734235Smarkfen {
16744235Smarkfen 	if (statlen < COUNTER_PAIR)
16754235Smarkfen 		return;
16764235Smarkfen 	(void) printf(gettext("%s %u Quick Mode SAs created; "), prefix,
16774235Smarkfen 	    sp->p1stat_new_qm_sas);
16784235Smarkfen 	(void) printf(gettext("%u Quick Mode SAs deleted\n"),
16794235Smarkfen 	    sp->p1stat_del_qm_sas);
16804235Smarkfen 	statlen -= COUNTER_PAIR;
16814235Smarkfen 
16824235Smarkfen 	if ((print_lifetimes) && (statlen >= LT_USAGE_LEN))
16834235Smarkfen 		print_lt_usage(prefix, sp);
16844235Smarkfen }
16854235Smarkfen 
16864235Smarkfen static void
16874235Smarkfen print_errs(char *prefix, ike_p1_errors_t *errp, int errlen)
16884235Smarkfen {
16894235Smarkfen 	/*
16904235Smarkfen 	 * Don't try to break this one up; it's either all or nothing!
16914235Smarkfen 	 */
16924235Smarkfen 	if (errlen < sizeof (ike_p1_errors_t))
16934235Smarkfen 		return;
16944235Smarkfen 
16954235Smarkfen 	(void) printf(gettext("%s %u RX errors: "), prefix,
16964235Smarkfen 	    errp->p1err_decrypt + errp->p1err_hash + errp->p1err_otherrx);
16974235Smarkfen 	(void) printf(gettext("%u decryption, %u hash, %u other\n"),
16984235Smarkfen 	    errp->p1err_decrypt, errp->p1err_hash, errp->p1err_otherrx);
16994235Smarkfen 	(void) printf(gettext("%s %u TX errors\n"), prefix, errp->p1err_tx);
17004235Smarkfen }
17014235Smarkfen 
17024235Smarkfen static void
17034235Smarkfen print_addr_range(char *prefix, ike_addr_pr_t *pr)
17044235Smarkfen {
17054235Smarkfen 	boolean_t	range = B_TRUE;
17064235Smarkfen 	struct sockaddr_storage	*beg, *end;
17074235Smarkfen 	struct sockaddr_in	*bsin, *esin;
17084235Smarkfen 	struct sockaddr_in6	*bsin6, *esin6;
17094235Smarkfen 
17104235Smarkfen 	beg = &pr->beg_iprange;
17114235Smarkfen 	end = &pr->end_iprange;
17124235Smarkfen 
17134235Smarkfen 	if (beg->ss_family != end->ss_family) {
17144235Smarkfen 		(void) printf(gettext("%s invalid address range\n"), prefix);
17154235Smarkfen 		return;
17164235Smarkfen 	}
17174235Smarkfen 
17184235Smarkfen 	switch (beg->ss_family) {
17194235Smarkfen 	case AF_INET:
17204235Smarkfen 		bsin = (struct sockaddr_in *)beg;
17214235Smarkfen 		esin = (struct sockaddr_in *)end;
17224235Smarkfen 		if ((uint32_t)bsin->sin_addr.s_addr ==
17234235Smarkfen 		    (uint32_t)esin->sin_addr.s_addr)
17244235Smarkfen 			range = B_FALSE;
17254235Smarkfen 		break;
17264235Smarkfen 	case AF_INET6:
17274235Smarkfen 		bsin6 = (struct sockaddr_in6 *)beg;
17284235Smarkfen 		esin6 = (struct sockaddr_in6 *)end;
17294235Smarkfen 		if (IN6_ARE_ADDR_EQUAL(&bsin6->sin6_addr, &esin6->sin6_addr))
17304235Smarkfen 			range = B_FALSE;
17314235Smarkfen 		break;
17324235Smarkfen 	default:
17334235Smarkfen 		(void) printf(gettext("%s invalid address range\n"), prefix);
17344235Smarkfen 		return;
17354235Smarkfen 	}
17364235Smarkfen 
17374235Smarkfen 	(void) printf("%s ", prefix);
17384867Spwernau 	(void) dump_sockaddr((struct sockaddr *)beg, 0, B_TRUE, stdout, nflag);
17394235Smarkfen 	if (range) {
17404235Smarkfen 		(void) printf(" - ");
17414867Spwernau 		(void) dump_sockaddr((struct sockaddr *)end, 0, B_TRUE, stdout,
17424867Spwernau 		    nflag);
17434235Smarkfen 	}
17444235Smarkfen 	(void) printf("\n");
17454235Smarkfen 
17464235Smarkfen }
17474235Smarkfen 
17484235Smarkfen /*
17494235Smarkfen  * used to tell printing function if info should be identified
17504235Smarkfen  * as belonging to initiator, responder, or neither
17514235Smarkfen  */
17524235Smarkfen #define	IS_INITIATOR	1
17534235Smarkfen #define	IS_RESPONDER	2
17544235Smarkfen #define	DONT_PRINT_INIT	3
17554235Smarkfen 
17564235Smarkfen static void
17574235Smarkfen print_addr(char *prefix, struct sockaddr_storage *sa, int init_instr)
17584235Smarkfen {
17594235Smarkfen 	(void) printf(gettext("%s Address"), prefix);
17604235Smarkfen 
17614235Smarkfen 	if (init_instr != DONT_PRINT_INIT)
17624235Smarkfen 		(void) printf(" (%s):\n", (init_instr == IS_INITIATOR) ?
17634235Smarkfen 		    gettext("Initiator") : gettext("Responder"));
17644235Smarkfen 	else
17654235Smarkfen 		(void) printf(":\n");
17664235Smarkfen 
17674235Smarkfen 	(void) printf("%s ", prefix);
17684867Spwernau 	(void) dump_sockaddr((struct sockaddr *)sa, 0, B_FALSE, stdout, nflag);
17694235Smarkfen }
17704235Smarkfen 
17714235Smarkfen static void
17724235Smarkfen print_id(char *prefix, sadb_ident_t *idp, int init_instr)
17734235Smarkfen {
17744235Smarkfen 	boolean_t	canprint;
17754235Smarkfen 
17764235Smarkfen 	switch (init_instr) {
17774235Smarkfen 	case IS_INITIATOR:
17784235Smarkfen 		(void) printf(gettext("%s Initiator identity, "), prefix);
17794235Smarkfen 		break;
17804235Smarkfen 	case IS_RESPONDER:
17814235Smarkfen 		(void) printf(gettext("%s Responder identity, "), prefix);
17824235Smarkfen 		break;
17834235Smarkfen 	case DONT_PRINT_INIT:
17844235Smarkfen 		(void) printf(gettext("%s Identity, "), prefix);
17854235Smarkfen 		break;
17864235Smarkfen 	default:
17874235Smarkfen 		(void) printf(gettext("<invalid identity>\n"));
17884235Smarkfen 		return;
17894235Smarkfen 	}
17904235Smarkfen 	(void) printf(gettext("uid=%d, type "), idp->sadb_ident_id);
17914235Smarkfen 	canprint = dump_sadb_idtype(idp->sadb_ident_type, stdout, NULL);
17926119Spwernau 	if (canprint) {
17934235Smarkfen 		(void) printf("\n%s %s\n", prefix, (char *)(idp + 1));
17946119Spwernau 	} else {
17956119Spwernau 		(void) printf(gettext("\n%s "), prefix);
17966119Spwernau 		print_asn1_name(stdout,
17976119Spwernau 		    (const unsigned char *)(idp + 1),
17986119Spwernau 		    SADB_64TO8(idp->sadb_ident_len) - sizeof (sadb_ident_t));
17996119Spwernau 	}
18004235Smarkfen }
18014235Smarkfen 
18024235Smarkfen static void
18034235Smarkfen print_idspec(char *prefix, char *idp, int icnt, int ecnt)
18044235Smarkfen {
18054235Smarkfen 	int	i;
18064235Smarkfen 
18074235Smarkfen 	(void) printf(gettext("%s Identity descriptors:\n"), prefix);
18084235Smarkfen 
18094235Smarkfen 	for (i = 0; i < icnt; i++) {
18104235Smarkfen 		if (i == 0)
18114235Smarkfen 			(void) printf(gettext("%s Includes:\n"), prefix);
18124235Smarkfen 		(void) printf("%s    %s\n", prefix, idp);
18134235Smarkfen 		idp += strlen(idp) + 1;
18144235Smarkfen 	}
18154235Smarkfen 
18164235Smarkfen 	for (i = 0; i < ecnt; i++) {
18174235Smarkfen 		if (i == 0)
18184235Smarkfen 			(void) printf(gettext("%s Excludes:\n"), prefix);
18194235Smarkfen 		(void) printf("%s    %s\n", prefix, idp);
18204235Smarkfen 		idp += strlen(idp) + 1;
18214235Smarkfen 	}
18224235Smarkfen }
18234235Smarkfen 
18244235Smarkfen static void
18254235Smarkfen print_keys(char *prefix, ike_p1_key_t *keyp, int size)
18264235Smarkfen {
18274235Smarkfen 	uint32_t	*curp;
18284235Smarkfen 	ike_p1_key_t	*p;
18294235Smarkfen 	int		ssize;
18304235Smarkfen 
18314235Smarkfen 	curp = (uint32_t *)keyp;
18324235Smarkfen 
18334235Smarkfen 	ssize = sizeof (ike_p1_key_t);
18344235Smarkfen 
18354235Smarkfen 	while ((intptr_t)curp - (intptr_t)keyp < size) {
18364235Smarkfen 		size_t p1klen, len;
18374235Smarkfen 
18384235Smarkfen 		p = (ike_p1_key_t *)curp;
18394235Smarkfen 		p1klen = p->p1key_len;
18404235Smarkfen 		len = p1klen - ssize;
18414235Smarkfen 
18424235Smarkfen 		p1klen = roundup(p1klen, sizeof (ike_p1_key_t));
18434235Smarkfen 		if (p1klen < ssize) {
18444235Smarkfen 			(void) printf(gettext("Short key\n"));
18454235Smarkfen 			break;
18464235Smarkfen 		}
18474235Smarkfen 
18484235Smarkfen 		switch (p->p1key_type) {
18494235Smarkfen 		case IKE_KEY_PRESHARED:
18504235Smarkfen 			(void) printf(gettext("%s Pre-shared key (%d bytes): "),
18514235Smarkfen 			    prefix, len);
18524235Smarkfen 			break;
18534235Smarkfen 		case IKE_KEY_SKEYID:
18544235Smarkfen 			(void) printf(gettext("%s SKEYID (%d bytes): "),
18554235Smarkfen 			    prefix, len);
18564235Smarkfen 			break;
18574235Smarkfen 		case IKE_KEY_SKEYID_D:
18584235Smarkfen 			(void) printf(gettext("%s SKEYID_d (%d bytes): "),
18594235Smarkfen 			    prefix, len);
18604235Smarkfen 			break;
18614235Smarkfen 		case IKE_KEY_SKEYID_A:
18624235Smarkfen 			(void) printf(gettext("%s SKEYID_a (%d bytes): "),
18634235Smarkfen 			    prefix, len);
18644235Smarkfen 			break;
18654235Smarkfen 		case IKE_KEY_SKEYID_E:
18664235Smarkfen 			(void) printf(gettext("%s SKEYID_e (%d bytes): "),
18674235Smarkfen 			    prefix, len);
18684235Smarkfen 			break;
18694235Smarkfen 		case IKE_KEY_ENCR:
18704235Smarkfen 			(void) printf(gettext("%s Encryption key (%d bytes): "),
18714235Smarkfen 			    prefix, len);
18724235Smarkfen 			break;
18734235Smarkfen 		case IKE_KEY_IV:
18744235Smarkfen 			(void) printf(
18754235Smarkfen 			    gettext("%s Initialization vector (%d bytes): "),
18764235Smarkfen 			    prefix, len);
18774235Smarkfen 			break;
18784235Smarkfen 		default:
18794235Smarkfen 			(void) printf(gettext("%s Unidentified key info %p %d"),
18804235Smarkfen 			    prefix, p, p1klen);
188111136SMark.Fenwick@Sun.COM 			goto badkey;
18824235Smarkfen 		}
188311136SMark.Fenwick@Sun.COM 		(void) dump_key((uint8_t *)(p + 1), SADB_8TO1(len), 0,
188411136SMark.Fenwick@Sun.COM 		    stdout, B_FALSE);
188511136SMark.Fenwick@Sun.COM badkey:
18864235Smarkfen 		(void) printf("\n");
18874235Smarkfen 		assert(IS_P2ALIGNED(p1klen, 8));
18884235Smarkfen 		curp += (p1klen >> 2);
18894235Smarkfen 	}
18904235Smarkfen }
18914235Smarkfen 
18924235Smarkfen static void
1893*12129SVladimir.Kotal@Sun.COM print_group_header(void)
1894*12129SVladimir.Kotal@Sun.COM {
1895*12129SVladimir.Kotal@Sun.COM 	(void) printf(gettext("\nList of Diffie-Hellman groups for setting "
1896*12129SVladimir.Kotal@Sun.COM 	    "up IKE SAs"));
1897*12129SVladimir.Kotal@Sun.COM 	(void) printf(gettext("\nThe values match the IPsec attribute "
1898*12129SVladimir.Kotal@Sun.COM 	    "assigned numbers published by IANA\n\n"));
1899*12129SVladimir.Kotal@Sun.COM 	(void) printf("%-6s%-9s%-50s\n",
1900*12129SVladimir.Kotal@Sun.COM 	    gettext("Value"), gettext("Strength"), gettext("Description"));
1901*12129SVladimir.Kotal@Sun.COM }
1902*12129SVladimir.Kotal@Sun.COM 
1903*12129SVladimir.Kotal@Sun.COM static void
1904*12129SVladimir.Kotal@Sun.COM print_group(ike_group_t *gp)
1905*12129SVladimir.Kotal@Sun.COM {
1906*12129SVladimir.Kotal@Sun.COM 	(void) printf("%-6u%-9u%-50s\n",
1907*12129SVladimir.Kotal@Sun.COM 	    gp->group_number, gp->group_bits, gp->group_label);
1908*12129SVladimir.Kotal@Sun.COM }
1909*12129SVladimir.Kotal@Sun.COM 
1910*12129SVladimir.Kotal@Sun.COM static void
1911*12129SVladimir.Kotal@Sun.COM print_encralg_header(void)
1912*12129SVladimir.Kotal@Sun.COM {
1913*12129SVladimir.Kotal@Sun.COM 	(void) printf(gettext("\nList of encryption algorithms for IKE"));
1914*12129SVladimir.Kotal@Sun.COM 	(void) printf(gettext("\nThe values match the IPsec attribute "
1915*12129SVladimir.Kotal@Sun.COM 	    "assigned numbers published by IANA\n\n"));
1916*12129SVladimir.Kotal@Sun.COM 	(void) printf("%-6s%-20s%-15s\n", gettext("Value"),
1917*12129SVladimir.Kotal@Sun.COM 	    gettext("Name"), gettext("Keylen range"));
1918*12129SVladimir.Kotal@Sun.COM }
1919*12129SVladimir.Kotal@Sun.COM 
1920*12129SVladimir.Kotal@Sun.COM static void
1921*12129SVladimir.Kotal@Sun.COM print_encralg(ike_encralg_t *ep)
1922*12129SVladimir.Kotal@Sun.COM {
1923*12129SVladimir.Kotal@Sun.COM 	char keylen_str[16];
1924*12129SVladimir.Kotal@Sun.COM 
1925*12129SVladimir.Kotal@Sun.COM 	(void) strlcpy(keylen_str, "N/A", sizeof (keylen_str));
1926*12129SVladimir.Kotal@Sun.COM 	if (ep->encr_keylen_min != 0 || ep->encr_keylen_max != 0)
1927*12129SVladimir.Kotal@Sun.COM 		(void) snprintf(keylen_str, sizeof (keylen_str), "%d-%d",
1928*12129SVladimir.Kotal@Sun.COM 		    ep->encr_keylen_min, ep->encr_keylen_max);
1929*12129SVladimir.Kotal@Sun.COM 	(void) printf("%-6u%-20s%-15s\n",
1930*12129SVladimir.Kotal@Sun.COM 	    ep->encr_value, ep->encr_name, keylen_str);
1931*12129SVladimir.Kotal@Sun.COM }
1932*12129SVladimir.Kotal@Sun.COM 
1933*12129SVladimir.Kotal@Sun.COM static void
1934*12129SVladimir.Kotal@Sun.COM print_authalg_header(void)
1935*12129SVladimir.Kotal@Sun.COM {
1936*12129SVladimir.Kotal@Sun.COM 	(void) printf(gettext("\nList of authentication algorithms for IKE"));
1937*12129SVladimir.Kotal@Sun.COM 	(void) printf(gettext("\nThe values match the IPsec attribute "
1938*12129SVladimir.Kotal@Sun.COM 	    "assigned numbers published by IANA\n\n"));
1939*12129SVladimir.Kotal@Sun.COM 	(void) printf("%-6s%-20s\n", gettext("Value"), gettext("Name"));
1940*12129SVladimir.Kotal@Sun.COM }
1941*12129SVladimir.Kotal@Sun.COM 
1942*12129SVladimir.Kotal@Sun.COM static void
1943*12129SVladimir.Kotal@Sun.COM print_authalg(ike_authalg_t *ap)
1944*12129SVladimir.Kotal@Sun.COM {
1945*12129SVladimir.Kotal@Sun.COM 	(void) printf("%-6u%-20s\n",
1946*12129SVladimir.Kotal@Sun.COM 	    ap->auth_value, ap->auth_name);
1947*12129SVladimir.Kotal@Sun.COM }
1948*12129SVladimir.Kotal@Sun.COM 
1949*12129SVladimir.Kotal@Sun.COM static void
19504235Smarkfen print_p1(ike_p1_sa_t *p1)
19514235Smarkfen {
19524235Smarkfen 	ike_p1_stats_t	*sp;
19534235Smarkfen 	ike_p1_errors_t	*ep;
19544235Smarkfen 	ike_p1_key_t	*kp;
19554235Smarkfen 	sadb_ident_t	*lidp, *ridp;
19564235Smarkfen 	int		lstat, rstat;
19574235Smarkfen 
19584235Smarkfen 	(void) printf("\n");
19594235Smarkfen 	print_hdr("IKESA:", &p1->p1sa_hdr);
19604235Smarkfen 	print_xform("XFORM:", &p1->p1sa_xform, B_FALSE);
19614235Smarkfen 
19624235Smarkfen 	if (p1->p1sa_hdr.p1hdr_isinit) {
19634235Smarkfen 		lstat = IS_INITIATOR;
19644235Smarkfen 		rstat = IS_RESPONDER;
19654235Smarkfen 	} else {
19664235Smarkfen 		lstat = IS_RESPONDER;
19674235Smarkfen 		rstat = IS_INITIATOR;
19684235Smarkfen 	}
19694235Smarkfen 	print_addr("LOCIP:", &p1->p1sa_ipaddrs.loc_addr, lstat);
19704235Smarkfen 	print_addr("REMIP:", &p1->p1sa_ipaddrs.rem_addr, rstat);
19714235Smarkfen 
19724235Smarkfen 	/*
19734235Smarkfen 	 * the stat len might be 0; but still make the call
19744235Smarkfen 	 * to print_lifetime() to pick up the xform info
19754235Smarkfen 	 */
19764235Smarkfen 	sp = (ike_p1_stats_t *)((int)(p1) + p1->p1sa_stat_off);
19774235Smarkfen 	print_lifetime("LIFTM:", &p1->p1sa_xform, sp, p1->p1sa_stat_len);
19784235Smarkfen 
19794235Smarkfen 	if (p1->p1sa_stat_len > 0) {
19804235Smarkfen 		print_p1stats("STATS:", sp, p1->p1sa_stat_len, B_FALSE);
19814235Smarkfen 	}
19824235Smarkfen 
19834235Smarkfen 	if (p1->p1sa_error_len > 0) {
19844235Smarkfen 		ep = (ike_p1_errors_t *)((int)(p1) + p1->p1sa_error_off);
19854235Smarkfen 		print_errs("ERRS: ", ep, p1->p1sa_error_len);
19864235Smarkfen 	}
19874235Smarkfen 
19884235Smarkfen 	if (p1->p1sa_localid_len > 0) {
19894235Smarkfen 		lidp = (sadb_ident_t *)((int)(p1) + p1->p1sa_localid_off);
19904235Smarkfen 		print_id("LOCID:", lidp, lstat);
19914235Smarkfen 	}
19924235Smarkfen 
19934235Smarkfen 	if (p1->p1sa_remoteid_len > 0) {
19944235Smarkfen 		ridp = (sadb_ident_t *)((int)(p1) + p1->p1sa_remoteid_off);
19954235Smarkfen 		print_id("REMID:", ridp, rstat);
19964235Smarkfen 	}
19974235Smarkfen 
19984235Smarkfen 	if (p1->p1sa_key_len > 0) {
19994235Smarkfen 		kp = (ike_p1_key_t *)((int)(p1) + p1->p1sa_key_off);
20004235Smarkfen 		print_keys("KEY:  ", kp, p1->p1sa_key_len);
20014235Smarkfen 	}
20024235Smarkfen }
20034235Smarkfen 
20044235Smarkfen static void
20058596SPaul.Wernau@Sun.COM print_certcache(ike_certcache_t *c)
20068596SPaul.Wernau@Sun.COM {
20078596SPaul.Wernau@Sun.COM 	(void) printf("\n");
20088596SPaul.Wernau@Sun.COM 
20098596SPaul.Wernau@Sun.COM 	(void) printf(gettext("CERTIFICATE CACHE ID: %d\n"), c->cache_id);
20108596SPaul.Wernau@Sun.COM 	(void) printf(gettext("\tSubject Name: <%s>\n"),
20118596SPaul.Wernau@Sun.COM 	    (c->subject != NULL) ? c->subject : gettext("Name unavailable"));
20128596SPaul.Wernau@Sun.COM 	(void) printf(gettext("\t Issuer Name: <%s>\n"),
20138596SPaul.Wernau@Sun.COM 	    (c->issuer != NULL) ? c->issuer : gettext("Name unavailable"));
201411379SVladimir.Kotal@Sun.COM 	if ((int)c->certclass == -1)
20158596SPaul.Wernau@Sun.COM 		(void) printf(gettext("\t\t[trusted certificate]\n"));
20168596SPaul.Wernau@Sun.COM 	switch (c->linkage) {
20178596SPaul.Wernau@Sun.COM 	case CERT_OFF_WIRE:
20188596SPaul.Wernau@Sun.COM 		(void) printf(gettext("\t\t[Public certificate only]\n"));
20198596SPaul.Wernau@Sun.COM 		(void) printf(gettext(
20208596SPaul.Wernau@Sun.COM 		    "\t\t[Obtained via certificate payload]\n"));
20218596SPaul.Wernau@Sun.COM 		break;
20228596SPaul.Wernau@Sun.COM 	case CERT_NO_PRIVKEY:
20238596SPaul.Wernau@Sun.COM 		(void) printf(gettext("\t\t[Public certificate only]\n"));
20248596SPaul.Wernau@Sun.COM 		break;
20258596SPaul.Wernau@Sun.COM 	case CERT_PRIVKEY_LOCKED:
20268596SPaul.Wernau@Sun.COM 		(void) printf(gettext(
20278596SPaul.Wernau@Sun.COM 		    "\t\t[Private key linked but locked]\n"));
20288596SPaul.Wernau@Sun.COM 		break;
20298596SPaul.Wernau@Sun.COM 	case CERT_PRIVKEY_AVAIL:
20308596SPaul.Wernau@Sun.COM 		(void) printf(gettext("\t\t[Private key available]\n"));
20318596SPaul.Wernau@Sun.COM 		break;
20328596SPaul.Wernau@Sun.COM 	}
20338596SPaul.Wernau@Sun.COM }
20348596SPaul.Wernau@Sun.COM 
20358596SPaul.Wernau@Sun.COM static void
20364235Smarkfen print_ps(ike_ps_t *ps)
20374235Smarkfen {
20384235Smarkfen 	sadb_ident_t	*lidp, *ridp;
20394235Smarkfen 	uint8_t		*keyp;
20404235Smarkfen 
20414235Smarkfen 	(void) printf("\n");
20424235Smarkfen 
20434235Smarkfen 	(void) printf(gettext("PSKEY: For %s exchanges\n"),
20444235Smarkfen 	    xchgstr(ps->ps_ike_mode));
20454235Smarkfen 
20464235Smarkfen 	if (ps->ps_key_len > 0) {
20474235Smarkfen 		keyp = (uint8_t *)((int)(ps) + ps->ps_key_off);
20484235Smarkfen 		(void) printf(gettext("PSKEY: Pre-shared key (%d bytes): "),
20494235Smarkfen 		    ps->ps_key_len);
205010824SMark.Fenwick@Sun.COM 		(void) dump_key(keyp, ps->ps_key_bits, 0, stdout, B_FALSE);
20514235Smarkfen 		(void) printf("\n");
20524235Smarkfen 	}
20534235Smarkfen 
20544235Smarkfen 	/*
20554235Smarkfen 	 * We get *either* and address or an ident, never both.  So if
20564235Smarkfen 	 * the ident is there, don't try printing an address.
20574235Smarkfen 	 */
20584235Smarkfen 	if (ps->ps_localid_len > 0) {
20594235Smarkfen 		lidp = (sadb_ident_t *)
20604235Smarkfen 		    ((int)(ps) + ps->ps_localid_off);
20614235Smarkfen 		print_id("LOCID:", lidp, DONT_PRINT_INIT);
20624235Smarkfen 	} else {
20634235Smarkfen 		print_addr("LOCIP:", &ps->ps_ipaddrs.loc_addr, DONT_PRINT_INIT);
20644235Smarkfen 	}
20654235Smarkfen 
20664235Smarkfen 	if (ps->ps_remoteid_len > 0) {
20674235Smarkfen 		ridp = (sadb_ident_t *)
20684235Smarkfen 		    ((int)(ps) + ps->ps_remoteid_off);
20694235Smarkfen 		print_id("REMID:", ridp, DONT_PRINT_INIT);
20704235Smarkfen 	} else {
20714235Smarkfen 		print_addr("REMIP:", &ps->ps_ipaddrs.rem_addr, DONT_PRINT_INIT);
20724235Smarkfen 	}
20734235Smarkfen }
20744235Smarkfen 
20754235Smarkfen #define	PREFIXLEN	16
20764235Smarkfen 
20774235Smarkfen static void
20784235Smarkfen print_rule(ike_rule_t *rp)
20794235Smarkfen {
20804235Smarkfen 	char		prefix[PREFIXLEN];
20814235Smarkfen 	int		i;
20824235Smarkfen 	ike_p1_xform_t	*xfp;
20834235Smarkfen 	ike_addr_pr_t	*lipp, *ripp;
20844235Smarkfen 	char		*lidp, *ridp;
208511379SVladimir.Kotal@Sun.COM 	char byte_str[BYTE_STR_SIZE]; /* kbyte string representation */
208611379SVladimir.Kotal@Sun.COM 	char secs_str[SECS_STR_SIZE]; /* seconds string representation */
20874235Smarkfen 
20884235Smarkfen 	(void) printf("\n");
20894235Smarkfen 	(void) printf(gettext("GLOBL: Label '%s', key manager cookie %u\n"),
20904235Smarkfen 	    rp->rule_label, rp->rule_kmcookie);
20914235Smarkfen 	(void) printf(gettext("GLOBL: local_idtype="));
20924235Smarkfen 	(void) dump_sadb_idtype(rp->rule_local_idtype, stdout, NULL);
20934235Smarkfen 	(void) printf(gettext(", ike_mode=%s\n"), xchgstr(rp->rule_ike_mode));
20944235Smarkfen 	(void) printf(gettext(
20954235Smarkfen 	    "GLOBL: p1_nonce_len=%u, p2_nonce_len=%u, p2_pfs=%s (group %u)\n"),
20964235Smarkfen 	    rp->rule_p1_nonce_len, rp->rule_p2_nonce_len,
20974235Smarkfen 	    (rp->rule_p2_pfs) ? gettext("true") : gettext("false"),
20984235Smarkfen 	    rp->rule_p2_pfs);
20994235Smarkfen 	(void) printf(
210011379SVladimir.Kotal@Sun.COM 	    gettext("GLOBL: p2_lifetime=%u seconds%s\n"),
210111379SVladimir.Kotal@Sun.COM 	    rp->rule_p2_lifetime_secs, secs2out(rp->rule_p2_lifetime_secs,
210211379SVladimir.Kotal@Sun.COM 	    secs_str, sizeof (secs_str), SPC_BEGIN));
210311379SVladimir.Kotal@Sun.COM 	(void) printf(
210411379SVladimir.Kotal@Sun.COM 	    gettext("GLOBL: p2_softlife=%u seconds%s\n"),
210511379SVladimir.Kotal@Sun.COM 	    rp->rule_p2_softlife_secs, secs2out(rp->rule_p2_softlife_secs,
210611379SVladimir.Kotal@Sun.COM 	    secs_str, sizeof (secs_str), SPC_BEGIN));
21074235Smarkfen 	(void) printf(
210811379SVladimir.Kotal@Sun.COM 	    gettext("GLOBL: p2_idletime=%u seconds%s\n"),
210911379SVladimir.Kotal@Sun.COM 	    rp->rule_p2_idletime_secs, secs2out(rp->rule_p2_idletime_secs,
211011379SVladimir.Kotal@Sun.COM 	    secs_str, sizeof (secs_str), SPC_BEGIN));
211111379SVladimir.Kotal@Sun.COM 	/*
211211379SVladimir.Kotal@Sun.COM 	 * Perform explicit conversion before passing to bytecnt2out()
211311379SVladimir.Kotal@Sun.COM 	 * to avoid integer overflow.
211411379SVladimir.Kotal@Sun.COM 	 */
21157749SThejaswini.Singarajipura@Sun.COM 	(void) printf(
211611379SVladimir.Kotal@Sun.COM 	    gettext("GLOBL: p2_lifetime_kb=%u kilobytes%s\n"),
211711379SVladimir.Kotal@Sun.COM 	    rp->rule_p2_lifetime_kb,
211811379SVladimir.Kotal@Sun.COM 	    bytecnt2out((uint64_t)(rp->rule_p2_lifetime_kb) << 10,
211911379SVladimir.Kotal@Sun.COM 	    byte_str, sizeof (byte_str), SPC_BEGIN));
212011379SVladimir.Kotal@Sun.COM 	(void) printf(
212111379SVladimir.Kotal@Sun.COM 	    gettext("GLOBL: p2_softlife_kb=%u kilobytes%s\n"),
212211379SVladimir.Kotal@Sun.COM 	    rp->rule_p2_softlife_kb,
212311379SVladimir.Kotal@Sun.COM 	    bytecnt2out(((uint64_t)(rp->rule_p2_softlife_kb)) << 10,
212411379SVladimir.Kotal@Sun.COM 	    byte_str, sizeof (byte_str), SPC_BEGIN));
21254235Smarkfen 
21264235Smarkfen 	if (rp->rule_locip_cnt > 0) {
21274235Smarkfen 		(void) printf(gettext("LOCIP: IP address range(s):\n"));
21284235Smarkfen 		lipp = (ike_addr_pr_t *)((int)rp + rp->rule_locip_off);
21294235Smarkfen 		for (i = 0; i < rp->rule_locip_cnt; i++, lipp++) {
21304235Smarkfen 			print_addr_range("LOCIP:", lipp);
21314235Smarkfen 		}
21324235Smarkfen 	}
21334235Smarkfen 
21344235Smarkfen 	if (rp->rule_remip_cnt > 0) {
21354235Smarkfen 		(void) printf(gettext("REMIP: IP address range(s):\n"));
21364235Smarkfen 		ripp = (ike_addr_pr_t *)((int)rp + rp->rule_remip_off);
21374235Smarkfen 		for (i = 0; i < rp->rule_remip_cnt; i++, ripp++) {
21384235Smarkfen 			print_addr_range("REMIP:", ripp);
21394235Smarkfen 		}
21404235Smarkfen 	}
21414235Smarkfen 
21424235Smarkfen 	if (rp->rule_locid_inclcnt + rp->rule_locid_exclcnt > 0) {
21434235Smarkfen 		lidp = (char *)((int)rp + rp->rule_locid_off);
21444235Smarkfen 		print_idspec("LOCID:", lidp, rp->rule_locid_inclcnt,
21454235Smarkfen 		    rp->rule_locid_exclcnt);
21464235Smarkfen 	}
21474235Smarkfen 
21484235Smarkfen 	if (rp->rule_remid_inclcnt + rp->rule_remid_exclcnt > 0) {
21494235Smarkfen 		ridp = (char *)((int)rp + rp->rule_remid_off);
21504235Smarkfen 		print_idspec("REMID:", ridp, rp->rule_remid_inclcnt,
21514235Smarkfen 		    rp->rule_remid_exclcnt);
21524235Smarkfen 	}
21534235Smarkfen 
21544235Smarkfen 	if (rp->rule_xform_cnt > 0) {
21554235Smarkfen 		(void) printf(gettext("XFRMS: Available Transforms:\n"));
21564235Smarkfen 		xfp = (ike_p1_xform_t *)((int)rp +  rp->rule_xform_off);
21574235Smarkfen 		for (i = 0; i < rp->rule_xform_cnt; i++, xfp++) {
21584235Smarkfen 			(void) snprintf(prefix, PREFIXLEN, "XF %2u:", i);
21594235Smarkfen 			print_xform(prefix, xfp, B_TRUE);
21604235Smarkfen 		}
21614235Smarkfen 	}
21624235Smarkfen }
21634235Smarkfen 
21644235Smarkfen #undef	PREFIXLEN
21654235Smarkfen 
21664235Smarkfen #define	PRSACNTS(init, resp) \
21674235Smarkfen 		(void) printf(gettext("initiator: %10u   responder: %10u\n"), \
21684235Smarkfen 		    (init), (resp))
21694235Smarkfen 
21704235Smarkfen static void
21714235Smarkfen print_stats(ike_stats_t *sp, int len)
21724235Smarkfen {
21734235Smarkfen 	/*
21744235Smarkfen 	 * before printing each line, make sure the structure we were
21754235Smarkfen 	 * given is big enough to include the fields needed.
21764235Smarkfen 	 */
21774235Smarkfen 	if (len < COUNTER_PAIR)
21784235Smarkfen 		return;
21794235Smarkfen 	(void) printf(gettext("Phase 1 SA counts:\n"));
21804235Smarkfen 	(void) printf(gettext("Current:   "));
21814235Smarkfen 	PRSACNTS(sp->st_init_p1_current, sp->st_resp_p1_current);
21824235Smarkfen 	len -= COUNTER_PAIR;
21834235Smarkfen 
21844235Smarkfen 	if (len < COUNTER_PAIR)
21854235Smarkfen 		return;
21864235Smarkfen 	(void) printf(gettext("Total:     "));
21874235Smarkfen 	PRSACNTS(sp->st_init_p1_total, sp->st_resp_p1_total);
21884235Smarkfen 	len -= COUNTER_PAIR;
21894235Smarkfen 
21904235Smarkfen 	if (len < COUNTER_PAIR)
21914235Smarkfen 		return;
21924235Smarkfen 	(void) printf(gettext("Attempted: "));
21934235Smarkfen 	PRSACNTS(sp->st_init_p1_attempts, sp->st_resp_p1_attempts);
21944235Smarkfen 	len -= COUNTER_PAIR;
21954235Smarkfen 
21964235Smarkfen 	if (len < (COUNTER_PAIR + COUNTER_32BIT))
21974235Smarkfen 		return;
21984235Smarkfen 	(void) printf(gettext("Failed:    "));
21994235Smarkfen 	PRSACNTS(sp->st_init_p1_noresp + sp->st_init_p1_respfail,
22004235Smarkfen 	    sp->st_resp_p1_fail);
22014235Smarkfen 	(void) printf(
22024235Smarkfen 	    gettext("           initiator fails include %u time-out(s)\n"),
22034235Smarkfen 	    sp->st_init_p1_noresp);
22044235Smarkfen 
22054235Smarkfen 	if (len < PATH_MAX)
22064235Smarkfen 		return;
22074235Smarkfen 	if (*(sp->st_pkcs11_libname) != '\0')
22084235Smarkfen 		(void) printf(gettext("PKCS#11 library linked in from %s\n"),
22094235Smarkfen 		    sp->st_pkcs11_libname);
22104235Smarkfen }
22114235Smarkfen 
221211379SVladimir.Kotal@Sun.COM /* Print one line of 'get defaults' output (i.e. single value). */
22134235Smarkfen static void
221411379SVladimir.Kotal@Sun.COM print_defaults(char *label, char *description, char *unit,
22154235Smarkfen     uint_t current, uint_t def)
22164235Smarkfen {
221711379SVladimir.Kotal@Sun.COM 	(void) printf("%-18s%-10s%11u %-10s%-26s\n", label,
22184235Smarkfen 	    (current != def) ? gettext("config") : gettext("default"),
221911379SVladimir.Kotal@Sun.COM 	    current, unit, description);
22204235Smarkfen }
22214235Smarkfen 
22224235Smarkfen /*
22234235Smarkfen  * Print out defaults used by in.iked, the argument is a buffer containing
22244235Smarkfen  * two ike_defaults_t's, the first contains the hard coded defaults, the second
22254235Smarkfen  * contains the actual values used. If these differ, then the defaults have been
22264235Smarkfen  * changed via a config file entry. Note that "-" indicates this default
222711379SVladimir.Kotal@Sun.COM  * is not tunable via ike.config(4) or is system wide tunable.
22284235Smarkfen  */
22294235Smarkfen static void
22304235Smarkfen do_print_defaults(ike_defaults_t *dp)
22314235Smarkfen {
22324235Smarkfen 	ike_defaults_t *ddp;
22334235Smarkfen 	ddp = (ike_defaults_t *)(dp + 1);
22344235Smarkfen 
22354235Smarkfen 	(void) printf(gettext("\nGlobal defaults. Some values can be"
223611379SVladimir.Kotal@Sun.COM 	    " over-ridden on a per rule basis.\n"));
223711379SVladimir.Kotal@Sun.COM 	(void) printf(gettext("\nSystem defaults are time delayed.\n\n"));
223811379SVladimir.Kotal@Sun.COM 
223911379SVladimir.Kotal@Sun.COM 	(void) printf("%-18s%-10s%-12s%-10s%-26s\n\n",
22404235Smarkfen 	    gettext("Token:"), gettext("Source:"), gettext("Value:"),
22414235Smarkfen 	    gettext("Unit:"), gettext("Description:"));
22424235Smarkfen 
224311379SVladimir.Kotal@Sun.COM 	/* iked tunables */
22444235Smarkfen 	print_defaults("p1_lifetime_secs", gettext("phase 1 lifetime"),
224511379SVladimir.Kotal@Sun.COM 	    gettext("seconds"), ddp->rule_p1_lifetime_secs,
22464235Smarkfen 	    dp->rule_p1_lifetime_secs);
22474235Smarkfen 
22484235Smarkfen 	print_defaults("-", gettext("minimum phase 1 lifetime"),
224911379SVladimir.Kotal@Sun.COM 	    gettext("seconds"), ddp->rule_p1_minlife,
22504235Smarkfen 	    dp->rule_p1_minlife);
22514235Smarkfen 
22524235Smarkfen 	print_defaults("p1_nonce_len", gettext("phase 1 nonce length"),
225311379SVladimir.Kotal@Sun.COM 	    gettext("bytes"), ddp->rule_p1_nonce_len,
22544235Smarkfen 	    dp->rule_p1_nonce_len);
22554235Smarkfen 
22564235Smarkfen 	print_defaults("p2_lifetime_secs", gettext("phase 2 lifetime"),
225711379SVladimir.Kotal@Sun.COM 	    gettext("seconds"), ddp->rule_p2_lifetime_secs,
22584235Smarkfen 	    dp->rule_p2_lifetime_secs);
22594235Smarkfen 
22604235Smarkfen 	print_defaults("p2_softlife_secs", gettext("phase 2 soft lifetime"),
226111379SVladimir.Kotal@Sun.COM 	    gettext("seconds"), ddp->rule_p2_softlife_secs,
22624235Smarkfen 	    dp->rule_p2_softlife_secs);
22634235Smarkfen 
22647749SThejaswini.Singarajipura@Sun.COM 	print_defaults("p2_idletime_secs", gettext("phase 2 idle time"),
226511379SVladimir.Kotal@Sun.COM 	    gettext("seconds"), ddp->rule_p2_idletime_secs,
22667749SThejaswini.Singarajipura@Sun.COM 	    dp->rule_p2_idletime_secs);
22677749SThejaswini.Singarajipura@Sun.COM 
226811379SVladimir.Kotal@Sun.COM 	print_defaults("p2_lifetime_kb", gettext("phase 2 lifetime"),
226911379SVladimir.Kotal@Sun.COM 	    gettext("kilobytes"), ddp->rule_p2_lifetime_kb,
227011379SVladimir.Kotal@Sun.COM 	    dp->rule_p2_lifetime_kb);
227111379SVladimir.Kotal@Sun.COM 
227211379SVladimir.Kotal@Sun.COM 	print_defaults("p2_softlife_kb", gettext("phase 2 soft lifetime"),
227311379SVladimir.Kotal@Sun.COM 	    gettext("kilobytes"), ddp->rule_p2_softlife_kb,
227411379SVladimir.Kotal@Sun.COM 	    dp->rule_p2_softlife_kb);
227511379SVladimir.Kotal@Sun.COM 
227611379SVladimir.Kotal@Sun.COM 	/* system wide tunables */
22775213Smarkfen 	print_defaults("-", gettext("system phase 2 lifetime"),
227811379SVladimir.Kotal@Sun.COM 	    gettext("seconds"), ddp->sys_p2_lifetime_secs,
22795213Smarkfen 	    dp->sys_p2_lifetime_secs);
22805213Smarkfen 
22815213Smarkfen 	print_defaults("-", gettext("system phase 2 soft lifetime"),
228211379SVladimir.Kotal@Sun.COM 	    gettext("seconds"), ddp->sys_p2_softlife_secs,
22835213Smarkfen 	    dp->sys_p2_softlife_secs);
22845213Smarkfen 
22857749SThejaswini.Singarajipura@Sun.COM 	print_defaults("-", gettext("system phase 2 idle time"),
228611379SVladimir.Kotal@Sun.COM 	    gettext("seconds"), ddp->sys_p2_idletime_secs,
22877749SThejaswini.Singarajipura@Sun.COM 	    dp->sys_p2_idletime_secs);
22887749SThejaswini.Singarajipura@Sun.COM 
22895213Smarkfen 	print_defaults("-", gettext("system phase 2 lifetime"),
229011379SVladimir.Kotal@Sun.COM 	    gettext("bytes"), ddp->sys_p2_lifetime_bytes,
22915213Smarkfen 	    dp->sys_p2_lifetime_bytes);
22925213Smarkfen 
22935213Smarkfen 	print_defaults("-", gettext("system phase 2 soft lifetime"),
229411379SVladimir.Kotal@Sun.COM 	    gettext("bytes"), ddp->sys_p2_softlife_bytes,
22955213Smarkfen 	    dp->sys_p2_softlife_bytes);
22965213Smarkfen 
229711379SVladimir.Kotal@Sun.COM 	/* minimum and maximum values */
229811379SVladimir.Kotal@Sun.COM 	print_defaults("-", gettext("minimum phase 2 hard lifetime"),
229911379SVladimir.Kotal@Sun.COM 	    gettext("seconds"), ddp->rule_p2_minlife_hard_secs,
230011379SVladimir.Kotal@Sun.COM 	    dp->rule_p2_minlife_hard_secs);
230111379SVladimir.Kotal@Sun.COM 
230211379SVladimir.Kotal@Sun.COM 	print_defaults("-", gettext("minimum phase 2 soft lifetime"),
230311379SVladimir.Kotal@Sun.COM 	    gettext("seconds"), ddp->rule_p2_minlife_soft_secs,
230411379SVladimir.Kotal@Sun.COM 	    dp->rule_p2_minlife_soft_secs);
230511379SVladimir.Kotal@Sun.COM 
230611379SVladimir.Kotal@Sun.COM 	print_defaults("-", gettext("minimum phase 2 idle lifetime"),
230711379SVladimir.Kotal@Sun.COM 	    gettext("seconds"), ddp->rule_p2_minlife_idle_secs,
230811379SVladimir.Kotal@Sun.COM 	    dp->rule_p2_minlife_idle_secs);
230911379SVladimir.Kotal@Sun.COM 
231011379SVladimir.Kotal@Sun.COM 	print_defaults("-", gettext("minimum phase 2 hard lifetime"),
231111379SVladimir.Kotal@Sun.COM 	    gettext("kilobytes"), ddp->rule_p2_minlife_hard_kb,
231211379SVladimir.Kotal@Sun.COM 	    dp->rule_p2_minlife_hard_kb);
231311379SVladimir.Kotal@Sun.COM 
231411379SVladimir.Kotal@Sun.COM 	print_defaults("-", gettext("minimum phase 2 soft lifetime"),
231511379SVladimir.Kotal@Sun.COM 	    gettext("kilobytes"), ddp->rule_p2_minlife_soft_kb,
231611379SVladimir.Kotal@Sun.COM 	    dp->rule_p2_minlife_soft_kb);
231711379SVladimir.Kotal@Sun.COM 
231811379SVladimir.Kotal@Sun.COM 	print_defaults("-", gettext("minimum phase 2 delta"),
231911379SVladimir.Kotal@Sun.COM 	    gettext("seconds"), ddp->rule_p2_mindiff_secs,
232011379SVladimir.Kotal@Sun.COM 	    dp->rule_p2_mindiff_secs);
232111379SVladimir.Kotal@Sun.COM 
232211379SVladimir.Kotal@Sun.COM 	print_defaults("-", gettext("minimum phase 2 delta"),
232311379SVladimir.Kotal@Sun.COM 	    gettext("kilobytes"), ddp->rule_p2_mindiff_kb,
232411379SVladimir.Kotal@Sun.COM 	    dp->rule_p2_mindiff_kb);
232511379SVladimir.Kotal@Sun.COM 
232611379SVladimir.Kotal@Sun.COM 	print_defaults("-", gettext("maximum phase 2 lifetime"),
232711379SVladimir.Kotal@Sun.COM 	    gettext("seconds"), ddp->rule_p2_maxlife_secs,
232811379SVladimir.Kotal@Sun.COM 	    dp->rule_p2_maxlife_secs);
232911379SVladimir.Kotal@Sun.COM 
233011379SVladimir.Kotal@Sun.COM 	print_defaults("-", gettext("conversion factor"),
233111379SVladimir.Kotal@Sun.COM 	    gettext("kbytes/s"), ddp->conversion_factor,
233211379SVladimir.Kotal@Sun.COM 	    dp->conversion_factor);
233311379SVladimir.Kotal@Sun.COM 
233411379SVladimir.Kotal@Sun.COM 	print_defaults("-", gettext("maximum phase 2 lifetime"),
233511379SVladimir.Kotal@Sun.COM 	    gettext("kilobytes"), ddp->rule_p2_maxlife_kb,
233611379SVladimir.Kotal@Sun.COM 	    dp->rule_p2_maxlife_kb);
233711379SVladimir.Kotal@Sun.COM 
233811379SVladimir.Kotal@Sun.COM 	/* other values */
23394235Smarkfen 	print_defaults("p2_nonce_len", gettext("phase 2 nonce length"),
234011379SVladimir.Kotal@Sun.COM 	    gettext("bytes"), ddp->rule_p2_nonce_len,
23414235Smarkfen 	    dp->rule_p2_nonce_len);
23424235Smarkfen 
23434235Smarkfen 	print_defaults("p2_pfs", gettext("phase 2 PFS"),
234411379SVladimir.Kotal@Sun.COM 	    " ", ddp->rule_p2_pfs, dp->rule_p2_pfs);
23454235Smarkfen 
23464235Smarkfen 	print_defaults("max_certs", gettext("max certificates"),
234711379SVladimir.Kotal@Sun.COM 	    " ", ddp->rule_max_certs, dp->rule_max_certs);
23484235Smarkfen 
23494235Smarkfen 	print_defaults("-", gettext("IKE port number"),
235011379SVladimir.Kotal@Sun.COM 	    " ", ddp->rule_ike_port, dp->rule_ike_port);
23514235Smarkfen 
23524235Smarkfen 	print_defaults("-", gettext("NAT-T port number"),
235311379SVladimir.Kotal@Sun.COM 	    " ", ddp->rule_natt_port, dp->rule_natt_port);
23544235Smarkfen }
23554235Smarkfen 
23564235Smarkfen static void
23574235Smarkfen print_categories(int level)
23584235Smarkfen {
23594235Smarkfen 	int	mask;
23604235Smarkfen 
23614235Smarkfen 	if (level == 0) {
23624235Smarkfen 		(void) printf(gettext("No debug categories enabled.\n"));
23634235Smarkfen 		return;
23644235Smarkfen 	}
23654235Smarkfen 
23664235Smarkfen 	(void) printf(gettext("Debug categories enabled:"));
23674235Smarkfen 	for (mask = 1; mask <= D_HIGHBIT; mask <<= 1) {
23684235Smarkfen 		if (level & mask)
23694235Smarkfen 			(void) printf("\n\t%s", dbgstr(mask));
23704235Smarkfen 	}
23714235Smarkfen 	(void) printf("\n");
23724235Smarkfen }
23734235Smarkfen 
23744235Smarkfen /*PRINTFLIKE2*/
23754235Smarkfen static void
23764235Smarkfen ikeadm_err_exit(ike_err_t *err, char *fmt, ...)
23774235Smarkfen {
23784235Smarkfen 	va_list	ap;
23794235Smarkfen 	char	bailbuf[BUFSIZ];
23804235Smarkfen 
23814235Smarkfen 	va_start(ap, fmt);
23824235Smarkfen 	(void) vsnprintf(bailbuf, BUFSIZ, fmt, ap);
23834235Smarkfen 	va_end(ap);
23844235Smarkfen 	if ((err != NULL) && (err->ike_err == IKE_ERR_SYS_ERR)) {
23854235Smarkfen 		bail_msg("%s: %s", bailbuf, (err->ike_err_unix == 0) ?
23864235Smarkfen 		    gettext("<unknown error>") : strerror(err->ike_err_unix));
23874235Smarkfen 	} else {
23884235Smarkfen 		bail_msg("%s: %s", bailbuf, (err == NULL) ?
23894235Smarkfen 		    gettext("<unknown error>") : errstr(err->ike_err));
23904235Smarkfen 	}
23914235Smarkfen }
23924235Smarkfen 
23934235Smarkfen /*PRINTFLIKE2*/
23944235Smarkfen static void
23954235Smarkfen ikeadm_err_msg(ike_err_t *err, char *fmt, ...)
23964235Smarkfen {
23974235Smarkfen 	va_list	ap;
23984235Smarkfen 	char	mbuf[BUFSIZ];
23994235Smarkfen 
24004235Smarkfen 	va_start(ap, fmt);
24014235Smarkfen 	(void) vsnprintf(mbuf, BUFSIZ, fmt, ap);
24024235Smarkfen 	va_end(ap);
24034235Smarkfen 	if ((err != NULL) && (err->ike_err == IKE_ERR_SYS_ERR)) {
24044235Smarkfen 		message("%s: %s", mbuf, (err->ike_err_unix == 0) ?
24054235Smarkfen 		    gettext("<unknown error>") :
24064235Smarkfen 		    ((err->ike_err_unix == EEXIST) ?
24074235Smarkfen 		    gettext("Duplicate entry") :
24084235Smarkfen 		    strerror(err->ike_err_unix)));
24094235Smarkfen 	} else {
24104235Smarkfen 		message("%s: %s", mbuf, (err == NULL) ?
24114235Smarkfen 		    gettext("<unknown error>") : errstr(err->ike_err));
24124235Smarkfen 	}
24134235Smarkfen }
24144235Smarkfen 
24154235Smarkfen 
24164235Smarkfen /*
24174235Smarkfen  * Command functions
24184235Smarkfen  */
24194235Smarkfen 
24204235Smarkfen /*
24214235Smarkfen  * Exploit the fact that ike_dbg_t and ike_priv_t have identical
24224235Smarkfen  * formats in the following two functions.
24234235Smarkfen  */
24244235Smarkfen static void
24254235Smarkfen do_getvar(int cmd)
24264235Smarkfen {
24274235Smarkfen 	ike_service_t	req, *rtn;
24284235Smarkfen 	ike_dbg_t	*dreq;
24294235Smarkfen 	char		*varname;
24304235Smarkfen 
24314235Smarkfen 	switch (cmd) {
24324235Smarkfen 	case IKE_SVC_GET_DBG:
24334235Smarkfen 		varname = gettext("debug");
24344235Smarkfen 		break;
24354235Smarkfen 	case IKE_SVC_GET_PRIV:
24364235Smarkfen 		varname = gettext("privilege");
24374235Smarkfen 		break;
24384235Smarkfen 	default:
24394235Smarkfen 		bail_msg(gettext("unrecognized get command (%d)"), cmd);
24404235Smarkfen 	}
24414235Smarkfen 
24424235Smarkfen 	dreq = &req.svc_dbg;
24434235Smarkfen 	dreq->cmd = cmd;
24444235Smarkfen 	dreq->dbg_level = 0;
24454235Smarkfen 
24464235Smarkfen 	rtn = ikedoor_call((char *)&req, sizeof (ike_dbg_t), NULL, 0);
24474235Smarkfen 
24484235Smarkfen 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
24494235Smarkfen 		ikeadm_err_exit(&rtn->svc_err,
24504235Smarkfen 		    gettext("error getting %s level"), varname);
24514235Smarkfen 	}
24524235Smarkfen 	dreq = &rtn->svc_dbg;
24534235Smarkfen 	(void) printf(gettext("Current %s level is 0x%x"),
24544235Smarkfen 	    varname, dreq->dbg_level);
24554235Smarkfen 
24564235Smarkfen 	if (cmd == IKE_SVC_GET_DBG) {
24574235Smarkfen 		(void) printf("\n");
24584235Smarkfen 		print_categories(dreq->dbg_level);
24594235Smarkfen 	} else {
24604235Smarkfen 		(void) printf(gettext(", %s enabled\n"),
24614235Smarkfen 		    privstr(dreq->dbg_level));
24624235Smarkfen 	}
24634235Smarkfen }
24644235Smarkfen 
24658596SPaul.Wernau@Sun.COM /*
24668596SPaul.Wernau@Sun.COM  * Log into a token and unlock all objects
24678596SPaul.Wernau@Sun.COM  * referenced by PKCS#11 hint files.
24688596SPaul.Wernau@Sun.COM  */
24698596SPaul.Wernau@Sun.COM static void
24708596SPaul.Wernau@Sun.COM do_setdel_pin(int cmd, int argc, char **argv)
24718596SPaul.Wernau@Sun.COM {
24728596SPaul.Wernau@Sun.COM 	ike_service_t	req, *rtn;
24738596SPaul.Wernau@Sun.COM 	ike_pin_t	*preq;
24748596SPaul.Wernau@Sun.COM 	char		token_label[PKCS11_TOKSIZE];
24758596SPaul.Wernau@Sun.COM 	char		*token_pin;
24768596SPaul.Wernau@Sun.COM 	char		prompt[80];
24778596SPaul.Wernau@Sun.COM 
24788596SPaul.Wernau@Sun.COM 	if (argc < 1)
24798596SPaul.Wernau@Sun.COM 		Bail(gettext("Must specify PKCS#11 token object."));
24808596SPaul.Wernau@Sun.COM 
24818596SPaul.Wernau@Sun.COM 	preq = &req.svc_pin;
24828596SPaul.Wernau@Sun.COM 	preq->cmd = cmd;
24838596SPaul.Wernau@Sun.COM 
24848596SPaul.Wernau@Sun.COM 	switch (cmd) {
24858596SPaul.Wernau@Sun.COM 	case IKE_SVC_SET_PIN:
24868596SPaul.Wernau@Sun.COM 		if (parse_token(argc, argv, token_label) != 0)
24878596SPaul.Wernau@Sun.COM 			Bail("Invalid syntax for \"token login\"");
24888596SPaul.Wernau@Sun.COM 		(void) snprintf(prompt, sizeof (prompt),
24898596SPaul.Wernau@Sun.COM 		    "Enter PIN for PKCS#11 token \'%s\': ", token_label);
24908596SPaul.Wernau@Sun.COM 		token_pin =
24918596SPaul.Wernau@Sun.COM 		    getpassphrase(prompt);
24928596SPaul.Wernau@Sun.COM 		(void) strlcpy((char *)preq->token_pin, token_pin, MAX_PIN_LEN);
24938596SPaul.Wernau@Sun.COM 		bzero(token_pin, strlen(token_pin));
24948596SPaul.Wernau@Sun.COM 		break;
24958596SPaul.Wernau@Sun.COM 	case IKE_SVC_DEL_PIN:
24968596SPaul.Wernau@Sun.COM 		if (parse_token(argc, argv, token_label) != 0)
24978596SPaul.Wernau@Sun.COM 			Bail("Invalid syntax for \"token logout\"");
24988596SPaul.Wernau@Sun.COM 		break;
24998596SPaul.Wernau@Sun.COM 	default:
25008596SPaul.Wernau@Sun.COM 		bail_msg(gettext("unrecognized token command (%d)"), cmd);
25018596SPaul.Wernau@Sun.COM 	}
25028596SPaul.Wernau@Sun.COM 
25038596SPaul.Wernau@Sun.COM 	(void) strlcpy(preq->pkcs11_token, token_label, PKCS11_TOKSIZE);
25048596SPaul.Wernau@Sun.COM 
25058596SPaul.Wernau@Sun.COM 	rtn = ikedoor_call((char *)&req, sizeof (ike_pin_t), NULL, 0);
25068596SPaul.Wernau@Sun.COM 	if (cmd == IKE_SVC_SET_PIN)
25078596SPaul.Wernau@Sun.COM 		bzero(preq->token_pin, sizeof (preq->token_pin));
25088596SPaul.Wernau@Sun.COM 
25098596SPaul.Wernau@Sun.COM 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
25108596SPaul.Wernau@Sun.COM 		ikeadm_err_exit(&rtn->svc_err,
25118596SPaul.Wernau@Sun.COM 		    gettext("PKCS#11 operation"));
25128596SPaul.Wernau@Sun.COM 	}
25138596SPaul.Wernau@Sun.COM 	preq = &rtn->svc_pin;
25148596SPaul.Wernau@Sun.COM 	message(gettext("PKCS#11 operation successful"));
25158596SPaul.Wernau@Sun.COM }
25168596SPaul.Wernau@Sun.COM 
25174235Smarkfen static void
25184235Smarkfen do_setvar(int cmd, int argc, char **argv)
25194235Smarkfen {
25204235Smarkfen 	ike_service_t	req, *rtn;
25214235Smarkfen 	ike_dbg_t	*dreq;
25224235Smarkfen 	door_desc_t	*descp = NULL, desc;
25234235Smarkfen 	int		fd, ndesc = 0;
25244235Smarkfen 	uint32_t	reqlevel;
25254235Smarkfen 	char		*varname;
25264235Smarkfen 
25274235Smarkfen 	if (argc < 1)
25284235Smarkfen 		Bail("unspecified level");
25294235Smarkfen 	reqlevel = strtoul(argv[0], NULL, 0);
25304235Smarkfen 
25314235Smarkfen 	switch (cmd) {
25324235Smarkfen 	case IKE_SVC_SET_DBG:
25334235Smarkfen 		if (argc > 2)
25344235Smarkfen 			Bail("Too many arguments to \"set debug\"");
25354235Smarkfen 		varname = gettext("debug");
25364235Smarkfen 		if (reqlevel == 0) {
25374235Smarkfen 			/* check for a string... */
25384235Smarkfen 			reqlevel = parsedbgopts(argv[0]);
25394235Smarkfen 		}
25404235Smarkfen 		if (reqlevel == D_INVALID)
25414235Smarkfen 			bail_msg(gettext("Bad debug flag: %s"), argv[0]);
25424235Smarkfen 		break;
25434235Smarkfen 	case IKE_SVC_SET_PRIV:
25444235Smarkfen 		if (argc > 1)
25454235Smarkfen 			Bail("Too many arguments to \"set priv\"");
25464235Smarkfen 
25474235Smarkfen 		varname = gettext("privilege");
25484235Smarkfen 		if (reqlevel == 0) {
25494235Smarkfen 			/* check for a string... */
25504235Smarkfen 			reqlevel = privstr2num(argv[0]);
25514235Smarkfen 		}
25524235Smarkfen 		if (reqlevel > IKE_PRIV_MAXIMUM)
25534235Smarkfen 			bail_msg(gettext("Bad privilege flag: %s"), argv[0]);
25544235Smarkfen 		break;
25554235Smarkfen 	default:
25564235Smarkfen 		bail_msg(gettext("unrecognized set command (%d)"), cmd);
25574235Smarkfen 	}
25584235Smarkfen 
25594235Smarkfen 	dreq = &req.svc_dbg;
25604235Smarkfen 	dreq->cmd = cmd;
25614235Smarkfen 	dreq->dbg_level = reqlevel;
25624235Smarkfen 
25634235Smarkfen 	if ((argc == 2) && (cmd == IKE_SVC_SET_DBG)) {
25644235Smarkfen 		fd = open(argv[1], O_RDWR | O_CREAT | O_APPEND,
25654235Smarkfen 		    S_IRUSR | S_IWUSR);
25664235Smarkfen 		if (fd < 0)
25674235Smarkfen 			Bail("open debug file");
25684235Smarkfen 		desc.d_data.d_desc.d_descriptor = fd;
25694235Smarkfen 		desc.d_attributes = DOOR_DESCRIPTOR;
25704235Smarkfen 		descp = &desc;
25714235Smarkfen 		ndesc = 1;
25724235Smarkfen 	}
25734235Smarkfen 
25744235Smarkfen 	rtn = ikedoor_call((char *)&req, sizeof (ike_dbg_t), descp, ndesc);
25754235Smarkfen 
25764235Smarkfen 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
25774235Smarkfen 		ikeadm_err_exit(&rtn->svc_err,
25784235Smarkfen 		    gettext("error setting %s level"), varname);
25794235Smarkfen 	}
25804235Smarkfen 	dreq = &rtn->svc_dbg;
25814235Smarkfen 	(void) printf(
25824235Smarkfen 	    gettext("Successfully changed %s level from 0x%x to 0x%x\n"),
25834235Smarkfen 	    varname, dreq->dbg_level, reqlevel);
25844235Smarkfen 
25854235Smarkfen 	if (cmd == IKE_SVC_SET_DBG) {
25864235Smarkfen 		print_categories(reqlevel);
25874235Smarkfen 	} else {
25884235Smarkfen 		(void) printf(gettext("New privilege level 0x%x enables %s\n"),
25894235Smarkfen 		    reqlevel, privstr(reqlevel));
25904235Smarkfen 	}
25914235Smarkfen }
25924235Smarkfen 
25934235Smarkfen static void
25944235Smarkfen do_getstats(int cmd)
25954235Smarkfen {
25964235Smarkfen 	ike_service_t	*rtn;
25974235Smarkfen 	ike_statreq_t	sreq, *sreqp;
25984235Smarkfen 	ike_stats_t	*sp;
25994235Smarkfen 
26004235Smarkfen 	sreq.cmd = cmd;
26014235Smarkfen 
26024235Smarkfen 	rtn = ikedoor_call((char *)&sreq, sizeof (ike_statreq_t), NULL, 0);
26034235Smarkfen 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
26044235Smarkfen 		ikeadm_err_exit(&rtn->svc_err, gettext("error getting stats"));
26054235Smarkfen 	}
26064235Smarkfen 
26074235Smarkfen 	sreqp = &rtn->svc_stats;
26084235Smarkfen 	sp = (ike_stats_t *)(sreqp + 1);
26094235Smarkfen 	print_stats(sp, sreqp->stat_len);
26104235Smarkfen }
26114235Smarkfen 
26124235Smarkfen static void
26134235Smarkfen do_getdefs(int cmd)
26144235Smarkfen {
26154235Smarkfen 	ike_service_t	*rtn;
26164235Smarkfen 	ike_defreq_t	dreq, *dreqp;
26174235Smarkfen 	ike_defaults_t	*dp;
26184235Smarkfen 
26194235Smarkfen 	dreq.cmd = cmd;
26204235Smarkfen 
26214235Smarkfen 	rtn = ikedoor_call((char *)&dreq, sizeof (ike_defreq_t), NULL, 0);
26224235Smarkfen 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
26234235Smarkfen 		ikeadm_err_exit(&rtn->svc_err,
26244235Smarkfen 		    gettext("error getting defaults"));
26254235Smarkfen 	}
26264235Smarkfen 
26274235Smarkfen 	dreqp = &rtn->svc_defaults;
26284235Smarkfen 	dp = (ike_defaults_t *)(dreqp + 1);
26294235Smarkfen 
26304235Smarkfen 	/*
26314235Smarkfen 	 * Before printing each line, make sure the structure we were
26324235Smarkfen 	 * given is big enough to include the fields needed.
26334235Smarkfen 	 * Silently bail out of there is a version mismatch.
26344235Smarkfen 	 */
26354235Smarkfen 	if (dreqp->stat_len < ((2 * sizeof (ike_defaults_t))
26364235Smarkfen 	    + sizeof (ike_defreq_t)) || dreqp->version != DOORVER) {
26374235Smarkfen 		return;
26384235Smarkfen 	}
26394235Smarkfen 	do_print_defaults(dp);
26404235Smarkfen }
26414235Smarkfen 
26424235Smarkfen static void
26434235Smarkfen do_dump(int cmd)
26444235Smarkfen {
26454235Smarkfen 	char		*name;
26464235Smarkfen 	ike_service_t	req, *rtn;
26474235Smarkfen 	ike_dump_t	*dreq, *dump;
26484235Smarkfen 
26494235Smarkfen 	switch (cmd) {
26504235Smarkfen 	case IKE_SVC_DUMP_P1S:
26514235Smarkfen 		name = gettext("phase 1 SA info");
26524235Smarkfen 		break;
26534235Smarkfen 	case IKE_SVC_DUMP_RULES:
26544235Smarkfen 		name = gettext("policy rules");
26554235Smarkfen 		break;
26564235Smarkfen 	case IKE_SVC_DUMP_PS:
26574235Smarkfen 		name = gettext("preshared keys");
26584235Smarkfen 		break;
26598596SPaul.Wernau@Sun.COM 	case IKE_SVC_DUMP_CERTCACHE:
26608596SPaul.Wernau@Sun.COM 		name = gettext("certcache");
26618596SPaul.Wernau@Sun.COM 		break;
2662*12129SVladimir.Kotal@Sun.COM 	case IKE_SVC_DUMP_GROUPS:
2663*12129SVladimir.Kotal@Sun.COM 		name = gettext("groups");
2664*12129SVladimir.Kotal@Sun.COM 		print_group_header();
2665*12129SVladimir.Kotal@Sun.COM 		break;
2666*12129SVladimir.Kotal@Sun.COM 	case IKE_SVC_DUMP_ENCRALGS:
2667*12129SVladimir.Kotal@Sun.COM 		name = gettext("encralgs");
2668*12129SVladimir.Kotal@Sun.COM 		print_encralg_header();
2669*12129SVladimir.Kotal@Sun.COM 		break;
2670*12129SVladimir.Kotal@Sun.COM 	case IKE_SVC_DUMP_AUTHALGS:
2671*12129SVladimir.Kotal@Sun.COM 		name = gettext("authalgs");
2672*12129SVladimir.Kotal@Sun.COM 		print_authalg_header();
2673*12129SVladimir.Kotal@Sun.COM 		break;
26744235Smarkfen 	default:
26754235Smarkfen 		bail_msg(gettext("unrecognized dump command (%d)"), cmd);
26764235Smarkfen 	}
26774235Smarkfen 
26784235Smarkfen 	dreq = &req.svc_dump;
26794235Smarkfen 	dreq->cmd = cmd;
26804235Smarkfen 	dreq->dump_len = 0;
26814235Smarkfen 	dreq->dump_next = 0;
26824235Smarkfen 	do {
26834235Smarkfen 		rtn = ikedoor_call((char *)&req, sizeof (ike_dump_t),
26844235Smarkfen 		    NULL, 0);
26854235Smarkfen 		if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
26864235Smarkfen 			if (rtn && (rtn->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
26874235Smarkfen 				/* no entries to print */
26884235Smarkfen 				break;
26894235Smarkfen 			}
26904235Smarkfen 			ikeadm_err_exit(&rtn->svc_err,
26914235Smarkfen 			    gettext("error getting %s"), name);
26924235Smarkfen 		}
26934235Smarkfen 		dump = &rtn->svc_dump;
26944235Smarkfen 
26954235Smarkfen 		switch (cmd) {
26964235Smarkfen 		case IKE_SVC_DUMP_P1S:
26974235Smarkfen 			print_p1((ike_p1_sa_t *)(dump + 1));
26984235Smarkfen 			break;
26994235Smarkfen 		case IKE_SVC_DUMP_RULES:
27004235Smarkfen 			print_rule((ike_rule_t *)(dump + 1));
27014235Smarkfen 			break;
27024235Smarkfen 		case IKE_SVC_DUMP_PS:
27034235Smarkfen 			print_ps((ike_ps_t *)(dump + 1));
27044235Smarkfen 			break;
27058596SPaul.Wernau@Sun.COM 		case IKE_SVC_DUMP_CERTCACHE:
27068596SPaul.Wernau@Sun.COM 			print_certcache((ike_certcache_t *)(dump + 1));
27078596SPaul.Wernau@Sun.COM 			break;
2708*12129SVladimir.Kotal@Sun.COM 		case IKE_SVC_DUMP_GROUPS:
2709*12129SVladimir.Kotal@Sun.COM 			print_group((ike_group_t *)(dump + 1));
2710*12129SVladimir.Kotal@Sun.COM 			break;
2711*12129SVladimir.Kotal@Sun.COM 		case IKE_SVC_DUMP_ENCRALGS:
2712*12129SVladimir.Kotal@Sun.COM 			print_encralg((ike_encralg_t *)(dump + 1));
2713*12129SVladimir.Kotal@Sun.COM 			break;
2714*12129SVladimir.Kotal@Sun.COM 		case IKE_SVC_DUMP_AUTHALGS:
2715*12129SVladimir.Kotal@Sun.COM 			print_authalg((ike_authalg_t *)(dump + 1));
2716*12129SVladimir.Kotal@Sun.COM 			break;
27174235Smarkfen 		}
27184235Smarkfen 
27194235Smarkfen 		dreq->dump_next = dump->dump_next;
27204235Smarkfen 
27214235Smarkfen 		(void) munmap((char *)rtn, dump->dump_len);
27224235Smarkfen 
27234235Smarkfen 	} while (dreq->dump_next);
27244235Smarkfen 
27254235Smarkfen 	(void) printf(gettext("\nCompleted dump of %s\n"), name);
27264235Smarkfen }
27274235Smarkfen 
27284235Smarkfen static void
27294235Smarkfen do_getdel_doorcall(int cmd, int idlen, int idtype, char *idp, char *name)
27304235Smarkfen {
27314235Smarkfen 	int		totallen;
27324235Smarkfen 	char		*p;
27334235Smarkfen 	ike_service_t	*reqp, *rtnp;
27344235Smarkfen 	ike_get_t	*getp;
27354235Smarkfen 	boolean_t	getcmd;
27364235Smarkfen 
27374235Smarkfen 	getcmd = ((cmd == IKE_SVC_GET_P1) || (cmd == IKE_SVC_GET_RULE) ||
27384235Smarkfen 	    (cmd == IKE_SVC_GET_PS));
27394235Smarkfen 
27404235Smarkfen 	/*
27414235Smarkfen 	 * WARNING: to avoid being redundant, this code takes advantage
27424235Smarkfen 	 * of the fact that the ike_get_t and ike_del_t structures are
27434235Smarkfen 	 * identical (only the field names differ, their function and
27444235Smarkfen 	 * size are the same).  If for some reason those structures
27454235Smarkfen 	 * change, this code will need to be re-written to accomodate
27464235Smarkfen 	 * that difference.
27474235Smarkfen 	 */
27484235Smarkfen 	totallen = sizeof (ike_get_t) + idlen;
27494235Smarkfen 	if ((reqp = (ike_service_t *)malloc(totallen)) == NULL)
27504235Smarkfen 		Bail("malloc(id)");
27514235Smarkfen 
27524235Smarkfen 	getp = &reqp->svc_get;
27534235Smarkfen 	getp->cmd = cmd;
27544235Smarkfen 	getp->get_len = totallen;
27554235Smarkfen 	getp->get_idtype = idtype;
27564235Smarkfen 	p = (char *)(getp + 1);
27574235Smarkfen 
27584235Smarkfen 	(void) memcpy(p, idp, idlen);
27594235Smarkfen 
27604235Smarkfen 	rtnp = ikedoor_call((char *)reqp, totallen, NULL, 0);
27614235Smarkfen 	if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
27624235Smarkfen 		if (rtnp && (rtnp->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
27634235Smarkfen 			message(gettext("Could not find requested %s."), name);
27644235Smarkfen 		} else {
27654235Smarkfen 			ikeadm_err_msg(&rtnp->svc_err, gettext("error %s %s"),
27664235Smarkfen 			    (getcmd) ? gettext("getting") : gettext("deleting"),
27674235Smarkfen 			    name);
27684235Smarkfen 		}
27694235Smarkfen 		free(reqp);
27704235Smarkfen 		return;
27714235Smarkfen 	}
27724235Smarkfen 	getp = &rtnp->svc_get;
27734235Smarkfen 
27744235Smarkfen 	if (getcmd) {
27754235Smarkfen 		switch (cmd) {
27764235Smarkfen 		case IKE_SVC_GET_P1:
27774235Smarkfen 			print_p1((ike_p1_sa_t *)(getp + 1));
27784235Smarkfen 			break;
27794235Smarkfen 		case IKE_SVC_GET_PS:
27804235Smarkfen 			print_ps((ike_ps_t *)(getp + 1));
27814235Smarkfen 			break;
27824235Smarkfen 		case IKE_SVC_GET_RULE:
27834235Smarkfen 			print_rule((ike_rule_t *)(getp + 1));
27844235Smarkfen 			break;
27854235Smarkfen 		}
27864235Smarkfen 	} else {
27874235Smarkfen 		message(gettext("Successfully deleted selected %s."), name);
27884235Smarkfen 	}
27894235Smarkfen 
27904235Smarkfen 	(void) munmap((char *)rtnp, getp->get_len);
27914235Smarkfen 	free(reqp);
27924235Smarkfen }
27934235Smarkfen 
27944235Smarkfen static void
27954235Smarkfen do_getdel(int cmd, int argc, char **argv)
27964235Smarkfen {
27974235Smarkfen 	int		idlen, idtype = 0, i, j;
27984235Smarkfen 	int		bytelen1, bytelen2;
27994235Smarkfen 	char		*name, *idp, *p, *p1, *p2;
28004235Smarkfen 	ike_addr_pr_t	apr;
28014235Smarkfen 	ike_cky_pr_t	cpr;
28024235Smarkfen 	sadb_ident_t	*sid1p, *sid2p;
28034235Smarkfen 	struct hostent	*he1p, *he2p;
28044235Smarkfen 	char		label[MAX_LABEL_LEN];
28054235Smarkfen 
28064235Smarkfen 	if ((argc < 1) || (argv[0] == NULL)) {
28074235Smarkfen 		Bail("not enough identification info");
28084235Smarkfen 	}
28094235Smarkfen 
28104235Smarkfen 	switch (cmd) {
28114235Smarkfen 	case IKE_SVC_GET_P1:
28124235Smarkfen 	case IKE_SVC_DEL_P1:
28134235Smarkfen 		name = gettext("phase 1 SA");
28144235Smarkfen 		/*
28154235Smarkfen 		 * The first token must either be an address (or hostname)
28164235Smarkfen 		 * or a cookie.  We require cookies to be entered as hex
28174235Smarkfen 		 * numbers, beginning with 0x; so if our token starts with
28184235Smarkfen 		 * that, it's a cookie.
28194235Smarkfen 		 */
28204235Smarkfen 		if (strncmp(argv[0], "0x", 2) == 0) {
28214235Smarkfen 			if (parse_cky_pr(argc, argv, &cpr) >= 0) {
28224235Smarkfen 				idtype = IKE_ID_CKY_PAIR;
28234235Smarkfen 				idlen = sizeof (ike_cky_pr_t);
28244235Smarkfen 				idp = (char *)&cpr;
28254235Smarkfen 			}
28264235Smarkfen 		} else {
28274235Smarkfen 			if (parse_addr_pr(argc, argv, &he1p, &he2p) >= 0) {
28284235Smarkfen 				idtype = IKE_ID_ADDR_PAIR;
28294235Smarkfen 				idlen = sizeof (ike_addr_pr_t);
28304235Smarkfen 			}
28314235Smarkfen 		}
28324235Smarkfen 		break;
28334235Smarkfen 
28344235Smarkfen 	case IKE_SVC_GET_RULE:
28354235Smarkfen 	case IKE_SVC_DEL_RULE:
28364235Smarkfen 		name = gettext("policy rule");
28374235Smarkfen 		if (parse_label(argc, argv, label) >= 0) {
28384235Smarkfen 			idtype = IKE_ID_LABEL;
28394235Smarkfen 			idlen = MAX_LABEL_LEN;
28404235Smarkfen 			idp = label;
28414235Smarkfen 		}
28424235Smarkfen 		break;
28434235Smarkfen 
28444235Smarkfen 	case IKE_SVC_GET_PS:
28454235Smarkfen 	case IKE_SVC_DEL_PS:
28464235Smarkfen 		name = gettext("preshared key");
28474235Smarkfen 		/*
28484235Smarkfen 		 * The first token must either be an address or an ident
28494235Smarkfen 		 * type.  Check for an ident type to determine which it is.
28504235Smarkfen 		 */
28514235Smarkfen 		if (parse_idtype(argv[0], NULL) >= 0) {
28524235Smarkfen 			if (parse_ident_pr(argc, argv, &sid1p, &sid2p) >= 0) {
28534235Smarkfen 				idtype = IKE_ID_IDENT_PAIR;
28544235Smarkfen 				idlen = SADB_64TO8(sid1p->sadb_ident_len) +
28554235Smarkfen 				    SADB_64TO8(sid2p->sadb_ident_len);
28564235Smarkfen 			}
28574235Smarkfen 		} else {
28584235Smarkfen 			if (parse_addr_pr(argc, argv, &he1p, &he2p) >= 0) {
28594235Smarkfen 				idtype = IKE_ID_ADDR_PAIR;
28604235Smarkfen 				idlen = sizeof (ike_addr_pr_t);
28614235Smarkfen 			}
28624235Smarkfen 		}
28634235Smarkfen 		break;
28644235Smarkfen 
28654235Smarkfen 	default:
28664235Smarkfen 		bail_msg(gettext("unrecognized get/del command (%d)"), cmd);
28674235Smarkfen 	}
28684235Smarkfen 
28694235Smarkfen 	switch (idtype) {
28704235Smarkfen 	case IKE_ID_ADDR_PAIR:
28714235Smarkfen 		/*
28724235Smarkfen 		 * we might have exploding addrs here; do every possible
28734235Smarkfen 		 * combination.
28744235Smarkfen 		 */
28754235Smarkfen 		i = 0;
28764235Smarkfen 		j = 0;
28774235Smarkfen 		while ((p1 = he1p->h_addr_list[i++]) != NULL) {
28784235Smarkfen 			headdr2sa(p1, &apr.loc_addr, he1p->h_length);
28794235Smarkfen 
28804235Smarkfen 			while ((p2 = he2p->h_addr_list[j++]) != NULL) {
28814235Smarkfen 				headdr2sa(p2, &apr.rem_addr, he2p->h_length);
28824235Smarkfen 				do_getdel_doorcall(cmd, idlen, idtype,
28834235Smarkfen 				    (char *)&apr, name);
28844235Smarkfen 			}
28854235Smarkfen 		}
28864235Smarkfen 		FREE_HE(he1p);
28874235Smarkfen 		FREE_HE(he2p);
28884235Smarkfen 		break;
28894235Smarkfen 
28904235Smarkfen 	case IKE_ID_IDENT_PAIR:
28914235Smarkfen 		bytelen1 = SADB_64TO8(sid1p->sadb_ident_len);
28924235Smarkfen 		bytelen2 = SADB_64TO8(sid2p->sadb_ident_len);
28934235Smarkfen 		if (idlen != bytelen1 + bytelen2)
28944235Smarkfen 			Bail("ident syntax error");
28954235Smarkfen 		idp = p = (char *)malloc(idlen);
28964235Smarkfen 		if (p == NULL)
28974235Smarkfen 			Bail("malloc(id)");
28984235Smarkfen 		(void) memcpy(p, (char *)sid1p, bytelen1);
28994235Smarkfen 		p += bytelen1;
29004235Smarkfen 		(void) memcpy(p, (char *)sid2p, bytelen2);
29014235Smarkfen 		do_getdel_doorcall(cmd, idlen, idtype, idp, name);
29024235Smarkfen 		free(idp);
29034235Smarkfen 		free(sid1p);
29044235Smarkfen 		free(sid2p);
29054235Smarkfen 		break;
29064235Smarkfen 
29074235Smarkfen 	case IKE_ID_CKY_PAIR:
29084235Smarkfen 	case IKE_ID_LABEL:
29094235Smarkfen 		do_getdel_doorcall(cmd, idlen, idtype, idp, name);
29104235Smarkfen 		break;
29114235Smarkfen 
29124235Smarkfen 	case 0:
29134235Smarkfen 	default:
29144235Smarkfen 		bail_msg(gettext("invalid %s identification\n"), name);
29154235Smarkfen 	}
29164235Smarkfen }
29174235Smarkfen 
29184235Smarkfen /*
29194235Smarkfen  * Copy source into target, inserting an escape character ('\') before
29204235Smarkfen  * any quotes that appear.  Return true on success, false on failure.
29214235Smarkfen  */
29224235Smarkfen static boolean_t
29234235Smarkfen escapequotes(char *target, char *source, int tlen)
29244235Smarkfen {
29254235Smarkfen 	int	s, t, len = strlen(source) + 1;
29264235Smarkfen 
29274235Smarkfen 	if (tlen < len)
29284235Smarkfen 		return (B_FALSE);
29294235Smarkfen 
29304235Smarkfen 	for (s = 0, t = 0; s < len && t < tlen; s++) {
29314235Smarkfen 		if (source[s] == '\"')
29324235Smarkfen 			target[t++] = '\\';
29334235Smarkfen 		target[t++] = source[s];
29344235Smarkfen 	}
29354235Smarkfen 
29364235Smarkfen 	if ((t == tlen) && (s < len))
29374235Smarkfen 		return (B_FALSE);
29384235Smarkfen 
29394235Smarkfen 	return (B_TRUE);
29404235Smarkfen }
29414235Smarkfen 
29424235Smarkfen /*
29434235Smarkfen  * Return true if the arg following the given keyword should
29444235Smarkfen  * be in quotes (i.e. is a string), false if not.
29454235Smarkfen  */
29464235Smarkfen static boolean_t
29474235Smarkfen quotedfield(char *keywd)
29484235Smarkfen {
29494235Smarkfen 	if ((strncmp(keywd, "label", strlen("label") + 1) == 0) ||
29504235Smarkfen 	    (strncmp(keywd, "local_id", strlen("local_id") + 1) == 0) ||
29514235Smarkfen 	    (strncmp(keywd, "remote_id", strlen("remote_id") + 1) == 0))
29524235Smarkfen 		return (B_TRUE);
29534235Smarkfen 
29544235Smarkfen 	return (B_FALSE);
29554235Smarkfen }
29564235Smarkfen 
29574235Smarkfen static void
29584235Smarkfen do_new(int cmd, int argc, char **argv)
29594235Smarkfen {
29604235Smarkfen 	ike_service_t	*rtn;
29614235Smarkfen 	ike_new_t	new, *newp = NULL;
29624235Smarkfen 	door_desc_t	desc, *descp = NULL;
29634235Smarkfen 	int		i, fd, ndesc = 0, buflen;
29644235Smarkfen 	char		*name, tmpfilepath[32];
29654235Smarkfen 	FILE		*tmpfile;
29664235Smarkfen 
29674235Smarkfen 	switch (cmd) {
29684235Smarkfen 	case IKE_SVC_NEW_PS:
29694235Smarkfen 		name = gettext("preshared key");
29704235Smarkfen 		break;
29714235Smarkfen 	case IKE_SVC_NEW_RULE:
29724235Smarkfen 		name = gettext("policy rule");
29734235Smarkfen 		break;
29744235Smarkfen 	default:
29754235Smarkfen 		bail_msg(gettext("unrecognized new command (%d)"), cmd);
29764235Smarkfen 	}
29774235Smarkfen 
29784235Smarkfen 	if (argc == 1) {
29794235Smarkfen 		/* We've been given a file to read from */
29804235Smarkfen 		fd = open(argv[0], O_RDONLY);
29814235Smarkfen 		if (fd < 0)
29824235Smarkfen 			Bail("open source file");
29834235Smarkfen 
29844235Smarkfen 		desc.d_data.d_desc.d_descriptor = fd;
29854235Smarkfen 		desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
29864235Smarkfen 		descp = &desc;
29874235Smarkfen 		ndesc = 1;
29884235Smarkfen 
29894235Smarkfen 		new.cmd = cmd;
29904235Smarkfen 		new.new_len = 0;
29914235Smarkfen 		newp = &new;
29924235Smarkfen 		buflen = sizeof (ike_new_t);
29934235Smarkfen 
29944235Smarkfen 	} else if ((argc > 1) && (cmd == IKE_SVC_NEW_PS)) {
29954235Smarkfen 		/*
29964235Smarkfen 		 * This is an alternative to using the tmpfile method
29974235Smarkfen 		 * for preshared keys.  It means we're duplicating the
29984235Smarkfen 		 * parsing effort that happens in readps.c; but it
29994235Smarkfen 		 * does avoid having the key sitting in a file.
30004235Smarkfen 		 */
30014235Smarkfen 		ike_ps_t	*psp;
30024235Smarkfen 		int		pslen;
30034235Smarkfen 
30044235Smarkfen 		/*
30054235Smarkfen 		 * must be in interactive mode; don't want keys in
30064235Smarkfen 		 * the process args.
30074235Smarkfen 		 */
30084235Smarkfen 		if (!interactive)
30094235Smarkfen 			Bail("Must be in interactive mode to add key info.");
30104235Smarkfen 		if (parse_ps(argc, argv, &psp, &pslen) < 0) {
30114235Smarkfen 			errno = 0;
30124235Smarkfen 			Bail("invalid preshared key definition");
30134235Smarkfen 		}
30144235Smarkfen 		newp = malloc(sizeof (ike_new_t) + pslen);
30154235Smarkfen 		if (newp == NULL)
30164235Smarkfen 			Bail("alloc pskey");
30174235Smarkfen 		newp->cmd = cmd;
30184235Smarkfen 		newp->new_len = sizeof (ike_new_t) + pslen;
30194235Smarkfen 		(void) memcpy((char *)(newp + 1), psp, pslen);
30204235Smarkfen 		buflen = newp->new_len;
30214235Smarkfen 		/* parse_ps allocated the ike_ps_t buffer; free it now */
30224235Smarkfen 		free(psp);
30234235Smarkfen 
30244235Smarkfen 	} else if ((argc > 1) && (cmd == IKE_SVC_NEW_RULE)) {
30254235Smarkfen 		/*
30264235Smarkfen 		 * We've been given the item in argv.  However, parsing
30274235Smarkfen 		 * rules can get more than a little messy, and in.iked
30284235Smarkfen 		 * already has a great parser for this stuff!  So don't
30294235Smarkfen 		 * fool around with trying to do the parsing here. Just
30304235Smarkfen 		 * write it out to a tempfile, and send the fd to in.iked.
30314235Smarkfen 		 *
30324235Smarkfen 		 * We could conceivably do this for preshared keys,
30334235Smarkfen 		 * rather than duplicating the parsing effort; but that
30344235Smarkfen 		 * would mean the key would be written out to a file,
30354235Smarkfen 		 * which isn't such a good idea.
30364235Smarkfen 		 */
30374235Smarkfen 		boolean_t	doquotes = B_FALSE;
30384235Smarkfen 		int		rtn;
30394235Smarkfen 
30404235Smarkfen 		if ((argv[0][0] != '{') ||
30414235Smarkfen 		    (argv[argc - 1][strlen(argv[argc - 1]) - 1] != '}'))
30424235Smarkfen 			bail_msg(gettext("improperly formatted %s"), name);
30434235Smarkfen 
30444235Smarkfen 		/* attempt to use a fairly unpredictable file name... */
30454235Smarkfen 		(void) sprintf(tmpfilepath, "/var/run/%x", (int)gethrtime());
30464235Smarkfen 		fd = open(tmpfilepath, O_RDWR | O_CREAT | O_EXCL,
30474235Smarkfen 		    S_IRUSR | S_IWUSR);
30484235Smarkfen 		if (fd < 0)
30494235Smarkfen 			Bail("cannot open tmpfile");
30504235Smarkfen 
30514235Smarkfen 		/* and make it inaccessible asap */
30524235Smarkfen 		if (unlink(tmpfilepath) < 0) {
30534235Smarkfen 			(void) close(fd);
30544235Smarkfen 			Bail("tmpfile error");
30554235Smarkfen 		}
30564235Smarkfen 
30574235Smarkfen 		tmpfile = fdopen(fd, "w");
30584235Smarkfen 		if (tmpfile == NULL) {
30594235Smarkfen 			(void) close(fd);
30604235Smarkfen 			Bail("cannot write to tmpfile");
30614235Smarkfen 		}
30624235Smarkfen 
30634235Smarkfen 		for (i = 0; i < argc; i++) {
30644235Smarkfen 			/*
30654235Smarkfen 			 * We have to do some gyrations with our string here,
30664235Smarkfen 			 * to properly handle quotes.  There are two issues:
30674235Smarkfen 			 * - some of the fields of a rule may have embedded
30684235Smarkfen 			 *   whitespace, and thus must be quoted on the cmd
30694235Smarkfen 			 *   line.  The shell removes the quotes, and gives
30704235Smarkfen 			 *   us a single argv string; but we need to put the
30714235Smarkfen 			 *   quotes back in when we write the string out to
30724235Smarkfen 			 *   file.  The doquotes boolean is set when we
30734235Smarkfen 			 *   process a keyword which will be followed by a
30744235Smarkfen 			 *   string value (so the NEXT argv element will be
30754235Smarkfen 			 *   quoted).
30764235Smarkfen 			 * - there might be a quote character in a field,
30774235Smarkfen 			 *   that was escaped on the cmdline.  The shell
30784235Smarkfen 			 *   removes the escape char, and leaves the quote
30794235Smarkfen 			 *   in the string it gives us.  We need to put the
30804235Smarkfen 			 *   escape char back in before writing to file.
30814235Smarkfen 			 */
30824235Smarkfen 			char	field[MAXLINESIZE];
30834235Smarkfen 			if (!escapequotes(field, argv[i], MAXLINESIZE))
30844235Smarkfen 				Bail("write to tmpfile failed (arg too big)");
30854235Smarkfen 			if (doquotes) {
30864235Smarkfen 				rtn = fprintf(tmpfile, "\"%s\"\n", field);
30874235Smarkfen 				doquotes = B_FALSE;
30884235Smarkfen 			} else {
30894235Smarkfen 				rtn = fprintf(tmpfile, "%s\n", field);
30904235Smarkfen 			}
30914235Smarkfen 			if (rtn < 0)
30924235Smarkfen 				Bail("write to tmpfile failed");
30934235Smarkfen 			/*
30944235Smarkfen 			 * check if this is a keyword identifying
30954235Smarkfen 			 * a field that needs to be quoted.
30964235Smarkfen 			 */
30974235Smarkfen 			doquotes = quotedfield(argv[i]);
30984235Smarkfen 		}
30994235Smarkfen 		if (fflush(tmpfile) == EOF)
31004235Smarkfen 			Bail("write to tmpfile failed");
31014235Smarkfen 		/* rewind so that the daemon will get the beginning */
31024235Smarkfen 		rewind(tmpfile);
31034235Smarkfen 
31044235Smarkfen 		desc.d_data.d_desc.d_descriptor = fd;
31054235Smarkfen 		desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
31064235Smarkfen 		descp = &desc;
31074235Smarkfen 		ndesc = 1;
31084235Smarkfen 
31094235Smarkfen 		new.cmd = cmd;
31104235Smarkfen 		new.new_len = 0;
31114235Smarkfen 		newp = &new;
31124235Smarkfen 		buflen = sizeof (ike_new_t);
31134235Smarkfen 
31144235Smarkfen 	} else {
31154235Smarkfen 		/* not enough information! */
31164235Smarkfen 		bail_msg(gettext("missing %s description or file name"), name);
31174235Smarkfen 	}
31184235Smarkfen 
31194235Smarkfen 	rtn = ikedoor_call((char *)newp, buflen, descp, ndesc);
31204235Smarkfen 
31214235Smarkfen 	if ((rtn == NULL) || (rtn->svc_err.cmd == IKE_SVC_ERROR)) {
31224235Smarkfen 		ikeadm_err_msg(&rtn->svc_err,
31234235Smarkfen 		    gettext("error creating new %s"), name);
31244235Smarkfen 	} else {
31254235Smarkfen 		message(gettext("Successfully created new %s."), name);
31264235Smarkfen 	}
31274235Smarkfen }
31284235Smarkfen 
31294235Smarkfen static void
31304235Smarkfen do_flush(int cmd)
31314235Smarkfen {
31324235Smarkfen 	ike_service_t	*rtnp;
31334235Smarkfen 	ike_flush_t	flush;
31344235Smarkfen 
31358596SPaul.Wernau@Sun.COM 	if (cmd != IKE_SVC_FLUSH_P1S && cmd != IKE_SVC_FLUSH_CERTCACHE) {
31364235Smarkfen 		bail_msg(gettext("unrecognized flush command (%d)."), cmd);
31374235Smarkfen 	}
31384235Smarkfen 
31394235Smarkfen 	flush.cmd = cmd;
31404235Smarkfen 
31414235Smarkfen 	rtnp = ikedoor_call((char *)&flush, sizeof (ike_flush_t), NULL, 0);
31424235Smarkfen 	if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
31434235Smarkfen 		ikeadm_err_exit(&rtnp->svc_err, gettext("error doing flush"));
31444235Smarkfen 	}
31458596SPaul.Wernau@Sun.COM 	if (cmd == IKE_SVC_FLUSH_P1S)
31468596SPaul.Wernau@Sun.COM 		message(gettext("Successfully flushed P1 SAs."));
31478596SPaul.Wernau@Sun.COM 	else
31488596SPaul.Wernau@Sun.COM 		message(gettext("Successfully flushed cert cache."));
31494235Smarkfen }
31504235Smarkfen 
31514235Smarkfen static void
31524235Smarkfen do_rw(int cmd, int argc, char **argv)
31534235Smarkfen {
31544235Smarkfen 	ike_service_t	*rtnp;
31554235Smarkfen 	ike_rw_t	rw;
31564235Smarkfen 	door_desc_t	desc, *descp = NULL;
31574235Smarkfen 	int		oflag, omode, fd, ndesc = 0;
31584235Smarkfen 	char		*op, *obj = NULL;
31594235Smarkfen 	boolean_t	writing = B_FALSE;
31604235Smarkfen 
31614235Smarkfen 	switch (cmd) {
31624235Smarkfen 	case IKE_SVC_READ_PS:
31634235Smarkfen 		obj = gettext("preshared key");
31644235Smarkfen 		/* FALLTHRU */
31654235Smarkfen 	case IKE_SVC_READ_RULES:
31664235Smarkfen 		if (obj == NULL)
31674235Smarkfen 			obj = gettext("policy rule");
31684235Smarkfen 		op = gettext("read");
31694235Smarkfen 		oflag = O_RDONLY;
31704235Smarkfen 		omode = 0;
31714235Smarkfen 		break;
31724235Smarkfen 
31734235Smarkfen 	case IKE_SVC_WRITE_PS:
31744235Smarkfen 		obj = gettext("preshared key");
31754235Smarkfen 		/* FALLTHRU */
31764235Smarkfen 	case IKE_SVC_WRITE_RULES:
31774235Smarkfen 		if (obj == NULL)
31784235Smarkfen 			obj = gettext("policy rule");
31794235Smarkfen 		op = gettext("write");
31804235Smarkfen 		oflag = O_RDWR | O_CREAT | O_EXCL;
31814235Smarkfen 		omode = S_IRUSR | S_IWUSR;
31824235Smarkfen 
31834235Smarkfen 		/* for write commands, dest location must be specified */
31844235Smarkfen 		if (argc < 1) {
31854235Smarkfen 			bail_msg(gettext("destination location required "
31864235Smarkfen 			    "to write %ss"), obj);
31874235Smarkfen 		}
31884235Smarkfen 		writing = B_TRUE;
31894235Smarkfen 		break;
31904235Smarkfen 
31914235Smarkfen 	default:
31924235Smarkfen 		bail_msg(gettext("unrecognized read/write command (%d)."), cmd);
31934235Smarkfen 	}
31944235Smarkfen 
31954235Smarkfen 	rw.cmd = cmd;
31964235Smarkfen 
31974235Smarkfen 	if (argc >= 1) {
31984235Smarkfen 		rw.rw_loc = IKE_RW_LOC_USER_SPEC;
31994235Smarkfen 		fd = open(argv[0], oflag, omode);
32004235Smarkfen 		if (fd < 0)
32014235Smarkfen 			Bail("open user-specified file");
32024235Smarkfen 
32034235Smarkfen 		desc.d_data.d_desc.d_descriptor = fd;
32044235Smarkfen 		desc.d_attributes = DOOR_DESCRIPTOR | DOOR_RELEASE;
32054235Smarkfen 		descp = &desc;
32064235Smarkfen 		ndesc = 1;
32074235Smarkfen 	} else {
32084235Smarkfen 		rw.rw_loc = IKE_RW_LOC_DEFAULT;
32094235Smarkfen 	}
32104235Smarkfen 
32114235Smarkfen 	rtnp = ikedoor_call((char *)&rw, sizeof (ike_rw_t), descp, ndesc);
32124235Smarkfen 	if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
32134235Smarkfen 		/*
32144235Smarkfen 		 * Need to remove the target file in the
32154235Smarkfen 		 * case of a failed write command.
32164235Smarkfen 		 */
32174235Smarkfen 		if (writing) {
32184235Smarkfen 			/*
32194235Smarkfen 			 * argv[0] must be valid if we're writing; we
32204235Smarkfen 			 * exit before setting this boolean if not.
32214235Smarkfen 			 */
32224235Smarkfen 			(void) unlink(argv[0]);
32234235Smarkfen 			(void) close(fd);
32244235Smarkfen 
32254235Smarkfen 			if ((rtnp != NULL) &&
32264235Smarkfen 			    (rtnp->svc_err.ike_err == IKE_ERR_NO_OBJ)) {
32274235Smarkfen 				message(gettext("No %s information to write."),
32284235Smarkfen 				    obj);
32294235Smarkfen 				return;
32304235Smarkfen 			}
32314235Smarkfen 		}
32324235Smarkfen 		ikeadm_err_exit(&rtnp->svc_err, gettext("error doing %s"), op);
32334235Smarkfen 	}
32344235Smarkfen 	message(gettext("Completed %s of %s configuration information."),
32354235Smarkfen 	    op, obj);
32364235Smarkfen }
32374235Smarkfen 
32384235Smarkfen static void
32394235Smarkfen do_rbdump()
32404235Smarkfen {
32414235Smarkfen 	ike_cmd_t	req;
32424235Smarkfen 	ike_service_t	*rtnp;
32434235Smarkfen 
32444235Smarkfen 	req.cmd = IKE_SVC_DBG_RBDUMP;
32454235Smarkfen 
32464235Smarkfen 	rtnp = ikedoor_call((char *)&req, sizeof (ike_cmd_t), NULL, 0);
32474235Smarkfen 	if ((rtnp == NULL) || (rtnp->svc_err.cmd == IKE_SVC_ERROR)) {
32484235Smarkfen 		ikeadm_err_exit(&rtnp->svc_err, gettext("error doing flush"));
32494235Smarkfen 	}
32504235Smarkfen 	message(gettext("Successfully dumped rulebase; check iked dbg"));
32514235Smarkfen }
32524235Smarkfen 
32534235Smarkfen #define	REQ_ARG_CNT	1
32544235Smarkfen 
32554235Smarkfen /*ARGSUSED*/
32564235Smarkfen static void
32574342Spwernau parseit(int argc, char **argv, char *notused, boolean_t notused_either)
32584235Smarkfen {
32594235Smarkfen 	int	cmd, cmd_obj_args = 1;
32604235Smarkfen 	char	*cmdstr, *objstr;
32614235Smarkfen 
32624235Smarkfen 	if (interactive) {
32634235Smarkfen 		if (argc == 0)
32644235Smarkfen 			return;
32654235Smarkfen 	}
32664235Smarkfen 
32674235Smarkfen 	if (argc < REQ_ARG_CNT) {
32684235Smarkfen 		usage();
32694235Smarkfen 	}
32704235Smarkfen 
32714235Smarkfen 	cmdstr = argv[0];
32724235Smarkfen 	if (argc > REQ_ARG_CNT) {
32734235Smarkfen 		cmd_obj_args++;
32744235Smarkfen 		objstr = argv[1];
32754235Smarkfen 	} else {
32764235Smarkfen 		objstr = NULL;
32774235Smarkfen 	}
32784235Smarkfen 	cmd = parsecmd(cmdstr, objstr);
32794235Smarkfen 
32804235Smarkfen 	/* skip over args specifying command/object */
32814235Smarkfen 	argc -= cmd_obj_args;
32824235Smarkfen 	argv += cmd_obj_args;
32834235Smarkfen 
32844235Smarkfen 	switch (cmd) {
32854235Smarkfen 	case IKE_SVC_GET_DEFS:
32869086SVladimir.Kotal@Sun.COM 		if (argc != 0) {
32879086SVladimir.Kotal@Sun.COM 			print_get_help();
32889086SVladimir.Kotal@Sun.COM 			break;
32899086SVladimir.Kotal@Sun.COM 		}
32904235Smarkfen 		do_getdefs(cmd);
32914235Smarkfen 		break;
32924235Smarkfen 	case IKE_SVC_GET_DBG:
32934235Smarkfen 	case IKE_SVC_GET_PRIV:
32949086SVladimir.Kotal@Sun.COM 		if (argc != 0) {
32959086SVladimir.Kotal@Sun.COM 			print_get_help();
32969086SVladimir.Kotal@Sun.COM 			break;
32979086SVladimir.Kotal@Sun.COM 		}
32984235Smarkfen 		do_getvar(cmd);
32994235Smarkfen 		break;
33004235Smarkfen 	case IKE_SVC_GET_STATS:
33019086SVladimir.Kotal@Sun.COM 		if (argc != 0) {
33029086SVladimir.Kotal@Sun.COM 			print_get_help();
33039086SVladimir.Kotal@Sun.COM 			break;
33049086SVladimir.Kotal@Sun.COM 		}
33054235Smarkfen 		do_getstats(cmd);
33064235Smarkfen 		break;
33074235Smarkfen 	case IKE_SVC_SET_DBG:
33084235Smarkfen 	case IKE_SVC_SET_PRIV:
33094235Smarkfen 		do_setvar(cmd, argc, argv);
33104235Smarkfen 		break;
33118596SPaul.Wernau@Sun.COM 	case IKE_SVC_SET_PIN:
33128596SPaul.Wernau@Sun.COM 	case IKE_SVC_DEL_PIN:
33138596SPaul.Wernau@Sun.COM 		do_setdel_pin(cmd, argc, argv);
33148596SPaul.Wernau@Sun.COM 		break;
33154235Smarkfen 	case IKE_SVC_DUMP_P1S:
33164235Smarkfen 	case IKE_SVC_DUMP_RULES:
3317*12129SVladimir.Kotal@Sun.COM 	case IKE_SVC_DUMP_GROUPS:
3318*12129SVladimir.Kotal@Sun.COM 	case IKE_SVC_DUMP_ENCRALGS:
3319*12129SVladimir.Kotal@Sun.COM 	case IKE_SVC_DUMP_AUTHALGS:
33204235Smarkfen 	case IKE_SVC_DUMP_PS:
33218596SPaul.Wernau@Sun.COM 	case IKE_SVC_DUMP_CERTCACHE:
33229086SVladimir.Kotal@Sun.COM 		if (argc != NULL) {
33239086SVladimir.Kotal@Sun.COM 			print_dump_help();
33249086SVladimir.Kotal@Sun.COM 			break;
33259086SVladimir.Kotal@Sun.COM 		}
33264235Smarkfen 		do_dump(cmd);
33274235Smarkfen 		break;
33284235Smarkfen 	case IKE_SVC_GET_P1:
33294235Smarkfen 	case IKE_SVC_GET_RULE:
33304235Smarkfen 	case IKE_SVC_GET_PS:
33314235Smarkfen 	case IKE_SVC_DEL_P1:
33324235Smarkfen 	case IKE_SVC_DEL_RULE:
33334235Smarkfen 	case IKE_SVC_DEL_PS:
33344235Smarkfen 		do_getdel(cmd, argc, argv);
33354235Smarkfen 		break;
33364235Smarkfen 	case IKE_SVC_NEW_RULE:
33374235Smarkfen 	case IKE_SVC_NEW_PS:
33384235Smarkfen 		do_new(cmd, argc, argv);
33394235Smarkfen 		break;
33404235Smarkfen 	case IKE_SVC_FLUSH_P1S:
33418596SPaul.Wernau@Sun.COM 	case IKE_SVC_FLUSH_CERTCACHE:
33429086SVladimir.Kotal@Sun.COM 		if (argc != 0) {
33439086SVladimir.Kotal@Sun.COM 			print_flush_help();
33449086SVladimir.Kotal@Sun.COM 			break;
33459086SVladimir.Kotal@Sun.COM 		}
33464235Smarkfen 		do_flush(cmd);
33474235Smarkfen 		break;
33484235Smarkfen 	case IKE_SVC_READ_RULES:
33494235Smarkfen 	case IKE_SVC_READ_PS:
33504235Smarkfen 	case IKE_SVC_WRITE_RULES:
33514235Smarkfen 	case IKE_SVC_WRITE_PS:
33524235Smarkfen 		do_rw(cmd, argc, argv);
33534235Smarkfen 		break;
33544235Smarkfen 	case IKEADM_HELP_GENERAL:
33554235Smarkfen 		print_help();
33564235Smarkfen 		break;
33574235Smarkfen 	case IKEADM_HELP_GET:
33584235Smarkfen 		print_get_help();
33594235Smarkfen 		break;
33604235Smarkfen 	case IKEADM_HELP_SET:
33614235Smarkfen 		print_set_help();
33624235Smarkfen 		break;
33634235Smarkfen 	case IKEADM_HELP_ADD:
33644235Smarkfen 		print_add_help();
33654235Smarkfen 		break;
33664235Smarkfen 	case IKEADM_HELP_DEL:
33674235Smarkfen 		print_del_help();
33684235Smarkfen 		break;
33694235Smarkfen 	case IKEADM_HELP_DUMP:
33704235Smarkfen 		print_dump_help();
33714235Smarkfen 		break;
33724235Smarkfen 	case IKEADM_HELP_FLUSH:
33734235Smarkfen 		print_flush_help();
33744235Smarkfen 		break;
33754235Smarkfen 	case IKEADM_HELP_READ:
33764235Smarkfen 		print_read_help();
33774235Smarkfen 		break;
33784235Smarkfen 	case IKEADM_HELP_WRITE:
33794235Smarkfen 		print_write_help();
33804235Smarkfen 		break;
33818596SPaul.Wernau@Sun.COM 	case IKEADM_HELP_TOKEN:
33828596SPaul.Wernau@Sun.COM 		print_token_help();
33838596SPaul.Wernau@Sun.COM 		break;
33844235Smarkfen 	case IKEADM_HELP_HELP:
33854235Smarkfen 		print_help_help();
33864235Smarkfen 		break;
33874235Smarkfen 	case IKEADM_EXIT:
33884235Smarkfen 		if (interactive)
33894235Smarkfen 			exit(0);
33904235Smarkfen 		break;
33914235Smarkfen 	case IKE_SVC_DBG_RBDUMP:
33924235Smarkfen 		do_rbdump();
33934235Smarkfen 		break;
33944235Smarkfen 	case IKE_SVC_ERROR:
33954235Smarkfen 		usage();
33964235Smarkfen 	default:
33974235Smarkfen 		exit(0);
33984235Smarkfen 	}
33994235Smarkfen }
34004235Smarkfen 
34014235Smarkfen int
34024235Smarkfen main(int argc, char **argv)
34034235Smarkfen {
34044235Smarkfen 	char	ch;
34054235Smarkfen 
34064235Smarkfen 	(void) setlocale(LC_ALL, "");
34074235Smarkfen #if !defined(TEXT_DOMAIN)
34084235Smarkfen #define	TEXT_DOMAIN "SYS_TEST"
34094235Smarkfen #endif
34104235Smarkfen 	(void) textdomain(TEXT_DOMAIN);
34114235Smarkfen 
34124235Smarkfen 	while ((ch = getopt(argc, argv, "hpn")) != EOF) {
34134235Smarkfen 		switch (ch) {
34144235Smarkfen 		case 'h':
34154235Smarkfen 			print_help();
34164235Smarkfen 			return (0);
34174235Smarkfen 		case 'p':
34184235Smarkfen 			pflag = B_TRUE;
34194235Smarkfen 			break;
34204235Smarkfen 		case 'n':
34214235Smarkfen 			nflag = B_TRUE;
34224235Smarkfen 			break;
34234235Smarkfen 		default:
34244235Smarkfen 			usage();
34254235Smarkfen 		}
34264235Smarkfen 	}
34274235Smarkfen 	argc -= optind;
34284235Smarkfen 	argv += optind;
34294235Smarkfen 
34304235Smarkfen 	if (open_door() < 0) {
34314235Smarkfen 		(void) fprintf(stderr,
34324235Smarkfen 		    gettext("Unable to communicate with in.iked\n"));
34334235Smarkfen 		Bail("open_door failed");
34344235Smarkfen 	}
34354235Smarkfen 
34364235Smarkfen 	if (*argv == NULL) {
34374235Smarkfen 		/* no cmd-line args, do interactive mode */
34389086SVladimir.Kotal@Sun.COM 		do_interactive(stdin, NULL, "ikeadm> ", NULL, parseit,
34399086SVladimir.Kotal@Sun.COM 		    no_match);
34404235Smarkfen 	}
34414235Smarkfen 
34424342Spwernau 	parseit(argc, argv, NULL, B_FALSE);
34434235Smarkfen 
34444235Smarkfen 	return (0);
34454235Smarkfen }
3446