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