xref: /titanic_53/usr/src/lib/libipsecutil/common/ipsec_util.c (revision 33f5ff17089e3a43e6e730bf80384c233123dbd9)
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.
25*33f5ff17SMilan Jurik  * Copyright 2012 Milan Juri. All rights reserved.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <unistd.h>
297c478bd9Sstevel@tonic-gate #include <stdio.h>
307c478bd9Sstevel@tonic-gate #include <stdlib.h>
317c478bd9Sstevel@tonic-gate #include <stdarg.h>
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/stat.h>
347c478bd9Sstevel@tonic-gate #include <fcntl.h>
357c478bd9Sstevel@tonic-gate #include <sys/sysconf.h>
367c478bd9Sstevel@tonic-gate #include <strings.h>
377c478bd9Sstevel@tonic-gate #include <ctype.h>
387c478bd9Sstevel@tonic-gate #include <errno.h>
397c478bd9Sstevel@tonic-gate #include <sys/socket.h>
407c478bd9Sstevel@tonic-gate #include <netdb.h>
417c478bd9Sstevel@tonic-gate #include <netinet/in.h>
427c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
437c478bd9Sstevel@tonic-gate #include <net/pfkeyv2.h>
447c478bd9Sstevel@tonic-gate #include <net/pfpolicy.h>
457c478bd9Sstevel@tonic-gate #include <libintl.h>
467c478bd9Sstevel@tonic-gate #include <setjmp.h>
477c478bd9Sstevel@tonic-gate #include <libgen.h>
48e3320f40Smarkfen #include <libscf.h>
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #include "ipsec_util.h"
517c478bd9Sstevel@tonic-gate #include "ikedoor.h"
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate /*
547c478bd9Sstevel@tonic-gate  * This file contains support functions that are shared by the ipsec
55bb3ed8dfSpwernau  * utilities and daemons including ipseckey(1m), ikeadm(1m) and in.iked(1m).
567c478bd9Sstevel@tonic-gate  */
577c478bd9Sstevel@tonic-gate 
58bb3ed8dfSpwernau 
59bb3ed8dfSpwernau #define	EFD(file) (((file) == stdout) ? stderr : (file))
60bb3ed8dfSpwernau 
61bfe6f8f5SVladimir Kotal /* Limits for interactive mode. */
62bfe6f8f5SVladimir Kotal #define	MAX_LINE_LEN	IBUF_SIZE
63bfe6f8f5SVladimir Kotal #define	MAX_CMD_HIST	64000	/* in bytes */
64bfe6f8f5SVladimir Kotal 
657c478bd9Sstevel@tonic-gate /* Set standard default/initial values for globals... */
667c478bd9Sstevel@tonic-gate boolean_t pflag = B_FALSE;	/* paranoid w.r.t. printing keying material */
677c478bd9Sstevel@tonic-gate boolean_t nflag = B_FALSE;	/* avoid nameservice? */
687c478bd9Sstevel@tonic-gate boolean_t interactive = B_FALSE;	/* util not running on cmdline */
697c478bd9Sstevel@tonic-gate boolean_t readfile = B_FALSE;	/* cmds are being read from a file */
707c478bd9Sstevel@tonic-gate uint_t	lineno = 0;		/* track location if reading cmds from file */
71e3320f40Smarkfen uint_t	lines_added = 0;
72e3320f40Smarkfen uint_t	lines_parsed = 0;
737c478bd9Sstevel@tonic-gate jmp_buf	env;		/* for error recovery in interactive/readfile modes */
74e3320f40Smarkfen char *my_fmri = NULL;
75e3320f40Smarkfen FILE *debugfile = stderr;
76bfe6f8f5SVladimir Kotal static GetLine *gl = NULL;	/* for interactive mode */
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate  * Print errno and exit if cmdline or readfile, reset state if interactive
80a7485808Smarkfen  * The error string *what should be dgettext()'d before calling bail().
817c478bd9Sstevel@tonic-gate  */
827c478bd9Sstevel@tonic-gate void
bail(char * what)837c478bd9Sstevel@tonic-gate bail(char *what)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate 	if (errno != 0)
867c478bd9Sstevel@tonic-gate 		warn(what);
877c478bd9Sstevel@tonic-gate 	else
88e3320f40Smarkfen 		warnx(dgettext(TEXT_DOMAIN, "Error: %s"), what);
897c478bd9Sstevel@tonic-gate 	if (readfile) {
90e3320f40Smarkfen 		return;
917c478bd9Sstevel@tonic-gate 	}
927c478bd9Sstevel@tonic-gate 	if (interactive && !readfile)
937c478bd9Sstevel@tonic-gate 		longjmp(env, 2);
94e3320f40Smarkfen 	EXIT_FATAL(NULL);
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate  * Print caller-supplied variable-arg error msg, then exit if cmdline or
997c478bd9Sstevel@tonic-gate  * readfile, or reset state if interactive.
1007c478bd9Sstevel@tonic-gate  */
1017c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/
1027c478bd9Sstevel@tonic-gate void
bail_msg(char * fmt,...)1037c478bd9Sstevel@tonic-gate bail_msg(char *fmt, ...)
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate 	va_list	ap;
1067c478bd9Sstevel@tonic-gate 	char	msgbuf[BUFSIZ];
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	va_start(ap, fmt);
1097c478bd9Sstevel@tonic-gate 	(void) vsnprintf(msgbuf, BUFSIZ, fmt, ap);
1107c478bd9Sstevel@tonic-gate 	va_end(ap);
1117c478bd9Sstevel@tonic-gate 	if (readfile)
112a7485808Smarkfen 		warnx(dgettext(TEXT_DOMAIN,
113a7485808Smarkfen 		    "ERROR on line %u:\n%s\n"), lineno,  msgbuf);
1147c478bd9Sstevel@tonic-gate 	else
115a7485808Smarkfen 		warnx(dgettext(TEXT_DOMAIN, "ERROR: %s\n"), msgbuf);
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	if (interactive && !readfile)
1187c478bd9Sstevel@tonic-gate 		longjmp(env, 1);
1197c478bd9Sstevel@tonic-gate 
120e3320f40Smarkfen 	EXIT_FATAL(NULL);
1217c478bd9Sstevel@tonic-gate }
1227c478bd9Sstevel@tonic-gate 
123510c3f91SVladimir Kotal /*
124510c3f91SVladimir Kotal  * bytecnt2str() wrapper. Zeroes out the input buffer and if the number
125510c3f91SVladimir Kotal  * of bytes to be converted is more than 1K, it will produce readable string
126510c3f91SVladimir Kotal  * in parentheses, store it in the original buffer and return the pointer to it.
127510c3f91SVladimir Kotal  * Maximum length of the returned string is 14 characters (not including
128510c3f91SVladimir Kotal  * the terminating zero).
129510c3f91SVladimir Kotal  */
130510c3f91SVladimir Kotal char *
bytecnt2out(uint64_t num,char * buf,size_t bufsiz,int flags)131510c3f91SVladimir Kotal bytecnt2out(uint64_t num, char *buf, size_t bufsiz, int flags)
132510c3f91SVladimir Kotal {
133510c3f91SVladimir Kotal 	char *str;
134510c3f91SVladimir Kotal 
135510c3f91SVladimir Kotal 	(void) memset(buf, '\0', bufsiz);
136510c3f91SVladimir Kotal 
137510c3f91SVladimir Kotal 	if (num > 1024) {
138510c3f91SVladimir Kotal 		/* Return empty string in case of out-of-memory. */
139510c3f91SVladimir Kotal 		if ((str = malloc(bufsiz)) == NULL)
140510c3f91SVladimir Kotal 			return (buf);
141510c3f91SVladimir Kotal 
142510c3f91SVladimir Kotal 		(void) bytecnt2str(num, str, bufsiz);
143510c3f91SVladimir Kotal 		/* Detect overflow. */
144510c3f91SVladimir Kotal 		if (strlen(str) == 0) {
145510c3f91SVladimir Kotal 			free(str);
146510c3f91SVladimir Kotal 			return (buf);
147510c3f91SVladimir Kotal 		}
148510c3f91SVladimir Kotal 
149510c3f91SVladimir Kotal 		/* Emit nothing in case of overflow. */
150510c3f91SVladimir Kotal 		if (snprintf(buf, bufsiz, "%s(%sB)%s",
151510c3f91SVladimir Kotal 		    flags & SPC_BEGIN ? " " : "", str,
152510c3f91SVladimir Kotal 		    flags & SPC_END ? " " : "") >= bufsiz)
153510c3f91SVladimir Kotal 			(void) memset(buf, '\0', bufsiz);
154510c3f91SVladimir Kotal 
155510c3f91SVladimir Kotal 		free(str);
156510c3f91SVladimir Kotal 	}
157510c3f91SVladimir Kotal 
158510c3f91SVladimir Kotal 	return (buf);
159510c3f91SVladimir Kotal }
160510c3f91SVladimir Kotal 
161510c3f91SVladimir Kotal /*
162510c3f91SVladimir Kotal  * Convert 64-bit number to human readable string. Useful mainly for the
163510c3f91SVladimir Kotal  * byte lifetime counters. Returns pointer to the user supplied buffer.
164510c3f91SVladimir Kotal  * Able to convert up to Exabytes. Maximum length of the string produced
165510c3f91SVladimir Kotal  * is 9 characters (not counting the terminating zero).
166510c3f91SVladimir Kotal  */
167510c3f91SVladimir Kotal char *
bytecnt2str(uint64_t num,char * buf,size_t buflen)168510c3f91SVladimir Kotal bytecnt2str(uint64_t num, char *buf, size_t buflen)
169510c3f91SVladimir Kotal {
170510c3f91SVladimir Kotal 	uint64_t n = num;
171510c3f91SVladimir Kotal 	char u;
172510c3f91SVladimir Kotal 	int index = 0;
173510c3f91SVladimir Kotal 
174510c3f91SVladimir Kotal 	while (n >= 1024) {
175510c3f91SVladimir Kotal 		n /= 1024;
176510c3f91SVladimir Kotal 		index++;
177510c3f91SVladimir Kotal 	}
178510c3f91SVladimir Kotal 
179510c3f91SVladimir Kotal 	/* The field has all units this function can represent. */
180510c3f91SVladimir Kotal 	u = " KMGTPE"[index];
181510c3f91SVladimir Kotal 
182510c3f91SVladimir Kotal 	if (index == 0) {
183510c3f91SVladimir Kotal 		/* Less than 1K */
184510c3f91SVladimir Kotal 		if (snprintf(buf, buflen, "%llu ", num) >= buflen)
185510c3f91SVladimir Kotal 			(void) memset(buf, '\0', buflen);
186510c3f91SVladimir Kotal 	} else {
187510c3f91SVladimir Kotal 		/* Otherwise display 2 precision digits. */
188510c3f91SVladimir Kotal 		if (snprintf(buf, buflen, "%.2f %c",
189510c3f91SVladimir Kotal 		    (double)num / (1ULL << index * 10), u) >= buflen)
190510c3f91SVladimir Kotal 			(void) memset(buf, '\0', buflen);
191510c3f91SVladimir Kotal 	}
192510c3f91SVladimir Kotal 
193510c3f91SVladimir Kotal 	return (buf);
194510c3f91SVladimir Kotal }
195510c3f91SVladimir Kotal 
196510c3f91SVladimir Kotal /*
197510c3f91SVladimir Kotal  * secs2str() wrapper. Zeroes out the input buffer and if the number of
198510c3f91SVladimir Kotal  * seconds to be converted is more than minute, it will produce readable
199510c3f91SVladimir Kotal  * string in parentheses, store it in the original buffer and return the
200510c3f91SVladimir Kotal  * pointer to it.
201510c3f91SVladimir Kotal  */
202510c3f91SVladimir Kotal char *
secs2out(unsigned int secs,char * buf,int bufsiz,int flags)203510c3f91SVladimir Kotal secs2out(unsigned int secs, char *buf, int bufsiz, int flags)
204510c3f91SVladimir Kotal {
205510c3f91SVladimir Kotal 	char *str;
206510c3f91SVladimir Kotal 
207510c3f91SVladimir Kotal 	(void) memset(buf, '\0', bufsiz);
208510c3f91SVladimir Kotal 
209510c3f91SVladimir Kotal 	if (secs > 60) {
210510c3f91SVladimir Kotal 		/* Return empty string in case of out-of-memory. */
211510c3f91SVladimir Kotal 		if ((str = malloc(bufsiz)) == NULL)
212510c3f91SVladimir Kotal 			return (buf);
213510c3f91SVladimir Kotal 
214510c3f91SVladimir Kotal 		(void) secs2str(secs, str, bufsiz);
215510c3f91SVladimir Kotal 		/* Detect overflow. */
216510c3f91SVladimir Kotal 		if (strlen(str) == 0) {
217510c3f91SVladimir Kotal 			free(str);
218510c3f91SVladimir Kotal 			return (buf);
219510c3f91SVladimir Kotal 		}
220510c3f91SVladimir Kotal 
221510c3f91SVladimir Kotal 		/* Emit nothing in case of overflow. */
222510c3f91SVladimir Kotal 		if (snprintf(buf, bufsiz, "%s(%s)%s",
223510c3f91SVladimir Kotal 		    flags & SPC_BEGIN ? " " : "", str,
224510c3f91SVladimir Kotal 		    flags & SPC_END ? " " : "") >= bufsiz)
225510c3f91SVladimir Kotal 			(void) memset(buf, '\0', bufsiz);
226510c3f91SVladimir Kotal 
227510c3f91SVladimir Kotal 		free(str);
228510c3f91SVladimir Kotal 	}
229510c3f91SVladimir Kotal 
230510c3f91SVladimir Kotal 	return (buf);
231510c3f91SVladimir Kotal }
232510c3f91SVladimir Kotal 
233510c3f91SVladimir Kotal /*
234510c3f91SVladimir Kotal  * Convert number of seconds to human readable string. Useful mainly for
235510c3f91SVladimir Kotal  * the lifetime counters. Returns pointer to the user supplied buffer.
236510c3f91SVladimir Kotal  * Able to convert up to days.
237510c3f91SVladimir Kotal  */
238510c3f91SVladimir Kotal char *
secs2str(unsigned int secs,char * buf,int bufsiz)239510c3f91SVladimir Kotal secs2str(unsigned int secs, char *buf, int bufsiz)
240510c3f91SVladimir Kotal {
241510c3f91SVladimir Kotal 	double val = secs;
242510c3f91SVladimir Kotal 	char *unit = "second";
243510c3f91SVladimir Kotal 
244510c3f91SVladimir Kotal 	if (val >= 24*60*60) {
245510c3f91SVladimir Kotal 		val /= 86400;
246510c3f91SVladimir Kotal 		unit = "day";
247510c3f91SVladimir Kotal 	} else if (val >= 60*60) {
248510c3f91SVladimir Kotal 		val /= 60*60;
249510c3f91SVladimir Kotal 		unit = "hour";
250510c3f91SVladimir Kotal 	} else if (val >= 60) {
251510c3f91SVladimir Kotal 		val /= 60;
252510c3f91SVladimir Kotal 		unit = "minute";
253510c3f91SVladimir Kotal 	}
254510c3f91SVladimir Kotal 
255510c3f91SVladimir Kotal 	/* Emit nothing in case of overflow. */
256510c3f91SVladimir Kotal 	if (snprintf(buf, bufsiz, "%.2f %s%s", val, unit,
257510c3f91SVladimir Kotal 	    val >= 2 ? "s" : "") >= bufsiz)
258510c3f91SVladimir Kotal 		(void) memset(buf, '\0', bufsiz);
259510c3f91SVladimir Kotal 
260510c3f91SVladimir Kotal 	return (buf);
261510c3f91SVladimir Kotal }
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate /*
2647c478bd9Sstevel@tonic-gate  * dump_XXX functions produce ASCII output from various structures.
2657c478bd9Sstevel@tonic-gate  *
2667c478bd9Sstevel@tonic-gate  * Because certain errors need to do this to stderr, dump_XXX functions
2677c478bd9Sstevel@tonic-gate  * take a FILE pointer.
2687c478bd9Sstevel@tonic-gate  *
2697c478bd9Sstevel@tonic-gate  * If an error occured while writing to the specified file, these
2707c478bd9Sstevel@tonic-gate  * functions return -1, zero otherwise.
2717c478bd9Sstevel@tonic-gate  */
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate int
dump_sockaddr(struct sockaddr * sa,uint8_t prefixlen,boolean_t addr_only,FILE * where,boolean_t ignore_nss)2748810c16bSdanmcd dump_sockaddr(struct sockaddr *sa, uint8_t prefixlen, boolean_t addr_only,
275bb3ed8dfSpwernau     FILE *where, boolean_t ignore_nss)
2767c478bd9Sstevel@tonic-gate {
2777c478bd9Sstevel@tonic-gate 	struct sockaddr_in	*sin;
2787c478bd9Sstevel@tonic-gate 	struct sockaddr_in6	*sin6;
2797c478bd9Sstevel@tonic-gate 	char			*printable_addr, *protocol;
2807c478bd9Sstevel@tonic-gate 	uint8_t			*addrptr;
2818810c16bSdanmcd 	/* Add 4 chars to hold '/nnn' for prefixes. */
2828810c16bSdanmcd 	char			storage[INET6_ADDRSTRLEN + 4];
2837c478bd9Sstevel@tonic-gate 	uint16_t		port;
2847c478bd9Sstevel@tonic-gate 	boolean_t		unspec;
2857c478bd9Sstevel@tonic-gate 	struct hostent		*hp;
2867c478bd9Sstevel@tonic-gate 	int			getipnode_errno, addrlen;
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate 	switch (sa->sa_family) {
2897c478bd9Sstevel@tonic-gate 	case AF_INET:
2907c478bd9Sstevel@tonic-gate 		/* LINTED E_BAD_PTR_CAST_ALIGN */
2917c478bd9Sstevel@tonic-gate 		sin = (struct sockaddr_in *)sa;
2927c478bd9Sstevel@tonic-gate 		addrptr = (uint8_t *)&sin->sin_addr;
2937c478bd9Sstevel@tonic-gate 		port = sin->sin_port;
2947c478bd9Sstevel@tonic-gate 		protocol = "AF_INET";
2957c478bd9Sstevel@tonic-gate 		unspec = (sin->sin_addr.s_addr == 0);
2967c478bd9Sstevel@tonic-gate 		addrlen = sizeof (sin->sin_addr);
2977c478bd9Sstevel@tonic-gate 		break;
2987c478bd9Sstevel@tonic-gate 	case AF_INET6:
2997c478bd9Sstevel@tonic-gate 		/* LINTED E_BAD_PTR_CAST_ALIGN */
3007c478bd9Sstevel@tonic-gate 		sin6 = (struct sockaddr_in6 *)sa;
3017c478bd9Sstevel@tonic-gate 		addrptr = (uint8_t *)&sin6->sin6_addr;
3027c478bd9Sstevel@tonic-gate 		port = sin6->sin6_port;
3037c478bd9Sstevel@tonic-gate 		protocol = "AF_INET6";
3047c478bd9Sstevel@tonic-gate 		unspec = IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr);
3057c478bd9Sstevel@tonic-gate 		addrlen = sizeof (sin6->sin6_addr);
3067c478bd9Sstevel@tonic-gate 		break;
3077c478bd9Sstevel@tonic-gate 	default:
3087c478bd9Sstevel@tonic-gate 		return (0);
3097c478bd9Sstevel@tonic-gate 	}
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	if (inet_ntop(sa->sa_family, addrptr, storage, INET6_ADDRSTRLEN) ==
3127c478bd9Sstevel@tonic-gate 	    NULL) {
313a7485808Smarkfen 		printable_addr = dgettext(TEXT_DOMAIN, "Invalid IP address.");
3147c478bd9Sstevel@tonic-gate 	} else {
3158810c16bSdanmcd 		char prefix[5];	/* "/nnn" with terminator. */
3168810c16bSdanmcd 
3178810c16bSdanmcd 		(void) snprintf(prefix, sizeof (prefix), "/%d", prefixlen);
3187c478bd9Sstevel@tonic-gate 		printable_addr = storage;
3198810c16bSdanmcd 		if (prefixlen != 0) {
3208810c16bSdanmcd 			(void) strlcat(printable_addr, prefix,
3218810c16bSdanmcd 			    sizeof (storage));
3228810c16bSdanmcd 		}
3237c478bd9Sstevel@tonic-gate 	}
3247c478bd9Sstevel@tonic-gate 	if (addr_only) {
3257c478bd9Sstevel@tonic-gate 		if (fprintf(where, "%s", printable_addr) < 0)
3267c478bd9Sstevel@tonic-gate 			return (-1);
3277c478bd9Sstevel@tonic-gate 	} else {
328a7485808Smarkfen 		if (fprintf(where, dgettext(TEXT_DOMAIN,
329a7485808Smarkfen 		    "%s: port %d, %s"), protocol,
3307c478bd9Sstevel@tonic-gate 		    ntohs(port), printable_addr) < 0)
3317c478bd9Sstevel@tonic-gate 			return (-1);
332bb3ed8dfSpwernau 		if (ignore_nss == B_FALSE) {
3337c478bd9Sstevel@tonic-gate 			/*
3347c478bd9Sstevel@tonic-gate 			 * Do AF_independent reverse hostname lookup here.
3357c478bd9Sstevel@tonic-gate 			 */
3367c478bd9Sstevel@tonic-gate 			if (unspec) {
3377c478bd9Sstevel@tonic-gate 				if (fprintf(where,
338a7485808Smarkfen 				    dgettext(TEXT_DOMAIN,
339a7485808Smarkfen 				    " <unspecified>")) < 0)
3407c478bd9Sstevel@tonic-gate 					return (-1);
3417c478bd9Sstevel@tonic-gate 			} else {
3427c478bd9Sstevel@tonic-gate 				hp = getipnodebyaddr((char *)addrptr, addrlen,
3437c478bd9Sstevel@tonic-gate 				    sa->sa_family, &getipnode_errno);
3447c478bd9Sstevel@tonic-gate 				if (hp != NULL) {
3457c478bd9Sstevel@tonic-gate 					if (fprintf(where,
3467c478bd9Sstevel@tonic-gate 					    " (%s)", hp->h_name) < 0)
3477c478bd9Sstevel@tonic-gate 						return (-1);
3487c478bd9Sstevel@tonic-gate 					freehostent(hp);
3497c478bd9Sstevel@tonic-gate 				} else {
3507c478bd9Sstevel@tonic-gate 					if (fprintf(where,
351a7485808Smarkfen 					    dgettext(TEXT_DOMAIN,
352a7485808Smarkfen 					    " <unknown>")) < 0)
3537c478bd9Sstevel@tonic-gate 						return (-1);
3547c478bd9Sstevel@tonic-gate 				}
3557c478bd9Sstevel@tonic-gate 			}
3567c478bd9Sstevel@tonic-gate 		}
3577c478bd9Sstevel@tonic-gate 		if (fputs(".\n", where) == EOF)
3587c478bd9Sstevel@tonic-gate 			return (-1);
3597c478bd9Sstevel@tonic-gate 	}
3607c478bd9Sstevel@tonic-gate 	return (0);
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate /*
364628b0c67SMark Fenwick  * Dump a key, any salt and bitlen.
365628b0c67SMark Fenwick  * The key is made up of a stream of bits. If the algorithm requires a salt
366628b0c67SMark Fenwick  * value, this will also be part of the dumped key. The last "saltbits" of the
367628b0c67SMark Fenwick  * key string, reading left to right will be the salt value. To make it easier
368628b0c67SMark Fenwick  * to see which bits make up the key, the salt value is enclosed in []'s.
369628b0c67SMark Fenwick  * This function can also be called when ipseckey(1m) -s is run, this "saves"
370628b0c67SMark Fenwick  * the SAs, including the key to a file. When this is the case, the []'s are
371628b0c67SMark Fenwick  * not printed.
372628b0c67SMark Fenwick  *
373628b0c67SMark Fenwick  * The implementation allows the kernel to be told about the length of the salt
374628b0c67SMark Fenwick  * in whole bytes only. If this changes, this function will need to be updated.
3757c478bd9Sstevel@tonic-gate  */
3767c478bd9Sstevel@tonic-gate int
dump_key(uint8_t * keyp,uint_t bitlen,uint_t saltbits,FILE * where,boolean_t separate_salt)377628b0c67SMark Fenwick dump_key(uint8_t *keyp, uint_t bitlen, uint_t saltbits, FILE *where,
378628b0c67SMark Fenwick     boolean_t separate_salt)
3797c478bd9Sstevel@tonic-gate {
380628b0c67SMark Fenwick 	int	numbytes, saltbytes;
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 	numbytes = SADB_1TO8(bitlen);
383628b0c67SMark Fenwick 	saltbytes = SADB_1TO8(saltbits);
384628b0c67SMark Fenwick 	numbytes += saltbytes;
385628b0c67SMark Fenwick 
3867c478bd9Sstevel@tonic-gate 	/* The & 0x7 is to check for leftover bits. */
3877c478bd9Sstevel@tonic-gate 	if ((bitlen & 0x7) != 0)
3887c478bd9Sstevel@tonic-gate 		numbytes++;
389628b0c67SMark Fenwick 
3907c478bd9Sstevel@tonic-gate 	while (numbytes-- != 0) {
3917c478bd9Sstevel@tonic-gate 		if (pflag) {
3927c478bd9Sstevel@tonic-gate 			/* Print no keys if paranoid */
3937c478bd9Sstevel@tonic-gate 			if (fprintf(where, "XX") < 0)
3947c478bd9Sstevel@tonic-gate 				return (-1);
3957c478bd9Sstevel@tonic-gate 		} else {
3967c478bd9Sstevel@tonic-gate 			if (fprintf(where, "%02x", *keyp++) < 0)
3977c478bd9Sstevel@tonic-gate 				return (-1);
3987c478bd9Sstevel@tonic-gate 		}
399628b0c67SMark Fenwick 		if (separate_salt && saltbytes != 0 &&
400628b0c67SMark Fenwick 		    numbytes == saltbytes) {
401628b0c67SMark Fenwick 			if (fprintf(where, "[") < 0)
4027c478bd9Sstevel@tonic-gate 				return (-1);
403628b0c67SMark Fenwick 		}
404628b0c67SMark Fenwick 	}
405628b0c67SMark Fenwick 
406628b0c67SMark Fenwick 	if (separate_salt && saltbits != 0) {
407628b0c67SMark Fenwick 		if (fprintf(where, "]/%u+%u", bitlen, saltbits) < 0)
408628b0c67SMark Fenwick 			return (-1);
409628b0c67SMark Fenwick 	} else {
410628b0c67SMark Fenwick 		if (fprintf(where, "/%u", bitlen + saltbits) < 0)
411628b0c67SMark Fenwick 			return (-1);
412628b0c67SMark Fenwick 	}
413628b0c67SMark Fenwick 
4147c478bd9Sstevel@tonic-gate 	return (0);
4157c478bd9Sstevel@tonic-gate }
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate /*
4187c478bd9Sstevel@tonic-gate  * Print an authentication or encryption algorithm
4197c478bd9Sstevel@tonic-gate  */
4207c478bd9Sstevel@tonic-gate static int
dump_generic_alg(uint8_t alg_num,int proto_num,FILE * where)4217c478bd9Sstevel@tonic-gate dump_generic_alg(uint8_t alg_num, int proto_num, FILE *where)
4227c478bd9Sstevel@tonic-gate {
4237c478bd9Sstevel@tonic-gate 	struct ipsecalgent *alg;
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate 	alg = getipsecalgbynum(alg_num, proto_num, NULL);
4267c478bd9Sstevel@tonic-gate 	if (alg == NULL) {
427a7485808Smarkfen 		if (fprintf(where, dgettext(TEXT_DOMAIN,
428a7485808Smarkfen 		    "<unknown %u>"), alg_num) < 0)
4297c478bd9Sstevel@tonic-gate 			return (-1);
4307c478bd9Sstevel@tonic-gate 		return (0);
4317c478bd9Sstevel@tonic-gate 	}
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	/*
4347c478bd9Sstevel@tonic-gate 	 * Special-case <none> for backward output compat.
4357c478bd9Sstevel@tonic-gate 	 * Assume that SADB_AALG_NONE == SADB_EALG_NONE.
4367c478bd9Sstevel@tonic-gate 	 */
4377c478bd9Sstevel@tonic-gate 	if (alg_num == SADB_AALG_NONE) {
438a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN,
439a7485808Smarkfen 		    "<none>"), where) == EOF)
4407c478bd9Sstevel@tonic-gate 			return (-1);
4417c478bd9Sstevel@tonic-gate 	} else {
4427c478bd9Sstevel@tonic-gate 		if (fputs(alg->a_names[0], where) == EOF)
4437c478bd9Sstevel@tonic-gate 			return (-1);
4447c478bd9Sstevel@tonic-gate 	}
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate 	freeipsecalgent(alg);
4477c478bd9Sstevel@tonic-gate 	return (0);
4487c478bd9Sstevel@tonic-gate }
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate int
dump_aalg(uint8_t aalg,FILE * where)4517c478bd9Sstevel@tonic-gate dump_aalg(uint8_t aalg, FILE *where)
4527c478bd9Sstevel@tonic-gate {
4537c478bd9Sstevel@tonic-gate 	return (dump_generic_alg(aalg, IPSEC_PROTO_AH, where));
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate int
dump_ealg(uint8_t ealg,FILE * where)4577c478bd9Sstevel@tonic-gate dump_ealg(uint8_t ealg, FILE *where)
4587c478bd9Sstevel@tonic-gate {
4597c478bd9Sstevel@tonic-gate 	return (dump_generic_alg(ealg, IPSEC_PROTO_ESP, where));
4607c478bd9Sstevel@tonic-gate }
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate /*
4637c478bd9Sstevel@tonic-gate  * Print an SADB_IDENTTYPE string
4647c478bd9Sstevel@tonic-gate  *
4657c478bd9Sstevel@tonic-gate  * Also return TRUE if the actual ident may be printed, FALSE if not.
4667c478bd9Sstevel@tonic-gate  *
4677c478bd9Sstevel@tonic-gate  * If rc is not NULL, set its value to -1 if an error occured while writing
4687c478bd9Sstevel@tonic-gate  * to the specified file, zero otherwise.
4697c478bd9Sstevel@tonic-gate  */
4707c478bd9Sstevel@tonic-gate boolean_t
dump_sadb_idtype(uint8_t idtype,FILE * where,int * rc)4717c478bd9Sstevel@tonic-gate dump_sadb_idtype(uint8_t idtype, FILE *where, int *rc)
4727c478bd9Sstevel@tonic-gate {
4737c478bd9Sstevel@tonic-gate 	boolean_t canprint = B_TRUE;
4747c478bd9Sstevel@tonic-gate 	int rc_val = 0;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	switch (idtype) {
4777c478bd9Sstevel@tonic-gate 	case SADB_IDENTTYPE_PREFIX:
478a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN, "prefix"), where) == EOF)
4797c478bd9Sstevel@tonic-gate 			rc_val = -1;
4807c478bd9Sstevel@tonic-gate 		break;
4817c478bd9Sstevel@tonic-gate 	case SADB_IDENTTYPE_FQDN:
482a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN, "FQDN"), where) == EOF)
4837c478bd9Sstevel@tonic-gate 			rc_val = -1;
4847c478bd9Sstevel@tonic-gate 		break;
4857c478bd9Sstevel@tonic-gate 	case SADB_IDENTTYPE_USER_FQDN:
486a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN,
487a7485808Smarkfen 		    "user-FQDN (mbox)"), where) == EOF)
4887c478bd9Sstevel@tonic-gate 			rc_val = -1;
4897c478bd9Sstevel@tonic-gate 		break;
4907c478bd9Sstevel@tonic-gate 	case SADB_X_IDENTTYPE_DN:
491a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN, "ASN.1 DER Distinguished Name"),
4927c478bd9Sstevel@tonic-gate 		    where) == EOF)
4937c478bd9Sstevel@tonic-gate 			rc_val = -1;
4947c478bd9Sstevel@tonic-gate 		canprint = B_FALSE;
4957c478bd9Sstevel@tonic-gate 		break;
4967c478bd9Sstevel@tonic-gate 	case SADB_X_IDENTTYPE_GN:
497a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN, "ASN.1 DER Generic Name"),
498a7485808Smarkfen 		    where) == EOF)
4997c478bd9Sstevel@tonic-gate 			rc_val = -1;
5007c478bd9Sstevel@tonic-gate 		canprint = B_FALSE;
5017c478bd9Sstevel@tonic-gate 		break;
5027c478bd9Sstevel@tonic-gate 	case SADB_X_IDENTTYPE_KEY_ID:
503a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN, "Generic key id"),
504a7485808Smarkfen 		    where) == EOF)
5057c478bd9Sstevel@tonic-gate 			rc_val = -1;
5067c478bd9Sstevel@tonic-gate 		break;
5077c478bd9Sstevel@tonic-gate 	case SADB_X_IDENTTYPE_ADDR_RANGE:
508a7485808Smarkfen 		if (fputs(dgettext(TEXT_DOMAIN, "Address range"), where) == EOF)
5097c478bd9Sstevel@tonic-gate 			rc_val = -1;
5107c478bd9Sstevel@tonic-gate 		break;
5117c478bd9Sstevel@tonic-gate 	default:
512a7485808Smarkfen 		if (fprintf(where, dgettext(TEXT_DOMAIN,
513a7485808Smarkfen 		    "<unknown %u>"), idtype) < 0)
5147c478bd9Sstevel@tonic-gate 			rc_val = -1;
5157c478bd9Sstevel@tonic-gate 		break;
5167c478bd9Sstevel@tonic-gate 	}
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	if (rc != NULL)
5197c478bd9Sstevel@tonic-gate 		*rc = rc_val;
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	return (canprint);
5227c478bd9Sstevel@tonic-gate }
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate /*
5257c478bd9Sstevel@tonic-gate  * Slice an argv/argc vector from an interactive line or a read-file line.
5267c478bd9Sstevel@tonic-gate  */
5277c478bd9Sstevel@tonic-gate static int
create_argv(char * ibuf,int * newargc,char *** thisargv)5287c478bd9Sstevel@tonic-gate create_argv(char *ibuf, int *newargc, char ***thisargv)
5297c478bd9Sstevel@tonic-gate {
5307c478bd9Sstevel@tonic-gate 	unsigned int argvlen = START_ARG;
5317c478bd9Sstevel@tonic-gate 	char **current;
5327c478bd9Sstevel@tonic-gate 	boolean_t firstchar = B_TRUE;
5337c478bd9Sstevel@tonic-gate 	boolean_t inquotes = B_FALSE;
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 	*thisargv = malloc(sizeof (char *) * argvlen);
5367c478bd9Sstevel@tonic-gate 	if ((*thisargv) == NULL)
5377c478bd9Sstevel@tonic-gate 		return (MEMORY_ALLOCATION);
5387c478bd9Sstevel@tonic-gate 	current = *thisargv;
5397c478bd9Sstevel@tonic-gate 	*current = NULL;
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	for (; *ibuf != '\0'; ibuf++) {
5427c478bd9Sstevel@tonic-gate 		if (isspace(*ibuf)) {
5437c478bd9Sstevel@tonic-gate 			if (inquotes) {
5447c478bd9Sstevel@tonic-gate 				continue;
5457c478bd9Sstevel@tonic-gate 			}
5467c478bd9Sstevel@tonic-gate 			if (*current != NULL) {
5477c478bd9Sstevel@tonic-gate 				*ibuf = '\0';
5487c478bd9Sstevel@tonic-gate 				current++;
5497c478bd9Sstevel@tonic-gate 				if (*thisargv + argvlen == current) {
5507c478bd9Sstevel@tonic-gate 					/* Regrow ***thisargv. */
5517c478bd9Sstevel@tonic-gate 					if (argvlen == TOO_MANY_ARGS) {
5527c478bd9Sstevel@tonic-gate 						free(*thisargv);
5537c478bd9Sstevel@tonic-gate 						return (TOO_MANY_TOKENS);
5547c478bd9Sstevel@tonic-gate 					}
5557c478bd9Sstevel@tonic-gate 					/* Double the allocation. */
5567c478bd9Sstevel@tonic-gate 					current = realloc(*thisargv,
5577c478bd9Sstevel@tonic-gate 					    sizeof (char *) * (argvlen << 1));
5587c478bd9Sstevel@tonic-gate 					if (current == NULL) {
5597c478bd9Sstevel@tonic-gate 						free(*thisargv);
5607c478bd9Sstevel@tonic-gate 						return (MEMORY_ALLOCATION);
5617c478bd9Sstevel@tonic-gate 					}
5627c478bd9Sstevel@tonic-gate 					*thisargv = current;
5637c478bd9Sstevel@tonic-gate 					current += argvlen;
5647c478bd9Sstevel@tonic-gate 					argvlen <<= 1;	/* Double the size. */
5657c478bd9Sstevel@tonic-gate 				}
5667c478bd9Sstevel@tonic-gate 				*current = NULL;
5677c478bd9Sstevel@tonic-gate 			}
5687c478bd9Sstevel@tonic-gate 		} else {
5697c478bd9Sstevel@tonic-gate 			if (firstchar) {
5707c478bd9Sstevel@tonic-gate 				firstchar = B_FALSE;
571e3320f40Smarkfen 				if (*ibuf == COMMENT_CHAR || *ibuf == '\n') {
5727c478bd9Sstevel@tonic-gate 					free(*thisargv);
5737c478bd9Sstevel@tonic-gate 					return (COMMENT_LINE);
5747c478bd9Sstevel@tonic-gate 				}
5757c478bd9Sstevel@tonic-gate 			}
5767c478bd9Sstevel@tonic-gate 			if (*ibuf == QUOTE_CHAR) {
5777c478bd9Sstevel@tonic-gate 				if (inquotes) {
5787c478bd9Sstevel@tonic-gate 					inquotes = B_FALSE;
5797c478bd9Sstevel@tonic-gate 					*ibuf = '\0';
5807c478bd9Sstevel@tonic-gate 				} else {
5817c478bd9Sstevel@tonic-gate 					inquotes = B_TRUE;
5827c478bd9Sstevel@tonic-gate 				}
5837c478bd9Sstevel@tonic-gate 				continue;
5847c478bd9Sstevel@tonic-gate 			}
5857c478bd9Sstevel@tonic-gate 			if (*current == NULL) {
5867c478bd9Sstevel@tonic-gate 				*current = ibuf;
5877c478bd9Sstevel@tonic-gate 				(*newargc)++;
5887c478bd9Sstevel@tonic-gate 			}
5897c478bd9Sstevel@tonic-gate 		}
5907c478bd9Sstevel@tonic-gate 	}
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 	/*
5937c478bd9Sstevel@tonic-gate 	 * Tricky corner case...
5947c478bd9Sstevel@tonic-gate 	 * I've parsed _exactly_ the amount of args as I have space.  It
5957c478bd9Sstevel@tonic-gate 	 * won't return NULL-terminated, and bad things will happen to
5967c478bd9Sstevel@tonic-gate 	 * the caller.
5977c478bd9Sstevel@tonic-gate 	 */
5987c478bd9Sstevel@tonic-gate 	if (argvlen == *newargc) {
5997c478bd9Sstevel@tonic-gate 		current = realloc(*thisargv, sizeof (char *) * (argvlen + 1));
6007c478bd9Sstevel@tonic-gate 		if (current == NULL) {
6017c478bd9Sstevel@tonic-gate 			free(*thisargv);
6027c478bd9Sstevel@tonic-gate 			return (MEMORY_ALLOCATION);
6037c478bd9Sstevel@tonic-gate 		}
6047c478bd9Sstevel@tonic-gate 		*thisargv = current;
6057c478bd9Sstevel@tonic-gate 		current[argvlen] = NULL;
6067c478bd9Sstevel@tonic-gate 	}
6077c478bd9Sstevel@tonic-gate 
6087c478bd9Sstevel@tonic-gate 	return (SUCCESS);
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate 
6117c478bd9Sstevel@tonic-gate /*
612bfe6f8f5SVladimir Kotal  * init interactive mode if needed and not yet initialized
613bfe6f8f5SVladimir Kotal  */
614bfe6f8f5SVladimir Kotal static void
init_interactive(FILE * infile,CplMatchFn * match_fn)615bfe6f8f5SVladimir Kotal init_interactive(FILE *infile, CplMatchFn *match_fn)
616bfe6f8f5SVladimir Kotal {
617bfe6f8f5SVladimir Kotal 	if (infile == stdin) {
618bfe6f8f5SVladimir Kotal 		if (gl == NULL) {
619bfe6f8f5SVladimir Kotal 			if ((gl = new_GetLine(MAX_LINE_LEN,
620bfe6f8f5SVladimir Kotal 			    MAX_CMD_HIST)) == NULL)
621bfe6f8f5SVladimir Kotal 				errx(1, dgettext(TEXT_DOMAIN,
622bfe6f8f5SVladimir Kotal 				    "tecla initialization failed"));
623bfe6f8f5SVladimir Kotal 
624bfe6f8f5SVladimir Kotal 			if (gl_customize_completion(gl, NULL,
625bfe6f8f5SVladimir Kotal 			    match_fn) != 0) {
626bfe6f8f5SVladimir Kotal 				(void) del_GetLine(gl);
627bfe6f8f5SVladimir Kotal 				errx(1, dgettext(TEXT_DOMAIN,
628bfe6f8f5SVladimir Kotal 				    "tab completion failed to initialize"));
629bfe6f8f5SVladimir Kotal 			}
630bfe6f8f5SVladimir Kotal 
631bfe6f8f5SVladimir Kotal 			/*
632bfe6f8f5SVladimir Kotal 			 * In interactive mode we only want to terminate
633bfe6f8f5SVladimir Kotal 			 * when explicitly requested (e.g. by a command).
634bfe6f8f5SVladimir Kotal 			 */
635bfe6f8f5SVladimir Kotal 			(void) sigset(SIGINT, SIG_IGN);
636bfe6f8f5SVladimir Kotal 		}
637bfe6f8f5SVladimir Kotal 	} else {
638bfe6f8f5SVladimir Kotal 		readfile = B_TRUE;
639bfe6f8f5SVladimir Kotal 	}
640bfe6f8f5SVladimir Kotal }
641bfe6f8f5SVladimir Kotal 
642bfe6f8f5SVladimir Kotal /*
643bfe6f8f5SVladimir Kotal  * free tecla data structure
644bfe6f8f5SVladimir Kotal  */
645bfe6f8f5SVladimir Kotal static void
fini_interactive(void)646bfe6f8f5SVladimir Kotal fini_interactive(void)
647bfe6f8f5SVladimir Kotal {
648bfe6f8f5SVladimir Kotal 	if (gl != NULL)
649bfe6f8f5SVladimir Kotal 		(void) del_GetLine(gl);
650bfe6f8f5SVladimir Kotal }
651bfe6f8f5SVladimir Kotal 
652bfe6f8f5SVladimir Kotal /*
653bfe6f8f5SVladimir Kotal  * Get single input line, wrapping around interactive and non-interactive
654bfe6f8f5SVladimir Kotal  * mode.
655bfe6f8f5SVladimir Kotal  */
656bfe6f8f5SVladimir Kotal static char *
do_getstr(FILE * infile,char * prompt,char * ibuf,size_t ibuf_size)657bfe6f8f5SVladimir Kotal do_getstr(FILE *infile, char *prompt, char *ibuf, size_t ibuf_size)
658bfe6f8f5SVladimir Kotal {
659bfe6f8f5SVladimir Kotal 	char	*line;
660bfe6f8f5SVladimir Kotal 
661bfe6f8f5SVladimir Kotal 	if (infile != stdin)
662bfe6f8f5SVladimir Kotal 		return (fgets(ibuf, ibuf_size, infile));
663bfe6f8f5SVladimir Kotal 
664bfe6f8f5SVladimir Kotal 	/*
665bfe6f8f5SVladimir Kotal 	 * If the user hits ^C then we want to catch it and
666bfe6f8f5SVladimir Kotal 	 * start over.  If the user hits EOF then we want to
667bfe6f8f5SVladimir Kotal 	 * bail out.
668bfe6f8f5SVladimir Kotal 	 */
669bfe6f8f5SVladimir Kotal once_again:
670bfe6f8f5SVladimir Kotal 	line = gl_get_line(gl, prompt, NULL, -1);
671bfe6f8f5SVladimir Kotal 	if (gl_return_status(gl) == GLR_SIGNAL) {
672bfe6f8f5SVladimir Kotal 		gl_abandon_line(gl);
673bfe6f8f5SVladimir Kotal 		goto once_again;
674bfe6f8f5SVladimir Kotal 	} else if (gl_return_status(gl) == GLR_ERROR) {
675bfe6f8f5SVladimir Kotal 		gl_abandon_line(gl);
676bfe6f8f5SVladimir Kotal 		errx(1, dgettext(TEXT_DOMAIN, "Error reading terminal: %s\n"),
677bfe6f8f5SVladimir Kotal 		    gl_error_message(gl, NULL, 0));
678bfe6f8f5SVladimir Kotal 	} else {
679bfe6f8f5SVladimir Kotal 		if (line != NULL) {
680bfe6f8f5SVladimir Kotal 			if (strlcpy(ibuf, line, ibuf_size) >= ibuf_size)
681bfe6f8f5SVladimir Kotal 				warnx(dgettext(TEXT_DOMAIN,
682bfe6f8f5SVladimir Kotal 				    "Line too long (max=%d chars)"),
683bfe6f8f5SVladimir Kotal 				    ibuf_size);
684bfe6f8f5SVladimir Kotal 			line = ibuf;
685bfe6f8f5SVladimir Kotal 		}
686bfe6f8f5SVladimir Kotal 	}
687bfe6f8f5SVladimir Kotal 
688bfe6f8f5SVladimir Kotal 	return (line);
689bfe6f8f5SVladimir Kotal }
690bfe6f8f5SVladimir Kotal 
691bfe6f8f5SVladimir Kotal /*
6927c478bd9Sstevel@tonic-gate  * Enter a mode where commands are read from a file.  Treat stdin special.
6937c478bd9Sstevel@tonic-gate  */
6947c478bd9Sstevel@tonic-gate void
do_interactive(FILE * infile,char * configfile,char * promptstring,char * my_fmri,parse_cmdln_fn parseit,CplMatchFn * match_fn)695e3320f40Smarkfen do_interactive(FILE *infile, char *configfile, char *promptstring,
696bfe6f8f5SVladimir Kotal     char *my_fmri, parse_cmdln_fn parseit, CplMatchFn *match_fn)
6977c478bd9Sstevel@tonic-gate {
6987c478bd9Sstevel@tonic-gate 	char		ibuf[IBUF_SIZE], holder[IBUF_SIZE];
699e3320f40Smarkfen 	char		*hptr, **thisargv, *ebuf;
7007c478bd9Sstevel@tonic-gate 	int		thisargc;
7017c478bd9Sstevel@tonic-gate 	boolean_t	continue_in_progress = B_FALSE;
702bfe6f8f5SVladimir Kotal 	char		*s;
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	(void) setjmp(env);
7057c478bd9Sstevel@tonic-gate 
706e3320f40Smarkfen 	ebuf = NULL;
7077c478bd9Sstevel@tonic-gate 	interactive = B_TRUE;
7087c478bd9Sstevel@tonic-gate 	bzero(ibuf, IBUF_SIZE);
7097c478bd9Sstevel@tonic-gate 
710bfe6f8f5SVladimir Kotal 	/* panics for us */
711bfe6f8f5SVladimir Kotal 	init_interactive(infile, match_fn);
7127c478bd9Sstevel@tonic-gate 
713bfe6f8f5SVladimir Kotal 	while ((s = do_getstr(infile, promptstring, ibuf, IBUF_SIZE)) != NULL) {
7147c478bd9Sstevel@tonic-gate 		if (readfile)
7157c478bd9Sstevel@tonic-gate 			lineno++;
7167c478bd9Sstevel@tonic-gate 		thisargc = 0;
7177c478bd9Sstevel@tonic-gate 		thisargv = NULL;
7187c478bd9Sstevel@tonic-gate 
7197c478bd9Sstevel@tonic-gate 		/*
7207c478bd9Sstevel@tonic-gate 		 * Check byte IBUF_SIZE - 2, because byte IBUF_SIZE - 1 will
7217c478bd9Sstevel@tonic-gate 		 * be null-terminated because of fgets().
7227c478bd9Sstevel@tonic-gate 		 */
7237c478bd9Sstevel@tonic-gate 		if (ibuf[IBUF_SIZE - 2] != '\0') {
724bfe6f8f5SVladimir Kotal 			if (infile == stdin) {
725bfe6f8f5SVladimir Kotal 				/* do_getstr() issued a warning already */
726bfe6f8f5SVladimir Kotal 				bzero(ibuf, IBUF_SIZE);
727bfe6f8f5SVladimir Kotal 				continue;
728bfe6f8f5SVladimir Kotal 			} else {
729bfe6f8f5SVladimir Kotal 				ipsecutil_exit(SERVICE_FATAL, my_fmri,
730bfe6f8f5SVladimir Kotal 				    debugfile, dgettext(TEXT_DOMAIN,
731bfe6f8f5SVladimir Kotal 				    "Line %d too big."), lineno);
732bfe6f8f5SVladimir Kotal 			}
7337c478bd9Sstevel@tonic-gate 		}
7347c478bd9Sstevel@tonic-gate 
7357c478bd9Sstevel@tonic-gate 		if (!continue_in_progress) {
7367c478bd9Sstevel@tonic-gate 			/* Use -2 because of \n from fgets. */
7377c478bd9Sstevel@tonic-gate 			if (ibuf[strlen(ibuf) - 2] == CONT_CHAR) {
7387c478bd9Sstevel@tonic-gate 				/*
7397c478bd9Sstevel@tonic-gate 				 * Can use strcpy here, I've checked the
7407c478bd9Sstevel@tonic-gate 				 * length already.
7417c478bd9Sstevel@tonic-gate 				 */
7427c478bd9Sstevel@tonic-gate 				(void) strcpy(holder, ibuf);
7437c478bd9Sstevel@tonic-gate 				hptr = &(holder[strlen(holder)]);
7447c478bd9Sstevel@tonic-gate 
7457c478bd9Sstevel@tonic-gate 				/* Remove the CONT_CHAR from the string. */
7467c478bd9Sstevel@tonic-gate 				hptr[-2] = ' ';
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 				continue_in_progress = B_TRUE;
7497c478bd9Sstevel@tonic-gate 				bzero(ibuf, IBUF_SIZE);
7507c478bd9Sstevel@tonic-gate 				continue;
7517c478bd9Sstevel@tonic-gate 			}
7527c478bd9Sstevel@tonic-gate 		} else {
7537c478bd9Sstevel@tonic-gate 			/* Handle continuations... */
7547c478bd9Sstevel@tonic-gate 			(void) strncpy(hptr, ibuf,
7557c478bd9Sstevel@tonic-gate 			    (size_t)(&(holder[IBUF_SIZE]) - hptr));
7567c478bd9Sstevel@tonic-gate 			if (holder[IBUF_SIZE - 1] != '\0') {
757e3320f40Smarkfen 				ipsecutil_exit(SERVICE_FATAL, my_fmri,
758e3320f40Smarkfen 				    debugfile, dgettext(TEXT_DOMAIN,
759e3320f40Smarkfen 				    "Command buffer overrun."));
7607c478bd9Sstevel@tonic-gate 			}
7617c478bd9Sstevel@tonic-gate 			/* Use - 2 because of \n from fgets. */
7627c478bd9Sstevel@tonic-gate 			if (hptr[strlen(hptr) - 2] == CONT_CHAR) {
7637c478bd9Sstevel@tonic-gate 				bzero(ibuf, IBUF_SIZE);
7647c478bd9Sstevel@tonic-gate 				hptr += strlen(hptr);
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 				/* Remove the CONT_CHAR from the string. */
7677c478bd9Sstevel@tonic-gate 				hptr[-2] = ' ';
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate 				continue;
7707c478bd9Sstevel@tonic-gate 			} else {
7717c478bd9Sstevel@tonic-gate 				continue_in_progress = B_FALSE;
7727c478bd9Sstevel@tonic-gate 				/*
7737c478bd9Sstevel@tonic-gate 				 * I've already checked the length...
7747c478bd9Sstevel@tonic-gate 				 */
7757c478bd9Sstevel@tonic-gate 				(void) strcpy(ibuf, holder);
7767c478bd9Sstevel@tonic-gate 			}
7777c478bd9Sstevel@tonic-gate 		}
7787c478bd9Sstevel@tonic-gate 
779e3320f40Smarkfen 		/*
780e3320f40Smarkfen 		 * Just in case the command fails keep a copy of the
781e3320f40Smarkfen 		 * command buffer for diagnostic output.
782e3320f40Smarkfen 		 */
783e3320f40Smarkfen 		if (readfile) {
784e3320f40Smarkfen 			/*
785e3320f40Smarkfen 			 * The error buffer needs to be big enough to
786e3320f40Smarkfen 			 * hold the longest command string, plus
787e3320f40Smarkfen 			 * some extra text, see below.
788e3320f40Smarkfen 			 */
789e3320f40Smarkfen 			ebuf = calloc((IBUF_SIZE * 2), sizeof (char));
790e3320f40Smarkfen 			if (ebuf == NULL) {
791e3320f40Smarkfen 				ipsecutil_exit(SERVICE_FATAL, my_fmri,
792e3320f40Smarkfen 				    debugfile, dgettext(TEXT_DOMAIN,
793e3320f40Smarkfen 				    "Memory allocation error."));
794e3320f40Smarkfen 			} else {
795e3320f40Smarkfen 				(void) snprintf(ebuf, (IBUF_SIZE * 2),
796e3320f40Smarkfen 				    dgettext(TEXT_DOMAIN,
797e3320f40Smarkfen 				    "Config file entry near line %u "
798e3320f40Smarkfen 				    "caused error(s) or warnings:\n\n%s\n\n"),
799e3320f40Smarkfen 				    lineno, ibuf);
800e3320f40Smarkfen 			}
801e3320f40Smarkfen 		}
802e3320f40Smarkfen 
8037c478bd9Sstevel@tonic-gate 		switch (create_argv(ibuf, &thisargc, &thisargv)) {
8047c478bd9Sstevel@tonic-gate 		case TOO_MANY_TOKENS:
805e3320f40Smarkfen 			ipsecutil_exit(SERVICE_BADCONF, my_fmri, debugfile,
806e3320f40Smarkfen 			    dgettext(TEXT_DOMAIN, "Too many input tokens."));
8077c478bd9Sstevel@tonic-gate 			break;
8087c478bd9Sstevel@tonic-gate 		case MEMORY_ALLOCATION:
809e3320f40Smarkfen 			ipsecutil_exit(SERVICE_BADCONF, my_fmri, debugfile,
810e3320f40Smarkfen 			    dgettext(TEXT_DOMAIN, "Memory allocation error."));
8117c478bd9Sstevel@tonic-gate 			break;
8127c478bd9Sstevel@tonic-gate 		case COMMENT_LINE:
8137c478bd9Sstevel@tonic-gate 			/* Comment line. */
814e3320f40Smarkfen 			free(ebuf);
8157c478bd9Sstevel@tonic-gate 			break;
8167c478bd9Sstevel@tonic-gate 		default:
817e3320f40Smarkfen 			if (thisargc != 0) {
818e3320f40Smarkfen 				lines_parsed++;
819e3320f40Smarkfen 				/* ebuf consumed */
82025e435e0Spwernau 				parseit(thisargc, thisargv, ebuf, readfile);
821e3320f40Smarkfen 			} else {
822e3320f40Smarkfen 				free(ebuf);
823e3320f40Smarkfen 			}
8247c478bd9Sstevel@tonic-gate 			free(thisargv);
8257c478bd9Sstevel@tonic-gate 			if (infile == stdin) {
8267c478bd9Sstevel@tonic-gate 				(void) printf("%s", promptstring);
8277c478bd9Sstevel@tonic-gate 				(void) fflush(stdout);
8287c478bd9Sstevel@tonic-gate 			}
8297c478bd9Sstevel@tonic-gate 			break;
8307c478bd9Sstevel@tonic-gate 		}
8317c478bd9Sstevel@tonic-gate 		bzero(ibuf, IBUF_SIZE);
8327c478bd9Sstevel@tonic-gate 	}
83325e435e0Spwernau 
83425e435e0Spwernau 	/*
83525e435e0Spwernau 	 * The following code is ipseckey specific. This should never be
83625e435e0Spwernau 	 * used by ikeadm which also calls this function because ikeadm
83725e435e0Spwernau 	 * only runs interactively. If this ever changes this code block
83825e435e0Spwernau 	 * sould be revisited.
83925e435e0Spwernau 	 */
84025e435e0Spwernau 	if (readfile) {
84125e435e0Spwernau 		if (lines_parsed != 0 && lines_added == 0) {
842e3320f40Smarkfen 			ipsecutil_exit(SERVICE_BADCONF, my_fmri, debugfile,
843e3320f40Smarkfen 			    dgettext(TEXT_DOMAIN, "Configuration file did not "
844e3320f40Smarkfen 			    "contain any valid SAs"));
84525e435e0Spwernau 		}
846e3320f40Smarkfen 
847e3320f40Smarkfen 		/*
84825e435e0Spwernau 		 * There were errors. Putting the service in maintenance mode.
849e3320f40Smarkfen 		 * When svc.startd(1M) allows services to degrade themselves,
850e3320f40Smarkfen 		 * this should be revisited.
851e3320f40Smarkfen 		 *
852e3320f40Smarkfen 		 * If this function was called from a program running as a
853e3320f40Smarkfen 		 * smf_method(5), print a warning message. Don't spew out the
854e3320f40Smarkfen 		 * errors as these will end up in the smf(5) log file which is
85525e435e0Spwernau 		 * publically readable, the errors may contain sensitive
85625e435e0Spwernau 		 * information.
857e3320f40Smarkfen 		 */
858e3320f40Smarkfen 		if ((lines_added < lines_parsed) && (configfile != NULL)) {
859e3320f40Smarkfen 			if (my_fmri != NULL) {
86025e435e0Spwernau 				ipsecutil_exit(SERVICE_BADCONF, my_fmri,
86125e435e0Spwernau 				    debugfile, dgettext(TEXT_DOMAIN,
86225e435e0Spwernau 				    "The configuration file contained %d "
86325e435e0Spwernau 				    "errors.\n"
864e3320f40Smarkfen 				    "Manually check the configuration with:\n"
865e3320f40Smarkfen 				    "ipseckey -c %s\n"
86625e435e0Spwernau 				    "Use svcadm(1M) to clear maintenance "
86725e435e0Spwernau 				    "condition when errors are resolved.\n"),
868e3320f40Smarkfen 				    lines_parsed - lines_added, configfile);
869e3320f40Smarkfen 			} else {
870e3320f40Smarkfen 				EXIT_BADCONFIG(NULL);
871e3320f40Smarkfen 			}
872e3320f40Smarkfen 		} else {
873e3320f40Smarkfen 			if (my_fmri != NULL)
87425e435e0Spwernau 				ipsecutil_exit(SERVICE_EXIT_OK, my_fmri,
87525e435e0Spwernau 				    debugfile, dgettext(TEXT_DOMAIN,
87625e435e0Spwernau 				    "%d actions successfully processed."),
87725e435e0Spwernau 				    lines_added);
87825e435e0Spwernau 		}
87925e435e0Spwernau 	} else {
880bfe6f8f5SVladimir Kotal 		/* no newline upon Ctrl-D */
881bfe6f8f5SVladimir Kotal 		if (s != NULL)
88225e435e0Spwernau 			(void) putchar('\n');
88325e435e0Spwernau 		(void) fflush(stdout);
884e3320f40Smarkfen 	}
885bfe6f8f5SVladimir Kotal 
886bfe6f8f5SVladimir Kotal 	fini_interactive();
887bfe6f8f5SVladimir Kotal 
888e3320f40Smarkfen 	EXIT_OK(NULL);
8897c478bd9Sstevel@tonic-gate }
8907c478bd9Sstevel@tonic-gate 
8917c478bd9Sstevel@tonic-gate /*
8927c478bd9Sstevel@tonic-gate  * Functions to parse strings that represent a debug or privilege level.
8937c478bd9Sstevel@tonic-gate  * These functions are copied from main.c and door.c in usr.lib/in.iked/common.
8947c478bd9Sstevel@tonic-gate  * If this file evolves into a common library that may be used by in.iked
8957c478bd9Sstevel@tonic-gate  * as well as the usr.sbin utilities, those duplicate functions should be
8967c478bd9Sstevel@tonic-gate  * deleted.
8977c478bd9Sstevel@tonic-gate  *
8987c478bd9Sstevel@tonic-gate  * A privilege level may be represented by a simple keyword, corresponding
8997c478bd9Sstevel@tonic-gate  * to one of the possible levels.  A debug level may be represented by a
9007c478bd9Sstevel@tonic-gate  * series of keywords, separated by '+' or '-', indicating categories to
9017c478bd9Sstevel@tonic-gate  * be added or removed from the set of categories in the debug level.
9027c478bd9Sstevel@tonic-gate  * For example, +all-op corresponds to level 0xfffffffb (all flags except
9037c478bd9Sstevel@tonic-gate  * for D_OP set); while p1+p2+pfkey corresponds to level 0x38.  Note that
9047c478bd9Sstevel@tonic-gate  * the leading '+' is implicit; the first keyword in the list must be for
9057c478bd9Sstevel@tonic-gate  * a category that is to be added.
9067c478bd9Sstevel@tonic-gate  *
9077c478bd9Sstevel@tonic-gate  * These parsing functions make use of a local version of strtok, strtok_d,
9087c478bd9Sstevel@tonic-gate  * which includes an additional parameter, char *delim.  This param is filled
9097c478bd9Sstevel@tonic-gate  * in with the character which ends the returned token.  In other words,
9107c478bd9Sstevel@tonic-gate  * this version of strtok, in addition to returning the token, also returns
9117c478bd9Sstevel@tonic-gate  * the single character delimiter from the original string which marked the
9127c478bd9Sstevel@tonic-gate  * end of the token.
9137c478bd9Sstevel@tonic-gate  */
9147c478bd9Sstevel@tonic-gate static char *
strtok_d(char * string,const char * sepset,char * delim)9157c478bd9Sstevel@tonic-gate strtok_d(char *string, const char *sepset, char *delim)
9167c478bd9Sstevel@tonic-gate {
9177c478bd9Sstevel@tonic-gate 	static char	*lasts;
9187c478bd9Sstevel@tonic-gate 	char		*q, *r;
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 	/* first or subsequent call */
9217c478bd9Sstevel@tonic-gate 	if (string == NULL)
9227c478bd9Sstevel@tonic-gate 		string = lasts;
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate 	if (string == 0)		/* return if no tokens remaining */
9257c478bd9Sstevel@tonic-gate 		return (NULL);
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 	q = string + strspn(string, sepset);	/* skip leading separators */
9287c478bd9Sstevel@tonic-gate 
9297c478bd9Sstevel@tonic-gate 	if (*q == '\0')			/* return if no tokens remaining */
9307c478bd9Sstevel@tonic-gate 		return (NULL);
9317c478bd9Sstevel@tonic-gate 
9327c478bd9Sstevel@tonic-gate 	if ((r = strpbrk(q, sepset)) == NULL) {		/* move past token */
9337c478bd9Sstevel@tonic-gate 		lasts = 0;	/* indicate that this is last token */
9347c478bd9Sstevel@tonic-gate 	} else {
9357c478bd9Sstevel@tonic-gate 		*delim = *r;	/* save delimitor */
9367c478bd9Sstevel@tonic-gate 		*r = '\0';
9377c478bd9Sstevel@tonic-gate 		lasts = r + 1;
9387c478bd9Sstevel@tonic-gate 	}
9397c478bd9Sstevel@tonic-gate 	return (q);
9407c478bd9Sstevel@tonic-gate }
9417c478bd9Sstevel@tonic-gate 
9427c478bd9Sstevel@tonic-gate static keywdtab_t	privtab[] = {
9437c478bd9Sstevel@tonic-gate 	{ IKE_PRIV_MINIMUM,	"base" },
9447c478bd9Sstevel@tonic-gate 	{ IKE_PRIV_MODKEYS,	"modkeys" },
9457c478bd9Sstevel@tonic-gate 	{ IKE_PRIV_KEYMAT,	"keymat" },
9467c478bd9Sstevel@tonic-gate 	{ IKE_PRIV_MINIMUM,	"0" },
9477c478bd9Sstevel@tonic-gate };
9487c478bd9Sstevel@tonic-gate 
9497c478bd9Sstevel@tonic-gate int
privstr2num(char * str)9507c478bd9Sstevel@tonic-gate privstr2num(char *str)
9517c478bd9Sstevel@tonic-gate {
9527c478bd9Sstevel@tonic-gate 	keywdtab_t	*pp;
9537c478bd9Sstevel@tonic-gate 	char		*endp;
9547c478bd9Sstevel@tonic-gate 	int		 priv;
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate 	for (pp = privtab; pp < A_END(privtab); pp++) {
9577c478bd9Sstevel@tonic-gate 		if (strcasecmp(str, pp->kw_str) == 0)
9587c478bd9Sstevel@tonic-gate 			return (pp->kw_tag);
9597c478bd9Sstevel@tonic-gate 	}
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 	priv = strtol(str, &endp, 0);
9627c478bd9Sstevel@tonic-gate 	if (*endp == '\0')
9637c478bd9Sstevel@tonic-gate 		return (priv);
9647c478bd9Sstevel@tonic-gate 
9657c478bd9Sstevel@tonic-gate 	return (-1);
9667c478bd9Sstevel@tonic-gate }
9677c478bd9Sstevel@tonic-gate 
9687c478bd9Sstevel@tonic-gate static keywdtab_t	dbgtab[] = {
9697c478bd9Sstevel@tonic-gate 	{ D_CERT,	"cert" },
9707c478bd9Sstevel@tonic-gate 	{ D_KEY,	"key" },
9717c478bd9Sstevel@tonic-gate 	{ D_OP,		"op" },
9727c478bd9Sstevel@tonic-gate 	{ D_P1,		"p1" },
9737c478bd9Sstevel@tonic-gate 	{ D_P1,		"phase1" },
9747c478bd9Sstevel@tonic-gate 	{ D_P2,		"p2" },
9757c478bd9Sstevel@tonic-gate 	{ D_P2,		"phase2" },
9767c478bd9Sstevel@tonic-gate 	{ D_PFKEY,	"pfkey" },
9777c478bd9Sstevel@tonic-gate 	{ D_POL,	"pol" },
9787c478bd9Sstevel@tonic-gate 	{ D_POL,	"policy" },
9797c478bd9Sstevel@tonic-gate 	{ D_PROP,	"prop" },
9807c478bd9Sstevel@tonic-gate 	{ D_DOOR,	"door" },
9817c478bd9Sstevel@tonic-gate 	{ D_CONFIG,	"config" },
9825d3b8cb7SBill Sommerfeld 	{ D_LABEL,	"label" },
9837c478bd9Sstevel@tonic-gate 	{ D_ALL,	"all" },
9847c478bd9Sstevel@tonic-gate 	{ 0,		"0" },
9857c478bd9Sstevel@tonic-gate };
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate int
dbgstr2num(char * str)9887c478bd9Sstevel@tonic-gate dbgstr2num(char *str)
9897c478bd9Sstevel@tonic-gate {
9907c478bd9Sstevel@tonic-gate 	keywdtab_t	*dp;
9917c478bd9Sstevel@tonic-gate 
9927c478bd9Sstevel@tonic-gate 	for (dp = dbgtab; dp < A_END(dbgtab); dp++) {
9937c478bd9Sstevel@tonic-gate 		if (strcasecmp(str, dp->kw_str) == 0)
9947c478bd9Sstevel@tonic-gate 			return (dp->kw_tag);
9957c478bd9Sstevel@tonic-gate 	}
9967c478bd9Sstevel@tonic-gate 	return (D_INVALID);
9977c478bd9Sstevel@tonic-gate }
9987c478bd9Sstevel@tonic-gate 
9997c478bd9Sstevel@tonic-gate int
parsedbgopts(char * optarg)10007c478bd9Sstevel@tonic-gate parsedbgopts(char *optarg)
10017c478bd9Sstevel@tonic-gate {
10027c478bd9Sstevel@tonic-gate 	char	*argp, *endp, op, nextop;
10037c478bd9Sstevel@tonic-gate 	int	mask = 0, new;
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 	mask = strtol(optarg, &endp, 0);
10067c478bd9Sstevel@tonic-gate 	if (*endp == '\0')
10077c478bd9Sstevel@tonic-gate 		return (mask);
10087c478bd9Sstevel@tonic-gate 
10097c478bd9Sstevel@tonic-gate 	op = optarg[0];
10107c478bd9Sstevel@tonic-gate 	if (op != '-')
10117c478bd9Sstevel@tonic-gate 		op = '+';
10127c478bd9Sstevel@tonic-gate 	argp = strtok_d(optarg, "+-", &nextop);
10137c478bd9Sstevel@tonic-gate 	do {
10147c478bd9Sstevel@tonic-gate 		new = dbgstr2num(argp);
10157c478bd9Sstevel@tonic-gate 		if (new == D_INVALID) {
10167c478bd9Sstevel@tonic-gate 			/* we encountered an invalid keywd */
10177c478bd9Sstevel@tonic-gate 			return (new);
10187c478bd9Sstevel@tonic-gate 		}
10197c478bd9Sstevel@tonic-gate 		if (op == '+') {
10207c478bd9Sstevel@tonic-gate 			mask |= new;
10217c478bd9Sstevel@tonic-gate 		} else {
10227c478bd9Sstevel@tonic-gate 			mask &= ~new;
10237c478bd9Sstevel@tonic-gate 		}
10247c478bd9Sstevel@tonic-gate 		op = nextop;
10257c478bd9Sstevel@tonic-gate 	} while ((argp = strtok_d(NULL, "+-", &nextop)) != NULL);
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 	return (mask);
10287c478bd9Sstevel@tonic-gate }
10297c478bd9Sstevel@tonic-gate 
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate /*
10327c478bd9Sstevel@tonic-gate  * functions to manipulate the kmcookie-label mapping file
10337c478bd9Sstevel@tonic-gate  */
10347c478bd9Sstevel@tonic-gate 
10357c478bd9Sstevel@tonic-gate /*
10367c478bd9Sstevel@tonic-gate  * Open, lockf, fdopen the given file, returning a FILE * on success,
10377c478bd9Sstevel@tonic-gate  * or NULL on failure.
10387c478bd9Sstevel@tonic-gate  */
10397c478bd9Sstevel@tonic-gate FILE *
kmc_open_and_lock(char * name)10407c478bd9Sstevel@tonic-gate kmc_open_and_lock(char *name)
10417c478bd9Sstevel@tonic-gate {
10427c478bd9Sstevel@tonic-gate 	int	fd, rtnerr;
10437c478bd9Sstevel@tonic-gate 	FILE	*fp;
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 	if ((fd = open(name, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
10467c478bd9Sstevel@tonic-gate 		return (NULL);
10477c478bd9Sstevel@tonic-gate 	}
10487c478bd9Sstevel@tonic-gate 	if (lockf(fd, F_LOCK, 0) < 0) {
10497c478bd9Sstevel@tonic-gate 		return (NULL);
10507c478bd9Sstevel@tonic-gate 	}
10517c478bd9Sstevel@tonic-gate 	if ((fp = fdopen(fd, "a+")) == NULL) {
10527c478bd9Sstevel@tonic-gate 		return (NULL);
10537c478bd9Sstevel@tonic-gate 	}
10547c478bd9Sstevel@tonic-gate 	if (fseek(fp, 0, SEEK_SET) < 0) {
10557c478bd9Sstevel@tonic-gate 		/* save errno in case fclose changes it */
10567c478bd9Sstevel@tonic-gate 		rtnerr = errno;
10577c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
10587c478bd9Sstevel@tonic-gate 		errno = rtnerr;
10597c478bd9Sstevel@tonic-gate 		return (NULL);
10607c478bd9Sstevel@tonic-gate 	}
10617c478bd9Sstevel@tonic-gate 	return (fp);
10627c478bd9Sstevel@tonic-gate }
10637c478bd9Sstevel@tonic-gate 
10647c478bd9Sstevel@tonic-gate /*
10657c478bd9Sstevel@tonic-gate  * Extract an integer cookie and string label from a line from the
10667c478bd9Sstevel@tonic-gate  * kmcookie-label file.  Return -1 on failure, 0 on success.
10677c478bd9Sstevel@tonic-gate  */
10687c478bd9Sstevel@tonic-gate int
kmc_parse_line(char * line,int * cookie,char ** label)10697c478bd9Sstevel@tonic-gate kmc_parse_line(char *line, int *cookie, char **label)
10707c478bd9Sstevel@tonic-gate {
10717c478bd9Sstevel@tonic-gate 	char	*cookiestr;
10727c478bd9Sstevel@tonic-gate 
10737c478bd9Sstevel@tonic-gate 	*cookie = 0;
10747c478bd9Sstevel@tonic-gate 	*label = NULL;
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 	cookiestr = strtok(line, " \t\n");
10777c478bd9Sstevel@tonic-gate 	if (cookiestr == NULL) {
10787c478bd9Sstevel@tonic-gate 		return (-1);
10797c478bd9Sstevel@tonic-gate 	}
10807c478bd9Sstevel@tonic-gate 
10817c478bd9Sstevel@tonic-gate 	/* Everything that follows, up to the newline, is the label. */
10827c478bd9Sstevel@tonic-gate 	*label = strtok(NULL, "\n");
10837c478bd9Sstevel@tonic-gate 	if (*label == NULL) {
10847c478bd9Sstevel@tonic-gate 		return (-1);
10857c478bd9Sstevel@tonic-gate 	}
10867c478bd9Sstevel@tonic-gate 
10877c478bd9Sstevel@tonic-gate 	*cookie = atoi(cookiestr);
10887c478bd9Sstevel@tonic-gate 	return (0);
10897c478bd9Sstevel@tonic-gate }
10907c478bd9Sstevel@tonic-gate 
10917c478bd9Sstevel@tonic-gate /*
10927c478bd9Sstevel@tonic-gate  * Insert a mapping into the file (if it's not already there), given the
10937c478bd9Sstevel@tonic-gate  * new label.  Return the assigned cookie, or -1 on error.
10947c478bd9Sstevel@tonic-gate  */
10957c478bd9Sstevel@tonic-gate int
kmc_insert_mapping(char * label)10967c478bd9Sstevel@tonic-gate kmc_insert_mapping(char *label)
10977c478bd9Sstevel@tonic-gate {
10987c478bd9Sstevel@tonic-gate 	FILE	*map;
1099c99ab7ceSdanmcd 	char	linebuf[IBUF_SIZE];
11007c478bd9Sstevel@tonic-gate 	char	*cur_label;
11017c478bd9Sstevel@tonic-gate 	int	max_cookie = 0, cur_cookie, rtn_cookie;
11027c478bd9Sstevel@tonic-gate 	int	rtnerr = 0;
11037c478bd9Sstevel@tonic-gate 	boolean_t	found = B_FALSE;
11047c478bd9Sstevel@tonic-gate 
11057c478bd9Sstevel@tonic-gate 	/* open and lock the file; will sleep until lock is available */
11067c478bd9Sstevel@tonic-gate 	if ((map = kmc_open_and_lock(KMCFILE)) == NULL) {
11077c478bd9Sstevel@tonic-gate 		/* kmc_open_and_lock() sets errno appropriately */
11087c478bd9Sstevel@tonic-gate 		return (-1);
11097c478bd9Sstevel@tonic-gate 	}
11107c478bd9Sstevel@tonic-gate 
11117c478bd9Sstevel@tonic-gate 	while (fgets(linebuf, sizeof (linebuf), map) != NULL) {
11127c478bd9Sstevel@tonic-gate 
1113c99ab7ceSdanmcd 		/* Skip blank lines, which often come near EOF. */
1114c99ab7ceSdanmcd 		if (strlen(linebuf) == 0)
1115c99ab7ceSdanmcd 			continue;
1116c99ab7ceSdanmcd 
11177c478bd9Sstevel@tonic-gate 		if (kmc_parse_line(linebuf, &cur_cookie, &cur_label) < 0) {
11187c478bd9Sstevel@tonic-gate 			rtnerr = EINVAL;
11197c478bd9Sstevel@tonic-gate 			goto error;
11207c478bd9Sstevel@tonic-gate 		}
11217c478bd9Sstevel@tonic-gate 
11227c478bd9Sstevel@tonic-gate 		if (cur_cookie > max_cookie)
11237c478bd9Sstevel@tonic-gate 			max_cookie = cur_cookie;
11247c478bd9Sstevel@tonic-gate 
11257c478bd9Sstevel@tonic-gate 		if ((!found) && (strcmp(cur_label, label) == 0)) {
11267c478bd9Sstevel@tonic-gate 			found = B_TRUE;
11277c478bd9Sstevel@tonic-gate 			rtn_cookie = cur_cookie;
11287c478bd9Sstevel@tonic-gate 		}
11297c478bd9Sstevel@tonic-gate 	}
11307c478bd9Sstevel@tonic-gate 
11317c478bd9Sstevel@tonic-gate 	if (!found) {
11327c478bd9Sstevel@tonic-gate 		rtn_cookie = ++max_cookie;
11337c478bd9Sstevel@tonic-gate 		if ((fprintf(map, "%u\t%s\n", rtn_cookie, label) < 0) ||
11347c478bd9Sstevel@tonic-gate 		    (fflush(map) < 0)) {
11357c478bd9Sstevel@tonic-gate 			rtnerr = errno;
11367c478bd9Sstevel@tonic-gate 			goto error;
11377c478bd9Sstevel@tonic-gate 		}
11387c478bd9Sstevel@tonic-gate 	}
11397c478bd9Sstevel@tonic-gate 	(void) fclose(map);
11407c478bd9Sstevel@tonic-gate 
11417c478bd9Sstevel@tonic-gate 	return (rtn_cookie);
11427c478bd9Sstevel@tonic-gate 
11437c478bd9Sstevel@tonic-gate error:
11447c478bd9Sstevel@tonic-gate 	(void) fclose(map);
11457c478bd9Sstevel@tonic-gate 	errno = rtnerr;
11467c478bd9Sstevel@tonic-gate 	return (-1);
11477c478bd9Sstevel@tonic-gate }
11487c478bd9Sstevel@tonic-gate 
11497c478bd9Sstevel@tonic-gate /*
11507c478bd9Sstevel@tonic-gate  * Lookup the given cookie and return its corresponding label.  Return
11517c478bd9Sstevel@tonic-gate  * a pointer to the label on success, NULL on error (or if the label is
11527c478bd9Sstevel@tonic-gate  * not found).  Note that the returned label pointer points to a static
11537c478bd9Sstevel@tonic-gate  * string, so the label will be overwritten by a subsequent call to the
11547c478bd9Sstevel@tonic-gate  * function; the function is also not thread-safe as a result.
11557c478bd9Sstevel@tonic-gate  */
11567c478bd9Sstevel@tonic-gate char *
kmc_lookup_by_cookie(int cookie)11577c478bd9Sstevel@tonic-gate kmc_lookup_by_cookie(int cookie)
11587c478bd9Sstevel@tonic-gate {
11597c478bd9Sstevel@tonic-gate 	FILE		*map;
1160c99ab7ceSdanmcd 	static char	linebuf[IBUF_SIZE];
11617c478bd9Sstevel@tonic-gate 	char		*cur_label;
11627c478bd9Sstevel@tonic-gate 	int		cur_cookie;
11637c478bd9Sstevel@tonic-gate 
11647c478bd9Sstevel@tonic-gate 	if ((map = kmc_open_and_lock(KMCFILE)) == NULL) {
11657c478bd9Sstevel@tonic-gate 		return (NULL);
11667c478bd9Sstevel@tonic-gate 	}
11677c478bd9Sstevel@tonic-gate 
11687c478bd9Sstevel@tonic-gate 	while (fgets(linebuf, sizeof (linebuf), map) != NULL) {
11697c478bd9Sstevel@tonic-gate 
11707c478bd9Sstevel@tonic-gate 		if (kmc_parse_line(linebuf, &cur_cookie, &cur_label) < 0) {
11717c478bd9Sstevel@tonic-gate 			(void) fclose(map);
11727c478bd9Sstevel@tonic-gate 			return (NULL);
11737c478bd9Sstevel@tonic-gate 		}
11747c478bd9Sstevel@tonic-gate 
11757c478bd9Sstevel@tonic-gate 		if (cookie == cur_cookie) {
11767c478bd9Sstevel@tonic-gate 			(void) fclose(map);
11777c478bd9Sstevel@tonic-gate 			return (cur_label);
11787c478bd9Sstevel@tonic-gate 		}
11797c478bd9Sstevel@tonic-gate 	}
11807c478bd9Sstevel@tonic-gate 	(void) fclose(map);
11817c478bd9Sstevel@tonic-gate 
11827c478bd9Sstevel@tonic-gate 	return (NULL);
11837c478bd9Sstevel@tonic-gate }
11847c478bd9Sstevel@tonic-gate 
11857c478bd9Sstevel@tonic-gate /*
11867c478bd9Sstevel@tonic-gate  * Parse basic extension headers and return in the passed-in pointer vector.
11877c478bd9Sstevel@tonic-gate  * Return values include:
11887c478bd9Sstevel@tonic-gate  *
11897c478bd9Sstevel@tonic-gate  *	KGE_OK	Everything's nice and parsed out.
11907c478bd9Sstevel@tonic-gate  *		If there are no extensions, place NULL in extv[0].
11917c478bd9Sstevel@tonic-gate  *	KGE_DUP	There is a duplicate extension.
11927c478bd9Sstevel@tonic-gate  *		First instance in appropriate bin.  First duplicate in
11937c478bd9Sstevel@tonic-gate  *		extv[0].
11947c478bd9Sstevel@tonic-gate  *	KGE_UNK	Unknown extension type encountered.  extv[0] contains
11957c478bd9Sstevel@tonic-gate  *		unknown header.
11967c478bd9Sstevel@tonic-gate  *	KGE_LEN	Extension length error.
11977c478bd9Sstevel@tonic-gate  *	KGE_CHK	High-level reality check failed on specific extension.
11987c478bd9Sstevel@tonic-gate  *
11997c478bd9Sstevel@tonic-gate  * My apologies for some of the pointer arithmetic in here.  I'm thinking
12007c478bd9Sstevel@tonic-gate  * like an assembly programmer, yet trying to make the compiler happy.
12017c478bd9Sstevel@tonic-gate  */
12027c478bd9Sstevel@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)12037c478bd9Sstevel@tonic-gate spdsock_get_ext(spd_ext_t *extv[], spd_msg_t *basehdr, uint_t msgsize,
12047c478bd9Sstevel@tonic-gate     char *diag_buf, uint_t diag_buf_len)
12057c478bd9Sstevel@tonic-gate {
12067c478bd9Sstevel@tonic-gate 	int i;
12077c478bd9Sstevel@tonic-gate 
12087c478bd9Sstevel@tonic-gate 	if (diag_buf != NULL)
12097c478bd9Sstevel@tonic-gate 		diag_buf[0] = '\0';
12107c478bd9Sstevel@tonic-gate 
12117c478bd9Sstevel@tonic-gate 	for (i = 1; i <= SPD_EXT_MAX; i++)
12127c478bd9Sstevel@tonic-gate 		extv[i] = NULL;
12137c478bd9Sstevel@tonic-gate 
12147c478bd9Sstevel@tonic-gate 	i = 0;
12157c478bd9Sstevel@tonic-gate 	/* Use extv[0] as the "current working pointer". */
12167c478bd9Sstevel@tonic-gate 
12177c478bd9Sstevel@tonic-gate 	extv[0] = (spd_ext_t *)(basehdr + 1);
12187c478bd9Sstevel@tonic-gate 	msgsize = SPD_64TO8(msgsize);
12197c478bd9Sstevel@tonic-gate 
12207c478bd9Sstevel@tonic-gate 	while ((char *)extv[0] < ((char *)basehdr + msgsize)) {
12217c478bd9Sstevel@tonic-gate 		/* Check for unknown headers. */
12227c478bd9Sstevel@tonic-gate 		i++;
12237c478bd9Sstevel@tonic-gate 		if (extv[0]->spd_ext_type == 0 ||
12247c478bd9Sstevel@tonic-gate 		    extv[0]->spd_ext_type > SPD_EXT_MAX) {
12257c478bd9Sstevel@tonic-gate 			if (diag_buf != NULL) {
12267c478bd9Sstevel@tonic-gate 				(void) snprintf(diag_buf, diag_buf_len,
12277c478bd9Sstevel@tonic-gate 				    "spdsock ext 0x%X unknown: 0x%X",
12287c478bd9Sstevel@tonic-gate 				    i, extv[0]->spd_ext_type);
12297c478bd9Sstevel@tonic-gate 			}
12307c478bd9Sstevel@tonic-gate 			return (KGE_UNK);
12317c478bd9Sstevel@tonic-gate 		}
12327c478bd9Sstevel@tonic-gate 
12337c478bd9Sstevel@tonic-gate 		/*
12347c478bd9Sstevel@tonic-gate 		 * Check length.  Use uint64_t because extlen is in units
12357c478bd9Sstevel@tonic-gate 		 * of 64-bit words.  If length goes beyond the msgsize,
12367c478bd9Sstevel@tonic-gate 		 * return an error.  (Zero length also qualifies here.)
12377c478bd9Sstevel@tonic-gate 		 */
12387c478bd9Sstevel@tonic-gate 		if (extv[0]->spd_ext_len == 0 ||
12397c478bd9Sstevel@tonic-gate 		    (uint8_t *)((uint64_t *)extv[0] + extv[0]->spd_ext_len) >
12407c478bd9Sstevel@tonic-gate 		    (uint8_t *)((uint8_t *)basehdr + msgsize))
12417c478bd9Sstevel@tonic-gate 			return (KGE_LEN);
12427c478bd9Sstevel@tonic-gate 
12437c478bd9Sstevel@tonic-gate 		/* Check for redundant headers. */
12447c478bd9Sstevel@tonic-gate 		if (extv[extv[0]->spd_ext_type] != NULL)
12457c478bd9Sstevel@tonic-gate 			return (KGE_DUP);
12467c478bd9Sstevel@tonic-gate 
12477c478bd9Sstevel@tonic-gate 		/* If I make it here, assign the appropriate bin. */
12487c478bd9Sstevel@tonic-gate 		extv[extv[0]->spd_ext_type] = extv[0];
12497c478bd9Sstevel@tonic-gate 
12507c478bd9Sstevel@tonic-gate 		/* Advance pointer (See above for uint64_t ptr reasoning.) */
12517c478bd9Sstevel@tonic-gate 		extv[0] = (spd_ext_t *)
12527c478bd9Sstevel@tonic-gate 		    ((uint64_t *)extv[0] + extv[0]->spd_ext_len);
12537c478bd9Sstevel@tonic-gate 	}
12547c478bd9Sstevel@tonic-gate 
12557c478bd9Sstevel@tonic-gate 	/* Everything's cool. */
12567c478bd9Sstevel@tonic-gate 
12577c478bd9Sstevel@tonic-gate 	/*
12587c478bd9Sstevel@tonic-gate 	 * If extv[0] == NULL, then there are no extension headers in this
12597c478bd9Sstevel@tonic-gate 	 * message.  Ensure that this is the case.
12607c478bd9Sstevel@tonic-gate 	 */
12617c478bd9Sstevel@tonic-gate 	if (extv[0] == (spd_ext_t *)(basehdr + 1))
12627c478bd9Sstevel@tonic-gate 		extv[0] = NULL;
12637c478bd9Sstevel@tonic-gate 
12647c478bd9Sstevel@tonic-gate 	return (KGE_OK);
12657c478bd9Sstevel@tonic-gate }
12667c478bd9Sstevel@tonic-gate 
12677c478bd9Sstevel@tonic-gate const char *
spdsock_diag(int diagnostic)12687c478bd9Sstevel@tonic-gate spdsock_diag(int diagnostic)
12697c478bd9Sstevel@tonic-gate {
12707c478bd9Sstevel@tonic-gate 	switch (diagnostic) {
12717c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_NONE:
1272a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "no error"));
12737c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_UNKNOWN_EXT:
1274a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "unknown extension"));
12757c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_BAD_EXTLEN:
1276a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "bad extension length"));
12777c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_NO_RULE_EXT:
1278a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "no rule extension"));
12797c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_BAD_ADDR_LEN:
1280a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "bad address len"));
12817c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MIXED_AF:
1282a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "mixed address family"));
12837c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ADD_NO_MEM:
1284a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "add: no memory"));
12857c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ADD_WRONG_ACT_COUNT:
1286a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "add: wrong action count"));
12877c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ADD_BAD_TYPE:
1288a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "add: bad type"));
12897c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ADD_BAD_FLAGS:
1290a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "add: bad flags"));
12917c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ADD_INCON_FLAGS:
1292a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "add: inconsistent flags"));
12937c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_LCLPORT:
1294a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed local port"));
12957c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_LCLPORT:
1296a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate local port"));
12977c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_REMPORT:
1298a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed remote port"));
12997c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_REMPORT:
1300a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate remote port"));
13017c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_PROTO:
1302a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed proto"));
13037c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_PROTO:
1304a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate proto"));
13057c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_LCLADDR:
1306a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed local address"));
13077c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_LCLADDR:
1308a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate local address"));
13097c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_REMADDR:
1310a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed remote address"));
13117c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_REMADDR:
1312a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate remote address"));
13137c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_ACTION:
1314a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed action"));
13157c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_ACTION:
1316a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate action"));
13177c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_RULE:
1318a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed rule"));
13197c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_RULE:
1320a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate rule"));
13217c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_MALFORMED_RULESET:
1322a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "malformed ruleset"));
13237c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_DUPLICATE_RULESET:
1324a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "duplicate ruleset"));
13257c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_INVALID_RULE_INDEX:
1326a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "invalid rule index"));
13277c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_BAD_SPDID:
1328a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "bad spdid"));
13297c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_BAD_MSG_TYPE:
1330a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "bad message type"));
13317c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_UNSUPP_AH_ALG:
1332a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "unsupported AH algorithm"));
13337c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_UNSUPP_ESP_ENCR_ALG:
1334a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1335a7485808Smarkfen 		    "unsupported ESP encryption algorithm"));
13367c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_UNSUPP_ESP_AUTH_ALG:
1337a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1338a7485808Smarkfen 		    "unsupported ESP authentication algorithm"));
13397c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_UNSUPP_AH_KEYSIZE:
1340a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "unsupported AH key size"));
13417c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_UNSUPP_ESP_ENCR_KEYSIZE:
1342a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1343a7485808Smarkfen 		    "unsupported ESP encryption key size"));
13447c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_UNSUPP_ESP_AUTH_KEYSIZE:
1345a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1346a7485808Smarkfen 		    "unsupported ESP authentication key size"));
13477c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_NO_ACTION_EXT:
1348a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "No ACTION extension"));
13497c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ALG_ID_RANGE:
1350a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "invalid algorithm identifer"));
13517c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ALG_NUM_KEY_SIZES:
1352a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1353a7485808Smarkfen 		    "number of key sizes inconsistent"));
13547c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ALG_NUM_BLOCK_SIZES:
1355a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1356a7485808Smarkfen 		    "number of block sizes inconsistent"));
13577c478bd9Sstevel@tonic-gate 	case SPD_DIAGNOSTIC_ALG_MECH_NAME_LEN:
1358a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "invalid mechanism name length"));
13598810c16bSdanmcd 	case SPD_DIAGNOSTIC_NOT_GLOBAL_OP:
1360a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1361a7485808Smarkfen 		    "operation not applicable to all policies"));
13628810c16bSdanmcd 	case SPD_DIAGNOSTIC_NO_TUNNEL_SELECTORS:
1363a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1364a7485808Smarkfen 		    "using selectors on a transport-mode tunnel"));
13657c478bd9Sstevel@tonic-gate 	default:
1366a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "unknown diagnostic"));
13677c478bd9Sstevel@tonic-gate 	}
13687c478bd9Sstevel@tonic-gate }
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate /*
13717c478bd9Sstevel@tonic-gate  * PF_KEY Diagnostic table.
13727c478bd9Sstevel@tonic-gate  *
13737c478bd9Sstevel@tonic-gate  * PF_KEY NOTE:  If you change pfkeyv2.h's SADB_X_DIAGNOSTIC_* space, this is
13747c478bd9Sstevel@tonic-gate  * where you need to add new messages.
13757c478bd9Sstevel@tonic-gate  */
13767c478bd9Sstevel@tonic-gate 
13777c478bd9Sstevel@tonic-gate const char *
keysock_diag(int diagnostic)13787c478bd9Sstevel@tonic-gate keysock_diag(int diagnostic)
13797c478bd9Sstevel@tonic-gate {
13807c478bd9Sstevel@tonic-gate 	switch (diagnostic) {
13817c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_NONE:
1382a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "No diagnostic"));
13837c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_UNKNOWN_MSG:
1384a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Unknown message type"));
13857c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_UNKNOWN_EXT:
1386a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Unknown extension type"));
13877c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_EXTLEN:
1388a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Bad extension length"));
13897c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_UNKNOWN_SATYPE:
1390a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1391a7485808Smarkfen 		    "Unknown Security Association type"));
13927c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_SATYPE_NEEDED:
1393a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1394a7485808Smarkfen 		    "Specific Security Association type needed"));
13957c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_NO_SADBS:
1396a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1397a7485808Smarkfen 		    "No Security Association Databases present"));
13987c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_NO_EXT:
1399a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1400a7485808Smarkfen 		    "No extensions needed for message"));
14017c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_SRC_AF:
1402a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Bad source address family"));
14037c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_DST_AF:
1404a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1405a7485808Smarkfen 		    "Bad destination address family"));
14067c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_PROXY_AF:
1407a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1408a7485808Smarkfen 		    "Bad inner-source address family"));
14097c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_AF_MISMATCH:
1410a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1411a7485808Smarkfen 		    "Source/destination address family mismatch"));
14127c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_SRC:
1413a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Bad source address value"));
14147c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_DST:
1415a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Bad destination address value"));
14167c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_ALLOC_HSERR:
1417a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1418a7485808Smarkfen 		    "Soft allocations limit more than hard limit"));
14197c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BYTES_HSERR:
1420a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1421a7485808Smarkfen 		    "Soft bytes limit more than hard limit"));
14227c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_ADDTIME_HSERR:
1423a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Soft add expiration time later "
14247c478bd9Sstevel@tonic-gate 		    "than hard expiration time"));
14257c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_USETIME_HSERR:
1426a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Soft use expiration time later "
14277c478bd9Sstevel@tonic-gate 		    "than hard expiration time"));
14287c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_SRC:
1429a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing source address"));
14307c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_DST:
1431a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing destination address"));
14327c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_SA:
1433a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing SA extension"));
14347c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_EKEY:
1435a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing encryption key"));
14367c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_AKEY:
1437a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing authentication key"));
14387c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_RANGE:
1439a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing SPI range"));
14407c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_SRC:
1441a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate source address"));
14427c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_DST:
1443a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate destination address"));
14447c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_SA:
1445a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate SA extension"));
14467c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_EKEY:
1447a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate encryption key"));
14487c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_AKEY:
1449a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate authentication key"));
14507c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_RANGE:
1451a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate SPI range"));
14527c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_SRC:
1453a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Malformed source address"));
14547c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_DST:
1455a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Malformed destination address"));
14567c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_SA:
1457a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Malformed SA extension"));
14587c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_EKEY:
1459a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Malformed encryption key"));
14607c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_AKEY:
1461a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Malformed authentication key"));
14627c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_RANGE:
1463a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Malformed SPI range"));
14647c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_AKEY_PRESENT:
1465a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Authentication key not needed"));
14667c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_EKEY_PRESENT:
1467a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Encryption key not needed"));
14687c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_PROP_PRESENT:
1469a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Proposal extension not needed"));
14707c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_SUPP_PRESENT:
1471a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1472a7485808Smarkfen 		    "Supported algorithms extension not needed"));
14737c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_AALG:
1474a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1475a7485808Smarkfen 		    "Unsupported authentication algorithm"));
14767c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_EALG:
1477a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1478a7485808Smarkfen 		    "Unsupported encryption algorithm"));
14797c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_SAFLAGS:
1480a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Invalid SA flags"));
14817c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_SASTATE:
1482a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Invalid SA state"));
14837c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_AKEYBITS:
1484a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1485a7485808Smarkfen 		    "Bad number of authentication bits"));
14867c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_BAD_EKEYBITS:
1487a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1488a7485808Smarkfen 		    "Bad number of encryption bits"));
14897c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_ENCR_NOTSUPP:
1490a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1491a7485808Smarkfen 		    "Encryption not supported for this SA type"));
14927c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_WEAK_EKEY:
1493a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Weak encryption key"));
14947c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_WEAK_AKEY:
1495a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Weak authentication key"));
14967c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_KMP:
1497a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1498a7485808Smarkfen 		    "Duplicate key management protocol"));
14997c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_KMC:
1500a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1501a7485808Smarkfen 		    "Duplicate key management cookie"));
15027c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_NATT_LOC:
1503a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing NAT-T local address"));
15047c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MISSING_NATT_REM:
1505a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing NAT-T remote address"));
15067c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_LOC:
1507a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate NAT-T local address"));
15087c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_REM:
1509a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1510a7485808Smarkfen 		    "Duplicate NAT-T remote address"));
15117c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_NATT_LOC:
1512a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Malformed NAT-T local address"));
15137c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_MALFORMED_NATT_REM:
1514a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1515a7485808Smarkfen 		    "Malformed NAT-T remote address"));
15167c478bd9Sstevel@tonic-gate 	case SADB_X_DIAGNOSTIC_DUPLICATE_NATT_PORTS:
1517a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Duplicate NAT-T ports"));
15188810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_MISSING_INNER_SRC:
1519a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Missing inner source address"));
15208810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_MISSING_INNER_DST:
1521a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1522a7485808Smarkfen 		    "Missing inner destination address"));
15238810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_DUPLICATE_INNER_SRC:
1524a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1525a7485808Smarkfen 		    "Duplicate inner source address"));
15268810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_DUPLICATE_INNER_DST:
1527a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1528a7485808Smarkfen 		    "Duplicate inner destination address"));
15298810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_MALFORMED_INNER_SRC:
1530a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1531a7485808Smarkfen 		    "Malformed inner source address"));
15328810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_MALFORMED_INNER_DST:
1533a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1534a7485808Smarkfen 		    "Malformed inner destination address"));
15358810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_PREFIX_INNER_SRC:
1536a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1537a7485808Smarkfen 		    "Invalid inner-source prefix length "));
15388810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_PREFIX_INNER_DST:
1539a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1540a7485808Smarkfen 		    "Invalid inner-destination prefix length"));
15418810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_BAD_INNER_DST_AF:
1542a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1543a7485808Smarkfen 		    "Bad inner-destination address family"));
15448810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_INNER_AF_MISMATCH:
1545a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
15468810c16bSdanmcd 		    "Inner source/destination address family mismatch"));
15478810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_BAD_NATT_REM_AF:
1548a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1549a7485808Smarkfen 		    "Bad NAT-T remote address family"));
15508810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_BAD_NATT_LOC_AF:
1551a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1552a7485808Smarkfen 		    "Bad NAT-T local address family"));
15538810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_PROTO_MISMATCH:
1554a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1555a7485808Smarkfen 		    "Source/desination protocol mismatch"));
15568810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_INNER_PROTO_MISMATCH:
1557a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1558a7485808Smarkfen 		    "Inner source/desination protocol mismatch"));
15598810c16bSdanmcd 	case SADB_X_DIAGNOSTIC_DUAL_PORT_SETS:
1560a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN,
1561a7485808Smarkfen 		    "Both inner ports and outer ports are set"));
156238d95a78Smarkfen 	case SADB_X_DIAGNOSTIC_PAIR_INAPPROPRIATE:
156338d95a78Smarkfen 		return (dgettext(TEXT_DOMAIN,
156438d95a78Smarkfen 		    "Pairing failed, target SA unsuitable for pairing"));
156538d95a78Smarkfen 	case SADB_X_DIAGNOSTIC_PAIR_ADD_MISMATCH:
156638d95a78Smarkfen 		return (dgettext(TEXT_DOMAIN,
156738d95a78Smarkfen 		    "Source/destination address differs from pair SA"));
156838d95a78Smarkfen 	case SADB_X_DIAGNOSTIC_PAIR_ALREADY:
156938d95a78Smarkfen 		return (dgettext(TEXT_DOMAIN,
157038d95a78Smarkfen 		    "Already paired with another security association"));
157138d95a78Smarkfen 	case SADB_X_DIAGNOSTIC_PAIR_SA_NOTFOUND:
157238d95a78Smarkfen 		return (dgettext(TEXT_DOMAIN,
157338d95a78Smarkfen 		    "Command failed, pair security association not found"));
157438d95a78Smarkfen 	case SADB_X_DIAGNOSTIC_BAD_SA_DIRECTION:
157538d95a78Smarkfen 		return (dgettext(TEXT_DOMAIN,
157638d95a78Smarkfen 		    "Inappropriate SA direction"));
157738d95a78Smarkfen 	case SADB_X_DIAGNOSTIC_SA_NOTFOUND:
157838d95a78Smarkfen 		return (dgettext(TEXT_DOMAIN,
157938d95a78Smarkfen 		    "Security association not found"));
158038d95a78Smarkfen 	case SADB_X_DIAGNOSTIC_SA_EXPIRED:
158138d95a78Smarkfen 		return (dgettext(TEXT_DOMAIN,
158238d95a78Smarkfen 		    "Security association is not valid"));
1583a1ba8781SMark Fenwick 	case SADB_X_DIAGNOSTIC_BAD_CTX:
1584a1ba8781SMark Fenwick 		return (dgettext(TEXT_DOMAIN,
1585a1ba8781SMark Fenwick 		    "Algorithm invalid or not supported by Crypto Framework"));
1586a1ba8781SMark Fenwick 	case SADB_X_DIAGNOSTIC_INVALID_REPLAY:
1587a1ba8781SMark Fenwick 		return (dgettext(TEXT_DOMAIN,
1588a1ba8781SMark Fenwick 		    "Invalid Replay counter"));
1589a1ba8781SMark Fenwick 	case SADB_X_DIAGNOSTIC_MISSING_LIFETIME:
1590a1ba8781SMark Fenwick 		return (dgettext(TEXT_DOMAIN,
1591a1ba8781SMark Fenwick 		    "Inappropriate lifetimes"));
15927c478bd9Sstevel@tonic-gate 	default:
1593a7485808Smarkfen 		return (dgettext(TEXT_DOMAIN, "Unknown diagnostic code"));
15947c478bd9Sstevel@tonic-gate 	}
15957c478bd9Sstevel@tonic-gate }
15968810c16bSdanmcd 
15978810c16bSdanmcd /*
15988810c16bSdanmcd  * Convert an IPv6 mask to a prefix len.  I assume all IPv6 masks are
15998810c16bSdanmcd  * contiguous, so I stop at the first zero bit!
16008810c16bSdanmcd  */
16018810c16bSdanmcd int
in_masktoprefix(uint8_t * mask,boolean_t is_v4mapped)16028810c16bSdanmcd in_masktoprefix(uint8_t *mask, boolean_t is_v4mapped)
16038810c16bSdanmcd {
16048810c16bSdanmcd 	int rc = 0;
16058810c16bSdanmcd 	uint8_t last;
16068810c16bSdanmcd 	int limit = IPV6_ABITS;
16078810c16bSdanmcd 
16088810c16bSdanmcd 	if (is_v4mapped) {
16098810c16bSdanmcd 		mask += ((IPV6_ABITS - IP_ABITS)/8);
16108810c16bSdanmcd 		limit = IP_ABITS;
16118810c16bSdanmcd 	}
16128810c16bSdanmcd 
16138810c16bSdanmcd 	while (*mask == 0xff) {
16148810c16bSdanmcd 		rc += 8;
16158810c16bSdanmcd 		if (rc == limit)
16168810c16bSdanmcd 			return (limit);
16178810c16bSdanmcd 		mask++;
16188810c16bSdanmcd 	}
16198810c16bSdanmcd 
16208810c16bSdanmcd 	last = *mask;
16218810c16bSdanmcd 	while (last != 0) {
16228810c16bSdanmcd 		rc++;
16238810c16bSdanmcd 		last = (last << 1) & 0xff;
16248810c16bSdanmcd 	}
16258810c16bSdanmcd 
16268810c16bSdanmcd 	return (rc);
16278810c16bSdanmcd }
16288810c16bSdanmcd 
16298810c16bSdanmcd /*
16308810c16bSdanmcd  * Expand the diagnostic code into a message.
16318810c16bSdanmcd  */
16328810c16bSdanmcd void
print_diagnostic(FILE * file,uint16_t diagnostic)16338810c16bSdanmcd print_diagnostic(FILE *file, uint16_t diagnostic)
16348810c16bSdanmcd {
16358810c16bSdanmcd 	/* Use two spaces so above strings can fit on the line. */
1636a7485808Smarkfen 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
1637a7485808Smarkfen 	    "  Diagnostic code %u:  %s.\n"),
16388810c16bSdanmcd 	    diagnostic, keysock_diag(diagnostic));
16398810c16bSdanmcd }
16408810c16bSdanmcd 
16418810c16bSdanmcd /*
16428810c16bSdanmcd  * Prints the base PF_KEY message.
16438810c16bSdanmcd  */
16448810c16bSdanmcd void
print_sadb_msg(FILE * file,struct sadb_msg * samsg,time_t wallclock,boolean_t vflag)1645bb3ed8dfSpwernau print_sadb_msg(FILE *file, struct sadb_msg *samsg, time_t wallclock,
1646bb3ed8dfSpwernau     boolean_t vflag)
16478810c16bSdanmcd {
16488810c16bSdanmcd 	if (wallclock != 0)
1649bb3ed8dfSpwernau 		printsatime(file, wallclock, dgettext(TEXT_DOMAIN,
1650a7485808Smarkfen 		    "%sTimestamp: %s\n"), "", NULL,
16518810c16bSdanmcd 		    vflag);
16528810c16bSdanmcd 
1653bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
1654bb3ed8dfSpwernau 	    "Base message (version %u) type "),
16558810c16bSdanmcd 	    samsg->sadb_msg_version);
16568810c16bSdanmcd 	switch (samsg->sadb_msg_type) {
16578810c16bSdanmcd 	case SADB_RESERVED:
1658bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1659a7485808Smarkfen 		    "RESERVED (warning: set to 0)"));
16608810c16bSdanmcd 		break;
16618810c16bSdanmcd 	case SADB_GETSPI:
1662bb3ed8dfSpwernau 		(void) fprintf(file, "GETSPI");
16638810c16bSdanmcd 		break;
16648810c16bSdanmcd 	case SADB_UPDATE:
1665bb3ed8dfSpwernau 		(void) fprintf(file, "UPDATE");
16668810c16bSdanmcd 		break;
166738d95a78Smarkfen 	case SADB_X_UPDATEPAIR:
166838d95a78Smarkfen 		(void) fprintf(file, "UPDATE PAIR");
166938d95a78Smarkfen 		break;
16708810c16bSdanmcd 	case SADB_ADD:
1671bb3ed8dfSpwernau 		(void) fprintf(file, "ADD");
16728810c16bSdanmcd 		break;
16738810c16bSdanmcd 	case SADB_DELETE:
1674bb3ed8dfSpwernau 		(void) fprintf(file, "DELETE");
16758810c16bSdanmcd 		break;
167638d95a78Smarkfen 	case SADB_X_DELPAIR:
167738d95a78Smarkfen 		(void) fprintf(file, "DELETE PAIR");
167838d95a78Smarkfen 		break;
16798810c16bSdanmcd 	case SADB_GET:
1680bb3ed8dfSpwernau 		(void) fprintf(file, "GET");
16818810c16bSdanmcd 		break;
16828810c16bSdanmcd 	case SADB_ACQUIRE:
1683bb3ed8dfSpwernau 		(void) fprintf(file, "ACQUIRE");
16848810c16bSdanmcd 		break;
16858810c16bSdanmcd 	case SADB_REGISTER:
1686bb3ed8dfSpwernau 		(void) fprintf(file, "REGISTER");
16878810c16bSdanmcd 		break;
16888810c16bSdanmcd 	case SADB_EXPIRE:
1689bb3ed8dfSpwernau 		(void) fprintf(file, "EXPIRE");
16908810c16bSdanmcd 		break;
16918810c16bSdanmcd 	case SADB_FLUSH:
1692bb3ed8dfSpwernau 		(void) fprintf(file, "FLUSH");
16938810c16bSdanmcd 		break;
16948810c16bSdanmcd 	case SADB_DUMP:
1695bb3ed8dfSpwernau 		(void) fprintf(file, "DUMP");
16968810c16bSdanmcd 		break;
16978810c16bSdanmcd 	case SADB_X_PROMISC:
1698bb3ed8dfSpwernau 		(void) fprintf(file, "X_PROMISC");
16998810c16bSdanmcd 		break;
17008810c16bSdanmcd 	case SADB_X_INVERSE_ACQUIRE:
1701bb3ed8dfSpwernau 		(void) fprintf(file, "X_INVERSE_ACQUIRE");
17028810c16bSdanmcd 		break;
17038810c16bSdanmcd 	default:
1704bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1705a7485808Smarkfen 		    "Unknown (%u)"), samsg->sadb_msg_type);
17068810c16bSdanmcd 		break;
17078810c16bSdanmcd 	}
1708bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN, ", SA type "));
17098810c16bSdanmcd 
17108810c16bSdanmcd 	switch (samsg->sadb_msg_satype) {
17118810c16bSdanmcd 	case SADB_SATYPE_UNSPEC:
1712bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1713bb3ed8dfSpwernau 		    "<unspecified/all>"));
17148810c16bSdanmcd 		break;
17158810c16bSdanmcd 	case SADB_SATYPE_AH:
1716bb3ed8dfSpwernau 		(void) fprintf(file, "AH");
17178810c16bSdanmcd 		break;
17188810c16bSdanmcd 	case SADB_SATYPE_ESP:
1719bb3ed8dfSpwernau 		(void) fprintf(file, "ESP");
17208810c16bSdanmcd 		break;
17218810c16bSdanmcd 	case SADB_SATYPE_RSVP:
1722bb3ed8dfSpwernau 		(void) fprintf(file, "RSVP");
17238810c16bSdanmcd 		break;
17248810c16bSdanmcd 	case SADB_SATYPE_OSPFV2:
1725bb3ed8dfSpwernau 		(void) fprintf(file, "OSPFv2");
17268810c16bSdanmcd 		break;
17278810c16bSdanmcd 	case SADB_SATYPE_RIPV2:
1728bb3ed8dfSpwernau 		(void) fprintf(file, "RIPv2");
17298810c16bSdanmcd 		break;
17308810c16bSdanmcd 	case SADB_SATYPE_MIP:
1731bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "Mobile IP"));
17328810c16bSdanmcd 		break;
17338810c16bSdanmcd 	default:
1734bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1735a7485808Smarkfen 		    "<unknown %u>"), samsg->sadb_msg_satype);
17368810c16bSdanmcd 		break;
17378810c16bSdanmcd 	}
17388810c16bSdanmcd 
1739bb3ed8dfSpwernau 	(void) fprintf(file, ".\n");
17408810c16bSdanmcd 
17418810c16bSdanmcd 	if (samsg->sadb_msg_errno != 0) {
1742bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1743bb3ed8dfSpwernau 		    "Error %s from PF_KEY.\n"),
17448810c16bSdanmcd 		    strerror(samsg->sadb_msg_errno));
1745bb3ed8dfSpwernau 		print_diagnostic(file, samsg->sadb_x_msg_diagnostic);
17468810c16bSdanmcd 	}
17478810c16bSdanmcd 
1748bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
1749a7485808Smarkfen 	    "Message length %u bytes, seq=%u, pid=%u.\n"),
17508810c16bSdanmcd 	    SADB_64TO8(samsg->sadb_msg_len), samsg->sadb_msg_seq,
17518810c16bSdanmcd 	    samsg->sadb_msg_pid);
17528810c16bSdanmcd }
17538810c16bSdanmcd 
17548810c16bSdanmcd /*
17558810c16bSdanmcd  * Print the SA extension for PF_KEY.
17568810c16bSdanmcd  */
17578810c16bSdanmcd void
print_sa(FILE * file,char * prefix,struct sadb_sa * assoc)1758bb3ed8dfSpwernau print_sa(FILE *file, char *prefix, struct sadb_sa *assoc)
17598810c16bSdanmcd {
17608810c16bSdanmcd 	if (assoc->sadb_sa_len != SADB_8TO64(sizeof (*assoc))) {
1761bb3ed8dfSpwernau 		warnxfp(EFD(file), dgettext(TEXT_DOMAIN,
1762a7485808Smarkfen 		    "WARNING: SA info extension length (%u) is bad."),
17638810c16bSdanmcd 		    SADB_64TO8(assoc->sadb_sa_len));
17648810c16bSdanmcd 	}
17658810c16bSdanmcd 
1766bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
17679c2c14abSThejaswini Singarajipura 	    "%sSADB_ASSOC spi=0x%x, replay window size=%u, state="),
17688810c16bSdanmcd 	    prefix, ntohl(assoc->sadb_sa_spi), assoc->sadb_sa_replay);
17698810c16bSdanmcd 	switch (assoc->sadb_sa_state) {
17708810c16bSdanmcd 	case SADB_SASTATE_LARVAL:
1771bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "LARVAL"));
17728810c16bSdanmcd 		break;
17738810c16bSdanmcd 	case SADB_SASTATE_MATURE:
1774bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "MATURE"));
17758810c16bSdanmcd 		break;
17768810c16bSdanmcd 	case SADB_SASTATE_DYING:
1777bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "DYING"));
17788810c16bSdanmcd 		break;
17798810c16bSdanmcd 	case SADB_SASTATE_DEAD:
1780bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "DEAD"));
17818810c16bSdanmcd 		break;
17829c2c14abSThejaswini Singarajipura 	case SADB_X_SASTATE_ACTIVE_ELSEWHERE:
17839c2c14abSThejaswini Singarajipura 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
17849c2c14abSThejaswini Singarajipura 		    "ACTIVE_ELSEWHERE"));
17859c2c14abSThejaswini Singarajipura 		break;
17869c2c14abSThejaswini Singarajipura 	case SADB_X_SASTATE_IDLE:
17879c2c14abSThejaswini Singarajipura 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "IDLE"));
17889c2c14abSThejaswini Singarajipura 		break;
17898810c16bSdanmcd 	default:
1790bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1791a7485808Smarkfen 		    "<unknown %u>"), assoc->sadb_sa_state);
17928810c16bSdanmcd 	}
17938810c16bSdanmcd 
17948810c16bSdanmcd 	if (assoc->sadb_sa_auth != SADB_AALG_NONE) {
1795bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1796a7485808Smarkfen 		    "\n%sAuthentication algorithm = "),
17978810c16bSdanmcd 		    prefix);
1798bb3ed8dfSpwernau 		(void) dump_aalg(assoc->sadb_sa_auth, file);
17998810c16bSdanmcd 	}
18008810c16bSdanmcd 
18018810c16bSdanmcd 	if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) {
1802bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1803a7485808Smarkfen 		    "\n%sEncryption algorithm = "), prefix);
1804bb3ed8dfSpwernau 		(void) dump_ealg(assoc->sadb_sa_encrypt, file);
18058810c16bSdanmcd 	}
18068810c16bSdanmcd 
1807bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN, "\n%sflags=0x%x < "), prefix,
18088810c16bSdanmcd 	    assoc->sadb_sa_flags);
18098810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_SAFLAGS_PFS)
1810bb3ed8dfSpwernau 		(void) fprintf(file, "PFS ");
18118810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_SAFLAGS_NOREPLAY)
1812bb3ed8dfSpwernau 		(void) fprintf(file, "NOREPLAY ");
18138810c16bSdanmcd 
18148810c16bSdanmcd 	/* BEGIN Solaris-specific flags. */
18158810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_USED)
1816bb3ed8dfSpwernau 		(void) fprintf(file, "X_USED ");
181738d95a78Smarkfen 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_PAIRED)
181838d95a78Smarkfen 		(void) fprintf(file, "X_PAIRED ");
181938d95a78Smarkfen 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_OUTBOUND)
182038d95a78Smarkfen 		(void) fprintf(file, "X_OUTBOUND ");
182138d95a78Smarkfen 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_INBOUND)
182238d95a78Smarkfen 		(void) fprintf(file, "X_INBOUND ");
18238810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_UNIQUE)
1824bb3ed8dfSpwernau 		(void) fprintf(file, "X_UNIQUE ");
18258810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_AALG1)
1826bb3ed8dfSpwernau 		(void) fprintf(file, "X_AALG1 ");
18278810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_AALG2)
1828bb3ed8dfSpwernau 		(void) fprintf(file, "X_AALG2 ");
18298810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_EALG1)
1830bb3ed8dfSpwernau 		(void) fprintf(file, "X_EALG1 ");
18318810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_EALG2)
1832bb3ed8dfSpwernau 		(void) fprintf(file, "X_EALG2 ");
18338810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_NATT_LOC)
1834bb3ed8dfSpwernau 		(void) fprintf(file, "X_NATT_LOC ");
18358810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_NATT_REM)
1836bb3ed8dfSpwernau 		(void) fprintf(file, "X_NATT_REM ");
18378810c16bSdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_TUNNEL)
1838bb3ed8dfSpwernau 		(void) fprintf(file, "X_TUNNEL ");
18394a179720Sdanmcd 	if (assoc->sadb_sa_flags & SADB_X_SAFLAGS_NATTED)
18404a179720Sdanmcd 		(void) fprintf(file, "X_NATTED ");
18418810c16bSdanmcd 	/* END Solaris-specific flags. */
18428810c16bSdanmcd 
1843bb3ed8dfSpwernau 	(void) fprintf(file, ">\n");
18448810c16bSdanmcd }
18458810c16bSdanmcd 
18468810c16bSdanmcd void
printsatime(FILE * file,int64_t lt,const char * msg,const char * pfx,const char * pfx2,boolean_t vflag)1847bb3ed8dfSpwernau printsatime(FILE *file, int64_t lt, const char *msg, const char *pfx,
1848bb3ed8dfSpwernau     const char *pfx2, boolean_t vflag)
18498810c16bSdanmcd {
18508810c16bSdanmcd 	char tbuf[TBUF_SIZE]; /* For strftime() call. */
18518810c16bSdanmcd 	const char *tp = tbuf;
18528810c16bSdanmcd 	time_t t = lt;
18538810c16bSdanmcd 	struct tm res;
18548810c16bSdanmcd 
18558810c16bSdanmcd 	if (t != lt) {
18568810c16bSdanmcd 		if (lt > 0)
18578810c16bSdanmcd 			t = LONG_MAX;
18588810c16bSdanmcd 		else
18598810c16bSdanmcd 			t = LONG_MIN;
18608810c16bSdanmcd 	}
18618810c16bSdanmcd 
18628810c16bSdanmcd 	if (strftime(tbuf, TBUF_SIZE, NULL, localtime_r(&t, &res)) == 0)
1863a7485808Smarkfen 		tp = dgettext(TEXT_DOMAIN, "<time conversion failed>");
1864bb3ed8dfSpwernau 	(void) fprintf(file, msg, pfx, tp);
18658810c16bSdanmcd 	if (vflag && (pfx2 != NULL))
1866bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1867c51cb4bcSDan McDonald 		    "%s\t(raw time value %" PRIu64 ")\n"), pfx2, lt);
18688810c16bSdanmcd }
18698810c16bSdanmcd 
18708810c16bSdanmcd /*
18718810c16bSdanmcd  * Print the SA lifetime information.  (An SADB_EXT_LIFETIME_* extension.)
18728810c16bSdanmcd  */
18738810c16bSdanmcd 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)1874bb3ed8dfSpwernau print_lifetimes(FILE *file, time_t wallclock, struct sadb_lifetime *current,
18759c2c14abSThejaswini Singarajipura     struct sadb_lifetime *hard, struct sadb_lifetime *soft,
18769c2c14abSThejaswini Singarajipura     struct sadb_lifetime *idle, boolean_t vflag)
18778810c16bSdanmcd {
18788810c16bSdanmcd 	int64_t scratch;
1879a7485808Smarkfen 	char *soft_prefix = dgettext(TEXT_DOMAIN, "SLT: ");
1880a7485808Smarkfen 	char *hard_prefix = dgettext(TEXT_DOMAIN, "HLT: ");
1881a7485808Smarkfen 	char *current_prefix = dgettext(TEXT_DOMAIN, "CLT: ");
18829c2c14abSThejaswini Singarajipura 	char *idle_prefix = dgettext(TEXT_DOMAIN, "ILT: ");
1883510c3f91SVladimir Kotal 	char byte_str[BYTE_STR_SIZE]; /* byte lifetime string representation */
1884510c3f91SVladimir Kotal 	char secs_str[SECS_STR_SIZE]; /* buffer for seconds representation */
18858810c16bSdanmcd 
18868810c16bSdanmcd 	if (current != NULL &&
18878810c16bSdanmcd 	    current->sadb_lifetime_len != SADB_8TO64(sizeof (*current))) {
1888bb3ed8dfSpwernau 		warnxfp(EFD(file), dgettext(TEXT_DOMAIN,
1889a7485808Smarkfen 		    "WARNING: CURRENT lifetime extension length (%u) is bad."),
18908810c16bSdanmcd 		    SADB_64TO8(current->sadb_lifetime_len));
18918810c16bSdanmcd 	}
18928810c16bSdanmcd 
18938810c16bSdanmcd 	if (hard != NULL &&
18948810c16bSdanmcd 	    hard->sadb_lifetime_len != SADB_8TO64(sizeof (*hard))) {
1895bb3ed8dfSpwernau 		warnxfp(EFD(file), dgettext(TEXT_DOMAIN,
1896bb3ed8dfSpwernau 		    "WARNING: HARD lifetime extension length (%u) is bad."),
18978810c16bSdanmcd 		    SADB_64TO8(hard->sadb_lifetime_len));
18988810c16bSdanmcd 	}
18998810c16bSdanmcd 
19008810c16bSdanmcd 	if (soft != NULL &&
19018810c16bSdanmcd 	    soft->sadb_lifetime_len != SADB_8TO64(sizeof (*soft))) {
1902bb3ed8dfSpwernau 		warnxfp(EFD(file), dgettext(TEXT_DOMAIN,
1903bb3ed8dfSpwernau 		    "WARNING: SOFT lifetime extension length (%u) is bad."),
19048810c16bSdanmcd 		    SADB_64TO8(soft->sadb_lifetime_len));
19058810c16bSdanmcd 	}
19068810c16bSdanmcd 
19079c2c14abSThejaswini Singarajipura 	if (idle != NULL &&
19089c2c14abSThejaswini Singarajipura 	    idle->sadb_lifetime_len != SADB_8TO64(sizeof (*idle))) {
19099c2c14abSThejaswini Singarajipura 		warnxfp(EFD(file), dgettext(TEXT_DOMAIN,
19109c2c14abSThejaswini Singarajipura 		    "WARNING: IDLE lifetime extension length (%u) is bad."),
19119c2c14abSThejaswini Singarajipura 		    SADB_64TO8(idle->sadb_lifetime_len));
19129c2c14abSThejaswini Singarajipura 	}
19139c2c14abSThejaswini Singarajipura 
1914bb3ed8dfSpwernau 	(void) fprintf(file, " LT: Lifetime information\n");
19158810c16bSdanmcd 	if (current != NULL) {
19168810c16bSdanmcd 		/* Express values as current values. */
1917bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1918510c3f91SVladimir Kotal 		    "%sCurrent lifetime information:\n"),
1919510c3f91SVladimir Kotal 		    current_prefix);
1920510c3f91SVladimir Kotal 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1921510c3f91SVladimir Kotal 		    "%s%" PRIu64 " bytes %sprotected, %u allocations "
1922510c3f91SVladimir Kotal 		    "used.\n"), current_prefix,
1923510c3f91SVladimir Kotal 		    current->sadb_lifetime_bytes,
1924510c3f91SVladimir Kotal 		    bytecnt2out(current->sadb_lifetime_bytes, byte_str,
1925510c3f91SVladimir Kotal 		    sizeof (byte_str), SPC_END),
19268810c16bSdanmcd 		    current->sadb_lifetime_allocations);
1927bb3ed8dfSpwernau 		printsatime(file, current->sadb_lifetime_addtime,
1928510c3f91SVladimir Kotal 		    dgettext(TEXT_DOMAIN, "%sSA added at time: %s\n"),
19298810c16bSdanmcd 		    current_prefix, current_prefix, vflag);
19308810c16bSdanmcd 		if (current->sadb_lifetime_usetime != 0) {
1931bb3ed8dfSpwernau 			printsatime(file, current->sadb_lifetime_usetime,
1932a7485808Smarkfen 			    dgettext(TEXT_DOMAIN,
1933a7485808Smarkfen 			    "%sSA first used at time %s\n"),
19348810c16bSdanmcd 			    current_prefix, current_prefix, vflag);
19358810c16bSdanmcd 		}
1936bb3ed8dfSpwernau 		printsatime(file, wallclock, dgettext(TEXT_DOMAIN,
1937a7485808Smarkfen 		    "%sTime now is %s\n"), current_prefix, current_prefix,
1938a7485808Smarkfen 		    vflag);
19398810c16bSdanmcd 	}
19408810c16bSdanmcd 
19418810c16bSdanmcd 	if (soft != NULL) {
1942bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1943510c3f91SVladimir Kotal 		    "%sSoft lifetime information:\n"),
19448810c16bSdanmcd 		    soft_prefix);
1945bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1946510c3f91SVladimir Kotal 		    "%s%" PRIu64 " bytes %sof lifetime, %u allocations.\n"),
1947510c3f91SVladimir Kotal 		    soft_prefix,
1948510c3f91SVladimir Kotal 		    soft->sadb_lifetime_bytes,
1949510c3f91SVladimir Kotal 		    bytecnt2out(soft->sadb_lifetime_bytes, byte_str,
1950510c3f91SVladimir Kotal 		    sizeof (byte_str), SPC_END),
19518810c16bSdanmcd 		    soft->sadb_lifetime_allocations);
1952bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1953510c3f91SVladimir Kotal 		    "%s%" PRIu64 " seconds %sof post-add lifetime.\n"),
1954510c3f91SVladimir Kotal 		    soft_prefix, soft->sadb_lifetime_addtime,
1955510c3f91SVladimir Kotal 		    secs2out(soft->sadb_lifetime_addtime, secs_str,
1956510c3f91SVladimir Kotal 		    sizeof (secs_str), SPC_END));
1957bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
1958510c3f91SVladimir Kotal 		    "%s%" PRIu64 " seconds %sof post-use lifetime.\n"),
1959510c3f91SVladimir Kotal 		    soft_prefix, soft->sadb_lifetime_usetime,
1960510c3f91SVladimir Kotal 		    secs2out(soft->sadb_lifetime_usetime, secs_str,
1961510c3f91SVladimir Kotal 		    sizeof (secs_str), SPC_END));
19628810c16bSdanmcd 		/* If possible, express values as time remaining. */
19638810c16bSdanmcd 		if (current != NULL) {
19648810c16bSdanmcd 			if (soft->sadb_lifetime_bytes != 0)
1965510c3f91SVladimir Kotal 				(void) fprintf(file, dgettext(TEXT_DOMAIN, "%s"
1966510c3f91SVladimir Kotal 				    "%" PRIu64 " bytes %smore can be "
1967510c3f91SVladimir Kotal 				    "protected.\n"), soft_prefix,
19688810c16bSdanmcd 				    (soft->sadb_lifetime_bytes >
19698810c16bSdanmcd 				    current->sadb_lifetime_bytes) ?
1970510c3f91SVladimir Kotal 				    soft->sadb_lifetime_bytes -
1971510c3f91SVladimir Kotal 				    current->sadb_lifetime_bytes : 0,
1972510c3f91SVladimir Kotal 				    (soft->sadb_lifetime_bytes >
1973510c3f91SVladimir Kotal 				    current->sadb_lifetime_bytes) ?
1974510c3f91SVladimir Kotal 				    bytecnt2out(soft->sadb_lifetime_bytes -
1975510c3f91SVladimir Kotal 				    current->sadb_lifetime_bytes, byte_str,
1976510c3f91SVladimir Kotal 				    sizeof (byte_str), SPC_END) : "");
19778810c16bSdanmcd 			if (soft->sadb_lifetime_addtime != 0 ||
19788810c16bSdanmcd 			    (soft->sadb_lifetime_usetime != 0 &&
19798810c16bSdanmcd 			    current->sadb_lifetime_usetime != 0)) {
19808810c16bSdanmcd 				int64_t adddelta, usedelta;
19818810c16bSdanmcd 
19828810c16bSdanmcd 				if (soft->sadb_lifetime_addtime != 0) {
19838810c16bSdanmcd 					adddelta =
19848810c16bSdanmcd 					    current->sadb_lifetime_addtime +
19858810c16bSdanmcd 					    soft->sadb_lifetime_addtime -
19868810c16bSdanmcd 					    wallclock;
19878810c16bSdanmcd 				} else {
19888810c16bSdanmcd 					adddelta = TIME_MAX;
19898810c16bSdanmcd 				}
19908810c16bSdanmcd 
19918810c16bSdanmcd 				if (soft->sadb_lifetime_usetime != 0 &&
19928810c16bSdanmcd 				    current->sadb_lifetime_usetime != 0) {
19938810c16bSdanmcd 					usedelta =
19948810c16bSdanmcd 					    current->sadb_lifetime_usetime +
19958810c16bSdanmcd 					    soft->sadb_lifetime_usetime -
19968810c16bSdanmcd 					    wallclock;
19978810c16bSdanmcd 				} else {
19988810c16bSdanmcd 					usedelta = TIME_MAX;
19998810c16bSdanmcd 				}
2000bb3ed8dfSpwernau 				(void) fprintf(file, "%s", soft_prefix);
20018810c16bSdanmcd 				scratch = MIN(adddelta, usedelta);
20028810c16bSdanmcd 				if (scratch >= 0) {
2003bb3ed8dfSpwernau 					(void) fprintf(file,
2004bb3ed8dfSpwernau 					    dgettext(TEXT_DOMAIN,
2005c51cb4bcSDan McDonald 					    "Soft expiration occurs in %"
2006510c3f91SVladimir Kotal 					    PRId64 " seconds%s\n"), scratch,
2007510c3f91SVladimir Kotal 					    secs2out(scratch, secs_str,
2008510c3f91SVladimir Kotal 					    sizeof (secs_str), SPC_BEGIN));
20098810c16bSdanmcd 				} else {
2010bb3ed8dfSpwernau 					(void) fprintf(file,
2011bb3ed8dfSpwernau 					    dgettext(TEXT_DOMAIN,
2012510c3f91SVladimir Kotal 					    "Soft expiration occurred\n"));
20138810c16bSdanmcd 				}
20148810c16bSdanmcd 				scratch += wallclock;
2015bb3ed8dfSpwernau 				printsatime(file, scratch, dgettext(TEXT_DOMAIN,
2016510c3f91SVladimir Kotal 				    "%sTime of expiration: %s.\n"),
2017510c3f91SVladimir Kotal 				    soft_prefix, soft_prefix, vflag);
20188810c16bSdanmcd 			}
20198810c16bSdanmcd 		}
20208810c16bSdanmcd 	}
20218810c16bSdanmcd 
20228810c16bSdanmcd 	if (hard != NULL) {
2023bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2024510c3f91SVladimir Kotal 		    "%sHard lifetime information:\n"), hard_prefix);
2025bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2026510c3f91SVladimir Kotal 		    "%s%" PRIu64 " bytes %sof lifetime, %u allocations.\n"),
2027510c3f91SVladimir Kotal 		    hard_prefix,
2028510c3f91SVladimir Kotal 		    hard->sadb_lifetime_bytes,
2029510c3f91SVladimir Kotal 		    bytecnt2out(hard->sadb_lifetime_bytes, byte_str,
2030510c3f91SVladimir Kotal 		    sizeof (byte_str), SPC_END),
2031510c3f91SVladimir Kotal 		    hard->sadb_lifetime_allocations);
2032bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2033510c3f91SVladimir Kotal 		    "%s%" PRIu64 " seconds %sof post-add lifetime.\n"),
2034510c3f91SVladimir Kotal 		    hard_prefix, hard->sadb_lifetime_addtime,
2035510c3f91SVladimir Kotal 		    secs2out(hard->sadb_lifetime_addtime, secs_str,
2036510c3f91SVladimir Kotal 		    sizeof (secs_str), SPC_END));
2037bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2038510c3f91SVladimir Kotal 		    "%s%" PRIu64 " seconds %sof post-use lifetime.\n"),
2039510c3f91SVladimir Kotal 		    hard_prefix, hard->sadb_lifetime_usetime,
2040510c3f91SVladimir Kotal 		    secs2out(hard->sadb_lifetime_usetime, secs_str,
2041510c3f91SVladimir Kotal 		    sizeof (secs_str), SPC_END));
20428810c16bSdanmcd 		/* If possible, express values as time remaining. */
20438810c16bSdanmcd 		if (current != NULL) {
20448810c16bSdanmcd 			if (hard->sadb_lifetime_bytes != 0)
2045510c3f91SVladimir Kotal 				(void) fprintf(file, dgettext(TEXT_DOMAIN, "%s"
2046510c3f91SVladimir Kotal 				    "%" PRIu64 " bytes %smore can be "
2047510c3f91SVladimir Kotal 				    "protected.\n"), hard_prefix,
20488810c16bSdanmcd 				    (hard->sadb_lifetime_bytes >
20498810c16bSdanmcd 				    current->sadb_lifetime_bytes) ?
2050510c3f91SVladimir Kotal 				    hard->sadb_lifetime_bytes -
2051510c3f91SVladimir Kotal 				    current->sadb_lifetime_bytes : 0,
2052510c3f91SVladimir Kotal 				    (hard->sadb_lifetime_bytes >
2053510c3f91SVladimir Kotal 				    current->sadb_lifetime_bytes) ?
2054510c3f91SVladimir Kotal 				    bytecnt2out(hard->sadb_lifetime_bytes -
2055510c3f91SVladimir Kotal 				    current->sadb_lifetime_bytes, byte_str,
2056510c3f91SVladimir Kotal 				    sizeof (byte_str), SPC_END) : "");
20578810c16bSdanmcd 			if (hard->sadb_lifetime_addtime != 0 ||
20588810c16bSdanmcd 			    (hard->sadb_lifetime_usetime != 0 &&
20598810c16bSdanmcd 			    current->sadb_lifetime_usetime != 0)) {
20608810c16bSdanmcd 				int64_t adddelta, usedelta;
20618810c16bSdanmcd 
20628810c16bSdanmcd 				if (hard->sadb_lifetime_addtime != 0) {
20638810c16bSdanmcd 					adddelta =
20648810c16bSdanmcd 					    current->sadb_lifetime_addtime +
20658810c16bSdanmcd 					    hard->sadb_lifetime_addtime -
20668810c16bSdanmcd 					    wallclock;
20678810c16bSdanmcd 				} else {
20688810c16bSdanmcd 					adddelta = TIME_MAX;
20698810c16bSdanmcd 				}
20708810c16bSdanmcd 
20718810c16bSdanmcd 				if (hard->sadb_lifetime_usetime != 0 &&
20728810c16bSdanmcd 				    current->sadb_lifetime_usetime != 0) {
20738810c16bSdanmcd 					usedelta =
20748810c16bSdanmcd 					    current->sadb_lifetime_usetime +
20758810c16bSdanmcd 					    hard->sadb_lifetime_usetime -
20768810c16bSdanmcd 					    wallclock;
20778810c16bSdanmcd 				} else {
20788810c16bSdanmcd 					usedelta = TIME_MAX;
20798810c16bSdanmcd 				}
2080bb3ed8dfSpwernau 				(void) fprintf(file, "%s", hard_prefix);
20818810c16bSdanmcd 				scratch = MIN(adddelta, usedelta);
20828810c16bSdanmcd 				if (scratch >= 0) {
2083bb3ed8dfSpwernau 					(void) fprintf(file,
2084bb3ed8dfSpwernau 					    dgettext(TEXT_DOMAIN,
2085c51cb4bcSDan McDonald 					    "Hard expiration occurs in %"
2086510c3f91SVladimir Kotal 					    PRId64 " seconds%s\n"), scratch,
2087510c3f91SVladimir Kotal 					    secs2out(scratch, secs_str,
2088510c3f91SVladimir Kotal 					    sizeof (secs_str), SPC_BEGIN));
20898810c16bSdanmcd 				} else {
2090bb3ed8dfSpwernau 					(void) fprintf(file,
2091bb3ed8dfSpwernau 					    dgettext(TEXT_DOMAIN,
2092510c3f91SVladimir Kotal 					    "Hard expiration occurred\n"));
20938810c16bSdanmcd 				}
20948810c16bSdanmcd 				scratch += wallclock;
2095bb3ed8dfSpwernau 				printsatime(file, scratch, dgettext(TEXT_DOMAIN,
2096510c3f91SVladimir Kotal 				    "%sTime of expiration: %s.\n"),
2097510c3f91SVladimir Kotal 				    hard_prefix, hard_prefix, vflag);
20988810c16bSdanmcd 			}
20998810c16bSdanmcd 		}
21008810c16bSdanmcd 	}
21019c2c14abSThejaswini Singarajipura 	if (idle != NULL) {
21029c2c14abSThejaswini Singarajipura 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2103510c3f91SVladimir Kotal 		    "%sIdle lifetime information:\n"), idle_prefix);
21049c2c14abSThejaswini Singarajipura 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2105510c3f91SVladimir Kotal 		    "%s%" PRIu64 " seconds %sof post-add lifetime.\n"),
2106510c3f91SVladimir Kotal 		    idle_prefix, idle->sadb_lifetime_addtime,
2107510c3f91SVladimir Kotal 		    secs2out(idle->sadb_lifetime_addtime, secs_str,
2108510c3f91SVladimir Kotal 		    sizeof (secs_str), SPC_END));
21099c2c14abSThejaswini Singarajipura 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2110510c3f91SVladimir Kotal 		    "%s%" PRIu64 " seconds %sof post-use lifetime.\n"),
2111510c3f91SVladimir Kotal 		    idle_prefix, idle->sadb_lifetime_usetime,
2112510c3f91SVladimir Kotal 		    secs2out(idle->sadb_lifetime_usetime, secs_str,
2113510c3f91SVladimir Kotal 		    sizeof (secs_str), SPC_END));
21149c2c14abSThejaswini Singarajipura 	}
21158810c16bSdanmcd }
21168810c16bSdanmcd 
21178810c16bSdanmcd /*
21188810c16bSdanmcd  * Print an SADB_EXT_ADDRESS_* extension.
21198810c16bSdanmcd  */
21208810c16bSdanmcd void
print_address(FILE * file,char * prefix,struct sadb_address * addr,boolean_t ignore_nss)2121bb3ed8dfSpwernau print_address(FILE *file, char *prefix, struct sadb_address *addr,
2122bb3ed8dfSpwernau     boolean_t ignore_nss)
21238810c16bSdanmcd {
21248810c16bSdanmcd 	struct protoent *pe;
21258810c16bSdanmcd 
2126bb3ed8dfSpwernau 	(void) fprintf(file, "%s", prefix);
21278810c16bSdanmcd 	switch (addr->sadb_address_exttype) {
21288810c16bSdanmcd 	case SADB_EXT_ADDRESS_SRC:
2129bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "Source address "));
21308810c16bSdanmcd 		break;
21318810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_INNER_SRC:
2132bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2133bb3ed8dfSpwernau 		    "Inner source address "));
21348810c16bSdanmcd 		break;
21358810c16bSdanmcd 	case SADB_EXT_ADDRESS_DST:
2136bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2137bb3ed8dfSpwernau 		    "Destination address "));
21388810c16bSdanmcd 		break;
21398810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_INNER_DST:
2140bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2141a7485808Smarkfen 		    "Inner destination address "));
21428810c16bSdanmcd 		break;
21438810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_NATT_LOC:
2144bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2145bb3ed8dfSpwernau 		    "NAT-T local address "));
21468810c16bSdanmcd 		break;
21478810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_NATT_REM:
2148bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2149bb3ed8dfSpwernau 		    "NAT-T remote address "));
21508810c16bSdanmcd 		break;
21518810c16bSdanmcd 	}
21528810c16bSdanmcd 
2153bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
2154a7485808Smarkfen 	    "(proto=%d"), addr->sadb_address_proto);
2155bb3ed8dfSpwernau 	if (ignore_nss == B_FALSE) {
21568810c16bSdanmcd 		if (addr->sadb_address_proto == 0) {
2157bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2158bb3ed8dfSpwernau 			    "/<unspecified>"));
21598810c16bSdanmcd 		} else if ((pe = getprotobynumber(addr->sadb_address_proto))
21608810c16bSdanmcd 		    != NULL) {
2161bb3ed8dfSpwernau 			(void) fprintf(file, "/%s", pe->p_name);
21628810c16bSdanmcd 		} else {
2163bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2164bb3ed8dfSpwernau 			    "/<unknown>"));
21658810c16bSdanmcd 		}
21668810c16bSdanmcd 	}
2167bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN, ")\n%s"), prefix);
21688810c16bSdanmcd 	(void) dump_sockaddr((struct sockaddr *)(addr + 1),
2169bb3ed8dfSpwernau 	    addr->sadb_address_prefixlen, B_FALSE, file, ignore_nss);
21708810c16bSdanmcd }
21718810c16bSdanmcd 
21728810c16bSdanmcd /*
21738810c16bSdanmcd  * Print an SADB_EXT_KEY extension.
21748810c16bSdanmcd  */
21758810c16bSdanmcd void
print_key(FILE * file,char * prefix,struct sadb_key * key)2176bb3ed8dfSpwernau print_key(FILE *file, char *prefix, struct sadb_key *key)
21778810c16bSdanmcd {
2178bb3ed8dfSpwernau 	(void) fprintf(file, "%s", prefix);
21798810c16bSdanmcd 
21808810c16bSdanmcd 	switch (key->sadb_key_exttype) {
21818810c16bSdanmcd 	case SADB_EXT_KEY_AUTH:
2182bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "Authentication"));
21838810c16bSdanmcd 		break;
21848810c16bSdanmcd 	case SADB_EXT_KEY_ENCRYPT:
2185bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "Encryption"));
21868810c16bSdanmcd 		break;
21878810c16bSdanmcd 	}
21888810c16bSdanmcd 
2189bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN, " key.\n%s"), prefix);
2190628b0c67SMark Fenwick 	(void) dump_key((uint8_t *)(key + 1), key->sadb_key_bits,
2191628b0c67SMark Fenwick 	    key->sadb_key_reserved, file, B_TRUE);
2192bb3ed8dfSpwernau 	(void) fprintf(file, "\n");
21938810c16bSdanmcd }
21948810c16bSdanmcd 
21958810c16bSdanmcd /*
21968810c16bSdanmcd  * Print an SADB_EXT_IDENTITY_* extension.
21978810c16bSdanmcd  */
21988810c16bSdanmcd void
print_ident(FILE * file,char * prefix,struct sadb_ident * id)2199bb3ed8dfSpwernau print_ident(FILE *file, char *prefix, struct sadb_ident *id)
22008810c16bSdanmcd {
22018810c16bSdanmcd 	boolean_t canprint = B_TRUE;
22028810c16bSdanmcd 
2203bb3ed8dfSpwernau 	(void) fprintf(file, "%s", prefix);
22048810c16bSdanmcd 	switch (id->sadb_ident_exttype) {
22058810c16bSdanmcd 	case SADB_EXT_IDENTITY_SRC:
2206bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "Source"));
22078810c16bSdanmcd 		break;
22088810c16bSdanmcd 	case SADB_EXT_IDENTITY_DST:
2209bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "Destination"));
22108810c16bSdanmcd 		break;
22118810c16bSdanmcd 	}
22128810c16bSdanmcd 
2213bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
2214a7485808Smarkfen 	    " identity, uid=%d, type "), id->sadb_ident_id);
2215bb3ed8dfSpwernau 	canprint = dump_sadb_idtype(id->sadb_ident_type, file, NULL);
2216bb3ed8dfSpwernau 	(void) fprintf(file, "\n%s", prefix);
2217a12f8217Spwernau 	if (canprint) {
2218bb3ed8dfSpwernau 		(void) fprintf(file, "%s\n", (char *)(id + 1));
2219a12f8217Spwernau 	} else {
2220a12f8217Spwernau 		print_asn1_name(file, (const unsigned char *)(id + 1),
2221a12f8217Spwernau 		    SADB_64TO8(id->sadb_ident_len) - sizeof (sadb_ident_t));
2222a12f8217Spwernau 	}
22238810c16bSdanmcd }
22248810c16bSdanmcd 
22258810c16bSdanmcd /*
22265d3b8cb7SBill Sommerfeld  * Convert sadb_sens extension into binary security label.
22275d3b8cb7SBill Sommerfeld  */
22285d3b8cb7SBill Sommerfeld 
22295d3b8cb7SBill Sommerfeld #include <tsol/label.h>
22305d3b8cb7SBill Sommerfeld #include <sys/tsol/tndb.h>
22315d3b8cb7SBill Sommerfeld #include <sys/tsol/label_macro.h>
22325d3b8cb7SBill Sommerfeld 
22335d3b8cb7SBill Sommerfeld void
ipsec_convert_sens_to_bslabel(const struct sadb_sens * sens,bslabel_t * sl)22345d3b8cb7SBill Sommerfeld ipsec_convert_sens_to_bslabel(const struct sadb_sens *sens, bslabel_t *sl)
22355d3b8cb7SBill Sommerfeld {
22365d3b8cb7SBill Sommerfeld 	uint64_t *bitmap = (uint64_t *)(sens + 1);
22375d3b8cb7SBill Sommerfeld 	int bitmap_len = SADB_64TO8(sens->sadb_sens_sens_len);
22385d3b8cb7SBill Sommerfeld 
22395d3b8cb7SBill Sommerfeld 	bsllow(sl);
22405d3b8cb7SBill Sommerfeld 	LCLASS_SET((_bslabel_impl_t *)sl, sens->sadb_sens_sens_level);
22415d3b8cb7SBill Sommerfeld 	bcopy(bitmap, &((_bslabel_impl_t *)sl)->compartments,
22425d3b8cb7SBill Sommerfeld 	    bitmap_len);
22435d3b8cb7SBill Sommerfeld }
22445d3b8cb7SBill Sommerfeld 
22455d3b8cb7SBill Sommerfeld void
ipsec_convert_bslabel_to_string(bslabel_t * sl,char ** plabel)22465d3b8cb7SBill Sommerfeld ipsec_convert_bslabel_to_string(bslabel_t *sl, char **plabel)
22475d3b8cb7SBill Sommerfeld {
22485d3b8cb7SBill Sommerfeld 	if (label_to_str(sl, plabel, M_LABEL, DEF_NAMES) != 0) {
22495d3b8cb7SBill Sommerfeld 		*plabel = strdup(dgettext(TEXT_DOMAIN,
22505d3b8cb7SBill Sommerfeld 		    "** Label conversion failed **"));
22515d3b8cb7SBill Sommerfeld 	}
22525d3b8cb7SBill Sommerfeld }
22535d3b8cb7SBill Sommerfeld 
22545d3b8cb7SBill Sommerfeld void
ipsec_convert_bslabel_to_hex(bslabel_t * sl,char ** plabel)22555d3b8cb7SBill Sommerfeld ipsec_convert_bslabel_to_hex(bslabel_t *sl, char **plabel)
22565d3b8cb7SBill Sommerfeld {
22575d3b8cb7SBill Sommerfeld 	if (label_to_str(sl, plabel, M_INTERNAL, DEF_NAMES) != 0) {
22585d3b8cb7SBill Sommerfeld 		*plabel = strdup(dgettext(TEXT_DOMAIN,
22595d3b8cb7SBill Sommerfeld 		    "** Label conversion failed **"));
22605d3b8cb7SBill Sommerfeld 	}
22615d3b8cb7SBill Sommerfeld }
22625d3b8cb7SBill Sommerfeld 
22635d3b8cb7SBill Sommerfeld int
ipsec_convert_sl_to_sens(int doi,bslabel_t * sl,sadb_sens_t * sens)22645d3b8cb7SBill Sommerfeld ipsec_convert_sl_to_sens(int doi, bslabel_t *sl, sadb_sens_t *sens)
22655d3b8cb7SBill Sommerfeld {
22665d3b8cb7SBill Sommerfeld 	uint8_t *bitmap;
22675d3b8cb7SBill Sommerfeld 	int sens_len = sizeof (sadb_sens_t) + _C_LEN * 4;
22685d3b8cb7SBill Sommerfeld 
22695d3b8cb7SBill Sommerfeld 
22705d3b8cb7SBill Sommerfeld 	if (sens == NULL)
22715d3b8cb7SBill Sommerfeld 		return (sens_len);
22725d3b8cb7SBill Sommerfeld 
22735d3b8cb7SBill Sommerfeld 
22745d3b8cb7SBill Sommerfeld 	(void) memset(sens, 0, sens_len);
22755d3b8cb7SBill Sommerfeld 
22765d3b8cb7SBill Sommerfeld 	sens->sadb_sens_exttype = SADB_EXT_SENSITIVITY;
22775d3b8cb7SBill Sommerfeld 	sens->sadb_sens_len = SADB_8TO64(sens_len);
22785d3b8cb7SBill Sommerfeld 	sens->sadb_sens_dpd = doi;
22795d3b8cb7SBill Sommerfeld 
22805d3b8cb7SBill Sommerfeld 	sens->sadb_sens_sens_level = LCLASS(sl);
22815d3b8cb7SBill Sommerfeld 	sens->sadb_sens_integ_level = 0;
22825d3b8cb7SBill Sommerfeld 	sens->sadb_sens_sens_len = _C_LEN >> 1;
22835d3b8cb7SBill Sommerfeld 	sens->sadb_sens_integ_len = 0;
22845d3b8cb7SBill Sommerfeld 
22855d3b8cb7SBill Sommerfeld 	sens->sadb_x_sens_flags = 0;
22865d3b8cb7SBill Sommerfeld 
22875d3b8cb7SBill Sommerfeld 	bitmap = (uint8_t *)(sens + 1);
22885d3b8cb7SBill Sommerfeld 	bcopy(&(((_bslabel_impl_t *)sl)->compartments), bitmap, _C_LEN * 4);
22895d3b8cb7SBill Sommerfeld 
22905d3b8cb7SBill Sommerfeld 	return (sens_len);
22915d3b8cb7SBill Sommerfeld }
22925d3b8cb7SBill Sommerfeld 
22935d3b8cb7SBill Sommerfeld 
22945d3b8cb7SBill Sommerfeld /*
22958810c16bSdanmcd  * Print an SADB_SENSITIVITY extension.
22968810c16bSdanmcd  */
22978810c16bSdanmcd void
print_sens(FILE * file,char * prefix,const struct sadb_sens * sens,boolean_t ignore_nss)22985d3b8cb7SBill Sommerfeld print_sens(FILE *file, char *prefix, const struct sadb_sens *sens,
22995d3b8cb7SBill Sommerfeld 	boolean_t ignore_nss)
23008810c16bSdanmcd {
23015d3b8cb7SBill Sommerfeld 	char *plabel;
23025d3b8cb7SBill Sommerfeld 	char *hlabel;
23038810c16bSdanmcd 	uint64_t *bitmap = (uint64_t *)(sens + 1);
23045d3b8cb7SBill Sommerfeld 	bslabel_t sl;
23058810c16bSdanmcd 	int i;
23065d3b8cb7SBill Sommerfeld 	int sens_len = sens->sadb_sens_sens_len;
23075d3b8cb7SBill Sommerfeld 	int integ_len = sens->sadb_sens_integ_len;
23085d3b8cb7SBill Sommerfeld 	boolean_t inner = (sens->sadb_sens_exttype == SADB_EXT_SENSITIVITY);
23095d3b8cb7SBill Sommerfeld 	const char *sensname = inner ?
23105d3b8cb7SBill Sommerfeld 	    dgettext(TEXT_DOMAIN, "Plaintext Sensitivity") :
23115d3b8cb7SBill Sommerfeld 	    dgettext(TEXT_DOMAIN, "Ciphertext Sensitivity");
23125d3b8cb7SBill Sommerfeld 
23135d3b8cb7SBill Sommerfeld 	ipsec_convert_sens_to_bslabel(sens, &sl);
23148810c16bSdanmcd 
2315bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
23165d3b8cb7SBill Sommerfeld 	    "%s%s DPD %d, sens level=%d, integ level=%d, flags=%x\n"),
23175d3b8cb7SBill Sommerfeld 	    prefix, sensname, sens->sadb_sens_dpd, sens->sadb_sens_sens_level,
23185d3b8cb7SBill Sommerfeld 	    sens->sadb_sens_integ_level, sens->sadb_x_sens_flags);
23195d3b8cb7SBill Sommerfeld 
23205d3b8cb7SBill Sommerfeld 	ipsec_convert_bslabel_to_hex(&sl, &hlabel);
23215d3b8cb7SBill Sommerfeld 
23225d3b8cb7SBill Sommerfeld 	if (ignore_nss) {
2323bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
23245d3b8cb7SBill Sommerfeld 		    "%s %s Label: %s\n"), prefix, sensname, hlabel);
23255d3b8cb7SBill Sommerfeld 
23265d3b8cb7SBill Sommerfeld 		for (i = 0; i < sens_len; i++, bitmap++)
23275d3b8cb7SBill Sommerfeld 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
23285d3b8cb7SBill Sommerfeld 			    "%s %s BM extended word %d 0x%" PRIx64 "\n"),
23295d3b8cb7SBill Sommerfeld 			    prefix, sensname, i, *bitmap);
23305d3b8cb7SBill Sommerfeld 
23315d3b8cb7SBill Sommerfeld 	} else {
23325d3b8cb7SBill Sommerfeld 		ipsec_convert_bslabel_to_string(&sl, &plabel);
23335d3b8cb7SBill Sommerfeld 
23345d3b8cb7SBill Sommerfeld 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
23355d3b8cb7SBill Sommerfeld 		    "%s %s Label: %s (%s)\n"),
23365d3b8cb7SBill Sommerfeld 		    prefix, sensname, plabel, hlabel);
23375d3b8cb7SBill Sommerfeld 		free(plabel);
23385d3b8cb7SBill Sommerfeld 
23395d3b8cb7SBill Sommerfeld 	}
23405d3b8cb7SBill Sommerfeld 	free(hlabel);
23415d3b8cb7SBill Sommerfeld 
23425d3b8cb7SBill Sommerfeld 	bitmap = (uint64_t *)(sens + 1 + sens_len);
23435d3b8cb7SBill Sommerfeld 
23445d3b8cb7SBill Sommerfeld 	for (i = 0; i < integ_len; i++, bitmap++)
23455d3b8cb7SBill Sommerfeld 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2346c51cb4bcSDan McDonald 		    "%s Integrity BM extended word %d 0x%" PRIx64 "\n"),
2347bb3ed8dfSpwernau 		    prefix, i, *bitmap);
23488810c16bSdanmcd }
23498810c16bSdanmcd 
23508810c16bSdanmcd /*
23518810c16bSdanmcd  * Print an SADB_EXT_PROPOSAL extension.
23528810c16bSdanmcd  */
23538810c16bSdanmcd void
print_prop(FILE * file,char * prefix,struct sadb_prop * prop)2354bb3ed8dfSpwernau print_prop(FILE *file, char *prefix, struct sadb_prop *prop)
23558810c16bSdanmcd {
23568810c16bSdanmcd 	struct sadb_comb *combs;
23578810c16bSdanmcd 	int i, numcombs;
23588810c16bSdanmcd 
2359bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
2360a7485808Smarkfen 	    "%sProposal, replay counter = %u.\n"), prefix,
23618810c16bSdanmcd 	    prop->sadb_prop_replay);
23628810c16bSdanmcd 
23638810c16bSdanmcd 	numcombs = prop->sadb_prop_len - SADB_8TO64(sizeof (*prop));
23648810c16bSdanmcd 	numcombs /= SADB_8TO64(sizeof (*combs));
23658810c16bSdanmcd 
23668810c16bSdanmcd 	combs = (struct sadb_comb *)(prop + 1);
23678810c16bSdanmcd 
23688810c16bSdanmcd 	for (i = 0; i < numcombs; i++) {
2369bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2370a7485808Smarkfen 		    "%s Combination #%u "), prefix, i + 1);
23718810c16bSdanmcd 		if (combs[i].sadb_comb_auth != SADB_AALG_NONE) {
2372bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2373a7485808Smarkfen 			    "Authentication = "));
2374bb3ed8dfSpwernau 			(void) dump_aalg(combs[i].sadb_comb_auth, file);
2375bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2376a7485808Smarkfen 			    "  minbits=%u, maxbits=%u.\n%s "),
23778810c16bSdanmcd 			    combs[i].sadb_comb_auth_minbits,
23788810c16bSdanmcd 			    combs[i].sadb_comb_auth_maxbits, prefix);
23798810c16bSdanmcd 		}
23808810c16bSdanmcd 
23818810c16bSdanmcd 		if (combs[i].sadb_comb_encrypt != SADB_EALG_NONE) {
2382bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2383bb3ed8dfSpwernau 			    "Encryption = "));
2384bb3ed8dfSpwernau 			(void) dump_ealg(combs[i].sadb_comb_encrypt, file);
2385bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2386a7485808Smarkfen 			    "  minbits=%u, maxbits=%u.\n%s "),
23878810c16bSdanmcd 			    combs[i].sadb_comb_encrypt_minbits,
23888810c16bSdanmcd 			    combs[i].sadb_comb_encrypt_maxbits, prefix);
23898810c16bSdanmcd 		}
23908810c16bSdanmcd 
2391bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "HARD: "));
23928810c16bSdanmcd 		if (combs[i].sadb_comb_hard_allocations)
2393bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN, "alloc=%u "),
23948810c16bSdanmcd 			    combs[i].sadb_comb_hard_allocations);
23958810c16bSdanmcd 		if (combs[i].sadb_comb_hard_bytes)
2396c51cb4bcSDan McDonald 			(void) fprintf(file, dgettext(TEXT_DOMAIN, "bytes=%"
2397c51cb4bcSDan McDonald 			    PRIu64 " "), combs[i].sadb_comb_hard_bytes);
23988810c16bSdanmcd 		if (combs[i].sadb_comb_hard_addtime)
2399bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2400c51cb4bcSDan McDonald 			    "post-add secs=%" PRIu64 " "),
24018810c16bSdanmcd 			    combs[i].sadb_comb_hard_addtime);
24028810c16bSdanmcd 		if (combs[i].sadb_comb_hard_usetime)
2403bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2404c51cb4bcSDan McDonald 			    "post-use secs=%" PRIu64 ""),
24058810c16bSdanmcd 			    combs[i].sadb_comb_hard_usetime);
24068810c16bSdanmcd 
2407bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "\n%s SOFT: "),
2408bb3ed8dfSpwernau 		    prefix);
24098810c16bSdanmcd 		if (combs[i].sadb_comb_soft_allocations)
2410bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN, "alloc=%u "),
24118810c16bSdanmcd 			    combs[i].sadb_comb_soft_allocations);
24128810c16bSdanmcd 		if (combs[i].sadb_comb_soft_bytes)
2413c51cb4bcSDan McDonald 			(void) fprintf(file, dgettext(TEXT_DOMAIN, "bytes=%"
2414c51cb4bcSDan McDonald 			    PRIu64 " "), combs[i].sadb_comb_soft_bytes);
24158810c16bSdanmcd 		if (combs[i].sadb_comb_soft_addtime)
2416bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2417c51cb4bcSDan McDonald 			    "post-add secs=%" PRIu64 " "),
24188810c16bSdanmcd 			    combs[i].sadb_comb_soft_addtime);
24198810c16bSdanmcd 		if (combs[i].sadb_comb_soft_usetime)
2420bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2421c51cb4bcSDan McDonald 			    "post-use secs=%" PRIu64 ""),
24228810c16bSdanmcd 			    combs[i].sadb_comb_soft_usetime);
2423bb3ed8dfSpwernau 		(void) fprintf(file, "\n");
24248810c16bSdanmcd 	}
24258810c16bSdanmcd }
24268810c16bSdanmcd 
24278810c16bSdanmcd /*
24288810c16bSdanmcd  * Print an extended proposal (SADB_X_EXT_EPROP).
24298810c16bSdanmcd  */
24308810c16bSdanmcd void
print_eprop(FILE * file,char * prefix,struct sadb_prop * eprop)2431bb3ed8dfSpwernau print_eprop(FILE *file, char *prefix, struct sadb_prop *eprop)
24328810c16bSdanmcd {
24338810c16bSdanmcd 	uint64_t *sofar;
24348810c16bSdanmcd 	struct sadb_x_ecomb *ecomb;
24358810c16bSdanmcd 	struct sadb_x_algdesc *algdesc;
24368810c16bSdanmcd 	int i, j;
24378810c16bSdanmcd 
2438bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
2439a7485808Smarkfen 	    "%sExtended Proposal, replay counter = %u, "), prefix,
2440a7485808Smarkfen 	    eprop->sadb_prop_replay);
2441bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
2442bb3ed8dfSpwernau 	    "number of combinations = %u.\n"), eprop->sadb_x_prop_numecombs);
24438810c16bSdanmcd 
24448810c16bSdanmcd 	sofar = (uint64_t *)(eprop + 1);
24458810c16bSdanmcd 	ecomb = (struct sadb_x_ecomb *)sofar;
24468810c16bSdanmcd 
24478810c16bSdanmcd 	for (i = 0; i < eprop->sadb_x_prop_numecombs; ) {
2448bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2449a7485808Smarkfen 		    "%s Extended combination #%u:\n"), prefix, ++i);
24508810c16bSdanmcd 
2451bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "%s HARD: "),
2452bb3ed8dfSpwernau 		    prefix);
2453bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "alloc=%u, "),
24548810c16bSdanmcd 		    ecomb->sadb_x_ecomb_hard_allocations);
2455c51cb4bcSDan McDonald 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "bytes=%" PRIu64
2456c51cb4bcSDan McDonald 		    ", "), ecomb->sadb_x_ecomb_hard_bytes);
2457c51cb4bcSDan McDonald 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "post-add secs=%"
2458c51cb4bcSDan McDonald 		    PRIu64 ", "), ecomb->sadb_x_ecomb_hard_addtime);
2459c51cb4bcSDan McDonald 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "post-use secs=%"
2460c51cb4bcSDan McDonald 		    PRIu64 "\n"), ecomb->sadb_x_ecomb_hard_usetime);
24618810c16bSdanmcd 
2462bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "%s SOFT: "),
2463bb3ed8dfSpwernau 		    prefix);
2464bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "alloc=%u, "),
24658810c16bSdanmcd 		    ecomb->sadb_x_ecomb_soft_allocations);
2466bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2467c51cb4bcSDan McDonald 		    "bytes=%" PRIu64 ", "), ecomb->sadb_x_ecomb_soft_bytes);
2468c51cb4bcSDan McDonald 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2469c51cb4bcSDan McDonald 		    "post-add secs=%" PRIu64 ", "),
24708810c16bSdanmcd 		    ecomb->sadb_x_ecomb_soft_addtime);
2471c51cb4bcSDan McDonald 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "post-use secs=%"
2472c51cb4bcSDan McDonald 		    PRIu64 "\n"), ecomb->sadb_x_ecomb_soft_usetime);
24738810c16bSdanmcd 
24748810c16bSdanmcd 		sofar = (uint64_t *)(ecomb + 1);
24758810c16bSdanmcd 		algdesc = (struct sadb_x_algdesc *)sofar;
24768810c16bSdanmcd 
24778810c16bSdanmcd 		for (j = 0; j < ecomb->sadb_x_ecomb_numalgs; ) {
2478bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2479a7485808Smarkfen 			    "%s Alg #%u "), prefix, ++j);
24808810c16bSdanmcd 			switch (algdesc->sadb_x_algdesc_satype) {
24818810c16bSdanmcd 			case SADB_SATYPE_ESP:
2482bb3ed8dfSpwernau 				(void) fprintf(file, dgettext(TEXT_DOMAIN,
2483a7485808Smarkfen 				    "for ESP "));
24848810c16bSdanmcd 				break;
24858810c16bSdanmcd 			case SADB_SATYPE_AH:
2486bb3ed8dfSpwernau 				(void) fprintf(file, dgettext(TEXT_DOMAIN,
2487bb3ed8dfSpwernau 				    "for AH "));
24888810c16bSdanmcd 				break;
24898810c16bSdanmcd 			default:
2490bb3ed8dfSpwernau 				(void) fprintf(file, dgettext(TEXT_DOMAIN,
2491a7485808Smarkfen 				    "for satype=%d "),
24928810c16bSdanmcd 				    algdesc->sadb_x_algdesc_satype);
24938810c16bSdanmcd 			}
24948810c16bSdanmcd 			switch (algdesc->sadb_x_algdesc_algtype) {
24958810c16bSdanmcd 			case SADB_X_ALGTYPE_CRYPT:
2496bb3ed8dfSpwernau 				(void) fprintf(file, dgettext(TEXT_DOMAIN,
2497a7485808Smarkfen 				    "Encryption = "));
24988810c16bSdanmcd 				(void) dump_ealg(algdesc->sadb_x_algdesc_alg,
2499bb3ed8dfSpwernau 				    file);
25008810c16bSdanmcd 				break;
25018810c16bSdanmcd 			case SADB_X_ALGTYPE_AUTH:
2502bb3ed8dfSpwernau 				(void) fprintf(file, dgettext(TEXT_DOMAIN,
2503a7485808Smarkfen 				    "Authentication = "));
25048810c16bSdanmcd 				(void) dump_aalg(algdesc->sadb_x_algdesc_alg,
2505bb3ed8dfSpwernau 				    file);
25068810c16bSdanmcd 				break;
25078810c16bSdanmcd 			default:
2508bb3ed8dfSpwernau 				(void) fprintf(file, dgettext(TEXT_DOMAIN,
2509a7485808Smarkfen 				    "algtype(%d) = alg(%d)"),
25108810c16bSdanmcd 				    algdesc->sadb_x_algdesc_algtype,
25118810c16bSdanmcd 				    algdesc->sadb_x_algdesc_alg);
25128810c16bSdanmcd 				break;
25138810c16bSdanmcd 			}
25148810c16bSdanmcd 
2515bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2516628b0c67SMark Fenwick 			    "  minbits=%u, maxbits=%u, saltbits=%u\n"),
25178810c16bSdanmcd 			    algdesc->sadb_x_algdesc_minbits,
2518628b0c67SMark Fenwick 			    algdesc->sadb_x_algdesc_maxbits,
2519628b0c67SMark Fenwick 			    algdesc->sadb_x_algdesc_reserved);
25208810c16bSdanmcd 
25218810c16bSdanmcd 			sofar = (uint64_t *)(++algdesc);
25228810c16bSdanmcd 		}
25238810c16bSdanmcd 		ecomb = (struct sadb_x_ecomb *)sofar;
25248810c16bSdanmcd 	}
25258810c16bSdanmcd }
25268810c16bSdanmcd 
25278810c16bSdanmcd /*
25288810c16bSdanmcd  * Print an SADB_EXT_SUPPORTED extension.
25298810c16bSdanmcd  */
25308810c16bSdanmcd void
print_supp(FILE * file,char * prefix,struct sadb_supported * supp)2531bb3ed8dfSpwernau print_supp(FILE *file, char *prefix, struct sadb_supported *supp)
25328810c16bSdanmcd {
25338810c16bSdanmcd 	struct sadb_alg *algs;
25348810c16bSdanmcd 	int i, numalgs;
25358810c16bSdanmcd 
2536bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN, "%sSupported "), prefix);
25378810c16bSdanmcd 	switch (supp->sadb_supported_exttype) {
25388810c16bSdanmcd 	case SADB_EXT_SUPPORTED_AUTH:
2539bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "authentication"));
25408810c16bSdanmcd 		break;
25418810c16bSdanmcd 	case SADB_EXT_SUPPORTED_ENCRYPT:
2542bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN, "encryption"));
25438810c16bSdanmcd 		break;
25448810c16bSdanmcd 	}
2545bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN, " algorithms.\n"));
25468810c16bSdanmcd 
25478810c16bSdanmcd 	algs = (struct sadb_alg *)(supp + 1);
25488810c16bSdanmcd 	numalgs = supp->sadb_supported_len - SADB_8TO64(sizeof (*supp));
25498810c16bSdanmcd 	numalgs /= SADB_8TO64(sizeof (*algs));
25508810c16bSdanmcd 	for (i = 0; i < numalgs; i++) {
2551e70cf235Svk199839 		uint16_t exttype = supp->sadb_supported_exttype;
2552e70cf235Svk199839 
2553bb3ed8dfSpwernau 		(void) fprintf(file, "%s", prefix);
2554e70cf235Svk199839 		switch (exttype) {
25558810c16bSdanmcd 		case SADB_EXT_SUPPORTED_AUTH:
2556bb3ed8dfSpwernau 			(void) dump_aalg(algs[i].sadb_alg_id, file);
25578810c16bSdanmcd 			break;
25588810c16bSdanmcd 		case SADB_EXT_SUPPORTED_ENCRYPT:
2559bb3ed8dfSpwernau 			(void) dump_ealg(algs[i].sadb_alg_id, file);
25608810c16bSdanmcd 			break;
25618810c16bSdanmcd 		}
2562bb3ed8dfSpwernau 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
2563628b0c67SMark Fenwick 		    " minbits=%u, maxbits=%u, ivlen=%u, saltbits=%u"),
25648810c16bSdanmcd 		    algs[i].sadb_alg_minbits, algs[i].sadb_alg_maxbits,
2565628b0c67SMark Fenwick 		    algs[i].sadb_alg_ivlen, algs[i].sadb_x_alg_saltbits);
2566e70cf235Svk199839 		if (exttype == SADB_EXT_SUPPORTED_ENCRYPT)
2567e70cf235Svk199839 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
2568e70cf235Svk199839 			    ", increment=%u"), algs[i].sadb_x_alg_increment);
2569e70cf235Svk199839 		(void) fprintf(file, dgettext(TEXT_DOMAIN, ".\n"));
25708810c16bSdanmcd 	}
25718810c16bSdanmcd }
25728810c16bSdanmcd 
25738810c16bSdanmcd /*
25748810c16bSdanmcd  * Print an SADB_EXT_SPIRANGE extension.
25758810c16bSdanmcd  */
25768810c16bSdanmcd void
print_spirange(FILE * file,char * prefix,struct sadb_spirange * range)2577bb3ed8dfSpwernau print_spirange(FILE *file, char *prefix, struct sadb_spirange *range)
25788810c16bSdanmcd {
2579bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
2580a7485808Smarkfen 	    "%sSPI Range, min=0x%x, max=0x%x\n"), prefix,
25818810c16bSdanmcd 	    htonl(range->sadb_spirange_min),
25828810c16bSdanmcd 	    htonl(range->sadb_spirange_max));
25838810c16bSdanmcd }
25848810c16bSdanmcd 
25858810c16bSdanmcd /*
25868810c16bSdanmcd  * Print an SADB_X_EXT_KM_COOKIE extension.
25878810c16bSdanmcd  */
25888810c16bSdanmcd 
25898810c16bSdanmcd void
print_kmc(FILE * file,char * prefix,struct sadb_x_kmc * kmc)2590bb3ed8dfSpwernau print_kmc(FILE *file, char *prefix, struct sadb_x_kmc *kmc)
25918810c16bSdanmcd {
25928810c16bSdanmcd 	char *cookie_label;
25938810c16bSdanmcd 
25948810c16bSdanmcd 	if ((cookie_label = kmc_lookup_by_cookie(kmc->sadb_x_kmc_cookie)) ==
25958810c16bSdanmcd 	    NULL)
2596a7485808Smarkfen 		cookie_label = dgettext(TEXT_DOMAIN, "<Label not found.>");
25978810c16bSdanmcd 
2598bb3ed8dfSpwernau 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
2599a7485808Smarkfen 	    "%sProtocol %u, cookie=\"%s\" (%u)\n"), prefix,
26008810c16bSdanmcd 	    kmc->sadb_x_kmc_proto, cookie_label, kmc->sadb_x_kmc_cookie);
26018810c16bSdanmcd }
26029c2c14abSThejaswini Singarajipura 
26039c2c14abSThejaswini Singarajipura /*
26049c2c14abSThejaswini Singarajipura  * Print an SADB_X_EXT_REPLAY_CTR extension.
26059c2c14abSThejaswini Singarajipura  */
26069c2c14abSThejaswini Singarajipura 
26079c2c14abSThejaswini Singarajipura void
print_replay(FILE * file,char * prefix,sadb_x_replay_ctr_t * repl)26089c2c14abSThejaswini Singarajipura print_replay(FILE *file, char *prefix, sadb_x_replay_ctr_t *repl)
26099c2c14abSThejaswini Singarajipura {
26109c2c14abSThejaswini Singarajipura 	(void) fprintf(file, dgettext(TEXT_DOMAIN,
26119c2c14abSThejaswini Singarajipura 	    "%sReplay Value "), prefix);
26129c2c14abSThejaswini Singarajipura 	if ((repl->sadb_x_rc_replay32 == 0) &&
26139c2c14abSThejaswini Singarajipura 	    (repl->sadb_x_rc_replay64 == 0)) {
26149c2c14abSThejaswini Singarajipura 		(void) fprintf(file, dgettext(TEXT_DOMAIN,
26159c2c14abSThejaswini Singarajipura 		    "<Value not found.>"));
26169c2c14abSThejaswini Singarajipura 	}
26179c2c14abSThejaswini Singarajipura 	/*
26189c2c14abSThejaswini Singarajipura 	 * We currently do not support a 64-bit replay value.
26199c2c14abSThejaswini Singarajipura 	 * RFC 4301 will require one, however, and we have a field
26209c2c14abSThejaswini Singarajipura 	 * in place when 4301 is built.
26219c2c14abSThejaswini Singarajipura 	 */
26229c2c14abSThejaswini Singarajipura 	(void) fprintf(file, "% " PRIu64 "\n",
26239c2c14abSThejaswini Singarajipura 	    ((repl->sadb_x_rc_replay32 == 0) ?
26249c2c14abSThejaswini Singarajipura 	    repl->sadb_x_rc_replay64 : repl->sadb_x_rc_replay32));
26259c2c14abSThejaswini Singarajipura }
262638d95a78Smarkfen /*
262738d95a78Smarkfen  * Print an SADB_X_EXT_PAIR extension.
262838d95a78Smarkfen  */
262938d95a78Smarkfen static void
print_pair(FILE * file,char * prefix,struct sadb_x_pair * pair)263038d95a78Smarkfen print_pair(FILE *file, char *prefix, struct sadb_x_pair *pair)
263138d95a78Smarkfen {
263238d95a78Smarkfen 	(void) fprintf(file, dgettext(TEXT_DOMAIN, "%sPaired with spi=0x%x\n"),
263338d95a78Smarkfen 	    prefix, ntohl(pair->sadb_x_pair_spi));
263438d95a78Smarkfen }
26358810c16bSdanmcd 
26368810c16bSdanmcd /*
26378810c16bSdanmcd  * Take a PF_KEY message pointed to buffer and print it.  Useful for DUMP
26388810c16bSdanmcd  * and GET.
26398810c16bSdanmcd  */
26408810c16bSdanmcd void
print_samsg(FILE * file,uint64_t * buffer,boolean_t want_timestamp,boolean_t vflag,boolean_t ignore_nss)2641bb3ed8dfSpwernau print_samsg(FILE *file, uint64_t *buffer, boolean_t want_timestamp,
2642bb3ed8dfSpwernau     boolean_t vflag, boolean_t ignore_nss)
26438810c16bSdanmcd {
26448810c16bSdanmcd 	uint64_t *current;
26458810c16bSdanmcd 	struct sadb_msg *samsg = (struct sadb_msg *)buffer;
26468810c16bSdanmcd 	struct sadb_ext *ext;
26478810c16bSdanmcd 	struct sadb_lifetime *currentlt = NULL, *hardlt = NULL, *softlt = NULL;
26489c2c14abSThejaswini Singarajipura 	struct sadb_lifetime *idlelt = NULL;
26498810c16bSdanmcd 	int i;
26508810c16bSdanmcd 	time_t wallclock;
26518810c16bSdanmcd 
26528810c16bSdanmcd 	(void) time(&wallclock);
26538810c16bSdanmcd 
2654bb3ed8dfSpwernau 	print_sadb_msg(file, samsg, want_timestamp ? wallclock : 0, vflag);
26558810c16bSdanmcd 	current = (uint64_t *)(samsg + 1);
26568810c16bSdanmcd 	while (current - buffer < samsg->sadb_msg_len) {
26578810c16bSdanmcd 		int lenbytes;
26588810c16bSdanmcd 
26598810c16bSdanmcd 		ext = (struct sadb_ext *)current;
26608810c16bSdanmcd 		lenbytes = SADB_64TO8(ext->sadb_ext_len);
26618810c16bSdanmcd 		switch (ext->sadb_ext_type) {
26628810c16bSdanmcd 		case SADB_EXT_SA:
2663bb3ed8dfSpwernau 			print_sa(file, dgettext(TEXT_DOMAIN,
2664a7485808Smarkfen 			    "SA: "), (struct sadb_sa *)current);
26658810c16bSdanmcd 			break;
26668810c16bSdanmcd 		/*
26678810c16bSdanmcd 		 * Pluck out lifetimes and print them at the end.  This is
26688810c16bSdanmcd 		 * to show relative lifetimes.
26698810c16bSdanmcd 		 */
26708810c16bSdanmcd 		case SADB_EXT_LIFETIME_CURRENT:
26718810c16bSdanmcd 			currentlt = (struct sadb_lifetime *)current;
26728810c16bSdanmcd 			break;
26738810c16bSdanmcd 		case SADB_EXT_LIFETIME_HARD:
26748810c16bSdanmcd 			hardlt = (struct sadb_lifetime *)current;
26758810c16bSdanmcd 			break;
26768810c16bSdanmcd 		case SADB_EXT_LIFETIME_SOFT:
26778810c16bSdanmcd 			softlt = (struct sadb_lifetime *)current;
26788810c16bSdanmcd 			break;
26799c2c14abSThejaswini Singarajipura 		case SADB_X_EXT_LIFETIME_IDLE:
26809c2c14abSThejaswini Singarajipura 			idlelt = (struct sadb_lifetime *)current;
26819c2c14abSThejaswini Singarajipura 			break;
26828810c16bSdanmcd 
26838810c16bSdanmcd 		case SADB_EXT_ADDRESS_SRC:
2684bb3ed8dfSpwernau 			print_address(file, dgettext(TEXT_DOMAIN, "SRC: "),
2685bb3ed8dfSpwernau 			    (struct sadb_address *)current, ignore_nss);
26868810c16bSdanmcd 			break;
26878810c16bSdanmcd 		case SADB_X_EXT_ADDRESS_INNER_SRC:
2688bb3ed8dfSpwernau 			print_address(file, dgettext(TEXT_DOMAIN, "INS: "),
2689bb3ed8dfSpwernau 			    (struct sadb_address *)current, ignore_nss);
26908810c16bSdanmcd 			break;
26918810c16bSdanmcd 		case SADB_EXT_ADDRESS_DST:
2692bb3ed8dfSpwernau 			print_address(file, dgettext(TEXT_DOMAIN, "DST: "),
2693bb3ed8dfSpwernau 			    (struct sadb_address *)current, ignore_nss);
26948810c16bSdanmcd 			break;
26958810c16bSdanmcd 		case SADB_X_EXT_ADDRESS_INNER_DST:
2696bb3ed8dfSpwernau 			print_address(file, dgettext(TEXT_DOMAIN, "IND: "),
2697bb3ed8dfSpwernau 			    (struct sadb_address *)current, ignore_nss);
26988810c16bSdanmcd 			break;
26998810c16bSdanmcd 		case SADB_EXT_KEY_AUTH:
2700bb3ed8dfSpwernau 			print_key(file, dgettext(TEXT_DOMAIN,
2701a7485808Smarkfen 			    "AKY: "), (struct sadb_key *)current);
27028810c16bSdanmcd 			break;
27038810c16bSdanmcd 		case SADB_EXT_KEY_ENCRYPT:
2704bb3ed8dfSpwernau 			print_key(file, dgettext(TEXT_DOMAIN,
2705a7485808Smarkfen 			    "EKY: "), (struct sadb_key *)current);
27068810c16bSdanmcd 			break;
27078810c16bSdanmcd 		case SADB_EXT_IDENTITY_SRC:
2708bb3ed8dfSpwernau 			print_ident(file, dgettext(TEXT_DOMAIN, "SID: "),
27098810c16bSdanmcd 			    (struct sadb_ident *)current);
27108810c16bSdanmcd 			break;
27118810c16bSdanmcd 		case SADB_EXT_IDENTITY_DST:
2712bb3ed8dfSpwernau 			print_ident(file, dgettext(TEXT_DOMAIN, "DID: "),
27138810c16bSdanmcd 			    (struct sadb_ident *)current);
27148810c16bSdanmcd 			break;
27158810c16bSdanmcd 		case SADB_EXT_SENSITIVITY:
2716bb3ed8dfSpwernau 			print_sens(file, dgettext(TEXT_DOMAIN, "SNS: "),
27175d3b8cb7SBill Sommerfeld 			    (struct sadb_sens *)current, ignore_nss);
27188810c16bSdanmcd 			break;
27198810c16bSdanmcd 		case SADB_EXT_PROPOSAL:
2720bb3ed8dfSpwernau 			print_prop(file, dgettext(TEXT_DOMAIN, "PRP: "),
27218810c16bSdanmcd 			    (struct sadb_prop *)current);
27228810c16bSdanmcd 			break;
27238810c16bSdanmcd 		case SADB_EXT_SUPPORTED_AUTH:
2724bb3ed8dfSpwernau 			print_supp(file, dgettext(TEXT_DOMAIN, "SUA: "),
27258810c16bSdanmcd 			    (struct sadb_supported *)current);
27268810c16bSdanmcd 			break;
27278810c16bSdanmcd 		case SADB_EXT_SUPPORTED_ENCRYPT:
2728bb3ed8dfSpwernau 			print_supp(file, dgettext(TEXT_DOMAIN, "SUE: "),
27298810c16bSdanmcd 			    (struct sadb_supported *)current);
27308810c16bSdanmcd 			break;
27318810c16bSdanmcd 		case SADB_EXT_SPIRANGE:
2732bb3ed8dfSpwernau 			print_spirange(file, dgettext(TEXT_DOMAIN, "SPR: "),
27338810c16bSdanmcd 			    (struct sadb_spirange *)current);
27348810c16bSdanmcd 			break;
27358810c16bSdanmcd 		case SADB_X_EXT_EPROP:
2736bb3ed8dfSpwernau 			print_eprop(file, dgettext(TEXT_DOMAIN, "EPR: "),
27378810c16bSdanmcd 			    (struct sadb_prop *)current);
27388810c16bSdanmcd 			break;
27398810c16bSdanmcd 		case SADB_X_EXT_KM_COOKIE:
2740bb3ed8dfSpwernau 			print_kmc(file, dgettext(TEXT_DOMAIN, "KMC: "),
27418810c16bSdanmcd 			    (struct sadb_x_kmc *)current);
27428810c16bSdanmcd 			break;
27438810c16bSdanmcd 		case SADB_X_EXT_ADDRESS_NATT_REM:
2744bb3ed8dfSpwernau 			print_address(file, dgettext(TEXT_DOMAIN, "NRM: "),
2745bb3ed8dfSpwernau 			    (struct sadb_address *)current, ignore_nss);
27468810c16bSdanmcd 			break;
27478810c16bSdanmcd 		case SADB_X_EXT_ADDRESS_NATT_LOC:
2748bb3ed8dfSpwernau 			print_address(file, dgettext(TEXT_DOMAIN, "NLC: "),
2749bb3ed8dfSpwernau 			    (struct sadb_address *)current, ignore_nss);
27508810c16bSdanmcd 			break;
275138d95a78Smarkfen 		case SADB_X_EXT_PAIR:
275238d95a78Smarkfen 			print_pair(file, dgettext(TEXT_DOMAIN, "OTH: "),
275338d95a78Smarkfen 			    (struct sadb_x_pair *)current);
275438d95a78Smarkfen 			break;
27555d3b8cb7SBill Sommerfeld 		case SADB_X_EXT_OUTER_SENS:
27565d3b8cb7SBill Sommerfeld 			print_sens(file, dgettext(TEXT_DOMAIN, "OSN: "),
27575d3b8cb7SBill Sommerfeld 			    (struct sadb_sens *)current, ignore_nss);
27585d3b8cb7SBill Sommerfeld 			break;
27599c2c14abSThejaswini Singarajipura 		case SADB_X_EXT_REPLAY_VALUE:
27609c2c14abSThejaswini Singarajipura 			(void) print_replay(file, dgettext(TEXT_DOMAIN,
27619c2c14abSThejaswini Singarajipura 			    "RPL: "), (sadb_x_replay_ctr_t *)current);
27629c2c14abSThejaswini Singarajipura 			break;
27638810c16bSdanmcd 		default:
2764bb3ed8dfSpwernau 			(void) fprintf(file, dgettext(TEXT_DOMAIN,
27658810c16bSdanmcd 			    "UNK: Unknown ext. %d, len %d.\n"),
27668810c16bSdanmcd 			    ext->sadb_ext_type, lenbytes);
27678810c16bSdanmcd 			for (i = 0; i < ext->sadb_ext_len; i++)
2768bb3ed8dfSpwernau 				(void) fprintf(file, dgettext(TEXT_DOMAIN,
2769c51cb4bcSDan McDonald 				    "UNK: 0x%" PRIx64 "\n"),
2770c51cb4bcSDan McDonald 				    ((uint64_t *)ext)[i]);
27718810c16bSdanmcd 			break;
27728810c16bSdanmcd 		}
27738810c16bSdanmcd 		current += (lenbytes == 0) ?
27748810c16bSdanmcd 		    SADB_8TO64(sizeof (struct sadb_ext)) : ext->sadb_ext_len;
27758810c16bSdanmcd 	}
27768810c16bSdanmcd 	/*
27778810c16bSdanmcd 	 * Print lifetimes NOW.
27788810c16bSdanmcd 	 */
27799c2c14abSThejaswini Singarajipura 	if (currentlt != NULL || hardlt != NULL || softlt != NULL ||
27809c2c14abSThejaswini Singarajipura 	    idlelt != NULL)
27819c2c14abSThejaswini Singarajipura 		print_lifetimes(file, wallclock, currentlt, hardlt,
27829c2c14abSThejaswini Singarajipura 		    softlt, idlelt, vflag);
27838810c16bSdanmcd 
27848810c16bSdanmcd 	if (current - buffer != samsg->sadb_msg_len) {
2785bb3ed8dfSpwernau 		warnxfp(EFD(file), dgettext(TEXT_DOMAIN,
2786bb3ed8dfSpwernau 		    "WARNING: insufficient buffer space or corrupt message."));
27878810c16bSdanmcd 	}
27888810c16bSdanmcd 
2789bb3ed8dfSpwernau 	(void) fflush(file);	/* Make sure our message is out there. */
27908810c16bSdanmcd }
27918810c16bSdanmcd 
27928810c16bSdanmcd /*
27938810c16bSdanmcd  * save_XXX functions are used when "saving" the SA tables to either a
27948810c16bSdanmcd  * file or standard output.  They use the dump_XXX functions where needed,
27958810c16bSdanmcd  * but mostly they use the rparseXXX functions.
27968810c16bSdanmcd  */
27978810c16bSdanmcd 
27988810c16bSdanmcd /*
27998810c16bSdanmcd  * Print save information for a lifetime extension.
28008810c16bSdanmcd  *
28018810c16bSdanmcd  * NOTE : It saves the lifetime in absolute terms.  For example, if you
28028810c16bSdanmcd  * had a hard_usetime of 60 seconds, you'll save it as 60 seconds, even though
28038810c16bSdanmcd  * there may have been 59 seconds burned off the clock.
28048810c16bSdanmcd  */
28058810c16bSdanmcd boolean_t
save_lifetime(struct sadb_lifetime * lifetime,FILE * ofile)28068810c16bSdanmcd save_lifetime(struct sadb_lifetime *lifetime, FILE *ofile)
28078810c16bSdanmcd {
28088810c16bSdanmcd 	char *prefix;
28098810c16bSdanmcd 
28109c2c14abSThejaswini Singarajipura 	switch (lifetime->sadb_lifetime_exttype) {
28119c2c14abSThejaswini Singarajipura 	case SADB_EXT_LIFETIME_HARD:
28129c2c14abSThejaswini Singarajipura 		prefix = "hard";
28139c2c14abSThejaswini Singarajipura 		break;
28149c2c14abSThejaswini Singarajipura 	case SADB_EXT_LIFETIME_SOFT:
28159c2c14abSThejaswini Singarajipura 		prefix = "soft";
28169c2c14abSThejaswini Singarajipura 		break;
28179c2c14abSThejaswini Singarajipura 	case SADB_X_EXT_LIFETIME_IDLE:
28189c2c14abSThejaswini Singarajipura 		prefix = "idle";
28199c2c14abSThejaswini Singarajipura 		break;
28209c2c14abSThejaswini Singarajipura 	}
28218810c16bSdanmcd 
28228810c16bSdanmcd 	if (putc('\t', ofile) == EOF)
28238810c16bSdanmcd 		return (B_FALSE);
28248810c16bSdanmcd 
28258810c16bSdanmcd 	if (lifetime->sadb_lifetime_allocations != 0 && fprintf(ofile,
28268810c16bSdanmcd 	    "%s_alloc %u ", prefix, lifetime->sadb_lifetime_allocations) < 0)
28278810c16bSdanmcd 		return (B_FALSE);
28288810c16bSdanmcd 
28298810c16bSdanmcd 	if (lifetime->sadb_lifetime_bytes != 0 && fprintf(ofile,
2830c51cb4bcSDan McDonald 	    "%s_bytes %" PRIu64 " ", prefix, lifetime->sadb_lifetime_bytes) < 0)
28318810c16bSdanmcd 		return (B_FALSE);
28328810c16bSdanmcd 
28338810c16bSdanmcd 	if (lifetime->sadb_lifetime_addtime != 0 && fprintf(ofile,
2834c51cb4bcSDan McDonald 	    "%s_addtime %" PRIu64 " ", prefix,
2835c51cb4bcSDan McDonald 	    lifetime->sadb_lifetime_addtime) < 0)
28368810c16bSdanmcd 		return (B_FALSE);
28378810c16bSdanmcd 
28388810c16bSdanmcd 	if (lifetime->sadb_lifetime_usetime != 0 && fprintf(ofile,
2839c51cb4bcSDan McDonald 	    "%s_usetime %" PRIu64 " ", prefix,
2840c51cb4bcSDan McDonald 	    lifetime->sadb_lifetime_usetime) < 0)
28418810c16bSdanmcd 		return (B_FALSE);
28428810c16bSdanmcd 
28438810c16bSdanmcd 	return (B_TRUE);
28448810c16bSdanmcd }
28458810c16bSdanmcd 
28468810c16bSdanmcd /*
28478810c16bSdanmcd  * Print save information for an address extension.
28488810c16bSdanmcd  */
28498810c16bSdanmcd boolean_t
save_address(struct sadb_address * addr,FILE * ofile)28508810c16bSdanmcd save_address(struct sadb_address *addr, FILE *ofile)
28518810c16bSdanmcd {
28528810c16bSdanmcd 	char *printable_addr, buf[INET6_ADDRSTRLEN];
28538810c16bSdanmcd 	const char *prefix, *pprefix;
28548810c16bSdanmcd 	struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)(addr + 1);
28558810c16bSdanmcd 	struct sockaddr_in *sin = (struct sockaddr_in *)sin6;
28568810c16bSdanmcd 	int af = sin->sin_family;
28578810c16bSdanmcd 
28588810c16bSdanmcd 	/*
28598810c16bSdanmcd 	 * Address-family reality check.
28608810c16bSdanmcd 	 */
28618810c16bSdanmcd 	if (af != AF_INET6 && af != AF_INET)
28628810c16bSdanmcd 		return (B_FALSE);
28638810c16bSdanmcd 
28648810c16bSdanmcd 	switch (addr->sadb_address_exttype) {
28658810c16bSdanmcd 	case SADB_EXT_ADDRESS_SRC:
28668810c16bSdanmcd 		prefix = "src";
28678810c16bSdanmcd 		pprefix = "sport";
28688810c16bSdanmcd 		break;
28698810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_INNER_SRC:
28708810c16bSdanmcd 		prefix = "isrc";
28718810c16bSdanmcd 		pprefix = "isport";
28728810c16bSdanmcd 		break;
28738810c16bSdanmcd 	case SADB_EXT_ADDRESS_DST:
28748810c16bSdanmcd 		prefix = "dst";
28758810c16bSdanmcd 		pprefix = "dport";
28768810c16bSdanmcd 		break;
28778810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_INNER_DST:
28788810c16bSdanmcd 		prefix = "idst";
28798810c16bSdanmcd 		pprefix = "idport";
28808810c16bSdanmcd 		break;
28818810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_NATT_LOC:
28828810c16bSdanmcd 		prefix = "nat_loc ";
28838810c16bSdanmcd 		pprefix = "nat_lport";
28848810c16bSdanmcd 		break;
28858810c16bSdanmcd 	case SADB_X_EXT_ADDRESS_NATT_REM:
28868810c16bSdanmcd 		prefix = "nat_rem ";
28878810c16bSdanmcd 		pprefix = "nat_rport";
28888810c16bSdanmcd 		break;
28898810c16bSdanmcd 	}
28908810c16bSdanmcd 
28918810c16bSdanmcd 	if (fprintf(ofile, "    %s ", prefix) < 0)
28928810c16bSdanmcd 		return (B_FALSE);
28938810c16bSdanmcd 
28948810c16bSdanmcd 	/*
28958810c16bSdanmcd 	 * Do not do address-to-name translation, given that we live in
28968810c16bSdanmcd 	 * an age of names that explode into many addresses.
28978810c16bSdanmcd 	 */
28988810c16bSdanmcd 	printable_addr = (char *)inet_ntop(af,
28998810c16bSdanmcd 	    (af == AF_INET) ? (char *)&sin->sin_addr : (char *)&sin6->sin6_addr,
29008810c16bSdanmcd 	    buf, sizeof (buf));
29018810c16bSdanmcd 	if (printable_addr == NULL)
2902a7485808Smarkfen 		printable_addr = "Invalid IP address.";
29038810c16bSdanmcd 	if (fprintf(ofile, "%s", printable_addr) < 0)
29048810c16bSdanmcd 		return (B_FALSE);
29058810c16bSdanmcd 	if (addr->sadb_address_prefixlen != 0 &&
29068810c16bSdanmcd 	    !((addr->sadb_address_prefixlen == 32 && af == AF_INET) ||
29078810c16bSdanmcd 	    (addr->sadb_address_prefixlen == 128 && af == AF_INET6))) {
29088810c16bSdanmcd 		if (fprintf(ofile, "/%d", addr->sadb_address_prefixlen) < 0)
29098810c16bSdanmcd 			return (B_FALSE);
29108810c16bSdanmcd 	}
29118810c16bSdanmcd 
29128810c16bSdanmcd 	/*
29138810c16bSdanmcd 	 * The port is in the same position for struct sockaddr_in and
29148810c16bSdanmcd 	 * struct sockaddr_in6.  We exploit that property here.
29158810c16bSdanmcd 	 */
29168810c16bSdanmcd 	if ((pprefix != NULL) && (sin->sin_port != 0))
29178810c16bSdanmcd 		(void) fprintf(ofile, " %s %d", pprefix, ntohs(sin->sin_port));
29188810c16bSdanmcd 
29198810c16bSdanmcd 	return (B_TRUE);
29208810c16bSdanmcd }
29218810c16bSdanmcd 
29228810c16bSdanmcd /*
29238810c16bSdanmcd  * Print save information for a key extension. Returns whether writing
29248810c16bSdanmcd  * to the specified output file was successful or not.
29258810c16bSdanmcd  */
29268810c16bSdanmcd boolean_t
save_key(struct sadb_key * key,FILE * ofile)29278810c16bSdanmcd save_key(struct sadb_key *key, FILE *ofile)
29288810c16bSdanmcd {
29298810c16bSdanmcd 	char *prefix;
29308810c16bSdanmcd 
29318810c16bSdanmcd 	if (putc('\t', ofile) == EOF)
29328810c16bSdanmcd 		return (B_FALSE);
29338810c16bSdanmcd 
29348810c16bSdanmcd 	prefix = (key->sadb_key_exttype == SADB_EXT_KEY_AUTH) ? "auth" : "encr";
29358810c16bSdanmcd 
29368810c16bSdanmcd 	if (fprintf(ofile, "%skey ", prefix) < 0)
29378810c16bSdanmcd 		return (B_FALSE);
29388810c16bSdanmcd 
2939628b0c67SMark Fenwick 	if (dump_key((uint8_t *)(key + 1), key->sadb_key_bits,
2940628b0c67SMark Fenwick 	    key->sadb_key_reserved, ofile, B_FALSE) == -1)
29418810c16bSdanmcd 		return (B_FALSE);
29428810c16bSdanmcd 
29438810c16bSdanmcd 	return (B_TRUE);
29448810c16bSdanmcd }
29458810c16bSdanmcd 
29468810c16bSdanmcd /*
29478810c16bSdanmcd  * Print save information for an identity extension.
29488810c16bSdanmcd  */
29498810c16bSdanmcd boolean_t
save_ident(struct sadb_ident * ident,FILE * ofile)29508810c16bSdanmcd save_ident(struct sadb_ident *ident, FILE *ofile)
29518810c16bSdanmcd {
29528810c16bSdanmcd 	char *prefix;
29538810c16bSdanmcd 
29548810c16bSdanmcd 	if (putc('\t', ofile) == EOF)
29558810c16bSdanmcd 		return (B_FALSE);
29568810c16bSdanmcd 
29578810c16bSdanmcd 	prefix = (ident->sadb_ident_exttype == SADB_EXT_IDENTITY_SRC) ? "src" :
29588810c16bSdanmcd 	    "dst";
29598810c16bSdanmcd 
29608810c16bSdanmcd 	if (fprintf(ofile, "%sidtype %s ", prefix,
29618810c16bSdanmcd 	    rparseidtype(ident->sadb_ident_type)) < 0)
29628810c16bSdanmcd 		return (B_FALSE);
29638810c16bSdanmcd 
29648810c16bSdanmcd 	if (ident->sadb_ident_type == SADB_X_IDENTTYPE_DN ||
29658810c16bSdanmcd 	    ident->sadb_ident_type == SADB_X_IDENTTYPE_GN) {
2966a7485808Smarkfen 		if (fprintf(ofile, dgettext(TEXT_DOMAIN,
2967a7485808Smarkfen 		    "<can-not-print>")) < 0)
29688810c16bSdanmcd 			return (B_FALSE);
29698810c16bSdanmcd 	} else {
29708810c16bSdanmcd 		if (fprintf(ofile, "%s", (char *)(ident + 1)) < 0)
29718810c16bSdanmcd 			return (B_FALSE);
29728810c16bSdanmcd 	}
29738810c16bSdanmcd 
29748810c16bSdanmcd 	return (B_TRUE);
29758810c16bSdanmcd }
29768810c16bSdanmcd 
29775d3b8cb7SBill Sommerfeld boolean_t
save_sens(struct sadb_sens * sens,FILE * ofile)29785d3b8cb7SBill Sommerfeld save_sens(struct sadb_sens *sens, FILE *ofile)
29795d3b8cb7SBill Sommerfeld {
29805d3b8cb7SBill Sommerfeld 	char *prefix;
29815d3b8cb7SBill Sommerfeld 	char *hlabel;
29825d3b8cb7SBill Sommerfeld 	bslabel_t sl;
29835d3b8cb7SBill Sommerfeld 
29845d3b8cb7SBill Sommerfeld 	if (putc('\t', ofile) == EOF)
29855d3b8cb7SBill Sommerfeld 		return (B_FALSE);
29865d3b8cb7SBill Sommerfeld 
29875d3b8cb7SBill Sommerfeld 	if (sens->sadb_sens_exttype == SADB_EXT_SENSITIVITY)
29885d3b8cb7SBill Sommerfeld 		prefix = "label";
29895d3b8cb7SBill Sommerfeld 	else if ((sens->sadb_x_sens_flags & SADB_X_SENS_IMPLICIT) == 0)
29905d3b8cb7SBill Sommerfeld 		prefix = "outer-label";
29915d3b8cb7SBill Sommerfeld 	else
29925d3b8cb7SBill Sommerfeld 		prefix = "implicit-label";
29935d3b8cb7SBill Sommerfeld 
29945d3b8cb7SBill Sommerfeld 	ipsec_convert_sens_to_bslabel(sens, &sl);
29955d3b8cb7SBill Sommerfeld 	ipsec_convert_bslabel_to_hex(&sl, &hlabel);
29965d3b8cb7SBill Sommerfeld 
29975d3b8cb7SBill Sommerfeld 	if (fprintf(ofile, "%s %s ", prefix, hlabel) < 0) {
29985d3b8cb7SBill Sommerfeld 		free(hlabel);
29995d3b8cb7SBill Sommerfeld 		return (B_FALSE);
30005d3b8cb7SBill Sommerfeld 	}
30015d3b8cb7SBill Sommerfeld 	free(hlabel);
30025d3b8cb7SBill Sommerfeld 
30035d3b8cb7SBill Sommerfeld 	return (B_TRUE);
30045d3b8cb7SBill Sommerfeld }
30055d3b8cb7SBill Sommerfeld 
30068810c16bSdanmcd /*
30078810c16bSdanmcd  * "Save" a security association to an output file.
30088810c16bSdanmcd  *
3009a7485808Smarkfen  * NOTE the lack of calls to dgettext() because I'm outputting parseable stuff.
30108810c16bSdanmcd  * ALSO NOTE that if you change keywords (see parsecmd()), you'll have to
30118810c16bSdanmcd  * change them here as well.
30128810c16bSdanmcd  */
30138810c16bSdanmcd void
save_assoc(uint64_t * buffer,FILE * ofile)30148810c16bSdanmcd save_assoc(uint64_t *buffer, FILE *ofile)
30158810c16bSdanmcd {
3016a7485808Smarkfen 	int terrno;
3017437220cdSdanmcd 	boolean_t seen_proto = B_FALSE, seen_iproto = B_FALSE;
30188810c16bSdanmcd 	uint64_t *current;
30198810c16bSdanmcd 	struct sadb_address *addr;
30209c2c14abSThejaswini Singarajipura 	struct sadb_x_replay_ctr *repl;
30218810c16bSdanmcd 	struct sadb_msg *samsg = (struct sadb_msg *)buffer;
30228810c16bSdanmcd 	struct sadb_ext *ext;
30238810c16bSdanmcd 
3024a7485808Smarkfen #define	tidyup() \
3025a7485808Smarkfen 	terrno = errno; (void) fclose(ofile); errno = terrno; \
3026a7485808Smarkfen 	interactive = B_FALSE
3027a7485808Smarkfen 
3028a7485808Smarkfen #define	savenl() if (fputs(" \\\n", ofile) == EOF) \
3029a7485808Smarkfen 	{ bail(dgettext(TEXT_DOMAIN, "savenl")); }
30308810c16bSdanmcd 
30318810c16bSdanmcd 	if (fputs("# begin assoc\n", ofile) == EOF)
3032a7485808Smarkfen 		bail(dgettext(TEXT_DOMAIN,
3033a7485808Smarkfen 		    "save_assoc: Opening comment of SA"));
30348810c16bSdanmcd 	if (fprintf(ofile, "add %s ", rparsesatype(samsg->sadb_msg_satype)) < 0)
3035a7485808Smarkfen 		bail(dgettext(TEXT_DOMAIN, "save_assoc: First line of SA"));
30368810c16bSdanmcd 	savenl();
30378810c16bSdanmcd 
30388810c16bSdanmcd 	current = (uint64_t *)(samsg + 1);
30398810c16bSdanmcd 	while (current - buffer < samsg->sadb_msg_len) {
30408810c16bSdanmcd 		struct sadb_sa *assoc;
30418810c16bSdanmcd 
30428810c16bSdanmcd 		ext = (struct sadb_ext *)current;
3043437220cdSdanmcd 		addr = (struct sadb_address *)ext;  /* Just in case... */
30448810c16bSdanmcd 		switch (ext->sadb_ext_type) {
30458810c16bSdanmcd 		case SADB_EXT_SA:
30468810c16bSdanmcd 			assoc = (struct sadb_sa *)ext;
30478810c16bSdanmcd 			if (assoc->sadb_sa_state != SADB_SASTATE_MATURE) {
30488810c16bSdanmcd 				if (fprintf(ofile, "# WARNING: SA was dying "
30498810c16bSdanmcd 				    "or dead.\n") < 0) {
3050a7485808Smarkfen 					tidyup();
3051a7485808Smarkfen 					bail(dgettext(TEXT_DOMAIN,
3052a7485808Smarkfen 					    "save_assoc: fprintf not mature"));
30538810c16bSdanmcd 				}
30548810c16bSdanmcd 			}
30558810c16bSdanmcd 			if (fprintf(ofile, "    spi 0x%x ",
3056a7485808Smarkfen 			    ntohl(assoc->sadb_sa_spi)) < 0) {
3057a7485808Smarkfen 				tidyup();
3058a7485808Smarkfen 				bail(dgettext(TEXT_DOMAIN,
3059a7485808Smarkfen 				    "save_assoc: fprintf spi"));
3060a7485808Smarkfen 			}
30618810c16bSdanmcd 			if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) {
30628810c16bSdanmcd 				if (fprintf(ofile, "encr_alg %s ",
30638810c16bSdanmcd 				    rparsealg(assoc->sadb_sa_encrypt,
3064a7485808Smarkfen 				    IPSEC_PROTO_ESP)) < 0) {
3065a7485808Smarkfen 					tidyup();
3066a7485808Smarkfen 					bail(dgettext(TEXT_DOMAIN,
3067a7485808Smarkfen 					    "save_assoc: fprintf encrypt"));
3068a7485808Smarkfen 				}
30698810c16bSdanmcd 			}
30708810c16bSdanmcd 			if (assoc->sadb_sa_auth != SADB_AALG_NONE) {
30718810c16bSdanmcd 				if (fprintf(ofile, "auth_alg %s ",
30728810c16bSdanmcd 				    rparsealg(assoc->sadb_sa_auth,
3073a7485808Smarkfen 				    IPSEC_PROTO_AH)) < 0) {
3074a7485808Smarkfen 					tidyup();
3075a7485808Smarkfen 					bail(dgettext(TEXT_DOMAIN,
3076a7485808Smarkfen 					    "save_assoc: fprintf auth"));
3077a7485808Smarkfen 				}
30788810c16bSdanmcd 			}
30798810c16bSdanmcd 			if (fprintf(ofile, "replay %d ",
3080a7485808Smarkfen 			    assoc->sadb_sa_replay) < 0) {
3081a7485808Smarkfen 				tidyup();
3082a7485808Smarkfen 				bail(dgettext(TEXT_DOMAIN,
3083a7485808Smarkfen 				    "save_assoc: fprintf replay"));
3084a7485808Smarkfen 			}
30858810c16bSdanmcd 			if (assoc->sadb_sa_flags & (SADB_X_SAFLAGS_NATT_LOC |
30868810c16bSdanmcd 			    SADB_X_SAFLAGS_NATT_REM)) {
3087a7485808Smarkfen 				if (fprintf(ofile, "encap udp") < 0) {
3088a7485808Smarkfen 					tidyup();
3089a7485808Smarkfen 					bail(dgettext(TEXT_DOMAIN,
3090a7485808Smarkfen 					    "save_assoc: fprintf encap"));
30918810c16bSdanmcd 				}
3092a7485808Smarkfen 			}
30938810c16bSdanmcd 			savenl();
30948810c16bSdanmcd 			break;
30958810c16bSdanmcd 		case SADB_EXT_LIFETIME_HARD:
30968810c16bSdanmcd 		case SADB_EXT_LIFETIME_SOFT:
30979c2c14abSThejaswini Singarajipura 		case SADB_X_EXT_LIFETIME_IDLE:
3098a7485808Smarkfen 			if (!save_lifetime((struct sadb_lifetime *)ext,
3099a7485808Smarkfen 			    ofile)) {
3100a7485808Smarkfen 				tidyup();
3101a7485808Smarkfen 				bail(dgettext(TEXT_DOMAIN, "save_lifetime"));
3102a7485808Smarkfen 			}
31038810c16bSdanmcd 			savenl();
31048810c16bSdanmcd 			break;
31058810c16bSdanmcd 		case SADB_X_EXT_ADDRESS_INNER_SRC:
31068810c16bSdanmcd 		case SADB_X_EXT_ADDRESS_INNER_DST:
3107437220cdSdanmcd 			if (!seen_iproto && addr->sadb_address_proto) {
3108437220cdSdanmcd 				(void) fprintf(ofile, "    iproto %d",
3109437220cdSdanmcd 				    addr->sadb_address_proto);
3110437220cdSdanmcd 				savenl();
3111437220cdSdanmcd 				seen_iproto = B_TRUE;
3112437220cdSdanmcd 			}
3113437220cdSdanmcd 			goto skip_srcdst;  /* Hack to avoid cases below... */
3114437220cdSdanmcd 			/* FALLTHRU */
3115437220cdSdanmcd 		case SADB_EXT_ADDRESS_SRC:
3116437220cdSdanmcd 		case SADB_EXT_ADDRESS_DST:
31178810c16bSdanmcd 			if (!seen_proto && addr->sadb_address_proto) {
31188810c16bSdanmcd 				(void) fprintf(ofile, "    proto %d",
31198810c16bSdanmcd 				    addr->sadb_address_proto);
31208810c16bSdanmcd 				savenl();
3121437220cdSdanmcd 				seen_proto = B_TRUE;
31228810c16bSdanmcd 			}
3123437220cdSdanmcd 			/* FALLTHRU */
3124437220cdSdanmcd 		case SADB_X_EXT_ADDRESS_NATT_REM:
3125437220cdSdanmcd 		case SADB_X_EXT_ADDRESS_NATT_LOC:
3126437220cdSdanmcd skip_srcdst:
3127a7485808Smarkfen 			if (!save_address(addr, ofile)) {
3128a7485808Smarkfen 				tidyup();
3129a7485808Smarkfen 				bail(dgettext(TEXT_DOMAIN, "save_address"));
3130a7485808Smarkfen 			}
31318810c16bSdanmcd 			savenl();
31328810c16bSdanmcd 			break;
31338810c16bSdanmcd 		case SADB_EXT_KEY_AUTH:
31348810c16bSdanmcd 		case SADB_EXT_KEY_ENCRYPT:
3135a7485808Smarkfen 			if (!save_key((struct sadb_key *)ext, ofile)) {
3136a7485808Smarkfen 				tidyup();
3137a7485808Smarkfen 				bail(dgettext(TEXT_DOMAIN, "save_address"));
3138a7485808Smarkfen 			}
31398810c16bSdanmcd 			savenl();
31408810c16bSdanmcd 			break;
31418810c16bSdanmcd 		case SADB_EXT_IDENTITY_SRC:
31428810c16bSdanmcd 		case SADB_EXT_IDENTITY_DST:
3143a7485808Smarkfen 			if (!save_ident((struct sadb_ident *)ext, ofile)) {
3144a7485808Smarkfen 				tidyup();
3145a7485808Smarkfen 				bail(dgettext(TEXT_DOMAIN, "save_address"));
3146a7485808Smarkfen 			}
31478810c16bSdanmcd 			savenl();
31488810c16bSdanmcd 			break;
31499c2c14abSThejaswini Singarajipura 		case SADB_X_EXT_REPLAY_VALUE:
31509c2c14abSThejaswini Singarajipura 			repl = (sadb_x_replay_ctr_t *)ext;
31519c2c14abSThejaswini Singarajipura 			if ((repl->sadb_x_rc_replay32 == 0) &&
31529c2c14abSThejaswini Singarajipura 			    (repl->sadb_x_rc_replay64 == 0)) {
31539c2c14abSThejaswini Singarajipura 				tidyup();
31549c2c14abSThejaswini Singarajipura 				bail(dgettext(TEXT_DOMAIN, "Replay Value"));
31559c2c14abSThejaswini Singarajipura 			}
31569c2c14abSThejaswini Singarajipura 			if (fprintf(ofile, "replay_value %" PRIu64 "",
31579c2c14abSThejaswini Singarajipura 			    (repl->sadb_x_rc_replay32 == 0 ?
31589c2c14abSThejaswini Singarajipura 			    repl->sadb_x_rc_replay64 :
31599c2c14abSThejaswini Singarajipura 			    repl->sadb_x_rc_replay32)) < 0) {
31609c2c14abSThejaswini Singarajipura 				tidyup();
31619c2c14abSThejaswini Singarajipura 				bail(dgettext(TEXT_DOMAIN,
31629c2c14abSThejaswini Singarajipura 				    "save_assoc: fprintf replay value"));
31639c2c14abSThejaswini Singarajipura 			}
31649c2c14abSThejaswini Singarajipura 			savenl();
31659c2c14abSThejaswini Singarajipura 			break;
31668810c16bSdanmcd 		case SADB_EXT_SENSITIVITY:
31675d3b8cb7SBill Sommerfeld 		case SADB_X_EXT_OUTER_SENS:
31685d3b8cb7SBill Sommerfeld 			if (!save_sens((struct sadb_sens *)ext, ofile)) {
31695d3b8cb7SBill Sommerfeld 				tidyup();
31705d3b8cb7SBill Sommerfeld 				bail(dgettext(TEXT_DOMAIN, "save_sens"));
31715d3b8cb7SBill Sommerfeld 			}
31725d3b8cb7SBill Sommerfeld 			savenl();
31735d3b8cb7SBill Sommerfeld 			break;
31748810c16bSdanmcd 		default:
31758810c16bSdanmcd 			/* Skip over irrelevant extensions. */
31768810c16bSdanmcd 			break;
31778810c16bSdanmcd 		}
31788810c16bSdanmcd 		current += ext->sadb_ext_len;
31798810c16bSdanmcd 	}
31808810c16bSdanmcd 
3181a7485808Smarkfen 	if (fputs(dgettext(TEXT_DOMAIN, "\n# end assoc\n\n"), ofile) == EOF) {
3182a7485808Smarkfen 		tidyup();
3183a7485808Smarkfen 		bail(dgettext(TEXT_DOMAIN, "save_assoc: last fputs"));
3184a7485808Smarkfen 	}
31858810c16bSdanmcd }
31868810c16bSdanmcd 
31878810c16bSdanmcd /*
31888810c16bSdanmcd  * Open the output file for the "save" command.
31898810c16bSdanmcd  */
31908810c16bSdanmcd FILE *
opensavefile(char * filename)31918810c16bSdanmcd opensavefile(char *filename)
31928810c16bSdanmcd {
31938810c16bSdanmcd 	int fd;
31948810c16bSdanmcd 	FILE *retval;
31958810c16bSdanmcd 	struct stat buf;
31968810c16bSdanmcd 
31978810c16bSdanmcd 	/*
31988810c16bSdanmcd 	 * If the user specifies "-" or doesn't give a filename, then
31998810c16bSdanmcd 	 * dump to stdout.  Make sure to document the dangers of files
32008810c16bSdanmcd 	 * that are NFS, directing your output to strange places, etc.
32018810c16bSdanmcd 	 */
32028810c16bSdanmcd 	if (filename == NULL || strcmp("-", filename) == 0)
32038810c16bSdanmcd 		return (stdout);
32048810c16bSdanmcd 
32058810c16bSdanmcd 	/*
32068810c16bSdanmcd 	 * open the file with the create bits set.  Since I check for
32078810c16bSdanmcd 	 * real UID == root in main(), I won't worry about the ownership
32088810c16bSdanmcd 	 * problem.
32098810c16bSdanmcd 	 */
32108810c16bSdanmcd 	fd = open(filename, O_WRONLY | O_EXCL | O_CREAT | O_TRUNC, S_IRUSR);
32118810c16bSdanmcd 	if (fd == -1) {
32128810c16bSdanmcd 		if (errno != EEXIST)
3213a7485808Smarkfen 			bail_msg("%s %s: %s", filename, dgettext(TEXT_DOMAIN,
3214a7485808Smarkfen 			    "open error"),
32158810c16bSdanmcd 			    strerror(errno));
32168810c16bSdanmcd 		fd = open(filename, O_WRONLY | O_TRUNC, 0);
32178810c16bSdanmcd 		if (fd == -1)
3218a7485808Smarkfen 			bail_msg("%s %s: %s", filename, dgettext(TEXT_DOMAIN,
3219a7485808Smarkfen 			    "open error"), strerror(errno));
32208810c16bSdanmcd 		if (fstat(fd, &buf) == -1) {
32218810c16bSdanmcd 			(void) close(fd);
32228810c16bSdanmcd 			bail_msg("%s fstat: %s", filename, strerror(errno));
32238810c16bSdanmcd 		}
32248810c16bSdanmcd 		if (S_ISREG(buf.st_mode) &&
32258810c16bSdanmcd 		    ((buf.st_mode & S_IAMB) != S_IRUSR)) {
3226a7485808Smarkfen 			warnx(dgettext(TEXT_DOMAIN,
3227a7485808Smarkfen 			    "WARNING: Save file already exists with "
32288810c16bSdanmcd 			    "permission %o."), buf.st_mode & S_IAMB);
3229a7485808Smarkfen 			warnx(dgettext(TEXT_DOMAIN,
3230a7485808Smarkfen 			    "Normal users may be able to read IPsec "
32318810c16bSdanmcd 			    "keying material."));
32328810c16bSdanmcd 		}
32338810c16bSdanmcd 	}
32348810c16bSdanmcd 
32358810c16bSdanmcd 	/* Okay, we have an FD.  Assign it to a stdio FILE pointer. */
32368810c16bSdanmcd 	retval = fdopen(fd, "w");
32378810c16bSdanmcd 	if (retval == NULL) {
32388810c16bSdanmcd 		(void) close(fd);
3239a7485808Smarkfen 		bail_msg("%s %s: %s", filename, dgettext(TEXT_DOMAIN,
3240a7485808Smarkfen 		    "fdopen error"), strerror(errno));
32418810c16bSdanmcd 	}
32428810c16bSdanmcd 	return (retval);
32438810c16bSdanmcd }
32448810c16bSdanmcd 
32458810c16bSdanmcd const char *
do_inet_ntop(const void * addr,char * cp,size_t size)32468810c16bSdanmcd do_inet_ntop(const void *addr, char *cp, size_t size)
32478810c16bSdanmcd {
32488810c16bSdanmcd 	boolean_t isv4;
32498810c16bSdanmcd 	struct in6_addr *inaddr6 = (struct in6_addr *)addr;
32508810c16bSdanmcd 	struct in_addr inaddr;
32518810c16bSdanmcd 
32528810c16bSdanmcd 	if ((isv4 = IN6_IS_ADDR_V4MAPPED(inaddr6)) == B_TRUE) {
32538810c16bSdanmcd 		IN6_V4MAPPED_TO_INADDR(inaddr6, &inaddr);
32548810c16bSdanmcd 	}
32558810c16bSdanmcd 
32568810c16bSdanmcd 	return (inet_ntop(isv4 ? AF_INET : AF_INET6,
32578810c16bSdanmcd 	    isv4 ? (void *)&inaddr : inaddr6, cp, size));
32588810c16bSdanmcd }
32598810c16bSdanmcd 
32608810c16bSdanmcd char numprint[NBUF_SIZE];
32618810c16bSdanmcd 
32628810c16bSdanmcd /*
32638810c16bSdanmcd  * Parse and reverse parse a specific SA type (AH, ESP, etc.).
32648810c16bSdanmcd  */
32658810c16bSdanmcd static struct typetable {
32668810c16bSdanmcd 	char *type;
32678810c16bSdanmcd 	int token;
32688810c16bSdanmcd } type_table[] = {
32698810c16bSdanmcd 	{"all", SADB_SATYPE_UNSPEC},
32708810c16bSdanmcd 	{"ah",  SADB_SATYPE_AH},
32718810c16bSdanmcd 	{"esp", SADB_SATYPE_ESP},
32728810c16bSdanmcd 	/* PF_KEY NOTE:  More to come if net/pfkeyv2.h gets updated. */
32738810c16bSdanmcd 	{NULL, 0}	/* Token value is irrelevant for this entry. */
32748810c16bSdanmcd };
32758810c16bSdanmcd 
32768810c16bSdanmcd char *
rparsesatype(int type)32778810c16bSdanmcd rparsesatype(int type)
32788810c16bSdanmcd {
32798810c16bSdanmcd 	struct typetable *tt = type_table;
32808810c16bSdanmcd 
32818810c16bSdanmcd 	while (tt->type != NULL && type != tt->token)
32828810c16bSdanmcd 		tt++;
32838810c16bSdanmcd 
32848810c16bSdanmcd 	if (tt->type == NULL) {
32858810c16bSdanmcd 		(void) snprintf(numprint, NBUF_SIZE, "%d", type);
32868810c16bSdanmcd 	} else {
32878810c16bSdanmcd 		return (tt->type);
32888810c16bSdanmcd 	}
32898810c16bSdanmcd 
32908810c16bSdanmcd 	return (numprint);
32918810c16bSdanmcd }
32928810c16bSdanmcd 
32938810c16bSdanmcd 
32948810c16bSdanmcd /*
32958810c16bSdanmcd  * Return a string containing the name of the specified numerical algorithm
32968810c16bSdanmcd  * identifier.
32978810c16bSdanmcd  */
32988810c16bSdanmcd char *
rparsealg(uint8_t alg,int proto_num)32998810c16bSdanmcd rparsealg(uint8_t alg, int proto_num)
33008810c16bSdanmcd {
33018810c16bSdanmcd 	static struct ipsecalgent *holder = NULL; /* we're single-threaded */
33028810c16bSdanmcd 
33038810c16bSdanmcd 	if (holder != NULL)
33048810c16bSdanmcd 		freeipsecalgent(holder);
33058810c16bSdanmcd 
33068810c16bSdanmcd 	holder = getipsecalgbynum(alg, proto_num, NULL);
33078810c16bSdanmcd 	if (holder == NULL) {
33088810c16bSdanmcd 		(void) snprintf(numprint, NBUF_SIZE, "%d", alg);
33098810c16bSdanmcd 		return (numprint);
33108810c16bSdanmcd 	}
33118810c16bSdanmcd 
33128810c16bSdanmcd 	return (*(holder->a_names));
33138810c16bSdanmcd }
33148810c16bSdanmcd 
33158810c16bSdanmcd /*
33168810c16bSdanmcd  * Parse and reverse parse out a source/destination ID type.
33178810c16bSdanmcd  */
33188810c16bSdanmcd static struct idtypes {
33198810c16bSdanmcd 	char *idtype;
33208810c16bSdanmcd 	uint8_t retval;
33218810c16bSdanmcd } idtypes[] = {
33228810c16bSdanmcd 	{"prefix",	SADB_IDENTTYPE_PREFIX},
33238810c16bSdanmcd 	{"fqdn",	SADB_IDENTTYPE_FQDN},
33248810c16bSdanmcd 	{"domain",	SADB_IDENTTYPE_FQDN},
33258810c16bSdanmcd 	{"domainname",	SADB_IDENTTYPE_FQDN},
33268810c16bSdanmcd 	{"user_fqdn",	SADB_IDENTTYPE_USER_FQDN},
33278810c16bSdanmcd 	{"mailbox",	SADB_IDENTTYPE_USER_FQDN},
33288810c16bSdanmcd 	{"der_dn",	SADB_X_IDENTTYPE_DN},
33298810c16bSdanmcd 	{"der_gn",	SADB_X_IDENTTYPE_GN},
33308810c16bSdanmcd 	{NULL,		0}
33318810c16bSdanmcd };
33328810c16bSdanmcd 
33338810c16bSdanmcd char *
rparseidtype(uint16_t type)33348810c16bSdanmcd rparseidtype(uint16_t type)
33358810c16bSdanmcd {
33368810c16bSdanmcd 	struct idtypes *idp;
33378810c16bSdanmcd 
33388810c16bSdanmcd 	for (idp = idtypes; idp->idtype != NULL; idp++) {
33398810c16bSdanmcd 		if (type == idp->retval)
33408810c16bSdanmcd 			return (idp->idtype);
33418810c16bSdanmcd 	}
33428810c16bSdanmcd 
33438810c16bSdanmcd 	(void) snprintf(numprint, NBUF_SIZE, "%d", type);
33448810c16bSdanmcd 	return (numprint);
33458810c16bSdanmcd }
3346e3320f40Smarkfen 
3347e3320f40Smarkfen /*
3348e3320f40Smarkfen  * This is a general purpose exit function, calling functions can specify an
3349e3320f40Smarkfen  * error type. If the command calling this function was started by smf(5) the
3350e3320f40Smarkfen  * error type could be used as a hint to the restarter. In the future this
3351e3320f40Smarkfen  * function could be used to do something more intelligent with a process that
3352a1ba8781SMark Fenwick  * encounters an error. If exit() is called with an error code other than those
3353a1ba8781SMark Fenwick  * defined by smf(5), the program will just get restarted. Unless restarting
3354a1ba8781SMark Fenwick  * is likely to resolve the error condition, its probably sensible to just
3355a1ba8781SMark Fenwick  * log the error and keep running.
3356a1ba8781SMark Fenwick  *
3357a1ba8781SMark Fenwick  * The SERVICE_* exit_types mean nothing if the command was run from the
3358a1ba8781SMark Fenwick  * command line, just exit(). There are two special cases:
3359a1ba8781SMark Fenwick  *
3360a1ba8781SMark Fenwick  * SERVICE_DEGRADE - Not implemented in smf(5), one day it could hint that
3361a1ba8781SMark Fenwick  *                   the service is not running as well is it could. For
3362a1ba8781SMark Fenwick  *                   now, don't do anything, just record the error.
3363a1ba8781SMark Fenwick  * DEBUG_FATAL - Something happened, if the command was being run in debug
3364a1ba8781SMark Fenwick  *               mode, exit() as you really want to know something happened,
3365a1ba8781SMark Fenwick  *               otherwise just keep running. This is ignored when running
3366a1ba8781SMark Fenwick  *               under smf(5).
3367e3320f40Smarkfen  *
3368e3320f40Smarkfen  * The function will handle an optional variable args error message, this
3369e3320f40Smarkfen  * will be written to the error stream, typically a log file or stderr.
3370e3320f40Smarkfen  */
3371e3320f40Smarkfen void
ipsecutil_exit(exit_type_t type,char * fmri,FILE * fp,const char * fmt,...)3372e3320f40Smarkfen ipsecutil_exit(exit_type_t type, char *fmri, FILE *fp, const char *fmt, ...)
3373e3320f40Smarkfen {
3374e3320f40Smarkfen 	int exit_status;
3375e3320f40Smarkfen 	va_list args;
3376e3320f40Smarkfen 
3377e3320f40Smarkfen 	if (fp == NULL)
3378e3320f40Smarkfen 		fp = stderr;
3379e3320f40Smarkfen 	if (fmt != NULL) {
3380e3320f40Smarkfen 		va_start(args, fmt);
3381e3320f40Smarkfen 		vwarnxfp(fp, fmt, args);
3382e3320f40Smarkfen 		va_end(args);
3383e3320f40Smarkfen 	}
3384e3320f40Smarkfen 
3385e3320f40Smarkfen 	if (fmri == NULL) {
3386e3320f40Smarkfen 		/* Command being run directly from a shell. */
3387e3320f40Smarkfen 		switch (type) {
3388e3320f40Smarkfen 		case SERVICE_EXIT_OK:
3389e3320f40Smarkfen 			exit_status = 0;
3390e3320f40Smarkfen 			break;
3391e3320f40Smarkfen 		case SERVICE_DEGRADE:
3392e3320f40Smarkfen 			return;
3393e3320f40Smarkfen 		case SERVICE_BADPERM:
3394e3320f40Smarkfen 		case SERVICE_BADCONF:
3395e3320f40Smarkfen 		case SERVICE_MAINTAIN:
3396e3320f40Smarkfen 		case SERVICE_DISABLE:
3397e3320f40Smarkfen 		case SERVICE_FATAL:
3398e3320f40Smarkfen 		case SERVICE_RESTART:
3399a1ba8781SMark Fenwick 		case DEBUG_FATAL:
3400e3320f40Smarkfen 			warnxfp(fp, "Fatal error - exiting.");
3401e3320f40Smarkfen 			exit_status = 1;
3402e3320f40Smarkfen 			break;
3403e3320f40Smarkfen 		}
3404e3320f40Smarkfen 	} else {
3405e3320f40Smarkfen 		/* Command being run as a smf(5) method. */
3406e3320f40Smarkfen 		switch (type) {
3407e3320f40Smarkfen 		case SERVICE_EXIT_OK:
3408e3320f40Smarkfen 			exit_status = SMF_EXIT_OK;
3409e3320f40Smarkfen 			break;
3410a1ba8781SMark Fenwick 		case SERVICE_DEGRADE: /* Not implemented yet. */
3411a1ba8781SMark Fenwick 		case DEBUG_FATAL:
3412a1ba8781SMark Fenwick 			/* Keep running, don't exit(). */
3413e3320f40Smarkfen 			return;
3414e3320f40Smarkfen 		case SERVICE_BADPERM:
3415e3320f40Smarkfen 			warnxfp(fp, dgettext(TEXT_DOMAIN,
3416e3320f40Smarkfen 			    "Permission error with %s."), fmri);
3417e3320f40Smarkfen 			exit_status = SMF_EXIT_ERR_PERM;
3418e3320f40Smarkfen 			break;
3419e3320f40Smarkfen 		case SERVICE_BADCONF:
3420e3320f40Smarkfen 			warnxfp(fp, dgettext(TEXT_DOMAIN,
3421e3320f40Smarkfen 			    "Bad configuration of service %s."), fmri);
3422e3320f40Smarkfen 			exit_status = SMF_EXIT_ERR_FATAL;
3423e3320f40Smarkfen 			break;
3424e3320f40Smarkfen 		case SERVICE_MAINTAIN:
3425e3320f40Smarkfen 			warnxfp(fp, dgettext(TEXT_DOMAIN,
3426e3320f40Smarkfen 			    "Service %s needs maintenance."), fmri);
3427e3320f40Smarkfen 			exit_status = SMF_EXIT_ERR_FATAL;
3428e3320f40Smarkfen 			break;
3429e3320f40Smarkfen 		case SERVICE_DISABLE:
3430e3320f40Smarkfen 			exit_status = SMF_EXIT_ERR_FATAL;
3431e3320f40Smarkfen 			break;
3432e3320f40Smarkfen 		case SERVICE_FATAL:
3433e3320f40Smarkfen 			warnxfp(fp, dgettext(TEXT_DOMAIN,
3434e3320f40Smarkfen 			    "Service %s fatal error."), fmri);
3435e3320f40Smarkfen 			exit_status = SMF_EXIT_ERR_FATAL;
3436e3320f40Smarkfen 			break;
3437e3320f40Smarkfen 		case SERVICE_RESTART:
3438e3320f40Smarkfen 			exit_status = 1;
3439e3320f40Smarkfen 			break;
3440e3320f40Smarkfen 		}
3441e3320f40Smarkfen 	}
3442e3320f40Smarkfen 	(void) fflush(fp);
3443e3320f40Smarkfen 	(void) fclose(fp);
3444e3320f40Smarkfen 	exit(exit_status);
3445e3320f40Smarkfen }
3446