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 2000-2002 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 /*
1196  * Private (static) Functions
1197  */
1198 
1199 
1200 /*
1201  * rdr_setopt:
1202  *
1203  * Set the specified option for a given transport endpoint.
1204  * This function only sets boolean options. It does not
1205  * provide the ability to unset an option, or set a non-
1206  * boolean option.
1207  */
1208 static int
1209 rdr_setopt(int fd, int name, int level)
1210 {
1211 	int	on = 1;
1212 
1213 
1214 	if (setsockopt(fd, level, name, &on, sizeof (on)) == -1) {
1215 		return (RDR_NET_ERR);
1216 	}
1217 
1218 	return (RDR_OK);
1219 }
1220 
1221 
1222 /*
1223  * rdr_bind:
1224  *
1225  * Bind the specified file descriptor to a specified
1226  * address. If the address is already bound, no error is
1227  * returned. This is the expected behavior if a server
1228  * has been started by inetd (1M).
1229  */
1230 static int
1231 rdr_bind(int fd, struct sockaddr *addr)
1232 {
1233 	unsigned int		addr_len;
1234 	int			rc;
1235 
1236 
1237 	/* initialize the address */
1238 	switch (addr->sa_family) {
1239 
1240 	case AF_INET:
1241 		addr_len = sizeof (struct sockaddr_in);
1242 		break;
1243 
1244 	case AF_INET6:
1245 		addr_len = sizeof (struct sockaddr_in6);
1246 		break;
1247 
1248 	default:
1249 		return (RDR_ERROR);
1250 	}
1251 
1252 	/* attempt to bind the address */
1253 	rc = bind(fd, addr, addr_len);
1254 
1255 	/*
1256 	 * Ignore the error if EINVAL is returned. In
1257 	 * this case, we assume that this means that
1258 	 * the address was already bound. This is not
1259 	 * an error for servers started by inetd (1M).
1260 	 */
1261 	if ((rc == -1) && (errno != EINVAL)) {
1262 		return (RDR_NET_ERR);
1263 	}
1264 
1265 	/*
1266 	 * Retreive the address information of the
1267 	 * address that was actually bound.
1268 	 */
1269 	addr_len = sizeof (*addr);
1270 	if (getsockname(fd, addr, &addr_len) == -1) {
1271 		(void) memset(addr, 0, sizeof (*addr));
1272 		return (RDR_NET_ERR);
1273 	}
1274 
1275 	return (RDR_OK);
1276 }
1277 
1278 
1279 /*
1280  * rdr_snd:
1281  *
1282  * Send a message in two stages. First the header is sent,
1283  * followed by the packed buffer containing the message
1284  * contents.
1285  */
1286 static int
1287 rdr_snd(int fd, rdr_msg_hdr_t *hdr, char *data, int data_sz, int timeout)
1288 {
1289 	int	err;
1290 
1291 
1292 	/* sanity check */
1293 	if (hdr == NULL) {
1294 		return (RDR_ERROR);
1295 	}
1296 
1297 	/* ensure null pad bytes */
1298 	hdr->pad_byte1 = 0;
1299 	hdr->pad_byte2 = 0;
1300 
1301 	/* initialize size information */
1302 	hdr->data_length = data_sz;
1303 
1304 	/* send message header */
1305 	err = rdr_snd_raw(fd, (char *)hdr, RDR_MSG_HDR_SIZE, timeout);
1306 	if (err != RDR_OK) {
1307 		return (err);
1308 	}
1309 
1310 	/* check if more to send */
1311 	if (data_sz == 0) {
1312 		return (RDR_OK);
1313 	}
1314 
1315 	/* send message data */
1316 	err = rdr_snd_raw(fd, data, data_sz, timeout);
1317 	if (err != RDR_OK) {
1318 		return (err);
1319 	}
1320 
1321 	return (RDR_OK);
1322 }
1323 
1324 
1325 /*
1326  * rdr_snd_raw:
1327  *
1328  * Send a raw buffer of information. This function handles
1329  * the low level details of the send operation.
1330  */
1331 static int
1332 rdr_snd_raw(int fd, char *msg, int data_sz, int timeout)
1333 {
1334 	int		err;
1335 	int		num_bytes;
1336 	int		bytes_left;
1337 	char		*bufp;
1338 	struct pollfd	pfd;
1339 
1340 
1341 	bufp = (char *)msg;
1342 
1343 	bytes_left = data_sz;
1344 
1345 	pfd.fd = fd;
1346 	pfd.events = POLLOUT;
1347 
1348 	while (bytes_left > 0) {
1349 
1350 		pfd.revents = 0;
1351 
1352 		/* wait until we can send the data */
1353 		if ((err = poll(&pfd, 1, timeout)) == -1) {
1354 
1355 			/* poll was interrupted */
1356 			if (errno == EINTR) {
1357 				return (RDR_ABORTED);
1358 			}
1359 
1360 			return (RDR_ERROR);
1361 
1362 		} else if (err == 0) {
1363 			return (RDR_TIMEOUT);
1364 		}
1365 
1366 		/* ready to send data */
1367 		if (pfd.revents & POLLOUT) {
1368 
1369 			num_bytes = write(fd, bufp, bytes_left);
1370 
1371 			if (num_bytes == -1) {
1372 
1373 				/*
1374 				 * Distinguish between an aborted
1375 				 * session and other network errors.
1376 				 */
1377 				if (errno == EPIPE) {
1378 					return (RDR_ABORTED);
1379 				} else {
1380 					return (RDR_NET_ERR);
1381 				}
1382 			}
1383 
1384 			/* wrote 0 bytes, so operation was aborted */
1385 			if (num_bytes == 0) {
1386 				return (RDR_ABORTED);
1387 			}
1388 
1389 		} else {
1390 			return (RDR_NET_ERR);
1391 		}
1392 
1393 		bytes_left -= num_bytes;
1394 		bufp += num_bytes;
1395 	}
1396 
1397 	return (RDR_OK);
1398 }
1399 
1400 
1401 /*
1402  * rdr_rcv:
1403  *
1404  * Receive a message in two stages. First the header is
1405  * received, followed by the packed buffer containing the
1406  * message contents.
1407  */
1408 static int
1409 rdr_rcv(int fd, rdr_msg_hdr_t *hdr, char **data, int timeout)
1410 {
1411 	int	err;
1412 	int	data_sz;
1413 	char	hdr_buf[RDR_MSG_HDR_SIZE];
1414 	char	*buf = NULL;
1415 
1416 
1417 	/* sanity check */
1418 	if (hdr == NULL) {
1419 		return (RDR_ERROR);
1420 	}
1421 
1422 	/* receive the header */
1423 	err = rdr_rcv_raw(fd, hdr_buf, RDR_MSG_HDR_SIZE, timeout);
1424 	if (err != RDR_OK) {
1425 		return (err);
1426 	}
1427 
1428 	/* verify that the data is good */
1429 	/* LINTED Pointer Cast Alignment Warning */
1430 	if (validate_header((rdr_msg_hdr_t *)hdr_buf) != RDR_OK) {
1431 		return (RDR_MSG_INVAL);
1432 	}
1433 
1434 	/* LINTED Pointer Cast Alignment Warning */
1435 	data_sz = ((rdr_msg_hdr_t *)hdr_buf)->data_length;
1436 
1437 	buf = (char *)malloc(data_sz);
1438 	if (!buf) {
1439 		return (RDR_MEM_ALLOC);
1440 	}
1441 
1442 	if (data_sz != 0) {
1443 
1444 		/* receive the rest of the message */
1445 		err = rdr_rcv_raw(fd, buf, data_sz, timeout);
1446 		if (err != RDR_OK) {
1447 			free((void *)buf);
1448 			return (err);
1449 		}
1450 	}
1451 
1452 	/* copy out data */
1453 	*data = buf;
1454 	(void) memcpy(hdr, hdr_buf, RDR_MSG_HDR_SIZE);
1455 
1456 	return (RDR_OK);
1457 }
1458 
1459 
1460 /*
1461  * rdr_rcv_raw:
1462  *
1463  * Receive a raw buffer of information. This function handles
1464  * the low level details of the receive operation.
1465  */
1466 static int
1467 rdr_rcv_raw(int fd, char *msg, int data_size, int timeout)
1468 {
1469 	int		num_bytes;
1470 	int		err;
1471 	int		bytes_left;
1472 	char		*bufp;
1473 	struct pollfd	pollfd;
1474 
1475 
1476 	bufp = (char *)msg;
1477 	bytes_left = data_size;
1478 
1479 	pollfd.fd = fd;
1480 	pollfd.events = POLLIN;
1481 
1482 	while (bytes_left > 0) {
1483 
1484 		errno = 0;
1485 		pollfd.revents = 0;
1486 
1487 		if ((err = poll(&pollfd, 1, timeout)) == -1) {
1488 
1489 			/*
1490 			 * In the DCA, if a session is aborted, SIGINT
1491 			 * is delivered to all active sessions. This
1492 			 * mistakenly causes all sessions waiting in
1493 			 * the poll to be interrupted. So, if EINTR
1494 			 * is returned, it is ignored. If another error
1495 			 * occurs right away, the current session really
1496 			 * was aborted. All other sessions won't encounter
1497 			 * an error and will proceed normally.
1498 			 */
1499 			if ((errno == 0) || (errno == EINTR)) {
1500 				continue;
1501 			}
1502 
1503 			return (RDR_ABORTED);
1504 
1505 		} else if (err == 0) {
1506 			return (RDR_TIMEOUT);
1507 		}
1508 
1509 		/* ready to receive data */
1510 		if (pollfd.revents & POLLIN) {
1511 
1512 			num_bytes = read(fd, bufp, bytes_left);
1513 
1514 			if (num_bytes == -1) {
1515 
1516 				/*
1517 				 * Distinguish between an aborted
1518 				 * session and other network errors.
1519 				 */
1520 				if (errno == ECONNRESET) {
1521 					return (RDR_ABORTED);
1522 				} else {
1523 					return (RDR_NET_ERR);
1524 				}
1525 			}
1526 
1527 			/* read 0 bytes, so operation was aborted */
1528 			if (num_bytes == 0) {
1529 				return (RDR_ABORTED);
1530 			}
1531 
1532 		} else {
1533 			return (RDR_NET_ERR);
1534 		}
1535 
1536 		bytes_left -= num_bytes;
1537 		bufp += num_bytes;
1538 	}
1539 
1540 	return (RDR_OK);
1541 }
1542 
1543 
1544 /*
1545  * validate_header:
1546  *
1547  * Perform a series of sanity checks on the header data that is
1548  * received. This gets called before the variable length data is
1549  * read in to make sure that the information in the header can
1550  * be trusted.
1551  */
1552 static int
1553 validate_header(rdr_msg_hdr_t *hdr)
1554 {
1555 	unsigned char	op;
1556 
1557 
1558 	if (hdr == NULL) {
1559 		return (RDR_ERROR);
1560 	}
1561 
1562 	op = hdr->message_opcode;
1563 
1564 	/* validate opcode */
1565 	if ((op < RDR_SES_REQ) || (op >= RDR_NUM_OPS)) {
1566 		return (RDR_ERROR);
1567 	}
1568 
1569 	/* validate message size (and type) for op */
1570 	switch (hdr->data_type) {
1571 
1572 	case RDR_REQUEST:
1573 		if (hdr->data_length > msg_sizes[op].req_max) {
1574 			return (RDR_ERROR);
1575 		}
1576 		break;
1577 
1578 	case RDR_REPLY:
1579 		if (hdr->data_length > msg_sizes[op].reply_max) {
1580 			return (RDR_ERROR);
1581 		}
1582 		break;
1583 
1584 	default:
1585 		/* invalid data type */
1586 		return (RDR_ERROR);
1587 	}
1588 
1589 	/* all checks passed */
1590 	return (RDR_OK);
1591 }
1592 
1593 
1594 /*
1595  * pack_ses_req_request:
1596  *
1597  * Handle packing a session request request message.
1598  */
1599 static int
1600 pack_ses_req_request(ses_req_params_t *params, char **buf, int *buf_size)
1601 {
1602 	char		*bufptr;
1603 	int		locale_str_len;
1604 	rdr_ses_req_t	ses_req;
1605 
1606 
1607 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
1608 		return (RDR_ERROR);
1609 	}
1610 
1611 	/*
1612 	 * Determine the size of the locale string
1613 	 */
1614 	if (params->locale_str != NULL) {
1615 		locale_str_len = strlen(params->locale_str) + 1;
1616 	} else {
1617 		locale_str_len = 0;
1618 	}
1619 
1620 	/*
1621 	 * Collect size info specific to the ses_req request message
1622 	 * and allocate a buffer
1623 	 */
1624 	*buf_size = sizeof (rdr_ses_req_t);
1625 	*buf_size += locale_str_len;
1626 
1627 	*buf = (char *)malloc(*buf_size);
1628 	if (*buf == NULL) {
1629 		return (RDR_MEM_ALLOC);
1630 	}
1631 
1632 	/*
1633 	 * Set fixed locale size label by name
1634 	 */
1635 	ses_req.locale_size = locale_str_len;
1636 
1637 	/*
1638 	 * Set variable information using memcpy
1639 	 */
1640 	bufptr = *buf;
1641 
1642 	(void) memcpy(bufptr, &ses_req, sizeof (rdr_ses_req_t));
1643 	bufptr += sizeof (rdr_ses_req_t);
1644 
1645 	if (params->locale_str != NULL) {
1646 		(void) memcpy(bufptr, params->locale_str, locale_str_len);
1647 		bufptr += locale_str_len;
1648 	}
1649 
1650 	return (RDR_OK);
1651 }
1652 
1653 
1654 /*
1655  * unpack_ses_req_request:
1656  *
1657  * Handle unpacking a session request request message.
1658  */
1659 static int
1660 unpack_ses_req_request(ses_req_params_t *params, const char *buf)
1661 {
1662 	char		*bufptr;
1663 	rdr_ses_req_t	ses_req_data;
1664 
1665 
1666 	if ((params == NULL) || (buf == NULL)) {
1667 		return (RDR_ERROR);
1668 	}
1669 
1670 	bufptr = (char *)buf;
1671 	(void) memcpy(&ses_req_data, bufptr, sizeof (rdr_ses_req_t));
1672 	bufptr += sizeof (rdr_ses_req_t);
1673 
1674 	/*
1675 	 * handle getting the locale string
1676 	 */
1677 	if (get_string_from_buf(&(params->locale_str),
1678 	    ses_req_data.locale_size, bufptr)) {
1679 		return (RDR_ERROR);
1680 	}
1681 
1682 	return (RDR_OK);
1683 }
1684 
1685 
1686 /*
1687  * pack_ses_req_reply:
1688  *
1689  * Handle packing a session request reply message.
1690  */
1691 static int
1692 pack_ses_req_reply(ses_req_params_t *params, char **buf, int *buf_size)
1693 {
1694 	rdr_ses_req_reply_t	ses_req_reply_data;
1695 
1696 
1697 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
1698 		return (RDR_ERROR);
1699 	}
1700 
1701 	/*
1702 	 * Collect size info specific to the session request reply
1703 	 * message and allocate a buffer
1704 	 */
1705 	*buf_size = sizeof (rdr_ses_req_reply_t);
1706 
1707 	*buf = (char *)malloc(*buf_size);
1708 	if (*buf == NULL) {
1709 		return (RDR_MEM_ALLOC);
1710 	}
1711 
1712 	/*
1713 	 * Set fixed session identifier
1714 	 */
1715 	ses_req_reply_data.session_id = params->session_id;
1716 
1717 	/*
1718 	 * Copy information using memcpy
1719 	 */
1720 	(void) memcpy(*buf, &ses_req_reply_data, sizeof (rdr_ses_req_reply_t));
1721 
1722 	return (RDR_OK);
1723 }
1724 
1725 
1726 /*
1727  * unpack_ses_req_request:
1728  *
1729  * Handle unpacking a session request reply message.
1730  */
1731 static int
1732 unpack_ses_req_reply(ses_req_params_t *params, const char *buf)
1733 {
1734 	rdr_ses_req_reply_t	*ses_req_reply_datap;
1735 
1736 
1737 	if ((params == NULL) || (buf == NULL)) {
1738 		return (RDR_ERROR);
1739 	}
1740 
1741 	/* LINTED Pointer Cast Alignment Warning */
1742 	ses_req_reply_datap = (rdr_ses_req_reply_t *)buf;
1743 
1744 	/*
1745 	 * copy out the session information
1746 	 */
1747 	params->session_id = ses_req_reply_datap->session_id;
1748 
1749 	return (RDR_OK);
1750 }
1751 
1752 
1753 /*
1754  * pack_change_state_request:
1755  *
1756  * Handle packing a change state request message.
1757  */
1758 static int
1759 pack_change_state_request(change_state_params_t *params, char **buf,
1760     int *buf_size)
1761 {
1762 	int				i;
1763 	char				*bufptr;
1764 	rdr_change_state_t		change_state_data;
1765 	rdr_variable_message_info_t	var_msg_info;
1766 
1767 
1768 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
1769 		return (RDR_ERROR);
1770 	}
1771 
1772 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
1773 
1774 	/*
1775 	 * Set variable length fields and make a call to partially
1776 	 * pack it.
1777 	 */
1778 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
1779 		cleanup_variable_ap_id_info(&var_msg_info);
1780 		return (RDR_ERROR);
1781 	}
1782 	if (find_options_sizes(params->options, &var_msg_info)) {
1783 		cleanup_variable_ap_id_info(&var_msg_info);
1784 		return (RDR_ERROR);
1785 	}
1786 
1787 	/*
1788 	 * Collect size info specific to the change_state request
1789 	 * message and allocate a buffer
1790 	 */
1791 	*buf_size = sizeof (rdr_change_state_t);
1792 	*buf_size += var_msg_info.ap_id_int_size;
1793 	*buf_size += var_msg_info.ap_id_char_size;
1794 	*buf_size += var_msg_info.options_strlen;
1795 	*buf_size += var_msg_info.options_pad_sz;
1796 
1797 	*buf = (char *)malloc(*buf_size);
1798 	if (*buf == NULL) {
1799 		cleanup_variable_ap_id_info(&var_msg_info);
1800 		return (RDR_MEM_ALLOC);
1801 	}
1802 
1803 	/*
1804 	 * Set fixed address labels by name
1805 	 */
1806 	change_state_data.num_ap_ids = params->num_ap_ids;
1807 	change_state_data.ap_id_char_size = var_msg_info.ap_id_char_size;
1808 	change_state_data.options_size = var_msg_info.options_strlen +
1809 	    var_msg_info.options_pad_sz;
1810 
1811 	if (params->confp != NULL) {
1812 		change_state_data.confirm_callback_id =
1813 		    (unsigned long)params->confp->confirm;
1814 		change_state_data.confirm_appdata_ptr =
1815 		    (unsigned long)params->confp->appdata_ptr;
1816 	} else {
1817 		change_state_data.confirm_callback_id = 0;
1818 		change_state_data.confirm_appdata_ptr = 0;
1819 	}
1820 	if (params->msgp != NULL) {
1821 		change_state_data.msg_callback_id =
1822 		    (unsigned long)params->msgp->message_routine;
1823 		change_state_data.msg_appdata_ptr =
1824 		    (unsigned long)params->msgp->appdata_ptr;
1825 	} else {
1826 		change_state_data.msg_callback_id = 0;
1827 		change_state_data.msg_appdata_ptr = 0;
1828 	}
1829 
1830 	change_state_data.flags = params->flags;
1831 	change_state_data.timeval = params->timeval;
1832 	change_state_data.state_change_cmd = params->state_change;
1833 	if (params->errstring != NULL) {
1834 		change_state_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
1835 	} else {
1836 		change_state_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
1837 	}
1838 	change_state_data.retries = params->retries;
1839 
1840 	/*
1841 	 * Set variable information using memcpy
1842 	 */
1843 	bufptr = *buf;
1844 
1845 	(void) memcpy(bufptr, &change_state_data, sizeof (rdr_change_state_t));
1846 	bufptr += sizeof (rdr_change_state_t);
1847 
1848 	if (var_msg_info.ap_id_sizes != NULL) {
1849 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
1850 		    var_msg_info.ap_id_int_size);
1851 		bufptr += var_msg_info.ap_id_int_size;
1852 	}
1853 
1854 	if (var_msg_info.ap_id_chars != NULL) {
1855 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
1856 		    var_msg_info.ap_id_char_size);
1857 		bufptr += var_msg_info.ap_id_char_size;
1858 	}
1859 
1860 	if (params->options != NULL) {
1861 		(void) memcpy(bufptr, params->options,
1862 		    var_msg_info.options_strlen);
1863 		bufptr += var_msg_info.options_strlen;
1864 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
1865 			bufptr[i] = 0;
1866 		}
1867 		bufptr += var_msg_info.options_pad_sz;
1868 	}
1869 
1870 	cleanup_variable_ap_id_info(&var_msg_info);
1871 
1872 	return (RDR_OK);
1873 }
1874 
1875 
1876 /*
1877  * unpack_change_state_request:
1878  *
1879  * Handle unpacking a change state request message.
1880  */
1881 static int
1882 unpack_change_state_request(change_state_params_t *params, const char *buf)
1883 {
1884 	char				*bufptr;
1885 	rdr_variable_message_info_t 	var_msg_info;
1886 	rdr_change_state_t		change_state_data;
1887 
1888 
1889 	if ((params == NULL) || (buf == NULL)) {
1890 		return (RDR_ERROR);
1891 	}
1892 
1893 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
1894 
1895 	bufptr = (char *)buf;
1896 	(void) memcpy(&change_state_data, bufptr, sizeof (rdr_change_state_t));
1897 	bufptr += sizeof (rdr_change_state_t);
1898 
1899 	/*
1900 	 * handle getting the ap_ids
1901 	 */
1902 	var_msg_info.ap_id_char_size = change_state_data.ap_id_char_size;
1903 	if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
1904 	    change_state_data.num_ap_ids, &var_msg_info, bufptr)) {
1905 		return (RDR_ERROR);
1906 	}
1907 	bufptr += var_msg_info.ap_id_int_size;
1908 	bufptr += var_msg_info.ap_id_char_size;
1909 
1910 	/*
1911 	 * handle getting the options
1912 	 */
1913 	if (get_string_from_buf(&(params->options),
1914 	    change_state_data.options_size, bufptr)) {
1915 		return (RDR_ERROR);
1916 	}
1917 	bufptr += change_state_data.options_size;
1918 
1919 	/*
1920 	 * Set fixed address labels by name
1921 	 */
1922 	params->state_change = (cfga_cmd_t)change_state_data.state_change_cmd;
1923 	params->num_ap_ids = change_state_data.num_ap_ids;
1924 
1925 	params->confp = (struct cfga_confirm *)
1926 	    malloc(sizeof (struct cfga_confirm));
1927 	if (params->confp == NULL) {
1928 		return (RDR_MEM_ALLOC);
1929 	}
1930 
1931 	/* set params->confp->confirm using memcpy */
1932 	(void) memcpy((void*)params->confp,
1933 	    &(change_state_data.confirm_callback_id), sizeof (unsigned long));
1934 	params->confp->appdata_ptr =
1935 	    (void*)change_state_data.confirm_appdata_ptr;
1936 
1937 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
1938 	if (params->msgp == NULL) {
1939 		return (RDR_MEM_ALLOC);
1940 	}
1941 
1942 	/* set params->msgp->message_routine using memcpy */
1943 	(void) memcpy((void*)params->msgp,
1944 	    &(change_state_data.msg_callback_id), sizeof (unsigned long));
1945 	params->msgp->appdata_ptr =
1946 	    (void*)change_state_data.msg_appdata_ptr;
1947 
1948 	if (change_state_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
1949 		params->errstring = (char **)malloc(sizeof (char *));
1950 		if (params->errstring == NULL) {
1951 			return (RDR_MEM_ALLOC);
1952 		}
1953 		*(params->errstring) = NULL;
1954 	} else {	/* error_msg_ctl == RDR_DONT_GENERATE_ERR_MSGS */
1955 		params->errstring = NULL;
1956 	}
1957 	params->flags = change_state_data.flags;
1958 	params->timeval = change_state_data.timeval;
1959 	params->retries = change_state_data.retries;
1960 
1961 	return (RDR_OK);
1962 }
1963 
1964 
1965 /*
1966  * pack_change_state_reply:
1967  *
1968  * Handle packing a change state reply message.
1969  */
1970 static int
1971 pack_change_state_reply(change_state_params_t *params, char **buf,
1972     int *buf_size)
1973 {
1974 	int				i;
1975 	char				*bufptr;
1976 	rdr_change_state_reply_t	change_state_data;
1977 	rdr_variable_message_info_t 	var_msg_info;
1978 
1979 
1980 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
1981 
1982 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
1983 		return (RDR_ERROR);
1984 	}
1985 
1986 	/*
1987 	 * Set variable length fields (size info)
1988 	 */
1989 	if (find_errstring_sizes(params->errstring, &var_msg_info)) {
1990 		return (RDR_ERROR);
1991 	}
1992 
1993 	/*
1994 	 * Collect size info specific to the change_state reply
1995 	 * message and allocate a buffer
1996 	 */
1997 	*buf_size = sizeof (rdr_change_state_reply_t);
1998 	*buf_size += var_msg_info.errstring_strlen;
1999 	*buf_size += var_msg_info.errstring_pad_sz;
2000 
2001 	*buf = (char *)malloc(*buf_size);
2002 	if (*buf == NULL) {
2003 		return (RDR_MEM_ALLOC);
2004 	}
2005 
2006 	/*
2007 	 * Set fixed address labels by name
2008 	 */
2009 	change_state_data.errstring_size = var_msg_info.errstring_strlen +
2010 	    var_msg_info.errstring_pad_sz;
2011 
2012 	/*
2013 	 * Set variable information using memcpy
2014 	 */
2015 	bufptr = *buf;
2016 
2017 	(void) memcpy(bufptr, &change_state_data,
2018 	    sizeof (rdr_change_state_reply_t));
2019 	bufptr += sizeof (rdr_change_state_reply_t);
2020 
2021 	if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
2022 		(void) memcpy(bufptr, *(params->errstring),
2023 		    var_msg_info.errstring_strlen);
2024 		bufptr += var_msg_info.errstring_strlen;
2025 		for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
2026 			bufptr[i] = 0;
2027 		}
2028 		bufptr += var_msg_info.errstring_pad_sz;
2029 	}
2030 
2031 	return (RDR_OK);
2032 }
2033 
2034 
2035 /*
2036  * unpack_change_state_reply:
2037  *
2038  * Handle unpacking a change state reply message.
2039  */
2040 static int
2041 unpack_change_state_reply(change_state_params_t *params, const char *buf)
2042 {
2043 	char				*bufptr;
2044 	rdr_change_state_reply_t	change_state_data;
2045 
2046 	if ((params == NULL) || (buf == NULL)) {
2047 		return (RDR_ERROR);
2048 	}
2049 
2050 	bufptr = (char *)buf;
2051 	(void) memcpy(&change_state_data, bufptr,
2052 	    sizeof (rdr_change_state_reply_t));
2053 	bufptr += sizeof (rdr_change_state_reply_t);
2054 
2055 	/*
2056 	 * handle getting the errstring
2057 	 */
2058 	params->errstring = (char **)malloc(sizeof (char *));
2059 	if (params->errstring == NULL) {
2060 		return (RDR_MEM_ALLOC);
2061 	}
2062 	if (get_string_from_buf(params->errstring,
2063 	    change_state_data.errstring_size, bufptr)) {
2064 		return (RDR_ERROR);
2065 	}
2066 	bufptr += change_state_data.errstring_size;
2067 
2068 	return (RDR_OK);
2069 }
2070 
2071 
2072 /*
2073  * pack_private_func_request:
2074  *
2075  * Handle packing a private function request message.
2076  */
2077 static int
2078 pack_private_func_request(private_func_params_t *params, char **buf,
2079     int *buf_size)
2080 {
2081 	int				i;
2082 	char				*bufptr;
2083 	rdr_private_func_t		private_func_data;
2084 	rdr_variable_message_info_t	var_msg_info;
2085 
2086 
2087 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
2088 		return (RDR_ERROR);
2089 	}
2090 
2091 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2092 
2093 	/*
2094 	 * Set variable length fields and make a call to partially
2095 	 * pack it.
2096 	 */
2097 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
2098 		cleanup_variable_ap_id_info(&var_msg_info);
2099 		return (RDR_ERROR);
2100 	}
2101 	if (find_options_sizes(params->options, &var_msg_info)) {
2102 		cleanup_variable_ap_id_info(&var_msg_info);
2103 		return (RDR_ERROR);
2104 	}
2105 	if (find_function_sizes(params->function, &var_msg_info)) {
2106 		cleanup_variable_ap_id_info(&var_msg_info);
2107 		return (RDR_ERROR);
2108 	}
2109 
2110 	/*
2111 	 * Collect size info specific to the private_func request
2112 	 * message and allocate a buffer
2113 	 */
2114 	*buf_size = sizeof (rdr_private_func_t);
2115 	*buf_size += var_msg_info.ap_id_int_size;
2116 	*buf_size += var_msg_info.ap_id_char_size;
2117 	*buf_size += var_msg_info.options_strlen;
2118 	*buf_size += var_msg_info.options_pad_sz;
2119 	*buf_size += var_msg_info.function_strlen;
2120 	*buf_size += var_msg_info.function_pad_sz;
2121 
2122 	*buf = (char *)malloc(*buf_size);
2123 	if (*buf == NULL) {
2124 		cleanup_variable_ap_id_info(&var_msg_info);
2125 		return (RDR_MEM_ALLOC);
2126 	}
2127 
2128 	/*
2129 	 * Set fixed address labels by name
2130 	 */
2131 	private_func_data.num_ap_ids = params->num_ap_ids;
2132 	private_func_data.ap_id_char_size = var_msg_info.ap_id_char_size;
2133 	private_func_data.options_size = var_msg_info.options_strlen +
2134 	    var_msg_info.options_pad_sz;
2135 	private_func_data.function_size = var_msg_info.function_strlen +
2136 	    var_msg_info.function_pad_sz;
2137 
2138 	if (params->confp != NULL) {
2139 		private_func_data.confirm_callback_id =
2140 		    (unsigned long)params->confp->confirm;
2141 		private_func_data.confirm_appdata_ptr =
2142 		    (unsigned long)params->confp->appdata_ptr;
2143 	} else {
2144 		private_func_data.confirm_callback_id = 0;
2145 		private_func_data.confirm_appdata_ptr = 0;
2146 	}
2147 	if (params->msgp != NULL) {
2148 		private_func_data.msg_callback_id =
2149 		    (unsigned long)params->msgp->message_routine;
2150 		private_func_data.msg_appdata_ptr =
2151 		    (unsigned long)params->msgp->appdata_ptr;
2152 	} else {
2153 		private_func_data.msg_callback_id = 0;
2154 		private_func_data.msg_appdata_ptr = 0;
2155 	}
2156 
2157 	private_func_data.flags = params->flags;
2158 
2159 	if (params->errstring != NULL) {
2160 		private_func_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
2161 	} else {
2162 		private_func_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
2163 	}
2164 
2165 	/*
2166 	 * Set variable information using memcpy
2167 	 */
2168 	bufptr = *buf;
2169 
2170 	(void) memcpy(bufptr, &private_func_data, sizeof (rdr_private_func_t));
2171 	bufptr += sizeof (rdr_private_func_t);
2172 
2173 	if (var_msg_info.ap_id_sizes != NULL) {
2174 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
2175 		    var_msg_info.ap_id_int_size);
2176 		bufptr += var_msg_info.ap_id_int_size;
2177 	}
2178 
2179 	if (var_msg_info.ap_id_chars != NULL) {
2180 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
2181 		    var_msg_info.ap_id_char_size);
2182 		bufptr += var_msg_info.ap_id_char_size;
2183 	}
2184 
2185 	if (params->options != NULL) {
2186 		(void) memcpy(bufptr, params->options,
2187 		    var_msg_info.options_strlen);
2188 		bufptr += var_msg_info.options_strlen;
2189 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
2190 			bufptr[i] = 0;
2191 		}
2192 		bufptr += var_msg_info.options_pad_sz;
2193 	}
2194 
2195 	if (params->function != NULL) {
2196 		(void) memcpy(bufptr, params->function,
2197 		    var_msg_info.function_strlen);
2198 		bufptr += var_msg_info.function_strlen;
2199 		for (i = 0; i < var_msg_info.function_pad_sz; i++) {
2200 			bufptr[i] = 0;
2201 		}
2202 		bufptr += var_msg_info.function_pad_sz;
2203 	}
2204 
2205 	cleanup_variable_ap_id_info(&var_msg_info);
2206 
2207 	return (RDR_OK);
2208 }
2209 
2210 
2211 /*
2212  * unpack_private_func_request:
2213  *
2214  * Handle unpacking a private function request message.
2215  */
2216 static int
2217 unpack_private_func_request(private_func_params_t *params, const char *buf)
2218 {
2219 	char				*bufptr;
2220 	rdr_variable_message_info_t 	var_msg_info;
2221 	rdr_private_func_t		private_func_data;
2222 
2223 
2224 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2225 
2226 	if ((params == NULL) || (buf == NULL)) {
2227 		return (RDR_ERROR);
2228 	}
2229 
2230 	bufptr = (char *)buf;
2231 	(void) memcpy(&private_func_data, bufptr, sizeof (rdr_private_func_t));
2232 	bufptr += sizeof (rdr_private_func_t);
2233 
2234 	/*
2235 	 * handle getting the ap_ids
2236 	 */
2237 	var_msg_info.ap_id_char_size = private_func_data.ap_id_char_size;
2238 	if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
2239 	    private_func_data.num_ap_ids, &var_msg_info, bufptr)) {
2240 		return (RDR_ERROR);
2241 	}
2242 	bufptr += var_msg_info.ap_id_int_size;
2243 	bufptr += var_msg_info.ap_id_char_size;
2244 
2245 	/*
2246 	 * handle getting the options and function
2247 	 */
2248 	if (get_string_from_buf(&(params->options),
2249 	    private_func_data.options_size, bufptr)) {
2250 		return (RDR_ERROR);
2251 	}
2252 	bufptr += private_func_data.options_size;
2253 
2254 	if (get_string_from_buf(&(params->function),
2255 	    private_func_data.function_size, bufptr)) {
2256 		return (RDR_ERROR);
2257 	}
2258 	bufptr += private_func_data.function_size;
2259 
2260 	/*
2261 	 * Set fixed address labels by name
2262 	 */
2263 	params->num_ap_ids = private_func_data.num_ap_ids;
2264 
2265 	params->confp = (struct cfga_confirm *)
2266 	    malloc(sizeof (struct cfga_confirm));
2267 	if (params->confp == NULL) {
2268 		return (RDR_MEM_ALLOC);
2269 	}
2270 
2271 	/* set params->confp->confirm using memcpy */
2272 	(void) memcpy((void*)params->confp,
2273 	    &(private_func_data.confirm_callback_id), sizeof (unsigned long));
2274 	params->confp->appdata_ptr =
2275 	    (void*)private_func_data.confirm_appdata_ptr;
2276 
2277 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
2278 	if (params->msgp == NULL) {
2279 		return (RDR_MEM_ALLOC);
2280 	}
2281 
2282 	/* set params->msgp->message_routine using memcpy */
2283 	(void) memcpy((void*)params->msgp,
2284 	    &(private_func_data.msg_callback_id), sizeof (unsigned long));
2285 	params->msgp->appdata_ptr =
2286 	    (void*)private_func_data.msg_appdata_ptr;
2287 
2288 	if (private_func_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
2289 		params->errstring = (char **)malloc(sizeof (char *));
2290 		if (params->errstring == NULL) {
2291 			return (RDR_MEM_ALLOC);
2292 		}
2293 		*(params->errstring) = NULL;
2294 	} else {	/* error_msg_ctl == RDR_DONT_GENERATE_ERR_MSGS */
2295 		params->errstring = NULL;
2296 	}
2297 	params->flags = private_func_data.flags;
2298 
2299 	return (RDR_OK);
2300 }
2301 
2302 
2303 /*
2304  * pack_private_func_reply:
2305  *
2306  * Handle packing a private function reply message.
2307  */
2308 static int
2309 pack_private_func_reply(private_func_params_t *params, char **buf,
2310     int *buf_size)
2311 {
2312 	int				i;
2313 	char				*bufptr;
2314 	rdr_private_func_reply_t	private_func_data;
2315 	rdr_variable_message_info_t 	var_msg_info;
2316 
2317 
2318 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2319 
2320 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
2321 		return (RDR_ERROR);
2322 	}
2323 
2324 	/*
2325 	 * Set variable length fields (size info)
2326 	 */
2327 	if (find_errstring_sizes(params->errstring, &var_msg_info)) {
2328 		return (RDR_ERROR);
2329 	}
2330 
2331 	/*
2332 	 * Collect size info specific to the private_func reply
2333 	 * message and allocate a buffer
2334 	 */
2335 	*buf_size = sizeof (rdr_private_func_reply_t);
2336 	*buf_size += var_msg_info.errstring_strlen;
2337 	*buf_size += var_msg_info.errstring_pad_sz;
2338 
2339 	*buf = (char *)malloc(*buf_size);
2340 	if (*buf == NULL) {
2341 		return (RDR_MEM_ALLOC);
2342 	}
2343 
2344 	/*
2345 	 * Set fixed address labels by name
2346 	 */
2347 	private_func_data.errstring_size = var_msg_info.errstring_strlen +
2348 	    var_msg_info.errstring_pad_sz;
2349 
2350 	/*
2351 	 * Set variable information using memcpy
2352 	 */
2353 	bufptr = *buf;
2354 
2355 	(void) memcpy(bufptr, &private_func_data,
2356 	    sizeof (rdr_private_func_reply_t));
2357 	bufptr += sizeof (rdr_private_func_reply_t);
2358 	if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
2359 		(void) memcpy(bufptr, *(params->errstring),
2360 		    var_msg_info.errstring_strlen);
2361 		bufptr += var_msg_info.errstring_strlen;
2362 		for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
2363 			bufptr[i] = 0;
2364 		}
2365 		bufptr += var_msg_info.errstring_pad_sz;
2366 	}
2367 
2368 	return (RDR_OK);
2369 }
2370 
2371 
2372 /*
2373  * unpack_private_func_reply:
2374  *
2375  * Handle unpacking a private function reply message.
2376  */
2377 static int
2378 unpack_private_func_reply(private_func_params_t *params, const char *buf)
2379 {
2380 	char				*bufptr;
2381 	rdr_private_func_reply_t	private_func_data;
2382 
2383 	if ((params == NULL) || (buf == NULL)) {
2384 		return (RDR_ERROR);
2385 	}
2386 
2387 	bufptr = (char *)buf;
2388 	(void) memcpy(&private_func_data, bufptr,
2389 	    sizeof (rdr_private_func_reply_t));
2390 	bufptr += sizeof (rdr_private_func_reply_t);
2391 
2392 	/*
2393 	 * handle getting the errstring
2394 	 */
2395 	params->errstring = (char **)malloc(sizeof (char *));
2396 	if (params->errstring == NULL) {
2397 		return (RDR_MEM_ALLOC);
2398 	}
2399 	if (get_string_from_buf(params->errstring,
2400 	    private_func_data.errstring_size, bufptr)) {
2401 		return (RDR_ERROR);
2402 	}
2403 	bufptr += private_func_data.errstring_size;
2404 
2405 	return (RDR_OK);
2406 }
2407 
2408 
2409 /*
2410  * pack_test_request:
2411  *
2412  * Handle packing a test request message.
2413  */
2414 static int
2415 pack_test_request(test_params_t *params, char **buf, int *buf_size)
2416 {
2417 	int				i;
2418 	char				*bufptr;
2419 	rdr_test_t			test_data;
2420 	rdr_variable_message_info_t	var_msg_info;
2421 
2422 
2423 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
2424 		return (RDR_ERROR);
2425 	}
2426 
2427 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2428 
2429 	/*
2430 	 * Set variable length fields and make a call to partially
2431 	 * pack it.
2432 	 */
2433 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
2434 		cleanup_variable_ap_id_info(&var_msg_info);
2435 		return (RDR_ERROR);
2436 	}
2437 	if (find_options_sizes(params->options, &var_msg_info)) {
2438 		cleanup_variable_ap_id_info(&var_msg_info);
2439 		return (RDR_ERROR);
2440 	}
2441 
2442 	/*
2443 	 * Collect size info specific to the test request
2444 	 * message and allocate a buffer
2445 	 */
2446 	*buf_size = sizeof (rdr_test_t);
2447 	*buf_size += var_msg_info.ap_id_int_size;
2448 	*buf_size += var_msg_info.ap_id_char_size;
2449 	*buf_size += var_msg_info.options_strlen;
2450 	*buf_size += var_msg_info.options_pad_sz;
2451 
2452 	*buf = (char *)malloc(*buf_size);
2453 	if (*buf == NULL) {
2454 		cleanup_variable_ap_id_info(&var_msg_info);
2455 		return (RDR_MEM_ALLOC);
2456 	}
2457 
2458 	/*
2459 	 * Set fixed address labels by name
2460 	 */
2461 	test_data.num_ap_ids = params->num_ap_ids;
2462 	test_data.ap_id_char_size = var_msg_info.ap_id_char_size;
2463 	test_data.options_size = var_msg_info.options_strlen +
2464 	    var_msg_info.options_pad_sz;
2465 
2466 	if (params->msgp != NULL) {
2467 		test_data.msg_callback_id =
2468 		    (unsigned long)params->msgp->message_routine;
2469 		test_data.msg_appdata_ptr =
2470 		    (unsigned long)params->msgp->appdata_ptr;
2471 	} else {
2472 		test_data.msg_callback_id = 0;
2473 		test_data.msg_appdata_ptr = 0;
2474 	}
2475 
2476 	test_data.flags = params->flags;
2477 
2478 	if (params->errstring != NULL) {
2479 		test_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
2480 	} else {
2481 		test_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
2482 	}
2483 
2484 	/*
2485 	 * Set variable information using memcpy
2486 	 */
2487 	bufptr = *buf;
2488 
2489 	(void) memcpy(bufptr, &test_data, sizeof (rdr_test_t));
2490 	bufptr += sizeof (rdr_test_t);
2491 
2492 	if (var_msg_info.ap_id_sizes != NULL) {
2493 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
2494 		    var_msg_info.ap_id_int_size);
2495 		bufptr += var_msg_info.ap_id_int_size;
2496 	}
2497 
2498 	if (var_msg_info.ap_id_chars != NULL) {
2499 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
2500 		    var_msg_info.ap_id_char_size);
2501 		bufptr += var_msg_info.ap_id_char_size;
2502 	}
2503 
2504 	if (params->options != NULL) {
2505 		(void) memcpy(bufptr, params->options,
2506 		    var_msg_info.options_strlen);
2507 		bufptr += var_msg_info.options_strlen;
2508 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
2509 			bufptr[i] = 0;
2510 		}
2511 		bufptr += var_msg_info.options_pad_sz;
2512 	}
2513 
2514 	cleanup_variable_ap_id_info(&var_msg_info);
2515 
2516 	return (RDR_OK);
2517 }
2518 
2519 
2520 /*
2521  * unpack_test_request:
2522  *
2523  * Handle unpacking a test request message.
2524  */
2525 static int
2526 unpack_test_request(test_params_t *params, const char *buf)
2527 {
2528 	char				*bufptr;
2529 	rdr_variable_message_info_t 	var_msg_info;
2530 	rdr_test_t			test_data;
2531 
2532 
2533 	if ((params == NULL) || (buf == NULL)) {
2534 		return (RDR_ERROR);
2535 	}
2536 
2537 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2538 
2539 	bufptr = (char *)buf;
2540 	(void) memcpy(&test_data, bufptr, sizeof (rdr_test_t));
2541 	bufptr += sizeof (rdr_test_t);
2542 
2543 	/*
2544 	 * handle getting the ap_ids
2545 	 */
2546 	var_msg_info.ap_id_char_size = test_data.ap_id_char_size;
2547 	if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
2548 	    test_data.num_ap_ids, &var_msg_info, bufptr)) {
2549 		return (RDR_ERROR);
2550 	}
2551 	bufptr += var_msg_info.ap_id_int_size;
2552 	bufptr += var_msg_info.ap_id_char_size;
2553 
2554 	/*
2555 	 * handle getting the options
2556 	 */
2557 	if (get_string_from_buf(&(params->options),
2558 	    test_data.options_size, bufptr)) {
2559 		return (RDR_ERROR);
2560 	}
2561 	bufptr += test_data.options_size;
2562 
2563 	/*
2564 	 * Set fixed address labels by name
2565 	 */
2566 	params->num_ap_ids = test_data.num_ap_ids;
2567 
2568 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
2569 	if (params->msgp == NULL) {
2570 		return (RDR_MEM_ALLOC);
2571 	}
2572 
2573 	/* set params->msgp->message_routine using memcpy */
2574 	(void) memcpy((void*)params->msgp,
2575 	    &(test_data.msg_callback_id), sizeof (unsigned long));
2576 	params->msgp->appdata_ptr =
2577 	    (void*)test_data.msg_appdata_ptr;
2578 
2579 	if (test_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
2580 		params->errstring = (char **)malloc(sizeof (char *));
2581 		if (params->errstring == NULL) {
2582 			return (RDR_MEM_ALLOC);
2583 		}
2584 		*(params->errstring) = NULL;
2585 	} else {	/* error_msg_ctl == RDR_DONT_GENERATE_ERR_MSGS */
2586 		params->errstring = NULL;
2587 	}
2588 	params->flags = test_data.flags;
2589 
2590 	return (RDR_OK);
2591 }
2592 
2593 
2594 /*
2595  * pack_test_reply:
2596  *
2597  * Handle packing a test reply message.
2598  */
2599 static int
2600 pack_test_reply(test_params_t *params, char **buf, int *buf_size)
2601 {
2602 	int				i;
2603 	char				*bufptr;
2604 	rdr_test_reply_t		test_data;
2605 	rdr_variable_message_info_t 	var_msg_info;
2606 
2607 
2608 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
2609 		return (RDR_ERROR);
2610 	}
2611 
2612 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2613 
2614 	/*
2615 	 * Set variable length fields (size info)
2616 	 */
2617 	if (find_errstring_sizes(params->errstring, &var_msg_info)) {
2618 		return (RDR_ERROR);
2619 	}
2620 
2621 	/*
2622 	 * Collect size info specific to the test reply
2623 	 * message and allocate a buffer
2624 	 */
2625 	*buf_size = sizeof (rdr_test_reply_t);
2626 	*buf_size += var_msg_info.errstring_strlen;
2627 	*buf_size += var_msg_info.errstring_pad_sz;
2628 
2629 	*buf = (char *)malloc(*buf_size);
2630 	if (*buf == NULL) {
2631 		return (RDR_MEM_ALLOC);
2632 	}
2633 
2634 	/*
2635 	 * Set fixed address labels by name
2636 	 */
2637 	test_data.errstring_size = var_msg_info.errstring_strlen +
2638 	    var_msg_info.errstring_pad_sz;
2639 
2640 	/*
2641 	 * Set variable information using memcpy
2642 	 */
2643 	bufptr = *buf;
2644 
2645 	(void) memcpy(bufptr, &test_data, sizeof (rdr_test_reply_t));
2646 	bufptr += sizeof (rdr_test_reply_t);
2647 	if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
2648 		(void) memcpy(bufptr, *(params->errstring),
2649 		    var_msg_info.errstring_strlen);
2650 		bufptr += var_msg_info.errstring_strlen;
2651 		for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
2652 			bufptr[i] = 0;
2653 		}
2654 		bufptr += var_msg_info.errstring_pad_sz;
2655 	}
2656 
2657 	return (RDR_OK);
2658 }
2659 
2660 
2661 /*
2662  * unpack_test_reply:
2663  *
2664  * Handle unpacking a test reply message.
2665  */
2666 static int
2667 unpack_test_reply(test_params_t *params, const char *buf)
2668 {
2669 	char			*bufptr;
2670 	rdr_test_reply_t	test_data;
2671 
2672 
2673 	if ((params == NULL) || (buf == NULL)) {
2674 		return (RDR_ERROR);
2675 	}
2676 
2677 	bufptr = (char *)buf;
2678 	(void) memcpy(&test_data, bufptr, sizeof (rdr_test_reply_t));
2679 	bufptr += sizeof (rdr_test_reply_t);
2680 
2681 	/*
2682 	 * handle getting the errstring
2683 	 */
2684 	params->errstring = (char **)malloc(sizeof (char *));
2685 	if (params->errstring == NULL) {
2686 		return (RDR_MEM_ALLOC);
2687 	}
2688 	if (get_string_from_buf(params->errstring,
2689 	    test_data.errstring_size, bufptr)) {
2690 		return (RDR_ERROR);
2691 	}
2692 	bufptr += test_data.errstring_size;
2693 
2694 	return (RDR_OK);
2695 }
2696 
2697 
2698 /*
2699  * pack_list_ext_request:
2700  *
2701  * Handle packing a list request message.
2702  */
2703 static int
2704 pack_list_ext_request(list_ext_params_t *params, char **buf, int *buf_size)
2705 {
2706 	int				i;
2707 	char				*bufptr;
2708 	rdr_list_ext_t 			list_ext_data;
2709 	rdr_variable_message_info_t 	var_msg_info;
2710 
2711 
2712 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
2713 		return (RDR_ERROR);
2714 	}
2715 
2716 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2717 
2718 	/*
2719 	 * Set variable length fields and make a call to partially
2720 	 * pack it.
2721 	 */
2722 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
2723 		cleanup_variable_ap_id_info(&var_msg_info);
2724 		return (RDR_ERROR);
2725 	}
2726 	if (find_options_sizes(params->options, &var_msg_info)) {
2727 		cleanup_variable_ap_id_info(&var_msg_info);
2728 		return (RDR_ERROR);
2729 	}
2730 	if (find_listopts_sizes(params->listopts, &var_msg_info)) {
2731 		cleanup_variable_ap_id_info(&var_msg_info);
2732 		return (RDR_ERROR);
2733 	}
2734 
2735 
2736 	/*
2737 	 * Collect size info specific to the list_ext request
2738 	 * message and allocate a buffer
2739 	 */
2740 	*buf_size = sizeof (rdr_list_ext_t);
2741 	*buf_size += var_msg_info.ap_id_int_size;
2742 	*buf_size += var_msg_info.ap_id_char_size;
2743 	*buf_size += var_msg_info.options_strlen;
2744 	*buf_size += var_msg_info.options_pad_sz;
2745 	*buf_size += var_msg_info.listopts_strlen;
2746 	*buf_size += var_msg_info.listopts_pad_sz;
2747 
2748 	*buf = (char *)malloc(*buf_size);
2749 	if (*buf == NULL) {
2750 		cleanup_variable_ap_id_info(&var_msg_info);
2751 		return (RDR_MEM_ALLOC);
2752 	}
2753 
2754 	/*
2755 	 * Set fixed address labels by name
2756 	 */
2757 	list_ext_data.num_ap_ids = params->num_ap_ids;
2758 	list_ext_data.ap_id_char_size = var_msg_info.ap_id_char_size;
2759 	list_ext_data.options_size = var_msg_info.options_strlen +
2760 	    var_msg_info.options_pad_sz;
2761 	list_ext_data.listopts_size = var_msg_info.listopts_strlen +
2762 	    var_msg_info.listopts_pad_sz;
2763 	if (params->errstring != NULL) {
2764 		list_ext_data.error_msg_ctl = RDR_GENERATE_ERR_MSGS;
2765 	} else {
2766 		list_ext_data.error_msg_ctl = RDR_DONT_GENERATE_ERR_MSGS;
2767 	}
2768 	if ((params->num_ap_ids != 0) || (params->ap_ids != NULL)) {
2769 		list_ext_data.list_msg_ctl = RDR_LIST_ONLY_PARAM_APS;
2770 	} else {
2771 		list_ext_data.list_msg_ctl = RDR_LIST_ALL_APS;
2772 	}
2773 	list_ext_data.flags = params->flags;
2774 	list_ext_data.permissions = params->permissions;
2775 
2776 	/*
2777 	 * Set variable information using memcpy
2778 	 */
2779 	bufptr = *buf;
2780 
2781 	(void) memcpy(bufptr, &list_ext_data, sizeof (rdr_list_ext_t));
2782 	bufptr += sizeof (rdr_list_ext_t);
2783 
2784 	if (var_msg_info.ap_id_sizes != NULL) {
2785 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
2786 		    var_msg_info.ap_id_int_size);
2787 		bufptr += var_msg_info.ap_id_int_size;
2788 	}
2789 
2790 	if (var_msg_info.ap_id_chars != NULL) {
2791 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
2792 		    var_msg_info.ap_id_char_size);
2793 		bufptr += var_msg_info.ap_id_char_size;
2794 	}
2795 
2796 	if (params->options != NULL) {
2797 		(void) memcpy(bufptr, params->options,
2798 		    var_msg_info.options_strlen);
2799 		bufptr += var_msg_info.options_strlen;
2800 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
2801 			bufptr[i] = 0;
2802 		}
2803 		bufptr += var_msg_info.options_pad_sz;
2804 	}
2805 
2806 	if (params->listopts != NULL) {
2807 		(void) memcpy(bufptr, params->listopts,
2808 		    var_msg_info.listopts_strlen);
2809 		bufptr += var_msg_info.listopts_strlen;
2810 		for (i = 0; i < var_msg_info.listopts_pad_sz; i++) {
2811 			bufptr[i] = 0;
2812 		}
2813 		bufptr += var_msg_info.listopts_pad_sz;
2814 	}
2815 
2816 	cleanup_variable_ap_id_info(&var_msg_info);
2817 
2818 	return (RDR_OK);
2819 }
2820 
2821 
2822 /*
2823  * unpack_list_ext_request:
2824  *
2825  * Handle unpacking a list request message.
2826  */
2827 static int
2828 unpack_list_ext_request(list_ext_params_t *params, const char *buf)
2829 {
2830 	char				*bufptr;
2831 	rdr_variable_message_info_t 	var_msg_info;
2832 	rdr_list_ext_t			list_ext_data;
2833 
2834 
2835 	if ((params == NULL) || (buf == NULL)) {
2836 		return (RDR_ERROR);
2837 	}
2838 
2839 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2840 
2841 	bufptr = (char *)buf;
2842 	(void) memcpy(&list_ext_data, bufptr, sizeof (rdr_list_ext_t));
2843 	bufptr += sizeof (rdr_list_ext_t);
2844 
2845 	/*
2846 	 * handle getting the ap_ids
2847 	 */
2848 	var_msg_info.ap_id_char_size = list_ext_data.ap_id_char_size;
2849 	if (get_ap_ids_from_buf(&(params->ap_ids), list_ext_data.num_ap_ids,
2850 	    &var_msg_info, bufptr)) {
2851 		return (RDR_ERROR);
2852 	}
2853 	bufptr += var_msg_info.ap_id_int_size;
2854 	bufptr += var_msg_info.ap_id_char_size;
2855 
2856 	/*
2857 	 * handle getting the options
2858 	 */
2859 	if (get_string_from_buf(&(params->options),
2860 	    list_ext_data.options_size, bufptr)) {
2861 		return (RDR_ERROR);
2862 	}
2863 	bufptr += list_ext_data.options_size;
2864 
2865 	/*
2866 	 * handle getting the listopts
2867 	 */
2868 	if (get_string_from_buf(&(params->listopts),
2869 	    list_ext_data.listopts_size, bufptr)) {
2870 		return (RDR_ERROR);
2871 	}
2872 	bufptr += list_ext_data.listopts_size;
2873 
2874 	/*
2875 	 * Set fixed address labels by name
2876 	 */
2877 	params->num_ap_ids = list_ext_data.num_ap_ids;
2878 
2879 	params->ap_id_list = (rdr_list_t **)malloc(sizeof (rdr_list_t *));
2880 	if (params->ap_id_list == NULL) {
2881 		return (RDR_MEM_ALLOC);
2882 	}
2883 	*(params->ap_id_list) = NULL;
2884 
2885 	params->nlist = (int *)malloc(sizeof (int));
2886 	if (params->nlist == NULL) {
2887 		return (RDR_MEM_ALLOC);
2888 	}
2889 	if (list_ext_data.error_msg_ctl == RDR_GENERATE_ERR_MSGS) {
2890 		params->errstring = (char **)malloc(sizeof (char *));
2891 		if (params->errstring == NULL) {
2892 			return (RDR_MEM_ALLOC);
2893 		}
2894 		*(params->errstring) = NULL;
2895 	} else {	/* error_msg_ctl == RDR_DONT_GENERATE_ERR_MSGS */
2896 	    params->errstring = NULL;
2897 	}
2898 	params->flags = list_ext_data.flags;
2899 	params->permissions = list_ext_data.permissions;
2900 
2901 	return (RDR_OK);
2902 }
2903 
2904 
2905 /*
2906  * pack_list_ext_reply:
2907  *
2908  * Handle packing a list reply message.
2909  */
2910 static int
2911 pack_list_ext_reply(list_ext_params_t *params, char **buf, int *buf_size)
2912 {
2913 	int				i;
2914 	char				*bufptr;
2915 	rdr_list_ext_reply_t		list_ext_data;
2916 	rdr_variable_message_info_t 	var_msg_info;
2917 	int 				list_data_size;
2918 
2919 
2920 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
2921 
2922 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
2923 		return (RDR_ERROR);
2924 	}
2925 
2926 	/*
2927 	 * Set variable length fields (size info)
2928 	 */
2929 	if (find_errstring_sizes(params->errstring, &var_msg_info)) {
2930 		return (RDR_ERROR);
2931 	}
2932 
2933 	if (params->nlist == NULL) {
2934 		list_data_size = 0;
2935 	} else {
2936 		list_data_size = *(params->nlist) * sizeof (rdr_list_t);
2937 	}
2938 
2939 	/*
2940 	 * Collect size info specific to the list_ext reply
2941 	 * message and allocate a buffer
2942 	 */
2943 	*buf_size = sizeof (rdr_list_ext_reply_t);
2944 	*buf_size += list_data_size;
2945 	*buf_size += var_msg_info.errstring_strlen;
2946 	*buf_size += var_msg_info.errstring_pad_sz;
2947 
2948 	*buf = (char *)malloc(*buf_size);
2949 	if (*buf == NULL) {
2950 		return (RDR_MEM_ALLOC);
2951 	}
2952 
2953 	/*
2954 	 * Set fixed address labels by name
2955 	 */
2956 	list_ext_data.num_ap_ids = (params->nlist) ? *(params->nlist) : 0;
2957 	list_ext_data.errstring_size = var_msg_info.errstring_strlen +
2958 	    var_msg_info.errstring_pad_sz;
2959 
2960 	/*
2961 	 * Set variable information using memcpy
2962 	 */
2963 	bufptr = *buf;
2964 
2965 	(void) memcpy(bufptr, &list_ext_data, sizeof (rdr_list_ext_reply_t));
2966 	bufptr += sizeof (rdr_list_ext_reply_t);
2967 
2968 	if ((params->ap_id_list != NULL) && (*(params->ap_id_list) != NULL)) {
2969 		(void) memcpy(bufptr, *(params->ap_id_list), list_data_size);
2970 		bufptr += list_data_size;
2971 	} else if (list_data_size) {
2972 		/*
2973 		 * Something is out of sync. We were expecting
2974 		 * some data to copy, but instead we found a
2975 		 * NULL pointer.
2976 		 */
2977 		(void) free((void *)*buf);
2978 		*buf = NULL;
2979 		return (RDR_ERROR);
2980 	}
2981 
2982 	if ((params->errstring != NULL) && (*(params->errstring) != NULL)) {
2983 		(void) memcpy(bufptr, *(params->errstring),
2984 		    var_msg_info.errstring_strlen);
2985 		bufptr += var_msg_info.errstring_strlen;
2986 		for (i = 0; i < var_msg_info.errstring_pad_sz; i++) {
2987 			bufptr[i] = 0;
2988 		}
2989 		bufptr += var_msg_info.errstring_pad_sz;
2990 	}
2991 
2992 	return (RDR_OK);
2993 }
2994 
2995 
2996 /*
2997  * unpack_list_ext_reply:
2998  *
2999  * Handle unpacking a list reply message.
3000  */
3001 static int
3002 unpack_list_ext_reply(list_ext_params_t *params, const char *buf)
3003 {
3004 	int 			list_data_size;
3005 	char 			*bufptr;
3006 	rdr_list_ext_reply_t	list_ext_data;
3007 
3008 
3009 	if ((params == NULL) || (buf == NULL)) {
3010 		return (RDR_ERROR);
3011 	}
3012 
3013 	bufptr = (char *)buf;
3014 	(void) memcpy(&list_ext_data, bufptr, sizeof (rdr_list_ext_reply_t));
3015 	bufptr += sizeof (rdr_list_ext_reply_t);
3016 
3017 	/*
3018 	 * handle getting the ap_id rcfga_list_data_t's.
3019 	 */
3020 	if (list_ext_data.num_ap_ids > 0) {
3021 		params->nlist = (int *)malloc(sizeof (int));
3022 		if (params->nlist == NULL) {
3023 			return (RDR_MEM_ALLOC);
3024 		}
3025 		*(params->nlist) = list_ext_data.num_ap_ids;
3026 		params->ap_id_list = (rdr_list_t **)
3027 		    malloc(sizeof (rdr_list_t *));
3028 		if (params->ap_id_list == NULL) {
3029 			return (RDR_MEM_ALLOC);
3030 		}
3031 		*(params->ap_id_list) = (rdr_list_t *)
3032 		malloc(sizeof (rdr_list_t) * list_ext_data.num_ap_ids);
3033 		if (*(params->ap_id_list) == NULL) {
3034 			return (RDR_MEM_ALLOC);
3035 		}
3036 		list_data_size = list_ext_data.num_ap_ids * sizeof (rdr_list_t);
3037 		(void) memcpy(*(params->ap_id_list), bufptr, list_data_size);
3038 		bufptr += list_data_size;
3039 	}
3040 
3041 	/*
3042 	 * handle getting the errstring
3043 	 */
3044 	params->errstring = (char **)malloc(sizeof (char *));
3045 	if (params->errstring == NULL) {
3046 		return (RDR_MEM_ALLOC);
3047 	}
3048 	if (get_string_from_buf(params->errstring,
3049 			list_ext_data.errstring_size, bufptr)) {
3050 		return (RDR_ERROR);
3051 	}
3052 	bufptr += list_ext_data.errstring_size;
3053 
3054 	return (RDR_OK);
3055 }
3056 
3057 
3058 /*
3059  * pack_help_request:
3060  *
3061  * Handle packing a help request message.
3062  */
3063 static int
3064 pack_help_request(help_params_t *params, char **buf, int *buf_size)
3065 {
3066 	int				i;
3067 	char				*bufptr;
3068 	rdr_help_t			help_data;
3069 	rdr_variable_message_info_t	var_msg_info;
3070 
3071 
3072 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
3073 
3074 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3075 		return (RDR_ERROR);
3076 	}
3077 
3078 	/*
3079 	 * Set variable length fields and make a call to partially
3080 	 * pack it.
3081 	 */
3082 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
3083 		cleanup_variable_ap_id_info(&var_msg_info);
3084 		return (RDR_ERROR);
3085 	}
3086 	if (find_options_sizes(params->options, &var_msg_info)) {
3087 		cleanup_variable_ap_id_info(&var_msg_info);
3088 		return (RDR_ERROR);
3089 	}
3090 
3091 	/*
3092 	 * Collect size info specific to the help request message and
3093 	 * and allocate a buffer
3094 	 */
3095 	*buf_size = sizeof (rdr_help_t);
3096 	*buf_size += var_msg_info.ap_id_int_size;
3097 	*buf_size += var_msg_info.ap_id_char_size;
3098 	*buf_size += var_msg_info.options_strlen;
3099 	*buf_size += var_msg_info.options_pad_sz;
3100 
3101 	*buf = (char *)malloc(*buf_size);
3102 	if (*buf == NULL) {
3103 		cleanup_variable_ap_id_info(&var_msg_info);
3104 		return (RDR_MEM_ALLOC);
3105 	}
3106 
3107 	/*
3108 	 * Set fixed address labels by name
3109 	 */
3110 	help_data.num_ap_ids = params->num_ap_ids;
3111 	help_data.ap_id_char_size = var_msg_info.ap_id_char_size;
3112 	help_data.options_size = var_msg_info.options_strlen +
3113 	    var_msg_info.options_pad_sz;
3114 
3115 	if (params->msgp != NULL) {
3116 		help_data.msg_callback_id =
3117 		    (unsigned long)params->msgp->message_routine;
3118 		help_data.msg_appdata_ptr =
3119 		    (unsigned long)params->msgp->appdata_ptr;
3120 	} else {
3121 		help_data.msg_callback_id = 0;
3122 		help_data.msg_appdata_ptr = 0;
3123 	}
3124 
3125 	help_data.flags = params->flags;
3126 
3127 	/*
3128 	 * Set variable information using memcpy
3129 	 */
3130 	bufptr = *buf;
3131 
3132 	(void) memcpy(bufptr, &help_data, sizeof (rdr_help_t));
3133 	bufptr += sizeof (rdr_help_t);
3134 
3135 	if (var_msg_info.ap_id_sizes != NULL) {
3136 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
3137 		    var_msg_info.ap_id_int_size);
3138 		bufptr += var_msg_info.ap_id_int_size;
3139 	}
3140 
3141 	if (var_msg_info.ap_id_chars != NULL) {
3142 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
3143 		    var_msg_info.ap_id_char_size);
3144 		bufptr += var_msg_info.ap_id_char_size;
3145 	}
3146 
3147 	if (params->options != NULL) {
3148 		(void) memcpy(bufptr, params->options,
3149 		    var_msg_info.options_strlen);
3150 		bufptr += var_msg_info.options_strlen;
3151 		for (i = 0; i < var_msg_info.options_pad_sz; i++) {
3152 			bufptr[i] = 0;
3153 		}
3154 		bufptr += var_msg_info.options_pad_sz;
3155 	}
3156 
3157 	cleanup_variable_ap_id_info(&var_msg_info);
3158 
3159 	return (RDR_OK);
3160 }
3161 
3162 
3163 /*
3164  * unpack_help_request:
3165  *
3166  * Handle unpacking a help request message.
3167  */
3168 static int
3169 unpack_help_request(help_params_t *params, const char *buf)
3170 {
3171 	char				*bufptr;
3172 	rdr_variable_message_info_t 	var_msg_info;
3173 	rdr_help_t			help_data;
3174 
3175 
3176 	if ((params == NULL) || (buf == NULL)) {
3177 		return (RDR_ERROR);
3178 	}
3179 
3180 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
3181 
3182 	bufptr = (char *)buf;
3183 	(void) memcpy(&help_data, bufptr, sizeof (rdr_help_t));
3184 	bufptr += sizeof (rdr_help_t);
3185 
3186 	/*
3187 	 * handle getting the ap_ids
3188 	 */
3189 	var_msg_info.ap_id_char_size = help_data.ap_id_char_size;
3190 	if (get_ap_ids_from_buf((char ***)&(params->ap_ids),
3191 	    help_data.num_ap_ids, &var_msg_info, bufptr)) {
3192 		return (RDR_ERROR);
3193 	}
3194 	bufptr += var_msg_info.ap_id_int_size;
3195 	bufptr += var_msg_info.ap_id_char_size;
3196 
3197 	/*
3198 	 * handle getting the options
3199 	 */
3200 	if (get_string_from_buf(&(params->options),
3201 	    help_data.options_size, bufptr)) {
3202 		return (RDR_ERROR);
3203 	}
3204 	bufptr += help_data.options_size;
3205 
3206 	/*
3207 	 * Set fixed address labels by name
3208 	 */
3209 	params->num_ap_ids = help_data.num_ap_ids;
3210 
3211 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
3212 	if (params->msgp == NULL) {
3213 		return (RDR_MEM_ALLOC);
3214 	}
3215 
3216 	/* set params->msgp->message_routine using memcpy */
3217 	(void) memcpy((void*)params->msgp, &(help_data.msg_callback_id),
3218 	    sizeof (unsigned long));
3219 
3220 	params->msgp->appdata_ptr = (void*)help_data.msg_appdata_ptr;
3221 	params->flags = help_data.flags;
3222 
3223 	return (RDR_OK);
3224 }
3225 
3226 
3227 /*
3228  * pack_ap_id_cmp_request:
3229  *
3230  * Handle packing an attachment point comparison request message.
3231  */
3232 static int
3233 pack_ap_id_cmp_request(ap_id_cmp_params_t *params, char **buf, int *buf_size)
3234 {
3235 	int			i;
3236 	char			*bufptr;
3237 	rdr_ap_id_cmp_t		ap_id_cmp_data;
3238 	int			ap_id1_strlen;
3239 	int			ap_id1_pad_sz;
3240 	int			ap_id2_strlen;
3241 	int			ap_id2_pad_sz;
3242 
3243 
3244 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3245 		return (RDR_ERROR);
3246 	}
3247 
3248 	/*
3249 	 * Set variable length fields and make a call to partially
3250 	 * pack it.
3251 	 */
3252 	if (params->ap_log_id1 != NULL) {
3253 		ap_id1_strlen = strlen(params->ap_log_id1) + 1;
3254 		ap_id1_pad_sz = RDR_ALIGN_64_BIT -
3255 		    (ap_id1_strlen % RDR_ALIGN_64_BIT);
3256 	} else {
3257 		ap_id1_strlen = 0;
3258 		ap_id1_pad_sz = 0;
3259 	}
3260 
3261 	if (params->ap_log_id2 != NULL) {
3262 		ap_id2_strlen = strlen(params->ap_log_id2) + 1;
3263 		ap_id2_pad_sz = RDR_ALIGN_64_BIT -
3264 		    (ap_id2_strlen % RDR_ALIGN_64_BIT);
3265 	} else {
3266 		ap_id2_strlen = 0;
3267 		ap_id2_pad_sz = 0;
3268 	}
3269 
3270 	/*
3271 	 * Collect size info specific to the ap id compare request
3272 	 * message and allocate a buffer
3273 	 */
3274 	*buf_size = sizeof (rdr_ap_id_cmp_t);
3275 	*buf_size += ap_id1_strlen;
3276 	*buf_size += ap_id1_pad_sz;
3277 	*buf_size += ap_id2_strlen;
3278 	*buf_size += ap_id2_pad_sz;
3279 
3280 	*buf = (char *)malloc(*buf_size);
3281 	if (*buf == NULL) {
3282 		return (RDR_MEM_ALLOC);
3283 	}
3284 
3285 	/*
3286 	 * Set fixed address labels by name
3287 	 */
3288 	ap_id_cmp_data.ap_id1_size = ap_id1_strlen + ap_id1_pad_sz;
3289 	ap_id_cmp_data.ap_id2_size = ap_id2_strlen + ap_id2_pad_sz;
3290 
3291 
3292 	/*
3293 	 * Set variable information using memcpy
3294 	 */
3295 	bufptr = *buf;
3296 
3297 	(void) memcpy(bufptr, &ap_id_cmp_data, sizeof (rdr_ap_id_cmp_t));
3298 	bufptr += sizeof (rdr_ap_id_cmp_t);
3299 
3300 	if (params->ap_log_id1 != NULL) {
3301 		(void) memcpy(bufptr, params->ap_log_id1, ap_id1_strlen);
3302 		bufptr += ap_id1_strlen;
3303 		for (i = 0; i < ap_id1_pad_sz; i++) {
3304 			bufptr[i] = 0;
3305 		}
3306 		bufptr += ap_id1_pad_sz;
3307 	}
3308 
3309 	if (params->ap_log_id2 != NULL) {
3310 		(void) memcpy(bufptr, params->ap_log_id2, ap_id2_strlen);
3311 		bufptr += ap_id2_strlen;
3312 		for (i = 0; i < ap_id2_pad_sz; i++) {
3313 			bufptr[i] = 0;
3314 		}
3315 		bufptr += ap_id2_pad_sz;
3316 	}
3317 
3318 	return (RDR_OK);
3319 }
3320 
3321 
3322 /*
3323  * unpack_ap_id_cmp_request:
3324  *
3325  * Handle unpacking an attachment point comparison request message.
3326  */
3327 static int
3328 unpack_ap_id_cmp_request(ap_id_cmp_params_t *params, const char *buf)
3329 {
3330 	char			*bufptr;
3331 	rdr_ap_id_cmp_t		ap_id_cmp_data;
3332 
3333 
3334 	if ((params == NULL) || (buf == NULL)) {
3335 		return (RDR_ERROR);
3336 	}
3337 
3338 	bufptr = (char *)buf;
3339 	(void) memcpy(&ap_id_cmp_data, bufptr, sizeof (rdr_ap_id_cmp_t));
3340 	bufptr += sizeof (rdr_ap_id_cmp_t);
3341 
3342 	/*
3343 	 * handle getting the cmp ap ids
3344 	 */
3345 	if (get_string_from_buf(&(params->ap_log_id1),
3346 	    ap_id_cmp_data.ap_id1_size, bufptr)) {
3347 		return (RDR_ERROR);
3348 	}
3349 	bufptr += ap_id_cmp_data.ap_id1_size;
3350 
3351 	if (get_string_from_buf(&(params->ap_log_id2),
3352 	    ap_id_cmp_data.ap_id2_size, bufptr)) {
3353 		return (RDR_ERROR);
3354 	}
3355 	bufptr += ap_id_cmp_data.ap_id2_size;
3356 
3357 	return (RDR_OK);
3358 }
3359 
3360 
3361 /*
3362  * pack_abort_cmd_request:
3363  *
3364  * Handle packing an abort request message.
3365  */
3366 static int
3367 pack_abort_cmd_request(abort_cmd_params_t *params, char **buf, int *buf_size)
3368 {
3369 	rdr_abort_cmd_t		abort_cmd_data;
3370 
3371 
3372 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3373 		return (RDR_ERROR);
3374 	}
3375 
3376 	/*
3377 	 * Collect size info specific to the abort cmd request
3378 	 * message and allocate a buffer
3379 	 */
3380 	*buf_size = sizeof (rdr_abort_cmd_t);
3381 
3382 	*buf = (char *)malloc(*buf_size);
3383 	if (*buf == NULL) {
3384 		return (RDR_MEM_ALLOC);
3385 	}
3386 
3387 	/*
3388 	 * Set fixed session identifier
3389 	 */
3390 	abort_cmd_data.session_id = params->session_id;
3391 
3392 	/*
3393 	 * Copy information using memcpy
3394 	 */
3395 	(void) memcpy(*buf, &abort_cmd_data, sizeof (rdr_abort_cmd_t));
3396 
3397 	return (RDR_OK);
3398 }
3399 
3400 
3401 /*
3402  * unpack_abort_cmd_request:
3403  *
3404  * Handle unpacking an abort request message.
3405  */
3406 static int
3407 unpack_abort_cmd_request(abort_cmd_params_t *params, const char *buf)
3408 {
3409 	rdr_abort_cmd_t		*abort_cmd_datap;
3410 
3411 
3412 	if ((params == NULL) || (buf == NULL)) {
3413 		return (RDR_ERROR);
3414 	}
3415 
3416 	/* LINTED Pointer Cast Alignment Warning */
3417 	abort_cmd_datap = (rdr_abort_cmd_t *)buf;
3418 
3419 	/*
3420 	 * copy out the session information
3421 	 */
3422 
3423 	params->session_id = abort_cmd_datap->session_id;
3424 
3425 	return (RDR_OK);
3426 }
3427 
3428 
3429 /*
3430  * pack_confirm_request:
3431  *
3432  * Handle packing a confirm callback request.
3433  */
3434 static int
3435 pack_confirm_request(confirm_callback_params_t *params, char **buf,
3436     int *buf_size)
3437 {
3438 	int				i;
3439 	char				*bufptr;
3440 	rdr_confirm_callback_t		confirm_callback_data;
3441 	int 				message_strlen;
3442 	int 				message_pad_sz;
3443 
3444 
3445 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3446 		return (RDR_ERROR);
3447 	}
3448 
3449 	/*
3450 	 * Set variable length fields and make a call to partially
3451 	 * pack it.
3452 	 */
3453 	if (params->message != NULL) {
3454 		message_strlen = strlen(params->message) + 1;
3455 		message_pad_sz = RDR_ALIGN_64_BIT -
3456 		    (message_strlen % RDR_ALIGN_64_BIT);
3457 	} else {
3458 		message_strlen = 0;
3459 		message_pad_sz = 0;
3460 	}
3461 
3462 
3463 	/*
3464 	 * Collect size info specific to the confirm callback request
3465 	 * message and allocate a buffer
3466 	 */
3467 	*buf_size = sizeof (rdr_confirm_callback_t);
3468 	*buf_size += message_strlen;
3469 	*buf_size += message_pad_sz;
3470 
3471 	*buf = (char *)malloc(*buf_size);
3472 	if (*buf == NULL) {
3473 		return (RDR_MEM_ALLOC);
3474 	}
3475 
3476 	/*
3477 	 * Set fixed address labels by name
3478 	 */
3479 	if (params->confp != NULL) {
3480 		confirm_callback_data.confirm_callback_id =
3481 		    (unsigned long)params->confp->confirm;
3482 		confirm_callback_data.appdata_ptr =
3483 		    (unsigned long)params->confp->appdata_ptr;
3484 	} else {
3485 		confirm_callback_data.confirm_callback_id = 0;
3486 		confirm_callback_data.appdata_ptr = 0;
3487 	}
3488 	confirm_callback_data.message_size = message_strlen + message_pad_sz;
3489 
3490 	/*
3491 	 * Set variable information using memcpy
3492 	 */
3493 	bufptr = *buf;
3494 	(void) memcpy(bufptr, &confirm_callback_data,
3495 	    sizeof (rdr_confirm_callback_t));
3496 	bufptr += sizeof (rdr_confirm_callback_t);
3497 
3498 	if (params->message != NULL) {
3499 		(void) memcpy(bufptr, params->message, message_strlen);
3500 		bufptr += message_strlen;
3501 		for (i = 0; i < message_pad_sz; i++) {
3502 			bufptr[i] = 0;
3503 		}
3504 		bufptr += message_pad_sz;
3505 	}
3506 
3507 	return (RDR_OK);
3508 }
3509 
3510 
3511 /*
3512  * unpack_confirm_request:
3513  *
3514  * Handle unpacking a confirm callback request.
3515  */
3516 static int
3517 unpack_confirm_request(confirm_callback_params_t *params, const char *buf)
3518 {
3519 	char				*bufptr;
3520 	rdr_confirm_callback_t		confirm_callback_data;
3521 
3522 
3523 	if ((params == NULL) || (buf == NULL)) {
3524 		return (RDR_ERROR);
3525 	}
3526 
3527 	bufptr = (char *)buf;
3528 	(void) memcpy(&confirm_callback_data, bufptr,
3529 	    sizeof (rdr_confirm_callback_t));
3530 	bufptr += sizeof (rdr_confirm_callback_t);
3531 
3532 	/*
3533 	 * handle getting the message text
3534 	 */
3535 	if (get_string_from_buf(&(params->message),
3536 	    confirm_callback_data.message_size, bufptr)) {
3537 		return (RDR_ERROR);
3538 	}
3539 	bufptr += confirm_callback_data.message_size;
3540 
3541 	/*
3542 	 * Set fixed address labels by name
3543 	 */
3544 	params->confp = (struct cfga_confirm *)
3545 	    malloc(sizeof (struct cfga_confirm));
3546 	if (params->confp == NULL) {
3547 		return (RDR_MEM_ALLOC);
3548 	}
3549 
3550 	/* set params->confp->confirm using memcpy */
3551 	(void) memcpy((void*)params->confp,
3552 	    &(confirm_callback_data.confirm_callback_id),
3553 	    sizeof (unsigned long));
3554 
3555 	params->confp->appdata_ptr =
3556 	    (void*)confirm_callback_data.appdata_ptr;
3557 
3558 	return (RDR_OK);
3559 }
3560 
3561 
3562 /*
3563  * pack_confirm_reply:
3564  *
3565  * Handle packing a confirm callback reply.
3566  */
3567 static int
3568 pack_confirm_reply(confirm_callback_params_t *params, char **buf, int *buf_size)
3569 {
3570 	char				*bufptr;
3571 	rdr_confirm_callback_reply_t	confirm_callback_data;
3572 
3573 
3574 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3575 		return (RDR_ERROR);
3576 	}
3577 
3578 	/*
3579 	 * Collect size info specific to the confirm callback reply
3580 	 * message and allocate a buffer
3581 	 */
3582 	*buf_size = sizeof (confirm_callback_params_t);
3583 	*buf = (char *)malloc(*buf_size);
3584 	if (*buf == NULL) {
3585 		return (RDR_MEM_ALLOC);
3586 	}
3587 
3588 	/*
3589 	 * Set fixed address labels by name
3590 	 */
3591 	if (params->confp != NULL) {
3592 		confirm_callback_data.confirm_callback_id =
3593 		    (unsigned long)params->confp->confirm;
3594 		confirm_callback_data.appdata_ptr =
3595 		    (unsigned long)params->confp->appdata_ptr;
3596 	} else {
3597 		confirm_callback_data.confirm_callback_id = 0;
3598 		confirm_callback_data.appdata_ptr = 0;
3599 	}
3600 	confirm_callback_data.response = params->response;
3601 
3602 	/*
3603 	 * Set variable information using memcpy
3604 	 */
3605 	bufptr = *buf;
3606 
3607 	(void) memcpy(bufptr, &confirm_callback_data,
3608 	    sizeof (rdr_confirm_callback_reply_t));
3609 
3610 	return (RDR_OK);
3611 }
3612 
3613 
3614 /*
3615  * unpack_confirm_reply:
3616  *
3617  * Handle unpacking a confirm callback reply.
3618  */
3619 static int
3620 unpack_confirm_reply(confirm_callback_params_t *params, const char *buf)
3621 {
3622 	char				*bufptr;
3623 	rdr_confirm_callback_reply_t	confirm_callback_data;
3624 
3625 	if ((params == NULL) || (buf == NULL)) {
3626 		return (RDR_ERROR);
3627 	}
3628 
3629 	bufptr = (char *)buf;
3630 	(void) memcpy(&confirm_callback_data, bufptr,
3631 	    sizeof (rdr_confirm_callback_reply_t));
3632 	bufptr += sizeof (confirm_callback_params_t);
3633 
3634 	/*
3635 	 * Set fixed address labels by name
3636 	 */
3637 	params->confp = (struct cfga_confirm *)
3638 	    malloc(sizeof (struct cfga_confirm));
3639 	if (params->confp == NULL) {
3640 		return (RDR_MEM_ALLOC);
3641 	}
3642 
3643 	/* set params->confp->confirm using memcpy */
3644 	(void) memcpy((void*)params->confp,
3645 	    &(confirm_callback_data.confirm_callback_id),
3646 	    sizeof (unsigned long));
3647 
3648 	params->confp->appdata_ptr =
3649 	    (void*)confirm_callback_data.appdata_ptr;
3650 	params->response = confirm_callback_data.response;
3651 
3652 	return (RDR_OK);
3653 }
3654 
3655 
3656 /*
3657  * pack_message_request:
3658  *
3659  * Handle packing a message callback request.
3660  */
3661 static int
3662 pack_message_request(msg_callback_params_t *params, char **buf, int *buf_size)
3663 {
3664 	int			i;
3665 	char			*bufptr;
3666 	rdr_msg_callback_t	msg_callback_data;
3667 	int			message_strlen;
3668 	int			message_pad_sz;
3669 
3670 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3671 		return (RDR_ERROR);
3672 	}
3673 
3674 	/*
3675 	 * Set variable length fields and make a call to partially
3676 	 * pack it.
3677 	 */
3678 	if (params->message != NULL) {
3679 		message_strlen = strlen(params->message) + 1;
3680 		message_pad_sz = RDR_ALIGN_64_BIT -
3681 		    (message_strlen % RDR_ALIGN_64_BIT);
3682 	} else {
3683 		message_strlen = 0;
3684 		message_pad_sz = 0;
3685 	}
3686 
3687 
3688 	/*
3689 	 * Collect size info specific to the message callback request
3690 	 * message and allocate a buffer
3691 	 */
3692 	*buf_size = sizeof (rdr_msg_callback_t);
3693 	*buf_size += message_strlen;
3694 	*buf_size += message_pad_sz;
3695 
3696 	*buf = (char *)malloc(*buf_size);
3697 	if (*buf == NULL) {
3698 		return (RDR_MEM_ALLOC);
3699 	}
3700 
3701 	/*
3702 	 * Set fixed address labels by name
3703 	 */
3704 	if (params->msgp != NULL) {
3705 		msg_callback_data.msg_callback_id =
3706 		    (unsigned long)params->msgp->message_routine;
3707 		msg_callback_data.appdata_ptr =
3708 		    (unsigned long)params->msgp->appdata_ptr;
3709 	} else {
3710 		msg_callback_data.msg_callback_id = 0;
3711 		msg_callback_data.appdata_ptr = 0;
3712 	}
3713 	msg_callback_data.message_size = message_strlen + message_pad_sz;
3714 
3715 	/*
3716 	 * Set variable information using memcpy
3717 	 */
3718 	bufptr = *buf;
3719 
3720 	(void) memcpy(bufptr, &msg_callback_data, sizeof (rdr_msg_callback_t));
3721 	bufptr += sizeof (rdr_msg_callback_t);
3722 
3723 	if (params->message != NULL) {
3724 		(void) memcpy(bufptr, params->message, message_strlen);
3725 		bufptr += message_strlen;
3726 		for (i = 0; i < message_pad_sz; i++) {
3727 			bufptr[i] = 0;
3728 		}
3729 		bufptr += message_pad_sz;
3730 	}
3731 
3732 	return (RDR_OK);
3733 }
3734 
3735 
3736 /*
3737  * unpack_message_request:
3738  *
3739  * Handle unpacking a message callback request.
3740  */
3741 static int
3742 unpack_message_request(msg_callback_params_t *params, const char *buf)
3743 {
3744 	char			*bufptr;
3745 	rdr_msg_callback_t	msg_callback_data;
3746 
3747 	if ((params == NULL) || (buf == NULL)) {
3748 		return (RDR_ERROR);
3749 	}
3750 
3751 	bufptr = (char *)buf;
3752 	(void) memcpy(&msg_callback_data, bufptr, sizeof (rdr_msg_callback_t));
3753 	bufptr += sizeof (rdr_msg_callback_t);
3754 
3755 	/*
3756 	 * handle getting the message text
3757 	 */
3758 	if (get_string_from_buf(&(params->message),
3759 	    msg_callback_data.message_size, bufptr)) {
3760 		return (RDR_ERROR);
3761 	}
3762 	bufptr += msg_callback_data.message_size;
3763 
3764 	/*
3765 	 * Set fixed address labels by name
3766 	 */
3767 	params->msgp = (struct cfga_msg *)malloc(sizeof (struct cfga_msg));
3768 	if (params->msgp == NULL) {
3769 		return (RDR_MEM_ALLOC);
3770 	}
3771 
3772 	/* set params->msgp->message_routine using memcpy */
3773 	(void) memcpy((void*)params->msgp, &(msg_callback_data.msg_callback_id),
3774 	    sizeof (unsigned long));
3775 
3776 	params->msgp->appdata_ptr = (void*)msg_callback_data.appdata_ptr;
3777 
3778 	return (RDR_OK);
3779 }
3780 
3781 /*
3782  * pack_rsrc_info_request:
3783  *
3784  * Handle packing a resource info request.
3785  */
3786 static int
3787 pack_rsrc_info_request(rsrc_info_params_t *params, char **buf, int *buf_size)
3788 {
3789 	char				*bufptr;
3790 	rdr_rsrc_info_t			rsrc_info_data;
3791 	rdr_variable_message_info_t 	var_msg_info;
3792 
3793 
3794 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3795 		return (RDR_ERROR);
3796 	}
3797 
3798 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
3799 
3800 	/*
3801 	 * Set variable length fields and make a call to partially
3802 	 * pack it.
3803 	 */
3804 	if (pack_ap_ids(params->num_ap_ids, params->ap_ids, &var_msg_info)) {
3805 		cleanup_variable_ap_id_info(&var_msg_info);
3806 		return (RDR_ERROR);
3807 	}
3808 
3809 	/*
3810 	 * Collect size info specific to the resource info request
3811 	 * message and allocate a buffer.
3812 	 */
3813 	*buf_size = sizeof (rdr_rsrc_info_t);
3814 	*buf_size += var_msg_info.ap_id_int_size;
3815 	*buf_size += var_msg_info.ap_id_char_size;
3816 
3817 	*buf = (char *)malloc(*buf_size);
3818 	if (*buf == NULL) {
3819 		return (RDR_MEM_ALLOC);
3820 	}
3821 
3822 	/*
3823 	 * Set fixed address labels by name.
3824 	 */
3825 	rsrc_info_data.num_ap_ids = params->num_ap_ids;
3826 	rsrc_info_data.ap_id_char_size = var_msg_info.ap_id_char_size;
3827 	rsrc_info_data.flags = params->flags;
3828 
3829 	/*
3830 	 * Set variable information using memcpy.
3831 	 */
3832 	bufptr = *buf;
3833 
3834 	(void) memcpy(bufptr, &rsrc_info_data, sizeof (rdr_rsrc_info_t));
3835 	bufptr += sizeof (rdr_rsrc_info_t);
3836 
3837 	if (var_msg_info.ap_id_sizes != NULL) {
3838 		(void) memcpy(bufptr, var_msg_info.ap_id_sizes,
3839 		    var_msg_info.ap_id_int_size);
3840 		bufptr += var_msg_info.ap_id_int_size;
3841 	}
3842 
3843 	if (var_msg_info.ap_id_chars != NULL) {
3844 		(void) memcpy(bufptr, var_msg_info.ap_id_chars,
3845 		    var_msg_info.ap_id_char_size);
3846 		bufptr += var_msg_info.ap_id_char_size;
3847 	}
3848 
3849 	cleanup_variable_ap_id_info(&var_msg_info);
3850 
3851 	return (RDR_OK);
3852 }
3853 
3854 
3855 /*
3856  * unpack_rsrc_info_request:
3857  *
3858  * Handle unpacking a resource info request message.
3859  */
3860 static int
3861 unpack_rsrc_info_request(rsrc_info_params_t *params, const char *buf)
3862 {
3863 	char				*bufptr;
3864 	rdr_variable_message_info_t 	var_msg_info;
3865 	rdr_rsrc_info_t			rsrc_info_data;
3866 
3867 
3868 	if ((params == NULL) || (buf == NULL)) {
3869 		return (RDR_ERROR);
3870 	}
3871 
3872 	(void) memset(&var_msg_info, 0, sizeof (rdr_variable_message_info_t));
3873 
3874 	bufptr = (char *)buf;
3875 	(void) memcpy(&rsrc_info_data, bufptr, sizeof (rdr_rsrc_info_t));
3876 	bufptr += sizeof (rdr_rsrc_info_t);
3877 
3878 	/*
3879 	 * Handle getting the ap_ids.
3880 	 */
3881 	var_msg_info.ap_id_char_size = rsrc_info_data.ap_id_char_size;
3882 	if (get_ap_ids_from_buf(&(params->ap_ids), rsrc_info_data.num_ap_ids,
3883 	    &var_msg_info, bufptr)) {
3884 		return (RDR_ERROR);
3885 	}
3886 	bufptr += var_msg_info.ap_id_int_size;
3887 	bufptr += var_msg_info.ap_id_char_size;
3888 
3889 	/*
3890 	 * Set fixed address labels by name.
3891 	 */
3892 	params->num_ap_ids = rsrc_info_data.num_ap_ids;
3893 	params->flags = rsrc_info_data.flags;
3894 
3895 	return (RDR_OK);
3896 }
3897 
3898 
3899 /*
3900  * pack_rsrc_info_reply:
3901  *
3902  * Handle packing a resource info reply message.
3903  */
3904 static int
3905 pack_rsrc_info_reply(rsrc_info_params_t *params, char **buf, int *buf_size)
3906 {
3907 	char				*bufptr;
3908 	rdr_rsrc_info_reply_t		rsrc_info_data;
3909 	int				pack_status;
3910 	caddr_t				rsrc_info_bufp = NULL;
3911 	size_t 				rsrc_info_size;
3912 
3913 
3914 	if ((params == NULL) || (buf == NULL) || (buf_size == NULL)) {
3915 		return (RDR_ERROR);
3916 	}
3917 
3918 	/*
3919 	 * Pack snapshot handle data.
3920 	 */
3921 	pack_status = ri_pack(params->hdl, &rsrc_info_bufp, &rsrc_info_size);
3922 	if (pack_status != 0) {
3923 		return (RDR_ERROR);
3924 	}
3925 
3926 	/*
3927 	 * Collect size info specific to the rsrc_info reply message
3928 	 * and allocate a buffer.
3929 	 */
3930 	*buf_size = sizeof (rdr_rsrc_info_reply_t);
3931 	*buf_size += rsrc_info_size;
3932 
3933 	*buf = (char *)malloc(*buf_size);
3934 	if (*buf == NULL) {
3935 		free(rsrc_info_bufp);
3936 		return (RDR_MEM_ALLOC);
3937 	}
3938 
3939 	/*
3940 	 * Set fixed address labels by name.
3941 	 */
3942 	rsrc_info_data.packed_hdl_size = rsrc_info_size;
3943 
3944 	/*
3945 	 * Set variable information using memcpy.
3946 	 */
3947 	bufptr = *buf;
3948 
3949 	(void) memcpy(bufptr, &rsrc_info_data, sizeof (rdr_rsrc_info_reply_t));
3950 	bufptr += sizeof (rdr_rsrc_info_reply_t);
3951 
3952 	if (rsrc_info_bufp) {
3953 		(void) memcpy(bufptr, rsrc_info_bufp, rsrc_info_size);
3954 		free(rsrc_info_bufp);
3955 	}
3956 
3957 	return (RDR_OK);
3958 }
3959 
3960 
3961 /*
3962  * unpack_rsrc_info_reply:
3963  *
3964  * Handle unpacking a resource info reply message.
3965  */
3966 static int
3967 unpack_rsrc_info_reply(rsrc_info_params_t *params, const char *buf)
3968 {
3969 	int			unpack_status;
3970 	char 			*bufptr;
3971 	rdr_rsrc_info_reply_t	rsrc_info_data;
3972 
3973 
3974 	if ((params == NULL) || (buf == NULL)) {
3975 		return (RDR_ERROR);
3976 	}
3977 
3978 	bufptr = (char *)buf;
3979 	(void) memcpy(&rsrc_info_data, bufptr, sizeof (rdr_rsrc_info_reply_t));
3980 	bufptr += sizeof (rdr_rsrc_info_reply_t);
3981 
3982 	/*
3983 	 * Unpack buf into resource info handle.
3984 	 */
3985 	unpack_status = ri_unpack(bufptr, rsrc_info_data.packed_hdl_size,
3986 	    &params->hdl);
3987 
3988 	return ((unpack_status == 0) ? RDR_OK : RDR_ERROR);
3989 }
3990 
3991 
3992 /*
3993  * pack_ap_ids:
3994  *
3995  * Pack a list of attachment point identifiers into a single buffer.
3996  * This buffer is stored in the specified rdr_variable_message_info_t
3997  * and is padded to be 64-bit aligned.
3998  */
3999 static int
4000 pack_ap_ids(int num_ap_ids, char *const *ap_ids,
4001     rdr_variable_message_info_t *var_msg_info)
4002 {
4003 	int	i;
4004 	int	ap_id_pad_sz;
4005 	char	*bufptr;
4006 
4007 
4008 	if (var_msg_info == NULL) {
4009 		return (RDR_ERROR);
4010 	}
4011 
4012 	/*
4013 	 * NULL is a valid value for ap_ids in the list_ext
4014 	 * case. For list_ext, no specified attachment points
4015 	 * indicates that _all_ attachment points should be
4016 	 * displayed. However, if ap_ids is NULL, num_ap_ids
4017 	 * should be 0.
4018 	 */
4019 	if ((ap_ids == NULL) && (num_ap_ids != 0)) {
4020 		num_ap_ids = 0;
4021 	}
4022 
4023 	var_msg_info->ap_id_int_size = sizeof (int) * num_ap_ids;
4024 	if (num_ap_ids > 0) {
4025 		var_msg_info->ap_id_sizes = (int *)malloc(sizeof (int) *
4026 		    var_msg_info->ap_id_int_size);
4027 		if (var_msg_info->ap_id_sizes == NULL) {
4028 			return (RDR_MEM_ALLOC);
4029 		}
4030 	}
4031 	for (i = 0; i < num_ap_ids; i++) {
4032 		if (ap_ids[i] != NULL) {
4033 			var_msg_info->ap_id_sizes[i] = strlen(ap_ids[i]) + 1;
4034 			var_msg_info->ap_id_char_size +=
4035 			    var_msg_info->ap_id_sizes[i];
4036 		}
4037 	}
4038 	if (var_msg_info->ap_id_char_size > 0) {
4039 		ap_id_pad_sz = RDR_ALIGN_64_BIT -
4040 		    (var_msg_info->ap_id_char_size % RDR_ALIGN_64_BIT);
4041 		var_msg_info->ap_id_char_size += ap_id_pad_sz;
4042 		var_msg_info->ap_id_chars = (char *)
4043 		    malloc(var_msg_info->ap_id_char_size);
4044 		if (var_msg_info->ap_id_chars == NULL) {
4045 			return (RDR_MEM_ALLOC);
4046 		}
4047 
4048 		bufptr = var_msg_info->ap_id_chars;
4049 		for (i = 0; i < num_ap_ids; i++) {
4050 			(void) memcpy(bufptr, ap_ids[i],
4051 			    var_msg_info->ap_id_sizes[i]);
4052 			bufptr += var_msg_info->ap_id_sizes[i];
4053 		}
4054 		for (i = 0; i < ap_id_pad_sz; i++) {
4055 			bufptr[i] = 0;
4056 		}
4057 	} else {
4058 		ap_id_pad_sz = 0;
4059 	}
4060 
4061 	return (RDR_OK);
4062 }
4063 
4064 
4065 /*
4066  * unpack_ap_ids:
4067  *
4068  * Unpack a buffer containing a concatenation of a list of
4069  * attachment point identifiers. The resulting list of strings
4070  * are stored in an array in the specified rdr_variable_message_info_t.
4071  */
4072 static int
4073 unpack_ap_ids(int num_ap_ids, char **ap_ids, const char *buf,
4074     rdr_variable_message_info_t *var_msg_info)
4075 {
4076 	int	i;
4077 	int	ap_id_size;
4078 	int	chars_copied;
4079 	char	*bufptr;
4080 
4081 
4082 	if ((ap_ids == NULL) || (buf == NULL) || (var_msg_info == NULL)) {
4083 		return (RDR_ERROR);
4084 	}
4085 	bufptr = (char *)buf;
4086 
4087 	var_msg_info->ap_id_int_size = sizeof (int) * num_ap_ids;
4088 	if (num_ap_ids > 0) {
4089 		var_msg_info->ap_id_sizes = (int *)
4090 		malloc(sizeof (int) * var_msg_info->ap_id_int_size);
4091 		if (var_msg_info->ap_id_sizes == NULL) {
4092 			return (RDR_MEM_ALLOC);
4093 		}
4094 		(void) memcpy(var_msg_info->ap_id_sizes, bufptr,
4095 		    var_msg_info->ap_id_int_size);
4096 	}
4097 	bufptr += var_msg_info->ap_id_int_size;
4098 
4099 	chars_copied = 0;
4100 	for (i = 0; i < num_ap_ids; i++) {
4101 		ap_id_size = var_msg_info->ap_id_sizes[i];
4102 		if (ap_id_size <= 0) {
4103 			continue;
4104 		}
4105 		if ((chars_copied + ap_id_size) >
4106 			var_msg_info->ap_id_char_size) {
4107 			return (RDR_ERROR);
4108 		}
4109 		ap_ids[i] = (char *)malloc(ap_id_size);
4110 		if (ap_ids[i] == NULL) {
4111 			return (RDR_MEM_ALLOC);
4112 		}
4113 		(void) memcpy(ap_ids[i], bufptr, ap_id_size);
4114 		bufptr += ap_id_size;
4115 		chars_copied += ap_id_size;
4116 	}
4117 	return (RDR_OK);
4118 }
4119 
4120 
4121 /*
4122  * find_options_sizes:
4123  *
4124  * Determine the size of a specified option string. The information
4125  * is stored in the specified rdr_variable_message_info_t.
4126  */
4127 static int
4128 find_options_sizes(char *options, rdr_variable_message_info_t *var_msg_info)
4129 {
4130 	if (var_msg_info == NULL) {
4131 		return (RDR_ERROR);
4132 	}
4133 	if (options != NULL) {
4134 		var_msg_info->options_strlen = strlen(options) + 1;
4135 		var_msg_info->options_pad_sz = RDR_ALIGN_64_BIT -
4136 		    (var_msg_info->options_strlen % RDR_ALIGN_64_BIT);
4137 	} else {
4138 		var_msg_info->options_strlen = 0;
4139 		var_msg_info->options_pad_sz = 0;
4140 	}
4141 	return (RDR_OK);
4142 }
4143 
4144 
4145 /*
4146  * find_listopts_sizes:
4147  *
4148  * Determine the size of a specified list option string. The information
4149  * is stored in the specified rdr_variable_message_info_t.
4150  */
4151 static int
4152 find_listopts_sizes(char *listopts, rdr_variable_message_info_t *var_msg_info)
4153 {
4154 	if (var_msg_info == NULL) {
4155 		return (RDR_ERROR);
4156 	}
4157 	if (listopts != NULL) {
4158 		var_msg_info->listopts_strlen = strlen(listopts) + 1;
4159 		var_msg_info->listopts_pad_sz = RDR_ALIGN_64_BIT -
4160 		    (var_msg_info->listopts_strlen % RDR_ALIGN_64_BIT);
4161 	} else {
4162 		var_msg_info->listopts_strlen = 0;
4163 		var_msg_info->listopts_pad_sz = 0;
4164 	}
4165 	return (RDR_OK);
4166 }
4167 
4168 
4169 /*
4170  * find_function_size:
4171  *
4172  * Determine the size of a specified private function string. The
4173  * information is stored in the specified rdr_variable_message_info_t.
4174  */
4175 static int
4176 find_function_sizes(char *function, rdr_variable_message_info_t *var_msg_info)
4177 {
4178 	if (var_msg_info == NULL) {
4179 		return (RDR_ERROR);
4180 	}
4181 	if (function != NULL) {
4182 		var_msg_info->function_strlen = strlen(function) + 1;
4183 		var_msg_info->function_pad_sz = RDR_ALIGN_64_BIT -
4184 		    (var_msg_info->function_strlen % RDR_ALIGN_64_BIT);
4185 	} else {
4186 		var_msg_info->function_strlen = 0;
4187 		var_msg_info->function_pad_sz = 0;
4188 	}
4189 	return (RDR_OK);
4190 }
4191 
4192 
4193 /*
4194  * find_errstring_sizes:
4195  *
4196  * Determine the size of a specified error string. The information
4197  * is stored in the specified rdr_variable_message_info_t.
4198  */
4199 static int
4200 find_errstring_sizes(char **errstring,
4201     rdr_variable_message_info_t *var_msg_info)
4202 {
4203 	if ((errstring != NULL) && (*errstring != NULL)) {
4204 		var_msg_info->errstring_strlen = strlen(*errstring) + 1;
4205 		var_msg_info->errstring_pad_sz = RDR_ALIGN_64_BIT -
4206 		    (var_msg_info->errstring_strlen % RDR_ALIGN_64_BIT);
4207 	} else {
4208 		var_msg_info->errstring_strlen = 0;
4209 		var_msg_info->errstring_pad_sz = 0;
4210 	}
4211 	return (RDR_OK);
4212 }
4213 
4214 
4215 /*
4216  * get_ap_ids_from_buf:
4217  *
4218  * Unpack a buffer containing a concatenation of a list of attachment
4219  * point identifiers. An appropriately sized buffer is allocated and
4220  * the resulting list of strings are stored in an array in the specified
4221  * rdr_variable_message_info_t.
4222  */
4223 static int
4224 get_ap_ids_from_buf(char ***ap_id_ptr, int num_ap_ids,
4225     rdr_variable_message_info_t *var_msg_info, const char *buf)
4226 {
4227 	if ((ap_id_ptr == NULL) || (buf == NULL) || (var_msg_info == NULL)) {
4228 		return (RDR_ERROR);
4229 	}
4230 	if (num_ap_ids > 0) {
4231 		*ap_id_ptr = (char **)malloc(sizeof (char *) * num_ap_ids);
4232 		if (*ap_id_ptr == NULL) {
4233 			return (RDR_MEM_ALLOC);
4234 		}
4235 		if (unpack_ap_ids(num_ap_ids, *ap_id_ptr, buf, var_msg_info)) {
4236 			cleanup_variable_ap_id_info(var_msg_info);
4237 			return (RDR_ERROR);
4238 		}
4239 
4240 	} else if (num_ap_ids < 0) {
4241 		return (RDR_ERROR);
4242 	}
4243 
4244 	cleanup_variable_ap_id_info(var_msg_info);
4245 
4246 	return (RDR_OK);
4247 }
4248 
4249 
4250 /*
4251  * get_string_from_buf:
4252  *
4253  * Copy a string to a new buffer. Memory is allocated for the
4254  * new buffer and the original string is copied to the new buffer.
4255  * This is primarily used when a string is located in a packed
4256  * buffer that will eventually get deallocated.
4257  */
4258 static int
4259 get_string_from_buf(char **stringptr, int strsize, const char *buf)
4260 {
4261 	if (buf == NULL) {
4262 		return (RDR_ERROR);
4263 	}
4264 
4265 	/*
4266 	 * A stringptr of NULL is a valid value. The errstring param
4267 	 * in an rconfig_xxx call is valid and is passed to this
4268 	 * function. For example, see errstring in the call to this
4269 	 * function in unpack_change_state_reply.
4270 	 */
4271 	if (stringptr != NULL) {
4272 		if (strsize > 0) {
4273 			*stringptr = (char *)malloc(strsize);
4274 			if (*stringptr == NULL) {
4275 				return (RDR_MEM_ALLOC);
4276 			}
4277 			(void) memcpy(*stringptr, buf, strsize);
4278 		} else if (strsize == 0) {
4279 			*stringptr = NULL;
4280 		} else if (strsize < 0) {
4281 			*stringptr = NULL;
4282 			return (RDR_ERROR);
4283 		}
4284 	}
4285 	return (RDR_OK);
4286 }
4287 
4288 
4289 /*
4290  * cleanup_ap_ids:
4291  *
4292  * Deallocate the specified array of attachment point identifiers.
4293  */
4294 static int
4295 cleanup_ap_ids(int num_ap_ids, char ** ap_ids)
4296 {
4297 	int	i;
4298 
4299 	if (ap_ids == NULL) {
4300 		return (RDR_ERROR);
4301 	}
4302 	for (i = 0; i < num_ap_ids; i++) {
4303 		if (ap_ids[i] != NULL) {
4304 			free((void *)ap_ids[i]);
4305 			ap_ids[i] = NULL;
4306 		}
4307 	}
4308 	return (RDR_OK);
4309 }
4310 
4311 
4312 /*
4313  * cleanup_errstring:
4314  *
4315  * Deallocate the specified error string.
4316  */
4317 static int
4318 cleanup_errstring(char **errstring)
4319 {
4320 	if (errstring) {
4321 		if (*errstring) {
4322 			free((void *)*errstring);
4323 		}
4324 		free((void *)errstring);
4325 		errstring = NULL;
4326 	}
4327 
4328 	return (RDR_OK);
4329 }
4330 
4331 
4332 /*
4333  * cleanup_variable_ap_id_info:
4334  *
4335  * Deallocate the ap_id information from the specified
4336  * rdr_variable_message_info_t.
4337  */
4338 static void
4339 cleanup_variable_ap_id_info(rdr_variable_message_info_t *var_msg_info)
4340 {
4341 	if (var_msg_info != NULL) {
4342 		if (var_msg_info->ap_id_sizes != NULL) {
4343 			free((void *)var_msg_info->ap_id_sizes);
4344 			var_msg_info->ap_id_sizes = NULL;
4345 		}
4346 		if (var_msg_info->ap_id_chars != NULL) {
4347 			free((void *)var_msg_info->ap_id_chars);
4348 			var_msg_info->ap_id_chars = NULL;
4349 		}
4350 	}
4351 }
4352