xref: /onnv-gate/usr/src/cmd/dcs/sparc/sun4u/rdr_messages.c (revision 1120:f038ea42ae91)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*1120Smb158278  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * WARNING: The contents of this file are shared by all projects
310Sstevel@tonic-gate  * that  wish to  perform  remote  Dynamic Reconfiguration  (DR)
320Sstevel@tonic-gate  * operations. Copies of this file can be found in the following
330Sstevel@tonic-gate  * locations:
340Sstevel@tonic-gate  *
350Sstevel@tonic-gate  *	Project	    Location
360Sstevel@tonic-gate  *	-------	    --------
370Sstevel@tonic-gate  *	Solaris	    usr/src/cmd/dcs/sparc/sun4u/%M%
380Sstevel@tonic-gate  *	SMS	    src/sms/lib/librdr/%M%
390Sstevel@tonic-gate  *
400Sstevel@tonic-gate  * In order for proper communication to occur,  the files in the
410Sstevel@tonic-gate  * above locations must match exactly. Any changes that are made
420Sstevel@tonic-gate  * to this file should  be made to all of the files in the list.
430Sstevel@tonic-gate  */
440Sstevel@tonic-gate 
450Sstevel@tonic-gate /*
460Sstevel@tonic-gate  * This file is a module that contains an interface for performing
470Sstevel@tonic-gate  * remote Dynamic Reconfiguration (DR) operations. It hides all
480Sstevel@tonic-gate  * network operations such as establishing a connection, sending
490Sstevel@tonic-gate  * and receiving messages, and closing a connection. It also handles
500Sstevel@tonic-gate  * the packing and unpacking of messages for network transport.
510Sstevel@tonic-gate  */
520Sstevel@tonic-gate 
530Sstevel@tonic-gate #include <stdio.h>
540Sstevel@tonic-gate #include <stdlib.h>
550Sstevel@tonic-gate #include <unistd.h>
560Sstevel@tonic-gate #include <string.h>
570Sstevel@tonic-gate #include <fcntl.h>
580Sstevel@tonic-gate #include <errno.h>
590Sstevel@tonic-gate #include <netdb.h>
600Sstevel@tonic-gate #include <sys/socket.h>
610Sstevel@tonic-gate #include <netinet/tcp.h>
620Sstevel@tonic-gate 
630Sstevel@tonic-gate #include "remote_cfg.h"
640Sstevel@tonic-gate #include "rdr_param_types.h"
650Sstevel@tonic-gate #include "rdr_messages.h"
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 
680Sstevel@tonic-gate /*
690Sstevel@tonic-gate  * Structure holding information about
700Sstevel@tonic-gate  * all possible variable length fields
710Sstevel@tonic-gate  * that can be present in an RDR message.
720Sstevel@tonic-gate  */
730Sstevel@tonic-gate typedef struct {
740Sstevel@tonic-gate 	int	ap_id_int_size;
750Sstevel@tonic-gate 	int	ap_id_char_size;
760Sstevel@tonic-gate 	int	*ap_id_sizes;
770Sstevel@tonic-gate 	char	*ap_id_chars;
780Sstevel@tonic-gate 	int	errstring_strlen;
790Sstevel@tonic-gate 	int	errstring_pad_sz;
800Sstevel@tonic-gate 	int	options_strlen;
810Sstevel@tonic-gate 	int	options_pad_sz;
820Sstevel@tonic-gate 	int	listopts_strlen;
830Sstevel@tonic-gate 	int	listopts_pad_sz;
840Sstevel@tonic-gate 	int	function_strlen;
850Sstevel@tonic-gate 	int	function_pad_sz;
860Sstevel@tonic-gate } rdr_variable_message_info_t;
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 
890Sstevel@tonic-gate /*
900Sstevel@tonic-gate  * A table of maximum sizes for each message type. Message size is
910Sstevel@tonic-gate  * validated when the message header is first received. This prevents
920Sstevel@tonic-gate  * a situation where a corrupted or bad header can cause too much
930Sstevel@tonic-gate  * memory to be allocated.
940Sstevel@tonic-gate  *
950Sstevel@tonic-gate  * The message size limits were chosen to be a very generous upper bound
960Sstevel@tonic-gate  * on the amount of data each message can send. They are not intended to
970Sstevel@tonic-gate  * be a precise measurement of the data size.
980Sstevel@tonic-gate  */
990Sstevel@tonic-gate #define	NOMSG		0
1000Sstevel@tonic-gate #define	SHORTMSG	(150 * 1024)		/* 150 KB */
1010Sstevel@tonic-gate #define	LONGMSG		(3 * 1024 * 1024)	/* 3 MB */
1020Sstevel@tonic-gate 
1030Sstevel@tonic-gate struct {
1040Sstevel@tonic-gate 	ulong_t	req_max;
1050Sstevel@tonic-gate 	ulong_t	reply_max;
1060Sstevel@tonic-gate } msg_sizes[] = {
1070Sstevel@tonic-gate 	/*
1080Sstevel@tonic-gate 	 * request	reply
1090Sstevel@tonic-gate 	 * -------	-----
1100Sstevel@tonic-gate 	 */
1110Sstevel@tonic-gate 	{  NOMSG,	NOMSG	  },	/*  Invalid Opcode		*/
1120Sstevel@tonic-gate 	{  SHORTMSG,	SHORTMSG  },	/*  RDR_SES_REQ			*/
1130Sstevel@tonic-gate 	{  NOMSG,	NOMSG	  },	/*  RDR_SES_ESTBL		*/
1140Sstevel@tonic-gate 	{  NOMSG,	NOMSG	  },	/*  RDR_SES_END			*/
1150Sstevel@tonic-gate 	{  SHORTMSG,	SHORTMSG  },	/*  RDR_CONF_CHANGE_STATE	*/
1160Sstevel@tonic-gate 	{  SHORTMSG,	SHORTMSG  },	/*  RDR_CONF_PRIVATE_FUNC	*/
1170Sstevel@tonic-gate 	{  SHORTMSG,	SHORTMSG  },	/*  RDR_CONF_TEST		*/
1180Sstevel@tonic-gate 	{  SHORTMSG,	LONGMSG	  },	/*  RDR_CONF_LIST_EXT		*/
1190Sstevel@tonic-gate 	{  SHORTMSG,	NOMSG	  },	/*  RDR_CONF_HELP		*/
1200Sstevel@tonic-gate 	{  SHORTMSG,	NOMSG	  },	/*  RDR_CONF_AP_ID_CMP		*/
1210Sstevel@tonic-gate 	{  SHORTMSG,	NOMSG	  },	/*  RDR_CONF_ABORT_CMD		*/
1220Sstevel@tonic-gate 	{  SHORTMSG,	SHORTMSG  },	/*  RDR_CONF_CONFIRM_CALLBACK 	*/
1230Sstevel@tonic-gate 	{  SHORTMSG,	NOMSG	  },	/*  RDR_CONF_MSG_CALLBACK	*/
1240Sstevel@tonic-gate 	{  SHORTMSG,	LONGMSG	  }	/*  RDR_RSRC_INFO		*/
1250Sstevel@tonic-gate };
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate #define	RDR_BAD_FD		(-1)
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate #define	RDR_MSG_HDR_SIZE 	sizeof (rdr_msg_hdr_t)
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate static const int RDR_ALIGN_64_BIT = 8;   /* 8 bytes */
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate /*
1360Sstevel@tonic-gate  * Static Function Declarations
1370Sstevel@tonic-gate  */
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate /*
1400Sstevel@tonic-gate  * Socket Related Routines
1410Sstevel@tonic-gate  */
1420Sstevel@tonic-gate static int rdr_setopt(int fd, int name, int level);
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate static int rdr_bind(int fd, struct sockaddr *addr);
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate static int rdr_snd(int fd, rdr_msg_hdr_t *hdr, char *data, int data_sz,
1470Sstevel@tonic-gate 			int timeout);
1480Sstevel@tonic-gate static int rdr_snd_raw(int fd, char *msg, int data_sz, int timeout);
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate static int rdr_rcv(int fd, rdr_msg_hdr_t *hdr, char **data, int timeout);
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate static int rdr_rcv_raw(int fd, char *msg, int data_size, int timeout);
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate /*
1560Sstevel@tonic-gate  * Data Validation Routines
1570Sstevel@tonic-gate  */
1580Sstevel@tonic-gate static int validate_header(rdr_msg_hdr_t *hdr);
1590Sstevel@tonic-gate 
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate /*
1620Sstevel@tonic-gate  * Session Request Routines
1630Sstevel@tonic-gate  */
1640Sstevel@tonic-gate static int pack_ses_req_request(ses_req_params_t *params, char **buf,
1650Sstevel@tonic-gate 			int *buf_size);
1660Sstevel@tonic-gate static int unpack_ses_req_request(ses_req_params_t *params, const char *buf);
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate static int pack_ses_req_reply(ses_req_params_t *params, char **buf,
1690Sstevel@tonic-gate 			int *buf_size);
1700Sstevel@tonic-gate static int unpack_ses_req_reply(ses_req_params_t *params, const char *buf);
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate /*
1740Sstevel@tonic-gate  * Change State Routines
1750Sstevel@tonic-gate  */
1760Sstevel@tonic-gate static int pack_change_state_request(change_state_params_t *params,
1770Sstevel@tonic-gate 			char **buf, int *buf_size);
1780Sstevel@tonic-gate static int unpack_change_state_request(change_state_params_t *params,
1790Sstevel@tonic-gate 			const char *buf);
1800Sstevel@tonic-gate static int pack_change_state_reply(change_state_params_t *params,
1810Sstevel@tonic-gate 			char **buf, int *buf_size);
1820Sstevel@tonic-gate static int unpack_change_state_reply(change_state_params_t *params,
1830Sstevel@tonic-gate 			const char *buf);
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate /*
1860Sstevel@tonic-gate  * Private Func Routines
1870Sstevel@tonic-gate  */
1880Sstevel@tonic-gate static int pack_private_func_request(private_func_params_t *params,
1890Sstevel@tonic-gate 			char **buf, int *buf_size);
1900Sstevel@tonic-gate static int unpack_private_func_request(private_func_params_t *params,
1910Sstevel@tonic-gate 			const char *buf);
1920Sstevel@tonic-gate static int pack_private_func_reply(private_func_params_t *params,
1930Sstevel@tonic-gate 			char **buf, int *buf_size);
1940Sstevel@tonic-gate static int unpack_private_func_reply(private_func_params_t *params,
1950Sstevel@tonic-gate 			const char *buf);
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate /*
1980Sstevel@tonic-gate  * Test Routines
1990Sstevel@tonic-gate  */
2000Sstevel@tonic-gate static int pack_test_request(test_params_t *params, char **buf, int *buf_size);
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate static int unpack_test_request(test_params_t *params, const char *buf);
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate static int pack_test_reply(test_params_t *params, char **buf, int *buf_size);
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate static int unpack_test_reply(test_params_t *params, const char *buf);
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate /*
2100Sstevel@tonic-gate  * List Ext Routines
2110Sstevel@tonic-gate  */
2120Sstevel@tonic-gate static int pack_list_ext_request(list_ext_params_t *params, char **buf,
2130Sstevel@tonic-gate 			int *buf_size);
2140Sstevel@tonic-gate static int unpack_list_ext_request(list_ext_params_t *params, const char *buf);
2150Sstevel@tonic-gate 
2160Sstevel@tonic-gate static int pack_list_ext_reply(list_ext_params_t *params, char **buf,
2170Sstevel@tonic-gate 			int *buf_size);
2180Sstevel@tonic-gate static int unpack_list_ext_reply(list_ext_params_t *params, const char *buf);
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate /*
2220Sstevel@tonic-gate  * Help Routines
2230Sstevel@tonic-gate  */
2240Sstevel@tonic-gate static int pack_help_request(help_params_t *params, char **buf, int *buf_size);
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate static int unpack_help_request(help_params_t *params, const char *buf);
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate /*
2300Sstevel@tonic-gate  * Ap Id Cmp Routines
2310Sstevel@tonic-gate  */
2320Sstevel@tonic-gate static int pack_ap_id_cmp_request(ap_id_cmp_params_t *params, char **buf,
2330Sstevel@tonic-gate 			int *buf_size);
2340Sstevel@tonic-gate static int unpack_ap_id_cmp_request(ap_id_cmp_params_t *params,
2350Sstevel@tonic-gate 			const char *buf);
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate /*
2380Sstevel@tonic-gate  * Abort Routines
2390Sstevel@tonic-gate  */
2400Sstevel@tonic-gate static int pack_abort_cmd_request(abort_cmd_params_t *params, char **buf,
2410Sstevel@tonic-gate 			int *buf_size);
2420Sstevel@tonic-gate static int unpack_abort_cmd_request(abort_cmd_params_t *params,
2430Sstevel@tonic-gate 			const char *buf);
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate /*
2460Sstevel@tonic-gate  * Confirm Callback Routines
2470Sstevel@tonic-gate  */
2480Sstevel@tonic-gate static int pack_confirm_request(confirm_callback_params_t *params, char **buf,
2490Sstevel@tonic-gate 			int *buf_size);
2500Sstevel@tonic-gate static int unpack_confirm_request(confirm_callback_params_t *params,
2510Sstevel@tonic-gate 			const char *buf);
2520Sstevel@tonic-gate static int pack_confirm_reply(confirm_callback_params_t *params,
2530Sstevel@tonic-gate 			char **buf, int *buf_size);
2540Sstevel@tonic-gate static int unpack_confirm_reply(confirm_callback_params_t *params,
2550Sstevel@tonic-gate 			const char *buf);
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate /*
2580Sstevel@tonic-gate  * Message Callback Routines
2590Sstevel@tonic-gate  */
2600Sstevel@tonic-gate static int pack_message_request(msg_callback_params_t *params, char **buf,
2610Sstevel@tonic-gate 			int *buf_size);
2620Sstevel@tonic-gate static int unpack_message_request(msg_callback_params_t *params,
2630Sstevel@tonic-gate 			const char *buf);
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate /*
2660Sstevel@tonic-gate  * Resource Info Routines
2670Sstevel@tonic-gate  */
2680Sstevel@tonic-gate static int pack_rsrc_info_request(rsrc_info_params_t *params, char **buf,
2690Sstevel@tonic-gate 			int *buf_size);
2700Sstevel@tonic-gate static int unpack_rsrc_info_request(rsrc_info_params_t *params,
2710Sstevel@tonic-gate 			const char *buf);
2720Sstevel@tonic-gate static int pack_rsrc_info_reply(rsrc_info_params_t *params, char **buf,
2730Sstevel@tonic-gate 			int *buf_size);
2740Sstevel@tonic-gate static int unpack_rsrc_info_reply(rsrc_info_params_t *params, const char *buf);
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate /*
2770Sstevel@tonic-gate  * General Pack/Unpack Routines
2780Sstevel@tonic-gate  */
2790Sstevel@tonic-gate static int pack_ap_ids(int num_ap_ids, char *const *ap_ids,
2800Sstevel@tonic-gate 			rdr_variable_message_info_t *var_msg_info);
2810Sstevel@tonic-gate static int unpack_ap_ids(int num_ap_ids, char **ap_ids, const char *buf,
2820Sstevel@tonic-gate 			rdr_variable_message_info_t *var_msg_info);
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate /*
2850Sstevel@tonic-gate  * Find Variable Info Sizes
2860Sstevel@tonic-gate  */
2870Sstevel@tonic-gate static int find_options_sizes(char *options,
2880Sstevel@tonic-gate 			rdr_variable_message_info_t *var_msg_info);
2890Sstevel@tonic-gate static int find_listopts_sizes(char *listopts,
2900Sstevel@tonic-gate 			rdr_variable_message_info_t *var_msg_info);
2910Sstevel@tonic-gate static int find_function_sizes(char *function,
2920Sstevel@tonic-gate 			rdr_variable_message_info_t *var_msg_info);
2930Sstevel@tonic-gate static int find_errstring_sizes(char **errstring,
2940Sstevel@tonic-gate 			rdr_variable_message_info_t *var_msg_info);
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate /*
2970Sstevel@tonic-gate  * Extract Info From Buffers
2980Sstevel@tonic-gate  */
2990Sstevel@tonic-gate static int get_ap_ids_from_buf(char ***ap_id_ptr, int num_ap_ids,
3000Sstevel@tonic-gate 			rdr_variable_message_info_t *var_msg_info,
3010Sstevel@tonic-gate 			const char *buf);
3020Sstevel@tonic-gate static int get_string_from_buf(char **stringptr, int strsize, const char *buf);
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate /*
3060Sstevel@tonic-gate  * Cleanup Routines
3070Sstevel@tonic-gate  */
3080Sstevel@tonic-gate static int cleanup_ap_ids(int num_ap_ids, char **ap_ids);
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate static int cleanup_errstring(char **errstring);
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate static void cleanup_variable_ap_id_info(
3130Sstevel@tonic-gate 			rdr_variable_message_info_t *var_msg_info);
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate /*
3160Sstevel@tonic-gate  * Public Functions
3170Sstevel@tonic-gate  */
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate /*
3210Sstevel@tonic-gate  * rdr_open:
3220Sstevel@tonic-gate  *
3230Sstevel@tonic-gate  * Establish a transport endpoint to prepare for a new
3240Sstevel@tonic-gate  * connection. Returns a file descriptor representing the
3250Sstevel@tonic-gate  * new transport if successful or RDR_BAD_FD upon failure.
3260Sstevel@tonic-gate  */
3270Sstevel@tonic-gate int
3280Sstevel@tonic-gate rdr_open(int family)
3290Sstevel@tonic-gate {
3300Sstevel@tonic-gate 	int	newfd;
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	if ((newfd = socket(family, SOCK_STREAM, 0)) == NULL) {
3340Sstevel@tonic-gate 		return (RDR_BAD_FD);
3350Sstevel@tonic-gate 	}
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	return (newfd);
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate /*
3420Sstevel@tonic-gate  * rdr_init:
3430Sstevel@tonic-gate  *
3440Sstevel@tonic-gate  * Initialize a transport endpoint. This involves binding to
3450Sstevel@tonic-gate  * a particular port and setting any user specified socket
3460Sstevel@tonic-gate  * options.
3470Sstevel@tonic-gate  */
3480Sstevel@tonic-gate int
3490Sstevel@tonic-gate rdr_init(int fd, struct sockaddr *addr, int *opts, int num_opts, int blog)
3500Sstevel@tonic-gate {
3510Sstevel@tonic-gate 	int	i;
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate 
3540Sstevel@tonic-gate 	/* sanity checks */
3550Sstevel@tonic-gate 	if ((fd < 0) || (addr == NULL)) {
3560Sstevel@tonic-gate 		return (RDR_ERROR);
3570Sstevel@tonic-gate 	}
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate 	if ((opts == NULL) || (num_opts < 0)) {
3600Sstevel@tonic-gate 		num_opts = 0;
3610Sstevel@tonic-gate 	}
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 	/* bind the address, if is not already bound */
3640Sstevel@tonic-gate 	if (rdr_bind(fd, addr) != RDR_OK) {
3650Sstevel@tonic-gate 		return (RDR_NET_ERR);
3660Sstevel@tonic-gate 	}
3670Sstevel@tonic-gate 
3680Sstevel@tonic-gate 	/*
3690Sstevel@tonic-gate 	 * Set TCP_NODELAY for this endpoint. This disables Nagle's
3700Sstevel@tonic-gate 	 * algorithm that can cause a delay in sending small sized
3710Sstevel@tonic-gate 	 * messages. Since most of the RDR messages are small, this
3720Sstevel@tonic-gate 	 * is a restriction that negatively impacts performance.
3730Sstevel@tonic-gate 	 */
3740Sstevel@tonic-gate 	if (rdr_setopt(fd, TCP_NODELAY, IPPROTO_TCP) != RDR_OK) {
3750Sstevel@tonic-gate 		return (RDR_NET_ERR);
3760Sstevel@tonic-gate 	}
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	/* set the user specified socket options */
3790Sstevel@tonic-gate 	for (i = 0; i < num_opts; i++) {
3800Sstevel@tonic-gate 		if (rdr_setopt(fd, opts[i], SOL_SOCKET) != RDR_OK) {
3810Sstevel@tonic-gate 			return (RDR_NET_ERR);
3820Sstevel@tonic-gate 		}
3830Sstevel@tonic-gate 	}
3840Sstevel@tonic-gate 
3850Sstevel@tonic-gate 	/*
3860Sstevel@tonic-gate 	 * If blog is not zero, it is a server that is being
3870Sstevel@tonic-gate 	 * initialized. In order for it to be able to accept
3880Sstevel@tonic-gate 	 * connections, we have to set the size of the incoming
3890Sstevel@tonic-gate 	 * connection queue.
3900Sstevel@tonic-gate 	 */
3910Sstevel@tonic-gate 	if (blog != 0) {
3920Sstevel@tonic-gate 		if (listen(fd, blog) == -1) {
3930Sstevel@tonic-gate 			return (RDR_NET_ERR);
3940Sstevel@tonic-gate 		}
3950Sstevel@tonic-gate 	}
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	return (RDR_OK);
3980Sstevel@tonic-gate }
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate /*
4020Sstevel@tonic-gate  * rdr_connect_clnt:
4030Sstevel@tonic-gate  *
4040Sstevel@tonic-gate  * Perform the necessary steps for a client to connect to
4050Sstevel@tonic-gate  * a server process. The required information is the file
4060Sstevel@tonic-gate  * descriptor for the transport endpoint, and the remote
4070Sstevel@tonic-gate  * address.
4080Sstevel@tonic-gate  */
4090Sstevel@tonic-gate int
4100Sstevel@tonic-gate rdr_connect_clnt(int fd, struct sockaddr *addr)
4110Sstevel@tonic-gate {
4120Sstevel@tonic-gate 	unsigned int	addr_len;
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 
4150Sstevel@tonic-gate 	/* sanity check */
4160Sstevel@tonic-gate 	if (addr == NULL) {
4170Sstevel@tonic-gate 		return (RDR_ERROR);
4180Sstevel@tonic-gate 	}
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	/* initialize the address length */
4210Sstevel@tonic-gate 	switch (addr->sa_family) {
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	case AF_INET:
4240Sstevel@tonic-gate 		addr_len = sizeof (struct sockaddr_in);
4250Sstevel@tonic-gate 		break;
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate 	case AF_INET6:
4280Sstevel@tonic-gate 		addr_len = sizeof (struct sockaddr_in6);
4290Sstevel@tonic-gate 		break;
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 	default:
4320Sstevel@tonic-gate 		return (RDR_ERROR);
4330Sstevel@tonic-gate 	}
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 	/* attempt the connection */
4360Sstevel@tonic-gate 	if (connect(fd, addr, addr_len) == -1) {
4370Sstevel@tonic-gate 		return (RDR_NET_ERR);
4380Sstevel@tonic-gate 	}
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	return (RDR_OK);
4410Sstevel@tonic-gate }
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate /*
4450Sstevel@tonic-gate  * rdr_connect_srv:
4460Sstevel@tonic-gate  *
4470Sstevel@tonic-gate  * Perform the necessary steps for a server to connect to a
4480Sstevel@tonic-gate  * pending client request. The new connection is allocated a
4490Sstevel@tonic-gate  * new file descriptor, separate from the one used to accept
4500Sstevel@tonic-gate  * the connection.
4510Sstevel@tonic-gate  */
4520Sstevel@tonic-gate int
4530Sstevel@tonic-gate rdr_connect_srv(int fd)
4540Sstevel@tonic-gate {
4550Sstevel@tonic-gate 	int			newfd;
4560Sstevel@tonic-gate 	unsigned int		faddr_len;
4570Sstevel@tonic-gate 	struct sockaddr_storage	faddr;
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	faddr_len = sizeof (faddr);
4610Sstevel@tonic-gate 	if ((newfd = accept(fd, (struct sockaddr *)&faddr, &faddr_len)) == -1) {
4620Sstevel@tonic-gate 		return (RDR_BAD_FD);
4630Sstevel@tonic-gate 	}
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	return (newfd);
4660Sstevel@tonic-gate }
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate 
4690Sstevel@tonic-gate /*
4700Sstevel@tonic-gate  * rdr_reject:
4710Sstevel@tonic-gate  *
4720Sstevel@tonic-gate  * Reject an incoming connection attempt. This requires
4730Sstevel@tonic-gate  * that the connection be accepted first.
4740Sstevel@tonic-gate  */
4750Sstevel@tonic-gate int
4760Sstevel@tonic-gate rdr_reject(int fd)
4770Sstevel@tonic-gate {
4780Sstevel@tonic-gate 	unsigned int		faddr_len;
4790Sstevel@tonic-gate 	struct sockaddr_storage	faddr;
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	/* first accept the connection */
4830Sstevel@tonic-gate 	faddr_len = sizeof (faddr);
4840Sstevel@tonic-gate 	if (accept(fd, (struct sockaddr *)&faddr, &faddr_len) == -1) {
4850Sstevel@tonic-gate 		return (RDR_NET_ERR);
4860Sstevel@tonic-gate 	}
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 	/* then close it */
4890Sstevel@tonic-gate 	close(fd);
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	return (RDR_OK);
4920Sstevel@tonic-gate }
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate /*
4960Sstevel@tonic-gate  * rdr_close:
4970Sstevel@tonic-gate  *
4980Sstevel@tonic-gate  * Close down an given connection.
4990Sstevel@tonic-gate  */
5000Sstevel@tonic-gate int
5010Sstevel@tonic-gate rdr_close(int fd)
5020Sstevel@tonic-gate {
5030Sstevel@tonic-gate 	close(fd);
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate 	return (RDR_OK);
5060Sstevel@tonic-gate }
5070Sstevel@tonic-gate 
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate /*
5100Sstevel@tonic-gate  * rdr_snd_msg:
5110Sstevel@tonic-gate  *
5120Sstevel@tonic-gate  * Public interface for sending an RDR message. The data
5130Sstevel@tonic-gate  * passed in through hdr and param are packed for network
5140Sstevel@tonic-gate  * transport and sent.
5150Sstevel@tonic-gate  */
5160Sstevel@tonic-gate int
5170Sstevel@tonic-gate rdr_snd_msg(int fd, rdr_msg_hdr_t *hdr, cfga_params_t *param, int timeout)
5180Sstevel@tonic-gate {
5190Sstevel@tonic-gate 	int	err;
5200Sstevel@tonic-gate 	char	*pack_buf = NULL;
5210Sstevel@tonic-gate 	int	pack_buf_sz = 0;
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 
5240Sstevel@tonic-gate 	/* sanity checks */
5250Sstevel@tonic-gate 	if ((hdr == NULL) || (param == NULL)) {
5260Sstevel@tonic-gate 		return (RDR_ERROR);
5270Sstevel@tonic-gate 	}
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 	/*
5300Sstevel@tonic-gate 	 * Pack the message for transport
5310Sstevel@tonic-gate 	 */
5320Sstevel@tonic-gate 	switch (hdr->message_opcode) {
5330Sstevel@tonic-gate 
5340Sstevel@tonic-gate 		case RDR_SES_REQ: {
5350Sstevel@tonic-gate 
5360Sstevel@tonic-gate 			ses_req_params_t *rparam;
5370Sstevel@tonic-gate 			rparam = (ses_req_params_t *)param;
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
5400Sstevel@tonic-gate 				err = pack_ses_req_request(rparam,
5410Sstevel@tonic-gate 				    &pack_buf, &pack_buf_sz);
5420Sstevel@tonic-gate 			} else {
5430Sstevel@tonic-gate 				err = pack_ses_req_reply(rparam,
5440Sstevel@tonic-gate 				    &pack_buf, &pack_buf_sz);
5450Sstevel@tonic-gate 			}
5460Sstevel@tonic-gate 
5470Sstevel@tonic-gate 			break;
5480Sstevel@tonic-gate 		}
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 		case RDR_SES_ESTBL:
5510Sstevel@tonic-gate 		case RDR_SES_END:
5520Sstevel@tonic-gate 
5530Sstevel@tonic-gate 			/*
5540Sstevel@tonic-gate 			 * This is not an error condition because
5550Sstevel@tonic-gate 			 * there is no extra information to pack.
5560Sstevel@tonic-gate 			 */
5570Sstevel@tonic-gate 			err = RDR_OK;
5580Sstevel@tonic-gate 			break;
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 		case RDR_CONF_CHANGE_STATE: {
5610Sstevel@tonic-gate 
5620Sstevel@tonic-gate 			change_state_params_t *cparam;
5630Sstevel@tonic-gate 			cparam = (change_state_params_t *)param;
5640Sstevel@tonic-gate 
5650Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
5660Sstevel@tonic-gate 				err = pack_change_state_request(cparam,
5670Sstevel@tonic-gate 				    &pack_buf, &pack_buf_sz);
5680Sstevel@tonic-gate 			} else {
5690Sstevel@tonic-gate 				err = pack_change_state_reply(cparam,
5700Sstevel@tonic-gate 				    &pack_buf, &pack_buf_sz);
5710Sstevel@tonic-gate 			}
5720Sstevel@tonic-gate 			break;
5730Sstevel@tonic-gate 		}
5740Sstevel@tonic-gate 
5750Sstevel@tonic-gate 		case RDR_CONF_PRIVATE_FUNC: {
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 			private_func_params_t *pparam;
5780Sstevel@tonic-gate 			pparam = (private_func_params_t *)param;
5790Sstevel@tonic-gate 
5800Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
5810Sstevel@tonic-gate 				err = pack_private_func_request(pparam,
5820Sstevel@tonic-gate 				    &pack_buf, &pack_buf_sz);
5830Sstevel@tonic-gate 			} else {
5840Sstevel@tonic-gate 				err = pack_private_func_reply(pparam,
5850Sstevel@tonic-gate 				    &pack_buf, &pack_buf_sz);
5860Sstevel@tonic-gate 			}
5870Sstevel@tonic-gate 			break;
5880Sstevel@tonic-gate 		}
5890Sstevel@tonic-gate 
5900Sstevel@tonic-gate 		case RDR_CONF_TEST: {
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate 			test_params_t *tparam;
5930Sstevel@tonic-gate 			tparam = (test_params_t *)param;
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
5960Sstevel@tonic-gate 				err = pack_test_request(tparam,
5970Sstevel@tonic-gate 				    &pack_buf, &pack_buf_sz);
5980Sstevel@tonic-gate 			} else {
5990Sstevel@tonic-gate 				err = pack_test_reply(tparam,
6000Sstevel@tonic-gate 				    &pack_buf, &pack_buf_sz);
6010Sstevel@tonic-gate 			}
6020Sstevel@tonic-gate 			break;
6030Sstevel@tonic-gate 		}
6040Sstevel@tonic-gate 
6050Sstevel@tonic-gate 		case RDR_CONF_LIST_EXT: {
6060Sstevel@tonic-gate 
6070Sstevel@tonic-gate 			list_ext_params_t *lparam;
6080Sstevel@tonic-gate 			lparam = (list_ext_params_t *)param;
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
6110Sstevel@tonic-gate 				err = pack_list_ext_request(lparam, &pack_buf,
6120Sstevel@tonic-gate 				    &pack_buf_sz);
6130Sstevel@tonic-gate 			} else {
6140Sstevel@tonic-gate 				err = pack_list_ext_reply(lparam, &pack_buf,
6150Sstevel@tonic-gate 				    &pack_buf_sz);
6160Sstevel@tonic-gate 			}
6170Sstevel@tonic-gate 			break;
6180Sstevel@tonic-gate 		}
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 		case RDR_CONF_HELP: {
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 			help_params_t *hparam;
6230Sstevel@tonic-gate 			hparam = (help_params_t *)param;
6240Sstevel@tonic-gate 
6250Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
6260Sstevel@tonic-gate 				err = pack_help_request(hparam,
6270Sstevel@tonic-gate 				    &pack_buf, &pack_buf_sz);
6280Sstevel@tonic-gate 			} else {
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate 				/*
6310Sstevel@tonic-gate 				 * This is not an error because help
6320Sstevel@tonic-gate 				 * reply does not have any extra information
6330Sstevel@tonic-gate 				 * to pack.
6340Sstevel@tonic-gate 				 */
6350Sstevel@tonic-gate 				err = RDR_OK;
6360Sstevel@tonic-gate 			}
6370Sstevel@tonic-gate 			break;
6380Sstevel@tonic-gate 		}
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 		case RDR_CONF_AP_ID_CMP: {
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 			ap_id_cmp_params_t *aparam;
6430Sstevel@tonic-gate 			aparam = (ap_id_cmp_params_t *)param;
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
6460Sstevel@tonic-gate 				err = pack_ap_id_cmp_request(aparam,
6470Sstevel@tonic-gate 				    &pack_buf, &pack_buf_sz);
6480Sstevel@tonic-gate 			} else {
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 				/*
6510Sstevel@tonic-gate 				 * This is not an error because ap_id_cmp
6520Sstevel@tonic-gate 				 * reply does not have any extra information
6530Sstevel@tonic-gate 				 * to pack.
6540Sstevel@tonic-gate 				 */
6550Sstevel@tonic-gate 				err = RDR_OK;
6560Sstevel@tonic-gate 			}
6570Sstevel@tonic-gate 			break;
6580Sstevel@tonic-gate 		}
6590Sstevel@tonic-gate 
6600Sstevel@tonic-gate 		case RDR_CONF_ABORT_CMD: {
6610Sstevel@tonic-gate 
6620Sstevel@tonic-gate 			abort_cmd_params_t *aparam;
6630Sstevel@tonic-gate 			aparam = (abort_cmd_params_t *)param;
6640Sstevel@tonic-gate 
6650Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
6660Sstevel@tonic-gate 				err = pack_abort_cmd_request(aparam,
6670Sstevel@tonic-gate 				    &pack_buf, &pack_buf_sz);
6680Sstevel@tonic-gate 			} else {
6690Sstevel@tonic-gate 				/*
6700Sstevel@tonic-gate 				 * This is not an error because session
6710Sstevel@tonic-gate 				 * abort reply does not have any extra
6720Sstevel@tonic-gate 				 * information to pack.
6730Sstevel@tonic-gate 				 */
6740Sstevel@tonic-gate 				err = RDR_OK;
6750Sstevel@tonic-gate 			}
6760Sstevel@tonic-gate 			break;
6770Sstevel@tonic-gate 		}
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate 		case RDR_CONF_CONFIRM_CALLBACK: {
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate 			confirm_callback_params_t *cparam;
6820Sstevel@tonic-gate 			cparam = (confirm_callback_params_t *)param;
6830Sstevel@tonic-gate 
6840Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
6850Sstevel@tonic-gate 				err = pack_confirm_request(cparam,
6860Sstevel@tonic-gate 				    &pack_buf, &pack_buf_sz);
6870Sstevel@tonic-gate 			} else {
6880Sstevel@tonic-gate 				err = pack_confirm_reply(cparam, &pack_buf,
6890Sstevel@tonic-gate 				    &pack_buf_sz);
6900Sstevel@tonic-gate 			}
6910Sstevel@tonic-gate 			break;
6920Sstevel@tonic-gate 		}
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 		case RDR_CONF_MSG_CALLBACK: {
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 			msg_callback_params_t *mparam;
6970Sstevel@tonic-gate 			mparam = (msg_callback_params_t *)param;
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
7000Sstevel@tonic-gate 				err = pack_message_request(mparam,
7010Sstevel@tonic-gate 				    &pack_buf, &pack_buf_sz);
7020Sstevel@tonic-gate 			} else {
7030Sstevel@tonic-gate 				/*
7040Sstevel@tonic-gate 				 * It is an error to send a reply
7050Sstevel@tonic-gate 				 * to a message callback.
7060Sstevel@tonic-gate 				 */
7070Sstevel@tonic-gate 				err = RDR_MSG_INVAL;
7080Sstevel@tonic-gate 			}
7090Sstevel@tonic-gate 			break;
7100Sstevel@tonic-gate 		}
7110Sstevel@tonic-gate 
7120Sstevel@tonic-gate 		case RDR_RSRC_INFO: {
7130Sstevel@tonic-gate 
7140Sstevel@tonic-gate 			rsrc_info_params_t *rparam;
7150Sstevel@tonic-gate 			rparam = (rsrc_info_params_t *)param;
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
7180Sstevel@tonic-gate 				err = pack_rsrc_info_request(rparam, &pack_buf,
7190Sstevel@tonic-gate 				    &pack_buf_sz);
7200Sstevel@tonic-gate 			} else {
7210Sstevel@tonic-gate 				err = pack_rsrc_info_reply(rparam, &pack_buf,
7220Sstevel@tonic-gate 				    &pack_buf_sz);
7230Sstevel@tonic-gate 			}
7240Sstevel@tonic-gate 			break;
7250Sstevel@tonic-gate 		}
7260Sstevel@tonic-gate 
7270Sstevel@tonic-gate 		default:
7280Sstevel@tonic-gate 			err = RDR_MSG_INVAL;
7290Sstevel@tonic-gate 			break;
7300Sstevel@tonic-gate 	}
7310Sstevel@tonic-gate 
7320Sstevel@tonic-gate 	/* check if packed correctly */
7330Sstevel@tonic-gate 	if (err != RDR_OK) {
7340Sstevel@tonic-gate 		return (err);
7350Sstevel@tonic-gate 	}
7360Sstevel@tonic-gate 
7370Sstevel@tonic-gate 	/* send the message */
7380Sstevel@tonic-gate 	err = rdr_snd(fd, hdr, pack_buf, pack_buf_sz, timeout);
7390Sstevel@tonic-gate 
7400Sstevel@tonic-gate 	free((void *)pack_buf);
7410Sstevel@tonic-gate 
7420Sstevel@tonic-gate 	return (err);
7430Sstevel@tonic-gate }
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate /*
7470Sstevel@tonic-gate  * rdr_rcv_msg:
7480Sstevel@tonic-gate  *
7490Sstevel@tonic-gate  * Public interface for receiving an RDR message. Data is
7500Sstevel@tonic-gate  * unpacked into the hdr and param paramters.
7510Sstevel@tonic-gate  */
7520Sstevel@tonic-gate int
7530Sstevel@tonic-gate rdr_rcv_msg(int fd, rdr_msg_hdr_t *hdr, cfga_params_t *param, int timeout)
7540Sstevel@tonic-gate {
7550Sstevel@tonic-gate 	int	err;
7560Sstevel@tonic-gate 	char	*unpack_buf = NULL;
7570Sstevel@tonic-gate 
7580Sstevel@tonic-gate 
7590Sstevel@tonic-gate 	/* sanity checks */
7600Sstevel@tonic-gate 	if ((hdr == NULL) || (param == NULL)) {
7610Sstevel@tonic-gate 		return (RDR_ERROR);
7620Sstevel@tonic-gate 	}
7630Sstevel@tonic-gate 
7640Sstevel@tonic-gate 	(void) memset(param, 0, sizeof (cfga_params_t));
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 	/* receive the message */
7670Sstevel@tonic-gate 	if ((err = rdr_rcv(fd, hdr, &unpack_buf, timeout)) != RDR_OK) {
7680Sstevel@tonic-gate 		return (err);
7690Sstevel@tonic-gate 	}
7700Sstevel@tonic-gate 
7710Sstevel@tonic-gate 	/*
7720Sstevel@tonic-gate 	 * Unpack the message
7730Sstevel@tonic-gate 	 */
7740Sstevel@tonic-gate 	switch (hdr->message_opcode) {
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate 		case RDR_SES_REQ: {
7770Sstevel@tonic-gate 
7780Sstevel@tonic-gate 			ses_req_params_t *rparam;
7790Sstevel@tonic-gate 			rparam = (ses_req_params_t *)param;
7800Sstevel@tonic-gate 
7810Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
7820Sstevel@tonic-gate 				err = unpack_ses_req_request(rparam,
7830Sstevel@tonic-gate 				    unpack_buf);
7840Sstevel@tonic-gate 			} else {
7850Sstevel@tonic-gate 				err = unpack_ses_req_reply(rparam, unpack_buf);
7860Sstevel@tonic-gate 			}
7870Sstevel@tonic-gate 			break;
7880Sstevel@tonic-gate 		}
7890Sstevel@tonic-gate 
7900Sstevel@tonic-gate 		case RDR_SES_ESTBL:
7910Sstevel@tonic-gate 		case RDR_SES_END:
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 			/* no information to unpack */
7940Sstevel@tonic-gate 			(void) memset(param, 0, sizeof (cfga_params_t));
7950Sstevel@tonic-gate 			err = RDR_OK;
7960Sstevel@tonic-gate 			break;
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate 		case RDR_CONF_CHANGE_STATE: {
7990Sstevel@tonic-gate 
8000Sstevel@tonic-gate 			change_state_params_t *cparam;
8010Sstevel@tonic-gate 			cparam = (change_state_params_t *)param;
8020Sstevel@tonic-gate 
8030Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
8040Sstevel@tonic-gate 				err = unpack_change_state_request(cparam,
8050Sstevel@tonic-gate 				    unpack_buf);
8060Sstevel@tonic-gate 			} else {
8070Sstevel@tonic-gate 				err = unpack_change_state_reply(cparam,
8080Sstevel@tonic-gate 				    unpack_buf);
8090Sstevel@tonic-gate 			}
8100Sstevel@tonic-gate 			break;
8110Sstevel@tonic-gate 		}
8120Sstevel@tonic-gate 
8130Sstevel@tonic-gate 		case RDR_CONF_PRIVATE_FUNC: {
8140Sstevel@tonic-gate 
8150Sstevel@tonic-gate 			private_func_params_t *pparam;
8160Sstevel@tonic-gate 			pparam = (private_func_params_t *)param;
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
8190Sstevel@tonic-gate 				err = unpack_private_func_request(pparam,
8200Sstevel@tonic-gate 				    unpack_buf);
8210Sstevel@tonic-gate 			} else {
8220Sstevel@tonic-gate 				err = unpack_private_func_reply(pparam,
8230Sstevel@tonic-gate 				    unpack_buf);
8240Sstevel@tonic-gate 			}
8250Sstevel@tonic-gate 			break;
8260Sstevel@tonic-gate 		}
8270Sstevel@tonic-gate 
8280Sstevel@tonic-gate 		case RDR_CONF_TEST: {
8290Sstevel@tonic-gate 
8300Sstevel@tonic-gate 			test_params_t *tparam;
8310Sstevel@tonic-gate 			tparam = (test_params_t *)param;
8320Sstevel@tonic-gate 
8330Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
8340Sstevel@tonic-gate 				err = unpack_test_request(tparam, unpack_buf);
8350Sstevel@tonic-gate 			} else {
8360Sstevel@tonic-gate 				err = unpack_test_reply(tparam, unpack_buf);
8370Sstevel@tonic-gate 			}
8380Sstevel@tonic-gate 			break;
8390Sstevel@tonic-gate 		}
8400Sstevel@tonic-gate 
8410Sstevel@tonic-gate 		case RDR_CONF_LIST_EXT: {
8420Sstevel@tonic-gate 
8430Sstevel@tonic-gate 			list_ext_params_t *lparam;
8440Sstevel@tonic-gate 			lparam = (list_ext_params_t *)param;
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
8470Sstevel@tonic-gate 				err = unpack_list_ext_request(lparam,
8480Sstevel@tonic-gate 				    unpack_buf);
8490Sstevel@tonic-gate 			} else {
8500Sstevel@tonic-gate 				err = unpack_list_ext_reply(lparam, unpack_buf);
8510Sstevel@tonic-gate 			}
8520Sstevel@tonic-gate 			break;
8530Sstevel@tonic-gate 		}
8540Sstevel@tonic-gate 
8550Sstevel@tonic-gate 		case RDR_CONF_HELP: {
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate 			help_params_t *hparam;
8580Sstevel@tonic-gate 			hparam = (help_params_t *)param;
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
8610Sstevel@tonic-gate 				err = unpack_help_request(hparam,
8620Sstevel@tonic-gate 				    unpack_buf);
8630Sstevel@tonic-gate 			} else {
8640Sstevel@tonic-gate 				/*
8650Sstevel@tonic-gate 				 * This is not an error because help
8660Sstevel@tonic-gate 				 * reply does not have any extra information
8670Sstevel@tonic-gate 				 * to unpack.
8680Sstevel@tonic-gate 				 */
8690Sstevel@tonic-gate 				err = RDR_OK;
8700Sstevel@tonic-gate 			}
8710Sstevel@tonic-gate 			break;
8720Sstevel@tonic-gate 		}
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate 		case RDR_CONF_AP_ID_CMP: {
8750Sstevel@tonic-gate 
8760Sstevel@tonic-gate 			ap_id_cmp_params_t *aparam;
8770Sstevel@tonic-gate 			aparam = (ap_id_cmp_params_t *)param;
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
8800Sstevel@tonic-gate 				err = unpack_ap_id_cmp_request(aparam,
8810Sstevel@tonic-gate 				    unpack_buf);
8820Sstevel@tonic-gate 			} else {
8830Sstevel@tonic-gate 				/*
8840Sstevel@tonic-gate 				 * This is not an error because ap_id_cmp
8850Sstevel@tonic-gate 				 * reply does not have any extra information
8860Sstevel@tonic-gate 				 * to pack.
8870Sstevel@tonic-gate 				 */
8880Sstevel@tonic-gate 				err = RDR_OK;
8890Sstevel@tonic-gate 			}
8900Sstevel@tonic-gate 			break;
8910Sstevel@tonic-gate 		}
8920Sstevel@tonic-gate 
8930Sstevel@tonic-gate 		case RDR_CONF_ABORT_CMD: {
8940Sstevel@tonic-gate 
8950Sstevel@tonic-gate 			abort_cmd_params_t *aparam;
8960Sstevel@tonic-gate 			aparam = (abort_cmd_params_t *)param;
8970Sstevel@tonic-gate 
8980Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
8990Sstevel@tonic-gate 				err = unpack_abort_cmd_request(aparam,
9000Sstevel@tonic-gate 				    unpack_buf);
9010Sstevel@tonic-gate 			} else {
9020Sstevel@tonic-gate 				/* no information to unpack */
9030Sstevel@tonic-gate 				(void) memset(param, 0, sizeof (cfga_params_t));
9040Sstevel@tonic-gate 				err = RDR_OK;
9050Sstevel@tonic-gate 			}
9060Sstevel@tonic-gate 
9070Sstevel@tonic-gate 			break;
9080Sstevel@tonic-gate 		}
9090Sstevel@tonic-gate 
9100Sstevel@tonic-gate 		case RDR_CONF_CONFIRM_CALLBACK: {
9110Sstevel@tonic-gate 
9120Sstevel@tonic-gate 			confirm_callback_params_t *cparam;
9130Sstevel@tonic-gate 			cparam = (confirm_callback_params_t *)param;
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
9160Sstevel@tonic-gate 				err = unpack_confirm_request(cparam,
9170Sstevel@tonic-gate 				    unpack_buf);
9180Sstevel@tonic-gate 			} else {
9190Sstevel@tonic-gate 				err = unpack_confirm_reply(cparam, unpack_buf);
9200Sstevel@tonic-gate 			}
9210Sstevel@tonic-gate 			break;
9220Sstevel@tonic-gate 		}
9230Sstevel@tonic-gate 
9240Sstevel@tonic-gate 		case RDR_CONF_MSG_CALLBACK: {
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate 			msg_callback_params_t *mparam;
9270Sstevel@tonic-gate 			mparam = (msg_callback_params_t *)param;
9280Sstevel@tonic-gate 
9290Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
9300Sstevel@tonic-gate 				err = unpack_message_request(mparam,
9310Sstevel@tonic-gate 				    unpack_buf);
9320Sstevel@tonic-gate 			} else {
9330Sstevel@tonic-gate 				/*
9340Sstevel@tonic-gate 				 * It is an error to send a reply
9350Sstevel@tonic-gate 				 * to a message callback.
9360Sstevel@tonic-gate 				 */
9370Sstevel@tonic-gate 				(void) memset(param, 0, sizeof (cfga_params_t));
9380Sstevel@tonic-gate 				err = RDR_MSG_INVAL;
9390Sstevel@tonic-gate 			}
9400Sstevel@tonic-gate 			break;
9410Sstevel@tonic-gate 		}
9420Sstevel@tonic-gate 
9430Sstevel@tonic-gate 		case RDR_RSRC_INFO: {
9440Sstevel@tonic-gate 
9450Sstevel@tonic-gate 			rsrc_info_params_t *rparam;
9460Sstevel@tonic-gate 			rparam = (rsrc_info_params_t *)param;
9470Sstevel@tonic-gate 
9480Sstevel@tonic-gate 			if (hdr->data_type == RDR_REQUEST) {
9490Sstevel@tonic-gate 				err = unpack_rsrc_info_request(rparam,
9500Sstevel@tonic-gate 				    unpack_buf);
9510Sstevel@tonic-gate 			} else {
9520Sstevel@tonic-gate 				err = unpack_rsrc_info_reply(rparam,
9530Sstevel@tonic-gate 				    unpack_buf);
9540Sstevel@tonic-gate 			}
9550Sstevel@tonic-gate 			break;
9560Sstevel@tonic-gate 		}
9570Sstevel@tonic-gate 
9580Sstevel@tonic-gate 		default:
9590Sstevel@tonic-gate 			err = RDR_MSG_INVAL;
9600Sstevel@tonic-gate 			break;
9610Sstevel@tonic-gate 	}
9620Sstevel@tonic-gate 
9630Sstevel@tonic-gate 	free(unpack_buf);
9640Sstevel@tonic-gate 
9650Sstevel@tonic-gate 	/* check if unpacked correctly */
9660Sstevel@tonic-gate 	if (err != RDR_OK) {
9670Sstevel@tonic-gate 		return (err);
9680Sstevel@tonic-gate 	}
9690Sstevel@tonic-gate 
9700Sstevel@tonic-gate 	return (RDR_OK);
9710Sstevel@tonic-gate }
9720Sstevel@tonic-gate 
9730Sstevel@tonic-gate 
9740Sstevel@tonic-gate /*
9750Sstevel@tonic-gate  * rdr_cleanup_params:
9760Sstevel@tonic-gate  *
9770Sstevel@tonic-gate  * Deallocate any memory that was allocated in unpacking a
9780Sstevel@tonic-gate  * message.
9790Sstevel@tonic-gate  */
9800Sstevel@tonic-gate int
9810Sstevel@tonic-gate rdr_cleanup_params(rdr_msg_opcode_t message_opcode, cfga_params_t *param)
9820Sstevel@tonic-gate {
9830Sstevel@tonic-gate 	/* sanity check */
9840Sstevel@tonic-gate 	if ((param == NULL)) {
9850Sstevel@tonic-gate 		return (RDR_ERROR);
9860Sstevel@tonic-gate 	}
9870Sstevel@tonic-gate 
9880Sstevel@tonic-gate 	/*
9890Sstevel@tonic-gate 	 * Deallocate memory depending on
9900Sstevel@tonic-gate 	 * the operation.
9910Sstevel@tonic-gate 	 */
9920Sstevel@tonic-gate 	switch (message_opcode) {
9930Sstevel@tonic-gate 
9940Sstevel@tonic-gate 	case RDR_SES_REQ: {
9950Sstevel@tonic-gate 
9960Sstevel@tonic-gate 		ses_req_params_t *sparam;
9970Sstevel@tonic-gate 		sparam = (ses_req_params_t *)param;
9980Sstevel@tonic-gate 
9990Sstevel@tonic-gate 		if (sparam->locale_str != NULL) {
10000Sstevel@tonic-gate 			free((void *)sparam->locale_str);
10010Sstevel@tonic-gate 			sparam->locale_str = NULL;
10020Sstevel@tonic-gate 		}
10030Sstevel@tonic-gate 		break;
10040Sstevel@tonic-gate 	}
10050Sstevel@tonic-gate 
10060Sstevel@tonic-gate 	case RDR_SES_ESTBL:
10070Sstevel@tonic-gate 	case RDR_SES_END:
10080Sstevel@tonic-gate 
10090Sstevel@tonic-gate 		/* nothing to deallocate */
10100Sstevel@tonic-gate 		break;
10110Sstevel@tonic-gate 
10120Sstevel@tonic-gate 	case RDR_CONF_CHANGE_STATE: {
10130Sstevel@tonic-gate 
10140Sstevel@tonic-gate 		change_state_params_t *cparam;
10150Sstevel@tonic-gate 		cparam = (change_state_params_t *)param;
10160Sstevel@tonic-gate 
10170Sstevel@tonic-gate 		cleanup_ap_ids(cparam->num_ap_ids, (char **)cparam->ap_ids);
10180Sstevel@tonic-gate 		cparam->ap_ids = NULL;
10190Sstevel@tonic-gate 		if (cparam->options != NULL) {
10200Sstevel@tonic-gate 			free((void *)cparam->options);
10210Sstevel@tonic-gate 			cparam->options = NULL;
10220Sstevel@tonic-gate 		}
10230Sstevel@tonic-gate 		if (cparam->confp != NULL) {
10240Sstevel@tonic-gate 			free((void *)cparam->confp);
10250Sstevel@tonic-gate 			cparam->confp = NULL;
10260Sstevel@tonic-gate 		}
10270Sstevel@tonic-gate 		if (cparam->msgp != NULL) {
10280Sstevel@tonic-gate 			free((void *)cparam->msgp);
10290Sstevel@tonic-gate 			cparam->msgp = NULL;
10300Sstevel@tonic-gate 		}
10310Sstevel@tonic-gate 		cleanup_errstring(cparam->errstring);
10320Sstevel@tonic-gate 		break;
10330Sstevel@tonic-gate 	}
10340Sstevel@tonic-gate 
10350Sstevel@tonic-gate 	case RDR_CONF_PRIVATE_FUNC: {
10360Sstevel@tonic-gate 
10370Sstevel@tonic-gate 		private_func_params_t *pparam;
10380Sstevel@tonic-gate 		pparam = (private_func_params_t *)param;
10390Sstevel@tonic-gate 
10400Sstevel@tonic-gate 		cleanup_ap_ids(pparam->num_ap_ids, (char **)pparam->ap_ids);
10410Sstevel@tonic-gate 		pparam->ap_ids = NULL;
10420Sstevel@tonic-gate 		if (pparam->options != NULL) {
10430Sstevel@tonic-gate 			free((void *)pparam->options);
10440Sstevel@tonic-gate 			pparam->options = NULL;
10450Sstevel@tonic-gate 		}
10460Sstevel@tonic-gate 		if (pparam->confp != NULL) {
10470Sstevel@tonic-gate 			free((void *)pparam->confp);
10480Sstevel@tonic-gate 			pparam->confp = NULL;
10490Sstevel@tonic-gate 		}
10500Sstevel@tonic-gate 		if (pparam->msgp != NULL) {
10510Sstevel@tonic-gate 			free((void *)pparam->msgp);
10520Sstevel@tonic-gate 			pparam->msgp = NULL;
10530Sstevel@tonic-gate 		}
10540Sstevel@tonic-gate 		cleanup_errstring(pparam->errstring);
10550Sstevel@tonic-gate 		break;
10560Sstevel@tonic-gate 	}
10570Sstevel@tonic-gate 
10580Sstevel@tonic-gate 	case RDR_CONF_TEST: {
10590Sstevel@tonic-gate 
10600Sstevel@tonic-gate 		test_params_t *tparam;
10610Sstevel@tonic-gate 		tparam = (test_params_t *)param;
10620Sstevel@tonic-gate 
10630Sstevel@tonic-gate 		cleanup_ap_ids(tparam->num_ap_ids, (char **)tparam->ap_ids);
10640Sstevel@tonic-gate 		tparam->ap_ids = NULL;
10650Sstevel@tonic-gate 		if (tparam->options != NULL) {
10660Sstevel@tonic-gate 			free((void *)tparam->options);
10670Sstevel@tonic-gate 			tparam->options = NULL;
10680Sstevel@tonic-gate 		}
10690Sstevel@tonic-gate 		if (tparam->msgp != NULL) {
10700Sstevel@tonic-gate 			free((void *)tparam->msgp);
10710Sstevel@tonic-gate 			tparam->msgp = NULL;
10720Sstevel@tonic-gate 		}
10730Sstevel@tonic-gate 		cleanup_errstring(tparam->errstring);
10740Sstevel@tonic-gate 		break;
10750Sstevel@tonic-gate 	}
10760Sstevel@tonic-gate 
10770Sstevel@tonic-gate 	case RDR_CONF_LIST_EXT: {
10780Sstevel@tonic-gate 
10790Sstevel@tonic-gate 		list_ext_params_t *lparam;
10800Sstevel@tonic-gate 		lparam = (list_ext_params_t *)param;
10810Sstevel@tonic-gate 
10820Sstevel@tonic-gate 		cleanup_ap_ids(lparam->num_ap_ids, (char **)lparam->ap_ids);
10830Sstevel@tonic-gate 		lparam->ap_ids = NULL;
10840Sstevel@tonic-gate 
10850Sstevel@tonic-gate 		if (lparam->nlist != NULL) {
10860Sstevel@tonic-gate 			free((void *)lparam->nlist);
10870Sstevel@tonic-gate 			lparam->nlist = NULL;
10880Sstevel@tonic-gate 		}
10890Sstevel@tonic-gate 		if (lparam->ap_id_list != NULL) {
10900Sstevel@tonic-gate 			if (*lparam->ap_id_list != NULL) {
10910Sstevel@tonic-gate 				free((void *)*lparam->ap_id_list);
10920Sstevel@tonic-gate 			}
10930Sstevel@tonic-gate 			free((void *)lparam->ap_id_list);
10940Sstevel@tonic-gate 			lparam->ap_id_list = NULL;
10950Sstevel@tonic-gate 		}
10960Sstevel@tonic-gate 		if (lparam->ap_id_list != NULL) {
10970Sstevel@tonic-gate 			free((void *)lparam->ap_id_list);
10980Sstevel@tonic-gate 			lparam->ap_id_list = NULL;
10990Sstevel@tonic-gate 		}
11000Sstevel@tonic-gate 
11010Sstevel@tonic-gate 		if (lparam->options != NULL) {
11020Sstevel@tonic-gate 			free((void *)lparam->options);
11030Sstevel@tonic-gate 			lparam->options = NULL;
11040Sstevel@tonic-gate 		}
11050Sstevel@tonic-gate 		if (lparam->listopts != NULL) {
11060Sstevel@tonic-gate 			free((void *)lparam->listopts);
11070Sstevel@tonic-gate 			lparam->listopts = NULL;
11080Sstevel@tonic-gate 		}
11090Sstevel@tonic-gate 		cleanup_errstring(lparam->errstring);
11100Sstevel@tonic-gate 		break;
11110Sstevel@tonic-gate 	}
11120Sstevel@tonic-gate 
11130Sstevel@tonic-gate 	case RDR_CONF_HELP: {
11140Sstevel@tonic-gate 
11150Sstevel@tonic-gate 		help_params_t *hparam;
11160Sstevel@tonic-gate 		hparam = (help_params_t *)param;
11170Sstevel@tonic-gate 
11180Sstevel@tonic-gate 		cleanup_ap_ids(hparam->num_ap_ids, (char **)hparam->ap_ids);
11190Sstevel@tonic-gate 		hparam->ap_ids = NULL;
11200Sstevel@tonic-gate 		if (hparam->msgp != NULL) {
11210Sstevel@tonic-gate 			free((void *)hparam->msgp);
11220Sstevel@tonic-gate 			hparam->msgp = NULL;
11230Sstevel@tonic-gate 		}
11240Sstevel@tonic-gate 		if (hparam->options != NULL) {
11250Sstevel@tonic-gate 			free((void *)hparam->options);
11260Sstevel@tonic-gate 			hparam->options = NULL;
11270Sstevel@tonic-gate 		}
11280Sstevel@tonic-gate 		break;
11290Sstevel@tonic-gate 	}
11300Sstevel@tonic-gate 
11310Sstevel@tonic-gate 	case RDR_CONF_AP_ID_CMP: {
11320Sstevel@tonic-gate 
11330Sstevel@tonic-gate 		ap_id_cmp_params_t *aparam;
11340Sstevel@tonic-gate 		aparam = (ap_id_cmp_params_t *)param;
11350Sstevel@tonic-gate 
11360Sstevel@tonic-gate 		if (aparam->ap_log_id1 != NULL) {
11370Sstevel@tonic-gate 			free((void *)aparam->ap_log_id1);
11380Sstevel@tonic-gate 			aparam->ap_log_id1 = NULL;
11390Sstevel@tonic-gate 		}
11400Sstevel@tonic-gate 		if (aparam->ap_log_id2 != NULL) {
11410Sstevel@tonic-gate 			free((void *)aparam->ap_log_id2);
11420Sstevel@tonic-gate 			aparam->ap_log_id2 = NULL;
11430Sstevel@tonic-gate 		}
11440Sstevel@tonic-gate 		break;
11450Sstevel@tonic-gate 	}
11460Sstevel@tonic-gate 
11470Sstevel@tonic-gate 	case RDR_CONF_ABORT_CMD:
11480Sstevel@tonic-gate 
11490Sstevel@tonic-gate 		/* nothing to deallocate */
11500Sstevel@tonic-gate 		break;
11510Sstevel@tonic-gate 
11520Sstevel@tonic-gate 	case RDR_CONF_CONFIRM_CALLBACK: {
11530Sstevel@tonic-gate 
11540Sstevel@tonic-gate 		confirm_callback_params_t *cparam;
11550Sstevel@tonic-gate 		cparam = (confirm_callback_params_t *)param;
11560Sstevel@tonic-gate 
11570Sstevel@tonic-gate 		if (cparam->confp != NULL) {
11580Sstevel@tonic-gate 			free((void *)cparam->confp);
11590Sstevel@tonic-gate 			cparam->confp = NULL;
11600Sstevel@tonic-gate 		}
11610Sstevel@tonic-gate 		if (cparam->message != NULL) {
11620Sstevel@tonic-gate 			free((void *)cparam->message);
11630Sstevel@tonic-gate 			cparam->message = NULL;
11640Sstevel@tonic-gate 		}
11650Sstevel@tonic-gate 		break;
11660Sstevel@tonic-gate 	}
11670Sstevel@tonic-gate 
11680Sstevel@tonic-gate 	case RDR_CONF_MSG_CALLBACK: {
11690Sstevel@tonic-gate 
11700Sstevel@tonic-gate 		msg_callback_params_t *mparam;
11710Sstevel@tonic-gate 		mparam = (msg_callback_params_t *)param;
11720Sstevel@tonic-gate 
11730Sstevel@tonic-gate 		if (mparam->msgp != NULL) {
11740Sstevel@tonic-gate 			free((void *)mparam->msgp);
11750Sstevel@tonic-gate 			mparam->msgp = NULL;
11760Sstevel@tonic-gate 		}
11770Sstevel@tonic-gate 		if (mparam->message != NULL) {
11780Sstevel@tonic-gate 			free((void *)mparam->message);
11790Sstevel@tonic-gate 			mparam->message = NULL;
11800Sstevel@tonic-gate 		}
11810Sstevel@tonic-gate 		break;
11820Sstevel@tonic-gate 	}
11830Sstevel@tonic-gate 
11840Sstevel@tonic-gate 	default:
11850Sstevel@tonic-gate 		return (RDR_ERROR);
11860Sstevel@tonic-gate 		/* NOTREACHED */
11870Sstevel@tonic-gate 		break;
11880Sstevel@tonic-gate 
11890Sstevel@tonic-gate 	}
11900Sstevel@tonic-gate 
11910Sstevel@tonic-gate 	return (RDR_OK);
11920Sstevel@tonic-gate }
11930Sstevel@tonic-gate 
1194*1120Smb158278 /*
1195*1120Smb158278  * rdr_setsockopt:
1196*1120Smb158278  *
1197*1120Smb158278  * Wrapper of the setsockopt(3SOCKET) library function.
1198*1120Smb158278  */
1199*1120Smb158278 int
1200*1120Smb158278 rdr_setsockopt(int fd, int level, int optname, const void *optval, int optlen)
1201*1120Smb158278 {
1202*1120Smb158278 	if (setsockopt(fd, level, optname, optval, optlen) == -1)
1203*1120Smb158278 		return (RDR_NET_ERR);
1204*1120Smb158278 	else
1205*1120Smb158278 		return (RDR_OK);
1206*1120Smb158278 }
1207*1120Smb158278 
12080Sstevel@tonic-gate 
12090Sstevel@tonic-gate /*
12100Sstevel@tonic-gate  * Private (static) Functions
12110Sstevel@tonic-gate  */
12120Sstevel@tonic-gate 
12130Sstevel@tonic-gate 
12140Sstevel@tonic-gate /*
12150Sstevel@tonic-gate  * rdr_setopt:
12160Sstevel@tonic-gate  *
12170Sstevel@tonic-gate  * Set the specified option for a given transport endpoint.
12180Sstevel@tonic-gate  * This function only sets boolean options. It does not
12190Sstevel@tonic-gate  * provide the ability to unset an option, or set a non-
12200Sstevel@tonic-gate  * boolean option.
12210Sstevel@tonic-gate  */
12220Sstevel@tonic-gate static int
12230Sstevel@tonic-gate rdr_setopt(int fd, int name, int level)
12240Sstevel@tonic-gate {
12250Sstevel@tonic-gate 	int	on = 1;
12260Sstevel@tonic-gate 
12270Sstevel@tonic-gate 
12280Sstevel@tonic-gate 	if (setsockopt(fd, level, name, &on, sizeof (on)) == -1) {
12290Sstevel@tonic-gate 		return (RDR_NET_ERR);
12300Sstevel@tonic-gate 	}
12310Sstevel@tonic-gate 
12320Sstevel@tonic-gate 	return (RDR_OK);
12330Sstevel@tonic-gate }
12340Sstevel@tonic-gate 
12350Sstevel@tonic-gate 
12360Sstevel@tonic-gate /*
12370Sstevel@tonic-gate  * rdr_bind:
12380Sstevel@tonic-gate  *
12390Sstevel@tonic-gate  * Bind the specified file descriptor to a specified
12400Sstevel@tonic-gate  * address. If the address is already bound, no error is
12410Sstevel@tonic-gate  * returned. This is the expected behavior if a server
12420Sstevel@tonic-gate  * has been started by inetd (1M).
12430Sstevel@tonic-gate  */
12440Sstevel@tonic-gate static int
12450Sstevel@tonic-gate rdr_bind(int fd, struct sockaddr *addr)
12460Sstevel@tonic-gate {
12470Sstevel@tonic-gate 	unsigned int		addr_len;
12480Sstevel@tonic-gate 	int			rc;
12490Sstevel@tonic-gate 
12500Sstevel@tonic-gate 
12510Sstevel@tonic-gate 	/* initialize the address */
12520Sstevel@tonic-gate 	switch (addr->sa_family) {
12530Sstevel@tonic-gate 
12540Sstevel@tonic-gate 	case AF_INET:
12550Sstevel@tonic-gate 		addr_len = sizeof (struct sockaddr_in);
12560Sstevel@tonic-gate 		break;
12570Sstevel@tonic-gate 
12580Sstevel@tonic-gate 	case AF_INET6:
12590Sstevel@tonic-gate 		addr_len = sizeof (struct sockaddr_in6);
12600Sstevel@tonic-gate 		break;
12610Sstevel@tonic-gate 
12620Sstevel@tonic-gate 	default:
12630Sstevel@tonic-gate 		return (RDR_ERROR);
12640Sstevel@tonic-gate 	}
12650Sstevel@tonic-gate 
12660Sstevel@tonic-gate 	/* attempt to bind the address */
12670Sstevel@tonic-gate 	rc = bind(fd, addr, addr_len);
12680Sstevel@tonic-gate 
12690Sstevel@tonic-gate 	/*
12700Sstevel@tonic-gate 	 * Ignore the error if EINVAL is returned. In
12710Sstevel@tonic-gate 	 * this case, we assume that this means that
12720Sstevel@tonic-gate 	 * the address was already bound. This is not
12730Sstevel@tonic-gate 	 * an error for servers started by inetd (1M).
12740Sstevel@tonic-gate 	 */
12750Sstevel@tonic-gate 	if ((rc == -1) && (errno != EINVAL)) {
12760Sstevel@tonic-gate 		return (RDR_NET_ERR);
12770Sstevel@tonic-gate 	}
12780Sstevel@tonic-gate 
12790Sstevel@tonic-gate 	/*
12800Sstevel@tonic-gate 	 * Retreive the address information of the
12810Sstevel@tonic-gate 	 * address that was actually bound.
12820Sstevel@tonic-gate 	 */
12830Sstevel@tonic-gate 	addr_len = sizeof (*addr);
12840Sstevel@tonic-gate 	if (getsockname(fd, addr, &addr_len) == -1) {
12850Sstevel@tonic-gate 		(void) memset(addr, 0, sizeof (*addr));
12860Sstevel@tonic-gate 		return (RDR_NET_ERR);
12870Sstevel@tonic-gate 	}
12880Sstevel@tonic-gate 
12890Sstevel@tonic-gate 	return (RDR_OK);
12900Sstevel@tonic-gate }
12910Sstevel@tonic-gate 
12920Sstevel@tonic-gate 
12930Sstevel@tonic-gate /*
12940Sstevel@tonic-gate  * rdr_snd:
12950Sstevel@tonic-gate  *
12960Sstevel@tonic-gate  * Send a message in two stages. First the header is sent,
12970Sstevel@tonic-gate  * followed by the packed buffer containing the message
12980Sstevel@tonic-gate  * contents.
12990Sstevel@tonic-gate  */
13000Sstevel@tonic-gate static int
13010Sstevel@tonic-gate rdr_snd(int fd, rdr_msg_hdr_t *hdr, char *data, int data_sz, int timeout)
13020Sstevel@tonic-gate {
13030Sstevel@tonic-gate 	int	err;
13040Sstevel@tonic-gate 
13050Sstevel@tonic-gate 
13060Sstevel@tonic-gate 	/* sanity check */
13070Sstevel@tonic-gate 	if (hdr == NULL) {
13080Sstevel@tonic-gate 		return (RDR_ERROR);
13090Sstevel@tonic-gate 	}
13100Sstevel@tonic-gate 
13110Sstevel@tonic-gate 	/* ensure null pad bytes */
13120Sstevel@tonic-gate 	hdr->pad_byte1 = 0;
13130Sstevel@tonic-gate 	hdr->pad_byte2 = 0;
13140Sstevel@tonic-gate 
13150Sstevel@tonic-gate 	/* initialize size information */
13160Sstevel@tonic-gate 	hdr->data_length = data_sz;
13170Sstevel@tonic-gate 
13180Sstevel@tonic-gate 	/* send message header */
13190Sstevel@tonic-gate 	err = rdr_snd_raw(fd, (char *)hdr, RDR_MSG_HDR_SIZE, timeout);
13200Sstevel@tonic-gate 	if (err != RDR_OK) {
13210Sstevel@tonic-gate 		return (err);
13220Sstevel@tonic-gate 	}
13230Sstevel@tonic-gate 
13240Sstevel@tonic-gate 	/* check if more to send */
13250Sstevel@tonic-gate 	if (data_sz == 0) {
13260Sstevel@tonic-gate 		return (RDR_OK);
13270Sstevel@tonic-gate 	}
13280Sstevel@tonic-gate 
13290Sstevel@tonic-gate 	/* send message data */
13300Sstevel@tonic-gate 	err = rdr_snd_raw(fd, data, data_sz, timeout);
13310Sstevel@tonic-gate 	if (err != RDR_OK) {
13320Sstevel@tonic-gate 		return (err);
13330Sstevel@tonic-gate 	}
13340Sstevel@tonic-gate 
13350Sstevel@tonic-gate 	return (RDR_OK);
13360Sstevel@tonic-gate }
13370Sstevel@tonic-gate 
13380Sstevel@tonic-gate 
13390Sstevel@tonic-gate /*
13400Sstevel@tonic-gate  * rdr_snd_raw:
13410Sstevel@tonic-gate  *
13420Sstevel@tonic-gate  * Send a raw buffer of information. This function handles
13430Sstevel@tonic-gate  * the low level details of the send operation.
13440Sstevel@tonic-gate  */
13450Sstevel@tonic-gate static int
13460Sstevel@tonic-gate rdr_snd_raw(int fd, char *msg, int data_sz, int timeout)
13470Sstevel@tonic-gate {
13480Sstevel@tonic-gate 	int		err;
13490Sstevel@tonic-gate 	int		num_bytes;
13500Sstevel@tonic-gate 	int		bytes_left;
13510Sstevel@tonic-gate 	char		*bufp;
13520Sstevel@tonic-gate 	struct pollfd	pfd;
13530Sstevel@tonic-gate 
13540Sstevel@tonic-gate 
13550Sstevel@tonic-gate 	bufp = (char *)msg;
13560Sstevel@tonic-gate 
13570Sstevel@tonic-gate 	bytes_left = data_sz;
13580Sstevel@tonic-gate 
13590Sstevel@tonic-gate 	pfd.fd = fd;
13600Sstevel@tonic-gate 	pfd.events = POLLOUT;
13610Sstevel@tonic-gate 
13620Sstevel@tonic-gate 	while (bytes_left > 0) {
13630Sstevel@tonic-gate 
13640Sstevel@tonic-gate 		pfd.revents = 0;
13650Sstevel@tonic-gate 
13660Sstevel@tonic-gate 		/* wait until we can send the data */
13670Sstevel@tonic-gate 		if ((err = poll(&pfd, 1, timeout)) == -1) {
13680Sstevel@tonic-gate 
13690Sstevel@tonic-gate 			/* poll was interrupted */
13700Sstevel@tonic-gate 			if (errno == EINTR) {
13710Sstevel@tonic-gate 				return (RDR_ABORTED);
13720Sstevel@tonic-gate 			}
13730Sstevel@tonic-gate 
13740Sstevel@tonic-gate 			return (RDR_ERROR);
13750Sstevel@tonic-gate 
13760Sstevel@tonic-gate 		} else if (err == 0) {
13770Sstevel@tonic-gate 			return (RDR_TIMEOUT);
13780Sstevel@tonic-gate 		}
13790Sstevel@tonic-gate 
13800Sstevel@tonic-gate 		/* ready to send data */
13810Sstevel@tonic-gate 		if (pfd.revents & POLLOUT) {
13820Sstevel@tonic-gate 
13830Sstevel@tonic-gate 			num_bytes = write(fd, bufp, bytes_left);
13840Sstevel@tonic-gate 
13850Sstevel@tonic-gate 			if (num_bytes == -1) {
13860Sstevel@tonic-gate 
13870Sstevel@tonic-gate 				/*
13880Sstevel@tonic-gate 				 * Distinguish between an aborted
13890Sstevel@tonic-gate 				 * session and other network errors.
13900Sstevel@tonic-gate 				 */
13910Sstevel@tonic-gate 				if (errno == EPIPE) {
13920Sstevel@tonic-gate 					return (RDR_ABORTED);
13930Sstevel@tonic-gate 				} else {
13940Sstevel@tonic-gate 					return (RDR_NET_ERR);
13950Sstevel@tonic-gate 				}
13960Sstevel@tonic-gate 			}
13970Sstevel@tonic-gate 
13980Sstevel@tonic-gate 			/* wrote 0 bytes, so operation was aborted */
13990Sstevel@tonic-gate 			if (num_bytes == 0) {
14000Sstevel@tonic-gate 				return (RDR_ABORTED);
14010Sstevel@tonic-gate 			}
14020Sstevel@tonic-gate 
14030Sstevel@tonic-gate 		} else {
14040Sstevel@tonic-gate 			return (RDR_NET_ERR);
14050Sstevel@tonic-gate 		}
14060Sstevel@tonic-gate 
14070Sstevel@tonic-gate 		bytes_left -= num_bytes;
14080Sstevel@tonic-gate 		bufp += num_bytes;
14090Sstevel@tonic-gate 	}
14100Sstevel@tonic-gate 
14110Sstevel@tonic-gate 	return (RDR_OK);
14120Sstevel@tonic-gate }
14130Sstevel@tonic-gate 
14140Sstevel@tonic-gate 
14150Sstevel@tonic-gate /*
14160Sstevel@tonic-gate  * rdr_rcv:
14170Sstevel@tonic-gate  *
14180Sstevel@tonic-gate  * Receive a message in two stages. First the header is
14190Sstevel@tonic-gate  * received, followed by the packed buffer containing the
14200Sstevel@tonic-gate  * message contents.
14210Sstevel@tonic-gate  */
14220Sstevel@tonic-gate static int
14230Sstevel@tonic-gate rdr_rcv(int fd, rdr_msg_hdr_t *hdr, char **data, int timeout)
14240Sstevel@tonic-gate {
14250Sstevel@tonic-gate 	int	err;
14260Sstevel@tonic-gate 	int	data_sz;
14270Sstevel@tonic-gate 	char	hdr_buf[RDR_MSG_HDR_SIZE];
14280Sstevel@tonic-gate 	char	*buf = NULL;
14290Sstevel@tonic-gate 
14300Sstevel@tonic-gate 
14310Sstevel@tonic-gate 	/* sanity check */
14320Sstevel@tonic-gate 	if (hdr == NULL) {
14330Sstevel@tonic-gate 		return (RDR_ERROR);
14340Sstevel@tonic-gate 	}
14350Sstevel@tonic-gate 
14360Sstevel@tonic-gate 	/* receive the header */
14370Sstevel@tonic-gate 	err = rdr_rcv_raw(fd, hdr_buf, RDR_MSG_HDR_SIZE, timeout);
14380Sstevel@tonic-gate 	if (err != RDR_OK) {
14390Sstevel@tonic-gate 		return (err);
14400Sstevel@tonic-gate 	}
14410Sstevel@tonic-gate 
14420Sstevel@tonic-gate 	/* verify that the data is good */
14430Sstevel@tonic-gate 	/* LINTED Pointer Cast Alignment Warning */
14440Sstevel@tonic-gate 	if (validate_header((rdr_msg_hdr_t *)hdr_buf) != RDR_OK) {
14450Sstevel@tonic-gate 		return (RDR_MSG_INVAL);
14460Sstevel@tonic-gate 	}
14470Sstevel@tonic-gate 
14480Sstevel@tonic-gate 	/* LINTED Pointer Cast Alignment Warning */
14490Sstevel@tonic-gate 	data_sz = ((rdr_msg_hdr_t *)hdr_buf)->data_length;
14500Sstevel@tonic-gate 
14510Sstevel@tonic-gate 	buf = (char *)malloc(data_sz);
14520Sstevel@tonic-gate 	if (!buf) {
14530Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
14540Sstevel@tonic-gate 	}
14550Sstevel@tonic-gate 
14560Sstevel@tonic-gate 	if (data_sz != 0) {
14570Sstevel@tonic-gate 
14580Sstevel@tonic-gate 		/* receive the rest of the message */
14590Sstevel@tonic-gate 		err = rdr_rcv_raw(fd, buf, data_sz, timeout);
14600Sstevel@tonic-gate 		if (err != RDR_OK) {
14610Sstevel@tonic-gate 			free((void *)buf);
14620Sstevel@tonic-gate 			return (err);
14630Sstevel@tonic-gate 		}
14640Sstevel@tonic-gate 	}
14650Sstevel@tonic-gate 
14660Sstevel@tonic-gate 	/* copy out data */
14670Sstevel@tonic-gate 	*data = buf;
14680Sstevel@tonic-gate 	(void) memcpy(hdr, hdr_buf, RDR_MSG_HDR_SIZE);
14690Sstevel@tonic-gate 
14700Sstevel@tonic-gate 	return (RDR_OK);
14710Sstevel@tonic-gate }
14720Sstevel@tonic-gate 
14730Sstevel@tonic-gate 
14740Sstevel@tonic-gate /*
14750Sstevel@tonic-gate  * rdr_rcv_raw:
14760Sstevel@tonic-gate  *
14770Sstevel@tonic-gate  * Receive a raw buffer of information. This function handles
14780Sstevel@tonic-gate  * the low level details of the receive operation.
14790Sstevel@tonic-gate  */
14800Sstevel@tonic-gate static int
14810Sstevel@tonic-gate rdr_rcv_raw(int fd, char *msg, int data_size, int timeout)
14820Sstevel@tonic-gate {
14830Sstevel@tonic-gate 	int		num_bytes;
14840Sstevel@tonic-gate 	int		err;
14850Sstevel@tonic-gate 	int		bytes_left;
14860Sstevel@tonic-gate 	char		*bufp;
14870Sstevel@tonic-gate 	struct pollfd	pollfd;
14880Sstevel@tonic-gate 
14890Sstevel@tonic-gate 
14900Sstevel@tonic-gate 	bufp = (char *)msg;
14910Sstevel@tonic-gate 	bytes_left = data_size;
14920Sstevel@tonic-gate 
14930Sstevel@tonic-gate 	pollfd.fd = fd;
14940Sstevel@tonic-gate 	pollfd.events = POLLIN;
14950Sstevel@tonic-gate 
14960Sstevel@tonic-gate 	while (bytes_left > 0) {
14970Sstevel@tonic-gate 
14980Sstevel@tonic-gate 		errno = 0;
14990Sstevel@tonic-gate 		pollfd.revents = 0;
15000Sstevel@tonic-gate 
15010Sstevel@tonic-gate 		if ((err = poll(&pollfd, 1, timeout)) == -1) {
15020Sstevel@tonic-gate 
15030Sstevel@tonic-gate 			/*
15040Sstevel@tonic-gate 			 * In the DCA, if a session is aborted, SIGINT
15050Sstevel@tonic-gate 			 * is delivered to all active sessions. This
15060Sstevel@tonic-gate 			 * mistakenly causes all sessions waiting in
15070Sstevel@tonic-gate 			 * the poll to be interrupted. So, if EINTR
15080Sstevel@tonic-gate 			 * is returned, it is ignored. If another error
15090Sstevel@tonic-gate 			 * occurs right away, the current session really
15100Sstevel@tonic-gate 			 * was aborted. All other sessions won't encounter
15110Sstevel@tonic-gate 			 * an error and will proceed normally.
15120Sstevel@tonic-gate 			 */
15130Sstevel@tonic-gate 			if ((errno == 0) || (errno == EINTR)) {
15140Sstevel@tonic-gate 				continue;
15150Sstevel@tonic-gate 			}
15160Sstevel@tonic-gate 
15170Sstevel@tonic-gate 			return (RDR_ABORTED);
15180Sstevel@tonic-gate 
15190Sstevel@tonic-gate 		} else if (err == 0) {
15200Sstevel@tonic-gate 			return (RDR_TIMEOUT);
15210Sstevel@tonic-gate 		}
15220Sstevel@tonic-gate 
15230Sstevel@tonic-gate 		/* ready to receive data */
15240Sstevel@tonic-gate 		if (pollfd.revents & POLLIN) {
15250Sstevel@tonic-gate 
15260Sstevel@tonic-gate 			num_bytes = read(fd, bufp, bytes_left);
15270Sstevel@tonic-gate 
15280Sstevel@tonic-gate 			if (num_bytes == -1) {
15290Sstevel@tonic-gate 
15300Sstevel@tonic-gate 				/*
15310Sstevel@tonic-gate 				 * Distinguish between an aborted
15320Sstevel@tonic-gate 				 * session and other network errors.
15330Sstevel@tonic-gate 				 */
15340Sstevel@tonic-gate 				if (errno == ECONNRESET) {
15350Sstevel@tonic-gate 					return (RDR_ABORTED);
15360Sstevel@tonic-gate 				} else {
15370Sstevel@tonic-gate 					return (RDR_NET_ERR);
15380Sstevel@tonic-gate 				}
15390Sstevel@tonic-gate 			}
15400Sstevel@tonic-gate 
15410Sstevel@tonic-gate 			/* read 0 bytes, so operation was aborted */
15420Sstevel@tonic-gate 			if (num_bytes == 0) {
15430Sstevel@tonic-gate 				return (RDR_ABORTED);
15440Sstevel@tonic-gate 			}
15450Sstevel@tonic-gate 
15460Sstevel@tonic-gate 		} else {
15470Sstevel@tonic-gate 			return (RDR_NET_ERR);
15480Sstevel@tonic-gate 		}
15490Sstevel@tonic-gate 
15500Sstevel@tonic-gate 		bytes_left -= num_bytes;
15510Sstevel@tonic-gate 		bufp += num_bytes;
15520Sstevel@tonic-gate 	}
15530Sstevel@tonic-gate 
15540Sstevel@tonic-gate 	return (RDR_OK);
15550Sstevel@tonic-gate }
15560Sstevel@tonic-gate 
15570Sstevel@tonic-gate 
15580Sstevel@tonic-gate /*
15590Sstevel@tonic-gate  * validate_header:
15600Sstevel@tonic-gate  *
15610Sstevel@tonic-gate  * Perform a series of sanity checks on the header data that is
15620Sstevel@tonic-gate  * received. This gets called before the variable length data is
15630Sstevel@tonic-gate  * read in to make sure that the information in the header can
15640Sstevel@tonic-gate  * be trusted.
15650Sstevel@tonic-gate  */
15660Sstevel@tonic-gate static int
15670Sstevel@tonic-gate validate_header(rdr_msg_hdr_t *hdr)
15680Sstevel@tonic-gate {
15690Sstevel@tonic-gate 	unsigned char	op;
15700Sstevel@tonic-gate 
15710Sstevel@tonic-gate 
15720Sstevel@tonic-gate 	if (hdr == NULL) {
15730Sstevel@tonic-gate 		return (RDR_ERROR);
15740Sstevel@tonic-gate 	}
15750Sstevel@tonic-gate 
15760Sstevel@tonic-gate 	op = hdr->message_opcode;
15770Sstevel@tonic-gate 
15780Sstevel@tonic-gate 	/* validate opcode */
15790Sstevel@tonic-gate 	if ((op < RDR_SES_REQ) || (op >= RDR_NUM_OPS)) {
15800Sstevel@tonic-gate 		return (RDR_ERROR);
15810Sstevel@tonic-gate 	}
15820Sstevel@tonic-gate 
15830Sstevel@tonic-gate 	/* validate message size (and type) for op */
15840Sstevel@tonic-gate 	switch (hdr->data_type) {
15850Sstevel@tonic-gate 
15860Sstevel@tonic-gate 	case RDR_REQUEST:
15870Sstevel@tonic-gate 		if (hdr->data_length > msg_sizes[op].req_max) {
15880Sstevel@tonic-gate 			return (RDR_ERROR);
15890Sstevel@tonic-gate 		}
15900Sstevel@tonic-gate 		break;
15910Sstevel@tonic-gate 
15920Sstevel@tonic-gate 	case RDR_REPLY:
15930Sstevel@tonic-gate 		if (hdr->data_length > msg_sizes[op].reply_max) {
15940Sstevel@tonic-gate 			return (RDR_ERROR);
15950Sstevel@tonic-gate 		}
15960Sstevel@tonic-gate 		break;
15970Sstevel@tonic-gate 
15980Sstevel@tonic-gate 	default:
15990Sstevel@tonic-gate 		/* invalid data type */
16000Sstevel@tonic-gate 		return (RDR_ERROR);
16010Sstevel@tonic-gate 	}
16020Sstevel@tonic-gate 
16030Sstevel@tonic-gate 	/* all checks passed */
16040Sstevel@tonic-gate 	return (RDR_OK);
16050Sstevel@tonic-gate }
16060Sstevel@tonic-gate 
16070Sstevel@tonic-gate 
16080Sstevel@tonic-gate /*
16090Sstevel@tonic-gate  * pack_ses_req_request:
16100Sstevel@tonic-gate  *
16110Sstevel@tonic-gate  * Handle packing a session request request message.
16120Sstevel@tonic-gate  */
16130Sstevel@tonic-gate static int
16140Sstevel@tonic-gate pack_ses_req_request(ses_req_params_t *params, char **buf, int *buf_size)
16150Sstevel@tonic-gate {
16160Sstevel@tonic-gate 	char		*bufptr;
16170Sstevel@tonic-gate 	int		locale_str_len;
16180Sstevel@tonic-gate 	rdr_ses_req_t	ses_req;
16190Sstevel@tonic-gate 
16200Sstevel@tonic-gate 
16210Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
16220Sstevel@tonic-gate 		return (RDR_ERROR);
16230Sstevel@tonic-gate 	}
16240Sstevel@tonic-gate 
16250Sstevel@tonic-gate 	/*
16260Sstevel@tonic-gate 	 * Determine the size of the locale string
16270Sstevel@tonic-gate 	 */
16280Sstevel@tonic-gate 	if (params->locale_str != NULL) {
16290Sstevel@tonic-gate 		locale_str_len = strlen(params->locale_str) + 1;
16300Sstevel@tonic-gate 	} else {
16310Sstevel@tonic-gate 		locale_str_len = 0;
16320Sstevel@tonic-gate 	}
16330Sstevel@tonic-gate 
16340Sstevel@tonic-gate 	/*
16350Sstevel@tonic-gate 	 * Collect size info specific to the ses_req request message
16360Sstevel@tonic-gate 	 * and allocate a buffer
16370Sstevel@tonic-gate 	 */
16380Sstevel@tonic-gate 	*buf_size = sizeof (rdr_ses_req_t);
16390Sstevel@tonic-gate 	*buf_size += locale_str_len;
16400Sstevel@tonic-gate 
16410Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
16420Sstevel@tonic-gate 	if (*buf == NULL) {
16430Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
16440Sstevel@tonic-gate 	}
16450Sstevel@tonic-gate 
16460Sstevel@tonic-gate 	/*
16470Sstevel@tonic-gate 	 * Set fixed locale size label by name
16480Sstevel@tonic-gate 	 */
16490Sstevel@tonic-gate 	ses_req.locale_size = locale_str_len;
16500Sstevel@tonic-gate 
16510Sstevel@tonic-gate 	/*
16520Sstevel@tonic-gate 	 * Set variable information using memcpy
16530Sstevel@tonic-gate 	 */
16540Sstevel@tonic-gate 	bufptr = *buf;
16550Sstevel@tonic-gate 
16560Sstevel@tonic-gate 	(void) memcpy(bufptr, &ses_req, sizeof (rdr_ses_req_t));
16570Sstevel@tonic-gate 	bufptr += sizeof (rdr_ses_req_t);
16580Sstevel@tonic-gate 
16590Sstevel@tonic-gate 	if (params->locale_str != NULL) {
16600Sstevel@tonic-gate 		(void) memcpy(bufptr, params->locale_str, locale_str_len);
16610Sstevel@tonic-gate 		bufptr += locale_str_len;
16620Sstevel@tonic-gate 	}
16630Sstevel@tonic-gate 
16640Sstevel@tonic-gate 	return (RDR_OK);
16650Sstevel@tonic-gate }
16660Sstevel@tonic-gate 
16670Sstevel@tonic-gate 
16680Sstevel@tonic-gate /*
16690Sstevel@tonic-gate  * unpack_ses_req_request:
16700Sstevel@tonic-gate  *
16710Sstevel@tonic-gate  * Handle unpacking a session request request message.
16720Sstevel@tonic-gate  */
16730Sstevel@tonic-gate static int
16740Sstevel@tonic-gate unpack_ses_req_request(ses_req_params_t *params, const char *buf)
16750Sstevel@tonic-gate {
16760Sstevel@tonic-gate 	char		*bufptr;
16770Sstevel@tonic-gate 	rdr_ses_req_t	ses_req_data;
16780Sstevel@tonic-gate 
16790Sstevel@tonic-gate 
16800Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
16810Sstevel@tonic-gate 		return (RDR_ERROR);
16820Sstevel@tonic-gate 	}
16830Sstevel@tonic-gate 
16840Sstevel@tonic-gate 	bufptr = (char *)buf;
16850Sstevel@tonic-gate 	(void) memcpy(&ses_req_data, bufptr, sizeof (rdr_ses_req_t));
16860Sstevel@tonic-gate 	bufptr += sizeof (rdr_ses_req_t);
16870Sstevel@tonic-gate 
16880Sstevel@tonic-gate 	/*
16890Sstevel@tonic-gate 	 * handle getting the locale string
16900Sstevel@tonic-gate 	 */
16910Sstevel@tonic-gate 	if (get_string_from_buf(&(params->locale_str),
16920Sstevel@tonic-gate 	    ses_req_data.locale_size, bufptr)) {
16930Sstevel@tonic-gate 		return (RDR_ERROR);
16940Sstevel@tonic-gate 	}
16950Sstevel@tonic-gate 
16960Sstevel@tonic-gate 	return (RDR_OK);
16970Sstevel@tonic-gate }
16980Sstevel@tonic-gate 
16990Sstevel@tonic-gate 
17000Sstevel@tonic-gate /*
17010Sstevel@tonic-gate  * pack_ses_req_reply:
17020Sstevel@tonic-gate  *
17030Sstevel@tonic-gate  * Handle packing a session request reply message.
17040Sstevel@tonic-gate  */
17050Sstevel@tonic-gate static int
17060Sstevel@tonic-gate pack_ses_req_reply(ses_req_params_t *params, char **buf, int *buf_size)
17070Sstevel@tonic-gate {
17080Sstevel@tonic-gate 	rdr_ses_req_reply_t	ses_req_reply_data;
17090Sstevel@tonic-gate 
17100Sstevel@tonic-gate 
17110Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
17120Sstevel@tonic-gate 		return (RDR_ERROR);
17130Sstevel@tonic-gate 	}
17140Sstevel@tonic-gate 
17150Sstevel@tonic-gate 	/*
17160Sstevel@tonic-gate 	 * Collect size info specific to the session request reply
17170Sstevel@tonic-gate 	 * message and allocate a buffer
17180Sstevel@tonic-gate 	 */
17190Sstevel@tonic-gate 	*buf_size = sizeof (rdr_ses_req_reply_t);
17200Sstevel@tonic-gate 
17210Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
17220Sstevel@tonic-gate 	if (*buf == NULL) {
17230Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
17240Sstevel@tonic-gate 	}
17250Sstevel@tonic-gate 
17260Sstevel@tonic-gate 	/*
17270Sstevel@tonic-gate 	 * Set fixed session identifier
17280Sstevel@tonic-gate 	 */
17290Sstevel@tonic-gate 	ses_req_reply_data.session_id = params->session_id;
17300Sstevel@tonic-gate 
17310Sstevel@tonic-gate 	/*
17320Sstevel@tonic-gate 	 * Copy information using memcpy
17330Sstevel@tonic-gate 	 */
17340Sstevel@tonic-gate 	(void) memcpy(*buf, &ses_req_reply_data, sizeof (rdr_ses_req_reply_t));
17350Sstevel@tonic-gate 
17360Sstevel@tonic-gate 	return (RDR_OK);
17370Sstevel@tonic-gate }
17380Sstevel@tonic-gate 
17390Sstevel@tonic-gate 
17400Sstevel@tonic-gate /*
17410Sstevel@tonic-gate  * unpack_ses_req_request:
17420Sstevel@tonic-gate  *
17430Sstevel@tonic-gate  * Handle unpacking a session request reply message.
17440Sstevel@tonic-gate  */
17450Sstevel@tonic-gate static int
17460Sstevel@tonic-gate unpack_ses_req_reply(ses_req_params_t *params, const char *buf)
17470Sstevel@tonic-gate {
17480Sstevel@tonic-gate 	rdr_ses_req_reply_t	*ses_req_reply_datap;
17490Sstevel@tonic-gate 
17500Sstevel@tonic-gate 
17510Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
17520Sstevel@tonic-gate 		return (RDR_ERROR);
17530Sstevel@tonic-gate 	}
17540Sstevel@tonic-gate 
17550Sstevel@tonic-gate 	/* LINTED Pointer Cast Alignment Warning */
17560Sstevel@tonic-gate 	ses_req_reply_datap = (rdr_ses_req_reply_t *)buf;
17570Sstevel@tonic-gate 
17580Sstevel@tonic-gate 	/*
17590Sstevel@tonic-gate 	 * copy out the session information
17600Sstevel@tonic-gate 	 */
17610Sstevel@tonic-gate 	params->session_id = ses_req_reply_datap->session_id;
17620Sstevel@tonic-gate 
17630Sstevel@tonic-gate 	return (RDR_OK);
17640Sstevel@tonic-gate }
17650Sstevel@tonic-gate 
17660Sstevel@tonic-gate 
17670Sstevel@tonic-gate /*
17680Sstevel@tonic-gate  * pack_change_state_request:
17690Sstevel@tonic-gate  *
17700Sstevel@tonic-gate  * Handle packing a change state request message.
17710Sstevel@tonic-gate  */
17720Sstevel@tonic-gate static int
17730Sstevel@tonic-gate pack_change_state_request(change_state_params_t *params, char **buf,
17740Sstevel@tonic-gate     int *buf_size)
17750Sstevel@tonic-gate {
17760Sstevel@tonic-gate 	int				i;
17770Sstevel@tonic-gate 	char				*bufptr;
17780Sstevel@tonic-gate 	rdr_change_state_t		change_state_data;
17790Sstevel@tonic-gate 	rdr_variable_message_info_t	var_msg_info;
17800Sstevel@tonic-gate 
17810Sstevel@tonic-gate 
17820Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
17830Sstevel@tonic-gate 		return (RDR_ERROR);
17840Sstevel@tonic-gate 	}
17850Sstevel@tonic-gate 
17860Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
17870Sstevel@tonic-gate 
17880Sstevel@tonic-gate 	/*
17890Sstevel@tonic-gate 	 * Set variable length fields and make a call to partially
17900Sstevel@tonic-gate 	 * pack it.
17910Sstevel@tonic-gate 	 */
17920Sstevel@tonic-gate 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
17930Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
17940Sstevel@tonic-gate 		return (RDR_ERROR);
17950Sstevel@tonic-gate 	}
17960Sstevel@tonic-gate 	if (find_options_sizes(params->options, &var_msg_info)) {
17970Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
17980Sstevel@tonic-gate 		return (RDR_ERROR);
17990Sstevel@tonic-gate 	}
18000Sstevel@tonic-gate 
18010Sstevel@tonic-gate 	/*
18020Sstevel@tonic-gate 	 * Collect size info specific to the change_state request
18030Sstevel@tonic-gate 	 * message and allocate a buffer
18040Sstevel@tonic-gate 	 */
18050Sstevel@tonic-gate 	*buf_size = sizeof (rdr_change_state_t);
18060Sstevel@tonic-gate 	*buf_size += var_msg_info.ap_id_int_size;
18070Sstevel@tonic-gate 	*buf_size += var_msg_info.ap_id_char_size;
18080Sstevel@tonic-gate 	*buf_size += var_msg_info.options_strlen;
18090Sstevel@tonic-gate 	*buf_size += var_msg_info.options_pad_sz;
18100Sstevel@tonic-gate 
18110Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
18120Sstevel@tonic-gate 	if (*buf == NULL) {
18130Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
18140Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
18150Sstevel@tonic-gate 	}
18160Sstevel@tonic-gate 
18170Sstevel@tonic-gate 	/*
18180Sstevel@tonic-gate 	 * Set fixed address labels by name
18190Sstevel@tonic-gate 	 */
18200Sstevel@tonic-gate 	change_state_data.num_ap_ids = params->num_ap_ids;
18210Sstevel@tonic-gate 	change_state_data.ap_id_char_size = var_msg_info.ap_id_char_size;
18220Sstevel@tonic-gate 	change_state_data.options_size = var_msg_info.options_strlen +
18230Sstevel@tonic-gate 	    var_msg_info.options_pad_sz;
18240Sstevel@tonic-gate 
18250Sstevel@tonic-gate 	if (params->confp != NULL) {
18260Sstevel@tonic-gate 		change_state_data.confirm_callback_id =
18270Sstevel@tonic-gate 		    (unsigned long)params->confp->confirm;
18280Sstevel@tonic-gate 		change_state_data.confirm_appdata_ptr =
18290Sstevel@tonic-gate 		    (unsigned long)params->confp->appdata_ptr;
18300Sstevel@tonic-gate 	} else {
18310Sstevel@tonic-gate 		change_state_data.confirm_callback_id = 0;
18320Sstevel@tonic-gate 		change_state_data.confirm_appdata_ptr = 0;
18330Sstevel@tonic-gate 	}
18340Sstevel@tonic-gate 	if (params->msgp != NULL) {
18350Sstevel@tonic-gate 		change_state_data.msg_callback_id =
18360Sstevel@tonic-gate 		    (unsigned long)params->msgp->message_routine;
18370Sstevel@tonic-gate 		change_state_data.msg_appdata_ptr =
18380Sstevel@tonic-gate 		    (unsigned long)params->msgp->appdata_ptr;
18390Sstevel@tonic-gate 	} else {
18400Sstevel@tonic-gate 		change_state_data.msg_callback_id = 0;
18410Sstevel@tonic-gate 		change_state_data.msg_appdata_ptr = 0;
18420Sstevel@tonic-gate 	}
18430Sstevel@tonic-gate 
18440Sstevel@tonic-gate 	change_state_data.flags = params->flags;
18450Sstevel@tonic-gate 	change_state_data.timeval = params->timeval;
18460Sstevel@tonic-gate 	change_state_data.state_change_cmd = params->state_change;
18470Sstevel@tonic-gate 	if (params->errstring != NULL) {
18480Sstevel@tonic-gate 		change_state_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
18490Sstevel@tonic-gate 	} else {
18500Sstevel@tonic-gate 		change_state_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
18510Sstevel@tonic-gate 	}
18520Sstevel@tonic-gate 	change_state_data.retries = params->retries;
18530Sstevel@tonic-gate 
18540Sstevel@tonic-gate 	/*
18550Sstevel@tonic-gate 	 * Set variable information using memcpy
18560Sstevel@tonic-gate 	 */
18570Sstevel@tonic-gate 	bufptr = *buf;
18580Sstevel@tonic-gate 
18590Sstevel@tonic-gate 	(void) memcpy(bufptr, &change_state_data, sizeof (rdr_change_state_t));
18600Sstevel@tonic-gate 	bufptr += sizeof (rdr_change_state_t);
18610Sstevel@tonic-gate 
18620Sstevel@tonic-gate 	if (var_msg_info.ap_id_sizes != NULL) {
18630Sstevel@tonic-gate 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
18640Sstevel@tonic-gate 		    var_msg_info.ap_id_int_size);
18650Sstevel@tonic-gate 		bufptr += var_msg_info.ap_id_int_size;
18660Sstevel@tonic-gate 	}
18670Sstevel@tonic-gate 
18680Sstevel@tonic-gate 	if (var_msg_info.ap_id_chars != NULL) {
18690Sstevel@tonic-gate 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
18700Sstevel@tonic-gate 		    var_msg_info.ap_id_char_size);
18710Sstevel@tonic-gate 		bufptr += var_msg_info.ap_id_char_size;
18720Sstevel@tonic-gate 	}
18730Sstevel@tonic-gate 
18740Sstevel@tonic-gate 	if (params->options != NULL) {
18750Sstevel@tonic-gate 		(void) memcpy(bufptr, params->options,
18760Sstevel@tonic-gate 		    var_msg_info.options_strlen);
18770Sstevel@tonic-gate 		bufptr += var_msg_info.options_strlen;
18780Sstevel@tonic-gate 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
18790Sstevel@tonic-gate 			bufptr[i] = 0;
18800Sstevel@tonic-gate 		}
18810Sstevel@tonic-gate 		bufptr += var_msg_info.options_pad_sz;
18820Sstevel@tonic-gate 	}
18830Sstevel@tonic-gate 
18840Sstevel@tonic-gate 	cleanup_variable_ap_id_info(&var_msg_info);
18850Sstevel@tonic-gate 
18860Sstevel@tonic-gate 	return (RDR_OK);
18870Sstevel@tonic-gate }
18880Sstevel@tonic-gate 
18890Sstevel@tonic-gate 
18900Sstevel@tonic-gate /*
18910Sstevel@tonic-gate  * unpack_change_state_request:
18920Sstevel@tonic-gate  *
18930Sstevel@tonic-gate  * Handle unpacking a change state request message.
18940Sstevel@tonic-gate  */
18950Sstevel@tonic-gate static int
18960Sstevel@tonic-gate unpack_change_state_request(change_state_params_t *params, const char *buf)
18970Sstevel@tonic-gate {
18980Sstevel@tonic-gate 	char				*bufptr;
18990Sstevel@tonic-gate 	rdr_variable_message_info_t 	var_msg_info;
19000Sstevel@tonic-gate 	rdr_change_state_t		change_state_data;
19010Sstevel@tonic-gate 
19020Sstevel@tonic-gate 
19030Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
19040Sstevel@tonic-gate 		return (RDR_ERROR);
19050Sstevel@tonic-gate 	}
19060Sstevel@tonic-gate 
19070Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
19080Sstevel@tonic-gate 
19090Sstevel@tonic-gate 	bufptr = (char *)buf;
19100Sstevel@tonic-gate 	(void) memcpy(&change_state_data, bufptr, sizeof (rdr_change_state_t));
19110Sstevel@tonic-gate 	bufptr += sizeof (rdr_change_state_t);
19120Sstevel@tonic-gate 
19130Sstevel@tonic-gate 	/*
19140Sstevel@tonic-gate 	 * handle getting the ap_ids
19150Sstevel@tonic-gate 	 */
19160Sstevel@tonic-gate 	var_msg_info.ap_id_char_size = change_state_data.ap_id_char_size;
19170Sstevel@tonic-gate 	if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
19180Sstevel@tonic-gate 	    change_state_data.num_ap_ids, &var_msg_info, bufptr)) {
19190Sstevel@tonic-gate 		return (RDR_ERROR);
19200Sstevel@tonic-gate 	}
19210Sstevel@tonic-gate 	bufptr += var_msg_info.ap_id_int_size;
19220Sstevel@tonic-gate 	bufptr += var_msg_info.ap_id_char_size;
19230Sstevel@tonic-gate 
19240Sstevel@tonic-gate 	/*
19250Sstevel@tonic-gate 	 * handle getting the options
19260Sstevel@tonic-gate 	 */
19270Sstevel@tonic-gate 	if (get_string_from_buf(&(params->options),
19280Sstevel@tonic-gate 	    change_state_data.options_size, bufptr)) {
19290Sstevel@tonic-gate 		return (RDR_ERROR);
19300Sstevel@tonic-gate 	}
19310Sstevel@tonic-gate 	bufptr += change_state_data.options_size;
19320Sstevel@tonic-gate 
19330Sstevel@tonic-gate 	/*
19340Sstevel@tonic-gate 	 * Set fixed address labels by name
19350Sstevel@tonic-gate 	 */
19360Sstevel@tonic-gate 	params->state_change = (cfga_cmd_t)change_state_data.state_change_cmd;
19370Sstevel@tonic-gate 	params->num_ap_ids = change_state_data.num_ap_ids;
19380Sstevel@tonic-gate 
19390Sstevel@tonic-gate 	params->confp = (struct cfga_confirm *)
19400Sstevel@tonic-gate 	    malloc(sizeof (struct cfga_confirm));
19410Sstevel@tonic-gate 	if (params->confp == NULL) {
19420Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
19430Sstevel@tonic-gate 	}
19440Sstevel@tonic-gate 
19450Sstevel@tonic-gate 	/* set params->confp->confirm using memcpy */
19460Sstevel@tonic-gate 	(void) memcpy((void*)params->confp,
19470Sstevel@tonic-gate 	    &(change_state_data.confirm_callback_id), sizeof (unsigned long));
19480Sstevel@tonic-gate 	params->confp->appdata_ptr =
19490Sstevel@tonic-gate 	    (void*)change_state_data.confirm_appdata_ptr;
19500Sstevel@tonic-gate 
19510Sstevel@tonic-gate 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
19520Sstevel@tonic-gate 	if (params->msgp == NULL) {
19530Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
19540Sstevel@tonic-gate 	}
19550Sstevel@tonic-gate 
19560Sstevel@tonic-gate 	/* set params->msgp->message_routine using memcpy */
19570Sstevel@tonic-gate 	(void) memcpy((void*)params->msgp,
19580Sstevel@tonic-gate 	    &(change_state_data.msg_callback_id), sizeof (unsigned long));
19590Sstevel@tonic-gate 	params->msgp->appdata_ptr =
19600Sstevel@tonic-gate 	    (void*)change_state_data.msg_appdata_ptr;
19610Sstevel@tonic-gate 
19620Sstevel@tonic-gate 	if (change_state_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
19630Sstevel@tonic-gate 		params->errstring = (char **)malloc(sizeof (char *));
19640Sstevel@tonic-gate 		if (params->errstring == NULL) {
19650Sstevel@tonic-gate 			return (RDR_MEM_ALLOC);
19660Sstevel@tonic-gate 		}
19670Sstevel@tonic-gate 		*(params->errstring) = NULL;
19680Sstevel@tonic-gate 	} else {	/* error_msg_ctl == RDR_DONT_GENERATE_ERR_MSGS */
19690Sstevel@tonic-gate 		params->errstring = NULL;
19700Sstevel@tonic-gate 	}
19710Sstevel@tonic-gate 	params->flags = change_state_data.flags;
19720Sstevel@tonic-gate 	params->timeval = change_state_data.timeval;
19730Sstevel@tonic-gate 	params->retries = change_state_data.retries;
19740Sstevel@tonic-gate 
19750Sstevel@tonic-gate 	return (RDR_OK);
19760Sstevel@tonic-gate }
19770Sstevel@tonic-gate 
19780Sstevel@tonic-gate 
19790Sstevel@tonic-gate /*
19800Sstevel@tonic-gate  * pack_change_state_reply:
19810Sstevel@tonic-gate  *
19820Sstevel@tonic-gate  * Handle packing a change state reply message.
19830Sstevel@tonic-gate  */
19840Sstevel@tonic-gate static int
19850Sstevel@tonic-gate pack_change_state_reply(change_state_params_t *params, char **buf,
19860Sstevel@tonic-gate     int *buf_size)
19870Sstevel@tonic-gate {
19880Sstevel@tonic-gate 	int				i;
19890Sstevel@tonic-gate 	char				*bufptr;
19900Sstevel@tonic-gate 	rdr_change_state_reply_t	change_state_data;
19910Sstevel@tonic-gate 	rdr_variable_message_info_t 	var_msg_info;
19920Sstevel@tonic-gate 
19930Sstevel@tonic-gate 
19940Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
19950Sstevel@tonic-gate 
19960Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
19970Sstevel@tonic-gate 		return (RDR_ERROR);
19980Sstevel@tonic-gate 	}
19990Sstevel@tonic-gate 
20000Sstevel@tonic-gate 	/*
20010Sstevel@tonic-gate 	 * Set variable length fields (size info)
20020Sstevel@tonic-gate 	 */
20030Sstevel@tonic-gate 	if (find_errstring_sizes(params->errstring, &var_msg_info)) {
20040Sstevel@tonic-gate 		return (RDR_ERROR);
20050Sstevel@tonic-gate 	}
20060Sstevel@tonic-gate 
20070Sstevel@tonic-gate 	/*
20080Sstevel@tonic-gate 	 * Collect size info specific to the change_state reply
20090Sstevel@tonic-gate 	 * message and allocate a buffer
20100Sstevel@tonic-gate 	 */
20110Sstevel@tonic-gate 	*buf_size = sizeof (rdr_change_state_reply_t);
20120Sstevel@tonic-gate 	*buf_size += var_msg_info.errstring_strlen;
20130Sstevel@tonic-gate 	*buf_size += var_msg_info.errstring_pad_sz;
20140Sstevel@tonic-gate 
20150Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
20160Sstevel@tonic-gate 	if (*buf == NULL) {
20170Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
20180Sstevel@tonic-gate 	}
20190Sstevel@tonic-gate 
20200Sstevel@tonic-gate 	/*
20210Sstevel@tonic-gate 	 * Set fixed address labels by name
20220Sstevel@tonic-gate 	 */
20230Sstevel@tonic-gate 	change_state_data.errstring_size = var_msg_info.errstring_strlen +
20240Sstevel@tonic-gate 	    var_msg_info.errstring_pad_sz;
20250Sstevel@tonic-gate 
20260Sstevel@tonic-gate 	/*
20270Sstevel@tonic-gate 	 * Set variable information using memcpy
20280Sstevel@tonic-gate 	 */
20290Sstevel@tonic-gate 	bufptr = *buf;
20300Sstevel@tonic-gate 
20310Sstevel@tonic-gate 	(void) memcpy(bufptr, &change_state_data,
20320Sstevel@tonic-gate 	    sizeof (rdr_change_state_reply_t));
20330Sstevel@tonic-gate 	bufptr += sizeof (rdr_change_state_reply_t);
20340Sstevel@tonic-gate 
20350Sstevel@tonic-gate 	if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
20360Sstevel@tonic-gate 		(void) memcpy(bufptr, *(params->errstring),
20370Sstevel@tonic-gate 		    var_msg_info.errstring_strlen);
20380Sstevel@tonic-gate 		bufptr += var_msg_info.errstring_strlen;
20390Sstevel@tonic-gate 		for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
20400Sstevel@tonic-gate 			bufptr[i] = 0;
20410Sstevel@tonic-gate 		}
20420Sstevel@tonic-gate 		bufptr += var_msg_info.errstring_pad_sz;
20430Sstevel@tonic-gate 	}
20440Sstevel@tonic-gate 
20450Sstevel@tonic-gate 	return (RDR_OK);
20460Sstevel@tonic-gate }
20470Sstevel@tonic-gate 
20480Sstevel@tonic-gate 
20490Sstevel@tonic-gate /*
20500Sstevel@tonic-gate  * unpack_change_state_reply:
20510Sstevel@tonic-gate  *
20520Sstevel@tonic-gate  * Handle unpacking a change state reply message.
20530Sstevel@tonic-gate  */
20540Sstevel@tonic-gate static int
20550Sstevel@tonic-gate unpack_change_state_reply(change_state_params_t *params, const char *buf)
20560Sstevel@tonic-gate {
20570Sstevel@tonic-gate 	char				*bufptr;
20580Sstevel@tonic-gate 	rdr_change_state_reply_t	change_state_data;
20590Sstevel@tonic-gate 
20600Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
20610Sstevel@tonic-gate 		return (RDR_ERROR);
20620Sstevel@tonic-gate 	}
20630Sstevel@tonic-gate 
20640Sstevel@tonic-gate 	bufptr = (char *)buf;
20650Sstevel@tonic-gate 	(void) memcpy(&change_state_data, bufptr,
20660Sstevel@tonic-gate 	    sizeof (rdr_change_state_reply_t));
20670Sstevel@tonic-gate 	bufptr += sizeof (rdr_change_state_reply_t);
20680Sstevel@tonic-gate 
20690Sstevel@tonic-gate 	/*
20700Sstevel@tonic-gate 	 * handle getting the errstring
20710Sstevel@tonic-gate 	 */
20720Sstevel@tonic-gate 	params->errstring = (char **)malloc(sizeof (char *));
20730Sstevel@tonic-gate 	if (params->errstring == NULL) {
20740Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
20750Sstevel@tonic-gate 	}
20760Sstevel@tonic-gate 	if (get_string_from_buf(params->errstring,
20770Sstevel@tonic-gate 	    change_state_data.errstring_size, bufptr)) {
20780Sstevel@tonic-gate 		return (RDR_ERROR);
20790Sstevel@tonic-gate 	}
20800Sstevel@tonic-gate 	bufptr += change_state_data.errstring_size;
20810Sstevel@tonic-gate 
20820Sstevel@tonic-gate 	return (RDR_OK);
20830Sstevel@tonic-gate }
20840Sstevel@tonic-gate 
20850Sstevel@tonic-gate 
20860Sstevel@tonic-gate /*
20870Sstevel@tonic-gate  * pack_private_func_request:
20880Sstevel@tonic-gate  *
20890Sstevel@tonic-gate  * Handle packing a private function request message.
20900Sstevel@tonic-gate  */
20910Sstevel@tonic-gate static int
20920Sstevel@tonic-gate pack_private_func_request(private_func_params_t *params, char **buf,
20930Sstevel@tonic-gate     int *buf_size)
20940Sstevel@tonic-gate {
20950Sstevel@tonic-gate 	int				i;
20960Sstevel@tonic-gate 	char				*bufptr;
20970Sstevel@tonic-gate 	rdr_private_func_t		private_func_data;
20980Sstevel@tonic-gate 	rdr_variable_message_info_t	var_msg_info;
20990Sstevel@tonic-gate 
21000Sstevel@tonic-gate 
21010Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
21020Sstevel@tonic-gate 		return (RDR_ERROR);
21030Sstevel@tonic-gate 	}
21040Sstevel@tonic-gate 
21050Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
21060Sstevel@tonic-gate 
21070Sstevel@tonic-gate 	/*
21080Sstevel@tonic-gate 	 * Set variable length fields and make a call to partially
21090Sstevel@tonic-gate 	 * pack it.
21100Sstevel@tonic-gate 	 */
21110Sstevel@tonic-gate 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
21120Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
21130Sstevel@tonic-gate 		return (RDR_ERROR);
21140Sstevel@tonic-gate 	}
21150Sstevel@tonic-gate 	if (find_options_sizes(params->options, &var_msg_info)) {
21160Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
21170Sstevel@tonic-gate 		return (RDR_ERROR);
21180Sstevel@tonic-gate 	}
21190Sstevel@tonic-gate 	if (find_function_sizes(params->function, &var_msg_info)) {
21200Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
21210Sstevel@tonic-gate 		return (RDR_ERROR);
21220Sstevel@tonic-gate 	}
21230Sstevel@tonic-gate 
21240Sstevel@tonic-gate 	/*
21250Sstevel@tonic-gate 	 * Collect size info specific to the private_func request
21260Sstevel@tonic-gate 	 * message and allocate a buffer
21270Sstevel@tonic-gate 	 */
21280Sstevel@tonic-gate 	*buf_size = sizeof (rdr_private_func_t);
21290Sstevel@tonic-gate 	*buf_size += var_msg_info.ap_id_int_size;
21300Sstevel@tonic-gate 	*buf_size += var_msg_info.ap_id_char_size;
21310Sstevel@tonic-gate 	*buf_size += var_msg_info.options_strlen;
21320Sstevel@tonic-gate 	*buf_size += var_msg_info.options_pad_sz;
21330Sstevel@tonic-gate 	*buf_size += var_msg_info.function_strlen;
21340Sstevel@tonic-gate 	*buf_size += var_msg_info.function_pad_sz;
21350Sstevel@tonic-gate 
21360Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
21370Sstevel@tonic-gate 	if (*buf == NULL) {
21380Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
21390Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
21400Sstevel@tonic-gate 	}
21410Sstevel@tonic-gate 
21420Sstevel@tonic-gate 	/*
21430Sstevel@tonic-gate 	 * Set fixed address labels by name
21440Sstevel@tonic-gate 	 */
21450Sstevel@tonic-gate 	private_func_data.num_ap_ids = params->num_ap_ids;
21460Sstevel@tonic-gate 	private_func_data.ap_id_char_size = var_msg_info.ap_id_char_size;
21470Sstevel@tonic-gate 	private_func_data.options_size = var_msg_info.options_strlen +
21480Sstevel@tonic-gate 	    var_msg_info.options_pad_sz;
21490Sstevel@tonic-gate 	private_func_data.function_size = var_msg_info.function_strlen +
21500Sstevel@tonic-gate 	    var_msg_info.function_pad_sz;
21510Sstevel@tonic-gate 
21520Sstevel@tonic-gate 	if (params->confp != NULL) {
21530Sstevel@tonic-gate 		private_func_data.confirm_callback_id =
21540Sstevel@tonic-gate 		    (unsigned long)params->confp->confirm;
21550Sstevel@tonic-gate 		private_func_data.confirm_appdata_ptr =
21560Sstevel@tonic-gate 		    (unsigned long)params->confp->appdata_ptr;
21570Sstevel@tonic-gate 	} else {
21580Sstevel@tonic-gate 		private_func_data.confirm_callback_id = 0;
21590Sstevel@tonic-gate 		private_func_data.confirm_appdata_ptr = 0;
21600Sstevel@tonic-gate 	}
21610Sstevel@tonic-gate 	if (params->msgp != NULL) {
21620Sstevel@tonic-gate 		private_func_data.msg_callback_id =
21630Sstevel@tonic-gate 		    (unsigned long)params->msgp->message_routine;
21640Sstevel@tonic-gate 		private_func_data.msg_appdata_ptr =
21650Sstevel@tonic-gate 		    (unsigned long)params->msgp->appdata_ptr;
21660Sstevel@tonic-gate 	} else {
21670Sstevel@tonic-gate 		private_func_data.msg_callback_id = 0;
21680Sstevel@tonic-gate 		private_func_data.msg_appdata_ptr = 0;
21690Sstevel@tonic-gate 	}
21700Sstevel@tonic-gate 
21710Sstevel@tonic-gate 	private_func_data.flags = params->flags;
21720Sstevel@tonic-gate 
21730Sstevel@tonic-gate 	if (params->errstring != NULL) {
21740Sstevel@tonic-gate 		private_func_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
21750Sstevel@tonic-gate 	} else {
21760Sstevel@tonic-gate 		private_func_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
21770Sstevel@tonic-gate 	}
21780Sstevel@tonic-gate 
21790Sstevel@tonic-gate 	/*
21800Sstevel@tonic-gate 	 * Set variable information using memcpy
21810Sstevel@tonic-gate 	 */
21820Sstevel@tonic-gate 	bufptr = *buf;
21830Sstevel@tonic-gate 
21840Sstevel@tonic-gate 	(void) memcpy(bufptr, &private_func_data, sizeof (rdr_private_func_t));
21850Sstevel@tonic-gate 	bufptr += sizeof (rdr_private_func_t);
21860Sstevel@tonic-gate 
21870Sstevel@tonic-gate 	if (var_msg_info.ap_id_sizes != NULL) {
21880Sstevel@tonic-gate 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
21890Sstevel@tonic-gate 		    var_msg_info.ap_id_int_size);
21900Sstevel@tonic-gate 		bufptr += var_msg_info.ap_id_int_size;
21910Sstevel@tonic-gate 	}
21920Sstevel@tonic-gate 
21930Sstevel@tonic-gate 	if (var_msg_info.ap_id_chars != NULL) {
21940Sstevel@tonic-gate 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
21950Sstevel@tonic-gate 		    var_msg_info.ap_id_char_size);
21960Sstevel@tonic-gate 		bufptr += var_msg_info.ap_id_char_size;
21970Sstevel@tonic-gate 	}
21980Sstevel@tonic-gate 
21990Sstevel@tonic-gate 	if (params->options != NULL) {
22000Sstevel@tonic-gate 		(void) memcpy(bufptr, params->options,
22010Sstevel@tonic-gate 		    var_msg_info.options_strlen);
22020Sstevel@tonic-gate 		bufptr += var_msg_info.options_strlen;
22030Sstevel@tonic-gate 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
22040Sstevel@tonic-gate 			bufptr[i] = 0;
22050Sstevel@tonic-gate 		}
22060Sstevel@tonic-gate 		bufptr += var_msg_info.options_pad_sz;
22070Sstevel@tonic-gate 	}
22080Sstevel@tonic-gate 
22090Sstevel@tonic-gate 	if (params->function != NULL) {
22100Sstevel@tonic-gate 		(void) memcpy(bufptr, params->function,
22110Sstevel@tonic-gate 		    var_msg_info.function_strlen);
22120Sstevel@tonic-gate 		bufptr += var_msg_info.function_strlen;
22130Sstevel@tonic-gate 		for (i = 0; i < var_msg_info.function_pad_sz; i++) {
22140Sstevel@tonic-gate 			bufptr[i] = 0;
22150Sstevel@tonic-gate 		}
22160Sstevel@tonic-gate 		bufptr += var_msg_info.function_pad_sz;
22170Sstevel@tonic-gate 	}
22180Sstevel@tonic-gate 
22190Sstevel@tonic-gate 	cleanup_variable_ap_id_info(&var_msg_info);
22200Sstevel@tonic-gate 
22210Sstevel@tonic-gate 	return (RDR_OK);
22220Sstevel@tonic-gate }
22230Sstevel@tonic-gate 
22240Sstevel@tonic-gate 
22250Sstevel@tonic-gate /*
22260Sstevel@tonic-gate  * unpack_private_func_request:
22270Sstevel@tonic-gate  *
22280Sstevel@tonic-gate  * Handle unpacking a private function request message.
22290Sstevel@tonic-gate  */
22300Sstevel@tonic-gate static int
22310Sstevel@tonic-gate unpack_private_func_request(private_func_params_t *params, const char *buf)
22320Sstevel@tonic-gate {
22330Sstevel@tonic-gate 	char				*bufptr;
22340Sstevel@tonic-gate 	rdr_variable_message_info_t 	var_msg_info;
22350Sstevel@tonic-gate 	rdr_private_func_t		private_func_data;
22360Sstevel@tonic-gate 
22370Sstevel@tonic-gate 
22380Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
22390Sstevel@tonic-gate 
22400Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
22410Sstevel@tonic-gate 		return (RDR_ERROR);
22420Sstevel@tonic-gate 	}
22430Sstevel@tonic-gate 
22440Sstevel@tonic-gate 	bufptr = (char *)buf;
22450Sstevel@tonic-gate 	(void) memcpy(&private_func_data, bufptr, sizeof (rdr_private_func_t));
22460Sstevel@tonic-gate 	bufptr += sizeof (rdr_private_func_t);
22470Sstevel@tonic-gate 
22480Sstevel@tonic-gate 	/*
22490Sstevel@tonic-gate 	 * handle getting the ap_ids
22500Sstevel@tonic-gate 	 */
22510Sstevel@tonic-gate 	var_msg_info.ap_id_char_size = private_func_data.ap_id_char_size;
22520Sstevel@tonic-gate 	if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
22530Sstevel@tonic-gate 	    private_func_data.num_ap_ids, &var_msg_info, bufptr)) {
22540Sstevel@tonic-gate 		return (RDR_ERROR);
22550Sstevel@tonic-gate 	}
22560Sstevel@tonic-gate 	bufptr += var_msg_info.ap_id_int_size;
22570Sstevel@tonic-gate 	bufptr += var_msg_info.ap_id_char_size;
22580Sstevel@tonic-gate 
22590Sstevel@tonic-gate 	/*
22600Sstevel@tonic-gate 	 * handle getting the options and function
22610Sstevel@tonic-gate 	 */
22620Sstevel@tonic-gate 	if (get_string_from_buf(&(params->options),
22630Sstevel@tonic-gate 	    private_func_data.options_size, bufptr)) {
22640Sstevel@tonic-gate 		return (RDR_ERROR);
22650Sstevel@tonic-gate 	}
22660Sstevel@tonic-gate 	bufptr += private_func_data.options_size;
22670Sstevel@tonic-gate 
22680Sstevel@tonic-gate 	if (get_string_from_buf(&(params->function),
22690Sstevel@tonic-gate 	    private_func_data.function_size, bufptr)) {
22700Sstevel@tonic-gate 		return (RDR_ERROR);
22710Sstevel@tonic-gate 	}
22720Sstevel@tonic-gate 	bufptr += private_func_data.function_size;
22730Sstevel@tonic-gate 
22740Sstevel@tonic-gate 	/*
22750Sstevel@tonic-gate 	 * Set fixed address labels by name
22760Sstevel@tonic-gate 	 */
22770Sstevel@tonic-gate 	params->num_ap_ids = private_func_data.num_ap_ids;
22780Sstevel@tonic-gate 
22790Sstevel@tonic-gate 	params->confp = (struct cfga_confirm *)
22800Sstevel@tonic-gate 	    malloc(sizeof (struct cfga_confirm));
22810Sstevel@tonic-gate 	if (params->confp == NULL) {
22820Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
22830Sstevel@tonic-gate 	}
22840Sstevel@tonic-gate 
22850Sstevel@tonic-gate 	/* set params->confp->confirm using memcpy */
22860Sstevel@tonic-gate 	(void) memcpy((void*)params->confp,
22870Sstevel@tonic-gate 	    &(private_func_data.confirm_callback_id), sizeof (unsigned long));
22880Sstevel@tonic-gate 	params->confp->appdata_ptr =
22890Sstevel@tonic-gate 	    (void*)private_func_data.confirm_appdata_ptr;
22900Sstevel@tonic-gate 
22910Sstevel@tonic-gate 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
22920Sstevel@tonic-gate 	if (params->msgp == NULL) {
22930Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
22940Sstevel@tonic-gate 	}
22950Sstevel@tonic-gate 
22960Sstevel@tonic-gate 	/* set params->msgp->message_routine using memcpy */
22970Sstevel@tonic-gate 	(void) memcpy((void*)params->msgp,
22980Sstevel@tonic-gate 	    &(private_func_data.msg_callback_id), sizeof (unsigned long));
22990Sstevel@tonic-gate 	params->msgp->appdata_ptr =
23000Sstevel@tonic-gate 	    (void*)private_func_data.msg_appdata_ptr;
23010Sstevel@tonic-gate 
23020Sstevel@tonic-gate 	if (private_func_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
23030Sstevel@tonic-gate 		params->errstring = (char **)malloc(sizeof (char *));
23040Sstevel@tonic-gate 		if (params->errstring == NULL) {
23050Sstevel@tonic-gate 			return (RDR_MEM_ALLOC);
23060Sstevel@tonic-gate 		}
23070Sstevel@tonic-gate 		*(params->errstring) = NULL;
23080Sstevel@tonic-gate 	} else {	/* error_msg_ctl == RDR_DONT_GENERATE_ERR_MSGS */
23090Sstevel@tonic-gate 		params->errstring = NULL;
23100Sstevel@tonic-gate 	}
23110Sstevel@tonic-gate 	params->flags = private_func_data.flags;
23120Sstevel@tonic-gate 
23130Sstevel@tonic-gate 	return (RDR_OK);
23140Sstevel@tonic-gate }
23150Sstevel@tonic-gate 
23160Sstevel@tonic-gate 
23170Sstevel@tonic-gate /*
23180Sstevel@tonic-gate  * pack_private_func_reply:
23190Sstevel@tonic-gate  *
23200Sstevel@tonic-gate  * Handle packing a private function reply message.
23210Sstevel@tonic-gate  */
23220Sstevel@tonic-gate static int
23230Sstevel@tonic-gate pack_private_func_reply(private_func_params_t *params, char **buf,
23240Sstevel@tonic-gate     int *buf_size)
23250Sstevel@tonic-gate {
23260Sstevel@tonic-gate 	int				i;
23270Sstevel@tonic-gate 	char				*bufptr;
23280Sstevel@tonic-gate 	rdr_private_func_reply_t	private_func_data;
23290Sstevel@tonic-gate 	rdr_variable_message_info_t 	var_msg_info;
23300Sstevel@tonic-gate 
23310Sstevel@tonic-gate 
23320Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
23330Sstevel@tonic-gate 
23340Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
23350Sstevel@tonic-gate 		return (RDR_ERROR);
23360Sstevel@tonic-gate 	}
23370Sstevel@tonic-gate 
23380Sstevel@tonic-gate 	/*
23390Sstevel@tonic-gate 	 * Set variable length fields (size info)
23400Sstevel@tonic-gate 	 */
23410Sstevel@tonic-gate 	if (find_errstring_sizes(params->errstring, &var_msg_info)) {
23420Sstevel@tonic-gate 		return (RDR_ERROR);
23430Sstevel@tonic-gate 	}
23440Sstevel@tonic-gate 
23450Sstevel@tonic-gate 	/*
23460Sstevel@tonic-gate 	 * Collect size info specific to the private_func reply
23470Sstevel@tonic-gate 	 * message and allocate a buffer
23480Sstevel@tonic-gate 	 */
23490Sstevel@tonic-gate 	*buf_size = sizeof (rdr_private_func_reply_t);
23500Sstevel@tonic-gate 	*buf_size += var_msg_info.errstring_strlen;
23510Sstevel@tonic-gate 	*buf_size += var_msg_info.errstring_pad_sz;
23520Sstevel@tonic-gate 
23530Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
23540Sstevel@tonic-gate 	if (*buf == NULL) {
23550Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
23560Sstevel@tonic-gate 	}
23570Sstevel@tonic-gate 
23580Sstevel@tonic-gate 	/*
23590Sstevel@tonic-gate 	 * Set fixed address labels by name
23600Sstevel@tonic-gate 	 */
23610Sstevel@tonic-gate 	private_func_data.errstring_size = var_msg_info.errstring_strlen +
23620Sstevel@tonic-gate 	    var_msg_info.errstring_pad_sz;
23630Sstevel@tonic-gate 
23640Sstevel@tonic-gate 	/*
23650Sstevel@tonic-gate 	 * Set variable information using memcpy
23660Sstevel@tonic-gate 	 */
23670Sstevel@tonic-gate 	bufptr = *buf;
23680Sstevel@tonic-gate 
23690Sstevel@tonic-gate 	(void) memcpy(bufptr, &private_func_data,
23700Sstevel@tonic-gate 	    sizeof (rdr_private_func_reply_t));
23710Sstevel@tonic-gate 	bufptr += sizeof (rdr_private_func_reply_t);
23720Sstevel@tonic-gate 	if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
23730Sstevel@tonic-gate 		(void) memcpy(bufptr, *(params->errstring),
23740Sstevel@tonic-gate 		    var_msg_info.errstring_strlen);
23750Sstevel@tonic-gate 		bufptr += var_msg_info.errstring_strlen;
23760Sstevel@tonic-gate 		for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
23770Sstevel@tonic-gate 			bufptr[i] = 0;
23780Sstevel@tonic-gate 		}
23790Sstevel@tonic-gate 		bufptr += var_msg_info.errstring_pad_sz;
23800Sstevel@tonic-gate 	}
23810Sstevel@tonic-gate 
23820Sstevel@tonic-gate 	return (RDR_OK);
23830Sstevel@tonic-gate }
23840Sstevel@tonic-gate 
23850Sstevel@tonic-gate 
23860Sstevel@tonic-gate /*
23870Sstevel@tonic-gate  * unpack_private_func_reply:
23880Sstevel@tonic-gate  *
23890Sstevel@tonic-gate  * Handle unpacking a private function reply message.
23900Sstevel@tonic-gate  */
23910Sstevel@tonic-gate static int
23920Sstevel@tonic-gate unpack_private_func_reply(private_func_params_t *params, const char *buf)
23930Sstevel@tonic-gate {
23940Sstevel@tonic-gate 	char				*bufptr;
23950Sstevel@tonic-gate 	rdr_private_func_reply_t	private_func_data;
23960Sstevel@tonic-gate 
23970Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
23980Sstevel@tonic-gate 		return (RDR_ERROR);
23990Sstevel@tonic-gate 	}
24000Sstevel@tonic-gate 
24010Sstevel@tonic-gate 	bufptr = (char *)buf;
24020Sstevel@tonic-gate 	(void) memcpy(&private_func_data, bufptr,
24030Sstevel@tonic-gate 	    sizeof (rdr_private_func_reply_t));
24040Sstevel@tonic-gate 	bufptr += sizeof (rdr_private_func_reply_t);
24050Sstevel@tonic-gate 
24060Sstevel@tonic-gate 	/*
24070Sstevel@tonic-gate 	 * handle getting the errstring
24080Sstevel@tonic-gate 	 */
24090Sstevel@tonic-gate 	params->errstring = (char **)malloc(sizeof (char *));
24100Sstevel@tonic-gate 	if (params->errstring == NULL) {
24110Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
24120Sstevel@tonic-gate 	}
24130Sstevel@tonic-gate 	if (get_string_from_buf(params->errstring,
24140Sstevel@tonic-gate 	    private_func_data.errstring_size, bufptr)) {
24150Sstevel@tonic-gate 		return (RDR_ERROR);
24160Sstevel@tonic-gate 	}
24170Sstevel@tonic-gate 	bufptr += private_func_data.errstring_size;
24180Sstevel@tonic-gate 
24190Sstevel@tonic-gate 	return (RDR_OK);
24200Sstevel@tonic-gate }
24210Sstevel@tonic-gate 
24220Sstevel@tonic-gate 
24230Sstevel@tonic-gate /*
24240Sstevel@tonic-gate  * pack_test_request:
24250Sstevel@tonic-gate  *
24260Sstevel@tonic-gate  * Handle packing a test request message.
24270Sstevel@tonic-gate  */
24280Sstevel@tonic-gate static int
24290Sstevel@tonic-gate pack_test_request(test_params_t *params, char **buf, int *buf_size)
24300Sstevel@tonic-gate {
24310Sstevel@tonic-gate 	int				i;
24320Sstevel@tonic-gate 	char				*bufptr;
24330Sstevel@tonic-gate 	rdr_test_t			test_data;
24340Sstevel@tonic-gate 	rdr_variable_message_info_t	var_msg_info;
24350Sstevel@tonic-gate 
24360Sstevel@tonic-gate 
24370Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
24380Sstevel@tonic-gate 		return (RDR_ERROR);
24390Sstevel@tonic-gate 	}
24400Sstevel@tonic-gate 
24410Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
24420Sstevel@tonic-gate 
24430Sstevel@tonic-gate 	/*
24440Sstevel@tonic-gate 	 * Set variable length fields and make a call to partially
24450Sstevel@tonic-gate 	 * pack it.
24460Sstevel@tonic-gate 	 */
24470Sstevel@tonic-gate 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
24480Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
24490Sstevel@tonic-gate 		return (RDR_ERROR);
24500Sstevel@tonic-gate 	}
24510Sstevel@tonic-gate 	if (find_options_sizes(params->options, &var_msg_info)) {
24520Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
24530Sstevel@tonic-gate 		return (RDR_ERROR);
24540Sstevel@tonic-gate 	}
24550Sstevel@tonic-gate 
24560Sstevel@tonic-gate 	/*
24570Sstevel@tonic-gate 	 * Collect size info specific to the test request
24580Sstevel@tonic-gate 	 * message and allocate a buffer
24590Sstevel@tonic-gate 	 */
24600Sstevel@tonic-gate 	*buf_size = sizeof (rdr_test_t);
24610Sstevel@tonic-gate 	*buf_size += var_msg_info.ap_id_int_size;
24620Sstevel@tonic-gate 	*buf_size += var_msg_info.ap_id_char_size;
24630Sstevel@tonic-gate 	*buf_size += var_msg_info.options_strlen;
24640Sstevel@tonic-gate 	*buf_size += var_msg_info.options_pad_sz;
24650Sstevel@tonic-gate 
24660Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
24670Sstevel@tonic-gate 	if (*buf == NULL) {
24680Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
24690Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
24700Sstevel@tonic-gate 	}
24710Sstevel@tonic-gate 
24720Sstevel@tonic-gate 	/*
24730Sstevel@tonic-gate 	 * Set fixed address labels by name
24740Sstevel@tonic-gate 	 */
24750Sstevel@tonic-gate 	test_data.num_ap_ids = params->num_ap_ids;
24760Sstevel@tonic-gate 	test_data.ap_id_char_size = var_msg_info.ap_id_char_size;
24770Sstevel@tonic-gate 	test_data.options_size = var_msg_info.options_strlen +
24780Sstevel@tonic-gate 	    var_msg_info.options_pad_sz;
24790Sstevel@tonic-gate 
24800Sstevel@tonic-gate 	if (params->msgp != NULL) {
24810Sstevel@tonic-gate 		test_data.msg_callback_id =
24820Sstevel@tonic-gate 		    (unsigned long)params->msgp->message_routine;
24830Sstevel@tonic-gate 		test_data.msg_appdata_ptr =
24840Sstevel@tonic-gate 		    (unsigned long)params->msgp->appdata_ptr;
24850Sstevel@tonic-gate 	} else {
24860Sstevel@tonic-gate 		test_data.msg_callback_id = 0;
24870Sstevel@tonic-gate 		test_data.msg_appdata_ptr = 0;
24880Sstevel@tonic-gate 	}
24890Sstevel@tonic-gate 
24900Sstevel@tonic-gate 	test_data.flags = params->flags;
24910Sstevel@tonic-gate 
24920Sstevel@tonic-gate 	if (params->errstring != NULL) {
24930Sstevel@tonic-gate 		test_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
24940Sstevel@tonic-gate 	} else {
24950Sstevel@tonic-gate 		test_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
24960Sstevel@tonic-gate 	}
24970Sstevel@tonic-gate 
24980Sstevel@tonic-gate 	/*
24990Sstevel@tonic-gate 	 * Set variable information using memcpy
25000Sstevel@tonic-gate 	 */
25010Sstevel@tonic-gate 	bufptr = *buf;
25020Sstevel@tonic-gate 
25030Sstevel@tonic-gate 	(void) memcpy(bufptr, &test_data, sizeof (rdr_test_t));
25040Sstevel@tonic-gate 	bufptr += sizeof (rdr_test_t);
25050Sstevel@tonic-gate 
25060Sstevel@tonic-gate 	if (var_msg_info.ap_id_sizes != NULL) {
25070Sstevel@tonic-gate 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
25080Sstevel@tonic-gate 		    var_msg_info.ap_id_int_size);
25090Sstevel@tonic-gate 		bufptr += var_msg_info.ap_id_int_size;
25100Sstevel@tonic-gate 	}
25110Sstevel@tonic-gate 
25120Sstevel@tonic-gate 	if (var_msg_info.ap_id_chars != NULL) {
25130Sstevel@tonic-gate 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
25140Sstevel@tonic-gate 		    var_msg_info.ap_id_char_size);
25150Sstevel@tonic-gate 		bufptr += var_msg_info.ap_id_char_size;
25160Sstevel@tonic-gate 	}
25170Sstevel@tonic-gate 
25180Sstevel@tonic-gate 	if (params->options != NULL) {
25190Sstevel@tonic-gate 		(void) memcpy(bufptr, params->options,
25200Sstevel@tonic-gate 		    var_msg_info.options_strlen);
25210Sstevel@tonic-gate 		bufptr += var_msg_info.options_strlen;
25220Sstevel@tonic-gate 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
25230Sstevel@tonic-gate 			bufptr[i] = 0;
25240Sstevel@tonic-gate 		}
25250Sstevel@tonic-gate 		bufptr += var_msg_info.options_pad_sz;
25260Sstevel@tonic-gate 	}
25270Sstevel@tonic-gate 
25280Sstevel@tonic-gate 	cleanup_variable_ap_id_info(&var_msg_info);
25290Sstevel@tonic-gate 
25300Sstevel@tonic-gate 	return (RDR_OK);
25310Sstevel@tonic-gate }
25320Sstevel@tonic-gate 
25330Sstevel@tonic-gate 
25340Sstevel@tonic-gate /*
25350Sstevel@tonic-gate  * unpack_test_request:
25360Sstevel@tonic-gate  *
25370Sstevel@tonic-gate  * Handle unpacking a test request message.
25380Sstevel@tonic-gate  */
25390Sstevel@tonic-gate static int
25400Sstevel@tonic-gate unpack_test_request(test_params_t *params, const char *buf)
25410Sstevel@tonic-gate {
25420Sstevel@tonic-gate 	char				*bufptr;
25430Sstevel@tonic-gate 	rdr_variable_message_info_t 	var_msg_info;
25440Sstevel@tonic-gate 	rdr_test_t			test_data;
25450Sstevel@tonic-gate 
25460Sstevel@tonic-gate 
25470Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
25480Sstevel@tonic-gate 		return (RDR_ERROR);
25490Sstevel@tonic-gate 	}
25500Sstevel@tonic-gate 
25510Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
25520Sstevel@tonic-gate 
25530Sstevel@tonic-gate 	bufptr = (char *)buf;
25540Sstevel@tonic-gate 	(void) memcpy(&test_data, bufptr, sizeof (rdr_test_t));
25550Sstevel@tonic-gate 	bufptr += sizeof (rdr_test_t);
25560Sstevel@tonic-gate 
25570Sstevel@tonic-gate 	/*
25580Sstevel@tonic-gate 	 * handle getting the ap_ids
25590Sstevel@tonic-gate 	 */
25600Sstevel@tonic-gate 	var_msg_info.ap_id_char_size = test_data.ap_id_char_size;
25610Sstevel@tonic-gate 	if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
25620Sstevel@tonic-gate 	    test_data.num_ap_ids, &var_msg_info, bufptr)) {
25630Sstevel@tonic-gate 		return (RDR_ERROR);
25640Sstevel@tonic-gate 	}
25650Sstevel@tonic-gate 	bufptr += var_msg_info.ap_id_int_size;
25660Sstevel@tonic-gate 	bufptr += var_msg_info.ap_id_char_size;
25670Sstevel@tonic-gate 
25680Sstevel@tonic-gate 	/*
25690Sstevel@tonic-gate 	 * handle getting the options
25700Sstevel@tonic-gate 	 */
25710Sstevel@tonic-gate 	if (get_string_from_buf(&(params->options),
25720Sstevel@tonic-gate 	    test_data.options_size, bufptr)) {
25730Sstevel@tonic-gate 		return (RDR_ERROR);
25740Sstevel@tonic-gate 	}
25750Sstevel@tonic-gate 	bufptr += test_data.options_size;
25760Sstevel@tonic-gate 
25770Sstevel@tonic-gate 	/*
25780Sstevel@tonic-gate 	 * Set fixed address labels by name
25790Sstevel@tonic-gate 	 */
25800Sstevel@tonic-gate 	params->num_ap_ids = test_data.num_ap_ids;
25810Sstevel@tonic-gate 
25820Sstevel@tonic-gate 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
25830Sstevel@tonic-gate 	if (params->msgp == NULL) {
25840Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
25850Sstevel@tonic-gate 	}
25860Sstevel@tonic-gate 
25870Sstevel@tonic-gate 	/* set params->msgp->message_routine using memcpy */
25880Sstevel@tonic-gate 	(void) memcpy((void*)params->msgp,
25890Sstevel@tonic-gate 	    &(test_data.msg_callback_id), sizeof (unsigned long));
25900Sstevel@tonic-gate 	params->msgp->appdata_ptr =
25910Sstevel@tonic-gate 	    (void*)test_data.msg_appdata_ptr;
25920Sstevel@tonic-gate 
25930Sstevel@tonic-gate 	if (test_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
25940Sstevel@tonic-gate 		params->errstring = (char **)malloc(sizeof (char *));
25950Sstevel@tonic-gate 		if (params->errstring == NULL) {
25960Sstevel@tonic-gate 			return (RDR_MEM_ALLOC);
25970Sstevel@tonic-gate 		}
25980Sstevel@tonic-gate 		*(params->errstring) = NULL;
25990Sstevel@tonic-gate 	} else {	/* error_msg_ctl == RDR_DONT_GENERATE_ERR_MSGS */
26000Sstevel@tonic-gate 		params->errstring = NULL;
26010Sstevel@tonic-gate 	}
26020Sstevel@tonic-gate 	params->flags = test_data.flags;
26030Sstevel@tonic-gate 
26040Sstevel@tonic-gate 	return (RDR_OK);
26050Sstevel@tonic-gate }
26060Sstevel@tonic-gate 
26070Sstevel@tonic-gate 
26080Sstevel@tonic-gate /*
26090Sstevel@tonic-gate  * pack_test_reply:
26100Sstevel@tonic-gate  *
26110Sstevel@tonic-gate  * Handle packing a test reply message.
26120Sstevel@tonic-gate  */
26130Sstevel@tonic-gate static int
26140Sstevel@tonic-gate pack_test_reply(test_params_t *params, char **buf, int *buf_size)
26150Sstevel@tonic-gate {
26160Sstevel@tonic-gate 	int				i;
26170Sstevel@tonic-gate 	char				*bufptr;
26180Sstevel@tonic-gate 	rdr_test_reply_t		test_data;
26190Sstevel@tonic-gate 	rdr_variable_message_info_t 	var_msg_info;
26200Sstevel@tonic-gate 
26210Sstevel@tonic-gate 
26220Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
26230Sstevel@tonic-gate 		return (RDR_ERROR);
26240Sstevel@tonic-gate 	}
26250Sstevel@tonic-gate 
26260Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
26270Sstevel@tonic-gate 
26280Sstevel@tonic-gate 	/*
26290Sstevel@tonic-gate 	 * Set variable length fields (size info)
26300Sstevel@tonic-gate 	 */
26310Sstevel@tonic-gate 	if (find_errstring_sizes(params->errstring, &var_msg_info)) {
26320Sstevel@tonic-gate 		return (RDR_ERROR);
26330Sstevel@tonic-gate 	}
26340Sstevel@tonic-gate 
26350Sstevel@tonic-gate 	/*
26360Sstevel@tonic-gate 	 * Collect size info specific to the test reply
26370Sstevel@tonic-gate 	 * message and allocate a buffer
26380Sstevel@tonic-gate 	 */
26390Sstevel@tonic-gate 	*buf_size = sizeof (rdr_test_reply_t);
26400Sstevel@tonic-gate 	*buf_size += var_msg_info.errstring_strlen;
26410Sstevel@tonic-gate 	*buf_size += var_msg_info.errstring_pad_sz;
26420Sstevel@tonic-gate 
26430Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
26440Sstevel@tonic-gate 	if (*buf == NULL) {
26450Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
26460Sstevel@tonic-gate 	}
26470Sstevel@tonic-gate 
26480Sstevel@tonic-gate 	/*
26490Sstevel@tonic-gate 	 * Set fixed address labels by name
26500Sstevel@tonic-gate 	 */
26510Sstevel@tonic-gate 	test_data.errstring_size = var_msg_info.errstring_strlen +
26520Sstevel@tonic-gate 	    var_msg_info.errstring_pad_sz;
26530Sstevel@tonic-gate 
26540Sstevel@tonic-gate 	/*
26550Sstevel@tonic-gate 	 * Set variable information using memcpy
26560Sstevel@tonic-gate 	 */
26570Sstevel@tonic-gate 	bufptr = *buf;
26580Sstevel@tonic-gate 
26590Sstevel@tonic-gate 	(void) memcpy(bufptr, &test_data, sizeof (rdr_test_reply_t));
26600Sstevel@tonic-gate 	bufptr += sizeof (rdr_test_reply_t);
26610Sstevel@tonic-gate 	if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
26620Sstevel@tonic-gate 		(void) memcpy(bufptr, *(params->errstring),
26630Sstevel@tonic-gate 		    var_msg_info.errstring_strlen);
26640Sstevel@tonic-gate 		bufptr += var_msg_info.errstring_strlen;
26650Sstevel@tonic-gate 		for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
26660Sstevel@tonic-gate 			bufptr[i] = 0;
26670Sstevel@tonic-gate 		}
26680Sstevel@tonic-gate 		bufptr += var_msg_info.errstring_pad_sz;
26690Sstevel@tonic-gate 	}
26700Sstevel@tonic-gate 
26710Sstevel@tonic-gate 	return (RDR_OK);
26720Sstevel@tonic-gate }
26730Sstevel@tonic-gate 
26740Sstevel@tonic-gate 
26750Sstevel@tonic-gate /*
26760Sstevel@tonic-gate  * unpack_test_reply:
26770Sstevel@tonic-gate  *
26780Sstevel@tonic-gate  * Handle unpacking a test reply message.
26790Sstevel@tonic-gate  */
26800Sstevel@tonic-gate static int
26810Sstevel@tonic-gate unpack_test_reply(test_params_t *params, const char *buf)
26820Sstevel@tonic-gate {
26830Sstevel@tonic-gate 	char			*bufptr;
26840Sstevel@tonic-gate 	rdr_test_reply_t	test_data;
26850Sstevel@tonic-gate 
26860Sstevel@tonic-gate 
26870Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
26880Sstevel@tonic-gate 		return (RDR_ERROR);
26890Sstevel@tonic-gate 	}
26900Sstevel@tonic-gate 
26910Sstevel@tonic-gate 	bufptr = (char *)buf;
26920Sstevel@tonic-gate 	(void) memcpy(&test_data, bufptr, sizeof (rdr_test_reply_t));
26930Sstevel@tonic-gate 	bufptr += sizeof (rdr_test_reply_t);
26940Sstevel@tonic-gate 
26950Sstevel@tonic-gate 	/*
26960Sstevel@tonic-gate 	 * handle getting the errstring
26970Sstevel@tonic-gate 	 */
26980Sstevel@tonic-gate 	params->errstring = (char **)malloc(sizeof (char *));
26990Sstevel@tonic-gate 	if (params->errstring == NULL) {
27000Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
27010Sstevel@tonic-gate 	}
27020Sstevel@tonic-gate 	if (get_string_from_buf(params->errstring,
27030Sstevel@tonic-gate 	    test_data.errstring_size, bufptr)) {
27040Sstevel@tonic-gate 		return (RDR_ERROR);
27050Sstevel@tonic-gate 	}
27060Sstevel@tonic-gate 	bufptr += test_data.errstring_size;
27070Sstevel@tonic-gate 
27080Sstevel@tonic-gate 	return (RDR_OK);
27090Sstevel@tonic-gate }
27100Sstevel@tonic-gate 
27110Sstevel@tonic-gate 
27120Sstevel@tonic-gate /*
27130Sstevel@tonic-gate  * pack_list_ext_request:
27140Sstevel@tonic-gate  *
27150Sstevel@tonic-gate  * Handle packing a list request message.
27160Sstevel@tonic-gate  */
27170Sstevel@tonic-gate static int
27180Sstevel@tonic-gate pack_list_ext_request(list_ext_params_t *params, char **buf, int *buf_size)
27190Sstevel@tonic-gate {
27200Sstevel@tonic-gate 	int				i;
27210Sstevel@tonic-gate 	char				*bufptr;
27220Sstevel@tonic-gate 	rdr_list_ext_t 			list_ext_data;
27230Sstevel@tonic-gate 	rdr_variable_message_info_t 	var_msg_info;
27240Sstevel@tonic-gate 
27250Sstevel@tonic-gate 
27260Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
27270Sstevel@tonic-gate 		return (RDR_ERROR);
27280Sstevel@tonic-gate 	}
27290Sstevel@tonic-gate 
27300Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
27310Sstevel@tonic-gate 
27320Sstevel@tonic-gate 	/*
27330Sstevel@tonic-gate 	 * Set variable length fields and make a call to partially
27340Sstevel@tonic-gate 	 * pack it.
27350Sstevel@tonic-gate 	 */
27360Sstevel@tonic-gate 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
27370Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
27380Sstevel@tonic-gate 		return (RDR_ERROR);
27390Sstevel@tonic-gate 	}
27400Sstevel@tonic-gate 	if (find_options_sizes(params->options, &var_msg_info)) {
27410Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
27420Sstevel@tonic-gate 		return (RDR_ERROR);
27430Sstevel@tonic-gate 	}
27440Sstevel@tonic-gate 	if (find_listopts_sizes(params->listopts, &var_msg_info)) {
27450Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
27460Sstevel@tonic-gate 		return (RDR_ERROR);
27470Sstevel@tonic-gate 	}
27480Sstevel@tonic-gate 
27490Sstevel@tonic-gate 
27500Sstevel@tonic-gate 	/*
27510Sstevel@tonic-gate 	 * Collect size info specific to the list_ext request
27520Sstevel@tonic-gate 	 * message and allocate a buffer
27530Sstevel@tonic-gate 	 */
27540Sstevel@tonic-gate 	*buf_size = sizeof (rdr_list_ext_t);
27550Sstevel@tonic-gate 	*buf_size += var_msg_info.ap_id_int_size;
27560Sstevel@tonic-gate 	*buf_size += var_msg_info.ap_id_char_size;
27570Sstevel@tonic-gate 	*buf_size += var_msg_info.options_strlen;
27580Sstevel@tonic-gate 	*buf_size += var_msg_info.options_pad_sz;
27590Sstevel@tonic-gate 	*buf_size += var_msg_info.listopts_strlen;
27600Sstevel@tonic-gate 	*buf_size += var_msg_info.listopts_pad_sz;
27610Sstevel@tonic-gate 
27620Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
27630Sstevel@tonic-gate 	if (*buf == NULL) {
27640Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
27650Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
27660Sstevel@tonic-gate 	}
27670Sstevel@tonic-gate 
27680Sstevel@tonic-gate 	/*
27690Sstevel@tonic-gate 	 * Set fixed address labels by name
27700Sstevel@tonic-gate 	 */
27710Sstevel@tonic-gate 	list_ext_data.num_ap_ids = params->num_ap_ids;
27720Sstevel@tonic-gate 	list_ext_data.ap_id_char_size = var_msg_info.ap_id_char_size;
27730Sstevel@tonic-gate 	list_ext_data.options_size = var_msg_info.options_strlen +
27740Sstevel@tonic-gate 	    var_msg_info.options_pad_sz;
27750Sstevel@tonic-gate 	list_ext_data.listopts_size = var_msg_info.listopts_strlen +
27760Sstevel@tonic-gate 	    var_msg_info.listopts_pad_sz;
27770Sstevel@tonic-gate 	if (params->errstring != NULL) {
27780Sstevel@tonic-gate 		list_ext_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
27790Sstevel@tonic-gate 	} else {
27800Sstevel@tonic-gate 		list_ext_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
27810Sstevel@tonic-gate 	}
27820Sstevel@tonic-gate 	if ((params->num_ap_ids != 0) || (params->ap_ids != NULL)) {
27830Sstevel@tonic-gate 		list_ext_data.list_msg_ctl = RDR_LIST_ONLY_PARAM_APS;
27840Sstevel@tonic-gate 	} else {
27850Sstevel@tonic-gate 		list_ext_data.list_msg_ctl = RDR_LIST_ALL_APS;
27860Sstevel@tonic-gate 	}
27870Sstevel@tonic-gate 	list_ext_data.flags = params->flags;
27880Sstevel@tonic-gate 	list_ext_data.permissions = params->permissions;
27890Sstevel@tonic-gate 
27900Sstevel@tonic-gate 	/*
27910Sstevel@tonic-gate 	 * Set variable information using memcpy
27920Sstevel@tonic-gate 	 */
27930Sstevel@tonic-gate 	bufptr = *buf;
27940Sstevel@tonic-gate 
27950Sstevel@tonic-gate 	(void) memcpy(bufptr, &list_ext_data, sizeof (rdr_list_ext_t));
27960Sstevel@tonic-gate 	bufptr += sizeof (rdr_list_ext_t);
27970Sstevel@tonic-gate 
27980Sstevel@tonic-gate 	if (var_msg_info.ap_id_sizes != NULL) {
27990Sstevel@tonic-gate 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
28000Sstevel@tonic-gate 		    var_msg_info.ap_id_int_size);
28010Sstevel@tonic-gate 		bufptr += var_msg_info.ap_id_int_size;
28020Sstevel@tonic-gate 	}
28030Sstevel@tonic-gate 
28040Sstevel@tonic-gate 	if (var_msg_info.ap_id_chars != NULL) {
28050Sstevel@tonic-gate 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
28060Sstevel@tonic-gate 		    var_msg_info.ap_id_char_size);
28070Sstevel@tonic-gate 		bufptr += var_msg_info.ap_id_char_size;
28080Sstevel@tonic-gate 	}
28090Sstevel@tonic-gate 
28100Sstevel@tonic-gate 	if (params->options != NULL) {
28110Sstevel@tonic-gate 		(void) memcpy(bufptr, params->options,
28120Sstevel@tonic-gate 		    var_msg_info.options_strlen);
28130Sstevel@tonic-gate 		bufptr += var_msg_info.options_strlen;
28140Sstevel@tonic-gate 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
28150Sstevel@tonic-gate 			bufptr[i] = 0;
28160Sstevel@tonic-gate 		}
28170Sstevel@tonic-gate 		bufptr += var_msg_info.options_pad_sz;
28180Sstevel@tonic-gate 	}
28190Sstevel@tonic-gate 
28200Sstevel@tonic-gate 	if (params->listopts != NULL) {
28210Sstevel@tonic-gate 		(void) memcpy(bufptr, params->listopts,
28220Sstevel@tonic-gate 		    var_msg_info.listopts_strlen);
28230Sstevel@tonic-gate 		bufptr += var_msg_info.listopts_strlen;
28240Sstevel@tonic-gate 		for (i = 0; i < var_msg_info.listopts_pad_sz; i++) {
28250Sstevel@tonic-gate 			bufptr[i] = 0;
28260Sstevel@tonic-gate 		}
28270Sstevel@tonic-gate 		bufptr += var_msg_info.listopts_pad_sz;
28280Sstevel@tonic-gate 	}
28290Sstevel@tonic-gate 
28300Sstevel@tonic-gate 	cleanup_variable_ap_id_info(&var_msg_info);
28310Sstevel@tonic-gate 
28320Sstevel@tonic-gate 	return (RDR_OK);
28330Sstevel@tonic-gate }
28340Sstevel@tonic-gate 
28350Sstevel@tonic-gate 
28360Sstevel@tonic-gate /*
28370Sstevel@tonic-gate  * unpack_list_ext_request:
28380Sstevel@tonic-gate  *
28390Sstevel@tonic-gate  * Handle unpacking a list request message.
28400Sstevel@tonic-gate  */
28410Sstevel@tonic-gate static int
28420Sstevel@tonic-gate unpack_list_ext_request(list_ext_params_t *params, const char *buf)
28430Sstevel@tonic-gate {
28440Sstevel@tonic-gate 	char				*bufptr;
28450Sstevel@tonic-gate 	rdr_variable_message_info_t 	var_msg_info;
28460Sstevel@tonic-gate 	rdr_list_ext_t			list_ext_data;
28470Sstevel@tonic-gate 
28480Sstevel@tonic-gate 
28490Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
28500Sstevel@tonic-gate 		return (RDR_ERROR);
28510Sstevel@tonic-gate 	}
28520Sstevel@tonic-gate 
28530Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
28540Sstevel@tonic-gate 
28550Sstevel@tonic-gate 	bufptr = (char *)buf;
28560Sstevel@tonic-gate 	(void) memcpy(&list_ext_data, bufptr, sizeof (rdr_list_ext_t));
28570Sstevel@tonic-gate 	bufptr += sizeof (rdr_list_ext_t);
28580Sstevel@tonic-gate 
28590Sstevel@tonic-gate 	/*
28600Sstevel@tonic-gate 	 * handle getting the ap_ids
28610Sstevel@tonic-gate 	 */
28620Sstevel@tonic-gate 	var_msg_info.ap_id_char_size = list_ext_data.ap_id_char_size;
28630Sstevel@tonic-gate 	if (get_ap_ids_from_buf(&(params->ap_ids), list_ext_data.num_ap_ids,
28640Sstevel@tonic-gate 	    &var_msg_info, bufptr)) {
28650Sstevel@tonic-gate 		return (RDR_ERROR);
28660Sstevel@tonic-gate 	}
28670Sstevel@tonic-gate 	bufptr += var_msg_info.ap_id_int_size;
28680Sstevel@tonic-gate 	bufptr += var_msg_info.ap_id_char_size;
28690Sstevel@tonic-gate 
28700Sstevel@tonic-gate 	/*
28710Sstevel@tonic-gate 	 * handle getting the options
28720Sstevel@tonic-gate 	 */
28730Sstevel@tonic-gate 	if (get_string_from_buf(&(params->options),
28740Sstevel@tonic-gate 	    list_ext_data.options_size, bufptr)) {
28750Sstevel@tonic-gate 		return (RDR_ERROR);
28760Sstevel@tonic-gate 	}
28770Sstevel@tonic-gate 	bufptr += list_ext_data.options_size;
28780Sstevel@tonic-gate 
28790Sstevel@tonic-gate 	/*
28800Sstevel@tonic-gate 	 * handle getting the listopts
28810Sstevel@tonic-gate 	 */
28820Sstevel@tonic-gate 	if (get_string_from_buf(&(params->listopts),
28830Sstevel@tonic-gate 	    list_ext_data.listopts_size, bufptr)) {
28840Sstevel@tonic-gate 		return (RDR_ERROR);
28850Sstevel@tonic-gate 	}
28860Sstevel@tonic-gate 	bufptr += list_ext_data.listopts_size;
28870Sstevel@tonic-gate 
28880Sstevel@tonic-gate 	/*
28890Sstevel@tonic-gate 	 * Set fixed address labels by name
28900Sstevel@tonic-gate 	 */
28910Sstevel@tonic-gate 	params->num_ap_ids = list_ext_data.num_ap_ids;
28920Sstevel@tonic-gate 
28930Sstevel@tonic-gate 	params->ap_id_list = (rdr_list_t **)malloc(sizeof (rdr_list_t *));
28940Sstevel@tonic-gate 	if (params->ap_id_list == NULL) {
28950Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
28960Sstevel@tonic-gate 	}
28970Sstevel@tonic-gate 	*(params->ap_id_list) = NULL;
28980Sstevel@tonic-gate 
28990Sstevel@tonic-gate 	params->nlist = (int *)malloc(sizeof (int));
29000Sstevel@tonic-gate 	if (params->nlist == NULL) {
29010Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
29020Sstevel@tonic-gate 	}
29030Sstevel@tonic-gate 	if (list_ext_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
29040Sstevel@tonic-gate 		params->errstring = (char **)malloc(sizeof (char *));
29050Sstevel@tonic-gate 		if (params->errstring == NULL) {
29060Sstevel@tonic-gate 			return (RDR_MEM_ALLOC);
29070Sstevel@tonic-gate 		}
29080Sstevel@tonic-gate 		*(params->errstring) = NULL;
29090Sstevel@tonic-gate 	} else {	/* error_msg_ctl == RDR_DONT_GENERATE_ERR_MSGS */
29100Sstevel@tonic-gate 	    params->errstring = NULL;
29110Sstevel@tonic-gate 	}
29120Sstevel@tonic-gate 	params->flags = list_ext_data.flags;
29130Sstevel@tonic-gate 	params->permissions = list_ext_data.permissions;
29140Sstevel@tonic-gate 
29150Sstevel@tonic-gate 	return (RDR_OK);
29160Sstevel@tonic-gate }
29170Sstevel@tonic-gate 
29180Sstevel@tonic-gate 
29190Sstevel@tonic-gate /*
29200Sstevel@tonic-gate  * pack_list_ext_reply:
29210Sstevel@tonic-gate  *
29220Sstevel@tonic-gate  * Handle packing a list reply message.
29230Sstevel@tonic-gate  */
29240Sstevel@tonic-gate static int
29250Sstevel@tonic-gate pack_list_ext_reply(list_ext_params_t *params, char **buf, int *buf_size)
29260Sstevel@tonic-gate {
29270Sstevel@tonic-gate 	int				i;
29280Sstevel@tonic-gate 	char				*bufptr;
29290Sstevel@tonic-gate 	rdr_list_ext_reply_t		list_ext_data;
29300Sstevel@tonic-gate 	rdr_variable_message_info_t 	var_msg_info;
29310Sstevel@tonic-gate 	int 				list_data_size;
29320Sstevel@tonic-gate 
29330Sstevel@tonic-gate 
29340Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
29350Sstevel@tonic-gate 
29360Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
29370Sstevel@tonic-gate 		return (RDR_ERROR);
29380Sstevel@tonic-gate 	}
29390Sstevel@tonic-gate 
29400Sstevel@tonic-gate 	/*
29410Sstevel@tonic-gate 	 * Set variable length fields (size info)
29420Sstevel@tonic-gate 	 */
29430Sstevel@tonic-gate 	if (find_errstring_sizes(params->errstring, &var_msg_info)) {
29440Sstevel@tonic-gate 		return (RDR_ERROR);
29450Sstevel@tonic-gate 	}
29460Sstevel@tonic-gate 
29470Sstevel@tonic-gate 	if (params->nlist == NULL) {
29480Sstevel@tonic-gate 		list_data_size = 0;
29490Sstevel@tonic-gate 	} else {
29500Sstevel@tonic-gate 		list_data_size = *(params->nlist) * sizeof (rdr_list_t);
29510Sstevel@tonic-gate 	}
29520Sstevel@tonic-gate 
29530Sstevel@tonic-gate 	/*
29540Sstevel@tonic-gate 	 * Collect size info specific to the list_ext reply
29550Sstevel@tonic-gate 	 * message and allocate a buffer
29560Sstevel@tonic-gate 	 */
29570Sstevel@tonic-gate 	*buf_size = sizeof (rdr_list_ext_reply_t);
29580Sstevel@tonic-gate 	*buf_size += list_data_size;
29590Sstevel@tonic-gate 	*buf_size += var_msg_info.errstring_strlen;
29600Sstevel@tonic-gate 	*buf_size += var_msg_info.errstring_pad_sz;
29610Sstevel@tonic-gate 
29620Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
29630Sstevel@tonic-gate 	if (*buf == NULL) {
29640Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
29650Sstevel@tonic-gate 	}
29660Sstevel@tonic-gate 
29670Sstevel@tonic-gate 	/*
29680Sstevel@tonic-gate 	 * Set fixed address labels by name
29690Sstevel@tonic-gate 	 */
29700Sstevel@tonic-gate 	list_ext_data.num_ap_ids = (params->nlist) ? *(params->nlist) : 0;
29710Sstevel@tonic-gate 	list_ext_data.errstring_size = var_msg_info.errstring_strlen +
29720Sstevel@tonic-gate 	    var_msg_info.errstring_pad_sz;
29730Sstevel@tonic-gate 
29740Sstevel@tonic-gate 	/*
29750Sstevel@tonic-gate 	 * Set variable information using memcpy
29760Sstevel@tonic-gate 	 */
29770Sstevel@tonic-gate 	bufptr = *buf;
29780Sstevel@tonic-gate 
29790Sstevel@tonic-gate 	(void) memcpy(bufptr, &list_ext_data, sizeof (rdr_list_ext_reply_t));
29800Sstevel@tonic-gate 	bufptr += sizeof (rdr_list_ext_reply_t);
29810Sstevel@tonic-gate 
29820Sstevel@tonic-gate 	if ((params->ap_id_list != NULL) && (*(params->ap_id_list) != NULL)) {
29830Sstevel@tonic-gate 		(void) memcpy(bufptr, *(params->ap_id_list), list_data_size);
29840Sstevel@tonic-gate 		bufptr += list_data_size;
29850Sstevel@tonic-gate 	} else if (list_data_size) {
29860Sstevel@tonic-gate 		/*
29870Sstevel@tonic-gate 		 * Something is out of sync. We were expecting
29880Sstevel@tonic-gate 		 * some data to copy, but instead we found a
29890Sstevel@tonic-gate 		 * NULL pointer.
29900Sstevel@tonic-gate 		 */
29910Sstevel@tonic-gate 		(void) free((void *)*buf);
29920Sstevel@tonic-gate 		*buf = NULL;
29930Sstevel@tonic-gate 		return (RDR_ERROR);
29940Sstevel@tonic-gate 	}
29950Sstevel@tonic-gate 
29960Sstevel@tonic-gate 	if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
29970Sstevel@tonic-gate 		(void) memcpy(bufptr, *(params->errstring),
29980Sstevel@tonic-gate 		    var_msg_info.errstring_strlen);
29990Sstevel@tonic-gate 		bufptr += var_msg_info.errstring_strlen;
30000Sstevel@tonic-gate 		for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
30010Sstevel@tonic-gate 			bufptr[i] = 0;
30020Sstevel@tonic-gate 		}
30030Sstevel@tonic-gate 		bufptr += var_msg_info.errstring_pad_sz;
30040Sstevel@tonic-gate 	}
30050Sstevel@tonic-gate 
30060Sstevel@tonic-gate 	return (RDR_OK);
30070Sstevel@tonic-gate }
30080Sstevel@tonic-gate 
30090Sstevel@tonic-gate 
30100Sstevel@tonic-gate /*
30110Sstevel@tonic-gate  * unpack_list_ext_reply:
30120Sstevel@tonic-gate  *
30130Sstevel@tonic-gate  * Handle unpacking a list reply message.
30140Sstevel@tonic-gate  */
30150Sstevel@tonic-gate static int
30160Sstevel@tonic-gate unpack_list_ext_reply(list_ext_params_t *params, const char *buf)
30170Sstevel@tonic-gate {
30180Sstevel@tonic-gate 	int 			list_data_size;
30190Sstevel@tonic-gate 	char 			*bufptr;
30200Sstevel@tonic-gate 	rdr_list_ext_reply_t	list_ext_data;
30210Sstevel@tonic-gate 
30220Sstevel@tonic-gate 
30230Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
30240Sstevel@tonic-gate 		return (RDR_ERROR);
30250Sstevel@tonic-gate 	}
30260Sstevel@tonic-gate 
30270Sstevel@tonic-gate 	bufptr = (char *)buf;
30280Sstevel@tonic-gate 	(void) memcpy(&list_ext_data, bufptr, sizeof (rdr_list_ext_reply_t));
30290Sstevel@tonic-gate 	bufptr += sizeof (rdr_list_ext_reply_t);
30300Sstevel@tonic-gate 
30310Sstevel@tonic-gate 	/*
30320Sstevel@tonic-gate 	 * handle getting the ap_id rcfga_list_data_t's.
30330Sstevel@tonic-gate 	 */
30340Sstevel@tonic-gate 	if (list_ext_data.num_ap_ids > 0) {
30350Sstevel@tonic-gate 		params->nlist = (int *)malloc(sizeof (int));
30360Sstevel@tonic-gate 		if (params->nlist == NULL) {
30370Sstevel@tonic-gate 			return (RDR_MEM_ALLOC);
30380Sstevel@tonic-gate 		}
30390Sstevel@tonic-gate 		*(params->nlist) = list_ext_data.num_ap_ids;
30400Sstevel@tonic-gate 		params->ap_id_list = (rdr_list_t **)
30410Sstevel@tonic-gate 		    malloc(sizeof (rdr_list_t *));
30420Sstevel@tonic-gate 		if (params->ap_id_list == NULL) {
30430Sstevel@tonic-gate 			return (RDR_MEM_ALLOC);
30440Sstevel@tonic-gate 		}
30450Sstevel@tonic-gate 		*(params->ap_id_list) = (rdr_list_t *)
30460Sstevel@tonic-gate 		malloc(sizeof (rdr_list_t) * list_ext_data.num_ap_ids);
30470Sstevel@tonic-gate 		if (*(params->ap_id_list) == NULL) {
30480Sstevel@tonic-gate 			return (RDR_MEM_ALLOC);
30490Sstevel@tonic-gate 		}
30500Sstevel@tonic-gate 		list_data_size = list_ext_data.num_ap_ids * sizeof (rdr_list_t);
30510Sstevel@tonic-gate 		(void) memcpy(*(params->ap_id_list), bufptr, list_data_size);
30520Sstevel@tonic-gate 		bufptr += list_data_size;
30530Sstevel@tonic-gate 	}
30540Sstevel@tonic-gate 
30550Sstevel@tonic-gate 	/*
30560Sstevel@tonic-gate 	 * handle getting the errstring
30570Sstevel@tonic-gate 	 */
30580Sstevel@tonic-gate 	params->errstring = (char **)malloc(sizeof (char *));
30590Sstevel@tonic-gate 	if (params->errstring == NULL) {
30600Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
30610Sstevel@tonic-gate 	}
30620Sstevel@tonic-gate 	if (get_string_from_buf(params->errstring,
30630Sstevel@tonic-gate 			list_ext_data.errstring_size, bufptr)) {
30640Sstevel@tonic-gate 		return (RDR_ERROR);
30650Sstevel@tonic-gate 	}
30660Sstevel@tonic-gate 	bufptr += list_ext_data.errstring_size;
30670Sstevel@tonic-gate 
30680Sstevel@tonic-gate 	return (RDR_OK);
30690Sstevel@tonic-gate }
30700Sstevel@tonic-gate 
30710Sstevel@tonic-gate 
30720Sstevel@tonic-gate /*
30730Sstevel@tonic-gate  * pack_help_request:
30740Sstevel@tonic-gate  *
30750Sstevel@tonic-gate  * Handle packing a help request message.
30760Sstevel@tonic-gate  */
30770Sstevel@tonic-gate static int
30780Sstevel@tonic-gate pack_help_request(help_params_t *params, char **buf, int *buf_size)
30790Sstevel@tonic-gate {
30800Sstevel@tonic-gate 	int				i;
30810Sstevel@tonic-gate 	char				*bufptr;
30820Sstevel@tonic-gate 	rdr_help_t			help_data;
30830Sstevel@tonic-gate 	rdr_variable_message_info_t	var_msg_info;
30840Sstevel@tonic-gate 
30850Sstevel@tonic-gate 
30860Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
30870Sstevel@tonic-gate 
30880Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
30890Sstevel@tonic-gate 		return (RDR_ERROR);
30900Sstevel@tonic-gate 	}
30910Sstevel@tonic-gate 
30920Sstevel@tonic-gate 	/*
30930Sstevel@tonic-gate 	 * Set variable length fields and make a call to partially
30940Sstevel@tonic-gate 	 * pack it.
30950Sstevel@tonic-gate 	 */
30960Sstevel@tonic-gate 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
30970Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
30980Sstevel@tonic-gate 		return (RDR_ERROR);
30990Sstevel@tonic-gate 	}
31000Sstevel@tonic-gate 	if (find_options_sizes(params->options, &var_msg_info)) {
31010Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
31020Sstevel@tonic-gate 		return (RDR_ERROR);
31030Sstevel@tonic-gate 	}
31040Sstevel@tonic-gate 
31050Sstevel@tonic-gate 	/*
31060Sstevel@tonic-gate 	 * Collect size info specific to the help request message and
31070Sstevel@tonic-gate 	 * and allocate a buffer
31080Sstevel@tonic-gate 	 */
31090Sstevel@tonic-gate 	*buf_size = sizeof (rdr_help_t);
31100Sstevel@tonic-gate 	*buf_size += var_msg_info.ap_id_int_size;
31110Sstevel@tonic-gate 	*buf_size += var_msg_info.ap_id_char_size;
31120Sstevel@tonic-gate 	*buf_size += var_msg_info.options_strlen;
31130Sstevel@tonic-gate 	*buf_size += var_msg_info.options_pad_sz;
31140Sstevel@tonic-gate 
31150Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
31160Sstevel@tonic-gate 	if (*buf == NULL) {
31170Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
31180Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
31190Sstevel@tonic-gate 	}
31200Sstevel@tonic-gate 
31210Sstevel@tonic-gate 	/*
31220Sstevel@tonic-gate 	 * Set fixed address labels by name
31230Sstevel@tonic-gate 	 */
31240Sstevel@tonic-gate 	help_data.num_ap_ids = params->num_ap_ids;
31250Sstevel@tonic-gate 	help_data.ap_id_char_size = var_msg_info.ap_id_char_size;
31260Sstevel@tonic-gate 	help_data.options_size = var_msg_info.options_strlen +
31270Sstevel@tonic-gate 	    var_msg_info.options_pad_sz;
31280Sstevel@tonic-gate 
31290Sstevel@tonic-gate 	if (params->msgp != NULL) {
31300Sstevel@tonic-gate 		help_data.msg_callback_id =
31310Sstevel@tonic-gate 		    (unsigned long)params->msgp->message_routine;
31320Sstevel@tonic-gate 		help_data.msg_appdata_ptr =
31330Sstevel@tonic-gate 		    (unsigned long)params->msgp->appdata_ptr;
31340Sstevel@tonic-gate 	} else {
31350Sstevel@tonic-gate 		help_data.msg_callback_id = 0;
31360Sstevel@tonic-gate 		help_data.msg_appdata_ptr = 0;
31370Sstevel@tonic-gate 	}
31380Sstevel@tonic-gate 
31390Sstevel@tonic-gate 	help_data.flags = params->flags;
31400Sstevel@tonic-gate 
31410Sstevel@tonic-gate 	/*
31420Sstevel@tonic-gate 	 * Set variable information using memcpy
31430Sstevel@tonic-gate 	 */
31440Sstevel@tonic-gate 	bufptr = *buf;
31450Sstevel@tonic-gate 
31460Sstevel@tonic-gate 	(void) memcpy(bufptr, &help_data, sizeof (rdr_help_t));
31470Sstevel@tonic-gate 	bufptr += sizeof (rdr_help_t);
31480Sstevel@tonic-gate 
31490Sstevel@tonic-gate 	if (var_msg_info.ap_id_sizes != NULL) {
31500Sstevel@tonic-gate 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
31510Sstevel@tonic-gate 		    var_msg_info.ap_id_int_size);
31520Sstevel@tonic-gate 		bufptr += var_msg_info.ap_id_int_size;
31530Sstevel@tonic-gate 	}
31540Sstevel@tonic-gate 
31550Sstevel@tonic-gate 	if (var_msg_info.ap_id_chars != NULL) {
31560Sstevel@tonic-gate 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
31570Sstevel@tonic-gate 		    var_msg_info.ap_id_char_size);
31580Sstevel@tonic-gate 		bufptr += var_msg_info.ap_id_char_size;
31590Sstevel@tonic-gate 	}
31600Sstevel@tonic-gate 
31610Sstevel@tonic-gate 	if (params->options != NULL) {
31620Sstevel@tonic-gate 		(void) memcpy(bufptr, params->options,
31630Sstevel@tonic-gate 		    var_msg_info.options_strlen);
31640Sstevel@tonic-gate 		bufptr += var_msg_info.options_strlen;
31650Sstevel@tonic-gate 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
31660Sstevel@tonic-gate 			bufptr[i] = 0;
31670Sstevel@tonic-gate 		}
31680Sstevel@tonic-gate 		bufptr += var_msg_info.options_pad_sz;
31690Sstevel@tonic-gate 	}
31700Sstevel@tonic-gate 
31710Sstevel@tonic-gate 	cleanup_variable_ap_id_info(&var_msg_info);
31720Sstevel@tonic-gate 
31730Sstevel@tonic-gate 	return (RDR_OK);
31740Sstevel@tonic-gate }
31750Sstevel@tonic-gate 
31760Sstevel@tonic-gate 
31770Sstevel@tonic-gate /*
31780Sstevel@tonic-gate  * unpack_help_request:
31790Sstevel@tonic-gate  *
31800Sstevel@tonic-gate  * Handle unpacking a help request message.
31810Sstevel@tonic-gate  */
31820Sstevel@tonic-gate static int
31830Sstevel@tonic-gate unpack_help_request(help_params_t *params, const char *buf)
31840Sstevel@tonic-gate {
31850Sstevel@tonic-gate 	char				*bufptr;
31860Sstevel@tonic-gate 	rdr_variable_message_info_t 	var_msg_info;
31870Sstevel@tonic-gate 	rdr_help_t			help_data;
31880Sstevel@tonic-gate 
31890Sstevel@tonic-gate 
31900Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
31910Sstevel@tonic-gate 		return (RDR_ERROR);
31920Sstevel@tonic-gate 	}
31930Sstevel@tonic-gate 
31940Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
31950Sstevel@tonic-gate 
31960Sstevel@tonic-gate 	bufptr = (char *)buf;
31970Sstevel@tonic-gate 	(void) memcpy(&help_data, bufptr, sizeof (rdr_help_t));
31980Sstevel@tonic-gate 	bufptr += sizeof (rdr_help_t);
31990Sstevel@tonic-gate 
32000Sstevel@tonic-gate 	/*
32010Sstevel@tonic-gate 	 * handle getting the ap_ids
32020Sstevel@tonic-gate 	 */
32030Sstevel@tonic-gate 	var_msg_info.ap_id_char_size = help_data.ap_id_char_size;
32040Sstevel@tonic-gate 	if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
32050Sstevel@tonic-gate 	    help_data.num_ap_ids, &var_msg_info, bufptr)) {
32060Sstevel@tonic-gate 		return (RDR_ERROR);
32070Sstevel@tonic-gate 	}
32080Sstevel@tonic-gate 	bufptr += var_msg_info.ap_id_int_size;
32090Sstevel@tonic-gate 	bufptr += var_msg_info.ap_id_char_size;
32100Sstevel@tonic-gate 
32110Sstevel@tonic-gate 	/*
32120Sstevel@tonic-gate 	 * handle getting the options
32130Sstevel@tonic-gate 	 */
32140Sstevel@tonic-gate 	if (get_string_from_buf(&(params->options),
32150Sstevel@tonic-gate 	    help_data.options_size, bufptr)) {
32160Sstevel@tonic-gate 		return (RDR_ERROR);
32170Sstevel@tonic-gate 	}
32180Sstevel@tonic-gate 	bufptr += help_data.options_size;
32190Sstevel@tonic-gate 
32200Sstevel@tonic-gate 	/*
32210Sstevel@tonic-gate 	 * Set fixed address labels by name
32220Sstevel@tonic-gate 	 */
32230Sstevel@tonic-gate 	params->num_ap_ids = help_data.num_ap_ids;
32240Sstevel@tonic-gate 
32250Sstevel@tonic-gate 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
32260Sstevel@tonic-gate 	if (params->msgp == NULL) {
32270Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
32280Sstevel@tonic-gate 	}
32290Sstevel@tonic-gate 
32300Sstevel@tonic-gate 	/* set params->msgp->message_routine using memcpy */
32310Sstevel@tonic-gate 	(void) memcpy((void*)params->msgp, &(help_data.msg_callback_id),
32320Sstevel@tonic-gate 	    sizeof (unsigned long));
32330Sstevel@tonic-gate 
32340Sstevel@tonic-gate 	params->msgp->appdata_ptr = (void*)help_data.msg_appdata_ptr;
32350Sstevel@tonic-gate 	params->flags = help_data.flags;
32360Sstevel@tonic-gate 
32370Sstevel@tonic-gate 	return (RDR_OK);
32380Sstevel@tonic-gate }
32390Sstevel@tonic-gate 
32400Sstevel@tonic-gate 
32410Sstevel@tonic-gate /*
32420Sstevel@tonic-gate  * pack_ap_id_cmp_request:
32430Sstevel@tonic-gate  *
32440Sstevel@tonic-gate  * Handle packing an attachment point comparison request message.
32450Sstevel@tonic-gate  */
32460Sstevel@tonic-gate static int
32470Sstevel@tonic-gate pack_ap_id_cmp_request(ap_id_cmp_params_t *params, char **buf, int *buf_size)
32480Sstevel@tonic-gate {
32490Sstevel@tonic-gate 	int			i;
32500Sstevel@tonic-gate 	char			*bufptr;
32510Sstevel@tonic-gate 	rdr_ap_id_cmp_t		ap_id_cmp_data;
32520Sstevel@tonic-gate 	int			ap_id1_strlen;
32530Sstevel@tonic-gate 	int			ap_id1_pad_sz;
32540Sstevel@tonic-gate 	int			ap_id2_strlen;
32550Sstevel@tonic-gate 	int			ap_id2_pad_sz;
32560Sstevel@tonic-gate 
32570Sstevel@tonic-gate 
32580Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
32590Sstevel@tonic-gate 		return (RDR_ERROR);
32600Sstevel@tonic-gate 	}
32610Sstevel@tonic-gate 
32620Sstevel@tonic-gate 	/*
32630Sstevel@tonic-gate 	 * Set variable length fields and make a call to partially
32640Sstevel@tonic-gate 	 * pack it.
32650Sstevel@tonic-gate 	 */
32660Sstevel@tonic-gate 	if (params->ap_log_id1 != NULL) {
32670Sstevel@tonic-gate 		ap_id1_strlen = strlen(params->ap_log_id1) + 1;
32680Sstevel@tonic-gate 		ap_id1_pad_sz = RDR_ALIGN_64_BIT -
32690Sstevel@tonic-gate 		    (ap_id1_strlen % RDR_ALIGN_64_BIT);
32700Sstevel@tonic-gate 	} else {
32710Sstevel@tonic-gate 		ap_id1_strlen = 0;
32720Sstevel@tonic-gate 		ap_id1_pad_sz = 0;
32730Sstevel@tonic-gate 	}
32740Sstevel@tonic-gate 
32750Sstevel@tonic-gate 	if (params->ap_log_id2 != NULL) {
32760Sstevel@tonic-gate 		ap_id2_strlen = strlen(params->ap_log_id2) + 1;
32770Sstevel@tonic-gate 		ap_id2_pad_sz = RDR_ALIGN_64_BIT -
32780Sstevel@tonic-gate 		    (ap_id2_strlen % RDR_ALIGN_64_BIT);
32790Sstevel@tonic-gate 	} else {
32800Sstevel@tonic-gate 		ap_id2_strlen = 0;
32810Sstevel@tonic-gate 		ap_id2_pad_sz = 0;
32820Sstevel@tonic-gate 	}
32830Sstevel@tonic-gate 
32840Sstevel@tonic-gate 	/*
32850Sstevel@tonic-gate 	 * Collect size info specific to the ap id compare request
32860Sstevel@tonic-gate 	 * message and allocate a buffer
32870Sstevel@tonic-gate 	 */
32880Sstevel@tonic-gate 	*buf_size = sizeof (rdr_ap_id_cmp_t);
32890Sstevel@tonic-gate 	*buf_size += ap_id1_strlen;
32900Sstevel@tonic-gate 	*buf_size += ap_id1_pad_sz;
32910Sstevel@tonic-gate 	*buf_size += ap_id2_strlen;
32920Sstevel@tonic-gate 	*buf_size += ap_id2_pad_sz;
32930Sstevel@tonic-gate 
32940Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
32950Sstevel@tonic-gate 	if (*buf == NULL) {
32960Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
32970Sstevel@tonic-gate 	}
32980Sstevel@tonic-gate 
32990Sstevel@tonic-gate 	/*
33000Sstevel@tonic-gate 	 * Set fixed address labels by name
33010Sstevel@tonic-gate 	 */
33020Sstevel@tonic-gate 	ap_id_cmp_data.ap_id1_size = ap_id1_strlen + ap_id1_pad_sz;
33030Sstevel@tonic-gate 	ap_id_cmp_data.ap_id2_size = ap_id2_strlen + ap_id2_pad_sz;
33040Sstevel@tonic-gate 
33050Sstevel@tonic-gate 
33060Sstevel@tonic-gate 	/*
33070Sstevel@tonic-gate 	 * Set variable information using memcpy
33080Sstevel@tonic-gate 	 */
33090Sstevel@tonic-gate 	bufptr = *buf;
33100Sstevel@tonic-gate 
33110Sstevel@tonic-gate 	(void) memcpy(bufptr, &ap_id_cmp_data, sizeof (rdr_ap_id_cmp_t));
33120Sstevel@tonic-gate 	bufptr += sizeof (rdr_ap_id_cmp_t);
33130Sstevel@tonic-gate 
33140Sstevel@tonic-gate 	if (params->ap_log_id1 != NULL) {
33150Sstevel@tonic-gate 		(void) memcpy(bufptr, params->ap_log_id1, ap_id1_strlen);
33160Sstevel@tonic-gate 		bufptr += ap_id1_strlen;
33170Sstevel@tonic-gate 		for (i = 0; i < ap_id1_pad_sz; i++) {
33180Sstevel@tonic-gate 			bufptr[i] = 0;
33190Sstevel@tonic-gate 		}
33200Sstevel@tonic-gate 		bufptr += ap_id1_pad_sz;
33210Sstevel@tonic-gate 	}
33220Sstevel@tonic-gate 
33230Sstevel@tonic-gate 	if (params->ap_log_id2 != NULL) {
33240Sstevel@tonic-gate 		(void) memcpy(bufptr, params->ap_log_id2, ap_id2_strlen);
33250Sstevel@tonic-gate 		bufptr += ap_id2_strlen;
33260Sstevel@tonic-gate 		for (i = 0; i < ap_id2_pad_sz; i++) {
33270Sstevel@tonic-gate 			bufptr[i] = 0;
33280Sstevel@tonic-gate 		}
33290Sstevel@tonic-gate 		bufptr += ap_id2_pad_sz;
33300Sstevel@tonic-gate 	}
33310Sstevel@tonic-gate 
33320Sstevel@tonic-gate 	return (RDR_OK);
33330Sstevel@tonic-gate }
33340Sstevel@tonic-gate 
33350Sstevel@tonic-gate 
33360Sstevel@tonic-gate /*
33370Sstevel@tonic-gate  * unpack_ap_id_cmp_request:
33380Sstevel@tonic-gate  *
33390Sstevel@tonic-gate  * Handle unpacking an attachment point comparison request message.
33400Sstevel@tonic-gate  */
33410Sstevel@tonic-gate static int
33420Sstevel@tonic-gate unpack_ap_id_cmp_request(ap_id_cmp_params_t *params, const char *buf)
33430Sstevel@tonic-gate {
33440Sstevel@tonic-gate 	char			*bufptr;
33450Sstevel@tonic-gate 	rdr_ap_id_cmp_t		ap_id_cmp_data;
33460Sstevel@tonic-gate 
33470Sstevel@tonic-gate 
33480Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
33490Sstevel@tonic-gate 		return (RDR_ERROR);
33500Sstevel@tonic-gate 	}
33510Sstevel@tonic-gate 
33520Sstevel@tonic-gate 	bufptr = (char *)buf;
33530Sstevel@tonic-gate 	(void) memcpy(&ap_id_cmp_data, bufptr, sizeof (rdr_ap_id_cmp_t));
33540Sstevel@tonic-gate 	bufptr += sizeof (rdr_ap_id_cmp_t);
33550Sstevel@tonic-gate 
33560Sstevel@tonic-gate 	/*
33570Sstevel@tonic-gate 	 * handle getting the cmp ap ids
33580Sstevel@tonic-gate 	 */
33590Sstevel@tonic-gate 	if (get_string_from_buf(&(params->ap_log_id1),
33600Sstevel@tonic-gate 	    ap_id_cmp_data.ap_id1_size, bufptr)) {
33610Sstevel@tonic-gate 		return (RDR_ERROR);
33620Sstevel@tonic-gate 	}
33630Sstevel@tonic-gate 	bufptr += ap_id_cmp_data.ap_id1_size;
33640Sstevel@tonic-gate 
33650Sstevel@tonic-gate 	if (get_string_from_buf(&(params->ap_log_id2),
33660Sstevel@tonic-gate 	    ap_id_cmp_data.ap_id2_size, bufptr)) {
33670Sstevel@tonic-gate 		return (RDR_ERROR);
33680Sstevel@tonic-gate 	}
33690Sstevel@tonic-gate 	bufptr += ap_id_cmp_data.ap_id2_size;
33700Sstevel@tonic-gate 
33710Sstevel@tonic-gate 	return (RDR_OK);
33720Sstevel@tonic-gate }
33730Sstevel@tonic-gate 
33740Sstevel@tonic-gate 
33750Sstevel@tonic-gate /*
33760Sstevel@tonic-gate  * pack_abort_cmd_request:
33770Sstevel@tonic-gate  *
33780Sstevel@tonic-gate  * Handle packing an abort request message.
33790Sstevel@tonic-gate  */
33800Sstevel@tonic-gate static int
33810Sstevel@tonic-gate pack_abort_cmd_request(abort_cmd_params_t *params, char **buf, int *buf_size)
33820Sstevel@tonic-gate {
33830Sstevel@tonic-gate 	rdr_abort_cmd_t		abort_cmd_data;
33840Sstevel@tonic-gate 
33850Sstevel@tonic-gate 
33860Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
33870Sstevel@tonic-gate 		return (RDR_ERROR);
33880Sstevel@tonic-gate 	}
33890Sstevel@tonic-gate 
33900Sstevel@tonic-gate 	/*
33910Sstevel@tonic-gate 	 * Collect size info specific to the abort cmd request
33920Sstevel@tonic-gate 	 * message and allocate a buffer
33930Sstevel@tonic-gate 	 */
33940Sstevel@tonic-gate 	*buf_size = sizeof (rdr_abort_cmd_t);
33950Sstevel@tonic-gate 
33960Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
33970Sstevel@tonic-gate 	if (*buf == NULL) {
33980Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
33990Sstevel@tonic-gate 	}
34000Sstevel@tonic-gate 
34010Sstevel@tonic-gate 	/*
34020Sstevel@tonic-gate 	 * Set fixed session identifier
34030Sstevel@tonic-gate 	 */
34040Sstevel@tonic-gate 	abort_cmd_data.session_id = params->session_id;
34050Sstevel@tonic-gate 
34060Sstevel@tonic-gate 	/*
34070Sstevel@tonic-gate 	 * Copy information using memcpy
34080Sstevel@tonic-gate 	 */
34090Sstevel@tonic-gate 	(void) memcpy(*buf, &abort_cmd_data, sizeof (rdr_abort_cmd_t));
34100Sstevel@tonic-gate 
34110Sstevel@tonic-gate 	return (RDR_OK);
34120Sstevel@tonic-gate }
34130Sstevel@tonic-gate 
34140Sstevel@tonic-gate 
34150Sstevel@tonic-gate /*
34160Sstevel@tonic-gate  * unpack_abort_cmd_request:
34170Sstevel@tonic-gate  *
34180Sstevel@tonic-gate  * Handle unpacking an abort request message.
34190Sstevel@tonic-gate  */
34200Sstevel@tonic-gate static int
34210Sstevel@tonic-gate unpack_abort_cmd_request(abort_cmd_params_t *params, const char *buf)
34220Sstevel@tonic-gate {
34230Sstevel@tonic-gate 	rdr_abort_cmd_t		*abort_cmd_datap;
34240Sstevel@tonic-gate 
34250Sstevel@tonic-gate 
34260Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
34270Sstevel@tonic-gate 		return (RDR_ERROR);
34280Sstevel@tonic-gate 	}
34290Sstevel@tonic-gate 
34300Sstevel@tonic-gate 	/* LINTED Pointer Cast Alignment Warning */
34310Sstevel@tonic-gate 	abort_cmd_datap = (rdr_abort_cmd_t *)buf;
34320Sstevel@tonic-gate 
34330Sstevel@tonic-gate 	/*
34340Sstevel@tonic-gate 	 * copy out the session information
34350Sstevel@tonic-gate 	 */
34360Sstevel@tonic-gate 
34370Sstevel@tonic-gate 	params->session_id = abort_cmd_datap->session_id;
34380Sstevel@tonic-gate 
34390Sstevel@tonic-gate 	return (RDR_OK);
34400Sstevel@tonic-gate }
34410Sstevel@tonic-gate 
34420Sstevel@tonic-gate 
34430Sstevel@tonic-gate /*
34440Sstevel@tonic-gate  * pack_confirm_request:
34450Sstevel@tonic-gate  *
34460Sstevel@tonic-gate  * Handle packing a confirm callback request.
34470Sstevel@tonic-gate  */
34480Sstevel@tonic-gate static int
34490Sstevel@tonic-gate pack_confirm_request(confirm_callback_params_t *params, char **buf,
34500Sstevel@tonic-gate     int *buf_size)
34510Sstevel@tonic-gate {
34520Sstevel@tonic-gate 	int				i;
34530Sstevel@tonic-gate 	char				*bufptr;
34540Sstevel@tonic-gate 	rdr_confirm_callback_t		confirm_callback_data;
34550Sstevel@tonic-gate 	int 				message_strlen;
34560Sstevel@tonic-gate 	int 				message_pad_sz;
34570Sstevel@tonic-gate 
34580Sstevel@tonic-gate 
34590Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
34600Sstevel@tonic-gate 		return (RDR_ERROR);
34610Sstevel@tonic-gate 	}
34620Sstevel@tonic-gate 
34630Sstevel@tonic-gate 	/*
34640Sstevel@tonic-gate 	 * Set variable length fields and make a call to partially
34650Sstevel@tonic-gate 	 * pack it.
34660Sstevel@tonic-gate 	 */
34670Sstevel@tonic-gate 	if (params->message != NULL) {
34680Sstevel@tonic-gate 		message_strlen = strlen(params->message) + 1;
34690Sstevel@tonic-gate 		message_pad_sz = RDR_ALIGN_64_BIT -
34700Sstevel@tonic-gate 		    (message_strlen % RDR_ALIGN_64_BIT);
34710Sstevel@tonic-gate 	} else {
34720Sstevel@tonic-gate 		message_strlen = 0;
34730Sstevel@tonic-gate 		message_pad_sz = 0;
34740Sstevel@tonic-gate 	}
34750Sstevel@tonic-gate 
34760Sstevel@tonic-gate 
34770Sstevel@tonic-gate 	/*
34780Sstevel@tonic-gate 	 * Collect size info specific to the confirm callback request
34790Sstevel@tonic-gate 	 * message and allocate a buffer
34800Sstevel@tonic-gate 	 */
34810Sstevel@tonic-gate 	*buf_size = sizeof (rdr_confirm_callback_t);
34820Sstevel@tonic-gate 	*buf_size += message_strlen;
34830Sstevel@tonic-gate 	*buf_size += message_pad_sz;
34840Sstevel@tonic-gate 
34850Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
34860Sstevel@tonic-gate 	if (*buf == NULL) {
34870Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
34880Sstevel@tonic-gate 	}
34890Sstevel@tonic-gate 
34900Sstevel@tonic-gate 	/*
34910Sstevel@tonic-gate 	 * Set fixed address labels by name
34920Sstevel@tonic-gate 	 */
34930Sstevel@tonic-gate 	if (params->confp != NULL) {
34940Sstevel@tonic-gate 		confirm_callback_data.confirm_callback_id =
34950Sstevel@tonic-gate 		    (unsigned long)params->confp->confirm;
34960Sstevel@tonic-gate 		confirm_callback_data.appdata_ptr =
34970Sstevel@tonic-gate 		    (unsigned long)params->confp->appdata_ptr;
34980Sstevel@tonic-gate 	} else {
34990Sstevel@tonic-gate 		confirm_callback_data.confirm_callback_id = 0;
35000Sstevel@tonic-gate 		confirm_callback_data.appdata_ptr = 0;
35010Sstevel@tonic-gate 	}
35020Sstevel@tonic-gate 	confirm_callback_data.message_size = message_strlen + message_pad_sz;
35030Sstevel@tonic-gate 
35040Sstevel@tonic-gate 	/*
35050Sstevel@tonic-gate 	 * Set variable information using memcpy
35060Sstevel@tonic-gate 	 */
35070Sstevel@tonic-gate 	bufptr = *buf;
35080Sstevel@tonic-gate 	(void) memcpy(bufptr, &confirm_callback_data,
35090Sstevel@tonic-gate 	    sizeof (rdr_confirm_callback_t));
35100Sstevel@tonic-gate 	bufptr += sizeof (rdr_confirm_callback_t);
35110Sstevel@tonic-gate 
35120Sstevel@tonic-gate 	if (params->message != NULL) {
35130Sstevel@tonic-gate 		(void) memcpy(bufptr, params->message, message_strlen);
35140Sstevel@tonic-gate 		bufptr += message_strlen;
35150Sstevel@tonic-gate 		for (i = 0; i < message_pad_sz; i++) {
35160Sstevel@tonic-gate 			bufptr[i] = 0;
35170Sstevel@tonic-gate 		}
35180Sstevel@tonic-gate 		bufptr += message_pad_sz;
35190Sstevel@tonic-gate 	}
35200Sstevel@tonic-gate 
35210Sstevel@tonic-gate 	return (RDR_OK);
35220Sstevel@tonic-gate }
35230Sstevel@tonic-gate 
35240Sstevel@tonic-gate 
35250Sstevel@tonic-gate /*
35260Sstevel@tonic-gate  * unpack_confirm_request:
35270Sstevel@tonic-gate  *
35280Sstevel@tonic-gate  * Handle unpacking a confirm callback request.
35290Sstevel@tonic-gate  */
35300Sstevel@tonic-gate static int
35310Sstevel@tonic-gate unpack_confirm_request(confirm_callback_params_t *params, const char *buf)
35320Sstevel@tonic-gate {
35330Sstevel@tonic-gate 	char				*bufptr;
35340Sstevel@tonic-gate 	rdr_confirm_callback_t		confirm_callback_data;
35350Sstevel@tonic-gate 
35360Sstevel@tonic-gate 
35370Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
35380Sstevel@tonic-gate 		return (RDR_ERROR);
35390Sstevel@tonic-gate 	}
35400Sstevel@tonic-gate 
35410Sstevel@tonic-gate 	bufptr = (char *)buf;
35420Sstevel@tonic-gate 	(void) memcpy(&confirm_callback_data, bufptr,
35430Sstevel@tonic-gate 	    sizeof (rdr_confirm_callback_t));
35440Sstevel@tonic-gate 	bufptr += sizeof (rdr_confirm_callback_t);
35450Sstevel@tonic-gate 
35460Sstevel@tonic-gate 	/*
35470Sstevel@tonic-gate 	 * handle getting the message text
35480Sstevel@tonic-gate 	 */
35490Sstevel@tonic-gate 	if (get_string_from_buf(&(params->message),
35500Sstevel@tonic-gate 	    confirm_callback_data.message_size, bufptr)) {
35510Sstevel@tonic-gate 		return (RDR_ERROR);
35520Sstevel@tonic-gate 	}
35530Sstevel@tonic-gate 	bufptr += confirm_callback_data.message_size;
35540Sstevel@tonic-gate 
35550Sstevel@tonic-gate 	/*
35560Sstevel@tonic-gate 	 * Set fixed address labels by name
35570Sstevel@tonic-gate 	 */
35580Sstevel@tonic-gate 	params->confp = (struct cfga_confirm *)
35590Sstevel@tonic-gate 	    malloc(sizeof (struct cfga_confirm));
35600Sstevel@tonic-gate 	if (params->confp == NULL) {
35610Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
35620Sstevel@tonic-gate 	}
35630Sstevel@tonic-gate 
35640Sstevel@tonic-gate 	/* set params->confp->confirm using memcpy */
35650Sstevel@tonic-gate 	(void) memcpy((void*)params->confp,
35660Sstevel@tonic-gate 	    &(confirm_callback_data.confirm_callback_id),
35670Sstevel@tonic-gate 	    sizeof (unsigned long));
35680Sstevel@tonic-gate 
35690Sstevel@tonic-gate 	params->confp->appdata_ptr =
35700Sstevel@tonic-gate 	    (void*)confirm_callback_data.appdata_ptr;
35710Sstevel@tonic-gate 
35720Sstevel@tonic-gate 	return (RDR_OK);
35730Sstevel@tonic-gate }
35740Sstevel@tonic-gate 
35750Sstevel@tonic-gate 
35760Sstevel@tonic-gate /*
35770Sstevel@tonic-gate  * pack_confirm_reply:
35780Sstevel@tonic-gate  *
35790Sstevel@tonic-gate  * Handle packing a confirm callback reply.
35800Sstevel@tonic-gate  */
35810Sstevel@tonic-gate static int
35820Sstevel@tonic-gate pack_confirm_reply(confirm_callback_params_t *params, char **buf, int *buf_size)
35830Sstevel@tonic-gate {
35840Sstevel@tonic-gate 	char				*bufptr;
35850Sstevel@tonic-gate 	rdr_confirm_callback_reply_t	confirm_callback_data;
35860Sstevel@tonic-gate 
35870Sstevel@tonic-gate 
35880Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
35890Sstevel@tonic-gate 		return (RDR_ERROR);
35900Sstevel@tonic-gate 	}
35910Sstevel@tonic-gate 
35920Sstevel@tonic-gate 	/*
35930Sstevel@tonic-gate 	 * Collect size info specific to the confirm callback reply
35940Sstevel@tonic-gate 	 * message and allocate a buffer
35950Sstevel@tonic-gate 	 */
35960Sstevel@tonic-gate 	*buf_size = sizeof (confirm_callback_params_t);
35970Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
35980Sstevel@tonic-gate 	if (*buf == NULL) {
35990Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
36000Sstevel@tonic-gate 	}
36010Sstevel@tonic-gate 
36020Sstevel@tonic-gate 	/*
36030Sstevel@tonic-gate 	 * Set fixed address labels by name
36040Sstevel@tonic-gate 	 */
36050Sstevel@tonic-gate 	if (params->confp != NULL) {
36060Sstevel@tonic-gate 		confirm_callback_data.confirm_callback_id =
36070Sstevel@tonic-gate 		    (unsigned long)params->confp->confirm;
36080Sstevel@tonic-gate 		confirm_callback_data.appdata_ptr =
36090Sstevel@tonic-gate 		    (unsigned long)params->confp->appdata_ptr;
36100Sstevel@tonic-gate 	} else {
36110Sstevel@tonic-gate 		confirm_callback_data.confirm_callback_id = 0;
36120Sstevel@tonic-gate 		confirm_callback_data.appdata_ptr = 0;
36130Sstevel@tonic-gate 	}
36140Sstevel@tonic-gate 	confirm_callback_data.response = params->response;
36150Sstevel@tonic-gate 
36160Sstevel@tonic-gate 	/*
36170Sstevel@tonic-gate 	 * Set variable information using memcpy
36180Sstevel@tonic-gate 	 */
36190Sstevel@tonic-gate 	bufptr = *buf;
36200Sstevel@tonic-gate 
36210Sstevel@tonic-gate 	(void) memcpy(bufptr, &confirm_callback_data,
36220Sstevel@tonic-gate 	    sizeof (rdr_confirm_callback_reply_t));
36230Sstevel@tonic-gate 
36240Sstevel@tonic-gate 	return (RDR_OK);
36250Sstevel@tonic-gate }
36260Sstevel@tonic-gate 
36270Sstevel@tonic-gate 
36280Sstevel@tonic-gate /*
36290Sstevel@tonic-gate  * unpack_confirm_reply:
36300Sstevel@tonic-gate  *
36310Sstevel@tonic-gate  * Handle unpacking a confirm callback reply.
36320Sstevel@tonic-gate  */
36330Sstevel@tonic-gate static int
36340Sstevel@tonic-gate unpack_confirm_reply(confirm_callback_params_t *params, const char *buf)
36350Sstevel@tonic-gate {
36360Sstevel@tonic-gate 	char				*bufptr;
36370Sstevel@tonic-gate 	rdr_confirm_callback_reply_t	confirm_callback_data;
36380Sstevel@tonic-gate 
36390Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
36400Sstevel@tonic-gate 		return (RDR_ERROR);
36410Sstevel@tonic-gate 	}
36420Sstevel@tonic-gate 
36430Sstevel@tonic-gate 	bufptr = (char *)buf;
36440Sstevel@tonic-gate 	(void) memcpy(&confirm_callback_data, bufptr,
36450Sstevel@tonic-gate 	    sizeof (rdr_confirm_callback_reply_t));
36460Sstevel@tonic-gate 	bufptr += sizeof (confirm_callback_params_t);
36470Sstevel@tonic-gate 
36480Sstevel@tonic-gate 	/*
36490Sstevel@tonic-gate 	 * Set fixed address labels by name
36500Sstevel@tonic-gate 	 */
36510Sstevel@tonic-gate 	params->confp = (struct cfga_confirm *)
36520Sstevel@tonic-gate 	    malloc(sizeof (struct cfga_confirm));
36530Sstevel@tonic-gate 	if (params->confp == NULL) {
36540Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
36550Sstevel@tonic-gate 	}
36560Sstevel@tonic-gate 
36570Sstevel@tonic-gate 	/* set params->confp->confirm using memcpy */
36580Sstevel@tonic-gate 	(void) memcpy((void*)params->confp,
36590Sstevel@tonic-gate 	    &(confirm_callback_data.confirm_callback_id),
36600Sstevel@tonic-gate 	    sizeof (unsigned long));
36610Sstevel@tonic-gate 
36620Sstevel@tonic-gate 	params->confp->appdata_ptr =
36630Sstevel@tonic-gate 	    (void*)confirm_callback_data.appdata_ptr;
36640Sstevel@tonic-gate 	params->response = confirm_callback_data.response;
36650Sstevel@tonic-gate 
36660Sstevel@tonic-gate 	return (RDR_OK);
36670Sstevel@tonic-gate }
36680Sstevel@tonic-gate 
36690Sstevel@tonic-gate 
36700Sstevel@tonic-gate /*
36710Sstevel@tonic-gate  * pack_message_request:
36720Sstevel@tonic-gate  *
36730Sstevel@tonic-gate  * Handle packing a message callback request.
36740Sstevel@tonic-gate  */
36750Sstevel@tonic-gate static int
36760Sstevel@tonic-gate pack_message_request(msg_callback_params_t *params, char **buf, int *buf_size)
36770Sstevel@tonic-gate {
36780Sstevel@tonic-gate 	int			i;
36790Sstevel@tonic-gate 	char			*bufptr;
36800Sstevel@tonic-gate 	rdr_msg_callback_t	msg_callback_data;
36810Sstevel@tonic-gate 	int			message_strlen;
36820Sstevel@tonic-gate 	int			message_pad_sz;
36830Sstevel@tonic-gate 
36840Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
36850Sstevel@tonic-gate 		return (RDR_ERROR);
36860Sstevel@tonic-gate 	}
36870Sstevel@tonic-gate 
36880Sstevel@tonic-gate 	/*
36890Sstevel@tonic-gate 	 * Set variable length fields and make a call to partially
36900Sstevel@tonic-gate 	 * pack it.
36910Sstevel@tonic-gate 	 */
36920Sstevel@tonic-gate 	if (params->message != NULL) {
36930Sstevel@tonic-gate 		message_strlen = strlen(params->message) + 1;
36940Sstevel@tonic-gate 		message_pad_sz = RDR_ALIGN_64_BIT -
36950Sstevel@tonic-gate 		    (message_strlen % RDR_ALIGN_64_BIT);
36960Sstevel@tonic-gate 	} else {
36970Sstevel@tonic-gate 		message_strlen = 0;
36980Sstevel@tonic-gate 		message_pad_sz = 0;
36990Sstevel@tonic-gate 	}
37000Sstevel@tonic-gate 
37010Sstevel@tonic-gate 
37020Sstevel@tonic-gate 	/*
37030Sstevel@tonic-gate 	 * Collect size info specific to the message callback request
37040Sstevel@tonic-gate 	 * message and allocate a buffer
37050Sstevel@tonic-gate 	 */
37060Sstevel@tonic-gate 	*buf_size = sizeof (rdr_msg_callback_t);
37070Sstevel@tonic-gate 	*buf_size += message_strlen;
37080Sstevel@tonic-gate 	*buf_size += message_pad_sz;
37090Sstevel@tonic-gate 
37100Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
37110Sstevel@tonic-gate 	if (*buf == NULL) {
37120Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
37130Sstevel@tonic-gate 	}
37140Sstevel@tonic-gate 
37150Sstevel@tonic-gate 	/*
37160Sstevel@tonic-gate 	 * Set fixed address labels by name
37170Sstevel@tonic-gate 	 */
37180Sstevel@tonic-gate 	if (params->msgp != NULL) {
37190Sstevel@tonic-gate 		msg_callback_data.msg_callback_id =
37200Sstevel@tonic-gate 		    (unsigned long)params->msgp->message_routine;
37210Sstevel@tonic-gate 		msg_callback_data.appdata_ptr =
37220Sstevel@tonic-gate 		    (unsigned long)params->msgp->appdata_ptr;
37230Sstevel@tonic-gate 	} else {
37240Sstevel@tonic-gate 		msg_callback_data.msg_callback_id = 0;
37250Sstevel@tonic-gate 		msg_callback_data.appdata_ptr = 0;
37260Sstevel@tonic-gate 	}
37270Sstevel@tonic-gate 	msg_callback_data.message_size = message_strlen + message_pad_sz;
37280Sstevel@tonic-gate 
37290Sstevel@tonic-gate 	/*
37300Sstevel@tonic-gate 	 * Set variable information using memcpy
37310Sstevel@tonic-gate 	 */
37320Sstevel@tonic-gate 	bufptr = *buf;
37330Sstevel@tonic-gate 
37340Sstevel@tonic-gate 	(void) memcpy(bufptr, &msg_callback_data, sizeof (rdr_msg_callback_t));
37350Sstevel@tonic-gate 	bufptr += sizeof (rdr_msg_callback_t);
37360Sstevel@tonic-gate 
37370Sstevel@tonic-gate 	if (params->message != NULL) {
37380Sstevel@tonic-gate 		(void) memcpy(bufptr, params->message, message_strlen);
37390Sstevel@tonic-gate 		bufptr += message_strlen;
37400Sstevel@tonic-gate 		for (i = 0; i < message_pad_sz; i++) {
37410Sstevel@tonic-gate 			bufptr[i] = 0;
37420Sstevel@tonic-gate 		}
37430Sstevel@tonic-gate 		bufptr += message_pad_sz;
37440Sstevel@tonic-gate 	}
37450Sstevel@tonic-gate 
37460Sstevel@tonic-gate 	return (RDR_OK);
37470Sstevel@tonic-gate }
37480Sstevel@tonic-gate 
37490Sstevel@tonic-gate 
37500Sstevel@tonic-gate /*
37510Sstevel@tonic-gate  * unpack_message_request:
37520Sstevel@tonic-gate  *
37530Sstevel@tonic-gate  * Handle unpacking a message callback request.
37540Sstevel@tonic-gate  */
37550Sstevel@tonic-gate static int
37560Sstevel@tonic-gate unpack_message_request(msg_callback_params_t *params, const char *buf)
37570Sstevel@tonic-gate {
37580Sstevel@tonic-gate 	char			*bufptr;
37590Sstevel@tonic-gate 	rdr_msg_callback_t	msg_callback_data;
37600Sstevel@tonic-gate 
37610Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
37620Sstevel@tonic-gate 		return (RDR_ERROR);
37630Sstevel@tonic-gate 	}
37640Sstevel@tonic-gate 
37650Sstevel@tonic-gate 	bufptr = (char *)buf;
37660Sstevel@tonic-gate 	(void) memcpy(&msg_callback_data, bufptr, sizeof (rdr_msg_callback_t));
37670Sstevel@tonic-gate 	bufptr += sizeof (rdr_msg_callback_t);
37680Sstevel@tonic-gate 
37690Sstevel@tonic-gate 	/*
37700Sstevel@tonic-gate 	 * handle getting the message text
37710Sstevel@tonic-gate 	 */
37720Sstevel@tonic-gate 	if (get_string_from_buf(&(params->message),
37730Sstevel@tonic-gate 	    msg_callback_data.message_size, bufptr)) {
37740Sstevel@tonic-gate 		return (RDR_ERROR);
37750Sstevel@tonic-gate 	}
37760Sstevel@tonic-gate 	bufptr += msg_callback_data.message_size;
37770Sstevel@tonic-gate 
37780Sstevel@tonic-gate 	/*
37790Sstevel@tonic-gate 	 * Set fixed address labels by name
37800Sstevel@tonic-gate 	 */
37810Sstevel@tonic-gate 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
37820Sstevel@tonic-gate 	if (params->msgp == NULL) {
37830Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
37840Sstevel@tonic-gate 	}
37850Sstevel@tonic-gate 
37860Sstevel@tonic-gate 	/* set params->msgp->message_routine using memcpy */
37870Sstevel@tonic-gate 	(void) memcpy((void*)params->msgp, &(msg_callback_data.msg_callback_id),
37880Sstevel@tonic-gate 	    sizeof (unsigned long));
37890Sstevel@tonic-gate 
37900Sstevel@tonic-gate 	params->msgp->appdata_ptr = (void*)msg_callback_data.appdata_ptr;
37910Sstevel@tonic-gate 
37920Sstevel@tonic-gate 	return (RDR_OK);
37930Sstevel@tonic-gate }
37940Sstevel@tonic-gate 
37950Sstevel@tonic-gate /*
37960Sstevel@tonic-gate  * pack_rsrc_info_request:
37970Sstevel@tonic-gate  *
37980Sstevel@tonic-gate  * Handle packing a resource info request.
37990Sstevel@tonic-gate  */
38000Sstevel@tonic-gate static int
38010Sstevel@tonic-gate pack_rsrc_info_request(rsrc_info_params_t *params, char **buf, int *buf_size)
38020Sstevel@tonic-gate {
38030Sstevel@tonic-gate 	char				*bufptr;
38040Sstevel@tonic-gate 	rdr_rsrc_info_t			rsrc_info_data;
38050Sstevel@tonic-gate 	rdr_variable_message_info_t 	var_msg_info;
38060Sstevel@tonic-gate 
38070Sstevel@tonic-gate 
38080Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
38090Sstevel@tonic-gate 		return (RDR_ERROR);
38100Sstevel@tonic-gate 	}
38110Sstevel@tonic-gate 
38120Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
38130Sstevel@tonic-gate 
38140Sstevel@tonic-gate 	/*
38150Sstevel@tonic-gate 	 * Set variable length fields and make a call to partially
38160Sstevel@tonic-gate 	 * pack it.
38170Sstevel@tonic-gate 	 */
38180Sstevel@tonic-gate 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
38190Sstevel@tonic-gate 		cleanup_variable_ap_id_info(&var_msg_info);
38200Sstevel@tonic-gate 		return (RDR_ERROR);
38210Sstevel@tonic-gate 	}
38220Sstevel@tonic-gate 
38230Sstevel@tonic-gate 	/*
38240Sstevel@tonic-gate 	 * Collect size info specific to the resource info request
38250Sstevel@tonic-gate 	 * message and allocate a buffer.
38260Sstevel@tonic-gate 	 */
38270Sstevel@tonic-gate 	*buf_size = sizeof (rdr_rsrc_info_t);
38280Sstevel@tonic-gate 	*buf_size += var_msg_info.ap_id_int_size;
38290Sstevel@tonic-gate 	*buf_size += var_msg_info.ap_id_char_size;
38300Sstevel@tonic-gate 
38310Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
38320Sstevel@tonic-gate 	if (*buf == NULL) {
38330Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
38340Sstevel@tonic-gate 	}
38350Sstevel@tonic-gate 
38360Sstevel@tonic-gate 	/*
38370Sstevel@tonic-gate 	 * Set fixed address labels by name.
38380Sstevel@tonic-gate 	 */
38390Sstevel@tonic-gate 	rsrc_info_data.num_ap_ids = params->num_ap_ids;
38400Sstevel@tonic-gate 	rsrc_info_data.ap_id_char_size = var_msg_info.ap_id_char_size;
38410Sstevel@tonic-gate 	rsrc_info_data.flags = params->flags;
38420Sstevel@tonic-gate 
38430Sstevel@tonic-gate 	/*
38440Sstevel@tonic-gate 	 * Set variable information using memcpy.
38450Sstevel@tonic-gate 	 */
38460Sstevel@tonic-gate 	bufptr = *buf;
38470Sstevel@tonic-gate 
38480Sstevel@tonic-gate 	(void) memcpy(bufptr, &rsrc_info_data, sizeof (rdr_rsrc_info_t));
38490Sstevel@tonic-gate 	bufptr += sizeof (rdr_rsrc_info_t);
38500Sstevel@tonic-gate 
38510Sstevel@tonic-gate 	if (var_msg_info.ap_id_sizes != NULL) {
38520Sstevel@tonic-gate 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
38530Sstevel@tonic-gate 		    var_msg_info.ap_id_int_size);
38540Sstevel@tonic-gate 		bufptr += var_msg_info.ap_id_int_size;
38550Sstevel@tonic-gate 	}
38560Sstevel@tonic-gate 
38570Sstevel@tonic-gate 	if (var_msg_info.ap_id_chars != NULL) {
38580Sstevel@tonic-gate 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
38590Sstevel@tonic-gate 		    var_msg_info.ap_id_char_size);
38600Sstevel@tonic-gate 		bufptr += var_msg_info.ap_id_char_size;
38610Sstevel@tonic-gate 	}
38620Sstevel@tonic-gate 
38630Sstevel@tonic-gate 	cleanup_variable_ap_id_info(&var_msg_info);
38640Sstevel@tonic-gate 
38650Sstevel@tonic-gate 	return (RDR_OK);
38660Sstevel@tonic-gate }
38670Sstevel@tonic-gate 
38680Sstevel@tonic-gate 
38690Sstevel@tonic-gate /*
38700Sstevel@tonic-gate  * unpack_rsrc_info_request:
38710Sstevel@tonic-gate  *
38720Sstevel@tonic-gate  * Handle unpacking a resource info request message.
38730Sstevel@tonic-gate  */
38740Sstevel@tonic-gate static int
38750Sstevel@tonic-gate unpack_rsrc_info_request(rsrc_info_params_t *params, const char *buf)
38760Sstevel@tonic-gate {
38770Sstevel@tonic-gate 	char				*bufptr;
38780Sstevel@tonic-gate 	rdr_variable_message_info_t 	var_msg_info;
38790Sstevel@tonic-gate 	rdr_rsrc_info_t			rsrc_info_data;
38800Sstevel@tonic-gate 
38810Sstevel@tonic-gate 
38820Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
38830Sstevel@tonic-gate 		return (RDR_ERROR);
38840Sstevel@tonic-gate 	}
38850Sstevel@tonic-gate 
38860Sstevel@tonic-gate 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
38870Sstevel@tonic-gate 
38880Sstevel@tonic-gate 	bufptr = (char *)buf;
38890Sstevel@tonic-gate 	(void) memcpy(&rsrc_info_data, bufptr, sizeof (rdr_rsrc_info_t));
38900Sstevel@tonic-gate 	bufptr += sizeof (rdr_rsrc_info_t);
38910Sstevel@tonic-gate 
38920Sstevel@tonic-gate 	/*
38930Sstevel@tonic-gate 	 * Handle getting the ap_ids.
38940Sstevel@tonic-gate 	 */
38950Sstevel@tonic-gate 	var_msg_info.ap_id_char_size = rsrc_info_data.ap_id_char_size;
38960Sstevel@tonic-gate 	if (get_ap_ids_from_buf(&(params->ap_ids), rsrc_info_data.num_ap_ids,
38970Sstevel@tonic-gate 	    &var_msg_info, bufptr)) {
38980Sstevel@tonic-gate 		return (RDR_ERROR);
38990Sstevel@tonic-gate 	}
39000Sstevel@tonic-gate 	bufptr += var_msg_info.ap_id_int_size;
39010Sstevel@tonic-gate 	bufptr += var_msg_info.ap_id_char_size;
39020Sstevel@tonic-gate 
39030Sstevel@tonic-gate 	/*
39040Sstevel@tonic-gate 	 * Set fixed address labels by name.
39050Sstevel@tonic-gate 	 */
39060Sstevel@tonic-gate 	params->num_ap_ids = rsrc_info_data.num_ap_ids;
39070Sstevel@tonic-gate 	params->flags = rsrc_info_data.flags;
39080Sstevel@tonic-gate 
39090Sstevel@tonic-gate 	return (RDR_OK);
39100Sstevel@tonic-gate }
39110Sstevel@tonic-gate 
39120Sstevel@tonic-gate 
39130Sstevel@tonic-gate /*
39140Sstevel@tonic-gate  * pack_rsrc_info_reply:
39150Sstevel@tonic-gate  *
39160Sstevel@tonic-gate  * Handle packing a resource info reply message.
39170Sstevel@tonic-gate  */
39180Sstevel@tonic-gate static int
39190Sstevel@tonic-gate pack_rsrc_info_reply(rsrc_info_params_t *params, char **buf, int *buf_size)
39200Sstevel@tonic-gate {
39210Sstevel@tonic-gate 	char				*bufptr;
39220Sstevel@tonic-gate 	rdr_rsrc_info_reply_t		rsrc_info_data;
39230Sstevel@tonic-gate 	int				pack_status;
39240Sstevel@tonic-gate 	caddr_t				rsrc_info_bufp = NULL;
39250Sstevel@tonic-gate 	size_t 				rsrc_info_size;
39260Sstevel@tonic-gate 
39270Sstevel@tonic-gate 
39280Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
39290Sstevel@tonic-gate 		return (RDR_ERROR);
39300Sstevel@tonic-gate 	}
39310Sstevel@tonic-gate 
39320Sstevel@tonic-gate 	/*
39330Sstevel@tonic-gate 	 * Pack snapshot handle data.
39340Sstevel@tonic-gate 	 */
39350Sstevel@tonic-gate 	pack_status = ri_pack(params->hdl, &rsrc_info_bufp, &rsrc_info_size);
39360Sstevel@tonic-gate 	if (pack_status != 0) {
39370Sstevel@tonic-gate 		return (RDR_ERROR);
39380Sstevel@tonic-gate 	}
39390Sstevel@tonic-gate 
39400Sstevel@tonic-gate 	/*
39410Sstevel@tonic-gate 	 * Collect size info specific to the rsrc_info reply message
39420Sstevel@tonic-gate 	 * and allocate a buffer.
39430Sstevel@tonic-gate 	 */
39440Sstevel@tonic-gate 	*buf_size = sizeof (rdr_rsrc_info_reply_t);
39450Sstevel@tonic-gate 	*buf_size += rsrc_info_size;
39460Sstevel@tonic-gate 
39470Sstevel@tonic-gate 	*buf = (char *)malloc(*buf_size);
39480Sstevel@tonic-gate 	if (*buf == NULL) {
39490Sstevel@tonic-gate 		free(rsrc_info_bufp);
39500Sstevel@tonic-gate 		return (RDR_MEM_ALLOC);
39510Sstevel@tonic-gate 	}
39520Sstevel@tonic-gate 
39530Sstevel@tonic-gate 	/*
39540Sstevel@tonic-gate 	 * Set fixed address labels by name.
39550Sstevel@tonic-gate 	 */
39560Sstevel@tonic-gate 	rsrc_info_data.packed_hdl_size = rsrc_info_size;
39570Sstevel@tonic-gate 
39580Sstevel@tonic-gate 	/*
39590Sstevel@tonic-gate 	 * Set variable information using memcpy.
39600Sstevel@tonic-gate 	 */
39610Sstevel@tonic-gate 	bufptr = *buf;
39620Sstevel@tonic-gate 
39630Sstevel@tonic-gate 	(void) memcpy(bufptr, &rsrc_info_data, sizeof (rdr_rsrc_info_reply_t));
39640Sstevel@tonic-gate 	bufptr += sizeof (rdr_rsrc_info_reply_t);
39650Sstevel@tonic-gate 
39660Sstevel@tonic-gate 	if (rsrc_info_bufp) {
39670Sstevel@tonic-gate 		(void) memcpy(bufptr, rsrc_info_bufp, rsrc_info_size);
39680Sstevel@tonic-gate 		free(rsrc_info_bufp);
39690Sstevel@tonic-gate 	}
39700Sstevel@tonic-gate 
39710Sstevel@tonic-gate 	return (RDR_OK);
39720Sstevel@tonic-gate }
39730Sstevel@tonic-gate 
39740Sstevel@tonic-gate 
39750Sstevel@tonic-gate /*
39760Sstevel@tonic-gate  * unpack_rsrc_info_reply:
39770Sstevel@tonic-gate  *
39780Sstevel@tonic-gate  * Handle unpacking a resource info reply message.
39790Sstevel@tonic-gate  */
39800Sstevel@tonic-gate static int
39810Sstevel@tonic-gate unpack_rsrc_info_reply(rsrc_info_params_t *params, const char *buf)
39820Sstevel@tonic-gate {
39830Sstevel@tonic-gate 	int			unpack_status;
39840Sstevel@tonic-gate 	char 			*bufptr;
39850Sstevel@tonic-gate 	rdr_rsrc_info_reply_t	rsrc_info_data;
39860Sstevel@tonic-gate 
39870Sstevel@tonic-gate 
39880Sstevel@tonic-gate 	if ((params == NULL) || (buf == NULL)) {
39890Sstevel@tonic-gate 		return (RDR_ERROR);
39900Sstevel@tonic-gate 	}
39910Sstevel@tonic-gate 
39920Sstevel@tonic-gate 	bufptr = (char *)buf;
39930Sstevel@tonic-gate 	(void) memcpy(&rsrc_info_data, bufptr, sizeof (rdr_rsrc_info_reply_t));
39940Sstevel@tonic-gate 	bufptr += sizeof (rdr_rsrc_info_reply_t);
39950Sstevel@tonic-gate 
39960Sstevel@tonic-gate 	/*
39970Sstevel@tonic-gate 	 * Unpack buf into resource info handle.
39980Sstevel@tonic-gate 	 */
39990Sstevel@tonic-gate 	unpack_status = ri_unpack(bufptr, rsrc_info_data.packed_hdl_size,
40000Sstevel@tonic-gate 	    &params->hdl);
40010Sstevel@tonic-gate 
40020Sstevel@tonic-gate 	return ((unpack_status == 0) ? RDR_OK : RDR_ERROR);
40030Sstevel@tonic-gate }
40040Sstevel@tonic-gate 
40050Sstevel@tonic-gate 
40060Sstevel@tonic-gate /*
40070Sstevel@tonic-gate  * pack_ap_ids:
40080Sstevel@tonic-gate  *
40090Sstevel@tonic-gate  * Pack a list of attachment point identifiers into a single buffer.
40100Sstevel@tonic-gate  * This buffer is stored in the specified rdr_variable_message_info_t
40110Sstevel@tonic-gate  * and is padded to be 64-bit aligned.
40120Sstevel@tonic-gate  */
40130Sstevel@tonic-gate static int
40140Sstevel@tonic-gate pack_ap_ids(int num_ap_ids, char *const *ap_ids,
40150Sstevel@tonic-gate     rdr_variable_message_info_t *var_msg_info)
40160Sstevel@tonic-gate {
40170Sstevel@tonic-gate 	int	i;
40180Sstevel@tonic-gate 	int	ap_id_pad_sz;
40190Sstevel@tonic-gate 	char	*bufptr;
40200Sstevel@tonic-gate 
40210Sstevel@tonic-gate 
40220Sstevel@tonic-gate 	if (var_msg_info == NULL) {
40230Sstevel@tonic-gate 		return (RDR_ERROR);
40240Sstevel@tonic-gate 	}
40250Sstevel@tonic-gate 
40260Sstevel@tonic-gate 	/*
40270Sstevel@tonic-gate 	 * NULL is a valid value for ap_ids in the list_ext
40280Sstevel@tonic-gate 	 * case. For list_ext, no specified attachment points
40290Sstevel@tonic-gate 	 * indicates that _all_ attachment points should be
40300Sstevel@tonic-gate 	 * displayed. However, if ap_ids is NULL, num_ap_ids
40310Sstevel@tonic-gate 	 * should be 0.
40320Sstevel@tonic-gate 	 */
40330Sstevel@tonic-gate 	if ((ap_ids == NULL) && (num_ap_ids != 0)) {
40340Sstevel@tonic-gate 		num_ap_ids = 0;
40350Sstevel@tonic-gate 	}
40360Sstevel@tonic-gate 
40370Sstevel@tonic-gate 	var_msg_info->ap_id_int_size = sizeof (int) * num_ap_ids;
40380Sstevel@tonic-gate 	if (num_ap_ids > 0) {
40390Sstevel@tonic-gate 		var_msg_info->ap_id_sizes = (int *)malloc(sizeof (int) *
40400Sstevel@tonic-gate 		    var_msg_info->ap_id_int_size);
40410Sstevel@tonic-gate 		if (var_msg_info->ap_id_sizes == NULL) {
40420Sstevel@tonic-gate 			return (RDR_MEM_ALLOC);
40430Sstevel@tonic-gate 		}
40440Sstevel@tonic-gate 	}
40450Sstevel@tonic-gate 	for (i = 0; i < num_ap_ids; i++) {
40460Sstevel@tonic-gate 		if (ap_ids[i] != NULL) {
40470Sstevel@tonic-gate 			var_msg_info->ap_id_sizes[i] = strlen(ap_ids[i]) + 1;
40480Sstevel@tonic-gate 			var_msg_info->ap_id_char_size +=
40490Sstevel@tonic-gate 			    var_msg_info->ap_id_sizes[i];
40500Sstevel@tonic-gate 		}
40510Sstevel@tonic-gate 	}
40520Sstevel@tonic-gate 	if (var_msg_info->ap_id_char_size > 0) {
40530Sstevel@tonic-gate 		ap_id_pad_sz = RDR_ALIGN_64_BIT -
40540Sstevel@tonic-gate 		    (var_msg_info->ap_id_char_size % RDR_ALIGN_64_BIT);
40550Sstevel@tonic-gate 		var_msg_info->ap_id_char_size += ap_id_pad_sz;
40560Sstevel@tonic-gate 		var_msg_info->ap_id_chars = (char *)
40570Sstevel@tonic-gate 		    malloc(var_msg_info->ap_id_char_size);
40580Sstevel@tonic-gate 		if (var_msg_info->ap_id_chars == NULL) {
40590Sstevel@tonic-gate 			return (RDR_MEM_ALLOC);
40600Sstevel@tonic-gate 		}
40610Sstevel@tonic-gate 
40620Sstevel@tonic-gate 		bufptr = var_msg_info->ap_id_chars;
40630Sstevel@tonic-gate 		for (i = 0; i < num_ap_ids; i++) {
40640Sstevel@tonic-gate 			(void) memcpy(bufptr, ap_ids[i],
40650Sstevel@tonic-gate 			    var_msg_info->ap_id_sizes[i]);
40660Sstevel@tonic-gate 			bufptr += var_msg_info->ap_id_sizes[i];
40670Sstevel@tonic-gate 		}
40680Sstevel@tonic-gate 		for (i = 0; i < ap_id_pad_sz; i++) {
40690Sstevel@tonic-gate 			bufptr[i] = 0;
40700Sstevel@tonic-gate 		}
40710Sstevel@tonic-gate 	} else {
40720Sstevel@tonic-gate 		ap_id_pad_sz = 0;
40730Sstevel@tonic-gate 	}
40740Sstevel@tonic-gate 
40750Sstevel@tonic-gate 	return (RDR_OK);
40760Sstevel@tonic-gate }
40770Sstevel@tonic-gate 
40780Sstevel@tonic-gate 
40790Sstevel@tonic-gate /*
40800Sstevel@tonic-gate  * unpack_ap_ids:
40810Sstevel@tonic-gate  *
40820Sstevel@tonic-gate  * Unpack a buffer containing a concatenation of a list of
40830Sstevel@tonic-gate  * attachment point identifiers. The resulting list of strings
40840Sstevel@tonic-gate  * are stored in an array in the specified rdr_variable_message_info_t.
40850Sstevel@tonic-gate  */
40860Sstevel@tonic-gate static int
40870Sstevel@tonic-gate unpack_ap_ids(int num_ap_ids, char **ap_ids, const char *buf,
40880Sstevel@tonic-gate     rdr_variable_message_info_t *var_msg_info)
40890Sstevel@tonic-gate {
40900Sstevel@tonic-gate 	int	i;
40910Sstevel@tonic-gate 	int	ap_id_size;
40920Sstevel@tonic-gate 	int	chars_copied;
40930Sstevel@tonic-gate 	char	*bufptr;
40940Sstevel@tonic-gate 
40950Sstevel@tonic-gate 
40960Sstevel@tonic-gate 	if ((ap_ids == NULL) || (buf == NULL) || (var_msg_info == NULL)) {
40970Sstevel@tonic-gate 		return (RDR_ERROR);
40980Sstevel@tonic-gate 	}
40990Sstevel@tonic-gate 	bufptr = (char *)buf;
41000Sstevel@tonic-gate 
41010Sstevel@tonic-gate 	var_msg_info->ap_id_int_size = sizeof (int) * num_ap_ids;
41020Sstevel@tonic-gate 	if (num_ap_ids > 0) {
41030Sstevel@tonic-gate 		var_msg_info->ap_id_sizes = (int *)
41040Sstevel@tonic-gate 		malloc(sizeof (int) * var_msg_info->ap_id_int_size);
41050Sstevel@tonic-gate 		if (var_msg_info->ap_id_sizes == NULL) {
41060Sstevel@tonic-gate 			return (RDR_MEM_ALLOC);
41070Sstevel@tonic-gate 		}
41080Sstevel@tonic-gate 		(void) memcpy(var_msg_info->ap_id_sizes, bufptr,
41090Sstevel@tonic-gate 		    var_msg_info->ap_id_int_size);
41100Sstevel@tonic-gate 	}
41110Sstevel@tonic-gate 	bufptr += var_msg_info->ap_id_int_size;
41120Sstevel@tonic-gate 
41130Sstevel@tonic-gate 	chars_copied = 0;
41140Sstevel@tonic-gate 	for (i = 0; i < num_ap_ids; i++) {
41150Sstevel@tonic-gate 		ap_id_size = var_msg_info->ap_id_sizes[i];
41160Sstevel@tonic-gate 		if (ap_id_size <= 0) {
41170Sstevel@tonic-gate 			continue;
41180Sstevel@tonic-gate 		}
41190Sstevel@tonic-gate 		if ((chars_copied + ap_id_size) >
41200Sstevel@tonic-gate 			var_msg_info->ap_id_char_size) {
41210Sstevel@tonic-gate 			return (RDR_ERROR);
41220Sstevel@tonic-gate 		}
41230Sstevel@tonic-gate 		ap_ids[i] = (char *)malloc(ap_id_size);
41240Sstevel@tonic-gate 		if (ap_ids[i] == NULL) {
41250Sstevel@tonic-gate 			return (RDR_MEM_ALLOC);
41260Sstevel@tonic-gate 		}
41270Sstevel@tonic-gate 		(void) memcpy(ap_ids[i], bufptr, ap_id_size);
41280Sstevel@tonic-gate 		bufptr += ap_id_size;
41290Sstevel@tonic-gate 		chars_copied += ap_id_size;
41300Sstevel@tonic-gate 	}
41310Sstevel@tonic-gate 	return (RDR_OK);
41320Sstevel@tonic-gate }
41330Sstevel@tonic-gate 
41340Sstevel@tonic-gate 
41350Sstevel@tonic-gate /*
41360Sstevel@tonic-gate  * find_options_sizes:
41370Sstevel@tonic-gate  *
41380Sstevel@tonic-gate  * Determine the size of a specified option string. The information
41390Sstevel@tonic-gate  * is stored in the specified rdr_variable_message_info_t.
41400Sstevel@tonic-gate  */
41410Sstevel@tonic-gate static int
41420Sstevel@tonic-gate find_options_sizes(char *options, rdr_variable_message_info_t *var_msg_info)
41430Sstevel@tonic-gate {
41440Sstevel@tonic-gate 	if (var_msg_info == NULL) {
41450Sstevel@tonic-gate 		return (RDR_ERROR);
41460Sstevel@tonic-gate 	}
41470Sstevel@tonic-gate 	if (options != NULL) {
41480Sstevel@tonic-gate 		var_msg_info->options_strlen = strlen(options) + 1;
41490Sstevel@tonic-gate 		var_msg_info->options_pad_sz = RDR_ALIGN_64_BIT -
41500Sstevel@tonic-gate 		    (var_msg_info->options_strlen % RDR_ALIGN_64_BIT);
41510Sstevel@tonic-gate 	} else {
41520Sstevel@tonic-gate 		var_msg_info->options_strlen = 0;
41530Sstevel@tonic-gate 		var_msg_info->options_pad_sz = 0;
41540Sstevel@tonic-gate 	}
41550Sstevel@tonic-gate 	return (RDR_OK);
41560Sstevel@tonic-gate }
41570Sstevel@tonic-gate 
41580Sstevel@tonic-gate 
41590Sstevel@tonic-gate /*
41600Sstevel@tonic-gate  * find_listopts_sizes:
41610Sstevel@tonic-gate  *
41620Sstevel@tonic-gate  * Determine the size of a specified list option string. The information
41630Sstevel@tonic-gate  * is stored in the specified rdr_variable_message_info_t.
41640Sstevel@tonic-gate  */
41650Sstevel@tonic-gate static int
41660Sstevel@tonic-gate find_listopts_sizes(char *listopts, rdr_variable_message_info_t *var_msg_info)
41670Sstevel@tonic-gate {
41680Sstevel@tonic-gate 	if (var_msg_info == NULL) {
41690Sstevel@tonic-gate 		return (RDR_ERROR);
41700Sstevel@tonic-gate 	}
41710Sstevel@tonic-gate 	if (listopts != NULL) {
41720Sstevel@tonic-gate 		var_msg_info->listopts_strlen = strlen(listopts) + 1;
41730Sstevel@tonic-gate 		var_msg_info->listopts_pad_sz = RDR_ALIGN_64_BIT -
41740Sstevel@tonic-gate 		    (var_msg_info->listopts_strlen % RDR_ALIGN_64_BIT);
41750Sstevel@tonic-gate 	} else {
41760Sstevel@tonic-gate 		var_msg_info->listopts_strlen = 0;
41770Sstevel@tonic-gate 		var_msg_info->listopts_pad_sz = 0;
41780Sstevel@tonic-gate 	}
41790Sstevel@tonic-gate 	return (RDR_OK);
41800Sstevel@tonic-gate }
41810Sstevel@tonic-gate 
41820Sstevel@tonic-gate 
41830Sstevel@tonic-gate /*
41840Sstevel@tonic-gate  * find_function_size:
41850Sstevel@tonic-gate  *
41860Sstevel@tonic-gate  * Determine the size of a specified private function string. The
41870Sstevel@tonic-gate  * information is stored in the specified rdr_variable_message_info_t.
41880Sstevel@tonic-gate  */
41890Sstevel@tonic-gate static int
41900Sstevel@tonic-gate find_function_sizes(char *function, rdr_variable_message_info_t *var_msg_info)
41910Sstevel@tonic-gate {
41920Sstevel@tonic-gate 	if (var_msg_info == NULL) {
41930Sstevel@tonic-gate 		return (RDR_ERROR);
41940Sstevel@tonic-gate 	}
41950Sstevel@tonic-gate 	if (function != NULL) {
41960Sstevel@tonic-gate 		var_msg_info->function_strlen = strlen(function) + 1;
41970Sstevel@tonic-gate 		var_msg_info->function_pad_sz = RDR_ALIGN_64_BIT -
41980Sstevel@tonic-gate 		    (var_msg_info->function_strlen % RDR_ALIGN_64_BIT);
41990Sstevel@tonic-gate 	} else {
42000Sstevel@tonic-gate 		var_msg_info->function_strlen = 0;
42010Sstevel@tonic-gate 		var_msg_info->function_pad_sz = 0;
42020Sstevel@tonic-gate 	}
42030Sstevel@tonic-gate 	return (RDR_OK);
42040Sstevel@tonic-gate }
42050Sstevel@tonic-gate 
42060Sstevel@tonic-gate 
42070Sstevel@tonic-gate /*
42080Sstevel@tonic-gate  * find_errstring_sizes:
42090Sstevel@tonic-gate  *
42100Sstevel@tonic-gate  * Determine the size of a specified error string. The information
42110Sstevel@tonic-gate  * is stored in the specified rdr_variable_message_info_t.
42120Sstevel@tonic-gate  */
42130Sstevel@tonic-gate static int
42140Sstevel@tonic-gate find_errstring_sizes(char **errstring,
42150Sstevel@tonic-gate     rdr_variable_message_info_t *var_msg_info)
42160Sstevel@tonic-gate {
42170Sstevel@tonic-gate 	if ((errstring != NULL) && (*errstring != NULL)) {
42180Sstevel@tonic-gate 		var_msg_info->errstring_strlen = strlen(*errstring) + 1;
42190Sstevel@tonic-gate 		var_msg_info->errstring_pad_sz = RDR_ALIGN_64_BIT -
42200Sstevel@tonic-gate 		    (var_msg_info->errstring_strlen % RDR_ALIGN_64_BIT);
42210Sstevel@tonic-gate 	} else {
42220Sstevel@tonic-gate 		var_msg_info->errstring_strlen = 0;
42230Sstevel@tonic-gate 		var_msg_info->errstring_pad_sz = 0;
42240Sstevel@tonic-gate 	}
42250Sstevel@tonic-gate 	return (RDR_OK);
42260Sstevel@tonic-gate }
42270Sstevel@tonic-gate 
42280Sstevel@tonic-gate 
42290Sstevel@tonic-gate /*
42300Sstevel@tonic-gate  * get_ap_ids_from_buf:
42310Sstevel@tonic-gate  *
42320Sstevel@tonic-gate  * Unpack a buffer containing a concatenation of a list of attachment
42330Sstevel@tonic-gate  * point identifiers. An appropriately sized buffer is allocated and
42340Sstevel@tonic-gate  * the resulting list of strings are stored in an array in the specified
42350Sstevel@tonic-gate  * rdr_variable_message_info_t.
42360Sstevel@tonic-gate  */
42370Sstevel@tonic-gate static int
42380Sstevel@tonic-gate get_ap_ids_from_buf(char ***ap_id_ptr, int num_ap_ids,
42390Sstevel@tonic-gate     rdr_variable_message_info_t *var_msg_info, const char *buf)
42400Sstevel@tonic-gate {
42410Sstevel@tonic-gate 	if ((ap_id_ptr == NULL) || (buf == NULL) || (var_msg_info == NULL)) {
42420Sstevel@tonic-gate 		return (RDR_ERROR);
42430Sstevel@tonic-gate 	}
42440Sstevel@tonic-gate 	if (num_ap_ids > 0) {
42450Sstevel@tonic-gate 		*ap_id_ptr = (char **)malloc(sizeof (char *) * num_ap_ids);
42460Sstevel@tonic-gate 		if (*ap_id_ptr == NULL) {
42470Sstevel@tonic-gate 			return (RDR_MEM_ALLOC);
42480Sstevel@tonic-gate 		}
42490Sstevel@tonic-gate 		if (unpack_ap_ids(num_ap_ids, *ap_id_ptr, buf, var_msg_info)) {
42500Sstevel@tonic-gate 			cleanup_variable_ap_id_info(var_msg_info);
42510Sstevel@tonic-gate 			return (RDR_ERROR);
42520Sstevel@tonic-gate 		}
42530Sstevel@tonic-gate 
42540Sstevel@tonic-gate 	} else if (num_ap_ids < 0) {
42550Sstevel@tonic-gate 		return (RDR_ERROR);
42560Sstevel@tonic-gate 	}
42570Sstevel@tonic-gate 
42580Sstevel@tonic-gate 	cleanup_variable_ap_id_info(var_msg_info);
42590Sstevel@tonic-gate 
42600Sstevel@tonic-gate 	return (RDR_OK);
42610Sstevel@tonic-gate }
42620Sstevel@tonic-gate 
42630Sstevel@tonic-gate 
42640Sstevel@tonic-gate /*
42650Sstevel@tonic-gate  * get_string_from_buf:
42660Sstevel@tonic-gate  *
42670Sstevel@tonic-gate  * Copy a string to a new buffer. Memory is allocated for the
42680Sstevel@tonic-gate  * new buffer and the original string is copied to the new buffer.
42690Sstevel@tonic-gate  * This is primarily used when a string is located in a packed
42700Sstevel@tonic-gate  * buffer that will eventually get deallocated.
42710Sstevel@tonic-gate  */
42720Sstevel@tonic-gate static int
42730Sstevel@tonic-gate get_string_from_buf(char **stringptr, int strsize, const char *buf)
42740Sstevel@tonic-gate {
42750Sstevel@tonic-gate 	if (buf == NULL) {
42760Sstevel@tonic-gate 		return (RDR_ERROR);
42770Sstevel@tonic-gate 	}
42780Sstevel@tonic-gate 
42790Sstevel@tonic-gate 	/*
42800Sstevel@tonic-gate 	 * A stringptr of NULL is a valid value. The errstring param
42810Sstevel@tonic-gate 	 * in an rconfig_xxx call is valid and is passed to this
42820Sstevel@tonic-gate 	 * function. For example, see errstring in the call to this
42830Sstevel@tonic-gate 	 * function in unpack_change_state_reply.
42840Sstevel@tonic-gate 	 */
42850Sstevel@tonic-gate 	if (stringptr != NULL) {
42860Sstevel@tonic-gate 		if (strsize > 0) {
42870Sstevel@tonic-gate 			*stringptr = (char *)malloc(strsize);
42880Sstevel@tonic-gate 			if (*stringptr == NULL) {
42890Sstevel@tonic-gate 				return (RDR_MEM_ALLOC);
42900Sstevel@tonic-gate 			}
42910Sstevel@tonic-gate 			(void) memcpy(*stringptr, buf, strsize);
42920Sstevel@tonic-gate 		} else if (strsize == 0) {
42930Sstevel@tonic-gate 			*stringptr = NULL;
42940Sstevel@tonic-gate 		} else if (strsize < 0) {
42950Sstevel@tonic-gate 			*stringptr = NULL;
42960Sstevel@tonic-gate 			return (RDR_ERROR);
42970Sstevel@tonic-gate 		}
42980Sstevel@tonic-gate 	}
42990Sstevel@tonic-gate 	return (RDR_OK);
43000Sstevel@tonic-gate }
43010Sstevel@tonic-gate 
43020Sstevel@tonic-gate 
43030Sstevel@tonic-gate /*
43040Sstevel@tonic-gate  * cleanup_ap_ids:
43050Sstevel@tonic-gate  *
43060Sstevel@tonic-gate  * Deallocate the specified array of attachment point identifiers.
43070Sstevel@tonic-gate  */
43080Sstevel@tonic-gate static int
43090Sstevel@tonic-gate cleanup_ap_ids(int num_ap_ids, char ** ap_ids)
43100Sstevel@tonic-gate {
43110Sstevel@tonic-gate 	int	i;
43120Sstevel@tonic-gate 
43130Sstevel@tonic-gate 	if (ap_ids == NULL) {
43140Sstevel@tonic-gate 		return (RDR_ERROR);
43150Sstevel@tonic-gate 	}
43160Sstevel@tonic-gate 	for (i = 0; i < num_ap_ids; i++) {
43170Sstevel@tonic-gate 		if (ap_ids[i] != NULL) {
43180Sstevel@tonic-gate 			free((void *)ap_ids[i]);
43190Sstevel@tonic-gate 			ap_ids[i] = NULL;
43200Sstevel@tonic-gate 		}
43210Sstevel@tonic-gate 	}
43220Sstevel@tonic-gate 	return (RDR_OK);
43230Sstevel@tonic-gate }
43240Sstevel@tonic-gate 
43250Sstevel@tonic-gate 
43260Sstevel@tonic-gate /*
43270Sstevel@tonic-gate  * cleanup_errstring:
43280Sstevel@tonic-gate  *
43290Sstevel@tonic-gate  * Deallocate the specified error string.
43300Sstevel@tonic-gate  */
43310Sstevel@tonic-gate static int
43320Sstevel@tonic-gate cleanup_errstring(char **errstring)
43330Sstevel@tonic-gate {
43340Sstevel@tonic-gate 	if (errstring) {
43350Sstevel@tonic-gate 		if (*errstring) {
43360Sstevel@tonic-gate 			free((void *)*errstring);
43370Sstevel@tonic-gate 		}
43380Sstevel@tonic-gate 		free((void *)errstring);
43390Sstevel@tonic-gate 		errstring = NULL;
43400Sstevel@tonic-gate 	}
43410Sstevel@tonic-gate 
43420Sstevel@tonic-gate 	return (RDR_OK);
43430Sstevel@tonic-gate }
43440Sstevel@tonic-gate 
43450Sstevel@tonic-gate 
43460Sstevel@tonic-gate /*
43470Sstevel@tonic-gate  * cleanup_variable_ap_id_info:
43480Sstevel@tonic-gate  *
43490Sstevel@tonic-gate  * Deallocate the ap_id information from the specified
43500Sstevel@tonic-gate  * rdr_variable_message_info_t.
43510Sstevel@tonic-gate  */
43520Sstevel@tonic-gate static void
43530Sstevel@tonic-gate cleanup_variable_ap_id_info(rdr_variable_message_info_t *var_msg_info)
43540Sstevel@tonic-gate {
43550Sstevel@tonic-gate 	if (var_msg_info != NULL) {
43560Sstevel@tonic-gate 		if (var_msg_info->ap_id_sizes != NULL) {
43570Sstevel@tonic-gate 			free((void *)var_msg_info->ap_id_sizes);
43580Sstevel@tonic-gate 			var_msg_info->ap_id_sizes = NULL;
43590Sstevel@tonic-gate 		}
43600Sstevel@tonic-gate 		if (var_msg_info->ap_id_chars != NULL) {
43610Sstevel@tonic-gate 			free((void *)var_msg_info->ap_id_chars);
43620Sstevel@tonic-gate 			var_msg_info->ap_id_chars = NULL;
43630Sstevel@tonic-gate 		}
43640Sstevel@tonic-gate 	}
43650Sstevel@tonic-gate }
4366