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