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