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