17c478bd9Sstevel@tonic-gate /*
2a12f8217Spwernau  *
37c478bd9Sstevel@tonic-gate  * CDDL HEADER START
47c478bd9Sstevel@tonic-gate  *
57c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
68810c16bSdanmcd  * Common Development and Distribution License (the "License").
78810c16bSdanmcd  * You may not use this file except in compliance with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
23bfe6f8f5SVladimir Kotal  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
2533f5ff17SMilan Jurik  * Copyright 2012 Milan Juri. All rights reserved.
26351128adSJason King  * Copyright 2018 Joyent, Inc.
27bdc560abSJason King  * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
287c478bd9Sstevel@tonic-gate  */
297c478bd9Sstevel@tonic-gate 
307c478bd9Sstevel@tonic-gate #include <unistd.h>
317c478bd9Sstevel@tonic-gate #include <stdio.h>
327c478bd9Sstevel@tonic-gate #include <stdlib.h>
337c478bd9Sstevel@tonic-gate #include <stdarg.h>
347c478bd9Sstevel@tonic-gate #include <sys/types.h>
357c478bd9Sstevel@tonic-gate #include <sys/stat.h>
367c478bd9Sstevel@tonic-gate #include <fcntl.h>
377c478bd9Sstevel@tonic-gate #include <sys/sysconf.h>
387c478bd9Sstevel@tonic-gate #include <strings.h>
397c478bd9Sstevel@tonic-gate #include <ctype.h>
407c478bd9Sstevel@tonic-gate #include <errno.h>
417c478bd9Sstevel@tonic-gate #include <sys/socket.h>
427c478bd9Sstevel@tonic-gate #include <netdb.h>
437c478bd9Sstevel@tonic-gate #include <netinet/in.h>
447c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
457c478bd9Sstevel@tonic-gate #include <net/pfkeyv2.h>
467c478bd9Sstevel@tonic-gate #include <net/pfpolicy.h>
477c478bd9Sstevel@tonic-gate #include <libintl.h>
487c478bd9Sstevel@tonic-gate #include <setjmp.h>
497c478bd9Sstevel@tonic-gate #include <libgen.h>
50e3320f40Smarkfen #include <libscf.h>
51bdc560abSJason King #include <kmfapi.h>
52bdc560abSJason King #include <ber_der.h>
537c478bd9Sstevel@tonic-gate 
547c478bd9Sstevel@tonic-gate #include "ipsec_util.h"
557c478bd9Sstevel@tonic-gate #include "ikedoor.h"
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /*
587c478bd9Sstevel@tonic-gate  * This file contains support functions that are shared by the ipsec
59*bbf21555SRichard Lowe  * utilities and daemons including ipseckey(8), ikeadm(8) and in.iked(8).
607c478bd9Sstevel@tonic-gate  */
617c478bd9Sstevel@tonic-gate 
62bb3ed8dfSpwernau 
63bb3ed8dfSpwernau #define	EFD(file) (((file) == stdout) ? stderr : (file))
64bb3ed8dfSpwernau 
65bfe6f8f5SVladimir Kotal /* Limits for interactive mode. */
66bfe6f8f5SVladimir Kotal #define	MAX_LINE_LEN	IBUF_SIZE
67bfe6f8f5SVladimir Kotal #define	MAX_CMD_HIST	64000	/* in bytes */
68bfe6f8f5SVladimir Kotal 
697c478bd9Sstevel@tonic-gate /* Set standard default/initial values for globals... */
707c478bd9Sstevel@tonic-gate boolean_t pflag = B_FALSE;	/* paranoid w.r.t. printing keying material */
717c478bd9Sstevel@tonic-gate boolean_t nflag = B_FALSE;	/* avoid nameservice? */
727c478bd9Sstevel@tonic-gate boolean_t interactive = B_FALSE;	/* util not running on cmdline */
737c478bd9Sstevel@tonic-gate boolean_t readfile = B_FALSE;	/* cmds are being read from a file */
747c478bd9Sstevel@tonic-gate uint_t	lineno = 0;		/* track location if reading cmds from file */
75e3320f40Smarkfen uint_t	lines_added = 0;
76e3320f40Smarkfen uint_t	lines_parsed = 0;
777c478bd9Sstevel@tonic-gate jmp_buf	env;		/* for error recovery in interactive/readfile modes */
78e3320f40Smarkfen char *my_fmri = NULL;
79e3320f40Smarkfen FILE *debugfile = stderr;
80bfe6f8f5SVladimir Kotal static GetLine *gl = NULL;	/* for interactive mode */
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate /*
837c478bd9Sstevel@tonic-gate  * Print errno and exit if cmdline or readfile, reset state if interactive
84a7485808Smarkfen  * The error string *what should be dgettext()'d before calling bail().
857c478bd9Sstevel@tonic-gate  */
867c478bd9Sstevel@tonic-gate void
bail(char * what)877c478bd9Sstevel@tonic-gate bail(char *what)
887c478bd9Sstevel@tonic-gate {
897c478bd9Sstevel@tonic-gate 	if (errno != 0)
907c478bd9Sstevel@tonic-gate 		warn(what);
917c478bd9Sstevel@tonic-gate 	else
92e3320f40Smarkfen 		warnx(dgettext(TEXT_DOMAIN, "Error: %s"), what);
937c478bd9Sstevel@tonic-gate 	if (readfile) {
94e3320f40Smarkfen 		return;
957c478bd9Sstevel@tonic-gate 	}
967c478bd9Sstevel@tonic-gate 	if (interactive && !readfile)
977c478bd9Sstevel@tonic-gate 		longjmp(env, 2);
98e3320f40Smarkfen 	EXIT_FATAL(NULL);
997c478bd9Sstevel@tonic-gate }
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate /*
1027c478bd9Sstevel@tonic-gate  * Print caller-supplied variable-arg error msg, then exit if cmdline or
1037c478bd9Sstevel@tonic-gate  * readfile, or reset state if interactive.
1047c478bd9Sstevel@tonic-gate  */
1057c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
1067c478bd9Sstevel@tonic-gate void
bail_msg(char * fmt,...)1077c478bd9Sstevel@tonic-gate bail_msg(char *fmt, ...)
1087c478bd9Sstevel@tonic-gate {
1097c478bd9Sstevel@tonic-gate 	va_list	ap;
1107c478bd9Sstevel@tonic-gate 	char	msgbuf[BUFSIZ];
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
1137c478bd9Sstevel@tonic-gate 	(void) vsnprintf(msgbuf, BUFSIZ, fmt, ap);
1147c478bd9Sstevel@tonic-gate 	va_end(ap);
1157c478bd9Sstevel@tonic-gate 	if (readfile)
116a7485808Smarkfen 		warnx(dgettext(TEXT_DOMAIN,
117a7485808Smarkfen 		    "ERROR on line %u:\n%s\n"), lineno,  msgbuf);
1187c478bd9Sstevel@tonic-gate 	else
119a7485808Smarkfen 		warnx(dgettext(TEXT_DOMAIN, "ERROR: %s\n"), msgbuf);
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	if (interactive && !readfile)
1227c478bd9Sstevel@tonic-gate 		longjmp(env, 1);
1237c478bd9Sstevel@tonic-gate 
124e3320f40Smarkfen 	EXIT_FATAL(NULL);
1257c478bd9Sstevel@tonic-gate }
1267c478bd9Sstevel@tonic-gate 
127510c3f91SVladimir Kotal /*
128510c3f91SVladimir Kotal  * bytecnt2str() wrapper. Zeroes out the input buffer and if the number
129510c3f91SVladimir Kotal  * of bytes to be converted is more than 1K, it will produce readable string
130510c3f91SVladimir Kotal  * in parentheses, store it in the original buffer and return the pointer to it.
131510c3f91SVladimir Kotal  * Maximum length of the returned string is 14 characters (not including
132510c3f91SVladimir Kotal  * the terminating zero).
133510c3f91SVladimir Kotal  */
134510c3f91SVladimir Kotal char *
bytecnt2out(uint64_t num,char * buf,size_t bufsiz,int flags)135510c3f91SVladimir Kotal bytecnt2out(uint64_t num, char *buf, size_t bufsiz, int flags)
136510c3f91SVladimir Kotal {
137510c3f91SVladimir Kotal 	char *str;
138510c3f91SVladimir Kotal 
139510c3f91SVladimir Kotal 	(void) memset(buf, '\0', bufsiz);
140510c3f91SVladimir Kotal 
141510c3f91SVladimir Kotal 	if (num > 1024) {
142510c3f91SVladimir Kotal 		/* Return empty string in case of out-of-memory. */
143510c3f91SVladimir Kotal 		if ((str = malloc(bufsiz)) == NULL)
144510c3f91SVladimir Kotal 			return (buf);
145510c3f91SVladimir Kotal 
146510c3f91SVladimir Kotal 		(void) bytecnt2str(num, str, bufsiz);
147510c3f91SVladimir Kotal 		/* Detect overflow. */
148510c3f91SVladimir Kotal 		if (strlen(str) == 0) {
149510c3f91SVladimir Kotal 			free(str);
150510c3f91SVladimir Kotal 			return (buf);
151510c3f91SVladimir Kotal 		}
152510c3f91SVladimir Kotal 
153510c3f91SVladimir Kotal 		/* Emit nothing in case of overflow. */
154510c3f91SVladimir Kotal 		if (snprintf(buf, bufsiz, "%s(%sB)%s",
155510c3f91SVladimir Kotal 		    flags & SPC_BEGIN ? " " : "", str,
156510c3f91SVladimir Kotal 		    flags & SPC_END ? " " : "") >= bufsiz)
157510c3f91SVladimir Kotal 			(void) memset(buf, '\0', bufsiz);
158510c3f91SVladimir Kotal 
159510c3f91SVladimir Kotal 		free(str);
160510c3f91SVladimir Kotal 	}
161510c3f91SVladimir Kotal 
162510c3f91SVladimir Kotal 	return (buf);
163510c3f91SVladimir Kotal }
164510c3f91SVladimir Kotal 
165510c3f91SVladimir Kotal /*
166510c3f91SVladimir Kotal  * Convert 64-bit number to human readable string. Useful mainly for the
167510c3f91SVladimir Kotal  * byte lifetime counters. Returns pointer to the user supplied buffer.
168510c3f91SVladimir Kotal  * Able to convert up to Exabytes. Maximum length of the string produced
169510c3f91SVladimir Kotal  * is 9 characters (not counting the terminating zero).
170510c3f91SVladimir Kotal  */
171510c3f91SVladimir Kotal char *
bytecnt2str(uint64_t num,char * buf,size_t buflen)172510c3f91SVladimir Kotal bytecnt2str(uint64_t num, char *buf, size_t buflen)
173510c3f91SVladimir Kotal {
174510c3f91SVladimir Kotal 	uint64_t n = num;
175510c3f91SVladimir Kotal 	char u;
176510c3f91SVladimir Kotal 	int index = 0;
177510c3f91SVladimir Kotal 
178510c3f91SVladimir Kotal 	while (n >= 1024) {
179510c3f91SVladimir Kotal 		n /= 1024;
180510c3f91SVladimir Kotal 		index++;
181510c3f91SVladimir Kotal 	}
182510c3f91SVladimir Kotal 
183510c3f91SVladimir Kotal 	/* The field has all units this function can represent. */
184510c3f91SVladimir Kotal 	u = " KMGTPE"[index];
185510c3f91SVladimir Kotal 
186510c3f91SVladimir Kotal 	if (index == 0) {
187510c3f91SVladimir Kotal 		/* Less than 1K */
188510c3f91SVladimir Kotal 		if (snprintf(buf, buflen, "%llu ", num) >= buflen)
189510c3f91SVladimir Kotal 			(void) memset(buf, '\0', buflen);
190510c3f91SVladimir Kotal 	} else {
191510c3f91SVladimir Kotal 		/* Otherwise display 2 precision digits. */
192510c3f91SVladimir Kotal 		if (snprintf(buf, buflen, "%.2f %c",
193510c3f91SVladimir Kotal 		    (double)num / (1ULL << index * 10), u) >= buflen)
194510c3f91SVladimir Kotal 			(void) memset(buf, '\0', buflen);
195510c3f91SVladimir Kotal 	}
196510c3f91SVladimir Kotal 
197510c3f91SVladimir Kotal 	return (buf);
198510c3f91SVladimir Kotal }
199510c3f91SVladimir Kotal 
200510c3f91SVladimir Kotal /*
201510c3f91SVladimir Kotal  * secs2str() wrapper. Zeroes out the input buffer and if the number of
202510c3f91SVladimir Kotal  * seconds to be converted is more than minute, it will produce readable
203510c3f91SVladimir Kotal  * string in parentheses, store it in the original buffer and return the
204510c3f91SVladimir Kotal  * pointer to it.
205510c3f91SVladimir Kotal  */
206510c3f91SVladimir Kotal char *
secs2out(unsigned int secs,char * buf,int bufsiz,int flags)207510c3f91SVladimir Kotal secs2out(unsigned int secs, char *buf, int bufsiz, int flags)
208510c3f91SVladimir Kotal {
209510c3f91SVladimir Kotal 	char *str;
210510c3f91SVladimir Kotal 
211510c3f91SVladimir Kotal 	(void) memset(buf, '\0', bufsiz);
212510c3f91SVladimir Kotal 
213510c3f91SVladimir Kotal 	if (secs > 60) {
214510c3f91SVladimir Kotal 		/* Return empty string in case of out-of-memory. */
215510c3f91SVladimir Kotal 		if ((str = malloc(bufsiz)) == NULL)
216510c3f91SVladimir Kotal 			return (buf);
217510c3f91SVladimir Kotal 
218510c3f91SVladimir Kotal 		(void) secs2str(secs, str, bufsiz);
219510c3f91SVladimir Kotal 		/* Detect overflow. */
220510c3f91SVladimir Kotal 		if (strlen(str) == 0) {
221510c3f91SVladimir Kotal 			free(str);
222510c3f91SVladimir Kotal 			return (buf);
223510c3f91SVladimir Kotal 		}
224510c3f91SVladimir Kotal 
225510c3f91SVladimir Kotal 		/* Emit nothing in case of overflow. */
226510c3f91SVladimir Kotal 		if (snprintf(buf, bufsiz, "%s(%s)%s",
227510c3f91SVladimir Kotal 		    flags & SPC_BEGIN ? " " : "", str,
228510c3f91SVladimir Kotal 		    flags & SPC_END ? " " : "") >= bufsiz)
229510c3f91SVladimir Kotal 			(void) memset(buf, '\0', bufsiz);
230510c3f91SVladimir Kotal 
231510c3f91SVladimir Kotal 		free(str);
232510c3f91SVladimir Kotal 	}
233510c3f91SVladimir Kotal 
234510c3f91SVladimir Kotal 	return (buf);
235510c3f91SVladimir Kotal }
236510c3f91SVladimir Kotal 
237510c3f91SVladimir Kotal /*
238510c3f91SVladimir Kotal  * Convert number of seconds to human readable string. Useful mainly for
239510c3f91SVladimir Kotal  * the lifetime counters. Returns pointer to the user supplied buffer.
240510c3f91SVladimir Kotal  * Able to convert up to days.
241510c3f91SVladimir Kotal  */
242510c3f91SVladimir Kotal char *
secs2str(unsigned int secs,char * buf,int bufsiz)243510c3f91SVladimir Kotal secs2str(unsigned int secs, char *buf, int bufsiz)
244510c3f91SVladimir Kotal {
245510c3f91SVladimir Kotal 	double val = secs;
246510c3f91SVladimir Kotal 	char *unit = "second";
247510c3f91SVladimir Kotal 
248510c3f91SVladimir Kotal 	if (val >= 24*60*60) {
249510c3f91SVladimir Kotal 		val /= 86400;
250510c3f91SVladimir Kotal 		unit = "day";
251510c3f91SVladimir Kotal 	} else if (val >= 60*60) {
252510c3f91SVladimir Kotal 		val /= 60*60;
253510c3f91SVladimir Kotal 		unit = "hour";
254510c3f91SVladimir Kotal 	} else if (val >= 60) {
255510c3f91SVladimir Kotal 		val /= 60;
256510c3f91SVladimir Kotal 		unit = "minute";
257510c3f91SVladimir Kotal 	}
258510c3f91SVladimir Kotal 
259510c3f91SVladimir Kotal 	/* Emit nothing in case of overflow. */
260510c3f91SVladimir Kotal 	if (snprintf(buf, bufsiz, "%.2f %s%s", val, unit,
261510c3f91SVladimir Kotal 	    val >= 2 ? "s" : "") >= bufsiz)
262510c3f91SVladimir Kotal 		(void) memset(buf, '\0', bufsiz);
263510c3f91SVladimir Kotal 
264510c3f91SVladimir Kotal 	return (buf);
265510c3f91SVladimir Kotal }
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate /*
2687c478bd9Sstevel@tonic-gate  * dump_XXX functions produce ASCII output from various structures.
2697c478bd9Sstevel@tonic-gate  *
2707c478bd9Sstevel@tonic-gate  * Because certain errors need to do this to stderr, dump_XXX functions
2717c478bd9Sstevel@tonic-gate  * take a FILE pointer.
2727c478bd9Sstevel@tonic-gate  *
2737c478bd9Sstevel@tonic-gate  * If an error occured while writing to the specified file, these
2747c478bd9Sstevel@tonic-gate  * functions return -1, zero otherwise.
2757c478bd9Sstevel@tonic-gate  */
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate int
dump_sockaddr(struct sockaddr * sa,uint8_t prefixlen,boolean_t addr_only,FILE * where,boolean_t ignore_nss)2788810c16bSdanmcd dump_sockaddr(struct sockaddr *sa, uint8_t prefixlen, boolean_t addr_only,
279bb3ed8dfSpwernau     FILE *where, boolean_t ignore_nss)
2807c478bd9Sstevel@tonic-gate {
2817c478bd9Sstevel@tonic-gate 	struct sockaddr_in	*sin;
2827c478bd9Sstevel@tonic-gate 	struct sockaddr_in6	*sin6;
2837c478bd9Sstevel@tonic-gate 	char			*printable_addr, *protocol;
2847c478bd9Sstevel@tonic-gate 	uint8_t			*addrptr;
2858810c16bSdanmcd 	/* Add 4 chars to hold '/nnn' for prefixes. */
2868810c16bSdanmcd 	char			storage[INET6_ADDRSTRLEN + 4];
2877c478bd9Sstevel@tonic-gate 	uint16_t		port;
2887c478bd9Sstevel@tonic-gate 	boolean_t		unspec;
2897c478bd9Sstevel@tonic-gate 	struct hostent		*hp;
2907c478bd9Sstevel@tonic-gate 	int			getipnode_errno, addrlen;
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	switch (sa->sa_family) {
2937c478bd9Sstevel@tonic-gate 	case AF_INET:
2947c478bd9Sstevel@tonic-gate 		/* LINTED E_BAD_PTR_CAST_ALIGN */
2957c478bd9Sstevel@tonic-gate 		sin = (struct sockaddr_in *)sa;
2967c478bd9Sstevel@tonic-gate 		addrptr = (uint8_t *)&sin->sin_addr;
2977c478bd9Sstevel@tonic-gate 		port = sin->sin_port;
2987c478bd9Sstevel@tonic-gate 		protocol = "AF_INET";
2997c478bd9Sstevel@tonic-gate 		unspec = (sin->sin_addr.s_addr == 0);
3007c478bd9Sstevel@tonic-gate 		addrlen = sizeof (sin->sin_addr);
3017c478bd9Sstevel@tonic-gate 		break;
3027c478bd9Sstevel@tonic-gate 	case AF_INET6:
3037c478bd9Sstevel@tonic-gate 		/* LINTED E_BAD_PTR_CAST_ALIGN */
3047c478bd9Sstevel@tonic-gate 		sin6 = (struct sockaddr_in6 *)sa;
3057c478bd9Sstevel@tonic-gate 		addrptr = (uint8_t *)&sin6->sin6_addr;
3067c478bd9Sstevel@tonic-gate 		port = sin6->sin6_port;
3077c478bd9Sstevel@tonic-gate 		protocol = "AF_INET6";
3087c478bd9Sstevel@tonic-gate 		unspec = IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr);
3097c478bd9Sstevel@tonic-gate 		addrlen = sizeof (sin6->sin6_addr);
3107c478bd9Sstevel@tonic-gate 		break;
3117c478bd9Sstevel@tonic-gate 	default:
3127c478bd9Sstevel@tonic-gate 		return (0);
3137c478bd9Sstevel@tonic-gate 	}
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	if (inet_ntop(sa->sa_family, addrptr, storage, INET6_ADDRSTRLEN) ==
3167c478bd9Sstevel@tonic-gate 	    NULL) {
317a7485808Smarkfen 		printable_addr = dgettext(TEXT_DOMAIN, "Invalid IP address.");
3187c478bd9Sstevel@tonic-gate 	} else {
3198810c16bSdanmcd 		char prefix[5];	/* "/nnn" with terminator. */
3208810c16bSdanmcd 
3218810c16bSdanmcd 		(void) snprintf(prefix, sizeof (prefix), "/%d", prefixlen);
3227c478bd9Sstevel@tonic-gate 		printable_addr = storage;
3238810c16bSdanmcd 		if (prefixlen != 0) {
3248810c16bSdanmcd 			(void) strlcat(printable_addr, prefix,
3258810c16bSdanmcd 			    sizeof (storage));
3268810c16bSdanmcd 		}
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 	if (addr_only) {
3297c478bd9Sstevel@tonic-gate 		if (fprintf(where, "%s", printable_addr) < 0)
3307c478bd9Sstevel@tonic-gate 			return (-1);
3317c478bd9Sstevel@tonic-gate 	} else {
332a7485808Smarkfen 		if (fprintf(where, dgettext(TEXT_DOMAIN,
333a7485808Smarkfen 		    "%s: port %d, %s"), protocol,
3347c478bd9Sstevel@tonic-gate 		    ntohs(port), printable_addr) < 0)
3357c478bd9Sstevel@tonic-gate 			return (-1);
336bb3ed8dfSpwernau 		if (ignore_nss == B_FALSE) {
3377c478bd9Sstevel@tonic-gate 			/*
3387c478bd9Sstevel@tonic-gate 			 * Do AF_independent reverse hostname lookup here.
3397c478bd9Sstevel@tonic-gate 			 */
3407c478bd9Sstevel@tonic-gate 			if (unspec) {
3417c478bd9Sstevel@tonic-gate 				if (fprintf(where,
342a7485808Smarkfen 				    dgettext(TEXT_DOMAIN,
343a7485808Smarkfen 				    " <unspecified>")) < 0)
3447c478bd9Sstevel@tonic-gate 					return (-1);
3457c478bd9Sstevel@tonic-gate 			} else {
3467c478bd9Sstevel@tonic-gate 				hp = getipnodebyaddr((char *)addrptr, addrlen,
3477c478bd9Sstevel@tonic-gate 				    sa->sa_family, &getipnode_errno);
3487c478bd9Sstevel@tonic-gate 				if (hp != NULL) {
3497c478bd9Sstevel@tonic-gate 					if (fprintf(where,
3507c478bd9Sstevel@tonic-gate 					    " (%s)", hp->h_name) < 0)
3517c478bd9Sstevel@tonic-gate 						return (-1);
3527c478bd9Sstevel@tonic-gate 					freehostent(hp);
3537c478bd9Sstevel@tonic-gate 				} else {
3547c478bd9Sstevel@tonic-gate 					if (fprintf(where,
355a7485808Smarkfen 					    dgettext(TEXT_DOMAIN,
356a7485808Smarkfen 					    " <unknown>")) < 0)
3577c478bd9Sstevel@tonic-gate 						return (-1);
3587c478bd9Sstevel@tonic-gate 				}
3597c478bd9Sstevel@tonic-gate 			}
3607c478bd9Sstevel@tonic-gate 		}
3617c478bd9Sstevel@tonic-gate 		if (fputs(".\n", where) == EOF)
3627c478bd9Sstevel@tonic-gate 			return (-1);
3637c478bd9Sstevel@tonic-gate 	}
3647c478bd9Sstevel@tonic-gate 	return (0);
3657c478bd9Sstevel@tonic-gate }
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate /*
368628b0c67SMark Fenwick  * Dump a key, any salt and bitlen.
369628b0c67SMark Fenwick  * The key is made up of a stream of bits. If the algorithm requires a salt
370628b0c67SMark Fenwick  * value, this will also be part of the dumped key. The last "saltbits" of the
371628b0c67SMark Fenwick  * key string, reading left to right will be the salt value. To make it easier
372628b0c67SMark Fenwick  * to see which bits make up the key, the salt value is enclosed in []'s.
373*bbf21555SRichard Lowe  * This function can also be called when ipseckey(8) -s is run, this "saves"
374628b0c67SMark Fenwick  * the SAs, including the key to a file. When this is the case, the []'s are
375628b0c67SMark Fenwick  * not printed.
376628b0c67SMark Fenwick  *
377628b0c67SMark Fenwick  * The implementation allows the kernel to be told about the length of the salt
378628b0c67SMark Fenwick  * in whole bytes only. If this changes, this function will need to be updated.
3797c478bd9Sstevel@tonic-gate  */
3807c478bd9Sstevel@tonic-gate int
dump_key(uint8_t * keyp,uint_t bitlen,uint_t saltbits,FILE * where,boolean_t separate_salt)381628b0c67SMark Fenwick dump_key(uint8_t *keyp, uint_t bitlen, uint_t saltbits, FILE *where,
382628b0c67SMark Fenwick     boolean_t separate_salt)
3837c478bd9Sstevel@tonic-gate {
384628b0c67SMark Fenwick 	int	numbytes, saltbytes;
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	numbytes = SADB_1TO8(bitlen);
387628b0c67SMark Fenwick 	saltbytes = SADB_1TO8(saltbits);
388628b0c67SMark Fenwick 	numbytes += saltbytes;
389628b0c67SMark Fenwick 
3907c478bd9Sstevel@tonic-gate 	/* The & 0x7 is to check for leftover bits. */
3917c478bd9Sstevel@tonic-gate 	if ((bitlen & 0x7) != 0)
3927c478bd9Sstevel@tonic-gate 		numbytes++;
393628b0c67SMark Fenwick 
3947c478bd9Sstevel@tonic-gate 	while (numbytes-- != 0) {
3957c478bd9Sstevel@tonic-gate 		if (pflag) {
3967c478bd9Sstevel@tonic-gate 			/* Print no keys if paranoid */
3977c478bd9Sstevel@tonic-gate 			if (fprintf(where, "XX") < 0)
3987c478bd9Sstevel@tonic-gate 				return (-1);
3997c478bd9Sstevel@tonic-gate 		} else {
4007c478bd9Sstevel@tonic-gate 			if (fprintf(where, "%02x", *keyp++) < 0)
4017c478bd9Sstevel@tonic-gate 				return (-1);
4027c478bd9Sstevel@tonic-gate 		}
403628b0c67SMark Fenwick 		if (separate_salt && saltbytes != 0 &&
404628b0c67SMark Fenwick 		    numbytes == saltbytes) {
405628b0c67SMark Fenwick 			if (fprintf(where, "[") < 0)
406628b0c67SMark Fenwick 				return (-1);
407628b0c67SMark Fenwick 		}
4087c478bd9Sstevel@tonic-gate 	}
409628b0c67SMark Fenwick 
410628b0c67SMark Fenwick 	if (separate_salt && saltbits != 0) {
411628b0c67SMark Fenwick 		if (fprintf(where, "]/%u+%u", bitlen, saltbits) < 0)
412628b0c67SMark Fenwick 			return (-1);
413628b0c67SMark Fenwick 	} else {
414628b0c67SMark Fenwick 		if (fprintf(where, "/%u", bitlen + saltbits) < 0)
415628b0c67SMark Fenwick 			return (-1);
416628b0c67SMark Fenwick 	}
417628b0c67SMark Fenwick 
4187c478bd9Sstevel@tonic-gate 	return (0);
4197c478bd9Sstevel@tonic-gate }
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate /*
4227c478bd9Sstevel@tonic-gate  * Print an authentication or encryption algorithm
4237c478bd9Sstevel@tonic-gate  */
4247c478bd9Sstevel@tonic-gate static int
dump_generic_alg(uint8_t alg_num,int proto_num,FILE * where)4257c478bd9Sstevel@tonic-gate dump_generic_alg(uint8_t alg_num, int proto_num, FILE *where)
4267c478bd9Sstevel@tonic-gate {
4277c478bd9Sstevel@tonic-gate 	struct ipsecalgent *alg;
4287c478bd9Sstevel@tonic-gate 
4297c478bd9Sstevel@tonic-gate 	alg = getipsecalgbynum(alg_num, proto_num, NULL);
4307c478bd9Sstevel@tonic-gate 	if (alg == NULL) {
431a7485808Smarkfen 		if (fprintf(where, dgettext(TEXT_DOMAIN,
432a7485808Smarkfen 		    "<unknown %u>"), alg_num) < 0)
4337c478bd9Sstevel@tonic-gate 			return (-1);
4347c478bd9Sstevel@tonic-gate 		return (0);
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate 
4377c478bd9Sstevel@tonic-gate 	/*
4387c478bd9Sstevel@tonic-gate 	 * Special-case <none> for backward output compat.
4397c478bd9Sstevel@tonic-gate 	 * Assume that SADB_AALG_NONE == SADB_EALG_NONE.
4407c478bd9Sstevel@tonic-gate 	 */
4417c478bd9Sstevel@tonic-gate 	if (alg_num == SADB_AALG_NONE) {
442a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN,
443a7485808Smarkfen 		    "<none>"), where) == EOF)
4447c478bd9Sstevel@tonic-gate 			return (-1);
4457c478bd9Sstevel@tonic-gate 	} else {
4467c478bd9Sstevel@tonic-gate 		if (fputs(alg->a_names[0], where) == EOF)
4477c478bd9Sstevel@tonic-gate 			return (-1);
4487c478bd9Sstevel@tonic-gate 	}
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 	freeipsecalgent(alg);
4517c478bd9Sstevel@tonic-gate 	return (0);
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate int
dump_aalg(uint8_t aalg,FILE * where)4557c478bd9Sstevel@tonic-gate dump_aalg(uint8_t aalg, FILE *where)
4567c478bd9Sstevel@tonic-gate {
4577c478bd9Sstevel@tonic-gate 	return (dump_generic_alg(aalg, IPSEC_PROTO_AH, where));
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate int
dump_ealg(uint8_t ealg,FILE * where)4617c478bd9Sstevel@tonic-gate dump_ealg(uint8_t ealg, FILE *where)
4627c478bd9Sstevel@tonic-gate {
4637c478bd9Sstevel@tonic-gate 	return (dump_generic_alg(ealg, IPSEC_PROTO_ESP, where));
4647c478bd9Sstevel@tonic-gate }
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate /*
4677c478bd9Sstevel@tonic-gate  * Print an SADB_IDENTTYPE string
4687c478bd9Sstevel@tonic-gate  *
4697c478bd9Sstevel@tonic-gate  * Also return TRUE if the actual ident may be printed, FALSE if not.
4707c478bd9Sstevel@tonic-gate  *
4717c478bd9Sstevel@tonic-gate  * If rc is not NULL, set its value to -1 if an error occured while writing
4727c478bd9Sstevel@tonic-gate  * to the specified file, zero otherwise.
4737c478bd9Sstevel@tonic-gate  */
4747c478bd9Sstevel@tonic-gate boolean_t
dump_sadb_idtype(uint8_t idtype,FILE * where,int * rc)4757c478bd9Sstevel@tonic-gate dump_sadb_idtype(uint8_t idtype, FILE *where, int *rc)
4767c478bd9Sstevel@tonic-gate {
4777c478bd9Sstevel@tonic-gate 	boolean_t canprint = B_TRUE;
4787c478bd9Sstevel@tonic-gate 	int rc_val = 0;
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	switch (idtype) {
4817c478bd9Sstevel@tonic-gate 	case SADB_IDENTTYPE_PREFIX:
482a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN, "prefix"), where) == EOF)
4837c478bd9Sstevel@tonic-gate 			rc_val = -1;
4847c478bd9Sstevel@tonic-gate 		break;
4857c478bd9Sstevel@tonic-gate 	case SADB_IDENTTYPE_FQDN:
486a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN, "FQDN"), where) == EOF)
4877c478bd9Sstevel@tonic-gate 			rc_val = -1;
4887c478bd9Sstevel@tonic-gate 		break;
4897c478bd9Sstevel@tonic-gate 	case SADB_IDENTTYPE_USER_FQDN:
490a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN,
491a7485808Smarkfen 		    "user-FQDN (mbox)"), where) == EOF)
4927c478bd9Sstevel@tonic-gate 			rc_val = -1;
4937c478bd9Sstevel@tonic-gate 		break;
4947c478bd9Sstevel@tonic-gate 	case SADB_X_IDENTTYPE_DN:
495a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN, "ASN.1 DER Distinguished Name"),
4967c478bd9Sstevel@tonic-gate 		    where) == EOF)
4977c478bd9Sstevel@tonic-gate 			rc_val = -1;
4987c478bd9Sstevel@tonic-gate 		canprint = B_FALSE;
4997c478bd9Sstevel@tonic-gate 		break;
5007c478bd9Sstevel@tonic-gate 	case SADB_X_IDENTTYPE_GN:
501a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN, "ASN.1 DER Generic Name"),
502a7485808Smarkfen 		    where) == EOF)
5037c478bd9Sstevel@tonic-gate 			rc_val = -1;
5047c478bd9Sstevel@tonic-gate 		canprint = B_FALSE;
5057c478bd9Sstevel@tonic-gate 		break;
5067c478bd9Sstevel@tonic-gate 	case SADB_X_IDENTTYPE_KEY_ID:
507a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN, "Generic key id"),
508a7485808Smarkfen 		    where) == EOF)
5097c478bd9Sstevel@tonic-gate 			rc_val = -1;
5107c478bd9Sstevel@tonic-gate 		break;
5117c478bd9Sstevel@tonic-gate 	case SADB_X_IDENTTYPE_ADDR_RANGE:
512a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN, "Address range"), where) == EOF)
5137c478bd9Sstevel@tonic-gate 			rc_val = -1;
5147c478bd9Sstevel@tonic-gate 		break;
5157c478bd9Sstevel@tonic-gate 	default:
516a7485808Smarkfen 		if (fprintf(where, dgettext(TEXT_DOMAIN,
517a7485808Smarkfen 		    "<unknown %u>"), idtype) < 0)
5187c478bd9Sstevel@tonic-gate 			rc_val = -1;
5197c478bd9Sstevel@tonic-gate 		break;
5207c478bd9Sstevel@tonic-gate 	}
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	if (rc != NULL)
5237c478bd9Sstevel@tonic-gate 		*rc = rc_val;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	return (canprint);
5267c478bd9Sstevel@tonic-gate }
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate /*
5297c478bd9Sstevel@tonic-gate  * Slice an argv/argc vector from an interactive line or a read-file line.
5307c478bd9Sstevel@tonic-gate  */
5317c478bd9Sstevel@tonic-gate static int
create_argv(char * ibuf,int * newargc,char *** thisargv)5327c478bd9Sstevel@tonic-gate create_argv(char *ibuf, int *newargc, char ***thisargv)
5337c478bd9Sstevel@tonic-gate {
5347c478bd9Sstevel@tonic-gate 	unsigned int argvlen = START_ARG;
5357c478bd9Sstevel@tonic-gate 	char **current;
5367c478bd9Sstevel@tonic-gate 	boolean_t firstchar = B_TRUE;
5377c478bd9Sstevel@tonic-gate 	boolean_t inquotes = B_FALSE;
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 	*thisargv = malloc(sizeof (char *) * argvlen);
5407c478bd9Sstevel@tonic-gate 	if ((*thisargv) == NULL)
5417c478bd9Sstevel@tonic-gate 		return (MEMORY_ALLOCATION);
5427c478bd9Sstevel@tonic-gate 	current = *thisargv;
5437c478bd9Sstevel@tonic-gate 	*current = NULL;
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate 	for (; *ibuf != '\0'; ibuf++) {
5467c478bd9Sstevel@tonic-gate 		if (isspace(*ibuf)) {
5477c478bd9Sstevel@tonic-gate 			if (inquotes) {
5487c478bd9Sstevel@tonic-gate 				continue;
5497c478bd9Sstevel@tonic-gate 			}
5507c478bd9Sstevel@tonic-gate 			if (*current != NULL) {
5517c478bd9Sstevel@tonic-gate 				*ibuf = '\0';
5527c478bd9Sstevel@tonic-gate 				current++;
5537c478bd9Sstevel@tonic-gate 				if (*thisargv + argvlen == current) {
5547c478bd9Sstevel@tonic-gate 					/* Regrow ***thisargv. */
5557c478bd9Sstevel@tonic-gate 					if (argvlen == TOO_MANY_ARGS) {
5567c478bd9Sstevel@tonic-gate 						free(*thisargv);
5577c478bd9Sstevel@tonic-gate 						return (TOO_MANY_TOKENS);
5587c478bd9Sstevel@tonic-gate 					}
5597c478bd9Sstevel@tonic-gate 					/* Double the allocation. */
5607c478bd9Sstevel@tonic-gate 					current = realloc(*thisargv,
5617c478bd9Sstevel@tonic-gate 					    sizeof (char *) * (argvlen << 1));
5627c478bd9Sstevel@tonic-gate 					if (current == NULL) {
5637c478bd9Sstevel@tonic-gate 						free(*thisargv);
5647c478bd9Sstevel@tonic-gate 						return (MEMORY_ALLOCATION);
5657c478bd9Sstevel@tonic-gate 					}
5667c478bd9Sstevel@tonic-gate 					*thisargv = current;
5677c478bd9Sstevel@tonic-gate 					current += argvlen;
5687c478bd9Sstevel@tonic-gate 					argvlen <<= 1;	/* Double the size. */
5697c478bd9Sstevel@tonic-gate 				}
5707c478bd9Sstevel@tonic-gate 				*current = NULL;
5717c478bd9Sstevel@tonic-gate 			}
5727c478bd9Sstevel@tonic-gate 		} else {
5737c478bd9Sstevel@tonic-gate 			if (firstchar) {
5747c478bd9Sstevel@tonic-gate 				firstchar = B_FALSE;
575e3320f40Smarkfen 				if (*ibuf == COMMENT_CHAR || *ibuf == '\n') {
5767c478bd9Sstevel@tonic-gate 					free(*thisargv);
5777c478bd9Sstevel@tonic-gate 					return (COMMENT_LINE);
5787c478bd9Sstevel@tonic-gate 				}
5797c478bd9Sstevel@tonic-gate 			}
5807c478bd9Sstevel@tonic-gate 			if (*ibuf == QUOTE_CHAR) {
5817c478bd9Sstevel@tonic-gate 				if (inquotes) {
5827c478bd9Sstevel@tonic-gate 					inquotes = B_FALSE;
5837c478bd9Sstevel@tonic-gate 					*ibuf = '\0';
5847c478bd9Sstevel@tonic-gate 				} else {
5857c478bd9Sstevel@tonic-gate 					inquotes = B_TRUE;
5867c478bd9Sstevel@tonic-gate 				}
5877c478bd9Sstevel@tonic-gate 				continue;
5887c478bd9Sstevel@tonic-gate 			}
5897c478bd9Sstevel@tonic-gate 			if (*current == NULL) {
5907c478bd9Sstevel@tonic-gate 				*current = ibuf;
5917c478bd9Sstevel@tonic-gate 				(*newargc)++;
5927c478bd9Sstevel@tonic-gate 			}
5937c478bd9Sstevel@tonic-gate 		}
5947c478bd9Sstevel@tonic-gate 	}
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 	/*
5977c478bd9Sstevel@tonic-gate 	 * Tricky corner case...
5987c478bd9Sstevel@tonic-gate 	 * I've parsed _exactly_ the amount of args as I have space.  It
5997c478bd9Sstevel@tonic-gate 	 * won't return NULL-terminated, and bad things will happen to
6007c478bd9Sstevel@tonic-gate 	 * the caller.
6017c478bd9Sstevel@tonic-gate 	 */
6027c478bd9Sstevel@tonic-gate 	if (argvlen == *newargc) {
6037c478bd9Sstevel@tonic-gate 		current = realloc(*thisargv, sizeof (char *) * (argvlen + 1));
6047c478bd9Sstevel@tonic-gate 		if (current == NULL) {
6057c478bd9Sstevel@tonic-gate 			free(*thisargv);
6067c478bd9Sstevel@tonic-gate 			return (MEMORY_ALLOCATION);
6077c478bd9Sstevel@tonic-gate 		}
6087c478bd9Sstevel@tonic-gate 		*thisargv = current;
6097c478bd9Sstevel@tonic-gate 		current[argvlen] = NULL;
6107c478bd9Sstevel@tonic-gate 	}
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	return (SUCCESS);
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate 
615bfe6f8f5SVladimir Kotal /*
616bfe6f8f5SVladimir Kotal  * init interactive mode if needed and not yet initialized
617bfe6f8f5SVladimir Kotal  */
618bfe6f8f5SVladimir Kotal static void
init_interactive(FILE * infile,CplMatchFn * match_fn)619bfe6f8f5SVladimir Kotal init_interactive(FILE *infile, CplMatchFn *match_fn)
620bfe6f8f5SVladimir Kotal {
621bfe6f8f5SVladimir Kotal 	if (infile == stdin) {
622bfe6f8f5SVladimir Kotal 		if (gl == NULL) {
623bfe6f8f5SVladimir Kotal 			if ((gl = new_GetLine(MAX_LINE_LEN,
624bfe6f8f5SVladimir Kotal 			    MAX_CMD_HIST)) == NULL)
625bfe6f8f5SVladimir Kotal 				errx(1, dgettext(TEXT_DOMAIN,
626bfe6f8f5SVladimir Kotal 				    "tecla initialization failed"));
627bfe6f8f5SVladimir Kotal 
628bfe6f8f5SVladimir Kotal 			if (gl_customize_completion(gl, NULL,
629bfe6f8f5SVladimir Kotal 			    match_fn) != 0) {
630bfe6f8f5SVladimir Kotal 				(void) del_GetLine(gl);
631bfe6f8f5SVladimir Kotal 				errx(1, dgettext(TEXT_DOMAIN,
632bfe6f8f5SVladimir Kotal 				    "tab completion failed to initialize"));
633bfe6f8f5SVladimir Kotal 			}
634bfe6f8f5SVladimir Kotal 
635bfe6f8f5SVladimir Kotal 			/*
636bfe6f8f5SVladimir Kotal 			 * In interactive mode we only want to terminate
637bfe6f8f5SVladimir Kotal 			 * when explicitly requested (e.g. by a command).
638bfe6f8f5SVladimir Kotal 			 */
639bfe6f8f5SVladimir Kotal 			(void) sigset(SIGINT, SIG_IGN);
640bfe6f8f5SVladimir Kotal 		}
641bfe6f8f5SVladimir Kotal 	} else {
642bfe6f8f5SVladimir Kotal 		readfile = B_TRUE;
643bfe6f8f5SVladimir Kotal 	}
644bfe6f8f5SVladimir Kotal }
645bfe6f8f5SVladimir Kotal 
646bfe6f8f5SVladimir Kotal /*
647bfe6f8f5SVladimir Kotal  * free tecla data structure
648bfe6f8f5SVladimir Kotal  */
649bfe6f8f5SVladimir Kotal static void
fini_interactive(void)650bfe6f8f5SVladimir Kotal fini_interactive(void)
651bfe6f8f5SVladimir Kotal {
652bfe6f8f5SVladimir Kotal 	if (gl != NULL)
653bfe6f8f5SVladimir Kotal 		(void) del_GetLine(gl);
654bfe6f8f5SVladimir Kotal }
655bfe6f8f5SVladimir Kotal 
656bfe6f8f5SVladimir Kotal /*
657bfe6f8f5SVladimir Kotal  * Get single input line, wrapping around interactive and non-interactive
658bfe6f8f5SVladimir Kotal  * mode.
659bfe6f8f5SVladimir Kotal  */
660bfe6f8f5SVladimir Kotal static char *
do_getstr(FILE * infile,char * prompt,char * ibuf,size_t ibuf_size)661bfe6f8f5SVladimir Kotal do_getstr(FILE *infile, char *prompt, char *ibuf, size_t ibuf_size)
662bfe6f8f5SVladimir Kotal {
663bfe6f8f5SVladimir Kotal 	char	*line;
664bfe6f8f5SVladimir Kotal 
665bfe6f8f5SVladimir Kotal 	if (infile != stdin)
666bfe6f8f5SVladimir Kotal 		return (fgets(ibuf, ibuf_size, infile));
667bfe6f8f5SVladimir Kotal 
668bfe6f8f5SVladimir Kotal 	/*
669bfe6f8f5SVladimir Kotal 	 * If the user hits ^C then we want to catch it and
670bfe6f8f5SVladimir Kotal 	 * start over.  If the user hits EOF then we want to
671bfe6f8f5SVladimir Kotal 	 * bail out.
672bfe6f8f5SVladimir Kotal 	 */
673bfe6f8f5SVladimir Kotal once_again:
674bfe6f8f5SVladimir Kotal 	line = gl_get_line(gl, prompt, NULL, -1);
675bfe6f8f5SVladimir Kotal 	if (gl_return_status(gl) == GLR_SIGNAL) {
676bfe6f8f5SVladimir Kotal 		gl_abandon_line(gl);
677bfe6f8f5SVladimir Kotal 		goto once_again;
678bfe6f8f5SVladimir Kotal 	} else if (gl_return_status(gl) == GLR_ERROR) {
679bfe6f8f5SVladimir Kotal 		gl_abandon_line(gl);
680bfe6f8f5SVladimir Kotal 		errx(1, dgettext(TEXT_DOMAIN, "Error reading terminal: %s\n"),
681bfe6f8f5SVladimir Kotal 		    gl_error_message(gl, NULL, 0));
682bfe6f8f5SVladimir Kotal 	} else {
683bfe6f8f5SVladimir Kotal 		if (line != NULL) {
684bfe6f8f5SVladimir Kotal 			if (strlcpy(ibuf, line, ibuf_size) >= ibuf_size)
685bfe6f8f5SVladimir Kotal 				warnx(dgettext(TEXT_DOMAIN,
686bfe6f8f5SVladimir Kotal 				    "Line too long (max=%d chars)"),
687bfe6f8f5SVladimir Kotal 				    ibuf_size);
688bfe6f8f5SVladimir Kotal 			line = ibuf;
689bfe6f8f5SVladimir Kotal 		}
690bfe6f8f5SVladimir Kotal 	}
691bfe6f8f5SVladimir Kotal 
692bfe6f8f5SVladimir Kotal 	return (line);
693bfe6f8f5SVladimir Kotal }
694bfe6f8f5SVladimir Kotal 
6957c478bd9Sstevel@tonic-gate /*
6967c478bd9Sstevel@tonic-gate  * Enter a mode where commands are read from a file.  Treat stdin special.
6977c478bd9Sstevel@tonic-gate  */
6987c478bd9Sstevel@tonic-gate void
do_interactive(FILE * infile,char * configfile,char * promptstring,char * my_fmri,parse_cmdln_fn parseit,CplMatchFn * match_fn)699e3320f40Smarkfen do_interactive(FILE *infile, char *configfile, char *promptstring,
700bfe6f8f5SVladimir Kotal     char *my_fmri, parse_cmdln_fn parseit, CplMatchFn *match_fn)
7017c478bd9Sstevel@tonic-gate {
7027c478bd9Sstevel@tonic-gate 	char		ibuf[IBUF_SIZE], holder[IBUF_SIZE];
70380ad54c9SToomas Soome 	char		*volatile hptr, **thisargv, *ebuf;
7047c478bd9Sstevel@tonic-gate 	int		thisargc;
70580ad54c9SToomas Soome 	volatile boolean_t	continue_in_progress = B_FALSE;
706bfe6f8f5SVladimir Kotal 	char		*s;
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	(void) setjmp(env);
7097c478bd9Sstevel@tonic-gate 
710e3320f40Smarkfen 	ebuf = NULL;
7117c478bd9Sstevel@tonic-gate 	interactive = B_TRUE;
7127c478bd9Sstevel@tonic-gate 	bzero(ibuf, IBUF_SIZE);
7137c478bd9Sstevel@tonic-gate 
714bfe6f8f5SVladimir Kotal 	/* panics for us */
715bfe6f8f5SVladimir Kotal 	init_interactive(infile, match_fn);
7167c478bd9Sstevel@tonic-gate 
717bfe6f8f5SVladimir Kotal 	while ((s = do_getstr(infile, promptstring, ibuf, IBUF_SIZE)) != NULL) {
7187c478bd9Sstevel@tonic-gate 		if (readfile)
7197c478bd9Sstevel@tonic-gate 			lineno++;
7207c478bd9Sstevel@tonic-gate 		thisargc = 0;
7217c478bd9Sstevel@tonic-gate 		thisargv = NULL;
7227c478bd9Sstevel@tonic-gate 
7237c478bd9Sstevel@tonic-gate 		/*
7247c478bd9Sstevel@tonic-gate 		 * Check byte IBUF_SIZE - 2, because byte IBUF_SIZE - 1 will
7257c478bd9Sstevel@tonic-gate 		 * be null-terminated because of fgets().
7267c478bd9Sstevel@tonic-gate 		 */
7277c478bd9Sstevel@tonic-gate 		if (ibuf[IBUF_SIZE - 2] != '\0') {
728bfe6f8f5SVladimir Kotal 			if (infile == stdin) {
729bfe6f8f5SVladimir Kotal 				/* do_getstr() issued a warning already */
730bfe6f8f5SVladimir Kotal 				bzero(ibuf, IBUF_SIZE);
731bfe6f8f5SVladimir Kotal 				continue;
732bfe6f8f5SVladimir Kotal 			} else {
733bfe6f8f5SVladimir Kotal 				ipsecutil_exit(SERVICE_FATAL, my_fmri,
734bfe6f8f5SVladimir Kotal 				    debugfile, dgettext(TEXT_DOMAIN,
735bfe6f8f5SVladimir Kotal 				    "Line %d too big."), lineno);
736bfe6f8f5SVladimir Kotal 			}
7377c478bd9Sstevel@tonic-gate 		}
7387c478bd9Sstevel@tonic-gate 
7397c478bd9Sstevel@tonic-gate 		if (!continue_in_progress) {
7407c478bd9Sstevel@tonic-gate 			/* Use -2 because of \n from fgets. */
7417c478bd9Sstevel@tonic-gate 			if (ibuf[strlen(ibuf) - 2] == CONT_CHAR) {
7427c478bd9Sstevel@tonic-gate 				/*
7437c478bd9Sstevel@tonic-gate 				 * Can use strcpy here, I've checked the
7447c478bd9Sstevel@tonic-gate 				 * length already.
7457c478bd9Sstevel@tonic-gate 				 */
7467c478bd9Sstevel@tonic-gate 				(void) strcpy(holder, ibuf);
7477c478bd9Sstevel@tonic-gate 				hptr = &(holder[strlen(holder)]);
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 				/* Remove the CONT_CHAR from the string. */
7507c478bd9Sstevel@tonic-gate 				hptr[-2] = ' ';
7517c478bd9Sstevel@tonic-gate 
7527c478bd9Sstevel@tonic-gate 				continue_in_progress = B_TRUE;
7537c478bd9Sstevel@tonic-gate 				bzero(ibuf, IBUF_SIZE);
7547c478bd9Sstevel@tonic-gate 				continue;
7557c478bd9Sstevel@tonic-gate 			}
7567c478bd9Sstevel@tonic-gate 		} else {
7577c478bd9Sstevel@tonic-gate 			/* Handle continuations... */
7587c478bd9Sstevel@tonic-gate 			(void) strncpy(hptr, ibuf,
7597c478bd9Sstevel@tonic-gate 			    (size_t)(&(holder[IBUF_SIZE]) - hptr));
7607c478bd9Sstevel@tonic-gate 			if (holder[IBUF_SIZE - 1] != '\0') {
761e3320f40Smarkfen 				ipsecutil_exit(SERVICE_FATAL, my_fmri,
762e3320f40Smarkfen 				    debugfile, dgettext(TEXT_DOMAIN,
763e3320f40Smarkfen 				    "Command buffer overrun."));
7647c478bd9Sstevel@tonic-gate 			}
7657c478bd9Sstevel@tonic-gate 			/* Use - 2 because of \n from fgets. */
7667c478bd9Sstevel@tonic-gate 			if (hptr[strlen(hptr) - 2] == CONT_CHAR) {
7677c478bd9Sstevel@tonic-gate 				bzero(ibuf, IBUF_SIZE);
7687c478bd9Sstevel@tonic-gate 				hptr += strlen(hptr);
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate 				/* Remove the CONT_CHAR from the string. */
7717c478bd9Sstevel@tonic-gate 				hptr[-2] = ' ';
7727c478bd9Sstevel@tonic-gate 
7737c478bd9Sstevel@tonic-gate 				continue;
7747c478bd9Sstevel@tonic-gate 			} else {
7757c478bd9Sstevel@tonic-gate 				continue_in_progress = B_FALSE;
7767c478bd9Sstevel@tonic-gate 				/*
7777c478bd9Sstevel@tonic-gate 				 * I've already checked the length...
7787c478bd9Sstevel@tonic-gate 				 */
7797c478bd9Sstevel@tonic-gate 				(void) strcpy(ibuf, holder);
7807c478bd9Sstevel@tonic-gate 			}
7817c478bd9Sstevel@tonic-gate 		}
7827c478bd9Sstevel@tonic-gate 
783e3320f40Smarkfen 		/*
784e3320f40Smarkfen 		 * Just in case the command fails keep a copy of the
785e3320f40Smarkfen 		 * command buffer for diagnostic output.
786e3320f40Smarkfen 		 */
787e3320f40Smarkfen 		if (readfile) {
788e3320f40Smarkfen 			/*
789e3320f40Smarkfen 			 * The error buffer needs to be big enough to
790e3320f40Smarkfen 			 * hold the longest command string, plus
791e3320f40Smarkfen 			 * some extra text, see below.
792e3320f40Smarkfen 			 */
793e3320f40Smarkfen 			ebuf = calloc((IBUF_SIZE * 2), sizeof (char));
794e3320f40Smarkfen 			if (ebuf == NULL) {
795e3320f40Smarkfen 				ipsecutil_exit(SERVICE_FATAL, my_fmri,
796e3320f40Smarkfen 				    debugfile, dgettext(TEXT_DOMAIN,
797e3320f40Smarkfen 				    "Memory allocation error."));
798e3320f40Smarkfen 			} else {
799e3320f40Smarkfen 				(void) snprintf(ebuf, (IBUF_SIZE * 2),
800e3320f40Smarkfen 				    dgettext(TEXT_DOMAIN,
801e3320f40Smarkfen 				    "Config file entry near line %u "
802e3320f40Smarkfen 				    "caused error(s) or warnings:\n\n%s\n\n"),
803e3320f40Smarkfen 				    lineno, ibuf);
804e3320f40Smarkfen 			}
805e3320f40Smarkfen 		}
806e3320f40Smarkfen 
8077c478bd9Sstevel@tonic-gate 		switch (create_argv(ibuf, &thisargc, &thisargv)) {
8087c478bd9Sstevel@tonic-gate 		case TOO_MANY_TOKENS:
809e3320f40Smarkfen 			ipsecutil_exit(SERVICE_BADCONF, my_fmri, debugfile,
810e3320f40Smarkfen 			    dgettext(TEXT_DOMAIN, "Too many input tokens."));
8117c478bd9Sstevel@tonic-gate 			break;
8127c478bd9Sstevel@tonic-gate 		case MEMORY_ALLOCATION:
813e3320f40Smarkfen 			ipsecutil_exit(SERVICE_BADCONF, my_fmri, debugfile,
814e3320f40Smarkfen 			    dgettext(TEXT_DOMAIN, "Memory allocation error."));
8157c478bd9Sstevel@tonic-gate 			break;
8167c478bd9Sstevel@tonic-gate 		case COMMENT_LINE:
8177c478bd9Sstevel@tonic-gate 			/* Comment line. */
818e3320f40Smarkfen 			free(ebuf);
8197c478bd9Sstevel@tonic-gate 			break;
8207c478bd9Sstevel@tonic-gate 		default:
821e3320f40Smarkfen 			if (thisargc != 0) {
822e3320f40Smarkfen 				lines_parsed++;
823e3320f40Smarkfen 				/* ebuf consumed */
82425e435e0Spwernau 				parseit(thisargc, thisargv, ebuf, readfile);
825e3320f40Smarkfen 			} else {
826e3320f40Smarkfen 				free(ebuf);
827e3320f40Smarkfen 			}
8287c478bd9Sstevel@tonic-gate 			free(thisargv);
8297c478bd9Sstevel@tonic-gate 			if (infile == stdin) {
8307c478bd9Sstevel@tonic-gate 				(void) printf("%s", promptstring);
8317c478bd9Sstevel@tonic-gate 				(void) fflush(stdout);
8327c478bd9Sstevel@tonic-gate 			}
8337c478bd9Sstevel@tonic-gate 			break;
8347c478bd9Sstevel@tonic-gate 		}
8357c478bd9Sstevel@tonic-gate 		bzero(ibuf, IBUF_SIZE);
8367c478bd9Sstevel@tonic-gate 	}
837e3320f40Smarkfen 
838e3320f40Smarkfen 	/*
83925e435e0Spwernau 	 * The following code is ipseckey specific. This should never be
84025e435e0Spwernau 	 * used by ikeadm which also calls this function because ikeadm
84125e435e0Spwernau 	 * only runs interactively. If this ever changes this code block
84225e435e0Spwernau 	 * sould be revisited.
843e3320f40Smarkfen 	 */
84425e435e0Spwernau 	if (readfile) {
84525e435e0Spwernau 		if (lines_parsed != 0 && lines_added == 0) {
846e3320f40Smarkfen 			ipsecutil_exit(SERVICE_BADCONF, my_fmri, debugfile,
84725e435e0Spwernau 			    dgettext(TEXT_DOMAIN, "Configuration file did not "
84825e435e0Spwernau 			    "contain any valid SAs"));
84925e435e0Spwernau 		}
85025e435e0Spwernau 
85125e435e0Spwernau 		/*
85225e435e0Spwernau 		 * There were errors. Putting the service in maintenance mode.
853*bbf21555SRichard Lowe 		 * When svc.startd(8) allows services to degrade themselves,
85425e435e0Spwernau 		 * this should be revisited.
85525e435e0Spwernau 		 *
85625e435e0Spwernau 		 * If this function was called from a program running as a
857*bbf21555SRichard Lowe 		 * smf_method(7), print a warning message. Don't spew out the
858*bbf21555SRichard Lowe 		 * errors as these will end up in the smf(7) log file which is
85925e435e0Spwernau 		 * publically readable, the errors may contain sensitive
86025e435e0Spwernau 		 * information.
86125e435e0Spwernau 		 */
86225e435e0Spwernau 		if ((lines_added < lines_parsed) && (configfile != NULL)) {
86325e435e0Spwernau 			if (my_fmri != NULL) {
86425e435e0Spwernau 				ipsecutil_exit(SERVICE_BADCONF, my_fmri,
86525e435e0Spwernau 				    debugfile, dgettext(TEXT_DOMAIN,
86625e435e0Spwernau 				    "The configuration file contained %d "
86725e435e0Spwernau 				    "errors.\n"
86825e435e0Spwernau 				    "Manually check the configuration with:\n"
86925e435e0Spwernau 				    "ipseckey -c %s\n"
870*bbf21555SRichard Lowe 				    "Use svcadm(8) to clear maintenance "
87125e435e0Spwernau 				    "condition when errors are resolved.\n"),
87225e435e0Spwernau 				    lines_parsed - lines_added, configfile);
87325e435e0Spwernau 			} else {
87425e435e0Spwernau 				EXIT_BADCONFIG(NULL);
87525e435e0Spwernau 			}
876e3320f40Smarkfen 		} else {
87725e435e0Spwernau 			if (my_fmri != NULL)
87825e435e0Spwernau 				ipsecutil_exit(SERVICE_EXIT_OK, my_fmri,
87925e435e0Spwernau 				    debugfile, dgettext(TEXT_DOMAIN,
88025e435e0Spwernau 				    "%d actions successfully processed."),
88125e435e0Spwernau 				    lines_added);
882e3320f40Smarkfen 		}
883e3320f40Smarkfen 	} else {
884bfe6f8f5SVladimir Kotal 		/* no newline upon Ctrl-D */
885bfe6f8f5SVladimir Kotal 		if (s != NULL)
886bfe6f8f5SVladimir Kotal 			(void) putchar('\n');
88725e435e0Spwernau 		(void) fflush(stdout);
888e3320f40Smarkfen 	}
889bfe6f8f5SVladimir Kotal 
890bfe6f8f5SVladimir Kotal 	fini_interactive();
891bfe6f8f5SVladimir Kotal 
892e3320f40Smarkfen 	EXIT_OK(NULL);
8937c478bd9Sstevel@tonic-gate }
8947c478bd9Sstevel@tonic-gate 
8957c478bd9Sstevel@tonic-gate /*
8967c478bd9Sstevel@tonic-gate  * Functions to parse strings that represent a debug or privilege level.
8977c478bd9Sstevel@tonic-gate  * These functions are copied from main.c and door.c in usr.lib/in.iked/common.
8987c478bd9Sstevel@tonic-gate  * If this file evolves into a common library that may be used by in.iked
8997c478bd9Sstevel@tonic-gate  * as well as the usr.sbin utilities, those duplicate functions should be
9007c478bd9Sstevel@tonic-gate  * deleted.
9017c478bd9Sstevel@tonic-gate  *
9027c478bd9Sstevel@tonic-gate  * A privilege level may be represented by a simple keyword, corresponding
9037c478bd9Sstevel@tonic-gate  * to one of the possible levels.  A debug level may be represented by a
9047c478bd9Sstevel@tonic-gate  * series of keywords, separated by '+' or '-', indicating categories to
9057c478bd9Sstevel@tonic-gate  * be added or removed from the set of categories in the debug level.
9067c478bd9Sstevel@tonic-gate  * For example, +all-op corresponds to level 0xfffffffb (all flags except
9077c478bd9Sstevel@tonic-gate  * for D_OP set); while p1+p2+pfkey corresponds to level 0x38.  Note that
9087c478bd9Sstevel@tonic-gate  * the leading '+' is implicit; the first keyword in the list must be for
9097c478bd9Sstevel@tonic-gate  * a category that is to be added.
9107c478bd9Sstevel@tonic-gate  *
9117c478bd9Sstevel@tonic-gate  * These parsing functions make use of a local version of strtok, strtok_d,
9127c478bd9Sstevel@tonic-gate  * which includes an additional parameter, char *delim.  This param is filled
9137c478bd9Sstevel@tonic-gate  * in with the character which ends the returned token.  In other words,
9147c478bd9Sstevel@tonic-gate  * this version of strtok, in addition to returning the token, also returns
9157c478bd9Sstevel@tonic-gate  * the single character delimiter from the original string which marked the
9167c478bd9Sstevel@tonic-gate  * end of the token.
9177c478bd9Sstevel@tonic-gate  */
9187c478bd9Sstevel@tonic-gate static char *
strtok_d(char * string,const char * sepset,char * delim)9197c478bd9Sstevel@tonic-gate strtok_d(char *string, const char *sepset, char *delim)
9207c478bd9Sstevel@tonic-gate {
9217c478bd9Sstevel@tonic-gate 	static char	*lasts;
9227c478bd9Sstevel@tonic-gate 	char		*q, *r;
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 	/* first or subsequent call */
9257c478bd9Sstevel@tonic-gate 	if (string == NULL)
9267c478bd9Sstevel@tonic-gate 		string = lasts;
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate 	if (string == 0)		/* return if no tokens remaining */
9297c478bd9Sstevel@tonic-gate 		return (NULL);
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 	q = string + strspn(string, sepset);	/* skip leading separators */
9327c478bd9Sstevel@tonic-gate 
9337c478bd9Sstevel@tonic-gate 	if (*q == '\0')			/* return if no tokens remaining */
9347c478bd9Sstevel@tonic-gate 		return (NULL);
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate 	if ((r = strpbrk(q, sepset)) == NULL) {		/* move past token */
9377c478bd9Sstevel@tonic-gate 		lasts = 0;	/* indicate that this is last token */
9387c478bd9Sstevel@tonic-gate 	} else {
9397c478bd9Sstevel@tonic-gate 		*delim = *r;	/* save delimitor */
9407c478bd9Sstevel@tonic-gate 		*r = '\0';
9417c478bd9Sstevel@tonic-gate 		lasts = r + 1;
9427c478bd9Sstevel@tonic-gate 	}
9437c478bd9Sstevel@tonic-gate 	return (q);
9447c478bd9Sstevel@tonic-gate }
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate static keywdtab_t	privtab[] = {
9477c478bd9Sstevel@tonic-gate 	{ IKE_PRIV_MINIMUM,	"base" },
9487c478bd9Sstevel@tonic-gate 	{ IKE_PRIV_MODKEYS,	"modkeys" },
9497c478bd9Sstevel@tonic-gate 	{ IKE_PRIV_KEYMAT,	"keymat" },
9507c478bd9Sstevel@tonic-gate 	{ IKE_PRIV_MINIMUM,	"0" },
9517c478bd9Sstevel@tonic-gate };
9527c478bd9Sstevel@tonic-gate 
9537c478bd9Sstevel@tonic-gate int
privstr2num(char * str)9547c478bd9Sstevel@tonic-gate privstr2num(char *str)
9557c478bd9Sstevel@tonic-gate {
9567c478bd9Sstevel@tonic-gate 	keywdtab_t	*pp;
9577c478bd9Sstevel@tonic-gate 	char		*endp;
9587c478bd9Sstevel@tonic-gate 	int		 priv;
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate 	for (pp = privtab; pp < A_END(privtab); pp++) {
9617c478bd9Sstevel@tonic-gate 		if (strcasecmp(str, pp->kw_str) == 0)
9627c478bd9Sstevel@tonic-gate 			return (pp->kw_tag);
9637c478bd9Sstevel@tonic-gate 	}
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 	priv = strtol(str, &endp, 0);
9667c478bd9Sstevel@tonic-gate 	if (*endp == '\0')
9677c478bd9Sstevel@tonic-gate 		return (priv);
9687c478bd9Sstevel@tonic-gate 
9697c478bd9Sstevel@tonic-gate 	return (-1);
9707c478bd9Sstevel@tonic-gate }
9717c478bd9Sstevel@tonic-gate 
9727c478bd9Sstevel@tonic-gate static keywdtab_t	dbgtab[] = {
9737c478bd9Sstevel@tonic-gate 	{ D_CERT,	"cert" },
9747c478bd9Sstevel@tonic-gate 	{ D_KEY,	"key" },
9757c478bd9Sstevel@tonic-gate 	{ D_OP,		"op" },
9767c478bd9Sstevel@tonic-gate 	{ D_P1,		"p1" },
9777c478bd9Sstevel@tonic-gate 	{ D_P1,		"phase1" },
9787c478bd9Sstevel@tonic-gate 	{ D_P2,		"p2" },
9797c478bd9Sstevel@tonic-gate 	{ D_P2,		"phase2" },
9807c478bd9Sstevel@tonic-gate 	{ D_PFKEY,	"pfkey" },
9817c478bd9Sstevel@tonic-gate 	{ D_POL,	"pol" },
9827c478bd9Sstevel@tonic-gate 	{ D_POL,	"policy" },
9837c478bd9Sstevel@tonic-gate 	{ D_PROP,	"prop" },
9847c478bd9Sstevel@tonic-gate 	{ D_DOOR,	"door" },
9857c478bd9Sstevel@tonic-gate 	{ D_CONFIG,	"config" },
9865d3b8cb7SBill Sommerfeld 	{ D_LABEL,	"label" },
9877c478bd9Sstevel@tonic-gate 	{ D_ALL,	"all" },
9887c478bd9Sstevel@tonic-gate 	{ 0,		"0" },
9897c478bd9Sstevel@tonic-gate };
9907c478bd9Sstevel@tonic-gate 
9917c478bd9Sstevel@tonic-gate int
dbgstr2num(char * str)9927c478bd9Sstevel@tonic-gate dbgstr2num(char *str)
9937c478bd9Sstevel@tonic-gate {
9947c478bd9Sstevel@tonic-gate 	keywdtab_t	*dp;
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate 	for (dp = dbgtab; dp < A_END(dbgtab); dp++) {
9977c478bd9Sstevel@tonic-gate 		if (strcasecmp(str, dp->kw_str) == 0)
9987c478bd9Sstevel@tonic-gate 			return (dp->kw_tag);
9997c478bd9Sstevel@tonic-gate 	}
10007c478bd9Sstevel@tonic-gate 	return (D_INVALID);
10017c478bd9Sstevel@tonic-gate }
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate int
parsedbgopts(char * optarg)10047c478bd9Sstevel@tonic-gate parsedbgopts(char *optarg)
10057c478bd9Sstevel@tonic-gate {
10067c478bd9Sstevel@tonic-gate 	char	*argp, *endp, op, nextop;
10077c478bd9Sstevel@tonic-gate 	int	mask = 0, new;
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 	mask = strtol(optarg, &endp, 0);
10107c478bd9Sstevel@tonic-gate 	if (*endp == '\0')
10117c478bd9Sstevel@tonic-gate 		return (mask);
10127c478bd9Sstevel@tonic-gate 
10137c478bd9Sstevel@tonic-gate 	op = optarg[0];
10147c478bd9Sstevel@tonic-gate 	if (op != '-')
10157c478bd9Sstevel@tonic-gate 		op = '+';
10167c478bd9Sstevel@tonic-gate 	argp = strtok_d(optarg, "+-", &nextop);
10177c478bd9Sstevel@tonic-gate 	do {
10187c478bd9Sstevel@tonic-gate 		new = dbgstr2num(argp);
10197c478bd9Sstevel@tonic-gate 		if (new == D_INVALID) {
10207c478bd9Sstevel@tonic-gate 			/* we encountered an invalid keywd */
10217c478bd9Sstevel@tonic-gate 			return (new);
10227c478bd9Sstevel@tonic-gate 		}
10237c478bd9Sstevel@tonic-gate 		if (op == '+') {
10247c478bd9Sstevel@tonic-gate 			mask |= new;
10257c478bd9Sstevel@tonic-gate 		} else {
10267c478bd9Sstevel@tonic-gate 			mask &= ~new;
10277c478bd9Sstevel@tonic-gate 		}
10287c478bd9Sstevel@tonic-gate 		op = nextop;
10297c478bd9Sstevel@tonic-gate 	} while ((argp = strtok_d(NULL, "+-", &nextop)) != NULL);
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 	return (mask);
10327c478bd9Sstevel@tonic-gate }
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate /*
10367c478bd9Sstevel@tonic-gate  * functions to manipulate the kmcookie-label mapping file
10377c478bd9Sstevel@tonic-gate  */
10387c478bd9Sstevel@tonic-gate 
10397c478bd9Sstevel@tonic-gate /*
10407c478bd9Sstevel@tonic-gate  * Open, lockf, fdopen the given file, returning a FILE * on success,
10417c478bd9Sstevel@tonic-gate  * or NULL on failure.
10427c478bd9Sstevel@tonic-gate  */
10437c478bd9Sstevel@tonic-gate FILE *
kmc_open_and_lock(char * name)10447c478bd9Sstevel@tonic-gate kmc_open_and_lock(char *name)
10457c478bd9Sstevel@tonic-gate {
10467c478bd9Sstevel@tonic-gate 	int	fd, rtnerr;
10477c478bd9Sstevel@tonic-gate 	FILE	*fp;
10487c478bd9Sstevel@tonic-gate 
10497c478bd9Sstevel@tonic-gate 	if ((fd = open(name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
10507c478bd9Sstevel@tonic-gate 		return (NULL);
10517c478bd9Sstevel@tonic-gate 	}
10527c478bd9Sstevel@tonic-gate 	if (lockf(fd, F_LOCK, 0) < 0) {
10537c478bd9Sstevel@tonic-gate 		return (NULL);
10547c478bd9Sstevel@tonic-gate 	}
10557c478bd9Sstevel@tonic-gate 	if ((fp = fdopen(fd, "a+")) == NULL) {
10567c478bd9Sstevel@tonic-gate 		return (NULL);
10577c478bd9Sstevel@tonic-gate 	}
10587c478bd9Sstevel@tonic-gate 	if (fseek(fp, 0, SEEK_SET) < 0) {
10597c478bd9Sstevel@tonic-gate 		/* save errno in case fclose changes it */
10607c478bd9Sstevel@tonic-gate 		rtnerr = errno;
10617c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
10627c478bd9Sstevel@tonic-gate 		errno = rtnerr;
10637c478bd9Sstevel@tonic-gate 		return (NULL);
10647c478bd9Sstevel@tonic-gate 	}
10657c478bd9Sstevel@tonic-gate 	return (fp);
10667c478bd9Sstevel@tonic-gate }
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate /*
10697c478bd9Sstevel@tonic-gate  * Extract an integer cookie and string label from a line from the
10707c478bd9Sstevel@tonic-gate  * kmcookie-label file.  Return -1 on failure, 0 on success.
10717c478bd9Sstevel@tonic-gate  */
10727c478bd9Sstevel@tonic-gate int
kmc_parse_line(char * line,int * cookie,char ** label)10737c478bd9Sstevel@tonic-gate kmc_parse_line(char *line, int *cookie, char **label)
10747c478bd9Sstevel@tonic-gate {
10757c478bd9Sstevel@tonic-gate 	char	*cookiestr;
10767c478bd9Sstevel@tonic-gate 
10777c478bd9Sstevel@tonic-gate 	*cookie = 0;
10787c478bd9Sstevel@tonic-gate 	*label = NULL;
10797c478bd9Sstevel@tonic-gate 
10807c478bd9Sstevel@tonic-gate 	cookiestr = strtok(line, " \t\n");
10817c478bd9Sstevel@tonic-gate 	if (cookiestr == NULL) {
10827c478bd9Sstevel@tonic-gate 		return (-1);
10837c478bd9Sstevel@tonic-gate 	}
10847c478bd9Sstevel@tonic-gate 
10857c478bd9Sstevel@tonic-gate 	/* Everything that follows, up to the newline, is the label. */
10867c478bd9Sstevel@tonic-gate 	*label = strtok(NULL, "\n");
10877c478bd9Sstevel@tonic-gate 	if (*label == NULL) {
10887c478bd9Sstevel@tonic-gate 		return (-1);
10897c478bd9Sstevel@tonic-gate 	}
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate 	*cookie = atoi(cookiestr);
10927c478bd9Sstevel@tonic-gate 	return (0);
10937c478bd9Sstevel@tonic-gate }
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate /*
10967c478bd9Sstevel@tonic-gate  * Insert a mapping into the file (if it's not already there), given the
10977c478bd9Sstevel@tonic-gate  * new label.  Return the assigned cookie, or -1 on error.
10987c478bd9Sstevel@tonic-gate  */
10997c478bd9Sstevel@tonic-gate int
kmc_insert_mapping(char * label)11007c478bd9Sstevel@tonic-gate kmc_insert_mapping(char *label)
11017c478bd9Sstevel@tonic-gate {
11027c478bd9Sstevel@tonic-gate 	FILE	*map;
1103c99ab7ceSdanmcd 	char	linebuf[IBUF_SIZE];
11047c478bd9Sstevel@tonic-gate 	char	*cur_label;
11057c478bd9Sstevel@tonic-gate 	int	max_cookie = 0, cur_cookie, rtn_cookie;
11067c478bd9Sstevel@tonic-gate 	int	rtnerr = 0;
11077c478bd9Sstevel@tonic-gate 	boolean_t	found = B_FALSE;
11087c478bd9Sstevel@tonic-gate 
11097c478bd9Sstevel@tonic-gate 	/* open and lock the file; will sleep until lock is available */
11107c478bd9Sstevel@tonic-gate 	if ((map = kmc_open_and_lock(KMCFILE)) == NULL) {
11117c478bd9Sstevel@tonic-gate 		/* kmc_open_and_lock() sets errno appropriately */
11127c478bd9Sstevel@tonic-gate 		return (-1);
11137c478bd9Sstevel@tonic-gate 	}
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate 	while (fgets(linebuf, sizeof (linebuf), map) != NULL) {
11167c478bd9Sstevel@tonic-gate 
1117c99ab7ceSdanmcd 		/* Skip blank lines, which often come near EOF. */
1118c99ab7ceSdanmcd 		if (strlen(linebuf) == 0)
1119c99ab7ceSdanmcd 			continue;
1120c99ab7ceSdanmcd 
11217c478bd9Sstevel@tonic-gate 		if (kmc_parse_line(linebuf, &cur_cookie, &cur_label) < 0) {
11227c478bd9Sstevel@tonic-gate 			rtnerr = EINVAL;
11237c478bd9Sstevel@tonic-gate 			goto error;
11247c478bd9Sstevel@tonic-gate 		}
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate 		if (cur_cookie > max_cookie)
11277c478bd9Sstevel@tonic-gate 			max_cookie = cur_cookie;
11287c478bd9Sstevel@tonic-gate 
11297c478bd9Sstevel@tonic-gate 		if ((!found) && (strcmp(cur_label, label) == 0)) {
11307c478bd9Sstevel@tonic-gate 			found = B_TRUE;
11317c478bd9Sstevel@tonic-gate 			rtn_cookie = cur_cookie;
11327c478bd9Sstevel@tonic-gate 		}
11337c478bd9Sstevel@tonic-gate 	}
11347c478bd9Sstevel@tonic-gate 
11357c478bd9Sstevel@tonic-gate 	if (!found) {
11367c478bd9Sstevel@tonic-gate 		rtn_cookie = ++max_cookie;
11377c478bd9Sstevel@tonic-gate 		if ((fprintf(map, "%u\t%s\n", rtn_cookie, label) < 0) ||
11387c478bd9Sstevel@tonic-gate 		    (fflush(map) < 0)) {
11397c478bd9Sstevel@tonic-gate 			rtnerr = errno;
11407c478bd9Sstevel@tonic-gate 			goto error;
11417c478bd9Sstevel@tonic-gate 		}
11427c478bd9Sstevel@tonic-gate 	}
11437c478bd9Sstevel@tonic-gate 	(void) fclose(map);
11447c478bd9Sstevel@tonic-gate 
11457c478bd9Sstevel@tonic-gate 	return (rtn_cookie);
11467c478bd9Sstevel@tonic-gate 
11477c478bd9Sstevel@tonic-gate error:
11487c478bd9Sstevel@tonic-gate 	(void) fclose(map);
11497c478bd9Sstevel@tonic-gate 	errno = rtnerr;
11507c478bd9Sstevel@tonic-gate 	return (-1);
11517c478bd9Sstevel@tonic-gate }
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate /*
11547c478bd9Sstevel@tonic-gate  * Lookup the given cookie and return its corresponding label.  Return
11557c478bd9Sstevel@tonic-gate  * a pointer to the label on success, NULL on error (or if the label is
11567c478bd9Sstevel@tonic-gate  * not found).  Note that the returned label pointer points to a static
11577c478bd9Sstevel@tonic-gate  * string, so the label will be overwritten by a subsequent call to the
11587c478bd9Sstevel@tonic-gate  * function; the function is also not thread-safe as a result.
1159f4a6f97eSDan McDonald  *
1160f4a6f97eSDan McDonald  * Because this is possibly publically exported, do not change its name,
1161f4a6f97eSDan McDonald  * but this is for all intents and purposes an IKEv1/in.iked function.
11627c478bd9Sstevel@tonic-gate  */
11637c478bd9Sstevel@tonic-gate char *
kmc_lookup_by_cookie(int cookie)11647c478bd9Sstevel@tonic-gate kmc_lookup_by_cookie(int cookie)
11657c478bd9Sstevel@tonic-gate {
11667c478bd9Sstevel@tonic-gate 	FILE		*map;
1167c99ab7ceSdanmcd 	static char	linebuf[IBUF_SIZE];
11687c478bd9Sstevel@tonic-gate 	char		*cur_label;
11697c478bd9Sstevel@tonic-gate 	int		cur_cookie;
11707c478bd9Sstevel@tonic-gate 
11717c478bd9Sstevel@tonic-gate 	if ((map = kmc_open_and_lock(KMCFILE)) == NULL) {
11727c478bd9Sstevel@tonic-gate 		return (NULL);
11737c478bd9Sstevel@tonic-gate 	}
11747c478bd9Sstevel@tonic-gate 
11757c478bd9Sstevel@tonic-gate 	while (fgets(linebuf, sizeof (linebuf), map) != NULL) {
11767c478bd9Sstevel@tonic-gate 
11777c478bd9Sstevel@tonic-gate 		if (kmc_parse_line(linebuf, &cur_cookie, &cur_label) < 0) {
11787c478bd9Sstevel@tonic-gate 			(void) fclose(map);
11797c478bd9Sstevel@tonic-gate 			return (NULL);
11807c478bd9Sstevel@tonic-gate 		}
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate 		if (cookie == cur_cookie) {
11837c478bd9Sstevel@tonic-gate 			(void) fclose(map);
11847c478bd9Sstevel@tonic-gate 			return (cur_label);
11857c478bd9Sstevel@tonic-gate 		}
11867c478bd9Sstevel@tonic-gate 	}
11877c478bd9Sstevel@tonic-gate 	(void) fclose(map);
11887c478bd9Sstevel@tonic-gate 
11897c478bd9Sstevel@tonic-gate 	return (NULL);
11907c478bd9Sstevel@tonic-gate }
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate /*
11937c478bd9Sstevel@tonic-gate  * Parse basic extension headers and return in the passed-in pointer vector.
11947c478bd9Sstevel@tonic-gate  * Return values include:
11957c478bd9Sstevel@tonic-gate  *
11967c478bd9Sstevel@tonic-gate  *	KGE_OK	Everything's nice and parsed out.
11977c478bd9Sstevel@tonic-gate  *		If there are no extensions, place NULL in extv[0].
11987c478bd9Sstevel@tonic-gate  *	KGE_DUP	There is a duplicate extension.
11997c478bd9Sstevel@tonic-gate  *		First instance in appropriate bin.  First duplicate in
12007c478bd9Sstevel@tonic-gate  *		extv[0].
12017c478bd9Sstevel@tonic-gate  *	KGE_UNK	Unknown extension type encountered.  extv[0] contains
12027c478bd9Sstevel@tonic-gate  *		unknown header.
12037c478bd9Sstevel@tonic-gate  *	KGE_LEN	Extension length error.
12047c478bd9Sstevel@tonic-gate  *	KGE_CHK	High-level reality check failed on specific extension.
12057c478bd9Sstevel@tonic-gate  *
12067c478bd9Sstevel@tonic-gate  * My apologies for some of the pointer arithmetic in here.  I'm thinking
12077c478bd9Sstevel@tonic-gate  * like an assembly programmer, yet trying to make the compiler happy.
12087c478bd9Sstevel@tonic-gate  */
12097c478bd9Sstevel@tonic-gate int
spdsock_get_ext(spd_ext_t * extv[],spd_msg_t * basehdr,uint_t msgsize,char * diag_buf,uint_t diag_buf_len)12107c478bd9Sstevel@tonic-gate spdsock_get_ext(spd_ext_t *extv[], spd_msg_t *basehdr, uint_t msgsize,
12117c478bd9Sstevel@tonic-gate     char *diag_buf, uint_t diag_buf_len)
12127c478bd9Sstevel@tonic-gate {
12137c478bd9Sstevel@tonic-gate 	int i;
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 	if (diag_buf != NULL)
12167c478bd9Sstevel@tonic-gate 		diag_buf[0] = '\0';
12177c478bd9Sstevel@tonic-gate 
12187c478bd9Sstevel@tonic-gate 	for (i = 1; i <= SPD_EXT_MAX; i++)
12197c478bd9Sstevel@tonic-gate 		extv[i] = NULL;
12207c478bd9Sstevel@tonic-gate 
12217c478bd9Sstevel@tonic-gate 	i = 0;
12227c478bd9Sstevel@tonic-gate 	/* Use extv[0] as the "current working pointer". */
12237c478bd9Sstevel@tonic-gate 
12247c478bd9Sstevel@tonic-gate 	extv[0] = (spd_ext_t *)(basehdr + 1);
12257c478bd9Sstevel@tonic-gate 	msgsize = SPD_64TO8(msgsize);
12267c478bd9Sstevel@tonic-gate 
12277c478bd9Sstevel@tonic-gate 	while ((char *)extv[0] < ((char *)basehdr + msgsize)) {
12287c478bd9Sstevel@tonic-gate 		/* Check for unknown headers. */
12297c478bd9Sstevel@tonic-gate 		i++;
12307c478bd9Sstevel@tonic-gate 		if (extv[0]->spd_ext_type == 0 ||
12317c478bd9Sstevel@tonic-gate 		    extv[0]->spd_ext_type > SPD_EXT_MAX) {
12327c478bd9Sstevel@tonic-gate 			if (diag_buf != NULL) {
12337c478bd9Sstevel@tonic-gate 				(void) snprintf(diag_buf, diag_buf_len,
12347c478bd9Sstevel@tonic-gate 				    "spdsock ext 0x%X unknown: 0x%X",
12357c478bd9Sstevel@tonic-gate 				    i, extv[0]->spd_ext_type);
12367c478bd9Sstevel@tonic-gate 			}
12377c478bd9Sstevel@tonic-gate 			return (KGE_UNK);
12387c478bd9Sstevel@tonic-gate 		}
12397c478bd9Sstevel@tonic-gate 
12407c478bd9Sstevel@tonic-gate 		/*
12417c478bd9Sstevel@tonic-gate 		 * Check length.  Use uint64_t because extlen is in units
12427c478bd9Sstevel@tonic-gate 		 * of 64-bit words.  If length goes beyond the msgsize,
12437c478bd9Sstevel@tonic-gate 		 * return an error.  (Zero length also qualifies here.)
12447c478bd9Sstevel@tonic-gate 		 */
12457c478bd9Sstevel@tonic-gate 		if (extv[0]->spd_ext_len == 0 ||
12467c478bd9Sstevel@tonic-gate 		    (uint8_t *)((uint64_t *)extv[0] + extv[0]->spd_ext_len) >
12477c478bd9Sstevel@tonic-gate 		    (uint8_t *)((uint8_t *)basehdr + msgsize))
12487c478bd9Sstevel@tonic-gate 			return (KGE_LEN);
12497c478bd9Sstevel@tonic-gate 
12507c478bd9Sstevel@tonic-gate 		/* Check for redundant headers. */
12517c478bd9Sstevel@tonic-gate 		if (extv[extv[0]->spd_ext_type] != NULL)
12527c478bd9Sstevel@tonic-gate 			return (KGE_DUP);
12537c478bd9Sstevel@tonic-gate 
12547c478bd9Sstevel@tonic-gate 		/* If I make it here, assign the appropriate bin. */
12557c478bd9Sstevel@tonic-gate 		extv[extv[0]->spd_ext_type] = extv[0];
12567c478bd9Sstevel@tonic-gate 
12577c478bd9Sstevel@tonic-gate 		/* Advance pointer (See above for uint64_t ptr reasoning.) */
12587c478bd9Sstevel@tonic-gate 		extv[0] = (spd_ext_t *)
12597c478bd9Sstevel@tonic-gate 		    ((uint64_t *)extv[0] + extv[0]->spd_ext_len);
12607c478bd9Sstevel@tonic-gate 	}
12617c478bd9Sstevel@tonic-gate 
12627c478bd9Sstevel@tonic-gate 	/* Everything's cool. */
12637c478bd9Sstevel@tonic-gate 
12647c478bd9Sstevel@tonic-gate 	/*
12657c478bd9Sstevel@tonic-gate 	 * If extv[0] == NULL, then there are no extension headers in this
12667c478bd9Sstevel@tonic-gate 	 * message.  Ensure that this is the case.
12677c478bd9Sstevel@tonic-gate 	 */
12687c478bd9Sstevel@tonic-gate 	if (extv[0] == (spd_ext_t *)(basehdr + 1))
12697c478bd9Sstevel@tonic-gate 		extv[0] = NULL;
12707c478bd9Sstevel@tonic-gate 
12717c478bd9Sstevel@tonic-gate 	return (KGE_OK);
12727c478bd9Sstevel@tonic-gate }
12737c478bd9Sstevel@tonic-gate 
12747c478bd9Sstevel@tonic-gate const char *
spdsock_diag(int diagnostic)12757c478bd9Sstevel@tonic-gate spdsock_diag(int diagnostic)
12767c478bd9Sstevel@tonic-gate {
12777c478bd9Sstevel@tonic-gate 	switch (diagnostic) {
12787c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_NONE:
1279a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "no error"));
12807c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_UNKNOWN_EXT:
1281a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "unknown extension"));
12827c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_BAD_EXTLEN:
1283a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "bad extension length"));
12847c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_NO_RULE_EXT:
1285a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "no rule extension"));
12867c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_BAD_ADDR_LEN:
1287a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "bad address len"));
12887c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MIXED_AF:
1289a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "mixed address family"));
12907c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ADD_NO_MEM:
1291a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "add: no memory"));
12927c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ADD_WRONG_ACT_COUNT:
1293a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "add: wrong action count"));
12947c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ADD_BAD_TYPE:
1295a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "add: bad type"));
12967c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ADD_BAD_FLAGS:
1297a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "add: bad flags"));
12987c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ADD_INCON_FLAGS:
1299a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "add: inconsistent flags"));
13007c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_LCLPORT:
1301a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed local port"));
13027c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_LCLPORT:
1303a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate local port"));
13047c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_REMPORT:
1305a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed remote port"));
13067c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_REMPORT:
1307a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate remote port"));
13087c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_PROTO:
1309a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed proto"));
13107c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_PROTO:
1311a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate proto"));
13127c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_LCLADDR:
1313a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed local address"));
13147c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_LCLADDR:
1315a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate local address"));
13167c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_REMADDR:
1317a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed remote address"));
13187c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_REMADDR:
1319a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate remote address"));
13207c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_ACTION:
1321a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed action"));
13227c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_ACTION:
1323a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate action"));
13247c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_RULE:
1325a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed rule"));
13267c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_RULE:
1327a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate rule"));
13287c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_RULESET:
1329a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed ruleset"));
13307c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_RULESET:
1331a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate ruleset"));
13327c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_INVALID_RULE_INDEX:
1333a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "invalid rule index"));
13347c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_BAD_SPDID:
1335a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "bad spdid"));
13367c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_BAD_MSG_TYPE:
1337a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "bad message type"));
13387c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_UNSUPP_AH_ALG:
1339a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "unsupported AH algorithm"));
13407c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_UNSUPP_ESP_ENCR_ALG:
1341a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1342a7485808Smarkfen 		    "unsupported ESP encryption algorithm"));
13437c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_UNSUPP_ESP_AUTH_ALG:
1344a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1345a7485808Smarkfen 		    "unsupported ESP authentication algorithm"));
13467c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_UNSUPP_AH_KEYSIZE:
1347a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "unsupported AH key size"));
13487c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_UNSUPP_ESP_ENCR_KEYSIZE:
1349a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1350a7485808Smarkfen 		    "unsupported ESP encryption key size"));
13517c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_UNSUPP_ESP_AUTH_KEYSIZE:
1352a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1353a7485808Smarkfen 		    "unsupported ESP authentication key size"));
13547c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_NO_ACTION_EXT:
1355a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "No ACTION extension"));
13567c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ALG_ID_RANGE:
1357a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "invalid algorithm identifer"));
13587c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ALG_NUM_KEY_SIZES:
1359a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1360a7485808Smarkfen 		    "number of key sizes inconsistent"));
13617c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ALG_NUM_BLOCK_SIZES:
1362a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1363a7485808Smarkfen 		    "number of block sizes inconsistent"));
13647c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ALG_MECH_NAME_LEN:
1365a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "invalid mechanism name length"));
13668810c16bSdanmcd 	case SPD_DIAGNOSTIC_NOT_GLOBAL_OP:
1367a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1368a7485808Smarkfen 		    "operation not applicable to all policies"));
13698810c16bSdanmcd 	case SPD_DIAGNOSTIC_NO_TUNNEL_SELECTORS:
1370a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1371a7485808Smarkfen 		    "using selectors on a transport-mode tunnel"));
13727c478bd9Sstevel@tonic-gate 	default:
1373a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "unknown diagnostic"));
13747c478bd9Sstevel@tonic-gate 	}
13757c478bd9Sstevel@tonic-gate }
13767c478bd9Sstevel@tonic-gate 
13777c478bd9Sstevel@tonic-gate /*
13787c478bd9Sstevel@tonic-gate  * PF_KEY Diagnostic table.
13797c478bd9Sstevel@tonic-gate  *
13807c478bd9Sstevel@tonic-gate  * PF_KEY NOTE:  If you change pfkeyv2.h's SADB_X_DIAGNOSTIC_* space, this is
13817c478bd9Sstevel@tonic-gate  * where you need to add new messages.
13827c478bd9Sstevel@tonic-gate  */
13837c478bd9Sstevel@tonic-gate 
13847c478bd9Sstevel@tonic-gate const char *
keysock_diag(int diagnostic)13857c478bd9Sstevel@tonic-gate keysock_diag(int diagnostic)
13867c478bd9Sstevel@tonic-gate {
13877c478bd9Sstevel@tonic-gate 	switch (diagnostic) {
13888810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_NONE:
1389a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "No diagnostic"));
13907c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_UNKNOWN_MSG:
1391a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Unknown message type"));
13927c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_UNKNOWN_EXT:
1393a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Unknown extension type"));
13947c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_EXTLEN:
1395a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Bad extension length"));
13967c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_UNKNOWN_SATYPE:
1397a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1398a7485808Smarkfen 		    "Unknown Security Association type"));
13997c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_SATYPE_NEEDED:
1400a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1401a7485808Smarkfen 		    "Specific Security Association type needed"));
14027c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_NO_SADBS:
1403a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1404a7485808Smarkfen 		    "No Security Association Databases present"));
14057c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_NO_EXT:
1406a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1407a7485808Smarkfen 		    "No extensions needed for message"));
14087c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_SRC_AF:
1409a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Bad source address family"));
14107c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_DST_AF:
1411a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1412a7485808Smarkfen 		    "Bad destination address family"));
14137c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_PROXY_AF:
1414a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1415a7485808Smarkfen 		    "Bad inner-source address family"));
14167c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_AF_MISMATCH:
1417a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1418a7485808Smarkfen 		    "Source/destination address family mismatch"));
14197c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_SRC:
1420a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Bad source address value"));
14217c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_DST:
1422a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Bad destination address value"));
14237c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_ALLOC_HSERR:
1424a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1425a7485808Smarkfen 		    "Soft allocations limit more than hard limit"));
14267c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BYTES_HSERR:
1427a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1428a7485808Smarkfen 		    "Soft bytes limit more than hard limit"));
14297c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_ADDTIME_HSERR:
1430a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Soft add expiration time later "
14317c478bd9Sstevel@tonic-gate 		    "than hard expiration time"));
14327c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_USETIME_HSERR:
1433a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Soft use expiration time later "
14347c478bd9Sstevel@tonic-gate 		    "than hard expiration time"));
14357c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_SRC:
1436a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing source address"));
14377c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_DST:
1438a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing destination address"));
14397c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_SA:
1440a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing SA extension"));
14417c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_EKEY:
1442a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing encryption key"));
14437c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_AKEY:
1444a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing authentication key"));
14457c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_RANGE:
1446a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing SPI range"));
14477c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_SRC:
1448a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate source address"));
14497c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_DST:
1450a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate destination address"));
14517c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_SA:
1452a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate SA extension"));
14537c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_EKEY:
1454a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate encryption key"));
14557c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_AKEY:
1456a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate authentication key"));
14577c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_RANGE:
1458a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate SPI range"));
14597c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_SRC:
1460a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Malformed source address"));
14617c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_DST:
1462a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Malformed destination address"));
14637c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_SA:
1464a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Malformed SA extension"));
14657c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_EKEY:
1466a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Malformed encryption key"));
14677c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_AKEY:
1468a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Malformed authentication key"));
14697c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_RANGE:
1470a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Malformed SPI range"));
14717c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_AKEY_PRESENT:
1472a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Authentication key not needed"));
14737c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_EKEY_PRESENT:
1474a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Encryption key not needed"));
14757c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_PROP_PRESENT:
1476a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Proposal extension not needed"));
14777c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_SUPP_PRESENT:
1478a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1479a7485808Smarkfen 		    "Supported algorithms extension not needed"));
14807c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_AALG:
1481a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1482a7485808Smarkfen 		    "Unsupported authentication algorithm"));
14837c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_EALG:
1484a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1485a7485808Smarkfen 		    "Unsupported encryption algorithm"));
14867c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_SAFLAGS:
1487a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Invalid SA flags"));
14887c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_SASTATE:
1489a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Invalid SA state"));
14907c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_AKEYBITS:
1491a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1492a7485808Smarkfen 		    "Bad number of authentication bits"));
14937c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_EKEYBITS:
1494a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1495a7485808Smarkfen 		    "Bad number of encryption bits"));
14967c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_ENCR_NOTSUPP:
1497a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1498a7485808Smarkfen 		    "Encryption not supported for this SA type"));
14997c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_WEAK_EKEY:
1500a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Weak encryption key"));
15017c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_WEAK_AKEY:
1502a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Weak authentication key"));
15037c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_KMP:
1504a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1505a7485808Smarkfen 		    "Duplicate key management protocol"));
15067c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_KMC:
1507a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1508a7485808Smarkfen 		    "Duplicate key management cookie"));
15097c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_NATT_LOC:
1510a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing NAT-T local address"));
15117c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_NATT_REM:
1512a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing NAT-T remote address"));
15137c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_LOC:
1514a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate NAT-T local address"));
15157c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_REM:
1516a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1517a7485808Smarkfen 		    "Duplicate NAT-T remote address"));
15187c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_NATT_LOC:
1519a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Malformed NAT-T local address"));
15207c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_NATT_REM:
1521a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1522a7485808Smarkfen 		    "Malformed NAT-T remote address"));
15237c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_PORTS:
1524a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate NAT-T ports"));
15258810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_MISSING_INNER_SRC:
1526a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing inner source address"));
15278810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_MISSING_INNER_DST:
1528a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1529a7485808Smarkfen 		    "Missing inner destination address"));
15308810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_DUPLICATE_INNER_SRC:
1531a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1532a7485808Smarkfen 		    "Duplicate inner source address"));
15338810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_DUPLICATE_INNER_DST:
1534a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1535a7485808Smarkfen 		    "Duplicate inner destination address"));
15368810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_MALFORMED_INNER_SRC:
1537a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1538a7485808Smarkfen 		    "Malformed inner source address"));
15398810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_MALFORMED_INNER_DST:
1540a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1541a7485808Smarkfen 		    "Malformed inner destination address"));
15428810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_PREFIX_INNER_SRC:
1543a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1544a7485808Smarkfen 		    "Invalid inner-source prefix length "));
15458810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_PREFIX_INNER_DST:
1546a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1547a7485808Smarkfen 		    "Invalid inner-destination prefix length"));
15488810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_BAD_INNER_DST_AF:
1549a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1550a7485808Smarkfen 		    "Bad inner-destination address family"));
15518810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH:
1552a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
15538810c16bSdanmcd 		    "Inner source/destination address family mismatch"));
15548810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_BAD_NATT_REM_AF:
1555a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1556a7485808Smarkfen 		    "Bad NAT-T remote address family"));
15578810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_BAD_NATT_LOC_AF:
1558a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1559a7485808Smarkfen 		    "Bad NAT-T local address family"));
15608810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_PROTO_MISMATCH:
1561a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1562a7485808Smarkfen 		    "Source/desination protocol mismatch"));
15638810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_INNER_PROTO_MISMATCH:
1564a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1565a7485808Smarkfen 		    "Inner source/desination protocol mismatch"));
15668810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_DUAL_PORT_SETS:
1567a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1568a7485808Smarkfen 		    "Both inner ports and outer ports are set"));
156938d95a78Smarkfen 	case SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE:
157038d95a78Smarkfen 		return (dgettext(TEXT_DOMAIN,
157138d95a78Smarkfen 		    "Pairing failed, target SA unsuitable for pairing"));
157238d95a78Smarkfen 	case SADB_X_DIAGNOSTIC_PAIR_ADD_MISMATCH:
157338d95a78Smarkfen 		return (dgettext(TEXT_DOMAIN,
157438d95a78Smarkfen 		    "Source/destination address differs from pair SA"));
157538d95a78Smarkfen 	case SADB_X_DIAGNOSTIC_PAIR_ALREADY:
157638d95a78Smarkfen 		return (dgettext(TEXT_DOMAIN,
157738d95a78Smarkfen 		    "Already paired with another security association"));
157838d95a78Smarkfen 	case SADB_X_DIAGNOSTIC_PAIR_SA_NOTFOUND:
157938d95a78Smarkfen 		return (dgettext(TEXT_DOMAIN,
158038d95a78Smarkfen 		    "Command failed, pair security association not found"));
158138d95a78Smarkfen 	case SADB_X_DIAGNOSTIC_BAD_SA_DIRECTION:
158238d95a78Smarkfen 		return (dgettext(TEXT_DOMAIN,
158338d95a78Smarkfen 		    "Inappropriate SA direction"));
158438d95a78Smarkfen 	case SADB_X_DIAGNOSTIC_SA_NOTFOUND:
158538d95a78Smarkfen 		return (dgettext(TEXT_DOMAIN,
158638d95a78Smarkfen 		    "Security association not found"));
158738d95a78Smarkfen 	case SADB_X_DIAGNOSTIC_SA_EXPIRED:
158838d95a78Smarkfen 		return (dgettext(TEXT_DOMAIN,
158938d95a78Smarkfen 		    "Security association is not valid"));
1590a1ba8781SMark Fenwick 	case SADB_X_DIAGNOSTIC_BAD_CTX:
1591a1ba8781SMark Fenwick 		return (dgettext(TEXT_DOMAIN,
1592a1ba8781SMark Fenwick 		    "Algorithm invalid or not supported by Crypto Framework"));
1593a1ba8781SMark Fenwick 	case SADB_X_DIAGNOSTIC_INVALID_REPLAY:
1594a1ba8781SMark Fenwick 		return (dgettext(TEXT_DOMAIN,
1595a1ba8781SMark Fenwick 		    "Invalid Replay counter"));
1596a1ba8781SMark Fenwick 	case SADB_X_DIAGNOSTIC_MISSING_LIFETIME:
1597a1ba8781SMark Fenwick 		return (dgettext(TEXT_DOMAIN,
1598a1ba8781SMark Fenwick 		    "Inappropriate lifetimes"));
15997c478bd9Sstevel@tonic-gate 	default:
1600a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Unknown diagnostic code"));
16017c478bd9Sstevel@tonic-gate 	}
16027c478bd9Sstevel@tonic-gate }
16038810c16bSdanmcd 
16048810c16bSdanmcd /*
16058810c16bSdanmcd  * Convert an IPv6 mask to a prefix len.  I assume all IPv6 masks are
16068810c16bSdanmcd  * contiguous, so I stop at the first zero bit!
16078810c16bSdanmcd  */
16088810c16bSdanmcd int
in_masktoprefix(uint8_t * mask,boolean_t is_v4mapped)16098810c16bSdanmcd in_masktoprefix(uint8_t *mask, boolean_t is_v4mapped)
16108810c16bSdanmcd {
16118810c16bSdanmcd 	int rc = 0;
16128810c16bSdanmcd 	uint8_t last;
16138810c16bSdanmcd 	int limit = IPV6_ABITS;
16148810c16bSdanmcd 
16158810c16bSdanmcd 	if (is_v4mapped) {
16168810c16bSdanmcd 		mask += ((IPV6_ABITS - IP_ABITS)/8);
16178810c16bSdanmcd 		limit = IP_ABITS;
16188810c16bSdanmcd 	}
16198810c16bSdanmcd 
16208810c16bSdanmcd 	while (*mask == 0xff) {
16218810c16bSdanmcd 		rc += 8;
16228810c16bSdanmcd 		if (rc == limit)
16238810c16bSdanmcd 			return (limit);
16248810c16bSdanmcd 		mask++;
16258810c16bSdanmcd 	}
16268810c16bSdanmcd 
16278810c16bSdanmcd 	last = *mask;
16288810c16bSdanmcd 	while (last != 0) {
16298810c16bSdanmcd 		rc++;
16308810c16bSdanmcd 		last = (last << 1) & 0xff;
16318810c16bSdanmcd 	}
16328810c16bSdanmcd 
16338810c16bSdanmcd 	return (rc);
16348810c16bSdanmcd }
16358810c16bSdanmcd 
16368810c16bSdanmcd /*
16378810c16bSdanmcd  * Expand the diagnostic code into a message.
16388810c16bSdanmcd  */
16398810c16bSdanmcd void
print_diagnostic(FILE * file,uint16_t diagnostic)16408810c16bSdanmcd print_diagnostic(FILE *file, uint16_t diagnostic)
16418810c16bSdanmcd {
16428810c16bSdanmcd 	/* Use two spaces so above strings can fit on the line. */
1643a7485808Smarkfen 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
1644a7485808Smarkfen 	    "  Diagnostic code %u:  %s.\n"),
16458810c16bSdanmcd 	    diagnostic, keysock_diag(diagnostic));
16468810c16bSdanmcd }
16478810c16bSdanmcd 
16488810c16bSdanmcd /*
16498810c16bSdanmcd  * Prints the base PF_KEY message.
16508810c16bSdanmcd  */
16518810c16bSdanmcd void
print_sadb_msg(FILE * file,struct sadb_msg * samsg,time_t wallclock,boolean_t vflag)1652bb3ed8dfSpwernau print_sadb_msg(FILE *file, struct sadb_msg *samsg, time_t wallclock,
1653bb3ed8dfSpwernau     boolean_t vflag)
16548810c16bSdanmcd {
16558810c16bSdanmcd 	if (wallclock != 0)
1656bb3ed8dfSpwernau 		printsatime(file, wallclock, dgettext(TEXT_DOMAIN,
1657a7485808Smarkfen 		    "%sTimestamp: %s\n"), "", NULL,
16588810c16bSdanmcd 		    vflag);
16598810c16bSdanmcd 
1660bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
1661bb3ed8dfSpwernau 	    "Base message (version %u) type "),
16628810c16bSdanmcd 	    samsg->sadb_msg_version);
16638810c16bSdanmcd 	switch (samsg->sadb_msg_type) {
16648810c16bSdanmcd 	case SADB_RESERVED:
1665bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1666a7485808Smarkfen 		    "RESERVED (warning: set to 0)"));
16678810c16bSdanmcd 		break;
16688810c16bSdanmcd 	case SADB_GETSPI:
1669bb3ed8dfSpwernau 		(void) fprintf(file, "GETSPI");
16708810c16bSdanmcd 		break;
16718810c16bSdanmcd 	case SADB_UPDATE:
1672bb3ed8dfSpwernau 		(void) fprintf(file, "UPDATE");
16738810c16bSdanmcd 		break;
167438d95a78Smarkfen 	case SADB_X_UPDATEPAIR:
167538d95a78Smarkfen 		(void) fprintf(file, "UPDATE PAIR");
167638d95a78Smarkfen 		break;
16778810c16bSdanmcd 	case SADB_ADD:
1678bb3ed8dfSpwernau 		(void) fprintf(file, "ADD");
16798810c16bSdanmcd 		break;
16808810c16bSdanmcd 	case SADB_DELETE:
1681bb3ed8dfSpwernau 		(void) fprintf(file, "DELETE");
16828810c16bSdanmcd 		break;
168338d95a78Smarkfen 	case SADB_X_DELPAIR:
168438d95a78Smarkfen 		(void) fprintf(file, "DELETE PAIR");
168538d95a78Smarkfen 		break;
16868810c16bSdanmcd 	case SADB_GET:
1687bb3ed8dfSpwernau 		(void) fprintf(file, "GET");
16888810c16bSdanmcd 		break;
16898810c16bSdanmcd 	case SADB_ACQUIRE:
1690bb3ed8dfSpwernau 		(void) fprintf(file, "ACQUIRE");
16918810c16bSdanmcd 		break;
16928810c16bSdanmcd 	case SADB_REGISTER:
1693bb3ed8dfSpwernau 		(void) fprintf(file, "REGISTER");
16948810c16bSdanmcd 		break;
16958810c16bSdanmcd 	case SADB_EXPIRE:
1696bb3ed8dfSpwernau 		(void) fprintf(file, "EXPIRE");
16978810c16bSdanmcd 		break;
16988810c16bSdanmcd 	case SADB_FLUSH:
1699bb3ed8dfSpwernau 		(void) fprintf(file, "FLUSH");
17008810c16bSdanmcd 		break;
17018810c16bSdanmcd 	case SADB_DUMP:
1702bb3ed8dfSpwernau 		(void) fprintf(file, "DUMP");
17038810c16bSdanmcd 		break;
17048810c16bSdanmcd 	case SADB_X_PROMISC:
1705bb3ed8dfSpwernau 		(void) fprintf(file, "X_PROMISC");
17068810c16bSdanmcd 		break;
17078810c16bSdanmcd 	case SADB_X_INVERSE_ACQUIRE:
1708bb3ed8dfSpwernau 		(void) fprintf(file, "X_INVERSE_ACQUIRE");
17098810c16bSdanmcd 		break;
17108810c16bSdanmcd 	default:
1711bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1712a7485808Smarkfen 		    "Unknown (%u)"), samsg->sadb_msg_type);
17138810c16bSdanmcd 		break;
17148810c16bSdanmcd 	}
1715bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN, ", SA type "));
17168810c16bSdanmcd 
17178810c16bSdanmcd 	switch (samsg->sadb_msg_satype) {
17188810c16bSdanmcd 	case SADB_SATYPE_UNSPEC:
1719bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1720bb3ed8dfSpwernau 		    "<unspecified/all>"));
17218810c16bSdanmcd 		break;
17228810c16bSdanmcd 	case SADB_SATYPE_AH:
1723bb3ed8dfSpwernau 		(void) fprintf(file, "AH");
17248810c16bSdanmcd 		break;
17258810c16bSdanmcd 	case SADB_SATYPE_ESP:
1726bb3ed8dfSpwernau 		(void) fprintf(file, "ESP");
17278810c16bSdanmcd 		break;
17288810c16bSdanmcd 	case SADB_SATYPE_RSVP:
1729bb3ed8dfSpwernau 		(void) fprintf(file, "RSVP");
17308810c16bSdanmcd 		break;
17318810c16bSdanmcd 	case SADB_SATYPE_OSPFV2:
1732bb3ed8dfSpwernau 		(void) fprintf(file, "OSPFv2");
17338810c16bSdanmcd 		break;
17348810c16bSdanmcd 	case SADB_SATYPE_RIPV2:
1735bb3ed8dfSpwernau 		(void) fprintf(file, "RIPv2");
17368810c16bSdanmcd 		break;
17378810c16bSdanmcd 	case SADB_SATYPE_MIP:
1738bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "Mobile IP"));
17398810c16bSdanmcd 		break;
17408810c16bSdanmcd 	default:
1741bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1742a7485808Smarkfen 		    "<unknown %u>"), samsg->sadb_msg_satype);
17438810c16bSdanmcd 		break;
17448810c16bSdanmcd 	}
17458810c16bSdanmcd 
1746bb3ed8dfSpwernau 	(void) fprintf(file, ".\n");
17478810c16bSdanmcd 
17488810c16bSdanmcd 	if (samsg->sadb_msg_errno != 0) {
1749bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1750bb3ed8dfSpwernau 		    "Error %s from PF_KEY.\n"),
17518810c16bSdanmcd 		    strerror(samsg->sadb_msg_errno));
1752bb3ed8dfSpwernau 		print_diagnostic(file, samsg->sadb_x_msg_diagnostic);
17538810c16bSdanmcd 	}
17548810c16bSdanmcd 
1755bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
1756a7485808Smarkfen 	    "Message length %u bytes, seq=%u, pid=%u.\n"),
17578810c16bSdanmcd 	    SADB_64TO8(samsg->sadb_msg_len), samsg->sadb_msg_seq,
17588810c16bSdanmcd 	    samsg->sadb_msg_pid);
17598810c16bSdanmcd }
17608810c16bSdanmcd 
17618810c16bSdanmcd /*
17628810c16bSdanmcd  * Print the SA extension for PF_KEY.
17638810c16bSdanmcd  */
17648810c16bSdanmcd void
print_sa(FILE * file,char * prefix,struct sadb_sa * assoc)1765bb3ed8dfSpwernau print_sa(FILE *file, char *prefix, struct sadb_sa *assoc)
17668810c16bSdanmcd {
17678810c16bSdanmcd 	if (assoc->sadb_sa_len != SADB_8TO64(sizeof (*assoc))) {
1768bb3ed8dfSpwernau 		warnxfp(EFD(file), dgettext(TEXT_DOMAIN,
1769a7485808Smarkfen 		    "WARNING: SA info extension length (%u) is bad."),
17708810c16bSdanmcd 		    SADB_64TO8(assoc->sadb_sa_len));
17718810c16bSdanmcd 	}
17728810c16bSdanmcd 
1773bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
17749c2c14abSThejaswini Singarajipura 	    "%sSADB_ASSOC spi=0x%x, replay window size=%u, state="),
17758810c16bSdanmcd 	    prefix, ntohl(assoc->sadb_sa_spi), assoc->sadb_sa_replay);
17768810c16bSdanmcd 	switch (assoc->sadb_sa_state) {
17778810c16bSdanmcd 	case SADB_SASTATE_LARVAL:
1778bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "LARVAL"));
17798810c16bSdanmcd 		break;
17808810c16bSdanmcd 	case SADB_SASTATE_MATURE:
1781bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "MATURE"));
17828810c16bSdanmcd 		break;
17838810c16bSdanmcd 	case SADB_SASTATE_DYING:
1784bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "DYING"));
17858810c16bSdanmcd 		break;
17868810c16bSdanmcd 	case SADB_SASTATE_DEAD:
1787bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "DEAD"));
17888810c16bSdanmcd 		break;
17899c2c14abSThejaswini Singarajipura 	case SADB_X_SASTATE_ACTIVE_ELSEWHERE:
17909c2c14abSThejaswini Singarajipura 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
17919c2c14abSThejaswini Singarajipura 		    "ACTIVE_ELSEWHERE"));
17929c2c14abSThejaswini Singarajipura 		break;
17939c2c14abSThejaswini Singarajipura 	case SADB_X_SASTATE_IDLE:
17949c2c14abSThejaswini Singarajipura 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "IDLE"));
17959c2c14abSThejaswini Singarajipura 		break;
17968810c16bSdanmcd 	default:
1797bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1798a7485808Smarkfen 		    "<unknown %u>"), assoc->sadb_sa_state);
17998810c16bSdanmcd 	}
18008810c16bSdanmcd 
18018810c16bSdanmcd 	if (assoc->sadb_sa_auth != SADB_AALG_NONE) {
1802bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1803a7485808Smarkfen 		    "\n%sAuthentication algorithm = "),
18048810c16bSdanmcd 		    prefix);
1805bb3ed8dfSpwernau 		(void) dump_aalg(assoc->sadb_sa_auth, file);
18068810c16bSdanmcd 	}
18078810c16bSdanmcd 
18088810c16bSdanmcd 	if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) {
1809bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1810a7485808Smarkfen 		    "\n%sEncryption algorithm = "), prefix);
1811bb3ed8dfSpwernau 		(void) dump_ealg(assoc->sadb_sa_encrypt, file);
18128810c16bSdanmcd 	}
18138810c16bSdanmcd 
1814bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN, "\n%sflags=0x%x < "), prefix,
18158810c16bSdanmcd 	    assoc->sadb_sa_flags);
18168810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_SAFLAGS_PFS)
1817bb3ed8dfSpwernau 		(void) fprintf(file, "PFS ");
18188810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_SAFLAGS_NOREPLAY)
1819bb3ed8dfSpwernau 		(void) fprintf(file, "NOREPLAY ");
18208810c16bSdanmcd 
18218810c16bSdanmcd 	/* BEGIN Solaris-specific flags. */
18228810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_USED)
1823bb3ed8dfSpwernau 		(void) fprintf(file, "X_USED ");
182438d95a78Smarkfen 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_PAIRED)
182538d95a78Smarkfen 		(void) fprintf(file, "X_PAIRED ");
182638d95a78Smarkfen 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_OUTBOUND)
182738d95a78Smarkfen 		(void) fprintf(file, "X_OUTBOUND ");
182838d95a78Smarkfen 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_INBOUND)
182938d95a78Smarkfen 		(void) fprintf(file, "X_INBOUND ");
18308810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_UNIQUE)
1831bb3ed8dfSpwernau 		(void) fprintf(file, "X_UNIQUE ");
18328810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_AALG1)
1833bb3ed8dfSpwernau 		(void) fprintf(file, "X_AALG1 ");
18348810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_AALG2)
1835bb3ed8dfSpwernau 		(void) fprintf(file, "X_AALG2 ");
18368810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_EALG1)
1837bb3ed8dfSpwernau 		(void) fprintf(file, "X_EALG1 ");
18388810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_EALG2)
1839bb3ed8dfSpwernau 		(void) fprintf(file, "X_EALG2 ");
18408810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_NATT_LOC)
1841bb3ed8dfSpwernau 		(void) fprintf(file, "X_NATT_LOC ");
18428810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_NATT_REM)
1843bb3ed8dfSpwernau 		(void) fprintf(file, "X_NATT_REM ");
18448810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_TUNNEL)
1845bb3ed8dfSpwernau 		(void) fprintf(file, "X_TUNNEL ");
18464a179720Sdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_NATTED)
18474a179720Sdanmcd 		(void) fprintf(file, "X_NATTED ");
18488810c16bSdanmcd 	/* END Solaris-specific flags. */
18498810c16bSdanmcd 
1850bb3ed8dfSpwernau 	(void) fprintf(file, ">\n");
18518810c16bSdanmcd }
18528810c16bSdanmcd 
18538810c16bSdanmcd void
printsatime(FILE * file,int64_t lt,const char * msg,const char * pfx,const char * pfx2,boolean_t vflag)1854bb3ed8dfSpwernau printsatime(FILE *file, int64_t lt, const char *msg, const char *pfx,
1855bb3ed8dfSpwernau     const char *pfx2, boolean_t vflag)
18568810c16bSdanmcd {
18578810c16bSdanmcd 	char tbuf[TBUF_SIZE]; /* For strftime() call. */
18588810c16bSdanmcd 	const char *tp = tbuf;
18598810c16bSdanmcd 	time_t t = lt;
18608810c16bSdanmcd 	struct tm res;
18618810c16bSdanmcd 
18628810c16bSdanmcd 	if (t != lt) {
18638810c16bSdanmcd 		if (lt > 0)
18648810c16bSdanmcd 			t = LONG_MAX;
18658810c16bSdanmcd 		else
18668810c16bSdanmcd 			t = LONG_MIN;
18678810c16bSdanmcd 	}
18688810c16bSdanmcd 
18698810c16bSdanmcd 	if (strftime(tbuf, TBUF_SIZE, NULL, localtime_r(&t, &res)) == 0)
1870a7485808Smarkfen 		tp = dgettext(TEXT_DOMAIN, "<time conversion failed>");
1871bb3ed8dfSpwernau 	(void) fprintf(file, msg, pfx, tp);
18728810c16bSdanmcd 	if (vflag && (pfx2 != NULL))
1873bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1874c51cb4bcSDan McDonald 		    "%s\t(raw time value %" PRIu64 ")\n"), pfx2, lt);
18758810c16bSdanmcd }
18768810c16bSdanmcd 
18778810c16bSdanmcd /*
18788810c16bSdanmcd  * Print the SA lifetime information.  (An SADB_EXT_LIFETIME_* extension.)
18798810c16bSdanmcd  */
18808810c16bSdanmcd void
print_lifetimes(FILE * file,time_t wallclock,struct sadb_lifetime * current,struct sadb_lifetime * hard,struct sadb_lifetime * soft,struct sadb_lifetime * idle,boolean_t vflag)1881bb3ed8dfSpwernau print_lifetimes(FILE *file, time_t wallclock, struct sadb_lifetime *current,
18829c2c14abSThejaswini Singarajipura     struct sadb_lifetime *hard, struct sadb_lifetime *soft,
18839c2c14abSThejaswini Singarajipura     struct sadb_lifetime *idle, boolean_t vflag)
18848810c16bSdanmcd {
18858810c16bSdanmcd 	int64_t scratch;
1886a7485808Smarkfen 	char *soft_prefix = dgettext(TEXT_DOMAIN, "SLT: ");
1887a7485808Smarkfen 	char *hard_prefix = dgettext(TEXT_DOMAIN, "HLT: ");
1888a7485808Smarkfen 	char *current_prefix = dgettext(TEXT_DOMAIN, "CLT: ");
18899c2c14abSThejaswini Singarajipura 	char *idle_prefix = dgettext(TEXT_DOMAIN, "ILT: ");
1890510c3f91SVladimir Kotal 	char byte_str[BYTE_STR_SIZE]; /* byte lifetime string representation */
1891510c3f91SVladimir Kotal 	char secs_str[SECS_STR_SIZE]; /* buffer for seconds representation */
18928810c16bSdanmcd 
18938810c16bSdanmcd 	if (current != NULL &&
18948810c16bSdanmcd 	    current->sadb_lifetime_len != SADB_8TO64(sizeof (*current))) {
1895bb3ed8dfSpwernau 		warnxfp(EFD(file), dgettext(TEXT_DOMAIN,
1896a7485808Smarkfen 		    "WARNING: CURRENT lifetime extension length (%u) is bad."),
18978810c16bSdanmcd 		    SADB_64TO8(current->sadb_lifetime_len));
18988810c16bSdanmcd 	}
18998810c16bSdanmcd 
19008810c16bSdanmcd 	if (hard != NULL &&
19018810c16bSdanmcd 	    hard->sadb_lifetime_len != SADB_8TO64(sizeof (*hard))) {
1902bb3ed8dfSpwernau 		warnxfp(EFD(file), dgettext(TEXT_DOMAIN,
1903bb3ed8dfSpwernau 		    "WARNING: HARD lifetime extension length (%u) is bad."),
19048810c16bSdanmcd 		    SADB_64TO8(hard->sadb_lifetime_len));
19058810c16bSdanmcd 	}
19068810c16bSdanmcd 
19078810c16bSdanmcd 	if (soft != NULL &&
19088810c16bSdanmcd 	    soft->sadb_lifetime_len != SADB_8TO64(sizeof (*soft))) {
1909bb3ed8dfSpwernau 		warnxfp(EFD(file), dgettext(TEXT_DOMAIN,
1910bb3ed8dfSpwernau 		    "WARNING: SOFT lifetime extension length (%u) is bad."),
19118810c16bSdanmcd 		    SADB_64TO8(soft->sadb_lifetime_len));
19128810c16bSdanmcd 	}
19138810c16bSdanmcd 
19149c2c14abSThejaswini Singarajipura 	if (idle != NULL &&
19159c2c14abSThejaswini Singarajipura 	    idle->sadb_lifetime_len != SADB_8TO64(sizeof (*idle))) {
19169c2c14abSThejaswini Singarajipura 		warnxfp(EFD(file), dgettext(TEXT_DOMAIN,
19179c2c14abSThejaswini Singarajipura 		    "WARNING: IDLE lifetime extension length (%u) is bad."),
19189c2c14abSThejaswini Singarajipura 		    SADB_64TO8(idle->sadb_lifetime_len));
19199c2c14abSThejaswini Singarajipura 	}
19209c2c14abSThejaswini Singarajipura 
1921bb3ed8dfSpwernau 	(void) fprintf(file, " LT: Lifetime information\n");
19228810c16bSdanmcd 	if (current != NULL) {
19238810c16bSdanmcd 		/* Express values as current values. */
1924bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1925510c3f91SVladimir Kotal 		    "%sCurrent lifetime information:\n"),
1926510c3f91SVladimir Kotal 		    current_prefix);
1927510c3f91SVladimir Kotal 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1928510c3f91SVladimir Kotal 		    "%s%" PRIu64 " bytes %sprotected, %u allocations "
1929510c3f91SVladimir Kotal 		    "used.\n"), current_prefix,
1930510c3f91SVladimir Kotal 		    current->sadb_lifetime_bytes,
1931510c3f91SVladimir Kotal 		    bytecnt2out(current->sadb_lifetime_bytes, byte_str,
1932510c3f91SVladimir Kotal 		    sizeof (byte_str), SPC_END),
19338810c16bSdanmcd 		    current->sadb_lifetime_allocations);
1934bb3ed8dfSpwernau 		printsatime(file, current->sadb_lifetime_addtime,
1935510c3f91SVladimir Kotal 		    dgettext(TEXT_DOMAIN, "%sSA added at time: %s\n"),
19368810c16bSdanmcd 		    current_prefix, current_prefix, vflag);
19378810c16bSdanmcd 		if (current->sadb_lifetime_usetime != 0) {
1938bb3ed8dfSpwernau 			printsatime(file, current->sadb_lifetime_usetime,
1939a7485808Smarkfen 			    dgettext(TEXT_DOMAIN,
1940a7485808Smarkfen 			    "%sSA first used at time %s\n"),
19418810c16bSdanmcd 			    current_prefix, current_prefix, vflag);
19428810c16bSdanmcd 		}
1943bb3ed8dfSpwernau 		printsatime(file, wallclock, dgettext(TEXT_DOMAIN,
1944a7485808Smarkfen 		    "%sTime now is %s\n"), current_prefix, current_prefix,
1945a7485808Smarkfen 		    vflag);
19468810c16bSdanmcd 	}
19478810c16bSdanmcd 
19488810c16bSdanmcd 	if (soft != NULL) {
1949bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1950510c3f91SVladimir Kotal 		    "%sSoft lifetime information:\n"),
19518810c16bSdanmcd 		    soft_prefix);
1952bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1953510c3f91SVladimir Kotal 		    "%s%" PRIu64 " bytes %sof lifetime, %u allocations.\n"),
1954510c3f91SVladimir Kotal 		    soft_prefix,
1955510c3f91SVladimir Kotal 		    soft->sadb_lifetime_bytes,
1956510c3f91SVladimir Kotal 		    bytecnt2out(soft->sadb_lifetime_bytes, byte_str,
1957510c3f91SVladimir Kotal 		    sizeof (byte_str), SPC_END),
19588810c16bSdanmcd 		    soft->sadb_lifetime_allocations);
1959bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1960510c3f91SVladimir Kotal 		    "%s%" PRIu64 " seconds %sof post-add lifetime.\n"),
1961510c3f91SVladimir Kotal 		    soft_prefix, soft->sadb_lifetime_addtime,
1962510c3f91SVladimir Kotal 		    secs2out(soft->sadb_lifetime_addtime, secs_str,
1963510c3f91SVladimir Kotal 		    sizeof (secs_str), SPC_END));
1964bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1965510c3f91SVladimir Kotal 		    "%s%" PRIu64 " seconds %sof post-use lifetime.\n"),
1966510c3f91SVladimir Kotal 		    soft_prefix, soft->sadb_lifetime_usetime,
1967510c3f91SVladimir Kotal 		    secs2out(soft->sadb_lifetime_usetime, secs_str,
1968510c3f91SVladimir Kotal 		    sizeof (secs_str), SPC_END));
19698810c16bSdanmcd 		/* If possible, express values as time remaining. */
19708810c16bSdanmcd 		if (current != NULL) {
19718810c16bSdanmcd 			if (soft->sadb_lifetime_bytes != 0)
1972510c3f91SVladimir Kotal 				(void) fprintf(file, dgettext(TEXT_DOMAIN, "%s"
1973510c3f91SVladimir Kotal 				    "%" PRIu64 " bytes %smore can be "
1974510c3f91SVladimir Kotal 				    "protected.\n"), soft_prefix,
1975510c3f91SVladimir Kotal 				    (soft->sadb_lifetime_bytes >
1976510c3f91SVladimir Kotal 				    current->sadb_lifetime_bytes) ?
1977510c3f91SVladimir Kotal 				    soft->sadb_lifetime_bytes -
1978510c3f91SVladimir Kotal 				    current->sadb_lifetime_bytes : 0,
19798810c16bSdanmcd 				    (soft->sadb_lifetime_bytes >
198025e435e0Spwernau 				    current->sadb_lifetime_bytes) ?
1981510c3f91SVladimir Kotal 				    bytecnt2out(soft->sadb_lifetime_bytes -
1982510c3f91SVladimir Kotal 				    current->sadb_lifetime_bytes, byte_str,
1983510c3f91SVladimir Kotal 				    sizeof (byte_str), SPC_END) : "");
19848810c16bSdanmcd 			if (soft->sadb_lifetime_addtime != 0 ||
19858810c16bSdanmcd 			    (soft->sadb_lifetime_usetime != 0 &&
198625e435e0Spwernau 			    current->sadb_lifetime_usetime != 0)) {
19878810c16bSdanmcd 				int64_t adddelta, usedelta;
19888810c16bSdanmcd 
19898810c16bSdanmcd 				if (soft->sadb_lifetime_addtime != 0) {
19908810c16bSdanmcd 					adddelta =
19918810c16bSdanmcd 					    current->sadb_lifetime_addtime +
19928810c16bSdanmcd 					    soft->sadb_lifetime_addtime -
19938810c16bSdanmcd 					    wallclock;
19948810c16bSdanmcd 				} else {
19958810c16bSdanmcd 					adddelta = TIME_MAX;
19968810c16bSdanmcd 				}
19978810c16bSdanmcd 
19988810c16bSdanmcd 				if (soft->sadb_lifetime_usetime != 0 &&
19998810c16bSdanmcd 				    current->sadb_lifetime_usetime != 0) {
20008810c16bSdanmcd 					usedelta =
20018810c16bSdanmcd 					    current->sadb_lifetime_usetime +
20028810c16bSdanmcd 					    soft->sadb_lifetime_usetime -
20038810c16bSdanmcd 					    wallclock;
20048810c16bSdanmcd 				} else {
20058810c16bSdanmcd 					usedelta = TIME_MAX;
20068810c16bSdanmcd 				}
2007bb3ed8dfSpwernau 				(void) fprintf(file, "%s", soft_prefix);
20088810c16bSdanmcd 				scratch = MIN(adddelta, usedelta);
20098810c16bSdanmcd 				if (scratch >= 0) {
2010bb3ed8dfSpwernau 					(void) fprintf(file,
2011bb3ed8dfSpwernau 					    dgettext(TEXT_DOMAIN,
2012c51cb4bcSDan McDonald 					    "Soft expiration occurs in %"
2013510c3f91SVladimir Kotal 					    PRId64 " seconds%s\n"), scratch,
2014510c3f91SVladimir Kotal 					    secs2out(scratch, secs_str,
2015510c3f91SVladimir Kotal 					    sizeof (secs_str), SPC_BEGIN));
20168810c16bSdanmcd 				} else {
2017bb3ed8dfSpwernau 					(void) fprintf(file,
2018bb3ed8dfSpwernau 					    dgettext(TEXT_DOMAIN,
2019510c3f91SVladimir Kotal 					    "Soft expiration occurred\n"));
20208810c16bSdanmcd 				}
20218810c16bSdanmcd 				scratch += wallclock;
2022bb3ed8dfSpwernau 				printsatime(file, scratch, dgettext(TEXT_DOMAIN,
2023510c3f91SVladimir Kotal 				    "%sTime of expiration: %s.\n"),
2024510c3f91SVladimir Kotal 				    soft_prefix, soft_prefix, vflag);
20258810c16bSdanmcd 			}
20268810c16bSdanmcd 		}
20278810c16bSdanmcd 	}
20288810c16bSdanmcd 
20298810c16bSdanmcd 	if (hard != NULL) {
2030bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2031510c3f91SVladimir Kotal 		    "%sHard lifetime information:\n"), hard_prefix);
2032bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2033510c3f91SVladimir Kotal 		    "%s%" PRIu64 " bytes %sof lifetime, %u allocations.\n"),
2034510c3f91SVladimir Kotal 		    hard_prefix,
2035510c3f91SVladimir Kotal 		    hard->sadb_lifetime_bytes,
2036510c3f91SVladimir Kotal 		    bytecnt2out(hard->sadb_lifetime_bytes, byte_str,
2037510c3f91SVladimir Kotal 		    sizeof (byte_str), SPC_END),
2038510c3f91SVladimir Kotal 		    hard->sadb_lifetime_allocations);
2039bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2040510c3f91SVladimir Kotal 		    "%s%" PRIu64 " seconds %sof post-add lifetime.\n"),
2041510c3f91SVladimir Kotal 		    hard_prefix, hard->sadb_lifetime_addtime,
2042510c3f91SVladimir Kotal 		    secs2out(hard->sadb_lifetime_addtime, secs_str,
2043510c3f91SVladimir Kotal 		    sizeof (secs_str), SPC_END));
2044bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2045510c3f91SVladimir Kotal 		    "%s%" PRIu64 " seconds %sof post-use lifetime.\n"),
2046510c3f91SVladimir Kotal 		    hard_prefix, hard->sadb_lifetime_usetime,
2047510c3f91SVladimir Kotal 		    secs2out(hard->sadb_lifetime_usetime, secs_str,
2048510c3f91SVladimir Kotal 		    sizeof (secs_str), SPC_END));
20498810c16bSdanmcd 		/* If possible, express values as time remaining. */
20508810c16bSdanmcd 		if (current != NULL) {
20518810c16bSdanmcd 			if (hard->sadb_lifetime_bytes != 0)
2052510c3f91SVladimir Kotal 				(void) fprintf(file, dgettext(TEXT_DOMAIN, "%s"
2053510c3f91SVladimir Kotal 				    "%" PRIu64 " bytes %smore can be "
2054510c3f91SVladimir Kotal 				    "protected.\n"), hard_prefix,
2055510c3f91SVladimir Kotal 				    (hard->sadb_lifetime_bytes >
2056510c3f91SVladimir Kotal 				    current->sadb_lifetime_bytes) ?
2057510c3f91SVladimir Kotal 				    hard->sadb_lifetime_bytes -
2058510c3f91SVladimir Kotal 				    current->sadb_lifetime_bytes : 0,
20598810c16bSdanmcd 				    (hard->sadb_lifetime_bytes >
206025e435e0Spwernau 				    current->sadb_lifetime_bytes) ?
2061510c3f91SVladimir Kotal 				    bytecnt2out(hard->sadb_lifetime_bytes -
2062510c3f91SVladimir Kotal 				    current->sadb_lifetime_bytes, byte_str,
2063510c3f91SVladimir Kotal 				    sizeof (byte_str), SPC_END) : "");
20648810c16bSdanmcd 			if (hard->sadb_lifetime_addtime != 0 ||
20658810c16bSdanmcd 			    (hard->sadb_lifetime_usetime != 0 &&
206625e435e0Spwernau 			    current->sadb_lifetime_usetime != 0)) {
20678810c16bSdanmcd 				int64_t adddelta, usedelta;
20688810c16bSdanmcd 
20698810c16bSdanmcd 				if (hard->sadb_lifetime_addtime != 0) {
20708810c16bSdanmcd 					adddelta =
20718810c16bSdanmcd 					    current->sadb_lifetime_addtime +
20728810c16bSdanmcd 					    hard->sadb_lifetime_addtime -
20738810c16bSdanmcd 					    wallclock;
20748810c16bSdanmcd 				} else {
20758810c16bSdanmcd 					adddelta = TIME_MAX;
20768810c16bSdanmcd 				}
20778810c16bSdanmcd 
20788810c16bSdanmcd 				if (hard->sadb_lifetime_usetime != 0 &&
20798810c16bSdanmcd 				    current->sadb_lifetime_usetime != 0) {
20808810c16bSdanmcd 					usedelta =
20818810c16bSdanmcd 					    current->sadb_lifetime_usetime +
20828810c16bSdanmcd 					    hard->sadb_lifetime_usetime -
20838810c16bSdanmcd 					    wallclock;
20848810c16bSdanmcd 				} else {
20858810c16bSdanmcd 					usedelta = TIME_MAX;
20868810c16bSdanmcd 				}
2087bb3ed8dfSpwernau 				(void) fprintf(file, "%s", hard_prefix);
20888810c16bSdanmcd 				scratch = MIN(adddelta, usedelta);
20898810c16bSdanmcd 				if (scratch >= 0) {
2090bb3ed8dfSpwernau 					(void) fprintf(file,
2091bb3ed8dfSpwernau 					    dgettext(TEXT_DOMAIN,
2092c51cb4bcSDan McDonald 					    "Hard expiration occurs in %"
2093510c3f91SVladimir Kotal 					    PRId64 " seconds%s\n"), scratch,
2094510c3f91SVladimir Kotal 					    secs2out(scratch, secs_str,
2095510c3f91SVladimir Kotal 					    sizeof (secs_str), SPC_BEGIN));
20968810c16bSdanmcd 				} else {
2097bb3ed8dfSpwernau 					(void) fprintf(file,
2098bb3ed8dfSpwernau 					    dgettext(TEXT_DOMAIN,
2099510c3f91SVladimir Kotal 					    "Hard expiration occurred\n"));
21008810c16bSdanmcd 				}
21018810c16bSdanmcd 				scratch += wallclock;
2102bb3ed8dfSpwernau 				printsatime(file, scratch, dgettext(TEXT_DOMAIN,
2103510c3f91SVladimir Kotal 				    "%sTime of expiration: %s.\n"),
2104510c3f91SVladimir Kotal 				    hard_prefix, hard_prefix, vflag);
21058810c16bSdanmcd 			}
21068810c16bSdanmcd 		}
21078810c16bSdanmcd 	}
21089c2c14abSThejaswini Singarajipura 	if (idle != NULL) {
21099c2c14abSThejaswini Singarajipura 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2110510c3f91SVladimir Kotal 		    "%sIdle lifetime information:\n"), idle_prefix);
21119c2c14abSThejaswini Singarajipura 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2112510c3f91SVladimir Kotal 		    "%s%" PRIu64 " seconds %sof post-add lifetime.\n"),
2113510c3f91SVladimir Kotal 		    idle_prefix, idle->sadb_lifetime_addtime,
2114510c3f91SVladimir Kotal 		    secs2out(idle->sadb_lifetime_addtime, secs_str,
2115510c3f91SVladimir Kotal 		    sizeof (secs_str), SPC_END));
21169c2c14abSThejaswini Singarajipura 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2117510c3f91SVladimir Kotal 		    "%s%" PRIu64 " seconds %sof post-use lifetime.\n"),
2118510c3f91SVladimir Kotal 		    idle_prefix, idle->sadb_lifetime_usetime,
2119510c3f91SVladimir Kotal 		    secs2out(idle->sadb_lifetime_usetime, secs_str,
2120510c3f91SVladimir Kotal 		    sizeof (secs_str), SPC_END));
21219c2c14abSThejaswini Singarajipura 	}
21228810c16bSdanmcd }
21238810c16bSdanmcd 
21248810c16bSdanmcd /*
21258810c16bSdanmcd  * Print an SADB_EXT_ADDRESS_* extension.
21268810c16bSdanmcd  */
21278810c16bSdanmcd void
print_address(FILE * file,char * prefix,struct sadb_address * addr,boolean_t ignore_nss)2128bb3ed8dfSpwernau print_address(FILE *file, char *prefix, struct sadb_address *addr,
2129bb3ed8dfSpwernau     boolean_t ignore_nss)
21308810c16bSdanmcd {
21318810c16bSdanmcd 	struct protoent *pe;
21328810c16bSdanmcd 
2133bb3ed8dfSpwernau 	(void) fprintf(file, "%s", prefix);
21348810c16bSdanmcd 	switch (addr->sadb_address_exttype) {
21358810c16bSdanmcd 	case SADB_EXT_ADDRESS_SRC:
2136bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "Source address "));
21378810c16bSdanmcd 		break;
21388810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_INNER_SRC:
2139bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2140bb3ed8dfSpwernau 		    "Inner source address "));
21418810c16bSdanmcd 		break;
21428810c16bSdanmcd 	case SADB_EXT_ADDRESS_DST:
2143bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2144bb3ed8dfSpwernau 		    "Destination address "));
21458810c16bSdanmcd 		break;
21468810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_INNER_DST:
2147bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2148a7485808Smarkfen 		    "Inner destination address "));
21498810c16bSdanmcd 		break;
21508810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_NATT_LOC:
2151bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2152bb3ed8dfSpwernau 		    "NAT-T local address "));
21538810c16bSdanmcd 		break;
21548810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_NATT_REM:
2155bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2156bb3ed8dfSpwernau 		    "NAT-T remote address "));
21578810c16bSdanmcd 		break;
21588810c16bSdanmcd 	}
21598810c16bSdanmcd 
2160bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
2161a7485808Smarkfen 	    "(proto=%d"), addr->sadb_address_proto);
2162bb3ed8dfSpwernau 	if (ignore_nss == B_FALSE) {
21638810c16bSdanmcd 		if (addr->sadb_address_proto == 0) {
2164bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2165bb3ed8dfSpwernau 			    "/<unspecified>"));
21668810c16bSdanmcd 		} else if ((pe = getprotobynumber(addr->sadb_address_proto))
21678810c16bSdanmcd 		    != NULL) {
2168bb3ed8dfSpwernau 			(void) fprintf(file, "/%s", pe->p_name);
21698810c16bSdanmcd 		} else {
2170bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2171bb3ed8dfSpwernau 			    "/<unknown>"));
21728810c16bSdanmcd 		}
21738810c16bSdanmcd 	}
2174bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN, ")\n%s"), prefix);
21758810c16bSdanmcd 	(void) dump_sockaddr((struct sockaddr *)(addr + 1),
2176bb3ed8dfSpwernau 	    addr->sadb_address_prefixlen, B_FALSE, file, ignore_nss);
21778810c16bSdanmcd }
21788810c16bSdanmcd 
21798810c16bSdanmcd /*
21808810c16bSdanmcd  * Print an SADB_EXT_KEY extension.
21818810c16bSdanmcd  */
21828810c16bSdanmcd void
print_key(FILE * file,char * prefix,struct sadb_key * key)2183bb3ed8dfSpwernau print_key(FILE *file, char *prefix, struct sadb_key *key)
21848810c16bSdanmcd {
2185bb3ed8dfSpwernau 	(void) fprintf(file, "%s", prefix);
21868810c16bSdanmcd 
21878810c16bSdanmcd 	switch (key->sadb_key_exttype) {
21888810c16bSdanmcd 	case SADB_EXT_KEY_AUTH:
2189bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "Authentication"));
21908810c16bSdanmcd 		break;
21918810c16bSdanmcd 	case SADB_EXT_KEY_ENCRYPT:
2192bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "Encryption"));
21938810c16bSdanmcd 		break;
21948810c16bSdanmcd 	}
21958810c16bSdanmcd 
2196bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN, " key.\n%s"), prefix);
2197628b0c67SMark Fenwick 	(void) dump_key((uint8_t *)(key + 1), key->sadb_key_bits,
2198628b0c67SMark Fenwick 	    key->sadb_key_reserved, file, B_TRUE);
2199bb3ed8dfSpwernau 	(void) fprintf(file, "\n");
22008810c16bSdanmcd }
22018810c16bSdanmcd 
22028810c16bSdanmcd /*
22038810c16bSdanmcd  * Print an SADB_EXT_IDENTITY_* extension.
22048810c16bSdanmcd  */
22058810c16bSdanmcd void
print_ident(FILE * file,char * prefix,struct sadb_ident * id)2206bb3ed8dfSpwernau print_ident(FILE *file, char *prefix, struct sadb_ident *id)
22078810c16bSdanmcd {
22088810c16bSdanmcd 	boolean_t canprint = B_TRUE;
22098810c16bSdanmcd 
2210bb3ed8dfSpwernau 	(void) fprintf(file, "%s", prefix);
22118810c16bSdanmcd 	switch (id->sadb_ident_exttype) {
22128810c16bSdanmcd 	case SADB_EXT_IDENTITY_SRC:
2213bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "Source"));
22148810c16bSdanmcd 		break;
22158810c16bSdanmcd 	case SADB_EXT_IDENTITY_DST:
2216bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "Destination"));
22178810c16bSdanmcd 		break;
22188810c16bSdanmcd 	}
22198810c16bSdanmcd 
2220bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
2221a7485808Smarkfen 	    " identity, uid=%d, type "), id->sadb_ident_id);
2222bb3ed8dfSpwernau 	canprint = dump_sadb_idtype(id->sadb_ident_type, file, NULL);
2223bb3ed8dfSpwernau 	(void) fprintf(file, "\n%s", prefix);
2224a12f8217Spwernau 	if (canprint) {
2225bb3ed8dfSpwernau 		(void) fprintf(file, "%s\n", (char *)(id + 1));
2226a12f8217Spwernau 	} else {
2227a12f8217Spwernau 		print_asn1_name(file, (const unsigned char *)(id + 1),
2228a12f8217Spwernau 		    SADB_64TO8(id->sadb_ident_len) - sizeof (sadb_ident_t));
2229a12f8217Spwernau 	}
22308810c16bSdanmcd }
22318810c16bSdanmcd 
22325d3b8cb7SBill Sommerfeld /*
22335d3b8cb7SBill Sommerfeld  * Convert sadb_sens extension into binary security label.
22345d3b8cb7SBill Sommerfeld  */
22355d3b8cb7SBill Sommerfeld 
22365d3b8cb7SBill Sommerfeld #include <tsol/label.h>
22375d3b8cb7SBill Sommerfeld #include <sys/tsol/tndb.h>
22385d3b8cb7SBill Sommerfeld #include <sys/tsol/label_macro.h>
22395d3b8cb7SBill Sommerfeld 
22405d3b8cb7SBill Sommerfeld void
ipsec_convert_sens_to_bslabel(const struct sadb_sens * sens,bslabel_t * sl)22415d3b8cb7SBill Sommerfeld ipsec_convert_sens_to_bslabel(const struct sadb_sens *sens, bslabel_t *sl)
22425d3b8cb7SBill Sommerfeld {
22435d3b8cb7SBill Sommerfeld 	uint64_t *bitmap = (uint64_t *)(sens + 1);
22445d3b8cb7SBill Sommerfeld 	int bitmap_len = SADB_64TO8(sens->sadb_sens_sens_len);
22455d3b8cb7SBill Sommerfeld 
22465d3b8cb7SBill Sommerfeld 	bsllow(sl);
22475d3b8cb7SBill Sommerfeld 	LCLASS_SET((_bslabel_impl_t *)sl, sens->sadb_sens_sens_level);
22485d3b8cb7SBill Sommerfeld 	bcopy(bitmap, &((_bslabel_impl_t *)sl)->compartments,
22495d3b8cb7SBill Sommerfeld 	    bitmap_len);
22505d3b8cb7SBill Sommerfeld }
22515d3b8cb7SBill Sommerfeld 
22525d3b8cb7SBill Sommerfeld void
ipsec_convert_bslabel_to_string(bslabel_t * sl,char ** plabel)22535d3b8cb7SBill Sommerfeld ipsec_convert_bslabel_to_string(bslabel_t *sl, char **plabel)
22545d3b8cb7SBill Sommerfeld {
22555d3b8cb7SBill Sommerfeld 	if (label_to_str(sl, plabel, M_LABEL, DEF_NAMES) != 0) {
22565d3b8cb7SBill Sommerfeld 		*plabel = strdup(dgettext(TEXT_DOMAIN,
22575d3b8cb7SBill Sommerfeld 		    "** Label conversion failed **"));
22585d3b8cb7SBill Sommerfeld 	}
22595d3b8cb7SBill Sommerfeld }
22605d3b8cb7SBill Sommerfeld 
22615d3b8cb7SBill Sommerfeld void
ipsec_convert_bslabel_to_hex(bslabel_t * sl,char ** plabel)22625d3b8cb7SBill Sommerfeld ipsec_convert_bslabel_to_hex(bslabel_t *sl, char **plabel)
22635d3b8cb7SBill Sommerfeld {
22645d3b8cb7SBill Sommerfeld 	if (label_to_str(sl, plabel, M_INTERNAL, DEF_NAMES) != 0) {
22655d3b8cb7SBill Sommerfeld 		*plabel = strdup(dgettext(TEXT_DOMAIN,
22665d3b8cb7SBill Sommerfeld 		    "** Label conversion failed **"));
22675d3b8cb7SBill Sommerfeld 	}
22685d3b8cb7SBill Sommerfeld }
22695d3b8cb7SBill Sommerfeld 
22705d3b8cb7SBill Sommerfeld int
ipsec_convert_sl_to_sens(int doi,bslabel_t * sl,sadb_sens_t * sens)22715d3b8cb7SBill Sommerfeld ipsec_convert_sl_to_sens(int doi, bslabel_t *sl, sadb_sens_t *sens)
22725d3b8cb7SBill Sommerfeld {
22735d3b8cb7SBill Sommerfeld 	uint8_t *bitmap;
22745d3b8cb7SBill Sommerfeld 	int sens_len = sizeof (sadb_sens_t) + _C_LEN * 4;
22755d3b8cb7SBill Sommerfeld 
22765d3b8cb7SBill Sommerfeld 
22775d3b8cb7SBill Sommerfeld 	if (sens == NULL)
22785d3b8cb7SBill Sommerfeld 		return (sens_len);
22795d3b8cb7SBill Sommerfeld 
22805d3b8cb7SBill Sommerfeld 
22815d3b8cb7SBill Sommerfeld 	(void) memset(sens, 0, sens_len);
22825d3b8cb7SBill Sommerfeld 
22835d3b8cb7SBill Sommerfeld 	sens->sadb_sens_exttype = SADB_EXT_SENSITIVITY;
22845d3b8cb7SBill Sommerfeld 	sens->sadb_sens_len = SADB_8TO64(sens_len);
22855d3b8cb7SBill Sommerfeld 	sens->sadb_sens_dpd = doi;
22865d3b8cb7SBill Sommerfeld 
22875d3b8cb7SBill Sommerfeld 	sens->sadb_sens_sens_level = LCLASS(sl);
22885d3b8cb7SBill Sommerfeld 	sens->sadb_sens_integ_level = 0;
22895d3b8cb7SBill Sommerfeld 	sens->sadb_sens_sens_len = _C_LEN >> 1;
22905d3b8cb7SBill Sommerfeld 	sens->sadb_sens_integ_len = 0;
22915d3b8cb7SBill Sommerfeld 
22925d3b8cb7SBill Sommerfeld 	sens->sadb_x_sens_flags = 0;
22935d3b8cb7SBill Sommerfeld 
22945d3b8cb7SBill Sommerfeld 	bitmap = (uint8_t *)(sens + 1);
22955d3b8cb7SBill Sommerfeld 	bcopy(&(((_bslabel_impl_t *)sl)->compartments), bitmap, _C_LEN * 4);
22965d3b8cb7SBill Sommerfeld 
22975d3b8cb7SBill Sommerfeld 	return (sens_len);
22985d3b8cb7SBill Sommerfeld }
22995d3b8cb7SBill Sommerfeld 
23005d3b8cb7SBill Sommerfeld 
23018810c16bSdanmcd /*
23028810c16bSdanmcd  * Print an SADB_SENSITIVITY extension.
23038810c16bSdanmcd  */
23048810c16bSdanmcd void
print_sens(FILE * file,char * prefix,const struct sadb_sens * sens,boolean_t ignore_nss)23055d3b8cb7SBill Sommerfeld print_sens(FILE *file, char *prefix, const struct sadb_sens *sens,
230680ad54c9SToomas Soome     boolean_t ignore_nss)
23078810c16bSdanmcd {
23085d3b8cb7SBill Sommerfeld 	char *plabel;
23095d3b8cb7SBill Sommerfeld 	char *hlabel;
23108810c16bSdanmcd 	uint64_t *bitmap = (uint64_t *)(sens + 1);
23115d3b8cb7SBill Sommerfeld 	bslabel_t sl;
23128810c16bSdanmcd 	int i;
23135d3b8cb7SBill Sommerfeld 	int sens_len = sens->sadb_sens_sens_len;
23145d3b8cb7SBill Sommerfeld 	int integ_len = sens->sadb_sens_integ_len;
23155d3b8cb7SBill Sommerfeld 	boolean_t inner = (sens->sadb_sens_exttype == SADB_EXT_SENSITIVITY);
23165d3b8cb7SBill Sommerfeld 	const char *sensname = inner ?
23175d3b8cb7SBill Sommerfeld 	    dgettext(TEXT_DOMAIN, "Plaintext Sensitivity") :
23185d3b8cb7SBill Sommerfeld 	    dgettext(TEXT_DOMAIN, "Ciphertext Sensitivity");
23195d3b8cb7SBill Sommerfeld 
23205d3b8cb7SBill Sommerfeld 	ipsec_convert_sens_to_bslabel(sens, &sl);
23218810c16bSdanmcd 
2322bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
23235d3b8cb7SBill Sommerfeld 	    "%s%s DPD %d, sens level=%d, integ level=%d, flags=%x\n"),
23245d3b8cb7SBill Sommerfeld 	    prefix, sensname, sens->sadb_sens_dpd, sens->sadb_sens_sens_level,
23255d3b8cb7SBill Sommerfeld 	    sens->sadb_sens_integ_level, sens->sadb_x_sens_flags);
23265d3b8cb7SBill Sommerfeld 
23275d3b8cb7SBill Sommerfeld 	ipsec_convert_bslabel_to_hex(&sl, &hlabel);
23285d3b8cb7SBill Sommerfeld 
23295d3b8cb7SBill Sommerfeld 	if (ignore_nss) {
23305d3b8cb7SBill Sommerfeld 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
23315d3b8cb7SBill Sommerfeld 		    "%s %s Label: %s\n"), prefix, sensname, hlabel);
23325d3b8cb7SBill Sommerfeld 
23335d3b8cb7SBill Sommerfeld 		for (i = 0; i < sens_len; i++, bitmap++)
23345d3b8cb7SBill Sommerfeld 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
23355d3b8cb7SBill Sommerfeld 			    "%s %s BM extended word %d 0x%" PRIx64 "\n"),
23365d3b8cb7SBill Sommerfeld 			    prefix, sensname, i, *bitmap);
23375d3b8cb7SBill Sommerfeld 
23385d3b8cb7SBill Sommerfeld 	} else {
23395d3b8cb7SBill Sommerfeld 		ipsec_convert_bslabel_to_string(&sl, &plabel);
23405d3b8cb7SBill Sommerfeld 
23415d3b8cb7SBill Sommerfeld 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
23425d3b8cb7SBill Sommerfeld 		    "%s %s Label: %s (%s)\n"),
23435d3b8cb7SBill Sommerfeld 		    prefix, sensname, plabel, hlabel);
23445d3b8cb7SBill Sommerfeld 		free(plabel);
23455d3b8cb7SBill Sommerfeld 
23465d3b8cb7SBill Sommerfeld 	}
23475d3b8cb7SBill Sommerfeld 	free(hlabel);
23485d3b8cb7SBill Sommerfeld 
23495d3b8cb7SBill Sommerfeld 	bitmap = (uint64_t *)(sens + 1 + sens_len);
23505d3b8cb7SBill Sommerfeld 
23515d3b8cb7SBill Sommerfeld 	for (i = 0; i < integ_len; i++, bitmap++)
2352bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2353c51cb4bcSDan McDonald 		    "%s Integrity BM extended word %d 0x%" PRIx64 "\n"),
2354bb3ed8dfSpwernau 		    prefix, i, *bitmap);
23558810c16bSdanmcd }
23568810c16bSdanmcd 
23578810c16bSdanmcd /*
23588810c16bSdanmcd  * Print an SADB_EXT_PROPOSAL extension.
23598810c16bSdanmcd  */
23608810c16bSdanmcd void
print_prop(FILE * file,char * prefix,struct sadb_prop * prop)2361bb3ed8dfSpwernau print_prop(FILE *file, char *prefix, struct sadb_prop *prop)
23628810c16bSdanmcd {
23638810c16bSdanmcd 	struct sadb_comb *combs;
23648810c16bSdanmcd 	int i, numcombs;
23658810c16bSdanmcd 
2366bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
2367a7485808Smarkfen 	    "%sProposal, replay counter = %u.\n"), prefix,
23688810c16bSdanmcd 	    prop->sadb_prop_replay);
23698810c16bSdanmcd 
23708810c16bSdanmcd 	numcombs = prop->sadb_prop_len - SADB_8TO64(sizeof (*prop));
23718810c16bSdanmcd 	numcombs /= SADB_8TO64(sizeof (*combs));
23728810c16bSdanmcd 
23738810c16bSdanmcd 	combs = (struct sadb_comb *)(prop + 1);
23748810c16bSdanmcd 
23758810c16bSdanmcd 	for (i = 0; i < numcombs; i++) {
2376bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2377a7485808Smarkfen 		    "%s Combination #%u "), prefix, i + 1);
23788810c16bSdanmcd 		if (combs[i].sadb_comb_auth != SADB_AALG_NONE) {
2379bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2380a7485808Smarkfen 			    "Authentication = "));
2381bb3ed8dfSpwernau 			(void) dump_aalg(combs[i].sadb_comb_auth, file);
2382bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2383a7485808Smarkfen 			    "  minbits=%u, maxbits=%u.\n%s "),
23848810c16bSdanmcd 			    combs[i].sadb_comb_auth_minbits,
23858810c16bSdanmcd 			    combs[i].sadb_comb_auth_maxbits, prefix);
23868810c16bSdanmcd 		}
23878810c16bSdanmcd 
23888810c16bSdanmcd 		if (combs[i].sadb_comb_encrypt != SADB_EALG_NONE) {
2389bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2390bb3ed8dfSpwernau 			    "Encryption = "));
2391bb3ed8dfSpwernau 			(void) dump_ealg(combs[i].sadb_comb_encrypt, file);
2392bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2393351128adSJason King 			    "  minbits=%u, maxbits=%u, saltbits=%u.\n%s "),
23948810c16bSdanmcd 			    combs[i].sadb_comb_encrypt_minbits,
2395351128adSJason King 			    combs[i].sadb_comb_encrypt_maxbits,
2396351128adSJason King 			    combs[i].sadb_x_comb_encrypt_saltbits, prefix);
23978810c16bSdanmcd 		}
23988810c16bSdanmcd 
2399bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "HARD: "));
24008810c16bSdanmcd 		if (combs[i].sadb_comb_hard_allocations)
2401bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN, "alloc=%u "),
24028810c16bSdanmcd 			    combs[i].sadb_comb_hard_allocations);
24038810c16bSdanmcd 		if (combs[i].sadb_comb_hard_bytes)
2404c51cb4bcSDan McDonald 			(void) fprintf(file, dgettext(TEXT_DOMAIN, "bytes=%"
2405c51cb4bcSDan McDonald 			    PRIu64 " "), combs[i].sadb_comb_hard_bytes);
24068810c16bSdanmcd 		if (combs[i].sadb_comb_hard_addtime)
2407bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2408c51cb4bcSDan McDonald 			    "post-add secs=%" PRIu64 " "),
24098810c16bSdanmcd 			    combs[i].sadb_comb_hard_addtime);
24108810c16bSdanmcd 		if (combs[i].sadb_comb_hard_usetime)
2411bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2412c51cb4bcSDan McDonald 			    "post-use secs=%" PRIu64 ""),
24138810c16bSdanmcd 			    combs[i].sadb_comb_hard_usetime);
24148810c16bSdanmcd 
2415bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "\n%s SOFT: "),
2416bb3ed8dfSpwernau 		    prefix);
24178810c16bSdanmcd 		if (combs[i].sadb_comb_soft_allocations)
2418bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN, "alloc=%u "),
24198810c16bSdanmcd 			    combs[i].sadb_comb_soft_allocations);
24208810c16bSdanmcd 		if (combs[i].sadb_comb_soft_bytes)
2421c51cb4bcSDan McDonald 			(void) fprintf(file, dgettext(TEXT_DOMAIN, "bytes=%"
2422c51cb4bcSDan McDonald 			    PRIu64 " "), combs[i].sadb_comb_soft_bytes);
24238810c16bSdanmcd 		if (combs[i].sadb_comb_soft_addtime)
2424bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2425c51cb4bcSDan McDonald 			    "post-add secs=%" PRIu64 " "),
24268810c16bSdanmcd 			    combs[i].sadb_comb_soft_addtime);
24278810c16bSdanmcd 		if (combs[i].sadb_comb_soft_usetime)
2428bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2429c51cb4bcSDan McDonald 			    "post-use secs=%" PRIu64 ""),
24308810c16bSdanmcd 			    combs[i].sadb_comb_soft_usetime);
2431bb3ed8dfSpwernau 		(void) fprintf(file, "\n");
24328810c16bSdanmcd 	}
24338810c16bSdanmcd }
24348810c16bSdanmcd 
24358810c16bSdanmcd /*
24368810c16bSdanmcd  * Print an extended proposal (SADB_X_EXT_EPROP).
24378810c16bSdanmcd  */
24388810c16bSdanmcd void
print_eprop(FILE * file,char * prefix,struct sadb_prop * eprop)2439bb3ed8dfSpwernau print_eprop(FILE *file, char *prefix, struct sadb_prop *eprop)
24408810c16bSdanmcd {
24418810c16bSdanmcd 	uint64_t *sofar;
24428810c16bSdanmcd 	struct sadb_x_ecomb *ecomb;
24438810c16bSdanmcd 	struct sadb_x_algdesc *algdesc;
24448810c16bSdanmcd 	int i, j;
24458810c16bSdanmcd 
2446bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
2447a7485808Smarkfen 	    "%sExtended Proposal, replay counter = %u, "), prefix,
2448a7485808Smarkfen 	    eprop->sadb_prop_replay);
2449bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
2450bb3ed8dfSpwernau 	    "number of combinations = %u.\n"), eprop->sadb_x_prop_numecombs);
24518810c16bSdanmcd 
24528810c16bSdanmcd 	sofar = (uint64_t *)(eprop + 1);
24538810c16bSdanmcd 	ecomb = (struct sadb_x_ecomb *)sofar;
24548810c16bSdanmcd 
24558810c16bSdanmcd 	for (i = 0; i < eprop->sadb_x_prop_numecombs; ) {
2456bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2457a7485808Smarkfen 		    "%s Extended combination #%u:\n"), prefix, ++i);
24588810c16bSdanmcd 
2459bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "%s HARD: "),
2460bb3ed8dfSpwernau 		    prefix);
2461bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "alloc=%u, "),
24628810c16bSdanmcd 		    ecomb->sadb_x_ecomb_hard_allocations);
2463c51cb4bcSDan McDonald 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "bytes=%" PRIu64
2464c51cb4bcSDan McDonald 		    ", "), ecomb->sadb_x_ecomb_hard_bytes);
2465c51cb4bcSDan McDonald 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "post-add secs=%"
2466c51cb4bcSDan McDonald 		    PRIu64 ", "), ecomb->sadb_x_ecomb_hard_addtime);
2467c51cb4bcSDan McDonald 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "post-use secs=%"
2468c51cb4bcSDan McDonald 		    PRIu64 "\n"), ecomb->sadb_x_ecomb_hard_usetime);
24698810c16bSdanmcd 
2470bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "%s SOFT: "),
2471bb3ed8dfSpwernau 		    prefix);
2472bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "alloc=%u, "),
24738810c16bSdanmcd 		    ecomb->sadb_x_ecomb_soft_allocations);
2474bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2475c51cb4bcSDan McDonald 		    "bytes=%" PRIu64 ", "), ecomb->sadb_x_ecomb_soft_bytes);
2476bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2477c51cb4bcSDan McDonald 		    "post-add secs=%" PRIu64 ", "),
2478c51cb4bcSDan McDonald 		    ecomb->sadb_x_ecomb_soft_addtime);
2479c51cb4bcSDan McDonald 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "post-use secs=%"
2480c51cb4bcSDan McDonald 		    PRIu64 "\n"), ecomb->sadb_x_ecomb_soft_usetime);
24818810c16bSdanmcd 
24828810c16bSdanmcd 		sofar = (uint64_t *)(ecomb + 1);
24838810c16bSdanmcd 		algdesc = (struct sadb_x_algdesc *)sofar;
24848810c16bSdanmcd 
24858810c16bSdanmcd 		for (j = 0; j < ecomb->sadb_x_ecomb_numalgs; ) {
2486bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2487a7485808Smarkfen 			    "%s Alg #%u "), prefix, ++j);
24888810c16bSdanmcd 			switch (algdesc->sadb_x_algdesc_satype) {
24898810c16bSdanmcd 			case SADB_SATYPE_ESP:
2490bb3ed8dfSpwernau 				(void) fprintf(file, dgettext(TEXT_DOMAIN,
2491a7485808Smarkfen 				    "for ESP "));
24928810c16bSdanmcd 				break;
24938810c16bSdanmcd 			case SADB_SATYPE_AH:
2494bb3ed8dfSpwernau 				(void) fprintf(file, dgettext(TEXT_DOMAIN,
2495bb3ed8dfSpwernau 				    "for AH "));
24968810c16bSdanmcd 				break;
24978810c16bSdanmcd 			default:
2498bb3ed8dfSpwernau 				(void) fprintf(file, dgettext(TEXT_DOMAIN,
2499a7485808Smarkfen 				    "for satype=%d "),
25008810c16bSdanmcd 				    algdesc->sadb_x_algdesc_satype);
25018810c16bSdanmcd 			}
25028810c16bSdanmcd 			switch (algdesc->sadb_x_algdesc_algtype) {
25038810c16bSdanmcd 			case SADB_X_ALGTYPE_CRYPT:
2504bb3ed8dfSpwernau 				(void) fprintf(file, dgettext(TEXT_DOMAIN,
2505a7485808Smarkfen 				    "Encryption = "));
25068810c16bSdanmcd 				(void) dump_ealg(algdesc->sadb_x_algdesc_alg,
2507bb3ed8dfSpwernau 				    file);
25088810c16bSdanmcd 				break;
25098810c16bSdanmcd 			case SADB_X_ALGTYPE_AUTH:
2510bb3ed8dfSpwernau 				(void) fprintf(file, dgettext(TEXT_DOMAIN,
2511a7485808Smarkfen 				    "Authentication = "));
25128810c16bSdanmcd 				(void) dump_aalg(algdesc->sadb_x_algdesc_alg,
2513bb3ed8dfSpwernau 				    file);
25148810c16bSdanmcd 				break;
25158810c16bSdanmcd 			default:
2516bb3ed8dfSpwernau 				(void) fprintf(file, dgettext(TEXT_DOMAIN,
2517a7485808Smarkfen 				    "algtype(%d) = alg(%d)"),
25188810c16bSdanmcd 				    algdesc->sadb_x_algdesc_algtype,
25198810c16bSdanmcd 				    algdesc->sadb_x_algdesc_alg);
25208810c16bSdanmcd 				break;
25218810c16bSdanmcd 			}
25228810c16bSdanmcd 
2523bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2524628b0c67SMark Fenwick 			    "  minbits=%u, maxbits=%u, saltbits=%u\n"),
25258810c16bSdanmcd 			    algdesc->sadb_x_algdesc_minbits,
2526628b0c67SMark Fenwick 			    algdesc->sadb_x_algdesc_maxbits,
2527351128adSJason King 			    algdesc->sadb_x_algdesc_saltbits);
25288810c16bSdanmcd 
25298810c16bSdanmcd 			sofar = (uint64_t *)(++algdesc);
25308810c16bSdanmcd 		}
25318810c16bSdanmcd 		ecomb = (struct sadb_x_ecomb *)sofar;
25328810c16bSdanmcd 	}
25338810c16bSdanmcd }
25348810c16bSdanmcd 
25358810c16bSdanmcd /*
25368810c16bSdanmcd  * Print an SADB_EXT_SUPPORTED extension.
25378810c16bSdanmcd  */
25388810c16bSdanmcd void
print_supp(FILE * file,char * prefix,struct sadb_supported * supp)2539bb3ed8dfSpwernau print_supp(FILE *file, char *prefix, struct sadb_supported *supp)
25408810c16bSdanmcd {
25418810c16bSdanmcd 	struct sadb_alg *algs;
25428810c16bSdanmcd 	int i, numalgs;
25438810c16bSdanmcd 
2544bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN, "%sSupported "), prefix);
25458810c16bSdanmcd 	switch (supp->sadb_supported_exttype) {
25468810c16bSdanmcd 	case SADB_EXT_SUPPORTED_AUTH:
2547bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "authentication"));
25488810c16bSdanmcd 		break;
25498810c16bSdanmcd 	case SADB_EXT_SUPPORTED_ENCRYPT:
2550bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "encryption"));
25518810c16bSdanmcd 		break;
25528810c16bSdanmcd 	}
2553bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN, " algorithms.\n"));
25548810c16bSdanmcd 
25558810c16bSdanmcd 	algs = (struct sadb_alg *)(supp + 1);
25568810c16bSdanmcd 	numalgs = supp->sadb_supported_len - SADB_8TO64(sizeof (*supp));
25578810c16bSdanmcd 	numalgs /= SADB_8TO64(sizeof (*algs));
25588810c16bSdanmcd 	for (i = 0; i < numalgs; i++) {
2559e70cf235Svk 		uint16_t exttype = supp->sadb_supported_exttype;
2560e70cf235Svk 
2561bb3ed8dfSpwernau 		(void) fprintf(file, "%s", prefix);
2562e70cf235Svk 		switch (exttype) {
25638810c16bSdanmcd 		case SADB_EXT_SUPPORTED_AUTH:
2564bb3ed8dfSpwernau 			(void) dump_aalg(algs[i].sadb_alg_id, file);
25658810c16bSdanmcd 			break;
25668810c16bSdanmcd 		case SADB_EXT_SUPPORTED_ENCRYPT:
2567bb3ed8dfSpwernau 			(void) dump_ealg(algs[i].sadb_alg_id, file);
25688810c16bSdanmcd 			break;
25698810c16bSdanmcd 		}
2570bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2571628b0c67SMark Fenwick 		    " minbits=%u, maxbits=%u, ivlen=%u, saltbits=%u"),
25728810c16bSdanmcd 		    algs[i].sadb_alg_minbits, algs[i].sadb_alg_maxbits,
2573628b0c67SMark Fenwick 		    algs[i].sadb_alg_ivlen, algs[i].sadb_x_alg_saltbits);
2574e70cf235Svk 		if (exttype == SADB_EXT_SUPPORTED_ENCRYPT)
2575e70cf235Svk 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2576e70cf235Svk 			    ", increment=%u"), algs[i].sadb_x_alg_increment);
2577e70cf235Svk 		(void) fprintf(file, dgettext(TEXT_DOMAIN, ".\n"));
25788810c16bSdanmcd 	}
25798810c16bSdanmcd }
25808810c16bSdanmcd 
25818810c16bSdanmcd /*
25828810c16bSdanmcd  * Print an SADB_EXT_SPIRANGE extension.
25838810c16bSdanmcd  */
25848810c16bSdanmcd void
print_spirange(FILE * file,char * prefix,struct sadb_spirange * range)2585bb3ed8dfSpwernau print_spirange(FILE *file, char *prefix, struct sadb_spirange *range)
25868810c16bSdanmcd {
2587bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
2588a7485808Smarkfen 	    "%sSPI Range, min=0x%x, max=0x%x\n"), prefix,
25898810c16bSdanmcd 	    htonl(range->sadb_spirange_min),
25908810c16bSdanmcd 	    htonl(range->sadb_spirange_max));
25918810c16bSdanmcd }
25928810c16bSdanmcd 
25938810c16bSdanmcd /*
25948810c16bSdanmcd  * Print an SADB_X_EXT_KM_COOKIE extension.
25958810c16bSdanmcd  */
25968810c16bSdanmcd 
25978810c16bSdanmcd void
print_kmc(FILE * file,char * prefix,struct sadb_x_kmc * kmc)2598bb3ed8dfSpwernau print_kmc(FILE *file, char *prefix, struct sadb_x_kmc *kmc)
25998810c16bSdanmcd {
26008810c16bSdanmcd 	char *cookie_label;
26018810c16bSdanmcd 
2602f4a6f97eSDan McDonald 	switch (kmc->sadb_x_kmc_proto) {
2603f4a6f97eSDan McDonald 	case SADB_X_KMP_IKE:
2604f4a6f97eSDan McDonald 		cookie_label = kmc_lookup_by_cookie(kmc->sadb_x_kmc_cookie);
2605f4a6f97eSDan McDonald 		if (cookie_label == NULL)
2606f4a6f97eSDan McDonald 			cookie_label =
2607f4a6f97eSDan McDonald 			    dgettext(TEXT_DOMAIN, "<Label not found.>");
2608f4a6f97eSDan McDonald 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2609cbc1abb4SDan McDonald 		    "%s Protocol %u, cookie=\"%s\" (%u)\n"), prefix,
2610f4a6f97eSDan McDonald 		    kmc->sadb_x_kmc_proto, cookie_label,
2611f4a6f97eSDan McDonald 		    kmc->sadb_x_kmc_cookie);
2612f4a6f97eSDan McDonald 		return;
2613cbc1abb4SDan McDonald 	case SADB_X_KMP_KINK:
2614cbc1abb4SDan McDonald 		cookie_label = dgettext(TEXT_DOMAIN, "KINK:");
2615cbc1abb4SDan McDonald 		break;
2616f4a6f97eSDan McDonald 	case SADB_X_KMP_MANUAL:
2617cbc1abb4SDan McDonald 		cookie_label = dgettext(TEXT_DOMAIN, "Manual SA with cookie:");
2618f4a6f97eSDan McDonald 		break;
26194c5582efSJason King 	case SADB_X_KMP_IKEV2:
26204c5582efSJason King 		cookie_label = dgettext(TEXT_DOMAIN, "IKEV2:");
26214c5582efSJason King 		break;
2622f4a6f97eSDan McDonald 	default:
2623f4a6f97eSDan McDonald 		cookie_label =
2624f4a6f97eSDan McDonald 		    dgettext(TEXT_DOMAIN, "<unknown KM protocol>");
2625f4a6f97eSDan McDonald 		break;
2626f4a6f97eSDan McDonald 	}
26278810c16bSdanmcd 
2628cbc1abb4SDan McDonald 	/*
2629cbc1abb4SDan McDonald 	 * Assume native-byte-order printing for now.  Exceptions (like
2630cbc1abb4SDan McDonald 	 * byte-swapping) should be handled in per-KM-protocol cases above.
2631cbc1abb4SDan McDonald 	 */
2632bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
2633cbc1abb4SDan McDonald 	    "%s Protocol %u, cookie=\"%s\" (0x%"PRIx64"/%"PRIu64")\n"),
2634f4a6f97eSDan McDonald 	    prefix, kmc->sadb_x_kmc_proto, cookie_label,
2635f4a6f97eSDan McDonald 	    kmc->sadb_x_kmc_cookie64, kmc->sadb_x_kmc_cookie64);
26368810c16bSdanmcd }
26379c2c14abSThejaswini Singarajipura 
26389c2c14abSThejaswini Singarajipura /*
26399c2c14abSThejaswini Singarajipura  * Print an SADB_X_EXT_REPLAY_CTR extension.
26409c2c14abSThejaswini Singarajipura  */
26419c2c14abSThejaswini Singarajipura 
26429c2c14abSThejaswini Singarajipura void
print_replay(FILE * file,char * prefix,sadb_x_replay_ctr_t * repl)26439c2c14abSThejaswini Singarajipura print_replay(FILE *file, char *prefix, sadb_x_replay_ctr_t *repl)
26449c2c14abSThejaswini Singarajipura {
26459c2c14abSThejaswini Singarajipura 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
26469c2c14abSThejaswini Singarajipura 	    "%sReplay Value "), prefix);
26479c2c14abSThejaswini Singarajipura 	if ((repl->sadb_x_rc_replay32 == 0) &&
26489c2c14abSThejaswini Singarajipura 	    (repl->sadb_x_rc_replay64 == 0)) {
26499c2c14abSThejaswini Singarajipura 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
26509c2c14abSThejaswini Singarajipura 		    "<Value not found.>"));
26519c2c14abSThejaswini Singarajipura 	}
26529c2c14abSThejaswini Singarajipura 	/*
26539c2c14abSThejaswini Singarajipura 	 * We currently do not support a 64-bit replay value.
26549c2c14abSThejaswini Singarajipura 	 * RFC 4301 will require one, however, and we have a field
26559c2c14abSThejaswini Singarajipura 	 * in place when 4301 is built.
26569c2c14abSThejaswini Singarajipura 	 */
26579c2c14abSThejaswini Singarajipura 	(void) fprintf(file, "% " PRIu64 "\n",
26589c2c14abSThejaswini Singarajipura 	    ((repl->sadb_x_rc_replay32 == 0) ?
26599c2c14abSThejaswini Singarajipura 	    repl->sadb_x_rc_replay64 : repl->sadb_x_rc_replay32));
26609c2c14abSThejaswini Singarajipura }
266138d95a78Smarkfen /*
266238d95a78Smarkfen  * Print an SADB_X_EXT_PAIR extension.
266338d95a78Smarkfen  */
266438d95a78Smarkfen static void
print_pair(FILE * file,char * prefix,struct sadb_x_pair * pair)266538d95a78Smarkfen print_pair(FILE *file, char *prefix, struct sadb_x_pair *pair)
266638d95a78Smarkfen {
266738d95a78Smarkfen 	(void) fprintf(file, dgettext(TEXT_DOMAIN, "%sPaired with spi=0x%x\n"),
266838d95a78Smarkfen 	    prefix, ntohl(pair->sadb_x_pair_spi));
266938d95a78Smarkfen }
26708810c16bSdanmcd 
26718810c16bSdanmcd /*
26728810c16bSdanmcd  * Take a PF_KEY message pointed to buffer and print it.  Useful for DUMP
26738810c16bSdanmcd  * and GET.
26748810c16bSdanmcd  */
26758810c16bSdanmcd void
print_samsg(FILE * file,uint64_t * buffer,boolean_t want_timestamp,boolean_t vflag,boolean_t ignore_nss)2676bb3ed8dfSpwernau print_samsg(FILE *file, uint64_t *buffer, boolean_t want_timestamp,
2677bb3ed8dfSpwernau     boolean_t vflag, boolean_t ignore_nss)
26788810c16bSdanmcd {
26798810c16bSdanmcd 	uint64_t *current;
26808810c16bSdanmcd 	struct sadb_msg *samsg = (struct sadb_msg *)buffer;
26818810c16bSdanmcd 	struct sadb_ext *ext;
26828810c16bSdanmcd 	struct sadb_lifetime *currentlt = NULL, *hardlt = NULL, *softlt = NULL;
26839c2c14abSThejaswini Singarajipura 	struct sadb_lifetime *idlelt = NULL;
26848810c16bSdanmcd 	int i;
26858810c16bSdanmcd 	time_t wallclock;
26868810c16bSdanmcd 
26878810c16bSdanmcd 	(void) time(&wallclock);
26888810c16bSdanmcd 
2689bb3ed8dfSpwernau 	print_sadb_msg(file, samsg, want_timestamp ? wallclock : 0, vflag);
26908810c16bSdanmcd 	current = (uint64_t *)(samsg + 1);
26918810c16bSdanmcd 	while (current - buffer < samsg->sadb_msg_len) {
26928810c16bSdanmcd 		int lenbytes;
26938810c16bSdanmcd 
26948810c16bSdanmcd 		ext = (struct sadb_ext *)current;
26958810c16bSdanmcd 		lenbytes = SADB_64TO8(ext->sadb_ext_len);
26968810c16bSdanmcd 		switch (ext->sadb_ext_type) {
26978810c16bSdanmcd 		case SADB_EXT_SA:
2698bb3ed8dfSpwernau 			print_sa(file, dgettext(TEXT_DOMAIN,
2699a7485808Smarkfen 			    "SA: "), (struct sadb_sa *)current);
27008810c16bSdanmcd 			break;
27018810c16bSdanmcd 		/*
27028810c16bSdanmcd 		 * Pluck out lifetimes and print them at the end.  This is
27038810c16bSdanmcd 		 * to show relative lifetimes.
27048810c16bSdanmcd 		 */
27058810c16bSdanmcd 		case SADB_EXT_LIFETIME_CURRENT:
27068810c16bSdanmcd 			currentlt = (struct sadb_lifetime *)current;
27078810c16bSdanmcd 			break;
27088810c16bSdanmcd 		case SADB_EXT_LIFETIME_HARD:
27098810c16bSdanmcd 			hardlt = (struct sadb_lifetime *)current;
27108810c16bSdanmcd 			break;
27118810c16bSdanmcd 		case SADB_EXT_LIFETIME_SOFT:
27128810c16bSdanmcd 			softlt = (struct sadb_lifetime *)current;
27138810c16bSdanmcd 			break;
27149c2c14abSThejaswini Singarajipura 		case SADB_X_EXT_LIFETIME_IDLE:
27159c2c14abSThejaswini Singarajipura 			idlelt = (struct sadb_lifetime *)current;
27169c2c14abSThejaswini Singarajipura 			break;
27178810c16bSdanmcd 
27188810c16bSdanmcd 		case SADB_EXT_ADDRESS_SRC:
2719bb3ed8dfSpwernau 			print_address(file, dgettext(TEXT_DOMAIN, "SRC: "),
2720bb3ed8dfSpwernau 			    (struct sadb_address *)current, ignore_nss);
27218810c16bSdanmcd 			break;
27228810c16bSdanmcd 		case SADB_X_EXT_ADDRESS_INNER_SRC:
2723bb3ed8dfSpwernau 			print_address(file, dgettext(TEXT_DOMAIN, "INS: "),
2724bb3ed8dfSpwernau 			    (struct sadb_address *)current, ignore_nss);
27258810c16bSdanmcd 			break;
27268810c16bSdanmcd 		case SADB_EXT_ADDRESS_DST:
2727bb3ed8dfSpwernau 			print_address(file, dgettext(TEXT_DOMAIN, "DST: "),
2728bb3ed8dfSpwernau 			    (struct sadb_address *)current, ignore_nss);
27298810c16bSdanmcd 			break;
27308810c16bSdanmcd 		case SADB_X_EXT_ADDRESS_INNER_DST:
2731bb3ed8dfSpwernau 			print_address(file, dgettext(TEXT_DOMAIN, "IND: "),
2732bb3ed8dfSpwernau 			    (struct sadb_address *)current, ignore_nss);
27338810c16bSdanmcd 			break;
27348810c16bSdanmcd 		case SADB_EXT_KEY_AUTH:
2735bb3ed8dfSpwernau 			print_key(file, dgettext(TEXT_DOMAIN,
2736a7485808Smarkfen 			    "AKY: "), (struct sadb_key *)current);
27378810c16bSdanmcd 			break;
27388810c16bSdanmcd 		case SADB_EXT_KEY_ENCRYPT:
2739bb3ed8dfSpwernau 			print_key(file, dgettext(TEXT_DOMAIN,
2740a7485808Smarkfen 			    "EKY: "), (struct sadb_key *)current);
27418810c16bSdanmcd 			break;
27428810c16bSdanmcd 		case SADB_EXT_IDENTITY_SRC:
2743bb3ed8dfSpwernau 			print_ident(file, dgettext(TEXT_DOMAIN, "SID: "),
27448810c16bSdanmcd 			    (struct sadb_ident *)current);
27458810c16bSdanmcd 			break;
27468810c16bSdanmcd 		case SADB_EXT_IDENTITY_DST:
2747bb3ed8dfSpwernau 			print_ident(file, dgettext(TEXT_DOMAIN, "DID: "),
27488810c16bSdanmcd 			    (struct sadb_ident *)current);
27498810c16bSdanmcd 			break;
27508810c16bSdanmcd 		case SADB_EXT_SENSITIVITY:
2751bb3ed8dfSpwernau 			print_sens(file, dgettext(TEXT_DOMAIN, "SNS: "),
27525d3b8cb7SBill Sommerfeld 			    (struct sadb_sens *)current, ignore_nss);
27538810c16bSdanmcd 			break;
27548810c16bSdanmcd 		case SADB_EXT_PROPOSAL:
2755bb3ed8dfSpwernau 			print_prop(file, dgettext(TEXT_DOMAIN, "PRP: "),
27568810c16bSdanmcd 			    (struct sadb_prop *)current);
27578810c16bSdanmcd 			break;
27588810c16bSdanmcd 		case SADB_EXT_SUPPORTED_AUTH:
2759bb3ed8dfSpwernau 			print_supp(file, dgettext(TEXT_DOMAIN, "SUA: "),
27608810c16bSdanmcd 			    (struct sadb_supported *)current);
27618810c16bSdanmcd 			break;
27628810c16bSdanmcd 		case SADB_EXT_SUPPORTED_ENCRYPT:
2763bb3ed8dfSpwernau 			print_supp(file, dgettext(TEXT_DOMAIN, "SUE: "),
27648810c16bSdanmcd 			    (struct sadb_supported *)current);
27658810c16bSdanmcd 			break;
27668810c16bSdanmcd 		case SADB_EXT_SPIRANGE:
2767bb3ed8dfSpwernau 			print_spirange(file, dgettext(TEXT_DOMAIN, "SPR: "),
27688810c16bSdanmcd 			    (struct sadb_spirange *)current);
27698810c16bSdanmcd 			break;
27708810c16bSdanmcd 		case SADB_X_EXT_EPROP:
2771bb3ed8dfSpwernau 			print_eprop(file, dgettext(TEXT_DOMAIN, "EPR: "),
27728810c16bSdanmcd 			    (struct sadb_prop *)current);
27738810c16bSdanmcd 			break;
27748810c16bSdanmcd 		case SADB_X_EXT_KM_COOKIE:
2775bb3ed8dfSpwernau 			print_kmc(file, dgettext(TEXT_DOMAIN, "KMC: "),
27768810c16bSdanmcd 			    (struct sadb_x_kmc *)current);
27778810c16bSdanmcd 			break;
27788810c16bSdanmcd 		case SADB_X_EXT_ADDRESS_NATT_REM:
2779bb3ed8dfSpwernau 			print_address(file, dgettext(TEXT_DOMAIN, "NRM: "),
2780bb3ed8dfSpwernau 			    (struct sadb_address *)current, ignore_nss);
27818810c16bSdanmcd 			break;
27828810c16bSdanmcd 		case SADB_X_EXT_ADDRESS_NATT_LOC:
2783bb3ed8dfSpwernau 			print_address(file, dgettext(TEXT_DOMAIN, "NLC: "),
2784bb3ed8dfSpwernau 			    (struct sadb_address *)current, ignore_nss);
27858810c16bSdanmcd 			break;
278638d95a78Smarkfen 		case SADB_X_EXT_PAIR:
278738d95a78Smarkfen 			print_pair(file, dgettext(TEXT_DOMAIN, "OTH: "),
278838d95a78Smarkfen 			    (struct sadb_x_pair *)current);
278938d95a78Smarkfen 			break;
27905d3b8cb7SBill Sommerfeld 		case SADB_X_EXT_OUTER_SENS:
27915d3b8cb7SBill Sommerfeld 			print_sens(file, dgettext(TEXT_DOMAIN, "OSN: "),
27925d3b8cb7SBill Sommerfeld 			    (struct sadb_sens *)current, ignore_nss);
27935d3b8cb7SBill Sommerfeld 			break;
27949c2c14abSThejaswini Singarajipura 		case SADB_X_EXT_REPLAY_VALUE:
27959c2c14abSThejaswini Singarajipura 			(void) print_replay(file, dgettext(TEXT_DOMAIN,
27969c2c14abSThejaswini Singarajipura 			    "RPL: "), (sadb_x_replay_ctr_t *)current);
27979c2c14abSThejaswini Singarajipura 			break;
27988810c16bSdanmcd 		default:
2799bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
28008810c16bSdanmcd 			    "UNK: Unknown ext. %d, len %d.\n"),
28018810c16bSdanmcd 			    ext->sadb_ext_type, lenbytes);
28028810c16bSdanmcd 			for (i = 0; i < ext->sadb_ext_len; i++)
2803bb3ed8dfSpwernau 				(void) fprintf(file, dgettext(TEXT_DOMAIN,
2804c51cb4bcSDan McDonald 				    "UNK: 0x%" PRIx64 "\n"),
2805c51cb4bcSDan McDonald 				    ((uint64_t *)ext)[i]);
28068810c16bSdanmcd 			break;
28078810c16bSdanmcd 		}
28088810c16bSdanmcd 		current += (lenbytes == 0) ?
28098810c16bSdanmcd 		    SADB_8TO64(sizeof (struct sadb_ext)) : ext->sadb_ext_len;
28108810c16bSdanmcd 	}
28118810c16bSdanmcd 	/*
28128810c16bSdanmcd 	 * Print lifetimes NOW.
28138810c16bSdanmcd 	 */
28149c2c14abSThejaswini Singarajipura 	if (currentlt != NULL || hardlt != NULL || softlt != NULL ||
28159c2c14abSThejaswini Singarajipura 	    idlelt != NULL)
28169c2c14abSThejaswini Singarajipura 		print_lifetimes(file, wallclock, currentlt, hardlt,
28179c2c14abSThejaswini Singarajipura 		    softlt, idlelt, vflag);
28188810c16bSdanmcd 
28198810c16bSdanmcd 	if (current - buffer != samsg->sadb_msg_len) {
2820bb3ed8dfSpwernau 		warnxfp(EFD(file), dgettext(TEXT_DOMAIN,
2821bb3ed8dfSpwernau 		    "WARNING: insufficient buffer space or corrupt message."));
28228810c16bSdanmcd 	}
28238810c16bSdanmcd 
2824bb3ed8dfSpwernau 	(void) fflush(file);	/* Make sure our message is out there. */
28258810c16bSdanmcd }
28268810c16bSdanmcd 
28278810c16bSdanmcd /*
28288810c16bSdanmcd  * save_XXX functions are used when "saving" the SA tables to either a
28298810c16bSdanmcd  * file or standard output.  They use the dump_XXX functions where needed,
28308810c16bSdanmcd  * but mostly they use the rparseXXX functions.
28318810c16bSdanmcd  */
28328810c16bSdanmcd 
28338810c16bSdanmcd /*
28348810c16bSdanmcd  * Print save information for a lifetime extension.
28358810c16bSdanmcd  *
28368810c16bSdanmcd  * NOTE : It saves the lifetime in absolute terms.  For example, if you
28378810c16bSdanmcd  * had a hard_usetime of 60 seconds, you'll save it as 60 seconds, even though
28388810c16bSdanmcd  * there may have been 59 seconds burned off the clock.
28398810c16bSdanmcd  */
28408810c16bSdanmcd boolean_t
save_lifetime(struct sadb_lifetime * lifetime,FILE * ofile)28418810c16bSdanmcd save_lifetime(struct sadb_lifetime *lifetime, FILE *ofile)
28428810c16bSdanmcd {
28438810c16bSdanmcd 	char *prefix;
28448810c16bSdanmcd 
28459c2c14abSThejaswini Singarajipura 	switch (lifetime->sadb_lifetime_exttype) {
28469c2c14abSThejaswini Singarajipura 	case SADB_EXT_LIFETIME_HARD:
28479c2c14abSThejaswini Singarajipura 		prefix = "hard";
28489c2c14abSThejaswini Singarajipura 		break;
28499c2c14abSThejaswini Singarajipura 	case SADB_EXT_LIFETIME_SOFT:
28509c2c14abSThejaswini Singarajipura 		prefix = "soft";
28519c2c14abSThejaswini Singarajipura 		break;
28529c2c14abSThejaswini Singarajipura 	case SADB_X_EXT_LIFETIME_IDLE:
28539c2c14abSThejaswini Singarajipura 		prefix = "idle";
28549c2c14abSThejaswini Singarajipura 		break;
28559c2c14abSThejaswini Singarajipura 	}
28568810c16bSdanmcd 
28578810c16bSdanmcd 	if (putc('\t', ofile) == EOF)
28588810c16bSdanmcd 		return (B_FALSE);
28598810c16bSdanmcd 
28608810c16bSdanmcd 	if (lifetime->sadb_lifetime_allocations != 0 && fprintf(ofile,
28618810c16bSdanmcd 	    "%s_alloc %u ", prefix, lifetime->sadb_lifetime_allocations) < 0)
28628810c16bSdanmcd 		return (B_FALSE);
28638810c16bSdanmcd 
28648810c16bSdanmcd 	if (lifetime->sadb_lifetime_bytes != 0 && fprintf(ofile,
2865c51cb4bcSDan McDonald 	    "%s_bytes %" PRIu64 " ", prefix, lifetime->sadb_lifetime_bytes) < 0)
28668810c16bSdanmcd 		return (B_FALSE);
28678810c16bSdanmcd 
28688810c16bSdanmcd 	if (lifetime->sadb_lifetime_addtime != 0 && fprintf(ofile,
2869c51cb4bcSDan McDonald 	    "%s_addtime %" PRIu64 " ", prefix,
2870c51cb4bcSDan McDonald 	    lifetime->sadb_lifetime_addtime) < 0)
28718810c16bSdanmcd 		return (B_FALSE);
28728810c16bSdanmcd 
28738810c16bSdanmcd 	if (lifetime->sadb_lifetime_usetime != 0 && fprintf(ofile,
2874c51cb4bcSDan McDonald 	    "%s_usetime %" PRIu64 " ", prefix,
2875c51cb4bcSDan McDonald 	    lifetime->sadb_lifetime_usetime) < 0)
28768810c16bSdanmcd 		return (B_FALSE);
28778810c16bSdanmcd 
28788810c16bSdanmcd 	return (B_TRUE);
28798810c16bSdanmcd }
28808810c16bSdanmcd 
28818810c16bSdanmcd /*
28828810c16bSdanmcd  * Print save information for an address extension.
28838810c16bSdanmcd  */
28848810c16bSdanmcd boolean_t
save_address(struct sadb_address * addr,FILE * ofile)28858810c16bSdanmcd save_address(struct sadb_address *addr, FILE *ofile)
28868810c16bSdanmcd {
28878810c16bSdanmcd 	char *printable_addr, buf[INET6_ADDRSTRLEN];
28888810c16bSdanmcd 	const char *prefix, *pprefix;
28898810c16bSdanmcd 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)(addr + 1);
28908810c16bSdanmcd 	struct sockaddr_in *sin = (struct sockaddr_in *)sin6;
28918810c16bSdanmcd 	int af = sin->sin_family;
28928810c16bSdanmcd 
28938810c16bSdanmcd 	/*
28948810c16bSdanmcd 	 * Address-family reality check.
28958810c16bSdanmcd 	 */
28968810c16bSdanmcd 	if (af != AF_INET6 && af != AF_INET)
28978810c16bSdanmcd 		return (B_FALSE);
28988810c16bSdanmcd 
28998810c16bSdanmcd 	switch (addr->sadb_address_exttype) {
29008810c16bSdanmcd 	case SADB_EXT_ADDRESS_SRC:
29018810c16bSdanmcd 		prefix = "src";
29028810c16bSdanmcd 		pprefix = "sport";
29038810c16bSdanmcd 		break;
29048810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_INNER_SRC:
29058810c16bSdanmcd 		prefix = "isrc";
29068810c16bSdanmcd 		pprefix = "isport";
29078810c16bSdanmcd 		break;
29088810c16bSdanmcd 	case SADB_EXT_ADDRESS_DST:
29098810c16bSdanmcd 		prefix = "dst";
29108810c16bSdanmcd 		pprefix = "dport";
29118810c16bSdanmcd 		break;
29128810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_INNER_DST:
29138810c16bSdanmcd 		prefix = "idst";
29148810c16bSdanmcd 		pprefix = "idport";
29158810c16bSdanmcd 		break;
29168810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_NATT_LOC:
29178810c16bSdanmcd 		prefix = "nat_loc ";
29188810c16bSdanmcd 		pprefix = "nat_lport";
29198810c16bSdanmcd 		break;
29208810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_NATT_REM:
29218810c16bSdanmcd 		prefix = "nat_rem ";
29228810c16bSdanmcd 		pprefix = "nat_rport";
29238810c16bSdanmcd 		break;
29248810c16bSdanmcd 	}
29258810c16bSdanmcd 
29268810c16bSdanmcd 	if (fprintf(ofile, "    %s ", prefix) < 0)
29278810c16bSdanmcd 		return (B_FALSE);
29288810c16bSdanmcd 
29298810c16bSdanmcd 	/*
29308810c16bSdanmcd 	 * Do not do address-to-name translation, given that we live in
29318810c16bSdanmcd 	 * an age of names that explode into many addresses.
29328810c16bSdanmcd 	 */
29338810c16bSdanmcd 	printable_addr = (char *)inet_ntop(af,
29348810c16bSdanmcd 	    (af == AF_INET) ? (char *)&sin->sin_addr : (char *)&sin6->sin6_addr,
29358810c16bSdanmcd 	    buf, sizeof (buf));
29368810c16bSdanmcd 	if (printable_addr == NULL)
2937a7485808Smarkfen 		printable_addr = "Invalid IP address.";
29388810c16bSdanmcd 	if (fprintf(ofile, "%s", printable_addr) < 0)
29398810c16bSdanmcd 		return (B_FALSE);
29408810c16bSdanmcd 	if (addr->sadb_address_prefixlen != 0 &&
29418810c16bSdanmcd 	    !((addr->sadb_address_prefixlen == 32 && af == AF_INET) ||
294225e435e0Spwernau 	    (addr->sadb_address_prefixlen == 128 && af == AF_INET6))) {
29438810c16bSdanmcd 		if (fprintf(ofile, "/%d", addr->sadb_address_prefixlen) < 0)
29448810c16bSdanmcd 			return (B_FALSE);
29458810c16bSdanmcd 	}
29468810c16bSdanmcd 
29478810c16bSdanmcd 	/*
29488810c16bSdanmcd 	 * The port is in the same position for struct sockaddr_in and
29498810c16bSdanmcd 	 * struct sockaddr_in6.  We exploit that property here.
29508810c16bSdanmcd 	 */
29518810c16bSdanmcd 	if ((pprefix != NULL) && (sin->sin_port != 0))
29528810c16bSdanmcd 		(void) fprintf(ofile, " %s %d", pprefix, ntohs(sin->sin_port));
29538810c16bSdanmcd 
29548810c16bSdanmcd 	return (B_TRUE);
29558810c16bSdanmcd }
29568810c16bSdanmcd 
29578810c16bSdanmcd /*
29588810c16bSdanmcd  * Print save information for a key extension. Returns whether writing
29598810c16bSdanmcd  * to the specified output file was successful or not.
29608810c16bSdanmcd  */
29618810c16bSdanmcd boolean_t
save_key(struct sadb_key * key,FILE * ofile)29628810c16bSdanmcd save_key(struct sadb_key *key, FILE *ofile)
29638810c16bSdanmcd {
29648810c16bSdanmcd 	char *prefix;
29658810c16bSdanmcd 
29668810c16bSdanmcd 	if (putc('\t', ofile) == EOF)
29678810c16bSdanmcd 		return (B_FALSE);
29688810c16bSdanmcd 
29698810c16bSdanmcd 	prefix = (key->sadb_key_exttype == SADB_EXT_KEY_AUTH) ? "auth" : "encr";
29708810c16bSdanmcd 
29718810c16bSdanmcd 	if (fprintf(ofile, "%skey ", prefix) < 0)
29728810c16bSdanmcd 		return (B_FALSE);
29738810c16bSdanmcd 
2974628b0c67SMark Fenwick 	if (dump_key((uint8_t *)(key + 1), key->sadb_key_bits,
2975628b0c67SMark Fenwick 	    key->sadb_key_reserved, ofile, B_FALSE) == -1)
29768810c16bSdanmcd 		return (B_FALSE);
29778810c16bSdanmcd 
29788810c16bSdanmcd 	return (B_TRUE);
29798810c16bSdanmcd }
29808810c16bSdanmcd 
29818810c16bSdanmcd /*
29828810c16bSdanmcd  * Print save information for an identity extension.
29838810c16bSdanmcd  */
29848810c16bSdanmcd boolean_t
save_ident(struct sadb_ident * ident,FILE * ofile)29858810c16bSdanmcd save_ident(struct sadb_ident *ident, FILE *ofile)
29868810c16bSdanmcd {
29878810c16bSdanmcd 	char *prefix;
29888810c16bSdanmcd 
29898810c16bSdanmcd 	if (putc('\t', ofile) == EOF)
29908810c16bSdanmcd 		return (B_FALSE);
29918810c16bSdanmcd 
29928810c16bSdanmcd 	prefix = (ident->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC) ? "src" :
29938810c16bSdanmcd 	    "dst";
29948810c16bSdanmcd 
29958810c16bSdanmcd 	if (fprintf(ofile, "%sidtype %s ", prefix,
29968810c16bSdanmcd 	    rparseidtype(ident->sadb_ident_type)) < 0)
29978810c16bSdanmcd 		return (B_FALSE);
29988810c16bSdanmcd 
29998810c16bSdanmcd 	if (ident->sadb_ident_type == SADB_X_IDENTTYPE_DN ||
30008810c16bSdanmcd 	    ident->sadb_ident_type == SADB_X_IDENTTYPE_GN) {
3001a7485808Smarkfen 		if (fprintf(ofile, dgettext(TEXT_DOMAIN,
3002a7485808Smarkfen 		    "<can-not-print>")) < 0)
30038810c16bSdanmcd 			return (B_FALSE);
30048810c16bSdanmcd 	} else {
30058810c16bSdanmcd 		if (fprintf(ofile, "%s", (char *)(ident + 1)) < 0)
30068810c16bSdanmcd 			return (B_FALSE);
30078810c16bSdanmcd 	}
30088810c16bSdanmcd 
30098810c16bSdanmcd 	return (B_TRUE);
30108810c16bSdanmcd }
30118810c16bSdanmcd 
30125d3b8cb7SBill Sommerfeld boolean_t
save_sens(struct sadb_sens * sens,FILE * ofile)30135d3b8cb7SBill Sommerfeld save_sens(struct sadb_sens *sens, FILE *ofile)
30145d3b8cb7SBill Sommerfeld {
30155d3b8cb7SBill Sommerfeld 	char *prefix;
30165d3b8cb7SBill Sommerfeld 	char *hlabel;
30175d3b8cb7SBill Sommerfeld 	bslabel_t sl;
30185d3b8cb7SBill Sommerfeld 
30195d3b8cb7SBill Sommerfeld 	if (putc('\t', ofile) == EOF)
30205d3b8cb7SBill Sommerfeld 		return (B_FALSE);
30215d3b8cb7SBill Sommerfeld 
30225d3b8cb7SBill Sommerfeld 	if (sens->sadb_sens_exttype == SADB_EXT_SENSITIVITY)
30235d3b8cb7SBill Sommerfeld 		prefix = "label";
30245d3b8cb7SBill Sommerfeld 	else if ((sens->sadb_x_sens_flags & SADB_X_SENS_IMPLICIT) == 0)
30255d3b8cb7SBill Sommerfeld 		prefix = "outer-label";
30265d3b8cb7SBill Sommerfeld 	else
30275d3b8cb7SBill Sommerfeld 		prefix = "implicit-label";
30285d3b8cb7SBill Sommerfeld 
30295d3b8cb7SBill Sommerfeld 	ipsec_convert_sens_to_bslabel(sens, &sl);
30305d3b8cb7SBill Sommerfeld 	ipsec_convert_bslabel_to_hex(&sl, &hlabel);
30315d3b8cb7SBill Sommerfeld 
30325d3b8cb7SBill Sommerfeld 	if (fprintf(ofile, "%s %s ", prefix, hlabel) < 0) {
30335d3b8cb7SBill Sommerfeld 		free(hlabel);
30345d3b8cb7SBill Sommerfeld 		return (B_FALSE);
30355d3b8cb7SBill Sommerfeld 	}
30365d3b8cb7SBill Sommerfeld 	free(hlabel);
30375d3b8cb7SBill Sommerfeld 
30385d3b8cb7SBill Sommerfeld 	return (B_TRUE);
30395d3b8cb7SBill Sommerfeld }
30405d3b8cb7SBill Sommerfeld 
30418810c16bSdanmcd /*
30428810c16bSdanmcd  * "Save" a security association to an output file.
30438810c16bSdanmcd  *
3044a7485808Smarkfen  * NOTE the lack of calls to dgettext() because I'm outputting parseable stuff.
30458810c16bSdanmcd  * ALSO NOTE that if you change keywords (see parsecmd()), you'll have to
30468810c16bSdanmcd  * change them here as well.
30478810c16bSdanmcd  */
30488810c16bSdanmcd void
save_assoc(uint64_t * buffer,FILE * ofile)30498810c16bSdanmcd save_assoc(uint64_t *buffer, FILE *ofile)
30508810c16bSdanmcd {
3051a7485808Smarkfen 	int terrno;
3052437220cdSdanmcd 	boolean_t seen_proto = B_FALSE, seen_iproto = B_FALSE;
30538810c16bSdanmcd 	uint64_t *current;
30548810c16bSdanmcd 	struct sadb_address *addr;
30559c2c14abSThejaswini Singarajipura 	struct sadb_x_replay_ctr *repl;
30568810c16bSdanmcd 	struct sadb_msg *samsg = (struct sadb_msg *)buffer;
30578810c16bSdanmcd 	struct sadb_ext *ext;
30588810c16bSdanmcd 
3059a7485808Smarkfen #define	tidyup() \
3060a7485808Smarkfen 	terrno = errno; (void) fclose(ofile); errno = terrno; \
3061a7485808Smarkfen 	interactive = B_FALSE
3062a7485808Smarkfen 
3063a7485808Smarkfen #define	savenl() if (fputs(" \\\n", ofile) == EOF) \
3064a7485808Smarkfen 	{ bail(dgettext(TEXT_DOMAIN, "savenl")); }
30658810c16bSdanmcd 
30668810c16bSdanmcd 	if (fputs("# begin assoc\n", ofile) == EOF)
3067a7485808Smarkfen 		bail(dgettext(TEXT_DOMAIN,
3068a7485808Smarkfen 		    "save_assoc: Opening comment of SA"));
30698810c16bSdanmcd 	if (fprintf(ofile, "add %s ", rparsesatype(samsg->sadb_msg_satype)) < 0)
3070a7485808Smarkfen 		bail(dgettext(TEXT_DOMAIN, "save_assoc: First line of SA"));
30718810c16bSdanmcd 	savenl();
30728810c16bSdanmcd 
30738810c16bSdanmcd 	current = (uint64_t *)(samsg + 1);
30748810c16bSdanmcd 	while (current - buffer < samsg->sadb_msg_len) {
30758810c16bSdanmcd 		struct sadb_sa *assoc;
30768810c16bSdanmcd 
30778810c16bSdanmcd 		ext = (struct sadb_ext *)current;
3078437220cdSdanmcd 		addr = (struct sadb_address *)ext;  /* Just in case... */
30798810c16bSdanmcd 		switch (ext->sadb_ext_type) {
30808810c16bSdanmcd 		case SADB_EXT_SA:
30818810c16bSdanmcd 			assoc = (struct sadb_sa *)ext;
30828810c16bSdanmcd 			if (assoc->sadb_sa_state != SADB_SASTATE_MATURE) {
30838810c16bSdanmcd 				if (fprintf(ofile, "# WARNING: SA was dying "
30848810c16bSdanmcd 				    "or dead.\n") < 0) {
3085a7485808Smarkfen 					tidyup();
3086a7485808Smarkfen 					bail(dgettext(TEXT_DOMAIN,
3087a7485808Smarkfen 					    "save_assoc: fprintf not mature"));
30888810c16bSdanmcd 				}
30898810c16bSdanmcd 			}
30908810c16bSdanmcd 			if (fprintf(ofile, "    spi 0x%x ",
3091a7485808Smarkfen 			    ntohl(assoc->sadb_sa_spi)) < 0) {
3092a7485808Smarkfen 				tidyup();
3093a7485808Smarkfen 				bail(dgettext(TEXT_DOMAIN,
3094a7485808Smarkfen 				    "save_assoc: fprintf spi"));
3095a7485808Smarkfen 			}
30968810c16bSdanmcd 			if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) {
30978810c16bSdanmcd 				if (fprintf(ofile, "encr_alg %s ",
30988810c16bSdanmcd 				    rparsealg(assoc->sadb_sa_encrypt,
309925e435e0Spwernau 				    IPSEC_PROTO_ESP)) < 0) {
3100a7485808Smarkfen 					tidyup();
3101a7485808Smarkfen 					bail(dgettext(TEXT_DOMAIN,
3102a7485808Smarkfen 					    "save_assoc: fprintf encrypt"));
3103a7485808Smarkfen 				}
31048810c16bSdanmcd 			}
31058810c16bSdanmcd 			if (assoc->sadb_sa_auth != SADB_AALG_NONE) {
31068810c16bSdanmcd 				if (fprintf(ofile, "auth_alg %s ",
31078810c16bSdanmcd 				    rparsealg(assoc->sadb_sa_auth,
310825e435e0Spwernau 				    IPSEC_PROTO_AH)) < 0) {
3109a7485808Smarkfen 					tidyup();
3110a7485808Smarkfen 					bail(dgettext(TEXT_DOMAIN,
3111a7485808Smarkfen 					    "save_assoc: fprintf auth"));
3112a7485808Smarkfen 				}
31138810c16bSdanmcd 			}
31148810c16bSdanmcd 			if (fprintf(ofile, "replay %d ",
3115a7485808Smarkfen 			    assoc->sadb_sa_replay) < 0) {
3116a7485808Smarkfen 				tidyup();
3117a7485808Smarkfen 				bail(dgettext(TEXT_DOMAIN,
3118a7485808Smarkfen 				    "save_assoc: fprintf replay"));
3119a7485808Smarkfen 			}
31208810c16bSdanmcd 			if (assoc->sadb_sa_flags & (SADB_X_SAFLAGS_NATT_LOC |
31218810c16bSdanmcd 			    SADB_X_SAFLAGS_NATT_REM)) {
3122a7485808Smarkfen 				if (fprintf(ofile, "encap udp") < 0) {
3123a7485808Smarkfen 					tidyup();
3124a7485808Smarkfen 					bail(dgettext(TEXT_DOMAIN,
3125a7485808Smarkfen 					    "save_assoc: fprintf encap"));
3126a7485808Smarkfen 				}
31278810c16bSdanmcd 			}
31288810c16bSdanmcd 			savenl();
31298810c16bSdanmcd 			break;
31308810c16bSdanmcd 		case SADB_EXT_LIFETIME_HARD:
31318810c16bSdanmcd 		case SADB_EXT_LIFETIME_SOFT:
31329c2c14abSThejaswini Singarajipura 		case SADB_X_EXT_LIFETIME_IDLE:
3133a7485808Smarkfen 			if (!save_lifetime((struct sadb_lifetime *)ext,
3134a7485808Smarkfen 			    ofile)) {
3135a7485808Smarkfen 				tidyup();
3136a7485808Smarkfen 				bail(dgettext(TEXT_DOMAIN, "save_lifetime"));
3137a7485808Smarkfen 			}
31388810c16bSdanmcd 			savenl();
31398810c16bSdanmcd 			break;
31408810c16bSdanmcd 		case SADB_X_EXT_ADDRESS_INNER_SRC:
31418810c16bSdanmcd 		case SADB_X_EXT_ADDRESS_INNER_DST:
3142437220cdSdanmcd 			if (!seen_iproto && addr->sadb_address_proto) {
3143437220cdSdanmcd 				(void) fprintf(ofile, "    iproto %d",
3144437220cdSdanmcd 				    addr->sadb_address_proto);
3145437220cdSdanmcd 				savenl();
3146437220cdSdanmcd 				seen_iproto = B_TRUE;
3147437220cdSdanmcd 			}
3148437220cdSdanmcd 			goto skip_srcdst;  /* Hack to avoid cases below... */
3149437220cdSdanmcd 			/* FALLTHRU */
3150437220cdSdanmcd 		case SADB_EXT_ADDRESS_SRC:
3151437220cdSdanmcd 		case SADB_EXT_ADDRESS_DST:
31528810c16bSdanmcd 			if (!seen_proto && addr->sadb_address_proto) {
31538810c16bSdanmcd 				(void) fprintf(ofile, "    proto %d",
31548810c16bSdanmcd 				    addr->sadb_address_proto);
31558810c16bSdanmcd 				savenl();
3156437220cdSdanmcd 				seen_proto = B_TRUE;
31578810c16bSdanmcd 			}
3158437220cdSdanmcd 			/* FALLTHRU */
3159437220cdSdanmcd 		case SADB_X_EXT_ADDRESS_NATT_REM:
3160437220cdSdanmcd 		case SADB_X_EXT_ADDRESS_NATT_LOC:
3161437220cdSdanmcd skip_srcdst:
3162a7485808Smarkfen 			if (!save_address(addr, ofile)) {
3163a7485808Smarkfen 				tidyup();
3164a7485808Smarkfen 				bail(dgettext(TEXT_DOMAIN, "save_address"));
3165a7485808Smarkfen 			}
31668810c16bSdanmcd 			savenl();
31678810c16bSdanmcd 			break;
31688810c16bSdanmcd 		case SADB_EXT_KEY_AUTH:
31698810c16bSdanmcd 		case SADB_EXT_KEY_ENCRYPT:
3170a7485808Smarkfen 			if (!save_key((struct sadb_key *)ext, ofile)) {
3171a7485808Smarkfen 				tidyup();
3172a7485808Smarkfen 				bail(dgettext(TEXT_DOMAIN, "save_address"));
3173a7485808Smarkfen 			}
31748810c16bSdanmcd 			savenl();
31758810c16bSdanmcd 			break;
31768810c16bSdanmcd 		case SADB_EXT_IDENTITY_SRC:
31778810c16bSdanmcd 		case SADB_EXT_IDENTITY_DST:
3178a7485808Smarkfen 			if (!save_ident((struct sadb_ident *)ext, ofile)) {
3179a7485808Smarkfen 				tidyup();
3180a7485808Smarkfen 				bail(dgettext(TEXT_DOMAIN, "save_address"));
3181a7485808Smarkfen 			}
31828810c16bSdanmcd 			savenl();
31838810c16bSdanmcd 			break;
31849c2c14abSThejaswini Singarajipura 		case SADB_X_EXT_REPLAY_VALUE:
31859c2c14abSThejaswini Singarajipura 			repl = (sadb_x_replay_ctr_t *)ext;
31869c2c14abSThejaswini Singarajipura 			if ((repl->sadb_x_rc_replay32 == 0) &&
31879c2c14abSThejaswini Singarajipura 			    (repl->sadb_x_rc_replay64 == 0)) {
31889c2c14abSThejaswini Singarajipura 				tidyup();
31899c2c14abSThejaswini Singarajipura 				bail(dgettext(TEXT_DOMAIN, "Replay Value"));
31909c2c14abSThejaswini Singarajipura 			}
31919c2c14abSThejaswini Singarajipura 			if (fprintf(ofile, "replay_value %" PRIu64 "",
31929c2c14abSThejaswini Singarajipura 			    (repl->sadb_x_rc_replay32 == 0 ?
31939c2c14abSThejaswini Singarajipura 			    repl->sadb_x_rc_replay64 :
31949c2c14abSThejaswini Singarajipura 			    repl->sadb_x_rc_replay32)) < 0) {
31959c2c14abSThejaswini Singarajipura 				tidyup();
31969c2c14abSThejaswini Singarajipura 				bail(dgettext(TEXT_DOMAIN,
31979c2c14abSThejaswini Singarajipura 				    "save_assoc: fprintf replay value"));
31989c2c14abSThejaswini Singarajipura 			}
31999c2c14abSThejaswini Singarajipura 			savenl();
32009c2c14abSThejaswini Singarajipura 			break;
32018810c16bSdanmcd 		case SADB_EXT_SENSITIVITY:
32025d3b8cb7SBill Sommerfeld 		case SADB_X_EXT_OUTER_SENS:
32035d3b8cb7SBill Sommerfeld 			if (!save_sens((struct sadb_sens *)ext, ofile)) {
32045d3b8cb7SBill Sommerfeld 				tidyup();
32055d3b8cb7SBill Sommerfeld 				bail(dgettext(TEXT_DOMAIN, "save_sens"));
32065d3b8cb7SBill Sommerfeld 			}
32075d3b8cb7SBill Sommerfeld 			savenl();
32085d3b8cb7SBill Sommerfeld 			break;
32098810c16bSdanmcd 		default:
32108810c16bSdanmcd 			/* Skip over irrelevant extensions. */
32118810c16bSdanmcd 			break;
32128810c16bSdanmcd 		}
32138810c16bSdanmcd 		current += ext->sadb_ext_len;
32148810c16bSdanmcd 	}
32158810c16bSdanmcd 
3216a7485808Smarkfen 	if (fputs(dgettext(TEXT_DOMAIN, "\n# end assoc\n\n"), ofile) == EOF) {
3217a7485808Smarkfen 		tidyup();
3218a7485808Smarkfen 		bail(dgettext(TEXT_DOMAIN, "save_assoc: last fputs"));
3219a7485808Smarkfen 	}
32208810c16bSdanmcd }
32218810c16bSdanmcd 
32228810c16bSdanmcd /*
32238810c16bSdanmcd  * Open the output file for the "save" command.
32248810c16bSdanmcd  */
32258810c16bSdanmcd FILE *
opensavefile(char * filename)32268810c16bSdanmcd opensavefile(char *filename)
32278810c16bSdanmcd {
32288810c16bSdanmcd 	int fd;
32298810c16bSdanmcd 	FILE *retval;
32308810c16bSdanmcd 	struct stat buf;
32318810c16bSdanmcd 
32328810c16bSdanmcd 	/*
32338810c16bSdanmcd 	 * If the user specifies "-" or doesn't give a filename, then
32348810c16bSdanmcd 	 * dump to stdout.  Make sure to document the dangers of files
32358810c16bSdanmcd 	 * that are NFS, directing your output to strange places, etc.
32368810c16bSdanmcd 	 */
32378810c16bSdanmcd 	if (filename == NULL || strcmp("-", filename) == 0)
32388810c16bSdanmcd 		return (stdout);
32398810c16bSdanmcd 
32408810c16bSdanmcd 	/*
32418810c16bSdanmcd 	 * open the file with the create bits set.  Since I check for
32428810c16bSdanmcd 	 * real UID == root in main(), I won't worry about the ownership
32438810c16bSdanmcd 	 * problem.
32448810c16bSdanmcd 	 */
32458810c16bSdanmcd 	fd = open(filename, O_WRONLY | O_EXCL | O_CREAT | O_TRUNC, S_IRUSR);
32468810c16bSdanmcd 	if (fd == -1) {
32478810c16bSdanmcd 		if (errno != EEXIST)
3248a7485808Smarkfen 			bail_msg("%s %s: %s", filename, dgettext(TEXT_DOMAIN,
3249a7485808Smarkfen 			    "open error"),
32508810c16bSdanmcd 			    strerror(errno));
32518810c16bSdanmcd 		fd = open(filename, O_WRONLY | O_TRUNC, 0);
32528810c16bSdanmcd 		if (fd == -1)
3253a7485808Smarkfen 			bail_msg("%s %s: %s", filename, dgettext(TEXT_DOMAIN,
3254a7485808Smarkfen 			    "open error"), strerror(errno));
32558810c16bSdanmcd 		if (fstat(fd, &buf) == -1) {
32568810c16bSdanmcd 			(void) close(fd);
32578810c16bSdanmcd 			bail_msg("%s fstat: %s", filename, strerror(errno));
32588810c16bSdanmcd 		}
32598810c16bSdanmcd 		if (S_ISREG(buf.st_mode) &&
32608810c16bSdanmcd 		    ((buf.st_mode & S_IAMB) != S_IRUSR)) {
3261a7485808Smarkfen 			warnx(dgettext(TEXT_DOMAIN,
3262a7485808Smarkfen 			    "WARNING: Save file already exists with "
3263a7485808Smarkfen 			    "permission %o."), buf.st_mode & S_IAMB);
3264a7485808Smarkfen 			warnx(dgettext(TEXT_DOMAIN,
3265a7485808Smarkfen 			    "Normal users may be able to read IPsec "
3266a7485808Smarkfen 			    "keying material."));
32678810c16bSdanmcd 		}
32688810c16bSdanmcd 	}
32698810c16bSdanmcd 
32708810c16bSdanmcd 	/* Okay, we have an FD.  Assign it to a stdio FILE pointer. */
32718810c16bSdanmcd 	retval = fdopen(fd, "w");
32728810c16bSdanmcd 	if (retval == NULL) {
32738810c16bSdanmcd 		(void) close(fd);
3274a7485808Smarkfen 		bail_msg("%s %s: %s", filename, dgettext(TEXT_DOMAIN,
3275a7485808Smarkfen 		    "fdopen error"), strerror(errno));
32768810c16bSdanmcd 	}
32778810c16bSdanmcd 	return (retval);
32788810c16bSdanmcd }
32798810c16bSdanmcd 
32808810c16bSdanmcd const char *
do_inet_ntop(const void * addr,char * cp,size_t size)32818810c16bSdanmcd do_inet_ntop(const void *addr, char *cp, size_t size)
32828810c16bSdanmcd {
32838810c16bSdanmcd 	boolean_t isv4;
32848810c16bSdanmcd 	struct in6_addr *inaddr6 = (struct in6_addr *)addr;
32858810c16bSdanmcd 	struct in_addr inaddr;
32868810c16bSdanmcd 
32878810c16bSdanmcd 	if ((isv4 = IN6_IS_ADDR_V4MAPPED(inaddr6)) == B_TRUE) {
32888810c16bSdanmcd 		IN6_V4MAPPED_TO_INADDR(inaddr6, &inaddr);
32898810c16bSdanmcd 	}
32908810c16bSdanmcd 
32918810c16bSdanmcd 	return (inet_ntop(isv4 ? AF_INET : AF_INET6,
32928810c16bSdanmcd 	    isv4 ? (void *)&inaddr : inaddr6, cp, size));
32938810c16bSdanmcd }
32948810c16bSdanmcd 
32958810c16bSdanmcd char numprint[NBUF_SIZE];
32968810c16bSdanmcd 
32978810c16bSdanmcd /*
32988810c16bSdanmcd  * Parse and reverse parse a specific SA type (AH, ESP, etc.).
32998810c16bSdanmcd  */
33008810c16bSdanmcd static struct typetable {
33018810c16bSdanmcd 	char *type;
33028810c16bSdanmcd 	int token;
33038810c16bSdanmcd } type_table[] = {
33048810c16bSdanmcd 	{"all", SADB_SATYPE_UNSPEC},
33058810c16bSdanmcd 	{"ah",  SADB_SATYPE_AH},
33068810c16bSdanmcd 	{"esp", SADB_SATYPE_ESP},
33078810c16bSdanmcd 	/* PF_KEY NOTE:  More to come if net/pfkeyv2.h gets updated. */
33088810c16bSdanmcd 	{NULL, 0}	/* Token value is irrelevant for this entry. */
33098810c16bSdanmcd };
33108810c16bSdanmcd 
33118810c16bSdanmcd char *
rparsesatype(int type)33128810c16bSdanmcd rparsesatype(int type)
33138810c16bSdanmcd {
33148810c16bSdanmcd 	struct typetable *tt = type_table;
33158810c16bSdanmcd 
33168810c16bSdanmcd 	while (tt->type != NULL && type != tt->token)
33178810c16bSdanmcd 		tt++;
33188810c16bSdanmcd 
33198810c16bSdanmcd 	if (tt->type == NULL) {
33208810c16bSdanmcd 		(void) snprintf(numprint, NBUF_SIZE, "%d", type);
33218810c16bSdanmcd 	} else {
33228810c16bSdanmcd 		return (tt->type);
33238810c16bSdanmcd 	}
33248810c16bSdanmcd 
33258810c16bSdanmcd 	return (numprint);
33268810c16bSdanmcd }
33278810c16bSdanmcd 
33288810c16bSdanmcd 
33298810c16bSdanmcd /*
33308810c16bSdanmcd  * Return a string containing the name of the specified numerical algorithm
33318810c16bSdanmcd  * identifier.
33328810c16bSdanmcd  */
33338810c16bSdanmcd char *
rparsealg(uint8_t alg,int proto_num)33348810c16bSdanmcd rparsealg(uint8_t alg, int proto_num)
33358810c16bSdanmcd {
33368810c16bSdanmcd 	static struct ipsecalgent *holder = NULL; /* we're single-threaded */
33378810c16bSdanmcd 
33388810c16bSdanmcd 	if (holder != NULL)
33398810c16bSdanmcd 		freeipsecalgent(holder);
33408810c16bSdanmcd 
33418810c16bSdanmcd 	holder = getipsecalgbynum(alg, proto_num, NULL);
33428810c16bSdanmcd 	if (holder == NULL) {
33438810c16bSdanmcd 		(void) snprintf(numprint, NBUF_SIZE, "%d", alg);
33448810c16bSdanmcd 		return (numprint);
33458810c16bSdanmcd 	}
33468810c16bSdanmcd 
33478810c16bSdanmcd 	return (*(holder->a_names));
33488810c16bSdanmcd }
33498810c16bSdanmcd 
33508810c16bSdanmcd /*
33518810c16bSdanmcd  * Parse and reverse parse out a source/destination ID type.
33528810c16bSdanmcd  */
33538810c16bSdanmcd static struct idtypes {
33548810c16bSdanmcd 	char *idtype;
33558810c16bSdanmcd 	uint8_t retval;
33568810c16bSdanmcd } idtypes[] = {
33578810c16bSdanmcd 	{"prefix",	SADB_IDENTTYPE_PREFIX},
33588810c16bSdanmcd 	{"fqdn",	SADB_IDENTTYPE_FQDN},
33598810c16bSdanmcd 	{"domain",	SADB_IDENTTYPE_FQDN},
33608810c16bSdanmcd 	{"domainname",	SADB_IDENTTYPE_FQDN},
33618810c16bSdanmcd 	{"user_fqdn",	SADB_IDENTTYPE_USER_FQDN},
33628810c16bSdanmcd 	{"mailbox",	SADB_IDENTTYPE_USER_FQDN},
33638810c16bSdanmcd 	{"der_dn",	SADB_X_IDENTTYPE_DN},
33648810c16bSdanmcd 	{"der_gn",	SADB_X_IDENTTYPE_GN},
33658810c16bSdanmcd 	{NULL,		0}
33668810c16bSdanmcd };
33678810c16bSdanmcd 
33688810c16bSdanmcd char *
rparseidtype(uint16_t type)33698810c16bSdanmcd rparseidtype(uint16_t type)
33708810c16bSdanmcd {
33718810c16bSdanmcd 	struct idtypes *idp;
33728810c16bSdanmcd 
33738810c16bSdanmcd 	for (idp = idtypes; idp->idtype != NULL; idp++) {
33748810c16bSdanmcd 		if (type == idp->retval)
33758810c16bSdanmcd 			return (idp->idtype);
33768810c16bSdanmcd 	}
33778810c16bSdanmcd 
33788810c16bSdanmcd 	(void) snprintf(numprint, NBUF_SIZE, "%d", type);
33798810c16bSdanmcd 	return (numprint);
33808810c16bSdanmcd }
3381e3320f40Smarkfen 
3382e3320f40Smarkfen /*
3383e3320f40Smarkfen  * This is a general purpose exit function, calling functions can specify an
3384*bbf21555SRichard Lowe  * error type. If the command calling this function was started by smf(7) the
3385e3320f40Smarkfen  * error type could be used as a hint to the restarter. In the future this
3386e3320f40Smarkfen  * function could be used to do something more intelligent with a process that
3387a1ba8781SMark Fenwick  * encounters an error. If exit() is called with an error code other than those
3388*bbf21555SRichard Lowe  * defined by smf(7), the program will just get restarted. Unless restarting
3389a1ba8781SMark Fenwick  * is likely to resolve the error condition, its probably sensible to just
3390a1ba8781SMark Fenwick  * log the error and keep running.
3391a1ba8781SMark Fenwick  *
3392a1ba8781SMark Fenwick  * The SERVICE_* exit_types mean nothing if the command was run from the
3393a1ba8781SMark Fenwick  * command line, just exit(). There are two special cases:
3394a1ba8781SMark Fenwick  *
3395*bbf21555SRichard Lowe  * SERVICE_DEGRADE - Not implemented in smf(7), one day it could hint that
3396a1ba8781SMark Fenwick  *                   the service is not running as well is it could. For
3397a1ba8781SMark Fenwick  *                   now, don't do anything, just record the error.
3398a1ba8781SMark Fenwick  * DEBUG_FATAL - Something happened, if the command was being run in debug
3399a1ba8781SMark Fenwick  *               mode, exit() as you really want to know something happened,
3400a1ba8781SMark Fenwick  *               otherwise just keep running. This is ignored when running
3401*bbf21555SRichard Lowe  *               under smf(7).
3402e3320f40Smarkfen  *
3403e3320f40Smarkfen  * The function will handle an optional variable args error message, this
3404e3320f40Smarkfen  * will be written to the error stream, typically a log file or stderr.
3405e3320f40Smarkfen  */
3406e3320f40Smarkfen void
ipsecutil_exit(exit_type_t type,char * fmri,FILE * fp,const char * fmt,...)3407e3320f40Smarkfen ipsecutil_exit(exit_type_t type, char *fmri, FILE *fp, const char *fmt, ...)
3408e3320f40Smarkfen {
3409e3320f40Smarkfen 	int exit_status;
3410e3320f40Smarkfen 	va_list args;
3411e3320f40Smarkfen 
3412e3320f40Smarkfen 	if (fp == NULL)
3413e3320f40Smarkfen 		fp = stderr;
3414e3320f40Smarkfen 	if (fmt != NULL) {
3415e3320f40Smarkfen 		va_start(args, fmt);
3416e3320f40Smarkfen 		vwarnxfp(fp, fmt, args);
3417e3320f40Smarkfen 		va_end(args);
3418e3320f40Smarkfen 	}
3419e3320f40Smarkfen 
3420e3320f40Smarkfen 	if (fmri == NULL) {
3421e3320f40Smarkfen 		/* Command being run directly from a shell. */
3422e3320f40Smarkfen 		switch (type) {
3423e3320f40Smarkfen 		case SERVICE_EXIT_OK:
3424e3320f40Smarkfen 			exit_status = 0;
3425e3320f40Smarkfen 			break;
3426e3320f40Smarkfen 		case SERVICE_DEGRADE:
3427e3320f40Smarkfen 			return;
3428e3320f40Smarkfen 		case SERVICE_BADPERM:
3429e3320f40Smarkfen 		case SERVICE_BADCONF:
3430e3320f40Smarkfen 		case SERVICE_MAINTAIN:
3431e3320f40Smarkfen 		case SERVICE_DISABLE:
3432e3320f40Smarkfen 		case SERVICE_FATAL:
3433e3320f40Smarkfen 		case SERVICE_RESTART:
3434a1ba8781SMark Fenwick 		case DEBUG_FATAL:
3435e3320f40Smarkfen 			warnxfp(fp, "Fatal error - exiting.");
3436e3320f40Smarkfen 			exit_status = 1;
3437e3320f40Smarkfen 			break;
3438e3320f40Smarkfen 		}
3439e3320f40Smarkfen 	} else {
3440*bbf21555SRichard Lowe 		/* Command being run as a smf(7) method. */
3441e3320f40Smarkfen 		switch (type) {
3442e3320f40Smarkfen 		case SERVICE_EXIT_OK:
3443e3320f40Smarkfen 			exit_status = SMF_EXIT_OK;
3444e3320f40Smarkfen 			break;
3445a1ba8781SMark Fenwick 		case SERVICE_DEGRADE: /* Not implemented yet. */
3446a1ba8781SMark Fenwick 		case DEBUG_FATAL:
3447a1ba8781SMark Fenwick 			/* Keep running, don't exit(). */
3448e3320f40Smarkfen 			return;
3449e3320f40Smarkfen 		case SERVICE_BADPERM:
3450e3320f40Smarkfen 			warnxfp(fp, dgettext(TEXT_DOMAIN,
3451e3320f40Smarkfen 			    "Permission error with %s."), fmri);
3452e3320f40Smarkfen 			exit_status = SMF_EXIT_ERR_PERM;
3453e3320f40Smarkfen 			break;
3454e3320f40Smarkfen 		case SERVICE_BADCONF:
3455e3320f40Smarkfen 			warnxfp(fp, dgettext(TEXT_DOMAIN,
3456e3320f40Smarkfen 			    "Bad configuration of service %s."), fmri);
3457e3320f40Smarkfen 			exit_status = SMF_EXIT_ERR_FATAL;
3458e3320f40Smarkfen 			break;
3459e3320f40Smarkfen 		case SERVICE_MAINTAIN:
3460e3320f40Smarkfen 			warnxfp(fp, dgettext(TEXT_DOMAIN,
3461e3320f40Smarkfen 			    "Service %s needs maintenance."), fmri);
3462e3320f40Smarkfen 			exit_status = SMF_EXIT_ERR_FATAL;
3463e3320f40Smarkfen 			break;
3464e3320f40Smarkfen 		case SERVICE_DISABLE:
3465e3320f40Smarkfen 			exit_status = SMF_EXIT_ERR_FATAL;
3466e3320f40Smarkfen 			break;
3467e3320f40Smarkfen 		case SERVICE_FATAL:
3468e3320f40Smarkfen 			warnxfp(fp, dgettext(TEXT_DOMAIN,
3469e3320f40Smarkfen 			    "Service %s fatal error."), fmri);
3470e3320f40Smarkfen 			exit_status = SMF_EXIT_ERR_FATAL;
3471e3320f40Smarkfen 			break;
3472e3320f40Smarkfen 		case SERVICE_RESTART:
3473e3320f40Smarkfen 			exit_status = 1;
3474e3320f40Smarkfen 			break;
3475e3320f40Smarkfen 		}
3476e3320f40Smarkfen 	}
3477e3320f40Smarkfen 	(void) fflush(fp);
3478e3320f40Smarkfen 	(void) fclose(fp);
3479e3320f40Smarkfen 	exit(exit_status);
3480e3320f40Smarkfen }
3481bdc560abSJason King 
3482bdc560abSJason King void
print_asn1_name(FILE * file,const unsigned char * buf,long buflen)3483bdc560abSJason King print_asn1_name(FILE *file, const unsigned char *buf, long buflen)
3484bdc560abSJason King {
3485bdc560abSJason King 	KMF_X509_NAME name = { 0 };
3486bdc560abSJason King 	KMF_DATA data = { 0 };
3487bdc560abSJason King 	char *str = NULL;
3488bdc560abSJason King 
3489bdc560abSJason King 	data.Data = (unsigned char *)buf;
3490bdc560abSJason King 	data.Length = buflen;
3491bdc560abSJason King 
3492bdc560abSJason King 	if (DerDecodeName(&data, &name) != KMF_OK)
3493bdc560abSJason King 		goto fail;
3494bdc560abSJason King 
3495bdc560abSJason King 	if (kmf_dn_to_string(&name, &str) != KMF_OK)
3496bdc560abSJason King 		goto fail;
3497bdc560abSJason King 
3498bdc560abSJason King 	(void) fprintf(file, "%s\n", str);
3499bdc560abSJason King 	kmf_free_dn(&name);
3500bdc560abSJason King 	free(str);
3501bdc560abSJason King 	return;
3502bdc560abSJason King fail:
3503bdc560abSJason King 	kmf_free_dn(&name);
3504bdc560abSJason King 	(void) fprintf(file, dgettext(TEXT_DOMAIN, "<cannot interpret>\n"));
3505bdc560abSJason King }
3506