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