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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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