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