1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** 79** NAME 80** 81** comif.c 82** 83** FACILITY: 84** 85** Remote Procedure Call (RPC) 86** 87** ABSTRACT: 88** 89** Interface Service for the Common Communications Service. Contains 90** routines to register an interface, unregister an interface, perform lookups 91** of interface specifications within the Interface Registry Table, which is 92** contained within this module. 93** 94** 95*/ 96 97#include <commonp.h> /* Common internals for RPC runtime system */ 98#include <com.h> /* Externals for Common Services component */ 99#include <comp.h> /* Internals for Common Services component */ 100 101#include <dce/mgmt.h> 102 103/* 104 * the size of the interface registry hash table 105 * - pick a prime number to avoid collisions 106 */ 107#define RPC_C_IF_REGISTRY_SIZE 31 108 109/* 110 * The Interface Registry Table, where interface specifications 111 * are registered, and upon which the routines contained within 112 * this module perform their actions. Protected by "if_mutex". 113 */ 114INTERNAL rpc_list_t if_registry[RPC_C_IF_REGISTRY_SIZE] = { {0,0} }; 115INTERNAL rpc_mutex_t if_mutex; 116 117/* 118 * an if registry list entry 119 */ 120typedef struct 121{ 122 rpc_list_t link; 123 rpc_if_rep_p_t if_spec; 124 rpc_mgr_epv_t default_mepv; 125 unsigned copied_mepv: 1; /* 1 = mepv copied at registration time */ 126 unsigned internal: 1; /* 1 = internal if; don't wildcard unregstr */ 127 rpc_list_t type_info_list; 128 unsigned32 flags; 129 unsigned32 max_calls; 130 unsigned32 max_rpc_size; 131 rpc_if_callback_fn_t if_callback; 132} rpc_if_rgy_entry_t, *rpc_if_rgy_entry_p_t; 133 134/* 135 * an if type/info list entry 136 */ 137typedef struct 138{ 139 rpc_list_t link; 140 idl_uuid_t type; /* type of object to which entry applies */ 141 rpc_mgr_epv_t mepv; /* pointer to manager procedures */ 142 unsigned copied_mepv: 1; /* 1 = mepv copied at registration time */ 143} rpc_if_type_info_t, *rpc_if_type_info_p_t; 144 145INTERNAL void unregister_if_entry ( 146 rpc_if_rgy_entry_p_t /*if_entry*/, 147 uuid_p_t /*mgr_type_uuid*/, 148 unsigned32 * /*status*/ 149 ); 150 151/* 152**++ 153** 154** ROUTINE NAME: rpc__if_init 155** 156** SCOPE: PRIVATE - declared in com.h 157** 158** DESCRIPTION: 159** 160** Initializes this module. 161** 162** INPUTS: none 163** 164** INPUTS/OUTPUTS: none 165** 166** OUTPUTS: 167** 168** status The result of the operation. 169** 170** IMPLICIT INPUTS: none 171** 172** IMPLICIT OUTPUTS: none 173** 174** FUNCTION VALUE: void 175** 176** SIDE EFFECTS: none 177** 178**-- 179**/ 180 181PRIVATE void rpc__if_init 182( 183 unsigned32 * status 184) 185{ 186 RPC_MUTEX_INIT (if_mutex); 187 *status = rpc_s_ok; 188} 189 190/* 191**++ 192** 193** ROUTINE NAME: rpc__if_fork_handler 194** 195** SCOPE: PRIVATE - declared in com.h 196** 197** DESCRIPTION: 198** 199** Initializes this module. 200** 201** INPUTS: stage The stage of the fork we are 202** currently handling. 203** 204** INPUTS/OUTPUTS: none 205** 206** OUTPUTS: none 207** 208** IMPLICIT INPUTS: none 209** 210** IMPLICIT OUTPUTS: none 211** 212** FUNCTION VALUE: void 213** 214** SIDE EFFECTS: none 215** 216**-- 217**/ 218 219PRIVATE void rpc__if_fork_handler 220( 221 rpc_fork_stage_id_t stage 222) 223{ 224 unsigned32 i; 225 226 switch ((int)stage) 227 { 228 case RPC_C_PREFORK: 229 break; 230 case RPC_C_POSTFORK_PARENT: 231 break; 232 case RPC_C_POSTFORK_CHILD: 233 /* 234 * Empty the Interface Registry Table 235 */ 236 for (i = 0; i < RPC_C_IF_REGISTRY_SIZE; i++) 237 { 238 if_registry[i].next = NULL; 239 if_registry[i].last = NULL; 240 } 241 break; 242 } 243} 244 245 246/* 247**++ 248** 249** ROUTINE NAME: rpc_server_register_if 250** 251** SCOPE: PUBLIC - declared in rpc.idl 252** 253** DESCRIPTION: 254** 255** See description of "rpc__server_register_if_int". 256** 257** INPUTS: 258** 259** ifspec_h Pointer to the ifspec 260** 261** mgr_type_uuid The interface type (if any) 262** 263** mgr_epv The manager epv for this interface 264** 265** INPUTS/OUTPUTS: none 266** 267** OUTPUTS: 268** 269** status The result of the operation. One of: 270** rpc_s_ok 271** rpc_s_type_already_registered 272** rpc_s_no_memory 273** rpc_s_coding_error 274** 275** IMPLICIT INPUTS: none 276** 277** IMPLICIT OUTPUTS: none 278** 279** FUNCTION VALUE: void 280** 281** SIDE EFFECTS: none 282** 283**-- 284**/ 285 286PUBLIC void rpc_server_register_if 287( 288 rpc_if_handle_t ifspec_h, 289 uuid_p_t mgr_type_uuid, 290 rpc_mgr_epv_t mgr_epv, 291 unsigned32 *status 292) 293{ 294 CODING_ERROR (status); 295 RPC_VERIFY_INIT (); 296 297 rpc__server_register_if_int 298 (ifspec_h, mgr_type_uuid, mgr_epv, 0, 299 rpc_c_listen_max_calls_default, -1, NULL, false, status); 300} 301 302/* 303**++ 304** 305** ROUTINE NAME: rpc__server_register_if_int 306** 307** SCOPE: PRIVATE - declared in com.h 308** 309** DESCRIPTION: 310** 311** Perform a hash lookup through the Interface Registry Table to try to 312** locate the interface spec requested. If the search fails, add the 313** interface entry to the appropriate list. Then proceed to insert the type 314** uuid specified into the linked list for the requested interface. If the 315** requested interface was located by the lookup, simply insert the type 316** uuid. 317** 318** If a NULL manager entry point vector is specified, use the one in the 319** ifspec. 320** 321** INPUTS: 322** 323** ifspec_h Pointer to the ifspec 324** 325** mgr_type_uuid The interface type (if any) 326** 327** mgr_epv The manager epv for this interface 328** 329** flags Registration flags 330** 331** max_calls Maximum calls 332** 333** max_rpc_size Maximum RPC size (-1 for no maximum) 334** 335** if_callback Security callback 336** 337** is_internal T => manager should not be unregisterable by wildcarding 338** 339** INPUTS/OUTPUTS: none 340** 341** OUTPUTS: 342** 343** status The result of the operation. One of: 344** rpc_s_ok 345** rpc_s_type_already_registered 346** rpc_s_no_memory 347** rpc_s_coding_error 348** 349** IMPLICIT INPUTS: none 350** 351** IMPLICIT OUTPUTS: none 352** 353** FUNCTION VALUE: void 354** 355** SIDE EFFECTS: none 356** 357**-- 358**/ 359 360PRIVATE void rpc__server_register_if_int 361( 362 rpc_if_handle_t ifspec_h, 363 uuid_p_t mgr_type_uuid, 364 rpc_mgr_epv_t mgr_epv, 365 unsigned32 flags, 366 unsigned32 max_calls, 367 unsigned32 max_rpc_size, 368 rpc_if_callback_fn_t if_callback, 369 boolean32 is_internal, 370 unsigned32 *status 371) 372{ 373 rpc_if_rep_p_t if_rep = (rpc_if_rep_p_t) ifspec_h; 374 rpc_mgr_epv_t mepv; 375 rpc_if_rgy_entry_p_t if_entry; 376 unsigned32 index; 377 unsigned32 ctr; 378 boolean copied_mepv = false; 379 boolean if_entry_alloced = false; 380 boolean if_entry_added = false; 381 382 CODING_ERROR (status); 383 384 RPC_IF_VALIDATE(if_rep, status); 385 if (*status != rpc_s_ok) 386 { 387 return; 388 } 389 390 /* 391 * check to see if a NULL mgr_epv was passed 392 * - if so, use the default one in the ifspec 393 * - if it's non-NULL, make a copy of it 394 */ 395 if (mgr_epv == (rpc_mgr_epv_t) NULL) 396 { 397 mepv = if_rep->manager_epv; 398 if (mepv == NULL) 399 { 400 *status = rpc_s_no_mepv; 401 return; 402 } 403 } 404 else 405 { 406 RPC_MEM_ALLOC ( 407 mepv, 408 rpc_mgr_epv_t, 409 sizeof (rpc_mgr_epv_t *) + 410 (sizeof (rpc_mgr_proc_t) * (if_rep->opcnt - 1)), 411 RPC_C_MEM_MGR_EPV, 412 RPC_C_MEM_WAITOK); 413 414 if (mepv == NULL) 415 { 416 *status = rpc_s_no_memory; 417 return; 418 } 419 420 /* 421 * fill the manager epv entries into the copy 422 */ 423 for (ctr = 0; ctr < if_rep->opcnt; ctr++) 424 { 425 mepv[ctr] = mgr_epv[ctr]; 426 } 427 428 copied_mepv = true; 429 } 430 431 /* 432 * compute a hash value using the interface uuid - check the status 433 * from uuid_hash to make sure the uuid has a valid format 434 */ 435 index = (uuid_hash (&(if_rep->id), status)) % RPC_C_IF_REGISTRY_SIZE; 436 437 if (*status != uuid_s_ok) 438 { 439 if (copied_mepv) 440 { 441 RPC_MEM_FREE (mepv, RPC_C_MEM_MGR_EPV); 442 } 443 return; 444 } 445 446 /* 447 * take out a lock to protect access to the if registry 448 */ 449 RPC_MUTEX_LOCK (if_mutex); 450 451 /* 452 * see if the specified interface already exists in the registry 453 */ 454 RPC_LIST_FIRST (if_registry[index], if_entry, rpc_if_rgy_entry_p_t); 455 456 while (if_entry != NULL) 457 { 458 /* 459 * see if the if uuid and version match 460 */ 461 if ((UUID_EQ (if_entry->if_spec->id, if_rep->id, status)) 462 && if_entry->if_spec->vers == if_rep->vers) 463 { 464 break; 465 } 466 467 RPC_LIST_NEXT (if_entry, if_entry, rpc_if_rgy_entry_p_t); 468 } 469 470 /* 471 * if no entry was found, create one and add it to the list 472 */ 473 if (if_entry == NULL) 474 { 475 RPC_MEM_ALLOC ( 476 if_entry, 477 rpc_if_rgy_entry_p_t, 478 sizeof (rpc_if_rgy_entry_t), 479 RPC_C_MEM_IF_RGY_ENTRY, 480 RPC_C_MEM_WAITOK); 481 482 if (if_entry == NULL) 483 { 484 *status = rpc_s_no_memory; 485 goto ERROR_AND_LOCKED; 486 } 487 if_entry_alloced = true; 488 489 /* 490 * initialize the entry 491 */ 492 if_entry->if_spec = if_rep; 493 if_entry->default_mepv = NULL; 494 if_entry->internal = is_internal; 495 RPC_LIST_INIT (if_entry->type_info_list); 496 if_entry->flags = flags; 497 if_entry->max_calls = max_calls; 498 if_entry->max_rpc_size = max_rpc_size; 499 if_entry->if_callback = if_callback; 500 501 /* 502 * put it on the list for this hash index 503 */ 504 RPC_LIST_ADD_TAIL (if_registry[index], if_entry, rpc_if_rgy_entry_p_t); 505 if_entry_added = true; 506 } 507 508 /* 509 * see if a manager type was specified (and is non-nil) 510 */ 511 if (mgr_type_uuid != NULL && !(uuid_is_nil (mgr_type_uuid, status))) 512 { 513 rpc_if_type_info_p_t type_info = NULL; 514 515 /* 516 * see if the specified mgr type already exists for this entry 517 */ 518 RPC_LIST_FIRST 519 (if_entry->type_info_list, type_info, rpc_if_type_info_p_t); 520 521 while (type_info != NULL) 522 { 523 /* 524 * see if the type uuid matches the one specified 525 */ 526 if (UUID_EQ (type_info->type, *mgr_type_uuid, status)) 527 { 528 *status = rpc_s_type_already_registered; 529 goto ERROR_AND_LOCKED; 530 } 531 532 RPC_LIST_NEXT (type_info, type_info, rpc_if_type_info_p_t); 533 } 534 535 /* 536 * no entry was found, create one and add it to the list 537 */ 538 assert (type_info == NULL); 539 540 /* 541 * malloc a type uuid/manager epv list element 542 */ 543 RPC_MEM_ALLOC ( 544 type_info, 545 rpc_if_type_info_p_t, 546 sizeof (rpc_if_type_info_t), 547 RPC_C_MEM_IF_TYPE_INFO, 548 RPC_C_MEM_WAITOK); 549 550 if (type_info == NULL) 551 { 552 *status = rpc_s_no_memory; 553 goto ERROR_AND_LOCKED; 554 } 555 556 /* 557 * fill in the supplied type info 558 */ 559 type_info->type = *mgr_type_uuid; 560 type_info->mepv = mepv; 561 type_info->copied_mepv = copied_mepv; 562 563 /* 564 * add the type info entry to the list for this interface 565 */ 566 RPC_LIST_ADD_TAIL 567 (if_entry->type_info_list, type_info, rpc_if_type_info_p_t); 568 } 569 else 570 { 571 /* 572 * set the default manager epv 573 */ 574 if (if_entry->default_mepv != NULL) 575 { 576 *status = rpc_s_type_already_registered; 577 goto ERROR_AND_LOCKED; 578 } 579 if_entry->default_mepv = mepv; 580 if_entry->copied_mepv = copied_mepv; 581 } 582 583 /* 584 * free the global lock and return 585 */ 586 RPC_MUTEX_UNLOCK (if_mutex); 587 *status = rpc_s_ok; 588 return; 589 590ERROR_AND_LOCKED: 591 /* 592 * perform necessary cleanup, free the global lock and return 593 * (the return status already set). 594 */ 595 596 if (if_entry_alloced) 597 { 598 if (if_entry_added) 599 { 600 RPC_LIST_REMOVE (if_registry[index], if_entry); 601 } 602 RPC_MEM_FREE (if_entry, RPC_C_MEM_IF_RGY_ENTRY); 603 } 604 if (copied_mepv) 605 { 606 RPC_MEM_FREE (mepv, RPC_C_MEM_MGR_EPV); 607 } 608 609 RPC_MUTEX_UNLOCK (if_mutex); 610 return; 611} 612 613/* 614**++ 615** 616** ROUTINE NAME: rpc_server_unregister_if_int 617** 618** SCOPE: PRIVATE - declared in com.h 619** 620** DESCRIPTION: 621** 622** Perform a hash lookup on the Interface Registry Table to locate the 623** specified interface spec. If the search fails, return 624** 'rpc_s_unknown_if'. If a registered interface is located with the 625** UUID and version specified in the if_spec, it is deleted from the 626** Interface Registry Table along with the linked list of Type UUIDs. 627** 628** Also returns the pointer to the ifspec in the entry that was 629** unregistered. This pointer turns out to be needed by the compatibility 630** library. 631** 632** INPUTS: 633** 634** ifspec_h Pointer to the ifspec 635** 636** mgr_type_uuid The type uuid of the manager epv to unregister. 637** 638** INPUTS/OUTPUTS: none 639** 640** OUTPUTS: 641** 642** rtn_ifspec_h Pointer to the ifspec that was in the entry that was 643** unregistered. 644** 645** status The result of the operation. One of: 646** rpc_s_ok 647** rpc_s_unknown_if 648** rpc_s_coding_error 649** 650** IMPLICIT INPUTS: none 651** 652** IMPLICIT OUTPUTS: none 653** 654** FUNCTION VALUE: void 655** 656** SIDE EFFECTS: none 657** 658**-- 659**/ 660 661PRIVATE void rpc__server_unregister_if_int 662( 663 rpc_if_handle_t ifspec_h, 664 uuid_p_t mgr_type_uuid, 665 rpc_if_handle_t *rtn_ifspec_h, 666 unsigned32 *status 667) 668{ 669 rpc_if_rep_p_t if_rep = (rpc_if_rep_p_t) ifspec_h; 670 unsigned32 index; 671 rpc_if_rgy_entry_p_t if_entry, next_if_entry; 672 boolean found_mgr_type; 673 674 CODING_ERROR (status); 675 676 *rtn_ifspec_h = NULL; 677 678 /* 679 * take out a lock to protect access to the if registry 680 */ 681 RPC_MUTEX_LOCK (if_mutex); 682 683 /* 684 * see what kind of unregister is wanted 685 */ 686 if (if_rep == NULL) 687 { 688 /* 689 * go through the whole registry hash table 690 */ 691 for (index = 0, found_mgr_type = false; 692 index < RPC_C_IF_REGISTRY_SIZE; index++) 693 { 694 /* 695 * walk the list of entries for each hash value 696 */ 697 RPC_LIST_FIRST (if_registry[index], if_entry, rpc_if_rgy_entry_p_t); 698 699 while (if_entry != NULL) 700 { 701 /* 702 * do whatever unregister is required for this entry 703 */ 704 if (! if_entry->internal) 705 { 706 unregister_if_entry (if_entry, mgr_type_uuid, status); 707 708 if (*status != rpc_s_ok) 709 { 710 if (*status != rpc_s_unknown_mgr_type) 711 { 712 RPC_MUTEX_UNLOCK (if_mutex); 713 return; 714 } 715 } 716 else 717 { 718 found_mgr_type = true; 719 } 720 } 721 722 RPC_LIST_NEXT (if_entry, next_if_entry, rpc_if_rgy_entry_p_t); 723 724 /* 725 * See if there are any mgr types left for this interface 726 * entry. If not, remove this entry from the list for this 727 * hash value, and free the entry. 728 */ 729 if (RPC_LIST_EMPTY (if_entry->type_info_list) && 730 if_entry->default_mepv == NULL) 731 { 732 RPC_LIST_REMOVE (if_registry[index], if_entry); 733 734 RPC_MEM_FREE (if_entry, RPC_C_MEM_IF_RGY_ENTRY); 735 } 736 737 if_entry = next_if_entry; 738 } 739 } 740 741 if (!found_mgr_type) 742 { 743 RPC_MUTEX_UNLOCK (if_mutex); 744 *status = rpc_s_unknown_mgr_type; 745 return; 746 } 747 } 748 else 749 { 750 /* 751 * compute a hash value using the interface uuid - check the status 752 * from uuid_hash to make sure the uuid has a valid format 753 */ 754 index = uuid_hash (&(if_rep->id), status) % RPC_C_IF_REGISTRY_SIZE; 755 756 if (*status != uuid_s_ok) 757 { 758 RPC_MUTEX_UNLOCK (if_mutex); 759 return; 760 } 761 762 /* 763 * walk the list of entries for this hash value 764 */ 765 RPC_LIST_FIRST (if_registry[index], if_entry, rpc_if_rgy_entry_p_t); 766 767 while (if_entry != NULL) 768 { 769 if (! if_entry->internal) 770 { 771 /* 772 * see if the if uuid and version match 773 */ 774 if ((UUID_EQ (if_entry->if_spec->id, if_rep->id, status)) 775 && if_entry->if_spec->vers == if_rep->vers) 776 { 777 /* 778 * snag the ifspec now, before the if entry (maybe) gets 779 * freed. 780 */ 781 *rtn_ifspec_h = (rpc_if_handle_t) if_entry->if_spec; 782 783 /* 784 * do whatever unregister is required for this entry 785 */ 786 unregister_if_entry (if_entry, mgr_type_uuid, status); 787 788 if (*status != rpc_s_ok) 789 { 790 RPC_MUTEX_UNLOCK (if_mutex); 791 return; 792 } 793 794 /* 795 * See if there are any mgr types left for this 796 * interface entry. If not, remove this entry from 797 * the list for this hash value, and free the entry. 798 */ 799 if (RPC_LIST_EMPTY (if_entry->type_info_list) && 800 if_entry->default_mepv == NULL) 801 { 802 RPC_LIST_REMOVE (if_registry[index], if_entry); 803 804 RPC_MEM_FREE (if_entry, RPC_C_MEM_IF_RGY_ENTRY); 805 } 806 807 /* 808 * finished searching 809 */ 810 break; 811 } 812 } 813 814 RPC_LIST_NEXT (if_entry, if_entry, rpc_if_rgy_entry_p_t); 815 } 816 817 if (*rtn_ifspec_h == NULL) 818 { 819 RPC_MUTEX_UNLOCK (if_mutex); 820 *status = rpc_s_unknown_if; 821 return; 822 } 823 } 824 825 RPC_MUTEX_UNLOCK (if_mutex); 826 *status = rpc_s_ok; 827 return; 828} 829 830/* 831**++ 832** 833** ROUTINE NAME: rpc_server_unregister_if 834** 835** SCOPE: PUBLIC - declared in rpc.idl 836** 837** DESCRIPTION: 838** 839** See description of "rpc__server_unregister_int". 840** 841** INPUTS: 842** 843** ifspec_h Pointer to the ifspec 844** 845** mgr_type_uuid The type uuid of the manager epv to unregister. 846** 847** INPUTS/OUTPUTS: none 848** 849** OUTPUTS: 850** 851** status The result of the operation. One of: 852** rpc_s_ok 853** rpc_s_unknown_if 854** rpc_s_coding_error 855** 856** IMPLICIT INPUTS: none 857** 858** IMPLICIT OUTPUTS: none 859** 860** FUNCTION VALUE: void 861** 862** SIDE EFFECTS: none 863** 864**-- 865**/ 866 867PUBLIC void rpc_server_unregister_if 868( 869 rpc_if_handle_t ifspec_h, 870 uuid_p_t mgr_type_uuid, 871 unsigned32 *status 872) 873{ 874 rpc_if_handle_t rtn_ifspec_h; 875 876 CODING_ERROR (status); 877 RPC_VERIFY_INIT (); 878 879 rpc__server_unregister_if_int (ifspec_h, mgr_type_uuid, &rtn_ifspec_h, status); 880} 881 882/* 883** This routine is called by rpc_server_unregister_if() to process a single 884** interface entry in the if registry. 885**/ 886 887INTERNAL void unregister_if_entry 888( 889 rpc_if_rgy_entry_p_t if_entry, 890 uuid_p_t mgr_type_uuid, 891 unsigned32 *status 892) 893{ 894 rpc_if_type_info_p_t type_info; 895 rpc_if_type_info_p_t current_type_info; 896 897 /* 898 * see if this is a wildcard operation 899 */ 900 if (mgr_type_uuid == NULL) 901 { 902 /* 903 * free the default manager epv if copied on register 904 */ 905 if (if_entry->copied_mepv) 906 { 907 RPC_MEM_FREE (if_entry->default_mepv, RPC_C_MEM_MGR_EPV); 908 } 909 910 if_entry->default_mepv = NULL; 911 912 /* 913 * walk the type info list and remove all entries 914 */ 915 RPC_LIST_FIRST 916 (if_entry->type_info_list, type_info, rpc_if_type_info_p_t); 917 918 while (type_info != NULL) 919 { 920 /* 921 * free the mepv if copied during register 922 */ 923 if (type_info->copied_mepv) 924 { 925 RPC_MEM_FREE (type_info->mepv, RPC_C_MEM_MGR_EPV); 926 } 927 928 /* 929 * remove this entry from the list for this interface 930 */ 931 RPC_LIST_REMOVE (if_entry->type_info_list, type_info); 932 933 /* 934 * save this entry and get the next one on the list 935 */ 936 current_type_info = type_info; 937 938 RPC_LIST_FIRST 939 (if_entry->type_info_list, type_info, rpc_if_type_info_p_t); 940 941 /* 942 * free the type info entry itself 943 */ 944 RPC_MEM_FREE (current_type_info, RPC_C_MEM_IF_TYPE_INFO); 945 } 946 } 947 else 948 { 949 /* 950 * see if this is an unregister for the default manager epv 951 */ 952 if (uuid_is_nil (mgr_type_uuid, status)) 953 { 954 if (if_entry->default_mepv == NULL) 955 { 956 *status = rpc_s_unknown_mgr_type; 957 return; 958 } 959 960 /* 961 * free the default manager epv if copied on register 962 */ 963 if (if_entry->copied_mepv) 964 { 965 RPC_MEM_FREE (if_entry->default_mepv, RPC_C_MEM_MGR_EPV); 966 } 967 968 if_entry->default_mepv = NULL; 969 } 970 else 971 { 972 /* 973 * walk the type info list looking for matches 974 */ 975 RPC_LIST_FIRST 976 (if_entry->type_info_list, type_info, rpc_if_type_info_p_t); 977 978 while (type_info != NULL) 979 { 980 /* 981 * only remove entries whose type uuid's match the one specified 982 */ 983 if (UUID_EQ (type_info->type, *mgr_type_uuid, status)) 984 { 985 /* 986 * free the mepv if copied during register 987 */ 988 if (type_info->copied_mepv) 989 { 990 RPC_MEM_FREE (type_info->mepv, RPC_C_MEM_MGR_EPV); 991 } 992 993 /* 994 * remove this entry from the list for this interface 995 */ 996 RPC_LIST_REMOVE (if_entry->type_info_list, type_info); 997 998 /* 999 * free the type info entry itself 1000 */ 1001 RPC_MEM_FREE (type_info, RPC_C_MEM_IF_TYPE_INFO); 1002 1003 /* 1004 * then stop the search 1005 */ 1006 break; 1007 } 1008 1009 RPC_LIST_NEXT (type_info, type_info, rpc_if_type_info_p_t); 1010 } 1011 1012 if (type_info == NULL) 1013 { 1014 *status = rpc_s_unknown_mgr_type; 1015 return; 1016 } 1017 } 1018 } 1019 1020 *status = rpc_s_ok; 1021 return; 1022} 1023 1024/* 1025**++ 1026** 1027** ROUTINE NAME: rpc__if_lookup 1028** 1029** SCOPE: PRIVATE - declared in comif.h 1030** 1031** DESCRIPTION: 1032** 1033** Look into the Interface Registry Table for the Interface requested. 1034** The search is conducted in either one or two steps. First the index 1035** from a previous request that is remembered in 'ihint' is tried, then 1036** if this fails to locate the interface, a regular hash lookup is performed. 1037** If the interface can't be located 'rpc_s_unknown_if' is returned. 1038** 1039** Once the interface is located, its attached linked list of type UUIDs 1040** is searched for the type UUID specified. If the requested type uuid 1041** is not found 'rpc_s_unknown_mgr_type' is returned. Once the requested 1042** interface and type UUID are located a pointer to the interface 1043** specification is returned. Also returned are the server stub epv 1044** and the manager epv. The index to this Interface registry is saved in 1045** the location pointed to by 'ihint', under the assumption that a subsequent 1046** lookup may request this same interface. 1047** 1048** INPUTS: 1049** 1050** if_uuid The interface UUID to lookup 1051** 1052** if_vers The interface version to lookup 1053** 1054** mgr_type_uuid The interface type (if any) 1055** (set this to NULL or the nil uuid to cause the 1056** default manager epv to be returned) 1057** 1058** INPUTS/OUTPUTS: 1059** 1060** ihint A hint of the index into the table for this if 1061** 1062** OUTPUTS: 1063** 1064** ifspec_h Pointer to the ifspec 1065** (NULL on input if not wanted) 1066** 1067** sepv The server stub epv for this interface 1068** (NULL on input if not wanted) 1069** 1070** mepv The manager epv for this interface 1071** (NULL on input if not wanted) 1072** 1073** status The result of the operation. One of: 1074** rpc_s_ok 1075** rpc_s_unknown_if 1076** rpc_s_unknown_mgr_type 1077** rpc_s_coding_error 1078** 1079** IMPLICIT INPUTS: none 1080** 1081** IMPLICIT OUTPUTS: none 1082** 1083** FUNCTION VALUE: void 1084** 1085** SIDE EFFECTS: none 1086** 1087**-- 1088**/ 1089 1090PRIVATE void rpc__if_lookup 1091( 1092 uuid_p_t if_uuid, 1093 unsigned32 if_vers, 1094 uuid_p_t mgr_type_uuid, 1095 unsigned16 *ihint, 1096 rpc_if_rep_p_t *ifspec, 1097 rpc_v2_server_stub_epv_t *sepv, 1098 rpc_mgr_epv_t *mepv, 1099 unsigned32 *status 1100) 1101{ 1102 return rpc__if_lookup2 (if_uuid, if_vers, mgr_type_uuid, 1103 ihint, ifspec, sepv, mepv, 1104 NULL, NULL, NULL, NULL, status); 1105} 1106 1107 1108/* 1109**++ 1110** 1111** ROUTINE NAME: rpc__if_lookup2 1112** 1113** SCOPE: PRIVATE - declared in comif.h 1114** 1115** DESCRIPTION: 1116** 1117** Look into the Interface Registry Table for the Interface requested. 1118** The search is conducted in either one or two steps. First the index 1119** from a previous request that is remembered in 'ihint' is tried, then 1120** if this fails to locate the interface, a regular hash lookup is performed. 1121** If the interface can't be located 'rpc_s_unknown_if' is returned. 1122** 1123** Once the interface is located, its attached linked list of type UUIDs 1124** is searched for the type UUID specified. If the requested type uuid 1125** is not found 'rpc_s_unknown_mgr_type' is returned. Once the requested 1126** interface and type UUID are located a pointer to the interface 1127** specification is returned. Also returned are the server stub epv 1128** and the manager epv. The index to this Interface registry is saved in 1129** the location pointed to by 'ihint', under the assumption that a subsequent 1130** lookup may request this same interface. 1131** 1132** INPUTS: 1133** 1134** if_uuid The interface UUID to lookup 1135** 1136** if_vers The interface version to lookup 1137** 1138** mgr_type_uuid The interface type (if any) 1139** (set this to NULL or the nil uuid to cause the 1140** default manager epv to be returned) 1141** 1142** INPUTS/OUTPUTS: 1143** 1144** ihint A hint of the index into the table for this if 1145** 1146** OUTPUTS: 1147** 1148** ifspec_h Pointer to the ifspec 1149** (NULL on input if not wanted) 1150** 1151** sepv The server stub epv for this interface 1152** (NULL on input if not wanted) 1153** 1154** mepv The manager epv for this interface 1155** (NULL on input if not wanted) 1156** 1157** flags The interface registration flags 1158** (NULL on input if not wanted) 1159** 1160** max_calls The maximum number of concurrent RPCs 1161** (NULL on input if not wanted) 1162** 1163** max_rpc_size The maximum size of incoming data blocks 1164** (NULL on input if not wanted) 1165** 1166** if_callback The security callback function 1167** (NULL on input if not wanted) 1168** 1169** status The result of the operation. One of: 1170** rpc_s_ok 1171** rpc_s_unknown_if 1172** rpc_s_unknown_mgr_type 1173** rpc_s_coding_error 1174** 1175** IMPLICIT INPUTS: none 1176** 1177** IMPLICIT OUTPUTS: none 1178** 1179** FUNCTION VALUE: void 1180** 1181** SIDE EFFECTS: none 1182** 1183**-- 1184**/ 1185 1186PRIVATE void rpc__if_lookup2 1187( 1188 uuid_p_t if_uuid, 1189 unsigned32 if_vers, 1190 uuid_p_t mgr_type_uuid, 1191 unsigned16 *ihint, 1192 rpc_if_rep_p_t *ifspec, 1193 rpc_v2_server_stub_epv_t *sepv, 1194 rpc_mgr_epv_t *mepv, 1195 unsigned32 *flags, 1196 unsigned32 *max_calls, 1197 unsigned32 *max_rpc_size, 1198 rpc_if_callback_fn_t *if_callback, 1199 unsigned32 *status 1200) 1201{ 1202 rpc_if_rgy_entry_p_t if_entry = NULL; 1203 rpc_if_type_info_p_t type_info; 1204 unsigned32 index; 1205 unsigned32 entry_count = 0; 1206 unsigned32 temp_status; 1207 1208 RPC_LOG_IF_LOOKUP_NTR; 1209 CODING_ERROR (status); 1210 1211 /* 1212 * take out a lock to protect access to the if registry 1213 */ 1214 RPC_MUTEX_LOCK (if_mutex); 1215 1216 /* 1217 * see if the interface hint we're given is valid 1218 */ 1219 if (*ihint != RPC_C_INVALID_IHINT) 1220 { 1221 /* 1222 * extract the hash value from the low byte of the ihint 1223 * and the list entry count form the high byte 1224 */ 1225 index = *ihint & 0x00FF; 1226 entry_count = (*ihint & 0xFF00) >> 8; 1227 1228 /* 1229 * try to find a match using the hints provided 1230 */ 1231 RPC_LIST_LOOKUP 1232 (if_registry[index], if_entry, rpc_if_rgy_entry_p_t, entry_count); 1233 1234 if (if_entry != NULL && 1235 ! RPC_IF_IS_COMPATIBLE (if_entry, if_uuid, if_vers, status)) 1236 { 1237 if_entry = NULL; 1238 } 1239 } 1240 else 1241 { 1242 /* 1243 * compute a hash value using the interface uuid - check the status 1244 * from uuid_hash to make sure the uuid has a valid format 1245 */ 1246 index = uuid_hash (if_uuid, status) % RPC_C_IF_REGISTRY_SIZE; 1247 1248 if (*status != uuid_s_ok) 1249 { 1250 RPC_MUTEX_UNLOCK (if_mutex); 1251 return; 1252 } 1253 } 1254 1255 /* 1256 * if we got this far and didn't find a match, search the whole list 1257 * under the current hash value for the given interface 1258 */ 1259 if (if_entry == NULL) 1260 { 1261 RPC_LIST_FIRST (if_registry[index], if_entry, rpc_if_rgy_entry_p_t); 1262 1263 for (entry_count = 1; if_entry != NULL; entry_count++) 1264 { 1265 if (RPC_IF_IS_COMPATIBLE (if_entry, if_uuid, if_vers, status)) 1266 { 1267 break; 1268 } 1269 1270 RPC_LIST_NEXT (if_entry, if_entry, rpc_if_rgy_entry_p_t); 1271 } 1272 } 1273 1274 /* 1275 * if still no entry was found, report unknown interface 1276 */ 1277 if (if_entry == NULL) 1278 { 1279 *ihint = RPC_C_INVALID_IHINT; 1280 *status = rpc_s_unknown_if; 1281 RPC_MUTEX_UNLOCK (if_mutex); 1282 return; 1283 } 1284 1285 /* 1286 * if a manager type uuid is given, and is not the nil uuid, try to match 1287 * for a registered type - otherwise, return the default manager epv 1288 */ 1289 if (mgr_type_uuid != NULL && !(uuid_is_nil (mgr_type_uuid, status))) 1290 { 1291 /* 1292 * scan the type uuid/mgr epv list for a match 1293 */ 1294 RPC_LIST_FIRST 1295 (if_entry->type_info_list, type_info, rpc_if_type_info_p_t); 1296 1297 while (type_info != NULL) 1298 { 1299 if (UUID_EQ (type_info->type, *mgr_type_uuid, status)) 1300 { 1301 if (mepv != NULL) 1302 { 1303 *mepv = type_info->mepv; 1304 } 1305 1306 break; 1307 } 1308 1309 RPC_LIST_NEXT (type_info, type_info, rpc_if_type_info_p_t); 1310 } 1311 1312 if (type_info == NULL) 1313 { 1314 /* 1315 * if no 'type' match is found, invalidate the interface 1316 * hint. But before giving up entirely, if the interface 1317 * we're looking for is the internal mgmt interface, try 1318 * one more time using a NIL type; this lets clients make 1319 * remote mgmt calls using bindings that might have a typed 1320 * object in them. 1321 */ 1322 *ihint = RPC_C_INVALID_IHINT; 1323 *status = rpc_s_unknown_mgr_type; 1324 RPC_MUTEX_UNLOCK (if_mutex); 1325 1326 if (UUID_EQ (((rpc_if_rep_p_t) mgmt_v1_0_s_ifspec)->id, *if_uuid, &temp_status)) 1327 { 1328 rpc__if_lookup2 (if_uuid, if_vers, NULL, ihint, ifspec, sepv, mepv, 1329 flags, max_calls, max_rpc_size, if_callback, status); 1330 } 1331 1332 return; 1333 } 1334 } 1335 else 1336 { 1337 /* 1338 * The default (nil-type) manager epv is requested, 1339 * return an error if one isn't registered and a manager epv 1340 * is wanted. 1341 */ 1342 if (mepv != NULL) 1343 { 1344 if (if_entry->default_mepv == NULL) 1345 { 1346 *ihint = RPC_C_INVALID_IHINT; 1347 *status = rpc_s_unknown_mgr_type; 1348 RPC_MUTEX_UNLOCK (if_mutex); 1349 return; 1350 } 1351 *mepv = if_entry->default_mepv; 1352 } 1353 } 1354 1355 /* 1356 * if a complete match is found, return its info (if wanted) 1357 */ 1358 if (ifspec != NULL) 1359 { 1360 *ifspec = if_entry->if_spec; 1361 } 1362 1363 if (sepv != NULL) 1364 { 1365 *sepv = if_entry->if_spec->server_epv; 1366 } 1367 1368 if (flags != NULL) 1369 { 1370 *flags = if_entry->flags; 1371 } 1372 1373 if (max_calls != NULL) 1374 { 1375 *max_calls = if_entry->max_calls; 1376 } 1377 1378 if (max_rpc_size != NULL) 1379 { 1380 *max_rpc_size = if_entry->max_rpc_size; 1381 } 1382 1383 if (if_callback != NULL) 1384 { 1385 *if_callback = if_entry->if_callback; 1386 } 1387 1388 /* 1389 * provide a useful hint for future references to this interface 1390 */ 1391 *ihint = (unsigned16) (index | ((entry_count & 0x00FF) << 8)); 1392 1393 RPC_MUTEX_UNLOCK (if_mutex); 1394 *status = rpc_s_ok; 1395 RPC_LOG_IF_LOOKUP_XIT; 1396 1397 return; 1398} 1399 1400/* 1401**++ 1402** 1403** ROUTINE NAME: rpc_if_inq_id 1404** 1405** SCOPE: PUBLIC - declared in rpc.idl 1406** 1407** DESCRIPTION: 1408** 1409** Extract the interface id (UUID and version numbers) from the given 1410** interface spec. 1411** 1412** INPUTS: 1413** 1414** ifspec_h Pointer to the ifspec 1415** 1416** INPUTS/OUTPUTS: none 1417** 1418** OUTPUTS: 1419** 1420** if_id The interface id. 1421** 1422** status The result of the operation. One of: 1423** rpc_s_ok 1424** rpc_s_coding_error 1425** 1426** IMPLICIT INPUTS: none 1427** 1428** IMPLICIT OUTPUTS: none 1429** 1430** FUNCTION VALUE: void 1431** 1432** SIDE EFFECTS: none 1433** 1434**-- 1435**/ 1436 1437PUBLIC void rpc_if_inq_id 1438( 1439 rpc_if_handle_t ifspec_h, 1440 rpc_if_id_t *if_id, 1441 unsigned32 *status 1442) 1443{ 1444 CODING_ERROR (status); 1445 RPC_VERIFY_INIT (); 1446 1447 /* 1448 * copy the interface UUID from the if_spec 1449 */ 1450 if_id->uuid = ((rpc_if_rep_p_t) (ifspec_h))->id; 1451 1452 /* 1453 * convert the old form of the version number (single unsigned long) 1454 * into the new form (major and minor unsigned16's) 1455 */ 1456 if_id->vers_major = RPC_IF_VERS_MAJOR(((rpc_if_rep_p_t) ifspec_h)->vers); 1457 if_id->vers_minor = RPC_IF_VERS_MINOR(((rpc_if_rep_p_t) (ifspec_h))->vers); 1458 1459 *status = rpc_s_ok; 1460} 1461 1462/* 1463**++ 1464** 1465** ROUTINE NAME: rpc__if_id_compare 1466** 1467** SCOPE: PRIVATE - declared in com.h 1468** 1469** DESCRIPTION: 1470** 1471** Compares two interface id's and matches based on the version option. 1472** 1473** INPUTS: 1474** 1475** if_id_ref The reference interface id against which the comparison 1476** is to be made. 1477** 1478** if_id The interface id to be compared to the reference. 1479** 1480** if_vers_option The criteria by which the if version numbers are to 1481** be compared. One of: 1482** rpc_c_vers_all 1483** rpc_c_vers_compatible 1484** rpc_c_vers_exact 1485** rpc_c_vers_major_only 1486** rpc_c_vers_upto 1487** 1488** INPUTS/OUTPUTS: none 1489** 1490** OUTPUTS: 1491** 1492** status The result of the operation. One of: 1493** rpc_s_ok 1494** the result of uuid_equal() 1495** 1496** IMPLICIT INPUTS: none 1497** 1498** IMPLICIT OUTPUTS: none 1499** 1500** FUNCTION VALUE: 1501** 1502** true if the interface id is compatible with the reference 1503** false if the interface id is not compatible with the reference 1504** 1505** SIDE EFFECTS: none 1506** 1507**-- 1508**/ 1509 1510PRIVATE boolean rpc__if_id_compare 1511( 1512 rpc_if_id_p_t if_id_ref, 1513 rpc_if_id_p_t if_id, 1514 unsigned32 if_vers_option, 1515 unsigned32 *status 1516) 1517{ 1518 *status = rpc_s_ok; 1519 1520 /* 1521 * see if the returned if uuid matches the one given 1522 */ 1523 if (! (UUID_EQ (if_id->uuid, if_id_ref->uuid, status))) 1524 { 1525 /* 1526 * return "incompatible" and the status of uuid_equal() 1527 */ 1528 return (false); 1529 } 1530 else 1531 { 1532 /* 1533 * if they do match, check what the version option is 1534 */ 1535 switch ((int)if_vers_option) 1536 { 1537 /* 1538 * any version is ok 1539 */ 1540 case rpc_c_vers_all: 1541 { 1542 return (true); 1543 } 1544 1545 /* 1546 * major versions must match, minor version must be greater than 1547 * or equal to minor version in the reference 1548 */ 1549 case rpc_c_vers_compatible: 1550 { 1551 if (if_id->vers_major == if_id_ref->vers_major && 1552 if_id->vers_minor >= if_id_ref->vers_minor) 1553 { 1554 return (true); 1555 } 1556 else 1557 { 1558 return (false); 1559 } 1560 } 1561 1562 /* 1563 * major and minor versions must match 1564 */ 1565 case rpc_c_vers_exact: 1566 { 1567 if (if_id->vers_major == if_id_ref->vers_major && 1568 if_id->vers_minor == if_id_ref->vers_minor) 1569 { 1570 return (true); 1571 } 1572 else 1573 { 1574 return (false); 1575 } 1576 } 1577 1578 /* 1579 * major versions must match - minor versions are ignored 1580 */ 1581 case rpc_c_vers_major_only: 1582 { 1583 if (if_id->vers_major == if_id_ref->vers_major) 1584 { 1585 return (true); 1586 } 1587 else 1588 { 1589 return (false); 1590 } 1591 } 1592 1593 /* 1594 * major version and minor version must both be less than or 1595 * equal to their counterparts in the reference 1596 */ 1597 case rpc_c_vers_upto: 1598 { 1599 if (if_id->vers_major < if_id_ref->vers_major) 1600 { 1601 return (true); 1602 } 1603 else 1604 { 1605 if (if_id->vers_major == if_id_ref->vers_major && 1606 if_id->vers_minor <= if_id_ref->vers_minor) 1607 { 1608 return (true); 1609 } 1610 else 1611 { 1612 return (false); 1613 } 1614 } 1615 } 1616 } 1617 return (false); 1618 } 1619} 1620 1621/* 1622**++ 1623** 1624** ROUTINE NAME: rpc_if_id_vector_free 1625** 1626** SCOPE: PUBLIC - declared in rpc.idl 1627** 1628** DESCRIPTION: 1629** 1630** Free the memory allocated for an rpc_if_id_vector_t. 1631** 1632** INPUTS: none 1633** 1634** INPUTS/OUTPUTS: 1635** 1636** if_id_vector The vector of interface id's to be freed. 1637** 1638** OUTPUTS: 1639** 1640** status The result of the operation. One of: 1641** rpc_s_ok 1642** rpc_s_coding_error 1643** rpc_s_invalid_arg 1644** 1645** IMPLICIT INPUTS: none 1646** 1647** IMPLICIT OUTPUTS: none 1648** 1649** FUNCTION VALUE: void 1650** 1651** SIDE EFFECTS: none 1652** 1653**-- 1654**/ 1655 1656PUBLIC void rpc_if_id_vector_free 1657( 1658 rpc_if_id_vector_p_t *if_id_vector, 1659 unsigned32 *status 1660) 1661{ 1662 unsigned32 i; 1663 1664 CODING_ERROR (status); 1665 RPC_VERIFY_INIT (); 1666 1667 /* 1668 * check to see if if_id_vector is NULL, and if 1669 * so, return an error status 1670 */ 1671 if (if_id_vector == NULL) 1672 { 1673 *status = rpc_s_invalid_arg; 1674 return; 1675 } 1676 1677 /* 1678 * walk the if id vector and free each element 1679 */ 1680 for (i = 0; i < (*if_id_vector)->count; i++) 1681 { 1682 if ((*if_id_vector)->if_id[i] != NULL) 1683 { 1684 RPC_MEM_FREE ((*if_id_vector)->if_id[i], RPC_C_MEM_IF_ID); 1685 } 1686 } 1687 1688 /* 1689 * then free the vector itself 1690 */ 1691 RPC_MEM_FREE ((*if_id_vector), RPC_C_MEM_IF_ID_VECTOR); 1692 1693 /* 1694 * return a NULL pointer 1695 */ 1696 *if_id_vector = NULL; 1697 *status = rpc_s_ok; 1698 return; 1699} 1700 1701/* 1702**++ 1703** 1704** ROUTINE NAME: rpc__if_inq_endpoint 1705** 1706** SCOPE: PRIVATE - declared in comif.h 1707** 1708** DESCRIPTION: 1709** 1710** With the given interface spec, search through the associated array 1711** of RPC Protocol Sequence/endpoint pairs. Compare the Protocol Sequence 1712** ID given to the one in the ifspec (protocol_id's are used instead 1713** of protseq id strings to make handling of aliases simpler and 1714** localized). Filter out any extraneous info, such as "endpoint=" and 1715** other information the user may have put into the endpoint attribute in 1716** the idl file. If the requested endpoint can't be located, return 1717** 'rpc_s_endpoint_not_found'. 1718** 1719** INPUTS: 1720** 1721** ifspec_h Pointer to the ifspec 1722** 1723** protseq_id The protocol sequence to be matched 1724** 1725** INPUTS/OUTPUTS: none 1726** 1727** OUTPUTS: 1728** 1729** endpoint The endpoint contained int he ifspec for the 1730** given protocol sequence. 1731** 1732** status The result of the operation. One of: 1733** rpc_s_ok 1734** rpc_s_endpoint_not_found 1735** rpc_s_coding_error 1736** 1737** IMPLICIT INPUTS: none 1738** 1739** IMPLICIT OUTPUTS: none 1740** 1741** FUNCTION VALUE: void 1742** 1743** SIDE EFFECTS: none 1744** 1745**-- 1746**/ 1747 1748PRIVATE void rpc__if_inq_endpoint 1749( 1750 rpc_if_rep_p_t ifspec, 1751 rpc_protseq_id_t protseq_id, 1752 unsigned_char_t **endpoint, 1753 unsigned32 *status 1754) 1755{ 1756 unsigned16 ctr; 1757 rpc_protseq_id_t pseq_id; 1758 unsigned_char_t *scratch_endpoint; 1759 1760 CODING_ERROR (status); 1761 1762 for (ctr = 0; ctr < ifspec->endpoint_vector.count; ctr++) 1763 { 1764 pseq_id = rpc__network_pseq_id_from_pseq ( 1765 ifspec->endpoint_vector.endpoint_vector_elt[ctr].rpc_protseq, 1766 status); 1767 if (*status == rpc_s_protseq_not_supported) 1768 { 1769 *status = rpc_s_ok; 1770 continue; 1771 } 1772 if (*status != rpc_s_ok) { 1773 return; 1774 } 1775 1776 if (pseq_id == protseq_id) 1777 { 1778 size_t len; 1779 /* 1780 * Allocate enough space so we can place brackets around the 1781 * string before attempting to filter it. We need 3 extra 1782 * bytes, for '[', ']', and '\0'. 1783 */ 1784 len = strlen ((char *) ifspec->endpoint_vector.endpoint_vector_elt[ctr].endpoint) + 3; 1785 RPC_MEM_ALLOC ( 1786 scratch_endpoint, 1787 unsigned_char_p_t, 1788 len, 1789 RPC_C_MEM_STRING, 1790 RPC_C_MEM_WAITOK); 1791 1792 snprintf ((char *) scratch_endpoint, len, "[%s]", 1793 (char *) (ifspec->endpoint_vector.endpoint_vector_elt[ctr].endpoint)); 1794 1795 /* 1796 * Extract just the endpoint portion. 1797 */ 1798 rpc_string_binding_parse(scratch_endpoint, NULL, NULL, NULL, 1799 endpoint, NULL, status); 1800 1801 RPC_MEM_FREE(scratch_endpoint, RPC_C_MEM_STRING); 1802 1803 return; 1804 } 1805 } 1806 *status = rpc_s_endpoint_not_found; 1807} 1808 1809/* 1810**++ 1811** 1812** ROUTINE NAME: rpc__if_set_wk_endpoint 1813** 1814** SCOPE: PRIVATE - declared in comif.h 1815** 1816** DESCRIPTION: 1817** 1818** Set an RPC addr's endpoint based on the well-known endpoint in the 1819** given ifspec, if there is one. 1820** 1821** INPUTS: 1822** 1823** ifspec_h Pointer to the ifspec 1824** 1825** INPUTS/OUTPUTS: 1826** 1827** rpc_addr The rpc address in which to set the endpoint 1828** 1829** OUTPUTS: 1830** 1831** status The result of the operation. One of: 1832** rpc_s_ok 1833** rpc_s_too_many_ifs 1834** rpc_s_no_memory 1835** rpc_s_coding_error 1836** 1837** IMPLICIT INPUTS: none 1838** 1839** IMPLICIT OUTPUTS: none 1840** 1841** FUNCTION VALUE: void 1842** 1843** SIDE EFFECTS: none 1844** 1845**-- 1846**/ 1847 1848PRIVATE void rpc__if_set_wk_endpoint 1849( 1850 rpc_if_rep_p_t ifspec, 1851 rpc_addr_p_t *rpc_addr, 1852 unsigned32 *status 1853) 1854{ 1855 unsigned_char_p_t endpoint; 1856 unsigned32 temp_status; 1857 1858 CODING_ERROR (status); 1859 1860 /* 1861 * get the endpoint from the if spec 1862 */ 1863 rpc__if_inq_endpoint ( 1864 ifspec, 1865 (*rpc_addr)->rpc_protseq_id, 1866 &endpoint, 1867 status); 1868 1869 if (*status == rpc_s_ok) 1870 { 1871 /* 1872 * call the naf extension service to put the endpoint in the rpc addr 1873 */ 1874 rpc__naf_addr_set_endpoint (endpoint, rpc_addr, status); 1875 rpc_string_free (&endpoint, &temp_status); 1876 } 1877 1878 return; 1879} 1880 1881/* 1882**++ 1883** 1884** ROUTINE NAME: rpc__if_mgmt_inq_num_registered 1885** 1886** SCOPE: PRIVATE - declared in com.h 1887** 1888** DESCRIPTION: 1889** 1890** Perform a linear search through the Interface Registry Table. 1891** For each slot found to contain a registered Interface specification, 1892** increment a counter. Return the number of active slots located. 1893** 1894** INPUTS: none 1895** 1896** INPUTS/OUTPUTS: none 1897** 1898** OUTPUTS: none 1899** 1900** IMPLICIT INPUTS: none 1901** 1902** IMPLICIT OUTPUTS: none 1903** 1904** FUNCTION VALUE: 1905** 1906** count The number of registered interfaces. 1907** 1908** SIDE EFFECTS: none 1909** 1910**-- 1911**/ 1912 1913PRIVATE unsigned32 rpc__if_mgmt_inq_num_registered( void ) 1914{ 1915 unsigned32 entry_count = 0; 1916 unsigned32 index; 1917 rpc_if_rgy_entry_p_t if_entry; 1918 1919 /* 1920 * take out a lock to protect access to the if registry 1921 */ 1922 RPC_MUTEX_LOCK (if_mutex); 1923 1924 /* 1925 * walk the hash table 1926 */ 1927 for (index = 0; index < RPC_C_IF_REGISTRY_SIZE; index++) 1928 { 1929 /* 1930 * walk the list under this hash entry 1931 */ 1932 RPC_LIST_FIRST (if_registry[index], if_entry, rpc_if_rgy_entry_p_t); 1933 1934 while (if_entry != NULL) 1935 { 1936 /* 1937 * don't count internal entries 1938 */ 1939 if (! if_entry->internal) 1940 { 1941 /* 1942 * bump the count for each entry in the list 1943 */ 1944 entry_count++; 1945 } 1946 1947 RPC_LIST_NEXT (if_entry, if_entry, rpc_if_rgy_entry_p_t); 1948 } 1949 } 1950 1951 RPC_MUTEX_UNLOCK (if_mutex); 1952 1953 /* 1954 * report the total number of entries found 1955 */ 1956 return (entry_count); 1957} 1958 1959/* 1960**++ 1961** 1962** ROUTINE NAME: rpc__if_mgmt_inq_if_ids 1963** 1964** SCOPE: PRIVATE - declared in com.h 1965** 1966** DESCRIPTION: 1967** 1968** Obtain the number of active entries in the Interface Registry Table. 1969** Then allocate enough memory to hold a vector of if_id elements. Scan 1970** through the Interface Registry Table and for each active interface copy 1971** its UUID and Version into an rpc_if_id_t element. Return a pointer, to 1972** the vector of info elements that have been built. 1973** 1974** INPUTS: none 1975** 1976** INPUTS/OUTPUTS: none 1977** 1978** OUTPUTS: 1979** 1980** if_info Pointer to an if id vector 1981** 1982** status The result of the operation. One of: 1983** rpc_s_ok 1984** rpc_s_no_interfaces 1985** rpc_s_no_memory 1986** rpc_s_coding_error 1987** 1988** IMPLICIT INPUTS: none 1989** 1990** IMPLICIT OUTPUTS: none 1991** 1992** FUNCTION VALUE: void 1993** 1994** SIDE EFFECTS: none 1995** 1996**-- 1997**/ 1998 1999PRIVATE void rpc__if_mgmt_inq_if_ids 2000( 2001 rpc_if_id_vector_p_t *if_id_vector, 2002 unsigned32 *status 2003) 2004{ 2005 rpc_if_rgy_entry_p_t if_entry; 2006 unsigned32 if_count; 2007 unsigned32 index; 2008 unsigned32 if_id_index; 2009 unsigned32 temp_status; 2010 2011 CODING_ERROR (status); 2012 2013 /* 2014 * find the number of registered interfaces 2015 */ 2016 if ((if_count = rpc__if_mgmt_inq_num_registered()) == 0) 2017 { 2018 *status = rpc_s_no_interfaces; 2019 *if_id_vector = NULL; 2020 return; 2021 } 2022 2023 /* 2024 * allocate memory for the if id vector 2025 */ 2026 RPC_MEM_ALLOC ( 2027 *if_id_vector, 2028 rpc_if_id_vector_p_t, 2029 ((sizeof if_count) + (if_count * sizeof (rpc_if_id_p_t))), 2030 RPC_C_MEM_IF_ID_VECTOR, 2031 RPC_C_MEM_WAITOK); 2032 2033 /* 2034 * set the count field in the vector 2035 */ 2036 (*if_id_vector)->count = if_count; 2037 2038 /* 2039 * take out a lock to protect access to the if registry 2040 */ 2041 RPC_MUTEX_LOCK (if_mutex); 2042 2043 /* 2044 * search through Interface Registry Table 2045 */ 2046 for (index = 0, if_id_index = 0; index < RPC_C_IF_REGISTRY_SIZE; index++) 2047 { 2048 /* 2049 * walk the list under this hash entry 2050 */ 2051 RPC_LIST_FIRST (if_registry[index], if_entry, rpc_if_rgy_entry_p_t); 2052 2053 while (if_entry != NULL) 2054 { 2055 /* 2056 * don't report internal entries 2057 */ 2058 if (! if_entry->internal) 2059 { 2060 /* 2061 * allocate memory for the if id 2062 */ 2063 RPC_MEM_ALLOC ( 2064 (*if_id_vector)->if_id[if_id_index], 2065 rpc_if_id_p_t, 2066 sizeof (rpc_if_id_t), 2067 RPC_C_MEM_IF_ID, 2068 RPC_C_MEM_WAITOK); 2069 2070 /* 2071 * extract the if id info for this registry entry 2072 */ 2073 rpc_if_inq_id ((rpc_if_handle_t) (if_entry->if_spec), 2074 (*if_id_vector)->if_id[if_id_index], status); 2075 2076 if (*status != rpc_s_ok) 2077 { 2078 /* 2079 * If anything went wrong, free the vector allocated; 2080 * but first reset the count field to the right value. 2081 */ 2082 (*if_id_vector)->count = if_id_index; 2083 rpc_if_id_vector_free (if_id_vector, &temp_status); 2084 RPC_MUTEX_UNLOCK (if_mutex); 2085 return; 2086 } 2087 if_id_index++; 2088 } 2089 2090 RPC_LIST_NEXT (if_entry, if_entry, rpc_if_rgy_entry_p_t); 2091 } 2092 } 2093 2094 RPC_MUTEX_UNLOCK (if_mutex); 2095 *status = rpc_s_ok; 2096 return; 2097} 2098 2099/* 2100**++ 2101** 2102** ROUTINE NAME: rpc_server_inq_if 2103** 2104** SCOPE: PUBLIC - declared in rpc.idl 2105** 2106** DESCRIPTION: 2107** 2108** Given an interface spec and type ID, return the manager EPV that has 2109** been registered for them (if any). 2110** 2111** INPUTS: 2112** 2113** ifspec_h Pointer to the ifspec 2114** 2115** INPUTS/OUTPUTS: none 2116** 2117** OUTPUTS: 2118** 2119** mgr_type_uuid The interface type 2120** 2121** mgr_epv The manager epv for this interface 2122** 2123** IMPLICIT INPUTS: none 2124** 2125** IMPLICIT OUTPUTS: none 2126** 2127** FUNCTION VALUE: void 2128** 2129** SIDE EFFECTS: none 2130** 2131**-- 2132**/ 2133 2134PUBLIC void rpc_server_inq_if 2135( 2136 rpc_if_handle_t ifspec_h, 2137 uuid_p_t mgr_type_uuid, 2138 rpc_mgr_epv_t *mgr_epv, 2139 unsigned32 *status 2140) 2141{ 2142 rpc_if_rep_p_t ifspec = (rpc_if_rep_p_t) ifspec_h; 2143 unsigned16 ihint = RPC_C_INVALID_IHINT; 2144 2145 CODING_ERROR (status); 2146 RPC_VERIFY_INIT (); 2147 2148 rpc__if_lookup2 (&ifspec->id, ifspec->vers, mgr_type_uuid, 2149 &ihint, NULL, NULL, mgr_epv, 2150 NULL, NULL, NULL, NULL, status); 2151} 2152 2153 2154/* 2155**++ 2156** 2157** ROUTINE NAME: rpc_server_register_if_ex 2158** 2159** SCOPE: PUBLIC - declared in rpc.idl 2160** 2161** DESCRIPTION: 2162** 2163** See description of "rpc__server_register_if_int". 2164** 2165** INPUTS: 2166** 2167** ifspec_h Pointer to the ifspec 2168** 2169** mgr_type_uuid The interface type (if any) 2170** 2171** mgr_epv The manager epv for this interface 2172** 2173** flags Registration flags 2174** 2175** max_calls The maximum number of calls 2176** 2177** if_callback Security callback 2178** 2179** INPUTS/OUTPUTS: none 2180** 2181** OUTPUTS: 2182** 2183** status The result of the operation. One of: 2184** rpc_s_ok 2185** rpc_s_type_already_registered 2186** rpc_s_no_memory 2187** rpc_s_coding_error 2188** 2189** IMPLICIT INPUTS: none 2190** 2191** IMPLICIT OUTPUTS: none 2192** 2193** FUNCTION VALUE: void 2194** 2195** SIDE EFFECTS: none 2196** 2197**-- 2198**/ 2199 2200PUBLIC void rpc_server_register_if_ex 2201( 2202 rpc_if_handle_t ifspec_h, 2203 uuid_p_t mgr_type_uuid, 2204 rpc_mgr_epv_t mgr_epv, 2205 unsigned32 flags, 2206 unsigned32 max_calls, 2207 rpc_if_callback_fn_t if_callback, 2208 unsigned32 *status 2209) 2210{ 2211 CODING_ERROR (status); 2212 RPC_VERIFY_INIT (); 2213 2214 rpc__server_register_if_int 2215 (ifspec_h, mgr_type_uuid, mgr_epv, flags, 2216 max_calls, -1, if_callback, false, status); 2217} 2218 2219 2220/* 2221**++ 2222** 2223** ROUTINE NAME: rpc_server_register_if_2 2224** 2225** SCOPE: PUBLIC - declared in rpc.idl 2226** 2227** DESCRIPTION: 2228** 2229** See description of "rpc__server_register_if_int". 2230** 2231** INPUTS: 2232** 2233** ifspec_h Pointer to the ifspec 2234** 2235** mgr_type_uuid The interface type (if any) 2236** 2237** mgr_epv The manager epv for this interface 2238** 2239** flags Registration flags 2240** 2241** max_calls The maximum number of calls 2242** 2243** max_rpc_size Maximum RPC size in bytes 2244** 2245** if_callback Security callback 2246** 2247** INPUTS/OUTPUTS: none 2248** 2249** OUTPUTS: 2250** 2251** status The result of the operation. One of: 2252** rpc_s_ok 2253** rpc_s_type_already_registered 2254** rpc_s_no_memory 2255** rpc_s_coding_error 2256** 2257** IMPLICIT INPUTS: none 2258** 2259** IMPLICIT OUTPUTS: none 2260** 2261** FUNCTION VALUE: void 2262** 2263** SIDE EFFECTS: none 2264** 2265**-- 2266**/ 2267 2268PUBLIC void rpc_server_register_if_2 2269( 2270 rpc_if_handle_t ifspec_h, 2271 uuid_p_t mgr_type_uuid, 2272 rpc_mgr_epv_t mgr_epv, 2273 unsigned32 flags, 2274 unsigned32 max_calls, 2275 unsigned32 max_rpc_size, 2276 rpc_if_callback_fn_t if_callback, 2277 unsigned32 *status 2278) 2279{ 2280 CODING_ERROR (status); 2281 RPC_VERIFY_INIT (); 2282 2283 rpc__server_register_if_int 2284 (ifspec_h, mgr_type_uuid, mgr_epv, flags, 2285 max_calls, max_rpc_size, if_callback, false, status); 2286} 2287