xref: /illumos-gate/usr/src/cmd/dcs/sparc/sun4u/rdr_messages.c (revision 10a4fa49f51ed9ae1c857a626de6ce9ebf41661a)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * WARNING: The contents of this file are shared by all projects
30  * that  wish to  perform  remote  Dynamic Reconfiguration  (DR)
31  * operations. Copies of this file can be found in the following
32  * locations:
33  *
34  *	Project	    Location
35  *	-------	    --------
36  *	Solaris	    usr/src/cmd/dcs/sparc/sun4u/%M%
37  *	SMS	    src/sms/lib/librdr/%M%
38  *
39  * In order for proper communication to occur,  the files in the
40  * above locations must match exactly. Any changes that are made
41  * to this file should  be made to all of the files in the list.
42  */
43 
44 /*
45  * This file is a module that contains an interface for performing
46  * remote Dynamic Reconfiguration (DR) operations. It hides all
47  * network operations such as establishing a connection, sending
48  * and receiving messages, and closing a connection. It also handles
49  * the packing and unpacking of messages for network transport.
50  */
51 
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <unistd.h>
55 #include <string.h>
56 #include <fcntl.h>
57 #include <errno.h>
58 #include <dlfcn.h>
59 #include <netdb.h>
60 #include <libdscp.h>
61 #include <sys/socket.h>
62 #include <sys/systeminfo.h>
63 #include <netinet/tcp.h>
64 
65 #include "dcs.h"
66 #include "remote_cfg.h"
67 #include "rdr_param_types.h"
68 #include "rdr_messages.h"
69 
70 
71 /*
72  * Structure holding information about
73  * all possible variable length fields
74  * that can be present in an RDR message.
75  */
76 typedef struct {
77 	int	ap_id_int_size;
78 	int	ap_id_char_size;
79 	int	*ap_id_sizes;
80 	char	*ap_id_chars;
81 	int	errstring_strlen;
82 	int	errstring_pad_sz;
83 	int	options_strlen;
84 	int	options_pad_sz;
85 	int	listopts_strlen;
86 	int	listopts_pad_sz;
87 	int	function_strlen;
88 	int	function_pad_sz;
89 } rdr_variable_message_info_t;
90 
91 /*
92  * A table of maximum sizes for each message type. Message size is
93  * validated when the message header is first received. This prevents
94  * a situation where a corrupted or bad header can cause too much
95  * memory to be allocated.
96  *
97  * The message size limits were chosen to be a very generous upper bound
98  * on the amount of data each message can send. They are not intended to
99  * be a precise measurement of the data size.
100  */
101 #define	NOMSG		0
102 #define	SHORTMSG	(150 * 1024)		/* 150 KB */
103 #define	LONGMSG		(3 * 1024 * 1024)	/* 3 MB */
104 
105 struct {
106 	ulong_t	req_max;
107 	ulong_t	reply_max;
108 } msg_sizes[] = {
109 	/*
110 	 * request	reply
111 	 * -------	-----
112 	 */
113 	{  NOMSG,	NOMSG	  },	/*  Invalid Opcode		*/
114 	{  SHORTMSG,	SHORTMSG  },	/*  RDR_SES_REQ			*/
115 	{  NOMSG,	NOMSG	  },	/*  RDR_SES_ESTBL		*/
116 	{  NOMSG,	NOMSG	  },	/*  RDR_SES_END			*/
117 	{  SHORTMSG,	SHORTMSG  },	/*  RDR_CONF_CHANGE_STATE	*/
118 	{  SHORTMSG,	SHORTMSG  },	/*  RDR_CONF_PRIVATE_FUNC	*/
119 	{  SHORTMSG,	SHORTMSG  },	/*  RDR_CONF_TEST		*/
120 	{  SHORTMSG,	LONGMSG	  },	/*  RDR_CONF_LIST_EXT		*/
121 	{  SHORTMSG,	NOMSG	  },	/*  RDR_CONF_HELP		*/
122 	{  SHORTMSG,	NOMSG	  },	/*  RDR_CONF_AP_ID_CMP		*/
123 	{  SHORTMSG,	NOMSG	  },	/*  RDR_CONF_ABORT_CMD		*/
124 	{  SHORTMSG,	SHORTMSG  },	/*  RDR_CONF_CONFIRM_CALLBACK 	*/
125 	{  SHORTMSG,	NOMSG	  },	/*  RDR_CONF_MSG_CALLBACK	*/
126 	{  SHORTMSG,	LONGMSG	  }	/*  RDR_RSRC_INFO		*/
127 };
128 
129 
130 #define	RDR_BAD_FD		(-1)
131 
132 #define	RDR_MSG_HDR_SIZE 	sizeof (rdr_msg_hdr_t)
133 
134 static const int RDR_ALIGN_64_BIT = 8;   /* 8 bytes */
135 
136 /*
137  * Interfaces for dynamic use of libdscp.
138  */
139 
140 #define	LIBDSCP_PATH	"/usr/platform/%s/lib/libdscp.so.1"
141 
142 #define	LIBDSCP_BIND	"dscpBind"
143 #define	LIBDSCP_SECURE	"dscpSecure"
144 #define	LIBDSCP_AUTH	"dscpAuth"
145 
146 typedef enum {
147 	LIBDSCP_UNKNOWN = 0,
148 	LIBDSCP_AVAILABLE,
149 	LIBDSCP_UNAVAILABLE
150 } dscp_status_t;
151 
152 typedef struct {
153 	dscp_status_t	status;
154 	int		(*bind)(int, int, int);
155 	int		(*secure)(int, int);
156 	int		(*auth)(int, struct sockaddr *, int);
157 } libdscp_t;
158 
159 static libdscp_t libdscp;
160 
161 /*
162  * Static Function Declarations
163  */
164 
165 /*
166  * Socket Related Routines
167  */
168 static int rdr_setopt(int fd, int name, int level);
169 
170 static int rdr_bind(int fd, struct sockaddr *addr);
171 
172 static int rdr_secure(int fd, struct sockaddr *addr);
173 
174 static int rdr_auth(struct sockaddr *addr, int len);
175 
176 static int rdr_snd(int fd, rdr_msg_hdr_t *hdr, char *data, int data_sz,
177 			int timeout);
178 static int rdr_snd_raw(int fd, char *msg, int data_sz, int timeout);
179 
180 static int rdr_rcv(int fd, rdr_msg_hdr_t *hdr, char **data, int timeout);
181 
182 static int rdr_rcv_raw(int fd, char *msg, int data_size, int timeout);
183 
184 /*
185  * Data Validation Routines
186  */
187 static int validate_header(rdr_msg_hdr_t *hdr);
188 
189 
190 /*
191  * Session Request Routines
192  */
193 static int pack_ses_req_request(ses_req_params_t *params, char **buf,
194 			int *buf_size);
195 static int unpack_ses_req_request(ses_req_params_t *params, const char *buf);
196 
197 static int pack_ses_req_reply(ses_req_params_t *params, char **buf,
198 			int *buf_size);
199 static int unpack_ses_req_reply(ses_req_params_t *params, const char *buf);
200 
201 
202 /*
203  * Change State Routines
204  */
205 static int pack_change_state_request(change_state_params_t *params,
206 			char **buf, int *buf_size);
207 static int unpack_change_state_request(change_state_params_t *params,
208 			const char *buf);
209 static int pack_change_state_reply(change_state_params_t *params,
210 			char **buf, int *buf_size);
211 static int unpack_change_state_reply(change_state_params_t *params,
212 			const char *buf);
213 
214 /*
215  * Private Func Routines
216  */
217 static int pack_private_func_request(private_func_params_t *params,
218 			char **buf, int *buf_size);
219 static int unpack_private_func_request(private_func_params_t *params,
220 			const char *buf);
221 static int pack_private_func_reply(private_func_params_t *params,
222 			char **buf, int *buf_size);
223 static int unpack_private_func_reply(private_func_params_t *params,
224 			const char *buf);
225 
226 /*
227  * Test Routines
228  */
229 static int pack_test_request(test_params_t *params, char **buf, int *buf_size);
230 
231 static int unpack_test_request(test_params_t *params, const char *buf);
232 
233 static int pack_test_reply(test_params_t *params, char **buf, int *buf_size);
234 
235 static int unpack_test_reply(test_params_t *params, const char *buf);
236 
237 
238 /*
239  * List Ext Routines
240  */
241 static int pack_list_ext_request(list_ext_params_t *params, char **buf,
242 			int *buf_size);
243 static int unpack_list_ext_request(list_ext_params_t *params, const char *buf);
244 
245 static int pack_list_ext_reply(list_ext_params_t *params, char **buf,
246 			int *buf_size);
247 static int unpack_list_ext_reply(list_ext_params_t *params, const char *buf);
248 
249 
250 /*
251  * Help Routines
252  */
253 static int pack_help_request(help_params_t *params, char **buf, int *buf_size);
254 
255 static int unpack_help_request(help_params_t *params, const char *buf);
256 
257 
258 /*
259  * Ap Id Cmp Routines
260  */
261 static int pack_ap_id_cmp_request(ap_id_cmp_params_t *params, char **buf,
262 			int *buf_size);
263 static int unpack_ap_id_cmp_request(ap_id_cmp_params_t *params,
264 			const char *buf);
265 
266 /*
267  * Abort Routines
268  */
269 static int pack_abort_cmd_request(abort_cmd_params_t *params, char **buf,
270 			int *buf_size);
271 static int unpack_abort_cmd_request(abort_cmd_params_t *params,
272 			const char *buf);
273 
274 /*
275  * Confirm Callback Routines
276  */
277 static int pack_confirm_request(confirm_callback_params_t *params, char **buf,
278 			int *buf_size);
279 static int unpack_confirm_request(confirm_callback_params_t *params,
280 			const char *buf);
281 static int pack_confirm_reply(confirm_callback_params_t *params,
282 			char **buf, int *buf_size);
283 static int unpack_confirm_reply(confirm_callback_params_t *params,
284 			const char *buf);
285 
286 /*
287  * Message Callback Routines
288  */
289 static int pack_message_request(msg_callback_params_t *params, char **buf,
290 			int *buf_size);
291 static int unpack_message_request(msg_callback_params_t *params,
292 			const char *buf);
293 
294 /*
295  * Resource Info Routines
296  */
297 static int pack_rsrc_info_request(rsrc_info_params_t *params, char **buf,
298 			int *buf_size);
299 static int unpack_rsrc_info_request(rsrc_info_params_t *params,
300 			const char *buf);
301 static int pack_rsrc_info_reply(rsrc_info_params_t *params, char **buf,
302 			int *buf_size, int encoding);
303 static int unpack_rsrc_info_reply(rsrc_info_params_t *params, const char *buf);
304 
305 /*
306  * General Pack/Unpack Routines
307  */
308 static int pack_ap_ids(int num_ap_ids, char *const *ap_ids,
309 			rdr_variable_message_info_t *var_msg_info);
310 static int unpack_ap_ids(int num_ap_ids, char **ap_ids, const char *buf,
311 			rdr_variable_message_info_t *var_msg_info);
312 
313 /*
314  * Find Variable Info Sizes
315  */
316 static int find_options_sizes(char *options,
317 			rdr_variable_message_info_t *var_msg_info);
318 static int find_listopts_sizes(char *listopts,
319 			rdr_variable_message_info_t *var_msg_info);
320 static int find_function_sizes(char *function,
321 			rdr_variable_message_info_t *var_msg_info);
322 static int find_errstring_sizes(char **errstring,
323 			rdr_variable_message_info_t *var_msg_info);
324 
325 /*
326  * Extract Info From Buffers
327  */
328 static int get_ap_ids_from_buf(char ***ap_id_ptr, int num_ap_ids,
329 			rdr_variable_message_info_t *var_msg_info,
330 			const char *buf);
331 static int get_string_from_buf(char **stringptr, int strsize, const char *buf);
332 
333 
334 /*
335  * Cleanup Routines
336  */
337 static int cleanup_ap_ids(int num_ap_ids, char **ap_ids);
338 
339 static int cleanup_errstring(char **errstring);
340 
341 static void cleanup_variable_ap_id_info(
342 			rdr_variable_message_info_t *var_msg_info);
343 
344 /*
345  * Functions for loading libdscp.
346  */
347 static int load_libdscp(libdscp_t *libdscp);
348 
349 /*
350  * Public Functions
351  */
352 
353 
354 /*
355  * rdr_open:
356  *
357  * Establish a transport endpoint to prepare for a new
358  * connection. Returns a file descriptor representing the
359  * new transport if successful or RDR_BAD_FD upon failure.
360  */
361 int
362 rdr_open(int family)
363 {
364 	int	newfd;
365 
366 
367 	if ((newfd = socket(family, SOCK_STREAM, 0)) == NULL) {
368 		return (RDR_BAD_FD);
369 	}
370 
371 	return (newfd);
372 }
373 
374 
375 /*
376  * rdr_init:
377  *
378  * Initialize a transport endpoint. This involves binding to
379  * a particular port and setting any user specified socket
380  * options.
381  */
382 int
383 rdr_init(int fd, struct sockaddr *addr, int *opts, int num_opts, int blog)
384 {
385 	int	i;
386 
387 
388 	/* sanity checks */
389 	if ((fd < 0) || (addr == NULL)) {
390 		return (RDR_ERROR);
391 	}
392 
393 	if ((opts == NULL) || (num_opts < 0)) {
394 		num_opts = 0;
395 	}
396 
397 	/* turn on security features */
398 	if (rdr_secure(fd, addr) != RDR_OK) {
399 		return (RDR_NET_ERR);
400 	}
401 
402 	/* bind the address, if is not already bound */
403 	if (rdr_bind(fd, addr) != RDR_OK) {
404 		return (RDR_NET_ERR);
405 	}
406 
407 	/*
408 	 * Set TCP_NODELAY for this endpoint. This disables Nagle's
409 	 * algorithm that can cause a delay in sending small sized
410 	 * messages. Since most of the RDR messages are small, this
411 	 * is a restriction that negatively impacts performance.
412 	 */
413 	if (rdr_setopt(fd, TCP_NODELAY, IPPROTO_TCP) != RDR_OK) {
414 		return (RDR_NET_ERR);
415 	}
416 
417 	/* set the user specified socket options */
418 	for (i = 0; i < num_opts; i++) {
419 		if (rdr_setopt(fd, opts[i], SOL_SOCKET) != RDR_OK) {
420 			return (RDR_NET_ERR);
421 		}
422 	}
423 
424 	/*
425 	 * If blog is not zero, it is a server that is being
426 	 * initialized. In order for it to be able to accept
427 	 * connections, we have to set the size of the incoming
428 	 * connection queue.
429 	 */
430 	if (blog != 0) {
431 		if (listen(fd, blog) == -1) {
432 			return (RDR_NET_ERR);
433 		}
434 	}
435 
436 	return (RDR_OK);
437 }
438 
439 
440 /*
441  * rdr_connect_clnt:
442  *
443  * Perform the necessary steps for a client to connect to
444  * a server process. The required information is the file
445  * descriptor for the transport endpoint, and the remote
446  * address.
447  */
448 int
449 rdr_connect_clnt(int fd, struct sockaddr *addr)
450 {
451 	unsigned int	addr_len;
452 
453 
454 	/* sanity check */
455 	if (addr == NULL) {
456 		return (RDR_ERROR);
457 	}
458 
459 	/* initialize the address length */
460 	switch (addr->sa_family) {
461 
462 	case AF_INET:
463 		addr_len = sizeof (struct sockaddr_in);
464 		break;
465 
466 	case AF_INET6:
467 		addr_len = sizeof (struct sockaddr_in6);
468 		break;
469 
470 	default:
471 		return (RDR_ERROR);
472 	}
473 
474 	/* attempt the connection */
475 	if (connect(fd, addr, addr_len) == -1) {
476 		return (RDR_NET_ERR);
477 	}
478 
479 	return (RDR_OK);
480 }
481 
482 
483 /*
484  * rdr_connect_srv:
485  *
486  * Perform the necessary steps for a server to connect to a
487  * pending client request. The new connection is allocated a
488  * new file descriptor, separate from the one used to accept
489  * the connection.
490  */
491 int
492 rdr_connect_srv(int fd)
493 {
494 	int			newfd;
495 	unsigned int		faddr_len;
496 	struct sockaddr_storage	faddr;
497 
498 
499 	/* accept the connection */
500 	faddr_len = sizeof (faddr);
501 	if ((newfd = accept(fd, (struct sockaddr *)&faddr, &faddr_len)) == -1) {
502 		return (RDR_BAD_FD);
503 	}
504 
505 	/* if the peer doesn't authenticate properly, reject */
506 	if (rdr_auth((struct sockaddr *)&faddr, faddr_len) != RDR_OK) {
507 		(void) close(newfd);
508 		return (RDR_BAD_FD);
509 	}
510 
511 	return (newfd);
512 }
513 
514 
515 /*
516  * rdr_reject:
517  *
518  * Reject an incoming connection attempt. This requires
519  * that the connection be accepted first.
520  */
521 int
522 rdr_reject(int fd)
523 {
524 	unsigned int		faddr_len;
525 	struct sockaddr_storage	faddr;
526 
527 
528 	/* first accept the connection */
529 	faddr_len = sizeof (faddr);
530 	if (accept(fd, (struct sockaddr *)&faddr, &faddr_len) == -1) {
531 		return (RDR_NET_ERR);
532 	}
533 
534 	/* then close it */
535 	(void) close(fd);
536 
537 	return (RDR_OK);
538 }
539 
540 
541 /*
542  * rdr_close:
543  *
544  * Close down an given connection.
545  */
546 int
547 rdr_close(int fd)
548 {
549 	(void) close(fd);
550 
551 	return (RDR_OK);
552 }
553 
554 
555 /*
556  * rdr_snd_msg:
557  *
558  * Public interface for sending an RDR message. The data
559  * passed in through hdr and param are packed for network
560  * transport and sent.
561  */
562 int
563 rdr_snd_msg(int fd, rdr_msg_hdr_t *hdr, cfga_params_t *param, int timeout)
564 {
565 	int	err;
566 	char	*pack_buf = NULL;
567 	int	pack_buf_sz = 0;
568 
569 
570 	/* sanity checks */
571 	if ((hdr == NULL) || (param == NULL)) {
572 		return (RDR_ERROR);
573 	}
574 
575 	/*
576 	 * Pack the message for transport
577 	 */
578 	switch (hdr->message_opcode) {
579 
580 		case RDR_SES_REQ: {
581 
582 			ses_req_params_t *rparam;
583 			rparam = (ses_req_params_t *)param;
584 
585 			if (hdr->data_type == RDR_REQUEST) {
586 				err = pack_ses_req_request(rparam,
587 				    &pack_buf, &pack_buf_sz);
588 			} else {
589 				err = pack_ses_req_reply(rparam,
590 				    &pack_buf, &pack_buf_sz);
591 			}
592 
593 			break;
594 		}
595 
596 		case RDR_SES_ESTBL:
597 		case RDR_SES_END:
598 
599 			/*
600 			 * This is not an error condition because
601 			 * there is no extra information to pack.
602 			 */
603 			err = RDR_OK;
604 			break;
605 
606 		case RDR_CONF_CHANGE_STATE: {
607 
608 			change_state_params_t *cparam;
609 			cparam = (change_state_params_t *)param;
610 
611 			if (hdr->data_type == RDR_REQUEST) {
612 				err = pack_change_state_request(cparam,
613 				    &pack_buf, &pack_buf_sz);
614 			} else {
615 				err = pack_change_state_reply(cparam,
616 				    &pack_buf, &pack_buf_sz);
617 			}
618 			break;
619 		}
620 
621 		case RDR_CONF_PRIVATE_FUNC: {
622 
623 			private_func_params_t *pparam;
624 			pparam = (private_func_params_t *)param;
625 
626 			if (hdr->data_type == RDR_REQUEST) {
627 				err = pack_private_func_request(pparam,
628 				    &pack_buf, &pack_buf_sz);
629 			} else {
630 				err = pack_private_func_reply(pparam,
631 				    &pack_buf, &pack_buf_sz);
632 			}
633 			break;
634 		}
635 
636 		case RDR_CONF_TEST: {
637 
638 			test_params_t *tparam;
639 			tparam = (test_params_t *)param;
640 
641 			if (hdr->data_type == RDR_REQUEST) {
642 				err = pack_test_request(tparam,
643 				    &pack_buf, &pack_buf_sz);
644 			} else {
645 				err = pack_test_reply(tparam,
646 				    &pack_buf, &pack_buf_sz);
647 			}
648 			break;
649 		}
650 
651 		case RDR_CONF_LIST_EXT: {
652 
653 			list_ext_params_t *lparam;
654 			lparam = (list_ext_params_t *)param;
655 
656 			if (hdr->data_type == RDR_REQUEST) {
657 				err = pack_list_ext_request(lparam, &pack_buf,
658 				    &pack_buf_sz);
659 			} else {
660 				err = pack_list_ext_reply(lparam, &pack_buf,
661 				    &pack_buf_sz);
662 			}
663 			break;
664 		}
665 
666 		case RDR_CONF_HELP: {
667 
668 			help_params_t *hparam;
669 			hparam = (help_params_t *)param;
670 
671 			if (hdr->data_type == RDR_REQUEST) {
672 				err = pack_help_request(hparam,
673 				    &pack_buf, &pack_buf_sz);
674 			} else {
675 
676 				/*
677 				 * This is not an error because help
678 				 * reply does not have any extra information
679 				 * to pack.
680 				 */
681 				err = RDR_OK;
682 			}
683 			break;
684 		}
685 
686 		case RDR_CONF_AP_ID_CMP: {
687 
688 			ap_id_cmp_params_t *aparam;
689 			aparam = (ap_id_cmp_params_t *)param;
690 
691 			if (hdr->data_type == RDR_REQUEST) {
692 				err = pack_ap_id_cmp_request(aparam,
693 				    &pack_buf, &pack_buf_sz);
694 			} else {
695 
696 				/*
697 				 * This is not an error because ap_id_cmp
698 				 * reply does not have any extra information
699 				 * to pack.
700 				 */
701 				err = RDR_OK;
702 			}
703 			break;
704 		}
705 
706 		case RDR_CONF_ABORT_CMD: {
707 
708 			abort_cmd_params_t *aparam;
709 			aparam = (abort_cmd_params_t *)param;
710 
711 			if (hdr->data_type == RDR_REQUEST) {
712 				err = pack_abort_cmd_request(aparam,
713 				    &pack_buf, &pack_buf_sz);
714 			} else {
715 				/*
716 				 * This is not an error because session
717 				 * abort reply does not have any extra
718 				 * information to pack.
719 				 */
720 				err = RDR_OK;
721 			}
722 			break;
723 		}
724 
725 		case RDR_CONF_CONFIRM_CALLBACK: {
726 
727 			confirm_callback_params_t *cparam;
728 			cparam = (confirm_callback_params_t *)param;
729 
730 			if (hdr->data_type == RDR_REQUEST) {
731 				err = pack_confirm_request(cparam,
732 				    &pack_buf, &pack_buf_sz);
733 			} else {
734 				err = pack_confirm_reply(cparam, &pack_buf,
735 				    &pack_buf_sz);
736 			}
737 			break;
738 		}
739 
740 		case RDR_CONF_MSG_CALLBACK: {
741 
742 			msg_callback_params_t *mparam;
743 			mparam = (msg_callback_params_t *)param;
744 
745 			if (hdr->data_type == RDR_REQUEST) {
746 				err = pack_message_request(mparam,
747 				    &pack_buf, &pack_buf_sz);
748 			} else {
749 				/*
750 				 * It is an error to send a reply
751 				 * to a message callback.
752 				 */
753 				err = RDR_MSG_INVAL;
754 			}
755 			break;
756 		}
757 
758 		case RDR_RSRC_INFO: {
759 
760 			rsrc_info_params_t *rparam;
761 			rparam = (rsrc_info_params_t *)param;
762 
763 			if (hdr->data_type == RDR_REQUEST) {
764 				err = pack_rsrc_info_request(rparam, &pack_buf,
765 				    &pack_buf_sz);
766 			} else {
767 				if ((hdr->major_version == 1) &&
768 				    (hdr->minor_version == 0)) {
769 					err = pack_rsrc_info_reply(rparam,
770 					    &pack_buf, &pack_buf_sz,
771 					    NV_ENCODE_NATIVE);
772 				} else {
773 					err = pack_rsrc_info_reply(rparam,
774 					    &pack_buf, &pack_buf_sz,
775 					    NV_ENCODE_XDR);
776 				}
777 			}
778 			break;
779 		}
780 
781 		default:
782 			err = RDR_MSG_INVAL;
783 			break;
784 	}
785 
786 	/* check if packed correctly */
787 	if (err != RDR_OK) {
788 		return (err);
789 	}
790 
791 	/* send the message */
792 	err = rdr_snd(fd, hdr, pack_buf, pack_buf_sz, timeout);
793 
794 	free((void *)pack_buf);
795 
796 	return (err);
797 }
798 
799 
800 /*
801  * rdr_rcv_msg:
802  *
803  * Public interface for receiving an RDR message. Data is
804  * unpacked into the hdr and param paramters.
805  */
806 int
807 rdr_rcv_msg(int fd, rdr_msg_hdr_t *hdr, cfga_params_t *param, int timeout)
808 {
809 	int	err;
810 	char	*unpack_buf = NULL;
811 
812 
813 	/* sanity checks */
814 	if ((hdr == NULL) || (param == NULL)) {
815 		return (RDR_ERROR);
816 	}
817 
818 	(void) memset(param, 0, sizeof (cfga_params_t));
819 
820 	/* receive the message */
821 	if ((err = rdr_rcv(fd, hdr, &unpack_buf, timeout)) != RDR_OK) {
822 		return (err);
823 	}
824 
825 	/*
826 	 * Unpack the message
827 	 */
828 	switch (hdr->message_opcode) {
829 
830 		case RDR_SES_REQ: {
831 
832 			ses_req_params_t *rparam;
833 			rparam = (ses_req_params_t *)param;
834 
835 			if (hdr->data_type == RDR_REQUEST) {
836 				err = unpack_ses_req_request(rparam,
837 				    unpack_buf);
838 			} else {
839 				err = unpack_ses_req_reply(rparam, unpack_buf);
840 			}
841 			break;
842 		}
843 
844 		case RDR_SES_ESTBL:
845 		case RDR_SES_END:
846 
847 			/* no information to unpack */
848 			(void) memset(param, 0, sizeof (cfga_params_t));
849 			err = RDR_OK;
850 			break;
851 
852 		case RDR_CONF_CHANGE_STATE: {
853 
854 			change_state_params_t *cparam;
855 			cparam = (change_state_params_t *)param;
856 
857 			if (hdr->data_type == RDR_REQUEST) {
858 				err = unpack_change_state_request(cparam,
859 				    unpack_buf);
860 			} else {
861 				err = unpack_change_state_reply(cparam,
862 				    unpack_buf);
863 			}
864 			break;
865 		}
866 
867 		case RDR_CONF_PRIVATE_FUNC: {
868 
869 			private_func_params_t *pparam;
870 			pparam = (private_func_params_t *)param;
871 
872 			if (hdr->data_type == RDR_REQUEST) {
873 				err = unpack_private_func_request(pparam,
874 				    unpack_buf);
875 			} else {
876 				err = unpack_private_func_reply(pparam,
877 				    unpack_buf);
878 			}
879 			break;
880 		}
881 
882 		case RDR_CONF_TEST: {
883 
884 			test_params_t *tparam;
885 			tparam = (test_params_t *)param;
886 
887 			if (hdr->data_type == RDR_REQUEST) {
888 				err = unpack_test_request(tparam, unpack_buf);
889 			} else {
890 				err = unpack_test_reply(tparam, unpack_buf);
891 			}
892 			break;
893 		}
894 
895 		case RDR_CONF_LIST_EXT: {
896 
897 			list_ext_params_t *lparam;
898 			lparam = (list_ext_params_t *)param;
899 
900 			if (hdr->data_type == RDR_REQUEST) {
901 				err = unpack_list_ext_request(lparam,
902 				    unpack_buf);
903 			} else {
904 				err = unpack_list_ext_reply(lparam, unpack_buf);
905 			}
906 			break;
907 		}
908 
909 		case RDR_CONF_HELP: {
910 
911 			help_params_t *hparam;
912 			hparam = (help_params_t *)param;
913 
914 			if (hdr->data_type == RDR_REQUEST) {
915 				err = unpack_help_request(hparam,
916 				    unpack_buf);
917 			} else {
918 				/*
919 				 * This is not an error because help
920 				 * reply does not have any extra information
921 				 * to unpack.
922 				 */
923 				err = RDR_OK;
924 			}
925 			break;
926 		}
927 
928 		case RDR_CONF_AP_ID_CMP: {
929 
930 			ap_id_cmp_params_t *aparam;
931 			aparam = (ap_id_cmp_params_t *)param;
932 
933 			if (hdr->data_type == RDR_REQUEST) {
934 				err = unpack_ap_id_cmp_request(aparam,
935 				    unpack_buf);
936 			} else {
937 				/*
938 				 * This is not an error because ap_id_cmp
939 				 * reply does not have any extra information
940 				 * to pack.
941 				 */
942 				err = RDR_OK;
943 			}
944 			break;
945 		}
946 
947 		case RDR_CONF_ABORT_CMD: {
948 
949 			abort_cmd_params_t *aparam;
950 			aparam = (abort_cmd_params_t *)param;
951 
952 			if (hdr->data_type == RDR_REQUEST) {
953 				err = unpack_abort_cmd_request(aparam,
954 				    unpack_buf);
955 			} else {
956 				/* no information to unpack */
957 				(void) memset(param, 0, sizeof (cfga_params_t));
958 				err = RDR_OK;
959 			}
960 
961 			break;
962 		}
963 
964 		case RDR_CONF_CONFIRM_CALLBACK: {
965 
966 			confirm_callback_params_t *cparam;
967 			cparam = (confirm_callback_params_t *)param;
968 
969 			if (hdr->data_type == RDR_REQUEST) {
970 				err = unpack_confirm_request(cparam,
971 				    unpack_buf);
972 			} else {
973 				err = unpack_confirm_reply(cparam, unpack_buf);
974 			}
975 			break;
976 		}
977 
978 		case RDR_CONF_MSG_CALLBACK: {
979 
980 			msg_callback_params_t *mparam;
981 			mparam = (msg_callback_params_t *)param;
982 
983 			if (hdr->data_type == RDR_REQUEST) {
984 				err = unpack_message_request(mparam,
985 				    unpack_buf);
986 			} else {
987 				/*
988 				 * It is an error to send a reply
989 				 * to a message callback.
990 				 */
991 				(void) memset(param, 0, sizeof (cfga_params_t));
992 				err = RDR_MSG_INVAL;
993 			}
994 			break;
995 		}
996 
997 		case RDR_RSRC_INFO: {
998 
999 			rsrc_info_params_t *rparam;
1000 			rparam = (rsrc_info_params_t *)param;
1001 
1002 			if (hdr->data_type == RDR_REQUEST) {
1003 				err = unpack_rsrc_info_request(rparam,
1004 				    unpack_buf);
1005 			} else {
1006 				err = unpack_rsrc_info_reply(rparam,
1007 				    unpack_buf);
1008 			}
1009 			break;
1010 		}
1011 
1012 		default:
1013 			err = RDR_MSG_INVAL;
1014 			break;
1015 	}
1016 
1017 	free(unpack_buf);
1018 
1019 	/* check if unpacked correctly */
1020 	if (err != RDR_OK) {
1021 		return (err);
1022 	}
1023 
1024 	return (RDR_OK);
1025 }
1026 
1027 
1028 /*
1029  * rdr_cleanup_params:
1030  *
1031  * Deallocate any memory that was allocated in unpacking a
1032  * message.
1033  */
1034 int
1035 rdr_cleanup_params(rdr_msg_opcode_t message_opcode, cfga_params_t *param)
1036 {
1037 	/* sanity check */
1038 	if ((param == NULL)) {
1039 		return (RDR_ERROR);
1040 	}
1041 
1042 	/*
1043 	 * Deallocate memory depending on
1044 	 * the operation.
1045 	 */
1046 	switch (message_opcode) {
1047 
1048 	case RDR_SES_REQ: {
1049 
1050 		ses_req_params_t *sparam;
1051 		sparam = (ses_req_params_t *)param;
1052 
1053 		if (sparam->locale_str != NULL) {
1054 			free((void *)sparam->locale_str);
1055 			sparam->locale_str = NULL;
1056 		}
1057 		break;
1058 	}
1059 
1060 	case RDR_SES_ESTBL:
1061 	case RDR_SES_END:
1062 
1063 		/* nothing to deallocate */
1064 		break;
1065 
1066 	case RDR_CONF_CHANGE_STATE: {
1067 
1068 		change_state_params_t *cparam;
1069 		cparam = (change_state_params_t *)param;
1070 
1071 		cleanup_ap_ids(cparam->num_ap_ids, (char **)cparam->ap_ids);
1072 		cparam->ap_ids = NULL;
1073 		if (cparam->options != NULL) {
1074 			free((void *)cparam->options);
1075 			cparam->options = NULL;
1076 		}
1077 		if (cparam->confp != NULL) {
1078 			free((void *)cparam->confp);
1079 			cparam->confp = NULL;
1080 		}
1081 		if (cparam->msgp != NULL) {
1082 			free((void *)cparam->msgp);
1083 			cparam->msgp = NULL;
1084 		}
1085 		cleanup_errstring(cparam->errstring);
1086 		break;
1087 	}
1088 
1089 	case RDR_CONF_PRIVATE_FUNC: {
1090 
1091 		private_func_params_t *pparam;
1092 		pparam = (private_func_params_t *)param;
1093 
1094 		cleanup_ap_ids(pparam->num_ap_ids, (char **)pparam->ap_ids);
1095 		pparam->ap_ids = NULL;
1096 		if (pparam->options != NULL) {
1097 			free((void *)pparam->options);
1098 			pparam->options = NULL;
1099 		}
1100 		if (pparam->confp != NULL) {
1101 			free((void *)pparam->confp);
1102 			pparam->confp = NULL;
1103 		}
1104 		if (pparam->msgp != NULL) {
1105 			free((void *)pparam->msgp);
1106 			pparam->msgp = NULL;
1107 		}
1108 		cleanup_errstring(pparam->errstring);
1109 		break;
1110 	}
1111 
1112 	case RDR_CONF_TEST: {
1113 
1114 		test_params_t *tparam;
1115 		tparam = (test_params_t *)param;
1116 
1117 		cleanup_ap_ids(tparam->num_ap_ids, (char **)tparam->ap_ids);
1118 		tparam->ap_ids = NULL;
1119 		if (tparam->options != NULL) {
1120 			free((void *)tparam->options);
1121 			tparam->options = NULL;
1122 		}
1123 		if (tparam->msgp != NULL) {
1124 			free((void *)tparam->msgp);
1125 			tparam->msgp = NULL;
1126 		}
1127 		cleanup_errstring(tparam->errstring);
1128 		break;
1129 	}
1130 
1131 	case RDR_CONF_LIST_EXT: {
1132 
1133 		list_ext_params_t *lparam;
1134 		lparam = (list_ext_params_t *)param;
1135 
1136 		cleanup_ap_ids(lparam->num_ap_ids, (char **)lparam->ap_ids);
1137 		lparam->ap_ids = NULL;
1138 
1139 		if (lparam->nlist != NULL) {
1140 			free((void *)lparam->nlist);
1141 			lparam->nlist = NULL;
1142 		}
1143 		if (lparam->ap_id_list != NULL) {
1144 			if (*lparam->ap_id_list != NULL) {
1145 				free((void *)*lparam->ap_id_list);
1146 			}
1147 			free((void *)lparam->ap_id_list);
1148 			lparam->ap_id_list = NULL;
1149 		}
1150 		if (lparam->ap_id_list != NULL) {
1151 			free((void *)lparam->ap_id_list);
1152 			lparam->ap_id_list = NULL;
1153 		}
1154 
1155 		if (lparam->options != NULL) {
1156 			free((void *)lparam->options);
1157 			lparam->options = NULL;
1158 		}
1159 		if (lparam->listopts != NULL) {
1160 			free((void *)lparam->listopts);
1161 			lparam->listopts = NULL;
1162 		}
1163 		cleanup_errstring(lparam->errstring);
1164 		break;
1165 	}
1166 
1167 	case RDR_CONF_HELP: {
1168 
1169 		help_params_t *hparam;
1170 		hparam = (help_params_t *)param;
1171 
1172 		cleanup_ap_ids(hparam->num_ap_ids, (char **)hparam->ap_ids);
1173 		hparam->ap_ids = NULL;
1174 		if (hparam->msgp != NULL) {
1175 			free((void *)hparam->msgp);
1176 			hparam->msgp = NULL;
1177 		}
1178 		if (hparam->options != NULL) {
1179 			free((void *)hparam->options);
1180 			hparam->options = NULL;
1181 		}
1182 		break;
1183 	}
1184 
1185 	case RDR_CONF_AP_ID_CMP: {
1186 
1187 		ap_id_cmp_params_t *aparam;
1188 		aparam = (ap_id_cmp_params_t *)param;
1189 
1190 		if (aparam->ap_log_id1 != NULL) {
1191 			free((void *)aparam->ap_log_id1);
1192 			aparam->ap_log_id1 = NULL;
1193 		}
1194 		if (aparam->ap_log_id2 != NULL) {
1195 			free((void *)aparam->ap_log_id2);
1196 			aparam->ap_log_id2 = NULL;
1197 		}
1198 		break;
1199 	}
1200 
1201 	case RDR_CONF_ABORT_CMD:
1202 
1203 		/* nothing to deallocate */
1204 		break;
1205 
1206 	case RDR_CONF_CONFIRM_CALLBACK: {
1207 
1208 		confirm_callback_params_t *cparam;
1209 		cparam = (confirm_callback_params_t *)param;
1210 
1211 		if (cparam->confp != NULL) {
1212 			free((void *)cparam->confp);
1213 			cparam->confp = NULL;
1214 		}
1215 		if (cparam->message != NULL) {
1216 			free((void *)cparam->message);
1217 			cparam->message = NULL;
1218 		}
1219 		break;
1220 	}
1221 
1222 	case RDR_CONF_MSG_CALLBACK: {
1223 
1224 		msg_callback_params_t *mparam;
1225 		mparam = (msg_callback_params_t *)param;
1226 
1227 		if (mparam->msgp != NULL) {
1228 			free((void *)mparam->msgp);
1229 			mparam->msgp = NULL;
1230 		}
1231 		if (mparam->message != NULL) {
1232 			free((void *)mparam->message);
1233 			mparam->message = NULL;
1234 		}
1235 		break;
1236 	}
1237 
1238 	default:
1239 		return (RDR_ERROR);
1240 		/* NOTREACHED */
1241 		break;
1242 
1243 	}
1244 
1245 	return (RDR_OK);
1246 }
1247 
1248 /*
1249  * rdr_setsockopt:
1250  *
1251  * Wrapper of the setsockopt(3SOCKET) library function.
1252  */
1253 int
1254 rdr_setsockopt(int fd, int level, int optname, const void *optval, int optlen)
1255 {
1256 	if (setsockopt(fd, level, optname, optval, optlen) == -1)
1257 		return (RDR_NET_ERR);
1258 	else
1259 		return (RDR_OK);
1260 }
1261 
1262 
1263 /*
1264  * Private (static) Functions
1265  */
1266 
1267 
1268 /*
1269  * rdr_setopt:
1270  *
1271  * Set the specified option for a given transport endpoint.
1272  * This function only sets boolean options. It does not
1273  * provide the ability to unset an option, or set a non-
1274  * boolean option.
1275  */
1276 static int
1277 rdr_setopt(int fd, int name, int level)
1278 {
1279 	int	on = 1;
1280 
1281 
1282 	if (setsockopt(fd, level, name, &on, sizeof (on)) == -1) {
1283 		return (RDR_NET_ERR);
1284 	}
1285 
1286 	return (RDR_OK);
1287 }
1288 
1289 
1290 /*
1291  * rdr_bind:
1292  *
1293  * Bind the specified file descriptor to a specified
1294  * address. If the address is already bound, no error is
1295  * returned. This is the expected behavior if a server
1296  * has been started by inetd (1M).
1297  */
1298 static int
1299 rdr_bind(int fd, struct sockaddr *addr)
1300 {
1301 	unsigned int		addr_len;
1302 	int			rc;
1303 
1304 
1305 	/* initialize the address */
1306 	switch (addr->sa_family) {
1307 
1308 	case AF_INET:
1309 		addr_len = sizeof (struct sockaddr_in);
1310 		break;
1311 
1312 	case AF_INET6:
1313 		addr_len = sizeof (struct sockaddr_in6);
1314 		break;
1315 
1316 	default:
1317 		return (RDR_ERROR);
1318 	}
1319 
1320 	/* attempt to bind the address */
1321 	rc = bind(fd, addr, addr_len);
1322 
1323 	/*
1324 	 * Ignore the error if EINVAL is returned. In
1325 	 * this case, we assume that this means that
1326 	 * the address was already bound. This is not
1327 	 * an error for servers started by inetd (1M).
1328 	 */
1329 	if ((rc == -1) && (errno != EINVAL)) {
1330 		return (RDR_NET_ERR);
1331 	}
1332 
1333 	/*
1334 	 * Retreive the address information of the
1335 	 * address that was actually bound.
1336 	 */
1337 	addr_len = sizeof (*addr);
1338 	if (getsockname(fd, addr, &addr_len) == -1) {
1339 		(void) memset(addr, 0, sizeof (*addr));
1340 		return (RDR_NET_ERR);
1341 	}
1342 
1343 	return (RDR_OK);
1344 }
1345 
1346 
1347 /*
1348  * rdr_secure:
1349  *
1350  * Activate security features for a socket.
1351  *
1352  * Some platforms have libdscp, which provides additional
1353  * security features.  An attempt is made to load libdscp
1354  * and use these features.
1355  *
1356  * Nothing is done if libdscp is not available.
1357  */
1358 static int
1359 rdr_secure(int fd, struct sockaddr *addr)
1360 {
1361 	struct sockaddr_in	*sin;
1362 	int			port;
1363 	int			error;
1364 
1365 	if (use_libdscp == 0) {
1366 		return (RDR_OK);
1367 	}
1368 
1369 	if (load_libdscp(&libdscp) != 1) {
1370 		return (RDR_ERROR);
1371 	}
1372 
1373 	/* LINTED E_BAD_PTR_CAST_ALIGN */
1374 	sin = (struct sockaddr_in *)addr;
1375 	port = ntohs(sin->sin_port);
1376 	error = libdscp.bind(0, fd, port);
1377 
1378 	if ((error != DSCP_OK) && (error != DSCP_ERROR_ALREADY)) {
1379 		return (RDR_ERROR);
1380 	}
1381 
1382 	if (libdscp.secure(0, fd) != DSCP_OK) {
1383 		return (RDR_ERROR);
1384 	}
1385 	return (RDR_OK);
1386 }
1387 
1388 /*
1389  * rdr_auth:
1390  *
1391  * Authenticate if a connection is really from the service
1392  * processor.  This is dependent upon functionality from
1393  * libdscp, so an attempt to load and use libdscp is made.
1394  *
1395  * Without libdscp, this function does nothing.
1396  */
1397 static int
1398 rdr_auth(struct sockaddr *addr, int len)
1399 {
1400 	if (use_libdscp != 0) {
1401 		if ((load_libdscp(&libdscp) == 0) ||
1402 		    (libdscp.auth(0, addr, len) != DSCP_OK)) {
1403 			return (RDR_ERROR);
1404 		}
1405 	}
1406 
1407 	return (RDR_OK);
1408 }
1409 
1410 /*
1411  * rdr_snd:
1412  *
1413  * Send a message in two stages. First the header is sent,
1414  * followed by the packed buffer containing the message
1415  * contents.
1416  */
1417 static int
1418 rdr_snd(int fd, rdr_msg_hdr_t *hdr, char *data, int data_sz, int timeout)
1419 {
1420 	int	err;
1421 
1422 
1423 	/* sanity check */
1424 	if (hdr == NULL) {
1425 		return (RDR_ERROR);
1426 	}
1427 
1428 	/* ensure null pad bytes */
1429 	hdr->pad_byte1 = 0;
1430 	hdr->pad_byte2 = 0;
1431 
1432 	/* initialize size information */
1433 	hdr->data_length = data_sz;
1434 
1435 	/* send message header */
1436 	err = rdr_snd_raw(fd, (char *)hdr, RDR_MSG_HDR_SIZE, timeout);
1437 	if (err != RDR_OK) {
1438 		return (err);
1439 	}
1440 
1441 	/* check if more to send */
1442 	if (data_sz == 0) {
1443 		return (RDR_OK);
1444 	}
1445 
1446 	/* send message data */
1447 	err = rdr_snd_raw(fd, data, data_sz, timeout);
1448 	if (err != RDR_OK) {
1449 		return (err);
1450 	}
1451 
1452 	return (RDR_OK);
1453 }
1454 
1455 
1456 /*
1457  * rdr_snd_raw:
1458  *
1459  * Send a raw buffer of information. This function handles
1460  * the low level details of the send operation.
1461  */
1462 static int
1463 rdr_snd_raw(int fd, char *msg, int data_sz, int timeout)
1464 {
1465 	int		err;
1466 	int		num_bytes;
1467 	int		bytes_left;
1468 	char		*bufp;
1469 	struct pollfd	pfd;
1470 
1471 
1472 	bufp = (char *)msg;
1473 
1474 	bytes_left = data_sz;
1475 
1476 	pfd.fd = fd;
1477 	pfd.events = POLLOUT;
1478 
1479 	while (bytes_left > 0) {
1480 
1481 		pfd.revents = 0;
1482 
1483 		/* wait until we can send the data */
1484 		if ((err = poll(&pfd, 1, timeout)) == -1) {
1485 
1486 			/* poll was interrupted */
1487 			if (errno == EINTR) {
1488 				return (RDR_ABORTED);
1489 			}
1490 
1491 			return (RDR_ERROR);
1492 
1493 		} else if (err == 0) {
1494 			return (RDR_TIMEOUT);
1495 		}
1496 
1497 		/* ready to send data */
1498 		if (pfd.revents & POLLOUT) {
1499 
1500 			num_bytes = write(fd, bufp, bytes_left);
1501 
1502 			if (num_bytes == -1) {
1503 
1504 				/*
1505 				 * Distinguish between an aborted
1506 				 * session and other network errors.
1507 				 */
1508 				if (errno == EPIPE) {
1509 					return (RDR_ABORTED);
1510 				} else {
1511 					return (RDR_NET_ERR);
1512 				}
1513 			}
1514 
1515 			/* wrote 0 bytes, so operation was aborted */
1516 			if (num_bytes == 0) {
1517 				return (RDR_ABORTED);
1518 			}
1519 
1520 		} else {
1521 			return (RDR_NET_ERR);
1522 		}
1523 
1524 		bytes_left -= num_bytes;
1525 		bufp += num_bytes;
1526 	}
1527 
1528 	return (RDR_OK);
1529 }
1530 
1531 
1532 /*
1533  * rdr_rcv:
1534  *
1535  * Receive a message in two stages. First the header is
1536  * received, followed by the packed buffer containing the
1537  * message contents.
1538  */
1539 static int
1540 rdr_rcv(int fd, rdr_msg_hdr_t *hdr, char **data, int timeout)
1541 {
1542 	int	err;
1543 	int	data_sz;
1544 	char	hdr_buf[RDR_MSG_HDR_SIZE];
1545 	char	*buf = NULL;
1546 
1547 
1548 	/* sanity check */
1549 	if (hdr == NULL) {
1550 		return (RDR_ERROR);
1551 	}
1552 
1553 	/* receive the header */
1554 	err = rdr_rcv_raw(fd, hdr_buf, RDR_MSG_HDR_SIZE, timeout);
1555 	if (err != RDR_OK) {
1556 		return (err);
1557 	}
1558 
1559 	/* verify that the data is good */
1560 	/* LINTED Pointer Cast Alignment Warning */
1561 	if (validate_header((rdr_msg_hdr_t *)hdr_buf) != RDR_OK) {
1562 		return (RDR_MSG_INVAL);
1563 	}
1564 
1565 	/* LINTED Pointer Cast Alignment Warning */
1566 	data_sz = ((rdr_msg_hdr_t *)hdr_buf)->data_length;
1567 
1568 	buf = (char *)malloc(data_sz);
1569 	if (!buf) {
1570 		return (RDR_MEM_ALLOC);
1571 	}
1572 
1573 	if (data_sz != 0) {
1574 
1575 		/* receive the rest of the message */
1576 		err = rdr_rcv_raw(fd, buf, data_sz, timeout);
1577 		if (err != RDR_OK) {
1578 			free((void *)buf);
1579 			return (err);
1580 		}
1581 	}
1582 
1583 	/* copy out data */
1584 	*data = buf;
1585 	(void) memcpy(hdr, hdr_buf, RDR_MSG_HDR_SIZE);
1586 
1587 	return (RDR_OK);
1588 }
1589 
1590 
1591 /*
1592  * rdr_rcv_raw:
1593  *
1594  * Receive a raw buffer of information. This function handles
1595  * the low level details of the receive operation.
1596  */
1597 static int
1598 rdr_rcv_raw(int fd, char *msg, int data_size, int timeout)
1599 {
1600 	int		num_bytes;
1601 	int		err;
1602 	int		bytes_left;
1603 	char		*bufp;
1604 	struct pollfd	pollfd;
1605 
1606 
1607 	bufp = (char *)msg;
1608 	bytes_left = data_size;
1609 
1610 	pollfd.fd = fd;
1611 	pollfd.events = POLLIN;
1612 
1613 	while (bytes_left > 0) {
1614 
1615 		errno = 0;
1616 		pollfd.revents = 0;
1617 
1618 		if ((err = poll(&pollfd, 1, timeout)) == -1) {
1619 
1620 			/*
1621 			 * In the DCA, if a session is aborted, SIGINT
1622 			 * is delivered to all active sessions. This
1623 			 * mistakenly causes all sessions waiting in
1624 			 * the poll to be interrupted. So, if EINTR
1625 			 * is returned, it is ignored. If another error
1626 			 * occurs right away, the current session really
1627 			 * was aborted. All other sessions won't encounter
1628 			 * an error and will proceed normally.
1629 			 */
1630 			if ((errno == 0) || (errno == EINTR)) {
1631 				continue;
1632 			}
1633 
1634 			return (RDR_ABORTED);
1635 
1636 		} else if (err == 0) {
1637 			return (RDR_TIMEOUT);
1638 		}
1639 
1640 		/* ready to receive data */
1641 		if (pollfd.revents & POLLIN) {
1642 
1643 			num_bytes = read(fd, bufp, bytes_left);
1644 
1645 			if (num_bytes == -1) {
1646 
1647 				/*
1648 				 * Distinguish between an aborted
1649 				 * session and other network errors.
1650 				 */
1651 				if (errno == ECONNRESET) {
1652 					return (RDR_ABORTED);
1653 				} else {
1654 					return (RDR_NET_ERR);
1655 				}
1656 			}
1657 
1658 			/* read 0 bytes, so operation was aborted */
1659 			if (num_bytes == 0) {
1660 				return (RDR_ABORTED);
1661 			}
1662 
1663 		} else {
1664 			return (RDR_NET_ERR);
1665 		}
1666 
1667 		bytes_left -= num_bytes;
1668 		bufp += num_bytes;
1669 	}
1670 
1671 	return (RDR_OK);
1672 }
1673 
1674 
1675 /*
1676  * validate_header:
1677  *
1678  * Perform a series of sanity checks on the header data that is
1679  * received. This gets called before the variable length data is
1680  * read in to make sure that the information in the header can
1681  * be trusted.
1682  */
1683 static int
1684 validate_header(rdr_msg_hdr_t *hdr)
1685 {
1686 	unsigned char	op;
1687 
1688 
1689 	if (hdr == NULL) {
1690 		return (RDR_ERROR);
1691 	}
1692 
1693 	op = hdr->message_opcode;
1694 
1695 	/* validate opcode */
1696 	if ((op < RDR_SES_REQ) || (op >= RDR_NUM_OPS)) {
1697 		return (RDR_ERROR);
1698 	}
1699 
1700 	/* validate message size (and type) for op */
1701 	switch (hdr->data_type) {
1702 
1703 	case RDR_REQUEST:
1704 		if (hdr->data_length > msg_sizes[op].req_max) {
1705 			return (RDR_ERROR);
1706 		}
1707 		break;
1708 
1709 	case RDR_REPLY:
1710 		if (hdr->data_length > msg_sizes[op].reply_max) {
1711 			return (RDR_ERROR);
1712 		}
1713 		break;
1714 
1715 	default:
1716 		/* invalid data type */
1717 		return (RDR_ERROR);
1718 	}
1719 
1720 	/* all checks passed */
1721 	return (RDR_OK);
1722 }
1723 
1724 
1725 /*
1726  * pack_ses_req_request:
1727  *
1728  * Handle packing a session request request message.
1729  */
1730 static int
1731 pack_ses_req_request(ses_req_params_t *params, char **buf, int *buf_size)
1732 {
1733 	char		*bufptr;
1734 	int		locale_str_len;
1735 	rdr_ses_req_t	ses_req;
1736 
1737 
1738 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
1739 		return (RDR_ERROR);
1740 	}
1741 
1742 	/*
1743 	 * Determine the size of the locale string
1744 	 */
1745 	if (params->locale_str != NULL) {
1746 		locale_str_len = strlen(params->locale_str) + 1;
1747 	} else {
1748 		locale_str_len = 0;
1749 	}
1750 
1751 	/*
1752 	 * Collect size info specific to the ses_req request message
1753 	 * and allocate a buffer
1754 	 */
1755 	*buf_size = sizeof (rdr_ses_req_t);
1756 	*buf_size += locale_str_len;
1757 
1758 	*buf = (char *)malloc(*buf_size);
1759 	if (*buf == NULL) {
1760 		return (RDR_MEM_ALLOC);
1761 	}
1762 
1763 	/*
1764 	 * Set fixed locale size label by name
1765 	 */
1766 	ses_req.locale_size = locale_str_len;
1767 
1768 	/*
1769 	 * Set variable information using memcpy
1770 	 */
1771 	bufptr = *buf;
1772 
1773 	(void) memcpy(bufptr, &ses_req, sizeof (rdr_ses_req_t));
1774 	bufptr += sizeof (rdr_ses_req_t);
1775 
1776 	if (params->locale_str != NULL) {
1777 		(void) memcpy(bufptr, params->locale_str, locale_str_len);
1778 		bufptr += locale_str_len;
1779 	}
1780 
1781 	return (RDR_OK);
1782 }
1783 
1784 
1785 /*
1786  * unpack_ses_req_request:
1787  *
1788  * Handle unpacking a session request request message.
1789  */
1790 static int
1791 unpack_ses_req_request(ses_req_params_t *params, const char *buf)
1792 {
1793 	char		*bufptr;
1794 	rdr_ses_req_t	ses_req_data;
1795 
1796 
1797 	if ((params == NULL) || (buf == NULL)) {
1798 		return (RDR_ERROR);
1799 	}
1800 
1801 	bufptr = (char *)buf;
1802 	(void) memcpy(&ses_req_data, bufptr, sizeof (rdr_ses_req_t));
1803 	bufptr += sizeof (rdr_ses_req_t);
1804 
1805 	/*
1806 	 * handle getting the locale string
1807 	 */
1808 	if (get_string_from_buf(&(params->locale_str),
1809 	    ses_req_data.locale_size, bufptr)) {
1810 		return (RDR_ERROR);
1811 	}
1812 
1813 	return (RDR_OK);
1814 }
1815 
1816 
1817 /*
1818  * pack_ses_req_reply:
1819  *
1820  * Handle packing a session request reply message.
1821  */
1822 static int
1823 pack_ses_req_reply(ses_req_params_t *params, char **buf, int *buf_size)
1824 {
1825 	rdr_ses_req_reply_t	ses_req_reply_data;
1826 
1827 
1828 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
1829 		return (RDR_ERROR);
1830 	}
1831 
1832 	/*
1833 	 * Collect size info specific to the session request reply
1834 	 * message and allocate a buffer
1835 	 */
1836 	*buf_size = sizeof (rdr_ses_req_reply_t);
1837 
1838 	*buf = (char *)malloc(*buf_size);
1839 	if (*buf == NULL) {
1840 		return (RDR_MEM_ALLOC);
1841 	}
1842 
1843 	/*
1844 	 * Set fixed session identifier
1845 	 */
1846 	ses_req_reply_data.session_id = params->session_id;
1847 
1848 	/*
1849 	 * Copy information using memcpy
1850 	 */
1851 	(void) memcpy(*buf, &ses_req_reply_data, sizeof (rdr_ses_req_reply_t));
1852 
1853 	return (RDR_OK);
1854 }
1855 
1856 
1857 /*
1858  * unpack_ses_req_request:
1859  *
1860  * Handle unpacking a session request reply message.
1861  */
1862 static int
1863 unpack_ses_req_reply(ses_req_params_t *params, const char *buf)
1864 {
1865 	rdr_ses_req_reply_t	*ses_req_reply_datap;
1866 
1867 
1868 	if ((params == NULL) || (buf == NULL)) {
1869 		return (RDR_ERROR);
1870 	}
1871 
1872 	/* LINTED Pointer Cast Alignment Warning */
1873 	ses_req_reply_datap = (rdr_ses_req_reply_t *)buf;
1874 
1875 	/*
1876 	 * copy out the session information
1877 	 */
1878 	params->session_id = ses_req_reply_datap->session_id;
1879 
1880 	return (RDR_OK);
1881 }
1882 
1883 
1884 /*
1885  * pack_change_state_request:
1886  *
1887  * Handle packing a change state request message.
1888  */
1889 static int
1890 pack_change_state_request(change_state_params_t *params, char **buf,
1891     int *buf_size)
1892 {
1893 	int				i;
1894 	char				*bufptr;
1895 	rdr_change_state_t		change_state_data;
1896 	rdr_variable_message_info_t	var_msg_info;
1897 
1898 
1899 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
1900 		return (RDR_ERROR);
1901 	}
1902 
1903 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
1904 
1905 	/*
1906 	 * Set variable length fields and make a call to partially
1907 	 * pack it.
1908 	 */
1909 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
1910 		cleanup_variable_ap_id_info(&var_msg_info);
1911 		return (RDR_ERROR);
1912 	}
1913 	if (find_options_sizes(params->options, &var_msg_info)) {
1914 		cleanup_variable_ap_id_info(&var_msg_info);
1915 		return (RDR_ERROR);
1916 	}
1917 
1918 	/*
1919 	 * Collect size info specific to the change_state request
1920 	 * message and allocate a buffer
1921 	 */
1922 	*buf_size = sizeof (rdr_change_state_t);
1923 	*buf_size += var_msg_info.ap_id_int_size;
1924 	*buf_size += var_msg_info.ap_id_char_size;
1925 	*buf_size += var_msg_info.options_strlen;
1926 	*buf_size += var_msg_info.options_pad_sz;
1927 
1928 	*buf = (char *)malloc(*buf_size);
1929 	if (*buf == NULL) {
1930 		cleanup_variable_ap_id_info(&var_msg_info);
1931 		return (RDR_MEM_ALLOC);
1932 	}
1933 
1934 	/*
1935 	 * Set fixed address labels by name
1936 	 */
1937 	change_state_data.num_ap_ids = params->num_ap_ids;
1938 	change_state_data.ap_id_char_size = var_msg_info.ap_id_char_size;
1939 	change_state_data.options_size = var_msg_info.options_strlen +
1940 	    var_msg_info.options_pad_sz;
1941 
1942 	if (params->confp != NULL) {
1943 		change_state_data.confirm_callback_id =
1944 		    (unsigned long)params->confp->confirm;
1945 		change_state_data.confirm_appdata_ptr =
1946 		    (unsigned long)params->confp->appdata_ptr;
1947 	} else {
1948 		change_state_data.confirm_callback_id = 0;
1949 		change_state_data.confirm_appdata_ptr = 0;
1950 	}
1951 	if (params->msgp != NULL) {
1952 		change_state_data.msg_callback_id =
1953 		    (unsigned long)params->msgp->message_routine;
1954 		change_state_data.msg_appdata_ptr =
1955 		    (unsigned long)params->msgp->appdata_ptr;
1956 	} else {
1957 		change_state_data.msg_callback_id = 0;
1958 		change_state_data.msg_appdata_ptr = 0;
1959 	}
1960 
1961 	change_state_data.flags = params->flags;
1962 	change_state_data.timeval = params->timeval;
1963 	change_state_data.state_change_cmd = params->state_change;
1964 	if (params->errstring != NULL) {
1965 		change_state_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
1966 	} else {
1967 		change_state_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
1968 	}
1969 	change_state_data.retries = params->retries;
1970 
1971 	/*
1972 	 * Set variable information using memcpy
1973 	 */
1974 	bufptr = *buf;
1975 
1976 	(void) memcpy(bufptr, &change_state_data, sizeof (rdr_change_state_t));
1977 	bufptr += sizeof (rdr_change_state_t);
1978 
1979 	if (var_msg_info.ap_id_sizes != NULL) {
1980 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
1981 		    var_msg_info.ap_id_int_size);
1982 		bufptr += var_msg_info.ap_id_int_size;
1983 	}
1984 
1985 	if (var_msg_info.ap_id_chars != NULL) {
1986 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
1987 		    var_msg_info.ap_id_char_size);
1988 		bufptr += var_msg_info.ap_id_char_size;
1989 	}
1990 
1991 	if (params->options != NULL) {
1992 		(void) memcpy(bufptr, params->options,
1993 		    var_msg_info.options_strlen);
1994 		bufptr += var_msg_info.options_strlen;
1995 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
1996 			bufptr[i] = 0;
1997 		}
1998 		bufptr += var_msg_info.options_pad_sz;
1999 	}
2000 
2001 	cleanup_variable_ap_id_info(&var_msg_info);
2002 
2003 	return (RDR_OK);
2004 }
2005 
2006 
2007 /*
2008  * unpack_change_state_request:
2009  *
2010  * Handle unpacking a change state request message.
2011  */
2012 static int
2013 unpack_change_state_request(change_state_params_t *params, const char *buf)
2014 {
2015 	char				*bufptr;
2016 	rdr_variable_message_info_t 	var_msg_info;
2017 	rdr_change_state_t		change_state_data;
2018 
2019 
2020 	if ((params == NULL) || (buf == NULL)) {
2021 		return (RDR_ERROR);
2022 	}
2023 
2024 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2025 
2026 	bufptr = (char *)buf;
2027 	(void) memcpy(&change_state_data, bufptr, sizeof (rdr_change_state_t));
2028 	bufptr += sizeof (rdr_change_state_t);
2029 
2030 	/*
2031 	 * handle getting the ap_ids
2032 	 */
2033 	var_msg_info.ap_id_char_size = change_state_data.ap_id_char_size;
2034 	if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
2035 	    change_state_data.num_ap_ids, &var_msg_info, bufptr)) {
2036 		return (RDR_ERROR);
2037 	}
2038 	bufptr += var_msg_info.ap_id_int_size;
2039 	bufptr += var_msg_info.ap_id_char_size;
2040 
2041 	/*
2042 	 * handle getting the options
2043 	 */
2044 	if (get_string_from_buf(&(params->options),
2045 	    change_state_data.options_size, bufptr)) {
2046 		return (RDR_ERROR);
2047 	}
2048 	bufptr += change_state_data.options_size;
2049 
2050 	/*
2051 	 * Set fixed address labels by name
2052 	 */
2053 	params->state_change = (cfga_cmd_t)change_state_data.state_change_cmd;
2054 	params->num_ap_ids = change_state_data.num_ap_ids;
2055 
2056 	params->confp = (struct cfga_confirm *)
2057 	    malloc(sizeof (struct cfga_confirm));
2058 	if (params->confp == NULL) {
2059 		return (RDR_MEM_ALLOC);
2060 	}
2061 
2062 	/* set params->confp->confirm using memcpy */
2063 	(void) memcpy((void*)params->confp,
2064 	    &(change_state_data.confirm_callback_id), sizeof (unsigned long));
2065 	params->confp->appdata_ptr =
2066 	    (void*)change_state_data.confirm_appdata_ptr;
2067 
2068 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
2069 	if (params->msgp == NULL) {
2070 		return (RDR_MEM_ALLOC);
2071 	}
2072 
2073 	/* set params->msgp->message_routine using memcpy */
2074 	(void) memcpy((void*)params->msgp,
2075 	    &(change_state_data.msg_callback_id), sizeof (unsigned long));
2076 	params->msgp->appdata_ptr =
2077 	    (void*)change_state_data.msg_appdata_ptr;
2078 
2079 	if (change_state_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
2080 		params->errstring = (char **)malloc(sizeof (char *));
2081 		if (params->errstring == NULL) {
2082 			return (RDR_MEM_ALLOC);
2083 		}
2084 		*(params->errstring) = NULL;
2085 	} else {	/* error_msg_ctl == RDR_DONT_GENERATE_ERR_MSGS */
2086 		params->errstring = NULL;
2087 	}
2088 	params->flags = change_state_data.flags;
2089 	params->timeval = change_state_data.timeval;
2090 	params->retries = change_state_data.retries;
2091 
2092 	return (RDR_OK);
2093 }
2094 
2095 
2096 /*
2097  * pack_change_state_reply:
2098  *
2099  * Handle packing a change state reply message.
2100  */
2101 static int
2102 pack_change_state_reply(change_state_params_t *params, char **buf,
2103     int *buf_size)
2104 {
2105 	int				i;
2106 	char				*bufptr;
2107 	rdr_change_state_reply_t	change_state_data;
2108 	rdr_variable_message_info_t 	var_msg_info;
2109 
2110 
2111 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2112 
2113 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
2114 		return (RDR_ERROR);
2115 	}
2116 
2117 	/*
2118 	 * Set variable length fields (size info)
2119 	 */
2120 	if (find_errstring_sizes(params->errstring, &var_msg_info)) {
2121 		return (RDR_ERROR);
2122 	}
2123 
2124 	/*
2125 	 * Collect size info specific to the change_state reply
2126 	 * message and allocate a buffer
2127 	 */
2128 	*buf_size = sizeof (rdr_change_state_reply_t);
2129 	*buf_size += var_msg_info.errstring_strlen;
2130 	*buf_size += var_msg_info.errstring_pad_sz;
2131 
2132 	*buf = (char *)malloc(*buf_size);
2133 	if (*buf == NULL) {
2134 		return (RDR_MEM_ALLOC);
2135 	}
2136 
2137 	/*
2138 	 * Set fixed address labels by name
2139 	 */
2140 	change_state_data.errstring_size = var_msg_info.errstring_strlen +
2141 	    var_msg_info.errstring_pad_sz;
2142 
2143 	/*
2144 	 * Set variable information using memcpy
2145 	 */
2146 	bufptr = *buf;
2147 
2148 	(void) memcpy(bufptr, &change_state_data,
2149 	    sizeof (rdr_change_state_reply_t));
2150 	bufptr += sizeof (rdr_change_state_reply_t);
2151 
2152 	if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
2153 		(void) memcpy(bufptr, *(params->errstring),
2154 		    var_msg_info.errstring_strlen);
2155 		bufptr += var_msg_info.errstring_strlen;
2156 		for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
2157 			bufptr[i] = 0;
2158 		}
2159 		bufptr += var_msg_info.errstring_pad_sz;
2160 	}
2161 
2162 	return (RDR_OK);
2163 }
2164 
2165 
2166 /*
2167  * unpack_change_state_reply:
2168  *
2169  * Handle unpacking a change state reply message.
2170  */
2171 static int
2172 unpack_change_state_reply(change_state_params_t *params, const char *buf)
2173 {
2174 	char				*bufptr;
2175 	rdr_change_state_reply_t	change_state_data;
2176 
2177 	if ((params == NULL) || (buf == NULL)) {
2178 		return (RDR_ERROR);
2179 	}
2180 
2181 	bufptr = (char *)buf;
2182 	(void) memcpy(&change_state_data, bufptr,
2183 	    sizeof (rdr_change_state_reply_t));
2184 	bufptr += sizeof (rdr_change_state_reply_t);
2185 
2186 	/*
2187 	 * handle getting the errstring
2188 	 */
2189 	params->errstring = (char **)malloc(sizeof (char *));
2190 	if (params->errstring == NULL) {
2191 		return (RDR_MEM_ALLOC);
2192 	}
2193 	if (get_string_from_buf(params->errstring,
2194 	    change_state_data.errstring_size, bufptr)) {
2195 		return (RDR_ERROR);
2196 	}
2197 	bufptr += change_state_data.errstring_size;
2198 
2199 	return (RDR_OK);
2200 }
2201 
2202 
2203 /*
2204  * pack_private_func_request:
2205  *
2206  * Handle packing a private function request message.
2207  */
2208 static int
2209 pack_private_func_request(private_func_params_t *params, char **buf,
2210     int *buf_size)
2211 {
2212 	int				i;
2213 	char				*bufptr;
2214 	rdr_private_func_t		private_func_data;
2215 	rdr_variable_message_info_t	var_msg_info;
2216 
2217 
2218 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
2219 		return (RDR_ERROR);
2220 	}
2221 
2222 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2223 
2224 	/*
2225 	 * Set variable length fields and make a call to partially
2226 	 * pack it.
2227 	 */
2228 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
2229 		cleanup_variable_ap_id_info(&var_msg_info);
2230 		return (RDR_ERROR);
2231 	}
2232 	if (find_options_sizes(params->options, &var_msg_info)) {
2233 		cleanup_variable_ap_id_info(&var_msg_info);
2234 		return (RDR_ERROR);
2235 	}
2236 	if (find_function_sizes(params->function, &var_msg_info)) {
2237 		cleanup_variable_ap_id_info(&var_msg_info);
2238 		return (RDR_ERROR);
2239 	}
2240 
2241 	/*
2242 	 * Collect size info specific to the private_func request
2243 	 * message and allocate a buffer
2244 	 */
2245 	*buf_size = sizeof (rdr_private_func_t);
2246 	*buf_size += var_msg_info.ap_id_int_size;
2247 	*buf_size += var_msg_info.ap_id_char_size;
2248 	*buf_size += var_msg_info.options_strlen;
2249 	*buf_size += var_msg_info.options_pad_sz;
2250 	*buf_size += var_msg_info.function_strlen;
2251 	*buf_size += var_msg_info.function_pad_sz;
2252 
2253 	*buf = (char *)malloc(*buf_size);
2254 	if (*buf == NULL) {
2255 		cleanup_variable_ap_id_info(&var_msg_info);
2256 		return (RDR_MEM_ALLOC);
2257 	}
2258 
2259 	/*
2260 	 * Set fixed address labels by name
2261 	 */
2262 	private_func_data.num_ap_ids = params->num_ap_ids;
2263 	private_func_data.ap_id_char_size = var_msg_info.ap_id_char_size;
2264 	private_func_data.options_size = var_msg_info.options_strlen +
2265 	    var_msg_info.options_pad_sz;
2266 	private_func_data.function_size = var_msg_info.function_strlen +
2267 	    var_msg_info.function_pad_sz;
2268 
2269 	if (params->confp != NULL) {
2270 		private_func_data.confirm_callback_id =
2271 		    (unsigned long)params->confp->confirm;
2272 		private_func_data.confirm_appdata_ptr =
2273 		    (unsigned long)params->confp->appdata_ptr;
2274 	} else {
2275 		private_func_data.confirm_callback_id = 0;
2276 		private_func_data.confirm_appdata_ptr = 0;
2277 	}
2278 	if (params->msgp != NULL) {
2279 		private_func_data.msg_callback_id =
2280 		    (unsigned long)params->msgp->message_routine;
2281 		private_func_data.msg_appdata_ptr =
2282 		    (unsigned long)params->msgp->appdata_ptr;
2283 	} else {
2284 		private_func_data.msg_callback_id = 0;
2285 		private_func_data.msg_appdata_ptr = 0;
2286 	}
2287 
2288 	private_func_data.flags = params->flags;
2289 
2290 	if (params->errstring != NULL) {
2291 		private_func_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
2292 	} else {
2293 		private_func_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
2294 	}
2295 
2296 	/*
2297 	 * Set variable information using memcpy
2298 	 */
2299 	bufptr = *buf;
2300 
2301 	(void) memcpy(bufptr, &private_func_data, sizeof (rdr_private_func_t));
2302 	bufptr += sizeof (rdr_private_func_t);
2303 
2304 	if (var_msg_info.ap_id_sizes != NULL) {
2305 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
2306 		    var_msg_info.ap_id_int_size);
2307 		bufptr += var_msg_info.ap_id_int_size;
2308 	}
2309 
2310 	if (var_msg_info.ap_id_chars != NULL) {
2311 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
2312 		    var_msg_info.ap_id_char_size);
2313 		bufptr += var_msg_info.ap_id_char_size;
2314 	}
2315 
2316 	if (params->options != NULL) {
2317 		(void) memcpy(bufptr, params->options,
2318 		    var_msg_info.options_strlen);
2319 		bufptr += var_msg_info.options_strlen;
2320 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
2321 			bufptr[i] = 0;
2322 		}
2323 		bufptr += var_msg_info.options_pad_sz;
2324 	}
2325 
2326 	if (params->function != NULL) {
2327 		(void) memcpy(bufptr, params->function,
2328 		    var_msg_info.function_strlen);
2329 		bufptr += var_msg_info.function_strlen;
2330 		for (i = 0; i < var_msg_info.function_pad_sz; i++) {
2331 			bufptr[i] = 0;
2332 		}
2333 		bufptr += var_msg_info.function_pad_sz;
2334 	}
2335 
2336 	cleanup_variable_ap_id_info(&var_msg_info);
2337 
2338 	return (RDR_OK);
2339 }
2340 
2341 
2342 /*
2343  * unpack_private_func_request:
2344  *
2345  * Handle unpacking a private function request message.
2346  */
2347 static int
2348 unpack_private_func_request(private_func_params_t *params, const char *buf)
2349 {
2350 	char				*bufptr;
2351 	rdr_variable_message_info_t 	var_msg_info;
2352 	rdr_private_func_t		private_func_data;
2353 
2354 
2355 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2356 
2357 	if ((params == NULL) || (buf == NULL)) {
2358 		return (RDR_ERROR);
2359 	}
2360 
2361 	bufptr = (char *)buf;
2362 	(void) memcpy(&private_func_data, bufptr, sizeof (rdr_private_func_t));
2363 	bufptr += sizeof (rdr_private_func_t);
2364 
2365 	/*
2366 	 * handle getting the ap_ids
2367 	 */
2368 	var_msg_info.ap_id_char_size = private_func_data.ap_id_char_size;
2369 	if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
2370 	    private_func_data.num_ap_ids, &var_msg_info, bufptr)) {
2371 		return (RDR_ERROR);
2372 	}
2373 	bufptr += var_msg_info.ap_id_int_size;
2374 	bufptr += var_msg_info.ap_id_char_size;
2375 
2376 	/*
2377 	 * handle getting the options and function
2378 	 */
2379 	if (get_string_from_buf(&(params->options),
2380 	    private_func_data.options_size, bufptr)) {
2381 		return (RDR_ERROR);
2382 	}
2383 	bufptr += private_func_data.options_size;
2384 
2385 	if (get_string_from_buf(&(params->function),
2386 	    private_func_data.function_size, bufptr)) {
2387 		return (RDR_ERROR);
2388 	}
2389 	bufptr += private_func_data.function_size;
2390 
2391 	/*
2392 	 * Set fixed address labels by name
2393 	 */
2394 	params->num_ap_ids = private_func_data.num_ap_ids;
2395 
2396 	params->confp = (struct cfga_confirm *)
2397 	    malloc(sizeof (struct cfga_confirm));
2398 	if (params->confp == NULL) {
2399 		return (RDR_MEM_ALLOC);
2400 	}
2401 
2402 	/* set params->confp->confirm using memcpy */
2403 	(void) memcpy((void*)params->confp,
2404 	    &(private_func_data.confirm_callback_id), sizeof (unsigned long));
2405 	params->confp->appdata_ptr =
2406 	    (void*)private_func_data.confirm_appdata_ptr;
2407 
2408 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
2409 	if (params->msgp == NULL) {
2410 		return (RDR_MEM_ALLOC);
2411 	}
2412 
2413 	/* set params->msgp->message_routine using memcpy */
2414 	(void) memcpy((void*)params->msgp,
2415 	    &(private_func_data.msg_callback_id), sizeof (unsigned long));
2416 	params->msgp->appdata_ptr =
2417 	    (void*)private_func_data.msg_appdata_ptr;
2418 
2419 	if (private_func_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
2420 		params->errstring = (char **)malloc(sizeof (char *));
2421 		if (params->errstring == NULL) {
2422 			return (RDR_MEM_ALLOC);
2423 		}
2424 		*(params->errstring) = NULL;
2425 	} else {	/* error_msg_ctl == RDR_DONT_GENERATE_ERR_MSGS */
2426 		params->errstring = NULL;
2427 	}
2428 	params->flags = private_func_data.flags;
2429 
2430 	return (RDR_OK);
2431 }
2432 
2433 
2434 /*
2435  * pack_private_func_reply:
2436  *
2437  * Handle packing a private function reply message.
2438  */
2439 static int
2440 pack_private_func_reply(private_func_params_t *params, char **buf,
2441     int *buf_size)
2442 {
2443 	int				i;
2444 	char				*bufptr;
2445 	rdr_private_func_reply_t	private_func_data;
2446 	rdr_variable_message_info_t 	var_msg_info;
2447 
2448 
2449 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2450 
2451 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
2452 		return (RDR_ERROR);
2453 	}
2454 
2455 	/*
2456 	 * Set variable length fields (size info)
2457 	 */
2458 	if (find_errstring_sizes(params->errstring, &var_msg_info)) {
2459 		return (RDR_ERROR);
2460 	}
2461 
2462 	/*
2463 	 * Collect size info specific to the private_func reply
2464 	 * message and allocate a buffer
2465 	 */
2466 	*buf_size = sizeof (rdr_private_func_reply_t);
2467 	*buf_size += var_msg_info.errstring_strlen;
2468 	*buf_size += var_msg_info.errstring_pad_sz;
2469 
2470 	*buf = (char *)malloc(*buf_size);
2471 	if (*buf == NULL) {
2472 		return (RDR_MEM_ALLOC);
2473 	}
2474 
2475 	/*
2476 	 * Set fixed address labels by name
2477 	 */
2478 	private_func_data.errstring_size = var_msg_info.errstring_strlen +
2479 	    var_msg_info.errstring_pad_sz;
2480 
2481 	/*
2482 	 * Set variable information using memcpy
2483 	 */
2484 	bufptr = *buf;
2485 
2486 	(void) memcpy(bufptr, &private_func_data,
2487 	    sizeof (rdr_private_func_reply_t));
2488 	bufptr += sizeof (rdr_private_func_reply_t);
2489 	if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
2490 		(void) memcpy(bufptr, *(params->errstring),
2491 		    var_msg_info.errstring_strlen);
2492 		bufptr += var_msg_info.errstring_strlen;
2493 		for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
2494 			bufptr[i] = 0;
2495 		}
2496 		bufptr += var_msg_info.errstring_pad_sz;
2497 	}
2498 
2499 	return (RDR_OK);
2500 }
2501 
2502 
2503 /*
2504  * unpack_private_func_reply:
2505  *
2506  * Handle unpacking a private function reply message.
2507  */
2508 static int
2509 unpack_private_func_reply(private_func_params_t *params, const char *buf)
2510 {
2511 	char				*bufptr;
2512 	rdr_private_func_reply_t	private_func_data;
2513 
2514 	if ((params == NULL) || (buf == NULL)) {
2515 		return (RDR_ERROR);
2516 	}
2517 
2518 	bufptr = (char *)buf;
2519 	(void) memcpy(&private_func_data, bufptr,
2520 	    sizeof (rdr_private_func_reply_t));
2521 	bufptr += sizeof (rdr_private_func_reply_t);
2522 
2523 	/*
2524 	 * handle getting the errstring
2525 	 */
2526 	params->errstring = (char **)malloc(sizeof (char *));
2527 	if (params->errstring == NULL) {
2528 		return (RDR_MEM_ALLOC);
2529 	}
2530 	if (get_string_from_buf(params->errstring,
2531 	    private_func_data.errstring_size, bufptr)) {
2532 		return (RDR_ERROR);
2533 	}
2534 	bufptr += private_func_data.errstring_size;
2535 
2536 	return (RDR_OK);
2537 }
2538 
2539 
2540 /*
2541  * pack_test_request:
2542  *
2543  * Handle packing a test request message.
2544  */
2545 static int
2546 pack_test_request(test_params_t *params, char **buf, int *buf_size)
2547 {
2548 	int				i;
2549 	char				*bufptr;
2550 	rdr_test_t			test_data;
2551 	rdr_variable_message_info_t	var_msg_info;
2552 
2553 
2554 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
2555 		return (RDR_ERROR);
2556 	}
2557 
2558 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2559 
2560 	/*
2561 	 * Set variable length fields and make a call to partially
2562 	 * pack it.
2563 	 */
2564 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
2565 		cleanup_variable_ap_id_info(&var_msg_info);
2566 		return (RDR_ERROR);
2567 	}
2568 	if (find_options_sizes(params->options, &var_msg_info)) {
2569 		cleanup_variable_ap_id_info(&var_msg_info);
2570 		return (RDR_ERROR);
2571 	}
2572 
2573 	/*
2574 	 * Collect size info specific to the test request
2575 	 * message and allocate a buffer
2576 	 */
2577 	*buf_size = sizeof (rdr_test_t);
2578 	*buf_size += var_msg_info.ap_id_int_size;
2579 	*buf_size += var_msg_info.ap_id_char_size;
2580 	*buf_size += var_msg_info.options_strlen;
2581 	*buf_size += var_msg_info.options_pad_sz;
2582 
2583 	*buf = (char *)malloc(*buf_size);
2584 	if (*buf == NULL) {
2585 		cleanup_variable_ap_id_info(&var_msg_info);
2586 		return (RDR_MEM_ALLOC);
2587 	}
2588 
2589 	/*
2590 	 * Set fixed address labels by name
2591 	 */
2592 	test_data.num_ap_ids = params->num_ap_ids;
2593 	test_data.ap_id_char_size = var_msg_info.ap_id_char_size;
2594 	test_data.options_size = var_msg_info.options_strlen +
2595 	    var_msg_info.options_pad_sz;
2596 
2597 	if (params->msgp != NULL) {
2598 		test_data.msg_callback_id =
2599 		    (unsigned long)params->msgp->message_routine;
2600 		test_data.msg_appdata_ptr =
2601 		    (unsigned long)params->msgp->appdata_ptr;
2602 	} else {
2603 		test_data.msg_callback_id = 0;
2604 		test_data.msg_appdata_ptr = 0;
2605 	}
2606 
2607 	test_data.flags = params->flags;
2608 
2609 	if (params->errstring != NULL) {
2610 		test_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
2611 	} else {
2612 		test_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
2613 	}
2614 
2615 	/*
2616 	 * Set variable information using memcpy
2617 	 */
2618 	bufptr = *buf;
2619 
2620 	(void) memcpy(bufptr, &test_data, sizeof (rdr_test_t));
2621 	bufptr += sizeof (rdr_test_t);
2622 
2623 	if (var_msg_info.ap_id_sizes != NULL) {
2624 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
2625 		    var_msg_info.ap_id_int_size);
2626 		bufptr += var_msg_info.ap_id_int_size;
2627 	}
2628 
2629 	if (var_msg_info.ap_id_chars != NULL) {
2630 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
2631 		    var_msg_info.ap_id_char_size);
2632 		bufptr += var_msg_info.ap_id_char_size;
2633 	}
2634 
2635 	if (params->options != NULL) {
2636 		(void) memcpy(bufptr, params->options,
2637 		    var_msg_info.options_strlen);
2638 		bufptr += var_msg_info.options_strlen;
2639 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
2640 			bufptr[i] = 0;
2641 		}
2642 		bufptr += var_msg_info.options_pad_sz;
2643 	}
2644 
2645 	cleanup_variable_ap_id_info(&var_msg_info);
2646 
2647 	return (RDR_OK);
2648 }
2649 
2650 
2651 /*
2652  * unpack_test_request:
2653  *
2654  * Handle unpacking a test request message.
2655  */
2656 static int
2657 unpack_test_request(test_params_t *params, const char *buf)
2658 {
2659 	char				*bufptr;
2660 	rdr_variable_message_info_t 	var_msg_info;
2661 	rdr_test_t			test_data;
2662 
2663 
2664 	if ((params == NULL) || (buf == NULL)) {
2665 		return (RDR_ERROR);
2666 	}
2667 
2668 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2669 
2670 	bufptr = (char *)buf;
2671 	(void) memcpy(&test_data, bufptr, sizeof (rdr_test_t));
2672 	bufptr += sizeof (rdr_test_t);
2673 
2674 	/*
2675 	 * handle getting the ap_ids
2676 	 */
2677 	var_msg_info.ap_id_char_size = test_data.ap_id_char_size;
2678 	if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
2679 	    test_data.num_ap_ids, &var_msg_info, bufptr)) {
2680 		return (RDR_ERROR);
2681 	}
2682 	bufptr += var_msg_info.ap_id_int_size;
2683 	bufptr += var_msg_info.ap_id_char_size;
2684 
2685 	/*
2686 	 * handle getting the options
2687 	 */
2688 	if (get_string_from_buf(&(params->options),
2689 	    test_data.options_size, bufptr)) {
2690 		return (RDR_ERROR);
2691 	}
2692 	bufptr += test_data.options_size;
2693 
2694 	/*
2695 	 * Set fixed address labels by name
2696 	 */
2697 	params->num_ap_ids = test_data.num_ap_ids;
2698 
2699 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
2700 	if (params->msgp == NULL) {
2701 		return (RDR_MEM_ALLOC);
2702 	}
2703 
2704 	/* set params->msgp->message_routine using memcpy */
2705 	(void) memcpy((void*)params->msgp,
2706 	    &(test_data.msg_callback_id), sizeof (unsigned long));
2707 	params->msgp->appdata_ptr =
2708 	    (void*)test_data.msg_appdata_ptr;
2709 
2710 	if (test_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
2711 		params->errstring = (char **)malloc(sizeof (char *));
2712 		if (params->errstring == NULL) {
2713 			return (RDR_MEM_ALLOC);
2714 		}
2715 		*(params->errstring) = NULL;
2716 	} else {	/* error_msg_ctl == RDR_DONT_GENERATE_ERR_MSGS */
2717 		params->errstring = NULL;
2718 	}
2719 	params->flags = test_data.flags;
2720 
2721 	return (RDR_OK);
2722 }
2723 
2724 
2725 /*
2726  * pack_test_reply:
2727  *
2728  * Handle packing a test reply message.
2729  */
2730 static int
2731 pack_test_reply(test_params_t *params, char **buf, int *buf_size)
2732 {
2733 	int				i;
2734 	char				*bufptr;
2735 	rdr_test_reply_t		test_data;
2736 	rdr_variable_message_info_t 	var_msg_info;
2737 
2738 
2739 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
2740 		return (RDR_ERROR);
2741 	}
2742 
2743 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2744 
2745 	/*
2746 	 * Set variable length fields (size info)
2747 	 */
2748 	if (find_errstring_sizes(params->errstring, &var_msg_info)) {
2749 		return (RDR_ERROR);
2750 	}
2751 
2752 	/*
2753 	 * Collect size info specific to the test reply
2754 	 * message and allocate a buffer
2755 	 */
2756 	*buf_size = sizeof (rdr_test_reply_t);
2757 	*buf_size += var_msg_info.errstring_strlen;
2758 	*buf_size += var_msg_info.errstring_pad_sz;
2759 
2760 	*buf = (char *)malloc(*buf_size);
2761 	if (*buf == NULL) {
2762 		return (RDR_MEM_ALLOC);
2763 	}
2764 
2765 	/*
2766 	 * Set fixed address labels by name
2767 	 */
2768 	test_data.errstring_size = var_msg_info.errstring_strlen +
2769 	    var_msg_info.errstring_pad_sz;
2770 
2771 	/*
2772 	 * Set variable information using memcpy
2773 	 */
2774 	bufptr = *buf;
2775 
2776 	(void) memcpy(bufptr, &test_data, sizeof (rdr_test_reply_t));
2777 	bufptr += sizeof (rdr_test_reply_t);
2778 	if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
2779 		(void) memcpy(bufptr, *(params->errstring),
2780 		    var_msg_info.errstring_strlen);
2781 		bufptr += var_msg_info.errstring_strlen;
2782 		for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
2783 			bufptr[i] = 0;
2784 		}
2785 		bufptr += var_msg_info.errstring_pad_sz;
2786 	}
2787 
2788 	return (RDR_OK);
2789 }
2790 
2791 
2792 /*
2793  * unpack_test_reply:
2794  *
2795  * Handle unpacking a test reply message.
2796  */
2797 static int
2798 unpack_test_reply(test_params_t *params, const char *buf)
2799 {
2800 	char			*bufptr;
2801 	rdr_test_reply_t	test_data;
2802 
2803 
2804 	if ((params == NULL) || (buf == NULL)) {
2805 		return (RDR_ERROR);
2806 	}
2807 
2808 	bufptr = (char *)buf;
2809 	(void) memcpy(&test_data, bufptr, sizeof (rdr_test_reply_t));
2810 	bufptr += sizeof (rdr_test_reply_t);
2811 
2812 	/*
2813 	 * handle getting the errstring
2814 	 */
2815 	params->errstring = (char **)malloc(sizeof (char *));
2816 	if (params->errstring == NULL) {
2817 		return (RDR_MEM_ALLOC);
2818 	}
2819 	if (get_string_from_buf(params->errstring,
2820 	    test_data.errstring_size, bufptr)) {
2821 		return (RDR_ERROR);
2822 	}
2823 	bufptr += test_data.errstring_size;
2824 
2825 	return (RDR_OK);
2826 }
2827 
2828 
2829 /*
2830  * pack_list_ext_request:
2831  *
2832  * Handle packing a list request message.
2833  */
2834 static int
2835 pack_list_ext_request(list_ext_params_t *params, char **buf, int *buf_size)
2836 {
2837 	int				i;
2838 	char				*bufptr;
2839 	rdr_list_ext_t 			list_ext_data;
2840 	rdr_variable_message_info_t 	var_msg_info;
2841 
2842 
2843 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
2844 		return (RDR_ERROR);
2845 	}
2846 
2847 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2848 
2849 	/*
2850 	 * Set variable length fields and make a call to partially
2851 	 * pack it.
2852 	 */
2853 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
2854 		cleanup_variable_ap_id_info(&var_msg_info);
2855 		return (RDR_ERROR);
2856 	}
2857 	if (find_options_sizes(params->options, &var_msg_info)) {
2858 		cleanup_variable_ap_id_info(&var_msg_info);
2859 		return (RDR_ERROR);
2860 	}
2861 	if (find_listopts_sizes(params->listopts, &var_msg_info)) {
2862 		cleanup_variable_ap_id_info(&var_msg_info);
2863 		return (RDR_ERROR);
2864 	}
2865 
2866 
2867 	/*
2868 	 * Collect size info specific to the list_ext request
2869 	 * message and allocate a buffer
2870 	 */
2871 	*buf_size = sizeof (rdr_list_ext_t);
2872 	*buf_size += var_msg_info.ap_id_int_size;
2873 	*buf_size += var_msg_info.ap_id_char_size;
2874 	*buf_size += var_msg_info.options_strlen;
2875 	*buf_size += var_msg_info.options_pad_sz;
2876 	*buf_size += var_msg_info.listopts_strlen;
2877 	*buf_size += var_msg_info.listopts_pad_sz;
2878 
2879 	*buf = (char *)malloc(*buf_size);
2880 	if (*buf == NULL) {
2881 		cleanup_variable_ap_id_info(&var_msg_info);
2882 		return (RDR_MEM_ALLOC);
2883 	}
2884 
2885 	/*
2886 	 * Set fixed address labels by name
2887 	 */
2888 	list_ext_data.num_ap_ids = params->num_ap_ids;
2889 	list_ext_data.ap_id_char_size = var_msg_info.ap_id_char_size;
2890 	list_ext_data.options_size = var_msg_info.options_strlen +
2891 	    var_msg_info.options_pad_sz;
2892 	list_ext_data.listopts_size = var_msg_info.listopts_strlen +
2893 	    var_msg_info.listopts_pad_sz;
2894 	if (params->errstring != NULL) {
2895 		list_ext_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
2896 	} else {
2897 		list_ext_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
2898 	}
2899 	if ((params->num_ap_ids != 0) || (params->ap_ids != NULL)) {
2900 		list_ext_data.list_msg_ctl = RDR_LIST_ONLY_PARAM_APS;
2901 	} else {
2902 		list_ext_data.list_msg_ctl = RDR_LIST_ALL_APS;
2903 	}
2904 	list_ext_data.flags = params->flags;
2905 	list_ext_data.permissions = params->permissions;
2906 
2907 	/*
2908 	 * Set variable information using memcpy
2909 	 */
2910 	bufptr = *buf;
2911 
2912 	(void) memcpy(bufptr, &list_ext_data, sizeof (rdr_list_ext_t));
2913 	bufptr += sizeof (rdr_list_ext_t);
2914 
2915 	if (var_msg_info.ap_id_sizes != NULL) {
2916 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
2917 		    var_msg_info.ap_id_int_size);
2918 		bufptr += var_msg_info.ap_id_int_size;
2919 	}
2920 
2921 	if (var_msg_info.ap_id_chars != NULL) {
2922 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
2923 		    var_msg_info.ap_id_char_size);
2924 		bufptr += var_msg_info.ap_id_char_size;
2925 	}
2926 
2927 	if (params->options != NULL) {
2928 		(void) memcpy(bufptr, params->options,
2929 		    var_msg_info.options_strlen);
2930 		bufptr += var_msg_info.options_strlen;
2931 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
2932 			bufptr[i] = 0;
2933 		}
2934 		bufptr += var_msg_info.options_pad_sz;
2935 	}
2936 
2937 	if (params->listopts != NULL) {
2938 		(void) memcpy(bufptr, params->listopts,
2939 		    var_msg_info.listopts_strlen);
2940 		bufptr += var_msg_info.listopts_strlen;
2941 		for (i = 0; i < var_msg_info.listopts_pad_sz; i++) {
2942 			bufptr[i] = 0;
2943 		}
2944 		bufptr += var_msg_info.listopts_pad_sz;
2945 	}
2946 
2947 	cleanup_variable_ap_id_info(&var_msg_info);
2948 
2949 	return (RDR_OK);
2950 }
2951 
2952 
2953 /*
2954  * unpack_list_ext_request:
2955  *
2956  * Handle unpacking a list request message.
2957  */
2958 static int
2959 unpack_list_ext_request(list_ext_params_t *params, const char *buf)
2960 {
2961 	char				*bufptr;
2962 	rdr_variable_message_info_t 	var_msg_info;
2963 	rdr_list_ext_t			list_ext_data;
2964 
2965 
2966 	if ((params == NULL) || (buf == NULL)) {
2967 		return (RDR_ERROR);
2968 	}
2969 
2970 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2971 
2972 	bufptr = (char *)buf;
2973 	(void) memcpy(&list_ext_data, bufptr, sizeof (rdr_list_ext_t));
2974 	bufptr += sizeof (rdr_list_ext_t);
2975 
2976 	/*
2977 	 * handle getting the ap_ids
2978 	 */
2979 	var_msg_info.ap_id_char_size = list_ext_data.ap_id_char_size;
2980 	if (get_ap_ids_from_buf(&(params->ap_ids), list_ext_data.num_ap_ids,
2981 	    &var_msg_info, bufptr)) {
2982 		return (RDR_ERROR);
2983 	}
2984 	bufptr += var_msg_info.ap_id_int_size;
2985 	bufptr += var_msg_info.ap_id_char_size;
2986 
2987 	/*
2988 	 * handle getting the options
2989 	 */
2990 	if (get_string_from_buf(&(params->options),
2991 	    list_ext_data.options_size, bufptr)) {
2992 		return (RDR_ERROR);
2993 	}
2994 	bufptr += list_ext_data.options_size;
2995 
2996 	/*
2997 	 * handle getting the listopts
2998 	 */
2999 	if (get_string_from_buf(&(params->listopts),
3000 	    list_ext_data.listopts_size, bufptr)) {
3001 		return (RDR_ERROR);
3002 	}
3003 	bufptr += list_ext_data.listopts_size;
3004 
3005 	/*
3006 	 * Set fixed address labels by name
3007 	 */
3008 	params->num_ap_ids = list_ext_data.num_ap_ids;
3009 
3010 	params->ap_id_list = (rdr_list_t **)malloc(sizeof (rdr_list_t *));
3011 	if (params->ap_id_list == NULL) {
3012 		return (RDR_MEM_ALLOC);
3013 	}
3014 	*(params->ap_id_list) = NULL;
3015 
3016 	params->nlist = (int *)malloc(sizeof (int));
3017 	if (params->nlist == NULL) {
3018 		return (RDR_MEM_ALLOC);
3019 	}
3020 	if (list_ext_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
3021 		params->errstring = (char **)malloc(sizeof (char *));
3022 		if (params->errstring == NULL) {
3023 			return (RDR_MEM_ALLOC);
3024 		}
3025 		*(params->errstring) = NULL;
3026 	} else {	/* error_msg_ctl == RDR_DONT_GENERATE_ERR_MSGS */
3027 	    params->errstring = NULL;
3028 	}
3029 	params->flags = list_ext_data.flags;
3030 	params->permissions = list_ext_data.permissions;
3031 
3032 	return (RDR_OK);
3033 }
3034 
3035 
3036 /*
3037  * pack_list_ext_reply:
3038  *
3039  * Handle packing a list reply message.
3040  */
3041 static int
3042 pack_list_ext_reply(list_ext_params_t *params, char **buf, int *buf_size)
3043 {
3044 	int				i;
3045 	char				*bufptr;
3046 	rdr_list_ext_reply_t		list_ext_data;
3047 	rdr_variable_message_info_t 	var_msg_info;
3048 	int 				list_data_size;
3049 
3050 
3051 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
3052 
3053 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3054 		return (RDR_ERROR);
3055 	}
3056 
3057 	/*
3058 	 * Set variable length fields (size info)
3059 	 */
3060 	if (find_errstring_sizes(params->errstring, &var_msg_info)) {
3061 		return (RDR_ERROR);
3062 	}
3063 
3064 	if (params->nlist == NULL) {
3065 		list_data_size = 0;
3066 	} else {
3067 		list_data_size = *(params->nlist) * sizeof (rdr_list_t);
3068 	}
3069 
3070 	/*
3071 	 * Collect size info specific to the list_ext reply
3072 	 * message and allocate a buffer
3073 	 */
3074 	*buf_size = sizeof (rdr_list_ext_reply_t);
3075 	*buf_size += list_data_size;
3076 	*buf_size += var_msg_info.errstring_strlen;
3077 	*buf_size += var_msg_info.errstring_pad_sz;
3078 
3079 	*buf = (char *)malloc(*buf_size);
3080 	if (*buf == NULL) {
3081 		return (RDR_MEM_ALLOC);
3082 	}
3083 
3084 	/*
3085 	 * Set fixed address labels by name
3086 	 */
3087 	list_ext_data.num_ap_ids = (params->nlist) ? *(params->nlist) : 0;
3088 	list_ext_data.errstring_size = var_msg_info.errstring_strlen +
3089 	    var_msg_info.errstring_pad_sz;
3090 
3091 	/*
3092 	 * Set variable information using memcpy
3093 	 */
3094 	bufptr = *buf;
3095 
3096 	(void) memcpy(bufptr, &list_ext_data, sizeof (rdr_list_ext_reply_t));
3097 	bufptr += sizeof (rdr_list_ext_reply_t);
3098 
3099 	if ((params->ap_id_list != NULL) && (*(params->ap_id_list) != NULL)) {
3100 		(void) memcpy(bufptr, *(params->ap_id_list), list_data_size);
3101 		bufptr += list_data_size;
3102 	} else if (list_data_size) {
3103 		/*
3104 		 * Something is out of sync. We were expecting
3105 		 * some data to copy, but instead we found a
3106 		 * NULL pointer.
3107 		 */
3108 		(void) free((void *)*buf);
3109 		*buf = NULL;
3110 		return (RDR_ERROR);
3111 	}
3112 
3113 	if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
3114 		(void) memcpy(bufptr, *(params->errstring),
3115 		    var_msg_info.errstring_strlen);
3116 		bufptr += var_msg_info.errstring_strlen;
3117 		for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
3118 			bufptr[i] = 0;
3119 		}
3120 		bufptr += var_msg_info.errstring_pad_sz;
3121 	}
3122 
3123 	return (RDR_OK);
3124 }
3125 
3126 
3127 /*
3128  * unpack_list_ext_reply:
3129  *
3130  * Handle unpacking a list reply message.
3131  */
3132 static int
3133 unpack_list_ext_reply(list_ext_params_t *params, const char *buf)
3134 {
3135 	int 			list_data_size;
3136 	char 			*bufptr;
3137 	rdr_list_ext_reply_t	list_ext_data;
3138 
3139 
3140 	if ((params == NULL) || (buf == NULL)) {
3141 		return (RDR_ERROR);
3142 	}
3143 
3144 	bufptr = (char *)buf;
3145 	(void) memcpy(&list_ext_data, bufptr, sizeof (rdr_list_ext_reply_t));
3146 	bufptr += sizeof (rdr_list_ext_reply_t);
3147 
3148 	/*
3149 	 * handle getting the ap_id rcfga_list_data_t's.
3150 	 */
3151 	if (list_ext_data.num_ap_ids > 0) {
3152 		params->nlist = (int *)malloc(sizeof (int));
3153 		if (params->nlist == NULL) {
3154 			return (RDR_MEM_ALLOC);
3155 		}
3156 		*(params->nlist) = list_ext_data.num_ap_ids;
3157 		params->ap_id_list = (rdr_list_t **)
3158 		    malloc(sizeof (rdr_list_t *));
3159 		if (params->ap_id_list == NULL) {
3160 			return (RDR_MEM_ALLOC);
3161 		}
3162 		*(params->ap_id_list) = (rdr_list_t *)
3163 		malloc(sizeof (rdr_list_t) * list_ext_data.num_ap_ids);
3164 		if (*(params->ap_id_list) == NULL) {
3165 			return (RDR_MEM_ALLOC);
3166 		}
3167 		list_data_size = list_ext_data.num_ap_ids * sizeof (rdr_list_t);
3168 		(void) memcpy(*(params->ap_id_list), bufptr, list_data_size);
3169 		bufptr += list_data_size;
3170 	}
3171 
3172 	/*
3173 	 * handle getting the errstring
3174 	 */
3175 	params->errstring = (char **)malloc(sizeof (char *));
3176 	if (params->errstring == NULL) {
3177 		return (RDR_MEM_ALLOC);
3178 	}
3179 	if (get_string_from_buf(params->errstring,
3180 			list_ext_data.errstring_size, bufptr)) {
3181 		return (RDR_ERROR);
3182 	}
3183 	bufptr += list_ext_data.errstring_size;
3184 
3185 	return (RDR_OK);
3186 }
3187 
3188 
3189 /*
3190  * pack_help_request:
3191  *
3192  * Handle packing a help request message.
3193  */
3194 static int
3195 pack_help_request(help_params_t *params, char **buf, int *buf_size)
3196 {
3197 	int				i;
3198 	char				*bufptr;
3199 	rdr_help_t			help_data;
3200 	rdr_variable_message_info_t	var_msg_info;
3201 
3202 
3203 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
3204 
3205 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3206 		return (RDR_ERROR);
3207 	}
3208 
3209 	/*
3210 	 * Set variable length fields and make a call to partially
3211 	 * pack it.
3212 	 */
3213 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
3214 		cleanup_variable_ap_id_info(&var_msg_info);
3215 		return (RDR_ERROR);
3216 	}
3217 	if (find_options_sizes(params->options, &var_msg_info)) {
3218 		cleanup_variable_ap_id_info(&var_msg_info);
3219 		return (RDR_ERROR);
3220 	}
3221 
3222 	/*
3223 	 * Collect size info specific to the help request message and
3224 	 * and allocate a buffer
3225 	 */
3226 	*buf_size = sizeof (rdr_help_t);
3227 	*buf_size += var_msg_info.ap_id_int_size;
3228 	*buf_size += var_msg_info.ap_id_char_size;
3229 	*buf_size += var_msg_info.options_strlen;
3230 	*buf_size += var_msg_info.options_pad_sz;
3231 
3232 	*buf = (char *)malloc(*buf_size);
3233 	if (*buf == NULL) {
3234 		cleanup_variable_ap_id_info(&var_msg_info);
3235 		return (RDR_MEM_ALLOC);
3236 	}
3237 
3238 	/*
3239 	 * Set fixed address labels by name
3240 	 */
3241 	help_data.num_ap_ids = params->num_ap_ids;
3242 	help_data.ap_id_char_size = var_msg_info.ap_id_char_size;
3243 	help_data.options_size = var_msg_info.options_strlen +
3244 	    var_msg_info.options_pad_sz;
3245 
3246 	if (params->msgp != NULL) {
3247 		help_data.msg_callback_id =
3248 		    (unsigned long)params->msgp->message_routine;
3249 		help_data.msg_appdata_ptr =
3250 		    (unsigned long)params->msgp->appdata_ptr;
3251 	} else {
3252 		help_data.msg_callback_id = 0;
3253 		help_data.msg_appdata_ptr = 0;
3254 	}
3255 
3256 	help_data.flags = params->flags;
3257 
3258 	/*
3259 	 * Set variable information using memcpy
3260 	 */
3261 	bufptr = *buf;
3262 
3263 	(void) memcpy(bufptr, &help_data, sizeof (rdr_help_t));
3264 	bufptr += sizeof (rdr_help_t);
3265 
3266 	if (var_msg_info.ap_id_sizes != NULL) {
3267 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
3268 		    var_msg_info.ap_id_int_size);
3269 		bufptr += var_msg_info.ap_id_int_size;
3270 	}
3271 
3272 	if (var_msg_info.ap_id_chars != NULL) {
3273 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
3274 		    var_msg_info.ap_id_char_size);
3275 		bufptr += var_msg_info.ap_id_char_size;
3276 	}
3277 
3278 	if (params->options != NULL) {
3279 		(void) memcpy(bufptr, params->options,
3280 		    var_msg_info.options_strlen);
3281 		bufptr += var_msg_info.options_strlen;
3282 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
3283 			bufptr[i] = 0;
3284 		}
3285 		bufptr += var_msg_info.options_pad_sz;
3286 	}
3287 
3288 	cleanup_variable_ap_id_info(&var_msg_info);
3289 
3290 	return (RDR_OK);
3291 }
3292 
3293 
3294 /*
3295  * unpack_help_request:
3296  *
3297  * Handle unpacking a help request message.
3298  */
3299 static int
3300 unpack_help_request(help_params_t *params, const char *buf)
3301 {
3302 	char				*bufptr;
3303 	rdr_variable_message_info_t 	var_msg_info;
3304 	rdr_help_t			help_data;
3305 
3306 
3307 	if ((params == NULL) || (buf == NULL)) {
3308 		return (RDR_ERROR);
3309 	}
3310 
3311 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
3312 
3313 	bufptr = (char *)buf;
3314 	(void) memcpy(&help_data, bufptr, sizeof (rdr_help_t));
3315 	bufptr += sizeof (rdr_help_t);
3316 
3317 	/*
3318 	 * handle getting the ap_ids
3319 	 */
3320 	var_msg_info.ap_id_char_size = help_data.ap_id_char_size;
3321 	if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
3322 	    help_data.num_ap_ids, &var_msg_info, bufptr)) {
3323 		return (RDR_ERROR);
3324 	}
3325 	bufptr += var_msg_info.ap_id_int_size;
3326 	bufptr += var_msg_info.ap_id_char_size;
3327 
3328 	/*
3329 	 * handle getting the options
3330 	 */
3331 	if (get_string_from_buf(&(params->options),
3332 	    help_data.options_size, bufptr)) {
3333 		return (RDR_ERROR);
3334 	}
3335 	bufptr += help_data.options_size;
3336 
3337 	/*
3338 	 * Set fixed address labels by name
3339 	 */
3340 	params->num_ap_ids = help_data.num_ap_ids;
3341 
3342 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
3343 	if (params->msgp == NULL) {
3344 		return (RDR_MEM_ALLOC);
3345 	}
3346 
3347 	/* set params->msgp->message_routine using memcpy */
3348 	(void) memcpy((void*)params->msgp, &(help_data.msg_callback_id),
3349 	    sizeof (unsigned long));
3350 
3351 	params->msgp->appdata_ptr = (void*)help_data.msg_appdata_ptr;
3352 	params->flags = help_data.flags;
3353 
3354 	return (RDR_OK);
3355 }
3356 
3357 
3358 /*
3359  * pack_ap_id_cmp_request:
3360  *
3361  * Handle packing an attachment point comparison request message.
3362  */
3363 static int
3364 pack_ap_id_cmp_request(ap_id_cmp_params_t *params, char **buf, int *buf_size)
3365 {
3366 	int			i;
3367 	char			*bufptr;
3368 	rdr_ap_id_cmp_t		ap_id_cmp_data;
3369 	int			ap_id1_strlen;
3370 	int			ap_id1_pad_sz;
3371 	int			ap_id2_strlen;
3372 	int			ap_id2_pad_sz;
3373 
3374 
3375 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3376 		return (RDR_ERROR);
3377 	}
3378 
3379 	/*
3380 	 * Set variable length fields and make a call to partially
3381 	 * pack it.
3382 	 */
3383 	if (params->ap_log_id1 != NULL) {
3384 		ap_id1_strlen = strlen(params->ap_log_id1) + 1;
3385 		ap_id1_pad_sz = RDR_ALIGN_64_BIT -
3386 		    (ap_id1_strlen % RDR_ALIGN_64_BIT);
3387 	} else {
3388 		ap_id1_strlen = 0;
3389 		ap_id1_pad_sz = 0;
3390 	}
3391 
3392 	if (params->ap_log_id2 != NULL) {
3393 		ap_id2_strlen = strlen(params->ap_log_id2) + 1;
3394 		ap_id2_pad_sz = RDR_ALIGN_64_BIT -
3395 		    (ap_id2_strlen % RDR_ALIGN_64_BIT);
3396 	} else {
3397 		ap_id2_strlen = 0;
3398 		ap_id2_pad_sz = 0;
3399 	}
3400 
3401 	/*
3402 	 * Collect size info specific to the ap id compare request
3403 	 * message and allocate a buffer
3404 	 */
3405 	*buf_size = sizeof (rdr_ap_id_cmp_t);
3406 	*buf_size += ap_id1_strlen;
3407 	*buf_size += ap_id1_pad_sz;
3408 	*buf_size += ap_id2_strlen;
3409 	*buf_size += ap_id2_pad_sz;
3410 
3411 	*buf = (char *)malloc(*buf_size);
3412 	if (*buf == NULL) {
3413 		return (RDR_MEM_ALLOC);
3414 	}
3415 
3416 	/*
3417 	 * Set fixed address labels by name
3418 	 */
3419 	ap_id_cmp_data.ap_id1_size = ap_id1_strlen + ap_id1_pad_sz;
3420 	ap_id_cmp_data.ap_id2_size = ap_id2_strlen + ap_id2_pad_sz;
3421 
3422 
3423 	/*
3424 	 * Set variable information using memcpy
3425 	 */
3426 	bufptr = *buf;
3427 
3428 	(void) memcpy(bufptr, &ap_id_cmp_data, sizeof (rdr_ap_id_cmp_t));
3429 	bufptr += sizeof (rdr_ap_id_cmp_t);
3430 
3431 	if (params->ap_log_id1 != NULL) {
3432 		(void) memcpy(bufptr, params->ap_log_id1, ap_id1_strlen);
3433 		bufptr += ap_id1_strlen;
3434 		for (i = 0; i < ap_id1_pad_sz; i++) {
3435 			bufptr[i] = 0;
3436 		}
3437 		bufptr += ap_id1_pad_sz;
3438 	}
3439 
3440 	if (params->ap_log_id2 != NULL) {
3441 		(void) memcpy(bufptr, params->ap_log_id2, ap_id2_strlen);
3442 		bufptr += ap_id2_strlen;
3443 		for (i = 0; i < ap_id2_pad_sz; i++) {
3444 			bufptr[i] = 0;
3445 		}
3446 		bufptr += ap_id2_pad_sz;
3447 	}
3448 
3449 	return (RDR_OK);
3450 }
3451 
3452 
3453 /*
3454  * unpack_ap_id_cmp_request:
3455  *
3456  * Handle unpacking an attachment point comparison request message.
3457  */
3458 static int
3459 unpack_ap_id_cmp_request(ap_id_cmp_params_t *params, const char *buf)
3460 {
3461 	char			*bufptr;
3462 	rdr_ap_id_cmp_t		ap_id_cmp_data;
3463 
3464 
3465 	if ((params == NULL) || (buf == NULL)) {
3466 		return (RDR_ERROR);
3467 	}
3468 
3469 	bufptr = (char *)buf;
3470 	(void) memcpy(&ap_id_cmp_data, bufptr, sizeof (rdr_ap_id_cmp_t));
3471 	bufptr += sizeof (rdr_ap_id_cmp_t);
3472 
3473 	/*
3474 	 * handle getting the cmp ap ids
3475 	 */
3476 	if (get_string_from_buf(&(params->ap_log_id1),
3477 	    ap_id_cmp_data.ap_id1_size, bufptr)) {
3478 		return (RDR_ERROR);
3479 	}
3480 	bufptr += ap_id_cmp_data.ap_id1_size;
3481 
3482 	if (get_string_from_buf(&(params->ap_log_id2),
3483 	    ap_id_cmp_data.ap_id2_size, bufptr)) {
3484 		return (RDR_ERROR);
3485 	}
3486 	bufptr += ap_id_cmp_data.ap_id2_size;
3487 
3488 	return (RDR_OK);
3489 }
3490 
3491 
3492 /*
3493  * pack_abort_cmd_request:
3494  *
3495  * Handle packing an abort request message.
3496  */
3497 static int
3498 pack_abort_cmd_request(abort_cmd_params_t *params, char **buf, int *buf_size)
3499 {
3500 	rdr_abort_cmd_t		abort_cmd_data;
3501 
3502 
3503 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3504 		return (RDR_ERROR);
3505 	}
3506 
3507 	/*
3508 	 * Collect size info specific to the abort cmd request
3509 	 * message and allocate a buffer
3510 	 */
3511 	*buf_size = sizeof (rdr_abort_cmd_t);
3512 
3513 	*buf = (char *)malloc(*buf_size);
3514 	if (*buf == NULL) {
3515 		return (RDR_MEM_ALLOC);
3516 	}
3517 
3518 	/*
3519 	 * Set fixed session identifier
3520 	 */
3521 	abort_cmd_data.session_id = params->session_id;
3522 
3523 	/*
3524 	 * Copy information using memcpy
3525 	 */
3526 	(void) memcpy(*buf, &abort_cmd_data, sizeof (rdr_abort_cmd_t));
3527 
3528 	return (RDR_OK);
3529 }
3530 
3531 
3532 /*
3533  * unpack_abort_cmd_request:
3534  *
3535  * Handle unpacking an abort request message.
3536  */
3537 static int
3538 unpack_abort_cmd_request(abort_cmd_params_t *params, const char *buf)
3539 {
3540 	rdr_abort_cmd_t		*abort_cmd_datap;
3541 
3542 
3543 	if ((params == NULL) || (buf == NULL)) {
3544 		return (RDR_ERROR);
3545 	}
3546 
3547 	/* LINTED Pointer Cast Alignment Warning */
3548 	abort_cmd_datap = (rdr_abort_cmd_t *)buf;
3549 
3550 	/*
3551 	 * copy out the session information
3552 	 */
3553 
3554 	params->session_id = abort_cmd_datap->session_id;
3555 
3556 	return (RDR_OK);
3557 }
3558 
3559 
3560 /*
3561  * pack_confirm_request:
3562  *
3563  * Handle packing a confirm callback request.
3564  */
3565 static int
3566 pack_confirm_request(confirm_callback_params_t *params, char **buf,
3567     int *buf_size)
3568 {
3569 	int				i;
3570 	char				*bufptr;
3571 	rdr_confirm_callback_t		confirm_callback_data;
3572 	int 				message_strlen;
3573 	int 				message_pad_sz;
3574 
3575 
3576 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3577 		return (RDR_ERROR);
3578 	}
3579 
3580 	/*
3581 	 * Set variable length fields and make a call to partially
3582 	 * pack it.
3583 	 */
3584 	if (params->message != NULL) {
3585 		message_strlen = strlen(params->message) + 1;
3586 		message_pad_sz = RDR_ALIGN_64_BIT -
3587 		    (message_strlen % RDR_ALIGN_64_BIT);
3588 	} else {
3589 		message_strlen = 0;
3590 		message_pad_sz = 0;
3591 	}
3592 
3593 
3594 	/*
3595 	 * Collect size info specific to the confirm callback request
3596 	 * message and allocate a buffer
3597 	 */
3598 	*buf_size = sizeof (rdr_confirm_callback_t);
3599 	*buf_size += message_strlen;
3600 	*buf_size += message_pad_sz;
3601 
3602 	*buf = (char *)malloc(*buf_size);
3603 	if (*buf == NULL) {
3604 		return (RDR_MEM_ALLOC);
3605 	}
3606 
3607 	/*
3608 	 * Set fixed address labels by name
3609 	 */
3610 	if (params->confp != NULL) {
3611 		confirm_callback_data.confirm_callback_id =
3612 		    (unsigned long)params->confp->confirm;
3613 		confirm_callback_data.appdata_ptr =
3614 		    (unsigned long)params->confp->appdata_ptr;
3615 	} else {
3616 		confirm_callback_data.confirm_callback_id = 0;
3617 		confirm_callback_data.appdata_ptr = 0;
3618 	}
3619 	confirm_callback_data.message_size = message_strlen + message_pad_sz;
3620 
3621 	/*
3622 	 * Set variable information using memcpy
3623 	 */
3624 	bufptr = *buf;
3625 	(void) memcpy(bufptr, &confirm_callback_data,
3626 	    sizeof (rdr_confirm_callback_t));
3627 	bufptr += sizeof (rdr_confirm_callback_t);
3628 
3629 	if (params->message != NULL) {
3630 		(void) memcpy(bufptr, params->message, message_strlen);
3631 		bufptr += message_strlen;
3632 		for (i = 0; i < message_pad_sz; i++) {
3633 			bufptr[i] = 0;
3634 		}
3635 		bufptr += message_pad_sz;
3636 	}
3637 
3638 	return (RDR_OK);
3639 }
3640 
3641 
3642 /*
3643  * unpack_confirm_request:
3644  *
3645  * Handle unpacking a confirm callback request.
3646  */
3647 static int
3648 unpack_confirm_request(confirm_callback_params_t *params, const char *buf)
3649 {
3650 	char				*bufptr;
3651 	rdr_confirm_callback_t		confirm_callback_data;
3652 
3653 
3654 	if ((params == NULL) || (buf == NULL)) {
3655 		return (RDR_ERROR);
3656 	}
3657 
3658 	bufptr = (char *)buf;
3659 	(void) memcpy(&confirm_callback_data, bufptr,
3660 	    sizeof (rdr_confirm_callback_t));
3661 	bufptr += sizeof (rdr_confirm_callback_t);
3662 
3663 	/*
3664 	 * handle getting the message text
3665 	 */
3666 	if (get_string_from_buf(&(params->message),
3667 	    confirm_callback_data.message_size, bufptr)) {
3668 		return (RDR_ERROR);
3669 	}
3670 	bufptr += confirm_callback_data.message_size;
3671 
3672 	/*
3673 	 * Set fixed address labels by name
3674 	 */
3675 	params->confp = (struct cfga_confirm *)
3676 	    malloc(sizeof (struct cfga_confirm));
3677 	if (params->confp == NULL) {
3678 		return (RDR_MEM_ALLOC);
3679 	}
3680 
3681 	/* set params->confp->confirm using memcpy */
3682 	(void) memcpy((void*)params->confp,
3683 	    &(confirm_callback_data.confirm_callback_id),
3684 	    sizeof (unsigned long));
3685 
3686 	params->confp->appdata_ptr =
3687 	    (void*)confirm_callback_data.appdata_ptr;
3688 
3689 	return (RDR_OK);
3690 }
3691 
3692 
3693 /*
3694  * pack_confirm_reply:
3695  *
3696  * Handle packing a confirm callback reply.
3697  */
3698 static int
3699 pack_confirm_reply(confirm_callback_params_t *params, char **buf, int *buf_size)
3700 {
3701 	char				*bufptr;
3702 	rdr_confirm_callback_reply_t	confirm_callback_data;
3703 
3704 
3705 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3706 		return (RDR_ERROR);
3707 	}
3708 
3709 	/*
3710 	 * Collect size info specific to the confirm callback reply
3711 	 * message and allocate a buffer
3712 	 */
3713 	*buf_size = sizeof (confirm_callback_params_t);
3714 	*buf = (char *)malloc(*buf_size);
3715 	if (*buf == NULL) {
3716 		return (RDR_MEM_ALLOC);
3717 	}
3718 
3719 	/*
3720 	 * Set fixed address labels by name
3721 	 */
3722 	if (params->confp != NULL) {
3723 		confirm_callback_data.confirm_callback_id =
3724 		    (unsigned long)params->confp->confirm;
3725 		confirm_callback_data.appdata_ptr =
3726 		    (unsigned long)params->confp->appdata_ptr;
3727 	} else {
3728 		confirm_callback_data.confirm_callback_id = 0;
3729 		confirm_callback_data.appdata_ptr = 0;
3730 	}
3731 	confirm_callback_data.response = params->response;
3732 
3733 	/*
3734 	 * Set variable information using memcpy
3735 	 */
3736 	bufptr = *buf;
3737 
3738 	(void) memcpy(bufptr, &confirm_callback_data,
3739 	    sizeof (rdr_confirm_callback_reply_t));
3740 
3741 	return (RDR_OK);
3742 }
3743 
3744 
3745 /*
3746  * unpack_confirm_reply:
3747  *
3748  * Handle unpacking a confirm callback reply.
3749  */
3750 static int
3751 unpack_confirm_reply(confirm_callback_params_t *params, const char *buf)
3752 {
3753 	char				*bufptr;
3754 	rdr_confirm_callback_reply_t	confirm_callback_data;
3755 
3756 	if ((params == NULL) || (buf == NULL)) {
3757 		return (RDR_ERROR);
3758 	}
3759 
3760 	bufptr = (char *)buf;
3761 	(void) memcpy(&confirm_callback_data, bufptr,
3762 	    sizeof (rdr_confirm_callback_reply_t));
3763 	bufptr += sizeof (confirm_callback_params_t);
3764 
3765 	/*
3766 	 * Set fixed address labels by name
3767 	 */
3768 	params->confp = (struct cfga_confirm *)
3769 	    malloc(sizeof (struct cfga_confirm));
3770 	if (params->confp == NULL) {
3771 		return (RDR_MEM_ALLOC);
3772 	}
3773 
3774 	/* set params->confp->confirm using memcpy */
3775 	(void) memcpy((void*)params->confp,
3776 	    &(confirm_callback_data.confirm_callback_id),
3777 	    sizeof (unsigned long));
3778 
3779 	params->confp->appdata_ptr =
3780 	    (void*)confirm_callback_data.appdata_ptr;
3781 	params->response = confirm_callback_data.response;
3782 
3783 	return (RDR_OK);
3784 }
3785 
3786 
3787 /*
3788  * pack_message_request:
3789  *
3790  * Handle packing a message callback request.
3791  */
3792 static int
3793 pack_message_request(msg_callback_params_t *params, char **buf, int *buf_size)
3794 {
3795 	int			i;
3796 	char			*bufptr;
3797 	rdr_msg_callback_t	msg_callback_data;
3798 	int			message_strlen;
3799 	int			message_pad_sz;
3800 
3801 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3802 		return (RDR_ERROR);
3803 	}
3804 
3805 	/*
3806 	 * Set variable length fields and make a call to partially
3807 	 * pack it.
3808 	 */
3809 	if (params->message != NULL) {
3810 		message_strlen = strlen(params->message) + 1;
3811 		message_pad_sz = RDR_ALIGN_64_BIT -
3812 		    (message_strlen % RDR_ALIGN_64_BIT);
3813 	} else {
3814 		message_strlen = 0;
3815 		message_pad_sz = 0;
3816 	}
3817 
3818 
3819 	/*
3820 	 * Collect size info specific to the message callback request
3821 	 * message and allocate a buffer
3822 	 */
3823 	*buf_size = sizeof (rdr_msg_callback_t);
3824 	*buf_size += message_strlen;
3825 	*buf_size += message_pad_sz;
3826 
3827 	*buf = (char *)malloc(*buf_size);
3828 	if (*buf == NULL) {
3829 		return (RDR_MEM_ALLOC);
3830 	}
3831 
3832 	/*
3833 	 * Set fixed address labels by name
3834 	 */
3835 	if (params->msgp != NULL) {
3836 		msg_callback_data.msg_callback_id =
3837 		    (unsigned long)params->msgp->message_routine;
3838 		msg_callback_data.appdata_ptr =
3839 		    (unsigned long)params->msgp->appdata_ptr;
3840 	} else {
3841 		msg_callback_data.msg_callback_id = 0;
3842 		msg_callback_data.appdata_ptr = 0;
3843 	}
3844 	msg_callback_data.message_size = message_strlen + message_pad_sz;
3845 
3846 	/*
3847 	 * Set variable information using memcpy
3848 	 */
3849 	bufptr = *buf;
3850 
3851 	(void) memcpy(bufptr, &msg_callback_data, sizeof (rdr_msg_callback_t));
3852 	bufptr += sizeof (rdr_msg_callback_t);
3853 
3854 	if (params->message != NULL) {
3855 		(void) memcpy(bufptr, params->message, message_strlen);
3856 		bufptr += message_strlen;
3857 		for (i = 0; i < message_pad_sz; i++) {
3858 			bufptr[i] = 0;
3859 		}
3860 		bufptr += message_pad_sz;
3861 	}
3862 
3863 	return (RDR_OK);
3864 }
3865 
3866 
3867 /*
3868  * unpack_message_request:
3869  *
3870  * Handle unpacking a message callback request.
3871  */
3872 static int
3873 unpack_message_request(msg_callback_params_t *params, const char *buf)
3874 {
3875 	char			*bufptr;
3876 	rdr_msg_callback_t	msg_callback_data;
3877 
3878 	if ((params == NULL) || (buf == NULL)) {
3879 		return (RDR_ERROR);
3880 	}
3881 
3882 	bufptr = (char *)buf;
3883 	(void) memcpy(&msg_callback_data, bufptr, sizeof (rdr_msg_callback_t));
3884 	bufptr += sizeof (rdr_msg_callback_t);
3885 
3886 	/*
3887 	 * handle getting the message text
3888 	 */
3889 	if (get_string_from_buf(&(params->message),
3890 	    msg_callback_data.message_size, bufptr)) {
3891 		return (RDR_ERROR);
3892 	}
3893 	bufptr += msg_callback_data.message_size;
3894 
3895 	/*
3896 	 * Set fixed address labels by name
3897 	 */
3898 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
3899 	if (params->msgp == NULL) {
3900 		return (RDR_MEM_ALLOC);
3901 	}
3902 
3903 	/* set params->msgp->message_routine using memcpy */
3904 	(void) memcpy((void*)params->msgp, &(msg_callback_data.msg_callback_id),
3905 	    sizeof (unsigned long));
3906 
3907 	params->msgp->appdata_ptr = (void*)msg_callback_data.appdata_ptr;
3908 
3909 	return (RDR_OK);
3910 }
3911 
3912 /*
3913  * pack_rsrc_info_request:
3914  *
3915  * Handle packing a resource info request.
3916  */
3917 static int
3918 pack_rsrc_info_request(rsrc_info_params_t *params, char **buf, int *buf_size)
3919 {
3920 	char				*bufptr;
3921 	rdr_rsrc_info_t			rsrc_info_data;
3922 	rdr_variable_message_info_t 	var_msg_info;
3923 
3924 
3925 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3926 		return (RDR_ERROR);
3927 	}
3928 
3929 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
3930 
3931 	/*
3932 	 * Set variable length fields and make a call to partially
3933 	 * pack it.
3934 	 */
3935 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
3936 		cleanup_variable_ap_id_info(&var_msg_info);
3937 		return (RDR_ERROR);
3938 	}
3939 
3940 	/*
3941 	 * Collect size info specific to the resource info request
3942 	 * message and allocate a buffer.
3943 	 */
3944 	*buf_size = sizeof (rdr_rsrc_info_t);
3945 	*buf_size += var_msg_info.ap_id_int_size;
3946 	*buf_size += var_msg_info.ap_id_char_size;
3947 
3948 	*buf = (char *)malloc(*buf_size);
3949 	if (*buf == NULL) {
3950 		return (RDR_MEM_ALLOC);
3951 	}
3952 
3953 	/*
3954 	 * Set fixed address labels by name.
3955 	 */
3956 	rsrc_info_data.num_ap_ids = params->num_ap_ids;
3957 	rsrc_info_data.ap_id_char_size = var_msg_info.ap_id_char_size;
3958 	rsrc_info_data.flags = params->flags;
3959 
3960 	/*
3961 	 * Set variable information using memcpy.
3962 	 */
3963 	bufptr = *buf;
3964 
3965 	(void) memcpy(bufptr, &rsrc_info_data, sizeof (rdr_rsrc_info_t));
3966 	bufptr += sizeof (rdr_rsrc_info_t);
3967 
3968 	if (var_msg_info.ap_id_sizes != NULL) {
3969 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
3970 		    var_msg_info.ap_id_int_size);
3971 		bufptr += var_msg_info.ap_id_int_size;
3972 	}
3973 
3974 	if (var_msg_info.ap_id_chars != NULL) {
3975 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
3976 		    var_msg_info.ap_id_char_size);
3977 		bufptr += var_msg_info.ap_id_char_size;
3978 	}
3979 
3980 	cleanup_variable_ap_id_info(&var_msg_info);
3981 
3982 	return (RDR_OK);
3983 }
3984 
3985 
3986 /*
3987  * unpack_rsrc_info_request:
3988  *
3989  * Handle unpacking a resource info request message.
3990  */
3991 static int
3992 unpack_rsrc_info_request(rsrc_info_params_t *params, const char *buf)
3993 {
3994 	char				*bufptr;
3995 	rdr_variable_message_info_t 	var_msg_info;
3996 	rdr_rsrc_info_t			rsrc_info_data;
3997 
3998 
3999 	if ((params == NULL) || (buf == NULL)) {
4000 		return (RDR_ERROR);
4001 	}
4002 
4003 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
4004 
4005 	bufptr = (char *)buf;
4006 	(void) memcpy(&rsrc_info_data, bufptr, sizeof (rdr_rsrc_info_t));
4007 	bufptr += sizeof (rdr_rsrc_info_t);
4008 
4009 	/*
4010 	 * Handle getting the ap_ids.
4011 	 */
4012 	var_msg_info.ap_id_char_size = rsrc_info_data.ap_id_char_size;
4013 	if (get_ap_ids_from_buf(&(params->ap_ids), rsrc_info_data.num_ap_ids,
4014 	    &var_msg_info, bufptr)) {
4015 		return (RDR_ERROR);
4016 	}
4017 	bufptr += var_msg_info.ap_id_int_size;
4018 	bufptr += var_msg_info.ap_id_char_size;
4019 
4020 	/*
4021 	 * Set fixed address labels by name.
4022 	 */
4023 	params->num_ap_ids = rsrc_info_data.num_ap_ids;
4024 	params->flags = rsrc_info_data.flags;
4025 
4026 	return (RDR_OK);
4027 }
4028 
4029 
4030 /*
4031  * pack_rsrc_info_reply:
4032  *
4033  * Handle packing a resource info reply message.
4034  */
4035 static int
4036 pack_rsrc_info_reply(rsrc_info_params_t *params, char **buf, int *buf_size,
4037     int encoding)
4038 {
4039 	char				*bufptr;
4040 	rdr_rsrc_info_reply_t		rsrc_info_data;
4041 	int				pack_status;
4042 	caddr_t				rsrc_info_bufp = NULL;
4043 	size_t 				rsrc_info_size;
4044 
4045 
4046 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
4047 		return (RDR_ERROR);
4048 	}
4049 
4050 	/*
4051 	 * Pack snapshot handle data.
4052 	 */
4053 	pack_status = ri_pack(params->hdl, &rsrc_info_bufp, &rsrc_info_size,
4054 	    encoding);
4055 	if (pack_status != 0) {
4056 		return (RDR_ERROR);
4057 	}
4058 
4059 	/*
4060 	 * Collect size info specific to the rsrc_info reply message
4061 	 * and allocate a buffer.
4062 	 */
4063 	*buf_size = sizeof (rdr_rsrc_info_reply_t);
4064 	*buf_size += rsrc_info_size;
4065 
4066 	*buf = (char *)malloc(*buf_size);
4067 	if (*buf == NULL) {
4068 		free(rsrc_info_bufp);
4069 		return (RDR_MEM_ALLOC);
4070 	}
4071 
4072 	/*
4073 	 * Set fixed address labels by name.
4074 	 */
4075 	rsrc_info_data.packed_hdl_size = rsrc_info_size;
4076 
4077 	/*
4078 	 * Set variable information using memcpy.
4079 	 */
4080 	bufptr = *buf;
4081 
4082 	(void) memcpy(bufptr, &rsrc_info_data, sizeof (rdr_rsrc_info_reply_t));
4083 	bufptr += sizeof (rdr_rsrc_info_reply_t);
4084 
4085 	if (rsrc_info_bufp) {
4086 		(void) memcpy(bufptr, rsrc_info_bufp, rsrc_info_size);
4087 		free(rsrc_info_bufp);
4088 	}
4089 
4090 	return (RDR_OK);
4091 }
4092 
4093 
4094 /*
4095  * unpack_rsrc_info_reply:
4096  *
4097  * Handle unpacking a resource info reply message.
4098  */
4099 static int
4100 unpack_rsrc_info_reply(rsrc_info_params_t *params, const char *buf)
4101 {
4102 	int			unpack_status;
4103 	char 			*bufptr;
4104 	rdr_rsrc_info_reply_t	rsrc_info_data;
4105 
4106 
4107 	if ((params == NULL) || (buf == NULL)) {
4108 		return (RDR_ERROR);
4109 	}
4110 
4111 	bufptr = (char *)buf;
4112 	(void) memcpy(&rsrc_info_data, bufptr, sizeof (rdr_rsrc_info_reply_t));
4113 	bufptr += sizeof (rdr_rsrc_info_reply_t);
4114 
4115 	/*
4116 	 * Unpack buf into resource info handle.
4117 	 */
4118 	unpack_status = ri_unpack(bufptr, rsrc_info_data.packed_hdl_size,
4119 	    &params->hdl);
4120 
4121 	return ((unpack_status == 0) ? RDR_OK : RDR_ERROR);
4122 }
4123 
4124 
4125 /*
4126  * pack_ap_ids:
4127  *
4128  * Pack a list of attachment point identifiers into a single buffer.
4129  * This buffer is stored in the specified rdr_variable_message_info_t
4130  * and is padded to be 64-bit aligned.
4131  */
4132 static int
4133 pack_ap_ids(int num_ap_ids, char *const *ap_ids,
4134     rdr_variable_message_info_t *var_msg_info)
4135 {
4136 	int	i;
4137 	int	ap_id_pad_sz;
4138 	char	*bufptr;
4139 
4140 
4141 	if (var_msg_info == NULL) {
4142 		return (RDR_ERROR);
4143 	}
4144 
4145 	/*
4146 	 * NULL is a valid value for ap_ids in the list_ext
4147 	 * case. For list_ext, no specified attachment points
4148 	 * indicates that _all_ attachment points should be
4149 	 * displayed. However, if ap_ids is NULL, num_ap_ids
4150 	 * should be 0.
4151 	 */
4152 	if ((ap_ids == NULL) && (num_ap_ids != 0)) {
4153 		num_ap_ids = 0;
4154 	}
4155 
4156 	var_msg_info->ap_id_int_size = sizeof (int) * num_ap_ids;
4157 	if (num_ap_ids > 0) {
4158 		var_msg_info->ap_id_sizes = (int *)malloc(sizeof (int) *
4159 		    var_msg_info->ap_id_int_size);
4160 		if (var_msg_info->ap_id_sizes == NULL) {
4161 			return (RDR_MEM_ALLOC);
4162 		}
4163 	}
4164 	for (i = 0; i < num_ap_ids; i++) {
4165 		if (ap_ids[i] != NULL) {
4166 			var_msg_info->ap_id_sizes[i] = strlen(ap_ids[i]) + 1;
4167 			var_msg_info->ap_id_char_size +=
4168 			    var_msg_info->ap_id_sizes[i];
4169 		}
4170 	}
4171 	if (var_msg_info->ap_id_char_size > 0) {
4172 		ap_id_pad_sz = RDR_ALIGN_64_BIT -
4173 		    (var_msg_info->ap_id_char_size % RDR_ALIGN_64_BIT);
4174 		var_msg_info->ap_id_char_size += ap_id_pad_sz;
4175 		var_msg_info->ap_id_chars = (char *)
4176 		    malloc(var_msg_info->ap_id_char_size);
4177 		if (var_msg_info->ap_id_chars == NULL) {
4178 			return (RDR_MEM_ALLOC);
4179 		}
4180 
4181 		bufptr = var_msg_info->ap_id_chars;
4182 		for (i = 0; i < num_ap_ids; i++) {
4183 			(void) memcpy(bufptr, ap_ids[i],
4184 			    var_msg_info->ap_id_sizes[i]);
4185 			bufptr += var_msg_info->ap_id_sizes[i];
4186 		}
4187 		for (i = 0; i < ap_id_pad_sz; i++) {
4188 			bufptr[i] = 0;
4189 		}
4190 	} else {
4191 		ap_id_pad_sz = 0;
4192 	}
4193 
4194 	return (RDR_OK);
4195 }
4196 
4197 
4198 /*
4199  * unpack_ap_ids:
4200  *
4201  * Unpack a buffer containing a concatenation of a list of
4202  * attachment point identifiers. The resulting list of strings
4203  * are stored in an array in the specified rdr_variable_message_info_t.
4204  */
4205 static int
4206 unpack_ap_ids(int num_ap_ids, char **ap_ids, const char *buf,
4207     rdr_variable_message_info_t *var_msg_info)
4208 {
4209 	int	i;
4210 	int	ap_id_size;
4211 	int	chars_copied;
4212 	char	*bufptr;
4213 
4214 
4215 	if ((ap_ids == NULL) || (buf == NULL) || (var_msg_info == NULL)) {
4216 		return (RDR_ERROR);
4217 	}
4218 	bufptr = (char *)buf;
4219 
4220 	var_msg_info->ap_id_int_size = sizeof (int) * num_ap_ids;
4221 	if (num_ap_ids > 0) {
4222 		var_msg_info->ap_id_sizes = (int *)
4223 		malloc(sizeof (int) * var_msg_info->ap_id_int_size);
4224 		if (var_msg_info->ap_id_sizes == NULL) {
4225 			return (RDR_MEM_ALLOC);
4226 		}
4227 		(void) memcpy(var_msg_info->ap_id_sizes, bufptr,
4228 		    var_msg_info->ap_id_int_size);
4229 	}
4230 	bufptr += var_msg_info->ap_id_int_size;
4231 
4232 	chars_copied = 0;
4233 	for (i = 0; i < num_ap_ids; i++) {
4234 		ap_id_size = var_msg_info->ap_id_sizes[i];
4235 		if (ap_id_size <= 0) {
4236 			continue;
4237 		}
4238 		if ((chars_copied + ap_id_size) >
4239 			var_msg_info->ap_id_char_size) {
4240 			return (RDR_ERROR);
4241 		}
4242 		ap_ids[i] = (char *)malloc(ap_id_size);
4243 		if (ap_ids[i] == NULL) {
4244 			return (RDR_MEM_ALLOC);
4245 		}
4246 		(void) memcpy(ap_ids[i], bufptr, ap_id_size);
4247 		bufptr += ap_id_size;
4248 		chars_copied += ap_id_size;
4249 	}
4250 	return (RDR_OK);
4251 }
4252 
4253 
4254 /*
4255  * find_options_sizes:
4256  *
4257  * Determine the size of a specified option string. The information
4258  * is stored in the specified rdr_variable_message_info_t.
4259  */
4260 static int
4261 find_options_sizes(char *options, rdr_variable_message_info_t *var_msg_info)
4262 {
4263 	if (var_msg_info == NULL) {
4264 		return (RDR_ERROR);
4265 	}
4266 	if (options != NULL) {
4267 		var_msg_info->options_strlen = strlen(options) + 1;
4268 		var_msg_info->options_pad_sz = RDR_ALIGN_64_BIT -
4269 		    (var_msg_info->options_strlen % RDR_ALIGN_64_BIT);
4270 	} else {
4271 		var_msg_info->options_strlen = 0;
4272 		var_msg_info->options_pad_sz = 0;
4273 	}
4274 	return (RDR_OK);
4275 }
4276 
4277 
4278 /*
4279  * find_listopts_sizes:
4280  *
4281  * Determine the size of a specified list option string. The information
4282  * is stored in the specified rdr_variable_message_info_t.
4283  */
4284 static int
4285 find_listopts_sizes(char *listopts, rdr_variable_message_info_t *var_msg_info)
4286 {
4287 	if (var_msg_info == NULL) {
4288 		return (RDR_ERROR);
4289 	}
4290 	if (listopts != NULL) {
4291 		var_msg_info->listopts_strlen = strlen(listopts) + 1;
4292 		var_msg_info->listopts_pad_sz = RDR_ALIGN_64_BIT -
4293 		    (var_msg_info->listopts_strlen % RDR_ALIGN_64_BIT);
4294 	} else {
4295 		var_msg_info->listopts_strlen = 0;
4296 		var_msg_info->listopts_pad_sz = 0;
4297 	}
4298 	return (RDR_OK);
4299 }
4300 
4301 
4302 /*
4303  * find_function_size:
4304  *
4305  * Determine the size of a specified private function string. The
4306  * information is stored in the specified rdr_variable_message_info_t.
4307  */
4308 static int
4309 find_function_sizes(char *function, rdr_variable_message_info_t *var_msg_info)
4310 {
4311 	if (var_msg_info == NULL) {
4312 		return (RDR_ERROR);
4313 	}
4314 	if (function != NULL) {
4315 		var_msg_info->function_strlen = strlen(function) + 1;
4316 		var_msg_info->function_pad_sz = RDR_ALIGN_64_BIT -
4317 		    (var_msg_info->function_strlen % RDR_ALIGN_64_BIT);
4318 	} else {
4319 		var_msg_info->function_strlen = 0;
4320 		var_msg_info->function_pad_sz = 0;
4321 	}
4322 	return (RDR_OK);
4323 }
4324 
4325 
4326 /*
4327  * find_errstring_sizes:
4328  *
4329  * Determine the size of a specified error string. The information
4330  * is stored in the specified rdr_variable_message_info_t.
4331  */
4332 static int
4333 find_errstring_sizes(char **errstring,
4334     rdr_variable_message_info_t *var_msg_info)
4335 {
4336 	if ((errstring != NULL) && (*errstring != NULL)) {
4337 		var_msg_info->errstring_strlen = strlen(*errstring) + 1;
4338 		var_msg_info->errstring_pad_sz = RDR_ALIGN_64_BIT -
4339 		    (var_msg_info->errstring_strlen % RDR_ALIGN_64_BIT);
4340 	} else {
4341 		var_msg_info->errstring_strlen = 0;
4342 		var_msg_info->errstring_pad_sz = 0;
4343 	}
4344 	return (RDR_OK);
4345 }
4346 
4347 
4348 /*
4349  * get_ap_ids_from_buf:
4350  *
4351  * Unpack a buffer containing a concatenation of a list of attachment
4352  * point identifiers. An appropriately sized buffer is allocated and
4353  * the resulting list of strings are stored in an array in the specified
4354  * rdr_variable_message_info_t.
4355  */
4356 static int
4357 get_ap_ids_from_buf(char ***ap_id_ptr, int num_ap_ids,
4358     rdr_variable_message_info_t *var_msg_info, const char *buf)
4359 {
4360 	if ((ap_id_ptr == NULL) || (buf == NULL) || (var_msg_info == NULL)) {
4361 		return (RDR_ERROR);
4362 	}
4363 	if (num_ap_ids > 0) {
4364 		*ap_id_ptr = (char **)malloc(sizeof (char *) * num_ap_ids);
4365 		if (*ap_id_ptr == NULL) {
4366 			return (RDR_MEM_ALLOC);
4367 		}
4368 		if (unpack_ap_ids(num_ap_ids, *ap_id_ptr, buf, var_msg_info)) {
4369 			cleanup_variable_ap_id_info(var_msg_info);
4370 			return (RDR_ERROR);
4371 		}
4372 
4373 	} else if (num_ap_ids < 0) {
4374 		return (RDR_ERROR);
4375 	}
4376 
4377 	cleanup_variable_ap_id_info(var_msg_info);
4378 
4379 	return (RDR_OK);
4380 }
4381 
4382 
4383 /*
4384  * get_string_from_buf:
4385  *
4386  * Copy a string to a new buffer. Memory is allocated for the
4387  * new buffer and the original string is copied to the new buffer.
4388  * This is primarily used when a string is located in a packed
4389  * buffer that will eventually get deallocated.
4390  */
4391 static int
4392 get_string_from_buf(char **stringptr, int strsize, const char *buf)
4393 {
4394 	if (buf == NULL) {
4395 		return (RDR_ERROR);
4396 	}
4397 
4398 	/*
4399 	 * A stringptr of NULL is a valid value. The errstring param
4400 	 * in an rconfig_xxx call is valid and is passed to this
4401 	 * function. For example, see errstring in the call to this
4402 	 * function in unpack_change_state_reply.
4403 	 */
4404 	if (stringptr != NULL) {
4405 		if (strsize > 0) {
4406 			*stringptr = (char *)malloc(strsize);
4407 			if (*stringptr == NULL) {
4408 				return (RDR_MEM_ALLOC);
4409 			}
4410 			(void) memcpy(*stringptr, buf, strsize);
4411 		} else if (strsize == 0) {
4412 			*stringptr = NULL;
4413 		} else if (strsize < 0) {
4414 			*stringptr = NULL;
4415 			return (RDR_ERROR);
4416 		}
4417 	}
4418 	return (RDR_OK);
4419 }
4420 
4421 
4422 /*
4423  * cleanup_ap_ids:
4424  *
4425  * Deallocate the specified array of attachment point identifiers.
4426  */
4427 static int
4428 cleanup_ap_ids(int num_ap_ids, char ** ap_ids)
4429 {
4430 	int	i;
4431 
4432 	if (ap_ids == NULL) {
4433 		return (RDR_ERROR);
4434 	}
4435 	for (i = 0; i < num_ap_ids; i++) {
4436 		if (ap_ids[i] != NULL) {
4437 			free((void *)ap_ids[i]);
4438 			ap_ids[i] = NULL;
4439 		}
4440 	}
4441 	return (RDR_OK);
4442 }
4443 
4444 
4445 /*
4446  * cleanup_errstring:
4447  *
4448  * Deallocate the specified error string.
4449  */
4450 static int
4451 cleanup_errstring(char **errstring)
4452 {
4453 	if (errstring) {
4454 		if (*errstring) {
4455 			free((void *)*errstring);
4456 		}
4457 		free((void *)errstring);
4458 		errstring = NULL;
4459 	}
4460 
4461 	return (RDR_OK);
4462 }
4463 
4464 
4465 /*
4466  * cleanup_variable_ap_id_info:
4467  *
4468  * Deallocate the ap_id information from the specified
4469  * rdr_variable_message_info_t.
4470  */
4471 static void
4472 cleanup_variable_ap_id_info(rdr_variable_message_info_t *var_msg_info)
4473 {
4474 	if (var_msg_info != NULL) {
4475 		if (var_msg_info->ap_id_sizes != NULL) {
4476 			free((void *)var_msg_info->ap_id_sizes);
4477 			var_msg_info->ap_id_sizes = NULL;
4478 		}
4479 		if (var_msg_info->ap_id_chars != NULL) {
4480 			free((void *)var_msg_info->ap_id_chars);
4481 			var_msg_info->ap_id_chars = NULL;
4482 		}
4483 	}
4484 }
4485 
4486 /*
4487  * load_libdscp:
4488  *
4489  * Try to dynamically link with libdscp.
4490  *
4491  * Returns:	0 if libdscp not available,
4492  *		1 if libdscp is available.
4493  */
4494 static int
4495 load_libdscp(libdscp_t *libdscp)
4496 {
4497 	int		len;
4498 	void		*lib;
4499 	static char	platform[100];
4500 	static char	pathname[MAXPATHLEN];
4501 
4502 	/*
4503 	 * Only try to load libdscp once.  Use the saved
4504 	 * status in the libdscp interface to know the
4505 	 * results of previous attempts.
4506 	 */
4507 	if (libdscp->status == LIBDSCP_AVAILABLE) {
4508 		return (1);
4509 	}
4510 	if (libdscp->status == LIBDSCP_UNAVAILABLE) {
4511 		return (0);
4512 	}
4513 
4514 	/*
4515 	 * Construct a platform specific pathname for libdscp.
4516 	 */
4517 	len = sysinfo(SI_PLATFORM, platform, sizeof (platform));
4518 	if ((len < 0) || (len > sizeof (platform))) {
4519 		return (0);
4520 	}
4521 	len = snprintf(pathname, MAXPATHLEN, LIBDSCP_PATH, platform);
4522 	if (len >= MAXPATHLEN) {
4523 		libdscp->status = LIBDSCP_UNAVAILABLE;
4524 		return (0);
4525 	}
4526 
4527 	/*
4528 	 * Try dynamically loading libdscp.
4529 	 */
4530 	if ((lib = dlopen(pathname, RTLD_LAZY)) == NULL) {
4531 		libdscp->status = LIBDSCP_UNAVAILABLE;
4532 		return (0);
4533 	}
4534 
4535 	/*
4536 	 * Try to resolve all the symbols.
4537 	 */
4538 	libdscp->bind = (int (*)(int, int, int))dlsym(lib, LIBDSCP_BIND);
4539 	libdscp->secure = (int (*)(int, int))dlsym(lib, LIBDSCP_SECURE);
4540 	libdscp->auth = (int (*)(int, struct sockaddr *, int))dlsym(lib,
4541 	    LIBDSCP_AUTH);
4542 
4543 	if ((libdscp->bind == NULL) ||
4544 	    (libdscp->secure == NULL) ||
4545 	    (libdscp->auth == NULL)) {
4546 		(void) dlclose(lib);
4547 		libdscp->status = LIBDSCP_UNAVAILABLE;
4548 		return (0);
4549 	}
4550 
4551 	/*
4552 	 * Success.
4553 	 * Update the status to indicate libdscp is available.
4554 	 */
4555 	libdscp->status = LIBDSCP_AVAILABLE;
4556 	return (1);
4557 }
4558