Home | History | Annotate | Download | only in ipsecutils
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*
     27  * NOTE:I'm trying to use "struct sadb_foo" instead of "sadb_foo_t"
     28  *	as a maximal PF_KEY portability test.
     29  *
     30  *	Also, this is a deliberately single-threaded app, also for portability
     31  *	to systems without POSIX threads.
     32  */
     33 
     34 #include <sys/types.h>
     35 #include <sys/stat.h>
     36 #include <sys/socket.h>
     37 #include <sys/sysmacros.h>
     38 #include <sys/fcntl.h>
     39 #include <net/pfkeyv2.h>
     40 #include <arpa/inet.h>
     41 #include <netinet/in.h>
     42 #include <sys/uio.h>
     43 
     44 #include <syslog.h>
     45 #include <signal.h>
     46 #include <unistd.h>
     47 #include <limits.h>
     48 #include <stdlib.h>
     49 #include <stdio.h>
     50 #include <stdarg.h>
     51 #include <netdb.h>
     52 #include <pwd.h>
     53 #include <errno.h>
     54 #include <libintl.h>
     55 #include <locale.h>
     56 #include <fcntl.h>
     57 #include <strings.h>
     58 #include <ctype.h>
     59 #include <sys/cladm.h>
     60 
     61 #include <ipsec_util.h>
     62 
     63 static int keysock;
     64 static int cluster_socket;
     65 static uint32_t seq;
     66 static pid_t mypid;
     67 static boolean_t vflag = B_FALSE;	/* Verbose? */
     68 static boolean_t cflag = B_FALSE;	/* Check Only */
     69 
     70 char *my_fmri = NULL;
     71 FILE *debugfile = stdout;
     72 static struct sockaddr_in cli_addr;
     73 static boolean_t in_cluster_mode = B_FALSE;
     74 
     75 #define	MAX_GET_SIZE	1024
     76 /*
     77  * WARN() and ERROR() do the same thing really, with ERROR() the function
     78  * that prints the error buffer needs to be called at the end of a code block
     79  * This will print out all accumulated errors before bailing. The WARN()
     80  * macro calls handle_errors() in such a way that it prints the message
     81  * then continues.
     82  * If the FATAL() macro used call handle_errors() immediately.
     83  */
     84 #define	ERROR(x, y, z)  x = record_error(x, y, z)
     85 #define	ERROR1(w, x, y, z)  w = record_error(w, x, y, z)
     86 #define	ERROR2(v, w, x, y, z)  v = record_error(v, w, x, y, z)
     87 #define	WARN(x, y, z) ERROR(x, y, z);\
     88 	handle_errors(x, NULL, B_FALSE, B_FALSE); x = NULL
     89 #define	WARN1(w, x, y, z) ERROR1(w, x, y, z);\
     90 	handle_errors(w, NULL, B_FALSE, B_FALSE); w = NULL
     91 #define	WARN2(v, w, x, y, z) ERROR2(v, w, x, y, z);\
     92 	handle_errors(v, NULL, B_FALSE, B_FALSE); v = NULL
     93 #define	FATAL(x, y, z) ERROR(x, y, z);\
     94 	handle_errors(x, y, B_TRUE, B_TRUE)
     95 #define	FATAL1(w, x, y, z) ERROR1(w, x, y, z);\
     96 	handle_errors(w, x, B_TRUE, B_TRUE)
     97 
     98 /* Defined as a uint64_t array for alignment purposes. */
     99 static uint64_t get_buffer[MAX_GET_SIZE];
    100 
    101 /*
    102  * Disable default TAB completion for now (until some brave soul tackles it).
    103  */
    104 /* ARGSUSED */
    105 static
    106 CPL_MATCH_FN(no_match)
    107 {
    108 	return (0);
    109 }
    110 
    111 /*
    112  * Create/Grow a buffer large enough to hold error messages. If *ebuf
    113  * is not NULL then it will contain a copy of the command line that
    114  * triggered the error/warning, copy this into a new buffer or
    115  * append new messages to the existing buffer.
    116  */
    117 /*PRINTFLIKE1*/
    118 char *
    119 record_error(char *ep, char *ebuf, char *fmt, ...)
    120 {
    121 	char *err_ptr;
    122 	char tmp_buff[1024];
    123 	va_list ap;
    124 	int length = 0;
    125 	err_ptr = ep;
    126 
    127 	va_start(ap, fmt);
    128 	length = vsnprintf(tmp_buff, sizeof (tmp_buff), fmt, ap);
    129 	va_end(ap);
    130 
    131 	/* There is a new line character */
    132 	length++;
    133 
    134 	if (ep == NULL) {
    135 		if (ebuf != NULL)
    136 			length += strlen(ebuf);
    137 	} else  {
    138 		length += strlen(ep);
    139 	}
    140 
    141 	if (err_ptr == NULL)
    142 		err_ptr = calloc(length, sizeof (char));
    143 	else
    144 		err_ptr = realloc(err_ptr, length);
    145 
    146 	if (err_ptr == NULL)
    147 		Bail("realloc() failure");
    148 
    149 	/*
    150 	 * If (ep == NULL) then this is the first error to record,
    151 	 * copy in the command line that triggered this error/warning.
    152 	 */
    153 	if (ep == NULL && ebuf != NULL)
    154 		(void) strlcpy(err_ptr, ebuf, length);
    155 
    156 	/*
    157 	 * Now the actual error.
    158 	 */
    159 	(void) strlcat(err_ptr, tmp_buff, length);
    160 	return (err_ptr);
    161 }
    162 
    163 /*
    164  * If not in interactive mode print usage message and exit.
    165  */
    166 static void
    167 usage(void)
    168 {
    169 	if (!interactive) {
    170 		(void) fprintf(stderr, gettext("Usage:\t"
    171 		    "ipseckey [ -nvp ] | cmd [sa_type] [extfield value]*\n"));
    172 		(void) fprintf(stderr,
    173 		    gettext("\tipseckey [ -nvp ] -f infile\n"));
    174 		(void) fprintf(stderr,
    175 		    gettext("\tipseckey [ -nvp ] -s outfile\n"));
    176 		EXIT_FATAL(NULL);
    177 	} else {
    178 		(void) fprintf(stderr,
    179 		    gettext("Type help or ? for usage info\n"));
    180 	}
    181 }
    182 
    183 
    184 /*
    185  * Print out any errors, tidy up as required.
    186  * error pointer ep will be free()'d
    187  */
    188 void
    189 handle_errors(char *ep, char *ebuf, boolean_t fatal, boolean_t done)
    190 {
    191 	if (ep != NULL) {
    192 		if (my_fmri == NULL) {
    193 			/*
    194 			 * For now suppress the errors when run from smf(5)
    195 			 * because potentially sensitive information could
    196 			 * end up in a publicly readable logfile.
    197 			 */
    198 			(void) fprintf(stdout, "%s\n", ep);
    199 			(void) fflush(stdout);
    200 		}
    201 		free(ep);
    202 		if (fatal) {
    203 			if (ebuf != NULL) {
    204 				free(ebuf);
    205 			}
    206 			/* reset command buffer */
    207 			if (interactive)
    208 				longjmp(env, 1);
    209 		} else {
    210 			return;
    211 		}
    212 	} else {
    213 		/*
    214 		 * No errors, if this is the last time that this function
    215 		 * is called, free(ebuf) and reset command buffer.
    216 		 */
    217 		if (done) {
    218 			if (ebuf != NULL) {
    219 				free(ebuf);
    220 			}
    221 			/* reset command buffer */
    222 			if (interactive)
    223 				longjmp(env, 1);
    224 		}
    225 		return;
    226 	}
    227 	EXIT_FATAL(NULL);
    228 }
    229 
    230 /*
    231  * Initialize a PF_KEY base message.
    232  */
    233 static void
    234 msg_init(struct sadb_msg *msg, uint8_t type, uint8_t satype)
    235 {
    236 	msg->sadb_msg_version = PF_KEY_V2;
    237 	msg->sadb_msg_type = type;
    238 	msg->sadb_msg_errno = 0;
    239 	msg->sadb_msg_satype = satype;
    240 	/* For starters... */
    241 	msg->sadb_msg_len = SADB_8TO64(sizeof (*msg));
    242 	msg->sadb_msg_reserved = 0;
    243 	msg->sadb_msg_seq = ++seq;
    244 	msg->sadb_msg_pid = mypid;
    245 }
    246 
    247 /*
    248  * parseXXX and rparseXXX commands parse input and convert them to PF_KEY
    249  * field values, or do the reverse for the purposes of saving the SA tables.
    250  * (See the save_XXX functions.)
    251  */
    252 
    253 #define	CMD_NONE	0
    254 #define	CMD_UPDATE	2
    255 #define	CMD_UPDATE_PAIR	3
    256 #define	CMD_ADD		4
    257 #define	CMD_DELETE	5
    258 #define	CMD_DELETE_PAIR	6
    259 #define	CMD_GET		7
    260 #define	CMD_FLUSH	9
    261 #define	CMD_DUMP	10
    262 #define	CMD_MONITOR	11
    263 #define	CMD_PMONITOR	12
    264 #define	CMD_QUIT	13
    265 #define	CMD_SAVE	14
    266 #define	CMD_HELP	15
    267 
    268 /*
    269  * Parse the command.
    270  */
    271 static int
    272 parsecmd(char *cmdstr)
    273 {
    274 	static struct cmdtable {
    275 		char *cmd;
    276 		int token;
    277 	} table[] = {
    278 		/*
    279 		 * Q: Do we want to do GETSPI?
    280 		 * A: No, it's for automated key mgmt. only.  Either that,
    281 		 *    or it isn't relevant until we support non IPsec SA types.
    282 		 */
    283 		{"update",		CMD_UPDATE},
    284 		{"update-pair",		CMD_UPDATE_PAIR},
    285 		{"add",			CMD_ADD},
    286 		{"delete", 		CMD_DELETE},
    287 		{"delete-pair",		CMD_DELETE_PAIR},
    288 		{"get", 		CMD_GET},
    289 		/*
    290 		 * Q: And ACQUIRE and REGISTER and EXPIRE?
    291 		 * A: not until we support non IPsec SA types.
    292 		 */
    293 		{"flush",		CMD_FLUSH},
    294 		{"dump",		CMD_DUMP},
    295 		{"monitor",		CMD_MONITOR},
    296 		{"passive_monitor",	CMD_PMONITOR},
    297 		{"pmonitor",		CMD_PMONITOR},
    298 		{"quit",		CMD_QUIT},
    299 		{"exit",		CMD_QUIT},
    300 		{"save",		CMD_SAVE},
    301 		{"help",		CMD_HELP},
    302 		{"?",			CMD_HELP},
    303 		{NULL,			CMD_NONE}
    304 	};
    305 	struct cmdtable *ct = table;
    306 
    307 	while (ct->cmd != NULL && strcmp(ct->cmd, cmdstr) != 0)
    308 		ct++;
    309 	return (ct->token);
    310 }
    311 
    312 /*
    313  * Convert a number from a command line.  I picked "u_longlong_t" for the
    314  * number because we need the largest number available.  Also, the strto<num>
    315  * calls don't deal in units of uintNN_t.
    316  */
    317 static u_longlong_t
    318 parsenum(char *num, boolean_t bail, char *ebuf)
    319 {
    320 	u_longlong_t rc = 0;
    321 	char *end = NULL;
    322 	char *ep = NULL;
    323 
    324 	if (num == NULL) {
    325 		FATAL(ep, ebuf, gettext("Unexpected end of command line,"
    326 		    " was expecting a number.\n"));
    327 		/* NOTREACHED */
    328 	}
    329 
    330 	errno = 0;
    331 	rc = strtoull(num, &end, 0);
    332 	if (errno != 0 || end == num || *end != '\0') {
    333 		if (bail) {
    334 			FATAL1(ep, ebuf, gettext(
    335 			"Expecting a number, not \"%s\"!\n"), num);
    336 		} else {
    337 			/*
    338 			 * -1, while not optimal, is sufficiently out of range
    339 			 * for most of this function's applications when
    340 			 * we don't just bail.
    341 			 */
    342 			return ((u_longlong_t)-1);
    343 		}
    344 	}
    345 	handle_errors(ep, NULL, B_FALSE, B_FALSE);
    346 	return (rc);
    347 }
    348 
    349 /*
    350  * Parse and reverse parse a specific SA type (AH, ESP, etc.).
    351  */
    352 static struct typetable {
    353 	char *type;
    354 	int token;
    355 } type_table[] = {
    356 	{"all",	SADB_SATYPE_UNSPEC},
    357 	{"ah",	SADB_SATYPE_AH},
    358 	{"esp",	SADB_SATYPE_ESP},
    359 	/* PF_KEY NOTE:  More to come if net/pfkeyv2.h gets updated. */
    360 	{NULL,	0}	/* Token value is irrelevant for this entry. */
    361 };
    362 
    363 
    364 static int
    365 parsesatype(char *type, char *ebuf)
    366 {
    367 	struct typetable *tt = type_table;
    368 	char *ep = NULL;
    369 
    370 	if (type == NULL)
    371 		return (SADB_SATYPE_UNSPEC);
    372 
    373 	while (tt->type != NULL && strcasecmp(tt->type, type) != 0)
    374 		tt++;
    375 
    376 	/*
    377 	 * New SA types (including ones keysock maintains for user-land
    378 	 * protocols) may be added, so parse a numeric value if possible.
    379 	 */
    380 	if (tt->type == NULL) {
    381 		tt->token = (int)parsenum(type, B_FALSE, ebuf);
    382 		if (tt->token == -1) {
    383 			ERROR1(ep, ebuf, gettext(
    384 			    "Unknown SA type (%s).\n"), type);
    385 			tt->token = SADB_SATYPE_UNSPEC;
    386 		}
    387 	}
    388 	handle_errors(ep, NULL, interactive ? B_TRUE : B_FALSE, B_FALSE);
    389 	return (tt->token);
    390 }
    391 
    392 #define	NEXTEOF		0
    393 #define	NEXTNONE	1
    394 #define	NEXTNUM		2
    395 #define	NEXTSTR		3
    396 #define	NEXTNUMSTR	4
    397 #define	NEXTADDR	5
    398 #define	NEXTHEX		6
    399 #define	NEXTIDENT	7
    400 #define	NEXTADDR4	8
    401 #define	NEXTADDR6	9
    402 #define	NEXTLABEL	10
    403 
    404 #define	TOK_EOF			0
    405 #define	TOK_UNKNOWN		1
    406 #define	TOK_SPI			2
    407 #define	TOK_REPLAY		3
    408 #define	TOK_STATE		4
    409 #define	TOK_AUTHALG		5
    410 #define	TOK_ENCRALG		6
    411 #define	TOK_FLAGS		7
    412 #define	TOK_SOFT_ALLOC		8
    413 #define	TOK_SOFT_BYTES		9
    414 #define	TOK_SOFT_ADDTIME	10
    415 #define	TOK_SOFT_USETIME	11
    416 #define	TOK_HARD_ALLOC		12
    417 #define	TOK_HARD_BYTES		13
    418 #define	TOK_HARD_ADDTIME	14
    419 #define	TOK_HARD_USETIME	15
    420 #define	TOK_CURRENT_ALLOC	16
    421 #define	TOK_CURRENT_BYTES	17
    422 #define	TOK_CURRENT_ADDTIME	18
    423 #define	TOK_CURRENT_USETIME	19
    424 #define	TOK_SRCADDR		20
    425 #define	TOK_DSTADDR		21
    426 #define	TOK_PROXYADDR		22
    427 #define	TOK_AUTHKEY		23
    428 #define	TOK_ENCRKEY		24
    429 #define	TOK_SRCIDTYPE		25
    430 #define	TOK_DSTIDTYPE		26
    431 #define	TOK_DPD			27
    432 #define	TOK_SENS_LEVEL		28
    433 #define	TOK_SENS_MAP		29
    434 #define	TOK_INTEG_LEVEL		30
    435 #define	TOK_INTEG_MAP		31
    436 #define	TOK_SRCADDR6		32
    437 #define	TOK_DSTADDR6		33
    438 #define	TOK_PROXYADDR6		34
    439 #define	TOK_SRCPORT		35
    440 #define	TOK_DSTPORT		36
    441 #define	TOK_PROTO		37
    442 #define	TOK_ENCAP		38
    443 #define	TOK_NATLOC		39
    444 #define	TOK_NATREM		40
    445 #define	TOK_NATLPORT		41
    446 #define	TOK_NATRPORT		42
    447 #define	TOK_IPROTO		43
    448 #define	TOK_IDSTADDR		44
    449 #define	TOK_IDSTADDR6		45
    450 #define	TOK_ISRCPORT		46
    451 #define	TOK_IDSTPORT		47
    452 #define	TOK_PAIR_SPI		48
    453 #define	TOK_FLAG_INBOUND	49
    454 #define	TOK_FLAG_OUTBOUND	50
    455 #define	TOK_REPLAY_VALUE	51
    456 #define	TOK_IDLE_ADDTIME	52
    457 #define	TOK_IDLE_USETIME	53
    458 #define	TOK_RESERVED		54
    459 #define	TOK_LABEL		55
    460 #define	TOK_OLABEL		56
    461 #define	TOK_IMPLABEL		57
    462 
    463 
    464 static struct toktable {
    465 	char *string;
    466 	int token;
    467 	int next;
    468 } tokens[] = {
    469 	/* "String",		token value,		next arg is */
    470 	{"spi",			TOK_SPI,		NEXTNUM},
    471 	{"pair-spi",		TOK_PAIR_SPI,		NEXTNUM},
    472 	{"replay",		TOK_REPLAY,		NEXTNUM},
    473 	{"state",		TOK_STATE,		NEXTNUMSTR},
    474 	{"auth_alg",		TOK_AUTHALG,		NEXTNUMSTR},
    475 	{"authalg",		TOK_AUTHALG,		NEXTNUMSTR},
    476 	{"encr_alg",		TOK_ENCRALG,		NEXTNUMSTR},
    477 	{"encralg",		TOK_ENCRALG,		NEXTNUMSTR},
    478 	{"flags",		TOK_FLAGS,		NEXTNUM},
    479 	{"soft_alloc",		TOK_SOFT_ALLOC,		NEXTNUM},
    480 	{"soft_bytes",		TOK_SOFT_BYTES,		NEXTNUM},
    481 	{"soft_addtime",	TOK_SOFT_ADDTIME,	NEXTNUM},
    482 	{"soft_usetime",	TOK_SOFT_USETIME,	NEXTNUM},
    483 	{"hard_alloc",		TOK_HARD_ALLOC,		NEXTNUM},
    484 	{"hard_bytes",		TOK_HARD_BYTES,		NEXTNUM},
    485 	{"hard_addtime",	TOK_HARD_ADDTIME,	NEXTNUM},
    486 	{"hard_usetime",	TOK_HARD_USETIME,	NEXTNUM},
    487 	{"current_alloc",	TOK_CURRENT_ALLOC,	NEXTNUM},
    488 	{"current_bytes",	TOK_CURRENT_BYTES,	NEXTNUM},
    489 	{"current_addtime",	TOK_CURRENT_ADDTIME,	NEXTNUM},
    490 	{"current_usetime",	TOK_CURRENT_USETIME,	NEXTNUM},
    491 
    492 	{"saddr",		TOK_SRCADDR,		NEXTADDR},
    493 	{"srcaddr",		TOK_SRCADDR,		NEXTADDR},
    494 	{"src",			TOK_SRCADDR,		NEXTADDR},
    495 	{"daddr",		TOK_DSTADDR,		NEXTADDR},
    496 	{"dstaddr",		TOK_DSTADDR,		NEXTADDR},
    497 	{"dst",			TOK_DSTADDR,		NEXTADDR},
    498 	{"proxyaddr",		TOK_PROXYADDR,		NEXTADDR},
    499 	{"proxy",		TOK_PROXYADDR,		NEXTADDR},
    500 	{"innersrc",		TOK_PROXYADDR,		NEXTADDR},
    501 	{"isrc",		TOK_PROXYADDR,		NEXTADDR},
    502 	{"innerdst",		TOK_IDSTADDR,		NEXTADDR},
    503 	{"idst",		TOK_IDSTADDR,		NEXTADDR},
    504 
    505 	{"sport",		TOK_SRCPORT,		NEXTNUM},
    506 	{"dport",		TOK_DSTPORT,		NEXTNUM},
    507 	{"innersport",		TOK_ISRCPORT,		NEXTNUM},
    508 	{"isport",		TOK_ISRCPORT,		NEXTNUM},
    509 	{"innerdport",		TOK_IDSTPORT,		NEXTNUM},
    510 	{"idport",		TOK_IDSTPORT,		NEXTNUM},
    511 	{"proto",		TOK_PROTO,		NEXTNUM},
    512 	{"ulp",			TOK_PROTO,		NEXTNUM},
    513 	{"iproto",		TOK_IPROTO,		NEXTNUM},
    514 	{"iulp",		TOK_IPROTO,		NEXTNUM},
    515 
    516 	{"saddr6",		TOK_SRCADDR6,		NEXTADDR},
    517 	{"srcaddr6",		TOK_SRCADDR6,		NEXTADDR},
    518 	{"src6",		TOK_SRCADDR6,		NEXTADDR},
    519 	{"daddr6",		TOK_DSTADDR6,		NEXTADDR},
    520 	{"dstaddr6",		TOK_DSTADDR6,		NEXTADDR},
    521 	{"dst6",		TOK_DSTADDR6,		NEXTADDR},
    522 	{"proxyaddr6",		TOK_PROXYADDR6,		NEXTADDR},
    523 	{"proxy6",		TOK_PROXYADDR6,		NEXTADDR},
    524 	{"innersrc6",		TOK_PROXYADDR6,		NEXTADDR},
    525 	{"isrc6",		TOK_PROXYADDR6,		NEXTADDR},
    526 	{"innerdst6",		TOK_IDSTADDR6,		NEXTADDR},
    527 	{"idst6",		TOK_IDSTADDR6,		NEXTADDR},
    528 
    529 	{"authkey",		TOK_AUTHKEY,		NEXTHEX},
    530 	{"encrkey",		TOK_ENCRKEY,		NEXTHEX},
    531 	{"srcidtype",		TOK_SRCIDTYPE,		NEXTIDENT},
    532 	{"dstidtype",		TOK_DSTIDTYPE,		NEXTIDENT},
    533 	{"dpd",			TOK_DPD,		NEXTNUM},
    534 	{"sens_level",		TOK_SENS_LEVEL,		NEXTNUM},
    535 	{"sens_map",		TOK_SENS_MAP,		NEXTHEX},
    536 	{"integ_level",		TOK_INTEG_LEVEL,	NEXTNUM},
    537 	{"integ_map",		TOK_INTEG_MAP,		NEXTHEX},
    538 	{"nat_loc",		TOK_NATLOC,		NEXTADDR},
    539 	{"nat_rem",		TOK_NATREM,		NEXTADDR},
    540 	{"nat_lport",		TOK_NATLPORT,		NEXTNUM},
    541 	{"nat_rport",		TOK_NATRPORT,		NEXTNUM},
    542 	{"encap",		TOK_ENCAP,		NEXTNUMSTR},
    543 
    544 	{"outbound",		TOK_FLAG_OUTBOUND,	NULL},
    545 	{"inbound",		TOK_FLAG_INBOUND,	NULL},
    546 
    547 	{"reserved_bits",	TOK_RESERVED,		NEXTNUM},
    548 	{"replay_value",	TOK_REPLAY_VALUE,	NEXTNUM},
    549 	{"idle_addtime",	TOK_IDLE_ADDTIME,	NEXTNUM},
    550 	{"idle_usetime",	TOK_IDLE_USETIME,	NEXTNUM},
    551 
    552 	{"label",		TOK_LABEL,		NEXTLABEL},
    553 	{"outer-label",		TOK_OLABEL,		NEXTLABEL},
    554 	{"implicit-label",	TOK_IMPLABEL,		NEXTLABEL},
    555 
    556 	{NULL,			TOK_UNKNOWN,		NEXTEOF}
    557 };
    558 
    559 /*
    560  * Q:	Do I need stuff for proposals, combinations, supported algorithms,
    561  *	or SPI ranges?
    562  *
    563  * A:	Probably not, but you never know.
    564  *
    565  * Parse out extension header type values.
    566  */
    567 static int
    568 parseextval(char *value, int *next)
    569 {
    570 	struct toktable *tp;
    571 
    572 	if (value == NULL)
    573 		return (TOK_EOF);
    574 
    575 	for (tp = tokens; tp->string != NULL; tp++)
    576 		if (strcmp(value, tp->string) == 0)
    577 			break;
    578 
    579 	/*
    580 	 * Since the OS controls what extensions are available, we don't have
    581 	 * to parse numeric values here.
    582 	 */
    583 
    584 	*next = tp->next;
    585 	return (tp->token);
    586 }
    587 
    588 /*
    589  * Parse possible state values.
    590  */
    591 static uint8_t
    592 parsestate(char *state, char *ebuf)
    593 {
    594 	struct states {
    595 		char *state;
    596 		uint8_t retval;
    597 	} states[] = {
    598 		{"larval",	SADB_SASTATE_LARVAL},
    599 		{"mature",	SADB_SASTATE_MATURE},
    600 		{"dying",	SADB_SASTATE_DYING},
    601 		{"dead",	SADB_SASTATE_DEAD},
    602 		{NULL,		0}
    603 	};
    604 	struct states *sp;
    605 	char *ep = NULL;
    606 
    607 	if (state == NULL) {
    608 		FATAL(ep, ebuf, "Unexpected end of command line "
    609 		    "was expecting a state.\n");
    610 	}
    611 
    612 	for (sp = states; sp->state != NULL; sp++) {
    613 		if (strcmp(sp->state, state) == 0)
    614 			return (sp->retval);
    615 	}
    616 	ERROR1(ep, ebuf, gettext("Unknown state type \"%s\"\n"), state);
    617 	handle_errors(ep, NULL, B_FALSE, B_FALSE);
    618 	return (0);
    619 }
    620 
    621 /*
    622  * Return the numerical algorithm identifier corresponding to the specified
    623  * algorithm name.
    624  */
    625 static uint8_t
    626 parsealg(char *alg, int proto_num, char *ebuf)
    627 {
    628 	u_longlong_t invalue;
    629 	struct ipsecalgent *algent;
    630 	char *ep = NULL;
    631 
    632 	if (alg == NULL) {
    633 		FATAL(ep, ebuf, gettext("Unexpected end of command line, "
    634 		    "was expecting an algorithm name.\n"));
    635 	}
    636 
    637 	algent = getipsecalgbyname(alg, proto_num, NULL);
    638 	if (algent != NULL) {
    639 		uint8_t alg_num;
    640 
    641 		alg_num = algent->a_alg_num;
    642 		if (ALG_FLAG_COUNTERMODE & algent->a_alg_flags)
    643 			WARN1(ep, ebuf, gettext(
    644 			    "Using manual keying with a Counter mode algorithm "
    645 			    "such as \"%s\" may be insecure!\n"),
    646 			    algent->a_names[0]);
    647 		freeipsecalgent(algent);
    648 
    649 		return (alg_num);
    650 	}
    651 
    652 	/*
    653 	 * Since algorithms can be loaded during kernel run-time, check for
    654 	 * numeric algorithm values too.  PF_KEY can catch bad ones with EINVAL.
    655 	 */
    656 	invalue = parsenum(alg, B_FALSE, ebuf);
    657 	if (invalue != (u_longlong_t)-1 &&
    658 	    (u_longlong_t)(invalue & (u_longlong_t)0xff) == invalue)
    659 		return ((uint8_t)invalue);
    660 
    661 	if (proto_num == IPSEC_PROTO_ESP) {
    662 		ERROR1(ep, ebuf, gettext(
    663 		    "Unknown encryption algorithm type \"%s\"\n"), alg);
    664 	} else {
    665 		ERROR1(ep, ebuf, gettext(
    666 		    "Unknown authentication algorithm type \"%s\"\n"), alg);
    667 	}
    668 	handle_errors(ep, NULL, B_FALSE, B_FALSE);
    669 	return (0);
    670 }
    671 
    672 /*
    673  * Parse and reverse parse out a source/destination ID type.
    674  */
    675 static struct idtypes {
    676 	char *idtype;
    677 	uint8_t retval;
    678 } idtypes[] = {
    679 	{"prefix",	SADB_IDENTTYPE_PREFIX},
    680 	{"fqdn",	SADB_IDENTTYPE_FQDN},
    681 	{"domain",	SADB_IDENTTYPE_FQDN},
    682 	{"domainname",	SADB_IDENTTYPE_FQDN},
    683 	{"user_fqdn",	SADB_IDENTTYPE_USER_FQDN},
    684 	{"mailbox",	SADB_IDENTTYPE_USER_FQDN},
    685 	{"der_dn",	SADB_X_IDENTTYPE_DN},
    686 	{"der_gn",	SADB_X_IDENTTYPE_GN},
    687 	{NULL,		0}
    688 };
    689 
    690 static uint16_t
    691 parseidtype(char *type, char *ebuf)
    692 {
    693 	struct idtypes *idp;
    694 	u_longlong_t invalue;
    695 	char *ep = NULL;
    696 
    697 	if (type == NULL) {
    698 		/* Shouldn't reach here, see callers for why. */
    699 		FATAL(ep, ebuf, gettext("Unexpected end of command line, "
    700 		    "was expecting a type.\n"));
    701 	}
    702 
    703 	for (idp = idtypes; idp->idtype != NULL; idp++) {
    704 		if (strcasecmp(idp->idtype, type) == 0)
    705 			return (idp->retval);
    706 	}
    707 	/*
    708 	 * Since identity types are almost arbitrary, check for numeric
    709 	 * algorithm values too.  PF_KEY can catch bad ones with EINVAL.
    710 	 */
    711 	invalue = parsenum(type, B_FALSE, ebuf);
    712 	if (invalue != (u_longlong_t)-1 &&
    713 	    (u_longlong_t)(invalue & (u_longlong_t)0xffff) == invalue)
    714 		return ((uint16_t)invalue);
    715 
    716 
    717 	ERROR1(ep, ebuf, gettext("Unknown identity type \"%s\"\n"), type);
    718 
    719 	handle_errors(ep, NULL, B_FALSE, B_FALSE);
    720 	return (0);
    721 }
    722 
    723 /*
    724  * Parse an address off the command line.  Return length of sockaddr,
    725  * and either return a hostent pointer (caller frees).  The new
    726  * getipnodebyname() call does the Right Thing (TM), even with
    727  * raw addresses (colon-separated IPv6 or dotted decimal IPv4).
    728  */
    729 
    730 static struct {
    731 	struct hostent he;
    732 	char *addtl[2];
    733 	} dummy;
    734 static union {
    735 	struct in6_addr ipv6;
    736 	struct in_addr ipv4;
    737 	uint64_t aligner;
    738 } addr1;
    739 
    740 static int
    741 parseaddr(char *addr, struct hostent **hpp, boolean_t v6only, char *ebuf)
    742 {
    743 	int hp_errno;
    744 	struct hostent *hp = NULL;
    745 	char *ep = NULL;
    746 
    747 	if (addr == NULL) {
    748 		FATAL(ep, ebuf, gettext("Unexpected end of command line, "
    749 		    "was expecting an address.\n"));
    750 	}
    751 
    752 	if (!nflag) {
    753 		/*
    754 		 * Try name->address first.  Assume AF_INET6, and
    755 		 * get IPv4's, plus IPv6's if and only if IPv6 is configured.
    756 		 * This means to add IPv6 SAs, you must have IPv6
    757 		 * up-and-running.  (AI_DEFAULT works here.)
    758 		 */
    759 		hp = getipnodebyname(addr, AF_INET6,
    760 		    (v6only ? AI_ADDRCONFIG : (AI_DEFAULT | AI_ALL)),
    761 		    &hp_errno);
    762 	} else {
    763 		/*
    764 		 * Try a normal address conversion only.  Use "dummy"
    765 		 * to construct a fake hostent.  Caller will know not
    766 		 * to free this one.
    767 		 */
    768 		if (inet_pton(AF_INET6, addr, &addr1) == 1) {
    769 			dummy.he.h_addr_list = dummy.addtl;
    770 			dummy.addtl[0] = (char *)&addr1;
    771 			dummy.addtl[1] = NULL;
    772 			hp = &dummy.he;
    773 			dummy.he.h_addrtype = AF_INET6;
    774 			dummy.he.h_length = sizeof (struct in6_addr);
    775 		} else if (inet_pton(AF_INET, addr, &addr1) == 1) {
    776 			/*
    777 			 * Remap to AF_INET6 anyway.
    778 			 */
    779 			dummy.he.h_addr_list = dummy.addtl;
    780 			dummy.addtl[0] = (char *)&addr1;
    781 			dummy.addtl[1] = NULL;
    782 			hp = &dummy.he;
    783 			dummy.he.h_addrtype = AF_INET6;
    784 			dummy.he.h_length = sizeof (struct in6_addr);
    785 			/*
    786 			 * NOTE:  If macro changes to disallow in-place
    787 			 * conversion, rewhack this.
    788 			 */
    789 			IN6_INADDR_TO_V4MAPPED(&addr1.ipv4, &addr1.ipv6);
    790 		} else {
    791 			hp = NULL;
    792 		}
    793 	}
    794 
    795 	if (hp == NULL)
    796 		WARN1(ep, ebuf, gettext("Unknown address %s."), addr);
    797 
    798 	*hpp = hp;
    799 	/* Always return sockaddr_in6 for now. */
    800 	handle_errors(ep, NULL, B_FALSE, B_FALSE);
    801 	return (sizeof (struct sockaddr_in6));
    802 }
    803 
    804 /*
    805  * Parse a hex character for a key.  A string will take the form:
    806  *	xxxxxxxxx/nn
    807  * where
    808  *	xxxxxxxxx == a string of hex characters ([0-9][a-f][A-F])
    809  *	nn == an optional decimal "mask".  If it is not present, it
    810  *	is assumed that the hex string will be rounded to the nearest
    811  *	byte, where odd nibbles, like 123 will become 0x0123.
    812  *
    813  * NOTE:Unlike the expression of IP addresses, I will not allow an
    814  *	excessive "mask".  For example 2112/50 is very illegal.
    815  * NOTE2:	This key should be in canonical order.  Consult your man
    816  *		pages per algorithm about said order.
    817  */
    818 
    819 #define	hd2num(hd) (((hd) >= '0' && (hd) <= '9') ? ((hd) - '0') : \
    820 	(((hd) >= 'a' && (hd) <= 'f') ? ((hd) - 'a' + 10) : ((hd) - 'A' + 10)))
    821 
    822 static struct sadb_key *
    823 parsekey(char *input, char *ebuf, uint_t reserved_bits)
    824 {
    825 	struct sadb_key *retval;
    826 	uint_t i, hexlen = 0, bits, alloclen;
    827 	uint8_t *key;
    828 	char *ep = NULL;
    829 
    830 	if (input == NULL) {
    831 		FATAL(ep, ebuf, gettext("Unexpected end of command line, "
    832 		    "was expecting a key.\n"));
    833 	}
    834 	/* Allow hex values prepended with 0x convention */
    835 	if ((strnlen(input, sizeof (hexlen)) > 2) &&
    836 	    (strncasecmp(input, "0x", 2) == 0))
    837 		input += 2;
    838 
    839 	for (i = 0; input[i] != '\0' && input[i] != '/'; i++)
    840 		hexlen++;
    841 
    842 	if (input[i] == '\0') {
    843 		bits = 0;
    844 	} else {
    845 		/* Have /nn. */
    846 		input[i] = '\0';
    847 		if (sscanf((input + i + 1), "%u", &bits) != 1) {
    848 			FATAL1(ep, ebuf, gettext(
    849 			    "\"%s\" is not a bit specifier.\n"),
    850 			    (input + i + 1));
    851 		}
    852 		/* hexlen in nibbles */
    853 		if (((bits + 3) >> 2) > hexlen) {
    854 			ERROR2(ep, ebuf, gettext(
    855 			    "bit length %d is too big for %s.\n"), bits, input);
    856 		}
    857 		/*
    858 		 * Adjust hexlen down if user gave us too small of a bit
    859 		 * count.
    860 		 */
    861 		if ((hexlen << 2) > bits + 3) {
    862 			WARN2(ep, ebuf, gettext(
    863 			    "WARNING: Lower bits will be truncated "
    864 			    "for:\n\t%s/%d.\n"), input, bits);
    865 			hexlen = (bits + 3) >> 2;
    866 			input[hexlen] = '\0';
    867 		}
    868 	}
    869 
    870 	/*
    871 	 * Allocate.  Remember, hexlen is in nibbles.
    872 	 */
    873 
    874 	alloclen = sizeof (*retval) + roundup((hexlen/2 + (hexlen & 0x1)), 8);
    875 	retval = malloc(alloclen);
    876 
    877 	if (retval == NULL)
    878 		Bail("malloc(parsekey)");
    879 	retval->sadb_key_len = SADB_8TO64(alloclen);
    880 
    881 	retval->sadb_key_reserved = reserved_bits;
    882 
    883 	if (bits == 0)
    884 		retval->sadb_key_bits = (hexlen + (hexlen & 0x1)) << 2;
    885 	else
    886 		retval->sadb_key_bits = bits;
    887 
    888 	/*
    889 	 * Read in nibbles.  Read in odd-numbered as shifted high.
    890 	 * (e.g. 123 becomes 0x1230).
    891 	 */
    892 
    893 	key = (uint8_t *)(retval + 1);
    894 	for (i = 0; input[i] != '\0'; i += 2) {
    895 		boolean_t second = (input[i + 1] != '\0');
    896 
    897 		if (!isxdigit(input[i]) ||
    898 		    (!isxdigit(input[i + 1]) && second)) {
    899 			ERROR1(ep, ebuf, gettext(
    900 			    "string '%s' not a hex value.\n"), input);
    901 			free(retval);
    902 			retval = NULL;
    903 			break;
    904 		}
    905 		*key = (hd2num(input[i]) << 4);
    906 		if (second)
    907 			*key |= hd2num(input[i + 1]);
    908 		else
    909 			break;	/* out of for loop. */
    910 		key++;
    911 	}
    912 
    913 	/* bzero the remaining bits if we're a non-octet amount. */
    914 	if (bits & 0x7)
    915 		*((input[i] == '\0') ? key - 1 : key) &=
    916 		    0xff << (8 - (bits & 0x7));
    917 
    918 	handle_errors(ep, NULL, B_FALSE, B_FALSE);
    919 	return (retval);
    920 }
    921 
    922 #include <tsol/label.h>
    923 
    924 #define	PARSELABEL_BAD_TOKEN ((struct sadb_sens *)-1)
    925 
    926 static struct sadb_sens *
    927 parselabel(int token, char *label)
    928 {
    929 	bslabel_t *sl = NULL;
    930 	int err, len;
    931 	sadb_sens_t *sens;
    932 	int doi = 1;  /* XXX XXX DEFAULT_DOI XXX XXX */
    933 
    934 	err = str_to_label(label, &sl, MAC_LABEL, L_DEFAULT, NULL);
    935 	if (err < 0)
    936 		return (NULL);
    937 
    938 	len = ipsec_convert_sl_to_sens(doi, sl, NULL);
    939 
    940 	sens = malloc(len);
    941 	if (sens == NULL) {
    942 		Bail("malloc parsed label");
    943 		/* Should exit before reaching here... */
    944 		return (NULL);
    945 	}
    946 
    947 	(void) ipsec_convert_sl_to_sens(doi, sl, sens);
    948 
    949 	switch (token) {
    950 	case TOK_LABEL:
    951 		break;
    952 
    953 	case TOK_OLABEL:
    954 		sens->sadb_sens_exttype = SADB_X_EXT_OUTER_SENS;
    955 		break;
    956 
    957 	case TOK_IMPLABEL:
    958 		sens->sadb_sens_exttype = SADB_X_EXT_OUTER_SENS;
    959 		sens->sadb_x_sens_flags = SADB_X_SENS_IMPLICIT;
    960 		break;
    961 
    962 	default:
    963 		free(sens);
    964 		/*
    965 		 * Return a different return code for a bad label, but really,
    966 		 * this would be a caller error.
    967 		 */
    968 		return (PARSELABEL_BAD_TOKEN);
    969 	}
    970 
    971 	return (sens);
    972 }
    973 
    974 /*
    975  * Write a message to the PF_KEY socket.  If verbose, print the message
    976  * heading into the kernel.
    977  */
    978 static int
    979 key_write(int fd, void *msg, size_t len)
    980 {
    981 	if (vflag) {
    982 		(void) printf(
    983 		    gettext("VERBOSE ON:  Message to kernel looks like:\n"));
    984 		(void) printf("==========================================\n");
    985 		print_samsg(stdout, msg, B_FALSE, vflag, nflag);
    986 		(void) printf("==========================================\n");
    987 	}
    988 
    989 	return (write(fd, msg, len));
    990 }
    991 
    992 /*
    993  * SIGALRM handler for time_critical_enter.
    994  */
    995 static void
    996 time_critical_catch(int signal)
    997 {
    998 	if (signal == SIGALRM) {
    999 		errx(1, gettext("Reply message from PF_KEY timed out."));
   1000 	} else {
   1001 		errx(1, gettext("Caught signal %d while trying to receive"
   1002 		    "PF_KEY reply message"), signal);
   1003 	}
   1004 	/* errx() calls exit. */
   1005 }
   1006 
   1007 #define	TIME_CRITICAL_TIME 10	/* In seconds */
   1008 
   1009 /*
   1010  * Enter a "time critical" section where key is waiting for a return message.
   1011  */
   1012 static void
   1013 time_critical_enter(void)
   1014 {
   1015 	(void) signal(SIGALRM, time_critical_catch);
   1016 	(void) alarm(TIME_CRITICAL_TIME);
   1017 }
   1018 
   1019 /*
   1020  * Exit the "time critical" section after getting an appropriate return
   1021  * message.
   1022  */
   1023 static void
   1024 time_critical_exit(void)
   1025 {
   1026 	(void) alarm(0);
   1027 	(void) signal(SIGALRM, SIG_DFL);
   1028 }
   1029 
   1030 /*
   1031  * Construct a PF_KEY FLUSH message for the SA type specified.
   1032  */
   1033 static void
   1034 doflush(int satype)
   1035 {
   1036 	struct sadb_msg msg;
   1037 	int rc;
   1038 
   1039 	msg_init(&msg, SADB_FLUSH, (uint8_t)satype);
   1040 	rc = key_write(keysock, &msg, sizeof (msg));
   1041 	if (rc == -1)
   1042 		Bail("write() to PF_KEY socket failed (in doflush)");
   1043 
   1044 	time_critical_enter();
   1045 	do {
   1046 		rc = read(keysock, &msg, sizeof (msg));
   1047 		if (rc == -1)
   1048 			Bail("read (in doflush)");
   1049 	} while (msg.sadb_msg_seq != seq || msg.sadb_msg_pid != mypid);
   1050 	time_critical_exit();
   1051 
   1052 	/*
   1053 	 * I should _never_ hit the following unless:
   1054 	 *
   1055 	 * 1. There is a kernel bug.
   1056 	 * 2. There is another process filling in its pid with mine, and
   1057 	 *    issuing a different message that would cause a different result.
   1058 	 */
   1059 	if (msg.sadb_msg_type != SADB_FLUSH ||
   1060 	    msg.sadb_msg_satype != (uint8_t)satype) {
   1061 		syslog((LOG_NOTICE|LOG_AUTH),
   1062 		    gettext("doflush: Return message not of type SADB_FLUSH!"));
   1063 		Bail("doflush: Return message not of type SADB_FLUSH!");
   1064 	}
   1065 
   1066 	if (msg.sadb_msg_errno != 0) {
   1067 		errno = msg.sadb_msg_errno;
   1068 		if (errno == EINVAL) {
   1069 			print_diagnostic(stderr, msg.sadb_x_msg_diagnostic);
   1070 			warnx(gettext("Cannot flush SA type %d."), satype);
   1071 		}
   1072 		Bail("return message (in doflush)");
   1073 	}
   1074 }
   1075 
   1076 /*
   1077  * save_XXX functions are used when "saving" the SA tables to either a
   1078  * file or standard output.  They use the dump_XXX functions where needed,
   1079  * but mostly they use the rparseXXX functions.
   1080  */
   1081 
   1082 /*
   1083  * Because "save" and "dump" both use the SADB_DUMP message, fold both
   1084  * into the same function.
   1085  */
   1086 static void
   1087 dodump(int satype, FILE *ofile)
   1088 {
   1089 	struct sadb_msg *msg = (struct sadb_msg *)get_buffer;
   1090 	int rc;
   1091 
   1092 	if (ofile != NULL) {
   1093 		(void) fprintf(ofile,
   1094 		    gettext("# This key file was generated by the"));
   1095 		(void) fprintf(ofile,
   1096 		    gettext(" ipseckey(1m) command's 'save' feature.\n\n"));
   1097 	}
   1098 	msg_init(msg, SADB_DUMP, (uint8_t)satype);
   1099 	rc = key_write(keysock, msg, sizeof (*msg));
   1100 	if (rc == -1)
   1101 		Bail("write to PF_KEY socket failed (in dodump)");
   1102 
   1103 	do {
   1104 		/*
   1105 		 * For DUMP, do only the read as a time critical section.
   1106 		 */
   1107 		time_critical_enter();
   1108 		rc = read(keysock, get_buffer, sizeof (get_buffer));
   1109 		time_critical_exit();
   1110 		if (rc == -1)
   1111 			Bail("read (in dodump)");
   1112 		if (msg->sadb_msg_pid == mypid &&
   1113 		    msg->sadb_msg_type == SADB_DUMP &&
   1114 		    msg->sadb_msg_seq != 0 &&
   1115 		    msg->sadb_msg_errno == 0) {
   1116 			if (ofile == NULL) {
   1117 				print_samsg(stdout, get_buffer, B_FALSE, vflag,
   1118 				    nflag);
   1119 				(void) putchar('\n');
   1120 			} else {
   1121 				save_assoc(get_buffer, ofile);
   1122 			}
   1123 		}
   1124 	} while (msg->sadb_msg_pid != mypid ||
   1125 	    (msg->sadb_msg_errno == 0 && msg->sadb_msg_seq != 0));
   1126 
   1127 	if (ofile != NULL && ofile != stdout)
   1128 		(void) fclose(ofile);
   1129 
   1130 	if (msg->sadb_msg_errno == 0) {
   1131 		if (ofile == NULL)
   1132 			(void) printf(
   1133 			    gettext("Dump succeeded for SA type %d.\n"),
   1134 			    satype);
   1135 	} else {
   1136 		print_diagnostic(stderr, msg->sadb_x_msg_diagnostic);
   1137 		errno = msg->sadb_msg_errno;
   1138 		Bail("Dump failed");
   1139 	}
   1140 }
   1141 
   1142 #define	SCOPE_UNSPEC 0
   1143 #define	SCOPE_LINKLOCAL 1
   1144 #define	SCOPE_SITELOCAL 2
   1145 #define	SCOPE_GLOBAL 3
   1146 #define	SCOPE_V4COMPAT 4
   1147 #define	SCOPE_LOOPBACK 5	/* Pedantic, yes, but necessary. */
   1148 
   1149 static int
   1150 ipv6_addr_scope(struct in6_addr *addr)
   1151 {
   1152 	/* Don't return anything regarding multicast for now... */
   1153 
   1154 	if (IN6_IS_ADDR_UNSPECIFIED(addr))
   1155 		return (SCOPE_UNSPEC);
   1156 
   1157 	if (IN6_IS_ADDR_LINKLOCAL(addr))
   1158 		return (SCOPE_LINKLOCAL);
   1159 
   1160 	if (IN6_IS_ADDR_SITELOCAL(addr))
   1161 		return (SCOPE_SITELOCAL);
   1162 
   1163 	if (IN6_IS_ADDR_V4COMPAT(addr))
   1164 		return (SCOPE_V4COMPAT);
   1165 
   1166 	if (IN6_IS_ADDR_LOOPBACK(addr))
   1167 		return (SCOPE_LOOPBACK);
   1168 
   1169 	/* For now, return global by default. */
   1170 	return (SCOPE_GLOBAL);
   1171 }
   1172 
   1173 /*
   1174  * doaddresses():
   1175  *
   1176  * Used by doaddup() and dodelget() to create new SA's based on the
   1177  * provided source and destination addresses hostent.
   1178  *
   1179  * sadb_msg_type: expected PF_KEY reply message type
   1180  * sadb_msg_satype: expected PF_KEY reply satype
   1181  * cmd: user command
   1182  * srchp: hostent for the source address(es)
   1183  * dsthp: hostent for the destination address(es)
   1184  * src: points to the SADB source address extension
   1185  * dst: points to the SADB destination address extension
   1186  * unspec_src: indicates an unspecified source address.
   1187  * buffer: pointer to the SADB buffer to use with PF_KEY
   1188  * buffer_size: size of buffer
   1189  * spi: spi for this message (set by caller)
   1190  * srcport: source port if specified
   1191  * dstport: destination port if specified
   1192  * proto: IP protocol number if specified
   1193  * iproto: Inner (tunnel mode) IP protocol number if specified
   1194  * NATT note: we are going to assume a semi-sane world where NAT
   1195  * boxen don't explode to multiple addresses.
   1196  */
   1197 static void
   1198 doaddresses(uint8_t sadb_msg_type, uint8_t sadb_msg_satype, int cmd,
   1199     struct hostent *srchp, struct hostent *dsthp,
   1200     struct sadb_address *src, struct sadb_address *dst,
   1201     boolean_t unspec_src, uint64_t *buffer, int buffer_size, uint32_t spi,
   1202     char *ebuf)
   1203 {
   1204 	boolean_t single_dst;
   1205 	struct sockaddr_in6 *sin6;
   1206 	struct sadb_msg *msgp;
   1207 	int i, rc;
   1208 	char **walker;	/* For the SRC and PROXY walking functions. */
   1209 	char *first_match;
   1210 	uint64_t savebuf[MAX_GET_SIZE];
   1211 	uint16_t srcport = 0, dstport = 0;
   1212 	char *ep = NULL;
   1213 
   1214 	/*
   1215 	 * Okay, now we have "src", "dst", and maybe "proxy" reassigned
   1216 	 * to point into the buffer to be written to PF_KEY, we can do
   1217 	 * potentially several writes based on destination address.
   1218 	 *
   1219 	 * First, obtain port numbers from passed-in extensions.
   1220 	 */
   1221 
   1222 	if (src != NULL) {
   1223 		sin6 = (struct sockaddr_in6 *)(src + 1);
   1224 		srcport = ntohs(sin6->sin6_port);
   1225 	}
   1226 	if (dst != NULL) {
   1227 		sin6 = (struct sockaddr_in6 *)(dst + 1);
   1228 		dstport = ntohs(sin6->sin6_port);
   1229 	}
   1230 
   1231 	/*
   1232 	 * The rules for ADD, GET, and UPDATE: (NOTE:  This assumes IPsec.
   1233 	 * If other consumers of PF_KEY happen, this will have to be
   1234 	 * rewhacked.):
   1235 	 *
   1236 	 *	Do a message for every possible DST address.
   1237 	 *
   1238 	 *	If a source or proxy address explodes, keep unspecified
   1239 	 *	(and mention unspecified).
   1240 	 *
   1241 	 * If dsthp is == dummy.he, then go through the loop once.
   1242 	 * If any other hp is == dummy.he, then you don't have to apply any
   1243 	 * silly rules.
   1244 	 *
   1245 	 * DELETE is different, because you can leave either "src" or "dst"
   1246 	 * blank!  You need to explode if one of them is full, and not assume
   1247 	 * that the other is set.
   1248 	 */
   1249 
   1250 	if (dsthp == NULL) {
   1251 		/*
   1252 		 * No destination address specified.
   1253 		 * With extended diagnostics, we don't have to bail the
   1254 		 * non-DELETE cases here.  The EINVAL diagnostics will be
   1255 		 * enough to inform the user(s) what happened.
   1256 		 */
   1257 		i = 0;
   1258 		do {
   1259 			if (srchp == &dummy.he) {
   1260 				/* Just to be sure... */
   1261 				srchp->h_addr_list[1] = NULL;
   1262 			} else if (srchp != NULL) {
   1263 				/* Degenerate case, h_addr_list[0] == NULL. */
   1264 				if (srchp->h_addr_list[i] == NULL)
   1265 					Bail("Empty source address list");
   1266 
   1267 				/*
   1268 				 * Fill in the src sockaddr.
   1269 				 */
   1270 				sin6 = (struct sockaddr_in6 *)(src + 1);
   1271 				bzero(sin6, sizeof (*sin6));
   1272 				bcopy(srchp->h_addr_list[i], &sin6->sin6_addr,
   1273 				    sizeof (struct in6_addr));
   1274 				sin6->sin6_family = AF_INET6;
   1275 				sin6->sin6_port = htons(srcport);
   1276 			}
   1277 
   1278 			/* Save off a copy for later writing... */
   1279 			msgp = (struct sadb_msg *)buffer;
   1280 			bcopy(buffer, savebuf, SADB_64TO8(msgp->sadb_msg_len));
   1281 
   1282 			rc = key_write(keysock, buffer,
   1283 			    SADB_64TO8(msgp->sadb_msg_len));
   1284 			if (rc == -1)
   1285 				Bail("write() to PF_KEY socket "
   1286 				    "(in doaddresses)");
   1287 			/*
   1288 			 * Sends the message to the Solaris Cluster daemon
   1289 			 */
   1290 
   1291 			if (in_cluster_mode) {
   1292 				(void) sendto(cluster_socket, buffer,
   1293 				    SADB_64TO8(msgp->sadb_msg_len), 0,
   1294 				    (struct sockaddr *)&cli_addr,
   1295 				    sizeof (cli_addr));
   1296 			}
   1297 
   1298 			time_critical_enter();
   1299 			do {
   1300 				rc = read(keysock, buffer, buffer_size);
   1301 				if (rc == -1)
   1302 					Bail("read (in doaddresses)");
   1303 			} while (msgp->sadb_msg_seq != seq ||
   1304 			    msgp->sadb_msg_pid != mypid);
   1305 			time_critical_exit();
   1306 
   1307 			if (msgp->sadb_msg_type != sadb_msg_type ||
   1308 			    msgp->sadb_msg_satype != sadb_msg_satype) {
   1309 				syslog((LOG_NOTICE|LOG_AUTH), gettext(
   1310 				    "doaddresses: Unexpected returned message "
   1311 				    "(%d exp %d)\n"), msgp->sadb_msg_type,
   1312 				    sadb_msg_type);
   1313 				Bail("doaddresses: Unexpected returned "
   1314 				    "message");
   1315 			}
   1316 
   1317 			errno = msgp->sadb_msg_errno;
   1318 			if (errno != 0) {
   1319 				if (errno == EINVAL) {
   1320 					WARN(ep, ebuf, gettext(
   1321 					    "One of the entered "
   1322 					    "values is incorrect."));
   1323 					print_diagnostic(stderr,
   1324 					    msgp->sadb_x_msg_diagnostic);
   1325 				} else {
   1326 					Bail("return message (in doaddresses)");
   1327 				}
   1328 			}
   1329 
   1330 			/* ...and then restore the saved buffer. */
   1331 			msgp = (struct sadb_msg *)savebuf;
   1332 			bcopy(savebuf, buffer, SADB_64TO8(msgp->sadb_msg_len));
   1333 		} while (srchp != NULL && srchp->h_addr_list[++i] != NULL);
   1334 		return;
   1335 	}
   1336 
   1337 	single_dst = (dsthp == &dummy.he || dsthp->h_addr_list[1] == NULL);
   1338 
   1339 	for (i = 0; dsthp->h_addr_list[i] != NULL; i++) {
   1340 		if (dsthp == &dummy.he) {
   1341 			/* Just to be sure... */
   1342 			dsthp->h_addr_list[1] = NULL;
   1343 		} else {
   1344 			/*
   1345 			 * Fill in the dst sockaddr.
   1346 			 */
   1347 			sin6 = (struct sockaddr_in6 *)(dst + 1);
   1348 			bzero(sin6, sizeof (*sin6));
   1349 			bcopy(dsthp->h_addr_list[i], &sin6->sin6_addr,
   1350 			    sizeof (struct in6_addr));
   1351 			sin6->sin6_family = AF_INET6;
   1352 			sin6->sin6_port = htons(dstport);
   1353 		}
   1354 
   1355 		/*
   1356 		 * Try and assign src, if there's any ambiguity.
   1357 		 */
   1358 		if (!unspec_src && srchp != &dummy.he) {
   1359 			if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
   1360 				/*
   1361 				 * IPv4 address.  Find an IPv4 address, then
   1362 				 * keep looking for a second one.  If a second
   1363 				 * exists, print a message, and fill in the
   1364 				 * unspecified address.
   1365 				 */
   1366 				first_match = NULL;
   1367 
   1368 				for (walker = srchp->h_addr_list;
   1369 				    *walker != NULL; walker++) {
   1370 					/* LINTED E_BAD_PTR_CAST_ALIGN */
   1371 					if (IN6_IS_ADDR_V4MAPPED(
   1372 					    (struct in6_addr *)*walker)) {
   1373 						if (first_match != NULL)
   1374 							break;
   1375 						else
   1376 							first_match = *walker;
   1377 					}
   1378 				}
   1379 				sin6 = (struct sockaddr_in6 *)(src + 1);
   1380 				bzero(sin6, sizeof (*sin6));
   1381 
   1382 				if (first_match == NULL) {
   1383 					/*
   1384 					 * No IPv4 hits.  Is this a single
   1385 					 * dest?
   1386 					 */
   1387 					WARN1(ep, ebuf, gettext(
   1388 					    "No IPv4 source address "
   1389 					    "for name %s.\n"), srchp->h_name);
   1390 					if (single_dst) {
   1391 						ERROR(ep, ebuf, gettext(
   1392 						    "Only single destination "
   1393 						    "IP address.\n"));
   1394 					} else {
   1395 						/* Continue, but do I print? */
   1396 						continue;  /* for loop */
   1397 					}
   1398 
   1399 					/* I should never reach here. */
   1400 				}
   1401 
   1402 				sin6->sin6_family = AF_INET6;
   1403 				sin6->sin6_port = htons(srcport);
   1404 				if (*walker != NULL) {
   1405 					/*
   1406 					 * Early loop exit.  It must've been
   1407 					 * multiple hits...
   1408 					 *
   1409 					 * Issue a null-source warning?
   1410 					 */
   1411 					WARN1(ep, ebuf, gettext(
   1412 					    "Multiple IPv4 source addresses "
   1413 					    "for %s, using unspecified source "
   1414 					    "instead."), srchp->h_name);
   1415 				} else {
   1416 					/*
   1417 					 * If I reach here w/o hitting the
   1418 					 * previous if statements, I have a
   1419 					 * single source address for this
   1420 					 * destination.
   1421 					 */
   1422 					bcopy(first_match, &sin6->sin6_addr,
   1423 					    sizeof (struct in6_addr));
   1424 				}
   1425 			} else {
   1426 				/*
   1427 				 * IPv6 address.  Find an IPv6 address.
   1428 				 * Unlike IPv4 addresses, things can get a
   1429 				 * little more sticky with scopes, etc.
   1430 				 */
   1431 				int dst_scope, src_scope;
   1432 
   1433 				dst_scope = ipv6_addr_scope(&sin6->sin6_addr);
   1434 
   1435 				first_match = NULL;
   1436 				for (walker = srchp->h_addr_list;
   1437 				    *walker != NULL; walker++) {
   1438 					/* LINTED E_BAD_PTR_CAST_ALIGN */
   1439 					if (!IN6_IS_ADDR_V4MAPPED(
   1440 					    (struct in6_addr *)*walker)) {
   1441 						/*
   1442 						 * Set first-match, etc.
   1443 						 * Take into account scopes,
   1444 						 * and other IPv6 thingies.
   1445 						 */
   1446 						src_scope = ipv6_addr_scope(
   1447 						    /* LINTED E_BAD_PTR_CAST */
   1448 						    (struct in6_addr *)*walker);
   1449 						if (src_scope == SCOPE_UNSPEC ||
   1450 						    src_scope == dst_scope) {
   1451 							if (first_match !=
   1452 							    NULL)
   1453 								break;
   1454 							else
   1455 								first_match =
   1456 								    *walker;
   1457 						}
   1458 					}
   1459 				}
   1460 
   1461 				sin6 = (struct sockaddr_in6 *)(src + 1);
   1462 				bzero(sin6, sizeof (*sin6));
   1463 				sin6->sin6_port = htons(srcport);
   1464 				if (first_match == NULL) {
   1465 					/*
   1466 					 * No IPv6 hits.  Is this a single
   1467 					 * dest?
   1468 					 */
   1469 					WARN1(ep, ebuf, gettext(
   1470 					    "No IPv6 source address of "
   1471 					    "matching scope for name %s.\n"),
   1472 					    srchp->h_name);
   1473 					if (single_dst) {
   1474 						ERROR(ep, ebuf, gettext(
   1475 						    "Only a single IPV6 "
   1476 						    "destination "
   1477 						    "address.\n"));
   1478 					} else {
   1479 						/* Continue, but do I print? */
   1480 						continue;  /* for loop */
   1481 					}
   1482 
   1483 					/* I should never reach here. */
   1484 				}
   1485 				sin6->sin6_family = AF_INET6;
   1486 				if (*walker != NULL) {
   1487 					/*
   1488 					 * Early loop exit.  Issue a
   1489 					 * null-source warning?
   1490 					 */
   1491 					WARN1(ep, ebuf, gettext(
   1492 					    "Multiple IPv6 source addresses "
   1493 					    "for %s of the same scope, using "
   1494 					    "unspecified source instead.\n"),
   1495 					    srchp->h_name);
   1496 				} else {
   1497 					/*
   1498 					 * If I reach here w/o hitting the
   1499 					 * previous if statements, I have a
   1500 					 * single source address for this
   1501 					 * destination.
   1502 					 */
   1503 					bcopy(first_match, &sin6->sin6_addr,
   1504 					    sizeof (struct in6_addr));
   1505 				}
   1506 			}
   1507 		}
   1508 
   1509 		/*
   1510 		 * If there are errors at this point there is no
   1511 		 * point sending anything to PF_KEY.
   1512 		 */
   1513 		handle_errors(ep, ebuf, B_TRUE, B_FALSE);
   1514 
   1515 		/* Save off a copy for later writing... */
   1516 		msgp = (struct sadb_msg *)buffer;
   1517 		bcopy(buffer, savebuf, SADB_64TO8(msgp->sadb_msg_len));
   1518 
   1519 		rc = key_write(keysock, buffer, SADB_64TO8(msgp->sadb_msg_len));
   1520 		if (rc == -1)
   1521 			Bail("write() to PF_KEY socket (in doaddresses)");
   1522 
   1523 		if (in_cluster_mode) {
   1524 			(void) sendto(cluster_socket, buffer,
   1525 			    SADB_64TO8(msgp->sadb_msg_len), 0,
   1526 			    (struct sockaddr *)&cli_addr,
   1527 			    sizeof (cli_addr));
   1528 		}
   1529 		/* Blank the key for paranoia's sake. */
   1530 		bzero(buffer, buffer_size);
   1531 		time_critical_enter();
   1532 		do {
   1533 			rc = read(keysock, buffer, buffer_size);
   1534 			if (rc == -1)
   1535 				Bail("read (in doaddresses)");
   1536 		} while (msgp->sadb_msg_seq != seq ||
   1537 		    msgp->sadb_msg_pid != mypid);
   1538 		time_critical_exit();
   1539 
   1540 		/*
   1541 		 * I should _never_ hit the following unless:
   1542 		 *
   1543 		 * 1. There is a kernel bug.
   1544 		 * 2. Another process is mistakenly using my pid in a PF_KEY
   1545 		 *    message.
   1546 		 */
   1547 		if (msgp->sadb_msg_type != sadb_msg_type ||
   1548 		    msgp->sadb_msg_satype != sadb_msg_satype) {
   1549 			syslog((LOG_NOTICE|LOG_AUTH), gettext(
   1550 			    "doaddresses: Unexpected returned message "
   1551 			    "(%d exp %d)\n"), msgp->sadb_msg_type,
   1552 			    sadb_msg_type);
   1553 			Bail("doaddresses: Unexpected returned message");
   1554 		}
   1555 
   1556 		if (msgp->sadb_msg_errno != 0) {
   1557 			char addrprint[INET6_ADDRSTRLEN];
   1558 			int on_errno = 0;
   1559 			char *on_errno_msg;
   1560 
   1561 			/*
   1562 			 * Print different error messages depending
   1563 			 * on the SADB message type being processed.
   1564 			 * If we get a ESRCH error for a GET/DELETE
   1565 			 * messages, we report that the SA does not
   1566 			 * exist. If we get a EEXIST error for a
   1567 			 * ADD/UPDATE message, we report that the
   1568 			 * SA already exists.
   1569 			 */
   1570 			if (sadb_msg_type == SADB_GET ||
   1571 			    sadb_msg_type == SADB_DELETE) {
   1572 				on_errno = ESRCH;
   1573 				on_errno_msg = "does not exist";
   1574 			} else if (sadb_msg_type == SADB_ADD ||
   1575 			    sadb_msg_type == SADB_UPDATE) {
   1576 				on_errno = EEXIST;
   1577 				on_errno_msg = "already exists";
   1578 			}
   1579 
   1580 			errno = msgp->sadb_msg_errno;
   1581 			if (errno == on_errno) {
   1582 				ERROR2(ep, ebuf, gettext(
   1583 				    "Association (type = %s) "
   1584 				    "with spi 0x%x and addr\n"),
   1585 				    rparsesatype(msgp->sadb_msg_satype),
   1586 				    ntohl(spi));
   1587 				ERROR2(ep, ebuf, "%s %s.\n",
   1588 				    do_inet_ntop(dsthp->h_addr_list[i],
   1589 				    addrprint, sizeof (addrprint)),
   1590 				    on_errno_msg);
   1591 				msgp = (struct sadb_msg *)savebuf;
   1592 				bcopy(savebuf, buffer,
   1593 				    SADB_64TO8(msgp->sadb_msg_len));
   1594 				continue;
   1595 			} else {
   1596 				if (errno == EINVAL || errno == ESRCH) {
   1597 					ERROR2(ep, ebuf, gettext(
   1598 					    "PF_KEY Diagnostic code %u: %s.\n"),
   1599 					    msgp->sadb_x_msg_diagnostic,
   1600 					    keysock_diag(
   1601 					    msgp->sadb_x_msg_diagnostic));
   1602 				} else {
   1603 					Bail("return message (in doaddresses)");
   1604 				}
   1605 			}
   1606 		}
   1607 
   1608 		if (cmd == CMD_GET) {
   1609 			if (msgp->sadb_msg_len > MAX_GET_SIZE) {
   1610 				WARN1(ep, ebuf, gettext("WARNING:  "
   1611 				    "SA information bigger than %d bytes.\n"),
   1612 				    SADB_64TO8(MAX_GET_SIZE));
   1613 			}
   1614 			print_samsg(stdout, buffer, B_FALSE, vflag, nflag);
   1615 		}
   1616 
   1617 		handle_errors(ep, ebuf, B_TRUE, B_FALSE);
   1618 
   1619 		/* ...and then restore the saved buffer. */
   1620 		msgp = (struct sadb_msg *)savebuf;
   1621 		bcopy(savebuf, buffer, SADB_64TO8(msgp->sadb_msg_len));
   1622 		lines_added++;
   1623 	}
   1624 
   1625 	/* Degenerate case, h_addr_list[0] == NULL. */
   1626 	if (i == 0)
   1627 		Bail("Empty destination address list");
   1628 
   1629 	/*
   1630 	 * free(ebuf) even if there are no errors.
   1631 	 * handle_errors() won't return here.
   1632 	 */
   1633 	handle_errors(ep, ebuf, B_TRUE, B_TRUE);
   1634 }
   1635 
   1636 /*
   1637  * Perform an add or an update.  ADD and UPDATE are similar in the extensions
   1638  * they need.
   1639  */
   1640 static void
   1641 doaddup(int cmd, int satype, char *argv[], char *ebuf)
   1642 {
   1643 	uint64_t *buffer, *nexthdr;
   1644 	struct sadb_msg msg;
   1645 	struct sadb_sa *assoc = NULL;
   1646 	struct sadb_x_pair *sadb_pair = NULL;
   1647 	struct sadb_address *src = NULL, *dst = NULL;
   1648 	struct sadb_address *isrc = NULL, *idst = NULL;
   1649 	struct sadb_address *natt_local = NULL, *natt_remote = NULL;
   1650 	struct sadb_key *encrypt = NULL, *auth = NULL;
   1651 	struct sadb_ident *srcid = NULL, *dstid = NULL;
   1652 	struct sadb_lifetime *hard = NULL, *soft = NULL;  /* Current? */
   1653 	struct sadb_lifetime *idle = NULL;
   1654 	struct sadb_x_replay_ctr *replay_ctr = NULL;
   1655 	struct sadb_sens *label = NULL, *olabel = NULL;
   1656 	struct sockaddr_in6 *sin6;
   1657 	/* MLS TODO:  Need sensitivity eventually. */
   1658 	int next, token, sa_len, alloclen, totallen = sizeof (msg), prefix;
   1659 	uint32_t spi = 0;
   1660 	uint_t reserved_bits = 0;
   1661 	uint8_t	sadb_msg_type;
   1662 	char *thiscmd, *pstr;
   1663 	boolean_t readstate = B_FALSE, unspec_src = B_FALSE;
   1664 	boolean_t alloc_inner = B_FALSE, use_natt = B_FALSE;
   1665 	struct hostent *srchp = NULL, *dsthp = NULL, *isrchp = NULL,
   1666 	    *idsthp = NULL;
   1667 	struct hostent *natt_lhp = NULL, *natt_rhp = NULL;
   1668 	uint16_t srcport = 0, dstport = 0, natt_lport = 0, natt_rport = 0,
   1669 	    isrcport = 0, idstport = 0;
   1670 	uint8_t proto = 0, iproto = 0;
   1671 	char *ep = NULL;
   1672 
   1673 	switch (cmd) {
   1674 	case CMD_ADD:
   1675 		thiscmd = "add";
   1676 		sadb_msg_type = SADB_ADD;
   1677 		break;
   1678 	case CMD_UPDATE:
   1679 		thiscmd = "update";
   1680 		sadb_msg_type = SADB_UPDATE;
   1681 		break;
   1682 	case CMD_UPDATE_PAIR:
   1683 		thiscmd = "update-pair";
   1684 		sadb_msg_type = SADB_X_UPDATEPAIR;
   1685 		break;
   1686 	}
   1687 
   1688 	msg_init(&msg, sadb_msg_type, (uint8_t)satype);
   1689 	/* Assume last element in argv is set to NULL. */
   1690 	do {
   1691 		token = parseextval(*argv, &next);
   1692 		argv++;
   1693 		switch (token) {
   1694 		case TOK_EOF:
   1695 			/* Do nothing, I'm done. */
   1696 			break;
   1697 		case TOK_UNKNOWN:
   1698 			ERROR1(ep, ebuf, gettext(
   1699 			    "Unknown extension field \"%s\" \n"), *(argv - 1));
   1700 			break;
   1701 		case TOK_SPI:
   1702 		case TOK_PAIR_SPI:
   1703 		case TOK_REPLAY:
   1704 		case TOK_STATE:
   1705 		case TOK_AUTHALG:
   1706 		case TOK_ENCRALG:
   1707 		case TOK_ENCAP:
   1708 			/*
   1709 			 * May want to place this chunk of code in a function.
   1710 			 *
   1711 			 * This code checks for duplicate entries on a command
   1712 			 * line.
   1713 			 */
   1714 
   1715 			/* Allocate the SADB_EXT_SA extension. */
   1716 			if (assoc == NULL) {
   1717 				assoc = malloc(sizeof (*assoc));
   1718 				if (assoc == NULL)
   1719 					Bail("malloc(assoc)");
   1720 				bzero(assoc, sizeof (*assoc));
   1721 				assoc->sadb_sa_exttype = SADB_EXT_SA;
   1722 				assoc->sadb_sa_len =
   1723 				    SADB_8TO64(sizeof (*assoc));
   1724 				totallen += sizeof (*assoc);
   1725 			}
   1726 			switch (token) {
   1727 			case TOK_SPI:
   1728 				/*
   1729 				 * If some cretin types in "spi 0" then he/she
   1730 				 * can type in another SPI.
   1731 				 */
   1732 				if (assoc->sadb_sa_spi != 0) {
   1733 					ERROR(ep, ebuf, gettext(
   1734 					    "Can only specify "
   1735 					    "single SPI value.\n"));
   1736 					break;
   1737 				}
   1738 				/* Must convert SPI to network order! */
   1739 				assoc->sadb_sa_spi =
   1740 				    htonl((uint32_t)parsenum(*argv, B_TRUE,
   1741 				    ebuf));
   1742 				if (assoc->sadb_sa_spi == 0) {
   1743 					ERROR(ep, ebuf, gettext(
   1744 					    "Invalid SPI value \"0\" .\n"));
   1745 				}
   1746 				break;
   1747 			case TOK_PAIR_SPI:
   1748 				if (cmd == CMD_UPDATE_PAIR) {
   1749 					ERROR(ep, ebuf, gettext(
   1750 					    "pair-spi can not be used with the "
   1751 					    "\"update-pair\" command.\n"));
   1752 				}
   1753 				if (sadb_pair == NULL) {
   1754 					sadb_pair = malloc(sizeof (*sadb_pair));
   1755 					if (assoc == NULL)
   1756 						Bail("malloc(assoc)");
   1757 					bzero(sadb_pair, sizeof (*sadb_pair));
   1758 					totallen += sizeof (*sadb_pair);
   1759 				}
   1760 				if (sadb_pair->sadb_x_pair_spi != 0) {
   1761 					ERROR(ep, ebuf, gettext(
   1762 					    "Can only specify "
   1763 					    "single pair SPI value.\n"));
   1764 					break;
   1765 				}
   1766 				/* Must convert SPI to network order! */
   1767 				sadb_pair->sadb_x_pair_len =
   1768 				    SADB_8TO64(sizeof (*sadb_pair));
   1769 				sadb_pair->sadb_x_pair_exttype =
   1770 				    SADB_X_EXT_PAIR;
   1771 				sadb_pair->sadb_x_pair_spi =
   1772 				    htonl((uint32_t)parsenum(*argv, B_TRUE,
   1773 				    ebuf));
   1774 				if (sadb_pair->sadb_x_pair_spi == 0) {
   1775 					ERROR(ep, ebuf, gettext(
   1776 					    "Invalid SPI value \"0\" .\n"));
   1777 				}
   1778 				assoc->sadb_sa_flags |=
   1779 				    SADB_X_SAFLAGS_PAIRED;
   1780 				break;
   1781 			case TOK_REPLAY:
   1782 				/*
   1783 				 * That same cretin can do the same with
   1784 				 * replay.
   1785 				 */
   1786 				if (assoc->sadb_sa_replay != 0) {
   1787 					ERROR(ep, ebuf, gettext(
   1788 					    "Can only specify "
   1789 					    "single replay window size.\n"));
   1790 					break;
   1791 				}
   1792 				assoc->sadb_sa_replay =
   1793 				    (uint8_t)parsenum(*argv, B_TRUE, ebuf);
   1794 				if (assoc->sadb_sa_replay != 0) {
   1795 					WARN(ep, ebuf, gettext(
   1796 					    "WARNING:  Replay with manual"
   1797 					    " keying considered harmful.\n"));
   1798 				}
   1799 				break;
   1800 			case TOK_STATE:
   1801 				/*
   1802 				 * 0 is an actual state value, LARVAL.  This
   1803 				 * means that one can type in the larval state
   1804 				 * and then type in another state on the same
   1805 				 * command line.
   1806 				 */
   1807 				if (assoc->sadb_sa_state != 0) {
   1808 					ERROR(ep, ebuf, gettext(
   1809 					    "Can only specify "
   1810 					    "single SA state.\n"));
   1811 					break;
   1812 				}
   1813 				assoc->sadb_sa_state = parsestate(*argv,
   1814 				    ebuf);
   1815 				readstate = B_TRUE;
   1816 				break;
   1817 			case TOK_AUTHALG:
   1818 				if (assoc->sadb_sa_auth != 0) {
   1819 					ERROR(ep, ebuf, gettext(
   1820 					    "Can only specify "
   1821 					    "single auth algorithm.\n"));
   1822 					break;
   1823 				}
   1824 				assoc->sadb_sa_auth = parsealg(*argv,
   1825 				    IPSEC_PROTO_AH, ebuf);
   1826 				break;
   1827 			case TOK_ENCRALG:
   1828 				if (satype == SADB_SATYPE_AH) {
   1829 					ERROR(ep, ebuf, gettext("Cannot specify"
   1830 					    " encryption with SA type ah.\n"));
   1831 					break;
   1832 				}
   1833 				if (assoc->sadb_sa_encrypt != 0) {
   1834 					ERROR(ep, ebuf, gettext(
   1835 					    "Can only specify "
   1836 					    "single encryption algorithm.\n"));
   1837 					break;
   1838 				}
   1839 				assoc->sadb_sa_encrypt = parsealg(*argv,
   1840 				    IPSEC_PROTO_ESP, ebuf);
   1841 				break;
   1842 			case TOK_ENCAP:
   1843 				if (use_natt) {
   1844 					ERROR(ep, ebuf, gettext(
   1845 					    "Can only specify single"
   1846 					    " encapsulation.\n"));
   1847 					break;
   1848 				}
   1849 				if (strncmp(*argv, "udp", 3)) {
   1850 					ERROR(ep, ebuf, gettext(
   1851 					    "Can only specify udp"
   1852 					    " encapsulation.\n"));
   1853 					break;
   1854 				}
   1855 				use_natt = B_TRUE;
   1856 				/* set assoc flags later */
   1857 				break;
   1858 			}
   1859 			argv++;
   1860 			break;
   1861 		case TOK_SRCPORT:
   1862 			if (srcport != 0) {
   1863 				ERROR(ep, ebuf,  gettext("Can only specify "
   1864 				    "single source port.\n"));
   1865 				break;
   1866 			}
   1867 			srcport = parsenum(*argv, B_TRUE, ebuf);
   1868 			argv++;
   1869 			break;
   1870 		case TOK_DSTPORT:
   1871 			if (dstport != 0) {
   1872 				ERROR(ep, ebuf, gettext("Can only specify "
   1873 				    "single destination port.\n"));
   1874 				break;
   1875 			}
   1876 			dstport = parsenum(*argv, B_TRUE, ebuf);
   1877 			argv++;
   1878 			break;
   1879 		case TOK_ISRCPORT:
   1880 			alloc_inner = B_TRUE;
   1881 			if (isrcport != 0) {
   1882 				ERROR(ep, ebuf, gettext(
   1883 				    "Can only specify "
   1884 				    "single inner-source port.\n"));
   1885 				break;
   1886 			}
   1887 			isrcport = parsenum(*argv, B_TRUE, ebuf);
   1888 			argv++;
   1889 			break;
   1890 		case TOK_IDSTPORT:
   1891 			alloc_inner = B_TRUE;
   1892 			if (idstport != 0) {
   1893 				ERROR(ep, ebuf, gettext(
   1894 				    "Can only specify "
   1895 				    "single inner-destination port.\n"));
   1896 				break;
   1897 			}
   1898 			idstport = parsenum(*argv, B_TRUE, ebuf);
   1899 			argv++;
   1900 			break;
   1901 		case TOK_NATLPORT:
   1902 			if (natt_lport != 0) {
   1903 				ERROR(ep, ebuf, gettext(
   1904 				    "Can only specify "
   1905 				    "single NAT-T local port.\n"));
   1906 				break;
   1907 			}
   1908 			natt_lport = parsenum(*argv, B_TRUE, ebuf);
   1909 			argv++;
   1910 			break;
   1911 		case TOK_NATRPORT:
   1912 			if (natt_rport != 0) {
   1913 				ERROR(ep, ebuf, gettext(
   1914 				    "Can only specify "
   1915 				    "single NAT-T remote port.\n"));
   1916 				break;
   1917 			}
   1918 			natt_rport = parsenum(*argv, B_TRUE, ebuf);
   1919 			argv++;
   1920 			break;
   1921 
   1922 		case TOK_PROTO:
   1923 			if (proto != 0) {
   1924 				ERROR(ep, ebuf, gettext(
   1925 				    "Can only specify "
   1926 				    "single protocol.\n"));
   1927 				break;
   1928 			}
   1929 			proto = parsenum(*argv, B_TRUE, ebuf);
   1930 			argv++;
   1931 			break;
   1932 		case TOK_IPROTO:
   1933 			alloc_inner = B_TRUE;
   1934 			if (iproto != 0) {
   1935 				ERROR(ep, ebuf, gettext(
   1936 				    "Can only specify "
   1937 				    "single inner protocol.\n"));
   1938 				break;
   1939 			}
   1940 			iproto = parsenum(*argv, B_TRUE, ebuf);
   1941 			argv++;
   1942 			break;
   1943 		case TOK_SRCADDR:
   1944 		case TOK_SRCADDR6:
   1945 			if (src != NULL) {
   1946 				ERROR(ep, ebuf, gettext(
   1947 				    "Can only specify "
   1948 				    "single source address.\n"));
   1949 				break;
   1950 			}
   1951 			sa_len = parseaddr(*argv, &srchp,
   1952 			    (token == TOK_SRCADDR6), ebuf);
   1953 			if (srchp == NULL) {
   1954 				ERROR1(ep, ebuf, gettext(
   1955 				    "Unknown src address \"%s\"\n"), *argv);
   1956 				break;
   1957 			}
   1958 			argv++;
   1959 			/*
   1960 			 * Round of the sockaddr length to an 8 byte
   1961 			 * boundary to make PF_KEY happy.
   1962 			 */
   1963 			alloclen = sizeof (*src) + roundup(sa_len, 8);
   1964 			src = malloc(alloclen);
   1965 			if (src == NULL)
   1966 				Bail("malloc(src)");
   1967 			totallen += alloclen;
   1968 			src->sadb_address_len = SADB_8TO64(alloclen);
   1969 			src->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
   1970 			src->sadb_address_reserved = 0;
   1971 			src->sadb_address_prefixlen = 0;
   1972 			src->sadb_address_proto = 0;
   1973 			if (srchp == &dummy.he) {
   1974 				/*
   1975 				 * Single address with -n flag.
   1976 				 */
   1977 				sin6 = (struct sockaddr_in6 *)(src + 1);
   1978 				bzero(sin6, sizeof (*sin6));
   1979 				sin6->sin6_family = AF_INET6;
   1980 				bcopy(srchp->h_addr_list[0], &sin6->sin6_addr,
   1981 				    sizeof (struct in6_addr));
   1982 			}
   1983 			break;
   1984 		case TOK_DSTADDR:
   1985 		case TOK_DSTADDR6:
   1986 			if (dst != NULL) {
   1987 				ERROR(ep, ebuf, gettext(
   1988 				    "Can only specify single "
   1989 				    "destination address.\n"));
   1990 				break;
   1991 			}
   1992 			sa_len = parseaddr(*argv, &dsthp,
   1993 			    (token == TOK_DSTADDR6), ebuf);
   1994 			if (dsthp == NULL) {
   1995 				ERROR1(ep, ebuf, gettext(
   1996 				    "Unknown dst address \"%s\"\n"), *argv);
   1997 				break;
   1998 			}
   1999 			argv++;
   2000 			alloclen = sizeof (*dst) + roundup(sa_len, 8);
   2001 			dst = malloc(alloclen);
   2002 			if (dst == NULL)
   2003 				Bail("malloc(dst)");
   2004 			totallen += alloclen;
   2005 			dst->sadb_address_len = SADB_8TO64(alloclen);
   2006 			dst->sadb_address_exttype = SADB_EXT_ADDRESS_DST;
   2007 			dst->sadb_address_reserved = 0;
   2008 			dst->sadb_address_prefixlen = 0;
   2009 			dst->sadb_address_proto = 0;
   2010 			if (dsthp == &dummy.he) {
   2011 				/*
   2012 				 * Single address with -n flag.
   2013 				 */
   2014 				sin6 = (struct sockaddr_in6 *)(dst + 1);
   2015 				bzero(sin6, sizeof (*sin6));
   2016 				sin6->sin6_family = AF_INET6;
   2017 				bcopy(dsthp->h_addr_list[0], &sin6->sin6_addr,
   2018 				    sizeof (struct in6_addr));
   2019 			}
   2020 			break;
   2021 		case TOK_PROXYADDR:
   2022 		case TOK_PROXYADDR6:
   2023 			if (isrc != NULL) {
   2024 				ERROR(ep, ebuf, gettext(
   2025 				    "Can only specify single "
   2026 				    "proxy/inner-source address.\n"));
   2027 				break;
   2028 			}
   2029 			if ((pstr = strchr(*argv, '/')) != NULL) {
   2030 				/* Parse out the prefix. */
   2031 				errno = 0;
   2032 				prefix = strtol(pstr + 1, NULL, 10);
   2033 				if (errno != 0) {
   2034 					ERROR1(ep, ebuf, gettext(
   2035 					    "Invalid prefix %s."), pstr);
   2036 					break;
   2037 				}
   2038 				/* Recycle pstr */
   2039 				alloclen = (int)(pstr - *argv);
   2040 				pstr = malloc(alloclen + 1);
   2041 				if (pstr == NULL) {
   2042 					Bail("malloc(pstr)");
   2043 				}
   2044 				(void) strlcpy(pstr, *argv, alloclen + 1);
   2045 			} else {
   2046 				pstr = *argv;
   2047 				/*
   2048 				 * Assume mapping to AF_INET6, and we're a host.
   2049 				 * XXX some miscreants may still make classful
   2050 				 * assumptions.  If this is a problem, fix it
   2051 				 * here.
   2052 				 */
   2053 				prefix = 128;
   2054 			}
   2055 			sa_len = parseaddr(pstr, &isrchp,
   2056 			    (token == TOK_PROXYADDR6), ebuf);
   2057 			if (isrchp == NULL) {
   2058 				ERROR1(ep, ebuf, gettext(
   2059 				    "Unknown proxy/inner-source address "
   2060 				    "\"%s\"\n"), *argv);
   2061 				break;
   2062 			}
   2063 			if (pstr != *argv)
   2064 				free(pstr);
   2065 			argv++;
   2066 			alloclen = sizeof (*isrc) + roundup(sa_len, 8);
   2067 			isrc = malloc(alloclen);
   2068 			if (isrc == NULL)
   2069 				Bail("malloc(isrc)");
   2070 			totallen += alloclen;
   2071 			isrc->sadb_address_len = SADB_8TO64(alloclen);
   2072 			isrc->sadb_address_exttype = SADB_EXT_ADDRESS_PROXY;
   2073 			isrc->sadb_address_reserved = 0;
   2074 			isrc->sadb_address_prefixlen = prefix;
   2075 			isrc->sadb_address_proto = 0;
   2076 			if (isrchp == &dummy.he ||
   2077 			    isrchp->h_addr_list[1] == NULL) {
   2078 				/*
   2079 				 * Single address with -n flag or single name.
   2080 				 */
   2081 				sin6 = (struct sockaddr_in6 *)(isrc + 1);
   2082 				bzero(sin6, sizeof (*sin6));
   2083 				sin6->sin6_family = AF_INET6;
   2084 				bcopy(isrchp->h_addr_list[0], &sin6->sin6_addr,
   2085 				    sizeof (struct in6_addr));
   2086 				/*
   2087 				 * normalize prefixlen for IPv4-mapped
   2088 				 * addresses.
   2089 				 */
   2090 				if (prefix <= 32 &&
   2091 				    IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
   2092 					isrc->sadb_address_prefixlen += 96;
   2093 				alloc_inner = B_TRUE;
   2094 			} else {
   2095 				/*
   2096 				 * If the proxy/isrc address is vague, don't
   2097 				 * bother.
   2098 				 */
   2099 				totallen -= alloclen;
   2100 				free(isrc);
   2101 				isrc = NULL;
   2102 				WARN1(ep, ebuf, gettext(
   2103 				    "Proxy/inner-source address %s "
   2104 				    "is vague, not using.\n"), isrchp->h_name);
   2105 				freehostent(isrchp);
   2106 				isrchp = NULL;
   2107 				break;
   2108 			}
   2109 			break;
   2110 		case TOK_IDSTADDR:
   2111 		case TOK_IDSTADDR6:
   2112 			if (idst != NULL) {
   2113 				ERROR(ep, ebuf, gettext(
   2114 				    "Can only specify single "
   2115 				    "inner-destination address.\n"));
   2116 				break;
   2117 			}
   2118 			if ((pstr = strchr(*argv, '/')) != NULL) {
   2119 				/* Parse out the prefix. */
   2120 				errno = 0;
   2121 				prefix = strtol(pstr + 1, NULL, 10);
   2122 				if (errno != 0) {
   2123 					ERROR1(ep, ebuf, gettext(
   2124 					    "Invalid prefix %s.\n"), pstr);
   2125 					break;
   2126 				}
   2127 				/* Recycle pstr */
   2128 				alloclen = (int)(pstr - *argv);
   2129 				pstr = malloc(alloclen + 1);
   2130 				if (pstr == NULL) {
   2131 					Bail("malloc(pstr)");
   2132 				}
   2133 				(void) strlcpy(pstr, *argv, alloclen + 1);
   2134 			} else {
   2135 				pstr = *argv;
   2136 				/*
   2137 				 * Assume mapping to AF_INET6, and we're a host.
   2138 				 * XXX some miscreants may still make classful
   2139 				 * assumptions.  If this is a problem, fix it
   2140 				 * here.
   2141 				 */
   2142 				prefix = 128;
   2143 			}
   2144 			sa_len = parseaddr(pstr, &idsthp,
   2145 			    (token == TOK_IDSTADDR6), ebuf);
   2146 			if (idsthp == NULL) {
   2147 				ERROR1(ep, ebuf, gettext(
   2148 				    "Unknown Inner Src address "
   2149 				    " \"%s\"\n"), *argv);
   2150 				break;
   2151 			}
   2152 			if (pstr != *argv)
   2153 				free(pstr);
   2154 			argv++;
   2155 			alloclen = sizeof (*idst) + roundup(sa_len, 8);
   2156 			idst = malloc(alloclen);
   2157 			if (idst == NULL)
   2158 				Bail("malloc(idst)");
   2159 			totallen += alloclen;
   2160 			idst->sadb_address_len = SADB_8TO64(alloclen);
   2161 			idst->sadb_address_exttype =
   2162 			    SADB_X_EXT_ADDRESS_INNER_DST;
   2163 			idst->sadb_address_reserved = 0;
   2164 			idst->sadb_address_prefixlen = prefix;
   2165 			idst->sadb_address_proto = 0;
   2166 			if (idsthp == &dummy.he ||
   2167 			    idsthp->h_addr_list[1] == NULL) {
   2168 				/*
   2169 				 * Single address with -n flag or single name.
   2170 				 */
   2171 				sin6 = (struct sockaddr_in6 *)(idst + 1);
   2172 				bzero(sin6, sizeof (*sin6));
   2173 				sin6->sin6_family = AF_INET6;
   2174 				bcopy(idsthp->h_addr_list[0], &sin6->sin6_addr,
   2175 				    sizeof (struct in6_addr));
   2176 				/*
   2177 				 * normalize prefixlen for IPv4-mapped
   2178 				 * addresses.
   2179 				 */
   2180 				if (prefix <= 32 &&
   2181 				    IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
   2182 					idst->sadb_address_prefixlen += 96;
   2183 				alloc_inner = B_TRUE;
   2184 			} else {
   2185 				/*
   2186 				 * If the idst address is vague, don't bother.
   2187 				 */
   2188 				totallen -= alloclen;
   2189 				free(idst);
   2190 				idst = NULL;
   2191 				WARN1(ep, ebuf, gettext(
   2192 				    "Inner destination address %s "
   2193 				    "is vague, not using.\n"), idsthp->h_name);
   2194 				freehostent(idsthp);
   2195 				idsthp = NULL;
   2196 				break;
   2197 			}
   2198 			break;
   2199 		case TOK_NATLOC:
   2200 			if (natt_local != NULL) {
   2201 				ERROR(ep, ebuf, gettext(
   2202 				    "Can only specify "
   2203 				    "single NAT-T local address.\n"));
   2204 				break;
   2205 			}
   2206 			sa_len = parseaddr(*argv, &natt_lhp, 0, ebuf);
   2207 			if (natt_lhp == NULL) {
   2208 				ERROR1(ep, ebuf, gettext(
   2209 				    "Unknown NAT-T local address \"%s\"\n"),
   2210 				    *argv);
   2211 				break;
   2212 			}
   2213 			argv++;
   2214 			/*
   2215 			 * Round of the sockaddr length to an 8 byte
   2216 			 * boundary to make PF_KEY happy.
   2217 			 */
   2218 			alloclen = sizeof (*natt_local) + roundup(sa_len, 8);
   2219 			natt_local = malloc(alloclen);
   2220 			if (natt_local == NULL)
   2221 				Bail("malloc(natt_local)");
   2222 			totallen += alloclen;
   2223 			natt_local->sadb_address_len = SADB_8TO64(alloclen);
   2224 			natt_local->sadb_address_exttype =
   2225 			    SADB_X_EXT_ADDRESS_NATT_LOC;
   2226 			natt_local->sadb_address_reserved = 0;
   2227 			natt_local->sadb_address_prefixlen = 0;
   2228 			natt_local->sadb_address_proto = 0;
   2229 			if (natt_lhp == &dummy.he ||
   2230 			    natt_lhp->h_addr_list[1] == NULL) {
   2231 				/*
   2232 				 * Single address with -n flag or single name.
   2233 				 */
   2234 				sin6 = (struct sockaddr_in6 *)(natt_local + 1);
   2235 				bzero(sin6, sizeof (*sin6));
   2236 				sin6->sin6_family = AF_INET6;
   2237 				bcopy(natt_lhp->h_addr_list[0],
   2238 				    &sin6->sin6_addr, sizeof (struct in6_addr));
   2239 			} else {
   2240 				/*
   2241 				 * If the nat-local address is vague, don't
   2242 				 * bother.
   2243 				 */
   2244 				totallen -= alloclen;
   2245 				free(natt_local);
   2246 				natt_local = NULL;
   2247 				WARN1(ep, ebuf, gettext(
   2248 				    "NAT-T local address %s "
   2249 				    "is vague, not using.\n"),
   2250 				    natt_lhp->h_name);
   2251 				freehostent(natt_lhp);
   2252 				natt_lhp = NULL;
   2253 				break;
   2254 			}
   2255 			break;
   2256 		case TOK_NATREM:
   2257 			if (natt_remote != NULL) {
   2258 				ERROR(ep, ebuf, gettext(
   2259 				    "Can only specify "
   2260 				    "single NAT-T remote address.\n"));
   2261 				break;
   2262 			}
   2263 			sa_len = parseaddr(*argv, &natt_rhp, 0, ebuf);
   2264 			if (natt_rhp == NULL) {
   2265 				ERROR1(ep, ebuf, gettext(
   2266 				    "Unknown NAT-T remote address \"%s\"\n"),
   2267 				    *argv);
   2268 				break;
   2269 			}
   2270 			argv++;
   2271 			/*
   2272 			 * Round of the sockaddr length to an 8 byte
   2273 			 * boundary to make PF_KEY happy.
   2274 			 */
   2275 			alloclen = sizeof (*natt_remote) + roundup(sa_len, 8);
   2276 			natt_remote = malloc(alloclen);
   2277 			if (natt_remote == NULL)
   2278 				Bail("malloc(natt_remote)");
   2279 			totallen += alloclen;
   2280 			natt_remote->sadb_address_len = SADB_8TO64(alloclen);
   2281 			natt_remote->sadb_address_exttype =
   2282 			    SADB_X_EXT_ADDRESS_NATT_REM;
   2283 			natt_remote->sadb_address_reserved = 0;
   2284 			natt_remote->sadb_address_prefixlen = 0;
   2285 			natt_remote->sadb_address_proto = 0;
   2286 			if (natt_rhp == &dummy.he ||
   2287 			    natt_rhp->h_addr_list[1] == NULL) {
   2288 				/*
   2289 				 * Single address with -n flag or single name.
   2290 				 */
   2291 				sin6 = (struct sockaddr_in6 *)(natt_remote + 1);
   2292 				bzero(sin6, sizeof (*sin6));
   2293 				sin6->sin6_family = AF_INET6;
   2294 				bcopy(natt_rhp->h_addr_list[0],
   2295 				    &sin6->sin6_addr, sizeof (struct in6_addr));
   2296 			} else {
   2297 				/*
   2298 				 * If the nat-renote address is vague, don't
   2299 				 * bother.
   2300 				 */
   2301 				totallen -= alloclen;
   2302 				free(natt_remote);
   2303 				natt_remote = NULL;
   2304 				WARN1(ep, ebuf, gettext(
   2305 				    "NAT-T remote address %s "
   2306 				    "is vague, not using.\n"),
   2307 				    natt_rhp->h_name);
   2308 				freehostent(natt_rhp);
   2309 				natt_rhp = NULL;
   2310 				break;
   2311 			}
   2312 			break;
   2313 		case TOK_ENCRKEY:
   2314 			if (encrypt != NULL) {
   2315 				ERROR(ep, ebuf, gettext(
   2316 				    "Can only specify "
   2317 				    "single encryption key.\n"));
   2318 				break;
   2319 			}
   2320 			if (assoc != NULL &&
   2321 			    assoc->sadb_sa_encrypt == SADB_EALG_NULL) {
   2322 				FATAL(ep, ebuf, gettext(
   2323 				    "Cannot specify a key with NULL "
   2324 				    "encryption algorithm.\n"));
   2325 				break;
   2326 			}
   2327 			encrypt = parsekey(*argv, ebuf, reserved_bits);
   2328 			argv++;
   2329 			if (encrypt == NULL) {
   2330 				ERROR(ep, ebuf, gettext(
   2331 				    "Invalid encryption key.\n"));
   2332 				break;
   2333 			}
   2334 			totallen += SADB_64TO8(encrypt->sadb_key_len);
   2335 			encrypt->sadb_key_exttype = SADB_EXT_KEY_ENCRYPT;
   2336 			break;
   2337 		case TOK_AUTHKEY:
   2338 			if (auth != NULL) {
   2339 				ERROR(ep, ebuf, gettext(
   2340 				    "Can only specify single"
   2341 				    " authentication key.\n"));
   2342 				break;
   2343 			}
   2344 			auth = parsekey(*argv, ebuf, 0);
   2345 			argv++;
   2346 			if (auth == NULL) {
   2347 				ERROR(ep, ebuf, gettext(
   2348 				    "Invalid authentication key.\n"));
   2349 				break;
   2350 			}
   2351 			totallen += SADB_64TO8(auth->sadb_key_len);
   2352 			auth->sadb_key_exttype = SADB_EXT_KEY_AUTH;
   2353 			break;
   2354 		case TOK_SRCIDTYPE:
   2355 			if (*argv == NULL || *(argv + 1) == NULL) {
   2356 				FATAL(ep, ebuf, gettext(
   2357 				    "Unexpected end of command "
   2358 				    "line - Expecting Src Type.\n"));
   2359 				/* NOTREACHED */
   2360 				break;
   2361 			}
   2362 			if (srcid != NULL) {
   2363 				ERROR(ep, ebuf, gettext(
   2364 				    "Can only specify single"
   2365 				    " source certificate identity.\n"));
   2366 				break;
   2367 			}
   2368 			alloclen = sizeof (*srcid) +
   2369 			    roundup(strlen(*(argv + 1)) + 1, 8);
   2370 			srcid = malloc(alloclen);
   2371 			if (srcid == NULL)
   2372 				Bail("malloc(srcid)");
   2373 			totallen += alloclen;
   2374 			srcid->sadb_ident_type = parseidtype(*argv, ebuf);
   2375 			argv++;
   2376 			srcid->sadb_ident_len = SADB_8TO64(alloclen);
   2377 			srcid->sadb_ident_exttype = SADB_EXT_IDENTITY_SRC;
   2378 			srcid->sadb_ident_reserved = 0;
   2379 			srcid->sadb_ident_id = 0;  /* Not useful here. */
   2380 			(void) strlcpy((char *)(srcid + 1), *argv, alloclen);
   2381 			argv++;
   2382 			break;
   2383 		case TOK_DSTIDTYPE:
   2384 			if (*argv == NULL || *(argv + 1) == NULL) {
   2385 				ERROR(ep, ebuf, gettext(
   2386 				    "Unexpected end of command"
   2387 				    " line - expecting dst type.\n"));
   2388 				break;
   2389 			}
   2390 			if (dstid != NULL) {
   2391 				ERROR(ep, ebuf, gettext(
   2392 				    "Can only specify single destination "
   2393 				    "certificate identity.\n"));
   2394 				break;
   2395 			}
   2396 			alloclen = sizeof (*dstid) +
   2397 			    roundup(strlen(*(argv + 1)) + 1, 8);
   2398 			dstid = malloc(alloclen);
   2399 			if (dstid == NULL)
   2400 				Bail("malloc(dstid)");
   2401 			totallen += alloclen;
   2402 			dstid->sadb_ident_type = parseidtype(*argv, ebuf);
   2403 			argv++;
   2404 			dstid->sadb_ident_len = SADB_8TO64(alloclen);
   2405 			dstid->sadb_ident_exttype = SADB_EXT_IDENTITY_DST;
   2406 			dstid->sadb_ident_reserved = 0;
   2407 			dstid->sadb_ident_id = 0;  /* Not useful here. */
   2408 			(void) strlcpy((char *)(dstid + 1), *argv, alloclen);
   2409 			argv++;
   2410 			break;
   2411 		case TOK_HARD_ALLOC:
   2412 		case TOK_HARD_BYTES:
   2413 		case TOK_HARD_ADDTIME:
   2414 		case TOK_HARD_USETIME:
   2415 			if (hard == NULL) {
   2416 				hard = malloc(sizeof (*hard));
   2417 				if (hard == NULL)
   2418 					Bail("malloc(hard_lifetime)");
   2419 				bzero(hard, sizeof (*hard));
   2420 				hard->sadb_lifetime_exttype =
   2421 				    SADB_EXT_LIFETIME_HARD;
   2422 				hard->sadb_lifetime_len =
   2423 				    SADB_8TO64(sizeof (*hard));
   2424 				totallen += sizeof (*hard);
   2425 			}
   2426 			switch (token) {
   2427 			case TOK_HARD_ALLOC:
   2428 				if (hard->sadb_lifetime_allocations != 0) {
   2429 					ERROR(ep, ebuf, gettext(
   2430 					    "Can only specify single"
   2431 					    " hard allocation limit.\n"));
   2432 					break;
   2433 				}
   2434 				hard->sadb_lifetime_allocations =
   2435 				    (uint32_t)parsenum(*argv, B_TRUE, ebuf);
   2436 				break;
   2437 			case TOK_HARD_BYTES:
   2438 				if (hard->sadb_lifetime_bytes != 0) {
   2439 					ERROR(ep, ebuf, gettext(
   2440 					    "Can only specify "
   2441 					    "single hard byte limit.\n"));
   2442 					break;
   2443 				}
   2444 				hard->sadb_lifetime_bytes = parsenum(*argv,
   2445 				    B_TRUE, ebuf);
   2446 				break;
   2447 			case TOK_HARD_ADDTIME:
   2448 				if (hard->sadb_lifetime_addtime != 0) {
   2449 					ERROR(ep, ebuf, gettext(
   2450 					    "Can only specify "
   2451 					    "single past-add lifetime.\n"));
   2452 					break;
   2453 				}
   2454 				hard->sadb_lifetime_addtime = parsenum(*argv,
   2455 				    B_TRUE, ebuf);
   2456 				break;
   2457 			case TOK_HARD_USETIME:
   2458 				if (hard->sadb_lifetime_usetime != 0) {
   2459 					ERROR(ep, ebuf, gettext(
   2460 					    "Can only specify "
   2461 					    "single past-use lifetime.\n"));
   2462 					break;
   2463 				}
   2464 				hard->sadb_lifetime_usetime = parsenum(*argv,
   2465 				    B_TRUE, ebuf);
   2466 				break;
   2467 			}
   2468 			argv++;
   2469 			break;
   2470 		case TOK_SOFT_ALLOC:
   2471 		case TOK_SOFT_BYTES:
   2472 		case TOK_SOFT_ADDTIME:
   2473 		case TOK_SOFT_USETIME:
   2474 			if (soft == NULL) {
   2475 				soft = malloc(sizeof (*soft));
   2476 				if (soft == NULL)
   2477 					Bail("malloc(soft_lifetime)");
   2478 				bzero(soft, sizeof (*soft));
   2479 				soft->sadb_lifetime_exttype =
   2480 				    SADB_EXT_LIFETIME_SOFT;
   2481 				soft->sadb_lifetime_len =
   2482 				    SADB_8TO64(sizeof (*soft));
   2483 				totallen += sizeof (*soft);
   2484 			}
   2485 			switch (token) {
   2486 			case TOK_SOFT_ALLOC:
   2487 				if (soft->sadb_lifetime_allocations != 0) {
   2488 					ERROR(ep, ebuf, gettext(
   2489 					    "Can only specify single"
   2490 					    " soft allocation limit.\n"));
   2491 					break;
   2492 				}
   2493 				soft->sadb_lifetime_allocations =
   2494 				    (uint32_t)parsenum(*argv, B_TRUE, ebuf);
   2495 				break;
   2496 			case TOK_SOFT_BYTES:
   2497 				if (soft->sadb_lifetime_bytes != 0) {
   2498 					ERROR(ep, ebuf, gettext(
   2499 					    "Can only specify single"
   2500 					    " soft byte limit.\n"));
   2501 					break;
   2502 				}
   2503 				soft->sadb_lifetime_bytes = parsenum(*argv,
   2504 				    B_TRUE, ebuf);
   2505 				break;
   2506 			case TOK_SOFT_ADDTIME:
   2507 				if (soft->sadb_lifetime_addtime != 0) {
   2508 					ERROR(ep, ebuf, gettext(
   2509 					    "Can only specify single"
   2510 					    " past-add lifetime.\n"));
   2511 					break;
   2512 				}
   2513 				soft->sadb_lifetime_addtime = parsenum(*argv,
   2514 				    B_TRUE, ebuf);
   2515 				break;
   2516 			case TOK_SOFT_USETIME:
   2517 				if (soft->sadb_lifetime_usetime != 0) {
   2518 					ERROR(ep, ebuf, gettext(
   2519 					    "Can only specify single"
   2520 					    " past-use lifetime.\n"));
   2521 					break;
   2522 				}
   2523 				soft->sadb_lifetime_usetime = parsenum(*argv,
   2524 				    B_TRUE, ebuf);
   2525 				break;
   2526 			}
   2527 			argv++;
   2528 			break;
   2529 		case TOK_FLAG_INBOUND:
   2530 			assoc->sadb_sa_flags |= SADB_X_SAFLAGS_INBOUND;
   2531 			break;
   2532 		case TOK_FLAG_OUTBOUND:
   2533 			assoc->sadb_sa_flags |= SADB_X_SAFLAGS_OUTBOUND;
   2534 			break;
   2535 		case TOK_REPLAY_VALUE:
   2536 			if (replay_ctr != NULL) {
   2537 				ERROR(ep, ebuf, gettext(
   2538 				    "Can only specify single "
   2539 				    "replay value."));
   2540 				break;
   2541 			}
   2542 			replay_ctr = calloc(1, sizeof (*replay_ctr));
   2543 			if (replay_ctr == NULL) {
   2544 				Bail("malloc(replay value)");
   2545 			}
   2546 			/*
   2547 			 * We currently do not support a 64-bit
   2548 			 * replay value.  RFC 4301 will require one,
   2549 			 * however, and we have a field in place when
   2550 			 * 4301 is built.
   2551 			 */
   2552 			replay_ctr->sadb_x_rc_exttype = SADB_X_EXT_REPLAY_VALUE;
   2553 			replay_ctr->sadb_x_rc_len =
   2554 			    SADB_8TO64(sizeof (*replay_ctr));
   2555 			totallen += sizeof (*replay_ctr);
   2556 			replay_ctr->sadb_x_rc_replay32 = (uint32_t)parsenum(
   2557 			    *argv, B_TRUE, ebuf);
   2558 			argv++;
   2559 			break;
   2560 		case TOK_IDLE_ADDTIME:
   2561 		case TOK_IDLE_USETIME:
   2562 			if (idle == NULL) {
   2563 				idle = calloc(1, sizeof (*idle));
   2564 				if (idle == NULL) {
   2565 					Bail("malloc idle lifetime");
   2566 				}
   2567 				idle->sadb_lifetime_exttype =
   2568 				    SADB_X_EXT_LIFETIME_IDLE;
   2569 				idle->sadb_lifetime_len =
   2570 				    SADB_8TO64(sizeof (*idle));
   2571 				totallen += sizeof (*idle);
   2572 			}
   2573 			switch (token) {
   2574 			case TOK_IDLE_ADDTIME:
   2575 				idle->sadb_lifetime_addtime =
   2576 				    (uint32_t)parsenum(*argv,
   2577 				    B_TRUE, ebuf);
   2578 				break;
   2579 			case TOK_IDLE_USETIME:
   2580 				idle->sadb_lifetime_usetime =
   2581 				    (uint32_t)parsenum(*argv,
   2582 				    B_TRUE, ebuf);
   2583 				break;
   2584 			}
   2585 			argv++;
   2586 			break;
   2587 		case TOK_RESERVED:
   2588 			if (encrypt != NULL)
   2589 				ERROR(ep, ebuf, gettext(
   2590 				    "Reserved bits need to be "
   2591 				    "specified before key.\n"));
   2592 			reserved_bits = (uint_t)parsenum(*argv,
   2593 			    B_TRUE, ebuf);
   2594 			argv++;
   2595 			break;
   2596 		case TOK_LABEL:
   2597 			label = parselabel(token, *argv);
   2598 			argv++;
   2599 			if (label == NULL) {
   2600 				ERROR(ep, ebuf,
   2601 				    gettext("Malformed security label\n"));
   2602 				break;
   2603 			} else if (label == PARSELABEL_BAD_TOKEN) {
   2604 				Bail("Internal token value error");
   2605 			}
   2606 			totallen += SADB_64TO8(label->sadb_sens_len);
   2607 			break;
   2608 
   2609 		case TOK_OLABEL:
   2610 		case TOK_IMPLABEL:
   2611 			olabel = parselabel(token, *argv);
   2612 			argv++;
   2613 			if (label == NULL) {
   2614 				ERROR(ep, ebuf,
   2615 				    gettext("Malformed security label\n"));
   2616 				break;
   2617 			} else if (label == PARSELABEL_BAD_TOKEN) {
   2618 				Bail("Internal token value error");
   2619 			}
   2620 			totallen += SADB_64TO8(olabel->sadb_sens_len);
   2621 			break;
   2622 		default:
   2623 			ERROR1(ep, ebuf, gettext(
   2624 			    "Don't use extension %s for add/update.\n"),
   2625 			    *(argv - 1));
   2626 			break;
   2627 		}
   2628 	} while (token != TOK_EOF);
   2629 
   2630 	handle_errors(ep, ebuf, B_TRUE, B_FALSE);
   2631 
   2632 #define	PORT_ONLY_ALLOCATE(af, socktype, exttype, extvar, port) {  \
   2633 	alloclen = sizeof (sadb_address_t) + roundup(sizeof (socktype), 8); \
   2634 	(extvar) = calloc(1, alloclen); \
   2635 	if ((extvar) == NULL) { \
   2636 		Bail("malloc(implicit port)"); \
   2637 	} \
   2638 	totallen += alloclen; \
   2639 	(extvar)->sadb_address_len = SADB_8TO64(alloclen); \
   2640 	(extvar)->sadb_address_exttype = (exttype); \
   2641 	/* sin/sin6 has equivalent offsets for ports! */ \
   2642 	sin6 = (struct sockaddr_in6 *)((extvar) + 1); \
   2643 	sin6->sin6_family = (af); \
   2644 	sin6->sin6_port = (port); \
   2645 	}
   2646 
   2647 	/*
   2648 	 * If we specify inner ports or NAT ports w/o addresses, we still need
   2649 	 * to allocate.  Also, if we have one inner address, we need the
   2650 	 * other, even if we don't specify anything.
   2651 	 */
   2652 	if (use_natt) {
   2653 		if (natt_lport != 0 && natt_local == NULL) {
   2654 			PORT_ONLY_ALLOCATE(AF_INET, struct sockaddr_in,
   2655 			    SADB_X_EXT_ADDRESS_NATT_LOC, natt_local,
   2656 			    natt_lport);
   2657 		}
   2658 
   2659 		if (natt_rport != 0 && natt_remote == NULL) {
   2660 			PORT_ONLY_ALLOCATE(AF_INET, struct sockaddr_in,
   2661 			    SADB_X_EXT_ADDRESS_NATT_REM, natt_remote,
   2662 			    natt_rport);
   2663 		}
   2664 	} else {
   2665 		if (natt_lport != 0 || natt_rport != 0) {
   2666 			ERROR(ep, ebuf, gettext("Must specify 'encap udp' "
   2667 			    "with any NAT-T port.\n"));
   2668 		} else if (natt_local != NULL || natt_remote != NULL) {
   2669 			ERROR(ep, ebuf, gettext("Must specify 'encap udp' "
   2670 			    "with any NAT-T address.\n"));
   2671 		}
   2672 	}
   2673 
   2674 	if (alloc_inner && idst == NULL) {
   2675 		PORT_ONLY_ALLOCATE(AF_INET6, struct sockaddr_in6,
   2676 		    SADB_X_EXT_ADDRESS_INNER_DST, idst, 0);
   2677 	}
   2678 
   2679 	if (alloc_inner && isrc == NULL) {
   2680 		PORT_ONLY_ALLOCATE(AF_INET6, struct sockaddr_in6,
   2681 		    SADB_X_EXT_ADDRESS_INNER_SRC, isrc, 0);
   2682 	}
   2683 #undef PORT_ONLY_ALLOCATE
   2684 
   2685 	/*
   2686 	 * Okay, so now I have all of the potential extensions!
   2687 	 * Allocate a single contiguous buffer.  Keep in mind that it'll
   2688 	 * be enough because the key itself will be yanked.
   2689 	 */
   2690 
   2691 	if (src == NULL && dst != NULL) {
   2692 		/*
   2693 		 * Set explicit unspecified source address.
   2694 		 */
   2695 		size_t lenbytes = SADB_64TO8(dst->sadb_address_len);
   2696 
   2697 		unspec_src = B_TRUE;
   2698 		totallen += lenbytes;
   2699 		src = malloc(lenbytes);
   2700 		if (src == NULL)
   2701 			Bail("malloc(implicit src)");
   2702 		/* Confusing, but we're copying from DST to SRC.  :) */
   2703 		bcopy(dst, src, lenbytes);
   2704 		src->sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
   2705 		sin6 = (struct sockaddr_in6 *)(src + 1);
   2706 		bzero(sin6, sizeof (*sin6));
   2707 		sin6->sin6_family = AF_INET6;
   2708 	}
   2709 
   2710 	msg.sadb_msg_len = SADB_8TO64(totallen);
   2711 
   2712 	buffer = malloc(totallen);
   2713 	nexthdr = buffer;
   2714 	bcopy(&msg, nexthdr, sizeof (msg));
   2715 	nexthdr += SADB_8TO64(sizeof (msg));
   2716 	if (assoc != NULL) {
   2717 		if (assoc->sadb_sa_spi == 0) {
   2718 			ERROR1(ep, ebuf, gettext(
   2719 			    "The SPI value is missing for "
   2720 			    "the association you wish to %s.\n"), thiscmd);
   2721 		}
   2722 		if (assoc->sadb_sa_auth == 0 && assoc->sadb_sa_encrypt == 0 &&
   2723 		    cmd == CMD_ADD) {
   2724 			free(assoc);
   2725 			FATAL(ep, ebuf, gettext(
   2726 			    "Select at least one algorithm "
   2727 			    "for this add.\n"));
   2728 		}
   2729 
   2730 		/* Hack to let user specify NULL ESP implicitly. */
   2731 		if (msg.sadb_msg_satype == SADB_SATYPE_ESP &&
   2732 		    assoc->sadb_sa_encrypt == 0)
   2733 			assoc->sadb_sa_encrypt = SADB_EALG_NULL;
   2734 
   2735 		/* 0 is an actual value.  Print a warning if it was entered. */
   2736 		if (assoc->sadb_sa_state == 0) {
   2737 			if (readstate) {
   2738 				ERROR(ep, ebuf, gettext(
   2739 				    "WARNING: Cannot set LARVAL SA state.\n"));
   2740 			}
   2741 			assoc->sadb_sa_state = SADB_SASTATE_MATURE;
   2742 		}
   2743 
   2744 		if (use_natt) {
   2745 			if (natt_remote != NULL)
   2746 				assoc->sadb_sa_flags |= SADB_X_SAFLAGS_NATT_REM;
   2747 			if (natt_local != NULL)
   2748 				assoc->sadb_sa_flags |= SADB_X_SAFLAGS_NATT_LOC;
   2749 		}
   2750 
   2751 		if (alloc_inner) {
   2752 			/*
   2753 			 * For now, assume RFC 3884's dream of transport-mode
   2754 			 * SAs with inner IP address selectors will not
   2755 			 * happen.
   2756 			 */
   2757 			assoc->sadb_sa_flags |= SADB_X_SAFLAGS_TUNNEL;
   2758 			if (proto != 0 && proto != IPPROTO_ENCAP &&
   2759 			    proto != IPPROTO_IPV6) {
   2760 				ERROR1(ep, ebuf, gettext(
   2761 				    "WARNING: Protocol type %d not "
   2762 				    "for use with Tunnel-Mode SA.\n"), proto);
   2763 				/* Continue and let PF_KEY scream... */
   2764 			}
   2765 		}
   2766 
   2767 		bcopy(assoc, nexthdr, SADB_64TO8(assoc->sadb_sa_len));
   2768 		nexthdr += assoc->sadb_sa_len;
   2769 		/* Save the SPI for the case of an error. */
   2770 		spi = assoc->sadb_sa_spi;
   2771 		free(assoc);
   2772 	} else {
   2773 		if (spi == 0)
   2774 			ERROR1(ep, ebuf, gettext(
   2775 			    "Need to define SPI for %s.\n"), thiscmd);
   2776 		ERROR1(ep, ebuf, gettext(
   2777 		    "Need SA parameters for %s.\n"), thiscmd);
   2778 	}
   2779 
   2780 	if (sadb_pair != NULL) {
   2781 		if (sadb_pair->sadb_x_pair_spi == 0) {
   2782 			ERROR1(ep, ebuf, gettext(
   2783 			    "The SPI value is missing for the "
   2784 			    "association you wish to %s.\n"), thiscmd);
   2785 		}
   2786 		bcopy(sadb_pair, nexthdr,
   2787 		    SADB_64TO8(sadb_pair->sadb_x_pair_len));
   2788 		nexthdr += sadb_pair->sadb_x_pair_len;
   2789 		free(sadb_pair);
   2790 	}
   2791 
   2792 	if (hard != NULL) {
   2793 		bcopy(hard, nexthdr, SADB_64TO8(hard->sadb_lifetime_len));
   2794 		nexthdr += hard->sadb_lifetime_len;
   2795 		free(hard);
   2796 	}
   2797 
   2798 	if (soft != NULL) {
   2799 		bcopy(soft, nexthdr, SADB_64TO8(soft->sadb_lifetime_len));
   2800 		nexthdr += soft->sadb_lifetime_len;
   2801 		free(soft);
   2802 	}
   2803 
   2804 	if (idle != NULL) {
   2805 		bcopy(idle, nexthdr, SADB_64TO8(idle->sadb_lifetime_len));
   2806 		nexthdr += idle->sadb_lifetime_len;
   2807 		free(idle);
   2808 	}
   2809 
   2810 	if (encrypt == NULL && auth == NULL && cmd == CMD_ADD) {
   2811 		ERROR(ep, ebuf, gettext(
   2812 		    "Must have at least one key for an add.\n"));
   2813 	}
   2814 
   2815 	if (encrypt != NULL) {
   2816 		bcopy(encrypt, nexthdr, SADB_64TO8(encrypt->sadb_key_len));
   2817 		nexthdr += encrypt->sadb_key_len;
   2818 		bzero(encrypt, SADB_64TO8(encrypt->sadb_key_len));
   2819 		free(encrypt);
   2820 	}
   2821 
   2822 	if (auth != NULL) {
   2823 		bcopy(auth, nexthdr, SADB_64TO8(auth->sadb_key_len));
   2824 		nexthdr += auth->sadb_key_len;
   2825 		bzero(auth, SADB_64TO8(auth->sadb_key_len));
   2826 		free(auth);
   2827 	}
   2828 
   2829 	if (srcid != NULL) {
   2830 		bcopy(srcid, nexthdr, SADB_64TO8(srcid->sadb_ident_len));
   2831 		nexthdr += srcid->sadb_ident_len;
   2832 		free(srcid);
   2833 	}
   2834 
   2835 	if (dstid != NULL) {
   2836 		bcopy(dstid, nexthdr, SADB_64TO8(dstid->sadb_ident_len));
   2837 		nexthdr += dstid->sadb_ident_len;
   2838 		free(dstid);
   2839 	}
   2840 
   2841 	if (dst != NULL) {
   2842 		bcopy(dst, nexthdr, SADB_64TO8(dst->sadb_address_len));
   2843 		free(dst);
   2844 		dst = (struct sadb_address *)nexthdr;
   2845 		dst->sadb_address_proto = proto;
   2846 		((struct sockaddr_in6 *)(dst + 1))->sin6_port = htons(dstport);
   2847 		nexthdr += dst->sadb_address_len;
   2848 	} else {
   2849 		FATAL1(ep, ebuf, gettext(
   2850 		    "Need destination address for %s.\n"), thiscmd);
   2851 	}
   2852 
   2853 	if (use_natt) {
   2854 		if (natt_remote == NULL && natt_local == NULL) {
   2855 			ERROR(ep, ebuf, gettext(
   2856 			    "Must specify NAT-T remote or local address "
   2857 			    "for UDP encapsulation.\n"));
   2858 		}
   2859 
   2860 		if (natt_remote != NULL) {
   2861 			bcopy(natt_remote, nexthdr,
   2862 			    SADB_64TO8(natt_remote->sadb_address_len));
   2863 			free(natt_remote);
   2864 			natt_remote = (struct sadb_address *)nexthdr;
   2865 			nexthdr += natt_remote->sadb_address_len;
   2866 			((struct sockaddr_in6 *)(natt_remote + 1))->sin6_port =
   2867 			    htons(natt_rport);
   2868 		}
   2869 
   2870 		if (natt_local != NULL) {
   2871 			bcopy(natt_local, nexthdr,
   2872 			    SADB_64TO8(natt_local->sadb_address_len));
   2873 			free(natt_local);
   2874 			natt_local = (struct sadb_address *)nexthdr;
   2875 			nexthdr += natt_local->sadb_address_len;
   2876 			((struct sockaddr_in6 *)(natt_local + 1))->sin6_port =
   2877 			    htons(natt_lport);
   2878 		}
   2879 	}
   2880 
   2881 	handle_errors(ep, ebuf, B_TRUE, B_FALSE);
   2882 
   2883 	/*
   2884 	 * PF_KEY requires a source address extension, even if the source
   2885 	 * address itself is unspecified. (See "Set explicit unspecified..."
   2886 	 * code fragment above. Destination reality check was above.)
   2887 	 */
   2888 	bcopy(src, nexthdr, SADB_64TO8(src->sadb_address_len));
   2889 	free(src);
   2890 	src = (struct sadb_address *)nexthdr;
   2891 	src->sadb_address_proto = proto;
   2892 	((struct sockaddr_in6 *)(src + 1))->sin6_port = htons(srcport);
   2893 	nexthdr += src->sadb_address_len;
   2894 
   2895 	if (isrc != NULL) {
   2896 		bcopy(isrc, nexthdr, SADB_64TO8(isrc->sadb_address_len));
   2897 		free(isrc);
   2898 		isrc = (struct sadb_address *)nexthdr;
   2899 		isrc->sadb_address_proto = iproto;
   2900 		((struct sockaddr_in6 *)(isrc + 1))->sin6_port =
   2901 		    htons(isrcport);
   2902 		nexthdr += isrc->sadb_address_len;
   2903 	}
   2904 
   2905 	if (idst != NULL) {
   2906 		bcopy(idst, nexthdr, SADB_64TO8(idst->sadb_address_len));
   2907 		free(idst);
   2908 		idst = (struct sadb_address *)nexthdr;
   2909 		idst->sadb_address_proto = iproto;
   2910 		((struct sockaddr_in6 *)(idst + 1))->sin6_port =
   2911 		    htons(idstport);
   2912 		nexthdr += idst->sadb_address_len;
   2913 	}
   2914 
   2915 	if (replay_ctr != NULL) {
   2916 		bcopy(replay_ctr, nexthdr,
   2917 		    SADB_64TO8(replay_ctr->sadb_x_rc_len));
   2918 		nexthdr += replay_ctr->sadb_x_rc_len;
   2919 		free(replay_ctr);
   2920 	}
   2921 
   2922 	if (label != NULL) {
   2923 		bcopy(label, nexthdr, SADB_64TO8(label->sadb_sens_len));
   2924 		nexthdr += label->sadb_sens_len;
   2925 		free(label);
   2926 		label = NULL;
   2927 	}
   2928 
   2929 	if (olabel != NULL) {
   2930 		bcopy(olabel, nexthdr, SADB_64TO8(olabel->sadb_sens_len));
   2931 		nexthdr += olabel->sadb_sens_len;
   2932 		free(olabel);
   2933 		olabel = NULL;
   2934 	}
   2935 
   2936 	if (cflag) {
   2937 		/*
   2938 		 * Assume the checked cmd would have worked if it was actually
   2939 		 * used. doaddresses() will increment lines_added if it
   2940 		 * succeeds.
   2941 		 */
   2942 		lines_added++;
   2943 	} else {
   2944 		doaddresses(sadb_msg_type, satype,
   2945 		    cmd, srchp, dsthp, src, dst, unspec_src, buffer, totallen,
   2946 		    spi, ebuf);
   2947 	}
   2948 
   2949 	if (isrchp != NULL && isrchp != &dummy.he)
   2950 		freehostent(isrchp);
   2951 	if (idsthp != NULL && idsthp != &dummy.he)
   2952 		freehostent(idsthp);
   2953 	if (srchp != NULL && srchp != &dummy.he)
   2954 		freehostent(srchp);
   2955 	if (dsthp != NULL && dsthp != &dummy.he)
   2956 		freehostent(dsthp);
   2957 	if (natt_lhp != NULL && natt_lhp != &dummy.he)
   2958 		freehostent(natt_lhp);
   2959 	if (natt_rhp != NULL && natt_rhp != &dummy.he)
   2960 		freehostent(natt_rhp);
   2961 	free(ebuf);
   2962 	free(buffer);
   2963 }
   2964 
   2965 /*
   2966  * DELETE and GET are similar, in that they only need the extensions
   2967  * required to _find_ an SA, and then either delete it or obtain its
   2968  * information.
   2969  */
   2970 static void
   2971 dodelget(int cmd, int satype, char *argv[], char *ebuf)
   2972 {
   2973 	struct sadb_msg *msg = (struct sadb_msg *)get_buffer;
   2974 	uint64_t *nextext;
   2975 	struct sadb_sa *assoc = NULL;
   2976 	struct sadb_address *src = NULL, *dst = NULL;
   2977 	int next, token, sa_len;
   2978 	char *thiscmd;
   2979 	uint32_t spi;
   2980 	uint8_t	sadb_msg_type;
   2981 	struct hostent *srchp = NULL, *dsthp = NULL;
   2982 	struct sockaddr_in6 *sin6;
   2983 	boolean_t unspec_src = B_TRUE;
   2984 	uint16_t srcport = 0, dstport = 0;
   2985 	uint8_t proto = 0;
   2986 	char *ep = NULL;
   2987 
   2988 	/* Set the first extension header to right past the base message. */
   2989 	nextext = (uint64_t *)(msg + 1);
   2990 	bzero(nextext, sizeof (get_buffer) - sizeof (*msg));
   2991 
   2992 	switch (cmd) {
   2993 	case CMD_GET:
   2994 		thiscmd = "get";
   2995 		sadb_msg_type = SADB_GET;
   2996 		break;
   2997 	case CMD_DELETE:
   2998 		thiscmd = "delete";
   2999 		sadb_msg_type = SADB_DELETE;
   3000 		break;
   3001 	case CMD_DELETE_PAIR:
   3002 		thiscmd = "delete-pair";
   3003 		sadb_msg_type = SADB_X_DELPAIR;
   3004 		break;
   3005 	}
   3006 
   3007 	msg_init(msg, sadb_msg_type, (uint8_t)satype);
   3008 
   3009 #define	ALLOC_ADDR_EXT(ext, exttype)			\
   3010 	(ext) = (struct sadb_address *)nextext;		\
   3011 	nextext = (uint64_t *)((ext) + 1);		\
   3012 	nextext += SADB_8TO64(roundup(sa_len, 8));	\
   3013 	(ext)->sadb_address_exttype = exttype;		\
   3014 	(ext)->sadb_address_len = nextext - ((uint64_t *)ext);
   3015 
   3016 	/* Assume last element in argv is set to NULL. */
   3017 	do {
   3018 		token = parseextval(*argv, &next);
   3019 		argv++;
   3020 		switch (token) {
   3021 		case TOK_EOF:
   3022 			/* Do nothing, I'm done. */
   3023 			break;
   3024 		case TOK_UNKNOWN:
   3025 			ERROR1(ep, ebuf, gettext(
   3026 			    "Unknown extension field \"%s\"\n"), *(argv - 1));
   3027 			break;
   3028 		case TOK_SPI:
   3029 			if (assoc != NULL) {
   3030 				ERROR(ep, ebuf, gettext(
   3031 				    "Can only specify single SPI value.\n"));
   3032 				break;
   3033 			}
   3034 			assoc = (struct sadb_sa *)nextext;
   3035 			nextext = (uint64_t *)(assoc + 1);
   3036 			assoc->sadb_sa_len = SADB_8TO64(sizeof (*assoc));
   3037 			assoc->sadb_sa_exttype = SADB_EXT_SA;
   3038 			assoc->sadb_sa_spi = htonl((uint32_t)parsenum(*argv,
   3039 			    B_TRUE, ebuf));
   3040 			spi = assoc->sadb_sa_spi;
   3041 			argv++;
   3042 			break;
   3043 		case TOK_SRCPORT:
   3044 			if (srcport != 0) {
   3045 				ERROR(ep, ebuf, gettext(
   3046 				    "Can only specify single source port.\n"));
   3047 				break;
   3048 			}
   3049 			srcport = parsenum(*argv, B_TRUE, ebuf);
   3050 			argv++;
   3051 			break;
   3052 		case TOK_DSTPORT:
   3053 			if (dstport != 0) {
   3054 				ERROR(ep, ebuf, gettext(
   3055 				    "Can only "
   3056 				    "specify single destination port.\n"));
   3057 				break;
   3058 			}
   3059 			dstport = parsenum(*argv, B_TRUE, ebuf);
   3060 			argv++;
   3061 			break;
   3062 		case TOK_PROTO:
   3063 			if (proto != 0) {
   3064 				ERROR(ep, ebuf, gettext(
   3065 				    "Can only specify single protocol.\n"));
   3066 				break;
   3067 			}
   3068 			proto = parsenum(*argv, B_TRUE, ebuf);
   3069 			argv++;
   3070 			break;
   3071 		case TOK_SRCADDR:
   3072 		case TOK_SRCADDR6:
   3073 			if (src != NULL) {
   3074 				ERROR(ep, ebuf, gettext(
   3075 				    "Can only specify single source addr.\n"));
   3076 				break;
   3077 			}
   3078 			sa_len = parseaddr(*argv, &srchp,
   3079 			    (token == TOK_SRCADDR6), ebuf);
   3080 			if (srchp == NULL) {
   3081 				ERROR1(ep, ebuf, gettext(
   3082 				    "Unknown source address \"%s\"\n"), *argv);
   3083 				break;
   3084 			}
   3085 			argv++;
   3086 
   3087 			unspec_src = B_FALSE;
   3088 
   3089 			ALLOC_ADDR_EXT(src, SADB_EXT_ADDRESS_SRC);
   3090 
   3091 			if (srchp == &dummy.he) {
   3092 				/*
   3093 				 * Single address with -n flag.
   3094 				 */
   3095 				sin6 = (struct sockaddr_in6 *)(src + 1);
   3096 				bzero(sin6, sizeof (*sin6));
   3097 				sin6->sin6_family = AF_INET6;
   3098 				bcopy(srchp->h_addr_list[0], &sin6->sin6_addr,
   3099 				    sizeof (struct in6_addr));
   3100 			}
   3101 			/* The rest is pre-bzeroed for us. */
   3102 			break;
   3103 		case TOK_DSTADDR:
   3104 		case TOK_DSTADDR6:
   3105 			if (dst != NULL) {
   3106 				ERROR(ep, ebuf, gettext(
   3107 				    "Can only specify single destination "
   3108 				    "address.\n"));
   3109 				break;
   3110 			}
   3111 			sa_len = parseaddr(*argv, &dsthp,
   3112 			    (token == TOK_SRCADDR6), ebuf);
   3113 			if (dsthp == NULL) {
   3114 				ERROR1(ep, ebuf, gettext(
   3115 				    "Unknown destination address \"%s\"\n"),
   3116 				    *argv);
   3117 				break;
   3118 			}
   3119 			argv++;
   3120 
   3121 			ALLOC_ADDR_EXT(dst, SADB_EXT_ADDRESS_DST);
   3122 
   3123 			if (dsthp == &dummy.he) {
   3124 				/*
   3125 				 * Single address with -n flag.
   3126 				 */
   3127 				sin6 = (struct sockaddr_in6 *)(dst + 1);
   3128 				bzero(sin6, sizeof (*sin6));
   3129 				sin6->sin6_family = AF_INET6;
   3130 				bcopy(dsthp->h_addr_list[0], &sin6->sin6_addr,
   3131 				    sizeof (struct in6_addr));
   3132 			}
   3133 			/* The rest is pre-bzeroed for us. */
   3134 			break;
   3135 		case TOK_FLAG_INBOUND:
   3136 			assoc->sadb_sa_flags |= SADB_X_SAFLAGS_INBOUND;
   3137 			break;
   3138 		case TOK_FLAG_OUTBOUND:
   3139 			assoc->sadb_sa_flags |= SADB_X_SAFLAGS_OUTBOUND;
   3140 			break;
   3141 		default:
   3142 			ERROR2(ep, ebuf, gettext(
   3143 			    "Don't use extension %s for '%s' command.\n"),
   3144 			    *(argv - 1), thiscmd);
   3145 			break;
   3146 		}
   3147 	} while (token != TOK_EOF);
   3148 
   3149 	handle_errors(ep, ebuf, B_TRUE, B_FALSE);
   3150 
   3151 	if ((srcport != 0) && (src == NULL)) {
   3152 		ALLOC_ADDR_EXT(src, SADB_EXT_ADDRESS_SRC);
   3153 		sin6 = (struct sockaddr_in6 *)(src + 1);
   3154 		src->sadb_address_proto = proto;
   3155 		bzero(sin6, sizeof (*sin6));
   3156 		sin6->sin6_family = AF_INET6;
   3157 		sin6->sin6_port = htons(srcport);
   3158 	}
   3159 
   3160 	if ((dstport != 0) && (dst == NULL)) {
   3161 		ALLOC_ADDR_EXT(dst, SADB_EXT_ADDRESS_DST);
   3162 		sin6 = (struct sockaddr_in6 *)(dst + 1);
   3163 		src->sadb_address_proto = proto;
   3164 		bzero(sin6, sizeof (*sin6));
   3165 		sin6->sin6_family = AF_INET6;
   3166 		sin6->sin6_port = htons(dstport);
   3167 	}
   3168 
   3169 	/* So I have enough of the message to send it down! */
   3170 	msg->sadb_msg_len = nextext - get_buffer;
   3171 
   3172 	if (assoc == NULL) {
   3173 		FATAL1(ep, ebuf, gettext(
   3174 		    "Need SA parameters for %s.\n"), thiscmd);
   3175 	}
   3176 
   3177 	if (cflag) {
   3178 		/*
   3179 		 * Assume the checked cmd would have worked if it was actually
   3180 		 * used. doaddresses() will increment lines_added if it
   3181 		 * succeeds.
   3182 		 */
   3183 		lines_added++;
   3184 	} else {
   3185 		doaddresses(sadb_msg_type, satype,
   3186 		    cmd, srchp, dsthp, src, dst, unspec_src, get_buffer,
   3187 		    sizeof (get_buffer), spi, NULL);
   3188 	}
   3189 
   3190 	if (srchp != NULL && srchp != &dummy.he)
   3191 		freehostent(srchp);
   3192 	if (dsthp != NULL && dsthp != &dummy.he)
   3193 		freehostent(dsthp);
   3194 }
   3195 
   3196 /*
   3197  * "ipseckey monitor" should exit very gracefully if ^C is tapped provided
   3198  * it is not running in interactive mode.
   3199  */
   3200 static void
   3201 monitor_catch(int signal)
   3202 {
   3203 	if (!interactive)
   3204 		errx(signal, gettext("Bailing on signal %d."), signal);
   3205 }
   3206 
   3207 /*
   3208  * Loop forever, listening on PF_KEY messages.
   3209  */
   3210 static void
   3211 domonitor(boolean_t passive)
   3212 {
   3213 	struct sadb_msg *samsg;
   3214 	struct sigaction newsig, oldsig;
   3215 	int rc;
   3216 
   3217 	/* Catch ^C. */
   3218 	newsig.sa_handler = monitor_catch;
   3219 	newsig.sa_flags = 0;
   3220 	(void) sigemptyset(&newsig.sa_mask);
   3221 	(void) sigaddset(&newsig.sa_mask, SIGINT);
   3222 	(void) sigaction(SIGINT, &newsig, &oldsig);
   3223 
   3224 	samsg = (struct sadb_msg *)get_buffer;
   3225 	if (!passive) {
   3226 		(void) printf(gettext("Actively"));
   3227 		msg_init(samsg, SADB_X_PROMISC, 1);	/* Turn ON promisc. */
   3228 		rc = key_write(keysock, samsg, sizeof (*samsg));
   3229 		if (rc == -1)
   3230 			Bail("write (SADB_X_PROMISC)");
   3231 	} else {
   3232 		(void) printf(gettext("Passively"));
   3233 	}
   3234 	(void) printf(gettext(" monitoring the PF_KEY socket.\n"));
   3235 
   3236 	for (; ; ) {
   3237 		/*
   3238 		 * I assume that read() is non-blocking, and will never
   3239 		 * return 0.
   3240 		 */
   3241 		rc = read(keysock, samsg, sizeof (get_buffer));
   3242 		if (rc == -1) {
   3243 			if (errno == EINTR && interactive)
   3244 				goto out;
   3245 			else
   3246 				Bail("read (in domonitor)");
   3247 		}
   3248 		(void) printf(gettext("Read %d bytes.\n"), rc);
   3249 		/*
   3250 		 * Q:  Should I use the same method of printing as GET does?
   3251 		 * A:  For now, yes.
   3252 		 */
   3253 		print_samsg(stdout, get_buffer, B_TRUE, vflag, nflag);
   3254 		(void) putchar('\n');
   3255 	}
   3256 
   3257 out:
   3258 	if (interactive)
   3259 		/* restore SIGINT behavior */
   3260 		(void) sigaction(SIGINT, &oldsig, NULL);
   3261 }
   3262 
   3263 /*
   3264  * Either mask or unmask all relevant signals.
   3265  */
   3266 static void
   3267 mask_signals(boolean_t unmask)
   3268 {
   3269 	sigset_t set;
   3270 	static sigset_t oset;
   3271 
   3272 	if (unmask) {
   3273 		(void) sigprocmask(SIG_SETMASK, &oset, NULL);
   3274 	} else {
   3275 		(void) sigfillset(&set);
   3276 		(void) sigprocmask(SIG_SETMASK, &set, &oset);
   3277 	}
   3278 }
   3279 
   3280 /*
   3281  * Assorted functions to print help text.
   3282  */
   3283 #define	puts_tr(s) (void) puts(gettext(s))
   3284 
   3285 static void
   3286 doattrhelp()
   3287 {
   3288 	int i;
   3289 
   3290 	puts_tr("\nSA attributes:");
   3291 
   3292 	for (i = 0; tokens[i].string != NULL; i++) {
   3293 		if (i%3 == 0)
   3294 			(void) printf("\n");
   3295 		(void) printf("    %-15.15s", tokens[i].string);
   3296 	}
   3297 	(void) printf("\n");
   3298 }
   3299 
   3300 static void
   3301 dohelpcmd(char *cmds)
   3302 {
   3303 	int cmd;
   3304 
   3305 	if (strcmp(cmds, "attr") == 0) {
   3306 		doattrhelp();
   3307 		return;
   3308 	}
   3309 
   3310 	cmd = parsecmd(cmds);
   3311 	switch (cmd) {
   3312 	case CMD_UPDATE:
   3313 		puts_tr("update	 - Update an existing SA");
   3314 		break;
   3315 	case CMD_UPDATE_PAIR:
   3316 		puts_tr("update-pair - Update an existing pair of SA's");
   3317 		break;
   3318 	case CMD_ADD:
   3319 		puts_tr("add	 - Add a new security association (SA)");
   3320 		break;
   3321 	case CMD_DELETE:
   3322 		puts_tr("delete - Delete an SA");
   3323 		break;
   3324 	case CMD_DELETE_PAIR:
   3325 		puts_tr("delete-pair - Delete a pair of SA's");
   3326 		break;
   3327 	case CMD_GET:
   3328 		puts_tr("get - Display an SA");
   3329 		break;
   3330 	case CMD_FLUSH:
   3331 		puts_tr("flush - Delete all SAs");
   3332 		puts_tr("");
   3333 		puts_tr("Optional arguments:");
   3334 		puts_tr("all        delete all SAs");
   3335 		puts_tr("esp        delete just ESP SAs");
   3336 		puts_tr("ah         delete just AH SAs");
   3337 		puts_tr("<number>   delete just SAs with type given by number");
   3338 		puts_tr("");
   3339 		break;
   3340 	case CMD_DUMP:
   3341 		puts_tr("dump - Display all SAs");
   3342 		puts_tr("");
   3343 		puts_tr("Optional arguments:");
   3344 		puts_tr("all        display all SAs");
   3345 		puts_tr("esp        display just ESP SAs");
   3346 		puts_tr("ah         display just AH SAs");
   3347 		puts_tr("<number>   display just SAs with type "
   3348 		    "given by number");
   3349 		puts_tr("");
   3350 		break;
   3351 	case CMD_MONITOR:
   3352 		puts_tr("monitor - Monitor all PF_KEY reply messages.");
   3353 		break;
   3354 	case CMD_PMONITOR:
   3355 		puts_tr(
   3356 "pmonitor, passive_monitor - Monitor PF_KEY messages that");
   3357 		puts_tr(
   3358 "                            reply to all PF_KEY sockets.");
   3359 		break;
   3360 
   3361 	case CMD_QUIT:
   3362 		puts_tr("quit, exit - Exit the program");
   3363 		break;
   3364 	case CMD_SAVE:
   3365 		puts_tr("save	    - Saves all SAs to a file");
   3366 		break;
   3367 	case CMD_HELP:
   3368 		puts_tr("help	    - Display list of commands");
   3369 		puts_tr("help <cmd> - Display help for command");
   3370 		puts_tr("help attr  - Display possible SA attributes");
   3371 		break;
   3372 	default:
   3373 		(void) printf(gettext("%s: Unknown command\n"), cmds);
   3374 		break;
   3375 	}
   3376 }
   3377 
   3378 
   3379 static void
   3380 dohelp(char *cmds)
   3381 {
   3382 	if (cmds != NULL) {
   3383 		dohelpcmd(cmds);
   3384 		return;
   3385 	}
   3386 	puts_tr("Commands");
   3387 	puts_tr("--------");
   3388 	puts_tr("?, help  - Display this list");
   3389 	puts_tr("help <cmd> - Display help for command");
   3390 	puts_tr("help attr  - Display possible SA attributes");
   3391 	puts_tr("quit, exit - Exit the program");
   3392 	puts_tr("monitor - Monitor all PF_KEY reply messages.");
   3393 	puts_tr("pmonitor, passive_monitor - Monitor PF_KEY messages that");
   3394 	puts_tr("                            reply to all PF_KEY sockets.");
   3395 	puts_tr("");
   3396 	puts_tr("The following commands are of the form:");
   3397 	puts_tr("    <command> {SA type} {attribute value}*");
   3398 	puts_tr("");
   3399 	puts_tr("add (interactive only) - Add a new security association (SA)");
   3400 	puts_tr("update (interactive only) - Update an existing SA");
   3401 	puts_tr("update-pair (interactive only) - Update an existing SA pair");
   3402 	puts_tr("delete - Delete an SA");
   3403 	puts_tr("delete-pair - Delete an SA pair");
   3404 	puts_tr("get - Display an SA");
   3405 	puts_tr("flush - Delete all SAs");
   3406 	puts_tr("dump - Display all SAs");
   3407 	puts_tr("save - Saves all SAs to a file");
   3408 }
   3409 
   3410 /*
   3411  * "Parse" a command line from argv.
   3412  */
   3413 static void
   3414 parseit(int argc, char *argv[], char *ebuf, boolean_t read_cmdfile)
   3415 {
   3416 	int cmd, satype;
   3417 	char *ep = NULL;
   3418 
   3419 	if (argc == 0)
   3420 		return;
   3421 	cmd = parsecmd(*argv++);
   3422 
   3423 	/*
   3424 	 * Some commands loop forever and should only be run from the command
   3425 	 * line, they should never be run from a command file as this may
   3426 	 * be used at boot time.
   3427 	 */
   3428 	switch (cmd) {
   3429 	case CMD_HELP:
   3430 		if (read_cmdfile)
   3431 			ERROR(ep, ebuf, gettext("Help not appropriate in "
   3432 			    "config file."));
   3433 		else
   3434 			dohelp(*argv);
   3435 		return;
   3436 	case CMD_MONITOR:
   3437 		if (read_cmdfile)
   3438 			ERROR(ep, ebuf, gettext("Monitor not appropriate in "
   3439 			    "config file."));
   3440 		else {
   3441 			domonitor(B_FALSE);
   3442 			/*
   3443 			 * Return from the function in interactive mode to
   3444 			 * avoid error message in the next switch statement.
   3445 			 * Also print newline to prevent prompt clobbering.
   3446 			 * The same is done for CMD_PMONITOR.
   3447 			 */
   3448 			if (interactive) {
   3449 				(void) printf("\n");
   3450 				return;
   3451 			}
   3452 		}
   3453 		break;
   3454 	case CMD_PMONITOR:
   3455 		if (read_cmdfile)
   3456 			ERROR(ep, ebuf, gettext("Monitor not appropriate in "
   3457 			    "config file."));
   3458 		else {
   3459 			domonitor(B_TRUE);
   3460 			if (interactive) {
   3461 				(void) printf("\n");
   3462 				return;
   3463 			}
   3464 		}
   3465 		break;
   3466 	case CMD_QUIT:
   3467 		EXIT_OK(NULL);
   3468 	}
   3469 
   3470 	handle_errors(ep, ebuf, B_FALSE, B_FALSE);
   3471 
   3472 	satype = parsesatype(*argv, ebuf);
   3473 
   3474 	if (satype != SADB_SATYPE_UNSPEC) {
   3475 		argv++;
   3476 	} else {
   3477 		/*
   3478 		 * You must specify either "all" or a specific SA type
   3479 		 * for the "save" command.
   3480 		 */
   3481 		if (cmd == CMD_SAVE)
   3482 			if (*argv == NULL) {
   3483 				FATAL(ep, ebuf, gettext(
   3484 				    "Must specify a specific "
   3485 				    "SA type for save.\n"));
   3486 			} else {
   3487 				argv++;
   3488 			}
   3489 	}
   3490 
   3491 	switch (cmd) {
   3492 	case CMD_FLUSH:
   3493 		if (argc > 2) {
   3494 			ERROR(ep, ebuf, gettext("Too many arguments for "
   3495 			    "flush command"));
   3496 			handle_errors(ep, ebuf,
   3497 			    interactive ? B_TRUE : B_FALSE, B_FALSE);
   3498 		}
   3499 		if (!cflag)
   3500 			doflush(satype);
   3501 		/*
   3502 		 * If this was called because of an entry in a cmd file
   3503 		 * then this action needs to be counted to prevent
   3504 		 * do_interactive() treating this as an error.
   3505 		 */
   3506 		lines_added++;
   3507 		break;
   3508 	case CMD_ADD:
   3509 	case CMD_UPDATE:
   3510 	case CMD_UPDATE_PAIR:
   3511 		/*
   3512 		 * NOTE: Shouldn't allow ADDs or UPDATEs with keying material
   3513 		 * from the command line.
   3514 		 */
   3515 		if (!interactive) {
   3516 			errx(1, gettext(
   3517 			    "can't do ADD or UPDATE from the command line.\n"));
   3518 		}
   3519 		if (satype == SADB_SATYPE_UNSPEC) {
   3520 			FATAL(ep, ebuf, gettext(
   3521 			    "Must specify a specific SA type."));
   3522 			/* NOTREACHED */
   3523 		}
   3524 		/* Parse for extensions, including keying material. */
   3525 		doaddup(cmd, satype, argv, ebuf);
   3526 		break;
   3527 	case CMD_DELETE:
   3528 	case CMD_DELETE_PAIR:
   3529 	case CMD_GET:
   3530 		if (satype == SADB_SATYPE_UNSPEC) {
   3531 			FATAL(ep, ebuf, gettext(
   3532 			    "Must specify a single SA type."));
   3533 			/* NOTREACHED */
   3534 		}
   3535 		/* Parse for bare minimum to locate an SA. */
   3536 		dodelget(cmd, satype, argv, ebuf);
   3537 		break;
   3538 	case CMD_DUMP:
   3539 		if (read_cmdfile)
   3540 			ERROR(ep, ebuf, gettext("Dump not appropriate in "
   3541 			    "config file."));
   3542 		else {
   3543 			if (argc > 2) {
   3544 				ERROR(ep, ebuf, gettext("Too many arguments "
   3545 				    "for dump command"));
   3546 				handle_errors(ep, ebuf,
   3547 				    interactive ? B_TRUE : B_FALSE, B_FALSE);
   3548 			}
   3549 			dodump(satype, NULL);
   3550 		}
   3551 		break;
   3552 	case CMD_SAVE:
   3553 		if (read_cmdfile) {
   3554 			ERROR(ep, ebuf, gettext("Save not appropriate in "
   3555 			    "config file."));
   3556 		} else {
   3557 			mask_signals(B_FALSE);	/* Mask signals */
   3558 			dodump(satype, opensavefile(argv[0]));
   3559 			mask_signals(B_TRUE);	/* Unmask signals */
   3560 		}
   3561 		break;
   3562 	default:
   3563 		warnx(gettext("Unknown command (%s).\n"),
   3564 		    *(argv - ((satype == SADB_SATYPE_UNSPEC) ? 1 : 2)));
   3565 		usage();
   3566 	}
   3567 	handle_errors(ep, ebuf, B_FALSE, B_FALSE);
   3568 }
   3569 
   3570 int
   3571 main(int argc, char *argv[])
   3572 {
   3573 	int ch;
   3574 	FILE *infile = stdin, *savefile;
   3575 	boolean_t dosave = B_FALSE, readfile = B_FALSE;
   3576 	char *configfile = NULL;
   3577 	struct stat sbuf;
   3578 	int bootflags;
   3579 
   3580 	(void) setlocale(LC_ALL, "");
   3581 #if !defined(TEXT_DOMAIN)
   3582 #define	TEXT_DOMAIN "SYS_TEST"
   3583 #endif
   3584 	(void) textdomain(TEXT_DOMAIN);
   3585 
   3586 	/*
   3587 	 * Check to see if the command is being run from smf(5).
   3588 	 */
   3589 	my_fmri = getenv("SMF_FMRI");
   3590 
   3591 	openlog("ipseckey", LOG_CONS, LOG_AUTH);
   3592 	if (getuid() != 0) {
   3593 		errx(1, "Insufficient privileges to run ipseckey.");
   3594 	}
   3595 
   3596 	/* umask me to paranoid, I only want to create files read-only */
   3597 	(void) umask((mode_t)00377);
   3598 
   3599 	while ((ch = getopt(argc, argv, "pnvf:s:c:")) != EOF)
   3600 		switch (ch) {
   3601 		case 'p':
   3602 			pflag = B_TRUE;
   3603 			break;
   3604 		case 'n':
   3605 			nflag = B_TRUE;
   3606 			break;
   3607 		case 'v':
   3608 			vflag = B_TRUE;
   3609 			break;
   3610 		case 'c':
   3611 			cflag = B_TRUE;
   3612 			/* FALLTHRU */
   3613 		case 'f':
   3614 			if (dosave)
   3615 				usage();
   3616 			infile = fopen(optarg, "r");
   3617 			if (infile == NULL) {
   3618 				EXIT_BADCONFIG2("Unable to open configuration "
   3619 				    "file: %s\n", optarg);
   3620 			}
   3621 			/*
   3622 			 * Check file permissions/ownership and warn or
   3623 			 * fail depending on state of SMF control.
   3624 			 */
   3625 			if (fstat(fileno(infile), &sbuf) == -1) {
   3626 				(void) fclose(infile);
   3627 				EXIT_BADCONFIG2("Unable to stat configuration "
   3628 				    "file: %s\n", optarg);
   3629 			}
   3630 			if (INSECURE_PERMS(sbuf)) {
   3631 				if (my_fmri != NULL) {
   3632 					(void) fclose(infile);
   3633 					EXIT_BADCONFIG2("Config file "
   3634 					    "%s has insecure permissions.",
   3635 					    optarg);
   3636 				} else 	{
   3637 					(void) fprintf(stderr, "%s %s\n",
   3638 					    optarg, gettext(
   3639 					    "has insecure permissions, will be "
   3640 					    "rejected in permanent config."));
   3641 				}
   3642 			}
   3643 			configfile = strdup(optarg);
   3644 			readfile = B_TRUE;
   3645 			break;
   3646 		case 's':
   3647 			if (readfile)
   3648 				usage();
   3649 			dosave = B_TRUE;
   3650 			savefile = opensavefile(optarg);
   3651 			break;
   3652 		default:
   3653 			usage();
   3654 		}
   3655 
   3656 	argc -= optind;
   3657 	argv += optind;
   3658 
   3659 	mypid = getpid();
   3660 
   3661 	keysock = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
   3662 
   3663 	if (keysock == -1) {
   3664 		if (errno == EPERM) {
   3665 			EXIT_BADPERM("Insufficient privileges to open "
   3666 			    "PF_KEY socket.\n");
   3667 		} else {
   3668 			/* some other reason */
   3669 			EXIT_FATAL("Opening PF_KEY socket");
   3670 		}
   3671 	}
   3672 
   3673 	if ((_cladm(CL_INITIALIZE, CL_GET_BOOTFLAG, &bootflags) != 0) ||
   3674 	    (bootflags & CLUSTER_BOOTED)) {
   3675 		in_cluster_mode = B_TRUE;
   3676 		cluster_socket = socket(AF_INET, SOCK_DGRAM, 0);
   3677 		cli_addr.sin_family = AF_INET;
   3678 		cli_addr.sin_addr.s_addr = INADDR_LOOPBACK;
   3679 		cli_addr.sin_port = htons(CLUSTER_UDP_PORT);
   3680 	}
   3681 
   3682 	if (dosave) {
   3683 		mask_signals(B_FALSE);	/* Mask signals */
   3684 		dodump(SADB_SATYPE_UNSPEC, savefile);
   3685 		mask_signals(B_TRUE);	/* Unmask signals */
   3686 		EXIT_OK(NULL);
   3687 	}
   3688 
   3689 	/*
   3690 	 * When run from smf(5) flush any existing SA's first
   3691 	 * otherwise you will end up in maintenance mode.
   3692 	 */
   3693 	if ((my_fmri != NULL) && readfile) {
   3694 		(void) fprintf(stdout, gettext(
   3695 		    "Flushing existing SA's before adding new SA's\n"));
   3696 		(void) fflush(stdout);
   3697 		doflush(SADB_SATYPE_UNSPEC);
   3698 	}
   3699 	if (infile != stdin || argc == 0) {
   3700 		/* Go into interactive mode here. */
   3701 		do_interactive(infile, configfile, "ipseckey> ", my_fmri,
   3702 		    parseit, no_match);
   3703 	}
   3704 	parseit(argc, argv, NULL, B_FALSE);
   3705 
   3706 	return (0);
   3707 }
   3708