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