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